Imported Upstream version 9.20 71/131671/1 upstream upstream/9.20
authorSunmin Lee <sunm.lee@samsung.com>
Tue, 30 May 2017 09:53:16 +0000 (18:53 +0900)
committerSunmin Lee <sunm.lee@samsung.com>
Tue, 30 May 2017 10:08:46 +0000 (19:08 +0900)
Change-Id: Ic7b17acf9b7bfcd1297adf5a6ca3919112ed5ede

1105 files changed:
Asm/arm/7zCrcOpt.asm [new file with mode: 0755]
Asm/x86/7zAsm.asm [new file with mode: 0755]
Asm/x86/7zCrcOpt.asm [new file with mode: 0755]
Asm/x86/AesOpt.asm [new file with mode: 0755]
C/7z.h [new file with mode: 0755]
C/7zAlloc.c [new file with mode: 0755]
C/7zAlloc.h [new file with mode: 0755]
C/7zBuf.c [new file with mode: 0755]
C/7zBuf.h [new file with mode: 0755]
C/7zBuf2.c [new file with mode: 0755]
C/7zCrc.c [new file with mode: 0755]
C/7zCrc.h [new file with mode: 0755]
C/7zCrcOpt.c [new file with mode: 0755]
C/7zDec.c [new file with mode: 0755]
C/7zFile.c [new file with mode: 0755]
C/7zFile.h [new file with mode: 0755]
C/7zIn.c [new file with mode: 0755]
C/7zStream.c [new file with mode: 0755]
C/7zVersion.h [new file with mode: 0755]
C/Aes.c [new file with mode: 0755]
C/Aes.h [new file with mode: 0755]
C/AesOpt.c [new file with mode: 0755]
C/Alloc.c [new file with mode: 0755]
C/Alloc.h [new file with mode: 0755]
C/Bcj2.c [new file with mode: 0755]
C/Bcj2.h [new file with mode: 0755]
C/Bra.c [new file with mode: 0755]
C/Bra.h [new file with mode: 0755]
C/Bra86.c [new file with mode: 0755]
C/BraIA64.c [new file with mode: 0755]
C/BwtSort.c [new file with mode: 0755]
C/BwtSort.h [new file with mode: 0755]
C/CpuArch.c [new file with mode: 0755]
C/CpuArch.h [new file with mode: 0755]
C/Delta.c [new file with mode: 0755]
C/Delta.h [new file with mode: 0755]
C/HuffEnc.c [new file with mode: 0755]
C/HuffEnc.h [new file with mode: 0755]
C/LzFind.c [new file with mode: 0755]
C/LzFind.h [new file with mode: 0755]
C/LzFindMt.c [new file with mode: 0755]
C/LzFindMt.h [new file with mode: 0755]
C/LzHash.h [new file with mode: 0755]
C/Lzma2Dec.c [new file with mode: 0755]
C/Lzma2Dec.h [new file with mode: 0755]
C/Lzma2Enc.c [new file with mode: 0755]
C/Lzma2Enc.h [new file with mode: 0755]
C/Lzma86.h [new file with mode: 0755]
C/Lzma86Dec.c [new file with mode: 0755]
C/Lzma86Enc.c [new file with mode: 0755]
C/LzmaDec.c [new file with mode: 0755]
C/LzmaDec.h [new file with mode: 0755]
C/LzmaEnc.c [new file with mode: 0755]
C/LzmaEnc.h [new file with mode: 0755]
C/LzmaLib.c [new file with mode: 0755]
C/LzmaLib.h [new file with mode: 0755]
C/MtCoder.c [new file with mode: 0755]
C/MtCoder.h [new file with mode: 0755]
C/Ppmd.h [new file with mode: 0755]
C/Ppmd7.c [new file with mode: 0755]
C/Ppmd7.h [new file with mode: 0755]
C/Ppmd7Dec.c [new file with mode: 0755]
C/Ppmd7Enc.c [new file with mode: 0755]
C/Ppmd8.c [new file with mode: 0755]
C/Ppmd8.h [new file with mode: 0755]
C/Ppmd8Dec.c [new file with mode: 0755]
C/Ppmd8Enc.c [new file with mode: 0755]
C/RotateDefs.h [new file with mode: 0755]
C/Sha256.c [new file with mode: 0755]
C/Sha256.h [new file with mode: 0755]
C/Sort.c [new file with mode: 0755]
C/Sort.h [new file with mode: 0755]
C/Threads.c [new file with mode: 0755]
C/Threads.h [new file with mode: 0755]
C/Types.h [new file with mode: 0755]
C/Util/7z/7z.dsp [new file with mode: 0755]
C/Util/7z/7z.dsw [new file with mode: 0755]
C/Util/7z/7zMain.c [new file with mode: 0755]
C/Util/7z/makefile [new file with mode: 0755]
C/Util/7z/makefile.gcc [new file with mode: 0755]
C/Util/Lzma/LzmaUtil.c [new file with mode: 0755]
C/Util/Lzma/LzmaUtil.dsp [new file with mode: 0755]
C/Util/Lzma/LzmaUtil.dsw [new file with mode: 0755]
C/Util/Lzma/makefile [new file with mode: 0755]
C/Util/Lzma/makefile.gcc [new file with mode: 0755]
C/Util/LzmaLib/LzmaLib.def [new file with mode: 0755]
C/Util/LzmaLib/LzmaLib.dsp [new file with mode: 0755]
C/Util/LzmaLib/LzmaLib.dsw [new file with mode: 0755]
C/Util/LzmaLib/LzmaLibExports.c [new file with mode: 0755]
C/Util/LzmaLib/makefile [new file with mode: 0755]
C/Util/LzmaLib/resource.rc [new file with mode: 0755]
C/Util/SfxSetup/SfxSetup.c [new file with mode: 0755]
C/Util/SfxSetup/SfxSetup.dsp [new file with mode: 0755]
C/Util/SfxSetup/SfxSetup.dsw [new file with mode: 0755]
C/Util/SfxSetup/makefile [new file with mode: 0755]
C/Util/SfxSetup/makefile_con [new file with mode: 0755]
C/Util/SfxSetup/resource.rc [new file with mode: 0755]
C/Util/SfxSetup/setup.ico [new file with mode: 0755]
C/Xz.c [new file with mode: 0755]
C/Xz.h [new file with mode: 0755]
C/XzCrc64.c [new file with mode: 0755]
C/XzCrc64.h [new file with mode: 0755]
C/XzDec.c [new file with mode: 0755]
C/XzEnc.c [new file with mode: 0755]
C/XzEnc.h [new file with mode: 0755]
C/XzIn.c [new file with mode: 0755]
CPP/7zip/Aes.mak [new file with mode: 0755]
CPP/7zip/Archive/7z/7z.dsp [new file with mode: 0755]
CPP/7zip/Archive/7z/7z.dsw [new file with mode: 0755]
CPP/7zip/Archive/7z/7zCompressionMode.cpp [new file with mode: 0755]
CPP/7zip/Archive/7z/7zCompressionMode.h [new file with mode: 0755]
CPP/7zip/Archive/7z/7zDecode.cpp [new file with mode: 0755]
CPP/7zip/Archive/7z/7zDecode.h [new file with mode: 0755]
CPP/7zip/Archive/7z/7zEncode.cpp [new file with mode: 0755]
CPP/7zip/Archive/7z/7zEncode.h [new file with mode: 0755]
CPP/7zip/Archive/7z/7zExtract.cpp [new file with mode: 0755]
CPP/7zip/Archive/7z/7zFolderInStream.cpp [new file with mode: 0755]
CPP/7zip/Archive/7z/7zFolderInStream.h [new file with mode: 0755]
CPP/7zip/Archive/7z/7zFolderOutStream.cpp [new file with mode: 0755]
CPP/7zip/Archive/7z/7zFolderOutStream.h [new file with mode: 0755]
CPP/7zip/Archive/7z/7zHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/7z/7zHandler.h [new file with mode: 0755]
CPP/7zip/Archive/7z/7zHandlerOut.cpp [new file with mode: 0755]
CPP/7zip/Archive/7z/7zHeader.cpp [new file with mode: 0755]
CPP/7zip/Archive/7z/7zHeader.h [new file with mode: 0755]
CPP/7zip/Archive/7z/7zIn.cpp [new file with mode: 0755]
CPP/7zip/Archive/7z/7zIn.h [new file with mode: 0755]
CPP/7zip/Archive/7z/7zItem.h [new file with mode: 0755]
CPP/7zip/Archive/7z/7zOut.cpp [new file with mode: 0755]
CPP/7zip/Archive/7z/7zOut.h [new file with mode: 0755]
CPP/7zip/Archive/7z/7zProperties.cpp [new file with mode: 0755]
CPP/7zip/Archive/7z/7zProperties.h [new file with mode: 0755]
CPP/7zip/Archive/7z/7zRegister.cpp [new file with mode: 0755]
CPP/7zip/Archive/7z/7zSpecStream.cpp [new file with mode: 0755]
CPP/7zip/Archive/7z/7zSpecStream.h [new file with mode: 0755]
CPP/7zip/Archive/7z/7zUpdate.cpp [new file with mode: 0755]
CPP/7zip/Archive/7z/7zUpdate.h [new file with mode: 0755]
CPP/7zip/Archive/7z/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/Archive/7z/StdAfx.h [new file with mode: 0755]
CPP/7zip/Archive/7z/makefile [new file with mode: 0755]
CPP/7zip/Archive/7z/resource.rc [new file with mode: 0755]
CPP/7zip/Archive/ApmHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Archive.def [new file with mode: 0755]
CPP/7zip/Archive/Archive2.def [new file with mode: 0755]
CPP/7zip/Archive/ArchiveExports.cpp [new file with mode: 0755]
CPP/7zip/Archive/ArjHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Bz2Handler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Cab/CabBlockInStream.cpp [new file with mode: 0755]
CPP/7zip/Archive/Cab/CabBlockInStream.h [new file with mode: 0755]
CPP/7zip/Archive/Cab/CabHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Cab/CabHandler.h [new file with mode: 0755]
CPP/7zip/Archive/Cab/CabHeader.cpp [new file with mode: 0755]
CPP/7zip/Archive/Cab/CabHeader.h [new file with mode: 0755]
CPP/7zip/Archive/Cab/CabIn.cpp [new file with mode: 0755]
CPP/7zip/Archive/Cab/CabIn.h [new file with mode: 0755]
CPP/7zip/Archive/Cab/CabItem.h [new file with mode: 0755]
CPP/7zip/Archive/Cab/CabRegister.cpp [new file with mode: 0755]
CPP/7zip/Archive/Cab/StdAfx.h [new file with mode: 0755]
CPP/7zip/Archive/Chm/ChmHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Chm/ChmHandler.h [new file with mode: 0755]
CPP/7zip/Archive/Chm/ChmHeader.cpp [new file with mode: 0755]
CPP/7zip/Archive/Chm/ChmHeader.h [new file with mode: 0755]
CPP/7zip/Archive/Chm/ChmIn.cpp [new file with mode: 0755]
CPP/7zip/Archive/Chm/ChmIn.h [new file with mode: 0755]
CPP/7zip/Archive/Chm/ChmRegister.cpp [new file with mode: 0755]
CPP/7zip/Archive/Chm/StdAfx.h [new file with mode: 0755]
CPP/7zip/Archive/Com/ComHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Com/ComHandler.h [new file with mode: 0755]
CPP/7zip/Archive/Com/ComIn.cpp [new file with mode: 0755]
CPP/7zip/Archive/Com/ComIn.h [new file with mode: 0755]
CPP/7zip/Archive/Com/ComRegister.cpp [new file with mode: 0755]
CPP/7zip/Archive/Common/CoderMixer.cpp [new file with mode: 0755]
CPP/7zip/Archive/Common/CoderMixer.h [new file with mode: 0755]
CPP/7zip/Archive/Common/CoderMixer2.cpp [new file with mode: 0755]
CPP/7zip/Archive/Common/CoderMixer2.h [new file with mode: 0755]
CPP/7zip/Archive/Common/CoderMixer2MT.cpp [new file with mode: 0755]
CPP/7zip/Archive/Common/CoderMixer2MT.h [new file with mode: 0755]
CPP/7zip/Archive/Common/CoderMixer2ST.cpp [new file with mode: 0755]
CPP/7zip/Archive/Common/CoderMixer2ST.h [new file with mode: 0755]
CPP/7zip/Archive/Common/CoderMixerMT.cpp [new file with mode: 0755]
CPP/7zip/Archive/Common/CoderMixerMT.h [new file with mode: 0755]
CPP/7zip/Archive/Common/CrossThreadProgress.cpp [new file with mode: 0755]
CPP/7zip/Archive/Common/CrossThreadProgress.h [new file with mode: 0755]
CPP/7zip/Archive/Common/DummyOutStream.cpp [new file with mode: 0755]
CPP/7zip/Archive/Common/DummyOutStream.h [new file with mode: 0755]
CPP/7zip/Archive/Common/FindSignature.cpp [new file with mode: 0755]
CPP/7zip/Archive/Common/FindSignature.h [new file with mode: 0755]
CPP/7zip/Archive/Common/HandlerOut.cpp [new file with mode: 0755]
CPP/7zip/Archive/Common/HandlerOut.h [new file with mode: 0755]
CPP/7zip/Archive/Common/InStreamWithCRC.cpp [new file with mode: 0755]
CPP/7zip/Archive/Common/InStreamWithCRC.h [new file with mode: 0755]
CPP/7zip/Archive/Common/ItemNameUtils.cpp [new file with mode: 0755]
CPP/7zip/Archive/Common/ItemNameUtils.h [new file with mode: 0755]
CPP/7zip/Archive/Common/MultiStream.cpp [new file with mode: 0755]
CPP/7zip/Archive/Common/MultiStream.h [new file with mode: 0755]
CPP/7zip/Archive/Common/OutStreamWithCRC.cpp [new file with mode: 0755]
CPP/7zip/Archive/Common/OutStreamWithCRC.h [new file with mode: 0755]
CPP/7zip/Archive/Common/OutStreamWithSha1.cpp [new file with mode: 0755]
CPP/7zip/Archive/Common/OutStreamWithSha1.h [new file with mode: 0755]
CPP/7zip/Archive/Common/ParseProperties.cpp [new file with mode: 0755]
CPP/7zip/Archive/Common/ParseProperties.h [new file with mode: 0755]
CPP/7zip/Archive/Common/StdAfx.h [new file with mode: 0755]
CPP/7zip/Archive/CpioHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/CramfsHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/DebHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/DeflateProps.cpp [new file with mode: 0755]
CPP/7zip/Archive/DeflateProps.h [new file with mode: 0755]
CPP/7zip/Archive/DllExports.cpp [new file with mode: 0755]
CPP/7zip/Archive/DllExports2.cpp [new file with mode: 0755]
CPP/7zip/Archive/DmgHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/ElfHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/FatHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/FlvHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/GzHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Hfs/HfsHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Hfs/HfsHandler.h [new file with mode: 0755]
CPP/7zip/Archive/Hfs/HfsIn.cpp [new file with mode: 0755]
CPP/7zip/Archive/Hfs/HfsIn.h [new file with mode: 0755]
CPP/7zip/Archive/Hfs/HfsRegister.cpp [new file with mode: 0755]
CPP/7zip/Archive/IArchive.h [new file with mode: 0755]
CPP/7zip/Archive/Icons/7z.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/arj.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/bz2.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/cab.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/cpio.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/deb.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/dmg.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/fat.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/gz.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/hfs.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/iso.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/lzh.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/lzma.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/ntfs.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/rar.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/rpm.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/split.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/squashfs.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/tar.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/vhd.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/wim.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/xar.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/xz.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/z.ico [new file with mode: 0755]
CPP/7zip/Archive/Icons/zip.ico [new file with mode: 0755]
CPP/7zip/Archive/Iso/IsoHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Iso/IsoHandler.h [new file with mode: 0755]
CPP/7zip/Archive/Iso/IsoHeader.cpp [new file with mode: 0755]
CPP/7zip/Archive/Iso/IsoHeader.h [new file with mode: 0755]
CPP/7zip/Archive/Iso/IsoIn.cpp [new file with mode: 0755]
CPP/7zip/Archive/Iso/IsoIn.h [new file with mode: 0755]
CPP/7zip/Archive/Iso/IsoItem.h [new file with mode: 0755]
CPP/7zip/Archive/Iso/IsoRegister.cpp [new file with mode: 0755]
CPP/7zip/Archive/Iso/StdAfx.h [new file with mode: 0755]
CPP/7zip/Archive/LzhHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/LzmaHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/MachoHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/MbrHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/MslzHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/MubHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Nsis/NsisDecode.cpp [new file with mode: 0755]
CPP/7zip/Archive/Nsis/NsisDecode.h [new file with mode: 0755]
CPP/7zip/Archive/Nsis/NsisHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Nsis/NsisHandler.h [new file with mode: 0755]
CPP/7zip/Archive/Nsis/NsisIn.cpp [new file with mode: 0755]
CPP/7zip/Archive/Nsis/NsisIn.h [new file with mode: 0755]
CPP/7zip/Archive/Nsis/NsisRegister.cpp [new file with mode: 0755]
CPP/7zip/Archive/Nsis/StdAfx.h [new file with mode: 0755]
CPP/7zip/Archive/NtfsHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/PeHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/PpmdHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Rar/RarHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Rar/RarHandler.h [new file with mode: 0755]
CPP/7zip/Archive/Rar/RarHeader.cpp [new file with mode: 0755]
CPP/7zip/Archive/Rar/RarHeader.h [new file with mode: 0755]
CPP/7zip/Archive/Rar/RarIn.cpp [new file with mode: 0755]
CPP/7zip/Archive/Rar/RarIn.h [new file with mode: 0755]
CPP/7zip/Archive/Rar/RarItem.cpp [new file with mode: 0755]
CPP/7zip/Archive/Rar/RarItem.h [new file with mode: 0755]
CPP/7zip/Archive/Rar/RarRegister.cpp [new file with mode: 0755]
CPP/7zip/Archive/Rar/RarVolumeInStream.cpp [new file with mode: 0755]
CPP/7zip/Archive/Rar/RarVolumeInStream.h [new file with mode: 0755]
CPP/7zip/Archive/Rar/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/Archive/Rar/StdAfx.h [new file with mode: 0755]
CPP/7zip/Archive/RpmHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/SplitHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/SquashfsHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/StdAfx.h [new file with mode: 0755]
CPP/7zip/Archive/SwfHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Tar/StdAfx.h [new file with mode: 0755]
CPP/7zip/Archive/Tar/TarHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Tar/TarHandler.h [new file with mode: 0755]
CPP/7zip/Archive/Tar/TarHandlerOut.cpp [new file with mode: 0755]
CPP/7zip/Archive/Tar/TarHeader.cpp [new file with mode: 0755]
CPP/7zip/Archive/Tar/TarHeader.h [new file with mode: 0755]
CPP/7zip/Archive/Tar/TarIn.cpp [new file with mode: 0755]
CPP/7zip/Archive/Tar/TarIn.h [new file with mode: 0755]
CPP/7zip/Archive/Tar/TarItem.h [new file with mode: 0755]
CPP/7zip/Archive/Tar/TarOut.cpp [new file with mode: 0755]
CPP/7zip/Archive/Tar/TarOut.h [new file with mode: 0755]
CPP/7zip/Archive/Tar/TarRegister.cpp [new file with mode: 0755]
CPP/7zip/Archive/Tar/TarUpdate.cpp [new file with mode: 0755]
CPP/7zip/Archive/Tar/TarUpdate.h [new file with mode: 0755]
CPP/7zip/Archive/Udf/StdAfx.h [new file with mode: 0755]
CPP/7zip/Archive/Udf/UdfHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Udf/UdfHandler.h [new file with mode: 0755]
CPP/7zip/Archive/Udf/UdfIn.cpp [new file with mode: 0755]
CPP/7zip/Archive/Udf/UdfIn.h [new file with mode: 0755]
CPP/7zip/Archive/Udf/UdfRegister.cpp [new file with mode: 0755]
CPP/7zip/Archive/VhdHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Wim/StdAfx.h [new file with mode: 0755]
CPP/7zip/Archive/Wim/WimHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Wim/WimHandler.h [new file with mode: 0755]
CPP/7zip/Archive/Wim/WimHandlerOut.cpp [new file with mode: 0755]
CPP/7zip/Archive/Wim/WimIn.cpp [new file with mode: 0755]
CPP/7zip/Archive/Wim/WimIn.h [new file with mode: 0755]
CPP/7zip/Archive/Wim/WimRegister.cpp [new file with mode: 0755]
CPP/7zip/Archive/XarHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/XzHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/ZHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Zip/StdAfx.h [new file with mode: 0755]
CPP/7zip/Archive/Zip/ZipAddCommon.cpp [new file with mode: 0755]
CPP/7zip/Archive/Zip/ZipAddCommon.h [new file with mode: 0755]
CPP/7zip/Archive/Zip/ZipCompressionMode.h [new file with mode: 0755]
CPP/7zip/Archive/Zip/ZipHandler.cpp [new file with mode: 0755]
CPP/7zip/Archive/Zip/ZipHandler.h [new file with mode: 0755]
CPP/7zip/Archive/Zip/ZipHandlerOut.cpp [new file with mode: 0755]
CPP/7zip/Archive/Zip/ZipHeader.cpp [new file with mode: 0755]
CPP/7zip/Archive/Zip/ZipHeader.h [new file with mode: 0755]
CPP/7zip/Archive/Zip/ZipIn.cpp [new file with mode: 0755]
CPP/7zip/Archive/Zip/ZipIn.h [new file with mode: 0755]
CPP/7zip/Archive/Zip/ZipItem.cpp [new file with mode: 0755]
CPP/7zip/Archive/Zip/ZipItem.h [new file with mode: 0755]
CPP/7zip/Archive/Zip/ZipItemEx.h [new file with mode: 0755]
CPP/7zip/Archive/Zip/ZipOut.cpp [new file with mode: 0755]
CPP/7zip/Archive/Zip/ZipOut.h [new file with mode: 0755]
CPP/7zip/Archive/Zip/ZipRegister.cpp [new file with mode: 0755]
CPP/7zip/Archive/Zip/ZipUpdate.cpp [new file with mode: 0755]
CPP/7zip/Archive/Zip/ZipUpdate.h [new file with mode: 0755]
CPP/7zip/Archive/makefile [new file with mode: 0755]
CPP/7zip/Asm.mak [new file with mode: 0755]
CPP/7zip/Bundles/Alone/Alone.dsp [new file with mode: 0755]
CPP/7zip/Bundles/Alone/Alone.dsw [new file with mode: 0755]
CPP/7zip/Bundles/Alone/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/Bundles/Alone/StdAfx.h [new file with mode: 0755]
CPP/7zip/Bundles/Alone/afxres.h [new file with mode: 0755]
CPP/7zip/Bundles/Alone/makefile [new file with mode: 0755]
CPP/7zip/Bundles/Alone/resource.rc [new file with mode: 0755]
CPP/7zip/Bundles/Alone7z/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/Bundles/Alone7z/StdAfx.h [new file with mode: 0755]
CPP/7zip/Bundles/Alone7z/makefile [new file with mode: 0755]
CPP/7zip/Bundles/Alone7z/resource.rc [new file with mode: 0755]
CPP/7zip/Bundles/Fm/FM.dsp [new file with mode: 0755]
CPP/7zip/Bundles/Fm/FM.dsw [new file with mode: 0755]
CPP/7zip/Bundles/Fm/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/Bundles/Fm/StdAfx.h [new file with mode: 0755]
CPP/7zip/Bundles/Fm/makefile [new file with mode: 0755]
CPP/7zip/Bundles/Fm/resource.rc [new file with mode: 0755]
CPP/7zip/Bundles/Format7z/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/Bundles/Format7z/StdAfx.h [new file with mode: 0755]
CPP/7zip/Bundles/Format7z/makefile [new file with mode: 0755]
CPP/7zip/Bundles/Format7z/resource.rc [new file with mode: 0755]
CPP/7zip/Bundles/Format7zExtract/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/Bundles/Format7zExtract/StdAfx.h [new file with mode: 0755]
CPP/7zip/Bundles/Format7zExtract/makefile [new file with mode: 0755]
CPP/7zip/Bundles/Format7zExtract/resource.rc [new file with mode: 0755]
CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/Bundles/Format7zExtractR/StdAfx.h [new file with mode: 0755]
CPP/7zip/Bundles/Format7zExtractR/makefile [new file with mode: 0755]
CPP/7zip/Bundles/Format7zExtractR/resource.rc [new file with mode: 0755]
CPP/7zip/Bundles/Format7zF/Format7z.dsp [new file with mode: 0755]
CPP/7zip/Bundles/Format7zF/Format7z.dsw [new file with mode: 0755]
CPP/7zip/Bundles/Format7zF/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/Bundles/Format7zF/StdAfx.h [new file with mode: 0755]
CPP/7zip/Bundles/Format7zF/makefile [new file with mode: 0755]
CPP/7zip/Bundles/Format7zF/resource.rc [new file with mode: 0755]
CPP/7zip/Bundles/Format7zR/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/Bundles/Format7zR/StdAfx.h [new file with mode: 0755]
CPP/7zip/Bundles/Format7zR/makefile [new file with mode: 0755]
CPP/7zip/Bundles/Format7zR/resource.rc [new file with mode: 0755]
CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp [new file with mode: 0755]
CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp [new file with mode: 0755]
CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw [new file with mode: 0755]
CPP/7zip/Bundles/LzmaCon/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/Bundles/LzmaCon/StdAfx.h [new file with mode: 0755]
CPP/7zip/Bundles/LzmaCon/makefile [new file with mode: 0755]
CPP/7zip/Bundles/LzmaCon/makefile.gcc [new file with mode: 0755]
CPP/7zip/Bundles/SFXCon/7z.ico [new file with mode: 0755]
CPP/7zip/Bundles/SFXCon/Main.cpp [new file with mode: 0755]
CPP/7zip/Bundles/SFXCon/SFXCon.dsp [new file with mode: 0755]
CPP/7zip/Bundles/SFXCon/SFXCon.dsw [new file with mode: 0755]
CPP/7zip/Bundles/SFXCon/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/Bundles/SFXCon/StdAfx.h [new file with mode: 0755]
CPP/7zip/Bundles/SFXCon/makefile [new file with mode: 0755]
CPP/7zip/Bundles/SFXCon/resource.rc [new file with mode: 0755]
CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp [new file with mode: 0755]
CPP/7zip/Bundles/SFXSetup/ExtractCallback.h [new file with mode: 0755]
CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp [new file with mode: 0755]
CPP/7zip/Bundles/SFXSetup/ExtractEngine.h [new file with mode: 0755]
CPP/7zip/Bundles/SFXSetup/Main.cpp [new file with mode: 0755]
CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp [new file with mode: 0755]
CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw [new file with mode: 0755]
CPP/7zip/Bundles/SFXSetup/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/Bundles/SFXSetup/StdAfx.h [new file with mode: 0755]
CPP/7zip/Bundles/SFXSetup/makefile [new file with mode: 0755]
CPP/7zip/Bundles/SFXSetup/resource.h [new file with mode: 0755]
CPP/7zip/Bundles/SFXSetup/resource.rc [new file with mode: 0755]
CPP/7zip/Bundles/SFXSetup/setup.ico [new file with mode: 0755]
CPP/7zip/Bundles/SFXWin/7z.ico [new file with mode: 0755]
CPP/7zip/Bundles/SFXWin/Main.cpp [new file with mode: 0755]
CPP/7zip/Bundles/SFXWin/SFXWin.dsp [new file with mode: 0755]
CPP/7zip/Bundles/SFXWin/SFXWin.dsw [new file with mode: 0755]
CPP/7zip/Bundles/SFXWin/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/Bundles/SFXWin/StdAfx.h [new file with mode: 0755]
CPP/7zip/Bundles/SFXWin/makefile [new file with mode: 0755]
CPP/7zip/Bundles/SFXWin/resource.h [new file with mode: 0755]
CPP/7zip/Bundles/SFXWin/resource.rc [new file with mode: 0755]
CPP/7zip/Bundles/makefile [new file with mode: 0755]
CPP/7zip/Common/CWrappers.cpp [new file with mode: 0755]
CPP/7zip/Common/CWrappers.h [new file with mode: 0755]
CPP/7zip/Common/CreateCoder.cpp [new file with mode: 0755]
CPP/7zip/Common/CreateCoder.h [new file with mode: 0755]
CPP/7zip/Common/FilePathAutoRename.cpp [new file with mode: 0755]
CPP/7zip/Common/FilePathAutoRename.h [new file with mode: 0755]
CPP/7zip/Common/FileStreams.cpp [new file with mode: 0755]
CPP/7zip/Common/FileStreams.h [new file with mode: 0755]
CPP/7zip/Common/FilterCoder.cpp [new file with mode: 0755]
CPP/7zip/Common/FilterCoder.h [new file with mode: 0755]
CPP/7zip/Common/InBuffer.cpp [new file with mode: 0755]
CPP/7zip/Common/InBuffer.h [new file with mode: 0755]
CPP/7zip/Common/InMemStream.cpp [new file with mode: 0755]
CPP/7zip/Common/InMemStream.h [new file with mode: 0755]
CPP/7zip/Common/InOutTempBuffer.cpp [new file with mode: 0755]
CPP/7zip/Common/InOutTempBuffer.h [new file with mode: 0755]
CPP/7zip/Common/LimitedStreams.cpp [new file with mode: 0755]
CPP/7zip/Common/LimitedStreams.h [new file with mode: 0755]
CPP/7zip/Common/LockedStream.cpp [new file with mode: 0755]
CPP/7zip/Common/LockedStream.h [new file with mode: 0755]
CPP/7zip/Common/MemBlocks.cpp [new file with mode: 0755]
CPP/7zip/Common/MemBlocks.h [new file with mode: 0755]
CPP/7zip/Common/MethodId.cpp [new file with mode: 0755]
CPP/7zip/Common/MethodId.h [new file with mode: 0755]
CPP/7zip/Common/MethodProps.cpp [new file with mode: 0755]
CPP/7zip/Common/MethodProps.h [new file with mode: 0755]
CPP/7zip/Common/OffsetStream.cpp [new file with mode: 0755]
CPP/7zip/Common/OffsetStream.h [new file with mode: 0755]
CPP/7zip/Common/OutBuffer.cpp [new file with mode: 0755]
CPP/7zip/Common/OutBuffer.h [new file with mode: 0755]
CPP/7zip/Common/OutMemStream.cpp [new file with mode: 0755]
CPP/7zip/Common/OutMemStream.h [new file with mode: 0755]
CPP/7zip/Common/ProgressMt.cpp [new file with mode: 0755]
CPP/7zip/Common/ProgressMt.h [new file with mode: 0755]
CPP/7zip/Common/ProgressUtils.cpp [new file with mode: 0755]
CPP/7zip/Common/ProgressUtils.h [new file with mode: 0755]
CPP/7zip/Common/RegisterArc.h [new file with mode: 0755]
CPP/7zip/Common/RegisterCodec.h [new file with mode: 0755]
CPP/7zip/Common/StdAfx.h [new file with mode: 0755]
CPP/7zip/Common/StreamBinder.cpp [new file with mode: 0755]
CPP/7zip/Common/StreamBinder.h [new file with mode: 0755]
CPP/7zip/Common/StreamObjects.cpp [new file with mode: 0755]
CPP/7zip/Common/StreamObjects.h [new file with mode: 0755]
CPP/7zip/Common/StreamUtils.cpp [new file with mode: 0755]
CPP/7zip/Common/StreamUtils.h [new file with mode: 0755]
CPP/7zip/Common/VirtThread.cpp [new file with mode: 0755]
CPP/7zip/Common/VirtThread.h [new file with mode: 0755]
CPP/7zip/Compress/ArjDecoder1.cpp [new file with mode: 0755]
CPP/7zip/Compress/ArjDecoder1.h [new file with mode: 0755]
CPP/7zip/Compress/ArjDecoder2.cpp [new file with mode: 0755]
CPP/7zip/Compress/ArjDecoder2.h [new file with mode: 0755]
CPP/7zip/Compress/BZip2Const.h [new file with mode: 0755]
CPP/7zip/Compress/BZip2Crc.cpp [new file with mode: 0755]
CPP/7zip/Compress/BZip2Crc.h [new file with mode: 0755]
CPP/7zip/Compress/BZip2Decoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/BZip2Decoder.h [new file with mode: 0755]
CPP/7zip/Compress/BZip2Encoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/BZip2Encoder.h [new file with mode: 0755]
CPP/7zip/Compress/BZip2Register.cpp [new file with mode: 0755]
CPP/7zip/Compress/Bcj2Coder.cpp [new file with mode: 0755]
CPP/7zip/Compress/Bcj2Coder.h [new file with mode: 0755]
CPP/7zip/Compress/Bcj2Register.cpp [new file with mode: 0755]
CPP/7zip/Compress/BcjCoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/BcjCoder.h [new file with mode: 0755]
CPP/7zip/Compress/BcjRegister.cpp [new file with mode: 0755]
CPP/7zip/Compress/BitlDecoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/BitlDecoder.h [new file with mode: 0755]
CPP/7zip/Compress/BitlEncoder.h [new file with mode: 0755]
CPP/7zip/Compress/BitmDecoder.h [new file with mode: 0755]
CPP/7zip/Compress/BitmEncoder.h [new file with mode: 0755]
CPP/7zip/Compress/BranchCoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/BranchCoder.h [new file with mode: 0755]
CPP/7zip/Compress/BranchMisc.cpp [new file with mode: 0755]
CPP/7zip/Compress/BranchMisc.h [new file with mode: 0755]
CPP/7zip/Compress/BranchRegister.cpp [new file with mode: 0755]
CPP/7zip/Compress/ByteSwap.cpp [new file with mode: 0755]
CPP/7zip/Compress/Codec.def [new file with mode: 0755]
CPP/7zip/Compress/CodecExports.cpp [new file with mode: 0755]
CPP/7zip/Compress/CopyCoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/CopyCoder.h [new file with mode: 0755]
CPP/7zip/Compress/CopyRegister.cpp [new file with mode: 0755]
CPP/7zip/Compress/Deflate64Register.cpp [new file with mode: 0755]
CPP/7zip/Compress/DeflateConst.h [new file with mode: 0755]
CPP/7zip/Compress/DeflateDecoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/DeflateDecoder.h [new file with mode: 0755]
CPP/7zip/Compress/DeflateEncoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/DeflateEncoder.h [new file with mode: 0755]
CPP/7zip/Compress/DeflateRegister.cpp [new file with mode: 0755]
CPP/7zip/Compress/DeltaFilter.cpp [new file with mode: 0755]
CPP/7zip/Compress/DllExports.cpp [new file with mode: 0755]
CPP/7zip/Compress/DllExports2.cpp [new file with mode: 0755]
CPP/7zip/Compress/HuffmanDecoder.h [new file with mode: 0755]
CPP/7zip/Compress/ImplodeDecoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/ImplodeDecoder.h [new file with mode: 0755]
CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/ImplodeHuffmanDecoder.h [new file with mode: 0755]
CPP/7zip/Compress/LzOutWindow.cpp [new file with mode: 0755]
CPP/7zip/Compress/LzOutWindow.h [new file with mode: 0755]
CPP/7zip/Compress/LzhDecoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/LzhDecoder.h [new file with mode: 0755]
CPP/7zip/Compress/Lzma2Decoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/Lzma2Decoder.h [new file with mode: 0755]
CPP/7zip/Compress/Lzma2Encoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/Lzma2Encoder.h [new file with mode: 0755]
CPP/7zip/Compress/Lzma2Register.cpp [new file with mode: 0755]
CPP/7zip/Compress/LzmaDecoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/LzmaDecoder.h [new file with mode: 0755]
CPP/7zip/Compress/LzmaEncoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/LzmaEncoder.h [new file with mode: 0755]
CPP/7zip/Compress/LzmaRegister.cpp [new file with mode: 0755]
CPP/7zip/Compress/Lzx.h [new file with mode: 0755]
CPP/7zip/Compress/Lzx86Converter.cpp [new file with mode: 0755]
CPP/7zip/Compress/Lzx86Converter.h [new file with mode: 0755]
CPP/7zip/Compress/LzxDecoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/LzxDecoder.h [new file with mode: 0755]
CPP/7zip/Compress/Mtf8.h [new file with mode: 0755]
CPP/7zip/Compress/PpmdDecoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/PpmdDecoder.h [new file with mode: 0755]
CPP/7zip/Compress/PpmdEncoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/PpmdEncoder.h [new file with mode: 0755]
CPP/7zip/Compress/PpmdRegister.cpp [new file with mode: 0755]
CPP/7zip/Compress/PpmdZip.cpp [new file with mode: 0755]
CPP/7zip/Compress/PpmdZip.h [new file with mode: 0755]
CPP/7zip/Compress/QuantumDecoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/QuantumDecoder.h [new file with mode: 0755]
CPP/7zip/Compress/RangeCoder.h [new file with mode: 0755]
CPP/7zip/Compress/RangeCoderBit.h [new file with mode: 0755]
CPP/7zip/Compress/Rar1Decoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/Rar1Decoder.h [new file with mode: 0755]
CPP/7zip/Compress/Rar2Decoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/Rar2Decoder.h [new file with mode: 0755]
CPP/7zip/Compress/Rar3Decoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/Rar3Decoder.h [new file with mode: 0755]
CPP/7zip/Compress/Rar3Vm.cpp [new file with mode: 0755]
CPP/7zip/Compress/Rar3Vm.h [new file with mode: 0755]
CPP/7zip/Compress/RarCodecsRegister.cpp [new file with mode: 0755]
CPP/7zip/Compress/ShrinkDecoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/ShrinkDecoder.h [new file with mode: 0755]
CPP/7zip/Compress/StdAfx.h [new file with mode: 0755]
CPP/7zip/Compress/ZDecoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/ZDecoder.h [new file with mode: 0755]
CPP/7zip/Compress/ZlibDecoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/ZlibDecoder.h [new file with mode: 0755]
CPP/7zip/Compress/ZlibEncoder.cpp [new file with mode: 0755]
CPP/7zip/Compress/ZlibEncoder.h [new file with mode: 0755]
CPP/7zip/Compress/makefile [new file with mode: 0755]
CPP/7zip/Crc.mak [new file with mode: 0755]
CPP/7zip/Crypto/7zAes.cpp [new file with mode: 0755]
CPP/7zip/Crypto/7zAes.h [new file with mode: 0755]
CPP/7zip/Crypto/7zAesRegister.cpp [new file with mode: 0755]
CPP/7zip/Crypto/Codec.def [new file with mode: 0755]
CPP/7zip/Crypto/HmacSha1.cpp [new file with mode: 0755]
CPP/7zip/Crypto/HmacSha1.h [new file with mode: 0755]
CPP/7zip/Crypto/MyAes.cpp [new file with mode: 0755]
CPP/7zip/Crypto/MyAes.h [new file with mode: 0755]
CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp [new file with mode: 0755]
CPP/7zip/Crypto/Pbkdf2HmacSha1.h [new file with mode: 0755]
CPP/7zip/Crypto/RandGen.cpp [new file with mode: 0755]
CPP/7zip/Crypto/RandGen.h [new file with mode: 0755]
CPP/7zip/Crypto/Rar20Crypto.cpp [new file with mode: 0755]
CPP/7zip/Crypto/Rar20Crypto.h [new file with mode: 0755]
CPP/7zip/Crypto/RarAes.cpp [new file with mode: 0755]
CPP/7zip/Crypto/RarAes.h [new file with mode: 0755]
CPP/7zip/Crypto/Sha1.cpp [new file with mode: 0755]
CPP/7zip/Crypto/Sha1.h [new file with mode: 0755]
CPP/7zip/Crypto/StdAfx.h [new file with mode: 0755]
CPP/7zip/Crypto/WzAes.cpp [new file with mode: 0755]
CPP/7zip/Crypto/WzAes.h [new file with mode: 0755]
CPP/7zip/Crypto/ZipCrypto.cpp [new file with mode: 0755]
CPP/7zip/Crypto/ZipCrypto.h [new file with mode: 0755]
CPP/7zip/Crypto/ZipStrong.cpp [new file with mode: 0755]
CPP/7zip/Crypto/ZipStrong.h [new file with mode: 0755]
CPP/7zip/GuiCommon.rc [new file with mode: 0755]
CPP/7zip/Guid.txt [new file with mode: 0755]
CPP/7zip/ICoder.h [new file with mode: 0755]
CPP/7zip/IDecl.h [new file with mode: 0755]
CPP/7zip/IPassword.h [new file with mode: 0755]
CPP/7zip/IProgress.h [new file with mode: 0755]
CPP/7zip/IStream.h [new file with mode: 0755]
CPP/7zip/MyVersion.h [new file with mode: 0755]
CPP/7zip/MyVersionInfo.rc [new file with mode: 0755]
CPP/7zip/PropID.h [new file with mode: 0755]
CPP/7zip/SubBuild.mak [new file with mode: 0755]
CPP/7zip/UI/Agent/Agent.cpp [new file with mode: 0755]
CPP/7zip/UI/Agent/Agent.h [new file with mode: 0755]
CPP/7zip/UI/Agent/AgentOut.cpp [new file with mode: 0755]
CPP/7zip/UI/Agent/AgentProxy.cpp [new file with mode: 0755]
CPP/7zip/UI/Agent/AgentProxy.h [new file with mode: 0755]
CPP/7zip/UI/Agent/ArchiveFolder.cpp [new file with mode: 0755]
CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp [new file with mode: 0755]
CPP/7zip/UI/Agent/ArchiveFolderOut.cpp [new file with mode: 0755]
CPP/7zip/UI/Agent/IFolderArchive.h [new file with mode: 0755]
CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp [new file with mode: 0755]
CPP/7zip/UI/Agent/UpdateCallbackAgent.h [new file with mode: 0755]
CPP/7zip/UI/Client7z/Client7z.cpp [new file with mode: 0755]
CPP/7zip/UI/Client7z/Client7z.dsp [new file with mode: 0755]
CPP/7zip/UI/Client7z/Client7z.dsw [new file with mode: 0755]
CPP/7zip/UI/Client7z/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/UI/Client7z/StdAfx.h [new file with mode: 0755]
CPP/7zip/UI/Client7z/makefile [new file with mode: 0755]
CPP/7zip/UI/Common/ArchiveCommandLine.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/ArchiveCommandLine.h [new file with mode: 0755]
CPP/7zip/UI/Common/ArchiveExtractCallback.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/ArchiveExtractCallback.h [new file with mode: 0755]
CPP/7zip/UI/Common/ArchiveName.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/ArchiveName.h [new file with mode: 0755]
CPP/7zip/UI/Common/ArchiveOpenCallback.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/ArchiveOpenCallback.h [new file with mode: 0755]
CPP/7zip/UI/Common/Bench.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/Bench.h [new file with mode: 0755]
CPP/7zip/UI/Common/CompressCall.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/CompressCall.h [new file with mode: 0755]
CPP/7zip/UI/Common/CompressCall2.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/DefaultName.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/DefaultName.h [new file with mode: 0755]
CPP/7zip/UI/Common/DirItem.h [new file with mode: 0755]
CPP/7zip/UI/Common/EnumDirItems.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/EnumDirItems.h [new file with mode: 0755]
CPP/7zip/UI/Common/ExitCode.h [new file with mode: 0755]
CPP/7zip/UI/Common/Extract.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/Extract.h [new file with mode: 0755]
CPP/7zip/UI/Common/ExtractMode.h [new file with mode: 0755]
CPP/7zip/UI/Common/ExtractingFilePath.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/ExtractingFilePath.h [new file with mode: 0755]
CPP/7zip/UI/Common/IFileExtractCallback.h [new file with mode: 0755]
CPP/7zip/UI/Common/LoadCodecs.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/LoadCodecs.h [new file with mode: 0755]
CPP/7zip/UI/Common/OpenArchive.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/OpenArchive.h [new file with mode: 0755]
CPP/7zip/UI/Common/PropIDUtils.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/PropIDUtils.h [new file with mode: 0755]
CPP/7zip/UI/Common/Property.h [new file with mode: 0755]
CPP/7zip/UI/Common/SetProperties.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/SetProperties.h [new file with mode: 0755]
CPP/7zip/UI/Common/SortUtils.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/SortUtils.h [new file with mode: 0755]
CPP/7zip/UI/Common/StdAfx.h [new file with mode: 0755]
CPP/7zip/UI/Common/TempFiles.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/TempFiles.h [new file with mode: 0755]
CPP/7zip/UI/Common/Update.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/Update.h [new file with mode: 0755]
CPP/7zip/UI/Common/UpdateAction.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/UpdateAction.h [new file with mode: 0755]
CPP/7zip/UI/Common/UpdateCallback.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/UpdateCallback.h [new file with mode: 0755]
CPP/7zip/UI/Common/UpdatePair.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/UpdatePair.h [new file with mode: 0755]
CPP/7zip/UI/Common/UpdateProduce.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/UpdateProduce.h [new file with mode: 0755]
CPP/7zip/UI/Common/WorkDir.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/WorkDir.h [new file with mode: 0755]
CPP/7zip/UI/Common/ZipRegistry.cpp [new file with mode: 0755]
CPP/7zip/UI/Common/ZipRegistry.h [new file with mode: 0755]
CPP/7zip/UI/Console/BenchCon.cpp [new file with mode: 0755]
CPP/7zip/UI/Console/BenchCon.h [new file with mode: 0755]
CPP/7zip/UI/Console/Console.dsp [new file with mode: 0755]
CPP/7zip/UI/Console/Console.dsw [new file with mode: 0755]
CPP/7zip/UI/Console/ConsoleClose.cpp [new file with mode: 0755]
CPP/7zip/UI/Console/ConsoleClose.h [new file with mode: 0755]
CPP/7zip/UI/Console/ExtractCallbackConsole.cpp [new file with mode: 0755]
CPP/7zip/UI/Console/ExtractCallbackConsole.h [new file with mode: 0755]
CPP/7zip/UI/Console/List.cpp [new file with mode: 0755]
CPP/7zip/UI/Console/List.h [new file with mode: 0755]
CPP/7zip/UI/Console/Main.cpp [new file with mode: 0755]
CPP/7zip/UI/Console/MainAr.cpp [new file with mode: 0755]
CPP/7zip/UI/Console/OpenCallbackConsole.cpp [new file with mode: 0755]
CPP/7zip/UI/Console/OpenCallbackConsole.h [new file with mode: 0755]
CPP/7zip/UI/Console/PercentPrinter.cpp [new file with mode: 0755]
CPP/7zip/UI/Console/PercentPrinter.h [new file with mode: 0755]
CPP/7zip/UI/Console/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/UI/Console/StdAfx.h [new file with mode: 0755]
CPP/7zip/UI/Console/UpdateCallbackConsole.cpp [new file with mode: 0755]
CPP/7zip/UI/Console/UpdateCallbackConsole.h [new file with mode: 0755]
CPP/7zip/UI/Console/UserInputUtils.cpp [new file with mode: 0755]
CPP/7zip/UI/Console/UserInputUtils.h [new file with mode: 0755]
CPP/7zip/UI/Console/makefile [new file with mode: 0755]
CPP/7zip/UI/Console/resource.rc [new file with mode: 0755]
CPP/7zip/UI/Explorer/7-zip.dll.manifest [new file with mode: 0755]
CPP/7zip/UI/Explorer/ContextMenu.cpp [new file with mode: 0755]
CPP/7zip/UI/Explorer/ContextMenu.h [new file with mode: 0755]
CPP/7zip/UI/Explorer/ContextMenuFlags.h [new file with mode: 0755]
CPP/7zip/UI/Explorer/DllExports.cpp [new file with mode: 0755]
CPP/7zip/UI/Explorer/Explorer.def [new file with mode: 0755]
CPP/7zip/UI/Explorer/Explorer.dsp [new file with mode: 0755]
CPP/7zip/UI/Explorer/Explorer.dsw [new file with mode: 0755]
CPP/7zip/UI/Explorer/MyMessages.cpp [new file with mode: 0755]
CPP/7zip/UI/Explorer/MyMessages.h [new file with mode: 0755]
CPP/7zip/UI/Explorer/OptionsDialog.cpp [new file with mode: 0755]
CPP/7zip/UI/Explorer/OptionsDialog.h [new file with mode: 0755]
CPP/7zip/UI/Explorer/RegistryContextMenu.cpp [new file with mode: 0755]
CPP/7zip/UI/Explorer/RegistryContextMenu.h [new file with mode: 0755]
CPP/7zip/UI/Explorer/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/UI/Explorer/StdAfx.h [new file with mode: 0755]
CPP/7zip/UI/Explorer/makefile [new file with mode: 0755]
CPP/7zip/UI/Explorer/resource.h [new file with mode: 0755]
CPP/7zip/UI/Explorer/resource.rc [new file with mode: 0755]
CPP/7zip/UI/Explorer/resource2.rc [new file with mode: 0755]
CPP/7zip/UI/Far/ExtractEngine.cpp [new file with mode: 0755]
CPP/7zip/UI/Far/ExtractEngine.h [new file with mode: 0755]
CPP/7zip/UI/Far/Far.def [new file with mode: 0755]
CPP/7zip/UI/Far/Far.dsp [new file with mode: 0755]
CPP/7zip/UI/Far/Far.dsw [new file with mode: 0755]
CPP/7zip/UI/Far/FarPlugin.h [new file with mode: 0755]
CPP/7zip/UI/Far/FarUtils.cpp [new file with mode: 0755]
CPP/7zip/UI/Far/FarUtils.h [new file with mode: 0755]
CPP/7zip/UI/Far/Main.cpp [new file with mode: 0755]
CPP/7zip/UI/Far/Messages.h [new file with mode: 0755]
CPP/7zip/UI/Far/OverwriteDialog.cpp [new file with mode: 0755]
CPP/7zip/UI/Far/OverwriteDialog.h [new file with mode: 0755]
CPP/7zip/UI/Far/Plugin.cpp [new file with mode: 0755]
CPP/7zip/UI/Far/Plugin.h [new file with mode: 0755]
CPP/7zip/UI/Far/PluginCommon.cpp [new file with mode: 0755]
CPP/7zip/UI/Far/PluginDelete.cpp [new file with mode: 0755]
CPP/7zip/UI/Far/PluginRead.cpp [new file with mode: 0755]
CPP/7zip/UI/Far/PluginWrite.cpp [new file with mode: 0755]
CPP/7zip/UI/Far/ProgressBox.cpp [new file with mode: 0755]
CPP/7zip/UI/Far/ProgressBox.h [new file with mode: 0755]
CPP/7zip/UI/Far/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/UI/Far/StdAfx.h [new file with mode: 0755]
CPP/7zip/UI/Far/UpdateCallback100.cpp [new file with mode: 0755]
CPP/7zip/UI/Far/UpdateCallback100.h [new file with mode: 0755]
CPP/7zip/UI/Far/makefile [new file with mode: 0755]
CPP/7zip/UI/Far/resource.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/7zFM.exe.manifest [new file with mode: 0755]
CPP/7zip/UI/FileManager/7zipLogo.ico [new file with mode: 0755]
CPP/7zip/UI/FileManager/AboutDialog.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/AboutDialog.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/AboutDialog.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/AboutDialogRes.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/Add.bmp [new file with mode: 0755]
CPP/7zip/UI/FileManager/Add2.bmp [new file with mode: 0755]
CPP/7zip/UI/FileManager/App.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/App.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/AppState.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/BrowseDialog.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/BrowseDialog.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/BrowseDialog.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/BrowseDialogRes.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/ClassDefs.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/ComboDialog.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/ComboDialog.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/ComboDialog.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/ComboDialogRes.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/Copy.bmp [new file with mode: 0755]
CPP/7zip/UI/FileManager/Copy2.bmp [new file with mode: 0755]
CPP/7zip/UI/FileManager/CopyDialog.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/CopyDialog.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/CopyDialog.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/CopyDialogRes.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/Delete.bmp [new file with mode: 0755]
CPP/7zip/UI/FileManager/Delete2.bmp [new file with mode: 0755]
CPP/7zip/UI/FileManager/DialogSize.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/EditPage.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/EditPage.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/EditPage.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/EditPage2.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/EditPageRes.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/EnumFormatEtc.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/EnumFormatEtc.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/Extract.bmp [new file with mode: 0755]
CPP/7zip/UI/FileManager/Extract2.bmp [new file with mode: 0755]
CPP/7zip/UI/FileManager/ExtractCallback.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/ExtractCallback.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/FM.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/FM.dsp [new file with mode: 0755]
CPP/7zip/UI/FileManager/FM.dsw [new file with mode: 0755]
CPP/7zip/UI/FileManager/FM.ico [new file with mode: 0755]
CPP/7zip/UI/FileManager/FSDrives.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/FSDrives.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/FSFolder.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/FSFolder.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/FSFolderCopy.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/FileFolderPluginOpen.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/FilePlugins.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/FilePlugins.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/FoldersPage.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/FoldersPage.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/FoldersPage.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/FoldersPage2.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/FoldersPageRes.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/FormatUtils.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/FormatUtils.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/HelpUtils.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/HelpUtils.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/IFolder.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/Info.bmp [new file with mode: 0755]
CPP/7zip/UI/FileManager/Info2.bmp [new file with mode: 0755]
CPP/7zip/UI/FileManager/LangPage.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/LangPage.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/LangPage.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/LangPageRes.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/LangUtils.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/LangUtils.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/ListViewDialog.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/ListViewDialog.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/ListViewDialog.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/ListViewDialogRes.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/MenuPage.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/MenuPage.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/MenuPage.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/MenuPage2.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/MenuPageRes.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/MessagesDialog.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/MessagesDialog.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/MessagesDialog.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/MessagesDialogRes.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/Move.bmp [new file with mode: 0755]
CPP/7zip/UI/FileManager/Move2.bmp [new file with mode: 0755]
CPP/7zip/UI/FileManager/MyCom2.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/MyLoadMenu.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/MyLoadMenu.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/NetFolder.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/NetFolder.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/OpenCallback.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/OpenCallback.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/OptionsDialog.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/OverwriteDialog.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/OverwriteDialog.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/OverwriteDialog.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/OverwriteDialogRes.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/Panel.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/Panel.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/PanelCopy.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/PanelCrc.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/PanelDrag.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/PanelFolderChange.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/PanelItemOpen.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/PanelItems.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/PanelKey.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/PanelListNotify.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/PanelMenu.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/PanelOperations.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/PanelSelect.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/PanelSort.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/PanelSplitFile.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/PasswordDialog.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/PasswordDialog.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/PasswordDialog.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/PasswordDialogRes.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/PluginInterface.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/PluginLoader.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/PluginsPage.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/PluginsPage.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/PluginsPage.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/PluginsPageRes.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/ProgramLocation.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/ProgramLocation.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/ProgressDialog.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/ProgressDialog.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/ProgressDialog.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/ProgressDialog2.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/ProgressDialog2.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/ProgressDialog2.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/ProgressDialog2Res.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/ProgressDialog2a.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/ProgressDialogRes.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/PropertyName.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/PropertyName.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/PropertyName.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/PropertyNameRes.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/RegistryAssociations.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/RegistryAssociations.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/RegistryPlugins.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/RegistryPlugins.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/RegistryUtils.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/RegistryUtils.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/RootFolder.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/RootFolder.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/SettingsPage.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/SettingsPage.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/SettingsPage.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/SettingsPage2.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/SettingsPageRes.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/SplitDialog.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/SplitDialog.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/SplitDialog.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/SplitDialogRes.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/SplitUtils.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/SplitUtils.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/StdAfx.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/StringUtils.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/StringUtils.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/SysIconUtils.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/SysIconUtils.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/SystemPage.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/SystemPage.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/SystemPage.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/SystemPageRes.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/Test.bmp [new file with mode: 0755]
CPP/7zip/UI/FileManager/Test2.bmp [new file with mode: 0755]
CPP/7zip/UI/FileManager/TextPairs.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/TextPairs.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/UpdateCallback100.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/UpdateCallback100.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/ViewSettings.cpp [new file with mode: 0755]
CPP/7zip/UI/FileManager/ViewSettings.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/makefile [new file with mode: 0755]
CPP/7zip/UI/FileManager/resource.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/resource.rc [new file with mode: 0755]
CPP/7zip/UI/FileManager/resourceGui.h [new file with mode: 0755]
CPP/7zip/UI/FileManager/resourceGui.rc [new file with mode: 0755]
CPP/7zip/UI/GUI/7zG.exe.manifest [new file with mode: 0755]
CPP/7zip/UI/GUI/BenchmarkDialog.cpp [new file with mode: 0755]
CPP/7zip/UI/GUI/BenchmarkDialog.h [new file with mode: 0755]
CPP/7zip/UI/GUI/BenchmarkDialog.rc [new file with mode: 0755]
CPP/7zip/UI/GUI/BenchmarkDialogRes.h [new file with mode: 0755]
CPP/7zip/UI/GUI/CompressDialog.cpp [new file with mode: 0755]
CPP/7zip/UI/GUI/CompressDialog.h [new file with mode: 0755]
CPP/7zip/UI/GUI/CompressDialog.rc [new file with mode: 0755]
CPP/7zip/UI/GUI/CompressDialogRes.h [new file with mode: 0755]
CPP/7zip/UI/GUI/Extract.rc [new file with mode: 0755]
CPP/7zip/UI/GUI/ExtractDialog.cpp [new file with mode: 0755]
CPP/7zip/UI/GUI/ExtractDialog.h [new file with mode: 0755]
CPP/7zip/UI/GUI/ExtractDialog.rc [new file with mode: 0755]
CPP/7zip/UI/GUI/ExtractDialogRes.h [new file with mode: 0755]
CPP/7zip/UI/GUI/ExtractGUI.cpp [new file with mode: 0755]
CPP/7zip/UI/GUI/ExtractGUI.h [new file with mode: 0755]
CPP/7zip/UI/GUI/ExtractRes.h [new file with mode: 0755]
CPP/7zip/UI/GUI/FM.ico [new file with mode: 0755]
CPP/7zip/UI/GUI/GUI.cpp [new file with mode: 0755]
CPP/7zip/UI/GUI/GUI.dsp [new file with mode: 0755]
CPP/7zip/UI/GUI/GUI.dsw [new file with mode: 0755]
CPP/7zip/UI/GUI/StdAfx.cpp [new file with mode: 0755]
CPP/7zip/UI/GUI/StdAfx.h [new file with mode: 0755]
CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp [new file with mode: 0755]
CPP/7zip/UI/GUI/UpdateCallbackGUI.h [new file with mode: 0755]
CPP/7zip/UI/GUI/UpdateGUI.cpp [new file with mode: 0755]
CPP/7zip/UI/GUI/UpdateGUI.h [new file with mode: 0755]
CPP/7zip/UI/GUI/makefile [new file with mode: 0755]
CPP/7zip/UI/GUI/resource.rc [new file with mode: 0755]
CPP/7zip/UI/GUI/resource2.h [new file with mode: 0755]
CPP/7zip/UI/GUI/resource2.rc [new file with mode: 0755]
CPP/7zip/UI/makefile [new file with mode: 0755]
CPP/7zip/makefile [new file with mode: 0755]
CPP/Build.mak [new file with mode: 0755]
CPP/Common/AutoPtr.h [new file with mode: 0755]
CPP/Common/Buffer.h [new file with mode: 0755]
CPP/Common/CRC.cpp [new file with mode: 0755]
CPP/Common/C_FileIO.cpp [new file with mode: 0755]
CPP/Common/C_FileIO.h [new file with mode: 0755]
CPP/Common/ComTry.h [new file with mode: 0755]
CPP/Common/CommandLineParser.cpp [new file with mode: 0755]
CPP/Common/CommandLineParser.h [new file with mode: 0755]
CPP/Common/Defs.h [new file with mode: 0755]
CPP/Common/DynamicBuffer.h [new file with mode: 0755]
CPP/Common/IntToString.cpp [new file with mode: 0755]
CPP/Common/IntToString.h [new file with mode: 0755]
CPP/Common/Lang.cpp [new file with mode: 0755]
CPP/Common/Lang.h [new file with mode: 0755]
CPP/Common/ListFileUtils.cpp [new file with mode: 0755]
CPP/Common/ListFileUtils.h [new file with mode: 0755]
CPP/Common/MyCom.h [new file with mode: 0755]
CPP/Common/MyException.h [new file with mode: 0755]
CPP/Common/MyGuidDef.h [new file with mode: 0755]
CPP/Common/MyInitGuid.h [new file with mode: 0755]
CPP/Common/MyMap.cpp [new file with mode: 0755]
CPP/Common/MyMap.h [new file with mode: 0755]
CPP/Common/MyString.cpp [new file with mode: 0755]
CPP/Common/MyString.h [new file with mode: 0755]
CPP/Common/MyUnknown.h [new file with mode: 0755]
CPP/Common/MyVector.cpp [new file with mode: 0755]
CPP/Common/MyVector.h [new file with mode: 0755]
CPP/Common/MyWindows.cpp [new file with mode: 0755]
CPP/Common/MyWindows.h [new file with mode: 0755]
CPP/Common/MyXml.cpp [new file with mode: 0755]
CPP/Common/MyXml.h [new file with mode: 0755]
CPP/Common/NewHandler.cpp [new file with mode: 0755]
CPP/Common/NewHandler.h [new file with mode: 0755]
CPP/Common/Random.cpp [new file with mode: 0755]
CPP/Common/Random.h [new file with mode: 0755]
CPP/Common/StdAfx.h [new file with mode: 0755]
CPP/Common/StdInStream.cpp [new file with mode: 0755]
CPP/Common/StdInStream.h [new file with mode: 0755]
CPP/Common/StdOutStream.cpp [new file with mode: 0755]
CPP/Common/StdOutStream.h [new file with mode: 0755]
CPP/Common/StringConvert.cpp [new file with mode: 0755]
CPP/Common/StringConvert.h [new file with mode: 0755]
CPP/Common/StringToInt.cpp [new file with mode: 0755]
CPP/Common/StringToInt.h [new file with mode: 0755]
CPP/Common/TextConfig.cpp [new file with mode: 0755]
CPP/Common/TextConfig.h [new file with mode: 0755]
CPP/Common/Types.h [new file with mode: 0755]
CPP/Common/UTFConvert.cpp [new file with mode: 0755]
CPP/Common/UTFConvert.h [new file with mode: 0755]
CPP/Common/Wildcard.cpp [new file with mode: 0755]
CPP/Common/Wildcard.h [new file with mode: 0755]
CPP/Windows/COM.cpp [new file with mode: 0755]
CPP/Windows/COM.h [new file with mode: 0755]
CPP/Windows/Clipboard.cpp [new file with mode: 0755]
CPP/Windows/Clipboard.h [new file with mode: 0755]
CPP/Windows/CommonDialog.cpp [new file with mode: 0755]
CPP/Windows/CommonDialog.h [new file with mode: 0755]
CPP/Windows/Console.cpp [new file with mode: 0755]
CPP/Windows/Console.h [new file with mode: 0755]
CPP/Windows/Control/ComboBox.cpp [new file with mode: 0755]
CPP/Windows/Control/ComboBox.h [new file with mode: 0755]
CPP/Windows/Control/CommandBar.h [new file with mode: 0755]
CPP/Windows/Control/Dialog.cpp [new file with mode: 0755]
CPP/Windows/Control/Dialog.h [new file with mode: 0755]
CPP/Windows/Control/Edit.h [new file with mode: 0755]
CPP/Windows/Control/ImageList.cpp [new file with mode: 0755]
CPP/Windows/Control/ImageList.h [new file with mode: 0755]
CPP/Windows/Control/ListView.cpp [new file with mode: 0755]
CPP/Windows/Control/ListView.h [new file with mode: 0755]
CPP/Windows/Control/ProgressBar.h [new file with mode: 0755]
CPP/Windows/Control/PropertyPage.cpp [new file with mode: 0755]
CPP/Windows/Control/PropertyPage.h [new file with mode: 0755]
CPP/Windows/Control/ReBar.h [new file with mode: 0755]
CPP/Windows/Control/Static.h [new file with mode: 0755]
CPP/Windows/Control/StatusBar.h [new file with mode: 0755]
CPP/Windows/Control/StdAfx.h [new file with mode: 0755]
CPP/Windows/Control/ToolBar.h [new file with mode: 0755]
CPP/Windows/Control/Trackbar.h [new file with mode: 0755]
CPP/Windows/Control/Window2.cpp [new file with mode: 0755]
CPP/Windows/Control/Window2.h [new file with mode: 0755]
CPP/Windows/DLL.cpp [new file with mode: 0755]
CPP/Windows/DLL.h [new file with mode: 0755]
CPP/Windows/Defs.h [new file with mode: 0755]
CPP/Windows/Error.cpp [new file with mode: 0755]
CPP/Windows/Error.h [new file with mode: 0755]
CPP/Windows/FileDir.cpp [new file with mode: 0755]
CPP/Windows/FileDir.h [new file with mode: 0755]
CPP/Windows/FileFind.cpp [new file with mode: 0755]
CPP/Windows/FileFind.h [new file with mode: 0755]
CPP/Windows/FileIO.cpp [new file with mode: 0755]
CPP/Windows/FileIO.h [new file with mode: 0755]
CPP/Windows/FileMapping.cpp [new file with mode: 0755]
CPP/Windows/FileMapping.h [new file with mode: 0755]
CPP/Windows/FileName.cpp [new file with mode: 0755]
CPP/Windows/FileName.h [new file with mode: 0755]
CPP/Windows/FileSystem.cpp [new file with mode: 0755]
CPP/Windows/FileSystem.h [new file with mode: 0755]
CPP/Windows/Handle.h [new file with mode: 0755]
CPP/Windows/Memory.cpp [new file with mode: 0755]
CPP/Windows/Memory.h [new file with mode: 0755]
CPP/Windows/MemoryLock.cpp [new file with mode: 0755]
CPP/Windows/MemoryLock.h [new file with mode: 0755]
CPP/Windows/Menu.cpp [new file with mode: 0755]
CPP/Windows/Menu.h [new file with mode: 0755]
CPP/Windows/NationalTime.cpp [new file with mode: 0755]
CPP/Windows/NationalTime.h [new file with mode: 0755]
CPP/Windows/Net.cpp [new file with mode: 0755]
CPP/Windows/Net.h [new file with mode: 0755]
CPP/Windows/NtCheck.h [new file with mode: 0755]
CPP/Windows/Process.cpp [new file with mode: 0755]
CPP/Windows/Process.h [new file with mode: 0755]
CPP/Windows/ProcessMessages.cpp [new file with mode: 0755]
CPP/Windows/ProcessMessages.h [new file with mode: 0755]
CPP/Windows/PropVariant.cpp [new file with mode: 0755]
CPP/Windows/PropVariant.h [new file with mode: 0755]
CPP/Windows/PropVariantConversions.cpp [new file with mode: 0755]
CPP/Windows/PropVariantConversions.h [new file with mode: 0755]
CPP/Windows/PropVariantUtils.cpp [new file with mode: 0755]
CPP/Windows/PropVariantUtils.h [new file with mode: 0755]
CPP/Windows/Registry.cpp [new file with mode: 0755]
CPP/Windows/Registry.h [new file with mode: 0755]
CPP/Windows/ResourceString.cpp [new file with mode: 0755]
CPP/Windows/ResourceString.h [new file with mode: 0755]
CPP/Windows/Security.cpp [new file with mode: 0755]
CPP/Windows/Security.h [new file with mode: 0755]
CPP/Windows/Shell.cpp [new file with mode: 0755]
CPP/Windows/Shell.h [new file with mode: 0755]
CPP/Windows/StdAfx.h [new file with mode: 0755]
CPP/Windows/Synchronization.cpp [new file with mode: 0755]
CPP/Windows/Synchronization.h [new file with mode: 0755]
CPP/Windows/System.cpp [new file with mode: 0755]
CPP/Windows/System.h [new file with mode: 0755]
CPP/Windows/Thread.h [new file with mode: 0755]
CPP/Windows/Time.cpp [new file with mode: 0755]
CPP/Windows/Time.h [new file with mode: 0755]
CPP/Windows/Window.cpp [new file with mode: 0755]
CPP/Windows/Window.h [new file with mode: 0755]
DOC/7zC.txt [new file with mode: 0755]
DOC/7zFormat.txt [new file with mode: 0755]
DOC/7zip.hhp [new file with mode: 0755]
DOC/7zip.inf [new file with mode: 0755]
DOC/7zip.nsi [new file with mode: 0755]
DOC/7zip.wxs [new file with mode: 0755]
DOC/License.txt [new file with mode: 0755]
DOC/Methods.txt [new file with mode: 0755]
DOC/copying.txt [new file with mode: 0755]
DOC/history.txt [new file with mode: 0755]
DOC/lzma.txt [new file with mode: 0755]
DOC/readme.txt [new file with mode: 0755]
DOC/unRarLicense.txt [new file with mode: 0755]

diff --git a/Asm/arm/7zCrcOpt.asm b/Asm/arm/7zCrcOpt.asm
new file mode 100755 (executable)
index 0000000..f008d65
--- /dev/null
@@ -0,0 +1,100 @@
+       CODE32\r
+\r
+       EXPORT  |CrcUpdateT4@16|\r
+\r
+       AREA    |.text|, CODE, ARM\r
+\r
+       MACRO\r
+       CRC32_STEP_1\r
+\r
+       ldrb    r4, [r1], #1\r
+       subs    r2, r2, #1\r
+       eor     r4, r4, r0\r
+       and     r4, r4, #0xFF\r
+       ldr     r4, [r3, +r4, lsl #2]\r
+       eor     r0, r4, r0, lsr #8\r
+\r
+       MEND\r
+\r
+\r
+       MACRO\r
+       CRC32_STEP_4 $STREAM_WORD\r
+       \r
+       eor     r7, r7, r8\r
+       eor     r7, r7, r9\r
+       eor     r0, r0, r7\r
+       eor     r0, r0, $STREAM_WORD\r
+       ldr     $STREAM_WORD, [r1], #4\r
+       \r
+       and     r7, r0, #0xFF\r
+       and     r8, r0, #0xFF00\r
+       and     r9, r0, #0xFF0000\r
+       and     r0, r0, #0xFF000000\r
+\r
+       ldr     r7, [r6, +r7, lsl #2]\r
+       ldr     r8, [r5, +r8, lsr #6]\r
+       ldr     r9, [r4, +r9, lsr #14]\r
+       ldr     r0, [r3, +r0, lsr #22]\r
+       \r
+       MEND\r
+\r
+\r
+|CrcUpdateT4@16| PROC\r
+\r
+       stmdb   sp!, {r4-r11, lr}\r
+       cmp     r2, #0\r
+       beq     |$fin|\r
+\r
+|$v1|\r
+       tst     r1, #7\r
+       beq     |$v2|\r
+       CRC32_STEP_1\r
+       bne     |$v1|\r
+\r
+|$v2|\r
+       cmp     r2, #16\r
+       blo     |$v3|\r
+\r
+       ldr     r10, [r1], #4\r
+       ldr     r11, [r1], #4\r
+\r
+       add     r4, r3, #0x400 \r
+       add     r5, r3, #0x800\r
+       add     r6, r3, #0xC00\r
+\r
+       mov     r7, #0\r
+       mov     r8, #0\r
+       mov     r9, #0\r
+\r
+       sub     r2, r2, #16\r
+\r
+|$loop|\r
+       ; pld     [r1, #0x40]\r
+\r
+       CRC32_STEP_4 r10\r
+       CRC32_STEP_4 r11\r
+\r
+       subs    r2, r2, #8\r
+       bhs     |$loop|\r
+\r
+       sub     r1, r1, #8\r
+       add     r2, r2, #16\r
+\r
+       eor     r7, r7, r8\r
+       eor     r7, r7, r9\r
+       eor     r0, r0, r7\r
+\r
+|$v3|\r
+       cmp     r2, #0\r
+       beq     |$fin|\r
+\r
+|$v4|\r
+       CRC32_STEP_1\r
+       bne     |$v4|\r
+\r
+|$fin|\r
+       ldmia   sp!, {r4-r11, pc}\r
+\r
+|CrcUpdateT4@16| ENDP\r
+\r
+       END\r
diff --git a/Asm/x86/7zAsm.asm b/Asm/x86/7zAsm.asm
new file mode 100755 (executable)
index 0000000..5a5f271
--- /dev/null
@@ -0,0 +1,93 @@
+; 7zAsm.asm -- ASM macros\r
+; 2009-12-12 : Igor Pavlov : Public domain\r
+\r
+MY_ASM_START macro\r
+  ifdef x64\r
+    .code\r
+  else\r
+    .386\r
+    .model flat\r
+    _TEXT$00 SEGMENT PARA PUBLIC 'CODE'\r
+  endif\r
+endm\r
+\r
+MY_PROC macro name:req, numParams:req\r
+  align 16\r
+  proc_numParams equ numParams\r
+  ifdef x64\r
+    proc_name equ name\r
+    name PROC\r
+  else\r
+    proc_fastcall_name equ @CatStr(@,name,@, %numParams * 4)\r
+    public proc_fastcall_name\r
+    proc_fastcall_name:\r
+  endif\r
+endm\r
+\r
+MY_ENDP macro\r
+  ifdef x64\r
+    ret\r
+    proc_name ENDP\r
+  else\r
+    ret (proc_numParams - 2) * 4\r
+  endif\r
+endm\r
+\r
+ifdef x64\r
+  REG_SIZE equ 8\r
+else\r
+  REG_SIZE equ 4\r
+endif\r
+\r
+  x0 equ EAX\r
+  x1 equ ECX\r
+  x2 equ EDX\r
+  x3 equ EBX\r
+  x4 equ ESP\r
+  x5 equ EBP\r
+  x6 equ ESI\r
+  x7 equ EDI\r
+\r
+  x0_L equ AL\r
+  x1_L equ CL\r
+  x2_L equ DL\r
+  x3_L equ BL\r
+\r
+  x0_H equ AH\r
+  x1_H equ CH\r
+  x2_H equ DH\r
+  x3_H equ BH\r
+\r
+ifdef x64\r
+  r0 equ RAX\r
+  r1 equ RCX\r
+  r2 equ RDX\r
+  r3 equ RBX\r
+  r4 equ RSP\r
+  r5 equ RBP\r
+  r6 equ RSI\r
+  r7 equ RDI\r
+else\r
+  r0 equ x0\r
+  r1 equ x1\r
+  r2 equ x2\r
+  r3 equ x3\r
+  r4 equ x4\r
+  r5 equ x5\r
+  r6 equ x6\r
+  r7 equ x7\r
+endif\r
+\r
+MY_PUSH_4_REGS macro\r
+    push    r3\r
+    push    r5\r
+    push    r6\r
+    push    r7\r
+endm\r
+\r
+MY_POP_4_REGS macro\r
+    pop     r7\r
+    pop     r6\r
+    pop     r5\r
+    pop     r3\r
+endm\r
diff --git a/Asm/x86/7zCrcOpt.asm b/Asm/x86/7zCrcOpt.asm
new file mode 100755 (executable)
index 0000000..2de5171
--- /dev/null
@@ -0,0 +1,147 @@
+; 7zCrcOpt.asm -- CRC32 calculation : optimized version\r
+; 2009-12-12 : Igor Pavlov : Public domain\r
+\r
+include 7zAsm.asm\r
+\r
+MY_ASM_START\r
+\r
+rD   equ  r2\r
+rN   equ  r7\r
+\r
+ifdef x64\r
+    num_VAR     equ r8\r
+    table_VAR   equ r9\r
+else\r
+    data_size   equ (REG_SIZE * 5)\r
+    crc_table   equ (REG_SIZE + data_size)\r
+    num_VAR     equ [r4 + data_size]\r
+    table_VAR   equ [r4 + crc_table]\r
+endif\r
+\r
+SRCDAT  equ  rN + rD + 4 *\r
+\r
+CRC macro op:req, dest:req, src:req, t:req\r
+    op      dest, DWORD PTR [r5 + src * 4 + 0400h * t]\r
+endm\r
+\r
+CRC_XOR macro dest:req, src:req, t:req\r
+    CRC xor, dest, src, t\r
+endm\r
+\r
+CRC_MOV macro dest:req, src:req, t:req\r
+    CRC mov, dest, src, t\r
+endm\r
+\r
+CRC1b macro\r
+    movzx   x6, BYTE PTR [rD]\r
+    inc     rD\r
+    movzx   x3, x0_L\r
+    xor     x6, x3\r
+    shr     x0, 8\r
+    CRC     xor, x0, r6, 0\r
+    dec     rN\r
+endm\r
+\r
+MY_PROLOG macro crc_end:req\r
+    MY_PUSH_4_REGS\r
+    \r
+    mov     x0, x1\r
+    mov     rN, num_VAR\r
+    mov     r5, table_VAR\r
+    test    rN, rN\r
+    jz      crc_end\r
+  @@:\r
+    test    rD, 7\r
+    jz      @F\r
+    CRC1b\r
+    jnz     @B\r
+  @@:\r
+    cmp     rN, 16\r
+    jb      crc_end\r
+    add     rN, rD\r
+    mov     num_VAR, rN\r
+    sub     rN, 8\r
+    and     rN, NOT 7\r
+    sub     rD, rN\r
+    xor     x0, [SRCDAT 0]\r
+endm\r
+\r
+MY_EPILOG macro crc_end:req\r
+    xor     x0, [SRCDAT 0]\r
+    mov     rD, rN\r
+    mov     rN, num_VAR\r
+    sub     rN, rD\r
+  crc_end:\r
+    test    rN, rN\r
+    jz      @F\r
+    CRC1b\r
+    jmp     crc_end\r
+  @@:\r
+    MY_POP_4_REGS\r
+endm\r
+\r
+MY_PROC CrcUpdateT8, 4\r
+    MY_PROLOG crc_end_8\r
+    mov     x1, [SRCDAT 1]\r
+    align 16\r
+  main_loop_8:\r
+    mov     x6, [SRCDAT 2]\r
+    movzx   x3, x1_L\r
+    CRC_XOR x6, r3, 3\r
+    movzx   x3, x1_H\r
+    CRC_XOR x6, r3, 2\r
+    shr     x1, 16\r
+    movzx   x3, x1_L\r
+    movzx   x1, x1_H\r
+    CRC_XOR x6, r3, 1\r
+    movzx   x3, x0_L\r
+    CRC_XOR x6, r1, 0\r
+\r
+    mov     x1, [SRCDAT 3]\r
+    CRC_XOR x6, r3, 7\r
+    movzx   x3, x0_H\r
+    shr     x0, 16\r
+    CRC_XOR x6, r3, 6\r
+    movzx   x3, x0_L\r
+    CRC_XOR x6, r3, 5\r
+    movzx   x3, x0_H\r
+    CRC_MOV x0, r3, 4\r
+    xor     x0, x6\r
+    add     rD, 8\r
+    jnz     main_loop_8\r
+\r
+    MY_EPILOG crc_end_8\r
+MY_ENDP\r
+\r
+MY_PROC CrcUpdateT4, 4\r
+    MY_PROLOG crc_end_4\r
+    align 16\r
+  main_loop_4:\r
+    movzx   x1, x0_L\r
+    movzx   x3, x0_H\r
+    shr     x0, 16\r
+    movzx   x6, x0_H\r
+    and     x0, 0FFh\r
+    CRC_MOV x1, r1, 3\r
+    xor     x1, [SRCDAT 1]\r
+    CRC_XOR x1, r3, 2\r
+    CRC_XOR x1, r6, 0\r
+    CRC_XOR x1, r0, 1\r
\r
+    movzx   x0, x1_L\r
+    movzx   x3, x1_H\r
+    shr     x1, 16\r
+    movzx   x6, x1_H\r
+    and     x1, 0FFh\r
+    CRC_MOV x0, r0, 3\r
+    xor     x0, [SRCDAT 2]\r
+    CRC_XOR x0, r3, 2\r
+    CRC_XOR x0, r6, 0\r
+    CRC_XOR x0, r1, 1\r
+    add     rD, 8\r
+    jnz     main_loop_4\r
+\r
+    MY_EPILOG crc_end_4\r
+MY_ENDP\r
+\r
+end\r
diff --git a/Asm/x86/AesOpt.asm b/Asm/x86/AesOpt.asm
new file mode 100755 (executable)
index 0000000..c32e48f
--- /dev/null
@@ -0,0 +1,237 @@
+; AesOpt.asm -- Intel's AES.\r
+; 2009-12-12 : Igor Pavlov : Public domain\r
+\r
+include 7zAsm.asm\r
+\r
+MY_ASM_START\r
+\r
+ifndef x64\r
+    .xmm\r
+endif\r
+\r
+ifdef x64\r
+    num     equ r8\r
+else\r
+    num     equ [r4 + REG_SIZE * 4]\r
+endif\r
+\r
+rD equ r2\r
+rN equ r0\r
+\r
+MY_PROLOG macro reg:req\r
+    ifdef x64\r
+    movdqa  [r4 + 8], xmm6\r
+    movdqa  [r4 + 8 + 16], xmm7\r
+    endif\r
+\r
+    push    r3\r
+    push    r5\r
+    push    r6\r
+\r
+    mov     rN, num\r
+    mov     x6, [r1 + 16]\r
+    shl     x6, 5\r
+\r
+    movdqa  reg, [r1]\r
+    add     r1, 32\r
+endm\r
+\r
+MY_EPILOG macro\r
+    pop     r6\r
+    pop     r5\r
+    pop     r3\r
+\r
+    ifdef x64\r
+    movdqa  xmm6, [r4 + 8]\r
+    movdqa  xmm7, [r4 + 8 + 16]\r
+    endif\r
+\r
+    MY_ENDP\r
+endm\r
+\r
+ways equ 4\r
+ways16 equ (ways * 16)\r
+\r
+OP_W macro op, op2\r
+    i = 0\r
+    rept ways\r
+    op @CatStr(xmm,%i), op2\r
+    i = i + 1\r
+    endm\r
+endm\r
+\r
+LOAD_OP macro op:req, offs:req\r
+    op      xmm0, [r1 + r3 offs]\r
+endm\r
+  \r
+LOAD_OP_W macro op:req, offs:req\r
+    movdqa  xmm7, [r1 + r3 offs]\r
+    OP_W    op, xmm7\r
+endm\r
+\r
+\r
+; ---------- AES-CBC Decode ----------\r
+\r
+CBC_DEC_UPDATE macro reg, offs\r
+    pxor    reg, xmm6\r
+    movdqa  xmm6, [rD + offs]\r
+    movdqa  [rD + offs], reg\r
+endm\r
+\r
+DECODE macro op:req\r
+    op      aesdec, +16\r
+  @@:\r
+    op      aesdec, +0\r
+    op      aesdec, -16\r
+    sub     x3, 32\r
+    jnz     @B\r
+    op      aesdeclast, +0\r
+endm\r
+\r
+MY_PROC AesCbc_Decode_Intel, 3\r
+    MY_PROLOG xmm6\r
+\r
+    sub     x6, 32\r
+\r
+    jmp     check2\r
+\r
+  align 16\r
+  nextBlocks2:\r
+    mov     x3, x6\r
+    OP_W    movdqa, [rD + i * 16]\r
+    LOAD_OP_W  pxor, +32\r
+    DECODE  LOAD_OP_W\r
+    OP_W    CBC_DEC_UPDATE, i * 16\r
+    add     rD, ways16\r
+  check2:\r
+    sub     rN, ways\r
+    jnc     nextBlocks2\r
+\r
+    add     rN, ways\r
+    jmp     check\r
+\r
+  nextBlock:\r
+    mov     x3, x6\r
+    movdqa  xmm1, [rD]\r
+    LOAD_OP movdqa, +32\r
+    pxor    xmm0, xmm1\r
+    DECODE  LOAD_OP\r
+    pxor    xmm0, xmm6\r
+    movdqa  [rD], xmm0\r
+    movdqa  xmm6, xmm1\r
+    add     rD, 16\r
+  check:\r
+    sub     rN, 1\r
+    jnc     nextBlock\r
+\r
+    movdqa  [r1 - 32], xmm6\r
+    MY_EPILOG\r
+\r
+\r
+; ---------- AES-CBC Encode ----------\r
+\r
+ENCODE macro op:req\r
+    op      aesenc, -16\r
+  @@:\r
+    op      aesenc, +0\r
+    op      aesenc, +16\r
+    add     r3, 32\r
+    jnz     @B\r
+    op      aesenclast, +0\r
+endm\r
+\r
+MY_PROC AesCbc_Encode_Intel, 3\r
+    MY_PROLOG xmm0\r
+\r
+    add     r1, r6\r
+    neg     r6\r
+    add     r6, 32\r
+\r
+    jmp     check_e\r
+\r
+  align 16\r
+  nextBlock_e:\r
+    mov     r3, r6\r
+    pxor    xmm0, [rD]\r
+    pxor    xmm0, [r1 + r3 - 32]\r
+    ENCODE  LOAD_OP\r
+    movdqa  [rD], xmm0\r
+    add     rD, 16\r
+  check_e:\r
+    sub     rN, 1\r
+    jnc     nextBlock_e\r
+\r
+    movdqa  [r1 + r6 - 64], xmm0\r
+    MY_EPILOG\r
+\r
+\r
+; ---------- AES-CTR ----------\r
+\r
+XOR_UPD_1 macro reg, offs\r
+    pxor    reg, [rD + offs]\r
+endm\r
+\r
+XOR_UPD_2 macro reg, offs\r
+    movdqa  [rD + offs], reg\r
+endm\r
+\r
+MY_PROC AesCtr_Code_Intel, 3\r
+    MY_PROLOG xmm6\r
+\r
+    mov     r5, r4\r
+    shr     r5, 4\r
+    dec     r5\r
+    shl     r5, 4\r
+\r
+    mov     DWORD PTR [r5], 1\r
+    mov     DWORD PTR [r5 + 4], 0\r
+    mov     DWORD PTR [r5 + 8], 0\r
+    mov     DWORD PTR [r5 + 12], 0\r
+    \r
+    add     r1, r6\r
+    neg     r6\r
+    add     r6, 32\r
+\r
+    jmp     check2_c\r
+\r
+  align 16\r
+  nextBlocks2_c:\r
+    movdqa  xmm7, [r5]\r
+\r
+    i = 0\r
+    rept ways\r
+    paddq   xmm6, xmm7\r
+    movdqa  @CatStr(xmm,%i), xmm6\r
+    i = i + 1\r
+    endm\r
+\r
+    mov     r3, r6\r
+    LOAD_OP_W  pxor, -32\r
+    ENCODE  LOAD_OP_W\r
+    OP_W    XOR_UPD_1, i * 16\r
+    OP_W    XOR_UPD_2, i * 16\r
+    add     rD, ways16\r
+  check2_c:\r
+    sub     rN, ways\r
+    jnc     nextBlocks2_c\r
+\r
+    add     rN, ways\r
+    jmp     check_c\r
+\r
+  nextBlock_c:\r
+    paddq   xmm6, [r5]\r
+    mov     r3, r6\r
+    movdqa  xmm0, [r1 + r3 - 32]\r
+    pxor    xmm0, xmm6\r
+    ENCODE  LOAD_OP\r
+    XOR_UPD_1 xmm0, 0\r
+    XOR_UPD_2 xmm0, 0\r
+    add     rD, 16\r
+  check_c:\r
+    sub     rN, 1\r
+    jnc     nextBlock_c\r
+\r
+    movdqa  [r1 + r6 - 64], xmm6\r
+    MY_EPILOG\r
+\r
+end\r
diff --git a/C/7z.h b/C/7z.h
new file mode 100755 (executable)
index 0000000..b7edd3b
--- /dev/null
+++ b/C/7z.h
@@ -0,0 +1,203 @@
+/* 7z.h -- 7z interface\r
+2010-03-11 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __7Z_H\r
+#define __7Z_H\r
+\r
+#include "7zBuf.h"\r
+\r
+EXTERN_C_BEGIN\r
+\r
+#define k7zStartHeaderSize 0x20\r
+#define k7zSignatureSize 6\r
+extern Byte k7zSignature[k7zSignatureSize];\r
+#define k7zMajorVersion 0\r
+\r
+enum EIdEnum\r
+{\r
+  k7zIdEnd,\r
+  k7zIdHeader,\r
+  k7zIdArchiveProperties,\r
+  k7zIdAdditionalStreamsInfo,\r
+  k7zIdMainStreamsInfo,\r
+  k7zIdFilesInfo,\r
+  k7zIdPackInfo,\r
+  k7zIdUnpackInfo,\r
+  k7zIdSubStreamsInfo,\r
+  k7zIdSize,\r
+  k7zIdCRC,\r
+  k7zIdFolder,\r
+  k7zIdCodersUnpackSize,\r
+  k7zIdNumUnpackStream,\r
+  k7zIdEmptyStream,\r
+  k7zIdEmptyFile,\r
+  k7zIdAnti,\r
+  k7zIdName,\r
+  k7zIdCTime,\r
+  k7zIdATime,\r
+  k7zIdMTime,\r
+  k7zIdWinAttributes,\r
+  k7zIdComment,\r
+  k7zIdEncodedHeader,\r
+  k7zIdStartPos,\r
+  k7zIdDummy\r
+};\r
+\r
+typedef struct\r
+{\r
+  UInt32 NumInStreams;\r
+  UInt32 NumOutStreams;\r
+  UInt64 MethodID;\r
+  CBuf Props;\r
+} CSzCoderInfo;\r
+\r
+void SzCoderInfo_Init(CSzCoderInfo *p);\r
+void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);\r
+\r
+typedef struct\r
+{\r
+  UInt32 InIndex;\r
+  UInt32 OutIndex;\r
+} CSzBindPair;\r
+\r
+typedef struct\r
+{\r
+  CSzCoderInfo *Coders;\r
+  CSzBindPair *BindPairs;\r
+  UInt32 *PackStreams;\r
+  UInt64 *UnpackSizes;\r
+  UInt32 NumCoders;\r
+  UInt32 NumBindPairs;\r
+  UInt32 NumPackStreams;\r
+  int UnpackCRCDefined;\r
+  UInt32 UnpackCRC;\r
+\r
+  UInt32 NumUnpackStreams;\r
+} CSzFolder;\r
+\r
+void SzFolder_Init(CSzFolder *p);\r
+UInt64 SzFolder_GetUnpackSize(CSzFolder *p);\r
+int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);\r
+UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);\r
+UInt64 SzFolder_GetUnpackSize(CSzFolder *p);\r
+\r
+SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,\r
+    ILookInStream *stream, UInt64 startPos,\r
+    Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);\r
+\r
+typedef struct\r
+{\r
+  UInt32 Low;\r
+  UInt32 High;\r
+} CNtfsFileTime;\r
+\r
+typedef struct\r
+{\r
+  CNtfsFileTime MTime;\r
+  UInt64 Size;\r
+  UInt32 Crc;\r
+  UInt32 Attrib;\r
+  Byte HasStream;\r
+  Byte IsDir;\r
+  Byte IsAnti;\r
+  Byte CrcDefined;\r
+  Byte MTimeDefined;\r
+  Byte AttribDefined;\r
+} CSzFileItem;\r
+\r
+void SzFile_Init(CSzFileItem *p);\r
+\r
+typedef struct\r
+{\r
+  UInt64 *PackSizes;\r
+  Byte *PackCRCsDefined;\r
+  UInt32 *PackCRCs;\r
+  CSzFolder *Folders;\r
+  CSzFileItem *Files;\r
+  UInt32 NumPackStreams;\r
+  UInt32 NumFolders;\r
+  UInt32 NumFiles;\r
+} CSzAr;\r
+\r
+void SzAr_Init(CSzAr *p);\r
+void SzAr_Free(CSzAr *p, ISzAlloc *alloc);\r
+\r
+\r
+/*\r
+  SzExtract extracts file from archive\r
+\r
+  *outBuffer must be 0 before first call for each new archive.\r
+\r
+  Extracting cache:\r
+    If you need to decompress more than one file, you can send\r
+    these values from previous call:\r
+      *blockIndex,\r
+      *outBuffer,\r
+      *outBufferSize\r
+    You can consider "*outBuffer" as cache of solid block. If your archive is solid,\r
+    it will increase decompression speed.\r
+  \r
+    If you use external function, you can declare these 3 cache variables\r
+    (blockIndex, outBuffer, outBufferSize) as static in that external function.\r
+    \r
+    Free *outBuffer and set *outBuffer to 0, if you want to flush cache.\r
+*/\r
+\r
+typedef struct\r
+{\r
+  CSzAr db;\r
+  \r
+  UInt64 startPosAfterHeader;\r
+  UInt64 dataPos;\r
+\r
+  UInt32 *FolderStartPackStreamIndex;\r
+  UInt64 *PackStreamStartPositions;\r
+  UInt32 *FolderStartFileIndex;\r
+  UInt32 *FileIndexToFolderIndexMap;\r
+\r
+  size_t *FileNameOffsets; /* in 2-byte steps */\r
+  CBuf FileNames;  /* UTF-16-LE */\r
+} CSzArEx;\r
+\r
+void SzArEx_Init(CSzArEx *p);\r
+void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);\r
+UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);\r
+int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);\r
+\r
+/*\r
+if dest == NULL, the return value specifies the required size of the buffer,\r
+  in 16-bit characters, including the null-terminating character.\r
+if dest != NULL, the return value specifies the number of 16-bit characters that\r
+  are written to the dest, including the null-terminating character. */\r
+\r
+size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest);\r
+\r
+SRes SzArEx_Extract(\r
+    const CSzArEx *db,\r
+    ILookInStream *inStream,\r
+    UInt32 fileIndex,         /* index of file */\r
+    UInt32 *blockIndex,       /* index of solid block */\r
+    Byte **outBuffer,         /* pointer to pointer to output buffer (allocated with allocMain) */\r
+    size_t *outBufferSize,    /* buffer size for output buffer */\r
+    size_t *offset,           /* offset of stream for required file in *outBuffer */\r
+    size_t *outSizeProcessed, /* size of file in *outBuffer */\r
+    ISzAlloc *allocMain,\r
+    ISzAlloc *allocTemp);\r
+\r
+\r
+/*\r
+SzArEx_Open Errors:\r
+SZ_ERROR_NO_ARCHIVE\r
+SZ_ERROR_ARCHIVE\r
+SZ_ERROR_UNSUPPORTED\r
+SZ_ERROR_MEM\r
+SZ_ERROR_CRC\r
+SZ_ERROR_INPUT_EOF\r
+SZ_ERROR_FAIL\r
+*/\r
+\r
+SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);\r
+\r
+EXTERN_C_END\r
+\r
+#endif\r
diff --git a/C/7zAlloc.c b/C/7zAlloc.c
new file mode 100755 (executable)
index 0000000..8874496
--- /dev/null
@@ -0,0 +1,76 @@
+/* 7zAlloc.c -- Allocation functions\r
+2010-10-29 : Igor Pavlov : Public domain */\r
+\r
+#include "7zAlloc.h"\r
+\r
+/* #define _SZ_ALLOC_DEBUG */\r
+/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */\r
+\r
+#ifdef _SZ_ALLOC_DEBUG\r
+\r
+#ifdef _WIN32\r
+#include <windows.h>\r
+#endif\r
+\r
+#include <stdio.h>\r
+int g_allocCount = 0;\r
+int g_allocCountTemp = 0;\r
+\r
+#endif\r
+\r
+void *SzAlloc(void *p, size_t size)\r
+{\r
+  p = p;\r
+  if (size == 0)\r
+    return 0;\r
+  #ifdef _SZ_ALLOC_DEBUG\r
+  fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount);\r
+  g_allocCount++;\r
+  #endif\r
+  return malloc(size);\r
+}\r
+\r
+void SzFree(void *p, void *address)\r
+{\r
+  p = p;\r
+  #ifdef _SZ_ALLOC_DEBUG\r
+  if (address != 0)\r
+  {\r
+    g_allocCount--;\r
+    fprintf(stderr, "\nFree; count = %10d", g_allocCount);\r
+  }\r
+  #endif\r
+  free(address);\r
+}\r
+\r
+void *SzAllocTemp(void *p, size_t size)\r
+{\r
+  p = p;\r
+  if (size == 0)\r
+    return 0;\r
+  #ifdef _SZ_ALLOC_DEBUG\r
+  fprintf(stderr, "\nAlloc_temp %10d bytes;  count = %10d", size, g_allocCountTemp);\r
+  g_allocCountTemp++;\r
+  #ifdef _WIN32\r
+  return HeapAlloc(GetProcessHeap(), 0, size);\r
+  #endif\r
+  #endif\r
+  return malloc(size);\r
+}\r
+\r
+void SzFreeTemp(void *p, void *address)\r
+{\r
+  p = p;\r
+  #ifdef _SZ_ALLOC_DEBUG\r
+  if (address != 0)\r
+  {\r
+    g_allocCountTemp--;\r
+    fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp);\r
+  }\r
+  #ifdef _WIN32\r
+  HeapFree(GetProcessHeap(), 0, address);\r
+  return;\r
+  #endif\r
+  #endif\r
+  free(address);\r
+}\r
diff --git a/C/7zAlloc.h b/C/7zAlloc.h
new file mode 100755 (executable)
index 0000000..860f116
--- /dev/null
@@ -0,0 +1,15 @@
+/* 7zAlloc.h -- Allocation functions\r
+2010-10-29 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __7Z_ALLOC_H\r
+#define __7Z_ALLOC_H\r
+\r
+#include <stdlib.h>\r
+\r
+void *SzAlloc(void *p, size_t size);\r
+void SzFree(void *p, void *address);\r
+\r
+void *SzAllocTemp(void *p, size_t size);\r
+void SzFreeTemp(void *p, void *address);\r
+\r
+#endif\r
diff --git a/C/7zBuf.c b/C/7zBuf.c
new file mode 100755 (executable)
index 0000000..a35fa2f
--- /dev/null
+++ b/C/7zBuf.c
@@ -0,0 +1,36 @@
+/* 7zBuf.c -- Byte Buffer\r
+2008-03-28\r
+Igor Pavlov\r
+Public domain */\r
+\r
+#include "7zBuf.h"\r
+\r
+void Buf_Init(CBuf *p)\r
+{\r
+  p->data = 0;\r
+  p->size = 0;\r
+}\r
+\r
+int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)\r
+{\r
+  p->size = 0;\r
+  if (size == 0)\r
+  {\r
+    p->data = 0;\r
+    return 1;\r
+  }\r
+  p->data = (Byte *)alloc->Alloc(alloc, size);\r
+  if (p->data != 0)\r
+  {\r
+    p->size = size;\r
+    return 1;\r
+  }\r
+  return 0;\r
+}\r
+\r
+void Buf_Free(CBuf *p, ISzAlloc *alloc)\r
+{\r
+  alloc->Free(alloc, p->data);\r
+  p->data = 0;\r
+  p->size = 0;\r
+}\r
diff --git a/C/7zBuf.h b/C/7zBuf.h
new file mode 100755 (executable)
index 0000000..88ff0c2
--- /dev/null
+++ b/C/7zBuf.h
@@ -0,0 +1,39 @@
+/* 7zBuf.h -- Byte Buffer\r
+2009-02-07 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __7Z_BUF_H\r
+#define __7Z_BUF_H\r
+\r
+#include "Types.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+typedef struct\r
+{\r
+  Byte *data;\r
+  size_t size;\r
+} CBuf;\r
+\r
+void Buf_Init(CBuf *p);\r
+int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc);\r
+void Buf_Free(CBuf *p, ISzAlloc *alloc);\r
+\r
+typedef struct\r
+{\r
+  Byte *data;\r
+  size_t size;\r
+  size_t pos;\r
+} CDynBuf;\r
+\r
+void DynBuf_Construct(CDynBuf *p);\r
+void DynBuf_SeekToBeg(CDynBuf *p);\r
+int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc);\r
+void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/C/7zBuf2.c b/C/7zBuf2.c
new file mode 100755 (executable)
index 0000000..1c8b931
--- /dev/null
@@ -0,0 +1,45 @@
+/* 7zBuf2.c -- Byte Buffer\r
+2008-10-04 : Igor Pavlov : Public domain */\r
+\r
+#include <string.h>\r
+#include "7zBuf.h"\r
+\r
+void DynBuf_Construct(CDynBuf *p)\r
+{\r
+  p->data = 0;\r
+  p->size = 0;\r
+  p->pos = 0;\r
+}\r
+\r
+void DynBuf_SeekToBeg(CDynBuf *p)\r
+{\r
+  p->pos = 0;\r
+}\r
+\r
+int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc)\r
+{\r
+  if (size > p->size - p->pos)\r
+  {\r
+    size_t newSize = p->pos + size;\r
+    Byte *data;\r
+    newSize += newSize / 4;\r
+    data = (Byte *)alloc->Alloc(alloc, newSize);\r
+    if (data == 0)\r
+      return 0;\r
+    p->size = newSize;\r
+    memcpy(data, p->data, p->pos);\r
+    alloc->Free(alloc, p->data);\r
+    p->data = data;\r
+  }\r
+  memcpy(p->data + p->pos, buf, size);\r
+  p->pos += size;\r
+  return 1;\r
+}\r
+\r
+void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc)\r
+{\r
+  alloc->Free(alloc, p->data);\r
+  p->data = 0;\r
+  p->size = 0;\r
+  p->pos = 0;\r
+}\r
diff --git a/C/7zCrc.c b/C/7zCrc.c
new file mode 100755 (executable)
index 0000000..5801dab
--- /dev/null
+++ b/C/7zCrc.c
@@ -0,0 +1,74 @@
+/* 7zCrc.c -- CRC32 calculation\r
+2009-11-23 : Igor Pavlov : Public domain */\r
+\r
+#include "7zCrc.h"\r
+#include "CpuArch.h"\r
+\r
+#define kCrcPoly 0xEDB88320\r
+\r
+#ifdef MY_CPU_LE\r
+#define CRC_NUM_TABLES 8\r
+#else\r
+#define CRC_NUM_TABLES 1\r
+#endif\r
+\r
+typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);\r
+\r
+static CRC_FUNC g_CrcUpdate;\r
+UInt32 g_CrcTable[256 * CRC_NUM_TABLES];\r
+\r
+#if CRC_NUM_TABLES == 1\r
+\r
+#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))\r
+\r
+static UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)\r
+{\r
+  const Byte *p = (const Byte *)data;\r
+  for (; size > 0; size--, p++)\r
+    v = CRC_UPDATE_BYTE_2(v, *p);\r
+  return v;\r
+}\r
+\r
+#else\r
+\r
+UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);\r
+UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);\r
+\r
+#endif\r
+\r
+UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)\r
+{\r
+  return g_CrcUpdate(v, data, size, g_CrcTable);\r
+}\r
+\r
+UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)\r
+{\r
+  return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;\r
+}\r
+\r
+void MY_FAST_CALL CrcGenerateTable()\r
+{\r
+  UInt32 i;\r
+  for (i = 0; i < 256; i++)\r
+  {\r
+    UInt32 r = i;\r
+    unsigned j;\r
+    for (j = 0; j < 8; j++)\r
+      r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));\r
+    g_CrcTable[i] = r;\r
+  }\r
+  #if CRC_NUM_TABLES == 1\r
+  g_CrcUpdate = CrcUpdateT1;\r
+  #else\r
+  for (; i < 256 * CRC_NUM_TABLES; i++)\r
+  {\r
+    UInt32 r = g_CrcTable[i - 256];\r
+    g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);\r
+  }\r
+  g_CrcUpdate = CrcUpdateT4;\r
+  #ifdef MY_CPU_X86_OR_AMD64\r
+  if (!CPU_Is_InOrder())\r
+    g_CrcUpdate = CrcUpdateT8;\r
+  #endif\r
+  #endif\r
+}\r
diff --git a/C/7zCrc.h b/C/7zCrc.h
new file mode 100755 (executable)
index 0000000..4a1ec38
--- /dev/null
+++ b/C/7zCrc.h
@@ -0,0 +1,25 @@
+/* 7zCrc.h -- CRC32 calculation\r
+2009-11-21 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __7Z_CRC_H\r
+#define __7Z_CRC_H\r
+\r
+#include "Types.h"\r
+\r
+EXTERN_C_BEGIN\r
+\r
+extern UInt32 g_CrcTable[];\r
+\r
+/* Call CrcGenerateTable one time before other CRC functions */\r
+void MY_FAST_CALL CrcGenerateTable(void);\r
+\r
+#define CRC_INIT_VAL 0xFFFFFFFF\r
+#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL)\r
+#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))\r
+\r
+UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size);\r
+UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size);\r
+\r
+EXTERN_C_END\r
+\r
+#endif\r
diff --git a/C/7zCrcOpt.c b/C/7zCrcOpt.c
new file mode 100755 (executable)
index 0000000..6205d71
--- /dev/null
@@ -0,0 +1,34 @@
+/* 7zCrcOpt.c -- CRC32 calculation : optimized version\r
+2009-11-23 : Igor Pavlov : Public domain */\r
+\r
+#include "CpuArch.h"\r
+\r
+#ifdef MY_CPU_LE\r
+\r
+#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))\r
+\r
+UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table)\r
+{\r
+  const Byte *p = (const Byte *)data;\r
+  for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)\r
+    v = CRC_UPDATE_BYTE_2(v, *p);\r
+  for (; size >= 4; size -= 4, p += 4)\r
+  {\r
+    v ^= *(const UInt32 *)p;\r
+    v =\r
+      table[0x300 + (v & 0xFF)] ^\r
+      table[0x200 + ((v >> 8) & 0xFF)] ^\r
+      table[0x100 + ((v >> 16) & 0xFF)] ^\r
+      table[0x000 + ((v >> 24))];\r
+  }\r
+  for (; size > 0; size--, p++)\r
+    v = CRC_UPDATE_BYTE_2(v, *p);\r
+  return v;\r
+}\r
+\r
+UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table)\r
+{\r
+  return CrcUpdateT4(v, data, size, table);\r
+}\r
+\r
+#endif\r
diff --git a/C/7zDec.c b/C/7zDec.c
new file mode 100755 (executable)
index 0000000..3386807
--- /dev/null
+++ b/C/7zDec.c
@@ -0,0 +1,470 @@
+/* 7zDec.c -- Decoding from 7z folder\r
+2010-11-02 : Igor Pavlov : Public domain */\r
+\r
+#include <string.h>\r
+\r
+/* #define _7ZIP_PPMD_SUPPPORT */\r
+\r
+#include "7z.h"\r
+\r
+#include "Bcj2.h"\r
+#include "Bra.h"\r
+#include "CpuArch.h"\r
+#include "LzmaDec.h"\r
+#include "Lzma2Dec.h"\r
+#ifdef _7ZIP_PPMD_SUPPPORT\r
+#include "Ppmd7.h"\r
+#endif\r
+\r
+#define k_Copy 0\r
+#define k_LZMA2 0x21\r
+#define k_LZMA  0x30101\r
+#define k_BCJ   0x03030103\r
+#define k_PPC   0x03030205\r
+#define k_ARM   0x03030501\r
+#define k_ARMT  0x03030701\r
+#define k_SPARC 0x03030805\r
+#define k_BCJ2  0x0303011B\r
+\r
+#ifdef _7ZIP_PPMD_SUPPPORT\r
+\r
+#define k_PPMD 0x30401\r
+\r
+typedef struct\r
+{\r
+  IByteIn p;\r
+  const Byte *cur;\r
+  const Byte *end;\r
+  const Byte *begin;\r
+  UInt64 processed;\r
+  Bool extra;\r
+  SRes res;\r
+  ILookInStream *inStream;\r
+} CByteInToLook;\r
+\r
+static Byte ReadByte(void *pp)\r
+{\r
+  CByteInToLook *p = (CByteInToLook *)pp;\r
+  if (p->cur != p->end)\r
+    return *p->cur++;\r
+  if (p->res == SZ_OK)\r
+  {\r
+    size_t size = p->cur - p->begin;\r
+    p->processed += size;\r
+    p->res = p->inStream->Skip(p->inStream, size);\r
+    size = (1 << 25);\r
+    p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size);\r
+    p->cur = p->begin;\r
+    p->end = p->begin + size;\r
+    if (size != 0)\r
+      return *p->cur++;;\r
+  }\r
+  p->extra = True;\r
+  return 0;\r
+}\r
+\r
+static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,\r
+    Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)\r
+{\r
+  CPpmd7 ppmd;\r
+  CByteInToLook s;\r
+  SRes res = SZ_OK;\r
+\r
+  s.p.Read = ReadByte;\r
+  s.inStream = inStream;\r
+  s.begin = s.end = s.cur = NULL;\r
+  s.extra = False;\r
+  s.res = SZ_OK;\r
+  s.processed = 0;\r
+\r
+  if (coder->Props.size != 5)\r
+    return SZ_ERROR_UNSUPPORTED;\r
+\r
+  {\r
+    unsigned order = coder->Props.data[0];\r
+    UInt32 memSize = GetUi32(coder->Props.data + 1);\r
+    if (order < PPMD7_MIN_ORDER ||\r
+        order > PPMD7_MAX_ORDER ||\r
+        memSize < PPMD7_MIN_MEM_SIZE ||\r
+        memSize > PPMD7_MAX_MEM_SIZE)\r
+      return SZ_ERROR_UNSUPPORTED;\r
+    Ppmd7_Construct(&ppmd);\r
+    if (!Ppmd7_Alloc(&ppmd, memSize, allocMain))\r
+      return SZ_ERROR_MEM;\r
+    Ppmd7_Init(&ppmd, order);\r
+  }\r
+  {\r
+    CPpmd7z_RangeDec rc;\r
+    Ppmd7z_RangeDec_CreateVTable(&rc);\r
+    rc.Stream = &s.p;\r
+    if (!Ppmd7z_RangeDec_Init(&rc))\r
+      res = SZ_ERROR_DATA;\r
+    else if (s.extra)\r
+      res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);\r
+    else\r
+    {\r
+      SizeT i;\r
+      for (i = 0; i < outSize; i++)\r
+      {\r
+        int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p);\r
+        if (s.extra || sym < 0)\r
+          break;\r
+        outBuffer[i] = (Byte)sym;\r
+      }\r
+      if (i != outSize)\r
+        res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);\r
+      else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))\r
+        res = SZ_ERROR_DATA;\r
+    }\r
+  }\r
+  Ppmd7_Free(&ppmd, allocMain);\r
+  return res;\r
+}\r
+\r
+#endif\r
+\r
+\r
+static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,\r
+    Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)\r
+{\r
+  CLzmaDec state;\r
+  SRes res = SZ_OK;\r
+\r
+  LzmaDec_Construct(&state);\r
+  RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain));\r
+  state.dic = outBuffer;\r
+  state.dicBufSize = outSize;\r
+  LzmaDec_Init(&state);\r
+\r
+  for (;;)\r
+  {\r
+    Byte *inBuf = NULL;\r
+    size_t lookahead = (1 << 18);\r
+    if (lookahead > inSize)\r
+      lookahead = (size_t)inSize;\r
+    res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);\r
+    if (res != SZ_OK)\r
+      break;\r
+\r
+    {\r
+      SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;\r
+      ELzmaStatus status;\r
+      res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);\r
+      lookahead -= inProcessed;\r
+      inSize -= inProcessed;\r
+      if (res != SZ_OK)\r
+        break;\r
+      if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))\r
+      {\r
+        if (state.dicBufSize != outSize || lookahead != 0 ||\r
+            (status != LZMA_STATUS_FINISHED_WITH_MARK &&\r
+             status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))\r
+          res = SZ_ERROR_DATA;\r
+        break;\r
+      }\r
+      res = inStream->Skip((void *)inStream, inProcessed);\r
+      if (res != SZ_OK)\r
+        break;\r
+    }\r
+  }\r
+\r
+  LzmaDec_FreeProbs(&state, allocMain);\r
+  return res;\r
+}\r
+\r
+static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,\r
+    Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)\r
+{\r
+  CLzma2Dec state;\r
+  SRes res = SZ_OK;\r
+\r
+  Lzma2Dec_Construct(&state);\r
+  if (coder->Props.size != 1)\r
+    return SZ_ERROR_DATA;\r
+  RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain));\r
+  state.decoder.dic = outBuffer;\r
+  state.decoder.dicBufSize = outSize;\r
+  Lzma2Dec_Init(&state);\r
+\r
+  for (;;)\r
+  {\r
+    Byte *inBuf = NULL;\r
+    size_t lookahead = (1 << 18);\r
+    if (lookahead > inSize)\r
+      lookahead = (size_t)inSize;\r
+    res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);\r
+    if (res != SZ_OK)\r
+      break;\r
+\r
+    {\r
+      SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos;\r
+      ELzmaStatus status;\r
+      res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);\r
+      lookahead -= inProcessed;\r
+      inSize -= inProcessed;\r
+      if (res != SZ_OK)\r
+        break;\r
+      if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos))\r
+      {\r
+        if (state.decoder.dicBufSize != outSize || lookahead != 0 ||\r
+            (status != LZMA_STATUS_FINISHED_WITH_MARK))\r
+          res = SZ_ERROR_DATA;\r
+        break;\r
+      }\r
+      res = inStream->Skip((void *)inStream, inProcessed);\r
+      if (res != SZ_OK)\r
+        break;\r
+    }\r
+  }\r
+\r
+  Lzma2Dec_FreeProbs(&state, allocMain);\r
+  return res;\r
+}\r
+\r
+static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)\r
+{\r
+  while (inSize > 0)\r
+  {\r
+    void *inBuf;\r
+    size_t curSize = (1 << 18);\r
+    if (curSize > inSize)\r
+      curSize = (size_t)inSize;\r
+    RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize));\r
+    if (curSize == 0)\r
+      return SZ_ERROR_INPUT_EOF;\r
+    memcpy(outBuffer, inBuf, curSize);\r
+    outBuffer += curSize;\r
+    inSize -= curSize;\r
+    RINOK(inStream->Skip((void *)inStream, curSize));\r
+  }\r
+  return SZ_OK;\r
+}\r
+\r
+static Bool IS_MAIN_METHOD(UInt32 m)\r
+{\r
+  switch(m)\r
+  {\r
+    case k_Copy:\r
+    case k_LZMA:\r
+    case k_LZMA2:\r
+    #ifdef _7ZIP_PPMD_SUPPPORT\r
+    case k_PPMD:\r
+    #endif\r
+      return True;\r
+  }\r
+  return False;\r
+}\r
+\r
+static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)\r
+{\r
+  return\r
+      c->NumInStreams == 1 &&\r
+      c->NumOutStreams == 1 &&\r
+      c->MethodID <= (UInt32)0xFFFFFFFF &&\r
+      IS_MAIN_METHOD((UInt32)c->MethodID);\r
+}\r
+\r
+#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1)\r
+\r
+static SRes CheckSupportedFolder(const CSzFolder *f)\r
+{\r
+  if (f->NumCoders < 1 || f->NumCoders > 4)\r
+    return SZ_ERROR_UNSUPPORTED;\r
+  if (!IS_SUPPORTED_CODER(&f->Coders[0]))\r
+    return SZ_ERROR_UNSUPPORTED;\r
+  if (f->NumCoders == 1)\r
+  {\r
+    if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)\r
+      return SZ_ERROR_UNSUPPORTED;\r
+    return SZ_OK;\r
+  }\r
+  if (f->NumCoders == 2)\r
+  {\r
+    CSzCoderInfo *c = &f->Coders[1];\r
+    if (c->MethodID > (UInt32)0xFFFFFFFF ||\r
+        c->NumInStreams != 1 ||\r
+        c->NumOutStreams != 1 ||\r
+        f->NumPackStreams != 1 ||\r
+        f->PackStreams[0] != 0 ||\r
+        f->NumBindPairs != 1 ||\r
+        f->BindPairs[0].InIndex != 1 ||\r
+        f->BindPairs[0].OutIndex != 0)\r
+      return SZ_ERROR_UNSUPPORTED;\r
+    switch ((UInt32)c->MethodID)\r
+    {\r
+      case k_BCJ:\r
+      case k_ARM:\r
+        break;\r
+      default:\r
+        return SZ_ERROR_UNSUPPORTED;\r
+    }\r
+    return SZ_OK;\r
+  }\r
+  if (f->NumCoders == 4)\r
+  {\r
+    if (!IS_SUPPORTED_CODER(&f->Coders[1]) ||\r
+        !IS_SUPPORTED_CODER(&f->Coders[2]) ||\r
+        !IS_BCJ2(&f->Coders[3]))\r
+      return SZ_ERROR_UNSUPPORTED;\r
+    if (f->NumPackStreams != 4 ||\r
+        f->PackStreams[0] != 2 ||\r
+        f->PackStreams[1] != 6 ||\r
+        f->PackStreams[2] != 1 ||\r
+        f->PackStreams[3] != 0 ||\r
+        f->NumBindPairs != 3 ||\r
+        f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||\r
+        f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||\r
+        f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)\r
+      return SZ_ERROR_UNSUPPORTED;\r
+    return SZ_OK;\r
+  }\r
+  return SZ_ERROR_UNSUPPORTED;\r
+}\r
+\r
+static UInt64 GetSum(const UInt64 *values, UInt32 index)\r
+{\r
+  UInt64 sum = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < index; i++)\r
+    sum += values[i];\r
+  return sum;\r
+}\r
+\r
+#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;\r
+\r
+static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,\r
+    ILookInStream *inStream, UInt64 startPos,\r
+    Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,\r
+    Byte *tempBuf[])\r
+{\r
+  UInt32 ci;\r
+  SizeT tempSizes[3] = { 0, 0, 0};\r
+  SizeT tempSize3 = 0;\r
+  Byte *tempBuf3 = 0;\r
+\r
+  RINOK(CheckSupportedFolder(folder));\r
+\r
+  for (ci = 0; ci < folder->NumCoders; ci++)\r
+  {\r
+    CSzCoderInfo *coder = &folder->Coders[ci];\r
+\r
+    if (IS_MAIN_METHOD((UInt32)coder->MethodID))\r
+    {\r
+      UInt32 si = 0;\r
+      UInt64 offset;\r
+      UInt64 inSize;\r
+      Byte *outBufCur = outBuffer;\r
+      SizeT outSizeCur = outSize;\r
+      if (folder->NumCoders == 4)\r
+      {\r
+        UInt32 indices[] = { 3, 2, 0 };\r
+        UInt64 unpackSize = folder->UnpackSizes[ci];\r
+        si = indices[ci];\r
+        if (ci < 2)\r
+        {\r
+          Byte *temp;\r
+          outSizeCur = (SizeT)unpackSize;\r
+          if (outSizeCur != unpackSize)\r
+            return SZ_ERROR_MEM;\r
+          temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);\r
+          if (temp == 0 && outSizeCur != 0)\r
+            return SZ_ERROR_MEM;\r
+          outBufCur = tempBuf[1 - ci] = temp;\r
+          tempSizes[1 - ci] = outSizeCur;\r
+        }\r
+        else if (ci == 2)\r
+        {\r
+          if (unpackSize > outSize) /* check it */\r
+            return SZ_ERROR_PARAM;\r
+          tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);\r
+          tempSize3 = outSizeCur = (SizeT)unpackSize;\r
+        }\r
+        else\r
+          return SZ_ERROR_UNSUPPORTED;\r
+      }\r
+      offset = GetSum(packSizes, si);\r
+      inSize = packSizes[si];\r
+      RINOK(LookInStream_SeekTo(inStream, startPos + offset));\r
+\r
+      if (coder->MethodID == k_Copy)\r
+      {\r
+        if (inSize != outSizeCur) /* check it */\r
+          return SZ_ERROR_DATA;\r
+        RINOK(SzDecodeCopy(inSize, inStream, outBufCur));\r
+      }\r
+      else if (coder->MethodID == k_LZMA)\r
+      {\r
+        RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));\r
+      }\r
+      else if (coder->MethodID == k_LZMA2)\r
+      {\r
+        RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));\r
+      }\r
+      else\r
+      {\r
+        #ifdef _7ZIP_PPMD_SUPPPORT\r
+        RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));\r
+        #else\r
+        return SZ_ERROR_UNSUPPORTED;\r
+        #endif\r
+      }\r
+    }\r
+    else if (coder->MethodID == k_BCJ2)\r
+    {\r
+      UInt64 offset = GetSum(packSizes, 1);\r
+      UInt64 s3Size = packSizes[1];\r
+      SRes res;\r
+      if (ci != 3)\r
+        return SZ_ERROR_UNSUPPORTED;\r
+      RINOK(LookInStream_SeekTo(inStream, startPos + offset));\r
+      tempSizes[2] = (SizeT)s3Size;\r
+      if (tempSizes[2] != s3Size)\r
+        return SZ_ERROR_MEM;\r
+      tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);\r
+      if (tempBuf[2] == 0 && tempSizes[2] != 0)\r
+        return SZ_ERROR_MEM;\r
+      res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);\r
+      RINOK(res)\r
+\r
+      res = Bcj2_Decode(\r
+          tempBuf3, tempSize3,\r
+          tempBuf[0], tempSizes[0],\r
+          tempBuf[1], tempSizes[1],\r
+          tempBuf[2], tempSizes[2],\r
+          outBuffer, outSize);\r
+      RINOK(res)\r
+    }\r
+    else\r
+    {\r
+      if (ci != 1)\r
+        return SZ_ERROR_UNSUPPORTED;\r
+      switch(coder->MethodID)\r
+      {\r
+        case k_BCJ:\r
+        {\r
+          UInt32 state;\r
+          x86_Convert_Init(state);\r
+          x86_Convert(outBuffer, outSize, 0, &state, 0);\r
+          break;\r
+        }\r
+        CASE_BRA_CONV(ARM)\r
+        default:\r
+          return SZ_ERROR_UNSUPPORTED;\r
+      }\r
+    }\r
+  }\r
+  return SZ_OK;\r
+}\r
+\r
+SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,\r
+    ILookInStream *inStream, UInt64 startPos,\r
+    Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)\r
+{\r
+  Byte *tempBuf[3] = { 0, 0, 0};\r
+  int i;\r
+  SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos,\r
+      outBuffer, (SizeT)outSize, allocMain, tempBuf);\r
+  for (i = 0; i < 3; i++)\r
+    IAlloc_Free(allocMain, tempBuf[i]);\r
+  return res;\r
+}\r
diff --git a/C/7zFile.c b/C/7zFile.c
new file mode 100755 (executable)
index 0000000..6d82c79
--- /dev/null
@@ -0,0 +1,284 @@
+/* 7zFile.c -- File IO\r
+2009-11-24 : Igor Pavlov : Public domain */\r
+\r
+#include "7zFile.h"\r
+\r
+#ifndef USE_WINDOWS_FILE\r
+\r
+#ifndef UNDER_CE\r
+#include <errno.h>\r
+#endif\r
+\r
+#else\r
+\r
+/*\r
+   ReadFile and WriteFile functions in Windows have BUG:\r
+   If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)\r
+   from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES\r
+   (Insufficient system resources exist to complete the requested service).\r
+   Probably in some version of Windows there are problems with other sizes:\r
+   for 32 MB (maybe also for 16 MB).\r
+   And message can be "Network connection was lost"\r
+*/\r
+\r
+#define kChunkSizeMax (1 << 22)\r
+\r
+#endif\r
+\r
+void File_Construct(CSzFile *p)\r
+{\r
+  #ifdef USE_WINDOWS_FILE\r
+  p->handle = INVALID_HANDLE_VALUE;\r
+  #else\r
+  p->file = NULL;\r
+  #endif\r
+}\r
+\r
+#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)\r
+static WRes File_Open(CSzFile *p, const char *name, int writeMode)\r
+{\r
+  #ifdef USE_WINDOWS_FILE\r
+  p->handle = CreateFileA(name,\r
+      writeMode ? GENERIC_WRITE : GENERIC_READ,\r
+      FILE_SHARE_READ, NULL,\r
+      writeMode ? CREATE_ALWAYS : OPEN_EXISTING,\r
+      FILE_ATTRIBUTE_NORMAL, NULL);\r
+  return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();\r
+  #else\r
+  p->file = fopen(name, writeMode ? "wb+" : "rb");\r
+  return (p->file != 0) ? 0 :\r
+    #ifdef UNDER_CE\r
+    2; /* ENOENT */\r
+    #else\r
+    errno;\r
+    #endif\r
+  #endif\r
+}\r
+\r
+WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); }\r
+WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); }\r
+#endif\r
+\r
+#ifdef USE_WINDOWS_FILE\r
+static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode)\r
+{\r
+  p->handle = CreateFileW(name,\r
+      writeMode ? GENERIC_WRITE : GENERIC_READ,\r
+      FILE_SHARE_READ, NULL,\r
+      writeMode ? CREATE_ALWAYS : OPEN_EXISTING,\r
+      FILE_ATTRIBUTE_NORMAL, NULL);\r
+  return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();\r
+}\r
+WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); }\r
+WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); }\r
+#endif\r
+\r
+WRes File_Close(CSzFile *p)\r
+{\r
+  #ifdef USE_WINDOWS_FILE\r
+  if (p->handle != INVALID_HANDLE_VALUE)\r
+  {\r
+    if (!CloseHandle(p->handle))\r
+      return GetLastError();\r
+    p->handle = INVALID_HANDLE_VALUE;\r
+  }\r
+  #else\r
+  if (p->file != NULL)\r
+  {\r
+    int res = fclose(p->file);\r
+    if (res != 0)\r
+      return res;\r
+    p->file = NULL;\r
+  }\r
+  #endif\r
+  return 0;\r
+}\r
+\r
+WRes File_Read(CSzFile *p, void *data, size_t *size)\r
+{\r
+  size_t originalSize = *size;\r
+  if (originalSize == 0)\r
+    return 0;\r
+\r
+  #ifdef USE_WINDOWS_FILE\r
+\r
+  *size = 0;\r
+  do\r
+  {\r
+    DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;\r
+    DWORD processed = 0;\r
+    BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL);\r
+    data = (void *)((Byte *)data + processed);\r
+    originalSize -= processed;\r
+    *size += processed;\r
+    if (!res)\r
+      return GetLastError();\r
+    if (processed == 0)\r
+      break;\r
+  }\r
+  while (originalSize > 0);\r
+  return 0;\r
+\r
+  #else\r
+  \r
+  *size = fread(data, 1, originalSize, p->file);\r
+  if (*size == originalSize)\r
+    return 0;\r
+  return ferror(p->file);\r
+  \r
+  #endif\r
+}\r
+\r
+WRes File_Write(CSzFile *p, const void *data, size_t *size)\r
+{\r
+  size_t originalSize = *size;\r
+  if (originalSize == 0)\r
+    return 0;\r
+  \r
+  #ifdef USE_WINDOWS_FILE\r
+\r
+  *size = 0;\r
+  do\r
+  {\r
+    DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;\r
+    DWORD processed = 0;\r
+    BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL);\r
+    data = (void *)((Byte *)data + processed);\r
+    originalSize -= processed;\r
+    *size += processed;\r
+    if (!res)\r
+      return GetLastError();\r
+    if (processed == 0)\r
+      break;\r
+  }\r
+  while (originalSize > 0);\r
+  return 0;\r
+\r
+  #else\r
+\r
+  *size = fwrite(data, 1, originalSize, p->file);\r
+  if (*size == originalSize)\r
+    return 0;\r
+  return ferror(p->file);\r
+  \r
+  #endif\r
+}\r
+\r
+WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin)\r
+{\r
+  #ifdef USE_WINDOWS_FILE\r
+\r
+  LARGE_INTEGER value;\r
+  DWORD moveMethod;\r
+  value.LowPart = (DWORD)*pos;\r
+  value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */\r
+  switch (origin)\r
+  {\r
+    case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break;\r
+    case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break;\r
+    case SZ_SEEK_END: moveMethod = FILE_END; break;\r
+    default: return ERROR_INVALID_PARAMETER;\r
+  }\r
+  value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod);\r
+  if (value.LowPart == 0xFFFFFFFF)\r
+  {\r
+    WRes res = GetLastError();\r
+    if (res != NO_ERROR)\r
+      return res;\r
+  }\r
+  *pos = ((Int64)value.HighPart << 32) | value.LowPart;\r
+  return 0;\r
+\r
+  #else\r
+  \r
+  int moveMethod;\r
+  int res;\r
+  switch (origin)\r
+  {\r
+    case SZ_SEEK_SET: moveMethod = SEEK_SET; break;\r
+    case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break;\r
+    case SZ_SEEK_END: moveMethod = SEEK_END; break;\r
+    default: return 1;\r
+  }\r
+  res = fseek(p->file, (long)*pos, moveMethod);\r
+  *pos = ftell(p->file);\r
+  return res;\r
+  \r
+  #endif\r
+}\r
+\r
+WRes File_GetLength(CSzFile *p, UInt64 *length)\r
+{\r
+  #ifdef USE_WINDOWS_FILE\r
+  \r
+  DWORD sizeHigh;\r
+  DWORD sizeLow = GetFileSize(p->handle, &sizeHigh);\r
+  if (sizeLow == 0xFFFFFFFF)\r
+  {\r
+    DWORD res = GetLastError();\r
+    if (res != NO_ERROR)\r
+      return res;\r
+  }\r
+  *length = (((UInt64)sizeHigh) << 32) + sizeLow;\r
+  return 0;\r
+  \r
+  #else\r
+  \r
+  long pos = ftell(p->file);\r
+  int res = fseek(p->file, 0, SEEK_END);\r
+  *length = ftell(p->file);\r
+  fseek(p->file, pos, SEEK_SET);\r
+  return res;\r
+  \r
+  #endif\r
+}\r
+\r
+\r
+/* ---------- FileSeqInStream ---------- */\r
+\r
+static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size)\r
+{\r
+  CFileSeqInStream *p = (CFileSeqInStream *)pp;\r
+  return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ;\r
+}\r
+\r
+void FileSeqInStream_CreateVTable(CFileSeqInStream *p)\r
+{\r
+  p->s.Read = FileSeqInStream_Read;\r
+}\r
+\r
+\r
+/* ---------- FileInStream ---------- */\r
+\r
+static SRes FileInStream_Read(void *pp, void *buf, size_t *size)\r
+{\r
+  CFileInStream *p = (CFileInStream *)pp;\r
+  return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ;\r
+}\r
+\r
+static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin)\r
+{\r
+  CFileInStream *p = (CFileInStream *)pp;\r
+  return File_Seek(&p->file, pos, origin);\r
+}\r
+\r
+void FileInStream_CreateVTable(CFileInStream *p)\r
+{\r
+  p->s.Read = FileInStream_Read;\r
+  p->s.Seek = FileInStream_Seek;\r
+}\r
+\r
+\r
+/* ---------- FileOutStream ---------- */\r
+\r
+static size_t FileOutStream_Write(void *pp, const void *data, size_t size)\r
+{\r
+  CFileOutStream *p = (CFileOutStream *)pp;\r
+  File_Write(&p->file, data, &size);\r
+  return size;\r
+}\r
+\r
+void FileOutStream_CreateVTable(CFileOutStream *p)\r
+{\r
+  p->s.Write = FileOutStream_Write;\r
+}\r
diff --git a/C/7zFile.h b/C/7zFile.h
new file mode 100755 (executable)
index 0000000..5d85787
--- /dev/null
@@ -0,0 +1,83 @@
+/* 7zFile.h -- File IO\r
+2009-11-24 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __7Z_FILE_H\r
+#define __7Z_FILE_H\r
+\r
+#ifdef _WIN32\r
+#define USE_WINDOWS_FILE\r
+#endif\r
+\r
+#ifdef USE_WINDOWS_FILE\r
+#include <windows.h>\r
+#else\r
+#include <stdio.h>\r
+#endif\r
+\r
+#include "Types.h"\r
+\r
+EXTERN_C_BEGIN\r
+\r
+/* ---------- File ---------- */\r
+\r
+typedef struct\r
+{\r
+  #ifdef USE_WINDOWS_FILE\r
+  HANDLE handle;\r
+  #else\r
+  FILE *file;\r
+  #endif\r
+} CSzFile;\r
+\r
+void File_Construct(CSzFile *p);\r
+#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)\r
+WRes InFile_Open(CSzFile *p, const char *name);\r
+WRes OutFile_Open(CSzFile *p, const char *name);\r
+#endif\r
+#ifdef USE_WINDOWS_FILE\r
+WRes InFile_OpenW(CSzFile *p, const WCHAR *name);\r
+WRes OutFile_OpenW(CSzFile *p, const WCHAR *name);\r
+#endif\r
+WRes File_Close(CSzFile *p);\r
+\r
+/* reads max(*size, remain file's size) bytes */\r
+WRes File_Read(CSzFile *p, void *data, size_t *size);\r
+\r
+/* writes *size bytes */\r
+WRes File_Write(CSzFile *p, const void *data, size_t *size);\r
+\r
+WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin);\r
+WRes File_GetLength(CSzFile *p, UInt64 *length);\r
+\r
+\r
+/* ---------- FileInStream ---------- */\r
+\r
+typedef struct\r
+{\r
+  ISeqInStream s;\r
+  CSzFile file;\r
+} CFileSeqInStream;\r
+\r
+void FileSeqInStream_CreateVTable(CFileSeqInStream *p);\r
+\r
+\r
+typedef struct\r
+{\r
+  ISeekInStream s;\r
+  CSzFile file;\r
+} CFileInStream;\r
+\r
+void FileInStream_CreateVTable(CFileInStream *p);\r
+\r
+\r
+typedef struct\r
+{\r
+  ISeqOutStream s;\r
+  CSzFile file;\r
+} CFileOutStream;\r
+\r
+void FileOutStream_CreateVTable(CFileOutStream *p);\r
+\r
+EXTERN_C_END\r
+\r
+#endif\r
diff --git a/C/7zIn.c b/C/7zIn.c
new file mode 100755 (executable)
index 0000000..f1a4492
--- /dev/null
+++ b/C/7zIn.c
@@ -0,0 +1,1402 @@
+/* 7zIn.c -- 7z Input functions\r
+2010-10-29 : Igor Pavlov : Public domain */\r
+\r
+#include <string.h>\r
+\r
+#include "7z.h"\r
+#include "7zCrc.h"\r
+#include "CpuArch.h"\r
+\r
+Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};\r
+\r
+#define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; }\r
+\r
+#define NUM_FOLDER_CODERS_MAX 32\r
+#define NUM_CODER_STREAMS_MAX 32\r
+\r
+void SzCoderInfo_Init(CSzCoderInfo *p)\r
+{\r
+  Buf_Init(&p->Props);\r
+}\r
+\r
+void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc)\r
+{\r
+  Buf_Free(&p->Props, alloc);\r
+  SzCoderInfo_Init(p);\r
+}\r
+\r
+void SzFolder_Init(CSzFolder *p)\r
+{\r
+  p->Coders = 0;\r
+  p->BindPairs = 0;\r
+  p->PackStreams = 0;\r
+  p->UnpackSizes = 0;\r
+  p->NumCoders = 0;\r
+  p->NumBindPairs = 0;\r
+  p->NumPackStreams = 0;\r
+  p->UnpackCRCDefined = 0;\r
+  p->UnpackCRC = 0;\r
+  p->NumUnpackStreams = 0;\r
+}\r
+\r
+void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc)\r
+{\r
+  UInt32 i;\r
+  if (p->Coders)\r
+    for (i = 0; i < p->NumCoders; i++)\r
+      SzCoderInfo_Free(&p->Coders[i], alloc);\r
+  IAlloc_Free(alloc, p->Coders);\r
+  IAlloc_Free(alloc, p->BindPairs);\r
+  IAlloc_Free(alloc, p->PackStreams);\r
+  IAlloc_Free(alloc, p->UnpackSizes);\r
+  SzFolder_Init(p);\r
+}\r
+\r
+UInt32 SzFolder_GetNumOutStreams(CSzFolder *p)\r
+{\r
+  UInt32 result = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < p->NumCoders; i++)\r
+    result += p->Coders[i].NumOutStreams;\r
+  return result;\r
+}\r
+\r
+int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex)\r
+{\r
+  UInt32 i;\r
+  for (i = 0; i < p->NumBindPairs; i++)\r
+    if (p->BindPairs[i].InIndex == inStreamIndex)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+\r
+int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex)\r
+{\r
+  UInt32 i;\r
+  for (i = 0; i < p->NumBindPairs; i++)\r
+    if (p->BindPairs[i].OutIndex == outStreamIndex)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+UInt64 SzFolder_GetUnpackSize(CSzFolder *p)\r
+{\r
+  int i = (int)SzFolder_GetNumOutStreams(p);\r
+  if (i == 0)\r
+    return 0;\r
+  for (i--; i >= 0; i--)\r
+    if (SzFolder_FindBindPairForOutStream(p, i) < 0)\r
+      return p->UnpackSizes[i];\r
+  /* throw 1; */\r
+  return 0;\r
+}\r
+\r
+void SzFile_Init(CSzFileItem *p)\r
+{\r
+  p->HasStream = 1;\r
+  p->IsDir = 0;\r
+  p->IsAnti = 0;\r
+  p->CrcDefined = 0;\r
+  p->MTimeDefined = 0;\r
+}\r
+\r
+void SzAr_Init(CSzAr *p)\r
+{\r
+  p->PackSizes = 0;\r
+  p->PackCRCsDefined = 0;\r
+  p->PackCRCs = 0;\r
+  p->Folders = 0;\r
+  p->Files = 0;\r
+  p->NumPackStreams = 0;\r
+  p->NumFolders = 0;\r
+  p->NumFiles = 0;\r
+}\r
+\r
+void SzAr_Free(CSzAr *p, ISzAlloc *alloc)\r
+{\r
+  UInt32 i;\r
+  if (p->Folders)\r
+    for (i = 0; i < p->NumFolders; i++)\r
+      SzFolder_Free(&p->Folders[i], alloc);\r
+\r
+  IAlloc_Free(alloc, p->PackSizes);\r
+  IAlloc_Free(alloc, p->PackCRCsDefined);\r
+  IAlloc_Free(alloc, p->PackCRCs);\r
+  IAlloc_Free(alloc, p->Folders);\r
+  IAlloc_Free(alloc, p->Files);\r
+  SzAr_Init(p);\r
+}\r
+\r
+\r
+void SzArEx_Init(CSzArEx *p)\r
+{\r
+  SzAr_Init(&p->db);\r
+  p->FolderStartPackStreamIndex = 0;\r
+  p->PackStreamStartPositions = 0;\r
+  p->FolderStartFileIndex = 0;\r
+  p->FileIndexToFolderIndexMap = 0;\r
+  p->FileNameOffsets = 0;\r
+  Buf_Init(&p->FileNames);\r
+}\r
+\r
+void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc)\r
+{\r
+  IAlloc_Free(alloc, p->FolderStartPackStreamIndex);\r
+  IAlloc_Free(alloc, p->PackStreamStartPositions);\r
+  IAlloc_Free(alloc, p->FolderStartFileIndex);\r
+  IAlloc_Free(alloc, p->FileIndexToFolderIndexMap);\r
+\r
+  IAlloc_Free(alloc, p->FileNameOffsets);\r
+  Buf_Free(&p->FileNames, alloc);\r
+\r
+  SzAr_Free(&p->db, alloc);\r
+  SzArEx_Init(p);\r
+}\r
+\r
+/*\r
+UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const\r
+{\r
+  return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];\r
+}\r
+\r
+UInt64 GetFilePackSize(int fileIndex) const\r
+{\r
+  int folderIndex = FileIndexToFolderIndexMap[fileIndex];\r
+  if (folderIndex >= 0)\r
+  {\r
+    const CSzFolder &folderInfo = Folders[folderIndex];\r
+    if (FolderStartFileIndex[folderIndex] == fileIndex)\r
+    return GetFolderFullPackSize(folderIndex);\r
+  }\r
+  return 0;\r
+}\r
+*/\r
+\r
+#define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \\r
+  if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; }\r
+\r
+static SRes SzArEx_Fill(CSzArEx *p, ISzAlloc *alloc)\r
+{\r
+  UInt32 startPos = 0;\r
+  UInt64 startPosSize = 0;\r
+  UInt32 i;\r
+  UInt32 folderIndex = 0;\r
+  UInt32 indexInFolder = 0;\r
+  MY_ALLOC(UInt32, p->FolderStartPackStreamIndex, p->db.NumFolders, alloc);\r
+  for (i = 0; i < p->db.NumFolders; i++)\r
+  {\r
+    p->FolderStartPackStreamIndex[i] = startPos;\r
+    startPos += p->db.Folders[i].NumPackStreams;\r
+  }\r
+\r
+  MY_ALLOC(UInt64, p->PackStreamStartPositions, p->db.NumPackStreams, alloc);\r
+\r
+  for (i = 0; i < p->db.NumPackStreams; i++)\r
+  {\r
+    p->PackStreamStartPositions[i] = startPosSize;\r
+    startPosSize += p->db.PackSizes[i];\r
+  }\r
+\r
+  MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders, alloc);\r
+  MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->db.NumFiles, alloc);\r
+\r
+  for (i = 0; i < p->db.NumFiles; i++)\r
+  {\r
+    CSzFileItem *file = p->db.Files + i;\r
+    int emptyStream = !file->HasStream;\r
+    if (emptyStream && indexInFolder == 0)\r
+    {\r
+      p->FileIndexToFolderIndexMap[i] = (UInt32)-1;\r
+      continue;\r
+    }\r
+    if (indexInFolder == 0)\r
+    {\r
+      /*\r
+      v3.13 incorrectly worked with empty folders\r
+      v4.07: Loop for skipping empty folders\r
+      */\r
+      for (;;)\r
+      {\r
+        if (folderIndex >= p->db.NumFolders)\r
+          return SZ_ERROR_ARCHIVE;\r
+        p->FolderStartFileIndex[folderIndex] = i;\r
+        if (p->db.Folders[folderIndex].NumUnpackStreams != 0)\r
+          break;\r
+        folderIndex++;\r
+      }\r
+    }\r
+    p->FileIndexToFolderIndexMap[i] = folderIndex;\r
+    if (emptyStream)\r
+      continue;\r
+    indexInFolder++;\r
+    if (indexInFolder >= p->db.Folders[folderIndex].NumUnpackStreams)\r
+    {\r
+      folderIndex++;\r
+      indexInFolder = 0;\r
+    }\r
+  }\r
+  return SZ_OK;\r
+}\r
+\r
+\r
+UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder)\r
+{\r
+  return p->dataPos +\r
+    p->PackStreamStartPositions[p->FolderStartPackStreamIndex[folderIndex] + indexInFolder];\r
+}\r
+\r
+int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize)\r
+{\r
+  UInt32 packStreamIndex = p->FolderStartPackStreamIndex[folderIndex];\r
+  CSzFolder *folder = p->db.Folders + folderIndex;\r
+  UInt64 size = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < folder->NumPackStreams; i++)\r
+  {\r
+    UInt64 t = size + p->db.PackSizes[packStreamIndex + i];\r
+    if (t < size) /* check it */\r
+      return SZ_ERROR_FAIL;\r
+    size = t;\r
+  }\r
+  *resSize = size;\r
+  return SZ_OK;\r
+}\r
+\r
+\r
+/*\r
+SRes SzReadTime(const CObjectVector<CBuf> &dataVector,\r
+    CObjectVector<CSzFileItem> &files, UInt64 type)\r
+{\r
+  CBoolVector boolVector;\r
+  RINOK(ReadBoolVector2(files.Size(), boolVector))\r
+\r
+  CStreamSwitch streamSwitch;\r
+  RINOK(streamSwitch.Set(this, &dataVector));\r
+\r
+  for (int i = 0; i < files.Size(); i++)\r
+  {\r
+    CSzFileItem &file = files[i];\r
+    CArchiveFileTime fileTime;\r
+    bool defined = boolVector[i];\r
+    if (defined)\r
+    {\r
+      UInt32 low, high;\r
+      RINOK(SzReadUInt32(low));\r
+      RINOK(SzReadUInt32(high));\r
+      fileTime.dwLowDateTime = low;\r
+      fileTime.dwHighDateTime = high;\r
+    }\r
+    switch(type)\r
+    {\r
+      case k7zIdCTime: file.IsCTimeDefined = defined; if (defined) file.CTime = fileTime; break;\r
+      case k7zIdATime: file.IsATimeDefined = defined; if (defined) file.ATime = fileTime; break;\r
+      case k7zIdMTime: file.IsMTimeDefined = defined; if (defined) file.MTime = fileTime; break;\r
+    }\r
+  }\r
+  return SZ_OK;\r
+}\r
+*/\r
+\r
+static int TestSignatureCandidate(Byte *testBytes)\r
+{\r
+  size_t i;\r
+  for (i = 0; i < k7zSignatureSize; i++)\r
+    if (testBytes[i] != k7zSignature[i])\r
+      return 0;\r
+  return 1;\r
+}\r
+\r
+typedef struct _CSzState\r
+{\r
+  Byte *Data;\r
+  size_t Size;\r
+}CSzData;\r
+\r
+static SRes SzReadByte(CSzData *sd, Byte *b)\r
+{\r
+  if (sd->Size == 0)\r
+    return SZ_ERROR_ARCHIVE;\r
+  sd->Size--;\r
+  *b = *sd->Data++;\r
+  return SZ_OK;\r
+}\r
+\r
+static SRes SzReadBytes(CSzData *sd, Byte *data, size_t size)\r
+{\r
+  size_t i;\r
+  for (i = 0; i < size; i++)\r
+  {\r
+    RINOK(SzReadByte(sd, data + i));\r
+  }\r
+  return SZ_OK;\r
+}\r
+\r
+static SRes SzReadUInt32(CSzData *sd, UInt32 *value)\r
+{\r
+  int i;\r
+  *value = 0;\r
+  for (i = 0; i < 4; i++)\r
+  {\r
+    Byte b;\r
+    RINOK(SzReadByte(sd, &b));\r
+    *value |= ((UInt32)(b) << (8 * i));\r
+  }\r
+  return SZ_OK;\r
+}\r
+\r
+static SRes SzReadNumber(CSzData *sd, UInt64 *value)\r
+{\r
+  Byte firstByte;\r
+  Byte mask = 0x80;\r
+  int i;\r
+  RINOK(SzReadByte(sd, &firstByte));\r
+  *value = 0;\r
+  for (i = 0; i < 8; i++)\r
+  {\r
+    Byte b;\r
+    if ((firstByte & mask) == 0)\r
+    {\r
+      UInt64 highPart = firstByte & (mask - 1);\r
+      *value += (highPart << (8 * i));\r
+      return SZ_OK;\r
+    }\r
+    RINOK(SzReadByte(sd, &b));\r
+    *value |= ((UInt64)b << (8 * i));\r
+    mask >>= 1;\r
+  }\r
+  return SZ_OK;\r
+}\r
+\r
+static SRes SzReadNumber32(CSzData *sd, UInt32 *value)\r
+{\r
+  UInt64 value64;\r
+  RINOK(SzReadNumber(sd, &value64));\r
+  if (value64 >= 0x80000000)\r
+    return SZ_ERROR_UNSUPPORTED;\r
+  if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2)))\r
+    return SZ_ERROR_UNSUPPORTED;\r
+  *value = (UInt32)value64;\r
+  return SZ_OK;\r
+}\r
+\r
+static SRes SzReadID(CSzData *sd, UInt64 *value)\r
+{\r
+  return SzReadNumber(sd, value);\r
+}\r
+\r
+static SRes SzSkeepDataSize(CSzData *sd, UInt64 size)\r
+{\r
+  if (size > sd->Size)\r
+    return SZ_ERROR_ARCHIVE;\r
+  sd->Size -= (size_t)size;\r
+  sd->Data += (size_t)size;\r
+  return SZ_OK;\r
+}\r
+\r
+static SRes SzSkeepData(CSzData *sd)\r
+{\r
+  UInt64 size;\r
+  RINOK(SzReadNumber(sd, &size));\r
+  return SzSkeepDataSize(sd, size);\r
+}\r
+\r
+static SRes SzReadArchiveProperties(CSzData *sd)\r
+{\r
+  for (;;)\r
+  {\r
+    UInt64 type;\r
+    RINOK(SzReadID(sd, &type));\r
+    if (type == k7zIdEnd)\r
+      break;\r
+    SzSkeepData(sd);\r
+  }\r
+  return SZ_OK;\r
+}\r
+\r
+static SRes SzWaitAttribute(CSzData *sd, UInt64 attribute)\r
+{\r
+  for (;;)\r
+  {\r
+    UInt64 type;\r
+    RINOK(SzReadID(sd, &type));\r
+    if (type == attribute)\r
+      return SZ_OK;\r
+    if (type == k7zIdEnd)\r
+      return SZ_ERROR_ARCHIVE;\r
+    RINOK(SzSkeepData(sd));\r
+  }\r
+}\r
+\r
+static SRes SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc)\r
+{\r
+  Byte b = 0;\r
+  Byte mask = 0;\r
+  size_t i;\r
+  MY_ALLOC(Byte, *v, numItems, alloc);\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    if (mask == 0)\r
+    {\r
+      RINOK(SzReadByte(sd, &b));\r
+      mask = 0x80;\r
+    }\r
+    (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0);\r
+    mask >>= 1;\r
+  }\r
+  return SZ_OK;\r
+}\r
+\r
+static SRes SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc)\r
+{\r
+  Byte allAreDefined;\r
+  size_t i;\r
+  RINOK(SzReadByte(sd, &allAreDefined));\r
+  if (allAreDefined == 0)\r
+    return SzReadBoolVector(sd, numItems, v, alloc);\r
+  MY_ALLOC(Byte, *v, numItems, alloc);\r
+  for (i = 0; i < numItems; i++)\r
+    (*v)[i] = 1;\r
+  return SZ_OK;\r
+}\r
+\r
+static SRes SzReadHashDigests(\r
+    CSzData *sd,\r
+    size_t numItems,\r
+    Byte **digestsDefined,\r
+    UInt32 **digests,\r
+    ISzAlloc *alloc)\r
+{\r
+  size_t i;\r
+  RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, alloc));\r
+  MY_ALLOC(UInt32, *digests, numItems, alloc);\r
+  for (i = 0; i < numItems; i++)\r
+    if ((*digestsDefined)[i])\r
+    {\r
+      RINOK(SzReadUInt32(sd, (*digests) + i));\r
+    }\r
+  return SZ_OK;\r
+}\r
+\r
+static SRes SzReadPackInfo(\r
+    CSzData *sd,\r
+    UInt64 *dataOffset,\r
+    UInt32 *numPackStreams,\r
+    UInt64 **packSizes,\r
+    Byte **packCRCsDefined,\r
+    UInt32 **packCRCs,\r
+    ISzAlloc *alloc)\r
+{\r
+  UInt32 i;\r
+  RINOK(SzReadNumber(sd, dataOffset));\r
+  RINOK(SzReadNumber32(sd, numPackStreams));\r
+\r
+  RINOK(SzWaitAttribute(sd, k7zIdSize));\r
+\r
+  MY_ALLOC(UInt64, *packSizes, (size_t)*numPackStreams, alloc);\r
+\r
+  for (i = 0; i < *numPackStreams; i++)\r
+  {\r
+    RINOK(SzReadNumber(sd, (*packSizes) + i));\r
+  }\r
+\r
+  for (;;)\r
+  {\r
+    UInt64 type;\r
+    RINOK(SzReadID(sd, &type));\r
+    if (type == k7zIdEnd)\r
+      break;\r
+    if (type == k7zIdCRC)\r
+    {\r
+      RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, alloc));\r
+      continue;\r
+    }\r
+    RINOK(SzSkeepData(sd));\r
+  }\r
+  if (*packCRCsDefined == 0)\r
+  {\r
+    MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, alloc);\r
+    MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, alloc);\r
+    for (i = 0; i < *numPackStreams; i++)\r
+    {\r
+      (*packCRCsDefined)[i] = 0;\r
+      (*packCRCs)[i] = 0;\r
+    }\r
+  }\r
+  return SZ_OK;\r
+}\r
+\r
+static SRes SzReadSwitch(CSzData *sd)\r
+{\r
+  Byte external;\r
+  RINOK(SzReadByte(sd, &external));\r
+  return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED;\r
+}\r
+\r
+static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc)\r
+{\r
+  UInt32 numCoders, numBindPairs, numPackStreams, i;\r
+  UInt32 numInStreams = 0, numOutStreams = 0;\r
+  \r
+  RINOK(SzReadNumber32(sd, &numCoders));\r
+  if (numCoders > NUM_FOLDER_CODERS_MAX)\r
+    return SZ_ERROR_UNSUPPORTED;\r
+  folder->NumCoders = numCoders;\r
+  \r
+  MY_ALLOC(CSzCoderInfo, folder->Coders, (size_t)numCoders, alloc);\r
+\r
+  for (i = 0; i < numCoders; i++)\r
+    SzCoderInfo_Init(folder->Coders + i);\r
+\r
+  for (i = 0; i < numCoders; i++)\r
+  {\r
+    Byte mainByte;\r
+    CSzCoderInfo *coder = folder->Coders + i;\r
+    {\r
+      unsigned idSize, j;\r
+      Byte longID[15];\r
+      RINOK(SzReadByte(sd, &mainByte));\r
+      idSize = (unsigned)(mainByte & 0xF);\r
+      RINOK(SzReadBytes(sd, longID, idSize));\r
+      if (idSize > sizeof(coder->MethodID))\r
+        return SZ_ERROR_UNSUPPORTED;\r
+      coder->MethodID = 0;\r
+      for (j = 0; j < idSize; j++)\r
+        coder->MethodID |= (UInt64)longID[idSize - 1 - j] << (8 * j);\r
+\r
+      if ((mainByte & 0x10) != 0)\r
+      {\r
+        RINOK(SzReadNumber32(sd, &coder->NumInStreams));\r
+        RINOK(SzReadNumber32(sd, &coder->NumOutStreams));\r
+        if (coder->NumInStreams > NUM_CODER_STREAMS_MAX ||\r
+            coder->NumOutStreams > NUM_CODER_STREAMS_MAX)\r
+          return SZ_ERROR_UNSUPPORTED;\r
+      }\r
+      else\r
+      {\r
+        coder->NumInStreams = 1;\r
+        coder->NumOutStreams = 1;\r
+      }\r
+      if ((mainByte & 0x20) != 0)\r
+      {\r
+        UInt64 propertiesSize = 0;\r
+        RINOK(SzReadNumber(sd, &propertiesSize));\r
+        if (!Buf_Create(&coder->Props, (size_t)propertiesSize, alloc))\r
+          return SZ_ERROR_MEM;\r
+        RINOK(SzReadBytes(sd, coder->Props.data, (size_t)propertiesSize));\r
+      }\r
+    }\r
+    while ((mainByte & 0x80) != 0)\r
+    {\r
+      RINOK(SzReadByte(sd, &mainByte));\r
+      RINOK(SzSkeepDataSize(sd, (mainByte & 0xF)));\r
+      if ((mainByte & 0x10) != 0)\r
+      {\r
+        UInt32 n;\r
+        RINOK(SzReadNumber32(sd, &n));\r
+        RINOK(SzReadNumber32(sd, &n));\r
+      }\r
+      if ((mainByte & 0x20) != 0)\r
+      {\r
+        UInt64 propertiesSize = 0;\r
+        RINOK(SzReadNumber(sd, &propertiesSize));\r
+        RINOK(SzSkeepDataSize(sd, propertiesSize));\r
+      }\r
+    }\r
+    numInStreams += coder->NumInStreams;\r
+    numOutStreams += coder->NumOutStreams;\r
+  }\r
+\r
+  if (numOutStreams == 0)\r
+    return SZ_ERROR_UNSUPPORTED;\r
+\r
+  folder->NumBindPairs = numBindPairs = numOutStreams - 1;\r
+  MY_ALLOC(CSzBindPair, folder->BindPairs, (size_t)numBindPairs, alloc);\r
+\r
+  for (i = 0; i < numBindPairs; i++)\r
+  {\r
+    CSzBindPair *bp = folder->BindPairs + i;\r
+    RINOK(SzReadNumber32(sd, &bp->InIndex));\r
+    RINOK(SzReadNumber32(sd, &bp->OutIndex));\r
+  }\r
+\r
+  if (numInStreams < numBindPairs)\r
+    return SZ_ERROR_UNSUPPORTED;\r
+\r
+  folder->NumPackStreams = numPackStreams = numInStreams - numBindPairs;\r
+  MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackStreams, alloc);\r
+\r
+  if (numPackStreams == 1)\r
+  {\r
+    for (i = 0; i < numInStreams ; i++)\r
+      if (SzFolder_FindBindPairForInStream(folder, i) < 0)\r
+        break;\r
+    if (i == numInStreams)\r
+      return SZ_ERROR_UNSUPPORTED;\r
+    folder->PackStreams[0] = i;\r
+  }\r
+  else\r
+    for (i = 0; i < numPackStreams; i++)\r
+    {\r
+      RINOK(SzReadNumber32(sd, folder->PackStreams + i));\r
+    }\r
+  return SZ_OK;\r
+}\r
+\r
+static SRes SzReadUnpackInfo(\r
+    CSzData *sd,\r
+    UInt32 *numFolders,\r
+    CSzFolder **folders,  /* for alloc */\r
+    ISzAlloc *alloc,\r
+    ISzAlloc *allocTemp)\r
+{\r
+  UInt32 i;\r
+  RINOK(SzWaitAttribute(sd, k7zIdFolder));\r
+  RINOK(SzReadNumber32(sd, numFolders));\r
+  {\r
+    RINOK(SzReadSwitch(sd));\r
+\r
+    MY_ALLOC(CSzFolder, *folders, (size_t)*numFolders, alloc);\r
+\r
+    for (i = 0; i < *numFolders; i++)\r
+      SzFolder_Init((*folders) + i);\r
+\r
+    for (i = 0; i < *numFolders; i++)\r
+    {\r
+      RINOK(SzGetNextFolderItem(sd, (*folders) + i, alloc));\r
+    }\r
+  }\r
+\r
+  RINOK(SzWaitAttribute(sd, k7zIdCodersUnpackSize));\r
+\r
+  for (i = 0; i < *numFolders; i++)\r
+  {\r
+    UInt32 j;\r
+    CSzFolder *folder = (*folders) + i;\r
+    UInt32 numOutStreams = SzFolder_GetNumOutStreams(folder);\r
+\r
+    MY_ALLOC(UInt64, folder->UnpackSizes, (size_t)numOutStreams, alloc);\r
+\r
+    for (j = 0; j < numOutStreams; j++)\r
+    {\r
+      RINOK(SzReadNumber(sd, folder->UnpackSizes + j));\r
+    }\r
+  }\r
+\r
+  for (;;)\r
+  {\r
+    UInt64 type;\r
+    RINOK(SzReadID(sd, &type));\r
+    if (type == k7zIdEnd)\r
+      return SZ_OK;\r
+    if (type == k7zIdCRC)\r
+    {\r
+      SRes res;\r
+      Byte *crcsDefined = 0;\r
+      UInt32 *crcs = 0;\r
+      res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp);\r
+      if (res == SZ_OK)\r
+      {\r
+        for (i = 0; i < *numFolders; i++)\r
+        {\r
+          CSzFolder *folder = (*folders) + i;\r
+          folder->UnpackCRCDefined = crcsDefined[i];\r
+          folder->UnpackCRC = crcs[i];\r
+        }\r
+      }\r
+      IAlloc_Free(allocTemp, crcs);\r
+      IAlloc_Free(allocTemp, crcsDefined);\r
+      RINOK(res);\r
+      continue;\r
+    }\r
+    RINOK(SzSkeepData(sd));\r
+  }\r
+}\r
+\r
+static SRes SzReadSubStreamsInfo(\r
+    CSzData *sd,\r
+    UInt32 numFolders,\r
+    CSzFolder *folders,\r
+    UInt32 *numUnpackStreams,\r
+    UInt64 **unpackSizes,\r
+    Byte **digestsDefined,\r
+    UInt32 **digests,\r
+    ISzAlloc *allocTemp)\r
+{\r
+  UInt64 type = 0;\r
+  UInt32 i;\r
+  UInt32 si = 0;\r
+  UInt32 numDigests = 0;\r
+\r
+  for (i = 0; i < numFolders; i++)\r
+    folders[i].NumUnpackStreams = 1;\r
+  *numUnpackStreams = numFolders;\r
+\r
+  for (;;)\r
+  {\r
+    RINOK(SzReadID(sd, &type));\r
+    if (type == k7zIdNumUnpackStream)\r
+    {\r
+      *numUnpackStreams = 0;\r
+      for (i = 0; i < numFolders; i++)\r
+      {\r
+        UInt32 numStreams;\r
+        RINOK(SzReadNumber32(sd, &numStreams));\r
+        folders[i].NumUnpackStreams = numStreams;\r
+        *numUnpackStreams += numStreams;\r
+      }\r
+      continue;\r
+    }\r
+    if (type == k7zIdCRC || type == k7zIdSize)\r
+      break;\r
+    if (type == k7zIdEnd)\r
+      break;\r
+    RINOK(SzSkeepData(sd));\r
+  }\r
+\r
+  if (*numUnpackStreams == 0)\r
+  {\r
+    *unpackSizes = 0;\r
+    *digestsDefined = 0;\r
+    *digests = 0;\r
+  }\r
+  else\r
+  {\r
+    *unpackSizes = (UInt64 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt64));\r
+    RINOM(*unpackSizes);\r
+    *digestsDefined = (Byte *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(Byte));\r
+    RINOM(*digestsDefined);\r
+    *digests = (UInt32 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt32));\r
+    RINOM(*digests);\r
+  }\r
+\r
+  for (i = 0; i < numFolders; i++)\r
+  {\r
+    /*\r
+    v3.13 incorrectly worked with empty folders\r
+    v4.07: we check that folder is empty\r
+    */\r
+    UInt64 sum = 0;\r
+    UInt32 j;\r
+    UInt32 numSubstreams = folders[i].NumUnpackStreams;\r
+    if (numSubstreams == 0)\r
+      continue;\r
+    if (type == k7zIdSize)\r
+    for (j = 1; j < numSubstreams; j++)\r
+    {\r
+      UInt64 size;\r
+      RINOK(SzReadNumber(sd, &size));\r
+      (*unpackSizes)[si++] = size;\r
+      sum += size;\r
+    }\r
+    (*unpackSizes)[si++] = SzFolder_GetUnpackSize(folders + i) - sum;\r
+  }\r
+  if (type == k7zIdSize)\r
+  {\r
+    RINOK(SzReadID(sd, &type));\r
+  }\r
+\r
+  for (i = 0; i < *numUnpackStreams; i++)\r
+  {\r
+    (*digestsDefined)[i] = 0;\r
+    (*digests)[i] = 0;\r
+  }\r
+\r
+\r
+  for (i = 0; i < numFolders; i++)\r
+  {\r
+    UInt32 numSubstreams = folders[i].NumUnpackStreams;\r
+    if (numSubstreams != 1 || !folders[i].UnpackCRCDefined)\r
+      numDigests += numSubstreams;\r
+  }\r
+\r
\r
+  si = 0;\r
+  for (;;)\r
+  {\r
+    if (type == k7zIdCRC)\r
+    {\r
+      int digestIndex = 0;\r
+      Byte *digestsDefined2 = 0;\r
+      UInt32 *digests2 = 0;\r
+      SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp);\r
+      if (res == SZ_OK)\r
+      {\r
+        for (i = 0; i < numFolders; i++)\r
+        {\r
+          CSzFolder *folder = folders + i;\r
+          UInt32 numSubstreams = folder->NumUnpackStreams;\r
+          if (numSubstreams == 1 && folder->UnpackCRCDefined)\r
+          {\r
+            (*digestsDefined)[si] = 1;\r
+            (*digests)[si] = folder->UnpackCRC;\r
+            si++;\r
+          }\r
+          else\r
+          {\r
+            UInt32 j;\r
+            for (j = 0; j < numSubstreams; j++, digestIndex++)\r
+            {\r
+              (*digestsDefined)[si] = digestsDefined2[digestIndex];\r
+              (*digests)[si] = digests2[digestIndex];\r
+              si++;\r
+            }\r
+          }\r
+        }\r
+      }\r
+      IAlloc_Free(allocTemp, digestsDefined2);\r
+      IAlloc_Free(allocTemp, digests2);\r
+      RINOK(res);\r
+    }\r
+    else if (type == k7zIdEnd)\r
+      return SZ_OK;\r
+    else\r
+    {\r
+      RINOK(SzSkeepData(sd));\r
+    }\r
+    RINOK(SzReadID(sd, &type));\r
+  }\r
+}\r
+\r
+\r
+static SRes SzReadStreamsInfo(\r
+    CSzData *sd,\r
+    UInt64 *dataOffset,\r
+    CSzAr *p,\r
+    UInt32 *numUnpackStreams,\r
+    UInt64 **unpackSizes, /* allocTemp */\r
+    Byte **digestsDefined,   /* allocTemp */\r
+    UInt32 **digests,        /* allocTemp */\r
+    ISzAlloc *alloc,\r
+    ISzAlloc *allocTemp)\r
+{\r
+  for (;;)\r
+  {\r
+    UInt64 type;\r
+    RINOK(SzReadID(sd, &type));\r
+    if ((UInt64)(int)type != type)\r
+      return SZ_ERROR_UNSUPPORTED;\r
+    switch((int)type)\r
+    {\r
+      case k7zIdEnd:\r
+        return SZ_OK;\r
+      case k7zIdPackInfo:\r
+      {\r
+        RINOK(SzReadPackInfo(sd, dataOffset, &p->NumPackStreams,\r
+            &p->PackSizes, &p->PackCRCsDefined, &p->PackCRCs, alloc));\r
+        break;\r
+      }\r
+      case k7zIdUnpackInfo:\r
+      {\r
+        RINOK(SzReadUnpackInfo(sd, &p->NumFolders, &p->Folders, alloc, allocTemp));\r
+        break;\r
+      }\r
+      case k7zIdSubStreamsInfo:\r
+      {\r
+        RINOK(SzReadSubStreamsInfo(sd, p->NumFolders, p->Folders,\r
+            numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp));\r
+        break;\r
+      }\r
+      default:\r
+        return SZ_ERROR_UNSUPPORTED;\r
+    }\r
+  }\r
+}\r
+\r
+size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest)\r
+{\r
+  size_t len = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];\r
+  if (dest != 0)\r
+  {\r
+    size_t i;\r
+    const Byte *src = p->FileNames.data + (p->FileNameOffsets[fileIndex] * 2);\r
+    for (i = 0; i < len; i++)\r
+      dest[i] = GetUi16(src + i * 2);\r
+  }\r
+  return len;\r
+}\r
+\r
+static SRes SzReadFileNames(const Byte *p, size_t size, UInt32 numFiles, size_t *sizes)\r
+{\r
+  UInt32 i;\r
+  size_t pos = 0;\r
+  for (i = 0; i < numFiles; i++)\r
+  {\r
+    sizes[i] = pos;\r
+    for (;;)\r
+    {\r
+      if (pos >= size)\r
+        return SZ_ERROR_ARCHIVE;\r
+      if (p[pos * 2] == 0 && p[pos * 2 + 1] == 0)\r
+        break;\r
+      pos++;\r
+    }\r
+    pos++;\r
+  }\r
+  sizes[i] = pos;\r
+  return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;\r
+}\r
+\r
+static SRes SzReadHeader2(\r
+    CSzArEx *p,   /* allocMain */\r
+    CSzData *sd,\r
+    UInt64 **unpackSizes,  /* allocTemp */\r
+    Byte **digestsDefined,    /* allocTemp */\r
+    UInt32 **digests,         /* allocTemp */\r
+    Byte **emptyStreamVector, /* allocTemp */\r
+    Byte **emptyFileVector,   /* allocTemp */\r
+    Byte **lwtVector,         /* allocTemp */\r
+    ISzAlloc *allocMain,\r
+    ISzAlloc *allocTemp)\r
+{\r
+  UInt64 type;\r
+  UInt32 numUnpackStreams = 0;\r
+  UInt32 numFiles = 0;\r
+  CSzFileItem *files = 0;\r
+  UInt32 numEmptyStreams = 0;\r
+  UInt32 i;\r
+\r
+  RINOK(SzReadID(sd, &type));\r
+\r
+  if (type == k7zIdArchiveProperties)\r
+  {\r
+    RINOK(SzReadArchiveProperties(sd));\r
+    RINOK(SzReadID(sd, &type));\r
+  }\r
\r
\r
+  if (type == k7zIdMainStreamsInfo)\r
+  {\r
+    RINOK(SzReadStreamsInfo(sd,\r
+        &p->dataPos,\r
+        &p->db,\r
+        &numUnpackStreams,\r
+        unpackSizes,\r
+        digestsDefined,\r
+        digests, allocMain, allocTemp));\r
+    p->dataPos += p->startPosAfterHeader;\r
+    RINOK(SzReadID(sd, &type));\r
+  }\r
+\r
+  if (type == k7zIdEnd)\r
+    return SZ_OK;\r
+  if (type != k7zIdFilesInfo)\r
+    return SZ_ERROR_ARCHIVE;\r
+  \r
+  RINOK(SzReadNumber32(sd, &numFiles));\r
+  p->db.NumFiles = numFiles;\r
+\r
+  MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain);\r
+\r
+  p->db.Files = files;\r
+  for (i = 0; i < numFiles; i++)\r
+    SzFile_Init(files + i);\r
+\r
+  for (;;)\r
+  {\r
+    UInt64 type;\r
+    UInt64 size;\r
+    RINOK(SzReadID(sd, &type));\r
+    if (type == k7zIdEnd)\r
+      break;\r
+    RINOK(SzReadNumber(sd, &size));\r
+    if (size > sd->Size)\r
+      return SZ_ERROR_ARCHIVE;\r
+    if ((UInt64)(int)type != type)\r
+    {\r
+      RINOK(SzSkeepDataSize(sd, size));\r
+    }\r
+    else\r
+    switch((int)type)\r
+    {\r
+      case k7zIdName:\r
+      {\r
+        size_t namesSize;\r
+        RINOK(SzReadSwitch(sd));\r
+        namesSize = (size_t)size - 1;\r
+        if ((namesSize & 1) != 0)\r
+          return SZ_ERROR_ARCHIVE;\r
+        if (!Buf_Create(&p->FileNames, namesSize, allocMain))\r
+          return SZ_ERROR_MEM;\r
+        MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain);\r
+        memcpy(p->FileNames.data, sd->Data, namesSize);\r
+        RINOK(SzReadFileNames(sd->Data, namesSize >> 1, numFiles, p->FileNameOffsets))\r
+        RINOK(SzSkeepDataSize(sd, namesSize));\r
+        break;\r
+      }\r
+      case k7zIdEmptyStream:\r
+      {\r
+        RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp));\r
+        numEmptyStreams = 0;\r
+        for (i = 0; i < numFiles; i++)\r
+          if ((*emptyStreamVector)[i])\r
+            numEmptyStreams++;\r
+        break;\r
+      }\r
+      case k7zIdEmptyFile:\r
+      {\r
+        RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp));\r
+        break;\r
+      }\r
+      case k7zIdWinAttributes:\r
+      {\r
+        RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));\r
+        RINOK(SzReadSwitch(sd));\r
+        for (i = 0; i < numFiles; i++)\r
+        {\r
+          CSzFileItem *f = &files[i];\r
+          Byte defined = (*lwtVector)[i];\r
+          f->AttribDefined = defined;\r
+          f->Attrib = 0;\r
+          if (defined)\r
+          {\r
+            RINOK(SzReadUInt32(sd, &f->Attrib));\r
+          }\r
+        }\r
+        IAlloc_Free(allocTemp, *lwtVector);\r
+        *lwtVector = NULL;\r
+        break;\r
+      }\r
+      case k7zIdMTime:\r
+      {\r
+        RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));\r
+        RINOK(SzReadSwitch(sd));\r
+        for (i = 0; i < numFiles; i++)\r
+        {\r
+          CSzFileItem *f = &files[i];\r
+          Byte defined = (*lwtVector)[i];\r
+          f->MTimeDefined = defined;\r
+          f->MTime.Low = f->MTime.High = 0;\r
+          if (defined)\r
+          {\r
+            RINOK(SzReadUInt32(sd, &f->MTime.Low));\r
+            RINOK(SzReadUInt32(sd, &f->MTime.High));\r
+          }\r
+        }\r
+        IAlloc_Free(allocTemp, *lwtVector);\r
+        *lwtVector = NULL;\r
+        break;\r
+      }\r
+      default:\r
+      {\r
+        RINOK(SzSkeepDataSize(sd, size));\r
+      }\r
+    }\r
+  }\r
+\r
+  {\r
+    UInt32 emptyFileIndex = 0;\r
+    UInt32 sizeIndex = 0;\r
+    for (i = 0; i < numFiles; i++)\r
+    {\r
+      CSzFileItem *file = files + i;\r
+      file->IsAnti = 0;\r
+      if (*emptyStreamVector == 0)\r
+        file->HasStream = 1;\r
+      else\r
+        file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1);\r
+      if (file->HasStream)\r
+      {\r
+        file->IsDir = 0;\r
+        file->Size = (*unpackSizes)[sizeIndex];\r
+        file->Crc = (*digests)[sizeIndex];\r
+        file->CrcDefined = (Byte)(*digestsDefined)[sizeIndex];\r
+        sizeIndex++;\r
+      }\r
+      else\r
+      {\r
+        if (*emptyFileVector == 0)\r
+          file->IsDir = 1;\r
+        else\r
+          file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1);\r
+        emptyFileIndex++;\r
+        file->Size = 0;\r
+        file->Crc = 0;\r
+        file->CrcDefined = 0;\r
+      }\r
+    }\r
+  }\r
+  return SzArEx_Fill(p, allocMain);\r
+}\r
+\r
+static SRes SzReadHeader(\r
+    CSzArEx *p,\r
+    CSzData *sd,\r
+    ISzAlloc *allocMain,\r
+    ISzAlloc *allocTemp)\r
+{\r
+  UInt64 *unpackSizes = 0;\r
+  Byte *digestsDefined = 0;\r
+  UInt32 *digests = 0;\r
+  Byte *emptyStreamVector = 0;\r
+  Byte *emptyFileVector = 0;\r
+  Byte *lwtVector = 0;\r
+  SRes res = SzReadHeader2(p, sd,\r
+      &unpackSizes, &digestsDefined, &digests,\r
+      &emptyStreamVector, &emptyFileVector, &lwtVector,\r
+      allocMain, allocTemp);\r
+  IAlloc_Free(allocTemp, unpackSizes);\r
+  IAlloc_Free(allocTemp, digestsDefined);\r
+  IAlloc_Free(allocTemp, digests);\r
+  IAlloc_Free(allocTemp, emptyStreamVector);\r
+  IAlloc_Free(allocTemp, emptyFileVector);\r
+  IAlloc_Free(allocTemp, lwtVector);\r
+  return res;\r
+}\r
+\r
+static SRes SzReadAndDecodePackedStreams2(\r
+    ILookInStream *inStream,\r
+    CSzData *sd,\r
+    CBuf *outBuffer,\r
+    UInt64 baseOffset,\r
+    CSzAr *p,\r
+    UInt64 **unpackSizes,\r
+    Byte **digestsDefined,\r
+    UInt32 **digests,\r
+    ISzAlloc *allocTemp)\r
+{\r
+\r
+  UInt32 numUnpackStreams = 0;\r
+  UInt64 dataStartPos;\r
+  CSzFolder *folder;\r
+  UInt64 unpackSize;\r
+  SRes res;\r
+\r
+  RINOK(SzReadStreamsInfo(sd, &dataStartPos, p,\r
+      &numUnpackStreams,  unpackSizes, digestsDefined, digests,\r
+      allocTemp, allocTemp));\r
+  \r
+  dataStartPos += baseOffset;\r
+  if (p->NumFolders != 1)\r
+    return SZ_ERROR_ARCHIVE;\r
+\r
+  folder = p->Folders;\r
+  unpackSize = SzFolder_GetUnpackSize(folder);\r
+  \r
+  RINOK(LookInStream_SeekTo(inStream, dataStartPos));\r
+\r
+  if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp))\r
+    return SZ_ERROR_MEM;\r
+  \r
+  res = SzFolder_Decode(folder, p->PackSizes,\r
+          inStream, dataStartPos,\r
+          outBuffer->data, (size_t)unpackSize, allocTemp);\r
+  RINOK(res);\r
+  if (folder->UnpackCRCDefined)\r
+    if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC)\r
+      return SZ_ERROR_CRC;\r
+  return SZ_OK;\r
+}\r
+\r
+static SRes SzReadAndDecodePackedStreams(\r
+    ILookInStream *inStream,\r
+    CSzData *sd,\r
+    CBuf *outBuffer,\r
+    UInt64 baseOffset,\r
+    ISzAlloc *allocTemp)\r
+{\r
+  CSzAr p;\r
+  UInt64 *unpackSizes = 0;\r
+  Byte *digestsDefined = 0;\r
+  UInt32 *digests = 0;\r
+  SRes res;\r
+  SzAr_Init(&p);\r
+  res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset,\r
+    &p, &unpackSizes, &digestsDefined, &digests,\r
+    allocTemp);\r
+  SzAr_Free(&p, allocTemp);\r
+  IAlloc_Free(allocTemp, unpackSizes);\r
+  IAlloc_Free(allocTemp, digestsDefined);\r
+  IAlloc_Free(allocTemp, digests);\r
+  return res;\r
+}\r
+\r
+static SRes SzArEx_Open2(\r
+    CSzArEx *p,\r
+    ILookInStream *inStream,\r
+    ISzAlloc *allocMain,\r
+    ISzAlloc *allocTemp)\r
+{\r
+  Byte header[k7zStartHeaderSize];\r
+  Int64 startArcPos;\r
+  UInt64 nextHeaderOffset, nextHeaderSize;\r
+  size_t nextHeaderSizeT;\r
+  UInt32 nextHeaderCRC;\r
+  CBuf buffer;\r
+  SRes res;\r
+\r
+  startArcPos = 0;\r
+  RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR));\r
+\r
+  RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE));\r
+\r
+  if (!TestSignatureCandidate(header))\r
+    return SZ_ERROR_NO_ARCHIVE;\r
+  if (header[6] != k7zMajorVersion)\r
+    return SZ_ERROR_UNSUPPORTED;\r
+\r
+  nextHeaderOffset = GetUi64(header + 12);\r
+  nextHeaderSize = GetUi64(header + 20);\r
+  nextHeaderCRC = GetUi32(header + 28);\r
+\r
+  p->startPosAfterHeader = startArcPos + k7zStartHeaderSize;\r
+  \r
+  if (CrcCalc(header + 12, 20) != GetUi32(header + 8))\r
+    return SZ_ERROR_CRC;\r
+\r
+  nextHeaderSizeT = (size_t)nextHeaderSize;\r
+  if (nextHeaderSizeT != nextHeaderSize)\r
+    return SZ_ERROR_MEM;\r
+  if (nextHeaderSizeT == 0)\r
+    return SZ_OK;\r
+  if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize ||\r
+      nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize)\r
+    return SZ_ERROR_NO_ARCHIVE;\r
+\r
+  {\r
+    Int64 pos = 0;\r
+    RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END));\r
+    if ((UInt64)pos < startArcPos + nextHeaderOffset ||\r
+        (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset ||\r
+        (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)\r
+      return SZ_ERROR_INPUT_EOF;\r
+  }\r
+\r
+  RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset));\r
+\r
+  if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp))\r
+    return SZ_ERROR_MEM;\r
+\r
+  res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT);\r
+  if (res == SZ_OK)\r
+  {\r
+    res = SZ_ERROR_ARCHIVE;\r
+    if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC)\r
+    {\r
+      CSzData sd;\r
+      UInt64 type;\r
+      sd.Data = buffer.data;\r
+      sd.Size = buffer.size;\r
+      res = SzReadID(&sd, &type);\r
+      if (res == SZ_OK)\r
+      {\r
+        if (type == k7zIdEncodedHeader)\r
+        {\r
+          CBuf outBuffer;\r
+          Buf_Init(&outBuffer);\r
+          res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp);\r
+          if (res != SZ_OK)\r
+            Buf_Free(&outBuffer, allocTemp);\r
+          else\r
+          {\r
+            Buf_Free(&buffer, allocTemp);\r
+            buffer.data = outBuffer.data;\r
+            buffer.size = outBuffer.size;\r
+            sd.Data = buffer.data;\r
+            sd.Size = buffer.size;\r
+            res = SzReadID(&sd, &type);\r
+          }\r
+        }\r
+      }\r
+      if (res == SZ_OK)\r
+      {\r
+        if (type == k7zIdHeader)\r
+          res = SzReadHeader(p, &sd, allocMain, allocTemp);\r
+        else\r
+          res = SZ_ERROR_UNSUPPORTED;\r
+      }\r
+    }\r
+  }\r
+  Buf_Free(&buffer, allocTemp);\r
+  return res;\r
+}\r
+\r
+SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp)\r
+{\r
+  SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp);\r
+  if (res != SZ_OK)\r
+    SzArEx_Free(p, allocMain);\r
+  return res;\r
+}\r
+\r
+SRes SzArEx_Extract(\r
+    const CSzArEx *p,\r
+    ILookInStream *inStream,\r
+    UInt32 fileIndex,\r
+    UInt32 *blockIndex,\r
+    Byte **outBuffer,\r
+    size_t *outBufferSize,\r
+    size_t *offset,\r
+    size_t *outSizeProcessed,\r
+    ISzAlloc *allocMain,\r
+    ISzAlloc *allocTemp)\r
+{\r
+  UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];\r
+  SRes res = SZ_OK;\r
+  *offset = 0;\r
+  *outSizeProcessed = 0;\r
+  if (folderIndex == (UInt32)-1)\r
+  {\r
+    IAlloc_Free(allocMain, *outBuffer);\r
+    *blockIndex = folderIndex;\r
+    *outBuffer = 0;\r
+    *outBufferSize = 0;\r
+    return SZ_OK;\r
+  }\r
+\r
+  if (*outBuffer == 0 || *blockIndex != folderIndex)\r
+  {\r
+    CSzFolder *folder = p->db.Folders + folderIndex;\r
+    UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder);\r
+    size_t unpackSize = (size_t)unpackSizeSpec;\r
+    UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);\r
+\r
+    if (unpackSize != unpackSizeSpec)\r
+      return SZ_ERROR_MEM;\r
+    *blockIndex = folderIndex;\r
+    IAlloc_Free(allocMain, *outBuffer);\r
+    *outBuffer = 0;\r
+    \r
+    RINOK(LookInStream_SeekTo(inStream, startOffset));\r
+    \r
+    if (res == SZ_OK)\r
+    {\r
+      *outBufferSize = unpackSize;\r
+      if (unpackSize != 0)\r
+      {\r
+        *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize);\r
+        if (*outBuffer == 0)\r
+          res = SZ_ERROR_MEM;\r
+      }\r
+      if (res == SZ_OK)\r
+      {\r
+        res = SzFolder_Decode(folder,\r
+          p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex],\r
+          inStream, startOffset,\r
+          *outBuffer, unpackSize, allocTemp);\r
+        if (res == SZ_OK)\r
+        {\r
+          if (folder->UnpackCRCDefined)\r
+          {\r
+            if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)\r
+              res = SZ_ERROR_CRC;\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+  if (res == SZ_OK)\r
+  {\r
+    UInt32 i;\r
+    CSzFileItem *fileItem = p->db.Files + fileIndex;\r
+    *offset = 0;\r
+    for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)\r
+      *offset += (UInt32)p->db.Files[i].Size;\r
+    *outSizeProcessed = (size_t)fileItem->Size;\r
+    if (*offset + *outSizeProcessed > *outBufferSize)\r
+      return SZ_ERROR_FAIL;\r
+    if (fileItem->CrcDefined && CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->Crc)\r
+      res = SZ_ERROR_CRC;\r
+  }\r
+  return res;\r
+}\r
diff --git a/C/7zStream.c b/C/7zStream.c
new file mode 100755 (executable)
index 0000000..f0959fb
--- /dev/null
@@ -0,0 +1,169 @@
+/* 7zStream.c -- 7z Stream functions\r
+2010-03-11 : Igor Pavlov : Public domain */\r
+\r
+#include <string.h>\r
+\r
+#include "Types.h"\r
+\r
+SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType)\r
+{\r
+  while (size != 0)\r
+  {\r
+    size_t processed = size;\r
+    RINOK(stream->Read(stream, buf, &processed));\r
+    if (processed == 0)\r
+      return errorType;\r
+    buf = (void *)((Byte *)buf + processed);\r
+    size -= processed;\r
+  }\r
+  return SZ_OK;\r
+}\r
+\r
+SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size)\r
+{\r
+  return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);\r
+}\r
+\r
+SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf)\r
+{\r
+  size_t processed = 1;\r
+  RINOK(stream->Read(stream, buf, &processed));\r
+  return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF;\r
+}\r
+\r
+SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset)\r
+{\r
+  Int64 t = offset;\r
+  return stream->Seek(stream, &t, SZ_SEEK_SET);\r
+}\r
+\r
+SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size)\r
+{\r
+  const void *lookBuf;\r
+  if (*size == 0)\r
+    return SZ_OK;\r
+  RINOK(stream->Look(stream, &lookBuf, size));\r
+  memcpy(buf, lookBuf, *size);\r
+  return stream->Skip(stream, *size);\r
+}\r
+\r
+SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType)\r
+{\r
+  while (size != 0)\r
+  {\r
+    size_t processed = size;\r
+    RINOK(stream->Read(stream, buf, &processed));\r
+    if (processed == 0)\r
+      return errorType;\r
+    buf = (void *)((Byte *)buf + processed);\r
+    size -= processed;\r
+  }\r
+  return SZ_OK;\r
+}\r
+\r
+SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size)\r
+{\r
+  return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);\r
+}\r
+\r
+static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size)\r
+{\r
+  SRes res = SZ_OK;\r
+  CLookToRead *p = (CLookToRead *)pp;\r
+  size_t size2 = p->size - p->pos;\r
+  if (size2 == 0 && *size > 0)\r
+  {\r
+    p->pos = 0;\r
+    size2 = LookToRead_BUF_SIZE;\r
+    res = p->realStream->Read(p->realStream, p->buf, &size2);\r
+    p->size = size2;\r
+  }\r
+  if (size2 < *size)\r
+    *size = size2;\r
+  *buf = p->buf + p->pos;\r
+  return res;\r
+}\r
+\r
+static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size)\r
+{\r
+  SRes res = SZ_OK;\r
+  CLookToRead *p = (CLookToRead *)pp;\r
+  size_t size2 = p->size - p->pos;\r
+  if (size2 == 0 && *size > 0)\r
+  {\r
+    p->pos = 0;\r
+    if (*size > LookToRead_BUF_SIZE)\r
+      *size = LookToRead_BUF_SIZE;\r
+    res = p->realStream->Read(p->realStream, p->buf, size);\r
+    size2 = p->size = *size;\r
+  }\r
+  if (size2 < *size)\r
+    *size = size2;\r
+  *buf = p->buf + p->pos;\r
+  return res;\r
+}\r
+\r
+static SRes LookToRead_Skip(void *pp, size_t offset)\r
+{\r
+  CLookToRead *p = (CLookToRead *)pp;\r
+  p->pos += offset;\r
+  return SZ_OK;\r
+}\r
+\r
+static SRes LookToRead_Read(void *pp, void *buf, size_t *size)\r
+{\r
+  CLookToRead *p = (CLookToRead *)pp;\r
+  size_t rem = p->size - p->pos;\r
+  if (rem == 0)\r
+    return p->realStream->Read(p->realStream, buf, size);\r
+  if (rem > *size)\r
+    rem = *size;\r
+  memcpy(buf, p->buf + p->pos, rem);\r
+  p->pos += rem;\r
+  *size = rem;\r
+  return SZ_OK;\r
+}\r
+\r
+static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin)\r
+{\r
+  CLookToRead *p = (CLookToRead *)pp;\r
+  p->pos = p->size = 0;\r
+  return p->realStream->Seek(p->realStream, pos, origin);\r
+}\r
+\r
+void LookToRead_CreateVTable(CLookToRead *p, int lookahead)\r
+{\r
+  p->s.Look = lookahead ?\r
+      LookToRead_Look_Lookahead :\r
+      LookToRead_Look_Exact;\r
+  p->s.Skip = LookToRead_Skip;\r
+  p->s.Read = LookToRead_Read;\r
+  p->s.Seek = LookToRead_Seek;\r
+}\r
+\r
+void LookToRead_Init(CLookToRead *p)\r
+{\r
+  p->pos = p->size = 0;\r
+}\r
+\r
+static SRes SecToLook_Read(void *pp, void *buf, size_t *size)\r
+{\r
+  CSecToLook *p = (CSecToLook *)pp;\r
+  return LookInStream_LookRead(p->realStream, buf, size);\r
+}\r
+\r
+void SecToLook_CreateVTable(CSecToLook *p)\r
+{\r
+  p->s.Read = SecToLook_Read;\r
+}\r
+\r
+static SRes SecToRead_Read(void *pp, void *buf, size_t *size)\r
+{\r
+  CSecToRead *p = (CSecToRead *)pp;\r
+  return p->realStream->Read(p->realStream, buf, size);\r
+}\r
+\r
+void SecToRead_CreateVTable(CSecToRead *p)\r
+{\r
+  p->s.Read = SecToRead_Read;\r
+}\r
diff --git a/C/7zVersion.h b/C/7zVersion.h
new file mode 100755 (executable)
index 0000000..d4ac470
--- /dev/null
@@ -0,0 +1,7 @@
+#define MY_VER_MAJOR 9\r
+#define MY_VER_MINOR 20\r
+#define MY_VER_BUILD 0\r
+#define MY_VERSION "9.20"\r
+#define MY_DATE "2010-11-18"\r
+#define MY_COPYRIGHT ": Igor Pavlov : Public domain"\r
+#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE\r
diff --git a/C/Aes.c b/C/Aes.c
new file mode 100755 (executable)
index 0000000..c632fda
--- /dev/null
+++ b/C/Aes.c
@@ -0,0 +1,282 @@
+/* Aes.c -- AES encryption / decryption\r
+2009-11-23 : Igor Pavlov : Public domain */\r
+\r
+#include "Aes.h"\r
+#include "CpuArch.h"\r
+\r
+static UInt32 T[256 * 4];\r
+static Byte Sbox[256] = {\r
+  0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,\r
+  0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,\r
+  0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,\r
+  0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,\r
+  0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,\r
+  0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,\r
+  0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,\r
+  0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,\r
+  0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,\r
+  0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,\r
+  0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,\r
+  0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,\r
+  0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,\r
+  0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,\r
+  0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,\r
+  0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};\r
+\r
+void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks);\r
+void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks);\r
+void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks);\r
+\r
+void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);\r
+void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);\r
+void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);\r
+\r
+AES_CODE_FUNC g_AesCbc_Encode;\r
+AES_CODE_FUNC g_AesCbc_Decode;\r
+AES_CODE_FUNC g_AesCtr_Code;\r
+\r
+static UInt32 D[256 * 4];\r
+static Byte InvS[256];\r
+\r
+static Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };\r
+\r
+#define xtime(x) ((((x) << 1) ^ (((x) & 0x80) != 0 ? 0x1B : 0)) & 0xFF)\r
+\r
+#define Ui32(a0, a1, a2, a3) ((UInt32)(a0) | ((UInt32)(a1) << 8) | ((UInt32)(a2) << 16) | ((UInt32)(a3) << 24))\r
+\r
+#define gb0(x) ( (x)          & 0xFF)\r
+#define gb1(x) (((x) >> ( 8)) & 0xFF)\r
+#define gb2(x) (((x) >> (16)) & 0xFF)\r
+#define gb3(x) (((x) >> (24)) & 0xFF)\r
+\r
+void AesGenTables(void)\r
+{\r
+  unsigned i;\r
+  for (i = 0; i < 256; i++)\r
+    InvS[Sbox[i]] = (Byte)i;\r
+  for (i = 0; i < 256; i++)\r
+  {\r
+    {\r
+      UInt32 a1 = Sbox[i];\r
+      UInt32 a2 = xtime(a1);\r
+      UInt32 a3 = a2 ^ a1;\r
+      T[        i] = Ui32(a2, a1, a1, a3);\r
+      T[0x100 + i] = Ui32(a3, a2, a1, a1);\r
+      T[0x200 + i] = Ui32(a1, a3, a2, a1);\r
+      T[0x300 + i] = Ui32(a1, a1, a3, a2);\r
+    }\r
+    {\r
+      UInt32 a1 = InvS[i];\r
+      UInt32 a2 = xtime(a1);\r
+      UInt32 a4 = xtime(a2);\r
+      UInt32 a8 = xtime(a4);\r
+      UInt32 a9 = a8 ^ a1;\r
+      UInt32 aB = a8 ^ a2 ^ a1;\r
+      UInt32 aD = a8 ^ a4 ^ a1;\r
+      UInt32 aE = a8 ^ a4 ^ a2;\r
+      D[        i] = Ui32(aE, a9, aD, aB);\r
+      D[0x100 + i] = Ui32(aB, aE, a9, aD);\r
+      D[0x200 + i] = Ui32(aD, aB, aE, a9);\r
+      D[0x300 + i] = Ui32(a9, aD, aB, aE);\r
+    }\r
+  }\r
+  g_AesCbc_Encode = AesCbc_Encode;\r
+  g_AesCbc_Decode = AesCbc_Decode;\r
+  g_AesCtr_Code = AesCtr_Code;\r
+  #ifdef MY_CPU_X86_OR_AMD64\r
+  if (CPU_Is_Aes_Supported())\r
+  {\r
+    g_AesCbc_Encode = AesCbc_Encode_Intel;\r
+    g_AesCbc_Decode = AesCbc_Decode_Intel;\r
+    g_AesCtr_Code = AesCtr_Code_Intel;\r
+  }\r
+  #endif\r
+}\r
+\r
+#define HT(i, x, s) (T + (x << 8))[gb ## x(s[(i + x) & 3])]\r
+#define HT4(m, i, s, p) m[i] = \\r
+    HT(i, 0, s) ^ \\r
+    HT(i, 1, s) ^ \\r
+    HT(i, 2, s) ^ \\r
+    HT(i, 3, s) ^ w[p + i]\r
+/* such order (2031) in HT16 is for VC6/K8 speed optimization) */\r
+#define HT16(m, s, p) \\r
+    HT4(m, 2, s, p); \\r
+    HT4(m, 0, s, p); \\r
+    HT4(m, 3, s, p); \\r
+    HT4(m, 1, s, p); \\r
+\r
+#define FT(i, x) Sbox[gb ## x(m[(i + x) & 3])]\r
+#define FT4(i) dest[i] = Ui32(FT(i, 0), FT(i, 1), FT(i, 2), FT(i, 3)) ^ w[i];\r
+\r
+#define HD(i, x, s) (D + (x << 8))[gb ## x(s[(i - x) & 3])]\r
+#define HD4(m, i, s, p) m[i] = \\r
+    HD(i, 0, s) ^ \\r
+    HD(i, 1, s) ^ \\r
+    HD(i, 2, s) ^ \\r
+    HD(i, 3, s) ^ w[p + i];\r
+/* such order (0231) in HD16 is for VC6/K8 speed optimization) */\r
+#define HD16(m, s, p) \\r
+    HD4(m, 0, s, p); \\r
+    HD4(m, 2, s, p); \\r
+    HD4(m, 3, s, p); \\r
+    HD4(m, 1, s, p); \\r
+\r
+#define FD(i, x) InvS[gb ## x(m[(i - x) & 3])]\r
+#define FD4(i) dest[i] = Ui32(FD(i, 0), FD(i, 1), FD(i, 2), FD(i, 3)) ^ w[i];\r
+\r
+void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *w, const Byte *key, unsigned keySize)\r
+{\r
+  unsigned i, wSize;\r
+  wSize = keySize + 28;\r
+  keySize /= 4;\r
+  w[0] = ((UInt32)keySize / 2) + 3;\r
+  w += 4;\r
+\r
+  for (i = 0; i < keySize; i++, key += 4)\r
+    w[i] = GetUi32(key);\r
+\r
+  for (; i < wSize; i++)\r
+  {\r
+    UInt32 t = w[i - 1];\r
+    unsigned rem = i % keySize;\r
+    if (rem == 0)\r
+      t = Ui32(Sbox[gb1(t)] ^ Rcon[i / keySize], Sbox[gb2(t)], Sbox[gb3(t)], Sbox[gb0(t)]);\r
+    else if (keySize > 6 && rem == 4)\r
+      t = Ui32(Sbox[gb0(t)], Sbox[gb1(t)], Sbox[gb2(t)], Sbox[gb3(t)]);\r
+    w[i] = w[i - keySize] ^ t;\r
+  }\r
+}\r
+\r
+void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *w, const Byte *key, unsigned keySize)\r
+{\r
+  unsigned i, num;\r
+  Aes_SetKey_Enc(w, key, keySize);\r
+  num = keySize + 20;\r
+  w += 8;\r
+  for (i = 0; i < num; i++)\r
+  {\r
+    UInt32 r = w[i];\r
+    w[i] =\r
+      D[        Sbox[gb0(r)]] ^\r
+      D[0x100 + Sbox[gb1(r)]] ^\r
+      D[0x200 + Sbox[gb2(r)]] ^\r
+      D[0x300 + Sbox[gb3(r)]];\r
+  }\r
+}\r
+\r
+/* Aes_Encode and Aes_Decode functions work with little-endian words.\r
+  src and dest are pointers to 4 UInt32 words.\r
+  arc and dest can point to same block */\r
+\r
+static void Aes_Encode(const UInt32 *w, UInt32 *dest, const UInt32 *src)\r
+{\r
+  UInt32 s[4];\r
+  UInt32 m[4];\r
+  UInt32 numRounds2 = w[0];\r
+  w += 4;\r
+  s[0] = src[0] ^ w[0];\r
+  s[1] = src[1] ^ w[1];\r
+  s[2] = src[2] ^ w[2];\r
+  s[3] = src[3] ^ w[3];\r
+  w += 4;\r
+  for (;;)\r
+  {\r
+    HT16(m, s, 0);\r
+    if (--numRounds2 == 0)\r
+      break;\r
+    HT16(s, m, 4);\r
+    w += 8;\r
+  }\r
+  w += 4;\r
+  FT4(0); FT4(1); FT4(2); FT4(3);\r
+}\r
+\r
+static void Aes_Decode(const UInt32 *w, UInt32 *dest, const UInt32 *src)\r
+{\r
+  UInt32 s[4];\r
+  UInt32 m[4];\r
+  UInt32 numRounds2 = w[0];\r
+  w += 4 + numRounds2 * 8;\r
+  s[0] = src[0] ^ w[0];\r
+  s[1] = src[1] ^ w[1];\r
+  s[2] = src[2] ^ w[2];\r
+  s[3] = src[3] ^ w[3];\r
+  for (;;)\r
+  {\r
+    w -= 8;\r
+    HD16(m, s, 4);\r
+    if (--numRounds2 == 0)\r
+      break;\r
+    HD16(s, m, 0);\r
+  }\r
+  FD4(0); FD4(1); FD4(2); FD4(3);\r
+}\r
+\r
+void AesCbc_Init(UInt32 *p, const Byte *iv)\r
+{\r
+  unsigned i;\r
+  for (i = 0; i < 4; i++)\r
+    p[i] = GetUi32(iv + i * 4);\r
+}\r
+\r
+void MY_FAST_CALL AesCbc_Encode(UInt32 *p, Byte *data, size_t numBlocks)\r
+{\r
+  for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE)\r
+  {\r
+    p[0] ^= GetUi32(data);\r
+    p[1] ^= GetUi32(data + 4);\r
+    p[2] ^= GetUi32(data + 8);\r
+    p[3] ^= GetUi32(data + 12);\r
+    \r
+    Aes_Encode(p + 4, p, p);\r
+    \r
+    SetUi32(data,      p[0]);\r
+    SetUi32(data + 4,  p[1]);\r
+    SetUi32(data + 8,  p[2]);\r
+    SetUi32(data + 12, p[3]);\r
+  }\r
+}\r
+\r
+void MY_FAST_CALL AesCbc_Decode(UInt32 *p, Byte *data, size_t numBlocks)\r
+{\r
+  UInt32 in[4], out[4];\r
+  for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE)\r
+  {\r
+    in[0] = GetUi32(data);\r
+    in[1] = GetUi32(data + 4);\r
+    in[2] = GetUi32(data + 8);\r
+    in[3] = GetUi32(data + 12);\r
+\r
+    Aes_Decode(p + 4, out, in);\r
+\r
+    SetUi32(data,      p[0] ^ out[0]);\r
+    SetUi32(data + 4,  p[1] ^ out[1]);\r
+    SetUi32(data + 8,  p[2] ^ out[2]);\r
+    SetUi32(data + 12, p[3] ^ out[3]);\r
+    \r
+    p[0] = in[0];\r
+    p[1] = in[1];\r
+    p[2] = in[2];\r
+    p[3] = in[3];\r
+  }\r
+}\r
+\r
+void MY_FAST_CALL AesCtr_Code(UInt32 *p, Byte *data, size_t numBlocks)\r
+{\r
+  for (; numBlocks != 0; numBlocks--)\r
+  {\r
+    UInt32 temp[4];\r
+    Byte buf[16];\r
+    int i;\r
+    if (++p[0] == 0)\r
+      p[1]++;\r
+    Aes_Encode(p + 4, temp, p);\r
+    SetUi32(buf,      temp[0]);\r
+    SetUi32(buf + 4,  temp[1]);\r
+    SetUi32(buf + 8,  temp[2]);\r
+    SetUi32(buf + 12, temp[3]);\r
+    for (i = 0; i < 16; i++)\r
+      *data++ ^= buf[i];\r
+  }\r
+}\r
diff --git a/C/Aes.h b/C/Aes.h
new file mode 100755 (executable)
index 0000000..7c3c3d3
--- /dev/null
+++ b/C/Aes.h
@@ -0,0 +1,38 @@
+/* Aes.h -- AES encryption / decryption\r
+2009-11-23 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __AES_H\r
+#define __AES_H\r
+\r
+#include "Types.h"\r
+\r
+EXTERN_C_BEGIN\r
+\r
+#define AES_BLOCK_SIZE 16\r
+\r
+/* Call AesGenTables one time before other AES functions */\r
+void AesGenTables(void);\r
+\r
+/* UInt32 pointers must be 16-byte aligned */\r
+\r
+/* 16-byte (4 * 32-bit words) blocks: 1 (IV) + 1 (keyMode) + 15 (AES-256 roundKeys) */\r
+#define AES_NUM_IVMRK_WORDS ((1 + 1 + 15) * 4)\r
+\r
+/* aes - 16-byte aligned pointer to keyMode+roundKeys sequence */\r
+/* keySize = 16 or 24 or 32 (bytes) */\r
+typedef void (MY_FAST_CALL *AES_SET_KEY_FUNC)(UInt32 *aes, const Byte *key, unsigned keySize);\r
+void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *aes, const Byte *key, unsigned keySize);\r
+void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *aes, const Byte *key, unsigned keySize);\r
+\r
+/* ivAes - 16-byte aligned pointer to iv+keyMode+roundKeys sequence: UInt32[AES_NUM_IVMRK_WORDS] */\r
+void AesCbc_Init(UInt32 *ivAes, const Byte *iv); /* iv size is AES_BLOCK_SIZE */\r
+/* data - 16-byte aligned pointer to data */\r
+/* numBlocks - the number of 16-byte blocks in data array */\r
+typedef void (MY_FAST_CALL *AES_CODE_FUNC)(UInt32 *ivAes, Byte *data, size_t numBlocks);\r
+extern AES_CODE_FUNC g_AesCbc_Encode;\r
+extern AES_CODE_FUNC g_AesCbc_Decode;\r
+extern AES_CODE_FUNC g_AesCtr_Code;\r
+\r
+EXTERN_C_END\r
+\r
+#endif\r
diff --git a/C/AesOpt.c b/C/AesOpt.c
new file mode 100755 (executable)
index 0000000..452e6ff
--- /dev/null
@@ -0,0 +1,182 @@
+/* AesOpt.c -- Intel's AES\r
+2009-11-23 : Igor Pavlov : Public domain */\r
+\r
+#include "CpuArch.h"\r
+\r
+#ifdef MY_CPU_X86_OR_AMD64\r
+#if _MSC_VER >= 1500\r
+#define USE_INTEL_AES\r
+#endif\r
+#endif\r
+\r
+#ifdef USE_INTEL_AES\r
+\r
+#include <wmmintrin.h>\r
+\r
+void MY_FAST_CALL AesCbc_Encode_Intel(__m128i *p, __m128i *data, size_t numBlocks)\r
+{\r
+  __m128i m = *p;\r
+  for (; numBlocks != 0; numBlocks--, data++)\r
+  {\r
+    UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;\r
+    const __m128i *w = p + 3;\r
+    m = _mm_xor_si128(m, *data);\r
+    m = _mm_xor_si128(m, p[2]);\r
+    do\r
+    {\r
+      m = _mm_aesenc_si128(m, w[0]);\r
+      m = _mm_aesenc_si128(m, w[1]);\r
+      w += 2;\r
+    }\r
+    while (--numRounds2 != 0);\r
+    m = _mm_aesenc_si128(m, w[0]);\r
+    m = _mm_aesenclast_si128(m, w[1]);\r
+    *data = m;\r
+  }\r
+  *p = m;\r
+}\r
+\r
+#define NUM_WAYS 3\r
+\r
+#define AES_OP_W(op, n) { \\r
+    const __m128i t = w[n]; \\r
+    m0 = op(m0, t); \\r
+    m1 = op(m1, t); \\r
+    m2 = op(m2, t); \\r
+    }\r
+\r
+#define AES_DEC(n) AES_OP_W(_mm_aesdec_si128, n)\r
+#define AES_DEC_LAST(n) AES_OP_W(_mm_aesdeclast_si128, n)\r
+#define AES_ENC(n) AES_OP_W(_mm_aesenc_si128, n)\r
+#define AES_ENC_LAST(n) AES_OP_W(_mm_aesenclast_si128, n)\r
+\r
+void MY_FAST_CALL AesCbc_Decode_Intel(__m128i *p, __m128i *data, size_t numBlocks)\r
+{\r
+  __m128i iv = *p;\r
+  for (; numBlocks >= NUM_WAYS; numBlocks -= NUM_WAYS, data += NUM_WAYS)\r
+  {\r
+    UInt32 numRounds2 = *(const UInt32 *)(p + 1);\r
+    const __m128i *w = p + numRounds2 * 2;\r
+    __m128i m0, m1, m2;\r
+    {\r
+      const __m128i t = w[2];\r
+      m0 = _mm_xor_si128(t, data[0]);\r
+      m1 = _mm_xor_si128(t, data[1]);\r
+      m2 = _mm_xor_si128(t, data[2]);\r
+    }\r
+    numRounds2--;\r
+    do\r
+    {\r
+      AES_DEC(1)\r
+      AES_DEC(0)\r
+      w -= 2;\r
+    }\r
+    while (--numRounds2 != 0);\r
+    AES_DEC(1)\r
+    AES_DEC_LAST(0)\r
+\r
+    {\r
+      __m128i t;\r
+      t = _mm_xor_si128(m0, iv); iv = data[0]; data[0] = t;\r
+      t = _mm_xor_si128(m1, iv); iv = data[1]; data[1] = t;\r
+      t = _mm_xor_si128(m2, iv); iv = data[2]; data[2] = t;\r
+    }\r
+  }\r
+  for (; numBlocks != 0; numBlocks--, data++)\r
+  {\r
+    UInt32 numRounds2 = *(const UInt32 *)(p + 1);\r
+    const __m128i *w = p + numRounds2 * 2;\r
+    __m128i m = _mm_xor_si128(w[2], *data);\r
+    numRounds2--;\r
+    do\r
+    {\r
+      m = _mm_aesdec_si128(m, w[1]);\r
+      m = _mm_aesdec_si128(m, w[0]);\r
+      w -= 2;\r
+    }\r
+    while (--numRounds2 != 0);\r
+    m = _mm_aesdec_si128(m, w[1]);\r
+    m = _mm_aesdeclast_si128(m, w[0]);\r
+\r
+    m = _mm_xor_si128(m, iv);\r
+    iv = *data;\r
+    *data = m;\r
+  }\r
+  *p = iv;\r
+}\r
+\r
+void MY_FAST_CALL AesCtr_Code_Intel(__m128i *p, __m128i *data, size_t numBlocks)\r
+{\r
+  __m128i ctr = *p;\r
+  __m128i one;\r
+  one.m128i_u64[0] = 1;\r
+  one.m128i_u64[1] = 0;\r
+  for (; numBlocks >= NUM_WAYS; numBlocks -= NUM_WAYS, data += NUM_WAYS)\r
+  {\r
+    UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;\r
+    const __m128i *w = p;\r
+    __m128i m0, m1, m2;\r
+    {\r
+      const __m128i t = w[2];\r
+      ctr = _mm_add_epi64(ctr, one); m0 = _mm_xor_si128(ctr, t);\r
+      ctr = _mm_add_epi64(ctr, one); m1 = _mm_xor_si128(ctr, t);\r
+      ctr = _mm_add_epi64(ctr, one); m2 = _mm_xor_si128(ctr, t);\r
+    }\r
+    w += 3;\r
+    do\r
+    {\r
+      AES_ENC(0)\r
+      AES_ENC(1)\r
+      w += 2;\r
+    }\r
+    while (--numRounds2 != 0);\r
+    AES_ENC(0)\r
+    AES_ENC_LAST(1)\r
+    data[0] = _mm_xor_si128(data[0], m0);\r
+    data[1] = _mm_xor_si128(data[1], m1);\r
+    data[2] = _mm_xor_si128(data[2], m2);\r
+  }\r
+  for (; numBlocks != 0; numBlocks--, data++)\r
+  {\r
+    UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;\r
+    const __m128i *w = p;\r
+    __m128i m;\r
+    ctr = _mm_add_epi64(ctr, one);\r
+    m = _mm_xor_si128(ctr, p[2]);\r
+    w += 3;\r
+    do\r
+    {\r
+      m = _mm_aesenc_si128(m, w[0]);\r
+      m = _mm_aesenc_si128(m, w[1]);\r
+      w += 2;\r
+    }\r
+    while (--numRounds2 != 0);\r
+    m = _mm_aesenc_si128(m, w[0]);\r
+    m = _mm_aesenclast_si128(m, w[1]);\r
+    *data = _mm_xor_si128(*data, m);\r
+  }\r
+  *p = ctr;\r
+}\r
+\r
+#else\r
+\r
+void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks);\r
+void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks);\r
+void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks);\r
+\r
+void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *p, Byte *data, size_t numBlocks)\r
+{\r
+  AesCbc_Encode(p, data, numBlocks);\r
+}\r
+\r
+void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *p, Byte *data, size_t numBlocks)\r
+{\r
+  AesCbc_Decode(p, data, numBlocks);\r
+}\r
+\r
+void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *p, Byte *data, size_t numBlocks)\r
+{\r
+  AesCtr_Code(p, data, numBlocks);\r
+}\r
+\r
+#endif\r
diff --git a/C/Alloc.c b/C/Alloc.c
new file mode 100755 (executable)
index 0000000..bb24a77
--- /dev/null
+++ b/C/Alloc.c
@@ -0,0 +1,127 @@
+/* Alloc.c -- Memory allocation functions\r
+2008-09-24\r
+Igor Pavlov\r
+Public domain */\r
+\r
+#ifdef _WIN32\r
+#include <windows.h>\r
+#endif\r
+#include <stdlib.h>\r
+\r
+#include "Alloc.h"\r
+\r
+/* #define _SZ_ALLOC_DEBUG */\r
+\r
+/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */\r
+#ifdef _SZ_ALLOC_DEBUG\r
+#include <stdio.h>\r
+int g_allocCount = 0;\r
+int g_allocCountMid = 0;\r
+int g_allocCountBig = 0;\r
+#endif\r
+\r
+void *MyAlloc(size_t size)\r
+{\r
+  if (size == 0)\r
+    return 0;\r
+  #ifdef _SZ_ALLOC_DEBUG\r
+  {\r
+    void *p = malloc(size);\r
+    fprintf(stderr, "\nAlloc %10d bytes, count = %10d,  addr = %8X", size, g_allocCount++, (unsigned)p);\r
+    return p;\r
+  }\r
+  #else\r
+  return malloc(size);\r
+  #endif\r
+}\r
+\r
+void MyFree(void *address)\r
+{\r
+  #ifdef _SZ_ALLOC_DEBUG\r
+  if (address != 0)\r
+    fprintf(stderr, "\nFree; count = %10d,  addr = %8X", --g_allocCount, (unsigned)address);\r
+  #endif\r
+  free(address);\r
+}\r
+\r
+#ifdef _WIN32\r
+\r
+void *MidAlloc(size_t size)\r
+{\r
+  if (size == 0)\r
+    return 0;\r
+  #ifdef _SZ_ALLOC_DEBUG\r
+  fprintf(stderr, "\nAlloc_Mid %10d bytes;  count = %10d", size, g_allocCountMid++);\r
+  #endif\r
+  return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);\r
+}\r
+\r
+void MidFree(void *address)\r
+{\r
+  #ifdef _SZ_ALLOC_DEBUG\r
+  if (address != 0)\r
+    fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid);\r
+  #endif\r
+  if (address == 0)\r
+    return;\r
+  VirtualFree(address, 0, MEM_RELEASE);\r
+}\r
+\r
+#ifndef MEM_LARGE_PAGES\r
+#undef _7ZIP_LARGE_PAGES\r
+#endif\r
+\r
+#ifdef _7ZIP_LARGE_PAGES\r
+SIZE_T g_LargePageSize = 0;\r
+typedef SIZE_T (WINAPI *GetLargePageMinimumP)();\r
+#endif\r
+\r
+void SetLargePageSize()\r
+{\r
+  #ifdef _7ZIP_LARGE_PAGES\r
+  SIZE_T size = 0;\r
+  GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP)\r
+        GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum");\r
+  if (largePageMinimum == 0)\r
+    return;\r
+  size = largePageMinimum();\r
+  if (size == 0 || (size & (size - 1)) != 0)\r
+    return;\r
+  g_LargePageSize = size;\r
+  #endif\r
+}\r
+\r
+\r
+void *BigAlloc(size_t size)\r
+{\r
+  if (size == 0)\r
+    return 0;\r
+  #ifdef _SZ_ALLOC_DEBUG\r
+  fprintf(stderr, "\nAlloc_Big %10d bytes;  count = %10d", size, g_allocCountBig++);\r
+  #endif\r
+  \r
+  #ifdef _7ZIP_LARGE_PAGES\r
+  if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18))\r
+  {\r
+    void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)),\r
+        MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);\r
+    if (res != 0)\r
+      return res;\r
+  }\r
+  #endif\r
+  return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);\r
+}\r
+\r
+void BigFree(void *address)\r
+{\r
+  #ifdef _SZ_ALLOC_DEBUG\r
+  if (address != 0)\r
+    fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig);\r
+  #endif\r
+  \r
+  if (address == 0)\r
+    return;\r
+  VirtualFree(address, 0, MEM_RELEASE);\r
+}\r
+\r
+#endif\r
diff --git a/C/Alloc.h b/C/Alloc.h
new file mode 100755 (executable)
index 0000000..6b3f034
--- /dev/null
+++ b/C/Alloc.h
@@ -0,0 +1,38 @@
+/* Alloc.h -- Memory allocation functions\r
+2009-02-07 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __COMMON_ALLOC_H\r
+#define __COMMON_ALLOC_H\r
+\r
+#include <stddef.h>\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+void *MyAlloc(size_t size);\r
+void MyFree(void *address);\r
+\r
+#ifdef _WIN32\r
+\r
+void SetLargePageSize();\r
+\r
+void *MidAlloc(size_t size);\r
+void MidFree(void *address);\r
+void *BigAlloc(size_t size);\r
+void BigFree(void *address);\r
+\r
+#else\r
+\r
+#define MidAlloc(size) MyAlloc(size)\r
+#define MidFree(address) MyFree(address)\r
+#define BigAlloc(size) MyAlloc(size)\r
+#define BigFree(address) MyFree(address)\r
+\r
+#endif\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/C/Bcj2.c b/C/Bcj2.c
new file mode 100755 (executable)
index 0000000..474bdd4
--- /dev/null
+++ b/C/Bcj2.c
@@ -0,0 +1,132 @@
+/* Bcj2.c -- Converter for x86 code (BCJ2)\r
+2008-10-04 : Igor Pavlov : Public domain */\r
+\r
+#include "Bcj2.h"\r
+\r
+#ifdef _LZMA_PROB32\r
+#define CProb UInt32\r
+#else\r
+#define CProb UInt16\r
+#endif\r
+\r
+#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)\r
+#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))\r
+\r
+#define kNumTopBits 24\r
+#define kTopValue ((UInt32)1 << kNumTopBits)\r
+\r
+#define kNumBitModelTotalBits 11\r
+#define kBitModelTotal (1 << kNumBitModelTotalBits)\r
+#define kNumMoveBits 5\r
+\r
+#define RC_READ_BYTE (*buffer++)\r
+#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }\r
+#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \\r
+  { int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }}\r
+\r
+#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; }\r
+\r
+#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)\r
+#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE;\r
+#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE;\r
+\r
+int Bcj2_Decode(\r
+    const Byte *buf0, SizeT size0,\r
+    const Byte *buf1, SizeT size1,\r
+    const Byte *buf2, SizeT size2,\r
+    const Byte *buf3, SizeT size3,\r
+    Byte *outBuf, SizeT outSize)\r
+{\r
+  CProb p[256 + 2];\r
+  SizeT inPos = 0, outPos = 0;\r
+\r
+  const Byte *buffer, *bufferLim;\r
+  UInt32 range, code;\r
+  Byte prevByte = 0;\r
+\r
+  unsigned int i;\r
+  for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)\r
+    p[i] = kBitModelTotal >> 1;\r
+\r
+  buffer = buf3;\r
+  bufferLim = buffer + size3;\r
+  RC_INIT2\r
+\r
+  if (outSize == 0)\r
+    return SZ_OK;\r
+\r
+  for (;;)\r
+  {\r
+    Byte b;\r
+    CProb *prob;\r
+    UInt32 bound;\r
+    UInt32 ttt;\r
+\r
+    SizeT limit = size0 - inPos;\r
+    if (outSize - outPos < limit)\r
+      limit = outSize - outPos;\r
+    while (limit != 0)\r
+    {\r
+      Byte b = buf0[inPos];\r
+      outBuf[outPos++] = b;\r
+      if (IsJ(prevByte, b))\r
+        break;\r
+      inPos++;\r
+      prevByte = b;\r
+      limit--;\r
+    }\r
+\r
+    if (limit == 0 || outPos == outSize)\r
+      break;\r
+\r
+    b = buf0[inPos++];\r
+\r
+    if (b == 0xE8)\r
+      prob = p + prevByte;\r
+    else if (b == 0xE9)\r
+      prob = p + 256;\r
+    else\r
+      prob = p + 257;\r
+\r
+    IF_BIT_0(prob)\r
+    {\r
+      UPDATE_0(prob)\r
+      prevByte = b;\r
+    }\r
+    else\r
+    {\r
+      UInt32 dest;\r
+      const Byte *v;\r
+      UPDATE_1(prob)\r
+      if (b == 0xE8)\r
+      {\r
+        v = buf1;\r
+        if (size1 < 4)\r
+          return SZ_ERROR_DATA;\r
+        buf1 += 4;\r
+        size1 -= 4;\r
+      }\r
+      else\r
+      {\r
+        v = buf2;\r
+        if (size2 < 4)\r
+          return SZ_ERROR_DATA;\r
+        buf2 += 4;\r
+        size2 -= 4;\r
+      }\r
+      dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) |\r
+          ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4);\r
+      outBuf[outPos++] = (Byte)dest;\r
+      if (outPos == outSize)\r
+        break;\r
+      outBuf[outPos++] = (Byte)(dest >> 8);\r
+      if (outPos == outSize)\r
+        break;\r
+      outBuf[outPos++] = (Byte)(dest >> 16);\r
+      if (outPos == outSize)\r
+        break;\r
+      outBuf[outPos++] = prevByte = (Byte)(dest >> 24);\r
+    }\r
+  }\r
+  return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;\r
+}\r
diff --git a/C/Bcj2.h b/C/Bcj2.h
new file mode 100755 (executable)
index 0000000..d9d857b
--- /dev/null
+++ b/C/Bcj2.h
@@ -0,0 +1,38 @@
+/* Bcj2.h -- Converter for x86 code (BCJ2)\r
+2009-02-07 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __BCJ2_H\r
+#define __BCJ2_H\r
+\r
+#include "Types.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/*\r
+Conditions:\r
+  outSize <= FullOutputSize,\r
+  where FullOutputSize is full size of output stream of x86_2 filter.\r
+\r
+If buf0 overlaps outBuf, there are two required conditions:\r
+  1) (buf0 >= outBuf)\r
+  2) (buf0 + size0 >= outBuf + FullOutputSize).\r
+\r
+Returns:\r
+  SZ_OK\r
+  SZ_ERROR_DATA - Data error\r
+*/\r
+\r
+int Bcj2_Decode(\r
+    const Byte *buf0, SizeT size0,\r
+    const Byte *buf1, SizeT size1,\r
+    const Byte *buf2, SizeT size2,\r
+    const Byte *buf3, SizeT size3,\r
+    Byte *outBuf, SizeT outSize);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/C/Bra.c b/C/Bra.c
new file mode 100755 (executable)
index 0000000..2a0f147
--- /dev/null
+++ b/C/Bra.c
@@ -0,0 +1,133 @@
+/* Bra.c -- Converters for RISC code\r
+2010-04-16 : Igor Pavlov : Public domain */\r
+\r
+#include "Bra.h"\r
+\r
+SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)\r
+{\r
+  SizeT i;\r
+  if (size < 4)\r
+    return 0;\r
+  size -= 4;\r
+  ip += 8;\r
+  for (i = 0; i <= size; i += 4)\r
+  {\r
+    if (data[i + 3] == 0xEB)\r
+    {\r
+      UInt32 dest;\r
+      UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]);\r
+      src <<= 2;\r
+      if (encoding)\r
+        dest = ip + (UInt32)i + src;\r
+      else\r
+        dest = src - (ip + (UInt32)i);\r
+      dest >>= 2;\r
+      data[i + 2] = (Byte)(dest >> 16);\r
+      data[i + 1] = (Byte)(dest >> 8);\r
+      data[i + 0] = (Byte)dest;\r
+    }\r
+  }\r
+  return i;\r
+}\r
+\r
+SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)\r
+{\r
+  SizeT i;\r
+  if (size < 4)\r
+    return 0;\r
+  size -= 4;\r
+  ip += 4;\r
+  for (i = 0; i <= size; i += 2)\r
+  {\r
+    if ((data[i + 1] & 0xF8) == 0xF0 &&\r
+        (data[i + 3] & 0xF8) == 0xF8)\r
+    {\r
+      UInt32 dest;\r
+      UInt32 src =\r
+        (((UInt32)data[i + 1] & 0x7) << 19) |\r
+        ((UInt32)data[i + 0] << 11) |\r
+        (((UInt32)data[i + 3] & 0x7) << 8) |\r
+        (data[i + 2]);\r
+      \r
+      src <<= 1;\r
+      if (encoding)\r
+        dest = ip + (UInt32)i + src;\r
+      else\r
+        dest = src - (ip + (UInt32)i);\r
+      dest >>= 1;\r
+      \r
+      data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7));\r
+      data[i + 0] = (Byte)(dest >> 11);\r
+      data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7));\r
+      data[i + 2] = (Byte)dest;\r
+      i += 2;\r
+    }\r
+  }\r
+  return i;\r
+}\r
+\r
+SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)\r
+{\r
+  SizeT i;\r
+  if (size < 4)\r
+    return 0;\r
+  size -= 4;\r
+  for (i = 0; i <= size; i += 4)\r
+  {\r
+    if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1)\r
+    {\r
+      UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) |\r
+        ((UInt32)data[i + 1] << 16) |\r
+        ((UInt32)data[i + 2] << 8) |\r
+        ((UInt32)data[i + 3] & (~3));\r
+      \r
+      UInt32 dest;\r
+      if (encoding)\r
+        dest = ip + (UInt32)i + src;\r
+      else\r
+        dest = src - (ip + (UInt32)i);\r
+      data[i + 0] = (Byte)(0x48 | ((dest >> 24) &  0x3));\r
+      data[i + 1] = (Byte)(dest >> 16);\r
+      data[i + 2] = (Byte)(dest >> 8);\r
+      data[i + 3] &= 0x3;\r
+      data[i + 3] |= dest;\r
+    }\r
+  }\r
+  return i;\r
+}\r
+\r
+SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)\r
+{\r
+  UInt32 i;\r
+  if (size < 4)\r
+    return 0;\r
+  size -= 4;\r
+  for (i = 0; i <= size; i += 4)\r
+  {\r
+    if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) ||\r
+        (data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0))\r
+    {\r
+      UInt32 src =\r
+        ((UInt32)data[i + 0] << 24) |\r
+        ((UInt32)data[i + 1] << 16) |\r
+        ((UInt32)data[i + 2] << 8) |\r
+        ((UInt32)data[i + 3]);\r
+      UInt32 dest;\r
+      \r
+      src <<= 2;\r
+      if (encoding)\r
+        dest = ip + i + src;\r
+      else\r
+        dest = src - (ip + i);\r
+      dest >>= 2;\r
+      \r
+      dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000;\r
+\r
+      data[i + 0] = (Byte)(dest >> 24);\r
+      data[i + 1] = (Byte)(dest >> 16);\r
+      data[i + 2] = (Byte)(dest >> 8);\r
+      data[i + 3] = (Byte)dest;\r
+    }\r
+  }\r
+  return i;\r
+}\r
diff --git a/C/Bra.h b/C/Bra.h
new file mode 100755 (executable)
index 0000000..9c91e33
--- /dev/null
+++ b/C/Bra.h
@@ -0,0 +1,68 @@
+/* Bra.h -- Branch converters for executables\r
+2009-02-07 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __BRA_H\r
+#define __BRA_H\r
+\r
+#include "Types.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/*\r
+These functions convert relative addresses to absolute addresses\r
+in CALL instructions to increase the compression ratio.\r
+  \r
+  In:\r
+    data     - data buffer\r
+    size     - size of data\r
+    ip       - current virtual Instruction Pinter (IP) value\r
+    state    - state variable for x86 converter\r
+    encoding - 0 (for decoding), 1 (for encoding)\r
+  \r
+  Out:\r
+    state    - state variable for x86 converter\r
+\r
+  Returns:\r
+    The number of processed bytes. If you call these functions with multiple calls,\r
+    you must start next call with first byte after block of processed bytes.\r
+  \r
+  Type   Endian  Alignment  LookAhead\r
+  \r
+  x86    little      1          4\r
+  ARMT   little      2          2\r
+  ARM    little      4          0\r
+  PPC     big        4          0\r
+  SPARC   big        4          0\r
+  IA64   little     16          0\r
+\r
+  size must be >= Alignment + LookAhead, if it's not last block.\r
+  If (size < Alignment + LookAhead), converter returns 0.\r
+\r
+  Example:\r
+\r
+    UInt32 ip = 0;\r
+    for ()\r
+    {\r
+      ; size must be >= Alignment + LookAhead, if it's not last block\r
+      SizeT processed = Convert(data, size, ip, 1);\r
+      data += processed;\r
+      size -= processed;\r
+      ip += processed;\r
+    }\r
+*/\r
+\r
+#define x86_Convert_Init(state) { state = 0; }\r
+SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding);\r
+SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);\r
+SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);\r
+SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);\r
+SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);\r
+SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/C/Bra86.c b/C/Bra86.c
new file mode 100755 (executable)
index 0000000..93566cb
--- /dev/null
+++ b/C/Bra86.c
@@ -0,0 +1,85 @@
+/* Bra86.c -- Converter for x86 code (BCJ)\r
+2008-10-04 : Igor Pavlov : Public domain */\r
+\r
+#include "Bra.h"\r
+\r
+#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)\r
+\r
+const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};\r
+const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};\r
+\r
+SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)\r
+{\r
+  SizeT bufferPos = 0, prevPosT;\r
+  UInt32 prevMask = *state & 0x7;\r
+  if (size < 5)\r
+    return 0;\r
+  ip += 5;\r
+  prevPosT = (SizeT)0 - 1;\r
+\r
+  for (;;)\r
+  {\r
+    Byte *p = data + bufferPos;\r
+    Byte *limit = data + size - 4;\r
+    for (; p < limit; p++)\r
+      if ((*p & 0xFE) == 0xE8)\r
+        break;\r
+    bufferPos = (SizeT)(p - data);\r
+    if (p >= limit)\r
+      break;\r
+    prevPosT = bufferPos - prevPosT;\r
+    if (prevPosT > 3)\r
+      prevMask = 0;\r
+    else\r
+    {\r
+      prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;\r
+      if (prevMask != 0)\r
+      {\r
+        Byte b = p[4 - kMaskToBitNumber[prevMask]];\r
+        if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b))\r
+        {\r
+          prevPosT = bufferPos;\r
+          prevMask = ((prevMask << 1) & 0x7) | 1;\r
+          bufferPos++;\r
+          continue;\r
+        }\r
+      }\r
+    }\r
+    prevPosT = bufferPos;\r
+\r
+    if (Test86MSByte(p[4]))\r
+    {\r
+      UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);\r
+      UInt32 dest;\r
+      for (;;)\r
+      {\r
+        Byte b;\r
+        int index;\r
+        if (encoding)\r
+          dest = (ip + (UInt32)bufferPos) + src;\r
+        else\r
+          dest = src - (ip + (UInt32)bufferPos);\r
+        if (prevMask == 0)\r
+          break;\r
+        index = kMaskToBitNumber[prevMask] * 8;\r
+        b = (Byte)(dest >> (24 - index));\r
+        if (!Test86MSByte(b))\r
+          break;\r
+        src = dest ^ ((1 << (32 - index)) - 1);\r
+      }\r
+      p[4] = (Byte)(~(((dest >> 24) & 1) - 1));\r
+      p[3] = (Byte)(dest >> 16);\r
+      p[2] = (Byte)(dest >> 8);\r
+      p[1] = (Byte)dest;\r
+      bufferPos += 5;\r
+    }\r
+    else\r
+    {\r
+      prevMask = ((prevMask << 1) & 0x7) | 1;\r
+      bufferPos++;\r
+    }\r
+  }\r
+  prevPosT = bufferPos - prevPosT;\r
+  *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));\r
+  return bufferPos;\r
+}\r
diff --git a/C/BraIA64.c b/C/BraIA64.c
new file mode 100755 (executable)
index 0000000..f359f16
--- /dev/null
@@ -0,0 +1,67 @@
+/* BraIA64.c -- Converter for IA-64 code\r
+2008-10-04 : Igor Pavlov : Public domain */\r
+\r
+#include "Bra.h"\r
+\r
+static const Byte kBranchTable[32] =\r
+{\r
+  0, 0, 0, 0, 0, 0, 0, 0,\r
+  0, 0, 0, 0, 0, 0, 0, 0,\r
+  4, 4, 6, 6, 0, 0, 7, 7,\r
+  4, 4, 0, 0, 4, 4, 0, 0\r
+};\r
+\r
+SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)\r
+{\r
+  SizeT i;\r
+  if (size < 16)\r
+    return 0;\r
+  size -= 16;\r
+  for (i = 0; i <= size; i += 16)\r
+  {\r
+    UInt32 instrTemplate = data[i] & 0x1F;\r
+    UInt32 mask = kBranchTable[instrTemplate];\r
+    UInt32 bitPos = 5;\r
+    int slot;\r
+    for (slot = 0; slot < 3; slot++, bitPos += 41)\r
+    {\r
+      UInt32 bytePos, bitRes;\r
+      UInt64 instruction, instNorm;\r
+      int j;\r
+      if (((mask >> slot) & 1) == 0)\r
+        continue;\r
+      bytePos = (bitPos >> 3);\r
+      bitRes = bitPos & 0x7;\r
+      instruction = 0;\r
+      for (j = 0; j < 6; j++)\r
+        instruction += (UInt64)data[i + j + bytePos] << (8 * j);\r
+\r
+      instNorm = instruction >> bitRes;\r
+      if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0)\r
+      {\r
+        UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF);\r
+        UInt32 dest;\r
+        src |= ((UInt32)(instNorm >> 36) & 1) << 20;\r
+        \r
+        src <<= 4;\r
+        \r
+        if (encoding)\r
+          dest = ip + (UInt32)i + src;\r
+        else\r
+          dest = src - (ip + (UInt32)i);\r
+        \r
+        dest >>= 4;\r
+        \r
+        instNorm &= ~((UInt64)(0x8FFFFF) << 13);\r
+        instNorm |= ((UInt64)(dest & 0xFFFFF) << 13);\r
+        instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20));\r
+        \r
+        instruction &= (1 << bitRes) - 1;\r
+        instruction |= (instNorm << bitRes);\r
+        for (j = 0; j < 6; j++)\r
+          data[i + j + bytePos] = (Byte)(instruction >> (8 * j));\r
+      }\r
+    }\r
+  }\r
+  return i;\r
+}\r
diff --git a/C/BwtSort.c b/C/BwtSort.c
new file mode 100755 (executable)
index 0000000..d6b545e
--- /dev/null
@@ -0,0 +1,516 @@
+/* BwtSort.c -- BWT block sorting\r
+2008-08-17\r
+Igor Pavlov\r
+Public domain */\r
+\r
+#include "BwtSort.h"\r
+#include "Sort.h"\r
+\r
+/* #define BLOCK_SORT_USE_HEAP_SORT */\r
+\r
+#define NO_INLINE MY_FAST_CALL\r
+\r
+/* Don't change it !!! */\r
+#define kNumHashBytes 2\r
+#define kNumHashValues (1 << (kNumHashBytes * 8))\r
+\r
+/* kNumRefBitsMax must be < (kNumHashBytes * 8) = 16 */\r
+#define kNumRefBitsMax 12\r
+\r
+#define BS_TEMP_SIZE kNumHashValues\r
+\r
+#ifdef BLOCK_SORT_EXTERNAL_FLAGS\r
+\r
+/* 32 Flags in UInt32 word */\r
+#define kNumFlagsBits 5\r
+#define kNumFlagsInWord (1 << kNumFlagsBits)\r
+#define kFlagsMask (kNumFlagsInWord - 1)\r
+#define kAllFlags 0xFFFFFFFF\r
+\r
+#else\r
+\r
+#define kNumBitsMax 20\r
+#define kIndexMask ((1 << kNumBitsMax) - 1)\r
+#define kNumExtraBits (32 - kNumBitsMax)\r
+#define kNumExtra0Bits (kNumExtraBits - 2)\r
+#define kNumExtra0Mask ((1 << kNumExtra0Bits) - 1)\r
+\r
+#define SetFinishedGroupSize(p, size) \\r
+  {  *(p) |= ((((size) - 1) & kNumExtra0Mask) << kNumBitsMax); \\r
+    if ((size) > (1 << kNumExtra0Bits)) { \\r
+    *(p) |= 0x40000000;  *((p) + 1) |= ((((size) - 1)>> kNumExtra0Bits) << kNumBitsMax); } } \\r
+\r
+static void SetGroupSize(UInt32 *p, UInt32 size)\r
+{\r
+  if (--size == 0)\r
+    return;\r
+  *p |= 0x80000000 | ((size & kNumExtra0Mask) << kNumBitsMax);\r
+  if (size >= (1 << kNumExtra0Bits))\r
+  {\r
+    *p |= 0x40000000;\r
+    p[1] |= ((size >> kNumExtra0Bits) << kNumBitsMax);\r
+  }\r
+}\r
+\r
+#endif\r
+\r
+/*\r
+SortGroup - is recursive Range-Sort function with HeapSort optimization for small blocks\r
+  "range" is not real range. It's only for optimization.\r
+returns: 1 - if there are groups, 0 - no more groups\r
+*/\r
+\r
+UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 groupOffset, UInt32 groupSize, int NumRefBits, UInt32 *Indices\r
+  #ifndef BLOCK_SORT_USE_HEAP_SORT\r
+  , UInt32 left, UInt32 range\r
+  #endif\r
+  )\r
+{\r
+  UInt32 *ind2 = Indices + groupOffset;\r
+  UInt32 *Groups;\r
+  if (groupSize <= 1)\r
+  {\r
+    /*\r
+    #ifndef BLOCK_SORT_EXTERNAL_FLAGS\r
+    SetFinishedGroupSize(ind2, 1);\r
+    #endif\r
+    */\r
+    return 0;\r
+  }\r
+  Groups = Indices + BlockSize + BS_TEMP_SIZE;\r
+  if (groupSize <= ((UInt32)1 << NumRefBits)\r
+      #ifndef BLOCK_SORT_USE_HEAP_SORT\r
+      && groupSize <= range\r
+      #endif\r
+      )\r
+  {\r
+    UInt32 *temp = Indices + BlockSize;\r
+    UInt32 j;\r
+    UInt32 mask, thereAreGroups, group, cg;\r
+    {\r
+      UInt32 gPrev;\r
+      UInt32 gRes = 0;\r
+      {\r
+        UInt32 sp = ind2[0] + NumSortedBytes;\r
+        if (sp >= BlockSize) sp -= BlockSize;\r
+        gPrev = Groups[sp];\r
+        temp[0] = (gPrev << NumRefBits);\r
+      }\r
+      \r
+      for (j = 1; j < groupSize; j++)\r
+      {\r
+        UInt32 sp = ind2[j] + NumSortedBytes;\r
+        UInt32 g;\r
+        if (sp >= BlockSize) sp -= BlockSize;\r
+        g = Groups[sp];\r
+        temp[j] = (g << NumRefBits) | j;\r
+        gRes |= (gPrev ^ g);\r
+      }\r
+      if (gRes == 0)\r
+      {\r
+        #ifndef BLOCK_SORT_EXTERNAL_FLAGS\r
+        SetGroupSize(ind2, groupSize);\r
+        #endif\r
+        return 1;\r
+      }\r
+    }\r
+    \r
+    HeapSort(temp, groupSize);\r
+    mask = ((1 << NumRefBits) - 1);\r
+    thereAreGroups = 0;\r
+    \r
+    group = groupOffset;\r
+    cg = (temp[0] >> NumRefBits);\r
+    temp[0] = ind2[temp[0] & mask];\r
+\r
+    {\r
+    #ifdef BLOCK_SORT_EXTERNAL_FLAGS\r
+    UInt32 *Flags = Groups + BlockSize;\r
+    #else\r
+    UInt32 prevGroupStart = 0;\r
+    #endif\r
+    \r
+    for (j = 1; j < groupSize; j++)\r
+    {\r
+      UInt32 val = temp[j];\r
+      UInt32 cgCur = (val >> NumRefBits);\r
+      \r
+      if (cgCur != cg)\r
+      {\r
+        cg = cgCur;\r
+        group = groupOffset + j;\r
+\r
+        #ifdef BLOCK_SORT_EXTERNAL_FLAGS\r
+        {\r
+        UInt32 t = group - 1;\r
+        Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));\r
+        }\r
+        #else\r
+        SetGroupSize(temp + prevGroupStart, j - prevGroupStart);\r
+        prevGroupStart = j;\r
+        #endif\r
+      }\r
+      else\r
+        thereAreGroups = 1;\r
+      {\r
+      UInt32 ind = ind2[val & mask];\r
+      temp[j] = ind;\r
+      Groups[ind] = group;\r
+      }\r
+    }\r
+\r
+    #ifndef BLOCK_SORT_EXTERNAL_FLAGS\r
+    SetGroupSize(temp + prevGroupStart, j - prevGroupStart);\r
+    #endif\r
+    }\r
+\r
+    for (j = 0; j < groupSize; j++)\r
+      ind2[j] = temp[j];\r
+    return thereAreGroups;\r
+  }\r
+\r
+  /* Check that all strings are in one group (cannot sort) */\r
+  {\r
+    UInt32 group, j;\r
+    UInt32 sp = ind2[0] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;\r
+    group = Groups[sp];\r
+    for (j = 1; j < groupSize; j++)\r
+    {\r
+      sp = ind2[j] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;\r
+      if (Groups[sp] != group)\r
+        break;\r
+    }\r
+    if (j == groupSize)\r
+    {\r
+      #ifndef BLOCK_SORT_EXTERNAL_FLAGS\r
+      SetGroupSize(ind2, groupSize);\r
+      #endif\r
+      return 1;\r
+    }\r
+  }\r
+\r
+  #ifndef BLOCK_SORT_USE_HEAP_SORT\r
+  {\r
+  /* ---------- Range Sort ---------- */\r
+  UInt32 i;\r
+  UInt32 mid;\r
+  for (;;)\r
+  {\r
+    UInt32 j;\r
+    if (range <= 1)\r
+    {\r
+      #ifndef BLOCK_SORT_EXTERNAL_FLAGS\r
+      SetGroupSize(ind2, groupSize);\r
+      #endif\r
+      return 1;\r
+    }\r
+    mid = left + ((range + 1) >> 1);\r
+    j = groupSize;\r
+    i = 0;\r
+    do\r
+    {\r
+      UInt32 sp = ind2[i] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;\r
+      if (Groups[sp] >= mid)\r
+      {\r
+        for (j--; j > i; j--)\r
+        {\r
+          sp = ind2[j] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;\r
+          if (Groups[sp] < mid)\r
+          {\r
+            UInt32 temp = ind2[i]; ind2[i] = ind2[j]; ind2[j] = temp;\r
+            break;\r
+          }\r
+        }\r
+        if (i >= j)\r
+          break;\r
+      }\r
+    }\r
+    while (++i < j);\r
+    if (i == 0)\r
+    {\r
+      range = range - (mid - left);\r
+      left = mid;\r
+    }\r
+    else if (i == groupSize)\r
+      range = (mid - left);\r
+    else\r
+      break;\r
+  }\r
+\r
+  #ifdef BLOCK_SORT_EXTERNAL_FLAGS\r
+  {\r
+    UInt32 t = (groupOffset + i - 1);\r
+    UInt32 *Flags = Groups + BlockSize;\r
+    Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));\r
+  }\r
+  #endif\r
+\r
+  {\r
+    UInt32 j;\r
+    for (j = i; j < groupSize; j++)\r
+      Groups[ind2[j]] = groupOffset + i;\r
+  }\r
+\r
+  {\r
+  UInt32 res = SortGroup(BlockSize, NumSortedBytes, groupOffset, i, NumRefBits, Indices, left, mid - left);\r
+  return res | SortGroup(BlockSize, NumSortedBytes, groupOffset + i, groupSize - i, NumRefBits, Indices, mid, range - (mid - left));\r
+  }\r
+\r
+  }\r
+\r
+  #else\r
+\r
+  /* ---------- Heap Sort ---------- */\r
+\r
+  {\r
+    UInt32 j;\r
+    for (j = 0; j < groupSize; j++)\r
+    {\r
+      UInt32 sp = ind2[j] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;\r
+      ind2[j] = sp;\r
+    }\r
+\r
+    HeapSortRef(ind2, Groups, groupSize);\r
+\r
+    /* Write Flags */\r
+    {\r
+    UInt32 sp = ind2[0];\r
+    UInt32 group = Groups[sp];\r
+\r
+    #ifdef BLOCK_SORT_EXTERNAL_FLAGS\r
+    UInt32 *Flags = Groups + BlockSize;\r
+    #else\r
+    UInt32 prevGroupStart = 0;\r
+    #endif\r
+\r
+    for (j = 1; j < groupSize; j++)\r
+    {\r
+      sp = ind2[j];\r
+      if (Groups[sp] != group)\r
+      {\r
+        group = Groups[sp];\r
+        #ifdef BLOCK_SORT_EXTERNAL_FLAGS\r
+        {\r
+        UInt32 t = groupOffset + j - 1;\r
+        Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));\r
+        }\r
+        #else\r
+        SetGroupSize(ind2 + prevGroupStart, j - prevGroupStart);\r
+        prevGroupStart = j;\r
+        #endif\r
+      }\r
+    }\r
+\r
+    #ifndef BLOCK_SORT_EXTERNAL_FLAGS\r
+    SetGroupSize(ind2 + prevGroupStart, j - prevGroupStart);\r
+    #endif\r
+    }\r
+    {\r
+    /* Write new Groups values and Check that there are groups */\r
+    UInt32 thereAreGroups = 0;\r
+    for (j = 0; j < groupSize; j++)\r
+    {\r
+      UInt32 group = groupOffset + j;\r
+      #ifndef BLOCK_SORT_EXTERNAL_FLAGS\r
+      UInt32 subGroupSize = ((ind2[j] & ~0xC0000000) >> kNumBitsMax);\r
+      if ((ind2[j] & 0x40000000) != 0)\r
+        subGroupSize += ((ind2[j + 1] >> kNumBitsMax) << kNumExtra0Bits);\r
+      subGroupSize++;\r
+      for (;;)\r
+      {\r
+        UInt32 original = ind2[j];\r
+        UInt32 sp = original & kIndexMask;\r
+        if (sp < NumSortedBytes) sp += BlockSize; sp -= NumSortedBytes;\r
+        ind2[j] = sp | (original & ~kIndexMask);\r
+        Groups[sp] = group;\r
+        if (--subGroupSize == 0)\r
+          break;\r
+        j++;\r
+        thereAreGroups = 1;\r
+      }\r
+      #else\r
+      UInt32 *Flags = Groups + BlockSize;\r
+      for (;;)\r
+      {\r
+        UInt32 sp = ind2[j]; if (sp < NumSortedBytes) sp += BlockSize; sp -= NumSortedBytes;\r
+        ind2[j] = sp;\r
+        Groups[sp] = group;\r
+        if ((Flags[(groupOffset + j) >> kNumFlagsBits] & (1 << ((groupOffset + j) & kFlagsMask))) == 0)\r
+          break;\r
+        j++;\r
+        thereAreGroups = 1;\r
+      }\r
+      #endif\r
+    }\r
+    return thereAreGroups;\r
+    }\r
+  }\r
+  #endif\r
+}\r
+\r
+/* conditions: blockSize > 0 */\r
+UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)\r
+{\r
+  UInt32 *counters = Indices + blockSize;\r
+  UInt32 i;\r
+  UInt32 *Groups;\r
+  #ifdef BLOCK_SORT_EXTERNAL_FLAGS\r
+  UInt32 *Flags;\r
+  #endif\r
+\r
+  /* Radix-Sort for 2 bytes */\r
+  for (i = 0; i < kNumHashValues; i++)\r
+    counters[i] = 0;\r
+  for (i = 0; i < blockSize - 1; i++)\r
+    counters[((UInt32)data[i] << 8) | data[i + 1]]++;\r
+  counters[((UInt32)data[i] << 8) | data[0]]++;\r
+\r
+  Groups = counters + BS_TEMP_SIZE;\r
+  #ifdef BLOCK_SORT_EXTERNAL_FLAGS\r
+  Flags = Groups + blockSize;\r
+    {\r
+      UInt32 numWords = (blockSize + kFlagsMask) >> kNumFlagsBits;\r
+      for (i = 0; i < numWords; i++)\r
+        Flags[i] = kAllFlags;\r
+    }\r
+  #endif\r
+\r
+  {\r
+    UInt32 sum = 0;\r
+    for (i = 0; i < kNumHashValues; i++)\r
+    {\r
+      UInt32 groupSize = counters[i];\r
+      if (groupSize > 0)\r
+      {\r
+        #ifdef BLOCK_SORT_EXTERNAL_FLAGS\r
+        UInt32 t = sum + groupSize - 1;\r
+        Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));\r
+        #endif\r
+        sum += groupSize;\r
+      }\r
+      counters[i] = sum - groupSize;\r
+    }\r
+\r
+    for (i = 0; i < blockSize - 1; i++)\r
+      Groups[i] = counters[((UInt32)data[i] << 8) | data[i + 1]];\r
+    Groups[i] = counters[((UInt32)data[i] << 8) | data[0]];\r
+\r
+    for (i = 0; i < blockSize - 1; i++)\r
+      Indices[counters[((UInt32)data[i] << 8) | data[i + 1]]++] = i;\r
+    Indices[counters[((UInt32)data[i] << 8) | data[0]]++] = i;\r
+    \r
+    #ifndef BLOCK_SORT_EXTERNAL_FLAGS\r
+    {\r
+    UInt32 prev = 0;\r
+    for (i = 0; i < kNumHashValues; i++)\r
+    {\r
+      UInt32 prevGroupSize = counters[i] - prev;\r
+      if (prevGroupSize == 0)\r
+        continue;\r
+      SetGroupSize(Indices + prev, prevGroupSize);\r
+      prev = counters[i];\r
+    }\r
+    }\r
+    #endif\r
+  }\r
+\r
+  {\r
+  int NumRefBits;\r
+  UInt32 NumSortedBytes;\r
+  for (NumRefBits = 0; ((blockSize - 1) >> NumRefBits) != 0; NumRefBits++);\r
+  NumRefBits = 32 - NumRefBits;\r
+  if (NumRefBits > kNumRefBitsMax)\r
+    NumRefBits = kNumRefBitsMax;\r
+\r
+  for (NumSortedBytes = kNumHashBytes; ; NumSortedBytes <<= 1)\r
+  {\r
+    #ifndef BLOCK_SORT_EXTERNAL_FLAGS\r
+    UInt32 finishedGroupSize = 0;\r
+    #endif\r
+    UInt32 newLimit = 0;\r
+    for (i = 0; i < blockSize;)\r
+    {\r
+      UInt32 groupSize;\r
+      #ifdef BLOCK_SORT_EXTERNAL_FLAGS\r
+\r
+      if ((Flags[i >> kNumFlagsBits] & (1 << (i & kFlagsMask))) == 0)\r
+      {\r
+        i++;\r
+        continue;\r
+      }\r
+      for (groupSize = 1;\r
+        (Flags[(i + groupSize) >> kNumFlagsBits] & (1 << ((i + groupSize) & kFlagsMask))) != 0;\r
+        groupSize++);\r
+      \r
+      groupSize++;\r
+\r
+      #else\r
+\r
+      groupSize = ((Indices[i] & ~0xC0000000) >> kNumBitsMax);\r
+      {\r
+      Bool finishedGroup = ((Indices[i] & 0x80000000) == 0);\r
+      if ((Indices[i] & 0x40000000) != 0)\r
+      {\r
+        groupSize += ((Indices[i + 1] >> kNumBitsMax) << kNumExtra0Bits);\r
+        Indices[i + 1] &= kIndexMask;\r
+      }\r
+      Indices[i] &= kIndexMask;\r
+      groupSize++;\r
+      if (finishedGroup || groupSize == 1)\r
+      {\r
+        Indices[i - finishedGroupSize] &= kIndexMask;\r
+        if (finishedGroupSize > 1)\r
+          Indices[i - finishedGroupSize + 1] &= kIndexMask;\r
+        {\r
+        UInt32 newGroupSize = groupSize + finishedGroupSize;\r
+        SetFinishedGroupSize(Indices + i - finishedGroupSize, newGroupSize);\r
+        finishedGroupSize = newGroupSize;\r
+        }\r
+        i += groupSize;\r
+        continue;\r
+      }\r
+      finishedGroupSize = 0;\r
+      }\r
+\r
+      #endif\r
+      \r
+      if (NumSortedBytes >= blockSize)\r
+      {\r
+        UInt32 j;\r
+        for (j = 0; j < groupSize; j++)\r
+        {\r
+          UInt32 t = (i + j);\r
+          /* Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask)); */\r
+          Groups[Indices[t]] = t;\r
+        }\r
+      }\r
+      else\r
+        if (SortGroup(blockSize, NumSortedBytes, i, groupSize, NumRefBits, Indices\r
+          #ifndef BLOCK_SORT_USE_HEAP_SORT\r
+          , 0, blockSize\r
+          #endif\r
+          ) != 0)\r
+          newLimit = i + groupSize;\r
+      i += groupSize;\r
+    }\r
+    if (newLimit == 0)\r
+      break;\r
+  }\r
+  }\r
+  #ifndef BLOCK_SORT_EXTERNAL_FLAGS\r
+  for (i = 0; i < blockSize;)\r
+  {\r
+    UInt32 groupSize = ((Indices[i] & ~0xC0000000) >> kNumBitsMax);\r
+    if ((Indices[i] & 0x40000000) != 0)\r
+    {\r
+      groupSize += ((Indices[i + 1] >> kNumBitsMax) << kNumExtra0Bits);\r
+      Indices[i + 1] &= kIndexMask;\r
+    }\r
+    Indices[i] &= kIndexMask;\r
+    groupSize++;\r
+    i += groupSize;\r
+  }\r
+  #endif\r
+  return Groups[0];\r
+}\r
+\r
diff --git a/C/BwtSort.h b/C/BwtSort.h
new file mode 100755 (executable)
index 0000000..9f6e095
--- /dev/null
@@ -0,0 +1,30 @@
+/* BwtSort.h -- BWT block sorting\r
+2009-02-07 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __BWT_SORT_H\r
+#define __BWT_SORT_H\r
+\r
+#include "Types.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize can be > 1M */\r
+/* #define BLOCK_SORT_EXTERNAL_FLAGS */\r
+\r
+#ifdef BLOCK_SORT_EXTERNAL_FLAGS\r
+#define BLOCK_SORT_EXTERNAL_SIZE(blockSize) ((((blockSize) + 31) >> 5))\r
+#else\r
+#define BLOCK_SORT_EXTERNAL_SIZE(blockSize) 0\r
+#endif\r
+\r
+#define BLOCK_SORT_BUF_SIZE(blockSize) ((blockSize) * 2 + BLOCK_SORT_EXTERNAL_SIZE(blockSize) + (1 << 16))\r
+\r
+UInt32 BlockSort(UInt32 *indices, const Byte *data, UInt32 blockSize);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/C/CpuArch.c b/C/CpuArch.c
new file mode 100755 (executable)
index 0000000..36e7680
--- /dev/null
@@ -0,0 +1,168 @@
+/* CpuArch.c -- CPU specific code\r
+2010-10-26: Igor Pavlov : Public domain */\r
+\r
+#include "CpuArch.h"\r
+\r
+#ifdef MY_CPU_X86_OR_AMD64\r
+\r
+#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__)\r
+#define USE_ASM\r
+#endif\r
+\r
+#if defined(USE_ASM) && !defined(MY_CPU_AMD64)\r
+static UInt32 CheckFlag(UInt32 flag)\r
+{\r
+  #ifdef _MSC_VER\r
+  __asm pushfd;\r
+  __asm pop EAX;\r
+  __asm mov EDX, EAX;\r
+  __asm xor EAX, flag;\r
+  __asm push EAX;\r
+  __asm popfd;\r
+  __asm pushfd;\r
+  __asm pop EAX;\r
+  __asm xor EAX, EDX;\r
+  __asm push EDX;\r
+  __asm popfd;\r
+  __asm and flag, EAX;\r
+  #else\r
+  __asm__ __volatile__ (\r
+    "pushf\n\t"\r
+    "pop  %%EAX\n\t"\r
+    "movl %%EAX,%%EDX\n\t"\r
+    "xorl %0,%%EAX\n\t"\r
+    "push %%EAX\n\t"\r
+    "popf\n\t"\r
+    "pushf\n\t"\r
+    "pop  %%EAX\n\t"\r
+    "xorl %%EDX,%%EAX\n\t"\r
+    "push %%EDX\n\t"\r
+    "popf\n\t"\r
+    "andl %%EAX, %0\n\t":\r
+    "=c" (flag) : "c" (flag));\r
+  #endif\r
+  return flag;\r
+}\r
+#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False;\r
+#else\r
+#define CHECK_CPUID_IS_SUPPORTED\r
+#endif\r
+\r
+static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)\r
+{\r
+  #ifdef USE_ASM\r
+\r
+  #ifdef _MSC_VER\r
+\r
+  UInt32 a2, b2, c2, d2;\r
+  __asm xor EBX, EBX;\r
+  __asm xor ECX, ECX;\r
+  __asm xor EDX, EDX;\r
+  __asm mov EAX, function;\r
+  __asm cpuid;\r
+  __asm mov a2, EAX;\r
+  __asm mov b2, EBX;\r
+  __asm mov c2, ECX;\r
+  __asm mov d2, EDX;\r
+\r
+  *a = a2;\r
+  *b = b2;\r
+  *c = c2;\r
+  *d = d2;\r
+\r
+  #else\r
+\r
+  __asm__ __volatile__ (\r
+    "cpuid"\r
+    : "=a" (*a) ,\r
+      "=b" (*b) ,\r
+      "=c" (*c) ,\r
+      "=d" (*d)\r
+    : "0" (function)) ;\r
+\r
+  #endif\r
+  \r
+  #else\r
+\r
+  int CPUInfo[4];\r
+  __cpuid(CPUInfo, function);\r
+  *a = CPUInfo[0];\r
+  *b = CPUInfo[1];\r
+  *c = CPUInfo[2];\r
+  *d = CPUInfo[3];\r
+\r
+  #endif\r
+}\r
+\r
+Bool x86cpuid_CheckAndRead(Cx86cpuid *p)\r
+{\r
+  CHECK_CPUID_IS_SUPPORTED\r
+  MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);\r
+  MyCPUID(1, &p->ver, &p->b, &p->c, &p->d);\r
+  return True;\r
+}\r
+\r
+static UInt32 kVendors[][3] =\r
+{\r
+  { 0x756E6547, 0x49656E69, 0x6C65746E},\r
+  { 0x68747541, 0x69746E65, 0x444D4163},\r
+  { 0x746E6543, 0x48727561, 0x736C7561}\r
+};\r
+\r
+int x86cpuid_GetFirm(const Cx86cpuid *p)\r
+{\r
+  unsigned i;\r
+  for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++)\r
+  {\r
+    const UInt32 *v = kVendors[i];\r
+    if (v[0] == p->vendor[0] &&\r
+        v[1] == p->vendor[1] &&\r
+        v[2] == p->vendor[2])\r
+      return (int)i;\r
+  }\r
+  return -1;\r
+}\r
+\r
+Bool CPU_Is_InOrder()\r
+{\r
+  Cx86cpuid p;\r
+  int firm;\r
+  UInt32 family, model;\r
+  if (!x86cpuid_CheckAndRead(&p))\r
+    return True;\r
+  family = x86cpuid_GetFamily(&p);\r
+  model = x86cpuid_GetModel(&p);\r
+  firm = x86cpuid_GetFirm(&p);\r
+  switch (firm)\r
+  {\r
+    case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C));\r
+    case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));\r
+    case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));\r
+  }\r
+  return True;\r
+}\r
+\r
+#if !defined(MY_CPU_AMD64) && defined(_WIN32)\r
+static Bool CPU_Sys_Is_SSE_Supported()\r
+{\r
+  OSVERSIONINFO vi;\r
+  vi.dwOSVersionInfoSize = sizeof(vi);\r
+  if (!GetVersionEx(&vi))\r
+    return False;\r
+  return (vi.dwMajorVersion >= 5);\r
+}\r
+#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;\r
+#else\r
+#define CHECK_SYS_SSE_SUPPORT\r
+#endif\r
+\r
+Bool CPU_Is_Aes_Supported()\r
+{\r
+  Cx86cpuid p;\r
+  CHECK_SYS_SSE_SUPPORT\r
+  if (!x86cpuid_CheckAndRead(&p))\r
+    return False;\r
+  return (p.c >> 25) & 1;\r
+}\r
+\r
+#endif\r
diff --git a/C/CpuArch.h b/C/CpuArch.h
new file mode 100755 (executable)
index 0000000..0a709bb
--- /dev/null
@@ -0,0 +1,155 @@
+/* CpuArch.h -- CPU specific code\r
+2010-10-26: Igor Pavlov : Public domain */\r
+\r
+#ifndef __CPU_ARCH_H\r
+#define __CPU_ARCH_H\r
+\r
+#include "Types.h"\r
+\r
+EXTERN_C_BEGIN\r
+\r
+/*\r
+MY_CPU_LE means that CPU is LITTLE ENDIAN.\r
+If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN).\r
+\r
+MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.\r
+If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform.\r
+*/\r
+\r
+#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__)\r
+#define MY_CPU_AMD64\r
+#endif\r
+\r
+#if defined(MY_CPU_AMD64) || defined(_M_IA64)\r
+#define MY_CPU_64BIT\r
+#endif\r
+\r
+#if defined(_M_IX86) || defined(__i386__)\r
+#define MY_CPU_X86\r
+#endif\r
+\r
+#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)\r
+#define MY_CPU_X86_OR_AMD64\r
+#endif\r
+\r
+#if defined(MY_CPU_X86) || defined(_M_ARM)\r
+#define MY_CPU_32BIT\r
+#endif\r
+\r
+#if defined(_WIN32) && defined(_M_ARM)\r
+#define MY_CPU_ARM_LE\r
+#endif\r
+\r
+#if defined(_WIN32) && defined(_M_IA64)\r
+#define MY_CPU_IA64_LE\r
+#endif\r
+\r
+#if defined(MY_CPU_X86_OR_AMD64)\r
+#define MY_CPU_LE_UNALIGN\r
+#endif\r
+\r
+#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE)  || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__)\r
+#define MY_CPU_LE\r
+#endif\r
+\r
+#if defined(__BIG_ENDIAN__)\r
+#define MY_CPU_BE\r
+#endif\r
+\r
+#if defined(MY_CPU_LE) && defined(MY_CPU_BE)\r
+Stop_Compiling_Bad_Endian\r
+#endif\r
+\r
+#ifdef MY_CPU_LE_UNALIGN\r
+\r
+#define GetUi16(p) (*(const UInt16 *)(p))\r
+#define GetUi32(p) (*(const UInt32 *)(p))\r
+#define GetUi64(p) (*(const UInt64 *)(p))\r
+#define SetUi16(p, d) *(UInt16 *)(p) = (d);\r
+#define SetUi32(p, d) *(UInt32 *)(p) = (d);\r
+#define SetUi64(p, d) *(UInt64 *)(p) = (d);\r
+\r
+#else\r
+\r
+#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8))\r
+\r
+#define GetUi32(p) ( \\r
+             ((const Byte *)(p))[0]        | \\r
+    ((UInt32)((const Byte *)(p))[1] <<  8) | \\r
+    ((UInt32)((const Byte *)(p))[2] << 16) | \\r
+    ((UInt32)((const Byte *)(p))[3] << 24))\r
+\r
+#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))\r
+\r
+#define SetUi16(p, d) { UInt32 _x_ = (d); \\r
+    ((Byte *)(p))[0] = (Byte)_x_; \\r
+    ((Byte *)(p))[1] = (Byte)(_x_ >> 8); }\r
+\r
+#define SetUi32(p, d) { UInt32 _x_ = (d); \\r
+    ((Byte *)(p))[0] = (Byte)_x_; \\r
+    ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \\r
+    ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \\r
+    ((Byte *)(p))[3] = (Byte)(_x_ >> 24); }\r
+\r
+#define SetUi64(p, d) { UInt64 _x64_ = (d); \\r
+    SetUi32(p, (UInt32)_x64_); \\r
+    SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); }\r
+\r
+#endif\r
+\r
+#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)\r
+\r
+#pragma intrinsic(_byteswap_ulong)\r
+#pragma intrinsic(_byteswap_uint64)\r
+#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))\r
+#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))\r
+\r
+#else\r
+\r
+#define GetBe32(p) ( \\r
+    ((UInt32)((const Byte *)(p))[0] << 24) | \\r
+    ((UInt32)((const Byte *)(p))[1] << 16) | \\r
+    ((UInt32)((const Byte *)(p))[2] <<  8) | \\r
+             ((const Byte *)(p))[3] )\r
+\r
+#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))\r
+\r
+#endif\r
+\r
+#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])\r
+\r
+\r
+#ifdef MY_CPU_X86_OR_AMD64\r
+\r
+typedef struct\r
+{\r
+  UInt32 maxFunc;\r
+  UInt32 vendor[3];\r
+  UInt32 ver;\r
+  UInt32 b;\r
+  UInt32 c;\r
+  UInt32 d;\r
+} Cx86cpuid;\r
+\r
+enum\r
+{\r
+  CPU_FIRM_INTEL,\r
+  CPU_FIRM_AMD,\r
+  CPU_FIRM_VIA\r
+};\r
+\r
+Bool x86cpuid_CheckAndRead(Cx86cpuid *p);\r
+int x86cpuid_GetFirm(const Cx86cpuid *p);\r
+\r
+#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F)\r
+#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F)\r
+#define x86cpuid_GetStepping(p) ((p)->ver & 0xF)\r
+\r
+Bool CPU_Is_InOrder();\r
+Bool CPU_Is_Aes_Supported();\r
+\r
+#endif\r
+\r
+EXTERN_C_END\r
+\r
+#endif\r
diff --git a/C/Delta.c b/C/Delta.c
new file mode 100755 (executable)
index 0000000..93c93a1
--- /dev/null
+++ b/C/Delta.c
@@ -0,0 +1,62 @@
+/* Delta.c -- Delta converter\r
+2009-05-26 : Igor Pavlov : Public domain */\r
+\r
+#include "Delta.h"\r
+\r
+void Delta_Init(Byte *state)\r
+{\r
+  unsigned i;\r
+  for (i = 0; i < DELTA_STATE_SIZE; i++)\r
+    state[i] = 0;\r
+}\r
+\r
+static void MyMemCpy(Byte *dest, const Byte *src, unsigned size)\r
+{\r
+  unsigned i;\r
+  for (i = 0; i < size; i++)\r
+    dest[i] = src[i];\r
+}\r
+\r
+void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size)\r
+{\r
+  Byte buf[DELTA_STATE_SIZE];\r
+  unsigned j = 0;\r
+  MyMemCpy(buf, state, delta);\r
+  {\r
+    SizeT i;\r
+    for (i = 0; i < size;)\r
+    {\r
+      for (j = 0; j < delta && i < size; i++, j++)\r
+      {\r
+        Byte b = data[i];\r
+        data[i] = (Byte)(b - buf[j]);\r
+        buf[j] = b;\r
+      }\r
+    }\r
+  }\r
+  if (j == delta)\r
+    j = 0;\r
+  MyMemCpy(state, buf + j, delta - j);\r
+  MyMemCpy(state + delta - j, buf, j);\r
+}\r
+\r
+void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size)\r
+{\r
+  Byte buf[DELTA_STATE_SIZE];\r
+  unsigned j = 0;\r
+  MyMemCpy(buf, state, delta);\r
+  {\r
+    SizeT i;\r
+    for (i = 0; i < size;)\r
+    {\r
+      for (j = 0; j < delta && i < size; i++, j++)\r
+      {\r
+        buf[j] = data[i] = (Byte)(buf[j] + data[i]);\r
+      }\r
+    }\r
+  }\r
+  if (j == delta)\r
+    j = 0;\r
+  MyMemCpy(state, buf + j, delta - j);\r
+  MyMemCpy(state + delta - j, buf, j);\r
+}\r
diff --git a/C/Delta.h b/C/Delta.h
new file mode 100755 (executable)
index 0000000..776cd45
--- /dev/null
+++ b/C/Delta.h
@@ -0,0 +1,23 @@
+/* Delta.h -- Delta converter\r
+2009-04-15 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __DELTA_H\r
+#define __DELTA_H\r
+\r
+#include "Types.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#define DELTA_STATE_SIZE 256\r
+\r
+void Delta_Init(Byte *state);\r
+void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size);\r
+void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/C/HuffEnc.c b/C/HuffEnc.c
new file mode 100755 (executable)
index 0000000..82dfb9a
--- /dev/null
@@ -0,0 +1,146 @@
+/* HuffEnc.c -- functions for Huffman encoding\r
+2009-09-02 : Igor Pavlov : Public domain */\r
+\r
+#include "HuffEnc.h"\r
+#include "Sort.h"\r
+\r
+#define kMaxLen 16\r
+#define NUM_BITS 10\r
+#define MASK ((1 << NUM_BITS) - 1)\r
+\r
+#define NUM_COUNTERS 64\r
+\r
+#define HUFFMAN_SPEED_OPT\r
+\r
+void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymbols, UInt32 maxLen)\r
+{\r
+  UInt32 num = 0;\r
+  /* if (maxLen > 10) maxLen = 10; */\r
+  {\r
+    UInt32 i;\r
+    \r
+    #ifdef HUFFMAN_SPEED_OPT\r
+    \r
+    UInt32 counters[NUM_COUNTERS];\r
+    for (i = 0; i < NUM_COUNTERS; i++)\r
+      counters[i] = 0;\r
+    for (i = 0; i < numSymbols; i++)\r
+    {\r
+      UInt32 freq = freqs[i];\r
+      counters[(freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1]++;\r
+    }\r
\r
+    for (i = 1; i < NUM_COUNTERS; i++)\r
+    {\r
+      UInt32 temp = counters[i];\r
+      counters[i] = num;\r
+      num += temp;\r
+    }\r
+\r
+    for (i = 0; i < numSymbols; i++)\r
+    {\r
+      UInt32 freq = freqs[i];\r
+      if (freq == 0)\r
+        lens[i] = 0;\r
+      else\r
+        p[counters[((freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1)]++] = i | (freq << NUM_BITS);\r
+    }\r
+    counters[0] = 0;\r
+    HeapSort(p + counters[NUM_COUNTERS - 2], counters[NUM_COUNTERS - 1] - counters[NUM_COUNTERS - 2]);\r
+    \r
+    #else\r
+\r
+    for (i = 0; i < numSymbols; i++)\r
+    {\r
+      UInt32 freq = freqs[i];\r
+      if (freq == 0)\r
+        lens[i] = 0;\r
+      else\r
+        p[num++] = i | (freq << NUM_BITS);\r
+    }\r
+    HeapSort(p, num);\r
+\r
+    #endif\r
+  }\r
+\r
+  if (num < 2)\r
+  {\r
+    unsigned minCode = 0;\r
+    unsigned maxCode = 1;\r
+    if (num == 1)\r
+    {\r
+      maxCode = (unsigned)p[0] & MASK;\r
+      if (maxCode == 0)\r
+        maxCode++;\r
+    }\r
+    p[minCode] = 0;\r
+    p[maxCode] = 1;\r
+    lens[minCode] = lens[maxCode] = 1;\r
+    return;\r
+  }\r
+  \r
+  {\r
+    UInt32 b, e, i;\r
+  \r
+    i = b = e = 0;\r
+    do\r
+    {\r
+      UInt32 n, m, freq;\r
+      n = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++;\r
+      freq = (p[n] & ~MASK);\r
+      p[n] = (p[n] & MASK) | (e << NUM_BITS);\r
+      m = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++;\r
+      freq += (p[m] & ~MASK);\r
+      p[m] = (p[m] & MASK) | (e << NUM_BITS);\r
+      p[e] = (p[e] & MASK) | freq;\r
+      e++;\r
+    }\r
+    while (num - e > 1);\r
+    \r
+    {\r
+      UInt32 lenCounters[kMaxLen + 1];\r
+      for (i = 0; i <= kMaxLen; i++)\r
+        lenCounters[i] = 0;\r
+      \r
+      p[--e] &= MASK;\r
+      lenCounters[1] = 2;\r
+      while (e > 0)\r
+      {\r
+        UInt32 len = (p[p[--e] >> NUM_BITS] >> NUM_BITS) + 1;\r
+        p[e] = (p[e] & MASK) | (len << NUM_BITS);\r
+        if (len >= maxLen)\r
+          for (len = maxLen - 1; lenCounters[len] == 0; len--);\r
+        lenCounters[len]--;\r
+        lenCounters[len + 1] += 2;\r
+      }\r
+      \r
+      {\r
+        UInt32 len;\r
+        i = 0;\r
+        for (len = maxLen; len != 0; len--)\r
+        {\r
+          UInt32 num;\r
+          for (num = lenCounters[len]; num != 0; num--)\r
+            lens[p[i++] & MASK] = (Byte)len;\r
+        }\r
+      }\r
+      \r
+      {\r
+        UInt32 nextCodes[kMaxLen + 1];\r
+        {\r
+          UInt32 code = 0;\r
+          UInt32 len;\r
+          for (len = 1; len <= kMaxLen; len++)\r
+            nextCodes[len] = code = (code + lenCounters[len - 1]) << 1;\r
+        }\r
+        /* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */\r
+\r
+        {\r
+          UInt32 i;\r
+          for (i = 0; i < numSymbols; i++)\r
+            p[i] = nextCodes[lens[i]]++;\r
+        }\r
+      }\r
+    }\r
+  }\r
+}\r
diff --git a/C/HuffEnc.h b/C/HuffEnc.h
new file mode 100755 (executable)
index 0000000..6508a83
--- /dev/null
@@ -0,0 +1,27 @@
+/* HuffEnc.h -- Huffman encoding\r
+2009-02-07 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __HUFF_ENC_H\r
+#define __HUFF_ENC_H\r
+\r
+#include "Types.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/*\r
+Conditions:\r
+  num <= 1024 = 2 ^ NUM_BITS\r
+  Sum(freqs) < 4M = 2 ^ (32 - NUM_BITS)\r
+  maxLen <= 16 = kMaxLen\r
+  Num_Items(p) >= HUFFMAN_TEMP_SIZE(num)\r
+*/\r
\r
+void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/C/LzFind.c b/C/LzFind.c
new file mode 100755 (executable)
index 0000000..f6c9e66
--- /dev/null
@@ -0,0 +1,761 @@
+/* LzFind.c -- Match finder for LZ algorithms\r
+2009-04-22 : Igor Pavlov : Public domain */\r
+\r
+#include <string.h>\r
+\r
+#include "LzFind.h"\r
+#include "LzHash.h"\r
+\r
+#define kEmptyHashValue 0\r
+#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)\r
+#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */\r
+#define kNormalizeMask (~(kNormalizeStepMin - 1))\r
+#define kMaxHistorySize ((UInt32)3 << 30)\r
+\r
+#define kStartMaxLen 3\r
+\r
+static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)\r
+{\r
+  if (!p->directInput)\r
+  {\r
+    alloc->Free(alloc, p->bufferBase);\r
+    p->bufferBase = 0;\r
+  }\r
+}\r
+\r
+/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */\r
+\r
+static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)\r
+{\r
+  UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;\r
+  if (p->directInput)\r
+  {\r
+    p->blockSize = blockSize;\r
+    return 1;\r
+  }\r
+  if (p->bufferBase == 0 || p->blockSize != blockSize)\r
+  {\r
+    LzInWindow_Free(p, alloc);\r
+    p->blockSize = blockSize;\r
+    p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize);\r
+  }\r
+  return (p->bufferBase != 0);\r
+}\r
+\r
+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }\r
+Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }\r
+\r
+UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }\r
+\r
+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)\r
+{\r
+  p->posLimit -= subValue;\r
+  p->pos -= subValue;\r
+  p->streamPos -= subValue;\r
+}\r
+\r
+static void MatchFinder_ReadBlock(CMatchFinder *p)\r
+{\r
+  if (p->streamEndWasReached || p->result != SZ_OK)\r
+    return;\r
+  if (p->directInput)\r
+  {\r
+    UInt32 curSize = 0xFFFFFFFF - p->streamPos;\r
+    if (curSize > p->directInputRem)\r
+      curSize = (UInt32)p->directInputRem;\r
+    p->directInputRem -= curSize;\r
+    p->streamPos += curSize;\r
+    if (p->directInputRem == 0)\r
+      p->streamEndWasReached = 1;\r
+    return;\r
+  }\r
+  for (;;)\r
+  {\r
+    Byte *dest = p->buffer + (p->streamPos - p->pos);\r
+    size_t size = (p->bufferBase + p->blockSize - dest);\r
+    if (size == 0)\r
+      return;\r
+    p->result = p->stream->Read(p->stream, dest, &size);\r
+    if (p->result != SZ_OK)\r
+      return;\r
+    if (size == 0)\r
+    {\r
+      p->streamEndWasReached = 1;\r
+      return;\r
+    }\r
+    p->streamPos += (UInt32)size;\r
+    if (p->streamPos - p->pos > p->keepSizeAfter)\r
+      return;\r
+  }\r
+}\r
+\r
+void MatchFinder_MoveBlock(CMatchFinder *p)\r
+{\r
+  memmove(p->bufferBase,\r
+    p->buffer - p->keepSizeBefore,\r
+    (size_t)(p->streamPos - p->pos + p->keepSizeBefore));\r
+  p->buffer = p->bufferBase + p->keepSizeBefore;\r
+}\r
+\r
+int MatchFinder_NeedMove(CMatchFinder *p)\r
+{\r
+  if (p->directInput)\r
+    return 0;\r
+  /* if (p->streamEndWasReached) return 0; */\r
+  return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);\r
+}\r
+\r
+void MatchFinder_ReadIfRequired(CMatchFinder *p)\r
+{\r
+  if (p->streamEndWasReached)\r
+    return;\r
+  if (p->keepSizeAfter >= p->streamPos - p->pos)\r
+    MatchFinder_ReadBlock(p);\r
+}\r
+\r
+static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)\r
+{\r
+  if (MatchFinder_NeedMove(p))\r
+    MatchFinder_MoveBlock(p);\r
+  MatchFinder_ReadBlock(p);\r
+}\r
+\r
+static void MatchFinder_SetDefaultSettings(CMatchFinder *p)\r
+{\r
+  p->cutValue = 32;\r
+  p->btMode = 1;\r
+  p->numHashBytes = 4;\r
+  p->bigHash = 0;\r
+}\r
+\r
+#define kCrcPoly 0xEDB88320\r
+\r
+void MatchFinder_Construct(CMatchFinder *p)\r
+{\r
+  UInt32 i;\r
+  p->bufferBase = 0;\r
+  p->directInput = 0;\r
+  p->hash = 0;\r
+  MatchFinder_SetDefaultSettings(p);\r
+\r
+  for (i = 0; i < 256; i++)\r
+  {\r
+    UInt32 r = i;\r
+    int j;\r
+    for (j = 0; j < 8; j++)\r
+      r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));\r
+    p->crc[i] = r;\r
+  }\r
+}\r
+\r
+static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)\r
+{\r
+  alloc->Free(alloc, p->hash);\r
+  p->hash = 0;\r
+}\r
+\r
+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)\r
+{\r
+  MatchFinder_FreeThisClassMemory(p, alloc);\r
+  LzInWindow_Free(p, alloc);\r
+}\r
+\r
+static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)\r
+{\r
+  size_t sizeInBytes = (size_t)num * sizeof(CLzRef);\r
+  if (sizeInBytes / sizeof(CLzRef) != num)\r
+    return 0;\r
+  return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);\r
+}\r
+\r
+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,\r
+    UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,\r
+    ISzAlloc *alloc)\r
+{\r
+  UInt32 sizeReserv;\r
+  if (historySize > kMaxHistorySize)\r
+  {\r
+    MatchFinder_Free(p, alloc);\r
+    return 0;\r
+  }\r
+  sizeReserv = historySize >> 1;\r
+  if (historySize > ((UInt32)2 << 30))\r
+    sizeReserv = historySize >> 2;\r
+  sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);\r
+\r
+  p->keepSizeBefore = historySize + keepAddBufferBefore + 1;\r
+  p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;\r
+  /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */\r
+  if (LzInWindow_Create(p, sizeReserv, alloc))\r
+  {\r
+    UInt32 newCyclicBufferSize = historySize + 1;\r
+    UInt32 hs;\r
+    p->matchMaxLen = matchMaxLen;\r
+    {\r
+      p->fixedHashSize = 0;\r
+      if (p->numHashBytes == 2)\r
+        hs = (1 << 16) - 1;\r
+      else\r
+      {\r
+        hs = historySize - 1;\r
+        hs |= (hs >> 1);\r
+        hs |= (hs >> 2);\r
+        hs |= (hs >> 4);\r
+        hs |= (hs >> 8);\r
+        hs >>= 1;\r
+        hs |= 0xFFFF; /* don't change it! It's required for Deflate */\r
+        if (hs > (1 << 24))\r
+        {\r
+          if (p->numHashBytes == 3)\r
+            hs = (1 << 24) - 1;\r
+          else\r
+            hs >>= 1;\r
+        }\r
+      }\r
+      p->hashMask = hs;\r
+      hs++;\r
+      if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;\r
+      if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;\r
+      if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;\r
+      hs += p->fixedHashSize;\r
+    }\r
+\r
+    {\r
+      UInt32 prevSize = p->hashSizeSum + p->numSons;\r
+      UInt32 newSize;\r
+      p->historySize = historySize;\r
+      p->hashSizeSum = hs;\r
+      p->cyclicBufferSize = newCyclicBufferSize;\r
+      p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);\r
+      newSize = p->hashSizeSum + p->numSons;\r
+      if (p->hash != 0 && prevSize == newSize)\r
+        return 1;\r
+      MatchFinder_FreeThisClassMemory(p, alloc);\r
+      p->hash = AllocRefs(newSize, alloc);\r
+      if (p->hash != 0)\r
+      {\r
+        p->son = p->hash + p->hashSizeSum;\r
+        return 1;\r
+      }\r
+    }\r
+  }\r
+  MatchFinder_Free(p, alloc);\r
+  return 0;\r
+}\r
+\r
+static void MatchFinder_SetLimits(CMatchFinder *p)\r
+{\r
+  UInt32 limit = kMaxValForNormalize - p->pos;\r
+  UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;\r
+  if (limit2 < limit)\r
+    limit = limit2;\r
+  limit2 = p->streamPos - p->pos;\r
+  if (limit2 <= p->keepSizeAfter)\r
+  {\r
+    if (limit2 > 0)\r
+      limit2 = 1;\r
+  }\r
+  else\r
+    limit2 -= p->keepSizeAfter;\r
+  if (limit2 < limit)\r
+    limit = limit2;\r
+  {\r
+    UInt32 lenLimit = p->streamPos - p->pos;\r
+    if (lenLimit > p->matchMaxLen)\r
+      lenLimit = p->matchMaxLen;\r
+    p->lenLimit = lenLimit;\r
+  }\r
+  p->posLimit = p->pos + limit;\r
+}\r
+\r
+void MatchFinder_Init(CMatchFinder *p)\r
+{\r
+  UInt32 i;\r
+  for (i = 0; i < p->hashSizeSum; i++)\r
+    p->hash[i] = kEmptyHashValue;\r
+  p->cyclicBufferPos = 0;\r
+  p->buffer = p->bufferBase;\r
+  p->pos = p->streamPos = p->cyclicBufferSize;\r
+  p->result = SZ_OK;\r
+  p->streamEndWasReached = 0;\r
+  MatchFinder_ReadBlock(p);\r
+  MatchFinder_SetLimits(p);\r
+}\r
+\r
+static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)\r
+{\r
+  return (p->pos - p->historySize - 1) & kNormalizeMask;\r
+}\r
+\r
+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)\r
+{\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    UInt32 value = items[i];\r
+    if (value <= subValue)\r
+      value = kEmptyHashValue;\r
+    else\r
+      value -= subValue;\r
+    items[i] = value;\r
+  }\r
+}\r
+\r
+static void MatchFinder_Normalize(CMatchFinder *p)\r
+{\r
+  UInt32 subValue = MatchFinder_GetSubValue(p);\r
+  MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);\r
+  MatchFinder_ReduceOffsets(p, subValue);\r
+}\r
+\r
+static void MatchFinder_CheckLimits(CMatchFinder *p)\r
+{\r
+  if (p->pos == kMaxValForNormalize)\r
+    MatchFinder_Normalize(p);\r
+  if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)\r
+    MatchFinder_CheckAndMoveAndRead(p);\r
+  if (p->cyclicBufferPos == p->cyclicBufferSize)\r
+    p->cyclicBufferPos = 0;\r
+  MatchFinder_SetLimits(p);\r
+}\r
+\r
+static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,\r
+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,\r
+    UInt32 *distances, UInt32 maxLen)\r
+{\r
+  son[_cyclicBufferPos] = curMatch;\r
+  for (;;)\r
+  {\r
+    UInt32 delta = pos - curMatch;\r
+    if (cutValue-- == 0 || delta >= _cyclicBufferSize)\r
+      return distances;\r
+    {\r
+      const Byte *pb = cur - delta;\r
+      curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];\r
+      if (pb[maxLen] == cur[maxLen] && *pb == *cur)\r
+      {\r
+        UInt32 len = 0;\r
+        while (++len != lenLimit)\r
+          if (pb[len] != cur[len])\r
+            break;\r
+        if (maxLen < len)\r
+        {\r
+          *distances++ = maxLen = len;\r
+          *distances++ = delta - 1;\r
+          if (len == lenLimit)\r
+            return distances;\r
+        }\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,\r
+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,\r
+    UInt32 *distances, UInt32 maxLen)\r
+{\r
+  CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;\r
+  CLzRef *ptr1 = son + (_cyclicBufferPos << 1);\r
+  UInt32 len0 = 0, len1 = 0;\r
+  for (;;)\r
+  {\r
+    UInt32 delta = pos - curMatch;\r
+    if (cutValue-- == 0 || delta >= _cyclicBufferSize)\r
+    {\r
+      *ptr0 = *ptr1 = kEmptyHashValue;\r
+      return distances;\r
+    }\r
+    {\r
+      CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);\r
+      const Byte *pb = cur - delta;\r
+      UInt32 len = (len0 < len1 ? len0 : len1);\r
+      if (pb[len] == cur[len])\r
+      {\r
+        if (++len != lenLimit && pb[len] == cur[len])\r
+          while (++len != lenLimit)\r
+            if (pb[len] != cur[len])\r
+              break;\r
+        if (maxLen < len)\r
+        {\r
+          *distances++ = maxLen = len;\r
+          *distances++ = delta - 1;\r
+          if (len == lenLimit)\r
+          {\r
+            *ptr1 = pair[0];\r
+            *ptr0 = pair[1];\r
+            return distances;\r
+          }\r
+        }\r
+      }\r
+      if (pb[len] < cur[len])\r
+      {\r
+        *ptr1 = curMatch;\r
+        ptr1 = pair + 1;\r
+        curMatch = *ptr1;\r
+        len1 = len;\r
+      }\r
+      else\r
+      {\r
+        *ptr0 = curMatch;\r
+        ptr0 = pair;\r
+        curMatch = *ptr0;\r
+        len0 = len;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,\r
+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)\r
+{\r
+  CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;\r
+  CLzRef *ptr1 = son + (_cyclicBufferPos << 1);\r
+  UInt32 len0 = 0, len1 = 0;\r
+  for (;;)\r
+  {\r
+    UInt32 delta = pos - curMatch;\r
+    if (cutValue-- == 0 || delta >= _cyclicBufferSize)\r
+    {\r
+      *ptr0 = *ptr1 = kEmptyHashValue;\r
+      return;\r
+    }\r
+    {\r
+      CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);\r
+      const Byte *pb = cur - delta;\r
+      UInt32 len = (len0 < len1 ? len0 : len1);\r
+      if (pb[len] == cur[len])\r
+      {\r
+        while (++len != lenLimit)\r
+          if (pb[len] != cur[len])\r
+            break;\r
+        {\r
+          if (len == lenLimit)\r
+          {\r
+            *ptr1 = pair[0];\r
+            *ptr0 = pair[1];\r
+            return;\r
+          }\r
+        }\r
+      }\r
+      if (pb[len] < cur[len])\r
+      {\r
+        *ptr1 = curMatch;\r
+        ptr1 = pair + 1;\r
+        curMatch = *ptr1;\r
+        len1 = len;\r
+      }\r
+      else\r
+      {\r
+        *ptr0 = curMatch;\r
+        ptr0 = pair;\r
+        curMatch = *ptr0;\r
+        len0 = len;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+#define MOVE_POS \\r
+  ++p->cyclicBufferPos; \\r
+  p->buffer++; \\r
+  if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);\r
+\r
+#define MOVE_POS_RET MOVE_POS return offset;\r
+\r
+static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }\r
+\r
+#define GET_MATCHES_HEADER2(minLen, ret_op) \\r
+  UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \\r
+  lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \\r
+  cur = p->buffer;\r
+\r
+#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)\r
+#define SKIP_HEADER(minLen)        GET_MATCHES_HEADER2(minLen, continue)\r
+\r
+#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue\r
+\r
+#define GET_MATCHES_FOOTER(offset, maxLen) \\r
+  offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \\r
+  distances + offset, maxLen) - distances); MOVE_POS_RET;\r
+\r
+#define SKIP_FOOTER \\r
+  SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;\r
+\r
+static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)\r
+{\r
+  UInt32 offset;\r
+  GET_MATCHES_HEADER(2)\r
+  HASH2_CALC;\r
+  curMatch = p->hash[hashValue];\r
+  p->hash[hashValue] = p->pos;\r
+  offset = 0;\r
+  GET_MATCHES_FOOTER(offset, 1)\r
+}\r
+\r
+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)\r
+{\r
+  UInt32 offset;\r
+  GET_MATCHES_HEADER(3)\r
+  HASH_ZIP_CALC;\r
+  curMatch = p->hash[hashValue];\r
+  p->hash[hashValue] = p->pos;\r
+  offset = 0;\r
+  GET_MATCHES_FOOTER(offset, 2)\r
+}\r
+\r
+static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)\r
+{\r
+  UInt32 hash2Value, delta2, maxLen, offset;\r
+  GET_MATCHES_HEADER(3)\r
+\r
+  HASH3_CALC;\r
+\r
+  delta2 = p->pos - p->hash[hash2Value];\r
+  curMatch = p->hash[kFix3HashSize + hashValue];\r
+  \r
+  p->hash[hash2Value] =\r
+  p->hash[kFix3HashSize + hashValue] = p->pos;\r
+\r
+\r
+  maxLen = 2;\r
+  offset = 0;\r
+  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)\r
+  {\r
+    for (; maxLen != lenLimit; maxLen++)\r
+      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])\r
+        break;\r
+    distances[0] = maxLen;\r
+    distances[1] = delta2 - 1;\r
+    offset = 2;\r
+    if (maxLen == lenLimit)\r
+    {\r
+      SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));\r
+      MOVE_POS_RET;\r
+    }\r
+  }\r
+  GET_MATCHES_FOOTER(offset, maxLen)\r
+}\r
+\r
+static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)\r
+{\r
+  UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;\r
+  GET_MATCHES_HEADER(4)\r
+\r
+  HASH4_CALC;\r
+\r
+  delta2 = p->pos - p->hash[                hash2Value];\r
+  delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];\r
+  curMatch = p->hash[kFix4HashSize + hashValue];\r
+  \r
+  p->hash[                hash2Value] =\r
+  p->hash[kFix3HashSize + hash3Value] =\r
+  p->hash[kFix4HashSize + hashValue] = p->pos;\r
+\r
+  maxLen = 1;\r
+  offset = 0;\r
+  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)\r
+  {\r
+    distances[0] = maxLen = 2;\r
+    distances[1] = delta2 - 1;\r
+    offset = 2;\r
+  }\r
+  if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)\r
+  {\r
+    maxLen = 3;\r
+    distances[offset + 1] = delta3 - 1;\r
+    offset += 2;\r
+    delta2 = delta3;\r
+  }\r
+  if (offset != 0)\r
+  {\r
+    for (; maxLen != lenLimit; maxLen++)\r
+      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])\r
+        break;\r
+    distances[offset - 2] = maxLen;\r
+    if (maxLen == lenLimit)\r
+    {\r
+      SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));\r
+      MOVE_POS_RET;\r
+    }\r
+  }\r
+  if (maxLen < 3)\r
+    maxLen = 3;\r
+  GET_MATCHES_FOOTER(offset, maxLen)\r
+}\r
+\r
+static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)\r
+{\r
+  UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;\r
+  GET_MATCHES_HEADER(4)\r
+\r
+  HASH4_CALC;\r
+\r
+  delta2 = p->pos - p->hash[                hash2Value];\r
+  delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];\r
+  curMatch = p->hash[kFix4HashSize + hashValue];\r
+\r
+  p->hash[                hash2Value] =\r
+  p->hash[kFix3HashSize + hash3Value] =\r
+  p->hash[kFix4HashSize + hashValue] = p->pos;\r
+\r
+  maxLen = 1;\r
+  offset = 0;\r
+  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)\r
+  {\r
+    distances[0] = maxLen = 2;\r
+    distances[1] = delta2 - 1;\r
+    offset = 2;\r
+  }\r
+  if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)\r
+  {\r
+    maxLen = 3;\r
+    distances[offset + 1] = delta3 - 1;\r
+    offset += 2;\r
+    delta2 = delta3;\r
+  }\r
+  if (offset != 0)\r
+  {\r
+    for (; maxLen != lenLimit; maxLen++)\r
+      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])\r
+        break;\r
+    distances[offset - 2] = maxLen;\r
+    if (maxLen == lenLimit)\r
+    {\r
+      p->son[p->cyclicBufferPos] = curMatch;\r
+      MOVE_POS_RET;\r
+    }\r
+  }\r
+  if (maxLen < 3)\r
+    maxLen = 3;\r
+  offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),\r
+    distances + offset, maxLen) - (distances));\r
+  MOVE_POS_RET\r
+}\r
+\r
+UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)\r
+{\r
+  UInt32 offset;\r
+  GET_MATCHES_HEADER(3)\r
+  HASH_ZIP_CALC;\r
+  curMatch = p->hash[hashValue];\r
+  p->hash[hashValue] = p->pos;\r
+  offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),\r
+    distances, 2) - (distances));\r
+  MOVE_POS_RET\r
+}\r
+\r
+static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)\r
+{\r
+  do\r
+  {\r
+    SKIP_HEADER(2)\r
+    HASH2_CALC;\r
+    curMatch = p->hash[hashValue];\r
+    p->hash[hashValue] = p->pos;\r
+    SKIP_FOOTER\r
+  }\r
+  while (--num != 0);\r
+}\r
+\r
+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)\r
+{\r
+  do\r
+  {\r
+    SKIP_HEADER(3)\r
+    HASH_ZIP_CALC;\r
+    curMatch = p->hash[hashValue];\r
+    p->hash[hashValue] = p->pos;\r
+    SKIP_FOOTER\r
+  }\r
+  while (--num != 0);\r
+}\r
+\r
+static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)\r
+{\r
+  do\r
+  {\r
+    UInt32 hash2Value;\r
+    SKIP_HEADER(3)\r
+    HASH3_CALC;\r
+    curMatch = p->hash[kFix3HashSize + hashValue];\r
+    p->hash[hash2Value] =\r
+    p->hash[kFix3HashSize + hashValue] = p->pos;\r
+    SKIP_FOOTER\r
+  }\r
+  while (--num != 0);\r
+}\r
+\r
+static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)\r
+{\r
+  do\r
+  {\r
+    UInt32 hash2Value, hash3Value;\r
+    SKIP_HEADER(4)\r
+    HASH4_CALC;\r
+    curMatch = p->hash[kFix4HashSize + hashValue];\r
+    p->hash[                hash2Value] =\r
+    p->hash[kFix3HashSize + hash3Value] = p->pos;\r
+    p->hash[kFix4HashSize + hashValue] = p->pos;\r
+    SKIP_FOOTER\r
+  }\r
+  while (--num != 0);\r
+}\r
+\r
+static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)\r
+{\r
+  do\r
+  {\r
+    UInt32 hash2Value, hash3Value;\r
+    SKIP_HEADER(4)\r
+    HASH4_CALC;\r
+    curMatch = p->hash[kFix4HashSize + hashValue];\r
+    p->hash[                hash2Value] =\r
+    p->hash[kFix3HashSize + hash3Value] =\r
+    p->hash[kFix4HashSize + hashValue] = p->pos;\r
+    p->son[p->cyclicBufferPos] = curMatch;\r
+    MOVE_POS\r
+  }\r
+  while (--num != 0);\r
+}\r
+\r
+void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)\r
+{\r
+  do\r
+  {\r
+    SKIP_HEADER(3)\r
+    HASH_ZIP_CALC;\r
+    curMatch = p->hash[hashValue];\r
+    p->hash[hashValue] = p->pos;\r
+    p->son[p->cyclicBufferPos] = curMatch;\r
+    MOVE_POS\r
+  }\r
+  while (--num != 0);\r
+}\r
+\r
+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)\r
+{\r
+  vTable->Init = (Mf_Init_Func)MatchFinder_Init;\r
+  vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;\r
+  vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;\r
+  vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;\r
+  if (!p->btMode)\r
+  {\r
+    vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;\r
+    vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;\r
+  }\r
+  else if (p->numHashBytes == 2)\r
+  {\r
+    vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;\r
+    vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;\r
+  }\r
+  else if (p->numHashBytes == 3)\r
+  {\r
+    vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;\r
+    vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;\r
+  }\r
+  else\r
+  {\r
+    vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;\r
+    vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;\r
+  }\r
+}\r
diff --git a/C/LzFind.h b/C/LzFind.h
new file mode 100755 (executable)
index 0000000..7ebdfa4
--- /dev/null
@@ -0,0 +1,115 @@
+/* LzFind.h -- Match finder for LZ algorithms\r
+2009-04-22 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __LZ_FIND_H\r
+#define __LZ_FIND_H\r
+\r
+#include "Types.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+typedef UInt32 CLzRef;\r
+\r
+typedef struct _CMatchFinder\r
+{\r
+  Byte *buffer;\r
+  UInt32 pos;\r
+  UInt32 posLimit;\r
+  UInt32 streamPos;\r
+  UInt32 lenLimit;\r
+\r
+  UInt32 cyclicBufferPos;\r
+  UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */\r
+\r
+  UInt32 matchMaxLen;\r
+  CLzRef *hash;\r
+  CLzRef *son;\r
+  UInt32 hashMask;\r
+  UInt32 cutValue;\r
+\r
+  Byte *bufferBase;\r
+  ISeqInStream *stream;\r
+  int streamEndWasReached;\r
+\r
+  UInt32 blockSize;\r
+  UInt32 keepSizeBefore;\r
+  UInt32 keepSizeAfter;\r
+\r
+  UInt32 numHashBytes;\r
+  int directInput;\r
+  size_t directInputRem;\r
+  int btMode;\r
+  int bigHash;\r
+  UInt32 historySize;\r
+  UInt32 fixedHashSize;\r
+  UInt32 hashSizeSum;\r
+  UInt32 numSons;\r
+  SRes result;\r
+  UInt32 crc[256];\r
+} CMatchFinder;\r
+\r
+#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)\r
+#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])\r
+\r
+#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)\r
+\r
+int MatchFinder_NeedMove(CMatchFinder *p);\r
+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);\r
+void MatchFinder_MoveBlock(CMatchFinder *p);\r
+void MatchFinder_ReadIfRequired(CMatchFinder *p);\r
+\r
+void MatchFinder_Construct(CMatchFinder *p);\r
+\r
+/* Conditions:\r
+     historySize <= 3 GB\r
+     keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB\r
+*/\r
+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,\r
+    UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,\r
+    ISzAlloc *alloc);\r
+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);\r
+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);\r
+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);\r
+\r
+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,\r
+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,\r
+    UInt32 *distances, UInt32 maxLen);\r
+\r
+/*\r
+Conditions:\r
+  Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.\r
+  Mf_GetPointerToCurrentPos_Func's result must be used only before any other function\r
+*/\r
+\r
+typedef void (*Mf_Init_Func)(void *object);\r
+typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);\r
+typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);\r
+typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);\r
+typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);\r
+typedef void (*Mf_Skip_Func)(void *object, UInt32);\r
+\r
+typedef struct _IMatchFinder\r
+{\r
+  Mf_Init_Func Init;\r
+  Mf_GetIndexByte_Func GetIndexByte;\r
+  Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;\r
+  Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;\r
+  Mf_GetMatches_Func GetMatches;\r
+  Mf_Skip_Func Skip;\r
+} IMatchFinder;\r
+\r
+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);\r
+\r
+void MatchFinder_Init(CMatchFinder *p);\r
+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);\r
+UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);\r
+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);\r
+void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/C/LzFindMt.c b/C/LzFindMt.c
new file mode 100755 (executable)
index 0000000..db95590
--- /dev/null
@@ -0,0 +1,793 @@
+/* LzFindMt.c -- multithreaded Match finder for LZ algorithms\r
+2009-09-20 : Igor Pavlov : Public domain */\r
+\r
+#include "LzHash.h"\r
+\r
+#include "LzFindMt.h"\r
+\r
+void MtSync_Construct(CMtSync *p)\r
+{\r
+  p->wasCreated = False;\r
+  p->csWasInitialized = False;\r
+  p->csWasEntered = False;\r
+  Thread_Construct(&p->thread);\r
+  Event_Construct(&p->canStart);\r
+  Event_Construct(&p->wasStarted);\r
+  Event_Construct(&p->wasStopped);\r
+  Semaphore_Construct(&p->freeSemaphore);\r
+  Semaphore_Construct(&p->filledSemaphore);\r
+}\r
+\r
+void MtSync_GetNextBlock(CMtSync *p)\r
+{\r
+  if (p->needStart)\r
+  {\r
+    p->numProcessedBlocks = 1;\r
+    p->needStart = False;\r
+    p->stopWriting = False;\r
+    p->exit = False;\r
+    Event_Reset(&p->wasStarted);\r
+    Event_Reset(&p->wasStopped);\r
+\r
+    Event_Set(&p->canStart);\r
+    Event_Wait(&p->wasStarted);\r
+  }\r
+  else\r
+  {\r
+    CriticalSection_Leave(&p->cs);\r
+    p->csWasEntered = False;\r
+    p->numProcessedBlocks++;\r
+    Semaphore_Release1(&p->freeSemaphore);\r
+  }\r
+  Semaphore_Wait(&p->filledSemaphore);\r
+  CriticalSection_Enter(&p->cs);\r
+  p->csWasEntered = True;\r
+}\r
+\r
+/* MtSync_StopWriting must be called if Writing was started */\r
+\r
+void MtSync_StopWriting(CMtSync *p)\r
+{\r
+  UInt32 myNumBlocks = p->numProcessedBlocks;\r
+  if (!Thread_WasCreated(&p->thread) || p->needStart)\r
+    return;\r
+  p->stopWriting = True;\r
+  if (p->csWasEntered)\r
+  {\r
+    CriticalSection_Leave(&p->cs);\r
+    p->csWasEntered = False;\r
+  }\r
+  Semaphore_Release1(&p->freeSemaphore);\r
\r
+  Event_Wait(&p->wasStopped);\r
+\r
+  while (myNumBlocks++ != p->numProcessedBlocks)\r
+  {\r
+    Semaphore_Wait(&p->filledSemaphore);\r
+    Semaphore_Release1(&p->freeSemaphore);\r
+  }\r
+  p->needStart = True;\r
+}\r
+\r
+void MtSync_Destruct(CMtSync *p)\r
+{\r
+  if (Thread_WasCreated(&p->thread))\r
+  {\r
+    MtSync_StopWriting(p);\r
+    p->exit = True;\r
+    if (p->needStart)\r
+      Event_Set(&p->canStart);\r
+    Thread_Wait(&p->thread);\r
+    Thread_Close(&p->thread);\r
+  }\r
+  if (p->csWasInitialized)\r
+  {\r
+    CriticalSection_Delete(&p->cs);\r
+    p->csWasInitialized = False;\r
+  }\r
+\r
+  Event_Close(&p->canStart);\r
+  Event_Close(&p->wasStarted);\r
+  Event_Close(&p->wasStopped);\r
+  Semaphore_Close(&p->freeSemaphore);\r
+  Semaphore_Close(&p->filledSemaphore);\r
+\r
+  p->wasCreated = False;\r
+}\r
+\r
+#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }\r
+\r
+static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)\r
+{\r
+  if (p->wasCreated)\r
+    return SZ_OK;\r
+\r
+  RINOK_THREAD(CriticalSection_Init(&p->cs));\r
+  p->csWasInitialized = True;\r
+\r
+  RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart));\r
+  RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted));\r
+  RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped));\r
+  \r
+  RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks));\r
+  RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks));\r
+\r
+  p->needStart = True;\r
+  \r
+  RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj));\r
+  p->wasCreated = True;\r
+  return SZ_OK;\r
+}\r
+\r
+static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)\r
+{\r
+  SRes res = MtSync_Create2(p, startAddress, obj, numBlocks);\r
+  if (res != SZ_OK)\r
+    MtSync_Destruct(p);\r
+  return res;\r
+}\r
+\r
+void MtSync_Init(CMtSync *p) { p->needStart = True; }\r
+\r
+#define kMtMaxValForNormalize 0xFFFFFFFF\r
+\r
+#define DEF_GetHeads2(name, v, action) \\r
+static void GetHeads ## name(const Byte *p, UInt32 pos, \\r
+UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \\r
+{ action; for (; numHeads != 0; numHeads--) { \\r
+const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++;  } }\r
+\r
+#define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;)\r
+\r
+DEF_GetHeads2(2,  (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; )\r
+DEF_GetHeads(3,  (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)\r
+DEF_GetHeads(4,  (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask)\r
+DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)\r
+/* DEF_GetHeads(5,  (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */\r
+\r
+void HashThreadFunc(CMatchFinderMt *mt)\r
+{\r
+  CMtSync *p = &mt->hashSync;\r
+  for (;;)\r
+  {\r
+    UInt32 numProcessedBlocks = 0;\r
+    Event_Wait(&p->canStart);\r
+    Event_Set(&p->wasStarted);\r
+    for (;;)\r
+    {\r
+      if (p->exit)\r
+        return;\r
+      if (p->stopWriting)\r
+      {\r
+        p->numProcessedBlocks = numProcessedBlocks;\r
+        Event_Set(&p->wasStopped);\r
+        break;\r
+      }\r
+\r
+      {\r
+        CMatchFinder *mf = mt->MatchFinder;\r
+        if (MatchFinder_NeedMove(mf))\r
+        {\r
+          CriticalSection_Enter(&mt->btSync.cs);\r
+          CriticalSection_Enter(&mt->hashSync.cs);\r
+          {\r
+            const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf);\r
+            const Byte *afterPtr;\r
+            MatchFinder_MoveBlock(mf);\r
+            afterPtr = MatchFinder_GetPointerToCurrentPos(mf);\r
+            mt->pointerToCurPos -= beforePtr - afterPtr;\r
+            mt->buffer -= beforePtr - afterPtr;\r
+          }\r
+          CriticalSection_Leave(&mt->btSync.cs);\r
+          CriticalSection_Leave(&mt->hashSync.cs);\r
+          continue;\r
+        }\r
+\r
+        Semaphore_Wait(&p->freeSemaphore);\r
+\r
+        MatchFinder_ReadIfRequired(mf);\r
+        if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize))\r
+        {\r
+          UInt32 subValue = (mf->pos - mf->historySize - 1);\r
+          MatchFinder_ReduceOffsets(mf, subValue);\r
+          MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1);\r
+        }\r
+        {\r
+          UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize;\r
+          UInt32 num = mf->streamPos - mf->pos;\r
+          heads[0] = 2;\r
+          heads[1] = num;\r
+          if (num >= mf->numHashBytes)\r
+          {\r
+            num = num - mf->numHashBytes + 1;\r
+            if (num > kMtHashBlockSize - 2)\r
+              num = kMtHashBlockSize - 2;\r
+            mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc);\r
+            heads[0] += num;\r
+          }\r
+          mf->pos += num;\r
+          mf->buffer += num;\r
+        }\r
+      }\r
+\r
+      Semaphore_Release1(&p->filledSemaphore);\r
+    }\r
+  }\r
+}\r
+\r
+void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)\r
+{\r
+  MtSync_GetNextBlock(&p->hashSync);\r
+  p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize;\r
+  p->hashBufPosLimit += p->hashBuf[p->hashBufPos++];\r
+  p->hashNumAvail = p->hashBuf[p->hashBufPos++];\r
+}\r
+\r
+#define kEmptyHashValue 0\r
+\r
+/* #define MFMT_GM_INLINE */\r
+\r
+#ifdef MFMT_GM_INLINE\r
+\r
+#define NO_INLINE MY_FAST_CALL\r
+\r
+Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,\r
+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,\r
+    UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)\r
+{\r
+  do\r
+  {\r
+  UInt32 *distances = _distances + 1;\r
+  UInt32 curMatch = pos - *hash++;\r
+\r
+  CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;\r
+  CLzRef *ptr1 = son + (_cyclicBufferPos << 1);\r
+  UInt32 len0 = 0, len1 = 0;\r
+  UInt32 cutValue = _cutValue;\r
+  UInt32 maxLen = _maxLen;\r
+  for (;;)\r
+  {\r
+    UInt32 delta = pos - curMatch;\r
+    if (cutValue-- == 0 || delta >= _cyclicBufferSize)\r
+    {\r
+      *ptr0 = *ptr1 = kEmptyHashValue;\r
+      break;\r
+    }\r
+    {\r
+      CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);\r
+      const Byte *pb = cur - delta;\r
+      UInt32 len = (len0 < len1 ? len0 : len1);\r
+      if (pb[len] == cur[len])\r
+      {\r
+        if (++len != lenLimit && pb[len] == cur[len])\r
+          while (++len != lenLimit)\r
+            if (pb[len] != cur[len])\r
+              break;\r
+        if (maxLen < len)\r
+        {\r
+          *distances++ = maxLen = len;\r
+          *distances++ = delta - 1;\r
+          if (len == lenLimit)\r
+          {\r
+            *ptr1 = pair[0];\r
+            *ptr0 = pair[1];\r
+            break;\r
+          }\r
+        }\r
+      }\r
+      if (pb[len] < cur[len])\r
+      {\r
+        *ptr1 = curMatch;\r
+        ptr1 = pair + 1;\r
+        curMatch = *ptr1;\r
+        len1 = len;\r
+      }\r
+      else\r
+      {\r
+        *ptr0 = curMatch;\r
+        ptr0 = pair;\r
+        curMatch = *ptr0;\r
+        len0 = len;\r
+      }\r
+    }\r
+  }\r
+  pos++;\r
+  _cyclicBufferPos++;\r
+  cur++;\r
+  {\r
+    UInt32 num = (UInt32)(distances - _distances);\r
+    *_distances = num - 1;\r
+    _distances += num;\r
+    limit -= num;\r
+  }\r
+  }\r
+  while (limit > 0 && --size != 0);\r
+  *posRes = pos;\r
+  return limit;\r
+}\r
+\r
+#endif\r
+\r
+void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)\r
+{\r
+  UInt32 numProcessed = 0;\r
+  UInt32 curPos = 2;\r
+  UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2);\r
+  distances[1] = p->hashNumAvail;\r
+  while (curPos < limit)\r
+  {\r
+    if (p->hashBufPos == p->hashBufPosLimit)\r
+    {\r
+      MatchFinderMt_GetNextBlock_Hash(p);\r
+      distances[1] = numProcessed + p->hashNumAvail;\r
+      if (p->hashNumAvail >= p->numHashBytes)\r
+        continue;\r
+      for (; p->hashNumAvail != 0; p->hashNumAvail--)\r
+        distances[curPos++] = 0;\r
+      break;\r
+    }\r
+    {\r
+      UInt32 size = p->hashBufPosLimit - p->hashBufPos;\r
+      UInt32 lenLimit = p->matchMaxLen;\r
+      UInt32 pos = p->pos;\r
+      UInt32 cyclicBufferPos = p->cyclicBufferPos;\r
+      if (lenLimit >= p->hashNumAvail)\r
+        lenLimit = p->hashNumAvail;\r
+      {\r
+        UInt32 size2 = p->hashNumAvail - lenLimit + 1;\r
+        if (size2 < size)\r
+          size = size2;\r
+        size2 = p->cyclicBufferSize - cyclicBufferPos;\r
+        if (size2 < size)\r
+          size = size2;\r
+      }\r
+      #ifndef MFMT_GM_INLINE\r
+      while (curPos < limit && size-- != 0)\r
+      {\r
+        UInt32 *startDistances = distances + curPos;\r
+        UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++],\r
+          pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,\r
+          startDistances + 1, p->numHashBytes - 1) - startDistances);\r
+        *startDistances = num - 1;\r
+        curPos += num;\r
+        cyclicBufferPos++;\r
+        pos++;\r
+        p->buffer++;\r
+      }\r
+      #else\r
+      {\r
+        UInt32 posRes;\r
+        curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,\r
+          distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes);\r
+        p->hashBufPos += posRes - pos;\r
+        cyclicBufferPos += posRes - pos;\r
+        p->buffer += posRes - pos;\r
+        pos = posRes;\r
+      }\r
+      #endif\r
+\r
+      numProcessed += pos - p->pos;\r
+      p->hashNumAvail -= pos - p->pos;\r
+      p->pos = pos;\r
+      if (cyclicBufferPos == p->cyclicBufferSize)\r
+        cyclicBufferPos = 0;\r
+      p->cyclicBufferPos = cyclicBufferPos;\r
+    }\r
+  }\r
+  distances[0] = curPos;\r
+}\r
+\r
+void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)\r
+{\r
+  CMtSync *sync = &p->hashSync;\r
+  if (!sync->needStart)\r
+  {\r
+    CriticalSection_Enter(&sync->cs);\r
+    sync->csWasEntered = True;\r
+  }\r
+  \r
+  BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize);\r
+\r
+  if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize)\r
+  {\r
+    UInt32 subValue = p->pos - p->cyclicBufferSize;\r
+    MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2);\r
+    p->pos -= subValue;\r
+  }\r
+\r
+  if (!sync->needStart)\r
+  {\r
+    CriticalSection_Leave(&sync->cs);\r
+    sync->csWasEntered = False;\r
+  }\r
+}\r
+\r
+void BtThreadFunc(CMatchFinderMt *mt)\r
+{\r
+  CMtSync *p = &mt->btSync;\r
+  for (;;)\r
+  {\r
+    UInt32 blockIndex = 0;\r
+    Event_Wait(&p->canStart);\r
+    Event_Set(&p->wasStarted);\r
+    for (;;)\r
+    {\r
+      if (p->exit)\r
+        return;\r
+      if (p->stopWriting)\r
+      {\r
+        p->numProcessedBlocks = blockIndex;\r
+        MtSync_StopWriting(&mt->hashSync);\r
+        Event_Set(&p->wasStopped);\r
+        break;\r
+      }\r
+      Semaphore_Wait(&p->freeSemaphore);\r
+      BtFillBlock(mt, blockIndex++);\r
+      Semaphore_Release1(&p->filledSemaphore);\r
+    }\r
+  }\r
+}\r
+\r
+void MatchFinderMt_Construct(CMatchFinderMt *p)\r
+{\r
+  p->hashBuf = 0;\r
+  MtSync_Construct(&p->hashSync);\r
+  MtSync_Construct(&p->btSync);\r
+}\r
+\r
+void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)\r
+{\r
+  alloc->Free(alloc, p->hashBuf);\r
+  p->hashBuf = 0;\r
+}\r
+\r
+void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)\r
+{\r
+  MtSync_Destruct(&p->hashSync);\r
+  MtSync_Destruct(&p->btSync);\r
+  MatchFinderMt_FreeMem(p, alloc);\r
+}\r
+\r
+#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks)\r
+#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks)\r
+\r
+static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p);  return 0; }\r
+static unsigned MY_STD_CALL BtThreadFunc2(void *p)\r
+{\r
+  Byte allocaDummy[0x180];\r
+  int i = 0;\r
+  for (i = 0; i < 16; i++)\r
+    allocaDummy[i] = (Byte)i;\r
+  BtThreadFunc((CMatchFinderMt *)p);\r
+  return 0;\r
+}\r
+\r
+SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,\r
+    UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc)\r
+{\r
+  CMatchFinder *mf = p->MatchFinder;\r
+  p->historySize = historySize;\r
+  if (kMtBtBlockSize <= matchMaxLen * 4)\r
+    return SZ_ERROR_PARAM;\r
+  if (p->hashBuf == 0)\r
+  {\r
+    p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32));\r
+    if (p->hashBuf == 0)\r
+      return SZ_ERROR_MEM;\r
+    p->btBuf = p->hashBuf + kHashBufferSize;\r
+  }\r
+  keepAddBufferBefore += (kHashBufferSize + kBtBufferSize);\r
+  keepAddBufferAfter += kMtHashBlockSize;\r
+  if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc))\r
+    return SZ_ERROR_MEM;\r
+\r
+  RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks));\r
+  RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks));\r
+  return SZ_OK;\r
+}\r
+\r
+/* Call it after ReleaseStream / SetStream */\r
+void MatchFinderMt_Init(CMatchFinderMt *p)\r
+{\r
+  CMatchFinder *mf = p->MatchFinder;\r
+  p->btBufPos = p->btBufPosLimit = 0;\r
+  p->hashBufPos = p->hashBufPosLimit = 0;\r
+  MatchFinder_Init(mf);\r
+  p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf);\r
+  p->btNumAvailBytes = 0;\r
+  p->lzPos = p->historySize + 1;\r
+\r
+  p->hash = mf->hash;\r
+  p->fixedHashSize = mf->fixedHashSize;\r
+  p->crc = mf->crc;\r
+\r
+  p->son = mf->son;\r
+  p->matchMaxLen = mf->matchMaxLen;\r
+  p->numHashBytes = mf->numHashBytes;\r
+  p->pos = mf->pos;\r
+  p->buffer = mf->buffer;\r
+  p->cyclicBufferPos = mf->cyclicBufferPos;\r
+  p->cyclicBufferSize = mf->cyclicBufferSize;\r
+  p->cutValue = mf->cutValue;\r
+}\r
+\r
+/* ReleaseStream is required to finish multithreading */\r
+void MatchFinderMt_ReleaseStream(CMatchFinderMt *p)\r
+{\r
+  MtSync_StopWriting(&p->btSync);\r
+  /* p->MatchFinder->ReleaseStream(); */\r
+}\r
+\r
+void MatchFinderMt_Normalize(CMatchFinderMt *p)\r
+{\r
+  MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize);\r
+  p->lzPos = p->historySize + 1;\r
+}\r
+\r
+void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)\r
+{\r
+  UInt32 blockIndex;\r
+  MtSync_GetNextBlock(&p->btSync);\r
+  blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask);\r
+  p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize;\r
+  p->btBufPosLimit += p->btBuf[p->btBufPos++];\r
+  p->btNumAvailBytes = p->btBuf[p->btBufPos++];\r
+  if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize)\r
+    MatchFinderMt_Normalize(p);\r
+}\r
+\r
+const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)\r
+{\r
+  return p->pointerToCurPos;\r
+}\r
+\r
+#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);\r
+\r
+UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)\r
+{\r
+  GET_NEXT_BLOCK_IF_REQUIRED;\r
+  return p->btNumAvailBytes;\r
+}\r
+\r
+Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index)\r
+{\r
+  return p->pointerToCurPos[index];\r
+}\r
+\r
+UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)\r
+{\r
+  UInt32 hash2Value, curMatch2;\r
+  UInt32 *hash = p->hash;\r
+  const Byte *cur = p->pointerToCurPos;\r
+  UInt32 lzPos = p->lzPos;\r
+  MT_HASH2_CALC\r
+      \r
+  curMatch2 = hash[hash2Value];\r
+  hash[hash2Value] = lzPos;\r
+\r
+  if (curMatch2 >= matchMinPos)\r
+    if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])\r
+    {\r
+      *distances++ = 2;\r
+      *distances++ = lzPos - curMatch2 - 1;\r
+    }\r
+  return distances;\r
+}\r
+\r
+UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)\r
+{\r
+  UInt32 hash2Value, hash3Value, curMatch2, curMatch3;\r
+  UInt32 *hash = p->hash;\r
+  const Byte *cur = p->pointerToCurPos;\r
+  UInt32 lzPos = p->lzPos;\r
+  MT_HASH3_CALC\r
+\r
+  curMatch2 = hash[                hash2Value];\r
+  curMatch3 = hash[kFix3HashSize + hash3Value];\r
+  \r
+  hash[                hash2Value] =\r
+  hash[kFix3HashSize + hash3Value] =\r
+    lzPos;\r
+\r
+  if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])\r
+  {\r
+    distances[1] = lzPos - curMatch2 - 1;\r
+    if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])\r
+    {\r
+      distances[0] = 3;\r
+      return distances + 2;\r
+    }\r
+    distances[0] = 2;\r
+    distances += 2;\r
+  }\r
+  if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])\r
+  {\r
+    *distances++ = 3;\r
+    *distances++ = lzPos - curMatch3 - 1;\r
+  }\r
+  return distances;\r
+}\r
+\r
+/*\r
+UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)\r
+{\r
+  UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4;\r
+  UInt32 *hash = p->hash;\r
+  const Byte *cur = p->pointerToCurPos;\r
+  UInt32 lzPos = p->lzPos;\r
+  MT_HASH4_CALC\r
+      \r
+  curMatch2 = hash[                hash2Value];\r
+  curMatch3 = hash[kFix3HashSize + hash3Value];\r
+  curMatch4 = hash[kFix4HashSize + hash4Value];\r
+  \r
+  hash[                hash2Value] =\r
+  hash[kFix3HashSize + hash3Value] =\r
+  hash[kFix4HashSize + hash4Value] =\r
+    lzPos;\r
+\r
+  if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])\r
+  {\r
+    distances[1] = lzPos - curMatch2 - 1;\r
+    if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])\r
+    {\r
+      distances[0] =  (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;\r
+      return distances + 2;\r
+    }\r
+    distances[0] = 2;\r
+    distances += 2;\r
+  }\r
+  if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])\r
+  {\r
+    distances[1] = lzPos - curMatch3 - 1;\r
+    if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3])\r
+    {\r
+      distances[0] = 4;\r
+      return distances + 2;\r
+    }\r
+    distances[0] = 3;\r
+    distances += 2;\r
+  }\r
+\r
+  if (curMatch4 >= matchMinPos)\r
+    if (\r
+      cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] &&\r
+      cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3]\r
+      )\r
+    {\r
+      *distances++ = 4;\r
+      *distances++ = lzPos - curMatch4 - 1;\r
+    }\r
+  return distances;\r
+}\r
+*/\r
+\r
+#define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++;\r
+\r
+UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)\r
+{\r
+  const UInt32 *btBuf = p->btBuf + p->btBufPos;\r
+  UInt32 len = *btBuf++;\r
+  p->btBufPos += 1 + len;\r
+  p->btNumAvailBytes--;\r
+  {\r
+    UInt32 i;\r
+    for (i = 0; i < len; i += 2)\r
+    {\r
+      *distances++ = *btBuf++;\r
+      *distances++ = *btBuf++;\r
+    }\r
+  }\r
+  INCREASE_LZ_POS\r
+  return len;\r
+}\r
+\r
+UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)\r
+{\r
+  const UInt32 *btBuf = p->btBuf + p->btBufPos;\r
+  UInt32 len = *btBuf++;\r
+  p->btBufPos += 1 + len;\r
+\r
+  if (len == 0)\r
+  {\r
+    if (p->btNumAvailBytes-- >= 4)\r
+      len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances));\r
+  }\r
+  else\r
+  {\r
+    /* Condition: there are matches in btBuf with length < p->numHashBytes */\r
+    UInt32 *distances2;\r
+    p->btNumAvailBytes--;\r
+    distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances);\r
+    do\r
+    {\r
+      *distances2++ = *btBuf++;\r
+      *distances2++ = *btBuf++;\r
+    }\r
+    while ((len -= 2) != 0);\r
+    len  = (UInt32)(distances2 - (distances));\r
+  }\r
+  INCREASE_LZ_POS\r
+  return len;\r
+}\r
+\r
+#define SKIP_HEADER2_MT  do { GET_NEXT_BLOCK_IF_REQUIRED\r
+#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;\r
+#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0);\r
+\r
+void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)\r
+{\r
+  SKIP_HEADER2_MT { p->btNumAvailBytes--;\r
+  SKIP_FOOTER_MT\r
+}\r
+\r
+void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)\r
+{\r
+  SKIP_HEADER_MT(2)\r
+      UInt32 hash2Value;\r
+      MT_HASH2_CALC\r
+      hash[hash2Value] = p->lzPos;\r
+  SKIP_FOOTER_MT\r
+}\r
+\r
+void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)\r
+{\r
+  SKIP_HEADER_MT(3)\r
+      UInt32 hash2Value, hash3Value;\r
+      MT_HASH3_CALC\r
+      hash[kFix3HashSize + hash3Value] =\r
+      hash[                hash2Value] =\r
+        p->lzPos;\r
+  SKIP_FOOTER_MT\r
+}\r
+\r
+/*\r
+void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)\r
+{\r
+  SKIP_HEADER_MT(4)\r
+      UInt32 hash2Value, hash3Value, hash4Value;\r
+      MT_HASH4_CALC\r
+      hash[kFix4HashSize + hash4Value] =\r
+      hash[kFix3HashSize + hash3Value] =\r
+      hash[                hash2Value] =\r
+        p->lzPos;\r
+  SKIP_FOOTER_MT\r
+}\r
+*/\r
+\r
+void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)\r
+{\r
+  vTable->Init = (Mf_Init_Func)MatchFinderMt_Init;\r
+  vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte;\r
+  vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes;\r
+  vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos;\r
+  vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches;\r
+  switch(p->MatchFinder->numHashBytes)\r
+  {\r
+    case 2:\r
+      p->GetHeadsFunc = GetHeads2;\r
+      p->MixMatchesFunc = (Mf_Mix_Matches)0;\r
+      vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip;\r
+      vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches;\r
+      break;\r
+    case 3:\r
+      p->GetHeadsFunc = GetHeads3;\r
+      p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2;\r
+      vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip;\r
+      break;\r
+    default:\r
+    /* case 4: */\r
+      p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4;\r
+      /* p->GetHeadsFunc = GetHeads4; */\r
+      p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3;\r
+      vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip;\r
+      break;\r
+    /*\r
+    default:\r
+      p->GetHeadsFunc = GetHeads5;\r
+      p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4;\r
+      vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip;\r
+      break;\r
+    */\r
+  }\r
+}\r
diff --git a/C/LzFindMt.h b/C/LzFindMt.h
new file mode 100755 (executable)
index 0000000..17ed237
--- /dev/null
@@ -0,0 +1,105 @@
+/* LzFindMt.h -- multithreaded Match finder for LZ algorithms\r
+2009-02-07 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __LZ_FIND_MT_H\r
+#define __LZ_FIND_MT_H\r
+\r
+#include "LzFind.h"\r
+#include "Threads.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#define kMtHashBlockSize (1 << 13)\r
+#define kMtHashNumBlocks (1 << 3)\r
+#define kMtHashNumBlocksMask (kMtHashNumBlocks - 1)\r
+\r
+#define kMtBtBlockSize (1 << 14)\r
+#define kMtBtNumBlocks (1 << 6)\r
+#define kMtBtNumBlocksMask (kMtBtNumBlocks - 1)\r
+\r
+typedef struct _CMtSync\r
+{\r
+  Bool wasCreated;\r
+  Bool needStart;\r
+  Bool exit;\r
+  Bool stopWriting;\r
+\r
+  CThread thread;\r
+  CAutoResetEvent canStart;\r
+  CAutoResetEvent wasStarted;\r
+  CAutoResetEvent wasStopped;\r
+  CSemaphore freeSemaphore;\r
+  CSemaphore filledSemaphore;\r
+  Bool csWasInitialized;\r
+  Bool csWasEntered;\r
+  CCriticalSection cs;\r
+  UInt32 numProcessedBlocks;\r
+} CMtSync;\r
+\r
+typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances);\r
+\r
+/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */\r
+#define kMtCacheLineDummy 128\r
+\r
+typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos,\r
+  UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc);\r
+\r
+typedef struct _CMatchFinderMt\r
+{\r
+  /* LZ */\r
+  const Byte *pointerToCurPos;\r
+  UInt32 *btBuf;\r
+  UInt32 btBufPos;\r
+  UInt32 btBufPosLimit;\r
+  UInt32 lzPos;\r
+  UInt32 btNumAvailBytes;\r
+\r
+  UInt32 *hash;\r
+  UInt32 fixedHashSize;\r
+  UInt32 historySize;\r
+  const UInt32 *crc;\r
+\r
+  Mf_Mix_Matches MixMatchesFunc;\r
+  \r
+  /* LZ + BT */\r
+  CMtSync btSync;\r
+  Byte btDummy[kMtCacheLineDummy];\r
+\r
+  /* BT */\r
+  UInt32 *hashBuf;\r
+  UInt32 hashBufPos;\r
+  UInt32 hashBufPosLimit;\r
+  UInt32 hashNumAvail;\r
+\r
+  CLzRef *son;\r
+  UInt32 matchMaxLen;\r
+  UInt32 numHashBytes;\r
+  UInt32 pos;\r
+  Byte *buffer;\r
+  UInt32 cyclicBufferPos;\r
+  UInt32 cyclicBufferSize; /* it must be historySize + 1 */\r
+  UInt32 cutValue;\r
+\r
+  /* BT + Hash */\r
+  CMtSync hashSync;\r
+  /* Byte hashDummy[kMtCacheLineDummy]; */\r
+  \r
+  /* Hash */\r
+  Mf_GetHeads GetHeadsFunc;\r
+  CMatchFinder *MatchFinder;\r
+} CMatchFinderMt;\r
+\r
+void MatchFinderMt_Construct(CMatchFinderMt *p);\r
+void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc);\r
+SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,\r
+    UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc);\r
+void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable);\r
+void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/C/LzHash.h b/C/LzHash.h
new file mode 100755 (executable)
index 0000000..b2f0e3c
--- /dev/null
@@ -0,0 +1,54 @@
+/* LzHash.h -- HASH functions for LZ algorithms\r
+2009-02-07 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __LZ_HASH_H\r
+#define __LZ_HASH_H\r
+\r
+#define kHash2Size (1 << 10)\r
+#define kHash3Size (1 << 16)\r
+#define kHash4Size (1 << 20)\r
+\r
+#define kFix3HashSize (kHash2Size)\r
+#define kFix4HashSize (kHash2Size + kHash3Size)\r
+#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)\r
+\r
+#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);\r
+\r
+#define HASH3_CALC { \\r
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \\r
+  hash2Value = temp & (kHash2Size - 1); \\r
+  hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }\r
+\r
+#define HASH4_CALC { \\r
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \\r
+  hash2Value = temp & (kHash2Size - 1); \\r
+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \\r
+  hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; }\r
+\r
+#define HASH5_CALC { \\r
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \\r
+  hash2Value = temp & (kHash2Size - 1); \\r
+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \\r
+  hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \\r
+  hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \\r
+  hash4Value &= (kHash4Size - 1); }\r
+\r
+/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */\r
+#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;\r
+\r
+\r
+#define MT_HASH2_CALC \\r
+  hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);\r
+\r
+#define MT_HASH3_CALC { \\r
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \\r
+  hash2Value = temp & (kHash2Size - 1); \\r
+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }\r
+\r
+#define MT_HASH4_CALC { \\r
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \\r
+  hash2Value = temp & (kHash2Size - 1); \\r
+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \\r
+  hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }\r
+\r
+#endif\r
diff --git a/C/Lzma2Dec.c b/C/Lzma2Dec.c
new file mode 100755 (executable)
index 0000000..8f24067
--- /dev/null
@@ -0,0 +1,356 @@
+/* Lzma2Dec.c -- LZMA2 Decoder\r
+2009-05-03 : Igor Pavlov : Public domain */\r
+\r
+/* #define SHOW_DEBUG_INFO */\r
+\r
+#ifdef SHOW_DEBUG_INFO\r
+#include <stdio.h>\r
+#endif\r
+\r
+#include <string.h>\r
+\r
+#include "Lzma2Dec.h"\r
+\r
+/*\r
+00000000  -  EOS\r
+00000001 U U  -  Uncompressed Reset Dic\r
+00000010 U U  -  Uncompressed No Reset\r
+100uuuuu U U P P  -  LZMA no reset\r
+101uuuuu U U P P  -  LZMA reset state\r
+110uuuuu U U P P S  -  LZMA reset state + new prop\r
+111uuuuu U U P P S  -  LZMA reset state + new prop + reset dic\r
+\r
+  u, U - Unpack Size\r
+  P - Pack Size\r
+  S - Props\r
+*/\r
+\r
+#define LZMA2_CONTROL_LZMA (1 << 7)\r
+#define LZMA2_CONTROL_COPY_NO_RESET 2\r
+#define LZMA2_CONTROL_COPY_RESET_DIC 1\r
+#define LZMA2_CONTROL_EOF 0\r
+\r
+#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)\r
+\r
+#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)\r
+#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)\r
+\r
+#define LZMA2_LCLP_MAX 4\r
+#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))\r
+\r
+#ifdef SHOW_DEBUG_INFO\r
+#define PRF(x) x\r
+#else\r
+#define PRF(x)\r
+#endif\r
+\r
+typedef enum\r
+{\r
+  LZMA2_STATE_CONTROL,\r
+  LZMA2_STATE_UNPACK0,\r
+  LZMA2_STATE_UNPACK1,\r
+  LZMA2_STATE_PACK0,\r
+  LZMA2_STATE_PACK1,\r
+  LZMA2_STATE_PROP,\r
+  LZMA2_STATE_DATA,\r
+  LZMA2_STATE_DATA_CONT,\r
+  LZMA2_STATE_FINISHED,\r
+  LZMA2_STATE_ERROR\r
+} ELzma2State;\r
+\r
+static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)\r
+{\r
+  UInt32 dicSize;\r
+  if (prop > 40)\r
+    return SZ_ERROR_UNSUPPORTED;\r
+  dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);\r
+  props[0] = (Byte)LZMA2_LCLP_MAX;\r
+  props[1] = (Byte)(dicSize);\r
+  props[2] = (Byte)(dicSize >> 8);\r
+  props[3] = (Byte)(dicSize >> 16);\r
+  props[4] = (Byte)(dicSize >> 24);\r
+  return SZ_OK;\r
+}\r
+\r
+SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)\r
+{\r
+  Byte props[LZMA_PROPS_SIZE];\r
+  RINOK(Lzma2Dec_GetOldProps(prop, props));\r
+  return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);\r
+}\r
+\r
+SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)\r
+{\r
+  Byte props[LZMA_PROPS_SIZE];\r
+  RINOK(Lzma2Dec_GetOldProps(prop, props));\r
+  return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);\r
+}\r
+\r
+void Lzma2Dec_Init(CLzma2Dec *p)\r
+{\r
+  p->state = LZMA2_STATE_CONTROL;\r
+  p->needInitDic = True;\r
+  p->needInitState = True;\r
+  p->needInitProp = True;\r
+  LzmaDec_Init(&p->decoder);\r
+}\r
+\r
+static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)\r
+{\r
+  switch(p->state)\r
+  {\r
+    case LZMA2_STATE_CONTROL:\r
+      p->control = b;\r
+      PRF(printf("\n %4X ", p->decoder.dicPos));\r
+      PRF(printf(" %2X", b));\r
+      if (p->control == 0)\r
+        return LZMA2_STATE_FINISHED;\r
+      if (LZMA2_IS_UNCOMPRESSED_STATE(p))\r
+      {\r
+        if ((p->control & 0x7F) > 2)\r
+          return LZMA2_STATE_ERROR;\r
+        p->unpackSize = 0;\r
+      }\r
+      else\r
+        p->unpackSize = (UInt32)(p->control & 0x1F) << 16;\r
+      return LZMA2_STATE_UNPACK0;\r
+    \r
+    case LZMA2_STATE_UNPACK0:\r
+      p->unpackSize |= (UInt32)b << 8;\r
+      return LZMA2_STATE_UNPACK1;\r
+    \r
+    case LZMA2_STATE_UNPACK1:\r
+      p->unpackSize |= (UInt32)b;\r
+      p->unpackSize++;\r
+      PRF(printf(" %8d", p->unpackSize));\r
+      return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;\r
+    \r
+    case LZMA2_STATE_PACK0:\r
+      p->packSize = (UInt32)b << 8;\r
+      return LZMA2_STATE_PACK1;\r
+\r
+    case LZMA2_STATE_PACK1:\r
+      p->packSize |= (UInt32)b;\r
+      p->packSize++;\r
+      PRF(printf(" %8d", p->packSize));\r
+      return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:\r
+        (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);\r
+\r
+    case LZMA2_STATE_PROP:\r
+    {\r
+      int lc, lp;\r
+      if (b >= (9 * 5 * 5))\r
+        return LZMA2_STATE_ERROR;\r
+      lc = b % 9;\r
+      b /= 9;\r
+      p->decoder.prop.pb = b / 5;\r
+      lp = b % 5;\r
+      if (lc + lp > LZMA2_LCLP_MAX)\r
+        return LZMA2_STATE_ERROR;\r
+      p->decoder.prop.lc = lc;\r
+      p->decoder.prop.lp = lp;\r
+      p->needInitProp = False;\r
+      return LZMA2_STATE_DATA;\r
+    }\r
+  }\r
+  return LZMA2_STATE_ERROR;\r
+}\r
+\r
+static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)\r
+{\r
+  memcpy(p->dic + p->dicPos, src, size);\r
+  p->dicPos += size;\r
+  if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)\r
+    p->checkDicSize = p->prop.dicSize;\r
+  p->processedPos += (UInt32)size;\r
+}\r
+\r
+void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);\r
+\r
+SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,\r
+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)\r
+{\r
+  SizeT inSize = *srcLen;\r
+  *srcLen = 0;\r
+  *status = LZMA_STATUS_NOT_SPECIFIED;\r
+\r
+  while (p->state != LZMA2_STATE_FINISHED)\r
+  {\r
+    SizeT dicPos = p->decoder.dicPos;\r
+    if (p->state == LZMA2_STATE_ERROR)\r
+      return SZ_ERROR_DATA;\r
+    if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)\r
+    {\r
+      *status = LZMA_STATUS_NOT_FINISHED;\r
+      return SZ_OK;\r
+    }\r
+    if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)\r
+    {\r
+      if (*srcLen == inSize)\r
+      {\r
+        *status = LZMA_STATUS_NEEDS_MORE_INPUT;\r
+        return SZ_OK;\r
+      }\r
+      (*srcLen)++;\r
+      p->state = Lzma2Dec_UpdateState(p, *src++);\r
+      continue;\r
+    }\r
+    {\r
+      SizeT destSizeCur = dicLimit - dicPos;\r
+      SizeT srcSizeCur = inSize - *srcLen;\r
+      ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;\r
+      \r
+      if (p->unpackSize <= destSizeCur)\r
+      {\r
+        destSizeCur = (SizeT)p->unpackSize;\r
+        curFinishMode = LZMA_FINISH_END;\r
+      }\r
+\r
+      if (LZMA2_IS_UNCOMPRESSED_STATE(p))\r
+      {\r
+        if (*srcLen == inSize)\r
+        {\r
+          *status = LZMA_STATUS_NEEDS_MORE_INPUT;\r
+          return SZ_OK;\r
+        }\r
+\r
+        if (p->state == LZMA2_STATE_DATA)\r
+        {\r
+          Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);\r
+          if (initDic)\r
+            p->needInitProp = p->needInitState = True;\r
+          else if (p->needInitDic)\r
+            return SZ_ERROR_DATA;\r
+          p->needInitDic = False;\r
+          LzmaDec_InitDicAndState(&p->decoder, initDic, False);\r
+        }\r
+\r
+        if (srcSizeCur > destSizeCur)\r
+          srcSizeCur = destSizeCur;\r
+\r
+        if (srcSizeCur == 0)\r
+          return SZ_ERROR_DATA;\r
+\r
+        LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);\r
+\r
+        src += srcSizeCur;\r
+        *srcLen += srcSizeCur;\r
+        p->unpackSize -= (UInt32)srcSizeCur;\r
+        p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;\r
+      }\r
+      else\r
+      {\r
+        SizeT outSizeProcessed;\r
+        SRes res;\r
+\r
+        if (p->state == LZMA2_STATE_DATA)\r
+        {\r
+          int mode = LZMA2_GET_LZMA_MODE(p);\r
+          Bool initDic = (mode == 3);\r
+          Bool initState = (mode > 0);\r
+          if ((!initDic && p->needInitDic) || (!initState && p->needInitState))\r
+            return SZ_ERROR_DATA;\r
+          \r
+          LzmaDec_InitDicAndState(&p->decoder, initDic, initState);\r
+          p->needInitDic = False;\r
+          p->needInitState = False;\r
+          p->state = LZMA2_STATE_DATA_CONT;\r
+        }\r
+        if (srcSizeCur > p->packSize)\r
+          srcSizeCur = (SizeT)p->packSize;\r
+          \r
+        res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);\r
+        \r
+        src += srcSizeCur;\r
+        *srcLen += srcSizeCur;\r
+        p->packSize -= (UInt32)srcSizeCur;\r
+\r
+        outSizeProcessed = p->decoder.dicPos - dicPos;\r
+        p->unpackSize -= (UInt32)outSizeProcessed;\r
+\r
+        RINOK(res);\r
+        if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)\r
+          return res;\r
+\r
+        if (srcSizeCur == 0 && outSizeProcessed == 0)\r
+        {\r
+          if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||\r
+              p->unpackSize != 0 || p->packSize != 0)\r
+            return SZ_ERROR_DATA;\r
+          p->state = LZMA2_STATE_CONTROL;\r
+        }\r
+        if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)\r
+          *status = LZMA_STATUS_NOT_FINISHED;\r
+      }\r
+    }\r
+  }\r
+  *status = LZMA_STATUS_FINISHED_WITH_MARK;\r
+  return SZ_OK;\r
+}\r
+\r
+SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)\r
+{\r
+  SizeT outSize = *destLen, inSize = *srcLen;\r
+  *srcLen = *destLen = 0;\r
+  for (;;)\r
+  {\r
+    SizeT srcSizeCur = inSize, outSizeCur, dicPos;\r
+    ELzmaFinishMode curFinishMode;\r
+    SRes res;\r
+    if (p->decoder.dicPos == p->decoder.dicBufSize)\r
+      p->decoder.dicPos = 0;\r
+    dicPos = p->decoder.dicPos;\r
+    if (outSize > p->decoder.dicBufSize - dicPos)\r
+    {\r
+      outSizeCur = p->decoder.dicBufSize;\r
+      curFinishMode = LZMA_FINISH_ANY;\r
+    }\r
+    else\r
+    {\r
+      outSizeCur = dicPos + outSize;\r
+      curFinishMode = finishMode;\r
+    }\r
+\r
+    res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);\r
+    src += srcSizeCur;\r
+    inSize -= srcSizeCur;\r
+    *srcLen += srcSizeCur;\r
+    outSizeCur = p->decoder.dicPos - dicPos;\r
+    memcpy(dest, p->decoder.dic + dicPos, outSizeCur);\r
+    dest += outSizeCur;\r
+    outSize -= outSizeCur;\r
+    *destLen += outSizeCur;\r
+    if (res != 0)\r
+      return res;\r
+    if (outSizeCur == 0 || outSize == 0)\r
+      return SZ_OK;\r
+  }\r
+}\r
+\r
+SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\r
+    Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)\r
+{\r
+  CLzma2Dec decoder;\r
+  SRes res;\r
+  SizeT outSize = *destLen, inSize = *srcLen;\r
+  Byte props[LZMA_PROPS_SIZE];\r
+\r
+  Lzma2Dec_Construct(&decoder);\r
+\r
+  *destLen = *srcLen = 0;\r
+  *status = LZMA_STATUS_NOT_SPECIFIED;\r
+  decoder.decoder.dic = dest;\r
+  decoder.decoder.dicBufSize = outSize;\r
+\r
+  RINOK(Lzma2Dec_GetOldProps(prop, props));\r
+  RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc));\r
+  \r
+  *srcLen = inSize;\r
+  res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status);\r
+  *destLen = decoder.decoder.dicPos;\r
+  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)\r
+    res = SZ_ERROR_INPUT_EOF;\r
+\r
+  LzmaDec_FreeProbs(&decoder.decoder, alloc);\r
+  return res;\r
+}\r
diff --git a/C/Lzma2Dec.h b/C/Lzma2Dec.h
new file mode 100755 (executable)
index 0000000..827698d
--- /dev/null
@@ -0,0 +1,84 @@
+/* Lzma2Dec.h -- LZMA2 Decoder\r
+2009-05-03 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __LZMA2_DEC_H\r
+#define __LZMA2_DEC_H\r
+\r
+#include "LzmaDec.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/* ---------- State Interface ---------- */\r
+\r
+typedef struct\r
+{\r
+  CLzmaDec decoder;\r
+  UInt32 packSize;\r
+  UInt32 unpackSize;\r
+  int state;\r
+  Byte control;\r
+  Bool needInitDic;\r
+  Bool needInitState;\r
+  Bool needInitProp;\r
+} CLzma2Dec;\r
+\r
+#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder)\r
+#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc);\r
+#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc);\r
+\r
+SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);\r
+SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);\r
+void Lzma2Dec_Init(CLzma2Dec *p);\r
+\r
+\r
+/*\r
+finishMode:\r
+  It has meaning only if the decoding reaches output limit (*destLen or dicLimit).\r
+  LZMA_FINISH_ANY - use smallest number of input bytes\r
+  LZMA_FINISH_END - read EndOfStream marker after decoding\r
+\r
+Returns:\r
+  SZ_OK\r
+    status:\r
+      LZMA_STATUS_FINISHED_WITH_MARK\r
+      LZMA_STATUS_NOT_FINISHED\r
+      LZMA_STATUS_NEEDS_MORE_INPUT\r
+  SZ_ERROR_DATA - Data error\r
+*/\r
+\r
+SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,\r
+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);\r
+\r
+SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,\r
+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);\r
+\r
+\r
+/* ---------- One Call Interface ---------- */\r
+\r
+/*\r
+finishMode:\r
+  It has meaning only if the decoding reaches output limit (*destLen).\r
+  LZMA_FINISH_ANY - use smallest number of input bytes\r
+  LZMA_FINISH_END - read EndOfStream marker after decoding\r
+\r
+Returns:\r
+  SZ_OK\r
+    status:\r
+      LZMA_STATUS_FINISHED_WITH_MARK\r
+      LZMA_STATUS_NOT_FINISHED\r
+  SZ_ERROR_DATA - Data error\r
+  SZ_ERROR_MEM  - Memory allocation error\r
+  SZ_ERROR_UNSUPPORTED - Unsupported properties\r
+  SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).\r
+*/\r
+\r
+SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\r
+    Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/C/Lzma2Enc.c b/C/Lzma2Enc.c
new file mode 100755 (executable)
index 0000000..35f6ed7
--- /dev/null
@@ -0,0 +1,477 @@
+/* Lzma2Enc.c -- LZMA2 Encoder\r
+2010-09-24 : Igor Pavlov : Public domain */\r
+\r
+/* #include <stdio.h> */\r
+#include <string.h>\r
+\r
+/* #define _7ZIP_ST */\r
+\r
+#include "Lzma2Enc.h"\r
+\r
+#ifndef _7ZIP_ST\r
+#include "MtCoder.h"\r
+#else\r
+#define NUM_MT_CODER_THREADS_MAX 1\r
+#endif\r
+\r
+#define LZMA2_CONTROL_LZMA (1 << 7)\r
+#define LZMA2_CONTROL_COPY_NO_RESET 2\r
+#define LZMA2_CONTROL_COPY_RESET_DIC 1\r
+#define LZMA2_CONTROL_EOF 0\r
+\r
+#define LZMA2_LCLP_MAX 4\r
+\r
+#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))\r
+\r
+#define LZMA2_PACK_SIZE_MAX (1 << 16)\r
+#define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX\r
+#define LZMA2_UNPACK_SIZE_MAX (1 << 21)\r
+#define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX\r
+\r
+#define LZMA2_CHUNK_SIZE_COMPRESSED_MAX ((1 << 16) + 16)\r
+\r
+\r
+#define PRF(x) /* x */\r
+\r
+/* ---------- CLzma2EncInt ---------- */\r
+\r
+typedef struct\r
+{\r
+  CLzmaEncHandle enc;\r
+  UInt64 srcPos;\r
+  Byte props;\r
+  Bool needInitState;\r
+  Bool needInitProp;\r
+} CLzma2EncInt;\r
+\r
+static SRes Lzma2EncInt_Init(CLzma2EncInt *p, const CLzma2EncProps *props)\r
+{\r
+  Byte propsEncoded[LZMA_PROPS_SIZE];\r
+  SizeT propsSize = LZMA_PROPS_SIZE;\r
+  RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps));\r
+  RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize));\r
+  p->srcPos = 0;\r
+  p->props = propsEncoded[0];\r
+  p->needInitState = True;\r
+  p->needInitProp = True;\r
+  return SZ_OK;\r
+}\r
+\r
+SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize,\r
+    ISzAlloc *alloc, ISzAlloc *allocBig);\r
+SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,\r
+    UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig);\r
+SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,\r
+    Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);\r
+const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp);\r
+void LzmaEnc_Finish(CLzmaEncHandle pp);\r
+void LzmaEnc_SaveState(CLzmaEncHandle pp);\r
+void LzmaEnc_RestoreState(CLzmaEncHandle pp);\r
+\r
+\r
+static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,\r
+    size_t *packSizeRes, ISeqOutStream *outStream)\r
+{\r
+  size_t packSizeLimit = *packSizeRes;\r
+  size_t packSize = packSizeLimit;\r
+  UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX;\r
+  unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0);\r
+  Bool useCopyBlock;\r
+  SRes res;\r
+\r
+  *packSizeRes = 0;\r
+  if (packSize < lzHeaderSize)\r
+    return SZ_ERROR_OUTPUT_EOF;\r
+  packSize -= lzHeaderSize;\r
+  \r
+  LzmaEnc_SaveState(p->enc);\r
+  res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState,\r
+      outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize);\r
+  \r
+  PRF(printf("\npackSize = %7d unpackSize = %7d  ", packSize, unpackSize));\r
+\r
+  if (unpackSize == 0)\r
+    return res;\r
+\r
+  if (res == SZ_OK)\r
+    useCopyBlock = (packSize + 2 >= unpackSize || packSize > (1 << 16));\r
+  else\r
+  {\r
+    if (res != SZ_ERROR_OUTPUT_EOF)\r
+      return res;\r
+    res = SZ_OK;\r
+    useCopyBlock = True;\r
+  }\r
+\r
+  if (useCopyBlock)\r
+  {\r
+    size_t destPos = 0;\r
+    PRF(printf("################# COPY           "));\r
+    while (unpackSize > 0)\r
+    {\r
+      UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE;\r
+      if (packSizeLimit - destPos < u + 3)\r
+        return SZ_ERROR_OUTPUT_EOF;\r
+      outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET);\r
+      outBuf[destPos++] = (Byte)((u - 1) >> 8);\r
+      outBuf[destPos++] = (Byte)(u - 1);\r
+      memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u);\r
+      unpackSize -= u;\r
+      destPos += u;\r
+      p->srcPos += u;\r
+      if (outStream)\r
+      {\r
+        *packSizeRes += destPos;\r
+        if (outStream->Write(outStream, outBuf, destPos) != destPos)\r
+          return SZ_ERROR_WRITE;\r
+        destPos = 0;\r
+      }\r
+      else\r
+        *packSizeRes = destPos;\r
+      /* needInitState = True; */\r
+    }\r
+    LzmaEnc_RestoreState(p->enc);\r
+    return SZ_OK;\r
+  }\r
+  {\r
+    size_t destPos = 0;\r
+    UInt32 u = unpackSize - 1;\r
+    UInt32 pm = (UInt32)(packSize - 1);\r
+    unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0);\r
+\r
+    PRF(printf("               "));\r
+\r
+    outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F));\r
+    outBuf[destPos++] = (Byte)(u >> 8);\r
+    outBuf[destPos++] = (Byte)u;\r
+    outBuf[destPos++] = (Byte)(pm >> 8);\r
+    outBuf[destPos++] = (Byte)pm;\r
+    \r
+    if (p->needInitProp)\r
+      outBuf[destPos++] = p->props;\r
+    \r
+    p->needInitProp = False;\r
+    p->needInitState = False;\r
+    destPos += packSize;\r
+    p->srcPos += unpackSize;\r
+\r
+    if (outStream)\r
+      if (outStream->Write(outStream, outBuf, destPos) != destPos)\r
+        return SZ_ERROR_WRITE;\r
+    *packSizeRes = destPos;\r
+    return SZ_OK;\r
+  }\r
+}\r
+\r
+/* ---------- Lzma2 Props ---------- */\r
+\r
+void Lzma2EncProps_Init(CLzma2EncProps *p)\r
+{\r
+  LzmaEncProps_Init(&p->lzmaProps);\r
+  p->numTotalThreads = -1;\r
+  p->numBlockThreads = -1;\r
+  p->blockSize = 0;\r
+}\r
+\r
+void Lzma2EncProps_Normalize(CLzma2EncProps *p)\r
+{\r
+  int t1, t1n, t2, t3;\r
+  {\r
+    CLzmaEncProps lzmaProps = p->lzmaProps;\r
+    LzmaEncProps_Normalize(&lzmaProps);\r
+    t1n = lzmaProps.numThreads;\r
+  }\r
+\r
+  t1 = p->lzmaProps.numThreads;\r
+  t2 = p->numBlockThreads;\r
+  t3 = p->numTotalThreads;\r
+\r
+  if (t2 > NUM_MT_CODER_THREADS_MAX)\r
+    t2 = NUM_MT_CODER_THREADS_MAX;\r
+\r
+  if (t3 <= 0)\r
+  {\r
+    if (t2 <= 0)\r
+      t2 = 1;\r
+    t3 = t1n * t2;\r
+  }\r
+  else if (t2 <= 0)\r
+  {\r
+    t2 = t3 / t1n;\r
+    if (t2 == 0)\r
+    {\r
+      t1 = 1;\r
+      t2 = t3;\r
+    }\r
+    if (t2 > NUM_MT_CODER_THREADS_MAX)\r
+      t2 = NUM_MT_CODER_THREADS_MAX;\r
+  }\r
+  else if (t1 <= 0)\r
+  {\r
+    t1 = t3 / t2;\r
+    if (t1 == 0)\r
+      t1 = 1;\r
+  }\r
+  else\r
+    t3 = t1n * t2;\r
+\r
+  p->lzmaProps.numThreads = t1;\r
+  p->numBlockThreads = t2;\r
+  p->numTotalThreads = t3;\r
+  LzmaEncProps_Normalize(&p->lzmaProps);\r
+\r
+  if (p->blockSize == 0)\r
+  {\r
+    UInt32 dictSize = p->lzmaProps.dictSize;\r
+    UInt64 blockSize = (UInt64)dictSize << 2;\r
+    const UInt32 kMinSize = (UInt32)1 << 20;\r
+    const UInt32 kMaxSize = (UInt32)1 << 28;\r
+    if (blockSize < kMinSize) blockSize = kMinSize;\r
+    if (blockSize > kMaxSize) blockSize = kMaxSize;\r
+    if (blockSize < dictSize) blockSize = dictSize;\r
+    p->blockSize = (size_t)blockSize;\r
+  }\r
+}\r
+\r
+static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)\r
+{\r
+  return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;\r
+}\r
+\r
+/* ---------- Lzma2 ---------- */\r
+\r
+typedef struct\r
+{\r
+  Byte propEncoded;\r
+  CLzma2EncProps props;\r
+  \r
+  Byte *outBuf;\r
+\r
+  ISzAlloc *alloc;\r
+  ISzAlloc *allocBig;\r
+\r
+  CLzma2EncInt coders[NUM_MT_CODER_THREADS_MAX];\r
+\r
+  #ifndef _7ZIP_ST\r
+  CMtCoder mtCoder;\r
+  #endif\r
+\r
+} CLzma2Enc;\r
+\r
+\r
+/* ---------- Lzma2EncThread ---------- */\r
+\r
+static SRes Lzma2Enc_EncodeMt1(CLzma2EncInt *p, CLzma2Enc *mainEncoder,\r
+  ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)\r
+{\r
+  UInt64 packTotal = 0;\r
+  SRes res = SZ_OK;\r
+\r
+  if (mainEncoder->outBuf == 0)\r
+  {\r
+    mainEncoder->outBuf = (Byte *)IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);\r
+    if (mainEncoder->outBuf == 0)\r
+      return SZ_ERROR_MEM;\r
+  }\r
+  RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));\r
+  RINOK(LzmaEnc_PrepareForLzma2(p->enc, inStream, LZMA2_KEEP_WINDOW_SIZE,\r
+      mainEncoder->alloc, mainEncoder->allocBig));\r
+  for (;;)\r
+  {\r
+    size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;\r
+    res = Lzma2EncInt_EncodeSubblock(p, mainEncoder->outBuf, &packSize, outStream);\r
+    if (res != SZ_OK)\r
+      break;\r
+    packTotal += packSize;\r
+    res = Progress(progress, p->srcPos, packTotal);\r
+    if (res != SZ_OK)\r
+      break;\r
+    if (packSize == 0)\r
+      break;\r
+  }\r
+  LzmaEnc_Finish(p->enc);\r
+  if (res == SZ_OK)\r
+  {\r
+    Byte b = 0;\r
+    if (outStream->Write(outStream, &b, 1) != 1)\r
+      return SZ_ERROR_WRITE;\r
+  }\r
+  return res;\r
+}\r
+\r
+#ifndef _7ZIP_ST\r
+\r
+typedef struct\r
+{\r
+  IMtCoderCallback funcTable;\r
+  CLzma2Enc *lzma2Enc;\r
+} CMtCallbackImp;\r
+\r
+static SRes MtCallbackImp_Code(void *pp, unsigned index, Byte *dest, size_t *destSize,\r
+      const Byte *src, size_t srcSize, int finished)\r
+{\r
+  CMtCallbackImp *imp = (CMtCallbackImp *)pp;\r
+  CLzma2Enc *mainEncoder = imp->lzma2Enc;\r
+  CLzma2EncInt *p = &mainEncoder->coders[index];\r
+\r
+  SRes res = SZ_OK;\r
+  {\r
+    size_t destLim = *destSize;\r
+    *destSize = 0;\r
+\r
+    if (srcSize != 0)\r
+    {\r
+      RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));\r
+     \r
+      RINOK(LzmaEnc_MemPrepare(p->enc, src, srcSize, LZMA2_KEEP_WINDOW_SIZE,\r
+          mainEncoder->alloc, mainEncoder->allocBig));\r
+     \r
+      while (p->srcPos < srcSize)\r
+      {\r
+        size_t packSize = destLim - *destSize;\r
+        res = Lzma2EncInt_EncodeSubblock(p, dest + *destSize, &packSize, NULL);\r
+        if (res != SZ_OK)\r
+          break;\r
+        *destSize += packSize;\r
+\r
+        if (packSize == 0)\r
+        {\r
+          res = SZ_ERROR_FAIL;\r
+          break;\r
+        }\r
+\r
+        if (MtProgress_Set(&mainEncoder->mtCoder.mtProgress, index, p->srcPos, *destSize) != SZ_OK)\r
+        {\r
+          res = SZ_ERROR_PROGRESS;\r
+          break;\r
+        }\r
+      }\r
+      LzmaEnc_Finish(p->enc);\r
+      if (res != SZ_OK)\r
+        return res;\r
+    }\r
+    if (finished)\r
+    {\r
+      if (*destSize == destLim)\r
+        return SZ_ERROR_OUTPUT_EOF;\r
+      dest[(*destSize)++] = 0;\r
+    }\r
+  }\r
+  return res;\r
+}\r
+\r
+#endif\r
+\r
+/* ---------- Lzma2Enc ---------- */\r
+\r
+CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig)\r
+{\r
+  CLzma2Enc *p = (CLzma2Enc *)alloc->Alloc(alloc, sizeof(CLzma2Enc));\r
+  if (p == 0)\r
+    return NULL;\r
+  Lzma2EncProps_Init(&p->props);\r
+  Lzma2EncProps_Normalize(&p->props);\r
+  p->outBuf = 0;\r
+  p->alloc = alloc;\r
+  p->allocBig = allocBig;\r
+  {\r
+    unsigned i;\r
+    for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)\r
+      p->coders[i].enc = 0;\r
+  }\r
+  #ifndef _7ZIP_ST\r
+  MtCoder_Construct(&p->mtCoder);\r
+  #endif\r
+\r
+  return p;\r
+}\r
+\r
+void Lzma2Enc_Destroy(CLzma2EncHandle pp)\r
+{\r
+  CLzma2Enc *p = (CLzma2Enc *)pp;\r
+  unsigned i;\r
+  for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)\r
+  {\r
+    CLzma2EncInt *t = &p->coders[i];\r
+    if (t->enc)\r
+    {\r
+      LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig);\r
+      t->enc = 0;\r
+    }\r
+  }\r
+\r
+  #ifndef _7ZIP_ST\r
+  MtCoder_Destruct(&p->mtCoder);\r
+  #endif\r
+\r
+  IAlloc_Free(p->alloc, p->outBuf);\r
+  IAlloc_Free(p->alloc, pp);\r
+}\r
+\r
+SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props)\r
+{\r
+  CLzma2Enc *p = (CLzma2Enc *)pp;\r
+  CLzmaEncProps lzmaProps = props->lzmaProps;\r
+  LzmaEncProps_Normalize(&lzmaProps);\r
+  if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX)\r
+    return SZ_ERROR_PARAM;\r
+  p->props = *props;\r
+  Lzma2EncProps_Normalize(&p->props);\r
+  return SZ_OK;\r
+}\r
+\r
+Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp)\r
+{\r
+  CLzma2Enc *p = (CLzma2Enc *)pp;\r
+  unsigned i;\r
+  UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps);\r
+  for (i = 0; i < 40; i++)\r
+    if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i))\r
+      break;\r
+  return (Byte)i;\r
+}\r
+\r
+SRes Lzma2Enc_Encode(CLzma2EncHandle pp,\r
+    ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)\r
+{\r
+  CLzma2Enc *p = (CLzma2Enc *)pp;\r
+  int i;\r
+\r
+  for (i = 0; i < p->props.numBlockThreads; i++)\r
+  {\r
+    CLzma2EncInt *t = &p->coders[i];\r
+    if (t->enc == NULL)\r
+    {\r
+      t->enc = LzmaEnc_Create(p->alloc);\r
+      if (t->enc == NULL)\r
+        return SZ_ERROR_MEM;\r
+    }\r
+  }\r
+\r
+  #ifndef _7ZIP_ST\r
+  if (p->props.numBlockThreads <= 1)\r
+  #endif\r
+    return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);\r
+\r
+  #ifndef _7ZIP_ST\r
+\r
+  {\r
+    CMtCallbackImp mtCallback;\r
+\r
+    mtCallback.funcTable.Code = MtCallbackImp_Code;\r
+    mtCallback.lzma2Enc = p;\r
+    \r
+    p->mtCoder.progress = progress;\r
+    p->mtCoder.inStream = inStream;\r
+    p->mtCoder.outStream = outStream;\r
+    p->mtCoder.alloc = p->alloc;\r
+    p->mtCoder.mtCallback = &mtCallback.funcTable;\r
+\r
+    p->mtCoder.blockSize = p->props.blockSize;\r
+    p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16;\r
+    p->mtCoder.numThreads = p->props.numBlockThreads;\r
+    \r
+    return MtCoder_Code(&p->mtCoder);\r
+  }\r
+  #endif\r
+}\r
diff --git a/C/Lzma2Enc.h b/C/Lzma2Enc.h
new file mode 100755 (executable)
index 0000000..38830e5
--- /dev/null
@@ -0,0 +1,66 @@
+/* Lzma2Enc.h -- LZMA2 Encoder\r
+2009-02-07 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __LZMA2_ENC_H\r
+#define __LZMA2_ENC_H\r
+\r
+#include "LzmaEnc.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+typedef struct\r
+{\r
+  CLzmaEncProps lzmaProps;\r
+  size_t blockSize;\r
+  int numBlockThreads;\r
+  int numTotalThreads;\r
+} CLzma2EncProps;\r
+\r
+void Lzma2EncProps_Init(CLzma2EncProps *p);\r
+void Lzma2EncProps_Normalize(CLzma2EncProps *p);\r
+\r
+/* ---------- CLzmaEnc2Handle Interface ---------- */\r
+\r
+/* Lzma2Enc_* functions can return the following exit codes:\r
+Returns:\r
+  SZ_OK           - OK\r
+  SZ_ERROR_MEM    - Memory allocation error\r
+  SZ_ERROR_PARAM  - Incorrect paramater in props\r
+  SZ_ERROR_WRITE  - Write callback error\r
+  SZ_ERROR_PROGRESS - some break from progress callback\r
+  SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)\r
+*/\r
+\r
+typedef void * CLzma2EncHandle;\r
+\r
+CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig);\r
+void Lzma2Enc_Destroy(CLzma2EncHandle p);\r
+SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props);\r
+Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p);\r
+SRes Lzma2Enc_Encode(CLzma2EncHandle p,\r
+    ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress);\r
+\r
+/* ---------- One Call Interface ---------- */\r
+\r
+/* Lzma2Encode\r
+Return code:\r
+  SZ_OK               - OK\r
+  SZ_ERROR_MEM        - Memory allocation error\r
+  SZ_ERROR_PARAM      - Incorrect paramater\r
+  SZ_ERROR_OUTPUT_EOF - output buffer overflow\r
+  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)\r
+*/\r
+\r
+/*\r
+SRes Lzma2Encode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,\r
+    const CLzmaEncProps *props, Byte *propsEncoded, int writeEndMark,\r
+    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);\r
+*/\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/C/Lzma86.h b/C/Lzma86.h
new file mode 100755 (executable)
index 0000000..6425bb8
--- /dev/null
@@ -0,0 +1,111 @@
+/* Lzma86.h -- LZMA + x86 (BCJ) Filter\r
+2009-08-14 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __LZMA86_H\r
+#define __LZMA86_H\r
+\r
+#include "Types.h"\r
+\r
+EXTERN_C_BEGIN\r
+\r
+#define LZMA86_SIZE_OFFSET (1 + 5)\r
+#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8)\r
+\r
+/*\r
+It's an example for LZMA + x86 Filter use.\r
+You can use .lzma86 extension, if you write that stream to file.\r
+.lzma86 header adds one additional byte to standard .lzma header.\r
+.lzma86 header (14 bytes):\r
+  Offset Size  Description\r
+    0     1    = 0 - no filter, pure LZMA\r
+               = 1 - x86 filter + LZMA\r
+    1     1    lc, lp and pb in encoded form\r
+    2     4    dictSize (little endian)\r
+    6     8    uncompressed size (little endian)\r
+\r
+\r
+Lzma86_Encode\r
+-------------\r
+level - compression level: 0 <= level <= 9, the default value for "level" is 5.\r
+\r
+dictSize - The dictionary size in bytes. The maximum value is\r
+        128 MB = (1 << 27) bytes for 32-bit version\r
+          1 GB = (1 << 30) bytes for 64-bit version\r
+     The default value is 16 MB = (1 << 24) bytes, for level = 5.\r
+     It's recommended to use the dictionary that is larger than 4 KB and\r
+     that can be calculated as (1 << N) or (3 << N) sizes.\r
+     For better compression ratio dictSize must be >= inSize.\r
+\r
+filterMode:\r
+    SZ_FILTER_NO   - no Filter\r
+    SZ_FILTER_YES  - x86 Filter\r
+    SZ_FILTER_AUTO - it tries both alternatives to select best.\r
+              Encoder will use 2 or 3 passes:\r
+              2 passes when FILTER_NO provides better compression.\r
+              3 passes when FILTER_YES provides better compression.\r
+\r
+Lzma86Encode allocates Data with MyAlloc functions.\r
+RAM Requirements for compressing:\r
+  RamSize = dictionarySize * 11.5 + 6MB + FilterBlockSize\r
+      filterMode     FilterBlockSize\r
+     SZ_FILTER_NO         0\r
+     SZ_FILTER_YES      inSize\r
+     SZ_FILTER_AUTO     inSize\r
+\r
+\r
+Return code:\r
+  SZ_OK               - OK\r
+  SZ_ERROR_MEM        - Memory allocation error\r
+  SZ_ERROR_PARAM      - Incorrect paramater\r
+  SZ_ERROR_OUTPUT_EOF - output buffer overflow\r
+  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)\r
+*/\r
+\r
+enum ESzFilterMode\r
+{\r
+  SZ_FILTER_NO,\r
+  SZ_FILTER_YES,\r
+  SZ_FILTER_AUTO\r
+};\r
+\r
+SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,\r
+    int level, UInt32 dictSize, int filterMode);\r
+\r
+\r
+/*\r
+Lzma86_GetUnpackSize:\r
+  In:\r
+    src      - input data\r
+    srcLen   - input data size\r
+  Out:\r
+    unpackSize - size of uncompressed stream\r
+  Return code:\r
+    SZ_OK               - OK\r
+    SZ_ERROR_INPUT_EOF  - Error in headers\r
+*/\r
+\r
+SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize);\r
+\r
+/*\r
+Lzma86_Decode:\r
+  In:\r
+    dest     - output data\r
+    destLen  - output data size\r
+    src      - input data\r
+    srcLen   - input data size\r
+  Out:\r
+    destLen  - processed output size\r
+    srcLen   - processed input size\r
+  Return code:\r
+    SZ_OK           - OK\r
+    SZ_ERROR_DATA  - Data error\r
+    SZ_ERROR_MEM   - Memory allocation error\r
+    SZ_ERROR_UNSUPPORTED - unsupported file\r
+    SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer\r
+*/\r
+\r
+SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen);\r
+\r
+EXTERN_C_END\r
+\r
+#endif\r
diff --git a/C/Lzma86Dec.c b/C/Lzma86Dec.c
new file mode 100755 (executable)
index 0000000..760a447
--- /dev/null
@@ -0,0 +1,56 @@
+/* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder\r
+2009-08-14 : Igor Pavlov : Public domain */\r
+\r
+#include "Lzma86.h"\r
+\r
+#include "Alloc.h"\r
+#include "Bra.h"\r
+#include "LzmaDec.h"\r
+\r
+static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }\r
+static void SzFree(void *p, void *address) { p = p; MyFree(address); }\r
+\r
+SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize)\r
+{\r
+  unsigned i;\r
+  if (srcLen < LZMA86_HEADER_SIZE)\r
+    return SZ_ERROR_INPUT_EOF;\r
+  *unpackSize = 0;\r
+  for (i = 0; i < sizeof(UInt64); i++)\r
+    *unpackSize += ((UInt64)src[LZMA86_SIZE_OFFSET + i]) << (8 * i);\r
+  return SZ_OK;\r
+}\r
+\r
+SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen)\r
+{\r
+  ISzAlloc g_Alloc = { SzAlloc, SzFree };\r
+  SRes res;\r
+  int useFilter;\r
+  SizeT inSizePure;\r
+  ELzmaStatus status;\r
+\r
+  if (*srcLen < LZMA86_HEADER_SIZE)\r
+    return SZ_ERROR_INPUT_EOF;\r
+\r
+  useFilter = src[0];\r
+\r
+  if (useFilter > 1)\r
+  {\r
+    *destLen = 0;\r
+    return SZ_ERROR_UNSUPPORTED;\r
+  }\r
+\r
+  inSizePure = *srcLen - LZMA86_HEADER_SIZE;\r
+  res = LzmaDecode(dest, destLen, src + LZMA86_HEADER_SIZE, &inSizePure,\r
+      src + 1, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &g_Alloc);\r
+  *srcLen = inSizePure + LZMA86_HEADER_SIZE;\r
+  if (res != SZ_OK)\r
+    return res;\r
+  if (useFilter == 1)\r
+  {\r
+    UInt32 x86State;\r
+    x86_Convert_Init(x86State);\r
+    x86_Convert(dest, *destLen, 0, &x86State, 0);\r
+  }\r
+  return SZ_OK;\r
+}\r
diff --git a/C/Lzma86Enc.c b/C/Lzma86Enc.c
new file mode 100755 (executable)
index 0000000..a29c605
--- /dev/null
@@ -0,0 +1,108 @@
+/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder\r
+2009-08-14 : Igor Pavlov : Public domain */\r
+\r
+#include <string.h>\r
+\r
+#include "Lzma86.h"\r
+\r
+#include "Alloc.h"\r
+#include "Bra.h"\r
+#include "LzmaEnc.h"\r
+\r
+#define SZE_OUT_OVERFLOW SZE_DATA_ERROR\r
+\r
+static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }\r
+static void SzFree(void *p, void *address) { p = p; MyFree(address); }\r
+\r
+int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,\r
+    int level, UInt32 dictSize, int filterMode)\r
+{\r
+  ISzAlloc g_Alloc = { SzAlloc, SzFree };\r
+  size_t outSize2 = *destLen;\r
+  Byte *filteredStream;\r
+  Bool useFilter;\r
+  int mainResult = SZ_ERROR_OUTPUT_EOF;\r
+  CLzmaEncProps props;\r
+  LzmaEncProps_Init(&props);\r
+  props.level = level;\r
+  props.dictSize = dictSize;\r
+  \r
+  *destLen = 0;\r
+  if (outSize2 < LZMA86_HEADER_SIZE)\r
+    return SZ_ERROR_OUTPUT_EOF;\r
+\r
+  {\r
+    int i;\r
+    UInt64 t = srcLen;\r
+    for (i = 0; i < 8; i++, t >>= 8)\r
+      dest[LZMA86_SIZE_OFFSET + i] = (Byte)t;\r
+  }\r
+\r
+  filteredStream = 0;\r
+  useFilter = (filterMode != SZ_FILTER_NO);\r
+  if (useFilter)\r
+  {\r
+    if (srcLen != 0)\r
+    {\r
+      filteredStream = (Byte *)MyAlloc(srcLen);\r
+      if (filteredStream == 0)\r
+        return SZ_ERROR_MEM;\r
+      memcpy(filteredStream, src, srcLen);\r
+    }\r
+    {\r
+      UInt32 x86State;\r
+      x86_Convert_Init(x86State);\r
+      x86_Convert(filteredStream, srcLen, 0, &x86State, 1);\r
+    }\r
+  }\r
+\r
+  {\r
+    size_t minSize = 0;\r
+    Bool bestIsFiltered = False;\r
+\r
+    /* passes for SZ_FILTER_AUTO:\r
+        0 - BCJ + LZMA\r
+        1 - LZMA\r
+        2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better.\r
+    */\r
+    int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1;\r
+\r
+    int i;\r
+    for (i = 0; i < numPasses; i++)\r
+    {\r
+      size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE;\r
+      size_t outPropsSize = 5;\r
+      SRes curRes;\r
+      Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1);\r
+      if (curModeIsFiltered && !bestIsFiltered)\r
+        break;\r
+      if (useFilter && i == 0)\r
+        curModeIsFiltered = True;\r
+      \r
+      curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed,\r
+          curModeIsFiltered ? filteredStream : src, srcLen,\r
+          &props, dest + 1, &outPropsSize, 0,\r
+          NULL, &g_Alloc, &g_Alloc);\r
+      \r
+      if (curRes != SZ_ERROR_OUTPUT_EOF)\r
+      {\r
+        if (curRes != SZ_OK)\r
+        {\r
+          mainResult = curRes;\r
+          break;\r
+        }\r
+        if (outSizeProcessed <= minSize || mainResult != SZ_OK)\r
+        {\r
+          minSize = outSizeProcessed;\r
+          bestIsFiltered = curModeIsFiltered;\r
+          mainResult = SZ_OK;\r
+        }\r
+      }\r
+    }\r
+    dest[0] = (bestIsFiltered ? 1 : 0);\r
+    *destLen = LZMA86_HEADER_SIZE + minSize;\r
+  }\r
+  if (useFilter)\r
+    MyFree(filteredStream);\r
+  return mainResult;\r
+}\r
diff --git a/C/LzmaDec.c b/C/LzmaDec.c
new file mode 100755 (executable)
index 0000000..4fdc11d
--- /dev/null
@@ -0,0 +1,999 @@
+/* LzmaDec.c -- LZMA Decoder\r
+2009-09-20 : Igor Pavlov : Public domain */\r
+\r
+#include "LzmaDec.h"\r
+\r
+#include <string.h>\r
+\r
+#define kNumTopBits 24\r
+#define kTopValue ((UInt32)1 << kNumTopBits)\r
+\r
+#define kNumBitModelTotalBits 11\r
+#define kBitModelTotal (1 << kNumBitModelTotalBits)\r
+#define kNumMoveBits 5\r
+\r
+#define RC_INIT_SIZE 5\r
+\r
+#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }\r
+\r
+#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)\r
+#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));\r
+#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));\r
+#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \\r
+  { UPDATE_0(p); i = (i + i); A0; } else \\r
+  { UPDATE_1(p); i = (i + i) + 1; A1; }\r
+#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)\r
+\r
+#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }\r
+#define TREE_DECODE(probs, limit, i) \\r
+  { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }\r
+\r
+/* #define _LZMA_SIZE_OPT */\r
+\r
+#ifdef _LZMA_SIZE_OPT\r
+#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)\r
+#else\r
+#define TREE_6_DECODE(probs, i) \\r
+  { i = 1; \\r
+  TREE_GET_BIT(probs, i); \\r
+  TREE_GET_BIT(probs, i); \\r
+  TREE_GET_BIT(probs, i); \\r
+  TREE_GET_BIT(probs, i); \\r
+  TREE_GET_BIT(probs, i); \\r
+  TREE_GET_BIT(probs, i); \\r
+  i -= 0x40; }\r
+#endif\r
+\r
+#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }\r
+\r
+#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)\r
+#define UPDATE_0_CHECK range = bound;\r
+#define UPDATE_1_CHECK range -= bound; code -= bound;\r
+#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \\r
+  { UPDATE_0_CHECK; i = (i + i); A0; } else \\r
+  { UPDATE_1_CHECK; i = (i + i) + 1; A1; }\r
+#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)\r
+#define TREE_DECODE_CHECK(probs, limit, i) \\r
+  { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }\r
+\r
+\r
+#define kNumPosBitsMax 4\r
+#define kNumPosStatesMax (1 << kNumPosBitsMax)\r
+\r
+#define kLenNumLowBits 3\r
+#define kLenNumLowSymbols (1 << kLenNumLowBits)\r
+#define kLenNumMidBits 3\r
+#define kLenNumMidSymbols (1 << kLenNumMidBits)\r
+#define kLenNumHighBits 8\r
+#define kLenNumHighSymbols (1 << kLenNumHighBits)\r
+\r
+#define LenChoice 0\r
+#define LenChoice2 (LenChoice + 1)\r
+#define LenLow (LenChoice2 + 1)\r
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))\r
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))\r
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)\r
+\r
+\r
+#define kNumStates 12\r
+#define kNumLitStates 7\r
+\r
+#define kStartPosModelIndex 4\r
+#define kEndPosModelIndex 14\r
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))\r
+\r
+#define kNumPosSlotBits 6\r
+#define kNumLenToPosStates 4\r
+\r
+#define kNumAlignBits 4\r
+#define kAlignTableSize (1 << kNumAlignBits)\r
+\r
+#define kMatchMinLen 2\r
+#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)\r
+\r
+#define IsMatch 0\r
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))\r
+#define IsRepG0 (IsRep + kNumStates)\r
+#define IsRepG1 (IsRepG0 + kNumStates)\r
+#define IsRepG2 (IsRepG1 + kNumStates)\r
+#define IsRep0Long (IsRepG2 + kNumStates)\r
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))\r
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))\r
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)\r
+#define LenCoder (Align + kAlignTableSize)\r
+#define RepLenCoder (LenCoder + kNumLenProbs)\r
+#define Literal (RepLenCoder + kNumLenProbs)\r
+\r
+#define LZMA_BASE_SIZE 1846\r
+#define LZMA_LIT_SIZE 768\r
+\r
+#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))\r
+\r
+#if Literal != LZMA_BASE_SIZE\r
+StopCompilingDueBUG\r
+#endif\r
+\r
+#define LZMA_DIC_MIN (1 << 12)\r
+\r
+/* First LZMA-symbol is always decoded.\r
+And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization\r
+Out:\r
+  Result:\r
+    SZ_OK - OK\r
+    SZ_ERROR_DATA - Error\r
+  p->remainLen:\r
+    < kMatchSpecLenStart : normal remain\r
+    = kMatchSpecLenStart : finished\r
+    = kMatchSpecLenStart + 1 : Flush marker\r
+    = kMatchSpecLenStart + 2 : State Init Marker\r
+*/\r
+\r
+static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)\r
+{\r
+  CLzmaProb *probs = p->probs;\r
+\r
+  unsigned state = p->state;\r
+  UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];\r
+  unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;\r
+  unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;\r
+  unsigned lc = p->prop.lc;\r
+\r
+  Byte *dic = p->dic;\r
+  SizeT dicBufSize = p->dicBufSize;\r
+  SizeT dicPos = p->dicPos;\r
+  \r
+  UInt32 processedPos = p->processedPos;\r
+  UInt32 checkDicSize = p->checkDicSize;\r
+  unsigned len = 0;\r
+\r
+  const Byte *buf = p->buf;\r
+  UInt32 range = p->range;\r
+  UInt32 code = p->code;\r
+\r
+  do\r
+  {\r
+    CLzmaProb *prob;\r
+    UInt32 bound;\r
+    unsigned ttt;\r
+    unsigned posState = processedPos & pbMask;\r
+\r
+    prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;\r
+    IF_BIT_0(prob)\r
+    {\r
+      unsigned symbol;\r
+      UPDATE_0(prob);\r
+      prob = probs + Literal;\r
+      if (checkDicSize != 0 || processedPos != 0)\r
+        prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +\r
+        (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));\r
+\r
+      if (state < kNumLitStates)\r
+      {\r
+        state -= (state < 4) ? state : 3;\r
+        symbol = 1;\r
+        do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);\r
+      }\r
+      else\r
+      {\r
+        unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];\r
+        unsigned offs = 0x100;\r
+        state -= (state < 10) ? 3 : 6;\r
+        symbol = 1;\r
+        do\r
+        {\r
+          unsigned bit;\r
+          CLzmaProb *probLit;\r
+          matchByte <<= 1;\r
+          bit = (matchByte & offs);\r
+          probLit = prob + offs + bit + symbol;\r
+          GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)\r
+        }\r
+        while (symbol < 0x100);\r
+      }\r
+      dic[dicPos++] = (Byte)symbol;\r
+      processedPos++;\r
+      continue;\r
+    }\r
+    else\r
+    {\r
+      UPDATE_1(prob);\r
+      prob = probs + IsRep + state;\r
+      IF_BIT_0(prob)\r
+      {\r
+        UPDATE_0(prob);\r
+        state += kNumStates;\r
+        prob = probs + LenCoder;\r
+      }\r
+      else\r
+      {\r
+        UPDATE_1(prob);\r
+        if (checkDicSize == 0 && processedPos == 0)\r
+          return SZ_ERROR_DATA;\r
+        prob = probs + IsRepG0 + state;\r
+        IF_BIT_0(prob)\r
+        {\r
+          UPDATE_0(prob);\r
+          prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;\r
+          IF_BIT_0(prob)\r
+          {\r
+            UPDATE_0(prob);\r
+            dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];\r
+            dicPos++;\r
+            processedPos++;\r
+            state = state < kNumLitStates ? 9 : 11;\r
+            continue;\r
+          }\r
+          UPDATE_1(prob);\r
+        }\r
+        else\r
+        {\r
+          UInt32 distance;\r
+          UPDATE_1(prob);\r
+          prob = probs + IsRepG1 + state;\r
+          IF_BIT_0(prob)\r
+          {\r
+            UPDATE_0(prob);\r
+            distance = rep1;\r
+          }\r
+          else\r
+          {\r
+            UPDATE_1(prob);\r
+            prob = probs + IsRepG2 + state;\r
+            IF_BIT_0(prob)\r
+            {\r
+              UPDATE_0(prob);\r
+              distance = rep2;\r
+            }\r
+            else\r
+            {\r
+              UPDATE_1(prob);\r
+              distance = rep3;\r
+              rep3 = rep2;\r
+            }\r
+            rep2 = rep1;\r
+          }\r
+          rep1 = rep0;\r
+          rep0 = distance;\r
+        }\r
+        state = state < kNumLitStates ? 8 : 11;\r
+        prob = probs + RepLenCoder;\r
+      }\r
+      {\r
+        unsigned limit, offset;\r
+        CLzmaProb *probLen = prob + LenChoice;\r
+        IF_BIT_0(probLen)\r
+        {\r
+          UPDATE_0(probLen);\r
+          probLen = prob + LenLow + (posState << kLenNumLowBits);\r
+          offset = 0;\r
+          limit = (1 << kLenNumLowBits);\r
+        }\r
+        else\r
+        {\r
+          UPDATE_1(probLen);\r
+          probLen = prob + LenChoice2;\r
+          IF_BIT_0(probLen)\r
+          {\r
+            UPDATE_0(probLen);\r
+            probLen = prob + LenMid + (posState << kLenNumMidBits);\r
+            offset = kLenNumLowSymbols;\r
+            limit = (1 << kLenNumMidBits);\r
+          }\r
+          else\r
+          {\r
+            UPDATE_1(probLen);\r
+            probLen = prob + LenHigh;\r
+            offset = kLenNumLowSymbols + kLenNumMidSymbols;\r
+            limit = (1 << kLenNumHighBits);\r
+          }\r
+        }\r
+        TREE_DECODE(probLen, limit, len);\r
+        len += offset;\r
+      }\r
+\r
+      if (state >= kNumStates)\r
+      {\r
+        UInt32 distance;\r
+        prob = probs + PosSlot +\r
+            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);\r
+        TREE_6_DECODE(prob, distance);\r
+        if (distance >= kStartPosModelIndex)\r
+        {\r
+          unsigned posSlot = (unsigned)distance;\r
+          int numDirectBits = (int)(((distance >> 1) - 1));\r
+          distance = (2 | (distance & 1));\r
+          if (posSlot < kEndPosModelIndex)\r
+          {\r
+            distance <<= numDirectBits;\r
+            prob = probs + SpecPos + distance - posSlot - 1;\r
+            {\r
+              UInt32 mask = 1;\r
+              unsigned i = 1;\r
+              do\r
+              {\r
+                GET_BIT2(prob + i, i, ; , distance |= mask);\r
+                mask <<= 1;\r
+              }\r
+              while (--numDirectBits != 0);\r
+            }\r
+          }\r
+          else\r
+          {\r
+            numDirectBits -= kNumAlignBits;\r
+            do\r
+            {\r
+              NORMALIZE\r
+              range >>= 1;\r
+              \r
+              {\r
+                UInt32 t;\r
+                code -= range;\r
+                t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */\r
+                distance = (distance << 1) + (t + 1);\r
+                code += range & t;\r
+              }\r
+              /*\r
+              distance <<= 1;\r
+              if (code >= range)\r
+              {\r
+                code -= range;\r
+                distance |= 1;\r
+              }\r
+              */\r
+            }\r
+            while (--numDirectBits != 0);\r
+            prob = probs + Align;\r
+            distance <<= kNumAlignBits;\r
+            {\r
+              unsigned i = 1;\r
+              GET_BIT2(prob + i, i, ; , distance |= 1);\r
+              GET_BIT2(prob + i, i, ; , distance |= 2);\r
+              GET_BIT2(prob + i, i, ; , distance |= 4);\r
+              GET_BIT2(prob + i, i, ; , distance |= 8);\r
+            }\r
+            if (distance == (UInt32)0xFFFFFFFF)\r
+            {\r
+              len += kMatchSpecLenStart;\r
+              state -= kNumStates;\r
+              break;\r
+            }\r
+          }\r
+        }\r
+        rep3 = rep2;\r
+        rep2 = rep1;\r
+        rep1 = rep0;\r
+        rep0 = distance + 1;\r
+        if (checkDicSize == 0)\r
+        {\r
+          if (distance >= processedPos)\r
+            return SZ_ERROR_DATA;\r
+        }\r
+        else if (distance >= checkDicSize)\r
+          return SZ_ERROR_DATA;\r
+        state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;\r
+      }\r
+\r
+      len += kMatchMinLen;\r
+\r
+      if (limit == dicPos)\r
+        return SZ_ERROR_DATA;\r
+      {\r
+        SizeT rem = limit - dicPos;\r
+        unsigned curLen = ((rem < len) ? (unsigned)rem : len);\r
+        SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);\r
+\r
+        processedPos += curLen;\r
+\r
+        len -= curLen;\r
+        if (pos + curLen <= dicBufSize)\r
+        {\r
+          Byte *dest = dic + dicPos;\r
+          ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;\r
+          const Byte *lim = dest + curLen;\r
+          dicPos += curLen;\r
+          do\r
+            *(dest) = (Byte)*(dest + src);\r
+          while (++dest != lim);\r
+        }\r
+        else\r
+        {\r
+          do\r
+          {\r
+            dic[dicPos++] = dic[pos];\r
+            if (++pos == dicBufSize)\r
+              pos = 0;\r
+          }\r
+          while (--curLen != 0);\r
+        }\r
+      }\r
+    }\r
+  }\r
+  while (dicPos < limit && buf < bufLimit);\r
+  NORMALIZE;\r
+  p->buf = buf;\r
+  p->range = range;\r
+  p->code = code;\r
+  p->remainLen = len;\r
+  p->dicPos = dicPos;\r
+  p->processedPos = processedPos;\r
+  p->reps[0] = rep0;\r
+  p->reps[1] = rep1;\r
+  p->reps[2] = rep2;\r
+  p->reps[3] = rep3;\r
+  p->state = state;\r
+\r
+  return SZ_OK;\r
+}\r
+\r
+static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)\r
+{\r
+  if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)\r
+  {\r
+    Byte *dic = p->dic;\r
+    SizeT dicPos = p->dicPos;\r
+    SizeT dicBufSize = p->dicBufSize;\r
+    unsigned len = p->remainLen;\r
+    UInt32 rep0 = p->reps[0];\r
+    if (limit - dicPos < len)\r
+      len = (unsigned)(limit - dicPos);\r
+\r
+    if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)\r
+      p->checkDicSize = p->prop.dicSize;\r
+\r
+    p->processedPos += len;\r
+    p->remainLen -= len;\r
+    while (len-- != 0)\r
+    {\r
+      dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];\r
+      dicPos++;\r
+    }\r
+    p->dicPos = dicPos;\r
+  }\r
+}\r
+\r
+static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)\r
+{\r
+  do\r
+  {\r
+    SizeT limit2 = limit;\r
+    if (p->checkDicSize == 0)\r
+    {\r
+      UInt32 rem = p->prop.dicSize - p->processedPos;\r
+      if (limit - p->dicPos > rem)\r
+        limit2 = p->dicPos + rem;\r
+    }\r
+    RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));\r
+    if (p->processedPos >= p->prop.dicSize)\r
+      p->checkDicSize = p->prop.dicSize;\r
+    LzmaDec_WriteRem(p, limit);\r
+  }\r
+  while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);\r
+\r
+  if (p->remainLen > kMatchSpecLenStart)\r
+  {\r
+    p->remainLen = kMatchSpecLenStart;\r
+  }\r
+  return 0;\r
+}\r
+\r
+typedef enum\r
+{\r
+  DUMMY_ERROR, /* unexpected end of input stream */\r
+  DUMMY_LIT,\r
+  DUMMY_MATCH,\r
+  DUMMY_REP\r
+} ELzmaDummy;\r
+\r
+static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)\r
+{\r
+  UInt32 range = p->range;\r
+  UInt32 code = p->code;\r
+  const Byte *bufLimit = buf + inSize;\r
+  CLzmaProb *probs = p->probs;\r
+  unsigned state = p->state;\r
+  ELzmaDummy res;\r
+\r
+  {\r
+    CLzmaProb *prob;\r
+    UInt32 bound;\r
+    unsigned ttt;\r
+    unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);\r
+\r
+    prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;\r
+    IF_BIT_0_CHECK(prob)\r
+    {\r
+      UPDATE_0_CHECK\r
+\r
+      /* if (bufLimit - buf >= 7) return DUMMY_LIT; */\r
+\r
+      prob = probs + Literal;\r
+      if (p->checkDicSize != 0 || p->processedPos != 0)\r
+        prob += (LZMA_LIT_SIZE *\r
+          ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +\r
+          (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));\r
+\r
+      if (state < kNumLitStates)\r
+      {\r
+        unsigned symbol = 1;\r
+        do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);\r
+      }\r
+      else\r
+      {\r
+        unsigned matchByte = p->dic[p->dicPos - p->reps[0] +\r
+            ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];\r
+        unsigned offs = 0x100;\r
+        unsigned symbol = 1;\r
+        do\r
+        {\r
+          unsigned bit;\r
+          CLzmaProb *probLit;\r
+          matchByte <<= 1;\r
+          bit = (matchByte & offs);\r
+          probLit = prob + offs + bit + symbol;\r
+          GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)\r
+        }\r
+        while (symbol < 0x100);\r
+      }\r
+      res = DUMMY_LIT;\r
+    }\r
+    else\r
+    {\r
+      unsigned len;\r
+      UPDATE_1_CHECK;\r
+\r
+      prob = probs + IsRep + state;\r
+      IF_BIT_0_CHECK(prob)\r
+      {\r
+        UPDATE_0_CHECK;\r
+        state = 0;\r
+        prob = probs + LenCoder;\r
+        res = DUMMY_MATCH;\r
+      }\r
+      else\r
+      {\r
+        UPDATE_1_CHECK;\r
+        res = DUMMY_REP;\r
+        prob = probs + IsRepG0 + state;\r
+        IF_BIT_0_CHECK(prob)\r
+        {\r
+          UPDATE_0_CHECK;\r
+          prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;\r
+          IF_BIT_0_CHECK(prob)\r
+          {\r
+            UPDATE_0_CHECK;\r
+            NORMALIZE_CHECK;\r
+            return DUMMY_REP;\r
+          }\r
+          else\r
+          {\r
+            UPDATE_1_CHECK;\r
+          }\r
+        }\r
+        else\r
+        {\r
+          UPDATE_1_CHECK;\r
+          prob = probs + IsRepG1 + state;\r
+          IF_BIT_0_CHECK(prob)\r
+          {\r
+            UPDATE_0_CHECK;\r
+          }\r
+          else\r
+          {\r
+            UPDATE_1_CHECK;\r
+            prob = probs + IsRepG2 + state;\r
+            IF_BIT_0_CHECK(prob)\r
+            {\r
+              UPDATE_0_CHECK;\r
+            }\r
+            else\r
+            {\r
+              UPDATE_1_CHECK;\r
+            }\r
+          }\r
+        }\r
+        state = kNumStates;\r
+        prob = probs + RepLenCoder;\r
+      }\r
+      {\r
+        unsigned limit, offset;\r
+        CLzmaProb *probLen = prob + LenChoice;\r
+        IF_BIT_0_CHECK(probLen)\r
+        {\r
+          UPDATE_0_CHECK;\r
+          probLen = prob + LenLow + (posState << kLenNumLowBits);\r
+          offset = 0;\r
+          limit = 1 << kLenNumLowBits;\r
+        }\r
+        else\r
+        {\r
+          UPDATE_1_CHECK;\r
+          probLen = prob + LenChoice2;\r
+          IF_BIT_0_CHECK(probLen)\r
+          {\r
+            UPDATE_0_CHECK;\r
+            probLen = prob + LenMid + (posState << kLenNumMidBits);\r
+            offset = kLenNumLowSymbols;\r
+            limit = 1 << kLenNumMidBits;\r
+          }\r
+          else\r
+          {\r
+            UPDATE_1_CHECK;\r
+            probLen = prob + LenHigh;\r
+            offset = kLenNumLowSymbols + kLenNumMidSymbols;\r
+            limit = 1 << kLenNumHighBits;\r
+          }\r
+        }\r
+        TREE_DECODE_CHECK(probLen, limit, len);\r
+        len += offset;\r
+      }\r
+\r
+      if (state < 4)\r
+      {\r
+        unsigned posSlot;\r
+        prob = probs + PosSlot +\r
+            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<\r
+            kNumPosSlotBits);\r
+        TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);\r
+        if (posSlot >= kStartPosModelIndex)\r
+        {\r
+          int numDirectBits = ((posSlot >> 1) - 1);\r
+\r
+          /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */\r
+\r
+          if (posSlot < kEndPosModelIndex)\r
+          {\r
+            prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;\r
+          }\r
+          else\r
+          {\r
+            numDirectBits -= kNumAlignBits;\r
+            do\r
+            {\r
+              NORMALIZE_CHECK\r
+              range >>= 1;\r
+              code -= range & (((code - range) >> 31) - 1);\r
+              /* if (code >= range) code -= range; */\r
+            }\r
+            while (--numDirectBits != 0);\r
+            prob = probs + Align;\r
+            numDirectBits = kNumAlignBits;\r
+          }\r
+          {\r
+            unsigned i = 1;\r
+            do\r
+            {\r
+              GET_BIT_CHECK(prob + i, i);\r
+            }\r
+            while (--numDirectBits != 0);\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+  NORMALIZE_CHECK;\r
+  return res;\r
+}\r
+\r
+\r
+static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)\r
+{\r
+  p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);\r
+  p->range = 0xFFFFFFFF;\r
+  p->needFlush = 0;\r
+}\r
+\r
+void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)\r
+{\r
+  p->needFlush = 1;\r
+  p->remainLen = 0;\r
+  p->tempBufSize = 0;\r
+\r
+  if (initDic)\r
+  {\r
+    p->processedPos = 0;\r
+    p->checkDicSize = 0;\r
+    p->needInitState = 1;\r
+  }\r
+  if (initState)\r
+    p->needInitState = 1;\r
+}\r
+\r
+void LzmaDec_Init(CLzmaDec *p)\r
+{\r
+  p->dicPos = 0;\r
+  LzmaDec_InitDicAndState(p, True, True);\r
+}\r
+\r
+static void LzmaDec_InitStateReal(CLzmaDec *p)\r
+{\r
+  UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));\r
+  UInt32 i;\r
+  CLzmaProb *probs = p->probs;\r
+  for (i = 0; i < numProbs; i++)\r
+    probs[i] = kBitModelTotal >> 1;\r
+  p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;\r
+  p->state = 0;\r
+  p->needInitState = 0;\r
+}\r
+\r
+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,\r
+    ELzmaFinishMode finishMode, ELzmaStatus *status)\r
+{\r
+  SizeT inSize = *srcLen;\r
+  (*srcLen) = 0;\r
+  LzmaDec_WriteRem(p, dicLimit);\r
+  \r
+  *status = LZMA_STATUS_NOT_SPECIFIED;\r
+\r
+  while (p->remainLen != kMatchSpecLenStart)\r
+  {\r
+      int checkEndMarkNow;\r
+\r
+      if (p->needFlush != 0)\r
+      {\r
+        for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)\r
+          p->tempBuf[p->tempBufSize++] = *src++;\r
+        if (p->tempBufSize < RC_INIT_SIZE)\r
+        {\r
+          *status = LZMA_STATUS_NEEDS_MORE_INPUT;\r
+          return SZ_OK;\r
+        }\r
+        if (p->tempBuf[0] != 0)\r
+          return SZ_ERROR_DATA;\r
+\r
+        LzmaDec_InitRc(p, p->tempBuf);\r
+        p->tempBufSize = 0;\r
+      }\r
+\r
+      checkEndMarkNow = 0;\r
+      if (p->dicPos >= dicLimit)\r
+      {\r
+        if (p->remainLen == 0 && p->code == 0)\r
+        {\r
+          *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;\r
+          return SZ_OK;\r
+        }\r
+        if (finishMode == LZMA_FINISH_ANY)\r
+        {\r
+          *status = LZMA_STATUS_NOT_FINISHED;\r
+          return SZ_OK;\r
+        }\r
+        if (p->remainLen != 0)\r
+        {\r
+          *status = LZMA_STATUS_NOT_FINISHED;\r
+          return SZ_ERROR_DATA;\r
+        }\r
+        checkEndMarkNow = 1;\r
+      }\r
+\r
+      if (p->needInitState)\r
+        LzmaDec_InitStateReal(p);\r
+  \r
+      if (p->tempBufSize == 0)\r
+      {\r
+        SizeT processed;\r
+        const Byte *bufLimit;\r
+        if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)\r
+        {\r
+          int dummyRes = LzmaDec_TryDummy(p, src, inSize);\r
+          if (dummyRes == DUMMY_ERROR)\r
+          {\r
+            memcpy(p->tempBuf, src, inSize);\r
+            p->tempBufSize = (unsigned)inSize;\r
+            (*srcLen) += inSize;\r
+            *status = LZMA_STATUS_NEEDS_MORE_INPUT;\r
+            return SZ_OK;\r
+          }\r
+          if (checkEndMarkNow && dummyRes != DUMMY_MATCH)\r
+          {\r
+            *status = LZMA_STATUS_NOT_FINISHED;\r
+            return SZ_ERROR_DATA;\r
+          }\r
+          bufLimit = src;\r
+        }\r
+        else\r
+          bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;\r
+        p->buf = src;\r
+        if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)\r
+          return SZ_ERROR_DATA;\r
+        processed = (SizeT)(p->buf - src);\r
+        (*srcLen) += processed;\r
+        src += processed;\r
+        inSize -= processed;\r
+      }\r
+      else\r
+      {\r
+        unsigned rem = p->tempBufSize, lookAhead = 0;\r
+        while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)\r
+          p->tempBuf[rem++] = src[lookAhead++];\r
+        p->tempBufSize = rem;\r
+        if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)\r
+        {\r
+          int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);\r
+          if (dummyRes == DUMMY_ERROR)\r
+          {\r
+            (*srcLen) += lookAhead;\r
+            *status = LZMA_STATUS_NEEDS_MORE_INPUT;\r
+            return SZ_OK;\r
+          }\r
+          if (checkEndMarkNow && dummyRes != DUMMY_MATCH)\r
+          {\r
+            *status = LZMA_STATUS_NOT_FINISHED;\r
+            return SZ_ERROR_DATA;\r
+          }\r
+        }\r
+        p->buf = p->tempBuf;\r
+        if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)\r
+          return SZ_ERROR_DATA;\r
+        lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));\r
+        (*srcLen) += lookAhead;\r
+        src += lookAhead;\r
+        inSize -= lookAhead;\r
+        p->tempBufSize = 0;\r
+      }\r
+  }\r
+  if (p->code == 0)\r
+    *status = LZMA_STATUS_FINISHED_WITH_MARK;\r
+  return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;\r
+}\r
+\r
+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)\r
+{\r
+  SizeT outSize = *destLen;\r
+  SizeT inSize = *srcLen;\r
+  *srcLen = *destLen = 0;\r
+  for (;;)\r
+  {\r
+    SizeT inSizeCur = inSize, outSizeCur, dicPos;\r
+    ELzmaFinishMode curFinishMode;\r
+    SRes res;\r
+    if (p->dicPos == p->dicBufSize)\r
+      p->dicPos = 0;\r
+    dicPos = p->dicPos;\r
+    if (outSize > p->dicBufSize - dicPos)\r
+    {\r
+      outSizeCur = p->dicBufSize;\r
+      curFinishMode = LZMA_FINISH_ANY;\r
+    }\r
+    else\r
+    {\r
+      outSizeCur = dicPos + outSize;\r
+      curFinishMode = finishMode;\r
+    }\r
+\r
+    res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);\r
+    src += inSizeCur;\r
+    inSize -= inSizeCur;\r
+    *srcLen += inSizeCur;\r
+    outSizeCur = p->dicPos - dicPos;\r
+    memcpy(dest, p->dic + dicPos, outSizeCur);\r
+    dest += outSizeCur;\r
+    outSize -= outSizeCur;\r
+    *destLen += outSizeCur;\r
+    if (res != 0)\r
+      return res;\r
+    if (outSizeCur == 0 || outSize == 0)\r
+      return SZ_OK;\r
+  }\r
+}\r
+\r
+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)\r
+{\r
+  alloc->Free(alloc, p->probs);\r
+  p->probs = 0;\r
+}\r
+\r
+static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)\r
+{\r
+  alloc->Free(alloc, p->dic);\r
+  p->dic = 0;\r
+}\r
+\r
+void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)\r
+{\r
+  LzmaDec_FreeProbs(p, alloc);\r
+  LzmaDec_FreeDict(p, alloc);\r
+}\r
+\r
+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)\r
+{\r
+  UInt32 dicSize;\r
+  Byte d;\r
+  \r
+  if (size < LZMA_PROPS_SIZE)\r
+    return SZ_ERROR_UNSUPPORTED;\r
+  else\r
+    dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);\r
\r
+  if (dicSize < LZMA_DIC_MIN)\r
+    dicSize = LZMA_DIC_MIN;\r
+  p->dicSize = dicSize;\r
+\r
+  d = data[0];\r
+  if (d >= (9 * 5 * 5))\r
+    return SZ_ERROR_UNSUPPORTED;\r
+\r
+  p->lc = d % 9;\r
+  d /= 9;\r
+  p->pb = d / 5;\r
+  p->lp = d % 5;\r
+\r
+  return SZ_OK;\r
+}\r
+\r
+static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)\r
+{\r
+  UInt32 numProbs = LzmaProps_GetNumProbs(propNew);\r
+  if (p->probs == 0 || numProbs != p->numProbs)\r
+  {\r
+    LzmaDec_FreeProbs(p, alloc);\r
+    p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));\r
+    p->numProbs = numProbs;\r
+    if (p->probs == 0)\r
+      return SZ_ERROR_MEM;\r
+  }\r
+  return SZ_OK;\r
+}\r
+\r
+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)\r
+{\r
+  CLzmaProps propNew;\r
+  RINOK(LzmaProps_Decode(&propNew, props, propsSize));\r
+  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));\r
+  p->prop = propNew;\r
+  return SZ_OK;\r
+}\r
+\r
+SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)\r
+{\r
+  CLzmaProps propNew;\r
+  SizeT dicBufSize;\r
+  RINOK(LzmaProps_Decode(&propNew, props, propsSize));\r
+  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));\r
+  dicBufSize = propNew.dicSize;\r
+  if (p->dic == 0 || dicBufSize != p->dicBufSize)\r
+  {\r
+    LzmaDec_FreeDict(p, alloc);\r
+    p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);\r
+    if (p->dic == 0)\r
+    {\r
+      LzmaDec_FreeProbs(p, alloc);\r
+      return SZ_ERROR_MEM;\r
+    }\r
+  }\r
+  p->dicBufSize = dicBufSize;\r
+  p->prop = propNew;\r
+  return SZ_OK;\r
+}\r
+\r
+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\r
+    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,\r
+    ELzmaStatus *status, ISzAlloc *alloc)\r
+{\r
+  CLzmaDec p;\r
+  SRes res;\r
+  SizeT inSize = *srcLen;\r
+  SizeT outSize = *destLen;\r
+  *srcLen = *destLen = 0;\r
+  if (inSize < RC_INIT_SIZE)\r
+    return SZ_ERROR_INPUT_EOF;\r
+\r
+  LzmaDec_Construct(&p);\r
+  res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);\r
+  if (res != 0)\r
+    return res;\r
+  p.dic = dest;\r
+  p.dicBufSize = outSize;\r
+\r
+  LzmaDec_Init(&p);\r
+  \r
+  *srcLen = inSize;\r
+  res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);\r
+\r
+  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)\r
+    res = SZ_ERROR_INPUT_EOF;\r
+\r
+  (*destLen) = p.dicPos;\r
+  LzmaDec_FreeProbs(&p, alloc);\r
+  return res;\r
+}\r
diff --git a/C/LzmaDec.h b/C/LzmaDec.h
new file mode 100755 (executable)
index 0000000..6741a64
--- /dev/null
@@ -0,0 +1,231 @@
+/* LzmaDec.h -- LZMA Decoder\r
+2009-02-07 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __LZMA_DEC_H\r
+#define __LZMA_DEC_H\r
+\r
+#include "Types.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/* #define _LZMA_PROB32 */\r
+/* _LZMA_PROB32 can increase the speed on some CPUs,\r
+   but memory usage for CLzmaDec::probs will be doubled in that case */\r
+\r
+#ifdef _LZMA_PROB32\r
+#define CLzmaProb UInt32\r
+#else\r
+#define CLzmaProb UInt16\r
+#endif\r
+\r
+\r
+/* ---------- LZMA Properties ---------- */\r
+\r
+#define LZMA_PROPS_SIZE 5\r
+\r
+typedef struct _CLzmaProps\r
+{\r
+  unsigned lc, lp, pb;\r
+  UInt32 dicSize;\r
+} CLzmaProps;\r
+\r
+/* LzmaProps_Decode - decodes properties\r
+Returns:\r
+  SZ_OK\r
+  SZ_ERROR_UNSUPPORTED - Unsupported properties\r
+*/\r
+\r
+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);\r
+\r
+\r
+/* ---------- LZMA Decoder state ---------- */\r
+\r
+/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.\r
+   Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */\r
+\r
+#define LZMA_REQUIRED_INPUT_MAX 20\r
+\r
+typedef struct\r
+{\r
+  CLzmaProps prop;\r
+  CLzmaProb *probs;\r
+  Byte *dic;\r
+  const Byte *buf;\r
+  UInt32 range, code;\r
+  SizeT dicPos;\r
+  SizeT dicBufSize;\r
+  UInt32 processedPos;\r
+  UInt32 checkDicSize;\r
+  unsigned state;\r
+  UInt32 reps[4];\r
+  unsigned remainLen;\r
+  int needFlush;\r
+  int needInitState;\r
+  UInt32 numProbs;\r
+  unsigned tempBufSize;\r
+  Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];\r
+} CLzmaDec;\r
+\r
+#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }\r
+\r
+void LzmaDec_Init(CLzmaDec *p);\r
+\r
+/* There are two types of LZMA streams:\r
+     0) Stream with end mark. That end mark adds about 6 bytes to compressed size.\r
+     1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */\r
+\r
+typedef enum\r
+{\r
+  LZMA_FINISH_ANY,   /* finish at any point */\r
+  LZMA_FINISH_END    /* block must be finished at the end */\r
+} ELzmaFinishMode;\r
+\r
+/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!\r
+\r
+   You must use LZMA_FINISH_END, when you know that current output buffer\r
+   covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.\r
+\r
+   If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,\r
+   and output value of destLen will be less than output buffer size limit.\r
+   You can check status result also.\r
+\r
+   You can use multiple checks to test data integrity after full decompression:\r
+     1) Check Result and "status" variable.\r
+     2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.\r
+     3) Check that output(srcLen) = compressedSize, if you know real compressedSize.\r
+        You must use correct finish mode in that case. */\r
+\r
+typedef enum\r
+{\r
+  LZMA_STATUS_NOT_SPECIFIED,               /* use main error code instead */\r
+  LZMA_STATUS_FINISHED_WITH_MARK,          /* stream was finished with end mark. */\r
+  LZMA_STATUS_NOT_FINISHED,                /* stream was not finished */\r
+  LZMA_STATUS_NEEDS_MORE_INPUT,            /* you must provide more input bytes */\r
+  LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK  /* there is probability that stream was finished without end mark */\r
+} ELzmaStatus;\r
+\r
+/* ELzmaStatus is used only as output value for function call */\r
+\r
+\r
+/* ---------- Interfaces ---------- */\r
+\r
+/* There are 3 levels of interfaces:\r
+     1) Dictionary Interface\r
+     2) Buffer Interface\r
+     3) One Call Interface\r
+   You can select any of these interfaces, but don't mix functions from different\r
+   groups for same object. */\r
+\r
+\r
+/* There are two variants to allocate state for Dictionary Interface:\r
+     1) LzmaDec_Allocate / LzmaDec_Free\r
+     2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs\r
+   You can use variant 2, if you set dictionary buffer manually.\r
+   For Buffer Interface you must always use variant 1.\r
+\r
+LzmaDec_Allocate* can return:\r
+  SZ_OK\r
+  SZ_ERROR_MEM         - Memory allocation error\r
+  SZ_ERROR_UNSUPPORTED - Unsupported properties\r
+*/\r
+   \r
+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);\r
+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);\r
+\r
+SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);\r
+void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);\r
+\r
+/* ---------- Dictionary Interface ---------- */\r
+\r
+/* You can use it, if you want to eliminate the overhead for data copying from\r
+   dictionary to some other external buffer.\r
+   You must work with CLzmaDec variables directly in this interface.\r
+\r
+   STEPS:\r
+     LzmaDec_Constr()\r
+     LzmaDec_Allocate()\r
+     for (each new stream)\r
+     {\r
+       LzmaDec_Init()\r
+       while (it needs more decompression)\r
+       {\r
+         LzmaDec_DecodeToDic()\r
+         use data from CLzmaDec::dic and update CLzmaDec::dicPos\r
+       }\r
+     }\r
+     LzmaDec_Free()\r
+*/\r
+\r
+/* LzmaDec_DecodeToDic\r
+   \r
+   The decoding to internal dictionary buffer (CLzmaDec::dic).\r
+   You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!\r
+\r
+finishMode:\r
+  It has meaning only if the decoding reaches output limit (dicLimit).\r
+  LZMA_FINISH_ANY - Decode just dicLimit bytes.\r
+  LZMA_FINISH_END - Stream must be finished after dicLimit.\r
+\r
+Returns:\r
+  SZ_OK\r
+    status:\r
+      LZMA_STATUS_FINISHED_WITH_MARK\r
+      LZMA_STATUS_NOT_FINISHED\r
+      LZMA_STATUS_NEEDS_MORE_INPUT\r
+      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK\r
+  SZ_ERROR_DATA - Data error\r
+*/\r
+\r
+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,\r
+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);\r
+\r
+\r
+/* ---------- Buffer Interface ---------- */\r
+\r
+/* It's zlib-like interface.\r
+   See LzmaDec_DecodeToDic description for information about STEPS and return results,\r
+   but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need\r
+   to work with CLzmaDec variables manually.\r
+\r
+finishMode:\r
+  It has meaning only if the decoding reaches output limit (*destLen).\r
+  LZMA_FINISH_ANY - Decode just destLen bytes.\r
+  LZMA_FINISH_END - Stream must be finished after (*destLen).\r
+*/\r
+\r
+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,\r
+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);\r
+\r
+\r
+/* ---------- One Call Interface ---------- */\r
+\r
+/* LzmaDecode\r
+\r
+finishMode:\r
+  It has meaning only if the decoding reaches output limit (*destLen).\r
+  LZMA_FINISH_ANY - Decode just destLen bytes.\r
+  LZMA_FINISH_END - Stream must be finished after (*destLen).\r
+\r
+Returns:\r
+  SZ_OK\r
+    status:\r
+      LZMA_STATUS_FINISHED_WITH_MARK\r
+      LZMA_STATUS_NOT_FINISHED\r
+      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK\r
+  SZ_ERROR_DATA - Data error\r
+  SZ_ERROR_MEM  - Memory allocation error\r
+  SZ_ERROR_UNSUPPORTED - Unsupported properties\r
+  SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).\r
+*/\r
+\r
+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\r
+    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,\r
+    ELzmaStatus *status, ISzAlloc *alloc);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/C/LzmaEnc.c b/C/LzmaEnc.c
new file mode 100755 (executable)
index 0000000..9e6dbdb
--- /dev/null
@@ -0,0 +1,2268 @@
+/* LzmaEnc.c -- LZMA Encoder\r
+2010-04-16 : Igor Pavlov : Public domain */\r
+\r
+#include <string.h>\r
+\r
+/* #define SHOW_STAT */\r
+/* #define SHOW_STAT2 */\r
+\r
+#if defined(SHOW_STAT) || defined(SHOW_STAT2)\r
+#include <stdio.h>\r
+#endif\r
+\r
+#include "LzmaEnc.h"\r
+\r
+#include "LzFind.h"\r
+#ifndef _7ZIP_ST\r
+#include "LzFindMt.h"\r
+#endif\r
+\r
+#ifdef SHOW_STAT\r
+static int ttt = 0;\r
+#endif\r
+\r
+#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)\r
+\r
+#define kBlockSize (9 << 10)\r
+#define kUnpackBlockSize (1 << 18)\r
+#define kMatchArraySize (1 << 21)\r
+#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX)\r
+\r
+#define kNumMaxDirectBits (31)\r
+\r
+#define kNumTopBits 24\r
+#define kTopValue ((UInt32)1 << kNumTopBits)\r
+\r
+#define kNumBitModelTotalBits 11\r
+#define kBitModelTotal (1 << kNumBitModelTotalBits)\r
+#define kNumMoveBits 5\r
+#define kProbInitValue (kBitModelTotal >> 1)\r
+\r
+#define kNumMoveReducingBits 4\r
+#define kNumBitPriceShiftBits 4\r
+#define kBitPrice (1 << kNumBitPriceShiftBits)\r
+\r
+void LzmaEncProps_Init(CLzmaEncProps *p)\r
+{\r
+  p->level = 5;\r
+  p->dictSize = p->mc = 0;\r
+  p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;\r
+  p->writeEndMark = 0;\r
+}\r
+\r
+void LzmaEncProps_Normalize(CLzmaEncProps *p)\r
+{\r
+  int level = p->level;\r
+  if (level < 0) level = 5;\r
+  p->level = level;\r
+  if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));\r
+  if (p->lc < 0) p->lc = 3;\r
+  if (p->lp < 0) p->lp = 0;\r
+  if (p->pb < 0) p->pb = 2;\r
+  if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);\r
+  if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);\r
+  if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);\r
+  if (p->numHashBytes < 0) p->numHashBytes = 4;\r
+  if (p->mc == 0)  p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);\r
+  if (p->numThreads < 0)\r
+    p->numThreads =\r
+      #ifndef _7ZIP_ST\r
+      ((p->btMode && p->algo) ? 2 : 1);\r
+      #else\r
+      1;\r
+      #endif\r
+}\r
+\r
+UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)\r
+{\r
+  CLzmaEncProps props = *props2;\r
+  LzmaEncProps_Normalize(&props);\r
+  return props.dictSize;\r
+}\r
+\r
+/* #define LZMA_LOG_BSR */\r
+/* Define it for Intel's CPU */\r
+\r
+\r
+#ifdef LZMA_LOG_BSR\r
+\r
+#define kDicLogSizeMaxCompress 30\r
+\r
+#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); }\r
+\r
+UInt32 GetPosSlot1(UInt32 pos)\r
+{\r
+  UInt32 res;\r
+  BSR2_RET(pos, res);\r
+  return res;\r
+}\r
+#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }\r
+#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }\r
+\r
+#else\r
+\r
+#define kNumLogBits (9 + (int)sizeof(size_t) / 2)\r
+#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)\r
+\r
+void LzmaEnc_FastPosInit(Byte *g_FastPos)\r
+{\r
+  int c = 2, slotFast;\r
+  g_FastPos[0] = 0;\r
+  g_FastPos[1] = 1;\r
+  \r
+  for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++)\r
+  {\r
+    UInt32 k = (1 << ((slotFast >> 1) - 1));\r
+    UInt32 j;\r
+    for (j = 0; j < k; j++, c++)\r
+      g_FastPos[c] = (Byte)slotFast;\r
+  }\r
+}\r
+\r
+#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \\r
+  (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \\r
+  res = p->g_FastPos[pos >> i] + (i * 2); }\r
+/*\r
+#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \\r
+  p->g_FastPos[pos >> 6] + 12 : \\r
+  p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }\r
+*/\r
+\r
+#define GetPosSlot1(pos) p->g_FastPos[pos]\r
+#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }\r
+#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); }\r
+\r
+#endif\r
+\r
+\r
+#define LZMA_NUM_REPS 4\r
+\r
+typedef unsigned CState;\r
+\r
+typedef struct\r
+{\r
+  UInt32 price;\r
+\r
+  CState state;\r
+  int prev1IsChar;\r
+  int prev2;\r
+\r
+  UInt32 posPrev2;\r
+  UInt32 backPrev2;\r
+\r
+  UInt32 posPrev;\r
+  UInt32 backPrev;\r
+  UInt32 backs[LZMA_NUM_REPS];\r
+} COptimal;\r
+\r
+#define kNumOpts (1 << 12)\r
+\r
+#define kNumLenToPosStates 4\r
+#define kNumPosSlotBits 6\r
+#define kDicLogSizeMin 0\r
+#define kDicLogSizeMax 32\r
+#define kDistTableSizeMax (kDicLogSizeMax * 2)\r
+\r
+\r
+#define kNumAlignBits 4\r
+#define kAlignTableSize (1 << kNumAlignBits)\r
+#define kAlignMask (kAlignTableSize - 1)\r
+\r
+#define kStartPosModelIndex 4\r
+#define kEndPosModelIndex 14\r
+#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)\r
+\r
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))\r
+\r
+#ifdef _LZMA_PROB32\r
+#define CLzmaProb UInt32\r
+#else\r
+#define CLzmaProb UInt16\r
+#endif\r
+\r
+#define LZMA_PB_MAX 4\r
+#define LZMA_LC_MAX 8\r
+#define LZMA_LP_MAX 4\r
+\r
+#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)\r
+\r
+\r
+#define kLenNumLowBits 3\r
+#define kLenNumLowSymbols (1 << kLenNumLowBits)\r
+#define kLenNumMidBits 3\r
+#define kLenNumMidSymbols (1 << kLenNumMidBits)\r
+#define kLenNumHighBits 8\r
+#define kLenNumHighSymbols (1 << kLenNumHighBits)\r
+\r
+#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)\r
+\r
+#define LZMA_MATCH_LEN_MIN 2\r
+#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)\r
+\r
+#define kNumStates 12\r
+\r
+typedef struct\r
+{\r
+  CLzmaProb choice;\r
+  CLzmaProb choice2;\r
+  CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits];\r
+  CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits];\r
+  CLzmaProb high[kLenNumHighSymbols];\r
+} CLenEnc;\r
+\r
+typedef struct\r
+{\r
+  CLenEnc p;\r
+  UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];\r
+  UInt32 tableSize;\r
+  UInt32 counters[LZMA_NUM_PB_STATES_MAX];\r
+} CLenPriceEnc;\r
+\r
+typedef struct\r
+{\r
+  UInt32 range;\r
+  Byte cache;\r
+  UInt64 low;\r
+  UInt64 cacheSize;\r
+  Byte *buf;\r
+  Byte *bufLim;\r
+  Byte *bufBase;\r
+  ISeqOutStream *outStream;\r
+  UInt64 processed;\r
+  SRes res;\r
+} CRangeEnc;\r
+\r
+typedef struct\r
+{\r
+  CLzmaProb *litProbs;\r
+\r
+  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];\r
+  CLzmaProb isRep[kNumStates];\r
+  CLzmaProb isRepG0[kNumStates];\r
+  CLzmaProb isRepG1[kNumStates];\r
+  CLzmaProb isRepG2[kNumStates];\r
+  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];\r
+\r
+  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];\r
+  CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];\r
+  CLzmaProb posAlignEncoder[1 << kNumAlignBits];\r
+  \r
+  CLenPriceEnc lenEnc;\r
+  CLenPriceEnc repLenEnc;\r
+\r
+  UInt32 reps[LZMA_NUM_REPS];\r
+  UInt32 state;\r
+} CSaveState;\r
+\r
+typedef struct\r
+{\r
+  IMatchFinder matchFinder;\r
+  void *matchFinderObj;\r
+\r
+  #ifndef _7ZIP_ST\r
+  Bool mtMode;\r
+  CMatchFinderMt matchFinderMt;\r
+  #endif\r
+\r
+  CMatchFinder matchFinderBase;\r
+\r
+  #ifndef _7ZIP_ST\r
+  Byte pad[128];\r
+  #endif\r
+  \r
+  UInt32 optimumEndIndex;\r
+  UInt32 optimumCurrentIndex;\r
+\r
+  UInt32 longestMatchLength;\r
+  UInt32 numPairs;\r
+  UInt32 numAvail;\r
+  COptimal opt[kNumOpts];\r
+  \r
+  #ifndef LZMA_LOG_BSR\r
+  Byte g_FastPos[1 << kNumLogBits];\r
+  #endif\r
+\r
+  UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];\r
+  UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];\r
+  UInt32 numFastBytes;\r
+  UInt32 additionalOffset;\r
+  UInt32 reps[LZMA_NUM_REPS];\r
+  UInt32 state;\r
+\r
+  UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];\r
+  UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];\r
+  UInt32 alignPrices[kAlignTableSize];\r
+  UInt32 alignPriceCount;\r
+\r
+  UInt32 distTableSize;\r
+\r
+  unsigned lc, lp, pb;\r
+  unsigned lpMask, pbMask;\r
+\r
+  CLzmaProb *litProbs;\r
+\r
+  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];\r
+  CLzmaProb isRep[kNumStates];\r
+  CLzmaProb isRepG0[kNumStates];\r
+  CLzmaProb isRepG1[kNumStates];\r
+  CLzmaProb isRepG2[kNumStates];\r
+  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];\r
+\r
+  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];\r
+  CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];\r
+  CLzmaProb posAlignEncoder[1 << kNumAlignBits];\r
+  \r
+  CLenPriceEnc lenEnc;\r
+  CLenPriceEnc repLenEnc;\r
+\r
+  unsigned lclp;\r
+\r
+  Bool fastMode;\r
+  \r
+  CRangeEnc rc;\r
+\r
+  Bool writeEndMark;\r
+  UInt64 nowPos64;\r
+  UInt32 matchPriceCount;\r
+  Bool finished;\r
+  Bool multiThread;\r
+\r
+  SRes result;\r
+  UInt32 dictSize;\r
+  UInt32 matchFinderCycles;\r
+\r
+  int needInit;\r
+\r
+  CSaveState saveState;\r
+} CLzmaEnc;\r
+\r
+void LzmaEnc_SaveState(CLzmaEncHandle pp)\r
+{\r
+  CLzmaEnc *p = (CLzmaEnc *)pp;\r
+  CSaveState *dest = &p->saveState;\r
+  int i;\r
+  dest->lenEnc = p->lenEnc;\r
+  dest->repLenEnc = p->repLenEnc;\r
+  dest->state = p->state;\r
+\r
+  for (i = 0; i < kNumStates; i++)\r
+  {\r
+    memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));\r
+    memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));\r
+  }\r
+  for (i = 0; i < kNumLenToPosStates; i++)\r
+    memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));\r
+  memcpy(dest->isRep, p->isRep, sizeof(p->isRep));\r
+  memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));\r
+  memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));\r
+  memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));\r
+  memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));\r
+  memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));\r
+  memcpy(dest->reps, p->reps, sizeof(p->reps));\r
+  memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb));\r
+}\r
+\r
+void LzmaEnc_RestoreState(CLzmaEncHandle pp)\r
+{\r
+  CLzmaEnc *dest = (CLzmaEnc *)pp;\r
+  const CSaveState *p = &dest->saveState;\r
+  int i;\r
+  dest->lenEnc = p->lenEnc;\r
+  dest->repLenEnc = p->repLenEnc;\r
+  dest->state = p->state;\r
+\r
+  for (i = 0; i < kNumStates; i++)\r
+  {\r
+    memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));\r
+    memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));\r
+  }\r
+  for (i = 0; i < kNumLenToPosStates; i++)\r
+    memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));\r
+  memcpy(dest->isRep, p->isRep, sizeof(p->isRep));\r
+  memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));\r
+  memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));\r
+  memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));\r
+  memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));\r
+  memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));\r
+  memcpy(dest->reps, p->reps, sizeof(p->reps));\r
+  memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb));\r
+}\r
+\r
+SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)\r
+{\r
+  CLzmaEnc *p = (CLzmaEnc *)pp;\r
+  CLzmaEncProps props = *props2;\r
+  LzmaEncProps_Normalize(&props);\r
+\r
+  if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX ||\r
+      props.dictSize > ((UInt32)1 << kDicLogSizeMaxCompress) || props.dictSize > ((UInt32)1 << 30))\r
+    return SZ_ERROR_PARAM;\r
+  p->dictSize = props.dictSize;\r
+  p->matchFinderCycles = props.mc;\r
+  {\r
+    unsigned fb = props.fb;\r
+    if (fb < 5)\r
+      fb = 5;\r
+    if (fb > LZMA_MATCH_LEN_MAX)\r
+      fb = LZMA_MATCH_LEN_MAX;\r
+    p->numFastBytes = fb;\r
+  }\r
+  p->lc = props.lc;\r
+  p->lp = props.lp;\r
+  p->pb = props.pb;\r
+  p->fastMode = (props.algo == 0);\r
+  p->matchFinderBase.btMode = props.btMode;\r
+  {\r
+    UInt32 numHashBytes = 4;\r
+    if (props.btMode)\r
+    {\r
+      if (props.numHashBytes < 2)\r
+        numHashBytes = 2;\r
+      else if (props.numHashBytes < 4)\r
+        numHashBytes = props.numHashBytes;\r
+    }\r
+    p->matchFinderBase.numHashBytes = numHashBytes;\r
+  }\r
+\r
+  p->matchFinderBase.cutValue = props.mc;\r
+\r
+  p->writeEndMark = props.writeEndMark;\r
+\r
+  #ifndef _7ZIP_ST\r
+  /*\r
+  if (newMultiThread != _multiThread)\r
+  {\r
+    ReleaseMatchFinder();\r
+    _multiThread = newMultiThread;\r
+  }\r
+  */\r
+  p->multiThread = (props.numThreads > 1);\r
+  #endif\r
+\r
+  return SZ_OK;\r
+}\r
+\r
+static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};\r
+static const int kMatchNextStates[kNumStates]   = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};\r
+static const int kRepNextStates[kNumStates]     = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};\r
+static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};\r
+\r
+#define IsCharState(s) ((s) < 7)\r
+\r
+#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)\r
+\r
+#define kInfinityPrice (1 << 30)\r
+\r
+static void RangeEnc_Construct(CRangeEnc *p)\r
+{\r
+  p->outStream = 0;\r
+  p->bufBase = 0;\r
+}\r
+\r
+#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)\r
+\r
+#define RC_BUF_SIZE (1 << 16)\r
+static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)\r
+{\r
+  if (p->bufBase == 0)\r
+  {\r
+    p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);\r
+    if (p->bufBase == 0)\r
+      return 0;\r
+    p->bufLim = p->bufBase + RC_BUF_SIZE;\r
+  }\r
+  return 1;\r
+}\r
+\r
+static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc)\r
+{\r
+  alloc->Free(alloc, p->bufBase);\r
+  p->bufBase = 0;\r
+}\r
+\r
+static void RangeEnc_Init(CRangeEnc *p)\r
+{\r
+  /* Stream.Init(); */\r
+  p->low = 0;\r
+  p->range = 0xFFFFFFFF;\r
+  p->cacheSize = 1;\r
+  p->cache = 0;\r
+\r
+  p->buf = p->bufBase;\r
+\r
+  p->processed = 0;\r
+  p->res = SZ_OK;\r
+}\r
+\r
+static void RangeEnc_FlushStream(CRangeEnc *p)\r
+{\r
+  size_t num;\r
+  if (p->res != SZ_OK)\r
+    return;\r
+  num = p->buf - p->bufBase;\r
+  if (num != p->outStream->Write(p->outStream, p->bufBase, num))\r
+    p->res = SZ_ERROR_WRITE;\r
+  p->processed += num;\r
+  p->buf = p->bufBase;\r
+}\r
+\r
+static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)\r
+{\r
+  if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0)\r
+  {\r
+    Byte temp = p->cache;\r
+    do\r
+    {\r
+      Byte *buf = p->buf;\r
+      *buf++ = (Byte)(temp + (Byte)(p->low >> 32));\r
+      p->buf = buf;\r
+      if (buf == p->bufLim)\r
+        RangeEnc_FlushStream(p);\r
+      temp = 0xFF;\r
+    }\r
+    while (--p->cacheSize != 0);\r
+    p->cache = (Byte)((UInt32)p->low >> 24);\r
+  }\r
+  p->cacheSize++;\r
+  p->low = (UInt32)p->low << 8;\r
+}\r
+\r
+static void RangeEnc_FlushData(CRangeEnc *p)\r
+{\r
+  int i;\r
+  for (i = 0; i < 5; i++)\r
+    RangeEnc_ShiftLow(p);\r
+}\r
+\r
+static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits)\r
+{\r
+  do\r
+  {\r
+    p->range >>= 1;\r
+    p->low += p->range & (0 - ((value >> --numBits) & 1));\r
+    if (p->range < kTopValue)\r
+    {\r
+      p->range <<= 8;\r
+      RangeEnc_ShiftLow(p);\r
+    }\r
+  }\r
+  while (numBits != 0);\r
+}\r
+\r
+static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol)\r
+{\r
+  UInt32 ttt = *prob;\r
+  UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt;\r
+  if (symbol == 0)\r
+  {\r
+    p->range = newBound;\r
+    ttt += (kBitModelTotal - ttt) >> kNumMoveBits;\r
+  }\r
+  else\r
+  {\r
+    p->low += newBound;\r
+    p->range -= newBound;\r
+    ttt -= ttt >> kNumMoveBits;\r
+  }\r
+  *prob = (CLzmaProb)ttt;\r
+  if (p->range < kTopValue)\r
+  {\r
+    p->range <<= 8;\r
+    RangeEnc_ShiftLow(p);\r
+  }\r
+}\r
+\r
+static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)\r
+{\r
+  symbol |= 0x100;\r
+  do\r
+  {\r
+    RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);\r
+    symbol <<= 1;\r
+  }\r
+  while (symbol < 0x10000);\r
+}\r
+\r
+static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)\r
+{\r
+  UInt32 offs = 0x100;\r
+  symbol |= 0x100;\r
+  do\r
+  {\r
+    matchByte <<= 1;\r
+    RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);\r
+    symbol <<= 1;\r
+    offs &= ~(matchByte ^ symbol);\r
+  }\r
+  while (symbol < 0x10000);\r
+}\r
+\r
+void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)\r
+{\r
+  UInt32 i;\r
+  for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))\r
+  {\r
+    const int kCyclesBits = kNumBitPriceShiftBits;\r
+    UInt32 w = i;\r
+    UInt32 bitCount = 0;\r
+    int j;\r
+    for (j = 0; j < kCyclesBits; j++)\r
+    {\r
+      w = w * w;\r
+      bitCount <<= 1;\r
+      while (w >= ((UInt32)1 << 16))\r
+      {\r
+        w >>= 1;\r
+        bitCount++;\r
+      }\r
+    }\r
+    ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);\r
+  }\r
+}\r
+\r
+\r
+#define GET_PRICE(prob, symbol) \\r
+  p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];\r
+\r
+#define GET_PRICEa(prob, symbol) \\r
+  ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];\r
+\r
+#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]\r
+#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]\r
+\r
+#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]\r
+#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]\r
+\r
+static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices)\r
+{\r
+  UInt32 price = 0;\r
+  symbol |= 0x100;\r
+  do\r
+  {\r
+    price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1);\r
+    symbol <<= 1;\r
+  }\r
+  while (symbol < 0x10000);\r
+  return price;\r
+}\r
+\r
+static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices)\r
+{\r
+  UInt32 price = 0;\r
+  UInt32 offs = 0x100;\r
+  symbol |= 0x100;\r
+  do\r
+  {\r
+    matchByte <<= 1;\r
+    price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1);\r
+    symbol <<= 1;\r
+    offs &= ~(matchByte ^ symbol);\r
+  }\r
+  while (symbol < 0x10000);\r
+  return price;\r
+}\r
+\r
+\r
+static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)\r
+{\r
+  UInt32 m = 1;\r
+  int i;\r
+  for (i = numBitLevels; i != 0;)\r
+  {\r
+    UInt32 bit;\r
+    i--;\r
+    bit = (symbol >> i) & 1;\r
+    RangeEnc_EncodeBit(rc, probs + m, bit);\r
+    m = (m << 1) | bit;\r
+  }\r
+}\r
+\r
+static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)\r
+{\r
+  UInt32 m = 1;\r
+  int i;\r
+  for (i = 0; i < numBitLevels; i++)\r
+  {\r
+    UInt32 bit = symbol & 1;\r
+    RangeEnc_EncodeBit(rc, probs + m, bit);\r
+    m = (m << 1) | bit;\r
+    symbol >>= 1;\r
+  }\r
+}\r
+\r
+static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)\r
+{\r
+  UInt32 price = 0;\r
+  symbol |= (1 << numBitLevels);\r
+  while (symbol != 1)\r
+  {\r
+    price += GET_PRICEa(probs[symbol >> 1], symbol & 1);\r
+    symbol >>= 1;\r
+  }\r
+  return price;\r
+}\r
+\r
+static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)\r
+{\r
+  UInt32 price = 0;\r
+  UInt32 m = 1;\r
+  int i;\r
+  for (i = numBitLevels; i != 0; i--)\r
+  {\r
+    UInt32 bit = symbol & 1;\r
+    symbol >>= 1;\r
+    price += GET_PRICEa(probs[m], bit);\r
+    m = (m << 1) | bit;\r
+  }\r
+  return price;\r
+}\r
+\r
+\r
+static void LenEnc_Init(CLenEnc *p)\r
+{\r
+  unsigned i;\r
+  p->choice = p->choice2 = kProbInitValue;\r
+  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++)\r
+    p->low[i] = kProbInitValue;\r
+  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++)\r
+    p->mid[i] = kProbInitValue;\r
+  for (i = 0; i < kLenNumHighSymbols; i++)\r
+    p->high[i] = kProbInitValue;\r
+}\r
+\r
+static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState)\r
+{\r
+  if (symbol < kLenNumLowSymbols)\r
+  {\r
+    RangeEnc_EncodeBit(rc, &p->choice, 0);\r
+    RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol);\r
+  }\r
+  else\r
+  {\r
+    RangeEnc_EncodeBit(rc, &p->choice, 1);\r
+    if (symbol < kLenNumLowSymbols + kLenNumMidSymbols)\r
+    {\r
+      RangeEnc_EncodeBit(rc, &p->choice2, 0);\r
+      RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols);\r
+    }\r
+    else\r
+    {\r
+      RangeEnc_EncodeBit(rc, &p->choice2, 1);\r
+      RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols);\r
+    }\r
+  }\r
+}\r
+\r
+static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices)\r
+{\r
+  UInt32 a0 = GET_PRICE_0a(p->choice);\r
+  UInt32 a1 = GET_PRICE_1a(p->choice);\r
+  UInt32 b0 = a1 + GET_PRICE_0a(p->choice2);\r
+  UInt32 b1 = a1 + GET_PRICE_1a(p->choice2);\r
+  UInt32 i = 0;\r
+  for (i = 0; i < kLenNumLowSymbols; i++)\r
+  {\r
+    if (i >= numSymbols)\r
+      return;\r
+    prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices);\r
+  }\r
+  for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++)\r
+  {\r
+    if (i >= numSymbols)\r
+      return;\r
+    prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices);\r
+  }\r
+  for (; i < numSymbols; i++)\r
+    prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);\r
+}\r
+\r
+static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices)\r
+{\r
+  LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);\r
+  p->counters[posState] = p->tableSize;\r
+}\r
+\r
+static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices)\r
+{\r
+  UInt32 posState;\r
+  for (posState = 0; posState < numPosStates; posState++)\r
+    LenPriceEnc_UpdateTable(p, posState, ProbPrices);\r
+}\r
+\r
+static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices)\r
+{\r
+  LenEnc_Encode(&p->p, rc, symbol, posState);\r
+  if (updatePrice)\r
+    if (--p->counters[posState] == 0)\r
+      LenPriceEnc_UpdateTable(p, posState, ProbPrices);\r
+}\r
+\r
+\r
+\r
+\r
+static void MovePos(CLzmaEnc *p, UInt32 num)\r
+{\r
+  #ifdef SHOW_STAT\r
+  ttt += num;\r
+  printf("\n MovePos %d", num);\r
+  #endif\r
+  if (num != 0)\r
+  {\r
+    p->additionalOffset += num;\r
+    p->matchFinder.Skip(p->matchFinderObj, num);\r
+  }\r
+}\r
+\r
+static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)\r
+{\r
+  UInt32 lenRes = 0, numPairs;\r
+  p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);\r
+  numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);\r
+  #ifdef SHOW_STAT\r
+  printf("\n i = %d numPairs = %d    ", ttt, numPairs / 2);\r
+  ttt++;\r
+  {\r
+    UInt32 i;\r
+    for (i = 0; i < numPairs; i += 2)\r
+      printf("%2d %6d   | ", p->matches[i], p->matches[i + 1]);\r
+  }\r
+  #endif\r
+  if (numPairs > 0)\r
+  {\r
+    lenRes = p->matches[numPairs - 2];\r
+    if (lenRes == p->numFastBytes)\r
+    {\r
+      const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\r
+      UInt32 distance = p->matches[numPairs - 1] + 1;\r
+      UInt32 numAvail = p->numAvail;\r
+      if (numAvail > LZMA_MATCH_LEN_MAX)\r
+        numAvail = LZMA_MATCH_LEN_MAX;\r
+      {\r
+        const Byte *pby2 = pby - distance;\r
+        for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++);\r
+      }\r
+    }\r
+  }\r
+  p->additionalOffset++;\r
+  *numDistancePairsRes = numPairs;\r
+  return lenRes;\r
+}\r
+\r
+\r
+#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False;\r
+#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False;\r
+#define IsShortRep(p) ((p)->backPrev == 0)\r
+\r
+static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState)\r
+{\r
+  return\r
+    GET_PRICE_0(p->isRepG0[state]) +\r
+    GET_PRICE_0(p->isRep0Long[state][posState]);\r
+}\r
+\r
+static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState)\r
+{\r
+  UInt32 price;\r
+  if (repIndex == 0)\r
+  {\r
+    price = GET_PRICE_0(p->isRepG0[state]);\r
+    price += GET_PRICE_1(p->isRep0Long[state][posState]);\r
+  }\r
+  else\r
+  {\r
+    price = GET_PRICE_1(p->isRepG0[state]);\r
+    if (repIndex == 1)\r
+      price += GET_PRICE_0(p->isRepG1[state]);\r
+    else\r
+    {\r
+      price += GET_PRICE_1(p->isRepG1[state]);\r
+      price += GET_PRICE(p->isRepG2[state], repIndex - 2);\r
+    }\r
+  }\r
+  return price;\r
+}\r
+\r
+static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState)\r
+{\r
+  return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] +\r
+    GetPureRepPrice(p, repIndex, state, posState);\r
+}\r
+\r
+static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)\r
+{\r
+  UInt32 posMem = p->opt[cur].posPrev;\r
+  UInt32 backMem = p->opt[cur].backPrev;\r
+  p->optimumEndIndex = cur;\r
+  do\r
+  {\r
+    if (p->opt[cur].prev1IsChar)\r
+    {\r
+      MakeAsChar(&p->opt[posMem])\r
+      p->opt[posMem].posPrev = posMem - 1;\r
+      if (p->opt[cur].prev2)\r
+      {\r
+        p->opt[posMem - 1].prev1IsChar = False;\r
+        p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2;\r
+        p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2;\r
+      }\r
+    }\r
+    {\r
+      UInt32 posPrev = posMem;\r
+      UInt32 backCur = backMem;\r
+      \r
+      backMem = p->opt[posPrev].backPrev;\r
+      posMem = p->opt[posPrev].posPrev;\r
+      \r
+      p->opt[posPrev].backPrev = backCur;\r
+      p->opt[posPrev].posPrev = cur;\r
+      cur = posPrev;\r
+    }\r
+  }\r
+  while (cur != 0);\r
+  *backRes = p->opt[0].backPrev;\r
+  p->optimumCurrentIndex  = p->opt[0].posPrev;\r
+  return p->optimumCurrentIndex;\r
+}\r
+\r
+#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300)\r
+\r
+static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)\r
+{\r
+  UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur;\r
+  UInt32 matchPrice, repMatchPrice, normalMatchPrice;\r
+  UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS];\r
+  UInt32 *matches;\r
+  const Byte *data;\r
+  Byte curByte, matchByte;\r
+  if (p->optimumEndIndex != p->optimumCurrentIndex)\r
+  {\r
+    const COptimal *opt = &p->opt[p->optimumCurrentIndex];\r
+    UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex;\r
+    *backRes = opt->backPrev;\r
+    p->optimumCurrentIndex = opt->posPrev;\r
+    return lenRes;\r
+  }\r
+  p->optimumCurrentIndex = p->optimumEndIndex = 0;\r
+  \r
+  if (p->additionalOffset == 0)\r
+    mainLen = ReadMatchDistances(p, &numPairs);\r
+  else\r
+  {\r
+    mainLen = p->longestMatchLength;\r
+    numPairs = p->numPairs;\r
+  }\r
+\r
+  numAvail = p->numAvail;\r
+  if (numAvail < 2)\r
+  {\r
+    *backRes = (UInt32)(-1);\r
+    return 1;\r
+  }\r
+  if (numAvail > LZMA_MATCH_LEN_MAX)\r
+    numAvail = LZMA_MATCH_LEN_MAX;\r
+\r
+  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\r
+  repMaxIndex = 0;\r
+  for (i = 0; i < LZMA_NUM_REPS; i++)\r
+  {\r
+    UInt32 lenTest;\r
+    const Byte *data2;\r
+    reps[i] = p->reps[i];\r
+    data2 = data - (reps[i] + 1);\r
+    if (data[0] != data2[0] || data[1] != data2[1])\r
+    {\r
+      repLens[i] = 0;\r
+      continue;\r
+    }\r
+    for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);\r
+    repLens[i] = lenTest;\r
+    if (lenTest > repLens[repMaxIndex])\r
+      repMaxIndex = i;\r
+  }\r
+  if (repLens[repMaxIndex] >= p->numFastBytes)\r
+  {\r
+    UInt32 lenRes;\r
+    *backRes = repMaxIndex;\r
+    lenRes = repLens[repMaxIndex];\r
+    MovePos(p, lenRes - 1);\r
+    return lenRes;\r
+  }\r
+\r
+  matches = p->matches;\r
+  if (mainLen >= p->numFastBytes)\r
+  {\r
+    *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;\r
+    MovePos(p, mainLen - 1);\r
+    return mainLen;\r
+  }\r
+  curByte = *data;\r
+  matchByte = *(data - (reps[0] + 1));\r
+\r
+  if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)\r
+  {\r
+    *backRes = (UInt32)-1;\r
+    return 1;\r
+  }\r
+\r
+  p->opt[0].state = (CState)p->state;\r
+\r
+  posState = (position & p->pbMask);\r
+\r
+  {\r
+    const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));\r
+    p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +\r
+        (!IsCharState(p->state) ?\r
+          LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :\r
+          LitEnc_GetPrice(probs, curByte, p->ProbPrices));\r
+  }\r
+\r
+  MakeAsChar(&p->opt[1]);\r
+\r
+  matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);\r
+  repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);\r
+\r
+  if (matchByte == curByte)\r
+  {\r
+    UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState);\r
+    if (shortRepPrice < p->opt[1].price)\r
+    {\r
+      p->opt[1].price = shortRepPrice;\r
+      MakeAsShortRep(&p->opt[1]);\r
+    }\r
+  }\r
+  lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]);\r
+\r
+  if (lenEnd < 2)\r
+  {\r
+    *backRes = p->opt[1].backPrev;\r
+    return 1;\r
+  }\r
+\r
+  p->opt[1].posPrev = 0;\r
+  for (i = 0; i < LZMA_NUM_REPS; i++)\r
+    p->opt[0].backs[i] = reps[i];\r
+\r
+  len = lenEnd;\r
+  do\r
+    p->opt[len--].price = kInfinityPrice;\r
+  while (len >= 2);\r
+\r
+  for (i = 0; i < LZMA_NUM_REPS; i++)\r
+  {\r
+    UInt32 repLen = repLens[i];\r
+    UInt32 price;\r
+    if (repLen < 2)\r
+      continue;\r
+    price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState);\r
+    do\r
+    {\r
+      UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2];\r
+      COptimal *opt = &p->opt[repLen];\r
+      if (curAndLenPrice < opt->price)\r
+      {\r
+        opt->price = curAndLenPrice;\r
+        opt->posPrev = 0;\r
+        opt->backPrev = i;\r
+        opt->prev1IsChar = False;\r
+      }\r
+    }\r
+    while (--repLen >= 2);\r
+  }\r
+\r
+  normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);\r
+\r
+  len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);\r
+  if (len <= mainLen)\r
+  {\r
+    UInt32 offs = 0;\r
+    while (len > matches[offs])\r
+      offs += 2;\r
+    for (; ; len++)\r
+    {\r
+      COptimal *opt;\r
+      UInt32 distance = matches[offs + 1];\r
+\r
+      UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN];\r
+      UInt32 lenToPosState = GetLenToPosState(len);\r
+      if (distance < kNumFullDistances)\r
+        curAndLenPrice += p->distancesPrices[lenToPosState][distance];\r
+      else\r
+      {\r
+        UInt32 slot;\r
+        GetPosSlot2(distance, slot);\r
+        curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot];\r
+      }\r
+      opt = &p->opt[len];\r
+      if (curAndLenPrice < opt->price)\r
+      {\r
+        opt->price = curAndLenPrice;\r
+        opt->posPrev = 0;\r
+        opt->backPrev = distance + LZMA_NUM_REPS;\r
+        opt->prev1IsChar = False;\r
+      }\r
+      if (len == matches[offs])\r
+      {\r
+        offs += 2;\r
+        if (offs == numPairs)\r
+          break;\r
+      }\r
+    }\r
+  }\r
+\r
+  cur = 0;\r
+\r
+    #ifdef SHOW_STAT2\r
+    if (position >= 0)\r
+    {\r
+      unsigned i;\r
+      printf("\n pos = %4X", position);\r
+      for (i = cur; i <= lenEnd; i++)\r
+      printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price);\r
+    }\r
+    #endif\r
+\r
+  for (;;)\r
+  {\r
+    UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen;\r
+    UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice;\r
+    Bool nextIsChar;\r
+    Byte curByte, matchByte;\r
+    const Byte *data;\r
+    COptimal *curOpt;\r
+    COptimal *nextOpt;\r
+\r
+    cur++;\r
+    if (cur == lenEnd)\r
+      return Backward(p, backRes, cur);\r
+\r
+    newLen = ReadMatchDistances(p, &numPairs);\r
+    if (newLen >= p->numFastBytes)\r
+    {\r
+      p->numPairs = numPairs;\r
+      p->longestMatchLength = newLen;\r
+      return Backward(p, backRes, cur);\r
+    }\r
+    position++;\r
+    curOpt = &p->opt[cur];\r
+    posPrev = curOpt->posPrev;\r
+    if (curOpt->prev1IsChar)\r
+    {\r
+      posPrev--;\r
+      if (curOpt->prev2)\r
+      {\r
+        state = p->opt[curOpt->posPrev2].state;\r
+        if (curOpt->backPrev2 < LZMA_NUM_REPS)\r
+          state = kRepNextStates[state];\r
+        else\r
+          state = kMatchNextStates[state];\r
+      }\r
+      else\r
+        state = p->opt[posPrev].state;\r
+      state = kLiteralNextStates[state];\r
+    }\r
+    else\r
+      state = p->opt[posPrev].state;\r
+    if (posPrev == cur - 1)\r
+    {\r
+      if (IsShortRep(curOpt))\r
+        state = kShortRepNextStates[state];\r
+      else\r
+        state = kLiteralNextStates[state];\r
+    }\r
+    else\r
+    {\r
+      UInt32 pos;\r
+      const COptimal *prevOpt;\r
+      if (curOpt->prev1IsChar && curOpt->prev2)\r
+      {\r
+        posPrev = curOpt->posPrev2;\r
+        pos = curOpt->backPrev2;\r
+        state = kRepNextStates[state];\r
+      }\r
+      else\r
+      {\r
+        pos = curOpt->backPrev;\r
+        if (pos < LZMA_NUM_REPS)\r
+          state = kRepNextStates[state];\r
+        else\r
+          state = kMatchNextStates[state];\r
+      }\r
+      prevOpt = &p->opt[posPrev];\r
+      if (pos < LZMA_NUM_REPS)\r
+      {\r
+        UInt32 i;\r
+        reps[0] = prevOpt->backs[pos];\r
+        for (i = 1; i <= pos; i++)\r
+          reps[i] = prevOpt->backs[i - 1];\r
+        for (; i < LZMA_NUM_REPS; i++)\r
+          reps[i] = prevOpt->backs[i];\r
+      }\r
+      else\r
+      {\r
+        UInt32 i;\r
+        reps[0] = (pos - LZMA_NUM_REPS);\r
+        for (i = 1; i < LZMA_NUM_REPS; i++)\r
+          reps[i] = prevOpt->backs[i - 1];\r
+      }\r
+    }\r
+    curOpt->state = (CState)state;\r
+\r
+    curOpt->backs[0] = reps[0];\r
+    curOpt->backs[1] = reps[1];\r
+    curOpt->backs[2] = reps[2];\r
+    curOpt->backs[3] = reps[3];\r
+\r
+    curPrice = curOpt->price;\r
+    nextIsChar = False;\r
+    data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\r
+    curByte = *data;\r
+    matchByte = *(data - (reps[0] + 1));\r
+\r
+    posState = (position & p->pbMask);\r
+\r
+    curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]);\r
+    {\r
+      const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));\r
+      curAnd1Price +=\r
+        (!IsCharState(state) ?\r
+          LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :\r
+          LitEnc_GetPrice(probs, curByte, p->ProbPrices));\r
+    }\r
+\r
+    nextOpt = &p->opt[cur + 1];\r
+\r
+    if (curAnd1Price < nextOpt->price)\r
+    {\r
+      nextOpt->price = curAnd1Price;\r
+      nextOpt->posPrev = cur;\r
+      MakeAsChar(nextOpt);\r
+      nextIsChar = True;\r
+    }\r
+\r
+    matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);\r
+    repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);\r
+    \r
+    if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0))\r
+    {\r
+      UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState);\r
+      if (shortRepPrice <= nextOpt->price)\r
+      {\r
+        nextOpt->price = shortRepPrice;\r
+        nextOpt->posPrev = cur;\r
+        MakeAsShortRep(nextOpt);\r
+        nextIsChar = True;\r
+      }\r
+    }\r
+    numAvailFull = p->numAvail;\r
+    {\r
+      UInt32 temp = kNumOpts - 1 - cur;\r
+      if (temp < numAvailFull)\r
+        numAvailFull = temp;\r
+    }\r
+\r
+    if (numAvailFull < 2)\r
+      continue;\r
+    numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);\r
+\r
+    if (!nextIsChar && matchByte != curByte) /* speed optimization */\r
+    {\r
+      /* try Literal + rep0 */\r
+      UInt32 temp;\r
+      UInt32 lenTest2;\r
+      const Byte *data2 = data - (reps[0] + 1);\r
+      UInt32 limit = p->numFastBytes + 1;\r
+      if (limit > numAvailFull)\r
+        limit = numAvailFull;\r
+\r
+      for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++);\r
+      lenTest2 = temp - 1;\r
+      if (lenTest2 >= 2)\r
+      {\r
+        UInt32 state2 = kLiteralNextStates[state];\r
+        UInt32 posStateNext = (position + 1) & p->pbMask;\r
+        UInt32 nextRepMatchPrice = curAnd1Price +\r
+            GET_PRICE_1(p->isMatch[state2][posStateNext]) +\r
+            GET_PRICE_1(p->isRep[state2]);\r
+        /* for (; lenTest2 >= 2; lenTest2--) */\r
+        {\r
+          UInt32 curAndLenPrice;\r
+          COptimal *opt;\r
+          UInt32 offset = cur + 1 + lenTest2;\r
+          while (lenEnd < offset)\r
+            p->opt[++lenEnd].price = kInfinityPrice;\r
+          curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);\r
+          opt = &p->opt[offset];\r
+          if (curAndLenPrice < opt->price)\r
+          {\r
+            opt->price = curAndLenPrice;\r
+            opt->posPrev = cur + 1;\r
+            opt->backPrev = 0;\r
+            opt->prev1IsChar = True;\r
+            opt->prev2 = False;\r
+          }\r
+        }\r
+      }\r
+    }\r
+    \r
+    startLen = 2; /* speed optimization */\r
+    {\r
+    UInt32 repIndex;\r
+    for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++)\r
+    {\r
+      UInt32 lenTest;\r
+      UInt32 lenTestTemp;\r
+      UInt32 price;\r
+      const Byte *data2 = data - (reps[repIndex] + 1);\r
+      if (data[0] != data2[0] || data[1] != data2[1])\r
+        continue;\r
+      for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);\r
+      while (lenEnd < cur + lenTest)\r
+        p->opt[++lenEnd].price = kInfinityPrice;\r
+      lenTestTemp = lenTest;\r
+      price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState);\r
+      do\r
+      {\r
+        UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2];\r
+        COptimal *opt = &p->opt[cur + lenTest];\r
+        if (curAndLenPrice < opt->price)\r
+        {\r
+          opt->price = curAndLenPrice;\r
+          opt->posPrev = cur;\r
+          opt->backPrev = repIndex;\r
+          opt->prev1IsChar = False;\r
+        }\r
+      }\r
+      while (--lenTest >= 2);\r
+      lenTest = lenTestTemp;\r
+      \r
+      if (repIndex == 0)\r
+        startLen = lenTest + 1;\r
+        \r
+      /* if (_maxMode) */\r
+        {\r
+          UInt32 lenTest2 = lenTest + 1;\r
+          UInt32 limit = lenTest2 + p->numFastBytes;\r
+          UInt32 nextRepMatchPrice;\r
+          if (limit > numAvailFull)\r
+            limit = numAvailFull;\r
+          for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);\r
+          lenTest2 -= lenTest + 1;\r
+          if (lenTest2 >= 2)\r
+          {\r
+            UInt32 state2 = kRepNextStates[state];\r
+            UInt32 posStateNext = (position + lenTest) & p->pbMask;\r
+            UInt32 curAndLenCharPrice =\r
+                price + p->repLenEnc.prices[posState][lenTest - 2] +\r
+                GET_PRICE_0(p->isMatch[state2][posStateNext]) +\r
+                LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),\r
+                    data[lenTest], data2[lenTest], p->ProbPrices);\r
+            state2 = kLiteralNextStates[state2];\r
+            posStateNext = (position + lenTest + 1) & p->pbMask;\r
+            nextRepMatchPrice = curAndLenCharPrice +\r
+                GET_PRICE_1(p->isMatch[state2][posStateNext]) +\r
+                GET_PRICE_1(p->isRep[state2]);\r
+            \r
+            /* for (; lenTest2 >= 2; lenTest2--) */\r
+            {\r
+              UInt32 curAndLenPrice;\r
+              COptimal *opt;\r
+              UInt32 offset = cur + lenTest + 1 + lenTest2;\r
+              while (lenEnd < offset)\r
+                p->opt[++lenEnd].price = kInfinityPrice;\r
+              curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);\r
+              opt = &p->opt[offset];\r
+              if (curAndLenPrice < opt->price)\r
+              {\r
+                opt->price = curAndLenPrice;\r
+                opt->posPrev = cur + lenTest + 1;\r
+                opt->backPrev = 0;\r
+                opt->prev1IsChar = True;\r
+                opt->prev2 = True;\r
+                opt->posPrev2 = cur;\r
+                opt->backPrev2 = repIndex;\r
+              }\r
+            }\r
+          }\r
+        }\r
+    }\r
+    }\r
+    /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */\r
+    if (newLen > numAvail)\r
+    {\r
+      newLen = numAvail;\r
+      for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2);\r
+      matches[numPairs] = newLen;\r
+      numPairs += 2;\r
+    }\r
+    if (newLen >= startLen)\r
+    {\r
+      UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);\r
+      UInt32 offs, curBack, posSlot;\r
+      UInt32 lenTest;\r
+      while (lenEnd < cur + newLen)\r
+        p->opt[++lenEnd].price = kInfinityPrice;\r
+\r
+      offs = 0;\r
+      while (startLen > matches[offs])\r
+        offs += 2;\r
+      curBack = matches[offs + 1];\r
+      GetPosSlot2(curBack, posSlot);\r
+      for (lenTest = /*2*/ startLen; ; lenTest++)\r
+      {\r
+        UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN];\r
+        UInt32 lenToPosState = GetLenToPosState(lenTest);\r
+        COptimal *opt;\r
+        if (curBack < kNumFullDistances)\r
+          curAndLenPrice += p->distancesPrices[lenToPosState][curBack];\r
+        else\r
+          curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask];\r
+        \r
+        opt = &p->opt[cur + lenTest];\r
+        if (curAndLenPrice < opt->price)\r
+        {\r
+          opt->price = curAndLenPrice;\r
+          opt->posPrev = cur;\r
+          opt->backPrev = curBack + LZMA_NUM_REPS;\r
+          opt->prev1IsChar = False;\r
+        }\r
+\r
+        if (/*_maxMode && */lenTest == matches[offs])\r
+        {\r
+          /* Try Match + Literal + Rep0 */\r
+          const Byte *data2 = data - (curBack + 1);\r
+          UInt32 lenTest2 = lenTest + 1;\r
+          UInt32 limit = lenTest2 + p->numFastBytes;\r
+          UInt32 nextRepMatchPrice;\r
+          if (limit > numAvailFull)\r
+            limit = numAvailFull;\r
+          for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);\r
+          lenTest2 -= lenTest + 1;\r
+          if (lenTest2 >= 2)\r
+          {\r
+            UInt32 state2 = kMatchNextStates[state];\r
+            UInt32 posStateNext = (position + lenTest) & p->pbMask;\r
+            UInt32 curAndLenCharPrice = curAndLenPrice +\r
+                GET_PRICE_0(p->isMatch[state2][posStateNext]) +\r
+                LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),\r
+                    data[lenTest], data2[lenTest], p->ProbPrices);\r
+            state2 = kLiteralNextStates[state2];\r
+            posStateNext = (posStateNext + 1) & p->pbMask;\r
+            nextRepMatchPrice = curAndLenCharPrice +\r
+                GET_PRICE_1(p->isMatch[state2][posStateNext]) +\r
+                GET_PRICE_1(p->isRep[state2]);\r
+            \r
+            /* for (; lenTest2 >= 2; lenTest2--) */\r
+            {\r
+              UInt32 offset = cur + lenTest + 1 + lenTest2;\r
+              UInt32 curAndLenPrice;\r
+              COptimal *opt;\r
+              while (lenEnd < offset)\r
+                p->opt[++lenEnd].price = kInfinityPrice;\r
+              curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);\r
+              opt = &p->opt[offset];\r
+              if (curAndLenPrice < opt->price)\r
+              {\r
+                opt->price = curAndLenPrice;\r
+                opt->posPrev = cur + lenTest + 1;\r
+                opt->backPrev = 0;\r
+                opt->prev1IsChar = True;\r
+                opt->prev2 = True;\r
+                opt->posPrev2 = cur;\r
+                opt->backPrev2 = curBack + LZMA_NUM_REPS;\r
+              }\r
+            }\r
+          }\r
+          offs += 2;\r
+          if (offs == numPairs)\r
+            break;\r
+          curBack = matches[offs + 1];\r
+          if (curBack >= kNumFullDistances)\r
+            GetPosSlot2(curBack, posSlot);\r
+        }\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))\r
+\r
+static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)\r
+{\r
+  UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i;\r
+  const Byte *data;\r
+  const UInt32 *matches;\r
+\r
+  if (p->additionalOffset == 0)\r
+    mainLen = ReadMatchDistances(p, &numPairs);\r
+  else\r
+  {\r
+    mainLen = p->longestMatchLength;\r
+    numPairs = p->numPairs;\r
+  }\r
+\r
+  numAvail = p->numAvail;\r
+  *backRes = (UInt32)-1;\r
+  if (numAvail < 2)\r
+    return 1;\r
+  if (numAvail > LZMA_MATCH_LEN_MAX)\r
+    numAvail = LZMA_MATCH_LEN_MAX;\r
+  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\r
+\r
+  repLen = repIndex = 0;\r
+  for (i = 0; i < LZMA_NUM_REPS; i++)\r
+  {\r
+    UInt32 len;\r
+    const Byte *data2 = data - (p->reps[i] + 1);\r
+    if (data[0] != data2[0] || data[1] != data2[1])\r
+      continue;\r
+    for (len = 2; len < numAvail && data[len] == data2[len]; len++);\r
+    if (len >= p->numFastBytes)\r
+    {\r
+      *backRes = i;\r
+      MovePos(p, len - 1);\r
+      return len;\r
+    }\r
+    if (len > repLen)\r
+    {\r
+      repIndex = i;\r
+      repLen = len;\r
+    }\r
+  }\r
+\r
+  matches = p->matches;\r
+  if (mainLen >= p->numFastBytes)\r
+  {\r
+    *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;\r
+    MovePos(p, mainLen - 1);\r
+    return mainLen;\r
+  }\r
+\r
+  mainDist = 0; /* for GCC */\r
+  if (mainLen >= 2)\r
+  {\r
+    mainDist = matches[numPairs - 1];\r
+    while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1)\r
+    {\r
+      if (!ChangePair(matches[numPairs - 3], mainDist))\r
+        break;\r
+      numPairs -= 2;\r
+      mainLen = matches[numPairs - 2];\r
+      mainDist = matches[numPairs - 1];\r
+    }\r
+    if (mainLen == 2 && mainDist >= 0x80)\r
+      mainLen = 1;\r
+  }\r
+\r
+  if (repLen >= 2 && (\r
+        (repLen + 1 >= mainLen) ||\r
+        (repLen + 2 >= mainLen && mainDist >= (1 << 9)) ||\r
+        (repLen + 3 >= mainLen && mainDist >= (1 << 15))))\r
+  {\r
+    *backRes = repIndex;\r
+    MovePos(p, repLen - 1);\r
+    return repLen;\r
+  }\r
+  \r
+  if (mainLen < 2 || numAvail <= 2)\r
+    return 1;\r
+\r
+  p->longestMatchLength = ReadMatchDistances(p, &p->numPairs);\r
+  if (p->longestMatchLength >= 2)\r
+  {\r
+    UInt32 newDistance = matches[p->numPairs - 1];\r
+    if ((p->longestMatchLength >= mainLen && newDistance < mainDist) ||\r
+        (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) ||\r
+        (p->longestMatchLength > mainLen + 1) ||\r
+        (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist)))\r
+      return 1;\r
+  }\r
+  \r
+  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\r
+  for (i = 0; i < LZMA_NUM_REPS; i++)\r
+  {\r
+    UInt32 len, limit;\r
+    const Byte *data2 = data - (p->reps[i] + 1);\r
+    if (data[0] != data2[0] || data[1] != data2[1])\r
+      continue;\r
+    limit = mainLen - 1;\r
+    for (len = 2; len < limit && data[len] == data2[len]; len++);\r
+    if (len >= limit)\r
+      return 1;\r
+  }\r
+  *backRes = mainDist + LZMA_NUM_REPS;\r
+  MovePos(p, mainLen - 2);\r
+  return mainLen;\r
+}\r
+\r
+static void WriteEndMarker(CLzmaEnc *p, UInt32 posState)\r
+{\r
+  UInt32 len;\r
+  RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);\r
+  RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);\r
+  p->state = kMatchNextStates[p->state];\r
+  len = LZMA_MATCH_LEN_MIN;\r
+  LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);\r
+  RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1);\r
+  RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits);\r
+  RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);\r
+}\r
+\r
+static SRes CheckErrors(CLzmaEnc *p)\r
+{\r
+  if (p->result != SZ_OK)\r
+    return p->result;\r
+  if (p->rc.res != SZ_OK)\r
+    p->result = SZ_ERROR_WRITE;\r
+  if (p->matchFinderBase.result != SZ_OK)\r
+    p->result = SZ_ERROR_READ;\r
+  if (p->result != SZ_OK)\r
+    p->finished = True;\r
+  return p->result;\r
+}\r
+\r
+static SRes Flush(CLzmaEnc *p, UInt32 nowPos)\r
+{\r
+  /* ReleaseMFStream(); */\r
+  p->finished = True;\r
+  if (p->writeEndMark)\r
+    WriteEndMarker(p, nowPos & p->pbMask);\r
+  RangeEnc_FlushData(&p->rc);\r
+  RangeEnc_FlushStream(&p->rc);\r
+  return CheckErrors(p);\r
+}\r
+\r
+static void FillAlignPrices(CLzmaEnc *p)\r
+{\r
+  UInt32 i;\r
+  for (i = 0; i < kAlignTableSize; i++)\r
+    p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);\r
+  p->alignPriceCount = 0;\r
+}\r
+\r
+static void FillDistancesPrices(CLzmaEnc *p)\r
+{\r
+  UInt32 tempPrices[kNumFullDistances];\r
+  UInt32 i, lenToPosState;\r
+  for (i = kStartPosModelIndex; i < kNumFullDistances; i++)\r
+  {\r
+    UInt32 posSlot = GetPosSlot1(i);\r
+    UInt32 footerBits = ((posSlot >> 1) - 1);\r
+    UInt32 base = ((2 | (posSlot & 1)) << footerBits);\r
+    tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices);\r
+  }\r
+\r
+  for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)\r
+  {\r
+    UInt32 posSlot;\r
+    const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];\r
+    UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];\r
+    for (posSlot = 0; posSlot < p->distTableSize; posSlot++)\r
+      posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);\r
+    for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++)\r
+      posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);\r
+\r
+    {\r
+      UInt32 *distancesPrices = p->distancesPrices[lenToPosState];\r
+      UInt32 i;\r
+      for (i = 0; i < kStartPosModelIndex; i++)\r
+        distancesPrices[i] = posSlotPrices[i];\r
+      for (; i < kNumFullDistances; i++)\r
+        distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i];\r
+    }\r
+  }\r
+  p->matchPriceCount = 0;\r
+}\r
+\r
+void LzmaEnc_Construct(CLzmaEnc *p)\r
+{\r
+  RangeEnc_Construct(&p->rc);\r
+  MatchFinder_Construct(&p->matchFinderBase);\r
+  #ifndef _7ZIP_ST\r
+  MatchFinderMt_Construct(&p->matchFinderMt);\r
+  p->matchFinderMt.MatchFinder = &p->matchFinderBase;\r
+  #endif\r
+\r
+  {\r
+    CLzmaEncProps props;\r
+    LzmaEncProps_Init(&props);\r
+    LzmaEnc_SetProps(p, &props);\r
+  }\r
+\r
+  #ifndef LZMA_LOG_BSR\r
+  LzmaEnc_FastPosInit(p->g_FastPos);\r
+  #endif\r
+\r
+  LzmaEnc_InitPriceTables(p->ProbPrices);\r
+  p->litProbs = 0;\r
+  p->saveState.litProbs = 0;\r
+}\r
+\r
+CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)\r
+{\r
+  void *p;\r
+  p = alloc->Alloc(alloc, sizeof(CLzmaEnc));\r
+  if (p != 0)\r
+    LzmaEnc_Construct((CLzmaEnc *)p);\r
+  return p;\r
+}\r
+\r
+void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)\r
+{\r
+  alloc->Free(alloc, p->litProbs);\r
+  alloc->Free(alloc, p->saveState.litProbs);\r
+  p->litProbs = 0;\r
+  p->saveState.litProbs = 0;\r
+}\r
+\r
+void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)\r
+{\r
+  #ifndef _7ZIP_ST\r
+  MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);\r
+  #endif\r
+  MatchFinder_Free(&p->matchFinderBase, allocBig);\r
+  LzmaEnc_FreeLits(p, alloc);\r
+  RangeEnc_Free(&p->rc, alloc);\r
+}\r
+\r
+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig)\r
+{\r
+  LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);\r
+  alloc->Free(alloc, p);\r
+}\r
+\r
+static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)\r
+{\r
+  UInt32 nowPos32, startPos32;\r
+  if (p->needInit)\r
+  {\r
+    p->matchFinder.Init(p->matchFinderObj);\r
+    p->needInit = 0;\r
+  }\r
+\r
+  if (p->finished)\r
+    return p->result;\r
+  RINOK(CheckErrors(p));\r
+\r
+  nowPos32 = (UInt32)p->nowPos64;\r
+  startPos32 = nowPos32;\r
+\r
+  if (p->nowPos64 == 0)\r
+  {\r
+    UInt32 numPairs;\r
+    Byte curByte;\r
+    if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)\r
+      return Flush(p, nowPos32);\r
+    ReadMatchDistances(p, &numPairs);\r
+    RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);\r
+    p->state = kLiteralNextStates[p->state];\r
+    curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset);\r
+    LitEnc_Encode(&p->rc, p->litProbs, curByte);\r
+    p->additionalOffset--;\r
+    nowPos32++;\r
+  }\r
+\r
+  if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)\r
+  for (;;)\r
+  {\r
+    UInt32 pos, len, posState;\r
+\r
+    if (p->fastMode)\r
+      len = GetOptimumFast(p, &pos);\r
+    else\r
+      len = GetOptimum(p, nowPos32, &pos);\r
+\r
+    #ifdef SHOW_STAT2\r
+    printf("\n pos = %4X,   len = %d   pos = %d", nowPos32, len, pos);\r
+    #endif\r
+\r
+    posState = nowPos32 & p->pbMask;\r
+    if (len == 1 && pos == (UInt32)-1)\r
+    {\r
+      Byte curByte;\r
+      CLzmaProb *probs;\r
+      const Byte *data;\r
+\r
+      RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0);\r
+      data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;\r
+      curByte = *data;\r
+      probs = LIT_PROBS(nowPos32, *(data - 1));\r
+      if (IsCharState(p->state))\r
+        LitEnc_Encode(&p->rc, probs, curByte);\r
+      else\r
+        LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1));\r
+      p->state = kLiteralNextStates[p->state];\r
+    }\r
+    else\r
+    {\r
+      RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);\r
+      if (pos < LZMA_NUM_REPS)\r
+      {\r
+        RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1);\r
+        if (pos == 0)\r
+        {\r
+          RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0);\r
+          RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1));\r
+        }\r
+        else\r
+        {\r
+          UInt32 distance = p->reps[pos];\r
+          RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1);\r
+          if (pos == 1)\r
+            RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0);\r
+          else\r
+          {\r
+            RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1);\r
+            RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2);\r
+            if (pos == 3)\r
+              p->reps[3] = p->reps[2];\r
+            p->reps[2] = p->reps[1];\r
+          }\r
+          p->reps[1] = p->reps[0];\r
+          p->reps[0] = distance;\r
+        }\r
+        if (len == 1)\r
+          p->state = kShortRepNextStates[p->state];\r
+        else\r
+        {\r
+          LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);\r
+          p->state = kRepNextStates[p->state];\r
+        }\r
+      }\r
+      else\r
+      {\r
+        UInt32 posSlot;\r
+        RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);\r
+        p->state = kMatchNextStates[p->state];\r
+        LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);\r
+        pos -= LZMA_NUM_REPS;\r
+        GetPosSlot(pos, posSlot);\r
+        RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);\r
+        \r
+        if (posSlot >= kStartPosModelIndex)\r
+        {\r
+          UInt32 footerBits = ((posSlot >> 1) - 1);\r
+          UInt32 base = ((2 | (posSlot & 1)) << footerBits);\r
+          UInt32 posReduced = pos - base;\r
+\r
+          if (posSlot < kEndPosModelIndex)\r
+            RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced);\r
+          else\r
+          {\r
+            RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);\r
+            RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);\r
+            p->alignPriceCount++;\r
+          }\r
+        }\r
+        p->reps[3] = p->reps[2];\r
+        p->reps[2] = p->reps[1];\r
+        p->reps[1] = p->reps[0];\r
+        p->reps[0] = pos;\r
+        p->matchPriceCount++;\r
+      }\r
+    }\r
+    p->additionalOffset -= len;\r
+    nowPos32 += len;\r
+    if (p->additionalOffset == 0)\r
+    {\r
+      UInt32 processed;\r
+      if (!p->fastMode)\r
+      {\r
+        if (p->matchPriceCount >= (1 << 7))\r
+          FillDistancesPrices(p);\r
+        if (p->alignPriceCount >= kAlignTableSize)\r
+          FillAlignPrices(p);\r
+      }\r
+      if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)\r
+        break;\r
+      processed = nowPos32 - startPos32;\r
+      if (useLimits)\r
+      {\r
+        if (processed + kNumOpts + 300 >= maxUnpackSize ||\r
+            RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)\r
+          break;\r
+      }\r
+      else if (processed >= (1 << 15))\r
+      {\r
+        p->nowPos64 += nowPos32 - startPos32;\r
+        return CheckErrors(p);\r
+      }\r
+    }\r
+  }\r
+  p->nowPos64 += nowPos32 - startPos32;\r
+  return Flush(p, nowPos32);\r
+}\r
+\r
+#define kBigHashDicLimit ((UInt32)1 << 24)\r
+\r
+static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)\r
+{\r
+  UInt32 beforeSize = kNumOpts;\r
+  Bool btMode;\r
+  if (!RangeEnc_Alloc(&p->rc, alloc))\r
+    return SZ_ERROR_MEM;\r
+  btMode = (p->matchFinderBase.btMode != 0);\r
+  #ifndef _7ZIP_ST\r
+  p->mtMode = (p->multiThread && !p->fastMode && btMode);\r
+  #endif\r
+\r
+  {\r
+    unsigned lclp = p->lc + p->lp;\r
+    if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp)\r
+    {\r
+      LzmaEnc_FreeLits(p, alloc);\r
+      p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));\r
+      p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));\r
+      if (p->litProbs == 0 || p->saveState.litProbs == 0)\r
+      {\r
+        LzmaEnc_FreeLits(p, alloc);\r
+        return SZ_ERROR_MEM;\r
+      }\r
+      p->lclp = lclp;\r
+    }\r
+  }\r
+\r
+  p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit);\r
+\r
+  if (beforeSize + p->dictSize < keepWindowSize)\r
+    beforeSize = keepWindowSize - p->dictSize;\r
+\r
+  #ifndef _7ZIP_ST\r
+  if (p->mtMode)\r
+  {\r
+    RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig));\r
+    p->matchFinderObj = &p->matchFinderMt;\r
+    MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))\r
+      return SZ_ERROR_MEM;\r
+    p->matchFinderObj = &p->matchFinderBase;\r
+    MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);\r
+  }\r
+  return SZ_OK;\r
+}\r
+\r
+void LzmaEnc_Init(CLzmaEnc *p)\r
+{\r
+  UInt32 i;\r
+  p->state = 0;\r
+  for (i = 0 ; i < LZMA_NUM_REPS; i++)\r
+    p->reps[i] = 0;\r
+\r
+  RangeEnc_Init(&p->rc);\r
+\r
+\r
+  for (i = 0; i < kNumStates; i++)\r
+  {\r
+    UInt32 j;\r
+    for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)\r
+    {\r
+      p->isMatch[i][j] = kProbInitValue;\r
+      p->isRep0Long[i][j] = kProbInitValue;\r
+    }\r
+    p->isRep[i] = kProbInitValue;\r
+    p->isRepG0[i] = kProbInitValue;\r
+    p->isRepG1[i] = kProbInitValue;\r
+    p->isRepG2[i] = kProbInitValue;\r
+  }\r
+\r
+  {\r
+    UInt32 num = 0x300 << (p->lp + p->lc);\r
+    for (i = 0; i < num; i++)\r
+      p->litProbs[i] = kProbInitValue;\r
+  }\r
+\r
+  {\r
+    for (i = 0; i < kNumLenToPosStates; i++)\r
+    {\r
+      CLzmaProb *probs = p->posSlotEncoder[i];\r
+      UInt32 j;\r
+      for (j = 0; j < (1 << kNumPosSlotBits); j++)\r
+        probs[j] = kProbInitValue;\r
+    }\r
+  }\r
+  {\r
+    for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)\r
+      p->posEncoders[i] = kProbInitValue;\r
+  }\r
+\r
+  LenEnc_Init(&p->lenEnc.p);\r
+  LenEnc_Init(&p->repLenEnc.p);\r
+\r
+  for (i = 0; i < (1 << kNumAlignBits); i++)\r
+    p->posAlignEncoder[i] = kProbInitValue;\r
+\r
+  p->optimumEndIndex = 0;\r
+  p->optimumCurrentIndex = 0;\r
+  p->additionalOffset = 0;\r
+\r
+  p->pbMask = (1 << p->pb) - 1;\r
+  p->lpMask = (1 << p->lp) - 1;\r
+}\r
+\r
+void LzmaEnc_InitPrices(CLzmaEnc *p)\r
+{\r
+  if (!p->fastMode)\r
+  {\r
+    FillDistancesPrices(p);\r
+    FillAlignPrices(p);\r
+  }\r
+\r
+  p->lenEnc.tableSize =\r
+  p->repLenEnc.tableSize =\r
+      p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;\r
+  LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices);\r
+  LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices);\r
+}\r
+\r
+static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)\r
+{\r
+  UInt32 i;\r
+  for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++)\r
+    if (p->dictSize <= ((UInt32)1 << i))\r
+      break;\r
+  p->distTableSize = i * 2;\r
+\r
+  p->finished = False;\r
+  p->result = SZ_OK;\r
+  RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));\r
+  LzmaEnc_Init(p);\r
+  LzmaEnc_InitPrices(p);\r
+  p->nowPos64 = 0;\r
+  return SZ_OK;\r
+}\r
+\r
+static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream,\r
+    ISzAlloc *alloc, ISzAlloc *allocBig)\r
+{\r
+  CLzmaEnc *p = (CLzmaEnc *)pp;\r
+  p->matchFinderBase.stream = inStream;\r
+  p->needInit = 1;\r
+  p->rc.outStream = outStream;\r
+  return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);\r
+}\r
+\r
+SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,\r
+    ISeqInStream *inStream, UInt32 keepWindowSize,\r
+    ISzAlloc *alloc, ISzAlloc *allocBig)\r
+{\r
+  CLzmaEnc *p = (CLzmaEnc *)pp;\r
+  p->matchFinderBase.stream = inStream;\r
+  p->needInit = 1;\r
+  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);\r
+}\r
+\r
+static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)\r
+{\r
+  p->matchFinderBase.directInput = 1;\r
+  p->matchFinderBase.bufferBase = (Byte *)src;\r
+  p->matchFinderBase.directInputRem = srcLen;\r
+}\r
+\r
+SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,\r
+    UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)\r
+{\r
+  CLzmaEnc *p = (CLzmaEnc *)pp;\r
+  LzmaEnc_SetInputBuf(p, src, srcLen);\r
+  p->needInit = 1;\r
+\r
+  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);\r
+}\r
+\r
+void LzmaEnc_Finish(CLzmaEncHandle pp)\r
+{\r
+  #ifndef _7ZIP_ST\r
+  CLzmaEnc *p = (CLzmaEnc *)pp;\r
+  if (p->mtMode)\r
+    MatchFinderMt_ReleaseStream(&p->matchFinderMt);\r
+  #else\r
+  pp = pp;\r
+  #endif\r
+}\r
+\r
+typedef struct\r
+{\r
+  ISeqOutStream funcTable;\r
+  Byte *data;\r
+  SizeT rem;\r
+  Bool overflow;\r
+} CSeqOutStreamBuf;\r
+\r
+static size_t MyWrite(void *pp, const void *data, size_t size)\r
+{\r
+  CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp;\r
+  if (p->rem < size)\r
+  {\r
+    size = p->rem;\r
+    p->overflow = True;\r
+  }\r
+  memcpy(p->data, data, size);\r
+  p->rem -= size;\r
+  p->data += size;\r
+  return size;\r
+}\r
+\r
+\r
+UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)\r
+{\r
+  const CLzmaEnc *p = (CLzmaEnc *)pp;\r
+  return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);\r
+}\r
+\r
+const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)\r
+{\r
+  const CLzmaEnc *p = (CLzmaEnc *)pp;\r
+  return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;\r
+}\r
+\r
+SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,\r
+    Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)\r
+{\r
+  CLzmaEnc *p = (CLzmaEnc *)pp;\r
+  UInt64 nowPos64;\r
+  SRes res;\r
+  CSeqOutStreamBuf outStream;\r
+\r
+  outStream.funcTable.Write = MyWrite;\r
+  outStream.data = dest;\r
+  outStream.rem = *destLen;\r
+  outStream.overflow = False;\r
+\r
+  p->writeEndMark = False;\r
+  p->finished = False;\r
+  p->result = SZ_OK;\r
+\r
+  if (reInit)\r
+    LzmaEnc_Init(p);\r
+  LzmaEnc_InitPrices(p);\r
+  nowPos64 = p->nowPos64;\r
+  RangeEnc_Init(&p->rc);\r
+  p->rc.outStream = &outStream.funcTable;\r
+\r
+  res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize);\r
+  \r
+  *unpackSize = (UInt32)(p->nowPos64 - nowPos64);\r
+  *destLen -= outStream.rem;\r
+  if (outStream.overflow)\r
+    return SZ_ERROR_OUTPUT_EOF;\r
+\r
+  return res;\r
+}\r
+\r
+static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)\r
+{\r
+  SRes res = SZ_OK;\r
+\r
+  #ifndef _7ZIP_ST\r
+  Byte allocaDummy[0x300];\r
+  int i = 0;\r
+  for (i = 0; i < 16; i++)\r
+    allocaDummy[i] = (Byte)i;\r
+  #endif\r
+\r
+  for (;;)\r
+  {\r
+    res = LzmaEnc_CodeOneBlock(p, False, 0, 0);\r
+    if (res != SZ_OK || p->finished != 0)\r
+      break;\r
+    if (progress != 0)\r
+    {\r
+      res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));\r
+      if (res != SZ_OK)\r
+      {\r
+        res = SZ_ERROR_PROGRESS;\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  LzmaEnc_Finish(p);\r
+  return res;\r
+}\r
+\r
+SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,\r
+    ISzAlloc *alloc, ISzAlloc *allocBig)\r
+{\r
+  RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig));\r
+  return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);\r
+}\r
+\r
+SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)\r
+{\r
+  CLzmaEnc *p = (CLzmaEnc *)pp;\r
+  int i;\r
+  UInt32 dictSize = p->dictSize;\r
+  if (*size < LZMA_PROPS_SIZE)\r
+    return SZ_ERROR_PARAM;\r
+  *size = LZMA_PROPS_SIZE;\r
+  props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);\r
+\r
+  for (i = 11; i <= 30; i++)\r
+  {\r
+    if (dictSize <= ((UInt32)2 << i))\r
+    {\r
+      dictSize = (2 << i);\r
+      break;\r
+    }\r
+    if (dictSize <= ((UInt32)3 << i))\r
+    {\r
+      dictSize = (3 << i);\r
+      break;\r
+    }\r
+  }\r
+\r
+  for (i = 0; i < 4; i++)\r
+    props[1 + i] = (Byte)(dictSize >> (8 * i));\r
+  return SZ_OK;\r
+}\r
+\r
+SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,\r
+    int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)\r
+{\r
+  SRes res;\r
+  CLzmaEnc *p = (CLzmaEnc *)pp;\r
+\r
+  CSeqOutStreamBuf outStream;\r
+\r
+  LzmaEnc_SetInputBuf(p, src, srcLen);\r
+\r
+  outStream.funcTable.Write = MyWrite;\r
+  outStream.data = dest;\r
+  outStream.rem = *destLen;\r
+  outStream.overflow = False;\r
+\r
+  p->writeEndMark = writeEndMark;\r
+\r
+  p->rc.outStream = &outStream.funcTable;\r
+  res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);\r
+  if (res == SZ_OK)\r
+    res = LzmaEnc_Encode2(p, progress);\r
+\r
+  *destLen -= outStream.rem;\r
+  if (outStream.overflow)\r
+    return SZ_ERROR_OUTPUT_EOF;\r
+  return res;\r
+}\r
+\r
+SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,\r
+    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,\r
+    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)\r
+{\r
+  CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);\r
+  SRes res;\r
+  if (p == 0)\r
+    return SZ_ERROR_MEM;\r
+\r
+  res = LzmaEnc_SetProps(p, props);\r
+  if (res == SZ_OK)\r
+  {\r
+    res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);\r
+    if (res == SZ_OK)\r
+      res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,\r
+          writeEndMark, progress, alloc, allocBig);\r
+  }\r
+\r
+  LzmaEnc_Destroy(p, alloc, allocBig);\r
+  return res;\r
+}\r
diff --git a/C/LzmaEnc.h b/C/LzmaEnc.h
new file mode 100755 (executable)
index 0000000..999f5af
--- /dev/null
@@ -0,0 +1,80 @@
+/*  LzmaEnc.h -- LZMA Encoder\r
+2009-02-07 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __LZMA_ENC_H\r
+#define __LZMA_ENC_H\r
+\r
+#include "Types.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#define LZMA_PROPS_SIZE 5\r
+\r
+typedef struct _CLzmaEncProps\r
+{\r
+  int level;       /*  0 <= level <= 9 */\r
+  UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version\r
+                      (1 << 12) <= dictSize <= (1 << 30) for 64-bit version\r
+                       default = (1 << 24) */\r
+  int lc;          /* 0 <= lc <= 8, default = 3 */\r
+  int lp;          /* 0 <= lp <= 4, default = 0 */\r
+  int pb;          /* 0 <= pb <= 4, default = 2 */\r
+  int algo;        /* 0 - fast, 1 - normal, default = 1 */\r
+  int fb;          /* 5 <= fb <= 273, default = 32 */\r
+  int btMode;      /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */\r
+  int numHashBytes; /* 2, 3 or 4, default = 4 */\r
+  UInt32 mc;        /* 1 <= mc <= (1 << 30), default = 32 */\r
+  unsigned writeEndMark;  /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */\r
+  int numThreads;  /* 1 or 2, default = 2 */\r
+} CLzmaEncProps;\r
+\r
+void LzmaEncProps_Init(CLzmaEncProps *p);\r
+void LzmaEncProps_Normalize(CLzmaEncProps *p);\r
+UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);\r
+\r
+\r
+/* ---------- CLzmaEncHandle Interface ---------- */\r
+\r
+/* LzmaEnc_* functions can return the following exit codes:\r
+Returns:\r
+  SZ_OK           - OK\r
+  SZ_ERROR_MEM    - Memory allocation error\r
+  SZ_ERROR_PARAM  - Incorrect paramater in props\r
+  SZ_ERROR_WRITE  - Write callback error.\r
+  SZ_ERROR_PROGRESS - some break from progress callback\r
+  SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)\r
+*/\r
+\r
+typedef void * CLzmaEncHandle;\r
+\r
+CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);\r
+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);\r
+SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);\r
+SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);\r
+SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,\r
+    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);\r
+SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,\r
+    int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);\r
+\r
+/* ---------- One Call Interface ---------- */\r
+\r
+/* LzmaEncode\r
+Return code:\r
+  SZ_OK               - OK\r
+  SZ_ERROR_MEM        - Memory allocation error\r
+  SZ_ERROR_PARAM      - Incorrect paramater\r
+  SZ_ERROR_OUTPUT_EOF - output buffer overflow\r
+  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)\r
+*/\r
+\r
+SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,\r
+    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,\r
+    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/C/LzmaLib.c b/C/LzmaLib.c
new file mode 100755 (executable)
index 0000000..3e3cf40
--- /dev/null
@@ -0,0 +1,46 @@
+/* LzmaLib.c -- LZMA library wrapper\r
+2008-08-05\r
+Igor Pavlov\r
+Public domain */\r
+\r
+#include "LzmaEnc.h"\r
+#include "LzmaDec.h"\r
+#include "Alloc.h"\r
+#include "LzmaLib.h"\r
+\r
+static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }\r
+static void SzFree(void *p, void *address) { p = p; MyFree(address); }\r
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };\r
+\r
+MY_STDAPI LzmaCompress(unsigned char *dest, size_t  *destLen, const unsigned char *src, size_t  srcLen,\r
+  unsigned char *outProps, size_t *outPropsSize,\r
+  int level, /* 0 <= level <= 9, default = 5 */\r
+  unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */\r
+  int lc, /* 0 <= lc <= 8, default = 3  */\r
+  int lp, /* 0 <= lp <= 4, default = 0  */\r
+  int pb, /* 0 <= pb <= 4, default = 2  */\r
+  int fb,  /* 5 <= fb <= 273, default = 32 */\r
+  int numThreads /* 1 or 2, default = 2 */\r
+)\r
+{\r
+  CLzmaEncProps props;\r
+  LzmaEncProps_Init(&props);\r
+  props.level = level;\r
+  props.dictSize = dictSize;\r
+  props.lc = lc;\r
+  props.lp = lp;\r
+  props.pb = pb;\r
+  props.fb = fb;\r
+  props.numThreads = numThreads;\r
+\r
+  return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0,\r
+      NULL, &g_Alloc, &g_Alloc);\r
+}\r
+\r
+\r
+MY_STDAPI LzmaUncompress(unsigned char *dest, size_t  *destLen, const unsigned char *src, size_t  *srcLen,\r
+  const unsigned char *props, size_t propsSize)\r
+{\r
+  ELzmaStatus status;\r
+  return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc);\r
+}\r
diff --git a/C/LzmaLib.h b/C/LzmaLib.h
new file mode 100755 (executable)
index 0000000..55e1e11
--- /dev/null
@@ -0,0 +1,135 @@
+/* LzmaLib.h -- LZMA library interface\r
+2009-04-07 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __LZMA_LIB_H\r
+#define __LZMA_LIB_H\r
+\r
+#include "Types.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#define MY_STDAPI int MY_STD_CALL\r
+\r
+#define LZMA_PROPS_SIZE 5\r
+\r
+/*\r
+RAM requirements for LZMA:\r
+  for compression:   (dictSize * 11.5 + 6 MB) + state_size\r
+  for decompression: dictSize + state_size\r
+    state_size = (4 + (1.5 << (lc + lp))) KB\r
+    by default (lc=3, lp=0), state_size = 16 KB.\r
+\r
+LZMA properties (5 bytes) format\r
+    Offset Size  Description\r
+      0     1    lc, lp and pb in encoded form.\r
+      1     4    dictSize (little endian).\r
+*/\r
+\r
+/*\r
+LzmaCompress\r
+------------\r
+\r
+outPropsSize -\r
+     In:  the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5.\r
+     Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5.\r
+\r
+  LZMA Encoder will use defult values for any parameter, if it is\r
+  -1  for any from: level, loc, lp, pb, fb, numThreads\r
+   0  for dictSize\r
+  \r
+level - compression level: 0 <= level <= 9;\r
+\r
+  level dictSize algo  fb\r
+    0:    16 KB   0    32\r
+    1:    64 KB   0    32\r
+    2:   256 KB   0    32\r
+    3:     1 MB   0    32\r
+    4:     4 MB   0    32\r
+    5:    16 MB   1    32\r
+    6:    32 MB   1    32\r
+    7+:   64 MB   1    64\r
\r
+  The default value for "level" is 5.\r
+\r
+  algo = 0 means fast method\r
+  algo = 1 means normal method\r
+\r
+dictSize - The dictionary size in bytes. The maximum value is\r
+        128 MB = (1 << 27) bytes for 32-bit version\r
+          1 GB = (1 << 30) bytes for 64-bit version\r
+     The default value is 16 MB = (1 << 24) bytes.\r
+     It's recommended to use the dictionary that is larger than 4 KB and\r
+     that can be calculated as (1 << N) or (3 << N) sizes.\r
+\r
+lc - The number of literal context bits (high bits of previous literal).\r
+     It can be in the range from 0 to 8. The default value is 3.\r
+     Sometimes lc=4 gives the gain for big files.\r
+\r
+lp - The number of literal pos bits (low bits of current position for literals).\r
+     It can be in the range from 0 to 4. The default value is 0.\r
+     The lp switch is intended for periodical data when the period is equal to 2^lp.\r
+     For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's\r
+     better to set lc=0, if you change lp switch.\r
+\r
+pb - The number of pos bits (low bits of current position).\r
+     It can be in the range from 0 to 4. The default value is 2.\r
+     The pb switch is intended for periodical data when the period is equal 2^pb.\r
+\r
+fb - Word size (the number of fast bytes).\r
+     It can be in the range from 5 to 273. The default value is 32.\r
+     Usually, a big number gives a little bit better compression ratio and\r
+     slower compression process.\r
+\r
+numThreads - The number of thereads. 1 or 2. The default value is 2.\r
+     Fast mode (algo = 0) can use only 1 thread.\r
+\r
+Out:\r
+  destLen  - processed output size\r
+Returns:\r
+  SZ_OK               - OK\r
+  SZ_ERROR_MEM        - Memory allocation error\r
+  SZ_ERROR_PARAM      - Incorrect paramater\r
+  SZ_ERROR_OUTPUT_EOF - output buffer overflow\r
+  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)\r
+*/\r
+\r
+MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,\r
+  unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */\r
+  int level,      /* 0 <= level <= 9, default = 5 */\r
+  unsigned dictSize,  /* default = (1 << 24) */\r
+  int lc,        /* 0 <= lc <= 8, default = 3  */\r
+  int lp,        /* 0 <= lp <= 4, default = 0  */\r
+  int pb,        /* 0 <= pb <= 4, default = 2  */\r
+  int fb,        /* 5 <= fb <= 273, default = 32 */\r
+  int numThreads /* 1 or 2, default = 2 */\r
+  );\r
+\r
+/*\r
+LzmaUncompress\r
+--------------\r
+In:\r
+  dest     - output data\r
+  destLen  - output data size\r
+  src      - input data\r
+  srcLen   - input data size\r
+Out:\r
+  destLen  - processed output size\r
+  srcLen   - processed input size\r
+Returns:\r
+  SZ_OK                - OK\r
+  SZ_ERROR_DATA        - Data error\r
+  SZ_ERROR_MEM         - Memory allocation arror\r
+  SZ_ERROR_UNSUPPORTED - Unsupported properties\r
+  SZ_ERROR_INPUT_EOF   - it needs more bytes in input buffer (src)\r
+*/\r
+\r
+MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen,\r
+  const unsigned char *props, size_t propsSize);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/C/MtCoder.c b/C/MtCoder.c
new file mode 100755 (executable)
index 0000000..9f0d268
--- /dev/null
@@ -0,0 +1,327 @@
+/* MtCoder.c -- Multi-thread Coder\r
+2010-09-24 : Igor Pavlov : Public domain */\r
+\r
+#include <stdio.h>\r
+\r
+#include "MtCoder.h"\r
+\r
+void LoopThread_Construct(CLoopThread *p)\r
+{\r
+  Thread_Construct(&p->thread);\r
+  Event_Construct(&p->startEvent);\r
+  Event_Construct(&p->finishedEvent);\r
+}\r
+\r
+void LoopThread_Close(CLoopThread *p)\r
+{\r
+  Thread_Close(&p->thread);\r
+  Event_Close(&p->startEvent);\r
+  Event_Close(&p->finishedEvent);\r
+}\r
+\r
+static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE LoopThreadFunc(void *pp)\r
+{\r
+  CLoopThread *p = (CLoopThread *)pp;\r
+  for (;;)\r
+  {\r
+    if (Event_Wait(&p->startEvent) != 0)\r
+      return SZ_ERROR_THREAD;\r
+    if (p->stop)\r
+      return 0;\r
+    p->res = p->func(p->param);\r
+    if (Event_Set(&p->finishedEvent) != 0)\r
+      return SZ_ERROR_THREAD;\r
+  }\r
+}\r
+\r
+WRes LoopThread_Create(CLoopThread *p)\r
+{\r
+  p->stop = 0;\r
+  RINOK(AutoResetEvent_CreateNotSignaled(&p->startEvent));\r
+  RINOK(AutoResetEvent_CreateNotSignaled(&p->finishedEvent));\r
+  return Thread_Create(&p->thread, LoopThreadFunc, p);\r
+}\r
+\r
+WRes LoopThread_StopAndWait(CLoopThread *p)\r
+{\r
+  p->stop = 1;\r
+  if (Event_Set(&p->startEvent) != 0)\r
+    return SZ_ERROR_THREAD;\r
+  return Thread_Wait(&p->thread);\r
+}\r
+\r
+WRes LoopThread_StartSubThread(CLoopThread *p) { return Event_Set(&p->startEvent); }\r
+WRes LoopThread_WaitSubThread(CLoopThread *p) { return Event_Wait(&p->finishedEvent); }\r
+\r
+static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)\r
+{\r
+  return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;\r
+}\r
+\r
+static void MtProgress_Init(CMtProgress *p, ICompressProgress *progress)\r
+{\r
+  unsigned i;\r
+  for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)\r
+    p->inSizes[i] = p->outSizes[i] = 0;\r
+  p->totalInSize = p->totalOutSize = 0;\r
+  p->progress = progress;\r
+  p->res = SZ_OK;\r
+}\r
+\r
+static void MtProgress_Reinit(CMtProgress *p, unsigned index)\r
+{\r
+  p->inSizes[index] = 0;\r
+  p->outSizes[index] = 0;\r
+}\r
+\r
+#define UPDATE_PROGRESS(size, prev, total) \\r
+  if (size != (UInt64)(Int64)-1) { total += size - prev; prev = size; }\r
+\r
+SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize)\r
+{\r
+  SRes res;\r
+  CriticalSection_Enter(&p->cs);\r
+  UPDATE_PROGRESS(inSize, p->inSizes[index], p->totalInSize)\r
+  UPDATE_PROGRESS(outSize, p->outSizes[index], p->totalOutSize)\r
+  if (p->res == SZ_OK)\r
+    p->res = Progress(p->progress, p->totalInSize, p->totalOutSize);\r
+  res = p->res;\r
+  CriticalSection_Leave(&p->cs);\r
+  return res;\r
+}\r
+\r
+static void MtProgress_SetError(CMtProgress *p, SRes res)\r
+{\r
+  CriticalSection_Enter(&p->cs);\r
+  if (p->res == SZ_OK)\r
+    p->res = res;\r
+  CriticalSection_Leave(&p->cs);\r
+}\r
+\r
+static void MtCoder_SetError(CMtCoder* p, SRes res)\r
+{\r
+  CriticalSection_Enter(&p->cs);\r
+  if (p->res == SZ_OK)\r
+    p->res = res;\r
+  CriticalSection_Leave(&p->cs);\r
+}\r
+\r
+/* ---------- MtThread ---------- */\r
+\r
+void CMtThread_Construct(CMtThread *p, CMtCoder *mtCoder)\r
+{\r
+  p->mtCoder = mtCoder;\r
+  p->outBuf = 0;\r
+  p->inBuf = 0;\r
+  Event_Construct(&p->canRead);\r
+  Event_Construct(&p->canWrite);\r
+  LoopThread_Construct(&p->thread);\r
+}\r
+\r
+#define RINOK_THREAD(x) { if((x) != 0) return SZ_ERROR_THREAD; }\r
+\r
+static void CMtThread_CloseEvents(CMtThread *p)\r
+{\r
+  Event_Close(&p->canRead);\r
+  Event_Close(&p->canWrite);\r
+}\r
+\r
+static void CMtThread_Destruct(CMtThread *p)\r
+{\r
+  CMtThread_CloseEvents(p);\r
+\r
+  if (Thread_WasCreated(&p->thread.thread))\r
+  {\r
+    LoopThread_StopAndWait(&p->thread);\r
+    LoopThread_Close(&p->thread);\r
+  }\r
+\r
+  if (p->mtCoder->alloc)\r
+    IAlloc_Free(p->mtCoder->alloc, p->outBuf);\r
+  p->outBuf = 0;\r
+\r
+  if (p->mtCoder->alloc)\r
+    IAlloc_Free(p->mtCoder->alloc, p->inBuf);\r
+  p->inBuf = 0;\r
+}\r
+\r
+#define MY_BUF_ALLOC(buf, size, newSize) \\r
+  if (buf == 0 || size != newSize) \\r
+  { IAlloc_Free(p->mtCoder->alloc, buf); \\r
+    size = newSize; buf = (Byte *)IAlloc_Alloc(p->mtCoder->alloc, size); \\r
+    if (buf == 0) return SZ_ERROR_MEM; }\r
+\r
+static SRes CMtThread_Prepare(CMtThread *p)\r
+{\r
+  MY_BUF_ALLOC(p->inBuf, p->inBufSize, p->mtCoder->blockSize)\r
+  MY_BUF_ALLOC(p->outBuf, p->outBufSize, p->mtCoder->destBlockSize)\r
+\r
+  p->stopReading = False;\r
+  p->stopWriting = False;\r
+  RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canRead));\r
+  RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canWrite));\r
+\r
+  return SZ_OK;\r
+}\r
+\r
+static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize)\r
+{\r
+  size_t size = *processedSize;\r
+  *processedSize = 0;\r
+  while (size != 0)\r
+  {\r
+    size_t curSize = size;\r
+    SRes res = stream->Read(stream, data, &curSize);\r
+    *processedSize += curSize;\r
+    data += curSize;\r
+    size -= curSize;\r
+    RINOK(res);\r
+    if (curSize == 0)\r
+      return SZ_OK;\r
+  }\r
+  return SZ_OK;\r
+}\r
+\r
+#define GET_NEXT_THREAD(p) &p->mtCoder->threads[p->index == p->mtCoder->numThreads  - 1 ? 0 : p->index + 1]\r
+\r
+static SRes MtThread_Process(CMtThread *p, Bool *stop)\r
+{\r
+  CMtThread *next;\r
+  *stop = True;\r
+  if (Event_Wait(&p->canRead) != 0)\r
+    return SZ_ERROR_THREAD;\r
+  \r
+  next = GET_NEXT_THREAD(p);\r
+  \r
+  if (p->stopReading)\r
+  {\r
+    next->stopReading = True;\r
+    return Event_Set(&next->canRead) == 0 ? SZ_OK : SZ_ERROR_THREAD;\r
+  }\r
+\r
+  {\r
+    size_t size = p->mtCoder->blockSize;\r
+    size_t destSize = p->outBufSize;\r
+\r
+    RINOK(FullRead(p->mtCoder->inStream, p->inBuf, &size));\r
+    next->stopReading = *stop = (size != p->mtCoder->blockSize);\r
+    if (Event_Set(&next->canRead) != 0)\r
+      return SZ_ERROR_THREAD;\r
+\r
+    RINOK(p->mtCoder->mtCallback->Code(p->mtCoder->mtCallback, p->index,\r
+        p->outBuf, &destSize, p->inBuf, size, *stop));\r
+\r
+    MtProgress_Reinit(&p->mtCoder->mtProgress, p->index);\r
+\r
+    if (Event_Wait(&p->canWrite) != 0)\r
+      return SZ_ERROR_THREAD;\r
+    if (p->stopWriting)\r
+      return SZ_ERROR_FAIL;\r
+    if (p->mtCoder->outStream->Write(p->mtCoder->outStream, p->outBuf, destSize) != destSize)\r
+      return SZ_ERROR_WRITE;\r
+    return Event_Set(&next->canWrite) == 0 ? SZ_OK : SZ_ERROR_THREAD;\r
+  }\r
+}\r
+\r
+static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp)\r
+{\r
+  CMtThread *p = (CMtThread *)pp;\r
+  for (;;)\r
+  {\r
+    Bool stop;\r
+    CMtThread *next = GET_NEXT_THREAD(p);\r
+    SRes res = MtThread_Process(p, &stop);\r
+    if (res != SZ_OK)\r
+    {\r
+      MtCoder_SetError(p->mtCoder, res);\r
+      MtProgress_SetError(&p->mtCoder->mtProgress, res);\r
+      next->stopReading = True;\r
+      next->stopWriting = True;\r
+      Event_Set(&next->canRead);\r
+      Event_Set(&next->canWrite);\r
+      return res;\r
+    }\r
+    if (stop)\r
+      return 0;\r
+  }\r
+}\r
+\r
+void MtCoder_Construct(CMtCoder* p)\r
+{\r
+  unsigned i;\r
+  p->alloc = 0;\r
+  for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)\r
+  {\r
+    CMtThread *t = &p->threads[i];\r
+    t->index = i;\r
+    CMtThread_Construct(t, p);\r
+  }\r
+  CriticalSection_Init(&p->cs);\r
+  CriticalSection_Init(&p->mtProgress.cs);\r
+}\r
+\r
+void MtCoder_Destruct(CMtCoder* p)\r
+{\r
+  unsigned i;\r
+  for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)\r
+    CMtThread_Destruct(&p->threads[i]);\r
+  CriticalSection_Delete(&p->cs);\r
+  CriticalSection_Delete(&p->mtProgress.cs);\r
+}\r
+\r
+SRes MtCoder_Code(CMtCoder *p)\r
+{\r
+  unsigned i, numThreads = p->numThreads;\r
+  SRes res = SZ_OK;\r
+  p->res = SZ_OK;\r
+\r
+  MtProgress_Init(&p->mtProgress, p->progress);\r
+\r
+  for (i = 0; i < numThreads; i++)\r
+  {\r
+    RINOK(CMtThread_Prepare(&p->threads[i]));\r
+  }\r
+\r
+  for (i = 0; i < numThreads; i++)\r
+  {\r
+    CMtThread *t = &p->threads[i];\r
+    CLoopThread *lt = &t->thread;\r
+\r
+    if (!Thread_WasCreated(&lt->thread))\r
+    {\r
+      lt->func = ThreadFunc;\r
+      lt->param = t;\r
+\r
+      if (LoopThread_Create(lt) != SZ_OK)\r
+      {\r
+        res = SZ_ERROR_THREAD;\r
+        break;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (res == SZ_OK)\r
+  {\r
+    unsigned j;\r
+    for (i = 0; i < numThreads; i++)\r
+    {\r
+      CMtThread *t = &p->threads[i];\r
+      if (LoopThread_StartSubThread(&t->thread) != SZ_OK)\r
+      {\r
+        res = SZ_ERROR_THREAD;\r
+        p->threads[0].stopReading = True;\r
+        break;\r
+      }\r
+    }\r
+\r
+    Event_Set(&p->threads[0].canWrite);\r
+    Event_Set(&p->threads[0].canRead);\r
+\r
+    for (j = 0; j < i; j++)\r
+      LoopThread_WaitSubThread(&p->threads[j].thread);\r
+  }\r
+\r
+  for (i = 0; i < numThreads; i++)\r
+    CMtThread_CloseEvents(&p->threads[i]);\r
+  return (res == SZ_OK) ? p->res : res;\r
+}\r
diff --git a/C/MtCoder.h b/C/MtCoder.h
new file mode 100755 (executable)
index 0000000..705208e
--- /dev/null
@@ -0,0 +1,98 @@
+/* MtCoder.h -- Multi-thread Coder\r
+2009-11-19 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __MT_CODER_H\r
+#define __MT_CODER_H\r
+\r
+#include "Threads.h"\r
+\r
+EXTERN_C_BEGIN\r
+\r
+typedef struct\r
+{\r
+  CThread thread;\r
+  CAutoResetEvent startEvent;\r
+  CAutoResetEvent finishedEvent;\r
+  int stop;\r
+  \r
+  THREAD_FUNC_TYPE func;\r
+  LPVOID param;\r
+  THREAD_FUNC_RET_TYPE res;\r
+} CLoopThread;\r
+\r
+void LoopThread_Construct(CLoopThread *p);\r
+void LoopThread_Close(CLoopThread *p);\r
+WRes LoopThread_Create(CLoopThread *p);\r
+WRes LoopThread_StopAndWait(CLoopThread *p);\r
+WRes LoopThread_StartSubThread(CLoopThread *p);\r
+WRes LoopThread_WaitSubThread(CLoopThread *p);\r
+\r
+#ifndef _7ZIP_ST\r
+#define NUM_MT_CODER_THREADS_MAX 32\r
+#else\r
+#define NUM_MT_CODER_THREADS_MAX 1\r
+#endif\r
+\r
+typedef struct\r
+{\r
+  UInt64 totalInSize;\r
+  UInt64 totalOutSize;\r
+  ICompressProgress *progress;\r
+  SRes res;\r
+  CCriticalSection cs;\r
+  UInt64 inSizes[NUM_MT_CODER_THREADS_MAX];\r
+  UInt64 outSizes[NUM_MT_CODER_THREADS_MAX];\r
+} CMtProgress;\r
+\r
+SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize);\r
+\r
+struct _CMtCoder;\r
+\r
+typedef struct\r
+{\r
+  struct _CMtCoder *mtCoder;\r
+  Byte *outBuf;\r
+  size_t outBufSize;\r
+  Byte *inBuf;\r
+  size_t inBufSize;\r
+  unsigned index;\r
+  CLoopThread thread;\r
+\r
+  Bool stopReading;\r
+  Bool stopWriting;\r
+  CAutoResetEvent canRead;\r
+  CAutoResetEvent canWrite;\r
+} CMtThread;\r
+\r
+typedef struct\r
+{\r
+  SRes (*Code)(void *p, unsigned index, Byte *dest, size_t *destSize,\r
+      const Byte *src, size_t srcSize, int finished);\r
+} IMtCoderCallback;\r
+\r
+typedef struct _CMtCoder\r
+{\r
+  size_t blockSize;\r
+  size_t destBlockSize;\r
+  unsigned numThreads;\r
+  \r
+  ISeqInStream *inStream;\r
+  ISeqOutStream *outStream;\r
+  ICompressProgress *progress;\r
+  ISzAlloc *alloc;\r
+\r
+  IMtCoderCallback *mtCallback;\r
+  CCriticalSection cs;\r
+  SRes res;\r
+\r
+  CMtProgress mtProgress;\r
+  CMtThread threads[NUM_MT_CODER_THREADS_MAX];\r
+} CMtCoder;\r
+\r
+void MtCoder_Construct(CMtCoder* p);\r
+void MtCoder_Destruct(CMtCoder* p);\r
+SRes MtCoder_Code(CMtCoder *p);\r
+\r
+EXTERN_C_END\r
+\r
+#endif\r
diff --git a/C/Ppmd.h b/C/Ppmd.h
new file mode 100755 (executable)
index 0000000..14344a7
--- /dev/null
+++ b/C/Ppmd.h
@@ -0,0 +1,81 @@
+/* Ppmd.h -- PPMD codec common code\r
+2010-03-12 : Igor Pavlov : Public domain\r
+This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */\r
+\r
+#ifndef __PPMD_H\r
+#define __PPMD_H\r
+\r
+#include "Types.h"\r
+#include "CpuArch.h"\r
+\r
+EXTERN_C_BEGIN\r
+\r
+#ifdef MY_CPU_32BIT\r
+  #define PPMD_32BIT\r
+#endif\r
+\r
+#define PPMD_INT_BITS 7\r
+#define PPMD_PERIOD_BITS 7\r
+#define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS))\r
+\r
+#define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift))\r
+#define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2)\r
+#define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob))\r
+#define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob))\r
+\r
+#define PPMD_N1 4\r
+#define PPMD_N2 4\r
+#define PPMD_N3 4\r
+#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4)\r
+#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4)\r
+\r
+/* SEE-contexts for PPM-contexts with masked symbols */\r
+typedef struct\r
+{\r
+  UInt16 Summ; /* Freq */\r
+  Byte Shift;  /* Speed of Freq change; low Shift is for fast change */\r
+  Byte Count;  /* Count to next change of Shift */\r
+} CPpmd_See;\r
+\r
+#define Ppmd_See_Update(p)  if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \\r
+    { (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); }\r
+\r
+typedef struct\r
+{\r
+  Byte Symbol;\r
+  Byte Freq;\r
+  UInt16 SuccessorLow;\r
+  UInt16 SuccessorHigh;\r
+} CPpmd_State;\r
+\r
+typedef\r
+  #ifdef PPMD_32BIT\r
+    CPpmd_State *\r
+  #else\r
+    UInt32\r
+  #endif\r
+  CPpmd_State_Ref;\r
+\r
+typedef\r
+  #ifdef PPMD_32BIT\r
+    void *\r
+  #else\r
+    UInt32\r
+  #endif\r
+  CPpmd_Void_Ref;\r
+\r
+typedef\r
+  #ifdef PPMD_32BIT\r
+    Byte *\r
+  #else\r
+    UInt32\r
+  #endif\r
+  CPpmd_Byte_Ref;\r
+\r
+#define PPMD_SetAllBitsIn256Bytes(p) \\r
+  { unsigned i; for (i = 0; i < 256 / sizeof(p[0]); i += 8) { \\r
+  p[i+7] = p[i+6] = p[i+5] = p[i+4] = p[i+3] = p[i+2] = p[i+1] = p[i+0] = ~(size_t)0; }}\r
+\r
+EXTERN_C_END\r
\r
+#endif\r
diff --git a/C/Ppmd7.c b/C/Ppmd7.c
new file mode 100755 (executable)
index 0000000..4b160cf
--- /dev/null
+++ b/C/Ppmd7.c
@@ -0,0 +1,708 @@
+/* Ppmd7.c -- PPMdH codec\r
+2010-03-12 : Igor Pavlov : Public domain\r
+This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */\r
+\r
+#include <memory.h>\r
+\r
+#include "Ppmd7.h"\r
+\r
+const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };\r
+static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};\r
+\r
+#define MAX_FREQ 124\r
+#define UNIT_SIZE 12\r
+\r
+#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)\r
+#define U2I(nu) (p->Units2Indx[(nu) - 1])\r
+#define I2U(indx) (p->Indx2Units[indx])\r
+\r
+#ifdef PPMD_32BIT\r
+  #define REF(ptr) (ptr)\r
+#else\r
+  #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))\r
+#endif\r
+\r
+#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))\r
+\r
+#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))\r
+#define STATS(ctx) Ppmd7_GetStats(p, ctx)\r
+#define ONE_STATE(ctx) Ppmd7Context_OneState(ctx)\r
+#define SUFFIX(ctx) CTX((ctx)->Suffix)\r
+\r
+typedef CPpmd7_Context * CTX_PTR;\r
+\r
+struct CPpmd7_Node_;\r
+\r
+typedef\r
+  #ifdef PPMD_32BIT\r
+    struct CPpmd7_Node_ *\r
+  #else\r
+    UInt32\r
+  #endif\r
+  CPpmd7_Node_Ref;\r
+\r
+typedef struct CPpmd7_Node_\r
+{\r
+  UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */\r
+  UInt16 NU;\r
+  CPpmd7_Node_Ref Next; /* must be at offset >= 4 */\r
+  CPpmd7_Node_Ref Prev;\r
+} CPpmd7_Node;\r
+\r
+#ifdef PPMD_32BIT\r
+  #define NODE(ptr) (ptr)\r
+#else\r
+  #define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs)))\r
+#endif\r
+\r
+void Ppmd7_Construct(CPpmd7 *p)\r
+{\r
+  unsigned i, k, m;\r
+\r
+  p->Base = 0;\r
+\r
+  for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)\r
+  {\r
+    unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);\r
+    do { p->Units2Indx[k++] = (Byte)i; } while(--step);\r
+    p->Indx2Units[i] = (Byte)k;\r
+  }\r
+\r
+  p->NS2BSIndx[0] = (0 << 1);\r
+  p->NS2BSIndx[1] = (1 << 1);\r
+  memset(p->NS2BSIndx + 2, (2 << 1), 9);\r
+  memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);\r
+\r
+  for (i = 0; i < 3; i++)\r
+    p->NS2Indx[i] = (Byte)i;\r
+  for (m = i, k = 1; i < 256; i++)\r
+  {\r
+    p->NS2Indx[i] = (Byte)m;\r
+    if (--k == 0)\r
+      k = (++m) - 2;\r
+  }\r
+\r
+  memset(p->HB2Flag, 0, 0x40);\r
+  memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);\r
+}\r
+\r
+void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc)\r
+{\r
+  alloc->Free(alloc, p->Base);\r
+  p->Size = 0;\r
+  p->Base = 0;\r
+}\r
+\r
+Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc)\r
+{\r
+  if (p->Base == 0 || p->Size != size)\r
+  {\r
+    Ppmd7_Free(p, alloc);\r
+    p->AlignOffset =\r
+      #ifdef PPMD_32BIT\r
+        (4 - size) & 3;\r
+      #else\r
+        4 - (size & 3);\r
+      #endif\r
+    if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size\r
+        #ifndef PPMD_32BIT\r
+        + UNIT_SIZE\r
+        #endif\r
+        )) == 0)\r
+      return False;\r
+    p->Size = size;\r
+  }\r
+  return True;\r
+}\r
+\r
+static void InsertNode(CPpmd7 *p, void *node, unsigned indx)\r
+{\r
+  *((CPpmd_Void_Ref *)node) = p->FreeList[indx];\r
+  p->FreeList[indx] = REF(node);\r
+}\r
+\r
+static void *RemoveNode(CPpmd7 *p, unsigned indx)\r
+{\r
+  CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]);\r
+  p->FreeList[indx] = *node;\r
+  return node;\r
+}\r
+\r
+static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx)\r
+{\r
+  unsigned i, nu = I2U(oldIndx) - I2U(newIndx);\r
+  ptr = (Byte *)ptr + U2B(I2U(newIndx));\r
+  if (I2U(i = U2I(nu)) != nu)\r
+  {\r
+    unsigned k = I2U(--i);\r
+    InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);\r
+  }\r
+  InsertNode(p, ptr, i);\r
+}\r
+\r
+static void GlueFreeBlocks(CPpmd7 *p)\r
+{\r
+  #ifdef PPMD_32BIT\r
+  CPpmd7_Node headItem;\r
+  CPpmd7_Node_Ref head = &headItem;\r
+  #else\r
+  CPpmd7_Node_Ref head = p->AlignOffset + p->Size;\r
+  #endif\r
+  \r
+  CPpmd7_Node_Ref n = head;\r
+  unsigned i;\r
+\r
+  p->GlueCount = 255;\r
+\r
+  /* create doubly-linked list of free blocks */\r
+  for (i = 0; i < PPMD_NUM_INDEXES; i++)\r
+  {\r
+    UInt16 nu = I2U(i);\r
+    CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i];\r
+    p->FreeList[i] = 0;\r
+    while (next != 0)\r
+    {\r
+      CPpmd7_Node *node = NODE(next);\r
+      node->Next = n;\r
+      n = NODE(n)->Prev = next;\r
+      next = *(const CPpmd7_Node_Ref *)node;\r
+      node->Stamp = 0;\r
+      node->NU = (UInt16)nu;\r
+    }\r
+  }\r
+  NODE(head)->Stamp = 1;\r
+  NODE(head)->Next = n;\r
+  NODE(n)->Prev = head;\r
+  if (p->LoUnit != p->HiUnit)\r
+    ((CPpmd7_Node *)p->LoUnit)->Stamp = 1;\r
+  \r
+  /* Glue free blocks */\r
+  while (n != head)\r
+  {\r
+    CPpmd7_Node *node = NODE(n);\r
+    UInt32 nu = (UInt32)node->NU;\r
+    for (;;)\r
+    {\r
+      CPpmd7_Node *node2 = NODE(n) + nu;\r
+      nu += node2->NU;\r
+      if (node2->Stamp != 0 || nu >= 0x10000)\r
+        break;\r
+      NODE(node2->Prev)->Next = node2->Next;\r
+      NODE(node2->Next)->Prev = node2->Prev;\r
+      node->NU = (UInt16)nu;\r
+    }\r
+    n = node->Next;\r
+  }\r
+  \r
+  /* Fill lists of free blocks */\r
+  for (n = NODE(head)->Next; n != head;)\r
+  {\r
+    CPpmd7_Node *node = NODE(n);\r
+    unsigned nu;\r
+    CPpmd7_Node_Ref next = node->Next;\r
+    for (nu = node->NU; nu > 128; nu -= 128, node += 128)\r
+      InsertNode(p, node, PPMD_NUM_INDEXES - 1);\r
+    if (I2U(i = U2I(nu)) != nu)\r
+    {\r
+      unsigned k = I2U(--i);\r
+      InsertNode(p, node + k, nu - k - 1);\r
+    }\r
+    InsertNode(p, node, i);\r
+    n = next;\r
+  }\r
+}\r
+\r
+static void *AllocUnitsRare(CPpmd7 *p, unsigned indx)\r
+{\r
+  unsigned i;\r
+  void *retVal;\r
+  if (p->GlueCount == 0)\r
+  {\r
+    GlueFreeBlocks(p);\r
+    if (p->FreeList[indx] != 0)\r
+      return RemoveNode(p, indx);\r
+  }\r
+  i = indx;\r
+  do\r
+  {\r
+    if (++i == PPMD_NUM_INDEXES)\r
+    {\r
+      UInt32 numBytes = U2B(I2U(indx));\r
+      p->GlueCount--;\r
+      return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL);\r
+    }\r
+  }\r
+  while (p->FreeList[i] == 0);\r
+  retVal = RemoveNode(p, i);\r
+  SplitBlock(p, retVal, i, indx);\r
+  return retVal;\r
+}\r
+\r
+static void *AllocUnits(CPpmd7 *p, unsigned indx)\r
+{\r
+  UInt32 numBytes;\r
+  if (p->FreeList[indx] != 0)\r
+    return RemoveNode(p, indx);\r
+  numBytes = U2B(I2U(indx));\r
+  if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit))\r
+  {\r
+    void *retVal = p->LoUnit;\r
+    p->LoUnit += numBytes;\r
+    return retVal;\r
+  }\r
+  return AllocUnitsRare(p, indx);\r
+}\r
+\r
+#define MyMem12Cpy(dest, src, num) \\r
+  { UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \\r
+    do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); }\r
+\r
+static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)\r
+{\r
+  unsigned i0 = U2I(oldNU);\r
+  unsigned i1 = U2I(newNU);\r
+  if (i0 == i1)\r
+    return oldPtr;\r
+  if (p->FreeList[i1] != 0)\r
+  {\r
+    void *ptr = RemoveNode(p, i1);\r
+    MyMem12Cpy(ptr, oldPtr, newNU);\r
+    InsertNode(p, oldPtr, i0);\r
+    return ptr;\r
+  }\r
+  SplitBlock(p, oldPtr, i0, i1);\r
+  return oldPtr;\r
+}\r
+\r
+#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))\r
+\r
+static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)\r
+{\r
+  (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);\r
+  (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);\r
+}\r
+\r
+static void RestartModel(CPpmd7 *p)\r
+{\r
+  unsigned i, k, m;\r
+\r
+  memset(p->FreeList, 0, sizeof(p->FreeList));\r
+  p->Text = p->Base + p->AlignOffset;\r
+  p->HiUnit = p->Text + p->Size;\r
+  p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;\r
+  p->GlueCount = 0;\r
+\r
+  p->OrderFall = p->MaxOrder;\r
+  p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;\r
+  p->PrevSuccess = 0;\r
+\r
+  p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */\r
+  p->MinContext->Suffix = 0;\r
+  p->MinContext->NumStats = 256;\r
+  p->MinContext->SummFreq = 256 + 1;\r
+  p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */\r
+  p->LoUnit += U2B(256 / 2);\r
+  p->MinContext->Stats = REF(p->FoundState);\r
+  for (i = 0; i < 256; i++)\r
+  {\r
+    CPpmd_State *s = &p->FoundState[i];\r
+    s->Symbol = (Byte)i;\r
+    s->Freq = 1;\r
+    SetSuccessor(s, 0);\r
+  }\r
+\r
+  for (i = 0; i < 128; i++)\r
+    for (k = 0; k < 8; k++)\r
+    {\r
+      UInt16 *dest = p->BinSumm[i] + k;\r
+      UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2));\r
+      for (m = 0; m < 64; m += 8)\r
+        dest[m] = val;\r
+    }\r
+  \r
+  for (i = 0; i < 25; i++)\r
+    for (k = 0; k < 16; k++)\r
+    {\r
+      CPpmd_See *s = &p->See[i][k];\r
+      s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4));\r
+      s->Count = 4;\r
+    }\r
+}\r
+\r
+void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)\r
+{\r
+  p->MaxOrder = maxOrder;\r
+  RestartModel(p);\r
+  p->DummySee.Shift = PPMD_PERIOD_BITS;\r
+  p->DummySee.Summ = 0; /* unused */\r
+  p->DummySee.Count = 64; /* unused */\r
+}\r
+\r
+static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip)\r
+{\r
+  CPpmd_State upState;\r
+  CTX_PTR c = p->MinContext;\r
+  CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);\r
+  CPpmd_State *ps[PPMD7_MAX_ORDER];\r
+  unsigned numPs = 0;\r
+  \r
+  if (!skip)\r
+    ps[numPs++] = p->FoundState;\r
+  \r
+  while (c->Suffix)\r
+  {\r
+    CPpmd_Void_Ref successor;\r
+    CPpmd_State *s;\r
+    c = SUFFIX(c);\r
+    if (c->NumStats != 1)\r
+    {\r
+      for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++);\r
+    }\r
+    else\r
+      s = ONE_STATE(c);\r
+    successor = SUCCESSOR(s);\r
+    if (successor != upBranch)\r
+    {\r
+      c = CTX(successor);\r
+      if (numPs == 0)\r
+        return c;\r
+      break;\r
+    }\r
+    ps[numPs++] = s;\r
+  }\r
+  \r
+  upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch);\r
+  SetSuccessor(&upState, upBranch + 1);\r
+  \r
+  if (c->NumStats == 1)\r
+    upState.Freq = ONE_STATE(c)->Freq;\r
+  else\r
+  {\r
+    UInt32 cf, s0;\r
+    CPpmd_State *s;\r
+    for (s = STATS(c); s->Symbol != upState.Symbol; s++);\r
+    cf = s->Freq - 1;\r
+    s0 = c->SummFreq - c->NumStats - cf;\r
+    upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0))));\r
+  }\r
+\r
+  do\r
+  {\r
+    /* Create Child */\r
+    CTX_PTR c1; /* = AllocContext(p); */\r
+    if (p->HiUnit != p->LoUnit)\r
+      c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE);\r
+    else if (p->FreeList[0] != 0)\r
+      c1 = (CTX_PTR)RemoveNode(p, 0);\r
+    else\r
+    {\r
+      c1 = (CTX_PTR)AllocUnitsRare(p, 0);\r
+      if (!c1)\r
+        return NULL;\r
+    }\r
+    c1->NumStats = 1;\r
+    *ONE_STATE(c1) = upState;\r
+    c1->Suffix = REF(c);\r
+    SetSuccessor(ps[--numPs], REF(c1));\r
+    c = c1;\r
+  }\r
+  while (numPs != 0);\r
+  \r
+  return c;\r
+}\r
+\r
+static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)\r
+{\r
+  CPpmd_State tmp = *t1;\r
+  *t1 = *t2;\r
+  *t2 = tmp;\r
+}\r
+\r
+static void UpdateModel(CPpmd7 *p)\r
+{\r
+  CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState);\r
+  CTX_PTR c;\r
+  unsigned s0, ns;\r
+  \r
+  if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)\r
+  {\r
+    c = SUFFIX(p->MinContext);\r
+    \r
+    if (c->NumStats == 1)\r
+    {\r
+      CPpmd_State *s = ONE_STATE(c);\r
+      if (s->Freq < 32)\r
+        s->Freq++;\r
+    }\r
+    else\r
+    {\r
+      CPpmd_State *s = STATS(c);\r
+      if (s->Symbol != p->FoundState->Symbol)\r
+      {\r
+        do { s++; } while (s->Symbol != p->FoundState->Symbol);\r
+        if (s[0].Freq >= s[-1].Freq)\r
+        {\r
+          SwapStates(&s[0], &s[-1]);\r
+          s--;\r
+        }\r
+      }\r
+      if (s->Freq < MAX_FREQ - 9)\r
+      {\r
+        s->Freq += 2;\r
+        c->SummFreq += 2;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (p->OrderFall == 0)\r
+  {\r
+    p->MinContext = p->MaxContext = CreateSuccessors(p, True);\r
+    if (p->MinContext == 0)\r
+    {\r
+      RestartModel(p);\r
+      return;\r
+    }\r
+    SetSuccessor(p->FoundState, REF(p->MinContext));\r
+    return;\r
+  }\r
+  \r
+  *p->Text++ = p->FoundState->Symbol;\r
+  successor = REF(p->Text);\r
+  if (p->Text >= p->UnitsStart)\r
+  {\r
+    RestartModel(p);\r
+    return;\r
+  }\r
+  \r
+  if (fSuccessor)\r
+  {\r
+    if (fSuccessor <= successor)\r
+    {\r
+      CTX_PTR cs = CreateSuccessors(p, False);\r
+      if (cs == NULL)\r
+      {\r
+        RestartModel(p);\r
+        return;\r
+      }\r
+      fSuccessor = REF(cs);\r
+    }\r
+    if (--p->OrderFall == 0)\r
+    {\r
+      successor = fSuccessor;\r
+      p->Text -= (p->MaxContext != p->MinContext);\r
+    }\r
+  }\r
+  else\r
+  {\r
+    SetSuccessor(p->FoundState, successor);\r
+    fSuccessor = REF(p->MinContext);\r
+  }\r
+  \r
+  s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1);\r
+  \r
+  for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c))\r
+  {\r
+    unsigned ns1;\r
+    UInt32 cf, sf;\r
+    if ((ns1 = c->NumStats) != 1)\r
+    {\r
+      if ((ns1 & 1) == 0)\r
+      {\r
+        /* Expand for one UNIT */\r
+        unsigned oldNU = ns1 >> 1;\r
+        unsigned i = U2I(oldNU);\r
+        if (i != U2I(oldNU + 1))\r
+        {\r
+          void *ptr = AllocUnits(p, i + 1);\r
+          void *oldPtr;\r
+          if (!ptr)\r
+          {\r
+            RestartModel(p);\r
+            return;\r
+          }\r
+          oldPtr = STATS(c);\r
+          MyMem12Cpy(ptr, oldPtr, oldNU);\r
+          InsertNode(p, oldPtr, i);\r
+          c->Stats = STATS_REF(ptr);\r
+        }\r
+      }\r
+      c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1)));\r
+    }\r
+    else\r
+    {\r
+      CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0);\r
+      if (!s)\r
+      {\r
+        RestartModel(p);\r
+        return;\r
+      }\r
+      *s = *ONE_STATE(c);\r
+      c->Stats = REF(s);\r
+      if (s->Freq < MAX_FREQ / 4 - 1)\r
+        s->Freq <<= 1;\r
+      else\r
+        s->Freq = MAX_FREQ - 4;\r
+      c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3));\r
+    }\r
+    cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6);\r
+    sf = (UInt32)s0 + c->SummFreq;\r
+    if (cf < 6 * sf)\r
+    {\r
+      cf = 1 + (cf > sf) + (cf >= 4 * sf);\r
+      c->SummFreq += 3;\r
+    }\r
+    else\r
+    {\r
+      cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);\r
+      c->SummFreq = (UInt16)(c->SummFreq + cf);\r
+    }\r
+    {\r
+      CPpmd_State *s = STATS(c) + ns1;\r
+      SetSuccessor(s, successor);\r
+      s->Symbol = p->FoundState->Symbol;\r
+      s->Freq = (Byte)cf;\r
+      c->NumStats = (UInt16)(ns1 + 1);\r
+    }\r
+  }\r
+  p->MaxContext = p->MinContext = CTX(fSuccessor);\r
+}\r
+  \r
+static void Rescale(CPpmd7 *p)\r
+{\r
+  unsigned i, adder, sumFreq, escFreq;\r
+  CPpmd_State *stats = STATS(p->MinContext);\r
+  CPpmd_State *s = p->FoundState;\r
+  {\r
+    CPpmd_State tmp = *s;\r
+    for (; s != stats; s--)\r
+      s[0] = s[-1];\r
+    *s = tmp;\r
+  }\r
+  escFreq = p->MinContext->SummFreq - s->Freq;\r
+  s->Freq += 4;\r
+  adder = (p->OrderFall != 0);\r
+  s->Freq = (Byte)((s->Freq + adder) >> 1);\r
+  sumFreq = s->Freq;\r
+  \r
+  i = p->MinContext->NumStats - 1;\r
+  do\r
+  {\r
+    escFreq -= (++s)->Freq;\r
+    s->Freq = (Byte)((s->Freq + adder) >> 1);\r
+    sumFreq += s->Freq;\r
+    if (s[0].Freq > s[-1].Freq)\r
+    {\r
+      CPpmd_State *s1 = s;\r
+      CPpmd_State tmp = *s1;\r
+      do\r
+        s1[0] = s1[-1];\r
+      while (--s1 != stats && tmp.Freq > s1[-1].Freq);\r
+      *s1 = tmp;\r
+    }\r
+  }\r
+  while (--i);\r
+  \r
+  if (s->Freq == 0)\r
+  {\r
+    unsigned numStats = p->MinContext->NumStats;\r
+    unsigned n0, n1;\r
+    do { i++; } while ((--s)->Freq == 0);\r
+    escFreq += i;\r
+    p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i);\r
+    if (p->MinContext->NumStats == 1)\r
+    {\r
+      CPpmd_State tmp = *stats;\r
+      do\r
+      {\r
+        tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1));\r
+        escFreq >>= 1;\r
+      }\r
+      while (escFreq > 1);\r
+      InsertNode(p, stats, U2I(((numStats + 1) >> 1)));\r
+      *(p->FoundState = ONE_STATE(p->MinContext)) = tmp;\r
+      return;\r
+    }\r
+    n0 = (numStats + 1) >> 1;\r
+    n1 = (p->MinContext->NumStats + 1) >> 1;\r
+    if (n0 != n1)\r
+      p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));\r
+  }\r
+  p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));\r
+  p->FoundState = STATS(p->MinContext);\r
+}\r
+\r
+CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)\r
+{\r
+  CPpmd_See *see;\r
+  unsigned nonMasked = p->MinContext->NumStats - numMasked;\r
+  if (p->MinContext->NumStats != 256)\r
+  {\r
+    see = p->See[p->NS2Indx[nonMasked - 1]] +\r
+        (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) +\r
+        2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) +\r
+        4 * (numMasked > nonMasked) +\r
+        p->HiBitsFlag;\r
+    {\r
+      unsigned r = (see->Summ >> see->Shift);\r
+      see->Summ = (UInt16)(see->Summ - r);\r
+      *escFreq = r + (r == 0);\r
+    }\r
+  }\r
+  else\r
+  {\r
+    see = &p->DummySee;\r
+    *escFreq = 1;\r
+  }\r
+  return see;\r
+}\r
+\r
+static void NextContext(CPpmd7 *p)\r
+{\r
+  CTX_PTR c = CTX(SUCCESSOR(p->FoundState));\r
+  if (p->OrderFall == 0 && (Byte *)c > p->Text)\r
+    p->MinContext = p->MaxContext = c;\r
+  else\r
+    UpdateModel(p);\r
+}\r
+\r
+void Ppmd7_Update1(CPpmd7 *p)\r
+{\r
+  CPpmd_State *s = p->FoundState;\r
+  s->Freq += 4;\r
+  p->MinContext->SummFreq += 4;\r
+  if (s[0].Freq > s[-1].Freq)\r
+  {\r
+    SwapStates(&s[0], &s[-1]);\r
+    p->FoundState = --s;\r
+    if (s->Freq > MAX_FREQ)\r
+      Rescale(p);\r
+  }\r
+  NextContext(p);\r
+}\r
+\r
+void Ppmd7_Update1_0(CPpmd7 *p)\r
+{\r
+  p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq);\r
+  p->RunLength += p->PrevSuccess;\r
+  p->MinContext->SummFreq += 4;\r
+  if ((p->FoundState->Freq += 4) > MAX_FREQ)\r
+    Rescale(p);\r
+  NextContext(p);\r
+}\r
+\r
+void Ppmd7_UpdateBin(CPpmd7 *p)\r
+{\r
+  p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0));\r
+  p->PrevSuccess = 1;\r
+  p->RunLength++;\r
+  NextContext(p);\r
+}\r
+\r
+void Ppmd7_Update2(CPpmd7 *p)\r
+{\r
+  p->MinContext->SummFreq += 4;\r
+  if ((p->FoundState->Freq += 4) > MAX_FREQ)\r
+    Rescale(p);\r
+  p->RunLength = p->InitRL;\r
+  UpdateModel(p);\r
+}\r
diff --git a/C/Ppmd7.h b/C/Ppmd7.h
new file mode 100755 (executable)
index 0000000..56e81eb
--- /dev/null
+++ b/C/Ppmd7.h
@@ -0,0 +1,140 @@
+/* Ppmd7.h -- PPMdH compression codec\r
+2010-03-12 : Igor Pavlov : Public domain\r
+This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */\r
+\r
+/* This code supports virtual RangeDecoder and includes the implementation\r
+of RangeCoder from 7z, instead of RangeCoder from original PPMd var.H.\r
+If you need the compatibility with original PPMd var.H, you can use external RangeDecoder */\r
+\r
+#ifndef __PPMD7_H\r
+#define __PPMD7_H\r
+\r
+#include "Ppmd.h"\r
+\r
+EXTERN_C_BEGIN\r
+\r
+#define PPMD7_MIN_ORDER 2\r
+#define PPMD7_MAX_ORDER 64\r
+\r
+#define PPMD7_MIN_MEM_SIZE (1 << 11)\r
+#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3)\r
+\r
+struct CPpmd7_Context_;\r
+\r
+typedef\r
+  #ifdef PPMD_32BIT\r
+    struct CPpmd7_Context_ *\r
+  #else\r
+    UInt32\r
+  #endif\r
+  CPpmd7_Context_Ref;\r
+\r
+typedef struct CPpmd7_Context_\r
+{\r
+  UInt16 NumStats;\r
+  UInt16 SummFreq;\r
+  CPpmd_State_Ref Stats;\r
+  CPpmd7_Context_Ref Suffix;\r
+} CPpmd7_Context;\r
+\r
+#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)\r
+\r
+typedef struct\r
+{\r
+  CPpmd7_Context *MinContext, *MaxContext;\r
+  CPpmd_State *FoundState;\r
+  unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, HiBitsFlag;\r
+  Int32 RunLength, InitRL; /* must be 32-bit at least */\r
+\r
+  UInt32 Size;\r
+  UInt32 GlueCount;\r
+  Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;\r
+  UInt32 AlignOffset;\r
+\r
+  Byte Indx2Units[PPMD_NUM_INDEXES];\r
+  Byte Units2Indx[128];\r
+  CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];\r
+  Byte NS2Indx[256], NS2BSIndx[256], HB2Flag[256];\r
+  CPpmd_See DummySee, See[25][16];\r
+  UInt16 BinSumm[128][64];\r
+} CPpmd7;\r
+\r
+void Ppmd7_Construct(CPpmd7 *p);\r
+Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc);\r
+void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc);\r
+void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder);\r
+#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)\r
+\r
+\r
+/* ---------- Internal Functions ---------- */\r
+\r
+extern const Byte PPMD7_kExpEscape[16];\r
+\r
+#ifdef PPMD_32BIT\r
+  #define Ppmd7_GetPtr(p, ptr) (ptr)\r
+  #define Ppmd7_GetContext(p, ptr) (ptr)\r
+  #define Ppmd7_GetStats(p, ctx) ((ctx)->Stats)\r
+#else\r
+  #define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs)))\r
+  #define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs)))\r
+  #define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats)))\r
+#endif\r
+\r
+void Ppmd7_Update1(CPpmd7 *p);\r
+void Ppmd7_Update1_0(CPpmd7 *p);\r
+void Ppmd7_Update2(CPpmd7 *p);\r
+void Ppmd7_UpdateBin(CPpmd7 *p);\r
+\r
+#define Ppmd7_GetBinSumm(p) \\r
+    &p->BinSumm[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \\r
+    p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \\r
+    (p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \\r
+    2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \\r
+    ((p->RunLength >> 26) & 0x20)]\r
+\r
+CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale);\r
+\r
+\r
+/* ---------- Decode ---------- */\r
+\r
+typedef struct\r
+{\r
+  UInt32 (*GetThreshold)(void *p, UInt32 total);\r
+  void (*Decode)(void *p, UInt32 start, UInt32 size);\r
+  UInt32 (*DecodeBit)(void *p, UInt32 size0);\r
+} IPpmd7_RangeDec;\r
+\r
+typedef struct\r
+{\r
+  IPpmd7_RangeDec p;\r
+  UInt32 Range;\r
+  UInt32 Code;\r
+  IByteIn *Stream;\r
+} CPpmd7z_RangeDec;\r
+\r
+void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p);\r
+Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p);\r
+#define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0)\r
+\r
+int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc);\r
+\r
+\r
+/* ---------- Encode ---------- */\r
+\r
+typedef struct\r
+{\r
+  UInt64 Low;\r
+  UInt32 Range;\r
+  Byte Cache;\r
+  UInt64 CacheSize;\r
+  IByteOut *Stream;\r
+} CPpmd7z_RangeEnc;\r
+\r
+void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p);\r
+void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p);\r
+\r
+void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol);\r
+\r
+EXTERN_C_END\r
\r
+#endif\r
diff --git a/C/Ppmd7Dec.c b/C/Ppmd7Dec.c
new file mode 100755 (executable)
index 0000000..d6608e8
--- /dev/null
@@ -0,0 +1,187 @@
+/* Ppmd7Dec.c -- PPMdH Decoder\r
+2010-03-12 : Igor Pavlov : Public domain\r
+This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */\r
+\r
+#include "Ppmd7.h"\r
+\r
+#define kTopValue (1 << 24)\r
+\r
+Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)\r
+{\r
+  unsigned i;\r
+  p->Code = 0;\r
+  p->Range = 0xFFFFFFFF;\r
+  if (p->Stream->Read((void *)p->Stream) != 0)\r
+    return False;\r
+  for (i = 0; i < 4; i++)\r
+    p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);\r
+  return (p->Code < 0xFFFFFFFF);\r
+}\r
+\r
+static UInt32 Range_GetThreshold(void *pp, UInt32 total)\r
+{\r
+  CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;\r
+  return (p->Code) / (p->Range /= total);\r
+}\r
+\r
+static void Range_Normalize(CPpmd7z_RangeDec *p)\r
+{\r
+  if (p->Range < kTopValue)\r
+  {\r
+    p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);\r
+    p->Range <<= 8;\r
+    if (p->Range < kTopValue)\r
+    {\r
+      p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);\r
+      p->Range <<= 8;\r
+    }\r
+  }\r
+}\r
+\r
+static void Range_Decode(void *pp, UInt32 start, UInt32 size)\r
+{\r
+  CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;\r
+  p->Code -= start * p->Range;\r
+  p->Range *= size;\r
+  Range_Normalize(p);\r
+}\r
+\r
+static UInt32 Range_DecodeBit(void *pp, UInt32 size0)\r
+{\r
+  CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;\r
+  UInt32 newBound = (p->Range >> 14) * size0;\r
+  UInt32 symbol;\r
+  if (p->Code < newBound)\r
+  {\r
+    symbol = 0;\r
+    p->Range = newBound;\r
+  }\r
+  else\r
+  {\r
+    symbol = 1;\r
+    p->Code -= newBound;\r
+    p->Range -= newBound;\r
+  }\r
+  Range_Normalize(p);\r
+  return symbol;\r
+}\r
+\r
+void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)\r
+{\r
+  p->p.GetThreshold = Range_GetThreshold;\r
+  p->p.Decode = Range_Decode;\r
+  p->p.DecodeBit = Range_DecodeBit;\r
+}\r
+\r
+\r
+#define MASK(sym) ((signed char *)charMask)[sym]\r
+\r
+int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc)\r
+{\r
+  size_t charMask[256 / sizeof(size_t)];\r
+  if (p->MinContext->NumStats != 1)\r
+  {\r
+    CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);\r
+    unsigned i;\r
+    UInt32 count, hiCnt;\r
+    if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq))\r
+    {\r
+      Byte symbol;\r
+      rc->Decode(rc, 0, s->Freq);\r
+      p->FoundState = s;\r
+      symbol = s->Symbol;\r
+      Ppmd7_Update1_0(p);\r
+      return symbol;\r
+    }\r
+    p->PrevSuccess = 0;\r
+    i = p->MinContext->NumStats - 1;\r
+    do\r
+    {\r
+      if ((hiCnt += (++s)->Freq) > count)\r
+      {\r
+        Byte symbol;\r
+        rc->Decode(rc, hiCnt - s->Freq, s->Freq);\r
+        p->FoundState = s;\r
+        symbol = s->Symbol;\r
+        Ppmd7_Update1(p);\r
+        return symbol;\r
+      }\r
+    }\r
+    while (--i);\r
+    if (count >= p->MinContext->SummFreq)\r
+      return -2;\r
+    p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];\r
+    rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt);\r
+    PPMD_SetAllBitsIn256Bytes(charMask);\r
+    MASK(s->Symbol) = 0;\r
+    i = p->MinContext->NumStats - 1;\r
+    do { MASK((--s)->Symbol) = 0; } while (--i);\r
+  }\r
+  else\r
+  {\r
+    UInt16 *prob = Ppmd7_GetBinSumm(p);\r
+    if (rc->DecodeBit(rc, *prob) == 0)\r
+    {\r
+      Byte symbol;\r
+      *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);\r
+      symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;\r
+      Ppmd7_UpdateBin(p);\r
+      return symbol;\r
+    }\r
+    *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);\r
+    p->InitEsc = PPMD7_kExpEscape[*prob >> 10];\r
+    PPMD_SetAllBitsIn256Bytes(charMask);\r
+    MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;\r
+    p->PrevSuccess = 0;\r
+  }\r
+  for (;;)\r
+  {\r
+    CPpmd_State *ps[256], *s;\r
+    UInt32 freqSum, count, hiCnt;\r
+    CPpmd_See *see;\r
+    unsigned i, num, numMasked = p->MinContext->NumStats;\r
+    do\r
+    {\r
+      p->OrderFall++;\r
+      if (!p->MinContext->Suffix)\r
+        return -1;\r
+      p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);\r
+    }\r
+    while (p->MinContext->NumStats == numMasked);\r
+    hiCnt = 0;\r
+    s = Ppmd7_GetStats(p, p->MinContext);\r
+    i = 0;\r
+    num = p->MinContext->NumStats - numMasked;\r
+    do\r
+    {\r
+      int k = (int)(MASK(s->Symbol));\r
+      hiCnt += (s->Freq & k);\r
+      ps[i] = s++;\r
+      i -= k;\r
+    }\r
+    while (i != num);\r
+    \r
+    see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);\r
+    freqSum += hiCnt;\r
+    count = rc->GetThreshold(rc, freqSum);\r
+    \r
+    if (count < hiCnt)\r
+    {\r
+      Byte symbol;\r
+      CPpmd_State **pps = ps;\r
+      for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);\r
+      s = *pps;\r
+      rc->Decode(rc, hiCnt - s->Freq, s->Freq);\r
+      Ppmd_See_Update(see);\r
+      p->FoundState = s;\r
+      symbol = s->Symbol;\r
+      Ppmd7_Update2(p);\r
+      return symbol;\r
+    }\r
+    if (count >= freqSum)\r
+      return -2;\r
+    rc->Decode(rc, hiCnt, freqSum - hiCnt);\r
+    see->Summ = (UInt16)(see->Summ + freqSum);\r
+    do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);\r
+  }\r
+}\r
diff --git a/C/Ppmd7Enc.c b/C/Ppmd7Enc.c
new file mode 100755 (executable)
index 0000000..b1fecae
--- /dev/null
@@ -0,0 +1,185 @@
+/* Ppmd7Enc.c -- PPMdH Encoder\r
+2010-03-12 : Igor Pavlov : Public domain\r
+This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */\r
+\r
+#include "Ppmd7.h"\r
+\r
+#define kTopValue (1 << 24)\r
+\r
+void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p)\r
+{\r
+  p->Low = 0;\r
+  p->Range = 0xFFFFFFFF;\r
+  p->Cache = 0;\r
+  p->CacheSize = 1;\r
+}\r
+\r
+static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p)\r
+{\r
+  if ((UInt32)p->Low < (UInt32)0xFF000000 || (unsigned)(p->Low >> 32) != 0)\r
+  {\r
+    Byte temp = p->Cache;\r
+    do\r
+    {\r
+      p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32)));\r
+      temp = 0xFF;\r
+    }\r
+    while(--p->CacheSize != 0);\r
+    p->Cache = (Byte)((UInt32)p->Low >> 24);\r
+  }\r
+  p->CacheSize++;\r
+  p->Low = (UInt32)p->Low << 8;\r
+}\r
+\r
+static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total)\r
+{\r
+  p->Low += start * (p->Range /= total);\r
+  p->Range *= size;\r
+  while (p->Range < kTopValue)\r
+  {\r
+    p->Range <<= 8;\r
+    RangeEnc_ShiftLow(p);\r
+  }\r
+}\r
+\r
+static void RangeEnc_EncodeBit_0(CPpmd7z_RangeEnc *p, UInt32 size0)\r
+{\r
+  p->Range = (p->Range >> 14) * size0;\r
+  while (p->Range < kTopValue)\r
+  {\r
+    p->Range <<= 8;\r
+    RangeEnc_ShiftLow(p);\r
+  }\r
+}\r
+\r
+static void RangeEnc_EncodeBit_1(CPpmd7z_RangeEnc *p, UInt32 size0)\r
+{\r
+  UInt32 newBound = (p->Range >> 14) * size0;\r
+  p->Low += newBound;\r
+  p->Range -= newBound;\r
+  while (p->Range < kTopValue)\r
+  {\r
+    p->Range <<= 8;\r
+    RangeEnc_ShiftLow(p);\r
+  }\r
+}\r
+\r
+void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p)\r
+{\r
+  unsigned i;\r
+  for (i = 0; i < 5; i++)\r
+    RangeEnc_ShiftLow(p);\r
+}\r
+\r
+\r
+#define MASK(sym) ((signed char *)charMask)[sym]\r
+\r
+void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol)\r
+{\r
+  size_t charMask[256 / sizeof(size_t)];\r
+  if (p->MinContext->NumStats != 1)\r
+  {\r
+    CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);\r
+    UInt32 sum;\r
+    unsigned i;\r
+    if (s->Symbol == symbol)\r
+    {\r
+      RangeEnc_Encode(rc, 0, s->Freq, p->MinContext->SummFreq);\r
+      p->FoundState = s;\r
+      Ppmd7_Update1_0(p);\r
+      return;\r
+    }\r
+    p->PrevSuccess = 0;\r
+    sum = s->Freq;\r
+    i = p->MinContext->NumStats - 1;\r
+    do\r
+    {\r
+      if ((++s)->Symbol == symbol)\r
+      {\r
+        RangeEnc_Encode(rc, sum, s->Freq, p->MinContext->SummFreq);\r
+        p->FoundState = s;\r
+        Ppmd7_Update1(p);\r
+        return;\r
+      }\r
+      sum += s->Freq;\r
+    }\r
+    while (--i);\r
+    \r
+    p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];\r
+    PPMD_SetAllBitsIn256Bytes(charMask);\r
+    MASK(s->Symbol) = 0;\r
+    i = p->MinContext->NumStats - 1;\r
+    do { MASK((--s)->Symbol) = 0; } while (--i);\r
+    RangeEnc_Encode(rc, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq);\r
+  }\r
+  else\r
+  {\r
+    UInt16 *prob = Ppmd7_GetBinSumm(p);\r
+    CPpmd_State *s = Ppmd7Context_OneState(p->MinContext);\r
+    if (s->Symbol == symbol)\r
+    {\r
+      RangeEnc_EncodeBit_0(rc, *prob);\r
+      *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);\r
+      p->FoundState = s;\r
+      Ppmd7_UpdateBin(p);\r
+      return;\r
+    }\r
+    else\r
+    {\r
+      RangeEnc_EncodeBit_1(rc, *prob);\r
+      *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);\r
+      p->InitEsc = PPMD7_kExpEscape[*prob >> 10];\r
+      PPMD_SetAllBitsIn256Bytes(charMask);\r
+      MASK(s->Symbol) = 0;\r
+      p->PrevSuccess = 0;\r
+    }\r
+  }\r
+  for (;;)\r
+  {\r
+    UInt32 escFreq;\r
+    CPpmd_See *see;\r
+    CPpmd_State *s;\r
+    UInt32 sum;\r
+    unsigned i, numMasked = p->MinContext->NumStats;\r
+    do\r
+    {\r
+      p->OrderFall++;\r
+      if (!p->MinContext->Suffix)\r
+        return; /* EndMarker (symbol = -1) */\r
+      p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);\r
+    }\r
+    while (p->MinContext->NumStats == numMasked);\r
+    \r
+    see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq);\r
+    s = Ppmd7_GetStats(p, p->MinContext);\r
+    sum = 0;\r
+    i = p->MinContext->NumStats;\r
+    do\r
+    {\r
+      int cur = s->Symbol;\r
+      if (cur == symbol)\r
+      {\r
+        UInt32 low = sum;\r
+        CPpmd_State *s1 = s;\r
+        do\r
+        {\r
+          sum += (s->Freq & (int)(MASK(s->Symbol)));\r
+          s++;\r
+        }\r
+        while (--i);\r
+        RangeEnc_Encode(rc, low, s1->Freq, sum + escFreq);\r
+        Ppmd_See_Update(see);\r
+        p->FoundState = s1;\r
+        Ppmd7_Update2(p);\r
+        return;\r
+      }\r
+      sum += (s->Freq & (int)(MASK(cur)));\r
+      MASK(cur) = 0;\r
+      s++;\r
+    }\r
+    while (--i);\r
+    \r
+    RangeEnc_Encode(rc, sum, escFreq, sum + escFreq);\r
+    see->Summ = (UInt16)(see->Summ + sum + escFreq);\r
+  }\r
+}\r
diff --git a/C/Ppmd8.c b/C/Ppmd8.c
new file mode 100755 (executable)
index 0000000..4fe723f
--- /dev/null
+++ b/C/Ppmd8.c
@@ -0,0 +1,1120 @@
+/* Ppmd8.c -- PPMdI codec\r
+2010-03-24 : Igor Pavlov : Public domain\r
+This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */\r
+\r
+#include <memory.h>\r
+\r
+#include "Ppmd8.h"\r
+\r
+const Byte PPMD8_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };\r
+static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};\r
+\r
+#define MAX_FREQ 124\r
+#define UNIT_SIZE 12\r
+\r
+#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)\r
+#define U2I(nu) (p->Units2Indx[(nu) - 1])\r
+#define I2U(indx) (p->Indx2Units[indx])\r
+\r
+#ifdef PPMD_32BIT\r
+  #define REF(ptr) (ptr)\r
+#else\r
+  #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))\r
+#endif\r
+\r
+#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))\r
+\r
+#define CTX(ref) ((CPpmd8_Context *)Ppmd8_GetContext(p, ref))\r
+#define STATS(ctx) Ppmd8_GetStats(p, ctx)\r
+#define ONE_STATE(ctx) Ppmd8Context_OneState(ctx)\r
+#define SUFFIX(ctx) CTX((ctx)->Suffix)\r
+\r
+typedef CPpmd8_Context * CTX_PTR;\r
+\r
+struct CPpmd8_Node_;\r
+\r
+typedef\r
+  #ifdef PPMD_32BIT\r
+    struct CPpmd8_Node_ *\r
+  #else\r
+    UInt32\r
+  #endif\r
+  CPpmd8_Node_Ref;\r
+\r
+typedef struct CPpmd8_Node_\r
+{\r
+  UInt32 Stamp;\r
+  CPpmd8_Node_Ref Next;\r
+  UInt32 NU;\r
+} CPpmd8_Node;\r
+\r
+#ifdef PPMD_32BIT\r
+  #define NODE(ptr) (ptr)\r
+#else\r
+  #define NODE(offs) ((CPpmd8_Node *)(p->Base + (offs)))\r
+#endif\r
+\r
+#define EMPTY_NODE 0xFFFFFFFF\r
+\r
+void Ppmd8_Construct(CPpmd8 *p)\r
+{\r
+  unsigned i, k, m;\r
+\r
+  p->Base = 0;\r
+\r
+  for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)\r
+  {\r
+    unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);\r
+    do { p->Units2Indx[k++] = (Byte)i; } while(--step);\r
+    p->Indx2Units[i] = (Byte)k;\r
+  }\r
+\r
+  p->NS2BSIndx[0] = (0 << 1);\r
+  p->NS2BSIndx[1] = (1 << 1);\r
+  memset(p->NS2BSIndx + 2, (2 << 1), 9);\r
+  memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);\r
+\r
+  for (i = 0; i < 5; i++)\r
+    p->NS2Indx[i] = (Byte)i;\r
+  for (m = i, k = 1; i < 260; i++)\r
+  {\r
+    p->NS2Indx[i] = (Byte)m;\r
+    if (--k == 0)\r
+      k = (++m) - 4;\r
+  }\r
+}\r
+\r
+void Ppmd8_Free(CPpmd8 *p, ISzAlloc *alloc)\r
+{\r
+  alloc->Free(alloc, p->Base);\r
+  p->Size = 0;\r
+  p->Base = 0;\r
+}\r
+\r
+Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size, ISzAlloc *alloc)\r
+{\r
+  if (p->Base == 0 || p->Size != size)\r
+  {\r
+    Ppmd8_Free(p, alloc);\r
+    p->AlignOffset =\r
+      #ifdef PPMD_32BIT\r
+        (4 - size) & 3;\r
+      #else\r
+        4 - (size & 3);\r
+      #endif\r
+    if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size)) == 0)\r
+      return False;\r
+    p->Size = size;\r
+  }\r
+  return True;\r
+}\r
+\r
+static void InsertNode(CPpmd8 *p, void *node, unsigned indx)\r
+{\r
+  ((CPpmd8_Node *)node)->Stamp = EMPTY_NODE;\r
+  ((CPpmd8_Node *)node)->Next = (CPpmd8_Node_Ref)p->FreeList[indx];\r
+  ((CPpmd8_Node *)node)->NU = I2U(indx);\r
+  p->FreeList[indx] = REF(node);\r
+  p->Stamps[indx]++;\r
+}\r
+\r
+static void *RemoveNode(CPpmd8 *p, unsigned indx)\r
+{\r
+  CPpmd8_Node *node = NODE((CPpmd8_Node_Ref)p->FreeList[indx]);\r
+  p->FreeList[indx] = node->Next;\r
+  p->Stamps[indx]--;\r
+  return node;\r
+}\r
+\r
+static void SplitBlock(CPpmd8 *p, void *ptr, unsigned oldIndx, unsigned newIndx)\r
+{\r
+  unsigned i, nu = I2U(oldIndx) - I2U(newIndx);\r
+  ptr = (Byte *)ptr + U2B(I2U(newIndx));\r
+  if (I2U(i = U2I(nu)) != nu)\r
+  {\r
+    unsigned k = I2U(--i);\r
+    InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);\r
+  }\r
+  InsertNode(p, ptr, i);\r
+}\r
+\r
+static void GlueFreeBlocks(CPpmd8 *p)\r
+{\r
+  CPpmd8_Node_Ref head = 0;\r
+  CPpmd8_Node_Ref *prev = &head;\r
+  unsigned i;\r
+\r
+  p->GlueCount = 1 << 13;\r
+  memset(p->Stamps, 0, sizeof(p->Stamps));\r
+  \r
+  /* Order-0 context is always at top UNIT, so we don't need guard NODE at the end.\r
+     All blocks up to p->LoUnit can be free, so we need guard NODE at LoUnit. */\r
+  if (p->LoUnit != p->HiUnit)\r
+    ((CPpmd8_Node *)p->LoUnit)->Stamp = 0;\r
+\r
+  /* Glue free blocks */\r
+  for (i = 0; i < PPMD_NUM_INDEXES; i++)\r
+  {\r
+    CPpmd8_Node_Ref next = (CPpmd8_Node_Ref)p->FreeList[i];\r
+    p->FreeList[i] = 0;\r
+    while (next != 0)\r
+    {\r
+      CPpmd8_Node *node = NODE(next);\r
+      if (node->NU != 0)\r
+      {\r
+        CPpmd8_Node *node2;\r
+        *prev = next;\r
+        prev = &(node->Next);\r
+        while ((node2 = node + node->NU)->Stamp == EMPTY_NODE)\r
+        {\r
+          node->NU += node2->NU;\r
+          node2->NU = 0;\r
+        }\r
+      }\r
+      next = node->Next;\r
+    }\r
+  }\r
+  *prev = 0;\r
+  \r
+  /* Fill lists of free blocks */\r
+  while (head != 0)\r
+  {\r
+    CPpmd8_Node *node = NODE(head);\r
+    unsigned nu;\r
+    head = node->Next;\r
+    nu = node->NU;\r
+    if (nu == 0)\r
+      continue;\r
+    for (; nu > 128; nu -= 128, node += 128)\r
+      InsertNode(p, node, PPMD_NUM_INDEXES - 1);\r
+    if (I2U(i = U2I(nu)) != nu)\r
+    {\r
+      unsigned k = I2U(--i);\r
+      InsertNode(p, node + k, nu - k - 1);\r
+    }\r
+    InsertNode(p, node, i);\r
+  }\r
+}\r
+\r
+static void *AllocUnitsRare(CPpmd8 *p, unsigned indx)\r
+{\r
+  unsigned i;\r
+  void *retVal;\r
+  if (p->GlueCount == 0)\r
+  {\r
+    GlueFreeBlocks(p);\r
+    if (p->FreeList[indx] != 0)\r
+      return RemoveNode(p, indx);\r
+  }\r
+  i = indx;\r
+  do\r
+  {\r
+    if (++i == PPMD_NUM_INDEXES)\r
+    {\r
+      UInt32 numBytes = U2B(I2U(indx));\r
+      p->GlueCount--;\r
+      return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL);\r
+    }\r
+  }\r
+  while (p->FreeList[i] == 0);\r
+  retVal = RemoveNode(p, i);\r
+  SplitBlock(p, retVal, i, indx);\r
+  return retVal;\r
+}\r
+\r
+static void *AllocUnits(CPpmd8 *p, unsigned indx)\r
+{\r
+  UInt32 numBytes;\r
+  if (p->FreeList[indx] != 0)\r
+    return RemoveNode(p, indx);\r
+  numBytes = U2B(I2U(indx));\r
+  if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit))\r
+  {\r
+    void *retVal = p->LoUnit;\r
+    p->LoUnit += numBytes;\r
+    return retVal;\r
+  }\r
+  return AllocUnitsRare(p, indx);\r
+}\r
+\r
+#define MyMem12Cpy(dest, src, num) \\r
+  { UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \\r
+    do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); }\r
+\r
+static void *ShrinkUnits(CPpmd8 *p, void *oldPtr, unsigned oldNU, unsigned newNU)\r
+{\r
+  unsigned i0 = U2I(oldNU);\r
+  unsigned i1 = U2I(newNU);\r
+  if (i0 == i1)\r
+    return oldPtr;\r
+  if (p->FreeList[i1] != 0)\r
+  {\r
+    void *ptr = RemoveNode(p, i1);\r
+    MyMem12Cpy(ptr, oldPtr, newNU);\r
+    InsertNode(p, oldPtr, i0);\r
+    return ptr;\r
+  }\r
+  SplitBlock(p, oldPtr, i0, i1);\r
+  return oldPtr;\r
+}\r
+\r
+static void FreeUnits(CPpmd8 *p, void *ptr, unsigned nu)\r
+{\r
+  InsertNode(p, ptr, U2I(nu));\r
+}\r
+\r
+static void SpecialFreeUnit(CPpmd8 *p, void *ptr)\r
+{\r
+  if ((Byte *)ptr != p->UnitsStart)\r
+    InsertNode(p, ptr, 0);\r
+  else\r
+  {\r
+    #ifdef PPMD8_FREEZE_SUPPORT\r
+    *(UInt32 *)ptr = EMPTY_NODE; /* it's used for (Flags == 0xFF) check in RemoveBinContexts */\r
+    #endif\r
+    p->UnitsStart += UNIT_SIZE;\r
+  }\r
+}\r
+\r
+static void *MoveUnitsUp(CPpmd8 *p, void *oldPtr, unsigned nu)\r
+{\r
+  unsigned indx = U2I(nu);\r
+  void *ptr;\r
+  if ((Byte *)oldPtr > p->UnitsStart + 16 * 1024 || REF(oldPtr) > p->FreeList[indx])\r
+    return oldPtr;\r
+  ptr = RemoveNode(p, indx);\r
+  MyMem12Cpy(ptr, oldPtr, nu);\r
+  if ((Byte*)oldPtr != p->UnitsStart)\r
+    InsertNode(p, oldPtr, indx);\r
+  else\r
+    p->UnitsStart += U2B(I2U(indx));\r
+  return ptr;\r
+}\r
+\r
+static void ExpandTextArea(CPpmd8 *p)\r
+{\r
+  UInt32 count[PPMD_NUM_INDEXES];\r
+  unsigned i;\r
+  memset(count, 0, sizeof(count));\r
+  if (p->LoUnit != p->HiUnit)\r
+    ((CPpmd8_Node *)p->LoUnit)->Stamp = 0;\r
+  \r
+  {\r
+    CPpmd8_Node *node = (CPpmd8_Node *)p->UnitsStart;\r
+    for (; node->Stamp == EMPTY_NODE; node += node->NU)\r
+    {\r
+      node->Stamp = 0;\r
+      count[U2I(node->NU)]++;\r
+    }\r
+    p->UnitsStart = (Byte *)node;\r
+  }\r
+  \r
+  for (i = 0; i < PPMD_NUM_INDEXES; i++)\r
+  {\r
+    CPpmd8_Node_Ref *next = (CPpmd8_Node_Ref *)&p->FreeList[i];\r
+    while (count[i] != 0)\r
+    {\r
+      CPpmd8_Node *node = NODE(*next);\r
+      while (node->Stamp == 0)\r
+      {\r
+        *next = node->Next;\r
+        node = NODE(*next);\r
+        p->Stamps[i]--;\r
+        if (--count[i] == 0)\r
+          break;\r
+      }\r
+      next = &node->Next;\r
+    }\r
+  }\r
+}\r
+\r
+#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))\r
+\r
+static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)\r
+{\r
+  (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);\r
+  (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);\r
+}\r
+\r
+#define RESET_TEXT(offs) { p->Text = p->Base + p->AlignOffset + (offs); }\r
+\r
+static void RestartModel(CPpmd8 *p)\r
+{\r
+  unsigned i, k, m, r;\r
+\r
+  memset(p->FreeList, 0, sizeof(p->FreeList));\r
+  memset(p->Stamps, 0, sizeof(p->Stamps));\r
+  RESET_TEXT(0);\r
+  p->HiUnit = p->Text + p->Size;\r
+  p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;\r
+  p->GlueCount = 0;\r
+\r
+  p->OrderFall = p->MaxOrder;\r
+  p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;\r
+  p->PrevSuccess = 0;\r
+\r
+  p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */\r
+  p->MinContext->Suffix = 0;\r
+  p->MinContext->NumStats = 255;\r
+  p->MinContext->Flags = 0;\r
+  p->MinContext->SummFreq = 256 + 1;\r
+  p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */\r
+  p->LoUnit += U2B(256 / 2);\r
+  p->MinContext->Stats = REF(p->FoundState);\r
+  for (i = 0; i < 256; i++)\r
+  {\r
+    CPpmd_State *s = &p->FoundState[i];\r
+    s->Symbol = (Byte)i;\r
+    s->Freq = 1;\r
+    SetSuccessor(s, 0);\r
+  }\r
+\r
+  for (i = m = 0; m < 25; m++)\r
+  {\r
+    while (p->NS2Indx[i] == m)\r
+      i++;\r
+    for (k = 0; k < 8; k++)\r
+    {\r
+      UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 1));\r
+      UInt16 *dest = p->BinSumm[m] + k;\r
+      for (r = 0; r < 64; r += 8)\r
+        dest[r] = val;\r
+    }\r
+  }\r
+\r
+  for (i = m = 0; m < 24; m++)\r
+  {\r
+    while (p->NS2Indx[i + 3] == m + 3)\r
+      i++;\r
+    for (k = 0; k < 32; k++)\r
+    {\r
+      CPpmd_See *s = &p->See[m][k];\r
+      s->Summ = (UInt16)((2 * i + 5) << (s->Shift = PPMD_PERIOD_BITS - 4));\r
+      s->Count = 7;\r
+    }\r
+  }\r
+}\r
+\r
+void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod)\r
+{\r
+  p->MaxOrder = maxOrder;\r
+  p->RestoreMethod = restoreMethod;\r
+  RestartModel(p);\r
+  p->DummySee.Shift = PPMD_PERIOD_BITS;\r
+  p->DummySee.Summ = 0; /* unused */\r
+  p->DummySee.Count = 64; /* unused */\r
+}\r
+\r
+static void Refresh(CPpmd8 *p, CTX_PTR ctx, unsigned oldNU, unsigned scale)\r
+{\r
+  unsigned i = ctx->NumStats, escFreq, sumFreq, flags;\r
+  CPpmd_State *s = (CPpmd_State *)ShrinkUnits(p, STATS(ctx), oldNU, (i + 2) >> 1);\r
+  ctx->Stats = REF(s);\r
+  #ifdef PPMD8_FREEZE_SUPPORT\r
+  /* fixed over Shkarin's code. Fixed code is not compatible with original code for some files in FREEZE mode. */\r
+  scale |= (ctx->SummFreq >= ((UInt32)1 << 15));\r
+  #endif\r
+  flags = (ctx->Flags & (0x10 + 0x04 * scale)) + 0x08 * (s->Symbol >= 0x40);\r
+  escFreq = ctx->SummFreq - s->Freq;\r
+  sumFreq = (s->Freq = (Byte)((s->Freq + scale) >> scale));\r
+  do\r
+  {\r
+    escFreq -= (++s)->Freq;\r
+    sumFreq += (s->Freq = (Byte)((s->Freq + scale) >> scale));\r
+    flags |= 0x08 * (s->Symbol >= 0x40);\r
+  }\r
+  while (--i);\r
+  ctx->SummFreq = (UInt16)(sumFreq + ((escFreq + scale) >> scale));\r
+  ctx->Flags = (Byte)flags;\r
+}\r
+\r
+static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)\r
+{\r
+  CPpmd_State tmp = *t1;\r
+  *t1 = *t2;\r
+  *t2 = tmp;\r
+}\r
+\r
+static CPpmd_Void_Ref CutOff(CPpmd8 *p, CTX_PTR ctx, unsigned order)\r
+{\r
+  int i;\r
+  unsigned tmp;\r
+  CPpmd_State *s;\r
+  \r
+  if (!ctx->NumStats)\r
+  {\r
+    s = ONE_STATE(ctx);\r
+    if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart)\r
+    {\r
+      if (order < p->MaxOrder)\r
+        SetSuccessor(s, CutOff(p, CTX(SUCCESSOR(s)), order + 1));\r
+      else\r
+        SetSuccessor(s, 0);\r
+      if (SUCCESSOR(s) || order <= 9) /* O_BOUND */\r
+        return REF(ctx);\r
+    }\r
+    SpecialFreeUnit(p, ctx);\r
+    return 0;\r
+  }\r
+\r
+  ctx->Stats = STATS_REF(MoveUnitsUp(p, STATS(ctx), tmp = ((unsigned)ctx->NumStats + 2) >> 1));\r
+\r
+  for (s = STATS(ctx) + (i = ctx->NumStats); s >= STATS(ctx); s--)\r
+    if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) < p->UnitsStart)\r
+    {\r
+      CPpmd_State *s2 = STATS(ctx) + (i--);\r
+      SetSuccessor(s, 0);\r
+      SwapStates(s, s2);\r
+    }\r
+    else if (order < p->MaxOrder)\r
+      SetSuccessor(s, CutOff(p, CTX(SUCCESSOR(s)), order + 1));\r
+    else\r
+      SetSuccessor(s, 0);\r
+    \r
+  if (i != ctx->NumStats && order)\r
+  {\r
+    ctx->NumStats = (Byte)i;\r
+    s = STATS(ctx);\r
+    if (i < 0)\r
+    {\r
+      FreeUnits(p, s, tmp);\r
+      SpecialFreeUnit(p, ctx);\r
+      return 0;\r
+    }\r
+    if (i == 0)\r
+    {\r
+      ctx->Flags = (ctx->Flags & 0x10) + 0x08 * (s->Symbol >= 0x40);\r
+      *ONE_STATE(ctx) = *s;\r
+      FreeUnits(p, s, tmp);\r
+      ONE_STATE(ctx)->Freq = (Byte)((unsigned)ONE_STATE(ctx)->Freq + 11) >> 3;\r
+    }\r
+    else\r
+      Refresh(p, ctx, tmp, ctx->SummFreq > 16 * i);\r
+  }\r
+  return REF(ctx);\r
+}\r
+\r
+#ifdef PPMD8_FREEZE_SUPPORT\r
+static CPpmd_Void_Ref RemoveBinContexts(CPpmd8 *p, CTX_PTR ctx, unsigned order)\r
+{\r
+  CPpmd_State *s;\r
+  if (!ctx->NumStats)\r
+  {\r
+    s = ONE_STATE(ctx);\r
+    if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart && order < p->MaxOrder)\r
+      SetSuccessor(s, RemoveBinContexts(p, CTX(SUCCESSOR(s)), order + 1));\r
+    else\r
+      SetSuccessor(s, 0);\r
+    /* Suffix context can be removed already, since different (high-order)\r
+       Successors may refer to same context. So we check Flags == 0xFF (Stamp == EMPTY_NODE) */\r
+    if (!SUCCESSOR(s) && (!SUFFIX(ctx)->NumStats || SUFFIX(ctx)->Flags == 0xFF))\r
+    {\r
+      FreeUnits(p, ctx, 1);\r
+      return 0;\r
+    }\r
+    else\r
+      return REF(ctx);\r
+  }\r
+\r
+  for (s = STATS(ctx) + ctx->NumStats; s >= STATS(ctx); s--)\r
+    if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart && order < p->MaxOrder)\r
+      SetSuccessor(s, RemoveBinContexts(p, CTX(SUCCESSOR(s)), order + 1));\r
+    else\r
+      SetSuccessor(s, 0);\r
+  \r
+  return REF(ctx);\r
+}\r
+#endif\r
+\r
+static UInt32 GetUsedMemory(const CPpmd8 *p)\r
+{\r
+  UInt32 v = 0;\r
+  unsigned i;\r
+  for (i = 0; i < PPMD_NUM_INDEXES; i++)\r
+    v += p->Stamps[i] * I2U(i);\r
+  return p->Size - (UInt32)(p->HiUnit - p->LoUnit) - (UInt32)(p->UnitsStart - p->Text) - U2B(v);\r
+}\r
+\r
+#ifdef PPMD8_FREEZE_SUPPORT\r
+  #define RESTORE_MODEL(c1, fSuccessor) RestoreModel(p, c1, fSuccessor)\r
+#else\r
+  #define RESTORE_MODEL(c1, fSuccessor) RestoreModel(p, c1)\r
+#endif\r
+\r
+static void RestoreModel(CPpmd8 *p, CTX_PTR c1\r
+    #ifdef PPMD8_FREEZE_SUPPORT\r
+    , CTX_PTR fSuccessor\r
+    #endif\r
+    )\r
+{\r
+  CTX_PTR c;\r
+  CPpmd_State *s;\r
+  RESET_TEXT(0);\r
+  for (c = p->MaxContext; c != c1; c = SUFFIX(c))\r
+    if (--(c->NumStats) == 0)\r
+    {\r
+      s = STATS(c);\r
+      c->Flags = (c->Flags & 0x10) + 0x08 * (s->Symbol >= 0x40);\r
+      *ONE_STATE(c) = *s;\r
+      SpecialFreeUnit(p, s);\r
+      ONE_STATE(c)->Freq = (ONE_STATE(c)->Freq + 11) >> 3;\r
+    }\r
+    else\r
+      Refresh(p, c, (c->NumStats+3) >> 1, 0);\r
\r
+  for (; c != p->MinContext; c = SUFFIX(c))\r
+    if (!c->NumStats)\r
+      ONE_STATE(c)->Freq -= ONE_STATE(c)->Freq >> 1;\r
+    else if ((c->SummFreq += 4) > 128 + 4 * c->NumStats)\r
+      Refresh(p, c, (c->NumStats + 2) >> 1, 1);\r
+\r
+  #ifdef PPMD8_FREEZE_SUPPORT\r
+  if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)\r
+  {\r
+    p->MaxContext = fSuccessor;\r
+    p->GlueCount += !(p->Stamps[1] & 1);\r
+  }\r
+  else if (p->RestoreMethod == PPMD8_RESTORE_METHOD_FREEZE)\r
+  {\r
+    while (p->MaxContext->Suffix)\r
+      p->MaxContext = SUFFIX(p->MaxContext);\r
+    RemoveBinContexts(p, p->MaxContext, 0);\r
+    p->RestoreMethod++;\r
+    p->GlueCount = 0;\r
+    p->OrderFall = p->MaxOrder;\r
+  }\r
+  else\r
+  #endif\r
+  if (p->RestoreMethod == PPMD8_RESTORE_METHOD_RESTART || GetUsedMemory(p) < (p->Size >> 1))\r
+    RestartModel(p);\r
+  else\r
+  {\r
+    while (p->MaxContext->Suffix)\r
+      p->MaxContext = SUFFIX(p->MaxContext);\r
+    do\r
+    {\r
+      CutOff(p, p->MaxContext, 0);\r
+      ExpandTextArea(p);\r
+    }\r
+    while (GetUsedMemory(p) > 3 * (p->Size >> 2));\r
+    p->GlueCount = 0;\r
+    p->OrderFall = p->MaxOrder;\r
+  }\r
+}\r
+\r
+static CTX_PTR CreateSuccessors(CPpmd8 *p, Bool skip, CPpmd_State *s1, CTX_PTR c)\r
+{\r
+  CPpmd_State upState;\r
+  Byte flags;\r
+  CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);\r
+  /* fixed over Shkarin's code. Maybe it could work without + 1 too. */\r
+  CPpmd_State *ps[PPMD8_MAX_ORDER + 1];\r
+  unsigned numPs = 0;\r
+  \r
+  if (!skip)\r
+    ps[numPs++] = p->FoundState;\r
+  \r
+  while (c->Suffix)\r
+  {\r
+    CPpmd_Void_Ref successor;\r
+    CPpmd_State *s;\r
+    c = SUFFIX(c);\r
+    if (s1)\r
+    {\r
+      s = s1;\r
+      s1 = NULL;\r
+    }\r
+    else if (c->NumStats != 0)\r
+    {\r
+      for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++);\r
+      if (s->Freq < MAX_FREQ - 9)\r
+      {\r
+        s->Freq++;\r
+        c->SummFreq++;\r
+      }\r
+    }\r
+    else\r
+    {\r
+      s = ONE_STATE(c);\r
+      s->Freq += (!SUFFIX(c)->NumStats & (s->Freq < 24));\r
+    }\r
+    successor = SUCCESSOR(s);\r
+    if (successor != upBranch)\r
+    {\r
+      c = CTX(successor);\r
+      if (numPs == 0)\r
+        return c;\r
+      break;\r
+    }\r
+    ps[numPs++] = s;\r
+  }\r
+  \r
+  upState.Symbol = *(const Byte *)Ppmd8_GetPtr(p, upBranch);\r
+  SetSuccessor(&upState, upBranch + 1);\r
+  flags = 0x10 * (p->FoundState->Symbol >= 0x40) + 0x08 * (upState.Symbol >= 0x40);\r
+\r
+  if (c->NumStats == 0)\r
+    upState.Freq = ONE_STATE(c)->Freq;\r
+  else\r
+  {\r
+    UInt32 cf, s0;\r
+    CPpmd_State *s;\r
+    for (s = STATS(c); s->Symbol != upState.Symbol; s++);\r
+    cf = s->Freq - 1;\r
+    s0 = c->SummFreq - c->NumStats - cf;\r
+    upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((cf + 2 * s0 - 3) / s0)));\r
+  }\r
+\r
+  do\r
+  {\r
+    /* Create Child */\r
+    CTX_PTR c1; /* = AllocContext(p); */\r
+    if (p->HiUnit != p->LoUnit)\r
+      c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE);\r
+    else if (p->FreeList[0] != 0)\r
+      c1 = (CTX_PTR)RemoveNode(p, 0);\r
+    else\r
+    {\r
+      c1 = (CTX_PTR)AllocUnitsRare(p, 0);\r
+      if (!c1)\r
+        return NULL;\r
+    }\r
+    c1->NumStats = 0;\r
+    c1->Flags = flags;\r
+    *ONE_STATE(c1) = upState;\r
+    c1->Suffix = REF(c);\r
+    SetSuccessor(ps[--numPs], REF(c1));\r
+    c = c1;\r
+  }\r
+  while (numPs != 0);\r
+  \r
+  return c;\r
+}\r
+\r
+static CTX_PTR ReduceOrder(CPpmd8 *p, CPpmd_State *s1, CTX_PTR c)\r
+{\r
+  CPpmd_State *s = NULL;\r
+  CTX_PTR c1 = c;\r
+  CPpmd_Void_Ref upBranch = REF(p->Text);\r
+  \r
+  #ifdef PPMD8_FREEZE_SUPPORT\r
+  /* The BUG in Shkarin's code was fixed: ps could overflow in CUT_OFF mode. */\r
+  CPpmd_State *ps[PPMD8_MAX_ORDER + 1];\r
+  unsigned numPs = 0;\r
+  ps[numPs++] = p->FoundState;\r
+  #endif\r
+\r
+  SetSuccessor(p->FoundState, upBranch);\r
+  p->OrderFall++;\r
+\r
+  for (;;)\r
+  {\r
+    if (s1)\r
+    {\r
+      c = SUFFIX(c);\r
+      s = s1;\r
+      s1 = NULL;\r
+    }\r
+    else\r
+    {\r
+      if (!c->Suffix)\r
+      {\r
+        #ifdef PPMD8_FREEZE_SUPPORT\r
+        if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)\r
+        {\r
+          do { SetSuccessor(ps[--numPs], REF(c)); } while (numPs);\r
+          RESET_TEXT(1);\r
+          p->OrderFall = 1;\r
+        }\r
+        #endif\r
+        return c;\r
+      }\r
+      c = SUFFIX(c);\r
+      if (c->NumStats)\r
+      {\r
+        if ((s = STATS(c))->Symbol != p->FoundState->Symbol)\r
+          do { s++; } while (s->Symbol != p->FoundState->Symbol);\r
+        if (s->Freq < MAX_FREQ - 9)\r
+        {\r
+          s->Freq += 2;\r
+          c->SummFreq += 2;\r
+        }\r
+      }\r
+      else\r
+      {\r
+        s = ONE_STATE(c);\r
+        s->Freq += (s->Freq < 32);\r
+      }\r
+    }\r
+    if (SUCCESSOR(s))\r
+      break;\r
+    #ifdef PPMD8_FREEZE_SUPPORT\r
+    ps[numPs++] = s;\r
+    #endif\r
+    SetSuccessor(s, upBranch);\r
+    p->OrderFall++;\r
+  }\r
+  \r
+  #ifdef PPMD8_FREEZE_SUPPORT\r
+  if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)\r
+  {\r
+    c = CTX(SUCCESSOR(s));\r
+    do { SetSuccessor(ps[--numPs], REF(c)); } while (numPs);\r
+    RESET_TEXT(1);\r
+    p->OrderFall = 1;\r
+    return c;\r
+  }\r
+  else\r
+  #endif\r
+  if (SUCCESSOR(s) <= upBranch)\r
+  {\r
+    CTX_PTR successor;\r
+    CPpmd_State *s1 = p->FoundState;\r
+    p->FoundState = s;\r
+\r
+    successor = CreateSuccessors(p, False, NULL, c);\r
+    if (successor == NULL)\r
+      SetSuccessor(s, 0);\r
+    else\r
+      SetSuccessor(s, REF(successor));\r
+    p->FoundState = s1;\r
+  }\r
+  \r
+  if (p->OrderFall == 1 && c1 == p->MaxContext)\r
+  {\r
+    SetSuccessor(p->FoundState, SUCCESSOR(s));\r
+    p->Text--;\r
+  }\r
+  if (SUCCESSOR(s) == 0)\r
+    return NULL;\r
+  return CTX(SUCCESSOR(s));\r
+}\r
+\r
+static void UpdateModel(CPpmd8 *p)\r
+{\r
+  CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState);\r
+  CTX_PTR c;\r
+  unsigned s0, ns, fFreq = p->FoundState->Freq;\r
+  Byte flag, fSymbol = p->FoundState->Symbol;\r
+  CPpmd_State *s = NULL;\r
+  \r
+  if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)\r
+  {\r
+    c = SUFFIX(p->MinContext);\r
+    \r
+    if (c->NumStats == 0)\r
+    {\r
+      s = ONE_STATE(c);\r
+      if (s->Freq < 32)\r
+        s->Freq++;\r
+    }\r
+    else\r
+    {\r
+      s = STATS(c);\r
+      if (s->Symbol != p->FoundState->Symbol)\r
+      {\r
+        do { s++; } while (s->Symbol != p->FoundState->Symbol);\r
+        if (s[0].Freq >= s[-1].Freq)\r
+        {\r
+          SwapStates(&s[0], &s[-1]);\r
+          s--;\r
+        }\r
+      }\r
+      if (s->Freq < MAX_FREQ - 9)\r
+      {\r
+        s->Freq += 2;\r
+        c->SummFreq += 2;\r
+      }\r
+    }\r
+  }\r
+  \r
+  c = p->MaxContext;\r
+  if (p->OrderFall == 0 && fSuccessor)\r
+  {\r
+    CTX_PTR cs = CreateSuccessors(p, True, s, p->MinContext);\r
+    if (cs == 0)\r
+    {\r
+      SetSuccessor(p->FoundState, 0);\r
+      RESTORE_MODEL(c, CTX(fSuccessor));\r
+    }\r
+    else\r
+    {\r
+      SetSuccessor(p->FoundState, REF(cs));\r
+      p->MaxContext = cs;\r
+    }\r
+    return;\r
+  }\r
+  \r
+  *p->Text++ = p->FoundState->Symbol;\r
+  successor = REF(p->Text);\r
+  if (p->Text >= p->UnitsStart)\r
+  {\r
+    RESTORE_MODEL(c, CTX(fSuccessor)); /* check it */\r
+    return;\r
+  }\r
+  \r
+  if (!fSuccessor)\r
+  {\r
+    CTX_PTR cs = ReduceOrder(p, s, p->MinContext);\r
+    if (cs == NULL)\r
+    {\r
+      RESTORE_MODEL(c, 0);\r
+      return;\r
+    }\r
+    fSuccessor = REF(cs);\r
+  }\r
+  else if ((Byte *)Ppmd8_GetPtr(p, fSuccessor) < p->UnitsStart)\r
+  {\r
+    CTX_PTR cs = CreateSuccessors(p, False, s, p->MinContext);\r
+    if (cs == NULL)\r
+    {\r
+      RESTORE_MODEL(c, 0);\r
+      return;\r
+    }\r
+    fSuccessor = REF(cs);\r
+  }\r
+  \r
+  if (--p->OrderFall == 0)\r
+  {\r
+    successor = fSuccessor;\r
+    p->Text -= (p->MaxContext != p->MinContext);\r
+  }\r
+  #ifdef PPMD8_FREEZE_SUPPORT\r
+  else if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)\r
+  {\r
+    successor = fSuccessor;\r
+    RESET_TEXT(0);\r
+    p->OrderFall = 0;\r
+  }\r
+  #endif\r
+  \r
+  s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - fFreq;\r
+  flag = 0x08 * (fSymbol >= 0x40);\r
+  \r
+  for (; c != p->MinContext; c = SUFFIX(c))\r
+  {\r
+    unsigned ns1;\r
+    UInt32 cf, sf;\r
+    if ((ns1 = c->NumStats) != 0)\r
+    {\r
+      if ((ns1 & 1) != 0)\r
+      {\r
+        /* Expand for one UNIT */\r
+        unsigned oldNU = (ns1 + 1) >> 1;\r
+        unsigned i = U2I(oldNU);\r
+        if (i != U2I(oldNU + 1))\r
+        {\r
+          void *ptr = AllocUnits(p, i + 1);\r
+          void *oldPtr;\r
+          if (!ptr)\r
+          {\r
+            RESTORE_MODEL(c, CTX(fSuccessor));\r
+            return;\r
+          }\r
+          oldPtr = STATS(c);\r
+          MyMem12Cpy(ptr, oldPtr, oldNU);\r
+          InsertNode(p, oldPtr, i);\r
+          c->Stats = STATS_REF(ptr);\r
+        }\r
+      }\r
+      c->SummFreq = (UInt16)(c->SummFreq + (3 * ns1 + 1 < ns));\r
+    }\r
+    else\r
+    {\r
+      CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0);\r
+      if (!s)\r
+      {\r
+        RESTORE_MODEL(c, CTX(fSuccessor));\r
+        return;\r
+      }\r
+      *s = *ONE_STATE(c);\r
+      c->Stats = REF(s);\r
+      if (s->Freq < MAX_FREQ / 4 - 1)\r
+        s->Freq <<= 1;\r
+      else\r
+        s->Freq = MAX_FREQ - 4;\r
+      c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 2));\r
+    }\r
+    cf = 2 * fFreq * (c->SummFreq + 6);\r
+    sf = (UInt32)s0 + c->SummFreq;\r
+    if (cf < 6 * sf)\r
+    {\r
+      cf = 1 + (cf > sf) + (cf >= 4 * sf);\r
+      c->SummFreq += 4;\r
+    }\r
+    else\r
+    {\r
+      cf = 4 + (cf > 9 * sf) + (cf > 12 * sf) + (cf > 15 * sf);\r
+      c->SummFreq = (UInt16)(c->SummFreq + cf);\r
+    }\r
+    {\r
+      CPpmd_State *s = STATS(c) + ns1 + 1;\r
+      SetSuccessor(s, successor);\r
+      s->Symbol = fSymbol;\r
+      s->Freq = (Byte)cf;\r
+      c->Flags |= flag;\r
+      c->NumStats = (Byte)(ns1 + 1);\r
+    }\r
+  }\r
+  p->MaxContext = p->MinContext = CTX(fSuccessor);\r
+}\r
+  \r
+static void Rescale(CPpmd8 *p)\r
+{\r
+  unsigned i, adder, sumFreq, escFreq;\r
+  CPpmd_State *stats = STATS(p->MinContext);\r
+  CPpmd_State *s = p->FoundState;\r
+  {\r
+    CPpmd_State tmp = *s;\r
+    for (; s != stats; s--)\r
+      s[0] = s[-1];\r
+    *s = tmp;\r
+  }\r
+  escFreq = p->MinContext->SummFreq - s->Freq;\r
+  s->Freq += 4;\r
+  adder = (p->OrderFall != 0\r
+      #ifdef PPMD8_FREEZE_SUPPORT\r
+      || p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE\r
+      #endif\r
+      );\r
+  s->Freq = (Byte)((s->Freq + adder) >> 1);\r
+  sumFreq = s->Freq;\r
+  \r
+  i = p->MinContext->NumStats;\r
+  do\r
+  {\r
+    escFreq -= (++s)->Freq;\r
+    s->Freq = (Byte)((s->Freq + adder) >> 1);\r
+    sumFreq += s->Freq;\r
+    if (s[0].Freq > s[-1].Freq)\r
+    {\r
+      CPpmd_State *s1 = s;\r
+      CPpmd_State tmp = *s1;\r
+      do\r
+        s1[0] = s1[-1];\r
+      while (--s1 != stats && tmp.Freq > s1[-1].Freq);\r
+      *s1 = tmp;\r
+    }\r
+  }\r
+  while (--i);\r
+  \r
+  if (s->Freq == 0)\r
+  {\r
+    unsigned numStats = p->MinContext->NumStats;\r
+    unsigned n0, n1;\r
+    do { i++; } while ((--s)->Freq == 0);\r
+    escFreq += i;\r
+    p->MinContext->NumStats = (Byte)(p->MinContext->NumStats - i);\r
+    if (p->MinContext->NumStats == 0)\r
+    {\r
+      CPpmd_State tmp = *stats;\r
+      tmp.Freq = (Byte)((2 * tmp.Freq + escFreq - 1) / escFreq);\r
+      if (tmp.Freq > MAX_FREQ / 3)\r
+        tmp.Freq = MAX_FREQ / 3;\r
+      InsertNode(p, stats, U2I((numStats + 2) >> 1));\r
+      p->MinContext->Flags = (p->MinContext->Flags & 0x10) + 0x08 * (tmp.Symbol >= 0x40);\r
+      *(p->FoundState = ONE_STATE(p->MinContext)) = tmp;\r
+      return;\r
+    }\r
+    n0 = (numStats + 2) >> 1;\r
+    n1 = (p->MinContext->NumStats + 2) >> 1;\r
+    if (n0 != n1)\r
+      p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));\r
+    p->MinContext->Flags &= ~0x08;\r
+    p->MinContext->Flags |= 0x08 * ((s = STATS(p->MinContext))->Symbol >= 0x40);\r
+    i = p->MinContext->NumStats;\r
+    do { p->MinContext->Flags |= 0x08*((++s)->Symbol >= 0x40); } while (--i);\r
+  }\r
+  p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));\r
+  p->MinContext->Flags |= 0x4;\r
+  p->FoundState = STATS(p->MinContext);\r
+}\r
+\r
+CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked1, UInt32 *escFreq)\r
+{\r
+  CPpmd_See *see;\r
+  if (p->MinContext->NumStats != 0xFF)\r
+  {\r
+    see = p->See[p->NS2Indx[p->MinContext->NumStats + 2] - 3] +\r
+        (p->MinContext->SummFreq > 11 * ((unsigned)p->MinContext->NumStats + 1)) +\r
+        2 * (2 * (unsigned)p->MinContext->NumStats <\r
+        ((unsigned)SUFFIX(p->MinContext)->NumStats + numMasked1)) +\r
+        p->MinContext->Flags;\r
+    {\r
+      unsigned r = (see->Summ >> see->Shift);\r
+      see->Summ = (UInt16)(see->Summ - r);\r
+      *escFreq = r + (r == 0);\r
+    }\r
+  }\r
+  else\r
+  {\r
+    see = &p->DummySee;\r
+    *escFreq = 1;\r
+  }\r
+  return see;\r
+}\r
+\r
+static void NextContext(CPpmd8 *p)\r
+{\r
+  CTX_PTR c = CTX(SUCCESSOR(p->FoundState));\r
+  if (p->OrderFall == 0 && (Byte *)c >= p->UnitsStart)\r
+    p->MinContext = p->MaxContext = c;\r
+  else\r
+  {\r
+    UpdateModel(p);\r
+    p->MinContext = p->MaxContext;\r
+  }\r
+}\r
+\r
+void Ppmd8_Update1(CPpmd8 *p)\r
+{\r
+  CPpmd_State *s = p->FoundState;\r
+  s->Freq += 4;\r
+  p->MinContext->SummFreq += 4;\r
+  if (s[0].Freq > s[-1].Freq)\r
+  {\r
+    SwapStates(&s[0], &s[-1]);\r
+    p->FoundState = --s;\r
+    if (s->Freq > MAX_FREQ)\r
+      Rescale(p);\r
+  }\r
+  NextContext(p);\r
+}\r
+\r
+void Ppmd8_Update1_0(CPpmd8 *p)\r
+{\r
+  p->PrevSuccess = (2 * p->FoundState->Freq >= p->MinContext->SummFreq);\r
+  p->RunLength += p->PrevSuccess;\r
+  p->MinContext->SummFreq += 4;\r
+  if ((p->FoundState->Freq += 4) > MAX_FREQ)\r
+    Rescale(p);\r
+  NextContext(p);\r
+}\r
+\r
+void Ppmd8_UpdateBin(CPpmd8 *p)\r
+{\r
+  p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 196));\r
+  p->PrevSuccess = 1;\r
+  p->RunLength++;\r
+  NextContext(p);\r
+}\r
+\r
+void Ppmd8_Update2(CPpmd8 *p)\r
+{\r
+  p->MinContext->SummFreq += 4;\r
+  if ((p->FoundState->Freq += 4) > MAX_FREQ)\r
+    Rescale(p);\r
+  p->RunLength = p->InitRL;\r
+  UpdateModel(p);\r
+  p->MinContext = p->MaxContext;\r
+}\r
+\r
+/* H->I changes:\r
+  NS2Indx\r
+  GlewCount, and Glue method\r
+  BinSum\r
+  See / EscFreq\r
+  CreateSuccessors updates more suffix contexts\r
+  UpdateModel consts.\r
+  PrevSuccess Update\r
+*/\r
diff --git a/C/Ppmd8.h b/C/Ppmd8.h
new file mode 100755 (executable)
index 0000000..6efd4ea
--- /dev/null
+++ b/C/Ppmd8.h
@@ -0,0 +1,133 @@
+/* Ppmd8.h -- PPMdI codec\r
+2010-03-24 : Igor Pavlov : Public domain\r
+This code is based on:\r
+  PPMd var.I (2002): Dmitry Shkarin : Public domain\r
+  Carryless rangecoder (1999): Dmitry Subbotin : Public domain */\r
+\r
+#ifndef __PPMD8_H\r
+#define __PPMD8_H\r
+\r
+#include "Ppmd.h"\r
+\r
+EXTERN_C_BEGIN\r
+\r
+#define PPMD8_MIN_ORDER 2\r
+#define PPMD8_MAX_ORDER 16\r
+\r
+struct CPpmd8_Context_;\r
+\r
+typedef\r
+  #ifdef PPMD_32BIT\r
+    struct CPpmd8_Context_ *\r
+  #else\r
+    UInt32\r
+  #endif\r
+  CPpmd8_Context_Ref;\r
+\r
+typedef struct CPpmd8_Context_\r
+{\r
+  Byte NumStats;\r
+  Byte Flags;\r
+  UInt16 SummFreq;\r
+  CPpmd_State_Ref Stats;\r
+  CPpmd8_Context_Ref Suffix;\r
+} CPpmd8_Context;\r
+\r
+#define Ppmd8Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)\r
+\r
+/* The BUG in Shkarin's code for FREEZE mode was fixed, but that fixed\r
+   code is not compatible with original code for some files compressed\r
+   in FREEZE mode. So we disable FREEZE mode support. */\r
+\r
+enum\r
+{\r
+  PPMD8_RESTORE_METHOD_RESTART,\r
+  PPMD8_RESTORE_METHOD_CUT_OFF\r
+  #ifdef PPMD8_FREEZE_SUPPORT\r
+  , PPMD8_RESTORE_METHOD_FREEZE\r
+  #endif\r
+};\r
+\r
+typedef struct\r
+{\r
+  CPpmd8_Context *MinContext, *MaxContext;\r
+  CPpmd_State *FoundState;\r
+  unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder;\r
+  Int32 RunLength, InitRL; /* must be 32-bit at least */\r
+\r
+  UInt32 Size;\r
+  UInt32 GlueCount;\r
+  Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;\r
+  UInt32 AlignOffset;\r
+  unsigned RestoreMethod;\r
+\r
+  /* Range Coder */\r
+  UInt32 Range;\r
+  UInt32 Code;\r
+  UInt32 Low;\r
+  union\r
+  {\r
+    IByteIn *In;\r
+    IByteOut *Out;\r
+  } Stream;\r
+\r
+  Byte Indx2Units[PPMD_NUM_INDEXES];\r
+  Byte Units2Indx[128];\r
+  CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];\r
+  UInt32 Stamps[PPMD_NUM_INDEXES];\r
+\r
+  Byte NS2BSIndx[256], NS2Indx[260];\r
+  CPpmd_See DummySee, See[24][32];\r
+  UInt16 BinSumm[25][64];\r
+} CPpmd8;\r
+\r
+void Ppmd8_Construct(CPpmd8 *p);\r
+Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size, ISzAlloc *alloc);\r
+void Ppmd8_Free(CPpmd8 *p, ISzAlloc *alloc);\r
+void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod);\r
+#define Ppmd8_WasAllocated(p) ((p)->Base != NULL)\r
+\r
+\r
+/* ---------- Internal Functions ---------- */\r
+\r
+extern const Byte PPMD8_kExpEscape[16];\r
+\r
+#ifdef PPMD_32BIT\r
+  #define Ppmd8_GetPtr(p, ptr) (ptr)\r
+  #define Ppmd8_GetContext(p, ptr) (ptr)\r
+  #define Ppmd8_GetStats(p, ctx) ((ctx)->Stats)\r
+#else\r
+  #define Ppmd8_GetPtr(p, offs) ((void *)((p)->Base + (offs)))\r
+  #define Ppmd8_GetContext(p, offs) ((CPpmd8_Context *)Ppmd8_GetPtr((p), (offs)))\r
+  #define Ppmd8_GetStats(p, ctx) ((CPpmd_State *)Ppmd8_GetPtr((p), ((ctx)->Stats)))\r
+#endif\r
+\r
+void Ppmd8_Update1(CPpmd8 *p);\r
+void Ppmd8_Update1_0(CPpmd8 *p);\r
+void Ppmd8_Update2(CPpmd8 *p);\r
+void Ppmd8_UpdateBin(CPpmd8 *p);\r
+\r
+#define Ppmd8_GetBinSumm(p) \\r
+    &p->BinSumm[p->NS2Indx[Ppmd8Context_OneState(p->MinContext)->Freq - 1]][ \\r
+    p->NS2BSIndx[Ppmd8_GetContext(p, p->MinContext->Suffix)->NumStats] + \\r
+    p->PrevSuccess + p->MinContext->Flags + ((p->RunLength >> 26) & 0x20)]\r
+\r
+CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked, UInt32 *scale);\r
+\r
+\r
+/* ---------- Decode ---------- */\r
+\r
+Bool Ppmd8_RangeDec_Init(CPpmd8 *p);\r
+#define Ppmd8_RangeDec_IsFinishedOK(p) ((p)->Code == 0)\r
+int Ppmd8_DecodeSymbol(CPpmd8 *p); /* returns: -1 as EndMarker, -2 as DataError */\r
+\r
+\r
+/* ---------- Encode ---------- */\r
+\r
+#define Ppmd8_RangeEnc_Init(p) { (p)->Low = 0; (p)->Range = 0xFFFFFFFF; }\r
+void Ppmd8_RangeEnc_FlushData(CPpmd8 *p);\r
+void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol); /* symbol = -1 means EndMarker */\r
+\r
+EXTERN_C_END\r
\r
+#endif\r
diff --git a/C/Ppmd8Dec.c b/C/Ppmd8Dec.c
new file mode 100755 (executable)
index 0000000..934eae7
--- /dev/null
@@ -0,0 +1,155 @@
+/* Ppmd8Dec.c -- PPMdI Decoder\r
+2010-04-16 : Igor Pavlov : Public domain\r
+This code is based on:\r
+  PPMd var.I (2002): Dmitry Shkarin : Public domain\r
+  Carryless rangecoder (1999): Dmitry Subbotin : Public domain */\r
+\r
+#include "Ppmd8.h"\r
+\r
+#define kTop (1 << 24)\r
+#define kBot (1 << 15)\r
+\r
+Bool Ppmd8_RangeDec_Init(CPpmd8 *p)\r
+{\r
+  unsigned i;\r
+  p->Low = 0;\r
+  p->Range = 0xFFFFFFFF;\r
+  p->Code = 0;\r
+  for (i = 0; i < 4; i++)\r
+    p->Code = (p->Code << 8) | p->Stream.In->Read(p->Stream.In);\r
+  return (p->Code < 0xFFFFFFFF);\r
+}\r
+\r
+static UInt32 RangeDec_GetThreshold(CPpmd8 *p, UInt32 total)\r
+{\r
+  return p->Code / (p->Range /= total);\r
+}\r
+\r
+static void RangeDec_Decode(CPpmd8 *p, UInt32 start, UInt32 size)\r
+{\r
+  start *= p->Range;\r
+  p->Low += start;\r
+  p->Code -= start;\r
+  p->Range *= size;\r
+\r
+  while ((p->Low ^ (p->Low + p->Range)) < kTop ||\r
+      (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1)))\r
+  {\r
+    p->Code = (p->Code << 8) | p->Stream.In->Read(p->Stream.In);\r
+    p->Range <<= 8;\r
+    p->Low <<= 8;\r
+  }\r
+}\r
+\r
+#define MASK(sym) ((signed char *)charMask)[sym]\r
+\r
+int Ppmd8_DecodeSymbol(CPpmd8 *p)\r
+{\r
+  size_t charMask[256 / sizeof(size_t)];\r
+  if (p->MinContext->NumStats != 0)\r
+  {\r
+    CPpmd_State *s = Ppmd8_GetStats(p, p->MinContext);\r
+    unsigned i;\r
+    UInt32 count, hiCnt;\r
+    if ((count = RangeDec_GetThreshold(p, p->MinContext->SummFreq)) < (hiCnt = s->Freq))\r
+    {\r
+      Byte symbol;\r
+      RangeDec_Decode(p, 0, s->Freq);\r
+      p->FoundState = s;\r
+      symbol = s->Symbol;\r
+      Ppmd8_Update1_0(p);\r
+      return symbol;\r
+    }\r
+    p->PrevSuccess = 0;\r
+    i = p->MinContext->NumStats;\r
+    do\r
+    {\r
+      if ((hiCnt += (++s)->Freq) > count)\r
+      {\r
+        Byte symbol;\r
+        RangeDec_Decode(p, hiCnt - s->Freq, s->Freq);\r
+        p->FoundState = s;\r
+        symbol = s->Symbol;\r
+        Ppmd8_Update1(p);\r
+        return symbol;\r
+      }\r
+    }\r
+    while (--i);\r
+    if (count >= p->MinContext->SummFreq)\r
+      return -2;\r
+    RangeDec_Decode(p, hiCnt, p->MinContext->SummFreq - hiCnt);\r
+    PPMD_SetAllBitsIn256Bytes(charMask);\r
+    MASK(s->Symbol) = 0;\r
+    i = p->MinContext->NumStats;\r
+    do { MASK((--s)->Symbol) = 0; } while (--i);\r
+  }\r
+  else\r
+  {\r
+    UInt16 *prob = Ppmd8_GetBinSumm(p);\r
+    if (((p->Code / (p->Range >>= 14)) < *prob))\r
+    {\r
+      Byte symbol;\r
+      RangeDec_Decode(p, 0, *prob);\r
+      *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);\r
+      symbol = (p->FoundState = Ppmd8Context_OneState(p->MinContext))->Symbol;\r
+      Ppmd8_UpdateBin(p);\r
+      return symbol;\r
+    }\r
+    RangeDec_Decode(p, *prob, (1 << 14) - *prob);\r
+    *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);\r
+    p->InitEsc = PPMD8_kExpEscape[*prob >> 10];\r
+    PPMD_SetAllBitsIn256Bytes(charMask);\r
+    MASK(Ppmd8Context_OneState(p->MinContext)->Symbol) = 0;\r
+    p->PrevSuccess = 0;\r
+  }\r
+  for (;;)\r
+  {\r
+    CPpmd_State *ps[256], *s;\r
+    UInt32 freqSum, count, hiCnt;\r
+    CPpmd_See *see;\r
+    unsigned i, num, numMasked = p->MinContext->NumStats;\r
+    do\r
+    {\r
+      p->OrderFall++;\r
+      if (!p->MinContext->Suffix)\r
+        return -1;\r
+      p->MinContext = Ppmd8_GetContext(p, p->MinContext->Suffix);\r
+    }\r
+    while (p->MinContext->NumStats == numMasked);\r
+    hiCnt = 0;\r
+    s = Ppmd8_GetStats(p, p->MinContext);\r
+    i = 0;\r
+    num = p->MinContext->NumStats - numMasked;\r
+    do\r
+    {\r
+      int k = (int)(MASK(s->Symbol));\r
+      hiCnt += (s->Freq & k);\r
+      ps[i] = s++;\r
+      i -= k;\r
+    }\r
+    while (i != num);\r
+    \r
+    see = Ppmd8_MakeEscFreq(p, numMasked, &freqSum);\r
+    freqSum += hiCnt;\r
+    count = RangeDec_GetThreshold(p, freqSum);\r
+    \r
+    if (count < hiCnt)\r
+    {\r
+      Byte symbol;\r
+      CPpmd_State **pps = ps;\r
+      for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);\r
+      s = *pps;\r
+      RangeDec_Decode(p, hiCnt - s->Freq, s->Freq);\r
+      Ppmd_See_Update(see);\r
+      p->FoundState = s;\r
+      symbol = s->Symbol;\r
+      Ppmd8_Update2(p);\r
+      return symbol;\r
+    }\r
+    if (count >= freqSum)\r
+      return -2;\r
+    RangeDec_Decode(p, hiCnt, freqSum - hiCnt);\r
+    see->Summ = (UInt16)(see->Summ + freqSum);\r
+    do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);\r
+  }\r
+}\r
diff --git a/C/Ppmd8Enc.c b/C/Ppmd8Enc.c
new file mode 100755 (executable)
index 0000000..24b6383
--- /dev/null
@@ -0,0 +1,161 @@
+/* Ppmd8Enc.c -- PPMdI Encoder\r
+2010-04-16 : Igor Pavlov : Public domain\r
+This code is based on:\r
+  PPMd var.I (2002): Dmitry Shkarin : Public domain\r
+  Carryless rangecoder (1999): Dmitry Subbotin : Public domain */\r
+\r
+#include "Ppmd8.h"\r
+\r
+#define kTop (1 << 24)\r
+#define kBot (1 << 15)\r
+\r
+void Ppmd8_RangeEnc_FlushData(CPpmd8 *p)\r
+{\r
+  unsigned i;\r
+  for (i = 0; i < 4; i++, p->Low <<= 8 )\r
+    p->Stream.Out->Write(p->Stream.Out, (Byte)(p->Low >> 24));\r
+}\r
+\r
+static void RangeEnc_Normalize(CPpmd8 *p)\r
+{\r
+  while ((p->Low ^ (p->Low + p->Range)) < kTop ||\r
+      (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1)))\r
+  {\r
+    p->Stream.Out->Write(p->Stream.Out, (Byte)(p->Low >> 24));\r
+    p->Range <<= 8;\r
+    p->Low <<= 8;\r
+  }\r
+}\r
+\r
+static void RangeEnc_Encode(CPpmd8 *p, UInt32 start, UInt32 size, UInt32 total)\r
+{\r
+  p->Low += start * (p->Range /= total);\r
+  p->Range *= size;\r
+  RangeEnc_Normalize(p);\r
+}\r
+\r
+static void RangeEnc_EncodeBit_0(CPpmd8 *p, UInt32 size0)\r
+{\r
+  p->Range >>= 14;\r
+  p->Range *= size0;\r
+  RangeEnc_Normalize(p);\r
+}\r
+\r
+static void RangeEnc_EncodeBit_1(CPpmd8 *p, UInt32 size0)\r
+{\r
+  p->Low += size0 * (p->Range >>= 14);\r
+  p->Range *= ((1 << 14) - size0);\r
+  RangeEnc_Normalize(p);\r
+}\r
+\r
+\r
+#define MASK(sym) ((signed char *)charMask)[sym]\r
+\r
+void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol)\r
+{\r
+  size_t charMask[256 / sizeof(size_t)];\r
+  if (p->MinContext->NumStats != 0)\r
+  {\r
+    CPpmd_State *s = Ppmd8_GetStats(p, p->MinContext);\r
+    UInt32 sum;\r
+    unsigned i;\r
+    if (s->Symbol == symbol)\r
+    {\r
+      RangeEnc_Encode(p, 0, s->Freq, p->MinContext->SummFreq);\r
+      p->FoundState = s;\r
+      Ppmd8_Update1_0(p);\r
+      return;\r
+    }\r
+    p->PrevSuccess = 0;\r
+    sum = s->Freq;\r
+    i = p->MinContext->NumStats;\r
+    do\r
+    {\r
+      if ((++s)->Symbol == symbol)\r
+      {\r
+        RangeEnc_Encode(p, sum, s->Freq, p->MinContext->SummFreq);\r
+        p->FoundState = s;\r
+        Ppmd8_Update1(p);\r
+        return;\r
+      }\r
+      sum += s->Freq;\r
+    }\r
+    while (--i);\r
+    \r
+    PPMD_SetAllBitsIn256Bytes(charMask);\r
+    MASK(s->Symbol) = 0;\r
+    i = p->MinContext->NumStats;\r
+    do { MASK((--s)->Symbol) = 0; } while (--i);\r
+    RangeEnc_Encode(p, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq);\r
+  }\r
+  else\r
+  {\r
+    UInt16 *prob = Ppmd8_GetBinSumm(p);\r
+    CPpmd_State *s = Ppmd8Context_OneState(p->MinContext);\r
+    if (s->Symbol == symbol)\r
+    {\r
+      RangeEnc_EncodeBit_0(p, *prob);\r
+      *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);\r
+      p->FoundState = s;\r
+      Ppmd8_UpdateBin(p);\r
+      return;\r
+    }\r
+    else\r
+    {\r
+      RangeEnc_EncodeBit_1(p, *prob);\r
+      *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);\r
+      p->InitEsc = PPMD8_kExpEscape[*prob >> 10];\r
+      PPMD_SetAllBitsIn256Bytes(charMask);\r
+      MASK(s->Symbol) = 0;\r
+      p->PrevSuccess = 0;\r
+    }\r
+  }\r
+  for (;;)\r
+  {\r
+    UInt32 escFreq;\r
+    CPpmd_See *see;\r
+    CPpmd_State *s;\r
+    UInt32 sum;\r
+    unsigned i, numMasked = p->MinContext->NumStats;\r
+    do\r
+    {\r
+      p->OrderFall++;\r
+      if (!p->MinContext->Suffix)\r
+        return; /* EndMarker (symbol = -1) */\r
+      p->MinContext = Ppmd8_GetContext(p, p->MinContext->Suffix);\r
+    }\r
+    while (p->MinContext->NumStats == numMasked);\r
+    \r
+    see = Ppmd8_MakeEscFreq(p, numMasked, &escFreq);\r
+    s = Ppmd8_GetStats(p, p->MinContext);\r
+    sum = 0;\r
+    i = p->MinContext->NumStats + 1;\r
+    do\r
+    {\r
+      int cur = s->Symbol;\r
+      if (cur == symbol)\r
+      {\r
+        UInt32 low = sum;\r
+        CPpmd_State *s1 = s;\r
+        do\r
+        {\r
+          sum += (s->Freq & (int)(MASK(s->Symbol)));\r
+          s++;\r
+        }\r
+        while (--i);\r
+        RangeEnc_Encode(p, low, s1->Freq, sum + escFreq);\r
+        Ppmd_See_Update(see);\r
+        p->FoundState = s1;\r
+        Ppmd8_Update2(p);\r
+        return;\r
+      }\r
+      sum += (s->Freq & (int)(MASK(cur)));\r
+      MASK(cur) = 0;\r
+      s++;\r
+    }\r
+    while (--i);\r
+    \r
+    RangeEnc_Encode(p, sum, escFreq, sum + escFreq);\r
+    see->Summ = (UInt16)(see->Summ + sum + escFreq);\r
+  }\r
+}\r
diff --git a/C/RotateDefs.h b/C/RotateDefs.h
new file mode 100755 (executable)
index 0000000..ff9b722
--- /dev/null
@@ -0,0 +1,20 @@
+/* RotateDefs.h -- Rotate functions\r
+2009-02-07 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __ROTATE_DEFS_H\r
+#define __ROTATE_DEFS_H\r
+\r
+#ifdef _MSC_VER\r
+\r
+#include <stdlib.h>\r
+#define rotlFixed(x, n) _rotl((x), (n))\r
+#define rotrFixed(x, n) _rotr((x), (n))\r
+\r
+#else\r
+\r
+#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n))))\r
+#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n))))\r
+\r
+#endif\r
+\r
+#endif\r
diff --git a/C/Sha256.c b/C/Sha256.c
new file mode 100755 (executable)
index 0000000..cfb9eac
--- /dev/null
@@ -0,0 +1,204 @@
+/* Crypto/Sha256.c -- SHA-256 Hash\r
+2010-06-11 : Igor Pavlov : Public domain\r
+This code is based on public domain code from Wei Dai's Crypto++ library. */\r
+\r
+#include "RotateDefs.h"\r
+#include "Sha256.h"\r
+\r
+/* define it for speed optimization */\r
+/* #define _SHA256_UNROLL */\r
+/* #define _SHA256_UNROLL2 */\r
+\r
+void Sha256_Init(CSha256 *p)\r
+{\r
+  p->state[0] = 0x6a09e667;\r
+  p->state[1] = 0xbb67ae85;\r
+  p->state[2] = 0x3c6ef372;\r
+  p->state[3] = 0xa54ff53a;\r
+  p->state[4] = 0x510e527f;\r
+  p->state[5] = 0x9b05688c;\r
+  p->state[6] = 0x1f83d9ab;\r
+  p->state[7] = 0x5be0cd19;\r
+  p->count = 0;\r
+}\r
+\r
+#define S0(x) (rotrFixed(x, 2) ^ rotrFixed(x,13) ^ rotrFixed(x, 22))\r
+#define S1(x) (rotrFixed(x, 6) ^ rotrFixed(x,11) ^ rotrFixed(x, 25))\r
+#define s0(x) (rotrFixed(x, 7) ^ rotrFixed(x,18) ^ (x >> 3))\r
+#define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >> 10))\r
+\r
+#define blk0(i) (W[i] = data[i])\r
+#define blk2(i) (W[i&15] += s1(W[(i-2)&15]) + W[(i-7)&15] + s0(W[(i-15)&15]))\r
+\r
+#define Ch(x,y,z) (z^(x&(y^z)))\r
+#define Maj(x,y,z) ((x&y)|(z&(x|y)))\r
+\r
+#define a(i) T[(0-(i))&7]\r
+#define b(i) T[(1-(i))&7]\r
+#define c(i) T[(2-(i))&7]\r
+#define d(i) T[(3-(i))&7]\r
+#define e(i) T[(4-(i))&7]\r
+#define f(i) T[(5-(i))&7]\r
+#define g(i) T[(6-(i))&7]\r
+#define h(i) T[(7-(i))&7]\r
+\r
+\r
+#ifdef _SHA256_UNROLL2\r
+\r
+#define R(a,b,c,d,e,f,g,h, i) h += S1(e) + Ch(e,f,g) + K[i+j] + (j?blk2(i):blk0(i));\\r
+  d += h; h += S0(a) + Maj(a, b, c)\r
+\r
+#define RX_8(i) \\r
+  R(a,b,c,d,e,f,g,h, i); \\r
+  R(h,a,b,c,d,e,f,g, i+1); \\r
+  R(g,h,a,b,c,d,e,f, i+2); \\r
+  R(f,g,h,a,b,c,d,e, i+3); \\r
+  R(e,f,g,h,a,b,c,d, i+4); \\r
+  R(d,e,f,g,h,a,b,c, i+5); \\r
+  R(c,d,e,f,g,h,a,b, i+6); \\r
+  R(b,c,d,e,f,g,h,a, i+7)\r
+\r
+#else\r
+\r
+#define R(i) h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + (j?blk2(i):blk0(i));\\r
+  d(i) += h(i); h(i) += S0(a(i)) + Maj(a(i), b(i), c(i))\r
+\r
+#ifdef _SHA256_UNROLL\r
+\r
+#define RX_8(i) R(i+0); R(i+1); R(i+2); R(i+3); R(i+4); R(i+5); R(i+6); R(i+7);\r
+\r
+#endif\r
+\r
+#endif\r
+\r
+static const UInt32 K[64] = {\r
+  0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,\r
+  0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\r
+  0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,\r
+  0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\r
+  0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,\r
+  0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\r
+  0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,\r
+  0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\r
+  0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,\r
+  0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\r
+  0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,\r
+  0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\r
+  0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,\r
+  0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\r
+  0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,\r
+  0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2\r
+};\r
+\r
+static void Sha256_Transform(UInt32 *state, const UInt32 *data)\r
+{\r
+  UInt32 W[16];\r
+  unsigned j;\r
+  #ifdef _SHA256_UNROLL2\r
+  UInt32 a,b,c,d,e,f,g,h;\r
+  a = state[0];\r
+  b = state[1];\r
+  c = state[2];\r
+  d = state[3];\r
+  e = state[4];\r
+  f = state[5];\r
+  g = state[6];\r
+  h = state[7];\r
+  #else\r
+  UInt32 T[8];\r
+  for (j = 0; j < 8; j++)\r
+    T[j] = state[j];\r
+  #endif\r
+\r
+  for (j = 0; j < 64; j += 16)\r
+  {\r
+    #if defined(_SHA256_UNROLL) || defined(_SHA256_UNROLL2)\r
+    RX_8(0); RX_8(8);\r
+    #else\r
+    unsigned i;\r
+    for (i = 0; i < 16; i++) { R(i); }\r
+    #endif\r
+  }\r
+\r
+  #ifdef _SHA256_UNROLL2\r
+  state[0] += a;\r
+  state[1] += b;\r
+  state[2] += c;\r
+  state[3] += d;\r
+  state[4] += e;\r
+  state[5] += f;\r
+  state[6] += g;\r
+  state[7] += h;\r
+  #else\r
+  for (j = 0; j < 8; j++)\r
+    state[j] += T[j];\r
+  #endif\r
+  \r
+  /* Wipe variables */\r
+  /* memset(W, 0, sizeof(W)); */\r
+  /* memset(T, 0, sizeof(T)); */\r
+}\r
+\r
+#undef S0\r
+#undef S1\r
+#undef s0\r
+#undef s1\r
+\r
+static void Sha256_WriteByteBlock(CSha256 *p)\r
+{\r
+  UInt32 data32[16];\r
+  unsigned i;\r
+  for (i = 0; i < 16; i++)\r
+    data32[i] =\r
+      ((UInt32)(p->buffer[i * 4    ]) << 24) +\r
+      ((UInt32)(p->buffer[i * 4 + 1]) << 16) +\r
+      ((UInt32)(p->buffer[i * 4 + 2]) <<  8) +\r
+      ((UInt32)(p->buffer[i * 4 + 3]));\r
+  Sha256_Transform(p->state, data32);\r
+}\r
+\r
+void Sha256_Update(CSha256 *p, const Byte *data, size_t size)\r
+{\r
+  UInt32 curBufferPos = (UInt32)p->count & 0x3F;\r
+  while (size > 0)\r
+  {\r
+    p->buffer[curBufferPos++] = *data++;\r
+    p->count++;\r
+    size--;\r
+    if (curBufferPos == 64)\r
+    {\r
+      curBufferPos = 0;\r
+      Sha256_WriteByteBlock(p);\r
+    }\r
+  }\r
+}\r
+\r
+void Sha256_Final(CSha256 *p, Byte *digest)\r
+{\r
+  UInt64 lenInBits = (p->count << 3);\r
+  UInt32 curBufferPos = (UInt32)p->count & 0x3F;\r
+  unsigned i;\r
+  p->buffer[curBufferPos++] = 0x80;\r
+  while (curBufferPos != (64 - 8))\r
+  {\r
+    curBufferPos &= 0x3F;\r
+    if (curBufferPos == 0)\r
+      Sha256_WriteByteBlock(p);\r
+    p->buffer[curBufferPos++] = 0;\r
+  }\r
+  for (i = 0; i < 8; i++)\r
+  {\r
+    p->buffer[curBufferPos++] = (Byte)(lenInBits >> 56);\r
+    lenInBits <<= 8;\r
+  }\r
+  Sha256_WriteByteBlock(p);\r
+\r
+  for (i = 0; i < 8; i++)\r
+  {\r
+    *digest++ = (Byte)(p->state[i] >> 24);\r
+    *digest++ = (Byte)(p->state[i] >> 16);\r
+    *digest++ = (Byte)(p->state[i] >> 8);\r
+    *digest++ = (Byte)(p->state[i]);\r
+  }\r
+  Sha256_Init(p);\r
+}\r
diff --git a/C/Sha256.h b/C/Sha256.h
new file mode 100755 (executable)
index 0000000..26d1e3a
--- /dev/null
@@ -0,0 +1,26 @@
+/* Sha256.h -- SHA-256 Hash\r
+2010-06-11 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __CRYPTO_SHA256_H\r
+#define __CRYPTO_SHA256_H\r
+\r
+#include "Types.h"\r
+\r
+EXTERN_C_BEGIN\r
+\r
+#define SHA256_DIGEST_SIZE 32\r
+\r
+typedef struct\r
+{\r
+  UInt32 state[8];\r
+  UInt64 count;\r
+  Byte buffer[64];\r
+} CSha256;\r
+\r
+void Sha256_Init(CSha256 *p);\r
+void Sha256_Update(CSha256 *p, const Byte *data, size_t size);\r
+void Sha256_Final(CSha256 *p, Byte *digest);\r
+\r
+EXTERN_C_END\r
+\r
+#endif\r
diff --git a/C/Sort.c b/C/Sort.c
new file mode 100755 (executable)
index 0000000..d06e565
--- /dev/null
+++ b/C/Sort.c
@@ -0,0 +1,93 @@
+/* Sort.c -- Sort functions\r
+2010-09-17 : Igor Pavlov : Public domain */\r
+\r
+#include "Sort.h"\r
+\r
+#define HeapSortDown(p, k, size, temp) \\r
+  { for (;;) { \\r
+    UInt32 s = (k << 1); \\r
+    if (s > size) break; \\r
+    if (s < size && p[s + 1] > p[s]) s++; \\r
+    if (temp >= p[s]) break; \\r
+    p[k] = p[s]; k = s; \\r
+  } p[k] = temp; }\r
+\r
+void HeapSort(UInt32 *p, UInt32 size)\r
+{\r
+  if (size <= 1)\r
+    return;\r
+  p--;\r
+  {\r
+    UInt32 i = size / 2;\r
+    do\r
+    {\r
+      UInt32 temp = p[i];\r
+      UInt32 k = i;\r
+      HeapSortDown(p, k, size, temp)\r
+    }\r
+    while (--i != 0);\r
+  }\r
+  /*\r
+  do\r
+  {\r
+    UInt32 k = 1;\r
+    UInt32 temp = p[size];\r
+    p[size--] = p[1];\r
+    HeapSortDown(p, k, size, temp)\r
+  }\r
+  while (size > 1);\r
+  */\r
+  while (size > 3)\r
+  {\r
+    UInt32 temp = p[size];\r
+    UInt32 k = (p[3] > p[2]) ? 3 : 2;\r
+    p[size--] = p[1];\r
+    p[1] = p[k];\r
+    HeapSortDown(p, k, size, temp)\r
+  }\r
+  {\r
+    UInt32 temp = p[size];\r
+    p[size] = p[1];\r
+    if (size > 2 && p[2] < temp)\r
+    {\r
+      p[1] = p[2];\r
+      p[2] = temp;\r
+    }\r
+    else\r
+      p[1] = temp;\r
+  }\r
+}\r
+\r
+/*\r
+#define HeapSortRefDown(p, vals, n, size, temp) \\r
+  { UInt32 k = n; UInt32 val = vals[temp]; for (;;) { \\r
+    UInt32 s = (k << 1); \\r
+    if (s > size) break; \\r
+    if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \\r
+    if (val >= vals[p[s]]) break; \\r
+    p[k] = p[s]; k = s; \\r
+  } p[k] = temp; }\r
+\r
+void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size)\r
+{\r
+  if (size <= 1)\r
+    return;\r
+  p--;\r
+  {\r
+    UInt32 i = size / 2;\r
+    do\r
+    {\r
+      UInt32 temp = p[i];\r
+      HeapSortRefDown(p, vals, i, size, temp);\r
+    }\r
+    while (--i != 0);\r
+  }\r
+  do\r
+  {\r
+    UInt32 temp = p[size];\r
+    p[size--] = p[1];\r
+    HeapSortRefDown(p, vals, 1, size, temp);\r
+  }\r
+  while (size > 1);\r
+}\r
+*/\r
diff --git a/C/Sort.h b/C/Sort.h
new file mode 100755 (executable)
index 0000000..7613039
--- /dev/null
+++ b/C/Sort.h
@@ -0,0 +1,20 @@
+/* Sort.h -- Sort functions\r
+2009-02-07 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __7Z_SORT_H\r
+#define __7Z_SORT_H\r
+\r
+#include "Types.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+void HeapSort(UInt32 *p, UInt32 size);\r
+/* void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size); */\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/C/Threads.c b/C/Threads.c
new file mode 100755 (executable)
index 0000000..4be44fb
--- /dev/null
@@ -0,0 +1,84 @@
+/* Threads.c -- multithreading library\r
+2009-09-20 : Igor Pavlov : Public domain */\r
+\r
+#ifndef _WIN32_WCE\r
+#include <process.h>\r
+#endif\r
+\r
+#include "Threads.h"\r
+\r
+static WRes GetError()\r
+{\r
+  DWORD res = GetLastError();\r
+  return (res) ? (WRes)(res) : 1;\r
+}\r
+\r
+WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); }\r
+WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); }\r
+\r
+WRes HandlePtr_Close(HANDLE *p)\r
+{\r
+  if (*p != NULL)\r
+    if (!CloseHandle(*p))\r
+      return GetError();\r
+  *p = NULL;\r
+  return 0;\r
+}\r
+\r
+WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); }\r
+\r
+WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)\r
+{\r
+  unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */\r
+  *p =\r
+    #ifdef UNDER_CE\r
+    CreateThread(0, 0, func, param, 0, &threadId);\r
+    #else\r
+    (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId);\r
+    #endif\r
+    /* maybe we must use errno here, but probably GetLastError() is also OK. */\r
+  return HandleToWRes(*p);\r
+}\r
+\r
+WRes Event_Create(CEvent *p, BOOL manualReset, int signaled)\r
+{\r
+  *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL);\r
+  return HandleToWRes(*p);\r
+}\r
+\r
+WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(*p)); }\r
+WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(*p)); }\r
+\r
+WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, TRUE, signaled); }\r
+WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, FALSE, signaled); }\r
+WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); }\r
+WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); }\r
+\r
+\r
+WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount)\r
+{\r
+  *p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL);\r
+  return HandleToWRes(*p);\r
+}\r
+\r
+static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount)\r
+  { return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); }\r
+WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num)\r
+  { return Semaphore_Release(p, (LONG)num, NULL); }\r
+WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); }\r
+\r
+WRes CriticalSection_Init(CCriticalSection *p)\r
+{\r
+  /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */\r
+  #ifdef _MSC_VER\r
+  __try\r
+  #endif\r
+  {\r
+    InitializeCriticalSection(p);\r
+    /* InitializeCriticalSectionAndSpinCount(p, 0); */\r
+  }\r
+  #ifdef _MSC_VER\r
+  __except (EXCEPTION_EXECUTE_HANDLER) { return 1; }\r
+  #endif\r
+  return 0;\r
+}\r
diff --git a/C/Threads.h b/C/Threads.h
new file mode 100755 (executable)
index 0000000..6a7afa8
--- /dev/null
@@ -0,0 +1,59 @@
+/* Threads.h -- multithreading library\r
+2009-03-27 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __7Z_THREADS_H\r
+#define __7Z_THREADS_H\r
+\r
+#include "Types.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+WRes HandlePtr_Close(HANDLE *h);\r
+WRes Handle_WaitObject(HANDLE h);\r
+\r
+typedef HANDLE CThread;\r
+#define Thread_Construct(p) *(p) = NULL\r
+#define Thread_WasCreated(p) (*(p) != NULL)\r
+#define Thread_Close(p) HandlePtr_Close(p)\r
+#define Thread_Wait(p) Handle_WaitObject(*(p))\r
+typedef unsigned THREAD_FUNC_RET_TYPE;\r
+#define THREAD_FUNC_CALL_TYPE MY_STD_CALL\r
+#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE\r
+typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);\r
+WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param);\r
+\r
+typedef HANDLE CEvent;\r
+typedef CEvent CAutoResetEvent;\r
+typedef CEvent CManualResetEvent;\r
+#define Event_Construct(p) *(p) = NULL\r
+#define Event_IsCreated(p) (*(p) != NULL)\r
+#define Event_Close(p) HandlePtr_Close(p)\r
+#define Event_Wait(p) Handle_WaitObject(*(p))\r
+WRes Event_Set(CEvent *p);\r
+WRes Event_Reset(CEvent *p);\r
+WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);\r
+WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);\r
+WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);\r
+WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);\r
+\r
+typedef HANDLE CSemaphore;\r
+#define Semaphore_Construct(p) (*p) = NULL\r
+#define Semaphore_Close(p) HandlePtr_Close(p)\r
+#define Semaphore_Wait(p) Handle_WaitObject(*(p))\r
+WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);\r
+WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);\r
+WRes Semaphore_Release1(CSemaphore *p);\r
+\r
+typedef CRITICAL_SECTION CCriticalSection;\r
+WRes CriticalSection_Init(CCriticalSection *p);\r
+#define CriticalSection_Delete(p) DeleteCriticalSection(p)\r
+#define CriticalSection_Enter(p) EnterCriticalSection(p)\r
+#define CriticalSection_Leave(p) LeaveCriticalSection(p)\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/C/Types.h b/C/Types.h
new file mode 100755 (executable)
index 0000000..f193ce2
--- /dev/null
+++ b/C/Types.h
@@ -0,0 +1,254 @@
+/* Types.h -- Basic types\r
+2010-10-09 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __7Z_TYPES_H\r
+#define __7Z_TYPES_H\r
+\r
+#include <stddef.h>\r
+\r
+#ifdef _WIN32\r
+#include <windows.h>\r
+#endif\r
+\r
+#ifndef EXTERN_C_BEGIN\r
+#ifdef __cplusplus\r
+#define EXTERN_C_BEGIN extern "C" {\r
+#define EXTERN_C_END }\r
+#else\r
+#define EXTERN_C_BEGIN\r
+#define EXTERN_C_END\r
+#endif\r
+#endif\r
+\r
+EXTERN_C_BEGIN\r
+\r
+#define SZ_OK 0\r
+\r
+#define SZ_ERROR_DATA 1\r
+#define SZ_ERROR_MEM 2\r
+#define SZ_ERROR_CRC 3\r
+#define SZ_ERROR_UNSUPPORTED 4\r
+#define SZ_ERROR_PARAM 5\r
+#define SZ_ERROR_INPUT_EOF 6\r
+#define SZ_ERROR_OUTPUT_EOF 7\r
+#define SZ_ERROR_READ 8\r
+#define SZ_ERROR_WRITE 9\r
+#define SZ_ERROR_PROGRESS 10\r
+#define SZ_ERROR_FAIL 11\r
+#define SZ_ERROR_THREAD 12\r
+\r
+#define SZ_ERROR_ARCHIVE 16\r
+#define SZ_ERROR_NO_ARCHIVE 17\r
+\r
+typedef int SRes;\r
+\r
+#ifdef _WIN32\r
+typedef DWORD WRes;\r
+#else\r
+typedef int WRes;\r
+#endif\r
+\r
+#ifndef RINOK\r
+#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }\r
+#endif\r
+\r
+typedef unsigned char Byte;\r
+typedef short Int16;\r
+typedef unsigned short UInt16;\r
+\r
+#ifdef _LZMA_UINT32_IS_ULONG\r
+typedef long Int32;\r
+typedef unsigned long UInt32;\r
+#else\r
+typedef int Int32;\r
+typedef unsigned int UInt32;\r
+#endif\r
+\r
+#ifdef _SZ_NO_INT_64\r
+\r
+/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.\r
+   NOTES: Some code will work incorrectly in that case! */\r
+\r
+typedef long Int64;\r
+typedef unsigned long UInt64;\r
+\r
+#else\r
+\r
+#if defined(_MSC_VER) || defined(__BORLANDC__)\r
+typedef __int64 Int64;\r
+typedef unsigned __int64 UInt64;\r
+#define UINT64_CONST(n) n\r
+#else\r
+typedef long long int Int64;\r
+typedef unsigned long long int UInt64;\r
+#define UINT64_CONST(n) n ## ULL\r
+#endif\r
+\r
+#endif\r
+\r
+#ifdef _LZMA_NO_SYSTEM_SIZE_T\r
+typedef UInt32 SizeT;\r
+#else\r
+typedef size_t SizeT;\r
+#endif\r
+\r
+typedef int Bool;\r
+#define True 1\r
+#define False 0\r
+\r
+\r
+#ifdef _WIN32\r
+#define MY_STD_CALL __stdcall\r
+#else\r
+#define MY_STD_CALL\r
+#endif\r
+\r
+#ifdef _MSC_VER\r
+\r
+#if _MSC_VER >= 1300\r
+#define MY_NO_INLINE __declspec(noinline)\r
+#else\r
+#define MY_NO_INLINE\r
+#endif\r
+\r
+#define MY_CDECL __cdecl\r
+#define MY_FAST_CALL __fastcall\r
+\r
+#else\r
+\r
+#define MY_CDECL\r
+#define MY_FAST_CALL\r
+\r
+#endif\r
+\r
+\r
+/* The following interfaces use first parameter as pointer to structure */\r
+\r
+typedef struct\r
+{\r
+  Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */\r
+} IByteIn;\r
+\r
+typedef struct\r
+{\r
+  void (*Write)(void *p, Byte b);\r
+} IByteOut;\r
+\r
+typedef struct\r
+{\r
+  SRes (*Read)(void *p, void *buf, size_t *size);\r
+    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.\r
+       (output(*size) < input(*size)) is allowed */\r
+} ISeqInStream;\r
+\r
+/* it can return SZ_ERROR_INPUT_EOF */\r
+SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);\r
+SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);\r
+SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);\r
+\r
+typedef struct\r
+{\r
+  size_t (*Write)(void *p, const void *buf, size_t size);\r
+    /* Returns: result - the number of actually written bytes.\r
+       (result < size) means error */\r
+} ISeqOutStream;\r
+\r
+typedef enum\r
+{\r
+  SZ_SEEK_SET = 0,\r
+  SZ_SEEK_CUR = 1,\r
+  SZ_SEEK_END = 2\r
+} ESzSeek;\r
+\r
+typedef struct\r
+{\r
+  SRes (*Read)(void *p, void *buf, size_t *size);  /* same as ISeqInStream::Read */\r
+  SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);\r
+} ISeekInStream;\r
+\r
+typedef struct\r
+{\r
+  SRes (*Look)(void *p, const void **buf, size_t *size);\r
+    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.\r
+       (output(*size) > input(*size)) is not allowed\r
+       (output(*size) < input(*size)) is allowed */\r
+  SRes (*Skip)(void *p, size_t offset);\r
+    /* offset must be <= output(*size) of Look */\r
+\r
+  SRes (*Read)(void *p, void *buf, size_t *size);\r
+    /* reads directly (without buffer). It's same as ISeqInStream::Read */\r
+  SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);\r
+} ILookInStream;\r
+\r
+SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);\r
+SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);\r
+\r
+/* reads via ILookInStream::Read */\r
+SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);\r
+SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);\r
+\r
+#define LookToRead_BUF_SIZE (1 << 14)\r
+\r
+typedef struct\r
+{\r
+  ILookInStream s;\r
+  ISeekInStream *realStream;\r
+  size_t pos;\r
+  size_t size;\r
+  Byte buf[LookToRead_BUF_SIZE];\r
+} CLookToRead;\r
+\r
+void LookToRead_CreateVTable(CLookToRead *p, int lookahead);\r
+void LookToRead_Init(CLookToRead *p);\r
+\r
+typedef struct\r
+{\r
+  ISeqInStream s;\r
+  ILookInStream *realStream;\r
+} CSecToLook;\r
+\r
+void SecToLook_CreateVTable(CSecToLook *p);\r
+\r
+typedef struct\r
+{\r
+  ISeqInStream s;\r
+  ILookInStream *realStream;\r
+} CSecToRead;\r
+\r
+void SecToRead_CreateVTable(CSecToRead *p);\r
+\r
+typedef struct\r
+{\r
+  SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);\r
+    /* Returns: result. (result != SZ_OK) means break.\r
+       Value (UInt64)(Int64)-1 for size means unknown value. */\r
+} ICompressProgress;\r
+\r
+typedef struct\r
+{\r
+  void *(*Alloc)(void *p, size_t size);\r
+  void (*Free)(void *p, void *address); /* address can be 0 */\r
+} ISzAlloc;\r
+\r
+#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)\r
+#define IAlloc_Free(p, a) (p)->Free((p), a)\r
+\r
+#ifdef _WIN32\r
+\r
+#define CHAR_PATH_SEPARATOR '\\'\r
+#define WCHAR_PATH_SEPARATOR L'\\'\r
+#define STRING_PATH_SEPARATOR "\\"\r
+#define WSTRING_PATH_SEPARATOR L"\\"\r
+\r
+#else\r
+\r
+#define CHAR_PATH_SEPARATOR '/'\r
+#define WCHAR_PATH_SEPARATOR L'/'\r
+#define STRING_PATH_SEPARATOR "/"\r
+#define WSTRING_PATH_SEPARATOR L"/"\r
+\r
+#endif\r
+\r
+EXTERN_C_END\r
+\r
+#endif\r
diff --git a/C/Util/7z/7z.dsp b/C/Util/7z/7z.dsp
new file mode 100755 (executable)
index 0000000..9f5806b
--- /dev/null
@@ -0,0 +1,214 @@
+# Microsoft Developer Studio Project File - Name="7z" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=7z - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "7z.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "7z.mak" CFG="7z - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "7z - Win32 Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "7z - Win32 Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
+# ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FAs /YX /FD /c\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# 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\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
+# 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\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x419 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# 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\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "7z - Win32 Release"\r
+# Name "7z - Win32 Debug"\r
+# Begin Group "Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7z.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zAlloc.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zAlloc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zBuf.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zBuf.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zCrc.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zCrc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zCrcOpt.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zDec.c\r
+# ADD CPP /D "_7ZIP_PPMD_SUPPPORT"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zFile.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zFile.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zIn.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zStream.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Bcj2.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Bcj2.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Bra.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Bra.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Bra86.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\CpuArch.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\CpuArch.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Lzma2Dec.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Lzma2Dec.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzmaDec.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzmaDec.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Ppmd.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Ppmd7.c\r
+# SUBTRACT CPP /YX\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Ppmd7.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Ppmd7Dec.c\r
+# SUBTRACT CPP /YX\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Types.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=.\7zMain.c\r
+# End Source File\r
+# End Target\r
+# End Project\r
diff --git a/C/Util/7z/7z.dsw b/C/Util/7z/7z.dsw
new file mode 100755 (executable)
index 0000000..23089fb
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "7z"=.\7z.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/C/Util/7z/7zMain.c b/C/Util/7z/7zMain.c
new file mode 100755 (executable)
index 0000000..f217340
--- /dev/null
@@ -0,0 +1,501 @@
+/* 7zMain.c - Test application for 7z Decoder\r
+2010-10-28 : Igor Pavlov : Public domain */\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+\r
+#include "../../7z.h"\r
+#include "../../7zAlloc.h"\r
+#include "../../7zCrc.h"\r
+#include "../../7zFile.h"\r
+#include "../../7zVersion.h"\r
+\r
+#ifndef USE_WINDOWS_FILE\r
+/* for mkdir */\r
+#ifdef _WIN32\r
+#include <direct.h>\r
+#else\r
+#include <sys/stat.h>\r
+#include <errno.h>\r
+#endif\r
+#endif\r
+\r
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };\r
+\r
+static int Buf_EnsureSize(CBuf *dest, size_t size)\r
+{\r
+  if (dest->size >= size)\r
+    return 1;\r
+  Buf_Free(dest, &g_Alloc);\r
+  return Buf_Create(dest, size, &g_Alloc);\r
+}\r
+\r
+#ifndef _WIN32\r
+\r
+static Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };\r
+\r
+static Bool Utf16_To_Utf8(Byte *dest, size_t *destLen, const UInt16 *src, size_t srcLen)\r
+{\r
+  size_t destPos = 0, srcPos = 0;\r
+  for (;;)\r
+  {\r
+    unsigned numAdds;\r
+    UInt32 value;\r
+    if (srcPos == srcLen)\r
+    {\r
+      *destLen = destPos;\r
+      return True;\r
+    }\r
+    value = src[srcPos++];\r
+    if (value < 0x80)\r
+    {\r
+      if (dest)\r
+        dest[destPos] = (char)value;\r
+      destPos++;\r
+      continue;\r
+    }\r
+    if (value >= 0xD800 && value < 0xE000)\r
+    {\r
+      UInt32 c2;\r
+      if (value >= 0xDC00 || srcPos == srcLen)\r
+        break;\r
+      c2 = src[srcPos++];\r
+      if (c2 < 0xDC00 || c2 >= 0xE000)\r
+        break;\r
+      value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;\r
+    }\r
+    for (numAdds = 1; numAdds < 5; numAdds++)\r
+      if (value < (((UInt32)1) << (numAdds * 5 + 6)))\r
+        break;\r
+    if (dest)\r
+      dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));\r
+    destPos++;\r
+    do\r
+    {\r
+      numAdds--;\r
+      if (dest)\r
+        dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));\r
+      destPos++;\r
+    }\r
+    while (numAdds != 0);\r
+  }\r
+  *destLen = destPos;\r
+  return False;\r
+}\r
+\r
+static SRes Utf16_To_Utf8Buf(CBuf *dest, const UInt16 *src, size_t srcLen)\r
+{\r
+  size_t destLen = 0;\r
+  Bool res;\r
+  Utf16_To_Utf8(NULL, &destLen, src, srcLen);\r
+  destLen += 1;\r
+  if (!Buf_EnsureSize(dest, destLen))\r
+    return SZ_ERROR_MEM;\r
+  res = Utf16_To_Utf8(dest->data, &destLen, src, srcLen);\r
+  dest->data[destLen] = 0;\r
+  return res ? SZ_OK : SZ_ERROR_FAIL;\r
+}\r
+#endif\r
+\r
+static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s, int fileMode)\r
+{\r
+  int len = 0;\r
+  for (len = 0; s[len] != '\0'; len++);\r
+\r
+  #ifdef _WIN32\r
+  {\r
+    int size = len * 3 + 100;\r
+    if (!Buf_EnsureSize(buf, size))\r
+      return SZ_ERROR_MEM;\r
+    {\r
+      char defaultChar = '_';\r
+      BOOL defUsed;\r
+      int numChars = WideCharToMultiByte(fileMode ?\r
+          (\r
+          #ifdef UNDER_CE\r
+          CP_ACP\r
+          #else\r
+          AreFileApisANSI() ? CP_ACP : CP_OEMCP\r
+          #endif\r
+          ) : CP_OEMCP,\r
+          0, s, len, (char *)buf->data, size, &defaultChar, &defUsed);\r
+      if (numChars == 0 || numChars >= size)\r
+        return SZ_ERROR_FAIL;\r
+      buf->data[numChars] = 0;\r
+      return SZ_OK;\r
+    }\r
+  }\r
+  #else\r
+  fileMode = fileMode;\r
+  return Utf16_To_Utf8Buf(buf, s, len);\r
+  #endif\r
+}\r
+\r
+static WRes MyCreateDir(const UInt16 *name)\r
+{\r
+  #ifdef USE_WINDOWS_FILE\r
+  \r
+  return CreateDirectoryW(name, NULL) ? 0 : GetLastError();\r
+  \r
+  #else\r
+\r
+  CBuf buf;\r
+  WRes res;\r
+  Buf_Init(&buf);\r
+  RINOK(Utf16_To_Char(&buf, name, 1));\r
+\r
+  res =\r
+  #ifdef _WIN32\r
+  _mkdir((const char *)buf.data)\r
+  #else\r
+  mkdir((const char *)buf.data, 0777)\r
+  #endif\r
+  == 0 ? 0 : errno;\r
+  Buf_Free(&buf, &g_Alloc);\r
+  return res;\r
+  \r
+  #endif\r
+}\r
+\r
+static WRes OutFile_OpenUtf16(CSzFile *p, const UInt16 *name)\r
+{\r
+  #ifdef USE_WINDOWS_FILE\r
+  return OutFile_OpenW(p, name);\r
+  #else\r
+  CBuf buf;\r
+  WRes res;\r
+  Buf_Init(&buf);\r
+  RINOK(Utf16_To_Char(&buf, name, 1));\r
+  res = OutFile_Open(p, (const char *)buf.data);\r
+  Buf_Free(&buf, &g_Alloc);\r
+  return res;\r
+  #endif\r
+}\r
+\r
+static SRes PrintString(const UInt16 *s)\r
+{\r
+  CBuf buf;\r
+  SRes res;\r
+  Buf_Init(&buf);\r
+  res = Utf16_To_Char(&buf, s, 0);\r
+  if (res == SZ_OK)\r
+    fputs((const char *)buf.data, stdout);\r
+  Buf_Free(&buf, &g_Alloc);\r
+  return res;\r
+}\r
+\r
+static void UInt64ToStr(UInt64 value, char *s)\r
+{\r
+  char temp[32];\r
+  int pos = 0;\r
+  do\r
+  {\r
+    temp[pos++] = (char)('0' + (unsigned)(value % 10));\r
+    value /= 10;\r
+  }\r
+  while (value != 0);\r
+  do\r
+    *s++ = temp[--pos];\r
+  while (pos);\r
+  *s = '\0';\r
+}\r
+\r
+static char *UIntToStr(char *s, unsigned value, int numDigits)\r
+{\r
+  char temp[16];\r
+  int pos = 0;\r
+  do\r
+    temp[pos++] = (char)('0' + (value % 10));\r
+  while (value /= 10);\r
+  for (numDigits -= pos; numDigits > 0; numDigits--)\r
+    *s++ = '0';\r
+  do\r
+    *s++ = temp[--pos];\r
+  while (pos);\r
+  *s = '\0';\r
+  return s;\r
+}\r
+\r
+#define PERIOD_4 (4 * 365 + 1)\r
+#define PERIOD_100 (PERIOD_4 * 25 - 1)\r
+#define PERIOD_400 (PERIOD_100 * 4 + 1)\r
+\r
+static void ConvertFileTimeToString(const CNtfsFileTime *ft, char *s)\r
+{\r
+  unsigned year, mon, day, hour, min, sec;\r
+  UInt64 v64 = (ft->Low | ((UInt64)ft->High << 32)) / 10000000;\r
+  Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\r
+  unsigned t;\r
+  UInt32 v;\r
+  sec = (unsigned)(v64 % 60); v64 /= 60;\r
+  min = (unsigned)(v64 % 60); v64 /= 60;\r
+  hour = (unsigned)(v64 % 24); v64 /= 24;\r
+\r
+  v = (UInt32)v64;\r
+\r
+  year = (unsigned)(1601 + v / PERIOD_400 * 400);\r
+  v %= PERIOD_400;\r
+\r
+  t = v / PERIOD_100; if (t ==  4) t =  3; year += t * 100; v -= t * PERIOD_100;\r
+  t = v / PERIOD_4;   if (t == 25) t = 24; year += t * 4;   v -= t * PERIOD_4;\r
+  t = v / 365;        if (t ==  4) t =  3; year += t;       v -= t * 365;\r
+\r
+  if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))\r
+    ms[1] = 29;\r
+  for (mon = 1; mon <= 12; mon++)\r
+  {\r
+    unsigned s = ms[mon - 1];\r
+    if (v < s)\r
+      break;\r
+    v -= s;\r
+  }\r
+  day = (unsigned)v + 1;\r
+  s = UIntToStr(s, year, 4); *s++ = '-';\r
+  s = UIntToStr(s, mon, 2);  *s++ = '-';\r
+  s = UIntToStr(s, day, 2);  *s++ = ' ';\r
+  s = UIntToStr(s, hour, 2); *s++ = ':';\r
+  s = UIntToStr(s, min, 2);  *s++ = ':';\r
+  s = UIntToStr(s, sec, 2);\r
+}\r
+\r
+void PrintError(char *sz)\r
+{\r
+  printf("\nERROR: %s\n", sz);\r
+}\r
+\r
+#ifdef USE_WINDOWS_FILE\r
+#define kEmptyAttribChar '.'\r
+static void GetAttribString(UInt32 wa, Bool isDir, char *s)\r
+{\r
+  s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : kEmptyAttribChar);\r
+  s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar);\r
+  s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar);\r
+  s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar);\r
+  s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar);\r
+  s[5] = '\0';\r
+}\r
+#else\r
+static void GetAttribString(UInt32, Bool, char *s)\r
+{\r
+  s[0] = '\0';\r
+}\r
+#endif\r
+\r
+int MY_CDECL main(int numargs, char *args[])\r
+{\r
+  CFileInStream archiveStream;\r
+  CLookToRead lookStream;\r
+  CSzArEx db;\r
+  SRes res;\r
+  ISzAlloc allocImp;\r
+  ISzAlloc allocTempImp;\r
+  UInt16 *temp = NULL;\r
+  size_t tempSize = 0;\r
+\r
+  printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n");\r
+  if (numargs == 1)\r
+  {\r
+    printf(\r
+      "Usage: 7zDec <command> <archive_name>\n\n"\r
+      "<Commands>\n"\r
+      "  e: Extract files from archive (without using directory names)\n"\r
+      "  l: List contents of archive\n"\r
+      "  t: Test integrity of archive\n"\r
+      "  x: eXtract files with full paths\n");\r
+    return 0;\r
+  }\r
+  if (numargs < 3)\r
+  {\r
+    PrintError("incorrect command");\r
+    return 1;\r
+  }\r
+\r
+  allocImp.Alloc = SzAlloc;\r
+  allocImp.Free = SzFree;\r
+\r
+  allocTempImp.Alloc = SzAllocTemp;\r
+  allocTempImp.Free = SzFreeTemp;\r
+\r
+  if (InFile_Open(&archiveStream.file, args[2]))\r
+  {\r
+    PrintError("can not open input file");\r
+    return 1;\r
+  }\r
+\r
+  FileInStream_CreateVTable(&archiveStream);\r
+  LookToRead_CreateVTable(&lookStream, False);\r
+  \r
+  lookStream.realStream = &archiveStream.s;\r
+  LookToRead_Init(&lookStream);\r
+\r
+  CrcGenerateTable();\r
+\r
+  SzArEx_Init(&db);\r
+  res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);\r
+  if (res == SZ_OK)\r
+  {\r
+    char *command = args[1];\r
+    int listCommand = 0, testCommand = 0, extractCommand = 0, fullPaths = 0;\r
+    if (strcmp(command, "l") == 0) listCommand = 1;\r
+    else if (strcmp(command, "t") == 0) testCommand = 1;\r
+    else if (strcmp(command, "e") == 0) extractCommand = 1;\r
+    else if (strcmp(command, "x") == 0) { extractCommand = 1; fullPaths = 1; }\r
+    else\r
+    {\r
+      PrintError("incorrect command");\r
+      res = SZ_ERROR_FAIL;\r
+    }\r
+\r
+    if (res == SZ_OK)\r
+    {\r
+      UInt32 i;\r
+\r
+      /*\r
+      if you need cache, use these 3 variables.\r
+      if you use external function, you can make these variable as static.\r
+      */\r
+      UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */\r
+      Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */\r
+      size_t outBufferSize = 0;  /* it can have any value before first call (if outBuffer = 0) */\r
+\r
+      for (i = 0; i < db.db.NumFiles; i++)\r
+      {\r
+        size_t offset = 0;\r
+        size_t outSizeProcessed = 0;\r
+        const CSzFileItem *f = db.db.Files + i;\r
+        size_t len;\r
+        if (listCommand == 0 && f->IsDir && !fullPaths)\r
+          continue;\r
+        len = SzArEx_GetFileNameUtf16(&db, i, NULL);\r
+\r
+        if (len > tempSize)\r
+        {\r
+          SzFree(NULL, temp);\r
+          tempSize = len;\r
+          temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0]));\r
+          if (temp == 0)\r
+          {\r
+            res = SZ_ERROR_MEM;\r
+            break;\r
+          }\r
+        }\r
+\r
+        SzArEx_GetFileNameUtf16(&db, i, temp);\r
+        if (listCommand)\r
+        {\r
+          char attr[8], s[32], t[32];\r
+\r
+          GetAttribString(f->AttribDefined ? f->Attrib : 0, f->IsDir, attr);\r
+\r
+          UInt64ToStr(f->Size, s);\r
+          if (f->MTimeDefined)\r
+            ConvertFileTimeToString(&f->MTime, t);\r
+          else\r
+          {\r
+            size_t j;\r
+            for (j = 0; j < 19; j++)\r
+              t[j] = ' ';\r
+            t[j] = '\0';\r
+          }\r
+          \r
+          printf("%s %s %10s  ", t, attr, s);\r
+          res = PrintString(temp);\r
+          if (res != SZ_OK)\r
+            break;\r
+          if (f->IsDir)\r
+            printf("/");\r
+          printf("\n");\r
+          continue;\r
+        }\r
+        fputs(testCommand ?\r
+            "Testing    ":\r
+            "Extracting ",\r
+            stdout);\r
+        res = PrintString(temp);\r
+        if (res != SZ_OK)\r
+          break;\r
+        if (f->IsDir)\r
+          printf("/");\r
+        else\r
+        {\r
+          res = SzArEx_Extract(&db, &lookStream.s, i,\r
+              &blockIndex, &outBuffer, &outBufferSize,\r
+              &offset, &outSizeProcessed,\r
+              &allocImp, &allocTempImp);\r
+          if (res != SZ_OK)\r
+            break;\r
+        }\r
+        if (!testCommand)\r
+        {\r
+          CSzFile outFile;\r
+          size_t processedSize;\r
+          size_t j;\r
+          UInt16 *name = (UInt16 *)temp;\r
+          const UInt16 *destPath = (const UInt16 *)name;\r
+          for (j = 0; name[j] != 0; j++)\r
+            if (name[j] == '/')\r
+            {\r
+              if (fullPaths)\r
+              {\r
+                name[j] = 0;\r
+                MyCreateDir(name);\r
+                name[j] = CHAR_PATH_SEPARATOR;\r
+              }\r
+              else\r
+                destPath = name + j + 1;\r
+            }\r
+    \r
+          if (f->IsDir)\r
+          {\r
+            MyCreateDir(destPath);\r
+            printf("\n");\r
+            continue;\r
+          }\r
+          else if (OutFile_OpenUtf16(&outFile, destPath))\r
+          {\r
+            PrintError("can not open output file");\r
+            res = SZ_ERROR_FAIL;\r
+            break;\r
+          }\r
+          processedSize = outSizeProcessed;\r
+          if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed)\r
+          {\r
+            PrintError("can not write output file");\r
+            res = SZ_ERROR_FAIL;\r
+            break;\r
+          }\r
+          if (File_Close(&outFile))\r
+          {\r
+            PrintError("can not close output file");\r
+            res = SZ_ERROR_FAIL;\r
+            break;\r
+          }\r
+          #ifdef USE_WINDOWS_FILE\r
+          if (f->AttribDefined)\r
+            SetFileAttributesW(destPath, f->Attrib);\r
+          #endif\r
+        }\r
+        printf("\n");\r
+      }\r
+      IAlloc_Free(&allocImp, outBuffer);\r
+    }\r
+  }\r
+  SzArEx_Free(&db, &allocImp);\r
+  SzFree(NULL, temp);\r
+\r
+  File_Close(&archiveStream.file);\r
+  if (res == SZ_OK)\r
+  {\r
+    printf("\nEverything is Ok\n");\r
+    return 0;\r
+  }\r
+  if (res == SZ_ERROR_UNSUPPORTED)\r
+    PrintError("decoder doesn't support this archive");\r
+  else if (res == SZ_ERROR_MEM)\r
+    PrintError("can not allocate memory");\r
+  else if (res == SZ_ERROR_CRC)\r
+    PrintError("CRC error");\r
+  else\r
+    printf("\nERROR #%d\n", res);\r
+  return 1;\r
+}\r
diff --git a/C/Util/7z/makefile b/C/Util/7z/makefile
new file mode 100755 (executable)
index 0000000..3b85364
--- /dev/null
@@ -0,0 +1,37 @@
+MY_STATIC_LINK=1\r
+CFLAGS = $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT\r
+\r
+PROG = 7zDec.exe\r
+\r
+C_OBJS = \\r
+  $O\7zAlloc.obj \\r
+  $O\7zBuf.obj \\r
+  $O\7zBuf2.obj \\r
+  $O\7zCrc.obj \\r
+  $O\7zCrcOpt.obj \\r
+  $O\7zFile.obj \\r
+  $O\7zDec.obj \\r
+  $O\7zIn.obj \\r
+  $O\7zStream.obj \\r
+  $O\Bcj2.obj \\r
+  $O\Bra.obj \\r
+  $O\Bra86.obj \\r
+  $O\CpuArch.obj \\r
+  $O\Lzma2Dec.obj \\r
+  $O\LzmaDec.obj \\r
+  $O\Ppmd7.obj \\r
+  $O\Ppmd7Dec.obj \\r
+\r
+7Z_OBJS = \\r
+  $O\7zMain.obj \\r
+\r
+OBJS = \\r
+  $(7Z_OBJS) \\r
+  $(C_OBJS) \\r
+\r
+!include "../../../CPP/Build.mak"\r
+\r
+$(7Z_OBJS): $(*B).c\r
+       $(COMPL_O1)\r
+$(C_OBJS): ../../$(*B).c\r
+       $(COMPL_O2)\r
diff --git a/C/Util/7z/makefile.gcc b/C/Util/7z/makefile.gcc
new file mode 100755 (executable)
index 0000000..2fb1576
--- /dev/null
@@ -0,0 +1,70 @@
+PROG = 7zDec\r
+CXX = g++\r
+LIB =\r
+RM = rm -f\r
+CFLAGS = -c -O2 -Wall\r
+\r
+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\r
+\r
+all: $(PROG)\r
+\r
+$(PROG): $(OBJS)\r
+       $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB)\r
+\r
+7zMain.o: 7zMain.c\r
+       $(CXX) $(CFLAGS) 7zMain.c\r
+\r
+7zAlloc.o: 7zAlloc.c\r
+       $(CXX) $(CFLAGS) ../../7zAlloc.c\r
+\r
+7zBuf.o: ../../7zBuf.c\r
+       $(CXX) $(CFLAGS) ../../7zBuf.c\r
+\r
+7zBuf2.o: ../../7zBuf2.c\r
+       $(CXX) $(CFLAGS) ../../7zBuf2.c\r
+\r
+7zCrc.o: ../../7zCrc.c\r
+       $(CXX) $(CFLAGS) ../../7zCrc.c\r
+\r
+7zCrcOpt.o: ../../7zCrc.c\r
+       $(CXX) $(CFLAGS) ../../7zCrcOpt.c\r
+\r
+7zDec.o: ../../7zDec.c\r
+       $(CXX) $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT ../../7zDec.c\r
+\r
+7zIn.o: ../../7zIn.c\r
+       $(CXX) $(CFLAGS) ../../7zIn.c\r
+\r
+CpuArch.o: ../../CpuArch.c\r
+       $(CXX) $(CFLAGS) ../../CpuArch.c\r
+\r
+LzmaDec.o: ../../LzmaDec.c\r
+       $(CXX) $(CFLAGS) ../../LzmaDec.c\r
+\r
+Lzma2Dec.o: ../../Lzma2Dec.c\r
+       $(CXX) $(CFLAGS) ../../Lzma2Dec.c\r
+\r
+Bra.o: ../../Bra.c\r
+       $(CXX) $(CFLAGS) ../../Bra.c\r
+\r
+Bra86.o: ../../Bra86.c\r
+       $(CXX) $(CFLAGS) ../../Bra86.c\r
+\r
+Bcj2.o: ../../Bcj2.c\r
+       $(CXX) $(CFLAGS) ../../Bcj2.c\r
+\r
+Ppmd7.o: ../../Ppmd7.c\r
+       $(CXX) $(CFLAGS) ../../Ppmd7.c\r
+\r
+Ppmd7Dec.o: ../../Ppmd7Dec.c\r
+       $(CXX) $(CFLAGS) ../../Ppmd7Dec.c\r
+\r
+7zFile.o: ../../7zFile.c\r
+       $(CXX) $(CFLAGS) ../../7zFile.c\r
+\r
+7zStream.o: ../../7zStream.c\r
+       $(CXX) $(CFLAGS) ../../7zStream.c\r
+\r
+clean:\r
+       -$(RM) $(PROG) $(OBJS)\r
+\r
diff --git a/C/Util/Lzma/LzmaUtil.c b/C/Util/Lzma/LzmaUtil.c
new file mode 100755 (executable)
index 0000000..f8de4a2
--- /dev/null
@@ -0,0 +1,254 @@
+/* LzmaUtil.c -- Test application for LZMA compression\r
+2010-09-20 : Igor Pavlov : Public domain */\r
+\r
+#define _CRT_SECURE_NO_WARNINGS\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#include "../../Alloc.h"\r
+#include "../../7zFile.h"\r
+#include "../../7zVersion.h"\r
+#include "../../LzmaDec.h"\r
+#include "../../LzmaEnc.h"\r
+\r
+const char *kCantReadMessage = "Can not read input file";\r
+const char *kCantWriteMessage = "Can not write output file";\r
+const char *kCantAllocateMessage = "Can not allocate memory";\r
+const char *kDataErrorMessage = "Data error";\r
+\r
+static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }\r
+static void SzFree(void *p, void *address) { p = p; MyFree(address); }\r
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };\r
+\r
+void PrintHelp(char *buffer)\r
+{\r
+  strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n"\r
+      "\nUsage:  lzma <e|d> inputFile outputFile\n"\r
+             "  e: encode file\n"\r
+             "  d: decode file\n");\r
+}\r
+\r
+int PrintError(char *buffer, const char *message)\r
+{\r
+  strcat(buffer, "\nError: ");\r
+  strcat(buffer, message);\r
+  strcat(buffer, "\n");\r
+  return 1;\r
+}\r
+\r
+int PrintErrorNumber(char *buffer, SRes val)\r
+{\r
+  sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);\r
+  return 1;\r
+}\r
+\r
+int PrintUserError(char *buffer)\r
+{\r
+  return PrintError(buffer, "Incorrect command");\r
+}\r
+\r
+#define IN_BUF_SIZE (1 << 16)\r
+#define OUT_BUF_SIZE (1 << 16)\r
+\r
+static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream,\r
+    UInt64 unpackSize)\r
+{\r
+  int thereIsSize = (unpackSize != (UInt64)(Int64)-1);\r
+  Byte inBuf[IN_BUF_SIZE];\r
+  Byte outBuf[OUT_BUF_SIZE];\r
+  size_t inPos = 0, inSize = 0, outPos = 0;\r
+  LzmaDec_Init(state);\r
+  for (;;)\r
+  {\r
+    if (inPos == inSize)\r
+    {\r
+      inSize = IN_BUF_SIZE;\r
+      RINOK(inStream->Read(inStream, inBuf, &inSize));\r
+      inPos = 0;\r
+    }\r
+    {\r
+      SRes res;\r
+      SizeT inProcessed = inSize - inPos;\r
+      SizeT outProcessed = OUT_BUF_SIZE - outPos;\r
+      ELzmaFinishMode finishMode = LZMA_FINISH_ANY;\r
+      ELzmaStatus status;\r
+      if (thereIsSize && outProcessed > unpackSize)\r
+      {\r
+        outProcessed = (SizeT)unpackSize;\r
+        finishMode = LZMA_FINISH_END;\r
+      }\r
+      \r
+      res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed,\r
+        inBuf + inPos, &inProcessed, finishMode, &status);\r
+      inPos += inProcessed;\r
+      outPos += outProcessed;\r
+      unpackSize -= outProcessed;\r
+      \r
+      if (outStream)\r
+        if (outStream->Write(outStream, outBuf, outPos) != outPos)\r
+          return SZ_ERROR_WRITE;\r
+        \r
+      outPos = 0;\r
+      \r
+      if (res != SZ_OK || thereIsSize && unpackSize == 0)\r
+        return res;\r
+      \r
+      if (inProcessed == 0 && outProcessed == 0)\r
+      {\r
+        if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)\r
+          return SZ_ERROR_DATA;\r
+        return res;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream)\r
+{\r
+  UInt64 unpackSize;\r
+  int i;\r
+  SRes res = 0;\r
+\r
+  CLzmaDec state;\r
+\r
+  /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */\r
+  unsigned char header[LZMA_PROPS_SIZE + 8];\r
+\r
+  /* Read and parse header */\r
+\r
+  RINOK(SeqInStream_Read(inStream, header, sizeof(header)));\r
+\r
+  unpackSize = 0;\r
+  for (i = 0; i < 8; i++)\r
+    unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8);\r
+\r
+  LzmaDec_Construct(&state);\r
+  RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc));\r
+  res = Decode2(&state, outStream, inStream, unpackSize);\r
+  LzmaDec_Free(&state, &g_Alloc);\r
+  return res;\r
+}\r
+\r
+static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs)\r
+{\r
+  CLzmaEncHandle enc;\r
+  SRes res;\r
+  CLzmaEncProps props;\r
+\r
+  rs = rs;\r
+\r
+  enc = LzmaEnc_Create(&g_Alloc);\r
+  if (enc == 0)\r
+    return SZ_ERROR_MEM;\r
+\r
+  LzmaEncProps_Init(&props);\r
+  res = LzmaEnc_SetProps(enc, &props);\r
+\r
+  if (res == SZ_OK)\r
+  {\r
+    Byte header[LZMA_PROPS_SIZE + 8];\r
+    size_t headerSize = LZMA_PROPS_SIZE;\r
+    int i;\r
+\r
+    res = LzmaEnc_WriteProperties(enc, header, &headerSize);\r
+    for (i = 0; i < 8; i++)\r
+      header[headerSize++] = (Byte)(fileSize >> (8 * i));\r
+    if (outStream->Write(outStream, header, headerSize) != headerSize)\r
+      res = SZ_ERROR_WRITE;\r
+    else\r
+    {\r
+      if (res == SZ_OK)\r
+        res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc);\r
+    }\r
+  }\r
+  LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);\r
+  return res;\r
+}\r
+\r
+int main2(int numArgs, const char *args[], char *rs)\r
+{\r
+  CFileSeqInStream inStream;\r
+  CFileOutStream outStream;\r
+  char c;\r
+  int res;\r
+  int encodeMode;\r
+  Bool useOutFile = False;\r
+\r
+  FileSeqInStream_CreateVTable(&inStream);\r
+  File_Construct(&inStream.file);\r
+\r
+  FileOutStream_CreateVTable(&outStream);\r
+  File_Construct(&outStream.file);\r
+\r
+  if (numArgs == 1)\r
+  {\r
+    PrintHelp(rs);\r
+    return 0;\r
+  }\r
+\r
+  if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1)\r
+    return PrintUserError(rs);\r
+\r
+  c = args[1][0];\r
+  encodeMode = (c == 'e' || c == 'E');\r
+  if (!encodeMode && c != 'd' && c != 'D')\r
+    return PrintUserError(rs);\r
+\r
+  {\r
+    size_t t4 = sizeof(UInt32);\r
+    size_t t8 = sizeof(UInt64);\r
+    if (t4 != 4 || t8 != 8)\r
+      return PrintError(rs, "Incorrect UInt32 or UInt64");\r
+  }\r
+\r
+  if (InFile_Open(&inStream.file, args[2]) != 0)\r
+    return PrintError(rs, "Can not open input file");\r
+\r
+  if (numArgs > 3)\r
+  {\r
+    useOutFile = True;\r
+    if (OutFile_Open(&outStream.file, args[3]) != 0)\r
+      return PrintError(rs, "Can not open output file");\r
+  }\r
+  else if (encodeMode)\r
+    PrintUserError(rs);\r
+\r
+  if (encodeMode)\r
+  {\r
+    UInt64 fileSize;\r
+    File_GetLength(&inStream.file, &fileSize);\r
+    res = Encode(&outStream.s, &inStream.s, fileSize, rs);\r
+  }\r
+  else\r
+  {\r
+    res = Decode(&outStream.s, useOutFile ? &inStream.s : NULL);\r
+  }\r
+\r
+  if (useOutFile)\r
+    File_Close(&outStream.file);\r
+  File_Close(&inStream.file);\r
+\r
+  if (res != SZ_OK)\r
+  {\r
+    if (res == SZ_ERROR_MEM)\r
+      return PrintError(rs, kCantAllocateMessage);\r
+    else if (res == SZ_ERROR_DATA)\r
+      return PrintError(rs, kDataErrorMessage);\r
+    else if (res == SZ_ERROR_WRITE)\r
+      return PrintError(rs, kCantWriteMessage);\r
+    else if (res == SZ_ERROR_READ)\r
+      return PrintError(rs, kCantReadMessage);\r
+    return PrintErrorNumber(rs, res);\r
+  }\r
+  return 0;\r
+}\r
+\r
+int MY_CDECL main(int numArgs, const char *args[])\r
+{\r
+  char rs[800] = { 0 };\r
+  int res = main2(numArgs, args, rs);\r
+  fputs(rs, stdout);\r
+  return res;\r
+}\r
diff --git a/C/Util/Lzma/LzmaUtil.dsp b/C/Util/Lzma/LzmaUtil.dsp
new file mode 100755 (executable)
index 0000000..4815511
--- /dev/null
@@ -0,0 +1,168 @@
+# Microsoft Developer Studio Project File - Name="LzmaUtil" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=LzmaUtil - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "LzmaUtil.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "LzmaUtil.mak" CFG="LzmaUtil - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "LzmaUtil - Win32 Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "LzmaUtil - Win32 Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "LzmaUtil - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
+# ADD CPP /nologo /MT /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c\r
+# SUBTRACT CPP /YX\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\7lzma.exe"\r
+\r
+!ELSEIF  "$(CFG)" == "LzmaUtil - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c\r
+# SUBTRACT CPP /YX\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x419 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\7lzma.exe" /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "LzmaUtil - Win32 Release"\r
+# Name "LzmaUtil - Win32 Debug"\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zFile.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zFile.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zStream.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zVersion.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Alloc.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Alloc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\CpuArch.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzFind.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzFind.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzFindMt.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzFindMt.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzHash.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzmaDec.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzmaDec.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzmaEnc.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzmaEnc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\LzmaUtil.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Threads.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Threads.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Types.h\r
+# End Source File\r
+# End Target\r
+# End Project\r
diff --git a/C/Util/Lzma/LzmaUtil.dsw b/C/Util/Lzma/LzmaUtil.dsw
new file mode 100755 (executable)
index 0000000..f435487
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "LzmaUtil"=.\LzmaUtil.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/C/Util/Lzma/makefile b/C/Util/Lzma/makefile
new file mode 100755 (executable)
index 0000000..e99e098
--- /dev/null
@@ -0,0 +1,28 @@
+MY_STATIC_LINK=1\r
+PROG = LZMAc.exe\r
+\r
+CFLAGS = $(CFLAGS) \\r
+\r
+LIB_OBJS = \\r
+  $O\LzmaUtil.obj \\r
+\r
+C_OBJS = \\r
+  $O\Alloc.obj \\r
+  $O\LzFind.obj \\r
+  $O\LzFindMt.obj \\r
+  $O\LzmaDec.obj \\r
+  $O\LzmaEnc.obj \\r
+  $O\7zFile.obj \\r
+  $O\7zStream.obj \\r
+  $O\Threads.obj \\r
+\r
+OBJS = \\r
+  $(LIB_OBJS) \\r
+  $(C_OBJS) \\r
+\r
+!include "../../../CPP/Build.mak"\r
+\r
+$(LIB_OBJS): $(*B).c\r
+       $(COMPL_O2)\r
+$(C_OBJS): ../../$(*B).c\r
+       $(COMPL_O2)\r
diff --git a/C/Util/Lzma/makefile.gcc b/C/Util/Lzma/makefile.gcc
new file mode 100755 (executable)
index 0000000..12a72bb
--- /dev/null
@@ -0,0 +1,44 @@
+PROG = lzma\r
+CXX = g++\r
+LIB =\r
+RM = rm -f\r
+CFLAGS = -c -O2 -Wall -D_7ZIP_ST\r
+\r
+OBJS = \\r
+  LzmaUtil.o \\r
+  Alloc.o \\r
+  LzFind.o \\r
+  LzmaDec.o \\r
+  LzmaEnc.o \\r
+  7zFile.o \\r
+  7zStream.o \\r
+\r
+\r
+all: $(PROG)\r
+\r
+$(PROG): $(OBJS)\r
+       $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2)\r
+\r
+LzmaUtil.o: LzmaUtil.c\r
+       $(CXX) $(CFLAGS) LzmaUtil.c\r
+\r
+Alloc.o: ../../Alloc.c\r
+       $(CXX) $(CFLAGS) ../../Alloc.c\r
+\r
+LzFind.o: ../../LzFind.c\r
+       $(CXX) $(CFLAGS) ../../LzFind.c\r
+\r
+LzmaDec.o: ../../LzmaDec.c\r
+       $(CXX) $(CFLAGS) ../../LzmaDec.c\r
+\r
+LzmaEnc.o: ../../LzmaEnc.c\r
+       $(CXX) $(CFLAGS) ../../LzmaEnc.c\r
+\r
+7zFile.o: ../../7zFile.c\r
+       $(CXX) $(CFLAGS) ../../7zFile.c\r
+\r
+7zStream.o: ../../7zStream.c\r
+       $(CXX) $(CFLAGS) ../../7zStream.c\r
+\r
+clean:\r
+       -$(RM) $(PROG) $(OBJS)\r
diff --git a/C/Util/LzmaLib/LzmaLib.def b/C/Util/LzmaLib/LzmaLib.def
new file mode 100755 (executable)
index 0000000..43b9597
--- /dev/null
@@ -0,0 +1,4 @@
+EXPORTS\r
+  LzmaCompress\r
+  LzmaUncompress\r
+\r
diff --git a/C/Util/LzmaLib/LzmaLib.dsp b/C/Util/LzmaLib/LzmaLib.dsp
new file mode 100755 (executable)
index 0000000..bf52b63
--- /dev/null
@@ -0,0 +1,178 @@
+# Microsoft Developer Studio Project File - Name="LzmaLib" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
+\r
+CFG=LzmaLib - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "LzmaLib.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "LzmaLib.mak" CFG="LzmaLib - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "LzmaLib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE "LzmaLib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+MTL=midl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "LzmaLib - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /c\r
+# ADD CPP /nologo /Gr /MT /W3 /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /FD /c\r
+# SUBTRACT CPP /YX\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Util\LZMA.dll" /opt:NOWIN98\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "LzmaLib - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /GZ /c\r
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /GZ /c\r
+# SUBTRACT CPP /YX\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x419 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Util\LZMA.dll" /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "LzmaLib - Win32 Release"\r
+# Name "LzmaLib - Win32 Debug"\r
+# Begin Group "Spec"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\LzmaLib.def\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\LzmaLibExports.c\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Alloc.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Alloc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\IStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzFind.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzFind.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzFindMt.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzFindMt.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzHash.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzmaDec.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzmaDec.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzmaEnc.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzmaEnc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzmaLib.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzmaLib.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\resource.rc\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Threads.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Threads.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Types.h\r
+# End Source File\r
+# End Target\r
+# End Project\r
diff --git a/C/Util/LzmaLib/LzmaLib.dsw b/C/Util/LzmaLib/LzmaLib.dsw
new file mode 100755 (executable)
index 0000000..f6c5559
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "LzmaLib"=.\LzmaLib.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/C/Util/LzmaLib/LzmaLibExports.c b/C/Util/LzmaLib/LzmaLibExports.c
new file mode 100755 (executable)
index 0000000..7434536
--- /dev/null
@@ -0,0 +1,12 @@
+/* LzmaLibExports.c -- LZMA library DLL Entry point\r
+2008-10-04 : Igor Pavlov : Public domain */\r
+\r
+#include <windows.h>\r
+\r
+BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)\r
+{\r
+  hInstance = hInstance;\r
+  dwReason = dwReason;\r
+  lpReserved = lpReserved;\r
+  return TRUE;\r
+}\r
diff --git a/C/Util/LzmaLib/makefile b/C/Util/LzmaLib/makefile
new file mode 100755 (executable)
index 0000000..e0f3114
--- /dev/null
@@ -0,0 +1,34 @@
+MY_STATIC_LINK=1\r
+SLIB = sLZMA.lib\r
+PROG = LZMA.dll\r
+SLIBPATH = $O\$(SLIB)\r
+\r
+DEF_FILE = LzmaLib.def\r
+CFLAGS = $(CFLAGS) \\r
+\r
+LIB_OBJS = \\r
+  $O\LzmaLibExports.obj \\r
+\r
+C_OBJS = \\r
+  $O\Alloc.obj \\r
+  $O\LzFind.obj \\r
+  $O\LzFindMt.obj \\r
+  $O\LzmaDec.obj \\r
+  $O\LzmaEnc.obj \\r
+  $O\LzmaLib.obj \\r
+  $O\Threads.obj \\r
+\r
+OBJS = \\r
+  $(LIB_OBJS) \\r
+  $(C_OBJS) \\r
+  $O\resource.res\r
+\r
+!include "../../../CPP/Build.mak"\r
+\r
+$(SLIBPATH): $O $(OBJS)\r
+       lib -out:$(SLIBPATH) $(OBJS) $(LIBS)\r
+\r
+$(LIB_OBJS): $(*B).c\r
+       $(COMPL_O2)\r
+$(C_OBJS): ../../$(*B).c\r
+       $(COMPL_O2)\r
diff --git a/C/Util/LzmaLib/resource.rc b/C/Util/LzmaLib/resource.rc
new file mode 100755 (executable)
index 0000000..cb62ed9
--- /dev/null
@@ -0,0 +1,4 @@
+#include "../../../CPP/7zip/MyVersionInfo.rc"\r
+\r
+MY_VERSION_INFO_DLL("LZMA library", "LZMA")\r
+\r
diff --git a/C/Util/SfxSetup/SfxSetup.c b/C/Util/SfxSetup/SfxSetup.c
new file mode 100755 (executable)
index 0000000..d4eb5c4
--- /dev/null
@@ -0,0 +1,592 @@
+/* SfxSetup.c - 7z SFX Setup\r
+2010-11-11 : Igor Pavlov : Public domain */\r
+\r
+#ifndef UNICODE\r
+#define UNICODE\r
+#endif\r
+\r
+#ifndef _UNICODE\r
+#define _UNICODE\r
+#endif\r
+\r
+#ifdef _CONSOLE\r
+#include <stdio.h>\r
+#endif\r
+\r
+#include "../../7z.h"\r
+#include "../../7zAlloc.h"\r
+#include "../../7zCrc.h"\r
+#include "../../7zFile.h"\r
+#include "../../CpuArch.h"\r
+\r
+#define k_EXE_ExtIndex 1\r
+\r
+static const char *kExts[] =\r
+{\r
+  "bat",\r
+  "exe",\r
+  "inf",\r
+  "msi",\r
+  #ifdef UNDER_CE\r
+  "cab",\r
+  #endif\r
+  "html",\r
+  "htm"\r
+};\r
+\r
+static const char *kNames[] =\r
+{\r
+  "setup",\r
+  "install",\r
+  "run",\r
+  "start"\r
+};\r
+\r
+static unsigned FindExt(const wchar_t *s, unsigned *extLen)\r
+{\r
+  unsigned len = (unsigned)wcslen(s);\r
+  unsigned i;\r
+  for (i = len; i > 0; i--)\r
+  {\r
+    if (s[i - 1] == '.')\r
+    {\r
+      *extLen = len - i;\r
+      return i - 1;\r
+    }\r
+  }\r
+  *extLen = 0;\r
+  return len;\r
+}\r
+\r
+#define MAKE_CHAR_UPPER(c) ((((c) >= 'a' && (c) <= 'z') ? (c) -= 0x20 : (c)))\r
+\r
+static unsigned FindItem(const char **items, unsigned num, const wchar_t *s, unsigned len)\r
+{\r
+  unsigned i;\r
+  for (i = 0; i < num; i++)\r
+  {\r
+    const char *item = items[i];\r
+    unsigned itemLen = (unsigned)strlen(item);\r
+    unsigned j;\r
+    if (len != itemLen)\r
+      continue;\r
+    for (j = 0; j < len; j++)\r
+    {\r
+      unsigned c = item[j];\r
+      if (c != s[j] && MAKE_CHAR_UPPER(c) != s[j])\r
+        break;\r
+    }\r
+    if (j == len)\r
+      return i;\r
+  }\r
+  return i;\r
+}\r
+\r
+#ifdef _CONSOLE\r
+static BOOL WINAPI HandlerRoutine(DWORD ctrlType)\r
+{\r
+  ctrlType = ctrlType;\r
+  return TRUE;\r
+}\r
+#endif\r
+\r
+static void PrintErrorMessage(const char *message)\r
+{\r
+  #ifdef _CONSOLE\r
+  printf("\n7-Zip Error: %s\n", message);\r
+  #else\r
+  #ifdef UNDER_CE\r
+  WCHAR messageW[256 + 4];\r
+  unsigned i;\r
+  for (i = 0; i < 256 && message[i] != 0; i++)\r
+    messageW[i] = message[i];\r
+  messageW[i] = 0;\r
+  MessageBoxW(0, messageW, L"7-Zip Error", MB_ICONERROR);\r
+  #else\r
+  MessageBoxA(0, message, "7-Zip Error", MB_ICONERROR);\r
+  #endif\r
+  #endif\r
+}\r
+\r
+static WRes MyCreateDir(const WCHAR *name)\r
+{\r
+  return CreateDirectoryW(name, NULL) ? 0 : GetLastError();\r
+}\r
+\r
+#ifdef UNDER_CE\r
+#define kBufferSize (1 << 13)\r
+#else\r
+#define kBufferSize (1 << 15)\r
+#endif\r
+\r
+#define kSignatureSearchLimit (1 << 22)\r
+\r
+static Bool FindSignature(CSzFile *stream, UInt64 *resPos)\r
+{\r
+  Byte buf[kBufferSize];\r
+  size_t numPrevBytes = 0;\r
+  *resPos = 0;\r
+  for (;;)\r
+  {\r
+    size_t numTests, pos;\r
+    if (*resPos > kSignatureSearchLimit)\r
+      return False;\r
+    \r
+    do\r
+    {\r
+      size_t processed = kBufferSize - numPrevBytes;\r
+      if (File_Read(stream, buf + numPrevBytes, &processed) != 0)\r
+        return False;\r
+      if (processed == 0)\r
+        return False;\r
+      numPrevBytes += processed;\r
+    }\r
+    while (numPrevBytes <= k7zStartHeaderSize);\r
+    \r
+    numTests = numPrevBytes - k7zStartHeaderSize;\r
+    for (pos = 0; pos < numTests; pos++)\r
+    {\r
+      for (; buf[pos] != '7' && pos < numTests; pos++);\r
+      if (pos == numTests)\r
+        break;\r
+      if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0)\r
+        if (CrcCalc(buf + pos + 12, 20) == GetUi32(buf + pos + 8))\r
+        {\r
+          *resPos += pos;\r
+          return True;\r
+        }\r
+    }\r
+    *resPos += numTests;\r
+    numPrevBytes -= numTests;\r
+    memmove(buf, buf + numTests, numPrevBytes);\r
+  }\r
+}\r
+\r
+static Bool DoesFileOrDirExist(const WCHAR *path)\r
+{\r
+  WIN32_FIND_DATAW fd;\r
+  HANDLE handle;\r
+  handle = FindFirstFileW(path, &fd);\r
+  if (handle == INVALID_HANDLE_VALUE)\r
+    return False;\r
+  FindClose(handle);\r
+  return True;\r
+}\r
+\r
+static WRes RemoveDirWithSubItems(WCHAR *path)\r
+{\r
+  WIN32_FIND_DATAW fd;\r
+  HANDLE handle;\r
+  WRes res = 0;\r
+  size_t len = wcslen(path);\r
+  wcscpy(path + len, L"*");\r
+  handle = FindFirstFileW(path, &fd);\r
+  path[len] = L'\0';\r
+  if (handle == INVALID_HANDLE_VALUE)\r
+    return GetLastError();\r
+  for (;;)\r
+  {\r
+    if (wcscmp(fd.cFileName, L".") != 0 &&\r
+        wcscmp(fd.cFileName, L"..") != 0)\r
+    {\r
+      wcscpy(path + len, fd.cFileName);\r
+      if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)\r
+      {\r
+        wcscat(path, L"\\");\r
+        res = RemoveDirWithSubItems(path);\r
+      }\r
+      else\r
+      {\r
+        SetFileAttributesW(path, 0);\r
+        if (DeleteFileW(path) == 0)\r
+          res = GetLastError();\r
+      }\r
+      if (res != 0)\r
+        break;\r
+    }\r
+    if (!FindNextFileW(handle, &fd))\r
+    {\r
+      res = GetLastError();\r
+      if (res == ERROR_NO_MORE_FILES)\r
+        res = 0;\r
+      break;\r
+    }\r
+  }\r
+  path[len] = L'\0';\r
+  FindClose(handle);\r
+  if (res == 0)\r
+  {\r
+    if (!RemoveDirectoryW(path))\r
+      res = GetLastError();\r
+  }\r
+  return res;\r
+}\r
+\r
+#ifdef _CONSOLE\r
+int MY_CDECL main()\r
+#else\r
+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,\r
+  #ifdef UNDER_CE\r
+  LPWSTR\r
+  #else\r
+  LPSTR\r
+  #endif\r
+  lpCmdLine, int nCmdShow)\r
+#endif\r
+{\r
+  CFileInStream archiveStream;\r
+  CLookToRead lookStream;\r
+  CSzArEx db;\r
+  SRes res = SZ_OK;\r
+  ISzAlloc allocImp;\r
+  ISzAlloc allocTempImp;\r
+  WCHAR sfxPath[MAX_PATH + 2];\r
+  WCHAR path[MAX_PATH * 3 + 2];\r
+  size_t pathLen;\r
+  DWORD winRes;\r
+  const wchar_t *cmdLineParams;\r
+  const char *errorMessage = NULL;\r
+  Bool useShellExecute = True;\r
+\r
+  #ifdef _CONSOLE\r
+  SetConsoleCtrlHandler(HandlerRoutine, TRUE);\r
+  #else\r
+  hInstance = hInstance;\r
+  hPrevInstance = hPrevInstance;\r
+  lpCmdLine = lpCmdLine;\r
+  nCmdShow = nCmdShow;\r
+  #endif\r
+\r
+  CrcGenerateTable();\r
+\r
+  allocImp.Alloc = SzAlloc;\r
+  allocImp.Free = SzFree;\r
+\r
+  allocTempImp.Alloc = SzAllocTemp;\r
+  allocTempImp.Free = SzFreeTemp;\r
+\r
+  FileInStream_CreateVTable(&archiveStream);\r
+  LookToRead_CreateVTable(&lookStream, False);\r
\r
+  winRes = GetModuleFileNameW(NULL, sfxPath, MAX_PATH);\r
+  if (winRes == 0 || winRes > MAX_PATH)\r
+    return 1;\r
+  {\r
+    cmdLineParams = GetCommandLineW();\r
+    #ifndef UNDER_CE\r
+    {\r
+      Bool quoteMode = False;\r
+      for (;; cmdLineParams++)\r
+      {\r
+        wchar_t c = *cmdLineParams;\r
+        if (c == L'\"')\r
+          quoteMode = !quoteMode;\r
+        else if (c == 0 || (c == L' ' && !quoteMode))\r
+          break;\r
+      }\r
+    }\r
+    #endif\r
+  }\r
+\r
+  {\r
+    unsigned i;\r
+    DWORD d;\r
+    winRes = GetTempPathW(MAX_PATH, path);\r
+    if (winRes == 0 || winRes > MAX_PATH)\r
+      return 1;\r
+    pathLen = wcslen(path);\r
+    d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId();\r
+    for (i = 0;; i++, d += GetTickCount())\r
+    {\r
+      if (i >= 100)\r
+      {\r
+        res = SZ_ERROR_FAIL;\r
+        break;\r
+      }\r
+      wcscpy(path + pathLen, L"7z");\r
+\r
+      {\r
+        wchar_t *s = path + wcslen(path);\r
+        UInt32 value = d;\r
+        unsigned k;\r
+        for (k = 0; k < 8; k++)\r
+        {\r
+          unsigned t = value & 0xF;\r
+          value >>= 4;\r
+          s[7 - k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));\r
+        }\r
+        s[k] = '\0';\r
+      }\r
+\r
+      if (DoesFileOrDirExist(path))\r
+        continue;\r
+      if (CreateDirectoryW(path, NULL))\r
+      {\r
+        wcscat(path, L"\\");\r
+        pathLen = wcslen(path);\r
+        break;\r
+      }\r
+      if (GetLastError() != ERROR_ALREADY_EXISTS)\r
+      {\r
+        res = SZ_ERROR_FAIL;\r
+        break;\r
+      }\r
+    }\r
+    if (res != SZ_OK)\r
+      errorMessage = "Can't create temp folder";\r
+  }\r
+\r
+  if (res != SZ_OK)\r
+  {\r
+    if (!errorMessage)\r
+      errorMessage = "Error";\r
+    PrintErrorMessage(errorMessage);\r
+    return 1;\r
+  }\r
+\r
+  if (InFile_OpenW(&archiveStream.file, sfxPath) != 0)\r
+  {\r
+    errorMessage = "can not open input file";\r
+    res = SZ_ERROR_FAIL;\r
+  }\r
+  else\r
+  {\r
+    UInt64 pos = 0;\r
+    if (!FindSignature(&archiveStream.file, &pos))\r
+      res = SZ_ERROR_FAIL;\r
+    else if (File_Seek(&archiveStream.file, (Int64 *)&pos, SZ_SEEK_SET) != 0)\r
+      res = SZ_ERROR_FAIL;\r
+    if (res != 0)\r
+      errorMessage = "Can't find 7z archive";\r
+  }\r
+\r
+  if (res == SZ_OK)\r
+  {\r
+    lookStream.realStream = &archiveStream.s;\r
+    LookToRead_Init(&lookStream);\r
+  }\r
+\r
+  SzArEx_Init(&db);\r
+  if (res == SZ_OK)\r
+  {\r
+    res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);\r
+  }\r
+  if (res == SZ_OK)\r
+  {\r
+    UInt32 executeFileIndex = (UInt32)(Int32)-1;\r
+    UInt32 minPrice = 1 << 30;\r
+    UInt32 i;\r
+    UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */\r
+    Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */\r
+    size_t outBufferSize = 0;  /* it can have any value before first call (if outBuffer = 0) */\r
+    \r
+    for (i = 0; i < db.db.NumFiles; i++)\r
+    {\r
+      size_t offset = 0;\r
+      size_t outSizeProcessed = 0;\r
+      const CSzFileItem *f = db.db.Files + i;\r
+      size_t len;\r
+      WCHAR *temp;\r
+      len = SzArEx_GetFileNameUtf16(&db, i, NULL);\r
+      \r
+      if (len >= MAX_PATH)\r
+      {\r
+        res = SZ_ERROR_FAIL;\r
+        break;\r
+      }\r
+      \r
+      temp = path + pathLen;\r
+      \r
+      SzArEx_GetFileNameUtf16(&db, i, temp);\r
+      {\r
+        res = SzArEx_Extract(&db, &lookStream.s, i,\r
+          &blockIndex, &outBuffer, &outBufferSize,\r
+          &offset, &outSizeProcessed,\r
+          &allocImp, &allocTempImp);\r
+        if (res != SZ_OK)\r
+          break;\r
+      }\r
+      {\r
+        CSzFile outFile;\r
+        size_t processedSize;\r
+        size_t j;\r
+        size_t nameStartPos = 0;\r
+        for (j = 0; temp[j] != 0; j++)\r
+        {\r
+          if (temp[j] == '/')\r
+          {\r
+            temp[j] = 0;\r
+            MyCreateDir(path);\r
+            temp[j] = CHAR_PATH_SEPARATOR;\r
+            nameStartPos = j + 1;\r
+          }\r
+        }\r
+\r
+        if (f->IsDir)\r
+        {\r
+          MyCreateDir(path);\r
+          continue;\r
+        }\r
+        else\r
+        {\r
+          unsigned extLen;\r
+          const WCHAR *name = temp + nameStartPos;\r
+          unsigned len = (unsigned)wcslen(name);\r
+          unsigned nameLen = FindExt(temp + nameStartPos, &extLen);\r
+          unsigned extPrice = FindItem(kExts, sizeof(kExts) / sizeof(kExts[0]), name + len - extLen, extLen);\r
+          unsigned namePrice = FindItem(kNames, sizeof(kNames) / sizeof(kNames[0]), name, nameLen);\r
+\r
+          unsigned price = namePrice + extPrice * 64 + (nameStartPos == 0 ? 0 : (1 << 12));\r
+          if (minPrice > price)\r
+          {\r
+            minPrice = price;\r
+            executeFileIndex = i;\r
+            useShellExecute = (extPrice != k_EXE_ExtIndex);\r
+          }\r
+         \r
+          if (DoesFileOrDirExist(path))\r
+          {\r
+            errorMessage = "Duplicate file";\r
+            res = SZ_ERROR_FAIL;\r
+            break;\r
+          }\r
+          if (OutFile_OpenW(&outFile, path))\r
+          {\r
+            errorMessage = "Can't open output file";\r
+            res = SZ_ERROR_FAIL;\r
+            break;\r
+          }\r
+        }\r
+        processedSize = outSizeProcessed;\r
+        if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed)\r
+        {\r
+          errorMessage = "Can't write output file";\r
+          res = SZ_ERROR_FAIL;\r
+        }\r
+        \r
+        #ifdef USE_WINDOWS_FILE\r
+        if (f->MTimeDefined)\r
+        {\r
+          FILETIME mTime;\r
+          mTime.dwLowDateTime = f->MTime.Low;\r
+          mTime.dwHighDateTime = f->MTime.High;\r
+          SetFileTime(outFile.handle, NULL, NULL, &mTime);\r
+        }\r
+        #endif\r
+        \r
+        {\r
+          SRes res2 = File_Close(&outFile);\r
+          if (res != SZ_OK)\r
+            break;\r
+          if (res2 != SZ_OK)\r
+          {\r
+            res = res2;\r
+            break;\r
+          }\r
+        }\r
+        #ifdef USE_WINDOWS_FILE\r
+        if (f->AttribDefined)\r
+          SetFileAttributesW(path, f->Attrib);\r
+        #endif\r
+      }\r
+    }\r
+\r
+    if (res == SZ_OK)\r
+    {\r
+      if (executeFileIndex == (UInt32)(Int32)-1)\r
+      {\r
+        errorMessage = "There is no file to execute";\r
+        res = SZ_ERROR_FAIL;\r
+      }\r
+      else\r
+      {\r
+        WCHAR *temp = path + pathLen;\r
+        UInt32 j;\r
+        SzArEx_GetFileNameUtf16(&db, executeFileIndex, temp);\r
+        for (j = 0; temp[j] != 0; j++)\r
+          if (temp[j] == '/')\r
+            temp[j] = CHAR_PATH_SEPARATOR;\r
+      }\r
+    }\r
+    IAlloc_Free(&allocImp, outBuffer);\r
+  }\r
+  SzArEx_Free(&db, &allocImp);\r
+\r
+  File_Close(&archiveStream.file);\r
+\r
+  if (res == SZ_OK)\r
+  {\r
+    HANDLE hProcess = 0;\r
+    if (useShellExecute)\r
+    {\r
+      SHELLEXECUTEINFO ei;\r
+      UINT32 executeRes;\r
+      BOOL success;\r
+      \r
+      memset(&ei, 0, sizeof(ei));\r
+      ei.cbSize = sizeof(ei);\r
+      ei.lpFile = path;\r
+      ei.fMask = SEE_MASK_NOCLOSEPROCESS\r
+          #ifndef UNDER_CE\r
+          | SEE_MASK_FLAG_DDEWAIT\r
+          #endif\r
+          /* | SEE_MASK_NO_CONSOLE */\r
+          ;\r
+      if (wcslen(cmdLineParams) != 0)\r
+        ei.lpParameters = cmdLineParams;\r
+      ei.nShow = SW_SHOWNORMAL; /* SW_HIDE; */\r
+      success = ShellExecuteEx(&ei);\r
+      executeRes = (UINT32)(UINT_PTR)ei.hInstApp;\r
+      if (!success || (executeRes <= 32 && executeRes != 0))  /* executeRes = 0 in Windows CE */\r
+        res = SZ_ERROR_FAIL;\r
+      else\r
+        hProcess = ei.hProcess;\r
+    }\r
+    else\r
+    {\r
+      STARTUPINFOW si;\r
+      PROCESS_INFORMATION pi;\r
+      WCHAR cmdLine[MAX_PATH * 3];\r
+\r
+      wcscpy(cmdLine, path);\r
+      wcscat(cmdLine, cmdLineParams);\r
+      memset(&si, 0, sizeof(si));\r
+      si.cb = sizeof(si);\r
+      if (CreateProcessW(NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) == 0)\r
+        res = SZ_ERROR_FAIL;\r
+      else\r
+      {\r
+        CloseHandle(pi.hThread);\r
+        hProcess = pi.hProcess;\r
+      }\r
+    }\r
+    if (hProcess != 0)\r
+    {\r
+      WaitForSingleObject(hProcess, INFINITE);\r
+      CloseHandle(hProcess);\r
+    }\r
+  }\r
+\r
+  path[pathLen] = L'\0';\r
+  RemoveDirWithSubItems(path);\r
+\r
+  if (res == SZ_OK)\r
+    return 0;\r
+  \r
+  {\r
+    if (res == SZ_ERROR_UNSUPPORTED)\r
+      errorMessage = "Decoder doesn't support this archive";\r
+    else if (res == SZ_ERROR_MEM)\r
+      errorMessage = "Can't allocate required memory";\r
+    else if (res == SZ_ERROR_CRC)\r
+      errorMessage = "CRC error";\r
+    else\r
+    {\r
+      if (!errorMessage)\r
+        errorMessage = "ERROR";\r
+    }\r
+    if (errorMessage)\r
+      PrintErrorMessage(errorMessage);\r
+  }\r
+  return 1;\r
+}\r
diff --git a/C/Util/SfxSetup/SfxSetup.dsp b/C/Util/SfxSetup/SfxSetup.dsp
new file mode 100755 (executable)
index 0000000..10814a5
--- /dev/null
@@ -0,0 +1,198 @@
+# Microsoft Developer Studio Project File - Name="SfxSetup" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Application" 0x0101\r
+\r
+CFG=SfxSetup - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "SfxSetup.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "SfxSetup.mak" CFG="SfxSetup - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "SfxSetup - Win32 Release" (based on "Win32 (x86) Application")\r
+!MESSAGE "SfxSetup - Win32 Debug" (based on "Win32 (x86) Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+MTL=midl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "SfxSetup - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c\r
+# ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /YX /FD /c\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386\r
+\r
+!ELSEIF  "$(CFG)" == "SfxSetup - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c\r
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /YX /FD /GZ /c\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x419 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "SfxSetup - Win32 Release"\r
+# Name "SfxSetup - Win32 Debug"\r
+# Begin Group "Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7z.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zAlloc.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zAlloc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zBuf.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zBuf.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zCrc.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zCrc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zCrcOpt.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zDec.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zFile.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zFile.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zIn.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\7zStream.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Bcj2.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Bcj2.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Bra.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Bra.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Bra86.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\CpuArch.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\CpuArch.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Lzma2Dec.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Lzma2Dec.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzmaDec.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\LzmaDec.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Types.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=.\SfxSetup.c\r
+# End Source File\r
+# End Target\r
+# End Project\r
diff --git a/C/Util/SfxSetup/SfxSetup.dsw b/C/Util/SfxSetup/SfxSetup.dsw
new file mode 100755 (executable)
index 0000000..128fcdd
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "SfxSetup"=.\SfxSetup.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/C/Util/SfxSetup/makefile b/C/Util/SfxSetup/makefile
new file mode 100755 (executable)
index 0000000..5d91be1
--- /dev/null
@@ -0,0 +1,35 @@
+PROG = 7zS2.sfx\r
+LIBS = $(LIBS) \r
+CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE\r
+\r
+C_OBJS = \\r
+  $O\7zAlloc.obj \\r
+  $O\7zBuf.obj \\r
+  $O\7zBuf2.obj \\r
+  $O\7zCrc.obj \\r
+  $O\7zCrcOpt.obj \\r
+  $O\7zFile.obj \\r
+  $O\7zDec.obj \\r
+  $O\7zIn.obj \\r
+  $O\7zStream.obj \\r
+  $O\Bcj2.obj \\r
+  $O\Bra.obj \\r
+  $O\Bra86.obj \\r
+  $O\CpuArch.obj \\r
+  $O\Lzma2Dec.obj \\r
+  $O\LzmaDec.obj \\r
+\r
+7Z_OBJS = \\r
+  $O\SfxSetup.obj \\r
+\r
+OBJS = \\r
+  $(7Z_OBJS) \\r
+  $(C_OBJS) \\r
+  $O\resource.res\r
+\r
+!include "../../../CPP/Build.mak"\r
+\r
+$(7Z_OBJS): $(*B).c\r
+       $(COMPL_O1)\r
+$(C_OBJS): ../../$(*B).c\r
+       $(COMPL_O1)\r
diff --git a/C/Util/SfxSetup/makefile_con b/C/Util/SfxSetup/makefile_con
new file mode 100755 (executable)
index 0000000..3fbb6b6
--- /dev/null
@@ -0,0 +1,35 @@
+PROG = 7zS2con.sfx\r
+LIBS = $(LIBS) \r
+CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE -D_CONSOLE\r
+\r
+C_OBJS = \\r
+  $O\7zAlloc.obj \\r
+  $O\7zBuf.obj \\r
+  $O\7zBuf2.obj \\r
+  $O\7zCrc.obj \\r
+  $O\7zCrcOpt.obj \\r
+  $O\7zFile.obj \\r
+  $O\7zDec.obj \\r
+  $O\7zIn.obj \\r
+  $O\7zStream.obj \\r
+  $O\Bcj2.obj \\r
+  $O\Bra.obj \\r
+  $O\Bra86.obj \\r
+  $O\CpuArch.obj \\r
+  $O\Lzma2Dec.obj \\r
+  $O\LzmaDec.obj \\r
+\r
+7Z_OBJS = \\r
+  $O\SfxSetup.obj \\r
+\r
+OBJS = \\r
+  $(7Z_OBJS) \\r
+  $(C_OBJS) \\r
+  $O\resource.res\r
+\r
+!include "../../../CPP/Build.mak"\r
+\r
+$(7Z_OBJS): $(*B).c\r
+       $(COMPL_O1)\r
+$(C_OBJS): ../../$(*B).c\r
+       $(COMPL_O1)\r
diff --git a/C/Util/SfxSetup/resource.rc b/C/Util/SfxSetup/resource.rc
new file mode 100755 (executable)
index 0000000..efff95e
--- /dev/null
@@ -0,0 +1,6 @@
+#include "../../../CPP/7zip/MyVersionInfo.rc"\r
+\r
+MY_VERSION_INFO_APP("7z Setup SFX small", "7zS2.sfx")\r
+\r
+1  ICON "setup.ico"\r
+\r
diff --git a/C/Util/SfxSetup/setup.ico b/C/Util/SfxSetup/setup.ico
new file mode 100755 (executable)
index 0000000..dbb6ca8
Binary files /dev/null and b/C/Util/SfxSetup/setup.ico differ
diff --git a/C/Xz.c b/C/Xz.c
new file mode 100755 (executable)
index 0000000..0bdf047
--- /dev/null
+++ b/C/Xz.c
@@ -0,0 +1,88 @@
+/* Xz.c - Xz\r
+2009-04-15 : Igor Pavlov : Public domain */\r
+\r
+#include "7zCrc.h"\r
+#include "CpuArch.h"\r
+#include "Xz.h"\r
+#include "XzCrc64.h"\r
+\r
+Byte XZ_SIG[XZ_SIG_SIZE] = { 0xFD, '7', 'z', 'X', 'Z', 0 };\r
+Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE] = { 'Y', 'Z' };\r
+\r
+unsigned Xz_WriteVarInt(Byte *buf, UInt64 v)\r
+{\r
+  unsigned i = 0;\r
+  do\r
+  {\r
+    buf[i++] = (Byte)((v & 0x7F) | 0x80);\r
+    v >>= 7;\r
+  }\r
+  while (v != 0);\r
+  buf[i - 1] &= 0x7F;\r
+  return i;\r
+}\r
+\r
+void Xz_Construct(CXzStream *p)\r
+{\r
+  p->numBlocks = p->numBlocksAllocated = 0;\r
+  p->blocks = 0;\r
+  p->flags = 0;\r
+}\r
+\r
+void Xz_Free(CXzStream *p, ISzAlloc *alloc)\r
+{\r
+  alloc->Free(alloc, p->blocks);\r
+  p->numBlocks = p->numBlocksAllocated = 0;\r
+  p->blocks = 0;\r
+}\r
+\r
+unsigned XzFlags_GetCheckSize(CXzStreamFlags f)\r
+{\r
+  int t = XzFlags_GetCheckType(f);\r
+  return (t == 0) ? 0 : (4 << ((t - 1) / 3));\r
+}\r
+\r
+void XzCheck_Init(CXzCheck *p, int mode)\r
+{\r
+  p->mode = mode;\r
+  switch (mode)\r
+  {\r
+    case XZ_CHECK_CRC32: p->crc = CRC_INIT_VAL; break;\r
+    case XZ_CHECK_CRC64: p->crc64 = CRC64_INIT_VAL; break;\r
+    case XZ_CHECK_SHA256: Sha256_Init(&p->sha); break;\r
+  }\r
+}\r
+\r
+void XzCheck_Update(CXzCheck *p, const void *data, size_t size)\r
+{\r
+  switch (p->mode)\r
+  {\r
+    case XZ_CHECK_CRC32: p->crc = CrcUpdate(p->crc, data, size); break;\r
+    case XZ_CHECK_CRC64: p->crc64 = Crc64Update(p->crc64, data, size); break;\r
+    case XZ_CHECK_SHA256: Sha256_Update(&p->sha, (const Byte *)data, size); break;\r
+  }\r
+}\r
+\r
+int XzCheck_Final(CXzCheck *p, Byte *digest)\r
+{\r
+  switch (p->mode)\r
+  {\r
+    case XZ_CHECK_CRC32:\r
+      SetUi32(digest, CRC_GET_DIGEST(p->crc));\r
+      break;\r
+    case XZ_CHECK_CRC64:\r
+    {\r
+      int i;\r
+      UInt64 v = CRC64_GET_DIGEST(p->crc64);\r
+      for (i = 0; i < 8; i++, v >>= 8)\r
+        digest[i] = (Byte)(v & 0xFF);\r
+      break;\r
+    }\r
+    case XZ_CHECK_SHA256:\r
+      Sha256_Final(&p->sha, digest);\r
+      break;\r
+    default:\r
+      return 0;\r
+  }\r
+  return 1;\r
+}\r
diff --git a/C/Xz.h b/C/Xz.h
new file mode 100755 (executable)
index 0000000..d307963
--- /dev/null
+++ b/C/Xz.h
@@ -0,0 +1,252 @@
+/* Xz.h - Xz interface\r
+2010-09-17 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __XZ_H\r
+#define __XZ_H\r
+\r
+#include "Sha256.h"\r
+\r
+EXTERN_C_BEGIN\r
+\r
+#define XZ_ID_Subblock 1\r
+#define XZ_ID_Delta 3\r
+#define XZ_ID_X86 4\r
+#define XZ_ID_PPC 5\r
+#define XZ_ID_IA64 6\r
+#define XZ_ID_ARM 7\r
+#define XZ_ID_ARMT 8\r
+#define XZ_ID_SPARC 9\r
+#define XZ_ID_LZMA2 0x21\r
+\r
+unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value);\r
+unsigned Xz_WriteVarInt(Byte *buf, UInt64 v);\r
+\r
+/* ---------- xz block ---------- */\r
+\r
+#define XZ_BLOCK_HEADER_SIZE_MAX 1024\r
+\r
+#define XZ_NUM_FILTERS_MAX 4\r
+#define XZ_BF_NUM_FILTERS_MASK 3\r
+#define XZ_BF_PACK_SIZE (1 << 6)\r
+#define XZ_BF_UNPACK_SIZE (1 << 7)\r
+\r
+#define XZ_FILTER_PROPS_SIZE_MAX 20\r
+\r
+typedef struct\r
+{\r
+  UInt64 id;\r
+  UInt32 propsSize;\r
+  Byte props[XZ_FILTER_PROPS_SIZE_MAX];\r
+} CXzFilter;\r
+\r
+typedef struct\r
+{\r
+  UInt64 packSize;\r
+  UInt64 unpackSize;\r
+  Byte flags;\r
+  CXzFilter filters[XZ_NUM_FILTERS_MAX];\r
+} CXzBlock;\r
+\r
+#define XzBlock_GetNumFilters(p) (((p)->flags & XZ_BF_NUM_FILTERS_MASK) + 1)\r
+#define XzBlock_HasPackSize(p)   (((p)->flags & XZ_BF_PACK_SIZE) != 0)\r
+#define XzBlock_HasUnpackSize(p) (((p)->flags & XZ_BF_UNPACK_SIZE) != 0)\r
+\r
+SRes XzBlock_Parse(CXzBlock *p, const Byte *header);\r
+SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt32 *headerSizeRes);\r
+\r
+/* ---------- xz stream ---------- */\r
+\r
+#define XZ_SIG_SIZE 6\r
+#define XZ_FOOTER_SIG_SIZE 2\r
+\r
+extern Byte XZ_SIG[XZ_SIG_SIZE];\r
+extern Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE];\r
+\r
+#define XZ_STREAM_FLAGS_SIZE 2\r
+#define XZ_STREAM_CRC_SIZE 4\r
+\r
+#define XZ_STREAM_HEADER_SIZE (XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE)\r
+#define XZ_STREAM_FOOTER_SIZE (XZ_FOOTER_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE + 4)\r
+\r
+#define XZ_CHECK_MASK 0xF\r
+#define XZ_CHECK_NO 0\r
+#define XZ_CHECK_CRC32 1\r
+#define XZ_CHECK_CRC64 4\r
+#define XZ_CHECK_SHA256 10\r
+\r
+typedef struct\r
+{\r
+  int mode;\r
+  UInt32 crc;\r
+  UInt64 crc64;\r
+  CSha256 sha;\r
+} CXzCheck;\r
+\r
+void XzCheck_Init(CXzCheck *p, int mode);\r
+void XzCheck_Update(CXzCheck *p, const void *data, size_t size);\r
+int XzCheck_Final(CXzCheck *p, Byte *digest);\r
+\r
+typedef UInt16 CXzStreamFlags;\r
+\r
+#define XzFlags_IsSupported(f) ((f) <= XZ_CHECK_MASK)\r
+#define XzFlags_GetCheckType(f) ((f) & XZ_CHECK_MASK)\r
+#define XzFlags_HasDataCrc32(f) (Xz_GetCheckType(f) == XZ_CHECK_CRC32)\r
+unsigned XzFlags_GetCheckSize(CXzStreamFlags f);\r
+\r
+SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf);\r
+SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream);\r
+\r
+typedef struct\r
+{\r
+  UInt64 unpackSize;\r
+  UInt64 totalSize;\r
+} CXzBlockSizes;\r
+\r
+typedef struct\r
+{\r
+  CXzStreamFlags flags;\r
+  size_t numBlocks;\r
+  size_t numBlocksAllocated;\r
+  CXzBlockSizes *blocks;\r
+  UInt64 startOffset;\r
+} CXzStream;\r
+\r
+void Xz_Construct(CXzStream *p);\r
+void Xz_Free(CXzStream *p, ISzAlloc *alloc);\r
+\r
+#define XZ_SIZE_OVERFLOW ((UInt64)(Int64)-1)\r
+\r
+UInt64 Xz_GetUnpackSize(const CXzStream *p);\r
+UInt64 Xz_GetPackSize(const CXzStream *p);\r
+\r
+typedef struct\r
+{\r
+  size_t num;\r
+  size_t numAllocated;\r
+  CXzStream *streams;\r
+} CXzs;\r
+\r
+void Xzs_Construct(CXzs *p);\r
+void Xzs_Free(CXzs *p, ISzAlloc *alloc);\r
+SRes Xzs_ReadBackward(CXzs *p, ILookInStream *inStream, Int64 *startOffset, ICompressProgress *progress, ISzAlloc *alloc);\r
+\r
+UInt64 Xzs_GetNumBlocks(const CXzs *p);\r
+UInt64 Xzs_GetUnpackSize(const CXzs *p);\r
+\r
+typedef enum\r
+{\r
+  CODER_STATUS_NOT_SPECIFIED,               /* use main error code instead */\r
+  CODER_STATUS_FINISHED_WITH_MARK,          /* stream was finished with end mark. */\r
+  CODER_STATUS_NOT_FINISHED,                /* stream was not finished */\r
+  CODER_STATUS_NEEDS_MORE_INPUT             /* you must provide more input bytes */\r
+} ECoderStatus;\r
+\r
+typedef enum\r
+{\r
+  CODER_FINISH_ANY,   /* finish at any point */\r
+  CODER_FINISH_END    /* block must be finished at the end */\r
+} ECoderFinishMode;\r
+\r
+typedef struct _IStateCoder\r
+{\r
+  void *p;\r
+  void (*Free)(void *p, ISzAlloc *alloc);\r
+  SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAlloc *alloc);\r
+  void (*Init)(void *p);\r
+  SRes (*Code)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\r
+      int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished);\r
+} IStateCoder;\r
+\r
+#define MIXCODER_NUM_FILTERS_MAX 4\r
+\r
+typedef struct\r
+{\r
+  ISzAlloc *alloc;\r
+  Byte *buf;\r
+  int numCoders;\r
+  int finished[MIXCODER_NUM_FILTERS_MAX - 1];\r
+  size_t pos[MIXCODER_NUM_FILTERS_MAX - 1];\r
+  size_t size[MIXCODER_NUM_FILTERS_MAX - 1];\r
+  UInt64 ids[MIXCODER_NUM_FILTERS_MAX];\r
+  IStateCoder coders[MIXCODER_NUM_FILTERS_MAX];\r
+} CMixCoder;\r
+\r
+void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc);\r
+void MixCoder_Free(CMixCoder *p);\r
+void MixCoder_Init(CMixCoder *p);\r
+SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId);\r
+SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,\r
+    const Byte *src, SizeT *srcLen, int srcWasFinished,\r
+    ECoderFinishMode finishMode, ECoderStatus *status);\r
+\r
+typedef enum\r
+{\r
+  XZ_STATE_STREAM_HEADER,\r
+  XZ_STATE_STREAM_INDEX,\r
+  XZ_STATE_STREAM_INDEX_CRC,\r
+  XZ_STATE_STREAM_FOOTER,\r
+  XZ_STATE_STREAM_PADDING,\r
+  XZ_STATE_BLOCK_HEADER,\r
+  XZ_STATE_BLOCK,\r
+  XZ_STATE_BLOCK_FOOTER\r
+} EXzState;\r
+\r
+typedef struct\r
+{\r
+  EXzState state;\r
+  UInt32 pos;\r
+  unsigned alignPos;\r
+  unsigned indexPreSize;\r
+\r
+  CXzStreamFlags streamFlags;\r
+  \r
+  UInt32 blockHeaderSize;\r
+  UInt64 packSize;\r
+  UInt64 unpackSize;\r
+\r
+  UInt64 numBlocks;\r
+  UInt64 indexSize;\r
+  UInt64 indexPos;\r
+  UInt64 padSize;\r
+\r
+  UInt64 numStreams;\r
+\r
+  UInt32 crc;\r
+  CMixCoder decoder;\r
+  CXzBlock block;\r
+  CXzCheck check;\r
+  CSha256 sha;\r
+  Byte shaDigest[SHA256_DIGEST_SIZE];\r
+  Byte buf[XZ_BLOCK_HEADER_SIZE_MAX];\r
+} CXzUnpacker;\r
+\r
+SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc);\r
+void XzUnpacker_Free(CXzUnpacker *p);\r
+\r
+/*\r
+finishMode:\r
+  It has meaning only if the decoding reaches output limit (*destLen).\r
+  LZMA_FINISH_ANY - use smallest number of input bytes\r
+  LZMA_FINISH_END - read EndOfStream marker after decoding\r
+\r
+Returns:\r
+  SZ_OK\r
+    status:\r
+      LZMA_STATUS_FINISHED_WITH_MARK\r
+      LZMA_STATUS_NOT_FINISHED\r
+  SZ_ERROR_DATA - Data error\r
+  SZ_ERROR_MEM  - Memory allocation error\r
+  SZ_ERROR_UNSUPPORTED - Unsupported properties\r
+  SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).\r
+*/\r
+\r
+\r
+SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,\r
+    const Byte *src, SizeT *srcLen, /* int srcWasFinished, */ int finishMode,\r
+    ECoderStatus *status);\r
+\r
+Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p);\r
+\r
+EXTERN_C_END\r
+\r
+#endif\r
diff --git a/C/XzCrc64.c b/C/XzCrc64.c
new file mode 100755 (executable)
index 0000000..f688b07
--- /dev/null
@@ -0,0 +1,33 @@
+/* XzCrc64.c -- CRC64 calculation\r
+2010-04-16 : Igor Pavlov : Public domain */\r
+\r
+#include "XzCrc64.h"\r
+\r
+#define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42)\r
+UInt64 g_Crc64Table[256];\r
+\r
+void MY_FAST_CALL Crc64GenerateTable(void)\r
+{\r
+  UInt32 i;\r
+  for (i = 0; i < 256; i++)\r
+  {\r
+    UInt64 r = i;\r
+    int j;\r
+    for (j = 0; j < 8; j++)\r
+      r = (r >> 1) ^ ((UInt64)kCrc64Poly & ~((r & 1) - 1));\r
+    g_Crc64Table[i] = r;\r
+  }\r
+}\r
+\r
+UInt64 MY_FAST_CALL Crc64Update(UInt64 v, const void *data, size_t size)\r
+{\r
+  const Byte *p = (const Byte *)data;\r
+  for (; size > 0 ; size--, p++)\r
+    v = CRC64_UPDATE_BYTE(v, *p);\r
+  return v;\r
+}\r
+\r
+UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size)\r
+{\r
+  return CRC64_GET_DIGEST(Crc64Update(CRC64_INIT_VAL, data, size));\r
+}\r
diff --git a/C/XzCrc64.h b/C/XzCrc64.h
new file mode 100755 (executable)
index 0000000..05d0d09
--- /dev/null
@@ -0,0 +1,26 @@
+/* XzCrc64.h -- CRC64 calculation\r
+2010-04-16 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __XZ_CRC64_H\r
+#define __XZ_CRC64_H\r
+\r
+#include <stddef.h>\r
+\r
+#include "Types.h"\r
+\r
+EXTERN_C_BEGIN\r
+\r
+extern UInt64 g_Crc64Table[];\r
+\r
+void MY_FAST_CALL Crc64GenerateTable(void);\r
+\r
+#define CRC64_INIT_VAL UINT64_CONST(0xFFFFFFFFFFFFFFFF)\r
+#define CRC64_GET_DIGEST(crc) ((crc) ^ CRC64_INIT_VAL)\r
+#define CRC64_UPDATE_BYTE(crc, b) (g_Crc64Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))\r
+\r
+UInt64 MY_FAST_CALL Crc64Update(UInt64 crc, const void *data, size_t size);\r
+UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size);\r
+\r
+EXTERN_C_END\r
+\r
+#endif\r
diff --git a/C/XzDec.c b/C/XzDec.c
new file mode 100755 (executable)
index 0000000..2eca1af
--- /dev/null
+++ b/C/XzDec.c
@@ -0,0 +1,875 @@
+/* XzDec.c -- Xz Decode\r
+2010-04-16 : Igor Pavlov : Public domain */\r
+\r
+/* #define XZ_DUMP */\r
+\r
+#ifdef XZ_DUMP\r
+#include <stdio.h>\r
+#endif\r
+\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#include "7zCrc.h"\r
+#include "Alloc.h"\r
+#include "Bra.h"\r
+#include "CpuArch.h"\r
+#include "Delta.h"\r
+#include "Lzma2Dec.h"\r
+\r
+#ifdef USE_SUBBLOCK\r
+#include "SbDec.h"\r
+#endif\r
+\r
+#include "Xz.h"\r
+\r
+#define XZ_CHECK_SIZE_MAX 64\r
+\r
+#define CODER_BUF_SIZE (1 << 17)\r
+\r
+unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)\r
+{\r
+  int i, limit;\r
+  *value = 0;\r
+  limit = (maxSize > 9) ? 9 : (int)maxSize;\r
+\r
+  for (i = 0; i < limit;)\r
+  {\r
+    Byte b = p[i];\r
+    *value |= (UInt64)(b & 0x7F) << (7 * i++);\r
+    if ((b & 0x80) == 0)\r
+      return (b == 0 && i != 1) ? 0 : i;\r
+  }\r
+  return 0;\r
+}\r
+\r
+/* ---------- BraState ---------- */\r
+\r
+#define BRA_BUF_SIZE (1 << 14)\r
+\r
+typedef struct\r
+{\r
+  size_t bufPos;\r
+  size_t bufConv;\r
+  size_t bufTotal;\r
+\r
+  UInt32 methodId;\r
+  int encodeMode;\r
+  UInt32 delta;\r
+  UInt32 ip;\r
+  UInt32 x86State;\r
+  Byte deltaState[DELTA_STATE_SIZE];\r
+\r
+  Byte buf[BRA_BUF_SIZE];\r
+} CBraState;\r
+\r
+void BraState_Free(void *pp, ISzAlloc *alloc)\r
+{\r
+  alloc->Free(alloc, pp);\r
+}\r
+\r
+SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)\r
+{\r
+  CBraState *p = ((CBraState *)pp);\r
+  alloc = alloc;\r
+  p->encodeMode = 0;\r
+  p->ip = 0;\r
+  if (p->methodId == XZ_ID_Delta)\r
+  {\r
+    if (propSize != 1)\r
+      return SZ_ERROR_UNSUPPORTED;\r
+    p->delta = (unsigned)props[0] + 1;\r
+  }\r
+  else\r
+  {\r
+    if (propSize == 4)\r
+    {\r
+      UInt32 v = GetUi32(props);\r
+      switch(p->methodId)\r
+      {\r
+        case XZ_ID_PPC:\r
+        case XZ_ID_ARM:\r
+        case XZ_ID_SPARC:\r
+          if ((v & 3) != 0)\r
+            return SZ_ERROR_UNSUPPORTED;\r
+          break;\r
+        case XZ_ID_ARMT:\r
+          if ((v & 1) != 0)\r
+            return SZ_ERROR_UNSUPPORTED;\r
+          break;\r
+        case XZ_ID_IA64:\r
+          if ((v & 0xF) != 0)\r
+            return SZ_ERROR_UNSUPPORTED;\r
+          break;\r
+      }\r
+      p->ip = v;\r
+    }\r
+    else if (propSize != 0)\r
+      return SZ_ERROR_UNSUPPORTED;\r
+  }\r
+  return SZ_OK;\r
+}\r
+\r
+void BraState_Init(void *pp)\r
+{\r
+  CBraState *p = ((CBraState *)pp);\r
+  p->bufPos = p->bufConv = p->bufTotal = 0;\r
+  x86_Convert_Init(p->x86State);\r
+  if (p->methodId == XZ_ID_Delta)\r
+    Delta_Init(p->deltaState);\r
+}\r
+\r
+#define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: p->bufConv = isa ## _Convert(p->buf, p->bufTotal, p->ip, p->encodeMode); break;\r
+\r
+static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\r
+    int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)\r
+{\r
+  CBraState *p = ((CBraState *)pp);\r
+  SizeT destLenOrig = *destLen;\r
+  SizeT srcLenOrig = *srcLen;\r
+  *destLen = 0;\r
+  *srcLen = 0;\r
+  finishMode = finishMode;\r
+  *wasFinished = 0;\r
+  while (destLenOrig > 0)\r
+  {\r
+    if (p->bufPos != p->bufConv)\r
+    {\r
+      size_t curSize = p->bufConv - p->bufPos;\r
+      if (curSize > destLenOrig)\r
+        curSize = destLenOrig;\r
+      memcpy(dest, p->buf + p->bufPos, curSize);\r
+      p->bufPos += curSize;\r
+      *destLen += curSize;\r
+      dest += curSize;\r
+      destLenOrig -= curSize;\r
+      continue;\r
+    }\r
+    p->bufTotal -= p->bufPos;\r
+    memmove(p->buf, p->buf + p->bufPos, p->bufTotal);\r
+    p->bufPos = 0;\r
+    p->bufConv = 0;\r
+    {\r
+      size_t curSize = BRA_BUF_SIZE - p->bufTotal;\r
+      if (curSize > srcLenOrig)\r
+        curSize = srcLenOrig;\r
+      memcpy(p->buf + p->bufTotal, src, curSize);\r
+      *srcLen += curSize;\r
+      src += curSize;\r
+      srcLenOrig -= curSize;\r
+      p->bufTotal += curSize;\r
+    }\r
+    if (p->bufTotal == 0)\r
+      break;\r
+    switch(p->methodId)\r
+    {\r
+      case XZ_ID_Delta:\r
+        if (p->encodeMode)\r
+          Delta_Encode(p->deltaState, p->delta, p->buf, p->bufTotal);\r
+        else\r
+          Delta_Decode(p->deltaState, p->delta, p->buf, p->bufTotal);\r
+        p->bufConv = p->bufTotal;\r
+        break;\r
+      case XZ_ID_X86:\r
+        p->bufConv = x86_Convert(p->buf, p->bufTotal, p->ip, &p->x86State, p->encodeMode);\r
+        break;\r
+      CASE_BRA_CONV(PPC)\r
+      CASE_BRA_CONV(IA64)\r
+      CASE_BRA_CONV(ARM)\r
+      CASE_BRA_CONV(ARMT)\r
+      CASE_BRA_CONV(SPARC)\r
+      default:\r
+        return SZ_ERROR_UNSUPPORTED;\r
+    }\r
+    p->ip += (UInt32)p->bufConv;\r
+\r
+    if (p->bufConv == 0)\r
+    {\r
+      if (!srcWasFinished)\r
+        break;\r
+      p->bufConv = p->bufTotal;\r
+    }\r
+  }\r
+  if (p->bufTotal == p->bufPos && srcLenOrig == 0 && srcWasFinished)\r
+    *wasFinished = 1;\r
+  return SZ_OK;\r
+}\r
+\r
+SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, ISzAlloc *alloc)\r
+{\r
+  CBraState *decoder;\r
+  if (id != XZ_ID_Delta &&\r
+      id != XZ_ID_X86 &&\r
+      id != XZ_ID_PPC &&\r
+      id != XZ_ID_IA64 &&\r
+      id != XZ_ID_ARM &&\r
+      id != XZ_ID_ARMT &&\r
+      id != XZ_ID_SPARC)\r
+    return SZ_ERROR_UNSUPPORTED;\r
+  p->p = 0;\r
+  decoder = alloc->Alloc(alloc, sizeof(CBraState));\r
+  if (decoder == 0)\r
+    return SZ_ERROR_MEM;\r
+  decoder->methodId = (UInt32)id;\r
+  p->p = decoder;\r
+  p->Free = BraState_Free;\r
+  p->SetProps = BraState_SetProps;\r
+  p->Init = BraState_Init;\r
+  p->Code = BraState_Code;\r
+  return SZ_OK;\r
+}\r
+\r
+/* ---------- SbState ---------- */\r
+\r
+#ifdef USE_SUBBLOCK\r
+\r
+static void SbState_Free(void *pp, ISzAlloc *alloc)\r
+{\r
+  CSubblockDec *p = (CSubblockDec *)pp;\r
+  SubblockDec_Free(p, alloc);\r
+  alloc->Free(alloc, pp);\r
+}\r
+\r
+static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)\r
+{\r
+  pp = pp;\r
+  props = props;\r
+  alloc = alloc;\r
+  return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;\r
+}\r
+\r
+static void SbState_Init(void *pp)\r
+{\r
+  SubblockDec_Init((CSubblockDec *)pp);\r
+}\r
+\r
+static SRes SbState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\r
+    int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)\r
+{\r
+  ECoderStatus status;\r
+  SRes res = SubblockDec_Decode((CSubblockDec *)pp, dest, destLen, src, srcLen, finishMode, &status);\r
+  srcWasFinished = srcWasFinished;\r
+  *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);\r
+  return res;\r
+}\r
+\r
+SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)\r
+{\r
+  CSubblockDec *decoder;\r
+  p->p = 0;\r
+  decoder = alloc->Alloc(alloc, sizeof(CSubblockDec));\r
+  if (decoder == 0)\r
+    return SZ_ERROR_MEM;\r
+  p->p = decoder;\r
+  p->Free = SbState_Free;\r
+  p->SetProps = SbState_SetProps;\r
+  p->Init = SbState_Init;\r
+  p->Code = SbState_Code;\r
+  SubblockDec_Construct(decoder);\r
+  return SZ_OK;\r
+}\r
+#endif\r
+\r
+/* ---------- Lzma2State ---------- */\r
+\r
+static void Lzma2State_Free(void *pp, ISzAlloc *alloc)\r
+{\r
+  Lzma2Dec_Free((CLzma2Dec *)pp, alloc);\r
+  alloc->Free(alloc, pp);\r
+}\r
+\r
+static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)\r
+{\r
+  if (propSize != 1)\r
+    return SZ_ERROR_UNSUPPORTED;\r
+  return Lzma2Dec_Allocate((CLzma2Dec *)pp, props[0], alloc);\r
+}\r
+\r
+static void Lzma2State_Init(void *pp)\r
+{\r
+  Lzma2Dec_Init((CLzma2Dec *)pp);\r
+}\r
+\r
+static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\r
+    int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)\r
+{\r
+  ELzmaStatus status;\r
+  /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */\r
+  SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, finishMode, &status);\r
+  srcWasFinished = srcWasFinished;\r
+  *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);\r
+  return res;\r
+}\r
+\r
+static SRes Lzma2State_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)\r
+{\r
+  CLzma2Dec *decoder = alloc->Alloc(alloc, sizeof(CLzma2Dec));\r
+  p->p = decoder;\r
+  if (decoder == 0)\r
+    return SZ_ERROR_MEM;\r
+  p->Free = Lzma2State_Free;\r
+  p->SetProps = Lzma2State_SetProps;\r
+  p->Init = Lzma2State_Init;\r
+  p->Code = Lzma2State_Code;\r
+  Lzma2Dec_Construct(decoder);\r
+  return SZ_OK;\r
+}\r
+\r
+\r
+void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc)\r
+{\r
+  int i;\r
+  p->alloc = alloc;\r
+  p->buf = 0;\r
+  p->numCoders = 0;\r
+  for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)\r
+    p->coders[i].p = NULL;\r
+}\r
+\r
+void MixCoder_Free(CMixCoder *p)\r
+{\r
+  int i;\r
+  for (i = 0; i < p->numCoders; i++)\r
+  {\r
+    IStateCoder *sc = &p->coders[i];\r
+    if (p->alloc && sc->p)\r
+      sc->Free(sc->p, p->alloc);\r
+  }\r
+  p->numCoders = 0;\r
+  if (p->buf)\r
+    p->alloc->Free(p->alloc, p->buf);\r
+}\r
+\r
+void MixCoder_Init(CMixCoder *p)\r
+{\r
+  int i;\r
+  for (i = 0; i < p->numCoders - 1; i++)\r
+  {\r
+    p->size[i] = 0;\r
+    p->pos[i] = 0;\r
+    p->finished[i] = 0;\r
+  }\r
+  for (i = 0; i < p->numCoders; i++)\r
+  {\r
+    IStateCoder *coder = &p->coders[i];\r
+    coder->Init(coder->p);\r
+  }\r
+}\r
+\r
+SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId)\r
+{\r
+  IStateCoder *sc = &p->coders[coderIndex];\r
+  p->ids[coderIndex] = methodId;\r
+  switch(methodId)\r
+  {\r
+    case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, p->alloc);\r
+    #ifdef USE_SUBBLOCK\r
+    case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc);\r
+    #endif\r
+  }\r
+  if (coderIndex == 0)\r
+    return SZ_ERROR_UNSUPPORTED;\r
+  return BraState_SetFromMethod(sc, methodId, p->alloc);\r
+}\r
+\r
+SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,\r
+    const Byte *src, SizeT *srcLen, int srcWasFinished,\r
+    ECoderFinishMode finishMode, ECoderStatus *status)\r
+{\r
+  SizeT destLenOrig = *destLen;\r
+  SizeT srcLenOrig = *srcLen;\r
+  Bool allFinished = True;\r
+  *destLen = 0;\r
+  *srcLen = 0;\r
+  *status = CODER_STATUS_NOT_FINISHED;\r
+\r
+  if (p->buf == 0)\r
+  {\r
+    p->buf = p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));\r
+    if (p->buf == 0)\r
+      return SZ_ERROR_MEM;\r
+  }\r
+\r
+  if (p->numCoders != 1)\r
+    finishMode = CODER_FINISH_ANY;\r
+\r
+  for (;;)\r
+  {\r
+    Bool processed = False;\r
+    int i;\r
+    /*\r
+    if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)\r
+      break;\r
+    */\r
+\r
+    for (i = 0; i < p->numCoders; i++)\r
+    {\r
+      SRes res;\r
+      IStateCoder *coder = &p->coders[i];\r
+      Byte *destCur;\r
+      SizeT destLenCur, srcLenCur;\r
+      const Byte *srcCur;\r
+      int srcFinishedCur;\r
+      int encodingWasFinished;\r
+      \r
+      if (i == 0)\r
+      {\r
+        srcCur = src;\r
+        srcLenCur = srcLenOrig - *srcLen;\r
+        srcFinishedCur = srcWasFinished;\r
+      }\r
+      else\r
+      {\r
+        srcCur = p->buf + (CODER_BUF_SIZE * (i - 1)) + p->pos[i - 1];\r
+        srcLenCur = p->size[i - 1] - p->pos[i - 1];\r
+        srcFinishedCur = p->finished[i - 1];\r
+      }\r
+      \r
+      if (i == p->numCoders - 1)\r
+      {\r
+        destCur = dest;\r
+        destLenCur = destLenOrig - *destLen;\r
+      }\r
+      else\r
+      {\r
+        if (p->pos[i] != p->size[i])\r
+          continue;\r
+        destCur = p->buf + (CODER_BUF_SIZE * i);\r
+        destLenCur = CODER_BUF_SIZE;\r
+      }\r
+      \r
+      res = coder->Code(coder->p, destCur, &destLenCur, srcCur, &srcLenCur, srcFinishedCur, finishMode, &encodingWasFinished);\r
+\r
+      if (!encodingWasFinished)\r
+        allFinished = False;\r
+\r
+      if (i == 0)\r
+      {\r
+        *srcLen += srcLenCur;\r
+        src += srcLenCur;\r
+      }\r
+      else\r
+      {\r
+        p->pos[i - 1] += srcLenCur;\r
+      }\r
+\r
+      if (i == p->numCoders - 1)\r
+      {\r
+        *destLen += destLenCur;\r
+        dest += destLenCur;\r
+      }\r
+      else\r
+      {\r
+        p->size[i] = destLenCur;\r
+        p->pos[i] = 0;\r
+        p->finished[i] = encodingWasFinished;\r
+      }\r
+      \r
+      if (res != SZ_OK)\r
+        return res;\r
+\r
+      if (destLenCur != 0 || srcLenCur != 0)\r
+        processed = True;\r
+    }\r
+    if (!processed)\r
+      break;\r
+  }\r
+  if (allFinished)\r
+    *status = CODER_STATUS_FINISHED_WITH_MARK;\r
+  return SZ_OK;\r
+}\r
+\r
+SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)\r
+{\r
+  *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE);\r
+  if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) !=\r
+      GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE))\r
+    return SZ_ERROR_NO_ARCHIVE;\r
+  return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED;\r
+}\r
+\r
+static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)\r
+{\r
+  return\r
+      indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2) &&\r
+      (GetUi32(buf) == CrcCalc(buf + 4, 6) &&\r
+      flags == GetBe16(buf + 8) &&\r
+      memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0);\r
+}\r
+\r
+#define READ_VARINT_AND_CHECK(buf, pos, size, res) \\r
+  { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \\r
+  if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }\r
+\r
+\r
+SRes XzBlock_Parse(CXzBlock *p, const Byte *header)\r
+{\r
+  unsigned pos;\r
+  int numFilters, i;\r
+  UInt32 headerSize = (UInt32)header[0] << 2;\r
+\r
+  if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))\r
+    return SZ_ERROR_ARCHIVE;\r
+\r
+  pos = 1;\r
+  if (pos == headerSize)\r
+    return SZ_ERROR_ARCHIVE;\r
+  p->flags = header[pos++];\r
+\r
+  if (XzBlock_HasPackSize(p))\r
+  {\r
+    READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize);\r
+    if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63)\r
+      return SZ_ERROR_ARCHIVE;\r
+  }\r
+\r
+  if (XzBlock_HasUnpackSize(p))\r
+    READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize);\r
+\r
+  numFilters = XzBlock_GetNumFilters(p);\r
+  for (i = 0; i < numFilters; i++)\r
+  {\r
+    CXzFilter *filter = p->filters + i;\r
+    UInt64 size;\r
+    READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id);\r
+    READ_VARINT_AND_CHECK(header, pos, headerSize, &size);\r
+    if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX)\r
+      return SZ_ERROR_ARCHIVE;\r
+    filter->propsSize = (UInt32)size;\r
+    memcpy(filter->props, header + pos, (size_t)size);\r
+    pos += (unsigned)size;\r
+\r
+    #ifdef XZ_DUMP\r
+    printf("\nf[%d] = %2X: ", i, filter->id);\r
+    {\r
+      int i;\r
+      for (i = 0; i < size; i++)\r
+        printf(" %2X", filter->props[i]);\r
+    }\r
+    #endif\r
+  }\r
+\r
+  while (pos < headerSize)\r
+    if (header[pos++] != 0)\r
+      return SZ_ERROR_ARCHIVE;\r
+  return SZ_OK;\r
+}\r
+\r
+SRes XzDec_Init(CMixCoder *p, const CXzBlock *block)\r
+{\r
+  int i;\r
+  Bool needReInit = True;\r
+  int numFilters = XzBlock_GetNumFilters(block);\r
+  if (numFilters == p->numCoders)\r
+  {\r
+    for (i = 0; i < numFilters; i++)\r
+      if (p->ids[i] != block->filters[numFilters - 1 - i].id)\r
+        break;\r
+    needReInit = (i != numFilters);\r
+  }\r
+  if (needReInit)\r
+  {\r
+    MixCoder_Free(p);\r
+    p->numCoders = numFilters;\r
+    for (i = 0; i < numFilters; i++)\r
+    {\r
+      const CXzFilter *f = &block->filters[numFilters - 1 - i];\r
+      RINOK(MixCoder_SetFromMethod(p, i, f->id));\r
+    }\r
+  }\r
+  for (i = 0; i < numFilters; i++)\r
+  {\r
+    const CXzFilter *f = &block->filters[numFilters - 1 - i];\r
+    IStateCoder *sc = &p->coders[i];\r
+    RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));\r
+  }\r
+  MixCoder_Init(p);\r
+  return SZ_OK;\r
+}\r
+\r
+SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc)\r
+{\r
+  MixCoder_Construct(&p->decoder, alloc);\r
+  p->state = XZ_STATE_STREAM_HEADER;\r
+  p->pos = 0;\r
+  p->numStreams = 0;\r
+  return SZ_OK;\r
+}\r
+\r
+void XzUnpacker_Free(CXzUnpacker *p)\r
+{\r
+  MixCoder_Free(&p->decoder);\r
+}\r
+\r
+SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,\r
+    const Byte *src, SizeT *srcLen, int finishMode, ECoderStatus *status)\r
+{\r
+  SizeT destLenOrig = *destLen;\r
+  SizeT srcLenOrig = *srcLen;\r
+  *destLen = 0;\r
+  *srcLen = 0;\r
+  *status = CODER_STATUS_NOT_SPECIFIED;\r
+  for (;;)\r
+  {\r
+    SizeT srcRem = srcLenOrig - *srcLen;\r
+\r
+    if (p->state == XZ_STATE_BLOCK)\r
+    {\r
+      SizeT destLen2 = destLenOrig - *destLen;\r
+      SizeT srcLen2 = srcLenOrig - *srcLen;\r
+      SRes res;\r
+      if (srcLen2 == 0 && destLen2 == 0)\r
+      {\r
+        *status = CODER_STATUS_NOT_FINISHED;\r
+        return SZ_OK;\r
+      }\r
+      \r
+      res = MixCoder_Code(&p->decoder, dest, &destLen2, src, &srcLen2, False, finishMode, status);\r
+      XzCheck_Update(&p->check, dest, destLen2);\r
+      \r
+      (*srcLen) += srcLen2;\r
+      src += srcLen2;\r
+      p->packSize += srcLen2;\r
+      \r
+      (*destLen) += destLen2;\r
+      dest += destLen2;\r
+      p->unpackSize += destLen2;\r
+      \r
+      RINOK(res);\r
+      \r
+      if (*status == CODER_STATUS_FINISHED_WITH_MARK)\r
+      {\r
+        Byte temp[32];\r
+        unsigned num = Xz_WriteVarInt(temp, p->packSize + p->blockHeaderSize + XzFlags_GetCheckSize(p->streamFlags));\r
+        num += Xz_WriteVarInt(temp + num, p->unpackSize);\r
+        Sha256_Update(&p->sha, temp, num);\r
+        p->indexSize += num;\r
+        p->numBlocks++;\r
+        \r
+        p->state = XZ_STATE_BLOCK_FOOTER;\r
+        p->pos = 0;\r
+        p->alignPos = 0;\r
+      }\r
+      else if (srcLen2 == 0 && destLen2 == 0)\r
+        return SZ_OK;\r
+      \r
+      continue;\r
+    }\r
+\r
+    if (srcRem == 0)\r
+    {\r
+      *status = CODER_STATUS_NEEDS_MORE_INPUT;\r
+      return SZ_OK;\r
+    }\r
+\r
+    switch(p->state)\r
+    {\r
+      case XZ_STATE_STREAM_HEADER:\r
+      {\r
+        if (p->pos < XZ_STREAM_HEADER_SIZE)\r
+        {\r
+          if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])\r
+            return SZ_ERROR_NO_ARCHIVE;\r
+          p->buf[p->pos++] = *src++;\r
+          (*srcLen)++;\r
+        }\r
+        else\r
+        {\r
+          RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));\r
+          p->state = XZ_STATE_BLOCK_HEADER;\r
+          Sha256_Init(&p->sha);\r
+          p->indexSize = 0;\r
+          p->numBlocks = 0;\r
+          p->pos = 0;\r
+        }\r
+        break;\r
+      }\r
+\r
+      case XZ_STATE_BLOCK_HEADER:\r
+      {\r
+        if (p->pos == 0)\r
+        {\r
+          p->buf[p->pos++] = *src++;\r
+          (*srcLen)++;\r
+          if (p->buf[0] == 0)\r
+          {\r
+            p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);\r
+            p->indexPos = p->indexPreSize;\r
+            p->indexSize += p->indexPreSize;\r
+            Sha256_Final(&p->sha, p->shaDigest);\r
+            Sha256_Init(&p->sha);\r
+            p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);\r
+            p->state = XZ_STATE_STREAM_INDEX;\r
+          }\r
+          p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4;\r
+        }\r
+        else if (p->pos != p->blockHeaderSize)\r
+        {\r
+          UInt32 cur = p->blockHeaderSize - p->pos;\r
+          if (cur > srcRem)\r
+            cur = (UInt32)srcRem;\r
+          memcpy(p->buf + p->pos, src, cur);\r
+          p->pos += cur;\r
+          (*srcLen) += cur;\r
+          src += cur;\r
+        }\r
+        else\r
+        {\r
+          RINOK(XzBlock_Parse(&p->block, p->buf));\r
+          p->state = XZ_STATE_BLOCK;\r
+          p->packSize = 0;\r
+          p->unpackSize = 0;\r
+          XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));\r
+          RINOK(XzDec_Init(&p->decoder, &p->block));\r
+        }\r
+        break;\r
+      }\r
+\r
+      case XZ_STATE_BLOCK_FOOTER:\r
+      {\r
+        if (((p->packSize + p->alignPos) & 3) != 0)\r
+        {\r
+          (*srcLen)++;\r
+          p->alignPos++;\r
+          if (*src++ != 0)\r
+            return SZ_ERROR_CRC;\r
+        }\r
+        else\r
+        {\r
+          UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags);\r
+          UInt32 cur = checkSize - p->pos;\r
+          if (cur != 0)\r
+          {\r
+            if (cur > srcRem)\r
+              cur = (UInt32)srcRem;\r
+            memcpy(p->buf + p->pos, src, cur);\r
+            p->pos += cur;\r
+            (*srcLen) += cur;\r
+            src += cur;\r
+          }\r
+          else\r
+          {\r
+            Byte digest[XZ_CHECK_SIZE_MAX];\r
+            p->state = XZ_STATE_BLOCK_HEADER;\r
+            p->pos = 0;\r
+            if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)\r
+              return SZ_ERROR_CRC;\r
+          }\r
+        }\r
+        break;\r
+      }\r
+\r
+      case XZ_STATE_STREAM_INDEX:\r
+      {\r
+        if (p->pos < p->indexPreSize)\r
+        {\r
+          (*srcLen)++;\r
+          if (*src++ != p->buf[p->pos++])\r
+            return SZ_ERROR_CRC;\r
+        }\r
+        else\r
+        {\r
+          if (p->indexPos < p->indexSize)\r
+          {\r
+            UInt64 cur = p->indexSize - p->indexPos;\r
+            if (srcRem > cur)\r
+              srcRem = (SizeT)cur;\r
+            p->crc = CrcUpdate(p->crc, src, srcRem);\r
+            Sha256_Update(&p->sha, src, srcRem);\r
+            (*srcLen) += srcRem;\r
+            src += srcRem;\r
+            p->indexPos += srcRem;\r
+          }\r
+          else if ((p->indexPos & 3) != 0)\r
+          {\r
+            Byte b = *src++;\r
+            p->crc = CRC_UPDATE_BYTE(p->crc, b);\r
+            (*srcLen)++;\r
+            p->indexPos++;\r
+            p->indexSize++;\r
+            if (b != 0)\r
+              return SZ_ERROR_CRC;\r
+          }\r
+          else\r
+          {\r
+            Byte digest[SHA256_DIGEST_SIZE];\r
+            p->state = XZ_STATE_STREAM_INDEX_CRC;\r
+            p->indexSize += 4;\r
+            p->pos = 0;\r
+            Sha256_Final(&p->sha, digest);\r
+            if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)\r
+              return SZ_ERROR_CRC;\r
+          }\r
+        }\r
+        break;\r
+      }\r
+\r
+      case XZ_STATE_STREAM_INDEX_CRC:\r
+      {\r
+        if (p->pos < 4)\r
+        {\r
+          (*srcLen)++;\r
+          p->buf[p->pos++] = *src++;\r
+        }\r
+        else\r
+        {\r
+          p->state = XZ_STATE_STREAM_FOOTER;\r
+          p->pos = 0;\r
+          if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf))\r
+            return SZ_ERROR_CRC;\r
+        }\r
+        break;\r
+      }\r
+\r
+      case XZ_STATE_STREAM_FOOTER:\r
+      {\r
+        UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos;\r
+        if (cur > srcRem)\r
+          cur = (UInt32)srcRem;\r
+        memcpy(p->buf + p->pos, src, cur);\r
+        p->pos += cur;\r
+        (*srcLen) += cur;\r
+        src += cur;\r
+        if (p->pos == XZ_STREAM_FOOTER_SIZE)\r
+        {\r
+          p->state = XZ_STATE_STREAM_PADDING;\r
+          p->numStreams++;\r
+          p->padSize = 0;\r
+          if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))\r
+            return SZ_ERROR_CRC;\r
+        }\r
+        break;\r
+      }\r
+\r
+      case XZ_STATE_STREAM_PADDING:\r
+      {\r
+        if (*src != 0)\r
+        {\r
+          if (((UInt32)p->padSize & 3) != 0)\r
+            return SZ_ERROR_NO_ARCHIVE;\r
+          p->pos = 0;\r
+          p->state = XZ_STATE_STREAM_HEADER;\r
+        }\r
+        else\r
+        {\r
+          (*srcLen)++;\r
+          src++;\r
+          p->padSize++;\r
+        }\r
+        break;\r
+      }\r
+      \r
+      case XZ_STATE_BLOCK: break; /* to disable GCC warning */\r
+    }\r
+  }\r
+  /*\r
+  if (p->state == XZ_STATE_FINISHED)\r
+    *status = CODER_STATUS_FINISHED_WITH_MARK;\r
+  return SZ_OK;\r
+  */\r
+}\r
+\r
+Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p)\r
+{\r
+  return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);\r
+}\r
diff --git a/C/XzEnc.c b/C/XzEnc.c
new file mode 100755 (executable)
index 0000000..e610140
--- /dev/null
+++ b/C/XzEnc.c
@@ -0,0 +1,497 @@
+/* XzEnc.c -- Xz Encode\r
+2009-06-04 : Igor Pavlov : Public domain */\r
+\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#include "7zCrc.h"\r
+#include "Alloc.h"\r
+#include "Bra.h"\r
+#include "CpuArch.h"\r
+#ifdef USE_SUBBLOCK\r
+#include "SbEnc.h"\r
+#endif\r
+\r
+#include "XzEnc.h"\r
+\r
+static void *SzBigAlloc(void *p, size_t size) { p = p; return BigAlloc(size); }\r
+static void SzBigFree(void *p, void *address) { p = p; BigFree(address); }\r
+static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };\r
+\r
+static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }\r
+static void SzFree(void *p, void *address) { p = p; MyFree(address); }\r
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };\r
+\r
+#define XzBlock_ClearFlags(p)       (p)->flags = 0;\r
+#define XzBlock_SetNumFilters(p, n) (p)->flags |= ((n) - 1);\r
+#define XzBlock_SetHasPackSize(p)   (p)->flags |= XZ_BF_PACK_SIZE;\r
+#define XzBlock_SetHasUnpackSize(p) (p)->flags |= XZ_BF_UNPACK_SIZE;\r
+\r
+static SRes WriteBytes(ISeqOutStream *s, const void *buf, UInt32 size)\r
+{\r
+  return (s->Write(s, buf, size) == size) ? SZ_OK : SZ_ERROR_WRITE;\r
+}\r
+\r
+static SRes WriteBytesAndCrc(ISeqOutStream *s, const void *buf, UInt32 size, UInt32 *crc)\r
+{\r
+  *crc = CrcUpdate(*crc, buf, size);\r
+  return WriteBytes(s, buf, size);\r
+}\r
+\r
+SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStream *s)\r
+{\r
+  UInt32 crc;\r
+  Byte header[XZ_STREAM_HEADER_SIZE];\r
+  memcpy(header, XZ_SIG, XZ_SIG_SIZE);\r
+  header[XZ_SIG_SIZE] = (Byte)(f >> 8);\r
+  header[XZ_SIG_SIZE + 1] = (Byte)(f & 0xFF);\r
+  crc = CrcCalc(header + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE);\r
+  SetUi32(header + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE, crc);\r
+  return WriteBytes(s, header, XZ_STREAM_HEADER_SIZE);\r
+}\r
+\r
+SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s)\r
+{\r
+  Byte header[XZ_BLOCK_HEADER_SIZE_MAX];\r
+\r
+  unsigned pos = 1;\r
+  int numFilters, i;\r
+  header[pos++] = p->flags;\r
+\r
+  if (XzBlock_HasPackSize(p)) pos += Xz_WriteVarInt(header + pos, p->packSize);\r
+  if (XzBlock_HasUnpackSize(p)) pos += Xz_WriteVarInt(header + pos, p->unpackSize);\r
+  numFilters = XzBlock_GetNumFilters(p);\r
+  for (i = 0; i < numFilters; i++)\r
+  {\r
+    const CXzFilter *f = &p->filters[i];\r
+    pos += Xz_WriteVarInt(header + pos, f->id);\r
+    pos += Xz_WriteVarInt(header + pos, f->propsSize);\r
+    memcpy(header + pos, f->props, f->propsSize);\r
+    pos += f->propsSize;\r
+  }\r
+  while((pos & 3) != 0)\r
+    header[pos++] = 0;\r
+  header[0] = (Byte)(pos >> 2);\r
+  SetUi32(header + pos, CrcCalc(header, pos));\r
+  return WriteBytes(s, header, pos + 4);\r
+}\r
+\r
+SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s)\r
+{\r
+  Byte buf[32];\r
+  UInt64 globalPos;\r
+  {\r
+    UInt32 crc = CRC_INIT_VAL;\r
+    unsigned pos = 1 + Xz_WriteVarInt(buf + 1, p->numBlocks);\r
+    size_t i;\r
+\r
+    globalPos = pos;\r
+    buf[0] = 0;\r
+    RINOK(WriteBytesAndCrc(s, buf, pos, &crc));\r
+    for (i = 0; i < p->numBlocks; i++)\r
+    {\r
+      const CXzBlockSizes *block = &p->blocks[i];\r
+      pos = Xz_WriteVarInt(buf, block->totalSize);\r
+      pos += Xz_WriteVarInt(buf + pos, block->unpackSize);\r
+      globalPos += pos;\r
+      RINOK(WriteBytesAndCrc(s, buf, pos, &crc));\r
+    }\r
+    pos = ((unsigned)globalPos & 3);\r
+    if (pos != 0)\r
+    {\r
+      buf[0] = buf[1] = buf[2] = 0;\r
+      RINOK(WriteBytesAndCrc(s, buf, 4 - pos, &crc));\r
+      globalPos += 4 - pos;\r
+    }\r
+    {\r
+      SetUi32(buf, CRC_GET_DIGEST(crc));\r
+      RINOK(WriteBytes(s, buf, 4));\r
+      globalPos += 4;\r
+    }\r
+  }\r
+\r
+  {\r
+    UInt32 indexSize = (UInt32)((globalPos >> 2) - 1);\r
+    SetUi32(buf + 4, indexSize);\r
+    buf[8] = (Byte)(p->flags >> 8);\r
+    buf[9] = (Byte)(p->flags & 0xFF);\r
+    SetUi32(buf, CrcCalc(buf + 4, 6));\r
+    memcpy(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE);\r
+    return WriteBytes(s, buf, 12);\r
+  }\r
+}\r
+\r
+SRes Xz_AddIndexRecord(CXzStream *p, UInt64 unpackSize, UInt64 totalSize, ISzAlloc *alloc)\r
+{\r
+  if (p->blocks == 0 || p->numBlocksAllocated == p->numBlocks)\r
+  {\r
+    size_t num = (p->numBlocks + 1) * 2;\r
+    size_t newSize = sizeof(CXzBlockSizes) * num;\r
+    CXzBlockSizes *blocks;\r
+    if (newSize / sizeof(CXzBlockSizes) != num)\r
+      return SZ_ERROR_MEM;\r
+    blocks = alloc->Alloc(alloc, newSize);\r
+    if (blocks == 0)\r
+      return SZ_ERROR_MEM;\r
+    if (p->numBlocks != 0)\r
+    {\r
+      memcpy(blocks, p->blocks, p->numBlocks * sizeof(CXzBlockSizes));\r
+      Xz_Free(p, alloc);\r
+    }\r
+    p->blocks = blocks;\r
+    p->numBlocksAllocated = num;\r
+  }\r
+  {\r
+    CXzBlockSizes *block = &p->blocks[p->numBlocks++];\r
+    block->totalSize = totalSize;\r
+    block->unpackSize = unpackSize;\r
+  }\r
+  return SZ_OK;\r
+}\r
+\r
+/* ---------- CSeqCheckInStream ---------- */\r
+\r
+typedef struct\r
+{\r
+  ISeqInStream p;\r
+  ISeqInStream *realStream;\r
+  UInt64 processed;\r
+  CXzCheck check;\r
+} CSeqCheckInStream;\r
+\r
+void SeqCheckInStream_Init(CSeqCheckInStream *p, int mode)\r
+{\r
+  p->processed = 0;\r
+  XzCheck_Init(&p->check, mode);\r
+}\r
+\r
+void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest)\r
+{\r
+  XzCheck_Final(&p->check, digest);\r
+}\r
+\r
+static SRes SeqCheckInStream_Read(void *pp, void *data, size_t *size)\r
+{\r
+  CSeqCheckInStream *p = (CSeqCheckInStream *)pp;\r
+  SRes res = p->realStream->Read(p->realStream, data, size);\r
+  XzCheck_Update(&p->check, data, *size);\r
+  p->processed += *size;\r
+  return res;\r
+}\r
+\r
+/* ---------- CSeqSizeOutStream ---------- */\r
+\r
+typedef struct\r
+{\r
+  ISeqOutStream p;\r
+  ISeqOutStream *realStream;\r
+  UInt64 processed;\r
+} CSeqSizeOutStream;\r
+\r
+static size_t MyWrite(void *pp, const void *data, size_t size)\r
+{\r
+  CSeqSizeOutStream *p = (CSeqSizeOutStream *)pp;\r
+  size = p->realStream->Write(p->realStream, data, size);\r
+  p->processed += size;\r
+  return size;\r
+}\r
+\r
+/* ---------- CSeqInFilter ---------- */\r
+\r
+/*\r
+typedef struct _IFilter\r
+{\r
+  void *p;\r
+  void (*Free)(void *p, ISzAlloc *alloc);\r
+  SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAlloc *alloc);\r
+  void (*Init)(void *p);\r
+  size_t (*Filter)(void *p, Byte *data, SizeT destLen);\r
+} IFilter;\r
+\r
+#define FILT_BUF_SIZE (1 << 19)\r
+\r
+typedef struct\r
+{\r
+  ISeqInStream p;\r
+  ISeqInStream *realStream;\r
+  UInt32 x86State;\r
+  UInt32 ip;\r
+  UInt64 processed;\r
+  CXzCheck check;\r
+  Byte buf[FILT_BUF_SIZE];\r
+  UInt32 bufferPos;\r
+  UInt32 convertedPosBegin;\r
+  UInt32 convertedPosEnd;\r
+  IFilter *filter;\r
+} CSeqInFilter;\r
+\r
+static SRes SeqInFilter_Read(void *pp, void *data, size_t *size)\r
+{\r
+  CSeqInFilter *p = (CSeqInFilter *)pp;\r
+  size_t remSize = *size;\r
+  *size = 0;\r
+\r
+  while (remSize > 0)\r
+  {\r
+    int i;\r
+    if (p->convertedPosBegin != p->convertedPosEnd)\r
+    {\r
+      UInt32 sizeTemp = p->convertedPosEnd - p->convertedPosBegin;\r
+      if (remSize < sizeTemp)\r
+        sizeTemp = (UInt32)remSize;\r
+      memmove(data, p->buf + p->convertedPosBegin, sizeTemp);\r
+      p->convertedPosBegin += sizeTemp;\r
+      data = (void *)((Byte *)data + sizeTemp);\r
+      remSize -= sizeTemp;\r
+      *size += sizeTemp;\r
+      break;\r
+    }\r
+    for (i = 0; p->convertedPosEnd + i < p->bufferPos; i++)\r
+      p->buf[i] = p->buf[i + p->convertedPosEnd];\r
+    p->bufferPos = i;\r
+    p->convertedPosBegin = p->convertedPosEnd = 0;\r
+    {\r
+      size_t processedSizeTemp = FILT_BUF_SIZE - p->bufferPos;\r
+      RINOK(p->realStream->Read(p->realStream, p->buf + p->bufferPos, &processedSizeTemp));\r
+      p->bufferPos = p->bufferPos + (UInt32)processedSizeTemp;\r
+    }\r
+    p->convertedPosEnd = (UInt32)p->filter->Filter(p->filter->p, p->buf, p->bufferPos);\r
+    if (p->convertedPosEnd == 0)\r
+    {\r
+      if (p->bufferPos == 0)\r
+        break;\r
+      else\r
+      {\r
+        p->convertedPosEnd = p->bufferPos;\r
+        continue;\r
+      }\r
+    }\r
+    if (p->convertedPosEnd > p->bufferPos)\r
+    {\r
+      for (; p->bufferPos < p->convertedPosEnd; p->bufferPos++)\r
+        p->buf[p->bufferPos] = 0;\r
+      p->convertedPosEnd = (UInt32)p->filter->Filter(p->filter->p, p->buf, p->bufferPos);\r
+    }\r
+  }\r
+  return SZ_OK;\r
+}\r
+*/\r
+\r
+/*\r
+typedef struct\r
+{\r
+  ISeqInStream p;\r
+  ISeqInStream *realStream;\r
+  CMixCoder mixCoder;\r
+  Byte buf[FILT_BUF_SIZE];\r
+  UInt32 bufPos;\r
+  UInt32 bufSize;\r
+} CMixCoderSeqInStream;\r
+\r
+static SRes CMixCoderSeqInStream_Read(void *pp, void *data, size_t *size)\r
+{\r
+  CMixCoderSeqInStream *p = (CMixCoderSeqInStream *)pp;\r
+  SRes res = SZ_OK;\r
+  size_t remSize = *size;\r
+  *size = 0;\r
+  while (remSize > 0)\r
+  {\r
+    if (p->bufPos == p->bufSize)\r
+    {\r
+      size_t curSize;\r
+      p->bufPos = p->bufSize = 0;\r
+      if (*size != 0)\r
+        break;\r
+      curSize = FILT_BUF_SIZE;\r
+      RINOK(p->realStream->Read(p->realStream, p->buf, &curSize));\r
+      p->bufSize = (UInt32)curSize;\r
+    }\r
+    {\r
+      SizeT destLen = remSize;\r
+      SizeT srcLen = p->bufSize - p->bufPos;\r
+      res = MixCoder_Code(&p->mixCoder, data, &destLen, p->buf + p->bufPos, &srcLen, 0);\r
+      data = (void *)((Byte *)data + destLen);\r
+      remSize -= destLen;\r
+      *size += destLen;\r
+      p->bufPos += srcLen;\r
+    }\r
+  }\r
+  return res;\r
+}\r
+*/\r
+\r
+#ifdef USE_SUBBLOCK\r
+typedef struct\r
+{\r
+  ISeqInStream p;\r
+  CSubblockEnc sb;\r
+  UInt64 processed;\r
+} CSbEncInStream;\r
+\r
+void SbEncInStream_Init(CSbEncInStream *p)\r
+{\r
+  p->processed = 0;\r
+  SubblockEnc_Init(&p->sb);\r
+}\r
+\r
+static SRes SbEncInStream_Read(void *pp, void *data, size_t *size)\r
+{\r
+  CSbEncInStream *p = (CSbEncInStream *)pp;\r
+  SRes res = SubblockEnc_Read(&p->sb, data, size);\r
+  p->processed += *size;\r
+  return res;\r
+}\r
+#endif\r
+\r
+typedef struct\r
+{\r
+  /* CMixCoderSeqInStream inStream; */\r
+  CLzma2EncHandle lzma2;\r
+  #ifdef USE_SUBBLOCK\r
+  CSbEncInStream sb;\r
+  #endif\r
+  ISzAlloc *alloc;\r
+  ISzAlloc *bigAlloc;\r
+} CLzma2WithFilters;\r
+\r
+\r
+static void Lzma2WithFilters_Construct(CLzma2WithFilters *p, ISzAlloc *alloc, ISzAlloc *bigAlloc)\r
+{\r
+  p->alloc = alloc;\r
+  p->bigAlloc = bigAlloc;\r
+  p->lzma2 = NULL;\r
+  #ifdef USE_SUBBLOCK\r
+  p->sb.p.Read = SbEncInStream_Read;\r
+  SubblockEnc_Construct(&p->sb.sb, p->alloc);\r
+  #endif\r
+}\r
+\r
+static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p)\r
+{\r
+  p->lzma2 = Lzma2Enc_Create(p->alloc, p->bigAlloc);\r
+  if (p->lzma2 == 0)\r
+    return SZ_ERROR_MEM;\r
+  return SZ_OK;\r
+}\r
+\r
+static void Lzma2WithFilters_Free(CLzma2WithFilters *p)\r
+{\r
+  #ifdef USE_SUBBLOCK\r
+  SubblockEnc_Free(&p->sb.sb);\r
+  #endif\r
+  if (p->lzma2)\r
+  {\r
+    Lzma2Enc_Destroy(p->lzma2);\r
+    p->lzma2 = NULL;\r
+  }\r
+}\r
+\r
+static SRes Xz_Compress(CXzStream *xz,\r
+    CLzma2WithFilters *lzmaf,\r
+    ISeqOutStream *outStream,\r
+    ISeqInStream *inStream,\r
+    const CLzma2EncProps *lzma2Props,\r
+    Bool useSubblock,\r
+    ICompressProgress *progress)\r
+{\r
+  xz->flags = XZ_CHECK_CRC32;\r
+\r
+  RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, lzma2Props));\r
+  RINOK(Xz_WriteHeader(xz->flags, outStream));\r
+\r
+  {\r
+    CSeqCheckInStream checkInStream;\r
+    CSeqSizeOutStream seqSizeOutStream;\r
+    CXzBlock block;\r
+    int filterIndex = 0;\r
+    \r
+    XzBlock_ClearFlags(&block);\r
+    XzBlock_SetNumFilters(&block, 1 + (useSubblock ? 1 : 0));\r
+    \r
+    if (useSubblock)\r
+    {\r
+      CXzFilter *f = &block.filters[filterIndex++];\r
+      f->id = XZ_ID_Subblock;\r
+      f->propsSize = 0;\r
+    }\r
+\r
+    {\r
+      CXzFilter *f = &block.filters[filterIndex++];\r
+      f->id = XZ_ID_LZMA2;\r
+      f->propsSize = 1;\r
+      f->props[0] = Lzma2Enc_WriteProperties(lzmaf->lzma2);\r
+    }\r
+\r
+    seqSizeOutStream.p.Write = MyWrite;\r
+    seqSizeOutStream.realStream = outStream;\r
+    seqSizeOutStream.processed = 0;\r
+    \r
+    RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.p));\r
+    \r
+    checkInStream.p.Read = SeqCheckInStream_Read;\r
+    checkInStream.realStream = inStream;\r
+    SeqCheckInStream_Init(&checkInStream, XzFlags_GetCheckType(xz->flags));\r
+    \r
+    #ifdef USE_SUBBLOCK\r
+    if (useSubblock)\r
+    {\r
+      lzmaf->sb.sb.inStream = &checkInStream.p;\r
+      SubblockEnc_Init(&lzmaf->sb.sb);\r
+    }\r
+    #endif\r
+    \r
+    {\r
+      UInt64 packPos = seqSizeOutStream.processed;\r
+      SRes res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p,\r
+        #ifdef USE_SUBBLOCK\r
+        useSubblock ? &lzmaf->sb.p:\r
+        #endif\r
+        &checkInStream.p,\r
+        progress);\r
+      RINOK(res);\r
+      block.unpackSize = checkInStream.processed;\r
+      block.packSize = seqSizeOutStream.processed - packPos;\r
+    }\r
+\r
+    {\r
+      unsigned padSize = 0;\r
+      Byte buf[128];\r
+      while((((unsigned)block.packSize + padSize) & 3) != 0)\r
+        buf[padSize++] = 0;\r
+      SeqCheckInStream_GetDigest(&checkInStream, buf + padSize);\r
+      RINOK(WriteBytes(&seqSizeOutStream.p, buf, padSize + XzFlags_GetCheckSize(xz->flags)));\r
+      RINOK(Xz_AddIndexRecord(xz, block.unpackSize, seqSizeOutStream.processed - padSize, &g_Alloc));\r
+    }\r
+  }\r
+  return Xz_WriteFooter(xz, outStream);\r
+}\r
+\r
+SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,\r
+    const CLzma2EncProps *lzma2Props, Bool useSubblock,\r
+    ICompressProgress *progress)\r
+{\r
+  SRes res;\r
+  CXzStream xz;\r
+  CLzma2WithFilters lzmaf;\r
+  Xz_Construct(&xz);\r
+  Lzma2WithFilters_Construct(&lzmaf, &g_Alloc, &g_BigAlloc);\r
+  res = Lzma2WithFilters_Create(&lzmaf);\r
+  if (res == SZ_OK)\r
+    res = Xz_Compress(&xz, &lzmaf, outStream, inStream,\r
+        lzma2Props, useSubblock, progress);\r
+  Lzma2WithFilters_Free(&lzmaf);\r
+  Xz_Free(&xz, &g_Alloc);\r
+  return res;\r
+}\r
+\r
+SRes Xz_EncodeEmpty(ISeqOutStream *outStream)\r
+{\r
+  SRes res;\r
+  CXzStream xz;\r
+  Xz_Construct(&xz);\r
+  res = Xz_WriteHeader(xz.flags, outStream);\r
+  if (res == SZ_OK)\r
+    res = Xz_WriteFooter(&xz, outStream);\r
+  Xz_Free(&xz, &g_Alloc);\r
+  return res;\r
+}\r
diff --git a/C/XzEnc.h b/C/XzEnc.h
new file mode 100755 (executable)
index 0000000..aad9aa4
--- /dev/null
+++ b/C/XzEnc.h
@@ -0,0 +1,25 @@
+/* XzEnc.h -- Xz Encode\r
+2009-04-15 : Igor Pavlov : Public domain */\r
+\r
+#ifndef __XZ_ENC_H\r
+#define __XZ_ENC_H\r
+\r
+#include "Lzma2Enc.h"\r
+\r
+#include "Xz.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,\r
+    const CLzma2EncProps *lzma2Props, Bool useSubblock,\r
+    ICompressProgress *progress);\r
+\r
+SRes Xz_EncodeEmpty(ISeqOutStream *outStream);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/C/XzIn.c b/C/XzIn.c
new file mode 100755 (executable)
index 0000000..356d019
--- /dev/null
+++ b/C/XzIn.c
@@ -0,0 +1,306 @@
+/* XzIn.c - Xz input\r
+2009-06-19 : Igor Pavlov : Public domain */\r
+\r
+#include <string.h>\r
+\r
+#include "7zCrc.h"\r
+#include "CpuArch.h"\r
+#include "Xz.h"\r
+\r
+SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream)\r
+{\r
+  Byte sig[XZ_STREAM_HEADER_SIZE];\r
+  RINOK(SeqInStream_Read2(inStream, sig, XZ_STREAM_HEADER_SIZE, SZ_ERROR_NO_ARCHIVE));\r
+  if (memcmp(sig, XZ_SIG, XZ_SIG_SIZE) != 0)\r
+    return SZ_ERROR_NO_ARCHIVE;\r
+  return Xz_ParseHeader(p, sig);\r
+}\r
+\r
+#define READ_VARINT_AND_CHECK(buf, pos, size, res) \\r
+  { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \\r
+  if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }\r
+\r
+SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt32 *headerSizeRes)\r
+{\r
+  Byte header[XZ_BLOCK_HEADER_SIZE_MAX];\r
+  unsigned headerSize;\r
+  *headerSizeRes = 0;\r
+  RINOK(SeqInStream_ReadByte(inStream, &header[0]));\r
+  headerSize = ((unsigned)header[0] << 2) + 4;\r
+  if (headerSize == 0)\r
+  {\r
+    *headerSizeRes = 1;\r
+    *isIndex = True;\r
+    return SZ_OK;\r
+  }\r
+\r
+  *isIndex = False;\r
+  *headerSizeRes = headerSize;\r
+  RINOK(SeqInStream_Read(inStream, header + 1, headerSize - 1));\r
+  return XzBlock_Parse(p, header);\r
+}\r
+\r
+#define ADD_SIZE_CHECH(size, val) \\r
+  { UInt64 newSize = size + (val); if (newSize < size) return XZ_SIZE_OVERFLOW; size = newSize; }\r
+\r
+UInt64 Xz_GetUnpackSize(const CXzStream *p)\r
+{\r
+  UInt64 size = 0;\r
+  size_t i;\r
+  for (i = 0; i < p->numBlocks; i++)\r
+    ADD_SIZE_CHECH(size, p->blocks[i].unpackSize);\r
+  return size;\r
+}\r
+\r
+UInt64 Xz_GetPackSize(const CXzStream *p)\r
+{\r
+  UInt64 size = 0;\r
+  size_t i;\r
+  for (i = 0; i < p->numBlocks; i++)\r
+    ADD_SIZE_CHECH(size, (p->blocks[i].totalSize + 3) & ~(UInt64)3);\r
+  return size;\r
+}\r
+\r
+/*\r
+SRes XzBlock_ReadFooter(CXzBlock *p, CXzStreamFlags f, ISeqInStream *inStream)\r
+{\r
+  return SeqInStream_Read(inStream, p->check, XzFlags_GetCheckSize(f));\r
+}\r
+*/\r
+\r
+static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc *alloc)\r
+{\r
+  size_t i, numBlocks, crcStartPos, pos = 1;\r
+  UInt32 crc;\r
+\r
+  if (size < 5 || buf[0] != 0)\r
+    return SZ_ERROR_ARCHIVE;\r
+\r
+  size -= 4;\r
+  crc = CrcCalc(buf, size);\r
+  if (crc != GetUi32(buf + size))\r
+    return SZ_ERROR_ARCHIVE;\r
+\r
+  {\r
+    UInt64 numBlocks64;\r
+    READ_VARINT_AND_CHECK(buf, pos, size, &numBlocks64);\r
+    numBlocks = (size_t)numBlocks64;\r
+    if (numBlocks != numBlocks64 || numBlocks * 2 > size)\r
+      return SZ_ERROR_ARCHIVE;\r
+  }\r
+  \r
+  crcStartPos = pos;\r
+  Xz_Free(p, alloc);\r
+  if (numBlocks != 0)\r
+  {\r
+    p->numBlocks = numBlocks;\r
+    p->numBlocksAllocated = numBlocks;\r
+    p->blocks = alloc->Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks);\r
+    if (p->blocks == 0)\r
+      return SZ_ERROR_MEM;\r
+    for (i = 0; i < numBlocks; i++)\r
+    {\r
+      CXzBlockSizes *block = &p->blocks[i];\r
+      READ_VARINT_AND_CHECK(buf, pos, size, &block->totalSize);\r
+      READ_VARINT_AND_CHECK(buf, pos, size, &block->unpackSize);\r
+      if (block->totalSize == 0)\r
+        return SZ_ERROR_ARCHIVE;\r
+    }\r
+  }\r
+  while ((pos & 3) != 0)\r
+    if (buf[pos++] != 0)\r
+      return SZ_ERROR_ARCHIVE;\r
+  return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;\r
+}\r
+\r
+static SRes Xz_ReadIndex(CXzStream *p, ILookInStream *stream, UInt64 indexSize, ISzAlloc *alloc)\r
+{\r
+  SRes res;\r
+  size_t size;\r
+  Byte *buf;\r
+  if (indexSize > ((UInt32)1 << 31))\r
+    return SZ_ERROR_UNSUPPORTED;\r
+  size = (size_t)indexSize;\r
+  if (size != indexSize)\r
+    return SZ_ERROR_UNSUPPORTED;\r
+  buf = alloc->Alloc(alloc, size);\r
+  if (buf == 0)\r
+    return SZ_ERROR_MEM;\r
+  res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED);\r
+  if (res == SZ_OK)\r
+    res = Xz_ReadIndex2(p, buf, size, alloc);\r
+  alloc->Free(alloc, buf);\r
+  return res;\r
+}\r
+\r
+static SRes SeekFromCur(ILookInStream *inStream, Int64 *res)\r
+{\r
+  return inStream->Seek(inStream, res, SZ_SEEK_CUR);\r
+}\r
+\r
+static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOffset, ISzAlloc *alloc)\r
+{\r
+  UInt64 indexSize;\r
+  Byte buf[XZ_STREAM_FOOTER_SIZE];\r
+\r
+  if ((*startOffset & 3) != 0 || *startOffset < XZ_STREAM_FOOTER_SIZE)\r
+    return SZ_ERROR_NO_ARCHIVE;\r
+  *startOffset = -XZ_STREAM_FOOTER_SIZE;\r
+  RINOK(SeekFromCur(stream, startOffset));\r
+\r
+  RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE));\r
+  \r
+  if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0)\r
+  {\r
+    Int64 i = 0;\r
+    *startOffset += XZ_STREAM_FOOTER_SIZE;\r
+    for (;;)\r
+    {\r
+      int j;\r
+      size_t processedSize;\r
+      #define TEMP_BUF_SIZE (1 << 10)\r
+      Byte tempBuf[TEMP_BUF_SIZE];\r
+      if (*startOffset < XZ_STREAM_FOOTER_SIZE || i > (1 << 16))\r
+        return SZ_ERROR_NO_ARCHIVE;\r
+      processedSize = (*startOffset > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)*startOffset;\r
+      i += processedSize;\r
+      *startOffset = -(Int64)processedSize;\r
+      RINOK(SeekFromCur(stream, startOffset));\r
+      RINOK(LookInStream_Read2(stream, tempBuf, processedSize, SZ_ERROR_NO_ARCHIVE));\r
+      for (j = (int)processedSize; j >= 0; j--)\r
+        if (tempBuf[j -1] != 0)\r
+          break;\r
+      if (j != 0)\r
+      {\r
+        if ((j & 3) != 0)\r
+          return SZ_ERROR_NO_ARCHIVE;\r
+        *startOffset += j;\r
+        if (*startOffset < XZ_STREAM_FOOTER_SIZE)\r
+          return SZ_ERROR_NO_ARCHIVE;\r
+        *startOffset -= XZ_STREAM_FOOTER_SIZE;\r
+        RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET));\r
+        RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE));\r
+        if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0)\r
+          return SZ_ERROR_NO_ARCHIVE;\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  \r
+  p->flags = (CXzStreamFlags)GetBe16(buf + 8);\r
+\r
+  if (!XzFlags_IsSupported(p->flags))\r
+    return SZ_ERROR_UNSUPPORTED;\r
+\r
+  if (GetUi32(buf) != CrcCalc(buf + 4, 6))\r
+    return SZ_ERROR_ARCHIVE;\r
+\r
+  indexSize = ((UInt64)GetUi32(buf + 4) + 1) << 2;\r
+\r
+  *startOffset = -(Int64)(indexSize + XZ_STREAM_FOOTER_SIZE);\r
+  RINOK(SeekFromCur(stream, startOffset));\r
+\r
+  RINOK(Xz_ReadIndex(p, stream, indexSize, alloc));\r
+\r
+  {\r
+    UInt64 totalSize = Xz_GetPackSize(p);\r
+    UInt64 sum = XZ_STREAM_HEADER_SIZE + totalSize + indexSize;\r
+    if (totalSize == XZ_SIZE_OVERFLOW ||\r
+      sum >= ((UInt64)1 << 63) ||\r
+      totalSize >= ((UInt64)1 << 63))\r
+      return SZ_ERROR_ARCHIVE;\r
+    *startOffset = -(Int64)sum;\r
+    RINOK(SeekFromCur(stream, startOffset));\r
+  }\r
+  {\r
+    CXzStreamFlags headerFlags;\r
+    CSecToRead secToRead;\r
+    SecToRead_CreateVTable(&secToRead);\r
+    secToRead.realStream = stream;\r
+\r
+    RINOK(Xz_ReadHeader(&headerFlags, &secToRead.s));\r
+    return (p->flags == headerFlags) ? SZ_OK : SZ_ERROR_ARCHIVE;\r
+  }\r
+}\r
+\r
+\r
+/* ---------- Xz Streams ---------- */\r
+\r
+void Xzs_Construct(CXzs *p)\r
+{\r
+  p->num = p->numAllocated = 0;\r
+  p->streams = 0;\r
+}\r
+\r
+void Xzs_Free(CXzs *p, ISzAlloc *alloc)\r
+{\r
+  size_t i;\r
+  for (i = 0; i < p->num; i++)\r
+    Xz_Free(&p->streams[i], alloc);\r
+  alloc->Free(alloc, p->streams);\r
+  p->num = p->numAllocated = 0;\r
+  p->streams = 0;\r
+}\r
+\r
+UInt64 Xzs_GetNumBlocks(const CXzs *p)\r
+{\r
+  UInt64 num = 0;\r
+  size_t i;\r
+  for (i = 0; i < p->num; i++)\r
+    num += p->streams[i].numBlocks;\r
+  return num;\r
+}\r
+\r
+UInt64 Xzs_GetUnpackSize(const CXzs *p)\r
+{\r
+  UInt64 size = 0;\r
+  size_t i;\r
+  for (i = 0; i < p->num; i++)\r
+    ADD_SIZE_CHECH(size, Xz_GetUnpackSize(&p->streams[i]));\r
+  return size;\r
+}\r
+\r
+/*\r
+UInt64 Xzs_GetPackSize(const CXzs *p)\r
+{\r
+  UInt64 size = 0;\r
+  size_t i;\r
+  for (i = 0; i < p->num; i++)\r
+    ADD_SIZE_CHECH(size, Xz_GetTotalSize(&p->streams[i]));\r
+  return size;\r
+}\r
+*/\r
+\r
+SRes Xzs_ReadBackward(CXzs *p, ILookInStream *stream, Int64 *startOffset, ICompressProgress *progress, ISzAlloc *alloc)\r
+{\r
+  Int64 endOffset = 0;\r
+  RINOK(stream->Seek(stream, &endOffset, SZ_SEEK_END));\r
+  *startOffset = endOffset;\r
+  for (;;)\r
+  {\r
+    CXzStream st;\r
+    SRes res;\r
+    Xz_Construct(&st);\r
+    res = Xz_ReadBackward(&st, stream, startOffset, alloc);\r
+    st.startOffset = *startOffset;\r
+    RINOK(res);\r
+    if (p->num == p->numAllocated)\r
+    {\r
+      size_t newNum = p->num + p->num / 4 + 1;\r
+      Byte *data = (Byte *)alloc->Alloc(alloc, newNum * sizeof(CXzStream));\r
+      if (data == 0)\r
+        return SZ_ERROR_MEM;\r
+      p->numAllocated = newNum;\r
+      memcpy(data, p->streams, p->num * sizeof(CXzStream));\r
+      alloc->Free(alloc, p->streams);\r
+      p->streams = (CXzStream *)data;\r
+    }\r
+    p->streams[p->num++] = st;\r
+    if (*startOffset == 0)\r
+      break;\r
+    RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET));\r
+    if (progress && progress->Progress(progress, endOffset - *startOffset, (UInt64)(Int64)-1) != SZ_OK)\r
+      return SZ_ERROR_PROGRESS;\r
+  }\r
+  return SZ_OK;\r
+}\r
diff --git a/CPP/7zip/Aes.mak b/CPP/7zip/Aes.mak
new file mode 100755 (executable)
index 0000000..7ce28cf
--- /dev/null
@@ -0,0 +1,7 @@
+C_OBJS = $(C_OBJS) \\r
+  $O\Aes.obj\r
+\r
+!IF "$(CPU)" != "IA64" && "$(CPU)" != "MIPS" && "$(CPU)" != "ARM"\r
+ASM_OBJS = $(ASM_OBJS) \\r
+  $O\AesOpt.obj\r
+!ENDIF\r
diff --git a/CPP/7zip/Archive/7z/7z.dsp b/CPP/7zip/Archive/7z/7z.dsp
new file mode 100755 (executable)
index 0000000..46d41b5
--- /dev/null
@@ -0,0 +1,650 @@
+# Microsoft Developer Studio Project File - Name="7z" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
+\r
+CFG=7z - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "7z.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "7z.mak" CFG="7z - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "7z - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE "7z - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+MTL=midl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 1\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /YX /FD /c\r
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "EXTERNAL_CODECS" /Yu"StdAfx.h" /FD /c\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-zip\Formats\7z.dll" /opt:NOWIN98\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 1\r
+# PROP Target_Dir ""\r
+# 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\r
+# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "EXTERNAL_CODECS" /Yu"StdAfx.h" /FD /GZ /c\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-zip\Formats\7z.dll" /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "7z - Win32 Release"\r
+# Name "7z - Win32 Debug"\r
+# Begin Group "Spec"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\Archive.def\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\ArchiveExports.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\DllExports.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\resource.rc\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.cpp\r
+# ADD CPP /Yc"StdAfx.h"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Engine"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\7zCompressionMode.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zCompressionMode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zDecode.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zDecode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zEncode.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zEncode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zExtract.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zFolderInStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zFolderInStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zFolderOutStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zFolderOutStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zHandlerOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zHeader.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zHeader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zItem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zOut.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zProperties.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zProperties.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zSpecStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zSpecStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zUpdate.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zUpdate.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Interface"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\IArchive.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\ICoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\IMyUnknown.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\IPassword.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\IProgress.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\IStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\PropID.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Buffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\DynamicBuffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringToInt.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringToInt.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Archive Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\CoderMixer2.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\CoderMixer2.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\CoderMixer2MT.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\CoderMixer2MT.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\CrossThreadProgress.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\CrossThreadProgress.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\HandlerOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\HandlerOut.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\InStreamWithCRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\InStreamWithCRC.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ItemNameUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ItemNameUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\MultiStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\MultiStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\OutStreamWithCRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\OutStreamWithCRC.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ParseProperties.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ParseProperties.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "7-Zip Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\InOutTempBuffer.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\InOutTempBuffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LimitedStreams.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LimitedStreams.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LockedStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LockedStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\MethodId.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\MethodId.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\MethodProps.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\MethodProps.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OutBuffer.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OutBuffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\RegisterArc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\RegisterCodec.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamBinder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamBinder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamObjects.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamObjects.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\VirtThread.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\VirtThread.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Windows"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Handle.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\System.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\System.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Thread.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Compress"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyCoder.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "C"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrcOpt.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.h\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/CPP/7zip/Archive/7z/7z.dsw b/CPP/7zip/Archive/7z/7z.dsw
new file mode 100755 (executable)
index 0000000..5b0e36c
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "7z"=".\7z.dsp" - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.cpp b/CPP/7zip/Archive/7z/7zCompressionMode.cpp
new file mode 100755 (executable)
index 0000000..232c638
--- /dev/null
@@ -0,0 +1,3 @@
+// CompressionMethod.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h
new file mode 100755 (executable)
index 0000000..a388e1f
--- /dev/null
@@ -0,0 +1,50 @@
+// 7zCompressionMode.h\r
+\r
+#ifndef __7Z_COMPRESSION_MODE_H\r
+#define __7Z_COMPRESSION_MODE_H\r
+\r
+#include "../../../Common/MyString.h"\r
+\r
+#include "../../../Windows/PropVariant.h"\r
+\r
+#include "../../Common/MethodProps.h"\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+struct CMethodFull: public CMethod\r
+{\r
+  UInt32 NumInStreams;\r
+  UInt32 NumOutStreams;\r
+  bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }\r
+};\r
+\r
+struct CBind\r
+{\r
+  UInt32 InCoder;\r
+  UInt32 InStream;\r
+  UInt32 OutCoder;\r
+  UInt32 OutStream;\r
+};\r
+\r
+struct CCompressionMethodMode\r
+{\r
+  CObjectVector<CMethodFull> Methods;\r
+  CRecordVector<CBind> Binds;\r
+  #ifndef _7ZIP_ST\r
+  UInt32 NumThreads;\r
+  #endif\r
+  bool PasswordIsDefined;\r
+  UString Password;\r
+\r
+  bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }\r
+  CCompressionMethodMode(): PasswordIsDefined(false)\r
+      #ifndef _7ZIP_ST\r
+      , NumThreads(1)\r
+      #endif\r
+  {}\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp
new file mode 100755 (executable)
index 0000000..3fcdd5f
--- /dev/null
@@ -0,0 +1,332 @@
+// 7zDecode.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/LimitedStreams.h"\r
+#include "../../Common/LockedStream.h"\r
+#include "../../Common/ProgressUtils.h"\r
+#include "../../Common/StreamObjects.h"\r
+\r
+#include "7zDecode.h"\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,\r
+    CBindInfoEx &bindInfo)\r
+{\r
+  bindInfo.Clear();\r
+  int i;\r
+  for (i = 0; i < folder.BindPairs.Size(); i++)\r
+  {\r
+    NCoderMixer::CBindPair bindPair;\r
+    bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;\r
+    bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;\r
+    bindInfo.BindPairs.Add(bindPair);\r
+  }\r
+  UInt32 outStreamIndex = 0;\r
+  for (i = 0; i < folder.Coders.Size(); i++)\r
+  {\r
+    NCoderMixer::CCoderStreamsInfo coderStreamsInfo;\r
+    const CCoderInfo &coderInfo = folder.Coders[i];\r
+    coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;\r
+    coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;\r
+    bindInfo.Coders.Add(coderStreamsInfo);\r
+    bindInfo.CoderMethodIDs.Add(coderInfo.MethodID);\r
+    for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)\r
+      if (folder.FindBindPairForOutStream(outStreamIndex) < 0)\r
+        bindInfo.OutStreams.Add(outStreamIndex);\r
+  }\r
+  for (i = 0; i < folder.PackStreams.Size(); i++)\r
+    bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]);\r
+}\r
+\r
+static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1,\r
+    const NCoderMixer::CCoderStreamsInfo &a2)\r
+{\r
+  return (a1.NumInStreams == a2.NumInStreams) &&\r
+    (a1.NumOutStreams == a2.NumOutStreams);\r
+}\r
+\r
+static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2)\r
+{\r
+  return (a1.InIndex == a2.InIndex) &&\r
+    (a1.OutIndex == a2.OutIndex);\r
+}\r
+\r
+static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)\r
+{\r
+  if (a1.Coders.Size() != a2.Coders.Size())\r
+    return false;\r
+  int i;\r
+  for (i = 0; i < a1.Coders.Size(); i++)\r
+    if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))\r
+      return false;\r
+  if (a1.BindPairs.Size() != a2.BindPairs.Size())\r
+    return false;\r
+  for (i = 0; i < a1.BindPairs.Size(); i++)\r
+    if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))\r
+      return false;\r
+  for (i = 0; i < a1.CoderMethodIDs.Size(); i++)\r
+    if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])\r
+      return false;\r
+  if (a1.InStreams.Size() != a2.InStreams.Size())\r
+    return false;\r
+  if (a1.OutStreams.Size() != a2.OutStreams.Size())\r
+    return false;\r
+  return true;\r
+}\r
+\r
+CDecoder::CDecoder(bool multiThread)\r
+{\r
+  #ifndef _ST_MODE\r
+  multiThread = true;\r
+  #endif\r
+  _multiThread = multiThread;\r
+  _bindInfoExPrevIsDefined = false;\r
+}\r
+\r
+HRESULT CDecoder::Decode(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    IInStream *inStream,\r
+    UInt64 startPos,\r
+    const UInt64 *packSizes,\r
+    const CFolder &folderInfo,\r
+    ISequentialOutStream *outStream,\r
+    ICompressProgressInfo *compressProgress\r
+    #ifndef _NO_CRYPTO\r
+    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined\r
+    #endif\r
+    #if !defined(_7ZIP_ST) && !defined(_SFX)\r
+    , bool mtMode, UInt32 numThreads\r
+    #endif\r
+    )\r
+{\r
+  if (!folderInfo.CheckStructure())\r
+    return E_NOTIMPL;\r
+  #ifndef _NO_CRYPTO\r
+  passwordIsDefined = false;\r
+  #endif\r
+  CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;\r
+  \r
+  CLockedInStream lockedInStream;\r
+  lockedInStream.Init(inStream);\r
+  \r
+  for (int j = 0; j < folderInfo.PackStreams.Size(); j++)\r
+  {\r
+    CLockedSequentialInStreamImp *lockedStreamImpSpec = new\r
+        CLockedSequentialInStreamImp;\r
+    CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;\r
+    lockedStreamImpSpec->Init(&lockedInStream, startPos);\r
+    startPos += packSizes[j];\r
+    \r
+    CLimitedSequentialInStream *streamSpec = new\r
+        CLimitedSequentialInStream;\r
+    CMyComPtr<ISequentialInStream> inStream = streamSpec;\r
+    streamSpec->SetStream(lockedStreamImp);\r
+    streamSpec->Init(packSizes[j]);\r
+    inStreams.Add(inStream);\r
+  }\r
+  \r
+  int numCoders = folderInfo.Coders.Size();\r
+  \r
+  CBindInfoEx bindInfo;\r
+  ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);\r
+  bool createNewCoders;\r
+  if (!_bindInfoExPrevIsDefined)\r
+    createNewCoders = true;\r
+  else\r
+    createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);\r
+  if (createNewCoders)\r
+  {\r
+    int i;\r
+    _decoders.Clear();\r
+    // _decoders2.Clear();\r
+    \r
+    _mixerCoder.Release();\r
+\r
+    if (_multiThread)\r
+    {\r
+      _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT;\r
+      _mixerCoder = _mixerCoderMTSpec;\r
+      _mixerCoderCommon = _mixerCoderMTSpec;\r
+    }\r
+    else\r
+    {\r
+      #ifdef _ST_MODE\r
+      _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST;\r
+      _mixerCoder = _mixerCoderSTSpec;\r
+      _mixerCoderCommon = _mixerCoderSTSpec;\r
+      #endif\r
+    }\r
+    RINOK(_mixerCoderCommon->SetBindInfo(bindInfo));\r
+    \r
+    for (i = 0; i < numCoders; i++)\r
+    {\r
+      const CCoderInfo &coderInfo = folderInfo.Coders[i];\r
+\r
+  \r
+      CMyComPtr<ICompressCoder> decoder;\r
+      CMyComPtr<ICompressCoder2> decoder2;\r
+      RINOK(CreateCoder(\r
+          EXTERNAL_CODECS_LOC_VARS\r
+          coderInfo.MethodID, decoder, decoder2, false));\r
+      CMyComPtr<IUnknown> decoderUnknown;\r
+      if (coderInfo.IsSimpleCoder())\r
+      {\r
+        if (decoder == 0)\r
+          return E_NOTIMPL;\r
+\r
+        decoderUnknown = (IUnknown *)decoder;\r
+        \r
+        if (_multiThread)\r
+          _mixerCoderMTSpec->AddCoder(decoder);\r
+        #ifdef _ST_MODE\r
+        else\r
+          _mixerCoderSTSpec->AddCoder(decoder, false);\r
+        #endif\r
+      }\r
+      else\r
+      {\r
+        if (decoder2 == 0)\r
+          return E_NOTIMPL;\r
+        decoderUnknown = (IUnknown *)decoder2;\r
+        if (_multiThread)\r
+          _mixerCoderMTSpec->AddCoder2(decoder2);\r
+        #ifdef _ST_MODE\r
+        else\r
+          _mixerCoderSTSpec->AddCoder2(decoder2, false);\r
+        #endif\r
+      }\r
+      _decoders.Add(decoderUnknown);\r
+      #ifdef EXTERNAL_CODECS\r
+      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;\r
+      decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);\r
+      if (setCompressCodecsInfo)\r
+      {\r
+        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));\r
+      }\r
+      #endif\r
+    }\r
+    _bindInfoExPrev = bindInfo;\r
+    _bindInfoExPrevIsDefined = true;\r
+  }\r
+  int i;\r
+  _mixerCoderCommon->ReInit();\r
+  \r
+  UInt32 packStreamIndex = 0, unpackStreamIndex = 0;\r
+  UInt32 coderIndex = 0;\r
+  // UInt32 coder2Index = 0;\r
+  \r
+  for (i = 0; i < numCoders; i++)\r
+  {\r
+    const CCoderInfo &coderInfo = folderInfo.Coders[i];\r
+    CMyComPtr<IUnknown> &decoder = _decoders[coderIndex];\r
+    \r
+    {\r
+      CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;\r
+      decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);\r
+      if (setDecoderProperties)\r
+      {\r
+        const CByteBuffer &props = coderInfo.Props;\r
+        size_t size = props.GetCapacity();\r
+        if (size > 0xFFFFFFFF)\r
+          return E_NOTIMPL;\r
+        // if (size > 0)\r
+        {\r
+          RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size));\r
+        }\r
+      }\r
+    }\r
+\r
+    #if !defined(_7ZIP_ST) && !defined(_SFX)\r
+    if (mtMode)\r
+    {\r
+      CMyComPtr<ICompressSetCoderMt> setCoderMt;\r
+      decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);\r
+      if (setCoderMt)\r
+      {\r
+        RINOK(setCoderMt->SetNumberOfThreads(numThreads));\r
+      }\r
+    }\r
+    #endif\r
+\r
+    #ifndef _NO_CRYPTO\r
+    {\r
+      CMyComPtr<ICryptoSetPassword> cryptoSetPassword;\r
+      decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);\r
+      if (cryptoSetPassword)\r
+      {\r
+        if (getTextPassword == 0)\r
+          return E_FAIL;\r
+        CMyComBSTR passwordBSTR;\r
+        RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR));\r
+        CByteBuffer buffer;\r
+        passwordIsDefined = true;\r
+        const UString password(passwordBSTR);\r
+        const UInt32 sizeInBytes = password.Length() * 2;\r
+        buffer.SetCapacity(sizeInBytes);\r
+        for (int i = 0; i < password.Length(); i++)\r
+        {\r
+          wchar_t c = password[i];\r
+          ((Byte *)buffer)[i * 2] = (Byte)c;\r
+          ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);\r
+        }\r
+        RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));\r
+      }\r
+    }\r
+    #endif\r
+\r
+    coderIndex++;\r
+    \r
+    UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;\r
+    UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;\r
+    CRecordVector<const UInt64 *> packSizesPointers;\r
+    CRecordVector<const UInt64 *> unpackSizesPointers;\r
+    packSizesPointers.Reserve(numInStreams);\r
+    unpackSizesPointers.Reserve(numOutStreams);\r
+    UInt32 j;\r
+    for (j = 0; j < numOutStreams; j++, unpackStreamIndex++)\r
+      unpackSizesPointers.Add(&folderInfo.UnpackSizes[unpackStreamIndex]);\r
+    \r
+    for (j = 0; j < numInStreams; j++, packStreamIndex++)\r
+    {\r
+      int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);\r
+      if (bindPairIndex >= 0)\r
+        packSizesPointers.Add(\r
+        &folderInfo.UnpackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]);\r
+      else\r
+      {\r
+        int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);\r
+        if (index < 0)\r
+          return E_FAIL;\r
+        packSizesPointers.Add(&packSizes[index]);\r
+      }\r
+    }\r
+    \r
+    _mixerCoderCommon->SetCoderInfo(i,\r
+        &packSizesPointers.Front(),\r
+        &unpackSizesPointers.Front());\r
+  }\r
+  UInt32 mainCoder, temp;\r
+  bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);\r
+\r
+  if (_multiThread)\r
+    _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);\r
+  /*\r
+  else\r
+    _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;\r
+  */\r
+  \r
+  if (numCoders == 0)\r
+    return 0;\r
+  CRecordVector<ISequentialInStream *> inStreamPointers;\r
+  inStreamPointers.Reserve(inStreams.Size());\r
+  for (i = 0; i < inStreams.Size(); i++)\r
+    inStreamPointers.Add(inStreams[i]);\r
+  ISequentialOutStream *outStreamPointer = outStream;\r
+  return _mixerCoder->Code(&inStreamPointers.Front(), NULL,\r
+    inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress);\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/7z/7zDecode.h b/CPP/7zip/Archive/7z/7zDecode.h
new file mode 100755 (executable)
index 0000000..da213a1
--- /dev/null
@@ -0,0 +1,68 @@
+// 7zDecode.h\r
+\r
+#ifndef __7Z_DECODE_H\r
+#define __7Z_DECODE_H\r
+\r
+#include "../../IStream.h"\r
+#include "../../IPassword.h"\r
+\r
+#include "../Common/CoderMixer2.h"\r
+#include "../Common/CoderMixer2MT.h"\r
+#ifdef _ST_MODE\r
+#include "../Common/CoderMixer2ST.h"\r
+#endif\r
+\r
+#include "../../Common/CreateCoder.h"\r
+\r
+#include "7zItem.h"\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+struct CBindInfoEx: public NCoderMixer::CBindInfo\r
+{\r
+  CRecordVector<CMethodId> CoderMethodIDs;\r
+  void Clear()\r
+  {\r
+    CBindInfo::Clear();\r
+    CoderMethodIDs.Clear();\r
+  }\r
+};\r
+\r
+class CDecoder\r
+{\r
+  bool _bindInfoExPrevIsDefined;\r
+  CBindInfoEx _bindInfoExPrev;\r
+  \r
+  bool _multiThread;\r
+  #ifdef _ST_MODE\r
+  NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec;\r
+  #endif\r
+  NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec;\r
+  NCoderMixer::CCoderMixer2 *_mixerCoderCommon;\r
+  \r
+  CMyComPtr<ICompressCoder2> _mixerCoder;\r
+  CObjectVector<CMyComPtr<IUnknown> > _decoders;\r
+  // CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2;\r
+public:\r
+  CDecoder(bool multiThread);\r
+  HRESULT Decode(\r
+      DECL_EXTERNAL_CODECS_LOC_VARS\r
+      IInStream *inStream,\r
+      UInt64 startPos,\r
+      const UInt64 *packSizes,\r
+      const CFolder &folder,\r
+      ISequentialOutStream *outStream,\r
+      ICompressProgressInfo *compressProgress\r
+      #ifndef _NO_CRYPTO\r
+      , ICryptoGetTextPassword *getTextPasswordSpec, bool &passwordIsDefined\r
+      #endif\r
+      #if !defined(_7ZIP_ST) && !defined(_SFX)\r
+      , bool mtMode, UInt32 numThreads\r
+      #endif\r
+      );\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp
new file mode 100755 (executable)
index 0000000..4b93449
--- /dev/null
@@ -0,0 +1,444 @@
+// 7zEncode.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/CreateCoder.h"\r
+#include "../../Common/FilterCoder.h"\r
+#include "../../Common/LimitedStreams.h"\r
+#include "../../Common/InOutTempBuffer.h"\r
+#include "../../Common/ProgressUtils.h"\r
+#include "../../Common/StreamObjects.h"\r
+\r
+#include "7zEncode.h"\r
+#include "7zSpecStream.h"\r
+\r
+static const UInt64 k_Delta = 0x03;\r
+static const UInt64 k_BCJ = 0x03030103;\r
+static const UInt64 k_BCJ2 = 0x0303011B;\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo,\r
+    const CRecordVector<CMethodId> decompressionMethods,\r
+    CFolder &folder)\r
+{\r
+  folder.Coders.Clear();\r
+  // bindInfo.CoderMethodIDs.Clear();\r
+  // folder.OutStreams.Clear();\r
+  folder.PackStreams.Clear();\r
+  folder.BindPairs.Clear();\r
+  int i;\r
+  for (i = 0; i < bindInfo.BindPairs.Size(); i++)\r
+  {\r
+    CBindPair bindPair;\r
+    bindPair.InIndex = bindInfo.BindPairs[i].InIndex;\r
+    bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex;\r
+    folder.BindPairs.Add(bindPair);\r
+  }\r
+  for (i = 0; i < bindInfo.Coders.Size(); i++)\r
+  {\r
+    CCoderInfo coderInfo;\r
+    const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];\r
+    coderInfo.NumInStreams = coderStreamsInfo.NumInStreams;\r
+    coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams;\r
+    coderInfo.MethodID = decompressionMethods[i];\r
+    folder.Coders.Add(coderInfo);\r
+  }\r
+  for (i = 0; i < bindInfo.InStreams.Size(); i++)\r
+    folder.PackStreams.Add(bindInfo.InStreams[i]);\r
+}\r
+\r
+HRESULT CEncoder::CreateMixerCoder(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    const UInt64 *inSizeForReduce)\r
+{\r
+  _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT;\r
+  _mixerCoder = _mixerCoderSpec;\r
+  RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo));\r
+  for (int i = 0; i < _options.Methods.Size(); i++)\r
+  {\r
+    const CMethodFull &methodFull = _options.Methods[i];\r
+    _codersInfo.Add(CCoderInfo());\r
+    CCoderInfo &encodingInfo = _codersInfo.Back();\r
+    encodingInfo.MethodID = methodFull.Id;\r
+    CMyComPtr<ICompressCoder> encoder;\r
+    CMyComPtr<ICompressCoder2> encoder2;\r
+    \r
+\r
+    RINOK(CreateCoder(\r
+        EXTERNAL_CODECS_LOC_VARS\r
+        methodFull.Id, encoder, encoder2, true));\r
+\r
+    if (!encoder && !encoder2)\r
+      return E_FAIL;\r
+\r
+    CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2;\r
+   \r
+    #ifndef _7ZIP_ST\r
+    {\r
+      CMyComPtr<ICompressSetCoderMt> setCoderMt;\r
+      encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);\r
+      if (setCoderMt)\r
+      {\r
+        RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads));\r
+      }\r
+    }\r
+    #endif\r
+        \r
+\r
+    RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon));\r
+\r
+    /*\r
+    CMyComPtr<ICryptoResetSalt> resetSalt;\r
+    encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt);\r
+    if (resetSalt != NULL)\r
+    {\r
+      resetSalt->ResetSalt();\r
+    }\r
+    */\r
+\r
+    #ifdef EXTERNAL_CODECS\r
+    CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;\r
+    encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);\r
+    if (setCompressCodecsInfo)\r
+    {\r
+      RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));\r
+    }\r
+    #endif\r
+    \r
+    CMyComPtr<ICryptoSetPassword> cryptoSetPassword;\r
+    encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);\r
+\r
+    if (cryptoSetPassword)\r
+    {\r
+      CByteBuffer buffer;\r
+      const UInt32 sizeInBytes = _options.Password.Length() * 2;\r
+      buffer.SetCapacity(sizeInBytes);\r
+      for (int i = 0; i < _options.Password.Length(); i++)\r
+      {\r
+        wchar_t c = _options.Password[i];\r
+        ((Byte *)buffer)[i * 2] = (Byte)c;\r
+        ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);\r
+      }\r
+      RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));\r
+    }\r
+\r
+    if (encoder)\r
+      _mixerCoderSpec->AddCoder(encoder);\r
+    else\r
+      _mixerCoderSpec->AddCoder2(encoder2);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CEncoder::Encode(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    ISequentialInStream *inStream,\r
+    const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,\r
+    CFolder &folderItem,\r
+    ISequentialOutStream *outStream,\r
+    CRecordVector<UInt64> &packSizes,\r
+    ICompressProgressInfo *compressProgress)\r
+{\r
+  RINOK(EncoderConstr());\r
+\r
+  if (_mixerCoderSpec == NULL)\r
+  {\r
+    RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));\r
+  }\r
+  _mixerCoderSpec->ReInit();\r
+  // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress);\r
+\r
+  CObjectVector<CInOutTempBuffer> inOutTempBuffers;\r
+  CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs;\r
+  CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;\r
+  int numMethods = _bindInfo.Coders.Size();\r
+  int i;\r
+  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)\r
+  {\r
+    inOutTempBuffers.Add(CInOutTempBuffer());\r
+    inOutTempBuffers.Back().Create();\r
+    inOutTempBuffers.Back().InitWriting();\r
+  }\r
+  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)\r
+  {\r
+    CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp;\r
+    CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;\r
+    tempBufferSpec->Init(&inOutTempBuffers[i - 1]);\r
+    tempBuffers.Add(tempBuffer);\r
+    tempBufferSpecs.Add(tempBufferSpec);\r
+  }\r
+\r
+  for (i = 0; i < numMethods; i++)\r
+    _mixerCoderSpec->SetCoderInfo(i, NULL, NULL);\r
+\r
+  if (_bindInfo.InStreams.IsEmpty())\r
+    return E_FAIL;\r
+  UInt32 mainCoderIndex, mainStreamIndex;\r
+  _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex);\r
+  \r
+  if (inStreamSize != NULL)\r
+  {\r
+    CRecordVector<const UInt64 *> sizePointers;\r
+    for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++)\r
+      if (i == mainStreamIndex)\r
+        sizePointers.Add(inStreamSize);\r
+      else\r
+        sizePointers.Add(NULL);\r
+    _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL);\r
+  }\r
+\r
+  \r
+  // UInt64 outStreamStartPos;\r
+  // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos));\r
+  \r
+  CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;\r
+  CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;\r
+  CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;\r
+  CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec;\r
+\r
+  inStreamSizeCountSpec->Init(inStream);\r
+  outStreamSizeCountSpec->SetStream(outStream);\r
+  outStreamSizeCountSpec->Init();\r
+\r
+  CRecordVector<ISequentialInStream *> inStreamPointers;\r
+  CRecordVector<ISequentialOutStream *> outStreamPointers;\r
+  inStreamPointers.Add(inStreamSizeCount);\r
+  outStreamPointers.Add(outStreamSizeCount);\r
+  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)\r
+    outStreamPointers.Add(tempBuffers[i - 1]);\r
+\r
+  for (i = 0; i < _codersInfo.Size(); i++)\r
+  {\r
+    CCoderInfo &encodingInfo = _codersInfo[i];\r
+    \r
+    CMyComPtr<ICryptoResetInitVector> resetInitVector;\r
+    _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);\r
+    if (resetInitVector != NULL)\r
+    {\r
+      resetInitVector->ResetInitVector();\r
+    }\r
+\r
+    CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;\r
+    _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);\r
+    if (writeCoderProperties != NULL)\r
+    {\r
+      CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;\r
+      CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\r
+      outStreamSpec->Init();\r
+      writeCoderProperties->WriteCoderProperties(outStream);\r
+      outStreamSpec->CopyToBuffer(encodingInfo.Props);\r
+    }\r
+  }\r
+\r
+  UInt32 progressIndex = mainCoderIndex;\r
+\r
+  for (i = 0; i + 1 < _codersInfo.Size(); i++)\r
+  {\r
+    UInt64 m = _codersInfo[i].MethodID;\r
+    if (m == k_Delta || m == k_BCJ || m == k_BCJ2)\r
+      progressIndex = i + 1;\r
+  }\r
+\r
+  _mixerCoderSpec->SetProgressCoderIndex(progressIndex);\r
+  \r
+  RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1,\r
+    &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress));\r
+  \r
+  ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem);\r
+  \r
+  packSizes.Add(outStreamSizeCountSpec->GetSize());\r
+  \r
+  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)\r
+  {\r
+    CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];\r
+    RINOK(inOutTempBuffer.WriteToStream(outStream));\r
+    packSizes.Add(inOutTempBuffer.GetDataSize());\r
+  }\r
+  \r
+  for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++)\r
+  {\r
+    int binder = _bindInfo.FindBinderForInStream(\r
+        _bindReverseConverter->DestOutToSrcInMap[i]);\r
+    UInt64 streamSize;\r
+    if (binder < 0)\r
+      streamSize = inStreamSizeCountSpec->GetSize();\r
+    else\r
+      streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder);\r
+    folderItem.UnpackSizes.Add(streamSize);\r
+  }\r
+  for (i = numMethods - 1; i >= 0; i--)\r
+    folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props;\r
+  return S_OK;\r
+}\r
+\r
+\r
+CEncoder::CEncoder(const CCompressionMethodMode &options):\r
+  _bindReverseConverter(0),\r
+  _constructed(false)\r
+{\r
+  if (options.IsEmpty())\r
+    throw 1;\r
+\r
+  _options = options;\r
+  _mixerCoderSpec = NULL;\r
+}\r
+\r
+HRESULT CEncoder::EncoderConstr()\r
+{\r
+  if (_constructed)\r
+    return S_OK;\r
+  if (_options.Methods.IsEmpty())\r
+  {\r
+    // it has only password method;\r
+    if (!_options.PasswordIsDefined)\r
+      throw 1;\r
+    if (!_options.Binds.IsEmpty())\r
+      throw 1;\r
+    NCoderMixer::CCoderStreamsInfo coderStreamsInfo;\r
+    CMethodFull method;\r
+    \r
+    method.NumInStreams = 1;\r
+    method.NumOutStreams = 1;\r
+    coderStreamsInfo.NumInStreams = 1;\r
+    coderStreamsInfo.NumOutStreams = 1;\r
+    method.Id = k_AES;\r
+    \r
+    _options.Methods.Add(method);\r
+    _bindInfo.Coders.Add(coderStreamsInfo);\r
+  \r
+    _bindInfo.InStreams.Add(0);\r
+    _bindInfo.OutStreams.Add(0);\r
+  }\r
+  else\r
+  {\r
+\r
+  UInt32 numInStreams = 0, numOutStreams = 0;\r
+  int i;\r
+  for (i = 0; i < _options.Methods.Size(); i++)\r
+  {\r
+    const CMethodFull &methodFull = _options.Methods[i];\r
+    NCoderMixer::CCoderStreamsInfo coderStreamsInfo;\r
+    coderStreamsInfo.NumInStreams = methodFull.NumOutStreams;\r
+    coderStreamsInfo.NumOutStreams = methodFull.NumInStreams;\r
+    if (_options.Binds.IsEmpty())\r
+    {\r
+      if (i < _options.Methods.Size() - 1)\r
+      {\r
+        NCoderMixer::CBindPair bindPair;\r
+        bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams;\r
+        bindPair.OutIndex = numOutStreams;\r
+        _bindInfo.BindPairs.Add(bindPair);\r
+      }\r
+      else\r
+        _bindInfo.OutStreams.Insert(0, numOutStreams);\r
+      for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++)\r
+        _bindInfo.OutStreams.Add(numOutStreams + j);\r
+    }\r
+    \r
+    numInStreams += coderStreamsInfo.NumInStreams;\r
+    numOutStreams += coderStreamsInfo.NumOutStreams;\r
+\r
+    _bindInfo.Coders.Add(coderStreamsInfo);\r
+  }\r
+\r
+  if (!_options.Binds.IsEmpty())\r
+  {\r
+    for (i = 0; i < _options.Binds.Size(); i++)\r
+    {\r
+      NCoderMixer::CBindPair bindPair;\r
+      const CBind &bind = _options.Binds[i];\r
+      bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream;\r
+      bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream;\r
+      _bindInfo.BindPairs.Add(bindPair);\r
+    }\r
+    for (i = 0; i < (int)numOutStreams; i++)\r
+      if (_bindInfo.FindBinderForOutStream(i) == -1)\r
+        _bindInfo.OutStreams.Add(i);\r
+  }\r
+\r
+  for (i = 0; i < (int)numInStreams; i++)\r
+    if (_bindInfo.FindBinderForInStream(i) == -1)\r
+      _bindInfo.InStreams.Add(i);\r
+\r
+  if (_bindInfo.InStreams.IsEmpty())\r
+    throw 1; // this is error\r
+\r
+  // Make main stream first in list\r
+  int inIndex = _bindInfo.InStreams[0];\r
+  for (;;)\r
+  {\r
+    UInt32 coderIndex, coderStreamIndex;\r
+    _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex);\r
+    UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);\r
+    int binder = _bindInfo.FindBinderForOutStream(outIndex);\r
+    if (binder >= 0)\r
+    {\r
+      inIndex = _bindInfo.BindPairs[binder].InIndex;\r
+      continue;\r
+    }\r
+    for (i = 0; i < _bindInfo.OutStreams.Size(); i++)\r
+      if (_bindInfo.OutStreams[i] == outIndex)\r
+      {\r
+        _bindInfo.OutStreams.Delete(i);\r
+        _bindInfo.OutStreams.Insert(0, outIndex);\r
+        break;\r
+      }\r
+    break;\r
+  }\r
+\r
+  if (_options.PasswordIsDefined)\r
+  {\r
+    int numCryptoStreams = _bindInfo.OutStreams.Size();\r
+\r
+    for (i = 0; i < numCryptoStreams; i++)\r
+    {\r
+      NCoderMixer::CBindPair bindPair;\r
+      bindPair.InIndex = numInStreams + i;\r
+      bindPair.OutIndex = _bindInfo.OutStreams[i];\r
+      _bindInfo.BindPairs.Add(bindPair);\r
+    }\r
+    _bindInfo.OutStreams.Clear();\r
+\r
+    /*\r
+    if (numCryptoStreams == 0)\r
+      numCryptoStreams = 1;\r
+    */\r
+\r
+    for (i = 0; i < numCryptoStreams; i++)\r
+    {\r
+      NCoderMixer::CCoderStreamsInfo coderStreamsInfo;\r
+      CMethodFull method;\r
+      method.NumInStreams = 1;\r
+      method.NumOutStreams = 1;\r
+      coderStreamsInfo.NumInStreams = method.NumOutStreams;\r
+      coderStreamsInfo.NumOutStreams = method.NumInStreams;\r
+      method.Id = k_AES;\r
+\r
+      _options.Methods.Add(method);\r
+      _bindInfo.Coders.Add(coderStreamsInfo);\r
+      _bindInfo.OutStreams.Add(numOutStreams + i);\r
+    }\r
+  }\r
+\r
+  }\r
+\r
+  for (int i = _options.Methods.Size() - 1; i >= 0; i--)\r
+  {\r
+    const CMethodFull &methodFull = _options.Methods[i];\r
+    _decompressionMethods.Add(methodFull.Id);\r
+  }\r
+\r
+  _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo);\r
+  _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo);\r
+  _constructed = true;\r
+  return S_OK;\r
+}\r
+\r
+CEncoder::~CEncoder()\r
+{\r
+  delete _bindReverseConverter;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/7z/7zEncode.h b/CPP/7zip/Archive/7z/7zEncode.h
new file mode 100755 (executable)
index 0000000..c75f02f
--- /dev/null
@@ -0,0 +1,55 @@
+// 7zEncode.h\r
+\r
+#ifndef __7Z_ENCODE_H\r
+#define __7Z_ENCODE_H\r
+\r
+// #include "../../Common/StreamObjects.h"\r
+\r
+#include "7zCompressionMode.h"\r
+\r
+#include "../Common/CoderMixer2.h"\r
+#include "../Common/CoderMixer2MT.h"\r
+#ifdef _ST_MODE\r
+#include "../Common/CoderMixer2ST.h"\r
+#endif\r
+#include "7zItem.h"\r
+\r
+#include "../../Common/CreateCoder.h"\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+class CEncoder\r
+{\r
+  NCoderMixer::CCoderMixer2MT *_mixerCoderSpec;\r
+  CMyComPtr<ICompressCoder2> _mixerCoder;\r
+\r
+  CObjectVector<CCoderInfo> _codersInfo;\r
+\r
+  CCompressionMethodMode _options;\r
+  NCoderMixer::CBindInfo _bindInfo;\r
+  NCoderMixer::CBindInfo _decompressBindInfo;\r
+  NCoderMixer::CBindReverseConverter *_bindReverseConverter;\r
+  CRecordVector<CMethodId> _decompressionMethods;\r
+\r
+  HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS\r
+      const UInt64 *inSizeForReduce);\r
+\r
+  bool _constructed;\r
+public:\r
+  CEncoder(const CCompressionMethodMode &options);\r
+  ~CEncoder();\r
+  HRESULT EncoderConstr();\r
+  HRESULT Encode(\r
+      DECL_EXTERNAL_CODECS_LOC_VARS\r
+      ISequentialInStream *inStream,\r
+      const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,\r
+      CFolder &folderItem,\r
+      ISequentialOutStream *outStream,\r
+      CRecordVector<UInt64> &packSizes,\r
+      ICompressProgressInfo *compressProgress);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp
new file mode 100755 (executable)
index 0000000..6e31943
--- /dev/null
@@ -0,0 +1,270 @@
+// 7zExtract.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../Common/ComTry.h"\r
+\r
+#include "../../Common/ProgressUtils.h"\r
+\r
+#include "7zDecode.h"\r
+// #include "7z1Decode.h"\r
+#include "7zFolderOutStream.h"\r
+#include "7zHandler.h"\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+struct CExtractFolderInfo\r
+{\r
+  #ifdef _7Z_VOL\r
+  int VolumeIndex;\r
+  #endif\r
+  CNum FileIndex;\r
+  CNum FolderIndex;\r
+  CBoolVector ExtractStatuses;\r
+  UInt64 UnpackSize;\r
+  CExtractFolderInfo(\r
+    #ifdef _7Z_VOL\r
+    int volumeIndex,\r
+    #endif\r
+    CNum fileIndex, CNum folderIndex):\r
+    #ifdef _7Z_VOL\r
+    VolumeIndex(volumeIndex),\r
+    #endif\r
+    FileIndex(fileIndex),\r
+    FolderIndex(folderIndex),\r
+    UnpackSize(0)\r
+  {\r
+    if (fileIndex != kNumNoIndex)\r
+    {\r
+      ExtractStatuses.Reserve(1);\r
+      ExtractStatuses.Add(true);\r
+    }\r
+  };\r
+};\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool testMode = (testModeSpec != 0);\r
+  CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;\r
+  UInt64 importantTotalUnpacked = 0;\r
+\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems =\r
+    #ifdef _7Z_VOL\r
+    _refs.Size();\r
+    #else\r
+    _db.Files.Size();\r
+    #endif\r
+\r
+  if(numItems == 0)\r
+    return S_OK;\r
+\r
+  /*\r
+  if(_volumes.Size() != 1)\r
+    return E_FAIL;\r
+  const CVolume &volume = _volumes.Front();\r
+  const CArchiveDatabaseEx &_db = volume.Database;\r
+  IInStream *_inStream = volume.Stream;\r
+  */\r
+  \r
+  CObjectVector<CExtractFolderInfo> extractFolderInfoVector;\r
+  for (UInt32 ii = 0; ii < numItems; ii++)\r
+  {\r
+    // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex];\r
+    UInt32 ref2Index = allFilesMode ? ii : indices[ii];\r
+    // const CRef2 &ref2 = _refs[ref2Index];\r
+\r
+    // for (UInt32 ri = 0; ri < ref2.Refs.Size(); ri++)\r
+    {\r
+      #ifdef _7Z_VOL\r
+      // const CRef &ref = ref2.Refs[ri];\r
+      const CRef &ref = _refs[ref2Index];\r
+\r
+      int volumeIndex = ref.VolumeIndex;\r
+      const CVolume &volume = _volumes[volumeIndex];\r
+      const CArchiveDatabaseEx &db = volume.Database;\r
+      UInt32 fileIndex = ref.ItemIndex;\r
+      #else\r
+      const CArchiveDatabaseEx &db = _db;\r
+      UInt32 fileIndex = ref2Index;\r
+      #endif\r
+\r
+      CNum folderIndex = db.FileIndexToFolderIndexMap[fileIndex];\r
+      if (folderIndex == kNumNoIndex)\r
+      {\r
+        extractFolderInfoVector.Add(CExtractFolderInfo(\r
+            #ifdef _7Z_VOL\r
+            volumeIndex,\r
+            #endif\r
+            fileIndex, kNumNoIndex));\r
+        continue;\r
+      }\r
+      if (extractFolderInfoVector.IsEmpty() ||\r
+        folderIndex != extractFolderInfoVector.Back().FolderIndex\r
+        #ifdef _7Z_VOL\r
+        || volumeIndex != extractFolderInfoVector.Back().VolumeIndex\r
+        #endif\r
+        )\r
+      {\r
+        extractFolderInfoVector.Add(CExtractFolderInfo(\r
+            #ifdef _7Z_VOL\r
+            volumeIndex,\r
+            #endif\r
+            kNumNoIndex, folderIndex));\r
+        const CFolder &folderInfo = db.Folders[folderIndex];\r
+        UInt64 unpackSize = folderInfo.GetUnpackSize();\r
+        importantTotalUnpacked += unpackSize;\r
+        extractFolderInfoVector.Back().UnpackSize = unpackSize;\r
+      }\r
+      \r
+      CExtractFolderInfo &efi = extractFolderInfoVector.Back();\r
+      \r
+      // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex];\r
+      CNum startIndex = db.FolderStartFileIndex[folderIndex];\r
+      for (CNum index = efi.ExtractStatuses.Size();\r
+          index <= fileIndex - startIndex; index++)\r
+      {\r
+        // UInt64 unpackSize = _db.Files[startIndex + index].UnpackSize;\r
+        // Count partial_folder_size\r
+        // efi.UnpackSize += unpackSize;\r
+        // importantTotalUnpacked += unpackSize;\r
+        efi.ExtractStatuses.Add(index == fileIndex - startIndex);\r
+      }\r
+    }\r
+  }\r
+\r
+  RINOK(extractCallback->SetTotal(importantTotalUnpacked));\r
+\r
+  CDecoder decoder(\r
+    #ifdef _ST_MODE\r
+    false\r
+    #else\r
+    true\r
+    #endif\r
+    );\r
+  // CDecoder1 decoder;\r
+\r
+  UInt64 totalPacked = 0;\r
+  UInt64 totalUnpacked = 0;\r
+  UInt64 curPacked, curUnpacked;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  for (int i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked)\r
+  {\r
+    lps->OutSize = totalUnpacked;\r
+    lps->InSize = totalPacked;\r
+    RINOK(lps->SetCur());\r
+\r
+    if (i >= extractFolderInfoVector.Size())\r
+      break;\r
+    \r
+    const CExtractFolderInfo &efi = extractFolderInfoVector[i];\r
+    curUnpacked = efi.UnpackSize;\r
+    curPacked = 0;\r
+\r
+    CFolderOutStream *folderOutStream = new CFolderOutStream;\r
+    CMyComPtr<ISequentialOutStream> outStream(folderOutStream);\r
+\r
+    #ifdef _7Z_VOL\r
+    const CVolume &volume = _volumes[efi.VolumeIndex];\r
+    const CArchiveDatabaseEx &db = volume.Database;\r
+    #else\r
+    const CArchiveDatabaseEx &db = _db;\r
+    #endif\r
+\r
+    CNum startIndex;\r
+    if (efi.FileIndex != kNumNoIndex)\r
+      startIndex = efi.FileIndex;\r
+    else\r
+      startIndex = db.FolderStartFileIndex[efi.FolderIndex];\r
+\r
+    HRESULT result = folderOutStream->Init(&db,\r
+        #ifdef _7Z_VOL\r
+        volume.StartRef2Index,\r
+        #else\r
+        0,\r
+        #endif\r
+        startIndex,\r
+        &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0);\r
+\r
+    RINOK(result);\r
+\r
+    if (efi.FileIndex != kNumNoIndex)\r
+      continue;\r
+\r
+    CNum folderIndex = efi.FolderIndex;\r
+    const CFolder &folderInfo = db.Folders[folderIndex];\r
+\r
+    curPacked = _db.GetFolderFullPackSize(folderIndex);\r
+\r
+    CNum packStreamIndex = db.FolderStartPackStreamIndex[folderIndex];\r
+    UInt64 folderStartPackPos = db.GetFolderStreamPos(folderIndex, 0);\r
+\r
+    #ifndef _NO_CRYPTO\r
+    CMyComPtr<ICryptoGetTextPassword> getTextPassword;\r
+    if (extractCallback)\r
+      extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);\r
+    #endif\r
+\r
+    try\r
+    {\r
+      #ifndef _NO_CRYPTO\r
+      bool passwordIsDefined;\r
+      #endif\r
+\r
+      HRESULT result = decoder.Decode(\r
+          EXTERNAL_CODECS_VARS\r
+          #ifdef _7Z_VOL\r
+          volume.Stream,\r
+          #else\r
+          _inStream,\r
+          #endif\r
+          folderStartPackPos,\r
+          &db.PackSizes[packStreamIndex],\r
+          folderInfo,\r
+          outStream,\r
+          progress\r
+          #ifndef _NO_CRYPTO\r
+          , getTextPassword, passwordIsDefined\r
+          #endif\r
+          #if !defined(_7ZIP_ST) && !defined(_SFX)\r
+          , true, _numThreads\r
+          #endif\r
+          );\r
+\r
+      if (result == S_FALSE)\r
+      {\r
+        RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));\r
+        continue;\r
+      }\r
+      if (result == E_NOTIMPL)\r
+      {\r
+        RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kUnSupportedMethod));\r
+        continue;\r
+      }\r
+      if (result != S_OK)\r
+        return result;\r
+      if (folderOutStream->WasWritingFinished() != S_OK)\r
+      {\r
+        RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));\r
+        continue;\r
+      }\r
+    }\r
+    catch(...)\r
+    {\r
+      RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));\r
+      continue;\r
+    }\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/CPP/7zip/Archive/7z/7zFolderInStream.cpp
new file mode 100755 (executable)
index 0000000..c49d341
--- /dev/null
@@ -0,0 +1,123 @@
+// 7zFolderInStream.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "7zFolderInStream.h"\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+CFolderInStream::CFolderInStream()\r
+{\r
+  _inStreamWithHashSpec = new CSequentialInStreamWithCRC;\r
+  _inStreamWithHash = _inStreamWithHashSpec;\r
+}\r
+\r
+void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,\r
+    const UInt32 *fileIndices, UInt32 numFiles)\r
+{\r
+  _updateCallback = updateCallback;\r
+  _numFiles = numFiles;\r
+  _fileIndex = 0;\r
+  _fileIndices = fileIndices;\r
+  Processed.Clear();\r
+  CRCs.Clear();\r
+  Sizes.Clear();\r
+  _fileIsOpen = false;\r
+  _currentSizeIsDefined = false;\r
+}\r
+\r
+HRESULT CFolderInStream::OpenStream()\r
+{\r
+  _filePos = 0;\r
+  while (_fileIndex < _numFiles)\r
+  {\r
+    CMyComPtr<ISequentialInStream> stream;\r
+    HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream);\r
+    if (result != S_OK && result != S_FALSE)\r
+      return result;\r
+    _fileIndex++;\r
+    _inStreamWithHashSpec->SetStream(stream);\r
+    _inStreamWithHashSpec->Init();\r
+    if (stream)\r
+    {\r
+      _fileIsOpen = true;\r
+      CMyComPtr<IStreamGetSize> streamGetSize;\r
+      stream.QueryInterface(IID_IStreamGetSize, &streamGetSize);\r
+      if (streamGetSize)\r
+      {\r
+        RINOK(streamGetSize->GetSize(&_currentSize));\r
+        _currentSizeIsDefined = true;\r
+      }\r
+      return S_OK;\r
+    }\r
+    RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));\r
+    Sizes.Add(0);\r
+    Processed.Add(result == S_OK);\r
+    AddDigest();\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+void CFolderInStream::AddDigest()\r
+{\r
+  CRCs.Add(_inStreamWithHashSpec->GetCRC());\r
+}\r
+\r
+HRESULT CFolderInStream::CloseStream()\r
+{\r
+  RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));\r
+  _inStreamWithHashSpec->ReleaseStream();\r
+  _fileIsOpen = false;\r
+  _currentSizeIsDefined = false;\r
+  Processed.Add(true);\r
+  Sizes.Add(_filePos);\r
+  AddDigest();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize != 0)\r
+    *processedSize = 0;\r
+  while (size > 0)\r
+  {\r
+    if (_fileIsOpen)\r
+    {\r
+      UInt32 processed2;\r
+      RINOK(_inStreamWithHash->Read(data, size, &processed2));\r
+      if (processed2 == 0)\r
+      {\r
+        RINOK(CloseStream());\r
+        continue;\r
+      }\r
+      if (processedSize != 0)\r
+        *processedSize = processed2;\r
+      _filePos += processed2;\r
+      break;\r
+    }\r
+    if (_fileIndex >= _numFiles)\r
+      break;\r
+    RINOK(OpenStream());\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)\r
+{\r
+  *value = 0;\r
+  int index2 = (int)subStream;\r
+  if (index2 < 0 || subStream > Sizes.Size())\r
+    return E_FAIL;\r
+  if (index2 < Sizes.Size())\r
+  {\r
+    *value = Sizes[index2];\r
+    return S_OK;\r
+  }\r
+  if (!_currentSizeIsDefined)\r
+    return S_FALSE;\r
+  *value = _currentSize;\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.h b/CPP/7zip/Archive/7z/7zFolderInStream.h
new file mode 100755 (executable)
index 0000000..fc27b9b
--- /dev/null
@@ -0,0 +1,58 @@
+// 7zFolderInStream.h\r
+\r
+#ifndef __7Z_FOLDER_IN_STREAM_H\r
+#define __7Z_FOLDER_IN_STREAM_H\r
+\r
+#include "../../ICoder.h"\r
+#include "../IArchive.h"\r
+#include "../Common/InStreamWithCRC.h"\r
+\r
+#include "7zItem.h"\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+class CFolderInStream:\r
+  public ISequentialInStream,\r
+  public ICompressGetSubStreamSize,\r
+  public CMyUnknownImp\r
+{\r
+  CSequentialInStreamWithCRC *_inStreamWithHashSpec;\r
+  CMyComPtr<ISequentialInStream> _inStreamWithHash;\r
+  CMyComPtr<IArchiveUpdateCallback> _updateCallback;\r
+\r
+  bool _currentSizeIsDefined;\r
+  bool _fileIsOpen;\r
+  UInt64 _currentSize;\r
+  UInt64 _filePos;\r
+  const UInt32 *_fileIndices;\r
+  UInt32 _numFiles;\r
+  UInt32 _fileIndex;\r
+\r
+  HRESULT OpenStream();\r
+  HRESULT CloseStream();\r
+  void AddDigest();\r
+\r
+public:\r
+  CRecordVector<bool> Processed;\r
+  CRecordVector<UInt32> CRCs;\r
+  CRecordVector<UInt64> Sizes;\r
+\r
+  MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);\r
+\r
+  CFolderInStream();\r
+  void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles);\r
+  UInt64 GetFullSize() const\r
+  {\r
+    UInt64 size = 0;\r
+    for (int i = 0; i < Sizes.Size(); i++)\r
+      size += Sizes[i];\r
+    return size;\r
+  }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
new file mode 100755 (executable)
index 0000000..403ca60
--- /dev/null
@@ -0,0 +1,149 @@
+// 7zFolderOutStream.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "7zFolderOutStream.h"\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+CFolderOutStream::CFolderOutStream()\r
+{\r
+  _crcStreamSpec = new COutStreamWithCRC;\r
+  _crcStream = _crcStreamSpec;\r
+}\r
+\r
+HRESULT CFolderOutStream::Init(\r
+    const CArchiveDatabaseEx *db,\r
+    UInt32 ref2Offset, UInt32 startIndex,\r
+    const CBoolVector *extractStatuses,\r
+    IArchiveExtractCallback *extractCallback,\r
+    bool testMode, bool checkCrc)\r
+{\r
+  _db = db;\r
+  _ref2Offset = ref2Offset;\r
+  _startIndex = startIndex;\r
+\r
+  _extractStatuses = extractStatuses;\r
+  _extractCallback = extractCallback;\r
+  _testMode = testMode;\r
+  _checkCrc = checkCrc;\r
+\r
+  _currentIndex = 0;\r
+  _fileIsOpen = false;\r
+  return ProcessEmptyFiles();\r
+}\r
+\r
+HRESULT CFolderOutStream::OpenFile()\r
+{\r
+  Int32 askMode = ((*_extractStatuses)[_currentIndex]) ? (_testMode ?\r
+      NExtract::NAskMode::kTest :\r
+      NExtract::NAskMode::kExtract) :\r
+      NExtract::NAskMode::kSkip;\r
+  CMyComPtr<ISequentialOutStream> realOutStream;\r
+  UInt32 index = _startIndex + _currentIndex;\r
+  RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));\r
+  _crcStreamSpec->SetStream(realOutStream);\r
+  _crcStreamSpec->Init(_checkCrc);\r
+  _fileIsOpen = true;\r
+  const CFileItem &fi = _db->Files[index];\r
+  _rem = fi.Size;\r
+  if (askMode == NExtract::NAskMode::kExtract && !realOutStream &&\r
+      !_db->IsItemAnti(index) && !fi.IsDir)\r
+    askMode = NExtract::NAskMode::kSkip;\r
+  return _extractCallback->PrepareOperation(askMode);\r
+}\r
+\r
+HRESULT CFolderOutStream::CloseFileAndSetResult(Int32 res)\r
+{\r
+  _crcStreamSpec->ReleaseStream();\r
+  _fileIsOpen = false;\r
+  _currentIndex++;\r
+  return _extractCallback->SetOperationResult(res);\r
+}\r
+\r
+HRESULT CFolderOutStream::CloseFileAndSetResult()\r
+{\r
+  const CFileItem &fi = _db->Files[_startIndex + _currentIndex];\r
+  return CloseFileAndSetResult(\r
+      (fi.IsDir || !fi.CrcDefined || !_checkCrc || fi.Crc == _crcStreamSpec->GetCRC()) ?\r
+      NExtract::NOperationResult::kOK :\r
+      NExtract::NOperationResult::kCRCError);\r
+}\r
+\r
+HRESULT CFolderOutStream::ProcessEmptyFiles()\r
+{\r
+  while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)\r
+  {\r
+    RINOK(OpenFile());\r
+    RINOK(CloseFileAndSetResult());\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize != NULL)\r
+    *processedSize = 0;\r
+  while (size != 0)\r
+  {\r
+    if (_fileIsOpen)\r
+    {\r
+      UInt32 cur = size < _rem ? size : (UInt32)_rem;\r
+      RINOK(_crcStream->Write(data, cur, &cur));\r
+      if (cur == 0)\r
+        break;\r
+      data = (const Byte *)data + cur;\r
+      size -= cur;\r
+      _rem -= cur;\r
+      if (processedSize != NULL)\r
+        *processedSize += cur;\r
+      if (_rem == 0)\r
+      {\r
+        RINOK(CloseFileAndSetResult());\r
+        RINOK(ProcessEmptyFiles());\r
+        continue;\r
+      }\r
+    }\r
+    else\r
+    {\r
+      RINOK(ProcessEmptyFiles());\r
+      if (_currentIndex == _extractStatuses->Size())\r
+      {\r
+        // we support partial extracting\r
+        if (processedSize != NULL)\r
+          *processedSize += size;\r
+        break;\r
+      }\r
+      RINOK(OpenFile());\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFolderOutStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)\r
+{\r
+  *value = 0;\r
+  if ((int)subStream >= _extractStatuses->Size())\r
+    return S_FALSE;\r
+  *value = _db->Files[_startIndex + (int)subStream].Size;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)\r
+{\r
+  while (_currentIndex < _extractStatuses->Size())\r
+  {\r
+    if (_fileIsOpen)\r
+    {\r
+      RINOK(CloseFileAndSetResult(resultEOperationResult));\r
+    }\r
+    else\r
+    {\r
+      RINOK(OpenFile());\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.h b/CPP/7zip/Archive/7z/7zFolderOutStream.h
new file mode 100755 (executable)
index 0000000..c964b1d
--- /dev/null
@@ -0,0 +1,58 @@
+// 7zFolderOutStream.h\r
+\r
+#ifndef __7Z_FOLDER_OUT_STREAM_H\r
+#define __7Z_FOLDER_OUT_STREAM_H\r
+\r
+#include "../../IStream.h"\r
+#include "../IArchive.h"\r
+#include "../Common/OutStreamWithCRC.h"\r
+\r
+#include "7zIn.h"\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+class CFolderOutStream:\r
+  public ISequentialOutStream,\r
+  public ICompressGetSubStreamSize,\r
+  public CMyUnknownImp\r
+{\r
+  COutStreamWithCRC *_crcStreamSpec;\r
+  CMyComPtr<ISequentialOutStream> _crcStream;\r
+  const CArchiveDatabaseEx *_db;\r
+  const CBoolVector *_extractStatuses;\r
+  CMyComPtr<IArchiveExtractCallback> _extractCallback;\r
+  UInt32 _ref2Offset;\r
+  UInt32 _startIndex;\r
+  int _currentIndex;\r
+  bool _testMode;\r
+  bool _checkCrc;\r
+  bool _fileIsOpen;\r
+  UInt64 _rem;\r
+\r
+  HRESULT OpenFile();\r
+  HRESULT CloseFileAndSetResult(Int32 res);\r
+  HRESULT CloseFileAndSetResult();\r
+  HRESULT ProcessEmptyFiles();\r
+public:\r
+  MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)\r
+\r
+  CFolderOutStream();\r
+\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);\r
+\r
+  HRESULT Init(\r
+      const CArchiveDatabaseEx *db,\r
+      UInt32 ref2Offset, UInt32 startIndex,\r
+      const CBoolVector *extractStatuses,\r
+      IArchiveExtractCallback *extractCallback,\r
+      bool testMode, bool checkCrc);\r
+  HRESULT FlushCorrupted(Int32 resultEOperationResult);\r
+  HRESULT WasWritingFinished() const\r
+      { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp
new file mode 100755 (executable)
index 0000000..c404b9c
--- /dev/null
@@ -0,0 +1,482 @@
+// 7zHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/CpuArch.h"\r
+\r
+#include "../../../Common/ComTry.h"\r
+#include "../../../Common/IntToString.h"\r
+\r
+#ifndef __7Z_SET_PROPERTIES\r
+#include "../../../Windows/System.h"\r
+#endif\r
+\r
+#include "../Common/ItemNameUtils.h"\r
+\r
+#include "7zHandler.h"\r
+#include "7zProperties.h"\r
+\r
+#ifdef __7Z_SET_PROPERTIES\r
+#ifdef EXTRACT_ONLY\r
+#include "../Common/ParseProperties.h"\r
+#endif\r
+#endif\r
+\r
+using namespace NWindows;\r
+\r
+extern UString ConvertMethodIdToString(UInt64 id);\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+CHandler::CHandler()\r
+{\r
+  _crcSize = 4;\r
+\r
+  #ifndef _NO_CRYPTO\r
+  _passwordIsDefined = false;\r
+  #endif\r
+\r
+  #ifdef EXTRACT_ONLY\r
+  #ifdef __7Z_SET_PROPERTIES\r
+  _numThreads = NSystem::GetNumberOfProcessors();\r
+  #endif\r
+  #else\r
+  Init();\r
+  #endif\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _db.Files.Size();\r
+  return S_OK;\r
+}\r
+\r
+#ifdef _SFX\r
+\r
+IMP_IInArchive_ArcProps_NO\r
+\r
+STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */)\r
+{\r
+  return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,\r
+      BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)\r
+{\r
+  return E_NOTIMPL;\r
+}\r
+\r
+\r
+#else\r
+\r
+STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidMethod, VT_BSTR},\r
+  { NULL, kpidSolid, VT_BOOL},\r
+  { NULL, kpidNumBlocks, VT_UI4},\r
+  { NULL, kpidPhySize, VT_UI8},\r
+  { NULL, kpidHeadersSize, VT_UI8},\r
+  { NULL, kpidOffset, VT_UI8}\r
+};\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidMethod:\r
+    {\r
+      UString resString;\r
+      CRecordVector<UInt64> ids;\r
+      int i;\r
+      for (i = 0; i < _db.Folders.Size(); i++)\r
+      {\r
+        const CFolder &f = _db.Folders[i];\r
+        for (int j = f.Coders.Size() - 1; j >= 0; j--)\r
+          ids.AddToUniqueSorted(f.Coders[j].MethodID);\r
+      }\r
+\r
+      for (i = 0; i < ids.Size(); i++)\r
+      {\r
+        UInt64 id = ids[i];\r
+        UString methodName;\r
+        /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName);\r
+        if (methodName.IsEmpty())\r
+          methodName = ConvertMethodIdToString(id);\r
+        if (!resString.IsEmpty())\r
+          resString += L' ';\r
+        resString += methodName;\r
+      }\r
+      prop = resString;\r
+      break;\r
+    }\r
+    case kpidSolid: prop = _db.IsSolid(); break;\r
+    case kpidNumBlocks: prop = (UInt32)_db.Folders.Size(); break;\r
+    case kpidHeadersSize:  prop = _db.HeadersSize; break;\r
+    case kpidPhySize:  prop = _db.PhySize; break;\r
+    case kpidOffset: if (_db.ArchiveInfo.StartPosition != 0) prop = _db.ArchiveInfo.StartPosition; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+IMP_IInArchive_ArcProps\r
+\r
+#endif\r
+\r
+static void SetPropFromUInt64Def(CUInt64DefVector &v, int index, NCOM::CPropVariant &prop)\r
+{\r
+  UInt64 value;\r
+  if (v.GetItem(index, value))\r
+  {\r
+    FILETIME ft;\r
+    ft.dwLowDateTime = (DWORD)value;\r
+    ft.dwHighDateTime = (DWORD)(value >> 32);\r
+    prop = ft;\r
+  }\r
+}\r
+\r
+#ifndef _SFX\r
+\r
+static UString ConvertUInt32ToString(UInt32 value)\r
+{\r
+  wchar_t buffer[32];\r
+  ConvertUInt64ToString(value, buffer);\r
+  return buffer;\r
+}\r
+\r
+static UString GetStringForSizeValue(UInt32 value)\r
+{\r
+  for (int i = 31; i >= 0; i--)\r
+    if ((UInt32(1) << i) == value)\r
+      return ConvertUInt32ToString(i);\r
+  UString result;\r
+  if (value % (1 << 20) == 0)\r
+  {\r
+    result += ConvertUInt32ToString(value >> 20);\r
+    result += L"m";\r
+  }\r
+  else if (value % (1 << 10) == 0)\r
+  {\r
+    result += ConvertUInt32ToString(value >> 10);\r
+    result += L"k";\r
+  }\r
+  else\r
+  {\r
+    result += ConvertUInt32ToString(value);\r
+    result += L"b";\r
+  }\r
+  return result;\r
+}\r
+\r
+static const UInt64 k_Copy = 0x0;\r
+static const UInt64 k_Delta = 3;\r
+static const UInt64 k_LZMA2 = 0x21;\r
+static const UInt64 k_LZMA  = 0x030101;\r
+static const UInt64 k_PPMD  = 0x030401;\r
+\r
+static wchar_t GetHex(Byte value)\r
+{\r
+  return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10)));\r
+}\r
+static inline void AddHexToString(UString &res, Byte value)\r
+{\r
+  res += GetHex((Byte)(value >> 4));\r
+  res += GetHex((Byte)(value & 0xF));\r
+}\r
+\r
+#endif\r
+\r
+bool CHandler::IsEncrypted(UInt32 index2) const\r
+{\r
+  CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];\r
+  if (folderIndex != kNumNoIndex)\r
+    return _db.Folders[folderIndex].IsEncrypted();\r
+  return false;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID,  PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NCOM::CPropVariant prop;\r
+  \r
+  /*\r
+  const CRef2 &ref2 = _refs[index];\r
+  if (ref2.Refs.IsEmpty())\r
+    return E_FAIL;\r
+  const CRef &ref = ref2.Refs.Front();\r
+  */\r
+  \r
+  const CFileItem &item = _db.Files[index];\r
+  UInt32 index2 = index;\r
+\r
+  switch(propID)\r
+  {\r
+    case kpidPath:\r
+      if (!item.Name.IsEmpty())\r
+        prop = NItemName::GetOSName(item.Name);\r
+      break;\r
+    case kpidIsDir:  prop = item.IsDir; break;\r
+    case kpidSize:\r
+    {\r
+      prop = item.Size;\r
+      // prop = ref2.Size;\r
+      break;\r
+    }\r
+    case kpidPackSize:\r
+    {\r
+      // prop = ref2.PackSize;\r
+      {\r
+        CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];\r
+        if (folderIndex != kNumNoIndex)\r
+        {\r
+          if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2)\r
+            prop = _db.GetFolderFullPackSize(folderIndex);\r
+          /*\r
+          else\r
+            prop = (UInt64)0;\r
+          */\r
+        }\r
+        else\r
+          prop = (UInt64)0;\r
+      }\r
+      break;\r
+    }\r
+    case kpidPosition:  { UInt64 v; if (_db.StartPos.GetItem(index2, v)) prop = v; break; }\r
+    case kpidCTime:  SetPropFromUInt64Def(_db.CTime, index2, prop); break;\r
+    case kpidATime:  SetPropFromUInt64Def(_db.ATime, index2, prop); break;\r
+    case kpidMTime:  SetPropFromUInt64Def(_db.MTime, index2, prop); break;\r
+    case kpidAttrib:  if (item.AttribDefined) prop = item.Attrib; break;\r
+    case kpidCRC:  if (item.CrcDefined) prop = item.Crc; break;\r
+    case kpidEncrypted:  prop = IsEncrypted(index2); break;\r
+    case kpidIsAnti:  prop = _db.IsItemAnti(index2); break;\r
+    #ifndef _SFX\r
+    case kpidMethod:\r
+      {\r
+        CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];\r
+        if (folderIndex != kNumNoIndex)\r
+        {\r
+          const CFolder &folderInfo = _db.Folders[folderIndex];\r
+          UString methodsString;\r
+          for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)\r
+          {\r
+            const CCoderInfo &coder = folderInfo.Coders[i];\r
+            if (!methodsString.IsEmpty())\r
+              methodsString += L' ';\r
+\r
+            UString methodName, propsString;\r
+            bool methodIsKnown = FindMethod(\r
+              EXTERNAL_CODECS_VARS\r
+              coder.MethodID, methodName);\r
+            \r
+            if (!methodIsKnown)\r
+              methodsString += ConvertMethodIdToString(coder.MethodID);\r
+            else\r
+            {\r
+              methodsString += methodName;\r
+              if (coder.MethodID == k_Delta && coder.Props.GetCapacity() == 1)\r
+                propsString = ConvertUInt32ToString((UInt32)coder.Props[0] + 1);\r
+              else if (coder.MethodID == k_LZMA && coder.Props.GetCapacity() == 5)\r
+              {\r
+                UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1);\r
+                propsString = GetStringForSizeValue(dicSize);\r
+              }\r
+              else if (coder.MethodID == k_LZMA2 && coder.Props.GetCapacity() == 1)\r
+              {\r
+                Byte p = coder.Props[0];\r
+                UInt32 dicSize = (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11));\r
+                propsString = GetStringForSizeValue(dicSize);\r
+              }\r
+              else if (coder.MethodID == k_PPMD && coder.Props.GetCapacity() == 5)\r
+              {\r
+                Byte order = *(const Byte *)coder.Props;\r
+                propsString = L'o';\r
+                propsString += ConvertUInt32ToString(order);\r
+                propsString += L":mem";\r
+                UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1);\r
+                propsString += GetStringForSizeValue(dicSize);\r
+              }\r
+              else if (coder.MethodID == k_AES && coder.Props.GetCapacity() >= 1)\r
+              {\r
+                const Byte *data = (const Byte *)coder.Props;\r
+                Byte firstByte = *data++;\r
+                UInt32 numCyclesPower = firstByte & 0x3F;\r
+                propsString = ConvertUInt32ToString(numCyclesPower);\r
+                /*\r
+                if ((firstByte & 0xC0) != 0)\r
+                {\r
+                  UInt32 saltSize = (firstByte >> 7) & 1;\r
+                  UInt32 ivSize = (firstByte >> 6) & 1;\r
+                  if (coder.Props.GetCapacity() >= 2)\r
+                  {\r
+                    Byte secondByte = *data++;\r
+                    saltSize += (secondByte >> 4);\r
+                    ivSize += (secondByte & 0x0F);\r
+                  }\r
+                }\r
+                */\r
+              }\r
+            }\r
+            if (!propsString.IsEmpty())\r
+            {\r
+              methodsString += L':';\r
+              methodsString += propsString;\r
+            }\r
+            else if (coder.Props.GetCapacity() > 0)\r
+            {\r
+              methodsString += L":[";\r
+              for (size_t bi = 0; bi < coder.Props.GetCapacity(); bi++)\r
+              {\r
+                if (bi > 5 && bi + 1 < coder.Props.GetCapacity())\r
+                {\r
+                  methodsString += L"..";\r
+                  break;\r
+                }\r
+                else\r
+                  AddHexToString(methodsString, coder.Props[bi]);\r
+              }\r
+              methodsString += L']';\r
+            }\r
+          }\r
+          prop = methodsString;\r
+        }\r
+      }\r
+      break;\r
+    case kpidBlock:\r
+      {\r
+        CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];\r
+        if (folderIndex != kNumNoIndex)\r
+          prop = (UInt32)folderIndex;\r
+      }\r
+      break;\r
+    case kpidPackedSize0:\r
+    case kpidPackedSize1:\r
+    case kpidPackedSize2:\r
+    case kpidPackedSize3:\r
+    case kpidPackedSize4:\r
+      {\r
+        CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];\r
+        if (folderIndex != kNumNoIndex)\r
+        {\r
+          const CFolder &folderInfo = _db.Folders[folderIndex];\r
+          if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&\r
+              folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0))\r
+          {\r
+            prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);\r
+          }\r
+          else\r
+            prop = (UInt64)0;\r
+        }\r
+        else\r
+          prop = (UInt64)0;\r
+      }\r
+      break;\r
+    #endif\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream,\r
+    const UInt64 *maxCheckStartPosition,\r
+    IArchiveOpenCallback *openArchiveCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  Close();\r
+  #ifndef _SFX\r
+  _fileInfoPopIDs.Clear();\r
+  #endif\r
+  try\r
+  {\r
+    CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;\r
+\r
+    #ifndef _NO_CRYPTO\r
+    CMyComPtr<ICryptoGetTextPassword> getTextPassword;\r
+    if (openArchiveCallback)\r
+    {\r
+      openArchiveCallbackTemp.QueryInterface(\r
+          IID_ICryptoGetTextPassword, &getTextPassword);\r
+    }\r
+    #endif\r
+    CInArchive archive;\r
+    RINOK(archive.Open(stream, maxCheckStartPosition));\r
+    #ifndef _NO_CRYPTO\r
+    _passwordIsDefined = false;\r
+    UString password;\r
+    #endif\r
+    HRESULT result = archive.ReadDatabase(\r
+      EXTERNAL_CODECS_VARS\r
+      _db\r
+      #ifndef _NO_CRYPTO\r
+      , getTextPassword, _passwordIsDefined\r
+      #endif\r
+      );\r
+    RINOK(result);\r
+    _db.Fill();\r
+    _inStream = stream;\r
+  }\r
+  catch(...)\r
+  {\r
+    Close();\r
+    return S_FALSE;\r
+  }\r
+  // _inStream = stream;\r
+  #ifndef _SFX\r
+  FillPopIDs();\r
+  #endif\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  COM_TRY_BEGIN\r
+  _inStream.Release();\r
+  _db.Clear();\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+#ifdef __7Z_SET_PROPERTIES\r
+#ifdef EXTRACT_ONLY\r
+\r
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)\r
+{\r
+  COM_TRY_BEGIN\r
+  const UInt32 numProcessors = NSystem::GetNumberOfProcessors();\r
+  _numThreads = numProcessors;\r
+\r
+  for (int i = 0; i < numProperties; i++)\r
+  {\r
+    UString name = names[i];\r
+    name.MakeUpper();\r
+    if (name.IsEmpty())\r
+      return E_INVALIDARG;\r
+    const PROPVARIANT &value = values[i];\r
+    UInt32 number;\r
+    int index = ParseStringToUInt32(name, number);\r
+    if (index == 0)\r
+    {\r
+      if(name.Left(2).CompareNoCase(L"MT") == 0)\r
+      {\r
+        RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));\r
+        continue;\r
+      }\r
+      else\r
+        return E_INVALIDARG;\r
+    }\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+#endif\r
+#endif\r
+\r
+IMPL_ISetCompressCodecsInfo\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h
new file mode 100755 (executable)
index 0000000..c0fd0e0
--- /dev/null
@@ -0,0 +1,119 @@
+// 7z/Handler.h\r
+\r
+#ifndef __7Z_HANDLER_H\r
+#define __7Z_HANDLER_H\r
+\r
+#include "../../ICoder.h"\r
+#include "../IArchive.h"\r
+\r
+#include "../../Common/CreateCoder.h"\r
+\r
+#ifndef EXTRACT_ONLY\r
+#include "../Common/HandlerOut.h"\r
+#endif\r
+\r
+#include "7zCompressionMode.h"\r
+#include "7zIn.h"\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+#ifndef __7Z_SET_PROPERTIES\r
+\r
+#ifdef EXTRACT_ONLY\r
+#if !defined(_7ZIP_ST) && !defined(_SFX)\r
+#define __7Z_SET_PROPERTIES\r
+#endif\r
+#else\r
+#define __7Z_SET_PROPERTIES\r
+#endif\r
+\r
+#endif\r
+\r
+\r
+class CHandler:\r
+  #ifndef EXTRACT_ONLY\r
+  public NArchive::COutHandler,\r
+  #endif\r
+  public IInArchive,\r
+  #ifdef __7Z_SET_PROPERTIES\r
+  public ISetProperties,\r
+  #endif\r
+  #ifndef EXTRACT_ONLY\r
+  public IOutArchive,\r
+  #endif\r
+  PUBLIC_ISetCompressCodecsInfo\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_QUERYINTERFACE_BEGIN2(IInArchive)\r
+  #ifdef __7Z_SET_PROPERTIES\r
+  MY_QUERYINTERFACE_ENTRY(ISetProperties)\r
+  #endif\r
+  #ifndef EXTRACT_ONLY\r
+  MY_QUERYINTERFACE_ENTRY(IOutArchive)\r
+  #endif\r
+  QUERY_ENTRY_ISetCompressCodecsInfo\r
+  MY_QUERYINTERFACE_END\r
+  MY_ADDREF_RELEASE\r
+\r
+  INTERFACE_IInArchive(;)\r
+\r
+  #ifdef __7Z_SET_PROPERTIES\r
+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties);\r
+  #endif\r
+\r
+  #ifndef EXTRACT_ONLY\r
+  INTERFACE_IOutArchive(;)\r
+  #endif\r
+\r
+  DECL_ISetCompressCodecsInfo\r
+\r
+  CHandler();\r
+\r
+private:\r
+  CMyComPtr<IInStream> _inStream;\r
+  NArchive::N7z::CArchiveDatabaseEx _db;\r
+  #ifndef _NO_CRYPTO\r
+  bool _passwordIsDefined;\r
+  #endif\r
+\r
+  #ifdef EXTRACT_ONLY\r
+  \r
+  #ifdef __7Z_SET_PROPERTIES\r
+  UInt32 _numThreads;\r
+  #endif\r
+\r
+  UInt32 _crcSize;\r
+\r
+  #else\r
+  \r
+  CRecordVector<CBind> _binds;\r
+\r
+  HRESULT SetCompressionMethod(CCompressionMethodMode &method,\r
+      CObjectVector<COneMethodInfo> &methodsInfo\r
+      #ifndef _7ZIP_ST\r
+      , UInt32 numThreads\r
+      #endif\r
+      );\r
+\r
+  HRESULT SetCompressionMethod(\r
+      CCompressionMethodMode &method,\r
+      CCompressionMethodMode &headerMethod);\r
+\r
+  #endif\r
+\r
+  bool IsEncrypted(UInt32 index2) const;\r
+  #ifndef _SFX\r
+\r
+  CRecordVector<UInt64> _fileInfoPopIDs;\r
+  void FillPopIDs();\r
+\r
+  #endif\r
+\r
+  DECL_EXTERNAL_CODECS_VARS\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
new file mode 100755 (executable)
index 0000000..59d6269
--- /dev/null
@@ -0,0 +1,483 @@
+// 7zHandlerOut.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../Windows/PropVariant.h"\r
+\r
+#include "../../../Common/ComTry.h"\r
+#include "../../../Common/StringToInt.h"\r
+\r
+#include "../../ICoder.h"\r
+\r
+#include "../Common/ItemNameUtils.h"\r
+#include "../Common/ParseProperties.h"\r
+\r
+#include "7zHandler.h"\r
+#include "7zOut.h"\r
+#include "7zUpdate.h"\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+static const wchar_t *kLZMAMethodName = L"LZMA";\r
+static const wchar_t *kCopyMethod = L"Copy";\r
+static const wchar_t *kDefaultMethodName = kLZMAMethodName;\r
+\r
+static const UInt32 kLzmaAlgorithmX5 = 1;\r
+static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";\r
+static const UInt32 kDictionaryForHeaders =\r
+  #ifdef UNDER_CE\r
+  1 << 18\r
+  #else\r
+  1 << 20\r
+  #endif\r
+;\r
+static const UInt32 kNumFastBytesForHeaders = 273;\r
+static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5;\r
+\r
+static inline bool IsCopyMethod(const UString &methodName)\r
+  { return (methodName.CompareNoCase(kCopyMethod) == 0); }\r
+\r
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)\r
+{\r
+  *type = NFileTimeType::kWindows;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CHandler::SetCompressionMethod(\r
+    CCompressionMethodMode &methodMode,\r
+    CCompressionMethodMode &headerMethod)\r
+{\r
+  HRESULT res = SetCompressionMethod(methodMode, _methods\r
+  #ifndef _7ZIP_ST\r
+  , _numThreads\r
+  #endif\r
+  );\r
+  RINOK(res);\r
+  methodMode.Binds = _binds;\r
+\r
+  if (_compressHeaders)\r
+  {\r
+    // headerMethod.Methods.Add(methodMode.Methods.Back());\r
+\r
+    CObjectVector<COneMethodInfo> headerMethodInfoVector;\r
+    COneMethodInfo oneMethodInfo;\r
+    oneMethodInfo.MethodName = kLZMAMethodName;\r
+    {\r
+      CProp prop;\r
+      prop.Id = NCoderPropID::kMatchFinder;\r
+      prop.Value = kLzmaMatchFinderForHeaders;\r
+      oneMethodInfo.Props.Add(prop);\r
+    }\r
+    {\r
+      CProp prop;\r
+      prop.Id = NCoderPropID::kAlgorithm;\r
+      prop.Value = kAlgorithmForHeaders;\r
+      oneMethodInfo.Props.Add(prop);\r
+    }\r
+    {\r
+      CProp prop;\r
+      prop.Id = NCoderPropID::kNumFastBytes;\r
+      prop.Value = (UInt32)kNumFastBytesForHeaders;\r
+      oneMethodInfo.Props.Add(prop);\r
+    }\r
+    {\r
+      CProp prop;\r
+      prop.Id = NCoderPropID::kDictionarySize;\r
+      prop.Value = (UInt32)kDictionaryForHeaders;\r
+      oneMethodInfo.Props.Add(prop);\r
+    }\r
+    headerMethodInfoVector.Add(oneMethodInfo);\r
+    HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector\r
+      #ifndef _7ZIP_ST\r
+      , 1\r
+      #endif\r
+    );\r
+    RINOK(res);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CHandler::SetCompressionMethod(\r
+    CCompressionMethodMode &methodMode,\r
+    CObjectVector<COneMethodInfo> &methodsInfo\r
+    #ifndef _7ZIP_ST\r
+    , UInt32 numThreads\r
+    #endif\r
+    )\r
+{\r
+  UInt32 level = _level;\r
+  \r
+  if (methodsInfo.IsEmpty())\r
+  {\r
+    COneMethodInfo oneMethodInfo;\r
+    oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName);\r
+    methodsInfo.Add(oneMethodInfo);\r
+  }\r
+\r
+  bool needSolid = false;\r
+  for(int i = 0; i < methodsInfo.Size(); i++)\r
+  {\r
+    COneMethodInfo &oneMethodInfo = methodsInfo[i];\r
+    SetCompressionMethod2(oneMethodInfo\r
+      #ifndef _7ZIP_ST\r
+      , numThreads\r
+      #endif\r
+      );\r
+\r
+    if (!IsCopyMethod(oneMethodInfo.MethodName))\r
+      needSolid = true;\r
+\r
+    CMethodFull methodFull;\r
+\r
+    if (!FindMethod(\r
+        EXTERNAL_CODECS_VARS\r
+        oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams))\r
+      return E_INVALIDARG;\r
+    methodFull.Props = oneMethodInfo.Props;\r
+    methodMode.Methods.Add(methodFull);\r
+\r
+    if (!_numSolidBytesDefined)\r
+    {\r
+      for (int j = 0; j < methodFull.Props.Size(); j++)\r
+      {\r
+        const CProp &prop = methodFull.Props[j];\r
+        if ((prop.Id == NCoderPropID::kDictionarySize ||\r
+             prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4)\r
+        {\r
+          _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7;\r
+          const UInt64 kMinSize = (1 << 24);\r
+          if (_numSolidBytes < kMinSize)\r
+            _numSolidBytes = kMinSize;\r
+          _numSolidBytesDefined = true;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (!needSolid && !_numSolidBytesDefined)\r
+  {\r
+    _numSolidBytesDefined = true;\r
+    _numSolidBytes  = 0;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, bool writeTime, PROPID propID, UInt64 &ft, bool &ftDefined)\r
+{\r
+  ft = 0;\r
+  ftDefined = false;\r
+  if (!writeTime)\r
+    return S_OK;\r
+  NCOM::CPropVariant prop;\r
+  RINOK(updateCallback->GetProperty(index, propID, &prop));\r
+  if (prop.vt == VT_FILETIME)\r
+  {\r
+    ft = prop.filetime.dwLowDateTime | ((UInt64)prop.filetime.dwHighDateTime << 32);\r
+    ftDefined = true;\r
+  }\r
+  else if (prop.vt != VT_EMPTY)\r
+    return E_INVALIDARG;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\r
+    IArchiveUpdateCallback *updateCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+\r
+  const CArchiveDatabaseEx *db = 0;\r
+  #ifdef _7Z_VOL\r
+  if (_volumes.Size() > 1)\r
+    return E_FAIL;\r
+  const CVolume *volume = 0;\r
+  if (_volumes.Size() == 1)\r
+  {\r
+    volume = &_volumes.Front();\r
+    db = &volume->Database;\r
+  }\r
+  #else\r
+  if (_inStream != 0)\r
+    db = &_db;\r
+  #endif\r
+\r
+  CObjectVector<CUpdateItem> updateItems;\r
+  \r
+  for (UInt32 i = 0; i < numItems; i++)\r
+  {\r
+    Int32 newData, newProps;\r
+    UInt32 indexInArchive;\r
+    if (!updateCallback)\r
+      return E_FAIL;\r
+    RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));\r
+    CUpdateItem ui;\r
+    ui.NewProps = IntToBool(newProps);\r
+    ui.NewData = IntToBool(newData);\r
+    ui.IndexInArchive = indexInArchive;\r
+    ui.IndexInClient = i;\r
+    ui.IsAnti = false;\r
+    ui.Size = 0;\r
+\r
+    if (ui.IndexInArchive != -1)\r
+    {\r
+      if (db == 0 || ui.IndexInArchive >= db->Files.Size())\r
+        return E_INVALIDARG;\r
+      const CFileItem &fi = db->Files[ui.IndexInArchive];\r
+      ui.Name = fi.Name;\r
+      ui.IsDir = fi.IsDir;\r
+      ui.Size = fi.Size;\r
+      ui.IsAnti = db->IsItemAnti(ui.IndexInArchive);\r
+      \r
+      ui.CTimeDefined = db->CTime.GetItem(ui.IndexInArchive, ui.CTime);\r
+      ui.ATimeDefined = db->ATime.GetItem(ui.IndexInArchive, ui.ATime);\r
+      ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime);\r
+    }\r
+\r
+    if (ui.NewProps)\r
+    {\r
+      bool nameIsDefined;\r
+      bool folderStatusIsDefined;\r
+      {\r
+        NCOM::CPropVariant prop;\r
+        RINOK(updateCallback->GetProperty(i, kpidAttrib, &prop));\r
+        if (prop.vt == VT_EMPTY)\r
+          ui.AttribDefined = false;\r
+        else if (prop.vt != VT_UI4)\r
+          return E_INVALIDARG;\r
+        else\r
+        {\r
+          ui.Attrib = prop.ulVal;\r
+          ui.AttribDefined = true;\r
+        }\r
+      }\r
+      \r
+      // we need MTime to sort files.\r
+      RINOK(GetTime(updateCallback, i, WriteCTime, kpidCTime, ui.CTime, ui.CTimeDefined));\r
+      RINOK(GetTime(updateCallback, i, WriteATime, kpidATime, ui.ATime, ui.ATimeDefined));\r
+      RINOK(GetTime(updateCallback, i, true,       kpidMTime, ui.MTime, ui.MTimeDefined));\r
+\r
+      {\r
+        NCOM::CPropVariant prop;\r
+        RINOK(updateCallback->GetProperty(i, kpidPath, &prop));\r
+        if (prop.vt == VT_EMPTY)\r
+          nameIsDefined = false;\r
+        else if (prop.vt != VT_BSTR)\r
+          return E_INVALIDARG;\r
+        else\r
+        {\r
+          ui.Name = NItemName::MakeLegalName(prop.bstrVal);\r
+          nameIsDefined = true;\r
+        }\r
+      }\r
+      {\r
+        NCOM::CPropVariant prop;\r
+        RINOK(updateCallback->GetProperty(i, kpidIsDir, &prop));\r
+        if (prop.vt == VT_EMPTY)\r
+          folderStatusIsDefined = false;\r
+        else if (prop.vt != VT_BOOL)\r
+          return E_INVALIDARG;\r
+        else\r
+        {\r
+          ui.IsDir = (prop.boolVal != VARIANT_FALSE);\r
+          folderStatusIsDefined = true;\r
+        }\r
+      }\r
+\r
+      {\r
+        NCOM::CPropVariant prop;\r
+        RINOK(updateCallback->GetProperty(i, kpidIsAnti, &prop));\r
+        if (prop.vt == VT_EMPTY)\r
+          ui.IsAnti = false;\r
+        else if (prop.vt != VT_BOOL)\r
+          return E_INVALIDARG;\r
+        else\r
+          ui.IsAnti = (prop.boolVal != VARIANT_FALSE);\r
+      }\r
+\r
+      if (ui.IsAnti)\r
+      {\r
+        ui.AttribDefined = false;\r
+\r
+        ui.CTimeDefined = false;\r
+        ui.ATimeDefined = false;\r
+        ui.MTimeDefined = false;\r
+        \r
+        ui.Size = 0;\r
+      }\r
+\r
+      if (!folderStatusIsDefined && ui.AttribDefined)\r
+        ui.SetDirStatusFromAttrib();\r
+    }\r
+\r
+    if (ui.NewData)\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      RINOK(updateCallback->GetProperty(i, kpidSize, &prop));\r
+      if (prop.vt != VT_UI8)\r
+        return E_INVALIDARG;\r
+      ui.Size = (UInt64)prop.uhVal.QuadPart;\r
+      if (ui.Size != 0 && ui.IsAnti)\r
+        return E_INVALIDARG;\r
+    }\r
+    updateItems.Add(ui);\r
+  }\r
+\r
+  CCompressionMethodMode methodMode, headerMethod;\r
+  RINOK(SetCompressionMethod(methodMode, headerMethod));\r
+  #ifndef _7ZIP_ST\r
+  methodMode.NumThreads = _numThreads;\r
+  headerMethod.NumThreads = 1;\r
+  #endif\r
+\r
+  CMyComPtr<ICryptoGetTextPassword2> getPassword2;\r
+  updateCallback->QueryInterface(IID_ICryptoGetTextPassword2, (void **)&getPassword2);\r
+\r
+  if (getPassword2)\r
+  {\r
+    CMyComBSTR password;\r
+    Int32 passwordIsDefined;\r
+    RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password));\r
+    methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);\r
+    if (methodMode.PasswordIsDefined)\r
+      methodMode.Password = password;\r
+  }\r
+  else\r
+    methodMode.PasswordIsDefined = false;\r
+\r
+  bool compressMainHeader = _compressHeaders;  // check it\r
+\r
+  bool encryptHeaders = false;\r
+\r
+  if (methodMode.PasswordIsDefined)\r
+  {\r
+    if (_encryptHeadersSpecified)\r
+      encryptHeaders = _encryptHeaders;\r
+    #ifndef _NO_CRYPTO\r
+    else\r
+      encryptHeaders = _passwordIsDefined;\r
+    #endif\r
+    compressMainHeader = true;\r
+    if (encryptHeaders)\r
+    {\r
+      headerMethod.PasswordIsDefined = methodMode.PasswordIsDefined;\r
+      headerMethod.Password = methodMode.Password;\r
+    }\r
+  }\r
+\r
+  if (numItems < 2)\r
+    compressMainHeader = false;\r
+\r
+  CUpdateOptions options;\r
+  options.Method = &methodMode;\r
+  options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0;\r
+  options.UseFilters = _level != 0 && _autoFilter;\r
+  options.MaxFilter = _level >= 8;\r
+\r
+  options.HeaderOptions.CompressMainHeader = compressMainHeader;\r
+  options.HeaderOptions.WriteCTime = WriteCTime;\r
+  options.HeaderOptions.WriteATime = WriteATime;\r
+  options.HeaderOptions.WriteMTime = WriteMTime;\r
+  \r
+  options.NumSolidFiles = _numSolidFiles;\r
+  options.NumSolidBytes = _numSolidBytes;\r
+  options.SolidExtension = _solidExtension;\r
+  options.RemoveSfxBlock = _removeSfxBlock;\r
+  options.VolumeMode = _volumeMode;\r
+\r
+  COutArchive archive;\r
+  CArchiveDatabase newDatabase;\r
+\r
+  CMyComPtr<ICryptoGetTextPassword> getPassword;\r
+  updateCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getPassword);\r
+  \r
+  HRESULT res = Update(\r
+      EXTERNAL_CODECS_VARS\r
+      #ifdef _7Z_VOL\r
+      volume ? volume->Stream: 0,\r
+      volume ? db : 0,\r
+      #else\r
+      _inStream,\r
+      db,\r
+      #endif\r
+      updateItems,\r
+      archive, newDatabase, outStream, updateCallback, options\r
+      #ifndef _NO_CRYPTO\r
+      , getPassword\r
+      #endif\r
+      );\r
+\r
+  RINOK(res);\r
+\r
+  updateItems.ClearAndFree();\r
+\r
+  return archive.WriteDatabase(EXTERNAL_CODECS_VARS\r
+      newDatabase, options.HeaderMethod, options.HeaderOptions);\r
+\r
+  COM_TRY_END\r
+}\r
+\r
+static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream)\r
+{\r
+  stream = 0;\r
+  int index = ParseStringToUInt32(srcString, coder);\r
+  if (index == 0)\r
+    return E_INVALIDARG;\r
+  srcString.Delete(0, index);\r
+  if (srcString[0] == 'S')\r
+  {\r
+    srcString.Delete(0);\r
+    int index = ParseStringToUInt32(srcString, stream);\r
+    if (index == 0)\r
+      return E_INVALIDARG;\r
+    srcString.Delete(0, index);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+static HRESULT GetBindInfo(UString &srcString, CBind &bind)\r
+{\r
+  RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream));\r
+  if (srcString[0] != ':')\r
+    return E_INVALIDARG;\r
+  srcString.Delete(0);\r
+  RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream));\r
+  if (!srcString.IsEmpty())\r
+    return E_INVALIDARG;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)\r
+{\r
+  COM_TRY_BEGIN\r
+  _binds.Clear();\r
+  BeforeSetProperty();\r
+\r
+  for (int i = 0; i < numProperties; i++)\r
+  {\r
+    UString name = names[i];\r
+    name.MakeUpper();\r
+    if (name.IsEmpty())\r
+      return E_INVALIDARG;\r
+\r
+    const PROPVARIANT &value = values[i];\r
+\r
+    if (name[0] == 'B')\r
+    {\r
+      name.Delete(0);\r
+      CBind bind;\r
+      RINOK(GetBindInfo(name, bind));\r
+      _binds.Add(bind);\r
+      continue;\r
+    }\r
+\r
+    RINOK(SetProperty(name, value));\r
+  }\r
+\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/7z/7zHeader.cpp b/CPP/7zip/Archive/7z/7zHeader.cpp
new file mode 100755 (executable)
index 0000000..d93670c
--- /dev/null
@@ -0,0 +1,14 @@
+// 7zHeader.cpp\r
+\r
+#include "StdAfx.h"\r
+#include "7zHeader.h"\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+Byte kSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};\r
+#ifdef _7Z_VOL\r
+Byte kFinishSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C + 1};\r
+#endif\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/7z/7zHeader.h b/CPP/7zip/Archive/7z/7zHeader.h
new file mode 100755 (executable)
index 0000000..57f455b
--- /dev/null
@@ -0,0 +1,97 @@
+// 7z/7zHeader.h\r
+\r
+#ifndef __7Z_HEADER_H\r
+#define __7Z_HEADER_H\r
+\r
+#include "../../../Common/Types.h"\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+const int kSignatureSize = 6;\r
+extern Byte kSignature[kSignatureSize];\r
+\r
+// #define _7Z_VOL\r
+// 7z-MultiVolume is not finished yet.\r
+// It can work already, but I still do not like some\r
+// things of that new multivolume format.\r
+// So please keep it commented.\r
+\r
+#ifdef _7Z_VOL\r
+extern Byte kFinishSignature[kSignatureSize];\r
+#endif\r
+\r
+struct CArchiveVersion\r
+{\r
+  Byte Major;\r
+  Byte Minor;\r
+};\r
+\r
+const Byte kMajorVersion = 0;\r
+\r
+struct CStartHeader\r
+{\r
+  UInt64 NextHeaderOffset;\r
+  UInt64 NextHeaderSize;\r
+  UInt32 NextHeaderCRC;\r
+};\r
+\r
+const UInt32 kStartHeaderSize = 20;\r
+\r
+#ifdef _7Z_VOL\r
+struct CFinishHeader: public CStartHeader\r
+{\r
+  UInt64 ArchiveStartOffset;  // data offset from end if that struct\r
+  UInt64 AdditionalStartBlockSize; // start  signature & start header size\r
+};\r
+\r
+const UInt32 kFinishHeaderSize = kStartHeaderSize + 16;\r
+#endif\r
+\r
+namespace NID\r
+{\r
+  enum EEnum\r
+  {\r
+    kEnd,\r
+\r
+    kHeader,\r
+\r
+    kArchiveProperties,\r
+    \r
+    kAdditionalStreamsInfo,\r
+    kMainStreamsInfo,\r
+    kFilesInfo,\r
+    \r
+    kPackInfo,\r
+    kUnpackInfo,\r
+    kSubStreamsInfo,\r
+\r
+    kSize,\r
+    kCRC,\r
+\r
+    kFolder,\r
+\r
+    kCodersUnpackSize,\r
+    kNumUnpackStream,\r
+\r
+    kEmptyStream,\r
+    kEmptyFile,\r
+    kAnti,\r
+\r
+    kName,\r
+    kCTime,\r
+    kATime,\r
+    kMTime,\r
+    kWinAttributes,\r
+    kComment,\r
+\r
+    kEncodedHeader,\r
+\r
+    kStartPos,\r
+    kDummy\r
+  };\r
+}\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp
new file mode 100755 (executable)
index 0000000..f418bb1
--- /dev/null
@@ -0,0 +1,1276 @@
+// 7zIn.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/7zCrc.h"\r
+#include "../../../../C/CpuArch.h"\r
+\r
+#include "../../Common/StreamObjects.h"\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "7zDecode.h"\r
+#include "7zIn.h"\r
+\r
+#define Get16(p) GetUi16(p)\r
+#define Get32(p) GetUi32(p)\r
+#define Get64(p) GetUi64(p)\r
+\r
+// define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader\r
+#ifndef _SFX\r
+#define FORMAT_7Z_RECOVERY\r
+#endif\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+static void BoolVector_Fill_False(CBoolVector &v, int size)\r
+{\r
+  v.Clear();\r
+  v.Reserve(size);\r
+  for (int i = 0; i < size; i++)\r
+    v.Add(false);\r
+}\r
+\r
+static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index)\r
+{\r
+  if (index >= (UInt32)v.Size())\r
+    return true;\r
+  bool res = v[index];\r
+  v[index] = true;\r
+  return res;\r
+}\r
+\r
+bool CFolder::CheckStructure() const\r
+{\r
+  const int kNumCodersMax = sizeof(UInt32) * 8; // don't change it\r
+  const int kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax\r
+  const int kNumBindsMax = 32;\r
+\r
+  if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax)\r
+    return false;\r
+\r
+  {\r
+    CBoolVector v;\r
+    BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size());\r
+    \r
+    int i;\r
+    for (i = 0; i < BindPairs.Size(); i++)\r
+      if (BoolVector_GetAndSet(v, BindPairs[i].InIndex))\r
+        return false;\r
+    for (i = 0; i < PackStreams.Size(); i++)\r
+      if (BoolVector_GetAndSet(v, PackStreams[i]))\r
+        return false;\r
+    \r
+    BoolVector_Fill_False(v, UnpackSizes.Size());\r
+    for (i = 0; i < BindPairs.Size(); i++)\r
+      if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex))\r
+        return false;\r
+  }\r
+  \r
+  UInt32 mask[kMaskSize];\r
+  int i;\r
+  for (i = 0; i < kMaskSize; i++)\r
+    mask[i] = 0;\r
+\r
+  {\r
+    CIntVector inStreamToCoder, outStreamToCoder;\r
+    for (i = 0; i < Coders.Size(); i++)\r
+    {\r
+      CNum j;\r
+      const CCoderInfo &coder = Coders[i];\r
+      for (j = 0; j < coder.NumInStreams; j++)\r
+        inStreamToCoder.Add(i);\r
+      for (j = 0; j < coder.NumOutStreams; j++)\r
+        outStreamToCoder.Add(i);\r
+    }\r
+    \r
+    for (i = 0; i < BindPairs.Size(); i++)\r
+    {\r
+      const CBindPair &bp = BindPairs[i];\r
+      mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]);\r
+    }\r
+  }\r
+  \r
+  for (i = 0; i < kMaskSize; i++)\r
+    for (int j = 0; j < kMaskSize; j++)\r
+      if (((1 << j) & mask[i]) != 0)\r
+        mask[i] |= mask[j];\r
+\r
+  for (i = 0; i < kMaskSize; i++)\r
+    if (((1 << i) & mask[i]) != 0)\r
+      return false;\r
+\r
+  return true;\r
+}\r
+\r
+class CInArchiveException {};\r
+\r
+static void ThrowException() { throw CInArchiveException(); }\r
+static inline void ThrowEndOfData()   { ThrowException(); }\r
+static inline void ThrowUnsupported() { ThrowException(); }\r
+static inline void ThrowIncorrect()   { ThrowException(); }\r
+static inline void ThrowUnsupportedVersion() { ThrowException(); }\r
+\r
+/*\r
+class CInArchiveException\r
+{\r
+public:\r
+  enum CCauseType\r
+  {\r
+    kUnsupportedVersion = 0,\r
+    kUnsupported,\r
+    kIncorrect,\r
+    kEndOfData\r
+  } Cause;\r
+  CInArchiveException(CCauseType cause): Cause(cause) {};\r
+};\r
+\r
+static void ThrowException(CInArchiveException::CCauseType c) { throw CInArchiveException(c); }\r
+static void ThrowEndOfData()   { ThrowException(CInArchiveException::kEndOfData); }\r
+static void ThrowUnsupported() { ThrowException(CInArchiveException::kUnsupported); }\r
+static void ThrowIncorrect()   { ThrowException(CInArchiveException::kIncorrect); }\r
+static void ThrowUnsupportedVersion() { ThrowException(CInArchiveException::kUnsupportedVersion); }\r
+*/\r
+\r
+class CStreamSwitch\r
+{\r
+  CInArchive *_archive;\r
+  bool _needRemove;\r
+public:\r
+  CStreamSwitch(): _needRemove(false) {}\r
+  ~CStreamSwitch() { Remove(); }\r
+  void Remove();\r
+  void Set(CInArchive *archive, const Byte *data, size_t size);\r
+  void Set(CInArchive *archive, const CByteBuffer &byteBuffer);\r
+  void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector);\r
+};\r
+\r
+void CStreamSwitch::Remove()\r
+{\r
+  if (_needRemove)\r
+  {\r
+    _archive->DeleteByteStream();\r
+    _needRemove = false;\r
+  }\r
+}\r
+\r
+void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size)\r
+{\r
+  Remove();\r
+  _archive = archive;\r
+  _archive->AddByteStream(data, size);\r
+  _needRemove = true;\r
+}\r
+\r
+void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer)\r
+{\r
+  Set(archive, byteBuffer, byteBuffer.GetCapacity());\r
+}\r
+\r
+void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector)\r
+{\r
+  Remove();\r
+  Byte external = archive->ReadByte();\r
+  if (external != 0)\r
+  {\r
+    int dataIndex = (int)archive->ReadNum();\r
+    if (dataIndex < 0 || dataIndex >= dataVector->Size())\r
+      ThrowIncorrect();\r
+    Set(archive, (*dataVector)[dataIndex]);\r
+  }\r
+}\r
+\r
+Byte CInByte2::ReadByte()\r
+{\r
+  if (_pos >= _size)\r
+    ThrowEndOfData();\r
+  return _buffer[_pos++];\r
+}\r
+\r
+void CInByte2::ReadBytes(Byte *data, size_t size)\r
+{\r
+  if (size > _size - _pos)\r
+    ThrowEndOfData();\r
+  for (size_t i = 0; i < size; i++)\r
+    data[i] = _buffer[_pos++];\r
+}\r
+\r
+void CInByte2::SkipData(UInt64 size)\r
+{\r
+  if (size > _size - _pos)\r
+    ThrowEndOfData();\r
+  _pos += (size_t)size;\r
+}\r
+\r
+void CInByte2::SkipData()\r
+{\r
+  SkipData(ReadNumber());\r
+}\r
+\r
+UInt64 CInByte2::ReadNumber()\r
+{\r
+  if (_pos >= _size)\r
+    ThrowEndOfData();\r
+  Byte firstByte = _buffer[_pos++];\r
+  Byte mask = 0x80;\r
+  UInt64 value = 0;\r
+  for (int i = 0; i < 8; i++)\r
+  {\r
+    if ((firstByte & mask) == 0)\r
+    {\r
+      UInt64 highPart = firstByte & (mask - 1);\r
+      value += (highPart << (i * 8));\r
+      return value;\r
+    }\r
+    if (_pos >= _size)\r
+      ThrowEndOfData();\r
+    value |= ((UInt64)_buffer[_pos++] << (8 * i));\r
+    mask >>= 1;\r
+  }\r
+  return value;\r
+}\r
+\r
+CNum CInByte2::ReadNum()\r
+{\r
+  UInt64 value = ReadNumber();\r
+  if (value > kNumMax)\r
+    ThrowUnsupported();\r
+  return (CNum)value;\r
+}\r
+\r
+UInt32 CInByte2::ReadUInt32()\r
+{\r
+  if (_pos + 4 > _size)\r
+    ThrowEndOfData();\r
+  UInt32 res = Get32(_buffer + _pos);\r
+  _pos += 4;\r
+  return res;\r
+}\r
+\r
+UInt64 CInByte2::ReadUInt64()\r
+{\r
+  if (_pos + 8 > _size)\r
+    ThrowEndOfData();\r
+  UInt64 res = Get64(_buffer + _pos);\r
+  _pos += 8;\r
+  return res;\r
+}\r
+\r
+void CInByte2::ReadString(UString &s)\r
+{\r
+  const Byte *buf = _buffer + _pos;\r
+  size_t rem = (_size - _pos) / 2 * 2;\r
+  {\r
+    size_t i;\r
+    for (i = 0; i < rem; i += 2)\r
+      if (buf[i] == 0 && buf[i + 1] == 0)\r
+        break;\r
+    if (i == rem)\r
+      ThrowEndOfData();\r
+    rem = i;\r
+  }\r
+  int len = (int)(rem / 2);\r
+  if (len < 0 || (size_t)len * 2 != rem)\r
+    ThrowUnsupported();\r
+  wchar_t *p = s.GetBuffer(len);\r
+  int i;\r
+  for (i = 0; i < len; i++, buf += 2)\r
+    p[i] = (wchar_t)Get16(buf);\r
+  s.ReleaseBuffer(len);\r
+  _pos += rem + 2;\r
+}\r
+\r
+static inline bool TestSignature(const Byte *p)\r
+{\r
+  for (int i = 0; i < kSignatureSize; i++)\r
+    if (p[i] != kSignature[i])\r
+      return false;\r
+  return CrcCalc(p + 12, 20) == GetUi32(p + 8);\r
+}\r
+\r
+#ifdef FORMAT_7Z_RECOVERY\r
+static inline bool TestSignature2(const Byte *p)\r
+{\r
+  int i;\r
+  for (i = 0; i < kSignatureSize; i++)\r
+    if (p[i] != kSignature[i])\r
+      return false;\r
+  if (CrcCalc(p + 12, 20) == GetUi32(p + 8))\r
+    return true;\r
+  for (i = 8; i < kHeaderSize; i++)\r
+    if (p[i] != 0)\r
+      return false;\r
+  return (p[6] != 0 || p[7] != 0);\r
+}\r
+#else\r
+#define TestSignature2(p) TestSignature(p)\r
+#endif\r
+\r
+HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit)\r
+{\r
+  RINOK(ReadStream_FALSE(stream, _header, kHeaderSize));\r
+\r
+  if (TestSignature2(_header))\r
+    return S_OK;\r
+\r
+  CByteBuffer byteBuffer;\r
+  const UInt32 kBufferSize = (1 << 16);\r
+  byteBuffer.SetCapacity(kBufferSize);\r
+  Byte *buffer = byteBuffer;\r
+  UInt32 numPrevBytes = kHeaderSize;\r
+  memcpy(buffer, _header, kHeaderSize);\r
+  UInt64 curTestPos = _arhiveBeginStreamPosition;\r
+  for (;;)\r
+  {\r
+    if (searchHeaderSizeLimit != NULL)\r
+      if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit)\r
+        break;\r
+    do\r
+    {\r
+      UInt32 numReadBytes = kBufferSize - numPrevBytes;\r
+      UInt32 processedSize;\r
+      RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize));\r
+      numPrevBytes += processedSize;\r
+      if (processedSize == 0)\r
+        return S_FALSE;\r
+    }\r
+    while (numPrevBytes <= kHeaderSize);\r
+    UInt32 numTests = numPrevBytes - kHeaderSize;\r
+    for (UInt32 pos = 0; pos < numTests; pos++)\r
+    {\r
+      for (; buffer[pos] != '7' && pos < numTests; pos++);\r
+      if (pos == numTests)\r
+        break;\r
+      if (TestSignature(buffer + pos))\r
+      {\r
+        memcpy(_header, buffer + pos, kHeaderSize);\r
+        curTestPos += pos;\r
+        _arhiveBeginStreamPosition = curTestPos;\r
+        return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL);\r
+      }\r
+    }\r
+    curTestPos += numTests;\r
+    numPrevBytes -= numTests;\r
+    memmove(buffer, buffer + numTests, numPrevBytes);\r
+  }\r
+  return S_FALSE;\r
+}\r
+\r
+// S_FALSE means that file is not archive\r
+HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit)\r
+{\r
+  HeadersSize = 0;\r
+  Close();\r
+  RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition))\r
+  RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit));\r
+  _stream = stream;\r
+  return S_OK;\r
+}\r
+  \r
+void CInArchive::Close()\r
+{\r
+  _stream.Release();\r
+}\r
+\r
+void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)\r
+{\r
+  for (;;)\r
+  {\r
+    if (ReadID() == NID::kEnd)\r
+      break;\r
+    SkipData();\r
+  }\r
+}\r
+\r
+void CInArchive::GetNextFolderItem(CFolder &folder)\r
+{\r
+  CNum numCoders = ReadNum();\r
+\r
+  folder.Coders.Clear();\r
+  folder.Coders.Reserve((int)numCoders);\r
+  CNum numInStreams = 0;\r
+  CNum numOutStreams = 0;\r
+  CNum i;\r
+  for (i = 0; i < numCoders; i++)\r
+  {\r
+    folder.Coders.Add(CCoderInfo());\r
+    CCoderInfo &coder = folder.Coders.Back();\r
+\r
+    {\r
+      Byte mainByte = ReadByte();\r
+      int idSize = (mainByte & 0xF);\r
+      Byte longID[15];\r
+      ReadBytes(longID, idSize);\r
+      if (idSize > 8)\r
+        ThrowUnsupported();\r
+      UInt64 id = 0;\r
+      for (int j = 0; j < idSize; j++)\r
+        id |= (UInt64)longID[idSize - 1 - j] << (8 * j);\r
+      coder.MethodID = id;\r
+\r
+      if ((mainByte & 0x10) != 0)\r
+      {\r
+        coder.NumInStreams = ReadNum();\r
+        coder.NumOutStreams = ReadNum();\r
+      }\r
+      else\r
+      {\r
+        coder.NumInStreams = 1;\r
+        coder.NumOutStreams = 1;\r
+      }\r
+      if ((mainByte & 0x20) != 0)\r
+      {\r
+        CNum propsSize = ReadNum();\r
+        coder.Props.SetCapacity((size_t)propsSize);\r
+        ReadBytes((Byte *)coder.Props, (size_t)propsSize);\r
+      }\r
+      if ((mainByte & 0x80) != 0)\r
+        ThrowUnsupported();\r
+    }\r
+    numInStreams += coder.NumInStreams;\r
+    numOutStreams += coder.NumOutStreams;\r
+  }\r
+\r
+  CNum numBindPairs = numOutStreams - 1;\r
+  folder.BindPairs.Clear();\r
+  folder.BindPairs.Reserve(numBindPairs);\r
+  for (i = 0; i < numBindPairs; i++)\r
+  {\r
+    CBindPair bp;\r
+    bp.InIndex = ReadNum();\r
+    bp.OutIndex = ReadNum();\r
+    folder.BindPairs.Add(bp);\r
+  }\r
+\r
+  if (numInStreams < numBindPairs)\r
+    ThrowUnsupported();\r
+  CNum numPackStreams = numInStreams - numBindPairs;\r
+  folder.PackStreams.Reserve(numPackStreams);\r
+  if (numPackStreams == 1)\r
+  {\r
+    for (i = 0; i < numInStreams; i++)\r
+      if (folder.FindBindPairForInStream(i) < 0)\r
+      {\r
+        folder.PackStreams.Add(i);\r
+        break;\r
+      }\r
+    if (folder.PackStreams.Size() != 1)\r
+      ThrowUnsupported();\r
+  }\r
+  else\r
+    for (i = 0; i < numPackStreams; i++)\r
+      folder.PackStreams.Add(ReadNum());\r
+}\r
+\r
+void CInArchive::WaitAttribute(UInt64 attribute)\r
+{\r
+  for (;;)\r
+  {\r
+    UInt64 type = ReadID();\r
+    if (type == attribute)\r
+      return;\r
+    if (type == NID::kEnd)\r
+      ThrowIncorrect();\r
+    SkipData();\r
+  }\r
+}\r
+\r
+void CInArchive::ReadHashDigests(int numItems,\r
+    CBoolVector &digestsDefined,\r
+    CRecordVector<UInt32> &digests)\r
+{\r
+  ReadBoolVector2(numItems, digestsDefined);\r
+  digests.Clear();\r
+  digests.Reserve(numItems);\r
+  for (int i = 0; i < numItems; i++)\r
+  {\r
+    UInt32 crc = 0;\r
+    if (digestsDefined[i])\r
+      crc = ReadUInt32();\r
+    digests.Add(crc);\r
+  }\r
+}\r
+\r
+void CInArchive::ReadPackInfo(\r
+    UInt64 &dataOffset,\r
+    CRecordVector<UInt64> &packSizes,\r
+    CBoolVector &packCRCsDefined,\r
+    CRecordVector<UInt32> &packCRCs)\r
+{\r
+  dataOffset = ReadNumber();\r
+  CNum numPackStreams = ReadNum();\r
+\r
+  WaitAttribute(NID::kSize);\r
+  packSizes.Clear();\r
+  packSizes.Reserve(numPackStreams);\r
+  for (CNum i = 0; i < numPackStreams; i++)\r
+    packSizes.Add(ReadNumber());\r
+\r
+  UInt64 type;\r
+  for (;;)\r
+  {\r
+    type = ReadID();\r
+    if (type == NID::kEnd)\r
+      break;\r
+    if (type == NID::kCRC)\r
+    {\r
+      ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs);\r
+      continue;\r
+    }\r
+    SkipData();\r
+  }\r
+  if (packCRCsDefined.IsEmpty())\r
+  {\r
+    BoolVector_Fill_False(packCRCsDefined, numPackStreams);\r
+    packCRCs.Reserve(numPackStreams);\r
+    packCRCs.Clear();\r
+    for (CNum i = 0; i < numPackStreams; i++)\r
+      packCRCs.Add(0);\r
+  }\r
+}\r
+\r
+void CInArchive::ReadUnpackInfo(\r
+    const CObjectVector<CByteBuffer> *dataVector,\r
+    CObjectVector<CFolder> &folders)\r
+{\r
+  WaitAttribute(NID::kFolder);\r
+  CNum numFolders = ReadNum();\r
+\r
+  {\r
+    CStreamSwitch streamSwitch;\r
+    streamSwitch.Set(this, dataVector);\r
+    folders.Clear();\r
+    folders.Reserve(numFolders);\r
+    for (CNum i = 0; i < numFolders; i++)\r
+    {\r
+      folders.Add(CFolder());\r
+      GetNextFolderItem(folders.Back());\r
+    }\r
+  }\r
+\r
+  WaitAttribute(NID::kCodersUnpackSize);\r
+\r
+  CNum i;\r
+  for (i = 0; i < numFolders; i++)\r
+  {\r
+    CFolder &folder = folders[i];\r
+    CNum numOutStreams = folder.GetNumOutStreams();\r
+    folder.UnpackSizes.Reserve(numOutStreams);\r
+    for (CNum j = 0; j < numOutStreams; j++)\r
+      folder.UnpackSizes.Add(ReadNumber());\r
+  }\r
+\r
+  for (;;)\r
+  {\r
+    UInt64 type = ReadID();\r
+    if (type == NID::kEnd)\r
+      return;\r
+    if (type == NID::kCRC)\r
+    {\r
+      CBoolVector crcsDefined;\r
+      CRecordVector<UInt32> crcs;\r
+      ReadHashDigests(numFolders, crcsDefined, crcs);\r
+      for (i = 0; i < numFolders; i++)\r
+      {\r
+        CFolder &folder = folders[i];\r
+        folder.UnpackCRCDefined = crcsDefined[i];\r
+        folder.UnpackCRC = crcs[i];\r
+      }\r
+      continue;\r
+    }\r
+    SkipData();\r
+  }\r
+}\r
+\r
+void CInArchive::ReadSubStreamsInfo(\r
+    const CObjectVector<CFolder> &folders,\r
+    CRecordVector<CNum> &numUnpackStreamsInFolders,\r
+    CRecordVector<UInt64> &unpackSizes,\r
+    CBoolVector &digestsDefined,\r
+    CRecordVector<UInt32> &digests)\r
+{\r
+  numUnpackStreamsInFolders.Clear();\r
+  numUnpackStreamsInFolders.Reserve(folders.Size());\r
+  UInt64 type;\r
+  for (;;)\r
+  {\r
+    type = ReadID();\r
+    if (type == NID::kNumUnpackStream)\r
+    {\r
+      for (int i = 0; i < folders.Size(); i++)\r
+        numUnpackStreamsInFolders.Add(ReadNum());\r
+      continue;\r
+    }\r
+    if (type == NID::kCRC || type == NID::kSize)\r
+      break;\r
+    if (type == NID::kEnd)\r
+      break;\r
+    SkipData();\r
+  }\r
+\r
+  if (numUnpackStreamsInFolders.IsEmpty())\r
+    for (int i = 0; i < folders.Size(); i++)\r
+      numUnpackStreamsInFolders.Add(1);\r
+\r
+  int i;\r
+  for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)\r
+  {\r
+    // v3.13 incorrectly worked with empty folders\r
+    // v4.07: we check that folder is empty\r
+    CNum numSubstreams = numUnpackStreamsInFolders[i];\r
+    if (numSubstreams == 0)\r
+      continue;\r
+    UInt64 sum = 0;\r
+    for (CNum j = 1; j < numSubstreams; j++)\r
+      if (type == NID::kSize)\r
+      {\r
+        UInt64 size = ReadNumber();\r
+        unpackSizes.Add(size);\r
+        sum += size;\r
+      }\r
+    unpackSizes.Add(folders[i].GetUnpackSize() - sum);\r
+  }\r
+  if (type == NID::kSize)\r
+    type = ReadID();\r
+\r
+  int numDigests = 0;\r
+  int numDigestsTotal = 0;\r
+  for (i = 0; i < folders.Size(); i++)\r
+  {\r
+    CNum numSubstreams = numUnpackStreamsInFolders[i];\r
+    if (numSubstreams != 1 || !folders[i].UnpackCRCDefined)\r
+      numDigests += numSubstreams;\r
+    numDigestsTotal += numSubstreams;\r
+  }\r
+\r
+  for (;;)\r
+  {\r
+    if (type == NID::kCRC)\r
+    {\r
+      CBoolVector digestsDefined2;\r
+      CRecordVector<UInt32> digests2;\r
+      ReadHashDigests(numDigests, digestsDefined2, digests2);\r
+      int digestIndex = 0;\r
+      for (i = 0; i < folders.Size(); i++)\r
+      {\r
+        CNum numSubstreams = numUnpackStreamsInFolders[i];\r
+        const CFolder &folder = folders[i];\r
+        if (numSubstreams == 1 && folder.UnpackCRCDefined)\r
+        {\r
+          digestsDefined.Add(true);\r
+          digests.Add(folder.UnpackCRC);\r
+        }\r
+        else\r
+          for (CNum j = 0; j < numSubstreams; j++, digestIndex++)\r
+          {\r
+            digestsDefined.Add(digestsDefined2[digestIndex]);\r
+            digests.Add(digests2[digestIndex]);\r
+          }\r
+      }\r
+    }\r
+    else if (type == NID::kEnd)\r
+    {\r
+      if (digestsDefined.IsEmpty())\r
+      {\r
+        BoolVector_Fill_False(digestsDefined, numDigestsTotal);\r
+        digests.Clear();\r
+        for (int i = 0; i < numDigestsTotal; i++)\r
+          digests.Add(0);\r
+      }\r
+      return;\r
+    }\r
+    else\r
+      SkipData();\r
+    type = ReadID();\r
+  }\r
+}\r
+\r
+void CInArchive::ReadStreamsInfo(\r
+    const CObjectVector<CByteBuffer> *dataVector,\r
+    UInt64 &dataOffset,\r
+    CRecordVector<UInt64> &packSizes,\r
+    CBoolVector &packCRCsDefined,\r
+    CRecordVector<UInt32> &packCRCs,\r
+    CObjectVector<CFolder> &folders,\r
+    CRecordVector<CNum> &numUnpackStreamsInFolders,\r
+    CRecordVector<UInt64> &unpackSizes,\r
+    CBoolVector &digestsDefined,\r
+    CRecordVector<UInt32> &digests)\r
+{\r
+  for (;;)\r
+  {\r
+    UInt64 type = ReadID();\r
+    if (type > ((UInt32)1 << 30))\r
+      ThrowIncorrect();\r
+    switch((UInt32)type)\r
+    {\r
+      case NID::kEnd:\r
+        return;\r
+      case NID::kPackInfo:\r
+      {\r
+        ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs);\r
+        break;\r
+      }\r
+      case NID::kUnpackInfo:\r
+      {\r
+        ReadUnpackInfo(dataVector, folders);\r
+        break;\r
+      }\r
+      case NID::kSubStreamsInfo:\r
+      {\r
+        ReadSubStreamsInfo(folders, numUnpackStreamsInFolders,\r
+            unpackSizes, digestsDefined, digests);\r
+        break;\r
+      }\r
+      default:\r
+        ThrowIncorrect();\r
+    }\r
+  }\r
+}\r
+\r
+void CInArchive::ReadBoolVector(int numItems, CBoolVector &v)\r
+{\r
+  v.Clear();\r
+  v.Reserve(numItems);\r
+  Byte b = 0;\r
+  Byte mask = 0;\r
+  for (int i = 0; i < numItems; i++)\r
+  {\r
+    if (mask == 0)\r
+    {\r
+      b = ReadByte();\r
+      mask = 0x80;\r
+    }\r
+    v.Add((b & mask) != 0);\r
+    mask >>= 1;\r
+  }\r
+}\r
+\r
+void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v)\r
+{\r
+  Byte allAreDefined = ReadByte();\r
+  if (allAreDefined == 0)\r
+  {\r
+    ReadBoolVector(numItems, v);\r
+    return;\r
+  }\r
+  v.Clear();\r
+  v.Reserve(numItems);\r
+  for (int i = 0; i < numItems; i++)\r
+    v.Add(true);\r
+}\r
+\r
+void CInArchive::ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,\r
+    CUInt64DefVector &v, int numFiles)\r
+{\r
+  ReadBoolVector2(numFiles, v.Defined);\r
+\r
+  CStreamSwitch streamSwitch;\r
+  streamSwitch.Set(this, &dataVector);\r
+  v.Values.Reserve(numFiles);\r
+\r
+  for (int i = 0; i < numFiles; i++)\r
+  {\r
+    UInt64 t = 0;\r
+    if (v.Defined[i])\r
+      t = ReadUInt64();\r
+    v.Values.Add(t);\r
+  }\r
+}\r
+\r
+HRESULT CInArchive::ReadAndDecodePackedStreams(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    UInt64 baseOffset,\r
+    UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector\r
+    #ifndef _NO_CRYPTO\r
+    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined\r
+    #endif\r
+    )\r
+{\r
+  CRecordVector<UInt64> packSizes;\r
+  CBoolVector packCRCsDefined;\r
+  CRecordVector<UInt32> packCRCs;\r
+  CObjectVector<CFolder> folders;\r
+  \r
+  CRecordVector<CNum> numUnpackStreamsInFolders;\r
+  CRecordVector<UInt64> unpackSizes;\r
+  CBoolVector digestsDefined;\r
+  CRecordVector<UInt32> digests;\r
+  \r
+  ReadStreamsInfo(NULL,\r
+    dataOffset,\r
+    packSizes,\r
+    packCRCsDefined,\r
+    packCRCs,\r
+    folders,\r
+    numUnpackStreamsInFolders,\r
+    unpackSizes,\r
+    digestsDefined,\r
+    digests);\r
+  \r
+  // db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader;\r
+  \r
+  CNum packIndex = 0;\r
+  CDecoder decoder(\r
+    #ifdef _ST_MODE\r
+    false\r
+    #else\r
+    true\r
+    #endif\r
+    );\r
+  UInt64 dataStartPos = baseOffset + dataOffset;\r
+  for (int i = 0; i < folders.Size(); i++)\r
+  {\r
+    const CFolder &folder = folders[i];\r
+    dataVector.Add(CByteBuffer());\r
+    CByteBuffer &data = dataVector.Back();\r
+    UInt64 unpackSize64 = folder.GetUnpackSize();\r
+    size_t unpackSize = (size_t)unpackSize64;\r
+    if (unpackSize != unpackSize64)\r
+      ThrowUnsupported();\r
+    data.SetCapacity(unpackSize);\r
+    \r
+    CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream;\r
+    CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;\r
+    outStreamSpec->Init(data, unpackSize);\r
+    \r
+    HRESULT result = decoder.Decode(\r
+      EXTERNAL_CODECS_LOC_VARS\r
+      _stream, dataStartPos,\r
+      &packSizes[packIndex], folder, outStream, NULL\r
+      #ifndef _NO_CRYPTO\r
+      , getTextPassword, passwordIsDefined\r
+      #endif\r
+      #if !defined(_7ZIP_ST) && !defined(_SFX)\r
+      , false, 1\r
+      #endif\r
+      );\r
+    RINOK(result);\r
+    \r
+    if (folder.UnpackCRCDefined)\r
+      if (CrcCalc(data, unpackSize) != folder.UnpackCRC)\r
+        ThrowIncorrect();\r
+    for (int j = 0; j < folder.PackStreams.Size(); j++)\r
+    {\r
+      UInt64 packSize = packSizes[packIndex++];\r
+      dataStartPos += packSize;\r
+      HeadersSize += packSize;\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::ReadHeader(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    CArchiveDatabaseEx &db\r
+    #ifndef _NO_CRYPTO\r
+    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined\r
+    #endif\r
+    )\r
+{\r
+  UInt64 type = ReadID();\r
+\r
+  if (type == NID::kArchiveProperties)\r
+  {\r
+    ReadArchiveProperties(db.ArchiveInfo);\r
+    type = ReadID();\r
+  }\r
\r
+  CObjectVector<CByteBuffer> dataVector;\r
+  \r
+  if (type == NID::kAdditionalStreamsInfo)\r
+  {\r
+    HRESULT result = ReadAndDecodePackedStreams(\r
+        EXTERNAL_CODECS_LOC_VARS\r
+        db.ArchiveInfo.StartPositionAfterHeader,\r
+        db.ArchiveInfo.DataStartPosition2,\r
+        dataVector\r
+        #ifndef _NO_CRYPTO\r
+        , getTextPassword, passwordIsDefined\r
+        #endif\r
+        );\r
+    RINOK(result);\r
+    db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader;\r
+    type = ReadID();\r
+  }\r
+\r
+  CRecordVector<UInt64> unpackSizes;\r
+  CBoolVector digestsDefined;\r
+  CRecordVector<UInt32> digests;\r
+  \r
+  if (type == NID::kMainStreamsInfo)\r
+  {\r
+    ReadStreamsInfo(&dataVector,\r
+        db.ArchiveInfo.DataStartPosition,\r
+        db.PackSizes,\r
+        db.PackCRCsDefined,\r
+        db.PackCRCs,\r
+        db.Folders,\r
+        db.NumUnpackStreamsVector,\r
+        unpackSizes,\r
+        digestsDefined,\r
+        digests);\r
+    db.ArchiveInfo.DataStartPosition += db.ArchiveInfo.StartPositionAfterHeader;\r
+    type = ReadID();\r
+  }\r
+  else\r
+  {\r
+    for (int i = 0; i < db.Folders.Size(); i++)\r
+    {\r
+      db.NumUnpackStreamsVector.Add(1);\r
+      CFolder &folder = db.Folders[i];\r
+      unpackSizes.Add(folder.GetUnpackSize());\r
+      digestsDefined.Add(folder.UnpackCRCDefined);\r
+      digests.Add(folder.UnpackCRC);\r
+    }\r
+  }\r
+\r
+  db.Files.Clear();\r
+\r
+  if (type == NID::kEnd)\r
+    return S_OK;\r
+  if (type != NID::kFilesInfo)\r
+    ThrowIncorrect();\r
+  \r
+  CNum numFiles = ReadNum();\r
+  db.Files.Reserve(numFiles);\r
+  CNum i;\r
+  for (i = 0; i < numFiles; i++)\r
+    db.Files.Add(CFileItem());\r
+\r
+  db.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize);\r
+  if (!db.PackSizes.IsEmpty())\r
+    db.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo);\r
+  if (numFiles > 0  && !digests.IsEmpty())\r
+    db.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC);\r
+\r
+  CBoolVector emptyStreamVector;\r
+  BoolVector_Fill_False(emptyStreamVector, (int)numFiles);\r
+  CBoolVector emptyFileVector;\r
+  CBoolVector antiFileVector;\r
+  CNum numEmptyStreams = 0;\r
+\r
+  for (;;)\r
+  {\r
+    UInt64 type = ReadID();\r
+    if (type == NID::kEnd)\r
+      break;\r
+    UInt64 size = ReadNumber();\r
+    size_t ppp = _inByteBack->_pos;\r
+    bool addPropIdToList = true;\r
+    bool isKnownType = true;\r
+    if (type > ((UInt32)1 << 30))\r
+      isKnownType = false;\r
+    else switch((UInt32)type)\r
+    {\r
+      case NID::kName:\r
+      {\r
+        CStreamSwitch streamSwitch;\r
+        streamSwitch.Set(this, &dataVector);\r
+        for (int i = 0; i < db.Files.Size(); i++)\r
+          _inByteBack->ReadString(db.Files[i].Name);\r
+        break;\r
+      }\r
+      case NID::kWinAttributes:\r
+      {\r
+        CBoolVector boolVector;\r
+        ReadBoolVector2(db.Files.Size(), boolVector);\r
+        CStreamSwitch streamSwitch;\r
+        streamSwitch.Set(this, &dataVector);\r
+        for (i = 0; i < numFiles; i++)\r
+        {\r
+          CFileItem &file = db.Files[i];\r
+          file.AttribDefined = boolVector[i];\r
+          if (file.AttribDefined)\r
+            file.Attrib = ReadUInt32();\r
+        }\r
+        break;\r
+      }\r
+      case NID::kEmptyStream:\r
+      {\r
+        ReadBoolVector(numFiles, emptyStreamVector);\r
+        for (i = 0; i < (CNum)emptyStreamVector.Size(); i++)\r
+          if (emptyStreamVector[i])\r
+            numEmptyStreams++;\r
+\r
+        BoolVector_Fill_False(emptyFileVector, numEmptyStreams);\r
+        BoolVector_Fill_False(antiFileVector, numEmptyStreams);\r
+\r
+        break;\r
+      }\r
+      case NID::kEmptyFile:  ReadBoolVector(numEmptyStreams, emptyFileVector); break;\r
+      case NID::kAnti:  ReadBoolVector(numEmptyStreams, antiFileVector); break;\r
+      case NID::kStartPos:  ReadUInt64DefVector(dataVector, db.StartPos, (int)numFiles); break;\r
+      case NID::kCTime:  ReadUInt64DefVector(dataVector, db.CTime, (int)numFiles); break;\r
+      case NID::kATime:  ReadUInt64DefVector(dataVector, db.ATime, (int)numFiles); break;\r
+      case NID::kMTime:  ReadUInt64DefVector(dataVector, db.MTime, (int)numFiles); break;\r
+      case NID::kDummy:\r
+      {\r
+        for (UInt64 j = 0; j < size; j++)\r
+          if (ReadByte() != 0)\r
+            ThrowIncorrect();\r
+        addPropIdToList = false;\r
+        break;\r
+      }\r
+      default:\r
+        addPropIdToList = isKnownType = false;\r
+    }\r
+    if (isKnownType)\r
+    {\r
+      if(addPropIdToList)\r
+        db.ArchiveInfo.FileInfoPopIDs.Add(type);\r
+    }\r
+    else\r
+      SkipData(size);\r
+    bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 ||\r
+        db.ArchiveInfo.Version.Minor > 2);\r
+    if (checkRecordsSize && _inByteBack->_pos - ppp != size)\r
+      ThrowIncorrect();\r
+  }\r
+\r
+  CNum emptyFileIndex = 0;\r
+  CNum sizeIndex = 0;\r
+\r
+  CNum numAntiItems = 0;\r
+  for (i = 0; i < numEmptyStreams; i++)\r
+    if (antiFileVector[i])\r
+      numAntiItems++;\r
+    \r
+  for (i = 0; i < numFiles; i++)\r
+  {\r
+    CFileItem &file = db.Files[i];\r
+    bool isAnti;\r
+    file.HasStream = !emptyStreamVector[i];\r
+    if (file.HasStream)\r
+    {\r
+      file.IsDir = false;\r
+      isAnti = false;\r
+      file.Size = unpackSizes[sizeIndex];\r
+      file.Crc = digests[sizeIndex];\r
+      file.CrcDefined = digestsDefined[sizeIndex];\r
+      sizeIndex++;\r
+    }\r
+    else\r
+    {\r
+      file.IsDir = !emptyFileVector[emptyFileIndex];\r
+      isAnti = antiFileVector[emptyFileIndex];\r
+      emptyFileIndex++;\r
+      file.Size = 0;\r
+      file.CrcDefined = false;\r
+    }\r
+    if (numAntiItems != 0)\r
+      db.IsAnti.Add(isAnti);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+\r
+void CArchiveDatabaseEx::FillFolderStartPackStream()\r
+{\r
+  FolderStartPackStreamIndex.Clear();\r
+  FolderStartPackStreamIndex.Reserve(Folders.Size());\r
+  CNum startPos = 0;\r
+  for (int i = 0; i < Folders.Size(); i++)\r
+  {\r
+    FolderStartPackStreamIndex.Add(startPos);\r
+    startPos += (CNum)Folders[i].PackStreams.Size();\r
+  }\r
+}\r
+\r
+void CArchiveDatabaseEx::FillStartPos()\r
+{\r
+  PackStreamStartPositions.Clear();\r
+  PackStreamStartPositions.Reserve(PackSizes.Size());\r
+  UInt64 startPos = 0;\r
+  for (int i = 0; i < PackSizes.Size(); i++)\r
+  {\r
+    PackStreamStartPositions.Add(startPos);\r
+    startPos += PackSizes[i];\r
+  }\r
+}\r
+\r
+void CArchiveDatabaseEx::FillFolderStartFileIndex()\r
+{\r
+  FolderStartFileIndex.Clear();\r
+  FolderStartFileIndex.Reserve(Folders.Size());\r
+  FileIndexToFolderIndexMap.Clear();\r
+  FileIndexToFolderIndexMap.Reserve(Files.Size());\r
+  \r
+  int folderIndex = 0;\r
+  CNum indexInFolder = 0;\r
+  for (int i = 0; i < Files.Size(); i++)\r
+  {\r
+    const CFileItem &file = Files[i];\r
+    bool emptyStream = !file.HasStream;\r
+    if (emptyStream && indexInFolder == 0)\r
+    {\r
+      FileIndexToFolderIndexMap.Add(kNumNoIndex);\r
+      continue;\r
+    }\r
+    if (indexInFolder == 0)\r
+    {\r
+      // v3.13 incorrectly worked with empty folders\r
+      // v4.07: Loop for skipping empty folders\r
+      for (;;)\r
+      {\r
+        if (folderIndex >= Folders.Size())\r
+          ThrowIncorrect();\r
+        FolderStartFileIndex.Add(i); // check it\r
+        if (NumUnpackStreamsVector[folderIndex] != 0)\r
+          break;\r
+        folderIndex++;\r
+      }\r
+    }\r
+    FileIndexToFolderIndexMap.Add(folderIndex);\r
+    if (emptyStream)\r
+      continue;\r
+    indexInFolder++;\r
+    if (indexInFolder >= NumUnpackStreamsVector[folderIndex])\r
+    {\r
+      folderIndex++;\r
+      indexInFolder = 0;\r
+    }\r
+  }\r
+}\r
+\r
+HRESULT CInArchive::ReadDatabase2(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    CArchiveDatabaseEx &db\r
+    #ifndef _NO_CRYPTO\r
+    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined\r
+    #endif\r
+    )\r
+{\r
+  db.Clear();\r
+  db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition;\r
+\r
+  db.ArchiveInfo.Version.Major = _header[6];\r
+  db.ArchiveInfo.Version.Minor = _header[7];\r
+\r
+  if (db.ArchiveInfo.Version.Major != kMajorVersion)\r
+    ThrowUnsupportedVersion();\r
+\r
+  UInt32 crcFromArchive = Get32(_header + 8);\r
+  UInt64 nextHeaderOffset = Get64(_header + 0xC);\r
+  UInt64 nextHeaderSize = Get64(_header + 0x14);\r
+  UInt32 nextHeaderCRC = Get32(_header + 0x1C);\r
+  UInt32 crc = CrcCalc(_header + 0xC, 20);\r
+\r
+  #ifdef FORMAT_7Z_RECOVERY\r
+  if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0)\r
+  {\r
+    UInt64 cur, cur2;\r
+    RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur));\r
+    const int kCheckSize = 500;\r
+    Byte buf[kCheckSize];\r
+    RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2));\r
+    int checkSize = kCheckSize;\r
+    if (cur2 - cur < kCheckSize)\r
+      checkSize = (int)(cur2 - cur);\r
+    RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2));\r
+    \r
+    RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize));\r
+\r
+    int i;\r
+    for (i = (int)checkSize - 2; i >= 0; i--)\r
+      if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04)\r
+        break;\r
+    if (i < 0)\r
+      return S_FALSE;\r
+    nextHeaderSize = checkSize - i;\r
+    nextHeaderOffset = cur2 - cur + i;\r
+    nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize);\r
+    RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL));\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    if (crc != crcFromArchive)\r
+      ThrowIncorrect();\r
+  }\r
+\r
+  db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize;\r
+\r
+  if (nextHeaderSize == 0)\r
+    return S_OK;\r
+\r
+  if (nextHeaderSize > (UInt64)0xFFFFFFFF)\r
+    return S_FALSE;\r
+\r
+  if ((Int64)nextHeaderOffset < 0)\r
+    return S_FALSE;\r
+\r
+  RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL));\r
+\r
+  CByteBuffer buffer2;\r
+  buffer2.SetCapacity((size_t)nextHeaderSize);\r
+\r
+  RINOK(ReadStream_FALSE(_stream, buffer2, (size_t)nextHeaderSize));\r
+  HeadersSize += kHeaderSize + nextHeaderSize;\r
+  db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize;\r
+\r
+  if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC)\r
+    ThrowIncorrect();\r
+  \r
+  CStreamSwitch streamSwitch;\r
+  streamSwitch.Set(this, buffer2);\r
+  \r
+  CObjectVector<CByteBuffer> dataVector;\r
+  \r
+  UInt64 type = ReadID();\r
+  if (type != NID::kHeader)\r
+  {\r
+    if (type != NID::kEncodedHeader)\r
+      ThrowIncorrect();\r
+    HRESULT result = ReadAndDecodePackedStreams(\r
+        EXTERNAL_CODECS_LOC_VARS\r
+        db.ArchiveInfo.StartPositionAfterHeader,\r
+        db.ArchiveInfo.DataStartPosition2,\r
+        dataVector\r
+        #ifndef _NO_CRYPTO\r
+        , getTextPassword, passwordIsDefined\r
+        #endif\r
+        );\r
+    RINOK(result);\r
+    if (dataVector.Size() == 0)\r
+      return S_OK;\r
+    if (dataVector.Size() > 1)\r
+      ThrowIncorrect();\r
+    streamSwitch.Remove();\r
+    streamSwitch.Set(this, dataVector.Front());\r
+    if (ReadID() != NID::kHeader)\r
+      ThrowIncorrect();\r
+  }\r
+\r
+  db.HeadersSize = HeadersSize;\r
+\r
+  return ReadHeader(\r
+    EXTERNAL_CODECS_LOC_VARS\r
+    db\r
+    #ifndef _NO_CRYPTO\r
+    , getTextPassword, passwordIsDefined\r
+    #endif\r
+    );\r
+}\r
+\r
+HRESULT CInArchive::ReadDatabase(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    CArchiveDatabaseEx &db\r
+    #ifndef _NO_CRYPTO\r
+    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined\r
+    #endif\r
+    )\r
+{\r
+  try\r
+  {\r
+    return ReadDatabase2(\r
+      EXTERNAL_CODECS_LOC_VARS db\r
+      #ifndef _NO_CRYPTO\r
+      , getTextPassword, passwordIsDefined\r
+      #endif\r
+      );\r
+  }\r
+  catch(CInArchiveException &) { return S_FALSE; }\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h
new file mode 100755 (executable)
index 0000000..b82a020
--- /dev/null
@@ -0,0 +1,245 @@
+// 7zIn.h\r
+\r
+#ifndef __7Z_IN_H\r
+#define __7Z_IN_H\r
+\r
+#include "../../../Common/MyCom.h"\r
+\r
+#include "../../IPassword.h"\r
+#include "../../IStream.h"\r
+\r
+#include "../../Common/CreateCoder.h"\r
+#include "../../Common/InBuffer.h"\r
+\r
+#include "7zItem.h"\r
\r
+namespace NArchive {\r
+namespace N7z {\r
+  \r
+struct CInArchiveInfo\r
+{\r
+  CArchiveVersion Version;\r
+  UInt64 StartPosition;\r
+  UInt64 StartPositionAfterHeader;\r
+  UInt64 DataStartPosition;\r
+  UInt64 DataStartPosition2;\r
+  CRecordVector<UInt64> FileInfoPopIDs;\r
+  void Clear()\r
+  {\r
+    FileInfoPopIDs.Clear();\r
+  }\r
+};\r
+\r
+struct CArchiveDatabaseEx: public CArchiveDatabase\r
+{\r
+  CInArchiveInfo ArchiveInfo;\r
+  CRecordVector<UInt64> PackStreamStartPositions;\r
+  CRecordVector<CNum> FolderStartPackStreamIndex;\r
+  CRecordVector<CNum> FolderStartFileIndex;\r
+  CRecordVector<CNum> FileIndexToFolderIndexMap;\r
+\r
+  UInt64 HeadersSize;\r
+  UInt64 PhySize;\r
+\r
+  void Clear()\r
+  {\r
+    CArchiveDatabase::Clear();\r
+    ArchiveInfo.Clear();\r
+    PackStreamStartPositions.Clear();\r
+    FolderStartPackStreamIndex.Clear();\r
+    FolderStartFileIndex.Clear();\r
+    FileIndexToFolderIndexMap.Clear();\r
+\r
+    HeadersSize = 0;\r
+    PhySize = 0;\r
+  }\r
+\r
+  void FillFolderStartPackStream();\r
+  void FillStartPos();\r
+  void FillFolderStartFileIndex();\r
+\r
+  void Fill()\r
+  {\r
+    FillFolderStartPackStream();\r
+    FillStartPos();\r
+    FillFolderStartFileIndex();\r
+  }\r
+  \r
+  UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const\r
+  {\r
+    return ArchiveInfo.DataStartPosition +\r
+        PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder];\r
+  }\r
+  \r
+  UInt64 GetFolderFullPackSize(int folderIndex) const\r
+  {\r
+    CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex];\r
+    const CFolder &folder = Folders[folderIndex];\r
+    UInt64 size = 0;\r
+    for (int i = 0; i < folder.PackStreams.Size(); i++)\r
+      size += PackSizes[packStreamIndex + i];\r
+    return size;\r
+  }\r
+  \r
+  UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const\r
+  {\r
+    return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];\r
+  }\r
+\r
+  UInt64 GetFilePackSize(CNum fileIndex) const\r
+  {\r
+    CNum folderIndex = FileIndexToFolderIndexMap[fileIndex];\r
+    if (folderIndex != kNumNoIndex)\r
+      if (FolderStartFileIndex[folderIndex] == fileIndex)\r
+        return GetFolderFullPackSize(folderIndex);\r
+    return 0;\r
+  }\r
+};\r
+\r
+class CInByte2\r
+{\r
+  const Byte *_buffer;\r
+  size_t _size;\r
+public:\r
+  size_t _pos;\r
+  void Init(const Byte *buffer, size_t size)\r
+  {\r
+    _buffer = buffer;\r
+    _size = size;\r
+    _pos = 0;\r
+  }\r
+  Byte ReadByte();\r
+  void ReadBytes(Byte *data, size_t size);\r
+  void SkipData(UInt64 size);\r
+  void SkipData();\r
+  UInt64 ReadNumber();\r
+  CNum ReadNum();\r
+  UInt32 ReadUInt32();\r
+  UInt64 ReadUInt64();\r
+  void ReadString(UString &s);\r
+};\r
+\r
+class CStreamSwitch;\r
+\r
+const UInt32 kHeaderSize = 32;\r
+\r
+class CInArchive\r
+{\r
+  friend class CStreamSwitch;\r
+\r
+  CMyComPtr<IInStream> _stream;\r
+\r
+  CObjectVector<CInByte2> _inByteVector;\r
+  CInByte2 *_inByteBack;\r
\r
+  UInt64 _arhiveBeginStreamPosition;\r
+\r
+  Byte _header[kHeaderSize];\r
+\r
+  UInt64 HeadersSize;\r
+\r
+  void AddByteStream(const Byte *buffer, size_t size)\r
+  {\r
+    _inByteVector.Add(CInByte2());\r
+    _inByteBack = &_inByteVector.Back();\r
+    _inByteBack->Init(buffer, size);\r
+  }\r
+  \r
+  void DeleteByteStream()\r
+  {\r
+    _inByteVector.DeleteBack();\r
+    if (!_inByteVector.IsEmpty())\r
+      _inByteBack = &_inByteVector.Back();\r
+  }\r
+\r
+private:\r
+  HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);\r
+  \r
+  void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }\r
+  Byte ReadByte() { return _inByteBack->ReadByte(); }\r
+  UInt64 ReadNumber() { return _inByteBack->ReadNumber(); }\r
+  CNum ReadNum() { return _inByteBack->ReadNum(); }\r
+  UInt64 ReadID() { return _inByteBack->ReadNumber(); }\r
+  UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }\r
+  UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }\r
+  void SkipData(UInt64 size) { _inByteBack->SkipData(size); }\r
+  void SkipData() { _inByteBack->SkipData(); }\r
+  void WaitAttribute(UInt64 attribute);\r
+\r
+  void ReadArchiveProperties(CInArchiveInfo &archiveInfo);\r
+  void GetNextFolderItem(CFolder &itemInfo);\r
+  void ReadHashDigests(int numItems,\r
+      CBoolVector &digestsDefined, CRecordVector<UInt32> &digests);\r
+  \r
+  void ReadPackInfo(\r
+      UInt64 &dataOffset,\r
+      CRecordVector<UInt64> &packSizes,\r
+      CBoolVector &packCRCsDefined,\r
+      CRecordVector<UInt32> &packCRCs);\r
+  \r
+  void ReadUnpackInfo(\r
+      const CObjectVector<CByteBuffer> *dataVector,\r
+      CObjectVector<CFolder> &folders);\r
+  \r
+  void ReadSubStreamsInfo(\r
+      const CObjectVector<CFolder> &folders,\r
+      CRecordVector<CNum> &numUnpackStreamsInFolders,\r
+      CRecordVector<UInt64> &unpackSizes,\r
+      CBoolVector &digestsDefined,\r
+      CRecordVector<UInt32> &digests);\r
+\r
+  void ReadStreamsInfo(\r
+      const CObjectVector<CByteBuffer> *dataVector,\r
+      UInt64 &dataOffset,\r
+      CRecordVector<UInt64> &packSizes,\r
+      CBoolVector &packCRCsDefined,\r
+      CRecordVector<UInt32> &packCRCs,\r
+      CObjectVector<CFolder> &folders,\r
+      CRecordVector<CNum> &numUnpackStreamsInFolders,\r
+      CRecordVector<UInt64> &unpackSizes,\r
+      CBoolVector &digestsDefined,\r
+      CRecordVector<UInt32> &digests);\r
+\r
+\r
+  void ReadBoolVector(int numItems, CBoolVector &v);\r
+  void ReadBoolVector2(int numItems, CBoolVector &v);\r
+  void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,\r
+      CUInt64DefVector &v, int numFiles);\r
+  HRESULT ReadAndDecodePackedStreams(\r
+      DECL_EXTERNAL_CODECS_LOC_VARS\r
+      UInt64 baseOffset, UInt64 &dataOffset,\r
+      CObjectVector<CByteBuffer> &dataVector\r
+      #ifndef _NO_CRYPTO\r
+      , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined\r
+      #endif\r
+      );\r
+  HRESULT ReadHeader(\r
+      DECL_EXTERNAL_CODECS_LOC_VARS\r
+      CArchiveDatabaseEx &db\r
+      #ifndef _NO_CRYPTO\r
+      ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined\r
+      #endif\r
+      );\r
+  HRESULT ReadDatabase2(\r
+      DECL_EXTERNAL_CODECS_LOC_VARS\r
+      CArchiveDatabaseEx &db\r
+      #ifndef _NO_CRYPTO\r
+      ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined\r
+      #endif\r
+      );\r
+public:\r
+  HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive\r
+  void Close();\r
+\r
+  HRESULT ReadDatabase(\r
+      DECL_EXTERNAL_CODECS_LOC_VARS\r
+      CArchiveDatabaseEx &db\r
+      #ifndef _NO_CRYPTO\r
+      ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined\r
+      #endif\r
+      );\r
+};\r
+  \r
+}}\r
+  \r
+#endif\r
diff --git a/CPP/7zip/Archive/7z/7zItem.h b/CPP/7zip/Archive/7z/7zItem.h
new file mode 100755 (executable)
index 0000000..3b01a8d
--- /dev/null
@@ -0,0 +1,268 @@
+// 7zItem.h\r
+\r
+#ifndef __7Z_ITEM_H\r
+#define __7Z_ITEM_H\r
+\r
+#include "../../../Common/Buffer.h"\r
+#include "../../../Common/MyString.h"\r
+\r
+#include "../../Common/MethodId.h"\r
+\r
+#include "7zHeader.h"\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+const UInt64 k_AES = 0x06F10701;\r
+\r
+typedef UInt32 CNum;\r
+const CNum kNumMax     = 0x7FFFFFFF;\r
+const CNum kNumNoIndex = 0xFFFFFFFF;\r
+\r
+struct CCoderInfo\r
+{\r
+  CMethodId MethodID;\r
+  CByteBuffer Props;\r
+  CNum NumInStreams;\r
+  CNum NumOutStreams;\r
+  bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }\r
+};\r
+\r
+struct CBindPair\r
+{\r
+  CNum InIndex;\r
+  CNum OutIndex;\r
+};\r
+\r
+struct CFolder\r
+{\r
+  CObjectVector<CCoderInfo> Coders;\r
+  CRecordVector<CBindPair> BindPairs;\r
+  CRecordVector<CNum> PackStreams;\r
+  CRecordVector<UInt64> UnpackSizes;\r
+  UInt32 UnpackCRC;\r
+  bool UnpackCRCDefined;\r
+\r
+  CFolder(): UnpackCRCDefined(false) {}\r
+\r
+  UInt64 GetUnpackSize() const // test it\r
+  {\r
+    if (UnpackSizes.IsEmpty())\r
+      return 0;\r
+    for (int i = UnpackSizes.Size() - 1; i >= 0; i--)\r
+      if (FindBindPairForOutStream(i) < 0)\r
+        return UnpackSizes[i];\r
+    throw 1;\r
+  }\r
+\r
+  CNum GetNumOutStreams() const\r
+  {\r
+    CNum result = 0;\r
+    for (int i = 0; i < Coders.Size(); i++)\r
+      result += Coders[i].NumOutStreams;\r
+    return result;\r
+  }\r
+\r
+  int FindBindPairForInStream(CNum inStreamIndex) const\r
+  {\r
+    for(int i = 0; i < BindPairs.Size(); i++)\r
+      if (BindPairs[i].InIndex == inStreamIndex)\r
+        return i;\r
+    return -1;\r
+  }\r
+  int FindBindPairForOutStream(CNum outStreamIndex) const\r
+  {\r
+    for(int i = 0; i < BindPairs.Size(); i++)\r
+      if (BindPairs[i].OutIndex == outStreamIndex)\r
+        return i;\r
+    return -1;\r
+  }\r
+  int FindPackStreamArrayIndex(CNum inStreamIndex) const\r
+  {\r
+    for(int i = 0; i < PackStreams.Size(); i++)\r
+      if (PackStreams[i] == inStreamIndex)\r
+        return i;\r
+    return -1;\r
+  }\r
+\r
+  bool IsEncrypted() const\r
+  {\r
+    for (int i = Coders.Size() - 1; i >= 0; i--)\r
+      if (Coders[i].MethodID == k_AES)\r
+        return true;\r
+    return false;\r
+  }\r
+\r
+  bool CheckStructure() const;\r
+};\r
+\r
+struct CUInt64DefVector\r
+{\r
+  CRecordVector<UInt64> Values;\r
+  CRecordVector<bool> Defined;\r
+  \r
+  void Clear()\r
+  {\r
+    Values.Clear();\r
+    Defined.Clear();\r
+  }\r
+  \r
+  void ReserveDown()\r
+  {\r
+    Values.ReserveDown();\r
+    Values.ReserveDown();\r
+  }\r
+\r
+  bool GetItem(int index, UInt64 &value) const\r
+  {\r
+    if (index < Defined.Size() && Defined[index])\r
+    {\r
+      value = Values[index];\r
+      return true;\r
+    }\r
+    value = 0;\r
+    return false;\r
+  }\r
+  \r
+  void SetItem(int index, bool defined, UInt64 value)\r
+  {\r
+    while (index >= Defined.Size())\r
+      Defined.Add(false);\r
+    Defined[index] = defined;\r
+    if (!defined)\r
+      return;\r
+    while (index >= Values.Size())\r
+      Values.Add(0);\r
+    Values[index] = value;\r
+  }\r
+\r
+  bool CheckSize(int size) const { return Defined.Size() == size || Defined.Size() == 0; }\r
+};\r
+\r
+struct CFileItem\r
+{\r
+  UInt64 Size;\r
+  UInt32 Attrib;\r
+  UInt32 Crc;\r
+  UString Name;\r
+\r
+  bool HasStream; // Test it !!! it means that there is\r
+                  // stream in some folder. It can be empty stream\r
+  bool IsDir;\r
+  bool CrcDefined;\r
+  bool AttribDefined;\r
+\r
+  CFileItem():\r
+    HasStream(true),\r
+    IsDir(false),\r
+    CrcDefined(false),\r
+    AttribDefined(false)\r
+      {}\r
+  void SetAttrib(UInt32 attrib)\r
+  {\r
+    AttribDefined = true;\r
+    Attrib = attrib;\r
+  }\r
+};\r
+\r
+struct CFileItem2\r
+{\r
+  UInt64 CTime;\r
+  UInt64 ATime;\r
+  UInt64 MTime;\r
+  UInt64 StartPos;\r
+  bool CTimeDefined;\r
+  bool ATimeDefined;\r
+  bool MTimeDefined;\r
+  bool StartPosDefined;\r
+  bool IsAnti;\r
+};\r
+\r
+struct CArchiveDatabase\r
+{\r
+  CRecordVector<UInt64> PackSizes;\r
+  CRecordVector<bool> PackCRCsDefined;\r
+  CRecordVector<UInt32> PackCRCs;\r
+  CObjectVector<CFolder> Folders;\r
+  CRecordVector<CNum> NumUnpackStreamsVector;\r
+  CObjectVector<CFileItem> Files;\r
+\r
+  CUInt64DefVector CTime;\r
+  CUInt64DefVector ATime;\r
+  CUInt64DefVector MTime;\r
+  CUInt64DefVector StartPos;\r
+  CRecordVector<bool> IsAnti;\r
+\r
+  void Clear()\r
+  {\r
+    PackSizes.Clear();\r
+    PackCRCsDefined.Clear();\r
+    PackCRCs.Clear();\r
+    Folders.Clear();\r
+    NumUnpackStreamsVector.Clear();\r
+    Files.Clear();\r
+    CTime.Clear();\r
+    ATime.Clear();\r
+    MTime.Clear();\r
+    StartPos.Clear();\r
+    IsAnti.Clear();\r
+  }\r
+\r
+  void ReserveDown()\r
+  {\r
+    PackSizes.ReserveDown();\r
+    PackCRCsDefined.ReserveDown();\r
+    PackCRCs.ReserveDown();\r
+    Folders.ReserveDown();\r
+    NumUnpackStreamsVector.ReserveDown();\r
+    Files.ReserveDown();\r
+    CTime.ReserveDown();\r
+    ATime.ReserveDown();\r
+    MTime.ReserveDown();\r
+    StartPos.ReserveDown();\r
+    IsAnti.ReserveDown();\r
+  }\r
+\r
+  bool IsEmpty() const\r
+  {\r
+    return (PackSizes.IsEmpty() &&\r
+      PackCRCsDefined.IsEmpty() &&\r
+      PackCRCs.IsEmpty() &&\r
+      Folders.IsEmpty() &&\r
+      NumUnpackStreamsVector.IsEmpty() &&\r
+      Files.IsEmpty());\r
+  }\r
+\r
+  bool CheckNumFiles() const\r
+  {\r
+    int size = Files.Size();\r
+    return (\r
+      CTime.CheckSize(size) &&\r
+      ATime.CheckSize(size) &&\r
+      MTime.CheckSize(size) &&\r
+      StartPos.CheckSize(size) &&\r
+      (size == IsAnti.Size() || IsAnti.Size() == 0));\r
+  }\r
+\r
+  bool IsSolid() const\r
+  {\r
+    for (int i = 0; i < NumUnpackStreamsVector.Size(); i++)\r
+      if (NumUnpackStreamsVector[i] > 1)\r
+        return true;\r
+    return false;\r
+  }\r
+  bool IsItemAnti(int index) const { return (index < IsAnti.Size() && IsAnti[index]); }\r
+  void SetItemAnti(int index, bool isAnti)\r
+  {\r
+    while (index >= IsAnti.Size())\r
+      IsAnti.Add(false);\r
+    IsAnti[index] = isAnti;\r
+  }\r
+\r
+  void GetFile(int index, CFileItem &file, CFileItem2 &file2) const;\r
+  void AddFile(const CFileItem &file, const CFileItem2 &file2);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp
new file mode 100755 (executable)
index 0000000..b34a2c9
--- /dev/null
@@ -0,0 +1,866 @@
+// 7zOut.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/7zCrc.h"\r
+\r
+#include "../../../Common/AutoPtr.h"\r
+\r
+#include "../../Common/StreamObjects.h"\r
+\r
+#include "7zOut.h"\r
+\r
+static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size)\r
+{\r
+  while (size > 0)\r
+  {\r
+    UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF);\r
+    UInt32 processedSize;\r
+    RINOK(stream->Write(data, curSize, &processedSize));\r
+    if (processedSize == 0)\r
+      return E_FAIL;\r
+    data = (const void *)((const Byte *)data + processedSize);\r
+    size -= processedSize;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+HRESULT COutArchive::WriteDirect(const void *data, UInt32 size)\r
+{\r
+  return ::WriteBytes(SeqStream, data, size);\r
+}\r
+\r
+HRESULT COutArchive::WriteSignature()\r
+{\r
+  Byte buf[8];\r
+  memcpy(buf, kSignature, kSignatureSize);\r
+  buf[kSignatureSize] = kMajorVersion;\r
+  buf[kSignatureSize + 1] = 3;\r
+  return WriteDirect(buf, 8);\r
+}\r
+\r
+#ifdef _7Z_VOL\r
+HRESULT COutArchive::WriteFinishSignature()\r
+{\r
+  RINOK(WriteDirect(kFinishSignature, kSignatureSize));\r
+  CArchiveVersion av;\r
+  av.Major = kMajorVersion;\r
+  av.Minor = 2;\r
+  RINOK(WriteDirectByte(av.Major));\r
+  return WriteDirectByte(av.Minor);\r
+}\r
+#endif\r
+\r
+static void SetUInt32(Byte *p, UInt32 d)\r
+{\r
+  for (int i = 0; i < 4; i++, d >>= 8)\r
+    p[i] = (Byte)d;\r
+}\r
+\r
+static void SetUInt64(Byte *p, UInt64 d)\r
+{\r
+  for (int i = 0; i < 8; i++, d >>= 8)\r
+    p[i] = (Byte)d;\r
+}\r
+\r
+HRESULT COutArchive::WriteStartHeader(const CStartHeader &h)\r
+{\r
+  Byte buf[24];\r
+  SetUInt64(buf + 4, h.NextHeaderOffset);\r
+  SetUInt64(buf + 12, h.NextHeaderSize);\r
+  SetUInt32(buf + 20, h.NextHeaderCRC);\r
+  SetUInt32(buf, CrcCalc(buf + 4, 20));\r
+  return WriteDirect(buf, 24);\r
+}\r
+\r
+#ifdef _7Z_VOL\r
+HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h)\r
+{\r
+  CCRC crc;\r
+  crc.UpdateUInt64(h.NextHeaderOffset);\r
+  crc.UpdateUInt64(h.NextHeaderSize);\r
+  crc.UpdateUInt32(h.NextHeaderCRC);\r
+  crc.UpdateUInt64(h.ArchiveStartOffset);\r
+  crc.UpdateUInt64(h.AdditionalStartBlockSize);\r
+  RINOK(WriteDirectUInt32(crc.GetDigest()));\r
+  RINOK(WriteDirectUInt64(h.NextHeaderOffset));\r
+  RINOK(WriteDirectUInt64(h.NextHeaderSize));\r
+  RINOK(WriteDirectUInt32(h.NextHeaderCRC));\r
+  RINOK(WriteDirectUInt64(h.ArchiveStartOffset));\r
+  return WriteDirectUInt64(h.AdditionalStartBlockSize);\r
+}\r
+#endif\r
+\r
+HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker)\r
+{\r
+  Close();\r
+  #ifdef _7Z_VOL\r
+  // endMarker = false;\r
+  _endMarker = endMarker;\r
+  #endif\r
+  SeqStream = stream;\r
+  if (!endMarker)\r
+  {\r
+    SeqStream.QueryInterface(IID_IOutStream, &Stream);\r
+    if (!Stream)\r
+    {\r
+      return E_NOTIMPL;\r
+      // endMarker = true;\r
+    }\r
+  }\r
+  #ifdef _7Z_VOL\r
+  if (endMarker)\r
+  {\r
+    /*\r
+    CStartHeader sh;\r
+    sh.NextHeaderOffset = (UInt32)(Int32)-1;\r
+    sh.NextHeaderSize = (UInt32)(Int32)-1;\r
+    sh.NextHeaderCRC = 0;\r
+    WriteStartHeader(sh);\r
+    */\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    if (!Stream)\r
+      return E_FAIL;\r
+    RINOK(WriteSignature());\r
+    RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos));\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+void COutArchive::Close()\r
+{\r
+  SeqStream.Release();\r
+  Stream.Release();\r
+}\r
+\r
+HRESULT COutArchive::SkipPrefixArchiveHeader()\r
+{\r
+  #ifdef _7Z_VOL\r
+  if (_endMarker)\r
+    return S_OK;\r
+  #endif\r
+  return Stream->Seek(24, STREAM_SEEK_CUR, NULL);\r
+}\r
+\r
+UInt64 COutArchive::GetPos() const\r
+{\r
+  if (_countMode)\r
+    return _countSize;\r
+  if (_writeToStream)\r
+    return _outByte.GetProcessedSize();\r
+  return _outByte2.GetPos();\r
+}\r
+\r
+void COutArchive::WriteBytes(const void *data, size_t size)\r
+{\r
+  if (_countMode)\r
+    _countSize += size;\r
+  else if (_writeToStream)\r
+  {\r
+    _outByte.WriteBytes(data, size);\r
+    _crc = CrcUpdate(_crc, data, size);\r
+  }\r
+  else\r
+    _outByte2.WriteBytes(data, size);\r
+}\r
+\r
+void COutArchive::WriteByte(Byte b)\r
+{\r
+  if (_countMode)\r
+    _countSize++;\r
+  else if (_writeToStream)\r
+  {\r
+    _outByte.WriteByte(b);\r
+    _crc = CRC_UPDATE_BYTE(_crc, b);\r
+  }\r
+  else\r
+    _outByte2.WriteByte(b);\r
+}\r
+\r
+void COutArchive::WriteUInt32(UInt32 value)\r
+{\r
+  for (int i = 0; i < 4; i++)\r
+  {\r
+    WriteByte((Byte)value);\r
+    value >>= 8;\r
+  }\r
+}\r
+\r
+void COutArchive::WriteUInt64(UInt64 value)\r
+{\r
+  for (int i = 0; i < 8; i++)\r
+  {\r
+    WriteByte((Byte)value);\r
+    value >>= 8;\r
+  }\r
+}\r
+\r
+void COutArchive::WriteNumber(UInt64 value)\r
+{\r
+  Byte firstByte = 0;\r
+  Byte mask = 0x80;\r
+  int i;\r
+  for (i = 0; i < 8; i++)\r
+  {\r
+    if (value < ((UInt64(1) << ( 7  * (i + 1)))))\r
+    {\r
+      firstByte |= Byte(value >> (8 * i));\r
+      break;\r
+    }\r
+    firstByte |= mask;\r
+    mask >>= 1;\r
+  }\r
+  WriteByte(firstByte);\r
+  for (;i > 0; i--)\r
+  {\r
+    WriteByte((Byte)value);\r
+    value >>= 8;\r
+  }\r
+}\r
+\r
+static UInt32 GetBigNumberSize(UInt64 value)\r
+{\r
+  int i;\r
+  for (i = 1; i < 9; i++)\r
+    if (value < (((UInt64)1 << (i * 7))))\r
+      break;\r
+  return i;\r
+}\r
+\r
+#ifdef _7Z_VOL\r
+UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props)\r
+{\r
+  UInt32 result = GetBigNumberSize(dataSize) * 2 + 41;\r
+  if (nameLength != 0)\r
+  {\r
+    nameLength = (nameLength + 1) * 2;\r
+    result += nameLength + GetBigNumberSize(nameLength) + 2;\r
+  }\r
+  if (props)\r
+  {\r
+    result += 20;\r
+  }\r
+  if (result >= 128)\r
+    result++;\r
+  result += kSignatureSize + 2 + kFinishHeaderSize;\r
+  return result;\r
+}\r
+\r
+UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props)\r
+{\r
+  UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props);\r
+  int testSize;\r
+  if (volSize > headersSizeBase)\r
+    testSize = volSize - headersSizeBase;\r
+  else\r
+    testSize = 1;\r
+  UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props);\r
+  UInt64 pureSize = 1;\r
+  if (volSize > headersSize)\r
+    pureSize = volSize - headersSize;\r
+  return pureSize;\r
+}\r
+#endif\r
+\r
+void COutArchive::WriteFolder(const CFolder &folder)\r
+{\r
+  WriteNumber(folder.Coders.Size());\r
+  int i;\r
+  for (i = 0; i < folder.Coders.Size(); i++)\r
+  {\r
+    const CCoderInfo &coder = folder.Coders[i];\r
+    {\r
+      size_t propsSize = coder.Props.GetCapacity();\r
+      \r
+      UInt64 id = coder.MethodID;\r
+      int idSize;\r
+      for (idSize = 1; idSize < sizeof(id); idSize++)\r
+        if ((id >> (8 * idSize)) == 0)\r
+          break;\r
+      BYTE longID[15];\r
+      for (int t = idSize - 1; t >= 0 ; t--, id >>= 8)\r
+        longID[t] = (Byte)(id & 0xFF);\r
+      Byte b;\r
+      b = (Byte)(idSize & 0xF);\r
+      bool isComplex = !coder.IsSimpleCoder();\r
+      b |= (isComplex ? 0x10 : 0);\r
+      b |= ((propsSize != 0) ? 0x20 : 0 );\r
+      WriteByte(b);\r
+      WriteBytes(longID, idSize);\r
+      if (isComplex)\r
+      {\r
+        WriteNumber(coder.NumInStreams);\r
+        WriteNumber(coder.NumOutStreams);\r
+      }\r
+      if (propsSize == 0)\r
+        continue;\r
+      WriteNumber(propsSize);\r
+      WriteBytes(coder.Props, propsSize);\r
+    }\r
+  }\r
+  for (i = 0; i < folder.BindPairs.Size(); i++)\r
+  {\r
+    const CBindPair &bindPair = folder.BindPairs[i];\r
+    WriteNumber(bindPair.InIndex);\r
+    WriteNumber(bindPair.OutIndex);\r
+  }\r
+  if (folder.PackStreams.Size() > 1)\r
+    for (i = 0; i < folder.PackStreams.Size(); i++)\r
+    {\r
+      WriteNumber(folder.PackStreams[i]);\r
+    }\r
+}\r
+\r
+void COutArchive::WriteBoolVector(const CBoolVector &boolVector)\r
+{\r
+  Byte b = 0;\r
+  Byte mask = 0x80;\r
+  for (int i = 0; i < boolVector.Size(); i++)\r
+  {\r
+    if (boolVector[i])\r
+      b |= mask;\r
+    mask >>= 1;\r
+    if (mask == 0)\r
+    {\r
+      WriteByte(b);\r
+      mask = 0x80;\r
+      b = 0;\r
+    }\r
+  }\r
+  if (mask != 0x80)\r
+    WriteByte(b);\r
+}\r
+\r
+\r
+void COutArchive::WriteHashDigests(\r
+    const CRecordVector<bool> &digestsDefined,\r
+    const CRecordVector<UInt32> &digests)\r
+{\r
+  int numDefined = 0;\r
+  int i;\r
+  for (i = 0; i < digestsDefined.Size(); i++)\r
+    if (digestsDefined[i])\r
+      numDefined++;\r
+  if (numDefined == 0)\r
+    return;\r
+\r
+  WriteByte(NID::kCRC);\r
+  if (numDefined == digestsDefined.Size())\r
+    WriteByte(1);\r
+  else\r
+  {\r
+    WriteByte(0);\r
+    WriteBoolVector(digestsDefined);\r
+  }\r
+  for (i = 0; i < digests.Size(); i++)\r
+    if (digestsDefined[i])\r
+      WriteUInt32(digests[i]);\r
+}\r
+\r
+void COutArchive::WritePackInfo(\r
+    UInt64 dataOffset,\r
+    const CRecordVector<UInt64> &packSizes,\r
+    const CRecordVector<bool> &packCRCsDefined,\r
+    const CRecordVector<UInt32> &packCRCs)\r
+{\r
+  if (packSizes.IsEmpty())\r
+    return;\r
+  WriteByte(NID::kPackInfo);\r
+  WriteNumber(dataOffset);\r
+  WriteNumber(packSizes.Size());\r
+  WriteByte(NID::kSize);\r
+  for (int i = 0; i < packSizes.Size(); i++)\r
+    WriteNumber(packSizes[i]);\r
+\r
+  WriteHashDigests(packCRCsDefined, packCRCs);\r
+  \r
+  WriteByte(NID::kEnd);\r
+}\r
+\r
+void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders)\r
+{\r
+  if (folders.IsEmpty())\r
+    return;\r
+\r
+  WriteByte(NID::kUnpackInfo);\r
+\r
+  WriteByte(NID::kFolder);\r
+  WriteNumber(folders.Size());\r
+  {\r
+    WriteByte(0);\r
+    for (int i = 0; i < folders.Size(); i++)\r
+      WriteFolder(folders[i]);\r
+  }\r
+  \r
+  WriteByte(NID::kCodersUnpackSize);\r
+  int i;\r
+  for (i = 0; i < folders.Size(); i++)\r
+  {\r
+    const CFolder &folder = folders[i];\r
+    for (int j = 0; j < folder.UnpackSizes.Size(); j++)\r
+      WriteNumber(folder.UnpackSizes[j]);\r
+  }\r
+\r
+  CRecordVector<bool> unpackCRCsDefined;\r
+  CRecordVector<UInt32> unpackCRCs;\r
+  for (i = 0; i < folders.Size(); i++)\r
+  {\r
+    const CFolder &folder = folders[i];\r
+    unpackCRCsDefined.Add(folder.UnpackCRCDefined);\r
+    unpackCRCs.Add(folder.UnpackCRC);\r
+  }\r
+  WriteHashDigests(unpackCRCsDefined, unpackCRCs);\r
+\r
+  WriteByte(NID::kEnd);\r
+}\r
+\r
+void COutArchive::WriteSubStreamsInfo(\r
+    const CObjectVector<CFolder> &folders,\r
+    const CRecordVector<CNum> &numUnpackStreamsInFolders,\r
+    const CRecordVector<UInt64> &unpackSizes,\r
+    const CRecordVector<bool> &digestsDefined,\r
+    const CRecordVector<UInt32> &digests)\r
+{\r
+  WriteByte(NID::kSubStreamsInfo);\r
+\r
+  int i;\r
+  for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)\r
+  {\r
+    if (numUnpackStreamsInFolders[i] != 1)\r
+    {\r
+      WriteByte(NID::kNumUnpackStream);\r
+      for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)\r
+        WriteNumber(numUnpackStreamsInFolders[i]);\r
+      break;\r
+    }\r
+  }\r
\r
+\r
+  bool needFlag = true;\r
+  CNum index = 0;\r
+  for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)\r
+    for (CNum j = 0; j < numUnpackStreamsInFolders[i]; j++)\r
+    {\r
+      if (j + 1 != numUnpackStreamsInFolders[i])\r
+      {\r
+        if (needFlag)\r
+          WriteByte(NID::kSize);\r
+        needFlag = false;\r
+        WriteNumber(unpackSizes[index]);\r
+      }\r
+      index++;\r
+    }\r
+\r
+  CRecordVector<bool> digestsDefined2;\r
+  CRecordVector<UInt32> digests2;\r
+\r
+  int digestIndex = 0;\r
+  for (i = 0; i < folders.Size(); i++)\r
+  {\r
+    int numSubStreams = (int)numUnpackStreamsInFolders[i];\r
+    if (numSubStreams == 1 && folders[i].UnpackCRCDefined)\r
+      digestIndex++;\r
+    else\r
+      for (int j = 0; j < numSubStreams; j++, digestIndex++)\r
+      {\r
+        digestsDefined2.Add(digestsDefined[digestIndex]);\r
+        digests2.Add(digests[digestIndex]);\r
+      }\r
+  }\r
+  WriteHashDigests(digestsDefined2, digests2);\r
+  WriteByte(NID::kEnd);\r
+}\r
+\r
+void COutArchive::SkipAlign(unsigned /* pos */, unsigned /* alignSize */)\r
+{\r
+  return;\r
+}\r
+\r
+/*\r
+7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field.\r
+\r
+void COutArchive::SkipAlign(unsigned pos, unsigned alignSize)\r
+{\r
+  pos += (unsigned)GetPos();\r
+  pos &= (alignSize - 1);\r
+  if (pos == 0)\r
+    return;\r
+  unsigned skip = alignSize - pos;\r
+  if (skip < 2)\r
+    skip += alignSize;\r
+  skip -= 2;\r
+  WriteByte(NID::kDummy);\r
+  WriteByte((Byte)skip);\r
+  for (unsigned i = 0; i < skip; i++)\r
+    WriteByte(0);\r
+}\r
+*/\r
+\r
+static inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; }\r
+\r
+void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize)\r
+{\r
+  const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v);\r
+  const UInt64 dataSize = (UInt64)numDefined * itemSize + bvSize + 2;\r
+  SkipAlign(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSize);\r
+\r
+  WriteByte(type);\r
+  WriteNumber(dataSize);\r
+  if (numDefined == v.Size())\r
+    WriteByte(1);\r
+  else\r
+  {\r
+    WriteByte(0);\r
+    WriteBoolVector(v);\r
+  }\r
+  WriteByte(0);\r
+}\r
+\r
+void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type)\r
+{\r
+  int numDefined = 0;\r
+\r
+  int i;\r
+  for (i = 0; i < v.Defined.Size(); i++)\r
+    if (v.Defined[i])\r
+      numDefined++;\r
+\r
+  if (numDefined == 0)\r
+    return;\r
+\r
+  WriteAlignedBoolHeader(v.Defined, numDefined, type, 8);\r
+  \r
+  for (i = 0; i < v.Defined.Size(); i++)\r
+    if (v.Defined[i])\r
+      WriteUInt64(v.Values[i]);\r
+}\r
+\r
+HRESULT COutArchive::EncodeStream(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    CEncoder &encoder, const CByteBuffer &data,\r
+    CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders)\r
+{\r
+  CBufInStream *streamSpec = new CBufInStream;\r
+  CMyComPtr<ISequentialInStream> stream = streamSpec;\r
+  streamSpec->Init(data, data.GetCapacity());\r
+  CFolder folderItem;\r
+  folderItem.UnpackCRCDefined = true;\r
+  folderItem.UnpackCRC = CrcCalc(data, data.GetCapacity());\r
+  UInt64 dataSize64 = data.GetCapacity();\r
+  RINOK(encoder.Encode(\r
+      EXTERNAL_CODECS_LOC_VARS\r
+      stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL))\r
+  folders.Add(folderItem);\r
+  return S_OK;\r
+}\r
+\r
+void COutArchive::WriteHeader(\r
+    const CArchiveDatabase &db,\r
+    const CHeaderOptions &headerOptions,\r
+    UInt64 &headerOffset)\r
+{\r
+  int i;\r
+  \r
+  UInt64 packedSize = 0;\r
+  for (i = 0; i < db.PackSizes.Size(); i++)\r
+    packedSize += db.PackSizes[i];\r
+\r
+  headerOffset = packedSize;\r
+\r
+  WriteByte(NID::kHeader);\r
+\r
+  // Archive Properties\r
+\r
+  if (db.Folders.Size() > 0)\r
+  {\r
+    WriteByte(NID::kMainStreamsInfo);\r
+    WritePackInfo(0, db.PackSizes,\r
+        db.PackCRCsDefined,\r
+        db.PackCRCs);\r
+\r
+    WriteUnpackInfo(db.Folders);\r
+\r
+    CRecordVector<UInt64> unpackSizes;\r
+    CRecordVector<bool> digestsDefined;\r
+    CRecordVector<UInt32> digests;\r
+    for (i = 0; i < db.Files.Size(); i++)\r
+    {\r
+      const CFileItem &file = db.Files[i];\r
+      if (!file.HasStream)\r
+        continue;\r
+      unpackSizes.Add(file.Size);\r
+      digestsDefined.Add(file.CrcDefined);\r
+      digests.Add(file.Crc);\r
+    }\r
+\r
+    WriteSubStreamsInfo(\r
+        db.Folders,\r
+        db.NumUnpackStreamsVector,\r
+        unpackSizes,\r
+        digestsDefined,\r
+        digests);\r
+    WriteByte(NID::kEnd);\r
+  }\r
+\r
+  if (db.Files.IsEmpty())\r
+  {\r
+    WriteByte(NID::kEnd);\r
+    return;\r
+  }\r
+\r
+  WriteByte(NID::kFilesInfo);\r
+  WriteNumber(db.Files.Size());\r
+\r
+  {\r
+  /* ---------- Empty Streams ---------- */\r
+  CBoolVector emptyStreamVector;\r
+  emptyStreamVector.Reserve(db.Files.Size());\r
+  int numEmptyStreams = 0;\r
+  for (i = 0; i < db.Files.Size(); i++)\r
+    if (db.Files[i].HasStream)\r
+      emptyStreamVector.Add(false);\r
+    else\r
+    {\r
+      emptyStreamVector.Add(true);\r
+      numEmptyStreams++;\r
+    }\r
+  if (numEmptyStreams > 0)\r
+  {\r
+    WriteByte(NID::kEmptyStream);\r
+    WriteNumber(Bv_GetSizeInBytes(emptyStreamVector));\r
+    WriteBoolVector(emptyStreamVector);\r
+\r
+    CBoolVector emptyFileVector, antiVector;\r
+    emptyFileVector.Reserve(numEmptyStreams);\r
+    antiVector.Reserve(numEmptyStreams);\r
+    CNum numEmptyFiles = 0, numAntiItems = 0;\r
+    for (i = 0; i < db.Files.Size(); i++)\r
+    {\r
+      const CFileItem &file = db.Files[i];\r
+      if (!file.HasStream)\r
+      {\r
+        emptyFileVector.Add(!file.IsDir);\r
+        if (!file.IsDir)\r
+          numEmptyFiles++;\r
+        bool isAnti = db.IsItemAnti(i);\r
+        antiVector.Add(isAnti);\r
+        if (isAnti)\r
+          numAntiItems++;\r
+      }\r
+    }\r
+\r
+    if (numEmptyFiles > 0)\r
+    {\r
+      WriteByte(NID::kEmptyFile);\r
+      WriteNumber(Bv_GetSizeInBytes(emptyFileVector));\r
+      WriteBoolVector(emptyFileVector);\r
+    }\r
+\r
+    if (numAntiItems > 0)\r
+    {\r
+      WriteByte(NID::kAnti);\r
+      WriteNumber(Bv_GetSizeInBytes(antiVector));\r
+      WriteBoolVector(antiVector);\r
+    }\r
+  }\r
+  }\r
+\r
+\r
+  {\r
+    /* ---------- Names ---------- */\r
+    \r
+    int numDefined = 0;\r
+    size_t namesDataSize = 0;\r
+    for (int i = 0; i < db.Files.Size(); i++)\r
+    {\r
+      const UString &name = db.Files[i].Name;\r
+      if (!name.IsEmpty())\r
+        numDefined++;\r
+      namesDataSize += (name.Length() + 1) * 2;\r
+    }\r
+    \r
+    if (numDefined > 0)\r
+    {\r
+      namesDataSize++;\r
+      SkipAlign(2 + GetBigNumberSize(namesDataSize), 2);\r
+\r
+      WriteByte(NID::kName);\r
+      WriteNumber(namesDataSize);\r
+      WriteByte(0);\r
+      for (int i = 0; i < db.Files.Size(); i++)\r
+      {\r
+        const UString &name = db.Files[i].Name;\r
+        for (int t = 0; t <= name.Length(); t++)\r
+        {\r
+          wchar_t c = name[t];\r
+          WriteByte((Byte)c);\r
+          WriteByte((Byte)(c >> 8));\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (headerOptions.WriteCTime) WriteUInt64DefVector(db.CTime, NID::kCTime);\r
+  if (headerOptions.WriteATime) WriteUInt64DefVector(db.ATime, NID::kATime);\r
+  if (headerOptions.WriteMTime) WriteUInt64DefVector(db.MTime, NID::kMTime);\r
+  WriteUInt64DefVector(db.StartPos, NID::kStartPos);\r
+  \r
+  {\r
+    /* ---------- Write Attrib ---------- */\r
+    CBoolVector boolVector;\r
+    boolVector.Reserve(db.Files.Size());\r
+    int numDefined = 0;\r
+    for (i = 0; i < db.Files.Size(); i++)\r
+    {\r
+      bool defined = db.Files[i].AttribDefined;\r
+      boolVector.Add(defined);\r
+      if (defined)\r
+        numDefined++;\r
+    }\r
+    if (numDefined > 0)\r
+    {\r
+      WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttributes, 4);\r
+      for (i = 0; i < db.Files.Size(); i++)\r
+      {\r
+        const CFileItem &file = db.Files[i];\r
+        if (file.AttribDefined)\r
+          WriteUInt32(file.Attrib);\r
+      }\r
+    }\r
+  }\r
+\r
+  WriteByte(NID::kEnd); // for files\r
+  WriteByte(NID::kEnd); // for headers\r
+}\r
+\r
+HRESULT COutArchive::WriteDatabase(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    const CArchiveDatabase &db,\r
+    const CCompressionMethodMode *options,\r
+    const CHeaderOptions &headerOptions)\r
+{\r
+  if (!db.CheckNumFiles())\r
+    return E_FAIL;\r
+\r
+  UInt64 headerOffset;\r
+  UInt32 headerCRC;\r
+  UInt64 headerSize;\r
+  if (db.IsEmpty())\r
+  {\r
+    headerSize = 0;\r
+    headerOffset = 0;\r
+    headerCRC = CrcCalc(0, 0);\r
+  }\r
+  else\r
+  {\r
+    bool encodeHeaders = false;\r
+    if (options != 0)\r
+      if (options->IsEmpty())\r
+        options = 0;\r
+    if (options != 0)\r
+      if (options->PasswordIsDefined || headerOptions.CompressMainHeader)\r
+        encodeHeaders = true;\r
+\r
+    _outByte.SetStream(SeqStream);\r
+    _outByte.Init();\r
+    _crc = CRC_INIT_VAL;\r
+    _countMode = encodeHeaders;\r
+    _writeToStream = true;\r
+    _countSize = 0;\r
+    WriteHeader(db, headerOptions, headerOffset);\r
+\r
+    if (encodeHeaders)\r
+    {\r
+      CByteBuffer buf;\r
+      buf.SetCapacity(_countSize);\r
+      _outByte2.Init((Byte *)buf, _countSize);\r
+      \r
+      _countMode = false;\r
+      _writeToStream = false;\r
+      WriteHeader(db, headerOptions, headerOffset);\r
+      \r
+      if (_countSize != _outByte2.GetPos())\r
+        return E_FAIL;\r
+\r
+      CCompressionMethodMode encryptOptions;\r
+      encryptOptions.PasswordIsDefined = options->PasswordIsDefined;\r
+      encryptOptions.Password = options->Password;\r
+      CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions);\r
+      CRecordVector<UInt64> packSizes;\r
+      CObjectVector<CFolder> folders;\r
+      RINOK(EncodeStream(\r
+          EXTERNAL_CODECS_LOC_VARS\r
+          encoder, buf,\r
+          packSizes, folders));\r
+\r
+      _writeToStream = true;\r
+      \r
+      if (folders.Size() == 0)\r
+        throw 1;\r
+\r
+      WriteID(NID::kEncodedHeader);\r
+      WritePackInfo(headerOffset, packSizes,\r
+        CRecordVector<bool>(), CRecordVector<UInt32>());\r
+      WriteUnpackInfo(folders);\r
+      WriteByte(NID::kEnd);\r
+      for (int i = 0; i < packSizes.Size(); i++)\r
+        headerOffset += packSizes[i];\r
+    }\r
+    RINOK(_outByte.Flush());\r
+    headerCRC = CRC_GET_DIGEST(_crc);\r
+    headerSize = _outByte.GetProcessedSize();\r
+  }\r
+  #ifdef _7Z_VOL\r
+  if (_endMarker)\r
+  {\r
+    CFinishHeader h;\r
+    h.NextHeaderSize = headerSize;\r
+    h.NextHeaderCRC = headerCRC;\r
+    h.NextHeaderOffset =\r
+        UInt64(0) - (headerSize +\r
+        4 + kFinishHeaderSize);\r
+    h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset;\r
+    h.AdditionalStartBlockSize = 0;\r
+    RINOK(WriteFinishHeader(h));\r
+    return WriteFinishSignature();\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    CStartHeader h;\r
+    h.NextHeaderSize = headerSize;\r
+    h.NextHeaderCRC = headerCRC;\r
+    h.NextHeaderOffset = headerOffset;\r
+    RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL));\r
+    return WriteStartHeader(h);\r
+  }\r
+}\r
+\r
+void CArchiveDatabase::GetFile(int index, CFileItem &file, CFileItem2 &file2) const\r
+{\r
+  file = Files[index];\r
+  file2.CTimeDefined = CTime.GetItem(index, file2.CTime);\r
+  file2.ATimeDefined = ATime.GetItem(index, file2.ATime);\r
+  file2.MTimeDefined = MTime.GetItem(index, file2.MTime);\r
+  file2.StartPosDefined = StartPos.GetItem(index, file2.StartPos);\r
+  file2.IsAnti = IsItemAnti(index);\r
+}\r
+\r
+void CArchiveDatabase::AddFile(const CFileItem &file, const CFileItem2 &file2)\r
+{\r
+  int index = Files.Size();\r
+  CTime.SetItem(index, file2.CTimeDefined, file2.CTime);\r
+  ATime.SetItem(index, file2.ATimeDefined, file2.ATime);\r
+  MTime.SetItem(index, file2.MTimeDefined, file2.MTime);\r
+  StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos);\r
+  SetItemAnti(index, file2.IsAnti);\r
+  Files.Add(file);\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/7z/7zOut.h b/CPP/7zip/Archive/7z/7zOut.h
new file mode 100755 (executable)
index 0000000..bdd465c
--- /dev/null
@@ -0,0 +1,152 @@
+// 7zOut.h\r
+\r
+#ifndef __7Z_OUT_H\r
+#define __7Z_OUT_H\r
+\r
+#include "7zCompressionMode.h"\r
+#include "7zEncode.h"\r
+#include "7zHeader.h"\r
+#include "7zItem.h"\r
+\r
+#include "../../Common/OutBuffer.h"\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+class CWriteBufferLoc\r
+{\r
+  Byte *_data;\r
+  size_t _size;\r
+  size_t _pos;\r
+public:\r
+  CWriteBufferLoc(): _size(0), _pos(0) {}\r
+  void Init(Byte *data, size_t size)\r
+  {\r
+    _data = data;\r
+    _size = size;\r
+    _pos = 0;\r
+  }\r
+  void WriteBytes(const void *data, size_t size)\r
+  {\r
+    if (size > _size - _pos)\r
+      throw 1;\r
+    memcpy(_data + _pos, data, size);\r
+    _pos += size;\r
+  }\r
+  void WriteByte(Byte b)\r
+  {\r
+    if (_size == _pos)\r
+      throw 1;\r
+    _data[_pos++] = b;\r
+  }\r
+  size_t GetPos() const { return _pos; }\r
+};\r
+\r
+struct CHeaderOptions\r
+{\r
+  bool CompressMainHeader;\r
+  bool WriteCTime;\r
+  bool WriteATime;\r
+  bool WriteMTime;\r
+\r
+  CHeaderOptions():\r
+      CompressMainHeader(true),\r
+      WriteCTime(false),\r
+      WriteATime(false),\r
+      WriteMTime(true)\r
+      {}\r
+};\r
+\r
+class COutArchive\r
+{\r
+  UInt64 _prefixHeaderPos;\r
+\r
+  HRESULT WriteDirect(const void *data, UInt32 size);\r
+  \r
+  UInt64 GetPos() const;\r
+  void WriteBytes(const void *data, size_t size);\r
+  void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.GetCapacity()); }\r
+  void WriteByte(Byte b);\r
+  void WriteUInt32(UInt32 value);\r
+  void WriteUInt64(UInt64 value);\r
+  void WriteNumber(UInt64 value);\r
+  void WriteID(UInt64 value) { WriteNumber(value); }\r
+\r
+  void WriteFolder(const CFolder &folder);\r
+  HRESULT WriteFileHeader(const CFileItem &itemInfo);\r
+  void WriteBoolVector(const CBoolVector &boolVector);\r
+  void WriteHashDigests(\r
+      const CRecordVector<bool> &digestsDefined,\r
+      const CRecordVector<UInt32> &hashDigests);\r
+\r
+  void WritePackInfo(\r
+      UInt64 dataOffset,\r
+      const CRecordVector<UInt64> &packSizes,\r
+      const CRecordVector<bool> &packCRCsDefined,\r
+      const CRecordVector<UInt32> &packCRCs);\r
+\r
+  void WriteUnpackInfo(const CObjectVector<CFolder> &folders);\r
+\r
+  void WriteSubStreamsInfo(\r
+      const CObjectVector<CFolder> &folders,\r
+      const CRecordVector<CNum> &numUnpackStreamsInFolders,\r
+      const CRecordVector<UInt64> &unpackSizes,\r
+      const CRecordVector<bool> &digestsDefined,\r
+      const CRecordVector<UInt32> &hashDigests);\r
+\r
+  void SkipAlign(unsigned pos, unsigned alignSize);\r
+  void WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize);\r
+  void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type);\r
+\r
+  HRESULT EncodeStream(\r
+      DECL_EXTERNAL_CODECS_LOC_VARS\r
+      CEncoder &encoder, const CByteBuffer &data,\r
+      CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders);\r
+  void WriteHeader(\r
+      const CArchiveDatabase &db,\r
+      const CHeaderOptions &headerOptions,\r
+      UInt64 &headerOffset);\r
+  \r
+  bool _countMode;\r
+  bool _writeToStream;\r
+  size_t _countSize;\r
+  UInt32 _crc;\r
+  COutBuffer _outByte;\r
+  CWriteBufferLoc _outByte2;\r
+\r
+  #ifdef _7Z_VOL\r
+  bool _endMarker;\r
+  #endif\r
+\r
+  HRESULT WriteSignature();\r
+  #ifdef _7Z_VOL\r
+  HRESULT WriteFinishSignature();\r
+  #endif\r
+  HRESULT WriteStartHeader(const CStartHeader &h);\r
+  #ifdef _7Z_VOL\r
+  HRESULT WriteFinishHeader(const CFinishHeader &h);\r
+  #endif\r
+  CMyComPtr<IOutStream> Stream;\r
+public:\r
+\r
+  COutArchive() { _outByte.Create(1 << 16); }\r
+  CMyComPtr<ISequentialOutStream> SeqStream;\r
+  HRESULT Create(ISequentialOutStream *stream, bool endMarker);\r
+  void Close();\r
+  HRESULT SkipPrefixArchiveHeader();\r
+  HRESULT WriteDatabase(\r
+      DECL_EXTERNAL_CODECS_LOC_VARS\r
+      const CArchiveDatabase &db,\r
+      const CCompressionMethodMode *options,\r
+      const CHeaderOptions &headerOptions);\r
+\r
+  #ifdef _7Z_VOL\r
+  static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false);\r
+  static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false);\r
+  #endif\r
+\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/7z/7zProperties.cpp b/CPP/7zip/Archive/7z/7zProperties.cpp
new file mode 100755 (executable)
index 0000000..432da23
--- /dev/null
@@ -0,0 +1,164 @@
+// 7zProperties.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "7zProperties.h"\r
+#include "7zHeader.h"\r
+#include "7zHandler.h"\r
+\r
+// #define _MULTI_PACK\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+struct CPropMap\r
+{\r
+  UInt64 FilePropID;\r
+  STATPROPSTG StatPROPSTG;\r
+};\r
+\r
+CPropMap kPropMap[] =\r
+{\r
+  { NID::kName, { NULL, kpidPath, VT_BSTR } },\r
+  { NID::kSize, { NULL, kpidSize, VT_UI8 } },\r
+  { NID::kPackInfo, { NULL, kpidPackSize, VT_UI8 } },\r
+  \r
+  #ifdef _MULTI_PACK\r
+  { 100, { L"Pack0", kpidPackedSize0, VT_UI8 } },\r
+  { 101, { L"Pack1", kpidPackedSize1, VT_UI8 } },\r
+  { 102, { L"Pack2", kpidPackedSize2, VT_UI8 } },\r
+  { 103, { L"Pack3", kpidPackedSize3, VT_UI8 } },\r
+  { 104, { L"Pack4", kpidPackedSize4, VT_UI8 } },\r
+  #endif\r
+\r
+  { NID::kCTime, { NULL, kpidCTime, VT_FILETIME } },\r
+  { NID::kMTime, { NULL, kpidMTime, VT_FILETIME } },\r
+  { NID::kATime, { NULL, kpidATime, VT_FILETIME } },\r
+  { NID::kWinAttributes, { NULL, kpidAttrib, VT_UI4 } },\r
+  { NID::kStartPos, { NULL, kpidPosition, VT_UI4 } },\r
+\r
+  { NID::kCRC, { NULL, kpidCRC, VT_UI4 } },\r
+  \r
+  { NID::kAnti, { NULL, kpidIsAnti, VT_BOOL } }\r
+\r
+  #ifndef _SFX\r
+  ,\r
+  { 97, { NULL,kpidEncrypted, VT_BOOL } },\r
+  { 98, { NULL,kpidMethod, VT_BSTR } },\r
+  { 99, { NULL,kpidBlock, VT_UI4 } }\r
+  #endif\r
+};\r
+\r
+static const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]);\r
+\r
+static int FindPropInMap(UInt64 filePropID)\r
+{\r
+  for (int i = 0; i < kPropMapSize; i++)\r
+    if (kPropMap[i].FilePropID == filePropID)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+static void CopyOneItem(CRecordVector<UInt64> &src,\r
+    CRecordVector<UInt64> &dest, UInt32 item)\r
+{\r
+  for (int i = 0; i < src.Size(); i++)\r
+    if (src[i] == item)\r
+    {\r
+      dest.Add(item);\r
+      src.Delete(i);\r
+      return;\r
+    }\r
+}\r
+\r
+static void RemoveOneItem(CRecordVector<UInt64> &src, UInt32 item)\r
+{\r
+  for (int i = 0; i < src.Size(); i++)\r
+    if (src[i] == item)\r
+    {\r
+      src.Delete(i);\r
+      return;\r
+    }\r
+}\r
+\r
+static void InsertToHead(CRecordVector<UInt64> &dest, UInt32 item)\r
+{\r
+  for (int i = 0; i < dest.Size(); i++)\r
+    if (dest[i] == item)\r
+    {\r
+      dest.Delete(i);\r
+      break;\r
+    }\r
+  dest.Insert(0, item);\r
+}\r
+\r
+void CHandler::FillPopIDs()\r
+{\r
+  _fileInfoPopIDs.Clear();\r
+\r
+  #ifdef _7Z_VOL\r
+  if(_volumes.Size() < 1)\r
+    return;\r
+  const CVolume &volume = _volumes.Front();\r
+  const CArchiveDatabaseEx &_db = volume.Database;\r
+  #endif\r
+\r
+  CRecordVector<UInt64> fileInfoPopIDs = _db.ArchiveInfo.FileInfoPopIDs;\r
+\r
+  RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream);\r
+  RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile);\r
+\r
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kName);\r
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kAnti);\r
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kSize);\r
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kPackInfo);\r
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCTime);\r
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kMTime);\r
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kATime);\r
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kWinAttributes);\r
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCRC);\r
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kComment);\r
+  _fileInfoPopIDs += fileInfoPopIDs;\r
\r
+  #ifndef _SFX\r
+  _fileInfoPopIDs.Add(97);\r
+  _fileInfoPopIDs.Add(98);\r
+  _fileInfoPopIDs.Add(99);\r
+  #endif\r
+  #ifdef _MULTI_PACK\r
+  _fileInfoPopIDs.Add(100);\r
+  _fileInfoPopIDs.Add(101);\r
+  _fileInfoPopIDs.Add(102);\r
+  _fileInfoPopIDs.Add(103);\r
+  _fileInfoPopIDs.Add(104);\r
+  #endif\r
+\r
+  #ifndef _SFX\r
+  InsertToHead(_fileInfoPopIDs, NID::kMTime);\r
+  InsertToHead(_fileInfoPopIDs, NID::kPackInfo);\r
+  InsertToHead(_fileInfoPopIDs, NID::kSize);\r
+  InsertToHead(_fileInfoPopIDs, NID::kName);\r
+  #endif\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties)\r
+{\r
+  *numProperties = _fileInfoPopIDs.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)\r
+{\r
+  if ((int)index >= _fileInfoPopIDs.Size())\r
+    return E_INVALIDARG;\r
+  int indexInMap = FindPropInMap(_fileInfoPopIDs[index]);\r
+  if (indexInMap == -1)\r
+    return E_INVALIDARG;\r
+  const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG;\r
+  *propID = srcItem.propid;\r
+  *varType = srcItem.vt;\r
+  *name = 0;\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/7z/7zProperties.h b/CPP/7zip/Archive/7z/7zProperties.h
new file mode 100755 (executable)
index 0000000..7b78130
--- /dev/null
@@ -0,0 +1,22 @@
+// 7zProperties.h\r
+\r
+#ifndef __7Z_PROPERTIES_H\r
+#define __7Z_PROPERTIES_H\r
+\r
+#include "../../PropID.h"\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+enum\r
+{\r
+  kpidPackedSize0 = kpidUserDefined,\r
+  kpidPackedSize1,\r
+  kpidPackedSize2,\r
+  kpidPackedSize3,\r
+  kpidPackedSize4\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/7z/7zRegister.cpp b/CPP/7zip/Archive/7z/7zRegister.cpp
new file mode 100755 (executable)
index 0000000..ac3d133
--- /dev/null
@@ -0,0 +1,18 @@
+// 7zRegister.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/RegisterArc.h"\r
+\r
+#include "7zHandler.h"\r
+static IInArchive *CreateArc() { return new NArchive::N7z::CHandler; }\r
+#ifndef EXTRACT_ONLY\r
+static IOutArchive *CreateArcOut() { return new NArchive::N7z::CHandler; }\r
+#else\r
+#define CreateArcOut 0\r
+#endif\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"7z", L"7z", 0, 7, {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}, 6, false, CreateArc, CreateArcOut };\r
+\r
+REGISTER_ARC(7z)\r
diff --git a/CPP/7zip/Archive/7z/7zSpecStream.cpp b/CPP/7zip/Archive/7z/7zSpecStream.cpp
new file mode 100755 (executable)
index 0000000..58f2ec4
--- /dev/null
@@ -0,0 +1,24 @@
+// 7zSpecStream.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "7zSpecStream.h"\r
+\r
+STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  UInt32 realProcessedSize;\r
+  HRESULT result = _stream->Read(data, size, &realProcessedSize);\r
+  _size += realProcessedSize;\r
+  if (processedSize != 0)\r
+    *processedSize = realProcessedSize;\r
+  return result;\r
+}\r
+\r
+STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize(\r
+    UInt64 subStream, UInt64 *value)\r
+{\r
+  if (_getSubStreamSize == NULL)\r
+    return E_NOTIMPL;\r
+  return  _getSubStreamSize->GetSubStreamSize(subStream, value);\r
+}\r
+\r
diff --git a/CPP/7zip/Archive/7z/7zSpecStream.h b/CPP/7zip/Archive/7z/7zSpecStream.h
new file mode 100755 (executable)
index 0000000..0058ac2
--- /dev/null
@@ -0,0 +1,35 @@
+// 7zSpecStream.h\r
+\r
+#ifndef __7Z_SPEC_STREAM_H\r
+#define __7Z_SPEC_STREAM_H\r
+\r
+#include "../../IStream.h"\r
+#include "../../ICoder.h"\r
+#include "../../../Common/MyCom.h"\r
+\r
+class CSequentialInStreamSizeCount2:\r
+  public ISequentialInStream,\r
+  public ICompressGetSubStreamSize,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<ISequentialInStream> _stream;\r
+  CMyComPtr<ICompressGetSubStreamSize> _getSubStreamSize;\r
+  UInt64 _size;\r
+public:\r
+  void Init(ISequentialInStream *stream)\r
+  {\r
+    _stream = stream;\r
+    _getSubStreamSize = 0;\r
+    _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);\r
+    _size = 0;\r
+  }\r
+  UInt64 GetSize() const { return _size; }\r
+\r
+  MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)\r
+\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+\r
+  STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp
new file mode 100755 (executable)
index 0000000..4b4db06
--- /dev/null
@@ -0,0 +1,1177 @@
+// 7zUpdate.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/CpuArch.h"\r
+\r
+#include "../../Common/LimitedStreams.h"\r
+#include "../../Common/ProgressUtils.h"\r
+\r
+#include "../../Common/CreateCoder.h"\r
+\r
+#include "../../Compress/CopyCoder.h"\r
+\r
+#include "../Common/ItemNameUtils.h"\r
+#include "../Common/OutStreamWithCRC.h"\r
+\r
+#include "7zDecode.h"\r
+#include "7zEncode.h"\r
+#include "7zFolderInStream.h"\r
+#include "7zHandler.h"\r
+#include "7zOut.h"\r
+#include "7zUpdate.h"\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+static const UInt64 k_LZMA = 0x030101;\r
+static const UInt64 k_BCJ  = 0x03030103;\r
+static const UInt64 k_BCJ2 = 0x0303011B;\r
+\r
+static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2";\r
+static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20;\r
+static const UInt32 kAlgorithmForBCJ2_LZMA = 1;\r
+static const UInt32 kNumFastBytesForBCJ2_LZMA = 64;\r
+\r
+#ifdef MY_CPU_X86_OR_AMD64\r
+#define USE_86_FILTER\r
+#endif\r
+\r
+static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream,\r
+    UInt64 position, UInt64 size, ICompressProgressInfo *progress)\r
+{\r
+  RINOK(inStream->Seek(position, STREAM_SEEK_SET, 0));\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec);\r
+  streamSpec->SetStream(inStream);\r
+  streamSpec->Init(size);\r
+\r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+  RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress));\r
+  return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL);\r
+}\r
+\r
+static int GetReverseSlashPos(const UString &name)\r
+{\r
+  int slashPos = name.ReverseFind(L'/');\r
+  #ifdef _WIN32\r
+  int slash1Pos = name.ReverseFind(L'\\');\r
+  slashPos = MyMax(slashPos, slash1Pos);\r
+  #endif\r
+  return slashPos;\r
+}\r
+\r
+int CUpdateItem::GetExtensionPos() const\r
+{\r
+  int slashPos = GetReverseSlashPos(Name);\r
+  int dotPos = Name.ReverseFind(L'.');\r
+  if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))\r
+    return Name.Length();\r
+  return dotPos + 1;\r
+}\r
+\r
+UString CUpdateItem::GetExtension() const\r
+{\r
+  return Name.Mid(GetExtensionPos());\r
+}\r
+\r
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }\r
+\r
+#define RINOZ_COMP(a, b) RINOZ(MyCompare(a, b))\r
+\r
+static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2)\r
+{\r
+  size_t c1 = a1.GetCapacity();\r
+  size_t c2 = a2.GetCapacity();\r
+  RINOZ_COMP(c1, c2);\r
+  for (size_t i = 0; i < c1; i++)\r
+    RINOZ_COMP(a1[i], a2[i]);\r
+  return 0;\r
+}\r
+\r
+static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2)\r
+{\r
+  RINOZ_COMP(c1.NumInStreams, c2.NumInStreams);\r
+  RINOZ_COMP(c1.NumOutStreams, c2.NumOutStreams);\r
+  RINOZ_COMP(c1.MethodID, c2.MethodID);\r
+  return CompareBuffers(c1.Props, c2.Props);\r
+}\r
+\r
+static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2)\r
+{\r
+  RINOZ_COMP(b1.InIndex, b2.InIndex);\r
+  return MyCompare(b1.OutIndex, b2.OutIndex);\r
+}\r
+\r
+static int CompareFolders(const CFolder &f1, const CFolder &f2)\r
+{\r
+  int s1 = f1.Coders.Size();\r
+  int s2 = f2.Coders.Size();\r
+  RINOZ_COMP(s1, s2);\r
+  int i;\r
+  for (i = 0; i < s1; i++)\r
+    RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i]));\r
+  s1 = f1.BindPairs.Size();\r
+  s2 = f2.BindPairs.Size();\r
+  RINOZ_COMP(s1, s2);\r
+  for (i = 0; i < s1; i++)\r
+    RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i]));\r
+  return 0;\r
+}\r
+\r
+/*\r
+static int CompareFiles(const CFileItem &f1, const CFileItem &f2)\r
+{\r
+  return MyStringCompareNoCase(f1.Name, f2.Name);\r
+}\r
+*/\r
+\r
+struct CFolderRepack\r
+{\r
+  int FolderIndex;\r
+  int Group;\r
+  CNum NumCopyFiles;\r
+};\r
+\r
+static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *param)\r
+{\r
+  RINOZ_COMP(p1->Group, p2->Group);\r
+  int i1 = p1->FolderIndex;\r
+  int i2 = p2->FolderIndex;\r
+  const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param;\r
+  RINOZ(CompareFolders(\r
+      db.Folders[i1],\r
+      db.Folders[i2]));\r
+  return MyCompare(i1, i2);\r
+  /*\r
+  RINOZ_COMP(\r
+      db.NumUnpackStreamsVector[i1],\r
+      db.NumUnpackStreamsVector[i2]);\r
+  if (db.NumUnpackStreamsVector[i1] == 0)\r
+    return 0;\r
+  return CompareFiles(\r
+      db.Files[db.FolderStartFileIndex[i1]],\r
+      db.Files[db.FolderStartFileIndex[i2]]);\r
+  */\r
+}\r
+\r
+////////////////////////////////////////////////////////////\r
+\r
+static int CompareEmptyItems(const int *p1, const int *p2, void *param)\r
+{\r
+  const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param;\r
+  const CUpdateItem &u1 = updateItems[*p1];\r
+  const CUpdateItem &u2 = updateItems[*p2];\r
+  if (u1.IsDir != u2.IsDir)\r
+    return (u1.IsDir) ? 1 : -1;\r
+  if (u1.IsDir)\r
+  {\r
+    if (u1.IsAnti != u2.IsAnti)\r
+      return (u1.IsAnti ? 1 : -1);\r
+    int n = MyStringCompareNoCase(u1.Name, u2.Name);\r
+    return -n;\r
+  }\r
+  if (u1.IsAnti != u2.IsAnti)\r
+    return (u1.IsAnti ? 1 : -1);\r
+  return MyStringCompareNoCase(u1.Name, u2.Name);\r
+}\r
+\r
+static const char *g_Exts =\r
+  " lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab ha lha lzh rar zoo"\r
+  " zip jar ear war msi"\r
+  " 3gp avi mov mpeg mpg mpe wmv"\r
+  " aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav"\r
+  " swf "\r
+  " chm hxi hxs"\r
+  " gif jpeg jpg jp2 png tiff  bmp ico psd psp"\r
+  " awg ps eps cgm dxf svg vrml wmf emf ai md"\r
+  " cad dwg pps key sxi"\r
+  " max 3ds"\r
+  " iso bin nrg mdf img pdi tar cpio xpi"\r
+  " vfd vhd vud vmc vsv"\r
+  " vmdk dsk nvram vmem vmsd vmsn vmss vmtm"\r
+  " inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def"\r
+  " f77 f f90 f95"\r
+  " asm sql manifest dep "\r
+  " mak clw csproj vcproj sln dsp dsw "\r
+  " class "\r
+  " bat cmd"\r
+  " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml"\r
+  " awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs"\r
+  " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf"\r
+  " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf"\r
+  " abw afp cwk lwp wpd wps wpt wrf wri"\r
+  " abf afm bdf fon mgf otf pcf pfa snf ttf"\r
+  " dbf mdb nsf ntf wdb db fdb gdb"\r
+  " exe dll ocx vbx sfx sys tlb awx com obj lib out o so "\r
+  " pdb pch idb ncb opt";\r
+\r
+int GetExtIndex(const char *ext)\r
+{\r
+  int extIndex = 1;\r
+  const char *p = g_Exts;\r
+  for (;;)\r
+  {\r
+    char c = *p++;\r
+    if (c == 0)\r
+      return extIndex;\r
+    if (c == ' ')\r
+      continue;\r
+    int pos = 0;\r
+    for (;;)\r
+    {\r
+      char c2 = ext[pos++];\r
+      if (c2 == 0 && (c == 0 || c == ' '))\r
+        return extIndex;\r
+      if (c != c2)\r
+        break;\r
+      c = *p++;\r
+    }\r
+    extIndex++;\r
+    for (;;)\r
+    {\r
+      if (c == 0)\r
+        return extIndex;\r
+      if (c == ' ')\r
+        break;\r
+      c = *p++;\r
+    }\r
+  }\r
+}\r
+\r
+struct CRefItem\r
+{\r
+  const CUpdateItem *UpdateItem;\r
+  UInt32 Index;\r
+  UInt32 ExtensionPos;\r
+  UInt32 NamePos;\r
+  int ExtensionIndex;\r
+  CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType):\r
+    UpdateItem(&ui),\r
+    Index(index),\r
+    ExtensionPos(0),\r
+    NamePos(0),\r
+    ExtensionIndex(0)\r
+  {\r
+    if (sortByType)\r
+    {\r
+      int slashPos = GetReverseSlashPos(ui.Name);\r
+      NamePos = ((slashPos >= 0) ? (slashPos + 1) : 0);\r
+      int dotPos = ui.Name.ReverseFind(L'.');\r
+      if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))\r
+        ExtensionPos = ui.Name.Length();\r
+      else\r
+      {\r
+        ExtensionPos = dotPos + 1;\r
+        UString us = ui.Name.Mid(ExtensionPos);\r
+        if (!us.IsEmpty())\r
+        {\r
+          us.MakeLower();\r
+          int i;\r
+          AString s;\r
+          for (i = 0; i < us.Length(); i++)\r
+          {\r
+            wchar_t c = us[i];\r
+            if (c >= 0x80)\r
+              break;\r
+            s += (char)c;\r
+          }\r
+          if (i == us.Length())\r
+            ExtensionIndex = GetExtIndex(s);\r
+          else\r
+            ExtensionIndex = 0;\r
+        }\r
+      }\r
+    }\r
+  }\r
+};\r
+\r
+static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param)\r
+{\r
+  const CRefItem &a1 = *p1;\r
+  const CRefItem &a2 = *p2;\r
+  const CUpdateItem &u1 = *a1.UpdateItem;\r
+  const CUpdateItem &u2 = *a2.UpdateItem;\r
+  int n;\r
+  if (u1.IsDir != u2.IsDir)\r
+    return (u1.IsDir) ? 1 : -1;\r
+  if (u1.IsDir)\r
+  {\r
+    if (u1.IsAnti != u2.IsAnti)\r
+      return (u1.IsAnti ? 1 : -1);\r
+    n = MyStringCompareNoCase(u1.Name, u2.Name);\r
+    return -n;\r
+  }\r
+  bool sortByType = *(bool *)param;\r
+  if (sortByType)\r
+  {\r
+    RINOZ_COMP(a1.ExtensionIndex, a2.ExtensionIndex);\r
+    RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos));\r
+    RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos));\r
+    if (!u1.MTimeDefined && u2.MTimeDefined) return 1;\r
+    if (u1.MTimeDefined && !u2.MTimeDefined) return -1;\r
+    if (u1.MTimeDefined && u2.MTimeDefined) RINOZ_COMP(u1.MTime, u2.MTime);\r
+    RINOZ_COMP(u1.Size, u2.Size);\r
+  }\r
+  return MyStringCompareNoCase(u1.Name, u2.Name);\r
+}\r
+\r
+struct CSolidGroup\r
+{\r
+  CRecordVector<UInt32> Indices;\r
+};\r
+\r
+static wchar_t *g_ExeExts[] =\r
+{\r
+  L"dll",\r
+  L"exe",\r
+  L"ocx",\r
+  L"sfx",\r
+  L"sys"\r
+};\r
+\r
+static bool IsExeExt(const UString &ext)\r
+{\r
+  for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++)\r
+    if (ext.CompareNoCase(g_ExeExts[i]) == 0)\r
+      return true;\r
+  return false;\r
+}\r
+\r
+#ifdef USE_86_FILTER\r
+\r
+static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult)\r
+{\r
+  methodResult.Id = methodID;\r
+  methodResult.NumInStreams = numInStreams;\r
+  methodResult.NumOutStreams = 1;\r
+}\r
+\r
+static void MakeExeMethod(const CCompressionMethodMode &method,\r
+    bool bcj2Filter, CCompressionMethodMode &exeMethod)\r
+{\r
+  exeMethod = method;\r
+  if (bcj2Filter)\r
+  {\r
+    CMethodFull methodFull;\r
+    GetMethodFull(k_BCJ2, 4, methodFull);\r
+    exeMethod.Methods.Insert(0, methodFull);\r
+    GetMethodFull(k_LZMA, 1, methodFull);\r
+    {\r
+      CProp prop;\r
+      prop.Id = NCoderPropID::kAlgorithm;\r
+      prop.Value = kAlgorithmForBCJ2_LZMA;\r
+      methodFull.Props.Add(prop);\r
+    }\r
+    {\r
+      CProp prop;\r
+      prop.Id = NCoderPropID::kMatchFinder;\r
+      prop.Value = kMatchFinderForBCJ2_LZMA;\r
+      methodFull.Props.Add(prop);\r
+    }\r
+    {\r
+      CProp prop;\r
+      prop.Id = NCoderPropID::kDictionarySize;\r
+      prop.Value = kDictionaryForBCJ2_LZMA;\r
+      methodFull.Props.Add(prop);\r
+    }\r
+    {\r
+      CProp prop;\r
+      prop.Id = NCoderPropID::kNumFastBytes;\r
+      prop.Value = kNumFastBytesForBCJ2_LZMA;\r
+      methodFull.Props.Add(prop);\r
+    }\r
+    {\r
+      CProp prop;\r
+      prop.Id = NCoderPropID::kNumThreads;\r
+      prop.Value = (UInt32)1;\r
+      methodFull.Props.Add(prop);\r
+    }\r
+\r
+    exeMethod.Methods.Add(methodFull);\r
+    exeMethod.Methods.Add(methodFull);\r
+    CBind bind;\r
+\r
+    bind.OutCoder = 0;\r
+    bind.InStream = 0;\r
+\r
+    bind.InCoder = 1;\r
+    bind.OutStream = 0;\r
+    exeMethod.Binds.Add(bind);\r
+\r
+    bind.InCoder = 2;\r
+    bind.OutStream = 1;\r
+    exeMethod.Binds.Add(bind);\r
+\r
+    bind.InCoder = 3;\r
+    bind.OutStream = 2;\r
+    exeMethod.Binds.Add(bind);\r
+  }\r
+  else\r
+  {\r
+    CMethodFull methodFull;\r
+    GetMethodFull(k_BCJ, 1, methodFull);\r
+    exeMethod.Methods.Insert(0, methodFull);\r
+    CBind bind;\r
+    bind.OutCoder = 0;\r
+    bind.InStream = 0;\r
+    bind.InCoder = 1;\r
+    bind.OutStream = 0;\r
+    exeMethod.Binds.Add(bind);\r
+  }\r
+}\r
+\r
+#endif\r
+\r
+static void FromUpdateItemToFileItem(const CUpdateItem &ui,\r
+    CFileItem &file, CFileItem2 &file2)\r
+{\r
+  file.Name = NItemName::MakeLegalName(ui.Name);\r
+  if (ui.AttribDefined)\r
+    file.SetAttrib(ui.Attrib);\r
+  \r
+  file2.CTime = ui.CTime;  file2.CTimeDefined = ui.CTimeDefined;\r
+  file2.ATime = ui.ATime;  file2.ATimeDefined = ui.ATimeDefined;\r
+  file2.MTime = ui.MTime;  file2.MTimeDefined = ui.MTimeDefined;\r
+  file2.IsAnti = ui.IsAnti;\r
+  file2.StartPosDefined = false;\r
+\r
+  file.Size = ui.Size;\r
+  file.IsDir = ui.IsDir;\r
+  file.HasStream = ui.HasStream();\r
+}\r
+\r
+class CFolderOutStream2:\r
+  public ISequentialOutStream,\r
+  public CMyUnknownImp\r
+{\r
+  COutStreamWithCRC *_crcStreamSpec;\r
+  CMyComPtr<ISequentialOutStream> _crcStream;\r
+  const CArchiveDatabaseEx *_db;\r
+  const CBoolVector *_extractStatuses;\r
+  CMyComPtr<ISequentialOutStream> _outStream;\r
+  UInt32 _startIndex;\r
+  int _currentIndex;\r
+  bool _fileIsOpen;\r
+  UInt64 _rem;\r
+\r
+  void OpenFile();\r
+  void CloseFile();\r
+  HRESULT CloseFileAndSetResult();\r
+  HRESULT ProcessEmptyFiles();\r
+public:\r
+  MY_UNKNOWN_IMP\r
+  \r
+  CFolderOutStream2()\r
+  {\r
+    _crcStreamSpec = new COutStreamWithCRC;\r
+    _crcStream = _crcStreamSpec;\r
+  }\r
+\r
+  HRESULT Init(const CArchiveDatabaseEx *db, UInt32 startIndex,\r
+      const CBoolVector *extractStatuses, ISequentialOutStream *outStream);\r
+  void ReleaseOutStream();\r
+  HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }\r
+\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+};\r
+\r
+HRESULT CFolderOutStream2::Init(const CArchiveDatabaseEx *db, UInt32 startIndex,\r
+    const CBoolVector *extractStatuses, ISequentialOutStream *outStream)\r
+{\r
+  _db = db;\r
+  _startIndex = startIndex;\r
+  _extractStatuses = extractStatuses;\r
+  _outStream = outStream;\r
+\r
+  _currentIndex = 0;\r
+  _fileIsOpen = false;\r
+  return ProcessEmptyFiles();\r
+}\r
+\r
+void CFolderOutStream2::ReleaseOutStream()\r
+{\r
+  _outStream.Release();\r
+  _crcStreamSpec->ReleaseStream();\r
+}\r
+\r
+void CFolderOutStream2::OpenFile()\r
+{\r
+  _crcStreamSpec->SetStream((*_extractStatuses)[_currentIndex] ? _outStream : NULL);\r
+  _crcStreamSpec->Init(true);\r
+  _fileIsOpen = true;\r
+  _rem = _db->Files[_startIndex + _currentIndex].Size;\r
+}\r
+\r
+void CFolderOutStream2::CloseFile()\r
+{\r
+  _crcStreamSpec->ReleaseStream();\r
+  _fileIsOpen = false;\r
+  _currentIndex++;\r
+}\r
+\r
+HRESULT CFolderOutStream2::CloseFileAndSetResult()\r
+{\r
+  const CFileItem &file = _db->Files[_startIndex + _currentIndex];\r
+  CloseFile();\r
+  return (file.IsDir || !file.CrcDefined || file.Crc == _crcStreamSpec->GetCRC()) ? S_OK: S_FALSE;\r
+}\r
+\r
+HRESULT CFolderOutStream2::ProcessEmptyFiles()\r
+{\r
+  while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)\r
+  {\r
+    OpenFile();\r
+    RINOK(CloseFileAndSetResult());\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize != NULL)\r
+    *processedSize = 0;\r
+  while (size != 0)\r
+  {\r
+    if (_fileIsOpen)\r
+    {\r
+      UInt32 cur = size < _rem ? size : (UInt32)_rem;\r
+      RINOK(_crcStream->Write(data, cur, &cur));\r
+      if (cur == 0)\r
+        break;\r
+      data = (const Byte *)data + cur;\r
+      size -= cur;\r
+      _rem -= cur;\r
+      if (processedSize != NULL)\r
+        *processedSize += cur;\r
+      if (_rem == 0)\r
+      {\r
+        RINOK(CloseFileAndSetResult());\r
+        RINOK(ProcessEmptyFiles());\r
+        continue;\r
+      }\r
+    }\r
+    else\r
+    {\r
+      RINOK(ProcessEmptyFiles());\r
+      if (_currentIndex == _extractStatuses->Size())\r
+      {\r
+        // we don't support partial extracting\r
+        return E_FAIL;\r
+      }\r
+      OpenFile();\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+class CThreadDecoder: public CVirtThread\r
+{\r
+public:\r
+  HRESULT Result;\r
+  CMyComPtr<IInStream> InStream;\r
+\r
+  CFolderOutStream2 *FosSpec;\r
+  CMyComPtr<ISequentialOutStream> Fos;\r
+\r
+  UInt64 StartPos;\r
+  const UInt64 *PackSizes;\r
+  const CFolder *Folder;\r
+  #ifndef _NO_CRYPTO\r
+  CMyComPtr<ICryptoGetTextPassword> GetTextPassword;\r
+  #endif\r
+\r
+  DECL_EXTERNAL_CODECS_VARS\r
+  CDecoder Decoder;\r
+\r
+  #ifndef _7ZIP_ST\r
+  bool MtMode;\r
+  UInt32 NumThreads;\r
+  #endif\r
+\r
+  CThreadDecoder():\r
+    Decoder(true)\r
+  {\r
+    #ifndef _7ZIP_ST\r
+    MtMode = false;\r
+    NumThreads = 1;\r
+    #endif\r
+    FosSpec = new CFolderOutStream2;\r
+    Fos = FosSpec;\r
+    Result = E_FAIL;\r
+  }\r
+  virtual void Execute();\r
+};\r
+\r
+void CThreadDecoder::Execute()\r
+{\r
+  try\r
+  {\r
+    #ifndef _NO_CRYPTO\r
+    bool passwordIsDefined;\r
+    #endif\r
+    Result = Decoder.Decode(\r
+      EXTERNAL_CODECS_VARS\r
+      InStream,\r
+      StartPos,\r
+      PackSizes,\r
+      *Folder,\r
+      Fos,\r
+      NULL\r
+      #ifndef _NO_CRYPTO\r
+      , GetTextPassword, passwordIsDefined\r
+      #endif\r
+      #ifndef _7ZIP_ST\r
+      , MtMode, NumThreads\r
+      #endif\r
+      );\r
+  }\r
+  catch(...)\r
+  {\r
+    Result = E_FAIL;\r
+  }\r
+  if (Result == S_OK)\r
+    Result = FosSpec->CheckFinishedState();\r
+  FosSpec->ReleaseOutStream();\r
+}\r
+\r
+bool static Is86FilteredFolder(const CFolder &f)\r
+{\r
+  for (int i = 0; i < f.Coders.Size(); i++)\r
+  {\r
+    CMethodId m = f.Coders[i].MethodID;\r
+    if (m == k_BCJ || m == k_BCJ2)\r
+      return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+#ifndef _NO_CRYPTO\r
+\r
+class CCryptoGetTextPassword:\r
+  public ICryptoGetTextPassword,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  UString Password;\r
+\r
+  MY_UNKNOWN_IMP\r
+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);\r
+};\r
+\r
+STDMETHODIMP CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password)\r
+{\r
+  return StringToBstr(Password, password);\r
+}\r
+\r
+#endif\r
+\r
+static const int kNumGroupsMax = 4;\r
+\r
+#ifdef USE_86_FILTER\r
+static bool Is86Group(int group) { return (group & 1) != 0; }\r
+#endif\r
+static bool IsEncryptedGroup(int group) { return (group & 2) != 0; }\r
+static int GetGroupIndex(bool encrypted, int bcjFiltered)\r
+  { return (encrypted ? 2 : 0) + (bcjFiltered ? 1 : 0); }\r
+\r
+HRESULT Update(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    IInStream *inStream,\r
+    const CArchiveDatabaseEx *db,\r
+    const CObjectVector<CUpdateItem> &updateItems,\r
+    COutArchive &archive,\r
+    CArchiveDatabase &newDatabase,\r
+    ISequentialOutStream *seqOutStream,\r
+    IArchiveUpdateCallback *updateCallback,\r
+    const CUpdateOptions &options\r
+    #ifndef _NO_CRYPTO\r
+    , ICryptoGetTextPassword *getDecoderPassword\r
+    #endif\r
+    )\r
+{\r
+  UInt64 numSolidFiles = options.NumSolidFiles;\r
+  if (numSolidFiles == 0)\r
+    numSolidFiles = 1;\r
+  /*\r
+  CMyComPtr<IOutStream> outStream;\r
+  RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream));\r
+  if (!outStream)\r
+    return E_NOTIMPL;\r
+  */\r
+\r
+  UInt64 startBlockSize = db != 0 ? db->ArchiveInfo.StartPosition: 0;\r
+  if (startBlockSize > 0 && !options.RemoveSfxBlock)\r
+  {\r
+    RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL));\r
+  }\r
+\r
+  CRecordVector<int> fileIndexToUpdateIndexMap;\r
+  CRecordVector<CFolderRepack> folderRefs;\r
+  UInt64 complexity = 0;\r
+  UInt64 inSizeForReduce2 = 0;\r
+  bool needEncryptedRepack = false;\r
+  if (db != 0)\r
+  {\r
+    fileIndexToUpdateIndexMap.Reserve(db->Files.Size());\r
+    int i;\r
+    for (i = 0; i < db->Files.Size(); i++)\r
+      fileIndexToUpdateIndexMap.Add(-1);\r
+\r
+    for (i = 0; i < updateItems.Size(); i++)\r
+    {\r
+      int index = updateItems[i].IndexInArchive;\r
+      if (index != -1)\r
+        fileIndexToUpdateIndexMap[index] = i;\r
+    }\r
+\r
+    for (i = 0; i < db->Folders.Size(); i++)\r
+    {\r
+      CNum indexInFolder = 0;\r
+      CNum numCopyItems = 0;\r
+      CNum numUnpackStreams = db->NumUnpackStreamsVector[i];\r
+      UInt64 repackSize = 0;\r
+      for (CNum fi = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fi++)\r
+      {\r
+        const CFileItem &file = db->Files[fi];\r
+        if (file.HasStream)\r
+        {\r
+          indexInFolder++;\r
+          int updateIndex = fileIndexToUpdateIndexMap[fi];\r
+          if (updateIndex >= 0 && !updateItems[updateIndex].NewData)\r
+          {\r
+            numCopyItems++;\r
+            repackSize += file.Size;\r
+          }\r
+        }\r
+      }\r
+\r
+      if (numCopyItems == 0)\r
+        continue;\r
+\r
+      CFolderRepack rep;\r
+      rep.FolderIndex = i;\r
+      rep.NumCopyFiles = numCopyItems;\r
+      const CFolder &f = db->Folders[i];\r
+      bool isEncrypted = f.IsEncrypted();\r
+      rep.Group = GetGroupIndex(isEncrypted, Is86FilteredFolder(f));\r
+      folderRefs.Add(rep);\r
+      if (numCopyItems == numUnpackStreams)\r
+        complexity += db->GetFolderFullPackSize(i);\r
+      else\r
+      {\r
+        complexity += repackSize;\r
+        if (repackSize > inSizeForReduce2)\r
+          inSizeForReduce2 = repackSize;\r
+        if (isEncrypted)\r
+          needEncryptedRepack = true;\r
+      }\r
+    }\r
+    folderRefs.Sort(CompareFolderRepacks, (void *)db);\r
+  }\r
+\r
+  UInt64 inSizeForReduce = 0;\r
+  int i;\r
+  for (i = 0; i < updateItems.Size(); i++)\r
+  {\r
+    const CUpdateItem &ui = updateItems[i];\r
+    if (ui.NewData)\r
+    {\r
+      complexity += ui.Size;\r
+      if (numSolidFiles != 1)\r
+        inSizeForReduce += ui.Size;\r
+      else if (ui.Size > inSizeForReduce)\r
+        inSizeForReduce = ui.Size;\r
+    }\r
+  }\r
+\r
+  if (inSizeForReduce2 > inSizeForReduce)\r
+    inSizeForReduce = inSizeForReduce2;\r
+\r
+  const UInt32 kMinReduceSize = (1 << 16);\r
+  if (inSizeForReduce < kMinReduceSize)\r
+    inSizeForReduce = kMinReduceSize;\r
+\r
+  RINOK(updateCallback->SetTotal(complexity));\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(updateCallback, true);\r
+\r
+  CThreadDecoder threadDecoder;\r
+  if (!folderRefs.IsEmpty())\r
+  {\r
+    #ifdef EXTERNAL_CODECS\r
+    threadDecoder._codecsInfo = codecsInfo;\r
+    threadDecoder._externalCodecs = *externalCodecs;\r
+    #endif\r
+    RINOK(threadDecoder.Create());\r
+  }\r
+\r
+  CObjectVector<CSolidGroup> groups;\r
+  for (i = 0; i < kNumGroupsMax; i++)\r
+    groups.Add(CSolidGroup());\r
+\r
+  {\r
+    // ---------- Split files to 2 groups ----------\r
+\r
+    bool useFilters = options.UseFilters;\r
+    const CCompressionMethodMode &method = *options.Method;\r
+    if (method.Methods.Size() != 1 || method.Binds.Size() != 0)\r
+      useFilters = false;\r
+    for (i = 0; i < updateItems.Size(); i++)\r
+    {\r
+      const CUpdateItem &ui = updateItems[i];\r
+      if (!ui.NewData || !ui.HasStream())\r
+        continue;\r
+      bool filteredGroup = false;\r
+      if (useFilters)\r
+      {\r
+        int dotPos = ui.Name.ReverseFind(L'.');\r
+        if (dotPos >= 0)\r
+          filteredGroup = IsExeExt(ui.Name.Mid(dotPos + 1));\r
+      }\r
+      groups[GetGroupIndex(method.PasswordIsDefined, filteredGroup)].Indices.Add(i);\r
+    }\r
+  }\r
+\r
+  #ifndef _NO_CRYPTO\r
+\r
+  CCryptoGetTextPassword *getPasswordSpec = NULL;\r
+  if (needEncryptedRepack)\r
+  {\r
+    getPasswordSpec = new CCryptoGetTextPassword;\r
+    threadDecoder.GetTextPassword = getPasswordSpec;\r
+\r
+    if (options.Method->PasswordIsDefined)\r
+      getPasswordSpec->Password = options.Method->Password;\r
+    else\r
+    {\r
+      if (!getDecoderPassword)\r
+        return E_NOTIMPL;\r
+      CMyComBSTR password;\r
+      RINOK(getDecoderPassword->CryptoGetTextPassword(&password));\r
+      getPasswordSpec->Password = password;\r
+    }\r
+  }\r
+\r
+  #endif\r
+\r
+  // ---------- Compress ----------\r
+\r
+  RINOK(archive.Create(seqOutStream, false));\r
+  RINOK(archive.SkipPrefixArchiveHeader());\r
+\r
+  int folderRefIndex = 0;\r
+  lps->ProgressOffset = 0;\r
+\r
+  for (int groupIndex = 0; groupIndex < kNumGroupsMax; groupIndex++)\r
+  {\r
+    const CSolidGroup &group = groups[groupIndex];\r
+\r
+    CCompressionMethodMode method;\r
+    #ifdef USE_86_FILTER\r
+    if (Is86Group(groupIndex))\r
+      MakeExeMethod(*options.Method, options.MaxFilter, method);\r
+    else\r
+    #endif\r
+      method = *options.Method;\r
+\r
+    if (IsEncryptedGroup(groupIndex))\r
+    {\r
+      if (!method.PasswordIsDefined)\r
+      {\r
+        #ifndef _NO_CRYPTO\r
+        if (getPasswordSpec)\r
+          method.Password = getPasswordSpec->Password;\r
+        #endif\r
+        method.PasswordIsDefined = true;\r
+      }\r
+    }\r
+    else\r
+    {\r
+      method.PasswordIsDefined = false;\r
+      method.Password.Empty();\r
+    }\r
+\r
+    CEncoder encoder(method);\r
+\r
+    for (; folderRefIndex < folderRefs.Size(); folderRefIndex++)\r
+    {\r
+      const CFolderRepack &rep = folderRefs[folderRefIndex];\r
+      if (rep.Group != groupIndex)\r
+        break;\r
+      int folderIndex = rep.FolderIndex;\r
+      \r
+      if (rep.NumCopyFiles == db->NumUnpackStreamsVector[folderIndex])\r
+      {\r
+        UInt64 packSize = db->GetFolderFullPackSize(folderIndex);\r
+        RINOK(WriteRange(inStream, archive.SeqStream,\r
+          db->GetFolderStreamPos(folderIndex, 0), packSize, progress));\r
+        lps->ProgressOffset += packSize;\r
+        \r
+        const CFolder &folder = db->Folders[folderIndex];\r
+        CNum startIndex = db->FolderStartPackStreamIndex[folderIndex];\r
+        for (int j = 0; j < folder.PackStreams.Size(); j++)\r
+        {\r
+          newDatabase.PackSizes.Add(db->PackSizes[startIndex + j]);\r
+          // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]);\r
+          // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]);\r
+        }\r
+        newDatabase.Folders.Add(folder);\r
+      }\r
+      else\r
+      {\r
+        CStreamBinder sb;\r
+        RINOK(sb.CreateEvents());\r
+        CMyComPtr<ISequentialOutStream> sbOutStream;\r
+        CMyComPtr<ISequentialInStream> sbInStream;\r
+        sb.CreateStreams(&sbInStream, &sbOutStream);\r
+        CBoolVector extractStatuses;\r
+        \r
+        CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];\r
+        CNum indexInFolder = 0;\r
+        \r
+        for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)\r
+        {\r
+          bool needExtract = false;\r
+          if (db->Files[fi].HasStream)\r
+          {\r
+            indexInFolder++;\r
+            int updateIndex = fileIndexToUpdateIndexMap[fi];\r
+            if (updateIndex >= 0 && !updateItems[updateIndex].NewData)\r
+              needExtract = true;\r
+          }\r
+          extractStatuses.Add(needExtract);\r
+        }\r
+\r
+        RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream));\r
+        sbOutStream.Release();\r
+        \r
+        threadDecoder.InStream = inStream;\r
+        threadDecoder.Folder = &db->Folders[folderIndex];\r
+        threadDecoder.StartPos = db->GetFolderStreamPos(folderIndex, 0);\r
+        threadDecoder.PackSizes = &db->PackSizes[db->FolderStartPackStreamIndex[folderIndex]];\r
+        \r
+        threadDecoder.Start();\r
+        \r
+        int startPackIndex = newDatabase.PackSizes.Size();\r
+        CFolder newFolder;\r
+        RINOK(encoder.Encode(\r
+          EXTERNAL_CODECS_LOC_VARS\r
+          sbInStream, NULL, &inSizeForReduce, newFolder,\r
+          archive.SeqStream, newDatabase.PackSizes, progress));\r
+        \r
+        threadDecoder.WaitFinish();\r
+\r
+        RINOK(threadDecoder.Result);\r
+\r
+        for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)\r
+          lps->OutSize += newDatabase.PackSizes[startPackIndex];\r
+        lps->InSize += newFolder.GetUnpackSize();\r
+        \r
+        newDatabase.Folders.Add(newFolder);\r
+      }\r
+      \r
+      newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles);\r
+      \r
+      CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];\r
+      \r
+      CNum indexInFolder = 0;\r
+      for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)\r
+      {\r
+        CFileItem file;\r
+        CFileItem2 file2;\r
+        db->GetFile(fi, file, file2);\r
+        if (file.HasStream)\r
+        {\r
+          indexInFolder++;\r
+          int updateIndex = fileIndexToUpdateIndexMap[fi];\r
+          if (updateIndex >= 0)\r
+          {\r
+            const CUpdateItem &ui = updateItems[updateIndex];\r
+            if (ui.NewData)\r
+              continue;\r
+            if (ui.NewProps)\r
+            {\r
+              CFileItem uf;\r
+              FromUpdateItemToFileItem(ui, uf, file2);\r
+              uf.Size = file.Size;\r
+              uf.Crc = file.Crc;\r
+              uf.CrcDefined = file.CrcDefined;\r
+              uf.HasStream = file.HasStream;\r
+              file = uf;\r
+            }\r
+            newDatabase.AddFile(file, file2);\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    int numFiles = group.Indices.Size();\r
+    if (numFiles == 0)\r
+      continue;\r
+    CRecordVector<CRefItem> refItems;\r
+    refItems.Reserve(numFiles);\r
+    bool sortByType = (numSolidFiles > 1);\r
+    for (i = 0; i < numFiles; i++)\r
+      refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType));\r
+    refItems.Sort(CompareUpdateItems, (void *)&sortByType);\r
+    \r
+    CRecordVector<UInt32> indices;\r
+    indices.Reserve(numFiles);\r
+\r
+    for (i = 0; i < numFiles; i++)\r
+    {\r
+      UInt32 index = refItems[i].Index;\r
+      indices.Add(index);\r
+      /*\r
+      const CUpdateItem &ui = updateItems[index];\r
+      CFileItem file;\r
+      if (ui.NewProps)\r
+        FromUpdateItemToFileItem(ui, file);\r
+      else\r
+        file = db.Files[ui.IndexInArchive];\r
+      if (file.IsAnti || file.IsDir)\r
+        return E_FAIL;\r
+      newDatabase.Files.Add(file);\r
+      */\r
+    }\r
+    \r
+    for (i = 0; i < numFiles;)\r
+    {\r
+      UInt64 totalSize = 0;\r
+      int numSubFiles;\r
+      UString prevExtension;\r
+      for (numSubFiles = 0; i + numSubFiles < numFiles &&\r
+          numSubFiles < numSolidFiles; numSubFiles++)\r
+      {\r
+        const CUpdateItem &ui = updateItems[indices[i + numSubFiles]];\r
+        totalSize += ui.Size;\r
+        if (totalSize > options.NumSolidBytes)\r
+          break;\r
+        if (options.SolidExtension)\r
+        {\r
+          UString ext = ui.GetExtension();\r
+          if (numSubFiles == 0)\r
+            prevExtension = ext;\r
+          else\r
+            if (ext.CompareNoCase(prevExtension) != 0)\r
+              break;\r
+        }\r
+      }\r
+      if (numSubFiles < 1)\r
+        numSubFiles = 1;\r
+\r
+      CFolderInStream *inStreamSpec = new CFolderInStream;\r
+      CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec);\r
+      inStreamSpec->Init(updateCallback, &indices[i], numSubFiles);\r
+      \r
+      CFolder folderItem;\r
+\r
+      int startPackIndex = newDatabase.PackSizes.Size();\r
+      RINOK(encoder.Encode(\r
+          EXTERNAL_CODECS_LOC_VARS\r
+          solidInStream, NULL, &inSizeForReduce, folderItem,\r
+          archive.SeqStream, newDatabase.PackSizes, progress));\r
+\r
+      for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)\r
+        lps->OutSize += newDatabase.PackSizes[startPackIndex];\r
+\r
+      lps->InSize += folderItem.GetUnpackSize();\r
+      // for ()\r
+      // newDatabase.PackCRCsDefined.Add(false);\r
+      // newDatabase.PackCRCs.Add(0);\r
+      \r
+      newDatabase.Folders.Add(folderItem);\r
+      \r
+      CNum numUnpackStreams = 0;\r
+      for (int subIndex = 0; subIndex < numSubFiles; subIndex++)\r
+      {\r
+        const CUpdateItem &ui = updateItems[indices[i + subIndex]];\r
+        CFileItem file;\r
+        CFileItem2 file2;\r
+        if (ui.NewProps)\r
+          FromUpdateItemToFileItem(ui, file, file2);\r
+        else\r
+          db->GetFile(ui.IndexInArchive, file, file2);\r
+        if (file2.IsAnti || file.IsDir)\r
+          return E_FAIL;\r
+        \r
+        /*\r
+        CFileItem &file = newDatabase.Files[\r
+              startFileIndexInDatabase + i + subIndex];\r
+        */\r
+        if (!inStreamSpec->Processed[subIndex])\r
+        {\r
+          continue;\r
+          // file.Name += L".locked";\r
+        }\r
+\r
+        file.Crc = inStreamSpec->CRCs[subIndex];\r
+        file.Size = inStreamSpec->Sizes[subIndex];\r
+        if (file.Size != 0)\r
+        {\r
+          file.CrcDefined = true;\r
+          file.HasStream = true;\r
+          numUnpackStreams++;\r
+        }\r
+        else\r
+        {\r
+          file.CrcDefined = false;\r
+          file.HasStream = false;\r
+        }\r
+        newDatabase.AddFile(file, file2);\r
+      }\r
+      // numUnpackStreams = 0 is very bad case for locked files\r
+      // v3.13 doesn't understand it.\r
+      newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams);\r
+      i += numSubFiles;\r
+    }\r
+  }\r
+\r
+  if (folderRefIndex != folderRefs.Size())\r
+    return E_FAIL;\r
+\r
+  /*\r
+  folderRefs.ClearAndFree();\r
+  fileIndexToUpdateIndexMap.ClearAndFree();\r
+  groups.ClearAndFree();\r
+  */\r
+\r
+  {\r
+    // ---------- Write Folders & Empty Files ----------\r
+    \r
+    CRecordVector<int> emptyRefs;\r
+    for (i = 0; i < updateItems.Size(); i++)\r
+    {\r
+      const CUpdateItem &ui = updateItems[i];\r
+      if (ui.NewData)\r
+      {\r
+        if (ui.HasStream())\r
+          continue;\r
+      }\r
+      else if (ui.IndexInArchive != -1 && db->Files[ui.IndexInArchive].HasStream)\r
+        continue;\r
+      emptyRefs.Add(i);\r
+    }\r
+    emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);\r
+    for (i = 0; i < emptyRefs.Size(); i++)\r
+    {\r
+      const CUpdateItem &ui = updateItems[emptyRefs[i]];\r
+      CFileItem file;\r
+      CFileItem2 file2;\r
+      if (ui.NewProps)\r
+        FromUpdateItemToFileItem(ui, file, file2);\r
+      else\r
+        db->GetFile(ui.IndexInArchive, file, file2);\r
+      newDatabase.AddFile(file, file2);\r
+    }\r
+  }\r
+    \r
+  newDatabase.ReserveDown();\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h
new file mode 100755 (executable)
index 0000000..f3dc885
--- /dev/null
@@ -0,0 +1,88 @@
+// 7zUpdate.h\r
+\r
+#ifndef __7Z_UPDATE_H\r
+#define __7Z_UPDATE_H\r
+\r
+#include "7zCompressionMode.h"\r
+#include "7zIn.h"\r
+#include "7zOut.h"\r
+\r
+#include "../IArchive.h"\r
+\r
+namespace NArchive {\r
+namespace N7z {\r
+\r
+struct CUpdateItem\r
+{\r
+  int IndexInArchive;\r
+  int IndexInClient;\r
+  \r
+  UInt64 CTime;\r
+  UInt64 ATime;\r
+  UInt64 MTime;\r
+\r
+  UInt64 Size;\r
+  UString Name;\r
+\r
+  UInt32 Attrib;\r
+  \r
+  bool NewData;\r
+  bool NewProps;\r
+\r
+  bool IsAnti;\r
+  bool IsDir;\r
+\r
+  bool AttribDefined;\r
+  bool CTimeDefined;\r
+  bool ATimeDefined;\r
+  bool MTimeDefined;\r
+\r
+  bool HasStream() const { return !IsDir && !IsAnti && Size != 0; }\r
+\r
+  CUpdateItem():\r
+      IsAnti(false),\r
+      IsDir(false),\r
+      AttribDefined(false),\r
+      CTimeDefined(false),\r
+      ATimeDefined(false),\r
+      MTimeDefined(false)\r
+      {}\r
+  void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); };\r
+\r
+  int GetExtensionPos() const;\r
+  UString GetExtension() const;\r
+};\r
+\r
+struct CUpdateOptions\r
+{\r
+  const CCompressionMethodMode *Method;\r
+  const CCompressionMethodMode *HeaderMethod;\r
+  bool UseFilters;\r
+  bool MaxFilter;\r
+\r
+  CHeaderOptions HeaderOptions;\r
+\r
+  UInt64 NumSolidFiles;\r
+  UInt64 NumSolidBytes;\r
+  bool SolidExtension;\r
+  bool RemoveSfxBlock;\r
+  bool VolumeMode;\r
+};\r
+\r
+HRESULT Update(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    IInStream *inStream,\r
+    const CArchiveDatabaseEx *db,\r
+    const CObjectVector<CUpdateItem> &updateItems,\r
+    COutArchive &archive,\r
+    CArchiveDatabase &newDatabase,\r
+    ISequentialOutStream *seqOutStream,\r
+    IArchiveUpdateCallback *updateCallback,\r
+    const CUpdateOptions &options\r
+    #ifndef _NO_CRYPTO\r
+    , ICryptoGetTextPassword *getDecoderPassword\r
+    #endif\r
+    );\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/7z/StdAfx.cpp b/CPP/7zip/Archive/7z/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..c6d3b1f
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/Archive/7z/StdAfx.h b/CPP/7zip/Archive/7z/StdAfx.h
new file mode 100755 (executable)
index 0000000..a4e6173
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+#include "../../../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/7z/makefile b/CPP/7zip/Archive/7z/makefile
new file mode 100755 (executable)
index 0000000..8836989
--- /dev/null
@@ -0,0 +1,110 @@
+PROG = 7z.dll\r
+DEF_FILE = ../Archive.def\r
+CFLAGS = $(CFLAGS) -I ../../../  \\r
+  -DEXTERNAL_CODECS \\r
+\r
+AR_OBJS = \\r
+  $O\ArchiveExports.obj \\r
+  $O\DllExports.obj \\r
+\r
+7Z_OBJS = \\r
+  $O\7zCompressionMode.obj \\r
+  $O\7zDecode.obj \\r
+  $O\7zEncode.obj \\r
+  $O\7zExtract.obj \\r
+  $O\7zFolderInStream.obj \\r
+  $O\7zFolderOutStream.obj \\r
+  $O\7zHandler.obj \\r
+  $O\7zHandlerOut.obj \\r
+  $O\7zHeader.obj \\r
+  $O\7zIn.obj \\r
+  $O\7zOut.obj \\r
+  $O\7zProperties.obj \\r
+  $O\7zSpecStream.obj \\r
+  $O\7zUpdate.obj \\r
+  $O\7zRegister.obj \\r
+\r
+COMMON_OBJS = \\r
+  $O\CRC.obj \\r
+  $O\IntToString.obj \\r
+  $O\NewHandler.obj \\r
+  $O\MyString.obj \\r
+  $O\StringConvert.obj \\r
+  $O\StringToInt.obj \\r
+  $O\MyVector.obj \\r
+\r
+WIN_OBJS = \\r
+  $O\DLL.obj \\r
+  $O\FileDir.obj \\r
+  $O\FileFind.obj \\r
+  $O\FileIO.obj \\r
+  $O\PropVariant.obj \\r
+  $O\Synchronization.obj \\r
+  $O\System.obj \\r
+\r
+7ZIP_COMMON_OBJS = \\r
+  $O\CreateCoder.obj \\r
+  $O\InOutTempBuffer.obj \\r
+  $O\FilterCoder.obj \\r
+  $O\LimitedStreams.obj \\r
+  $O\LockedStream.obj \\r
+  $O\MethodId.obj \\r
+  $O\MethodProps.obj \\r
+  $O\OutBuffer.obj \\r
+  $O\ProgressUtils.obj \\r
+  $O\StreamBinder.obj \\r
+  $O\StreamObjects.obj \\r
+  $O\StreamUtils.obj \\r
+  $O\VirtThread.obj \\r
+\r
+AR_COMMON_OBJS = \\r
+  $O\CoderMixer2.obj \\r
+  $O\CoderMixer2MT.obj \\r
+  $O\CrossThreadProgress.obj \\r
+  $O\HandlerOut.obj \\r
+  $O\InStreamWithCRC.obj \\r
+  $O\ItemNameUtils.obj \\r
+  $O\MultiStream.obj \\r
+  $O\OutStreamWithCRC.obj \\r
+  $O\ParseProperties.obj \\r
+\r
+C_OBJS = \\r
+  $O\Alloc.obj \\r
+  $O\CpuArch.obj \\r
+  $O\Threads.obj \\r
+\r
+!include "../../Crc.mak"\r
+\r
+OBJS = \\r
+  $O\StdAfx.obj \\r
+  $(AR_OBJS) \\r
+  $(7Z_OBJS) \\r
+  $(COMMON_OBJS) \\r
+  $(WIN_OBJS) \\r
+  $(7ZIP_COMMON_OBJS) \\r
+  $(AR_COMMON_OBJS) \\r
+  $O\CopyCoder.obj \\r
+  $(C_OBJS) \\r
+  $(ASM_OBJS) \\r
+  $O\resource.res\r
+\r
+!include "../../../Build.mak"\r
+\r
+$(AR_OBJS): ../$(*B).cpp\r
+       $(COMPL)\r
+$(7Z_OBJS): $(*B).cpp\r
+       $(COMPL)\r
+$(COMMON_OBJS): ../../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_OBJS): ../../../Windows/$(*B).cpp\r
+       $(COMPL)\r
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_COMMON_OBJS): ../Common/$(*B).cpp\r
+       $(COMPL)\r
+$O\CopyCoder.obj: ../../Compress/$(*B).cpp\r
+       $(COMPL)\r
+$(C_OBJS): ../../../../C/$(*B).c\r
+       $(COMPL_O2)\r
+\r
+!include "../../Asm.mak"\r
diff --git a/CPP/7zip/Archive/7z/resource.rc b/CPP/7zip/Archive/7z/resource.rc
new file mode 100755 (executable)
index 0000000..3958af8
--- /dev/null
@@ -0,0 +1,11 @@
+#include "../../MyVersionInfo.rc"\r
+\r
+MY_VERSION_INFO_DLL("7z Plugin", "7z")\r
+\r
+0 ICON  "../Icons/7z.ico"\r
+\r
+STRINGTABLE\r
+BEGIN\r
+  100 "7z:0"\r
+END\r
+\r
diff --git a/CPP/7zip/Archive/ApmHandler.cpp b/CPP/7zip/Archive/ApmHandler.cpp
new file mode 100755 (executable)
index 0000000..666f3a4
--- /dev/null
@@ -0,0 +1,356 @@
+// ApmHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/IntToString.h"\r
+#include "Common/MyString.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../Common/LimitedStreams.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/CopyCoder.h"\r
+\r
+#define Get16(p) GetBe16(p)\r
+#define Get32(p) GetBe32(p)\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace NApm {\r
+\r
+struct CItem\r
+{\r
+  UInt32 StartBlock;\r
+  UInt32 NumBlocks;\r
+  char Name[32];\r
+  char Type[32];\r
+  /*\r
+  UInt32 DataStartBlock;\r
+  UInt32 NumDataBlocks;\r
+  UInt32 Status;\r
+  UInt32 BootStartBlock;\r
+  UInt32 BootSize;\r
+  UInt32 BootAddr;\r
+  UInt32 BootEntry;\r
+  UInt32 BootChecksum;\r
+  char Processor[16];\r
+  */\r
+\r
+  bool Parse(const Byte *p, UInt32 &numBlocksInMap)\r
+  {\r
+    if (p[0] != 0x50 || p[1] != 0x4D || p[2] != 0 || p[3] != 0)\r
+      return false;\r
+    numBlocksInMap = Get32(p + 4);\r
+    StartBlock = Get32(p + 8);\r
+    NumBlocks = Get32(p + 0xC);\r
+    memcpy(Name, p + 0x10, 32);\r
+    memcpy(Type, p + 0x30, 32);\r
+    /*\r
+    DataStartBlock = Get32(p + 0x50);\r
+    NumDataBlocks = Get32(p + 0x54);\r
+    Status = Get32(p + 0x58);\r
+    BootStartBlock = Get32(p + 0x5C);\r
+    BootSize = Get32(p + 0x60);\r
+    BootAddr = Get32(p + 0x64);\r
+    if (Get32(p + 0x68) != 0)\r
+      return false;\r
+    BootEntry = Get32(p + 0x6C);\r
+    if (Get32(p + 0x70) != 0)\r
+      return false;\r
+    BootChecksum = Get32(p + 0x74);\r
+    memcpy(Processor, p + 0x78, 16);\r
+    */\r
+    return true;\r
+  }\r
+};\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IInArchiveGetStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<IInStream> _stream;\r
+  CRecordVector<CItem> _items;\r
+\r
+  int _blockSizeLog;\r
+  UInt32 _numBlocks;\r
+\r
+  HRESULT ReadTables(IInStream *stream);\r
+  UInt64 BlocksToBytes(UInt32 i) const { return (UInt64)i << _blockSizeLog; }\r
+  UInt64 GetItemSize(const CItem &item) { return BlocksToBytes(item.NumBlocks); }\r
+public:\r
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);\r
+};\r
+\r
+static inline int GetLog(UInt32 num)\r
+{\r
+  for (int i = 0; i < 31; i++)\r
+    if (((UInt32)1 << i) == num)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+HRESULT CHandler::ReadTables(IInStream *stream)\r
+{\r
+  const UInt32 kSectorSize = 512;\r
+  Byte buf[kSectorSize];\r
+  {\r
+    RINOK(ReadStream_FALSE(stream, buf, kSectorSize));\r
+    if (buf[0] != 0x45 || buf[1] != 0x52)\r
+      return S_FALSE;\r
+    _blockSizeLog = GetLog(Get16(buf + 2));\r
+    if (_blockSizeLog < 9 || _blockSizeLog > 14)\r
+      return S_FALSE;\r
+    _numBlocks = Get32(buf + 4);\r
+    for (int i = 8; i < 16; i++)\r
+      if (buf[i] != 0)\r
+        return S_FALSE;\r
+  }\r
+\r
+  unsigned numSkips = (unsigned)1 << (_blockSizeLog - 9);\r
+  for (unsigned j = 1; j < numSkips; j++)\r
+  {\r
+    RINOK(ReadStream_FALSE(stream, buf, kSectorSize));\r
+  }\r
+\r
+  UInt32 numBlocksInMap = 0;\r
+  for (unsigned i = 0;;)\r
+  {\r
+    RINOK(ReadStream_FALSE(stream, buf, kSectorSize));\r
\r
+    CItem item;\r
+    \r
+    UInt32 numBlocksInMap2;\r
+    if (!item.Parse(buf, numBlocksInMap2))\r
+      return S_FALSE;\r
+    if (i == 0)\r
+    {\r
+      numBlocksInMap = numBlocksInMap2;\r
+      if (numBlocksInMap > (1 << 8))\r
+        return S_FALSE;\r
+    }\r
+    else if (numBlocksInMap2 != numBlocksInMap)\r
+      return S_FALSE;\r
+\r
+    UInt32 finish = item.StartBlock + item.NumBlocks;\r
+    if (finish < item.StartBlock)\r
+      return S_FALSE;\r
+    _numBlocks = MyMax(_numBlocks, finish);\r
+    \r
+    _items.Add(item);\r
+    for (unsigned j = 1; j < numSkips; j++)\r
+    {\r
+      RINOK(ReadStream_FALSE(stream, buf, kSectorSize));\r
+    }\r
+    if (++i == numBlocksInMap)\r
+      break;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream,\r
+    const UInt64 * /* maxCheckStartPosition */,\r
+    IArchiveOpenCallback * /* openArchiveCallback */)\r
+{\r
+  COM_TRY_BEGIN\r
+  Close();\r
+  RINOK(ReadTables(stream));\r
+  _stream = stream;\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _items.Clear();\r
+  _stream.Release();\r
+  return S_OK;\r
+}\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidOffset, VT_UI8}\r
+};\r
+\r
+STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidClusterSize, VT_UI4},\r
+  { NULL, kpidPhySize, VT_UI8}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+static AString GetString(const char *s)\r
+{\r
+  AString res;\r
+  for (int i = 0; i < 32 && s[i] != 0; i++)\r
+    res += s[i];\r
+  return res;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidMainSubfile:\r
+    {\r
+      int mainIndex = -1;\r
+      for (int i = 0; i < _items.Size(); i++)\r
+      {\r
+        AString s = GetString(_items[i].Type);\r
+        if (s != "Apple_Free" &&\r
+            s != "Apple_partition_map")\r
+        {\r
+          if (mainIndex >= 0)\r
+          {\r
+            mainIndex = -1;\r
+            break;\r
+          }\r
+          mainIndex = i;\r
+        }\r
+      }\r
+      if (mainIndex >= 0)\r
+        prop = (UInt32)mainIndex;\r
+      break;\r
+    }\r
+    case kpidClusterSize: prop = (UInt32)1 << _blockSizeLog; break;\r
+    case kpidPhySize: prop = BlocksToBytes(_numBlocks); break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _items.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NCOM::CPropVariant prop;\r
+  const CItem &item = _items[index];\r
+  switch(propID)\r
+  {\r
+    case kpidPath:\r
+    {\r
+      AString s = GetString(item.Name);\r
+      if (s.IsEmpty())\r
+      {\r
+        char s2[32];\r
+        ConvertUInt32ToString(index, s2);\r
+        s = s2;\r
+      }\r
+      AString type = GetString(item.Type);\r
+      if (type == "Apple_HFS")\r
+        type = "hfs";\r
+      if (!type.IsEmpty())\r
+      {\r
+        s += '.';\r
+        s += type;\r
+      }\r
+      prop = s;\r
+      break;\r
+    }\r
+    case kpidSize:\r
+    case kpidPackSize:\r
+      prop = GetItemSize(item);\r
+      break;\r
+    case kpidOffset: prop = BlocksToBytes(item.StartBlock); break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _items.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt64 totalSize = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+    totalSize += GetItemSize(_items[allFilesMode ? i : indices[i]]);\r
+  extractCallback->SetTotal(totalSize);\r
+\r
+  totalSize = 0;\r
+  \r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);\r
+  streamSpec->SetStream(_stream);\r
+\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    lps->InSize = totalSize;\r
+    lps->OutSize = totalSize;\r
+    RINOK(lps->SetCur());\r
+    CMyComPtr<ISequentialOutStream> outStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    Int32 index = allFilesMode ? i : indices[i];\r
+    const CItem &item = _items[index];\r
+\r
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));\r
+    UInt64 size = GetItemSize(item);\r
+    totalSize += size;\r
+    if (!testMode && !outStream)\r
+      continue;\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+\r
+    RINOK(_stream->Seek(BlocksToBytes(item.StartBlock), STREAM_SEEK_SET, NULL));\r
+    streamSpec->Init(size);\r
+    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));\r
+    outStream.Release();\r
+    RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == size ?\r
+        NExtract::NOperationResult::kOK:\r
+        NExtract::NOperationResult::kDataError));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)\r
+{\r
+  COM_TRY_BEGIN\r
+  const CItem &item = _items[index];\r
+  return CreateLimitedInStream(_stream, BlocksToBytes(item.StartBlock), GetItemSize(item), stream);\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"APM", L"", 0, 0xD4, { 0x50, 0x4D, 0, 0, 0, 0, 0 }, 7, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Apm)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Archive.def b/CPP/7zip/Archive/Archive.def
new file mode 100755 (executable)
index 0000000..839245e
--- /dev/null
@@ -0,0 +1,6 @@
+EXPORTS\r
+  CreateObject PRIVATE\r
+  GetHandlerProperty PRIVATE\r
+  GetNumberOfFormats PRIVATE\r
+  GetHandlerProperty2 PRIVATE\r
+  CreateObject PRIVATE\r
diff --git a/CPP/7zip/Archive/Archive2.def b/CPP/7zip/Archive/Archive2.def
new file mode 100755 (executable)
index 0000000..190fbd8
--- /dev/null
@@ -0,0 +1,9 @@
+EXPORTS\r
+  CreateObject PRIVATE\r
+  GetHandlerProperty PRIVATE\r
+  GetNumberOfFormats PRIVATE\r
+  GetHandlerProperty2 PRIVATE\r
+  CreateObject PRIVATE\r
+  GetNumberOfMethods PRIVATE\r
+  GetMethodProperty PRIVATE\r
+  SetLargePageMode PRIVATE\r
diff --git a/CPP/7zip/Archive/ArchiveExports.cpp b/CPP/7zip/Archive/ArchiveExports.cpp
new file mode 100755 (executable)
index 0000000..5d6cf92
--- /dev/null
@@ -0,0 +1,135 @@
+// ArchiveExports.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/ComTry.h"\r
+\r
+#include "../../Windows/PropVariant.h"\r
+\r
+#include "../Common/RegisterArc.h"\r
+\r
+static const unsigned int kNumArcsMax = 48;\r
+static unsigned int g_NumArcs = 0;\r
+static unsigned int g_DefaultArcIndex = 0;\r
+static const CArcInfo *g_Arcs[kNumArcsMax];\r
+void RegisterArc(const CArcInfo *arcInfo)\r
+{\r
+  if (g_NumArcs < kNumArcsMax)\r
+  {\r
+    const wchar_t *p = arcInfo->Name;\r
+    if (p[0] == '7' && p[1] == 'z' && p[2] == 0)\r
+      g_DefaultArcIndex = g_NumArcs;\r
+    g_Arcs[g_NumArcs++] = arcInfo;\r
+  }\r
+}\r
+\r
+DEFINE_GUID(CLSID_CArchiveHandler,\r
+0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);\r
+\r
+#define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5])\r
+\r
+static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value)\r
+{\r
+  if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)\r
+    value->vt = VT_BSTR;\r
+  return S_OK;\r
+}\r
+\r
+static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)\r
+{\r
+  return SetPropString((const char *)&guid, sizeof(GUID), value);\r
+}\r
+\r
+int FindFormatCalssId(const GUID *clsID)\r
+{\r
+  GUID cls = *clsID;\r
+  CLS_ARC_ID_ITEM(cls) = 0;\r
+  if (cls != CLSID_CArchiveHandler)\r
+    return -1;\r
+  Byte id = CLS_ARC_ID_ITEM(*clsID);\r
+  for (unsigned i = 0; i < g_NumArcs; i++)\r
+    if (g_Arcs[i]->ClassId == id)\r
+      return (int)i;\r
+  return -1;\r
+}\r
+\r
+STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject)\r
+{\r
+  COM_TRY_BEGIN\r
+  {\r
+    int needIn = (*iid == IID_IInArchive);\r
+    int needOut = (*iid == IID_IOutArchive);\r
+    if (!needIn && !needOut)\r
+      return E_NOINTERFACE;\r
+    int formatIndex = FindFormatCalssId(clsid);\r
+    if (formatIndex < 0)\r
+      return CLASS_E_CLASSNOTAVAILABLE;\r
+    \r
+    const CArcInfo &arc = *g_Arcs[formatIndex];\r
+    if (needIn)\r
+    {\r
+      *outObject = arc.CreateInArchive();\r
+      ((IInArchive *)*outObject)->AddRef();\r
+    }\r
+    else\r
+    {\r
+      if (!arc.CreateOutArchive)\r
+        return CLASS_E_CLASSNOTAVAILABLE;\r
+      *outObject = arc.CreateOutArchive();\r
+      ((IOutArchive *)*outObject)->AddRef();\r
+    }\r
+  }\r
+  COM_TRY_END\r
+  return S_OK;\r
+}\r
+\r
+STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (formatIndex >= g_NumArcs)\r
+    return E_INVALIDARG;\r
+  const CArcInfo &arc = *g_Arcs[formatIndex];\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case NArchive::kName:\r
+      prop = arc.Name;\r
+      break;\r
+    case NArchive::kClassID:\r
+    {\r
+      GUID clsId = CLSID_CArchiveHandler;\r
+      CLS_ARC_ID_ITEM(clsId) = arc.ClassId;\r
+      return SetPropGUID(clsId, value);\r
+    }\r
+    case NArchive::kExtension:\r
+      if (arc.Ext != 0)\r
+        prop = arc.Ext;\r
+      break;\r
+    case NArchive::kAddExtension:\r
+      if (arc.AddExt != 0)\r
+        prop = arc.AddExt;\r
+      break;\r
+    case NArchive::kUpdate:\r
+      prop = (bool)(arc.CreateOutArchive != 0);\r
+      break;\r
+    case NArchive::kKeepName:\r
+      prop = arc.KeepName;\r
+      break;\r
+    case NArchive::kStartSignature:\r
+      return SetPropString((const char *)arc.Signature, arc.SignatureSize, value);\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  return GetHandlerProperty2(g_DefaultArcIndex, propID, value);\r
+}\r
+\r
+STDAPI GetNumberOfFormats(UINT32 *numFormats)\r
+{\r
+  *numFormats = g_NumArcs;\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/Archive/ArjHandler.cpp b/CPP/7zip/Archive/ArjHandler.cpp
new file mode 100755 (executable)
index 0000000..813ef70
--- /dev/null
@@ -0,0 +1,798 @@
+// ArjHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../Common/LimitedStreams.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamObjects.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/ArjDecoder1.h"\r
+#include "../Compress/ArjDecoder2.h"\r
+#include "../Compress/CopyCoder.h"\r
+\r
+#include "Common/ItemNameUtils.h"\r
+#include "Common/OutStreamWithCRC.h"\r
+\r
+using namespace NWindows;\r
+\r
+#define Get16(p) GetUi16(p)\r
+#define Get32(p) GetUi32(p)\r
+\r
+namespace NArchive {\r
+namespace NArj {\r
+\r
+const int kBlockSizeMin = 30;\r
+const int kBlockSizeMax = 2600;\r
+\r
+namespace NSignature\r
+{\r
+  const Byte kSig0 = 0x60;\r
+  const Byte kSig1 = 0xEA;\r
+}\r
+\r
+namespace NFileHeader\r
+{\r
+  namespace NCompressionMethod\r
+  {\r
+    enum\r
+    {\r
+      kStored = 0,\r
+      kCompressed1a = 1,\r
+      kCompressed1b = 2,\r
+      kCompressed1c = 3,\r
+      kCompressed2 = 4,\r
+      kNoDataNoCRC = 8,\r
+      kNoData = 9\r
+    };\r
+  }\r
+\r
+  namespace NFileType\r
+  {\r
+    enum\r
+    {\r
+      kBinary = 0,\r
+      k7BitText = 1,\r
+      kArchiveHeader = 2,\r
+      kDirectory = 3,\r
+      kVolumeLablel = 4,\r
+      kChapterLabel = 5\r
+    };\r
+  }\r
+  \r
+  namespace NFlags\r
+  {\r
+    const Byte kGarbled = 1;\r
+    const Byte kVolume = 4;\r
+    const Byte kExtFile = 8;\r
+    const Byte kPathSym = 0x10;\r
+    const Byte kBackup = 0x20;\r
+  }\r
+\r
+  namespace NHostOS\r
+  {\r
+    enum EEnum\r
+    {\r
+      kMSDOS = 0,  // filesystem used by MS-DOS, OS/2, Win32\r
+          // pkarj 2.50 (FAT / VFAT / FAT32 file systems)\r
+      kPRIMOS,\r
+      kUnix,\r
+      kAMIGA,\r
+      kMac,\r
+      kOS_2,\r
+      kAPPLE_GS,\r
+      kAtari_ST,\r
+      kNext,\r
+      kVAX_VMS,\r
+      kWIN95\r
+    };\r
+  }\r
+}\r
+\r
+struct CArchiveHeader\r
+{\r
+  // Byte ArchiverVersion;\r
+  // Byte ExtractVersion;\r
+  Byte HostOS;\r
+  // Byte Flags;\r
+  // Byte SecuryVersion;\r
+  // Byte FileType;\r
+  // Byte Reserved;\r
+  UInt32 CTime;\r
+  UInt32 MTime;\r
+  UInt32 ArchiveSize;\r
+  // UInt32 SecurityEnvelopeFilePosition;\r
+  // UInt16 FilespecPositionInFilename;\r
+  // UInt16 LengthOfSecurityEnvelopeSata;\r
+  // Byte EncryptionVersion;\r
+  // Byte LastChapter;\r
+  AString Name;\r
+  AString Comment;\r
+  \r
+  HRESULT Parse(const Byte *p, unsigned size);\r
+};\r
+\r
+static HRESULT ReadString(const Byte *p, unsigned &size, AString &res)\r
+{\r
+  AString s;\r
+  for (unsigned i = 0; i < size;)\r
+  {\r
+    char c = (char)p[i++];\r
+    if (c == 0)\r
+    {\r
+      size = i;\r
+      res = s;\r
+      return S_OK;\r
+    }\r
+    s += c;\r
+  }\r
+  return S_FALSE;\r
+}\r
+\r
+HRESULT CArchiveHeader::Parse(const Byte *p, unsigned size)\r
+{\r
+  if (size < kBlockSizeMin)\r
+    return S_FALSE;\r
+  Byte firstHeaderSize = p[0];\r
+  if (firstHeaderSize > size)\r
+    return S_FALSE;\r
+  // ArchiverVersion = p[1];\r
+  // ExtractVersion = p[2];\r
+  HostOS = p[3];\r
+  // Flags = p[4];\r
+  // SecuryVersion = p[5];\r
+  if (p[6] != NFileHeader::NFileType::kArchiveHeader)\r
+    return S_FALSE;\r
+  // Reserved = p[7];\r
+  CTime = Get32(p + 8);\r
+  MTime = Get32(p + 12);\r
+  ArchiveSize = Get32(p + 16);\r
+  // SecurityEnvelopeFilePosition = Get32(p + 20);\r
+  // UInt16 filespecPositionInFilename = Get16(p + 24);\r
+  // LengthOfSecurityEnvelopeSata = Get16(p + 26);\r
+  // EncryptionVersion = p[28];\r
+  // LastChapter = p[29];\r
+  unsigned pos = firstHeaderSize;\r
+  unsigned size1 = size - pos;\r
+  RINOK(ReadString(p + pos, size1, Name));\r
+  pos += size1;\r
+  size1 = size - pos;\r
+  RINOK(ReadString(p + pos, size1, Comment));\r
+  pos += size1;\r
+  return S_OK;\r
+}\r
+\r
+struct CItem\r
+{\r
+  AString Name;\r
+  AString Comment;\r
+\r
+  UInt32 MTime;\r
+  UInt32 PackSize;\r
+  UInt32 Size;\r
+  UInt32 FileCRC;\r
+  UInt32 SplitPos;\r
+\r
+  Byte Version;\r
+  Byte ExtractVersion;\r
+  Byte HostOS;\r
+  Byte Flags;\r
+  Byte Method;\r
+  Byte FileType;\r
+\r
+  // UInt16 FilespecPositionInFilename;\r
+  UInt16 FileAccessMode;\r
+  // Byte FirstChapter;\r
+  // Byte LastChapter;\r
+  \r
+  UInt64 DataPosition;\r
+  \r
+  bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kGarbled) != 0; }\r
+  bool IsDir() const { return (FileType == NFileHeader::NFileType::kDirectory); }\r
+  bool IsSplitAfter() const { return (Flags & NFileHeader::NFlags::kVolume) != 0; }\r
+  bool IsSplitBefore() const { return (Flags & NFileHeader::NFlags::kExtFile) != 0; }\r
+  UInt32 GetWinAttributes() const\r
+  {\r
+    UInt32 winAtrributes;\r
+    switch(HostOS)\r
+    {\r
+      case NFileHeader::NHostOS::kMSDOS:\r
+      case NFileHeader::NHostOS::kWIN95:\r
+        winAtrributes = FileAccessMode;\r
+        break;\r
+      default:\r
+        winAtrributes = 0;\r
+    }\r
+    if (IsDir())\r
+      winAtrributes |= FILE_ATTRIBUTE_DIRECTORY;\r
+    return winAtrributes;\r
+  }\r
+\r
+  HRESULT Parse(const Byte *p, unsigned size);\r
+};\r
+\r
+HRESULT CItem::Parse(const Byte *p, unsigned size)\r
+{\r
+  if (size < kBlockSizeMin)\r
+    return S_FALSE;\r
+\r
+  Byte firstHeaderSize = p[0];\r
+\r
+  Version = p[1];\r
+  ExtractVersion = p[2];\r
+  HostOS = p[3];\r
+  Flags = p[4];\r
+  Method = p[5];\r
+  FileType = p[6];\r
+  // Reserved = p[7];\r
+  MTime = Get32(p + 8);\r
+  PackSize = Get32(p + 12);\r
+  Size = Get32(p + 16);\r
+  FileCRC = Get32(p + 20);\r
+  // FilespecPositionInFilename = Get16(p + 24);\r
+  FileAccessMode = Get16(p + 26);\r
+  // FirstChapter = p[28];\r
+  // FirstChapter = p[29];\r
+\r
+  SplitPos = 0;\r
+  if (IsSplitBefore() && firstHeaderSize >= 34)\r
+    SplitPos = Get32(p + 30);\r
+\r
+  unsigned pos = firstHeaderSize;\r
+  unsigned size1 = size - pos;\r
+  RINOK(ReadString(p + pos, size1, Name));\r
+  pos += size1;\r
+  size1 = size - pos;\r
+  RINOK(ReadString(p + pos, size1, Comment));\r
+  pos += size1;\r
+\r
+  return S_OK;\r
+}\r
+\r
+struct CInArchiveException\r
+{\r
+  enum CCauseType\r
+  {\r
+    kUnexpectedEndOfArchive = 0,\r
+    kCRCError,\r
+    kIncorrectArchive\r
+  }\r
+  Cause;\r
+  CInArchiveException(CCauseType cause): Cause(cause) {};\r
+};\r
+\r
+class CInArchive\r
+{\r
+  UInt32 _blockSize;\r
+  Byte _block[kBlockSizeMax + 4];\r
+  \r
+  HRESULT ReadBlock(bool &filled);\r
+  HRESULT ReadSignatureAndBlock(bool &filled);\r
+  HRESULT SkipExtendedHeaders();\r
+\r
+  HRESULT SafeReadBytes(void *data, UInt32 size);\r
+    \r
+public:\r
+  CArchiveHeader Header;\r
+\r
+  IInStream *Stream;\r
+  IArchiveOpenCallback *Callback;\r
+  UInt64 NumFiles;\r
+  UInt64 NumBytes;\r
+\r
+  HRESULT Open(const UInt64 *searchHeaderSizeLimit);\r
+  HRESULT GetNextItem(bool &filled, CItem &item);\r
+};\r
+\r
+static inline bool TestMarkerCandidate(const Byte *p, unsigned maxSize)\r
+{\r
+  if (p[0] != NSignature::kSig0 || p[1] != NSignature::kSig1)\r
+    return false;\r
+  UInt32 blockSize = Get16(p + 2);\r
+  p += 4;\r
+  if (p[6] != NFileHeader::NFileType::kArchiveHeader ||\r
+      p[0] > blockSize ||\r
+      maxSize < 2 + 2 + blockSize + 4 ||\r
+      blockSize < kBlockSizeMin || blockSize > kBlockSizeMax ||\r
+      p[28] > 8) // EncryptionVersion\r
+    return false;\r
+  // return (Get32(p + blockSize) == CrcCalc(p, blockSize));\r
+  return true;\r
+}\r
+\r
+static HRESULT FindAndReadMarker(ISequentialInStream *stream, const UInt64 *searchHeaderSizeLimit, UInt64 &position)\r
+{\r
+  position = 0;\r
+\r
+  const int kMarkerSizeMin = 2 + 2 + kBlockSizeMin + 4;\r
+  const int kMarkerSizeMax = 2 + 2 + kBlockSizeMax + 4;\r
+\r
+  CByteBuffer byteBuffer;\r
+  const UInt32 kBufSize = 1 << 16;\r
+  byteBuffer.SetCapacity(kBufSize);\r
+  Byte *buf = byteBuffer;\r
+\r
+  size_t processedSize = kMarkerSizeMax;\r
+  RINOK(ReadStream(stream, buf, &processedSize));\r
+  if (processedSize < kMarkerSizeMin)\r
+    return S_FALSE;\r
+  if (TestMarkerCandidate(buf, (unsigned)processedSize))\r
+    return S_OK;\r
+\r
+  UInt32 numBytesPrev = (UInt32)processedSize - 1;\r
+  memmove(buf, buf + 1, numBytesPrev);\r
+  UInt64 curTestPos = 1;\r
+  for (;;)\r
+  {\r
+    if (searchHeaderSizeLimit != NULL)\r
+      if (curTestPos > *searchHeaderSizeLimit)\r
+        return S_FALSE;\r
+    processedSize = kBufSize - numBytesPrev;\r
+    RINOK(ReadStream(stream, buf + numBytesPrev, &processedSize));\r
+    UInt32 numBytesInBuffer = numBytesPrev + (UInt32)processedSize;\r
+    if (numBytesInBuffer < kMarkerSizeMin)\r
+      return S_FALSE;\r
+    UInt32 numTests = numBytesInBuffer - kMarkerSizeMin + 1;\r
+    UInt32 pos;\r
+    for (pos = 0; pos < numTests; pos++)\r
+    {\r
+      for (; buf[pos] != NSignature::kSig0 && pos < numTests; pos++);\r
+      if (pos == numTests)\r
+        break;\r
+      if (TestMarkerCandidate(buf + pos, numBytesInBuffer - pos))\r
+      {\r
+        position = curTestPos + pos;\r
+        return S_OK;\r
+      }\r
+    }\r
+    curTestPos += pos;\r
+    numBytesPrev = numBytesInBuffer - numTests;\r
+    memmove(buf, buf + numTests, numBytesPrev);\r
+  }\r
+}\r
+\r
+HRESULT CInArchive::SafeReadBytes(void *data, UInt32 size)\r
+{\r
+  size_t processed = size;\r
+  RINOK(ReadStream(Stream, data, &processed));\r
+  if (processed != size)\r
+    throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::ReadBlock(bool &filled)\r
+{\r
+  filled = false;\r
+  Byte buf[2];\r
+  RINOK(SafeReadBytes(buf, 2));\r
+  _blockSize = Get16(buf);\r
+  if (_blockSize == 0)\r
+    return S_OK;\r
+  if (_blockSize > kBlockSizeMax)\r
+    throw CInArchiveException(CInArchiveException::kIncorrectArchive);\r
+  RINOK(SafeReadBytes(_block, _blockSize + 4));\r
+  NumBytes += _blockSize + 6;\r
+  if (Get32(_block + _blockSize) != CrcCalc(_block, _blockSize))\r
+    throw CInArchiveException(CInArchiveException::kCRCError);\r
+  filled = true;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::ReadSignatureAndBlock(bool &filled)\r
+{\r
+  Byte id[2];\r
+  RINOK(SafeReadBytes(id, 2));\r
+  if (id[0] != NSignature::kSig0 || id[1] != NSignature::kSig1)\r
+    throw CInArchiveException(CInArchiveException::kIncorrectArchive);\r
+  return ReadBlock(filled);\r
+}\r
+\r
+HRESULT CInArchive::SkipExtendedHeaders()\r
+{\r
+  for (UInt32 i = 0;; i++)\r
+  {\r
+    bool filled;\r
+    RINOK(ReadBlock(filled));\r
+    if (!filled)\r
+      return S_OK;\r
+    if (Callback && (i & 0xFF) == 0)\r
+      RINOK(Callback->SetCompleted(&NumFiles, &NumBytes));\r
+  }\r
+}\r
+\r
+HRESULT CInArchive::Open(const UInt64 *searchHeaderSizeLimit)\r
+{\r
+  UInt64 position = 0;\r
+  RINOK(FindAndReadMarker(Stream, searchHeaderSizeLimit, position));\r
+  RINOK(Stream->Seek(position, STREAM_SEEK_SET, NULL));\r
+  bool filled;\r
+  RINOK(ReadSignatureAndBlock(filled));\r
+  if (!filled)\r
+    return S_FALSE;\r
+  RINOK(Header.Parse(_block, _blockSize));\r
+  return SkipExtendedHeaders();\r
+}\r
+\r
+HRESULT CInArchive::GetNextItem(bool &filled, CItem &item)\r
+{\r
+  RINOK(ReadSignatureAndBlock(filled));\r
+  if (!filled)\r
+    return S_OK;\r
+  filled = false;\r
+  RINOK(item.Parse(_block, _blockSize));\r
+  /*\r
+  UInt32 extraData;\r
+  if ((header.Flags & NFileHeader::NFlags::kExtFile) != 0)\r
+    extraData = GetUi32(_block + pos);\r
+  */\r
+\r
+  RINOK(SkipExtendedHeaders());\r
+  filled = true;\r
+  return S_OK;\r
+}\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP1(IInArchive)\r
+\r
+  INTERFACE_IInArchive(;)\r
+\r
+  HRESULT Open2(IInStream *inStream, const UInt64 *maxCheckStartPosition,\r
+      IArchiveOpenCallback *callback);\r
+private:\r
+  CInArchive _archive;\r
+  CObjectVector<CItem> _items;\r
+  CMyComPtr<IInStream> _stream;\r
+};\r
+\r
+const wchar_t *kHostOS[] =\r
+{\r
+  L"MSDOS",\r
+  L"PRIMOS",\r
+  L"UNIX",\r
+  L"AMIGA",\r
+  L"MAC",\r
+  L"OS/2",\r
+  L"APPLE GS",\r
+  L"ATARI ST",\r
+  L"NEXT",\r
+  L"VAX VMS",\r
+  L"WIN95"\r
+};\r
+\r
+const wchar_t *kUnknownOS = L"Unknown";\r
+\r
+const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]);\r
+\r
+STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidName, VT_BSTR},\r
+  { NULL, kpidCTime, VT_BSTR},\r
+  { NULL, kpidMTime, VT_BSTR},\r
+  { NULL, kpidHostOS, VT_BSTR},\r
+  { NULL, kpidComment, VT_BSTR}\r
+};\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidIsDir, VT_BOOL},\r
+  { NULL, kpidSize, VT_UI4},\r
+  { NULL, kpidPosition, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI4},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidAttrib, VT_UI4},\r
+  { NULL, kpidEncrypted, VT_BOOL},\r
+  { NULL, kpidCRC, VT_UI4},\r
+  { NULL, kpidMethod, VT_UI1},\r
+  { NULL, kpidHostOS, VT_BSTR},\r
+  { NULL, kpidComment, VT_BSTR}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+static void SetTime(UInt32 dosTime, NWindows::NCOM::CPropVariant &prop)\r
+{\r
+  if (dosTime == 0)\r
+    return;\r
+  FILETIME localFileTime, utc;\r
+  if (NTime::DosTimeToFileTime(dosTime, localFileTime))\r
+  {\r
+    if (!LocalFileTimeToFileTime(&localFileTime, &utc))\r
+      utc.dwHighDateTime = utc.dwLowDateTime = 0;\r
+  }\r
+  else\r
+    utc.dwHighDateTime = utc.dwLowDateTime = 0;\r
+  prop = utc;\r
+}\r
+\r
+static void SetHostOS(Byte hostOS, NWindows::NCOM::CPropVariant &prop)\r
+{\r
+  prop = hostOS < kNumHostOSes ? kHostOS[hostOS] : kUnknownOS;\r
+}\r
+\r
+static void SetUnicodeString(const AString &s, NWindows::NCOM::CPropVariant &prop)\r
+{\r
+  if (!s.IsEmpty())\r
+    prop = MultiByteToUnicodeString(s, CP_OEMCP);\r
+}\r
\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidName:  SetUnicodeString(_archive.Header.Name, prop); break;\r
+    case kpidCTime:  SetTime(_archive.Header.CTime, prop); break;\r
+    case kpidMTime:  SetTime(_archive.Header.MTime, prop); break;\r
+    case kpidHostOS:  SetHostOS(_archive.Header.HostOS, prop); break;\r
+    case kpidComment:  SetUnicodeString(_archive.Header.Comment, prop); break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _items.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  const CItem &item = _items[index];\r
+  switch(propID)\r
+  {\r
+    case kpidPath:  prop = NItemName::GetOSName(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break;\r
+    case kpidIsDir:  prop = item.IsDir(); break;\r
+    case kpidSize:  prop = item.Size; break;\r
+    case kpidPackSize:  prop = item.PackSize; break;\r
+    case kpidPosition:  if (item.IsSplitBefore() || item.IsSplitAfter()) prop = (UInt64)item.SplitPos; break;\r
+    case kpidAttrib:  prop = item.GetWinAttributes(); break;\r
+    case kpidEncrypted:  prop = item.IsEncrypted(); break;\r
+    case kpidCRC:  prop = item.FileCRC; break;\r
+    case kpidMethod:  prop = item.Method; break;\r
+    case kpidHostOS:  SetHostOS(item.HostOS, prop); break;\r
+    case kpidMTime:  SetTime(item.MTime, prop); break;\r
+    case kpidComment:  SetUnicodeString(item.Comment, prop); break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+HRESULT CHandler::Open2(IInStream *inStream, const UInt64 *maxCheckStartPosition,\r
+      IArchiveOpenCallback *callback)\r
+{\r
+  Close();\r
+  \r
+  UInt64 endPos = 0;\r
+  if (callback != NULL)\r
+  {\r
+    RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos));\r
+    RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));\r
+  }\r
+  \r
+  _archive.Stream = inStream;\r
+  _archive.Callback = callback;\r
+  _archive.NumFiles = _archive.NumBytes = 0;\r
+\r
+  RINOK(_archive.Open(maxCheckStartPosition));\r
+  if (callback != NULL)\r
+    RINOK(callback->SetTotal(NULL, &endPos));\r
+  for (;;)\r
+  {\r
+    CItem item;\r
+    bool filled;\r
+\r
+\r
+    RINOK(_archive.GetNextItem(filled, item));\r
+    \r
+    RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &item.DataPosition));\r
+    \r
+    if (!filled)\r
+      break;\r
+    _items.Add(item);\r
+    \r
+    if (inStream->Seek(item.PackSize, STREAM_SEEK_CUR, NULL) != S_OK)\r
+      throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);\r
+\r
+    _archive.NumFiles = _items.Size();\r
+    _archive.NumBytes = item.DataPosition;\r
+    \r
+    if (callback != NULL && _items.Size() % 100 == 0)\r
+    {\r
+      RINOK(callback->SetCompleted(&_archive.NumFiles, &_archive.NumBytes));\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *inStream,\r
+    const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback)\r
+{\r
+  COM_TRY_BEGIN\r
+  HRESULT res;\r
+  try\r
+  {\r
+    res = Open2(inStream, maxCheckStartPosition, callback);\r
+    if (res == S_OK)\r
+    {\r
+      _stream = inStream;\r
+      return S_OK;\r
+    }\r
+  }\r
+  catch(const CInArchiveException &) { res = S_FALSE; }\r
+  Close();\r
+  return res;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _items.Clear();\r
+  _stream.Release();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  UInt64 totalUnpacked = 0, totalPacked = 0;\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _items.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    const CItem &item = _items[allFilesMode ? i : indices[i]];\r
+    totalUnpacked += item.Size;\r
+    totalPacked += item.PackSize;\r
+  }\r
+  extractCallback->SetTotal(totalUnpacked);\r
+\r
+  totalUnpacked = totalPacked = 0;\r
+  UInt64 curUnpacked, curPacked;\r
+  \r
+  CMyComPtr<ICompressCoder> arj1Decoder;\r
+  CMyComPtr<ICompressCoder> arj2Decoder;\r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  CLimitedSequentialInStream *inStreamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> inStream(inStreamSpec);\r
+  inStreamSpec->SetStream(_stream);\r
+\r
+  for (i = 0; i < numItems; i++, totalUnpacked += curUnpacked, totalPacked += curPacked)\r
+  {\r
+    lps->InSize = totalPacked;\r
+    lps->OutSize = totalUnpacked;\r
+    RINOK(lps->SetCur());\r
+\r
+    curUnpacked = curPacked = 0;\r
+\r
+    CMyComPtr<ISequentialOutStream> realOutStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    Int32 index = allFilesMode ? i : indices[i];\r
+    const CItem &item = _items[index];\r
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+\r
+    if (item.IsDir())\r
+    {\r
+      // if (!testMode)\r
+      {\r
+        RINOK(extractCallback->PrepareOperation(askMode));\r
+        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+      }\r
+      continue;\r
+    }\r
+\r
+    if (!testMode && !realOutStream)\r
+      continue;\r
+\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+    curUnpacked = item.Size;\r
+    curPacked = item.PackSize;\r
+\r
+    {\r
+      COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;\r
+      CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\r
+      outStreamSpec->SetStream(realOutStream);\r
+      realOutStream.Release();\r
+      outStreamSpec->Init();\r
+  \r
+      inStreamSpec->Init(item.PackSize);\r
+      \r
+      UInt64 pos;\r
+      _stream->Seek(item.DataPosition, STREAM_SEEK_SET, &pos);\r
+\r
+      HRESULT result = S_OK;\r
+      Int32 opRes = NExtract::NOperationResult::kOK;\r
+\r
+      if (item.IsEncrypted())\r
+        opRes = NExtract::NOperationResult::kUnSupportedMethod;\r
+      else\r
+      {\r
+        switch(item.Method)\r
+        {\r
+          case NFileHeader::NCompressionMethod::kStored:\r
+          {\r
+            result = copyCoder->Code(inStream, outStream, NULL, NULL, progress);\r
+            if (result == S_OK && copyCoderSpec->TotalSize != item.PackSize)\r
+              result = S_FALSE;\r
+            break;\r
+          }\r
+          case NFileHeader::NCompressionMethod::kCompressed1a:\r
+          case NFileHeader::NCompressionMethod::kCompressed1b:\r
+          case NFileHeader::NCompressionMethod::kCompressed1c:\r
+          {\r
+            if (!arj1Decoder)\r
+              arj1Decoder = new NCompress::NArj::NDecoder1::CCoder;\r
+            result = arj1Decoder->Code(inStream, outStream, NULL, &curUnpacked, progress);\r
+            break;\r
+          }\r
+          case NFileHeader::NCompressionMethod::kCompressed2:\r
+          {\r
+            if (!arj2Decoder)\r
+              arj2Decoder = new NCompress::NArj::NDecoder2::CCoder;\r
+            result = arj2Decoder->Code(inStream, outStream, NULL, &curUnpacked, progress);\r
+            break;\r
+          }\r
+          default:\r
+            opRes = NExtract::NOperationResult::kUnSupportedMethod;\r
+        }\r
+      }\r
+      if (opRes == NExtract::NOperationResult::kOK)\r
+      {\r
+        if (result == S_FALSE)\r
+          opRes = NExtract::NOperationResult::kDataError;\r
+        else\r
+        {\r
+          RINOK(result);\r
+          opRes = (outStreamSpec->GetCRC() == item.FileCRC) ?\r
+              NExtract::NOperationResult::kOK:\r
+              NExtract::NOperationResult::kCRCError;\r
+        }\r
+      }\r
+      outStream.Release();\r
+      RINOK(extractCallback->SetOperationResult(opRes));\r
+    }\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"Arj", L"arj", 0, 4, { 0x60, 0xEA }, 2, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Arj)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Bz2Handler.cpp b/CPP/7zip/Archive/Bz2Handler.cpp
new file mode 100755 (executable)
index 0000000..39cd3b3
--- /dev/null
@@ -0,0 +1,423 @@
+// Bz2Handler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#ifndef _7ZIP_ST\r
+#include "../../Windows/System.h"\r
+#endif\r
+\r
+#include "../Common/CreateCoder.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/BZip2Decoder.h"\r
+#include "../Compress/BZip2Encoder.h"\r
+#include "../Compress/CopyCoder.h"\r
+\r
+#include "Common/DummyOutStream.h"\r
+#include "Common/ParseProperties.h"\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace NBz2 {\r
+\r
+static const UInt32 kNumPassesX1 = 1;\r
+static const UInt32 kNumPassesX7 = 2;\r
+static const UInt32 kNumPassesX9 = 7;\r
+\r
+static const UInt32 kDicSizeX1 = 100000;\r
+static const UInt32 kDicSizeX3 = 500000;\r
+static const UInt32 kDicSizeX5 = 900000;\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IArchiveOpenSeq,\r
+  public IOutArchive,\r
+  public ISetProperties,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<IInStream> _stream;\r
+  CMyComPtr<ISequentialInStream> _seqStream;\r
+  UInt64 _packSize;\r
+  UInt64 _startPosition;\r
+  bool _packSizeDefined;\r
+\r
+  UInt32 _level;\r
+  UInt32 _dicSize;\r
+  UInt32 _numPasses;\r
+  #ifndef _7ZIP_ST\r
+  UInt32 _numThreads;\r
+  #endif\r
+\r
+  void InitMethodProperties()\r
+  {\r
+    _level = 5;\r
+    _dicSize =\r
+    _numPasses = 0xFFFFFFFF;\r
+    #ifndef _7ZIP_ST\r
+    _numThreads = NWindows::NSystem::GetNumberOfProcessors();;\r
+    #endif\r
+  }\r
+\r
+public:\r
+  MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties)\r
+\r
+  INTERFACE_IInArchive(;)\r
+  INTERFACE_IOutArchive(;)\r
+  STDMETHOD(OpenSeq)(ISequentialInStream *stream);\r
+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);\r
+\r
+  CHandler() { InitMethodProperties(); }\r
+};\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPackSize, VT_UI8}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps_NO_Table\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = 1;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID,  PROPVARIANT *value)\r
+{\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream,\r
+    const UInt64 * /* maxCheckStartPosition */,\r
+    IArchiveOpenCallback * /* openArchiveCallback */)\r
+{\r
+  COM_TRY_BEGIN\r
+  try\r
+  {\r
+    Close();\r
+    RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_startPosition));\r
+    const int kSignatureSize = 3;\r
+    Byte buf[kSignatureSize];\r
+    RINOK(ReadStream_FALSE(stream, buf, kSignatureSize));\r
+    if (buf[0] != 'B' || buf[1] != 'Z' || buf[2] != 'h')\r
+      return S_FALSE;\r
+\r
+    UInt64 endPosition;\r
+    RINOK(stream->Seek(0, STREAM_SEEK_END, &endPosition));\r
+    _packSize = endPosition - _startPosition;\r
+    _packSizeDefined = true;\r
+    _stream = stream;\r
+    _seqStream = stream;\r
+  }\r
+  catch(...) { return S_FALSE; }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)\r
+{\r
+  Close();\r
+  _seqStream = stream;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _packSizeDefined = false;\r
+  _seqStream.Release();\r
+  _stream.Release();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))\r
+    return E_INVALIDARG;\r
+\r
+  if (_stream)\r
+    extractCallback->SetTotal(_packSize);\r
+  UInt64 currentTotalPacked = 0;\r
+  RINOK(extractCallback->SetCompleted(&currentTotalPacked));\r
+  CMyComPtr<ISequentialOutStream> realOutStream;\r
+  Int32 askMode = testMode ?\r
+      NExtract::NAskMode::kTest :\r
+      NExtract::NAskMode::kExtract;\r
+  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));\r
+  if (!testMode && !realOutStream)\r
+    return S_OK;\r
+\r
+  extractCallback->PrepareOperation(askMode);\r
+\r
+  NCompress::NBZip2::CDecoder *decoderSpec = new NCompress::NBZip2::CDecoder;\r
+  CMyComPtr<ICompressCoder> decoder = decoderSpec;\r
+\r
+  if (_stream)\r
+  {\r
+    RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));\r
+  }\r
+\r
+  decoderSpec->SetInStream(_seqStream);\r
+\r
+  #ifndef _7ZIP_ST\r
+  RINOK(decoderSpec->SetNumberOfThreads(_numThreads));\r
+  #endif\r
+\r
+  CDummyOutStream *outStreamSpec = new CDummyOutStream;\r
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\r
+  outStreamSpec->SetStream(realOutStream);\r
+  outStreamSpec->Init();\r
+  \r
+  realOutStream.Release();\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, true);\r
+\r
+  HRESULT result = S_OK;\r
+\r
+  bool firstItem = true;\r
+  for (;;)\r
+  {\r
+    lps->InSize = currentTotalPacked;\r
+    lps->OutSize = outStreamSpec->GetSize();\r
+\r
+    RINOK(lps->SetCur());\r
+\r
+    bool isBz2;\r
+    result = decoderSpec->CodeResume(outStream, isBz2, progress);\r
+\r
+    if (result != S_OK)\r
+      break;\r
+    if (!isBz2)\r
+    {\r
+      if (firstItem)\r
+        result = S_FALSE;\r
+      break;\r
+    }\r
+    firstItem = false;\r
+\r
+    _packSize = currentTotalPacked = decoderSpec->GetInputProcessedSize();\r
+    _packSizeDefined = true;\r
+  }\r
+  decoderSpec->ReleaseInStream();\r
+  outStream.Release();\r
+\r
+  Int32 retResult;\r
+  if (result == S_OK)\r
+    retResult = NExtract::NOperationResult::kOK;\r
+  else if (result == S_FALSE)\r
+    retResult = NExtract::NOperationResult::kDataError;\r
+  else\r
+    return result;\r
+  return extractCallback->SetOperationResult(retResult);\r
+\r
+  COM_TRY_END\r
+}\r
+\r
+static HRESULT UpdateArchive(\r
+    UInt64 unpackSize,\r
+    ISequentialOutStream *outStream,\r
+    int indexInClient,\r
+    UInt32 dictionary,\r
+    UInt32 numPasses,\r
+    #ifndef _7ZIP_ST\r
+    UInt32 numThreads,\r
+    #endif\r
+    IArchiveUpdateCallback *updateCallback)\r
+{\r
+  RINOK(updateCallback->SetTotal(unpackSize));\r
+  UInt64 complexity = 0;\r
+  RINOK(updateCallback->SetCompleted(&complexity));\r
+\r
+  CMyComPtr<ISequentialInStream> fileInStream;\r
+\r
+  RINOK(updateCallback->GetStream(indexInClient, &fileInStream));\r
+\r
+  CLocalProgress *localProgressSpec = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;\r
+  localProgressSpec->Init(updateCallback, true);\r
+  \r
+  NCompress::NBZip2::CEncoder *encoderSpec = new NCompress::NBZip2::CEncoder;\r
+  CMyComPtr<ICompressCoder> encoder = encoderSpec;\r
+  {\r
+    NWindows::NCOM::CPropVariant properties[] =\r
+    {\r
+      dictionary,\r
+      numPasses\r
+      #ifndef _7ZIP_ST\r
+      , numThreads\r
+      #endif\r
+    };\r
+    PROPID propIDs[] =\r
+    {\r
+      NCoderPropID::kDictionarySize,\r
+      NCoderPropID::kNumPasses\r
+      #ifndef _7ZIP_ST\r
+      , NCoderPropID::kNumThreads\r
+      #endif\r
+    };\r
+    RINOK(encoderSpec->SetCoderProperties(propIDs, properties, sizeof(propIDs) / sizeof(propIDs[0])));\r
+  }\r
+  \r
+  RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress));\r
+  \r
+  return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);\r
+}\r
+\r
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)\r
+{\r
+  *type = NFileTimeType::kUnix;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\r
+    IArchiveUpdateCallback *updateCallback)\r
+{\r
+  if (numItems != 1)\r
+    return E_INVALIDARG;\r
+\r
+  Int32 newData, newProps;\r
+  UInt32 indexInArchive;\r
+  if (!updateCallback)\r
+    return E_FAIL;\r
+  RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));\r
\r
+  if (IntToBool(newProps))\r
+  {\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));\r
+      if (prop.vt == VT_BOOL)\r
+      {\r
+        if (prop.boolVal != VARIANT_FALSE)\r
+          return E_INVALIDARG;\r
+      }\r
+      else if (prop.vt != VT_EMPTY)\r
+        return E_INVALIDARG;\r
+    }\r
+  }\r
+  \r
+  if (IntToBool(newData))\r
+  {\r
+    UInt64 size;\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      RINOK(updateCallback->GetProperty(0, kpidSize, &prop));\r
+      if (prop.vt != VT_UI8)\r
+        return E_INVALIDARG;\r
+      size = prop.uhVal.QuadPart;\r
+    }\r
+  \r
+    UInt32 dicSize = _dicSize;\r
+    if (dicSize == 0xFFFFFFFF)\r
+      dicSize = (_level >= 5 ? kDicSizeX5 :\r
+                (_level >= 3 ? kDicSizeX3 :\r
+                               kDicSizeX1));\r
+\r
+    UInt32 numPasses = _numPasses;\r
+    if (numPasses == 0xFFFFFFFF)\r
+      numPasses = (_level >= 9 ? kNumPassesX9 :\r
+                  (_level >= 7 ? kNumPassesX7 :\r
+                                 kNumPassesX1));\r
+\r
+    return UpdateArchive(\r
+        size, outStream, 0, dicSize, numPasses,\r
+        #ifndef _7ZIP_ST\r
+        _numThreads,\r
+        #endif\r
+        updateCallback);\r
+  }\r
+  if (indexInArchive != 0)\r
+    return E_INVALIDARG;\r
+  if (_stream)\r
+    RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));\r
+  return NCompress::CopyStream(_stream, outStream, NULL);\r
+}\r
+\r
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)\r
+{\r
+  InitMethodProperties();\r
+  #ifndef _7ZIP_ST\r
+  const UInt32 numProcessors = NSystem::GetNumberOfProcessors();\r
+  _numThreads = numProcessors;\r
+  #endif\r
+\r
+  for (int i = 0; i < numProps; i++)\r
+  {\r
+    UString name = names[i];\r
+    name.MakeUpper();\r
+    if (name.IsEmpty())\r
+      return E_INVALIDARG;\r
+    const PROPVARIANT &prop = values[i];\r
+    if (name[0] == L'X')\r
+    {\r
+      UInt32 level = 9;\r
+      RINOK(ParsePropValue(name.Mid(1), prop, level));\r
+      _level = level;\r
+    }\r
+    else if (name[0] == L'D')\r
+    {\r
+      UInt32 dicSize = kDicSizeX5;\r
+      RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize));\r
+      _dicSize = dicSize;\r
+    }\r
+    else if (name.Left(4) == L"PASS")\r
+    {\r
+      UInt32 num = kNumPassesX9;\r
+      RINOK(ParsePropValue(name.Mid(4), prop, num));\r
+      _numPasses = num;\r
+    }\r
+    else if (name.Left(2) == L"MT")\r
+    {\r
+      #ifndef _7ZIP_ST\r
+      RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads));\r
+      #endif\r
+    }\r
+    else\r
+      return E_INVALIDARG;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+#ifndef EXTRACT_ONLY\r
+static IOutArchive *CreateArcOut() { return new CHandler; }\r
+#else\r
+#define CreateArcOut 0\r
+#endif\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"bzip2", L"bz2 bzip2 tbz2 tbz", L"* * .tar .tar", 2, { 'B', 'Z', 'h' }, 3, true, CreateArc, CreateArcOut };\r
+\r
+REGISTER_ARC(BZip2)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp
new file mode 100755 (executable)
index 0000000..e34d265
--- /dev/null
@@ -0,0 +1,189 @@
+// CabBlockInStream.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/Alloc.h"\r
+\r
+#include "Common/Defs.h"\r
+\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "CabBlockInStream.h"\r
+\r
+namespace NArchive {\r
+namespace NCab {\r
+\r
+static const UInt32 kBlockSize = (1 << 16);\r
+\r
+bool CCabBlockInStream::Create()\r
+{\r
+  if (!_buffer)\r
+    _buffer = (Byte *)::MyAlloc(kBlockSize);\r
+  return (_buffer != 0);\r
+}\r
+\r
+CCabBlockInStream::~CCabBlockInStream()\r
+{\r
+  MyFree(_buffer);\r
+}\r
+\r
+class CCheckSum2\r
+{\r
+  UInt32 m_Value;\r
+  int m_Pos;\r
+  Byte m_Hist[4];\r
+public:\r
+  CCheckSum2(): m_Value(0){};\r
+  void Init() { m_Value = 0;  m_Pos = 0; }\r
+  void Update(const void *data, UInt32 size);\r
+  void FinishDataUpdate()\r
+  {\r
+    for (int i = 0; i < m_Pos; i++)\r
+      m_Value ^= ((UInt32)(m_Hist[i])) << (8 * (m_Pos - i - 1));\r
+  }\r
+  void UpdateUInt32(UInt32 v) { m_Value ^= v; }\r
+  UInt32 GetResult() const {  return m_Value; }\r
+};\r
+\r
+void CCheckSum2::Update(const void *data, UInt32 size)\r
+{\r
+  UInt32 checkSum = m_Value;\r
+  const Byte *dataPointer = (const Byte *)data;\r
+\r
+  while (size != 0 && m_Pos != 0)\r
+  {\r
+    m_Hist[m_Pos] = *dataPointer++;\r
+    m_Pos = (m_Pos + 1) & 3;\r
+    size--;\r
+    if (m_Pos == 0)\r
+      for (int i = 0; i < 4; i++)\r
+        checkSum ^= ((UInt32)m_Hist[i]) << (8 * i);\r
+  }\r
+\r
+  int numWords = size / 4;\r
+  \r
+  while (numWords-- != 0)\r
+  {\r
+    UInt32 temp = *dataPointer++;\r
+    temp |= ((UInt32)(*dataPointer++)) <<  8;\r
+    temp |= ((UInt32)(*dataPointer++)) << 16;\r
+    temp |= ((UInt32)(*dataPointer++)) << 24;\r
+    checkSum ^= temp;\r
+  }\r
+  m_Value = checkSum;\r
+\r
+  size &= 3;\r
+  \r
+  while (size != 0)\r
+  {\r
+    m_Hist[m_Pos] = *dataPointer++;\r
+    m_Pos = (m_Pos + 1) & 3;\r
+    size--;\r
+  }\r
+}\r
+\r
+static const UInt32 kDataBlockHeaderSize = 8;\r
+\r
+class CTempCabInBuffer2\r
+{\r
+public:\r
+  Byte Buffer[kDataBlockHeaderSize];\r
+  UInt32 Pos;\r
+  Byte ReadByte()\r
+  {\r
+    return Buffer[Pos++];\r
+  }\r
+  UInt32 ReadUInt32()\r
+  {\r
+    UInt32 value = 0;\r
+    for (int i = 0; i < 4; i++)\r
+      value |= (((UInt32)ReadByte()) << (8 * i));\r
+    return value;\r
+  }\r
+  UInt16 ReadUInt16()\r
+  {\r
+    UInt16 value = 0;\r
+    for (int i = 0; i < 2; i++)\r
+      value |= (((UInt16)ReadByte()) << (8 * i));\r
+    return value;\r
+  }\r
+};\r
+\r
+HRESULT CCabBlockInStream::PreRead(UInt32 &packSize, UInt32 &unpackSize)\r
+{\r
+  CTempCabInBuffer2 inBuffer;\r
+  inBuffer.Pos = 0;\r
+  RINOK(ReadStream_FALSE(_stream, inBuffer.Buffer, kDataBlockHeaderSize))\r
+\r
+  UInt32 checkSum = inBuffer.ReadUInt32();\r
+  packSize = inBuffer.ReadUInt16();\r
+  unpackSize = inBuffer.ReadUInt16();\r
+  if (ReservedSize != 0)\r
+  {\r
+    RINOK(ReadStream_FALSE(_stream, _buffer, ReservedSize));\r
+  }\r
+  _pos = 0;\r
+  CCheckSum2 checkSumCalc;\r
+  checkSumCalc.Init();\r
+  UInt32 packSize2 = packSize;\r
+  if (MsZip && _size == 0)\r
+  {\r
+    if (packSize < 2)\r
+      return S_FALSE; // bad block;\r
+    Byte sig[2];\r
+    RINOK(ReadStream_FALSE(_stream, sig, 2));\r
+    if (sig[0] != 0x43 || sig[1] != 0x4B)\r
+      return S_FALSE;\r
+    packSize2 -= 2;\r
+    checkSumCalc.Update(sig, 2);\r
+  }\r
+\r
+  if (kBlockSize - _size < packSize2)\r
+    return S_FALSE;\r
+\r
+  UInt32 curSize = packSize2;\r
+  if (curSize != 0)\r
+  {\r
+    size_t processedSizeLoc = curSize;\r
+    RINOK(ReadStream(_stream, _buffer + _size, &processedSizeLoc));\r
+    checkSumCalc.Update(_buffer + _size, (UInt32)processedSizeLoc);\r
+    _size += (UInt32)processedSizeLoc;\r
+    if (processedSizeLoc != curSize)\r
+      return S_FALSE;\r
+  }\r
+  TotalPackSize = _size;\r
+\r
+  checkSumCalc.FinishDataUpdate();\r
+  \r
+  bool dataError;\r
+  if (checkSum == 0)\r
+    dataError = false;\r
+  else\r
+  {\r
+    checkSumCalc.UpdateUInt32(packSize | (((UInt32)unpackSize) << 16));\r
+    dataError = (checkSumCalc.GetResult() != checkSum);\r
+  }\r
+  DataError |= dataError;\r
+  return dataError ? S_FALSE : S_OK;\r
+}\r
+\r
+STDMETHODIMP CCabBlockInStream::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize != 0)\r
+    *processedSize = 0;\r
+  if (size == 0)\r
+    return S_OK;\r
+  if (_size != 0)\r
+  {\r
+    size = MyMin(_size, size);\r
+    memmove(data, _buffer + _pos, size);\r
+    _pos += size;\r
+    _size -= size;\r
+    if (processedSize != 0)\r
+      *processedSize = size;\r
+    return S_OK;\r
+  }\r
+  return S_OK; // no blocks data\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Cab/CabBlockInStream.h b/CPP/7zip/Archive/Cab/CabBlockInStream.h
new file mode 100755 (executable)
index 0000000..b01113d
--- /dev/null
@@ -0,0 +1,44 @@
+// CabBlockInStream.cpp\r
+\r
+#ifndef __CABBLOCKINSTREAM_H\r
+#define __CABBLOCKINSTREAM_H\r
+\r
+#include "Common/MyCom.h"\r
+#include "../../IStream.h"\r
+\r
+namespace NArchive {\r
+namespace NCab {\r
+\r
+class CCabBlockInStream:\r
+  public ISequentialInStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<ISequentialInStream> _stream;\r
+  Byte *_buffer;\r
+  UInt32 _pos;\r
+  UInt32 _size;\r
+\r
+public:\r
+  UInt32 TotalPackSize;\r
+  UInt32 ReservedSize;\r
+  bool DataError;\r
+  bool MsZip;\r
+\r
+  CCabBlockInStream(): _buffer(0), ReservedSize(0), MsZip(false), DataError(false), TotalPackSize(0) {}\r
+  ~CCabBlockInStream();\r
+  bool Create();\r
+  void SetStream(ISequentialInStream *stream) {  _stream = stream; }\r
+\r
+  void InitForNewFolder() { TotalPackSize = 0; }\r
+  void InitForNewBlock() { _size = 0; }\r
+\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+\r
+  HRESULT PreRead(UInt32 &packSize, UInt32 &unpackSize);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp
new file mode 100755 (executable)
index 0000000..084a96b
--- /dev/null
@@ -0,0 +1,929 @@
+// CabHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/Alloc.h"\r
+\r
+#include "Common/Buffer.h"\r
+#include "Common/ComTry.h"\r
+#include "Common/Defs.h"\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+#include "Common/UTFConvert.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../../Common/ProgressUtils.h"\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "../../Compress/CopyCoder.h"\r
+#include "../../Compress/DeflateDecoder.h"\r
+#include "../../Compress/LzxDecoder.h"\r
+#include "../../Compress/QuantumDecoder.h"\r
+\r
+#include "../Common/ItemNameUtils.h"\r
+\r
+#include "CabBlockInStream.h"\r
+#include "CabHandler.h"\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace NCab {\r
+\r
+// #define _CAB_DETAILS\r
+\r
+#ifdef _CAB_DETAILS\r
+enum\r
+{\r
+  kpidBlockReal = kpidUserDefined\r
+};\r
+#endif\r
+\r
+static STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidAttrib, VT_UI4},\r
+  { NULL, kpidMethod, VT_BSTR},\r
+  { NULL, kpidBlock, VT_I4}\r
+  #ifdef _CAB_DETAILS\r
+  ,\r
+  { L"BlockReal", kpidBlockReal, VT_UI4},\r
+  { NULL, kpidOffset, VT_UI4},\r
+  { NULL, kpidVolume, VT_UI4}\r
+  #endif\r
+};\r
+\r
+static const char *kMethods[] =\r
+{\r
+  "None",\r
+  "MSZip",\r
+  "Quantum",\r
+  "LZX"\r
+};\r
+\r
+static const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]);\r
+static const char *kUnknownMethod = "Unknown";\r
+\r
+static STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidMethod, VT_BSTR},\r
+  // { NULL, kpidSolid, VT_BOOL},\r
+  { NULL, kpidNumBlocks, VT_UI4},\r
+  { NULL, kpidNumVolumes, VT_UI4}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidMethod:\r
+    {\r
+      AString resString;\r
+      CRecordVector<Byte> ids;\r
+      int i;\r
+      for (int v = 0; v < m_Database.Volumes.Size(); v++)\r
+      {\r
+        const CDatabaseEx &de = m_Database.Volumes[v];\r
+        for (i = 0; i < de.Folders.Size(); i++)\r
+          ids.AddToUniqueSorted(de.Folders[i].GetCompressionMethod());\r
+      }\r
+      for (i = 0; i < ids.Size(); i++)\r
+      {\r
+        Byte id = ids[i];\r
+        AString method = (id < kNumMethods) ? kMethods[id] : kUnknownMethod;\r
+        if (!resString.IsEmpty())\r
+          resString += ' ';\r
+        resString += method;\r
+      }\r
+      prop = resString;\r
+      break;\r
+    }\r
+    // case kpidSolid: prop = _database.IsSolid(); break;\r
+    case kpidNumBlocks:\r
+    {\r
+      UInt32 numFolders = 0;\r
+      for (int v = 0; v < m_Database.Volumes.Size(); v++)\r
+        numFolders += m_Database.Volumes[v].Folders.Size();\r
+      prop = numFolders;\r
+      break;\r
+    }\r
+    case kpidNumVolumes:\r
+    {\r
+      prop = (UInt32)m_Database.Volumes.Size();\r
+      break;\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID,  PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  \r
+  const CMvItem &mvItem = m_Database.Items[index];\r
+  const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex];\r
+  int itemIndex = mvItem.ItemIndex;\r
+  const CItem &item = db.Items[itemIndex];\r
+  switch(propID)\r
+  {\r
+    case kpidPath:\r
+    {\r
+      UString unicodeName;\r
+      if (item.IsNameUTF())\r
+        ConvertUTF8ToUnicode(item.Name, unicodeName);\r
+      else\r
+        unicodeName = MultiByteToUnicodeString(item.Name, CP_ACP);\r
+      prop = (const wchar_t *)NItemName::WinNameToOSName(unicodeName);\r
+      break;\r
+    }\r
+    case kpidIsDir:  prop = item.IsDir(); break;\r
+    case kpidSize:  prop = item.Size; break;\r
+    case kpidAttrib:  prop = item.GetWinAttributes(); break;\r
+\r
+    case kpidMTime:\r
+    {\r
+      FILETIME localFileTime, utcFileTime;\r
+      if (NTime::DosTimeToFileTime(item.Time, localFileTime))\r
+      {\r
+        if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime))\r
+          utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;\r
+      }\r
+      else\r
+        utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;\r
+      prop = utcFileTime;\r
+      break;\r
+    }\r
+\r
+    case kpidMethod:\r
+    {\r
+      UInt32 realFolderIndex = item.GetFolderIndex(db.Folders.Size());\r
+      const CFolder &folder = db.Folders[realFolderIndex];\r
+      int methodIndex = folder.GetCompressionMethod();\r
+      AString method = (methodIndex < kNumMethods) ? kMethods[methodIndex] : kUnknownMethod;\r
+      if (methodIndex == NHeader::NCompressionMethodMajor::kLZX ||\r
+        methodIndex == NHeader::NCompressionMethodMajor::kQuantum)\r
+      {\r
+        method += ':';\r
+        char temp[32];\r
+        ConvertUInt64ToString(folder.CompressionTypeMinor, temp);\r
+        method += temp;\r
+      }\r
+      prop = method;\r
+      break;\r
+    }\r
+    case kpidBlock:  prop = (Int32)m_Database.GetFolderIndex(&mvItem); break;\r
+    \r
+    #ifdef _CAB_DETAILS\r
+    \r
+    case kpidBlockReal:  prop = (UInt32)item.FolderIndex; break;\r
+    case kpidOffset:  prop = (UInt32)item.Offset; break;\r
+    case kpidVolume:  prop = (UInt32)mvItem.VolumeIndex; break;\r
+\r
+    #endif\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+/*\r
+class CProgressImp: public CProgressVirt\r
+{\r
+  CMyComPtr<IArchiveOpenCallback> m_OpenArchiveCallback;\r
+public:\r
+  STDMETHOD(SetTotal)(const UInt64 *numFiles);\r
+  STDMETHOD(SetCompleted)(const UInt64 *numFiles);\r
+  void Init(IArchiveOpenCallback *openArchiveCallback)\r
+    { m_OpenArchiveCallback = openArchiveCallback; }\r
+};\r
+\r
+STDMETHODIMP CProgressImp::SetTotal(const UInt64 *numFiles)\r
+{\r
+  if (m_OpenArchiveCallback)\r
+    return m_OpenArchiveCallback->SetCompleted(numFiles, NULL);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CProgressImp::SetCompleted(const UInt64 *numFiles)\r
+{\r
+  if (m_OpenArchiveCallback)\r
+    return m_OpenArchiveCallback->SetCompleted(numFiles, NULL);\r
+  return S_OK;\r
+}\r
+*/\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *inStream,\r
+    const UInt64 *maxCheckStartPosition,\r
+    IArchiveOpenCallback *callback)\r
+{\r
+  COM_TRY_BEGIN\r
+  Close();\r
+  HRESULT res = S_FALSE;\r
+  CInArchive archive;\r
+  CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;\r
+  callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);\r
+  \r
+  CMyComPtr<IInStream> nextStream = inStream;\r
+  bool prevChecked = false;\r
+  UInt64 numItems = 0;\r
+  try\r
+  {\r
+    while (nextStream != 0)\r
+    {\r
+      CDatabaseEx db;\r
+      db.Stream = nextStream;\r
+      res = archive.Open(maxCheckStartPosition, db);\r
+      if (res == S_OK)\r
+      {\r
+        if (!m_Database.Volumes.IsEmpty())\r
+        {\r
+          const CDatabaseEx &dbPrev = m_Database.Volumes[prevChecked ? m_Database.Volumes.Size() - 1 : 0];\r
+          if (dbPrev.ArchiveInfo.SetID != db.ArchiveInfo.SetID ||\r
+              dbPrev.ArchiveInfo.CabinetNumber + (prevChecked ? 1: - 1) !=\r
+              db.ArchiveInfo.CabinetNumber)\r
+            res = S_FALSE;\r
+        }\r
+      }\r
+      if (res == S_OK)\r
+        m_Database.Volumes.Insert(prevChecked ? m_Database.Volumes.Size() : 0, db);\r
+      else if (res != S_FALSE)\r
+        return res;\r
+      else\r
+      {\r
+        if (m_Database.Volumes.IsEmpty())\r
+          return S_FALSE;\r
+        if (prevChecked)\r
+          break;\r
+        prevChecked = true;\r
+      }\r
+\r
+      numItems += db.Items.Size();\r
+      RINOK(callback->SetCompleted(&numItems, NULL));\r
+        \r
+      nextStream = 0;\r
+      for (;;)\r
+      {\r
+        const COtherArchive *otherArchive = 0;\r
+        if (!prevChecked)\r
+        {\r
+          const CInArchiveInfo &ai = m_Database.Volumes.Front().ArchiveInfo;\r
+          if (ai.IsTherePrev())\r
+            otherArchive = &ai.PrevArc;\r
+          else\r
+            prevChecked = true;\r
+        }\r
+        if (otherArchive == 0)\r
+        {\r
+          const CInArchiveInfo &ai = m_Database.Volumes.Back().ArchiveInfo;\r
+          if (ai.IsThereNext())\r
+            otherArchive = &ai.NextArc;\r
+        }\r
+        if (!otherArchive)\r
+          break;\r
+        const UString fullName = MultiByteToUnicodeString(otherArchive->FileName, CP_ACP);\r
+        if (!openVolumeCallback)\r
+          break;\r
+\r
+        HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream);\r
+        if (result == S_OK)\r
+          break;\r
+        if (result != S_FALSE)\r
+          return result;\r
+        if (prevChecked)\r
+          break;\r
+        prevChecked = true;\r
+      }\r
+    }\r
+    if (res == S_OK)\r
+    {\r
+      m_Database.FillSortAndShrink();\r
+      if (!m_Database.Check())\r
+        res = S_FALSE;\r
+    }\r
+  }\r
+  catch(...)\r
+  {\r
+    res = S_FALSE;\r
+  }\r
+  if (res != S_OK)\r
+  {\r
+    Close();\r
+    return res;\r
+  }\r
+  COM_TRY_END\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  m_Database.Clear();\r
+  return S_OK;\r
+}\r
+\r
+class CFolderOutStream:\r
+  public ISequentialOutStream,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+private:\r
+  const CMvDatabaseEx *m_Database;\r
+  const CRecordVector<bool> *m_ExtractStatuses;\r
+  \r
+  Byte *TempBuf;\r
+  UInt32 TempBufSize;\r
+  int NumIdenticalFiles;\r
+  bool TempBufMode;\r
+  UInt32 m_BufStartFolderOffset;\r
+\r
+  int m_StartIndex;\r
+  int m_CurrentIndex;\r
+  CMyComPtr<IArchiveExtractCallback> m_ExtractCallback;\r
+  bool m_TestMode;\r
+\r
+  CMyComPtr<ISequentialOutStream> m_RealOutStream;\r
+\r
+  bool m_IsOk;\r
+  bool m_FileIsOpen;\r
+  UInt32 m_RemainFileSize;\r
+  UInt64 m_FolderSize;\r
+  UInt64 m_PosInFolder;\r
+\r
+  void FreeTempBuf()\r
+  {\r
+    ::MyFree(TempBuf);\r
+    TempBuf = NULL;\r
+  }\r
+\r
+  HRESULT OpenFile();\r
+  HRESULT CloseFileWithResOp(Int32 resOp);\r
+  HRESULT CloseFile();\r
+  HRESULT Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK);\r
+public:\r
+  HRESULT WriteEmptyFiles();\r
+\r
+  CFolderOutStream(): TempBuf(NULL) {}\r
+  ~CFolderOutStream() { FreeTempBuf(); }\r
+  void Init(\r
+      const CMvDatabaseEx *database,\r
+      const CRecordVector<bool> *extractStatuses,\r
+      int startIndex,\r
+      UInt64 folderSize,\r
+      IArchiveExtractCallback *extractCallback,\r
+      bool testMode);\r
+  HRESULT FlushCorrupted();\r
+  HRESULT Unsupported();\r
+\r
+  UInt64 GetRemain() const { return m_FolderSize - m_PosInFolder; }\r
+  UInt64 GetPosInFolder() const { return m_PosInFolder; }\r
+};\r
+\r
+void CFolderOutStream::Init(\r
+    const CMvDatabaseEx *database,\r
+    const CRecordVector<bool> *extractStatuses,\r
+    int startIndex,\r
+    UInt64 folderSize,\r
+    IArchiveExtractCallback *extractCallback,\r
+    bool testMode)\r
+{\r
+  m_Database = database;\r
+  m_ExtractStatuses = extractStatuses;\r
+  m_StartIndex = startIndex;\r
+  m_FolderSize = folderSize;\r
+\r
+  m_ExtractCallback = extractCallback;\r
+  m_TestMode = testMode;\r
+\r
+  m_CurrentIndex = 0;\r
+  m_PosInFolder = 0;\r
+  m_FileIsOpen = false;\r
+  m_IsOk = true;\r
+  TempBufMode = false;\r
+  NumIdenticalFiles = 0;\r
+}\r
+\r
+HRESULT CFolderOutStream::CloseFileWithResOp(Int32 resOp)\r
+{\r
+  m_RealOutStream.Release();\r
+  m_FileIsOpen = false;\r
+  NumIdenticalFiles--;\r
+  return m_ExtractCallback->SetOperationResult(resOp);\r
+}\r
+\r
+HRESULT CFolderOutStream::CloseFile()\r
+{\r
+  return CloseFileWithResOp(m_IsOk ?\r
+      NExtract::NOperationResult::kOK:\r
+      NExtract::NOperationResult::kDataError);\r
+}\r
+\r
+HRESULT CFolderOutStream::OpenFile()\r
+{\r
+  if (NumIdenticalFiles == 0)\r
+  {\r
+    const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];\r
+    const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];\r
+    int numExtractItems = 0;\r
+    int curIndex;\r
+    for (curIndex = m_CurrentIndex; curIndex < m_ExtractStatuses->Size(); curIndex++)\r
+    {\r
+      const CMvItem &mvItem2 = m_Database->Items[m_StartIndex + curIndex];\r
+      const CItem &item2 = m_Database->Volumes[mvItem2.VolumeIndex].Items[mvItem2.ItemIndex];\r
+      if (item.Offset != item2.Offset ||\r
+          item.Size != item2.Size ||\r
+          item.Size == 0)\r
+        break;\r
+      if (!m_TestMode && (*m_ExtractStatuses)[curIndex])\r
+        numExtractItems++;\r
+    }\r
+    NumIdenticalFiles = (curIndex - m_CurrentIndex);\r
+    if (NumIdenticalFiles == 0)\r
+      NumIdenticalFiles = 1;\r
+    TempBufMode = false;\r
+    if (numExtractItems > 1)\r
+    {\r
+      if (!TempBuf || item.Size > TempBufSize)\r
+      {\r
+        FreeTempBuf();\r
+        TempBuf = (Byte *)MyAlloc(item.Size);\r
+        TempBufSize = item.Size;\r
+        if (TempBuf == NULL)\r
+          return E_OUTOFMEMORY;\r
+      }\r
+      TempBufMode = true;\r
+      m_BufStartFolderOffset = item.Offset;\r
+    }\r
+    else if (numExtractItems == 1)\r
+    {\r
+      while (NumIdenticalFiles && !(*m_ExtractStatuses)[m_CurrentIndex])\r
+      {\r
+        CMyComPtr<ISequentialOutStream> stream;\r
+        RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &stream, NExtract::NAskMode::kSkip));\r
+        if (stream)\r
+          return E_FAIL;\r
+        RINOK(m_ExtractCallback->PrepareOperation(NExtract::NAskMode::kSkip));\r
+        m_CurrentIndex++;\r
+        m_FileIsOpen = true;\r
+        CloseFile();\r
+      }\r
+    }\r
+  }\r
+\r
+  Int32 askMode = (*m_ExtractStatuses)[m_CurrentIndex] ? (m_TestMode ?\r
+      NExtract::NAskMode::kTest :\r
+      NExtract::NAskMode::kExtract) :\r
+      NExtract::NAskMode::kSkip;\r
+  RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode));\r
+  if (!m_RealOutStream && !m_TestMode)\r
+    askMode = NExtract::NAskMode::kSkip;\r
+  return m_ExtractCallback->PrepareOperation(askMode);\r
+}\r
+\r
+HRESULT CFolderOutStream::WriteEmptyFiles()\r
+{\r
+  if (m_FileIsOpen)\r
+    return S_OK;\r
+  for (; m_CurrentIndex < m_ExtractStatuses->Size(); m_CurrentIndex++)\r
+  {\r
+    const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];\r
+    const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];\r
+    UInt64 fileSize = item.Size;\r
+    if (fileSize != 0)\r
+      return S_OK;\r
+    HRESULT result = OpenFile();\r
+    m_RealOutStream.Release();\r
+    RINOK(result);\r
+    RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+// This is Write function\r
+HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK)\r
+{\r
+  COM_TRY_BEGIN\r
+  UInt32 realProcessed = 0;\r
+  if (processedSize != NULL)\r
+   *processedSize = 0;\r
+  while (size != 0)\r
+  {\r
+    if (m_FileIsOpen)\r
+    {\r
+      UInt32 numBytesToWrite = MyMin(m_RemainFileSize, size);\r
+      HRESULT res = S_OK;\r
+      if (numBytesToWrite > 0)\r
+      {\r
+        if (!isOK)\r
+          m_IsOk = false;\r
+        if (m_RealOutStream)\r
+        {\r
+          UInt32 processedSizeLocal = 0;\r
+          res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal);\r
+          numBytesToWrite = processedSizeLocal;\r
+        }\r
+        if (TempBufMode && TempBuf)\r
+          memcpy(TempBuf + (m_PosInFolder - m_BufStartFolderOffset), data, numBytesToWrite);\r
+      }\r
+      realProcessed += numBytesToWrite;\r
+      if (processedSize != NULL)\r
+        *processedSize = realProcessed;\r
+      data = (const void *)((const Byte *)data + numBytesToWrite);\r
+      size -= numBytesToWrite;\r
+      m_RemainFileSize -= numBytesToWrite;\r
+      m_PosInFolder += numBytesToWrite;\r
+      if (res != S_OK)\r
+        return res;\r
+      if (m_RemainFileSize == 0)\r
+      {\r
+        RINOK(CloseFile());\r
+\r
+        while (NumIdenticalFiles)\r
+        {\r
+          HRESULT result = OpenFile();\r
+          m_FileIsOpen = true;\r
+          m_CurrentIndex++;\r
+          if (result == S_OK && m_RealOutStream && TempBuf)\r
+            result = WriteStream(m_RealOutStream, TempBuf, (size_t)(m_PosInFolder - m_BufStartFolderOffset));\r
+          \r
+          if (!TempBuf && TempBufMode && m_RealOutStream)\r
+          {\r
+            RINOK(CloseFileWithResOp(NExtract::NOperationResult::kUnSupportedMethod));\r
+          }\r
+          else\r
+          {\r
+            RINOK(CloseFile());\r
+          }\r
+          RINOK(result);\r
+        }\r
+        TempBufMode = false;\r
+      }\r
+      if (realProcessed > 0)\r
+        break; // with this break this function works as Write-Part\r
+    }\r
+    else\r
+    {\r
+      if (m_CurrentIndex >= m_ExtractStatuses->Size())\r
+        return E_FAIL;\r
+\r
+      const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];\r
+      const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];\r
+\r
+      m_RemainFileSize = item.Size;\r
+\r
+      UInt32 fileOffset = item.Offset;\r
+      if (fileOffset < m_PosInFolder)\r
+        return E_FAIL;\r
+      if (fileOffset > m_PosInFolder)\r
+      {\r
+        UInt32 numBytesToWrite = MyMin(fileOffset - (UInt32)m_PosInFolder, size);\r
+        realProcessed += numBytesToWrite;\r
+        if (processedSize != NULL)\r
+          *processedSize = realProcessed;\r
+        data = (const void *)((const Byte *)data + numBytesToWrite);\r
+        size -= numBytesToWrite;\r
+        m_PosInFolder += numBytesToWrite;\r
+      }\r
+      if (fileOffset == m_PosInFolder)\r
+      {\r
+        RINOK(OpenFile());\r
+        m_FileIsOpen = true;\r
+        m_CurrentIndex++;\r
+        m_IsOk = true;\r
+      }\r
+    }\r
+  }\r
+  return WriteEmptyFiles();\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  return Write2(data, size, processedSize, true);\r
+}\r
+\r
+HRESULT CFolderOutStream::FlushCorrupted()\r
+{\r
+  const UInt32 kBufferSize = (1 << 10);\r
+  Byte buffer[kBufferSize];\r
+  for (int i = 0; i < kBufferSize; i++)\r
+    buffer[i] = 0;\r
+  for (;;)\r
+  {\r
+    UInt64 remain = GetRemain();\r
+    if (remain == 0)\r
+      return S_OK;\r
+    UInt32 size = (UInt32)MyMin(remain, (UInt64)kBufferSize);\r
+    UInt32 processedSizeLocal = 0;\r
+    RINOK(Write2(buffer, size, &processedSizeLocal, false));\r
+  }\r
+}\r
+\r
+HRESULT CFolderOutStream::Unsupported()\r
+{\r
+  while(m_CurrentIndex < m_ExtractStatuses->Size())\r
+  {\r
+    HRESULT result = OpenFile();\r
+    if (result != S_FALSE && result != S_OK)\r
+      return result;\r
+    m_RealOutStream.Release();\r
+    RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));\r
+    m_CurrentIndex++;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testModeSpec, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = m_Database.Items.Size();\r
+  if(numItems == 0)\r
+    return S_OK;\r
+  bool testMode = (testModeSpec != 0);\r
+  UInt64 totalUnPacked = 0;\r
+\r
+  UInt32 i;\r
+  int lastFolder = -2;\r
+  UInt64 lastFolderSize = 0;\r
+  for(i = 0; i < numItems; i++)\r
+  {\r
+    int index = allFilesMode ? i : indices[i];\r
+    const CMvItem &mvItem = m_Database.Items[index];\r
+    const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];\r
+    if (item.IsDir())\r
+      continue;\r
+    int folderIndex = m_Database.GetFolderIndex(&mvItem);\r
+    if (folderIndex != lastFolder)\r
+      totalUnPacked += lastFolderSize;\r
+    lastFolder = folderIndex;\r
+    lastFolderSize = item.GetEndOffset();\r
+  }\r
+  totalUnPacked += lastFolderSize;\r
+\r
+  extractCallback->SetTotal(totalUnPacked);\r
+\r
+  totalUnPacked = 0;\r
+\r
+  UInt64 totalPacked = 0;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  NCompress::NDeflate::NDecoder::CCOMCoder *deflateDecoderSpec = NULL;\r
+  CMyComPtr<ICompressCoder> deflateDecoder;\r
+\r
+  NCompress::NLzx::CDecoder *lzxDecoderSpec = NULL;\r
+  CMyComPtr<ICompressCoder> lzxDecoder;\r
+\r
+  NCompress::NQuantum::CDecoder *quantumDecoderSpec = NULL;\r
+  CMyComPtr<ICompressCoder> quantumDecoder;\r
+\r
+  CCabBlockInStream *cabBlockInStreamSpec = new CCabBlockInStream();\r
+  CMyComPtr<ISequentialInStream> cabBlockInStream = cabBlockInStreamSpec;\r
+  if (!cabBlockInStreamSpec->Create())\r
+    return E_OUTOFMEMORY;\r
+\r
+  CRecordVector<bool> extractStatuses;\r
+  for(i = 0; i < numItems;)\r
+  {\r
+    int index = allFilesMode ? i : indices[i];\r
+\r
+    const CMvItem &mvItem = m_Database.Items[index];\r
+    const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex];\r
+    int itemIndex = mvItem.ItemIndex;\r
+    const CItem &item = db.Items[itemIndex];\r
+\r
+    i++;\r
+    if (item.IsDir())\r
+    {\r
+      Int32 askMode = testMode ?\r
+          NExtract::NAskMode::kTest :\r
+          NExtract::NAskMode::kExtract;\r
+      CMyComPtr<ISequentialOutStream> realOutStream;\r
+      RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      realOutStream.Release();\r
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+      continue;\r
+    }\r
+    int folderIndex = m_Database.GetFolderIndex(&mvItem);\r
+    if (folderIndex < 0)\r
+    {\r
+      // If we need previous archive\r
+      Int32 askMode= testMode ?\r
+          NExtract::NAskMode::kTest :\r
+          NExtract::NAskMode::kExtract;\r
+      CMyComPtr<ISequentialOutStream> realOutStream;\r
+      RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      realOutStream.Release();\r
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError));\r
+      continue;\r
+    }\r
+    int startIndex2 = m_Database.FolderStartFileIndex[folderIndex];\r
+    int startIndex = startIndex2;\r
+    extractStatuses.Clear();\r
+    for (; startIndex < index; startIndex++)\r
+      extractStatuses.Add(false);\r
+    extractStatuses.Add(true);\r
+    startIndex++;\r
+    UInt64 curUnpack = item.GetEndOffset();\r
+    for(;i < numItems; i++)\r
+    {\r
+      int indexNext = allFilesMode ? i : indices[i];\r
+      const CMvItem &mvItem = m_Database.Items[indexNext];\r
+      const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];\r
+      if (item.IsDir())\r
+        continue;\r
+      int newFolderIndex = m_Database.GetFolderIndex(&mvItem);\r
+\r
+      if (newFolderIndex != folderIndex)\r
+        break;\r
+      for (; startIndex < indexNext; startIndex++)\r
+        extractStatuses.Add(false);\r
+      extractStatuses.Add(true);\r
+      startIndex++;\r
+      curUnpack = item.GetEndOffset();\r
+    }\r
+\r
+    lps->OutSize = totalUnPacked;\r
+    lps->InSize = totalPacked;\r
+    RINOK(lps->SetCur());\r
+\r
+    CFolderOutStream *cabFolderOutStream = new CFolderOutStream;\r
+    CMyComPtr<ISequentialOutStream> outStream(cabFolderOutStream);\r
+\r
+    const CFolder &folder = db.Folders[item.GetFolderIndex(db.Folders.Size())];\r
+\r
+    cabFolderOutStream->Init(&m_Database, &extractStatuses, startIndex2,\r
+        curUnpack, extractCallback, testMode);\r
+\r
+    cabBlockInStreamSpec->MsZip = false;\r
+    switch(folder.GetCompressionMethod())\r
+    {\r
+      case NHeader::NCompressionMethodMajor::kNone:\r
+        break;\r
+      case NHeader::NCompressionMethodMajor::kMSZip:\r
+        if(deflateDecoderSpec == NULL)\r
+        {\r
+          deflateDecoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder;\r
+          deflateDecoder = deflateDecoderSpec;\r
+        }\r
+        cabBlockInStreamSpec->MsZip = true;\r
+        break;\r
+      case NHeader::NCompressionMethodMajor::kLZX:\r
+        if(lzxDecoderSpec == NULL)\r
+        {\r
+          lzxDecoderSpec = new NCompress::NLzx::CDecoder;\r
+          lzxDecoder = lzxDecoderSpec;\r
+        }\r
+        RINOK(lzxDecoderSpec->SetParams(folder.CompressionTypeMinor));\r
+        break;\r
+      case NHeader::NCompressionMethodMajor::kQuantum:\r
+        if(quantumDecoderSpec == NULL)\r
+        {\r
+          quantumDecoderSpec = new NCompress::NQuantum::CDecoder;\r
+          quantumDecoder = quantumDecoderSpec;\r
+        }\r
+        quantumDecoderSpec->SetParams(folder.CompressionTypeMinor);\r
+        break;\r
+      default:\r
+      {\r
+        RINOK(cabFolderOutStream->Unsupported());\r
+        totalUnPacked += curUnpack;\r
+        continue;\r
+      }\r
+    }\r
+\r
+    cabBlockInStreamSpec->InitForNewFolder();\r
+\r
+    HRESULT res = S_OK;\r
+\r
+    {\r
+      int volIndex = mvItem.VolumeIndex;\r
+      int locFolderIndex = item.GetFolderIndex(db.Folders.Size());\r
+      bool keepHistory = false;\r
+      bool keepInputBuffer = false;\r
+      for (UInt32 f = 0; cabFolderOutStream->GetRemain() != 0;)\r
+      {\r
+        if (volIndex >= m_Database.Volumes.Size())\r
+        {\r
+          res = S_FALSE;\r
+          break;\r
+        }\r
+\r
+        const CDatabaseEx &db = m_Database.Volumes[volIndex];\r
+        const CFolder &folder = db.Folders[locFolderIndex];\r
+        if (f == 0)\r
+        {\r
+          cabBlockInStreamSpec->SetStream(db.Stream);\r
+          cabBlockInStreamSpec->ReservedSize = db.ArchiveInfo.GetDataBlockReserveSize();\r
+          RINOK(db.Stream->Seek(db.StartPosition + folder.DataStart, STREAM_SEEK_SET, NULL));\r
+        }\r
+        if (f == folder.NumDataBlocks)\r
+        {\r
+          volIndex++;\r
+          locFolderIndex = 0;\r
+          f = 0;\r
+          continue;\r
+        }\r
+        f++;\r
+\r
+        cabBlockInStreamSpec->DataError = false;\r
+        \r
+        if (!keepInputBuffer)\r
+          cabBlockInStreamSpec->InitForNewBlock();\r
+\r
+        UInt32 packSize, unpackSize;\r
+        res = cabBlockInStreamSpec->PreRead(packSize, unpackSize);\r
+        if (res == S_FALSE)\r
+          break;\r
+        RINOK(res);\r
+        keepInputBuffer = (unpackSize == 0);\r
+        if (keepInputBuffer)\r
+          continue;\r
+\r
+        UInt64 totalUnPacked2 = totalUnPacked + cabFolderOutStream->GetPosInFolder();\r
+        totalPacked += packSize;\r
+\r
+        lps->OutSize = totalUnPacked2;\r
+        lps->InSize = totalPacked;\r
+        RINOK(lps->SetCur());\r
+\r
+        UInt64 unpackRemain = cabFolderOutStream->GetRemain();\r
+\r
+        const UInt32 kBlockSizeMax = (1 << 15);\r
+        if (unpackRemain > kBlockSizeMax)\r
+          unpackRemain = kBlockSizeMax;\r
+        if (unpackRemain > unpackSize)\r
+          unpackRemain  = unpackSize;\r
+   \r
+        switch(folder.GetCompressionMethod())\r
+        {\r
+          case NHeader::NCompressionMethodMajor::kNone:\r
+            res = copyCoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);\r
+            break;\r
+          case NHeader::NCompressionMethodMajor::kMSZip:\r
+            deflateDecoderSpec->SetKeepHistory(keepHistory);\r
+            res = deflateDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);\r
+            break;\r
+          case NHeader::NCompressionMethodMajor::kLZX:\r
+            lzxDecoderSpec->SetKeepHistory(keepHistory);\r
+            res = lzxDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);\r
+            break;\r
+          case NHeader::NCompressionMethodMajor::kQuantum:\r
+            quantumDecoderSpec->SetKeepHistory(keepHistory);\r
+            res = quantumDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);\r
+          break;\r
+        }\r
+        if (res != S_OK)\r
+        {\r
+          if (res != S_FALSE)\r
+            RINOK(res);\r
+          break;\r
+        }\r
+        keepHistory = true;\r
+      }\r
+      if (res == S_OK)\r
+      {\r
+        RINOK(cabFolderOutStream->WriteEmptyFiles());\r
+      }\r
+    }\r
+    if (res != S_OK || cabFolderOutStream->GetRemain() != 0)\r
+    {\r
+      RINOK(cabFolderOutStream->FlushCorrupted());\r
+    }\r
+    totalUnPacked += curUnpack;\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = m_Database.Items.Size();\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Cab/CabHandler.h b/CPP/7zip/Archive/Cab/CabHandler.h
new file mode 100755 (executable)
index 0000000..67c0d03
--- /dev/null
@@ -0,0 +1,28 @@
+// CabHandler.h\r
+\r
+#ifndef __CAB_HANDLER_H\r
+#define __CAB_HANDLER_H\r
+\r
+#include "Common/MyCom.h"\r
+#include "../IArchive.h"\r
+#include "CabIn.h"\r
+\r
+namespace NArchive {\r
+namespace NCab {\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP1(IInArchive)\r
+\r
+  INTERFACE_IInArchive(;)\r
+\r
+private:\r
+  CMvDatabaseEx m_Database;\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Cab/CabHeader.cpp b/CPP/7zip/Archive/Cab/CabHeader.cpp
new file mode 100755 (executable)
index 0000000..4d59ba0
--- /dev/null
@@ -0,0 +1,15 @@
+// CabHeader.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "CabHeader.h"\r
+\r
+namespace NArchive {\r
+namespace NCab {\r
+namespace NHeader {\r
+\r
+Byte kMarker[kMarkerSize] = {'M', 'S', 'C', 'F', 0, 0, 0, 0 };\r
+\r
+// struct CSignatureInitializer { CSignatureInitializer() { kMarker[0]--; }; } g_SignatureInitializer;\r
+\r
+}}}\r
diff --git a/CPP/7zip/Archive/Cab/CabHeader.h b/CPP/7zip/Archive/Cab/CabHeader.h
new file mode 100755 (executable)
index 0000000..5e68471
--- /dev/null
@@ -0,0 +1,44 @@
+// Archive/Cab/Header.h\r
+\r
+#ifndef __ARCHIVE_CAB_HEADER_H\r
+#define __ARCHIVE_CAB_HEADER_H\r
+\r
+#include "Common/Types.h"\r
+\r
+namespace NArchive {\r
+namespace NCab {\r
+namespace NHeader {\r
+\r
+const unsigned kMarkerSize = 8;\r
+extern Byte kMarker[kMarkerSize];\r
+\r
+namespace NArchive\r
+{\r
+  namespace NFlags\r
+  {\r
+    const int kPrevCabinet = 0x0001;\r
+    const int kNextCabinet = 0x0002;\r
+    const int kReservePresent = 0x0004;\r
+  }\r
+}\r
+\r
+namespace NCompressionMethodMajor\r
+{\r
+  const Byte kNone = 0;\r
+  const Byte kMSZip = 1;\r
+  const Byte kQuantum = 2;\r
+  const Byte kLZX = 3;\r
+}\r
+\r
+const int kFileNameIsUTFAttributeMask = 0x80;\r
+\r
+namespace NFolderIndex\r
+{\r
+  const int kContinuedFromPrev    = 0xFFFD;\r
+  const int kContinuedToNext      = 0xFFFE;\r
+  const int kContinuedPrevAndNext = 0xFFFF;\r
+}\r
+\r
+}}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Cab/CabIn.cpp b/CPP/7zip/Archive/Cab/CabIn.cpp
new file mode 100755 (executable)
index 0000000..a0ff0ad
--- /dev/null
@@ -0,0 +1,272 @@
+// Archive/CabIn.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../Common/FindSignature.h"\r
+\r
+#include "CabIn.h"\r
+\r
+namespace NArchive {\r
+namespace NCab {\r
+\r
+Byte CInArchive::Read8()\r
+{\r
+  Byte b;\r
+  if (!inBuffer.ReadByte(b))\r
+    throw CInArchiveException(CInArchiveException::kUnsupported);\r
+  return b;\r
+}\r
+\r
+UInt16 CInArchive::Read16()\r
+{\r
+  UInt16 value = 0;\r
+  for (int i = 0; i < 2; i++)\r
+  {\r
+    Byte b = Read8();\r
+    value |= (UInt16(b) << (8 * i));\r
+  }\r
+  return value;\r
+}\r
+\r
+UInt32 CInArchive::Read32()\r
+{\r
+  UInt32 value = 0;\r
+  for (int i = 0; i < 4; i++)\r
+  {\r
+    Byte b = Read8();\r
+    value |= (UInt32(b) << (8 * i));\r
+  }\r
+  return value;\r
+}\r
+\r
+AString CInArchive::SafeReadName()\r
+{\r
+  AString name;\r
+  for (;;)\r
+  {\r
+    Byte b = Read8();\r
+    if (b == 0)\r
+      return name;\r
+    name += (char)b;\r
+  }\r
+}\r
+\r
+void CInArchive::ReadOtherArchive(COtherArchive &oa)\r
+{\r
+  oa.FileName = SafeReadName();\r
+  oa.DiskName = SafeReadName();\r
+}\r
+\r
+void CInArchive::Skip(UInt32 size)\r
+{\r
+  while (size-- != 0)\r
+    Read8();\r
+}\r
+\r
+HRESULT CInArchive::Open(const UInt64 *searchHeaderSizeLimit, CDatabaseEx &db)\r
+{\r
+  IInStream *stream = db.Stream;\r
+  db.Clear();\r
+  RINOK(stream->Seek(0, STREAM_SEEK_SET, &db.StartPosition));\r
+\r
+  RINOK(FindSignatureInStream(stream, NHeader::kMarker, NHeader::kMarkerSize,\r
+      searchHeaderSizeLimit, db.StartPosition));\r
+\r
+  RINOK(stream->Seek(db.StartPosition + NHeader::kMarkerSize, STREAM_SEEK_SET, NULL));\r
+  if (!inBuffer.Create(1 << 17))\r
+    return E_OUTOFMEMORY;\r
+  inBuffer.SetStream(stream);\r
+  inBuffer.Init();\r
+\r
+  CInArchiveInfo &ai = db.ArchiveInfo;\r
+\r
+  ai.Size = Read32();\r
+  if (Read32() != 0)\r
+    return S_FALSE;\r
+  ai.FileHeadersOffset = Read32();\r
+  if (Read32() != 0)\r
+    return S_FALSE;\r
+\r
+  ai.VersionMinor = Read8();\r
+  ai.VersionMajor = Read8();\r
+  ai.NumFolders = Read16();\r
+  ai.NumFiles = Read16();\r
+  ai.Flags = Read16();\r
+  if (ai.Flags > 7)\r
+    return S_FALSE;\r
+  ai.SetID = Read16();\r
+  ai.CabinetNumber = Read16();\r
+\r
+  if (ai.ReserveBlockPresent())\r
+  {\r
+    ai.PerCabinetAreaSize = Read16();\r
+    ai.PerFolderAreaSize = Read8();\r
+    ai.PerDataBlockAreaSize = Read8();\r
+\r
+    Skip(ai.PerCabinetAreaSize);\r
+  }\r
+\r
+  {\r
+    if (ai.IsTherePrev())\r
+      ReadOtherArchive(ai.PrevArc);\r
+    if (ai.IsThereNext())\r
+      ReadOtherArchive(ai.NextArc);\r
+  }\r
+  \r
+  int i;\r
+  for (i = 0; i < ai.NumFolders; i++)\r
+  {\r
+    CFolder folder;\r
+\r
+    folder.DataStart = Read32();\r
+    folder.NumDataBlocks = Read16();\r
+    folder.CompressionTypeMajor = Read8();\r
+    folder.CompressionTypeMinor = Read8();\r
+\r
+    Skip(ai.PerFolderAreaSize);\r
+    db.Folders.Add(folder);\r
+  }\r
+  \r
+  RINOK(stream->Seek(db.StartPosition + ai.FileHeadersOffset, STREAM_SEEK_SET, NULL));\r
+\r
+  inBuffer.SetStream(stream);\r
+  inBuffer.Init();\r
+  for (i = 0; i < ai.NumFiles; i++)\r
+  {\r
+    CItem item;\r
+    item.Size = Read32();\r
+    item.Offset = Read32();\r
+    item.FolderIndex = Read16();\r
+    UInt16 pureDate = Read16();\r
+    UInt16 pureTime = Read16();\r
+    item.Time = ((UInt32(pureDate) << 16)) | pureTime;\r
+    item.Attributes = Read16();\r
+    item.Name = SafeReadName();\r
+    int folderIndex = item.GetFolderIndex(db.Folders.Size());\r
+    if (folderIndex >= db.Folders.Size())\r
+      return S_FALSE;\r
+    db.Items.Add(item);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }\r
+\r
+static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param)\r
+{\r
+  const CMvDatabaseEx &mvDb = *(const CMvDatabaseEx *)param;\r
+  const CDatabaseEx &db1 = mvDb.Volumes[p1->VolumeIndex];\r
+  const CDatabaseEx &db2 = mvDb.Volumes[p2->VolumeIndex];\r
+  const CItem &item1 = db1.Items[p1->ItemIndex];\r
+  const CItem &item2 = db2.Items[p2->ItemIndex];;\r
+  bool isDir1 = item1.IsDir();\r
+  bool isDir2 = item2.IsDir();\r
+  if (isDir1 && !isDir2)\r
+    return -1;\r
+  if (isDir2 && !isDir1)\r
+    return 1;\r
+  int f1 = mvDb.GetFolderIndex(p1);\r
+  int f2 = mvDb.GetFolderIndex(p2);\r
+  RINOZ(MyCompare(f1, f2));\r
+  RINOZ(MyCompare(item1.Offset, item2.Offset));\r
+  RINOZ(MyCompare(item1.Size, item2.Size));\r
+  RINOZ(MyCompare(p1->VolumeIndex, p2->VolumeIndex));\r
+  return MyCompare(p1->ItemIndex, p2->ItemIndex);\r
+}\r
+\r
+bool CMvDatabaseEx::AreItemsEqual(int i1, int i2)\r
+{\r
+  const CMvItem *p1 = &Items[i1];\r
+  const CMvItem *p2 = &Items[i2];\r
+  const CDatabaseEx &db1 = Volumes[p1->VolumeIndex];\r
+  const CDatabaseEx &db2 = Volumes[p2->VolumeIndex];\r
+  const CItem &item1 = db1.Items[p1->ItemIndex];\r
+  const CItem &item2 = db2.Items[p2->ItemIndex];;\r
+  return GetFolderIndex(p1) == GetFolderIndex(p2) &&\r
+    item1.Offset == item2.Offset &&\r
+    item1.Size == item2.Size &&\r
+    item1.Name == item2.Name;\r
+}\r
+\r
+void CMvDatabaseEx::FillSortAndShrink()\r
+{\r
+  Items.Clear();\r
+  StartFolderOfVol.Clear();\r
+  FolderStartFileIndex.Clear();\r
+  int offset = 0;\r
+  for (int v = 0; v < Volumes.Size(); v++)\r
+  {\r
+    const CDatabaseEx &db = Volumes[v];\r
+    int curOffset = offset;\r
+    if (db.IsTherePrevFolder())\r
+      curOffset--;\r
+    StartFolderOfVol.Add(curOffset);\r
+    offset += db.GetNumberOfNewFolders();\r
+\r
+    CMvItem mvItem;\r
+    mvItem.VolumeIndex = v;\r
+    for (int i = 0 ; i < db.Items.Size(); i++)\r
+    {\r
+      mvItem.ItemIndex = i;\r
+      Items.Add(mvItem);\r
+    }\r
+  }\r
+\r
+  Items.Sort(CompareMvItems, (void *)this);\r
+  int j = 1;\r
+  int i;\r
+  for (i = 1; i < Items.Size(); i++)\r
+    if (!AreItemsEqual(i, i -1))\r
+      Items[j++] = Items[i];\r
+  Items.DeleteFrom(j);\r
+\r
+  for (i = 0; i < Items.Size(); i++)\r
+  {\r
+    int folderIndex = GetFolderIndex(&Items[i]);\r
+    if (folderIndex >= FolderStartFileIndex.Size())\r
+      FolderStartFileIndex.Add(i);\r
+  }\r
+}\r
+\r
+bool CMvDatabaseEx::Check()\r
+{\r
+  for (int v = 1; v < Volumes.Size(); v++)\r
+  {\r
+    const CDatabaseEx &db1 = Volumes[v];\r
+    if (db1.IsTherePrevFolder())\r
+    {\r
+      const CDatabaseEx &db0 = Volumes[v - 1];\r
+      if (db0.Folders.IsEmpty() || db1.Folders.IsEmpty())\r
+        return false;\r
+      const CFolder &f0 = db0.Folders.Back();\r
+      const CFolder &f1 = db1.Folders.Front();\r
+      if (f0.CompressionTypeMajor != f1.CompressionTypeMajor ||\r
+          f0.CompressionTypeMinor != f1.CompressionTypeMinor)\r
+        return false;\r
+    }\r
+  }\r
+  UInt32 beginPos = 0;\r
+  UInt64 endPos = 0;\r
+  int prevFolder = -2;\r
+  for (int i = 0; i < Items.Size(); i++)\r
+  {\r
+    const CMvItem &mvItem = Items[i];\r
+    int fIndex = GetFolderIndex(&mvItem);\r
+    if (fIndex >= FolderStartFileIndex.Size())\r
+      return false;\r
+    const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];\r
+    if (item.IsDir())\r
+      continue;\r
+    int folderIndex = GetFolderIndex(&mvItem);\r
+    if (folderIndex != prevFolder)\r
+      prevFolder = folderIndex;\r
+    else if (item.Offset < endPos &&\r
+        (item.Offset != beginPos || item.GetEndOffset() != endPos))\r
+      return false;\r
+    beginPos = item.Offset;\r
+    endPos = item.GetEndOffset();\r
+  }\r
+  return true;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Cab/CabIn.h b/CPP/7zip/Archive/Cab/CabIn.h
new file mode 100755 (executable)
index 0000000..a672989
--- /dev/null
@@ -0,0 +1,161 @@
+// Archive/CabIn.h\r
+\r
+#ifndef __ARCHIVE_CAB_IN_H\r
+#define __ARCHIVE_CAB_IN_H\r
+\r
+#include "../../IStream.h"\r
+#include "../../Common/InBuffer.h"\r
+#include "CabHeader.h"\r
+#include "CabItem.h"\r
+\r
+namespace NArchive {\r
+namespace NCab {\r
+\r
+class CInArchiveException\r
+{\r
+public:\r
+  enum CCauseType\r
+  {\r
+    kUnexpectedEndOfArchive = 0,\r
+    kIncorrectArchive,\r
+    kUnsupported\r
+  } Cause;\r
+  CInArchiveException(CCauseType cause) : Cause(cause) {}\r
+};\r
+\r
+struct COtherArchive\r
+{\r
+  AString FileName;\r
+  AString DiskName;\r
+};\r
+\r
+struct CArchiveInfo\r
+{\r
+  Byte VersionMinor; /* cabinet file format version, minor */\r
+  Byte VersionMajor; /* cabinet file format version, major */\r
+  UInt16 NumFolders; /* number of CFFOLDER entries in this cabinet */\r
+  UInt16 NumFiles;   /* number of CFFILE entries in this cabinet */\r
+  UInt16 Flags;      /* cabinet file option indicators */\r
+  UInt16 SetID;      /* must be the same for all cabinets in a set */\r
+  UInt16 CabinetNumber; /* number of this cabinet file in a set */\r
+\r
+  bool ReserveBlockPresent() const { return (Flags & NHeader::NArchive::NFlags::kReservePresent) != 0; }\r
+\r
+  bool IsTherePrev() const { return (Flags & NHeader::NArchive::NFlags::kPrevCabinet) != 0; }\r
+  bool IsThereNext() const { return (Flags & NHeader::NArchive::NFlags::kNextCabinet) != 0; }\r
+\r
+  UInt16 PerCabinetAreaSize; // (optional) size of per-cabinet reserved area\r
+  Byte PerFolderAreaSize;    // (optional) size of per-folder reserved area\r
+  Byte PerDataBlockAreaSize; // (optional) size of per-datablock reserved area\r
+\r
+  Byte GetDataBlockReserveSize() const { return (Byte)(ReserveBlockPresent() ? PerDataBlockAreaSize : 0); }\r
+\r
+  COtherArchive PrevArc;\r
+  COtherArchive NextArc;\r
+\r
+  CArchiveInfo()\r
+  {\r
+    Clear();\r
+  }\r
+\r
+  void Clear()\r
+  {\r
+    PerCabinetAreaSize = 0;\r
+    PerFolderAreaSize = 0;\r
+    PerDataBlockAreaSize = 0;\r
+  }\r
+};\r
+\r
+struct CInArchiveInfo: public CArchiveInfo\r
+{\r
+  UInt32 Size; /* size of this cabinet file in bytes */\r
+  UInt32 FileHeadersOffset; // offset of the first CFFILE entry\r
+};\r
+\r
+\r
+struct CDatabase\r
+{\r
+  UInt64 StartPosition;\r
+  CInArchiveInfo ArchiveInfo;\r
+  CObjectVector<CFolder> Folders;\r
+  CObjectVector<CItem> Items;\r
+  \r
+  void Clear()\r
+  {\r
+    ArchiveInfo.Clear();\r
+    Folders.Clear();\r
+    Items.Clear();\r
+  }\r
+  bool IsTherePrevFolder() const\r
+  {\r
+    for (int i = 0; i < Items.Size(); i++)\r
+      if (Items[i].ContinuedFromPrev())\r
+        return true;\r
+    return false;\r
+  }\r
+  int GetNumberOfNewFolders() const\r
+  {\r
+    int res = Folders.Size();\r
+    if (IsTherePrevFolder())\r
+      res--;\r
+    return res;\r
+  }\r
+  UInt32 GetFileOffset(int index) const { return Items[index].Offset; }\r
+  UInt32 GetFileSize(int index) const { return Items[index].Size; }\r
+};\r
+\r
+struct CDatabaseEx: public CDatabase\r
+{\r
+  CMyComPtr<IInStream> Stream;\r
+};\r
+\r
+struct CMvItem\r
+{\r
+  int VolumeIndex;\r
+  int ItemIndex;\r
+};\r
+\r
+class CMvDatabaseEx\r
+{\r
+  bool AreItemsEqual(int i1, int i2);\r
+public:\r
+  CObjectVector<CDatabaseEx> Volumes;\r
+  CRecordVector<CMvItem> Items;\r
+  CRecordVector<int> StartFolderOfVol;\r
+  CRecordVector<int> FolderStartFileIndex;\r
+  \r
+  int GetFolderIndex(const CMvItem *mvi) const\r
+  {\r
+    const CDatabaseEx &db = Volumes[mvi->VolumeIndex];\r
+    return StartFolderOfVol[mvi->VolumeIndex] +\r
+        db.Items[mvi->ItemIndex].GetFolderIndex(db.Folders.Size());\r
+  }\r
+  void Clear()\r
+  {\r
+    Volumes.Clear();\r
+    Items.Clear();\r
+    StartFolderOfVol.Clear();\r
+    FolderStartFileIndex.Clear();\r
+  }\r
+  void FillSortAndShrink();\r
+  bool Check();\r
+};\r
+\r
+class CInArchive\r
+{\r
+  CInBuffer inBuffer;\r
+\r
+  Byte Read8();\r
+  UInt16 Read16();\r
+  UInt32 Read32();\r
+  AString SafeReadName();\r
+  void Skip(UInt32 size);\r
+  void ReadOtherArchive(COtherArchive &oa);\r
+\r
+public:\r
+  HRESULT Open(const UInt64 *searchHeaderSizeLimit, CDatabaseEx &db);\r
+};\r
+  \r
+}}\r
+  \r
+#endif\r
diff --git a/CPP/7zip/Archive/Cab/CabItem.h b/CPP/7zip/Archive/Cab/CabItem.h
new file mode 100755 (executable)
index 0000000..98a0f9b
--- /dev/null
@@ -0,0 +1,63 @@
+// Archive/CabItem.h\r
+\r
+#ifndef __ARCHIVE_CAB_ITEM_H\r
+#define __ARCHIVE_CAB_ITEM_H\r
+\r
+#include "Common/Types.h"\r
+#include "Common/MyString.h"\r
+#include "CabHeader.h"\r
+\r
+namespace NArchive {\r
+namespace NCab {\r
+\r
+struct CFolder\r
+{\r
+  UInt32 DataStart; // offset of the first CFDATA block in this folder\r
+  UInt16 NumDataBlocks; // number of CFDATA blocks in this folder\r
+  Byte CompressionTypeMajor;\r
+  Byte CompressionTypeMinor;\r
+  Byte GetCompressionMethod() const { return (Byte)(CompressionTypeMajor & 0xF); }\r
+};\r
+\r
+struct CItem\r
+{\r
+  AString Name;\r
+  UInt32 Offset;\r
+  UInt32 Size;\r
+  UInt32 Time;\r
+  UInt16 FolderIndex;\r
+  UInt16 Flags;\r
+  UInt16 Attributes;\r
+  \r
+  UInt64 GetEndOffset() const { return (UInt64)Offset + Size; }\r
+  UInt32 GetWinAttributes() const { return (Attributes & ~NHeader::kFileNameIsUTFAttributeMask); }\r
+  bool IsNameUTF() const { return (Attributes & NHeader::kFileNameIsUTFAttributeMask) != 0; }\r
+  bool IsDir() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; }\r
+\r
+  bool ContinuedFromPrev() const\r
+  {\r
+    return\r
+      (FolderIndex == NHeader::NFolderIndex::kContinuedFromPrev) ||\r
+      (FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext);\r
+  }\r
+  \r
+  bool ContinuedToNext() const\r
+  {\r
+    return\r
+      (FolderIndex == NHeader::NFolderIndex::kContinuedToNext) ||\r
+      (FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext);\r
+  }\r
+\r
+  int GetFolderIndex(int numFolders) const\r
+  {\r
+    if (ContinuedFromPrev())\r
+      return 0;\r
+    if (ContinuedToNext())\r
+      return (numFolders - 1);\r
+    return FolderIndex;\r
+  }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Cab/CabRegister.cpp b/CPP/7zip/Archive/Cab/CabRegister.cpp
new file mode 100755 (executable)
index 0000000..eb27d04
--- /dev/null
@@ -0,0 +1,13 @@
+// CabRegister.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/RegisterArc.h"\r
+\r
+#include "CabHandler.h"\r
+static IInArchive *CreateArc() { return new NArchive::NCab::CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"Cab", L"cab", 0, 8, { 0x4D, 0x53, 0x43, 0x46 }, 4, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Cab)\r
diff --git a/CPP/7zip/Archive/Cab/StdAfx.h b/CPP/7zip/Archive/Cab/StdAfx.h
new file mode 100755 (executable)
index 0000000..83fdd22
--- /dev/null
@@ -0,0 +1,8 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Chm/ChmHandler.cpp b/CPP/7zip/Archive/Chm/ChmHandler.cpp
new file mode 100755 (executable)
index 0000000..24f88b6
--- /dev/null
@@ -0,0 +1,721 @@
+// ChmHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/Defs.h"\r
+#include "Common/StringConvert.h"\r
+#include "Common/UTFConvert.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../../Common/LimitedStreams.h"\r
+#include "../../Common/ProgressUtils.h"\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "../../Compress/CopyCoder.h"\r
+#include "../../Compress/LzxDecoder.h"\r
+\r
+#include "../Common/ItemNameUtils.h"\r
+\r
+#include "ChmHandler.h"\r
+\r
+using namespace NWindows;\r
+using namespace NTime;\r
+\r
+namespace NArchive {\r
+namespace NChm {\r
+\r
+// #define _CHM_DETAILS\r
+\r
+#ifdef _CHM_DETAILS\r
+\r
+enum\r
+{\r
+  kpidSection = kpidUserDefined\r
+};\r
+\r
+#endif\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidMethod, VT_BSTR},\r
+  { NULL, kpidBlock, VT_UI4}\r
+  \r
+  #ifdef _CHM_DETAILS\r
+  ,\r
+  { L"Section", kpidSection, VT_UI4},\r
+  { NULL, kpidOffset, VT_UI4}\r
+  #endif\r
+};\r
+\r
+STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidNumBlocks, VT_UI8}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+\r
+IMP_IInArchive_ArcProps_NO\r
+/*\r
+IMP_IInArchive_ArcProps\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidNumBlocks:\r
+    {\r
+      UInt64 numBlocks = 0;\r
+      for (int i = 0; i < m_Database.Sections.Size(); i++)\r
+      {\r
+        const CSectionInfo &s = m_Database.Sections[i];\r
+        for (int j = 0; j < s.Methods.Size(); j++)\r
+        {\r
+          const CMethodInfo &m = s.Methods[j];\r
+          if (m.IsLzx())\r
+            numBlocks += m.LzxInfo.ResetTable.GetNumBlocks();\r
+        }\r
+      }\r
+      prop = numBlocks;\r
+      break;\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+*/\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID,  PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  if (m_Database.NewFormat)\r
+  {\r
+    switch(propID)\r
+    {\r
+      case kpidSize:\r
+        prop = (UInt64)m_Database.NewFormatString.Length();\r
+      break;\r
+    }\r
+    prop.Detach(value);\r
+    return S_OK;\r
+  }\r
+  int entryIndex;\r
+  if (m_Database.LowLevel)\r
+    entryIndex = index;\r
+  else\r
+    entryIndex = m_Database.Indices[index];\r
+  const CItem &item = m_Database.Items[entryIndex];\r
+  switch(propID)\r
+  {\r
+    case kpidPath:\r
+    {\r
+      UString us;\r
+      if (ConvertUTF8ToUnicode(item.Name, us))\r
+      {\r
+        if (!m_Database.LowLevel)\r
+        {\r
+          if (us.Length() > 1)\r
+            if (us[0] == L'/')\r
+              us.Delete(0);\r
+        }\r
+        prop = NItemName::GetOSName2(us);\r
+      }\r
+      break;\r
+    }\r
+    case kpidIsDir:  prop = item.IsDir(); break;\r
+    case kpidSize:  prop = item.Size; break;\r
+    case kpidMethod:\r
+    {\r
+      if (!item.IsDir())\r
+        if (item.Section == 0)\r
+          prop = L"Copy";\r
+        else if (item.Section < m_Database.Sections.Size())\r
+          prop = m_Database.Sections[(int)item.Section].GetMethodName();\r
+      break;\r
+    }\r
+    case kpidBlock:\r
+      if (m_Database.LowLevel)\r
+        prop = item.Section;\r
+      else if (item.Section != 0)\r
+        prop = m_Database.GetFolder(index);\r
+      break;\r
+    \r
+    #ifdef _CHM_DETAILS\r
+    \r
+    case kpidSection:  prop = (UInt32)item.Section; break;\r
+    case kpidOffset:  prop = (UInt32)item.Offset; break;\r
+\r
+    #endif\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+class CProgressImp: public CProgressVirt\r
+{\r
+  CMyComPtr<IArchiveOpenCallback> _callback;\r
+public:\r
+  STDMETHOD(SetTotal)(const UInt64 *numFiles);\r
+  STDMETHOD(SetCompleted)(const UInt64 *numFiles);\r
+  CProgressImp(IArchiveOpenCallback *callback): _callback(callback) {};\r
+};\r
+\r
+STDMETHODIMP CProgressImp::SetTotal(const UInt64 *numFiles)\r
+{\r
+  if (_callback)\r
+    return _callback->SetCompleted(numFiles, NULL);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CProgressImp::SetCompleted(const UInt64 *numFiles)\r
+{\r
+  if (_callback)\r
+    return _callback->SetCompleted(numFiles, NULL);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *inStream,\r
+    const UInt64 *maxCheckStartPosition,\r
+    IArchiveOpenCallback * /* openArchiveCallback */)\r
+{\r
+  COM_TRY_BEGIN\r
+  m_Stream.Release();\r
+  try\r
+  {\r
+    CInArchive archive;\r
+    // CProgressImp progressImp(openArchiveCallback);\r
+    RINOK(archive.Open(inStream, maxCheckStartPosition, m_Database));\r
+    /*\r
+    if (m_Database.LowLevel)\r
+      return S_FALSE;\r
+    */\r
+    m_Stream = inStream;\r
+  }\r
+  catch(...)\r
+  {\r
+    return S_FALSE;\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  m_Database.Clear();\r
+  m_Stream.Release();\r
+  return S_OK;\r
+}\r
+\r
+class CChmFolderOutStream:\r
+  public ISequentialOutStream,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP\r
+\r
+  HRESULT Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK);\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+\r
+  UInt64 m_FolderSize;\r
+  UInt64 m_PosInFolder;\r
+  UInt64 m_PosInSection;\r
+  const CRecordVector<bool> *m_ExtractStatuses;\r
+  int m_StartIndex;\r
+  int m_CurrentIndex;\r
+  int m_NumFiles;\r
+\r
+private:\r
+  const CFilesDatabase *m_Database;\r
+  CMyComPtr<IArchiveExtractCallback> m_ExtractCallback;\r
+  bool m_TestMode;\r
+\r
+  bool m_IsOk;\r
+  bool m_FileIsOpen;\r
+  UInt64 m_RemainFileSize;\r
+  CMyComPtr<ISequentialOutStream> m_RealOutStream;\r
+\r
+  HRESULT OpenFile();\r
+  HRESULT WriteEmptyFiles();\r
+public:\r
+  void Init(\r
+    const CFilesDatabase *database,\r
+    IArchiveExtractCallback *extractCallback,\r
+    bool testMode);\r
+  HRESULT FlushCorrupted(UInt64 maxSize);\r
+};\r
+\r
+void CChmFolderOutStream::Init(\r
+    const CFilesDatabase *database,\r
+    IArchiveExtractCallback *extractCallback,\r
+    bool testMode)\r
+{\r
+  m_Database = database;\r
+  m_ExtractCallback = extractCallback;\r
+  m_TestMode = testMode;\r
+\r
+  m_CurrentIndex = 0;\r
+  m_FileIsOpen = false;\r
+}\r
+\r
+HRESULT CChmFolderOutStream::OpenFile()\r
+{\r
+  Int32 askMode = (*m_ExtractStatuses)[m_CurrentIndex] ? (m_TestMode ?\r
+      NExtract::NAskMode::kTest :\r
+      NExtract::NAskMode::kExtract) :\r
+      NExtract::NAskMode::kSkip;\r
+  m_RealOutStream.Release();\r
+  RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode));\r
+  if (!m_RealOutStream && !m_TestMode)\r
+    askMode = NExtract::NAskMode::kSkip;\r
+  return m_ExtractCallback->PrepareOperation(askMode);\r
+}\r
+\r
+HRESULT CChmFolderOutStream::WriteEmptyFiles()\r
+{\r
+  if (m_FileIsOpen)\r
+    return S_OK;\r
+  for (;m_CurrentIndex < m_NumFiles; m_CurrentIndex++)\r
+  {\r
+    UInt64 fileSize = m_Database->GetFileSize(m_StartIndex + m_CurrentIndex);\r
+    if (fileSize != 0)\r
+      return S_OK;\r
+    HRESULT result = OpenFile();\r
+    m_RealOutStream.Release();\r
+    RINOK(result);\r
+    RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+// This is WritePart function\r
+HRESULT CChmFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK)\r
+{\r
+  UInt32 realProcessed = 0;\r
+  if (processedSize != NULL)\r
+   *processedSize = 0;\r
+  while(size != 0)\r
+  {\r
+    if (m_FileIsOpen)\r
+    {\r
+      UInt32 numBytesToWrite = (UInt32)MyMin(m_RemainFileSize, (UInt64)(size));\r
+      HRESULT res = S_OK;\r
+      if (numBytesToWrite > 0)\r
+      {\r
+        if (!isOK)\r
+          m_IsOk = false;\r
+        if (m_RealOutStream)\r
+        {\r
+          UInt32 processedSizeLocal = 0;\r
+          res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal);\r
+          numBytesToWrite = processedSizeLocal;\r
+        }\r
+      }\r
+      realProcessed += numBytesToWrite;\r
+      if (processedSize != NULL)\r
+        *processedSize = realProcessed;\r
+      data = (const void *)((const Byte *)data + numBytesToWrite);\r
+      size -= numBytesToWrite;\r
+      m_RemainFileSize -= numBytesToWrite;\r
+      m_PosInSection += numBytesToWrite;\r
+      m_PosInFolder += numBytesToWrite;\r
+      if (res != S_OK)\r
+        return res;\r
+      if (m_RemainFileSize == 0)\r
+      {\r
+        m_RealOutStream.Release();\r
+        RINOK(m_ExtractCallback->SetOperationResult(\r
+          m_IsOk ?\r
+            NExtract::NOperationResult::kOK:\r
+            NExtract::NOperationResult::kDataError));\r
+        m_FileIsOpen = false;\r
+      }\r
+      if (realProcessed > 0)\r
+        break; // with this break this function works as write part\r
+    }\r
+    else\r
+    {\r
+      if (m_CurrentIndex >= m_NumFiles)\r
+        return E_FAIL;\r
+      int fullIndex = m_StartIndex + m_CurrentIndex;\r
+      m_RemainFileSize = m_Database->GetFileSize(fullIndex);\r
+      UInt64 fileOffset = m_Database->GetFileOffset(fullIndex);\r
+      if (fileOffset < m_PosInSection)\r
+        return E_FAIL;\r
+      if (fileOffset > m_PosInSection)\r
+      {\r
+        UInt32 numBytesToWrite = (UInt32)MyMin(fileOffset - m_PosInSection, UInt64(size));\r
+        realProcessed += numBytesToWrite;\r
+        if (processedSize != NULL)\r
+          *processedSize = realProcessed;\r
+        data = (const void *)((const Byte *)data + numBytesToWrite);\r
+        size -= numBytesToWrite;\r
+        m_PosInSection += numBytesToWrite;\r
+        m_PosInFolder += numBytesToWrite;\r
+      }\r
+      if (fileOffset == m_PosInSection)\r
+      {\r
+        RINOK(OpenFile());\r
+        m_FileIsOpen = true;\r
+        m_CurrentIndex++;\r
+        m_IsOk = true;\r
+      }\r
+    }\r
+  }\r
+  return WriteEmptyFiles();\r
+}\r
+\r
+STDMETHODIMP CChmFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  return Write2(data, size, processedSize, true);\r
+}\r
+\r
+HRESULT CChmFolderOutStream::FlushCorrupted(UInt64 maxSize)\r
+{\r
+  const UInt32 kBufferSize = (1 << 10);\r
+  Byte buffer[kBufferSize];\r
+  for (int i = 0; i < kBufferSize; i++)\r
+    buffer[i] = 0;\r
+  if (maxSize > m_FolderSize)\r
+    maxSize = m_FolderSize;\r
+  while (m_PosInFolder < maxSize)\r
+  {\r
+    UInt32 size = (UInt32)MyMin(maxSize - m_PosInFolder, (UInt64)kBufferSize);\r
+    UInt32 processedSizeLocal = 0;\r
+    RINOK(Write2(buffer, size, &processedSizeLocal, false));\r
+    if (processedSizeLocal == 0)\r
+      return S_OK;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testModeSpec, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+\r
+  if (allFilesMode)\r
+    numItems = m_Database.NewFormat ? 1:\r
+      (m_Database.LowLevel ?\r
+      m_Database.Items.Size():\r
+      m_Database.Indices.Size());\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  bool testMode = (testModeSpec != 0);\r
+\r
+  UInt64 currentTotalSize = 0;\r
+\r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+  UInt32 i;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);\r
+  streamSpec->SetStream(m_Stream);\r
+\r
+  if (m_Database.LowLevel)\r
+  {\r
+    UInt64 currentItemSize = 0;\r
+    UInt64 totalSize = 0;\r
+    if (m_Database.NewFormat)\r
+      totalSize = m_Database.NewFormatString.Length();\r
+    else\r
+      for (i = 0; i < numItems; i++)\r
+        totalSize += m_Database.Items[allFilesMode ? i : indices[i]].Size;\r
+    extractCallback->SetTotal(totalSize);\r
+    \r
+    for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)\r
+    {\r
+      currentItemSize = 0;\r
+      lps->InSize = currentTotalSize; // Change it\r
+      lps->OutSize = currentTotalSize;\r
+\r
+      RINOK(lps->SetCur());\r
+      CMyComPtr<ISequentialOutStream> realOutStream;\r
+      Int32 askMode= testMode ?\r
+          NExtract::NAskMode::kTest :\r
+          NExtract::NAskMode::kExtract;\r
+      Int32 index = allFilesMode ? i : indices[i];\r
+      RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+\r
+      if (m_Database.NewFormat)\r
+      {\r
+        if (index != 0)\r
+          return E_FAIL;\r
+        if (!testMode && !realOutStream)\r
+          continue;\r
+        if (!testMode)\r
+        {\r
+          UInt32 size = m_Database.NewFormatString.Length();\r
+          RINOK(WriteStream(realOutStream, (const char *)m_Database.NewFormatString, size));\r
+        }\r
+        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+        continue;\r
+      }\r
+      const CItem &item = m_Database.Items[index];\r
+      \r
+      currentItemSize = item.Size;\r
+      \r
+      if (!testMode && !realOutStream)\r
+        continue;\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      if (item.Section != 0)\r
+      {\r
+        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));\r
+        continue;\r
+      }\r
+\r
+      if (testMode)\r
+      {\r
+        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+        continue;\r
+      }\r
+      \r
+      RINOK(m_Stream->Seek(m_Database.ContentOffset + item.Offset, STREAM_SEEK_SET, NULL));\r
+      streamSpec->Init(item.Size);\r
+      \r
+      RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));\r
+      realOutStream.Release();\r
+      RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ?\r
+          NExtract::NOperationResult::kOK:\r
+          NExtract::NOperationResult::kDataError));\r
+    }\r
+    return S_OK;\r
+  }\r
+  \r
+  UInt64 lastFolderIndex = ((UInt64)0 - 1);\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    UInt32 index = allFilesMode ? i : indices[i];\r
+    int entryIndex = m_Database.Indices[index];\r
+    const CItem &item = m_Database.Items[entryIndex];\r
+    UInt64 sectionIndex = item.Section;\r
+    if (item.IsDir() || item.Size == 0)\r
+      continue;\r
+    if (sectionIndex == 0)\r
+    {\r
+      currentTotalSize += item.Size;\r
+      continue;\r
+    }\r
+    const CSectionInfo &section = m_Database.Sections[(int)item.Section];\r
+    if (section.IsLzx())\r
+    {\r
+      const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo;\r
+      UInt64 folderIndex = m_Database.GetFolder(index);\r
+      if (lastFolderIndex == folderIndex)\r
+        folderIndex++;\r
+      lastFolderIndex = m_Database.GetLastFolder(index);\r
+      for (; folderIndex <= lastFolderIndex; folderIndex++)\r
+        currentTotalSize += lzxInfo.GetFolderSize();\r
+    }\r
+  }\r
+\r
+  RINOK(extractCallback->SetTotal(currentTotalSize));\r
+\r
+  NCompress::NLzx::CDecoder *lzxDecoderSpec = 0;\r
+  CMyComPtr<ICompressCoder> lzxDecoder;\r
+  CChmFolderOutStream *chmFolderOutStream = 0;\r
+  CMyComPtr<ISequentialOutStream> outStream;\r
+\r
+  currentTotalSize = 0;\r
+\r
+  CRecordVector<bool> extractStatuses;\r
+  for (i = 0; i < numItems;)\r
+  {\r
+    RINOK(extractCallback->SetCompleted(&currentTotalSize));\r
+    UInt32 index = allFilesMode ? i : indices[i];\r
+    i++;\r
+    int entryIndex = m_Database.Indices[index];\r
+    const CItem &item = m_Database.Items[entryIndex];\r
+    UInt64 sectionIndex = item.Section;\r
+    Int32 askMode= testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    if (item.IsDir())\r
+    {\r
+      CMyComPtr<ISequentialOutStream> realOutStream;\r
+      RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      realOutStream.Release();\r
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+      continue;\r
+    }\r
+\r
+    lps->InSize = currentTotalSize; // Change it\r
+    lps->OutSize = currentTotalSize;\r
+\r
+    if (item.Size == 0 || sectionIndex == 0)\r
+    {\r
+      CMyComPtr<ISequentialOutStream> realOutStream;\r
+      RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+      if (!testMode && !realOutStream)\r
+        continue;\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      Int32 opRes = NExtract::NOperationResult::kOK;\r
+      if (!testMode && item.Size != 0)\r
+      {\r
+        RINOK(m_Stream->Seek(m_Database.ContentOffset + item.Offset, STREAM_SEEK_SET, NULL));\r
+        streamSpec->Init(item.Size);\r
+        RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));\r
+        if (copyCoderSpec->TotalSize != item.Size)\r
+          opRes = NExtract::NOperationResult::kDataError;\r
+      }\r
+      realOutStream.Release();\r
+      RINOK(extractCallback->SetOperationResult(opRes));\r
+      currentTotalSize += item.Size;\r
+      continue;\r
+    }\r
+  \r
+    const CSectionInfo &section = m_Database.Sections[(int)sectionIndex];\r
+\r
+    if (!section.IsLzx())\r
+    {\r
+      CMyComPtr<ISequentialOutStream> realOutStream;\r
+      RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+      if (!testMode && !realOutStream)\r
+        continue;\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));\r
+      continue;\r
+    }\r
+\r
+    const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo;\r
+\r
+    if (chmFolderOutStream == 0)\r
+    {\r
+      chmFolderOutStream = new CChmFolderOutStream;\r
+      outStream = chmFolderOutStream;\r
+    }\r
+\r
+    chmFolderOutStream->Init(&m_Database, extractCallback, testMode);\r
+\r
+    if (lzxDecoderSpec == NULL)\r
+    {\r
+      lzxDecoderSpec = new NCompress::NLzx::CDecoder;\r
+      lzxDecoder = lzxDecoderSpec;\r
+    }\r
+\r
+    UInt64 folderIndex = m_Database.GetFolder(index);\r
+\r
+    UInt64 compressedPos = m_Database.ContentOffset + section.Offset;\r
+    UInt32 numDictBits = lzxInfo.GetNumDictBits();\r
+    RINOK(lzxDecoderSpec->SetParams(numDictBits));\r
+\r
+    const CItem *lastItem = &item;\r
+    extractStatuses.Clear();\r
+    extractStatuses.Add(true);\r
+\r
+    for (;; folderIndex++)\r
+    {\r
+      RINOK(extractCallback->SetCompleted(&currentTotalSize));\r
+\r
+      UInt64 startPos = lzxInfo.GetFolderPos(folderIndex);\r
+      UInt64 finishPos = lastItem->Offset + lastItem->Size;\r
+      UInt64 limitFolderIndex = lzxInfo.GetFolder(finishPos);\r
+\r
+      lastFolderIndex = m_Database.GetLastFolder(index);\r
+      UInt64 folderSize = lzxInfo.GetFolderSize();\r
+      UInt64 unPackSize = folderSize;\r
+      if (extractStatuses.IsEmpty())\r
+        chmFolderOutStream->m_StartIndex = index + 1;\r
+      else\r
+        chmFolderOutStream->m_StartIndex = index;\r
+      if (limitFolderIndex == folderIndex)\r
+      {\r
+        for (; i < numItems; i++)\r
+        {\r
+          UInt32 nextIndex = allFilesMode ? i : indices[i];\r
+          int entryIndex = m_Database.Indices[nextIndex];\r
+          const CItem &nextItem = m_Database.Items[entryIndex];\r
+          if (nextItem.Section != sectionIndex)\r
+            break;\r
+          UInt64 nextFolderIndex = m_Database.GetFolder(nextIndex);\r
+          if (nextFolderIndex != folderIndex)\r
+            break;\r
+          for (index++; index < nextIndex; index++)\r
+            extractStatuses.Add(false);\r
+          extractStatuses.Add(true);\r
+          index = nextIndex;\r
+          lastItem = &nextItem;\r
+          if (nextItem.Size != 0)\r
+            finishPos = nextItem.Offset + nextItem.Size;\r
+          lastFolderIndex = m_Database.GetLastFolder(index);\r
+        }\r
+      }\r
+      unPackSize = MyMin(finishPos - startPos, unPackSize);\r
+\r
+      chmFolderOutStream->m_FolderSize = folderSize;\r
+      chmFolderOutStream->m_PosInFolder = 0;\r
+      chmFolderOutStream->m_PosInSection = startPos;\r
+      chmFolderOutStream->m_ExtractStatuses = &extractStatuses;\r
+      chmFolderOutStream->m_NumFiles = extractStatuses.Size();\r
+      chmFolderOutStream->m_CurrentIndex = 0;\r
+      try\r
+      {\r
+        UInt64 startBlock = lzxInfo.GetBlockIndexFromFolderIndex(folderIndex);\r
+        const CResetTable &rt = lzxInfo.ResetTable;\r
+        UInt32 numBlocks = (UInt32)rt.GetNumBlocks(unPackSize);\r
+        for (UInt32 b = 0; b < numBlocks; b++)\r
+        {\r
+          UInt64 completedSize = currentTotalSize + chmFolderOutStream->m_PosInSection - startPos;\r
+          RINOK(extractCallback->SetCompleted(&completedSize));\r
+          UInt64 bCur = startBlock + b;\r
+          if (bCur >= rt.ResetOffsets.Size())\r
+            return E_FAIL;\r
+          UInt64 offset = rt.ResetOffsets[(int)bCur];\r
+          UInt64 compressedSize;\r
+          rt.GetCompressedSizeOfBlock(bCur, compressedSize);\r
+          UInt64 rem = finishPos - chmFolderOutStream->m_PosInSection;\r
+          if (rem > rt.BlockSize)\r
+            rem = rt.BlockSize;\r
+          RINOK(m_Stream->Seek(compressedPos + offset, STREAM_SEEK_SET, NULL));\r
+          streamSpec->SetStream(m_Stream);\r
+          streamSpec->Init(compressedSize);\r
+          lzxDecoderSpec->SetKeepHistory(b > 0);\r
+          HRESULT res = lzxDecoder->Code(inStream, outStream, NULL, &rem, NULL);\r
+          if (res != S_OK)\r
+          {\r
+            if (res != S_FALSE)\r
+              return res;\r
+            throw 1;\r
+          }\r
+        }\r
+      }\r
+      catch(...)\r
+      {\r
+        RINOK(chmFolderOutStream->FlushCorrupted(unPackSize));\r
+      }\r
+      currentTotalSize += folderSize;\r
+      if (folderIndex == lastFolderIndex)\r
+        break;\r
+      extractStatuses.Clear();\r
+    }\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+    *numItems = m_Database.NewFormat ? 1:\r
+      (m_Database.LowLevel ?\r
+      m_Database.Items.Size():\r
+      m_Database.Indices.Size());\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Chm/ChmHandler.h b/CPP/7zip/Archive/Chm/ChmHandler.h
new file mode 100755 (executable)
index 0000000..69075cc
--- /dev/null
@@ -0,0 +1,29 @@
+// ChmHandler.h\r
+\r
+#ifndef __ARCHIVE_CHM_HANDLER_H\r
+#define __ARCHIVE_CHM_HANDLER_H\r
+\r
+#include "Common/MyCom.h"\r
+#include "../IArchive.h"\r
+#include "ChmIn.h"\r
+\r
+namespace NArchive {\r
+namespace NChm {\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP1(IInArchive)\r
+\r
+  INTERFACE_IInArchive(;)\r
+\r
+private:\r
+  CFilesDatabase m_Database;\r
+  CMyComPtr<IInStream> m_Stream;\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Chm/ChmHeader.cpp b/CPP/7zip/Archive/Chm/ChmHeader.cpp
new file mode 100755 (executable)
index 0000000..89b0bfc
--- /dev/null
@@ -0,0 +1,24 @@
+// Archive/Chm/Header.h\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "ChmHeader.h"\r
+\r
+namespace NArchive{\r
+namespace NChm{\r
+namespace NHeader{\r
+\r
+UInt32 kItsfSignature = 0x46535449 + 1;\r
+UInt32 kItolSignature = 0x4C4F5449 + 1;\r
+static class CSignatureInitializer\r
+{\r
+public:\r
+  CSignatureInitializer()\r
+  {\r
+    kItsfSignature--;\r
+    kItolSignature--;\r
+  }\r
+}g_SignatureInitializer;\r
+\r
+\r
+}}}\r
diff --git a/CPP/7zip/Archive/Chm/ChmHeader.h b/CPP/7zip/Archive/Chm/ChmHeader.h
new file mode 100755 (executable)
index 0000000..ad6e0a9
--- /dev/null
@@ -0,0 +1,28 @@
+// Archive/Chm/Header.h\r
+\r
+#ifndef __ARCHIVE_CHM_HEADER_H\r
+#define __ARCHIVE_CHM_HEADER_H\r
+\r
+#include "Common/Types.h"\r
+\r
+namespace NArchive {\r
+namespace NChm {\r
+namespace NHeader{\r
+\r
+const UInt32 kItspSignature = 0x50535449;\r
+const UInt32 kPmglSignature = 0x4C474D50;\r
+const UInt32 kLzxcSignature = 0x43585A4C;\r
+\r
+const UInt32 kIfcmSignature = 0x4D434649;\r
+const UInt32 kAollSignature = 0x4C4C4F41;\r
+const UInt32 kCaolSignature = 0x4C4F4143;\r
+\r
+extern UInt32 kItsfSignature;\r
+\r
+extern UInt32 kItolSignature;\r
+const UInt32 kItlsSignature = 0x534C5449;\r
+UInt64 inline GetHxsSignature() { return ((UInt64)kItlsSignature << 32) | kItolSignature; }\r
+  \r
+}}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Chm/ChmIn.cpp b/CPP/7zip/Archive/Chm/ChmIn.cpp
new file mode 100755 (executable)
index 0000000..78ea590
--- /dev/null
@@ -0,0 +1,937 @@
+// Archive/ChmIn.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/UTFConvert.h"\r
+\r
+#include "../../Common/LimitedStreams.h"\r
+\r
+#include "ChmIn.h"\r
+\r
+namespace NArchive {\r
+namespace NChm {\r
+\r
+// define CHM_LOW, if you want to see low level items\r
+// #define CHM_LOW\r
+\r
+static const GUID kChmLzxGuid   = { 0x7FC28940, 0x9D31, 0x11D0, { 0x9B, 0x27, 0x00, 0xA0, 0xC9, 0x1E, 0x9C, 0x7C } };\r
+static const GUID kHelp2LzxGuid = { 0x0A9007C6, 0x4076, 0x11D3, { 0x87, 0x89, 0x00, 0x00, 0xF8, 0x10, 0x57, 0x54 } };\r
+static const GUID kDesGuid =      { 0x67F6E4A2, 0x60BF, 0x11D3, { 0x85, 0x40, 0x00, 0xC0, 0x4F, 0x58, 0xC3, 0xCF } };\r
+\r
+static bool AreGuidsEqual(REFGUID g1, REFGUID g2)\r
+{\r
+  if (g1.Data1 != g2.Data1 ||\r
+      g1.Data2 != g2.Data2 ||\r
+      g1.Data3 != g2.Data3)\r
+    return false;\r
+  for (int i = 0; i < 8; i++)\r
+    if (g1.Data4[i] != g2.Data4[i])\r
+      return false;\r
+  return true;\r
+}\r
+\r
+static char GetHex(Byte value)\r
+{\r
+  return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));\r
+}\r
+\r
+static void PrintByte(Byte b, AString &s)\r
+{\r
+  s += GetHex(b >> 4);\r
+  s += GetHex(b & 0xF);\r
+}\r
+\r
+static void PrintUInt16(UInt16 v, AString &s)\r
+{\r
+  PrintByte((Byte)(v >> 8), s);\r
+  PrintByte((Byte)v, s);\r
+}\r
+\r
+static void PrintUInt32(UInt32 v, AString &s)\r
+{\r
+  PrintUInt16((UInt16)(v >> 16), s);\r
+  PrintUInt16((UInt16)v, s);\r
+}\r
+\r
+AString CMethodInfo::GetGuidString() const\r
+{\r
+  AString s;\r
+  s += '{';\r
+  PrintUInt32(Guid.Data1, s);\r
+  s += '-';\r
+  PrintUInt16(Guid.Data2, s);\r
+  s += '-';\r
+  PrintUInt16(Guid.Data3, s);\r
+  s += '-';\r
+  PrintByte(Guid.Data4[0], s);\r
+  PrintByte(Guid.Data4[1], s);\r
+  s += '-';\r
+  for (int i = 2; i < 8; i++)\r
+    PrintByte(Guid.Data4[i], s);\r
+  s += '}';\r
+  return s;\r
+}\r
+\r
+bool CMethodInfo::IsLzx() const\r
+{\r
+  if (AreGuidsEqual(Guid, kChmLzxGuid))\r
+    return true;\r
+  return AreGuidsEqual(Guid, kHelp2LzxGuid);\r
+}\r
+\r
+bool CMethodInfo::IsDes() const\r
+{\r
+  return AreGuidsEqual(Guid, kDesGuid);\r
+}\r
+\r
+UString CMethodInfo::GetName() const\r
+{\r
+  UString s;\r
+  if (IsLzx())\r
+  {\r
+    s = L"LZX:";\r
+    wchar_t temp[16];\r
+    ConvertUInt32ToString(LzxInfo.GetNumDictBits(), temp);\r
+    s += temp;\r
+  }\r
+  else\r
+  {\r
+    AString s2;\r
+    if (IsDes())\r
+      s2 = "DES";\r
+    else\r
+    {\r
+      s2 = GetGuidString();\r
+      if (ControlData.GetCapacity() > 0)\r
+      {\r
+        s2 += ':';\r
+        for (size_t i = 0; i < ControlData.GetCapacity(); i++)\r
+          PrintByte(ControlData[i], s2);\r
+      }\r
+    }\r
+    ConvertUTF8ToUnicode(s2, s);\r
+  }\r
+  return s;\r
+}\r
+\r
+bool CSectionInfo::IsLzx() const\r
+{\r
+  if (Methods.Size() != 1)\r
+    return false;\r
+  return Methods[0].IsLzx();\r
+}\r
+\r
+UString CSectionInfo::GetMethodName() const\r
+{\r
+  UString s;\r
+  if (!IsLzx())\r
+  {\r
+    UString temp;\r
+    if (ConvertUTF8ToUnicode(Name, temp))\r
+      s += temp;\r
+    s += L": ";\r
+  }\r
+  for (int i = 0; i < Methods.Size(); i++)\r
+  {\r
+    if (i != 0)\r
+      s += L' ';\r
+    s += Methods[i].GetName();\r
+  }\r
+  return s;\r
+}\r
+\r
+Byte CInArchive::ReadByte()\r
+{\r
+  Byte b;\r
+  if (!_inBuffer.ReadByte(b))\r
+    throw 1;\r
+  return b;\r
+}\r
+\r
+void CInArchive::Skip(size_t size)\r
+{\r
+  while (size-- != 0)\r
+    ReadByte();\r
+}\r
+\r
+void CInArchive::ReadBytes(Byte *data, UInt32 size)\r
+{\r
+  for (UInt32 i = 0; i < size; i++)\r
+    data[i] = ReadByte();\r
+}\r
+\r
+UInt16 CInArchive::ReadUInt16()\r
+{\r
+  UInt16 value = 0;\r
+  for (int i = 0; i < 2; i++)\r
+    value |= ((UInt16)(ReadByte()) << (8 * i));\r
+  return value;\r
+}\r
+\r
+UInt32 CInArchive::ReadUInt32()\r
+{\r
+  UInt32 value = 0;\r
+  for (int i = 0; i < 4; i++)\r
+    value |= ((UInt32)(ReadByte()) << (8 * i));\r
+  return value;\r
+}\r
+\r
+UInt64 CInArchive::ReadUInt64()\r
+{\r
+  UInt64 value = 0;\r
+  for (int i = 0; i < 8; i++)\r
+    value |= ((UInt64)(ReadByte()) << (8 * i));\r
+  return value;\r
+}\r
+\r
+UInt64 CInArchive::ReadEncInt()\r
+{\r
+  UInt64 val = 0;;\r
+  for (int i = 0; i < 10; i++)\r
+  {\r
+    Byte b = ReadByte();\r
+    val |= (b & 0x7F);\r
+    if (b < 0x80)\r
+      return val;\r
+    val <<= 7;\r
+  }\r
+  throw 1;\r
+}\r
+\r
+void CInArchive::ReadGUID(GUID &g)\r
+{\r
+  g.Data1 = ReadUInt32();\r
+  g.Data2 = ReadUInt16();\r
+  g.Data3 = ReadUInt16();\r
+  ReadBytes(g.Data4, 8);\r
+}\r
+\r
+void CInArchive::ReadString(int size, AString &s)\r
+{\r
+  s.Empty();\r
+  while(size-- != 0)\r
+  {\r
+    char c = (char)ReadByte();\r
+    if (c == 0)\r
+    {\r
+      Skip(size);\r
+      return;\r
+    }\r
+    s += c;\r
+  }\r
+}\r
+\r
+void CInArchive::ReadUString(int size, UString &s)\r
+{\r
+  s.Empty();\r
+  while(size-- != 0)\r
+  {\r
+    wchar_t c = ReadUInt16();\r
+    if (c == 0)\r
+    {\r
+      Skip(2 * size);\r
+      return;\r
+    }\r
+    s += c;\r
+  }\r
+}\r
+\r
+HRESULT CInArchive::ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size)\r
+{\r
+  RINOK(inStream->Seek(pos, STREAM_SEEK_SET, NULL));\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> limitedStream(streamSpec);\r
+  streamSpec->SetStream(inStream);\r
+  streamSpec->Init(size);\r
+  _inBuffer.SetStream(limitedStream);\r
+  _inBuffer.Init();\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::ReadDirEntry(CDatabase &database)\r
+{\r
+  CItem item;\r
+  UInt64 nameLength = ReadEncInt();\r
+  if (nameLength == 0 || nameLength >= 0x10000000)\r
+    return S_FALSE;\r
+  ReadString((int)nameLength, item.Name);\r
+  item.Section = ReadEncInt();\r
+  item.Offset = ReadEncInt();\r
+  item.Size = ReadEncInt();\r
+  database.Items.Add(item);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database)\r
+{\r
+  UInt32 headerSize = ReadUInt32();\r
+  if (headerSize != 0x60)\r
+    return S_FALSE;\r
+  UInt32 unknown1 = ReadUInt32();\r
+  if (unknown1 != 0 && unknown1 != 1) // it's 0 in one .sll file\r
+    return S_FALSE;\r
+  /* UInt32 timeStamp = */ ReadUInt32();\r
+      // Considered as a big-endian DWORD, it appears to contain seconds (MSB) and\r
+      // fractional seconds (second byte).\r
+      // The third and fourth bytes may contain even more fractional bits.\r
+      // The 4 least significant bits in the last byte are constant.\r
+  /* UInt32 lang = */ ReadUInt32();\r
+  GUID g;\r
+  ReadGUID(g); // {7C01FD10-7BAA-11D0-9E0C-00A0-C922-E6EC}\r
+  ReadGUID(g); // {7C01FD11-7BAA-11D0-9E0C-00A0-C922-E6EC}\r
+  const int kNumSections = 2;\r
+  UInt64 sectionOffsets[kNumSections];\r
+  UInt64 sectionSizes[kNumSections];\r
+  int i;\r
+  for (i = 0; i < kNumSections; i++)\r
+  {\r
+    sectionOffsets[i] = ReadUInt64();\r
+    sectionSizes[i] = ReadUInt64();\r
+  }\r
+  // if (chmVersion == 3)\r
+    database.ContentOffset = ReadUInt64();\r
+  /*\r
+  else\r
+    database.ContentOffset = _startPosition + 0x58\r
+  */\r
+\r
+  /*\r
+  // Section 0\r
+  ReadChunk(inStream, sectionOffsets[0], sectionSizes[0]);\r
+  if (sectionSizes[0] != 0x18)\r
+    return S_FALSE;\r
+  ReadUInt32(); // unknown:  01FE\r
+  ReadUInt32(); // unknown:  0\r
+  UInt64 fileSize = ReadUInt64();\r
+  ReadUInt32(); // unknown:  0\r
+  ReadUInt32(); // unknown:  0\r
+  */\r
+\r
+  // Section 1: The Directory Listing\r
+  ReadChunk(inStream, sectionOffsets[1], sectionSizes[1]);\r
+  if (ReadUInt32() != NHeader::kItspSignature)\r
+    return S_FALSE;\r
+  if (ReadUInt32() != 1) // version\r
+    return S_FALSE;\r
+  /* UInt32 dirHeaderSize = */ ReadUInt32();\r
+  ReadUInt32(); // 0x0A (unknown)\r
+  UInt32 dirChunkSize = ReadUInt32(); // $1000\r
+  if (dirChunkSize < 32)\r
+    return S_FALSE;\r
+  /* UInt32 density = */ ReadUInt32(); //  "Density" of quickref section, usually 2.\r
+  /* UInt32 depth = */ ReadUInt32(); //  Depth of the index tree: 1 there is no index,\r
+                               // 2 if there is one level of PMGI chunks.\r
+\r
+  /* UInt32 chunkNumber = */ ReadUInt32(); //  Chunk number of root index chunk, -1 if there is none\r
+                                     // (though at least one file has 0 despite there being no\r
+                                     // index chunk, probably a bug.)\r
+  /* UInt32 firstPmglChunkNumber = */ ReadUInt32(); // Chunk number of first PMGL (listing) chunk\r
+  /* UInt32 lastPmglChunkNumber = */ ReadUInt32();  // Chunk number of last PMGL (listing) chunk\r
+  ReadUInt32(); // -1 (unknown)\r
+  UInt32 numDirChunks = ReadUInt32(); // Number of directory chunks (total)\r
+  /* UInt32 windowsLangId = */ ReadUInt32();\r
+  ReadGUID(g);  // {5D02926A-212E-11D0-9DF9-00A0C922E6EC}\r
+  ReadUInt32(); // 0x54 (This is the length again)\r
+  ReadUInt32(); // -1 (unknown)\r
+  ReadUInt32(); // -1 (unknown)\r
+  ReadUInt32(); // -1 (unknown)\r
+\r
+  for (UInt32 ci = 0; ci < numDirChunks; ci++)\r
+  {\r
+    UInt64 chunkPos = _inBuffer.GetProcessedSize();\r
+    if (ReadUInt32() == NHeader::kPmglSignature)\r
+    {\r
+      // The quickref area is written backwards from the end of the chunk.\r
+      // One quickref entry exists for every n entries in the file, where n\r
+      // is calculated as 1 + (1 << quickref density). So for density = 2, n = 5.\r
+\r
+      UInt32 quickrefLength = ReadUInt32(); // Length of free space and/or quickref area at end of directory chunk\r
+      if (quickrefLength > dirChunkSize || quickrefLength < 2)\r
+        return S_FALSE;\r
+      ReadUInt32(); // Always 0\r
+      ReadUInt32(); // Chunk number of previous listing chunk when reading\r
+                    // directory in sequence (-1 if this is the first listing chunk)\r
+      ReadUInt32(); // Chunk number of next  listing chunk when reading\r
+                    // directory in sequence (-1 if this is the last listing chunk)\r
+      int numItems = 0;\r
+      for (;;)\r
+      {\r
+        UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos;\r
+        UInt32 offsetLimit = dirChunkSize - quickrefLength;\r
+        if (offset > offsetLimit)\r
+          return S_FALSE;\r
+        if (offset == offsetLimit)\r
+          break;\r
+        RINOK(ReadDirEntry(database));\r
+        numItems++;\r
+      }\r
+      Skip(quickrefLength - 2);\r
+      if (ReadUInt16() != numItems)\r
+        return S_FALSE;\r
+    }\r
+    else\r
+      Skip(dirChunkSize - 4);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)\r
+{\r
+  if (ReadUInt32() != 1) // version\r
+    return S_FALSE;\r
+  if (ReadUInt32() != 0x28) // Location of header section table\r
+    return S_FALSE;\r
+  UInt32 numHeaderSections = ReadUInt32();\r
+  const int kNumHeaderSectionsMax = 5;\r
+  if (numHeaderSections != kNumHeaderSectionsMax)\r
+    return S_FALSE;\r
+  ReadUInt32(); // Length of post-header table\r
+  GUID g;\r
+  ReadGUID(g);  // {0A9007C1-4076-11D3-8789-0000F8105754}\r
+\r
+  // header section table\r
+  UInt64 sectionOffsets[kNumHeaderSectionsMax];\r
+  UInt64 sectionSizes[kNumHeaderSectionsMax];\r
+  UInt32 i;\r
+  for (i = 0; i < numHeaderSections; i++)\r
+  {\r
+    sectionOffsets[i] = ReadUInt64();\r
+    sectionSizes[i] = ReadUInt64();\r
+  }\r
+  \r
+  // Post-Header\r
+  ReadUInt32(); // 2\r
+  ReadUInt32(); // 0x98: offset to CAOL from beginning of post-header)\r
+  // ----- Directory information\r
+  ReadUInt64(); // Chunk number of top-level AOLI chunk in directory, or -1\r
+  ReadUInt64(); // Chunk number of first AOLL chunk in directory\r
+  ReadUInt64(); // Chunk number of last AOLL chunk in directory\r
+  ReadUInt64(); // 0 (unknown)\r
+  ReadUInt32(); // $2000 (Directory chunk size of directory)\r
+  ReadUInt32(); // Quickref density for main directory, usually 2\r
+  ReadUInt32(); // 0 (unknown)\r
+  ReadUInt32(); // Depth of main directory index tree\r
+                // 1 there is no index, 2 if there is one level of AOLI chunks.\r
+  ReadUInt64(); // 0 (unknown)\r
+  UInt64 numDirEntries = ReadUInt64(); // Number of directory entries\r
+  // ----- Directory Index Information\r
+  ReadUInt64(); // -1 (unknown, probably chunk number of top-level AOLI in directory index)\r
+  ReadUInt64(); // Chunk number of first AOLL chunk in directory index\r
+  ReadUInt64(); // Chunk number of last AOLL chunk in directory index\r
+  ReadUInt64(); // 0 (unknown)\r
+  ReadUInt32(); // $200 (Directory chunk size of directory index)\r
+  ReadUInt32(); // Quickref density for directory index, usually 2\r
+  ReadUInt32(); // 0 (unknown)\r
+  ReadUInt32(); // Depth of directory index index tree.\r
+  ReadUInt64(); // Possibly flags -- sometimes 1, sometimes 0.\r
+  ReadUInt64(); // Number of directory index entries (same as number of AOLL\r
+               // chunks in main directory)\r
+  \r
+  // (The obvious guess for the following two fields, which recur in a number\r
+  // of places, is they are maximum sizes for the directory and directory index.\r
+  // However, I have seen no direct evidence that this is the case.)\r
+\r
+  ReadUInt32(); // $100000 (Same as field following chunk size in directory)\r
+  ReadUInt32(); // $20000 (Same as field following chunk size in directory index)\r
+\r
+  ReadUInt64(); // 0 (unknown)\r
+  if (ReadUInt32() != NHeader::kCaolSignature)\r
+    return S_FALSE;\r
+  if (ReadUInt32() != 2) // (Most likely a version number)\r
+    return S_FALSE;\r
+  UInt32 caolLength = ReadUInt32(); // $50 (Length of the CAOL section, which includes the ITSF section)\r
+  if (caolLength >= 0x2C)\r
+  {\r
+    /* UInt32 c7 = */ ReadUInt16(); // Unknown.  Remains the same when identical files are built.\r
+              // Does not appear to be a checksum.  Many files have\r
+              // 'HH' (HTML Help?) here, indicating this may be a compiler ID\r
+              //  field.  But at least one ITOL/ITLS compiler does not set this\r
+              // field to a constant value.\r
+    ReadUInt16(); // 0 (Unknown.  Possibly part of 00A4 field)\r
+    ReadUInt32(); // Unknown.  Two values have been seen -- $43ED, and 0.\r
+    ReadUInt32(); // $2000 (Directory chunk size of directory)\r
+    ReadUInt32(); // $200 (Directory chunk size of directory index)\r
+    ReadUInt32(); // $100000 (Same as field following chunk size in directory)\r
+    ReadUInt32(); // $20000 (Same as field following chunk size in directory index)\r
+    ReadUInt32(); // 0 (unknown)\r
+    ReadUInt32(); // 0 (Unknown)\r
+    if (caolLength == 0x2C)\r
+    {\r
+      database.ContentOffset = 0;\r
+      database.NewFormat = true;\r
+    }\r
+    else if (caolLength == 0x50)\r
+    {\r
+      ReadUInt32(); // 0 (Unknown)\r
+      if (ReadUInt32() != NHeader::kItsfSignature)\r
+        return S_FALSE;\r
+      if (ReadUInt32() != 4) // $4 (Version number -- CHM uses 3)\r
+        return S_FALSE;\r
+      if (ReadUInt32() != 0x20) // $20 (length of ITSF)\r
+        return S_FALSE;\r
+      UInt32 unknown = ReadUInt32();\r
+      if (unknown != 0 && unknown != 1) // = 0 for some HxW files, 1 in other cases;\r
+        return S_FALSE;\r
+      database.ContentOffset = _startPosition + ReadUInt64();\r
+      /* UInt32 timeStamp = */ ReadUInt32();\r
+          // A timestamp of some sort.\r
+          // Considered as a big-endian DWORD, it appears to contain\r
+          // seconds (MSB) and fractional seconds (second byte).\r
+          // The third and fourth bytes may contain even more fractional\r
+          // bits.  The 4 least significant bits in the last byte are constant.\r
+      /* UInt32 lang = */ ReadUInt32(); // BE?\r
+    }\r
+    else\r
+      return S_FALSE;\r
+  }\r
+\r
+  /*\r
+  // Section 0\r
+  ReadChunk(inStream, _startPosition + sectionOffsets[0], sectionSizes[0]);\r
+  if (sectionSizes[0] != 0x18)\r
+    return S_FALSE;\r
+  ReadUInt32(); // unknown:  01FE\r
+  ReadUInt32(); // unknown:  0\r
+  UInt64 fileSize = ReadUInt64();\r
+  ReadUInt32(); // unknown:  0\r
+  ReadUInt32(); // unknown:  0\r
+  */\r
+\r
+  // Section 1: The Directory Listing\r
+  ReadChunk(inStream, _startPosition + sectionOffsets[1], sectionSizes[1]);\r
+  if (ReadUInt32() != NHeader::kIfcmSignature)\r
+    return S_FALSE;\r
+  if (ReadUInt32() != 1) // (probably a version number)\r
+    return S_FALSE;\r
+  UInt32 dirChunkSize = ReadUInt32(); // $2000\r
+  if (dirChunkSize < 64)\r
+    return S_FALSE;\r
+  ReadUInt32(); // $100000  (unknown)\r
+  ReadUInt32(); // -1 (unknown)\r
+  ReadUInt32(); // -1 (unknown)\r
+  UInt32 numDirChunks = ReadUInt32();\r
+  ReadUInt32(); // 0 (unknown, probably high word of above)\r
+\r
+  for (UInt32 ci = 0; ci < numDirChunks; ci++)\r
+  {\r
+    UInt64 chunkPos = _inBuffer.GetProcessedSize();\r
+    if (ReadUInt32() == NHeader::kAollSignature)\r
+    {\r
+      UInt32 quickrefLength = ReadUInt32(); // Length of quickref area at end of directory chunk\r
+      if (quickrefLength > dirChunkSize || quickrefLength < 2)\r
+        return S_FALSE;\r
+      ReadUInt64(); // Directory chunk number\r
+            // This must match physical position in file, that is\r
+            // the chunk size times the chunk number must be the\r
+            // offset from the end of the directory header.\r
+      ReadUInt64(); // Chunk number of previous listing chunk when reading\r
+                    // directory in sequence (-1 if first listing chunk)\r
+      ReadUInt64(); // Chunk number of next listing chunk when reading\r
+                    // directory in sequence (-1 if last listing chunk)\r
+      ReadUInt64(); // Number of first listing entry in this chunk\r
+      ReadUInt32(); // 1 (unknown -- other values have also been seen here)\r
+      ReadUInt32(); // 0 (unknown)\r
+      \r
+      int numItems = 0;\r
+      for (;;)\r
+      {\r
+        UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos;\r
+        UInt32 offsetLimit = dirChunkSize - quickrefLength;\r
+        if (offset > offsetLimit)\r
+          return S_FALSE;\r
+        if (offset == offsetLimit)\r
+          break;\r
+        if (database.NewFormat)\r
+        {\r
+          UInt16 nameLength = ReadUInt16();\r
+          if (nameLength == 0)\r
+            return S_FALSE;\r
+          UString name;\r
+          ReadUString((int)nameLength, name);\r
+          AString s;\r
+          ConvertUnicodeToUTF8(name, s);\r
+          Byte b = ReadByte();\r
+          s += ' ';\r
+          PrintByte(b, s);\r
+          s += ' ';\r
+          UInt64 len = ReadEncInt();\r
+          // then number of items ?\r
+          // then length ?\r
+          // then some data (binary encoding?)\r
+          while (len-- != 0)\r
+          {\r
+            b = ReadByte();\r
+            PrintByte(b, s);\r
+          }\r
+          database.NewFormatString += s;\r
+          database.NewFormatString += "\r\n";\r
+        }\r
+        else\r
+        {\r
+          RINOK(ReadDirEntry(database));\r
+        }\r
+        numItems++;\r
+      }\r
+      Skip(quickrefLength - 2);\r
+      if (ReadUInt16() != numItems)\r
+        return S_FALSE;\r
+      if (numItems > numDirEntries)\r
+        return S_FALSE;\r
+      numDirEntries -= numItems;\r
+    }\r
+    else\r
+      Skip(dirChunkSize - 4);\r
+  }\r
+  return numDirEntries == 0 ? S_OK : S_FALSE;\r
+}\r
+\r
+HRESULT CInArchive::DecompressStream(IInStream *inStream, const CDatabase &database, const AString &name)\r
+{\r
+  int index = database.FindItem(name);\r
+  if (index < 0)\r
+    return S_FALSE;\r
+  const CItem &item = database.Items[index];\r
+  _chunkSize = item.Size;\r
+  return ReadChunk(inStream, database.ContentOffset + item.Offset, item.Size);\r
+}\r
+\r
+\r
+#define DATA_SPACE "::DataSpace/"\r
+static const char *kNameList = DATA_SPACE "NameList";\r
+static const char *kStorage = DATA_SPACE "Storage/";\r
+static const char *kContent = "Content";\r
+static const char *kControlData = "ControlData";\r
+static const char *kSpanInfo = "SpanInfo";\r
+static const char *kTransform = "Transform/";\r
+static const char *kResetTable = "/InstanceData/ResetTable";\r
+static const char *kTransformList = "List";\r
+\r
+static AString GetSectionPrefix(const AString &name)\r
+{\r
+  return AString(kStorage) + name + AString("/");\r
+}\r
+\r
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }\r
+\r
+static int CompareFiles(const int *p1, const int *p2, void *param)\r
+{\r
+  const CObjectVector<CItem> &items = *(const CObjectVector<CItem> *)param;\r
+  const CItem &item1 = items[*p1];\r
+  const CItem &item2 = items[*p2];\r
+  bool isDir1 = item1.IsDir();\r
+  bool isDir2 = item2.IsDir();\r
+  if (isDir1 && !isDir2)\r
+    return -1;\r
+  if (isDir2)\r
+  {\r
+    if (isDir1)\r
+      return MyCompare(*p1, *p2);\r
+    return 1;\r
+  }\r
+  RINOZ(MyCompare(item1.Section, item2.Section));\r
+  RINOZ(MyCompare(item1.Offset, item2.Offset));\r
+  RINOZ(MyCompare(item1.Size, item2.Size));\r
+  return MyCompare(*p1, *p2);\r
+}\r
+\r
+void CFilesDatabase::SetIndices()\r
+{\r
+  for (int i = 0; i < Items.Size(); i++)\r
+  {\r
+    const CItem &item = Items[i];\r
+    if (item.IsUserItem() && item.Name.Length() != 1)\r
+      Indices.Add(i);\r
+  }\r
+}\r
+\r
+void CFilesDatabase::Sort()\r
+{\r
+  Indices.Sort(CompareFiles, (void *)&Items);\r
+}\r
+\r
+bool CFilesDatabase::Check()\r
+{\r
+  UInt64 maxPos = 0;\r
+  UInt64 prevSection = 0;\r
+  for(int i = 0; i < Indices.Size(); i++)\r
+  {\r
+    const CItem &item = Items[Indices[i]];\r
+    if (item.Section == 0 || item.IsDir())\r
+      continue;\r
+    if (item.Section != prevSection)\r
+    {\r
+      prevSection = item.Section;\r
+      maxPos = 0;\r
+      continue;\r
+    }\r
+    if (item.Offset < maxPos)\r
+      return false;\r
+    maxPos = item.Offset + item.Size;\r
+    if (maxPos < item.Offset)\r
+      return false;\r
+  }\r
+  return true;\r
+}\r
+\r
+HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)\r
+{\r
+  {\r
+    // The NameList file\r
+    RINOK(DecompressStream(inStream, database, kNameList));\r
+    /* UInt16 length = */ ReadUInt16();\r
+    UInt16 numSections = ReadUInt16();\r
+    for (int i = 0; i < numSections; i++)\r
+    {\r
+      CSectionInfo section;\r
+      UInt16 nameLength  = ReadUInt16();\r
+      UString name;\r
+      ReadUString(nameLength, name);\r
+      if (ReadUInt16() != 0)\r
+        return S_FALSE;\r
+      if (!ConvertUnicodeToUTF8(name, section.Name))\r
+        return S_FALSE;\r
+      database.Sections.Add(section);\r
+    }\r
+  }\r
+\r
+  int i;\r
+  for (i = 1; i < database.Sections.Size(); i++)\r
+  {\r
+    CSectionInfo &section = database.Sections[i];\r
+    AString sectionPrefix = GetSectionPrefix(section.Name);\r
+    {\r
+      // Content\r
+      int index = database.FindItem(sectionPrefix + kContent);\r
+      if (index < 0)\r
+        return S_FALSE;\r
+      const CItem &item = database.Items[index];\r
+      section.Offset = item.Offset;\r
+      section.CompressedSize = item.Size;\r
+    }\r
+    AString transformPrefix = sectionPrefix + kTransform;\r
+    if (database.Help2Format)\r
+    {\r
+      // Transform List\r
+      RINOK(DecompressStream(inStream, database, transformPrefix + kTransformList));\r
+      if ((_chunkSize & 0xF) != 0)\r
+        return S_FALSE;\r
+      int numGuids = (int)(_chunkSize / 0x10);\r
+      if (numGuids < 1)\r
+        return S_FALSE;\r
+      for (int i = 0; i < numGuids; i++)\r
+      {\r
+        CMethodInfo method;\r
+        ReadGUID(method.Guid);\r
+        section.Methods.Add(method);\r
+      }\r
+    }\r
+    else\r
+    {\r
+      CMethodInfo method;\r
+      method.Guid = kChmLzxGuid;\r
+      section.Methods.Add(method);\r
+    }\r
+\r
+    {\r
+      // Control Data\r
+      RINOK(DecompressStream(inStream, database, sectionPrefix + kControlData));\r
+      for (int mi = 0; mi < section.Methods.Size(); mi++)\r
+      {\r
+        CMethodInfo &method = section.Methods[mi];\r
+        UInt32 numDWORDS = ReadUInt32();\r
+        if (method.IsLzx())\r
+        {\r
+          if (numDWORDS < 5)\r
+            return S_FALSE;\r
+          if (ReadUInt32() != NHeader::kLzxcSignature)\r
+            return S_FALSE;\r
+          CLzxInfo &li = method.LzxInfo;\r
+          li.Version = ReadUInt32();\r
+          if (li.Version != 2 && li.Version != 3)\r
+            return S_FALSE;\r
+          li.ResetInterval = ReadUInt32();\r
+          li.WindowSize = ReadUInt32();\r
+          li.CacheSize = ReadUInt32();\r
+          if (\r
+              li.ResetInterval != 1 &&\r
+              li.ResetInterval != 2 &&\r
+              li.ResetInterval != 4 &&\r
+              li.ResetInterval != 8 &&\r
+              li.ResetInterval != 16 &&\r
+              li.ResetInterval != 32 &&\r
+              li.ResetInterval != 64)\r
+            return S_FALSE;\r
+          if (\r
+              li.WindowSize != 1 &&\r
+              li.WindowSize != 2 &&\r
+              li.WindowSize != 4 &&\r
+              li.WindowSize != 8 &&\r
+              li.WindowSize != 16 &&\r
+              li.WindowSize != 32 &&\r
+              li.WindowSize != 64)\r
+            return S_FALSE;\r
+          numDWORDS -= 5;\r
+          while (numDWORDS-- != 0)\r
+            ReadUInt32();\r
+        }\r
+        else\r
+        {\r
+          UInt32 numBytes = numDWORDS * 4;\r
+          method.ControlData.SetCapacity(numBytes);\r
+          ReadBytes(method.ControlData, numBytes);\r
+        }\r
+      }\r
+    }\r
+\r
+    {\r
+      // SpanInfo\r
+      RINOK(DecompressStream(inStream, database, sectionPrefix + kSpanInfo));\r
+      section.UncompressedSize = ReadUInt64();\r
+    }\r
+\r
+    // read ResetTable for LZX\r
+    for (int mi = 0; mi < section.Methods.Size(); mi++)\r
+    {\r
+      CMethodInfo &method = section.Methods[mi];\r
+      if (method.IsLzx())\r
+      {\r
+        // ResetTable;\r
+        RINOK(DecompressStream(inStream, database, transformPrefix +\r
+            method.GetGuidString() + kResetTable));\r
+        CResetTable &rt = method.LzxInfo.ResetTable;\r
+        if (_chunkSize < 4)\r
+        {\r
+          if (_chunkSize != 0)\r
+            return S_FALSE;\r
+          // ResetTable is empty in .chw files\r
+          if (section.UncompressedSize != 0)\r
+            return S_FALSE;\r
+          rt.UncompressedSize = 0;\r
+          rt.CompressedSize = 0;\r
+          rt.BlockSize = 0;\r
+        }\r
+        else\r
+        {\r
+          UInt32 ver = ReadUInt32(); // 2  unknown (possibly a version number)\r
+          if (ver != 2 && ver != 3)\r
+            return S_FALSE;\r
+          UInt32 numEntries = ReadUInt32();\r
+          if (ReadUInt32() != 8) // Size of table entry (bytes)\r
+            return S_FALSE;\r
+          if (ReadUInt32() != 0x28) // Length of table header\r
+            return S_FALSE;\r
+          rt.UncompressedSize = ReadUInt64();\r
+          rt.CompressedSize = ReadUInt64();\r
+          rt.BlockSize = ReadUInt64(); //  0x8000 block size for locations below\r
+          if (rt.BlockSize != 0x8000)\r
+            return S_FALSE;\r
+          rt.ResetOffsets.Reserve(numEntries);\r
+          for (UInt32 i = 0; i < numEntries; i++)\r
+            rt.ResetOffsets.Add(ReadUInt64());\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  database.SetIndices();\r
+  database.Sort();\r
+  return database.Check() ? S_OK : S_FALSE;\r
+}\r
+\r
+HRESULT CInArchive::Open2(IInStream *inStream,\r
+    const UInt64 *searchHeaderSizeLimit,\r
+    CFilesDatabase &database)\r
+{\r
+  database.Clear();\r
+\r
+  RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_startPosition));\r
+\r
+  database.Help2Format = false;\r
+  const UInt32 chmVersion = 3;\r
+  {\r
+    if (!_inBuffer.Create(1 << 14))\r
+      return E_OUTOFMEMORY;\r
+    _inBuffer.SetStream(inStream);\r
+    _inBuffer.Init();\r
+    UInt64 value = 0;\r
+    const int kSignatureSize = 8;\r
+    UInt64 hxsSignature = NHeader::GetHxsSignature();\r
+    UInt64 chmSignature = ((UInt64)chmVersion << 32)| NHeader::kItsfSignature;\r
+    UInt64 limit = 1 << 18;\r
+    if (searchHeaderSizeLimit)\r
+      if (limit > *searchHeaderSizeLimit)\r
+        limit = *searchHeaderSizeLimit;\r
+\r
+    for (;;)\r
+    {\r
+      Byte b;\r
+      if (!_inBuffer.ReadByte(b))\r
+        return S_FALSE;\r
+      value >>= 8;\r
+      value |= ((UInt64)b) << ((kSignatureSize - 1) * 8);\r
+      if (_inBuffer.GetProcessedSize() >= kSignatureSize)\r
+      {\r
+        if (value == chmSignature)\r
+          break;\r
+        if (value == hxsSignature)\r
+        {\r
+          database.Help2Format = true;\r
+          break;\r
+        }\r
+        if (_inBuffer.GetProcessedSize() > limit)\r
+          return S_FALSE;\r
+      }\r
+    }\r
+    _startPosition += _inBuffer.GetProcessedSize() - kSignatureSize;\r
+  }\r
+\r
+  if (database.Help2Format)\r
+  {\r
+    RINOK(OpenHelp2(inStream, database));\r
+    if (database.NewFormat)\r
+      return S_OK;\r
+  }\r
+  else\r
+  {\r
+    RINOK(OpenChm(inStream, database));\r
+  }\r
+\r
+  #ifndef CHM_LOW\r
+  try\r
+  {\r
+    HRESULT res = OpenHighLevel(inStream, database);\r
+    if (res == S_FALSE)\r
+    {\r
+      database.HighLevelClear();\r
+      return S_OK;\r
+    }\r
+    RINOK(res);\r
+    database.LowLevel = false;\r
+  }\r
+  catch(...)\r
+  {\r
+    return S_OK;\r
+  }\r
+  #endif\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::Open(IInStream *inStream,\r
+    const UInt64 *searchHeaderSizeLimit,\r
+    CFilesDatabase &database)\r
+{\r
+  try\r
+  {\r
+    HRESULT res = Open2(inStream, searchHeaderSizeLimit, database);\r
+    _inBuffer.ReleaseStream();\r
+    return res;\r
+  }\r
+  catch(...)\r
+  {\r
+    _inBuffer.ReleaseStream();\r
+    throw;\r
+  }\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Chm/ChmIn.h b/CPP/7zip/Archive/Chm/ChmIn.h
new file mode 100755 (executable)
index 0000000..8b6eb97
--- /dev/null
@@ -0,0 +1,244 @@
+// Archive/ChmIn.h\r
+\r
+#ifndef __ARCHIVE_CHM_IN_H\r
+#define __ARCHIVE_CHM_IN_H\r
+\r
+#include "Common/Buffer.h"\r
+#include "Common/MyString.h"\r
+\r
+#include "../../IStream.h"\r
+#include "../../Common/InBuffer.h"\r
+\r
+#include "ChmHeader.h"\r
+\r
+namespace NArchive {\r
+namespace NChm {\r
+\r
+struct CItem\r
+{\r
+  UInt64 Section;\r
+  UInt64 Offset;\r
+  UInt64 Size;\r
+  AString Name;\r
+\r
+  bool IsFormatRelatedItem() const\r
+  {\r
+    if (Name.Length() < 2)\r
+      return false;\r
+    return Name[0] == ':' && Name[1] == ':';\r
+  }\r
+  \r
+  bool IsUserItem() const\r
+  {\r
+    if (Name.Length() < 2)\r
+      return false;\r
+    return Name[0] == '/';\r
+  }\r
+  \r
+  bool IsDir() const\r
+  {\r
+    if (Name.Length() == 0)\r
+      return false;\r
+    return (Name[Name.Length() - 1] == '/');\r
+  }\r
+};\r
+\r
+struct CDatabase\r
+{\r
+  UInt64 ContentOffset;\r
+  CObjectVector<CItem> Items;\r
+  AString NewFormatString;\r
+  bool Help2Format;\r
+  bool NewFormat;\r
+\r
+  int FindItem(const AString &name) const\r
+  {\r
+    for (int i = 0; i < Items.Size(); i++)\r
+      if (Items[i].Name == name)\r
+        return i;\r
+    return -1;\r
+  }\r
+\r
+  void Clear()\r
+  {\r
+    NewFormat = false;\r
+    NewFormatString.Empty();\r
+    Help2Format = false;\r
+    Items.Clear();\r
+  }\r
+};\r
+\r
+struct CResetTable\r
+{\r
+  UInt64 UncompressedSize;\r
+  UInt64 CompressedSize;\r
+  UInt64 BlockSize;\r
+  CRecordVector<UInt64> ResetOffsets;\r
+  bool GetCompressedSizeOfBlocks(UInt64 blockIndex, UInt32 numBlocks, UInt64 &size) const\r
+  {\r
+    if (blockIndex >= ResetOffsets.Size())\r
+      return false;\r
+    UInt64 startPos = ResetOffsets[(int)blockIndex];\r
+    if (blockIndex + numBlocks >= ResetOffsets.Size())\r
+      size = CompressedSize - startPos;\r
+    else\r
+      size = ResetOffsets[(int)(blockIndex + numBlocks)] - startPos;\r
+    return true;\r
+  }\r
+  bool GetCompressedSizeOfBlock(UInt64 blockIndex, UInt64 &size) const\r
+  {\r
+    return GetCompressedSizeOfBlocks(blockIndex, 1, size);\r
+  }\r
+  UInt64 GetNumBlocks(UInt64 size) const\r
+  {\r
+    return (size + BlockSize - 1) / BlockSize;\r
+  }\r
+};\r
+\r
+struct CLzxInfo\r
+{\r
+  UInt32 Version;\r
+  UInt32 ResetInterval;\r
+  UInt32 WindowSize;\r
+  UInt32 CacheSize;\r
+  CResetTable ResetTable;\r
+\r
+  UInt32 GetNumDictBits() const\r
+  {\r
+    if (Version == 2 || Version == 3)\r
+    {\r
+      for (int i = 0; i <= 31; i++)\r
+        if (((UInt32)1 << i) >= WindowSize)\r
+          return 15 + i;\r
+    }\r
+    return 0;\r
+  }\r
+\r
+  UInt64 GetFolderSize() const { return ResetTable.BlockSize * ResetInterval; };\r
+  UInt64 GetFolder(UInt64 offset) const { return offset / GetFolderSize(); };\r
+  UInt64 GetFolderPos(UInt64 folderIndex) const { return folderIndex * GetFolderSize(); };\r
+  UInt64 GetBlockIndexFromFolderIndex(UInt64 folderIndex) const { return folderIndex * ResetInterval; };\r
+  bool GetOffsetOfFolder(UInt64 folderIndex, UInt64 &offset) const\r
+  {\r
+    UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex);\r
+    if (blockIndex >= ResetTable.ResetOffsets.Size())\r
+      return false;\r
+    offset = ResetTable.ResetOffsets[(int)blockIndex];\r
+    return true;\r
+  }\r
+  bool GetCompressedSizeOfFolder(UInt64 folderIndex, UInt64 &size) const\r
+  {\r
+    UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex);\r
+    return ResetTable.GetCompressedSizeOfBlocks(blockIndex, ResetInterval, size);\r
+  }\r
+};\r
+\r
+struct CMethodInfo\r
+{\r
+  GUID Guid;\r
+  CByteBuffer ControlData;\r
+  CLzxInfo LzxInfo;\r
+  bool IsLzx() const;\r
+  bool IsDes() const;\r
+  AString GetGuidString() const;\r
+  UString GetName() const;\r
+};\r
+\r
+struct CSectionInfo\r
+{\r
+  UInt64 Offset;\r
+  UInt64 CompressedSize;\r
+  UInt64 UncompressedSize;\r
+\r
+  AString Name;\r
+  CObjectVector<CMethodInfo> Methods;\r
+\r
+  bool IsLzx() const;\r
+  UString GetMethodName() const;\r
+};\r
+\r
+class CFilesDatabase: public CDatabase\r
+{\r
+public:\r
+  bool LowLevel;\r
+  CRecordVector<int> Indices;\r
+  CObjectVector<CSectionInfo> Sections;\r
+\r
+  UInt64 GetFileSize(int fileIndex) const { return Items[Indices[fileIndex]].Size; }\r
+  UInt64 GetFileOffset(int fileIndex) const { return Items[Indices[fileIndex]].Offset; }\r
+\r
+  UInt64 GetFolder(int fileIndex) const\r
+  {\r
+    const CItem &item = Items[Indices[fileIndex]];\r
+    const CSectionInfo &section = Sections[(int)item.Section];\r
+    if (section.IsLzx())\r
+      return section.Methods[0].LzxInfo.GetFolder(item.Offset);\r
+    return 0;\r
+  }\r
+\r
+  UInt64 GetLastFolder(int fileIndex) const\r
+  {\r
+    const CItem &item = Items[Indices[fileIndex]];\r
+    const CSectionInfo &section = Sections[(int)item.Section];\r
+    if (section.IsLzx())\r
+      return section.Methods[0].LzxInfo.GetFolder(item.Offset + item.Size - 1);\r
+    return 0;\r
+  }\r
+\r
+  void HighLevelClear()\r
+  {\r
+    LowLevel = true;\r
+    Indices.Clear();\r
+    Sections.Clear();\r
+  }\r
+\r
+  void Clear()\r
+  {\r
+    CDatabase::Clear();\r
+    HighLevelClear();\r
+  }\r
+  void SetIndices();\r
+  void Sort();\r
+  bool Check();\r
+};\r
+\r
+class CProgressVirt\r
+{\r
+public:\r
+  STDMETHOD(SetTotal)(const UInt64 *numFiles) PURE;\r
+  STDMETHOD(SetCompleted)(const UInt64 *numFiles) PURE;\r
+};\r
+\r
+class CInArchive\r
+{\r
+  UInt64 _startPosition;\r
+  ::CInBuffer _inBuffer;\r
+  UInt64 _chunkSize;\r
+\r
+  Byte ReadByte();\r
+  void ReadBytes(Byte *data, UInt32 size);\r
+  void Skip(size_t size);\r
+  UInt16 ReadUInt16();\r
+  UInt32 ReadUInt32();\r
+  UInt64 ReadUInt64();\r
+  UInt64 ReadEncInt();\r
+  void ReadString(int size, AString &s);\r
+  void ReadUString(int size, UString &s);\r
+  void ReadGUID(GUID &g);\r
+\r
+  HRESULT ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size);\r
+\r
+  HRESULT ReadDirEntry(CDatabase &database);\r
+  HRESULT DecompressStream(IInStream *inStream, const CDatabase &database, const AString &name);\r
+\r
+public:\r
+  HRESULT OpenChm(IInStream *inStream, CDatabase &database);\r
+  HRESULT OpenHelp2(IInStream *inStream, CDatabase &database);\r
+  HRESULT OpenHighLevel(IInStream *inStream, CFilesDatabase &database);\r
+  HRESULT Open2(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, CFilesDatabase &database);\r
+  HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, CFilesDatabase &database);\r
+};\r
+  \r
+}}\r
+  \r
+#endif\r
diff --git a/CPP/7zip/Archive/Chm/ChmRegister.cpp b/CPP/7zip/Archive/Chm/ChmRegister.cpp
new file mode 100755 (executable)
index 0000000..8f1f2ec
--- /dev/null
@@ -0,0 +1,13 @@
+// ChmRegister.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/RegisterArc.h"\r
+\r
+#include "ChmHandler.h"\r
+static IInArchive *CreateArc() { return new NArchive::NChm::CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"Chm", L"chm chi chq chw hxs hxi hxr hxq hxw lit", 0, 0xE9, { 'I', 'T', 'S', 'F' }, 4, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Chm)\r
diff --git a/CPP/7zip/Archive/Chm/StdAfx.h b/CPP/7zip/Archive/Chm/StdAfx.h
new file mode 100755 (executable)
index 0000000..83fdd22
--- /dev/null
@@ -0,0 +1,8 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Com/ComHandler.cpp b/CPP/7zip/Archive/Com/ComHandler.cpp
new file mode 100755 (executable)
index 0000000..8b9437e
--- /dev/null
@@ -0,0 +1,239 @@
+// ComHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../../Common/LimitedStreams.h"\r
+#include "../../Common/ProgressUtils.h"\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "../../Compress/CopyCoder.h"\r
+\r
+#include "ComHandler.h"\r
+\r
+namespace NArchive {\r
+namespace NCom {\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidIsDir, VT_BOOL},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidCTime, VT_FILETIME},\r
+  { NULL, kpidMTime, VT_FILETIME}\r
+};\r
+\r
+STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidClusterSize, VT_UI4},\r
+  { NULL, kpidSectorSize, VT_UI4}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break;\r
+    case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break;\r
+    case kpidMainSubfile: if (_db.MainSubfile >= 0) prop = (UInt32)_db.MainSubfile; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  const CRef &ref = _db.Refs[index];\r
+  const CItem &item = _db.Items[ref.Did];\r
+    \r
+  switch(propID)\r
+  {\r
+    case kpidPath:  prop = _db.GetItemPath(index); break;\r
+    case kpidIsDir:  prop = item.IsDir(); break;\r
+    case kpidCTime:  prop = item.CTime; break;\r
+    case kpidMTime:  prop = item.MTime; break;\r
+    case kpidPackSize:  if (!item.IsDir()) prop = _db.GetItemPackSize(item.Size); break;\r
+    case kpidSize:  if (!item.IsDir()) prop = item.Size; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *inStream,\r
+    const UInt64 * /* maxCheckStartPosition */,\r
+    IArchiveOpenCallback * /* openArchiveCallback */)\r
+{\r
+  COM_TRY_BEGIN\r
+  Close();\r
+  try\r
+  {\r
+    if (_db.Open(inStream) != S_OK)\r
+      return S_FALSE;\r
+    _stream = inStream;\r
+  }\r
+  catch(...) { return S_FALSE; }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _db.Clear();\r
+  _stream.Release();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _db.Refs.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt32 i;\r
+  UInt64 totalSize = 0;\r
+  for(i = 0; i < numItems; i++)\r
+  {\r
+    const CItem &item = _db.Items[_db.Refs[allFilesMode ? i : indices[i]].Did];\r
+    if (!item.IsDir())\r
+      totalSize += item.Size;\r
+  }\r
+  RINOK(extractCallback->SetTotal(totalSize));\r
+\r
+  UInt64 totalPackSize;\r
+  totalSize = totalPackSize = 0;\r
+  \r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    lps->InSize = totalPackSize;\r
+    lps->OutSize = totalSize;\r
+    RINOK(lps->SetCur());\r
+    Int32 index = allFilesMode ? i : indices[i];\r
+    const CItem &item = _db.Items[_db.Refs[index].Did];\r
+\r
+    CMyComPtr<ISequentialOutStream> outStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));\r
+\r
+    if (item.IsDir())\r
+    {\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+      continue;\r
+    }\r
+\r
+    totalPackSize += _db.GetItemPackSize(item.Size);\r
+    totalSize += item.Size;\r
+    \r
+    if (!testMode && !outStream)\r
+      continue;\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+    Int32 res = NExtract::NOperationResult::kDataError;\r
+    CMyComPtr<ISequentialInStream> inStream;\r
+    HRESULT hres = GetStream(index, &inStream);\r
+    if (hres == S_FALSE)\r
+      res = NExtract::NOperationResult::kDataError;\r
+    else if (hres == E_NOTIMPL)\r
+      res = NExtract::NOperationResult::kUnSupportedMethod;\r
+    else\r
+    {\r
+      RINOK(hres);\r
+      if (inStream)\r
+      {\r
+        RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));\r
+        if (copyCoderSpec->TotalSize == item.Size)\r
+          res = NExtract::NOperationResult::kOK;\r
+      }\r
+    }\r
+    outStream.Release();\r
+    RINOK(extractCallback->SetOperationResult(res));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _db.Refs.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)\r
+{\r
+  COM_TRY_BEGIN\r
+  *stream = 0;\r
+  const CItem &item = _db.Items[_db.Refs[index].Did];\r
+  CClusterInStream *streamSpec = new CClusterInStream;\r
+  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;\r
+  streamSpec->Stream = _stream;\r
+  streamSpec->StartOffset = 0;\r
+\r
+  bool isLargeStream = _db.IsLargeStream(item.Size);\r
+  int bsLog = isLargeStream ? _db.SectorSizeBits : _db.MiniSectorSizeBits;\r
+  streamSpec->BlockSizeLog = bsLog;\r
+  streamSpec->Size = item.Size;\r
+\r
+  UInt32 clusterSize = (UInt32)1 << bsLog;\r
+  UInt64 numClusters64 = (item.Size + clusterSize - 1) >> bsLog;\r
+  if (numClusters64 >= ((UInt32)1 << 31))\r
+    return E_NOTIMPL;\r
+  streamSpec->Vector.Reserve((int)numClusters64);\r
+  UInt32 sid = item.Sid;\r
+  UInt64 size = item.Size;\r
+\r
+  if (size != 0)\r
+  {\r
+    for (;; size -= clusterSize)\r
+    {\r
+      if (isLargeStream)\r
+      {\r
+        if (sid >= _db.FatSize)\r
+          return S_FALSE;\r
+        streamSpec->Vector.Add(sid + 1);\r
+        sid = _db.Fat[sid];\r
+      }\r
+      else\r
+      {\r
+        UInt64 val;\r
+        if (sid >= _db.MatSize || !_db.GetMiniCluster(sid, val) || val >= (UInt64)1 << 32)\r
+          return S_FALSE;\r
+        streamSpec->Vector.Add((UInt32)val);\r
+        sid = _db.Mat[sid];\r
+      }\r
+      if (size <= clusterSize)\r
+        break;\r
+    }\r
+  }\r
+  if (sid != NFatID::kEndOfChain)\r
+    return S_FALSE;\r
+  RINOK(streamSpec->InitAndSeek());\r
+  *stream = streamTemp.Detach();\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Com/ComHandler.h b/CPP/7zip/Archive/Com/ComHandler.h
new file mode 100755 (executable)
index 0000000..6b725e7
--- /dev/null
@@ -0,0 +1,28 @@
+// ComHandler.h\r
+\r
+#ifndef __ARCHIVE_COM_HANDLER_H\r
+#define __ARCHIVE_COM_HANDLER_H\r
+\r
+#include "Common/MyCom.h"\r
+#include "../IArchive.h"\r
+#include "ComIn.h"\r
+\r
+namespace NArchive {\r
+namespace NCom {\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IInArchiveGetStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<IInStream> _stream;\r
+  CDatabase _db;\r
+public:\r
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Com/ComIn.cpp b/CPP/7zip/Archive/Com/ComIn.cpp
new file mode 100755 (executable)
index 0000000..f69e134
--- /dev/null
@@ -0,0 +1,389 @@
+// Archive/ComIn.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/Alloc.h"\r
+#include "../../../../C/CpuArch.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/MyCom.h"\r
+\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "ComIn.h"\r
+\r
+#define Get16(p) GetUi16(p)\r
+#define Get32(p) GetUi32(p)\r
+\r
+namespace NArchive{\r
+namespace NCom{\r
+\r
+static const UInt32 kSignatureSize = 8;\r
+static const Byte kSignature[kSignatureSize] = { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 };\r
+\r
+void CUInt32Buf::Free()\r
+{\r
+  MyFree(_buf);\r
+  _buf = 0;\r
+}\r
+\r
+bool CUInt32Buf::Allocate(UInt32 numItems)\r
+{\r
+  Free();\r
+  if (numItems == 0)\r
+    return true;\r
+  size_t newSize = (size_t)numItems * sizeof(UInt32);\r
+  if (newSize / sizeof(UInt32) != numItems)\r
+    return false;\r
+  _buf = (UInt32 *)MyAlloc(newSize);\r
+  return (_buf != 0);\r
+}\r
+\r
+static HRESULT ReadSector(IInStream *inStream, Byte *buf, int sectorSizeBits, UInt32 sid)\r
+{\r
+  RINOK(inStream->Seek((((UInt64)sid + 1) << sectorSizeBits), STREAM_SEEK_SET, NULL));\r
+  return ReadStream_FALSE(inStream, buf, (UInt32)1 << sectorSizeBits);\r
+}\r
+\r
+static HRESULT ReadIDs(IInStream *inStream, Byte *buf, int sectorSizeBits, UInt32 sid, UInt32 *dest)\r
+{\r
+  RINOK(ReadSector(inStream, buf, sectorSizeBits, sid));\r
+  UInt32 sectorSize = (UInt32)1 << sectorSizeBits;\r
+  for (UInt32 t = 0; t < sectorSize; t += 4)\r
+    *dest++ = Get32(buf + t);\r
+  return S_OK;\r
+}\r
+\r
+static void GetFileTimeFromMem(const Byte *p, FILETIME *ft)\r
+{\r
+  ft->dwLowDateTime = Get32(p);\r
+  ft->dwHighDateTime = Get32(p + 4);\r
+}\r
+\r
+void CItem::Parse(const Byte *p, bool mode64bit)\r
+{\r
+  memcpy(Name, p, kNameSizeMax);\r
+  // NameSize = Get16(p + 64);\r
+  Type = p[66];\r
+  LeftDid = Get32(p + 68);\r
+  RightDid = Get32(p + 72);\r
+  SonDid = Get32(p + 76);\r
+  // Flags = Get32(p + 96);\r
+  GetFileTimeFromMem(p + 100, &CTime);\r
+  GetFileTimeFromMem(p + 108, &MTime);\r
+  Sid = Get32(p + 116);\r
+  Size = Get32(p + 120);\r
+  if (mode64bit)\r
+    Size |= ((UInt64)Get32(p + 124) << 32);\r
+}\r
+\r
+void CDatabase::Clear()\r
+{\r
+  Fat.Free();\r
+  MiniSids.Free();\r
+  Mat.Free();\r
+  Items.Clear();\r
+  Refs.Clear();\r
+}\r
+\r
+static const UInt32 kNoDid = 0xFFFFFFFF;\r
+\r
+HRESULT CDatabase::AddNode(int parent, UInt32 did)\r
+{\r
+  if (did == kNoDid)\r
+    return S_OK;\r
+  if (did >= (UInt32)Items.Size())\r
+    return S_FALSE;\r
+  const CItem &item = Items[did];\r
+  if (item.IsEmpty())\r
+    return S_FALSE;\r
+  CRef ref;\r
+  ref.Parent = parent;\r
+  ref.Did = did;\r
+  int index = Refs.Add(ref);\r
+  if (Refs.Size() > Items.Size())\r
+    return S_FALSE;\r
+  RINOK(AddNode(parent, item.LeftDid));\r
+  RINOK(AddNode(parent, item.RightDid));\r
+  if (item.IsDir())\r
+  {\r
+    RINOK(AddNode(index, item.SonDid));\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+static const char kCharOpenBracket  = '[';\r
+static const char kCharCloseBracket = ']';\r
+\r
+static UString CompoundNameToFileName(const UString &s)\r
+{\r
+  UString res;\r
+  for (int i = 0; i < s.Length(); i++)\r
+  {\r
+    wchar_t c = s[i];\r
+    if (c < 0x20)\r
+    {\r
+      res += kCharOpenBracket;\r
+      wchar_t buf[32];\r
+      ConvertUInt32ToString(c, buf);\r
+      res += buf;\r
+      res += kCharCloseBracket;\r
+    }\r
+    else\r
+      res += c;\r
+  }\r
+  return res;\r
+}\r
+\r
+static char g_MsiChars[] =\r
+"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._";\r
+\r
+static const wchar_t *kMsi_ID = L""; // L"{msi}";\r
+\r
+static const int kMsiNumBits = 6;\r
+static const UInt32 kMsiNumChars = 1 << kMsiNumBits;\r
+static const UInt32 kMsiCharMask = kMsiNumChars - 1;\r
+static const UInt32 kMsiStartUnicodeChar = 0x3800;\r
+static const UInt32 kMsiUnicodeRange = kMsiNumChars * (kMsiNumChars + 1);\r
+\r
+bool CompoundMsiNameToFileName(const UString &name, UString &resultName)\r
+{\r
+  resultName.Empty();\r
+  for (int i = 0; i < name.Length(); i++)\r
+  {\r
+    wchar_t c =  name[i];\r
+    if (c < kMsiStartUnicodeChar || c > kMsiStartUnicodeChar + kMsiUnicodeRange)\r
+      return false;\r
+    if (i == 0)\r
+      resultName += kMsi_ID;\r
+    c -= kMsiStartUnicodeChar;\r
+    \r
+    UInt32 c0 = c & kMsiCharMask;\r
+    UInt32 c1 = c >> kMsiNumBits;\r
+\r
+    if (c1 <= kMsiNumChars)\r
+    {\r
+      resultName += (wchar_t)g_MsiChars[c0];\r
+      if (c1 == kMsiNumChars)\r
+        break;\r
+      resultName += (wchar_t)g_MsiChars[c1];\r
+    }\r
+    else\r
+      resultName += L'!';\r
+  }\r
+  return true;\r
+}\r
+\r
+static UString ConvertName(const Byte *p, bool &isMsi)\r
+{\r
+  isMsi = false;\r
+  UString s;\r
+  for (int i = 0; i < kNameSizeMax; i += 2)\r
+  {\r
+    wchar_t c = (p[i] | (wchar_t)p[i + 1] << 8);\r
+    if (c == 0)\r
+      break;\r
+    s += c;\r
+  }\r
+  UString msiName;\r
+  if (CompoundMsiNameToFileName(s, msiName))\r
+  {\r
+    isMsi = true;\r
+    return msiName;\r
+  }\r
+  return CompoundNameToFileName(s);\r
+}\r
+\r
+static UString ConvertName(const Byte *p)\r
+{\r
+  bool isMsi;\r
+  return ConvertName(p, isMsi);\r
+}\r
+\r
+UString CDatabase::GetItemPath(UInt32 index) const\r
+{\r
+  UString s;\r
+  while (index != kNoDid)\r
+  {\r
+    const CRef &ref = Refs[index];\r
+    const CItem &item = Items[ref.Did];\r
+    if (!s.IsEmpty())\r
+      s = (UString)WCHAR_PATH_SEPARATOR + s;\r
+    s = ConvertName(item.Name) + s;\r
+    index = ref.Parent;\r
+  }\r
+  return s;\r
+}\r
+\r
+HRESULT CDatabase::Open(IInStream *inStream)\r
+{\r
+  MainSubfile = -1;\r
+  static const UInt32 kHeaderSize = 512;\r
+  Byte p[kHeaderSize];\r
+  RINOK(ReadStream_FALSE(inStream, p, kHeaderSize));\r
+  if (memcmp(p, kSignature, kSignatureSize) != 0)\r
+    return S_FALSE;\r
+  if (Get16(p + 0x1A) > 4) // majorVer\r
+    return S_FALSE;\r
+  if (Get16(p + 0x1C) != 0xFFFE)\r
+    return S_FALSE;\r
+  int sectorSizeBits = Get16(p + 0x1E);\r
+  bool mode64bit = (sectorSizeBits >= 12);\r
+  int miniSectorSizeBits = Get16(p + 0x20);\r
+  SectorSizeBits = sectorSizeBits;\r
+  MiniSectorSizeBits = miniSectorSizeBits;\r
+\r
+  if (sectorSizeBits > 28 || miniSectorSizeBits > 28 ||\r
+      sectorSizeBits < 7 || miniSectorSizeBits < 2 || miniSectorSizeBits > sectorSizeBits)\r
+    return S_FALSE;\r
+  UInt32 numSectorsForFAT = Get32(p + 0x2C);\r
+  LongStreamMinSize = Get32(p + 0x38);\r
+  \r
+  UInt32 sectSize = (UInt32)1 << (int)sectorSizeBits;\r
+\r
+  CByteBuffer sect;\r
+  sect.SetCapacity(sectSize);\r
+\r
+  int ssb2 = (int)(sectorSizeBits - 2);\r
+  UInt32 numSidsInSec = (UInt32)1 << ssb2;\r
+  UInt32 numFatItems = numSectorsForFAT << ssb2;\r
+  if ((numFatItems >> ssb2) != numSectorsForFAT)\r
+    return S_FALSE;\r
+  FatSize = numFatItems;\r
+\r
+  {\r
+    CUInt32Buf bat;\r
+    UInt32 numSectorsForBat = Get32(p + 0x48);\r
+    const UInt32 kNumHeaderBatItems = 109;\r
+    UInt32 numBatItems = kNumHeaderBatItems + (numSectorsForBat << ssb2);\r
+    if (numBatItems < kNumHeaderBatItems || ((numBatItems - kNumHeaderBatItems) >> ssb2) != numSectorsForBat)\r
+      return S_FALSE;\r
+    if (!bat.Allocate(numBatItems))\r
+      return S_FALSE;\r
+    UInt32 i;\r
+    for (i = 0; i < kNumHeaderBatItems; i++)\r
+      bat[i] = Get32(p + 0x4c + i * 4);\r
+    UInt32 sid = Get32(p + 0x44);\r
+    for (UInt32 s = 0; s < numSectorsForBat; s++)\r
+    {\r
+      RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, bat + i));\r
+      i += numSidsInSec - 1;\r
+      sid = bat[i];\r
+    }\r
+    numBatItems = i;\r
+    \r
+    if (!Fat.Allocate(numFatItems))\r
+      return S_FALSE;\r
+    UInt32 j = 0;\r
+      \r
+    for (i = 0; i < numFatItems; j++, i += numSidsInSec)\r
+    {\r
+      if (j >= numBatItems)\r
+        return S_FALSE;\r
+      RINOK(ReadIDs(inStream, sect, sectorSizeBits, bat[j], Fat + i));\r
+    }\r
+  }\r
+\r
+  UInt32 numMatItems;\r
+  {\r
+    UInt32 numSectorsForMat = Get32(p + 0x40);\r
+    numMatItems = (UInt32)numSectorsForMat << ssb2;\r
+    if ((numMatItems >> ssb2) != numSectorsForMat)\r
+      return S_FALSE;\r
+    if (!Mat.Allocate(numMatItems))\r
+      return S_FALSE;\r
+    UInt32 i;\r
+    UInt32 sid = Get32(p + 0x3C);\r
+    for (i = 0; i < numMatItems; i += numSidsInSec)\r
+    {\r
+      RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, Mat + i));\r
+      if (sid >= numFatItems)\r
+        return S_FALSE;\r
+      sid = Fat[sid];\r
+    }\r
+    if (sid != NFatID::kEndOfChain)\r
+      return S_FALSE;\r
+  }\r
+\r
+  {\r
+    UInt32 sid = Get32(p + 0x30);\r
+    for (;;)\r
+    {\r
+      if (sid >= numFatItems)\r
+        return S_FALSE;\r
+      RINOK(ReadSector(inStream, sect, sectorSizeBits, sid));\r
+      for (UInt32 i = 0; i < sectSize; i += 128)\r
+      {\r
+        CItem item;\r
+        item.Parse(sect + i, mode64bit);\r
+        Items.Add(item);\r
+      }\r
+      sid = Fat[sid];\r
+      if (sid == NFatID::kEndOfChain)\r
+        break;\r
+    }\r
+  }\r
+\r
+  CItem root = Items[0];\r
+\r
+  {\r
+    UInt32 numSectorsInMiniStream;\r
+    {\r
+      UInt64 numSatSects64 = (root.Size + sectSize - 1) >> sectorSizeBits;\r
+      if (numSatSects64 > NFatID::kMaxValue)\r
+        return S_FALSE;\r
+      numSectorsInMiniStream = (UInt32)numSatSects64;\r
+    }\r
+    NumSectorsInMiniStream = numSectorsInMiniStream;\r
+    if (!MiniSids.Allocate(numSectorsInMiniStream))\r
+      return S_FALSE;\r
+    {\r
+      UInt64 matSize64 = (root.Size + ((UInt64)1 << miniSectorSizeBits) - 1) >> miniSectorSizeBits;\r
+      if (matSize64 > NFatID::kMaxValue)\r
+        return S_FALSE;\r
+      MatSize = (UInt32)matSize64;\r
+      if (numMatItems < MatSize)\r
+        return S_FALSE;\r
+    }\r
+\r
+    UInt32 sid = root.Sid;\r
+    for (UInt32 i = 0; ; i++)\r
+    {\r
+      if (sid == NFatID::kEndOfChain)\r
+      {\r
+        if (i != numSectorsInMiniStream)\r
+          return S_FALSE;\r
+        break;\r
+      }\r
+      if (i >= numSectorsInMiniStream)\r
+        return S_FALSE;\r
+      MiniSids[i] = sid;\r
+      if (sid >= numFatItems)\r
+        return S_FALSE;\r
+      sid = Fat[sid];\r
+    }\r
+  }\r
+\r
+  RINOK(AddNode(-1, root.SonDid));\r
+  \r
+  unsigned numCabs = 0;\r
+  for (int i = 0; i < Refs.Size(); i++)\r
+  {\r
+    const CItem &item = Items[Refs[i].Did];\r
+    if (item.IsDir() || numCabs > 1)\r
+      continue;\r
+    bool isMsiName;\r
+    UString msiName = ConvertName(item.Name, isMsiName);\r
+    if (isMsiName && msiName.Right(4).CompareNoCase(L".cab") == 0)\r
+    {\r
+      numCabs++;\r
+      MainSubfile = i;\r
+    }\r
+  }\r
+  if (numCabs > 1)\r
+    MainSubfile = -1;\r
+\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Com/ComIn.h b/CPP/7zip/Archive/Com/ComIn.h
new file mode 100755 (executable)
index 0000000..1439d2f
--- /dev/null
@@ -0,0 +1,119 @@
+// Archive/ComIn.h\r
+\r
+#ifndef __ARCHIVE_COM_IN_H\r
+#define __ARCHIVE_COM_IN_H\r
+\r
+#include "Common/MyString.h"\r
+#include "Common/Buffer.h"\r
+\r
+namespace NArchive {\r
+namespace NCom {\r
+\r
+struct CUInt32Buf\r
+{\r
+  UInt32 *_buf;\r
+public:\r
+  CUInt32Buf(): _buf(0) {}\r
+  ~CUInt32Buf() { Free(); }\r
+  void Free();\r
+  bool Allocate(UInt32 numItems);\r
+  operator UInt32 *() const { return _buf; };\r
+};\r
+\r
+namespace NFatID\r
+{\r
+  const UInt32 kFree       = 0xFFFFFFFF;\r
+  const UInt32 kEndOfChain = 0xFFFFFFFE;\r
+  const UInt32 kFatSector  = 0xFFFFFFFD;\r
+  const UInt32 kMatSector  = 0xFFFFFFFC;\r
+  const UInt32 kMaxValue   = 0xFFFFFFFA;\r
+}\r
+\r
+namespace NItemType\r
+{\r
+  const Byte kEmpty = 0;\r
+  const Byte kStorage = 1;\r
+  const Byte kStream = 2;\r
+  const Byte kLockBytes = 3;\r
+  const Byte kProperty = 4;\r
+  const Byte kRootStorage = 5;\r
+}\r
+\r
+const UInt32 kNameSizeMax = 64;\r
+\r
+struct CItem\r
+{\r
+  Byte Name[kNameSizeMax];\r
+  // UInt16 NameSize;\r
+  // UInt32 Flags;\r
+  FILETIME CTime;\r
+  FILETIME MTime;\r
+  UInt64 Size;\r
+  UInt32 LeftDid;\r
+  UInt32 RightDid;\r
+  UInt32 SonDid;\r
+  UInt32 Sid;\r
+  Byte Type;\r
+\r
+  bool IsEmpty() const { return Type == NItemType::kEmpty; }\r
+  bool IsDir() const { return Type == NItemType::kStorage || Type == NItemType::kRootStorage; }\r
+\r
+  void Parse(const Byte *p, bool mode64bit);\r
+};\r
+\r
+struct CRef\r
+{\r
+  int Parent;\r
+  UInt32 Did;\r
+};\r
+\r
+class CDatabase\r
+{\r
+  UInt32 NumSectorsInMiniStream;\r
+  CUInt32Buf MiniSids;\r
+\r
+  HRESULT AddNode(int parent, UInt32 did);\r
+public:\r
+\r
+  CUInt32Buf Fat;\r
+  UInt32 FatSize;\r
+  \r
+  CUInt32Buf Mat;\r
+  UInt32 MatSize;\r
+\r
+  CObjectVector<CItem> Items;\r
+  CRecordVector<CRef> Refs;\r
+\r
+  UInt32 LongStreamMinSize;\r
+  int SectorSizeBits;\r
+  int MiniSectorSizeBits;\r
+\r
+  Int32 MainSubfile;\r
+\r
+  void Clear();\r
+  bool IsLargeStream(UInt64 size) const { return size >= LongStreamMinSize; }\r
+  UString GetItemPath(UInt32 index) const;\r
+\r
+  UInt64 GetItemPackSize(UInt64 size) const\r
+  {\r
+    UInt64 mask = ((UInt64)1 << (IsLargeStream(size) ? SectorSizeBits : MiniSectorSizeBits)) - 1;\r
+    return (size + mask) & ~mask;\r
+  }\r
+\r
+  bool GetMiniCluster(UInt32 sid, UInt64 &res) const\r
+  {\r
+    int subBits = SectorSizeBits - MiniSectorSizeBits;\r
+    UInt32 fid = sid >> subBits;\r
+    if (fid >= NumSectorsInMiniStream)\r
+      return false;\r
+    res = (((UInt64)MiniSids[fid] + 1) << subBits) + (sid & ((1 << subBits) - 1));\r
+    return true;\r
+  }\r
+\r
+  HRESULT Open(IInStream *inStream);\r
+};\r
+\r
+\r
+}}\r
+  \r
+#endif\r
diff --git a/CPP/7zip/Archive/Com/ComRegister.cpp b/CPP/7zip/Archive/Com/ComRegister.cpp
new file mode 100755 (executable)
index 0000000..46a6810
--- /dev/null
@@ -0,0 +1,13 @@
+// ComRegister.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/RegisterArc.h"\r
+\r
+#include "ComHandler.h"\r
+static IInArchive *CreateArc() { return new NArchive::NCom::CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"Compound", L"msi msp doc xls ppt", 0, 0xE5, { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }, 8, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Com)\r
diff --git a/CPP/7zip/Archive/Common/CoderMixer.cpp b/CPP/7zip/Archive/Common/CoderMixer.cpp
new file mode 100755 (executable)
index 0000000..8a4b038
--- /dev/null
@@ -0,0 +1,19 @@
+// CoderMixer.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "CoderMixer.h"\r
+\r
+namespace NCoderMixer {\r
+\r
+void CCoderInfo::SetCoderInfo(const UInt64 *inSize, const UInt64 *outSize)\r
+{\r
+  InSizeAssigned = (inSize != 0);\r
+  if (InSizeAssigned)\r
+    InSizeValue = *inSize;\r
+  OutSizeAssigned = (outSize != 0);\r
+  if (OutSizeAssigned)\r
+    OutSizeValue = *outSize;\r
+}\r
+\r
+}\r
diff --git a/CPP/7zip/Archive/Common/CoderMixer.h b/CPP/7zip/Archive/Common/CoderMixer.h
new file mode 100755 (executable)
index 0000000..aefe702
--- /dev/null
@@ -0,0 +1,32 @@
+// CoderMixer.h\r
+\r
+#ifndef __CODER_MIXER_H\r
+#define __CODER_MIXER_H\r
+\r
+#include "../../../Common/MyCom.h"\r
+#include "../../ICoder.h"\r
+\r
+namespace NCoderMixer {\r
+\r
+struct CCoderInfo\r
+{\r
+  CMyComPtr<ICompressCoder> Coder;\r
+  CMyComPtr<ISequentialInStream> InStream;\r
+  CMyComPtr<ISequentialOutStream> OutStream;\r
+  CMyComPtr<ICompressProgressInfo> Progress;\r
+\r
+  UInt64 InSizeValue;\r
+  UInt64 OutSizeValue;\r
+  bool InSizeAssigned;\r
+  bool OutSizeAssigned;\r
+\r
+  void ReInit()\r
+  {\r
+    InSizeAssigned = OutSizeAssigned = false;\r
+  }\r
+\r
+  void SetCoderInfo(const UInt64 *inSize, const UInt64 *outSize);\r
+};\r
+\r
+}\r
+#endif\r
diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp
new file mode 100755 (executable)
index 0000000..417e8a7
--- /dev/null
@@ -0,0 +1,121 @@
+// CoderMixer2.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "CoderMixer2.h"\r
+\r
+namespace NCoderMixer {\r
+\r
+CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo):\r
+  _srcBindInfo(srcBindInfo)\r
+{\r
+  srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams);\r
+\r
+  UInt32  j;\r
+  for (j = 0; j < NumSrcInStreams; j++)\r
+  {\r
+    _srcInToDestOutMap.Add(0);\r
+    DestOutToSrcInMap.Add(0);\r
+  }\r
+  for (j = 0; j < _numSrcOutStreams; j++)\r
+  {\r
+    _srcOutToDestInMap.Add(0);\r
+    _destInToSrcOutMap.Add(0);\r
+  }\r
+\r
+  UInt32 destInOffset = 0;\r
+  UInt32 destOutOffset = 0;\r
+  UInt32 srcInOffset = NumSrcInStreams;\r
+  UInt32 srcOutOffset = _numSrcOutStreams;\r
+\r
+  for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--)\r
+  {\r
+    const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i];\r
+\r
+    srcInOffset -= srcCoderInfo.NumInStreams;\r
+    srcOutOffset -= srcCoderInfo.NumOutStreams;\r
+    \r
+    UInt32 j;\r
+    for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++)\r
+    {\r
+      UInt32 index = srcInOffset + j;\r
+      _srcInToDestOutMap[index] = destOutOffset;\r
+      DestOutToSrcInMap[destOutOffset] = index;\r
+    }\r
+    for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++)\r
+    {\r
+      UInt32 index = srcOutOffset + j;\r
+      _srcOutToDestInMap[index] = destInOffset;\r
+      _destInToSrcOutMap[destInOffset] = index;\r
+    }\r
+  }\r
+}\r
+\r
+void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo)\r
+{\r
+  destBindInfo.Coders.Clear();\r
+  destBindInfo.BindPairs.Clear();\r
+  destBindInfo.InStreams.Clear();\r
+  destBindInfo.OutStreams.Clear();\r
+\r
+  int i;\r
+  for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--)\r
+  {\r
+    const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i];\r
+    CCoderStreamsInfo destCoderInfo;\r
+    destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams;\r
+    destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams;\r
+    destBindInfo.Coders.Add(destCoderInfo);\r
+  }\r
+  for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--)\r
+  {\r
+    const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i];\r
+    CBindPair destBindPair;\r
+    destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex];\r
+    destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex];\r
+    destBindInfo.BindPairs.Add(destBindPair);\r
+  }\r
+  for (i = 0; i < _srcBindInfo.InStreams.Size(); i++)\r
+    destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]);\r
+  for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++)\r
+    destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]);\r
+}\r
+\r
+CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams):\r
+    NumInStreams(numInStreams),\r
+    NumOutStreams(numOutStreams)\r
+{\r
+  InSizes.Reserve(NumInStreams);\r
+  InSizePointers.Reserve(NumInStreams);\r
+  OutSizes.Reserve(NumOutStreams);\r
+  OutSizePointers.Reserve(NumOutStreams);\r
+}\r
+\r
+static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,\r
+    CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)\r
+{\r
+  sizes.Clear();\r
+  sizePointers.Clear();\r
+  for(UInt32 i = 0; i < numItems; i++)\r
+  {\r
+    if (srcSizes == 0 || srcSizes[i] == NULL)\r
+    {\r
+      sizes.Add(0);\r
+      sizePointers.Add(NULL);\r
+    }\r
+    else\r
+    {\r
+      sizes.Add(*srcSizes[i]);\r
+      sizePointers.Add(&sizes.Back());\r
+    }\r
+  }\r
+}\r
+\r
+void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes,\r
+      const UInt64 **outSizes)\r
+{\r
+  SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);\r
+  SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);\r
+}\r
+\r
+}\r
diff --git a/CPP/7zip/Archive/Common/CoderMixer2.h b/CPP/7zip/Archive/Common/CoderMixer2.h
new file mode 100755 (executable)
index 0000000..b1893b2
--- /dev/null
@@ -0,0 +1,174 @@
+// CoderMixer2.h\r
+\r
+#ifndef __CODER_MIXER2_H\r
+#define __CODER_MIXER2_H\r
+\r
+#include "../../../Common/MyVector.h"\r
+#include "../../../Common/Types.h"\r
+#include "../../../Common/MyCom.h"\r
+#include "../../ICoder.h"\r
+\r
+namespace NCoderMixer {\r
+\r
+struct CBindPair\r
+{\r
+  UInt32 InIndex;\r
+  UInt32 OutIndex;\r
+};\r
+\r
+struct CCoderStreamsInfo\r
+{\r
+  UInt32 NumInStreams;\r
+  UInt32 NumOutStreams;\r
+};\r
+\r
+struct CBindInfo\r
+{\r
+  CRecordVector<CCoderStreamsInfo> Coders;\r
+  CRecordVector<CBindPair> BindPairs;\r
+  CRecordVector<UInt32> InStreams;\r
+  CRecordVector<UInt32> OutStreams;\r
+\r
+  void Clear()\r
+  {\r
+    Coders.Clear();\r
+    BindPairs.Clear();\r
+    InStreams.Clear();\r
+    OutStreams.Clear();\r
+  }\r
+\r
+  /*\r
+  UInt32 GetCoderStartOutStream(UInt32 coderIndex) const\r
+  {\r
+    UInt32 numOutStreams = 0;\r
+    for (UInt32 i = 0; i < coderIndex; i++)\r
+      numOutStreams += Coders[i].NumOutStreams;\r
+    return numOutStreams;\r
+  }\r
+  */\r
+\r
+\r
+  void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const\r
+  {\r
+    numInStreams = 0;\r
+    numOutStreams = 0;\r
+    for (int i = 0; i < Coders.Size(); i++)\r
+    {\r
+      const CCoderStreamsInfo &coderStreamsInfo = Coders[i];\r
+      numInStreams += coderStreamsInfo.NumInStreams;\r
+      numOutStreams += coderStreamsInfo.NumOutStreams;\r
+    }\r
+  }\r
+\r
+  int FindBinderForInStream(UInt32 inStream) const\r
+  {\r
+    for (int i = 0; i < BindPairs.Size(); i++)\r
+      if (BindPairs[i].InIndex == inStream)\r
+        return i;\r
+    return -1;\r
+  }\r
+  int FindBinderForOutStream(UInt32 outStream) const\r
+  {\r
+    for (int i = 0; i < BindPairs.Size(); i++)\r
+      if (BindPairs[i].OutIndex == outStream)\r
+        return i;\r
+    return -1;\r
+  }\r
+\r
+  UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const\r
+  {\r
+    UInt32 streamIndex = 0;\r
+    for (UInt32 i = 0; i < coderIndex; i++)\r
+      streamIndex += Coders[i].NumInStreams;\r
+    return streamIndex;\r
+  }\r
+\r
+  UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const\r
+  {\r
+    UInt32 streamIndex = 0;\r
+    for (UInt32 i = 0; i < coderIndex; i++)\r
+      streamIndex += Coders[i].NumOutStreams;\r
+    return streamIndex;\r
+  }\r
+\r
+\r
+  void FindInStream(UInt32 streamIndex, UInt32 &coderIndex,\r
+      UInt32 &coderStreamIndex) const\r
+  {\r
+    for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)\r
+    {\r
+      UInt32 curSize = Coders[coderIndex].NumInStreams;\r
+      if (streamIndex < curSize)\r
+      {\r
+        coderStreamIndex = streamIndex;\r
+        return;\r
+      }\r
+      streamIndex -= curSize;\r
+    }\r
+    throw 1;\r
+  }\r
+  void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex,\r
+      UInt32 &coderStreamIndex) const\r
+  {\r
+    for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)\r
+    {\r
+      UInt32 curSize = Coders[coderIndex].NumOutStreams;\r
+      if (streamIndex < curSize)\r
+      {\r
+        coderStreamIndex = streamIndex;\r
+        return;\r
+      }\r
+      streamIndex -= curSize;\r
+    }\r
+    throw 1;\r
+  }\r
+};\r
+\r
+class CBindReverseConverter\r
+{\r
+  UInt32 _numSrcOutStreams;\r
+  NCoderMixer::CBindInfo _srcBindInfo;\r
+  CRecordVector<UInt32> _srcInToDestOutMap;\r
+  CRecordVector<UInt32> _srcOutToDestInMap;\r
+  CRecordVector<UInt32> _destInToSrcOutMap;\r
+public:\r
+  UInt32 NumSrcInStreams;\r
+  CRecordVector<UInt32> DestOutToSrcInMap;\r
+\r
+  CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo);\r
+  void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo);\r
+};\r
+\r
+struct CCoderInfo2\r
+{\r
+  CMyComPtr<ICompressCoder> Coder;\r
+  CMyComPtr<ICompressCoder2> Coder2;\r
+  UInt32 NumInStreams;\r
+  UInt32 NumOutStreams;\r
+\r
+  CRecordVector<UInt64> InSizes;\r
+  CRecordVector<UInt64> OutSizes;\r
+  CRecordVector<const UInt64 *> InSizePointers;\r
+  CRecordVector<const UInt64 *> OutSizePointers;\r
+\r
+  CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams);\r
+  void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);\r
+\r
+  HRESULT QueryInterface(REFGUID iid, void** pp) const\r
+  {\r
+    IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;\r
+    return p->QueryInterface(iid, pp);\r
+  }\r
+};\r
+\r
+class CCoderMixer2\r
+{\r
+public:\r
+  virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0;\r
+  virtual void ReInit() = 0;\r
+  virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0;\r
+};\r
+\r
+}\r
+#endif\r
+\r
diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
new file mode 100755 (executable)
index 0000000..3047b13
--- /dev/null
@@ -0,0 +1,240 @@
+// CoderMixer2MT.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "CoderMixer2MT.h"\r
+\r
+namespace NCoderMixer {\r
+\r
+CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams):\r
+    CCoderInfo2(numInStreams, numOutStreams)\r
+{\r
+  InStreams.Reserve(NumInStreams);\r
+  InStreamPointers.Reserve(NumInStreams);\r
+  OutStreams.Reserve(NumOutStreams);\r
+  OutStreamPointers.Reserve(NumOutStreams);\r
+}\r
+\r
+void CCoder2::Execute() { Code(NULL); }\r
+\r
+void CCoder2::Code(ICompressProgressInfo *progress)\r
+{\r
+  InStreamPointers.Clear();\r
+  OutStreamPointers.Clear();\r
+  UInt32 i;\r
+  for (i = 0; i < NumInStreams; i++)\r
+  {\r
+    if (InSizePointers[i] != NULL)\r
+      InSizePointers[i] = &InSizes[i];\r
+    InStreamPointers.Add((ISequentialInStream *)InStreams[i]);\r
+  }\r
+  for (i = 0; i < NumOutStreams; i++)\r
+  {\r
+    if (OutSizePointers[i] != NULL)\r
+      OutSizePointers[i] = &OutSizes[i];\r
+    OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]);\r
+  }\r
+  if (Coder)\r
+    Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],\r
+        InSizePointers[0], OutSizePointers[0], progress);\r
+  else\r
+    Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams,\r
+      &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress);\r
+  {\r
+    int i;\r
+    for (i = 0; i < InStreams.Size(); i++)\r
+      InStreams[i].Release();\r
+    for (i = 0; i < OutStreams.Size(); i++)\r
+      OutStreams[i].Release();\r
+  }\r
+}\r
+\r
+static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,\r
+    CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)\r
+{\r
+  sizes.Clear();\r
+  sizePointers.Clear();\r
+  for (UInt32 i = 0; i < numItems; i++)\r
+  {\r
+    if (srcSizes == 0 || srcSizes[i] == NULL)\r
+    {\r
+      sizes.Add(0);\r
+      sizePointers.Add(NULL);\r
+    }\r
+    else\r
+    {\r
+      sizes.Add(*srcSizes[i]);\r
+      sizePointers.Add(&sizes.Back());\r
+    }\r
+  }\r
+}\r
+\r
+\r
+void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)\r
+{\r
+  SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);\r
+  SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);\r
+}\r
+\r
+//////////////////////////////////////\r
+// CCoderMixer2MT\r
+\r
+HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)\r
+{\r
+  _bindInfo = bindInfo;\r
+  _streamBinders.Clear();\r
+  for (int i = 0; i < _bindInfo.BindPairs.Size(); i++)\r
+  {\r
+    _streamBinders.Add(CStreamBinder());\r
+    RINOK(_streamBinders.Back().CreateEvents());\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+void CCoderMixer2MT::AddCoderCommon()\r
+{\r
+  const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()];\r
+  CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams);\r
+  _coders.Add(threadCoderInfo);\r
+}\r
+\r
+void CCoderMixer2MT::AddCoder(ICompressCoder *coder)\r
+{\r
+  AddCoderCommon();\r
+  _coders.Back().Coder = coder;\r
+}\r
+\r
+void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)\r
+{\r
+  AddCoderCommon();\r
+  _coders.Back().Coder2 = coder;\r
+}\r
+\r
+\r
+void CCoderMixer2MT::ReInit()\r
+{\r
+  for (int i = 0; i < _streamBinders.Size(); i++)\r
+    _streamBinders[i].ReInit();\r
+}\r
+\r
+\r
+HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams)\r
+{\r
+  /*\r
+  if (_coders.Size() != _bindInfo.Coders.Size())\r
+    throw 0;\r
+  */\r
+  int i;\r
+  for (i = 0; i < _coders.Size(); i++)\r
+  {\r
+    CCoder2 &coderInfo = _coders[i];\r
+    const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i];\r
+    coderInfo.InStreams.Clear();\r
+    UInt32 j;\r
+    for (j = 0; j < coderStreamsInfo.NumInStreams; j++)\r
+      coderInfo.InStreams.Add(NULL);\r
+    coderInfo.OutStreams.Clear();\r
+    for (j = 0; j < coderStreamsInfo.NumOutStreams; j++)\r
+      coderInfo.OutStreams.Add(NULL);\r
+  }\r
+\r
+  for (i = 0; i < _bindInfo.BindPairs.Size(); i++)\r
+  {\r
+    const CBindPair &bindPair = _bindInfo.BindPairs[i];\r
+    UInt32 inCoderIndex, inCoderStreamIndex;\r
+    UInt32 outCoderIndex, outCoderStreamIndex;\r
+    _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex);\r
+    _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex);\r
+\r
+    _streamBinders[i].CreateStreams(\r
+        &_coders[inCoderIndex].InStreams[inCoderStreamIndex],\r
+        &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]);\r
+\r
+    CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize;\r
+    _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize);\r
+    _coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize);\r
+    if (inSetSize && outSetSize)\r
+    {\r
+      const UInt32 kBufSize = 1 << 19;\r
+      inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize);\r
+      outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize);\r
+    }\r
+  }\r
+\r
+  for (i = 0; i < _bindInfo.InStreams.Size(); i++)\r
+  {\r
+    UInt32 inCoderIndex, inCoderStreamIndex;\r
+    _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex);\r
+    _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i];\r
+  }\r
+  \r
+  for (i = 0; i < _bindInfo.OutStreams.Size(); i++)\r
+  {\r
+    UInt32 outCoderIndex, outCoderStreamIndex;\r
+    _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex);\r
+    _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i];\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code)\r
+{\r
+  for (int i = 0; i < _coders.Size(); i++)\r
+    if (_coders[i].Result == code)\r
+      return code;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,\r
+      const UInt64 ** /* inSizes */,\r
+      UInt32 numInStreams,\r
+      ISequentialOutStream **outStreams,\r
+      const UInt64 ** /* outSizes */,\r
+      UInt32 numOutStreams,\r
+      ICompressProgressInfo *progress)\r
+{\r
+  if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||\r
+      numOutStreams != (UInt32)_bindInfo.OutStreams.Size())\r
+    return E_INVALIDARG;\r
+\r
+  Init(inStreams, outStreams);\r
+\r
+  int i;\r
+  for (i = 0; i < _coders.Size(); i++)\r
+    if (i != _progressCoderIndex)\r
+    {\r
+      RINOK(_coders[i].Create());\r
+    }\r
+\r
+  for (i = 0; i < _coders.Size(); i++)\r
+    if (i != _progressCoderIndex)\r
+      _coders[i].Start();\r
+\r
+  _coders[_progressCoderIndex].Code(progress);\r
+\r
+  for (i = 0; i < _coders.Size(); i++)\r
+    if (i != _progressCoderIndex)\r
+      _coders[i].WaitFinish();\r
+\r
+  RINOK(ReturnIfError(E_ABORT));\r
+  RINOK(ReturnIfError(E_OUTOFMEMORY));\r
+\r
+  for (i = 0; i < _coders.Size(); i++)\r
+  {\r
+    HRESULT result = _coders[i].Result;\r
+    if (result != S_OK && result != E_FAIL && result != S_FALSE)\r
+      return result;\r
+  }\r
+\r
+  RINOK(ReturnIfError(S_FALSE));\r
+\r
+  for (i = 0; i < _coders.Size(); i++)\r
+  {\r
+    HRESULT result = _coders[i].Result;\r
+    if (result != S_OK)\r
+      return result;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+}\r
diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.h b/CPP/7zip/Archive/Common/CoderMixer2MT.h
new file mode 100755 (executable)
index 0000000..acecc39
--- /dev/null
@@ -0,0 +1,80 @@
+// CoderMixer2MT.h\r
+\r
+#ifndef __CODER_MIXER2_MT_H\r
+#define __CODER_MIXER2_MT_H\r
+\r
+#include "CoderMixer2.h"\r
+#include "../../../Common/MyCom.h"\r
+#include "../../Common/StreamBinder.h"\r
+#include "../../Common/VirtThread.h"\r
+\r
+namespace NCoderMixer {\r
+\r
+struct CCoder2: public CCoderInfo2, public CVirtThread\r
+{\r
+  HRESULT Result;\r
+  CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;\r
+  CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;\r
+  CRecordVector<ISequentialInStream*> InStreamPointers;\r
+  CRecordVector<ISequentialOutStream*> OutStreamPointers;\r
+\r
+  CCoder2(UInt32 numInStreams, UInt32 numOutStreams);\r
+  void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);\r
+  virtual void Execute();\r
+  void Code(ICompressProgressInfo *progress);\r
+};\r
+\r
+\r
+/*\r
+  SetBindInfo()\r
+  for each coder\r
+    AddCoder[2]()\r
+  SetProgressIndex(UInt32 coderIndex);\r
\r
+  for each file\r
+  {\r
+    ReInit()\r
+    for each coder\r
+      SetCoderInfo\r
+    Code\r
+  }\r
+*/\r
+\r
+class CCoderMixer2MT:\r
+  public ICompressCoder2,\r
+  public CCoderMixer2,\r
+  public CMyUnknownImp\r
+{\r
+  CBindInfo _bindInfo;\r
+  CObjectVector<CStreamBinder> _streamBinders;\r
+  int _progressCoderIndex;\r
+\r
+  void AddCoderCommon();\r
+  HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams);\r
+  HRESULT ReturnIfError(HRESULT code);\r
+public:\r
+  CObjectVector<CCoder2> _coders;\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(Code)(ISequentialInStream **inStreams,\r
+      const UInt64 **inSizes,\r
+      UInt32 numInStreams,\r
+      ISequentialOutStream **outStreams,\r
+      const UInt64 **outSizes,\r
+      UInt32 numOutStreams,\r
+      ICompressProgressInfo *progress);\r
+\r
+  HRESULT SetBindInfo(const CBindInfo &bindInfo);\r
+  void AddCoder(ICompressCoder *coder);\r
+  void AddCoder2(ICompressCoder2 *coder);\r
+  void SetProgressCoderIndex(int coderIndex) {  _progressCoderIndex = coderIndex; }\r
+\r
+  void ReInit();\r
+  void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes)\r
+    {  _coders[coderIndex].SetCoderInfo(inSizes, outSizes); }\r
+  UInt64 GetWriteProcessedSize(UInt32 binderIndex) const\r
+    {  return _streamBinders[binderIndex].ProcessedSize; }\r
+};\r
+\r
+}\r
+#endif\r
diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp
new file mode 100755 (executable)
index 0000000..4d9916e
--- /dev/null
@@ -0,0 +1,239 @@
+// CoderMixer2ST.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "CoderMixer2ST.h"\r
+\r
+namespace NCoderMixer2 {\r
+\r
+CCoderMixer2ST::CCoderMixer2ST() {}\r
+\r
+CCoderMixer2ST::~CCoderMixer2ST(){ }\r
+\r
+HRESULT CCoderMixer2ST::SetBindInfo(const CBindInfo &bindInfo)\r
+{\r
+  _bindInfo = bindInfo;\r
+  return S_OK;\r
+}\r
+\r
+void CCoderMixer2ST::AddCoderCommon(bool isMain)\r
+{\r
+  const CCoderStreamsInfo &csi = _bindInfo.Coders[_coders.Size()];\r
+  _coders.Add(CSTCoderInfo(csi.NumInStreams, csi.NumOutStreams, isMain));\r
+}\r
+\r
+void CCoderMixer2ST::AddCoder(ICompressCoder *coder, bool isMain)\r
+{\r
+  AddCoderCommon(isMain);\r
+  _coders.Back().Coder = coder;\r
+}\r
+\r
+void CCoderMixer2ST::AddCoder2(ICompressCoder2 *coder, bool isMain)\r
+{\r
+  AddCoderCommon(isMain);\r
+  _coders.Back().Coder2 = coder;\r
+}\r
+\r
+void CCoderMixer2ST::ReInit() { }\r
+\r
+HRESULT CCoderMixer2ST::GetInStream(\r
+    ISequentialInStream **inStreams, const UInt64 **inSizes,\r
+    UInt32 streamIndex, ISequentialInStream **inStreamRes)\r
+{\r
+  CMyComPtr<ISequentialInStream> seqInStream;\r
+  int i;\r
+  for(i = 0; i < _bindInfo.InStreams.Size(); i++)\r
+    if (_bindInfo.InStreams[i] == streamIndex)\r
+    {\r
+      seqInStream = inStreams[i];\r
+      *inStreamRes = seqInStream.Detach();\r
+      return  S_OK;\r
+    }\r
+  int binderIndex = _bindInfo.FindBinderForInStream(streamIndex);\r
+  if (binderIndex < 0)\r
+    return E_INVALIDARG;\r
+\r
+  UInt32 coderIndex, coderStreamIndex;\r
+  _bindInfo.FindOutStream(_bindInfo.BindPairs[binderIndex].OutIndex,\r
+      coderIndex, coderStreamIndex);\r
+\r
+  CCoderInfo &coder = _coders[coderIndex];\r
+  if (!coder.Coder)\r
+    return E_NOTIMPL;\r
+  coder.Coder.QueryInterface(IID_ISequentialInStream, &seqInStream);\r
+  if (!seqInStream)\r
+    return E_NOTIMPL;\r
+\r
+  UInt32 startIndex = _bindInfo.GetCoderInStreamIndex(coderIndex);\r
+\r
+  CMyComPtr<ICompressSetInStream> setInStream;\r
+  if (!coder.Coder)\r
+    return E_NOTIMPL;\r
+  coder.Coder.QueryInterface(IID_ICompressSetInStream, &setInStream);\r
+  if (!setInStream)\r
+    return E_NOTIMPL;\r
+\r
+  if (coder.NumInStreams > 1)\r
+    return E_NOTIMPL;\r
+  for (i = 0; i < (int)coder.NumInStreams; i++)\r
+  {\r
+    CMyComPtr<ISequentialInStream> seqInStream2;\r
+    RINOK(GetInStream(inStreams, inSizes, startIndex + i, &seqInStream2));\r
+    RINOK(setInStream->SetInStream(seqInStream2));\r
+  }\r
+  *inStreamRes = seqInStream.Detach();\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CCoderMixer2ST::GetOutStream(\r
+    ISequentialOutStream **outStreams, const UInt64 **outSizes,\r
+    UInt32 streamIndex, ISequentialOutStream **outStreamRes)\r
+{\r
+  CMyComPtr<ISequentialOutStream> seqOutStream;\r
+  int i;\r
+  for(i = 0; i < _bindInfo.OutStreams.Size(); i++)\r
+    if (_bindInfo.OutStreams[i] == streamIndex)\r
+    {\r
+      seqOutStream = outStreams[i];\r
+      *outStreamRes = seqOutStream.Detach();\r
+      return  S_OK;\r
+    }\r
+  int binderIndex = _bindInfo.FindBinderForOutStream(streamIndex);\r
+  if (binderIndex < 0)\r
+    return E_INVALIDARG;\r
+\r
+  UInt32 coderIndex, coderStreamIndex;\r
+  _bindInfo.FindInStream(_bindInfo.BindPairs[binderIndex].InIndex,\r
+      coderIndex, coderStreamIndex);\r
+\r
+  CCoderInfo &coder = _coders[coderIndex];\r
+  if (!coder.Coder)\r
+    return E_NOTIMPL;\r
+  coder.Coder.QueryInterface(IID_ISequentialOutStream, &seqOutStream);\r
+  if (!seqOutStream)\r
+    return E_NOTIMPL;\r
+\r
+  UInt32 startIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);\r
+\r
+  CMyComPtr<ICompressSetOutStream> setOutStream;\r
+  if (!coder.Coder)\r
+    return E_NOTIMPL;\r
+  coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);\r
+  if (!setOutStream)\r
+    return E_NOTIMPL;\r
+\r
+  if (coder.NumOutStreams > 1)\r
+    return E_NOTIMPL;\r
+  for (i = 0; i < (int)coder.NumOutStreams; i++)\r
+  {\r
+    CMyComPtr<ISequentialOutStream> seqOutStream2;\r
+    RINOK(GetOutStream(outStreams, outSizes, startIndex + i, &seqOutStream2));\r
+    RINOK(setOutStream->SetOutStream(seqOutStream2));\r
+  }\r
+  *outStreamRes = seqOutStream.Detach();\r
+  return S_OK;\r
+}\r
+    \r
+\r
+STDMETHODIMP CCoderMixer2ST::Code(ISequentialInStream **inStreams,\r
+      const UInt64 **inSizes,\r
+      UInt32 numInStreams,\r
+      ISequentialOutStream **outStreams,\r
+      const UInt64 **outSizes,\r
+      UInt32 numOutStreams,\r
+      ICompressProgressInfo *progress)\r
+{\r
+  if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||\r
+      numOutStreams != (UInt32)_bindInfo.OutStreams.Size())\r
+    return E_INVALIDARG;\r
+\r
+  // Find main coder\r
+  int _mainCoderIndex = -1;\r
+  int i;\r
+  for (i = 0; i < _coders.Size(); i++)\r
+    if (_coders[i].IsMain)\r
+    {\r
+      _mainCoderIndex = i;\r
+      break;\r
+    }\r
+  if (_mainCoderIndex < 0)\r
+  for (i = 0; i < _coders.Size(); i++)\r
+    if (_coders[i].NumInStreams > 1)\r
+    {\r
+      if (_mainCoderIndex >= 0)\r
+        return E_NOTIMPL;\r
+      _mainCoderIndex = i;\r
+    }\r
+  if (_mainCoderIndex < 0)\r
+    _mainCoderIndex = 0;\r
\r
+  // _mainCoderIndex = 0;\r
+  // _mainCoderIndex = _coders.Size() - 1;\r
+  CCoderInfo &mainCoder = _coders[_mainCoderIndex];\r
+\r
+  CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;\r
+  CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;\r
+  UInt32 startInIndex = _bindInfo.GetCoderInStreamIndex(_mainCoderIndex);\r
+  UInt32 startOutIndex = _bindInfo.GetCoderOutStreamIndex(_mainCoderIndex);\r
+  for (i = 0; i < (int)mainCoder.NumInStreams; i++)\r
+  {\r
+    CMyComPtr<ISequentialInStream> seqInStream;\r
+    RINOK(GetInStream(inStreams, inSizes, startInIndex + i, &seqInStream));\r
+    seqInStreams.Add(seqInStream);\r
+  }\r
+  for (i = 0; i < (int)mainCoder.NumOutStreams; i++)\r
+  {\r
+    CMyComPtr<ISequentialOutStream> seqOutStream;\r
+    RINOK(GetOutStream(outStreams, outSizes, startOutIndex + i, &seqOutStream));\r
+    seqOutStreams.Add(seqOutStream);\r
+  }\r
+  CRecordVector< ISequentialInStream * > seqInStreamsSpec;\r
+  CRecordVector< ISequentialOutStream * > seqOutStreamsSpec;\r
+  for (i = 0; i < (int)mainCoder.NumInStreams; i++)\r
+    seqInStreamsSpec.Add(seqInStreams[i]);\r
+  for (i = 0; i < (int)mainCoder.NumOutStreams; i++)\r
+    seqOutStreamsSpec.Add(seqOutStreams[i]);\r
+\r
+  for (i = 0; i < _coders.Size(); i++)\r
+  {\r
+    if (i == _mainCoderIndex)\r
+      continue;\r
+    CCoderInfo &coder = _coders[i];\r
+    CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;\r
+    coder.Coder.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);\r
+    if (setOutStreamSize)\r
+    {\r
+      RINOK(setOutStreamSize->SetOutStreamSize(coder.OutSizePointers[0]));\r
+    }\r
+  }\r
+  if (mainCoder.Coder)\r
+  {\r
+    RINOK(mainCoder.Coder->Code(\r
+        seqInStreamsSpec[0], seqOutStreamsSpec[0],\r
+        mainCoder.InSizePointers[0], mainCoder.OutSizePointers[0],\r
+        progress));\r
+  }\r
+  else\r
+  {\r
+    RINOK(mainCoder.Coder2->Code(\r
+        &seqInStreamsSpec.Front(),\r
+        &mainCoder.InSizePointers.Front(), mainCoder.NumInStreams,\r
+        &seqOutStreamsSpec.Front(),\r
+        &mainCoder.OutSizePointers.Front(), mainCoder.NumOutStreams,\r
+        progress));\r
+  }\r
+  CMyComPtr<IOutStreamFlush> flush;\r
+  seqOutStreams.Front().QueryInterface(IID_IOutStreamFlush, &flush);\r
+  if (flush)\r
+    return flush->Flush();\r
+  return S_OK;\r
+}\r
+\r
+/*\r
+UInt64 CCoderMixer2ST::GetWriteProcessedSize(UInt32 binderIndex) const\r
+{\r
+  return _streamBinders[binderIndex].ProcessedSize;\r
+}\r
+*/\r
+\r
+}\r
diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.h b/CPP/7zip/Archive/Common/CoderMixer2ST.h
new file mode 100755 (executable)
index 0000000..fee21d5
--- /dev/null
@@ -0,0 +1,88 @@
+// CoderMixer2ST.h\r
+\r
+#ifndef __CODER_MIXER2_ST_H\r
+#define __CODER_MIXER2_ST_H\r
+\r
+#include "CoderMixer2.h"\r
+#include "../../../Common/MyCom.h"\r
+#include "../../ICoder.h"\r
+\r
+namespace NCoderMixer2 {\r
+\r
+//  SetBindInfo()\r
+//  for each coder\r
+//  {\r
+//    AddCoder[2]()\r
+//  }\r
+//\r
+//  for each file\r
+//  {\r
+//    ReInit()\r
+//    for each coder\r
+//    {\r
+//      SetCoderInfo\r
+//    }\r
+//    SetProgressIndex(UInt32 coderIndex);\r
+//    Code\r
+//  }\r
+\r
+struct CSTCoderInfo: public CCoderInfo\r
+{\r
+  bool IsMain;\r
+  CSTCoderInfo(UInt32 numInStreams, UInt32 numOutStreams, bool isMain):\r
+    CCoderInfo(numInStreams, numOutStreams),IsMain(isMain) {}\r
+};\r
+\r
+class CCoderMixer2ST:\r
+  public ICompressCoder2,\r
+  public CCoderMixer2,\r
+  public CMyUnknownImp\r
+{\r
+  MY_UNKNOWN_IMP\r
+\r
+  HRESULT GetInStream(\r
+    ISequentialInStream **inStreams, const UInt64 **inSizes,\r
+    UInt32 streamIndex, ISequentialInStream **inStreamRes);\r
+  HRESULT GetOutStream(\r
+    ISequentialOutStream **outStreams, const UInt64 **outSizes,\r
+    UInt32 streamIndex, ISequentialOutStream **outStreamRes);\r
+public:\r
+  STDMETHOD(Code)(ISequentialInStream **inStreams,\r
+      const UInt64 **inSizes,\r
+      UInt32 numInStreams,\r
+      ISequentialOutStream **outStreams,\r
+      const UInt64 **outSizes,\r
+      UInt32 numOutStreams,\r
+      ICompressProgressInfo *progress);\r
+\r
+  CCoderMixer2ST();\r
+  ~CCoderMixer2ST();\r
+  void AddCoderCommon(bool isMain);\r
+  void AddCoder(ICompressCoder *coder, bool isMain);\r
+  void AddCoder2(ICompressCoder2 *coder, bool isMain);\r
+\r
+  void ReInit();\r
+  void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes)\r
+  {\r
+    {  _coders[coderIndex].SetCoderInfo(inSizes, outSizes); }\r
+  }\r
+\r
+  void SetProgressCoderIndex(UInt32 /*coderIndex*/)\r
+  {\r
+    // _progressCoderIndex = coderIndex;\r
+  }\r
+\r
+  // UInt64 GetWriteProcessedSize(UInt32 binderIndex) const;\r
+\r
+private:\r
+  CBindInfo _bindInfo;\r
+  CObjectVector<CSTCoderInfo> _coders;\r
+  int _mainCoderIndex;\r
+public:\r
+  HRESULT SetBindInfo(const CBindInfo &bindInfo);\r
+\r
+};\r
+\r
+}\r
+#endif\r
+\r
diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.cpp b/CPP/7zip/Archive/Common/CoderMixerMT.cpp
new file mode 100755 (executable)
index 0000000..79a6299
--- /dev/null
@@ -0,0 +1,99 @@
+// CoderMixerMT.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "CoderMixerMT.h"\r
+\r
+namespace NCoderMixer {\r
+\r
+void CCoder::Execute() { Code(NULL); }\r
+\r
+void CCoder::Code(ICompressProgressInfo *progress)\r
+{\r
+  Result = Coder->Code(InStream, OutStream,\r
+      InSizeAssigned ? &InSizeValue : NULL,\r
+      OutSizeAssigned ? &OutSizeValue : NULL,\r
+      progress);\r
+  InStream.Release();\r
+  OutStream.Release();\r
+}\r
+\r
+void CCoderMixerMT::AddCoder(ICompressCoder *coder)\r
+{\r
+  _coders.Add(CCoder());\r
+  _coders.Back().Coder = coder;\r
+}\r
+\r
+void CCoderMixerMT::ReInit()\r
+{\r
+  for(int i = 0; i < _coders.Size(); i++)\r
+    _coders[i].ReInit();\r
+}\r
+\r
+HRESULT CCoderMixerMT::ReturnIfError(HRESULT code)\r
+{\r
+  for (int i = 0; i < _coders.Size(); i++)\r
+    if (_coders[i].Result == code)\r
+      return code;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CCoderMixerMT::Code(ISequentialInStream *inStream,\r
+    ISequentialOutStream *outStream,\r
+    const UInt64 * /* inSize */, const UInt64 * /* outSize */,\r
+    ICompressProgressInfo *progress)\r
+{\r
+  _coders.Front().InStream = inStream;\r
+  int i;\r
+  _coders.Back().OutStream = outStream;\r
+\r
+  for (i = 0; i < _coders.Size(); i++)\r
+    if (i != _progressCoderIndex)\r
+    {\r
+      RINOK(_coders[i].Create());\r
+    }\r
+\r
+  _streamBinders.Clear();\r
+  for (i = 0; i + 1 < _coders.Size(); i++)\r
+  {\r
+    _streamBinders.Add(CStreamBinder());\r
+    CStreamBinder &sb = _streamBinders[i];\r
+    RINOK(sb.CreateEvents());\r
+    sb.CreateStreams(&_coders[i + 1].InStream, &_coders[i].OutStream);\r
+  }\r
+\r
+  for(i = 0; i < _streamBinders.Size(); i++)\r
+    _streamBinders[i].ReInit();\r
+\r
+  for (i = 0; i < _coders.Size(); i++)\r
+    if (i != _progressCoderIndex)\r
+      _coders[i].Start();\r
+\r
+  _coders[_progressCoderIndex].Code(progress);\r
+\r
+  for (i = 0; i < _coders.Size(); i++)\r
+    if (i != _progressCoderIndex)\r
+      _coders[i].WaitFinish();\r
+\r
+  RINOK(ReturnIfError(E_ABORT));\r
+  RINOK(ReturnIfError(E_OUTOFMEMORY));\r
+\r
+  for (i = 0; i < _coders.Size(); i++)\r
+  {\r
+    HRESULT result = _coders[i].Result;\r
+    if (result != S_OK && result != E_FAIL && result != S_FALSE)\r
+      return result;\r
+  }\r
+\r
+  RINOK(ReturnIfError(S_FALSE));\r
+  \r
+  for (i = 0; i < _coders.Size(); i++)\r
+  {\r
+    HRESULT result = _coders[i].Result;\r
+    if (result != S_OK)\r
+      return result;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+}\r
diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.h b/CPP/7zip/Archive/Common/CoderMixerMT.h
new file mode 100755 (executable)
index 0000000..346ed1e
--- /dev/null
@@ -0,0 +1,69 @@
+// CoderMixerMT.h\r
+\r
+#ifndef __CODER_MIXER_MT_H\r
+#define __CODER_MIXER_MT_H\r
+\r
+#include "../../../Common/MyVector.h"\r
+#include "../../../Common/MyCom.h"\r
+#include "../../ICoder.h"\r
+#include "../../Common/StreamBinder.h"\r
+#include "../../Common/VirtThread.h"\r
+#include "CoderMixer.h"\r
+\r
+namespace NCoderMixer {\r
+\r
+struct CCoder: public CCoderInfo, public CVirtThread\r
+{\r
+  HRESULT Result;\r
+\r
+  virtual void Execute();\r
+  void Code(ICompressProgressInfo *progress);\r
+};\r
+\r
+/*\r
+  for each coder\r
+    AddCoder()\r
+  SetProgressIndex(UInt32 coderIndex);\r
\r
+  for each file\r
+  {\r
+    ReInit()\r
+    for each coder\r
+      SetCoderInfo\r
+    Code\r
+  }\r
+*/\r
+\r
+\r
+class CCoderMixerMT:\r
+  public ICompressCoder,\r
+  public CMyUnknownImp\r
+{\r
+  CObjectVector<CStreamBinder> _streamBinders;\r
+  int _progressCoderIndex;\r
+\r
+  HRESULT ReturnIfError(HRESULT code);\r
+public:\r
+  CObjectVector<CCoder> _coders;\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(Code)(ISequentialInStream *inStream,\r
+      ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize,\r
+      ICompressProgressInfo *progress);\r
+\r
+  void AddCoder(ICompressCoder *coder);\r
+  void SetProgressCoderIndex(int coderIndex) {  _progressCoderIndex = coderIndex; }\r
+\r
+  void ReInit();\r
+  void SetCoderInfo(UInt32 coderIndex, const UInt64 *inSize, const UInt64 *outSize)\r
+    {  _coders[coderIndex].SetCoderInfo(inSize, outSize); }\r
+\r
+  /*\r
+  UInt64 GetWriteProcessedSize(UInt32 binderIndex) const\r
+    {  return _streamBinders[binderIndex].ProcessedSize; }\r
+  */\r
+};\r
+\r
+}\r
+#endif\r
diff --git a/CPP/7zip/Archive/Common/CrossThreadProgress.cpp b/CPP/7zip/Archive/Common/CrossThreadProgress.cpp
new file mode 100755 (executable)
index 0000000..62d05af
--- /dev/null
@@ -0,0 +1,15 @@
+// CrossThreadProgress.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "CrossThreadProgress.h"\r
+\r
+STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)\r
+{\r
+  InSize = inSize;\r
+  OutSize = outSize;\r
+  ProgressEvent.Set();\r
+  WaitEvent.Lock();\r
+  return Result;\r
+}\r
+\r
diff --git a/CPP/7zip/Archive/Common/CrossThreadProgress.h b/CPP/7zip/Archive/Common/CrossThreadProgress.h
new file mode 100755 (executable)
index 0000000..d414958
--- /dev/null
@@ -0,0 +1,37 @@
+// CrossThreadProgress.h\r
+\r
+#ifndef __CROSSTHREADPROGRESS_H\r
+#define __CROSSTHREADPROGRESS_H\r
+\r
+#include "../../ICoder.h"\r
+#include "../../../Windows/Synchronization.h"\r
+#include "../../../Common/MyCom.h"\r
+\r
+class CCrossThreadProgress:\r
+  public ICompressProgressInfo,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  const UInt64 *InSize;\r
+  const UInt64 *OutSize;\r
+  HRESULT Result;\r
+  NWindows::NSynchronization::CAutoResetEvent ProgressEvent;\r
+  NWindows::NSynchronization::CAutoResetEvent WaitEvent;\r
+\r
+  HRes Create()\r
+  {\r
+    RINOK(ProgressEvent.CreateIfNotCreated());\r
+    return WaitEvent.CreateIfNotCreated();\r
+  }\r
+  void Init()\r
+  {\r
+    ProgressEvent.Reset();\r
+    WaitEvent.Reset();\r
+  }\r
+\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Common/DummyOutStream.cpp b/CPP/7zip/Archive/Common/DummyOutStream.cpp
new file mode 100755 (executable)
index 0000000..237e01e
--- /dev/null
@@ -0,0 +1,22 @@
+// DummyOutStream.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "DummyOutStream.h"\r
+\r
+STDMETHODIMP CDummyOutStream::Write(const void *data,  UInt32 size, UInt32 *processedSize)\r
+{\r
+  UInt32 realProcessedSize;\r
+  HRESULT result;\r
+  if(!_stream)\r
+  {\r
+    realProcessedSize = size;\r
+    result = S_OK;\r
+  }\r
+  else\r
+    result = _stream->Write(data, size, &realProcessedSize);\r
+  _size += realProcessedSize;\r
+  if(processedSize != NULL)\r
+    *processedSize = realProcessedSize;\r
+  return result;\r
+}\r
diff --git a/CPP/7zip/Archive/Common/DummyOutStream.h b/CPP/7zip/Archive/Common/DummyOutStream.h
new file mode 100755 (executable)
index 0000000..c993bb3
--- /dev/null
@@ -0,0 +1,24 @@
+// DummyOutStream.h\r
+\r
+#ifndef __DUMMYOUTSTREAM_H\r
+#define __DUMMYOUTSTREAM_H\r
+\r
+#include "../../IStream.h"\r
+#include "Common/MyCom.h"\r
+\r
+class CDummyOutStream:\r
+  public ISequentialOutStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<ISequentialOutStream> _stream;\r
+  UInt64 _size;\r
+public:\r
+  void SetStream(ISequentialOutStream *outStream) { _stream = outStream; }\r
+  void ReleaseStream() { _stream.Release(); }\r
+  void Init() { _size = 0; }\r
+  MY_UNKNOWN_IMP\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+  UInt64 GetSize() const { return _size; }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Common/FindSignature.cpp b/CPP/7zip/Archive/Common/FindSignature.cpp
new file mode 100755 (executable)
index 0000000..ad04bfc
--- /dev/null
@@ -0,0 +1,62 @@
+// FindSignature.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/Buffer.h"\r
+\r
+#include "FindSignature.h"\r
+\r
+#include "../../Common/StreamUtils.h"\r
+\r
+HRESULT FindSignatureInStream(ISequentialInStream *stream,\r
+    const Byte *signature, unsigned signatureSize,\r
+    const UInt64 *limit, UInt64 &resPos)\r
+{\r
+  resPos = 0;\r
+  CByteBuffer byteBuffer2;\r
+  byteBuffer2.SetCapacity(signatureSize);\r
+  RINOK(ReadStream_FALSE(stream, byteBuffer2, signatureSize));\r
+\r
+  if (memcmp(byteBuffer2, signature, signatureSize) == 0)\r
+    return S_OK;\r
+\r
+  const UInt32 kBufferSize = (1 << 16);\r
+  CByteBuffer byteBuffer;\r
+  byteBuffer.SetCapacity(kBufferSize);\r
+  Byte *buffer = byteBuffer;\r
+  UInt32 numPrevBytes = signatureSize - 1;\r
+  memcpy(buffer, (const Byte *)byteBuffer2 + 1, numPrevBytes);\r
+  resPos = 1;\r
+  for (;;)\r
+  {\r
+    if (limit != NULL)\r
+      if (resPos > *limit)\r
+        return S_FALSE;\r
+    do\r
+    {\r
+      UInt32 numReadBytes = kBufferSize - numPrevBytes;\r
+      UInt32 processedSize;\r
+      RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize));\r
+      numPrevBytes += processedSize;\r
+      if (processedSize == 0)\r
+        return S_FALSE;\r
+    }\r
+    while (numPrevBytes < signatureSize);\r
+    UInt32 numTests = numPrevBytes - signatureSize + 1;\r
+    for (UInt32 pos = 0; pos < numTests; pos++)\r
+    {\r
+      Byte b = signature[0];\r
+      for (; buffer[pos] != b && pos < numTests; pos++);\r
+      if (pos == numTests)\r
+        break;\r
+      if (memcmp(buffer + pos, signature, signatureSize) == 0)\r
+      {\r
+        resPos += pos;\r
+        return S_OK;\r
+      }\r
+    }\r
+    resPos += numTests;\r
+    numPrevBytes -= numTests;\r
+    memmove(buffer, buffer + numTests, numPrevBytes);\r
+  }\r
+}\r
diff --git a/CPP/7zip/Archive/Common/FindSignature.h b/CPP/7zip/Archive/Common/FindSignature.h
new file mode 100755 (executable)
index 0000000..f801d98
--- /dev/null
@@ -0,0 +1,12 @@
+// FindSignature.h\r
+\r
+#ifndef __FINDSIGNATURE_H\r
+#define __FINDSIGNATURE_H\r
+\r
+#include "../../IStream.h"\r
+\r
+HRESULT FindSignatureInStream(ISequentialInStream *stream,\r
+    const Byte *signature, unsigned signatureSize,\r
+    const UInt64 *limit, UInt64 &resPos);\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp
new file mode 100755 (executable)
index 0000000..c2254a7
--- /dev/null
@@ -0,0 +1,623 @@
+// HandlerOut.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../Common/StringToInt.h"\r
+\r
+#include "../../../Windows/PropVariant.h"\r
+\r
+#ifndef _7ZIP_ST\r
+#include "../../../Windows/System.h"\r
+#endif\r
+\r
+#include "../../ICoder.h"\r
+\r
+#include "../Common/ParseProperties.h"\r
+\r
+#include "HandlerOut.h"\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+\r
+static const wchar_t *kCopyMethod = L"Copy";\r
+static const wchar_t *kLZMAMethodName = L"LZMA";\r
+static const wchar_t *kLZMA2MethodName = L"LZMA2";\r
+static const wchar_t *kBZip2MethodName = L"BZip2";\r
+static const wchar_t *kPpmdMethodName = L"PPMd";\r
+static const wchar_t *kDeflateMethodName = L"Deflate";\r
+static const wchar_t *kDeflate64MethodName = L"Deflate64";\r
+\r
+static const wchar_t *kLzmaMatchFinderX1 = L"HC4";\r
+static const wchar_t *kLzmaMatchFinderX5 = L"BT4";\r
+\r
+static const UInt32 kLzmaAlgoX1 = 0;\r
+static const UInt32 kLzmaAlgoX5 = 1;\r
+\r
+static const UInt32 kLzmaDicSizeX1 = 1 << 16;\r
+static const UInt32 kLzmaDicSizeX3 = 1 << 20;\r
+static const UInt32 kLzmaDicSizeX5 = 1 << 24;\r
+static const UInt32 kLzmaDicSizeX7 = 1 << 25;\r
+static const UInt32 kLzmaDicSizeX9 = 1 << 26;\r
+\r
+static const UInt32 kLzmaFastBytesX1 = 32;\r
+static const UInt32 kLzmaFastBytesX7 = 64;\r
+\r
+static const UInt32 kPpmdMemSizeX1 = (1 << 22);\r
+static const UInt32 kPpmdMemSizeX5 = (1 << 24);\r
+static const UInt32 kPpmdMemSizeX7 = (1 << 26);\r
+static const UInt32 kPpmdMemSizeX9 = (192 << 20);\r
+\r
+static const UInt32 kPpmdOrderX1 = 4;\r
+static const UInt32 kPpmdOrderX5 = 6;\r
+static const UInt32 kPpmdOrderX7 = 16;\r
+static const UInt32 kPpmdOrderX9 = 32;\r
+\r
+static const UInt32 kDeflateAlgoX1 = 0;\r
+static const UInt32 kDeflateAlgoX5 = 1;\r
+\r
+static const UInt32 kDeflateFastBytesX1 = 32;\r
+static const UInt32 kDeflateFastBytesX7 = 64;\r
+static const UInt32 kDeflateFastBytesX9 = 128;\r
+\r
+static const UInt32 kDeflatePassesX1 = 1;\r
+static const UInt32 kDeflatePassesX7 = 3;\r
+static const UInt32 kDeflatePassesX9 = 10;\r
+\r
+static const UInt32 kBZip2NumPassesX1 = 1;\r
+static const UInt32 kBZip2NumPassesX7 = 2;\r
+static const UInt32 kBZip2NumPassesX9 = 7;\r
+\r
+static const UInt32 kBZip2DicSizeX1 = 100000;\r
+static const UInt32 kBZip2DicSizeX3 = 500000;\r
+static const UInt32 kBZip2DicSizeX5 = 900000;\r
+\r
+static const wchar_t *kDefaultMethodName = kLZMAMethodName;\r
+\r
+static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";\r
+static const UInt32 kDictionaryForHeaders = 1 << 20;\r
+static const UInt32 kNumFastBytesForHeaders = 273;\r
+static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5;\r
+\r
+static bool AreEqual(const UString &methodName, const wchar_t *s)\r
+  { return (methodName.CompareNoCase(s) == 0); }\r
+\r
+bool COneMethodInfo::IsLzma() const\r
+{\r
+  return\r
+    AreEqual(MethodName, kLZMAMethodName) ||\r
+    AreEqual(MethodName, kLZMA2MethodName);\r
+}\r
+\r
+static inline bool IsBZip2Method(const UString &methodName)\r
+  { return AreEqual(methodName, kBZip2MethodName); }\r
+\r
+static inline bool IsPpmdMethod(const UString &methodName)\r
+  { return AreEqual(methodName, kPpmdMethodName); }\r
+\r
+static inline bool IsDeflateMethod(const UString &methodName)\r
+{\r
+  return\r
+    AreEqual(methodName, kDeflateMethodName) ||\r
+    AreEqual(methodName, kDeflate64MethodName);\r
+}\r
+\r
+struct CNameToPropID\r
+{\r
+  PROPID PropID;\r
+  VARTYPE VarType;\r
+  const wchar_t *Name;\r
+};\r
+\r
+static CNameToPropID g_NameToPropID[] =\r
+{\r
+  { NCoderPropID::kBlockSize, VT_UI4, L"C" },\r
+  { NCoderPropID::kDictionarySize, VT_UI4, L"D" },\r
+  { NCoderPropID::kUsedMemorySize, VT_UI4, L"MEM" },\r
+\r
+  { NCoderPropID::kOrder, VT_UI4, L"O" },\r
+  { NCoderPropID::kPosStateBits, VT_UI4, L"PB" },\r
+  { NCoderPropID::kLitContextBits, VT_UI4, L"LC" },\r
+  { NCoderPropID::kLitPosBits, VT_UI4, L"LP" },\r
+  { NCoderPropID::kEndMarker, VT_BOOL, L"eos" },\r
+\r
+  { NCoderPropID::kNumPasses, VT_UI4, L"Pass" },\r
+  { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" },\r
+  { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" },\r
+  { NCoderPropID::kAlgorithm, VT_UI4, L"a" },\r
+  { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" },\r
+  { NCoderPropID::kNumThreads, VT_UI4, L"mt" },\r
+  { NCoderPropID::kDefaultProp, VT_UI4, L"" }\r
+};\r
+\r
+static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)\r
+{\r
+  if (varType == srcProp.vt)\r
+  {\r
+    destProp = srcProp;\r
+    return true;\r
+  }\r
+  if (varType == VT_UI1)\r
+  {\r
+    if (srcProp.vt == VT_UI4)\r
+    {\r
+      UInt32 value = srcProp.ulVal;\r
+      if (value > 0xFF)\r
+        return false;\r
+      destProp = (Byte)value;\r
+      return true;\r
+    }\r
+  }\r
+  else if (varType == VT_BOOL)\r
+  {\r
+    bool res;\r
+    if (SetBoolProperty(res, srcProp) != S_OK)\r
+      return false;\r
+    destProp = res;\r
+    return true;\r
+  }\r
+  return false;\r
+}\r
+    \r
+static int FindPropIdExact(const UString &name)\r
+{\r
+  for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++)\r
+    if (name.CompareNoCase(g_NameToPropID[i].Name) == 0)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+static int FindPropIdStart(const UString &name)\r
+{\r
+  for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++)\r
+  {\r
+    UString t = g_NameToPropID[i].Name;\r
+    if (t.CompareNoCase(name.Left(t.Length())) == 0)\r
+      return i;\r
+  }\r
+  return -1;\r
+}\r
+\r
+static void SetMethodProp(COneMethodInfo &m, PROPID propID, const NCOM::CPropVariant &value)\r
+{\r
+  for (int j = 0; j < m.Props.Size(); j++)\r
+    if (m.Props[j].Id == propID)\r
+      return;\r
+  CProp prop;\r
+  prop.Id = propID;\r
+  prop.Value = value;\r
+  m.Props.Add(prop);\r
+}\r
+\r
+void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo\r
+    #ifndef _7ZIP_ST\r
+    , UInt32 numThreads\r
+    #endif\r
+    )\r
+{\r
+  UInt32 level = _level;\r
+  if (oneMethodInfo.MethodName.IsEmpty())\r
+    oneMethodInfo.MethodName = kDefaultMethodName;\r
+  \r
+  if (oneMethodInfo.IsLzma())\r
+  {\r
+    UInt32 dicSize =\r
+      (level >= 9 ? kLzmaDicSizeX9 :\r
+      (level >= 7 ? kLzmaDicSizeX7 :\r
+      (level >= 5 ? kLzmaDicSizeX5 :\r
+      (level >= 3 ? kLzmaDicSizeX3 :\r
+                    kLzmaDicSizeX1))));\r
+    \r
+    UInt32 algo =\r
+      (level >= 5 ? kLzmaAlgoX5 :\r
+                    kLzmaAlgoX1);\r
+    \r
+    UInt32 fastBytes =\r
+      (level >= 7 ? kLzmaFastBytesX7 :\r
+                    kLzmaFastBytesX1);\r
+    \r
+    const wchar_t *matchFinder =\r
+      (level >= 5 ? kLzmaMatchFinderX5 :\r
+                    kLzmaMatchFinderX1);\r
+    \r
+    SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);\r
+    SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);\r
+    SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);\r
+    SetMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder);\r
+    #ifndef _7ZIP_ST\r
+    SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);\r
+    #endif\r
+  }\r
+  else if (IsDeflateMethod(oneMethodInfo.MethodName))\r
+  {\r
+    UInt32 fastBytes =\r
+      (level >= 9 ? kDeflateFastBytesX9 :\r
+      (level >= 7 ? kDeflateFastBytesX7 :\r
+                    kDeflateFastBytesX1));\r
+    \r
+    UInt32 numPasses =\r
+      (level >= 9 ? kDeflatePassesX9 :\r
+      (level >= 7 ? kDeflatePassesX7 :\r
+                    kDeflatePassesX1));\r
+    \r
+    UInt32 algo =\r
+      (level >= 5 ? kDeflateAlgoX5 :\r
+                    kDeflateAlgoX1);\r
+    \r
+    SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);\r
+    SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);\r
+    SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);\r
+  }\r
+  else if (IsBZip2Method(oneMethodInfo.MethodName))\r
+  {\r
+    UInt32 numPasses =\r
+      (level >= 9 ? kBZip2NumPassesX9 :\r
+      (level >= 7 ? kBZip2NumPassesX7 :\r
+                    kBZip2NumPassesX1));\r
+    \r
+    UInt32 dicSize =\r
+      (level >= 5 ? kBZip2DicSizeX5 :\r
+      (level >= 3 ? kBZip2DicSizeX3 :\r
+                    kBZip2DicSizeX1));\r
+    \r
+    SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);\r
+    SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);\r
+    #ifndef _7ZIP_ST\r
+    SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);\r
+    #endif\r
+  }\r
+  else if (IsPpmdMethod(oneMethodInfo.MethodName))\r
+  {\r
+    UInt32 useMemSize =\r
+      (level >= 9 ? kPpmdMemSizeX9 :\r
+      (level >= 7 ? kPpmdMemSizeX7 :\r
+      (level >= 5 ? kPpmdMemSizeX5 :\r
+                    kPpmdMemSizeX1)));\r
+    \r
+    UInt32 order =\r
+      (level >= 9 ? kPpmdOrderX9 :\r
+      (level >= 7 ? kPpmdOrderX7 :\r
+      (level >= 5 ? kPpmdOrderX5 :\r
+                    kPpmdOrderX1)));\r
+    \r
+    SetMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize);\r
+    SetMethodProp(oneMethodInfo, NCoderPropID::kOrder, order);\r
+  }\r
+}\r
+\r
+static void SplitParams(const UString &srcString, UStringVector &subStrings)\r
+{\r
+  subStrings.Clear();\r
+  UString name;\r
+  int len = srcString.Length();\r
+  if (len == 0)\r
+    return;\r
+  for (int i = 0; i < len; i++)\r
+  {\r
+    wchar_t c = srcString[i];\r
+    if (c == L':')\r
+    {\r
+      subStrings.Add(name);\r
+      name.Empty();\r
+    }\r
+    else\r
+      name += c;\r
+  }\r
+  subStrings.Add(name);\r
+}\r
+\r
+static void SplitParam(const UString &param, UString &name, UString &value)\r
+{\r
+  int eqPos = param.Find(L'=');\r
+  if (eqPos >= 0)\r
+  {\r
+    name = param.Left(eqPos);\r
+    value = param.Mid(eqPos + 1);\r
+    return;\r
+  }\r
+  for(int i = 0; i < param.Length(); i++)\r
+  {\r
+    wchar_t c = param[i];\r
+    if (c >= L'0' && c <= L'9')\r
+    {\r
+      name = param.Left(i);\r
+      value = param.Mid(i);\r
+      return;\r
+    }\r
+  }\r
+  name = param;\r
+}\r
+\r
+HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value)\r
+{\r
+  CProp prop;\r
+  int index = FindPropIdExact(name);\r
+  if (index < 0)\r
+    return E_INVALIDARG;\r
+  const CNameToPropID &nameToPropID = g_NameToPropID[index];\r
+  prop.Id = nameToPropID.PropID;\r
+\r
+  if (prop.Id == NCoderPropID::kBlockSize ||\r
+      prop.Id == NCoderPropID::kDictionarySize ||\r
+      prop.Id == NCoderPropID::kUsedMemorySize)\r
+  {\r
+    UInt32 dicSize;\r
+    RINOK(ParsePropDictionaryValue(value, dicSize));\r
+    prop.Value = dicSize;\r
+  }\r
+  else\r
+  {\r
+    NCOM::CPropVariant propValue;\r
+    \r
+    if (nameToPropID.VarType == VT_BSTR)\r
+      propValue = value;\r
+    else if (nameToPropID.VarType == VT_BOOL)\r
+    {\r
+      bool res;\r
+      if (!StringToBool(value, res))\r
+        return E_INVALIDARG;\r
+      propValue = res;\r
+    }\r
+    else\r
+    {\r
+      UInt32 number;\r
+      if (ParseStringToUInt32(value, number) == value.Length())\r
+        propValue = number;\r
+      else\r
+        propValue = value;\r
+    }\r
+    \r
+    if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value))\r
+      return E_INVALIDARG;\r
+  }\r
+  oneMethodInfo.Props.Add(prop);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString)\r
+{\r
+  UStringVector params;\r
+  SplitParams(srcString, params);\r
+  if (params.Size() > 0)\r
+    oneMethodInfo.MethodName = params[0];\r
+  for (int i = 1; i < params.Size(); i++)\r
+  {\r
+    const UString &param = params[i];\r
+    UString name, value;\r
+    SplitParam(param, name, value);\r
+    RINOK(SetParam(oneMethodInfo, name, value));\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT COutHandler::SetSolidSettings(const UString &s)\r
+{\r
+  UString s2 = s;\r
+  s2.MakeUpper();\r
+  for (int i = 0; i < s2.Length();)\r
+  {\r
+    const wchar_t *start = ((const wchar_t *)s2) + i;\r
+    const wchar_t *end;\r
+    UInt64 v = ConvertStringToUInt64(start, &end);\r
+    if (start == end)\r
+    {\r
+      if (s2[i++] != 'E')\r
+        return E_INVALIDARG;\r
+      _solidExtension = true;\r
+      continue;\r
+    }\r
+    i += (int)(end - start);\r
+    if (i == s2.Length())\r
+      return E_INVALIDARG;\r
+    wchar_t c = s2[i++];\r
+    switch(c)\r
+    {\r
+      case 'F':\r
+        if (v < 1)\r
+          v = 1;\r
+        _numSolidFiles = v;\r
+        break;\r
+      case 'B':\r
+        _numSolidBytes = v;\r
+        _numSolidBytesDefined = true;\r
+        break;\r
+      case 'K':\r
+        _numSolidBytes = (v << 10);\r
+        _numSolidBytesDefined = true;\r
+        break;\r
+      case 'M':\r
+        _numSolidBytes = (v << 20);\r
+        _numSolidBytesDefined = true;\r
+        break;\r
+      case 'G':\r
+        _numSolidBytes = (v << 30);\r
+        _numSolidBytesDefined = true;\r
+        break;\r
+      default:\r
+        return E_INVALIDARG;\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value)\r
+{\r
+  bool isSolid;\r
+  switch(value.vt)\r
+  {\r
+    case VT_EMPTY:\r
+      isSolid = true;\r
+      break;\r
+    case VT_BOOL:\r
+      isSolid = (value.boolVal != VARIANT_FALSE);\r
+      break;\r
+    case VT_BSTR:\r
+      if (StringToBool(value.bstrVal, isSolid))\r
+        break;\r
+      return SetSolidSettings(value.bstrVal);\r
+    default:\r
+      return E_INVALIDARG;\r
+  }\r
+  if (isSolid)\r
+    InitSolid();\r
+  else\r
+    _numSolidFiles = 1;\r
+  return S_OK;\r
+}\r
+\r
+void COutHandler::Init()\r
+{\r
+  _removeSfxBlock = false;\r
+  _compressHeaders = true;\r
+  _encryptHeadersSpecified = false;\r
+  _encryptHeaders = false;\r
+  \r
+  WriteCTime = false;\r
+  WriteATime = false;\r
+  WriteMTime = true;\r
+  \r
+  #ifndef _7ZIP_ST\r
+  _numThreads = NSystem::GetNumberOfProcessors();\r
+  #endif\r
+  \r
+  _level = 5;\r
+  _autoFilter = true;\r
+  _volumeMode = false;\r
+  _crcSize = 4;\r
+  InitSolid();\r
+}\r
+\r
+void COutHandler::BeforeSetProperty()\r
+{\r
+  Init();\r
+  #ifndef _7ZIP_ST\r
+  numProcessors = NSystem::GetNumberOfProcessors();\r
+  #endif\r
+\r
+  mainDicSize = 0xFFFFFFFF;\r
+  mainDicMethodIndex = 0xFFFFFFFF;\r
+  minNumber = 0;\r
+  _crcSize = 4;\r
+}\r
+\r
+HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)\r
+{\r
+  UString name = nameSpec;\r
+  name.MakeUpper();\r
+  if (name.IsEmpty())\r
+    return E_INVALIDARG;\r
+  \r
+  if (name[0] == 'X')\r
+  {\r
+    name.Delete(0);\r
+    _level = 9;\r
+    return ParsePropValue(name, value, _level);\r
+  }\r
+  \r
+  if (name[0] == L'S')\r
+  {\r
+    name.Delete(0);\r
+    if (name.IsEmpty())\r
+      return SetSolidSettings(value);\r
+    if (value.vt != VT_EMPTY)\r
+      return E_INVALIDARG;\r
+    return SetSolidSettings(name);\r
+  }\r
+  \r
+  if (name == L"CRC")\r
+  {\r
+    _crcSize = 4;\r
+    name.Delete(0, 3);\r
+    return ParsePropValue(name, value, _crcSize);\r
+  }\r
+  \r
+  UInt32 number;\r
+  int index = ParseStringToUInt32(name, number);\r
+  UString realName = name.Mid(index);\r
+  if (index == 0)\r
+  {\r
+    if(name.Left(2).CompareNoCase(L"MT") == 0)\r
+    {\r
+      #ifndef _7ZIP_ST\r
+      RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));\r
+      #endif\r
+      return S_OK;\r
+    }\r
+    if (name.CompareNoCase(L"RSFX") == 0)  return SetBoolProperty(_removeSfxBlock, value);\r
+    if (name.CompareNoCase(L"F") == 0) return SetBoolProperty(_autoFilter, value);\r
+    if (name.CompareNoCase(L"HC") == 0) return SetBoolProperty(_compressHeaders, value);\r
+    if (name.CompareNoCase(L"HCF") == 0)\r
+    {\r
+      bool compressHeadersFull = true;\r
+      RINOK(SetBoolProperty(compressHeadersFull, value));\r
+      if (!compressHeadersFull)\r
+        return E_INVALIDARG;\r
+      return S_OK;\r
+    }\r
+    if (name.CompareNoCase(L"HE") == 0)\r
+    {\r
+      RINOK(SetBoolProperty(_encryptHeaders, value));\r
+      _encryptHeadersSpecified = true;\r
+      return S_OK;\r
+    }\r
+    if (name.CompareNoCase(L"TC") == 0) return SetBoolProperty(WriteCTime, value);\r
+    if (name.CompareNoCase(L"TA") == 0) return SetBoolProperty(WriteATime, value);\r
+    if (name.CompareNoCase(L"TM") == 0) return SetBoolProperty(WriteMTime, value);\r
+    if (name.CompareNoCase(L"V") == 0) return SetBoolProperty(_volumeMode, value);\r
+    number = 0;\r
+  }\r
+  if (number > 10000)\r
+    return E_FAIL;\r
+  if (number < minNumber)\r
+    return E_INVALIDARG;\r
+  number -= minNumber;\r
+  for(int j = _methods.Size(); j <= (int)number; j++)\r
+  {\r
+    COneMethodInfo oneMethodInfo;\r
+    _methods.Add(oneMethodInfo);\r
+  }\r
+  \r
+  COneMethodInfo &oneMethodInfo = _methods[number];\r
+  \r
+  if (realName.Length() == 0)\r
+  {\r
+    if (value.vt != VT_BSTR)\r
+      return E_INVALIDARG;\r
+    \r
+    RINOK(SetParams(oneMethodInfo, value.bstrVal));\r
+  }\r
+  else\r
+  {\r
+    int index = FindPropIdStart(realName);\r
+    if (index < 0)\r
+      return E_INVALIDARG;\r
+    const CNameToPropID &nameToPropID = g_NameToPropID[index];\r
+    CProp prop;\r
+    prop.Id = nameToPropID.PropID;\r
+\r
+    if (prop.Id == NCoderPropID::kBlockSize ||\r
+        prop.Id == NCoderPropID::kDictionarySize ||\r
+        prop.Id == NCoderPropID::kUsedMemorySize)\r
+    {\r
+      UInt32 dicSize;\r
+      RINOK(ParsePropDictionaryValue(realName.Mid(MyStringLen(nameToPropID.Name)), value, dicSize));\r
+      prop.Value = dicSize;\r
+      if (number <= mainDicMethodIndex)\r
+        mainDicSize = dicSize;\r
+    }\r
+    else\r
+    {\r
+      int index = FindPropIdExact(realName);\r
+      if (index < 0)\r
+        return E_INVALIDARG;\r
+      const CNameToPropID &nameToPropID = g_NameToPropID[index];\r
+      prop.Id = nameToPropID.PropID;\r
+      if (!ConvertProperty(value, nameToPropID.VarType, prop.Value))\r
+        return E_INVALIDARG;\r
+    }\r
+    oneMethodInfo.Props.Add(prop);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+}\r
diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h
new file mode 100755 (executable)
index 0000000..c4ccf37
--- /dev/null
@@ -0,0 +1,87 @@
+// HandlerOut.h\r
+\r
+#ifndef __HANDLER_OUT_H\r
+#define __HANDLER_OUT_H\r
+\r
+#include "../../../Common/MyString.h"\r
+#include "../../Common/MethodProps.h"\r
+\r
+namespace NArchive {\r
+\r
+struct COneMethodInfo\r
+{\r
+  CObjectVector<CProp> Props;\r
+  UString MethodName;\r
+\r
+  bool IsLzma() const;\r
+};\r
+\r
+class COutHandler\r
+{\r
+public:\r
+  HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);\r
+  \r
+  HRESULT SetSolidSettings(const UString &s);\r
+  HRESULT SetSolidSettings(const PROPVARIANT &value);\r
+\r
+  #ifndef _7ZIP_ST\r
+  UInt32 _numThreads;\r
+  #endif\r
+\r
+  UInt32 _crcSize;\r
+\r
+  CObjectVector<COneMethodInfo> _methods;\r
+  bool _removeSfxBlock;\r
+  \r
+  UInt64 _numSolidFiles;\r
+  UInt64 _numSolidBytes;\r
+  bool _numSolidBytesDefined;\r
+  bool _solidExtension;\r
+\r
+  bool _compressHeaders;\r
+  bool _encryptHeadersSpecified;\r
+  bool _encryptHeaders;\r
+\r
+  bool WriteCTime;\r
+  bool WriteATime;\r
+  bool WriteMTime;\r
+\r
+  bool _autoFilter;\r
+  UInt32 _level;\r
+\r
+  bool _volumeMode;\r
+\r
+  HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value);\r
+  HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString);\r
+\r
+  void SetCompressionMethod2(COneMethodInfo &oneMethodInfo\r
+      #ifndef _7ZIP_ST\r
+      , UInt32 numThreads\r
+      #endif\r
+      );\r
+\r
+  void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }\r
+  void InitSolidSize()  { _numSolidBytes = (UInt64)(Int64)(-1); }\r
+  void InitSolid()\r
+  {\r
+    InitSolidFiles();\r
+    InitSolidSize();\r
+    _solidExtension = false;\r
+    _numSolidBytesDefined = false;\r
+  }\r
+\r
+  void Init();\r
+\r
+  COutHandler() { Init(); }\r
+\r
+  void BeforeSetProperty();\r
+\r
+  UInt32 minNumber;\r
+  UInt32 numProcessors;\r
+  UInt32 mainDicSize;\r
+  UInt32 mainDicMethodIndex;\r
+};\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Common/InStreamWithCRC.cpp b/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
new file mode 100755 (executable)
index 0000000..6338d0a
--- /dev/null
@@ -0,0 +1,42 @@
+// InStreamWithCRC.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "InStreamWithCRC.h"\r
+\r
+STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  UInt32 realProcessedSize;\r
+  HRESULT result = _stream->Read(data, size, &realProcessedSize);\r
+  _size += realProcessedSize;\r
+  if (size > 0 && realProcessedSize == 0)\r
+    _wasFinished = true;\r
+  _crc = CrcUpdate(_crc, data, realProcessedSize);\r
+  if(processedSize != NULL)\r
+    *processedSize = realProcessedSize;\r
+  return result;\r
+}\r
+\r
+STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  UInt32 realProcessedSize;\r
+  HRESULT result = _stream->Read(data, size, &realProcessedSize);\r
+  /*\r
+  if (size > 0 && realProcessedSize == 0)\r
+    _wasFinished = true;\r
+  */\r
+  _size += realProcessedSize;\r
+  _crc = CrcUpdate(_crc, data, realProcessedSize);\r
+  if(processedSize != NULL)\r
+    *processedSize = realProcessedSize;\r
+  return result;\r
+}\r
+\r
+STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)\r
+{\r
+  if (seekOrigin != STREAM_SEEK_SET || offset != 0)\r
+    return E_FAIL;\r
+  _size = 0;\r
+  _crc = CRC_INIT_VAL;\r
+  return _stream->Seek(offset, seekOrigin, newPosition);\r
+}\r
diff --git a/CPP/7zip/Archive/Common/InStreamWithCRC.h b/CPP/7zip/Archive/Common/InStreamWithCRC.h
new file mode 100755 (executable)
index 0000000..1a4b2c9
--- /dev/null
@@ -0,0 +1,67 @@
+// InStreamWithCRC.h\r
+\r
+#ifndef __IN_STREAM_WITH_CRC_H\r
+#define __IN_STREAM_WITH_CRC_H\r
+\r
+#include "../../../../C/7zCrc.h"\r
+\r
+#include "../../../Common/MyCom.h"\r
+\r
+#include "../../IStream.h"\r
+\r
+class CSequentialInStreamWithCRC:\r
+  public ISequentialInStream,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+private:\r
+  CMyComPtr<ISequentialInStream> _stream;\r
+  UInt64 _size;\r
+  UInt32 _crc;\r
+  bool _wasFinished;\r
+public:\r
+  void SetStream(ISequentialInStream *stream) { _stream = stream;  }\r
+  void Init()\r
+  {\r
+    _size = 0;\r
+    _wasFinished = false;\r
+    _crc = CRC_INIT_VAL;\r
+  }\r
+  void ReleaseStream() { _stream.Release(); }\r
+  UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }\r
+  UInt64 GetSize() const { return _size; }\r
+  bool WasFinished() const { return _wasFinished; }\r
+};\r
+\r
+class CInStreamWithCRC:\r
+  public IInStream,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP1(IInStream)\r
+\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);\r
+private:\r
+  CMyComPtr<IInStream> _stream;\r
+  UInt64 _size;\r
+  UInt32 _crc;\r
+  // bool _wasFinished;\r
+public:\r
+  void SetStream(IInStream *stream) { _stream = stream;  }\r
+  void Init()\r
+  {\r
+    _size = 0;\r
+    // _wasFinished = false;\r
+    _crc = CRC_INIT_VAL;\r
+  }\r
+  void ReleaseStream() { _stream.Release(); }\r
+  UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }\r
+  UInt64 GetSize() const { return _size; }\r
+  // bool WasFinished() const { return _wasFinished; }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/CPP/7zip/Archive/Common/ItemNameUtils.cpp
new file mode 100755 (executable)
index 0000000..287ddce
--- /dev/null
@@ -0,0 +1,61 @@
+// Archive/Common/ItemNameUtils.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/Types.h"\r
+\r
+#include "ItemNameUtils.h"\r
+\r
+namespace NArchive {\r
+namespace NItemName {\r
+\r
+static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR;\r
+static const wchar_t kDirDelimiter = L'/';\r
+\r
+UString MakeLegalName(const UString &name)\r
+{\r
+  UString zipName = name;\r
+  zipName.Replace(kOSDirDelimiter, kDirDelimiter);\r
+  return zipName;\r
+}\r
+\r
+UString GetOSName(const UString &name)\r
+{\r
+  UString newName = name;\r
+  newName.Replace(kDirDelimiter, kOSDirDelimiter);\r
+  return newName;\r
+}\r
+\r
+UString GetOSName2(const UString &name)\r
+{\r
+  if (name.IsEmpty())\r
+    return UString();\r
+  UString newName = GetOSName(name);\r
+  if (newName[newName.Length() - 1] == kOSDirDelimiter)\r
+    newName.Delete(newName.Length() - 1);\r
+  return newName;\r
+}\r
+\r
+bool HasTailSlash(const AString &name, UINT codePage)\r
+{\r
+  if (name.IsEmpty())\r
+    return false;\r
+  LPCSTR prev =\r
+  #if defined(_WIN32) && !defined(UNDER_CE)\r
+    CharPrevExA((WORD)codePage, name, &name[name.Length()], 0);\r
+  #else\r
+    (LPCSTR)(name) + (name.Length() - 1);\r
+  #endif\r
+  return (*prev == '/');\r
+}\r
+\r
+#ifndef _WIN32\r
+UString WinNameToOSName(const UString &name)\r
+{\r
+  UString newName = name;\r
+  newName.Replace(L'\\', kOSDirDelimiter);\r
+  return newName;\r
+}\r
+#endif\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.h b/CPP/7zip/Archive/Common/ItemNameUtils.h
new file mode 100755 (executable)
index 0000000..8b91d1c
--- /dev/null
@@ -0,0 +1,24 @@
+// Archive/Common/ItemNameUtils.h\r
+\r
+#ifndef __ARCHIVE_ITEMNAMEUTILS_H\r
+#define __ARCHIVE_ITEMNAMEUTILS_H\r
+\r
+#include "../../../Common/MyString.h"\r
+\r
+namespace NArchive {\r
+namespace NItemName {\r
+\r
+  UString MakeLegalName(const UString &name);\r
+  UString GetOSName(const UString &name);\r
+  UString GetOSName2(const UString &name);\r
+  bool HasTailSlash(const AString &name, UINT codePage);\r
+\r
+  #ifdef _WIN32\r
+  inline UString WinNameToOSName(const UString &name)  { return name; }\r
+  #else\r
+  UString WinNameToOSName(const UString &name);\r
+  #endif\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Common/MultiStream.cpp b/CPP/7zip/Archive/Common/MultiStream.cpp
new file mode 100755 (executable)
index 0000000..83b3da1
--- /dev/null
@@ -0,0 +1,190 @@
+// MultiStream.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "MultiStream.h"\r
+\r
+STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize)\r
+    *processedSize = 0;\r
+  if (size == 0)\r
+    return S_OK;\r
+  if (_pos >= _totalLength)\r
+    return (_pos == _totalLength) ? S_OK : E_FAIL;\r
+\r
+  {\r
+    int left = 0, mid = _streamIndex, right = Streams.Size();\r
+    for (;;)\r
+    {\r
+      CSubStreamInfo &m = Streams[mid];\r
+      if (_pos < m.GlobalOffset)\r
+        right = mid;\r
+      else if (_pos >= m.GlobalOffset + m.Size)\r
+        left = mid + 1;\r
+      else\r
+      {\r
+        _streamIndex = mid;\r
+        break;\r
+      }\r
+      mid = (left + right) / 2;\r
+    }\r
+    _streamIndex = mid;\r
+  }\r
+  \r
+  CSubStreamInfo &s = Streams[_streamIndex];\r
+  UInt64 localPos = _pos - s.GlobalOffset;\r
+  if (localPos != s.LocalPos)\r
+  {\r
+    RINOK(s.Stream->Seek(localPos, STREAM_SEEK_SET, &s.LocalPos));\r
+  }\r
+  UInt64 rem = s.Size - localPos;\r
+  if (size > rem)\r
+    size = (UInt32)rem;\r
+  HRESULT result = s.Stream->Read(data, size, &size);\r
+  _pos += size;\r
+  s.LocalPos += size;\r
+  if (processedSize)\r
+    *processedSize = size;\r
+  return result;\r
+}\r
+  \r
+STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)\r
+{\r
+  switch(seekOrigin)\r
+  {\r
+    case STREAM_SEEK_SET: _pos = offset; break;\r
+    case STREAM_SEEK_CUR: _pos = _pos + offset; break;\r
+    case STREAM_SEEK_END: _pos = _totalLength + offset; break;\r
+    default: return STG_E_INVALIDFUNCTION;\r
+  }\r
+  if (newPosition != 0)\r
+    *newPosition = _pos;\r
+  return S_OK;\r
+}\r
+\r
+\r
+/*\r
+class COutVolumeStream:\r
+  public ISequentialOutStream,\r
+  public CMyUnknownImp\r
+{\r
+  int _volIndex;\r
+  UInt64 _volSize;\r
+  UInt64 _curPos;\r
+  CMyComPtr<ISequentialOutStream> _volumeStream;\r
+  COutArchive _archive;\r
+  CCRC _crc;\r
+\r
+public:\r
+  MY_UNKNOWN_IMP\r
+\r
+  CFileItem _file;\r
+  CUpdateOptions _options;\r
+  CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;\r
+  void Init(IArchiveUpdateCallback2 *volumeCallback,\r
+      const UString &name)\r
+  {\r
+    _file.Name = name;\r
+    _file.IsStartPosDefined = true;\r
+    _file.StartPos = 0;\r
+    \r
+    VolumeCallback = volumeCallback;\r
+    _volIndex = 0;\r
+    _volSize = 0;\r
+  }\r
+  \r
+  HRESULT Flush();\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+};\r
+\r
+HRESULT COutVolumeStream::Flush()\r
+{\r
+  if (_volumeStream)\r
+  {\r
+    _file.UnPackSize = _curPos;\r
+    _file.FileCRC = _crc.GetDigest();\r
+    RINOK(WriteVolumeHeader(_archive, _file, _options));\r
+    _archive.Close();\r
+    _volumeStream.Release();\r
+    _file.StartPos += _file.UnPackSize;\r
+  }\r
+  return S_OK;\r
+}\r
+*/\r
+\r
+/*\r
+STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if(processedSize != NULL)\r
+    *processedSize = 0;\r
+  while(size > 0)\r
+  {\r
+    if (_streamIndex >= Streams.Size())\r
+    {\r
+      CSubStreamInfo subStream;\r
+      RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size));\r
+      RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream));\r
+      subStream.Pos = 0;\r
+      Streams.Add(subStream);\r
+      continue;\r
+    }\r
+    CSubStreamInfo &subStream = Streams[_streamIndex];\r
+    if (_offsetPos >= subStream.Size)\r
+    {\r
+      _offsetPos -= subStream.Size;\r
+      _streamIndex++;\r
+      continue;\r
+    }\r
+    if (_offsetPos != subStream.Pos)\r
+    {\r
+      CMyComPtr<IOutStream> outStream;\r
+      RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));\r
+      RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));\r
+      subStream.Pos = _offsetPos;\r
+    }\r
+\r
+    UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos);\r
+    UInt32 realProcessed;\r
+    RINOK(subStream.Stream->Write(data, curSize, &realProcessed));\r
+    data = (void *)((Byte *)data + realProcessed);\r
+    size -= realProcessed;\r
+    subStream.Pos += realProcessed;\r
+    _offsetPos += realProcessed;\r
+    _absPos += realProcessed;\r
+    if (_absPos > _length)\r
+      _length = _absPos;\r
+    if(processedSize != NULL)\r
+      *processedSize += realProcessed;\r
+    if (subStream.Pos == subStream.Size)\r
+    {\r
+      _streamIndex++;\r
+      _offsetPos = 0;\r
+    }\r
+    if (realProcessed != curSize && realProcessed == 0)\r
+      return E_FAIL;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)\r
+{\r
+  if(seekOrigin >= 3)\r
+    return STG_E_INVALIDFUNCTION;\r
+  switch(seekOrigin)\r
+  {\r
+    case STREAM_SEEK_SET:\r
+      _absPos = offset;\r
+      break;\r
+    case STREAM_SEEK_CUR:\r
+      _absPos += offset;\r
+      break;\r
+    case STREAM_SEEK_END:\r
+      _absPos = _length + offset;\r
+      break;\r
+  }\r
+  _offsetPos = _absPos;\r
+  _streamIndex = 0;\r
+  return S_OK;\r
+}\r
+*/\r
diff --git a/CPP/7zip/Archive/Common/MultiStream.h b/CPP/7zip/Archive/Common/MultiStream.h
new file mode 100755 (executable)
index 0000000..74ec6ad
--- /dev/null
@@ -0,0 +1,84 @@
+// MultiStream.h\r
+\r
+#ifndef __MULTI_STREAM_H\r
+#define __MULTI_STREAM_H\r
+\r
+#include "../../../Common/MyCom.h"\r
+#include "../../../Common/MyVector.h"\r
+\r
+#include "../../IStream.h"\r
+\r
+class CMultiStream:\r
+  public IInStream,\r
+  public CMyUnknownImp\r
+{\r
+  UInt64 _pos;\r
+  UInt64 _totalLength;\r
+  int _streamIndex;\r
+public:\r
+  struct CSubStreamInfo\r
+  {\r
+    CMyComPtr<IInStream> Stream;\r
+    UInt64 Size;\r
+    UInt64 GlobalOffset;\r
+    UInt64 LocalPos;\r
+  };\r
+  CObjectVector<CSubStreamInfo> Streams;\r
+  \r
+  HRESULT Init()\r
+  {\r
+    UInt64 total = 0;\r
+    for (int i = 0; i < Streams.Size(); i++)\r
+    {\r
+      CSubStreamInfo &s = Streams[i];\r
+      s.GlobalOffset = total;\r
+      total += Streams[i].Size;\r
+      RINOK(s.Stream->Seek(0, STREAM_SEEK_CUR, &s.LocalPos));\r
+    }\r
+    _totalLength = total;\r
+    _pos = 0;\r
+    _streamIndex = 0;\r
+    return S_OK;\r
+  }\r
+\r
+  MY_UNKNOWN_IMP1(IInStream)\r
+\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);\r
+};\r
+\r
+/*\r
+class COutMultiStream:\r
+  public IOutStream,\r
+  public CMyUnknownImp\r
+{\r
+  int _streamIndex; // required stream\r
+  UInt64 _offsetPos; // offset from start of _streamIndex index\r
+  UInt64 _absPos;\r
+  UInt64 _length;\r
+\r
+  struct CSubStreamInfo\r
+  {\r
+    CMyComPtr<ISequentialOutStream> Stream;\r
+    UInt64 Size;\r
+    UInt64 Pos;\r
+ };\r
+  CObjectVector<CSubStreamInfo> Streams;\r
+public:\r
+  CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;\r
+  void Init()\r
+  {\r
+    _streamIndex = 0;\r
+    _offsetPos = 0;\r
+    _absPos = 0;\r
+    _length = 0;\r
+  }\r
+\r
+  MY_UNKNOWN_IMP1(IOutStream)\r
+\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);\r
+};\r
+*/\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp b/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
new file mode 100755 (executable)
index 0000000..e0d3894
--- /dev/null
@@ -0,0 +1,18 @@
+// OutStreamWithCRC.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "OutStreamWithCRC.h"\r
+\r
+STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  HRESULT result = S_OK;\r
+  if (_stream)\r
+    result = _stream->Write(data, size, &size);\r
+  if (_calculate)\r
+    _crc = CrcUpdate(_crc, data, size);\r
+  _size += size;\r
+  if (processedSize != NULL)\r
+    *processedSize = size;\r
+  return result;\r
+}\r
diff --git a/CPP/7zip/Archive/Common/OutStreamWithCRC.h b/CPP/7zip/Archive/Common/OutStreamWithCRC.h
new file mode 100755 (executable)
index 0000000..d9eb646
--- /dev/null
@@ -0,0 +1,36 @@
+// OutStreamWithCRC.h\r
+\r
+#ifndef __OUT_STREAM_WITH_CRC_H\r
+#define __OUT_STREAM_WITH_CRC_H\r
+\r
+#include "../../../../C/7zCrc.h"\r
+\r
+#include "../../../Common/MyCom.h"\r
+\r
+#include "../../IStream.h"\r
+\r
+class COutStreamWithCRC:\r
+  public ISequentialOutStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<ISequentialOutStream> _stream;\r
+  UInt64 _size;\r
+  UInt32 _crc;\r
+  bool _calculate;\r
+public:\r
+  MY_UNKNOWN_IMP\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+  void SetStream(ISequentialOutStream *stream) { _stream = stream; }\r
+  void ReleaseStream() { _stream.Release(); }\r
+  void Init(bool calculate = true)\r
+  {\r
+    _size = 0;\r
+    _calculate = calculate;\r
+    _crc = CRC_INIT_VAL;\r
+  }\r
+  void InitCRC() { _crc = CRC_INIT_VAL; }\r
+  UInt64 GetSize() const { return _size; }\r
+  UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp
new file mode 100755 (executable)
index 0000000..ba10802
--- /dev/null
@@ -0,0 +1,18 @@
+// OutStreamWithSha1.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "OutStreamWithSha1.h"\r
+\r
+STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  HRESULT result = S_OK;\r
+  if (_stream)\r
+    result = _stream->Write(data, size, &size);\r
+  if (_calculate)\r
+    _sha.Update((const Byte *)data, size);\r
+  _size += size;\r
+  if (processedSize != NULL)\r
+    *processedSize = size;\r
+  return result;\r
+}\r
diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.h b/CPP/7zip/Archive/Common/OutStreamWithSha1.h
new file mode 100755 (executable)
index 0000000..9e13244
--- /dev/null
@@ -0,0 +1,36 @@
+// OutStreamWithSha1.h\r
+\r
+#ifndef __OUT_STREAM_WITH_SHA1_H\r
+#define __OUT_STREAM_WITH_SHA1_H\r
+\r
+#include "../../Crypto/Sha1.h"\r
+\r
+#include "../../../Common/MyCom.h"\r
+\r
+#include "../../IStream.h"\r
+\r
+class COutStreamWithSha1:\r
+  public ISequentialOutStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<ISequentialOutStream> _stream;\r
+  UInt64 _size;\r
+  NCrypto::NSha1::CContext _sha;\r
+  bool _calculate;\r
+public:\r
+  MY_UNKNOWN_IMP\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+  void SetStream(ISequentialOutStream *stream) { _stream = stream; }\r
+  void ReleaseStream() { _stream.Release(); }\r
+  void Init(bool calculate = true)\r
+  {\r
+    _size = 0;\r
+    _calculate = calculate;\r
+    _sha.Init();\r
+  }\r
+  void InitSha1() { _sha.Init(); }\r
+  UInt64 GetSize() const { return _size; }\r
+  void Final(Byte *digest) { _sha.Final(digest); }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Common/ParseProperties.cpp b/CPP/7zip/Archive/Common/ParseProperties.cpp
new file mode 100755 (executable)
index 0000000..5550a23
--- /dev/null
@@ -0,0 +1,177 @@
+// ParseProperties.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "ParseProperties.h"\r
+\r
+#include "Common/StringToInt.h"\r
+#include "Common/MyCom.h"\r
+\r
+HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)\r
+{\r
+  if (prop.vt == VT_UI4)\r
+  {\r
+    if (!name.IsEmpty())\r
+      return E_INVALIDARG;\r
+    resValue = prop.ulVal;\r
+  }\r
+  else if (prop.vt == VT_EMPTY)\r
+  {\r
+    if(!name.IsEmpty())\r
+    {\r
+      const wchar_t *start = name;\r
+      const wchar_t *end;\r
+      UInt64 v = ConvertStringToUInt64(start, &end);\r
+      if (end - start != name.Length())\r
+        return E_INVALIDARG;\r
+      resValue = (UInt32)v;\r
+    }\r
+  }\r
+  else\r
+    return E_INVALIDARG;\r
+  return S_OK;\r
+}\r
+\r
+static const int kLogarithmicSizeLimit = 32;\r
+static const wchar_t kByteSymbol = L'B';\r
+static const wchar_t kKiloByteSymbol = L'K';\r
+static const wchar_t kMegaByteSymbol = L'M';\r
+\r
+HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize)\r
+{\r
+  UString srcString = srcStringSpec;\r
+  srcString.MakeUpper();\r
+\r
+  const wchar_t *start = srcString;\r
+  const wchar_t *end;\r
+  UInt64 number = ConvertStringToUInt64(start, &end);\r
+  int numDigits = (int)(end - start);\r
+  if (numDigits == 0 || srcString.Length() > numDigits + 1)\r
+    return E_INVALIDARG;\r
+  if (srcString.Length() == numDigits)\r
+  {\r
+    if (number >= kLogarithmicSizeLimit)\r
+      return E_INVALIDARG;\r
+    dicSize = (UInt32)1 << (int)number;\r
+    return S_OK;\r
+  }\r
+  switch (srcString[numDigits])\r
+  {\r
+    case kByteSymbol:\r
+      if (number >= ((UInt64)1 << kLogarithmicSizeLimit))\r
+        return E_INVALIDARG;\r
+      dicSize = (UInt32)number;\r
+      break;\r
+    case kKiloByteSymbol:\r
+      if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10)))\r
+        return E_INVALIDARG;\r
+      dicSize = (UInt32)(number << 10);\r
+      break;\r
+    case kMegaByteSymbol:\r
+      if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20)))\r
+        return E_INVALIDARG;\r
+      dicSize = (UInt32)(number << 20);\r
+      break;\r
+    default:\r
+      return E_INVALIDARG;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)\r
+{\r
+  if (name.IsEmpty())\r
+  {\r
+    if (prop.vt == VT_UI4)\r
+    {\r
+      UInt32 logDicSize = prop.ulVal;\r
+      if (logDicSize >= 32)\r
+        return E_INVALIDARG;\r
+      resValue = (UInt32)1 << logDicSize;\r
+      return S_OK;\r
+    }\r
+    if (prop.vt == VT_BSTR)\r
+      return ParsePropDictionaryValue(prop.bstrVal, resValue);\r
+    return E_INVALIDARG;\r
+  }\r
+  return ParsePropDictionaryValue(name, resValue);\r
+}\r
+\r
+bool StringToBool(const UString &s, bool &res)\r
+{\r
+  if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0 || s.Compare(L"+") == 0)\r
+  {\r
+    res = true;\r
+    return true;\r
+  }\r
+  if (s.CompareNoCase(L"OFF") == 0 || s.Compare(L"-") == 0)\r
+  {\r
+    res = false;\r
+    return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value)\r
+{\r
+  switch(value.vt)\r
+  {\r
+    case VT_EMPTY:\r
+      dest = true;\r
+      return S_OK;\r
+    case VT_BOOL:\r
+      dest = (value.boolVal != VARIANT_FALSE);\r
+      return S_OK;\r
+    /*\r
+    case VT_UI4:\r
+      dest = (value.ulVal != 0);\r
+      break;\r
+    */\r
+    case VT_BSTR:\r
+      return StringToBool(value.bstrVal, dest) ?  S_OK : E_INVALIDARG;\r
+  }\r
+  return E_INVALIDARG;\r
+}\r
+\r
+int ParseStringToUInt32(const UString &srcString, UInt32 &number)\r
+{\r
+  const wchar_t *start = srcString;\r
+  const wchar_t *end;\r
+  UInt64 number64 = ConvertStringToUInt64(start, &end);\r
+  if (number64 > 0xFFFFFFFF)\r
+  {\r
+    number = 0;\r
+    return 0;\r
+  }\r
+  number = (UInt32)number64;\r
+  return (int)(end - start);\r
+}\r
+\r
+HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads)\r
+{\r
+  if (name.IsEmpty())\r
+  {\r
+    switch(prop.vt)\r
+    {\r
+      case VT_UI4:\r
+        numThreads = prop.ulVal;\r
+        break;\r
+      default:\r
+      {\r
+        bool val;\r
+        RINOK(SetBoolProperty(val, prop));\r
+        numThreads = (val ? defaultNumThreads : 1);\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  else\r
+  {\r
+    UInt32 number;\r
+    int index = ParseStringToUInt32(name, number);\r
+    if (index != name.Length())\r
+      return E_INVALIDARG;\r
+    numThreads = number;\r
+  }\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/Archive/Common/ParseProperties.h b/CPP/7zip/Archive/Common/ParseProperties.h
new file mode 100755 (executable)
index 0000000..c64fc1e
--- /dev/null
@@ -0,0 +1,18 @@
+// ParseProperties.h\r
+\r
+#ifndef __PARSEPROPERTIES_H\r
+#define __PARSEPROPERTIES_H\r
+\r
+#include "Common/MyString.h"\r
+#include "Common/Types.h"\r
+\r
+HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);\r
+HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize);\r
+HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);\r
+\r
+bool StringToBool(const UString &s, bool &res);\r
+HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value);\r
+int ParseStringToUInt32(const UString &srcString, UInt32 &number);\r
+HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads);\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Common/StdAfx.h b/CPP/7zip/Archive/Common/StdAfx.h
new file mode 100755 (executable)
index 0000000..a4e6173
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+#include "../../../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/CpioHandler.cpp b/CPP/7zip/Archive/CpioHandler.cpp
new file mode 100755 (executable)
index 0000000..44633f2
--- /dev/null
@@ -0,0 +1,624 @@
+// CpioHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/StringConvert.h"\r
+#include "Common/StringToInt.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../Common/LimitedStreams.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/CopyCoder.h"\r
+\r
+#include "Common/ItemNameUtils.h"\r
+\r
+namespace NArchive {\r
+namespace NCpio {\r
+\r
+namespace NFileHeader\r
+{\r
+  namespace NMagic\r
+  {\r
+    const char *kMagic1 = "070701";\r
+    const char *kMagic2 = "070702";\r
+    const char *kMagic3 = "070707";\r
+    const char *kEndName = "TRAILER!!!";\r
+\r
+    const Byte kMagicForRecord2[2] = { 0xC7, 0x71 };\r
+  }\r
+\r
+  const UInt32 kRecord2Size = 26;\r
+  /*\r
+  struct CRecord2\r
+  {\r
+    unsigned short c_magic;\r
+    short c_dev;\r
+    unsigned short c_ino;\r
+    unsigned short c_mode;\r
+    unsigned short c_uid;\r
+    unsigned short c_gid;\r
+    unsigned short c_nlink;\r
+    short c_rdev;\r
+    unsigned short c_mtimes[2];\r
+    unsigned short c_namesize;\r
+    unsigned short c_filesizes[2];\r
+  };\r
+  */\r
\r
+  const UInt32 kRecordSize = 110;\r
+  /*\r
+  struct CRecord\r
+  {\r
+    char Magic[6];  // "070701" for "new" portable format, "070702" for CRC format\r
+    char inode[8];\r
+    char Mode[8];\r
+    char UID[8];\r
+    char GID[8];\r
+    char nlink[8];\r
+    char mtime[8];\r
+    char Size[8]; // must be 0 for FIFOs and directories\r
+    char DevMajor[8];\r
+    char DevMinor[8];\r
+    char RDevMajor[8];  //only valid for chr and blk special files\r
+    char RDevMinor[8];  //only valid for chr and blk special files\r
+    char NameSize[8]; // count includes terminating NUL in pathname\r
+    char ChkSum[8];  // 0 for "new" portable format; for CRC format the sum of all the bytes in the file\r
+    bool CheckMagic() const\r
+    { return memcmp(Magic, NMagic::kMagic1, 6) == 0 ||\r
+             memcmp(Magic, NMagic::kMagic2, 6) == 0; };\r
+  };\r
+  */\r
+\r
+  const UInt32 kOctRecordSize = 76;\r
\r
+}\r
+\r
+struct CItem\r
+{\r
+  AString Name;\r
+  UInt32 inode;\r
+  UInt32 Mode;\r
+  UInt32 UID;\r
+  UInt32 GID;\r
+  UInt32 Size;\r
+  UInt32 MTime;\r
+\r
+  // char LinkFlag;\r
+  // AString LinkName; ?????\r
+  char Magic[8];\r
+  UInt32 NumLinks;\r
+  UInt32 DevMajor;\r
+  UInt32 DevMinor;\r
+  UInt32 RDevMajor;\r
+  UInt32 RDevMinor;\r
+  UInt32 ChkSum;\r
+\r
+  UInt32 Align;\r
+\r
+  bool IsDir() const { return (Mode & 0170000) == 0040000; }\r
+};\r
+\r
+class CItemEx: public CItem\r
+{\r
+public:\r
+  UInt64 HeaderPosition;\r
+  UInt32 HeaderSize;\r
+  UInt64 GetDataPosition() const { return HeaderPosition + HeaderSize; };\r
+};\r
+\r
+const UInt32 kMaxBlockSize = NFileHeader::kRecordSize;\r
+\r
+class CInArchive\r
+{\r
+  CMyComPtr<IInStream> m_Stream;\r
+  UInt64 m_Position;\r
+\r
+  UInt16 _blockSize;\r
+  Byte _block[kMaxBlockSize];\r
+  UInt32 _blockPos;\r
+  Byte ReadByte();\r
+  UInt16 ReadUInt16();\r
+  UInt32 ReadUInt32();\r
+  \r
+  bool ReadNumber(UInt32 &resultValue);\r
+  bool ReadOctNumber(int size, UInt32 &resultValue);\r
+\r
+  HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize);\r
+public:\r
+  HRESULT Open(IInStream *inStream);\r
+  HRESULT GetNextItem(bool &filled, CItemEx &itemInfo);\r
+  HRESULT Skip(UInt64 numBytes);\r
+  HRESULT SkipDataRecords(UInt64 dataSize, UInt32 align);\r
+};\r
+\r
+HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize)\r
+{\r
+  size_t realProcessedSize = size;\r
+  RINOK(ReadStream(m_Stream, data, &realProcessedSize));\r
+  processedSize = (UInt32)realProcessedSize;\r
+  m_Position += processedSize;\r
+  return S_OK;\r
+}\r
+\r
+Byte CInArchive::ReadByte()\r
+{\r
+  if (_blockPos >= _blockSize)\r
+    throw "Incorrect cpio archive";\r
+  return _block[_blockPos++];\r
+}\r
+\r
+UInt16 CInArchive::ReadUInt16()\r
+{\r
+  UInt16 value = 0;\r
+  for (int i = 0; i < 2; i++)\r
+  {\r
+    Byte b = ReadByte();\r
+    value |= (UInt16(b) << (8 * i));\r
+  }\r
+  return value;\r
+}\r
+\r
+UInt32 CInArchive::ReadUInt32()\r
+{\r
+  UInt32 value = 0;\r
+  for (int i = 0; i < 4; i++)\r
+  {\r
+    Byte b = ReadByte();\r
+    value |= (UInt32(b) << (8 * i));\r
+  }\r
+  return value;\r
+}\r
+\r
+HRESULT CInArchive::Open(IInStream *inStream)\r
+{\r
+  RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position));\r
+  m_Stream = inStream;\r
+  return S_OK;\r
+}\r
+\r
+bool CInArchive::ReadNumber(UInt32 &resultValue)\r
+{\r
+  resultValue = 0;\r
+  for (int i = 0; i < 8; i++)\r
+  {\r
+    char c = char(ReadByte());\r
+    int d;\r
+    if (c >= '0' && c <= '9')\r
+      d = c - '0';\r
+    else if (c >= 'A' && c <= 'F')\r
+      d = 10 + c - 'A';\r
+    else if (c >= 'a' && c <= 'f')\r
+      d = 10 + c - 'a';\r
+    else\r
+      return false;\r
+    resultValue *= 0x10;\r
+    resultValue += d;\r
+  }\r
+  return true;\r
+}\r
+\r
+static bool OctalToNumber(const char *s, UInt64 &res)\r
+{\r
+  const char *end;\r
+  res = ConvertOctStringToUInt64(s, &end);\r
+  return (*end == ' ' || *end == 0);\r
+}\r
+\r
+static bool OctalToNumber32(const char *s, UInt32 &res)\r
+{\r
+  UInt64 res64;\r
+  if (!OctalToNumber(s, res64))\r
+    return false;\r
+  res = (UInt32)res64;\r
+  return (res64 <= 0xFFFFFFFF);\r
+}\r
+\r
+bool CInArchive::ReadOctNumber(int size, UInt32 &resultValue)\r
+{\r
+  char sz[32 + 4];\r
+  int i;\r
+  for (i = 0; i < size && i < 32; i++)\r
+    sz[i] = (char)ReadByte();\r
+  sz[i] = 0;\r
+  return OctalToNumber32(sz, resultValue);\r
+}\r
+\r
+#define GetFromHex(y) { if (!ReadNumber(y)) return S_FALSE; }\r
+#define GetFromOct6(y) { if (!ReadOctNumber(6, y)) return S_FALSE; }\r
+#define GetFromOct11(y) { if (!ReadOctNumber(11, y)) return S_FALSE; }\r
+\r
+static unsigned short ConvertValue(unsigned short value, bool convert)\r
+{\r
+  if (!convert)\r
+    return value;\r
+  return (unsigned short)((((unsigned short)(value & 0xFF)) << 8) | (value >> 8));\r
+}\r
+\r
+static UInt32 GetAlignedSize(UInt32 size, UInt32 align)\r
+{\r
+  while ((size & (align - 1)) != 0)\r
+    size++;\r
+  return size;\r
+}\r
+\r
+\r
+HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)\r
+{\r
+  filled = false;\r
+\r
+  UInt32 processedSize;\r
+  item.HeaderPosition = m_Position;\r
+\r
+  _blockSize = kMaxBlockSize;\r
+  RINOK(ReadBytes(_block, 2, processedSize));\r
+  if (processedSize != 2)\r
+    return S_FALSE;\r
+  _blockPos = 0;\r
+\r
+  UInt32 nameSize;\r
+\r
+  bool oldBE =\r
+    _block[0] == NFileHeader::NMagic::kMagicForRecord2[1] &&\r
+    _block[1] == NFileHeader::NMagic::kMagicForRecord2[0];\r
+\r
+  bool binMode = (_block[0] == NFileHeader::NMagic::kMagicForRecord2[0] &&\r
+    _block[1] == NFileHeader::NMagic::kMagicForRecord2[1]) ||\r
+    oldBE;\r
+\r
+  if (binMode)\r
+  {\r
+    RINOK(ReadBytes(_block + 2, NFileHeader::kRecord2Size - 2, processedSize));\r
+    if (processedSize != NFileHeader::kRecord2Size - 2)\r
+      return S_FALSE;\r
+    item.Align = 2;\r
+    _blockPos = 2;\r
+    item.DevMajor = 0;\r
+    item.DevMinor = ConvertValue(ReadUInt16(), oldBE);\r
+    item.inode = ConvertValue(ReadUInt16(), oldBE);\r
+    item.Mode = ConvertValue(ReadUInt16(), oldBE);\r
+    item.UID = ConvertValue(ReadUInt16(), oldBE);\r
+    item.GID = ConvertValue(ReadUInt16(), oldBE);\r
+    item.NumLinks = ConvertValue(ReadUInt16(), oldBE);\r
+    item.RDevMajor =0;\r
+    item.RDevMinor = ConvertValue(ReadUInt16(), oldBE);\r
+    UInt16 timeHigh = ConvertValue(ReadUInt16(), oldBE);\r
+    UInt16 timeLow = ConvertValue(ReadUInt16(), oldBE);\r
+    item.MTime = (UInt32(timeHigh) << 16) + timeLow;\r
+    nameSize = ConvertValue(ReadUInt16(), oldBE);\r
+    UInt16 sizeHigh = ConvertValue(ReadUInt16(), oldBE);\r
+    UInt16 sizeLow = ConvertValue(ReadUInt16(), oldBE);\r
+    item.Size = (UInt32(sizeHigh) << 16) + sizeLow;\r
+\r
+    item.ChkSum = 0;\r
+    item.HeaderSize = GetAlignedSize(\r
+        nameSize + NFileHeader::kRecord2Size, item.Align);\r
+    nameSize = item.HeaderSize - NFileHeader::kRecord2Size;\r
+  }\r
+  else\r
+  {\r
+    RINOK(ReadBytes(_block + 2, 4, processedSize));\r
+    if (processedSize != 4)\r
+      return S_FALSE;\r
+\r
+    bool magicOK =\r
+        memcmp(_block, NFileHeader::NMagic::kMagic1, 6) == 0 ||\r
+        memcmp(_block, NFileHeader::NMagic::kMagic2, 6) == 0;\r
+    _blockPos = 6;\r
+    if (magicOK)\r
+    {\r
+      RINOK(ReadBytes(_block + 6, NFileHeader::kRecordSize - 6, processedSize));\r
+      if (processedSize != NFileHeader::kRecordSize - 6)\r
+        return S_FALSE;\r
+      item.Align = 4;\r
+\r
+      GetFromHex(item.inode);\r
+      GetFromHex(item.Mode);\r
+      GetFromHex(item.UID);\r
+      GetFromHex(item.GID);\r
+      GetFromHex(item.NumLinks);\r
+      UInt32 mTime;\r
+      GetFromHex(mTime);\r
+      item.MTime = mTime;\r
+      GetFromHex(item.Size);\r
+      GetFromHex(item.DevMajor);\r
+      GetFromHex(item.DevMinor);\r
+      GetFromHex(item.RDevMajor);\r
+      GetFromHex(item.RDevMinor);\r
+      GetFromHex(nameSize);\r
+      GetFromHex(item.ChkSum);\r
+      item.HeaderSize = GetAlignedSize(\r
+          nameSize + NFileHeader::kRecordSize, item.Align);\r
+      nameSize = item.HeaderSize - NFileHeader::kRecordSize;\r
+    }\r
+    else\r
+    {\r
+      if (!memcmp(_block, NFileHeader::NMagic::kMagic3, 6) == 0)\r
+        return S_FALSE;\r
+      RINOK(ReadBytes(_block + 6, NFileHeader::kOctRecordSize - 6, processedSize));\r
+      if (processedSize != NFileHeader::kOctRecordSize - 6)\r
+        return S_FALSE;\r
+      item.Align = 1;\r
+      item.DevMajor = 0;\r
+      GetFromOct6(item.DevMinor);\r
+      GetFromOct6(item.inode);\r
+      GetFromOct6(item.Mode);\r
+      GetFromOct6(item.UID);\r
+      GetFromOct6(item.GID);\r
+      GetFromOct6(item.NumLinks);\r
+      item.RDevMajor = 0;\r
+      GetFromOct6(item.RDevMinor);\r
+      UInt32 mTime;\r
+      GetFromOct11(mTime);\r
+      item.MTime = mTime;\r
+      GetFromOct6(nameSize);\r
+      GetFromOct11(item.Size);  // ?????\r
+      item.HeaderSize = GetAlignedSize(\r
+          nameSize + NFileHeader::kOctRecordSize, item.Align);\r
+      nameSize = item.HeaderSize - NFileHeader::kOctRecordSize;\r
+    }\r
+  }\r
+  if (nameSize == 0 || nameSize >= (1 << 27))\r
+    return E_FAIL;\r
+  RINOK(ReadBytes(item.Name.GetBuffer(nameSize), nameSize, processedSize));\r
+  if (processedSize != nameSize)\r
+    return E_FAIL;\r
+  item.Name.ReleaseBuffer();\r
+  if (strcmp(item.Name, NFileHeader::NMagic::kEndName) == 0)\r
+    return S_OK;\r
+  filled = true;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::Skip(UInt64 numBytes)\r
+{\r
+  UInt64 newPostion;\r
+  RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion));\r
+  m_Position += numBytes;\r
+  if (m_Position != newPostion)\r
+    return E_FAIL;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::SkipDataRecords(UInt64 dataSize, UInt32 align)\r
+{\r
+  while ((dataSize & (align - 1)) != 0)\r
+    dataSize++;\r
+  return Skip(dataSize);\r
+}\r
+\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IInArchiveGetStream,\r
+  public CMyUnknownImp\r
+{\r
+  CObjectVector<CItemEx> _items;\r
+  CMyComPtr<IInStream> _stream;\r
+public:\r
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);\r
+};\r
+\r
+/*\r
+enum\r
+{\r
+  kpidinode = kpidUserDefined,\r
+  kpidiChkSum\r
+};\r
+*/\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidIsDir, VT_BOOL},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidPosixAttrib, VT_UI4},\r
+  // { L"inode", kpidinode, VT_UI4}\r
+  // { L"CheckSum", kpidiChkSum, VT_UI4}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps_NO\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback)\r
+{\r
+  COM_TRY_BEGIN\r
+  // try\r
+  {\r
+    CInArchive archive;\r
+\r
+    UInt64 endPos = 0;\r
+    bool needSetTotal = true;\r
+\r
+    if (callback != NULL)\r
+    {\r
+      RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));\r
+      RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));\r
+    }\r
+\r
+    RINOK(archive.Open(stream));\r
+\r
+    _items.Clear();\r
+\r
+    for (;;)\r
+    {\r
+      CItemEx item;\r
+      bool filled;\r
+      HRESULT result = archive.GetNextItem(filled, item);\r
+      if (result == S_FALSE)\r
+        return S_FALSE;\r
+      if (result != S_OK)\r
+        return S_FALSE;\r
+      if (!filled)\r
+        break;\r
+      _items.Add(item);\r
+      archive.SkipDataRecords(item.Size, item.Align);\r
+      if (callback != NULL)\r
+      {\r
+        if (needSetTotal)\r
+        {\r
+          RINOK(callback->SetTotal(NULL, &endPos));\r
+          needSetTotal = false;\r
+        }\r
+        if (_items.Size() % 100 == 0)\r
+        {\r
+          UInt64 numFiles = _items.Size();\r
+          UInt64 numBytes = item.HeaderPosition;\r
+          RINOK(callback->SetCompleted(&numFiles, &numBytes));\r
+        }\r
+      }\r
+    }\r
+    if (_items.Size() == 0)\r
+      return S_FALSE;\r
+\r
+    _stream = stream;\r
+  }\r
+  /*\r
+  catch(...)\r
+  {\r
+    return S_FALSE;\r
+  }\r
+  */\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _items.Clear();\r
+  _stream.Release();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _items.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  const CItemEx &item = _items[index];\r
+\r
+  switch(propID)\r
+  {\r
+    case kpidPath: prop = NItemName::GetOSName(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break;\r
+    case kpidIsDir: prop = item.IsDir(); break;\r
+    case kpidSize:\r
+    case kpidPackSize:\r
+      prop = (UInt64)item.Size;\r
+      break;\r
+    case kpidMTime:\r
+    {\r
+      if (item.MTime != 0)\r
+      {\r
+        FILETIME utc;\r
+        NWindows::NTime::UnixTimeToFileTime(item.MTime, utc);\r
+        prop = utc;\r
+      }\r
+      break;\r
+    }\r
+    case kpidPosixAttrib: prop = item.Mode; break;\r
+    /*\r
+    case kpidinode:  prop = item.inode; break;\r
+    case kpidiChkSum:  prop = item.ChkSum; break;\r
+    */\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _items.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt64 totalSize = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+    totalSize += _items[allFilesMode ? i : indices[i]].Size;\r
+  extractCallback->SetTotal(totalSize);\r
+\r
+  UInt64 currentTotalSize = 0;\r
+  \r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);\r
+  streamSpec->SetStream(_stream);\r
+\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    lps->InSize = lps->OutSize = currentTotalSize;\r
+    RINOK(lps->SetCur());\r
+    CMyComPtr<ISequentialOutStream> outStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    Int32 index = allFilesMode ? i : indices[i];\r
+    const CItemEx &item = _items[index];\r
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));\r
+    currentTotalSize += item.Size;\r
+    if (item.IsDir())\r
+    {\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+      continue;\r
+    }\r
+    if (!testMode && !outStream)\r
+      continue;\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+    if (testMode)\r
+    {\r
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+      continue;\r
+    }\r
+    RINOK(_stream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL));\r
+    streamSpec->Init(item.Size);\r
+    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));\r
+    outStream.Release();\r
+    RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ?\r
+        NExtract::NOperationResult::kOK:\r
+        NExtract::NOperationResult::kDataError));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)\r
+{\r
+  COM_TRY_BEGIN\r
+  const CItemEx &item = _items[index];\r
+  return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream);\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new NArchive::NCpio::CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"Cpio", L"cpio", 0, 0xED, { 0 }, 0, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Cpio)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/CramfsHandler.cpp b/CPP/7zip/Archive/CramfsHandler.cpp
new file mode 100755 (executable)
index 0000000..a574cdf
--- /dev/null
@@ -0,0 +1,644 @@
+// CramfsHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/7zCrc.h"\r
+#include "../../../C/CpuArch.h"\r
+#include "../../../C/Alloc.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/PropVariantUtils.h"\r
+\r
+#include "../Common/LimitedStreams.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamObjects.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/CopyCoder.h"\r
+#include "../Compress/ZlibDecoder.h"\r
+\r
+namespace NArchive {\r
+namespace NCramfs {\r
+\r
+#define SIGNATURE { 'C','o','m','p','r','e','s','s','e','d',' ','R','O','M','F','S' }\r
+\r
+static const UInt32 kSignatureSize = 16;\r
+static const char kSignature[kSignatureSize] = SIGNATURE;\r
+\r
+static const UInt32 kArcSizeMax = (256 + 16) << 20;\r
+static const UInt32 kNumFilesMax = (1 << 19);\r
+static const unsigned kNumDirLevelsMax = (1 << 8);\r
+\r
+static const UInt32 kHeaderSize = 0x40;\r
+static const unsigned kHeaderNameSize = 16;\r
+static const UInt32 kNodeSize = 12;\r
+\r
+static const UInt32 kFlag_FsVer2 = (1 << 0);\r
+\r
+static const CUInt32PCharPair k_Flags[] =\r
+{\r
+  { 0, "Ver2" },\r
+  { 1, "SortedDirs" },\r
+  { 8, "Holes" },\r
+  { 9, "WrongSignature" },\r
+  { 10, "ShiftedRootOffset" }\r
+};\r
+\r
+static const unsigned kBlockSizeLog = 12;\r
+static const UInt32 kBlockSize = 1 << kBlockSizeLog;\r
+\r
+/*\r
+struct CNode\r
+{\r
+  UInt16 Mode;\r
+  UInt16 Uid;\r
+  UInt32 Size;\r
+  Byte Gid;\r
+  UInt32 NameLen;\r
+  UInt32 Offset;\r
+\r
+  void Parse(const Byte *p)\r
+  {\r
+    Mode = GetUi16(p);\r
+    Uid = GetUi16(p + 2);\r
+    Size = Get32(p + 4) & 0xFFFFFF;\r
+    Gid = p[7];\r
+    NameLen = p[8] & 0x3F;\r
+    Offset = Get32(p + 8) >> 6;\r
+  }\r
+};\r
+*/\r
+\r
+#define Get32(p) (be ? GetBe32(p) : GetUi32(p))\r
+\r
+static UInt32 GetMode(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); }\r
+static bool IsDir(const Byte *p, bool be) { return (GetMode(p, be) & 0xF000) == 0x4000; }\r
+\r
+static UInt32 GetSize(const Byte *p, bool be)\r
+{\r
+  if (be)\r
+    return GetBe32(p + 4) >> 8;\r
+  else\r
+    return GetUi32(p + 4) & 0xFFFFFF;\r
+}\r
+\r
+static UInt32 GetNameLen(const Byte *p, bool be)\r
+{\r
+  if (be)\r
+    return (p[8] & 0xFC);\r
+  else\r
+    return (p[8] & 0x3F) << 2;\r
+}\r
+\r
+static UInt32 GetOffset(const Byte *p, bool be)\r
+{\r
+  if (be)\r
+    return (GetBe32(p + 8) & 0x03FFFFFF) << 2;\r
+  else\r
+    return GetUi32(p + 8) >> 6 << 2;\r
+}\r
+\r
+struct CItem\r
+{\r
+  UInt32 Offset;\r
+  int Parent;\r
+};\r
+\r
+struct CHeader\r
+{\r
+  bool be;\r
+  UInt32 Size;\r
+  UInt32 Flags;\r
+  // UInt32 Future;\r
+  UInt32 Crc;\r
+  // UInt32 Edition;\r
+  UInt32 NumBlocks;\r
+  UInt32 NumFiles;\r
+  char Name[kHeaderNameSize];\r
+\r
+  bool Parse(const Byte *p)\r
+  {\r
+    if (memcmp(p + 16, kSignature, kSignatureSize) != 0)\r
+      return false;\r
+    switch(GetUi32(p))\r
+    {\r
+      case 0x28CD3D45: be = false; break;\r
+      case 0x453DCD28: be = true; break;\r
+      default: return false;\r
+    }\r
+    Size = Get32(p + 4);\r
+    Flags = Get32(p + 8);\r
+    // Future = Get32(p + 0xC);\r
+    Crc = Get32(p + 0x20);\r
+    // Edition = Get32(p + 0x24);\r
+    NumBlocks = Get32(p + 0x28);\r
+    NumFiles = Get32(p + 0x2C);\r
+    memcpy(Name, p + 0x30, kHeaderNameSize);\r
+    return true;\r
+  }\r
+\r
+  bool IsVer2() const { return (Flags & kFlag_FsVer2) != 0; }\r
+};\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IInArchiveGetStream,\r
+  public CMyUnknownImp\r
+{\r
+  CRecordVector<CItem> _items;\r
+  CMyComPtr<IInStream> _stream;\r
+  Byte *_data;\r
+  UInt32 _size;\r
+  UInt32 _headersSize;\r
+  AString _errorMessage;\r
+  CHeader _h;\r
+\r
+  // Current file\r
+\r
+  NCompress::NZlib::CDecoder *_zlibDecoderSpec;\r
+  CMyComPtr<ICompressCoder> _zlibDecoder;\r
+  \r
+  CBufInStream *_inStreamSpec;\r
+  CMyComPtr<ISequentialInStream> _inStream;\r
+\r
+  CBufPtrSeqOutStream *_outStreamSpec;\r
+  CMyComPtr<ISequentialOutStream> _outStream;\r
+\r
+  UInt32 _curBlocksOffset;\r
+  UInt32 _curNumBlocks;\r
+\r
+  HRESULT OpenDir(int parent, UInt32 baseOffsetBase, unsigned level);\r
+  HRESULT Open2(IInStream *inStream);\r
+  AString GetPath(int index) const;\r
+  bool GetPackSize(int index, UInt32 &res) const;\r
+  void Free();\r
+public:\r
+  CHandler(): _data(0) {}\r
+  ~CHandler() { Free(); }\r
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);\r
+  HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize);\r
+};\r
+\r
+static const STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidIsDir, VT_BOOL},\r
+  { NULL, kpidSize, VT_UI4},\r
+  { NULL, kpidPackSize, VT_UI4},\r
+  { NULL, kpidPosixAttrib, VT_UI4}\r
+  // { NULL, kpidOffset, VT_UI4}\r
+};\r
+\r
+static const STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidName, VT_BSTR},\r
+  { NULL, kpidBigEndian, VT_BOOL},\r
+  { NULL, kpidCharacts, VT_BSTR},\r
+  { NULL, kpidPhySize, VT_UI4},\r
+  { NULL, kpidHeadersSize, VT_UI4},\r
+  { NULL, kpidNumSubFiles, VT_UI4},\r
+  { NULL, kpidNumBlocks, VT_UI4}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+HRESULT CHandler::OpenDir(int parent, UInt32 baseOffset, unsigned level)\r
+{\r
+  const Byte *p = _data + baseOffset;\r
+  bool be = _h.be;\r
+  if (!IsDir(p, be))\r
+    return S_OK;\r
+  UInt32 offset = GetOffset(p, be);\r
+  UInt32 size = GetSize(p, be);\r
+  if (offset == 0 && size == 0)\r
+    return S_OK;\r
+  UInt32 end = offset + size;\r
+  if (offset < kHeaderSize || end > _size || level > kNumDirLevelsMax)\r
+    return S_FALSE;\r
+  if (end > _headersSize)\r
+    _headersSize = end;\r
+\r
+  int startIndex = _items.Size();\r
+  \r
+  while (size != 0)\r
+  {\r
+    if (size < kNodeSize || (UInt32)_items.Size() >= kNumFilesMax)\r
+      return S_FALSE;\r
+    CItem item;\r
+    item.Parent = parent;\r
+    item.Offset = offset;\r
+    _items.Add(item);\r
+    UInt32 nodeLen = kNodeSize + GetNameLen(_data + offset, be);\r
+    if (size < nodeLen)\r
+      return S_FALSE;\r
+    offset += nodeLen;\r
+    size -= nodeLen;\r
+  }\r
+\r
+  int endIndex = _items.Size();\r
+  for (int i = startIndex; i < endIndex; i++)\r
+  {\r
+    RINOK(OpenDir(i, _items[i].Offset, level + 1));\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CHandler::Open2(IInStream *inStream)\r
+{\r
+  Byte buf[kHeaderSize];\r
+  RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize));\r
+  if (!_h.Parse(buf))\r
+    return S_FALSE;\r
+  if (_h.IsVer2())\r
+  {\r
+    if (_h.Size < kHeaderSize || _h.Size > kArcSizeMax || _h.NumFiles > kNumFilesMax)\r
+      return S_FALSE;\r
+  }\r
+  else\r
+  {\r
+    UInt64 size;\r
+    RINOK(inStream->Seek(0, STREAM_SEEK_END, &size));\r
+    if (size > kArcSizeMax)\r
+      return S_FALSE;\r
+    _h.Size = (UInt32)size;\r
+    RINOK(inStream->Seek(kHeaderSize, STREAM_SEEK_SET, NULL));\r
+  }\r
+  _data = (Byte *)MidAlloc(_h.Size);\r
+  if (_data == 0)\r
+    return E_OUTOFMEMORY;\r
+  memcpy(_data, buf, kHeaderSize);\r
+  size_t processed = _h.Size - kHeaderSize;\r
+  RINOK(ReadStream(inStream, _data + kHeaderSize, &processed));\r
+  if (processed < kNodeSize)\r
+    return S_FALSE;\r
+  _size = kHeaderSize + (UInt32)processed;\r
+  if (_size != _h.Size)\r
+    _errorMessage = "Unexpected end of archive";\r
+  else\r
+  {\r
+    SetUi32(_data + 0x20, 0);\r
+    if (_h.IsVer2())\r
+      if (CrcCalc(_data, _h.Size) != _h.Crc)\r
+        _errorMessage = "CRC error";\r
+  }\r
+  if (_h.IsVer2())\r
+    _items.Reserve(_h.NumFiles - 1);\r
+  return OpenDir(-1, kHeaderSize, 0);\r
+}\r
+\r
+AString CHandler::GetPath(int index) const\r
+{\r
+  unsigned len = 0;\r
+  int indexMem = index;\r
+  do\r
+  {\r
+    const CItem &item = _items[index];\r
+    index = item.Parent;\r
+    const Byte *p = _data + item.Offset;\r
+    unsigned size = GetNameLen(p, _h.be);\r
+    p += kNodeSize;\r
+    unsigned i;\r
+    for (i = 0; i < size && p[i]; i++);\r
+    len += i + 1;\r
+  }\r
+  while (index >= 0);\r
+  len--;\r
+\r
+  AString path;\r
+  char *dest = path.GetBuffer(len) + len;\r
+  index = indexMem;\r
+  for (;;)\r
+  {\r
+    const CItem &item = _items[index];\r
+    index = item.Parent;\r
+    const Byte *p = _data + item.Offset;\r
+    unsigned size = GetNameLen(p, _h.be);\r
+    p += kNodeSize;\r
+    unsigned i;\r
+    for (i = 0; i < size && p[i]; i++);\r
+    dest -= i;\r
+    memcpy(dest, p, i);\r
+    if (index < 0)\r
+      break;\r
+    *(--dest) = CHAR_PATH_SEPARATOR;\r
+  }\r
+  path.ReleaseBuffer(len);\r
+  return path;\r
+}\r
+\r
+bool CHandler::GetPackSize(int index, UInt32 &res) const\r
+{\r
+  const CItem &item = _items[index];\r
+  const Byte *p = _data + item.Offset;\r
+  bool be = _h.be;\r
+  UInt32 offset = GetOffset(p, be);\r
+  if (offset < kHeaderSize)\r
+    return false;\r
+  UInt32 numBlocks = (GetSize(p, be) + kBlockSize - 1) >> kBlockSizeLog;\r
+  UInt32 start = offset + numBlocks * 4;\r
+  if (start > _size)\r
+    return false;\r
+  UInt32 end = Get32(_data + start - 4);\r
+  if (end < start)\r
+    return false;\r
+  res = end - start;\r
+  return true;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* callback */)\r
+{\r
+  COM_TRY_BEGIN\r
+  {\r
+    Close();\r
+    RINOK(Open2(stream));\r
+    _stream = stream;\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+void CHandler::Free()\r
+{\r
+  MidFree(_data);\r
+  _data = 0;\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _headersSize = 0;\r
+  _items.Clear();\r
+  _stream.Release();\r
+  _errorMessage.Empty();\r
+  Free();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _items.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidName:\r
+    {\r
+      char dest[kHeaderNameSize + 4];\r
+      memcpy(dest, _h.Name, kHeaderNameSize);\r
+      dest[kHeaderNameSize] = 0;\r
+      prop = dest;\r
+      break;\r
+    }\r
+    case kpidBigEndian: prop = _h.be; break;\r
+    case kpidCharacts: FLAGS_TO_PROP(k_Flags, _h.Flags, prop); break;\r
+    case kpidNumBlocks: if (_h.IsVer2()) prop = _h.NumBlocks; break;\r
+    case kpidNumSubFiles: if (_h.IsVer2()) prop = _h.NumFiles; break;\r
+    case kpidPhySize: if (_h.IsVer2()) prop = _h.Size; break;\r
+    case kpidHeadersSize: prop = _headersSize; break;\r
+    case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  const CItem &item = _items[index];\r
+  const Byte *p = _data + item.Offset;\r
+  bool be = _h.be;\r
+  bool isDir = IsDir(p, be);\r
+  switch(propID)\r
+  {\r
+    case kpidPath: prop = MultiByteToUnicodeString(GetPath(index), CP_OEMCP); break;\r
+    case kpidIsDir: prop = isDir; break;\r
+    // case kpidOffset: prop = (UInt32)GetOffset(p, be); break;\r
+    case kpidSize: if (!isDir) prop = GetSize(p, be); break;\r
+    case kpidPackSize:\r
+      if (!isDir)\r
+      {\r
+        UInt32 size;\r
+        if (GetPackSize(index, size))\r
+          prop = size;\r
+      }\r
+      break;\r
+    case kpidPosixAttrib: prop = (UInt32)GetMode(p, be); break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+class CCramfsInStream: public CCachedInStream\r
+{\r
+  HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize);\r
+public:\r
+  CHandler *Handler;\r
+};\r
+\r
+HRESULT CCramfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)\r
+{\r
+  return Handler->ReadBlock(blockIndex, dest, blockSize);\r
+}\r
+\r
+HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)\r
+{\r
+  if (!_zlibDecoder)\r
+  {\r
+    _zlibDecoderSpec = new NCompress::NZlib::CDecoder();\r
+    _zlibDecoder = _zlibDecoderSpec;\r
+  }\r
+  if (!_inStream)\r
+  {\r
+    _inStreamSpec = new CBufInStream();\r
+    _inStream = _inStreamSpec;\r
+  }\r
+  if (!_outStream)\r
+  {\r
+    _outStreamSpec = new CBufPtrSeqOutStream();\r
+    _outStream = _outStreamSpec;\r
+  }\r
+  bool be = _h.be;\r
+  const Byte *p = _data + (_curBlocksOffset + (UInt32)blockIndex * 4);\r
+  UInt32 start = (blockIndex == 0 ? _curBlocksOffset + _curNumBlocks * 4: Get32(p - 4));\r
+  UInt32 end = Get32(p);\r
+  if (end < start || end > _size)\r
+    return S_FALSE;\r
+  UInt32 inSize = end - start;\r
+  _inStreamSpec->Init(_data + start, inSize);\r
+  _outStreamSpec->Init(dest, blockSize);\r
+  RINOK(_zlibDecoder->Code(_inStream, _outStream, NULL, NULL, NULL));\r
+  return (_zlibDecoderSpec->GetInputProcessedSize() == inSize &&\r
+      _outStreamSpec->GetPos() == blockSize) ? S_OK : S_FALSE;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _items.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  bool be = _h.be;\r
+  UInt64 totalSize = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    const Byte *p = _data + _items[allFilesMode ? i : indices[i]].Offset;\r
+    if (!IsDir(p, be))\r
+      totalSize += GetSize(p, be);\r
+  }\r
+  extractCallback->SetTotal(totalSize);\r
+\r
+  UInt64 totalPackSize;\r
+  totalSize = totalPackSize = 0;\r
+  \r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);\r
+  streamSpec->SetStream(_stream);\r
+\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    lps->InSize = totalPackSize;\r
+    lps->OutSize = totalSize;\r
+    RINOK(lps->SetCur());\r
+    CMyComPtr<ISequentialOutStream> outStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    UInt32 index = allFilesMode ? i : indices[i];\r
+    const CItem &item = _items[index];\r
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));\r
+    const Byte *p = _data + item.Offset;\r
+\r
+    if (IsDir(p, be))\r
+    {\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+      continue;\r
+    }\r
+    UInt32 curSize = GetSize(p, be);\r
+    totalSize += curSize;\r
+    UInt32 packSize;\r
+    if (GetPackSize(index, packSize))\r
+      totalPackSize += packSize;\r
+\r
+    if (!testMode && !outStream)\r
+      continue;\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+\r
+    UInt32 offset = GetOffset(p, be);\r
+    if (offset < kHeaderSize)\r
+      curSize = 0;\r
+\r
+    int res = NExtract::NOperationResult::kDataError;\r
+    {\r
+      CMyComPtr<ISequentialInStream> inSeqStream;\r
+      CMyComPtr<IInStream> inStream;\r
+      HRESULT hres = GetStream(index, &inSeqStream);\r
+      if (inSeqStream)\r
+        inSeqStream.QueryInterface(IID_IInStream, &inStream);\r
+      if (hres == E_OUTOFMEMORY)\r
+        return E_OUTOFMEMORY;\r
+      if (hres == S_FALSE || !inStream)\r
+        res = NExtract::NOperationResult::kUnSupportedMethod;\r
+      else\r
+      {\r
+        RINOK(hres);\r
+        if (inStream)\r
+        {\r
+          HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress);\r
+          if (hres != S_OK && hres != S_FALSE)\r
+          {\r
+            RINOK(hres);\r
+          }\r
+          if (copyCoderSpec->TotalSize == curSize && hres == S_OK)\r
+            res = NExtract::NOperationResult::kOK;\r
+        }\r
+      }\r
+    }\r
+    RINOK(extractCallback->SetOperationResult(res));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)\r
+{\r
+  COM_TRY_BEGIN\r
+\r
+  const CItem &item = _items[index];\r
+  const Byte *p = _data + item.Offset;\r
+\r
+  bool be = _h.be;\r
+  if (IsDir(p, be))\r
+    return E_FAIL;\r
+\r
+  UInt32 size = GetSize(p, be);\r
+  UInt32 numBlocks = (size + kBlockSize - 1) >> kBlockSizeLog;\r
+  UInt32 offset = GetOffset(p, be);\r
+  if (offset < kHeaderSize)\r
+  {\r
+    if (offset != 0)\r
+      return S_FALSE;\r
+    CBufInStream *streamSpec = new CBufInStream;\r
+    CMyComPtr<IInStream> streamTemp = streamSpec;\r
+    streamSpec->Init(NULL, 0);\r
+    *stream = streamTemp.Detach();\r
+    return S_OK;\r
+  }\r
+\r
+  if (offset + numBlocks * 4 > _size)\r
+    return S_FALSE;\r
+  UInt32 prev = offset;\r
+  for (UInt32 i = 0; i < numBlocks; i++)\r
+  {\r
+    UInt32 next = Get32(_data + offset + i * 4);\r
+    if (next < prev || next > _size)\r
+      return S_FALSE;\r
+    prev = next;\r
+  }\r
+\r
+  CCramfsInStream *streamSpec = new CCramfsInStream;\r
+  CMyComPtr<IInStream> streamTemp = streamSpec;\r
+  _curNumBlocks = numBlocks;\r
+  _curBlocksOffset = offset;\r
+  streamSpec->Handler = this;\r
+  if (!streamSpec->Alloc(kBlockSizeLog, 21 - kBlockSizeLog))\r
+    return E_OUTOFMEMORY;\r
+  streamSpec->Init(size);\r
+  *stream = streamTemp.Detach();\r
+\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new NArchive::NCramfs::CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"CramFS", L"cramfs", 0, 0xD3, SIGNATURE, kSignatureSize, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Cramfs)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/DebHandler.cpp b/CPP/7zip/Archive/DebHandler.cpp
new file mode 100755 (executable)
index 0000000..1699b17
--- /dev/null
@@ -0,0 +1,413 @@
+// DebHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/StringConvert.h"\r
+#include "Common/StringToInt.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../Common/LimitedStreams.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/CopyCoder.h"\r
+\r
+#include "Common/ItemNameUtils.h"\r
+\r
+using namespace NWindows;\r
+using namespace NTime;\r
+\r
+namespace NArchive {\r
+namespace NDeb {\r
+\r
+namespace NHeader\r
+{\r
+  const int kSignatureLen = 8;\r
+  \r
+  const char *kSignature = "!<arch>\n";\r
+\r
+  const int kNameSize = 16;\r
+  const int kTimeSize = 12;\r
+  const int kModeSize = 8;\r
+  const int kSizeSize = 10;\r
+\r
+  /*\r
+  struct CHeader\r
+  {\r
+    char Name[kNameSize];\r
+    char MTime[kTimeSize];\r
+    char Number0[6];\r
+    char Number1[6];\r
+    char Mode[kModeSize];\r
+    char Size[kSizeSize];\r
+    char Quote;\r
+    char NewLine;\r
+  };\r
+  */\r
+  const int kHeaderSize = kNameSize + kTimeSize + 6 + 6 + kModeSize + kSizeSize + 1 + 1;\r
+}\r
+\r
+struct CItem\r
+{\r
+  AString Name;\r
+  UInt64 Size;\r
+  UInt32 MTime;\r
+  UInt32 Mode;\r
+\r
+  UInt64 HeaderPos;\r
+  UInt64 GetDataPos() const { return HeaderPos + NHeader::kHeaderSize; };\r
+  // UInt64 GetFullSize() const { return NFileHeader::kRecordSize + Size; };\r
+};\r
+\r
+class CInArchive\r
+{\r
+  CMyComPtr<IInStream> m_Stream;\r
+  \r
+  HRESULT GetNextItemReal(bool &filled, CItem &itemInfo);\r
+public:\r
+  UInt64 m_Position;\r
+  HRESULT Open(IInStream *inStream);\r
+  HRESULT GetNextItem(bool &filled, CItem &itemInfo);\r
+  HRESULT SkipData(UInt64 dataSize);\r
+};\r
+\r
+HRESULT CInArchive::Open(IInStream *inStream)\r
+{\r
+  RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position));\r
+  char signature[NHeader::kSignatureLen];\r
+  RINOK(ReadStream_FALSE(inStream, signature, NHeader::kSignatureLen));\r
+  m_Position += NHeader::kSignatureLen;\r
+  if (memcmp(signature, NHeader::kSignature, NHeader::kSignatureLen) != 0)\r
+    return S_FALSE;\r
+  m_Stream = inStream;\r
+  return S_OK;\r
+}\r
+\r
+static void MyStrNCpy(char *dest, const char *src, int size)\r
+{\r
+  for (int i = 0; i < size; i++)\r
+  {\r
+    char c = src[i];\r
+    dest[i] = c;\r
+    if (c == 0)\r
+      break;\r
+  }\r
+}\r
+\r
+static bool OctalToNumber(const char *s, int size, UInt64 &res)\r
+{\r
+  char sz[32];\r
+  MyStrNCpy(sz, s, size);\r
+  sz[size] = 0;\r
+  const char *end;\r
+  int i;\r
+  for (i = 0; sz[i] == ' '; i++);\r
+  res = ConvertOctStringToUInt64(sz + i, &end);\r
+  return (*end == ' ' || *end == 0);\r
+}\r
+\r
+static bool OctalToNumber32(const char *s, int size, UInt32 &res)\r
+{\r
+  UInt64 res64;\r
+  if (!OctalToNumber(s, size, res64))\r
+    return false;\r
+  res = (UInt32)res64;\r
+  return (res64 <= 0xFFFFFFFF);\r
+}\r
+\r
+static bool DecimalToNumber(const char *s, int size, UInt64 &res)\r
+{\r
+  char sz[32];\r
+  MyStrNCpy(sz, s, size);\r
+  sz[size] = 0;\r
+  const char *end;\r
+  int i;\r
+  for (i = 0; sz[i] == ' '; i++);\r
+  res = ConvertStringToUInt64(sz + i, &end);\r
+  return (*end == ' ' || *end == 0);\r
+}\r
+\r
+static bool DecimalToNumber32(const char *s, int size, UInt32 &res)\r
+{\r
+  UInt64 res64;\r
+  if (!DecimalToNumber(s, size, res64))\r
+    return false;\r
+  res = (UInt32)res64;\r
+  return (res64 <= 0xFFFFFFFF);\r
+}\r
+\r
+#define RIF(x) { if (!(x)) return S_FALSE; }\r
+\r
+\r
+HRESULT CInArchive::GetNextItemReal(bool &filled, CItem &item)\r
+{\r
+  filled = false;\r
+\r
+  char header[NHeader::kHeaderSize];\r
+  const char *cur = header;\r
+\r
+  size_t processedSize = sizeof(header);\r
+  item.HeaderPos = m_Position;\r
+  RINOK(ReadStream(m_Stream, header, &processedSize));\r
+  if (processedSize != sizeof(header))\r
+    return S_OK;\r
+  m_Position += processedSize;\r
+  \r
+  char tempString[NHeader::kNameSize + 1];\r
+  MyStrNCpy(tempString, cur, NHeader::kNameSize);\r
+  cur += NHeader::kNameSize;\r
+  tempString[NHeader::kNameSize] = '\0';\r
+  item.Name = tempString;\r
+  item.Name.Trim();\r
+\r
+  for (int i = 0; i < item.Name.Length(); i++)\r
+    if (((Byte)item.Name[i]) < 0x20)\r
+      return S_FALSE;\r
+\r
+  RIF(DecimalToNumber32(cur, NHeader::kTimeSize, item.MTime));\r
+  cur += NHeader::kTimeSize;\r
+\r
+  cur += 6 + 6;\r
+  \r
+  RIF(OctalToNumber32(cur, NHeader::kModeSize, item.Mode));\r
+  cur += NHeader::kModeSize;\r
+\r
+  RIF(DecimalToNumber(cur, NHeader::kSizeSize, item.Size));\r
+  cur += NHeader::kSizeSize;\r
+\r
+  filled = true;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::GetNextItem(bool &filled, CItem &item)\r
+{\r
+  for (;;)\r
+  {\r
+    RINOK(GetNextItemReal(filled, item));\r
+    if (!filled)\r
+      return S_OK;\r
+    if (item.Name.Compare("debian-binary") != 0)\r
+      return S_OK;\r
+    if (item.Size != 4)\r
+      return S_OK;\r
+    SkipData(item.Size);\r
+  }\r
+}\r
+\r
+HRESULT CInArchive::SkipData(UInt64 dataSize)\r
+{\r
+  return m_Stream->Seek((dataSize + 1) & (~((UInt64)0x1)), STREAM_SEEK_CUR, &m_Position);\r
+}\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IInArchiveGetStream,\r
+  public CMyUnknownImp\r
+{\r
+  CObjectVector<CItem> _items;\r
+  CMyComPtr<IInStream> _stream;\r
+  Int32 _mainSubfile;\r
+  UInt64 _phySize;\r
+public:\r
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);\r
+};\r
+\r
+static STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidPhySize, VT_UI8}\r
+};\r
+\r
+static STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidMTime, VT_FILETIME}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream,\r
+    const UInt64 * /* maxCheckStartPosition */,\r
+    IArchiveOpenCallback *openArchiveCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  {\r
+    _mainSubfile = -1;\r
+    CInArchive archive;\r
+    if (archive.Open(stream) != S_OK)\r
+      return S_FALSE;\r
+    _items.Clear();\r
+\r
+    if (openArchiveCallback != NULL)\r
+    {\r
+      RINOK(openArchiveCallback->SetTotal(NULL, NULL));\r
+      UInt64 numFiles = _items.Size();\r
+      RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));\r
+    }\r
+\r
+    for (;;)\r
+    {\r
+      CItem item;\r
+      bool filled;\r
+      HRESULT result = archive.GetNextItem(filled, item);\r
+      if (result == S_FALSE)\r
+        return S_FALSE;\r
+      if (result != S_OK)\r
+        return S_FALSE;\r
+      if (!filled)\r
+        break;\r
+      if (item.Name.Left(5) == "data.")\r
+        _mainSubfile = _items.Size();\r
+      _items.Add(item);\r
+      archive.SkipData(item.Size);\r
+      if (openArchiveCallback != NULL)\r
+      {\r
+        UInt64 numFiles = _items.Size();\r
+        RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));\r
+      }\r
+    }\r
+    _stream = stream;\r
+    _phySize = archive.m_Position;\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _stream.Release();\r
+  _items.Clear();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _items.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidPhySize: prop = _phySize; break;\r
+    case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  const CItem &item = _items[index];\r
+\r
+  switch(propID)\r
+  {\r
+    case kpidPath: prop = (const wchar_t *)NItemName::GetOSName2(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break;\r
+    case kpidSize:\r
+    case kpidPackSize:\r
+      prop = item.Size;\r
+      break;\r
+    case kpidMTime:\r
+    {\r
+      if (item.MTime != 0)\r
+      {\r
+        FILETIME fileTime;\r
+        NTime::UnixTimeToFileTime(item.MTime, fileTime);\r
+        prop = fileTime;\r
+      }\r
+      break;\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _items.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt64 totalSize = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+    totalSize += _items[allFilesMode ? i : indices[i]].Size;\r
+  extractCallback->SetTotal(totalSize);\r
+\r
+  UInt64 currentTotalSize = 0;\r
+  \r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);\r
+  streamSpec->SetStream(_stream);\r
+\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    lps->InSize = lps->OutSize = currentTotalSize;\r
+    RINOK(lps->SetCur());\r
+    CMyComPtr<ISequentialOutStream> realOutStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    Int32 index = allFilesMode ? i : indices[i];\r
+    const CItem &item = _items[index];\r
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+    currentTotalSize += item.Size;\r
+    \r
+    if (!testMode && !realOutStream)\r
+      continue;\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+    if (testMode)\r
+    {\r
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+      continue;\r
+    }\r
+    RINOK(_stream->Seek(item.GetDataPos(), STREAM_SEEK_SET, NULL));\r
+    streamSpec->Init(item.Size);\r
+    RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));\r
+    realOutStream.Release();\r
+    RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ?\r
+        NExtract::NOperationResult::kOK:\r
+        NExtract::NOperationResult::kDataError));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)\r
+{\r
+  COM_TRY_BEGIN\r
+  const CItem &item = _items[index];\r
+  return CreateLimitedInStream(_stream, item.GetDataPos(), item.Size, stream);\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new NArchive::NDeb::CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"Deb", L"deb", 0, 0xEC, { '!', '<', 'a', 'r', 'c', 'h', '>', '\n' }, 8, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Deb)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/DeflateProps.cpp b/CPP/7zip/Archive/DeflateProps.cpp
new file mode 100755 (executable)
index 0000000..41d7f0e
--- /dev/null
@@ -0,0 +1,118 @@
+// DeflateProps.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "Common/ParseProperties.h"\r
+\r
+#include "DeflateProps.h"\r
+\r
+namespace NArchive {\r
+\r
+static const UInt32 kAlgo1 = 0;\r
+static const UInt32 kAlgo5 = 1;\r
+\r
+static const UInt32 kPasses1 = 1;\r
+static const UInt32 kPasses7 = 3;\r
+static const UInt32 kPasses9 = 10;\r
+\r
+static const UInt32 kFb1 = 32;\r
+static const UInt32 kFb7 = 64;\r
+static const UInt32 kFb9 = 128;\r
+\r
+void CDeflateProps::Normalize()\r
+{\r
+  UInt32 level = Level;\r
+  if (level == 0xFFFFFFFF)\r
+    level = 5;\r
+  \r
+  if (Algo == 0xFFFFFFFF)\r
+    Algo = (level >= 5 ?\r
+      kAlgo5 :\r
+      kAlgo1);\r
+\r
+  if (NumPasses == 0xFFFFFFFF)\r
+    NumPasses =\r
+      (level >= 9 ? kPasses9 :\r
+      (level >= 7 ? kPasses7 :\r
+                    kPasses1));\r
+  if (Fb == 0xFFFFFFFF)\r
+    Fb =\r
+      (level >= 9 ? kFb9 :\r
+      (level >= 7 ? kFb7 :\r
+                    kFb1));\r
+}\r
+\r
+HRESULT CDeflateProps::SetCoderProperties(ICompressSetCoderProperties *setCoderProperties)\r
+{\r
+  Normalize();\r
+\r
+  NWindows::NCOM::CPropVariant props[] =\r
+  {\r
+    Algo,\r
+    NumPasses,\r
+    Fb,\r
+    Mc\r
+  };\r
+  PROPID propIDs[] =\r
+  {\r
+    NCoderPropID::kAlgorithm,\r
+    NCoderPropID::kNumPasses,\r
+    NCoderPropID::kNumFastBytes,\r
+    NCoderPropID::kMatchFinderCycles\r
+  };\r
+  int numProps = sizeof(propIDs) / sizeof(propIDs[0]);\r
+  if (!McDefined)\r
+    numProps--;\r
+  return setCoderProperties->SetCoderProperties(propIDs, props, numProps);\r
+}\r
+\r
+HRESULT CDeflateProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)\r
+{\r
+  Init();\r
+  for (int i = 0; i < numProps; i++)\r
+  {\r
+    UString name = names[i];\r
+    name.MakeUpper();\r
+    if (name.IsEmpty())\r
+      return E_INVALIDARG;\r
+    const PROPVARIANT &prop = values[i];\r
+    if (name[0] == L'X')\r
+    {\r
+      UInt32 a = 9;\r
+      RINOK(ParsePropValue(name.Mid(1), prop, a));\r
+      Level = a;\r
+    }\r
+    else if (name.Left(1) == L"A")\r
+    {\r
+      UInt32 a = kAlgo5;\r
+      RINOK(ParsePropValue(name.Mid(1), prop, a));\r
+      Algo = a;\r
+    }\r
+    else if (name.Left(4) == L"PASS")\r
+    {\r
+      UInt32 a = kPasses9;\r
+      RINOK(ParsePropValue(name.Mid(4), prop, a));\r
+      NumPasses = a;\r
+    }\r
+    else if (name.Left(2) == L"FB")\r
+    {\r
+      UInt32 a = kFb9;\r
+      RINOK(ParsePropValue(name.Mid(2), prop, a));\r
+      Fb = a;\r
+    }\r
+    else if (name.Left(2) == L"MC")\r
+    {\r
+      UInt32 a = 0xFFFFFFFF;\r
+      RINOK(ParsePropValue(name.Mid(2), prop, a));\r
+      Mc = a;\r
+      McDefined = true;\r
+    }\r
+    else\r
+      return E_INVALIDARG;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+}\r
diff --git a/CPP/7zip/Archive/DeflateProps.h b/CPP/7zip/Archive/DeflateProps.h
new file mode 100755 (executable)
index 0000000..454da8d
--- /dev/null
@@ -0,0 +1,35 @@
+// DeflateProps.h\r
+\r
+#ifndef __DEFLATE_PROPS_H\r
+#define __DEFLATE_PROPS_H\r
+\r
+#include "../ICoder.h"\r
+\r
+namespace NArchive {\r
+\r
+class CDeflateProps\r
+{\r
+  UInt32 Level;\r
+  UInt32 NumPasses;\r
+  UInt32 Fb;\r
+  UInt32 Algo;\r
+  UInt32 Mc;\r
+  bool McDefined;\r
+\r
+  void Init()\r
+  {\r
+    Level = NumPasses = Fb = Algo = Mc = 0xFFFFFFFF;\r
+    McDefined = false;\r
+  }\r
+  void Normalize();\r
+public:\r
+  CDeflateProps() { Init(); }\r
+  bool IsMaximum() const { return Algo > 0; }\r
+\r
+  HRESULT SetCoderProperties(ICompressSetCoderProperties *setCoderProperties);\r
+  HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);\r
+};\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/DllExports.cpp b/CPP/7zip/Archive/DllExports.cpp
new file mode 100755 (executable)
index 0000000..9b72d04
--- /dev/null
@@ -0,0 +1,47 @@
+// DLLExports.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/MyInitGuid.h"\r
+#include "../../Common/ComTry.h"\r
+#include "../../Common/Types.h"\r
+\r
+#include "../../Windows/NtCheck.h"\r
+#include "../../Windows/PropVariant.h"\r
+\r
+#include "IArchive.h"\r
+#include "../ICoder.h"\r
+#include "../IPassword.h"\r
+\r
+HINSTANCE g_hInstance;\r
+\r
+#define NT_CHECK_FAIL_ACTION return FALSE;\r
+\r
+extern "C"\r
+BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)\r
+{\r
+  if (dwReason == DLL_PROCESS_ATTACH)\r
+  {\r
+    g_hInstance = hInstance;\r
+    NT_CHECK;\r
+  }\r
+  return TRUE;\r
+}\r
+\r
+DEFINE_GUID(CLSID_CArchiveHandler,\r
+0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);\r
+\r
+STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject);\r
+\r
+STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)\r
+{\r
+  return CreateArchiver(clsid, iid, outObject);\r
+}\r
+\r
+STDAPI SetLargePageMode()\r
+{\r
+  #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)\r
+  SetLargePageSize();\r
+  #endif\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/Archive/DllExports2.cpp b/CPP/7zip/Archive/DllExports2.cpp
new file mode 100755 (executable)
index 0000000..a45b5c9
--- /dev/null
@@ -0,0 +1,74 @@
+// DLLExports.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/MyInitGuid.h"\r
+\r
+#if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)\r
+#include "../../../C/Alloc.h"\r
+#endif\r
+\r
+#include "../../Common/ComTry.h"\r
+\r
+#include "../../Windows/NtCheck.h"\r
+#include "../../Windows/PropVariant.h"\r
+\r
+#include "../ICoder.h"\r
+#include "../IPassword.h"\r
+\r
+#include "IArchive.h"\r
+\r
+HINSTANCE g_hInstance;\r
+\r
+#define NT_CHECK_FAIL_ACTION return FALSE;\r
+\r
+extern "C"\r
+BOOL WINAPI DllMain(\r
+  #ifdef UNDER_CE\r
+  HANDLE\r
+  #else\r
+  HINSTANCE\r
+  #endif\r
+  hInstance, DWORD dwReason, LPVOID /*lpReserved*/)\r
+{\r
+  if (dwReason == DLL_PROCESS_ATTACH)\r
+  {\r
+    g_hInstance = (HINSTANCE)hInstance;\r
+    NT_CHECK;\r
+  }\r
+  return TRUE;\r
+}\r
+\r
+DEFINE_GUID(CLSID_CArchiveHandler,\r
+0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);\r
+\r
+static const UInt16 kDecodeId = 0x2790;\r
+\r
+DEFINE_GUID(CLSID_CCodec,\r
+0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);\r
+\r
+STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject);\r
+STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject);\r
+\r
+STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)\r
+{\r
+  // COM_TRY_BEGIN\r
+  *outObject = 0;\r
+  if (*iid == IID_ICompressCoder || *iid == IID_ICompressCoder2 || *iid == IID_ICompressFilter)\r
+  {\r
+    return CreateCoder(clsid, iid, outObject);\r
+  }\r
+  else\r
+  {\r
+    return CreateArchiver(clsid, iid, outObject);\r
+  }\r
+  // COM_TRY_END\r
+}\r
+\r
+STDAPI SetLargePageMode()\r
+{\r
+  #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)\r
+  SetLargePageSize();\r
+  #endif\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/Archive/DmgHandler.cpp b/CPP/7zip/Archive/DmgHandler.cpp
new file mode 100755 (executable)
index 0000000..8e812d8
--- /dev/null
@@ -0,0 +1,918 @@
+// DmgHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/Buffer.h"\r
+#include "Common/ComTry.h"\r
+#include "Common/IntToString.h"\r
+#include "Common/MyXml.h"\r
+#include "Common/UTFConvert.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../Common/LimitedStreams.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/BZip2Decoder.h"\r
+#include "../Compress/CopyCoder.h"\r
+#include "../Compress/ZlibDecoder.h"\r
+\r
+// #define DMG_SHOW_RAW\r
+\r
+// #include <stdio.h>\r
+#define PRF(x) // x\r
+\r
+#define Get32(p) GetBe32(p)\r
+#define Get64(p) GetBe64(p)\r
+\r
+static int Base64ToByte(char c)\r
+{\r
+  if (c >= 'A' && c <= 'Z') return c - 'A';\r
+  if (c >= 'a' && c <= 'z') return c - 'a' + 26;\r
+  if (c >= '0' && c <= '9') return c - '0' + 52;\r
+  if (c == '+') return 62;\r
+  if (c == '/') return 63;\r
+  if (c == '=') return 0;\r
+  return -1;\r
+}\r
+\r
+static int Base64ToBin(Byte *dest, const char *src, int srcLen)\r
+{\r
+  int srcPos = 0;\r
+  int destPos = 0;\r
+  while (srcPos < srcLen)\r
+  {\r
+    Byte buf[4];\r
+    int filled = 0;\r
+    while (srcPos < srcLen)\r
+    {\r
+      int n = Base64ToByte(src[srcPos++]);\r
+      if (n >= 0)\r
+      {\r
+        buf[filled++] = (Byte)n;\r
+        if (filled == 4)\r
+          break;\r
+      }\r
+    }\r
+    if (filled >= 2) { if (dest) dest[destPos] = (buf[0] << 2) | (buf[1] >> 4); destPos++; }\r
+    if (filled >= 3) { if (dest) dest[destPos] = (buf[1] << 4) | (buf[2] >> 2); destPos++; }\r
+    if (filled >= 4) { if (dest) dest[destPos] = (buf[2] << 6) | (buf[3]     ); destPos++; }\r
+  }\r
+  return destPos;\r
+}\r
+\r
+static UString GetSizeString(UInt64 value)\r
+{\r
+  wchar_t s[32];\r
+  wchar_t c;\r
+  if (value < (UInt64)20000) c = 0;\r
+  else if (value < ((UInt64)20000 << 10)) { value >>= 10; c = L'K'; }\r
+  else if (value < ((UInt64)20000 << 20)) { value >>= 20; c = L'M'; }\r
+  else                                    { value >>= 30; c = L'G'; }\r
+  ConvertUInt64ToString(value, s);\r
+  int p = MyStringLen(s);\r
+  s[p++] = c;\r
+  s[p++] = L'\0';\r
+  return s;\r
+}\r
+\r
+namespace NArchive {\r
+namespace NDmg {\r
+\r
+struct CBlock\r
+{\r
+  UInt32 Type;\r
+  UInt64 UnpPos;\r
+  UInt64 UnpSize;\r
+  UInt64 PackPos;\r
+  UInt64 PackSize;\r
+  \r
+  UInt64 GetNextPackOffset() const { return PackPos + PackSize; }\r
+};\r
+\r
+struct CFile\r
+{\r
+  CByteBuffer Raw;\r
+  UInt64 StartPos;\r
+  CRecordVector<CBlock> Blocks;\r
+  UInt64 GetUnpackSize() const\r
+  {\r
+    UInt64 size = 0;\r
+    for (int i = 0; i < Blocks.Size(); i++)\r
+      size += Blocks[i].UnpSize;\r
+    return size;\r
+  };\r
+  UInt64 GetPackSize() const\r
+  {\r
+    UInt64 size = 0;\r
+    for (int i = 0; i < Blocks.Size(); i++)\r
+      size += Blocks[i].PackSize;\r
+    return size;\r
+  };\r
+\r
+  AString Name;\r
+};\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<IInStream> _inStream;\r
+\r
+  AString _xml;\r
+  CObjectVector<CFile> _files;\r
+  CRecordVector<int> _fileIndices;\r
+\r
+  HRESULT Open2(IInStream *stream);\r
+  HRESULT Extract(IInStream *stream);\r
+public:\r
+  MY_UNKNOWN_IMP1(IInArchive)\r
+  INTERFACE_IInArchive(;)\r
+};\r
+\r
+const UInt32 kXmlSizeMax = ((UInt32)1 << 31) - (1 << 14);\r
+\r
+enum\r
+{\r
+  METHOD_ZERO_0 = 0,\r
+  METHOD_COPY   = 1,\r
+  METHOD_ZERO_2 = 2,\r
+  METHOD_ADC    = 0x80000004,\r
+  METHOD_ZLIB   = 0x80000005,\r
+  METHOD_BZIP2  = 0x80000006,\r
+  METHOD_DUMMY  = 0x7FFFFFFE,\r
+  METHOD_END    = 0xFFFFFFFF\r
+};\r
+\r
+struct CMethodStat\r
+{\r
+  UInt32 NumBlocks;\r
+  UInt64 PackSize;\r
+  UInt64 UnpSize;\r
+  CMethodStat(): NumBlocks(0), PackSize(0), UnpSize(0) {}\r
+};\r
+\r
+struct CMethods\r
+{\r
+  CRecordVector<CMethodStat> Stats;\r
+  CRecordVector<UInt32> Types;\r
+  void Update(const CFile &file);\r
+  UString GetString() const;\r
+};\r
+\r
+void CMethods::Update(const CFile &file)\r
+{\r
+  for (int i = 0; i < file.Blocks.Size(); i++)\r
+  {\r
+    const CBlock &b = file.Blocks[i];\r
+    int index = Types.FindInSorted(b.Type);\r
+    if (index < 0)\r
+    {\r
+      index = Types.AddToUniqueSorted(b.Type);\r
+      Stats.Insert(index, CMethodStat());\r
+    }\r
+    CMethodStat &m = Stats[index];\r
+    m.PackSize += b.PackSize;\r
+    m.UnpSize += b.UnpSize;\r
+    m.NumBlocks++;\r
+  }\r
+}\r
+\r
+UString CMethods::GetString() const\r
+{\r
+  UString res;\r
+  for (int i = 0; i < Types.Size(); i++)\r
+  {\r
+    if (i != 0)\r
+      res += L' ';\r
+    wchar_t buf[32];\r
+    const wchar_t *s;\r
+    const CMethodStat &m = Stats[i];\r
+    bool showPack = true;\r
+    UInt32 type = Types[i];\r
+    switch(type)\r
+    {\r
+      case METHOD_ZERO_0: s = L"zero0"; showPack = (m.PackSize != 0); break;\r
+      case METHOD_ZERO_2: s = L"zero2"; showPack = (m.PackSize != 0); break;\r
+      case METHOD_COPY:   s = L"copy"; showPack = (m.UnpSize != m.PackSize); break;\r
+      case METHOD_ADC:    s = L"adc"; break;\r
+      case METHOD_ZLIB:   s = L"zlib"; break;\r
+      case METHOD_BZIP2:  s = L"bzip2"; break;\r
+      default: ConvertUInt64ToString(type, buf); s = buf;\r
+    }\r
+    res += s;\r
+    if (m.NumBlocks != 1)\r
+    {\r
+      res += L'[';\r
+      ConvertUInt64ToString(m.NumBlocks, buf);\r
+      res += buf;\r
+      res += L']';\r
+    }\r
+    res += L'-';\r
+    res += GetSizeString(m.UnpSize);\r
+    if (showPack)\r
+    {\r
+      res += L'-';\r
+      res += GetSizeString(m.PackSize);\r
+    }\r
+  }\r
+  return res;\r
+}\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidComment, VT_BSTR},\r
+  { NULL, kpidMethod, VT_BSTR}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+\r
+STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidMethod, VT_BSTR},\r
+  { NULL, kpidNumBlocks, VT_UI4}\r
+};\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidMethod:\r
+    {\r
+      CMethods m;\r
+      for (int i = 0; i < _files.Size(); i++)\r
+        m.Update(_files[i]);\r
+      prop = m.GetString();\r
+      break;\r
+    }\r
+    case kpidNumBlocks:\r
+    {\r
+      UInt64 numBlocks = 0;\r
+      for (int i = 0; i < _files.Size(); i++)\r
+        numBlocks += _files[i].Blocks.Size();\r
+      prop = numBlocks;\r
+      break;\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+IMP_IInArchive_ArcProps\r
+\r
+static int FindKeyPair(const CXmlItem &item, const AString &key, const AString &nextTag)\r
+{\r
+  for (int i = 0; i + 1 < item.SubItems.Size(); i++)\r
+  {\r
+    const CXmlItem &si = item.SubItems[i];\r
+    if (si.IsTagged("key") && si.GetSubString() == key && item.SubItems[i + 1].IsTagged(nextTag))\r
+      return i + 1;\r
+  }\r
+  return -1;\r
+}\r
+\r
+static AString GetStringFromKeyPair(const CXmlItem &item, const AString &key, const AString &nextTag)\r
+{\r
+  int index = FindKeyPair(item, key, nextTag);\r
+  if (index >= 0)\r
+    return item.SubItems[index].GetSubString();\r
+  return AString();\r
+}\r
+\r
+HRESULT CHandler::Open2(IInStream *stream)\r
+{\r
+  const int HEADER_SIZE = 0x1E0;\r
+\r
+  UInt64 headerPos;\r
+  RINOK(stream->Seek(-HEADER_SIZE, STREAM_SEEK_END, &headerPos));\r
+  Byte buf[HEADER_SIZE];\r
+  RINOK(ReadStream_FALSE(stream, buf, HEADER_SIZE));\r
+  UInt64 address1 = Get64(buf + 0);\r
+  UInt64 address2 = Get64(buf + 0xB8);\r
+  UInt64 size64 = Get64(buf + 0xC0);\r
+  if (address1 != address2 || size64 >= kXmlSizeMax || size64 == 0 ||\r
+      address1 >= headerPos || address1 + size64 > headerPos)\r
+    return S_FALSE;\r
+  RINOK(stream->Seek(address1, STREAM_SEEK_SET, NULL));\r
+  size_t size = (size_t)size64;\r
+\r
+  char *ss = _xml.GetBuffer((int)size + 1);\r
+  RINOK(ReadStream_FALSE(stream, ss, size));\r
+  ss[size] = 0;\r
+  _xml.ReleaseBuffer();\r
+\r
+  CXml xml;\r
+  if (!xml.Parse(_xml))\r
+    return S_FALSE;\r
+  if (xml.Root.Name != "plist")\r
+    return S_FALSE;\r
+  \r
+  int dictIndex = xml.Root.FindSubTag("dict");\r
+  if (dictIndex < 0)\r
+    return S_FALSE;\r
+  \r
+  const CXmlItem &dictItem = xml.Root.SubItems[dictIndex];\r
+  int rfDictIndex = FindKeyPair(dictItem, "resource-fork", "dict");\r
+  if (rfDictIndex < 0)\r
+    return S_FALSE;\r
+  \r
+  const CXmlItem &rfDictItem = dictItem.SubItems[rfDictIndex];\r
+  int arrIndex = FindKeyPair(rfDictItem, "blkx", "array");\r
+  if (arrIndex < 0)\r
+    return S_FALSE;\r
+\r
+  const CXmlItem &arrItem = rfDictItem.SubItems[arrIndex];\r
+\r
+  int i;\r
+  for (i = 0; i < arrItem.SubItems.Size(); i++)\r
+  {\r
+    const CXmlItem &item = arrItem.SubItems[i];\r
+    if (!item.IsTagged("dict"))\r
+      continue;\r
+\r
+    CFile file;\r
+    file.StartPos = 0;\r
+\r
+    int destLen;\r
+    {\r
+      AString dataString;\r
+      AString name = GetStringFromKeyPair(item, "Name", "string");\r
+      if (name.IsEmpty())\r
+        name = GetStringFromKeyPair(item, "CFName", "string");\r
+      file.Name = name;\r
+      dataString = GetStringFromKeyPair(item, "Data", "data");\r
+     \r
+      destLen = Base64ToBin(NULL, dataString, dataString.Length());\r
+      file.Raw.SetCapacity(destLen);\r
+      Base64ToBin(file.Raw, dataString, dataString.Length());\r
+    }\r
+\r
+    if (destLen > 0xCC && Get32(file.Raw) == 0x6D697368)\r
+    {\r
+      PRF(printf("\n\n index = %d", _files.Size()));\r
+      const int kRecordSize = 40;\r
+      for (int offset = 0xCC; offset + kRecordSize <= destLen; offset += kRecordSize)\r
+      {\r
+        const Byte *p = (const Byte *)file.Raw + offset;\r
+        CBlock b;\r
+        b.Type = Get32(p);\r
+        if (b.Type == METHOD_END)\r
+          break;\r
+        if (b.Type == METHOD_DUMMY)\r
+          continue;\r
+\r
+        b.UnpPos   = Get64(p + 0x08) << 9;\r
+        b.UnpSize  = Get64(p + 0x10) << 9;\r
+        b.PackPos  = Get64(p + 0x18);\r
+        b.PackSize = Get64(p + 0x20);\r
+\r
+        file.Blocks.Add(b);\r
+\r
+        PRF(printf("\nType=%8x  m[1]=%8x  uPos=%8x  uSize=%7x  pPos=%8x  pSize=%7x",\r
+            b.Type, Get32(p + 4), (UInt32)b.UnpPos, (UInt32)b.UnpSize, (UInt32)b.PackPos, (UInt32)b.PackSize));\r
+      }\r
+    }\r
+    int itemIndex = _files.Add(file);\r
+    if (file.Blocks.Size() > 0)\r
+    {\r
+      // if (file.Name.Find("HFS") >= 0)\r
+        _fileIndices.Add(itemIndex);\r
+    }\r
+  }\r
+  \r
+  // PackPos for each new file is 0 in some DMG files. So we use additional StartPos\r
+\r
+  bool allStartAreZeros = true;\r
+  for (i = 0; i < _files.Size(); i++)\r
+  {\r
+    const CFile &file = _files[i];\r
+    if (!file.Blocks.IsEmpty() && file.Blocks[0].PackPos != 0)\r
+      allStartAreZeros = false;\r
+  }\r
+  UInt64 startPos = 0;\r
+  if (allStartAreZeros)\r
+  {\r
+    for (i = 0; i < _files.Size(); i++)\r
+    {\r
+      CFile &file = _files[i];\r
+      file.StartPos = startPos;\r
+      if (!file.Blocks.IsEmpty())\r
+        startPos += file.Blocks.Back().GetNextPackOffset();\r
+    }\r
+  }\r
+\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream,\r
+    const UInt64 * /* maxCheckStartPosition */,\r
+    IArchiveOpenCallback * /* openArchiveCallback */)\r
+{\r
+  COM_TRY_BEGIN\r
+  {\r
+    Close();\r
+    if (Open2(stream) != S_OK)\r
+      return S_FALSE;\r
+    _inStream = stream;\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _inStream.Release();\r
+  _fileIndices.Clear();\r
+  _files.Clear();\r
+  _xml.Empty();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _fileIndices.Size()\r
+    #ifdef DMG_SHOW_RAW\r
+    + _files.Size() + 1;\r
+    #endif\r
+  ;\r
+  return S_OK;\r
+}\r
+\r
+#define RAW_PREFIX L"raw" WSTRING_PATH_SEPARATOR\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  \r
+  #ifdef DMG_SHOW_RAW\r
+  if ((int)index == _fileIndices.Size())\r
+  {\r
+    switch(propID)\r
+    {\r
+      case kpidPath:\r
+        prop = RAW_PREFIX L"a.xml";\r
+        break;\r
+      case kpidSize:\r
+      case kpidPackSize:\r
+        prop = (UInt64)_xml.Length();\r
+        break;\r
+    }\r
+  }\r
+  else if ((int)index > _fileIndices.Size())\r
+  {\r
+    int rawIndex = (int)index - (_fileIndices.Size() + 1);\r
+    switch(propID)\r
+    {\r
+      case kpidPath:\r
+      {\r
+        wchar_t s[32] = RAW_PREFIX;\r
+        ConvertUInt64ToString(rawIndex, s + MyStringLen(s));\r
+        prop = s;\r
+        break;\r
+      }\r
+      case kpidSize:\r
+      case kpidPackSize:\r
+        prop = (UInt64)_files[rawIndex].Raw.GetCapacity();\r
+        break;\r
+    }\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    int itemIndex = _fileIndices[index];\r
+    const CFile &item = _files[itemIndex];\r
+    switch(propID)\r
+    {\r
+      case kpidMethod:\r
+      {\r
+        CMethods m;\r
+        m.Update(item);\r
+        UString resString = m.GetString();\r
+        if (!resString.IsEmpty())\r
+          prop = resString;\r
+        break;\r
+      }\r
+      \r
+      // case kpidExtension: prop = L"hfs"; break;\r
+\r
+      case kpidPath:\r
+      {\r
+        // break;\r
+        UString name;\r
+        wchar_t s[32];\r
+        ConvertUInt64ToString(index, s);\r
+        name = s;\r
+        int num = 10;\r
+        int numDigits;\r
+        for (numDigits = 1; num < _fileIndices.Size(); numDigits++)\r
+          num *= 10;\r
+        while (name.Length() < numDigits)\r
+          name = L'0' + name;\r
+\r
+        AString subName;\r
+        int pos1 = item.Name.Find('(');\r
+        if (pos1 >= 0)\r
+        {\r
+          pos1++;\r
+          int pos2 = item.Name.Find(')', pos1);\r
+          if (pos2 >= 0)\r
+          {\r
+            subName = item.Name.Mid(pos1, pos2 - pos1);\r
+            pos1 = subName.Find(':');\r
+            if (pos1 >= 0)\r
+              subName = subName.Left(pos1);\r
+          }\r
+        }\r
+        subName.Trim();\r
+        if (!subName.IsEmpty())\r
+        {\r
+          if (subName == "Apple_HFS")\r
+            subName = "hfs";\r
+          else if (subName == "Apple_HFSX")\r
+            subName = "hfsx";\r
+          else if (subName == "Apple_Free")\r
+            subName = "free";\r
+          else if (subName == "DDM")\r
+            subName = "ddm";\r
+          UString name2;\r
+          ConvertUTF8ToUnicode(subName, name2);\r
+          name += L'.';\r
+          name += name2;\r
+        }\r
+        else\r
+        {\r
+          UString name2;\r
+          ConvertUTF8ToUnicode(item.Name, name2);\r
+          if (!name2.IsEmpty())\r
+            name += L" - ";\r
+          name += name2;\r
+        }\r
+        prop = name;\r
+        break;\r
+      }\r
+      case kpidComment:\r
+      {\r
+        UString name;\r
+        ConvertUTF8ToUnicode(item.Name, name);\r
+        prop = name;\r
+        break;\r
+      }\r
+\r
+      case kpidSize:  prop = item.GetUnpackSize(); break;\r
+      case kpidPackSize:  prop = item.GetPackSize(); break;\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+class CAdcDecoder:\r
+  public ICompressCoder,\r
+  public CMyUnknownImp\r
+{\r
+  CLzOutWindow m_OutWindowStream;\r
+  CInBuffer m_InStream;\r
+\r
+  void ReleaseStreams()\r
+  {\r
+    m_OutWindowStream.ReleaseStream();\r
+    m_InStream.ReleaseStream();\r
+  }\r
+\r
+  class CCoderReleaser\r
+  {\r
+    CAdcDecoder *m_Coder;\r
+  public:\r
+    bool NeedFlush;\r
+    CCoderReleaser(CAdcDecoder *coder): m_Coder(coder), NeedFlush(true) {}\r
+    ~CCoderReleaser()\r
+    {\r
+      if (NeedFlush)\r
+        m_Coder->m_OutWindowStream.Flush();\r
+      m_Coder->ReleaseStreams();\r
+    }\r
+  };\r
+  friend class CCoderReleaser;\r
+\r
+public:\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(CodeReal)(ISequentialInStream *inStream,\r
+      ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,\r
+      ICompressProgressInfo *progress);\r
+\r
+  STDMETHOD(Code)(ISequentialInStream *inStream,\r
+      ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,\r
+      ICompressProgressInfo *progress);\r
+};\r
+\r
+STDMETHODIMP CAdcDecoder::CodeReal(ISequentialInStream *inStream,\r
+    ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,\r
+    ICompressProgressInfo *progress)\r
+{\r
+  if (!m_OutWindowStream.Create(1 << 18))\r
+    return E_OUTOFMEMORY;\r
+  if (!m_InStream.Create(1 << 18))\r
+    return E_OUTOFMEMORY;\r
+\r
+  m_OutWindowStream.SetStream(outStream);\r
+  m_OutWindowStream.Init(false);\r
+  m_InStream.SetStream(inStream);\r
+  m_InStream.Init();\r
+  \r
+  CCoderReleaser coderReleaser(this);\r
+\r
+  const UInt32 kStep = (1 << 20);\r
+  UInt64 nextLimit = kStep;\r
+\r
+  UInt64 pos = 0;\r
+  while (pos < *outSize)\r
+  {\r
+    if (pos > nextLimit && progress)\r
+    {\r
+      UInt64 packSize = m_InStream.GetProcessedSize();\r
+      RINOK(progress->SetRatioInfo(&packSize, &pos));\r
+      nextLimit += kStep;\r
+    }\r
+    Byte b;\r
+    if (!m_InStream.ReadByte(b))\r
+      return S_FALSE;\r
+    UInt64 rem = *outSize - pos;\r
+    if (b & 0x80)\r
+    {\r
+      unsigned num = (b & 0x7F) + 1;\r
+      if (num > rem)\r
+        return S_FALSE;\r
+      for (unsigned i = 0; i < num; i++)\r
+      {\r
+        if (!m_InStream.ReadByte(b))\r
+          return S_FALSE;\r
+        m_OutWindowStream.PutByte(b);\r
+      }\r
+      pos += num;\r
+      continue;\r
+    }\r
+    Byte b1;\r
+    if (!m_InStream.ReadByte(b1))\r
+      return S_FALSE;\r
+\r
+    UInt32 len, distance;\r
+\r
+    if (b & 0x40)\r
+    {\r
+      len = ((UInt32)b & 0x3F) + 4;\r
+      Byte b2;\r
+      if (!m_InStream.ReadByte(b2))\r
+        return S_FALSE;\r
+      distance = ((UInt32)b1 << 8) + b2;\r
+    }\r
+    else\r
+    {\r
+      b &= 0x3F;\r
+      len = ((UInt32)b >> 2) + 3;\r
+      distance = (((UInt32)b & 3) << 8) + b1;\r
+    }\r
+\r
+    if (distance >= pos || len > rem)\r
+      return S_FALSE;\r
+    m_OutWindowStream.CopyBlock(distance, len);\r
+    pos += len;\r
+  }\r
+  if (*inSize != m_InStream.GetProcessedSize())\r
+    return S_FALSE;\r
+  coderReleaser.NeedFlush = false;\r
+  return m_OutWindowStream.Flush();\r
+}\r
+\r
+STDMETHODIMP CAdcDecoder::Code(ISequentialInStream *inStream,\r
+    ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,\r
+    ICompressProgressInfo *progress)\r
+{\r
+  try { return CodeReal(inStream, outStream, inSize, outSize, progress);}\r
+  catch(const CInBufferException &e) { return e.ErrorCode; }\r
+  catch(const CLzOutWindowException &e) { return e.ErrorCode; }\r
+  catch(...) { return S_FALSE; }\r
+}\r
+\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _files.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt64 totalSize = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    int index = (int)(allFilesMode ? i : indices[i]);\r
+    #ifdef DMG_SHOW_RAW\r
+    if (index == _fileIndices.Size())\r
+      totalSize += _xml.Length();\r
+    else if (index > _fileIndices.Size())\r
+      totalSize += _files[index - (_fileIndices.Size() + 1)].Raw.GetCapacity();\r
+    else\r
+    #endif\r
+      totalSize += _files[_fileIndices[index]].GetUnpackSize();\r
+  }\r
+  extractCallback->SetTotal(totalSize);\r
+\r
+  UInt64 currentPackTotal = 0;\r
+  UInt64 currentUnpTotal = 0;\r
+  UInt64 currentPackSize = 0;\r
+  UInt64 currentUnpSize = 0;\r
+\r
+  const UInt32 kZeroBufSize = (1 << 14);\r
+  CByteBuffer zeroBuf;\r
+  zeroBuf.SetCapacity(kZeroBufSize);\r
+  memset(zeroBuf, 0, kZeroBufSize);\r
+  \r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  NCompress::NBZip2::CDecoder *bzip2CoderSpec = new NCompress::NBZip2::CDecoder();\r
+  CMyComPtr<ICompressCoder> bzip2Coder = bzip2CoderSpec;\r
+\r
+  NCompress::NZlib::CDecoder *zlibCoderSpec = new NCompress::NZlib::CDecoder();\r
+  CMyComPtr<ICompressCoder> zlibCoder = zlibCoderSpec;\r
+\r
+  CAdcDecoder *adcCoderSpec = new CAdcDecoder();\r
+  CMyComPtr<ICompressCoder> adcCoder = adcCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);\r
+  streamSpec->SetStream(_inStream);\r
+\r
+  for (i = 0; i < numItems; i++, currentPackTotal += currentPackSize, currentUnpTotal += currentUnpSize)\r
+  {\r
+    lps->InSize = currentPackTotal;\r
+    lps->OutSize = currentUnpTotal;\r
+    currentPackSize = 0;\r
+    currentUnpSize = 0;\r
+    RINOK(lps->SetCur());\r
+    CMyComPtr<ISequentialOutStream> realOutStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    Int32 index = allFilesMode ? i : indices[i];\r
+    // const CItemEx &item = _files[index];\r
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+    \r
+    \r
+    if (!testMode && !realOutStream)\r
+      continue;\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+\r
+    CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream;\r
+    CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\r
+    outStreamSpec->SetStream(realOutStream);\r
+    \r
+    realOutStream.Release();\r
+\r
+    Int32 opRes = NExtract::NOperationResult::kOK;\r
+    #ifdef DMG_SHOW_RAW\r
+    if (index > _fileIndices.Size())\r
+    {\r
+      const CByteBuffer &buf = _files[index - (_fileIndices.Size() + 1)].Raw;\r
+      outStreamSpec->Init(buf.GetCapacity());\r
+      RINOK(WriteStream(outStream, buf, buf.GetCapacity()));\r
+      currentPackSize = currentUnpSize = buf.GetCapacity();\r
+    }\r
+    else if (index == _fileIndices.Size())\r
+    {\r
+      outStreamSpec->Init(_xml.Length());\r
+      RINOK(WriteStream(outStream, (const char *)_xml, _xml.Length()));\r
+      currentPackSize = currentUnpSize = _xml.Length();\r
+    }\r
+    else\r
+    #endif\r
+    {\r
+      const CFile &item = _files[_fileIndices[index]];\r
+      currentPackSize = item.GetPackSize();\r
+      currentUnpSize = item.GetUnpackSize();\r
+\r
+      UInt64 unpPos = 0;\r
+      UInt64 packPos = 0;\r
+      {\r
+        for (int j = 0; j < item.Blocks.Size(); j++)\r
+        {\r
+          lps->InSize = currentPackTotal + packPos;\r
+          lps->OutSize = currentUnpTotal + unpPos;\r
+          RINOK(lps->SetCur());\r
+\r
+          const CBlock &block = item.Blocks[j];\r
+\r
+          packPos += block.PackSize;\r
+          if (block.UnpPos != unpPos)\r
+          {\r
+            opRes = NExtract::NOperationResult::kDataError;\r
+            break;\r
+          }\r
+\r
+          RINOK(_inStream->Seek(item.StartPos + block.PackPos, STREAM_SEEK_SET, NULL));\r
+          streamSpec->Init(block.PackSize);\r
+          // UInt64 startSize = outStreamSpec->GetSize();\r
+          bool realMethod = true;\r
+          outStreamSpec->Init(block.UnpSize);\r
+          HRESULT res = S_OK;\r
+\r
+          switch(block.Type)\r
+          {\r
+            case METHOD_ZERO_0:\r
+            case METHOD_ZERO_2:\r
+              realMethod = false;\r
+              if (block.PackSize != 0)\r
+                opRes = NExtract::NOperationResult::kUnSupportedMethod;\r
+              break;\r
+\r
+            case METHOD_COPY:\r
+              if (block.UnpSize != block.PackSize)\r
+              {\r
+                opRes = NExtract::NOperationResult::kUnSupportedMethod;\r
+                break;\r
+              }\r
+              res = copyCoder->Code(inStream, outStream, NULL, NULL, progress);\r
+              break;\r
+            \r
+            case METHOD_ADC:\r
+            {\r
+              res = adcCoder->Code(inStream, outStream, &block.PackSize, &block.UnpSize, progress);\r
+              break;\r
+            }\r
+            \r
+            case METHOD_ZLIB:\r
+            {\r
+              res = zlibCoder->Code(inStream, outStream, NULL, NULL, progress);\r
+              break;\r
+            }\r
+\r
+            case METHOD_BZIP2:\r
+            {\r
+              res = bzip2Coder->Code(inStream, outStream, NULL, NULL, progress);\r
+              if (res == S_OK)\r
+                if (streamSpec->GetSize() != block.PackSize)\r
+                  opRes = NExtract::NOperationResult::kDataError;\r
+              break;\r
+            }\r
+            \r
+            default:\r
+              opRes = NExtract::NOperationResult::kUnSupportedMethod;\r
+              break;\r
+          }\r
+          if (res != S_OK)\r
+          {\r
+            if (res != S_FALSE)\r
+              return res;\r
+            if (opRes == NExtract::NOperationResult::kOK)\r
+              opRes = NExtract::NOperationResult::kDataError;\r
+          }\r
+          unpPos += block.UnpSize;\r
+          if (!outStreamSpec->IsFinishedOK())\r
+          {\r
+            if (realMethod && opRes == NExtract::NOperationResult::kOK)\r
+              opRes = NExtract::NOperationResult::kDataError;\r
+\r
+            while (outStreamSpec->GetRem() != 0)\r
+            {\r
+              UInt64 rem = outStreamSpec->GetRem();\r
+              UInt32 size = (UInt32)MyMin(rem, (UInt64)kZeroBufSize);\r
+              RINOK(WriteStream(outStream, zeroBuf, size));\r
+            }\r
+          }\r
+        }\r
+      }\r
+    }\r
+    outStream.Release();\r
+    RINOK(extractCallback->SetOperationResult(opRes));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"Dmg", L"dmg", 0, 0xE4, { 0 }, 0, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Dmg)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/ElfHandler.cpp b/CPP/7zip/Archive/ElfHandler.cpp
new file mode 100755 (executable)
index 0000000..171f049
--- /dev/null
@@ -0,0 +1,534 @@
+// ElfHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/Buffer.h"\r
+#include "Common/ComTry.h"\r
+#include "Common/IntToString.h"\r
+\r
+#include "Windows/PropVariantUtils.h"\r
+\r
+#include "../Common/LimitedStreams.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/CopyCoder.h"\r
+\r
+static UInt16 Get16(const Byte *p, int be) { if (be) return GetBe16(p); return GetUi16(p); }\r
+static UInt32 Get32(const Byte *p, int be) { if (be) return GetBe32(p); return GetUi32(p); }\r
+static UInt64 Get64(const Byte *p, int be) { if (be) return GetBe64(p); return GetUi64(p); }\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace NElf {\r
+\r
+#define ELF_CLASS_32 1\r
+#define ELF_CLASS_64 2\r
+\r
+#define ELF_DATA_2LSB 1\r
+#define ELF_DATA_2MSB 2\r
+\r
+#define NUM_SCAN_SECTIONS_MAX (1 << 6)\r
+\r
+struct CHeader\r
+{\r
+  bool Mode64;\r
+  bool Be;\r
+  Byte Os;\r
+  Byte AbiVer;\r
+\r
+  UInt16 Type;\r
+  UInt16 Machine;\r
+  // UInt32 Version;\r
+\r
+  // UInt64 EntryVa;\r
+  UInt64 ProgOffset;\r
+  UInt64 SectOffset;\r
+  UInt32 Flags;\r
+  UInt16 ElfHeaderSize;\r
+  UInt16 SegmentEntrySize;\r
+  UInt16 NumSegments;\r
+  UInt16 SectEntrySize;\r
+  UInt16 NumSections;\r
+  // UInt16 SectNameStringTableIndex;\r
+\r
+  bool Parse(const Byte *buf);\r
+\r
+  bool CheckSegmentEntrySize() const\r
+  {\r
+    return (Mode64 && SegmentEntrySize == 0x38) || (!Mode64 && SegmentEntrySize == 0x20);\r
+  };\r
+\r
+  UInt64 GetHeadersSize() const\r
+    { return ElfHeaderSize +\r
+      (UInt64)SegmentEntrySize * NumSegments +\r
+      (UInt64)SectEntrySize * NumSections; }\r
+    \r
+};\r
+\r
+bool CHeader::Parse(const Byte *p)\r
+{\r
+  switch(p[4])\r
+  {\r
+    case ELF_CLASS_32: Mode64 = false; break;\r
+    case ELF_CLASS_64: Mode64 = true; break;\r
+    default: return false;\r
+  }\r
+  bool be;\r
+  switch(p[5])\r
+  {\r
+    case ELF_DATA_2LSB: be = false; break;\r
+    case ELF_DATA_2MSB: be = true; break;\r
+    default: return false;\r
+  }\r
+  Be = be;\r
+  if (p[6] != 1) // Version\r
+    return false;\r
+  Os = p[7];\r
+  AbiVer = p[8];\r
+  for (int i = 9; i < 16; i++)\r
+    if (p[i] != 0)\r
+      return false;\r
+\r
+  Type = Get16(p + 0x10, be);\r
+  Machine = Get16(p + 0x12, be);\r
+  if (Get32(p + 0x14, be) != 1) // Version\r
+    return false;\r
+\r
+  if (Mode64)\r
+  {\r
+    // EntryVa = Get64(p + 0x18, be);\r
+    ProgOffset = Get64(p + 0x20, be);\r
+    SectOffset = Get64(p + 0x28, be);\r
+    p += 0x30;\r
+  }\r
+  else\r
+  {\r
+    // EntryVa = Get32(p + 0x18, be);\r
+    ProgOffset = Get32(p + 0x1C, be);\r
+    SectOffset = Get32(p + 0x20, be);\r
+    p += 0x24;\r
+  }\r
+\r
+  Flags = Get32(p + 0, be);\r
+  ElfHeaderSize = Get16(p + 4, be);\r
+  SegmentEntrySize = Get16(p + 6, be);\r
+  NumSegments = Get16(p + 8, be);\r
+  SectEntrySize = Get16(p + 10, be);\r
+  NumSections = Get16(p + 12, be);\r
+  // SectNameStringTableIndex = Get16(p + 14, be);\r
+  return CheckSegmentEntrySize();\r
+}\r
+\r
+struct CSegment\r
+{\r
+  UInt32 Type;\r
+  UInt32 Flags;\r
+  UInt64 Offset;\r
+  UInt64 Va;\r
+  // UInt64 Pa;\r
+  UInt64 PSize;\r
+  UInt64 VSize;\r
+  // UInt64 Align;\r
+\r
+  void UpdateTotalSize(UInt64 &totalSize)\r
+  {\r
+    UInt64 t = Offset + PSize;\r
+    if (t > totalSize)\r
+      totalSize = t;\r
+  }\r
+  void Parse(const Byte *p, bool mode64, bool be);\r
+};\r
+\r
+void CSegment::Parse(const Byte *p, bool mode64, bool be)\r
+{\r
+  Type = Get32(p, be);\r
+  if (mode64)\r
+  {\r
+    Flags = Get32(p + 4, be);\r
+    Offset = Get64(p + 8, be);\r
+    Va = Get64(p + 0x10, be);\r
+    // Pa = Get64(p + 0x18, be);\r
+    PSize = Get64(p + 0x20, be);\r
+    VSize = Get64(p + 0x28, be);\r
+    // Align = Get64(p + 0x30, be);\r
+  }\r
+  else\r
+  {\r
+    Offset = Get32(p + 4, be);\r
+    Va = Get32(p + 8, be);\r
+    // Pa = Get32(p + 12, be);\r
+    PSize = Get32(p + 16, be);\r
+    VSize = Get32(p + 20, be);\r
+    Flags = Get32(p + 24, be);\r
+    // Align = Get32(p + 28, be);\r
+  }\r
+}\r
+\r
+static const CUInt32PCharPair g_MachinePairs[] =\r
+{\r
+  { 0, "None" },\r
+  { 1, "AT&T WE 32100" },\r
+  { 2, "SPARC" },\r
+  { 3, "Intel 386" },\r
+  { 4, "Motorola 68000" },\r
+  { 5, "Motorola 88000" },\r
+  { 6, "Intel 486" },\r
+  { 7, "Intel i860" },\r
+  { 8, "MIPS" },\r
+  { 9, "IBM S/370" },\r
+  { 10, "MIPS RS3000 LE" },\r
+  { 11, "RS6000" },\r
+\r
+  { 15, "PA-RISC" },\r
+  { 16, "nCUBE" },\r
+  { 17, "Fujitsu VPP500" },\r
+  { 18, "SPARC 32+" },\r
+  { 19, "Intel i960" },\r
+  { 20, "PowerPC" },\r
+  { 21, "PowerPC 64-bit" },\r
+  { 22, "IBM S/390" },\r
+\r
+  { 36, "NEX v800" },\r
+  { 37, "Fujitsu FR20" },\r
+  { 38, "TRW RH-32" },\r
+  { 39, "Motorola RCE" },\r
+  { 40, "ARM" },\r
+  { 41, "Alpha" },\r
+  { 42, "Hitachi SH" },\r
+  { 43, "SPARC-V9" },\r
+  { 44, "Siemens Tricore" },\r
+  { 45, "ARC" },\r
+  { 46, "H8/300" },\r
+  { 47, "H8/300H" },\r
+  { 48, "H8S" },\r
+  { 49, "H8/500" },\r
+  { 50, "IA-64" },\r
+  { 51, "Stanford MIPS-X" },\r
+  { 52, "Motorola ColdFire" },\r
+  { 53, "M68HC12" },\r
+  { 54, "Fujitsu MMA" },\r
+  { 55, "Siemens PCP" },\r
+  { 56, "Sony nCPU" },\r
+  { 57, "Denso NDR1" },\r
+  { 58, "Motorola StarCore" },\r
+  { 59, "Toyota ME16" },\r
+  { 60, "ST100" },\r
+  { 61, "Advanced Logic TinyJ" },\r
+  { 62, "AMD64" },\r
+  { 63, "Sony DSP" },\r
+\r
+  { 66, "Siemens FX66" },\r
+  { 67, "ST9+" },\r
+  { 68, "ST7" },\r
+  { 69, "MC68HC16" },\r
+  { 70, "MC68HC11" },\r
+  { 71, "MC68HC08" },\r
+  { 72, "MC68HC05" },\r
+  { 73, "Silicon Graphics SVx" },\r
+  { 74, "ST19" },\r
+  { 75, "Digital VAX" },\r
+  { 76, "Axis CRIS" },\r
+  { 77, "Infineon JAVELIN" },\r
+  { 78, "Element 14 FirePath" },\r
+  { 79, "LSI ZSP" },\r
+  { 80, "MMIX" },\r
+  { 81, "HUANY" },\r
+  { 82, "SiTera Prism" },\r
+  { 83, "Atmel AVR" },\r
+  { 84, "Fujitsu FR30" },\r
+  { 85, "Mitsubishi D10V" },\r
+  { 86, "Mitsubishi D30V" },\r
+  { 87, "NEC v850" },\r
+  { 88, "Mitsubishi M32R" },\r
+  { 89, "Matsushita MN10300" },\r
+  { 90, "Matsushita MN10200" },\r
+  { 91, "picoJava" },\r
+  { 92, "OpenRISC" },\r
+  { 93, "ARC Tangent-A5" },\r
+  { 94, "Tensilica Xtensa" },\r
+  { 0x9026, "Alpha" }\r
+};\r
+\r
+static const CUInt32PCharPair g_AbiOS[] =\r
+{\r
+  { 0, "None" },\r
+  { 1, "HP-UX" },\r
+  { 2, "NetBSD" },\r
+  { 3, "Linux" },\r
+\r
+  { 6, "Solaris" },\r
+  { 7, "AIX" },\r
+  { 8, "IRIX" },\r
+  { 9, "FreeBSD" },\r
+  { 10, "TRU64" },\r
+  { 11, "Novell Modesto" },\r
+  { 12, "OpenBSD" },\r
+  { 13, "OpenVMS" },\r
+  { 14, "HP NSK" },\r
+  { 15, "AROS" },\r
+  { 97, "ARM" },\r
+  { 255, "Standalone" }\r
+};\r
+\r
+static const CUInt32PCharPair g_SegmentFlags[] =\r
+{\r
+  { 0, "Execute" },\r
+  { 1, "Write" },\r
+  { 2, "Read" }\r
+};\r
+\r
+static const char *g_Types[] =\r
+{\r
+  "None",\r
+  "Relocatable file",\r
+  "Executable file",\r
+  "Shared object file",\r
+  "Core file"\r
+};\r
+\r
+static const char *g_SegnmentTypes[] =\r
+{\r
+  "Unused",\r
+  "Loadable segment",\r
+  "Dynamic linking tables",\r
+  "Program interpreter path name",\r
+  "Note section",\r
+  "SHLIB",\r
+  "Program header table",\r
+  "TLS"\r
+};\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<IInStream> _inStream;\r
+  CObjectVector<CSegment> _sections;\r
+  UInt32 _peOffset;\r
+  CHeader _header;\r
+  UInt64 _totalSize;\r
+  HRESULT Open2(IInStream *stream);\r
+  bool Parse(const Byte *buf, UInt32 size);\r
+public:\r
+  MY_UNKNOWN_IMP1(IInArchive)\r
+  INTERFACE_IInArchive(;)\r
+};\r
+\r
+#define ELF_PT_PHDR 6\r
+\r
+bool CHandler::Parse(const Byte *buf, UInt32 size)\r
+{\r
+  if (size < 64)\r
+    return false;\r
+  if (!_header.Parse(buf))\r
+    return false;\r
+  if (_header.ProgOffset > size ||\r
+      _header.ProgOffset + (UInt64)_header.SegmentEntrySize * _header.NumSegments > size ||\r
+      _header.NumSegments > NUM_SCAN_SECTIONS_MAX)\r
+    return false;\r
+  const Byte *p = buf + _header.ProgOffset;\r
+  _totalSize = _header.ProgOffset;\r
+  \r
+  for (int i = 0; i < _header.NumSegments; i++, p += _header.SegmentEntrySize)\r
+  {\r
+    CSegment sect;\r
+    sect.Parse(p, _header.Mode64, _header.Be);\r
+    sect.UpdateTotalSize(_totalSize);\r
+    if (sect.Type != ELF_PT_PHDR)\r
+      _sections.Add(sect);\r
+  }\r
+  UInt64 total2 = _header.SectOffset + (UInt64)_header.SectEntrySize * _header.NumSections;\r
+  if (total2 > _totalSize)\r
+    _totalSize = total2;\r
+  return true;\r
+}\r
+\r
+STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidCpu, VT_BSTR},\r
+  { NULL, kpidBit64, VT_BOOL},\r
+  { NULL, kpidBigEndian, VT_BOOL},\r
+  { NULL, kpidHostOS, VT_BSTR},\r
+  { NULL, kpidCharacts, VT_BSTR},\r
+  { NULL, kpidPhySize, VT_UI8},\r
+  { NULL, kpidHeadersSize, VT_UI8}\r
+ };\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidType, VT_BSTR},\r
+  { NULL, kpidCharacts, VT_BSTR},\r
+  { NULL, kpidOffset, VT_UI8},\r
+  { NULL, kpidVa, VT_UI8}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidPhySize:  prop = _totalSize; break;\r
+    case kpidHeadersSize:  prop = _header.GetHeadersSize(); break;\r
+    case kpidBit64:  if (_header.Mode64) prop = _header.Mode64; break;\r
+    case kpidBigEndian:  if (_header.Be) prop = _header.Be; break;\r
+    case kpidCpu:  PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop); break;\r
+    case kpidHostOS:  PAIR_TO_PROP(g_AbiOS, _header.Os, prop); break;\r
+    case kpidCharacts:  TYPE_TO_PROP(g_Types, _header.Type, prop); break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NCOM::CPropVariant prop;\r
+  const CSegment &item = _sections[index];\r
+  switch(propID)\r
+  {\r
+    case kpidPath:\r
+    {\r
+      wchar_t sz[32];\r
+      ConvertUInt64ToString(index, sz);\r
+      prop = sz;\r
+      break;\r
+    }\r
+    case kpidSize:  prop = (UInt64)item.VSize; break;\r
+    case kpidPackSize:  prop = (UInt64)item.PSize; break;\r
+    case kpidOffset:  prop = item.Offset; break;\r
+    case kpidVa:  prop = item.Va; break;\r
+    case kpidType:  TYPE_TO_PROP(g_SegnmentTypes, item.Type, prop); break;\r
+    case kpidCharacts:  FLAGS_TO_PROP(g_SegmentFlags, item.Flags, prop); break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+HRESULT CHandler::Open2(IInStream *stream)\r
+{\r
+  const UInt32 kBufSize = 1 << 18;\r
+  const UInt32 kSigSize = 4;\r
+\r
+  CByteBuffer buffer;\r
+  buffer.SetCapacity(kBufSize);\r
+  Byte *buf = buffer;\r
+\r
+  size_t processed = kSigSize;\r
+  RINOK(ReadStream_FALSE(stream, buf, processed));\r
+  if (buf[0] != 0x7F || buf[1] != 'E' || buf[2] != 'L' || buf[3] != 'F')\r
+    return S_FALSE;\r
+  processed = kBufSize - kSigSize;\r
+  RINOK(ReadStream(stream, buf + kSigSize, &processed));\r
+  processed += kSigSize;\r
+  if (!Parse(buf, (UInt32)processed))\r
+    return S_FALSE;\r
+  UInt64 fileSize;\r
+  RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize));\r
+  return (fileSize == _totalSize) ? S_OK : S_FALSE;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *inStream,\r
+    const UInt64 * /* maxCheckStartPosition */,\r
+    IArchiveOpenCallback * /* openArchiveCallback */)\r
+{\r
+  COM_TRY_BEGIN\r
+  Close();\r
+  RINOK(Open2(inStream));\r
+  _inStream = inStream;\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _inStream.Release();\r
+  _sections.Clear();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _sections.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _sections.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt64 totalSize = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+    totalSize += _sections[allFilesMode ? i : indices[i]].PSize;\r
+  extractCallback->SetTotal(totalSize);\r
+\r
+  UInt64 currentTotalSize = 0;\r
+  UInt64 currentItemSize;\r
+  \r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);\r
+  streamSpec->SetStream(_inStream);\r
+\r
+  for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)\r
+  {\r
+    lps->InSize = lps->OutSize = currentTotalSize;\r
+    RINOK(lps->SetCur());\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    UInt32 index = allFilesMode ? i : indices[i];\r
+    const CSegment &item = _sections[index];\r
+    currentItemSize = item.PSize;\r
+    \r
+    CMyComPtr<ISequentialOutStream> outStream;\r
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));\r
+    if (!testMode && !outStream)\r
+      continue;\r
+      \r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+    RINOK(_inStream->Seek(item.Offset, STREAM_SEEK_SET, NULL));\r
+    streamSpec->Init(currentItemSize);\r
+    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));\r
+    outStream.Release();\r
+    RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == currentItemSize ?\r
+        NExtract::NOperationResult::kOK:\r
+        NExtract::NOperationResult::kDataError));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"ELF", L"", 0, 0xDE, { 0 }, 0, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Elf)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/FatHandler.cpp b/CPP/7zip/Archive/FatHandler.cpp
new file mode 100755 (executable)
index 0000000..1886906
--- /dev/null
@@ -0,0 +1,996 @@
+// FatHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+// #include <stdio.h>\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/Buffer.h"\r
+#include "Common/ComTry.h"\r
+#include "Common/IntToString.h"\r
+#include "Common/MyCom.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../Common/LimitedStreams.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/CopyCoder.h"\r
+\r
+#include "Common/DummyOutStream.h"\r
+\r
+#define Get16(p) GetUi16(p)\r
+#define Get32(p) GetUi32(p)\r
+\r
+#define PRF(x) /* x */\r
+\r
+namespace NArchive {\r
+namespace NFat {\r
+\r
+static const UInt32 kFatItemUsedByDirMask = (UInt32)1 << 31;\r
+\r
+struct CHeader\r
+{\r
+  UInt32 NumSectors;\r
+  UInt16 NumReservedSectors;\r
+  Byte NumFats;\r
+  UInt32 NumFatSectors;\r
+  UInt32 RootDirSector;\r
+  UInt32 NumRootDirSectors;\r
+  UInt32 DataSector;\r
+\r
+  UInt32 FatSize;\r
+  UInt32 BadCluster;\r
+\r
+  Byte NumFatBits;\r
+  Byte SectorSizeLog;\r
+  Byte SectorsPerClusterLog;\r
+  Byte ClusterSizeLog;\r
+  \r
+  UInt16 SectorsPerTrack;\r
+  UInt16 NumHeads;\r
+  UInt32 NumHiddenSectors;\r
+\r
+  bool VolFieldsDefined;\r
+  \r
+  UInt32 VolId;\r
+  // Byte VolName[11];\r
+  // Byte FileSys[8];\r
+\r
+  // Byte OemName[5];\r
+  Byte MediaType;\r
+\r
+  // 32-bit FAT\r
+  UInt16 Flags;\r
+  UInt16 FsInfoSector;\r
+  UInt32 RootCluster;\r
+\r
+  bool IsFat32() const { return NumFatBits == 32; }\r
+  UInt64 GetPhySize() const { return (UInt64)NumSectors << SectorSizeLog; }\r
+  UInt32 SectorSize() const { return (UInt32)1 << SectorSizeLog; }\r
+  UInt32 ClusterSize() const { return (UInt32)1 << ClusterSizeLog; }\r
+  UInt32 ClusterToSector(UInt32 c) const { return DataSector + ((c - 2) << SectorsPerClusterLog); }\r
+  UInt32 IsEoc(UInt32 c) const { return c > BadCluster; }\r
+  UInt32 IsEocAndUnused(UInt32 c) const { return c > BadCluster && (c & kFatItemUsedByDirMask) == 0; }\r
+  UInt32 IsValidCluster(UInt32 c) const { return c >= 2 && c < FatSize; }\r
+  UInt32 SizeToSectors(UInt32 size) const { return (size + SectorSize() - 1) >> SectorSizeLog; }\r
+  UInt32 CalcFatSizeInSectors() const { return SizeToSectors((FatSize * (NumFatBits / 4) + 1) / 2); }\r
+\r
+  UInt32 GetFatSector() const\r
+  {\r
+    UInt32 index = (IsFat32() && (Flags & 0x80) != 0) ? (Flags & 0xF) : 0;\r
+    if (index > NumFats)\r
+      index = 0;\r
+    return NumReservedSectors + index * NumFatSectors;\r
+  }\r
+\r
+  UInt64 GetFilePackSize(UInt32 unpackSize) const\r
+  {\r
+    UInt64 mask = ClusterSize() - 1;\r
+    return (unpackSize + mask) & ~mask;\r
+  }\r
+\r
+  UInt32 GetNumClusters(UInt32 size) const\r
+    { return (UInt32)(((UInt64)size + ClusterSize() - 1) >> ClusterSizeLog); }\r
+\r
+  bool Parse(const Byte *p);\r
+};\r
+\r
+static int GetLog(UInt32 num)\r
+{\r
+  for (int i = 0; i < 31; i++)\r
+    if (((UInt32)1 << i) == num)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+bool CHeader::Parse(const Byte *p)\r
+{\r
+  if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA)\r
+    return false;\r
+\r
+  int codeOffset = 0;\r
+  switch (p[0])\r
+  {\r
+    case 0xE9: codeOffset = 3 + (Int16)Get16(p + 1); break;\r
+    case 0xEB: if (p[2] != 0x90) return false; codeOffset = 2 + (signed char)p[1]; break;\r
+    default: return false;\r
+  }\r
+  {\r
+    int s = GetLog(Get16(p + 11));\r
+    if (s < 9 || s > 12)\r
+      return false;\r
+    SectorSizeLog = (Byte)s;\r
+    s = GetLog(p[13]);\r
+    if (s < 0)\r
+      return false;\r
+    SectorsPerClusterLog = (Byte)s;\r
+    ClusterSizeLog = SectorSizeLog + SectorsPerClusterLog;\r
+  }\r
+\r
+  NumReservedSectors = Get16(p + 14);\r
+  if (NumReservedSectors == 0)\r
+    return false;\r
+\r
+  NumFats = p[16];\r
+  if (NumFats < 1 || NumFats > 4)\r
+    return false;\r
+\r
+  UInt16 numRootDirEntries = Get16(p + 17);\r
+  if (numRootDirEntries == 0)\r
+  {\r
+    if (codeOffset < 90)\r
+      return false;\r
+    NumFatBits = 32;\r
+    NumRootDirSectors = 0;\r
+  }\r
+  else\r
+  {\r
+    if (codeOffset < 62)\r
+      return false;\r
+    NumFatBits = 0;\r
+    UInt32 mask = (1 << (SectorSizeLog - 5)) - 1;\r
+    if ((numRootDirEntries & mask) != 0)\r
+      return false;\r
+    NumRootDirSectors = (numRootDirEntries + mask) >> (SectorSizeLog - 5);\r
+  }\r
+\r
+  NumSectors = Get16(p + 19);\r
+  if (NumSectors == 0)\r
+    NumSectors = Get32(p + 32);\r
+  else if (IsFat32())\r
+    return false;\r
+\r
+  MediaType = p[21];\r
+  NumFatSectors = Get16(p + 22);\r
+  SectorsPerTrack = Get16(p + 24);\r
+  NumHeads = Get16(p + 26);\r
+  NumHiddenSectors = Get32(p + 28);\r
+\r
+  // memcpy(OemName, p + 3, 5);\r
+\r
+  p += 36;\r
+  if (IsFat32())\r
+  {\r
+    if (NumFatSectors != 0)\r
+      return false;\r
+    NumFatSectors = Get32(p);\r
+    if (NumFatSectors >= (1 << 24))\r
+      return false;\r
+\r
+    Flags = Get16(p + 4);\r
+    if (Get16(p + 6) != 0)\r
+      return false;\r
+    RootCluster = Get32(p + 8);\r
+    FsInfoSector = Get16(p + 12);\r
+    for (int i = 16; i < 28; i++)\r
+      if (p[i] != 0)\r
+        return false;\r
+    p += 28;\r
+  }\r
+\r
+  // DriveNumber = p[0];\r
+  VolFieldsDefined = (p[2] == 0x29); // ExtendedBootSig\r
+  VolId = Get32(p + 3);\r
+  // memcpy(VolName, p + 7, 11);\r
+  // memcpy(FileSys, p + 18, 8);\r
+\r
+  if (NumFatSectors == 0)\r
+    return false;\r
+  RootDirSector = NumReservedSectors + NumFatSectors * NumFats;\r
+  DataSector = RootDirSector + NumRootDirSectors;\r
+  if (NumSectors < DataSector)\r
+    return false;\r
+  UInt32 numDataSectors = NumSectors - DataSector;\r
+  UInt32 numClusters = numDataSectors >> SectorsPerClusterLog;\r
+  \r
+  BadCluster = 0x0FFFFFF7;\r
+  if (numClusters < 0xFFF5)\r
+  {\r
+    if (NumFatBits == 32)\r
+      return false;\r
+    NumFatBits = (numClusters < 0xFF5) ? 12: 16;\r
+    BadCluster &= ((1 << NumFatBits) - 1);\r
+  }\r
+  else if (NumFatBits != 32)\r
+    return false;\r
+\r
+  FatSize = numClusters + 2;\r
+  if (FatSize > BadCluster || CalcFatSizeInSectors() > NumFatSectors)\r
+    return false;\r
+  return true;\r
+}\r
+\r
+struct CItem\r
+{\r
+  UString UName;\r
+  char DosName[11];\r
+  Byte CTime2;\r
+  UInt32 CTime;\r
+  UInt32 MTime;\r
+  UInt16 ADate;\r
+  Byte Attrib;\r
+  Byte Flags;\r
+  UInt32 Size;\r
+  UInt32 Cluster;\r
+  Int32 Parent;\r
+\r
+  // NT uses Flags to store Low Case status\r
+  bool NameIsLow() const { return (Flags & 0x8) != 0; }\r
+  bool ExtIsLow() const { return (Flags & 0x10) != 0; }\r
+  bool IsDir() const { return (Attrib & 0x10) != 0; }\r
+  UString GetShortName() const;\r
+  UString GetName() const;\r
+  UString GetVolName() const;\r
+};\r
+\r
+static int CopyAndTrim(char *dest, const char *src, int size, bool toLower)\r
+{\r
+  int i;\r
+  memcpy(dest, src, size);\r
+  if (toLower)\r
+    for (i = 0; i < size; i++)\r
+    {\r
+      char c = dest[i];\r
+      if (c >= 'A' && c <= 'Z')\r
+        dest[i] = c + 0x20;\r
+    }\r
+  for (i = size - 1; i >= 0 && dest[i] == ' '; i--);\r
+  return i + 1;\r
+}\r
+\r
+static UString FatStringToUnicode(const char *s)\r
+{\r
+  return MultiByteToUnicodeString(s, CP_OEMCP);\r
+}\r
+\r
+UString CItem::GetShortName() const\r
+{\r
+  char s[16];\r
+  int i = CopyAndTrim(s, DosName, 8, NameIsLow());\r
+  s[i++] = '.';\r
+  int j = CopyAndTrim(s + i, DosName + 8, 3, ExtIsLow());\r
+  if (j == 0)\r
+    j--;\r
+  s[i + j] = 0;\r
+  return FatStringToUnicode(s);\r
+}\r
+\r
+UString CItem::GetName() const\r
+{\r
+  if (!UName.IsEmpty())\r
+    return UName;\r
+  return GetShortName();\r
+}\r
+\r
+UString CItem::GetVolName() const\r
+{\r
+  if (!UName.IsEmpty())\r
+    return UName;\r
+  char s[12];\r
+  int i = CopyAndTrim(s, DosName, 11, false);\r
+  s[i] = 0;\r
+  return FatStringToUnicode(s);\r
+}\r
+\r
+struct CDatabase\r
+{\r
+  CHeader Header;\r
+  CObjectVector<CItem> Items;\r
+  UInt32 *Fat;\r
+  CMyComPtr<IInStream> InStream;\r
+  IArchiveOpenCallback *OpenCallback;\r
+\r
+  UInt32 NumFreeClusters;\r
+  bool VolItemDefined;\r
+  CItem VolItem;\r
+  UInt32 NumDirClusters;\r
+  CByteBuffer ByteBuf;\r
+  UInt64 NumCurUsedBytes;\r
+\r
+  CDatabase(): Fat(0) {}\r
+  ~CDatabase() { ClearAndClose(); }\r
+\r
+  void Clear();\r
+  void ClearAndClose();\r
+  HRESULT OpenProgressFat(bool changeTotal = true);\r
+  HRESULT OpenProgress();\r
+\r
+  UString GetItemPath(Int32 index) const;\r
+  HRESULT Open();\r
+  HRESULT ReadDir(Int32 parent, UInt32 cluster, int level);\r
+\r
+  UInt64 GetHeadersSize() const\r
+  {\r
+    return (UInt64)(Header.DataSector + (NumDirClusters << Header.SectorsPerClusterLog)) << Header.SectorSizeLog;\r
+  }\r
+  HRESULT SeekToSector(UInt32 sector);\r
+  HRESULT SeekToCluster(UInt32 cluster) { return SeekToSector(Header.ClusterToSector(cluster)); }\r
+};\r
+\r
+HRESULT CDatabase::SeekToSector(UInt32 sector)\r
+{\r
+  return InStream->Seek((UInt64)sector << Header.SectorSizeLog, STREAM_SEEK_SET, NULL);\r
+}\r
+\r
+void CDatabase::Clear()\r
+{\r
+  VolItemDefined = false;\r
+  NumDirClusters = 0;\r
+  NumCurUsedBytes = 0;\r
+\r
+  Items.Clear();\r
+  delete []Fat;\r
+  Fat = 0;\r
+}\r
+\r
+void CDatabase::ClearAndClose()\r
+{\r
+  Clear();\r
+  InStream.Release();\r
+}\r
+\r
+HRESULT CDatabase::OpenProgressFat(bool changeTotal)\r
+{\r
+  if (!OpenCallback)\r
+    return S_OK;\r
+  if (changeTotal)\r
+  {\r
+    UInt64 numTotalBytes = (Header.CalcFatSizeInSectors() << Header.SectorSizeLog) +\r
+        ((UInt64)(Header.FatSize - NumFreeClusters) << Header.ClusterSizeLog);\r
+    RINOK(OpenCallback->SetTotal(NULL, &numTotalBytes));\r
+  }\r
+  return OpenCallback->SetCompleted(NULL, &NumCurUsedBytes);\r
+}\r
+\r
+HRESULT CDatabase::OpenProgress()\r
+{\r
+  if (!OpenCallback)\r
+    return S_OK;\r
+  UInt64 numItems = Items.Size();\r
+  return OpenCallback->SetCompleted(&numItems, &NumCurUsedBytes);\r
+}\r
+\r
+UString CDatabase::GetItemPath(Int32 index) const\r
+{\r
+  const CItem *item = &Items[index];\r
+  UString name = item->GetName();\r
+  for (;;)\r
+  {\r
+    index = item->Parent;\r
+    if (index < 0)\r
+      return name;\r
+    item = &Items[index];\r
+    name = item->GetName() + WCHAR_PATH_SEPARATOR + name;\r
+  }\r
+}\r
+\r
+static wchar_t *AddSubStringToName(wchar_t *dest, const Byte *p, int numChars)\r
+{\r
+  for (int i = 0; i < numChars; i++)\r
+  {\r
+    wchar_t c = Get16(p + i * 2);\r
+    if (c != 0 && c != 0xFFFF)\r
+      *dest++ = c;\r
+  }\r
+  *dest = 0;\r
+  return dest;\r
+}\r
+\r
+HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)\r
+{\r
+  int startIndex = Items.Size();\r
+  if (startIndex >= (1 << 30) || level > 256)\r
+    return S_FALSE;\r
+\r
+  UInt32 sectorIndex = 0;\r
+  UInt32 blockSize = Header.ClusterSize();\r
+  bool clusterMode = (Header.IsFat32() || parent >= 0);\r
+  if (!clusterMode)\r
+  {\r
+    blockSize = Header.SectorSize();\r
+    RINOK(SeekToSector(Header.RootDirSector));\r
+  }\r
+\r
+  ByteBuf.SetCapacity(blockSize);\r
+  UString curName;\r
+  int checkSum = -1;\r
+  int numLongRecords = -1;\r
+  for (UInt32 pos = blockSize;; pos += 32)\r
+  {\r
+    if (pos == blockSize)\r
+    {\r
+      pos = 0;\r
+\r
+      if ((NumDirClusters & 0xFF) == 0)\r
+      {\r
+        RINOK(OpenProgress());\r
+      }\r
+\r
+      if (clusterMode)\r
+      {\r
+        if (Header.IsEoc(cluster))\r
+          break;\r
+        if (!Header.IsValidCluster(cluster))\r
+          return S_FALSE;\r
+        PRF(printf("\nCluster = %4X", cluster));\r
+        RINOK(SeekToCluster(cluster));\r
+        UInt32 newCluster = Fat[cluster];\r
+        if ((newCluster & kFatItemUsedByDirMask) != 0)\r
+          return S_FALSE;\r
+        Fat[cluster] |= kFatItemUsedByDirMask;\r
+        cluster = newCluster;\r
+        NumDirClusters++;\r
+        NumCurUsedBytes += Header.ClusterSize();\r
+      }\r
+      else if (sectorIndex++ >= Header.NumRootDirSectors)\r
+        break;\r
+      \r
+      RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize));\r
+    }\r
+    const Byte *p = ByteBuf + pos;\r
+    if (p[0] == 0)\r
+    {\r
+      /*\r
+      // FreeDOS formats FAT partition with cluster chain longer than required.\r
+      if (clusterMode && !Header.IsEoc(cluster))\r
+        return S_FALSE;\r
+      */\r
+      break;\r
+    }\r
+    if (p[0] == 0xE5)\r
+    {\r
+      if (numLongRecords > 0)\r
+        return S_FALSE;\r
+      continue;\r
+    }\r
+    \r
+    Byte attrib = p[11];\r
+    if ((attrib & 0x3F) == 0xF)\r
+    {\r
+      if (p[0] > 0x7F || Get16(p + 26) != 0)\r
+        return S_FALSE;\r
+      int longIndex = p[0] & 0x3F;\r
+      if (longIndex == 0)\r
+        return S_FALSE;\r
+      bool isLast = (p[0] & 0x40) != 0;\r
+      if (numLongRecords < 0)\r
+      {\r
+        if (!isLast)\r
+          return S_FALSE;\r
+        numLongRecords = longIndex;\r
+      }\r
+      else if (isLast || numLongRecords != longIndex)\r
+        return S_FALSE;\r
+\r
+      numLongRecords--;\r
+      \r
+      if (p[12] == 0)\r
+      {\r
+        wchar_t nameBuf[14];\r
+        wchar_t *dest;\r
+        \r
+        dest = AddSubStringToName(nameBuf, p + 1, 5);\r
+        dest = AddSubStringToName(dest, p + 14, 6);\r
+        AddSubStringToName(dest, p + 28, 2);\r
+        curName = nameBuf + curName;\r
+        if (isLast)\r
+          checkSum = p[13];\r
+        if (checkSum != p[13])\r
+          return S_FALSE;\r
+      }\r
+    }\r
+    else\r
+    {\r
+      if (numLongRecords > 0)\r
+        return S_FALSE;\r
+      CItem item;\r
+      memcpy(item.DosName, p, 11);\r
+\r
+      if (checkSum >= 0)\r
+      {\r
+        Byte sum = 0;\r
+        for (int i = 0; i < 11; i++)\r
+          sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + (Byte)item.DosName[i];\r
+        if (sum == checkSum)\r
+          item.UName = curName;\r
+      }\r
+\r
+      if (item.DosName[0] == 5)\r
+        item.DosName[0] = (char)(Byte)0xE5;\r
+      item.Attrib = attrib;\r
+      item.Flags = p[12];\r
+      item.Size = Get32(p + 28);\r
+      item.Cluster = Get16(p + 26);\r
+      if (Header.NumFatBits > 16)\r
+        item.Cluster |= ((UInt32)Get16(p + 20) << 16);\r
+      else\r
+      {\r
+        // OS/2 and WinNT probably can store EA (extended atributes) in that field.\r
+      }\r
+\r
+      item.CTime = Get32(p + 14);\r
+      item.CTime2 = p[13];\r
+      item.ADate = Get16(p + 18);\r
+      item.MTime = Get32(p + 22);\r
+      item.Parent = parent;\r
+\r
+      if (attrib == 8)\r
+      {\r
+        VolItem = item;\r
+        VolItemDefined = true;\r
+      }\r
+      else\r
+        if (memcmp(item.DosName, ".          ", 11) != 0 &&\r
+            memcmp(item.DosName, "..         ", 11) != 0)\r
+      {\r
+        if (!item.IsDir())\r
+          NumCurUsedBytes += Header.GetFilePackSize(item.Size);\r
+        Items.Add(item);\r
+        PRF(printf("\n%7d: %S", Items.Size(), GetItemPath(Items.Size() - 1)));\r
+      }\r
+      numLongRecords = -1;\r
+      curName.Empty();\r
+      checkSum = -1;\r
+    }\r
+  }\r
+\r
+  int finishIndex = Items.Size();\r
+  for (int i = startIndex; i < finishIndex; i++)\r
+  {\r
+    const CItem &item = Items[i];\r
+    if (item.IsDir())\r
+    {\r
+      PRF(printf("\n%S", GetItemPath(i)));\r
+      RINOK(CDatabase::ReadDir(i, item.Cluster, level + 1));\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CDatabase::Open()\r
+{\r
+  Clear();\r
+  bool numFreeClustersDefined = false;\r
+  {\r
+    static const UInt32 kHeaderSize = 512;\r
+    Byte buf[kHeaderSize];\r
+    RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize));\r
+    if (!Header.Parse(buf))\r
+      return S_FALSE;\r
+    UInt64 fileSize;\r
+    RINOK(InStream->Seek(0, STREAM_SEEK_END, &fileSize));\r
+\r
+    /* we comment that check to support truncated images */\r
+    /*\r
+    if (fileSize < Header.GetPhySize())\r
+      return S_FALSE;\r
+    */\r
+\r
+    if (Header.IsFat32())\r
+    {\r
+      SeekToSector(Header.FsInfoSector);\r
+      RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize));\r
+      if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA)\r
+        return S_FALSE;\r
+      if (Get32(buf) == 0x41615252 && Get32(buf + 484) == 0x61417272)\r
+      {\r
+        NumFreeClusters = Get32(buf + 488);\r
+        numFreeClustersDefined = (NumFreeClusters <= Header.FatSize);\r
+      }\r
+    }\r
+  }\r
+\r
+  // numFreeClustersDefined = false; // to recalculate NumFreeClusters\r
+  if (!numFreeClustersDefined)\r
+    NumFreeClusters = 0;\r
+\r
+  CByteBuffer byteBuf;\r
+  Fat = new UInt32[Header.FatSize];\r
+\r
+  RINOK(OpenProgressFat());\r
+  RINOK(SeekToSector(Header.GetFatSector()));\r
+  if (Header.NumFatBits == 32)\r
+  {\r
+    const UInt32 kBufSize = (1 << 15);\r
+    byteBuf.SetCapacity(kBufSize);\r
+    for (UInt32 i = 0; i < Header.FatSize;)\r
+    {\r
+      UInt32 size = Header.FatSize - i;\r
+      const UInt32 kBufSize32 = kBufSize / 4;\r
+      if (size > kBufSize32)\r
+        size = kBufSize32;\r
+      UInt32 readSize = Header.SizeToSectors(size * 4) << Header.SectorSizeLog;\r
+      RINOK(ReadStream_FALSE(InStream, byteBuf, readSize));\r
+      NumCurUsedBytes += readSize;\r
+\r
+      const UInt32 *src = (const UInt32 *)(const Byte *)byteBuf;\r
+      UInt32 *dest = Fat + i;\r
+      if (numFreeClustersDefined)\r
+        for (UInt32 j = 0; j < size; j++)\r
+          dest[j] = Get32(src + j) & 0x0FFFFFFF;\r
+      else\r
+      {\r
+        UInt32 numFreeClusters = 0;\r
+        for (UInt32 j = 0; j < size; j++)\r
+        {\r
+          UInt32 v = Get32(src + j) & 0x0FFFFFFF;\r
+          numFreeClusters += (UInt32)(v - 1) >> 31;\r
+          dest[j] = v;\r
+        }\r
+        NumFreeClusters += numFreeClusters;\r
+      }\r
+      i += size;\r
+      if ((i & 0xFFFFF) == 0)\r
+      {\r
+        RINOK(OpenProgressFat(!numFreeClustersDefined));\r
+      }\r
+    }\r
+  }\r
+  else\r
+  {\r
+    const UInt32 kBufSize = (UInt32)Header.CalcFatSizeInSectors() << Header.SectorSizeLog;\r
+    NumCurUsedBytes += kBufSize;\r
+    byteBuf.SetCapacity(kBufSize);\r
+    Byte *p = byteBuf;\r
+    RINOK(ReadStream_FALSE(InStream, p, kBufSize));\r
+    UInt32 fatSize = Header.FatSize;\r
+    UInt32 *fat = &Fat[0];\r
+    if (Header.NumFatBits == 16)\r
+      for (UInt32 j = 0; j < fatSize; j++)\r
+        fat[j] = Get16(p + j * 2);\r
+    else\r
+      for (UInt32 j = 0; j < fatSize; j++)\r
+        fat[j] = (Get16(p + j * 3 / 2) >> ((j & 1) << 2)) & 0xFFF;\r
+\r
+    if (!numFreeClustersDefined)\r
+    {\r
+      UInt32 numFreeClusters = 0;\r
+      for (UInt32 i = 0; i < fatSize; i++)\r
+        numFreeClusters += (UInt32)(fat[i] - 1) >> 31;\r
+      NumFreeClusters = numFreeClusters;\r
+    }\r
+  }\r
+\r
+  RINOK(OpenProgressFat());\r
+\r
+  if ((Fat[0] & 0xFF) != Header.MediaType)\r
+     return S_FALSE;\r
+\r
+  return ReadDir(-1, Header.RootCluster, 0);\r
+}\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IInArchiveGetStream,\r
+  public CMyUnknownImp,\r
+  CDatabase\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);\r
+};\r
+\r
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)\r
+{\r
+  COM_TRY_BEGIN\r
+  *stream = 0;\r
+  const CItem &item = Items[index];\r
+  CClusterInStream *streamSpec = new CClusterInStream;\r
+  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;\r
+  streamSpec->Stream = InStream;\r
+  streamSpec->StartOffset = Header.DataSector << Header.SectorSizeLog;\r
+  streamSpec->BlockSizeLog = Header.ClusterSizeLog;\r
+  streamSpec->Size = item.Size;\r
+\r
+  UInt32 numClusters = Header.GetNumClusters(item.Size);\r
+  streamSpec->Vector.Reserve(numClusters);\r
+  UInt32 cluster = item.Cluster;\r
+  UInt32 size = item.Size;\r
+\r
+  if (size == 0)\r
+  {\r
+    if (cluster != 0)\r
+      return S_FALSE;\r
+  }\r
+  else\r
+  {\r
+    UInt32 clusterSize = Header.ClusterSize();\r
+    for (;; size -= clusterSize)\r
+    {\r
+      if (!Header.IsValidCluster(cluster))\r
+        return S_FALSE;\r
+      streamSpec->Vector.Add(cluster - 2);\r
+      cluster = Fat[cluster];\r
+      if (size <= clusterSize)\r
+        break;\r
+    }\r
+    if (!Header.IsEocAndUnused(cluster))\r
+      return S_FALSE;\r
+  }\r
+  RINOK(streamSpec->InitAndSeek());\r
+  *stream = streamTemp.Detach();\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidIsDir, VT_BOOL},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidCTime, VT_FILETIME},\r
+  { NULL, kpidATime, VT_FILETIME},\r
+  { NULL, kpidAttrib, VT_UI8},\r
+  { NULL, kpidShortName, VT_BSTR}\r
+};\r
+\r
+enum\r
+{\r
+  kpidNumFats = kpidUserDefined\r
+  // kpidOemName,\r
+  // kpidVolName,\r
+  // kpidFileSysType\r
+};\r
+\r
+STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidFileSystem, VT_BSTR},\r
+  { NULL, kpidClusterSize, VT_UI4},\r
+  { NULL, kpidPhySize, VT_UI8},\r
+  { NULL, kpidFreeSpace, VT_UI8},\r
+  { NULL, kpidHeadersSize, VT_UI8},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidVolumeName, VT_BSTR},\r
+\r
+  { L"FATs", kpidNumFats, VT_UI4},\r
+  { NULL, kpidSectorSize, VT_UI4},\r
+  { NULL, kpidId, VT_UI4},\r
+  // { L"OEM Name", kpidOemName, VT_BSTR},\r
+  // { L"Volume Name", kpidVolName, VT_BSTR},\r
+  // { L"File System Type", kpidFileSysType, VT_BSTR}\r
+  // { NULL, kpidSectorsPerTrack, VT_UI4},\r
+  // { NULL, kpidNumHeads, VT_UI4},\r
+  // { NULL, kpidHiddenSectors, VT_UI4}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps_WITH_NAME\r
+\r
+static void FatTimeToProp(UInt32 dosTime, UInt32 ms10, NWindows::NCOM::CPropVariant &prop)\r
+{\r
+  FILETIME localFileTime, utc;\r
+  if (NWindows::NTime::DosTimeToFileTime(dosTime, localFileTime))\r
+    if (LocalFileTimeToFileTime(&localFileTime, &utc))\r
+    {\r
+      UInt64 t64 = (((UInt64)utc.dwHighDateTime) << 32) + utc.dwLowDateTime;\r
+      t64 += ms10 * 100000;\r
+      utc.dwLowDateTime = (DWORD)t64;\r
+      utc.dwHighDateTime = (DWORD)(t64 >> 32);\r
+      prop = utc;\r
+    }\r
+}\r
+\r
+/*\r
+static void StringToProp(const Byte *src, int size, NWindows::NCOM::CPropVariant &prop)\r
+{\r
+  char dest[32];\r
+  memcpy(dest, src, size);\r
+  dest[size] = 0;\r
+  prop = FatStringToUnicode(dest);\r
+}\r
+\r
+#define STRING_TO_PROP(s, p) StringToProp(s, sizeof(s), prop)\r
+*/\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidFileSystem:\r
+    {\r
+      wchar_t s[32] = { L'F', L'A', L'T' };\r
+      ConvertUInt32ToString(Header.NumFatBits, s + 3);\r
+      prop = s;\r
+      break;\r
+    }\r
+    case kpidClusterSize: prop = Header.ClusterSize(); break;\r
+    case kpidPhySize: prop = Header.GetPhySize(); break;\r
+    case kpidFreeSpace: prop = (UInt64)NumFreeClusters << Header.ClusterSizeLog; break;\r
+    case kpidHeadersSize: prop = GetHeadersSize(); break;\r
+    case kpidMTime: if (VolItemDefined) FatTimeToProp(VolItem.MTime, 0, prop); break;\r
+    case kpidVolumeName: if (VolItemDefined) prop = VolItem.GetVolName(); break;\r
+    case kpidNumFats: if (Header.NumFats != 2) prop = Header.NumFats; break;\r
+    case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break;\r
+    // case kpidSectorsPerTrack: prop = Header.SectorsPerTrack; break;\r
+    // case kpidNumHeads: prop = Header.NumHeads; break;\r
+    // case kpidOemName: STRING_TO_PROP(Header.OemName, prop); break;\r
+    case kpidId: if (Header.VolFieldsDefined) prop = Header.VolId; break;\r
+    // case kpidVolName: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.VolName, prop); break;\r
+    // case kpidFileSysType: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.FileSys, prop); break;\r
+    // case kpidHiddenSectors: prop = Header.NumHiddenSectors; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  const CItem &item = Items[index];\r
+  switch(propID)\r
+  {\r
+    case kpidPath: prop = GetItemPath(index); break;\r
+    case kpidShortName: prop = item.GetShortName(); break;\r
+    case kpidIsDir: prop = item.IsDir(); break;\r
+    case kpidMTime: FatTimeToProp(item.MTime, 0, prop); break;\r
+    case kpidCTime: FatTimeToProp(item.CTime, item.CTime2, prop); break;\r
+    case kpidATime: FatTimeToProp(((UInt32)item.ADate << 16), 0, prop); break;\r
+    case kpidAttrib: prop = (UInt32)item.Attrib; break;\r
+    case kpidSize: if (!item.IsDir()) prop = item.Size; break;\r
+    case kpidPackSize: if (!item.IsDir()) prop = Header.GetFilePackSize(item.Size); break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback)\r
+{\r
+  COM_TRY_BEGIN\r
+  {\r
+    OpenCallback = callback;\r
+    InStream = stream;\r
+    HRESULT res;\r
+    try\r
+    {\r
+      res = CDatabase::Open();\r
+      if (res == S_OK)\r
+        return S_OK;\r
+    }\r
+    catch(...)\r
+    {\r
+      Close();\r
+      throw;\r
+    }\r
+    Close();\r
+    return res;\r
+  }\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  ClearAndClose();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = Items.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt32 i;\r
+  UInt64 totalSize = 0;\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    const CItem &item = Items[allFilesMode ? i : indices[i]];\r
+    if (!item.IsDir())\r
+      totalSize += item.Size;\r
+  }\r
+  RINOK(extractCallback->SetTotal(totalSize));\r
+\r
+  UInt64 totalPackSize;\r
+  totalSize = totalPackSize = 0;\r
+  \r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  CDummyOutStream *outStreamSpec = new CDummyOutStream;\r
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\r
+\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    lps->InSize = totalPackSize;\r
+    lps->OutSize = totalSize;\r
+    RINOK(lps->SetCur());\r
+    CMyComPtr<ISequentialOutStream> realOutStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    Int32 index = allFilesMode ? i : indices[i];\r
+    const CItem &item = Items[index];\r
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+\r
+    if (item.IsDir())\r
+    {\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+      continue;\r
+    }\r
+\r
+    totalPackSize += Header.GetFilePackSize(item.Size);\r
+    totalSize += item.Size;\r
+\r
+    if (!testMode && !realOutStream)\r
+      continue;\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+\r
+    outStreamSpec->SetStream(realOutStream);\r
+    realOutStream.Release();\r
+    outStreamSpec->Init();\r
+\r
+    int res = NExtract::NOperationResult::kDataError;\r
+    CMyComPtr<ISequentialInStream> inStream;\r
+    HRESULT hres = GetStream(index, &inStream);\r
+    if (hres != S_FALSE)\r
+    {\r
+      RINOK(hres);\r
+      if (inStream)\r
+      {\r
+        RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));\r
+        if (copyCoderSpec->TotalSize == item.Size)\r
+          res = NExtract::NOperationResult::kOK;\r
+      }\r
+    }\r
+    outStreamSpec->ReleaseStream();\r
+    RINOK(extractCallback->SetOperationResult(res));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = Items.Size();\r
+  return S_OK;\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"FAT", L"fat img", 0, 0xDA, { 0x55, 0xAA }, 2, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Fat)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/FlvHandler.cpp b/CPP/7zip/Archive/FlvHandler.cpp
new file mode 100755 (executable)
index 0000000..f64b8bb
--- /dev/null
@@ -0,0 +1,544 @@
+// FlvHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/Buffer.h"\r
+#include "Common/ComTry.h"\r
+// #include "Common/Defs.h"\r
+#include "Common/MyString.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamObjects.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#define GetBe24(p) ( \\r
+    ((UInt32)((const Byte *)(p))[0] << 16) | \\r
+    ((UInt32)((const Byte *)(p))[1] <<  8) | \\r
+             ((const Byte *)(p))[2] )\r
+\r
+#define Get16(p) GetBe16(p)\r
+#define Get24(p) GetBe24(p)\r
+#define Get32(p) GetBe32(p)\r
+\r
+namespace NArchive {\r
+namespace NFlv {\r
+\r
+static const UInt32 kFileSizeMax = (UInt32)1 << 30;\r
+static const int kNumChunksMax = (UInt32)1 << 23;\r
+\r
+const UInt32 kTagHeaderSize = 11;\r
+\r
+static const Byte kFlag_Video = 1;\r
+static const Byte kFlag_Audio = 4;\r
+\r
+static const Byte kType_Audio = 8;\r
+static const Byte kType_Video = 9;\r
+static const Byte kType_Meta = 18;\r
+static const int kNumTypes = 19;\r
+\r
+struct CItem\r
+{\r
+  UInt32 Offset;\r
+  UInt32 Size;\r
+  // UInt32 Time;\r
+  Byte Type;\r
+};\r
+\r
+struct CItem2\r
+{\r
+  Byte Type;\r
+  Byte SubType;\r
+  Byte Props;\r
+  bool SameSubTypes;\r
+  int NumChunks;\r
+  size_t Size;\r
+\r
+  CReferenceBuf *BufSpec;\r
+  CMyComPtr<IUnknown> RefBuf;\r
+\r
+  bool IsAudio() const { return Type == kType_Audio; }\r
+};\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IInArchiveGetStream,\r
+  public CMyUnknownImp\r
+{\r
+  int _isRaw;\r
+  CMyComPtr<IInStream> _stream;\r
+  CObjectVector<CItem2> _items2;\r
+  // CByteBuffer _metadata;\r
+  HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);\r
+  AString GetComment();\r
+public:\r
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);\r
+};\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidNumBlocks, VT_UI4},\r
+  { NULL, kpidComment, VT_BSTR}\r
+};\r
+\r
+/*\r
+STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidComment, VT_BSTR}\r
+};\r
+*/\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps_NO\r
+\r
+static const char *g_AudioTypes[16] =\r
+{\r
+  "pcm",\r
+  "adpcm",\r
+  "mp3",\r
+  "pcm_le",\r
+  "nellymoser16",\r
+  "nellymoser8",\r
+  "nellymoser",\r
+  "g711a",\r
+  "g711m",\r
+  "audio9",\r
+  "aac",\r
+  "speex",\r
+  "audio12",\r
+  "audio13",\r
+  "mp3",\r
+  "audio15"\r
+};\r
+\r
+static const char *g_VideoTypes[16] =\r
+{\r
+  "video0",\r
+  "jpeg",\r
+  "h263",\r
+  "screen",\r
+  "vp6",\r
+  "vp6alpha",\r
+  "screen2",\r
+  "avc",\r
+  "video8",\r
+  "video9",\r
+  "video10",\r
+  "video11",\r
+  "video12",\r
+  "video13",\r
+  "video14",\r
+  "video15"\r
+};\r
+\r
+static const char *g_Rates[4] =\r
+{\r
+  "5.5 kHz",\r
+  "11 kHz",\r
+  "22 kHz",\r
+  "44 kHz"\r
+};\r
+\r
+static void MyStrCat(char *d, const char *s)\r
+{\r
+  MyStringCopy(d + MyStringLen(d), s);\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  NWindows::NCOM::CPropVariant prop;\r
+  const CItem2 &item = _items2[index];\r
+  switch(propID)\r
+  {\r
+    case kpidExtension:\r
+      prop = _isRaw ?\r
+        (item.IsAudio() ? g_AudioTypes[item.SubType] : g_VideoTypes[item.SubType]) :\r
+        (item.IsAudio() ? "audio.flv" : "video.flv");\r
+      break;\r
+    case kpidSize:\r
+    case kpidPackSize:\r
+      prop = (UInt64)item.Size;\r
+      break;\r
+    case kpidNumBlocks: prop = (UInt32)item.NumChunks; break;\r
+    case kpidComment:\r
+    {\r
+      char sz[64];\r
+      MyStringCopy(sz, (item.IsAudio() ? g_AudioTypes[item.SubType] : g_VideoTypes[item.SubType]) );\r
+      if (item.IsAudio())\r
+      {\r
+        MyStrCat(sz, " ");\r
+        MyStrCat(sz, g_Rates[(item.Props >> 2) & 3]);\r
+        MyStrCat(sz, (item.Props & 2) ? " 16-bit" : " 8-bit");\r
+        MyStrCat(sz, (item.Props & 1) ? " stereo" : " mono");\r
+      }\r
+      prop = sz;\r
+      break;\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+/*\r
+AString CHandler::GetComment()\r
+{\r
+  const Byte *p = _metadata;\r
+  size_t size = _metadata.GetCapacity();\r
+  AString res;\r
+  if (size > 0)\r
+  {\r
+    p++;\r
+    size--;\r
+    for (;;)\r
+    {\r
+      if (size < 2)\r
+        break;\r
+      int len = Get16(p);\r
+      p += 2;\r
+      size -= 2;\r
+      if (len == 0 || (size_t)len > size)\r
+        break;\r
+      {\r
+        AString temp;\r
+        char *sz = temp.GetBuffer(len);\r
+        memcpy(sz, p, len);\r
+        sz[len] = 0;\r
+        temp.ReleaseBuffer();\r
+        if (!res.IsEmpty())\r
+          res += '\n';\r
+        res += temp;\r
+      }\r
+      p += len;\r
+      size -= len;\r
+      if (size < 1)\r
+        break;\r
+      Byte type = *p++;\r
+      size--;\r
+      bool ok = false;\r
+      switch(type)\r
+      {\r
+        case 0:\r
+        {\r
+          if (size < 8)\r
+            break;\r
+          ok = true;\r
+          Byte reverse[8];\r
+          for (int i = 0; i < 8; i++)\r
+          {\r
+            bool little_endian = 1;\r
+            if (little_endian)\r
+              reverse[i] = p[7 - i];\r
+            else\r
+              reverse[i] = p[i];\r
+          }\r
+          double d = *(double *)reverse;\r
+          char temp[32];\r
+          sprintf(temp, " = %.3f", d);\r
+          res += temp;\r
+          p += 8;\r
+          size -= 8;\r
+          break;\r
+        }\r
+        case 8:\r
+        {\r
+          if (size < 4)\r
+            break;\r
+          ok = true;\r
+          // UInt32 numItems = Get32(p);\r
+          p += 4;\r
+          size -= 4;\r
+          break;\r
+        }\r
+      }\r
+      if (!ok)\r
+        break;\r
+    }\r
+  }\r
+  return res;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidComment: prop = GetComment(); break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+*/\r
+\r
+HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)\r
+{\r
+  CRecordVector<CItem> items;\r
+\r
+  const UInt32 kHeaderSize = 13;\r
+  Byte header[kHeaderSize];\r
+  RINOK(ReadStream_FALSE(stream, header, kHeaderSize));\r
+  if (header[0] != 'F' ||\r
+      header[1] != 'L' ||\r
+      header[2] != 'V' ||\r
+      header[3] != 1 ||\r
+      (header[4] & 0xFA) != 0)\r
+    return S_FALSE;\r
+  UInt32 offset = Get32(header + 5);\r
+  if (offset != 9 || Get32(header + 9) != 0)\r
+    return S_FALSE;\r
+  offset += 4;\r
\r
+  CByteBuffer inBuf;\r
+  size_t fileSize;\r
+  {\r
+    UInt64 fileSize64;\r
+    RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize64));\r
+    if (fileSize64 > kFileSizeMax)\r
+      return S_FALSE;\r
+\r
+    if (callback)\r
+      RINOK(callback->SetTotal(NULL, &fileSize64))\r
+\r
+    RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));\r
+    fileSize = (size_t)fileSize64;\r
+    inBuf.SetCapacity(fileSize);\r
+    for (size_t pos = 0; pos < fileSize;)\r
+    {\r
+      UInt64 offset64 = pos;\r
+      if (callback)\r
+        RINOK(callback->SetCompleted(NULL, &offset64))\r
+      size_t rem = MyMin(fileSize - pos, (size_t)(1 << 20));\r
+      RINOK(ReadStream_FALSE(stream, inBuf + pos, rem));\r
+      pos += rem;\r
+    }\r
+  }\r
+\r
+  int lasts[kNumTypes];\r
+  int i;\r
+  for (i = 0; i < kNumTypes; i++)\r
+    lasts[i] = -1;\r
+\r
+  while (offset < fileSize)\r
+  {\r
+    CItem item;\r
+    item.Offset = offset;\r
+    const Byte *buf = inBuf + offset;\r
+    offset += kTagHeaderSize;\r
+    if (offset > fileSize)\r
+      return S_FALSE;\r
+\r
+    item.Type = buf[0];\r
+    UInt32 size = Get24(buf + 1);\r
+    if (size < 1)\r
+      return S_FALSE;\r
+    // item.Time = Get24(buf + 4);\r
+    // item.Time |= (UInt32)buf[7] << 24;\r
+    if (Get24(buf + 8) != 0) // streamID\r
+      return S_FALSE;\r
+\r
+    UInt32 curSize = kTagHeaderSize + size + 4;\r
+    item.Size = curSize;\r
+    \r
+    offset += curSize - kTagHeaderSize;\r
+    if (offset > fileSize)\r
+      return S_FALSE;\r
+    \r
+    if (Get32(buf + kTagHeaderSize + size) != kTagHeaderSize + size)\r
+      return S_FALSE;\r
+\r
+    // printf("\noffset = %6X type = %2d time = %6d size = %6d", (UInt32)offset, item.Type, item.Time, item.Size);\r
+\r
+    if (item.Type == kType_Meta)\r
+    {\r
+      // _metadata = item.Buf;\r
+    }\r
+    else\r
+    {\r
+      if (item.Type != kType_Audio && item.Type != kType_Video)\r
+        return S_FALSE;\r
+      if (items.Size() >= kNumChunksMax)\r
+        return S_FALSE;\r
+      Byte firstByte = buf[kTagHeaderSize];\r
+      Byte subType, props;\r
+      if (item.Type == kType_Audio)\r
+      {\r
+        subType = firstByte >> 4;\r
+        props = firstByte & 0xF;\r
+      }\r
+      else\r
+      {\r
+        subType = firstByte & 0xF;\r
+        props = firstByte >> 4;\r
+      }\r
+      int last = lasts[item.Type];\r
+      if (last < 0)\r
+      {\r
+        CItem2 item2;\r
+        item2.RefBuf = item2.BufSpec = new CReferenceBuf;\r
+        item2.Size = curSize;\r
+        item2.Type = item.Type;\r
+        item2.SubType = subType;\r
+        item2.Props = props;\r
+        item2.NumChunks = 1;\r
+        item2.SameSubTypes = true;\r
+        lasts[item.Type] = _items2.Add(item2);\r
+      }\r
+      else\r
+      {\r
+        CItem2 &item2 = _items2[last];\r
+        if (subType != item2.SubType)\r
+          item2.SameSubTypes = false;\r
+        item2.Size += curSize;\r
+        item2.NumChunks++;\r
+      }\r
+      items.Add(item);\r
+    }\r
+  }\r
+\r
+  _isRaw = (_items2.Size() == 1);\r
+  for (i = 0; i < _items2.Size(); i++)\r
+  {\r
+    CItem2 &item2 = _items2[i];\r
+    CByteBuffer &itemBuf = item2.BufSpec->Buf;\r
+    if (_isRaw)\r
+    {\r
+      if (!item2.SameSubTypes)\r
+        return S_FALSE;\r
+      itemBuf.SetCapacity((size_t)item2.Size - (kTagHeaderSize + 4 + 1) * item2.NumChunks);\r
+      item2.Size = 0;\r
+    }\r
+    else\r
+    {\r
+      itemBuf.SetCapacity(kHeaderSize + (size_t)item2.Size);\r
+      memcpy(itemBuf, header, kHeaderSize);\r
+      itemBuf[4] = item2.IsAudio() ? kFlag_Audio : kFlag_Video;\r
+      item2.Size = kHeaderSize;\r
+    }\r
+  }\r
+\r
+  for (i = 0; i < items.Size(); i++)\r
+  {\r
+    const CItem &item = items[i];\r
+    CItem2 &item2 = _items2[lasts[item.Type]];\r
+    size_t size = item.Size;\r
+    const Byte *src = inBuf + item.Offset;\r
+    if (_isRaw)\r
+    {\r
+      src += kTagHeaderSize + 1;\r
+      size -= (kTagHeaderSize + 4 + 1);\r
+    }\r
+    memcpy(item2.BufSpec->Buf + item2.Size, src, size);\r
+    item2.Size += size;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback)\r
+{\r
+  COM_TRY_BEGIN\r
+  Close();\r
+  HRESULT res;\r
+  try\r
+  {\r
+    res = Open2(inStream, callback);\r
+    if (res == S_OK)\r
+      _stream = inStream;\r
+  }\r
+  catch(...) { res = S_FALSE; }\r
+  if (res != S_OK)\r
+  {\r
+    Close();\r
+    return S_FALSE;\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _stream.Release();\r
+  _items2.Clear();\r
+  // _metadata.SetCapacity(0);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _items2.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _items2.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt64 totalSize = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+    totalSize += _items2[allFilesMode ? i : indices[i]].Size;\r
+  extractCallback->SetTotal(totalSize);\r
+\r
+  totalSize = 0;\r
+  \r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    lps->InSize = lps->OutSize = totalSize;\r
+    RINOK(lps->SetCur());\r
+    CMyComPtr<ISequentialOutStream> outStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    UInt32 index = allFilesMode ? i : indices[i];\r
+    const CItem2 &item = _items2[index];\r
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));\r
+    totalSize += item.Size;\r
+    if (!testMode && !outStream)\r
+      continue;\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+    if (outStream)\r
+    {\r
+      RINOK(WriteStream(outStream, item.BufSpec->Buf, item.BufSpec->Buf.GetCapacity()));\r
+    }\r
+    RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)\r
+{\r
+  COM_TRY_BEGIN\r
+  *stream = 0;\r
+  CBufInStream *streamSpec = new CBufInStream;\r
+  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;\r
+  streamSpec->Init(_items2[index].BufSpec);\r
+  *stream = streamTemp.Detach();\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"FLV", L"flv", 0, 0xD6, { 'F', 'L', 'V' }, 3, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Flv)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/GzHandler.cpp b/CPP/7zip/Archive/GzHandler.cpp
new file mode 100755 (executable)
index 0000000..4c8c692
--- /dev/null
@@ -0,0 +1,698 @@
+// GzHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/CopyCoder.h"\r
+#include "../Compress/DeflateDecoder.h"\r
+#include "../Compress/DeflateEncoder.h"\r
+\r
+#include "Common/InStreamWithCRC.h"\r
+#include "Common/OutStreamWithCRC.h"\r
+\r
+#include "DeflateProps.h"\r
+\r
+#define Get32(p) GetUi32(p)\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace NGz {\r
+\r
+static const UInt16 kSignature = 0x8B1F;\r
+\r
+namespace NHeader\r
+{\r
+  namespace NFlags\r
+  {\r
+    const Byte kIsText = 1 << 0;\r
+    const Byte kCrc = 1 << 1;\r
+    const Byte kExtra = 1 << 2;\r
+    const Byte kName = 1 << 3;\r
+    const Byte kComment = 1 << 4;\r
+  }\r
+  \r
+  namespace NExtraFlags\r
+  {\r
+    const Byte kMaximum = 2;\r
+    const Byte kFastest = 4;\r
+  }\r
+  \r
+  namespace NCompressionMethod\r
+  {\r
+    const Byte kDeflate = 8;\r
+  }\r
+\r
+  namespace NHostOS\r
+  {\r
+    enum EEnum\r
+    {\r
+      kFAT = 0,\r
+      kAMIGA,\r
+      kVMS,\r
+      kUnix,\r
+      kVM_CMS,\r
+      kAtari,\r
+      kHPFS,\r
+      kMac,\r
+      kZ_System,\r
+      kCPM,\r
+      kTOPS20,\r
+      kNTFS,\r
+      kQDOS,\r
+      kAcorn,\r
+      kVFAT,\r
+      kMVS,\r
+      kBeOS,\r
+      kTandem,\r
+      \r
+      kUnknown = 255\r
+    };\r
+  }\r
+}\r
+\r
+static const char *kHostOSes[] =\r
+{\r
+  "FAT",\r
+  "AMIGA",\r
+  "VMS",\r
+  "Unix",\r
+  "VM/CMS",\r
+  "Atari",\r
+  "HPFS",\r
+  "Macintosh",\r
+  "Z-System",\r
+  "CP/M",\r
+  "TOPS-20",\r
+  "NTFS",\r
+  "SMS/QDOS",\r
+  "Acorn",\r
+  "VFAT",\r
+  "MVS",\r
+  "BeOS",\r
+  "Tandem",\r
+  "OS/400",\r
+  "OS/X"\r
+};\r
+\r
+static const char *kUnknownOS = "Unknown";\r
+\r
+class CItem\r
+{\r
+  bool TestFlag(Byte flag) const { return (Flags & flag) != 0; }\r
+public:\r
+  Byte Method;\r
+  Byte Flags;\r
+  Byte ExtraFlags;\r
+  Byte HostOS;\r
+  UInt32 Time;\r
+  UInt32 Crc;\r
+  UInt32 Size32;\r
+\r
+  AString Name;\r
+  AString Comment;\r
+  // CByteBuffer Extra;\r
+\r
+  // bool IsText() const { return TestFlag(NHeader::NFlags::kIsText); }\r
+  bool HeaderCrcIsPresent() const { return TestFlag(NHeader::NFlags::kCrc); }\r
+  bool ExtraFieldIsPresent() const { return TestFlag(NHeader::NFlags::kExtra); }\r
+  bool NameIsPresent() const { return TestFlag(NHeader::NFlags::kName); }\r
+  bool CommentIsPresent() const { return TestFlag(NHeader::NFlags::kComment); }\r
+\r
+  void Clear()\r
+  {\r
+    Name.Empty();\r
+    Comment.Empty();\r
+    // Extra.SetCapacity(0);\r
+  }\r
+\r
+  HRESULT ReadHeader(NCompress::NDeflate::NDecoder::CCOMCoder *stream);\r
+  HRESULT ReadFooter1(NCompress::NDeflate::NDecoder::CCOMCoder *stream);\r
+  HRESULT ReadFooter2(ISequentialInStream *stream);\r
+\r
+  HRESULT WriteHeader(ISequentialOutStream *stream);\r
+  HRESULT WriteFooter(ISequentialOutStream *stream);\r
+};\r
+\r
+static HRESULT ReadBytes(NCompress::NDeflate::NDecoder::CCOMCoder *stream, Byte *data, UInt32 size)\r
+{\r
+  for (UInt32 i = 0; i < size; i++)\r
+    data[i] = stream->ReadByte();\r
+  return stream->InputEofError() ? S_FALSE : S_OK;\r
+}\r
+\r
+static HRESULT SkipBytes(NCompress::NDeflate::NDecoder::CCOMCoder *stream, UInt32 size)\r
+{\r
+  for (UInt32 i = 0; i < size; i++)\r
+    stream->ReadByte();\r
+  return stream->InputEofError() ? S_FALSE : S_OK;\r
+}\r
+\r
+static HRESULT ReadUInt16(NCompress::NDeflate::NDecoder::CCOMCoder *stream, UInt16 &value /* , UInt32 &crc */)\r
+{\r
+  value = 0;\r
+  for (int i = 0; i < 2; i++)\r
+  {\r
+    Byte b = stream->ReadByte();\r
+    if (stream->InputEofError())\r
+      return S_FALSE;\r
+    // crc = CRC_UPDATE_BYTE(crc, b);\r
+    value |= (UInt16(b) << (8 * i));\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+static HRESULT ReadString(NCompress::NDeflate::NDecoder::CCOMCoder *stream, AString &s, UInt32 limit /* , UInt32 &crc */)\r
+{\r
+  s.Empty();\r
+  for (UInt32 i = 0; i < limit; i++)\r
+  {\r
+    Byte b = stream->ReadByte();\r
+    if (stream->InputEofError())\r
+      return S_FALSE;\r
+    // crc = CRC_UPDATE_BYTE(crc, b);\r
+    if (b == 0)\r
+      return S_OK;\r
+    s += (char)b;\r
+  }\r
+  return S_FALSE;\r
+}\r
+\r
+HRESULT CItem::ReadHeader(NCompress::NDeflate::NDecoder::CCOMCoder *stream)\r
+{\r
+  Clear();\r
+\r
+  // Header-CRC field had another meaning in old version of gzip!\r
+  // UInt32 crc = CRC_INIT_VAL;\r
+  Byte buf[10];\r
+\r
+  RINOK(ReadBytes(stream, buf, 10));\r
+  \r
+  if (GetUi16(buf) != kSignature)\r
+    return S_FALSE;\r
+\r
+  Method = buf[2];\r
+\r
+  if (Method != NHeader::NCompressionMethod::kDeflate)\r
+    return S_FALSE;\r
+\r
+  Flags = buf[3];\r
+  Time = Get32(buf + 4);\r
+  ExtraFlags = buf[8];\r
+  HostOS = buf[9];\r
+\r
+  // crc = CrcUpdate(crc, buf, 10);\r
+  \r
+  if (ExtraFieldIsPresent())\r
+  {\r
+    UInt16 extraSize;\r
+    RINOK(ReadUInt16(stream, extraSize /* , crc */));\r
+    RINOK(SkipBytes(stream, extraSize));\r
+    // Extra.SetCapacity(extraSize);\r
+    // RINOK(ReadStream_FALSE(stream, Extra, extraSize));\r
+    // crc = CrcUpdate(crc, Extra, extraSize);\r
+  }\r
+  if (NameIsPresent())\r
+    RINOK(ReadString(stream, Name, (1 << 10) /* , crc */));\r
+  if (CommentIsPresent())\r
+    RINOK(ReadString(stream, Comment, (1 << 16) /* , crc */));\r
+\r
+  if (HeaderCrcIsPresent())\r
+  {\r
+    UInt16 headerCRC;\r
+    // UInt32 dummy = 0;\r
+    RINOK(ReadUInt16(stream, headerCRC /* , dummy */));\r
+    /*\r
+    if ((UInt16)CRC_GET_DIGEST(crc) != headerCRC)\r
+      return S_FALSE;\r
+    */\r
+  }\r
+  return stream->InputEofError() ? S_FALSE : S_OK;\r
+}\r
+\r
+HRESULT CItem::ReadFooter1(NCompress::NDeflate::NDecoder::CCOMCoder *stream)\r
+{\r
+  Byte buf[8];\r
+  RINOK(ReadBytes(stream, buf, 8));\r
+  Crc = Get32(buf);\r
+  Size32 = Get32(buf + 4);\r
+  return stream->InputEofError() ? S_FALSE : S_OK;\r
+}\r
+\r
+HRESULT CItem::ReadFooter2(ISequentialInStream *stream)\r
+{\r
+  Byte buf[8];\r
+  RINOK(ReadStream_FALSE(stream, buf, 8));\r
+  Crc = Get32(buf);\r
+  Size32 = Get32(buf + 4);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CItem::WriteHeader(ISequentialOutStream *stream)\r
+{\r
+  Byte buf[10];\r
+  SetUi16(buf, kSignature);\r
+  buf[2] = Method;\r
+  buf[3] = Flags & NHeader::NFlags::kName;\r
+  // buf[3] |= NHeader::NFlags::kCrc;\r
+  SetUi32(buf + 4, Time);\r
+  buf[8] = ExtraFlags;\r
+  buf[9] = HostOS;\r
+  RINOK(WriteStream(stream, buf, 10));\r
+  // crc = CrcUpdate(CRC_INIT_VAL, buf, 10);\r
+  if (NameIsPresent())\r
+  {\r
+    // crc = CrcUpdate(crc, (const char *)Name, Name.Length() + 1);\r
+    RINOK(WriteStream(stream, (const char *)Name, Name.Length() + 1));\r
+  }\r
+  // SetUi16(buf, (UInt16)CRC_GET_DIGEST(crc));\r
+  // RINOK(WriteStream(stream, buf, 2));\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CItem::WriteFooter(ISequentialOutStream *stream)\r
+{\r
+  Byte buf[8];\r
+  SetUi32(buf, Crc);\r
+  SetUi32(buf + 4, Size32);\r
+  return WriteStream(stream, buf, 8);\r
+}\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IArchiveOpenSeq,\r
+  public IOutArchive,\r
+  public ISetProperties,\r
+  public CMyUnknownImp\r
+{\r
+  CItem _item;\r
+  UInt64 _startPosition;\r
+  UInt64 _headerSize;\r
+  UInt64 _packSize;\r
+  bool _packSizeDefined;\r
+  CMyComPtr<IInStream> _stream;\r
+  CMyComPtr<ICompressCoder> _decoder;\r
+  NCompress::NDeflate::NDecoder::CCOMCoder *_decoderSpec;\r
+\r
+  CDeflateProps _method;\r
+\r
+public:\r
+  MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties)\r
+  INTERFACE_IInArchive(;)\r
+  INTERFACE_IOutArchive(;)\r
+  STDMETHOD(OpenSeq)(ISequentialInStream *stream);\r
+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);\r
+\r
+  CHandler()\r
+  {\r
+    _decoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder;\r
+    _decoder = _decoderSpec;\r
+  }\r
+};\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidHostOS, VT_BSTR},\r
+  { NULL, kpidCRC, VT_UI4}\r
+  // { NULL, kpidComment, VT_BSTR}\r
+}\r
+;\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps_NO_Table\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = 1;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID,  PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidPath:\r
+      if (_item.NameIsPresent())\r
+        prop = MultiByteToUnicodeString(_item.Name, CP_ACP);\r
+      break;\r
+    // case kpidComment: if (_item.CommentIsPresent()) prop = MultiByteToUnicodeString(_item.Comment, CP_ACP); break;\r
+    case kpidMTime:\r
+    {\r
+      if (_item.Time != 0)\r
+      {\r
+        FILETIME utc;\r
+        NTime::UnixTimeToFileTime(_item.Time, utc);\r
+        prop = utc;\r
+      }\r
+      break;\r
+    }\r
+    case kpidSize: if (_stream) prop = (UInt64)_item.Size32; break;\r
+    case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;\r
+    case kpidHostOS: prop = (_item.HostOS < sizeof(kHostOSes) / sizeof(kHostOSes[0])) ?\r
+          kHostOSes[_item.HostOS] : kUnknownOS; break;\r
+    case kpidCRC: if (_stream) prop = _item.Crc; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *)\r
+{\r
+  COM_TRY_BEGIN\r
+  HRESULT res;\r
+  try\r
+  {\r
+    RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_startPosition));\r
+    res = OpenSeq(stream);\r
+    if (res == S_OK)\r
+    {\r
+      UInt64 endPos;\r
+      res = stream->Seek(-8, STREAM_SEEK_END, &endPos);\r
+      _packSize = endPos + 8 - _startPosition;\r
+      _packSizeDefined = true;\r
+      if (res == S_OK)\r
+      {\r
+        res = _item.ReadFooter2(stream);\r
+        _stream = stream;\r
+      }\r
+    }\r
+  }\r
+  catch(...) { res = S_FALSE; }\r
+  if (res != S_OK)\r
+    Close();\r
+  return res;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)\r
+{\r
+  COM_TRY_BEGIN\r
+  HRESULT res;\r
+  try\r
+  {\r
+    Close();\r
+    _decoderSpec->SetInStream(stream);\r
+    _decoderSpec->InitInStream(true);\r
+    res = _item.ReadHeader(_decoderSpec);\r
+    _headerSize = _decoderSpec->GetInputProcessedSize();\r
+  }\r
+  catch(...) { res = S_FALSE; }\r
+  if (res != S_OK)\r
+    Close();\r
+  return res;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _packSizeDefined = false;\r
+  _stream.Release();\r
+  _decoderSpec->ReleaseInStream();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))\r
+    return E_INVALIDARG;\r
+\r
+  if (_stream)\r
+    extractCallback->SetTotal(_packSize);\r
+  UInt64 currentTotalPacked = 0;\r
+  RINOK(extractCallback->SetCompleted(&currentTotalPacked));\r
+  CMyComPtr<ISequentialOutStream> realOutStream;\r
+  Int32 askMode = testMode ?\r
+      NExtract::NAskMode::kTest :\r
+      NExtract::NAskMode::kExtract;\r
+  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));\r
+  if (!testMode && !realOutStream)\r
+    return S_OK;\r
+\r
+  extractCallback->PrepareOperation(askMode);\r
+\r
+  COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;\r
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\r
+  outStreamSpec->SetStream(realOutStream);\r
+  outStreamSpec->Init();\r
+  realOutStream.Release();\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, true);\r
+\r
+  if (_stream)\r
+  {\r
+    RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));\r
+    _decoderSpec->InitInStream(true);\r
+  }\r
+  bool firstItem = true;\r
+  Int32 opRes;\r
+  for (;;)\r
+  {\r
+    lps->InSize = _packSize = _decoderSpec->GetInputProcessedSize();\r
+    _packSizeDefined = true;\r
+    lps->OutSize = outStreamSpec->GetSize();\r
+    RINOK(lps->SetCur());\r
+\r
+    CItem item;\r
+    if (!firstItem || _stream)\r
+    {\r
+      HRESULT result = item.ReadHeader(_decoderSpec);\r
+      if (result != S_OK)\r
+      {\r
+        if (result != S_FALSE)\r
+          return result;\r
+        opRes = firstItem ?\r
+            NExtract::NOperationResult::kDataError :\r
+            NExtract::NOperationResult::kOK;\r
+        break;\r
+      }\r
+    }\r
+    firstItem = false;\r
+\r
+    UInt64 startOffset = outStreamSpec->GetSize();\r
+    outStreamSpec->InitCRC();\r
+\r
+    HRESULT result = _decoderSpec->CodeResume(outStream, NULL, progress);\r
+    if (result != S_OK)\r
+    {\r
+      if (result != S_FALSE)\r
+        return result;\r
+      opRes = NExtract::NOperationResult::kDataError;\r
+      break;\r
+    }\r
+\r
+    _decoderSpec->AlignToByte();\r
+    if (item.ReadFooter1(_decoderSpec) != S_OK)\r
+    {\r
+      opRes = NExtract::NOperationResult::kDataError;\r
+      break;\r
+    }\r
+    if (item.Crc != outStreamSpec->GetCRC() ||\r
+        item.Size32 != (UInt32)(outStreamSpec->GetSize() - startOffset))\r
+    {\r
+      opRes = NExtract::NOperationResult::kCRCError;\r
+      break;\r
+    }\r
+  }\r
+  outStream.Release();\r
+  return extractCallback->SetOperationResult(opRes);\r
+  COM_TRY_END\r
+}\r
+\r
+static const Byte kHostOS =\r
+  #ifdef _WIN32\r
+  NHeader::NHostOS::kFAT;\r
+  #else\r
+  NHeader::NHostOS::kUnix;\r
+  #endif\r
+\r
+static HRESULT UpdateArchive(\r
+    ISequentialOutStream *outStream,\r
+    UInt64 unpackSize,\r
+    const CItem &newItem,\r
+    CDeflateProps &deflateProps,\r
+    IArchiveUpdateCallback *updateCallback)\r
+{\r
+  UInt64 complexity = 0;\r
+  RINOK(updateCallback->SetTotal(unpackSize));\r
+  RINOK(updateCallback->SetCompleted(&complexity));\r
+\r
+  CMyComPtr<ISequentialInStream> fileInStream;\r
+\r
+  RINOK(updateCallback->GetStream(0, &fileInStream));\r
+\r
+  CSequentialInStreamWithCRC *inStreamSpec = new CSequentialInStreamWithCRC;\r
+  CMyComPtr<ISequentialInStream> crcStream(inStreamSpec);\r
+  inStreamSpec->SetStream(fileInStream);\r
+  inStreamSpec->Init();\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(updateCallback, true);\r
+  \r
+  CItem item = newItem;\r
+  item.Method = NHeader::NCompressionMethod::kDeflate;\r
+  item.ExtraFlags = deflateProps.IsMaximum() ?\r
+      NHeader::NExtraFlags::kMaximum :\r
+      NHeader::NExtraFlags::kFastest;\r
+\r
+  item.HostOS = kHostOS;\r
+\r
+  RINOK(item.WriteHeader(outStream));\r
+\r
+  NCompress::NDeflate::NEncoder::CCOMCoder *deflateEncoderSpec = new NCompress::NDeflate::NEncoder::CCOMCoder;\r
+  CMyComPtr<ICompressCoder> deflateEncoder = deflateEncoderSpec;\r
+  RINOK(deflateProps.SetCoderProperties(deflateEncoderSpec));\r
+  RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, progress));\r
+\r
+  item.Crc = inStreamSpec->GetCRC();\r
+  item.Size32 = (UInt32)inStreamSpec->GetSize();\r
+  RINOK(item.WriteFooter(outStream));\r
+  return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);\r
+}\r
+\r
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)\r
+{\r
+  *timeType = NFileTimeType::kUnix;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\r
+    IArchiveUpdateCallback *updateCallback)\r
+{\r
+  if (numItems != 1)\r
+    return E_INVALIDARG;\r
+\r
+  Int32 newData, newProps;\r
+  UInt32 indexInArchive;\r
+  if (!updateCallback)\r
+    return E_FAIL;\r
+  RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));\r
+\r
+  CItem newItem = _item;\r
+  newItem.ExtraFlags = 0;\r
+  newItem.Flags = 0;\r
+  if (IntToBool(newProps))\r
+  {\r
+    {\r
+      FILETIME utcTime;\r
+      NCOM::CPropVariant prop;\r
+      RINOK(updateCallback->GetProperty(0, kpidMTime, &prop));\r
+      if (prop.vt != VT_FILETIME)\r
+        return E_INVALIDARG;\r
+      utcTime = prop.filetime;\r
+      if (!NTime::FileTimeToUnixTime(utcTime, newItem.Time))\r
+        return E_INVALIDARG;\r
+    }\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      RINOK(updateCallback->GetProperty(0, kpidPath, &prop));\r
+      if (prop.vt == VT_BSTR)\r
+      {\r
+        UString name = prop.bstrVal;\r
+        int dirDelimiterPos = name.ReverseFind(CHAR_PATH_SEPARATOR);\r
+        if (dirDelimiterPos >= 0)\r
+          name = name.Mid(dirDelimiterPos + 1);\r
+        newItem.Name = UnicodeStringToMultiByte(name, CP_ACP);\r
+        if (!newItem.Name.IsEmpty())\r
+          newItem.Flags |= NHeader::NFlags::kName;\r
+      }\r
+      else if (prop.vt != VT_EMPTY)\r
+        return E_INVALIDARG;\r
+    }\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));\r
+      if (prop.vt == VT_BOOL)\r
+      {\r
+        if (prop.boolVal != VARIANT_FALSE)\r
+          return E_INVALIDARG;\r
+      }\r
+      else if (prop.vt != VT_EMPTY)\r
+        return E_INVALIDARG;\r
+    }\r
+  }\r
+\r
+  if (IntToBool(newData))\r
+  {\r
+    UInt64 size;\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      RINOK(updateCallback->GetProperty(0, kpidSize, &prop));\r
+      if (prop.vt != VT_UI8)\r
+        return E_INVALIDARG;\r
+      size = prop.uhVal.QuadPart;\r
+    }\r
+\r
+    return UpdateArchive(outStream, size, newItem, _method, updateCallback);\r
+  }\r
+    \r
+  if (indexInArchive != 0)\r
+    return E_INVALIDARG;\r
+\r
+  if (!_stream)\r
+    return E_NOTIMPL;\r
+\r
+  UInt64 offset = _startPosition;\r
+  if (IntToBool(newProps))\r
+  {\r
+    newItem.WriteHeader(outStream);\r
+    offset += _headerSize;\r
+  }\r
+  RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL));\r
+  return NCompress::CopyStream(_stream, outStream, NULL);\r
+}\r
+\r
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)\r
+{\r
+  return _method.SetProperties(names, values, numProps);\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+#ifndef EXTRACT_ONLY\r
+static IOutArchive *CreateArcOut() { return new CHandler; }\r
+#else\r
+#define CreateArcOut 0\r
+#endif\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"gzip", L"gz gzip tgz tpz", L"* * .tar .tar", 0xEF, { 0x1F, 0x8B, 8 }, 3, true, CreateArc, CreateArcOut };\r
+\r
+REGISTER_ARC(GZip)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Hfs/HfsHandler.cpp b/CPP/7zip/Archive/Hfs/HfsHandler.cpp
new file mode 100755 (executable)
index 0000000..756da17
--- /dev/null
@@ -0,0 +1,243 @@
+// HfsHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Windows/PropVariant.h"\r
+#include "../../Common/StreamUtils.h"\r
+#include "HfsHandler.h"\r
+\r
+namespace NArchive {\r
+namespace NHfs {\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidIsDir, VT_BOOL},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidCTime, VT_FILETIME},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidATime, VT_FILETIME}\r
+};\r
+\r
+STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidMethod, VT_BSTR},\r
+  { NULL, kpidClusterSize, VT_UI4},\r
+  { NULL, kpidFreeSpace, VT_UI8},\r
+  { NULL, kpidCTime, VT_FILETIME},\r
+  { NULL, kpidMTime, VT_FILETIME}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+static void HfsTimeToProp(UInt32 hfsTime, NWindows::NCOM::CPropVariant &prop)\r
+{\r
+  FILETIME ft;\r
+  HfsTimeToFileTime(hfsTime, ft);\r
+  prop = ft;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidMethod: prop = _db.Header.IsHfsX() ? L"HFSX" : L"HFS+"; break;\r
+    case kpidClusterSize: prop = (UInt32)1 << _db.Header.BlockSizeLog; break;\r
+    case kpidFreeSpace: prop = (UInt64)_db.Header.NumFreeBlocks << _db.Header.BlockSizeLog; break;\r
+    case kpidMTime: HfsTimeToProp(_db.Header.MTime, prop); break;\r
+    case kpidCTime:\r
+    {\r
+      FILETIME localFt, ft;\r
+      HfsTimeToFileTime(_db.Header.CTime, localFt);\r
+      if (LocalFileTimeToFileTime(&localFt, &ft))\r
+        prop = ft;\r
+      break;\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  const CItem &item = _db.Items[index];\r
+  switch(propID)\r
+  {\r
+    case kpidPath: prop = _db.GetItemPath(index); break;\r
+    case kpidIsDir: prop = item.IsDir(); break;\r
+\r
+    case kpidCTime:  HfsTimeToProp(item.CTime, prop); break;\r
+    case kpidMTime:  HfsTimeToProp(item.MTime, prop); break;\r
+    case kpidATime:  HfsTimeToProp(item.ATime, prop); break;\r
+\r
+    case kpidPackSize: if (!item.IsDir()) prop = (UInt64)item.NumBlocks << _db.Header.BlockSizeLog; break;\r
+    case kpidSize:     if (!item.IsDir()) prop = item.Size; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+class CProgressImp: public CProgressVirt\r
+{\r
+  CMyComPtr<IArchiveOpenCallback> _callback;\r
+public:\r
+  HRESULT SetTotal(UInt64 numFiles);\r
+  HRESULT SetCompleted(UInt64 numFiles);\r
+  CProgressImp(IArchiveOpenCallback *callback): _callback(callback) {}\r
+};\r
+\r
+HRESULT CProgressImp::SetTotal(UInt64 numFiles)\r
+{\r
+  if (_callback)\r
+    return _callback->SetTotal(&numFiles, NULL);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CProgressImp::SetCompleted(UInt64 numFiles)\r
+{\r
+  if (_callback)\r
+    return _callback->SetCompleted(&numFiles, NULL);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *inStream,\r
+    const UInt64 * /* maxCheckStartPosition */,\r
+    IArchiveOpenCallback *callback)\r
+{\r
+  COM_TRY_BEGIN\r
+  Close();\r
+  try\r
+  {\r
+    CProgressImp progressImp(callback);\r
+    HRESULT res = _db.Open(inStream, &progressImp);\r
+    if (res == E_ABORT)\r
+      return res;\r
+    if (res != S_OK)\r
+      return S_FALSE;\r
+    _stream = inStream;\r
+  }\r
+  catch(...) { return S_FALSE; }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _stream.Release();\r
+  _db.Clear();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _db.Items.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt32 i;\r
+  UInt64 totalSize = 0;\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    const CItem &item = _db.Items[allFilesMode ? i : indices[i]];\r
+    if (!item.IsDir())\r
+      totalSize += item.Size;\r
+  }\r
+  RINOK(extractCallback->SetTotal(totalSize));\r
+\r
+  UInt64 currentTotalSize = 0, currentItemSize = 0;\r
+  \r
+  CByteBuffer buf;\r
+  const UInt32 kBufSize = (1 << 16);\r
+  buf.SetCapacity(kBufSize);\r
+\r
+  for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)\r
+  {\r
+    RINOK(extractCallback->SetCompleted(&currentTotalSize));\r
+    Int32 index = allFilesMode ? i : indices[i];\r
+    const CItem &item = _db.Items[index];\r
+    currentItemSize = 0;\r
+    if (!item.IsDir())\r
+      currentItemSize = item.Size;\r
+\r
+    CMyComPtr<ISequentialOutStream> realOutStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+\r
+    if (item.IsDir())\r
+    {\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+      continue;\r
+    }\r
+    if (!testMode && !realOutStream)\r
+      continue;\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+    UInt64 pos = 0;\r
+    int res = NExtract::NOperationResult::kOK;\r
+    int i;\r
+    for (i = 0; i < item.Extents.Size(); i++)\r
+    {\r
+      if (item.Size == pos)\r
+        break;\r
+      if (res != NExtract::NOperationResult::kOK)\r
+        break;\r
+      const CExtent &e = item.Extents[i];\r
+      RINOK(_stream->Seek((UInt64)e.Pos << _db.Header.BlockSizeLog, STREAM_SEEK_SET, NULL));\r
+      UInt64 extentSize = (UInt64)e.NumBlocks << _db.Header.BlockSizeLog;\r
+      for (;;)\r
+      {\r
+        if (extentSize == 0)\r
+          break;\r
+        UInt64 rem = item.Size - pos;\r
+        if (rem == 0)\r
+        {\r
+          if (extentSize >= (UInt64)((UInt32)1 << _db.Header.BlockSizeLog))\r
+            res = NExtract::NOperationResult::kDataError;\r
+          break;\r
+        }\r
+        UInt32 curSize = kBufSize;\r
+        if (curSize > rem)\r
+          curSize = (UInt32)rem;\r
+        if (curSize > extentSize)\r
+          curSize = (UInt32)extentSize;\r
+        RINOK(ReadStream_FALSE(_stream, buf, curSize));\r
+        if (realOutStream)\r
+        {\r
+          RINOK(WriteStream(realOutStream, buf, curSize));\r
+        }\r
+        pos += curSize;\r
+        extentSize -= curSize;\r
+        UInt64 processed = currentTotalSize + pos;\r
+        RINOK(extractCallback->SetCompleted(&processed));\r
+      }\r
+    }\r
+    if (i != item.Extents.Size() || item.Size != pos)\r
+      res = NExtract::NOperationResult::kDataError;\r
+    realOutStream.Release();\r
+    RINOK(extractCallback->SetOperationResult(res));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _db.Items.Size();\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Hfs/HfsHandler.h b/CPP/7zip/Archive/Hfs/HfsHandler.h
new file mode 100755 (executable)
index 0000000..8cfa9f6
--- /dev/null
@@ -0,0 +1,26 @@
+// HfsHandler.h\r
+\r
+#ifndef __ARCHIVE_HFS_HANDLER_H\r
+#define __ARCHIVE_HFS_HANDLER_H\r
+\r
+#include "Common/MyCom.h"\r
+#include "../IArchive.h"\r
+#include "HfsIn.h"\r
+\r
+namespace NArchive {\r
+namespace NHfs {\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<IInStream> _stream;\r
+  CDatabase _db;\r
+public:\r
+  MY_UNKNOWN_IMP1(IInArchive)\r
+  INTERFACE_IInArchive(;)\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Hfs/HfsIn.cpp b/CPP/7zip/Archive/Hfs/HfsIn.cpp
new file mode 100755 (executable)
index 0000000..0e84898
--- /dev/null
@@ -0,0 +1,480 @@
+// HfsIn.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/StreamUtils.h"\r
+#include "Common/IntToString.h"\r
+\r
+#include "HfsIn.h"\r
+\r
+#include "../../../../C/CpuArch.h"\r
+\r
+#define Get16(p) GetBe16(p)\r
+#define Get32(p) GetBe32(p)\r
+#define Get64(p) GetBe64(p)\r
+\r
+namespace NArchive {\r
+namespace NHfs {\r
+\r
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }\r
+\r
+static int CompareIdToIndex(const CIdIndexPair *p1, const CIdIndexPair *p2, void * /* param */)\r
+{\r
+  RINOZ(MyCompare(p1->ID, p2->ID));\r
+  return MyCompare(p1->Index, p2->Index);\r
+}\r
+\r
+bool operator< (const CIdIndexPair &a1, const CIdIndexPair &a2) { return (a1.ID  < a2.ID); }\r
+bool operator> (const CIdIndexPair &a1, const CIdIndexPair &a2) { return (a1.ID  > a2.ID); }\r
+bool operator==(const CIdIndexPair &a1, const CIdIndexPair &a2) { return (a1.ID == a2.ID); }\r
+bool operator!=(const CIdIndexPair &a1, const CIdIndexPair &a2) { return (a1.ID != a2.ID); }\r
+\r
+static UString GetSpecName(const UString &name, UInt32 /* id */)\r
+{\r
+  UString name2 = name;\r
+  name2.Trim();\r
+  if (name2.IsEmpty())\r
+  {\r
+    /*\r
+    wchar_t s[32];\r
+    ConvertUInt64ToString(id, s);\r
+    return L"[" + (UString)s + L"]";\r
+    */\r
+    return L"[]";\r
+  }\r
+  return name;\r
+}\r
+\r
+UString CDatabase::GetItemPath(int index) const\r
+{\r
+  const CItem *item = &Items[index];\r
+  UString name = GetSpecName(item->Name, item->ID);\r
+\r
+  for (int i = 0; i < 1000; i++)\r
+  {\r
+    if (item->ParentID < 16 && item->ParentID != 2)\r
+    {\r
+      if (item->ParentID != 1)\r
+        break;\r
+      return name;\r
+    }\r
+    CIdIndexPair pair;\r
+    pair.ID = item->ParentID;\r
+    pair.Index = 0;\r
+    int indexInMap = IdToIndexMap.FindInSorted(pair);\r
+    if (indexInMap < 0)\r
+      break;\r
+    item = &Items[IdToIndexMap[indexInMap].Index];\r
+    name = GetSpecName(item->Name, item->ID) + WCHAR_PATH_SEPARATOR + name;\r
+  }\r
+  return (UString)L"Unknown" + WCHAR_PATH_SEPARATOR + name;\r
+}\r
+\r
+void CFork::Parse(const Byte *p)\r
+{\r
+  Size = Get64(p);\r
+  // ClumpSize = Get32(p + 8);\r
+  NumBlocks = Get32(p + 0xC);\r
+  for (int i = 0; i < 8; i++)\r
+  {\r
+    CExtent &e = Extents[i];\r
+    e.Pos = Get32(p + 0x10 + i * 8);\r
+    e.NumBlocks = Get32(p + 0x10 + i * 8 + 4);\r
+  }\r
+}\r
+\r
+static HRESULT ReadExtent(int blockSizeLog, IInStream *inStream, Byte *buf, const CExtent &e)\r
+{\r
+  RINOK(inStream->Seek((UInt64)e.Pos << blockSizeLog, STREAM_SEEK_SET, NULL));\r
+  return ReadStream_FALSE(inStream, buf, (size_t)e.NumBlocks << blockSizeLog);\r
+}\r
+\r
+HRESULT CDatabase::ReadFile(const CFork &fork, CByteBuffer &buf, IInStream *inStream)\r
+{\r
+  if (fork.NumBlocks >= Header.NumBlocks)\r
+    return S_FALSE;\r
+  size_t totalSize = (size_t)fork.NumBlocks << Header.BlockSizeLog;\r
+  if ((totalSize >> Header.BlockSizeLog) != fork.NumBlocks)\r
+    return S_FALSE;\r
+  buf.SetCapacity(totalSize);\r
+  UInt32 curBlock = 0;\r
+  for (int i = 0; i < 8; i++)\r
+  {\r
+    if (curBlock >= fork.NumBlocks)\r
+      break;\r
+    const CExtent &e = fork.Extents[i];\r
+    if (fork.NumBlocks - curBlock < e.NumBlocks || e.Pos >= Header.NumBlocks)\r
+      return S_FALSE;\r
+    RINOK(ReadExtent(Header.BlockSizeLog, inStream,\r
+        (Byte *)buf + ((size_t)curBlock << Header.BlockSizeLog), e));\r
+    curBlock += e.NumBlocks;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+struct CNodeDescriptor\r
+{\r
+  UInt32 fLink;\r
+  UInt32 bLink;\r
+  Byte Kind;\r
+  Byte Height;\r
+  UInt16 NumRecords;\r
+  // UInt16 Reserved;\r
+  void Parse(const Byte *p);\r
+};\r
+\r
+void CNodeDescriptor::Parse(const Byte *p)\r
+{\r
+  fLink = Get32(p);\r
+  bLink = Get32(p + 4);\r
+  Kind = p[8];\r
+  Height = p[9];\r
+  NumRecords = Get16(p + 10);\r
+}\r
+\r
+struct CHeaderRec\r
+{\r
+  // UInt16 TreeDepth;\r
+  // UInt32 RootNode;\r
+  // UInt32 LeafRecords;\r
+  UInt32 FirstLeafNode;\r
+  // UInt32 LastLeafNode;\r
+  int NodeSizeLog;\r
+  // UInt16 MaxKeyLength;\r
+  UInt32 TotalNodes;\r
+  // UInt32 FreeNodes;\r
+  // UInt16 Reserved1;\r
+  // UInt32 ClumpSize;\r
+  // Byte BtreeType;\r
+  // Byte KeyCompareType;\r
+  // UInt32 Attributes;\r
+  // UInt32 Reserved3[16];\r
+  \r
+  HRESULT Parse(const Byte *p);\r
+};\r
+\r
+HRESULT CHeaderRec::Parse(const Byte *p)\r
+{\r
+  // TreeDepth = Get16(p);\r
+  // RootNode = Get32(p + 2);\r
+  // LeafRecords = Get32(p + 6);\r
+  FirstLeafNode = Get32(p + 0xA);\r
+  // LastLeafNode = Get32(p + 0xE);\r
+  UInt32 nodeSize = Get16(p + 0x12);\r
+\r
+  int i;\r
+  for (i = 9; ((UInt32)1 << i) != nodeSize; i++)\r
+    if (i == 16)\r
+      return S_FALSE;\r
+  NodeSizeLog = i;\r
+\r
+  // MaxKeyLength = Get16(p + 0x14);\r
+  TotalNodes = Get32(p + 0x16);\r
+  // FreeNodes = Get32(p + 0x1A);\r
+  // Reserved1 = Get16(p + 0x1E);\r
+  // ClumpSize = Get32(p + 0x20);\r
+  // BtreeType = p[0x24];\r
+  // KeyCompareType = p[0x25];\r
+  // Attributes = Get32(p + 0x26);\r
+  /*\r
+  for (int i = 0; i < 16; i++)\r
+    Reserved3[i] = Get32(p + 0x2A + i * 4);\r
+  */\r
+  return S_OK;\r
+}\r
+\r
+\r
+enum ENodeType\r
+{\r
+  NODE_TYPE_LEAF = 0xFF,\r
+  NODE_TYPE_INDEX = 0,\r
+  NODE_TYPE_HEADER = 1,\r
+  NODE_TYPE_MODE = 2\r
+};\r
+\r
+HRESULT CDatabase::LoadExtentFile(IInStream *inStream)\r
+{\r
+  // FileExtents.Clear();\r
+  // ResExtents.Clear();\r
+\r
+  CByteBuffer extents;\r
+  RINOK(ReadFile(Header.ExtentsFile, extents, inStream));\r
+\r
+  const Byte *p = (const Byte *)extents;\r
+\r
+  // CNodeDescriptor nodeDesc;\r
+  // nodeDesc.Parse(p);\r
+  CHeaderRec hr;\r
+  RINOK(hr.Parse(p + 14));\r
+\r
+  UInt32 node = hr.FirstLeafNode;\r
+  if (node != 0)\r
+    return S_FALSE;\r
+  /*\r
+  while (node != 0)\r
+  {\r
+    size_t nodeOffset = node * hr.NodeSize;\r
+    if ((node + 1)* hr.NodeSize > CatalogBuf.GetCapacity())\r
+      return S_FALSE;\r
+    CNodeDescriptor desc;\r
+    desc.Parse(p + nodeOffset);\r
+    if (desc.Kind != NODE_TYPE_LEAF)\r
+      return S_FALSE;\r
+    UInt32 ptr = hr.NodeSize;\r
+    for (int i = 0; i < desc.NumRecords; i++)\r
+    {\r
+      UInt32 offs = Get16(p + nodeOffset + hr.NodeSize - (i + 1) * 2);\r
+      UInt32 offsNext = Get16(p + nodeOffset + hr.NodeSize - (i + 2) * 2);\r
+\r
+      const Byte *r = p + nodeOffset + offs;\r
+      int keyLength = Get16(r);\r
+      Byte forkType = r[2];\r
+      UInt32 id = Get16(r + 4);\r
+      UInt32 startBlock = Get16(r + 4);\r
+      CObjectVector<CIdExtents> *extents = (forkType == 0) ? &FileExtents : &ResExtents;\r
+      if (extents->Size() == 0)\r
+        extents->Add(CIdExtents());\r
+      else\r
+      {\r
+        CIdExtents &e = extents->Back();\r
+        if (e.ID != id)\r
+        {\r
+          if (e.ID > id)\r
+            return S_FALSE;\r
+          extents->Add(CIdExtents());\r
+        }\r
+      }\r
+      CIdExtents &e = extents->Back();\r
+      for (UInt32 k = offs + 10 + 2; k + 8 <= offsNext; k += 8)\r
+      {\r
+        CExtent ee;\r
+        ee.Pos = Get32(p + nodeOffset + k);\r
+        ee.NumBlocks  = Get32(p + nodeOffset + k * 4);\r
+        e.Extents.Add(ee);\r
+      }\r
+    }\r
+    node = desc.fLink;\r
+  }\r
+  */\r
+  return S_OK;\r
+}\r
+\r
+\r
+HRESULT CDatabase::LoadCatalog(IInStream *inStream, CProgressVirt *progress)\r
+{\r
+  Items.Clear();\r
+  IdToIndexMap.ClearAndFree();\r
+\r
+  CByteBuffer catalogBuf;\r
+  RINOK(ReadFile(Header.CatalogFile, catalogBuf, inStream));\r
+  const Byte *p = (const Byte *)catalogBuf;\r
+\r
+  // CNodeDescriptor nodeDesc;\r
+  // nodeDesc.Parse(p);\r
+  CHeaderRec hr;\r
+  hr.Parse(p + 14);\r
+  \r
+  // CaseSensetive = (Header.IsHfsX() && hr.KeyCompareType == 0xBC);\r
+\r
+  if ((catalogBuf.GetCapacity() >> hr.NodeSizeLog) < hr.TotalNodes)\r
+    return S_FALSE;\r
+\r
+  CByteBuffer usedBuf;\r
+  usedBuf.SetCapacity(hr.TotalNodes);\r
+  for (UInt32 i = 0; i < hr.TotalNodes; i++)\r
+    usedBuf[i] = 0;\r
+\r
+  UInt32 node = hr.FirstLeafNode;\r
+  while (node != 0)\r
+  {\r
+    if (node >= hr.TotalNodes)\r
+      return S_FALSE;\r
+    if (usedBuf[node])\r
+      return S_FALSE;\r
+    usedBuf[node] = 1;\r
+    size_t nodeOffset = (size_t)node << hr.NodeSizeLog;\r
+    CNodeDescriptor desc;\r
+    desc.Parse(p + nodeOffset);\r
+    if (desc.Kind != NODE_TYPE_LEAF)\r
+      return S_FALSE;\r
+    for (int i = 0; i < desc.NumRecords; i++)\r
+    {\r
+      UInt32 nodeSize = (1 << hr.NodeSizeLog);\r
+      UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2);\r
+      UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2);\r
+      UInt32 recSize = offsNext - offs;\r
+      if (offsNext >= nodeSize || offsNext < offs || recSize < 6)\r
+        return S_FALSE;\r
+\r
+      CItem item;\r
+\r
+      const Byte *r = p + nodeOffset + offs;\r
+      UInt32 keyLength = Get16(r);\r
+      item.ParentID = Get32(r + 2);\r
+      UString name;\r
+      if (keyLength < 6 || (keyLength & 1) != 0 || keyLength + 2 > recSize)\r
+        return S_FALSE;\r
+      r += 6;\r
+      recSize -= 6;\r
+      keyLength -= 6;\r
+      \r
+      int nameLength = Get16(r);\r
+      if (nameLength * 2 != (int)keyLength)\r
+        return S_FALSE;\r
+      r += 2;\r
+      recSize -= 2;\r
+     \r
+      wchar_t *pp = name.GetBuffer(nameLength + 1);\r
+      \r
+      int j;\r
+      for (j = 0; j < nameLength; j++)\r
+        pp[j] = ((wchar_t)r[j * 2] << 8) | r[j * 2 + 1];\r
+      pp[j] = 0;\r
+      name.ReleaseBuffer();\r
+      r += j * 2;\r
+      recSize -= j * 2;\r
+\r
+      if (recSize < 2)\r
+        return S_FALSE;\r
+      item.Type = Get16(r);\r
+\r
+      if (item.Type != RECORD_TYPE_FOLDER && item.Type != RECORD_TYPE_FILE)\r
+        continue;\r
+      if (recSize < 0x58)\r
+        return S_FALSE;\r
+\r
+      // item.Flags = Get16(r + 2);\r
+      // item.Valence = Get32(r + 4);\r
+      item.ID = Get32(r + 8);\r
+      item.CTime = Get32(r + 0xC);\r
+      item.MTime = Get32(r + 0x10);\r
+      // item.AttrMTime = Get32(r + 0x14);\r
+      item.ATime = Get32(r + 0x18);\r
+      // item.BackupDate = Get32(r + 0x1C);\r
+      \r
+      /*\r
+      item.OwnerID = Get32(r + 0x20);\r
+      item.GroupID = Get32(r + 0x24);\r
+      item.AdminFlags = r[0x28];\r
+      item.OwnerFlags = r[0x29];\r
+      item.FileMode = Get16(r + 0x2A);\r
+      item.special.iNodeNum = Get16(r + 0x2C);\r
+      */\r
+\r
+      item.Name = name;\r
+\r
+      if (item.IsDir())\r
+      {\r
+        CIdIndexPair pair;\r
+        pair.ID = item.ID;\r
+        pair.Index = Items.Size();\r
+        IdToIndexMap.Add(pair);\r
+      }\r
+      else\r
+      {\r
+        CFork fd;\r
+        recSize -= 0x58;\r
+        r += 0x58;\r
+        if (recSize < 0x50 * 2)\r
+          return S_FALSE;\r
+        fd.Parse(r);\r
+        item.Size = fd.Size;\r
+        item.NumBlocks = fd.NumBlocks;\r
+        UInt32 curBlock = 0;\r
+        for (int j = 0; j < 8; j++)\r
+        {\r
+          if (curBlock >= fd.NumBlocks)\r
+            break;\r
+          const CExtent &e = fd.Extents[j];\r
+          item.Extents.Add(e);\r
+          curBlock += e.NumBlocks;\r
+        }\r
+      }\r
+      Items.Add(item);\r
+      if (progress && Items.Size() % 100 == 0)\r
+      {\r
+        RINOK(progress->SetCompleted(Items.Size()));\r
+      }\r
+    }\r
+    node = desc.fLink;\r
+  }\r
+  IdToIndexMap.Sort(CompareIdToIndex, NULL);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CDatabase::Open(IInStream *inStream, CProgressVirt *progress)\r
+{\r
+  static const UInt32 kHeaderSize = 1024 + 512;\r
+  Byte buf[kHeaderSize];\r
+  RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize));\r
+  int i;\r
+  for (i = 0; i < 1024; i++)\r
+    if (buf[i] != 0)\r
+      return S_FALSE;\r
+  const Byte *p = buf + 1024;\r
+  CVolHeader &h = Header;\r
+\r
+  h.Header[0] = p[0];\r
+  h.Header[1] = p[1];\r
+  if (p[0] != 'H' || (p[1] != '+' && p[1] != 'X'))\r
+    return S_FALSE;\r
+  h.Version = Get16(p + 2);\r
+  if (h.Version < 4 || h.Version > 5)\r
+    return S_FALSE;\r
+\r
+  // h.Attr = Get32(p + 4);\r
+  // h.LastMountedVersion = Get32(p + 8);\r
+  // h.JournalInfoBlock = Get32(p + 0xC);\r
+\r
+  h.CTime = Get32(p + 0x10);\r
+  h.MTime = Get32(p + 0x14);\r
+  // h.BackupTime = Get32(p + 0x18);\r
+  // h.CheckedTime = Get32(p + 0x1C);\r
+\r
+  // h.NumFiles = Get32(p + 0x20);\r
+  // h.NumFolders = Get32(p + 0x24);\r
+  \r
+  UInt32 numFiles = Get32(p + 0x20);\r
+  UInt32 numFolders = Get32(p + 0x24);;\r
+  if (progress)\r
+  {\r
+    RINOK(progress->SetTotal(numFolders + numFiles));\r
+  }\r
+\r
+  UInt32 blockSize = Get32(p + 0x28);\r
+\r
+  for (i = 9; ((UInt32)1 << i) != blockSize; i++)\r
+    if (i == 31)\r
+      return S_FALSE;\r
+  h.BlockSizeLog = i;\r
+\r
+  h.NumBlocks = Get32(p + 0x2C);\r
+  h.NumFreeBlocks = Get32(p + 0x30);\r
+\r
+  /*\r
+  h.WriteCount = Get32(p + 0x44);\r
+  for (i = 0; i < 6; i++)\r
+    h.FinderInfo[i] = Get32(p + 0x50 + i * 4);\r
+  h.VolID = Get64(p + 0x68);\r
+  */\r
+\r
+  UInt64 endPos;\r
+  RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos));\r
+  if ((endPos >> h.BlockSizeLog) < h.NumBlocks)\r
+    return S_FALSE;\r
+\r
+  // h.AllocationFile.Parse(p + 0x70 + 0x50 * 0);\r
+  h.ExtentsFile.Parse(   p + 0x70 + 0x50 * 1);\r
+  h.CatalogFile.Parse(   p + 0x70 + 0x50 * 2);\r
+  // h.AttributesFile.Parse(p + 0x70 + 0x50 * 3);\r
+  // h.StartupFile.Parse(   p + 0x70 + 0x50 * 4);\r
+\r
+  RINOK(LoadExtentFile(inStream));\r
+  RINOK(LoadCatalog(inStream, progress));\r
+\r
+  // if (Header.NumFiles + Header.NumFolders != (UInt32)Items.Size()) return S_OK;\r
+\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Hfs/HfsIn.h b/CPP/7zip/Archive/Hfs/HfsIn.h
new file mode 100755 (executable)
index 0000000..c7993e5
--- /dev/null
@@ -0,0 +1,154 @@
+// HfsIn.h\r
+\r
+#ifndef __ARCHIVE_HFS_IN_H\r
+#define __ARCHIVE_HFS_IN_H\r
+\r
+#include "Common/MyString.h"\r
+#include "Common/Buffer.h"\r
+\r
+namespace NArchive {\r
+namespace NHfs {\r
+\r
+struct CExtent\r
+{\r
+  UInt32 Pos;\r
+  UInt32 NumBlocks;\r
+};\r
+\r
+struct CFork\r
+{\r
+  UInt64 Size;\r
+  // UInt32 ClumpSize;\r
+  UInt32 NumBlocks;\r
+  CExtent Extents[8];\r
+  void Parse(const Byte *p);\r
+};\r
+\r
+struct CVolHeader\r
+{\r
+  Byte Header[2];\r
+  UInt16 Version;\r
+  // UInt32 Attr;\r
+  // UInt32 LastMountedVersion;\r
+  // UInt32 JournalInfoBlock;\r
+\r
+  UInt32 CTime;\r
+  UInt32 MTime;\r
+  // UInt32 BackupTime;\r
+  // UInt32 CheckedTime;\r
+  \r
+  // UInt32 NumFiles;\r
+  // UInt32 NumFolders;\r
+  int BlockSizeLog;\r
+  UInt32 NumBlocks;\r
+  UInt32 NumFreeBlocks;\r
+\r
+  // UInt32 WriteCount;\r
+  // UInt32 FinderInfo[8];\r
+  // UInt64 VolID;\r
+\r
+  // CFork AllocationFile;\r
+  CFork ExtentsFile;\r
+  CFork CatalogFile;\r
+  // CFork AttributesFile;\r
+  // CFork StartupFile;\r
+\r
+  bool IsHfsX() const { return Version > 4; }\r
+};\r
+\r
+inline void HfsTimeToFileTime(UInt32 hfsTime, FILETIME &ft)\r
+{\r
+  UInt64 v = ((UInt64)3600 * 24 * (365 * 303 + 24 * 3) + hfsTime) * 10000000;\r
+  ft.dwLowDateTime = (DWORD)v;\r
+  ft.dwHighDateTime = (DWORD)(v >> 32);\r
+}\r
+\r
+enum ERecordType\r
+{\r
+  RECORD_TYPE_FOLDER = 1,\r
+  RECORD_TYPE_FILE = 2,\r
+  RECORD_TYPE_FOLDER_THREAD = 3,\r
+  RECORD_TYPE_FILE_THREAD = 4\r
+};\r
+\r
+struct CItem\r
+{\r
+  UString Name;\r
+  \r
+  UInt32 ParentID;\r
+\r
+  UInt16 Type;\r
+  // UInt16 Flags;\r
+  // UInt32 Valence;\r
+  UInt32 ID;\r
+  UInt32 CTime;\r
+  UInt32 MTime;\r
+  // UInt32 AttrMTime;\r
+  UInt32 ATime;\r
+  // UInt32 BackupDate;\r
+\r
+  /*\r
+  UInt32 OwnerID;\r
+  UInt32 GroupID;\r
+  Byte AdminFlags;\r
+  Byte OwnerFlags;\r
+  UInt16 FileMode;\r
+  union\r
+  {\r
+    UInt32  iNodeNum;\r
+    UInt32  LinkCount;\r
+    UInt32  RawDevice;\r
+  } special;\r
+  */\r
+\r
+  UInt64 Size;\r
+  UInt32 NumBlocks;\r
+  CRecordVector<CExtent> Extents;\r
+\r
+  bool IsDir() const { return Type == RECORD_TYPE_FOLDER; }\r
+  CItem(): Size(0), NumBlocks(0) {}\r
+};\r
+\r
+struct CIdIndexPair\r
+{\r
+  UInt32 ID;\r
+  int Index;\r
+};\r
+\r
+struct CProgressVirt\r
+{\r
+  virtual HRESULT SetTotal(UInt64 numFiles) PURE;\r
+  virtual HRESULT SetCompleted(UInt64 numFiles) PURE;\r
+};\r
+\r
+class CDatabase\r
+{\r
+  // CObjectVector<CIdExtents> FileExtents;\r
+  // CObjectVector<CIdExtents> ResExtents;\r
+  CRecordVector<CIdIndexPair> IdToIndexMap;\r
+\r
+  HRESULT LoadExtentFile(IInStream *inStream);\r
+  HRESULT LoadCatalog(IInStream *inStream, CProgressVirt *progress);\r
+\r
+  HRESULT ReadFile(const CFork &fork, CByteBuffer &buf, IInStream *inStream);\r
+public:\r
+  CVolHeader Header;\r
+  CObjectVector<CItem> Items;\r
+  // bool CaseSensetive;\r
+\r
+  void Clear()\r
+  {\r
+    // CaseSensetive = false;\r
+    Items.Clear();\r
+    // FileExtents.Clear();\r
+    // ResExtents.Clear();\r
+    IdToIndexMap.Clear();\r
+  }\r
+\r
+  UString GetItemPath(int index) const;\r
+  HRESULT Open(IInStream *inStream, CProgressVirt *progress);\r
+};\r
+\r
+}}\r
+  \r
+#endif\r
diff --git a/CPP/7zip/Archive/Hfs/HfsRegister.cpp b/CPP/7zip/Archive/Hfs/HfsRegister.cpp
new file mode 100755 (executable)
index 0000000..d877f9e
--- /dev/null
@@ -0,0 +1,13 @@
+// HfsRegister.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/RegisterArc.h"\r
+\r
+#include "HfsHandler.h"\r
+static IInArchive *CreateArc() { return new NArchive::NHfs::CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"HFS", L"hfs", 0, 0xE3, { 'H', '+', 0, 4 }, 4, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Hfs)\r
diff --git a/CPP/7zip/Archive/IArchive.h b/CPP/7zip/Archive/IArchive.h
new file mode 100755 (executable)
index 0000000..e4101cc
--- /dev/null
@@ -0,0 +1,234 @@
+// IArchive.h\r
+\r
+#ifndef __IARCHIVE_H\r
+#define __IARCHIVE_H\r
+\r
+#include "../IProgress.h"\r
+#include "../IStream.h"\r
+#include "../PropID.h"\r
+\r
+#define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x)\r
+#define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x)\r
+\r
+namespace NFileTimeType\r
+{\r
+  enum EEnum\r
+  {\r
+    kWindows,\r
+    kUnix,\r
+    kDOS\r
+  };\r
+}\r
+\r
+namespace NArchive\r
+{\r
+  enum\r
+  {\r
+    kName = 0,\r
+    kClassID,\r
+    kExtension,\r
+    kAddExtension,\r
+    kUpdate,\r
+    kKeepName,\r
+    kStartSignature,\r
+    kFinishSignature,\r
+    kAssociate\r
+  };\r
+\r
+  namespace NExtract\r
+  {\r
+    namespace NAskMode\r
+    {\r
+      enum\r
+      {\r
+        kExtract = 0,\r
+        kTest,\r
+        kSkip\r
+      };\r
+    }\r
+    namespace NOperationResult\r
+    {\r
+      enum\r
+      {\r
+        kOK = 0,\r
+        kUnSupportedMethod,\r
+        kDataError,\r
+        kCRCError\r
+      };\r
+    }\r
+  }\r
+  namespace NUpdate\r
+  {\r
+    namespace NOperationResult\r
+    {\r
+      enum\r
+      {\r
+        kOK = 0,\r
+        kError\r
+      };\r
+    }\r
+  }\r
+}\r
+\r
+#define INTERFACE_IArchiveOpenCallback(x) \\r
+  STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) x; \\r
+  STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) x; \\r
+\r
+ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10)\r
+{\r
+  INTERFACE_IArchiveOpenCallback(PURE);\r
+};\r
+\r
+\r
+#define INTERFACE_IArchiveExtractCallback(x) \\r
+  INTERFACE_IProgress(x) \\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream,  Int32 askExtractMode) x; \\r
+  STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \\r
+  STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \\r
+\r
+ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20)\r
+{\r
+  INTERFACE_IArchiveExtractCallback(PURE)\r
+};\r
+\r
+\r
+#define INTERFACE_IArchiveOpenVolumeCallback(x) \\r
+  STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \\r
+  STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \\r
+\r
+ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30)\r
+{\r
+  INTERFACE_IArchiveOpenVolumeCallback(PURE);\r
+};\r
+\r
+\r
+ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40)\r
+{\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE;\r
+};\r
+\r
+\r
+ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50)\r
+{\r
+  STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE;\r
+};\r
+\r
+\r
+/*\r
+IInArchive::Extract:\r
+  indices must be sorted\r
+  numItems = 0xFFFFFFFF means "all files"\r
+  testMode != 0 means "test files without writing to outStream"\r
+*/\r
+\r
+#define INTERFACE_IInArchive(x) \\r
+  STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \\r
+  STDMETHOD(Close)() x; \\r
+  STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \\r
+  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \\r
+  STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \\r
+  STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \\r
+  STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \\r
+  STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \\r
+  STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \\r
+  STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x;\r
+\r
+ARCHIVE_INTERFACE(IInArchive, 0x60)\r
+{\r
+  INTERFACE_IInArchive(PURE)\r
+};\r
+\r
+ARCHIVE_INTERFACE(IArchiveOpenSeq, 0x61)\r
+{\r
+  STDMETHOD(OpenSeq)(ISequentialInStream *stream) PURE;\r
+};\r
+\r
+#define INTERFACE_IArchiveUpdateCallback(x) \\r
+  INTERFACE_IProgress(x); \\r
+  STDMETHOD(GetUpdateItemInfo)(UInt32 index,  \\r
+      Int32 *newData, /*1 - new data, 0 - old data */ \\r
+      Int32 *newProperties, /* 1 - new properties, 0 - old properties */ \\r
+      UInt32 *indexInArchive /* -1 if there is no in archive, or if doesn't matter */ \\r
+      )  x; \\r
+  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \\r
+  STDMETHOD(SetOperationResult)(Int32 operationResult) x; \\r
+\r
+ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80)\r
+{\r
+  INTERFACE_IArchiveUpdateCallback(PURE);\r
+};\r
+\r
+#define INTERFACE_IArchiveUpdateCallback2(x) \\r
+  INTERFACE_IArchiveUpdateCallback(x) \\r
+  STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) x; \\r
+  STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) x; \\r
+\r
+ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82)\r
+{\r
+  INTERFACE_IArchiveUpdateCallback2(PURE);\r
+};\r
+\r
+\r
+#define INTERFACE_IOutArchive(x) \\r
+  STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \\r
+  STDMETHOD(GetFileTimeType)(UInt32 *type) x;\r
+\r
+ARCHIVE_INTERFACE(IOutArchive, 0xA0)\r
+{\r
+  INTERFACE_IOutArchive(PURE)\r
+};\r
+\r
+\r
+ARCHIVE_INTERFACE(ISetProperties, 0x03)\r
+{\r
+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE;\r
+};\r
+\r
+\r
+#define IMP_IInArchive_GetProp(k) \\r
+  (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \\r
+    { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \\r
+    const STATPROPSTG &srcItem = k[index]; \\r
+    *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \\r
+\r
+#define IMP_IInArchive_GetProp_WITH_NAME(k) \\r
+  (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \\r
+    { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \\r
+    const STATPROPSTG &srcItem = k[index]; \\r
+    *propID = srcItem.propid; *varType = srcItem.vt; \\r
+    if (srcItem.lpwstrName == 0) *name = 0; else *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } \\r
+\r
+#define IMP_IInArchive_Props \\r
+  STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \\r
+    { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \\r
+  STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps)\r
+\r
+#define IMP_IInArchive_Props_WITH_NAME \\r
+  STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \\r
+    { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \\r
+  STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps)\r
+\r
+\r
+#define IMP_IInArchive_ArcProps \\r
+  STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \\r
+    { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \\r
+  STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps)\r
+\r
+#define IMP_IInArchive_ArcProps_WITH_NAME \\r
+  STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \\r
+    { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \\r
+  STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps)\r
+\r
+#define IMP_IInArchive_ArcProps_NO_Table \\r
+  STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \\r
+    { *numProperties = 0; return S_OK; } \\r
+  STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \\r
+    { return E_NOTIMPL; } \\r
+\r
+#define IMP_IInArchive_ArcProps_NO \\r
+  IMP_IInArchive_ArcProps_NO_Table \\r
+  STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \\r
+    { value->vt = VT_EMPTY; return S_OK; }\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Icons/7z.ico b/CPP/7zip/Archive/Icons/7z.ico
new file mode 100755 (executable)
index 0000000..319753a
Binary files /dev/null and b/CPP/7zip/Archive/Icons/7z.ico differ
diff --git a/CPP/7zip/Archive/Icons/arj.ico b/CPP/7zip/Archive/Icons/arj.ico
new file mode 100755 (executable)
index 0000000..c0f8b14
Binary files /dev/null and b/CPP/7zip/Archive/Icons/arj.ico differ
diff --git a/CPP/7zip/Archive/Icons/bz2.ico b/CPP/7zip/Archive/Icons/bz2.ico
new file mode 100755 (executable)
index 0000000..614e354
Binary files /dev/null and b/CPP/7zip/Archive/Icons/bz2.ico differ
diff --git a/CPP/7zip/Archive/Icons/cab.ico b/CPP/7zip/Archive/Icons/cab.ico
new file mode 100755 (executable)
index 0000000..cc2007f
Binary files /dev/null and b/CPP/7zip/Archive/Icons/cab.ico differ
diff --git a/CPP/7zip/Archive/Icons/cpio.ico b/CPP/7zip/Archive/Icons/cpio.ico
new file mode 100755 (executable)
index 0000000..9abaabc
Binary files /dev/null and b/CPP/7zip/Archive/Icons/cpio.ico differ
diff --git a/CPP/7zip/Archive/Icons/deb.ico b/CPP/7zip/Archive/Icons/deb.ico
new file mode 100755 (executable)
index 0000000..97a0865
Binary files /dev/null and b/CPP/7zip/Archive/Icons/deb.ico differ
diff --git a/CPP/7zip/Archive/Icons/dmg.ico b/CPP/7zip/Archive/Icons/dmg.ico
new file mode 100755 (executable)
index 0000000..7d63b09
Binary files /dev/null and b/CPP/7zip/Archive/Icons/dmg.ico differ
diff --git a/CPP/7zip/Archive/Icons/fat.ico b/CPP/7zip/Archive/Icons/fat.ico
new file mode 100755 (executable)
index 0000000..882753a
Binary files /dev/null and b/CPP/7zip/Archive/Icons/fat.ico differ
diff --git a/CPP/7zip/Archive/Icons/gz.ico b/CPP/7zip/Archive/Icons/gz.ico
new file mode 100755 (executable)
index 0000000..f50d8c0
Binary files /dev/null and b/CPP/7zip/Archive/Icons/gz.ico differ
diff --git a/CPP/7zip/Archive/Icons/hfs.ico b/CPP/7zip/Archive/Icons/hfs.ico
new file mode 100755 (executable)
index 0000000..92a46b8
Binary files /dev/null and b/CPP/7zip/Archive/Icons/hfs.ico differ
diff --git a/CPP/7zip/Archive/Icons/iso.ico b/CPP/7zip/Archive/Icons/iso.ico
new file mode 100755 (executable)
index 0000000..2538e40
Binary files /dev/null and b/CPP/7zip/Archive/Icons/iso.ico differ
diff --git a/CPP/7zip/Archive/Icons/lzh.ico b/CPP/7zip/Archive/Icons/lzh.ico
new file mode 100755 (executable)
index 0000000..84dab49
Binary files /dev/null and b/CPP/7zip/Archive/Icons/lzh.ico differ
diff --git a/CPP/7zip/Archive/Icons/lzma.ico b/CPP/7zip/Archive/Icons/lzma.ico
new file mode 100755 (executable)
index 0000000..2de2c24
Binary files /dev/null and b/CPP/7zip/Archive/Icons/lzma.ico differ
diff --git a/CPP/7zip/Archive/Icons/ntfs.ico b/CPP/7zip/Archive/Icons/ntfs.ico
new file mode 100755 (executable)
index 0000000..6b2aeb0
Binary files /dev/null and b/CPP/7zip/Archive/Icons/ntfs.ico differ
diff --git a/CPP/7zip/Archive/Icons/rar.ico b/CPP/7zip/Archive/Icons/rar.ico
new file mode 100755 (executable)
index 0000000..2918d29
Binary files /dev/null and b/CPP/7zip/Archive/Icons/rar.ico differ
diff --git a/CPP/7zip/Archive/Icons/rpm.ico b/CPP/7zip/Archive/Icons/rpm.ico
new file mode 100755 (executable)
index 0000000..cdeb8d1
Binary files /dev/null and b/CPP/7zip/Archive/Icons/rpm.ico differ
diff --git a/CPP/7zip/Archive/Icons/split.ico b/CPP/7zip/Archive/Icons/split.ico
new file mode 100755 (executable)
index 0000000..79cb089
Binary files /dev/null and b/CPP/7zip/Archive/Icons/split.ico differ
diff --git a/CPP/7zip/Archive/Icons/squashfs.ico b/CPP/7zip/Archive/Icons/squashfs.ico
new file mode 100755 (executable)
index 0000000..551a743
Binary files /dev/null and b/CPP/7zip/Archive/Icons/squashfs.ico differ
diff --git a/CPP/7zip/Archive/Icons/tar.ico b/CPP/7zip/Archive/Icons/tar.ico
new file mode 100755 (executable)
index 0000000..6835885
Binary files /dev/null and b/CPP/7zip/Archive/Icons/tar.ico differ
diff --git a/CPP/7zip/Archive/Icons/vhd.ico b/CPP/7zip/Archive/Icons/vhd.ico
new file mode 100755 (executable)
index 0000000..33bed3c
Binary files /dev/null and b/CPP/7zip/Archive/Icons/vhd.ico differ
diff --git a/CPP/7zip/Archive/Icons/wim.ico b/CPP/7zip/Archive/Icons/wim.ico
new file mode 100755 (executable)
index 0000000..887975e
Binary files /dev/null and b/CPP/7zip/Archive/Icons/wim.ico differ
diff --git a/CPP/7zip/Archive/Icons/xar.ico b/CPP/7zip/Archive/Icons/xar.ico
new file mode 100755 (executable)
index 0000000..281aa7d
Binary files /dev/null and b/CPP/7zip/Archive/Icons/xar.ico differ
diff --git a/CPP/7zip/Archive/Icons/xz.ico b/CPP/7zip/Archive/Icons/xz.ico
new file mode 100755 (executable)
index 0000000..0270735
Binary files /dev/null and b/CPP/7zip/Archive/Icons/xz.ico differ
diff --git a/CPP/7zip/Archive/Icons/z.ico b/CPP/7zip/Archive/Icons/z.ico
new file mode 100755 (executable)
index 0000000..2db5358
Binary files /dev/null and b/CPP/7zip/Archive/Icons/z.ico differ
diff --git a/CPP/7zip/Archive/Icons/zip.ico b/CPP/7zip/Archive/Icons/zip.ico
new file mode 100755 (executable)
index 0000000..2af4606
Binary files /dev/null and b/CPP/7zip/Archive/Icons/zip.ico differ
diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp
new file mode 100755 (executable)
index 0000000..9f78605
--- /dev/null
@@ -0,0 +1,326 @@
+// IsoHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../../Common/LimitedStreams.h"\r
+#include "../../Common/ProgressUtils.h"\r
+\r
+#include "../../Compress/CopyCoder.h"\r
+\r
+#include "../Common/ItemNameUtils.h"\r
+\r
+#include "IsoHandler.h"\r
+\r
+using namespace NWindows;\r
+using namespace NTime;\r
+\r
+namespace NArchive {\r
+namespace NIso {\r
+\r
+static const STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidIsDir, VT_BOOL},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidMTime, VT_FILETIME}\r
+};\r
+\r
+static const STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidComment, VT_BSTR},\r
+  { NULL, kpidCTime, VT_FILETIME},\r
+  { NULL, kpidMTime, VT_FILETIME}\r
+  // { NULL, kpidPhySize, VT_UI8},\r
+  // { NULL, kpidHeadersSize, VT_UI8}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream,\r
+    const UInt64 * /* maxCheckStartPosition */,\r
+    IArchiveOpenCallback * /* openArchiveCallback */)\r
+{\r
+  COM_TRY_BEGIN\r
+  Close();\r
+  // try\r
+  {\r
+    if (_archive.Open(stream) != S_OK)\r
+      return S_FALSE;\r
+    _stream = stream;\r
+  }\r
+  // catch(...) { return S_FALSE; }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _archive.Clear();\r
+  _stream.Release();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _archive.Refs.Size() + _archive.BootEntries.Size();\r
+  return S_OK;\r
+}\r
+\r
+static void AddString(AString &s, const char *name, const Byte *p, int size)\r
+{\r
+  int i;\r
+  for (i = 0; i < size && p[i]; i++);\r
+  for (; i > 0 && p[i - 1] == ' '; i--);\r
+  if (i != 0)\r
+  {\r
+    AString d;\r
+    memcpy(d.GetBuffer(i), p, i);\r
+    d.ReleaseBuffer(i);\r
+    s += '\n';\r
+    s += name;\r
+    s += ": ";\r
+    s += d;\r
+  }\r
+}\r
+\r
+#define ADD_STRING(n, v) AddString(s, n, vol. ## v, sizeof(vol. ## v))\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  const CVolumeDescriptor &vol = _archive.VolDescs[_archive.MainVolDescIndex];\r
+  switch(propID)\r
+  {\r
+    case kpidComment:\r
+    {\r
+      AString s;\r
+      ADD_STRING("System", SystemId);\r
+      ADD_STRING("Volume", VolumeId);\r
+      ADD_STRING("VolumeSet", VolumeSetId);\r
+      ADD_STRING("Publisher", PublisherId);\r
+      ADD_STRING("Preparer", DataPreparerId);\r
+      ADD_STRING("Application", ApplicationId);\r
+      ADD_STRING("Copyright", CopyrightFileId);\r
+      ADD_STRING("Abstract", AbstractFileId);\r
+      ADD_STRING("Bib", BibFileId);\r
+      prop = s;\r
+      break;\r
+    }\r
+    case kpidCTime: { FILETIME utc; if (vol.CTime.GetFileTime(utc)) prop = utc; break; }\r
+    case kpidMTime: { FILETIME utc; if (vol.MTime.GetFileTime(utc)) prop = utc; break; }\r
+    // case kpidPhySize: break;\r
+    // case kpidHeadersSize: break;\r
+    case kpidError: if (_archive.IncorrectBigEndian) prop = "Incorrect big-endian headers"; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  if (index >= (UInt32)_archive.Refs.Size())\r
+  {\r
+    index -= _archive.Refs.Size();\r
+    const CBootInitialEntry &be = _archive.BootEntries[index];\r
+    switch(propID)\r
+    {\r
+      case kpidPath:\r
+      {\r
+        // wchar_t name[32];\r
+        // ConvertUInt64ToString(index + 1, name);\r
+        UString s = L"[BOOT]" WSTRING_PATH_SEPARATOR;\r
+        // s += name;\r
+        // s += L"-";\r
+        s += be.GetName();\r
+        prop = (const wchar_t *)s;\r
+        break;\r
+      }\r
+      case kpidIsDir: prop = false; break;\r
+      case kpidSize:\r
+      case kpidPackSize:\r
+        prop = (UInt64)_archive.GetBootItemSize(index);\r
+        break;\r
+    }\r
+  }\r
+  else\r
+  {\r
+    const CRef &ref = _archive.Refs[index];\r
+    const CDir &item = ref.Dir->_subItems[ref.Index];\r
+    switch(propID)\r
+    {\r
+      case kpidPath:\r
+        // if (item.FileId.GetCapacity() >= 0)\r
+        {\r
+          UString s;\r
+          if (_archive.IsJoliet())\r
+            s = item.GetPathU();\r
+          else\r
+            s = MultiByteToUnicodeString(item.GetPath(_archive.IsSusp, _archive.SuspSkipSize), CP_OEMCP);\r
+\r
+          int pos = s.ReverseFind(L';');\r
+          if (pos >= 0 && pos == s.Length() - 2)\r
+              if (s[s.Length() - 1] == L'1')\r
+                s = s.Left(pos);\r
+          if (!s.IsEmpty())\r
+            if (s[s.Length() - 1] == L'.')\r
+              s = s.Left(s.Length() - 1);\r
+          prop = (const wchar_t *)NItemName::GetOSName2(s);\r
+        }\r
+        break;\r
+      case kpidIsDir: prop = item.IsDir(); break;\r
+      case kpidSize:\r
+      case kpidPackSize:\r
+        if (!item.IsDir())\r
+          prop = (UInt64)item.DataLength;\r
+        break;\r
+      case kpidMTime:\r
+      {\r
+        FILETIME utc;\r
+        if (item.DateTime.GetFileTime(utc))\r
+          prop = utc;\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _archive.Refs.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt64 totalSize = 0;\r
+  UInt32 i;\r
+  for(i = 0; i < numItems; i++)\r
+  {\r
+    UInt32 index = (allFilesMode ? i : indices[i]);\r
+    if (index < (UInt32)_archive.Refs.Size())\r
+    {\r
+      const CRef &ref = _archive.Refs[index];\r
+      const CDir &item = ref.Dir->_subItems[ref.Index];\r
+      totalSize += item.DataLength;\r
+    }\r
+    else\r
+    {\r
+      totalSize += _archive.GetBootItemSize(index - _archive.Refs.Size());\r
+    }\r
+  }\r
+  extractCallback->SetTotal(totalSize);\r
+\r
+  UInt64 currentTotalSize = 0;\r
+  UInt64 currentItemSize;\r
+  \r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);\r
+  streamSpec->SetStream(_stream);\r
+\r
+  CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream;\r
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\r
+\r
+  for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)\r
+  {\r
+    lps->InSize = lps->OutSize = currentTotalSize;\r
+    RINOK(lps->SetCur());\r
+    currentItemSize = 0;\r
+    CMyComPtr<ISequentialOutStream> realOutStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    UInt32 index = allFilesMode ? i : indices[i];\r
+    \r
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+\r
+    UInt64 blockIndex;\r
+    if (index < (UInt32)_archive.Refs.Size())\r
+    {\r
+      const CRef &ref = _archive.Refs[index];\r
+      const CDir &item = ref.Dir->_subItems[ref.Index];\r
+      if (item.IsDir())\r
+      {\r
+        RINOK(extractCallback->PrepareOperation(askMode));\r
+        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+        continue;\r
+      }\r
+      currentItemSize = item.DataLength;\r
+      blockIndex = item.ExtentLocation;\r
+    }\r
+    else\r
+    {\r
+      int bootIndex = index - _archive.Refs.Size();\r
+      const CBootInitialEntry &be = _archive.BootEntries[bootIndex];\r
+      currentItemSize = _archive.GetBootItemSize(bootIndex);\r
+      blockIndex = be.LoadRBA;\r
+    }\r
+   \r
+    if (!testMode && !realOutStream)\r
+      continue;\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+    outStreamSpec->SetStream(realOutStream);\r
+    realOutStream.Release();\r
+    outStreamSpec->Init(currentItemSize);\r
+    RINOK(_stream->Seek(blockIndex * _archive.BlockSize, STREAM_SEEK_SET, NULL));\r
+    streamSpec->Init(currentItemSize);\r
+    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));\r
+    outStreamSpec->ReleaseStream();\r
+    RINOK(extractCallback->SetOperationResult(outStreamSpec->IsFinishedOK() ?\r
+        NExtract::NOperationResult::kOK:\r
+        NExtract::NOperationResult::kDataError));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)\r
+{\r
+  COM_TRY_BEGIN\r
+  *stream = 0;\r
+  UInt64 blockIndex;\r
+  UInt64 currentItemSize;\r
+  if (index < (UInt32)_archive.Refs.Size())\r
+  {\r
+    const CRef &ref = _archive.Refs[index];\r
+    const CDir &item = ref.Dir->_subItems[ref.Index];\r
+    if (item.IsDir())\r
+      return S_FALSE;\r
+    currentItemSize = item.DataLength;\r
+    blockIndex = item.ExtentLocation;\r
+  }\r
+  else\r
+  {\r
+    int bootIndex = index - _archive.Refs.Size();\r
+    const CBootInitialEntry &be = _archive.BootEntries[bootIndex];\r
+    currentItemSize = _archive.GetBootItemSize(bootIndex);\r
+    blockIndex = be.LoadRBA;\r
+  }\r
+  return CreateLimitedInStream(_stream, blockIndex * _archive.BlockSize, currentItemSize, stream);\r
+  COM_TRY_END\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Iso/IsoHandler.h b/CPP/7zip/Archive/Iso/IsoHandler.h
new file mode 100755 (executable)
index 0000000..29b6472
--- /dev/null
@@ -0,0 +1,30 @@
+// IsoHandler.h\r
+\r
+#ifndef __ISO_HANDLER_H\r
+#define __ISO_HANDLER_H\r
+\r
+#include "Common/MyCom.h"\r
+#include "../IArchive.h"\r
+\r
+#include "IsoIn.h"\r
+#include "IsoItem.h"\r
+\r
+namespace NArchive {\r
+namespace NIso {\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IInArchiveGetStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<IInStream> _stream;\r
+  CInArchive _archive;\r
+public:\r
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Iso/IsoHeader.cpp b/CPP/7zip/Archive/Iso/IsoHeader.cpp
new file mode 100755 (executable)
index 0000000..fa4c8e7
--- /dev/null
@@ -0,0 +1,21 @@
+// Archive/Iso/Header.h\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "IsoHeader.h"\r
+\r
+namespace NArchive {\r
+namespace NIso {\r
+\r
+const char *kElToritoSpec = "EL TORITO SPECIFICATION\0\0\0\0\0\0\0\0\0";\r
+\r
+const wchar_t *kMediaTypes[5] =\r
+{\r
+  L"NoEmulation",\r
+  L"1.2M",\r
+  L"1.44M",\r
+  L"2.88M",\r
+  L"HardDisk"\r
+};\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Iso/IsoHeader.h b/CPP/7zip/Archive/Iso/IsoHeader.h
new file mode 100755 (executable)
index 0000000..bd50666
--- /dev/null
@@ -0,0 +1,61 @@
+// Archive/IsoHeader.h\r
+\r
+#ifndef __ARCHIVE_ISO_HEADER_H\r
+#define __ARCHIVE_ISO_HEADER_H\r
+\r
+#include "Common/Types.h"\r
+\r
+namespace NArchive {\r
+namespace NIso {\r
+\r
+namespace NVolDescType\r
+{\r
+  const Byte kBootRecord = 0;\r
+  const Byte kPrimaryVol = 1;\r
+  const Byte kSupplementaryVol = 2;\r
+  const Byte kVolParttition = 3;\r
+  const Byte kTerminator = 255;\r
+}\r
+\r
+const Byte kVersion = 1;\r
+\r
+namespace NFileFlags\r
+{\r
+  const Byte kDirectory = 1 << 1;\r
+}\r
+\r
+extern const char *kElToritoSpec;\r
+\r
+const UInt32 kStartPos = 0x8000;\r
+\r
+namespace NBootEntryId\r
+{\r
+  const Byte kValidationEntry = 1;\r
+  const Byte kInitialEntryNotBootable = 0;\r
+  const Byte kInitialEntryBootable = 0x88;\r
+}\r
+\r
+namespace NBootPlatformId\r
+{\r
+  const Byte kX86 = 0;\r
+  const Byte kPowerPC = 1;\r
+  const Byte kMac = 2;\r
+}\r
+\r
+const BYTE kBootMediaTypeMask = 0xF;\r
+\r
+namespace NBootMediaType\r
+{\r
+  const Byte kNoEmulation = 0;\r
+  const Byte k1d2Floppy = 1;\r
+  const Byte k1d44Floppy = 2;\r
+  const Byte k2d88Floppy = 3;\r
+  const Byte kHardDisk = 4;\r
+}\r
+\r
+const int kNumBootMediaTypes = 5;\r
+extern const wchar_t *kMediaTypes[];\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp
new file mode 100755 (executable)
index 0000000..400d6ca
--- /dev/null
@@ -0,0 +1,453 @@
+// Archive/IsoIn.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "IsoIn.h"\r
+\r
+#include "../../Common/StreamUtils.h"\r
+\r
+namespace NArchive {\r
+namespace NIso {\r
\r
+Byte CInArchive::ReadByte()\r
+{\r
+  if (m_BufferPos >= BlockSize)\r
+    m_BufferPos = 0;\r
+  if (m_BufferPos == 0)\r
+  {\r
+    size_t processedSize = BlockSize;\r
+    if (ReadStream(_stream, m_Buffer, &processedSize) != S_OK)\r
+      throw 1;\r
+    if (processedSize != BlockSize)\r
+      throw 1;\r
+  }\r
+  Byte b = m_Buffer[m_BufferPos++];\r
+  _position++;\r
+  return b;\r
+}\r
+\r
+void CInArchive::ReadBytes(Byte *data, UInt32 size)\r
+{\r
+  for (UInt32 i = 0; i < size; i++)\r
+    data[i] = ReadByte();\r
+}\r
+\r
+void CInArchive::Skip(size_t size)\r
+{\r
+  while (size-- != 0)\r
+    ReadByte();\r
+}\r
+\r
+void CInArchive::SkipZeros(size_t size)\r
+{\r
+  while (size-- != 0)\r
+  {\r
+    Byte b = ReadByte();\r
+    if (b != 0)\r
+      throw 1;\r
+  }\r
+}\r
+\r
+UInt16 CInArchive::ReadUInt16Spec()\r
+{\r
+  UInt16 value = 0;\r
+  for (int i = 0; i < 2; i++)\r
+    value |= ((UInt16)(ReadByte()) << (8 * i));\r
+  return value;\r
+}\r
+\r
+\r
+UInt16 CInArchive::ReadUInt16()\r
+{\r
+  Byte b[4];\r
+  ReadBytes(b, 4);\r
+  UInt32 value = 0;\r
+  for (int i = 0; i < 2; i++)\r
+  {\r
+    if (b[i] != b[3 - i])\r
+      IncorrectBigEndian = true;\r
+    value |= ((UInt16)(b[i]) << (8 * i));\r
+  }\r
+  return (UInt16)value;\r
+}\r
+\r
+UInt32 CInArchive::ReadUInt32Le()\r
+{\r
+  UInt32 value = 0;\r
+  for (int i = 0; i < 4; i++)\r
+    value |= ((UInt32)(ReadByte()) << (8 * i));\r
+  return value;\r
+}\r
+\r
+UInt32 CInArchive::ReadUInt32Be()\r
+{\r
+  UInt32 value = 0;\r
+  for (int i = 0; i < 4; i++)\r
+  {\r
+    value <<= 8;\r
+    value |= ReadByte();\r
+  }\r
+  return value;\r
+}\r
+\r
+UInt32 CInArchive::ReadUInt32()\r
+{\r
+  Byte b[8];\r
+  ReadBytes(b, 8);\r
+  UInt32 value = 0;\r
+  for (int i = 0; i < 4; i++)\r
+  {\r
+    if (b[i] != b[7 - i])\r
+      throw 1;\r
+    value |= ((UInt32)(b[i]) << (8 * i));\r
+  }\r
+  return value;\r
+}\r
+\r
+UInt32 CInArchive::ReadDigits(int numDigits)\r
+{\r
+  UInt32 res = 0;\r
+  for (int i = 0; i < numDigits; i++)\r
+  {\r
+    Byte b = ReadByte();\r
+    if (b < '0' || b > '9')\r
+    {\r
+      if (b == 0) // it's bug in some CD's\r
+        b = '0';\r
+      else\r
+        throw 1;\r
+    }\r
+    UInt32 d = (UInt32)(b - '0');\r
+    res *= 10;\r
+    res += d;\r
+  }\r
+  return res;\r
+}\r
+\r
+void CInArchive::ReadDateTime(CDateTime &d)\r
+{\r
+  d.Year = (UInt16)ReadDigits(4);\r
+  d.Month = (Byte)ReadDigits(2);\r
+  d.Day = (Byte)ReadDigits(2);\r
+  d.Hour = (Byte)ReadDigits(2);\r
+  d.Minute = (Byte)ReadDigits(2);\r
+  d.Second = (Byte)ReadDigits(2);\r
+  d.Hundredths = (Byte)ReadDigits(2);\r
+  d.GmtOffset = (signed char)ReadByte();\r
+}\r
+\r
+void CInArchive::ReadBootRecordDescriptor(CBootRecordDescriptor &d)\r
+{\r
+  ReadBytes(d.BootSystemId, sizeof(d.BootSystemId));\r
+  ReadBytes(d.BootId, sizeof(d.BootId));\r
+  ReadBytes(d.BootSystemUse, sizeof(d.BootSystemUse));\r
+}\r
+\r
+void CInArchive::ReadRecordingDateTime(CRecordingDateTime &t)\r
+{\r
+  t.Year = ReadByte();\r
+  t.Month = ReadByte();\r
+  t.Day = ReadByte();\r
+  t.Hour = ReadByte();\r
+  t.Minute = ReadByte();\r
+  t.Second = ReadByte();\r
+  t.GmtOffset = (signed char)ReadByte();\r
+}\r
+\r
+void CInArchive::ReadDirRecord2(CDirRecord &r, Byte len)\r
+{\r
+  r.ExtendedAttributeRecordLen = ReadByte();\r
+  if (r.ExtendedAttributeRecordLen != 0)\r
+    throw 1;\r
+  r.ExtentLocation = ReadUInt32();\r
+  r.DataLength = ReadUInt32();\r
+  ReadRecordingDateTime(r.DateTime);\r
+  r.FileFlags = ReadByte();\r
+  r.FileUnitSize = ReadByte();\r
+  r.InterleaveGapSize = ReadByte();\r
+  r.VolSequenceNumber = ReadUInt16();\r
+  Byte idLen = ReadByte();\r
+  r.FileId.SetCapacity(idLen);\r
+  ReadBytes((Byte *)r.FileId, idLen);\r
+  int padSize = 1 - (idLen & 1);\r
+  \r
+  // SkipZeros(1 - (idLen & 1));\r
+  Skip(1 - (idLen & 1)); // it's bug in some cd's. Must be zeros\r
+\r
+  int curPos = 33 + idLen + padSize;\r
+  if (curPos > len)\r
+    throw 1;\r
+  int rem = len - curPos;\r
+  r.SystemUse.SetCapacity(rem);\r
+  ReadBytes((Byte *)r.SystemUse, rem);\r
+}\r
+\r
+void CInArchive::ReadDirRecord(CDirRecord &r)\r
+{\r
+  Byte len = ReadByte();\r
+  // Some CDs can have incorrect value len = 48 ('0') in VolumeDescriptor.\r
+  // But maybe we must use real "len" for other records.\r
+  len = 34;\r
+  ReadDirRecord2(r, len);\r
+}\r
+\r
+void CInArchive::ReadVolumeDescriptor(CVolumeDescriptor &d)\r
+{\r
+  d.VolFlags = ReadByte();\r
+  ReadBytes(d.SystemId, sizeof(d.SystemId));\r
+  ReadBytes(d.VolumeId, sizeof(d.VolumeId));\r
+  SkipZeros(8);\r
+  d.VolumeSpaceSize = ReadUInt32();\r
+  ReadBytes(d.EscapeSequence, sizeof(d.EscapeSequence));\r
+  d.VolumeSetSize = ReadUInt16();\r
+  d.VolumeSequenceNumber = ReadUInt16();\r
+  d.LogicalBlockSize = ReadUInt16();\r
+  d.PathTableSize = ReadUInt32();\r
+  d.LPathTableLocation = ReadUInt32Le();\r
+  d.LOptionalPathTableLocation = ReadUInt32Le();\r
+  d.MPathTableLocation = ReadUInt32Be();\r
+  d.MOptionalPathTableLocation = ReadUInt32Be();\r
+  ReadDirRecord(d.RootDirRecord);\r
+  ReadBytes(d.VolumeSetId, sizeof(d.VolumeSetId));\r
+  ReadBytes(d.PublisherId, sizeof(d.PublisherId));\r
+  ReadBytes(d.DataPreparerId, sizeof(d.DataPreparerId));\r
+  ReadBytes(d.ApplicationId, sizeof(d.ApplicationId));\r
+  ReadBytes(d.CopyrightFileId, sizeof(d.CopyrightFileId));\r
+  ReadBytes(d.AbstractFileId, sizeof(d.AbstractFileId));\r
+  ReadBytes(d.BibFileId, sizeof(d.BibFileId));\r
+  ReadDateTime(d.CTime);\r
+  ReadDateTime(d.MTime);\r
+  ReadDateTime(d.ExpirationTime);\r
+  ReadDateTime(d.EffectiveTime);\r
+  d.FileStructureVersion = ReadByte(); // = 1\r
+  SkipZeros(1);\r
+  ReadBytes(d.ApplicationUse, sizeof(d.ApplicationUse));\r
+  SkipZeros(653);\r
+}\r
+\r
+static const Byte kSig_CD001[5] = { 'C', 'D', '0', '0', '1' };\r
+\r
+static const Byte kSig_NSR02[5] = { 'N', 'S', 'R', '0', '2' };\r
+static const Byte kSig_NSR03[5] = { 'N', 'S', 'R', '0', '3' };\r
+static const Byte kSig_BEA01[5] = { 'B', 'E', 'A', '0', '1' };\r
+static const Byte kSig_TEA01[5] = { 'T', 'E', 'A', '0', '1' };\r
+\r
+static inline bool CheckSignature(const Byte *sig, const Byte *data)\r
+{\r
+  for (int i = 0; i < 5; i++)\r
+    if (sig[i] != data[i])\r
+      return false;\r
+  return true;\r
+}\r
+\r
+void CInArchive::SeekToBlock(UInt32 blockIndex)\r
+{\r
+  if (_stream->Seek((UInt64)blockIndex * VolDescs[MainVolDescIndex].LogicalBlockSize, STREAM_SEEK_SET, &_position) != S_OK)\r
+    throw 1;\r
+  m_BufferPos = 0;\r
+}\r
+\r
+void CInArchive::ReadDir(CDir &d, int level)\r
+{\r
+  if (!d.IsDir())\r
+    return;\r
+  SeekToBlock(d.ExtentLocation);\r
+  UInt64 startPos = _position;\r
+\r
+  bool firstItem = true;\r
+  for (;;)\r
+  {\r
+    UInt64 offset = _position - startPos;\r
+    if (offset >= d.DataLength)\r
+      break;\r
+    Byte len = ReadByte();\r
+    if (len == 0)\r
+      continue;\r
+    CDir subItem;\r
+    ReadDirRecord2(subItem, len);\r
+    if (firstItem && level == 0)\r
+      IsSusp = subItem.CheckSusp(SuspSkipSize);\r
+      \r
+    if (!subItem.IsSystemItem())\r
+      d._subItems.Add(subItem);\r
+\r
+    firstItem = false;\r
+  }\r
+  for (int i = 0; i < d._subItems.Size(); i++)\r
+    ReadDir(d._subItems[i], level + 1);\r
+}\r
+\r
+void CInArchive::CreateRefs(CDir &d)\r
+{\r
+  if (!d.IsDir())\r
+    return;\r
+  for (int i = 0; i < d._subItems.Size(); i++)\r
+  {\r
+    CRef ref;\r
+    CDir &subItem = d._subItems[i];\r
+    subItem.Parent = &d;\r
+    ref.Dir = &d;\r
+    ref.Index = i;\r
+    Refs.Add(ref);\r
+    CreateRefs(subItem);\r
+  }\r
+}\r
+\r
+void CInArchive::ReadBootInfo()\r
+{\r
+  if (!_bootIsDefined)\r
+    return;\r
+  if (memcmp(_bootDesc.BootSystemId, kElToritoSpec, sizeof(_bootDesc.BootSystemId)) != 0)\r
+    return;\r
+  \r
+  const Byte *p = (const Byte *)_bootDesc.BootSystemUse;\r
+  UInt32 blockIndex = p[0] | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16) | ((UInt32)p[3] << 24);\r
+  SeekToBlock(blockIndex);\r
+  Byte b = ReadByte();\r
+  if (b != NBootEntryId::kValidationEntry)\r
+    return;\r
+  {\r
+    CBootValidationEntry e;\r
+    e.PlatformId = ReadByte();\r
+    if (ReadUInt16Spec() != 0)\r
+      throw 1;\r
+    ReadBytes(e.Id, sizeof(e.Id));\r
+    /* UInt16 checkSum = */ ReadUInt16Spec();\r
+    if (ReadByte() != 0x55)\r
+      throw 1;\r
+    if (ReadByte() != 0xAA)\r
+      throw 1;\r
+  }\r
+  b = ReadByte();\r
+  if (b == NBootEntryId::kInitialEntryBootable || b == NBootEntryId::kInitialEntryNotBootable)\r
+  {\r
+    CBootInitialEntry e;\r
+    e.Bootable = (b == NBootEntryId::kInitialEntryBootable);\r
+    e.BootMediaType = ReadByte();\r
+    e.LoadSegment = ReadUInt16Spec();\r
+    e.SystemType = ReadByte();\r
+    if (ReadByte() != 0)\r
+      throw 1;\r
+    e.SectorCount = ReadUInt16Spec();\r
+    e.LoadRBA = ReadUInt32Le();\r
+    if (ReadByte() != 0)\r
+      throw 1;\r
+    BootEntries.Add(e);\r
+  }\r
+  else\r
+    return;\r
+}\r
+\r
+HRESULT CInArchive::Open2()\r
+{\r
+  Clear();\r
+  RINOK(_stream->Seek(kStartPos, STREAM_SEEK_CUR, &_position));\r
+\r
+  m_BufferPos = 0;\r
+  BlockSize = kBlockSize;\r
+  for (;;)\r
+  {\r
+    Byte sig[7];\r
+    ReadBytes(sig, 7);\r
+    Byte ver = sig[6];\r
+    if (!CheckSignature(kSig_CD001, sig + 1))\r
+    {\r
+      return S_FALSE;\r
+      /*\r
+      if (sig[0] != 0 || ver != 1)\r
+        break;\r
+      if (CheckSignature(kSig_BEA01, sig + 1))\r
+      {\r
+      }\r
+      else if (CheckSignature(kSig_TEA01, sig + 1))\r
+      {\r
+        break;\r
+      }\r
+      else if (CheckSignature(kSig_NSR02, sig + 1))\r
+      {\r
+      }\r
+      else\r
+        break;\r
+      SkipZeros(0x800 - 7);\r
+      continue;\r
+      */\r
+    }\r
+    // version = 2 for ISO 9660:1999?\r
+    if (ver > 2)\r
+      throw S_FALSE;\r
+\r
+    if (sig[0] == NVolDescType::kTerminator)\r
+    {\r
+      break;\r
+      // Skip(0x800 - 7);\r
+      // continue;\r
+    }\r
+    switch(sig[0])\r
+    {\r
+      case NVolDescType::kBootRecord:\r
+      {\r
+        _bootIsDefined = true;\r
+        ReadBootRecordDescriptor(_bootDesc);\r
+        break;\r
+      }\r
+      case NVolDescType::kPrimaryVol:\r
+      case NVolDescType::kSupplementaryVol:\r
+      {\r
+        // some ISOs have two PrimaryVols.\r
+        CVolumeDescriptor vd;\r
+        ReadVolumeDescriptor(vd);\r
+        if (sig[0] == NVolDescType::kPrimaryVol)\r
+        {\r
+          // some burners write "Joliet" Escape Sequence to primary volume\r
+          memset(vd.EscapeSequence, 0, sizeof(vd.EscapeSequence));\r
+        }\r
+        VolDescs.Add(vd);\r
+        break;\r
+      }\r
+      default:\r
+        break;\r
+    }\r
+  }\r
+  if (VolDescs.IsEmpty())\r
+    return S_FALSE;\r
+  for (MainVolDescIndex = VolDescs.Size() - 1; MainVolDescIndex > 0; MainVolDescIndex--)\r
+    if (VolDescs[MainVolDescIndex].IsJoliet())\r
+      break;\r
+  // MainVolDescIndex = 0; // to read primary volume\r
+  const CVolumeDescriptor &vd = VolDescs[MainVolDescIndex];\r
+  if (vd.LogicalBlockSize != kBlockSize)\r
+    return S_FALSE;\r
+  (CDirRecord &)_rootDir = vd.RootDirRecord;\r
+  ReadDir(_rootDir, 0);\r
+  CreateRefs(_rootDir);\r
+  ReadBootInfo();\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::Open(IInStream *inStream)\r
+{\r
+  _stream = inStream;\r
+  UInt64 pos;\r
+  RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &pos));\r
+  RINOK(_stream->Seek(0, STREAM_SEEK_END, &_archiveSize));\r
+  RINOK(_stream->Seek(pos, STREAM_SEEK_SET, &_position));\r
+  HRESULT res = S_FALSE;\r
+  try { res = Open2(); }\r
+  catch(...) { Clear(); res = S_FALSE; }\r
+  _stream.Release();\r
+  return res;\r
+}\r
+\r
+void CInArchive::Clear()\r
+{\r
+  IncorrectBigEndian = false;\r
+  Refs.Clear();\r
+  _rootDir.Clear();\r
+  VolDescs.Clear();\r
+  _bootIsDefined = false;\r
+  BootEntries.Clear();\r
+  SuspSkipSize = 0;\r
+  IsSusp = false;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Iso/IsoIn.h b/CPP/7zip/Archive/Iso/IsoIn.h
new file mode 100755 (executable)
index 0000000..38908ca
--- /dev/null
@@ -0,0 +1,315 @@
+// Archive/IsoIn.h\r
+\r
+#ifndef __ARCHIVE_ISO_IN_H\r
+#define __ARCHIVE_ISO_IN_H\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/MyCom.h"\r
+\r
+#include "../../IStream.h"\r
+\r
+#include "IsoHeader.h"\r
+#include "IsoItem.h"\r
+\r
+namespace NArchive {\r
+namespace NIso {\r
+\r
+struct CDir: public CDirRecord\r
+{\r
+  CDir *Parent;\r
+  CObjectVector<CDir> _subItems;\r
+\r
+  void Clear()\r
+  {\r
+    Parent = 0;\r
+    _subItems.Clear();\r
+  }\r
+  \r
+  int GetLength(bool checkSusp, int skipSize) const\r
+  {\r
+    int len = GetLengthCur(checkSusp, skipSize);\r
+    if (Parent != 0)\r
+      if (Parent->Parent != 0)\r
+        len += 1 + Parent->GetLength(checkSusp, skipSize);\r
+    return len;\r
+  }\r
+\r
+  int GetLengthU() const\r
+  {\r
+    int len = (int)(FileId.GetCapacity() / 2);\r
+    if (Parent != 0)\r
+      if (Parent->Parent != 0)\r
+        len += 1 + Parent->GetLengthU();\r
+    return len;\r
+  }\r
+  \r
+  AString GetPath(bool checkSusp, int skipSize) const\r
+  {\r
+    AString s;\r
+    int len = GetLength(checkSusp, skipSize);\r
+    char *p = s.GetBuffer(len +  1);\r
+    p += len;\r
+    *p = 0;\r
+    const CDir *cur = this;\r
+    for (;;)\r
+    {\r
+      int curLen = cur->GetLengthCur(checkSusp, skipSize);\r
+      p -= curLen;\r
+      memmove(p, (const char *)(const Byte *)cur->GetNameCur(checkSusp, skipSize), curLen);\r
+      cur = cur->Parent;\r
+      if (cur == 0)\r
+        break;\r
+      if (cur->Parent == 0)\r
+        break;\r
+      p--;\r
+      *p = CHAR_PATH_SEPARATOR;\r
+    }\r
+    s.ReleaseBuffer();\r
+    return s;\r
+  }\r
+\r
+  UString GetPathU() const\r
+  {\r
+    UString s;\r
+    int len = GetLengthU();\r
+    wchar_t *p = s.GetBuffer(len +  1);\r
+    p += len;\r
+    *p = 0;\r
+    const CDir *cur = this;\r
+    for (;;)\r
+    {\r
+      int curLen = (int)(cur->FileId.GetCapacity() / 2);\r
+      p -= curLen;\r
+      for (int i = 0; i < curLen; i++)\r
+      {\r
+        Byte b0 = ((const Byte *)cur->FileId)[i * 2];\r
+        Byte b1 = ((const Byte *)cur->FileId)[i * 2 + 1];\r
+        p[i] = (wchar_t)(((wchar_t)b0 << 8) | b1);\r
+      }\r
+      cur = cur->Parent;\r
+      if (cur == 0)\r
+        break;\r
+      if (cur->Parent == 0)\r
+        break;\r
+      p--;\r
+      *p = WCHAR_PATH_SEPARATOR;\r
+    }\r
+    s.ReleaseBuffer();\r
+    return s;\r
+  }\r
+};\r
+\r
+struct CDateTime\r
+{\r
+  UInt16 Year;\r
+  Byte Month;\r
+  Byte Day;\r
+  Byte Hour;\r
+  Byte Minute;\r
+  Byte Second;\r
+  Byte Hundredths;\r
+  signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded.\r
+  bool NotSpecified() const { return Year == 0 && Month == 0 && Day == 0 &&\r
+      Hour == 0 && Minute == 0 && Second == 0 && GmtOffset == 0; }\r
+\r
+  bool GetFileTime(FILETIME &ft) const\r
+  {\r
+    UInt64 value;\r
+    bool res = NWindows::NTime::GetSecondsSince1601(Year, Month, Day, Hour, Minute, Second, value);\r
+    if (res)\r
+    {\r
+      value -= (UInt64)((Int64)GmtOffset * 15 * 60);\r
+      value *= 10000000;\r
+    }\r
+    ft.dwLowDateTime = (DWORD)value;\r
+    ft.dwHighDateTime = (DWORD)(value >> 32);\r
+    return res;\r
+  }\r
+};\r
+\r
+struct CBootRecordDescriptor\r
+{\r
+  Byte BootSystemId[32];  // a-characters\r
+  Byte BootId[32];        // a-characters\r
+  Byte BootSystemUse[1977];\r
+};\r
+\r
+struct CBootValidationEntry\r
+{\r
+  Byte PlatformId;\r
+  Byte Id[24]; // to identify the manufacturer/developer of the CD-ROM.\r
+};\r
+\r
+struct CBootInitialEntry\r
+{\r
+  bool Bootable;\r
+  Byte BootMediaType;\r
+  UInt16 LoadSegment;\r
+  /* This is the load segment for the initial boot image. If this\r
+     value is 0 the system will use the traditional segment of 7C0. If this value\r
+     is non-zero the system will use the specified segment. This applies to x86\r
+     architectures only. For "flat" model architectures (such as Motorola) this\r
+     is the address divided by 10. */\r
+  Byte SystemType;    // This must be a copy of byte 5 (System Type) from the\r
+                      // Partition Table found in the boot image.\r
+  UInt16 SectorCount; // This is the number of virtual/emulated sectors the system\r
+                      // will store at Load Segment during the initial boot procedure.\r
+  UInt32 LoadRBA;     // This is the start address of the virtual disk. CD\92s use\r
+                      // Relative/Logical block addressing.\r
+\r
+  UInt64 GetSize() const\r
+  {\r
+    // if (BootMediaType == NBootMediaType::k1d44Floppy) (1440 << 10);\r
+    return SectorCount * 512;\r
+  }\r
+\r
+  UString GetName() const\r
+  {\r
+    UString s;\r
+    if (Bootable)\r
+      s += L"Bootable";\r
+    else\r
+      s += L"NotBootable";\r
+    s += L"_";\r
+    if (BootMediaType >= kNumBootMediaTypes)\r
+    {\r
+      wchar_t name[16];\r
+      ConvertUInt32ToString(BootMediaType, name);\r
+      s += name;\r
+    }\r
+    else\r
+      s += kMediaTypes[BootMediaType];\r
+    s += L".img";\r
+    return s;\r
+  }\r
+};\r
+\r
+struct CVolumeDescriptor\r
+{\r
+  Byte VolFlags;\r
+  Byte SystemId[32]; // a-characters. An identification of a system\r
+                     // which can recognize and act upon the content of the Logical\r
+                     // Sectors with logical Sector Numbers 0 to 15 of the volume.\r
+  Byte VolumeId[32]; // d-characters. An identification of the volume.\r
+  UInt32 VolumeSpaceSize; // the number of Logical Blocks in which the Volume Space of the volume is recorded\r
+  Byte EscapeSequence[32];\r
+  UInt16 VolumeSetSize;\r
+  UInt16 VolumeSequenceNumber; // the ordinal number of the volume in the Volume Set of which the volume is a member.\r
+  UInt16 LogicalBlockSize;\r
+  UInt32 PathTableSize;\r
+  UInt32 LPathTableLocation;\r
+  UInt32 LOptionalPathTableLocation;\r
+  UInt32 MPathTableLocation;\r
+  UInt32 MOptionalPathTableLocation;\r
+  CDirRecord RootDirRecord;\r
+  Byte VolumeSetId[128];\r
+  Byte PublisherId[128];\r
+  Byte DataPreparerId[128];\r
+  Byte ApplicationId[128];\r
+  Byte CopyrightFileId[37];\r
+  Byte AbstractFileId[37];\r
+  Byte BibFileId[37];\r
+  CDateTime CTime;\r
+  CDateTime MTime;\r
+  CDateTime ExpirationTime;\r
+  CDateTime EffectiveTime;\r
+  Byte FileStructureVersion; // = 1;\r
+  Byte ApplicationUse[512];\r
+\r
+  bool IsJoliet() const\r
+  {\r
+    if ((VolFlags & 1) != 0)\r
+      return false;\r
+    Byte b = EscapeSequence[2];\r
+    return (EscapeSequence[0] == 0x25 && EscapeSequence[1] == 0x2F &&\r
+      (b == 0x40 || b == 0x43 || b == 0x45));\r
+  }\r
+};\r
+\r
+struct CRef\r
+{\r
+  CDir *Dir;\r
+  UInt32 Index;\r
+};\r
+\r
+const UInt32 kBlockSize = 1 << 11;\r
+\r
+class CInArchive\r
+{\r
+  CMyComPtr<IInStream> _stream;\r
+  UInt64 _position;\r
+\r
+  Byte m_Buffer[kBlockSize];\r
+  UInt32 m_BufferPos;\r
+  \r
+  CDir _rootDir;\r
+  bool _bootIsDefined;\r
+  CBootRecordDescriptor _bootDesc;\r
+\r
+  void Skip(size_t size);\r
+  void SkipZeros(size_t size);\r
+  Byte ReadByte();\r
+  void ReadBytes(Byte *data, UInt32 size);\r
+  UInt16 ReadUInt16Spec();\r
+  UInt16 ReadUInt16();\r
+  UInt32 ReadUInt32Le();\r
+  UInt32 ReadUInt32Be();\r
+  UInt32 ReadUInt32();\r
+  UInt64 ReadUInt64();\r
+  UInt32 ReadDigits(int numDigits);\r
+  void ReadDateTime(CDateTime &d);\r
+  void ReadRecordingDateTime(CRecordingDateTime &t);\r
+  void ReadDirRecord2(CDirRecord &r, Byte len);\r
+  void ReadDirRecord(CDirRecord &r);\r
+\r
+  void ReadBootRecordDescriptor(CBootRecordDescriptor &d);\r
+  void ReadVolumeDescriptor(CVolumeDescriptor &d);\r
+\r
+  void SeekToBlock(UInt32 blockIndex);\r
+  void ReadDir(CDir &d, int level);\r
+  void CreateRefs(CDir &d);\r
+\r
+  void ReadBootInfo();\r
+  HRESULT Open2();\r
+public:\r
+  HRESULT Open(IInStream *inStream);\r
+  void Clear();\r
+\r
+  UInt64 _archiveSize;\r
+\r
+  CRecordVector<CRef> Refs;\r
+  CObjectVector<CVolumeDescriptor> VolDescs;\r
+  int MainVolDescIndex;\r
+  UInt32 BlockSize;\r
+  CObjectVector<CBootInitialEntry> BootEntries;\r
+  bool IncorrectBigEndian;\r
+\r
+\r
+  bool IsJoliet() const { return VolDescs[MainVolDescIndex].IsJoliet(); }\r
+\r
+  UInt64 GetBootItemSize(int index) const\r
+  {\r
+    const CBootInitialEntry &be = BootEntries[index];\r
+    UInt64 size = be.GetSize();\r
+    if (be.BootMediaType == NBootMediaType::k1d2Floppy)\r
+      size = (1200 << 10);\r
+    else if (be.BootMediaType == NBootMediaType::k1d44Floppy)\r
+      size = (1440 << 10);\r
+    else if (be.BootMediaType == NBootMediaType::k2d88Floppy)\r
+      size = (2880 << 10);\r
+    UInt64 startPos = be.LoadRBA * BlockSize;\r
+    if (startPos < _archiveSize)\r
+    {\r
+      if (_archiveSize - startPos < size)\r
+        size = _archiveSize - startPos;\r
+    }\r
+    return size;\r
+  }\r
+\r
+  bool IsSusp;\r
+  int SuspSkipSize;\r
+};\r
+  \r
+}}\r
+  \r
+#endif\r
diff --git a/CPP/7zip/Archive/Iso/IsoItem.h b/CPP/7zip/Archive/Iso/IsoItem.h
new file mode 100755 (executable)
index 0000000..7788974
--- /dev/null
@@ -0,0 +1,141 @@
+// Archive/IsoItem.h\r
+\r
+#ifndef __ARCHIVE_ISO_ITEM_H\r
+#define __ARCHIVE_ISO_ITEM_H\r
+\r
+#include "Common/Types.h"\r
+#include "Common/MyString.h"\r
+#include "Common/Buffer.h"\r
+\r
+#include "Windows/Time.h"\r
+\r
+#include "IsoHeader.h"\r
+\r
+namespace NArchive {\r
+namespace NIso {\r
+\r
+struct CRecordingDateTime\r
+{\r
+  Byte Year;\r
+  Byte Month;\r
+  Byte Day;\r
+  Byte Hour;\r
+  Byte Minute;\r
+  Byte Second;\r
+  signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded.\r
+  \r
+  bool GetFileTime(FILETIME &ft) const\r
+  {\r
+    UInt64 value;\r
+    bool res = NWindows::NTime::GetSecondsSince1601(Year + 1900, Month, Day, Hour, Minute, Second, value);\r
+    if (res)\r
+    {\r
+      value -= (UInt64)((Int64)GmtOffset * 15 * 60);\r
+      value *= 10000000;\r
+    }\r
+    ft.dwLowDateTime = (DWORD)value;\r
+    ft.dwHighDateTime = (DWORD)(value >> 32);\r
+    return res;\r
+  }\r
+};\r
+\r
+struct CDirRecord\r
+{\r
+  Byte ExtendedAttributeRecordLen;\r
+  UInt32 ExtentLocation;\r
+  UInt32 DataLength;\r
+  CRecordingDateTime DateTime;\r
+  Byte FileFlags;\r
+  Byte FileUnitSize;\r
+  Byte InterleaveGapSize;\r
+  UInt16 VolSequenceNumber;\r
+  CByteBuffer FileId;\r
+  CByteBuffer SystemUse;\r
+\r
+  bool IsDir() const { return  (FileFlags & NFileFlags::kDirectory) != 0; }\r
+  bool IsSystemItem() const\r
+  {\r
+    if (FileId.GetCapacity() != 1)\r
+      return false;\r
+    Byte b = *(const Byte *)FileId;\r
+    return (b == 0 || b == 1);\r
+  }\r
+\r
+  const Byte* FindSuspName(int skipSize, int &lenRes) const\r
+  {\r
+    lenRes = 0;\r
+    const Byte *p = (const Byte *)SystemUse + skipSize;\r
+    int length = (int)(SystemUse.GetCapacity() - skipSize);\r
+    while (length >= 5)\r
+    {\r
+      int len = p[2];\r
+      if (p[0] == 'N' && p[1] == 'M' && p[3] == 1)\r
+      {\r
+        lenRes = len - 5;\r
+        return p + 5;\r
+      }\r
+      p += len;\r
+      length -= len;\r
+    }\r
+    return 0;\r
+  }\r
+\r
+  int GetLengthCur(bool checkSusp, int skipSize) const\r
+  {\r
+    if (checkSusp)\r
+    {\r
+      int len;\r
+      const Byte *res = FindSuspName(skipSize, len);\r
+      if (res != 0)\r
+        return len;\r
+    }\r
+    return (int)FileId.GetCapacity();\r
+  }\r
+\r
+  const Byte* GetNameCur(bool checkSusp, int skipSize) const\r
+  {\r
+    if (checkSusp)\r
+    {\r
+      int len;\r
+      const Byte *res = FindSuspName(skipSize, len);\r
+      if (res != 0)\r
+        return res;\r
+    }\r
+    return (const Byte *)FileId;\r
+  }\r
+\r
+\r
+  bool CheckSusp(const Byte *p, int &startPos) const\r
+  {\r
+    if (p[0] == 'S' &&\r
+        p[1] == 'P' &&\r
+        p[2] == 0x7 &&\r
+        p[3] == 0x1 &&\r
+        p[4] == 0xBE &&\r
+        p[5] == 0xEF)\r
+    {\r
+      startPos = p[6];\r
+      return true;\r
+    }\r
+    return false;\r
+  }\r
+\r
+  bool CheckSusp(int &startPos) const\r
+  {\r
+    const Byte *p = (const Byte *)SystemUse;\r
+    int length = (int)SystemUse.GetCapacity();\r
+    const int kMinLen = 7;\r
+    if (length < kMinLen)\r
+      return false;\r
+    if (CheckSusp(p, startPos))\r
+      return true;\r
+    const int kOffset2 = 14;\r
+    if (length < kOffset2 + kMinLen)\r
+      return false;\r
+    return CheckSusp(p + kOffset2, startPos);\r
+  }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Iso/IsoRegister.cpp b/CPP/7zip/Archive/Iso/IsoRegister.cpp
new file mode 100755 (executable)
index 0000000..e6e8ade
--- /dev/null
@@ -0,0 +1,13 @@
+// IsoRegister.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/RegisterArc.h"\r
+\r
+#include "IsoHandler.h"\r
+static IInArchive *CreateArc() { return new NArchive::NIso::CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"Iso", L"iso img", 0, 0xE7, { 'C', 'D', '0', '0', '1', 0x1 }, 7, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Iso)\r
diff --git a/CPP/7zip/Archive/Iso/StdAfx.h b/CPP/7zip/Archive/Iso/StdAfx.h
new file mode 100755 (executable)
index 0000000..a4e6173
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+#include "../../../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/LzhHandler.cpp b/CPP/7zip/Archive/LzhHandler.cpp
new file mode 100755 (executable)
index 0000000..ce09b6a
--- /dev/null
@@ -0,0 +1,775 @@
+// LzhHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/Buffer.h"\r
+#include "Common/ComTry.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "../Common/LimitedStreams.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/CopyCoder.h"\r
+#include "../Compress/LzhDecoder.h"\r
+\r
+#include "IArchive.h"\r
+\r
+#include "Common/ItemNameUtils.h"\r
+\r
+using namespace NWindows;\r
+using namespace NTime;\r
+\r
+#define Get16(p) GetUi16(p)\r
+#define Get32(p) GetUi32(p)\r
+\r
+namespace NArchive {\r
+namespace NLzh{\r
+\r
+const int kMethodIdSize = 5;\r
+\r
+const Byte kExtIdFileName = 0x01;\r
+const Byte kExtIdDirName  = 0x02;\r
+const Byte kExtIdUnixTime = 0x54;\r
+\r
+struct CExtension\r
+{\r
+  Byte Type;\r
+  CByteBuffer Data;\r
+  AString GetString() const\r
+  {\r
+    AString s;\r
+    for (size_t i = 0; i < Data.GetCapacity(); i++)\r
+    {\r
+      char c = (char)Data[i];\r
+      if (c == 0)\r
+        break;\r
+      s += c;\r
+    }\r
+    return s;\r
+  }\r
+};\r
+\r
+struct CItem\r
+{\r
+  AString Name;\r
+  Byte Method[kMethodIdSize];\r
+  Byte Attributes;\r
+  Byte Level;\r
+  Byte OsId;\r
+  UInt32 PackSize;\r
+  UInt32 Size;\r
+  UInt32 ModifiedTime;\r
+  UInt16 CRC;\r
+  CObjectVector<CExtension> Extensions;\r
+\r
+  bool IsValidMethod() const  { return (Method[0] == '-' && Method[1] == 'l' && Method[4] == '-'); }\r
+  bool IsLhMethod() const  {return (IsValidMethod() && Method[2] == 'h'); }\r
+  bool IsDir() const {return (IsLhMethod() && Method[3] == 'd'); }\r
+\r
+  bool IsCopyMethod() const\r
+  {\r
+    return (IsLhMethod() && Method[3] == '0') ||\r
+      (IsValidMethod() && Method[2] == 'z' && Method[3] == '4');\r
+  }\r
+  \r
+  bool IsLh1GroupMethod() const\r
+  {\r
+    if (!IsLhMethod())\r
+      return false;\r
+    switch(Method[3])\r
+    {\r
+      case '1':\r
+        return true;\r
+    }\r
+    return false;\r
+  }\r
+  \r
+  bool IsLh4GroupMethod() const\r
+  {\r
+    if (!IsLhMethod())\r
+      return false;\r
+    switch(Method[3])\r
+    {\r
+      case '4':\r
+      case '5':\r
+      case '6':\r
+      case '7':\r
+        return true;\r
+    }\r
+    return false;\r
+  }\r
+  \r
+  int GetNumDictBits() const\r
+  {\r
+    if (!IsLhMethod())\r
+      return 0;\r
+    switch(Method[3])\r
+    {\r
+      case '1': return 12;\r
+      case '2': return 13;\r
+      case '3': return 13;\r
+      case '4': return 12;\r
+      case '5': return 13;\r
+      case '6': return 15;\r
+      case '7': return 16;\r
+    }\r
+    return 0;\r
+  }\r
+\r
+  int FindExt(Byte type) const\r
+  {\r
+    for (int i = 0; i < Extensions.Size(); i++)\r
+      if (Extensions[i].Type == type)\r
+        return i;\r
+    return -1;\r
+  }\r
+  bool GetUnixTime(UInt32 &value) const\r
+  {\r
+    int index = FindExt(kExtIdUnixTime);\r
+    if (index < 0)\r
+    {\r
+      if (Level == 2)\r
+      {\r
+        value = ModifiedTime;\r
+        return true;\r
+      }\r
+      return false;\r
+    }\r
+    const Byte *data = (const Byte *)(Extensions[index].Data);\r
+    value = GetUi32(data);\r
+    return true;\r
+  }\r
+\r
+  AString GetDirName() const\r
+  {\r
+    int index = FindExt(kExtIdDirName);\r
+    if (index < 0)\r
+      return AString();\r
+    return Extensions[index].GetString();\r
+  }\r
+\r
+  AString GetFileName() const\r
+  {\r
+    int index = FindExt(kExtIdFileName);\r
+    if (index < 0)\r
+      return Name;\r
+    return Extensions[index].GetString();\r
+  }\r
+\r
+  AString GetName() const\r
+  {\r
+    AString dirName = GetDirName();\r
+    const char kDirSeparator = '\\';\r
+    // check kDirSeparator in Linux\r
+    dirName.Replace((char)(unsigned char)0xFF, kDirSeparator);\r
+    if (!dirName.IsEmpty() && dirName.Back() != kDirSeparator)\r
+      dirName += kDirSeparator;\r
+    return dirName + GetFileName();\r
+  }\r
+};\r
+\r
+struct CItemEx: public CItem\r
+{\r
+  UInt64 DataPosition;\r
+};\r
+\r
+class CInArchive\r
+{\r
+  CMyComPtr<IInStream> m_Stream;\r
+  UInt64 m_Position;\r
+  \r
+  HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize);\r
+  HRESULT CheckReadBytes(void *data, UInt32 size);\r
+public:\r
+  HRESULT Open(IInStream *inStream);\r
+  HRESULT GetNextItem(bool &filled, CItemEx &itemInfo);\r
+  HRESULT Skip(UInt64 numBytes);\r
+};\r
+\r
+HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize)\r
+{\r
+  size_t realProcessedSize = size;\r
+  RINOK(ReadStream(m_Stream, data, &realProcessedSize));\r
+  processedSize = (UInt32)realProcessedSize;\r
+  m_Position += processedSize;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::CheckReadBytes(void *data, UInt32 size)\r
+{\r
+  UInt32 processedSize;\r
+  RINOK(ReadBytes(data, size, processedSize));\r
+  return (processedSize == size) ? S_OK: S_FALSE;\r
+}\r
+\r
+HRESULT CInArchive::Open(IInStream *inStream)\r
+{\r
+  RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position));\r
+  m_Stream = inStream;\r
+  return S_OK;\r
+}\r
+\r
+static const Byte *ReadUInt16(const Byte *p, UInt16 &v)\r
+{\r
+  v = Get16(p);\r
+  return p + 2;\r
+}\r
+\r
+static const Byte *ReadString(const Byte *p, size_t size, AString &s)\r
+{\r
+  s.Empty();\r
+  for (size_t i = 0; i < size; i++)\r
+  {\r
+    char c = p[i];\r
+    if (c == 0)\r
+      break;\r
+    s += c;\r
+  }\r
+  return p + size;\r
+}\r
+\r
+static Byte CalcSum(const Byte *data, size_t size)\r
+{\r
+  Byte sum = 0;\r
+  for (size_t i = 0; i < size; i++)\r
+    sum = (Byte)(sum + data[i]);\r
+  return sum;\r
+}\r
+\r
+HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)\r
+{\r
+  filled = false;\r
+\r
+  UInt32 processedSize;\r
+  Byte startHeader[2];\r
+  RINOK(ReadBytes(startHeader, 2, processedSize))\r
+  if (processedSize == 0)\r
+    return S_OK;\r
+  if (processedSize == 1)\r
+    return (startHeader[0] == 0) ? S_OK: S_FALSE;\r
+  if (startHeader[0] == 0 && startHeader[1] == 0)\r
+    return S_OK;\r
+\r
+  Byte header[256];\r
+  const UInt32 kBasicPartSize = 22;\r
+  RINOK(ReadBytes(header, kBasicPartSize, processedSize));\r
+  if (processedSize != kBasicPartSize)\r
+    return (startHeader[0] == 0) ? S_OK: S_FALSE;\r
+\r
+  const Byte *p = header;\r
+  memcpy(item.Method, p, kMethodIdSize);\r
+  if (!item.IsValidMethod())\r
+    return S_OK;\r
+  p += kMethodIdSize;\r
+  item.PackSize = Get32(p);\r
+  item.Size = Get32(p + 4);\r
+  item.ModifiedTime = Get32(p + 8);\r
+  item.Attributes = p[12];\r
+  item.Level = p[13];\r
+  p += 14;\r
+  if (item.Level > 2)\r
+    return S_FALSE;\r
+  UInt32 headerSize;\r
+  if (item.Level < 2)\r
+  {\r
+    headerSize = startHeader[0];\r
+    if (headerSize < kBasicPartSize)\r
+      return S_FALSE;\r
+    UInt32 remain = headerSize - kBasicPartSize;\r
+    RINOK(CheckReadBytes(header + kBasicPartSize, remain));\r
+    if (startHeader[1] != CalcSum(header, headerSize))\r
+      return S_FALSE;\r
+    size_t nameLength = *p++;\r
+    if ((p - header) + nameLength + 2 > headerSize)\r
+      return S_FALSE;\r
+    p = ReadString(p, nameLength, item.Name);\r
+  }\r
+  else\r
+   headerSize = startHeader[0] | ((UInt32)startHeader[1] << 8);\r
+  p = ReadUInt16(p, item.CRC);\r
+  if (item.Level != 0)\r
+  {\r
+    if (item.Level == 2)\r
+    {\r
+      RINOK(CheckReadBytes(header + kBasicPartSize, 2));\r
+    }\r
+    if ((size_t)(p - header) + 3 > headerSize)\r
+      return S_FALSE;\r
+    item.OsId = *p++;\r
+    UInt16 nextSize;\r
+    p = ReadUInt16(p, nextSize);\r
+    while (nextSize != 0)\r
+    {\r
+      if (nextSize < 3)\r
+        return S_FALSE;\r
+      if (item.Level == 1)\r
+      {\r
+        if (item.PackSize < nextSize)\r
+          return S_FALSE;\r
+        item.PackSize -= nextSize;\r
+      }\r
+      CExtension ext;\r
+      RINOK(CheckReadBytes(&ext.Type, 1))\r
+      nextSize -= 3;\r
+      ext.Data.SetCapacity(nextSize);\r
+      RINOK(CheckReadBytes((Byte *)ext.Data, nextSize))\r
+      item.Extensions.Add(ext);\r
+      Byte hdr2[2];\r
+      RINOK(CheckReadBytes(hdr2, 2));\r
+      ReadUInt16(hdr2, nextSize);\r
+    }\r
+  }\r
+  item.DataPosition = m_Position;\r
+  filled = true;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::Skip(UInt64 numBytes)\r
+{\r
+  UInt64 newPostion;\r
+  RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion));\r
+  m_Position += numBytes;\r
+  if (m_Position != newPostion)\r
+    return E_FAIL;\r
+  return S_OK;\r
+}\r
+\r
+struct COsPair\r
+{\r
+  Byte Id;\r
+  const char *Name;\r
+};\r
+\r
+static COsPair g_OsPairs[] =\r
+{\r
+  {   0, "MS-DOS" },\r
+  { 'M', "MS-DOS" },\r
+  { '2', "OS/2" },\r
+  { '9', "OS9" },\r
+  { 'K', "OS/68K" },\r
+  { '3', "OS/386" },\r
+  { 'H', "HUMAN" },\r
+  { 'U', "UNIX" },\r
+  { 'C', "CP/M" },\r
+  { 'F', "FLEX" },\r
+  { 'm', "Mac" },\r
+  { 'R', "Runser" },\r
+  { 'T', "TownsOS" },\r
+  { 'X', "XOSK" },\r
+  { 'w', "Windows 95" },\r
+  { 'W', "Windows NT" },\r
+  { 'J', "Java VM" }\r
+};\r
+\r
+static const char *kUnknownOS = "Unknown";\r
+\r
+static const char *GetOS(Byte osId)\r
+{\r
+  for (int i = 0; i < sizeof(g_OsPairs) / sizeof(g_OsPairs[0]); i++)\r
+    if (g_OsPairs[i].Id == osId)\r
+      return g_OsPairs[i].Name;\r
+  return kUnknownOS;\r
+}\r
+\r
+static STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidIsDir, VT_BOOL},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  // { NULL, kpidAttrib, VT_UI4},\r
+  { NULL, kpidCRC, VT_UI4},\r
+  { NULL, kpidMethod, VT_BSTR},\r
+  { NULL, kpidHostOS, VT_BSTR}\r
+};\r
+\r
+class CCRC\r
+{\r
+  UInt16 _value;\r
+public:\r
+  static UInt16 Table[256];\r
+  static void InitTable();\r
+  \r
+  CCRC(): _value(0) {}\r
+  void Init() { _value = 0; }\r
+  void Update(const void *data, size_t size);\r
+  UInt16 GetDigest() const { return _value; }\r
+};\r
+\r
+static const UInt16 kCRCPoly = 0xA001;\r
+\r
+UInt16 CCRC::Table[256];\r
+\r
+void CCRC::InitTable()\r
+{\r
+  for (UInt32 i = 0; i < 256; i++)\r
+  {\r
+    UInt32 r = i;\r
+    for (int j = 0; j < 8; j++)\r
+      if (r & 1)\r
+        r = (r >> 1) ^ kCRCPoly;\r
+      else\r
+        r >>= 1;\r
+    CCRC::Table[i] = (UInt16)r;\r
+  }\r
+}\r
+\r
+class CCRCTableInit\r
+{\r
+public:\r
+  CCRCTableInit() { CCRC::InitTable(); }\r
+} g_CRCTableInit;\r
+\r
+void CCRC::Update(const void *data, size_t size)\r
+{\r
+  UInt16 v = _value;\r
+  const Byte *p = (const Byte *)data;\r
+  for (; size > 0; size--, p++)\r
+    v = (UInt16)(Table[((Byte)(v)) ^ *p] ^ (v >> 8));\r
+  _value = v;\r
+}\r
+\r
+\r
+class COutStreamWithCRC:\r
+  public ISequentialOutStream,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+private:\r
+  CCRC _crc;\r
+  CMyComPtr<ISequentialOutStream> _stream;\r
+public:\r
+  void Init(ISequentialOutStream *stream)\r
+  {\r
+    _stream = stream;\r
+    _crc.Init();\r
+  }\r
+  void ReleaseStream() { _stream.Release(); }\r
+  UInt32 GetCRC() const { return _crc.GetDigest(); }\r
+  void InitCRC() { _crc.Init(); }\r
+};\r
+\r
+STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  UInt32 realProcessedSize;\r
+  HRESULT result;\r
+  if (!_stream)\r
+  {\r
+    realProcessedSize = size;\r
+    result = S_OK;\r
+  }\r
+  else\r
+    result = _stream->Write(data, size, &realProcessedSize);\r
+  _crc.Update(data, realProcessedSize);\r
+  if (processedSize != NULL)\r
+    *processedSize = realProcessedSize;\r
+  return result;\r
+}\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public CMyUnknownImp\r
+{\r
+  CObjectVector<CItemEx> _items;\r
+  CMyComPtr<IInStream> _stream;\r
+public:\r
+  MY_UNKNOWN_IMP1(IInArchive)\r
+  INTERFACE_IInArchive(;)\r
+  CHandler();\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps_NO\r
+\r
+CHandler::CHandler() {}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _items.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID,  PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  const CItemEx &item = _items[index];\r
+  switch(propID)\r
+  {\r
+    case kpidPath:\r
+    {\r
+      UString s = NItemName::WinNameToOSName(MultiByteToUnicodeString(item.GetName(), CP_OEMCP));\r
+      if (!s.IsEmpty())\r
+      {\r
+        if (s[s.Length() - 1] == WCHAR_PATH_SEPARATOR)\r
+           s.Delete(s.Length() - 1);\r
+        prop = s;\r
+      }\r
+      break;\r
+    }\r
+    case kpidIsDir:  prop = item.IsDir(); break;\r
+    case kpidSize:   prop = item.Size; break;\r
+    case kpidPackSize:  prop = item.PackSize; break;\r
+    case kpidCRC:  prop = (UInt32)item.CRC; break;\r
+    case kpidHostOS:  prop = GetOS(item.OsId); break;\r
+    case kpidMTime:\r
+    {\r
+      FILETIME utc;\r
+      UInt32 unixTime;\r
+      if (item.GetUnixTime(unixTime))\r
+        NTime::UnixTimeToFileTime(unixTime, utc);\r
+      else\r
+      {\r
+        FILETIME localFileTime;\r
+        if (DosTimeToFileTime(item.ModifiedTime, localFileTime))\r
+        {\r
+          if (!LocalFileTimeToFileTime(&localFileTime, &utc))\r
+            utc.dwHighDateTime = utc.dwLowDateTime = 0;\r
+        }\r
+        else\r
+          utc.dwHighDateTime = utc.dwLowDateTime = 0;\r
+      }\r
+      prop = utc;\r
+      break;\r
+    }\r
+    // case kpidAttrib:  prop = (UInt32)item.Attributes; break;\r
+    case kpidMethod:\r
+    {\r
+      char method2[kMethodIdSize + 1];\r
+      method2[kMethodIdSize] = 0;\r
+      memcpy(method2, item.Method, kMethodIdSize);\r
+      prop = method2;\r
+      break;\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream,\r
+    const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *callback)\r
+{\r
+  COM_TRY_BEGIN\r
+  try\r
+  {\r
+    _items.Clear();\r
+    CInArchive archive;\r
+\r
+    UInt64 endPos = 0;\r
+    bool needSetTotal = true;\r
+\r
+    if (callback != NULL)\r
+    {\r
+      RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));\r
+      RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));\r
+    }\r
+\r
+    RINOK(archive.Open(stream));\r
+    for (;;)\r
+    {\r
+      CItemEx item;\r
+      bool filled;\r
+      HRESULT result = archive.GetNextItem(filled, item);\r
+      if (result == S_FALSE)\r
+        return S_FALSE;\r
+      if (result != S_OK)\r
+        return S_FALSE;\r
+      if (!filled)\r
+        break;\r
+      _items.Add(item);\r
+      archive.Skip(item.PackSize);\r
+      if (callback != NULL)\r
+      {\r
+        if (needSetTotal)\r
+        {\r
+          RINOK(callback->SetTotal(NULL, &endPos));\r
+          needSetTotal = false;\r
+        }\r
+        if (_items.Size() % 100 == 0)\r
+        {\r
+          UInt64 numFiles = _items.Size();\r
+          UInt64 numBytes = item.DataPosition;\r
+          RINOK(callback->SetCompleted(&numFiles, &numBytes));\r
+        }\r
+      }\r
+    }\r
+    if (_items.IsEmpty())\r
+      return S_FALSE;\r
+\r
+    _stream = stream;\r
+  }\r
+  catch(...)\r
+  {\r
+    return S_FALSE;\r
+  }\r
+  COM_TRY_END\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _items.Clear();\r
+  _stream.Release();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testModeSpec, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool testMode = (testModeSpec != 0);\r
+  UInt64 totalUnPacked = 0, totalPacked = 0;\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _items.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    const CItemEx &item = _items[allFilesMode ? i : indices[i]];\r
+    totalUnPacked += item.Size;\r
+    totalPacked += item.PackSize;\r
+  }\r
+  RINOK(extractCallback->SetTotal(totalUnPacked));\r
+\r
+  UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0;\r
+  UInt64 currentItemUnPacked, currentItemPacked;\r
+  \r
+  NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = 0;\r
+  CMyComPtr<ICompressCoder> lzhDecoder;\r
+  CMyComPtr<ICompressCoder> lzh1Decoder;\r
+  CMyComPtr<ICompressCoder> arj2Decoder;\r
+\r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);\r
+  streamSpec->SetStream(_stream);\r
+\r
+  for (i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked,\r
+      currentTotalPacked += currentItemPacked)\r
+  {\r
+    currentItemUnPacked = 0;\r
+    currentItemPacked = 0;\r
+\r
+    lps->InSize = currentTotalPacked;\r
+    lps->OutSize = currentTotalUnPacked;\r
+    RINOK(lps->SetCur());\r
+\r
+    CMyComPtr<ISequentialOutStream> realOutStream;\r
+    Int32 askMode;\r
+    askMode = testMode ? NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    Int32 index = allFilesMode ? i : indices[i];\r
+    const CItemEx &item = _items[index];\r
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+\r
+    if (item.IsDir())\r
+    {\r
+      // if (!testMode)\r
+      {\r
+        RINOK(extractCallback->PrepareOperation(askMode));\r
+        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+      }\r
+      continue;\r
+    }\r
+\r
+    if (!testMode && !realOutStream)\r
+      continue;\r
+\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+    currentItemUnPacked = item.Size;\r
+    currentItemPacked = item.PackSize;\r
+\r
+    {\r
+      COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;\r
+      CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\r
+      outStreamSpec->Init(realOutStream);\r
+      realOutStream.Release();\r
+      \r
+      UInt64 pos;\r
+      _stream->Seek(item.DataPosition, STREAM_SEEK_SET, &pos);\r
+\r
+      streamSpec->Init(item.PackSize);\r
+\r
+      HRESULT result = S_OK;\r
+      Int32 opRes = NExtract::NOperationResult::kOK;\r
+\r
+      if (item.IsCopyMethod())\r
+      {\r
+        result = copyCoder->Code(inStream, outStream, NULL, NULL, progress);\r
+        if (result == S_OK && copyCoderSpec->TotalSize != item.PackSize)\r
+          result = S_FALSE;\r
+      }\r
+      else if (item.IsLh4GroupMethod())\r
+      {\r
+        if (!lzhDecoder)\r
+        {\r
+          lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder;\r
+          lzhDecoder = lzhDecoderSpec;\r
+        }\r
+        lzhDecoderSpec->SetDictionary(item.GetNumDictBits());\r
+        result = lzhDecoder->Code(inStream, outStream, NULL, &currentItemUnPacked, progress);\r
+      }\r
+      /*\r
+      else if (item.IsLh1GroupMethod())\r
+      {\r
+        if (!lzh1Decoder)\r
+        {\r
+          lzh1DecoderSpec = new NCompress::NLzh1::NDecoder::CCoder;\r
+          lzh1Decoder = lzh1DecoderSpec;\r
+        }\r
+        lzh1DecoderSpec->SetDictionary(item.GetNumDictBits());\r
+        result = lzh1Decoder->Code(inStream, outStream, NULL, &currentItemUnPacked, progress);\r
+      }\r
+      */\r
+      else\r
+        opRes = NExtract::NOperationResult::kUnSupportedMethod;\r
+\r
+      if (opRes == NExtract::NOperationResult::kOK)\r
+      {\r
+        if (result == S_FALSE)\r
+          opRes = NExtract::NOperationResult::kDataError;\r
+        else\r
+        {\r
+          RINOK(result);\r
+          if (outStreamSpec->GetCRC() != item.CRC)\r
+            opRes = NExtract::NOperationResult::kCRCError;\r
+        }\r
+      }\r
+      outStream.Release();\r
+      RINOK(extractCallback->SetOperationResult(opRes));\r
+    }\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"Lzh", L"lzh lha", 0, 6, { '-', 'l' }, 2, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Lzh)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp
new file mode 100755 (executable)
index 0000000..9b8db45
--- /dev/null
@@ -0,0 +1,430 @@
+// LzmaHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/IntToString.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../Common/CreateCoder.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/LzmaDecoder.h"\r
+\r
+#include "Common/DummyOutStream.h"\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace NLzma {\r
+\r
+static bool CheckDicSize(const Byte *p)\r
+{\r
+  UInt32 dicSize = GetUi32(p);\r
+  for (int i = 1; i <= 30; i++)\r
+    if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i))\r
+      return true;\r
+  return (dicSize == 0xFFFFFFFF);\r
+}\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidMethod, VT_BSTR}\r
+};\r
+\r
+struct CHeader\r
+{\r
+  UInt64 Size;\r
+  Byte FilterID;\r
+  Byte LzmaProps[5];\r
+\r
+  UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); }\r
+  bool HasSize() const { return (Size != (UInt64)(Int64)-1); }\r
+  bool Parse(const Byte *buf, bool isThereFilter);\r
+};\r
+\r
+bool CHeader::Parse(const Byte *buf, bool isThereFilter)\r
+{\r
+  FilterID = 0;\r
+  if (isThereFilter)\r
+    FilterID = buf[0];\r
+  const Byte *sig = buf + (isThereFilter ? 1 : 0);\r
+  for (int i = 0; i < 5; i++)\r
+    LzmaProps[i] = sig[i];\r
+  Size = GetUi64(sig + 5);\r
+  return\r
+    LzmaProps[0] < 5 * 5 * 9 &&\r
+    FilterID < 2 &&\r
+    (!HasSize() || Size < ((UInt64)1 << 56)) &&\r
+    CheckDicSize(LzmaProps + 1);\r
+}\r
+\r
+class CDecoder\r
+{\r
+  NCompress::NLzma::CDecoder *_lzmaDecoderSpec;\r
+  CMyComPtr<ICompressCoder> _lzmaDecoder;\r
+  CMyComPtr<ISequentialOutStream> _bcjStream;\r
+public:\r
+  ~CDecoder();\r
+  HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS\r
+      bool filtered, ISequentialInStream *inStream);\r
+\r
+  HRESULT Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress);\r
+\r
+  UInt64 GetInputProcessedSize() const { return _lzmaDecoderSpec->GetInputProcessedSize(); }\r
+\r
+  void ReleaseInStream() { if (_lzmaDecoder) _lzmaDecoderSpec->ReleaseInStream(); }\r
+\r
+  HRESULT ReadInput(Byte *data, UInt32 size, UInt32 *processedSize)\r
+    { return _lzmaDecoderSpec->ReadFromInputStream(data, size, processedSize); }\r
+};\r
+\r
+static const UInt64 k_BCJ = 0x03030103;\r
+  \r
+HRESULT CDecoder::Create(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    bool filteredMode, ISequentialInStream *inStream)\r
+{\r
+  if (!_lzmaDecoder)\r
+  {\r
+    _lzmaDecoderSpec = new NCompress::NLzma::CDecoder;\r
+    _lzmaDecoder = _lzmaDecoderSpec;\r
+  }\r
+\r
+  if (filteredMode)\r
+  {\r
+    if (!_bcjStream)\r
+    {\r
+      CMyComPtr<ICompressCoder> coder;\r
+      RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false));\r
+      if (!coder)\r
+        return E_NOTIMPL;\r
+      coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream);\r
+      if (!_bcjStream)\r
+        return E_NOTIMPL;\r
+    }\r
+  }\r
+\r
+  return _lzmaDecoderSpec->SetInStream(inStream);\r
+}\r
+\r
+CDecoder::~CDecoder()\r
+{\r
+  ReleaseInStream();\r
+}\r
+\r
+HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,\r
+    ICompressProgressInfo *progress)\r
+{\r
+  if (header.FilterID > 1)\r
+    return E_NOTIMPL;\r
+\r
+  {\r
+    CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;\r
+    _lzmaDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);\r
+    if (!setDecoderProperties)\r
+      return E_NOTIMPL;\r
+    RINOK(setDecoderProperties->SetDecoderProperties2(header.LzmaProps, 5));\r
+  }\r
+\r
+  CMyComPtr<ICompressSetOutStream> setOutStream;\r
+\r
+  bool filteredMode = (header.FilterID == 1);\r
+\r
+  if (filteredMode)\r
+  {\r
+    _bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream);\r
+    if (!setOutStream)\r
+      return E_NOTIMPL;\r
+    RINOK(setOutStream->SetOutStream(outStream));\r
+    outStream = _bcjStream;\r
+  }\r
+\r
+  const UInt64 *Size = header.HasSize() ? &header.Size : NULL;\r
+  HRESULT res = _lzmaDecoderSpec->CodeResume(outStream, Size, progress);\r
+\r
+  if (filteredMode)\r
+  {\r
+    CMyComPtr<IOutStreamFlush> flush;\r
+    _bcjStream.QueryInterface(IID_IOutStreamFlush, &flush);\r
+    if (flush)\r
+    {\r
+      HRESULT res2 = flush->Flush();\r
+      if (res == S_OK)\r
+        res = res2;\r
+    }\r
+    HRESULT res2 = setOutStream->ReleaseOutStream();\r
+    if (res == S_OK)\r
+      res = res2;\r
+  }\r
+  RINOK(res);\r
+\r
+  return S_OK;\r
+}\r
+\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IArchiveOpenSeq,\r
+  PUBLIC_ISetCompressCodecsInfo\r
+  public CMyUnknownImp\r
+{\r
+  CHeader _header;\r
+  bool _lzma86;\r
+  UInt64 _startPosition;\r
+  UInt64 _packSize;\r
+  bool _packSizeDefined;\r
+  CMyComPtr<IInStream> _stream;\r
+  CMyComPtr<ISequentialInStream> _seqStream;\r
+\r
+  DECL_EXTERNAL_CODECS_VARS\r
+  DECL_ISetCompressCodecsInfo\r
+\r
+public:\r
+  MY_QUERYINTERFACE_BEGIN2(IInArchive)\r
+  MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq)\r
+  QUERY_ENTRY_ISetCompressCodecsInfo\r
+  MY_QUERYINTERFACE_END\r
+  MY_ADDREF_RELEASE\r
+\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(OpenSeq)(ISequentialInStream *stream);\r
+\r
+  CHandler(bool lzma86) { _lzma86 = lzma86; }\r
+\r
+  unsigned GetHeaderSize() const { return 5 + 8 + (_lzma86 ? 1 : 0); }\r
+\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps_NO_Table\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = 1;\r
+  return S_OK;\r
+}\r
+\r
+static void DictSizeToString(UInt32 value, char *s)\r
+{\r
+  for (int i = 0; i <= 31; i++)\r
+    if ((UInt32(1) << i) == value)\r
+    {\r
+      ::ConvertUInt32ToString(i, s);\r
+      return;\r
+    }\r
+  char c = 'b';\r
+  if ((value & ((1 << 20) - 1)) == 0)\r
+  {\r
+    value >>= 20;\r
+    c = 'm';\r
+  }\r
+  else if ((value & ((1 << 10) - 1)) == 0)\r
+  {\r
+    value >>= 10;\r
+    c = 'k';\r
+  }\r
+  ::ConvertUInt32ToString(value, s);\r
+  int p = MyStringLen(s);\r
+  s[p++] = c;\r
+  s[p++] = '\0';\r
+}\r
+\r
+static void MyStrCat(char *d, const char *s)\r
+{\r
+  MyStringCopy(d + MyStringLen(d), s);\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID,  PROPVARIANT *value)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidSize: if (_stream && _header.HasSize()) prop = _header.Size; break;\r
+    case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;\r
+    case kpidMethod:\r
+      if (_stream)\r
+      {\r
+        char s[64];\r
+        s[0] = '\0';\r
+        if (_header.FilterID != 0)\r
+          MyStrCat(s, "BCJ ");\r
+        MyStrCat(s, "LZMA:");\r
+        DictSizeToString(_header.GetDicSize(), s + MyStringLen(s));\r
+        prop = s;\r
+      }\r
+      break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *)\r
+{\r
+  RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_startPosition));\r
+  \r
+  const UInt32 kBufSize = 1 + 5 + 8 + 1;\r
+  Byte buf[kBufSize];\r
+  \r
+  RINOK(ReadStream_FALSE(inStream, buf, kBufSize));\r
+  \r
+  if (!_header.Parse(buf, _lzma86))\r
+    return S_FALSE;\r
+  const Byte *start = buf + GetHeaderSize();\r
+  if (start[0] != 0)\r
+    return S_FALSE;\r
+  \r
+  UInt64 endPos;\r
+  RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos));\r
+  _packSize = endPos - _startPosition;\r
+  _packSizeDefined = true;\r
+  \r
+  _stream = inStream;\r
+  _seqStream = inStream;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)\r
+{\r
+  Close();\r
+  _seqStream = stream;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _packSizeDefined = false;\r
+  _stream.Release();\r
+  _seqStream.Release();\r
+   return S_OK;\r
+}\r
+\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))\r
+    return E_INVALIDARG;\r
+\r
+  if (_stream)\r
+    extractCallback->SetTotal(_packSize);\r
+    \r
+  \r
+  CMyComPtr<ISequentialOutStream> realOutStream;\r
+  Int32 askMode = testMode ?\r
+      NExtract::NAskMode::kTest :\r
+      NExtract::NAskMode::kExtract;\r
+  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));\r
+  if (!testMode && !realOutStream)\r
+    return S_OK;\r
+  \r
+  extractCallback->PrepareOperation(askMode);\r
+\r
+  CDummyOutStream *outStreamSpec = new CDummyOutStream;\r
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\r
+  outStreamSpec->SetStream(realOutStream);\r
+  outStreamSpec->Init();\r
+  realOutStream.Release();\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, true);\r
+\r
+  if (_stream)\r
+  {\r
+    RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));\r
+  }\r
+\r
+  CDecoder decoder;\r
+  HRESULT result = decoder.Create(\r
+      EXTERNAL_CODECS_VARS\r
+      _lzma86, _seqStream);\r
+  RINOK(result);\r
\r
+  Int32 opRes = NExtract::NOperationResult::kOK;\r
+  bool firstItem = true;\r
+\r
+  for (;;)\r
+  {\r
+    lps->OutSize = outStreamSpec->GetSize();\r
+    lps->InSize = _packSize = decoder.GetInputProcessedSize();\r
+    _packSizeDefined = true;\r
+    RINOK(lps->SetCur());\r
+\r
+    CHeader st;\r
+\r
+    const UInt32 kBufSize = 1 + 5 + 8;\r
+    Byte buf[kBufSize];\r
+    const UInt32 headerSize = GetHeaderSize();\r
+    UInt32 processed;\r
+    RINOK(decoder.ReadInput(buf, headerSize, &processed));\r
+    if (processed != headerSize)\r
+      break;\r
+  \r
+    if (!st.Parse(buf, _lzma86))\r
+      break;\r
+    firstItem = false;\r
+\r
+    result = decoder.Code(st, outStream, progress);\r
+    if (result == E_NOTIMPL)\r
+    {\r
+      opRes = NExtract::NOperationResult::kUnSupportedMethod;\r
+      break;\r
+    }\r
+    if (result == S_FALSE)\r
+    {\r
+      opRes = NExtract::NOperationResult::kDataError;\r
+      break;\r
+    }\r
+    RINOK(result);\r
+  }\r
+  if (firstItem)\r
+    return E_FAIL;\r
+  outStream.Release();\r
+  return extractCallback->SetOperationResult(opRes);\r
+  COM_TRY_END\r
+}\r
+\r
+IMPL_ISetCompressCodecsInfo\r
+\r
+static IInArchive *CreateArc() { return new CHandler(false); }\r
+static IInArchive *CreateArc86() { return new CHandler(true); }\r
+\r
+namespace NLzmaAr {\r
+  \r
+static CArcInfo g_ArcInfo =\r
+  { L"lzma", L"lzma", 0, 0xA, { 0 }, 0, true, CreateArc, NULL };\r
+REGISTER_ARC(Lzma)\r
+\r
+}\r
+\r
+namespace NLzma86Ar {\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"lzma86", L"lzma86", 0, 0xB, { 0 }, 0, true, CreateArc86, NULL };\r
+REGISTER_ARC(Lzma86)\r
+\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/MachoHandler.cpp b/CPP/7zip/Archive/MachoHandler.cpp
new file mode 100755 (executable)
index 0000000..4f3e37f
--- /dev/null
@@ -0,0 +1,500 @@
+// MachoHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/Buffer.h"\r
+#include "Common/ComTry.h"\r
+\r
+#include "Windows/PropVariantUtils.h"\r
+\r
+#include "../Common/LimitedStreams.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/CopyCoder.h"\r
+\r
+static UInt32 Get32(const Byte *p, int be) { if (be) return GetBe32(p); return GetUi32(p); }\r
+static UInt64 Get64(const Byte *p, int be) { if (be) return GetBe64(p); return GetUi64(p); }\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace NMacho {\r
+\r
+#define MACH_ARCH_ABI64 (1 << 24)\r
+#define MACH_MACHINE_386 7\r
+#define MACH_MACHINE_ARM 12\r
+#define MACH_MACHINE_SPARC 14\r
+#define MACH_MACHINE_PPC 18\r
+\r
+#define MACH_MACHINE_PPC64 (MACH_ARCH_ABI64 | MACH_MACHINE_PPC)\r
+#define MACH_MACHINE_AMD64 (MACH_ARCH_ABI64 | MACH_MACHINE_386)\r
+\r
+#define MACH_CMD_SEGMENT_32 1\r
+#define MACH_CMD_SEGMENT_64 0x19\r
+\r
+#define MACH_SECT_TYPE_MASK 0x000000FF\r
+#define MACH_SECT_ATTR_MASK 0xFFFFFF00\r
+\r
+#define MACH_SECT_ATTR_ZEROFILL 1\r
+\r
+static const char *g_SectTypes[] =\r
+{\r
+  "REGULAR",\r
+  "ZEROFILL",\r
+  "CSTRINGS",\r
+  "4BYTE_LITERALS",\r
+  "8BYTE_LITERALS",\r
+  "LITERAL_POINTERS",\r
+  "NON_LAZY_SYMBOL_POINTERS",\r
+  "LAZY_SYMBOL_POINTERS",\r
+  "SYMBOL_STUBS",\r
+  "MOD_INIT_FUNC_POINTERS",\r
+  "MOD_TERM_FUNC_POINTERS",\r
+  "COALESCED",\r
+  "GB_ZEROFILL",\r
+  "INTERPOSING",\r
+  "16BYTE_LITERALS"\r
+};\r
+\r
+static const char *g_FileTypes[] =\r
+{\r
+  "0",\r
+  "OBJECT",\r
+  "EXECUTE",\r
+  "FVMLIB",\r
+  "CORE",\r
+  "PRELOAD",\r
+  "DYLIB",\r
+  "DYLINKER",\r
+  "BUNDLE",\r
+  "DYLIB_STUB",\r
+  "DSYM"\r
+};\r
+\r
+static const CUInt32PCharPair g_Flags[] =\r
+{\r
+  { 31, "PURE_INSTRUCTIONS" },\r
+  { 30, "NO_TOC" },\r
+  { 29, "STRIP_STATIC_SYMS" },\r
+  { 28, "NO_DEAD_STRIP" },\r
+  { 27, "LIVE_SUPPORT" },\r
+  { 26, "SELF_MODIFYING_CODE" },\r
+  { 25, "DEBUG" },\r
+  { 10, "SOME_INSTRUCTIONS" },\r
+  {  9, "EXT_RELOC" },\r
+  {  8, "LOC_RELOC" }\r
+};\r
+\r
+static const CUInt32PCharPair g_MachinePairs[] =\r
+{\r
+  { MACH_MACHINE_386, "x86" },\r
+  { MACH_MACHINE_ARM, "ARM" },\r
+  { MACH_MACHINE_SPARC, "SPARC" },\r
+  { MACH_MACHINE_PPC, "PowerPC" },\r
+  { MACH_MACHINE_PPC64, "PowerPC 64-bit" },\r
+  { MACH_MACHINE_AMD64, "x64" }\r
+};\r
+\r
+static const int kNameSize = 16;\r
+\r
+struct CSegment\r
+{\r
+  char Name[kNameSize];\r
+};\r
+\r
+struct CSection\r
+{\r
+  char Name[kNameSize];\r
+  char SegName[kNameSize];\r
+  UInt64 Va;\r
+  UInt64 Pa;\r
+  UInt64 VSize;\r
+  UInt64 PSize;\r
+\r
+  UInt32 Flags;\r
+  int SegmentIndex;\r
+\r
+  bool IsDummy;\r
+\r
+  CSection(): IsDummy(false) {}\r
+  // UInt64 GetPackSize() const { return Flags == MACH_SECT_ATTR_ZEROFILL ? 0 : Size; }\r
+  UInt64 GetPackSize() const { return PSize; }\r
+};\r
+\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<IInStream> _inStream;\r
+  CObjectVector<CSegment> _segments;\r
+  CObjectVector<CSection> _sections;\r
+  bool _mode64;\r
+  bool _be;\r
+  UInt32 _machine;\r
+  UInt32 _type;\r
+  UInt32 _headersSize;\r
+  UInt64 _totalSize;\r
+  HRESULT Open2(ISequentialInStream *stream);\r
+  bool Parse(const Byte *buf, UInt32 size);\r
+public:\r
+  MY_UNKNOWN_IMP1(IInArchive)\r
+  INTERFACE_IInArchive(;)\r
+};\r
+\r
+bool CHandler::Parse(const Byte *buf, UInt32 size)\r
+{\r
+  bool mode64 = _mode64;\r
+  bool be = _be;\r
+\r
+  const Byte *bufStart = buf;\r
+  bool reduceCommands = false;\r
+  if (size < 512)\r
+    return false;\r
+\r
+  _machine = Get32(buf + 4, be);\r
+  _type = Get32(buf + 0xC, be);\r
+\r
+  UInt32 numCommands = Get32(buf + 0x10, be);\r
+  UInt32 commandsSize = Get32(buf + 0x14, be);\r
+  if (commandsSize > size)\r
+    return false;\r
+\r
+  if (commandsSize > (1 << 24) || numCommands > (1 << 18))\r
+    return false;\r
+\r
+  if (numCommands > 16)\r
+  {\r
+    reduceCommands = true;\r
+    numCommands = 16;\r
+  }\r
+\r
+  _headersSize = 0;\r
+\r
+  buf += 0x1C;\r
+  size -= 0x1C;\r
+\r
+  if (mode64)\r
+  {\r
+    buf += 4;\r
+    size -= 4;\r
+  }\r
+\r
+  _totalSize = (UInt32)(buf - bufStart);\r
+  if (commandsSize < size)\r
+    size = commandsSize;\r
+\r
+  for (UInt32 cmdIndex = 0; cmdIndex < numCommands; cmdIndex++)\r
+  {\r
+    if (size < 8)\r
+      return false;\r
+    UInt32 cmd = Get32(buf, be);\r
+    UInt32 cmdSize = Get32(buf + 4, be);\r
+    if (size < cmdSize)\r
+      return false;\r
+    if (cmd == MACH_CMD_SEGMENT_32 || cmd == MACH_CMD_SEGMENT_64)\r
+    {\r
+      UInt32 offs = (cmd == MACH_CMD_SEGMENT_64) ? 0x48 : 0x38;\r
+      if (cmdSize < offs)\r
+        break;\r
+\r
+      UInt64 vmAddr, vmSize, phAddr, phSize;\r
+\r
+      {\r
+        if (cmd == MACH_CMD_SEGMENT_64)\r
+        {\r
+          vmAddr = Get64(buf + 0x18, be);\r
+          vmSize = Get64(buf + 0x20, be);\r
+          phAddr = Get64(buf + 0x28, be);\r
+          phSize = Get64(buf + 0x30, be);\r
+        }\r
+        else\r
+        {\r
+          vmAddr = Get32(buf + 0x18, be);\r
+          vmSize = Get32(buf + 0x1C, be);\r
+          phAddr = Get32(buf + 0x20, be);\r
+          phSize = Get32(buf + 0x24, be);\r
+        }\r
+        {\r
+          UInt64 totalSize = phAddr + phSize;\r
+          if (totalSize > _totalSize)\r
+            _totalSize = totalSize;\r
+        }\r
+      }\r
+      \r
+      CSegment seg;\r
+      memcpy(seg.Name, buf + 8, kNameSize);\r
+      _segments.Add(seg);\r
+\r
+      UInt32 numSections = Get32(buf + offs - 8, be);\r
+      if (numSections > (1 << 8))\r
+        return false;\r
+\r
+      if (numSections == 0)\r
+      {\r
+        CSection section;\r
+        section.IsDummy = true;\r
+        section.SegmentIndex = _segments.Size() - 1;\r
+          section.Va = vmAddr;\r
+          section.PSize = phSize;\r
+          section.VSize = vmSize;\r
+          section.Pa = phAddr;\r
+          section.Flags = 0;\r
+        _sections.Add(section);\r
+      }\r
+      else do\r
+      {\r
+        CSection section;\r
+        UInt32 headerSize = (cmd == MACH_CMD_SEGMENT_64) ? 0x50 : 0x44;\r
+        const Byte *p = buf + offs;\r
+        if (cmdSize - offs < headerSize)\r
+          break;\r
+        if (cmd == MACH_CMD_SEGMENT_64)\r
+        {\r
+          section.Va = Get64(p + 0x20, be);\r
+          section.VSize = Get64(p + 0x28, be);\r
+          section.Pa = Get32(p + 0x30, be);\r
+          section.Flags = Get32(p + 0x40, be);\r
+        }\r
+        else\r
+        {\r
+          section.Va = Get32(p + 0x20, be);\r
+          section.VSize = Get32(p + 0x24, be);\r
+          section.Pa = Get32(p + 0x28, be);\r
+          section.Flags = Get32(p + 0x38, be);\r
+        }\r
+        if (section.Flags == MACH_SECT_ATTR_ZEROFILL)\r
+          section.PSize = 0;\r
+        else\r
+          section.PSize = section.VSize;\r
+        memcpy(section.Name, p, kNameSize);\r
+        memcpy(section.SegName, p + kNameSize, kNameSize);\r
+        section.SegmentIndex = _segments.Size() - 1;\r
+        _sections.Add(section);\r
+        offs += headerSize;\r
+      }\r
+      while (--numSections);\r
+\r
+      if (offs != cmdSize)\r
+        return false;\r
+    }\r
+    buf += cmdSize;\r
+    size -= cmdSize;\r
+  }\r
+  _headersSize = (UInt32)(buf - bufStart);\r
+  return reduceCommands || (size == 0);\r
+}\r
+\r
+static STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidCpu, VT_BSTR},\r
+  { NULL, kpidBit64, VT_BOOL},\r
+  { NULL, kpidBigEndian, VT_BOOL},\r
+  { NULL, kpidCharacts, VT_BSTR},\r
+  { NULL, kpidPhySize, VT_UI8},\r
+  { NULL, kpidHeadersSize, VT_UI4}\r
+};\r
+\r
+static STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidCharacts, VT_BSTR},\r
+  { NULL, kpidOffset, VT_UI8},\r
+  { NULL, kpidVa, VT_UI8}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidCpu:  PAIR_TO_PROP(g_MachinePairs, _machine, prop); break;\r
+    case kpidCharacts:  TYPE_TO_PROP(g_FileTypes, _type, prop); break;\r
+    case kpidPhySize:  prop = _totalSize; break;\r
+    case kpidHeadersSize:  prop = _headersSize; break;\r
+    case kpidBit64:  if (_mode64) prop = _mode64; break;\r
+    case kpidBigEndian:  if (_be) prop = _be; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+static AString GetName(const char *name)\r
+{\r
+  char res[kNameSize + 1];\r
+  memcpy(res, name, kNameSize);\r
+  res[kNameSize] = 0;\r
+  return res;\r
+}\r
+\r
+static AString SectFlagsToString(UInt32 flags)\r
+{\r
+  AString res = TypeToString(g_SectTypes, sizeof(g_SectTypes) / sizeof(g_SectTypes[0]),\r
+      flags & MACH_SECT_TYPE_MASK);\r
+  AString s = FlagsToString(g_Flags, sizeof(g_Flags) / sizeof(g_Flags[0]),\r
+      flags & MACH_SECT_ATTR_MASK);\r
+  if (!s.IsEmpty())\r
+  {\r
+    res += ' ';\r
+    res += s;\r
+  }\r
+  return res;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NCOM::CPropVariant prop;\r
+  const CSection &item = _sections[index];\r
+  switch(propID)\r
+  {\r
+    case kpidPath:\r
+    {\r
+      AString s = GetName(_segments[item.SegmentIndex].Name);\r
+      if (!item.IsDummy)\r
+        s += GetName(item.Name);\r
+      StringToProp(s, prop);\r
+      break;\r
+    }\r
+    case kpidSize:  /* prop = (UInt64)item.VSize; break; */\r
+    case kpidPackSize:  prop = (UInt64)item.GetPackSize(); break;\r
+    case kpidCharacts:  if (!item.IsDummy) StringToProp(SectFlagsToString(item.Flags), prop); break;\r
+    case kpidOffset:  prop = item.Pa; break;\r
+    case kpidVa:  prop = item.Va; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+HRESULT CHandler::Open2(ISequentialInStream *stream)\r
+{\r
+  const UInt32 kBufSize = 1 << 18;\r
+  const UInt32 kSigSize = 4;\r
+\r
+  CByteBuffer buffer;\r
+  buffer.SetCapacity(kBufSize);\r
+  Byte *buf = buffer;\r
+\r
+  size_t processed = kSigSize;\r
+  RINOK(ReadStream_FALSE(stream, buf, processed));\r
+  UInt32 sig = GetUi32(buf);\r
+  bool be, mode64;\r
+  switch(sig)\r
+  {\r
+    case 0xCEFAEDFE:  be = true; mode64 = false; break;\r
+    case 0xCFFAEDFE:  be = true; mode64 = true; break;\r
+    case 0xFEEDFACE:  be = false; mode64 = false; break;\r
+    case 0xFEEDFACF:  be = false; mode64 = true; break;\r
+    default: return S_FALSE;\r
+  }\r
+  processed = kBufSize - kSigSize;\r
+  RINOK(ReadStream(stream, buf + kSigSize, &processed));\r
+  _mode64 = mode64;\r
+  _be = be;\r
+  return Parse(buf, (UInt32)processed + kSigSize) ? S_OK : S_FALSE;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *inStream,\r
+    const UInt64 * /* maxCheckStartPosition */,\r
+    IArchiveOpenCallback * /* openArchiveCallback */)\r
+{\r
+  COM_TRY_BEGIN\r
+  Close();\r
+  RINOK(Open2(inStream));\r
+  _inStream = inStream;\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _inStream.Release();\r
+  _sections.Clear();\r
+  _segments.Clear();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _sections.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _sections.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt64 totalSize = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+    totalSize += _sections[allFilesMode ? i : indices[i]].GetPackSize();\r
+  extractCallback->SetTotal(totalSize);\r
+\r
+  UInt64 currentTotalSize = 0;\r
+  UInt64 currentItemSize;\r
+  \r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);\r
+  streamSpec->SetStream(_inStream);\r
+\r
+  for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)\r
+  {\r
+    lps->InSize = lps->OutSize = currentTotalSize;\r
+    RINOK(lps->SetCur());\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    UInt32 index = allFilesMode ? i : indices[i];\r
+    const CSection &item = _sections[index];\r
+    currentItemSize = item.GetPackSize();\r
+\r
+    CMyComPtr<ISequentialOutStream> outStream;\r
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));\r
+    if (!testMode && !outStream)\r
+      continue;\r
+    \r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+    RINOK(_inStream->Seek(item.Pa, STREAM_SEEK_SET, NULL));\r
+    streamSpec->Init(currentItemSize);\r
+    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));\r
+    outStream.Release();\r
+    RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == currentItemSize ?\r
+        NExtract::NOperationResult::kOK:\r
+        NExtract::NOperationResult::kDataError));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"MachO", L"", 0, 0xDF, { 0 }, 0, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Macho)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/MbrHandler.cpp b/CPP/7zip/Archive/MbrHandler.cpp
new file mode 100755 (executable)
index 0000000..8fb9a8e
--- /dev/null
@@ -0,0 +1,507 @@
+// MbrHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+// #define SHOW_DEBUG_INFO\r
+\r
+#ifdef SHOW_DEBUG_INFO\r
+#include <stdio.h>\r
+#endif\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/Buffer.h"\r
+#include "Common/ComTry.h"\r
+#include "Common/IntToString.h"\r
+#include "Common/MyString.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../Common/LimitedStreams.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/CopyCoder.h"\r
+\r
+#ifdef SHOW_DEBUG_INFO\r
+#define PRF(x) x\r
+#else\r
+#define PRF(x)\r
+#endif\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace NMbr {\r
+\r
+struct CChs\r
+{\r
+  Byte Head;\r
+  Byte SectCyl;\r
+  Byte Cyl8;\r
+  \r
+  UInt32 GetSector() const { return SectCyl & 0x3F; }\r
+  UInt32 GetCyl() const { return ((UInt32)SectCyl >> 6 << 8) | Cyl8; }\r
+  void ToString(NCOM::CPropVariant &prop) const;\r
+\r
+  void Parse(const Byte *p)\r
+  {\r
+    Head = p[0];\r
+    SectCyl = p[1];\r
+    Cyl8 = p[2];\r
+  }\r
+  bool Check() const { return GetSector() > 0; }\r
+};\r
+\r
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }\r
+\r
+static int CompareChs(const CChs &c1, const CChs &c2)\r
+{\r
+  RINOZ(MyCompare(c1.GetCyl(), c2.GetCyl()));\r
+  RINOZ(MyCompare(c1.Head, c2.Head));\r
+  return MyCompare(c1.GetSector(), c2.GetSector());\r
+}\r
+\r
+static void AddUIntToString(UInt32 val, AString &res)\r
+{\r
+  char s[16];\r
+  ConvertUInt32ToString(val, s);\r
+  res += s;\r
+}\r
+\r
+void CChs::ToString(NCOM::CPropVariant &prop) const\r
+{\r
+  AString s;\r
+  AddUIntToString(GetCyl(), s);\r
+  s += '-';\r
+  AddUIntToString(Head, s);\r
+  s += '-';\r
+  AddUIntToString(GetSector(), s);\r
+  prop = s;\r
+}\r
+\r
+struct CPartition\r
+{\r
+  Byte Status;\r
+  CChs BeginChs;\r
+  Byte Type;\r
+  CChs EndChs;\r
+  UInt32 Lba;\r
+  UInt32 NumBlocks;\r
+\r
+  CPartition() { memset (this, 0, sizeof(*this)); }\r
+  \r
+  bool IsEmpty() const { return Type == 0; }\r
+  bool IsExtended() const { return Type == 5 || Type == 0xF; }\r
+  UInt32 GetLimit() const { return Lba + NumBlocks; }\r
+  // bool IsActive() const { return Status == 0x80; }\r
+  UInt64 GetPos() const { return (UInt64)Lba * 512; }\r
+  UInt64 GetSize() const { return (UInt64)NumBlocks * 512; }\r
+\r
+  bool CheckLbaLimits() const { return (UInt32)0xFFFFFFFF - Lba >= NumBlocks; }\r
+  bool Parse(const Byte *p)\r
+  {\r
+    Status = p[0];\r
+    BeginChs.Parse(p + 1);\r
+    Type = p[4];\r
+    EndChs.Parse(p + 5);\r
+    Lba = GetUi32(p + 8);\r
+    NumBlocks = GetUi32(p + 12);\r
+    if (Type == 0)\r
+      return true;\r
+    if (Status != 0 && Status != 0x80)\r
+      return false;\r
+    return\r
+       BeginChs.Check() &&\r
+       EndChs.Check() &&\r
+       CompareChs(BeginChs, EndChs) <= 0 &&\r
+       NumBlocks > 0 &&\r
+       CheckLbaLimits();\r
+  }\r
+\r
+  #ifdef SHOW_DEBUG_INFO\r
+  void Print() const\r
+  {\r
+    NCOM::CPropVariant prop, prop2;\r
+    BeginChs.ToString(prop);\r
+    EndChs.ToString(prop2);\r
+    printf("   %2x %2x %8X %8X %12S %12S", (int)Status, (int)Type, Lba, NumBlocks, prop.bstrVal, prop2.bstrVal);\r
+  }\r
+  #endif\r
+};\r
+\r
+struct CPartType\r
+{\r
+  UInt32 Id;\r
+  const char *Ext;\r
+  const char *Name;\r
+};\r
+\r
+static const char *kFat = "fat";\r
+\r
+static const CPartType kPartTypes[] =\r
+{\r
+  { 0x01, kFat, "FAT12" },\r
+  { 0x04, kFat, "FAT16 DOS 3.0+" },\r
+  { 0x05, 0, "Extended" },\r
+  { 0x06, kFat, "FAT16 DOS 3.31+" },\r
+  { 0x07, "ntfs", "NTFS" },\r
+  { 0x0B, kFat, "FAT32" },\r
+  { 0x0C, kFat, "FAT32-LBA" },\r
+  { 0x0E, kFat, "FAT16-LBA" },\r
+  { 0x0F, 0, "Extended-LBA" },\r
+  { 0x11, kFat, "FAT12-Hidden" },\r
+  { 0x14, kFat, "FAT16-Hidden < 32 MB" },\r
+  { 0x16, kFat, "FAT16-Hidden >= 32 MB" },\r
+  { 0x1B, kFat, "FAT32-Hidden" },\r
+  { 0x1C, kFat, "FAT32-LBA-Hidden" },\r
+  { 0x1E, kFat, "FAT16-LBA-WIN95-Hidden" },\r
+  { 0x82, 0, "Solaris x86 / Linux swap" },\r
+  { 0x83, 0, "Linux" },\r
+  { 0xBE, 0, "Solaris 8 boot" },\r
+  { 0xBF, 0, "New Solaris x86" },\r
+  { 0xC2, 0, "Linux-Hidden" },\r
+  { 0xC3, 0, "Linux swap-Hidden" },\r
+  { 0xEE, 0, "EFI-MBR" },\r
+  { 0xEE, 0, "EFI" }\r
+};\r
+\r
+static int FindPartType(UInt32 type)\r
+{\r
+  for (int i = 0; i < sizeof(kPartTypes) / sizeof(kPartTypes[0]); i++)\r
+    if (kPartTypes[i].Id == type)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+struct CItem\r
+{\r
+  bool IsReal;\r
+  bool IsPrim;\r
+  UInt64 Size;\r
+  CPartition Part;\r
+};\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IInArchiveGetStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<IInStream> _stream;\r
+  CObjectVector<CItem> _items;\r
+  UInt64 _totalSize;\r
+  CByteBuffer _buffer;\r
+\r
+  HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int level);\r
+public:\r
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);\r
+};\r
+\r
+HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int level)\r
+{\r
+  if (level >= 128 || _items.Size() >= 128)\r
+    return S_FALSE;\r
+\r
+  const int kNumHeaderParts = 4;\r
+  CPartition parts[kNumHeaderParts];\r
+\r
+  {\r
+    const UInt32 kSectorSize = 512;\r
+    _buffer.SetCapacity(kSectorSize);\r
+    Byte *buf = _buffer;\r
+    UInt64 newPos = (UInt64)lba << 9;\r
+    if (newPos + 512 > _totalSize)\r
+      return S_FALSE;\r
+    RINOK(stream->Seek(newPos, STREAM_SEEK_SET, NULL));\r
+    RINOK(ReadStream_FALSE(stream, buf, kSectorSize));\r
+    \r
+    if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA)\r
+      return S_FALSE;\r
+    \r
+    for (int i = 0; i < kNumHeaderParts; i++)\r
+      if (!parts[i].Parse(buf + 0x1BE + 16 * i))\r
+        return S_FALSE;\r
+  }\r
+\r
+  PRF(printf("\n# %8X", lba));\r
+\r
+  UInt32 limLba = lba + 1;\r
+  if (limLba == 0)\r
+    return S_FALSE;\r
+\r
+  for (int i = 0; i < kNumHeaderParts; i++)\r
+  {\r
+    CPartition &part = parts[i];\r
+    \r
+    if (part.IsEmpty())\r
+      continue;\r
+    PRF(printf("\n   %2d ", (int)level));\r
+    #ifdef SHOW_DEBUG_INFO\r
+    part.Print();\r
+    #endif\r
+    \r
+    int numItems = _items.Size();\r
+    UInt32 newLba = lba + part.Lba;\r
+    \r
+    if (part.IsExtended())\r
+    {\r
+      // if (part.Type == 5) // Check it!\r
+      newLba = baseLba + part.Lba;\r
+      if (newLba < limLba)\r
+        return S_FALSE;\r
+      HRESULT res = ReadTables(stream, level < 1 ? newLba : baseLba, newLba, level + 1);\r
+      if (res != S_FALSE && res != S_OK)\r
+        return res;\r
+    }\r
+    if (newLba < limLba)\r
+      return S_FALSE;\r
+    part.Lba = newLba;\r
+    if (!part.CheckLbaLimits())\r
+      return S_FALSE;\r
+\r
+    CItem n;\r
+    n.Part = part;\r
+    bool addItem = false;\r
+    if (numItems == _items.Size())\r
+    {\r
+      n.IsPrim = (level == 0);\r
+      n.IsReal = true;\r
+      addItem = true;\r
+    }\r
+    else\r
+    {\r
+      const CItem &back = _items.Back();\r
+      UInt32 backLimit = back.Part.GetLimit();\r
+      UInt32 partLimit = part.GetLimit();\r
+      if (backLimit < partLimit)\r
+      {\r
+        n.IsReal = false;\r
+        n.Part.Lba = backLimit;\r
+        n.Part.NumBlocks = partLimit - backLimit;\r
+        addItem = true;\r
+      }\r
+    }\r
+    if (addItem)\r
+    {\r
+      if (n.Part.GetLimit() < limLba)\r
+        return S_FALSE;\r
+      limLba = n.Part.GetLimit();\r
+      n.Size = n.Part.GetSize();\r
+      _items.Add(n);\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream,\r
+    const UInt64 * /* maxCheckStartPosition */,\r
+    IArchiveOpenCallback * /* openArchiveCallback */)\r
+{\r
+  COM_TRY_BEGIN\r
+  Close();\r
+  RINOK(stream->Seek(0, STREAM_SEEK_END, &_totalSize));\r
+  RINOK(ReadTables(stream, 0, 0, 0));\r
+  if (_items.IsEmpty())\r
+    return S_FALSE;\r
+  UInt32 lbaLimit = _items.Back().Part.GetLimit();\r
+  UInt64 lim = (UInt64)lbaLimit << 9;\r
+  if (lim < _totalSize)\r
+  {\r
+    CItem n;\r
+    n.Part.Lba = lbaLimit;\r
+    n.Size = _totalSize - lim;\r
+    n.IsReal = false;\r
+    _items.Add(n);\r
+  }\r
+  _stream = stream;\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _items.Clear();\r
+  _stream.Release();\r
+  return S_OK;\r
+}\r
+\r
+enum\r
+{\r
+  kpidPrimary = kpidUserDefined,\r
+  kpidBegChs,\r
+  kpidEndChs\r
+};\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidFileSystem, VT_BSTR},\r
+  { NULL, kpidOffset, VT_UI8},\r
+  { L"Primary", kpidPrimary, VT_BOOL},\r
+  { L"Begin CHS", kpidBegChs, VT_BSTR},\r
+  { L"End CHS", kpidEndChs, VT_BSTR}\r
+};\r
+\r
+IMP_IInArchive_Props_WITH_NAME\r
+IMP_IInArchive_ArcProps_NO_Table\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidMainSubfile:\r
+    {\r
+      int mainIndex = -1;\r
+      for (int i = 0; i < _items.Size(); i++)\r
+        if (_items[i].IsReal)\r
+        {\r
+          if (mainIndex >= 0)\r
+          {\r
+            mainIndex = -1;\r
+            break;\r
+          }\r
+          mainIndex = i;\r
+        }\r
+      if (mainIndex >= 0)\r
+        prop = (UInt32)mainIndex;\r
+      break;\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _items.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NCOM::CPropVariant prop;\r
+\r
+  const CItem &item = _items[index];\r
+  const CPartition &part = item.Part;\r
+  switch(propID)\r
+  {\r
+    case kpidPath:\r
+    {\r
+      AString s;\r
+      AddUIntToString(index, s);\r
+      if (item.IsReal)\r
+      {\r
+        int typeIndex = FindPartType(part.Type);\r
+        s += '.';\r
+        const char *ext = "img";\r
+        if (typeIndex >= 0 && kPartTypes[typeIndex].Ext != 0)\r
+          ext = kPartTypes[typeIndex].Ext;\r
+        s += ext;\r
+      }\r
+      prop = s;\r
+      break;\r
+    }\r
+    case kpidFileSystem:\r
+      if (item.IsReal)\r
+      {\r
+        char s[32];\r
+        ConvertUInt32ToString(part.Type, s);\r
+        const char *res = s;\r
+        int typeIndex = FindPartType(part.Type);\r
+        if (typeIndex >= 0 && kPartTypes[typeIndex].Name)\r
+          res = kPartTypes[typeIndex].Name;\r
+        prop = res;\r
+      }\r
+      break;\r
+    case kpidSize: prop = item.Size; break;;\r
+    case kpidPackSize: prop = item.Size; break;\r
+    case kpidOffset: prop = part.GetPos(); break;\r
+    case kpidPrimary: if (item.IsReal) prop = item.IsPrim; break;\r
+    case kpidBegChs: if (item.IsReal) part.BeginChs.ToString(prop); break;\r
+    case kpidEndChs: if (item.IsReal) part.EndChs.ToString(prop); break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _items.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt64 totalSize = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+    totalSize += _items[allFilesMode ? i : indices[i]].Size;\r
+  extractCallback->SetTotal(totalSize);\r
+\r
+  totalSize = 0;\r
+  \r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);\r
+  streamSpec->SetStream(_stream);\r
+\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    lps->InSize = totalSize;\r
+    lps->OutSize = totalSize;\r
+    RINOK(lps->SetCur());\r
+    CMyComPtr<ISequentialOutStream> outStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    Int32 index = allFilesMode ? i : indices[i];\r
+    const CItem &item = _items[index];\r
+    const CPartition &part = item.Part;\r
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));\r
+    totalSize += item.Size;\r
+    if (!testMode && !outStream)\r
+      continue;\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+\r
+    RINOK(_stream->Seek(part.GetPos(), STREAM_SEEK_SET, NULL));\r
+    streamSpec->Init(item.Size);\r
+    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));\r
+    outStream.Release();\r
+    RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == item.Size ?\r
+        NExtract::NOperationResult::kOK:\r
+        NExtract::NOperationResult::kDataError));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)\r
+{\r
+  COM_TRY_BEGIN\r
+  const CItem &item = _items[index];\r
+  return CreateLimitedInStream(_stream, item.Part.GetPos(), item.Size, stream);\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"MBR", L"mbr", 0, 0xDB, { 1, 1, 0 }, 3, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Mbr)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/MslzHandler.cpp b/CPP/7zip/Archive/MslzHandler.cpp
new file mode 100755 (executable)
index 0000000..8515cdd
--- /dev/null
@@ -0,0 +1,257 @@
+// MslzHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/MyString.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../Common/InBuffer.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "Common/DummyOutStream.h"\r
+\r
+namespace NArchive {\r
+namespace NMslz {\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<IInStream> _stream;\r
+  UInt32 _size;\r
+  UInt64 _packSize;\r
+  UString _name;\r
+public:\r
+  MY_UNKNOWN_IMP1(IInArchive)\r
+  INTERFACE_IInArchive(;)\r
+};\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps_NO\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = 1;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidPath: if (!_name.IsEmpty()) prop = _name; break;\r
+    case kpidSize: prop = _size; break;\r
+    case kpidPackSize: prop = _packSize; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+static const unsigned kSignatureSize = 9;\r
+static const unsigned kHeaderSize = kSignatureSize + 1 + 4;\r
+#define MSLZ_SIGNATURE { 0x53, 0x5A, 0x44, 0x44, 0x88, 0xF0, 0x27, 0x33, 0x41 }\r
+// old signature: 53 5A 20 88 F0 27 33\r
+static const Byte signature[kSignatureSize] = MSLZ_SIGNATURE;\r
+\r
+static const wchar_t *g_Exts[] =\r
+{\r
+  L"dll",\r
+  L"exe",\r
+  L"kmd",\r
+  L"sys"\r
+};\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */,\r
+    IArchiveOpenCallback *callback)\r
+{\r
+  COM_TRY_BEGIN\r
+  {\r
+    Close();\r
+    Byte buffer[kHeaderSize];\r
+    RINOK(ReadStream_FALSE(stream, buffer, kHeaderSize));\r
+    if (memcmp(buffer, signature, kSignatureSize) != 0)\r
+      return S_FALSE;\r
+    _size = GetUi32(buffer + 10);\r
+    if (_size > 0xFFFFFFE0)\r
+      return S_FALSE;\r
+    RINOK(stream->Seek(0, STREAM_SEEK_END, &_packSize));\r
+\r
+    if (callback)\r
+    {\r
+      CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;\r
+      callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);\r
+      if (openVolumeCallback)\r
+      {\r
+        NWindows::NCOM::CPropVariant prop;\r
+        if (openVolumeCallback->GetProperty(kpidName, &prop) == S_OK && prop.vt == VT_BSTR)\r
+        {\r
+          UString baseName = prop.bstrVal;\r
+          if (!baseName.IsEmpty() && baseName.Back() == L'_')\r
+          {\r
+            baseName.DeleteBack();\r
+            Byte replaceByte = buffer[kSignatureSize];\r
+            if (replaceByte == 0)\r
+            {\r
+              for (int i = 0; i < sizeof(g_Exts) / sizeof(g_Exts[0]); i++)\r
+              {\r
+                UString s = g_Exts[i];\r
+                int len = s.Length();\r
+                Byte b = (Byte)s.Back();\r
+                s.DeleteBack();\r
+                if (baseName.Length() >= len &&\r
+                    baseName[baseName.Length() - len] == '.' &&\r
+                    s.CompareNoCase(baseName.Right(len - 1)) == 0)\r
+                {\r
+                  replaceByte = b;\r
+                  break;\r
+                }\r
+              }\r
+            }\r
+            if (replaceByte >= 0x20 && replaceByte < 0x80)\r
+              _name = baseName + (wchar_t)replaceByte;\r
+          }\r
+        }\r
+      }\r
+    }\r
+    _stream = stream;\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _stream.Release();\r
+  _name.Empty();\r
+  return S_OK;\r
+}\r
+\r
+// MslzDec is modified LZSS algorithm of Haruhiko Okumura:\r
+//   maxLen = 18; Okumura\r
+//   maxLen = 16; MS\r
+\r
+#define PROGRESS_AND_WRITE \\r
+  if ((dest & kMask) == 0) { RINOK(WriteStream(outStream, buf, kBufSize)); \\r
+    if ((dest & ((1 << 20) - 1)) == 0) \\r
+    { UInt64 inSize = inStream.GetProcessedSize(); UInt64 outSize = dest; \\r
+      RINOK(progress->SetRatioInfo(&inSize, &outSize)); }}\r
+\r
+static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UInt32 unpackSize, ICompressProgressInfo *progress)\r
+{\r
+  const unsigned kBufSize = (1 << 12);\r
+  const unsigned kMask = kBufSize - 1;\r
+  Byte buf[kBufSize];\r
+  UInt32 dest = 0;\r
+  memset(buf, ' ', kBufSize);\r
+  while (dest < unpackSize)\r
+  {\r
+    Byte b;\r
+    if (!inStream.ReadByte(b))\r
+      return S_FALSE;\r
+    for (unsigned mask = (unsigned)b | 0x100; mask > 1 && dest < unpackSize; mask >>= 1)\r
+    {\r
+      if (!inStream.ReadByte(b))\r
+        return S_FALSE;\r
+      if (mask & 1)\r
+      {\r
+        buf[dest++ & kMask] = b;\r
+        PROGRESS_AND_WRITE\r
+      }\r
+      else\r
+      {\r
+        Byte b1;\r
+        if (!inStream.ReadByte(b1))\r
+          return S_FALSE;\r
+        const unsigned kMaxLen = 16; // 18 in Okumura's code.\r
+        unsigned src = (((((unsigned)b1 & 0xF0) << 4) | b) + kMaxLen) & kMask;\r
+        unsigned len = (b1 & 0xF) + 3;\r
+        if (len > kMaxLen || dest + len > unpackSize)\r
+          return S_FALSE;\r
+        do\r
+        {\r
+          buf[dest++ & kMask] = buf[src++ & kMask];\r
+          PROGRESS_AND_WRITE\r
+        }\r
+        while (--len != 0);\r
+      }\r
+    }\r
+  }\r
+  return WriteStream(outStream, buf, dest & kMask);\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))\r
+    return E_INVALIDARG;\r
+\r
+  extractCallback->SetTotal(_size);\r
+\r
+  CMyComPtr<ISequentialOutStream> realOutStream;\r
+  Int32 askMode = testMode ?\r
+      NExtract::NAskMode::kTest :\r
+      NExtract::NAskMode::kExtract;\r
+  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));\r
+  if (!testMode && !realOutStream)\r
+    return S_OK;\r
+\r
+  extractCallback->PrepareOperation(askMode);\r
+\r
+  CDummyOutStream *outStreamSpec = new CDummyOutStream;\r
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\r
+  outStreamSpec->SetStream(realOutStream);\r
+  outStreamSpec->Init();\r
+  realOutStream.Release();\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+  \r
+  RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));\r
+  CInBuffer s;\r
+  if (!s.Create(1 << 20))\r
+    return E_OUTOFMEMORY;\r
+  s.SetStream(_stream);\r
+  s.Init();\r
+  Byte buffer[kHeaderSize];\r
+  Int32 opRes = NExtract::NOperationResult::kDataError;\r
+  if (s.ReadBytes(buffer, kHeaderSize) == kHeaderSize)\r
+  {\r
+    HRESULT result = MslzDec(s, outStream, _size, progress);\r
+    if (result == S_OK)\r
+      opRes = NExtract::NOperationResult::kOK;\r
+    else if (result != S_FALSE)\r
+      return result;\r
+  }\r
+  outStream.Release();\r
+  return extractCallback->SetOperationResult(opRes);\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"MsLZ", L"", 0, 0xD5, MSLZ_SIGNATURE, kSignatureSize, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Mslz)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/MubHandler.cpp b/CPP/7zip/Archive/MubHandler.cpp
new file mode 100755 (executable)
index 0000000..0445eda
--- /dev/null
@@ -0,0 +1,266 @@
+// MubHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/ComTry.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../Common/LimitedStreams.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/CopyCoder.h"\r
+\r
+#define Get32(p) GetBe32(p)\r
+\r
+namespace NArchive {\r
+namespace NMub {\r
+\r
+struct CItem\r
+{\r
+  UInt32 Type;\r
+  UInt32 SubType;\r
+  UInt64 Offset;\r
+  UInt64 Size;\r
+  UInt32 Align;\r
+  bool IsTail;\r
+};\r
+\r
+const UInt32 kNumFilesMax = 10;\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IInArchiveGetStream,\r
+  public CMyUnknownImp\r
+{\r
+  UInt64 _startPos;\r
+  CMyComPtr<IInStream> _stream;\r
+  UInt32 _numItems;\r
+  CItem _items[kNumFilesMax + 1];\r
+  HRESULT Open2(IInStream *stream);\r
+public:\r
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);\r
+};\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidSize, VT_UI8}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps_NO\r
+\r
+#define MACH_ARCH_ABI64  0x1000000\r
+#define MACH_MACHINE_386   7\r
+#define MACH_MACHINE_ARM   12\r
+#define MACH_MACHINE_SPARC 14\r
+#define MACH_MACHINE_PPC   18\r
+\r
+#define MACH_MACHINE_PPC64 (MACH_MACHINE_PPC | MACH_ARCH_ABI64)\r
+#define MACH_MACHINE_AMD64 (MACH_MACHINE_386 | MACH_ARCH_ABI64)\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  NWindows::NCOM::CPropVariant prop;\r
+  const CItem &item = _items[index];\r
+  switch(propID)\r
+  {\r
+    case kpidExtension:\r
+    {\r
+      const wchar_t *ext;\r
+      if (item.IsTail)\r
+        ext = L"tail";\r
+      else\r
+      {\r
+        switch(item.Type)\r
+        {\r
+          case MACH_MACHINE_386:   ext = L"86";    break;\r
+          case MACH_MACHINE_ARM:   ext = L"arm";   break;\r
+          case MACH_MACHINE_SPARC: ext = L"sparc"; break;\r
+          case MACH_MACHINE_PPC:   ext = L"ppc";   break;\r
+          case MACH_MACHINE_PPC64: ext = L"ppc64"; break;\r
+          case MACH_MACHINE_AMD64: ext = L"x64";   break;\r
+          default: ext = L"unknown"; break;\r
+        }\r
+      }\r
+      prop = ext;\r
+      break;\r
+    }\r
+    case kpidSize:\r
+    case kpidPackSize:\r
+      prop = (UInt64)item.Size;\r
+      break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+#define MACH_TYPE_ABI64 (1 << 24)\r
+#define MACH_SUBTYPE_ABI64 (1 << 31)\r
+\r
+HRESULT CHandler::Open2(IInStream *stream)\r
+{\r
+  RINOK(stream->Seek(0, STREAM_SEEK_SET, &_startPos));\r
+\r
+  const UInt32 kHeaderSize = 8;\r
+  const UInt32 kRecordSize = 5 * 4;\r
+  const UInt32 kBufSize = kHeaderSize + kNumFilesMax * kRecordSize;\r
+  Byte buf[kBufSize];\r
+  size_t processed = kBufSize;\r
+  RINOK(ReadStream(stream, buf, &processed));\r
+  if (processed < kHeaderSize)\r
+    return S_FALSE;\r
+  UInt32 num = Get32(buf + 4);\r
+  if (Get32(buf) != 0xCAFEBABE || num > kNumFilesMax || processed < kHeaderSize + num * kRecordSize)\r
+    return S_FALSE;\r
+  UInt64 endPosMax = kHeaderSize;\r
+  for (UInt32 i = 0; i < num; i++)\r
+  {\r
+    const Byte *p = buf + kHeaderSize + i * kRecordSize;\r
+    CItem &sb = _items[i];\r
+    sb.IsTail = false;\r
+    sb.Type = Get32(p);\r
+    sb.SubType = Get32(p + 4);\r
+    sb.Offset = Get32(p + 8);\r
+    sb.Size = Get32(p + 12);\r
+    sb.Align = Get32(p + 16);\r
+\r
+    if ((sb.Type & ~MACH_TYPE_ABI64) >= 0x100 ||\r
+        (sb.SubType & ~MACH_SUBTYPE_ABI64) >= 0x100 ||\r
+        sb.Align > 31)\r
+      return S_FALSE;\r
+\r
+    UInt64 endPos = (UInt64)sb.Offset + sb.Size;\r
+    if (endPos > endPosMax)\r
+      endPosMax = endPos;\r
+  }\r
+  UInt64 fileSize;\r
+  RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize));\r
+  fileSize -= _startPos;\r
+  _numItems = num;\r
+  if (fileSize > endPosMax)\r
+  {\r
+    CItem &sb = _items[_numItems++];\r
+    sb.IsTail = true;\r
+    sb.Type = 0;\r
+    sb.SubType = 0;\r
+    sb.Offset = endPosMax;\r
+    sb.Size = fileSize - endPosMax;\r
+    sb.Align = 0;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *inStream,\r
+    const UInt64 * /* maxCheckStartPosition */,\r
+    IArchiveOpenCallback * /* openArchiveCallback */)\r
+{\r
+  COM_TRY_BEGIN\r
+  Close();\r
+  try\r
+  {\r
+    if (Open2(inStream) != S_OK)\r
+      return S_FALSE;\r
+    _stream = inStream;\r
+  }\r
+  catch(...) { return S_FALSE; }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _stream.Release();\r
+  _numItems = 0;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _numItems;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _numItems;\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt64 totalSize = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+    totalSize += _items[allFilesMode ? i : indices[i]].Size;\r
+  extractCallback->SetTotal(totalSize);\r
+\r
+  UInt64 currentTotalSize = 0;\r
+  \r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);\r
+  streamSpec->SetStream(_stream);\r
+\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    lps->InSize = lps->OutSize = currentTotalSize;\r
+    RINOK(lps->SetCur());\r
+    CMyComPtr<ISequentialOutStream> realOutStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    UInt32 index = allFilesMode ? i : indices[i];\r
+    const CItem &item = _items[index];\r
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+    currentTotalSize += item.Size;\r
+    \r
+    if (!testMode && !realOutStream)\r
+      continue;\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+    if (testMode)\r
+    {\r
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+      continue;\r
+    }\r
+    RINOK(_stream->Seek(_startPos + item.Offset, STREAM_SEEK_SET, NULL));\r
+    streamSpec->Init(item.Size);\r
+    RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));\r
+    realOutStream.Release();\r
+    RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ?\r
+        NExtract::NOperationResult::kOK:\r
+        NExtract::NOperationResult::kDataError));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)\r
+{\r
+  COM_TRY_BEGIN\r
+  const CItem &item = _items[index];\r
+  return CreateLimitedInStream(_stream, _startPos + item.Offset, item.Size, stream);\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"Mub", L"", 0, 0xE2, { 0xCA, 0xFE, 0xBA, 0xBE, 0, 0, 0 }, 7, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Mub)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.cpp b/CPP/7zip/Archive/Nsis/NsisDecode.cpp
new file mode 100755 (executable)
index 0000000..f7cf2f0
--- /dev/null
@@ -0,0 +1,130 @@
+// NsisDecode.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "NsisDecode.h"\r
+\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "../../Common/MethodId.h"\r
+\r
+#include "../../Compress/BZip2Decoder.h"\r
+#include "../../Compress/DeflateDecoder.h"\r
+#include "../../Compress/LzmaDecoder.h"\r
+\r
+namespace NArchive {\r
+namespace NNsis {\r
+\r
+static const CMethodId k_BCJ_X86 = 0x03030103;\r
+\r
+HRESULT CDecoder::Init(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    IInStream *inStream, NMethodType::EEnum method, bool thereIsFilterFlag, bool &useFilter)\r
+{\r
+  useFilter = false;\r
+  CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;\r
+\r
+  if (_decoderInStream)\r
+    if (method != _method)\r
+      Release();\r
+  _method = method;\r
+  if (!_codecInStream)\r
+  {\r
+    switch (method)\r
+    {\r
+      // case NMethodType::kCopy: return E_NOTIMPL;\r
+      case NMethodType::kDeflate: _codecInStream = new NCompress::NDeflate::NDecoder::CNsisCOMCoder(); break;\r
+      case NMethodType::kBZip2: _codecInStream = new NCompress::NBZip2::CNsisDecoder(); break;\r
+      case NMethodType::kLZMA: _codecInStream = new NCompress::NLzma::CDecoder(); break;\r
+      default: return E_NOTIMPL;\r
+    }\r
+  }\r
+\r
+  if (thereIsFilterFlag)\r
+  {\r
+    UInt32 processedSize;\r
+    BYTE flag;\r
+    RINOK(inStream->Read(&flag, 1, &processedSize));\r
+    if (processedSize != 1)\r
+      return E_FAIL;\r
+    if (flag > 1)\r
+      return E_NOTIMPL;\r
+    useFilter = (flag != 0);\r
+  }\r
+  \r
+  if (useFilter)\r
+  {\r
+    if (!_filterInStream)\r
+    {\r
+      CMyComPtr<ICompressCoder> coder;\r
+      RINOK(CreateCoder(\r
+          EXTERNAL_CODECS_LOC_VARS\r
+          k_BCJ_X86, coder, false));\r
+      if (!coder)\r
+        return E_NOTIMPL;\r
+      coder.QueryInterface(IID_ISequentialInStream, &_filterInStream);\r
+      if (!_filterInStream)\r
+        return E_NOTIMPL;\r
+    }\r
+    CMyComPtr<ICompressSetInStream> setInStream;\r
+    _filterInStream.QueryInterface(IID_ICompressSetInStream, &setInStream);\r
+    if (!setInStream)\r
+      return E_NOTIMPL;\r
+    RINOK(setInStream->SetInStream(_codecInStream));\r
+    _decoderInStream = _filterInStream;\r
+  }\r
+  else\r
+    _decoderInStream = _codecInStream;\r
+\r
+  if (method == NMethodType::kLZMA)\r
+  {\r
+    CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;\r
+    _codecInStream.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);\r
+    if (setDecoderProperties)\r
+    {\r
+      static const UInt32 kPropertiesSize = 5;\r
+      BYTE properties[kPropertiesSize];\r
+      UInt32 processedSize;\r
+      RINOK(inStream->Read(properties, kPropertiesSize, &processedSize));\r
+      if (processedSize != kPropertiesSize)\r
+        return E_FAIL;\r
+      RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, kPropertiesSize));\r
+    }\r
+  }\r
+\r
+  {\r
+    CMyComPtr<ICompressSetInStream> setInStream;\r
+    _codecInStream.QueryInterface(IID_ICompressSetInStream, &setInStream);\r
+    if (!setInStream)\r
+      return E_NOTIMPL;\r
+    RINOK(setInStream->SetInStream(inStream));\r
+  }\r
+\r
+  {\r
+    CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;\r
+    _codecInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);\r
+    if (!setOutStreamSize)\r
+      return E_NOTIMPL;\r
+    RINOK(setOutStreamSize->SetOutStreamSize(NULL));\r
+  }\r
+\r
+  if (useFilter)\r
+  {\r
+    /*\r
+    CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;\r
+    _filterInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);\r
+    if (!setOutStreamSize)\r
+      return E_NOTIMPL;\r
+    RINOK(setOutStreamSize->SetOutStreamSize(NULL));\r
+    */\r
+  }\r
+\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CDecoder::Read(void *data, size_t *processedSize)\r
+{\r
+  return ReadStream(_decoderInStream, data, processedSize);;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.h b/CPP/7zip/Archive/Nsis/NsisDecode.h
new file mode 100755 (executable)
index 0000000..fcdf4ea
--- /dev/null
@@ -0,0 +1,47 @@
+// NsisDecode.h\r
+\r
+#ifndef __NSIS_DECODE_H\r
+#define __NSIS_DECODE_H\r
+\r
+#include "../../IStream.h"\r
+\r
+#include "../../Common/CreateCoder.h"\r
+\r
+namespace NArchive {\r
+namespace NNsis {\r
+\r
+namespace NMethodType\r
+{\r
+  enum EEnum\r
+  {\r
+    kCopy,\r
+    kDeflate,\r
+    kBZip2,\r
+    kLZMA\r
+  };\r
+}\r
+\r
+class CDecoder\r
+{\r
+  NMethodType::EEnum _method;\r
+\r
+  CMyComPtr<ISequentialInStream> _filterInStream;\r
+  CMyComPtr<ISequentialInStream> _codecInStream;\r
+  CMyComPtr<ISequentialInStream> _decoderInStream;\r
+\r
+public:\r
+  void Release()\r
+  {\r
+    _filterInStream.Release();\r
+    _codecInStream.Release();\r
+    _decoderInStream.Release();\r
+  }\r
+  HRESULT Init(\r
+      DECL_EXTERNAL_CODECS_LOC_VARS\r
+      IInStream *inStream, NMethodType::EEnum method, bool thereIsFilterFlag, bool &useFilter);\r
+  HRESULT Read(void *data, size_t *processedSize);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.cpp b/CPP/7zip/Archive/Nsis/NsisHandler.cpp
new file mode 100755 (executable)
index 0000000..2bdd2c8
--- /dev/null
@@ -0,0 +1,510 @@
+// NSisHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/CpuArch.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/IntToString.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "../Common/ItemNameUtils.h"\r
+\r
+#include "NsisHandler.h"\r
+\r
+#define Get32(p) GetUi32(p)\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace NNsis {\r
+\r
+static const char *kBcjMethod = "BCJ";\r
+static const char *kUnknownMethod = "Unknown";\r
+\r
+static const char *kMethods[] =\r
+{\r
+  "Copy",\r
+  "Deflate",\r
+  "BZip2",\r
+  "LZMA"\r
+};\r
+\r
+static const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]);\r
+\r
+static STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidMethod, VT_BSTR},\r
+  { NULL, kpidSolid, VT_BOOL}\r
+};\r
+\r
+static STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidMethod, VT_BSTR},\r
+  { NULL, kpidSolid, VT_BOOL}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidMethod:\r
+    {\r
+      UInt32 dict = 1;\r
+      bool filter = false;\r
+      for (int i = 0; i < _archive.Items.Size(); i++)\r
+      {\r
+        const CItem &item = _archive.Items[i];\r
+        filter |= item.UseFilter;\r
+        if (item.DictionarySize > dict)\r
+          dict = item.DictionarySize;\r
+      }\r
+      prop = GetMethod(filter, dict);\r
+      break;\r
+    }\r
+    case kpidSolid: prop = _archive.IsSolid; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * maxCheckStartPosition, IArchiveOpenCallback * /* openArchiveCallback */)\r
+{\r
+  COM_TRY_BEGIN\r
+  Close();\r
+  {\r
+    if (_archive.Open(\r
+        EXTERNAL_CODECS_VARS\r
+        stream, maxCheckStartPosition) != S_OK)\r
+      return S_FALSE;\r
+    _inStream = stream;\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _archive.Clear();\r
+  _archive.Release();\r
+  _inStream.Release();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _archive.Items.Size()\r
+  #ifdef NSIS_SCRIPT\r
+    + 1\r
+  #endif\r
+  ;\r
+  return S_OK;\r
+}\r
+\r
+static AString UInt32ToString(UInt32 value)\r
+{\r
+  char buffer[16];\r
+  ConvertUInt32ToString(value, buffer);\r
+  return buffer;\r
+}\r
+\r
+static AString GetStringForSizeValue(UInt32 value)\r
+{\r
+  for (int i = 31; i >= 0; i--)\r
+    if (((UInt32)1 << i) == value)\r
+      return UInt32ToString(i);\r
+  char c = 'b';\r
+  if (value % (1 << 20) == 0)\r
+  {\r
+    value >>= 20;\r
+    c = 'm';\r
+  }\r
+  else if (value % (1 << 10) == 0)\r
+  {\r
+    value >>= 10;\r
+    c = 'k';\r
+  }\r
+  return UInt32ToString(value) + c;\r
+}\r
+\r
+AString CHandler::GetMethod(bool useItemFilter, UInt32 dictionary) const\r
+{\r
+  NMethodType::EEnum methodIndex = _archive.Method;\r
+  AString method;\r
+  if (_archive.IsSolid && _archive.UseFilter || !_archive.IsSolid && useItemFilter)\r
+  {\r
+    method += kBcjMethod;\r
+    method += ' ';\r
+  }\r
+  method += (methodIndex < kNumMethods) ? kMethods[methodIndex] : kUnknownMethod;\r
+  if (methodIndex == NMethodType::kLZMA)\r
+  {\r
+    method += ':';\r
+    method += GetStringForSizeValue(_archive.IsSolid ? _archive.DictionarySize: dictionary);\r
+  }\r
+  return method;\r
+}\r
+\r
+bool CHandler::GetUncompressedSize(int index, UInt32 &size)\r
+{\r
+  size = 0;\r
+  const CItem &item = _archive.Items[index];\r
+  if (item.SizeIsDefined)\r
+     size = item.Size;\r
+  else if (_archive.IsSolid && item.EstimatedSizeIsDefined)\r
+     size  = item.EstimatedSize;\r
+  else\r
+    return false;\r
+  return true;\r
+}\r
+\r
+bool CHandler::GetCompressedSize(int index, UInt32 &size)\r
+{\r
+  size = 0;\r
+  const CItem &item = _archive.Items[index];\r
+  if (item.CompressedSizeIsDefined)\r
+    size = item.CompressedSize;\r
+  else\r
+  {\r
+    if (_archive.IsSolid)\r
+    {\r
+      if (index == 0)\r
+        size = _archive.FirstHeader.GetDataSize();\r
+      else\r
+        return false;\r
+    }\r
+    else\r
+    {\r
+      if (!item.IsCompressed)\r
+        size = item.Size;\r
+      else\r
+        return false;\r
+    }\r
+  }\r
+  return true;\r
+}\r
+\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  #ifdef NSIS_SCRIPT\r
+  if (index >= (UInt32)_archive.Items.Size())\r
+  {\r
+    switch(propID)\r
+    {\r
+      case kpidPath:  prop = L"[NSIS].nsi"; break;\r
+      case kpidSize:\r
+      case kpidPackSize:  prop = (UInt64)_archive.Script.Length(); break;\r
+      case kpidSolid:  prop = false; break;\r
+    }\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    const CItem &item = _archive.Items[index];\r
+    switch(propID)\r
+    {\r
+      case kpidPath:\r
+      {\r
+        UString s = NItemName::WinNameToOSName(item.GetReducedName(_archive.IsUnicode));\r
+        if (!s.IsEmpty())\r
+          prop = (const wchar_t *)s;\r
+        break;\r
+      }\r
+      case kpidSize:\r
+      {\r
+        UInt32 size;\r
+        if (GetUncompressedSize(index, size))\r
+          prop = (UInt64)size;\r
+        break;\r
+      }\r
+      case kpidPackSize:\r
+      {\r
+        UInt32 size;\r
+        if (GetCompressedSize(index, size))\r
+          prop = (UInt64)size;\r
+        break;\r
+      }\r
+      case kpidMTime:\r
+      {\r
+        if (item.MTime.dwHighDateTime > 0x01000000 &&\r
+            item.MTime.dwHighDateTime < 0xFF000000)\r
+          prop = item.MTime;\r
+        break;\r
+      }\r
+      case kpidMethod:  prop = GetMethod(item.UseFilter, item.DictionarySize); break;\r
+      case kpidSolid:  prop = _archive.IsSolid; break;\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    GetNumberOfItems(&numItems);\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt64 totalSize = 0;\r
+\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    UInt32 index = (allFilesMode ? i : indices[i]);\r
+    #ifdef NSIS_SCRIPT\r
+    if (index >= (UInt32)_archive.Items.Size())\r
+      totalSize += _archive.Script.Length();\r
+    else\r
+    #endif\r
+    {\r
+      UInt32 size;\r
+      if (_archive.IsSolid)\r
+      {\r
+        GetUncompressedSize(index, size);\r
+        UInt64 pos = _archive.GetPosOfSolidItem(index);\r
+        if (pos > totalSize)\r
+          totalSize = pos + size;\r
+      }\r
+      else\r
+      {\r
+        GetCompressedSize(index, size);\r
+        totalSize += size;\r
+      }\r
+    }\r
+  }\r
+  extractCallback->SetTotal(totalSize);\r
+\r
+  UInt64 currentTotalSize = 0;\r
+  UInt32 currentItemSize = 0;\r
+\r
+  UInt64 streamPos = 0;\r
+  if (_archive.IsSolid)\r
+  {\r
+    RINOK(_inStream->Seek(_archive.StreamOffset, STREAM_SEEK_SET, NULL));\r
+    bool useFilter;\r
+    RINOK(_archive.Decoder.Init(\r
+        EXTERNAL_CODECS_VARS\r
+        _inStream, _archive.Method, _archive.FilterFlag, useFilter));\r
+  }\r
+\r
+  CByteBuffer byteBuf;\r
+  const UInt32 kBufferLength = 1 << 16;\r
+  byteBuf.SetCapacity(kBufferLength);\r
+  Byte *buffer = byteBuf;\r
+\r
+  CByteBuffer tempBuf;\r
+\r
+  bool dataError = false;\r
+  for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)\r
+  {\r
+    currentItemSize = 0;\r
+    RINOK(extractCallback->SetCompleted(&currentTotalSize));\r
+    CMyComPtr<ISequentialOutStream> realOutStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    UInt32 index = allFilesMode ? i : indices[i];\r
+\r
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+\r
+    #ifdef NSIS_SCRIPT\r
+    if (index >= (UInt32)_archive.Items.Size())\r
+    {\r
+      currentItemSize = _archive.Script.Length();\r
+      if (!testMode && !realOutStream)\r
+        continue;\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      if (!testMode)\r
+        RINOK(WriteStream(realOutStream, (const char *)_archive.Script, (UInt32)_archive.Script.Length()));\r
+    }\r
+    else\r
+    #endif\r
+    {\r
+      const CItem &item = _archive.Items[index];\r
+      \r
+      if (_archive.IsSolid)\r
+        GetUncompressedSize(index, currentItemSize);\r
+      else\r
+        GetCompressedSize(index, currentItemSize);\r
+      \r
+      if (!testMode && !realOutStream)\r
+        continue;\r
+      \r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      \r
+      if (!dataError)\r
+      {\r
+        bool needDecompress = false;\r
+        bool sizeIsKnown = false;\r
+        UInt32 fullSize = 0;\r
+\r
+        bool writeToTemp = false;\r
+        bool readFromTemp = false;\r
+\r
+        if (_archive.IsSolid)\r
+        {\r
+          UInt64 pos = _archive.GetPosOfSolidItem(index);\r
+          while (streamPos < pos)\r
+          {\r
+            size_t processedSize = (UInt32)MyMin(pos - streamPos, (UInt64)kBufferLength);\r
+            HRESULT res = _archive.Decoder.Read(buffer, &processedSize);\r
+            if (res != S_OK)\r
+            {\r
+              if (res != S_FALSE)\r
+                return res;\r
+              dataError = true;\r
+              break;\r
+            }\r
+            if (processedSize == 0)\r
+            {\r
+              dataError = true;\r
+              break;\r
+            }\r
+            streamPos += processedSize;\r
+          }\r
+          if (streamPos == pos)\r
+          {\r
+            Byte buffer2[4];\r
+            size_t processedSize = 4;\r
+            RINOK(_archive.Decoder.Read(buffer2, &processedSize));\r
+            if (processedSize != 4)\r
+              return E_FAIL;\r
+            streamPos += processedSize;\r
+            fullSize = Get32(buffer2);\r
+            sizeIsKnown = true;\r
+            needDecompress = true;\r
+\r
+            if (!testMode && i + 1 < numItems)\r
+            {\r
+              UInt64 nextPos = _archive.GetPosOfSolidItem(allFilesMode ? i : indices[i + 1]);\r
+              if (nextPos < streamPos + fullSize)\r
+              {\r
+                tempBuf.Free();\r
+                tempBuf.SetCapacity(fullSize);\r
+                writeToTemp = true;\r
+              }\r
+            }\r
+          }\r
+          else\r
+            readFromTemp = true;\r
+        }\r
+        else\r
+        {\r
+          RINOK(_inStream->Seek(_archive.GetPosOfNonSolidItem(index) + 4, STREAM_SEEK_SET, NULL));\r
+          if (item.IsCompressed)\r
+          {\r
+            needDecompress = true;\r
+            bool useFilter;\r
+            RINOK(_archive.Decoder.Init(\r
+                EXTERNAL_CODECS_VARS\r
+                _inStream, _archive.Method, _archive.FilterFlag, useFilter));\r
+            // fullSize = Get32(buffer); // It's bug !!!\r
+            // Test it: what is exact fullSize?\r
+            fullSize =  0xFFFFFFFF;\r
+          }\r
+          else\r
+            fullSize = item.Size;\r
+        }\r
+        if (!dataError)\r
+        {\r
+          if (needDecompress)\r
+          {\r
+            UInt64 offset = 0;\r
+            while (!sizeIsKnown || fullSize > 0)\r
+            {\r
+              UInt32 curSize = kBufferLength;\r
+              if (sizeIsKnown && curSize > fullSize)\r
+                curSize = fullSize;\r
+              size_t processedSize = curSize;\r
+              HRESULT res = _archive.Decoder.Read(buffer, &processedSize);\r
+              if (res != S_OK)\r
+              {\r
+                if (res != S_FALSE)\r
+                  return res;\r
+                dataError = true;\r
+                break;\r
+              }\r
+              if (processedSize == 0)\r
+              {\r
+                if (sizeIsKnown)\r
+                  dataError = true;\r
+                break;\r
+              }\r
+\r
+              if (writeToTemp)\r
+                memcpy((Byte *)tempBuf + (size_t)offset, buffer, processedSize);\r
+              \r
+              fullSize -= (UInt32)processedSize;\r
+              streamPos += processedSize;\r
+              offset += processedSize;\r
+              \r
+              UInt64 completed;\r
+              if (_archive.IsSolid)\r
+                completed = currentTotalSize + offset;\r
+              else\r
+                completed = streamPos;\r
+              RINOK(extractCallback->SetCompleted(&completed));\r
+              if (!testMode)\r
+                RINOK(WriteStream(realOutStream, buffer, processedSize));\r
+            }\r
+          }\r
+          else\r
+          {\r
+            if (readFromTemp)\r
+            {\r
+              if (!testMode)\r
+                RINOK(WriteStream(realOutStream, tempBuf, tempBuf.GetCapacity()));\r
+            }\r
+            else\r
+            while (fullSize > 0)\r
+            {\r
+              UInt32 curSize = MyMin(fullSize, kBufferLength);\r
+              UInt32 processedSize;\r
+              RINOK(_inStream->Read(buffer, curSize, &processedSize));\r
+              if (processedSize == 0)\r
+              {\r
+                dataError = true;\r
+                break;\r
+              }\r
+              fullSize -= processedSize;\r
+              streamPos += processedSize;\r
+              if (!testMode)\r
+                RINOK(WriteStream(realOutStream, buffer, processedSize));\r
+            }\r
+          }\r
+        }\r
+      }\r
+    }\r
+    realOutStream.Release();\r
+    RINOK(extractCallback->SetOperationResult(dataError ?\r
+        NExtract::NOperationResult::kDataError :\r
+        NExtract::NOperationResult::kOK));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+IMPL_ISetCompressCodecsInfo\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.h b/CPP/7zip/Archive/Nsis/NsisHandler.h
new file mode 100755 (executable)
index 0000000..c3db089
--- /dev/null
@@ -0,0 +1,43 @@
+// NSisHandler.h\r
+\r
+#ifndef __NSIS_HANDLER_H\r
+#define __NSIS_HANDLER_H\r
+\r
+#include "Common/MyCom.h"\r
+#include "../IArchive.h"\r
+\r
+#include "NsisIn.h"\r
+\r
+#include "../../Common/CreateCoder.h"\r
+\r
+namespace NArchive {\r
+namespace NNsis {\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  PUBLIC_ISetCompressCodecsInfo\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<IInStream> _inStream;\r
+  CInArchive _archive;\r
+\r
+  DECL_EXTERNAL_CODECS_VARS\r
+\r
+  bool GetUncompressedSize(int index, UInt32 &size);\r
+  bool GetCompressedSize(int index, UInt32 &size);\r
+\r
+  AString GetMethod(bool useItemFilter, UInt32 dictionary) const;\r
+public:\r
+  MY_QUERYINTERFACE_BEGIN2(IInArchive)\r
+  QUERY_ENTRY_ISetCompressCodecsInfo\r
+  MY_QUERYINTERFACE_END\r
+  MY_ADDREF_RELEASE\r
+\r
+  INTERFACE_IInArchive(;)\r
+\r
+  DECL_ISetCompressCodecsInfo\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp
new file mode 100755 (executable)
index 0000000..18bdff0
--- /dev/null
@@ -0,0 +1,1461 @@
+// NsisIn.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/CpuArch.h"\r
+\r
+#include "Common/IntToString.h"\r
+\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "NsisIn.h"\r
+\r
+#define Get32(p) GetUi32(p)\r
+\r
+namespace NArchive {\r
+namespace NNsis {\r
+\r
+Byte kSignature[kSignatureSize] = NSIS_SIGNATURE;\r
+\r
+#ifdef NSIS_SCRIPT\r
+static const char *kCrLf = "\x0D\x0A";\r
+#endif\r
+\r
+#define NS_UN_SKIP_CODE  0xE000\r
+#define NS_UN_VAR_CODE   0xE001\r
+#define NS_UN_SHELL_CODE 0xE002\r
+#define NS_UN_LANG_CODE  0xE003\r
+#define NS_UN_CODES_START NS_UN_SKIP_CODE\r
+#define NS_UN_CODES_END   NS_UN_LANG_CODE\r
+\r
+Byte CInArchive::ReadByte()\r
+{\r
+  if (_posInData >= _size)\r
+    throw 1;\r
+  return _data[_posInData++];\r
+}\r
+\r
+UInt32 CInArchive::ReadUInt32()\r
+{\r
+  UInt32 value = 0;\r
+  for (int i = 0; i < 4; i++)\r
+    value |= ((UInt32)(ReadByte()) << (8 * i));\r
+  return value;\r
+}\r
+\r
+void CInArchive::ReadBlockHeader(CBlockHeader &bh)\r
+{\r
+  bh.Offset = ReadUInt32();\r
+  bh.Num = ReadUInt32();\r
+}\r
+\r
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }\r
+\r
+static int CompareItems(void *const *p1, void *const *p2, void * /* param */)\r
+{\r
+  const CItem &i1 = **(CItem **)p1;\r
+  const CItem &i2 = **(CItem **)p2;\r
+  RINOZ(MyCompare(i1.Pos, i2.Pos));\r
+  if (i1.IsUnicode)\r
+  {\r
+    RINOZ(i1.PrefixU.Compare(i2.PrefixU));\r
+    RINOZ(i1.NameU.Compare(i2.NameU));\r
+  }\r
+  else\r
+  {\r
+    RINOZ(i1.PrefixA.Compare(i2.PrefixA));\r
+    RINOZ(i1.NameA.Compare(i2.NameA));\r
+  }\r
+  return 0;\r
+}\r
+\r
+static AString UIntToString(UInt32 v)\r
+{\r
+  char sz[32];\r
+  ConvertUInt64ToString(v, sz);\r
+  return sz;\r
+}\r
+\r
+static AString IntToString(Int32 v)\r
+{\r
+  char sz[32];\r
+  ConvertInt64ToString(v, sz);\r
+  return sz;\r
+}\r
+\r
+AString CInArchive::ReadStringA(UInt32 pos) const\r
+{\r
+  AString s;\r
+  if (pos >= _size)\r
+    return IntToString((Int32)pos);\r
+  UInt32 offset = GetOffset() + _stringsPos + pos;\r
+  for (;;)\r
+  {\r
+    if (offset >= _size)\r
+      break; // throw 1;\r
+    char c = _data[offset++];\r
+    if (c == 0)\r
+      break;\r
+    s += c;\r
+  }\r
+  return s;\r
+}\r
+\r
+UString CInArchive::ReadStringU(UInt32 pos) const\r
+{\r
+  UString s;\r
+  UInt32 offset = GetOffset() + _stringsPos + (pos * 2);\r
+  for (;;)\r
+  {\r
+    if (offset >= _size || offset + 1 >= _size)\r
+      return s; // throw 1;\r
+    char c0 = _data[offset++];\r
+    char c1 = _data[offset++];\r
+    wchar_t c = (c0 | ((wchar_t)c1 << 8));\r
+    if (c == 0)\r
+      break;\r
+    s += c;\r
+  }\r
+  return s;\r
+}\r
+\r
+/*\r
+static AString ParsePrefix(const AString &prefix)\r
+{\r
+  AString res = prefix;\r
+  if (prefix.Length() >= 3)\r
+  {\r
+    if ((Byte)prefix[0] == 0xFD && (Byte)prefix[1] == 0x95 && (Byte)prefix[2] == 0x80)\r
+      res = "$INSTDIR" + prefix.Mid(3);\r
+    else if ((Byte)prefix[0] == 0xFD && (Byte)prefix[1] == 0x96 && (Byte)prefix[2] == 0x80)\r
+      res = "$OUTDIR" + prefix.Mid(3);\r
+  }\r
+  return res;\r
+}\r
+*/\r
+\r
+#define SYSREGKEY "Software\\Microsoft\\Windows\\CurrentVersion"\r
+\r
+/*\r
+#  define CSIDL_PROGRAMS 0x2\r
+#  define CSIDL_PRINTERS 0x4\r
+#  define CSIDL_PERSONAL 0x5\r
+#  define CSIDL_FAVORITES 0x6\r
+#  define CSIDL_STARTUP 0x7\r
+#  define CSIDL_RECENT 0x8\r
+#  define CSIDL_SENDTO 0x9\r
+#  define CSIDL_STARTMENU 0xB\r
+#  define CSIDL_MYMUSIC 0xD\r
+#  define CSIDL_MYVIDEO 0xE\r
+\r
+#  define CSIDL_DESKTOPDIRECTORY 0x10\r
+#  define CSIDL_NETHOOD 0x13\r
+#  define CSIDL_FONTS 0x14\r
+#  define CSIDL_TEMPLATES 0x15\r
+#  define CSIDL_COMMON_STARTMENU 0x16\r
+#  define CSIDL_COMMON_PROGRAMS 0x17\r
+#  define CSIDL_COMMON_STARTUP 0x18\r
+#  define CSIDL_COMMON_DESKTOPDIRECTORY 0x19\r
+#  define CSIDL_APPDATA 0x1A\r
+#  define CSIDL_PRINTHOOD 0x1B\r
+#  define CSIDL_LOCAL_APPDATA 0x1C\r
+#  define CSIDL_ALTSTARTUP 0x1D\r
+#  define CSIDL_COMMON_ALTSTARTUP 0x1E\r
+#  define CSIDL_COMMON_FAVORITES 0x1F\r
+\r
+#  define CSIDL_INTERNET_CACHE 0x20\r
+#  define CSIDL_COOKIES 0x21\r
+#  define CSIDL_HISTORY 0x22\r
+#  define CSIDL_COMMON_APPDATA 0x23\r
+#  define CSIDL_WINDOWS 0x24\r
+#  define CSIDL_SYSTEM 0x25\r
+#  define CSIDL_PROGRAM_FILES 0x26\r
+#  define CSIDL_MYPICTURES 0x27\r
+#  define CSIDL_PROFILE 0x28\r
+#  define CSIDL_PROGRAM_FILES_COMMON 0x2B\r
+#  define CSIDL_COMMON_TEMPLATES 0x2D\r
+#  define CSIDL_COMMON_DOCUMENTS 0x2E\r
+#  define CSIDL_COMMON_ADMINTOOLS 0x2F\r
+\r
+#  define CSIDL_ADMINTOOLS 0x30\r
+#  define CSIDL_COMMON_MUSIC 0x35\r
+#  define CSIDL_COMMON_PICTURES 0x36\r
+#  define CSIDL_COMMON_VIDEO 0x37\r
+#  define CSIDL_RESOURCES 0x38\r
+#  define CSIDL_RESOURCES_LOCALIZED 0x39\r
+#  define CSIDL_CDBURN_AREA 0x3B\r
+*/\r
+\r
+struct CCommandPair\r
+{\r
+  int NumParams;\r
+  const char *Name;\r
+};\r
+\r
+enum\r
+{\r
+  // 0\r
+  EW_INVALID_OPCODE,    // zero is invalid. useful for catching errors. (otherwise an all zeroes instruction\r
+                        // does nothing, which is easily ignored but means something is wrong.\r
+  EW_RET,               // return from function call\r
+  EW_NOP,               // Nop/Jump, do nothing: 1, [?new address+1:advance one]\r
+  EW_ABORT,             // Abort: 1 [status]\r
+  EW_QUIT,              // Quit: 0\r
+  EW_CALL,              // Call: 1 [new address+1]\r
+  EW_UPDATETEXT,        // Update status text: 2 [update str, ui_st_updateflag=?ui_st_updateflag:this]\r
+  EW_SLEEP,             // Sleep: 1 [sleep time in milliseconds]\r
+  EW_BRINGTOFRONT,      // BringToFront: 0\r
+  EW_CHDETAILSVIEW,     // SetDetailsView: 2 [listaction,buttonaction]\r
+  \r
+  // 10\r
+  EW_SETFILEATTRIBUTES, // SetFileAttributes: 2 [filename, attributes]\r
+  EW_CREATEDIR,         // Create directory: 2, [path, ?update$INSTDIR]\r
+  EW_IFFILEEXISTS,      // IfFileExists: 3, [file name, jump amount if exists, jump amount if not exists]\r
+  EW_SETFLAG,           // Sets a flag: 2 [id, data]\r
+  EW_IFFLAG,            // If a flag: 4 [on, off, id, new value mask]\r
+  EW_GETFLAG,           // Gets a flag: 2 [output, id]\r
+  EW_RENAME,            // Rename: 3 [old, new, rebootok]\r
+  EW_GETFULLPATHNAME,   // GetFullPathName: 2 [output, input, ?lfn:sfn]\r
+  EW_SEARCHPATH,        // SearchPath: 2 [output, filename]\r
+  EW_GETTEMPFILENAME,   // GetTempFileName: 2 [output, base_dir]\r
+  \r
+  // 20\r
+  EW_EXTRACTFILE,       // File to extract: 6 [overwriteflag, output filename, compressed filedata, filedatetimelow, filedatetimehigh, allow ignore]\r
+                        //  overwriteflag: 0x1 = no. 0x0=force, 0x2=try, 0x3=if date is newer\r
+  EW_DELETEFILE,        // Delete File: 2, [filename, rebootok]\r
+  EW_MESSAGEBOX,        // MessageBox: 5,[MB_flags,text,retv1:retv2,moveonretv1:moveonretv2]\r
+  EW_RMDIR,             // RMDir: 2 [path, recursiveflag]\r
+  EW_STRLEN,            // StrLen: 2 [output, input]\r
+  EW_ASSIGNVAR,         // Assign: 4 [variable (0-9) to assign, string to assign, maxlen, startpos]\r
+  EW_STRCMP,            // StrCmp: 5 [str1, str2, jump_if_equal, jump_if_not_equal, case-sensitive?]\r
+  EW_READENVSTR,        // ReadEnvStr/ExpandEnvStrings: 3 [output, string_with_env_variables, IsRead]\r
+  EW_INTCMP,            // IntCmp: 6 [val1, val2, equal, val1<val2, val1>val2, unsigned?]\r
+  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\r
+  \r
+  // 30\r
+  EW_INTFMT,            // IntFmt: [output, format, input]\r
+  EW_PUSHPOP,           // Push/Pop/Exchange: 3 [variable/string, ?pop:push, ?exch]\r
+  EW_FINDWINDOW,        // FindWindow: 5, [outputvar, window class,window name, window_parent, window_after]\r
+  EW_SENDMESSAGE,       // SendMessage: 6 [output, hwnd, msg, wparam, lparam, [wparamstring?1:0 | lparamstring?2:0 | timeout<<2]\r
+  EW_ISWINDOW,          // IsWindow: 3 [hwnd, jump_if_window, jump_if_notwindow]\r
+  EW_GETDLGITEM,        // GetDlgItem:        3: [outputvar, dialog, item_id]\r
+  EW_SETCTLCOLORS,      // SerCtlColors:      3: [hwnd, pointer to struct colors]\r
+  EW_SETBRANDINGIMAGE,  // SetBrandingImage:  1: [Bitmap file]\r
+  EW_CREATEFONT,        // CreateFont:        5: [handle output, face name, height, weight, flags]\r
+  EW_SHOWWINDOW,        // ShowWindow:        2: [hwnd, show state]\r
+  \r
+  // 40\r
+  EW_SHELLEXEC,         // ShellExecute program: 4, [shell action, complete commandline, parameters, showwindow]\r
+  EW_EXECUTE,           // Execute program: 3,[complete command line,waitflag,>=0?output errorcode]\r
+  EW_GETFILETIME,       // GetFileTime; 3 [file highout lowout]\r
+  EW_GETDLLVERSION,     // GetDLLVersion: 3 [file highout lowout]\r
+  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]\r
+  EW_CREATESHORTCUT,    // Make Shortcut: 5, [link file, target file, parameters, icon file, iconindex|show mode<<8|hotkey<<16]\r
+  EW_COPYFILES,         // CopyFiles: 3 [source mask, destination location, flags]\r
+  EW_REBOOT,            // Reboot: 0\r
+  EW_WRITEINI,          // Write INI String: 4, [Section, Name, Value, INI File]\r
+  EW_READINISTR,        // ReadINIStr: 4 [output, section, name, ini_file]\r
+  \r
+  // 50\r
+  EW_DELREG,            // DeleteRegValue/DeleteRegKey: 4, [root key(int), KeyName, ValueName, delkeyonlyifempty]. ValueName is -1 if delete key\r
+  EW_WRITEREG,          // Write Registry value: 5, [RootKey(int),KeyName,ItemName,ItemData,typelen]\r
+                        //  typelen=1 for str, 2 for dword, 3 for binary, 0 for expanded str\r
+  EW_READREGSTR,        // ReadRegStr: 5 [output, rootkey(int), keyname, itemname, ==1?int::str]\r
+  EW_REGENUM,           // RegEnum: 5 [output, rootkey, keyname, index, ?key:value]\r
+  EW_FCLOSE,            // FileClose: 1 [handle]\r
+  EW_FOPEN,             // FileOpen: 4  [name, openmode, createmode, outputhandle]\r
+  EW_FPUTS,             // FileWrite: 3 [handle, string, ?int:string]\r
+  EW_FGETS,             // FileRead: 4  [handle, output, maxlen, ?getchar:gets]\r
+  EW_FSEEK,             // FileSeek: 4  [handle, offset, mode, >=0?positionoutput]\r
+  EW_FINDCLOSE,         // FindClose: 1 [handle]\r
+  \r
+  // 60\r
+  EW_FINDNEXT,          // FindNext: 2  [output, handle]\r
+  EW_FINDFIRST,         // FindFirst: 2 [filespec, output, handleoutput]\r
+  EW_WRITEUNINSTALLER,  // WriteUninstaller: 3 [name, offset, icon_size]\r
+  EW_LOG,               // LogText: 2 [0, text] / LogSet: [1, logstate]\r
+  EW_SECTIONSET,        // SectionSetText:    3: [idx, 0, text]\r
+                        // SectionGetText:    3: [idx, 1, output]\r
+                        // SectionSetFlags:   3: [idx, 2, flags]\r
+                        // SectionGetFlags:   3: [idx, 3, output]\r
+  EW_INSTTYPESET,       // InstTypeSetFlags:  3: [idx, 0, flags]\r
+                        // InstTypeGetFlags:  3: [idx, 1, output]\r
+  // instructions not actually implemented in exehead, but used in compiler.\r
+  EW_GETLABELADDR,      // both of these get converted to EW_ASSIGNVAR\r
+  EW_GETFUNCTIONADDR,\r
+\r
+  EW_LOCKWINDOW\r
+};\r
+\r
+#ifdef NSIS_SCRIPT\r
+static CCommandPair kCommandPairs[] =\r
+{\r
+  { 0, "Invalid" },\r
+  { 0, "Return" },\r
+  { 1, "Goto" },\r
+  { 0, "Abort" },\r
+  { 0, "Quit" },\r
+  { 1, "Call" },\r
+  { 2, "UpdateSatusText" },\r
+  { 1, "Sleep" },\r
+  { 0, "BringToFront" },\r
+  { 2, "SetDetailsView" },\r
+\r
+  { 2, "SetFileAttributes" },\r
+  { 2, "SetOutPath" },\r
+  { 3, "IfFileExists" },\r
+  { 2, "SetFlag" },\r
+  { 4, "IfFlag" },\r
+  { 2, "GetFlag" },\r
+  { 3, "Rename" },\r
+  { 2, "GetFullPathName" },\r
+  { 2, "SearchPath" },\r
+  { 2, "GetTempFileName" },\r
+\r
+  { 6, "File" },\r
+  { 2, "Delete" },\r
+  { 5, "MessageBox" },\r
+  { 2, "RMDir" },\r
+  { 2, "StrLen" },\r
+  { 4, "StrCpy" },\r
+  { 5, "StrCmp" },\r
+  { 3, "ReadEnvStr" },\r
+  { 6, "IntCmp" },\r
+  { 4, "IntOp" },\r
+\r
+  { 3, "IntFmt" },\r
+  { 3, "PushPop" },\r
+  { 5, "FindWindow" },\r
+  { 6, "SendMessage" },\r
+  { 3, "IsWindow" },\r
+  { 3, "GetDlgItem" },\r
+  { 3, "SerCtlColors" },\r
+  { 1, "SetBrandingImage" },\r
+  { 5, "CreateFont" },\r
+  { 2, "ShowWindow" },\r
+\r
+  { 4, "ShellExecute" },\r
+  { 3, "Execute" },\r
+  { 3, "GetFileTime" },\r
+  { 3, "GetDLLVersion" },\r
+  { 3, "RegisterDLL" },\r
+  { 5, "CreateShortCut" },\r
+  { 3, "CopyFiles" },\r
+  { 0, "Reboot" },\r
+  { 4, "WriteINIStr" },\r
+  { 4, "ReadINIStr" },\r
+\r
+  { 4, "DelReg" },\r
+  { 5, "WriteReg" },\r
+  { 5, "ReadRegStr" },\r
+  { 5, "RegEnum" },\r
+  { 1, "FileClose" },\r
+  { 4, "FileOpen" },\r
+  { 3, "FileWrite" },\r
+  { 4, "FileRead" },\r
+  { 4, "FileSeek" },\r
+  { 1, "FindClose" },\r
+\r
+  { 2, "FindNext" },\r
+  { 2, "FindFirst" },\r
+  { 3, "WriteUninstaller" },\r
+  { 2, "LogText" },\r
+  { 3, "Section?etText" },\r
+  { 3, "InstType?etFlags" },\r
+  { 6, "GetLabelAddr" },\r
+  { 2, "GetFunctionAddress" },\r
+  { 6, "LockWindow" }\r
+};\r
+\r
+#endif\r
+\r
+static const char *kShellStrings[] =\r
+{\r
+  "",\r
+  "",\r
+\r
+  "SMPROGRAMS",\r
+  "",\r
+  "PRINTERS",\r
+  "DOCUMENTS",\r
+  "FAVORITES",\r
+  "SMSTARTUP",\r
+  "RECENT",\r
+  "SENDTO",\r
+  "",\r
+  "STARTMENU",\r
+  "",\r
+  "MUSIC",\r
+  "VIDEO",\r
+  "",\r
+\r
+  "DESKTOP",\r
+  "",\r
+  "",\r
+  "NETHOOD",\r
+  "FONTS",\r
+  "TEMPLATES",\r
+  "COMMONSTARTMENU",\r
+  "COMMONFILES",\r
+  "COMMON_STARTUP",\r
+  "COMMON_DESKTOPDIRECTORY",\r
+  "QUICKLAUNCH",\r
+  "PRINTHOOD",\r
+  "LOCALAPPDATA",\r
+  "ALTSTARTUP",\r
+  "ALTSTARTUP",\r
+  "FAVORITES",\r
+\r
+  "INTERNET_CACHE",\r
+  "COOKIES",\r
+  "HISTORY",\r
+  "APPDATA",\r
+  "WINDIR",\r
+  "SYSDIR",\r
+  "PROGRAMFILES",\r
+  "PICTURES",\r
+  "PROFILE",\r
+  "",\r
+  "",\r
+  "COMMONFILES",\r
+  "",\r
+  "TEMPLATES",\r
+  "DOCUMENTS",\r
+  "ADMINTOOLS",\r
+\r
+  "ADMINTOOLS",\r
+  "",\r
+  "",\r
+  "",\r
+  "",\r
+  "MUSIC",\r
+  "PICTURES",\r
+  "VIDEO",\r
+  "RESOURCES",\r
+  "RESOURCES_LOCALIZED",\r
+  "",\r
+  "CDBURN_AREA"\r
+};\r
+\r
+static const int kNumShellStrings = sizeof(kShellStrings) / sizeof(kShellStrings[0]);\r
+\r
+/*\r
+# define CMDLINE 20 // everything before here doesn't have trailing slash removal\r
+# define INSTDIR 21\r
+# define OUTDIR 22\r
+# define EXEDIR 23\r
+# define LANGUAGE 24\r
+# define TEMP   25\r
+# define PLUGINSDIR 26\r
+# define HWNDPARENT 27\r
+# define _CLICK 28\r
+# define _OUTDIR 29\r
+*/\r
+\r
+static const char *kVarStrings[] =\r
+{\r
+  "CMDLINE",\r
+  "INSTDIR",\r
+  "OUTDIR",\r
+  "EXEDIR",\r
+  "LANGUAGE",\r
+  "TEMP",\r
+  "PLUGINSDIR",\r
+  "EXEPATH", // test it\r
+  "EXEFILE", // test it\r
+  "HWNDPARENT",\r
+  "_CLICK",\r
+  "_OUTDIR"\r
+};\r
+\r
+static const int kNumVarStrings = sizeof(kVarStrings) / sizeof(kVarStrings[0]);\r
+\r
+\r
+static AString GetVar(UInt32 index)\r
+{\r
+  AString res = "$";\r
+  if (index < 10)\r
+    res += UIntToString(index);\r
+  else if (index < 20)\r
+  {\r
+    res += "R";\r
+    res += UIntToString(index - 10);\r
+  }\r
+  else if (index < 20 + kNumVarStrings)\r
+    res += kVarStrings[index - 20];\r
+  else\r
+  {\r
+    res += "[";\r
+    res += UIntToString(index);\r
+    res += "]";\r
+  }\r
+  return res;\r
+}\r
+\r
+#define NS_SKIP_CODE  252\r
+#define NS_VAR_CODE   253\r
+#define NS_SHELL_CODE 254\r
+#define NS_LANG_CODE  255\r
+#define NS_CODES_START NS_SKIP_CODE\r
+\r
+static AString GetShellString(int index)\r
+{\r
+  AString res = "$";\r
+  if (index < kNumShellStrings)\r
+  {\r
+    const char *sz = kShellStrings[index];\r
+    if (sz[0] != 0)\r
+      return res + sz;\r
+  }\r
+  res += "SHELL[";\r
+  res += UIntToString(index);\r
+  res += "]";\r
+  return res;\r
+}\r
+\r
+// Based on Dave Laundon's simplified process_string\r
+AString GetNsisString(const AString &s)\r
+{\r
+  AString res;\r
+  for (int i = 0; i < s.Length();)\r
+  {\r
+    unsigned char nVarIdx = s[i++];\r
+    if (nVarIdx > NS_CODES_START && i + 2 <= s.Length())\r
+    {\r
+      int nData = s[i++] & 0x7F;\r
+      unsigned char c1 = s[i++];\r
+      nData |= (((int)(c1 & 0x7F)) << 7);\r
+\r
+      if (nVarIdx == NS_SHELL_CODE)\r
+        res += GetShellString(c1);\r
+      else if (nVarIdx == NS_VAR_CODE)\r
+        res += GetVar(nData);\r
+      else if (nVarIdx == NS_LANG_CODE)\r
+        res += "NS_LANG_CODE";\r
+    }\r
+    else if (nVarIdx == NS_SKIP_CODE)\r
+    {\r
+      if (i < s.Length())\r
+        res += s[i++];\r
+    }\r
+    else // Normal char\r
+      res += (char)nVarIdx;\r
+  }\r
+  return res;\r
+}\r
+\r
+UString GetNsisString(const UString &s)\r
+{\r
+  UString res;\r
+  for (int i = 0; i < s.Length();)\r
+  {\r
+    wchar_t nVarIdx = s[i++];\r
+    if (nVarIdx > NS_UN_CODES_START && nVarIdx <= NS_UN_CODES_END)\r
+    {\r
+      if (i == s.Length())\r
+        break;\r
+      int nData = s[i++] & 0x7FFF;\r
+\r
+      if (nVarIdx == NS_UN_SHELL_CODE)\r
+        res += GetUnicodeString(GetShellString(nData >> 8));\r
+      else if (nVarIdx == NS_UN_VAR_CODE)\r
+        res += GetUnicodeString(GetVar(nData));\r
+      else if (nVarIdx == NS_UN_LANG_CODE)\r
+        res += L"NS_LANG_CODE";\r
+    }\r
+    else if (nVarIdx == NS_UN_SKIP_CODE)\r
+    {\r
+      if (i == s.Length())\r
+        break;\r
+      res += s[i++];\r
+    }\r
+    else // Normal char\r
+      res += (char)nVarIdx;\r
+  }\r
+  return res;\r
+}\r
+\r
+AString CInArchive::ReadString2A(UInt32 pos) const\r
+{\r
+  return GetNsisString(ReadStringA(pos));\r
+}\r
+\r
+UString CInArchive::ReadString2U(UInt32 pos) const\r
+{\r
+  return GetNsisString(ReadStringU(pos));\r
+}\r
+\r
+AString CInArchive::ReadString2(UInt32 pos) const\r
+{\r
+  if (IsUnicode)\r
+    return UnicodeStringToMultiByte(ReadString2U(pos));\r
+  else\r
+    return ReadString2A(pos);\r
+}\r
+\r
+AString CInArchive::ReadString2Qw(UInt32 pos) const\r
+{\r
+  return "\"" + ReadString2(pos) + "\"";\r
+}\r
+\r
+#define DEL_DIR 1\r
+#define DEL_RECURSE 2\r
+#define DEL_REBOOT 4\r
+// #define DEL_SIMPLE 8\r
+\r
+static const int kNumEntryParams = 6;\r
+\r
+struct CEntry\r
+{\r
+  UInt32 Which;\r
+  UInt32 Params[kNumEntryParams];\r
+  AString GetParamsString(int numParams);\r
+  CEntry()\r
+  {\r
+    Which = 0;\r
+    for (UInt32 j = 0; j < kNumEntryParams; j++)\r
+      Params[j] = 0;\r
+  }\r
+};\r
+\r
+AString CEntry::GetParamsString(int numParams)\r
+{\r
+  AString s;\r
+  for (int i = 0; i < numParams; i++)\r
+  {\r
+    s += " ";\r
+    UInt32 v = Params[i];\r
+    if (v > 0xFFF00000)\r
+      s += IntToString((Int32)Params[i]);\r
+    else\r
+      s += UIntToString(Params[i]);\r
+  }\r
+  return s;\r
+}\r
+\r
+#ifdef NSIS_SCRIPT\r
+\r
+static AString GetRegRootID(UInt32 val)\r
+{\r
+  const char *s;\r
+  switch(val)\r
+  {\r
+    case 0:  s = "SHCTX"; break;\r
+    case 0x80000000:  s = "HKCR"; break;\r
+    case 0x80000001:  s = "HKCU"; break;\r
+    case 0x80000002:  s = "HKLM"; break;\r
+    case 0x80000003:  s = "HKU";  break;\r
+    case 0x80000004:  s = "HKPD"; break;\r
+    case 0x80000005:  s = "HKCC"; break;\r
+    case 0x80000006:  s = "HKDD"; break;\r
+    case 0x80000050:  s = "HKPT"; break;\r
+    case 0x80000060:  s = "HKPN"; break;\r
+    default:\r
+      return UIntToString(val); break;\r
+  }\r
+  return s;\r
+}\r
+\r
+#endif\r
+\r
+HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)\r
+{\r
+  _posInData = bh.Offset + GetOffset();\r
+  AString prefixA;\r
+  UString prefixU;\r
+  for (UInt32 i = 0; i < bh.Num; i++)\r
+  {\r
+    CEntry e;\r
+    e.Which = ReadUInt32();\r
+    for (UInt32 j = 0; j < kNumEntryParams; j++)\r
+      e.Params[j] = ReadUInt32();\r
+    #ifdef NSIS_SCRIPT\r
+    if (e.Which != EW_PUSHPOP && e.Which < sizeof(kCommandPairs) / sizeof(kCommandPairs[0]))\r
+    {\r
+      const CCommandPair &pair = kCommandPairs[e.Which];\r
+      Script += pair.Name;\r
+    }\r
+    #endif\r
+\r
+    switch (e.Which)\r
+    {\r
+      case EW_CREATEDIR:\r
+      {\r
+        if (IsUnicode)\r
+        {\r
+          prefixU.Empty();\r
+          prefixU = ReadString2U(e.Params[0]);\r
+        }\r
+        else\r
+        {\r
+          prefixA.Empty();\r
+          prefixA = ReadString2A(e.Params[0]);\r
+        }\r
+        #ifdef NSIS_SCRIPT\r
+        Script += " ";\r
+        if (IsUnicode)\r
+          Script += UnicodeStringToMultiByte(prefixU);\r
+        else\r
+          Script += prefixA;\r
+        #endif\r
+        break;\r
+      }\r
+\r
+      case EW_EXTRACTFILE:\r
+      {\r
+        CItem item;\r
+        item.IsUnicode = IsUnicode;\r
+        if (IsUnicode)\r
+        {\r
+          item.PrefixU = prefixU;\r
+          item.NameU = ReadString2U(e.Params[1]);\r
+        }\r
+        else\r
+        {\r
+          item.PrefixA = prefixA;\r
+          item.NameA = ReadString2A(e.Params[1]);\r
+        }\r
+        /* UInt32 overwriteFlag = e.Params[0]; */\r
+        item.Pos = e.Params[2];\r
+        item.MTime.dwLowDateTime = e.Params[3];\r
+        item.MTime.dwHighDateTime = e.Params[4];\r
+        /* UInt32 allowIgnore = e.Params[5]; */\r
+        if (Items.Size() > 0)\r
+        {\r
+          /*\r
+          if (item.Pos == Items.Back().Pos)\r
+            continue;\r
+          */\r
+        }\r
+        Items.Add(item);\r
+        #ifdef NSIS_SCRIPT\r
+        Script += " ";\r
+\r
+        if (IsUnicode)\r
+          Script += UnicodeStringToMultiByte(item.NameU);\r
+        else\r
+          Script += item.NameA;\r
+        #endif\r
+        break;\r
+      }\r
+\r
+\r
+      #ifdef NSIS_SCRIPT\r
+      case EW_UPDATETEXT:\r
+      {\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[0]);\r
+        Script += " ";\r
+        Script += UIntToString(e.Params[1]);\r
+        break;\r
+      }\r
+      case EW_SETFILEATTRIBUTES:\r
+      {\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[0]);\r
+        Script += " ";\r
+        Script += UIntToString(e.Params[1]);\r
+        break;\r
+      }\r
+      case EW_IFFILEEXISTS:\r
+      {\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[0]);\r
+        Script += " ";\r
+        Script += UIntToString(e.Params[1]);\r
+        Script += " ";\r
+        Script += UIntToString(e.Params[2]);\r
+        break;\r
+      }\r
+      case EW_RENAME:\r
+      {\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[0]);\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[1]);\r
+        Script += " ";\r
+        Script += UIntToString(e.Params[2]);\r
+        break;\r
+      }\r
+      case EW_GETFULLPATHNAME:\r
+      {\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[0]);\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[1]);\r
+        Script += " ";\r
+        Script += UIntToString(e.Params[2]);\r
+        break;\r
+      }\r
+      case EW_SEARCHPATH:\r
+      {\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[0]);\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[1]);\r
+        break;\r
+      }\r
+      case EW_GETTEMPFILENAME:\r
+      {\r
+        AString s;\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[0]);\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[1]);\r
+        break;\r
+      }\r
+\r
+      case EW_DELETEFILE:\r
+      {\r
+        UInt64 flag = e.Params[1];\r
+        if (flag != 0)\r
+        {\r
+          Script += " ";\r
+          if (flag == DEL_REBOOT)\r
+            Script += "/REBOOTOK";\r
+          else\r
+            Script += UIntToString(e.Params[1]);\r
+        }\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[0]);\r
+        break;\r
+      }\r
+      case EW_RMDIR:\r
+      {\r
+        UInt64 flag = e.Params[1];\r
+        if (flag != 0)\r
+        {\r
+          if ((flag & DEL_REBOOT) != 0)\r
+            Script += " /REBOOTOK";\r
+          if ((flag & DEL_RECURSE) != 0)\r
+            Script += " /r";\r
+        }\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[0]);\r
+        break;\r
+      }\r
+      case EW_STRLEN:\r
+      {\r
+        Script += " ";\r
+        Script += GetVar(e.Params[0]);;\r
+        Script += " ";\r
+        Script += ReadString2Qw(e.Params[1]);\r
+        break;\r
+      }\r
+      case EW_ASSIGNVAR:\r
+      {\r
+        Script += " ";\r
+        Script += GetVar(e.Params[0]);;\r
+        Script += " ";\r
+        Script += ReadString2Qw(e.Params[1]);\r
+        AString maxLen, startOffset;\r
+        if (e.Params[2] != 0)\r
+          maxLen = ReadString2(e.Params[2]);\r
+        if (e.Params[3] != 0)\r
+          startOffset = ReadString2(e.Params[3]);\r
+        if (!maxLen.IsEmpty() || !startOffset.IsEmpty())\r
+        {\r
+          Script += " ";\r
+          if (maxLen.IsEmpty())\r
+            Script += "\"\"";\r
+          else\r
+            Script += maxLen;\r
+          if (!startOffset.IsEmpty())\r
+          {\r
+            Script += " ";\r
+            Script += startOffset;\r
+          }\r
+        }\r
+        break;\r
+      }\r
+      case EW_STRCMP:\r
+      {\r
+        Script += " ";\r
+\r
+        Script += " ";\r
+        Script += ReadString2Qw(e.Params[0]);\r
+        \r
+        Script += " ";\r
+        Script += ReadString2Qw(e.Params[1]);\r
+\r
+        for (int j = 2; j < 5; j++)\r
+        {\r
+          Script += " ";\r
+          Script += UIntToString(e.Params[j]);\r
+        }\r
+        break;\r
+      }\r
+      case EW_INTCMP:\r
+      {\r
+        if (e.Params[5] != 0)\r
+          Script += "U";\r
+\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[0]);\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[1]);\r
+\r
+        for (int i = 2; i < 5; i++)\r
+        {\r
+          Script += " ";\r
+          Script += UIntToString(e.Params[i]);\r
+        }\r
+        break;\r
+      }\r
+      case EW_INTOP:\r
+      {\r
+        Script += " ";\r
+        Script += GetVar(e.Params[0]);\r
+        Script += " ";\r
+        int numOps = 2;\r
+        AString op;\r
+        switch (e.Params[3])\r
+        {\r
+          case 0: op = '+'; break;\r
+          case 1: op = '-'; break;\r
+          case 2: op = '*'; break;\r
+          case 3: op = '/'; break;\r
+          case 4: op = '|'; break;\r
+          case 5: op = '&'; break;\r
+          case 6: op = '^'; break;\r
+          case 7: op = '~'; numOps = 1; break;\r
+          case 8: op = '!'; numOps = 1; break;\r
+          case 9: op = "||"; break;\r
+          case 10: op = "&&"; break;\r
+          case 11: op = '%'; break;\r
+          default: op = UIntToString(e.Params[3]);\r
+        }\r
+        AString p1 = ReadString2(e.Params[1]);\r
+        if (numOps == 1)\r
+        {\r
+          Script += op;\r
+          Script += p1;\r
+        }\r
+        else\r
+        {\r
+          Script += p1;\r
+          Script += " ";\r
+          Script += op;\r
+          Script += " ";\r
+          Script += ReadString2(e.Params[2]);\r
+        }\r
+        break;\r
+      }\r
+\r
+      case EW_PUSHPOP:\r
+      {\r
+        int isPop = (e.Params[1] != 0);\r
+        if (isPop)\r
+        {\r
+          Script += "Pop";\r
+          Script += " ";\r
+          Script += GetVar(e.Params[0]);;\r
+        }\r
+        else\r
+        {\r
+          int isExch = (e.Params[2] != 0);\r
+          if (isExch)\r
+          {\r
+            Script += "Exch";\r
+          }\r
+          else\r
+          {\r
+            Script += "Push";\r
+            Script += " ";\r
+            Script += ReadString2(e.Params[0]);\r
+          }\r
+        }\r
+        break;\r
+      }\r
+\r
+      case EW_SENDMESSAGE:\r
+      {\r
+        // SendMessage: 6 [output, hwnd, msg, wparam, lparam, [wparamstring?1:0 | lparamstring?2:0 | timeout<<2]\r
+        Script += " ";\r
+        // Script += ReadString2(e.Params[0]);\r
+        // Script += " ";\r
+        Script += ReadString2(e.Params[1]);\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[2]);\r
+        \r
+        Script += " ";\r
+        UInt32 spec = e.Params[5];\r
+        // if (spec & 1)\r
+          Script += IntToString(e.Params[3]);\r
+        // else\r
+        //   Script += ReadString2(e.Params[3]);\r
+        \r
+        Script += " ";\r
+        // if (spec & 2)\r
+          Script += IntToString(e.Params[4]);\r
+        // else\r
+        //   Script += ReadString2(e.Params[4]);\r
+\r
+        if ((Int32)e.Params[0] >= 0)\r
+        {\r
+          Script += " ";\r
+          Script += GetVar(e.Params[1]);\r
+        }\r
+\r
+        spec >>= 2;\r
+        if (spec != 0)\r
+        {\r
+          Script += " /TIMEOUT=";\r
+          Script += IntToString(spec);\r
+        }\r
+        break;\r
+      }\r
+\r
+      case EW_GETDLGITEM:\r
+      {\r
+        Script += " ";\r
+        Script += GetVar(e.Params[0]);;\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[1]);\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[2]);\r
+        break;\r
+     }\r
+\r
+\r
+      case EW_REGISTERDLL:\r
+      {\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[0]);\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[1]);\r
+        Script += " ";\r
+        Script += UIntToString(e.Params[2]);\r
+        break;\r
+      }\r
+\r
+      case EW_CREATESHORTCUT:\r
+      {\r
+        AString s;\r
+\r
+        Script += " ";\r
+        Script += ReadString2Qw(e.Params[0]);\r
+\r
+        Script += " ";\r
+        Script += ReadString2Qw(e.Params[1]);\r
+\r
+        for (int j = 2; j < 5; j++)\r
+        {\r
+          Script += " ";\r
+          Script += UIntToString(e.Params[j]);\r
+        }\r
+        break;\r
+      }\r
+\r
+      /*\r
+      case EW_DELREG:\r
+      {\r
+        AString keyName, valueName;\r
+        keyName = ReadString2(e.Params[1]);\r
+        bool isValue = (e.Params[2] != -1);\r
+        if (isValue)\r
+        {\r
+          valueName = ReadString2(e.Params[2]);\r
+          Script += "Key";\r
+        }\r
+        else\r
+          Script += "Value";\r
+        Script += " ";\r
+        Script += UIntToString(e.Params[0]);\r
+        Script += " ";\r
+        Script += keyName;\r
+        if (isValue)\r
+        {\r
+          Script += " ";\r
+          Script += valueName;\r
+        }\r
+        Script += " ";\r
+        Script += UIntToString(e.Params[3]);\r
+        break;\r
+      }\r
+      */\r
+\r
+      case EW_WRITEREG:\r
+      {\r
+        AString s;\r
+        switch(e.Params[4])\r
+        {\r
+          case 1:  s = "Str"; break;\r
+          case 2:  s = "ExpandStr"; break;\r
+          case 3:  s = "Bin"; break;\r
+          case 4:  s = "DWORD"; break;\r
+          default: s = "?" + UIntToString(e.Params[4]); break;\r
+        }\r
+        Script += s;\r
+        Script += " ";\r
+        Script += GetRegRootID(e.Params[0]);\r
+        Script += " ";\r
+\r
+        AString keyName, valueName;\r
+        keyName = ReadString2Qw(e.Params[1]);\r
+        Script += keyName;\r
+        Script += " ";\r
+        \r
+        valueName = ReadString2Qw(e.Params[2]);\r
+        Script += valueName;\r
+        Script += " ";\r
+\r
+        valueName = ReadString2Qw(e.Params[3]);\r
+        Script += valueName;\r
+        Script += " ";\r
+\r
+        break;\r
+      }\r
+\r
+      case EW_WRITEUNINSTALLER:\r
+      {\r
+        Script += " ";\r
+        Script += ReadString2(e.Params[0]);\r
+        for (int j = 1; j < 3; j++)\r
+        {\r
+          Script += " ";\r
+          Script += UIntToString(e.Params[j]);\r
+        }\r
+        break;\r
+      }\r
+\r
+      default:\r
+      {\r
+        int numParams = kNumEntryParams;\r
+        if (e.Which < sizeof(kCommandPairs) / sizeof(kCommandPairs[0]))\r
+        {\r
+          const CCommandPair &pair = kCommandPairs[e.Which];\r
+          // Script += pair.Name;\r
+          numParams = pair.NumParams;\r
+        }\r
+        else\r
+        {\r
+          Script += "Unknown";\r
+          Script += UIntToString(e.Which);\r
+        }\r
+        Script += e.GetParamsString(numParams);\r
+      }\r
+      #endif\r
+    }\r
+    #ifdef NSIS_SCRIPT\r
+    Script += kCrLf;\r
+    #endif\r
+  }\r
+\r
+  {\r
+    Items.Sort(CompareItems, 0);\r
+    int i;\r
+    // if (IsSolid)\r
+    for (i = 0; i + 1 < Items.Size();)\r
+    {\r
+      bool sameName = IsUnicode ?\r
+        (Items[i].NameU == Items[i + 1].NameU) :\r
+        (Items[i].NameA == Items[i + 1].NameA);\r
+      if (Items[i].Pos == Items[i + 1].Pos && sameName)\r
+        Items.Delete(i + 1);\r
+      else\r
+        i++;\r
+    }\r
+    for (i = 0; i < Items.Size(); i++)\r
+    {\r
+      CItem &item = Items[i];\r
+      UInt32 curPos = item.Pos + 4;\r
+      for (int nextIndex = i + 1; nextIndex < Items.Size(); nextIndex++)\r
+      {\r
+        UInt32 nextPos = Items[nextIndex].Pos;\r
+        if (curPos <= nextPos)\r
+        {\r
+          item.EstimatedSizeIsDefined = true;\r
+          item.EstimatedSize = nextPos - curPos;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+    if (!IsSolid)\r
+    {\r
+      for (i = 0; i < Items.Size(); i++)\r
+      {\r
+        CItem &item = Items[i];\r
+        RINOK(_stream->Seek(GetPosOfNonSolidItem(i), STREAM_SEEK_SET, NULL));\r
+        const UInt32 kSigSize = 4 + 1 + 5;\r
+        BYTE sig[kSigSize];\r
+        size_t processedSize = kSigSize;\r
+        RINOK(ReadStream(_stream, sig, &processedSize));\r
+        if (processedSize < 4)\r
+          return S_FALSE;\r
+        UInt32 size = Get32(sig);\r
+        if ((size & 0x80000000) != 0)\r
+        {\r
+          item.IsCompressed = true;\r
+          // is compressed;\r
+          size &= ~0x80000000;\r
+          if (Method == NMethodType::kLZMA)\r
+          {\r
+            if (processedSize < 9)\r
+              return S_FALSE;\r
+            if (FilterFlag)\r
+              item.UseFilter = (sig[4] != 0);\r
+            item.DictionarySize = Get32(sig + 5 + (FilterFlag ? 1 : 0));\r
+          }\r
+        }\r
+        else\r
+        {\r
+          item.IsCompressed = false;\r
+          item.Size = size;\r
+          item.SizeIsDefined = true;\r
+        }\r
+        item.CompressedSize = size;\r
+        item.CompressedSizeIsDefined = true;\r
+      }\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::Parse()\r
+{\r
+  // UInt32 offset = ReadUInt32();\r
+  // ???? offset == FirstHeader.HeaderLength\r
+  /* UInt32 ehFlags = */ ReadUInt32();\r
+  CBlockHeader bhPages, bhSections, bhEntries, bhStrings, bhLangTables, bhCtlColors, bhData;\r
+  // CBlockHeader bgFont;\r
+  ReadBlockHeader(bhPages);\r
+  ReadBlockHeader(bhSections);\r
+  ReadBlockHeader(bhEntries);\r
+  ReadBlockHeader(bhStrings);\r
+  ReadBlockHeader(bhLangTables);\r
+  ReadBlockHeader(bhCtlColors);\r
+  // ReadBlockHeader(bgFont);\r
+  ReadBlockHeader(bhData);\r
+\r
+  _stringsPos = bhStrings.Offset;\r
+  UInt32 pos = GetOffset() + _stringsPos;\r
+  int numZeros0 = 0;\r
+  int numZeros1 = 0;\r
+  int i;\r
+  const int kBlockSize = 256;\r
+  for (i = 0; i < kBlockSize; i++)\r
+  {\r
+    if (pos >= _size || pos + 1 >= _size)\r
+      break;\r
+    char c0 = _data[pos++];\r
+    char c1 = _data[pos++];\r
+    wchar_t c = (c0 | ((wchar_t)c1 << 8));\r
+\r
+    if (c >= NS_UN_CODES_START && c < NS_UN_CODES_END)\r
+    {\r
+      if (pos >= _size || pos + 1 >= _size)\r
+        break;\r
+      pos += 2;\r
+      numZeros1++;\r
+    }\r
+    else\r
+    {\r
+      if (c0 == 0 && c1 != 0)\r
+        numZeros0++;\r
+      if (c1 == 0)\r
+        numZeros1++;\r
+    }\r
+    // printf("\nnumZeros0 = %2x %2x", _data[pos + 0],  _data[pos + 1]);\r
+  }\r
+  IsUnicode = (numZeros1 > numZeros0 * 3 + kBlockSize / 16);\r
+  // printf("\nnumZeros0 = %3d    numZeros1 = %3d", numZeros0,  numZeros1);\r
+  return ReadEntries(bhEntries);\r
+}\r
+\r
+static bool IsLZMA(const Byte *p, UInt32 &dictionary)\r
+{\r
+  dictionary = Get32(p + 1);\r
+  return (p[0] == 0x5D && p[1] == 0x00 && p[2] == 0x00 && p[5] == 0x00);\r
+}\r
+\r
+static bool IsLZMA(const Byte *p, UInt32 &dictionary, bool &thereIsFlag)\r
+{\r
+  if (IsLZMA(p, dictionary))\r
+  {\r
+    thereIsFlag = false;\r
+    return true;\r
+  }\r
+  if (IsLZMA(p + 1, dictionary))\r
+  {\r
+    thereIsFlag = true;\r
+    return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+static bool IsBZip2(const Byte *p)\r
+{\r
+  return (p[0] == 0x31 && p[1] < 14);\r
+}\r
+\r
+HRESULT CInArchive::Open2(\r
+      DECL_EXTERNAL_CODECS_LOC_VARS2\r
+      )\r
+{\r
+  RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &StreamOffset));\r
+\r
+  const UInt32 kSigSize = 4 + 1 + 5 + 1; // size, flag, lzma props, lzma first byte\r
+  BYTE sig[kSigSize];\r
+  RINOK(ReadStream_FALSE(_stream, sig, kSigSize));\r
+  UInt64 position;\r
+  RINOK(_stream->Seek(StreamOffset, STREAM_SEEK_SET, &position));\r
+\r
+  _headerIsCompressed = true;\r
+  IsSolid = true;\r
+  FilterFlag = false;\r
+  DictionarySize = 1;\r
+\r
+  UInt32 compressedHeaderSize = Get32(sig);\r
+  \r
+  if (compressedHeaderSize == FirstHeader.HeaderLength)\r
+  {\r
+    _headerIsCompressed = false;\r
+    IsSolid = false;\r
+    Method = NMethodType::kCopy;\r
+  }\r
+  else if (IsLZMA(sig, DictionarySize, FilterFlag))\r
+  {\r
+    Method = NMethodType::kLZMA;\r
+  }\r
+  else if (IsLZMA(sig + 4, DictionarySize, FilterFlag))\r
+  {\r
+    IsSolid = false;\r
+    Method = NMethodType::kLZMA;\r
+  }\r
+  else if (sig[3] == 0x80)\r
+  {\r
+    IsSolid = false;\r
+    if (IsBZip2(sig + 4))\r
+      Method = NMethodType::kBZip2;\r
+    else\r
+      Method = NMethodType::kDeflate;\r
+  }\r
+  else if (IsBZip2(sig))\r
+  {\r
+    Method = NMethodType::kBZip2;\r
+  }\r
+  else\r
+  {\r
+    Method = NMethodType::kDeflate;\r
+  }\r
+\r
+  _posInData = 0;\r
+  if (!IsSolid)\r
+  {\r
+    _headerIsCompressed = ((compressedHeaderSize & 0x80000000) != 0);\r
+    if (_headerIsCompressed)\r
+      compressedHeaderSize &= ~0x80000000;\r
+    _nonSolidStartOffset = compressedHeaderSize;\r
+    RINOK(_stream->Seek(StreamOffset + 4, STREAM_SEEK_SET, NULL));\r
+  }\r
+  UInt32 unpackSize = FirstHeader.HeaderLength;\r
+  if (_headerIsCompressed)\r
+  {\r
+    // unpackSize = (1 << 23);\r
+    _data.SetCapacity(unpackSize);\r
+    RINOK(Decoder.Init(\r
+        EXTERNAL_CODECS_LOC_VARS\r
+        _stream, Method, FilterFlag, UseFilter));\r
+    size_t processedSize = unpackSize;\r
+    RINOK(Decoder.Read(_data, &processedSize));\r
+    if (processedSize != unpackSize)\r
+      return S_FALSE;\r
+    _size = processedSize;\r
+    if (IsSolid)\r
+    {\r
+      UInt32 size2 = ReadUInt32();\r
+      if (size2 < _size)\r
+        _size = size2;\r
+    }\r
+  }\r
+  else\r
+  {\r
+    _data.SetCapacity(unpackSize);\r
+    _size = (size_t)unpackSize;\r
+    RINOK(ReadStream_FALSE(_stream, (Byte *)_data, unpackSize));\r
+  }\r
+  return Parse();\r
+}\r
+\r
+/*\r
+NsisExe =\r
+{\r
+  ExeStub\r
+  Archive  // must start from 512 * N\r
+  #ifndef NSIS_CONFIG_CRC_ANAL\r
+  {\r
+    Some additional data\r
+  }\r
+}\r
+\r
+Archive\r
+{\r
+  FirstHeader\r
+  Data\r
+  #ifdef NSIS_CONFIG_CRC_SUPPORT && FirstHeader.ThereIsCrc()\r
+  {\r
+    CRC\r
+  }\r
+}\r
+\r
+FirstHeader\r
+{\r
+  UInt32 Flags;\r
+  Byte Signature[16];\r
+  // points to the header+sections+entries+stringtable in the datablock\r
+  UInt32 HeaderLength;\r
+  UInt32 ArchiveSize;\r
+}\r
+*/\r
+\r
+HRESULT CInArchive::Open(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    IInStream *inStream, const UInt64 *maxCheckStartPosition)\r
+{\r
+  Clear();\r
+  RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));\r
+  UInt64 maxSize = ((maxCheckStartPosition != 0) ? *maxCheckStartPosition : 0);\r
+  const UInt32 kStep = 512;\r
+  Byte buffer[kStep];\r
+  \r
+  UInt64 position = 0;\r
+  for (; position <= maxSize; position += kStep)\r
+  {\r
+    RINOK(ReadStream_FALSE(inStream, buffer, kStep));\r
+    if (memcmp(buffer + 4, kSignature, kSignatureSize) == 0)\r
+      break;\r
+  }\r
+  if (position > maxSize)\r
+    return S_FALSE;\r
+  const UInt32 kStartHeaderSize = 4 * 7;\r
+  RINOK(inStream->Seek(0, STREAM_SEEK_END, &_archiveSize));\r
+  RINOK(inStream->Seek(position + kStartHeaderSize, STREAM_SEEK_SET, 0));\r
+  FirstHeader.Flags = Get32(buffer);\r
+  FirstHeader.HeaderLength = Get32(buffer + kSignatureSize + 4);\r
+  FirstHeader.ArchiveSize = Get32(buffer + kSignatureSize + 8);\r
+  if (_archiveSize - position < FirstHeader.ArchiveSize)\r
+    return S_FALSE;\r
+\r
+  try\r
+  {\r
+    _stream = inStream;\r
+    HRESULT res = Open2(EXTERNAL_CODECS_LOC_VARS2);\r
+    if (res != S_OK)\r
+      Clear();\r
+    _stream.Release();\r
+    return res;\r
+  }\r
+  catch(...) { Clear(); return S_FALSE; }\r
+}\r
+\r
+void CInArchive::Clear()\r
+{\r
+  #ifdef NSIS_SCRIPT\r
+  Script.Empty();\r
+  #endif\r
+  Items.Clear();\r
+  _stream.Release();\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h
new file mode 100755 (executable)
index 0000000..1c36d09
--- /dev/null
@@ -0,0 +1,181 @@
+// NsisIn.h\r
+\r
+#ifndef __ARCHIVE_NSIS_IN_H\r
+#define __ARCHIVE_NSIS_IN_H\r
+\r
+#include "Common/Buffer.h"\r
+#include "Common/MyCom.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "NsisDecode.h"\r
+\r
+// #define NSIS_SCRIPT\r
+\r
+namespace NArchive {\r
+namespace NNsis {\r
+\r
+const int kSignatureSize = 16;\r
+#define NSIS_SIGNATURE { 0xEF, 0xBE, 0xAD, 0xDE, 0x4E, 0x75, 0x6C, 0x6C, 0x73, 0x6F, 0x66, 0x74, 0x49, 0x6E, 0x73, 0x74}\r
+\r
+extern Byte kSignature[kSignatureSize];\r
+\r
+const UInt32 kFlagsMask = 0xF;\r
+namespace NFlags\r
+{\r
+  const UInt32 kUninstall = 1;\r
+  const UInt32 kSilent = 2;\r
+  const UInt32 kNoCrc = 4;\r
+  const UInt32 kForceCrc = 8;\r
+}\r
+\r
+struct CFirstHeader\r
+{\r
+  UInt32 Flags;\r
+  UInt32 HeaderLength;\r
\r
+  UInt32 ArchiveSize;\r
+\r
+  bool ThereIsCrc() const\r
+  {\r
+    if ((Flags & NFlags::kForceCrc ) != 0)\r
+      return true;\r
+    return ((Flags & NFlags::kNoCrc) == 0);\r
+  }\r
+\r
+  UInt32 GetDataSize() const { return ArchiveSize - (ThereIsCrc() ? 4 : 0); }\r
+};\r
+\r
+\r
+struct CBlockHeader\r
+{\r
+  UInt32 Offset;\r
+  UInt32 Num;\r
+};\r
+\r
+struct CItem\r
+{\r
+  AString PrefixA;\r
+  UString PrefixU;\r
+  AString NameA;\r
+  UString NameU;\r
+  FILETIME MTime;\r
+  bool IsUnicode;\r
+  bool UseFilter;\r
+  bool IsCompressed;\r
+  bool SizeIsDefined;\r
+  bool CompressedSizeIsDefined;\r
+  bool EstimatedSizeIsDefined;\r
+  UInt32 Pos;\r
+  UInt32 Size;\r
+  UInt32 CompressedSize;\r
+  UInt32 EstimatedSize;\r
+  UInt32 DictionarySize;\r
+  \r
+  CItem(): IsUnicode(false), UseFilter(false), IsCompressed(true), SizeIsDefined(false),\r
+      CompressedSizeIsDefined(false), EstimatedSizeIsDefined(false), Size(0), DictionarySize(1) {}\r
+\r
+  bool IsINSTDIR() const\r
+  {\r
+    return (PrefixA.Length() >= 3 || PrefixU.Length() >= 3);\r
+  }\r
+\r
+  UString GetReducedName(bool unicode) const\r
+  {\r
+    UString s;\r
+    if (unicode)\r
+      s = PrefixU;\r
+    else\r
+      s = MultiByteToUnicodeString(PrefixA);\r
+    if (s.Length() > 0)\r
+      if (s[s.Length() - 1] != L'\\')\r
+        s += L'\\';\r
+    if (unicode)\r
+      s += NameU;\r
+    else\r
+      s += MultiByteToUnicodeString(NameA);\r
+    const int len = 9;\r
+    if (s.Left(len).CompareNoCase(L"$INSTDIR\\") == 0)\r
+      s = s.Mid(len);\r
+    return s;\r
+  }\r
+};\r
+\r
+class CInArchive\r
+{\r
+  UInt64 _archiveSize;\r
+  CMyComPtr<IInStream> _stream;\r
+\r
+  Byte ReadByte();\r
+  UInt32 ReadUInt32();\r
+  HRESULT Open2(\r
+      DECL_EXTERNAL_CODECS_LOC_VARS2\r
+      );\r
+  void ReadBlockHeader(CBlockHeader &bh);\r
+  AString ReadStringA(UInt32 pos) const;\r
+  UString ReadStringU(UInt32 pos) const;\r
+  AString ReadString2A(UInt32 pos) const;\r
+  UString ReadString2U(UInt32 pos) const;\r
+  AString ReadString2(UInt32 pos) const;\r
+  AString ReadString2Qw(UInt32 pos) const;\r
+  HRESULT ReadEntries(const CBlockHeader &bh);\r
+  HRESULT Parse();\r
+\r
+  CByteBuffer _data;\r
+  UInt64 _size;\r
+\r
+  size_t _posInData;\r
+\r
+  UInt32 _stringsPos;\r
+\r
+\r
+  bool _headerIsCompressed;\r
+  UInt32 _nonSolidStartOffset;\r
+public:\r
+  HRESULT Open(\r
+      DECL_EXTERNAL_CODECS_LOC_VARS\r
+      IInStream *inStream, const UInt64 *maxCheckStartPosition);\r
+  void Clear();\r
+\r
+  UInt64 StreamOffset;\r
+  CDecoder Decoder;\r
+  CObjectVector<CItem> Items;\r
+  CFirstHeader FirstHeader;\r
+  NMethodType::EEnum Method;\r
+  UInt32 DictionarySize;\r
+  bool IsSolid;\r
+  bool UseFilter;\r
+  bool FilterFlag;\r
+  bool IsUnicode;\r
+\r
+  #ifdef NSIS_SCRIPT\r
+  AString Script;\r
+  #endif\r
+  UInt32 GetOffset() const { return IsSolid ? 4 : 0; }\r
+  UInt64 GetDataPos(int index)\r
+  {\r
+    const CItem &item = Items[index];\r
+    return GetOffset() + FirstHeader.HeaderLength + item.Pos;\r
+  }\r
+\r
+  UInt64 GetPosOfSolidItem(int index) const\r
+  {\r
+    const CItem &item = Items[index];\r
+    return 4 + FirstHeader.HeaderLength + item.Pos;\r
+  }\r
+  \r
+  UInt64 GetPosOfNonSolidItem(int index) const\r
+  {\r
+    const CItem &item = Items[index];\r
+    return StreamOffset + _nonSolidStartOffset + 4  + item.Pos;\r
+  }\r
+\r
+  void Release()\r
+  {\r
+    Decoder.Release();\r
+  }\r
+\r
+};\r
+\r
+}}\r
+  \r
+#endif\r
diff --git a/CPP/7zip/Archive/Nsis/NsisRegister.cpp b/CPP/7zip/Archive/Nsis/NsisRegister.cpp
new file mode 100755 (executable)
index 0000000..66cf10f
--- /dev/null
@@ -0,0 +1,13 @@
+// NsisRegister.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/RegisterArc.h"\r
+\r
+#include "NsisHandler.h"\r
+static IInArchive *CreateArc() { return new NArchive::NNsis::CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"Nsis", L"", 0, 0x9, NSIS_SIGNATURE, NArchive::NNsis::kSignatureSize, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Nsis)\r
diff --git a/CPP/7zip/Archive/Nsis/StdAfx.h b/CPP/7zip/Archive/Nsis/StdAfx.h
new file mode 100755 (executable)
index 0000000..a4e6173
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+#include "../../../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp
new file mode 100755 (executable)
index 0000000..f1df803
--- /dev/null
@@ -0,0 +1,1764 @@
+// NtfsHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+// #define SHOW_DEBUG_INFO\r
+// #define SHOW_DEBUG_INFO2\r
+\r
+#if defined(SHOW_DEBUG_INFO) || defined(SHOW_DEBUG_INFO2)\r
+#include <stdio.h>\r
+#endif\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/Buffer.h"\r
+#include "Common/ComTry.h"\r
+#include "Common/IntToString.h"\r
+#include "Common/MyCom.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/CopyCoder.h"\r
+\r
+#include "Common/DummyOutStream.h"\r
+\r
+#ifdef SHOW_DEBUG_INFO\r
+#define PRF(x) x\r
+#else\r
+#define PRF(x)\r
+#endif\r
+\r
+#ifdef SHOW_DEBUG_INFO2\r
+#define PRF2(x) x\r
+#else\r
+#define PRF2(x)\r
+#endif\r
+\r
+#define Get16(p) GetUi16(p)\r
+#define Get32(p) GetUi32(p)\r
+#define Get64(p) GetUi64(p)\r
+\r
+#define G16(p, dest) dest = Get16(p);\r
+#define G32(p, dest) dest = Get32(p);\r
+#define G64(p, dest) dest = Get64(p);\r
+\r
+namespace NArchive {\r
+namespace Ntfs {\r
+\r
+static const UInt32 kNumSysRecs = 16;\r
+static const UInt32 kRecIndex_Volume = 3;\r
+static const UInt32 kRecIndex_BadClus = 8;\r
+\r
+struct CHeader\r
+{\r
+  Byte SectorSizeLog;\r
+  Byte ClusterSizeLog;\r
+  // Byte MediaType;\r
+  UInt32 NumHiddenSectors;\r
+  UInt64 NumClusters;\r
+  UInt64 MftCluster;\r
+  UInt64 SerialNumber;\r
+  UInt16 SectorsPerTrack;\r
+  UInt16 NumHeads;\r
+\r
+  UInt64 GetPhySize() const { return NumClusters << ClusterSizeLog; }\r
+  UInt32 ClusterSize() const { return (UInt32)1 << ClusterSizeLog; }\r
+  bool Parse(const Byte *p);\r
+};\r
+\r
+static int GetLog(UInt32 num)\r
+{\r
+  for (int i = 0; i < 31; i++)\r
+    if (((UInt32)1 << i) == num)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+bool CHeader::Parse(const Byte *p)\r
+{\r
+  if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA)\r
+    return false;\r
+\r
+  int codeOffset = 0;\r
+  switch (p[0])\r
+  {\r
+    case 0xE9: codeOffset = 3 + (Int16)Get16(p + 1); break;\r
+    case 0xEB: if (p[2] != 0x90) return false; codeOffset = 2 + (signed char)p[1]; break;\r
+    default: return false;\r
+  }\r
+  Byte sectorsPerClusterLog;\r
+\r
+  if (memcmp(p + 3, "NTFS    ", 8) != 0)\r
+    return false;\r
+  {\r
+    int s = GetLog(Get16(p + 11));\r
+    if (s < 9 || s > 12)\r
+      return false;\r
+    SectorSizeLog = (Byte)s;\r
+    s = GetLog(p[13]);\r
+    if (s < 0)\r
+      return false;\r
+    sectorsPerClusterLog = (Byte)s;\r
+    ClusterSizeLog = SectorSizeLog + sectorsPerClusterLog;\r
+  }\r
+\r
+  for (int i = 14; i < 21; i++)\r
+    if (p[i] != 0)\r
+      return false;\r
+\r
+  // MediaType = p[21];\r
+  if (Get16(p + 22) != 0) // NumFatSectors\r
+    return false;\r
+  G16(p + 24, SectorsPerTrack);\r
+  G16(p + 26, NumHeads);\r
+  G32(p + 28, NumHiddenSectors);\r
+  if (Get32(p + 32) != 0) // NumSectors32\r
+    return false;\r
+\r
+  // DriveNumber = p[0x24];\r
+  if (p[0x25] != 0) // CurrentHead\r
+    return false;\r
+  /*\r
+  NTFS-HDD:   p[0x26] = 0x80\r
+  NTFS-FLASH: p[0x26] = 0\r
+  */\r
+  if (p[0x26] != 0x80 && p[0x26] != 0) // ExtendedBootSig\r
+    return false;\r
+  if (p[0x27] != 0) // reserved\r
+    return false;\r
+  UInt64 numSectors = Get64(p + 0x28);\r
+  NumClusters = numSectors >> sectorsPerClusterLog;\r
+\r
+  G64(p + 0x30, MftCluster);\r
+  // G64(p + 0x38, Mft2Cluster);\r
+  G64(p + 0x48, SerialNumber);\r
+  UInt32 numClustersInMftRec;\r
+  UInt32 numClustersInIndexBlock;\r
+  G32(p + 0x40, numClustersInMftRec);\r
+  G32(p + 0x44, numClustersInIndexBlock);\r
+  return (numClustersInMftRec < 256 && numClustersInIndexBlock < 256);\r
+}\r
+\r
+struct CMftRef\r
+{\r
+  UInt64 Val;\r
+  UInt64 GetIndex() const { return Val & (((UInt64)1 << 48) - 1); }\r
+  UInt16 GetNumber() const { return (UInt16)(Val >> 48); }\r
+  bool IsBaseItself() const { return Val == 0; }\r
+};\r
+\r
+#define ATNAME(n) ATTR_TYPE_ ## n\r
+#define DEF_ATTR_TYPE(v, n) ATNAME(n) = v\r
+\r
+enum\r
+{\r
+  DEF_ATTR_TYPE(0x00, UNUSED),\r
+  DEF_ATTR_TYPE(0x10, STANDARD_INFO),\r
+  DEF_ATTR_TYPE(0x20, ATTRIBUTE_LIST),\r
+  DEF_ATTR_TYPE(0x30, FILE_NAME),\r
+  DEF_ATTR_TYPE(0x40, OBJECT_ID),\r
+  DEF_ATTR_TYPE(0x50, SECURITY_DESCRIPTOR),\r
+  DEF_ATTR_TYPE(0x60, VOLUME_NAME),\r
+  DEF_ATTR_TYPE(0x70, VOLUME_INFO),\r
+  DEF_ATTR_TYPE(0x80, DATA),\r
+  DEF_ATTR_TYPE(0x90, INDEX_ROOT),\r
+  DEF_ATTR_TYPE(0xA0, INDEX_ALLOCATION),\r
+  DEF_ATTR_TYPE(0xB0, BITMAP),\r
+  DEF_ATTR_TYPE(0xC0, REPARSE_POINT),\r
+  DEF_ATTR_TYPE(0xD0, EA_INFO),\r
+  DEF_ATTR_TYPE(0xE0, EA),\r
+  DEF_ATTR_TYPE(0xF0, PROPERTY_SET),\r
+  DEF_ATTR_TYPE(0x100, LOGGED_UTILITY_STREAM),\r
+  DEF_ATTR_TYPE(0x1000, FIRST_USER_DEFINED_ATTRIBUTE)\r
+};\r
+\r
+static const Byte kFileNameType_Posix = 0;\r
+static const Byte kFileNameType_Win32 = 1;\r
+static const Byte kFileNameType_Dos = 2;\r
+static const Byte kFileNameType_Win32Dos = 3;\r
+\r
+struct CFileNameAttr\r
+{\r
+  CMftRef ParentDirRef;\r
+  // UInt64 CTime;\r
+  // UInt64 MTime;\r
+  // UInt64 ThisRecMTime;\r
+  // UInt64 ATime;\r
+  // UInt64 AllocatedSize;\r
+  // UInt64 DataSize;\r
+  // UInt16 PackedEaSize;\r
+  UString Name;\r
+  UInt32 Attrib;\r
+  Byte NameType;\r
+  \r
+  bool IsDos() const { return NameType == kFileNameType_Dos; }\r
+  bool Parse(const Byte *p, unsigned size);\r
+};\r
+\r
+static void GetString(const Byte *p, unsigned length, UString &res)\r
+{\r
+  wchar_t *s = res.GetBuffer(length);\r
+  for (unsigned i = 0; i < length; i++)\r
+    s[i] = Get16(p + i * 2);\r
+  s[length] = 0;\r
+  res.ReleaseBuffer();\r
+}\r
+\r
+bool CFileNameAttr::Parse(const Byte *p, unsigned size)\r
+{\r
+  if (size < 0x42)\r
+    return false;\r
+  G64(p + 0x00, ParentDirRef.Val);\r
+  // G64(p + 0x08, CTime);\r
+  // G64(p + 0x10, MTime);\r
+  // G64(p + 0x18, ThisRecMTime);\r
+  // G64(p + 0x20, ATime);\r
+  // G64(p + 0x28, AllocatedSize);\r
+  // G64(p + 0x30, DataSize);\r
+  G32(p + 0x38, Attrib);\r
+  // G16(p + 0x3C, PackedEaSize);\r
+  NameType = p[0x41];\r
+  unsigned length = p[0x40];\r
+  if (0x42 + length > size)\r
+    return false;\r
+  GetString(p + 0x42, length, Name);\r
+  return true;\r
+}\r
+\r
+struct CSiAttr\r
+{\r
+  UInt64 CTime;\r
+  UInt64 MTime;\r
+  // UInt64 ThisRecMTime;\r
+  UInt64 ATime;\r
+  UInt32 Attrib;\r
+\r
+  /*\r
+  UInt32 MaxVersions;\r
+  UInt32 Version;\r
+  UInt32 ClassId;\r
+  UInt32 OwnerId;\r
+  UInt32 SecurityId;\r
+  UInt64 QuotaCharged;\r
+  */\r
+\r
+  bool Parse(const Byte *p, unsigned size);\r
+};\r
+\r
+bool CSiAttr::Parse(const Byte *p, unsigned size)\r
+{\r
+  if (size < 0x24)\r
+    return false;\r
+  G64(p + 0x00, CTime);\r
+  G64(p + 0x08, MTime);\r
+  // G64(p + 0x10, ThisRecMTime);\r
+  G64(p + 0x18, ATime);\r
+  G32(p + 0x20, Attrib);\r
+  return true;\r
+}\r
+\r
+static const UInt64 kEmptyExtent = (UInt64)(Int64)-1;\r
+\r
+struct CExtent\r
+{\r
+  UInt64 Virt;\r
+  UInt64 Phy;\r
+\r
+  bool IsEmpty() const { return Phy == kEmptyExtent; }\r
+};\r
+\r
+struct CVolInfo\r
+{\r
+  Byte MajorVer;\r
+  Byte MinorVer;\r
+  // UInt16 Flags;\r
+\r
+  bool Parse(const Byte *p, unsigned size);\r
+};\r
+\r
+bool CVolInfo::Parse(const Byte *p, unsigned size)\r
+{\r
+  if (size < 12)\r
+    return false;\r
+  MajorVer = p[8];\r
+  MinorVer = p[9];\r
+  // Flags = Get16(p + 10);\r
+  return true;\r
+}\r
+\r
+struct CAttr\r
+{\r
+  UInt32 Type;\r
+  // UInt32 Length;\r
+  UString Name;\r
+  // UInt16 Flags;\r
+  // UInt16 Instance;\r
+  CByteBuffer Data;\r
+  Byte NonResident;\r
+\r
+  // Non-Resident\r
+  Byte CompressionUnit;\r
+  UInt64 LowVcn;\r
+  UInt64 HighVcn;\r
+  UInt64 AllocatedSize;\r
+  UInt64 Size;\r
+  UInt64 PackSize;\r
+  UInt64 InitializedSize;\r
+\r
+  // Resident\r
+  // UInt16 ResidentFlags;\r
+\r
+  bool IsCompressionUnitSupported() const { return CompressionUnit == 0 || CompressionUnit == 4; }\r
+\r
+  UInt32 Parse(const Byte *p, unsigned size);\r
+  bool ParseFileName(CFileNameAttr &a) const { return a.Parse(Data, (unsigned)Data.GetCapacity()); }\r
+  bool ParseSi(CSiAttr &a) const { return a.Parse(Data, (unsigned)Data.GetCapacity()); }\r
+  bool ParseVolInfo(CVolInfo &a) const { return a.Parse(Data, (unsigned)Data.GetCapacity()); }\r
+  bool ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax, int compressionUnit) const;\r
+  UInt64 GetSize() const { return NonResident ? Size : Data.GetCapacity(); }\r
+  UInt64 GetPackSize() const\r
+  {\r
+    if (!NonResident)\r
+      return Data.GetCapacity();\r
+    if (CompressionUnit != 0)\r
+      return PackSize;\r
+    return AllocatedSize;\r
+  }\r
+};\r
+\r
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }\r
+\r
+static int CompareAttr(void *const *elem1, void *const *elem2, void *)\r
+{\r
+  const CAttr &a1 = *(*((const CAttr **)elem1));\r
+  const CAttr &a2 = *(*((const CAttr **)elem2));\r
+  RINOZ(MyCompare(a1.Type, a2.Type));\r
+  RINOZ(MyCompare(a1.Name, a2.Name));\r
+  return MyCompare(a1.LowVcn, a2.LowVcn);\r
+}\r
+\r
+UInt32 CAttr::Parse(const Byte *p, unsigned size)\r
+{\r
+  if (size < 4)\r
+    return 0;\r
+  G32(p, Type);\r
+  if (Type == 0xFFFFFFFF)\r
+    return 4;\r
+  if (size < 0x18)\r
+    return 0;\r
+  PRF(printf(" T=%2X", Type));\r
+  \r
+  UInt32 length = Get32(p + 0x04);\r
+  PRF(printf(" L=%3d", length));\r
+  if (length > size)\r
+    return 0;\r
+  NonResident = p[0x08];\r
+  {\r
+    int nameLength = p[9];\r
+    UInt32 nameOffset = Get16(p + 0x0A);\r
+    if (nameLength != 0)\r
+    {\r
+      if (nameOffset + nameLength * 2 > length)\r
+        return 0;\r
+      GetString(p + nameOffset, nameLength, Name);\r
+      PRF(printf(" N=%S", Name));\r
+    }\r
+  }\r
+\r
+  // G16(p + 0x0C, Flags);\r
+  // G16(p + 0x0E, Instance);\r
+  // PRF(printf(" F=%4X", Flags));\r
+  // PRF(printf(" Inst=%d", Instance));\r
+\r
+  UInt32 dataSize;\r
+  UInt32 offs;\r
+  if (NonResident)\r
+  {\r
+    if (length < 0x40)\r
+      return 0;\r
+    PRF(printf(" NR"));\r
+    G64(p + 0x10, LowVcn);\r
+    G64(p + 0x18, HighVcn);\r
+    G64(p + 0x28, AllocatedSize);\r
+    G64(p + 0x30, Size);\r
+    G64(p + 0x38, InitializedSize);\r
+    G16(p + 0x20, offs);\r
+    CompressionUnit = p[0x22];\r
+\r
+    PackSize = Size;\r
+    if (CompressionUnit != 0)\r
+    {\r
+      if (length < 0x48)\r
+        return 0;\r
+      G64(p + 0x40, PackSize);\r
+      PRF(printf(" PS=%I64x", PackSize));\r
+    }\r
+\r
+    // PRF(printf("\n"));\r
+    PRF(printf(" ASize=%4I64d", AllocatedSize));\r
+    PRF(printf(" Size=%I64d", Size));\r
+    PRF(printf(" IS=%I64d", InitializedSize));\r
+    PRF(printf(" Low=%I64d", LowVcn));\r
+    PRF(printf(" High=%I64d", HighVcn));\r
+    PRF(printf(" CU=%d", (int)CompressionUnit));\r
+    dataSize = length - offs;\r
+  }\r
+  else\r
+  {\r
+    if (length < 0x18)\r
+      return 0;\r
+    PRF(printf(" RES"));\r
+    dataSize = Get32(p + 0x10);\r
+    PRF(printf(" dataSize=%3d", dataSize));\r
+    offs = Get16(p + 0x14);\r
+    // G16(p + 0x16, ResidentFlags);\r
+    // PRF(printf(" ResFlags=%4X", ResidentFlags));\r
+  }\r
+  if (offs > length || dataSize > length || length - dataSize < offs)\r
+    return 0;\r
+  Data.SetCapacity(dataSize);\r
+  memcpy(Data, p + offs, dataSize);\r
+  #ifdef SHOW_DEBUG_INFO\r
+  PRF(printf("  : "));\r
+  for (unsigned i = 0; i < Data.GetCapacity(); i++)\r
+  {\r
+    PRF(printf(" %02X", (int)Data[i]));\r
+  }\r
+  #endif\r
+  return length;\r
+}\r
+\r
+bool CAttr::ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax, int compressionUnit) const\r
+{\r
+  const Byte *p = Data;\r
+  unsigned size = (unsigned)Data.GetCapacity();\r
+  UInt64 vcn = LowVcn;\r
+  UInt64 lcn = 0;\r
+  UInt64 highVcn1 = HighVcn + 1;\r
+  if (LowVcn != extents.Back().Virt || highVcn1 > (UInt64)1 << 63)\r
+    return false;\r
+\r
+  extents.DeleteBack();\r
+\r
+  PRF2(printf("\n# ParseExtents # LowVcn = %4I64X # HighVcn = %4I64X", LowVcn, HighVcn));\r
+\r
+  while (size > 0)\r
+  {\r
+    Byte b = *p++;\r
+    size--;\r
+    if (b == 0)\r
+      break;\r
+    UInt32 num = b & 0xF;\r
+    if (num == 0 || num > 8 || num > size)\r
+      return false;\r
+\r
+    int i;\r
+    UInt64 vSize = p[num - 1];\r
+    for (i = (int)num - 2; i >= 0; i--)\r
+      vSize = (vSize << 8) | p[i];\r
+    if (vSize == 0)\r
+      return false;\r
+    p += num;\r
+    size -= num;\r
+    if ((highVcn1 - vcn) < vSize)\r
+      return false;\r
+\r
+    num = (b >> 4) & 0xF;\r
+    if (num > 8 || num > size)\r
+      return false;\r
+    CExtent e;\r
+    e.Virt = vcn;\r
+    if (num == 0)\r
+    {\r
+      if (compressionUnit == 0)\r
+        return false;\r
+      e.Phy = kEmptyExtent;\r
+    }\r
+    else\r
+    {\r
+      Int64 v = (signed char)p[num - 1];\r
+      for (i = (int)num - 2; i >= 0; i--)\r
+        v = (v << 8) | p[i];\r
+      p += num;\r
+      size -= num;\r
+      lcn += v;\r
+      if (lcn > numClustersMax)\r
+        return false;\r
+      e.Phy = lcn;\r
+    }\r
+    extents.Add(e);\r
+    vcn += vSize;\r
+  }\r
+  CExtent e;\r
+  e.Phy = kEmptyExtent;\r
+  e.Virt = vcn;\r
+  extents.Add(e);\r
+  return (highVcn1 == vcn);\r
+}\r
+\r
+static const UInt64 kEmptyTag = (UInt64)(Int64)-1;\r
+\r
+static const int kNumCacheChunksLog = 1;\r
+static const UInt32 kNumCacheChunks = (1 << kNumCacheChunksLog);\r
+\r
+class CInStream:\r
+  public IInStream,\r
+  public CMyUnknownImp\r
+{\r
+  UInt64 _virtPos;\r
+  UInt64 _physPos;\r
+  UInt64 _curRem;\r
+  bool _sparseMode;\r
+  size_t _compressedPos;\r
+  \r
+  UInt64 _tags[kNumCacheChunks];\r
+  int _chunkSizeLog;\r
+  CByteBuffer _inBuf;\r
+  CByteBuffer _outBuf;\r
+public:\r
+  CMyComPtr<IInStream> Stream;\r
+  UInt64 Size;\r
+  UInt64 InitializedSize;\r
+  int BlockSizeLog;\r
+  int CompressionUnit;\r
+  bool InUse;\r
+  CRecordVector<CExtent> Extents;\r
+\r
+  HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }\r
+\r
+  UInt32 GetCuSize() const { return (UInt32)1 << (BlockSizeLog + CompressionUnit); }\r
+  HRESULT InitAndSeek(int compressionUnit)\r
+  {\r
+    CompressionUnit = compressionUnit;\r
+    if (compressionUnit != 0)\r
+    {\r
+      UInt32 cuSize = GetCuSize();\r
+      _inBuf.SetCapacity(cuSize);\r
+      _chunkSizeLog = BlockSizeLog + CompressionUnit;\r
+      _outBuf.SetCapacity(kNumCacheChunks << _chunkSizeLog);\r
+    }\r
+    for (int i = 0; i < kNumCacheChunks; i++)\r
+      _tags[i] = kEmptyTag;\r
+\r
+    _sparseMode = false;\r
+    _curRem = 0;\r
+    _virtPos = 0;\r
+    _physPos = 0;\r
+    const CExtent &e = Extents[0];\r
+    if (!e.IsEmpty())\r
+      _physPos = e.Phy << BlockSizeLog;\r
+    return SeekToPhys();\r
+  }\r
+\r
+  MY_UNKNOWN_IMP1(IInStream)\r
+\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);\r
+};\r
+\r
+static size_t Lznt1Dec(Byte *dest, size_t outBufLim, size_t destLen, const Byte *src, size_t srcLen)\r
+{\r
+  size_t destSize = 0;\r
+  while (destSize < destLen)\r
+  {\r
+    if (srcLen < 2 || (destSize & 0xFFF) != 0)\r
+      break;\r
+    UInt32 v = Get16(src);\r
+    if (v == 0)\r
+      break;\r
+    src += 2;\r
+    srcLen -= 2;\r
+    UInt32 comprSize = (v & 0xFFF) + 1;\r
+    if (comprSize > srcLen)\r
+      break;\r
+    srcLen -= comprSize;\r
+    if ((v & 0x8000) == 0)\r
+    {\r
+      if (comprSize != (1 << 12))\r
+        break;\r
+      memcpy(dest + destSize, src, comprSize);\r
+      src += comprSize;\r
+      destSize += comprSize;\r
+    }\r
+    else\r
+    {\r
+      if (destSize + (1 << 12) > outBufLim || (src[0] & 1) != 0)\r
+        return 0;\r
+      int numDistBits = 4;\r
+      UInt32 sbOffset = 0;\r
+      UInt32 pos = 0;\r
+\r
+      do\r
+      {\r
+        comprSize--;\r
+        for (UInt32 mask = src[pos++] | 0x100; mask > 1 && comprSize > 0; mask >>= 1)\r
+        {\r
+          if ((mask & 1) == 0)\r
+          {\r
+            if (sbOffset >= (1 << 12))\r
+              return 0;\r
+            dest[destSize++] = src[pos++];\r
+            sbOffset++;\r
+            comprSize--;\r
+          }\r
+          else\r
+          {\r
+            if (comprSize < 2)\r
+              return 0;\r
+            UInt32 v = Get16(src + pos);\r
+            pos += 2;\r
+            comprSize -= 2;\r
+\r
+            while (((sbOffset - 1) >> numDistBits) != 0)\r
+              numDistBits++;\r
+\r
+            UInt32 len = (v & (0xFFFF >> numDistBits)) + 3;\r
+            if (sbOffset + len > (1 << 12))\r
+              return 0;\r
+            UInt32 dist = (v >> (16 - numDistBits));\r
+            if (dist >= sbOffset)\r
+              return 0;\r
+            Int32 offs = -1 - dist;\r
+            Byte *p = dest + destSize;\r
+            for (UInt32 t = 0; t < len; t++)\r
+              p[t] = p[t + offs];\r
+            destSize += len;\r
+            sbOffset += len;\r
+          }\r
+        }\r
+      }\r
+      while (comprSize > 0);\r
+      src += pos;\r
+    }\r
+  }\r
+  return destSize;\r
+}\r
+\r
+STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize != NULL)\r
+    *processedSize = 0;\r
+  if (_virtPos >= Size)\r
+    return (Size == _virtPos) ? S_OK: E_FAIL;\r
+  if (size == 0)\r
+    return S_OK;\r
+  UInt64 rem = Size - _virtPos;\r
+  if (size > rem)\r
+    size = (UInt32)rem;\r
+  if (_virtPos >= InitializedSize)\r
+  {\r
+    memset((Byte *)data, 0, size);\r
+    _virtPos += size;\r
+    *processedSize = size;\r
+    return S_OK;\r
+  }\r
+  rem = InitializedSize - _virtPos;\r
+  if (size > rem)\r
+    size = (UInt32)rem;\r
+\r
+  while (_curRem == 0)\r
+  {\r
+    UInt64 cacheTag = _virtPos >> _chunkSizeLog;\r
+    UInt32 cacheIndex = (UInt32)cacheTag & (kNumCacheChunks - 1);\r
+    if (_tags[cacheIndex] == cacheTag)\r
+    {\r
+      UInt32 chunkSize = (UInt32)1 << _chunkSizeLog;\r
+      UInt32 offset = (UInt32)_virtPos & (chunkSize - 1);\r
+      UInt32 cur = MyMin(chunkSize - offset, size);\r
+      memcpy(data, _outBuf + (cacheIndex << _chunkSizeLog) + offset, cur);\r
+      *processedSize = cur;\r
+      _virtPos += cur;\r
+      return S_OK;\r
+    }\r
+\r
+    PRF2(printf("\nVirtPos = %6d", _virtPos));\r
+    \r
+    UInt32 comprUnitSize = (UInt32)1 << CompressionUnit;\r
+    UInt64 virtBlock = _virtPos >> BlockSizeLog;\r
+    UInt64 virtBlock2 = virtBlock & ~((UInt64)comprUnitSize - 1);\r
+    \r
+    int left = 0, right = Extents.Size();\r
+    for (;;)\r
+    {\r
+      int mid = (left + right) / 2;\r
+      if (mid == left)\r
+        break;\r
+      if (virtBlock2 < Extents[mid].Virt)\r
+        right = mid;\r
+      else\r
+        left = mid;\r
+    }\r
+    \r
+    bool isCompressed = false;\r
+    UInt64 virtBlock2End = virtBlock2 + comprUnitSize;\r
+    if (CompressionUnit != 0)\r
+      for (int i = left; i < Extents.Size(); i++)\r
+      {\r
+        const CExtent &e = Extents[i];\r
+        if (e.Virt >= virtBlock2End)\r
+          break;\r
+        if (e.IsEmpty())\r
+        {\r
+          isCompressed = true;\r
+          break;\r
+        }\r
+      }\r
+\r
+    int i;\r
+    for (i = left; Extents[i + 1].Virt <= virtBlock; i++);\r
+    \r
+    _sparseMode = false;\r
+    if (!isCompressed)\r
+    {\r
+      const CExtent &e = Extents[i];\r
+      UInt64 newPos = (e.Phy << BlockSizeLog) + _virtPos - (e.Virt << BlockSizeLog);\r
+      if (newPos != _physPos)\r
+      {\r
+        _physPos = newPos;\r
+        RINOK(SeekToPhys());\r
+      }\r
+      UInt64 next = Extents[i + 1].Virt;\r
+      if (next > virtBlock2End)\r
+        next &= ~((UInt64)comprUnitSize - 1);\r
+      next <<= BlockSizeLog;\r
+      if (next > Size)\r
+        next = Size;\r
+      _curRem = next - _virtPos;\r
+      break;\r
+    }\r
+    bool thereArePhy = false;\r
+    for (int i2 = left; i2 < Extents.Size(); i2++)\r
+    {\r
+      const CExtent &e = Extents[i2];\r
+      if (e.Virt >= virtBlock2End)\r
+        break;\r
+      if (!e.IsEmpty())\r
+      {\r
+        thereArePhy = true;\r
+        break;\r
+      }\r
+    }\r
+    if (!thereArePhy)\r
+    {\r
+      _curRem = (Extents[i + 1].Virt << BlockSizeLog) - _virtPos;\r
+      _sparseMode = true;\r
+      break;\r
+    }\r
+    \r
+    size_t offs = 0;\r
+    UInt64 curVirt = virtBlock2;\r
+    for (i = left; i < Extents.Size(); i++)\r
+    {\r
+      const CExtent &e = Extents[i];\r
+      if (e.IsEmpty())\r
+        break;\r
+      if (e.Virt >= virtBlock2End)\r
+        return S_FALSE;\r
+      UInt64 newPos = (e.Phy + (curVirt - e.Virt)) << BlockSizeLog;\r
+      if (newPos != _physPos)\r
+      {\r
+        _physPos = newPos;\r
+        RINOK(SeekToPhys());\r
+      }\r
+      UInt64 numChunks = Extents[i + 1].Virt - curVirt;\r
+      if (curVirt + numChunks > virtBlock2End)\r
+        numChunks = virtBlock2End - curVirt;\r
+      size_t compressed = (size_t)numChunks << BlockSizeLog;\r
+      RINOK(ReadStream_FALSE(Stream, _inBuf + offs, compressed));\r
+      curVirt += numChunks;\r
+      _physPos += compressed;\r
+      offs += compressed;\r
+    }\r
+    size_t destLenMax = GetCuSize();\r
+    size_t destLen = destLenMax;\r
+    UInt64 rem = Size - (virtBlock2 << BlockSizeLog);\r
+    if (destLen > rem)\r
+      destLen = (size_t)rem;\r
+\r
+    Byte *dest = _outBuf + (cacheIndex << _chunkSizeLog);\r
+    size_t destSizeRes = Lznt1Dec(dest, destLenMax, destLen, _inBuf, offs);\r
+    _tags[cacheIndex] = cacheTag;\r
+\r
+    // some files in Vista have destSize > destLen\r
+    if (destSizeRes < destLen)\r
+    {\r
+      memset(dest, 0, destLenMax);\r
+      if (InUse)\r
+        return S_FALSE;\r
+    }\r
+  }\r
+  if (size > _curRem)\r
+    size = (UInt32)_curRem;\r
+  HRESULT res = S_OK;\r
+  if (_sparseMode)\r
+    memset(data, 0, size);\r
+  else\r
+  {\r
+    res = Stream->Read(data, size, &size);\r
+    _physPos += size;\r
+  }\r
+  if (processedSize != NULL)\r
+    *processedSize = size;\r
+  _virtPos += size;\r
+  _curRem -= size;\r
+  return res;\r
+}\r
\r
+STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)\r
+{\r
+  UInt64 newVirtPos = offset;\r
+  switch(seekOrigin)\r
+  {\r
+    case STREAM_SEEK_SET: break;\r
+    case STREAM_SEEK_CUR: newVirtPos += _virtPos; break;\r
+    case STREAM_SEEK_END: newVirtPos += Size; break;\r
+    default: return STG_E_INVALIDFUNCTION;\r
+  }\r
+  if (_virtPos != newVirtPos)\r
+    _curRem = 0;\r
+  _virtPos = newVirtPos;\r
+  if (newPosition)\r
+    *newPosition = newVirtPos;\r
+  return S_OK;\r
+}\r
+\r
+class CByteBufStream:\r
+  public IInStream,\r
+  public CMyUnknownImp\r
+{\r
+  UInt64 _virtPos;\r
+public:\r
+  CByteBuffer Buf;\r
+  void Init() { _virtPos = 0; }\r
\r
+  MY_UNKNOWN_IMP1(IInStream)\r
+\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);\r
+};\r
+\r
+STDMETHODIMP CByteBufStream::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize != NULL)\r
+    *processedSize = 0;\r
+  if (_virtPos >= Buf.GetCapacity())\r
+    return (_virtPos == Buf.GetCapacity()) ? S_OK: E_FAIL;\r
+  UInt64 rem = Buf.GetCapacity() - _virtPos;\r
+  if (rem < size)\r
+    size = (UInt32)rem;\r
+  memcpy(data, Buf + (size_t)_virtPos, size);\r
+  if (processedSize != NULL)\r
+    *processedSize = size;\r
+  _virtPos += size;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CByteBufStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)\r
+{\r
+  switch(seekOrigin)\r
+  {\r
+    case STREAM_SEEK_SET: _virtPos = offset; break;\r
+    case STREAM_SEEK_CUR: _virtPos += offset; break;\r
+    case STREAM_SEEK_END: _virtPos = Buf.GetCapacity() + offset; break;\r
+    default: return STG_E_INVALIDFUNCTION;\r
+  }\r
+  if (newPosition)\r
+    *newPosition = _virtPos;\r
+  return S_OK;\r
+}\r
+\r
+static HRESULT DataParseExtents(int clusterSizeLog, const CObjectVector<CAttr> &attrs,\r
+    int attrIndex, int attrIndexLim, UInt64 numPhysClusters, CRecordVector<CExtent> &Extents)\r
+{\r
+  CExtent e;\r
+  e.Virt = 0;\r
+  e.Phy = kEmptyExtent;\r
+  Extents.Add(e);\r
+  const CAttr &attr0 = attrs[attrIndex];\r
+\r
+  if (attr0.AllocatedSize < attr0.Size ||\r
+      (attrs[attrIndexLim - 1].HighVcn + 1) != (attr0.AllocatedSize >> clusterSizeLog) ||\r
+      (attr0.AllocatedSize & ((1 << clusterSizeLog) - 1)) != 0)\r
+    return S_FALSE;\r
+  \r
+  for (int i = attrIndex; i < attrIndexLim; i++)\r
+    if (!attrs[i].ParseExtents(Extents, numPhysClusters, attr0.CompressionUnit))\r
+      return S_FALSE;\r
+\r
+  UInt64 packSizeCalc = 0;\r
+  for (int k = 0; k < Extents.Size(); k++)\r
+  {\r
+    CExtent &e = Extents[k];\r
+    if (!e.IsEmpty())\r
+      packSizeCalc += (Extents[k + 1].Virt - e.Virt) << clusterSizeLog;\r
+    PRF2(printf("\nSize = %4I64X", Extents[k + 1].Virt - e.Virt));\r
+    PRF2(printf("  Pos = %4I64X", e.Phy));\r
+  }\r
+  \r
+  if (attr0.CompressionUnit != 0)\r
+  {\r
+    if (packSizeCalc != attr0.PackSize)\r
+      return S_FALSE;\r
+  }\r
+  else\r
+  {\r
+    if (packSizeCalc != attr0.AllocatedSize)\r
+      return S_FALSE;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+struct CDataRef\r
+{\r
+  int Start;\r
+  int Num;\r
+};\r
+\r
+static const UInt32 kMagic_FILE = 0x454c4946;\r
+static const UInt32 kMagic_BAAD = 0x44414142;\r
+\r
+struct CMftRec\r
+{\r
+  UInt32 Magic;\r
+  // UInt64 Lsn;\r
+  UInt16 SeqNumber;\r
+  UInt16 Flags;\r
+  // UInt16 LinkCount;\r
+  // UInt16 NextAttrInstance;\r
+  CMftRef BaseMftRef;\r
+  // UInt32 ThisRecNumber;\r
+  UInt32 MyNumNameLinks;\r
+\r
+  CObjectVector<CAttr> DataAttrs;\r
+  CObjectVector<CFileNameAttr> FileNames;\r
+  CRecordVector<CDataRef> DataRefs;\r
+\r
+  CSiAttr SiAttr;\r
+\r
+  void MoveAttrsFrom(CMftRec &src)\r
+  {\r
+    DataAttrs += src.DataAttrs;\r
+    FileNames += src.FileNames;\r
+    src.DataAttrs.ClearAndFree();\r
+    src.FileNames.ClearAndFree();\r
+  }\r
+\r
+  UInt64 GetPackSize() const\r
+  {\r
+    UInt64 res = 0;\r
+    for (int i = 0; i < DataRefs.Size(); i++)\r
+      res += DataAttrs[DataRefs[i].Start].GetPackSize();\r
+    return res;\r
+  }\r
+\r
+  bool Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNumber, CObjectVector<CAttr> *attrs);\r
+\r
+  bool IsEmpty() const { return (Magic <= 2); }\r
+  bool IsFILE() const { return (Magic == kMagic_FILE); }\r
+  bool IsBAAD() const { return (Magic == kMagic_BAAD); }\r
+\r
+  bool InUse() const { return (Flags & 1) != 0; }\r
+  bool IsDir() const { return (Flags & 2) != 0; }\r
+\r
+  void ParseDataNames();\r
+  HRESULT GetStream(IInStream *mainStream, int dataIndex,\r
+      int clusterSizeLog, UInt64 numPhysClusters, IInStream **stream) const;\r
+  int GetNumExtents(int dataIndex, int clusterSizeLog, UInt64 numPhysClusters) const;\r
+\r
+  UInt64 GetSize(int dataIndex) const { return DataAttrs[DataRefs[dataIndex].Start].GetSize(); }\r
+\r
+  CMftRec(): MyNumNameLinks(0) {}\r
+};\r
+\r
+void CMftRec::ParseDataNames()\r
+{\r
+  DataRefs.Clear();\r
+  DataAttrs.Sort(CompareAttr, 0);\r
+\r
+  for (int i = 0; i < DataAttrs.Size();)\r
+  {\r
+    CDataRef ref;\r
+    ref.Start = i;\r
+    for (i++; i < DataAttrs.Size(); i++)\r
+      if (DataAttrs[ref.Start].Name != DataAttrs[i].Name)\r
+        break;\r
+    ref.Num = i - ref.Start;\r
+    DataRefs.Add(ref);\r
+  }\r
+}\r
+\r
+HRESULT CMftRec::GetStream(IInStream *mainStream, int dataIndex,\r
+    int clusterSizeLog, UInt64 numPhysClusters, IInStream **destStream) const\r
+{\r
+  *destStream = 0;\r
+  CByteBufStream *streamSpec = new CByteBufStream;\r
+  CMyComPtr<IInStream> streamTemp = streamSpec;\r
+\r
+  if (dataIndex < 0)\r
+    return E_FAIL;\r
+\r
+  if (dataIndex < DataRefs.Size())\r
+  {\r
+    const CDataRef &ref = DataRefs[dataIndex];\r
+    int numNonResident = 0;\r
+    int i;\r
+    for (i = ref.Start; i < ref.Start + ref.Num; i++)\r
+      if (DataAttrs[i].NonResident)\r
+        numNonResident++;\r
+\r
+    const CAttr &attr0 = DataAttrs[ref.Start];\r
+      \r
+    if (numNonResident != 0 || ref.Num != 1)\r
+    {\r
+      if (numNonResident != ref.Num || !attr0.IsCompressionUnitSupported())\r
+        return S_FALSE;\r
+      CInStream *streamSpec = new CInStream;\r
+      CMyComPtr<IInStream> streamTemp = streamSpec;\r
+      RINOK(DataParseExtents(clusterSizeLog, DataAttrs, ref.Start, ref.Start + ref.Num, numPhysClusters, streamSpec->Extents));\r
+      streamSpec->Size = attr0.Size;\r
+      streamSpec->InitializedSize = attr0.InitializedSize;\r
+      streamSpec->Stream = mainStream;\r
+      streamSpec->BlockSizeLog = clusterSizeLog;\r
+      streamSpec->InUse = InUse();\r
+      RINOK(streamSpec->InitAndSeek(attr0.CompressionUnit));\r
+      *destStream = streamTemp.Detach();\r
+      return S_OK;\r
+    }\r
+    streamSpec->Buf = attr0.Data;\r
+  }\r
+  streamSpec->Init();\r
+  *destStream = streamTemp.Detach();\r
+  return S_OK;\r
+}\r
+\r
+int CMftRec::GetNumExtents(int dataIndex, int clusterSizeLog, UInt64 numPhysClusters) const\r
+{\r
+  if (dataIndex < 0)\r
+    return 0;\r
+  {\r
+    const CDataRef &ref = DataRefs[dataIndex];\r
+    int numNonResident = 0;\r
+    int i;\r
+    for (i = ref.Start; i < ref.Start + ref.Num; i++)\r
+      if (DataAttrs[i].NonResident)\r
+        numNonResident++;\r
+\r
+    const CAttr &attr0 = DataAttrs[ref.Start];\r
+      \r
+    if (numNonResident != 0 || ref.Num != 1)\r
+    {\r
+      if (numNonResident != ref.Num || !attr0.IsCompressionUnitSupported())\r
+        return 0; // error;\r
+      CRecordVector<CExtent> extents;\r
+      if (DataParseExtents(clusterSizeLog, DataAttrs, ref.Start, ref.Start + ref.Num, numPhysClusters, extents) != S_OK)\r
+        return 0; // error;\r
+      return extents.Size() - 1;\r
+    }\r
+    // if (attr0.Data.GetCapacity() != 0)\r
+    //   return 1;\r
+    return 0;\r
+  }\r
+}\r
+\r
+bool CMftRec::Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNumber,\r
+    CObjectVector<CAttr> *attrs)\r
+{\r
+  G32(p, Magic);\r
+  if (!IsFILE())\r
+    return IsEmpty() || IsBAAD();\r
+\r
+  UInt32 usaOffset;\r
+  UInt32 numUsaItems;\r
+  G16(p + 0x04, usaOffset);\r
+  G16(p + 0x06, numUsaItems);\r
+  \r
+  if ((usaOffset & 1) != 0 || usaOffset + numUsaItems * 2 > ((UInt32)1 << sectorSizeLog) - 2 ||\r
+      numUsaItems == 0 || numUsaItems - 1 != numSectors)\r
+    return false;\r
+\r
+  UInt16 usn = Get16(p + usaOffset);\r
+  // PRF(printf("\nusn = %d", usn));\r
+  for (UInt32 i = 1; i < numUsaItems; i++)\r
+  {\r
+    void *pp = p + (i << sectorSizeLog)  - 2;\r
+    if (Get16(pp) != usn)\r
+      return false;\r
+    SetUi16(pp, Get16(p + usaOffset + i * 2));\r
+  }\r
+\r
+  // G64(p + 0x08, Lsn);\r
+  G16(p + 0x10, SeqNumber);\r
+  // G16(p + 0x12, LinkCount);\r
+  // PRF(printf(" L=%d", LinkCount));\r
+  UInt32 attrOffs = Get16(p + 0x14);\r
+  G16(p + 0x16, Flags);\r
+  PRF(printf(" F=%4X", Flags));\r
+\r
+  UInt32 bytesInUse = Get32(p + 0x18);\r
+  UInt32 bytesAlloc = Get32(p + 0x1C);\r
+  G64(p + 0x20, BaseMftRef.Val);\r
+  if (BaseMftRef.Val != 0)\r
+  {\r
+    PRF(printf("  BaseRef=%d", (int)BaseMftRef.Val));\r
+    // return false; // Check it;\r
+  }\r
+  // G16(p + 0x28, NextAttrInstance);\r
+  if (usaOffset >= 0x30)\r
+    if (Get32(p + 0x2C) != recNumber) // NTFS 3.1+\r
+      return false;\r
+\r
+  UInt32 limit = numSectors << sectorSizeLog;\r
+  if (attrOffs >= limit || (attrOffs & 7) != 0 || bytesInUse > limit\r
+      || bytesAlloc != limit)\r
+    return false;\r
+\r
+\r
+  for (UInt32 t = attrOffs; t < limit;)\r
+  {\r
+    CAttr attr;\r
+    // PRF(printf("\n  %2d:", Attrs.Size()));\r
+    PRF(printf("\n"));\r
+    UInt32 length = attr.Parse(p + t, limit - t);\r
+    if (length == 0 || limit - t < length)\r
+      return false;\r
+    t += length;\r
+    if (attr.Type == 0xFFFFFFFF)\r
+      break;\r
+    switch(attr.Type)\r
+    {\r
+      case ATTR_TYPE_FILE_NAME:\r
+      {\r
+        CFileNameAttr fna;\r
+        if (!attr.ParseFileName(fna))\r
+          return false;\r
+        FileNames.Add(fna);\r
+        PRF(printf("  flags = %4x", (int)fna.NameType));\r
+        PRF(printf("\n  %S", fna.Name));\r
+        break;\r
+      }\r
+      case ATTR_TYPE_STANDARD_INFO:\r
+        if (!attr.ParseSi(SiAttr))\r
+          return false;\r
+        break;\r
+      case ATTR_TYPE_DATA:\r
+        DataAttrs.Add(attr);\r
+        break;\r
+      default:\r
+        if (attrs)\r
+          attrs->Add(attr);\r
+        break;\r
+    }\r
+  }\r
+\r
+  return true;\r
+}\r
+\r
+struct CItem\r
+{\r
+  int RecIndex;\r
+  int DataIndex;\r
+  CMftRef ParentRef;\r
+  UString Name;\r
+  UInt32 Attrib;\r
+\r
+  bool IsDir() const { return (DataIndex < 0); }\r
+};\r
+\r
+struct CDatabase\r
+{\r
+  CHeader Header;\r
+  CObjectVector<CItem> Items;\r
+  CObjectVector<CMftRec> Recs;\r
+  CMyComPtr<IInStream> InStream;\r
+  IArchiveOpenCallback *OpenCallback;\r
+\r
+  CByteBuffer ByteBuf;\r
+\r
+  CObjectVector<CAttr> VolAttrs;\r
+\r
+  ~CDatabase() { ClearAndClose(); }\r
+\r
+  void Clear();\r
+  void ClearAndClose();\r
+\r
+  UString GetItemPath(Int32 index) const;\r
+  HRESULT Open();\r
+  HRESULT ReadDir(Int32 parent, UInt32 cluster, int level);\r
+\r
+  HRESULT SeekToCluster(UInt64 cluster);\r
+\r
+  int FindMtfRec(const CMftRef &ref) const\r
+  {\r
+    UInt64 val = ref.GetIndex();\r
+    int left = 0, right = Items.Size();\r
+    while (left != right)\r
+    {\r
+      int mid = (left + right) / 2;\r
+      UInt64 midValue = Items[mid].RecIndex;\r
+      if (val == midValue)\r
+        return mid;\r
+      if (val < midValue)\r
+        right = mid;\r
+      else\r
+        left = mid + 1;\r
+    }\r
+    return -1;\r
+  }\r
+\r
+};\r
+\r
+HRESULT CDatabase::SeekToCluster(UInt64 cluster)\r
+{\r
+  return InStream->Seek(cluster << Header.ClusterSizeLog, STREAM_SEEK_SET, NULL);\r
+}\r
+\r
+void CDatabase::Clear()\r
+{\r
+  Items.Clear();\r
+  Recs.Clear();\r
+}\r
+\r
+void CDatabase::ClearAndClose()\r
+{\r
+  Clear();\r
+  InStream.Release();\r
+}\r
+\r
+#define MY_DIR_PREFIX(x) L"[" x L"]" WSTRING_PATH_SEPARATOR\r
+\r
+UString CDatabase::GetItemPath(Int32 index) const\r
+{\r
+  const CItem *item = &Items[index];\r
+  UString name = item->Name;\r
+  for (int j = 0; j < 256; j++)\r
+  {\r
+    CMftRef ref = item->ParentRef;\r
+    index = FindMtfRec(ref);\r
+    if (ref.GetIndex() == 5)\r
+      return name;\r
+    if (index < 0 || Recs[Items[index].RecIndex].SeqNumber != ref.GetNumber())\r
+      return MY_DIR_PREFIX(L"UNKNOWN") + name;\r
+    item = &Items[index];\r
+    name = item->Name + WCHAR_PATH_SEPARATOR + name;\r
+  }\r
+  return MY_DIR_PREFIX(L"BAD") + name;\r
+}\r
+\r
+HRESULT CDatabase::Open()\r
+{\r
+  Clear();\r
+  \r
+  static const UInt32 kHeaderSize = 512;\r
+  Byte buf[kHeaderSize];\r
+  RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize));\r
+  if (!Header.Parse(buf))\r
+    return S_FALSE;\r
+  UInt64 fileSize;\r
+  RINOK(InStream->Seek(0, STREAM_SEEK_END, &fileSize));\r
+  if (fileSize < Header.GetPhySize())\r
+    return S_FALSE;\r
+  \r
+  SeekToCluster(Header.MftCluster);\r
+\r
+  CMftRec mftRec;\r
+  UInt32 numSectorsInRec;\r
+  int recSizeLog;\r
+  CMyComPtr<IInStream> mftStream;\r
+  {\r
+    UInt32 blockSize = 1 << 12;\r
+    ByteBuf.SetCapacity(blockSize);\r
+    RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize));\r
+    \r
+    UInt32 allocSize = Get32(ByteBuf + 0x1C);\r
+    recSizeLog = GetLog(allocSize);\r
+    if (recSizeLog < Header.SectorSizeLog)\r
+      return false;\r
+    numSectorsInRec = 1 << (recSizeLog - Header.SectorSizeLog);\r
+    if (!mftRec.Parse(ByteBuf, Header.SectorSizeLog, numSectorsInRec, NULL, 0))\r
+      return S_FALSE;\r
+    if (!mftRec.IsFILE())\r
+      return S_FALSE;\r
+    mftRec.ParseDataNames();\r
+    if (mftRec.DataRefs.IsEmpty())\r
+      return S_FALSE;\r
+    RINOK(mftRec.GetStream(InStream, 0, Header.ClusterSizeLog, Header.NumClusters, &mftStream));\r
+    if (!mftStream)\r
+      return S_FALSE;\r
+  }\r
+\r
+  UInt64 mftSize = mftRec.DataAttrs[0].Size;\r
+  if ((mftSize >> 4) > Header.GetPhySize())\r
+    return S_FALSE;\r
+\r
+  UInt64 numFiles = mftSize >> recSizeLog;\r
+  if (numFiles > (1 << 30))\r
+    return S_FALSE;\r
+  if (OpenCallback)\r
+  {\r
+    RINOK(OpenCallback->SetTotal(&numFiles, &mftSize));\r
+  }\r
+  const UInt32 kBufSize = (1 << 15);\r
+  if (kBufSize < (1 << recSizeLog))\r
+    return S_FALSE;\r
+\r
+  ByteBuf.SetCapacity((size_t)kBufSize);\r
+  Recs.Reserve((int)numFiles);\r
+  for (UInt64 pos64 = 0;;)\r
+  {\r
+    if (OpenCallback)\r
+    {\r
+      UInt64 numFiles = Recs.Size();\r
+      if ((numFiles & 0x3FF) == 0)\r
+      {\r
+        RINOK(OpenCallback->SetCompleted(&numFiles, &pos64));\r
+      }\r
+    }\r
+    UInt32 readSize = kBufSize;\r
+    UInt64 rem = mftSize - pos64;\r
+    if (readSize > rem)\r
+      readSize = (UInt32)rem;\r
+    if (readSize < ((UInt32)1 << recSizeLog))\r
+      break;\r
+    RINOK(ReadStream_FALSE(mftStream, ByteBuf, (size_t)readSize));\r
+    pos64 += readSize;\r
+    for (int i = 0; ((UInt32)(i + 1) << recSizeLog) <= readSize; i++)\r
+    {\r
+      PRF(printf("\n---------------------"));\r
+      PRF(printf("\n%5d:", Recs.Size()));\r
+      Byte *p = ByteBuf + ((UInt32)i << recSizeLog);\r
+      CMftRec rec;\r
+      if (!rec.Parse(p, Header.SectorSizeLog, numSectorsInRec, (UInt32)Recs.Size(),\r
+          (Recs.Size() == kRecIndex_Volume) ? &VolAttrs: NULL))\r
+        return S_FALSE;\r
+      Recs.Add(rec);\r
+    }\r
+  }\r
+\r
+  int i;\r
+  for (i = 0; i < Recs.Size(); i++)\r
+  {\r
+    CMftRec &rec = Recs[i];\r
+    if (!rec.BaseMftRef.IsBaseItself())\r
+    {\r
+      UInt64 refIndex = rec.BaseMftRef.GetIndex();\r
+      if (refIndex > (UInt32)Recs.Size())\r
+        return S_FALSE;\r
+      CMftRec &refRec = Recs[(int)refIndex];\r
+      bool moveAttrs = (refRec.SeqNumber == rec.BaseMftRef.GetNumber() && refRec.BaseMftRef.IsBaseItself());\r
+      if (rec.InUse() && refRec.InUse())\r
+      {\r
+        if (!moveAttrs)\r
+          return S_FALSE;\r
+      }\r
+      else if (rec.InUse() || refRec.InUse())\r
+        moveAttrs = false;\r
+      if (moveAttrs)\r
+        refRec.MoveAttrsFrom(rec);\r
+    }\r
+  }\r
+\r
+  for (i = 0; i < Recs.Size(); i++)\r
+    Recs[i].ParseDataNames();\r
+  \r
+  for (i = 0; i < Recs.Size(); i++)\r
+  {\r
+    CMftRec &rec = Recs[i];\r
+    if (!rec.IsFILE() || !rec.BaseMftRef.IsBaseItself())\r
+      continue;\r
+    int numNames = 0;\r
+    // printf("\n%4d: ", i);\r
+    for (int t = 0; t < rec.FileNames.Size(); t++)\r
+    {\r
+      const CFileNameAttr &fna = rec.FileNames[t];\r
+      // printf("%4d %S  | ", (int)fna.NameType, fna.Name);\r
+      if (fna.IsDos())\r
+        continue;\r
+      int numDatas = rec.DataRefs.Size();\r
+\r
+      // For hard linked files we show substreams only for first Name.\r
+      if (numDatas > 1 && numNames > 0)\r
+        numDatas = 1;\r
+      numNames++;\r
+\r
+      if (rec.IsDir())\r
+      {\r
+        CItem item;\r
+        item.Name = fna.Name;\r
+        item.RecIndex = i;\r
+        item.DataIndex = -1;\r
+        item.ParentRef = fna.ParentDirRef;\r
+        item.Attrib = rec.SiAttr.Attrib | 0x10;\r
+        // item.Attrib = fna.Attrib;\r
+        Items.Add(item);\r
+      }\r
+      for (int di = 0; di < numDatas; di++)\r
+      {\r
+        CItem item;\r
+        item.Name = fna.Name;\r
+        item.Attrib = rec.SiAttr.Attrib;\r
+        const UString &subName = rec.DataAttrs[rec.DataRefs[di].Start].Name;\r
+        if (!subName.IsEmpty())\r
+        {\r
+          // $BadClus:$Bad is sparse file for all clusters. So we skip it.\r
+          if (i == kRecIndex_BadClus && subName == L"$Bad")\r
+            continue;\r
+          item.Name += L":";\r
+          item.Name += subName;\r
+          item.Attrib = fna.Attrib;\r
+        }\r
+        \r
+        PRF(printf("\n%3d", i));\r
+        PRF(printf("  attrib=%2x", rec.SiAttr.Attrib));\r
+        PRF(printf(" %S", item.Name));\r
+        \r
+        item.RecIndex = i;\r
+        item.DataIndex = di;\r
+        item.ParentRef = fna.ParentDirRef;\r
+\r
+        Items.Add(item);\r
+        rec.MyNumNameLinks++;\r
+      }\r
+    }\r
+    rec.FileNames.ClearAndFree();\r
+  }\r
+  \r
+  return S_OK;\r
+}\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IInArchiveGetStream,\r
+  public CMyUnknownImp,\r
+  CDatabase\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);\r
+};\r
+\r
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)\r
+{\r
+  COM_TRY_BEGIN\r
+  IInStream *stream2;\r
+  const CItem &item = Items[index];\r
+  const CMftRec &rec = Recs[item.RecIndex];\r
+  HRESULT res = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeLog, Header.NumClusters, &stream2);\r
+  *stream = (ISequentialInStream *)stream2;\r
+  return res;\r
+  COM_TRY_END\r
+}\r
+\r
+static const STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidIsDir, VT_BOOL},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidCTime, VT_FILETIME},\r
+  { NULL, kpidATime, VT_FILETIME},\r
+  { NULL, kpidAttrib, VT_UI4},\r
+  { NULL, kpidLinks, VT_UI4},\r
+  { NULL, kpidNumBlocks, VT_UI4}\r
+};\r
+\r
+static const STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidVolumeName, VT_BSTR},\r
+  { NULL, kpidFileSystem, VT_BSTR},\r
+  { NULL, kpidClusterSize, VT_UI4},\r
+  { NULL, kpidPhySize, VT_UI8},\r
+  { NULL, kpidHeadersSize, VT_UI8},\r
+  { NULL, kpidCTime, VT_FILETIME},\r
+\r
+  { NULL, kpidSectorSize, VT_UI4},\r
+  { NULL, kpidId, VT_UI8}\r
+  // { NULL, kpidSectorsPerTrack, VT_UI4},\r
+  // { NULL, kpidNumHeads, VT_UI4},\r
+  // { NULL, kpidHiddenSectors, VT_UI4}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+static void NtfsTimeToProp(UInt64 t, NWindows::NCOM::CPropVariant &prop)\r
+{\r
+  FILETIME ft;\r
+  ft.dwLowDateTime = (DWORD)t;\r
+  ft.dwHighDateTime = (DWORD)(t >> 32);\r
+  prop = ft;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+\r
+  const CMftRec *volRec = (Recs.Size() > kRecIndex_Volume ? &Recs[kRecIndex_Volume] : NULL);\r
+\r
+  switch(propID)\r
+  {\r
+    case kpidClusterSize: prop = Header.ClusterSize(); break;\r
+    case kpidPhySize: prop = Header.GetPhySize(); break;\r
+    /*\r
+    case kpidHeadersSize:\r
+    {\r
+      UInt64 val = 0;\r
+      for (int i = 0; i < kNumSysRecs; i++)\r
+      {\r
+        printf("\n%2d: %8I64d ", i, Recs[i].GetPackSize());\r
+        if (i == 8)\r
+          i = i\r
+        val += Recs[i].GetPackSize();\r
+      }\r
+      prop = val;\r
+      break;\r
+    }\r
+    */\r
+    case kpidCTime: if (volRec) NtfsTimeToProp(volRec->SiAttr.CTime, prop); break;break;\r
+    case kpidVolumeName:\r
+    {\r
+      for (int i = 0; i < VolAttrs.Size(); i++)\r
+      {\r
+        const CAttr &attr = VolAttrs[i];\r
+        if (attr.Type == ATTR_TYPE_VOLUME_NAME)\r
+        {\r
+          UString name;\r
+          GetString(attr.Data, (int)attr.Data.GetCapacity() / 2, name);\r
+          prop = name;\r
+          break;\r
+        }\r
+      }\r
+      break;\r
+    }\r
+    case kpidFileSystem:\r
+    {\r
+      AString s = "NTFS";\r
+      for (int i = 0; i < VolAttrs.Size(); i++)\r
+      {\r
+        const CAttr &attr = VolAttrs[i];\r
+        if (attr.Type == ATTR_TYPE_VOLUME_INFO)\r
+        {\r
+          CVolInfo vi;\r
+          if (attr.ParseVolInfo(vi))\r
+          {\r
+            s += ' ';\r
+            char temp[16];\r
+            ConvertUInt32ToString(vi.MajorVer, temp);\r
+            s += temp;\r
+            s += '.';\r
+            ConvertUInt32ToString(vi.MinorVer, temp);\r
+            s += temp;\r
+          }\r
+          break;\r
+        }\r
+      }\r
+      prop = s;\r
+      break;\r
+    }\r
+    case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break;\r
+    case kpidId: prop = Header.SerialNumber; break;\r
+    // case kpidMediaType: prop = Header.MediaType; break;\r
+    // case kpidSectorsPerTrack: prop = Header.SectorsPerTrack; break;\r
+    // case kpidNumHeads: prop = Header.NumHeads; break;\r
+    // case kpidHiddenSectors: prop = Header.NumHiddenSectors; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  const CItem &item = Items[index];\r
+  const CMftRec &rec = Recs[item.RecIndex];\r
+\r
+  const CAttr *data= NULL;\r
+  if (item.DataIndex >= 0)\r
+    data = &rec.DataAttrs[rec.DataRefs[item.DataIndex].Start];\r
+\r
+  switch(propID)\r
+  {\r
+    case kpidPath:\r
+    {\r
+      UString name = GetItemPath(index);\r
+      const wchar_t *prefix = NULL;\r
+      if (!rec.InUse())\r
+        prefix = MY_DIR_PREFIX(L"DELETED");\r
+      else if (item.RecIndex < kNumSysRecs)\r
+        prefix = MY_DIR_PREFIX(L"SYSTEM");\r
+      if (prefix)\r
+        name = prefix + name;\r
+      prop = name;\r
+      break;\r
+    }\r
+\r
+    case kpidIsDir: prop = item.IsDir(); break;\r
+    case kpidMTime: NtfsTimeToProp(rec.SiAttr.MTime, prop); break;\r
+      \r
+    case kpidCTime: NtfsTimeToProp(rec.SiAttr.CTime, prop); break;\r
+    case kpidATime: NtfsTimeToProp(rec.SiAttr.ATime, prop); break;\r
+    case kpidAttrib:\r
+      prop = item.Attrib;\r
+      break;\r
+    case kpidLinks: prop = rec.MyNumNameLinks; break;\r
+    case kpidSize: if (data) prop = data->GetSize(); break;\r
+    case kpidPackSize: if (data) prop = data->GetPackSize(); break;\r
+    case kpidNumBlocks: if (data) prop = (UInt32)rec.GetNumExtents(item.DataIndex, Header.ClusterSizeLog, Header.NumClusters); break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback)\r
+{\r
+  COM_TRY_BEGIN\r
+  {\r
+    OpenCallback = callback;\r
+    InStream = stream;\r
+    HRESULT res;\r
+    try\r
+    {\r
+      res = CDatabase::Open();\r
+      if (res == S_OK)\r
+        return S_OK;\r
+    }\r
+    catch(...)\r
+    {\r
+      Close();\r
+      throw;\r
+    }\r
+    Close();\r
+    return res;\r
+  }\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  ClearAndClose();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = Items.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt32 i;\r
+  UInt64 totalSize = 0;\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    const CItem &item = Items[allFilesMode ? i : indices[i]];\r
+    const CMftRec &rec = Recs[item.RecIndex];\r
+    if (!rec.IsDir())\r
+      totalSize += rec.GetSize(item.DataIndex);\r
+  }\r
+  RINOK(extractCallback->SetTotal(totalSize));\r
+\r
+  UInt64 totalPackSize;\r
+  totalSize = totalPackSize = 0;\r
+  \r
+  CByteBuffer buf;\r
+  UInt32 clusterSize = Header.ClusterSize();\r
+  buf.SetCapacity(clusterSize);\r
+\r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  CDummyOutStream *outStreamSpec = new CDummyOutStream;\r
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\r
+\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    lps->InSize = totalPackSize;\r
+    lps->OutSize = totalSize;\r
+    RINOK(lps->SetCur());\r
+    CMyComPtr<ISequentialOutStream> realOutStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    Int32 index = allFilesMode ? i : indices[i];\r
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+\r
+    const CItem &item = Items[index];\r
+    if (item.IsDir())\r
+    {\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+      continue;\r
+    }\r
+\r
+    if (!testMode && !realOutStream)\r
+      continue;\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+\r
+    outStreamSpec->SetStream(realOutStream);\r
+    realOutStream.Release();\r
+    outStreamSpec->Init();\r
+\r
+    const CMftRec &rec = Recs[item.RecIndex];\r
+    const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start];\r
+\r
+    int res = NExtract::NOperationResult::kDataError;\r
+    {\r
+      CMyComPtr<IInStream> inStream;\r
+      HRESULT hres = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeLog, Header.NumClusters, &inStream);\r
+      if (hres == S_FALSE)\r
+        res = NExtract::NOperationResult::kUnSupportedMethod;\r
+      else\r
+      {\r
+        RINOK(hres);\r
+        if (inStream)\r
+        {\r
+          HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress);\r
+          if (hres != S_OK &&  hres != S_FALSE)\r
+          {\r
+            RINOK(hres);\r
+          }\r
+          if (/* copyCoderSpec->TotalSize == item.GetSize() && */ hres == S_OK)\r
+            res = NExtract::NOperationResult::kOK;\r
+        }\r
+      }\r
+    }\r
+    totalPackSize += data.GetPackSize();\r
+    totalSize += data.GetSize();\r
+    outStreamSpec->ReleaseStream();\r
+    RINOK(extractCallback->SetOperationResult(res));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = Items.Size();\r
+  return S_OK;\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"NTFS", L"ntfs img", 0, 0xD9, { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 }, 9, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Fat)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp
new file mode 100755 (executable)
index 0000000..111eb08
--- /dev/null
@@ -0,0 +1,1752 @@
+// PeHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/DynamicBuffer.h"\r
+#include "Common/ComTry.h"\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/PropVariantUtils.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../Common/LimitedStreams.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamObjects.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/CopyCoder.h"\r
+\r
+#define Get16(p) GetUi16(p)\r
+#define Get32(p) GetUi32(p)\r
+#define Get64(p) GetUi64(p)\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace NPe {\r
+\r
+#define NUM_SCAN_SECTIONS_MAX (1 << 6)\r
+\r
+#define PE_SIG 0x00004550\r
+#define PE_OptHeader_Magic_32 0x10B\r
+#define PE_OptHeader_Magic_64 0x20B\r
+\r
+static AString GetDecString(UInt32 v)\r
+{\r
+  char sz[32];\r
+  ConvertUInt64ToString(v, sz);\r
+  return sz;\r
+}\r
+\r
+struct CVersion\r
+{\r
+  UInt16 Major;\r
+  UInt16 Minor;\r
+\r
+  void Parse(const Byte *buf);\r
+  AString GetString() const { return GetDecString(Major) + '.' + GetDecString(Minor); }\r
+};\r
+\r
+void CVersion::Parse(const Byte *p)\r
+{\r
+  Major = Get16(p);\r
+  Minor = Get16(p + 2);\r
+}\r
+\r
+static const UInt32 kHeaderSize =  4 + 20;\r
+\r
+struct CHeader\r
+{\r
+  UInt16 NumSections;\r
+  UInt32 Time;\r
+  UInt32 PointerToSymbolTable;\r
+  UInt32 NumSymbols;\r
+  UInt16 OptHeaderSize;\r
+  UInt16 Flags;\r
+  UInt16 Machine;\r
+\r
+  bool Parse(const Byte *buf);\r
+};\r
+\r
+bool CHeader::Parse(const Byte *p)\r
+{\r
+  if (Get32(p) != PE_SIG)\r
+    return false;\r
+  p += 4;\r
+  Machine = Get16(p + 0);\r
+  NumSections = Get16(p + 2);\r
+  Time = Get32(p + 4);\r
+  PointerToSymbolTable = Get32(p + 8);\r
+  NumSymbols = Get32(p + 12);\r
+  OptHeaderSize = Get16(p + 16);\r
+  Flags = Get16(p + 18);\r
+  return true;\r
+}\r
+\r
+struct CDirLink\r
+{\r
+  UInt32 Va;\r
+  UInt32 Size;\r
+  void Parse(const Byte *p);\r
+};\r
+\r
+void CDirLink::Parse(const Byte *p)\r
+{\r
+  Va = Get32(p);\r
+  Size = Get32(p + 4);\r
+}\r
+\r
+enum\r
+{\r
+  kDirLink_Certificate = 4,\r
+  kDirLink_Debug = 6\r
+};\r
+\r
+struct CDebugEntry\r
+{\r
+  UInt32 Flags;\r
+  UInt32 Time;\r
+  CVersion Ver;\r
+  UInt32 Type;\r
+  UInt32 Size;\r
+  UInt32 Va;\r
+  UInt32 Pa;\r
+  \r
+  void Parse(const Byte *p);\r
+};\r
+\r
+void CDebugEntry::Parse(const Byte *p)\r
+{\r
+  Flags = Get32(p);\r
+  Time = Get32(p + 4);\r
+  Ver.Parse(p + 8);\r
+  Type = Get32(p + 12);\r
+  Size = Get32(p + 16);\r
+  Va = Get32(p + 20);\r
+  Pa = Get32(p + 24);\r
+}\r
+\r
+static const UInt32 kNumDirItemsMax = 16;\r
+\r
+struct COptHeader\r
+{\r
+  UInt16 Magic;\r
+  Byte LinkerVerMajor;\r
+  Byte LinkerVerMinor;\r
+\r
+  UInt32 CodeSize;\r
+  UInt32 InitDataSize;\r
+  UInt32 UninitDataSize;\r
+  \r
+  // UInt32 AddressOfEntryPoint;\r
+  // UInt32 BaseOfCode;\r
+  // UInt32 BaseOfData32;\r
+  UInt64 ImageBase;\r
+\r
+  UInt32 SectAlign;\r
+  UInt32 FileAlign;\r
+\r
+  CVersion OsVer;\r
+  CVersion ImageVer;\r
+  CVersion SubsysVer;\r
+  \r
+  UInt32 ImageSize;\r
+  UInt32 HeadersSize;\r
+  UInt32 CheckSum;\r
+  UInt16 SubSystem;\r
+  UInt16 DllCharacts;\r
+\r
+  UInt64 StackReserve;\r
+  UInt64 StackCommit;\r
+  UInt64 HeapReserve;\r
+  UInt64 HeapCommit;\r
+\r
+  UInt32 NumDirItems;\r
+  CDirLink DirItems[kNumDirItemsMax];\r
+\r
+  bool Is64Bit() const { return Magic == PE_OptHeader_Magic_64; }\r
+  bool Parse(const Byte *p, UInt32 size);\r
+\r
+  int GetNumFileAlignBits() const\r
+  {\r
+    for (int i = 9; i <= 16; i++)\r
+      if (((UInt32)1 << i) == FileAlign)\r
+        return i;\r
+    return -1;\r
+  }\r
+};\r
+\r
+bool COptHeader::Parse(const Byte *p, UInt32 size)\r
+{\r
+  Magic = Get16(p);\r
+  switch (Magic)\r
+  {\r
+    case PE_OptHeader_Magic_32:\r
+    case PE_OptHeader_Magic_64:\r
+      break;\r
+    default:\r
+      return false;\r
+  }\r
+  LinkerVerMajor = p[2];\r
+  LinkerVerMinor = p[3];\r
+  \r
+  bool hdr64 = Is64Bit();\r
+  \r
+  CodeSize = Get32(p + 4);\r
+  InitDataSize = Get32(p + 8);\r
+  UninitDataSize = Get32(p + 12);\r
+\r
+  // AddressOfEntryPoint = Get32(p + 16);\r
+  // BaseOfCode = Get32(p + 20);\r
+  // BaseOfData32 = hdr64 ? 0: Get32(p + 24);\r
+  ImageBase = hdr64 ? GetUi64(p + 24) : Get32(p + 28);\r
+\r
+  SectAlign = Get32(p + 32);\r
+  FileAlign = Get32(p + 36);\r
+\r
+  OsVer.Parse(p + 40);\r
+  ImageVer.Parse(p + 44);\r
+  SubsysVer.Parse(p + 48);\r
+\r
+  // reserved = Get32(p + 52);\r
+\r
+  ImageSize = Get32(p + 56);\r
+  HeadersSize = Get32(p + 60);\r
+  CheckSum = Get32(p + 64);\r
+  SubSystem = Get16(p + 68);\r
+  DllCharacts = Get16(p + 70);\r
+\r
+  if (hdr64)\r
+  {\r
+    StackReserve = Get64(p + 72);\r
+    StackCommit = Get64(p + 80);\r
+    HeapReserve = Get64(p + 88);\r
+    HeapCommit = Get64(p + 96);\r
+  }\r
+  else\r
+  {\r
+    StackReserve = Get32(p + 72);\r
+    StackCommit = Get32(p + 76);\r
+    HeapReserve = Get32(p + 80);\r
+    HeapCommit = Get32(p + 84);\r
+  }\r
+  UInt32 pos = (hdr64 ? 108 : 92);\r
+  NumDirItems = Get32(p + pos);\r
+  pos += 4;\r
+  if (pos + 8 * NumDirItems != size)\r
+    return false;\r
+  for (UInt32 i = 0; i < NumDirItems && i < kNumDirItemsMax; i++)\r
+    DirItems[i].Parse(p + pos + i * 8);\r
+  return true;\r
+}\r
+\r
+static const UInt32 kSectionSize = 40;\r
+\r
+struct CSection\r
+{\r
+  AString Name;\r
+\r
+  UInt32 VSize;\r
+  UInt32 Va;\r
+  UInt32 PSize;\r
+  UInt32 Pa;\r
+  UInt32 Flags;\r
+  UInt32 Time;\r
+  // UInt16 NumRelocs;\r
+  bool IsDebug;\r
+  bool IsRealSect;\r
+  bool IsAdditionalSection;\r
+\r
+  CSection(): IsRealSect(false), IsDebug(false), IsAdditionalSection(false) {}\r
+  UInt64 GetPackSize() const { return PSize; }\r
+\r
+  void UpdateTotalSize(UInt32 &totalSize)\r
+  {\r
+    UInt32 t = Pa + PSize;\r
+    if (t > totalSize)\r
+      totalSize = t;\r
+  }\r
+  void Parse(const Byte *p);\r
+};\r
+\r
+static bool operator <(const CSection &a1, const CSection &a2) { return (a1.Pa < a2.Pa) || ((a1.Pa == a2.Pa) && (a1.PSize < a2.PSize)) ; }\r
+static bool operator ==(const CSection &a1, const CSection &a2) { return (a1.Pa == a2.Pa) && (a1.PSize == a2.PSize); }\r
+\r
+static AString GetName(const Byte *name)\r
+{\r
+  const int kNameSize = 8;\r
+  AString res;\r
+  char *p = res.GetBuffer(kNameSize);\r
+  memcpy(p, name, kNameSize);\r
+  p[kNameSize] = 0;\r
+  res.ReleaseBuffer();\r
+  return res;\r
+}\r
+\r
+void CSection::Parse(const Byte *p)\r
+{\r
+  Name = GetName(p);\r
+  VSize = Get32(p + 8);\r
+  Va = Get32(p + 12);\r
+  PSize = Get32(p + 16);\r
+  Pa = Get32(p + 20);\r
+  // NumRelocs = Get16(p + 32);\r
+  Flags = Get32(p + 36);\r
+}\r
+\r
+static const CUInt32PCharPair g_HeaderCharacts[] =\r
+{\r
+  {  1, "Executable" },\r
+  { 13, "DLL" },\r
+  {  8, "32-bit" },\r
+  {  5, "LargeAddress" },\r
+  {  0, "NoRelocs" },\r
+  {  2, "NoLineNums" },\r
+  {  3, "NoLocalSyms" },\r
+  {  4, "AggressiveWsTrim" },\r
+  {  9, "NoDebugInfo" },\r
+  { 10, "RemovableRun" },\r
+  { 11, "NetRun" },\r
+  { 12, "System" },\r
+  { 14, "UniCPU" },\r
+  {  7, "Little-Endian" },\r
+  { 15, "Big-Endian" }\r
+};\r
+\r
+static const CUInt32PCharPair g_DllCharacts[] =\r
+{\r
+  {  6, "Relocated" },\r
+  {  7, "Integrity" },\r
+  {  8, "NX-Compatible" },\r
+  {  9, "NoIsolation" },\r
+  { 10, "NoSEH" },\r
+  { 11, "NoBind" },\r
+  { 13, "WDM" },\r
+  { 15, "TerminalServerAware" }\r
+};\r
+\r
+static const CUInt32PCharPair g_SectFlags[] =\r
+{\r
+  {  3, "NoPad" },\r
+  {  5, "Code" },\r
+  {  6, "InitializedData" },\r
+  {  7, "UninitializedData" },\r
+  {  9, "Comments" },\r
+  { 11, "Remove" },\r
+  { 12, "COMDAT" },\r
+  { 15, "GP" },\r
+  { 24, "ExtendedRelocations" },\r
+  { 25, "Discardable" },\r
+  { 26, "NotCached" },\r
+  { 27, "NotPaged" },\r
+  { 28, "Shared" },\r
+  { 29, "Execute" },\r
+  { 30, "Read" },\r
+  { 31, "Write" }\r
+};\r
+\r
+static const CUInt32PCharPair g_MachinePairs[] =\r
+{\r
+  { 0x014C, "x86" },\r
+  { 0x0162, "MIPS-R3000" },\r
+  { 0x0166, "MIPS-R4000" },\r
+  { 0x0168, "MIPS-R10000" },\r
+  { 0x0169, "MIPS-V2" },\r
+  { 0x0184, "Alpha" },\r
+  { 0x01A2, "SH3" },\r
+  { 0x01A3, "SH3-DSP" },\r
+  { 0x01A4, "SH3E" },\r
+  { 0x01A6, "SH4" },\r
+  { 0x01A8, "SH5" },\r
+  { 0x01C0, "ARM" },\r
+  { 0x01C2, "ARM-Thumb" },\r
+  { 0x01F0, "PPC" },\r
+  { 0x01F1, "PPC-FP" },\r
+  { 0x0200, "IA-64" },\r
+  { 0x0284, "Alpha-64" },\r
+  { 0x0200, "IA-64" },\r
+  { 0x0366, "MIPSFPU" },\r
+  { 0x8664, "x64" },\r
+  { 0x0EBC, "EFI" }\r
+};\r
+\r
+static const CUInt32PCharPair g_SubSystems[] =\r
+{\r
+  { 0, "Unknown" },\r
+  { 1, "Native" },\r
+  { 2, "Windows GUI" },\r
+  { 3, "Windows CUI" },\r
+  { 7, "Posix" },\r
+  { 9, "Windows CE" },\r
+  { 10, "EFI" },\r
+  { 11, "EFI Boot" },\r
+  { 12, "EFI Runtime" },\r
+  { 13, "EFI ROM" },\r
+  { 14, "XBOX" }\r
+};\r
+\r
+static const wchar_t *g_ResTypes[] =\r
+{\r
+  NULL,\r
+  L"CURSOR",\r
+  L"BITMAP",\r
+  L"ICON",\r
+  L"MENU",\r
+  L"DIALOG",\r
+  L"STRING",\r
+  L"FONTDIR",\r
+  L"FONT",\r
+  L"ACCELERATOR",\r
+  L"RCDATA",\r
+  L"MESSAGETABLE",\r
+  L"GROUP_CURSOR",\r
+  NULL,\r
+  L"GROUP_ICON",\r
+  NULL,\r
+  L"VERSION",\r
+  L"DLGINCLUDE",\r
+  NULL,\r
+  L"PLUGPLAY",\r
+  L"VXD",\r
+  L"ANICURSOR",\r
+  L"ANIICON",\r
+  L"HTML",\r
+  L"MANIFEST"\r
+};\r
+\r
+const UInt32 kFlag = (UInt32)1 << 31;\r
+const UInt32 kMask = ~kFlag;\r
+\r
+struct CTableItem\r
+{\r
+  UInt32 Offset;\r
+  UInt32 ID;\r
+};\r
+\r
+\r
+const UInt32 kBmpHeaderSize = 14;\r
+const UInt32 kIconHeaderSize = 22;\r
+\r
+struct CResItem\r
+{\r
+  UInt32 Type;\r
+  UInt32 ID;\r
+  UInt32 Lang;\r
+\r
+  UInt32 Size;\r
+  UInt32 Offset;\r
+\r
+  UInt32 HeaderSize;\r
+  Byte Header[kIconHeaderSize]; // it must be enough for max size header.\r
+  bool Enabled;\r
+\r
+  bool IsNameEqual(const CResItem &item) const { return Lang == item.Lang; }\r
+  UInt32 GetSize() const { return Size + HeaderSize; }\r
+  bool IsBmp() const { return Type == 2; }\r
+  bool IsIcon() const { return Type == 3; }\r
+  bool IsString() const { return Type == 6; }\r
+  bool IsRcData() const { return Type == 10; }\r
+  bool IsRcDataOrUnknown() const { return IsRcData() || Type > 64; }\r
+};\r
+\r
+struct CStringItem\r
+{\r
+  UInt32 Lang;\r
+  UInt32 Size;\r
+  CByteDynamicBuffer Buf;\r
+\r
+  void AddChar(Byte c);\r
+  void AddWChar(UInt16 c);\r
+};\r
+\r
+void CStringItem::AddChar(Byte c)\r
+{\r
+  Buf.EnsureCapacity(Size + 2);\r
+  Buf[Size++] = c;\r
+  Buf[Size++] = 0;\r
+}\r
+\r
+void CStringItem::AddWChar(UInt16 c)\r
+{\r
+  if (c == '\n')\r
+  {\r
+    AddChar('\\');\r
+    c = 'n';\r
+  }\r
+  Buf.EnsureCapacity(Size + 2);\r
+  SetUi16(Buf + Size, c);\r
+  Size += 2;\r
+}\r
+\r
+struct CMixItem\r
+{\r
+  int SectionIndex;\r
+  int ResourceIndex;\r
+  int StringIndex;\r
+\r
+  bool IsSectionItem() const { return ResourceIndex < 0 && StringIndex < 0; };\r
+};\r
+\r
+struct CUsedBitmap\r
+{\r
+  CByteBuffer Buf;\r
+public:\r
+  void Alloc(size_t size)\r
+  {\r
+    size = (size + 7) / 8;\r
+    Buf.SetCapacity(size);\r
+    memset(Buf, 0, size);\r
+  }\r
+  void Free()\r
+  {\r
+    Buf.SetCapacity(0);\r
+  }\r
+  bool SetRange(size_t from, int size)\r
+  {\r
+    for (int i = 0; i < size; i++)\r
+    {\r
+      size_t pos = (from + i) >> 3;\r
+      Byte mask = (Byte)(1 << ((from + i) & 7));\r
+      Byte b = Buf[pos];\r
+      if ((b & mask) != 0)\r
+        return false;\r
+      Buf[pos] = b | mask;\r
+    }\r
+    return true;\r
+  }\r
+};\r
\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IInArchiveGetStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<IInStream> _stream;\r
+  CObjectVector<CSection> _sections;\r
+  UInt32 _peOffset;\r
+  CHeader _header;\r
+  COptHeader _optHeader;\r
+  UInt32 _totalSize;\r
+  UInt32 _totalSizeLimited;\r
+  Int32 _mainSubfile;\r
+\r
+  CRecordVector<CResItem> _items;\r
+  CObjectVector<CStringItem> _strings;\r
+\r
+  CByteBuffer _buf;\r
+  bool _oneLang;\r
+  UString _resourceFileName;\r
+  CUsedBitmap _usedRes;\r
+  bool _parseResources;\r
+\r
+  CRecordVector<CMixItem> _mixItems;\r
+\r
+  HRESULT LoadDebugSections(IInStream *stream, bool &thereIsSection);\r
+  HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);\r
+  bool Parse(const Byte *buf, UInt32 size);\r
+\r
+  void AddResNameToString(UString &s, UInt32 id) const;\r
+  UString GetLangPrefix(UInt32 lang);\r
+  HRESULT ReadString(UInt32 offset, UString &dest) const;\r
+  HRESULT ReadTable(UInt32 offset, CRecordVector<CTableItem> &items);\r
+  bool ParseStringRes(UInt32 id, UInt32 lang, const Byte *src, UInt32 size);\r
+  HRESULT OpenResources(int sectIndex, IInStream *stream, IArchiveOpenCallback *callback);\r
+  void CloseResources();\r
+\r
+\r
+  bool CheckItem(const CSection &sect, const CResItem &item, size_t offset) const\r
+  {\r
+    return item.Offset >= sect.Va && offset <= _buf.GetCapacity() && _buf.GetCapacity() - offset >= item.Size;\r
+  }\r
+\r
+public:\r
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);\r
+};\r
+\r
+bool CHandler::Parse(const Byte *buf, UInt32 size)\r
+{\r
+  UInt32 i;\r
+  if (size < 512)\r
+    return false;\r
+  _peOffset = Get32(buf + 0x3C);\r
+  if (_peOffset >= 0x1000 || _peOffset + 512 > size || (_peOffset & 7) != 0)\r
+    return false;\r
+\r
+  UInt32 pos = _peOffset;\r
+  if (!_header.Parse(buf + pos))\r
+    return false;\r
+  if (_header.OptHeaderSize > 512 || _header.NumSections > NUM_SCAN_SECTIONS_MAX)\r
+    return false;\r
+  pos += kHeaderSize;\r
+\r
+  if (!_optHeader.Parse(buf + pos, _header.OptHeaderSize))\r
+    return false;\r
+\r
+  pos += _header.OptHeaderSize;\r
+  _totalSize = pos;\r
+\r
+  for (i = 0; i < _header.NumSections; i++, pos += kSectionSize)\r
+  {\r
+    CSection sect;\r
+    if (pos + kSectionSize > size)\r
+      return false;\r
+    sect.Parse(buf + pos);\r
+    sect.IsRealSect = true;\r
+    sect.UpdateTotalSize(_totalSize);\r
+    _sections.Add(sect);\r
+  }\r
+\r
+  return true;\r
+}\r
+\r
+enum\r
+{\r
+  kpidSectAlign = kpidUserDefined,\r
+  kpidFileAlign,\r
+  kpidLinkerVer,\r
+  kpidOsVer,\r
+  kpidImageVer,\r
+  kpidSubsysVer,\r
+  kpidCodeSize,\r
+  kpidImageSize,\r
+  kpidInitDataSize,\r
+  kpidUnInitDataSize,\r
+  kpidHeadersSizeUnInitDataSize,\r
+  kpidSubSystem,\r
+  kpidDllCharacts,\r
+  kpidStackReserve,\r
+  kpidStackCommit,\r
+  kpidHeapReserve,\r
+  kpidHeapCommit,\r
+  kpidImageBase\r
+  // kpidAddressOfEntryPoint,\r
+  // kpidBaseOfCode,\r
+  // kpidBaseOfData32,\r
+};\r
+\r
+STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidCpu, VT_BSTR},\r
+  { NULL, kpidBit64, VT_BOOL},\r
+  { NULL, kpidCharacts, VT_BSTR},\r
+  { NULL, kpidCTime, VT_FILETIME},\r
+  { NULL, kpidPhySize, VT_UI4},\r
+  { NULL, kpidHeadersSize, VT_UI4},\r
+  { NULL, kpidChecksum, VT_UI4},\r
+  { L"Image Size", kpidImageSize, VT_UI4},\r
+  { L"Section Alignment", kpidSectAlign, VT_UI4},\r
+  { L"File Alignment", kpidFileAlign, VT_UI4},\r
+  { L"Code Size", kpidCodeSize, VT_UI4},\r
+  { L"Initialized Data Size", kpidInitDataSize, VT_UI4},\r
+  { L"Uninitialized Data Size", kpidUnInitDataSize, VT_UI4},\r
+  { L"Linker Version", kpidLinkerVer, VT_BSTR},\r
+  { L"OS Version", kpidOsVer, VT_BSTR},\r
+  { L"Image Version", kpidImageVer, VT_BSTR},\r
+  { L"Subsystem Version", kpidSubsysVer, VT_BSTR},\r
+  { L"Subsystem", kpidSubSystem, VT_BSTR},\r
+  { L"DLL Characteristics", kpidDllCharacts, VT_BSTR},\r
+  { L"Stack Reserve", kpidStackReserve, VT_UI8},\r
+  { L"Stack Commit", kpidStackCommit, VT_UI8},\r
+  { L"Heap Reserve", kpidHeapReserve, VT_UI8},\r
+  { L"Heap Commit", kpidHeapCommit, VT_UI8},\r
+  { L"Image Base", kpidImageBase, VT_UI8}\r
+  // { L"Address Of Entry Point", kpidAddressOfEntryPoint, VT_UI8},\r
+  // { L"Base Of Code", kpidBaseOfCode, VT_UI8},\r
+  // { L"Base Of Data", kpidBaseOfData32, VT_UI8},\r
+};\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidCharacts, VT_BSTR},\r
+  { NULL, kpidOffset, VT_UI8},\r
+  { NULL, kpidVa, VT_UI8}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps_WITH_NAME\r
+\r
+static void VerToProp(const CVersion &v, NCOM::CPropVariant &prop)\r
+{\r
+  StringToProp(v.GetString(), prop);\r
+}\r
+\r
+void TimeToProp(UInt32 unixTime, NCOM::CPropVariant &prop)\r
+{\r
+  if (unixTime != 0)\r
+  {\r
+    FILETIME ft;\r
+    NTime::UnixTimeToFileTime(unixTime, ft);\r
+    prop = ft;\r
+  }\r
+}\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidSectAlign: prop = _optHeader.SectAlign; break;\r
+    case kpidFileAlign: prop = _optHeader.FileAlign; break;\r
+    case kpidLinkerVer:\r
+    {\r
+      CVersion v = { _optHeader.LinkerVerMajor, _optHeader.LinkerVerMinor };\r
+      VerToProp(v, prop);\r
+      break;\r
+    }\r
+  \r
+    case kpidOsVer: VerToProp(_optHeader.OsVer, prop); break;\r
+    case kpidImageVer: VerToProp(_optHeader.ImageVer, prop); break;\r
+    case kpidSubsysVer: VerToProp(_optHeader.SubsysVer, prop); break;\r
+    case kpidCodeSize: prop = _optHeader.CodeSize; break;\r
+    case kpidInitDataSize: prop = _optHeader.InitDataSize; break;\r
+    case kpidUnInitDataSize: prop = _optHeader.UninitDataSize; break;\r
+    case kpidImageSize: prop = _optHeader.ImageSize; break;\r
+    case kpidPhySize: prop = _totalSize; break;\r
+    case kpidHeadersSize: prop = _optHeader.HeadersSize; break;\r
+    case kpidChecksum: prop = _optHeader.CheckSum; break;\r
+      \r
+    case kpidCpu: PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop); break;\r
+    case kpidBit64: if (_optHeader.Is64Bit()) prop = true; break;\r
+    case kpidSubSystem: PAIR_TO_PROP(g_SubSystems, _optHeader.SubSystem, prop); break;\r
+\r
+    case kpidMTime:\r
+    case kpidCTime: TimeToProp(_header.Time, prop); break;\r
+    case kpidCharacts: FLAGS_TO_PROP(g_HeaderCharacts, _header.Flags, prop); break;\r
+    case kpidDllCharacts: FLAGS_TO_PROP(g_DllCharacts, _optHeader.DllCharacts, prop); break;\r
+    case kpidStackReserve: prop = _optHeader.StackReserve; break;\r
+    case kpidStackCommit: prop = _optHeader.StackCommit; break;\r
+    case kpidHeapReserve: prop = _optHeader.HeapReserve; break;\r
+    case kpidHeapCommit: prop = _optHeader.HeapCommit; break;\r
+\r
+    case kpidImageBase: prop = _optHeader.ImageBase; break;\r
+    // case kpidAddressOfEntryPoint: prop = _optHeader.AddressOfEntryPoint; break;\r
+    // case kpidBaseOfCode: prop = _optHeader.BaseOfCode; break;\r
+    // case kpidBaseOfData32: if (!_optHeader.Is64Bit()) prop = _optHeader.BaseOfData32; break;\r
+\r
+    case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+void CHandler::AddResNameToString(UString &s, UInt32 id) const\r
+{\r
+  if ((id & kFlag) != 0)\r
+  {\r
+    UString name;\r
+    if (ReadString(id & kMask, name) == S_OK)\r
+    {\r
+      if (name.IsEmpty())\r
+        s += L"[]";\r
+      else\r
+      {\r
+        if (name.Length() > 1 && name[0] == '"' && name.Back() == '"')\r
+          name = name.Mid(1, name.Length() - 2);\r
+        s += name;\r
+      }\r
+      return;\r
+    }\r
+  }\r
+  wchar_t sz[32];\r
+  ConvertUInt32ToString(id, sz);\r
+  s += sz;\r
+}\r
+\r
+UString CHandler::GetLangPrefix(UInt32 lang)\r
+{\r
+  UString s = _resourceFileName;\r
+  s += WCHAR_PATH_SEPARATOR;\r
+  if (!_oneLang)\r
+  {\r
+    AddResNameToString(s, lang);\r
+    s += WCHAR_PATH_SEPARATOR;\r
+  }\r
+  return s;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NCOM::CPropVariant prop;\r
+  const CMixItem &mixItem = _mixItems[index];\r
+  if (mixItem.StringIndex >= 0)\r
+  {\r
+    const CStringItem &item = _strings[mixItem.StringIndex];\r
+    switch(propID)\r
+    {\r
+      case kpidPath: prop = GetLangPrefix(item.Lang) + L"string.txt"; break;\r
+      case kpidSize:\r
+      case kpidPackSize:\r
+        prop = (UInt64)item.Size; break;\r
+    }\r
+  }\r
+  else if (mixItem.ResourceIndex < 0)\r
+  {\r
+    const CSection &item = _sections[mixItem.SectionIndex];\r
+    switch(propID)\r
+    {\r
+      case kpidPath: StringToProp(item.Name, prop); break;\r
+      case kpidSize: prop = (UInt64)item.VSize; break;\r
+      case kpidPackSize: prop = (UInt64)item.GetPackSize(); break;\r
+      case kpidOffset: prop = item.Pa; break;\r
+      case kpidVa: if (item.IsRealSect) prop = item.Va; break;\r
+      case kpidMTime:\r
+      case kpidCTime:\r
+        TimeToProp(item.IsDebug ? item.Time : _header.Time, prop); break;\r
+      case kpidCharacts: if (item.IsRealSect) FLAGS_TO_PROP(g_SectFlags, item.Flags, prop); break;\r
+    }\r
+  }\r
+  else\r
+  {\r
+    const CResItem &item = _items[mixItem.ResourceIndex];\r
+    switch(propID)\r
+    {\r
+      case kpidPath:\r
+      {\r
+        UString s = GetLangPrefix(item.Lang);\r
+        {\r
+          const wchar_t *p = NULL;\r
+          if (item.Type < sizeof(g_ResTypes) / sizeof(g_ResTypes[0]))\r
+            p = g_ResTypes[item.Type];\r
+          if (p != 0)\r
+            s += p;\r
+          else\r
+            AddResNameToString(s, item.Type);\r
+        }\r
+        s += WCHAR_PATH_SEPARATOR;\r
+        AddResNameToString(s, item.ID);\r
+        if (item.HeaderSize != 0)\r
+        {\r
+          if (item.IsBmp())\r
+            s += L".bmp";\r
+          else if (item.IsIcon())\r
+            s += L".ico";\r
+        }\r
+        prop = s;\r
+        break;\r
+      }\r
+      case kpidSize: prop = (UInt64)item.GetSize(); break;\r
+      case kpidPackSize: prop = (UInt64)item.Size; break;\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection)\r
+{\r
+  thereIsSection = false;\r
+  const CDirLink &debugLink = _optHeader.DirItems[kDirLink_Debug];\r
+  if (debugLink.Size == 0)\r
+    return S_OK;\r
+  const unsigned kEntrySize = 28;\r
+  UInt32 numItems = debugLink.Size / kEntrySize;\r
+  if (numItems * kEntrySize != debugLink.Size || numItems > 16)\r
+    return S_FALSE;\r
+  \r
+  UInt64 pa = 0;\r
+  int i;\r
+  for (i = 0; i < _sections.Size(); i++)\r
+  {\r
+    const CSection &sect = _sections[i];\r
+    if (sect.Va < debugLink.Va && debugLink.Va + debugLink.Size <= sect.Va + sect.PSize)\r
+    {\r
+      pa = sect.Pa + (debugLink.Va - sect.Va);\r
+      break;\r
+    }\r
+  }\r
+  if (i == _sections.Size())\r
+  {\r
+    return S_OK;\r
+    // Exe for ARM requires S_OK\r
+    // return S_FALSE;\r
+  }\r
+  \r
+  CByteBuffer buffer;\r
+  buffer.SetCapacity(debugLink.Size);\r
+  Byte *buf = buffer;\r
+  \r
+  RINOK(stream->Seek(pa, STREAM_SEEK_SET, NULL));\r
+  RINOK(ReadStream_FALSE(stream, buf, debugLink.Size));\r
+\r
+  for (i = 0; i < (int)numItems; i++)\r
+  {\r
+    CDebugEntry de;\r
+    de.Parse(buf);\r
+\r
+    if (de.Size == 0)\r
+      continue;\r
+    \r
+    CSection sect;\r
+    sect.Name = ".debug" + GetDecString(i);\r
+    \r
+    sect.IsDebug = true;\r
+    sect.Time = de.Time;\r
+    sect.Va = de.Va;\r
+    sect.Pa = de.Pa;\r
+    sect.PSize = sect.VSize = de.Size;\r
+    UInt32 totalSize = sect.Pa + sect.PSize;\r
+    if (totalSize > _totalSize)\r
+    {\r
+      _totalSize = totalSize;\r
+      _sections.Add(sect);\r
+      thereIsSection = true;\r
+    }\r
+    buf += kEntrySize;\r
+  }\r
+\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CHandler::ReadString(UInt32 offset, UString &dest) const\r
+{\r
+  if ((offset & 1) != 0 || offset >= _buf.GetCapacity())\r
+    return S_FALSE;\r
+  size_t rem = _buf.GetCapacity() - offset;\r
+  if (rem < 2)\r
+    return S_FALSE;\r
+  unsigned length = Get16(_buf + offset);\r
+  if ((rem - 2) / 2 < length)\r
+    return S_FALSE;\r
+  dest.Empty();\r
+  offset += 2;\r
+  for (unsigned i = 0; i < length; i++)\r
+    dest += (wchar_t)Get16(_buf + offset + i * 2);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CHandler::ReadTable(UInt32 offset, CRecordVector<CTableItem> &items)\r
+{\r
+  if ((offset & 3) != 0 || offset >= _buf.GetCapacity())\r
+    return S_FALSE;\r
+  size_t rem = _buf.GetCapacity() - offset;\r
+  if (rem < 16)\r
+    return S_FALSE;\r
+  items.Clear();\r
+  unsigned numNameItems = Get16(_buf + offset + 12);\r
+  unsigned numIdItems = Get16(_buf + offset + 14);\r
+  unsigned numItems = numNameItems + numIdItems;\r
+  if ((rem - 16) / 8 < numItems)\r
+    return S_FALSE;\r
+  if (!_usedRes.SetRange(offset, 16 + numItems * 8))\r
+    return S_FALSE;\r
+  offset += 16;\r
+  _oneLang = true;\r
+  unsigned i;\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    CTableItem item;\r
+    const Byte *buf = _buf + offset;\r
+    offset += 8;\r
+    item.ID = Get32(buf + 0);\r
+    if (((item.ID & kFlag) != 0) != (i < numNameItems))\r
+      return S_FALSE;\r
+    item.Offset = Get32(buf + 4);\r
+    items.Add(item);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+static const UInt32 kFileSizeMax = (UInt32)1 << 30;\r
+static const int kNumResItemsMax = (UInt32)1 << 23;\r
+static const int kNumStringLangsMax = 128;\r
+\r
+// BITMAPINFOHEADER\r
+struct CBitmapInfoHeader\r
+{\r
+  // UInt32 HeaderSize;\r
+  UInt32 XSize;\r
+  Int32 YSize;\r
+  UInt16 Planes;\r
+  UInt16 BitCount;\r
+  UInt32 Compression;\r
+  UInt32 SizeImage;\r
+\r
+  bool Parse(const Byte *p, size_t size);\r
+};\r
+\r
+static const UInt32 kBitmapInfoHeader_Size = 0x28;\r
+\r
+bool CBitmapInfoHeader::Parse(const Byte *p, size_t size)\r
+{\r
+  if (size < kBitmapInfoHeader_Size || Get32(p) != kBitmapInfoHeader_Size)\r
+    return false;\r
+  XSize = Get32(p + 4);\r
+  YSize = (Int32)Get32(p + 8);\r
+  Planes = Get16(p + 12);\r
+  BitCount = Get16(p + 14);\r
+  Compression = Get32(p + 16);\r
+  SizeImage = Get32(p + 20);\r
+  return true;\r
+}\r
+\r
+static UInt32 GetImageSize(UInt32 xSize, UInt32 ySize, UInt32 bitCount)\r
+{\r
+  return ((xSize * bitCount + 7) / 8 + 3) / 4 * 4 * ySize;\r
+}\r
+  \r
+static UInt32 SetBitmapHeader(Byte *dest, const Byte *src, UInt32 size)\r
+{\r
+  CBitmapInfoHeader h;\r
+  if (!h.Parse(src, size))\r
+    return 0;\r
+  if (h.YSize < 0)\r
+    h.YSize = -h.YSize;\r
+  if (h.XSize > (1 << 26) || h.YSize > (1 << 26) || h.Planes != 1 || h.BitCount > 32 ||\r
+      h.Compression != 0) // BI_RGB\r
+    return 0;\r
+  if (h.SizeImage == 0)\r
+    h.SizeImage = GetImageSize(h.XSize, h.YSize, h.BitCount);\r
+  UInt32 totalSize = kBmpHeaderSize + size;\r
+  UInt32 offBits = totalSize - h.SizeImage;\r
+  // BITMAPFILEHEADER\r
+  SetUi16(dest, 0x4D42);\r
+  SetUi32(dest + 2, totalSize);\r
+  SetUi32(dest + 6, 0);\r
+  SetUi32(dest + 10, offBits);\r
+  return kBmpHeaderSize;\r
+}\r
+\r
+static UInt32 SetIconHeader(Byte *dest, const Byte *src, UInt32 size)\r
+{\r
+  CBitmapInfoHeader h;\r
+  if (!h.Parse(src, size))\r
+    return 0;\r
+  if (h.YSize < 0)\r
+    h.YSize = -h.YSize;\r
+  if (h.XSize > (1 << 26) || h.YSize > (1 << 26) || h.Planes != 1 ||\r
+      h.Compression != 0) // BI_RGB\r
+    return 0;\r
+\r
+  UInt32 numBitCount = h.BitCount;\r
+  if (numBitCount != 1 &&\r
+      numBitCount != 4 &&\r
+      numBitCount != 8 &&\r
+      numBitCount != 24 &&\r
+      numBitCount != 32)\r
+    return 0;\r
+\r
+  if ((h.YSize & 1) != 0)\r
+    return 0;\r
+  h.YSize /= 2;\r
+  if (h.XSize > 0x100 || h.YSize > 0x100)\r
+    return 0;\r
+\r
+  UInt32 imageSize;\r
+  // imageSize is not correct if AND mask array contains zeros\r
+  // in this case it is equal image1Size\r
+\r
+  // UInt32 imageSize = h.SizeImage;\r
+  // if (imageSize == 0)\r
+  // {\r
+    UInt32 image1Size = GetImageSize(h.XSize, h.YSize, h.BitCount);\r
+    UInt32 image2Size = GetImageSize(h.XSize, h.YSize, 1);\r
+    imageSize = image1Size + image2Size;\r
+  // }\r
+  UInt32 numColors = 0;\r
+  if (numBitCount < 16)\r
+    numColors = 1 << numBitCount;\r
+\r
+  SetUi16(dest, 0); // Reserved\r
+  SetUi16(dest + 2, 1); // RES_ICON\r
+  SetUi16(dest + 4, 1); // ResCount\r
+\r
+  dest[6] = (Byte)h.XSize; // Width\r
+  dest[7] = (Byte)h.YSize; // Height\r
+  dest[8] = (Byte)numColors; // ColorCount\r
+  dest[9] = 0; // Reserved\r
+  \r
+  SetUi32(dest + 10, 0); // Reserved1 / Reserved2\r
+\r
+  UInt32 numQuadsBytes = numColors * 4;\r
+  UInt32 BytesInRes = kBitmapInfoHeader_Size + numQuadsBytes + imageSize;\r
+  SetUi32(dest + 14, BytesInRes);\r
+  SetUi32(dest + 18, kIconHeaderSize);\r
+\r
+  /*\r
+  Description = DWORDToString(xSize) +\r
+      kDelimiterChar + DWORDToString(ySize) +\r
+      kDelimiterChar + DWORDToString(numBitCount);\r
+  */\r
+  return kIconHeaderSize;\r
+}\r
+\r
+bool CHandler::ParseStringRes(UInt32 id, UInt32 lang, const Byte *src, UInt32 size)\r
+{\r
+  if ((size & 1) != 0)\r
+    return false;\r
+\r
+  int i;\r
+  for (i = 0; i < _strings.Size(); i++)\r
+    if (_strings[i].Lang == lang)\r
+      break;\r
+  if (i == _strings.Size())\r
+  {\r
+    if (_strings.Size() >= kNumStringLangsMax)\r
+      return false;\r
+    CStringItem item;\r
+    item.Size = 0;\r
+    item.Lang = lang;\r
+    i = _strings.Add(item);\r
+  }\r
+  \r
+  CStringItem &item = _strings[i];\r
+  id = (id - 1) << 4;\r
+  UInt32 pos = 0;\r
+  for (i = 0; i < 16; i++)\r
+  {\r
+    if (size - pos < 2)\r
+      return false;\r
+    UInt32 len = Get16(src + pos);\r
+    pos += 2;\r
+    if (len != 0)\r
+    {\r
+      if (size - pos < len * 2)\r
+        return false;\r
+      char temp[32];\r
+      ConvertUInt32ToString(id  + i, temp);\r
+      size_t tempLen = strlen(temp);\r
+      size_t j;\r
+      for (j = 0; j < tempLen; j++)\r
+        item.AddChar(temp[j]);\r
+      item.AddChar('\t');\r
+      for (j = 0; j < len; j++, pos += 2)\r
+        item.AddWChar(Get16(src + pos));\r
+      item.AddChar(0x0D);\r
+      item.AddChar(0x0A);\r
+    }\r
+  }\r
+  return (size == pos);\r
+}\r
+\r
+HRESULT CHandler::OpenResources(int sectionIndex, IInStream *stream, IArchiveOpenCallback *callback)\r
+{\r
+  const CSection &sect = _sections[sectionIndex];\r
+  size_t fileSize = sect.PSize; // Maybe we need sect.VSize here !!!\r
+  if (fileSize > kFileSizeMax)\r
+    return S_FALSE;\r
+  {\r
+    UInt64 fileSize64 = fileSize;\r
+    if (callback)\r
+      RINOK(callback->SetTotal(NULL, &fileSize64));\r
+    RINOK(stream->Seek(sect.Pa, STREAM_SEEK_SET, NULL));\r
+    _buf.SetCapacity(fileSize);\r
+    for (size_t pos = 0; pos < fileSize;)\r
+    {\r
+      UInt64 offset64 = pos;\r
+      if (callback)\r
+        RINOK(callback->SetCompleted(NULL, &offset64))\r
+      size_t rem = MyMin(fileSize - pos, (size_t)(1 << 20));\r
+      RINOK(ReadStream_FALSE(stream, _buf + pos, rem));\r
+      pos += rem;\r
+    }\r
+  }\r
+  \r
+  _usedRes.Alloc(fileSize);\r
+  CRecordVector<CTableItem> specItems;\r
+  RINOK(ReadTable(0, specItems));\r
+\r
+  _oneLang = true;\r
+  bool stringsOk = true;\r
+  size_t maxOffset = 0;\r
+  for (int i = 0; i < specItems.Size(); i++)\r
+  {\r
+    const CTableItem &item1 = specItems[i];\r
+    if ((item1.Offset & kFlag) == 0)\r
+      return S_FALSE;\r
+\r
+    CRecordVector<CTableItem> specItems2;\r
+    RINOK(ReadTable(item1.Offset & kMask, specItems2));\r
+\r
+    for (int j = 0; j < specItems2.Size(); j++)\r
+    {\r
+      const CTableItem &item2 = specItems2[j];\r
+      if ((item2.Offset & kFlag) == 0)\r
+        return S_FALSE;\r
+      \r
+      CRecordVector<CTableItem> specItems3;\r
+      RINOK(ReadTable(item2.Offset & kMask, specItems3));\r
+      \r
+      CResItem item;\r
+      item.Type = item1.ID;\r
+      item.ID = item2.ID;\r
+      \r
+      for (int k = 0; k < specItems3.Size(); k++)\r
+      {\r
+        if (_items.Size() >= kNumResItemsMax)\r
+          return S_FALSE;\r
+        const CTableItem &item3 = specItems3[k];\r
+        if ((item3.Offset & kFlag) != 0)\r
+          return S_FALSE;\r
+        if (item3.Offset >= _buf.GetCapacity() || _buf.GetCapacity() - item3.Offset < 16)\r
+          return S_FALSE;\r
+        const Byte *buf = _buf + item3.Offset;\r
+        item.Lang = item3.ID;\r
+        item.Offset = Get32(buf + 0);\r
+        item.Size = Get32(buf + 4);\r
+        // UInt32 codePage = Get32(buf + 8);\r
+        if (Get32(buf + 12) != 0)\r
+          return S_FALSE;\r
+        if (!_items.IsEmpty() && _oneLang && !item.IsNameEqual(_items.Back()))\r
+          _oneLang = false;\r
+\r
+        item.HeaderSize = 0;\r
+      \r
+        size_t offset = item.Offset - sect.Va;\r
+        if (offset > maxOffset)\r
+          maxOffset = offset;\r
+        if (offset + item.Size > maxOffset)\r
+          maxOffset = offset + item.Size;\r
+\r
+        if (CheckItem(sect, item, offset))\r
+        {\r
+          const Byte *data = _buf + offset;\r
+          if (item.IsBmp())\r
+            item.HeaderSize = SetBitmapHeader(item.Header, data, item.Size);\r
+          else if (item.IsIcon())\r
+            item.HeaderSize = SetIconHeader(item.Header, data, item.Size);\r
+          else if (item.IsString())\r
+          {\r
+            if (stringsOk)\r
+              stringsOk = ParseStringRes(item.ID, item.Lang, data, item.Size);\r
+          }\r
+        }\r
+\r
+        item.Enabled = true;\r
+        _items.Add(item);\r
+      }\r
+    }\r
+  }\r
+  \r
+  if (stringsOk && !_strings.IsEmpty())\r
+  {\r
+    int i;\r
+    for (i = 0; i < _items.Size(); i++)\r
+    {\r
+      CResItem &item = _items[i];\r
+      if (item.IsString())\r
+        item.Enabled = false;\r
+    }\r
+    for (i = 0; i < _strings.Size(); i++)\r
+    {\r
+      if (_strings[i].Size == 0)\r
+        continue;\r
+      CMixItem mixItem;\r
+      mixItem.ResourceIndex = -1;\r
+      mixItem.StringIndex = i;\r
+      mixItem.SectionIndex = sectionIndex;\r
+      _mixItems.Add(mixItem);\r
+    }\r
+  }\r
+\r
+  _usedRes.Free();\r
+\r
+  int numBits = _optHeader.GetNumFileAlignBits();\r
+  if (numBits >= 0)\r
+  {\r
+    UInt32 mask = (1 << numBits) - 1;\r
+    size_t end = ((maxOffset + mask) & ~mask);\r
+    if (end < sect.VSize && end <= sect.PSize)\r
+    {\r
+      CSection sect2;\r
+      sect2.Flags = 0;\r
+\r
+      // we skip Zeros to start of aligned block\r
+      size_t i;\r
+      for (i = maxOffset; i < end; i++)\r
+        if (_buf[i] != 0)\r
+          break;\r
+      if (i == end)\r
+        maxOffset = end;\r
+      \r
+      sect2.Pa = sect.Pa + (UInt32)maxOffset;\r
+      sect2.Va = sect.Va + (UInt32)maxOffset;\r
+      sect2.PSize = sect.VSize - (UInt32)maxOffset;\r
+      sect2.VSize = sect2.PSize;\r
+      sect2.Name = ".rsrc_1";\r
+      sect2.Time = 0;\r
+      sect2.IsAdditionalSection = true;\r
+      _sections.Add(sect2);\r
+    }\r
+  }\r
+\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)\r
+{\r
+  const UInt32 kBufSize = 1 << 18;\r
+  const UInt32 kSigSize = 2;\r
+\r
+  _mainSubfile = -1;\r
+\r
+  CByteBuffer buffer;\r
+  buffer.SetCapacity(kBufSize);\r
+  Byte *buf = buffer;\r
+\r
+  size_t processed = kSigSize;\r
+  RINOK(ReadStream_FALSE(stream, buf, processed));\r
+  if (buf[0] != 'M' || buf[1] != 'Z')\r
+    return S_FALSE;\r
+  processed = kBufSize - kSigSize;\r
+  RINOK(ReadStream(stream, buf + kSigSize, &processed));\r
+  processed += kSigSize;\r
+  if (!Parse(buf, (UInt32)processed))\r
+    return S_FALSE;\r
+  bool thereISDebug;\r
+  RINOK(LoadDebugSections(stream, thereISDebug));\r
+\r
+  const CDirLink &certLink = _optHeader.DirItems[kDirLink_Certificate];\r
+  if (certLink.Size != 0)\r
+  {\r
+    CSection sect;\r
+    sect.Name = "CERTIFICATE";\r
+    sect.Va = 0;\r
+    sect.Pa = certLink.Va;\r
+    sect.PSize = sect.VSize = certLink.Size;\r
+    sect.UpdateTotalSize(_totalSize);\r
+    _sections.Add(sect);\r
+  }\r
+\r
+  if (thereISDebug)\r
+  {\r
+    const UInt32 kAlign = 1 << 12;\r
+    UInt32 alignPos = _totalSize & (kAlign - 1);\r
+    if (alignPos != 0)\r
+    {\r
+      UInt32 size = kAlign - alignPos;\r
+      RINOK(stream->Seek(_totalSize, STREAM_SEEK_SET, NULL));\r
+      buffer.Free();\r
+      buffer.SetCapacity(kAlign);\r
+      Byte *buf = buffer;\r
+      size_t processed = size;\r
+      RINOK(ReadStream(stream, buf, &processed));\r
+      size_t i;\r
+      for (i = 0; i < processed; i++)\r
+      {\r
+        if (buf[i] != 0)\r
+          break;\r
+      }\r
+      if (processed < size && processed < 100)\r
+        _totalSize += (UInt32)processed;\r
+      else if (((_totalSize + i) & 0x1FF) == 0 || processed < size)\r
+        _totalSize += (UInt32)i;\r
+    }\r
+  }\r
+\r
+  if (_header.NumSymbols > 0 && _header.PointerToSymbolTable >= 512)\r
+  {\r
+    if (_header.NumSymbols >= (1 << 24))\r
+      return S_FALSE;\r
+    CSection sect;\r
+    sect.Name = "COFF_SYMBOLS";\r
+    UInt32 size = _header.NumSymbols * 18;\r
+    RINOK(stream->Seek((UInt64)_header.PointerToSymbolTable + size, STREAM_SEEK_SET, NULL));\r
+    Byte buf[4];\r
+    RINOK(ReadStream_FALSE(stream, buf, 4));\r
+    UInt32 size2 = Get32(buf);\r
+    if (size2 >= (1 << 28))\r
+      return S_FALSE;\r
+    size += size2;\r
+\r
+    sect.Va = 0;\r
+    sect.Pa = _header.PointerToSymbolTable;\r
+    sect.PSize = sect.VSize = size;\r
+    sect.UpdateTotalSize(_totalSize);\r
+    _sections.Add(sect);\r
+  }\r
+\r
+  UInt64 fileSize;\r
+  RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize));\r
+  if (fileSize > _totalSize)\r
+    return S_FALSE;\r
+  _totalSizeLimited = (_totalSize < fileSize) ? _totalSize : (UInt32)fileSize;\r
+\r
+  {\r
+    CObjectVector<CSection> sections = _sections;\r
+    sections.Sort();\r
+    UInt32 limit = (1 << 12);\r
+    int num = 0;\r
+    int numSections = sections.Size();\r
+    for (int i = 0; i < numSections; i++)\r
+    {\r
+      const CSection &s = sections[i];\r
+      if (s.Pa > limit)\r
+      {\r
+        CSection s2;\r
+        s2.Pa = s2.Va = limit;\r
+        s2.PSize = s2.VSize = s.Pa - limit;\r
+        s2.IsAdditionalSection = true;\r
+        s2.Name = '[';\r
+        s2.Name += GetDecString(num++);\r
+        s2.Name += ']';\r
+        _sections.Add(s2);\r
+        limit = s.Pa;\r
+      }\r
+      UInt32 next = s.Pa + s.PSize;\r
+      if (next < s.Pa)\r
+        break;\r
+      if (next >= limit)\r
+        limit = next;\r
+    }\r
+  }\r
+\r
+  _parseResources = true;\r
+\r
+  UInt64 mainSize = 0, mainSize2 = 0;\r
+  int i;\r
+  for (i = 0; i < _sections.Size(); i++)\r
+  {\r
+    const CSection &sect = _sections[i];\r
+    CMixItem mixItem;\r
+    mixItem.SectionIndex = i;\r
+    if (_parseResources && sect.Name == ".rsrc" && _items.IsEmpty())\r
+    {\r
+      HRESULT res = OpenResources(i, stream, callback);\r
+      if (res == S_OK)\r
+      {\r
+        _resourceFileName = GetUnicodeString(sect.Name);\r
+        for (int j = 0; j < _items.Size(); j++)\r
+        {\r
+          const CResItem &item = _items[j];\r
+          if (item.Enabled)\r
+          {\r
+            mixItem.ResourceIndex = j;\r
+            mixItem.StringIndex = -1;\r
+            if (item.IsRcDataOrUnknown())\r
+            {\r
+              if (item.Size >= mainSize)\r
+              {\r
+                mainSize2 = mainSize;\r
+                mainSize = item.Size;\r
+                _mainSubfile = _mixItems.Size();\r
+              }\r
+              else if (item.Size >= mainSize2)\r
+                mainSize2 = item.Size;\r
+            }\r
+            _mixItems.Add(mixItem);\r
+          }\r
+        }\r
+        if (sect.PSize > sect.VSize)\r
+        {\r
+          int numBits = _optHeader.GetNumFileAlignBits();\r
+          if (numBits >= 0)\r
+          {\r
+            UInt32 mask = (1 << numBits) - 1;\r
+            UInt32 end = ((sect.VSize + mask) & ~mask);\r
+\r
+            if (sect.PSize > end)\r
+            {\r
+              CSection sect2;\r
+              sect2.Flags = 0;\r
+              sect2.Pa = sect.Pa + end;\r
+              sect2.Va = sect.Va + end;\r
+              sect2.PSize = sect.PSize - end;\r
+              sect2.VSize = sect2.PSize;\r
+              sect2.Name = ".rsrc_2";\r
+              sect2.Time = 0;\r
+              sect2.IsAdditionalSection = true;\r
+              _sections.Add(sect2);\r
+            }\r
+          }\r
+        }\r
+        continue;\r
+      }\r
+      if (res != S_FALSE)\r
+        return res;\r
+      CloseResources();\r
+    }\r
+    mixItem.StringIndex = -1;\r
+    mixItem.ResourceIndex = -1;\r
+    if (sect.IsAdditionalSection)\r
+    {\r
+      if (sect.PSize >= mainSize)\r
+      {\r
+        mainSize2 = mainSize;\r
+        mainSize = sect.PSize;\r
+        _mainSubfile = _mixItems.Size();\r
+      }\r
+      else\r
+        mainSize2 = sect.PSize;\r
+    }\r
+    _mixItems.Add(mixItem);\r
+  }\r
+  \r
+  if (mainSize2 >= (1 << 20) && mainSize < mainSize2 * 2)\r
+    _mainSubfile = -1;\r
+\r
+  for (i = 0; i < _mixItems.Size(); i++)\r
+  {\r
+    const CMixItem &mixItem = _mixItems[i];\r
+    if (mixItem.StringIndex < 0 && mixItem.ResourceIndex < 0 && _sections[mixItem.SectionIndex].Name == "_winzip_")\r
+    {\r
+      _mainSubfile = i;\r
+      break;\r
+    }\r
+  }\r
+\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CalcCheckSum(ISequentialInStream *stream, UInt32 size, UInt32 excludePos, UInt32 &res)\r
+{\r
+  // size &= ~1;\r
+  const UInt32 kBufSize = 1 << 23;\r
+  CByteBuffer buffer;\r
+  buffer.SetCapacity(kBufSize);\r
+  Byte *buf = buffer;\r
+\r
+  UInt32 sum = 0;\r
+  UInt32 pos = 0;\r
+  for (;;)\r
+  {\r
+    UInt32 rem = size - pos;\r
+    if (rem > kBufSize)\r
+      rem = kBufSize;\r
+    if (rem == 0)\r
+      break;\r
+    size_t processed = rem;\r
+    RINOK(ReadStream(stream, buf, &processed));\r
+    \r
+    /*\r
+    for (; processed < rem; processed++)\r
+      buf[processed] = 0;\r
+    */\r
+\r
+    if ((processed & 1) != 0)\r
+      buf[processed] = 0;\r
+\r
+    for (int j = 0; j < 4; j++)\r
+    {\r
+      UInt32 p = excludePos + j;\r
+      if (pos <= p && p < pos + processed)\r
+        buf[p - pos] = 0;\r
+    }\r
+\r
+    for (size_t i = 0; i < processed; i += 2)\r
+    {\r
+      sum += Get16(buf + i);\r
+      sum = (sum + (sum >> 16)) & 0xFFFF;\r
+    }\r
+    pos += (UInt32)processed;\r
+    if (rem != processed)\r
+      break;\r
+  }\r
+  sum += pos;\r
+  res = sum;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback)\r
+{\r
+  COM_TRY_BEGIN\r
+  Close();\r
+  RINOK(Open2(inStream, callback));\r
+  _stream = inStream;\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+void CHandler::CloseResources()\r
+{\r
+  _usedRes.Free();\r
+  _items.Clear();\r
+  _strings.Clear();\r
+  _buf.SetCapacity(0);\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _stream.Release();\r
+  _sections.Clear();\r
+  _mixItems.Clear();\r
+  CloseResources();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _mixItems.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _mixItems.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt64 totalSize = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    const CMixItem &mixItem = _mixItems[allFilesMode ? i : indices[i]];\r
+    if (mixItem.StringIndex >= 0)\r
+      totalSize += _strings[mixItem.StringIndex].Size;\r
+    else if (mixItem.ResourceIndex < 0)\r
+      totalSize += _sections[mixItem.SectionIndex].GetPackSize();\r
+    else\r
+      totalSize += _items[mixItem.ResourceIndex].GetSize();\r
+  }\r
+  extractCallback->SetTotal(totalSize);\r
+\r
+  UInt64 currentTotalSize = 0;\r
+  UInt64 currentItemSize;\r
+  \r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  bool checkSumOK = true;\r
+  if (_optHeader.CheckSum != 0 && (int)numItems == _mixItems.Size())\r
+  {\r
+    UInt32 checkSum = 0;\r
+    RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));\r
+    CalcCheckSum(_stream, _totalSizeLimited, _peOffset + kHeaderSize + 64, checkSum);\r
+    checkSumOK = (checkSum == _optHeader.CheckSum);\r
+  }\r
+\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);\r
+  streamSpec->SetStream(_stream);\r
+\r
+  for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)\r
+  {\r
+    lps->InSize = lps->OutSize = currentTotalSize;\r
+    RINOK(lps->SetCur());\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    UInt32 index = allFilesMode ? i : indices[i];\r
+\r
+    CMyComPtr<ISequentialOutStream> outStream;\r
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));\r
+    const CMixItem &mixItem = _mixItems[index];\r
+\r
+    const CSection &sect = _sections[mixItem.SectionIndex];\r
+    bool isOk = true;\r
+    if (mixItem.StringIndex >= 0)\r
+    {\r
+      const CStringItem &item = _strings[mixItem.StringIndex];\r
+      currentItemSize = item.Size;\r
+      if (!testMode && !outStream)\r
+        continue;\r
+\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      if (outStream)\r
+        RINOK(WriteStream(outStream, item.Buf, item.Size));\r
+    }\r
+    else if (mixItem.ResourceIndex < 0)\r
+    {\r
+      currentItemSize = sect.GetPackSize();\r
+      if (!testMode && !outStream)\r
+        continue;\r
+      \r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      RINOK(_stream->Seek(sect.Pa, STREAM_SEEK_SET, NULL));\r
+      streamSpec->Init(currentItemSize);\r
+      RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));\r
+      isOk = (copyCoderSpec->TotalSize == currentItemSize);\r
+    }\r
+    else\r
+    {\r
+      const CResItem &item = _items[mixItem.ResourceIndex];\r
+      currentItemSize = item.GetSize();\r
+      if (!testMode && !outStream)\r
+        continue;\r
+\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      size_t offset = item.Offset - sect.Va;\r
+      if (!CheckItem(sect, item, offset))\r
+        isOk = false;\r
+      else if (outStream)\r
+      {\r
+        if (item.HeaderSize != 0)\r
+          RINOK(WriteStream(outStream, item.Header, item.HeaderSize));\r
+        RINOK(WriteStream(outStream, _buf + offset, item.Size));\r
+      }\r
+    }\r
+    \r
+    outStream.Release();\r
+    RINOK(extractCallback->SetOperationResult(isOk ?\r
+      checkSumOK ?\r
+        NExtract::NOperationResult::kOK:\r
+        NExtract::NOperationResult::kCRCError:\r
+        NExtract::NOperationResult::kDataError));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)\r
+{\r
+  COM_TRY_BEGIN\r
+  *stream = 0;\r
+\r
+  const CMixItem &mixItem = _mixItems[index];\r
+  const CSection &sect = _sections[mixItem.SectionIndex];\r
+  if (mixItem.IsSectionItem())\r
+    return CreateLimitedInStream(_stream, sect.Pa, sect.PSize, stream);\r
+\r
+  CBufInStream *inStreamSpec = new CBufInStream;\r
+  CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;\r
+  CReferenceBuf *referenceBuf = new CReferenceBuf;\r
+  CMyComPtr<IUnknown> ref = referenceBuf;\r
+  if (mixItem.StringIndex >= 0)\r
+  {\r
+    const CStringItem &item = _strings[mixItem.StringIndex];\r
+    referenceBuf->Buf.SetCapacity(item.Size);\r
+    memcpy(referenceBuf->Buf, item.Buf, item.Size);\r
+  }\r
+  else\r
+  {\r
+    const CResItem &item = _items[mixItem.ResourceIndex];\r
+    size_t offset = item.Offset - sect.Va;\r
+    if (!CheckItem(sect, item, offset))\r
+      return S_FALSE;\r
+    if (item.HeaderSize == 0)\r
+    {\r
+      CBufInStream *streamSpec = new CBufInStream;\r
+      CMyComPtr<IInStream> streamTemp2 = streamSpec;\r
+      streamSpec->Init(_buf + offset, item.Size, (IInArchive *)this);\r
+      *stream = streamTemp2.Detach();\r
+      return S_OK;\r
+    }\r
+    referenceBuf->Buf.SetCapacity(item.HeaderSize + item.Size);\r
+    memcpy(referenceBuf->Buf, item.Header, item.HeaderSize);\r
+    memcpy(referenceBuf->Buf + item.HeaderSize, _buf + offset, item.Size);\r
+  }\r
+  inStreamSpec->Init(referenceBuf);\r
+\r
+  *stream = streamTemp.Detach();\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"PE", L"exe dll sys", 0, 0xDD, { 'P', 'E', 0, 0 }, 4, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Pe)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/PpmdHandler.cpp b/CPP/7zip/Archive/PpmdHandler.cpp
new file mode 100755 (executable)
index 0000000..e9ee2b1
--- /dev/null
@@ -0,0 +1,456 @@
+/* PpmdHandler.c -- PPMd format handler\r
+2010-03-10 : Igor Pavlov : Public domain\r
+This code is based on:\r
+  PPMd var.H (2001) / var.I (2002): Dmitry Shkarin : Public domain\r
+  Carryless rangecoder (1999): Dmitry Subbotin : Public domain */\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/CpuArch.h"\r
+#include "../../../C/Alloc.h"\r
+#include "../../../C/Ppmd7.h"\r
+#include "../../../C/Ppmd8.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../Common/CWrappers.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace NPpmd {\r
+\r
+static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }\r
+static void SzBigFree(void *, void *address) { BigFree(address); }\r
+static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };\r
+\r
+static const UInt32 kBufSize = (1 << 20);\r
+\r
+struct CBuf\r
+{\r
+  Byte *Buf;\r
+  \r
+  CBuf(): Buf(0) {}\r
+  ~CBuf() { ::MidFree(Buf); }\r
+  bool Alloc()\r
+  {\r
+    if (!Buf)\r
+      Buf = (Byte *)::MidAlloc(kBufSize);\r
+    return (Buf != 0);\r
+  }\r
+};\r
+\r
+static const UInt32 kHeaderSize = 16;\r
+static const UInt32 kSignature = 0x84ACAF8F;\r
+static const unsigned kNewHeaderVer = 8;\r
+\r
+struct CItem\r
+{\r
+  UInt32 Attrib;\r
+  UInt32 Time;\r
+  AString Name;\r
+  \r
+  unsigned Order;\r
+  unsigned MemInMB;\r
+  unsigned Ver;\r
+  unsigned Restor;\r
+\r
+  HRESULT ReadHeader(ISequentialInStream *s, UInt32 &headerSize);\r
+  bool IsSupported() const { return Ver == 7 || (Ver == 8 && Restor <= 1); }\r
+};\r
+\r
+HRESULT CItem::ReadHeader(ISequentialInStream *s, UInt32 &headerSize)\r
+{\r
+  Byte h[kHeaderSize];\r
+  RINOK(ReadStream_FALSE(s, h, kHeaderSize));\r
+  if (GetUi32(h) != kSignature)\r
+    return S_FALSE;\r
+  Attrib = GetUi32(h + 4);\r
+  Time = GetUi32(h + 12);\r
+  \r
+  unsigned info = GetUi16(h + 8);\r
+  Order = (info & 0xF) + 1;\r
+  MemInMB = ((info >> 4) & 0xFF) + 1;\r
+  Ver = info >> 12;\r
\r
+  UInt32 nameLen = GetUi16(h + 10);\r
+  Restor = nameLen >> 14;\r
+  if (Restor > 2)\r
+    return S_FALSE;\r
+  if (Ver >= kNewHeaderVer)\r
+    nameLen &= 0x3FFF;\r
+  if (nameLen > (1 << 9))\r
+    return S_FALSE;\r
+  char *name = Name.GetBuffer(nameLen + 1);\r
+  HRESULT res = ReadStream_FALSE(s, name, nameLen);\r
+  name[nameLen] = 0;\r
+  headerSize = kHeaderSize + nameLen;\r
+  Name.ReleaseBuffer();\r
+  return res;\r
+}\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IArchiveOpenSeq,\r
+  public CMyUnknownImp\r
+{\r
+  CItem _item;\r
+  UInt32 _headerSize;\r
+  UInt64 _packSize;\r
+  bool _packSizeDefined;\r
+  CMyComPtr<ISequentialInStream> _stream;\r
+\r
+public:\r
+  MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq)\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(OpenSeq)(ISequentialInStream *stream);\r
+};\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidAttrib, VT_UI4},\r
+  { NULL, kpidMethod, VT_BSTR}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps_NO_Table\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = 1;\r
+  return S_OK;\r
+}\r
+\r
+static void UIntToString(AString &s, const char *prefix, unsigned value)\r
+{\r
+  s += prefix;\r
+  char temp[16];\r
+  ::ConvertUInt32ToString((UInt32)value, temp);\r
+  s += temp;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID,  PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidPath: prop = MultiByteToUnicodeString(_item.Name, CP_ACP); break;\r
+    case kpidMTime:\r
+    {\r
+      FILETIME utc;\r
+      if (NTime::DosTimeToFileTime(_item.Time, utc))\r
+        prop = utc;\r
+      break;\r
+    }\r
+    case kpidAttrib: prop = _item.Attrib; break;\r
+    case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;\r
+    case kpidMethod:\r
+    {\r
+      AString s = "PPMd";\r
+      s += (char)('A' + _item.Ver);\r
+      UIntToString(s, ":o", _item.Order);\r
+      UIntToString(s, ":mem", _item.MemInMB);\r
+      s += 'm';\r
+      if (_item.Ver >= kNewHeaderVer && _item.Restor != 0)\r
+        UIntToString(s, ":r", _item.Restor);\r
+      prop = s;\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *)\r
+{\r
+  return OpenSeq(stream);\r
+}\r
+\r
+STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)\r
+{\r
+  COM_TRY_BEGIN\r
+  HRESULT res;\r
+  try\r
+  {\r
+    Close();\r
+    res = _item.ReadHeader(stream, _headerSize);\r
+  }\r
+  catch(...) { res = S_FALSE; }\r
+  if (res == S_OK)\r
+    _stream = stream;\r
+  else\r
+    Close();\r
+  return res;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _packSizeDefined = false;\r
+  _stream.Release();\r
+  return S_OK;\r
+}\r
+\r
+static const UInt32 kTopValue = (1 << 24);\r
+static const UInt32 kBot = (1 << 15);\r
+\r
+struct CRangeDecoder\r
+{\r
+  IPpmd7_RangeDec s;\r
+  UInt32 Range;\r
+  UInt32 Code;\r
+  UInt32 Low;\r
+  CByteInBufWrap *Stream;\r
+\r
+public:\r
+  bool Init()\r
+  {\r
+    Code = 0;\r
+    Low = 0;\r
+    Range = 0xFFFFFFFF;\r
+    for (int i = 0; i < 4; i++)\r
+      Code = (Code << 8) | Stream->ReadByte();\r
+    return Code < 0xFFFFFFFF;\r
+  }\r
+\r
+  void Normalize()\r
+  {\r
+    while ((Low ^ (Low + Range)) < kTopValue ||\r
+       Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1))\r
+    {\r
+      Code = (Code << 8) | Stream->ReadByte();\r
+      Range <<= 8;\r
+      Low <<= 8;\r
+    }\r
+  }\r
+\r
+  CRangeDecoder();\r
+};\r
+\r
+\r
+extern "C" {\r
+\r
+static UInt32 Range_GetThreshold(void *pp, UInt32 total)\r
+{\r
+  CRangeDecoder *p = (CRangeDecoder *)pp;\r
+  return p->Code / (p->Range /= total);\r
+}\r
+\r
+static void Range_Decode(void *pp, UInt32 start, UInt32 size)\r
+{\r
+  CRangeDecoder *p = (CRangeDecoder *)pp;\r
+  start *= p->Range;\r
+  p->Low += start;\r
+  p->Code -= start;\r
+  p->Range *= size;\r
+  p->Normalize();\r
+}\r
+\r
+static UInt32 Range_DecodeBit(void *pp, UInt32 size0)\r
+{\r
+  CRangeDecoder *p = (CRangeDecoder *)pp;\r
+  if (p->Code / (p->Range >>= 14) < size0)\r
+  {\r
+    Range_Decode(p, 0, size0);\r
+    return 0;\r
+  }\r
+  else\r
+  {\r
+    Range_Decode(p, size0, (1 << 14) - size0);\r
+    return 1;\r
+  }\r
+}\r
+\r
+}\r
+\r
+CRangeDecoder::CRangeDecoder()\r
+{\r
+  s.GetThreshold = Range_GetThreshold;\r
+  s.Decode = Range_Decode;\r
+  s.DecodeBit = Range_DecodeBit;\r
+}\r
+\r
+struct CPpmdCpp\r
+{\r
+  unsigned Ver;\r
+  CRangeDecoder _rc;\r
+  CPpmd7 _ppmd7;\r
+  CPpmd8 _ppmd8;\r
+  \r
+  CPpmdCpp(unsigned version)\r
+  {\r
+    Ver = version;\r
+    Ppmd7_Construct(&_ppmd7);\r
+    Ppmd8_Construct(&_ppmd8);\r
+  }\r
+\r
+  ~CPpmdCpp()\r
+  {\r
+    Ppmd7_Free(&_ppmd7, &g_BigAlloc);\r
+    Ppmd8_Free(&_ppmd8, &g_BigAlloc);\r
+  }\r
+\r
+  bool Alloc(UInt32 memInMB)\r
+  {\r
+    memInMB <<= 20;\r
+    if (Ver == 7)\r
+      return Ppmd7_Alloc(&_ppmd7, memInMB, &g_BigAlloc) != 0;\r
+    return Ppmd8_Alloc(&_ppmd8, memInMB, &g_BigAlloc) != 0;\r
+  }\r
+\r
+  void Init(unsigned order, unsigned restor)\r
+  {\r
+    if (Ver == 7)\r
+      Ppmd7_Init(&_ppmd7, order);\r
+    else\r
+      Ppmd8_Init(&_ppmd8, order, restor);;\r
+  }\r
+    \r
+  bool InitRc(CByteInBufWrap *inStream)\r
+  {\r
+    if (Ver == 7)\r
+    {\r
+      _rc.Stream = inStream;\r
+      return _rc.Init();\r
+    }\r
+    else\r
+    {\r
+      _ppmd8.Stream.In = &inStream->p;\r
+      return Ppmd8_RangeDec_Init(&_ppmd8) != 0;\r
+    }\r
+  }\r
+\r
+  bool IsFinishedOK()\r
+  {\r
+    if (Ver == 7)\r
+      return Ppmd7z_RangeDec_IsFinishedOK(&_rc);\r
+    return Ppmd8_RangeDec_IsFinishedOK(&_ppmd8);\r
+  }\r
+};\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))\r
+    return E_INVALIDARG;\r
+\r
+  // extractCallback->SetTotal(_packSize);\r
+  UInt64 currentTotalPacked = 0;\r
+  RINOK(extractCallback->SetCompleted(&currentTotalPacked));\r
+  CMyComPtr<ISequentialOutStream> realOutStream;\r
+  Int32 askMode = testMode ?\r
+      NExtract::NAskMode::kTest :\r
+      NExtract::NAskMode::kExtract;\r
+  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));\r
+  if (!testMode && !realOutStream)\r
+    return S_OK;\r
+\r
+  extractCallback->PrepareOperation(askMode);\r
+\r
+  CByteInBufWrap inBuf;\r
+  if (!inBuf.Alloc(1 << 20))\r
+    return E_OUTOFMEMORY;\r
+  inBuf.Stream = _stream;\r
+\r
+  CBuf outBuf;\r
+  if (!outBuf.Alloc())\r
+    return E_OUTOFMEMORY;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, true);\r
+\r
+  CPpmdCpp ppmd(_item.Ver);\r
+  if (!ppmd.Alloc(_item.MemInMB))\r
+    return E_OUTOFMEMORY;\r
+  Int32 opRes = NExtract::NOperationResult::kUnSupportedMethod;\r
+  if (_item.IsSupported())\r
+  {\r
+    opRes = NExtract::NOperationResult::kDataError;\r
+    ppmd.Init(_item.Order, _item.Restor);\r
+    inBuf.Init();\r
+    UInt64 outSize = 0;\r
+    if (ppmd.InitRc(&inBuf) && !inBuf.Extra && inBuf.Res == S_OK)\r
+    for (;;)\r
+    {\r
+      lps->InSize = _packSize = inBuf.GetProcessed();\r
+      lps->OutSize = outSize;\r
+      RINOK(lps->SetCur());\r
+\r
+      size_t i;\r
+      int sym = 0;\r
+\r
+      if (ppmd.Ver == 7)\r
+      {\r
+        for (i = 0; i < kBufSize; i++)\r
+        {\r
+          sym = Ppmd7_DecodeSymbol(&ppmd._ppmd7, &ppmd._rc.s);\r
+          if (inBuf.Extra || sym < 0)\r
+            break;\r
+          outBuf.Buf[i] = (Byte)sym;\r
+        }\r
+      }\r
+      else\r
+      {\r
+        for (i = 0; i < kBufSize; i++)\r
+        {\r
+          sym = Ppmd8_DecodeSymbol(&ppmd._ppmd8);\r
+          if (inBuf.Extra || sym < 0)\r
+            break;\r
+          outBuf.Buf[i] = (Byte)sym;\r
+        }\r
+      }\r
+\r
+      outSize += i;\r
+      _packSize = _headerSize + inBuf.GetProcessed();\r
+      _packSizeDefined = true;\r
+      if (realOutStream)\r
+      {\r
+        RINOK(WriteStream(realOutStream, outBuf.Buf, i));\r
+      }\r
+      if (sym < 0)\r
+      {\r
+        if (sym == -1 && ppmd.IsFinishedOK())\r
+          opRes = NExtract::NOperationResult::kOK;\r
+        break;\r
+      }\r
+    }\r
+    RINOK(inBuf.Res);\r
+  }\r
+  realOutStream.Release();\r
+  return extractCallback->SetOperationResult(opRes);\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"Ppmd", L"pmd", 0, 0xD, { 0x8F, 0xAF, 0xAC, 0x84 }, 4, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Ppmd)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp
new file mode 100755 (executable)
index 0000000..15abec6
--- /dev/null
@@ -0,0 +1,869 @@
+// RarHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/PropVariantUtils.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../../IPassword.h"\r
+\r
+#include "../../Common/CreateCoder.h"\r
+#include "../../Common/FilterCoder.h"\r
+#include "../../Common/MethodId.h"\r
+#include "../../Common/ProgressUtils.h"\r
+\r
+#include "../../Compress/CopyCoder.h"\r
+\r
+#include "../../Crypto/Rar20Crypto.h"\r
+#include "../../Crypto/RarAes.h"\r
+\r
+#include "../Common/ItemNameUtils.h"\r
+#include "../Common/OutStreamWithCRC.h"\r
+\r
+#include "RarHandler.h"\r
+\r
+using namespace NWindows;\r
+using namespace NTime;\r
+\r
+namespace NArchive {\r
+namespace NRar {\r
+\r
+static const wchar_t *kHostOS[] =\r
+{\r
+  L"MS DOS",\r
+  L"OS/2",\r
+  L"Win32",\r
+  L"Unix",\r
+  L"Mac OS",\r
+  L"BeOS"\r
+};\r
+\r
+static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]);\r
+\r
+static const wchar_t *kUnknownOS = L"Unknown";\r
+\r
+static const CUInt32PCharPair k_Flags[] =\r
+{\r
+  { 0, "Volume" },\r
+  { 1, "Comment" },\r
+  { 2, "Lock" },\r
+  { 3, "Solid" },\r
+  { 4, "NewVolName" }, // pack_comment in old versuons\r
+  { 5, "Authenticity" },\r
+  { 6, "Recovery" },\r
+  { 7, "BlockEncryption" },\r
+  { 8, "FirstVolume" },\r
+  { 9, "EncryptVer" }\r
+};\r
+\r
+static const STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidIsDir, VT_BOOL},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidCTime, VT_FILETIME},\r
+  { NULL, kpidATime, VT_FILETIME},\r
+  { NULL, kpidAttrib, VT_UI4},\r
+\r
+  { NULL, kpidEncrypted, VT_BOOL},\r
+  { NULL, kpidSolid, VT_BOOL},\r
+  { NULL, kpidCommented, VT_BOOL},\r
+  { NULL, kpidSplitBefore, VT_BOOL},\r
+  { NULL, kpidSplitAfter, VT_BOOL},\r
+  { NULL, kpidCRC, VT_UI4},\r
+  { NULL, kpidHostOS, VT_BSTR},\r
+  { NULL, kpidMethod, VT_BSTR},\r
+  { NULL, kpidUnpackVer, VT_UI1}\r
+};\r
+\r
+static const STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidCharacts, VT_BSTR},\r
+  { NULL, kpidSolid, VT_BOOL},\r
+  { NULL, kpidNumBlocks, VT_UI4},\r
+  // { NULL, kpidEncrypted, VT_BOOL},\r
+  { NULL, kpidIsVolume, VT_BOOL},\r
+  { NULL, kpidNumVolumes, VT_UI4},\r
+  { NULL, kpidPhySize, VT_UI8}\r
+  // { NULL, kpidCommented, VT_BOOL}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+UInt64 CHandler::GetPackSize(int refIndex) const\r
+{\r
+  const CRefItem &refItem = _refItems[refIndex];\r
+  UInt64 totalPackSize = 0;\r
+  for (int i = 0; i < refItem.NumItems; i++)\r
+    totalPackSize += _items[refItem.ItemIndex + i].PackSize;\r
+  return totalPackSize;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidSolid: prop = _archiveInfo.IsSolid(); break;\r
+    case kpidCharacts: FLAGS_TO_PROP(k_Flags, _archiveInfo.Flags, prop); break;\r
+    // case kpidEncrypted: prop = _archiveInfo.IsEncrypted(); break; // it's for encrypted names.\r
+    case kpidIsVolume: prop = _archiveInfo.IsVolume(); break;\r
+    case kpidNumVolumes: prop = (UInt32)_archives.Size(); break;\r
+    case kpidOffset: if (_archiveInfo.StartPosition != 0) prop = _archiveInfo.StartPosition; break;\r
+    // case kpidCommented: prop = _archiveInfo.IsCommented(); break;\r
+    case kpidNumBlocks:\r
+    {\r
+      UInt32 numBlocks = 0;\r
+      for (int i = 0; i < _refItems.Size(); i++)\r
+        if (!IsSolid(i))\r
+          numBlocks++;\r
+      prop = (UInt32)numBlocks;\r
+      break;\r
+    }\r
+    case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _refItems.Size();\r
+  return S_OK;\r
+}\r
+\r
+static bool RarTimeToFileTime(const CRarTime &rarTime, FILETIME &result)\r
+{\r
+  if (!DosTimeToFileTime(rarTime.DosTime, result))\r
+    return false;\r
+  UInt64 value =  (((UInt64)result.dwHighDateTime) << 32) + result.dwLowDateTime;\r
+  value += (UInt64)rarTime.LowSecond * 10000000;\r
+  value += ((UInt64)rarTime.SubTime[2] << 16) +\r
+    ((UInt64)rarTime.SubTime[1] << 8) +\r
+    ((UInt64)rarTime.SubTime[0]);\r
+  result.dwLowDateTime = (DWORD)value;\r
+  result.dwHighDateTime = DWORD(value >> 32);\r
+  return true;\r
+}\r
+\r
+static void RarTimeToProp(const CRarTime &rarTime, NWindows::NCOM::CPropVariant &prop)\r
+{\r
+  FILETIME localFileTime, utcFileTime;\r
+  if (RarTimeToFileTime(rarTime, localFileTime))\r
+  {\r
+    if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime))\r
+      utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;\r
+  }\r
+  else\r
+    utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;\r
+  prop = utcFileTime;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID,  PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  const CRefItem &refItem = _refItems[index];\r
+  const CItemEx &item = _items[refItem.ItemIndex];\r
+  switch(propID)\r
+  {\r
+    case kpidPath:\r
+    {\r
+      UString u;\r
+      if (item.HasUnicodeName() && !item.UnicodeName.IsEmpty())\r
+        u = item.UnicodeName;\r
+      else\r
+        u = MultiByteToUnicodeString(item.Name, CP_OEMCP);\r
+      prop = (const wchar_t *)NItemName::WinNameToOSName(u);\r
+      break;\r
+    }\r
+    case kpidIsDir: prop = item.IsDir(); break;\r
+    case kpidSize: prop = item.Size; break;\r
+    case kpidPackSize: prop = GetPackSize(index); break;\r
+    case kpidMTime: RarTimeToProp(item.MTime, prop); break;\r
+    case kpidCTime: if (item.CTimeDefined) RarTimeToProp(item.CTime, prop); break;\r
+    case kpidATime: if (item.ATimeDefined) RarTimeToProp(item.ATime, prop); break;\r
+    case kpidAttrib: prop = item.GetWinAttributes(); break;\r
+    case kpidEncrypted: prop = item.IsEncrypted(); break;\r
+    case kpidSolid: prop = IsSolid(index); break;\r
+    case kpidCommented: prop = item.IsCommented(); break;\r
+    case kpidSplitBefore: prop = item.IsSplitBefore(); break;\r
+    case kpidSplitAfter: prop = _items[refItem.ItemIndex + refItem.NumItems - 1].IsSplitAfter(); break;\r
+    case kpidCRC:\r
+    {\r
+      const CItemEx &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];\r
+      prop = ((lastItem.IsSplitAfter()) ? item.FileCRC : lastItem.FileCRC);\r
+      break;\r
+    }\r
+    case kpidUnpackVer: prop = item.UnPackVersion; break;\r
+    case kpidMethod:\r
+    {\r
+      UString method;\r
+      if (item.Method >= Byte('0') && item.Method <= Byte('5'))\r
+      {\r
+        method = L"m";\r
+        wchar_t temp[32];\r
+        ConvertUInt64ToString(item.Method - Byte('0'), temp);\r
+        method += temp;\r
+        if (!item.IsDir())\r
+        {\r
+          method += L":";\r
+          ConvertUInt64ToString(16 + item.GetDictSize(), temp);\r
+          method += temp;\r
+        }\r
+      }\r
+      else\r
+      {\r
+        wchar_t temp[32];\r
+        ConvertUInt64ToString(item.Method, temp);\r
+        method += temp;\r
+      }\r
+      prop = method;\r
+      break;\r
+    }\r
+    case kpidHostOS: prop = (item.HostOS < kNumHostOSes) ? (kHostOS[item.HostOS]) : kUnknownOS; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+class CVolumeName\r
+{\r
+  bool _first;\r
+  bool _newStyle;\r
+  UString _unchangedPart;\r
+  UString _changedPart;\r
+  UString _afterPart;\r
+public:\r
+  CVolumeName(): _newStyle(true) {};\r
+\r
+  bool InitName(const UString &name, bool newStyle)\r
+  {\r
+    _first = true;\r
+    _newStyle = newStyle;\r
+    int dotPos = name.ReverseFind('.');\r
+    UString basePart = name;\r
+    if (dotPos >= 0)\r
+    {\r
+      UString ext = name.Mid(dotPos + 1);\r
+      if (ext.CompareNoCase(L"rar") == 0)\r
+      {\r
+        _afterPart = name.Mid(dotPos);\r
+        basePart = name.Left(dotPos);\r
+      }\r
+      else if (ext.CompareNoCase(L"exe") == 0)\r
+      {\r
+        _afterPart = L".rar";\r
+        basePart = name.Left(dotPos);\r
+      }\r
+      else if (!_newStyle)\r
+      {\r
+        if (ext.CompareNoCase(L"000") == 0 ||\r
+            ext.CompareNoCase(L"001") == 0 ||\r
+            ext.CompareNoCase(L"r00") == 0 ||\r
+            ext.CompareNoCase(L"r01") == 0)\r
+        {\r
+          _afterPart.Empty();\r
+          _first = false;\r
+          _changedPart = ext;\r
+          _unchangedPart = name.Left(dotPos + 1);\r
+          return true;\r
+        }\r
+      }\r
+    }\r
+\r
+    if (!_newStyle)\r
+    {\r
+      _afterPart.Empty();\r
+      _unchangedPart = basePart + UString(L".");\r
+      _changedPart = L"r00";\r
+      return true;\r
+    }\r
+\r
+    int numLetters = 1;\r
+    if (basePart.Right(numLetters) == L"1" || basePart.Right(numLetters) == L"0")\r
+    {\r
+      while (numLetters < basePart.Length())\r
+      {\r
+        if (basePart[basePart.Length() - numLetters - 1] != '0')\r
+          break;\r
+        numLetters++;\r
+      }\r
+    }\r
+    else\r
+      return false;\r
+    _unchangedPart = basePart.Left(basePart.Length() - numLetters);\r
+    _changedPart = basePart.Right(numLetters);\r
+    return true;\r
+  }\r
+\r
+  UString GetNextName()\r
+  {\r
+    UString newName;\r
+    if (_newStyle || !_first)\r
+    {\r
+      int i;\r
+      int numLetters = _changedPart.Length();\r
+      for (i = numLetters - 1; i >= 0; i--)\r
+      {\r
+        wchar_t c = _changedPart[i];\r
+        if (c == L'9')\r
+        {\r
+          c = L'0';\r
+          newName = c + newName;\r
+          if (i == 0)\r
+            newName = UString(L'1') + newName;\r
+          continue;\r
+        }\r
+        c++;\r
+        newName = UString(c) + newName;\r
+        i--;\r
+        for (; i >= 0; i--)\r
+          newName = _changedPart[i] + newName;\r
+        break;\r
+      }\r
+      _changedPart = newName;\r
+    }\r
+    _first = false;\r
+    return _unchangedPart + _changedPart + _afterPart;\r
+  }\r
+};\r
+\r
+HRESULT CHandler::Open2(IInStream *stream,\r
+    const UInt64 *maxCheckStartPosition,\r
+    IArchiveOpenCallback *openCallback)\r
+{\r
+  {\r
+    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;\r
+    CMyComPtr<ICryptoGetTextPassword> getTextPassword;\r
+    CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openCallback;\r
+    \r
+    CVolumeName seqName;\r
+\r
+    UInt64 totalBytes = 0;\r
+    UInt64 curBytes = 0;\r
+\r
+    if (openCallback)\r
+    {\r
+      openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);\r
+      openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);\r
+    }\r
+\r
+    for (;;)\r
+    {\r
+      CMyComPtr<IInStream> inStream;\r
+      if (!_archives.IsEmpty())\r
+      {\r
+        if (!openVolumeCallback)\r
+          break;\r
+        \r
+        if (_archives.Size() == 1)\r
+        {\r
+          if (!_archiveInfo.IsVolume())\r
+            break;\r
+          UString baseName;\r
+          {\r
+            NCOM::CPropVariant prop;\r
+            RINOK(openVolumeCallback->GetProperty(kpidName, &prop));\r
+            if (prop.vt != VT_BSTR)\r
+              break;\r
+            baseName = prop.bstrVal;\r
+          }\r
+          seqName.InitName(baseName, _archiveInfo.HaveNewVolumeName());\r
+        }\r
+\r
+        UString fullName = seqName.GetNextName();\r
+        HRESULT result = openVolumeCallback->GetStream(fullName, &inStream);\r
+        if (result == S_FALSE)\r
+          break;\r
+        if (result != S_OK)\r
+          return result;\r
+        if (!stream)\r
+          break;\r
+      }\r
+      else\r
+        inStream = stream;\r
+\r
+      UInt64 endPos = 0;\r
+      RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));\r
+      RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));\r
+      if (openCallback)\r
+      {\r
+        totalBytes += endPos;\r
+        RINOK(openCallback->SetTotal(NULL, &totalBytes));\r
+      }\r
+      \r
+      NArchive::NRar::CInArchive archive;\r
+      RINOK(archive.Open(inStream, maxCheckStartPosition));\r
+\r
+      if (_archives.IsEmpty())\r
+        archive.GetArchiveInfo(_archiveInfo);\r
+     \r
+      CItemEx item;\r
+      for (;;)\r
+      {\r
+        if (archive.m_Position > endPos)\r
+        {\r
+          AddErrorMessage("Unexpected end of archive");\r
+          break;\r
+        }\r
+        bool decryptionError;\r
+        AString errorMessageLoc;\r
+        HRESULT result = archive.GetNextItem(item, getTextPassword, decryptionError, errorMessageLoc);\r
+        if (errorMessageLoc)\r
+          AddErrorMessage(errorMessageLoc);\r
+        if (result == S_FALSE)\r
+        {\r
+          if (decryptionError && _items.IsEmpty())\r
+            return S_FALSE;\r
+          break;\r
+        }\r
+        RINOK(result);\r
+        if (item.IgnoreItem())\r
+          continue;\r
+\r
+        bool needAdd = true;\r
+        if (item.IsSplitBefore())\r
+        {\r
+          if (!_refItems.IsEmpty())\r
+          {\r
+            CRefItem &refItem = _refItems.Back();\r
+            refItem.NumItems++;\r
+            needAdd = false;\r
+          }\r
+        }\r
+        if (needAdd)\r
+        {\r
+          CRefItem refItem;\r
+          refItem.ItemIndex = _items.Size();\r
+          refItem.NumItems = 1;\r
+          refItem.VolumeIndex = _archives.Size();\r
+          _refItems.Add(refItem);\r
+        }\r
+        _items.Add(item);\r
+        if (openCallback && _items.Size() % 100 == 0)\r
+        {\r
+          UInt64 numFiles = _items.Size();\r
+          UInt64 numBytes = curBytes + item.Position;\r
+          RINOK(openCallback->SetCompleted(&numFiles, &numBytes));\r
+        }\r
+      }\r
+      curBytes += endPos;\r
+      _archives.Add(archive);\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream,\r
+    const UInt64 *maxCheckStartPosition,\r
+    IArchiveOpenCallback *openCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  Close();\r
+  try\r
+  {\r
+    HRESULT res = Open2(stream, maxCheckStartPosition, openCallback);\r
+    if (res != S_OK)\r
+      Close();\r
+    return res;\r
+  }\r
+  catch(const CInArchiveException &) { Close(); return S_FALSE; }\r
+  catch(...) { Close(); throw; }\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  COM_TRY_BEGIN\r
+  _errorMessage.Empty();\r
+  _refItems.Clear();\r
+  _items.Clear();\r
+  _archives.Clear();\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+struct CMethodItem\r
+{\r
+  Byte RarUnPackVersion;\r
+  CMyComPtr<ICompressCoder> Coder;\r
+};\r
+\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  CMyComPtr<ICryptoGetTextPassword> getTextPassword;\r
+  UInt64 censoredTotalUnPacked = 0,\r
+        // censoredTotalPacked = 0,\r
+        importantTotalUnPacked = 0;\r
+        // importantTotalPacked = 0;\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _refItems.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  int lastIndex = 0;\r
+  CRecordVector<int> importantIndexes;\r
+  CRecordVector<bool> extractStatuses;\r
+\r
+  for (UInt32 t = 0; t < numItems; t++)\r
+  {\r
+    int index = allFilesMode ? t : indices[t];\r
+    const CRefItem &refItem = _refItems[index];\r
+    const CItemEx &item = _items[refItem.ItemIndex];\r
+    censoredTotalUnPacked += item.Size;\r
+    // censoredTotalPacked += item.PackSize;\r
+    int j;\r
+    for (j = lastIndex; j <= index; j++)\r
+      // if (!_items[_refItems[j].ItemIndex].IsSolid())\r
+      if (!IsSolid(j))\r
+        lastIndex = j;\r
+    for (j = lastIndex; j <= index; j++)\r
+    {\r
+      const CRefItem &refItem = _refItems[j];\r
+      const CItemEx &item = _items[refItem.ItemIndex];\r
+\r
+      // const CItemEx &item = _items[j];\r
+\r
+      importantTotalUnPacked += item.Size;\r
+      // importantTotalPacked += item.PackSize;\r
+      importantIndexes.Add(j);\r
+      extractStatuses.Add(j == index);\r
+    }\r
+    lastIndex = index + 1;\r
+  }\r
+\r
+  RINOK(extractCallback->SetTotal(importantTotalUnPacked));\r
+  UInt64 currentImportantTotalUnPacked = 0;\r
+  UInt64 currentImportantTotalPacked = 0;\r
+  UInt64 currentUnPackSize, currentPackSize;\r
+\r
+  CObjectVector<CMethodItem> methodItems;\r
+\r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CFilterCoder *filterStreamSpec = new CFilterCoder;\r
+  CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec;\r
+\r
+  NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec = NULL;\r
+  CMyComPtr<ICompressFilter> rar20CryptoDecoder;\r
+  NCrypto::NRar29::CDecoder *rar29CryptoDecoderSpec = NULL;\r
+  CMyComPtr<ICompressFilter> rar29CryptoDecoder;\r
+\r
+  CFolderInStream *folderInStreamSpec = NULL;\r
+  CMyComPtr<ISequentialInStream> folderInStream;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  bool solidStart = true;\r
+  for (int i = 0; i < importantIndexes.Size(); i++,\r
+      currentImportantTotalUnPacked += currentUnPackSize,\r
+      currentImportantTotalPacked += currentPackSize)\r
+  {\r
+    lps->InSize = currentImportantTotalPacked;\r
+    lps->OutSize = currentImportantTotalUnPacked;\r
+    RINOK(lps->SetCur());\r
+    CMyComPtr<ISequentialOutStream> realOutStream;\r
+\r
+    Int32 askMode;\r
+    if (extractStatuses[i])\r
+      askMode = testMode ?\r
+          NExtract::NAskMode::kTest :\r
+          NExtract::NAskMode::kExtract;\r
+    else\r
+      askMode = NExtract::NAskMode::kSkip;\r
+\r
+    UInt32 index = importantIndexes[i];\r
+\r
+    const CRefItem &refItem = _refItems[index];\r
+    const CItemEx &item = _items[refItem.ItemIndex];\r
+\r
+    currentUnPackSize = item.Size;\r
+\r
+    currentPackSize = GetPackSize(index);\r
+\r
+    if (item.IgnoreItem())\r
+      continue;\r
+\r
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+\r
+    if (!IsSolid(index))\r
+      solidStart = true;\r
+    if (item.IsDir())\r
+    {\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+      continue;\r
+    }\r
+\r
+    bool mustBeProcessedAnywhere = false;\r
+    if (i < importantIndexes.Size() - 1)\r
+    {\r
+      // const CRefItem &nextRefItem = _refItems[importantIndexes[i + 1]];\r
+      // const CItemEx &nextItemInfo = _items[nextRefItem.ItemIndex];\r
+      // mustBeProcessedAnywhere = nextItemInfo.IsSolid();\r
+      mustBeProcessedAnywhere = IsSolid(importantIndexes[i + 1]);\r
+    }\r
+    \r
+    if (!mustBeProcessedAnywhere && !testMode && !realOutStream)\r
+      continue;\r
+    \r
+    if (!realOutStream && !testMode)\r
+      askMode = NExtract::NAskMode::kSkip;\r
+\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+\r
+    COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;\r
+    CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\r
+    outStreamSpec->SetStream(realOutStream);\r
+    outStreamSpec->Init();\r
+    realOutStream.Release();\r
+    \r
+    /*\r
+    for (int partIndex = 0; partIndex < 1; partIndex++)\r
+    {\r
+    CMyComPtr<ISequentialInStream> inStream;\r
+\r
+    // item redefinition\r
+    const CItemEx &item = _items[refItem.ItemIndex + partIndex];\r
+\r
+    NArchive::NRar::CInArchive &archive = _archives[refItem.VolumeIndex + partIndex];\r
+\r
+    inStream.Attach(archive.CreateLimitedStream(item.GetDataPosition(),\r
+      item.PackSize));\r
+    */\r
+    if (!folderInStream)\r
+    {\r
+      folderInStreamSpec = new CFolderInStream;\r
+      folderInStream = folderInStreamSpec;\r
+    }\r
+\r
+    folderInStreamSpec->Init(&_archives, &_items, refItem);\r
+\r
+    UInt64 packSize = currentPackSize;\r
+\r
+    // packedPos += item.PackSize;\r
+    // unpackedPos += 0;\r
+    \r
+    CMyComPtr<ISequentialInStream> inStream;\r
+    if (item.IsEncrypted())\r
+    {\r
+      CMyComPtr<ICryptoSetPassword> cryptoSetPassword;\r
+      if (item.UnPackVersion >= 29)\r
+      {\r
+        if (!rar29CryptoDecoder)\r
+        {\r
+          rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder;\r
+          rar29CryptoDecoder = rar29CryptoDecoderSpec;\r
+          // RINOK(rar29CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar29Decoder));\r
+        }\r
+        rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);\r
+        CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties;\r
+        RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,\r
+            &cryptoProperties));\r
+        RINOK(cryptoProperties->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));\r
+        filterStreamSpec->Filter = rar29CryptoDecoder;\r
+      }\r
+      else if (item.UnPackVersion >= 20)\r
+      {\r
+        if (!rar20CryptoDecoder)\r
+        {\r
+          rar20CryptoDecoderSpec = new NCrypto::NRar20::CDecoder;\r
+          rar20CryptoDecoder = rar20CryptoDecoderSpec;\r
+          // RINOK(rar20CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar20Decoder));\r
+        }\r
+        filterStreamSpec->Filter = rar20CryptoDecoder;\r
+      }\r
+      else\r
+      {\r
+        outStream.Release();\r
+        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));\r
+        continue;\r
+      }\r
+      RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword,\r
+          &cryptoSetPassword));\r
+\r
+      if (!getTextPassword)\r
+        extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);\r
+      if (getTextPassword)\r
+      {\r
+        CMyComBSTR password;\r
+        RINOK(getTextPassword->CryptoGetTextPassword(&password));\r
+        if (item.UnPackVersion >= 29)\r
+        {\r
+          CByteBuffer buffer;\r
+          UString unicodePassword(password);\r
+          const UInt32 sizeInBytes = unicodePassword.Length() * 2;\r
+          buffer.SetCapacity(sizeInBytes);\r
+          for (int i = 0; i < unicodePassword.Length(); i++)\r
+          {\r
+            wchar_t c = unicodePassword[i];\r
+            ((Byte *)buffer)[i * 2] = (Byte)c;\r
+            ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);\r
+          }\r
+          RINOK(cryptoSetPassword->CryptoSetPassword(\r
+            (const Byte *)buffer, sizeInBytes));\r
+        }\r
+        else\r
+        {\r
+          AString oemPassword = UnicodeStringToMultiByte(\r
+            (const wchar_t *)password, CP_OEMCP);\r
+          RINOK(cryptoSetPassword->CryptoSetPassword(\r
+            (const Byte *)(const char *)oemPassword, oemPassword.Length()));\r
+        }\r
+      }\r
+      else\r
+      {\r
+        RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));\r
+      }\r
+      filterStreamSpec->SetInStream(folderInStream);\r
+      inStream = filterStream;\r
+    }\r
+    else\r
+    {\r
+      inStream = folderInStream;\r
+    }\r
+    CMyComPtr<ICompressCoder> commonCoder;\r
+    switch(item.Method)\r
+    {\r
+      case '0':\r
+      {\r
+        commonCoder = copyCoder;\r
+        break;\r
+      }\r
+      case '1':\r
+      case '2':\r
+      case '3':\r
+      case '4':\r
+      case '5':\r
+      {\r
+        /*\r
+        if (item.UnPackVersion >= 29)\r
+        {\r
+          outStream.Release();\r
+          RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));\r
+          continue;\r
+        }\r
+        */\r
+        int m;\r
+        for (m = 0; m < methodItems.Size(); m++)\r
+          if (methodItems[m].RarUnPackVersion == item.UnPackVersion)\r
+            break;\r
+        if (m == methodItems.Size())\r
+        {\r
+          CMethodItem mi;\r
+          mi.RarUnPackVersion = item.UnPackVersion;\r
+\r
+          mi.Coder.Release();\r
+          if (item.UnPackVersion <= 30)\r
+          {\r
+            UInt32 methodID = 0x040300;\r
+            if (item.UnPackVersion < 20)\r
+              methodID += 1;\r
+            else if (item.UnPackVersion < 29)\r
+              methodID += 2;\r
+            else\r
+              methodID += 3;\r
+            RINOK(CreateCoder(EXTERNAL_CODECS_VARS methodID, mi.Coder, false));\r
+          }\r
+         \r
+          if (mi.Coder == 0)\r
+          {\r
+            outStream.Release();\r
+            RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));\r
+            continue;\r
+          }\r
+\r
+          m = methodItems.Add(mi);\r
+        }\r
+        CMyComPtr<ICompressCoder> decoder = methodItems[m].Coder;\r
+\r
+        CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties;\r
+        RINOK(decoder.QueryInterface(IID_ICompressSetDecoderProperties2,\r
+            &compressSetDecoderProperties));\r
+        \r
+        Byte isSolid = (Byte)((IsSolid(index) || item.IsSplitBefore()) ? 1: 0);\r
+        if (solidStart)\r
+        {\r
+          isSolid = false;\r
+          solidStart = false;\r
+        }\r
+\r
+\r
+        RINOK(compressSetDecoderProperties->SetDecoderProperties2(&isSolid, 1));\r
+          \r
+        commonCoder = decoder;\r
+        break;\r
+      }\r
+      default:\r
+        outStream.Release();\r
+        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));\r
+        continue;\r
+    }\r
+    HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &item.Size, progress);\r
+    if (item.IsEncrypted())\r
+      filterStreamSpec->ReleaseInStream();\r
+    if (result == S_FALSE)\r
+    {\r
+      outStream.Release();\r
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError));\r
+      continue;\r
+    }\r
+    if (result != S_OK)\r
+      return result;\r
+\r
+    /*\r
+    if (refItem.NumItems == 1 &&\r
+        !item.IsSplitBefore() && !item.IsSplitAfter())\r
+    */\r
+    {\r
+      const CItemEx &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];\r
+      bool crcOK = outStreamSpec->GetCRC() == lastItem.FileCRC;\r
+      outStream.Release();\r
+      RINOK(extractCallback->SetOperationResult(crcOK ?\r
+          NExtract::NOperationResult::kOK:\r
+          NExtract::NOperationResult::kCRCError));\r
+    }\r
+    /*\r
+    else\r
+    {\r
+      bool crcOK = true;\r
+      for (int partIndex = 0; partIndex < refItem.NumItems; partIndex++)\r
+      {\r
+        const CItemEx &item = _items[refItem.ItemIndex + partIndex];\r
+        if (item.FileCRC != folderInStreamSpec->CRCs[partIndex])\r
+        {\r
+          crcOK = false;\r
+          break;\r
+        }\r
+      }\r
+      RINOK(extractCallback->SetOperationResult(crcOK ?\r
+          NExtract::NOperationResult::kOK:\r
+          NExtract::NOperationResult::kCRCError));\r
+    }\r
+    */\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+IMPL_ISetCompressCodecsInfo\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Rar/RarHandler.h b/CPP/7zip/Archive/Rar/RarHandler.h
new file mode 100755 (executable)
index 0000000..3d43874
--- /dev/null
@@ -0,0 +1,66 @@
+// Rar/Handler.h\r
+\r
+#ifndef __RAR_HANDLER_H\r
+#define __RAR_HANDLER_H\r
+\r
+#include "../IArchive.h"\r
+\r
+#include "../../Common/CreateCoder.h"\r
+\r
+#include "RarIn.h"\r
+#include "RarVolumeInStream.h"\r
+\r
+namespace NArchive {\r
+namespace NRar {\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  PUBLIC_ISetCompressCodecsInfo\r
+  public CMyUnknownImp\r
+{\r
+  CRecordVector<CRefItem> _refItems;\r
+  CObjectVector<CItemEx> _items;\r
+  CObjectVector<CInArchive> _archives;\r
+  NArchive::NRar::CInArchiveInfo _archiveInfo;\r
+  AString _errorMessage;\r
+\r
+  DECL_EXTERNAL_CODECS_VARS\r
+\r
+  UInt64 GetPackSize(int refIndex) const;\r
+\r
+  bool IsSolid(int refIndex)\r
+  {\r
+    const CItemEx &item = _items[_refItems[refIndex].ItemIndex];\r
+    if (item.UnPackVersion < 20)\r
+    {\r
+      if (_archiveInfo.IsSolid())\r
+        return (refIndex > 0);\r
+      return false;\r
+    }\r
+    return item.IsSolid();\r
+  }\r
+  void AddErrorMessage(const AString &s)\r
+  {\r
+    if (!_errorMessage.IsEmpty())\r
+      _errorMessage += '\n';\r
+    _errorMessage += s;\r
+  }\r
+\r
+  HRESULT Open2(IInStream *stream,\r
+      const UInt64 *maxCheckStartPosition,\r
+      IArchiveOpenCallback *openCallback);\r
+\r
+public:\r
+  MY_QUERYINTERFACE_BEGIN2(IInArchive)\r
+  QUERY_ENTRY_ISetCompressCodecsInfo\r
+  MY_QUERYINTERFACE_END\r
+  MY_ADDREF_RELEASE\r
+  \r
+  INTERFACE_IInArchive(;)\r
+\r
+  DECL_ISetCompressCodecsInfo\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Rar/RarHeader.cpp b/CPP/7zip/Archive/Rar/RarHeader.cpp
new file mode 100755 (executable)
index 0000000..7c34875
--- /dev/null
@@ -0,0 +1,21 @@
+// Archive/Rar/Headers.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "RarHeader.h"\r
+\r
+namespace NArchive{\r
+namespace NRar{\r
+namespace NHeader{\r
+\r
+Byte kMarker[kMarkerSize] = {0x52 + 1, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00};\r
+  \r
+class CMarkerInitializer\r
+{\r
+public:\r
+  CMarkerInitializer() { kMarker[0]--; };\r
+};\r
+\r
+static CMarkerInitializer markerInitializer;\r
+\r
+}}}\r
diff --git a/CPP/7zip/Archive/Rar/RarHeader.h b/CPP/7zip/Archive/Rar/RarHeader.h
new file mode 100755 (executable)
index 0000000..6624d84
--- /dev/null
@@ -0,0 +1,205 @@
+// Archive/RarHeader.h\r
+\r
+#ifndef __ARCHIVE_RAR_HEADER_H\r
+#define __ARCHIVE_RAR_HEADER_H\r
+\r
+#include "Common/Types.h"\r
+\r
+namespace NArchive {\r
+namespace NRar {\r
+namespace NHeader {\r
+\r
+const int kMarkerSize = 7;\r
+extern Byte kMarker[kMarkerSize];\r
+  \r
+const int kArchiveSolid = 0x1;\r
+\r
+namespace NBlockType\r
+{\r
+  enum EBlockType\r
+  {\r
+    kMarker = 0x72,\r
+    kArchiveHeader,\r
+    kFileHeader,\r
+    kCommentHeader,\r
+    kOldAuthenticity,\r
+    kOldSubBlock,\r
+    kRecoveryRecord,\r
+    kAuthenticity,\r
+    kSubBlock,\r
+    kEndOfArchive\r
+  };\r
+}\r
+\r
+namespace NArchive\r
+{\r
+  const UInt16 kVolume  = 1;\r
+  const UInt16 kComment = 2;\r
+  const UInt16 kLock    = 4;\r
+  const UInt16 kSolid   = 8;\r
+  const UInt16 kNewVolName = 0x10; // ('volname.partN.rar')\r
+  const UInt16 kAuthenticity  = 0x20;\r
+  const UInt16 kRecovery = 0x40;\r
+  const UInt16 kBlockEncryption  = 0x80;\r
+  const UInt16 kFirstVolume = 0x100; // (set only by RAR 3.0 and later)\r
+  const UInt16 kEncryptVer = 0x200; // RAR 3.6 there is EncryptVer Byte in End of MainHeader\r
+\r
+  const int kHeaderSizeMin = 7;\r
+  \r
+  const int kArchiveHeaderSize = 13;\r
+\r
+  const int kBlockHeadersAreEncrypted = 0x80;\r
+\r
+}\r
+\r
+namespace NFile\r
+{\r
+  const int kSplitBefore = 1 << 0;\r
+  const int kSplitAfter  = 1 << 1;\r
+  const int kEncrypted   = 1 << 2;\r
+  const int kComment     = 1 << 3;\r
+  const int kSolid       = 1 << 4;\r
+  \r
+  const int kDictBitStart     = 5;\r
+  const int kNumDictBits  = 3;\r
+  const int kDictMask         = (1 << kNumDictBits) - 1;\r
+  const int kDictDirectoryValue  = 0x7;\r
+  \r
+  const int kSize64Bits    = 1 << 8;\r
+  const int kUnicodeName   = 1 << 9;\r
+  const int kSalt          = 1 << 10;\r
+  const int kOldVersion    = 1 << 11;\r
+  const int kExtTime       = 1 << 12;\r
+  // const int kExtFlags      = 1 << 13;\r
+  // const int kSkipIfUnknown = 1 << 14;\r
+\r
+  const int kLongBlock    = 1 << 15;\r
+  \r
+  /*\r
+  struct CBlock\r
+  {\r
+    // UInt16 HeadCRC;\r
+    // Byte Type;\r
+    // UInt16 Flags;\r
+    // UInt16 HeadSize;\r
+    UInt32 PackSize;\r
+    UInt32 UnPackSize;\r
+    Byte HostOS;\r
+    UInt32 FileCRC;\r
+    UInt32 Time;\r
+    Byte UnPackVersion;\r
+    Byte Method;\r
+    UInt16 NameSize;\r
+    UInt32 Attributes;\r
+  };\r
+  */\r
+\r
+  /*\r
+  struct CBlock32\r
+  {\r
+    UInt16 HeadCRC;\r
+    Byte Type;\r
+    UInt16 Flags;\r
+    UInt16 HeadSize;\r
+    UInt32 PackSize;\r
+    UInt32 UnPackSize;\r
+    Byte HostOS;\r
+    UInt32 FileCRC;\r
+    UInt32 Time;\r
+    Byte UnPackVersion;\r
+    Byte Method;\r
+    UInt16 NameSize;\r
+    UInt32 Attributes;\r
+    UInt16 GetRealCRC(const void *aName, UInt32 aNameSize,\r
+        bool anExtraDataDefined = false, Byte *anExtraData = 0) const;\r
+  };\r
+  struct CBlock64\r
+  {\r
+    UInt16 HeadCRC;\r
+    Byte Type;\r
+    UInt16 Flags;\r
+    UInt16 HeadSize;\r
+    UInt32 PackSizeLow;\r
+    UInt32 UnPackSizeLow;\r
+    Byte HostOS;\r
+    UInt32 FileCRC;\r
+    UInt32 Time;\r
+    Byte UnPackVersion;\r
+    Byte Method;\r
+    UInt16 NameSize;\r
+    UInt32 Attributes;\r
+    UInt32 PackSizeHigh;\r
+    UInt32 UnPackSizeHigh;\r
+    UInt16 GetRealCRC(const void *aName, UInt32 aNameSize) const;\r
+  };\r
+  */\r
+  \r
+  const int kLabelFileAttribute            = 0x08;\r
+  const int kWinFileDirectoryAttributeMask = 0x10;\r
+  \r
+  enum CHostOS\r
+  {\r
+    kHostMSDOS = 0,\r
+      kHostOS2   = 1,\r
+      kHostWin32 = 2,\r
+      kHostUnix  = 3,\r
+      kHostMacOS = 4,\r
+      kHostBeOS = 5\r
+  };\r
+}\r
+\r
+namespace NBlock\r
+{\r
+  const UInt16 kLongBlock = 1 << 15;\r
+  struct CBlock\r
+  {\r
+    UInt16 CRC;\r
+    Byte Type;\r
+    UInt16 Flags;\r
+    UInt16 HeadSize;\r
+    //  UInt32 DataSize;\r
+  };\r
+}\r
+\r
+/*\r
+struct CSubBlock\r
+{\r
+  UInt16 HeadCRC;\r
+  Byte HeadType;\r
+  UInt16 Flags;\r
+  UInt16 HeadSize;\r
+  UInt32 DataSize;\r
+  UInt16 SubType;\r
+  Byte Level; // Reserved : Must be 0\r
+};\r
+\r
+struct CCommentBlock\r
+{\r
+  UInt16 HeadCRC;\r
+  Byte HeadType;\r
+  UInt16 Flags;\r
+  UInt16 HeadSize;\r
+  UInt16 UnpSize;\r
+  Byte UnpVer;\r
+  Byte Method;\r
+  UInt16 CommCRC;\r
+};\r
+\r
+\r
+struct CProtectHeader\r
+{\r
+  UInt16 HeadCRC;\r
+  Byte HeadType;\r
+  UInt16 Flags;\r
+  UInt16 HeadSize;\r
+  UInt32 DataSize;\r
+  Byte Version;\r
+  UInt16 RecSectors;\r
+  UInt32 TotalBlocks;\r
+  Byte Mark[8];\r
+};\r
+*/\r
+\r
+}}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Rar/RarIn.cpp b/CPP/7zip/Archive/Rar/RarIn.cpp
new file mode 100755 (executable)
index 0000000..c277fe2
--- /dev/null
@@ -0,0 +1,478 @@
+// Archive/RarIn.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/7zCrc.h"\r
+#include "../../../../C/CpuArch.h"\r
+\r
+#include "Common/StringConvert.h"\r
+#include "Common/UTFConvert.h"\r
+\r
+#include "../../Common/LimitedStreams.h"\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "../Common/FindSignature.h"\r
+\r
+#include "RarIn.h"\r
+\r
+#define Get16(p) GetUi16(p)\r
+#define Get32(p) GetUi32(p)\r
+#define Get64(p) GetUi64(p)\r
+\r
+namespace NArchive {\r
+namespace NRar {\r
+\r
+static const char *k_UnexpectedEnd = "Unexpected end of archive";\r
+static const char *k_DecryptionError = "Decryption Error";\r
+\r
+void CInArchive::ThrowExceptionWithCode(\r
+    CInArchiveException::CCauseType cause)\r
+{\r
+  throw CInArchiveException(cause);\r
+}\r
+\r
+HRESULT CInArchive::Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit)\r
+{\r
+  try\r
+  {\r
+    Close();\r
+    HRESULT res = Open2(inStream, searchHeaderSizeLimit);\r
+    if (res == S_OK)\r
+      return res;\r
+    Close();\r
+    return res;\r
+  }\r
+  catch(...) { Close(); throw; }\r
+}\r
+\r
+void CInArchive::Close()\r
+{\r
+  m_Stream.Release();\r
+}\r
+\r
+HRESULT CInArchive::ReadBytesSpec(void *data, size_t *resSize)\r
+{\r
+  if (m_CryptoMode)\r
+  {\r
+    size_t size = *resSize;\r
+    *resSize = 0;\r
+    const Byte *bufData = m_DecryptedDataAligned;\r
+    UInt32 bufSize = m_DecryptedDataSize;\r
+    size_t i;\r
+    for (i = 0; i < size && m_CryptoPos < bufSize; i++)\r
+      ((Byte *)data)[i] = bufData[m_CryptoPos++];\r
+    *resSize = i;\r
+    return S_OK;\r
+  }\r
+  return ReadStream(m_Stream, data, resSize);\r
+}\r
+\r
+bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size)\r
+{\r
+  size_t processed = size;\r
+  if (ReadBytesSpec(data, &processed) != S_OK)\r
+    return false;\r
+  return processed == size;\r
+}\r
+\r
+HRESULT CInArchive::Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit)\r
+{\r
+  m_CryptoMode = false;\r
+  RINOK(stream->Seek(0, STREAM_SEEK_SET, &m_StreamStartPosition));\r
+  m_Position = m_StreamStartPosition;\r
+\r
+  UInt64 arcStartPos;\r
+  RINOK(FindSignatureInStream(stream, NHeader::kMarker, NHeader::kMarkerSize,\r
+      searchHeaderSizeLimit, arcStartPos));\r
+  m_Position = arcStartPos + NHeader::kMarkerSize;\r
+  RINOK(stream->Seek(m_Position, STREAM_SEEK_SET, NULL));\r
+  Byte buf[NHeader::NArchive::kArchiveHeaderSize + 1];\r
+\r
+  RINOK(ReadStream_FALSE(stream, buf, NHeader::NArchive::kArchiveHeaderSize));\r
+  AddToSeekValue(NHeader::NArchive::kArchiveHeaderSize);\r
+\r
+\r
+  UInt32 blockSize = Get16(buf + 5);\r
+\r
+  _header.EncryptVersion = 0;\r
+  _header.Flags = Get16(buf + 3);\r
+\r
+  UInt32 headerSize = NHeader::NArchive::kArchiveHeaderSize;\r
+  if (_header.IsThereEncryptVer())\r
+  {\r
+    if (blockSize <= headerSize)\r
+      return S_FALSE;\r
+    RINOK(ReadStream_FALSE(stream, buf + NHeader::NArchive::kArchiveHeaderSize, 1));\r
+    AddToSeekValue(1);\r
+    _header.EncryptVersion = buf[NHeader::NArchive::kArchiveHeaderSize];\r
+    headerSize += 1;\r
+  }\r
+  if (blockSize < headerSize ||\r
+      buf[2] != NHeader::NBlockType::kArchiveHeader ||\r
+      (UInt32)Get16(buf) != (CrcCalc(buf + 2, headerSize - 2) & 0xFFFF))\r
+    return S_FALSE;\r
+\r
+  size_t commentSize = blockSize - headerSize; \r
+  _comment.SetCapacity(commentSize);\r
+  RINOK(ReadStream_FALSE(stream, _comment, commentSize));\r
+  AddToSeekValue(commentSize);\r
+  m_Stream = stream;\r
+  _header.StartPosition = arcStartPos;\r
+  return S_OK;\r
+}\r
+\r
+void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const\r
+{\r
+  archiveInfo = _header;\r
+}\r
+\r
+static void DecodeUnicodeFileName(const char *name, const Byte *encName,\r
+    int encSize, wchar_t *unicodeName, int maxDecSize)\r
+{\r
+  int encPos = 0;\r
+  int decPos = 0;\r
+  int flagBits = 0;\r
+  Byte flags = 0;\r
+  Byte highByte = encName[encPos++];\r
+  while (encPos < encSize && decPos < maxDecSize)\r
+  {\r
+    if (flagBits == 0)\r
+    {\r
+      flags = encName[encPos++];\r
+      flagBits = 8;\r
+    }\r
+    switch(flags >> 6)\r
+    {\r
+      case 0:\r
+        unicodeName[decPos++] = encName[encPos++];\r
+        break;\r
+      case 1:\r
+        unicodeName[decPos++] = (wchar_t)(encName[encPos++] + (highByte << 8));\r
+        break;\r
+      case 2:\r
+        unicodeName[decPos++] = (wchar_t)(encName[encPos] + (encName[encPos + 1] << 8));\r
+        encPos += 2;\r
+        break;\r
+      case 3:\r
+        {\r
+          int length = encName[encPos++];\r
+          if (length & 0x80)\r
+          {\r
+            Byte correction = encName[encPos++];\r
+            for (length = (length & 0x7f) + 2;\r
+                length > 0 && decPos < maxDecSize; length--, decPos++)\r
+              unicodeName[decPos] = (wchar_t)(((name[decPos] + correction) & 0xff) + (highByte << 8));\r
+          }\r
+          else\r
+            for (length += 2; length > 0 && decPos < maxDecSize; length--, decPos++)\r
+              unicodeName[decPos] = name[decPos];\r
+        }\r
+        break;\r
+    }\r
+    flags <<= 2;\r
+    flagBits -= 2;\r
+  }\r
+  unicodeName[decPos < maxDecSize ? decPos : maxDecSize - 1] = 0;\r
+}\r
+\r
+void CInArchive::ReadName(CItemEx &item, int nameSize)\r
+{\r
+  item.UnicodeName.Empty();\r
+  if (nameSize > 0)\r
+  {\r
+    m_NameBuffer.EnsureCapacity(nameSize + 1);\r
+    char *buffer = (char *)m_NameBuffer;\r
+\r
+    for (int i = 0; i < nameSize; i++)\r
+      buffer[i] = ReadByte();\r
+\r
+    int mainLen;\r
+    for (mainLen = 0; mainLen < nameSize; mainLen++)\r
+      if (buffer[mainLen] == '\0')\r
+        break;\r
+    buffer[mainLen] = '\0';\r
+    item.Name = buffer;\r
+\r
+    if(item.HasUnicodeName())\r
+    {\r
+      if(mainLen < nameSize)\r
+      {\r
+        int unicodeNameSizeMax = MyMin(nameSize, (0x400));\r
+        _unicodeNameBuffer.EnsureCapacity(unicodeNameSizeMax + 1);\r
+        DecodeUnicodeFileName(buffer, (const Byte *)buffer + mainLen + 1,\r
+            nameSize - (mainLen + 1), _unicodeNameBuffer, unicodeNameSizeMax);\r
+        item.UnicodeName = _unicodeNameBuffer;\r
+      }\r
+      else if (!ConvertUTF8ToUnicode(item.Name, item.UnicodeName))\r
+        item.UnicodeName.Empty();\r
+    }\r
+  }\r
+  else\r
+    item.Name.Empty();\r
+}\r
+\r
+Byte CInArchive::ReadByte()\r
+{\r
+  if (m_CurPos >= m_PosLimit)\r
+    throw CInArchiveException(CInArchiveException::kIncorrectArchive);\r
+  return m_CurData[m_CurPos++];\r
+}\r
+\r
+UInt16 CInArchive::ReadUInt16()\r
+{\r
+  UInt16 value = 0;\r
+  for (int i = 0; i < 2; i++)\r
+  {\r
+    Byte b = ReadByte();\r
+    value |= (UInt16(b) << (8 * i));\r
+  }\r
+  return value;\r
+}\r
+\r
+UInt32 CInArchive::ReadUInt32()\r
+{\r
+  UInt32 value = 0;\r
+  for (int i = 0; i < 4; i++)\r
+  {\r
+    Byte b = ReadByte();\r
+    value |= (UInt32(b) << (8 * i));\r
+  }\r
+  return value;\r
+}\r
+\r
+void CInArchive::ReadTime(Byte mask, CRarTime &rarTime)\r
+{\r
+  rarTime.LowSecond = (Byte)(((mask & 4) != 0) ? 1 : 0);\r
+  int numDigits = (mask & 3);\r
+  rarTime.SubTime[0] = rarTime.SubTime[1] = rarTime.SubTime[2] = 0;\r
+  for (int i = 0; i < numDigits; i++)\r
+    rarTime.SubTime[3 - numDigits + i] = ReadByte();\r
+}\r
+\r
+void CInArchive::ReadHeaderReal(CItemEx &item)\r
+{\r
+  item.Flags = m_BlockHeader.Flags;\r
+  item.PackSize = ReadUInt32();\r
+  item.Size = ReadUInt32();\r
+  item.HostOS = ReadByte();\r
+  item.FileCRC = ReadUInt32();\r
+  item.MTime.DosTime = ReadUInt32();\r
+  item.UnPackVersion = ReadByte();\r
+  item.Method = ReadByte();\r
+  int nameSize = ReadUInt16();\r
+  item.Attrib = ReadUInt32();\r
+\r
+  item.MTime.LowSecond = 0;\r
+  item.MTime.SubTime[0] =\r
+      item.MTime.SubTime[1] =\r
+      item.MTime.SubTime[2] = 0;\r
+\r
+  if((item.Flags & NHeader::NFile::kSize64Bits) != 0)\r
+  {\r
+    item.PackSize |= ((UInt64)ReadUInt32() << 32);\r
+    item.Size |= ((UInt64)ReadUInt32() << 32);\r
+  }\r
+\r
+  ReadName(item, nameSize);\r
+\r
+  if (item.HasSalt())\r
+    for (int i = 0; i < sizeof(item.Salt); i++)\r
+      item.Salt[i] = ReadByte();\r
+\r
+  // some rar archives have HasExtTime flag without field.\r
+  if (m_CurPos < m_PosLimit && item.HasExtTime())\r
+  {\r
+    Byte accessMask = (Byte)(ReadByte() >> 4);\r
+    Byte b = ReadByte();\r
+    Byte modifMask = (Byte)(b >> 4);\r
+    Byte createMask = (Byte)(b & 0xF);\r
+    if ((modifMask & 8) != 0)\r
+      ReadTime(modifMask, item.MTime);\r
+    item.CTimeDefined = ((createMask & 8) != 0);\r
+    if (item.CTimeDefined)\r
+    {\r
+      item.CTime.DosTime = ReadUInt32();\r
+      ReadTime(createMask, item.CTime);\r
+    }\r
+    item.ATimeDefined = ((accessMask & 8) != 0);\r
+    if (item.ATimeDefined)\r
+    {\r
+      item.ATime.DosTime = ReadUInt32();\r
+      ReadTime(accessMask, item.ATime);\r
+    }\r
+  }\r
+\r
+  UInt16 fileHeaderWithNameSize = (UInt16)m_CurPos;\r
+  \r
+  item.Position = m_Position;\r
+  item.MainPartSize = fileHeaderWithNameSize;\r
+  item.CommentSize = (UInt16)(m_BlockHeader.HeadSize - fileHeaderWithNameSize);\r
+\r
+  if (m_CryptoMode)\r
+    item.AlignSize = (UInt16)((16 - ((m_BlockHeader.HeadSize) & 0xF)) & 0xF);\r
+  else\r
+    item.AlignSize = 0;\r
+  AddToSeekValue(m_BlockHeader.HeadSize);\r
+}\r
+\r
+void CInArchive::AddToSeekValue(UInt64 addValue)\r
+{\r
+  m_Position += addValue;\r
+}\r
+\r
+HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError, AString &errorMessage)\r
+{\r
+  decryptionError = false;\r
+  for (;;)\r
+  {\r
+    SeekInArchive(m_Position);\r
+    if (!m_CryptoMode && (_header.Flags &\r
+        NHeader::NArchive::kBlockHeadersAreEncrypted) != 0)\r
+    {\r
+      m_CryptoMode = false;\r
+      if (getTextPassword == 0)\r
+        return S_FALSE;\r
+      if (!m_RarAES)\r
+      {\r
+        m_RarAESSpec = new NCrypto::NRar29::CDecoder;\r
+        m_RarAES = m_RarAESSpec;\r
+      }\r
+      m_RarAESSpec->SetRar350Mode(_header.IsEncryptOld());\r
+\r
+      // Salt\r
+      const UInt32 kSaltSize = 8;\r
+      Byte salt[kSaltSize];\r
+      if(!ReadBytesAndTestSize(salt, kSaltSize))\r
+        return S_FALSE;\r
+      m_Position += kSaltSize;\r
+      RINOK(m_RarAESSpec->SetDecoderProperties2(salt, kSaltSize))\r
+      // Password\r
+      CMyComBSTR password;\r
+      RINOK(getTextPassword->CryptoGetTextPassword(&password))\r
+      UString unicodePassword(password);\r
+\r
+      CByteBuffer buffer;\r
+      const UInt32 sizeInBytes = unicodePassword.Length() * 2;\r
+      buffer.SetCapacity(sizeInBytes);\r
+      for (int i = 0; i < unicodePassword.Length(); i++)\r
+      {\r
+        wchar_t c = unicodePassword[i];\r
+        ((Byte *)buffer)[i * 2] = (Byte)c;\r
+        ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);\r
+      }\r
+\r
+      RINOK(m_RarAESSpec->CryptoSetPassword((const Byte *)buffer, sizeInBytes));\r
+\r
+      const UInt32 kDecryptedBufferSize = (1 << 12);\r
+      if (m_DecryptedData.GetCapacity() == 0)\r
+      {\r
+        const UInt32 kAlign = 16;\r
+        m_DecryptedData.SetCapacity(kDecryptedBufferSize + kAlign);\r
+        m_DecryptedDataAligned = (Byte *)((ptrdiff_t)((Byte *)m_DecryptedData + kAlign - 1) & ~(ptrdiff_t)(kAlign - 1));\r
+      }\r
+      RINOK(m_RarAES->Init());\r
+      size_t decryptedDataSizeT = kDecryptedBufferSize;\r
+      RINOK(ReadStream(m_Stream, m_DecryptedDataAligned, &decryptedDataSizeT));\r
+      m_DecryptedDataSize = (UInt32)decryptedDataSizeT;\r
+      m_DecryptedDataSize = m_RarAES->Filter(m_DecryptedDataAligned, m_DecryptedDataSize);\r
+\r
+      m_CryptoMode = true;\r
+      m_CryptoPos = 0;\r
+    }\r
+\r
+    m_FileHeaderData.EnsureCapacity(7);\r
+    size_t processed = 7;\r
+    RINOK(ReadBytesSpec((Byte *)m_FileHeaderData, &processed));\r
+    if (processed != 7)\r
+    {\r
+      if (processed != 0)\r
+        errorMessage = k_UnexpectedEnd;\r
+      return S_FALSE;\r
+    }\r
+\r
+    m_CurData = (Byte *)m_FileHeaderData;\r
+    m_CurPos = 0;\r
+    m_PosLimit = 7;\r
+    m_BlockHeader.CRC = ReadUInt16();\r
+    m_BlockHeader.Type = ReadByte();\r
+    m_BlockHeader.Flags = ReadUInt16();\r
+    m_BlockHeader.HeadSize = ReadUInt16();\r
+\r
+    if (m_BlockHeader.HeadSize < 7)\r
+      ThrowExceptionWithCode(CInArchiveException::kIncorrectArchive);\r
+\r
+    if (m_BlockHeader.Type == NHeader::NBlockType::kEndOfArchive)\r
+      return S_FALSE;\r
+\r
+    if (m_BlockHeader.Type == NHeader::NBlockType::kFileHeader)\r
+    {\r
+      m_FileHeaderData.EnsureCapacity(m_BlockHeader.HeadSize);\r
+      m_CurData = (Byte *)m_FileHeaderData;\r
+      m_PosLimit = m_BlockHeader.HeadSize;\r
+      if (!ReadBytesAndTestSize(m_CurData + m_CurPos, m_BlockHeader.HeadSize - 7))\r
+      {\r
+        errorMessage = k_UnexpectedEnd;\r
+        return S_FALSE;\r
+      }\r
+\r
+      ReadHeaderReal(item);\r
+      if ((CrcCalc(m_CurData + 2,\r
+          m_BlockHeader.HeadSize - item.CommentSize - 2) & 0xFFFF) != m_BlockHeader.CRC)\r
+        ThrowExceptionWithCode(CInArchiveException::kFileHeaderCRCError);\r
+\r
+      FinishCryptoBlock();\r
+      m_CryptoMode = false;\r
+      SeekInArchive(m_Position); // Move Position to compressed Data;\r
+      AddToSeekValue(item.PackSize);  // m_Position points to next header;\r
+      return S_OK;\r
+    }\r
+    if (m_CryptoMode && m_BlockHeader.HeadSize > (1 << 10))\r
+    {\r
+      decryptionError = true;\r
+      errorMessage = k_DecryptionError;\r
+      return S_FALSE;\r
+    }\r
+    if ((m_BlockHeader.Flags & NHeader::NBlock::kLongBlock) != 0)\r
+    {\r
+      m_FileHeaderData.EnsureCapacity(7 + 4);\r
+      m_CurData = (Byte *)m_FileHeaderData;\r
+      if (!ReadBytesAndTestSize(m_CurData + m_CurPos, 4))\r
+      {\r
+        errorMessage = k_UnexpectedEnd;\r
+        return S_FALSE;\r
+      }\r
+      m_PosLimit = 7 + 4;\r
+      UInt32 dataSize = ReadUInt32();\r
+      AddToSeekValue(dataSize);\r
+      if (m_CryptoMode && dataSize > (1 << 27))\r
+      {\r
+        decryptionError = true;\r
+        errorMessage = k_DecryptionError;\r
+        return S_FALSE;\r
+      }\r
+      m_CryptoPos = m_BlockHeader.HeadSize;\r
+    }\r
+    else\r
+      m_CryptoPos = 0;\r
+    AddToSeekValue(m_BlockHeader.HeadSize);\r
+    FinishCryptoBlock();\r
+    m_CryptoMode = false;\r
+  }\r
+}\r
+\r
+void CInArchive::SeekInArchive(UInt64 position)\r
+{\r
+  m_Stream->Seek(position, STREAM_SEEK_SET, NULL);\r
+}\r
+\r
+ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size)\r
+{\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);\r
+  SeekInArchive(position);\r
+  streamSpec->SetStream(m_Stream);\r
+  streamSpec->Init(size);\r
+  return inStream.Detach();\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Rar/RarIn.h b/CPP/7zip/Archive/Rar/RarIn.h
new file mode 100755 (executable)
index 0000000..4ab3269
--- /dev/null
@@ -0,0 +1,123 @@
+// RarIn.h\r
+\r
+#ifndef __ARCHIVE_RAR_IN_H\r
+#define __ARCHIVE_RAR_IN_H\r
+\r
+#include "Common/DynamicBuffer.h"\r
+#include "Common/MyCom.h"\r
+\r
+#include "../../ICoder.h"\r
+#include "../../IStream.h"\r
+\r
+#include "../../Common/StreamObjects.h"\r
+\r
+#include "../../Crypto/RarAes.h"\r
+\r
+#include "RarHeader.h"\r
+#include "RarItem.h"\r
+\r
+namespace NArchive {\r
+namespace NRar {\r
+\r
+class CInArchiveException\r
+{\r
+public:\r
+  enum CCauseType\r
+  {\r
+    kUnexpectedEndOfArchive = 0,\r
+    kArchiveHeaderCRCError,\r
+    kFileHeaderCRCError,\r
+    kIncorrectArchive\r
+  }\r
+  Cause;\r
+  CInArchiveException(CCauseType cause) :   Cause(cause) {}\r
+};\r
+\r
+\r
+struct CInArchiveInfo\r
+{\r
+  UInt32 Flags;\r
+  Byte EncryptVersion;\r
+  UInt64 StartPosition;\r
+  \r
+  bool IsSolid() const { return (Flags & NHeader::NArchive::kSolid) != 0; }\r
+  bool IsCommented() const {  return (Flags & NHeader::NArchive::kComment) != 0; }\r
+  bool IsVolume() const {  return (Flags & NHeader::NArchive::kVolume) != 0; }\r
+  bool HaveNewVolumeName() const {  return (Flags & NHeader::NArchive::kNewVolName) != 0; }\r
+  bool IsEncrypted() const { return (Flags & NHeader::NArchive::kBlockEncryption) != 0; }\r
+  bool IsThereEncryptVer() const { return (Flags & NHeader::NArchive::kEncryptVer) != 0; }\r
+  bool IsEncryptOld() const { return (!IsThereEncryptVer() || EncryptVersion < 36); }\r
+};\r
+\r
+class CInArchive\r
+{\r
+  CMyComPtr<IInStream> m_Stream;\r
+  \r
+  UInt64 m_StreamStartPosition;\r
+  \r
+  CInArchiveInfo _header;\r
+  CDynamicBuffer<char> m_NameBuffer;\r
+  CDynamicBuffer<wchar_t> _unicodeNameBuffer;\r
+\r
+  CByteBuffer _comment;\r
+  \r
+  void ReadName(CItemEx &item, int nameSize);\r
+  void ReadHeaderReal(CItemEx &item);\r
+  \r
+  HRESULT ReadBytesSpec(void *data, size_t *size);\r
+  bool ReadBytesAndTestSize(void *data, UInt32 size);\r
+  \r
+  HRESULT Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit);\r
+\r
+  void ThrowExceptionWithCode(CInArchiveException::CCauseType cause);\r
+  void ThrowUnexpectedEndOfArchiveException();\r
+  \r
+  void AddToSeekValue(UInt64 addValue);\r
+  \r
+  CDynamicBuffer<Byte> m_FileHeaderData;\r
+  \r
+  NHeader::NBlock::CBlock m_BlockHeader;\r
+\r
+  NCrypto::NRar29::CDecoder *m_RarAESSpec;\r
+  CMyComPtr<ICompressFilter> m_RarAES;\r
+  \r
+  Byte *m_CurData; // it must point to start of Rar::Block\r
+  UInt32 m_CurPos;\r
+  UInt32 m_PosLimit;\r
+  Byte ReadByte();\r
+  UInt16 ReadUInt16();\r
+  UInt32 ReadUInt32();\r
+  void ReadTime(Byte mask, CRarTime &rarTime);\r
+\r
+  CBuffer<Byte> m_DecryptedData;\r
+  Byte *m_DecryptedDataAligned;\r
+  UInt32 m_DecryptedDataSize;\r
+\r
+  bool m_CryptoMode;\r
+  UInt32 m_CryptoPos;\r
+  void FinishCryptoBlock()\r
+  {\r
+    if (m_CryptoMode)\r
+      while ((m_CryptoPos & 0xF) != 0)\r
+      {\r
+        m_CryptoPos++;\r
+        m_Position++;\r
+      }\r
+  }\r
+\r
+public:\r
+  UInt64 m_Position;\r
+\r
+  HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit);\r
+  void Close();\r
+  HRESULT GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError, AString &errorMessage);\r
+  \r
+  void GetArchiveInfo(CInArchiveInfo &archiveInfo) const;\r
+  \r
+  void SeekInArchive(UInt64 position);\r
+  ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size);\r
+};\r
+  \r
+}}\r
+  \r
+#endif\r
diff --git a/CPP/7zip/Archive/Rar/RarItem.cpp b/CPP/7zip/Archive/Rar/RarItem.cpp
new file mode 100755 (executable)
index 0000000..b096377
--- /dev/null
@@ -0,0 +1,55 @@
+// RarItem.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "RarItem.h"\r
+\r
+namespace NArchive{\r
+namespace NRar{\r
+\r
+bool CItem::IgnoreItem() const\r
+{\r
+  switch(HostOS)\r
+  {\r
+    case NHeader::NFile::kHostMSDOS:\r
+    case NHeader::NFile::kHostOS2:\r
+    case NHeader::NFile::kHostWin32:\r
+      return ((Attrib & NHeader::NFile::kLabelFileAttribute) != 0);\r
+  }\r
+  return false;\r
+}\r
+\r
+bool CItem::IsDir() const\r
+{\r
+  if (GetDictSize() == NHeader::NFile::kDictDirectoryValue)\r
+    return true;\r
+  switch(HostOS)\r
+  {\r
+    case NHeader::NFile::kHostMSDOS:\r
+    case NHeader::NFile::kHostOS2:\r
+    case NHeader::NFile::kHostWin32:\r
+      if ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)\r
+        return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+UInt32 CItem::GetWinAttributes() const\r
+{\r
+  UInt32 winAttributes;\r
+  switch(HostOS)\r
+  {\r
+    case NHeader::NFile::kHostMSDOS:\r
+    case NHeader::NFile::kHostOS2:\r
+    case NHeader::NFile::kHostWin32:\r
+      winAttributes = Attrib;\r
+      break;\r
+    default:\r
+      winAttributes = 0; // must be converted from unix value;\r
+  }\r
+  if (IsDir())\r
+    winAttributes |= NHeader::NFile::kWinFileDirectoryAttributeMask;\r
+  return winAttributes;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Rar/RarItem.h b/CPP/7zip/Archive/Rar/RarItem.h
new file mode 100755 (executable)
index 0000000..515ecd4
--- /dev/null
@@ -0,0 +1,79 @@
+// RarItem.h\r
+\r
+#ifndef __ARCHIVE_RAR_ITEM_H\r
+#define __ARCHIVE_RAR_ITEM_H\r
+\r
+#include "Common/Types.h"\r
+#include "Common/MyString.h"\r
+\r
+#include "RarHeader.h"\r
+\r
+namespace NArchive{\r
+namespace NRar{\r
+\r
+struct CRarTime\r
+{\r
+  UInt32 DosTime;\r
+  Byte LowSecond;\r
+  Byte SubTime[3];\r
+};\r
+\r
+struct CItem\r
+{\r
+  UInt64 Size;\r
+  UInt64 PackSize;\r
+  \r
+  CRarTime CTime;\r
+  CRarTime ATime;\r
+  CRarTime MTime;\r
+\r
+  UInt32 FileCRC;\r
+  UInt32 Attrib;\r
+\r
+  UInt16 Flags;\r
+  Byte HostOS;\r
+  Byte UnPackVersion;\r
+  Byte Method;\r
+\r
+  bool CTimeDefined;\r
+  bool ATimeDefined;\r
+\r
+  AString Name;\r
+  UString UnicodeName;\r
+\r
+  Byte Salt[8];\r
+  \r
+  bool IsEncrypted()   const { return (Flags & NHeader::NFile::kEncrypted) != 0; }\r
+  bool IsSolid()       const { return (Flags & NHeader::NFile::kSolid) != 0; }\r
+  bool IsCommented()   const { return (Flags & NHeader::NFile::kComment) != 0; }\r
+  bool IsSplitBefore() const { return (Flags & NHeader::NFile::kSplitBefore) != 0; }\r
+  bool IsSplitAfter()  const { return (Flags & NHeader::NFile::kSplitAfter) != 0; }\r
+  bool HasSalt()       const { return (Flags & NHeader::NFile::kSalt) != 0; }\r
+  bool HasExtTime()    const { return (Flags & NHeader::NFile::kExtTime) != 0; }\r
+  bool HasUnicodeName()const { return (Flags & NHeader::NFile::kUnicodeName) != 0; }\r
+  bool IsOldVersion()  const { return (Flags & NHeader::NFile::kOldVersion) != 0; }\r
+  \r
+  UInt32 GetDictSize() const { return (Flags >> NHeader::NFile::kDictBitStart) & NHeader::NFile::kDictMask; }\r
+  bool IsDir() const;\r
+  bool IgnoreItem() const;\r
+  UInt32 GetWinAttributes() const;\r
+  \r
+  CItem(): CTimeDefined(false), ATimeDefined(false) {}\r
+};\r
+\r
+class CItemEx: public CItem\r
+{\r
+public:\r
+  UInt64 Position;\r
+  UInt16 MainPartSize;\r
+  UInt16 CommentSize;\r
+  UInt16 AlignSize;\r
+  UInt64 GetFullSize()  const { return MainPartSize + CommentSize + AlignSize + PackSize; };\r
+  //  DWORD GetHeaderWithCommentSize()  const { return MainPartSize + CommentSize; };\r
+  UInt64 GetCommentPosition() const { return Position + MainPartSize; };\r
+  UInt64 GetDataPosition()    const { return GetCommentPosition() + CommentSize + AlignSize; };\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Rar/RarRegister.cpp b/CPP/7zip/Archive/Rar/RarRegister.cpp
new file mode 100755 (executable)
index 0000000..1db21e0
--- /dev/null
@@ -0,0 +1,13 @@
+// RarRegister.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/RegisterArc.h"\r
+\r
+#include "RarHandler.h"\r
+static IInArchive *CreateArc() { return new NArchive::NRar::CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"Rar", L"rar r00", 0, 3, {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}, 7, false, CreateArc, 0,  };\r
+\r
+REGISTER_ARC(Rar)\r
diff --git a/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp b/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp
new file mode 100755 (executable)
index 0000000..cc0333b
--- /dev/null
@@ -0,0 +1,78 @@
+// RarVolumeInStream.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/7zCrc.h"\r
+\r
+#include "RarVolumeInStream.h"\r
+\r
+namespace NArchive {\r
+namespace NRar {\r
+\r
+void CFolderInStream::Init(\r
+    CObjectVector<CInArchive> *archives,\r
+    const CObjectVector<CItemEx> *items,\r
+    const CRefItem &refItem)\r
+{\r
+  _archives = archives;\r
+  _items = items;\r
+  _refItem = refItem;\r
+  _curIndex = 0;\r
+  CRCs.Clear();\r
+  _fileIsOpen = false;\r
+}\r
+\r
+HRESULT CFolderInStream::OpenStream()\r
+{\r
+  while (_curIndex < _refItem.NumItems)\r
+  {\r
+    const CItemEx &item = (*_items)[_refItem.ItemIndex + _curIndex];\r
+    _stream.Attach((*_archives)[_refItem.VolumeIndex + _curIndex].\r
+        CreateLimitedStream(item.GetDataPosition(), item.PackSize));\r
+    _curIndex++;\r
+    _fileIsOpen = true;\r
+    _crc = CRC_INIT_VAL;\r
+    return S_OK;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CFolderInStream::CloseStream()\r
+{\r
+  CRCs.Add(CRC_GET_DIGEST(_crc));\r
+  _stream.Release();\r
+  _fileIsOpen = false;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  UInt32 realProcessedSize = 0;\r
+  while ((_curIndex < _refItem.NumItems || _fileIsOpen) && size > 0)\r
+  {\r
+    if (_fileIsOpen)\r
+    {\r
+      UInt32 localProcessedSize;\r
+      RINOK(_stream->Read(\r
+          ((Byte *)data) + realProcessedSize, size, &localProcessedSize));\r
+      _crc = CrcUpdate(_crc, ((Byte *)data) + realProcessedSize, localProcessedSize);\r
+      if (localProcessedSize == 0)\r
+      {\r
+        RINOK(CloseStream());\r
+        continue;\r
+      }\r
+      realProcessedSize += localProcessedSize;\r
+      size -= localProcessedSize;\r
+      break;\r
+    }\r
+    else\r
+    {\r
+      RINOK(OpenStream());\r
+    }\r
+  }\r
+  if (processedSize != 0)\r
+    *processedSize = realProcessedSize;\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Rar/RarVolumeInStream.h b/CPP/7zip/Archive/Rar/RarVolumeInStream.h
new file mode 100755 (executable)
index 0000000..d175a2c
--- /dev/null
@@ -0,0 +1,49 @@
+// RarVolumeInStream.h\r
+\r
+#ifndef __RAR_VOLUME_IN_STREAM_H\r
+#define __RAR_VOLUME_IN_STREAM_H\r
+\r
+#include "../../IStream.h"\r
+#include "RarIn.h"\r
+\r
+namespace NArchive {\r
+namespace NRar {\r
+\r
+struct CRefItem\r
+{\r
+  int VolumeIndex;\r
+  int ItemIndex;\r
+  int NumItems;\r
+};\r
+\r
+class CFolderInStream:\r
+  public ISequentialInStream,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+\r
+private:\r
+  CObjectVector<CInArchive> *_archives;\r
+  const CObjectVector<CItemEx> *_items;\r
+  CRefItem _refItem;\r
+  int _curIndex;\r
+  UInt32 _crc;\r
+  bool _fileIsOpen;\r
+  CMyComPtr<ISequentialInStream> _stream;\r
+\r
+  HRESULT OpenStream();\r
+  HRESULT CloseStream();\r
+public:\r
+  void Init(CObjectVector<CInArchive> *archives,\r
+      const CObjectVector<CItemEx> *items,\r
+      const CRefItem &refItem);\r
+\r
+  CRecordVector<UInt32> CRCs;\r
+};\r
+  \r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Rar/StdAfx.cpp b/CPP/7zip/Archive/Rar/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..c6d3b1f
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/Archive/Rar/StdAfx.h b/CPP/7zip/Archive/Rar/StdAfx.h
new file mode 100755 (executable)
index 0000000..83fdd22
--- /dev/null
@@ -0,0 +1,8 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/RpmHandler.cpp b/CPP/7zip/Archive/RpmHandler.cpp
new file mode 100755 (executable)
index 0000000..536c968
--- /dev/null
@@ -0,0 +1,292 @@
+// RpmHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/MyString.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../Common/LimitedStreams.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/CopyCoder.h"\r
+\r
+using namespace NWindows;\r
+\r
+#define Get16(p) GetBe16(p)\r
+#define Get32(p) GetBe32(p)\r
+\r
+namespace NArchive {\r
+namespace NRpm {\r
+\r
+/* Reference: lib/signature.h of rpm package */\r
+#define RPMSIG_NONE         0  /* Do not change! */\r
+/* The following types are no longer generated */\r
+#define RPMSIG_PGP262_1024  1  /* No longer generated */ /* 256 byte */\r
+/* These are the new-style signatures.  They are Header structures.    */\r
+/* Inside them we can put any number of any type of signature we like. */\r
+\r
+#define RPMSIG_HEADERSIG    5  /* New Header style signature */\r
+\r
+const UInt32 kLeadSize = 96;\r
+struct CLead\r
+{\r
+  unsigned char Magic[4];\r
+  unsigned char Major;  // not supported  ver1, only support 2,3 and lator\r
+  unsigned char Minor;\r
+  UInt16 Type;\r
+  UInt16 ArchNum;\r
+  char Name[66];\r
+  UInt16 OSNum;\r
+  UInt16 SignatureType;\r
+  char Reserved[16];  // pad to 96 bytes -- 8 byte aligned\r
+  bool MagicCheck() const\r
+    { return Magic[0] == 0xed && Magic[1] == 0xab && Magic[2] == 0xee && Magic[3] == 0xdb; };\r
+};\r
+  \r
+const UInt32 kEntryInfoSize = 16;\r
+/*\r
+struct CEntryInfo\r
+{\r
+  int Tag;\r
+  int Type;\r
+  int Offset; // Offset from beginning of data segment, only defined on disk\r
+  int Count;\r
+};\r
+*/\r
+\r
+// case: SignatureType == RPMSIG_HEADERSIG\r
+const UInt32 kCSigHeaderSigSize = 16;\r
+struct CSigHeaderSig\r
+{\r
+  unsigned char Magic[4];\r
+  UInt32 Reserved;\r
+  UInt32 IndexLen;  // count of index entries\r
+  UInt32 DataLen;   // number of bytes\r
+  bool MagicCheck()\r
+    { return Magic[0] == 0x8e && Magic[1] == 0xad && Magic[2] == 0xe8 && Magic[3] == 0x01; };\r
+  UInt32 GetLostHeaderLen()\r
+    { return IndexLen * kEntryInfoSize + DataLen; };\r
+};\r
+\r
+static HRESULT RedSigHeaderSig(IInStream *inStream, CSigHeaderSig &h)\r
+{\r
+  char dat[kCSigHeaderSigSize];\r
+  char *cur = dat;\r
+  RINOK(ReadStream_FALSE(inStream, dat, kCSigHeaderSigSize));\r
+  memcpy(h.Magic, cur, 4);\r
+  cur += 4;\r
+  cur += 4;\r
+  h.IndexLen = Get32(cur);\r
+  cur += 4;\r
+  h.DataLen = Get32(cur);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT OpenArchive(IInStream *inStream)\r
+{\r
+  UInt64 pos;\r
+  char leadData[kLeadSize];\r
+  char *cur = leadData;\r
+  CLead lead;\r
+  RINOK(ReadStream_FALSE(inStream, leadData, kLeadSize));\r
+  memcpy(lead.Magic, cur, 4);\r
+  cur += 4;\r
+  lead.Major = *cur++;\r
+  lead.Minor = *cur++;\r
+  lead.Type = Get16(cur);\r
+  cur += 2;\r
+  lead.ArchNum = Get16(cur);\r
+  cur += 2;\r
+  memcpy(lead.Name, cur, sizeof(lead.Name));\r
+  cur += sizeof(lead.Name);\r
+  lead.OSNum = Get16(cur);\r
+  cur += 2;\r
+  lead.SignatureType = Get16(cur);\r
+  cur += 2;\r
+\r
+  if (!lead.MagicCheck() || lead.Major < 3)\r
+    return S_FALSE;\r
+\r
+  CSigHeaderSig sigHeader, header;\r
+  if (lead.SignatureType == RPMSIG_NONE)\r
+  {\r
+    ;\r
+  }\r
+  else if (lead.SignatureType == RPMSIG_PGP262_1024)\r
+  {\r
+    UInt64 pos;\r
+    RINOK(inStream->Seek(256, STREAM_SEEK_CUR, &pos));\r
+  }\r
+  else if (lead.SignatureType == RPMSIG_HEADERSIG)\r
+  {\r
+    RINOK(RedSigHeaderSig(inStream, sigHeader));\r
+    if (!sigHeader.MagicCheck())\r
+      return S_FALSE;\r
+    UInt32 len = sigHeader.GetLostHeaderLen();\r
+    RINOK(inStream->Seek(len, STREAM_SEEK_CUR, &pos));\r
+    if ((pos % 8) != 0)\r
+    {\r
+      RINOK(inStream->Seek((pos / 8 + 1) * 8 - pos,\r
+          STREAM_SEEK_CUR, &pos));\r
+    }\r
+  }\r
+  else\r
+    return S_FALSE;\r
+\r
+  RINOK(RedSigHeaderSig(inStream, header));\r
+  if (!header.MagicCheck())\r
+    return S_FALSE;\r
+  int headerLen = header.GetLostHeaderLen();\r
+  if (headerLen == -1)\r
+    return S_FALSE;\r
+  RINOK(inStream->Seek(headerLen, STREAM_SEEK_CUR, &pos));\r
+  return S_OK;\r
+}\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IInArchiveGetStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<IInStream> _stream;\r
+  UInt64 _pos;\r
+  UInt64 _size;\r
+  Byte _sig[4];\r
+public:\r
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);\r
+};\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidSize, VT_UI8}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps_NO_Table\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  switch(propID) { case kpidMainSubfile: prop = (UInt32)0; break; }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *inStream,\r
+    const UInt64 * /* maxCheckStartPosition */,\r
+    IArchiveOpenCallback * /* openArchiveCallback */)\r
+{\r
+  COM_TRY_BEGIN\r
+  try\r
+  {\r
+    Close();\r
+    if (OpenArchive(inStream) != S_OK)\r
+      return S_FALSE;\r
+    RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_pos));\r
+    RINOK(ReadStream_FALSE(inStream, _sig, sizeof(_sig) / sizeof(_sig[0])));\r
+    UInt64 endPosition;\r
+    RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPosition));\r
+    _size = endPosition - _pos;\r
+    _stream = inStream;\r
+    return S_OK;\r
+  }\r
+  catch(...) { return S_FALSE; }\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _stream.Release();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = 1;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)\r
+{\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidSize:\r
+    case kpidPackSize:\r
+      prop = _size;\r
+      break;\r
+    case kpidExtension:\r
+    {\r
+      char s[32];\r
+      MyStringCopy(s, "cpio.");\r
+      const char *ext;\r
+      if (_sig[0] == 0x1F && _sig[1] == 0x8B)\r
+        ext = "gz";\r
+      else if (_sig[0] == 'B' && _sig[1] == 'Z' && _sig[2] == 'h')\r
+        ext = "bz2";\r
+      else\r
+        ext = "lzma";\r
+      MyStringCopy(s + MyStringLen(s), ext);\r
+      prop = s;\r
+      break;\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))\r
+    return E_INVALIDARG;\r
+\r
+  RINOK(extractCallback->SetTotal(_size));\r
+  CMyComPtr<ISequentialOutStream> outStream;\r
+  Int32 askMode = testMode ?\r
+      NExtract::NAskMode::kTest :\r
+      NExtract::NAskMode::kExtract;\r
+  RINOK(extractCallback->GetStream(0, &outStream, askMode));\r
+  if (!testMode && !outStream)\r
+    return S_OK;\r
+  RINOK(extractCallback->PrepareOperation(askMode));\r
+\r
+  CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+  \r
+  RINOK(_stream->Seek(_pos, STREAM_SEEK_SET, NULL));\r
+  RINOK(copyCoder->Code(_stream, outStream, NULL, NULL, progress));\r
+  outStream.Release();\r
+  return extractCallback->SetOperationResult(NExtract::NOperationResult::kOK);\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream)\r
+{\r
+  COM_TRY_BEGIN\r
+  return CreateLimitedInStream(_stream, _pos, _size, stream);\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new NArchive::NRpm::CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"Rpm", L"rpm", 0, 0xEB, { 0xED, 0xAB, 0xEE, 0xDB}, 4, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Rpm)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp
new file mode 100755 (executable)
index 0000000..cb98a77
--- /dev/null
@@ -0,0 +1,366 @@
+// SplitHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/MyString.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+\r
+#include "../Compress/CopyCoder.h"\r
+\r
+#include "Common/MultiStream.h"\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace NSplit {\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidSize, VT_UI8}\r
+};\r
+\r
+STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidNumVolumes, VT_UI4}\r
+};\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IInArchiveGetStream,\r
+  public CMyUnknownImp\r
+{\r
+  UString _subName;\r
+  CObjectVector<CMyComPtr<IInStream> > _streams;\r
+  CRecordVector<UInt64> _sizes;\r
+  UInt64 _totalSize;\r
+public:\r
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidMainSubfile: prop = (UInt32)0; break;\r
+    case kpidNumVolumes: prop = (UInt32)_streams.Size(); break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+struct CSeqName\r
+{\r
+  UString _unchangedPart;\r
+  UString _changedPart;\r
+  bool _splitStyle;\r
+  \r
+  UString GetNextName()\r
+  {\r
+    UString newName;\r
+    if (_splitStyle)\r
+    {\r
+      int i;\r
+      int numLetters = _changedPart.Length();\r
+      for (i = numLetters - 1; i >= 0; i--)\r
+      {\r
+        wchar_t c = _changedPart[i];\r
+        if (c == 'z')\r
+        {\r
+          c = 'a';\r
+          newName = c + newName;\r
+          continue;\r
+        }\r
+        else if (c == 'Z')\r
+        {\r
+          c = 'A';\r
+          newName = c + newName;\r
+          continue;\r
+        }\r
+        c++;\r
+        if ((c == 'z' || c == 'Z') && i == 0)\r
+        {\r
+          _unchangedPart += c;\r
+          wchar_t newChar = (c == 'z') ? L'a' : L'A';\r
+          newName.Empty();\r
+          numLetters++;\r
+          for (int k = 0; k < numLetters; k++)\r
+            newName += newChar;\r
+          break;\r
+        }\r
+        newName = c + newName;\r
+        i--;\r
+        for (; i >= 0; i--)\r
+          newName = _changedPart[i] + newName;\r
+        break;\r
+      }\r
+    }\r
+    else\r
+    {\r
+      int i;\r
+      int numLetters = _changedPart.Length();\r
+      for (i = numLetters - 1; i >= 0; i--)\r
+      {\r
+        wchar_t c = _changedPart[i];\r
+        if (c == L'9')\r
+        {\r
+          c = L'0';\r
+          newName = c + newName;\r
+          if (i == 0)\r
+            newName = UString(L'1') + newName;\r
+          continue;\r
+        }\r
+        c++;\r
+        newName = c + newName;\r
+        i--;\r
+        for (; i >= 0; i--)\r
+          newName = _changedPart[i] + newName;\r
+        break;\r
+      }\r
+    }\r
+    _changedPart = newName;\r
+    return _unchangedPart + _changedPart;\r
+  }\r
+};\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream,\r
+    const UInt64 * /* maxCheckStartPosition */,\r
+    IArchiveOpenCallback *openArchiveCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  Close();\r
+  if (openArchiveCallback == 0)\r
+    return S_FALSE;\r
+  // try\r
+  {\r
+    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;\r
+    CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback;\r
+    if (openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback,\r
+        &openVolumeCallback) != S_OK)\r
+      return S_FALSE;\r
+    \r
+    UString name;\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      RINOK(openVolumeCallback->GetProperty(kpidName, &prop));\r
+      if (prop.vt != VT_BSTR)\r
+        return S_FALSE;\r
+      name = prop.bstrVal;\r
+    }\r
+    \r
+    int dotPos = name.ReverseFind('.');\r
+    UString prefix, ext;\r
+    if (dotPos >= 0)\r
+    {\r
+      prefix = name.Left(dotPos + 1);\r
+      ext = name.Mid(dotPos + 1);\r
+    }\r
+    else\r
+      ext = name;\r
+    UString extBig = ext;\r
+    extBig.MakeUpper();\r
+\r
+    CSeqName seqName;\r
+\r
+    int numLetters = 2;\r
+    bool splitStyle = false;\r
+    if (extBig.Right(2) == L"AA")\r
+    {\r
+      splitStyle = true;\r
+      while (numLetters < extBig.Length())\r
+      {\r
+        if (extBig[extBig.Length() - numLetters - 1] != 'A')\r
+          break;\r
+        numLetters++;\r
+      }\r
+    }\r
+    else if (ext.Right(2) == L"01")\r
+    {\r
+      while (numLetters < extBig.Length())\r
+      {\r
+        if (extBig[extBig.Length() - numLetters - 1] != '0')\r
+          break;\r
+        numLetters++;\r
+      }\r
+      if (numLetters != ext.Length())\r
+        return S_FALSE;\r
+    }\r
+    else\r
+      return S_FALSE;\r
+\r
+    _streams.Add(stream);\r
+\r
+    seqName._unchangedPart = prefix + ext.Left(extBig.Length() - numLetters);\r
+    seqName._changedPart = ext.Right(numLetters);\r
+    seqName._splitStyle = splitStyle;\r
+\r
+    if (prefix.Length() < 1)\r
+      _subName = L"file";\r
+    else\r
+      _subName = prefix.Left(prefix.Length() - 1);\r
+\r
+    _totalSize = 0;\r
+    UInt64 size;\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      RINOK(openVolumeCallback->GetProperty(kpidSize, &prop));\r
+      if (prop.vt != VT_UI8)\r
+        return E_INVALIDARG;\r
+      size = prop.uhVal.QuadPart;\r
+    }\r
+    _totalSize += size;\r
+    _sizes.Add(size);\r
+    \r
+    if (openArchiveCallback != NULL)\r
+    {\r
+      UInt64 numFiles = _streams.Size();\r
+      RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));\r
+    }\r
+\r
+    for (;;)\r
+    {\r
+      UString fullName = seqName.GetNextName();\r
+      CMyComPtr<IInStream> nextStream;\r
+      HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream);\r
+      if (result == S_FALSE)\r
+        break;\r
+      if (result != S_OK)\r
+        return result;\r
+      if (!stream)\r
+        break;\r
+      {\r
+        NCOM::CPropVariant prop;\r
+        RINOK(openVolumeCallback->GetProperty(kpidSize, &prop));\r
+        if (prop.vt != VT_UI8)\r
+          return E_INVALIDARG;\r
+        size = prop.uhVal.QuadPart;\r
+      }\r
+      _totalSize += size;\r
+      _sizes.Add(size);\r
+      _streams.Add(nextStream);\r
+      if (openArchiveCallback != NULL)\r
+      {\r
+        UInt64 numFiles = _streams.Size();\r
+        RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));\r
+      }\r
+    }\r
+  }\r
+  /*\r
+  catch(...)\r
+  {\r
+    return S_FALSE;\r
+  }\r
+  */\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _sizes.Clear();\r
+  _streams.Clear();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _streams.IsEmpty() ? 0 : 1;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)\r
+{\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidPath: prop = _subName; break;\r
+    case kpidSize:\r
+    case kpidPackSize:\r
+      prop = _totalSize;\r
+      break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))\r
+    return E_INVALIDARG;\r
+\r
+  UInt64 currentTotalSize = 0;\r
+  RINOK(extractCallback->SetTotal(_totalSize));\r
+  CMyComPtr<ISequentialOutStream> outStream;\r
+  Int32 askMode = testMode ?\r
+      NExtract::NAskMode::kTest :\r
+      NExtract::NAskMode::kExtract;\r
+  RINOK(extractCallback->GetStream(0, &outStream, askMode));\r
+  if (!testMode && !outStream)\r
+    return S_OK;\r
+  RINOK(extractCallback->PrepareOperation(askMode));\r
+  \r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  for (int i = 0; i < _streams.Size(); i++)\r
+  {\r
+    lps->InSize = lps->OutSize = currentTotalSize;\r
+    RINOK(lps->SetCur());\r
+    IInStream *inStream = _streams[i];\r
+    RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));\r
+    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));\r
+    currentTotalSize += copyCoderSpec->TotalSize;\r
+  }\r
+  outStream.Release();\r
+  return extractCallback->SetOperationResult(NExtract::NOperationResult::kOK);\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (index != 0)\r
+    return E_INVALIDARG;\r
+  *stream = 0;\r
+  CMultiStream *streamSpec = new CMultiStream;\r
+  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;\r
+  for (int i = 0; i < _streams.Size(); i++)\r
+  {\r
+    CMultiStream::CSubStreamInfo subStreamInfo;\r
+    subStreamInfo.Stream = _streams[i];\r
+    subStreamInfo.Size = _sizes[i];\r
+    streamSpec->Streams.Add(subStreamInfo);\r
+  }\r
+  streamSpec->Init();\r
+  *stream = streamTemp.Detach();\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+{ L"Split", L"001", 0, 0xEA, { 0 }, 0, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Split)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/SquashfsHandler.cpp b/CPP/7zip/Archive/SquashfsHandler.cpp
new file mode 100755 (executable)
index 0000000..acc0362
--- /dev/null
@@ -0,0 +1,2155 @@
+// SquashfsHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/7zCrc.h"\r
+#include "../../../C/Alloc.h"\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/PropVariantUtils.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../Common/LimitedStreams.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamObjects.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/CopyCoder.h"\r
+#include "../Compress/ZlibDecoder.h"\r
+#include "../Compress/LzmaDecoder.h"\r
+\r
+namespace NArchive {\r
+namespace NSquashfs {\r
+\r
+static const UInt32 kNumFilesMax = (1 << 28);\r
+static const unsigned kNumDirLevelsMax = (1 << 10);\r
+\r
+// Layout: Header, Data, inodes, Directories, Fragments, UIDs, GIDs\r
+\r
+/*\r
+#define Get16(p) (be ? GetBe16(p) : GetUi16(p))\r
+#define Get32(p) (be ? GetBe32(p) : GetUi32(p))\r
+#define Get64(p) (be ? GetBe64(p) : GetUi64(p))\r
+*/\r
+\r
+UInt16 Get16b(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); }\r
+UInt32 Get32b(const Byte *p, bool be) { return be ? GetBe32(p) : GetUi32(p); }\r
+UInt64 Get64b(const Byte *p, bool be) { return be ? GetBe64(p) : GetUi64(p); }\r
+\r
+#define Get16(p) Get16b(p, be)\r
+#define Get32(p) Get32b(p, be)\r
+#define Get64(p) Get64b(p, be)\r
+\r
+#define LE_16(offs, dest) dest = GetUi16(p + (offs));\r
+#define LE_32(offs, dest) dest = GetUi32(p + (offs));\r
+#define LE_64(offs, dest) dest = GetUi64(p + (offs));\r
+\r
+#define GET_16(offs, dest) dest = Get16(p + (offs));\r
+#define GET_32(offs, dest) dest = Get32(p + (offs));\r
+#define GET_64(offs, dest) dest = Get64(p + (offs));\r
+\r
+static const UInt32 kSignatureSize = 4;\r
+#define SIGNATURE { 'h', 's', 'q', 's' }\r
+static const UInt32 kSignature32_LE = 0x73717368;\r
+static const UInt32 kSignature32_BE = 0x68737173;\r
+static const UInt32 kSignature32_LZ = 0x71736873;\r
+\r
+#define kMethod_ZLIB 1\r
+#define kMethod_LZMA 2\r
+#define kMethod_LZO  3\r
+\r
+static const char *k_Methods[] =\r
+{\r
+  "Unknown",\r
+  "ZLIB",\r
+  "LZMA",\r
+  "LZO"\r
+};\r
+\r
+static const UInt32 kMetadataBlockSizeLog = 13;\r
+static const UInt32 kMetadataBlockSize = (1 << kMetadataBlockSizeLog);\r
+\r
+#define MY_S_IFIFO  0x1000\r
+#define MY_S_IFCHR  0x2000\r
+#define MY_S_IFDIR  0x4000\r
+#define MY_S_IFBLK  0x6000\r
+#define MY_S_IFREG  0x8000\r
+#define MY_S_IFLNK  0xA000\r
+#define MY_S_IFSOCK 0xC000\r
+\r
+enum\r
+{\r
+  kType_IPC,\r
+  kType_DIR,\r
+  kType_FILE,\r
+  kType_LNK,\r
+  kType_BLK,\r
+  kType_CHR,\r
+  kType_FIFO,\r
+  kType_SOCK\r
+};\r
+\r
+static const UInt32 k_TypeToMode[] =\r
+{\r
+  0,\r
+  MY_S_IFDIR, MY_S_IFREG, MY_S_IFLNK, MY_S_IFBLK, MY_S_IFCHR, MY_S_IFIFO, MY_S_IFSOCK,\r
+  MY_S_IFDIR, MY_S_IFREG, MY_S_IFLNK, MY_S_IFBLK, MY_S_IFCHR, MY_S_IFIFO, MY_S_IFSOCK\r
+};\r
+\r
+\r
+enum\r
+{\r
+  kFlag_UNC_INODES,\r
+  kFlag_UNC_DATA,\r
+  kFlag_CHECK,\r
+  kFlag_UNC_FRAGS,\r
+  kFlag_NO_FRAGS,\r
+  kFlag_ALWAYS_FRAG,\r
+  kFlag_DUPLICATE,\r
+  kFlag_EXPORT\r
+};\r
+\r
+static const CUInt32PCharPair k_Flags[] =\r
+{\r
+  { kFlag_UNC_INODES, "UNCOMPRESSED_INODES" },\r
+  { kFlag_UNC_DATA, "UNCOMPRESSED_DATA" },\r
+  { kFlag_CHECK, "CHECK" },\r
+  { kFlag_UNC_FRAGS, "UNCOMPRESSED_FRAGMENTS" },\r
+  { kFlag_NO_FRAGS, "NO_FRAGMENTS" },\r
+  { kFlag_ALWAYS_FRAG, "ALWAYS_FRAGMENTS" },\r
+  { kFlag_DUPLICATE, "DUPLICATES_REMOVED" },\r
+  { kFlag_EXPORT, "EXPORTABLE" }\r
+};\r
+\r
+static const UInt32 kNotCompressedBit16 = (1 << 15);\r
+static const UInt32 kNotCompressedBit32 = (1 << 24);\r
+\r
+#define GET_COMPRESSED_BLOCK_SIZE(size) ((size) & ~kNotCompressedBit32)\r
+#define IS_COMPRESSED_BLOCK(size) (((size) & kNotCompressedBit32) == 0)\r
+\r
+static const UInt32 kHeaderSize1 = 0x33;\r
+static const UInt32 kHeaderSize2 = 0x3F;\r
+static const UInt32 kHeaderSize3 = 0x77;\r
+static const UInt32 kHeaderSize4 = 0x60;\r
+\r
+struct CHeader\r
+{\r
+  bool be;\r
+  bool SeveralMethods;\r
+  Byte NumUids;\r
+  Byte NumGids;\r
+\r
+  UInt32 NumInodes;\r
+  UInt32 CTime;\r
+  UInt32 BlockSize;\r
+  UInt32 NumFrags;\r
+  UInt16 Method;\r
+  UInt16 BlockSizeLog;\r
+  UInt16 Flags;\r
+  UInt16 NumIDs;\r
+  UInt16 Major;\r
+  UInt16 Minor;\r
+  UInt64 RootInode;\r
+  UInt64 Size;\r
+  UInt64 UidTable;\r
+  UInt64 GidTable;\r
+  UInt64 XattrIdTable;\r
+  UInt64 InodeTable;\r
+  UInt64 DirTable;\r
+  UInt64 FragTable;\r
+  UInt64 LookupTable;\r
+\r
+  void Parse3(const Byte *p)\r
+  {\r
+    Method = kMethod_ZLIB;\r
+    GET_32 (0x08, Size);\r
+    GET_32 (0x0C, UidTable);\r
+    GET_32 (0x10, GidTable);\r
+    GET_32 (0x14, InodeTable);\r
+    GET_32 (0x18, DirTable);\r
+    GET_16 (0x20, BlockSize);\r
+    GET_16 (0x22, BlockSizeLog);\r
+    Flags   = p[0x24];\r
+    NumUids = p[0x25];\r
+    NumGids = p[0x26];\r
+    GET_32 (0x27, CTime);\r
+    GET_64 (0x2B, RootInode);\r
+    NumFrags = 0;\r
+    FragTable = UidTable;\r
+\r
+    if (Major >= 2)\r
+    {\r
+      GET_32 (0x33, BlockSize);\r
+      GET_32 (0x37, NumFrags);\r
+      GET_32 (0x3B, FragTable);\r
+      if (Major == 3)\r
+      {\r
+        GET_64 (0x3F, Size);\r
+        GET_64 (0x47, UidTable);\r
+        GET_64 (0x4F, GidTable);\r
+        GET_64 (0x57, InodeTable);\r
+        GET_64 (0x5F, DirTable);\r
+        GET_64 (0x67, FragTable);\r
+        GET_64 (0x6F, LookupTable);\r
+      }\r
+    }\r
+  }\r
+\r
+  void Parse4(const Byte *p)\r
+  {\r
+    LE_32 (0x08, CTime);\r
+    LE_32 (0x0C, BlockSize);\r
+    LE_32 (0x10, NumFrags);\r
+    LE_16 (0x14, Method);\r
+    LE_16 (0x16, BlockSizeLog);\r
+    LE_16 (0x18, Flags);\r
+    LE_16 (0x1A, NumIDs);\r
+    LE_64 (0x20, RootInode);\r
+    LE_64 (0x28, Size);\r
+    LE_64 (0x30, UidTable);\r
+    LE_64 (0x38, XattrIdTable);\r
+    LE_64 (0x40, InodeTable);\r
+    LE_64 (0x48, DirTable);\r
+    LE_64 (0x50, FragTable);\r
+    LE_64 (0x58, LookupTable);\r
+    GidTable = 0;\r
+  }\r
+\r
+  bool Parse(const Byte *p)\r
+  {\r
+    be = false;\r
+    SeveralMethods = false;\r
+    switch (GetUi32(p))\r
+    {\r
+      case kSignature32_LE: break;\r
+      case kSignature32_BE: be = true; break;\r
+      case kSignature32_LZ: SeveralMethods = true; break;\r
+      default: return false;\r
+    }\r
+    GET_32 (4, NumInodes);\r
+    GET_16 (0x1C, Major);\r
+    GET_16 (0x1E, Minor);\r
+    if (Major <= 3)\r
+      Parse3(p);\r
+    else\r
+    {\r
+      if (be)\r
+        return false;\r
+      Parse4(p);\r
+    }\r
+    return\r
+      InodeTable < DirTable &&\r
+      DirTable <= FragTable &&\r
+      FragTable <= Size &&\r
+      UidTable <= Size &&\r
+      BlockSizeLog >= 12 &&\r
+      BlockSizeLog < 31 &&\r
+      BlockSize == ((UInt32)1 << BlockSizeLog);\r
+  }\r
+\r
+  bool IsSupported() const { return Major > 0 && Major <= 4 && BlockSizeLog <= 23; }\r
+  bool IsOldVersion() const { return Major < 4; }\r
+  bool NeedCheckData() const { return (Flags & (1 << kFlag_CHECK)) != 0; }\r
+  unsigned GetFileNameOffset() const { return Major <= 2 ? 3 : (Major == 3 ? 5 : 8); }\r
+  unsigned GetSymLinkOffset() const { return Major <= 1 ? 5: (Major <= 2 ? 6: (Major == 3 ? 18 : 24)); }\r
+  unsigned GetSpecGuidIndex() const { return Major <= 1 ? 0xF: 0xFF; }\r
+};\r
+\r
+static const UInt32 kFrag_Empty = (UInt32)(Int32)-1;\r
+// static const UInt32 kXattr_Empty = (UInt32)(Int32)-1;\r
+\r
+struct CNode\r
+{\r
+  UInt16 Type;\r
+  UInt16 Mode;\r
+  UInt16 Uid;\r
+  UInt16 Gid;\r
+  UInt32 Frag;\r
+  UInt32 Offset;\r
+  // UInt32 MTime;\r
+  // UInt32 Number;\r
+  // UInt32 NumLinks;\r
+  // UInt32 RDev;\r
+  // UInt32 Xattr;\r
+  // UInt32 Parent;\r
+  \r
+  UInt64 FileSize;\r
+  UInt64 StartBlock;\r
+  // UInt64 Sparse;\r
+  \r
+  UInt32 Parse1(const Byte *p, UInt32 size, const CHeader &_h);\r
+  UInt32 Parse2(const Byte *p, UInt32 size, const CHeader &_h);\r
+  UInt32 Parse3(const Byte *p, UInt32 size, const CHeader &_h);\r
+  UInt32 Parse4(const Byte *p, UInt32 size, const CHeader &_h);\r
+  \r
+  bool IsDir() const { return (Type == kType_DIR || Type == kType_DIR + 7); }\r
+  bool IsLink() const { return (Type == kType_LNK || Type == kType_LNK + 7); }\r
+  UInt64 GetSize() const { return IsDir() ? 0 : FileSize; }\r
+  \r
+  bool ThereAreFrags() const { return Frag != kFrag_Empty; }\r
+  UInt64 GetNumBlocks(const CHeader &_h) const\r
+  {\r
+    return (FileSize >> _h.BlockSizeLog) +\r
+      (!ThereAreFrags() && (FileSize & (_h.BlockSize - 1)) != 0);\r
+  }\r
+};\r
+\r
+UInt32 CNode::Parse1(const Byte *p, UInt32 size, const CHeader &_h)\r
+{\r
+  bool be = _h.be;\r
+  if (size < 4)\r
+    return 0;\r
+  UInt16 t = Get16(p);\r
+  if (be)\r
+  {\r
+    Type = t >> 12;\r
+    Mode = t & 0xFFF;\r
+    Uid = p[2] >> 4;\r
+    Gid = p[2] & 0xF;\r
+  }\r
+  else\r
+  {\r
+    Type = t & 0xF;\r
+    Mode = t >> 4;\r
+    Uid = p[2] & 0xF;\r
+    Gid = p[2] >> 4;\r
+  }\r
+\r
+  // Xattr = kXattr_Empty;\r
+  // MTime = 0;\r
+  FileSize = 0;\r
+  StartBlock = 0;\r
+  Frag = kFrag_Empty;\r
+\r
+  if (Type == 0)\r
+  {\r
+    Byte t = p[3];\r
+    if (be)\r
+    {\r
+      Type = t >> 4;\r
+      Offset = t & 0xF;\r
+    }\r
+    else\r
+    {\r
+      Type = t & 0xF;\r
+      Offset = t >> 4;\r
+    }\r
+    return (Type == kType_FIFO || Type == kType_SOCK) ? 4 : 0;\r
+  }\r
+\r
+  Type--;\r
+  Uid += (Type / 5) * 16;\r
+  Type = (Type % 5) + 1;\r
+\r
+  if (Type == kType_FILE)\r
+  {\r
+    if (size < 15)\r
+      return 0;\r
+    // GET_32 (3, MTime);\r
+    GET_32 (7, StartBlock);\r
+    UInt32 t;\r
+    GET_32 (11, t);\r
+    FileSize = t;\r
+    UInt32 numBlocks = t >> _h.BlockSizeLog;\r
+    if ((t & (_h.BlockSize - 1)) != 0)\r
+      numBlocks++;\r
+    UInt32 pos = numBlocks * 2 + 15;\r
+    return (pos <= size) ? pos : 0;\r
+  }\r
+  \r
+  if (Type == kType_DIR)\r
+  {\r
+    if (size < 14)\r
+      return 0;\r
+    UInt32 t = Get32(p + 3);\r
+    if (be)\r
+    {\r
+      FileSize = t >> 13;\r
+      Offset = t & 0x1FFF;\r
+    }\r
+    else\r
+    {\r
+      FileSize = t & 0x7FFFF;\r
+      Offset = t >> 19;\r
+    }\r
+    // GET_32 (7, MTime);\r
+    GET_32 (10, StartBlock);\r
+    if (be)\r
+      StartBlock &= 0xFFFFFF;\r
+    else\r
+      StartBlock >>= 8;\r
+    return 14;\r
+  }\r
+  \r
+  if (size < 5)\r
+    return 0;\r
+\r
+  if (Type == kType_LNK)\r
+  {\r
+    UInt32 len;\r
+    GET_16 (3, len);\r
+    FileSize = len;\r
+    len += 5;\r
+    return (len <= size) ? len : 0;\r
+  }\r
+\r
+  // GET_32 (3, RDev);\r
+  return 5;\r
+}\r
+\r
+UInt32 CNode::Parse2(const Byte *p, UInt32 size, const CHeader &_h)\r
+{\r
+  bool be = _h.be;\r
+  if (size < 4)\r
+    return 0;\r
+  UInt16 t = Get16(p);\r
+  if (be)\r
+  {\r
+    Type = t >> 12;\r
+    Mode = t & 0xFFF;\r
+  }\r
+  else\r
+  {\r
+    Type = t & 0xF;\r
+    Mode = t >> 4;\r
+  }\r
+  Uid = p[2];\r
+  Gid = p[3];\r
+\r
+  // Xattr = kXattr_Empty;\r
+\r
+  if (Type == kType_FILE)\r
+  {\r
+    if (size < 24)\r
+      return 0;\r
+    // GET_32 (4, MTime);\r
+    GET_32 (8, StartBlock);\r
+    GET_32 (12, Frag);\r
+    GET_32 (16, Offset);\r
+    UInt32 t;\r
+    GET_32 (20, t);\r
+    FileSize = t;\r
+    UInt32 numBlocks = t >> _h.BlockSizeLog;\r
+    if (!ThereAreFrags() && (t & (_h.BlockSize - 1)) != 0)\r
+      numBlocks++;\r
+    UInt32 pos = numBlocks * 4 + 24;\r
+    return (pos <= size) ? (UInt32)pos : 0;\r
+  }\r
+\r
+  FileSize = 0;\r
+  // MTime = 0;\r
+  StartBlock = 0;\r
+  Frag = kFrag_Empty;\r
+  \r
+  if (Type == kType_DIR)\r
+  {\r
+    if (size < 15)\r
+      return 0;\r
+    UInt32 t = Get32(p + 4);\r
+    if (be)\r
+    {\r
+      FileSize = t >> 13;\r
+      Offset = t & 0x1FFF;\r
+    }\r
+    else\r
+    {\r
+      FileSize = t & 0x7FFFF;\r
+      Offset = t >> 19;\r
+    }\r
+    // GET_32 (8, MTime);\r
+    GET_32 (11, StartBlock);\r
+    if (be)\r
+      StartBlock &= 0xFFFFFF;\r
+    else\r
+      StartBlock >>= 8;\r
+    return 15;\r
+  }\r
+  \r
+  if (Type == kType_DIR + 7)\r
+  {\r
+    if (size < 18)\r
+      return 0;\r
+    UInt32 t = Get32(p + 4);\r
+    UInt32 t2 = Get16(p + 7);\r
+    if (be)\r
+    {\r
+      FileSize = t >> 5;\r
+      Offset = t2 & 0x1FFF;\r
+    }\r
+    else\r
+    {\r
+      FileSize = t & 0x7FFFFFF;\r
+      Offset = t2 >> 3;\r
+    }\r
+    // GET_32 (9, MTime);\r
+    GET_32 (12, StartBlock);\r
+    if (be)\r
+      StartBlock &= 0xFFFFFF;\r
+    else\r
+      StartBlock >>= 8;\r
+    UInt32 iCount;\r
+    GET_16 (16, iCount);\r
+    UInt32 pos = 18;\r
+    for (UInt32 i = 0; i < iCount; i++)\r
+    {\r
+      // 27 bits: index\r
+      // 29 bits: startBlock\r
+      if (pos + 8 > size)\r
+        return 0;\r
+      pos += 8 + (UInt32)p[pos + 7] + 1; // nameSize\r
+      if (pos > size)\r
+        return 0;\r
+    }\r
+    return pos;\r
+  }\r
+\r
+  if (Type == kType_FIFO || Type == kType_SOCK)\r
+    return 4;\r
+\r
+  if (size < 6)\r
+    return 0;\r
+  \r
+  if (Type == kType_LNK)\r
+  {\r
+    UInt32 len;\r
+    GET_16 (4, len);\r
+    FileSize = len;\r
+    len += 6;\r
+    return (len <= size) ? len : 0;\r
+  }\r
+  \r
+  if (Type == kType_BLK || Type == kType_CHR)\r
+  {\r
+    // GET_16 (4, RDev);\r
+    return 6;\r
+  }\r
+  \r
+  return 0;\r
+}\r
+\r
+UInt32 CNode::Parse3(const Byte *p, UInt32 size, const CHeader &_h)\r
+{\r
+  bool be = _h.be;\r
+  if (size < 12)\r
+    return 0;\r
+  UInt16 t = Get16(p);\r
+  if (be)\r
+  {\r
+    Type = t >> 12;\r
+    Mode = t & 0xFFF;\r
+  }\r
+  else\r
+  {\r
+    Type = t & 0xF;\r
+    Mode = t >> 4;\r
+  }\r
+  Uid = p[2];\r
+  Gid = p[3];\r
+  // GET_32 (4, MTime);\r
+  // GET_32 (8, Number);\r
+  // Xattr = kXattr_Empty;\r
+  FileSize = 0;\r
+  StartBlock = 0;\r
+  \r
+  if (Type == kType_FILE || Type == kType_FILE + 7)\r
+  {\r
+    UInt32 offset;\r
+    if (Type == kType_FILE)\r
+    {\r
+      if (size < 32)\r
+        return 0;\r
+      GET_64 (12, StartBlock);\r
+      GET_32 (20, Frag);\r
+      GET_32 (24, Offset);\r
+      GET_32 (28, FileSize);\r
+      offset = 32;\r
+    }\r
+    else\r
+    {\r
+      if (size < 40)\r
+        return 0;\r
+      // GET_32 (12, NumLinks);\r
+      GET_64 (16, StartBlock);\r
+      GET_32 (24, Frag);\r
+      GET_32 (28, Offset);\r
+      GET_64 (32, FileSize);\r
+      offset = 40;\r
+    }\r
+    UInt64 pos = GetNumBlocks(_h) * 4 + offset;\r
+    return (pos <= size) ? (UInt32)pos : 0;\r
+  }\r
+\r
+  if (size < 16)\r
+    return 0;\r
+  // GET_32 (12, NumLinks);\r
\r
+  if (Type == kType_DIR)\r
+  {\r
+    if (size < 28)\r
+      return 0;\r
+    UInt32 t = Get32(p + 16);\r
+    if (be)\r
+    {\r
+      FileSize = t >> 13;\r
+      Offset = t & 0x1FFF;\r
+    }\r
+    else\r
+    {\r
+      FileSize = t & 0x7FFFF;\r
+      Offset = t >> 19;\r
+    }\r
+    GET_32 (20, StartBlock);\r
+    // GET_32 (24, Parent);\r
+    return 28;\r
+  }\r
+  \r
+  if (Type == kType_DIR + 7)\r
+  {\r
+    if (size < 31)\r
+      return 0;\r
+    UInt32 t = Get32(p + 16);\r
+    UInt32 t2 = Get16(p + 19);\r
+    if (be)\r
+    {\r
+      FileSize = t >> 5;\r
+      Offset = t2 & 0x1FFF;\r
+    }\r
+    else\r
+    {\r
+      FileSize = t & 0x7FFFFFF;\r
+      Offset = t2 >> 3;\r
+    }\r
+    GET_32 (21, StartBlock);\r
+    UInt32 iCount;\r
+    GET_16 (25, iCount);\r
+    // GET_32 (27, Parent);\r
+    UInt32 pos = 31;\r
+    for (UInt32 i = 0; i < iCount; i++)\r
+    {\r
+      // UInt32 index\r
+      // UInt32 startBlock\r
+      if (pos + 9 > size)\r
+        return 0;\r
+      pos += 9 + (unsigned)p[pos + 8] + 1; // nameSize\r
+      if (pos > size)\r
+        return 0;\r
+    }\r
+    return pos;\r
+  }\r
+\r
+  if (Type == kType_FIFO || Type == kType_SOCK)\r
+    return 16;\r
+  \r
+  if (size < 18)\r
+    return 0;\r
+  if (Type == kType_LNK)\r
+  {\r
+    UInt32 len;\r
+    GET_16 (16, len);\r
+    FileSize = len;\r
+    len += 18;\r
+    return (len <= size) ? len : 0;\r
+  }\r
+\r
+  if (Type == kType_BLK || Type == kType_CHR)\r
+  {\r
+    // GET_16 (16, RDev);\r
+    return 18;\r
+  }\r
+  \r
+  return 0;\r
+}\r
+\r
+UInt32 CNode::Parse4(const Byte *p, UInt32 size, const CHeader &_h)\r
+{\r
+  if (size < 20)\r
+    return 0;\r
+  LE_16 (0, Type);\r
+  LE_16 (2, Mode);\r
+  LE_16 (4, Uid);\r
+  LE_16 (6, Gid);\r
+  // LE_32 (8, MTime);\r
+  // LE_32 (12, Number);\r
+  \r
+  // Xattr = kXattr_Empty;\r
+  FileSize = 0;\r
+  StartBlock = 0;\r
+  \r
+  if (Type == kType_FILE || Type == kType_FILE + 7)\r
+  {\r
+    UInt32 offset;\r
+    if (Type == kType_FILE)\r
+    {\r
+      if (size < 32)\r
+        return 0;\r
+      LE_32 (16, StartBlock);\r
+      LE_32 (20, Frag);\r
+      LE_32 (24, Offset);\r
+      LE_32 (28, FileSize);\r
+      offset = 32;\r
+    }\r
+    else\r
+    {\r
+      if (size < 56)\r
+        return 0;\r
+      LE_64 (16, StartBlock);\r
+      LE_64 (24, FileSize);\r
+      // LE_64 (32, Sparse);\r
+      // LE_32 (40, NumLinks);\r
+      LE_32 (44, Frag);\r
+      LE_32 (48, Offset);\r
+      // LE_32 (52, Xattr);\r
+      offset = 56;\r
+    }\r
+    UInt64 pos = GetNumBlocks(_h) * 4 + offset;\r
+    return (pos <= size) ? (UInt32)pos : 0;\r
+  }\r
+  \r
+  if (Type == kType_DIR)\r
+  {\r
+    if (size < 32)\r
+      return 0;\r
+    LE_32 (16, StartBlock);\r
+    // LE_32 (20, NumLinks);\r
+    LE_16 (24, FileSize);\r
+    LE_16 (26, Offset);\r
+    // LE_32 (28, Parent);\r
+    return 32;\r
+  }\r
+  \r
+  // LE_32 (16, NumLinks);\r
+\r
+  if (Type == kType_DIR + 7)\r
+  {\r
+    if (size < 40)\r
+      return 0;\r
+    LE_32 (20, FileSize);\r
+    LE_32 (24, StartBlock);\r
+    // LE_32 (28, Parent);\r
+    UInt32 iCount;\r
+    LE_16 (32, iCount);\r
+    LE_16 (34, Offset);\r
+    // LE_32 (36, Xattr);\r
+\r
+    UInt32 pos = 40;\r
+    for (UInt32 i = 0; i < iCount; i++)\r
+    {\r
+      // UInt32 index\r
+      // UInt32 startBlock\r
+      if (pos + 12 > size)\r
+        return 0;\r
+      UInt32 nameLen = GetUi32(p + pos + 8);\r
+      pos += 12 + nameLen + 1;\r
+      if (pos > size || nameLen > (1 << 10))\r
+        return 0;\r
+    }\r
+    return pos;\r
+  }\r
+  \r
+  unsigned offset = 20;\r
+  switch(Type)\r
+  {\r
+    case kType_FIFO: case kType_FIFO + 7:\r
+    case kType_SOCK: case kType_SOCK + 7:\r
+      break;\r
+    case kType_LNK: case kType_LNK + 7:\r
+    {\r
+      if (size < 24)\r
+        return 0;\r
+      UInt32 len;\r
+      LE_32 (20, len);\r
+      FileSize = len;\r
+      offset = len + 24;\r
+      if (size < offset || len > (1 << 30))\r
+        return 0;\r
+      break;\r
+    }\r
+    case kType_BLK: case kType_BLK + 7:\r
+    case kType_CHR: case kType_CHR + 7:\r
+      if (size < 24)\r
+        return 0;\r
+      // LE_32 (20, RDev);\r
+      offset = 24;\r
+      break;\r
+    default:\r
+      return 0;\r
+  }\r
+  \r
+  if (Type >= 8)\r
+  {\r
+    if (size < offset + 4)\r
+      return 0;\r
+    // LE_32 (offset, Xattr);\r
+    offset += 4;\r
+  }\r
+  return offset;\r
+}\r
+\r
+struct CItem\r
+{\r
+  int Node;\r
+  int Parent;\r
+  UInt32 Ptr;\r
+};\r
+\r
+struct CData\r
+{\r
+  CByteBuffer Data;\r
+  CRecordVector<UInt32> PackPos;\r
+  CRecordVector<UInt32> UnpackPos; // additional item at the end contains TotalUnpackSize\r
+  \r
+  UInt32 GetNumBlocks() const { return PackPos.Size(); }\r
+  void Clear()\r
+  {\r
+    Data.Free();\r
+    PackPos.Clear();\r
+    UnpackPos.Clear();\r
+  }\r
+};\r
+\r
+struct CFrag\r
+{\r
+  UInt64 StartBlock;\r
+  UInt32 Size;\r
+};\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IInArchiveGetStream,\r
+  public CMyUnknownImp\r
+{\r
+  CRecordVector<CItem> _items;\r
+  CRecordVector<CNode> _nodes;\r
+  CRecordVector<UInt32> _nodesPos;\r
+  CRecordVector<UInt32> _blockToNode;\r
+  CData _inodesData;\r
+  CData _dirs;\r
+  CRecordVector<CFrag> _frags;\r
+  // CByteBuffer _uids;\r
+  // CByteBuffer _gids;\r
+  CHeader _h;\r
+\r
+  CMyComPtr<IInStream> _stream;\r
+  UInt64 _sizeCalculated;\r
+\r
+  IArchiveOpenCallback *_openCallback;\r
+\r
+  int _nodeIndex;\r
+  CRecordVector<bool> _blockCompressed;\r
+  CRecordVector<UInt64> _blockOffsets;\r
+  \r
+  CByteBuffer _cachedBlock;\r
+  UInt64 _cachedBlockStartPos;\r
+  UInt32 _cachedPackBlockSize;\r
+  UInt32 _cachedUnpackBlockSize;\r
+\r
+  CLimitedSequentialInStream *_limitedInStreamSpec;\r
+  CMyComPtr<ISequentialInStream> _limitedInStream;\r
+\r
+  CBufPtrSeqOutStream *_outStreamSpec;\r
+  CMyComPtr<ISequentialOutStream> _outStream;\r
+\r
+  NCompress::NLzma::CDecoder *_lzmaDecoderSpec;\r
+  CMyComPtr<ICompressCoder> _lzmaDecoder;\r
+\r
+  NCompress::NZlib::CDecoder *_zlibDecoderSpec;\r
+  CMyComPtr<ICompressCoder> _zlibDecoder;\r
+  \r
+  CByteBuffer _inputBuffer;\r
+\r
+  CDynBufSeqOutStream *_dynOutStreamSpec;\r
+  CMyComPtr<ISequentialOutStream> _dynOutStream;\r
+\r
+  void ClearCache()\r
+  {\r
+    _cachedBlockStartPos = 0;\r
+    _cachedPackBlockSize = 0;\r
+    _cachedUnpackBlockSize = 0;\r
+  }\r
+\r
+  HRESULT Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool *outBufWasWritten, UInt32 *outBufWasWrittenSize,\r
+      UInt32 inSize, UInt32 outSizeMax);\r
+  HRESULT ReadMetadataBlock(UInt32 &packSize);\r
+  HRESULT ReadData(CData &data, UInt64 start, UInt64 end);\r
+\r
+  HRESULT OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned level, int &nodeIndex);\r
+  HRESULT ScanInodes(UInt64 ptr);\r
+  // HRESULT ReadUids(UInt64 start, UInt32 num, CByteBuffer &ids);\r
+  HRESULT Open2(IInStream *inStream);\r
+  AString GetPath(int index) const;\r
+  bool GetPackSize(int index, UInt64 &res, bool fillOffsets);\r
+\r
+public:\r
+  CHandler();\r
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);\r
+\r
+  HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize);\r
+};\r
+\r
+CHandler::CHandler()\r
+{\r
+  _limitedInStreamSpec = new CLimitedSequentialInStream;\r
+  _limitedInStream = _limitedInStreamSpec;\r
+\r
+  _outStreamSpec = new CBufPtrSeqOutStream();\r
+  _outStream = _outStreamSpec;\r
+\r
+  _dynOutStreamSpec = new CDynBufSeqOutStream;\r
+  _dynOutStream = _dynOutStreamSpec;\r
+}\r
+\r
+static const STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidIsDir, VT_BOOL},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidPosixAttrib, VT_UI4}\r
+  // { NULL, kpidUser, VT_BSTR},\r
+  // { NULL, kpidGroup, VT_BSTR},\r
+  // { NULL, kpidLinks, VT_UI4},\r
+  // { NULL, kpidOffset, VT_UI4}\r
+};\r
+\r
+static const STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidFileSystem, VT_BSTR},\r
+  { NULL, kpidMethod, VT_BSTR},\r
+  { NULL, kpidBlock, VT_UI4},\r
+  { NULL, kpidPhySize, VT_UI8},\r
+  { NULL, kpidHeadersSize, VT_UI8},\r
+  { NULL, kpidBigEndian, VT_BOOL},\r
+  { NULL, kpidCTime, VT_FILETIME},\r
+  { NULL, kpidCharacts, VT_BSTR}\r
+  // { NULL, kpidNumBlocks, VT_UI4}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+static HRESULT LzoDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen)\r
+{\r
+  SizeT destRem = *destLen;\r
+  SizeT srcRem = *srcLen;\r
+  *destLen = 0;\r
+  *srcLen = 0;\r
+  const Byte *destStart = dest;\r
+  const Byte *srcStart = src;\r
+  unsigned mode = 2;\r
+\r
+  {\r
+    if (srcRem == 0)\r
+      return S_FALSE;\r
+    UInt32 b = *src;\r
+    if (b > 17)\r
+    {\r
+      src++;\r
+      srcRem--;\r
+      b -= 17;\r
+      mode = (b < 4 ? 0 : 1);\r
+      if (b > srcRem || b > destRem)\r
+        return S_FALSE;\r
+      srcRem -= b;\r
+      destRem -= b;\r
+      do\r
+        *dest++ = *src++;\r
+      while (--b);\r
+    }\r
+  }\r
+\r
+  for (;;)\r
+  {\r
+    if (srcRem < 3)\r
+      return S_FALSE;\r
+    UInt32 b = *src++;\r
+    srcRem--;\r
+    UInt32 len, back;\r
+    if (b >= 64)\r
+    {\r
+      srcRem--;\r
+      back = ((b >> 2) & 7) + ((UInt32)*src++ << 3);\r
+      len = (b >> 5) + 1;\r
+    }\r
+    else if (b < 16)\r
+    {\r
+      if (mode == 2)\r
+      {\r
+        if (b == 0)\r
+        {\r
+          for (b = 15;; b += 255)\r
+          {\r
+            if (srcRem == 0)\r
+              return S_FALSE;\r
+            UInt32 b2 = *src++;\r
+            srcRem--;\r
+            if (b2 != 0)\r
+            {\r
+              b += b2;\r
+              break;\r
+            }\r
+          }\r
+        }\r
+        b += 3;\r
+        if (b > srcRem || b > destRem)\r
+          return S_FALSE;\r
+        srcRem -= b;\r
+        destRem -= b;\r
+        mode = 1;\r
+        do\r
+          *dest++ = *src++;\r
+        while (--b);\r
+        continue;\r
+      }\r
+      srcRem--;\r
+      back = (b >> 2) + (*src++ << 2);\r
+      len = 2;\r
+      if (mode == 1)\r
+      {\r
+        back += (1 << 11);\r
+        len = 3;\r
+      }\r
+    }\r
+    else\r
+    {\r
+      UInt32 bOld = b;\r
+      b = (b < 32 ? 7 : 31);\r
+      len = bOld & b;\r
+      if (len == 0)\r
+      {\r
+        for (len = b;; len += 255)\r
+        {\r
+          if (srcRem == 0)\r
+            return S_FALSE;\r
+          UInt32 b2 = *src++;\r
+          srcRem--;\r
+          if (b2 != 0)\r
+          {\r
+            len += b2;\r
+            break;\r
+          }\r
+        }\r
+      }\r
+      len += 2;\r
+      if (srcRem < 2)\r
+        return S_FALSE;\r
+      b = *src;\r
+      back = (b >> 2) + ((UInt32)src[1] << 6);\r
+      src += 2;\r
+      srcRem -= 2;\r
+      if (bOld < 32)\r
+      {\r
+        if (back == 0)\r
+        {\r
+          *destLen = dest - destStart;\r
+          *srcLen = src - srcStart;\r
+          return S_OK;\r
+        }\r
+        back += ((bOld & 8) << 11) + (1 << 14) - 1;\r
+      }\r
+    }\r
+    back++;\r
+    if (len > destRem || (size_t)(dest - destStart) < back)\r
+      return S_FALSE;\r
+    destRem -= len;\r
+    Byte *destTemp = dest - back;\r
+    dest += len;\r
+    do\r
+    {\r
+      *(destTemp + back) = *destTemp;\r
+      destTemp++;\r
+    }\r
+    while (--len);\r
+    b &= 3;\r
+    if (b == 0)\r
+    {\r
+      mode = 2;\r
+      continue;\r
+    }\r
+    if (b > srcRem || b > destRem)\r
+      return S_FALSE;\r
+    srcRem -= b;\r
+    destRem -= b;\r
+    mode = 0;\r
+    *dest++ = *src++;\r
+    if (b > 1)\r
+    {\r
+      *dest++ = *src++;\r
+      if (b > 2)\r
+        *dest++ = *src++;\r
+    }\r
+  }\r
+}\r
+\r
+HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool *outBufWasWritten, UInt32 *outBufWasWrittenSize, UInt32 inSize, UInt32 outSizeMax)\r
+{\r
+  if (outBuf)\r
+  {\r
+    *outBufWasWritten = false;\r
+    *outBufWasWrittenSize = 0;\r
+  }\r
+  UInt32 method = _h.Method;\r
+  if (_h.SeveralMethods)\r
+  {\r
+    Byte props[1];\r
+    RINOK(ReadStream_FALSE(_stream, props, 1));\r
+    method = (props[0] == 0x5D ? kMethod_LZMA : kMethod_ZLIB);\r
+    RINOK(_stream->Seek(-1, STREAM_SEEK_CUR, NULL));\r
+  }\r
+\r
+  if (method == kMethod_LZO)\r
+  {\r
+    if (_inputBuffer.GetCapacity() < inSize)\r
+    {\r
+      _inputBuffer.Free();\r
+      _inputBuffer.SetCapacity(inSize);\r
+    }\r
+    RINOK(ReadStream_FALSE(_stream, _inputBuffer, inSize));\r
+\r
+    Byte *dest = outBuf;\r
+    if (!outBuf)\r
+    {\r
+      dest = _dynOutStreamSpec->GetBufPtrForWriting(outSizeMax);\r
+      if (!dest)\r
+        return E_OUTOFMEMORY;\r
+    }\r
+    SizeT destLen = outSizeMax, srcLen = inSize;\r
+    RINOK(LzoDecode(dest, &destLen, _inputBuffer, &srcLen));\r
+    if (inSize != srcLen)\r
+      return S_FALSE;\r
+    if (outBuf)\r
+    {\r
+      *outBufWasWritten = true;\r
+      *outBufWasWrittenSize = (UInt32)destLen;\r
+    }\r
+    else\r
+      _dynOutStreamSpec->UpdateSize(destLen);\r
+  }\r
+  else if (method == kMethod_LZMA)\r
+  {\r
+    if (!_lzmaDecoder)\r
+    {\r
+      _lzmaDecoderSpec = new NCompress::NLzma::CDecoder();\r
+      _lzmaDecoderSpec->FinishStream = true;\r
+      _lzmaDecoder = _lzmaDecoderSpec;\r
+    }\r
+    const UInt32 kPropsSize = 5 + 8;\r
+    Byte props[kPropsSize];\r
+    ReadStream_FALSE(_limitedInStream, props, kPropsSize);\r
+    RINOK(_lzmaDecoderSpec->SetDecoderProperties2(props, 5));\r
+    UInt64 outSize = GetUi64(props + 5);\r
+    if (outSize > outSizeMax)\r
+      return S_FALSE;\r
+    RINOK(_lzmaDecoder->Code(_limitedInStream, outStream, NULL, &outSize, NULL));\r
+    if (inSize != kPropsSize + _lzmaDecoderSpec->GetInputProcessedSize())\r
+      return S_FALSE;\r
+  }\r
+  else\r
+  {\r
+    if (!_zlibDecoder)\r
+    {\r
+      _zlibDecoderSpec = new NCompress::NZlib::CDecoder();\r
+      _zlibDecoder = _zlibDecoderSpec;\r
+    }\r
+    RINOK(_zlibDecoder->Code(_limitedInStream, outStream, NULL, NULL, NULL));\r
+    if (inSize != _zlibDecoderSpec->GetInputProcessedSize())\r
+      return S_FALSE;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CHandler::ReadMetadataBlock(UInt32 &packSize)\r
+{\r
+  Byte temp[3];\r
+  unsigned offset = _h.NeedCheckData() ? 3 : 2;\r
+  if (offset > packSize)\r
+    return S_FALSE;\r
+  RINOK(ReadStream_FALSE(_stream, temp, offset));\r
+  // if (NeedCheckData && Major < 4) checkByte must be = 0xFF\r
+  bool be = _h.be;\r
+  UInt32 size = Get16(temp);\r
+  bool isCompressed = ((size & kNotCompressedBit16) == 0);\r
+  if (size != kNotCompressedBit16)\r
+    size &= ~kNotCompressedBit16;\r
+\r
+  if (size > kMetadataBlockSize || offset + size > packSize)\r
+    return S_FALSE;\r
+  packSize = offset + size;\r
+  if (isCompressed)\r
+  {\r
+    _limitedInStreamSpec->Init(size);\r
+    RINOK(Decompress(_dynOutStream, NULL, NULL, NULL, size, kMetadataBlockSize));\r
+  }\r
+  else\r
+  {\r
+    // size != 0 here\r
+    Byte *buf = _dynOutStreamSpec->GetBufPtrForWriting(size);\r
+    if (!buf)\r
+      return E_OUTOFMEMORY;\r
+    RINOK(ReadStream_FALSE(_stream, buf, size));\r
+    _dynOutStreamSpec->UpdateSize(size);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CHandler::ReadData(CData &data, UInt64 start, UInt64 end)\r
+{\r
+  if (end < start || end - start >= ((UInt64)1 << 32))\r
+    return S_FALSE;\r
+  UInt32 size = (UInt32)(end - start);\r
+  RINOK(_stream->Seek(start, STREAM_SEEK_SET, NULL));\r
+  _dynOutStreamSpec->Init();\r
+  UInt32 packPos = 0;\r
+  while (packPos != size)\r
+  {\r
+    data.PackPos.Add(packPos);\r
+    data.UnpackPos.Add((UInt32)_dynOutStreamSpec->GetSize());\r
+    if (packPos > size)\r
+      return S_FALSE;\r
+    UInt32 packSize = size - packPos;\r
+    RINOK(ReadMetadataBlock(packSize));\r
+    if (_dynOutStreamSpec->GetSize() >= ((UInt64)1 << 32))\r
+      return S_FALSE;\r
+    packPos += packSize;\r
+  }\r
+  data.UnpackPos.Add((UInt32)_dynOutStreamSpec->GetSize());\r
+  _dynOutStreamSpec->CopyToBuffer(data.Data);\r
+  return S_OK;\r
+}\r
+\r
+struct CTempItem\r
+{\r
+  UInt32 StartBlock;\r
+  // UInt32 iNodeNumber1;\r
+  UInt32 Offset;\r
+  // UInt16 iNodeNumber2;\r
+  UInt16 Type;\r
+};\r
+  \r
+HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned level, int &nodeIndex)\r
+{\r
+  if (level > kNumDirLevelsMax)\r
+    return S_FALSE;\r
+\r
+  int blockIndex = _inodesData.PackPos.FindInSorted(startBlock);\r
+  if (blockIndex < 0)\r
+    return S_FALSE;\r
+  UInt32 unpackPos = _inodesData.UnpackPos[blockIndex] + offset;\r
+  if (unpackPos < offset)\r
+    return S_FALSE;\r
+\r
+  nodeIndex = _nodesPos.FindInSorted(unpackPos, _blockToNode[blockIndex], _blockToNode[blockIndex + 1]);\r
+  // nodeIndex = _nodesPos.FindInSorted(unpackPos);\r
+  if (nodeIndex < 0)\r
+    return S_FALSE;\r
+  \r
+  const CNode &n = _nodes[nodeIndex];\r
+  if (!n.IsDir())\r
+    return S_OK;\r
+  blockIndex = _dirs.PackPos.FindInSorted((UInt32)n.StartBlock);\r
+  if (blockIndex < 0)\r
+    return S_FALSE;\r
+  unpackPos = _dirs.UnpackPos[blockIndex] + n.Offset;\r
+  if (unpackPos < n.Offset || unpackPos > _dirs.Data.GetCapacity())\r
+    return S_FALSE;\r
+\r
+  UInt32 rem = (UInt32)_dirs.Data.GetCapacity() - unpackPos;\r
+  const Byte *p = _dirs.Data + unpackPos;\r
+  UInt32 fileSize = (UInt32)n.FileSize;\r
+\r
+  if (fileSize > rem)\r
+    return S_FALSE;\r
+  rem = fileSize;\r
+  if (_h.Major >= 3)\r
+  {\r
+    if (rem < 3)\r
+      return S_FALSE;\r
+    rem -= 3;\r
+  }\r
+\r
+  CRecordVector<CTempItem> tempItems;\r
+  while (rem != 0)\r
+  {\r
+    bool be = _h.be;\r
+    UInt32 count;\r
+    CTempItem tempItem;\r
+    if (_h.Major <= 2)\r
+    {\r
+      if (rem < 4)\r
+        return S_FALSE;\r
+      count = p[0];\r
+      tempItem.StartBlock = Get32(p);\r
+      if (be)\r
+        tempItem.StartBlock &= 0xFFFFFF;\r
+      else\r
+        tempItem.StartBlock >>= 8;\r
+      p += 4;\r
+      rem -= 4;\r
+    }\r
+    else\r
+    {\r
+      if (_h.Major == 3)\r
+      {\r
+        if (rem < 9)\r
+          return S_FALSE;\r
+        count = p[0];\r
+        p += 1;\r
+        rem -= 1;\r
+      }\r
+      else\r
+      {\r
+        if (rem < 12)\r
+          return S_FALSE;\r
+        count = GetUi32(p);\r
+        p += 4;\r
+        rem -= 4;\r
+      }\r
+      GET_32 (0, tempItem.StartBlock);\r
+      // GET_32 (4, tempItem.iNodeNumber1);\r
+      p += 8;\r
+      rem -= 8;\r
+    }\r
+    count++;\r
+    \r
+    for (UInt32 i = 0; i < count; i++)\r
+    {\r
+      if (rem == 0)\r
+        return S_FALSE;\r
+\r
+      UInt32 nameOffset = _h.GetFileNameOffset();\r
+      if (rem < nameOffset)\r
+        return S_FALSE;\r
+\r
+      if ((UInt32)_items.Size() >= kNumFilesMax)\r
+        return S_FALSE;\r
+      if (_openCallback)\r
+      {\r
+        UInt64 numFiles = _items.Size();\r
+        if ((numFiles & 0xFFFF) == 0)\r
+        {\r
+          RINOK(_openCallback->SetCompleted(&numFiles, NULL));\r
+        }\r
+      }\r
+      \r
+      CItem item;\r
+      item.Ptr = (UInt32)(p - _dirs.Data);\r
+\r
+      UInt32 size;\r
+      if (_h.IsOldVersion())\r
+      {\r
+        UInt32 t = Get16(p);\r
+        if (be)\r
+        {\r
+          tempItem.Offset = t >> 3;\r
+          tempItem.Type = (UInt16)(t & 0x7);\r
+        }\r
+        else\r
+        {\r
+          tempItem.Offset = t & 0x1FFF;\r
+          tempItem.Type = (UInt16)(t >> 13);\r
+        }\r
+        size = (UInt32)p[2];\r
+        /*\r
+        if (_h.Major > 2)\r
+          tempItem.iNodeNumber2 = Get16(p + 3);\r
+        */\r
+      }\r
+      else\r
+      {\r
+        GET_16 (0, tempItem.Offset);\r
+        // GET_16 (2, tempItem.iNodeNumber2);\r
+        GET_16 (4, tempItem.Type);\r
+        GET_16 (6, size);\r
+      }\r
+      p += nameOffset;\r
+      rem -= nameOffset;\r
+      size++;\r
+      if (rem < size)\r
+        return S_FALSE;\r
+      p += size;\r
+      rem -= size;\r
+      item.Parent = parent;\r
+      _items.Add(item);\r
+      tempItems.Add(tempItem);\r
+    }\r
+  }\r
+\r
+  int startItemIndex = _items.Size() - tempItems.Size();\r
+  for (int i = 0; i < tempItems.Size(); i++)\r
+  {\r
+    const CTempItem &tempItem = tempItems[i];\r
+    int index = startItemIndex + i;\r
+    CItem &item = _items[index];\r
+    RINOK(OpenDir(index, tempItem.StartBlock, tempItem.Offset, level + 1, item.Node));\r
+  }\r
+\r
+  return S_OK;\r
+}\r
+\r
+/*\r
+HRESULT CHandler::ReadUids(UInt64 start, UInt32 num, CByteBuffer &ids)\r
+{\r
+  size_t size = num * 4;\r
+  ids.SetCapacity(size);\r
+  RINOK(_stream->Seek(start, STREAM_SEEK_SET, NULL));\r
+  return ReadStream_FALSE(_stream, ids, size);\r
+}\r
+*/\r
+\r
+HRESULT CHandler::Open2(IInStream *inStream)\r
+{\r
+  {\r
+    Byte buf[kHeaderSize3];\r
+    RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize3));\r
+    if (!_h.Parse(buf))\r
+      return S_FALSE;\r
+    if (!_h.IsSupported())\r
+      return E_NOTIMPL;\r
+    \r
+    switch (_h.Method)\r
+    {\r
+      case kMethod_ZLIB:\r
+      case kMethod_LZMA:\r
+      case kMethod_LZO:\r
+        break;\r
+      default:\r
+        return E_NOTIMPL;\r
+    }\r
+  }\r
+\r
+  _stream = inStream;\r
+\r
+  if (_h.NumFrags != 0)\r
+  {\r
+    if (_h.NumFrags > kNumFilesMax)\r
+      return S_FALSE;\r
+    _frags.Reserve(_h.NumFrags);\r
+    CByteBuffer data;\r
+    unsigned bigFrag = (_h.Major > 2);\r
+    \r
+    unsigned fragPtrsInBlockLog = kMetadataBlockSizeLog - (3 + bigFrag);\r
+    UInt32 numBlocks = (_h.NumFrags + (1 << fragPtrsInBlockLog) - 1) >> fragPtrsInBlockLog;\r
+    size_t numBlocksBytes = (size_t)numBlocks << (2 + bigFrag);\r
+    data.SetCapacity(numBlocksBytes);\r
+    RINOK(inStream->Seek(_h.FragTable, STREAM_SEEK_SET, NULL));\r
+    RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes));\r
+    bool be = _h.be;\r
+    \r
+    for (UInt32 i = 0; i < numBlocks; i++)\r
+    {\r
+      UInt64 offset = bigFrag ? Get64(data + i * 8) : Get32(data + i * 4);\r
+      RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL));\r
+      _dynOutStreamSpec->Init();\r
+      UInt32 packSize = kMetadataBlockSize + 3;\r
+      RINOK(ReadMetadataBlock(packSize));\r
+      UInt32 unpackSize = (UInt32)_dynOutStreamSpec->GetSize();\r
+      if (unpackSize != kMetadataBlockSize)\r
+        if (i != numBlocks - 1 || unpackSize != ((_h.NumFrags << (3 + bigFrag)) & (kMetadataBlockSize - 1)))\r
+          return S_FALSE;\r
+      const Byte *buf = _dynOutStreamSpec->GetBuffer();\r
+      for (UInt32 j = 0; j < kMetadataBlockSize && j < unpackSize;)\r
+      {\r
+        CFrag frag;\r
+        if (bigFrag)\r
+        {\r
+          frag.StartBlock = Get64(buf + j);\r
+          frag.Size = Get32(buf + j + 8);\r
+          // some archives contain nonzero in unused (buf + j + 12)\r
+          j += 16;\r
+        }\r
+        else\r
+        {\r
+          frag.StartBlock = Get32(buf + j);\r
+          frag.Size = Get32(buf + j + 4);\r
+          j += 8;\r
+        }\r
+        _frags.Add(frag);\r
+      }\r
+    }\r
+    if ((UInt32)_frags.Size() != _h.NumFrags)\r
+      return S_FALSE;\r
+  }\r
+\r
+  // RINOK(inStream->Seek(_h.InodeTable, STREAM_SEEK_SET, NULL));\r
+\r
+  RINOK(ReadData(_inodesData, _h.InodeTable, _h.DirTable));\r
+  RINOK(ReadData(_dirs, _h.DirTable, _h.FragTable));\r
+\r
+  UInt64 absOffset = _h.RootInode >> 16;\r
+  if (absOffset >= ((UInt64)1 << 32))\r
+    return S_FALSE;\r
+  {\r
+    UInt32 pos = 0;\r
+    UInt32 totalSize = (UInt32)_inodesData.Data.GetCapacity();\r
+    _nodesPos.Reserve(_h.NumInodes);\r
+    _nodes.Reserve(_h.NumInodes);\r
+    // we use _blockToNode for binary search seed optimizations\r
+    _blockToNode.Reserve(_inodesData.GetNumBlocks() + 1);\r
+    int curBlock = 0;\r
+    for (UInt32 i = 0; i < _h.NumInodes; i++)\r
+    {\r
+      CNode n;\r
+      const Byte *p = _inodesData.Data + pos;\r
+      UInt32 size = totalSize - pos;\r
+\r
+      switch(_h.Major)\r
+      {\r
+        case 1:  size = n.Parse1(p, size, _h); break;\r
+        case 2:  size = n.Parse2(p, size, _h); break;\r
+        case 3:  size = n.Parse3(p, size, _h); break;\r
+        default: size = n.Parse4(p, size, _h); break;\r
+      }\r
+      if (size == 0)\r
+        return S_FALSE;\r
+      while (pos >= _inodesData.UnpackPos[curBlock])\r
+      {\r
+        _blockToNode.Add(_nodesPos.Size());\r
+        curBlock++;\r
+      }\r
+      _nodesPos.Add(pos);\r
+      _nodes.Add(n);\r
+      pos += size;\r
+    }\r
+    _blockToNode.Add(_nodesPos.Size());\r
+    if (pos != totalSize)\r
+      return S_FALSE;\r
+  }\r
+  int rootNodeIndex;\r
+  RINOK(OpenDir(-1, (UInt32)absOffset, (UInt32)_h.RootInode & 0xFFFF, 0, rootNodeIndex));\r
+\r
+  /*\r
+  if (_h.Major < 4)\r
+  {\r
+    RINOK(ReadUids(_h.UidTable, _h.NumUids, _uids));\r
+    RINOK(ReadUids(_h.GidTable, _h.NumGids, _gids));\r
+  }\r
+  else\r
+  {\r
+    UInt32 size = _h.NumIDs * 4;\r
+    _uids.SetCapacity(size);\r
+\r
+    UInt32 numBlocks = (size + kMetadataBlockSize - 1) / kMetadataBlockSize;\r
+    UInt32 numBlocksBytes = numBlocks << 3;\r
+    CByteBuffer data;\r
+    data.SetCapacity(numBlocksBytes);\r
+    RINOK(inStream->Seek(_h.UidTable, STREAM_SEEK_SET, NULL));\r
+    RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes));\r
+\r
+    for (UInt32 i = 0; i < numBlocks; i++)\r
+    {\r
+      UInt64 offset = GetUi64(data + i * 8);\r
+      UInt32 unpackSize, packSize;\r
+      RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL));\r
+      RINOK(ReadMetadataBlock(NULL, _uids + kMetadataBlockSize * i, packSize, unpackSize));\r
+      if (unpackSize != kMetadataBlockSize)\r
+        if (i != numBlocks - 1 || unpackSize != (size & (kMetadataBlockSize - 1)))\r
+          return S_FALSE;\r
+    }\r
+  }\r
+  */\r
+\r
+  {\r
+    const UInt32 alignSize = 1 << 12;\r
+    Byte buf[alignSize];\r
+    RINOK(inStream->Seek(_h.Size, STREAM_SEEK_SET, NULL));\r
+    UInt32 rem = (UInt32)(0 - _h.Size) & (alignSize - 1);\r
+    _sizeCalculated = _h.Size;\r
+    if (rem != 0)\r
+    {\r
+      if (ReadStream_FALSE(_stream, buf, rem) == S_OK)\r
+      {\r
+        size_t i;\r
+        for (i = 0; i < rem && buf[i] == 0; i++);\r
+        if (i == rem)\r
+          _sizeCalculated = _h.Size + rem;\r
+      }\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+AString CHandler::GetPath(int index) const\r
+{\r
+  unsigned len = 0;\r
+  int indexMem = index;\r
+  bool be = _h.be;\r
+  do\r
+  {\r
+    const CItem &item = _items[index];\r
+    index = item.Parent;\r
+    const Byte *p = _dirs.Data + item.Ptr;\r
+    unsigned size = (_h.IsOldVersion() ? (unsigned)p[2] : (unsigned)Get16(p + 6)) + 1;\r
+    p += _h.GetFileNameOffset();\r
+    unsigned i;\r
+    for (i = 0; i < size && p[i]; i++);\r
+    len += i + 1;\r
+  }\r
+  while (index >= 0);\r
+  len--;\r
+\r
+  AString path;\r
+  char *dest = path.GetBuffer(len) + len;\r
+  index = indexMem;\r
+  for (;;)\r
+  {\r
+    const CItem &item = _items[index];\r
+    index = item.Parent;\r
+\r
+    const Byte *p = _dirs.Data + item.Ptr;\r
+    unsigned size = (_h.IsOldVersion() ? (unsigned)p[2] : (unsigned)Get16(p + 6)) + 1;\r
+    p += _h.GetFileNameOffset();\r
+    unsigned i;\r
+    for (i = 0; i < size && p[i]; i++);\r
+    dest -= i;\r
+    memcpy(dest, p, i);\r
+    if (index < 0)\r
+      break;\r
+    *(--dest) = CHAR_PATH_SEPARATOR;\r
+  }\r
+  path.ReleaseBuffer(len);\r
+  return path;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback)\r
+{\r
+  COM_TRY_BEGIN\r
+  {\r
+    Close();\r
+    _limitedInStreamSpec->SetStream(stream);\r
+    HRESULT res;\r
+    try\r
+    {\r
+      RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));\r
+      _openCallback = callback;\r
+      res = Open2(stream);\r
+    }\r
+    catch(...)\r
+    {\r
+      Close();\r
+      throw;\r
+    }\r
+    if (res != S_OK)\r
+    {\r
+      Close();\r
+      return res;\r
+    }\r
+    _stream = stream;\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _limitedInStreamSpec->ReleaseStream();\r
+  _stream.Release();\r
+\r
+  _items.Clear();\r
+  _nodes.Clear();\r
+  _nodesPos.Clear();\r
+  _blockToNode.Clear();\r
+  _frags.Clear();\r
+  _inodesData.Clear();\r
+  _dirs.Clear();\r
+\r
+  // _uids.Free();\r
+  // _gids.Free();;\r
+\r
+  _cachedBlock.Free();\r
+  ClearCache();\r
+\r
+  return S_OK;\r
+}\r
+\r
+bool CHandler::GetPackSize(int index, UInt64 &totalPack, bool fillOffsets)\r
+{\r
+  totalPack = 0;\r
+  const CItem &item = _items[index];\r
+  const CNode &node = _nodes[item.Node];\r
+  UInt32 ptr = _nodesPos[item.Node];\r
+  const Byte *p = _inodesData.Data + ptr;\r
+  bool be = _h.be;\r
+\r
+  UInt32 type = node.Type;\r
+  UInt32 offset;\r
+  if (node.IsLink() || node.FileSize == 0)\r
+  {\r
+    totalPack = node.FileSize;\r
+    return true;\r
+  }\r
+\r
+  UInt32 numBlocks = (UInt32)node.GetNumBlocks(_h);\r
+\r
+  if (fillOffsets)\r
+  {\r
+    _blockOffsets.Clear();\r
+    _blockCompressed.Clear();\r
+    _blockOffsets.Add(totalPack);\r
+  }\r
+\r
+  if (_h.Major <= 1)\r
+  {\r
+    offset = 15;\r
+    p += offset;\r
+    \r
+    for (UInt32 i = 0; i < numBlocks; i++)\r
+    {\r
+      UInt32 t = Get16(p + i * 2);\r
+      if (fillOffsets)\r
+        _blockCompressed.Add((t & kNotCompressedBit16) == 0);\r
+      if (t != kNotCompressedBit16)\r
+        t &= ~kNotCompressedBit16;\r
+      totalPack += t;\r
+      if (fillOffsets)\r
+        _blockOffsets.Add(totalPack);\r
+    }\r
+  }\r
+  else\r
+  {\r
+    if (_h.Major <= 2)\r
+      offset = 24;\r
+    else if (type == kType_FILE)\r
+      offset = 32;\r
+    else if (type == kType_FILE + 7)\r
+      offset = (_h.Major <= 3 ? 40 : 56);\r
+    else\r
+      return false;\r
+    \r
+    p += offset;\r
+    \r
+    for (UInt64 i = 0; i < numBlocks; i++)\r
+    {\r
+      UInt32 t = Get32(p + i * 4);\r
+      if (fillOffsets)\r
+        _blockCompressed.Add(IS_COMPRESSED_BLOCK(t));\r
+      UInt32 size = GET_COMPRESSED_BLOCK_SIZE(t);\r
+      if (size > _h.BlockSize)\r
+        return false;\r
+      totalPack += size;\r
+      if (fillOffsets)\r
+        _blockOffsets.Add(totalPack);\r
+    }\r
+\r
+    if (node.ThereAreFrags())\r
+    {\r
+      if (node.Frag >= (UInt32)_frags.Size())\r
+        return false;\r
+      const CFrag &frag = _frags[node.Frag];\r
+      if (node.Offset == 0)\r
+      {\r
+        UInt32 size = GET_COMPRESSED_BLOCK_SIZE(frag.Size);\r
+        if (size > _h.BlockSize)\r
+          return false;\r
+        totalPack += size;\r
+      }\r
+    }\r
+  }\r
+  return true;\r
+}\r
+\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _items.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidMethod:\r
+    {\r
+      const char *s;\r
+      if (_h.SeveralMethods)\r
+        s = "LZMA ZLIB";\r
+      else\r
+      {\r
+        s = k_Methods[0];\r
+        if (_h.Method < sizeof(k_Methods) / sizeof(k_Methods[0]))\r
+          s = k_Methods[_h.Method];\r
+      }\r
+      prop = s;\r
+      break;\r
+    }\r
+    case kpidFileSystem:\r
+    {\r
+      AString res = "SquashFS";\r
+      if (_h.SeveralMethods)\r
+        res += "-LZMA";\r
+      res += ' ';\r
+      char s[16];\r
+      ConvertUInt32ToString(_h.Major, s);\r
+      res += s;\r
+      res += '.';\r
+      ConvertUInt32ToString(_h.Minor, s);\r
+      res += s;\r
+      prop = res;\r
+      break;\r
+    }\r
+    case kpidBlock: prop = _h.BlockSize; break;\r
+    case kpidBigEndian: prop = _h.be; break;\r
+    case kpidCTime:\r
+      if (_h.CTime != 0)\r
+      {\r
+        FILETIME ft;\r
+        NWindows::NTime::UnixTimeToFileTime(_h.CTime, ft);\r
+        prop = ft;\r
+      }\r
+      break;\r
+    case kpidCharacts: FLAGS_TO_PROP(k_Flags, _h.Flags, prop); break;\r
+    // case kpidNumBlocks: prop = _h.NumFrags; break;\r
+    case kpidPhySize: prop = _sizeCalculated; break;\r
+    case kpidHeadersSize:\r
+      if (_sizeCalculated >= _h.InodeTable)\r
+        prop = _sizeCalculated - _h.InodeTable;\r
+      break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  const CItem &item = _items[index];\r
+  const CNode &node = _nodes[item.Node];\r
+  bool isDir = node.IsDir();\r
+  bool be = _h.be;\r
+\r
+  switch(propID)\r
+  {\r
+    case kpidPath: prop = MultiByteToUnicodeString(GetPath(index), CP_OEMCP); break;\r
+    case kpidIsDir: prop = isDir; break;\r
+    // case kpidOffset: if (!node.IsLink()) prop = (UInt64)node.StartBlock; break;\r
+    case kpidSize: if (!isDir) prop = node.GetSize(); break;\r
+    case kpidPackSize:\r
+      if (!isDir)\r
+      {\r
+        UInt64 size;\r
+        if (GetPackSize(index, size, false))\r
+          prop = size;\r
+      }\r
+      break;\r
+    case kpidMTime:\r
+    {\r
+      UInt32 offset = 0;\r
+      switch(_h.Major)\r
+      {\r
+        case 1:\r
+          if (node.Type == kType_FILE)\r
+            offset = 3;\r
+          else if (node.Type == kType_DIR)\r
+            offset = 7;\r
+          break;\r
+        case 2:\r
+          if (node.Type == kType_FILE)\r
+            offset = 4;\r
+          else if (node.Type == kType_DIR)\r
+            offset = 8;\r
+          else if (node.Type == kType_DIR + 7)\r
+            offset = 9;\r
+          break;\r
+        case 3: offset = 4; break;\r
+        case 4: offset = 8; break;\r
+      }\r
+      if (offset != 0)\r
+      {\r
+        const Byte *p = _inodesData.Data + _nodesPos[item.Node] + offset;\r
+        FILETIME ft;\r
+        NWindows::NTime::UnixTimeToFileTime(Get32(p), ft);\r
+        prop = ft;\r
+      }\r
+      break;\r
+    }\r
+    case kpidPosixAttrib:\r
+    {\r
+      if (node.Type != 0 && node.Type < sizeof(k_TypeToMode) / sizeof(k_TypeToMode[0]))\r
+        prop = (UInt32)(node.Mode & 0xFFF) | k_TypeToMode[node.Type];\r
+      break;\r
+    }\r
+    /*\r
+    case kpidUser:\r
+    {\r
+      UInt32 offset = node.Uid * 4;\r
+      if (offset < _uids.GetCapacity())\r
+        prop = (UInt32)Get32(_uids + offset);\r
+      break;\r
+    }\r
+    case kpidGroup:\r
+    {\r
+      if (_h.Major == 4 || node.Gid == _h.GetSpecGuidIndex())\r
+      {\r
+        UInt32 offset = node.Uid * 4;\r
+        if (offset < _uids.GetCapacity())\r
+          prop = (UInt32)Get32(_uids + offset);\r
+      }\r
+      else\r
+      {\r
+        UInt32 offset = node.Gid * 4;\r
+        if (offset < _gids.GetCapacity())\r
+          prop = (UInt32)Get32(_gids + offset);\r
+      }\r
+      break;\r
+    }\r
+    */\r
+    /*\r
+    case kpidLinks:\r
+      if (_h.Major >= 3 && node.Type != kType_FILE)\r
+        prop = node.NumLinks;\r
+      break;\r
+    */\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+class CSquashfsInStream: public CCachedInStream\r
+{\r
+  HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize);\r
+public:\r
+  CHandler *Handler;\r
+};\r
+\r
+HRESULT CSquashfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)\r
+{\r
+  return Handler->ReadBlock(blockIndex, dest, blockSize);\r
+}\r
+\r
+HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)\r
+{\r
+  const CNode &node = _nodes[_nodeIndex];\r
+  UInt64 blockOffset;\r
+  UInt32 packBlockSize;\r
+  UInt32 offsetInBlock = 0;\r
+  bool compressed;\r
+  if (blockIndex < _blockCompressed.Size())\r
+  {\r
+    compressed = _blockCompressed[(int)blockIndex];\r
+    blockOffset = _blockOffsets[(int)blockIndex];\r
+    packBlockSize = (UInt32)(_blockOffsets[(int)blockIndex + 1] - blockOffset);\r
+    blockOffset += node.StartBlock;\r
+  }\r
+  else\r
+  {\r
+    if (!node.ThereAreFrags())\r
+      return S_FALSE;\r
+    const CFrag &frag = _frags[node.Frag];\r
+    offsetInBlock = node.Offset;\r
+    blockOffset = frag.StartBlock;\r
+    packBlockSize = GET_COMPRESSED_BLOCK_SIZE(frag.Size);\r
+    compressed = IS_COMPRESSED_BLOCK(frag.Size);\r
+  }\r
+\r
+  if (packBlockSize == 0)\r
+  {\r
+    // sparse file ???\r
+    memset(dest, 0, blockSize);\r
+    return S_OK;\r
+  }\r
+\r
+  if (blockOffset != _cachedBlockStartPos ||\r
+      packBlockSize != _cachedPackBlockSize)\r
+  {\r
+    ClearCache();\r
+    RINOK(_stream->Seek(blockOffset, STREAM_SEEK_SET, NULL));\r
+    _limitedInStreamSpec->Init(packBlockSize);\r
+    \r
+    if (compressed)\r
+    {\r
+      _outStreamSpec->Init((Byte *)_cachedBlock, _h.BlockSize);\r
+      bool outBufWasWritten;\r
+      UInt32 outBufWasWrittenSize;\r
+      HRESULT res = Decompress(_outStream, _cachedBlock, &outBufWasWritten, &outBufWasWrittenSize, packBlockSize, _h.BlockSize);\r
+      if (outBufWasWritten)\r
+        _cachedUnpackBlockSize = outBufWasWrittenSize;\r
+      else\r
+        _cachedUnpackBlockSize = (UInt32)_outStreamSpec->GetPos();\r
+      RINOK(res);\r
+    }\r
+    else\r
+    {\r
+      RINOK(ReadStream_FALSE(_limitedInStream, _cachedBlock, packBlockSize));\r
+      _cachedUnpackBlockSize = packBlockSize;\r
+    }\r
+    _cachedBlockStartPos = blockOffset;\r
+    _cachedPackBlockSize = packBlockSize;\r
+  }\r
+  if (offsetInBlock + blockSize > _cachedUnpackBlockSize)\r
+    return S_FALSE;\r
+  memcpy(dest, _cachedBlock + offsetInBlock, blockSize);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _items.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt64 totalSize = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    const CItem &item = _items[allFilesMode ? i : indices[i]];\r
+    const CNode &node = _nodes[item.Node];\r
+    totalSize += node.GetSize();\r
+  }\r
+  extractCallback->SetTotal(totalSize);\r
+\r
+  UInt64 totalPackSize;\r
+  totalSize = totalPackSize = 0;\r
+  \r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    lps->InSize = totalPackSize;\r
+    lps->OutSize = totalSize;\r
+    RINOK(lps->SetCur());\r
+    CMyComPtr<ISequentialOutStream> outStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    UInt32 index = allFilesMode ? i : indices[i];\r
+    const CItem &item = _items[index];\r
+    const CNode &node = _nodes[item.Node];\r
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));\r
+    // const Byte *p = _data + item.Offset;\r
+\r
+    if (node.IsDir())\r
+    {\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+      continue;\r
+    }\r
+    UInt64 unpackSize = node.GetSize();\r
+    totalSize += unpackSize;\r
+    UInt64 packSize;\r
+    if (GetPackSize(index, packSize, false))\r
+      totalPackSize += packSize;\r
+\r
+    if (!testMode && !outStream)\r
+      continue;\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+\r
+    int res = NExtract::NOperationResult::kDataError;\r
+    {\r
+      CMyComPtr<ISequentialInStream> inSeqStream;\r
+      CMyComPtr<IInStream> inStream;\r
+      HRESULT hres = GetStream(index, &inSeqStream);\r
+      if (inSeqStream)\r
+        inSeqStream.QueryInterface(IID_IInStream, &inStream);\r
+      if (hres == S_FALSE || !inStream)\r
+      {\r
+        if (hres == E_OUTOFMEMORY)\r
+          return hres;\r
+        res = NExtract::NOperationResult::kUnSupportedMethod;\r
+      }\r
+      else\r
+      {\r
+        RINOK(hres);\r
+        if (inStream)\r
+        {\r
+          HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress);\r
+          if (hres != S_OK &&  hres != S_FALSE)\r
+          {\r
+            RINOK(hres);\r
+          }\r
+          if (copyCoderSpec->TotalSize == unpackSize && hres == S_OK)\r
+            res = NExtract::NOperationResult::kOK;\r
+          else\r
+          {\r
+            res = res;\r
+          }\r
+        }\r
+      }\r
+    }\r
+    RINOK(extractCallback->SetOperationResult(res));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+\r
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)\r
+{\r
+  COM_TRY_BEGIN\r
+\r
+  const CItem &item = _items[index];\r
+  const CNode &node = _nodes[item.Node];\r
+\r
+  if (node.IsDir())\r
+    return E_FAIL;\r
+\r
+  const Byte *p = _inodesData.Data + _nodesPos[item.Node];\r
+\r
+  if (node.FileSize == 0 || node.IsLink())\r
+  {\r
+    CBufInStream *streamSpec = new CBufInStream;\r
+    CMyComPtr<IInStream> streamTemp = streamSpec;\r
+    if (node.IsLink())\r
+      streamSpec->Init(p + _h.GetSymLinkOffset(), (size_t)node.FileSize);\r
+    else\r
+      streamSpec->Init(NULL, 0);\r
+    *stream = streamTemp.Detach();\r
+    return S_OK;\r
+  }\r
+\r
+  UInt64 packSize;\r
+  if (!GetPackSize(index, packSize, true))\r
+    return S_FALSE;\r
+\r
+  _nodeIndex = item.Node;\r
+\r
+  size_t cacheSize = _h.BlockSize;\r
+  if (_cachedBlock.GetCapacity() != cacheSize)\r
+  {\r
+    ClearCache();\r
+    _cachedBlock.SetCapacity(cacheSize);\r
+  }\r
+\r
+  CSquashfsInStream *streamSpec = new CSquashfsInStream;\r
+  CMyComPtr<IInStream> streamTemp = streamSpec;\r
+  streamSpec->Handler = this;\r
+  unsigned cacheSizeLog = 22;\r
+  if (cacheSizeLog <= _h.BlockSizeLog)\r
+    cacheSizeLog = _h.BlockSizeLog + 1;\r
+  if (!streamSpec->Alloc(_h.BlockSizeLog, cacheSizeLog - _h.BlockSizeLog))\r
+    return E_OUTOFMEMORY;\r
+  streamSpec->Init(node.FileSize);\r
+  *stream = streamTemp.Detach();\r
+\r
+  return S_OK;\r
+\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new NArchive::NSquashfs::CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"SquashFS", L"squashfs", 0, 0xD2, SIGNATURE, kSignatureSize, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Cramfs)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/StdAfx.h b/CPP/7zip/Archive/StdAfx.h
new file mode 100755 (executable)
index 0000000..f56e92f
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../Common/MyWindows.h"\r
+#include "../../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/SwfHandler.cpp b/CPP/7zip/Archive/SwfHandler.cpp
new file mode 100755 (executable)
index 0000000..398aa0f
--- /dev/null
@@ -0,0 +1,706 @@
+// SwfHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/Buffer.h"\r
+#include "Common/ComTry.h"\r
+#include "Common/IntToString.h"\r
+#include "Common/MyString.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../Common/InBuffer.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/CopyCoder.h"\r
+#include "../Compress/ZlibDecoder.h"\r
+#include "../Compress/ZlibEncoder.h"\r
+\r
+#include "Common/DummyOutStream.h"\r
+\r
+#include "DeflateProps.h"\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace NSwfc {\r
+\r
+static const UInt32 kHeaderSize = 8;\r
+\r
+static const Byte SWF_UNCOMPRESSED = 'F';\r
+static const Byte SWF_COMPRESSED = 'C';\r
+static const Byte SWF_MIN_COMPRESSED_VER = 6;\r
+\r
+struct CItem\r
+{\r
+  Byte Buf[kHeaderSize];\r
+\r
+  UInt32 GetSize() const { return GetUi32(Buf + 4); }\r
+  bool IsSwf(Byte c) const { return (Buf[0] == c && Buf[1] == 'W' && Buf[2] == 'S' && Buf[3] < 32); }\r
+  bool IsUncompressed() const { return IsSwf(SWF_UNCOMPRESSED); }\r
+  bool IsCompressed() const { return IsSwf(SWF_COMPRESSED); }\r
+\r
+  void MakeUncompressed() { Buf[0] = SWF_UNCOMPRESSED; }\r
+  void MakeCompressed()\r
+  {\r
+    Buf[0] = SWF_COMPRESSED;\r
+    if (Buf[3] < SWF_MIN_COMPRESSED_VER)\r
+      Buf[3] = SWF_MIN_COMPRESSED_VER;\r
+  }\r
+\r
+  HRESULT ReadHeader(ISequentialInStream *stream) { return ReadStream_FALSE(stream, Buf, kHeaderSize); }\r
+  HRESULT WriteHeader(ISequentialOutStream *stream) { return WriteStream(stream, Buf, kHeaderSize); }\r
+};\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IArchiveOpenSeq,\r
+  public IOutArchive,\r
+  public ISetProperties,\r
+  public CMyUnknownImp\r
+{\r
+  CItem _item;\r
+  UInt64 _packSize;\r
+  bool _packSizeDefined;\r
+  CMyComPtr<ISequentialInStream> _seqStream;\r
+  CMyComPtr<IInStream> _stream;\r
+\r
+  CDeflateProps _method;\r
+\r
+public:\r
+  MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties)\r
+  INTERFACE_IInArchive(;)\r
+  INTERFACE_IOutArchive(;)\r
+  STDMETHOD(OpenSeq)(ISequentialInStream *stream);\r
+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);\r
+};\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps_NO_Table\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = 1;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)\r
+{\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidSize: prop = (UInt64)_item.GetSize(); break;\r
+    case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *)\r
+{\r
+  RINOK(OpenSeq(stream));\r
+  _stream = stream;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)\r
+{\r
+  Close();\r
+  HRESULT res = _item.ReadHeader(stream);\r
+  if (res == S_OK)\r
+    if (_item.IsCompressed())\r
+      _seqStream = stream;\r
+    else\r
+      res = S_FALSE;\r
+  return res;\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _packSizeDefined = false;\r
+  _seqStream.Release();\r
+  _stream.Release();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))\r
+    return E_INVALIDARG;\r
+\r
+  extractCallback->SetTotal(_item.GetSize());\r
+  CMyComPtr<ISequentialOutStream> realOutStream;\r
+  Int32 askMode = testMode ?\r
+      NExtract::NAskMode::kTest :\r
+      NExtract::NAskMode::kExtract;\r
+  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));\r
+  if (!testMode && !realOutStream)\r
+    return S_OK;\r
+\r
+  extractCallback->PrepareOperation(askMode);\r
+\r
+  NCompress::NZlib::CDecoder *_decoderSpec = new NCompress::NZlib::CDecoder;\r
+  CMyComPtr<ICompressCoder> _decoder = _decoderSpec;\r
+\r
+  CDummyOutStream *outStreamSpec = new CDummyOutStream;\r
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\r
+  outStreamSpec->SetStream(realOutStream);\r
+  outStreamSpec->Init();\r
+  realOutStream.Release();\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  lps->InSize = kHeaderSize;\r
+  lps->OutSize = outStreamSpec->GetSize();\r
+  RINOK(lps->SetCur());\r
+  \r
+  CItem item = _item;\r
+  item.MakeUncompressed();\r
+  RINOK(item.WriteHeader(outStream));\r
+  if (_stream)\r
+    RINOK(_stream->Seek(kHeaderSize, STREAM_SEEK_SET, NULL));\r
+  HRESULT result = _decoderSpec->Code(_seqStream, outStream, NULL, NULL, progress);\r
+  Int32 opRes = NExtract::NOperationResult::kDataError;\r
+  if (result == S_OK)\r
+  {\r
+    if (_item.GetSize() == outStreamSpec->GetSize())\r
+    {\r
+      _packSizeDefined = true;\r
+      _packSize = _decoderSpec->GetInputProcessedSize() + kHeaderSize;\r
+      opRes = NExtract::NOperationResult::kOK;\r
+    }\r
+  }\r
+  else if (result != S_FALSE)\r
+    return result;\r
+\r
+  outStream.Release();\r
+  return extractCallback->SetOperationResult(opRes);\r
+  COM_TRY_END\r
+}\r
+\r
+static HRESULT UpdateArchive(ISequentialOutStream *outStream,\r
+    UInt64 size, CDeflateProps &deflateProps,\r
+    IArchiveUpdateCallback *updateCallback)\r
+{\r
+  UInt64 complexity = 0;\r
+  RINOK(updateCallback->SetTotal(size));\r
+  RINOK(updateCallback->SetCompleted(&complexity));\r
+\r
+  CMyComPtr<ISequentialInStream> fileInStream;\r
+  RINOK(updateCallback->GetStream(0, &fileInStream));\r
+\r
+  CItem item;\r
+  HRESULT res = item.ReadHeader(fileInStream);\r
+  if (res == S_FALSE)\r
+    return E_INVALIDARG;\r
+  RINOK(res);\r
+  if (!item.IsUncompressed() || size != item.GetSize())\r
+    return E_INVALIDARG;\r
+\r
+  item.MakeCompressed();\r
+  item.WriteHeader(outStream);\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(updateCallback, true);\r
+  \r
+  NCompress::NZlib::CEncoder *encoderSpec = new NCompress::NZlib::CEncoder;\r
+  CMyComPtr<ICompressCoder> encoder = encoderSpec;\r
+  encoderSpec->Create();\r
+  RINOK(deflateProps.SetCoderProperties(encoderSpec->DeflateEncoderSpec));\r
+  RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, progress));\r
+  if (encoderSpec->GetInputProcessedSize() + kHeaderSize != size)\r
+    return E_INVALIDARG;\r
+  return updateCallback->SetOperationResult(NUpdate::NOperationResult::kOK);\r
+}\r
+\r
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)\r
+{\r
+  *timeType = NFileTimeType::kUnix;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\r
+    IArchiveUpdateCallback *updateCallback)\r
+{\r
+  if (numItems != 1)\r
+    return E_INVALIDARG;\r
+\r
+  Int32 newData, newProps;\r
+  UInt32 indexInArchive;\r
+  if (!updateCallback)\r
+    return E_FAIL;\r
+  RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));\r
+\r
+  if (IntToBool(newProps))\r
+  {\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));\r
+      if (prop.vt == VT_BOOL)\r
+      {\r
+        if (prop.boolVal != VARIANT_FALSE)\r
+          return E_INVALIDARG;\r
+      }\r
+      else if (prop.vt != VT_EMPTY)\r
+        return E_INVALIDARG;\r
+    }\r
+  }\r
+\r
+  if (IntToBool(newData))\r
+  {\r
+    UInt64 size;\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      RINOK(updateCallback->GetProperty(0, kpidSize, &prop));\r
+      if (prop.vt != VT_UI8)\r
+        return E_INVALIDARG;\r
+      size = prop.uhVal.QuadPart;\r
+    }\r
+    return UpdateArchive(outStream, size, _method, updateCallback);\r
+  }\r
+    \r
+  if (indexInArchive != 0)\r
+    return E_INVALIDARG;\r
+\r
+  if (!_seqStream)\r
+    return E_NOTIMPL;\r
+\r
+  if (_stream)\r
+  {\r
+    RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));\r
+  }\r
+  else\r
+    _item.WriteHeader(outStream);\r
+  return NCompress::CopyStream(_seqStream, outStream, NULL);\r
+}\r
+\r
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)\r
+{\r
+  return _method.SetProperties(names, values, numProps);\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+#ifndef EXTRACT_ONLY\r
+static IOutArchive *CreateArcOut() { return new CHandler; }\r
+#else\r
+#define CreateArcOut 0\r
+#endif\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"SWFc", L"swf", L"~.swf", 0xD8, { 'C', 'W', 'S' }, 3, true, CreateArc, CreateArcOut };\r
+\r
+REGISTER_ARC(Swfc)\r
+\r
+}\r
+\r
+namespace NSwf {\r
+\r
+static const UInt32 kFileSizeMax = (UInt32)1 << 30;\r
+static const int kNumTagsMax = (UInt32)1 << 23;\r
+\r
+struct CTag\r
+{\r
+  UInt32 Type;\r
+  CByteBuffer Buf;\r
+};\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IArchiveOpenSeq,\r
+  public CMyUnknownImp\r
+{\r
+  CObjectVector<CTag> _tags;\r
+  NSwfc::CItem _item;\r
+  UInt64 _packSize;\r
+\r
+  HRESULT OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *callback);\r
+  HRESULT OpenSeq2(ISequentialInStream *stream, IArchiveOpenCallback *callback);\r
+public:\r
+  MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq)\r
+  INTERFACE_IInArchive(;)\r
+\r
+  STDMETHOD(OpenSeq)(ISequentialInStream *stream);\r
+};\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidComment, VT_BSTR}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps_NO_Table\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidPhySize: prop = _packSize; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _tags.Size();\r
+  return S_OK;\r
+}\r
+\r
+static const char *g_TagDesc[92] =\r
+{\r
+  "End",\r
+  "ShowFrame",\r
+  "DefineShape",\r
+  NULL,\r
+  "PlaceObject",\r
+  "RemoveObject",\r
+  "DefineBits",\r
+  "DefineButton",\r
+  "JPEGTables",\r
+  "SetBackgroundColor",\r
+  "DefineFont",\r
+  "DefineText",\r
+  "DoAction",\r
+  "DefineFontInfo",\r
+  "DefineSound",\r
+  "StartSound",\r
+  NULL,\r
+  "DefineButtonSound",\r
+  "SoundStreamHead",\r
+  "SoundStreamBlock",\r
+  "DefineBitsLossless",\r
+  "DefineBitsJPEG2",\r
+  "DefineShape2",\r
+  "DefineButtonCxform",\r
+  "Protect",\r
+  NULL,\r
+  "PlaceObject2",\r
+  NULL,\r
+  "RemoveObject2",\r
+  NULL,\r
+  NULL,\r
+  NULL,\r
+  "DefineShape3",\r
+  "DefineText2",\r
+  "DefineButton2",\r
+  "DefineBitsJPEG3",\r
+  "DefineBitsLossless2",\r
+  "DefineEditText",\r
+  NULL,\r
+  "DefineSprite",\r
+  NULL,\r
+  "41",\r
+  NULL,\r
+  "FrameLabel",\r
+  NULL,\r
+  "SoundStreamHead2",\r
+  "DefineMorphShape",\r
+  NULL,\r
+  "DefineFont2",\r
+  NULL,\r
+  NULL,\r
+  NULL,\r
+  NULL,\r
+  NULL,\r
+  NULL,\r
+  NULL,\r
+  "ExportAssets",\r
+  "ImportAssets",\r
+  "EnableDebugger",\r
+  "DoInitAction",\r
+  "DefineVideoStream",\r
+  "VideoFrame",\r
+  "DefineFontInfo2",\r
+  NULL,\r
+  "EnableDebugger2",\r
+  "ScriptLimits",\r
+  "SetTabIndex",\r
+  NULL,\r
+  NULL,\r
+  "FileAttributes",\r
+  "PlaceObject3",\r
+  "ImportAssets2",\r
+  NULL,\r
+  "DefineFontAlignZones",\r
+  "CSMTextSettings",\r
+  "DefineFont3",\r
+  "SymbolClass",\r
+  "Metadata",\r
+  "DefineScalingGrid",\r
+  NULL,\r
+  NULL,\r
+  NULL,\r
+  "DoABC",\r
+  "DefineShape4",\r
+  "DefineMorphShape2",\r
+  NULL,\r
+  "DefineSceneAndFrameLabelData",\r
+  "DefineBinaryData",\r
+  "DefineFontName",\r
+  "StartSound2",\r
+  "DefineBitsJPEG4",\r
+  "DefineFont4"\r
+};\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  NWindows::NCOM::CPropVariant prop;\r
+  const CTag &tag = _tags[index];\r
+  switch(propID)\r
+  {\r
+    case kpidPath:\r
+    {\r
+      char s[32];\r
+      ConvertUInt32ToString(index, s);\r
+      size_t i = strlen(s);\r
+      s[i++] = '.';\r
+      ConvertUInt32ToString(tag.Type, s + i);\r
+      prop = s;\r
+      break;\r
+    }\r
+    case kpidSize:\r
+    case kpidPackSize:\r
+      prop = (UInt64)tag.Buf.GetCapacity(); break;\r
+    case kpidComment:\r
+      if (tag.Type < sizeof(g_TagDesc) / sizeof(g_TagDesc[0]))\r
+      {\r
+        const char *s = g_TagDesc[tag.Type];\r
+        if (s != NULL)\r
+          prop = s;\r
+      }\r
+      break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback)\r
+{\r
+  return OpenSeq2(stream, callback);\r
+}\r
+\r
+static UInt16 Read16(CInBuffer &stream)\r
+{\r
+  UInt16 res = 0;\r
+  for (int i = 0; i < 2; i++)\r
+  {\r
+    Byte b;\r
+    if (!stream.ReadByte(b))\r
+      throw 1;\r
+    res |= (UInt16)b << (i * 8);\r
+  }\r
+  return res;\r
+}\r
+\r
+static UInt32 Read32(CInBuffer &stream)\r
+{\r
+  UInt32 res = 0;\r
+  for (int i = 0; i < 4; i++)\r
+  {\r
+    Byte b;\r
+    if (!stream.ReadByte(b))\r
+      throw 1;\r
+    res |= (UInt32)b << (i * 8);\r
+  }\r
+  return res;\r
+}\r
+\r
+struct CBitReader\r
+{\r
+  CInBuffer *stream;\r
+  unsigned NumBits;\r
+  Byte Val;\r
+\r
+  CBitReader(): NumBits(0), Val(0) {}\r
+\r
+  UInt32 ReadBits(unsigned numBits);\r
+};\r
+\r
+UInt32 CBitReader::ReadBits(unsigned numBits)\r
+{\r
+  UInt32 res = 0;\r
+  while (numBits > 0)\r
+  {\r
+    if (NumBits == 0)\r
+    {\r
+      Val = stream->ReadByte();\r
+      NumBits = 8;\r
+    }\r
+    if (numBits <= NumBits)\r
+    {\r
+      res <<= numBits;\r
+      NumBits -= numBits;\r
+      res |= (Val >> NumBits);\r
+      Val &= (1 << NumBits) - 1;\r
+      break;\r
+    }\r
+    else\r
+    {\r
+      res <<= NumBits;\r
+      res |= Val;\r
+      numBits -= NumBits;\r
+      NumBits = 0;\r
+    }\r
+  }\r
+  return res;\r
+}\r
+\r
+HRESULT CHandler::OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *callback)\r
+{\r
+  RINOK(_item.ReadHeader(stream))\r
+  if (!_item.IsUncompressed())\r
+    return S_FALSE;\r
+  \r
+  CInBuffer s;\r
+  if (!s.Create(1 << 20))\r
+    return E_OUTOFMEMORY;\r
+  s.SetStream(stream);\r
+  s.Init();\r
+  {\r
+    CBitReader br;\r
+    br.stream = &s;\r
+    unsigned numBits = br.ReadBits(5);\r
+    /* UInt32 xMin = */ br.ReadBits(numBits);\r
+    /* UInt32 xMax = */ br.ReadBits(numBits);\r
+    /* UInt32 yMin = */ br.ReadBits(numBits);\r
+    /* UInt32 yMax = */ br.ReadBits(numBits);\r
+  }\r
+  /* UInt32 frameDelay = */ Read16(s);\r
+  /* UInt32 numFrames =  */ Read16(s);\r
+\r
+  _tags.Clear();\r
+  UInt64 offsetPrev = 0;\r
+  for (;;)\r
+  {\r
+    UInt32 pair = Read16(s);\r
+    UInt32 type = pair >> 6;\r
+    UInt32 length = pair & 0x3F;\r
+    if (length == 0x3F)\r
+      length = Read32(s);\r
+    if (type == 0)\r
+      break;\r
+    UInt64 offset = s.GetProcessedSize() + NSwfc::kHeaderSize + length;\r
+    if (offset > kFileSizeMax || _tags.Size() >= kNumTagsMax)\r
+      return S_FALSE;\r
+    _tags.Add(CTag());\r
+    CTag &tag = _tags.Back();\r
+    tag.Type = type;\r
+    tag.Buf.SetCapacity(length);\r
+    if (s.ReadBytes(tag.Buf, length) != length)\r
+      return S_FALSE;\r
+    if (callback && offset >= offsetPrev + (1 << 20))\r
+    {\r
+      UInt64 numItems = _tags.Size();\r
+      RINOK(callback->SetCompleted(&numItems, &offset));\r
+      offsetPrev = offset;\r
+    }\r
+  }\r
+  _packSize = s.GetProcessedSize() + NSwfc::kHeaderSize;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CHandler::OpenSeq2(ISequentialInStream *stream, IArchiveOpenCallback *callback)\r
+{\r
+  HRESULT res;\r
+  try { res = OpenSeq3(stream, callback); }\r
+  catch(...) { res = S_FALSE; }\r
+  return res;\r
+}\r
+\r
+STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)\r
+{\r
+  return OpenSeq2(stream, NULL);\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _tags.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt64 totalSize = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+    totalSize += _tags[allFilesMode ? i : indices[i]].Buf.GetCapacity();\r
+  extractCallback->SetTotal(totalSize);\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  totalSize = 0;\r
+\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    lps->InSize = lps->OutSize = totalSize;\r
+    RINOK(lps->SetCur());\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    UInt32 index = allFilesMode ? i : indices[i];\r
+    const CByteBuffer &buf = _tags[index].Buf;\r
+    totalSize += buf.GetCapacity();\r
+\r
+    CMyComPtr<ISequentialOutStream> outStream;\r
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));\r
+    if (!testMode && !outStream)\r
+      continue;\r
+      \r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+    if (outStream)\r
+      RINOK(WriteStream(outStream, buf, buf.GetCapacity()));\r
+    outStream.Release();\r
+    RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"SWF", L"swf", 0, 0xD7, { 'F', 'W', 'S' }, 3, true, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Swf)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Tar/StdAfx.h b/CPP/7zip/Archive/Tar/StdAfx.h
new file mode 100755 (executable)
index 0000000..a4e6173
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+#include "../../../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp
new file mode 100755 (executable)
index 0000000..a0a19a3
--- /dev/null
@@ -0,0 +1,386 @@
+// TarHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../../Common/LimitedStreams.h"\r
+#include "../../Common/ProgressUtils.h"\r
+#include "../../Common/StreamObjects.h"\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "../Common/ItemNameUtils.h"\r
+\r
+#include "TarHandler.h"\r
+#include "TarIn.h"\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace NTar {\r
+\r
+static const char *kUnexpectedEnd = "Unexpected end of archive";\r
+\r
+static const STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidIsDir, VT_BOOL},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidPosixAttrib, VT_UI4},\r
+  { NULL, kpidUser, VT_BSTR},\r
+  { NULL, kpidGroup, VT_BSTR},\r
+  { NULL, kpidLink, VT_BSTR}\r
+};\r
+\r
+static const STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidPhySize, VT_UI8},\r
+  { NULL, kpidHeadersSize, VT_UI8}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidPhySize: if (_phySizeDefined) prop = _phySize; break;\r
+    case kpidHeadersSize: if (_phySizeDefined) prop = _headersSize; break;\r
+    case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CHandler::ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &item)\r
+{\r
+  item.HeaderPos = _phySize;\r
+  RINOK(ReadItem(stream, filled, item, _errorMessage));\r
+  _phySize += item.HeaderSize;\r
+  _headersSize += item.HeaderSize;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)\r
+{\r
+  UInt64 endPos = 0;\r
+  {\r
+    RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));\r
+    RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));\r
+  }\r
+  \r
+  _phySizeDefined = true;\r
+  for (;;)\r
+  {\r
+    CItemEx item;\r
+    bool filled;\r
+    RINOK(ReadItem2(stream, filled, item));\r
+    if (!filled)\r
+      break;\r
+    _items.Add(item);\r
+    \r
+    RINOK(stream->Seek(item.GetPackSize(), STREAM_SEEK_CUR, &_phySize));\r
+    if (_phySize > endPos)\r
+    {\r
+      _errorMessage = kUnexpectedEnd;\r
+      break;\r
+    }\r
+    /*\r
+    if (_phySize == endPos)\r
+    {\r
+      _errorMessage = "There are no trailing zero-filled records";\r
+      break;\r
+    }\r
+    */\r
+    if (callback != NULL)\r
+    {\r
+      if (_items.Size() == 1)\r
+      {\r
+        RINOK(callback->SetTotal(NULL, &endPos));\r
+      }\r
+      if (_items.Size() % 100 == 0)\r
+      {\r
+        UInt64 numFiles = _items.Size();\r
+        RINOK(callback->SetCompleted(&numFiles, &_phySize));\r
+      }\r
+    }\r
+  }\r
+\r
+  if (_items.Size() == 0)\r
+  {\r
+    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;\r
+    if (!callback)\r
+      return S_FALSE;\r
+    callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);\r
+    if (!openVolumeCallback)\r
+      return S_FALSE;\r
+    NCOM::CPropVariant prop;\r
+    if (openVolumeCallback->GetProperty(kpidName, &prop) != S_OK)\r
+      return S_FALSE;\r
+    if (prop.vt != VT_BSTR)\r
+      return S_FALSE;\r
+    UString baseName = prop.bstrVal;\r
+    baseName = baseName.Right(4);\r
+    if (baseName.CompareNoCase(L".tar") != 0)\r
+      return S_FALSE;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openArchiveCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  {\r
+    Close();\r
+    RINOK(Open2(stream, openArchiveCallback));\r
+    _stream = stream;\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)\r
+{\r
+  Close();\r
+  _seqStream = stream;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _errorMessage.Empty();\r
+  _phySizeDefined = false;\r
+  _phySize = 0;\r
+  _headersSize = 0;\r
+  _curIndex = 0;\r
+  _latestIsRead = false;\r
+  _items.Clear();\r
+  _seqStream.Release();\r
+  _stream.Release();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = (_stream ? _items.Size() : (UInt32)(Int32)-1);\r
+  return S_OK;\r
+}\r
+\r
+CHandler::CHandler()\r
+{\r
+  copyCoderSpec = new NCompress::CCopyCoder();\r
+  copyCoder = copyCoderSpec;\r
+}\r
+\r
+HRESULT CHandler::SkipTo(UInt32 index)\r
+{\r
+  while (_curIndex < index || !_latestIsRead)\r
+  {\r
+    if (_latestIsRead)\r
+    {\r
+      UInt64 packSize = _latestItem.GetPackSize();\r
+      RINOK(copyCoderSpec->Code(_seqStream, NULL, &packSize, &packSize, NULL));\r
+      _phySize += copyCoderSpec->TotalSize;\r
+      if (copyCoderSpec->TotalSize != packSize)\r
+      {\r
+        _errorMessage = kUnexpectedEnd;\r
+        return S_FALSE;\r
+      }\r
+      _latestIsRead = false;\r
+      _curIndex++;\r
+    }\r
+    else\r
+    {\r
+      bool filled;\r
+      RINOK(ReadItem2(_seqStream, filled, _latestItem));\r
+      if (!filled)\r
+      {\r
+        _phySizeDefined = true;\r
+        return E_INVALIDARG;\r
+      }\r
+      _latestIsRead = true;\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+static UString TarStringToUnicode(const AString &s)\r
+{\r
+  return MultiByteToUnicodeString(s, CP_OEMCP);\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+\r
+  const CItemEx *item;\r
+  if (_stream)\r
+    item = &_items[index];\r
+  else\r
+  {\r
+    if (index < _curIndex)\r
+      return E_INVALIDARG;\r
+    else\r
+    {\r
+      RINOK(SkipTo(index));\r
+      item = &_latestItem;\r
+    }\r
+  }\r
+\r
+  switch(propID)\r
+  {\r
+    case kpidPath: prop = NItemName::GetOSName2(TarStringToUnicode(item->Name)); break;\r
+    case kpidIsDir: prop = item->IsDir(); break;\r
+    case kpidSize: prop = item->GetUnpackSize(); break;\r
+    case kpidPackSize: prop = item->GetPackSize(); break;\r
+    case kpidMTime:\r
+      if (item->MTime != 0)\r
+      {\r
+        FILETIME ft;\r
+        NTime::UnixTimeToFileTime(item->MTime, ft);\r
+        prop = ft;\r
+      }\r
+      break;\r
+    case kpidPosixAttrib: prop = item->Mode; break;\r
+    case kpidUser: prop = TarStringToUnicode(item->User); break;\r
+    case kpidGroup: prop = TarStringToUnicode(item->Group); break;\r
+    case kpidLink: prop = TarStringToUnicode(item->LinkName); break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  ISequentialInStream *stream = _seqStream;\r
+  bool seqMode = (_stream == NULL);\r
+  if (!seqMode)\r
+    stream = _stream;\r
+\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _items.Size();\r
+  if (_stream && numItems == 0)\r
+    return S_OK;\r
+  UInt64 totalSize = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+    totalSize += _items[allFilesMode ? i : indices[i]].GetUnpackSize();\r
+  extractCallback->SetTotal(totalSize);\r
+\r
+  UInt64 totalPackSize;\r
+  totalSize = totalPackSize = 0;\r
+  \r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);\r
+  streamSpec->SetStream(stream);\r
+\r
+  CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream;\r
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\r
+\r
+  for (i = 0; i < numItems || seqMode; i++)\r
+  {\r
+    lps->InSize = totalPackSize;\r
+    lps->OutSize = totalSize;\r
+    RINOK(lps->SetCur());\r
+    CMyComPtr<ISequentialOutStream> realOutStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    Int32 index = allFilesMode ? i : indices[i];\r
+    const CItemEx *item;\r
+    if (seqMode)\r
+    {\r
+      HRESULT res = SkipTo(index);\r
+      if (res == E_INVALIDARG)\r
+        break;\r
+      RINOK(res);\r
+      item = &_latestItem;\r
+    }\r
+    else\r
+      item = &_items[index];\r
+\r
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+    UInt64 unpackSize = item->GetUnpackSize();\r
+    totalSize += unpackSize;\r
+    totalPackSize += item->GetPackSize();\r
+    if (item->IsDir())\r
+    {\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+      continue;\r
+    }\r
+    bool skipMode = false;\r
+    if (!testMode && !realOutStream)\r
+    {\r
+      if (!seqMode)\r
+        continue;\r
+      skipMode = true;\r
+      askMode = NExtract::NAskMode::kSkip;\r
+    }\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+\r
+    outStreamSpec->SetStream(realOutStream);\r
+    realOutStream.Release();\r
+    outStreamSpec->Init(skipMode ? 0 : unpackSize, true);\r
+\r
+    if (item->IsLink())\r
+    {\r
+      RINOK(WriteStream(outStreamSpec, (const char *)item->LinkName, item->LinkName.Length()));\r
+    }\r
+    else\r
+    {\r
+      if (!seqMode)\r
+      {\r
+        RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL));\r
+      }\r
+      streamSpec->Init(item->GetPackSize());\r
+      RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));\r
+    }\r
+    if (seqMode)\r
+    {\r
+      _latestIsRead = false;\r
+      _curIndex++;\r
+    }\r
+    outStreamSpec->ReleaseStream();\r
+    RINOK(extractCallback->SetOperationResult(outStreamSpec->GetRem() == 0 ?\r
+        NExtract::NOperationResult::kOK:\r
+        NExtract::NOperationResult::kDataError));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)\r
+{\r
+  COM_TRY_BEGIN\r
+  const CItemEx &item = _items[index];\r
+  if (item.IsLink())\r
+  {\r
+    CBufInStream *streamSpec = new CBufInStream;\r
+    CMyComPtr<IInStream> streamTemp = streamSpec;\r
+    streamSpec->Init((const Byte *)(const char *)item.LinkName, item.LinkName.Length(), (IInArchive *)this);\r
+    *stream = streamTemp.Detach();\r
+    return S_OK;\r
+  }\r
+  return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream);\r
+  COM_TRY_END\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Tar/TarHandler.h b/CPP/7zip/Archive/Tar/TarHandler.h
new file mode 100755 (executable)
index 0000000..10593da
--- /dev/null
@@ -0,0 +1,61 @@
+// TarHandler.h\r
+\r
+#ifndef __TAR_HANDLER_H\r
+#define __TAR_HANDLER_H\r
+\r
+#include "Common/MyCom.h"\r
+#include "../IArchive.h"\r
+\r
+#include "../../Compress/CopyCoder.h"\r
+\r
+#include "TarItem.h"\r
+\r
+namespace NArchive {\r
+namespace NTar {\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IArchiveOpenSeq,\r
+  public IInArchiveGetStream,\r
+  public IOutArchive,\r
+  public CMyUnknownImp\r
+{\r
+  CObjectVector<CItemEx> _items;\r
+  CMyComPtr<IInStream> _stream;\r
+  CMyComPtr<ISequentialInStream> _seqStream;\r
+  \r
+  UInt32 _curIndex;\r
+  bool _latestIsRead;\r
+  CItemEx _latestItem;\r
+\r
+  UInt64 _phySize;\r
+  UInt64 _headersSize;\r
+  bool _phySizeDefined;\r
+  AString _errorMessage;\r
+\r
+  NCompress::CCopyCoder *copyCoderSpec;\r
+  CMyComPtr<ICompressCoder> copyCoder;\r
+\r
+  HRESULT ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo);\r
+  HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);\r
+  HRESULT SkipTo(UInt32 index);\r
+\r
+public:\r
+  MY_UNKNOWN_IMP4(\r
+    IInArchive,\r
+    IArchiveOpenSeq,\r
+    IInArchiveGetStream,\r
+    IOutArchive\r
+  )\r
+\r
+  INTERFACE_IInArchive(;)\r
+  INTERFACE_IOutArchive(;)\r
+  STDMETHOD(OpenSeq)(ISequentialInStream *stream);\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);\r
+\r
+  CHandler();\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
new file mode 100755 (executable)
index 0000000..dfdea31
--- /dev/null
@@ -0,0 +1,122 @@
+// TarHandlerOut.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "TarHandler.h"\r
+#include "TarUpdate.h"\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace NTar {\r
+\r
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)\r
+{\r
+  *type = NFileTimeType::kUnix;\r
+  return S_OK;\r
+}\r
+\r
+static HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  RINOK(callback->GetProperty(index, propId, &prop));\r
+  if (prop.vt == VT_BSTR)\r
+    res = UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP);\r
+  else if (prop.vt != VT_EMPTY)\r
+    return E_INVALIDARG;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\r
+    IArchiveUpdateCallback *callback)\r
+{\r
+  COM_TRY_BEGIN\r
+  if ((_stream && !_errorMessage.IsEmpty()) || _seqStream)\r
+    return E_NOTIMPL;\r
+  CObjectVector<CUpdateItem> updateItems;\r
+  for (UInt32 i = 0; i < numItems; i++)\r
+  {\r
+    CUpdateItem ui;\r
+    Int32 newData;\r
+    Int32 newProps;\r
+    UInt32 indexInArchive;\r
+    if (!callback)\r
+      return E_FAIL;\r
+    RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));\r
+    ui.NewProps = IntToBool(newProps);\r
+    ui.NewData = IntToBool(newData);\r
+    ui.IndexInArchive = indexInArchive;\r
+    ui.IndexInClient = i;\r
+\r
+    if (IntToBool(newProps))\r
+    {\r
+      {\r
+        NCOM::CPropVariant prop;\r
+        RINOK(callback->GetProperty(i, kpidIsDir, &prop));\r
+        if (prop.vt == VT_EMPTY)\r
+          ui.IsDir = false;\r
+        else if (prop.vt != VT_BOOL)\r
+          return E_INVALIDARG;\r
+        else\r
+          ui.IsDir = (prop.boolVal != VARIANT_FALSE);\r
+      }\r
+\r
+      {\r
+        NCOM::CPropVariant prop;\r
+        RINOK(callback->GetProperty(i, kpidPosixAttrib, &prop));\r
+        if (prop.vt == VT_EMPTY)\r
+          ui.Mode = 0777 | (ui.IsDir ? 0040000 : 0100000);\r
+        else if (prop.vt != VT_UI4)\r
+          return E_INVALIDARG;\r
+        else\r
+          ui.Mode = prop.ulVal;\r
+      }\r
+      {\r
+        NCOM::CPropVariant prop;\r
+        RINOK(callback->GetProperty(i, kpidMTime, &prop));\r
+        if (prop.vt == VT_EMPTY)\r
+          ui.Time = 0;\r
+        else if (prop.vt != VT_FILETIME)\r
+          return E_INVALIDARG;\r
+        else if (!NTime::FileTimeToUnixTime(prop.filetime, ui.Time))\r
+          ui.Time = 0;\r
+      }\r
+      {\r
+        NCOM::CPropVariant prop;\r
+        RINOK(callback->GetProperty(i, kpidPath, &prop));\r
+        if (prop.vt == VT_BSTR)\r
+          ui.Name = UnicodeStringToMultiByte(NItemName::MakeLegalName(prop.bstrVal), CP_OEMCP);\r
+        else if (prop.vt != VT_EMPTY)\r
+          return E_INVALIDARG;\r
+        if (ui.IsDir)\r
+          ui.Name += '/';\r
+      }\r
+      RINOK(GetPropString(callback, i, kpidUser, ui.User));\r
+      RINOK(GetPropString(callback, i, kpidGroup, ui.Group));\r
+    }\r
+    if (IntToBool(newData))\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      RINOK(callback->GetProperty(i, kpidSize, &prop));\r
+      if (prop.vt != VT_UI8)\r
+        return E_INVALIDARG;\r
+      ui.Size = prop.uhVal.QuadPart;\r
+      /*\r
+      // now we support GNU extension for big files\r
+      if (ui.Size >= ((UInt64)1 << 33))\r
+        return E_INVALIDARG;\r
+      */\r
+    }\r
+    updateItems.Add(ui);\r
+  }\r
+  return UpdateArchive(_stream, outStream, _items, updateItems, callback);\r
+  COM_TRY_END\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Tar/TarHeader.cpp b/CPP/7zip/Archive/Tar/TarHeader.cpp
new file mode 100755 (executable)
index 0000000..9304388
--- /dev/null
@@ -0,0 +1,25 @@
+// Archive/Tar/Header.h\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "TarHeader.h"\r
+\r
+namespace NArchive {\r
+namespace NTar {\r
+namespace NFileHeader {\r
+\r
+  // The checksum field is filled with this while the checksum is computed.\r
+  const char *kCheckSumBlanks = "        ";   // 8 blanks, no null\r
+\r
+  const char *kLongLink = "././@LongLink";\r
+  const char *kLongLink2 = "@LongLink";\r
+\r
+  // The magic field is filled with this if uname and gname are valid.\r
+  namespace NMagic\r
+  {\r
+    const char *kUsTar  = "ustar"; // 5 chars\r
+    const char *kGNUTar = "GNUtar "; // 7 chars and a null\r
+    const char *kEmpty = "\0\0\0\0\0\0\0\0"; // 7 chars and a null\r
+  }\r
+\r
+}}}\r
diff --git a/CPP/7zip/Archive/Tar/TarHeader.h b/CPP/7zip/Archive/Tar/TarHeader.h
new file mode 100755 (executable)
index 0000000..dece1f7
--- /dev/null
@@ -0,0 +1,108 @@
+// Archive/Tar/Header.h\r
+\r
+#ifndef __ARCHIVE_TAR_HEADER_H\r
+#define __ARCHIVE_TAR_HEADER_H\r
+\r
+#include "Common/Types.h"\r
+\r
+namespace NArchive {\r
+namespace NTar {\r
+\r
+namespace NFileHeader\r
+{\r
+  const int kRecordSize = 512;\r
+  const int kNameSize = 100;\r
+  const int kUserNameSize = 32;\r
+  const int kGroupNameSize = 32;\r
+  const int kPrefixSize = 155;\r
+\r
+  /*\r
+  struct CHeader\r
+  {\r
+    char Name[kNameSize];\r
+    char Mode[8];\r
+    char UID[8];\r
+    char GID[8];\r
+    char Size[12];\r
+    char ModificationTime[12];\r
+    char CheckSum[8];\r
+    char LinkFlag;\r
+    char LinkName[kNameSize];\r
+    char Magic[8];\r
+    char UserName[kUserNameSize];\r
+    char GroupName[kGroupNameSize];\r
+    char DeviceMajor[8];\r
+    char DeviceMinor[8];\r
+    char Prefix[155];\r
+  };\r
+  union CRecord\r
+  {\r
+    CHeader Header;\r
+    Byte Padding[kRecordSize];\r
+  };\r
+  */\r
+\r
+  namespace NMode\r
+  {\r
+    const int kSetUID   = 04000;  // Set UID on execution\r
+    const int kSetGID   = 02000;  // Set GID on execution\r
+    const int kSaveText = 01000;  // Save text (sticky bit)\r
+  }\r
+\r
+  namespace NFilePermissions\r
+  {\r
+    const int kUserRead     = 00400;  // read by owner\r
+    const int kUserWrite    = 00200;  // write by owner\r
+    const int kUserExecute  = 00100;  // execute/search by owner\r
+    const int kGroupRead    = 00040;  // read by group\r
+    const int kGroupWrite   = 00020;  // write by group\r
+    const int kGroupExecute = 00010;  // execute/search by group\r
+    const int kOtherRead    = 00004;  // read by other\r
+    const int kOtherWrite   = 00002;  // write by other\r
+    const int kOtherExecute = 00001;  // execute/search by other\r
+  }\r
+\r
+\r
+  // The linkflag defines the type of file\r
+  namespace NLinkFlag\r
+  {\r
+    const char kOldNormal    = '\0'; // Normal disk file, Unix compatible\r
+    const char kNormal       = '0'; // Normal disk file\r
+    const char kLink         = '1'; // Link to previously dumped file\r
+    const char kSymbolicLink = '2'; // Symbolic link\r
+    const char kCharacter    = '3'; // Character special file\r
+    const char kBlock        = '4'; // Block special file\r
+    const char kDirectory    = '5'; // Directory\r
+    const char kFIFO         = '6'; // FIFO special file\r
+    const char kContiguous   = '7'; // Contiguous file\r
+\r
+    const char kDumpDir       = 'D'; /* GNUTYPE_DUMPDIR.\r
+      data: list of files created by the --incremental (-G) option\r
+      Each file name is preceded by either\r
+        - 'Y' (file should be in this archive)\r
+        - 'N' (file is a directory, or is not stored in the archive.)\r
+        Each file name is terminated by a null + an additional null after\r
+        the last file name. */\r
+\r
+  }\r
+  // Further link types may be defined later.\r
+\r
+  // The checksum field is filled with this while the checksum is computed.\r
+  extern const char *kCheckSumBlanks;//   = "        ";   // 8 blanks, no null\r
+\r
+  extern const char *kLongLink;  //   = "././@LongLink";\r
+  extern const char *kLongLink2; //   = "@LongLink";\r
+\r
+  // The magic field is filled with this if uname and gname are valid.\r
+  namespace NMagic\r
+  {\r
+    extern const char *kUsTar; //   = "ustar"; // 5 chars\r
+    extern const char *kGNUTar; //  = "GNUtar "; // 7 chars and a null\r
+    extern const char *kEmpty; //  = "GNUtar "; // 7 chars and a null\r
+  }\r
+\r
+}\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp
new file mode 100755 (executable)
index 0000000..97d4f7e
--- /dev/null
@@ -0,0 +1,207 @@
+// TarIn.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/CpuArch.h"\r
+\r
+#include "Common/StringToInt.h"\r
+\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "TarIn.h"\r
+\r
+namespace NArchive {\r
+namespace NTar {\r
\r
+static void MyStrNCpy(char *dest, const char *src, int size)\r
+{\r
+  for (int i = 0; i < size; i++)\r
+  {\r
+    char c = src[i];\r
+    dest[i] = c;\r
+    if (c == 0)\r
+      break;\r
+  }\r
+}\r
+\r
+static bool OctalToNumber(const char *srcString, int size, UInt64 &res)\r
+{\r
+  char sz[32];\r
+  MyStrNCpy(sz, srcString, size);\r
+  sz[size] = 0;\r
+  const char *end;\r
+  int i;\r
+  for (i = 0; sz[i] == ' '; i++);\r
+  res = ConvertOctStringToUInt64(sz + i, &end);\r
+  return (*end == ' ' || *end == 0);\r
+}\r
+\r
+static bool OctalToNumber32(const char *srcString, int size, UInt32 &res)\r
+{\r
+  UInt64 res64;\r
+  if (!OctalToNumber(srcString, size, res64))\r
+    return false;\r
+  res = (UInt32)res64;\r
+  return (res64 <= 0xFFFFFFFF);\r
+}\r
+\r
+#define RIF(x) { if (!(x)) return S_FALSE; }\r
+\r
+static bool IsRecordLast(const char *buf)\r
+{\r
+  for (int i = 0; i < NFileHeader::kRecordSize; i++)\r
+    if (buf[i] != 0)\r
+      return false;\r
+  return true;\r
+}\r
+\r
+static void ReadString(const char *s, int size, AString &result)\r
+{\r
+  char temp[NFileHeader::kRecordSize + 1];\r
+  MyStrNCpy(temp, s, size);\r
+  temp[size] = '\0';\r
+  result = temp;\r
+}\r
+\r
+static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemEx &item, AString &error)\r
+{\r
+  char buf[NFileHeader::kRecordSize];\r
+  char *p = buf;\r
+\r
+  error.Empty();\r
+  filled = false;\r
+\r
+  bool thereAreEmptyRecords = false;\r
+  for (;;)\r
+  {\r
+    size_t processedSize = NFileHeader::kRecordSize;\r
+    RINOK(ReadStream(stream, buf, &processedSize));\r
+    if (processedSize == 0)\r
+    {\r
+      if (!thereAreEmptyRecords )\r
+        error = "There are no trailing zero-filled records";\r
+      return S_OK;\r
+    }\r
+    if (processedSize != NFileHeader::kRecordSize)\r
+    {\r
+      error = "There is no correct record at the end of archive";\r
+      return S_OK;\r
+    }\r
+    item.HeaderSize += NFileHeader::kRecordSize;\r
+    if (!IsRecordLast(buf))\r
+      break;\r
+    thereAreEmptyRecords = true;\r
+  }\r
+  if (thereAreEmptyRecords)\r
+  {\r
+    error = "There are data after end of archive";\r
+    return S_OK;\r
+  }\r
+  \r
+  ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize;\r
+\r
+  RIF(OctalToNumber32(p, 8, item.Mode)); p += 8;\r
+\r
+  if (!OctalToNumber32(p, 8, item.UID)) item.UID = 0; p += 8;\r
+  if (!OctalToNumber32(p, 8, item.GID)) item.GID = 0; p += 8;\r
+\r
+  if (GetBe32(p) == (UInt32)1 << 31)\r
+  {\r
+    // GNU extension\r
+    item.Size = GetBe64(p + 4);\r
+  }\r
+  else\r
+  {\r
+    RIF(OctalToNumber(p, 12, item.Size));\r
+  }\r
+  p += 12;\r
+  RIF(OctalToNumber32(p, 12, item.MTime)); p += 12;\r
+  \r
+  UInt32 checkSum;\r
+  RIF(OctalToNumber32(p, 8, checkSum));\r
+  memcpy(p, NFileHeader::kCheckSumBlanks, 8); p += 8;\r
+\r
+  item.LinkFlag = *p++;\r
+\r
+  ReadString(p, NFileHeader::kNameSize, item.LinkName); p += NFileHeader::kNameSize;\r
+\r
+  memcpy(item.Magic, p, 8); p += 8;\r
+\r
+  ReadString(p, NFileHeader::kUserNameSize, item.User); p += NFileHeader::kUserNameSize;\r
+  ReadString(p, NFileHeader::kGroupNameSize, item.Group); p += NFileHeader::kGroupNameSize;\r
+\r
+  item.DeviceMajorDefined = (p[0] != 0); RIF(OctalToNumber32(p, 8, item.DeviceMajor)); p += 8;\r
+  item.DeviceMinorDefined = (p[0] != 0); RIF(OctalToNumber32(p, 8, item.DeviceMinor)); p += 8;\r
+\r
+  AString prefix;\r
+  ReadString(p, NFileHeader::kPrefixSize, prefix);\r
+  p += NFileHeader::kPrefixSize;\r
+  if (!prefix.IsEmpty() && item.IsMagic() &&\r
+      (item.LinkFlag != 'L' /* || prefix != "00000000000" */ ))\r
+    item.Name = prefix + AString('/') + item.Name;\r
+\r
+  if (item.LinkFlag == NFileHeader::NLinkFlag::kLink)\r
+    item.Size = 0;\r
\r
+  UInt32 checkSumReal = 0;\r
+  for (int i = 0; i < NFileHeader::kRecordSize; i++)\r
+    checkSumReal += (Byte)buf[i];\r
+  \r
+  if (checkSumReal != checkSum)\r
+    return S_FALSE;\r
+\r
+  filled = true;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, AString &error)\r
+{\r
+  item.HeaderSize = 0;\r
+  bool flagL = false;\r
+  bool flagK = false;\r
+  AString nameL;\r
+  AString nameK;\r
+  for (;;)\r
+  {\r
+    RINOK(GetNextItemReal(stream, filled, item, error));\r
+    if (!filled)\r
+      return S_OK;\r
+    if (item.LinkFlag == 'L' || // NEXT file has a long name\r
+        item.LinkFlag == 'K') // NEXT file has a long linkname\r
+    {\r
+      AString *name;\r
+      if (item.LinkFlag == 'L')\r
+        { if (flagL) return S_FALSE; flagL = true; name = &nameL; }\r
+      else\r
+        { if (flagK) return S_FALSE; flagK = true; name = &nameK; }\r
+\r
+      if (item.Name.Compare(NFileHeader::kLongLink) != 0 &&\r
+          item.Name.Compare(NFileHeader::kLongLink2) != 0)\r
+        return S_FALSE;\r
+      if (item.Size > (1 << 14))\r
+        return S_FALSE;\r
+      int packSize = (int)item.GetPackSize();\r
+      char *buf = name->GetBuffer(packSize);\r
+      RINOK(ReadStream_FALSE(stream, buf, packSize));\r
+      item.HeaderSize += packSize;\r
+      buf[(size_t)item.Size] = '\0';\r
+      name->ReleaseBuffer();\r
+      continue;\r
+    }\r
+    if (item.LinkFlag == 'g' || item.LinkFlag == 'x' || item.LinkFlag == 'X')\r
+    {\r
+      // pax Extended Header\r
+    }\r
+    else if (item.LinkFlag == NFileHeader::NLinkFlag::kDumpDir)\r
+    {\r
+      // GNU Extensions to the Archive Format\r
+    }\r
+    else if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0))\r
+      return S_FALSE;\r
+    if (flagL) item.Name = nameL;\r
+    if (flagK) item.LinkName = nameK;\r
+    return S_OK;\r
+  }\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Tar/TarIn.h b/CPP/7zip/Archive/Tar/TarIn.h
new file mode 100755 (executable)
index 0000000..33bf6f6
--- /dev/null
@@ -0,0 +1,17 @@
+// TarIn.h\r
+\r
+#ifndef __ARCHIVE_TAR_IN_H\r
+#define __ARCHIVE_TAR_IN_H\r
+\r
+#include "../../IStream.h"\r
+\r
+#include "TarItem.h"\r
+\r
+namespace NArchive {\r
+namespace NTar {\r
+  \r
+HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo, AString &error);\r
+\r
+}}\r
+  \r
+#endif\r
diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h
new file mode 100755 (executable)
index 0000000..5bcad47
--- /dev/null
@@ -0,0 +1,72 @@
+// TarItem.h\r
+\r
+#ifndef __ARCHIVE_TAR_ITEM_H\r
+#define __ARCHIVE_TAR_ITEM_H\r
+\r
+#include "../Common/ItemNameUtils.h"\r
+\r
+#include "TarHeader.h"\r
+\r
+namespace NArchive {\r
+namespace NTar {\r
+\r
+struct CItem\r
+{\r
+  AString Name;\r
+  UInt64 Size;\r
+\r
+  UInt32 Mode;\r
+  UInt32 UID;\r
+  UInt32 GID;\r
+  UInt32 MTime;\r
+  UInt32 DeviceMajor;\r
+  UInt32 DeviceMinor;\r
+\r
+  AString LinkName;\r
+  AString User;\r
+  AString Group;\r
+\r
+  char Magic[8];\r
+  char LinkFlag;\r
+  bool DeviceMajorDefined;\r
+  bool DeviceMinorDefined;\r
+\r
+  bool IsLink() const { return LinkFlag == NFileHeader::NLinkFlag::kSymbolicLink && (Size == 0); }\r
+  UInt64 GetUnpackSize() const { return IsLink() ? LinkName.Length() : Size; }\r
+\r
+  bool IsDir() const\r
+  {\r
+    switch(LinkFlag)\r
+    {\r
+      case NFileHeader::NLinkFlag::kDirectory:\r
+      case NFileHeader::NLinkFlag::kDumpDir:\r
+        return true;\r
+      case NFileHeader::NLinkFlag::kOldNormal:\r
+      case NFileHeader::NLinkFlag::kNormal:\r
+        return NItemName::HasTailSlash(Name, CP_OEMCP);\r
+    }\r
+    return false;\r
+  }\r
+\r
+  bool IsMagic() const\r
+  {\r
+    for (int i = 0; i < 5; i++)\r
+      if (Magic[i] != NFileHeader::NMagic::kUsTar[i])\r
+        return false;\r
+    return true;\r
+  }\r
+\r
+  UInt64 GetPackSize() const { return (Size + 0x1FF) & (~((UInt64)0x1FF)); }\r
+};\r
+\r
+struct CItemEx: public CItem\r
+{\r
+  UInt64 HeaderPos;\r
+  unsigned HeaderSize;\r
+  UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; }\r
+  UInt64 GetFullSize() const { return HeaderSize + Size; }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Tar/TarOut.cpp b/CPP/7zip/Archive/Tar/TarOut.cpp
new file mode 100755 (executable)
index 0000000..d0cb360
--- /dev/null
@@ -0,0 +1,187 @@
+// TarOut.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "TarOut.h"\r
+\r
+namespace NArchive {\r
+namespace NTar {\r
+\r
+HRESULT COutArchive::WriteBytes(const void *buffer, UInt32 size)\r
+{\r
+  return WriteStream(m_Stream, buffer, size);\r
+}\r
+\r
+void COutArchive::Create(ISequentialOutStream *outStream)\r
+{\r
+  m_Stream = outStream;\r
+}\r
+\r
+static AString MakeOctalString(UInt64 value)\r
+{\r
+  char s[32];\r
+  ConvertUInt64ToString(value, s, 8);\r
+  return AString(s) + ' ';\r
+}\r
+\r
+static void MyStrNCpy(char *dest, const char *src, int size)\r
+{\r
+  for (int i = 0; i < size; i++)\r
+  {\r
+    char c = src[i];\r
+    dest[i] = c;\r
+    if (c == 0)\r
+      break;\r
+  }\r
+}\r
+\r
+static bool MakeOctalString8(char *s, UInt32 value)\r
+{\r
+  AString tempString = MakeOctalString(value);\r
+\r
+  const int kMaxSize = 8;\r
+  if (tempString.Length() >= kMaxSize)\r
+    return false;\r
+  int numSpaces = kMaxSize - (tempString.Length() + 1);\r
+  for(int i = 0; i < numSpaces; i++)\r
+    s[i] = ' ';\r
+  MyStringCopy(s + numSpaces, (const char *)tempString);\r
+  return true;\r
+}\r
+\r
+static void MakeOctalString12(char *s, UInt64 value)\r
+{\r
+  AString tempString  = MakeOctalString(value);\r
+  const int kMaxSize = 12;\r
+  if (tempString.Length() > kMaxSize)\r
+  {\r
+    // GNU extension;\r
+    s[0] = (char)(Byte)0x80;\r
+    s[1] = s[2] = s[3] = 0;\r
+    for (int i = 0; i < 8; i++, value <<= 8)\r
+      s[4 + i] = (char)(value >> 56);\r
+    return;\r
+  }\r
+  int numSpaces = kMaxSize - tempString.Length();\r
+  for(int i = 0; i < numSpaces; i++)\r
+    s[i] = ' ';\r
+  memmove(s + numSpaces, (const char *)tempString, tempString.Length());\r
+}\r
+\r
+static bool CopyString(char *dest, const AString &src, int maxSize)\r
+{\r
+  if (src.Length() >= maxSize)\r
+    return false;\r
+  MyStringCopy(dest, (const char *)src);\r
+  return true;\r
+}\r
+\r
+#define RETURN_IF_NOT_TRUE(x) { if (!(x)) return E_FAIL; }\r
+\r
+HRESULT COutArchive::WriteHeaderReal(const CItem &item)\r
+{\r
+  char record[NFileHeader::kRecordSize];\r
+  char *cur = record;\r
+  int i;\r
+  for (i = 0; i < NFileHeader::kRecordSize; i++)\r
+    record[i] = 0;\r
+\r
+  // RETURN_IF_NOT_TRUE(CopyString(header.Name, item.Name, NFileHeader::kNameSize));\r
+  if (item.Name.Length() > NFileHeader::kNameSize)\r
+    return E_FAIL;\r
+  MyStrNCpy(cur, item.Name, NFileHeader::kNameSize);\r
+  cur += NFileHeader::kNameSize;\r
+\r
+  RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.Mode)); cur += 8;\r
+  RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.UID)); cur += 8;\r
+  RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.GID)); cur += 8;\r
+\r
+  MakeOctalString12(cur, item.Size); cur += 12;\r
+  MakeOctalString12(cur, item.MTime); cur += 12;\r
+  \r
+  memmove(cur, NFileHeader::kCheckSumBlanks, 8);\r
+  cur += 8;\r
+\r
+  *cur++ = item.LinkFlag;\r
+\r
+  RETURN_IF_NOT_TRUE(CopyString(cur, item.LinkName, NFileHeader::kNameSize));\r
+  cur += NFileHeader::kNameSize;\r
+\r
+  memmove(cur, item.Magic, 8);\r
+  cur += 8;\r
+\r
+  RETURN_IF_NOT_TRUE(CopyString(cur, item.User, NFileHeader::kUserNameSize));\r
+  cur += NFileHeader::kUserNameSize;\r
+  RETURN_IF_NOT_TRUE(CopyString(cur, item.Group, NFileHeader::kGroupNameSize));\r
+  cur += NFileHeader::kGroupNameSize;\r
+\r
+\r
+  if (item.DeviceMajorDefined)\r
+    RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.DeviceMajor));\r
+  cur += 8;\r
+\r
+  if (item.DeviceMinorDefined)\r
+    RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.DeviceMinor));\r
+  cur += 8;\r
+\r
+\r
+  UInt32 checkSumReal = 0;\r
+  for(i = 0; i < NFileHeader::kRecordSize; i++)\r
+    checkSumReal += Byte(record[i]);\r
+\r
+  RETURN_IF_NOT_TRUE(MakeOctalString8(record + 148, checkSumReal));\r
+\r
+  return WriteBytes(record, NFileHeader::kRecordSize);\r
+}\r
+\r
+HRESULT COutArchive::WriteHeader(const CItem &item)\r
+{\r
+  int nameSize = item.Name.Length();\r
+  if (nameSize < NFileHeader::kNameSize)\r
+    return WriteHeaderReal(item);\r
+\r
+  CItem modifiedItem = item;\r
+  int nameStreamSize = nameSize + 1;\r
+  modifiedItem.Size = nameStreamSize;\r
+  modifiedItem.LinkFlag = 'L';\r
+  modifiedItem.Name = NFileHeader::kLongLink;\r
+  modifiedItem.LinkName.Empty();\r
+  RINOK(WriteHeaderReal(modifiedItem));\r
+  RINOK(WriteBytes(item.Name, nameStreamSize));\r
+  RINOK(FillDataResidual(nameStreamSize));\r
+\r
+  modifiedItem = item;\r
+  modifiedItem.Name = item.Name.Left(NFileHeader::kNameSize - 1);\r
+  return WriteHeaderReal(modifiedItem);\r
+}\r
+\r
+HRESULT COutArchive::FillDataResidual(UInt64 dataSize)\r
+{\r
+  UInt32 lastRecordSize = UInt32(dataSize & (NFileHeader::kRecordSize - 1));\r
+  if (lastRecordSize == 0)\r
+    return S_OK;\r
+  UInt32 residualSize = NFileHeader::kRecordSize - lastRecordSize;\r
+  Byte residualBytes[NFileHeader::kRecordSize];\r
+  for (UInt32 i = 0; i < residualSize; i++)\r
+    residualBytes[i] = 0;\r
+  return WriteBytes(residualBytes, residualSize);\r
+}\r
+\r
+HRESULT COutArchive::WriteFinishHeader()\r
+{\r
+  Byte record[NFileHeader::kRecordSize];\r
+  int i;\r
+  for (i = 0; i < NFileHeader::kRecordSize; i++)\r
+    record[i] = 0;\r
+  for (i = 0; i < 2; i++)\r
+  {\r
+    RINOK(WriteBytes(record, NFileHeader::kRecordSize));\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Tar/TarOut.h b/CPP/7zip/Archive/Tar/TarOut.h
new file mode 100755 (executable)
index 0000000..7430904
--- /dev/null
@@ -0,0 +1,28 @@
+// Archive/TarOut.h\r
+\r
+#ifndef __ARCHIVE_TAR_OUT_H\r
+#define __ARCHIVE_TAR_OUT_H\r
+\r
+#include "TarItem.h"\r
+\r
+#include "Common/MyCom.h"\r
+#include "../../IStream.h"\r
+\r
+namespace NArchive {\r
+namespace NTar {\r
+\r
+class COutArchive\r
+{\r
+  CMyComPtr<ISequentialOutStream> m_Stream;\r
+  HRESULT WriteBytes(const void *buffer, UInt32 size);\r
+public:\r
+  void Create(ISequentialOutStream *outStream);\r
+  HRESULT WriteHeaderReal(const CItem &item);\r
+  HRESULT WriteHeader(const CItem &item);\r
+  HRESULT FillDataResidual(UInt64 dataSize);\r
+  HRESULT WriteFinishHeader();\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Tar/TarRegister.cpp b/CPP/7zip/Archive/Tar/TarRegister.cpp
new file mode 100755 (executable)
index 0000000..1ed9c20
--- /dev/null
@@ -0,0 +1,18 @@
+// TarRegister.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/RegisterArc.h"\r
+\r
+#include "TarHandler.h"\r
+static IInArchive *CreateArc() { return new NArchive::NTar::CHandler; }\r
+#ifndef EXTRACT_ONLY\r
+static IOutArchive *CreateArcOut() { return new NArchive::NTar::CHandler; }\r
+#else\r
+#define CreateArcOut 0\r
+#endif\r
+\r
+static CArcInfo g_ArcInfo =\r
+{ L"tar", L"tar", 0, 0xEE, { 'u', 's', 't', 'a', 'r' }, 5, false, CreateArc, CreateArcOut };\r
+\r
+REGISTER_ARC(Tar)\r
diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp
new file mode 100755 (executable)
index 0000000..996fd0f
--- /dev/null
@@ -0,0 +1,139 @@
+// TarUpdate.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/LimitedStreams.h"\r
+#include "../../Common/ProgressUtils.h"\r
+\r
+#include "../../Compress/CopyCoder.h"\r
+\r
+#include "TarOut.h"\r
+#include "TarUpdate.h"\r
+\r
+namespace NArchive {\r
+namespace NTar {\r
+\r
+HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,\r
+    const CObjectVector<NArchive::NTar::CItemEx> &inputItems,\r
+    const CObjectVector<CUpdateItem> &updateItems,\r
+    IArchiveUpdateCallback *updateCallback)\r
+{\r
+  COutArchive outArchive;\r
+  outArchive.Create(outStream);\r
+\r
+  UInt64 complexity = 0;\r
+\r
+  int i;\r
+  for(i = 0; i < updateItems.Size(); i++)\r
+  {\r
+    const CUpdateItem &ui = updateItems[i];\r
+    if (ui.NewData)\r
+      complexity += ui.Size;\r
+    else\r
+      complexity += inputItems[ui.IndexInArchive].GetFullSize();\r
+  }\r
+\r
+  RINOK(updateCallback->SetTotal(complexity));\r
+\r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(updateCallback, true);\r
+\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec);\r
+  streamSpec->SetStream(inStream);\r
+\r
+  complexity = 0;\r
+\r
+  for(i = 0; i < updateItems.Size(); i++)\r
+  {\r
+    lps->InSize = lps->OutSize = complexity;\r
+    RINOK(lps->SetCur());\r
+\r
+    const CUpdateItem &ui = updateItems[i];\r
+    CItem item;\r
+    if (ui.NewProps)\r
+    {\r
+      item.Mode = ui.Mode;\r
+      item.Name = ui.Name;\r
+      item.User = ui.User;\r
+      item.Group = ui.Group;\r
+      if (ui.IsDir)\r
+      {\r
+        item.LinkFlag = NFileHeader::NLinkFlag::kDirectory;\r
+        item.Size = 0;\r
+      }\r
+      else\r
+      {\r
+        item.LinkFlag = NFileHeader::NLinkFlag::kNormal;\r
+        item.Size = ui.Size;\r
+      }\r
+      item.MTime = ui.Time;\r
+      item.DeviceMajorDefined = false;\r
+      item.DeviceMinorDefined = false;\r
+      item.UID = 0;\r
+      item.GID = 0;\r
+      memmove(item.Magic, NFileHeader::NMagic::kEmpty, 8);\r
+    }\r
+    else\r
+      item = inputItems[ui.IndexInArchive];\r
+\r
+    if (ui.NewData)\r
+    {\r
+      item.Size = ui.Size;\r
+      if (item.Size == (UInt64)(Int64)-1)\r
+        return E_INVALIDARG;\r
+    }\r
+    else\r
+      item.Size = inputItems[ui.IndexInArchive].Size;\r
+  \r
+    if (ui.NewData)\r
+    {\r
+      CMyComPtr<ISequentialInStream> fileInStream;\r
+      HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream);\r
+      if (res != S_FALSE)\r
+      {\r
+        RINOK(res);\r
+        RINOK(outArchive.WriteHeader(item));\r
+        if (!ui.IsDir)\r
+        {\r
+          RINOK(copyCoder->Code(fileInStream, outStream, NULL, NULL, progress));\r
+          if (copyCoderSpec->TotalSize != item.Size)\r
+            return E_FAIL;\r
+          RINOK(outArchive.FillDataResidual(item.Size));\r
+        }\r
+      }\r
+      complexity += ui.Size;\r
+      RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));\r
+    }\r
+    else\r
+    {\r
+      const CItemEx &existItem = inputItems[ui.IndexInArchive];\r
+      UInt64 size;\r
+      if (ui.NewProps)\r
+      {\r
+        RINOK(outArchive.WriteHeader(item));\r
+        RINOK(inStream->Seek(existItem.GetDataPosition(), STREAM_SEEK_SET, NULL));\r
+        size = existItem.Size;\r
+      }\r
+      else\r
+      {\r
+        RINOK(inStream->Seek(existItem.HeaderPos, STREAM_SEEK_SET, NULL));\r
+        size = existItem.GetFullSize();\r
+      }\r
+      streamSpec->Init(size);\r
+\r
+      RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress));\r
+      if (copyCoderSpec->TotalSize != size)\r
+        return E_FAIL;\r
+      RINOK(outArchive.FillDataResidual(existItem.Size));\r
+      complexity += size;\r
+    }\r
+  }\r
+  return outArchive.WriteFinishHeader();\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Tar/TarUpdate.h b/CPP/7zip/Archive/Tar/TarUpdate.h
new file mode 100755 (executable)
index 0000000..78461c9
--- /dev/null
@@ -0,0 +1,34 @@
+// TarUpdate.h\r
+\r
+#ifndef __TAR_UPDATE_H\r
+#define __TAR_UPDATE_H\r
+\r
+#include "../IArchive.h"\r
+#include "TarItem.h"\r
+\r
+namespace NArchive {\r
+namespace NTar {\r
+\r
+struct CUpdateItem\r
+{\r
+  int IndexInArchive;\r
+  int IndexInClient;\r
+  UInt32 Time;\r
+  UInt32 Mode;\r
+  UInt64 Size;\r
+  AString Name;\r
+  AString User;\r
+  AString Group;\r
+  bool NewData;\r
+  bool NewProps;\r
+  bool IsDir;\r
+};\r
+\r
+HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,\r
+    const CObjectVector<CItemEx> &inputItems,\r
+    const CObjectVector<CUpdateItem> &updateItems,\r
+    IArchiveUpdateCallback *updateCallback);\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Udf/StdAfx.h b/CPP/7zip/Archive/Udf/StdAfx.h
new file mode 100755 (executable)
index 0000000..a4e6173
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+#include "../../../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Udf/UdfHandler.cpp b/CPP/7zip/Archive/Udf/UdfHandler.cpp
new file mode 100755 (executable)
index 0000000..a1df87f
--- /dev/null
@@ -0,0 +1,451 @@
+// UdfHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../../Common/LimitedStreams.h"\r
+#include "../../Common/ProgressUtils.h"\r
+#include "../../Common/StreamObjects.h"\r
+\r
+#include "../../Compress/CopyCoder.h"\r
+\r
+#include "UdfHandler.h"\r
+\r
+namespace NArchive {\r
+namespace NUdf {\r
+\r
+void UdfTimeToFileTime(const CTime &t, NWindows::NCOM::CPropVariant &prop)\r
+{\r
+  UInt64 numSecs;\r
+  const Byte *d = t.Data;\r
+  if (!NWindows::NTime::GetSecondsSince1601(t.GetYear(), d[4], d[5], d[6], d[7], d[8], numSecs))\r
+    return;\r
+  if (t.IsLocal())\r
+    numSecs -= t.GetMinutesOffset() * 60;\r
+  FILETIME ft;\r
+  UInt64 v = (((numSecs * 100 + d[9]) * 100 + d[10]) * 100 + d[11]) * 10;\r
+  ft.dwLowDateTime = (UInt32)v;\r
+  ft.dwHighDateTime = (UInt32)(v >> 32);\r
+  prop = ft;\r
+}\r
+\r
+static STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidIsDir, VT_BOOL},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidATime, VT_FILETIME}\r
+};\r
+\r
+static STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidComment, VT_BSTR},\r
+  { NULL, kpidClusterSize, VT_UI4},\r
+  { NULL, kpidCTime, VT_FILETIME}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidComment:\r
+    {\r
+      UString comment = _archive.GetComment();\r
+      if (!comment.IsEmpty())\r
+        prop = comment;\r
+      break;\r
+    }\r
+\r
+    case kpidClusterSize:\r
+      if (_archive.LogVols.Size() > 0)\r
+      {\r
+        UInt32 blockSize = _archive.LogVols[0].BlockSize;\r
+        int i;\r
+        for (i = 1; i < _archive.LogVols.Size(); i++)\r
+          if (_archive.LogVols[i].BlockSize != blockSize)\r
+            break;\r
+        if (i == _archive.LogVols.Size())\r
+          prop = blockSize;\r
+      }\r
+      break;\r
+\r
+    case kpidCTime:\r
+      if (_archive.LogVols.Size() == 1)\r
+      {\r
+        const CLogVol &vol = _archive.LogVols[0];\r
+        if (vol.FileSets.Size() >= 1)\r
+          UdfTimeToFileTime(vol.FileSets[0].RecodringTime, prop);\r
+      }\r
+      break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+class CProgressImp: public CProgressVirt\r
+{\r
+  CMyComPtr<IArchiveOpenCallback> _callback;\r
+  UInt64 _numFiles;\r
+  UInt64 _numBytes;\r
+public:\r
+  HRESULT SetTotal(UInt64 numBytes);\r
+  HRESULT SetCompleted(UInt64 numFiles, UInt64 numBytes);\r
+  HRESULT SetCompleted();\r
+  CProgressImp(IArchiveOpenCallback *callback): _callback(callback), _numFiles(0), _numBytes(0) {}\r
+};\r
+\r
+HRESULT CProgressImp::SetTotal(UInt64 numBytes)\r
+{\r
+  if (_callback)\r
+    return _callback->SetTotal(NULL, &numBytes);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CProgressImp::SetCompleted(UInt64 numFiles, UInt64 numBytes)\r
+{\r
+  _numFiles = numFiles;\r
+  _numBytes = numBytes;\r
+  return SetCompleted();\r
+}\r
+\r
+HRESULT CProgressImp::SetCompleted()\r
+{\r
+  if (_callback)\r
+    return _callback->SetCompleted(&_numFiles, &_numBytes);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream,\r
+    const UInt64 * /* maxCheckStartPosition */,\r
+    IArchiveOpenCallback *callback)\r
+{\r
+  COM_TRY_BEGIN\r
+  {\r
+    Close();\r
+    CProgressImp progressImp(callback);\r
+    RINOK(_archive.Open(stream, &progressImp));\r
+    bool showVolName = (_archive.LogVols.Size() > 1);\r
+    for (int volIndex = 0; volIndex < _archive.LogVols.Size(); volIndex++)\r
+    {\r
+      const CLogVol &vol = _archive.LogVols[volIndex];\r
+      bool showFileSetName = (vol.FileSets.Size() > 1);\r
+      for (int fsIndex = 0; fsIndex < vol.FileSets.Size(); fsIndex++)\r
+      {\r
+        const CFileSet &fs = vol.FileSets[fsIndex];\r
+        for (int i = ((showVolName || showFileSetName) ? 0 : 1); i < fs.Refs.Size(); i++)\r
+        {\r
+          CRef2 ref2;\r
+          ref2.Vol = volIndex;\r
+          ref2.Fs = fsIndex;\r
+          ref2.Ref = i;\r
+          _refs2.Add(ref2);\r
+        }\r
+      }\r
+    }\r
+    _inStream = stream;\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _inStream.Release();\r
+  _archive.Clear();\r
+  _refs2.Clear();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _refs2.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  {\r
+    const CRef2 &ref2 = _refs2[index];\r
+    const CLogVol &vol = _archive.LogVols[ref2.Vol];\r
+    const CRef &ref = vol.FileSets[ref2.Fs].Refs[ref2.Ref];\r
+    const CFile &file = _archive.Files[ref.FileIndex];\r
+    const CItem &item = _archive.Items[file.ItemIndex];\r
+    switch(propID)\r
+    {\r
+      case kpidPath:  prop = _archive.GetItemPath(ref2.Vol, ref2.Fs, ref2.Ref,\r
+            _archive.LogVols.Size() > 1, vol.FileSets.Size() > 1); break;\r
+      case kpidIsDir:  prop = item.IsDir(); break;\r
+      case kpidSize:      if (!item.IsDir()) prop = (UInt64)item.Size; break;\r
+      case kpidPackSize:  if (!item.IsDir()) prop = (UInt64)item.NumLogBlockRecorded * vol.BlockSize; break;\r
+      case kpidMTime:  UdfTimeToFileTime(item.MTime, prop); break;\r
+      case kpidATime:  UdfTimeToFileTime(item.ATime, prop); break;\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+struct CSeekExtent\r
+{\r
+  UInt64 Phy;\r
+  UInt64 Virt;\r
+};\r
+\r
+class CExtentsStream:\r
+  public IInStream,\r
+  public CMyUnknownImp\r
+{\r
+  UInt64 _phyPos;\r
+  UInt64 _virtPos;\r
+  bool _needStartSeek;\r
+\r
+  HRESULT SeekToPhys() { return Stream->Seek(_phyPos, STREAM_SEEK_SET, NULL); }\r
+\r
+public:\r
+  CMyComPtr<IInStream> Stream;\r
+  CRecordVector<CSeekExtent> Extents;\r
+\r
+  MY_UNKNOWN_IMP1(IInStream)\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);\r
+  void ReleaseStream() { Stream.Release(); }\r
+\r
+  void Init()\r
+  {\r
+    _virtPos = 0;\r
+    _phyPos = 0;\r
+    _needStartSeek = true;\r
+  }\r
+\r
+};\r
+\r
+\r
+STDMETHODIMP CExtentsStream::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize)\r
+    *processedSize = 0;\r
+  if (size > 0)\r
+  {\r
+    UInt64 totalSize = Extents.Back().Virt;\r
+    if (_virtPos >= totalSize)\r
+      return (_virtPos == totalSize) ? S_OK : E_FAIL;\r
+    int left = 0, right = Extents.Size() - 1;\r
+    for (;;)\r
+    {\r
+      int mid = (left + right) / 2;\r
+      if (mid == left)\r
+        break;\r
+      if (_virtPos < Extents[mid].Virt)\r
+        right = mid;\r
+      else\r
+        left = mid;\r
+    }\r
+    \r
+    const CSeekExtent &extent = Extents[left];\r
+    UInt64 phyPos = extent.Phy + (_virtPos - extent.Virt);\r
+    if (_needStartSeek || _phyPos != phyPos)\r
+    {\r
+      _needStartSeek = false;\r
+      _phyPos = phyPos;\r
+      RINOK(SeekToPhys());\r
+    }\r
+\r
+    UInt64 rem = Extents[left + 1].Virt - _virtPos;\r
+    if (size > rem)\r
+      size = (UInt32)rem;\r
\r
+    HRESULT res = Stream->Read(data, size, &size);\r
+    _phyPos += size;\r
+    _virtPos += size;\r
+    if (processedSize)\r
+      *processedSize = size;\r
+    return res;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)\r
+{\r
+  switch(seekOrigin)\r
+  {\r
+    case STREAM_SEEK_SET: _virtPos = offset; break;\r
+    case STREAM_SEEK_CUR: _virtPos += offset; break;\r
+    case STREAM_SEEK_END: _virtPos = Extents.Back().Virt + offset; break;\r
+    default: return STG_E_INVALIDFUNCTION;\r
+  }\r
+  if (newPosition)\r
+    *newPosition = _virtPos;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)\r
+{\r
+  *stream = 0;\r
+\r
+  const CRef2 &ref2 = _refs2[index];\r
+  const CLogVol &vol = _archive.LogVols[ref2.Vol];\r
+  const CRef &ref = vol.FileSets[ref2.Fs].Refs[ref2.Ref];\r
+  const CFile &file = _archive.Files[ref.FileIndex];\r
+  const CItem &item = _archive.Items[file.ItemIndex];\r
+  UInt64 size = item.Size;\r
+\r
+  if (!item.IsRecAndAlloc() || !item.CheckChunkSizes() || ! _archive.CheckItemExtents(ref2.Vol, item))\r
+    return E_NOTIMPL;\r
+\r
+  if (item.IsInline)\r
+  {\r
+    CBufInStream *inStreamSpec = new CBufInStream;\r
+    CMyComPtr<ISequentialInStream> inStream = inStreamSpec;\r
+    CReferenceBuf *referenceBuf = new CReferenceBuf;\r
+    CMyComPtr<IUnknown> ref = referenceBuf;\r
+    referenceBuf->Buf = item.InlineData;\r
+    inStreamSpec->Init(referenceBuf);\r
+    *stream = inStream.Detach();\r
+    return S_OK;\r
+  }\r
+\r
+  CExtentsStream *extentStreamSpec = new CExtentsStream();\r
+  CMyComPtr<ISequentialInStream> extentStream = extentStreamSpec;\r
+  \r
+  extentStreamSpec->Stream = _inStream;\r
+\r
+  UInt64 virtOffset = 0;\r
+  for (int extentIndex = 0; extentIndex < item.Extents.Size(); extentIndex++)\r
+  {\r
+    const CMyExtent &extent = item.Extents[extentIndex];\r
+    UInt32 len = extent.GetLen();\r
+    if (len == 0)\r
+      continue;\r
+    if (size < len)\r
+      return S_FALSE;\r
+      \r
+    int partitionIndex = vol.PartitionMaps[extent.PartitionRef].PartitionIndex;\r
+    UInt32 logBlockNumber = extent.Pos;\r
+    const CPartition &partition = _archive.Partitions[partitionIndex];\r
+    UInt64 offset = ((UInt64)partition.Pos << _archive.SecLogSize) +\r
+      (UInt64)logBlockNumber * vol.BlockSize;\r
+      \r
+    CSeekExtent se;\r
+    se.Phy = offset;\r
+    se.Virt = virtOffset;\r
+    virtOffset += len;\r
+    extentStreamSpec->Extents.Add(se);\r
+\r
+    size -= len;\r
+  }\r
+  if (size != 0)\r
+    return S_FALSE;\r
+  CSeekExtent se;\r
+  se.Phy = 0;\r
+  se.Virt = virtOffset;\r
+  extentStreamSpec->Extents.Add(se);\r
+  extentStreamSpec->Init();\r
+  *stream = extentStream.Detach();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _refs2.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt64 totalSize = 0;\r
+  UInt32 i;\r
+\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    UInt32 index = (allFilesMode ? i : indices[i]);\r
+    const CRef2 &ref2 = _refs2[index];\r
+    const CRef &ref = _archive.LogVols[ref2.Vol].FileSets[ref2.Fs].Refs[ref2.Ref];\r
+    const CFile &file = _archive.Files[ref.FileIndex];\r
+    const CItem &item = _archive.Items[file.ItemIndex];\r
+    if (!item.IsDir())\r
+      totalSize += item.Size;\r
+  }\r
+  extractCallback->SetTotal(totalSize);\r
+\r
+  UInt64 currentTotalSize = 0;\r
+  \r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream;\r
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\r
+\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    lps->InSize = lps->OutSize = currentTotalSize;\r
+    RINOK(lps->SetCur());\r
+    CMyComPtr<ISequentialOutStream> realOutStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    UInt32 index = allFilesMode ? i : indices[i];\r
+    \r
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+\r
+    const CRef2 &ref2 = _refs2[index];\r
+    const CRef &ref = _archive.LogVols[ref2.Vol].FileSets[ref2.Fs].Refs[ref2.Ref];\r
+    const CFile &file = _archive.Files[ref.FileIndex];\r
+    const CItem &item = _archive.Items[file.ItemIndex];\r
+\r
+    if (item.IsDir())\r
+    {\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+      continue;\r
+    }\r
+    currentTotalSize += item.Size;\r
+\r
+    if (!testMode && !realOutStream)\r
+      continue;\r
+\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+    outStreamSpec->SetStream(realOutStream);\r
+    realOutStream.Release();\r
+    outStreamSpec->Init(item.Size);\r
+    Int32 opRes;\r
+    CMyComPtr<ISequentialInStream> udfInStream;\r
+    HRESULT res = GetStream(index, &udfInStream);\r
+    if (res == E_NOTIMPL)\r
+      opRes = NExtract::NOperationResult::kUnSupportedMethod;\r
+    else if (res != S_OK)\r
+      opRes = NExtract::NOperationResult::kDataError;\r
+    else\r
+    {\r
+      RINOK(copyCoder->Code(udfInStream, outStream, NULL, NULL, progress));\r
+      opRes = outStreamSpec->IsFinishedOK() ?\r
+        NExtract::NOperationResult::kOK:\r
+        NExtract::NOperationResult::kDataError;\r
+    }\r
+    outStreamSpec->ReleaseStream();\r
+    RINOK(extractCallback->SetOperationResult(opRes));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Udf/UdfHandler.h b/CPP/7zip/Archive/Udf/UdfHandler.h
new file mode 100755 (executable)
index 0000000..20af208
--- /dev/null
@@ -0,0 +1,37 @@
+// Udf/Handler.h\r
+\r
+#ifndef __UDF_HANDLER_H\r
+#define __UDF_HANDLER_H\r
+\r
+#include "Common/MyCom.h"\r
+#include "../IArchive.h"\r
+\r
+#include "UdfIn.h"\r
+\r
+namespace NArchive {\r
+namespace NUdf {\r
+\r
+struct CRef2\r
+{\r
+  int Vol;\r
+  int Fs;\r
+  int Ref;\r
+};\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IInArchiveGetStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<IInStream> _inStream;\r
+  CInArchive _archive;\r
+  CRecordVector<CRef2> _refs2;\r
+public:\r
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp
new file mode 100755 (executable)
index 0000000..d9b987f
--- /dev/null
@@ -0,0 +1,876 @@
+// Archive/UdfIn.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/CpuArch.h"\r
+\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "UdfIn.h"\r
+\r
+#define Get16(p) GetUi16(p)\r
+#define Get32(p) GetUi32(p)\r
+#define Get64(p) GetUi64(p)\r
+\r
+namespace NArchive {\r
+namespace NUdf {\r
+\r
+const int kNumPartitionsMax = 64;\r
+const int kNumLogVolumesMax = 64;\r
+const int kNumRecureseLevelsMax = 1 << 10;\r
+const int kNumItemsMax = 1 << 27;\r
+const int kNumFilesMax = 1 << 28;\r
+const int kNumRefsMax = 1 << 28;\r
+const UInt32 kNumExtentsMax = (UInt32)1 << 30;\r
+const UInt64 kFileNameLengthTotalMax = (UInt64)1 << 33;\r
+const UInt64 kInlineExtentsSizeMax = (UInt64)1 << 33;\r
+\r
+void MY_FAST_CALL Crc16GenerateTable(void);\r
+\r
+#define CRC16_INIT_VAL 0\r
+#define CRC16_GET_DIGEST(crc) (crc)\r
+#define CRC16_UPDATE_BYTE(crc, b) (g_Crc16Table[(((crc) >> 8) ^ (b)) & 0xFF] ^ ((crc) << 8))\r
+\r
+#define kCrc16Poly 0x1021\r
+UInt16 g_Crc16Table[256];\r
+\r
+void MY_FAST_CALL Crc16GenerateTable(void)\r
+{\r
+  UInt32 i;\r
+  for (i = 0; i < 256; i++)\r
+  {\r
+    UInt32 r = (i << 8);\r
+    for (int j = 8; j > 0; j--)\r
+      r = ((r & 0x8000) ? ((r << 1) ^ kCrc16Poly) : (r << 1)) & 0xFFFF;\r
+    g_Crc16Table[i] = (UInt16)r;\r
+  }\r
+}\r
+\r
+UInt16 MY_FAST_CALL Crc16_Update(UInt16 v, const void *data, size_t size)\r
+{\r
+  const Byte *p = (const Byte *)data;\r
+  for (; size > 0 ; size--, p++)\r
+    v = CRC16_UPDATE_BYTE(v, *p);\r
+  return v;\r
+}\r
+\r
+UInt16 MY_FAST_CALL Crc16Calc(const void *data, size_t size)\r
+{\r
+  return Crc16_Update(CRC16_INIT_VAL, data, size);\r
+}\r
+\r
+struct CCrc16TableInit { CCrc16TableInit() { Crc16GenerateTable(); } } g_Crc16TableInit;\r
+\r
+void CDString128::Parse(const Byte *buf) { memcpy(Data, buf, sizeof(Data)); }\r
+\r
+void CDString::Parse(const Byte *p, unsigned size)\r
+{\r
+  Data.SetCapacity(size);\r
+  memcpy(Data, p, size);\r
+}\r
+\r
+static UString ParseDString(const Byte *data, int size)\r
+{\r
+  UString res;\r
+  wchar_t *p;\r
+  if (size > 0)\r
+  {\r
+    Byte type = data[0];\r
+    if (type == 8)\r
+    {\r
+      p = res.GetBuffer((int)size + 1);\r
+      for (int i = 1; i < size; i++)\r
+      {\r
+        wchar_t c = data[i];\r
+        if (c == 0)\r
+          break;\r
+        *p++ = c;\r
+      }\r
+    }\r
+    else if (type == 16)\r
+    {\r
+      p = res.GetBuffer((int)size / 2 + 1);\r
+      for (int i = 1; i + 2 <= size; i += 2)\r
+      {\r
+        wchar_t c = ((wchar_t)data[i] << 8) | data[i + 1];\r
+        if (c == 0)\r
+          break;\r
+        *p++ = c;\r
+      }\r
+    }\r
+    else\r
+      return L"[unknow]";\r
+    *p++ = 0;\r
+    res.ReleaseBuffer();\r
+  }\r
+  return res;\r
+}\r
+\r
+UString CDString::   GetString() const { return ParseDString(Data, (int)Data.GetCapacity()); }\r
+UString CDString128::GetString() const\r
+{\r
+  int size = Data[sizeof(Data) - 1];\r
+  return ParseDString(Data, MyMin(size, (int)(sizeof(Data) - 1)));\r
+}\r
+\r
+void CTime::Parse(const Byte *buf) { memcpy(Data, buf, sizeof(Data)); }\r
+\r
+/*\r
+void CRegId::Parse(const Byte *buf)\r
+{\r
+  Flags = buf[0];\r
+  memcpy(Id, buf + 1, sizeof(Id));\r
+  memcpy(Suffix, buf + 24, sizeof(Suffix));\r
+}\r
+*/\r
+\r
+// ECMA 3/7.1\r
+\r
+struct CExtent\r
+{\r
+  UInt32 Len;\r
+  UInt32 Pos;\r
+\r
+  void Parse(const Byte *buf);\r
+};\r
+\r
+void CExtent::Parse(const Byte *buf)\r
+{\r
+  Len = Get32(buf);\r
+  Pos = Get32(buf + 4);\r
+}\r
+\r
+// ECMA 3/7.2\r
+\r
+struct CTag\r
+{\r
+  UInt16 Id;\r
+  UInt16 Version;\r
+  // Byte Checksum;\r
+  // UInt16 SerialNumber;\r
+  // UInt16 Crc;\r
+  // UInt16 CrcLen;\r
+  // UInt32 TagLocation;\r
+  \r
+  HRESULT Parse(const Byte *buf, size_t size);\r
+};\r
+\r
+HRESULT CTag::Parse(const Byte *buf, size_t size)\r
+{\r
+  if (size < 16)\r
+    return S_FALSE;\r
+  Byte sum = 0;\r
+  int i;\r
+  for (i = 0; i <  4; i++) sum = sum + buf[i];\r
+  for (i = 5; i < 16; i++) sum = sum + buf[i];\r
+  if (sum != buf[4] || buf[5] != 0) return S_FALSE;\r
+\r
+  Id = Get16(buf);\r
+  Version = Get16(buf + 2);\r
+  // SerialNumber = Get16(buf + 6);\r
+  UInt16 crc = Get16(buf + 8);\r
+  UInt16 crcLen = Get16(buf + 10);\r
+  // TagLocation = Get32(buf + 12);\r
+\r
+  if (size >= 16 + (size_t)crcLen)\r
+    if (crc == Crc16Calc(buf + 16, crcLen))\r
+      return S_OK;\r
+  return S_FALSE;\r
+}\r
+\r
+// ECMA 3/7.2.1\r
+\r
+enum EDescriptorType\r
+{\r
+  DESC_TYPE_SpoaringTable = 0, // UDF\r
+  DESC_TYPE_PrimVol = 1,\r
+  DESC_TYPE_AnchorVolPtr = 2,\r
+  DESC_TYPE_VolPtr = 3,\r
+  DESC_TYPE_ImplUseVol = 4,\r
+  DESC_TYPE_Partition = 5,\r
+  DESC_TYPE_LogicalVol = 6,\r
+  DESC_TYPE_UnallocSpace = 7,\r
+  DESC_TYPE_Terminating = 8,\r
+  DESC_TYPE_LogicalVolIntegrity = 9,\r
+  DESC_TYPE_FileSet = 256,\r
+  DESC_TYPE_FileId  = 257,\r
+  DESC_TYPE_AllocationExtent = 258,\r
+  DESC_TYPE_Indirect = 259,\r
+  DESC_TYPE_Terminal = 260,\r
+  DESC_TYPE_File = 261,\r
+  DESC_TYPE_ExtendedAttrHeader = 262,\r
+  DESC_TYPE_UnallocatedSpace = 263,\r
+  DESC_TYPE_SpaceBitmap = 264,\r
+  DESC_TYPE_PartitionIntegrity = 265,\r
+  DESC_TYPE_ExtendedFile = 266\r
+};\r
+\r
+\r
+void CLogBlockAddr::Parse(const Byte *buf)\r
+{\r
+  Pos = Get32(buf);\r
+  PartitionRef = Get16(buf + 4);\r
+}\r
+\r
+void CShortAllocDesc::Parse(const Byte *buf)\r
+{\r
+  Len = Get32(buf);\r
+  Pos = Get32(buf + 4);\r
+}\r
+\r
+/*\r
+void CADImpUse::Parse(const Byte *buf)\r
+{\r
+  Flags = Get16(buf);\r
+  UdfUniqueId = Get32(buf + 2);\r
+}\r
+*/\r
+\r
+void CLongAllocDesc::Parse(const Byte *buf)\r
+{\r
+  Len = Get32(buf);\r
+  Location.Parse(buf + 4);\r
+  // memcpy(ImplUse, buf + 10, sizeof(ImplUse));\r
+  // adImpUse.Parse(ImplUse);\r
+}\r
+\r
+bool CInArchive::CheckExtent(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len) const\r
+{\r
+  const CLogVol &vol = LogVols[volIndex];\r
+  const CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex];\r
+  UInt64 offset = ((UInt64)partition.Pos << SecLogSize) + (UInt64)blockPos * vol.BlockSize;\r
+  return (offset + len) <= (((UInt64)partition.Pos + partition.Len) << SecLogSize);\r
+}\r
+\r
+bool CInArchive::CheckItemExtents(int volIndex, const CItem &item) const\r
+{\r
+  for (int i = 0; i < item.Extents.Size(); i++)\r
+  {\r
+    const CMyExtent &e = item.Extents[i];\r
+    if (!CheckExtent(volIndex, e.PartitionRef, e.Pos, e.GetLen()))\r
+      return false;\r
+  }\r
+  return true;\r
+}\r
+\r
+HRESULT CInArchive::Read(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len, Byte *buf)\r
+{\r
+  if (!CheckExtent(volIndex, partitionRef, blockPos, len))\r
+    return S_FALSE;\r
+  const CLogVol &vol = LogVols[volIndex];\r
+  const CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex];\r
+  RINOK(_stream->Seek(((UInt64)partition.Pos << SecLogSize) +\r
+      (UInt64)blockPos * vol.BlockSize, STREAM_SEEK_SET, NULL));\r
+  return ReadStream_FALSE(_stream, buf, len);\r
+}\r
+\r
+HRESULT CInArchive::Read(int volIndex, const CLongAllocDesc &lad, Byte *buf)\r
+{\r
+  return Read(volIndex, lad.Location.PartitionRef, lad.Location.Pos, lad.GetLen(), (Byte *)buf);\r
+}\r
+\r
+HRESULT CInArchive::ReadFromFile(int volIndex, const CItem &item, CByteBuffer &buf)\r
+{\r
+  if (item.Size >= (UInt32)1 << 30)\r
+    return S_FALSE;\r
+  if (item.IsInline)\r
+  {\r
+    buf = item.InlineData;\r
+    return S_OK;\r
+  }\r
+  buf.SetCapacity((size_t)item.Size);\r
+  size_t pos = 0;\r
+  for (int i = 0; i < item.Extents.Size(); i++)\r
+  {\r
+    const CMyExtent &e = item.Extents[i];\r
+    UInt32 len = e.GetLen();\r
+    RINOK(Read(volIndex, e.PartitionRef, e.Pos, len, (Byte *)buf + pos));\r
+    pos += len;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+\r
+void CIcbTag::Parse(const Byte *p)\r
+{\r
+  // PriorDirectNum = Get32(p);\r
+  // StrategyType = Get16(p + 4);\r
+  // StrategyParam = Get16(p + 6);\r
+  // MaxNumOfEntries = Get16(p + 8);\r
+  FileType = p[11];\r
+  // ParentIcb.Parse(p + 12);\r
+  Flags = Get16(p + 18);\r
+}\r
+\r
+void CItem::Parse(const Byte *p)\r
+{\r
+  // Uid = Get32(p + 36);\r
+  // Gid = Get32(p + 40);\r
+  // Permissions = Get32(p + 44);\r
+  // FileLinkCount = Get16(p + 48);\r
+  // RecordFormat = p[50];\r
+  // RecordDisplayAttr = p[51];\r
+  // RecordLen = Get32(p + 52);\r
+  Size = Get64(p + 56);\r
+  NumLogBlockRecorded = Get64(p + 64);\r
+  ATime.Parse(p + 72);\r
+  MTime.Parse(p + 84);\r
+  // AttrtTime.Parse(p + 96);\r
+  // CheckPoint = Get32(p + 108);\r
+  // ExtendedAttrIcb.Parse(p + 112);\r
+  // ImplId.Parse(p + 128);\r
+  // UniqueId = Get64(p + 160);\r
+}\r
+\r
+// 4/14.4\r
+struct CFileId\r
+{\r
+  // UInt16 FileVersion;\r
+  Byte FileCharacteristics;\r
+  // CByteBuffer ImplUse;\r
+  CDString Id;\r
+  CLongAllocDesc Icb;\r
+\r
+  bool IsItLinkParent() const { return (FileCharacteristics & FILEID_CHARACS_Parent) != 0; }\r
+  HRESULT Parse(const Byte *p, size_t size, size_t &processed);\r
+};\r
+\r
+HRESULT CFileId::Parse(const Byte *p, size_t size, size_t &processed)\r
+{\r
+  processed = 0;\r
+  if (size < 38)\r
+    return S_FALSE;\r
+  CTag tag;\r
+  RINOK(tag.Parse(p, size));\r
+  if (tag.Id != DESC_TYPE_FileId)\r
+    return S_FALSE;\r
+  // FileVersion = Get16(p + 16);\r
+  FileCharacteristics = p[18];\r
+  unsigned idLen = p[19];\r
+  Icb.Parse(p + 20);\r
+  unsigned impLen = Get16(p + 36);\r
+  if (size < 38 + idLen + impLen)\r
+    return S_FALSE;\r
+  // ImplUse.SetCapacity(impLen);\r
+  processed = 38;\r
+  // memcpy(ImplUse, p + processed, impLen);\r
+  processed += impLen;\r
+  Id.Parse(p + processed, idLen);\r
+  processed += idLen;\r
+  for (;(processed & 3) != 0; processed++)\r
+    if (p[processed] != 0)\r
+      return S_FALSE;\r
+  return (processed <= size) ? S_OK : S_FALSE;\r
+}\r
+\r
+HRESULT CInArchive::ReadFileItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed)\r
+{\r
+  if (Files.Size() % 100 == 0)\r
+    RINOK(_progress->SetCompleted(Files.Size(), _processedProgressBytes));\r
+  if (numRecurseAllowed-- == 0)\r
+    return S_FALSE;\r
+  CFile &file = Files.Back();\r
+  const CLogVol &vol = LogVols[volIndex];\r
+  CPartition &partition = Partitions[vol.PartitionMaps[lad.Location.PartitionRef].PartitionIndex];\r
+\r
+  UInt32 key = lad.Location.Pos;\r
+  UInt32 value;\r
+  const UInt32 kRecursedErrorValue = (UInt32)(Int32)-1;\r
+  if (partition.Map.Find(key, value))\r
+  {\r
+    if (value == kRecursedErrorValue)\r
+      return S_FALSE;\r
+    file.ItemIndex = value;\r
+  }\r
+  else\r
+  {\r
+    value = Items.Size();\r
+    file.ItemIndex = (int)value;\r
+    if (partition.Map.Set(key, kRecursedErrorValue))\r
+      return S_FALSE;\r
+    RINOK(ReadItem(volIndex, fsIndex, lad, numRecurseAllowed));\r
+    if (!partition.Map.Set(key, value))\r
+      return S_FALSE;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed)\r
+{\r
+  if (Items.Size() > kNumItemsMax)\r
+    return S_FALSE;\r
+  Items.Add(CItem());\r
+  CItem &item = Items.Back();\r
+  \r
+  const CLogVol &vol = LogVols[volIndex];\r
\r
+  if (lad.GetLen() != vol.BlockSize)\r
+    return S_FALSE;\r
+\r
+  CByteBuffer buf;\r
+  size_t size = lad.GetLen();\r
+  buf.SetCapacity(size);\r
+  RINOK(Read(volIndex, lad, buf));\r
+\r
+  CTag tag;\r
+  const Byte *p = buf;\r
+  RINOK(tag.Parse(p, size));\r
+  if (tag.Id != DESC_TYPE_File)\r
+    return S_FALSE;\r
+\r
+  item.IcbTag.Parse(p + 16);\r
+  if (item.IcbTag.FileType != ICB_FILE_TYPE_DIR &&\r
+      item.IcbTag.FileType != ICB_FILE_TYPE_FILE)\r
+    return S_FALSE;\r
+\r
+  item.Parse(p);\r
+\r
+  _processedProgressBytes += (UInt64)item.NumLogBlockRecorded * vol.BlockSize + size;\r
+\r
+  UInt32 extendedAttrLen = Get32(p + 168);\r
+  UInt32 allocDescriptorsLen = Get32(p + 172);\r
+\r
+  if ((extendedAttrLen & 3) != 0)\r
+    return S_FALSE;\r
+  int pos = 176;\r
+  if (extendedAttrLen > size - pos)\r
+    return S_FALSE;\r
+  /*\r
+  if (extendedAttrLen != 16)\r
+  {\r
+    if (extendedAttrLen < 24)\r
+      return S_FALSE;\r
+    CTag attrTag;\r
+    RINOK(attrTag.Parse(p + pos, size));\r
+    if (attrTag.Id != DESC_TYPE_ExtendedAttrHeader)\r
+      return S_FALSE;\r
+    // UInt32 implAttrLocation = Get32(p + pos + 16);\r
+    // UInt32 applicationlAttrLocation = Get32(p + pos + 20);\r
+  }\r
+  */\r
+  pos += extendedAttrLen;\r
+\r
+  int desctType = item.IcbTag.GetDescriptorType();\r
+  if (allocDescriptorsLen > size - pos)\r
+    return S_FALSE;\r
+  if (desctType == ICB_DESC_TYPE_INLINE)\r
+  {\r
+    item.IsInline = true;\r
+    item.InlineData.SetCapacity(allocDescriptorsLen);\r
+    memcpy(item.InlineData, p + pos, allocDescriptorsLen);\r
+  }\r
+  else\r
+  {\r
+    item.IsInline = false;\r
+    if (desctType != ICB_DESC_TYPE_SHORT && desctType != ICB_DESC_TYPE_LONG)\r
+      return S_FALSE;\r
+    for (UInt32 i = 0; i < allocDescriptorsLen;)\r
+    {\r
+      CMyExtent e;\r
+      if (desctType == ICB_DESC_TYPE_SHORT)\r
+      {\r
+        if (i + 8 > allocDescriptorsLen)\r
+          return S_FALSE;\r
+        CShortAllocDesc sad;\r
+        sad.Parse(p + pos + i);\r
+        e.Pos = sad.Pos;\r
+        e.Len = sad.Len;\r
+        e.PartitionRef = lad.Location.PartitionRef;\r
+        i += 8;\r
+      }\r
+      else\r
+      {\r
+        if (i + 16 > allocDescriptorsLen)\r
+          return S_FALSE;\r
+        CLongAllocDesc ladNew;\r
+        ladNew.Parse(p + pos + i);\r
+        e.Pos = ladNew.Location.Pos;\r
+        e.PartitionRef = ladNew.Location.PartitionRef;\r
+        e.Len = ladNew.Len;\r
+        i += 16;\r
+      }\r
+      item.Extents.Add(e);\r
+    }\r
+  }\r
+\r
+  if (item.IcbTag.IsDir())\r
+  {\r
+    if (!item.CheckChunkSizes() || !CheckItemExtents(volIndex, item))\r
+      return S_FALSE;\r
+    CByteBuffer buf;\r
+    RINOK(ReadFromFile(volIndex, item, buf));\r
+    item.Size = 0;\r
+    item.Extents.ClearAndFree();\r
+    item.InlineData.Free();\r
+\r
+    const Byte *p = buf;\r
+    size = buf.GetCapacity();\r
+    size_t processedTotal = 0;\r
+    for (; processedTotal < size;)\r
+    {\r
+      size_t processedCur;\r
+      CFileId fileId;\r
+      RINOK(fileId.Parse(p + processedTotal, size - processedTotal, processedCur));\r
+      if (!fileId.IsItLinkParent())\r
+      {\r
+        CFile file;\r
+        // file.FileVersion = fileId.FileVersion;\r
+        // file.FileCharacteristics = fileId.FileCharacteristics;\r
+        // file.ImplUse = fileId.ImplUse;\r
+        file.Id = fileId.Id;\r
+        \r
+        _fileNameLengthTotal += file.Id.Data.GetCapacity();\r
+        if (_fileNameLengthTotal > kFileNameLengthTotalMax)\r
+          return S_FALSE;\r
+        \r
+        item.SubFiles.Add(Files.Size());\r
+        if (Files.Size() > kNumFilesMax)\r
+          return S_FALSE;\r
+        Files.Add(file);\r
+        RINOK(ReadFileItem(volIndex, fsIndex, fileId.Icb, numRecurseAllowed));\r
+      }\r
+      processedTotal += processedCur;\r
+    }\r
+  }\r
+  else\r
+  {\r
+    if ((UInt32)item.Extents.Size() > kNumExtentsMax - _numExtents)\r
+      return S_FALSE;\r
+    _numExtents += item.Extents.Size();\r
+\r
+    if (item.InlineData.GetCapacity() > kInlineExtentsSizeMax - _inlineExtentsSize)\r
+      return S_FALSE;\r
+    _inlineExtentsSize += item.InlineData.GetCapacity();\r
+  }\r
+\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::FillRefs(CFileSet &fs, int fileIndex, int parent, int numRecurseAllowed)\r
+{\r
+  if (_numRefs % 10000 == 0)\r
+  {\r
+    RINOK(_progress->SetCompleted());\r
+  }\r
+  if (numRecurseAllowed-- == 0)\r
+    return S_FALSE;\r
+  if (_numRefs >= kNumRefsMax)\r
+    return S_FALSE;\r
+  _numRefs++;\r
+  CRef ref;\r
+  ref.FileIndex = fileIndex;\r
+  ref.Parent = parent;\r
+  parent = fs.Refs.Size();\r
+  fs.Refs.Add(ref);\r
+  const CItem &item = Items[Files[fileIndex].ItemIndex];\r
+  for (int i = 0; i < item.SubFiles.Size(); i++)\r
+  {\r
+    RINOK(FillRefs(fs, item.SubFiles[i], parent, numRecurseAllowed));\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::Open2()\r
+{\r
+  Clear();\r
+\r
+  UInt64 fileSize;\r
+  RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize));\r
+\r
+  // Some UDFs contain additional 2 KB of zeros, so we also check 12, corrected to 11.\r
+  const int kSecLogSizeMax = 12;\r
+  Byte buf[1 << kSecLogSizeMax];\r
+  Byte kSizesLog[] = { 11, 8, 12 };\r
+\r
+  for (int i = 0;; i++)\r
+  {\r
+    if (i == sizeof(kSizesLog) / sizeof(kSizesLog[0]))\r
+      return S_FALSE;\r
+    SecLogSize = kSizesLog[i];\r
+    Int32 bufSize = 1 << SecLogSize;\r
+    if (bufSize > fileSize)\r
+      return S_FALSE;\r
+    RINOK(_stream->Seek(-bufSize, STREAM_SEEK_END, NULL));\r
+    RINOK(ReadStream_FALSE(_stream, buf, bufSize));\r
+    CTag tag;\r
+    if (tag.Parse(buf, bufSize) == S_OK)\r
+      if (tag.Id == DESC_TYPE_AnchorVolPtr)\r
+        break;\r
+  }\r
+  if (SecLogSize == 12)\r
+    SecLogSize = 11;\r
+\r
+  CExtent extentVDS;\r
+  extentVDS.Parse(buf + 16);\r
+\r
+  for (UInt32 location = extentVDS.Pos; ; location++)\r
+  {\r
+    size_t bufSize = 1 << SecLogSize;\r
+    size_t pos = 0;\r
+    RINOK(_stream->Seek((UInt64)location << SecLogSize, STREAM_SEEK_SET, NULL));\r
+    RINOK(ReadStream_FALSE(_stream, buf, bufSize));\r
+    CTag tag;\r
+    RINOK(tag.Parse(buf + pos, bufSize - pos));\r
+    if (tag.Id == DESC_TYPE_Terminating)\r
+      break;\r
+    if (tag.Id == DESC_TYPE_Partition)\r
+    {\r
+      if (Partitions.Size() >= kNumPartitionsMax)\r
+        return S_FALSE;\r
+      CPartition partition;\r
+      // UInt32 volDescSeqNumer = Get32(buf + 16);\r
+      // partition.Flags = Get16(buf + 20);\r
+      partition.Number = Get16(buf + 22);\r
+      // partition.ContentsId.Parse(buf + 24);\r
+      \r
+      // memcpy(partition.ContentsUse, buf + 56, sizeof(partition.ContentsUse));\r
+      // ContentsUse is Partition Header Description.\r
+\r
+      // partition.AccessType = Get32(buf + 184);\r
+      partition.Pos = Get32(buf + 188);\r
+      partition.Len = Get32(buf + 192);\r
+      // partition.ImplId.Parse(buf + 196);\r
+      // memcpy(partition.ImplUse, buf + 228, sizeof(partition.ImplUse));\r
+\r
+      Partitions.Add(partition);\r
+    }\r
+    else if (tag.Id == DESC_TYPE_LogicalVol)\r
+    {\r
+      if (LogVols.Size() >= kNumLogVolumesMax)\r
+        return S_FALSE;\r
+      CLogVol vol;\r
+      vol.Id.Parse(buf + 84);\r
+      vol.BlockSize = Get32(buf + 212);\r
+      // vol.DomainId.Parse(buf + 216);\r
+\r
+      if (vol.BlockSize < 512 || vol.BlockSize > ((UInt32)1 << 30))\r
+        return S_FALSE;\r
+      \r
+      // memcpy(vol.ContentsUse, buf + 248, sizeof(vol.ContentsUse));\r
+      vol.FileSetLocation.Parse(buf + 248);\r
+\r
+      // UInt32 mapTableLength = Get32(buf + 264);\r
+      UInt32 numPartitionMaps = Get32(buf + 268);\r
+      if (numPartitionMaps > kNumPartitionsMax)\r
+        return S_FALSE;\r
+      // vol.ImplId.Parse(buf + 272);\r
+      // memcpy(vol.ImplUse, buf + 128, sizeof(vol.ImplUse));\r
+      size_t pos = 440;\r
+      for (UInt32 i = 0; i < numPartitionMaps; i++)\r
+      {\r
+        if (pos + 2 > bufSize)\r
+          return S_FALSE;\r
+        CPartitionMap pm;\r
+        pm.Type = buf[pos];\r
+        // pm.Length = buf[pos + 1];\r
+        Byte len = buf[pos + 1];\r
+\r
+        if (pos + len > bufSize)\r
+          return S_FALSE;\r
+        \r
+        // memcpy(pm.Data, buf + pos + 2, pm.Length - 2);\r
+        if (pm.Type == 1)\r
+        {\r
+          if (pos + 6 > bufSize)\r
+            return S_FALSE;\r
+          // pm.VolSeqNumber = Get16(buf + pos + 2);\r
+          pm.PartitionNumber = Get16(buf + pos + 4);\r
+        }\r
+        else\r
+          return S_FALSE;\r
+        pos += len;\r
+        vol.PartitionMaps.Add(pm);\r
+      }\r
+      LogVols.Add(vol);\r
+    }\r
+  }\r
+\r
+  UInt64 totalSize = 0;\r
+\r
+  int volIndex;\r
+  for (volIndex = 0; volIndex < LogVols.Size(); volIndex++)\r
+  {\r
+    CLogVol &vol = LogVols[volIndex];\r
+    for (int pmIndex = 0; pmIndex < vol.PartitionMaps.Size(); pmIndex++)\r
+    {\r
+      CPartitionMap &pm = vol.PartitionMaps[pmIndex];\r
+      int i;\r
+      for (i = 0; i < Partitions.Size(); i++)\r
+      {\r
+        CPartition &part = Partitions[i];\r
+        if (part.Number == pm.PartitionNumber)\r
+        {\r
+          if (part.VolIndex >= 0)\r
+            return S_FALSE;\r
+          pm.PartitionIndex = i;\r
+          part.VolIndex = volIndex;\r
+\r
+          totalSize += (UInt64)part.Len << SecLogSize;\r
+          break;\r
+        }\r
+      }\r
+      if (i == Partitions.Size())\r
+        return S_FALSE;\r
+    }\r
+  }\r
+\r
+  RINOK(_progress->SetTotal(totalSize));\r
+\r
+  for (volIndex = 0; volIndex < LogVols.Size(); volIndex++)\r
+  {\r
+    CLogVol &vol = LogVols[volIndex];\r
+\r
+    CLongAllocDesc nextExtent = vol.FileSetLocation;\r
+    // while (nextExtent.ExtentLen != 0)\r
+    // for (int i = 0; i < 1; i++)\r
+    {\r
+      if (nextExtent.GetLen() < 512)\r
+        return S_FALSE;\r
+      CByteBuffer buf;\r
+      buf.SetCapacity(nextExtent.GetLen());\r
+      RINOK(Read(volIndex, nextExtent, buf));\r
+      const Byte *p = buf;\r
+      size_t size = nextExtent.GetLen();\r
+\r
+      CTag tag;\r
+      RINOK(tag.Parse(p, size));\r
+      if (tag.Id != DESC_TYPE_FileSet)\r
+        return S_FALSE;\r
+      \r
+      CFileSet fs;\r
+      fs.RecodringTime.Parse(p + 16);\r
+      // fs.InterchangeLevel = Get16(p + 18);\r
+      // fs.MaxInterchangeLevel = Get16(p + 20);\r
+      // fs.FileSetNumber = Get32(p + 40);\r
+      // fs.FileSetDescNumber = Get32(p + 44);\r
+      \r
+      // fs.Id.Parse(p + 304);\r
+      // fs.CopyrightId.Parse(p + 336);\r
+      // fs.AbstractId.Parse(p + 368);\r
+      \r
+      fs.RootDirICB.Parse(p + 400);\r
+      // fs.DomainId.Parse(p + 416);\r
+      \r
+      // fs.SystemStreamDirICB.Parse(p + 464);\r
+      \r
+      vol.FileSets.Add(fs);\r
+\r
+      // nextExtent.Parse(p + 448);\r
+    }\r
+\r
+    for (int fsIndex = 0; fsIndex < vol.FileSets.Size(); fsIndex++)\r
+    {\r
+      CFileSet &fs = vol.FileSets[fsIndex];\r
+      int fileIndex = Files.Size();\r
+      Files.Add(CFile());\r
+      RINOK(ReadFileItem(volIndex, fsIndex, fs.RootDirICB, kNumRecureseLevelsMax));\r
+      RINOK(FillRefs(fs, fileIndex, -1, kNumRecureseLevelsMax));\r
+    }\r
+  }\r
+\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::Open(IInStream *inStream, CProgressVirt *progress)\r
+{\r
+  _progress = progress;\r
+  _stream = inStream;\r
+  HRESULT res;\r
+  try { res = Open2(); }\r
+  catch(...) { Clear(); res = S_FALSE; }\r
+  _stream.Release();\r
+  return res;\r
+}\r
+\r
+void CInArchive::Clear()\r
+{\r
+  Partitions.Clear();\r
+  LogVols.Clear();\r
+  Items.Clear();\r
+  Files.Clear();\r
+  _fileNameLengthTotal = 0;\r
+  _numRefs = 0;\r
+  _numExtents = 0;\r
+  _inlineExtentsSize = 0;\r
+  _processedProgressBytes = 0;\r
+}\r
+\r
+UString CInArchive::GetComment() const\r
+{\r
+  UString res;\r
+  for (int i = 0; i < LogVols.Size(); i++)\r
+  {\r
+    if (i > 0)\r
+      res += L" ";\r
+    res += LogVols[i].GetName();\r
+  }\r
+  return res;\r
+}\r
+\r
+static UString GetSpecName(const UString &name)\r
+{\r
+  UString name2 = name;\r
+  name2.Trim();\r
+  if (name2.IsEmpty())\r
+  {\r
+    /*\r
+    wchar_t s[32];\r
+    ConvertUInt64ToString(id, s);\r
+    return L"[" + (UString)s + L"]";\r
+    */\r
+    return L"[]";\r
+  }\r
+  return name;\r
+}\r
+\r
+static void UpdateWithName(UString &res, const UString &addString)\r
+{\r
+  if (res.IsEmpty())\r
+    res = addString;\r
+  else\r
+    res = addString + WCHAR_PATH_SEPARATOR + res;\r
+}\r
+\r
+UString CInArchive::GetItemPath(int volIndex, int fsIndex, int refIndex,\r
+    bool showVolName, bool showFsName) const\r
+{\r
+  // showVolName = true;\r
+  const CLogVol &vol = LogVols[volIndex];\r
+  const CFileSet &fs = vol.FileSets[fsIndex];\r
+\r
+  UString name;\r
+\r
+  for (;;)\r
+  {\r
+    const CRef &ref = fs.Refs[refIndex];\r
+    refIndex = ref.Parent;\r
+    if (refIndex < 0)\r
+      break;\r
+    UpdateWithName(name, GetSpecName(Files[ref.FileIndex].GetName()));\r
+  }\r
+\r
+  if (showFsName)\r
+  {\r
+    wchar_t s[32];\r
+    ConvertUInt64ToString(fsIndex, s);\r
+    UString newName = L"File Set ";\r
+    newName += s;\r
+    UpdateWithName(name, newName);\r
+  }\r
+\r
+  if (showVolName)\r
+  {\r
+    wchar_t s[32];\r
+    ConvertUInt64ToString(volIndex, s);\r
+    UString newName = s;\r
+    UString newName2 = vol.GetName();\r
+    if (newName2.IsEmpty())\r
+      newName2 = L"Volume";\r
+    newName += L'-';\r
+    newName += newName2;\r
+    UpdateWithName(name, newName);\r
+  }\r
+  return name;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Udf/UdfIn.h b/CPP/7zip/Archive/Udf/UdfIn.h
new file mode 100755 (executable)
index 0000000..c9a3c02
--- /dev/null
@@ -0,0 +1,375 @@
+// Archive/UdfIn.h -- UDF / ECMA-167\r
+\r
+#ifndef __ARCHIVE_UDF_IN_H\r
+#define __ARCHIVE_UDF_IN_H\r
+\r
+#include "Common/MyCom.h"\r
+#include "Common/IntToString.h"\r
+#include "Common/Buffer.h"\r
+#include "Common/MyString.h"\r
+#include "Common/MyMap.h"\r
+\r
+#include "../../IStream.h"\r
+\r
+namespace NArchive {\r
+namespace NUdf {\r
+\r
+// ---------- ECMA Part 1 ----------\r
+\r
+// ECMA 1/7.2.12\r
+\r
+/*\r
+struct CDString32\r
+{\r
+  Byte Data[32];\r
+  void Parse(const Byte *buf);\r
+  // UString GetString() const;\r
+};\r
+*/\r
+\r
+struct CDString128\r
+{\r
+  Byte Data[128];\r
+  void Parse(const Byte *buf);\r
+  UString GetString() const;\r
+};\r
+\r
+struct CDString\r
+{\r
+  CByteBuffer Data;\r
+  void Parse(const Byte *p, unsigned size);\r
+  UString GetString() const;\r
+};\r
+\r
+\r
+// ECMA 1/7.3\r
+\r
+struct CTime\r
+{\r
+  Byte Data[12];\r
+\r
+  unsigned GetType() const { return Data[1] >> 4; }\r
+  bool IsLocal() const { return GetType() == 1; }\r
+  int GetMinutesOffset() const\r
+  {\r
+    int t = (Data[0] | ((UInt16)Data[1] << 8)) & 0xFFF;\r
+    if ((t >> 11) != 0)\r
+      t -= (1 << 12);\r
+    return (t > (60 * 24) || t < -(60 * 24)) ? 0 : t;\r
+  }\r
+  unsigned GetYear() const { return (Data[2] | ((UInt16)Data[3] << 8)); }\r
+  void Parse(const Byte *buf);\r
+};\r
+\r
+\r
+// ECMA 1/7.4\r
+\r
+/*\r
+struct CRegId\r
+{\r
+  Byte Flags;\r
+  char Id[23];\r
+  char Suffix[8];\r
+\r
+  void Parse(const Byte *buf);\r
+};\r
+*/\r
+\r
+// ---------- ECMA Part 3: Volume Structure ----------\r
+\r
+// ECMA 3/10.5\r
+\r
+struct CPartition\r
+{\r
+  // UInt16 Flags;\r
+  UInt16 Number;\r
+  // CRegId ContentsId;\r
+  // Byte ContentsUse[128];\r
+  // UInt32 AccessType;\r
+\r
+  UInt32 Pos;\r
+  UInt32 Len;\r
+\r
+  // CRegId ImplId;\r
+  // Byte ImplUse[128];\r
+\r
+  int VolIndex;\r
+  CMap32 Map;\r
+\r
+  CPartition(): VolIndex(-1) {}\r
+\r
+  // bool IsNsr() const { return (strncmp(ContentsId.Id, "+NSR0", 5) == 0); }\r
+  // bool IsAllocated() const { return ((Flags & 1) != 0); }\r
+};\r
+\r
+struct CLogBlockAddr\r
+{\r
+  UInt32 Pos;\r
+  UInt16 PartitionRef;\r
+  \r
+  void Parse(const Byte *buf);\r
+};\r
+\r
+enum EShortAllocDescType\r
+{\r
+  SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated = 0,\r
+  SHORT_ALLOC_DESC_TYPE_NotRecordedButAllocated = 1,\r
+  SHORT_ALLOC_DESC_TYPE_NotRecordedAndNotAllocated = 2,\r
+  SHORT_ALLOC_DESC_TYPE_NextExtent = 3\r
+};\r
+\r
+struct CShortAllocDesc\r
+{\r
+  UInt32 Len;\r
+  UInt32 Pos;\r
+\r
+  // 4/14.14.1\r
+  // UInt32 GetLen() const { return Len & 0x3FFFFFFF; }\r
+  // UInt32 GetType() const { return Len >> 30; }\r
+  // bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; }\r
+  void Parse(const Byte *buf);\r
+};\r
+\r
+/*\r
+struct CADImpUse\r
+{\r
+  UInt16 Flags;\r
+  UInt32 UdfUniqueId;\r
+  void Parse(const Byte *buf);\r
+};\r
+*/\r
+\r
+struct CLongAllocDesc\r
+{\r
+  UInt32 Len;\r
+  CLogBlockAddr Location;\r
+  \r
+  // Byte ImplUse[6];\r
+  // CADImpUse adImpUse; // UDF\r
+  \r
+  UInt32 GetLen() const { return Len & 0x3FFFFFFF; }\r
+  UInt32 GetType() const { return Len >> 30; }\r
+  bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; }\r
+  void Parse(const Byte *buf);\r
+};\r
+\r
+struct CPartitionMap\r
+{\r
+  Byte Type;\r
+  // Byte Len;\r
+\r
+  // Type - 1\r
+  // UInt16 VolSeqNumber;\r
+  UInt16 PartitionNumber;\r
+\r
+  // Byte Data[256];\r
+\r
+  int PartitionIndex;\r
+};\r
+\r
+// ECMA 4/14.6\r
+\r
+enum EIcbFileType\r
+{\r
+  ICB_FILE_TYPE_DIR = 4,\r
+  ICB_FILE_TYPE_FILE = 5\r
+};\r
+\r
+enum EIcbDescriptorType\r
+{\r
+  ICB_DESC_TYPE_SHORT = 0,\r
+  ICB_DESC_TYPE_LONG = 1,\r
+  ICB_DESC_TYPE_EXTENDED = 2,\r
+  ICB_DESC_TYPE_INLINE = 3\r
+};\r
+\r
+struct CIcbTag\r
+{\r
+  // UInt32 PriorDirectNum;\r
+  // UInt16 StrategyType;\r
+  // UInt16 StrategyParam;\r
+  // UInt16 MaxNumOfEntries;\r
+  Byte FileType;\r
+  // CLogBlockAddr ParentIcb;\r
+  UInt16 Flags;\r
+\r
+  bool IsDir() const { return FileType == ICB_FILE_TYPE_DIR; }\r
+  int GetDescriptorType() const { return Flags & 3; }\r
+  void Parse(const Byte *p);\r
+};\r
+\r
+// const Byte FILEID_CHARACS_Existance = (1 << 0);\r
+const Byte FILEID_CHARACS_Parent = (1 << 3);\r
+\r
+struct CFile\r
+{\r
+  // UInt16 FileVersion;\r
+  // Byte FileCharacteristics;\r
+  // CByteBuffer ImplUse;\r
+  CDString Id;\r
+\r
+  CFile(): /* FileVersion(0), FileCharacteristics(0), */ ItemIndex(-1) {}\r
+  int ItemIndex;\r
+  UString GetName() const { return Id.GetString(); }\r
+};\r
+\r
+struct CMyExtent\r
+{\r
+  UInt32 Pos;\r
+  UInt32 Len;\r
+  int PartitionRef;\r
+  \r
+  UInt32 GetLen() const { return Len & 0x3FFFFFFF; }\r
+  UInt32 GetType() const { return Len >> 30; }\r
+  bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; }\r
+};\r
+\r
+struct CItem\r
+{\r
+  CIcbTag IcbTag;\r
+\r
+  // UInt32 Uid;\r
+  // UInt32 Gid;\r
+  // UInt32 Permissions;\r
+  // UInt16 FileLinkCount;\r
+  // Byte RecordFormat;\r
+  // Byte RecordDisplayAttr;\r
+  // UInt32 RecordLen;\r
+  UInt64 Size;\r
+  UInt64 NumLogBlockRecorded;\r
+  CTime ATime;\r
+  CTime MTime;\r
+  // CTime AttrtTime;\r
+  // UInt32 CheckPoint;\r
+  // CLongAllocDesc ExtendedAttrIcb;\r
+  // CRegId ImplId;\r
+  // UInt64 UniqueId;\r
+\r
+  bool IsInline;\r
+  CByteBuffer InlineData;\r
+  CRecordVector<CMyExtent> Extents;\r
+  CRecordVector<int> SubFiles;\r
+\r
+  void Parse(const Byte *buf);\r
+\r
+  bool IsRecAndAlloc() const\r
+  {\r
+    for (int i = 0; i < Extents.Size(); i++)\r
+      if (!Extents[i].IsRecAndAlloc())\r
+        return false;\r
+    return true;\r
+  }\r
+\r
+  UInt64 GetChunksSumSize() const\r
+  {\r
+    if (IsInline)\r
+      return InlineData.GetCapacity();\r
+    UInt64 size = 0;\r
+    for (int i = 0; i < Extents.Size(); i++)\r
+      size += Extents[i].GetLen();\r
+    return size;\r
+  }\r
+\r
+  bool CheckChunkSizes() const  {  return GetChunksSumSize() == Size; }\r
+\r
+  bool IsDir() const { return IcbTag.IsDir(); }\r
+};\r
\r
+struct CRef\r
+{\r
+  int Parent;\r
+  int FileIndex;\r
+};\r
+\r
+\r
+// ECMA 4 / 14.1\r
+struct CFileSet\r
+{\r
+  CTime RecodringTime;\r
+  // UInt16 InterchangeLevel;\r
+  // UInt16 MaxInterchangeLevel;\r
+  // UInt32 FileSetNumber;\r
+  // UInt32 FileSetDescNumber;\r
+  // CDString32 Id;\r
+  // CDString32 CopyrightId;\r
+  // CDString32 AbstractId;\r
+\r
+  CLongAllocDesc RootDirICB;\r
+  // CRegId DomainId;\r
+  // CLongAllocDesc SystemStreamDirICB;\r
+\r
+  CRecordVector<CRef> Refs;\r
+};\r
+\r
+\r
+// ECMA 3/10.6\r
+\r
+struct CLogVol\r
+{\r
+  CDString128 Id;\r
+  UInt32 BlockSize;\r
+  // CRegId DomainId;\r
+  \r
+  // Byte ContentsUse[16];\r
+  CLongAllocDesc FileSetLocation; // UDF\r
+\r
+  // CRegId ImplId;\r
+  // Byte ImplUse[128];\r
+\r
+  CObjectVector<CPartitionMap> PartitionMaps;\r
+  CObjectVector<CFileSet> FileSets;\r
+\r
+  UString GetName() const { return Id.GetString(); }\r
+};\r
+\r
+struct CProgressVirt\r
+{\r
+  virtual HRESULT SetTotal(UInt64 numBytes) PURE;\r
+  virtual HRESULT SetCompleted(UInt64 numFiles, UInt64 numBytes) PURE;\r
+  virtual HRESULT SetCompleted() PURE;\r
+};\r
+\r
+class CInArchive\r
+{\r
+  CMyComPtr<IInStream> _stream;\r
+  CProgressVirt *_progress;\r
+\r
+  HRESULT Read(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len, Byte *buf);\r
+  HRESULT Read(int volIndex, const CLongAllocDesc &lad, Byte *buf);\r
+  HRESULT ReadFromFile(int volIndex, const CItem &item, CByteBuffer &buf);\r
+\r
+  HRESULT ReadFileItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed);\r
+  HRESULT ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed);\r
+\r
+  HRESULT Open2();\r
+  HRESULT FillRefs(CFileSet &fs, int fileIndex, int parent, int numRecurseAllowed);\r
+\r
+  UInt64 _processedProgressBytes;\r
+\r
+  UInt64 _fileNameLengthTotal;\r
+  int _numRefs;\r
+  UInt32 _numExtents;\r
+  UInt64 _inlineExtentsSize;\r
+  bool CheckExtent(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len) const;\r
+public:\r
+  HRESULT Open(IInStream *inStream, CProgressVirt *progress);\r
+  void Clear();\r
+\r
+  CObjectVector<CPartition> Partitions;\r
+  CObjectVector<CLogVol> LogVols;\r
+\r
+  CObjectVector<CItem> Items;\r
+  CObjectVector<CFile> Files;\r
+\r
+  int SecLogSize;\r
+\r
+  UString GetComment() const;\r
+  UString GetItemPath(int volIndex, int fsIndex, int refIndex,\r
+      bool showVolName, bool showFsName) const;\r
+\r
+  bool CheckItemExtents(int volIndex, const CItem &item) const;\r
+};\r
+\r
+}}\r
+  \r
+#endif\r
diff --git a/CPP/7zip/Archive/Udf/UdfRegister.cpp b/CPP/7zip/Archive/Udf/UdfRegister.cpp
new file mode 100755 (executable)
index 0000000..483614a
--- /dev/null
@@ -0,0 +1,13 @@
+// UdfRegister.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/RegisterArc.h"\r
+\r
+#include "UdfHandler.h"\r
+static IInArchive *CreateArc() { return new NArchive::NUdf::CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"Udf", L"iso img", 0, 0xE0, { 0, 'N', 'S', 'R', '0' }, 5, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Udf)\r
diff --git a/CPP/7zip/Archive/VhdHandler.cpp b/CPP/7zip/Archive/VhdHandler.cpp
new file mode 100755 (executable)
index 0000000..26d1c69
--- /dev/null
@@ -0,0 +1,734 @@
+// VhdHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/Buffer.h"\r
+#include "Common/ComTry.h"\r
+#include "Common/IntToString.h"\r
+#include "Common/MyString.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../Common/LimitedStreams.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/CopyCoder.h"\r
+\r
+#define Get16(p) GetBe16(p)\r
+#define Get32(p) GetBe32(p)\r
+#define Get64(p) GetBe64(p)\r
+\r
+#define G32(p, dest) dest = Get32(p);\r
+#define G64(p, dest) dest = Get64(p);\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace NVhd {\r
+\r
+static const UInt32 kUnusedBlock = 0xFFFFFFFF;\r
+\r
+static const UInt32 kDiskType_Fixed = 2;\r
+static const UInt32 kDiskType_Dynamic = 3;\r
+static const UInt32 kDiskType_Diff = 4;\r
+\r
+static const char *kDiskTypes[] =\r
+{\r
+  "0",\r
+  "1",\r
+  "Fixed",\r
+  "Dynamic",\r
+  "Differencing"\r
+};\r
+\r
+struct CFooter\r
+{\r
+  // UInt32 Features;\r
+  // UInt32 FormatVersion;\r
+  UInt64 DataOffset;\r
+  UInt32 CTime;\r
+  UInt32 CreatorApp;\r
+  UInt32 CreatorVersion;\r
+  UInt32 CreatorHostOS;\r
+  // UInt64 OriginalSize;\r
+  UInt64 CurrentSize;\r
+  UInt32 DiskGeometry;\r
+  UInt32 Type;\r
+  Byte Id[16];\r
+  Byte SavedState;\r
+\r
+  bool IsFixed() const { return Type == kDiskType_Fixed; }\r
+  bool ThereIsDynamic() const { return Type == kDiskType_Dynamic || Type == kDiskType_Diff; }\r
+  // bool IsSupported() const { return Type == kDiskType_Fixed || Type == kDiskType_Dynamic || Type == kDiskType_Diff; }\r
+  UInt32 NumCyls() const { return DiskGeometry >> 16; }\r
+  UInt32 NumHeads() const { return (DiskGeometry >> 8) & 0xFF; }\r
+  UInt32 NumSectorsPerTrack() const { return DiskGeometry & 0xFF; }\r
+  AString GetTypeString() const;\r
+  bool Parse(const Byte *p);\r
+};\r
+\r
+AString CFooter::GetTypeString() const\r
+{\r
+  if (Type < sizeof(kDiskTypes) / sizeof(kDiskTypes[0]))\r
+    return kDiskTypes[Type];\r
+  char s[16];\r
+  ConvertUInt32ToString(Type, s);\r
+  return s;\r
+}\r
+\r
+static bool CheckBlock(const Byte *p, unsigned size, unsigned checkSumOffset, unsigned zeroOffset)\r
+{\r
+  UInt32 sum = 0;\r
+  unsigned i;\r
+  for (i = 0; i < checkSumOffset; i++)\r
+    sum += p[i];\r
+  for (i = checkSumOffset + 4; i < size; i++)\r
+    sum += p[i];\r
+  if (~sum != Get32(p + checkSumOffset))\r
+    return false;\r
+  for (i = zeroOffset; i < size; i++)\r
+    if (p[i] != 0)\r
+      return false;\r
+  return true;\r
+}\r
+\r
+bool CFooter::Parse(const Byte *p)\r
+{\r
+  if (memcmp(p, "conectix", 8) != 0)\r
+    return false;\r
+  // G32(p + 0x08, Features);\r
+  // G32(p + 0x0C, FormatVersion);\r
+  G64(p + 0x10, DataOffset);\r
+  G32(p + 0x18, CTime);\r
+  G32(p + 0x1C, CreatorApp);\r
+  G32(p + 0x20, CreatorVersion);\r
+  G32(p + 0x24, CreatorHostOS);\r
+  // G64(p + 0x28, OriginalSize);\r
+  G64(p + 0x30, CurrentSize);\r
+  G32(p + 0x38, DiskGeometry);\r
+  G32(p + 0x3C, Type);\r
+  memcpy(Id, p + 0x44, 16);\r
+  SavedState = p[0x54];\r
+  return CheckBlock(p, 512, 0x40, 0x55);\r
+}\r
+\r
+/*\r
+struct CParentLocatorEntry\r
+{\r
+  UInt32 Code;\r
+  UInt32 DataSpace;\r
+  UInt32 DataLen;\r
+  UInt64 DataOffset;\r
+\r
+  bool Parse(const Byte *p);\r
+};\r
+bool CParentLocatorEntry::Parse(const Byte *p)\r
+{\r
+  G32(p + 0x00, Code);\r
+  G32(p + 0x04, DataSpace);\r
+  G32(p + 0x08, DataLen);\r
+  G32(p + 0x10, DataOffset);\r
+  return (Get32(p + 0x0C) == 0); // Resrved\r
+}\r
+*/\r
+\r
+struct CDynHeader\r
+{\r
+  // UInt64 DataOffset;\r
+  UInt64 TableOffset;\r
+  // UInt32 HeaderVersion;\r
+  UInt32 NumBlocks;\r
+  int BlockSizeLog;\r
+  UInt32 ParentTime;\r
+  Byte ParentId[16];\r
+  UString ParentName;\r
+  // CParentLocatorEntry ParentLocators[8];\r
+\r
+  bool Parse(const Byte *p);\r
+  UInt32 NumBitMapSectors() const\r
+  {\r
+    UInt32 numSectorsInBlock = (1 << (BlockSizeLog - 9));\r
+    return (numSectorsInBlock + 512 * 8 - 1) / (512 * 8);\r
+  }\r
+};\r
+\r
+static int GetLog(UInt32 num)\r
+{\r
+  for (int i = 0; i < 31; i++)\r
+    if (((UInt32)1 << i) == num)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+bool CDynHeader::Parse(const Byte *p)\r
+{\r
+  if (memcmp(p, "cxsparse", 8) != 0)\r
+    return false;\r
+  // G64(p + 0x08, DataOffset);\r
+  G64(p + 0x10, TableOffset);\r
+  // G32(p + 0x18, HeaderVersion);\r
+  G32(p + 0x1C, NumBlocks);\r
+  BlockSizeLog = GetLog(Get32(p + 0x20));\r
+  if (BlockSizeLog < 9 || BlockSizeLog > 30)\r
+    return false;\r
+  G32(p + 0x38, ParentTime);\r
+  if (Get32(p + 0x3C) != 0) // reserved\r
+    return false;\r
+  memcpy(ParentId, p + 0x28, 16);\r
+  {\r
+    const int kNameLength = 256;\r
+    wchar_t *s = ParentName.GetBuffer(kNameLength);\r
+    for (unsigned i = 0; i < kNameLength; i++)\r
+      s[i] = Get16(p + 0x40 + i * 2);\r
+    s[kNameLength] = 0;\r
+    ParentName.ReleaseBuffer();\r
+  }\r
+  /*\r
+  for (int i = 0; i < 8; i++)\r
+    if (!ParentLocators[i].Parse(p + 0x240 + i * 24))\r
+      return false;\r
+  */\r
+  return CheckBlock(p, 1024, 0x24, 0x240 + 8 * 24);\r
+}\r
+\r
+class CHandler:\r
+  public IInStream,\r
+  public IInArchive,\r
+  public IInArchiveGetStream,\r
+  public CMyUnknownImp\r
+{\r
+  UInt64 _virtPos;\r
+  UInt64 _phyPos;\r
+  UInt64 _phyLimit;\r
+\r
+  CFooter Footer;\r
+  CDynHeader Dyn;\r
+  CRecordVector<UInt32> Bat;\r
+  CByteBuffer BitMap;\r
+  UInt32 BitMapTag;\r
+  UInt32 NumUsedBlocks;\r
+  CMyComPtr<IInStream> Stream;\r
+  CMyComPtr<IInStream> ParentStream;\r
+  CHandler *Parent;\r
+\r
+  HRESULT Seek(UInt64 offset);\r
+  HRESULT InitAndSeek();\r
+  HRESULT ReadPhy(UInt64 offset, void *data, UInt32 size);\r
+\r
+  bool NeedParent() const { return Footer.Type == kDiskType_Diff; }\r
+  UInt64 GetPackSize() const\r
+    { return Footer.ThereIsDynamic() ? ((UInt64)NumUsedBlocks << Dyn.BlockSizeLog) : Footer.CurrentSize; }\r
+\r
+  UString GetParentName() const\r
+  {\r
+    const CHandler *p = this;\r
+    UString res;\r
+    while (p && p->NeedParent())\r
+    {\r
+      if (!res.IsEmpty())\r
+        res += L" -> ";\r
+      res += p->Dyn.ParentName;\r
+      p = p->Parent;\r
+    }\r
+    return res;\r
+  }\r
+\r
+  bool IsOK() const\r
+  {\r
+    const CHandler *p = this;\r
+    while (p->NeedParent())\r
+    {\r
+      p = p->Parent;\r
+      if (p == 0)\r
+        return false;\r
+    }\r
+    return true;\r
+  }\r
+\r
+  HRESULT Open3();\r
+  HRESULT Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback *openArchiveCallback, int level);\r
+\r
+public:\r
+  MY_UNKNOWN_IMP3(IInArchive, IInArchiveGetStream, IInStream)\r
+\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);\r
+};\r
+\r
+HRESULT CHandler::Seek(UInt64 offset) { return Stream->Seek(offset, STREAM_SEEK_SET, NULL); }\r
+\r
+HRESULT CHandler::InitAndSeek()\r
+{\r
+  if (ParentStream)\r
+  {\r
+    RINOK(Parent->InitAndSeek());\r
+  }\r
+  _virtPos = _phyPos = 0;\r
+  BitMapTag = kUnusedBlock;\r
+  BitMap.SetCapacity(Dyn.NumBitMapSectors() << 9);\r
+  return Seek(0);\r
+}\r
+\r
+HRESULT CHandler::ReadPhy(UInt64 offset, void *data, UInt32 size)\r
+{\r
+  if (offset + size > _phyLimit)\r
+    return S_FALSE;\r
+  if (offset != _phyPos)\r
+  {\r
+    _phyPos = offset;\r
+    RINOK(Seek(offset));\r
+  }\r
+  HRESULT res = ReadStream_FALSE(Stream, data, size);\r
+  _phyPos += size;\r
+  return res;\r
+}\r
+\r
+HRESULT CHandler::Open3()\r
+{\r
+  RINOK(Stream->Seek(0, STREAM_SEEK_END, &_phyPos));\r
+  if (_phyPos < 512)\r
+    return S_FALSE;\r
+  const UInt32 kDynSize = 1024;\r
+  Byte buf[kDynSize];\r
+\r
+  _phyLimit = _phyPos;\r
+  RINOK(ReadPhy(_phyLimit - 512, buf, 512));\r
+  if (!Footer.Parse(buf))\r
+    return S_FALSE;\r
+  _phyLimit -= 512;\r
+\r
+  if (!Footer.ThereIsDynamic())\r
+    return S_OK;\r
+\r
+  RINOK(ReadPhy(0, buf + 512, 512));\r
+  if (memcmp(buf, buf + 512, 512) != 0)\r
+    return S_FALSE;\r
+\r
+  RINOK(ReadPhy(Footer.DataOffset, buf, kDynSize));\r
+  if (!Dyn.Parse(buf))\r
+    return S_FALSE;\r
+  \r
+  if (Dyn.NumBlocks >= (UInt32)1 << 31)\r
+    return S_FALSE;\r
+  if (Footer.CurrentSize == 0)\r
+  {\r
+    if (Dyn.NumBlocks != 0)\r
+      return S_FALSE;\r
+  }\r
+  else if (((Footer.CurrentSize - 1) >> Dyn.BlockSizeLog) + 1 != Dyn.NumBlocks)\r
+    return S_FALSE;\r
+\r
+  Bat.Reserve(Dyn.NumBlocks);\r
+  while ((UInt32)Bat.Size() < Dyn.NumBlocks)\r
+  {\r
+    RINOK(ReadPhy(Dyn.TableOffset + (UInt64)Bat.Size() * 4, buf, 512));\r
+    for (UInt32 j = 0; j < 512; j += 4)\r
+    {\r
+      UInt32 v = Get32(buf + j);\r
+      if (v != kUnusedBlock)\r
+        NumUsedBlocks++;\r
+      Bat.Add(v);\r
+      if ((UInt32)Bat.Size() >= Dyn.NumBlocks)\r
+        break;\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize != NULL)\r
+    *processedSize = 0;\r
+  if (_virtPos >= Footer.CurrentSize)\r
+    return (Footer.CurrentSize == _virtPos) ? S_OK: E_FAIL;\r
+  UInt64 rem = Footer.CurrentSize - _virtPos;\r
+  if (size > rem)\r
+    size = (UInt32)rem;\r
+  if (size == 0)\r
+    return S_OK;\r
+  UInt32 blockIndex = (UInt32)(_virtPos >> Dyn.BlockSizeLog);\r
+  UInt32 blockSectIndex = Bat[blockIndex];\r
+  UInt32 blockSize = (UInt32)1 << Dyn.BlockSizeLog;\r
+  UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1);\r
+  size = MyMin(blockSize - offsetInBlock, size);\r
+\r
+  HRESULT res = S_OK;\r
+  if (blockSectIndex == kUnusedBlock)\r
+  {\r
+    if (ParentStream)\r
+    {\r
+      RINOK(ParentStream->Seek(_virtPos, STREAM_SEEK_SET, NULL));\r
+      res = ParentStream->Read(data, size, &size);\r
+    }\r
+    else\r
+      memset(data, 0, size);\r
+  }\r
+  else\r
+  {\r
+    UInt64 newPos = (UInt64)blockSectIndex << 9;\r
+    if (BitMapTag != blockIndex)\r
+    {\r
+      RINOK(ReadPhy(newPos, BitMap, (UInt32)BitMap.GetCapacity()));\r
+      BitMapTag = blockIndex;\r
+    }\r
+    RINOK(ReadPhy(newPos + BitMap.GetCapacity() + offsetInBlock, data, size));\r
+    for (UInt32 cur = 0; cur < size;)\r
+    {\r
+      UInt32 rem = MyMin(0x200 - (offsetInBlock & 0x1FF), size - cur);\r
+      UInt32 bmi = offsetInBlock >> 9;\r
+      if (((BitMap[bmi >> 3] >> (7 - (bmi & 7))) & 1) == 0)\r
+      {\r
+        if (ParentStream)\r
+        {\r
+          RINOK(ParentStream->Seek(_virtPos + cur, STREAM_SEEK_SET, NULL));\r
+          RINOK(ReadStream_FALSE(ParentStream, (Byte *)data + cur, rem));\r
+        }\r
+        else\r
+        {\r
+          const Byte *p = (const Byte *)data + cur;\r
+          for (UInt32 i = 0; i < rem; i++)\r
+            if (p[i] != 0)\r
+              return S_FALSE;\r
+        }\r
+      }\r
+      offsetInBlock += rem;\r
+      cur += rem;\r
+    }\r
+  }\r
+  if (processedSize != NULL)\r
+    *processedSize = size;\r
+  _virtPos += size;\r
+  return res;\r
+}\r
+\r
+STDMETHODIMP CHandler::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)\r
+{\r
+  switch(seekOrigin)\r
+  {\r
+    case STREAM_SEEK_SET: _virtPos = offset; break;\r
+    case STREAM_SEEK_CUR: _virtPos += offset; break;\r
+    case STREAM_SEEK_END: _virtPos = Footer.CurrentSize + offset; break;\r
+    default: return STG_E_INVALIDFUNCTION;\r
+  }\r
+  if (newPosition)\r
+    *newPosition = _virtPos;\r
+  return S_OK;\r
+}\r
+\r
+enum\r
+{\r
+  kpidParent = kpidUserDefined,\r
+  kpidSavedState\r
+};\r
+\r
+STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidCTime, VT_FILETIME},\r
+  { NULL, kpidClusterSize, VT_UI8},\r
+  { NULL, kpidMethod, VT_BSTR},\r
+  { L"Parent", kpidParent, VT_BSTR},\r
+  { NULL, kpidCreatorApp, VT_BSTR},\r
+  { NULL, kpidHostOS, VT_BSTR},\r
+  { L"Saved State", kpidSavedState, VT_BOOL},\r
+  { NULL, kpidId, VT_BSTR}\r
+ };\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidCTime, VT_FILETIME}\r
+  \r
+  /*\r
+  { NULL, kpidNumCyls, VT_UI4},\r
+  { NULL, kpidNumHeads, VT_UI4},\r
+  { NULL, kpidSectorsPerTrack, VT_UI4}\r
+  */\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps_WITH_NAME\r
+\r
+// VHD start time: 2000-01-01\r
+static const UInt64 kVhdTimeStartValue = (UInt64)3600 * 24 * (399 * 365 + 24 * 4);\r
+\r
+static void VhdTimeToFileTime(UInt32 vhdTime, NCOM::CPropVariant &prop)\r
+{\r
+  FILETIME ft, utc;\r
+  UInt64 v = (kVhdTimeStartValue + vhdTime) * 10000000;\r
+  ft.dwLowDateTime = (DWORD)v;\r
+  ft.dwHighDateTime = (DWORD)(v >> 32);\r
+  // specification says that it's UTC time, but Virtual PC 6 writes local time. Why?\r
+  LocalFileTimeToFileTime(&ft, &utc);\r
+  prop = utc;\r
+}\r
+\r
+static void StringToAString(char *dest, UInt32 s)\r
+{\r
+  for (int i = 24; i >= 0; i -= 8)\r
+  {\r
+    Byte b = (Byte)((s >> i) & 0xFF);\r
+    if (b < 0x20 || b > 0x7F)\r
+      break;\r
+    *dest++ = b;\r
+  }\r
+  *dest = 0;\r
+}\r
+\r
+static void ConvertByteToHex(unsigned value, char *s)\r
+{\r
+  for (int i = 0; i < 2; i++)\r
+  {\r
+    unsigned t = value & 0xF;\r
+    value >>= 4;\r
+    s[1 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));\r
+  }\r
+}\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidMainSubfile: prop = (UInt32)0; break;\r
+    case kpidCTime: VhdTimeToFileTime(Footer.CTime, prop); break;\r
+    case kpidClusterSize: if (Footer.ThereIsDynamic()) prop = (UInt32)1 << Dyn.BlockSizeLog; break;\r
+    case kpidMethod:\r
+    {\r
+      AString s = Footer.GetTypeString();\r
+      if (NeedParent())\r
+      {\r
+        s += " -> ";\r
+        const CHandler *p = this;\r
+        while (p != 0 && p->NeedParent())\r
+          p = p->Parent;\r
+        if (p == 0)\r
+          s += '?';\r
+        else\r
+          s += p->Footer.GetTypeString();\r
+      }\r
+      prop = s;\r
+      break;\r
+    }\r
+    case kpidCreatorApp:\r
+    {\r
+      char s[16];\r
+      StringToAString(s, Footer.CreatorApp);\r
+      AString res = s;\r
+      res.Trim();\r
+      ConvertUInt32ToString(Footer.CreatorVersion >> 16, s);\r
+      res += ' ';\r
+      res += s;\r
+      res += '.';\r
+      ConvertUInt32ToString(Footer.CreatorVersion & 0xFFFF, s);\r
+      res += s;\r
+      prop = res;\r
+      break;\r
+    }\r
+    case kpidHostOS:\r
+    {\r
+      if (Footer.CreatorHostOS == 0x5769326b)\r
+        prop = "Windows";\r
+      else\r
+      {\r
+        char s[16];\r
+        StringToAString(s, Footer.CreatorHostOS);\r
+        prop = s;\r
+      }\r
+      break;\r
+    }\r
+    case kpidId:\r
+    {\r
+      char s[32 + 4];\r
+      for (int i = 0; i < 16; i++)\r
+        ConvertByteToHex(Footer.Id[i], s + i * 2);\r
+      s[32] = 0;\r
+      prop = s;\r
+      break;\r
+    }\r
+    case kpidSavedState: prop = Footer.SavedState ? true : false; break;\r
+    case kpidParent: if (NeedParent()) prop = GetParentName(); break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+HRESULT CHandler::Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback *openArchiveCallback, int level)\r
+{\r
+  Close();\r
+  Stream = stream;\r
+  if (level > 32)\r
+    return S_FALSE;\r
+  RINOK(Open3());\r
+  if (child && memcmp(child->Dyn.ParentId, Footer.Id, 16) != 0)\r
+    return S_FALSE;\r
+  if (Footer.Type != kDiskType_Diff)\r
+    return S_OK;\r
+  CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;\r
+  if (openArchiveCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback) != S_OK)\r
+    return S_FALSE;\r
+  CMyComPtr<IInStream> nextStream;\r
+  HRESULT res = openVolumeCallback->GetStream(Dyn.ParentName, &nextStream);\r
+  if (res == S_FALSE)\r
+    return S_OK;\r
+  RINOK(res);\r
+\r
+  Parent = new CHandler;\r
+  ParentStream = Parent;\r
+  return Parent->Open2(nextStream, this, openArchiveCallback, level + 1);\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream,\r
+    const UInt64 * /* maxCheckStartPosition */,\r
+    IArchiveOpenCallback * openArchiveCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  {\r
+    HRESULT res;\r
+    try\r
+    {\r
+      res = Open2(stream, NULL, openArchiveCallback, 0);\r
+      if (res == S_OK)\r
+        return S_OK;\r
+    }\r
+    catch(...)\r
+    {\r
+      Close();\r
+      throw;\r
+    }\r
+    Close();\r
+    return res;\r
+  }\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  Bat.Clear();\r
+  NumUsedBlocks = 0;\r
+  Parent = 0;\r
+  Stream.Release();\r
+  ParentStream.Release();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = 1;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+\r
+  switch(propID)\r
+  {\r
+    case kpidSize: prop = Footer.CurrentSize; break;\r
+    case kpidPackSize: prop = GetPackSize(); break;\r
+    case kpidCTime: VhdTimeToFileTime(Footer.CTime, prop); break;\r
+    /*\r
+    case kpidNumCyls: prop = Footer.NumCyls(); break;\r
+    case kpidNumHeads: prop = Footer.NumHeads(); break;\r
+    case kpidSectorsPerTrack: prop = Footer.NumSectorsPerTrack(); break;\r
+    */\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))\r
+    return E_INVALIDARG;\r
+\r
+  RINOK(extractCallback->SetTotal(Footer.CurrentSize));\r
+  CMyComPtr<ISequentialOutStream> outStream;\r
+  Int32 askMode = testMode ?\r
+      NExtract::NAskMode::kTest :\r
+      NExtract::NAskMode::kExtract;\r
+  RINOK(extractCallback->GetStream(0, &outStream, askMode));\r
+  if (!testMode && !outStream)\r
+    return S_OK;\r
+  RINOK(extractCallback->PrepareOperation(askMode));\r
+\r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  int res = NExtract::NOperationResult::kDataError;\r
+  CMyComPtr<ISequentialInStream> inStream;\r
+  HRESULT hres = GetStream(0, &inStream);\r
+  if (hres == S_FALSE)\r
+    res = NExtract::NOperationResult::kUnSupportedMethod;\r
+  else\r
+  {\r
+    RINOK(hres);\r
+    HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress);\r
+    if (hres == S_OK)\r
+    {\r
+      if (copyCoderSpec->TotalSize == Footer.CurrentSize)\r
+        res = NExtract::NOperationResult::kOK;\r
+    }\r
+    else\r
+    {\r
+      if (hres != S_FALSE)\r
+      {\r
+        RINOK(hres);\r
+      }\r
+    }\r
+  }\r
+  outStream.Release();\r
+  return extractCallback->SetOperationResult(res);\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream)\r
+{\r
+  COM_TRY_BEGIN\r
+  *stream = 0;\r
+  if (Footer.IsFixed())\r
+  {\r
+    CLimitedInStream *streamSpec = new CLimitedInStream;\r
+    CMyComPtr<ISequentialInStream> streamTemp = streamSpec;\r
+    streamSpec->SetStream(Stream);\r
+    streamSpec->InitAndSeek(0, Footer.CurrentSize);\r
+    RINOK(streamSpec->SeekToStart());\r
+    *stream = streamTemp.Detach();\r
+    return S_OK;\r
+  }\r
+  if (!Footer.ThereIsDynamic() || !IsOK())\r
+    return S_FALSE;\r
+  CMyComPtr<ISequentialInStream> streamTemp = this;\r
+  RINOK(InitAndSeek());\r
+  *stream = streamTemp.Detach();\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"VHD", L"vhd", L".mbr", 0xDC, { 'c', 'o', 'n', 'e', 'c', 't', 'i', 'x', 0, 0 }, 10, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Vhd)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Wim/StdAfx.h b/CPP/7zip/Archive/Wim/StdAfx.h
new file mode 100755 (executable)
index 0000000..83fdd22
--- /dev/null
@@ -0,0 +1,8 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp
new file mode 100755 (executable)
index 0000000..a1fddff
--- /dev/null
@@ -0,0 +1,660 @@
+// WimHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/CpuArch.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/IntToString.h"\r
+#include "Common/StringToInt.h"\r
+#include "Common/UTFConvert.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../../Common/ProgressUtils.h"\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "WimHandler.h"\r
+\r
+#define Get16(p) GetUi16(p)\r
+#define Get32(p) GetUi32(p)\r
+#define Get64(p) GetUi64(p)\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace NWim {\r
+\r
+#define WIM_DETAILS\r
+\r
+static STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidIsDir, VT_BOOL},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidCTime, VT_FILETIME},\r
+  { NULL, kpidATime, VT_FILETIME},\r
+  { NULL, kpidAttrib, VT_UI4},\r
+  { NULL, kpidMethod, VT_BSTR},\r
+  { NULL, kpidShortName, VT_BSTR}\r
+  \r
+  #ifdef WIM_DETAILS\r
+  , { NULL, kpidVolume, VT_UI4}\r
+  , { NULL, kpidOffset, VT_UI8}\r
+  , { NULL, kpidLinks, VT_UI4}\r
+  #endif\r
+};\r
+\r
+static STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidMethod, VT_BSTR},\r
+  { NULL, kpidCTime, VT_FILETIME},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidComment, VT_BSTR},\r
+  { NULL, kpidUnpackVer, VT_BSTR},\r
+  { NULL, kpidIsVolume, VT_BOOL},\r
+  { NULL, kpidVolume, VT_UI4},\r
+  { NULL, kpidNumVolumes, VT_UI4}\r
+};\r
+\r
+static bool ParseNumber64(const AString &s, UInt64 &res)\r
+{\r
+  const char *end;\r
+  if (s.Left(2) == "0x")\r
+  {\r
+    if (s.Length() == 2)\r
+      return false;\r
+    res = ConvertHexStringToUInt64((const char *)s + 2, &end);\r
+  }\r
+  else\r
+  {\r
+    if (s.IsEmpty())\r
+      return false;\r
+    res = ConvertStringToUInt64(s, &end);\r
+  }\r
+  return *end == 0;\r
+}\r
+\r
+static bool ParseNumber32(const AString &s, UInt32 &res)\r
+{\r
+  UInt64 res64;\r
+  if (!ParseNumber64(s, res64) || res64 >= ((UInt64)1 << 32))\r
+    return false;\r
+  res = (UInt32)res64;\r
+  return true;\r
+}\r
+\r
+bool ParseTime(const CXmlItem &item, FILETIME &ft, const char *tag)\r
+{\r
+  int index = item.FindSubTag(tag);\r
+  if (index >= 0)\r
+  {\r
+    const CXmlItem &timeItem = item.SubItems[index];\r
+    UInt32 low = 0, high = 0;\r
+    if (ParseNumber32(timeItem.GetSubStringForTag("LOWPART"), low) &&\r
+        ParseNumber32(timeItem.GetSubStringForTag("HIGHPART"), high))\r
+    {\r
+      ft.dwLowDateTime = low;\r
+      ft.dwHighDateTime = high;\r
+      return true;\r
+    }\r
+  }\r
+  return false;\r
+}\r
+\r
+void CImageInfo::Parse(const CXmlItem &item)\r
+{\r
+  CTimeDefined = ParseTime(item, CTime, "CREATIONTIME");\r
+  MTimeDefined = ParseTime(item, MTime, "LASTMODIFICATIONTIME");\r
+  NameDefined = ConvertUTF8ToUnicode(item.GetSubStringForTag("NAME"), Name);\r
+  // IndexDefined = ParseNumber32(item.GetPropertyValue("INDEX"), Index);\r
+}\r
+\r
+void CXml::ToUnicode(UString &s)\r
+{\r
+  size_t size = Data.GetCapacity();\r
+  if (size < 2 || (size & 1) != 0 || size > (1 << 24))\r
+    return;\r
+  const Byte *p = Data;\r
+  if (Get16(p) != 0xFEFF)\r
+    return;\r
+  wchar_t *chars = s.GetBuffer((int)size / 2);\r
+  for (size_t i = 2; i < size; i += 2)\r
+    *chars++ = (wchar_t)Get16(p + i);\r
+  *chars = 0;\r
+  s.ReleaseBuffer();\r
+}\r
+\r
+void CXml::Parse()\r
+{\r
+  UString s;\r
+  ToUnicode(s);\r
+  AString utf;\r
+  if (!ConvertUnicodeToUTF8(s, utf))\r
+    return;\r
+  ::CXml xml;\r
+  if (!xml.Parse(utf))\r
+    return;\r
+  if (xml.Root.Name != "WIM")\r
+    return;\r
+\r
+  for (int i = 0; i < xml.Root.SubItems.Size(); i++)\r
+  {\r
+    const CXmlItem &item = xml.Root.SubItems[i];\r
+    if (item.IsTagged("IMAGE"))\r
+    {\r
+      CImageInfo imageInfo;\r
+      imageInfo.Parse(item);\r
+      Images.Add(imageInfo);\r
+    }\r
+  }\r
+}\r
+\r
+static const char *kMethodLZX = "LZX";\r
+static const char *kMethodXpress = "XPress";\r
+static const char *kMethodCopy = "Copy";\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+\r
+  const CImageInfo *image = NULL;\r
+  if (_xmls.Size() == 1)\r
+  {\r
+    const CXml &xml = _xmls[0];\r
+    if (xml.Images.Size() == 1)\r
+      image = &xml.Images[0];\r
+  }\r
+\r
+  switch(propID)\r
+  {\r
+    case kpidSize: prop = _db.GetUnpackSize(); break;\r
+    case kpidPackSize: prop = _db.GetPackSize(); break;\r
+    \r
+    case kpidCTime:\r
+      if (_xmls.Size() == 1)\r
+      {\r
+        const CXml &xml = _xmls[0];\r
+        int index = -1;\r
+        for (int i = 0; i < xml.Images.Size(); i++)\r
+        {\r
+          const CImageInfo &image = xml.Images[i];\r
+          if (image.CTimeDefined)\r
+            if (index < 0 || ::CompareFileTime(&image.CTime, &xml.Images[index].CTime) < 0)\r
+              index = i;\r
+        }\r
+        if (index >= 0)\r
+          prop = xml.Images[index].CTime;\r
+      }\r
+      break;\r
+\r
+    case kpidMTime:\r
+      if (_xmls.Size() == 1)\r
+      {\r
+        const CXml &xml = _xmls[0];\r
+        int index = -1;\r
+        for (int i = 0; i < xml.Images.Size(); i++)\r
+        {\r
+          const CImageInfo &image = xml.Images[i];\r
+          if (image.MTimeDefined)\r
+            if (index < 0 || ::CompareFileTime(&image.MTime, &xml.Images[index].MTime) > 0)\r
+              index = i;\r
+        }\r
+        if (index >= 0)\r
+          prop = xml.Images[index].MTime;\r
+      }\r
+      break;\r
+\r
+    case kpidComment:\r
+      if (image != NULL)\r
+      {\r
+        if (_xmlInComments)\r
+        {\r
+          UString s;\r
+          _xmls[0].ToUnicode(s);\r
+          prop = s;\r
+        }\r
+        else if (image->NameDefined)\r
+          prop = image->Name;\r
+      }\r
+      break;\r
+\r
+    case kpidUnpackVer:\r
+    {\r
+      UInt32 ver1 = _version >> 16;\r
+      UInt32 ver2 = (_version >> 8) & 0xFF;\r
+      UInt32 ver3 = (_version) & 0xFF;\r
+\r
+      char s[16];\r
+      ConvertUInt32ToString(ver1, s);\r
+      AString res = s;\r
+      res += '.';\r
+      ConvertUInt32ToString(ver2, s);\r
+      res += s;\r
+      if (ver3 != 0)\r
+      {\r
+        res += '.';\r
+        ConvertUInt32ToString(ver3, s);\r
+        res += s;\r
+      }\r
+      prop = res;\r
+      break;\r
+    }\r
+\r
+    case kpidIsVolume:\r
+      if (_xmls.Size() > 0)\r
+      {\r
+        UInt16 volIndex = _xmls[0].VolIndex;\r
+        if (volIndex < _volumes.Size())\r
+          prop = (_volumes[volIndex].Header.NumParts > 1);\r
+      }\r
+      break;\r
+    case kpidVolume:\r
+      if (_xmls.Size() > 0)\r
+      {\r
+        UInt16 volIndex = _xmls[0].VolIndex;\r
+        if (volIndex < _volumes.Size())\r
+          prop = (UInt32)_volumes[volIndex].Header.PartNumber;\r
+      }\r
+      break;\r
+    case kpidNumVolumes: if (_volumes.Size() > 0) prop = (UInt32)(_volumes.Size() - 1); break;\r
+    case kpidMethod:\r
+    {\r
+      bool lzx = false, xpress = false, copy = false;\r
+      for (int i = 0; i < _xmls.Size(); i++)\r
+      {\r
+        const CHeader &header = _volumes[_xmls[i].VolIndex].Header;\r
+        if (header.IsCompressed())\r
+          if (header.IsLzxMode())\r
+            lzx = true;\r
+          else\r
+            xpress = true;\r
+        else\r
+          copy = true;\r
+      }\r
+      AString res;\r
+      if (lzx)\r
+        res = kMethodLZX;\r
+      if (xpress)\r
+      {\r
+        if (!res.IsEmpty())\r
+          res += ' ';\r
+        res += kMethodXpress;\r
+      }\r
+      if (copy)\r
+      {\r
+        if (!res.IsEmpty())\r
+          res += ' ';\r
+        res += kMethodCopy;\r
+      }\r
+      prop = res;\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  if (index < (UInt32)_db.SortedItems.Size())\r
+  {\r
+    int realIndex = _db.SortedItems[index];\r
+    const CItem &item = _db.Items[realIndex];\r
+    const CStreamInfo *si = NULL;\r
+    const CVolume *vol = NULL;\r
+    if (item.StreamIndex >= 0)\r
+    {\r
+      si = &_db.Streams[item.StreamIndex];\r
+      vol = &_volumes[si->PartNumber];\r
+    }\r
+\r
+    switch(propID)\r
+    {\r
+      case kpidPath:\r
+        if (item.HasMetadata)\r
+          prop = _db.GetItemPath(realIndex);\r
+        else\r
+        {\r
+          char sz[16];\r
+          ConvertUInt32ToString(item.StreamIndex, sz);\r
+          AString s = sz;\r
+          while (s.Length() < _nameLenForStreams)\r
+            s = '0' + s;\r
+          /*\r
+          if (si->Resource.IsFree())\r
+            prefix = "[Free]";\r
+          */\r
+          s = "[Files]" STRING_PATH_SEPARATOR + s;\r
+          prop = s;\r
+        }\r
+        break;\r
+      case kpidShortName: if (item.HasMetadata) prop = item.ShortName; break;\r
+\r
+      case kpidIsDir: prop = item.IsDir(); break;\r
+      case kpidAttrib: if (item.HasMetadata) prop = item.Attrib; break;\r
+      case kpidCTime: if (item.HasMetadata) prop = item.CTime; break;\r
+      case kpidATime: if (item.HasMetadata) prop = item.ATime; break;\r
+      case kpidMTime: if (item.HasMetadata) prop = item.MTime; break;\r
+      case kpidPackSize: prop = si ? si->Resource.PackSize : (UInt64)0; break;\r
+      case kpidSize: prop = si ? si->Resource.UnpackSize : (UInt64)0; break;\r
+      case kpidMethod: if (si) prop = si->Resource.IsCompressed() ?\r
+          (vol->Header.IsLzxMode() ? kMethodLZX : kMethodXpress) : kMethodCopy; break;\r
+      #ifdef WIM_DETAILS\r
+      case kpidVolume: if (si) prop = (UInt32)si->PartNumber; break;\r
+      case kpidOffset: if (si)  prop = (UInt64)si->Resource.Offset; break;\r
+      case kpidLinks: prop = si ? (UInt32)si->RefCount : (UInt32)0; break;\r
+      #endif\r
+    }\r
+  }\r
+  else\r
+  {\r
+    index -= _db.SortedItems.Size();\r
+    {\r
+      switch(propID)\r
+      {\r
+        case kpidPath:\r
+        {\r
+          char sz[16];\r
+          ConvertUInt32ToString(_xmls[index].VolIndex, sz);\r
+          prop = (AString)"[" + (AString)sz + "].xml";\r
+          break;\r
+        }\r
+        case kpidIsDir: prop = false; break;\r
+        case kpidPackSize:\r
+        case kpidSize: prop = (UInt64)_xmls[index].Data.GetCapacity(); break;\r
+        case kpidMethod: prop = kMethodCopy; break;\r
+      }\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+class CVolumeName\r
+{\r
+  // UInt32 _volIndex;\r
+  UString _before;\r
+  UString _after;\r
+public:\r
+  CVolumeName() {};\r
+\r
+  void InitName(const UString &name)\r
+  {\r
+    // _volIndex = 1;\r
+    int dotPos = name.ReverseFind('.');\r
+    if (dotPos < 0)\r
+      dotPos = name.Length();\r
+    _before = name.Left(dotPos);\r
+    _after = name.Mid(dotPos);\r
+  }\r
+\r
+  UString GetNextName(UInt32 index)\r
+  {\r
+    wchar_t s[16];\r
+    ConvertUInt32ToString(index, s);\r
+    return _before + (UString)s + _after;\r
+  }\r
+};\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *inStream,\r
+    const UInt64 * /* maxCheckStartPosition */,\r
+    IArchiveOpenCallback *openArchiveCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  Close();\r
+  {\r
+    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;\r
+    \r
+    CVolumeName seqName;\r
+    if (openArchiveCallback != NULL)\r
+      openArchiveCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);\r
+\r
+    UInt32 numVolumes = 1;\r
+    int firstVolumeIndex = -1;\r
+    for (UInt32 i = 1; i <= numVolumes; i++)\r
+    {\r
+      CMyComPtr<IInStream> curStream;\r
+      if (i != 1)\r
+      {\r
+        UString fullName = seqName.GetNextName(i);\r
+        HRESULT result = openVolumeCallback->GetStream(fullName, &curStream);\r
+        if (result == S_FALSE)\r
+          continue;\r
+        if (result != S_OK)\r
+          return result;\r
+        if (!curStream)\r
+          break;\r
+      }\r
+      else\r
+        curStream = inStream;\r
+      CHeader header;\r
+      HRESULT res = NWim::ReadHeader(curStream, header);\r
+      if (res != S_OK)\r
+      {\r
+        if (i == 1)\r
+          return res;\r
+        if (res == S_FALSE)\r
+          continue;\r
+        return res;\r
+      }\r
+      _version = header.Version;\r
+      _isOldVersion = header.IsOldVersion();\r
+      if (firstVolumeIndex >= 0)\r
+        if (!header.AreFromOnArchive(_volumes[firstVolumeIndex].Header))\r
+          break;\r
+      if (_volumes.Size() > header.PartNumber && _volumes[header.PartNumber].Stream)\r
+        break;\r
+      CXml xml;\r
+      xml.VolIndex = header.PartNumber;\r
+      res = _db.Open(curStream, header, xml.Data, openArchiveCallback);\r
+      if (res != S_OK)\r
+      {\r
+        if (i == 1)\r
+          return res;\r
+        if (res == S_FALSE)\r
+          continue;\r
+        return res;\r
+      }\r
+      \r
+      while (_volumes.Size() <= header.PartNumber)\r
+        _volumes.Add(CVolume());\r
+      CVolume &volume = _volumes[header.PartNumber];\r
+      volume.Header = header;\r
+      volume.Stream = curStream;\r
+      \r
+      firstVolumeIndex = header.PartNumber;\r
+      \r
+      bool needAddXml = true;\r
+      if (_xmls.Size() != 0)\r
+        if (xml.Data == _xmls[0].Data)\r
+          needAddXml = false;\r
+      if (needAddXml)\r
+      {\r
+        xml.Parse();\r
+        _xmls.Add(xml);\r
+      }\r
+      \r
+      if (i == 1)\r
+      {\r
+        if (header.PartNumber != 1)\r
+          break;\r
+        if (!openVolumeCallback)\r
+          break;\r
+        numVolumes = header.NumParts;\r
+        {\r
+          NCOM::CPropVariant prop;\r
+          RINOK(openVolumeCallback->GetProperty(kpidName, &prop));\r
+          if (prop.vt != VT_BSTR)\r
+            break;\r
+          seqName.InitName(prop.bstrVal);\r
+        }\r
+      }\r
+    }\r
+\r
+    _db.DetectPathMode();\r
+    RINOK(_db.Sort(_db.SkipRoot));\r
+\r
+    wchar_t sz[16];\r
+    ConvertUInt32ToString(_db.Streams.Size(), sz);\r
+    _nameLenForStreams = MyStringLen(sz);\r
+\r
+    _xmlInComments = (_xmls.Size() == 1 && !_db.ShowImageNumber);\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _db.Clear();\r
+  _volumes.Clear();\r
+  _xmls.Clear();\r
+  _nameLenForStreams = 0;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+\r
+  if (allFilesMode)\r
+    numItems = _db.SortedItems.Size() + _xmls.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+\r
+  UInt32 i;\r
+  UInt64 totalSize = 0;\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    UInt32 index = allFilesMode ? i : indices[i];\r
+    if (index < (UInt32)_db.SortedItems.Size())\r
+    {\r
+      int streamIndex = _db.Items[_db.SortedItems[index]].StreamIndex;\r
+      if (streamIndex >= 0)\r
+      {\r
+        const CStreamInfo &si = _db.Streams[streamIndex];\r
+        totalSize += si.Resource.UnpackSize;\r
+      }\r
+    }\r
+    else\r
+      totalSize += _xmls[index - (UInt32)_db.SortedItems.Size()].Data.GetCapacity();\r
+  }\r
+\r
+  RINOK(extractCallback->SetTotal(totalSize));\r
+\r
+  UInt64 currentTotalPacked = 0;\r
+  UInt64 currentTotalUnPacked = 0;\r
+  UInt64 currentItemUnPacked, currentItemPacked;\r
+  \r
+  int prevSuccessStreamIndex = -1;\r
+\r
+  CUnpacker unpacker;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  for (i = 0; i < numItems; currentTotalUnPacked += currentItemUnPacked,\r
+      currentTotalPacked += currentItemPacked)\r
+  {\r
+    currentItemUnPacked = 0;\r
+    currentItemPacked = 0;\r
+\r
+    lps->InSize = currentTotalPacked;\r
+    lps->OutSize = currentTotalUnPacked;\r
+\r
+    RINOK(lps->SetCur());\r
+    UInt32 index = allFilesMode ? i : indices[i];\r
+    i++;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+\r
+    CMyComPtr<ISequentialOutStream> realOutStream;\r
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+    if (index >= (UInt32)_db.SortedItems.Size())\r
+    {\r
+      if (!testMode && !realOutStream)\r
+        continue;\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      const CByteBuffer &data = _xmls[index - (UInt32)_db.SortedItems.Size()].Data;\r
+      currentItemUnPacked = data.GetCapacity();\r
+      if (realOutStream)\r
+      {\r
+        RINOK(WriteStream(realOutStream, (const Byte *)data, data.GetCapacity()));\r
+        realOutStream.Release();\r
+      }\r
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+      continue;\r
+    }\r
+\r
+    const CItem &item = _db.Items[_db.SortedItems[index]];\r
+    int streamIndex = item.StreamIndex;\r
+    if (streamIndex < 0)\r
+    {\r
+      if (!testMode && !realOutStream)\r
+        continue;\r
+      RINOK(extractCallback->PrepareOperation(askMode));\r
+      realOutStream.Release();\r
+      RINOK(extractCallback->SetOperationResult(item.HasStream() ?\r
+            NExtract::NOperationResult::kDataError :\r
+            NExtract::NOperationResult::kOK));\r
+      continue;\r
+    }\r
+\r
+    const CStreamInfo &si = _db.Streams[streamIndex];\r
+    currentItemUnPacked = si.Resource.UnpackSize;\r
+    currentItemPacked = si.Resource.PackSize;\r
+\r
+    if (!testMode && !realOutStream)\r
+      continue;\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+    Int32 opRes = NExtract::NOperationResult::kOK;\r
+    if (streamIndex != prevSuccessStreamIndex || realOutStream)\r
+    {\r
+      Byte digest[20];\r
+      const CVolume &vol = _volumes[si.PartNumber];\r
+      HRESULT res = unpacker.Unpack(vol.Stream, si.Resource, vol.Header.IsLzxMode(),\r
+          realOutStream, progress, digest);\r
+      if (res == S_OK)\r
+      {\r
+        if (memcmp(digest, si.Hash, kHashSize) == 0)\r
+          prevSuccessStreamIndex = streamIndex;\r
+        else\r
+          opRes = NExtract::NOperationResult::kCRCError;\r
+      }\r
+      else if (res == S_FALSE)\r
+        opRes = NExtract::NOperationResult::kDataError;\r
+      else\r
+        return res;\r
+    }\r
+    realOutStream.Release();\r
+    RINOK(extractCallback->SetOperationResult(opRes));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _db.SortedItems.Size();\r
+  if (!_xmlInComments)\r
+    *numItems += _xmls.Size();\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Wim/WimHandler.h b/CPP/7zip/Archive/Wim/WimHandler.h
new file mode 100755 (executable)
index 0000000..5f5ab98
--- /dev/null
@@ -0,0 +1,77 @@
+// WimHandler.h\r
+\r
+#ifndef __ARCHIVE_WIM_HANDLER_H\r
+#define __ARCHIVE_WIM_HANDLER_H\r
+\r
+#include "Common/MyCom.h"\r
+#include "Common/MyXml.h"\r
+\r
+#include "WimIn.h"\r
+\r
+namespace NArchive {\r
+namespace NWim {\r
+\r
+struct CVolume\r
+{\r
+  CHeader Header;\r
+  CMyComPtr<IInStream> Stream;\r
+};\r
+\r
+struct CImageInfo\r
+{\r
+  bool CTimeDefined;\r
+  bool MTimeDefined;\r
+  bool NameDefined;\r
+  // bool IndexDefined;\r
+  \r
+  FILETIME CTime;\r
+  FILETIME MTime;\r
+  UString Name;\r
+  // UInt32 Index;\r
+  \r
+  CImageInfo(): CTimeDefined(false), MTimeDefined(false), NameDefined(false)\r
+      // , IndexDefined(false)\r
+      {}\r
+  void Parse(const CXmlItem &item);\r
+};\r
+\r
+struct CXml\r
+{\r
+  CByteBuffer Data;\r
+  UInt16 VolIndex;\r
+  CObjectVector<CImageInfo> Images;\r
+\r
+  void ToUnicode(UString &s);\r
+  void Parse();\r
+};\r
+\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public CMyUnknownImp\r
+{\r
+  CDatabase _db;\r
+  UInt32 _version;\r
+  bool _isOldVersion;\r
+  CObjectVector<CVolume> _volumes;\r
+  CObjectVector<CXml> _xmls;\r
+  int _nameLenForStreams;\r
+  bool _xmlInComments;\r
+\r
+public:\r
+  MY_UNKNOWN_IMP1(IInArchive)\r
+  INTERFACE_IInArchive(;)\r
+};\r
+\r
+class COutHandler:\r
+  public IOutArchive,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP1(IOutArchive)\r
+  INTERFACE_IOutArchive(;)\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
new file mode 100755 (executable)
index 0000000..5ee1b73
--- /dev/null
@@ -0,0 +1,639 @@
+// WimHandlerOut.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/CpuArch.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/IntToString.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../../Common/LimitedStreams.h"\r
+#include "../../Common/ProgressUtils.h"\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "../../Crypto/RandGen.h"\r
+#include "../../Crypto/Sha1.h"\r
+\r
+#include "WimHandler.h"\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace NWim {\r
+\r
+struct CSha1Hash\r
+{\r
+  Byte Hash[kHashSize];\r
+};\r
+\r
+struct CHashList\r
+{\r
+  CRecordVector<CSha1Hash> Digests;\r
+  CIntVector Sorted;\r
+\r
+  int AddUnique(const CSha1Hash &h);\r
+};\r
+\r
+int CHashList::AddUnique(const CSha1Hash &h)\r
+{\r
+  int left = 0, right = Sorted.Size();\r
+  while (left != right)\r
+  {\r
+    int mid = (left + right) / 2;\r
+    int index = Sorted[mid];\r
+    UInt32 i;\r
+    const Byte *hash2 = Digests[index].Hash;\r
+    for (i = 0; i < kHashSize; i++)\r
+      if (h.Hash[i] != hash2[i])\r
+        break;\r
+    if (i == kHashSize)\r
+      return index;\r
+    if (h.Hash[i] < hash2[i])\r
+      right = mid;\r
+    else\r
+      left = mid + 1;\r
+  }\r
+  Sorted.Insert(left, Digests.Add(h));\r
+  return -1;\r
+}\r
+\r
+struct CUpdateItem\r
+{\r
+  UString Name;\r
+  UInt64 Size;\r
+  FILETIME CTime;\r
+  FILETIME ATime;\r
+  FILETIME MTime;\r
+  UInt32 Attrib;\r
+  bool IsDir;\r
+  int HashIndex;\r
+\r
+  CUpdateItem(): HashIndex(-1) {}\r
+};\r
+\r
+struct CDir\r
+{\r
+  int Index;\r
+  UString Name;\r
+  CObjectVector<CDir> Dirs;\r
+  CIntVector Files;\r
+  \r
+  CDir(): Index(-1) {}\r
+  bool IsLeaf() const { return Index >= 0; }\r
+  UInt64 GetNumDirs() const;\r
+  UInt64 GetNumFiles() const;\r
+  CDir* AddDir(CObjectVector<CUpdateItem> &items, const UString &name, int index);\r
+};\r
+\r
+UInt64 CDir::GetNumDirs() const\r
+{\r
+  UInt64 num = Dirs.Size();\r
+  for (int i = 0; i < Dirs.Size(); i++)\r
+    num += Dirs[i].GetNumDirs();\r
+  return num;\r
+}\r
+\r
+UInt64 CDir::GetNumFiles() const\r
+{\r
+  UInt64 num = Files.Size();\r
+  for (int i = 0; i < Dirs.Size(); i++)\r
+    num += Dirs[i].GetNumFiles();\r
+  return num;\r
+}\r
+\r
+CDir* CDir::AddDir(CObjectVector<CUpdateItem> &items, const UString &name, int index)\r
+{\r
+  int left = 0, right = Dirs.Size();\r
+  while (left != right)\r
+  {\r
+    int mid = (left + right) / 2;\r
+    CDir &d = Dirs[mid];\r
+    int compare = name.CompareNoCase(d.IsLeaf() ? items[Dirs[mid].Index].Name : d.Name);\r
+    if (compare == 0)\r
+    {\r
+      if (index >= 0)\r
+        d.Index = index;\r
+      return &d;\r
+    }\r
+    if (compare < 0)\r
+      right = mid;\r
+    else\r
+      left = mid + 1;\r
+  }\r
+  Dirs.Insert(left, CDir());\r
+  CDir &d = Dirs[left];\r
+  d.Index = index;\r
+  if (index < 0)\r
+    d.Name = name;\r
+  return &d;\r
+}\r
+\r
+\r
+STDMETHODIMP COutHandler::GetFileTimeType(UInt32 *type)\r
+{\r
+  *type = NFileTimeType::kWindows;\r
+  return S_OK;\r
+}\r
+\r
+static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propID, FILETIME &ft)\r
+{\r
+  ft.dwLowDateTime = ft.dwHighDateTime = 0;\r
+  NCOM::CPropVariant prop;\r
+  RINOK(callback->GetProperty(index, propID, &prop));\r
+  if (prop.vt == VT_FILETIME)\r
+    ft = prop.filetime;\r
+  else if (prop.vt != VT_EMPTY)\r
+    return E_INVALIDARG;\r
+  return S_OK;\r
+}\r
+\r
+#define Set16(p, d) SetUi16(p, d)\r
+#define Set32(p, d) SetUi32(p, d)\r
+#define Set64(p, d) SetUi64(p, d)\r
+\r
+void CResource::WriteTo(Byte *p) const\r
+{\r
+  Set64(p, PackSize);\r
+  p[7] = Flags;\r
+  Set64(p + 8, Offset);\r
+  Set64(p + 16, UnpackSize);\r
+}\r
+\r
+void CHeader::WriteTo(Byte *p) const\r
+{\r
+  memcpy(p, kSignature, kSignatureSize);\r
+  Set32(p + 8, kHeaderSizeMax);\r
+  Set32(p + 0xC, Version);\r
+  Set32(p + 0x10, Flags);\r
+  Set32(p + 0x14, ChunkSize);\r
+  memcpy(p + 0x18, Guid, 16);\r
+  Set16(p + 0x28, PartNumber);\r
+  Set16(p + 0x2A, NumParts);\r
+  Set32(p + 0x2C, NumImages);\r
+  OffsetResource.WriteTo(p + 0x30);\r
+  XmlResource.WriteTo(p + 0x48);\r
+  MetadataResource.WriteTo(p + 0x60);\r
+  IntegrityResource.WriteTo(p + 0x7C);\r
+  Set32(p + 0x78, BootIndex);\r
+  memset(p + 0x94, 0, 60);\r
+}\r
+\r
+void CStreamInfo::WriteTo(Byte *p) const\r
+{\r
+  Resource.WriteTo(p);\r
+  Set16(p + 0x18, PartNumber);\r
+  Set32(p + 0x1A, RefCount);\r
+  memcpy(p + 0x1E, Hash, kHashSize);\r
+}\r
+\r
+class CInStreamWithSha1:\r
+  public ISequentialInStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<ISequentialInStream> _stream;\r
+  UInt64 _size;\r
+  NCrypto::NSha1::CContext _sha;\r
+public:\r
+  MY_UNKNOWN_IMP1(IInStream)\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+\r
+  void SetStream(ISequentialInStream *stream) { _stream = stream;  }\r
+  void Init()\r
+  {\r
+    _size = 0;\r
+    _sha.Init();\r
+  }\r
+  void ReleaseStream() { _stream.Release(); }\r
+  UInt64 GetSize() const { return _size; }\r
+  void Final(Byte *digest) { _sha.Final(digest); }\r
+};\r
+\r
+STDMETHODIMP CInStreamWithSha1::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  UInt32 realProcessedSize;\r
+  HRESULT result = _stream->Read(data, size, &realProcessedSize);\r
+  _size += realProcessedSize;\r
+  _sha.Update((const Byte *)data, realProcessedSize);\r
+  if (processedSize != NULL)\r
+    *processedSize = realProcessedSize;\r
+  return result;\r
+}\r
+\r
+static void SetFileTimeToMem(Byte *p, const FILETIME &ft)\r
+{\r
+  Set32(p, ft.dwLowDateTime);\r
+  Set32(p + 4, ft.dwHighDateTime);\r
+}\r
+\r
+static size_t WriteItem(const CUpdateItem &item, Byte *p, const Byte *hash)\r
+{\r
+  int fileNameLen = item.Name.Length() * 2;\r
+  int fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2);\r
+\r
+  size_t totalLen = ((kDirRecordSize + fileNameLen2 + 6) & ~7);\r
+  if (p)\r
+  {\r
+    memset(p, 0, totalLen);\r
+    Set64(p, totalLen);\r
+    Set64(p + 8, item.Attrib);\r
+    Set32(p + 0xC, (UInt32)(Int32)-1); // item.SecurityId\r
+    // Set64(p + 0x10, 0); // subdirOffset\r
+    SetFileTimeToMem(p + 0x28, item.CTime);\r
+    SetFileTimeToMem(p + 0x30, item.ATime);\r
+    SetFileTimeToMem(p + 0x38, item.MTime);\r
+    if (hash)\r
+      memcpy(p + 0x40, hash, kHashSize);\r
+    /*\r
+    else\r
+      memset(p + 0x40, 0, kHashSize);\r
+    */\r
+    // Set16(p + 98, 0); // shortNameLen\r
+    Set16(p + 100, (UInt16)fileNameLen);\r
+    for (int i = 0; i * 2 < fileNameLen; i++)\r
+      Set16(p + kDirRecordSize + i * 2, item.Name[i]);\r
+  }\r
+  return totalLen;\r
+}\r
+\r
+static void WriteTree(const CDir &tree, CRecordVector<CSha1Hash> &digests,\r
+    CUpdateItem &defaultDirItem,\r
+    CObjectVector<CUpdateItem> &updateItems, Byte *dest, size_t &pos)\r
+{\r
+  int i;\r
+  for (i = 0; i < tree.Files.Size(); i++)\r
+  {\r
+    const CUpdateItem &ui = updateItems[tree.Files[i]];\r
+    pos += WriteItem(ui, dest ? dest + pos : NULL,\r
+        ui.HashIndex >= 0 ? digests[ui.HashIndex].Hash : NULL);\r
+  }\r
+\r
+  size_t posStart = pos;\r
+  for (i = 0; i < tree.Dirs.Size(); i++)\r
+  {\r
+    const CDir &subfolder = tree.Dirs[i];\r
+    CUpdateItem *item = &defaultDirItem;\r
+    if (subfolder.IsLeaf())\r
+      item = &updateItems[subfolder.Index];\r
+    else\r
+      defaultDirItem.Name = subfolder.Name;\r
+    pos += WriteItem(*item, NULL, NULL);\r
+  }\r
+\r
+  if (dest)\r
+    Set64(dest + pos, 0);\r
+\r
+  pos += 8;\r
+\r
+  for (i = 0; i < tree.Dirs.Size(); i++)\r
+  {\r
+    const CDir &subfolder = tree.Dirs[i];\r
+    if (dest)\r
+    {\r
+      CUpdateItem *item = &defaultDirItem;\r
+      if (subfolder.IsLeaf())\r
+        item = &updateItems[subfolder.Index];\r
+      else\r
+        defaultDirItem.Name = subfolder.Name;\r
+      size_t len = WriteItem(*item, dest + posStart, NULL);\r
+      Set64(dest + posStart + 0x10, pos);\r
+      posStart += len;\r
+    }\r
+    WriteTree(subfolder, digests, defaultDirItem, updateItems, dest, pos);\r
+  }\r
+}\r
+\r
+static void AddTag(AString &s, const char *name, const AString &value)\r
+{\r
+  s += "<";\r
+  s += name;\r
+  s += ">";\r
+  s += value;\r
+  s += "</";\r
+  s += name;\r
+  s += ">";\r
+}\r
+\r
+static void AddTagUInt64(AString &s, const char *name, UInt64 value)\r
+{\r
+  char temp[32];\r
+  ConvertUInt64ToString(value, temp);\r
+  AddTag(s, name, temp);\r
+}\r
+\r
+static AString TimeToXml(FILETIME &ft)\r
+{\r
+  AString res;\r
+  char temp[16] = { '0', 'x' };\r
+  ConvertUInt32ToHexWithZeros(ft.dwHighDateTime, temp + 2);\r
+  AddTag(res, "HIGHPART", temp);\r
+  ConvertUInt32ToHexWithZeros(ft.dwLowDateTime, temp + 2);\r
+  AddTag(res, "LOWPART", temp);\r
+  return res;\r
+}\r
+\r
+void CHeader::SetDefaultFields(bool useLZX)\r
+{\r
+  Version = kWimVersion;\r
+  Flags = NHeaderFlags::kRpFix;\r
+  ChunkSize = 0;\r
+  if (useLZX)\r
+  {\r
+    Flags |= NHeaderFlags::kCompression | NHeaderFlags::kLZX;\r
+    ChunkSize = kChunkSize;\r
+  }\r
+  g_RandomGenerator.Generate(Guid, 16);\r
+  PartNumber = 1;\r
+  NumParts = 1;\r
+  NumImages = 1;\r
+  BootIndex = 0;\r
+  OffsetResource.Clear();\r
+  XmlResource.Clear();\r
+  MetadataResource.Clear();\r
+  IntegrityResource.Clear();\r
+}\r
+\r
+static HRESULT UpdateArchive(ISequentialOutStream *seqOutStream,\r
+    CDir &rootFolder,\r
+    CObjectVector<CUpdateItem> &updateItems,\r
+    IArchiveUpdateCallback *callback)\r
+{\r
+  CMyComPtr<IOutStream> outStream;\r
+  RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream));\r
+  if (!outStream)\r
+    return E_NOTIMPL;\r
+\r
+  UInt64 complexity = 0;\r
+\r
+  int i;\r
+  for (i = 0; i < updateItems.Size(); i++)\r
+    complexity += updateItems[i].Size;\r
+\r
+  RINOK(callback->SetTotal(complexity));\r
+\r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(callback, true);\r
+\r
+  complexity = 0;\r
+\r
+  bool useCompression = false;\r
+\r
+  CHeader header;\r
+  header.SetDefaultFields(useCompression);\r
+  Byte buf[kHeaderSizeMax];\r
+  header.WriteTo(buf);\r
+  RINOK(WriteStream(outStream, buf, kHeaderSizeMax));\r
+\r
+  CHashList hashes;\r
+  CObjectVector<CStreamInfo> streams;\r
+\r
+  UInt64 curPos = kHeaderSizeMax;\r
+  UInt64 unpackTotalSize = 0;\r
+  for (i = 0; i < updateItems.Size(); i++)\r
+  {\r
+    lps->InSize = lps->OutSize = complexity;\r
+    RINOK(lps->SetCur());\r
+\r
+    CUpdateItem &ui = updateItems[i];\r
+    if (ui.IsDir || ui.Size == 0)\r
+      continue;\r
+\r
+    CInStreamWithSha1 *inShaStreamSpec = new CInStreamWithSha1;\r
+    CMyComPtr<ISequentialInStream> inShaStream = inShaStreamSpec;\r
+\r
+    {\r
+      CMyComPtr<ISequentialInStream> fileInStream;\r
+      HRESULT res = callback->GetStream(i, &fileInStream);\r
+      if (res != S_FALSE)\r
+      {\r
+        RINOK(res);\r
+        inShaStreamSpec->SetStream(fileInStream);\r
+        fileInStream.Release();\r
+        inShaStreamSpec->Init();\r
+        UInt64 offsetBlockSize = 0;\r
+        if (useCompression)\r
+        {\r
+          for (UInt64 t = kChunkSize; t < ui.Size; t += kChunkSize)\r
+          {\r
+            Byte buf[8];\r
+            SetUi32(buf, (UInt32)t);\r
+            RINOK(WriteStream(outStream, buf, 4));\r
+            offsetBlockSize += 4;\r
+          }\r
+        }\r
+\r
+        RINOK(copyCoder->Code(inShaStream, outStream, NULL, NULL, progress));\r
+        ui.Size = copyCoderSpec->TotalSize;\r
+\r
+        CSha1Hash hash;\r
+        unpackTotalSize += ui.Size;\r
+        UInt64 packSize = offsetBlockSize + ui.Size;\r
+        inShaStreamSpec->Final(hash.Hash);\r
+        int index = hashes.AddUnique(hash);\r
+        if (index >= 0)\r
+        {\r
+          ui.HashIndex = index;\r
+          streams[index].RefCount++;\r
+          outStream->Seek(-(Int64)packSize, STREAM_SEEK_CUR, &curPos);\r
+          outStream->SetSize(curPos);\r
+        }\r
+        else\r
+        {\r
+          ui.HashIndex = hashes.Digests.Size() - 1;\r
+          CStreamInfo s;\r
+          s.Resource.PackSize = packSize;\r
+          s.Resource.Offset = curPos;\r
+          s.Resource.UnpackSize = ui.Size;\r
+          s.Resource.Flags = 0;\r
+          if (useCompression)\r
+            s.Resource.Flags = NResourceFlags::Compressed;\r
+          s.PartNumber = 1;\r
+          s.RefCount = 1;\r
+          memcpy(s.Hash, hash.Hash, kHashSize);\r
+          streams.Add(s);\r
+          curPos += packSize;\r
+        }\r
+      }\r
+      fileInStream.Release();\r
+      complexity += ui.Size;\r
+      RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));\r
+    }\r
+  }\r
+\r
+\r
+  CUpdateItem ri;\r
+  FILETIME ft;\r
+  NTime::GetCurUtcFileTime(ft);\r
+  ri.MTime = ri.ATime = ri.CTime = ft;\r
+  ri.Attrib = FILE_ATTRIBUTE_DIRECTORY;\r
+\r
+  const UInt32 kSecuritySize = 8;\r
+  size_t pos = kSecuritySize;\r
+  WriteTree(rootFolder, hashes.Digests, ri, updateItems, NULL, pos);\r
+  \r
+  CByteBuffer meta;\r
+  meta.SetCapacity(pos);\r
+  \r
+  // we can write 0 here only if there is no security data, imageX does it,\r
+  // but some programs expect size = 8\r
+  Set32((Byte *)meta, 8); // size of security data\r
+  Set32((Byte *)meta + 4, 0); // num security entries\r
+  \r
+  pos = kSecuritySize;\r
+  WriteTree(rootFolder, hashes.Digests, ri, updateItems, (Byte *)meta, pos);\r
+\r
+  {\r
+    NCrypto::NSha1::CContext sha;\r
+    sha.Init();\r
+    sha.Update((const Byte *)meta, pos);\r
+    CSha1Hash digest;\r
+    sha.Final(digest.Hash);\r
+\r
+    CStreamInfo s;\r
+    s.Resource.PackSize = pos;\r
+    s.Resource.Offset = curPos;\r
+    s.Resource.UnpackSize = pos;\r
+    s.Resource.Flags = NResourceFlags::kMetadata;\r
+    s.PartNumber = 1;\r
+    s.RefCount = 1;\r
+    memcpy(s.Hash, digest.Hash, kHashSize);\r
+    streams.Add(s);\r
+    RINOK(WriteStream(outStream, (const Byte *)meta, pos));\r
+    meta.Free();\r
+    curPos += pos;\r
+  }\r
+\r
+\r
+  header.OffsetResource.UnpackSize = header.OffsetResource.PackSize = (UInt64)streams.Size() * kStreamInfoSize;\r
+  header.OffsetResource.Offset = curPos;\r
+  header.OffsetResource.Flags = NResourceFlags::kMetadata;\r
+\r
+  for (i = 0; i < streams.Size(); i++)\r
+  {\r
+    Byte buf[kStreamInfoSize];\r
+    streams[i].WriteTo(buf);\r
+    RINOK(WriteStream(outStream, buf, kStreamInfoSize));\r
+    curPos += kStreamInfoSize;\r
+  }\r
+\r
+  AString xml = "<WIM>";\r
+  AddTagUInt64(xml, "TOTALBYTES", curPos);\r
+  xml += "<IMAGE INDEX=\"1\"><NAME>1</NAME>";\r
+  AddTagUInt64(xml, "DIRCOUNT", rootFolder.GetNumDirs());\r
+  AddTagUInt64(xml, "FILECOUNT", rootFolder.GetNumFiles());\r
+  AddTagUInt64(xml, "TOTALBYTES", unpackTotalSize);\r
+  NTime::GetCurUtcFileTime(ft);\r
+  AddTag(xml, "CREATIONTIME", TimeToXml(ft));\r
+  AddTag(xml, "LASTMODIFICATIONTIME", TimeToXml(ft));\r
+  xml += "</IMAGE></WIM>";\r
+\r
+  size_t xmlSize = (xml.Length() + 1) * 2;\r
+  meta.SetCapacity(xmlSize);\r
+  Set16((Byte *)meta, 0xFEFF);\r
+  for (i = 0; i < xml.Length(); i++)\r
+    Set16((Byte *)meta + 2 + i * 2, xml[i]);\r
+  RINOK(WriteStream(outStream, (const Byte *)meta, xmlSize));\r
+  meta.Free();\r
+  \r
+  header.XmlResource.UnpackSize = header.XmlResource.PackSize = xmlSize;\r
+  header.XmlResource.Offset = curPos;\r
+  header.XmlResource.Flags = NResourceFlags::kMetadata;\r
+\r
+  outStream->Seek(0, STREAM_SEEK_SET, NULL);\r
+  header.WriteTo(buf);\r
+  return WriteStream(outStream, buf, kHeaderSizeMax);\r
+}\r
+\r
+STDMETHODIMP COutHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\r
+    IArchiveUpdateCallback *callback)\r
+{\r
+  COM_TRY_BEGIN\r
+  CObjectVector<CUpdateItem> updateItems;\r
+  CDir tree;\r
+  tree.Dirs.Add(CDir());\r
+  CDir &rootFolder = tree.Dirs.Back();\r
+\r
+  for (UInt32 i = 0; i < numItems; i++)\r
+  {\r
+    CUpdateItem ui;\r
+    Int32 newData, newProps;\r
+    UInt32 indexInArchive;\r
+    if (!callback)\r
+      return E_FAIL;\r
+    RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));\r
+\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      RINOK(callback->GetProperty(i, kpidIsDir, &prop));\r
+      if (prop.vt == VT_EMPTY)\r
+        ui.IsDir = false;\r
+      else if (prop.vt != VT_BOOL)\r
+        return E_INVALIDARG;\r
+      else\r
+        ui.IsDir = (prop.boolVal != VARIANT_FALSE);\r
+    }\r
+    \r
+    {\r
+      NCOM::CPropVariant prop;\r
+      RINOK(callback->GetProperty(i, kpidAttrib, &prop));\r
+      if (prop.vt == VT_EMPTY)\r
+        ui.Attrib = (ui.IsDir ? FILE_ATTRIBUTE_DIRECTORY : 0);\r
+      else if (prop.vt != VT_UI4)\r
+        return E_INVALIDARG;\r
+      else\r
+        ui.Attrib = prop.ulVal;\r
+    }\r
+    \r
+    RINOK(GetTime(callback, i, kpidCTime, ui.CTime));\r
+    RINOK(GetTime(callback, i, kpidATime, ui.ATime));\r
+    RINOK(GetTime(callback, i, kpidMTime, ui.MTime));\r
+\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      RINOK(callback->GetProperty(i, kpidSize, &prop));\r
+      if (prop.vt != VT_UI8)\r
+        return E_INVALIDARG;\r
+      ui.Size = prop.uhVal.QuadPart;\r
+    }\r
+\r
+    UString path;\r
+    NCOM::CPropVariant prop;\r
+    RINOK(callback->GetProperty(i, kpidPath, &prop));\r
+    if (prop.vt == VT_BSTR)\r
+      path = prop.bstrVal;\r
+    else if (prop.vt != VT_EMPTY)\r
+      return E_INVALIDARG;\r
+\r
+    CDir *curItem = &rootFolder;\r
+    int len = path.Length();\r
+    UString fileName;\r
+    for (int j = 0; j < len; j++)\r
+    {\r
+      wchar_t c = path[j];\r
+      if (c == WCHAR_PATH_SEPARATOR || c == L'/')\r
+      {\r
+        curItem = curItem->AddDir(updateItems, fileName, -1);\r
+        fileName.Empty();\r
+      }\r
+      else\r
+        fileName += c;\r
+    }\r
+\r
+    ui.Name = fileName;\r
+    updateItems.Add(ui);\r
+    if (ui.IsDir)\r
+      curItem->AddDir(updateItems, fileName, (int)i);\r
+    else\r
+      curItem->Files.Add(i);\r
+  }\r
+  return UpdateArchive(outStream, tree, updateItems, callback);\r
+  COM_TRY_END\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp
new file mode 100755 (executable)
index 0000000..48d8321
--- /dev/null
@@ -0,0 +1,855 @@
+// Archive/WimIn.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/CpuArch.h"\r
+\r
+#include "Common/IntToString.h"\r
+\r
+#include "../../Common/StreamUtils.h"\r
+#include "../../Common/StreamObjects.h"\r
+#include "../../Common/LimitedStreams.h"\r
+\r
+#include "../Common/OutStreamWithSha1.h"\r
+\r
+#include "WimIn.h"\r
+\r
+#define Get16(p) GetUi16(p)\r
+#define Get32(p) GetUi32(p)\r
+#define Get64(p) GetUi64(p)\r
+\r
+namespace NArchive {\r
+namespace NWim {\r
+\r
+namespace NXpress {\r
+\r
+class CDecoderFlusher\r
+{\r
+  CDecoder *m_Decoder;\r
+public:\r
+  bool NeedFlush;\r
+  CDecoderFlusher(CDecoder *decoder): m_Decoder(decoder), NeedFlush(true) {}\r
+  ~CDecoderFlusher()\r
+  {\r
+    if (NeedFlush)\r
+      m_Decoder->Flush();\r
+    m_Decoder->ReleaseStreams();\r
+  }\r
+};\r
+\r
+HRESULT CDecoder::CodeSpec(UInt32 outSize)\r
+{\r
+  {\r
+    Byte levels[kMainTableSize];\r
+    for (unsigned i = 0; i < kMainTableSize; i += 2)\r
+    {\r
+      Byte b = m_InBitStream.DirectReadByte();\r
+      levels[i] = b & 0xF;\r
+      levels[i + 1] = b >> 4;\r
+    }\r
+    if (!m_MainDecoder.SetCodeLengths(levels))\r
+      return S_FALSE;\r
+  }\r
+\r
+  while (outSize > 0)\r
+  {\r
+    UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);\r
+    if (number < 256)\r
+    {\r
+      m_OutWindowStream.PutByte((Byte)number);\r
+      outSize--;\r
+    }\r
+    else\r
+    {\r
+      if (number >= kMainTableSize)\r
+        return S_FALSE;\r
+      UInt32 posLenSlot = number - 256;\r
+      UInt32 posSlot = posLenSlot / kNumLenSlots;\r
+      UInt32 len = posLenSlot % kNumLenSlots;\r
+      UInt32 distance = (1 << posSlot) - 1 + m_InBitStream.ReadBits(posSlot);\r
+      \r
+      if (len == kNumLenSlots - 1)\r
+      {\r
+        len = m_InBitStream.DirectReadByte();\r
+        if (len == 0xFF)\r
+        {\r
+          len = m_InBitStream.DirectReadByte();\r
+          len |= (UInt32)m_InBitStream.DirectReadByte() << 8;\r
+        }\r
+        else\r
+          len += kNumLenSlots - 1;\r
+      }\r
+      \r
+      len += kMatchMinLen;\r
+      UInt32 locLen = (len <= outSize ? len : outSize);\r
+\r
+      if (!m_OutWindowStream.CopyBlock(distance, locLen))\r
+        return S_FALSE;\r
+      \r
+      len -= locLen;\r
+      outSize -= locLen;\r
+      if (len != 0)\r
+        return S_FALSE;\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+const UInt32 kDictSize = (1 << kNumPosSlots);\r
+\r
+HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt32 outSize)\r
+{\r
+  if (!m_OutWindowStream.Create(kDictSize) || !m_InBitStream.Create(1 << 16))\r
+    return E_OUTOFMEMORY;\r
+\r
+  CDecoderFlusher flusher(this);\r
+\r
+  m_InBitStream.SetStream(inStream);\r
+  m_OutWindowStream.SetStream(outStream);\r
+  m_InBitStream.Init();\r
+  m_OutWindowStream.Init(false);\r
+\r
+  RINOK(CodeSpec(outSize));\r
+\r
+  flusher.NeedFlush = false;\r
+  return Flush();\r
+}\r
+\r
+HRESULT CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt32 outSize)\r
+{\r
+  try { return CodeReal(inStream, outStream, outSize); }\r
+  catch(const CInBufferException &e) { return e.ErrorCode; } \\r
+  catch(const CLzOutWindowException &e) { return e.ErrorCode; }\r
+  catch(...) { return S_FALSE; }\r
+}\r
+\r
+}\r
+\r
+HRESULT CUnpacker::Unpack(IInStream *inStream, const CResource &resource, bool lzxMode,\r
+    ISequentialOutStream *outStream, ICompressProgressInfo *progress)\r
+{\r
+  RINOK(inStream->Seek(resource.Offset, STREAM_SEEK_SET, NULL));\r
+\r
+  CLimitedSequentialInStream *limitedStreamSpec = new CLimitedSequentialInStream();\r
+  CMyComPtr<ISequentialInStream> limitedStream = limitedStreamSpec;\r
+  limitedStreamSpec->SetStream(inStream);\r
+\r
+  if (!copyCoder)\r
+  {\r
+    copyCoderSpec = new NCompress::CCopyCoder;\r
+    copyCoder = copyCoderSpec;\r
+  }\r
+  if (!resource.IsCompressed())\r
+  {\r
+    if (resource.PackSize != resource.UnpackSize)\r
+      return S_FALSE;\r
+    limitedStreamSpec->Init(resource.PackSize);\r
+    return copyCoder->Code(limitedStreamSpec, outStream, NULL, NULL, progress);\r
+  }\r
+  if (resource.UnpackSize == 0)\r
+    return S_OK;\r
+  UInt64 numChunks = (resource.UnpackSize + kChunkSize - 1) >> kChunkSizeBits;\r
+  unsigned entrySize = ((resource.UnpackSize > (UInt64)1 << 32) ? 8 : 4);\r
+  UInt64 sizesBufSize64 = entrySize * (numChunks - 1);\r
+  size_t sizesBufSize = (size_t)sizesBufSize64;\r
+  if (sizesBufSize != sizesBufSize64)\r
+    return E_OUTOFMEMORY;\r
+  if (sizesBufSize > sizesBuf.GetCapacity())\r
+  {\r
+    sizesBuf.Free();\r
+    sizesBuf.SetCapacity(sizesBufSize);\r
+  }\r
+  RINOK(ReadStream_FALSE(inStream, (Byte *)sizesBuf, sizesBufSize));\r
+  const Byte *p = (const Byte *)sizesBuf;\r
+  \r
+  if (lzxMode && !lzxDecoder)\r
+  {\r
+    lzxDecoderSpec = new NCompress::NLzx::CDecoder(true);\r
+    lzxDecoder = lzxDecoderSpec;\r
+    RINOK(lzxDecoderSpec->SetParams(kChunkSizeBits));\r
+  }\r
+  \r
+  UInt64 baseOffset = resource.Offset + sizesBufSize64;\r
+  UInt64 outProcessed = 0;\r
+  for (UInt32 i = 0; i < (UInt32)numChunks; i++)\r
+  {\r
+    UInt64 offset = 0;\r
+    if (i > 0)\r
+    {\r
+      offset = (entrySize == 4) ? Get32(p): Get64(p);\r
+      p += entrySize;\r
+    }\r
+    UInt64 nextOffset = resource.PackSize - sizesBufSize64;\r
+    if (i + 1 < (UInt32)numChunks)\r
+      nextOffset = (entrySize == 4) ? Get32(p): Get64(p);\r
+    if (nextOffset < offset)\r
+      return S_FALSE;\r
+\r
+    RINOK(inStream->Seek(baseOffset + offset, STREAM_SEEK_SET, NULL));\r
+    UInt64 inSize = nextOffset - offset;\r
+    limitedStreamSpec->Init(inSize);\r
+\r
+    if (progress)\r
+    {\r
+      RINOK(progress->SetRatioInfo(&offset, &outProcessed));\r
+    }\r
+    \r
+    UInt32 outSize = kChunkSize;\r
+    if (outProcessed + outSize > resource.UnpackSize)\r
+      outSize = (UInt32)(resource.UnpackSize - outProcessed);\r
+    UInt64 outSize64 = outSize;\r
+    if (inSize == outSize)\r
+    {\r
+      RINOK(copyCoder->Code(limitedStreamSpec, outStream, NULL, &outSize64, NULL));\r
+    }\r
+    else\r
+    {\r
+      if (lzxMode)\r
+      {\r
+        lzxDecoderSpec->SetKeepHistory(false);\r
+        RINOK(lzxDecoder->Code(limitedStreamSpec, outStream, NULL, &outSize64, NULL));\r
+      }\r
+      else\r
+      {\r
+        RINOK(xpressDecoder.Code(limitedStreamSpec, outStream, outSize));\r
+      }\r
+    }\r
+    outProcessed += outSize;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUnpacker::Unpack(IInStream *inStream, const CResource &resource, bool lzxMode,\r
+    ISequentialOutStream *outStream, ICompressProgressInfo *progress, Byte *digest)\r
+{\r
+  COutStreamWithSha1 *shaStreamSpec = new COutStreamWithSha1();\r
+  CMyComPtr<ISequentialOutStream> shaStream = shaStreamSpec;\r
+  shaStreamSpec->SetStream(outStream);\r
+  shaStreamSpec->Init(digest != NULL);\r
+  HRESULT result = Unpack(inStream, resource, lzxMode, shaStream, progress);\r
+  if (digest)\r
+    shaStreamSpec->Final(digest);\r
+  return result;\r
+}\r
+\r
+static HRESULT UnpackData(IInStream *inStream, const CResource &resource, bool lzxMode, CByteBuffer &buf, Byte *digest)\r
+{\r
+  size_t size = (size_t)resource.UnpackSize;\r
+  if (size != resource.UnpackSize)\r
+    return E_OUTOFMEMORY;\r
+  buf.Free();\r
+  buf.SetCapacity(size);\r
+\r
+  CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream();\r
+  CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;\r
+  outStreamSpec->Init((Byte *)buf, size);\r
+\r
+  CUnpacker unpacker;\r
+  return unpacker.Unpack(inStream, resource, lzxMode, outStream, NULL, digest);\r
+}\r
+\r
+void CResource::Parse(const Byte *p)\r
+{\r
+  Flags = p[7];\r
+  PackSize = Get64(p) & (((UInt64)1 << 56) - 1);\r
+  Offset = Get64(p + 8);\r
+  UnpackSize = Get64(p + 16);\r
+}\r
+\r
+#define GetResource(p, res) res.Parse(p)\r
+\r
+static void GetStream(bool oldVersion, const Byte *p, CStreamInfo &s)\r
+{\r
+  s.Resource.Parse(p);\r
+  if (oldVersion)\r
+  {\r
+    s.PartNumber = 1;\r
+    s.Id = Get32(p + 24);\r
+    s.RefCount = Get32(p + 28);\r
+    memcpy(s.Hash, p + 32, kHashSize);\r
+  }\r
+  else\r
+  {\r
+    s.PartNumber = Get16(p + 24);\r
+    s.RefCount = Get32(p + 26);\r
+    memcpy(s.Hash, p + 30, kHashSize);\r
+  }\r
+}\r
+\r
+static const wchar_t *kLongPath = L"[LongPath]";\r
+\r
+UString CDatabase::GetItemPath(const int index1) const\r
+{\r
+  int size = 0;\r
+  int index = index1;\r
+  int newLevel;\r
+  for (newLevel = 0;; newLevel = 1)\r
+  {\r
+    const CItem &item = Items[index];\r
+    index = item.Parent;\r
+    if (index >= 0 || !SkipRoot)\r
+      size += item.Name.Length() + newLevel;\r
+    if (index < 0)\r
+      break;\r
+    if ((UInt32)size >= ((UInt32)1 << 16))\r
+      return kLongPath;\r
+  }\r
+\r
+  wchar_t temp[16];\r
+  int imageLen = 0;\r
+  if (ShowImageNumber)\r
+  {\r
+    ConvertUInt32ToString(-1 - index, temp);\r
+    imageLen = MyStringLen(temp);\r
+    size += imageLen + 1;\r
+  }\r
+  if ((UInt32)size >= ((UInt32)1 << 16))\r
+    return kLongPath;\r
+  \r
+  UString path;\r
+  wchar_t *s = path.GetBuffer(size);\r
+  s[size] = 0;\r
+  if (ShowImageNumber)\r
+  {\r
+    memcpy(s, temp, imageLen * sizeof(wchar_t));\r
+    s[imageLen] = WCHAR_PATH_SEPARATOR;\r
+  }\r
+\r
+  index = index1;\r
+  \r
+  for (newLevel = 0;; newLevel = 1)\r
+  {\r
+    const CItem &item = Items[index];\r
+    index = item.Parent;\r
+    if (index >= 0 || !SkipRoot)\r
+    {\r
+      if (newLevel)\r
+        s[--size] = WCHAR_PATH_SEPARATOR;\r
+      size -= item.Name.Length();\r
+      memcpy(s + size, item.Name, sizeof(wchar_t) * item.Name.Length());\r
+    }\r
+    if (index < 0)\r
+    {\r
+      path.ReleaseBuffer();\r
+      return path;\r
+    }\r
+  }\r
+}\r
+\r
+static void GetFileTimeFromMem(const Byte *p, FILETIME *ft)\r
+{\r
+  ft->dwLowDateTime = Get32(p);\r
+  ft->dwHighDateTime = Get32(p + 4);\r
+}\r
+\r
+static HRESULT ReadName(const Byte *p, int size, UString &dest)\r
+{\r
+  if (size == 0)\r
+    return S_OK;\r
+  if (Get16(p + size) != 0)\r
+    return S_FALSE;\r
+  wchar_t *s = dest.GetBuffer(size / 2);\r
+  for (int i = 0; i <= size; i += 2)\r
+    *s++ = Get16(p + i);\r
+  dest.ReleaseBuffer();\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CDatabase::ParseDirItem(size_t pos, int parent)\r
+{\r
+  if ((pos & 7) != 0)\r
+    return S_FALSE;\r
+  \r
+  int prevIndex = -1;\r
+  for (int numItems = 0;; numItems++)\r
+  {\r
+    if (OpenCallback)\r
+    {\r
+      UInt64 numFiles = Items.Size();\r
+      if ((numFiles & 0x3FF) == 0)\r
+      {\r
+        RINOK(OpenCallback->SetCompleted(&numFiles, NULL));\r
+      }\r
+    }\r
+    size_t rem = DirSize - pos;\r
+    if (pos < DirStartOffset || pos > DirSize || rem < 8)\r
+      return S_FALSE;\r
+    const Byte *p = DirData + pos;\r
+    UInt64 len = Get64(p);\r
+    if (len == 0)\r
+    {\r
+      if (parent < 0 && numItems != 1)\r
+        SkipRoot = false;\r
+      DirProcessed += 8;\r
+      return S_OK;\r
+    }\r
+    if ((len & 7) != 0 || rem < len)\r
+      return S_FALSE;\r
+    if (!IsOldVersion)\r
+      if (len < 0x28)\r
+        return S_FALSE;\r
+    DirProcessed += (size_t)len;\r
+    if (DirProcessed > DirSize)\r
+      return S_FALSE;\r
+    int extraOffset = 0;\r
+    if (IsOldVersion)\r
+    {\r
+      if (len < 0x40 || (/* Get32(p + 12) == 0 && */ Get32(p + 0x14) != 0))\r
+      {\r
+        extraOffset = 0x10;\r
+      }\r
+    }\r
+    else if (Get64(p + 8) == 0)\r
+      extraOffset = 0x24;\r
+    if (extraOffset)\r
+    {\r
+      if (prevIndex == -1)\r
+        return S_FALSE;\r
+      UInt32 fileNameLen = Get16(p + extraOffset);\r
+      if ((fileNameLen & 1) != 0)\r
+        return S_FALSE;\r
+      /* Probably different versions of ImageX can use different number of\r
+         additional ZEROs. So we don't use exact check. */\r
+      UInt32 fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2);\r
+      if (((extraOffset + 2 + fileNameLen2 + 6) & ~7) > len)\r
+        return S_FALSE;\r
+      \r
+      UString name;\r
+      RINOK(ReadName(p + extraOffset + 2, fileNameLen, name));\r
+\r
+      CItem &prevItem = Items[prevIndex];\r
+      if (name.IsEmpty() && !prevItem.HasStream())\r
+      {\r
+        if (IsOldVersion)\r
+          prevItem.Id = Get32(p + 8);\r
+        else\r
+          memcpy(prevItem.Hash, p + 0x10, kHashSize);\r
+      }\r
+      else\r
+      {\r
+        CItem item;\r
+        item.Name = prevItem.Name + L':' + name;\r
+        item.CTime = prevItem.CTime;\r
+        item.ATime = prevItem.ATime;\r
+        item.MTime = prevItem.MTime;\r
+        if (IsOldVersion)\r
+        {\r
+          item.Id = Get32(p + 8);\r
+          memset(item.Hash, 0, kHashSize);\r
+        }\r
+        else\r
+          memcpy(item.Hash, p + 0x10, kHashSize);\r
+        item.Attrib = 0;\r
+        item.Order = Order++;\r
+        item.Parent = parent;\r
+        Items.Add(item);\r
+      }\r
+      pos += (size_t)len;\r
+      continue;\r
+    }\r
+\r
+    UInt32 dirRecordSize = IsOldVersion ? kDirRecordSizeOld : kDirRecordSize;\r
+    if (len < dirRecordSize)\r
+      return S_FALSE;\r
+\r
+    CItem item;\r
+    item.Attrib = Get32(p + 8);\r
+    // item.SecurityId = Get32(p + 0xC);\r
+    UInt64 subdirOffset = Get64(p + 0x10);\r
+    UInt32 timeOffset = IsOldVersion ? 0x18: 0x28;\r
+    GetFileTimeFromMem(p + timeOffset,      &item.CTime);\r
+    GetFileTimeFromMem(p + timeOffset + 8,  &item.ATime);\r
+    GetFileTimeFromMem(p + timeOffset + 16, &item.MTime);\r
+    if (IsOldVersion)\r
+    {\r
+      item.Id = Get32(p + 0x10);\r
+      memset(item.Hash, 0, kHashSize);\r
+    }\r
+    else\r
+    {\r
+      memcpy(item.Hash, p + 0x40, kHashSize);\r
+    }\r
+    // UInt32 numStreams = Get16(p + dirRecordSize - 6);\r
+    UInt32 shortNameLen = Get16(p + dirRecordSize - 4);\r
+    UInt32 fileNameLen = Get16(p + dirRecordSize - 2);\r
+\r
+    if ((shortNameLen & 1) != 0 || (fileNameLen & 1) != 0)\r
+      return S_FALSE;\r
+\r
+    UInt32 shortNameLen2 = (shortNameLen == 0 ? shortNameLen : shortNameLen + 2);\r
+    UInt32 fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2);\r
+\r
+    if (((dirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7) > len)\r
+      return S_FALSE;\r
+    p += dirRecordSize;\r
+    \r
+    RINOK(ReadName(p, fileNameLen, item.Name));\r
+    RINOK(ReadName(p + fileNameLen2, shortNameLen, item.ShortName));\r
+\r
+    if (parent < 0 && (shortNameLen || fileNameLen || !item.IsDir()))\r
+      SkipRoot = false;\r
+\r
+    /*\r
+    // there are some extra data for some files.\r
+    p -= dirRecordSize;\r
+    p += ((dirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7);\r
+    if (((dirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7) != len)\r
+      p = p;\r
+    */\r
+\r
+    /*\r
+    if (parent >= 0)\r
+    {\r
+      UString s = GetItemPath(parent) + L"\\" + item.Name;\r
+      printf("\n%s %8x %S", item.IsDir() ? "D" : " ", (int)subdirOffset, (const wchar_t *)s);\r
+    }\r
+    */\r
+\r
+    if (fileNameLen == 0 && item.IsDir() && !item.HasStream())\r
+      item.Attrib = 0x10; // some swm archives have system/hidden attributes for root\r
+\r
+    item.Parent = parent;\r
+    prevIndex = Items.Add(item);\r
+    if (item.IsDir() && subdirOffset != 0)\r
+    {\r
+      RINOK(ParseDirItem((size_t)subdirOffset, prevIndex));\r
+    }\r
+    Items[prevIndex].Order = Order++;\r
+    pos += (size_t)len;\r
+  }\r
+}\r
+\r
+HRESULT CDatabase::ParseImageDirs(const CByteBuffer &buf, int parent)\r
+{\r
+  DirData = buf;\r
+  DirSize = buf.GetCapacity();\r
+\r
+  size_t pos = 0;\r
+  if (DirSize < 8)\r
+    return S_FALSE;\r
+  const Byte *p = DirData;\r
+  UInt32 totalLength = Get32(p);\r
+  if (IsOldVersion)\r
+  {\r
+    for (pos = 4;; pos += 8)\r
+    {\r
+      if (pos + 4 > DirSize)\r
+        return S_FALSE;\r
+      UInt32 n = Get32(p + pos);\r
+      if (n == 0)\r
+        break;\r
+      if (pos + 8 > DirSize)\r
+        return S_FALSE;\r
+      totalLength += Get32(p + pos + 4);\r
+      if (totalLength > DirSize)\r
+        return S_FALSE;\r
+    }\r
+    pos += totalLength + 4;\r
+    pos = (pos + 7) & ~(size_t)7;\r
+    if (pos > DirSize)\r
+      return S_FALSE;\r
+  }\r
+  else\r
+  {\r
+\r
+  // UInt32 numEntries = Get32(p + 4);\r
+  pos += 8;\r
+  {\r
+    /*\r
+    CRecordVector<UInt64> entryLens;\r
+    UInt64 sum = 0;\r
+    for (UInt32 i = 0; i < numEntries; i++)\r
+    {\r
+      if (pos + 8 > DirSize)\r
+        return S_FALSE;\r
+      UInt64 len = Get64(p + pos);\r
+      entryLens.Add(len);\r
+      sum += len;\r
+      pos += 8;\r
+    }\r
+    pos += (size_t)sum; // skip security descriptors\r
+    while ((pos & 7) != 0)\r
+      pos++;\r
+    if (pos != totalLength)\r
+      return S_FALSE;\r
+    */\r
+    if (totalLength == 0)\r
+      pos = 8;\r
+    else if (totalLength < 8)\r
+      return S_FALSE;\r
+    else\r
+      pos = totalLength;\r
+  }\r
+  }\r
+  DirStartOffset = DirProcessed = pos;\r
+  RINOK(ParseDirItem(pos, parent));\r
+  if (DirProcessed == DirSize)\r
+    return S_OK;\r
+  /* Original program writes additional 8 bytes (END_OF_ROOT_FOLDER), but\r
+     reference to that folder is empty */\r
+  if (DirProcessed == DirSize - 8 && DirProcessed - DirStartOffset == 112 &&\r
+      Get64(p + DirSize - 8) == 0)\r
+    return S_OK;\r
+  return S_FALSE;\r
+}\r
+\r
+HRESULT CHeader::Parse(const Byte *p)\r
+{\r
+  UInt32 headerSize = Get32(p + 8);\r
+  Version = Get32(p + 0x0C);\r
+  Flags = Get32(p + 0x10);\r
+  if (!IsSupported())\r
+    return S_FALSE;\r
+  ChunkSize = Get32(p + 0x14);\r
+  if (ChunkSize != kChunkSize && ChunkSize != 0)\r
+    return S_FALSE;\r
+  int offset;\r
+  if (IsOldVersion())\r
+  {\r
+    if (headerSize != 0x60)\r
+      return S_FALSE;\r
+    memset(Guid, 0, 16);\r
+    offset = 0x18;\r
+    PartNumber = 1;\r
+    NumParts = 1;\r
+  }\r
+  else\r
+  {\r
+    if (headerSize < 0x74)\r
+      return S_FALSE;\r
+    memcpy(Guid, p + 0x18, 16);\r
+    PartNumber = Get16(p + 0x28);\r
+    NumParts = Get16(p + 0x2A);\r
+    offset = 0x2C;\r
+    if (IsNewVersion())\r
+    {\r
+      NumImages = Get32(p + offset);\r
+      offset += 4;\r
+    }\r
+  }\r
+  GetResource(p + offset, OffsetResource);\r
+  GetResource(p + offset + 0x18, XmlResource);\r
+  GetResource(p + offset + 0x30, MetadataResource);\r
+  if (IsNewVersion())\r
+  {\r
+    if (headerSize < 0xD0)\r
+      return S_FALSE;\r
+    BootIndex = Get32(p + 0x48);\r
+    IntegrityResource.Parse(p + offset + 0x4C);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+const Byte kSignature[kSignatureSize] = { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 };\r
+\r
+HRESULT ReadHeader(IInStream *inStream, CHeader &h)\r
+{\r
+  Byte p[kHeaderSizeMax];\r
+  RINOK(ReadStream_FALSE(inStream, p, kHeaderSizeMax));\r
+  if (memcmp(p, kSignature, kSignatureSize) != 0)\r
+    return S_FALSE;\r
+  return h.Parse(p);\r
+}\r
+\r
+static HRESULT ReadStreams(bool oldVersion, IInStream *inStream, const CHeader &h, CDatabase &db)\r
+{\r
+  CByteBuffer offsetBuf;\r
+  RINOK(UnpackData(inStream, h.OffsetResource, h.IsLzxMode(), offsetBuf, NULL));\r
+  size_t i;\r
+  size_t streamInfoSize = oldVersion ? kStreamInfoSize + 2 : kStreamInfoSize;\r
+  for (i = 0; offsetBuf.GetCapacity() - i >= streamInfoSize; i += streamInfoSize)\r
+  {\r
+    CStreamInfo s;\r
+    GetStream(oldVersion, (const Byte *)offsetBuf + i, s);\r
+    if (s.PartNumber == h.PartNumber)\r
+      db.Streams.Add(s);\r
+  }\r
+  return (i == offsetBuf.GetCapacity()) ? S_OK : S_FALSE;\r
+}\r
+\r
+static bool IsEmptySha(const Byte *data)\r
+{\r
+  for (int i = 0; i < kHashSize; i++)\r
+    if (data[i] != 0)\r
+      return false;\r
+  return true;\r
+}\r
+\r
+HRESULT CDatabase::Open(IInStream *inStream, const CHeader &h, CByteBuffer &xml, IArchiveOpenCallback *openCallback)\r
+{\r
+  OpenCallback = openCallback;\r
+  IsOldVersion = h.IsOldVersion();\r
+  RINOK(UnpackData(inStream, h.XmlResource, h.IsLzxMode(), xml, NULL));\r
+  RINOK(ReadStreams(h.IsOldVersion(), inStream, h, *this));\r
+  bool needBootMetadata = !h.MetadataResource.IsEmpty();\r
+  Order = 0;\r
+  if (h.PartNumber == 1)\r
+  {\r
+    int imageIndex = 1;\r
+    for (int i = 0; i < Streams.Size(); i++)\r
+    {\r
+      // if (imageIndex > 1) break;\r
+      const CStreamInfo &si = Streams[i];\r
+      if (!si.Resource.IsMetadata() || si.PartNumber != h.PartNumber)\r
+        continue;\r
+      Byte hash[kHashSize];\r
+      CByteBuffer metadata;\r
+      RINOK(UnpackData(inStream, si.Resource, h.IsLzxMode(), metadata, hash));\r
+      if (memcmp(hash, si.Hash, kHashSize) != 0 &&\r
+          !(h.IsOldVersion() && IsEmptySha(si.Hash)))\r
+        return S_FALSE;\r
+      NumImages++;\r
+      RINOK(ParseImageDirs(metadata, -(int)(++imageIndex)));\r
+      if (needBootMetadata)\r
+        if (h.MetadataResource.Offset == si.Resource.Offset)\r
+          needBootMetadata = false;\r
+    }\r
+  }\r
+  \r
+  if (needBootMetadata)\r
+  {\r
+    CByteBuffer metadata;\r
+    RINOK(UnpackData(inStream, h.MetadataResource, h.IsLzxMode(), metadata, NULL));\r
+    RINOK(ParseImageDirs(metadata, -1));\r
+    NumImages++;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+\r
+static int CompareStreamsByPos(const CStreamInfo *p1, const CStreamInfo *p2, void * /* param */)\r
+{\r
+  int res = MyCompare(p1->PartNumber, p2->PartNumber);\r
+  if (res != 0)\r
+    return res;\r
+  return MyCompare(p1->Resource.Offset, p2->Resource.Offset);\r
+}\r
+\r
+static int CompareIDs(const int *p1, const int *p2, void *param)\r
+{\r
+  const CRecordVector<CStreamInfo> &streams = *(const CRecordVector<CStreamInfo> *)param;\r
+  return MyCompare(streams[*p1].Id, streams[*p2].Id);\r
+}\r
+\r
+static int CompareHashRefs(const int *p1, const int *p2, void *param)\r
+{\r
+  const CRecordVector<CStreamInfo> &streams = *(const CRecordVector<CStreamInfo> *)param;\r
+  return memcmp(streams[*p1].Hash, streams[*p2].Hash, kHashSize);\r
+}\r
+\r
+static int FindId(const CRecordVector<CStreamInfo> &streams,\r
+    const CIntVector &sortedByHash, UInt32 id)\r
+{\r
+  int left = 0, right = streams.Size();\r
+  while (left != right)\r
+  {\r
+    int mid = (left + right) / 2;\r
+    int streamIndex = sortedByHash[mid];\r
+    UInt32 id2 = streams[streamIndex].Id;\r
+    if (id == id2)\r
+      return streamIndex;\r
+    if (id < id2)\r
+      right = mid;\r
+    else\r
+      left = mid + 1;\r
+  }\r
+  return -1;\r
+}\r
+\r
+static int FindHash(const CRecordVector<CStreamInfo> &streams,\r
+    const CIntVector &sortedByHash, const Byte *hash)\r
+{\r
+  int left = 0, right = streams.Size();\r
+  while (left != right)\r
+  {\r
+    int mid = (left + right) / 2;\r
+    int streamIndex = sortedByHash[mid];\r
+    UInt32 i;\r
+    const Byte *hash2 = streams[streamIndex].Hash;\r
+    for (i = 0; i < kHashSize; i++)\r
+      if (hash[i] != hash2[i])\r
+        break;\r
+    if (i == kHashSize)\r
+      return streamIndex;\r
+    if (hash[i] < hash2[i])\r
+      right = mid;\r
+    else\r
+      left = mid + 1;\r
+  }\r
+  return -1;\r
+}\r
+\r
+static int CompareItems(const int *a1, const int *a2, void *param)\r
+{\r
+  const CObjectVector<CItem> &items = ((CDatabase *)param)->Items;\r
+  const CItem &i1 = items[*a1];\r
+  const CItem &i2 = items[*a2];\r
+\r
+  if (i1.IsDir() != i2.IsDir())\r
+    return i1.IsDir() ? 1 : -1;\r
+  int res = MyCompare(i1.StreamIndex, i2.StreamIndex);\r
+  if (res != 0)\r
+    return res;\r
+  return MyCompare(i1.Order, i2.Order);\r
+}\r
+\r
+HRESULT CDatabase::Sort(bool skipRootDir)\r
+{\r
+  Streams.Sort(CompareStreamsByPos, NULL);\r
+\r
+  {\r
+    CIntVector sortedByHash;\r
+    {\r
+      for (int i = 0; i < Streams.Size(); i++)\r
+        sortedByHash.Add(i);\r
+      if (IsOldVersion)\r
+        sortedByHash.Sort(CompareIDs, &Streams);\r
+      else\r
+        sortedByHash.Sort(CompareHashRefs, &Streams);\r
+    }\r
+    \r
+    for (int i = 0; i < Items.Size(); i++)\r
+    {\r
+      CItem &item = Items[i];\r
+      item.StreamIndex = -1;\r
+      if (item.HasStream())\r
+        if (IsOldVersion)\r
+          item.StreamIndex = FindId(Streams, sortedByHash, item.Id);\r
+        else\r
+          item.StreamIndex = FindHash(Streams, sortedByHash, item.Hash);\r
+    }\r
+  }\r
+\r
+  {\r
+    CRecordVector<bool> used;\r
+    int i;\r
+    for (i = 0; i < Streams.Size(); i++)\r
+    {\r
+      const CStreamInfo &s = Streams[i];\r
+      used.Add(s.Resource.IsMetadata() && s.PartNumber == 1);\r
+      // used.Add(false);\r
+    }\r
+    for (i = 0; i < Items.Size(); i++)\r
+    {\r
+      CItem &item = Items[i];\r
+      if (item.StreamIndex >= 0)\r
+        used[item.StreamIndex] = true;\r
+    }\r
+    for (i = 0; i < Streams.Size(); i++)\r
+      if (!used[i])\r
+      {\r
+        CItem item;\r
+        item.StreamIndex = i;\r
+        item.HasMetadata = false;\r
+        Items.Add(item);\r
+      }\r
+  }\r
+\r
+  SortedItems.Reserve(Items.Size());\r
+  for (int i = (skipRootDir ? 1 : 0); i < Items.Size(); i++)\r
+    SortedItems.Add(i);\r
+  SortedItems.Sort(CompareItems, this);\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Wim/WimIn.h b/CPP/7zip/Archive/Wim/WimIn.h
new file mode 100755 (executable)
index 0000000..0d9be3e
--- /dev/null
@@ -0,0 +1,297 @@
+// Archive/WimIn.h\r
+\r
+#ifndef __ARCHIVE_WIM_IN_H\r
+#define __ARCHIVE_WIM_IN_H\r
+\r
+#include "Common/Buffer.h"\r
+#include "Common/MyString.h"\r
+\r
+#include "../../Compress/CopyCoder.h"\r
+#include "../../Compress/LzxDecoder.h"\r
+\r
+#include "../IArchive.h"\r
+\r
+namespace NArchive {\r
+namespace NWim {\r
+\r
+namespace NXpress {\r
+\r
+class CBitStream\r
+{\r
+  CInBuffer m_Stream;\r
+  UInt32 m_Value;\r
+  unsigned m_BitPos;\r
+public:\r
+  bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }\r
+  void SetStream(ISequentialInStream *s) { m_Stream.SetStream(s); }\r
+  void ReleaseStream() { m_Stream.ReleaseStream(); }\r
+\r
+  void Init() { m_Stream.Init(); m_BitPos = 0; }\r
+  // UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() - m_BitPos / 8; }\r
+  Byte DirectReadByte() { return m_Stream.ReadByte(); }\r
+\r
+  void Normalize()\r
+  {\r
+    if (m_BitPos < 16)\r
+    {\r
+      Byte b0 = m_Stream.ReadByte();\r
+      Byte b1 = m_Stream.ReadByte();\r
+      m_Value = (m_Value << 8) | b1;\r
+      m_Value = (m_Value << 8) | b0;\r
+      m_BitPos += 16;\r
+    }\r
+  }\r
+\r
+  UInt32 GetValue(unsigned numBits)\r
+  {\r
+    Normalize();\r
+    return (m_Value >> (m_BitPos - numBits)) & ((1 << numBits) - 1);\r
+  }\r
+  \r
+  void MovePos(unsigned numBits) { m_BitPos -= numBits; }\r
+  \r
+  UInt32 ReadBits(unsigned numBits)\r
+  {\r
+    UInt32 res = GetValue(numBits);\r
+    m_BitPos -= numBits;\r
+    return res;\r
+  }\r
+};\r
+\r
+const unsigned kNumHuffmanBits = 16;\r
+const UInt32 kMatchMinLen = 3;\r
+const UInt32 kNumLenSlots = 16;\r
+const UInt32 kNumPosSlots = 16;\r
+const UInt32 kNumPosLenSlots = kNumPosSlots * kNumLenSlots;\r
+const UInt32 kMainTableSize = 256 + kNumPosLenSlots;\r
+\r
+class CDecoder\r
+{\r
+  CBitStream m_InBitStream;\r
+  CLzOutWindow m_OutWindowStream;\r
+  NCompress::NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder;\r
+\r
+  HRESULT CodeSpec(UInt32 size);\r
+  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt32 outSize);\r
+public:\r
+  void ReleaseStreams()\r
+  {\r
+    m_OutWindowStream.ReleaseStream();\r
+    m_InBitStream.ReleaseStream();\r
+  }\r
+  HRESULT Flush() { return m_OutWindowStream.Flush(); }\r
+  HRESULT Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt32 outSize);\r
+};\r
+\r
+}\r
+\r
+namespace NResourceFlags\r
+{\r
+  const Byte kFree = 1;\r
+  const Byte kMetadata = 2;\r
+  const Byte Compressed = 4;\r
+  const Byte Spanned = 4;\r
+}\r
+\r
+struct CResource\r
+{\r
+  UInt64 PackSize;\r
+  UInt64 Offset;\r
+  UInt64 UnpackSize;\r
+  Byte Flags;\r
+\r
+  void Clear()\r
+  {\r
+    PackSize = 0;\r
+    Offset = 0;\r
+    UnpackSize = 0;\r
+    Flags = 0;\r
+  }\r
+  void Parse(const Byte *p);\r
+  void WriteTo(Byte *p) const;\r
+  bool IsFree() const { return (Flags & NResourceFlags::kFree) != 0; }\r
+  bool IsMetadata() const { return (Flags & NResourceFlags::kMetadata) != 0; }\r
+  bool IsCompressed() const { return (Flags & NResourceFlags::Compressed) != 0; }\r
+  bool IsEmpty() const { return (UnpackSize == 0); }\r
+};\r
+\r
+namespace NHeaderFlags\r
+{\r
+  const UInt32 kCompression = 2;\r
+  const UInt32 kSpanned = 8;\r
+  const UInt32 kRpFix = 0x80;\r
+  const UInt32 kXPRESS = 0x20000;\r
+  const UInt32 kLZX = 0x40000;\r
+}\r
+\r
+const UInt32 kWimVersion = 0x010D00;\r
+const UInt32 kHeaderSizeMax = 0xD0;\r
+const UInt32 kSignatureSize = 8;\r
+extern const Byte kSignature[kSignatureSize];\r
+const unsigned kChunkSizeBits = 15;\r
+const UInt32 kChunkSize = (1 << kChunkSizeBits);\r
+\r
+struct CHeader\r
+{\r
+  UInt32 Version;\r
+  UInt32 Flags;\r
+  UInt32 ChunkSize;\r
+  Byte Guid[16];\r
+  UInt16 PartNumber;\r
+  UInt16 NumParts;\r
+  UInt32 NumImages;\r
+  \r
+  CResource OffsetResource;\r
+  CResource XmlResource;\r
+  CResource MetadataResource;\r
+  CResource IntegrityResource;\r
+  UInt32 BootIndex;\r
+\r
+  void SetDefaultFields(bool useLZX);\r
+\r
+  void WriteTo(Byte *p) const;\r
+  HRESULT Parse(const Byte *p);\r
+  bool IsCompressed() const { return (Flags & NHeaderFlags::kCompression) != 0; }\r
+  bool IsSupported() const { return (!IsCompressed() || (Flags & NHeaderFlags::kLZX) != 0 || (Flags & NHeaderFlags::kXPRESS) != 0 ) ; }\r
+  bool IsLzxMode() const { return (Flags & NHeaderFlags::kLZX) != 0; }\r
+  bool IsSpanned() const { return (!IsCompressed() || (Flags & NHeaderFlags::kSpanned) != 0); }\r
+  bool IsOldVersion() const { return (Version <= 0x010A00); }\r
+  bool IsNewVersion() const { return (Version > 0x010C00); }\r
+\r
+  bool AreFromOnArchive(const CHeader &h)\r
+  {\r
+    return (memcmp(Guid, h.Guid, sizeof(Guid)) == 0) && (h.NumParts == NumParts);\r
+  }\r
+};\r
+\r
+const UInt32 kHashSize = 20;\r
+const UInt32 kStreamInfoSize = 24 + 2 + 4 + kHashSize;\r
+\r
+struct CStreamInfo\r
+{\r
+  CResource Resource;\r
+  UInt16 PartNumber;\r
+  UInt32 RefCount;\r
+  UInt32 Id;\r
+  BYTE Hash[kHashSize];\r
+\r
+  void WriteTo(Byte *p) const;\r
+};\r
+\r
+const UInt32 kDirRecordSizeOld = 62;\r
+const UInt32 kDirRecordSize = 102;\r
+\r
+struct CItem\r
+{\r
+  UString Name;\r
+  UString ShortName;\r
+  UInt32 Attrib;\r
+  // UInt32 SecurityId;\r
+  BYTE Hash[kHashSize];\r
+  UInt32 Id;\r
+  FILETIME CTime;\r
+  FILETIME ATime;\r
+  FILETIME MTime;\r
+  // UInt32 ReparseTag;\r
+  // UInt64 HardLink;\r
+  // UInt16 NumStreams;\r
+  int StreamIndex;\r
+  int Parent;\r
+  unsigned Order;\r
+  bool HasMetadata;\r
+  CItem(): HasMetadata(true), StreamIndex(-1), Id(0) {}\r
+  bool IsDir() const { return HasMetadata && ((Attrib & 0x10) != 0); }\r
+  bool HasStream() const\r
+  {\r
+    for (unsigned i = 0; i < kHashSize; i++)\r
+      if (Hash[i] != 0)\r
+        return true;\r
+    return Id != 0;\r
+  }\r
+};\r
+\r
+class CDatabase\r
+{\r
+  const Byte *DirData;\r
+  size_t DirSize;\r
+  size_t DirProcessed;\r
+  size_t DirStartOffset;\r
+  int Order;\r
+  IArchiveOpenCallback *OpenCallback;\r
+  \r
+  HRESULT ParseDirItem(size_t pos, int parent);\r
+  HRESULT ParseImageDirs(const CByteBuffer &buf, int parent);\r
+\r
+public:\r
+  CRecordVector<CStreamInfo> Streams;\r
+  CObjectVector<CItem> Items;\r
+  CIntVector SortedItems;\r
+  int NumImages;\r
+  bool SkipRoot;\r
+  bool ShowImageNumber;\r
+\r
+  bool IsOldVersion;\r
+\r
+  UInt64 GetUnpackSize() const\r
+  {\r
+    UInt64 res = 0;\r
+    for (int i = 0; i < Streams.Size(); i++)\r
+      res += Streams[i].Resource.UnpackSize;\r
+    return res;\r
+  }\r
+\r
+  UInt64 GetPackSize() const\r
+  {\r
+    UInt64 res = 0;\r
+    for (int i = 0; i < Streams.Size(); i++)\r
+      res += Streams[i].Resource.PackSize;\r
+    return res;\r
+  }\r
+\r
+  void Clear()\r
+  {\r
+    Streams.Clear();\r
+    Items.Clear();\r
+    SortedItems.Clear();\r
+    NumImages = 0;\r
+\r
+    SkipRoot = true;\r
+    ShowImageNumber = true;\r
+    IsOldVersion = false;\r
+  }\r
+\r
+  UString GetItemPath(int index) const;\r
+\r
+  HRESULT Open(IInStream *inStream, const CHeader &h, CByteBuffer &xml, IArchiveOpenCallback *openCallback);\r
+\r
+  void DetectPathMode()\r
+  {\r
+    ShowImageNumber = (NumImages != 1);\r
+  }\r
+\r
+  HRESULT Sort(bool skipRootDir);\r
+};\r
+\r
+HRESULT ReadHeader(IInStream *inStream, CHeader &header);\r
+\r
+class CUnpacker\r
+{\r
+  NCompress::CCopyCoder *copyCoderSpec;\r
+  CMyComPtr<ICompressCoder> copyCoder;\r
+\r
+  NCompress::NLzx::CDecoder *lzxDecoderSpec;\r
+  CMyComPtr<ICompressCoder> lzxDecoder;\r
+\r
+  NXpress::CDecoder xpressDecoder;\r
+\r
+  CByteBuffer sizesBuf;\r
+  HRESULT Unpack(IInStream *inStream, const CResource &res, bool lzxMode,\r
+      ISequentialOutStream *outStream, ICompressProgressInfo *progress);\r
+public:\r
+  HRESULT Unpack(IInStream *inStream, const CResource &res, bool lzxMode,\r
+      ISequentialOutStream *outStream, ICompressProgressInfo *progress, Byte *digest);\r
+};\r
+\r
+}}\r
+  \r
+#endif\r
diff --git a/CPP/7zip/Archive/Wim/WimRegister.cpp b/CPP/7zip/Archive/Wim/WimRegister.cpp
new file mode 100755 (executable)
index 0000000..e91ac53
--- /dev/null
@@ -0,0 +1,18 @@
+// WimRegister.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/RegisterArc.h"\r
+\r
+#include "WimHandler.h"\r
+static IInArchive *CreateArc() { return new NArchive::NWim::CHandler; }\r
+#ifndef EXTRACT_ONLY\r
+static IOutArchive *CreateArcOut() { return new NArchive::NWim::COutHandler; }\r
+#else\r
+#define CreateArcOut 0\r
+#endif\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"wim", L"wim swm", 0, 0xE6, { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 }, 8, false, CreateArc, CreateArcOut };\r
+\r
+REGISTER_ARC(Wim)\r
diff --git a/CPP/7zip/Archive/XarHandler.cpp b/CPP/7zip/Archive/XarHandler.cpp
new file mode 100755 (executable)
index 0000000..b2d67d8
--- /dev/null
@@ -0,0 +1,588 @@
+// XarHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/MyXml.h"\r
+#include "Common/StringToInt.h"\r
+#include "Common/UTFConvert.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../Common/LimitedStreams.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamObjects.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/BZip2Decoder.h"\r
+#include "../Compress/CopyCoder.h"\r
+#include "../Compress/ZlibDecoder.h"\r
+\r
+#include "Common/OutStreamWithSha1.h"\r
+\r
+#define XAR_SHOW_RAW\r
+\r
+#define Get16(p) GetBe16(p)\r
+#define Get32(p) GetBe32(p)\r
+#define Get64(p) GetBe64(p)\r
+\r
+namespace NArchive {\r
+namespace NXar {\r
+\r
+struct CFile\r
+{\r
+  AString Name;\r
+  AString Method;\r
+  UInt64 Size;\r
+  UInt64 PackSize;\r
+  UInt64 Offset;\r
+  \r
+  // UInt32 mode;\r
+  UInt64 CTime;\r
+  UInt64 MTime;\r
+  UInt64 ATime;\r
+  \r
+  bool IsDir;\r
+  bool HasData;\r
+\r
+  bool Sha1IsDefined;\r
+  Byte Sha1[20];\r
+  // bool packSha1IsDefined;\r
+  // Byte packSha1[20];\r
+\r
+  int Parent;\r
+\r
+  CFile(): IsDir(false), HasData(false), Sha1IsDefined(false),\r
+    /* packSha1IsDefined(false), */\r
+    Parent(-1), Size(0), PackSize(0), CTime(0), MTime(0), ATime(0) {}\r
+};\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public CMyUnknownImp\r
+{\r
+  UInt64 _dataStartPos;\r
+  CMyComPtr<IInStream> _inStream;\r
+  AString _xml;\r
+  CObjectVector<CFile> _files;\r
+\r
+  HRESULT Open2(IInStream *stream);\r
+  HRESULT Extract(IInStream *stream);\r
+public:\r
+  MY_UNKNOWN_IMP1(IInArchive)\r
+  INTERFACE_IInArchive(;)\r
+};\r
+\r
+const UInt32 kXmlSizeMax = ((UInt32)1 << 30) - (1 << 14);\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidCTime, VT_FILETIME},\r
+  { NULL, kpidATime, VT_FILETIME},\r
+  { NULL, kpidMethod, VT_BSTR}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps_NO\r
+\r
+static bool ParseNumber(const char *s, int size, UInt32 &res)\r
+{\r
+  const char *end;\r
+  res = (UInt32)ConvertStringToUInt64(s, &end);\r
+  return (end - s == size);\r
+}\r
+\r
+static bool ParseUInt64(const CXmlItem &item, const char *name, UInt64 &res)\r
+{\r
+  AString s = item.GetSubStringForTag(name);\r
+  const char *end;\r
+  res = ConvertStringToUInt64(s, &end);\r
+  return (end - (const char *)s == s.Length());\r
+}\r
+\r
+static UInt64 ParseTime(const CXmlItem &item, const char *name)\r
+{\r
+  AString s = item.GetSubStringForTag(name);\r
+  if (s.Length() < 20)\r
+    return 0;\r
+  const char *p = s;\r
+  if (p[ 4] != '-' || p[ 7] != '-' || p[10] != 'T' ||\r
+      p[13] != ':' || p[16] != ':' || p[19] != 'Z')\r
+    return 0;\r
+  UInt32 year, month, day, hour, min, sec;\r
+  if (!ParseNumber(p,      4, year )) return 0;\r
+  if (!ParseNumber(p + 5,  2, month)) return 0;\r
+  if (!ParseNumber(p + 8,  2, day  )) return 0;\r
+  if (!ParseNumber(p + 11, 2, hour )) return 0;\r
+  if (!ParseNumber(p + 14, 2, min  )) return 0;\r
+  if (!ParseNumber(p + 17, 2, sec  )) return 0;\r
+  \r
+  UInt64 numSecs;\r
+  if (!NWindows::NTime::GetSecondsSince1601(year, month, day, hour, min, sec, numSecs))\r
+    return 0;\r
+  return numSecs * 10000000;\r
+}\r
+\r
+static bool HexToByte(char c, Byte &res)\r
+{\r
+  if      (c >= '0' && c <= '9') res = c - '0';\r
+  else if (c >= 'A' && c <= 'F') res = c - 'A' + 10;\r
+  else if (c >= 'a' && c <= 'f') res = c - 'a' + 10;\r
+  else return false;\r
+  return true;\r
+}\r
+\r
+#define METHOD_NAME_ZLIB "zlib"\r
+\r
+static bool ParseSha1(const CXmlItem &item, const char *name, Byte *digest)\r
+{\r
+  int index = item.FindSubTag(name);\r
+  if (index  < 0)\r
+    return false;\r
+  const CXmlItem &checkItem = item.SubItems[index];\r
+  AString style = checkItem.GetPropertyValue("style");\r
+  if (style == "SHA1")\r
+  {\r
+    AString s = checkItem.GetSubString();\r
+    if (s.Length() != 40)\r
+      return false;\r
+    for (int i = 0; i < s.Length(); i += 2)\r
+    {\r
+      Byte b0, b1;\r
+      if (!HexToByte(s[i], b0) || !HexToByte(s[i + 1], b1))\r
+        return false;\r
+      digest[i / 2] = (b0 << 4) | b1;\r
+    }\r
+    return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+static bool AddItem(const CXmlItem &item, CObjectVector<CFile> &files, int parent)\r
+{\r
+  if (!item.IsTag)\r
+    return true;\r
+  if (item.Name == "file")\r
+  {\r
+    CFile file;\r
+    file.Parent = parent;\r
+    parent = files.Size();\r
+    file.Name = item.GetSubStringForTag("name");\r
+    AString type = item.GetSubStringForTag("type");\r
+    if (type == "directory")\r
+      file.IsDir = true;\r
+    else if (type == "file")\r
+      file.IsDir = false;\r
+    else\r
+      return false;\r
+\r
+    int dataIndex = item.FindSubTag("data");\r
+    if (dataIndex >= 0 && !file.IsDir)\r
+    {\r
+      file.HasData = true;\r
+      const CXmlItem &dataItem = item.SubItems[dataIndex];\r
+      if (!ParseUInt64(dataItem, "size", file.Size))\r
+        return false;\r
+      if (!ParseUInt64(dataItem, "length", file.PackSize))\r
+        return false;\r
+      if (!ParseUInt64(dataItem, "offset", file.Offset))\r
+        return false;\r
+      file.Sha1IsDefined = ParseSha1(dataItem, "extracted-checksum", file.Sha1);\r
+      // file.packSha1IsDefined = ParseSha1(dataItem, "archived-checksum",  file.packSha1);\r
+      int encodingIndex = dataItem.FindSubTag("encoding");\r
+      if (encodingIndex >= 0)\r
+      {\r
+        const CXmlItem &encodingItem = dataItem.SubItems[encodingIndex];\r
+        if (encodingItem.IsTag)\r
+        {\r
+          AString s = encodingItem.GetPropertyValue("style");\r
+          if (s.Length() >= 0)\r
+          {\r
+            AString appl = "application/";\r
+            if (s.Left(appl.Length()) == appl)\r
+            {\r
+              s = s.Mid(appl.Length());\r
+              AString xx = "x-";\r
+              if (s.Left(xx.Length()) == xx)\r
+              {\r
+                s = s.Mid(xx.Length());\r
+                if (s == "gzip")\r
+                  s = METHOD_NAME_ZLIB;\r
+              }\r
+            }\r
+            file.Method = s;\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    file.CTime = ParseTime(item, "ctime");\r
+    file.MTime = ParseTime(item, "mtime");\r
+    file.ATime = ParseTime(item, "atime");\r
+    files.Add(file);\r
+  }\r
+  for (int i = 0; i < item.SubItems.Size(); i++)\r
+    if (!AddItem(item.SubItems[i], files, parent))\r
+      return false;\r
+  return true;\r
+}\r
+\r
+HRESULT CHandler::Open2(IInStream *stream)\r
+{\r
+  UInt64 archiveStartPos;\r
+  RINOK(stream->Seek(0, STREAM_SEEK_SET, &archiveStartPos));\r
+\r
+  const UInt32 kHeaderSize = 0x1C;\r
+  Byte buf[kHeaderSize];\r
+  RINOK(ReadStream_FALSE(stream, buf, kHeaderSize));\r
+\r
+  UInt32 size = Get16(buf + 4);\r
+  // UInt32 ver = Get16(buf + 6); // == 0\r
+  if (Get32(buf) != 0x78617221 || size != kHeaderSize)\r
+    return S_FALSE;\r
+\r
+  UInt64 packSize = Get64(buf + 8);\r
+  UInt64 unpackSize = Get64(buf + 0x10);\r
+  // UInt32 checkSumAlogo = Get32(buf + 0x18);\r
+\r
+  if (unpackSize >= kXmlSizeMax)\r
+    return S_FALSE;\r
+\r
+  _dataStartPos = archiveStartPos + kHeaderSize + packSize;\r
+\r
+  char *ss = _xml.GetBuffer((int)unpackSize + 1);\r
+\r
+  NCompress::NZlib::CDecoder *zlibCoderSpec = new NCompress::NZlib::CDecoder();\r
+  CMyComPtr<ICompressCoder> zlibCoder = zlibCoderSpec;\r
+\r
+  CLimitedSequentialInStream *inStreamLimSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> inStreamLim(inStreamLimSpec);\r
+  inStreamLimSpec->SetStream(stream);\r
+  inStreamLimSpec->Init(packSize);\r
+\r
+  CBufPtrSeqOutStream *outStreamLimSpec = new CBufPtrSeqOutStream;\r
+  CMyComPtr<ISequentialOutStream> outStreamLim(outStreamLimSpec);\r
+  outStreamLimSpec->Init((Byte *)ss, (size_t)unpackSize);\r
+\r
+  RINOK(zlibCoder->Code(inStreamLim, outStreamLim, NULL, NULL, NULL));\r
+\r
+  if (outStreamLimSpec->GetPos() != (size_t)unpackSize)\r
+    return S_FALSE;\r
+\r
+  ss[(size_t)unpackSize] = 0;\r
+  _xml.ReleaseBuffer();\r
+\r
+  CXml xml;\r
+  if (!xml.Parse(_xml))\r
+    return S_FALSE;\r
+  \r
+  if (!xml.Root.IsTagged("xar") || xml.Root.SubItems.Size() != 1)\r
+    return S_FALSE;\r
+  const CXmlItem &toc = xml.Root.SubItems[0];\r
+  if (!toc.IsTagged("toc"))\r
+    return S_FALSE;\r
+  if (!AddItem(toc, _files, -1))\r
+    return S_FALSE;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream,\r
+    const UInt64 * /* maxCheckStartPosition */,\r
+    IArchiveOpenCallback * /* openArchiveCallback */)\r
+{\r
+  COM_TRY_BEGIN\r
+  {\r
+    Close();\r
+    if (Open2(stream) != S_OK)\r
+      return S_FALSE;\r
+    _inStream = stream;\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _inStream.Release();\r
+  _files.Clear();\r
+  _xml.Empty();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _files.Size()\r
+    #ifdef XAR_SHOW_RAW\r
+    + 1\r
+    #endif\r
+  ;\r
+  return S_OK;\r
+}\r
+\r
+static void TimeToProp(UInt64 t, NWindows::NCOM::CPropVariant &prop)\r
+{\r
+  if (t != 0)\r
+  {\r
+    FILETIME ft;\r
+    ft.dwLowDateTime = (UInt32)(t);\r
+    ft.dwHighDateTime = (UInt32)(t >> 32);\r
+    prop = ft;\r
+  }\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  \r
+  #ifdef XAR_SHOW_RAW\r
+  if ((int)index == _files.Size())\r
+  {\r
+    switch(propID)\r
+    {\r
+      case kpidPath: prop = L"[TOC].xml"; break;\r
+      case kpidSize:\r
+      case kpidPackSize: prop = (UInt64)_xml.Length(); break;\r
+    }\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    const CFile &item = _files[index];\r
+    switch(propID)\r
+    {\r
+      case kpidMethod:\r
+      {\r
+        UString name;\r
+        if (!item.Method.IsEmpty() && ConvertUTF8ToUnicode(item.Method, name))\r
+          prop = name;\r
+        break;\r
+      }\r
+      case kpidPath:\r
+      {\r
+        AString path;\r
+        int cur = index;\r
+        do\r
+        {\r
+          const CFile &item = _files[cur];\r
+          AString s = item.Name;\r
+          if (s.IsEmpty())\r
+            s = "unknown";\r
+          if (path.IsEmpty())\r
+            path = s;\r
+          else\r
+            path = s + CHAR_PATH_SEPARATOR + path;\r
+          cur = item.Parent;\r
+        }\r
+        while (cur >= 0);\r
+\r
+        UString name;\r
+        if (ConvertUTF8ToUnicode(path, name))\r
+          prop = name;\r
+        break;\r
+      }\r
+      \r
+      case kpidIsDir:  prop = item.IsDir; break;\r
+      case kpidSize:      if (!item.IsDir) prop = item.Size; break;\r
+      case kpidPackSize:  if (!item.IsDir) prop = item.PackSize; break;\r
+      \r
+      case kpidMTime:  TimeToProp(item.MTime, prop); break;\r
+      case kpidCTime:  TimeToProp(item.CTime, prop); break;\r
+      case kpidATime:  TimeToProp(item.ATime, prop); break;\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = _files.Size();\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  UInt64 totalSize = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    int index = (int)(allFilesMode ? i : indices[i]);\r
+    #ifdef XAR_SHOW_RAW\r
+    if (index == _files.Size())\r
+      totalSize += _xml.Length();\r
+    else\r
+    #endif\r
+      totalSize += _files[index].Size;\r
+  }\r
+  extractCallback->SetTotal(totalSize);\r
+\r
+  UInt64 currentPackTotal = 0;\r
+  UInt64 currentUnpTotal = 0;\r
+  UInt64 currentPackSize = 0;\r
+  UInt64 currentUnpSize = 0;\r
+\r
+  const UInt32 kZeroBufSize = (1 << 14);\r
+  CByteBuffer zeroBuf;\r
+  zeroBuf.SetCapacity(kZeroBufSize);\r
+  memset(zeroBuf, 0, kZeroBufSize);\r
+  \r
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\r
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\r
+\r
+  NCompress::NZlib::CDecoder *zlibCoderSpec = new NCompress::NZlib::CDecoder();\r
+  CMyComPtr<ICompressCoder> zlibCoder = zlibCoderSpec;\r
+  \r
+  NCompress::NBZip2::CDecoder *bzip2CoderSpec = new NCompress::NBZip2::CDecoder();\r
+  CMyComPtr<ICompressCoder> bzip2Coder = bzip2CoderSpec;\r
+\r
+  NCompress::NDeflate::NDecoder::CCOMCoder *deflateCoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder();\r
+  CMyComPtr<ICompressCoder> deflateCoder = deflateCoderSpec;\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  CLimitedSequentialInStream *inStreamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> inStream(inStreamSpec);\r
+  inStreamSpec->SetStream(_inStream);\r
+\r
+  \r
+  CLimitedSequentialOutStream *outStreamLimSpec = new CLimitedSequentialOutStream;\r
+  CMyComPtr<ISequentialOutStream> outStream(outStreamLimSpec);\r
+\r
+  COutStreamWithSha1 *outStreamSha1Spec = new COutStreamWithSha1;\r
+  {\r
+    CMyComPtr<ISequentialOutStream> outStreamSha1(outStreamSha1Spec);\r
+    outStreamLimSpec->SetStream(outStreamSha1);\r
+  }\r
+\r
+  for (i = 0; i < numItems; i++, currentPackTotal += currentPackSize, currentUnpTotal += currentUnpSize)\r
+  {\r
+    lps->InSize = currentPackTotal;\r
+    lps->OutSize = currentUnpTotal;\r
+    currentPackSize = 0;\r
+    currentUnpSize = 0;\r
+    RINOK(lps->SetCur());\r
+    CMyComPtr<ISequentialOutStream> realOutStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    Int32 index = allFilesMode ? i : indices[i];\r
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+    \r
+    if (index < _files.Size())\r
+    {\r
+      const CFile &item = _files[index];\r
+      if (item.IsDir)\r
+      {\r
+        RINOK(extractCallback->PrepareOperation(askMode));\r
+        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+        continue;\r
+      }\r
+    }\r
+\r
+    if (!testMode && !realOutStream)\r
+      continue;\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+\r
+    outStreamSha1Spec->SetStream(realOutStream);\r
+    realOutStream.Release();\r
+\r
+    Int32 opRes = NExtract::NOperationResult::kOK;\r
+    #ifdef XAR_SHOW_RAW\r
+    if (index == _files.Size())\r
+    {\r
+      outStreamSha1Spec->Init(false);\r
+      outStreamLimSpec->Init(_xml.Length());\r
+      RINOK(WriteStream(outStream, (const char *)_xml, _xml.Length()));\r
+      currentPackSize = currentUnpSize = _xml.Length();\r
+    }\r
+    else\r
+    #endif\r
+    {\r
+      const CFile &item = _files[index];\r
+      if (item.HasData)\r
+      {\r
+        currentPackSize = item.PackSize;\r
+        currentUnpSize = item.Size;\r
+        \r
+        RINOK(_inStream->Seek(_dataStartPos + item.Offset, STREAM_SEEK_SET, NULL));\r
+        inStreamSpec->Init(item.PackSize);\r
+        outStreamSha1Spec->Init(item.Sha1IsDefined);\r
+        outStreamLimSpec->Init(item.Size);\r
+        HRESULT res = S_OK;\r
+        \r
+        ICompressCoder *coder = NULL;\r
+        if (item.Method.IsEmpty() || item.Method == "octet-stream")\r
+          if (item.PackSize == item.Size)\r
+            coder = copyCoder;\r
+          else\r
+            opRes = NExtract::NOperationResult::kUnSupportedMethod;\r
+        else if (item.Method == METHOD_NAME_ZLIB)\r
+          coder = zlibCoder;\r
+        else if (item.Method == "bzip2")\r
+          coder = bzip2Coder;\r
+        else\r
+          opRes = NExtract::NOperationResult::kUnSupportedMethod;\r
+        \r
+        if (coder)\r
+          res = coder->Code(inStream, outStream, NULL, NULL, progress);\r
+        \r
+        if (res != S_OK)\r
+        {\r
+          if (!outStreamLimSpec->IsFinishedOK())\r
+            opRes = NExtract::NOperationResult::kDataError;\r
+          else if (res != S_FALSE)\r
+            return res;\r
+          if (opRes == NExtract::NOperationResult::kOK)\r
+            opRes = NExtract::NOperationResult::kDataError;\r
+        }\r
+\r
+        if (opRes == NExtract::NOperationResult::kOK)\r
+        {\r
+          if (outStreamLimSpec->IsFinishedOK() &&\r
+              outStreamSha1Spec->GetSize() == item.Size)\r
+          {\r
+            if (!outStreamLimSpec->IsFinishedOK())\r
+            {\r
+              opRes = NExtract::NOperationResult::kDataError;\r
+            }\r
+            else if (item.Sha1IsDefined)\r
+            {\r
+              Byte digest[NCrypto::NSha1::kDigestSize];\r
+              outStreamSha1Spec->Final(digest);\r
+              if (memcmp(digest, item.Sha1, NCrypto::NSha1::kDigestSize) != 0)\r
+                opRes = NExtract::NOperationResult::kCRCError;\r
+            }\r
+          }\r
+          else\r
+            opRes = NExtract::NOperationResult::kDataError;\r
+        }\r
+      }\r
+    }\r
+    outStreamSha1Spec->ReleaseStream();\r
+    RINOK(extractCallback->SetOperationResult(opRes));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new NArchive::NXar::CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"Xar", L"xar", 0, 0xE1, { 'x', 'a', 'r', '!', 0, 0x1C }, 6, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Xar)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp
new file mode 100755 (executable)
index 0000000..e4029e0
--- /dev/null
@@ -0,0 +1,707 @@
+// XzHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+#include "../../../C/XzCrc64.h"\r
+#include "../../../C/XzEnc.h"\r
+\r
+#include "../../Common/ComTry.h"\r
+#include "../../Common/IntToString.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "../Common/CWrappers.h"\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/CopyCoder.h"\r
+\r
+#include "IArchive.h"\r
+\r
+#include "Common/HandlerOut.h"\r
+\r
+using namespace NWindows;\r
+\r
+namespace NCompress {\r
+namespace NLzma2 {\r
+\r
+HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props);\r
+\r
+}}\r
+\r
+static void *SzAlloc(void *, size_t size) { return MyAlloc(size); }\r
+static void SzFree(void *, void *address) { MyFree(address); }\r
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };\r
+\r
+namespace NArchive {\r
+namespace NXz {\r
+\r
+struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit;\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IArchiveOpenSeq,\r
+  #ifndef EXTRACT_ONLY\r
+  public IOutArchive,\r
+  public ISetProperties,\r
+  public COutHandler,\r
+  #endif\r
+  public CMyUnknownImp\r
+{\r
+  Int64 _startPosition;\r
+  UInt64 _packSize;\r
+  UInt64 _unpackSize;\r
+  UInt64 _numBlocks;\r
+  AString _methodsString;\r
+  bool _useSeq;\r
+  UInt64 _unpackSizeDefined;\r
+  UInt64 _packSizeDefined;\r
+  \r
+  CMyComPtr<IInStream> _stream;\r
+  CMyComPtr<ISequentialInStream> _seqStream;\r
+\r
+  UInt32 _crcSize;\r
+\r
+  void Init()\r
+  {\r
+    _crcSize = 4;\r
+    COutHandler::Init();\r
+  }\r
+\r
+  HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *callback);\r
+\r
+public:\r
+  MY_QUERYINTERFACE_BEGIN2(IInArchive)\r
+  MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq)\r
+  #ifndef EXTRACT_ONLY\r
+  MY_QUERYINTERFACE_ENTRY(IOutArchive)\r
+  MY_QUERYINTERFACE_ENTRY(ISetProperties)\r
+  #endif\r
+  MY_QUERYINTERFACE_END\r
+  MY_ADDREF_RELEASE\r
+\r
+  INTERFACE_IInArchive(;)\r
+  STDMETHOD(OpenSeq)(ISequentialInStream *stream);\r
+\r
+  #ifndef EXTRACT_ONLY\r
+  INTERFACE_IOutArchive(;)\r
+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);\r
+  #endif\r
+\r
+  CHandler();\r
+};\r
+\r
+CHandler::CHandler()\r
+{\r
+  Init();\r
+}\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidMethod, VT_BSTR}\r
+};\r
+\r
+STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidMethod, VT_BSTR},\r
+  { NULL, kpidNumBlocks, VT_UI4}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+static char GetHex(Byte value)\r
+{\r
+  return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));\r
+}\r
+\r
+static inline void AddHexToString(AString &res, Byte value)\r
+{\r
+  res += GetHex((Byte)(value >> 4));\r
+  res += GetHex((Byte)(value & 0xF));\r
+}\r
+\r
+static AString ConvertUInt32ToString(UInt32 value)\r
+{\r
+  char temp[32];\r
+  ::ConvertUInt32ToString(value, temp);\r
+  return temp;\r
+}\r
+\r
+static AString Lzma2PropToString(int prop)\r
+{\r
+  if ((prop & 1) == 0)\r
+    return ConvertUInt32ToString(prop / 2 + 12);\r
+  AString res;\r
+  char c;\r
+\r
+  UInt32 size = (2 | ((prop) & 1)) << ((prop) / 2 + 1);\r
+\r
+  if (prop > 17)\r
+  {\r
+    res = ConvertUInt32ToString(size >> 10);\r
+    c = 'm';\r
+  }\r
+  else\r
+  {\r
+    res = ConvertUInt32ToString(size);\r
+    c = 'k';\r
+  }\r
+  return res + c;\r
+}\r
+\r
+struct CMethodNamePair\r
+{\r
+  UInt32 Id;\r
+  const char *Name;\r
+};\r
+\r
+static CMethodNamePair g_NamePairs[] =\r
+{\r
+  { XZ_ID_Subblock, "SB" },\r
+  { XZ_ID_Delta, "Delta" },\r
+  { XZ_ID_X86, "x86" },\r
+  { XZ_ID_PPC, "PPC" },\r
+  { XZ_ID_IA64, "IA64" },\r
+  { XZ_ID_ARM, "ARM" },\r
+  { XZ_ID_ARMT, "ARMT" },\r
+  { XZ_ID_SPARC, "SPARC" },\r
+  { XZ_ID_LZMA2, "LZMA2" }\r
+};\r
+\r
+static AString GetMethodString(const CXzFilter &f)\r
+{\r
+  AString s;\r
+\r
+  for (int i = 0; i < sizeof(g_NamePairs) / sizeof(g_NamePairs[i]); i++)\r
+    if (g_NamePairs[i].Id == f.id)\r
+      s = g_NamePairs[i].Name;\r
+  if (s.IsEmpty())\r
+  {\r
+    char temp[32];\r
+    ::ConvertUInt64ToString(f.id, temp);\r
+    s = temp;\r
+  }\r
+\r
+  if (f.propsSize > 0)\r
+  {\r
+    s += ':';\r
+    if (f.id == XZ_ID_LZMA2 && f.propsSize == 1)\r
+      s += Lzma2PropToString(f.props[0]);\r
+    else if (f.id == XZ_ID_Delta && f.propsSize == 1)\r
+      s += ConvertUInt32ToString((UInt32)f.props[0] + 1);\r
+    else\r
+    {\r
+      s += '[';\r
+      for (UInt32 bi = 0; bi < f.propsSize; bi++)\r
+        AddHexToString(s, f.props[bi]);\r
+      s += ']';\r
+    }\r
+  }\r
+  return s;\r
+}\r
+\r
+static void AddString(AString &dest, const AString &src)\r
+{\r
+  if (!dest.IsEmpty())\r
+    dest += ' ';\r
+  dest += src;\r
+}\r
+\r
+static const char *kChecks[] =\r
+{\r
+  "NoCheck",\r
+  "CRC32",\r
+  NULL,\r
+  NULL,\r
+  "CRC64",\r
+  NULL,\r
+  NULL,\r
+  NULL,\r
+  NULL,\r
+  NULL,\r
+  "SHA256",\r
+  NULL,\r
+  NULL,\r
+  NULL,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
+static AString GetCheckString(const CXzs &xzs)\r
+{\r
+  size_t i;\r
+  UInt32 mask = 0;\r
+  for (i = 0; i < xzs.num; i++)\r
+    mask |= ((UInt32)1 << XzFlags_GetCheckType(xzs.streams[i].flags));\r
+  AString s;\r
+  for (i = 0; i <= XZ_CHECK_MASK; i++)\r
+    if (((mask >> i) & 1) != 0)\r
+    {\r
+      AString s2;\r
+      if (kChecks[i])\r
+        s2 = kChecks[i];\r
+      else\r
+        s2 = "Check-" + ConvertUInt32ToString((UInt32)i);\r
+      AddString(s, s2);\r
+    }\r
+  return s;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidNumBlocks: if (!_useSeq) prop = _numBlocks; break;\r
+    case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;\r
+    case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = 1;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID,  PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidSize: if (_unpackSizeDefined) prop = _unpackSize; break;\r
+    case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;\r
+    case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+\r
+struct COpenCallbackWrap\r
+{\r
+  ICompressProgress p;\r
+  IArchiveOpenCallback *OpenCallback;\r
+  HRESULT Res;\r
+  COpenCallbackWrap(IArchiveOpenCallback *progress);\r
+};\r
+\r
+static SRes OpenCallbackProgress(void *pp, UInt64 inSize, UInt64 /* outSize */)\r
+{\r
+  COpenCallbackWrap *p = (COpenCallbackWrap *)pp;\r
+  p->Res = p->OpenCallback->SetCompleted(NULL, &inSize);\r
+  return (SRes)p->Res;\r
+}\r
+\r
+COpenCallbackWrap::COpenCallbackWrap(IArchiveOpenCallback *callback)\r
+{\r
+  p.Progress = OpenCallbackProgress;\r
+  OpenCallback = callback;\r
+  Res = SZ_OK;\r
+}\r
+\r
+struct CXzsCPP\r
+{\r
+  CXzs p;\r
+  CXzsCPP() { Xzs_Construct(&p); }\r
+  ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); }\r
+};\r
+\r
+HRESULT CHandler::Open2(IInStream *inStream, IArchiveOpenCallback *callback)\r
+{\r
+  CSeekInStreamWrap inStreamImp(inStream);\r
+\r
+  CLookToRead lookStream;\r
+  LookToRead_CreateVTable(&lookStream, True);\r
+  lookStream.realStream = &inStreamImp.p;\r
+  LookToRead_Init(&lookStream);\r
+\r
+  COpenCallbackWrap openWrap(callback);\r
+  RINOK(inStream->Seek(0, STREAM_SEEK_END, &_packSize));\r
+  RINOK(callback->SetTotal(NULL, &_packSize));\r
+\r
+  CXzsCPP xzs;\r
+  SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.s, &_startPosition, &openWrap.p, &g_Alloc);\r
+  if (res == SZ_ERROR_NO_ARCHIVE && xzs.p.num > 0)\r
+    res = SZ_OK;\r
+  if (res == SZ_OK)\r
+  {\r
+    _packSize -= _startPosition;\r
+    _unpackSize = Xzs_GetUnpackSize(&xzs.p);\r
+    _unpackSizeDefined = _packSizeDefined = true;\r
+    _numBlocks = (UInt64)Xzs_GetNumBlocks(&xzs.p);\r
+\r
+    RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));\r
+    CXzStreamFlags st;\r
+    CSeqInStreamWrap inStreamWrap(inStream);\r
+    SRes res2 = Xz_ReadHeader(&st, &inStreamWrap.p);\r
+\r
+    if (res2 == SZ_OK)\r
+    {\r
+      CXzBlock block;\r
+      Bool isIndex;\r
+      UInt32 headerSizeRes;\r
+      res2 = XzBlock_ReadHeader(&block, &inStreamWrap.p, &isIndex, &headerSizeRes);\r
+      if (res2 == SZ_OK && !isIndex)\r
+      {\r
+        int numFilters = XzBlock_GetNumFilters(&block);\r
+        for (int i = 0; i < numFilters; i++)\r
+          AddString(_methodsString, GetMethodString(block.filters[i]));\r
+      }\r
+    }\r
+    AddString(_methodsString, GetCheckString(xzs.p));\r
+  }\r
+\r
+  if (res != SZ_OK || _startPosition != 0)\r
+  {\r
+    RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));\r
+    CXzStreamFlags st;\r
+    CSeqInStreamWrap inStreamWrap(inStream);\r
+    SRes res2 = Xz_ReadHeader(&st, &inStreamWrap.p);\r
+    if (res2 == SZ_OK)\r
+    {\r
+      res = res2;\r
+      _startPosition = 0;\r
+      _useSeq = True;\r
+      _unpackSizeDefined = _packSizeDefined = false;\r
+    }\r
+  }\r
+  if (res == SZ_ERROR_NO_ARCHIVE)\r
+    return S_FALSE;\r
+  RINOK(SResToHRESULT(res));\r
+  _stream = inStream;\r
+  _seqStream = inStream;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback)\r
+{\r
+  COM_TRY_BEGIN\r
+  try\r
+  {\r
+    Close();\r
+    return Open2(inStream, callback);\r
+  }\r
+  catch(...) { return S_FALSE; }\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)\r
+{\r
+  Close();\r
+  _seqStream = stream;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _numBlocks = 0;\r
+  _useSeq = true;\r
+  _unpackSizeDefined = _packSizeDefined = false;\r
+  _methodsString.Empty();\r
+  _stream.Release();\r
+  _seqStream.Release();\r
+  return S_OK;\r
+}\r
+\r
+class CSeekToSeqStream:\r
+  public IInStream,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  CMyComPtr<ISequentialInStream> Stream;\r
+  MY_UNKNOWN_IMP1(IInStream)\r
+\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);\r
+};\r
+\r
+STDMETHODIMP CSeekToSeqStream::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  return Stream->Read(data, size, processedSize);\r
+}\r
+\r
+STDMETHODIMP CSeekToSeqStream::Seek(Int64, UInt32, UInt64 *) { return E_NOTIMPL; }\r
+\r
+struct CXzUnpackerCPP\r
+{\r
+  Byte *InBuf;\r
+  Byte *OutBuf;\r
+  CXzUnpacker p;\r
+  CXzUnpackerCPP(): InBuf(0), OutBuf(0) {}\r
+  ~CXzUnpackerCPP()\r
+  {\r
+    XzUnpacker_Free(&p);\r
+    MyFree(InBuf);\r
+    MyFree(OutBuf);\r
+  }\r
+};\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))\r
+    return E_INVALIDARG;\r
+\r
+  extractCallback->SetTotal(_packSize);\r
+  UInt64 currentTotalPacked = 0;\r
+  RINOK(extractCallback->SetCompleted(&currentTotalPacked));\r
+  CMyComPtr<ISequentialOutStream> realOutStream;\r
+  Int32 askMode = testMode ?\r
+      NExtract::NAskMode::kTest :\r
+      NExtract::NAskMode::kExtract;\r
+  \r
+  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));\r
+  \r
+  if (!testMode && !realOutStream)\r
+    return S_OK;\r
+\r
+  extractCallback->PrepareOperation(askMode);\r
+\r
+  if (_stream)\r
+  {\r
+    RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));\r
+  }\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, true);\r
+\r
+  CCompressProgressWrap progressWrap(progress);\r
+\r
+  SRes res;\r
+\r
+  const UInt32 kInBufSize = 1 << 15;\r
+  const UInt32 kOutBufSize = 1 << 21;\r
+\r
+  UInt32 inPos = 0;\r
+  UInt32 inSize = 0;\r
+  UInt32 outPos = 0;\r
+  CXzUnpackerCPP xzu;\r
+  res = XzUnpacker_Create(&xzu.p, &g_Alloc);\r
+  if (res == SZ_OK)\r
+  {\r
+    xzu.InBuf = (Byte *)MyAlloc(kInBufSize);\r
+    xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize);\r
+    if (xzu.InBuf == 0 || xzu.OutBuf == 0)\r
+      res = SZ_ERROR_MEM;\r
+  }\r
+  if (res == SZ_OK)\r
+  for (;;)\r
+  {\r
+    if (inPos == inSize)\r
+    {\r
+      inPos = inSize = 0;\r
+      RINOK(_seqStream->Read(xzu.InBuf, kInBufSize, &inSize));\r
+    }\r
+\r
+    SizeT inLen = inSize - inPos;\r
+    SizeT outLen = kOutBufSize - outPos;\r
+    ECoderStatus status;\r
+    res = XzUnpacker_Code(&xzu.p,\r
+        xzu.OutBuf + outPos, &outLen,\r
+        xzu.InBuf + inPos, &inLen,\r
+        (inSize == 0 ? CODER_FINISH_END : CODER_FINISH_ANY), &status);\r
+\r
+    // printf("\n_inPos = %6d  inLen = %5d, outLen = %5d", inPos, inLen, outLen);\r
+\r
+    inPos += (UInt32)inLen;\r
+    outPos += (UInt32)outLen;\r
+    lps->InSize += inLen;\r
+    lps->OutSize += outLen;\r
+\r
+    bool finished = (((inLen == 0) && (outLen == 0)) || res != SZ_OK);\r
+\r
+    if (outPos == kOutBufSize || finished)\r
+    {\r
+      if (realOutStream && outPos > 0)\r
+      {\r
+        RINOK(WriteStream(realOutStream, xzu.OutBuf, outPos));\r
+      }\r
+      outPos = 0;\r
+    }\r
+    if (finished)\r
+    {\r
+      _packSize = lps->InSize;\r
+      _unpackSize = lps->OutSize;\r
+      _packSizeDefined = _unpackSizeDefined = true;\r
+      if (res == SZ_OK)\r
+      {\r
+        if (status == CODER_STATUS_NEEDS_MORE_INPUT)\r
+        {\r
+          if (XzUnpacker_IsStreamWasFinished(&xzu.p))\r
+            _packSize -= xzu.p.padSize;\r
+          else\r
+            res = SZ_ERROR_DATA;\r
+        }\r
+        else\r
+          res = SZ_ERROR_DATA;\r
+      }\r
+      break;\r
+    }\r
+    RINOK(lps->SetCur());\r
+  }\r
+\r
+  Int32 opRes;\r
+  switch(res)\r
+  {\r
+    case SZ_OK:\r
+      opRes = NExtract::NOperationResult::kOK; break;\r
+    case SZ_ERROR_UNSUPPORTED:\r
+      opRes = NExtract::NOperationResult::kUnSupportedMethod; break;\r
+    case SZ_ERROR_CRC:\r
+      opRes = NExtract::NOperationResult::kCRCError; break;\r
+    case SZ_ERROR_DATA:\r
+    case SZ_ERROR_ARCHIVE:\r
+    case SZ_ERROR_NO_ARCHIVE:\r
+      opRes = NExtract::NOperationResult::kDataError; break;\r
+    default:\r
+      return SResToHRESULT(res);\r
+  }\r
+  realOutStream.Release();\r
+  RINOK(extractCallback->SetOperationResult(opRes));\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+#ifndef EXTRACT_ONLY\r
+\r
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)\r
+{\r
+  *timeType = NFileTimeType::kUnix;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\r
+    IArchiveUpdateCallback *updateCallback)\r
+{\r
+  CSeqOutStreamWrap seqOutStream(outStream);\r
+  \r
+  if (numItems == 0)\r
+  {\r
+    SRes res = Xz_EncodeEmpty(&seqOutStream.p);\r
+    return SResToHRESULT(res);\r
+  }\r
+  \r
+  if (numItems != 1)\r
+    return E_INVALIDARG;\r
+\r
+  Int32 newData, newProps;\r
+  UInt32 indexInArchive;\r
+  if (!updateCallback)\r
+    return E_FAIL;\r
+  RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));\r
+\r
+  if (IntToBool(newProps))\r
+  {\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));\r
+      if (prop.vt != VT_EMPTY)\r
+        if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)\r
+          return E_INVALIDARG;\r
+    }\r
+  }\r
+\r
+  if (IntToBool(newData))\r
+  {\r
+    {\r
+      UInt64 size;\r
+      NCOM::CPropVariant prop;\r
+      RINOK(updateCallback->GetProperty(0, kpidSize, &prop));\r
+      if (prop.vt != VT_UI8)\r
+        return E_INVALIDARG;\r
+      size = prop.uhVal.QuadPart;\r
+      RINOK(updateCallback->SetTotal(size));\r
+    }\r
+\r
+    CLzma2EncProps lzma2Props;\r
+    Lzma2EncProps_Init(&lzma2Props);\r
+\r
+    lzma2Props.lzmaProps.level = _level;\r
+\r
+    CMyComPtr<ISequentialInStream> fileInStream;\r
+    RINOK(updateCallback->GetStream(0, &fileInStream));\r
+\r
+    CSeqInStreamWrap seqInStream(fileInStream);\r
+\r
+    for (int i = 0; i < _methods.Size(); i++)\r
+    {\r
+      COneMethodInfo &m = _methods[i];\r
+      SetCompressionMethod2(m\r
+      #ifndef _7ZIP_ST\r
+      , _numThreads\r
+      #endif\r
+      );\r
+      if (m.IsLzma())\r
+      {\r
+        for (int j = 0; j < m.Props.Size(); j++)\r
+        {\r
+          const CProp &prop = m.Props[j];\r
+          RINOK(NCompress::NLzma2::SetLzma2Prop(prop.Id, prop.Value, lzma2Props));\r
+        }\r
+      }\r
+    }\r
+\r
+    #ifndef _7ZIP_ST\r
+    lzma2Props.numTotalThreads = _numThreads;\r
+    #endif\r
+\r
+    CLocalProgress *lps = new CLocalProgress;\r
+    CMyComPtr<ICompressProgressInfo> progress = lps;\r
+    lps->Init(updateCallback, true);\r
+\r
+    CCompressProgressWrap progressWrap(progress);\r
+    SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &lzma2Props, False, &progressWrap.p);\r
+    if (res == SZ_OK)\r
+      return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);\r
+    return SResToHRESULT(res);\r
+  }\r
+  if (indexInArchive != 0)\r
+    return E_INVALIDARG;\r
+  if (_stream)\r
+    RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));\r
+  return NCompress::CopyStream(_stream, outStream, 0);\r
+}\r
+\r
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)\r
+{\r
+  COM_TRY_BEGIN\r
+  BeforeSetProperty();\r
+  for (int i = 0; i < numProps; i++)\r
+  {\r
+    RINOK(SetProperty(names[i], values[i]));\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+#endif\r
+\r
+static IInArchive *CreateArc() { return new NArchive::NXz::CHandler; }\r
+#ifndef EXTRACT_ONLY\r
+static IOutArchive *CreateArcOut() { return new NArchive::NXz::CHandler; }\r
+#else\r
+#define CreateArcOut 0\r
+#endif\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"xz", L"xz txz", L"* .tar", 0xC, {0xFD, '7' , 'z', 'X', 'Z', '\0'}, 6, true, CreateArc, CreateArcOut };\r
+\r
+REGISTER_ARC(xz)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/ZHandler.cpp b/CPP/7zip/Archive/ZHandler.cpp
new file mode 100755 (executable)
index 0000000..1307197
--- /dev/null
@@ -0,0 +1,161 @@
+// ZHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../Common/ProgressUtils.h"\r
+#include "../Common/RegisterArc.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "../Compress/ZDecoder.h"\r
+\r
+#include "Common/DummyOutStream.h"\r
+\r
+namespace NArchive {\r
+namespace NZ {\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<IInStream> _stream;\r
+  UInt64 _streamStartPosition;\r
+  UInt64 _packSize;\r
+  Byte _properties;\r
+public:\r
+  MY_UNKNOWN_IMP1(IInArchive)\r
+  INTERFACE_IInArchive(;)\r
+};\r
+\r
+STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPackSize, VT_UI8}\r
+};\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps_NO\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = 1;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID,  PROPVARIANT *value)\r
+{\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidPackSize: prop = _packSize; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+static const int kSignatureSize = 3;\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *stream,\r
+    const UInt64 * /* maxCheckStartPosition */,\r
+    IArchiveOpenCallback * /* openArchiveCallback */)\r
+{\r
+  COM_TRY_BEGIN\r
+  {\r
+    RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_streamStartPosition));\r
+    Byte buffer[kSignatureSize];\r
+    RINOK(ReadStream_FALSE(stream, buffer, kSignatureSize));\r
+    if (buffer[0] != 0x1F || buffer[1] != 0x9D)\r
+      return S_FALSE;\r
+    _properties = buffer[2];\r
+\r
+    UInt64 endPosition;\r
+    RINOK(stream->Seek(0, STREAM_SEEK_END, &endPosition));\r
+    _packSize = endPosition - _streamStartPosition - kSignatureSize;\r
+    \r
+    _stream = stream;\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  _stream.Release();\r
+  return S_OK;\r
+}\r
+\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))\r
+    return E_INVALIDARG;\r
+\r
+  extractCallback->SetTotal(_packSize);\r
+\r
+  UInt64 currentTotalPacked = 0;\r
+  \r
+  RINOK(extractCallback->SetCompleted(&currentTotalPacked));\r
+  \r
+  CMyComPtr<ISequentialOutStream> realOutStream;\r
+  Int32 askMode = testMode ?\r
+      NExtract::NAskMode::kTest :\r
+      NExtract::NAskMode::kExtract;\r
+  \r
+  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));\r
+    \r
+  if (!testMode && !realOutStream)\r
+    return S_OK;\r
+\r
+  extractCallback->PrepareOperation(askMode);\r
+\r
+  CDummyOutStream *outStreamSpec = new CDummyOutStream;\r
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\r
+  outStreamSpec->SetStream(realOutStream);\r
+  outStreamSpec->Init();\r
+  realOutStream.Release();\r
+\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, true);\r
+  \r
+  RINOK(_stream->Seek(_streamStartPosition + kSignatureSize, STREAM_SEEK_SET, NULL));\r
+\r
+  CMyComPtr<ICompressCoder> decoder;\r
+  NCompress::NZ::CDecoder *decoderSpec = new NCompress::NZ::CDecoder;\r
+  decoder = decoderSpec;\r
+\r
+  HRESULT result = decoderSpec->SetDecoderProperties2(&_properties, 1);\r
+\r
+  int opResult;\r
+  if (result != S_OK)\r
+    opResult = NExtract::NOperationResult::kUnSupportedMethod;\r
+  else\r
+  {\r
+    result = decoder->Code(_stream, outStream, NULL, NULL, progress);\r
+    if (result == S_FALSE)\r
+      opResult = NExtract::NOperationResult::kDataError;\r
+    else\r
+    {\r
+      RINOK(result);\r
+      opResult = NExtract::NOperationResult::kOK;\r
+    }\r
+  }\r
+  outStream.Release();\r
+  return extractCallback->SetOperationResult(opResult);\r
+  COM_TRY_END\r
+}\r
+\r
+static IInArchive *CreateArc() { return new CHandler; }\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"Z", L"z taz", L"* .tar", 5, { 0x1F, 0x9D }, 2, false, CreateArc, 0 };\r
+\r
+REGISTER_ARC(Z)\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Zip/StdAfx.h b/CPP/7zip/Archive/Zip/StdAfx.h
new file mode 100755 (executable)
index 0000000..83fdd22
--- /dev/null
@@ -0,0 +1,8 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
new file mode 100755 (executable)
index 0000000..f86391e
--- /dev/null
@@ -0,0 +1,379 @@
+// ZipAddCommon.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/7zCrc.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../../ICoder.h"\r
+#include "../../IPassword.h"\r
+#include "../../MyVersion.h"\r
+\r
+#include "../../Common/CreateCoder.h"\r
+#include "../../Common/StreamObjects.h"\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "../../Compress/LzmaEncoder.h"\r
+#include "../../Compress/PpmdZip.h"\r
+\r
+#include "../Common/InStreamWithCRC.h"\r
+\r
+#include "ZipAddCommon.h"\r
+#include "ZipHeader.h"\r
+\r
+namespace NArchive {\r
+namespace NZip {\r
+\r
+static const CMethodId kMethodId_ZipBase   = 0x040100;\r
+static const CMethodId kMethodId_BZip2     = 0x040202;\r
+\r
+static const UInt32 kLzmaPropsSize = 5;\r
+static const UInt32 kLzmaHeaderSize = 4 + kLzmaPropsSize;\r
+\r
+class CLzmaEncoder:\r
+  public ICompressCoder,\r
+  public CMyUnknownImp\r
+{\r
+  NCompress::NLzma::CEncoder *EncoderSpec;\r
+  CMyComPtr<ICompressCoder> Encoder;\r
+  Byte Header[kLzmaHeaderSize];\r
+public:\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+  HRESULT SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);\r
+\r
+  MY_UNKNOWN_IMP\r
+};\r
+\r
+HRESULT CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)\r
+{\r
+  if (!Encoder)\r
+  {\r
+    EncoderSpec = new NCompress::NLzma::CEncoder;\r
+    Encoder = EncoderSpec;\r
+  }\r
+  CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream;\r
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\r
+  outStreamSpec->Init(Header + 4, kLzmaPropsSize);\r
+  RINOK(EncoderSpec->SetCoderProperties(propIDs, props, numProps));\r
+  RINOK(EncoderSpec->WriteCoderProperties(outStream));\r
+  if (outStreamSpec->GetPos() != kLzmaPropsSize)\r
+    return E_FAIL;\r
+  Header[0] = MY_VER_MAJOR;\r
+  Header[1] = MY_VER_MINOR;\r
+  Header[2] = kLzmaPropsSize;\r
+  Header[3] = 0;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  RINOK(WriteStream(outStream, Header, kLzmaHeaderSize));\r
+  return Encoder->Code(inStream, outStream, inSize, outSize, progress);\r
+}\r
+\r
+\r
+CAddCommon::CAddCommon(const CCompressionMethodMode &options):\r
+  _options(options),\r
+  _copyCoderSpec(NULL),\r
+  _cryptoStreamSpec(0)\r
+  {}\r
+\r
+static HRESULT GetStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC)\r
+{\r
+  UInt32 crc = CRC_INIT_VAL;\r
+  const UInt32 kBufferSize = (1 << 14);\r
+  Byte buffer[kBufferSize];\r
+  for (;;)\r
+  {\r
+    UInt32 realProcessedSize;\r
+    RINOK(inStream->Read(buffer, kBufferSize, &realProcessedSize));\r
+    if (realProcessedSize == 0)\r
+    {\r
+      resultCRC = CRC_GET_DIGEST(crc);\r
+      return S_OK;\r
+    }\r
+    crc = CrcUpdate(crc, buffer, (size_t)realProcessedSize);\r
+  }\r
+}\r
+\r
+HRESULT CAddCommon::Compress(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    ISequentialInStream *inStream, IOutStream *outStream,\r
+    ICompressProgressInfo *progress, CCompressingResult &opRes)\r
+{\r
+  CSequentialInStreamWithCRC *inSecCrcStreamSpec = 0;\r
+  CInStreamWithCRC *inCrcStreamSpec = 0;\r
+  CMyComPtr<ISequentialInStream> inCrcStream;\r
+  {\r
+    CMyComPtr<IInStream> inStream2;\r
+    // we don't support stdin, since stream from stdin can require 64-bit size header\r
+    RINOK(inStream->QueryInterface(IID_IInStream, (void **)&inStream2));\r
+    if (inStream2)\r
+    {\r
+      inCrcStreamSpec = new CInStreamWithCRC;\r
+      inCrcStream = inCrcStreamSpec;\r
+      inCrcStreamSpec->SetStream(inStream2);\r
+      inCrcStreamSpec->Init();\r
+    }\r
+    else\r
+    {\r
+      inSecCrcStreamSpec = new CSequentialInStreamWithCRC;\r
+      inCrcStream = inSecCrcStreamSpec;\r
+      inSecCrcStreamSpec->SetStream(inStream);\r
+      inSecCrcStreamSpec->Init();\r
+    }\r
+  }\r
+\r
+  int numTestMethods = _options.MethodSequence.Size();\r
+  if (numTestMethods > 1 || _options.PasswordIsDefined)\r
+  {\r
+    if (inCrcStreamSpec == 0)\r
+    {\r
+      if (_options.PasswordIsDefined)\r
+        return E_NOTIMPL;\r
+      numTestMethods = 1;\r
+    }\r
+  }\r
+  Byte method = 0;\r
+  COutStreamReleaser outStreamReleaser;\r
+  opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default;\r
+  for (int i = 0; i < numTestMethods; i++)\r
+  {\r
+    opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default;\r
+    if (inCrcStreamSpec != 0)\r
+      RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));\r
+    RINOK(outStream->SetSize(0));\r
+    RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL));\r
+    if (_options.PasswordIsDefined)\r
+    {\r
+      opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_ZipCrypto;\r
+\r
+      if (!_cryptoStream)\r
+      {\r
+        _cryptoStreamSpec = new CFilterCoder;\r
+        _cryptoStream = _cryptoStreamSpec;\r
+      }\r
+      if (_options.IsAesMode)\r
+      {\r
+        opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Aes;\r
+        if (!_cryptoStreamSpec->Filter)\r
+        {\r
+          _cryptoStreamSpec->Filter = _filterAesSpec = new NCrypto::NWzAes::CEncoder;\r
+          _filterAesSpec->SetKeyMode(_options.AesKeyMode);\r
+          RINOK(_filterAesSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Length()));\r
+        }\r
+        RINOK(_filterAesSpec->WriteHeader(outStream));\r
+      }\r
+      else\r
+      {\r
+        if (!_cryptoStreamSpec->Filter)\r
+        {\r
+          _cryptoStreamSpec->Filter = _filterSpec = new NCrypto::NZip::CEncoder;\r
+          _filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Length());\r
+        }\r
+        UInt32 crc = 0;\r
+        RINOK(GetStreamCRC(inStream, crc));\r
+        RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));\r
+        RINOK(_filterSpec->WriteHeader(outStream, crc));\r
+      }\r
+      RINOK(_cryptoStreamSpec->SetOutStream(outStream));\r
+      outStreamReleaser.FilterCoder = _cryptoStreamSpec;\r
+    }\r
+\r
+    method = _options.MethodSequence[i];\r
+    switch(method)\r
+    {\r
+      case NFileHeader::NCompressionMethod::kStored:\r
+      {\r
+        if (_copyCoderSpec == NULL)\r
+        {\r
+          _copyCoderSpec = new NCompress::CCopyCoder;\r
+          _copyCoder = _copyCoderSpec;\r
+        }\r
+        CMyComPtr<ISequentialOutStream> outStreamNew;\r
+        if (_options.PasswordIsDefined)\r
+          outStreamNew = _cryptoStream;\r
+        else\r
+          outStreamNew = outStream;\r
+        RINOK(_copyCoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress));\r
+        break;\r
+      }\r
+      default:\r
+      {\r
+        if (!_compressEncoder)\r
+        {\r
+          if (method == NFileHeader::NCompressionMethod::kLZMA)\r
+          {\r
+            _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_LZMA;\r
+            CLzmaEncoder *_lzmaEncoder = new CLzmaEncoder();\r
+            _compressEncoder = _lzmaEncoder;\r
+            NWindows::NCOM::CPropVariant props[] =\r
+            {\r
+              #ifndef _7ZIP_ST\r
+              _options.NumThreads,\r
+              #endif\r
+              _options.Algo,\r
+              _options.DicSize,\r
+              _options.NumFastBytes,\r
+              const_cast<BSTR>((const wchar_t *)_options.MatchFinder),\r
+              _options.NumMatchFinderCycles\r
+            };\r
+            PROPID propIDs[] =\r
+            {\r
+              #ifndef _7ZIP_ST\r
+              NCoderPropID::kNumThreads,\r
+              #endif\r
+              NCoderPropID::kAlgorithm,\r
+              NCoderPropID::kDictionarySize,\r
+              NCoderPropID::kNumFastBytes,\r
+              NCoderPropID::kMatchFinder,\r
+              NCoderPropID::kMatchFinderCycles\r
+            };\r
+            int numProps = sizeof(propIDs) / sizeof(propIDs[0]);\r
+            if (!_options.NumMatchFinderCyclesDefined)\r
+              numProps--;\r
+            RINOK(_lzmaEncoder->SetCoderProperties(propIDs, props, numProps));\r
+          }\r
+          else if (method == NFileHeader::NCompressionMethod::kPPMd)\r
+          {\r
+            _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_PPMd;\r
+            NCompress::NPpmdZip::CEncoder *encoder = new NCompress::NPpmdZip::CEncoder();\r
+            _compressEncoder = encoder;\r
+            NWindows::NCOM::CPropVariant props[] =\r
+            {\r
+              _options.Algo,\r
+              _options.MemSize,\r
+              _options.Order\r
+              \r
+            };\r
+            PROPID propIDs[] =\r
+            {\r
+              NCoderPropID::kAlgorithm,\r
+              NCoderPropID::kUsedMemorySize,\r
+              NCoderPropID::kOrder\r
+            };\r
+            RINOK(encoder->SetCoderProperties(propIDs, props, sizeof(propIDs) / sizeof(propIDs[0])));\r
+          }\r
+          else\r
+          {\r
+          CMethodId methodId;\r
+          switch(method)\r
+          {\r
+            case NFileHeader::NCompressionMethod::kBZip2:\r
+              methodId = kMethodId_BZip2;\r
+              _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_BZip2;\r
+              break;\r
+            default:\r
+              _compressExtractVersion = ((method == NFileHeader::NCompressionMethod::kDeflated64) ?\r
+                  NFileHeader::NCompressionMethod::kExtractVersion_Deflate64 :\r
+                  NFileHeader::NCompressionMethod::kExtractVersion_Deflate);\r
+              methodId = kMethodId_ZipBase + method;\r
+              break;\r
+          }\r
+          RINOK(CreateCoder(\r
+              EXTERNAL_CODECS_LOC_VARS\r
+              methodId, _compressEncoder, true));\r
+          if (!_compressEncoder)\r
+            return E_NOTIMPL;\r
+\r
+          if (method == NFileHeader::NCompressionMethod::kDeflated ||\r
+              method == NFileHeader::NCompressionMethod::kDeflated64)\r
+          {\r
+            NWindows::NCOM::CPropVariant props[] =\r
+            {\r
+              _options.Algo,\r
+              _options.NumPasses,\r
+              _options.NumFastBytes,\r
+              _options.NumMatchFinderCycles\r
+            };\r
+            PROPID propIDs[] =\r
+            {\r
+              NCoderPropID::kAlgorithm,\r
+              NCoderPropID::kNumPasses,\r
+              NCoderPropID::kNumFastBytes,\r
+              NCoderPropID::kMatchFinderCycles\r
+            };\r
+            int numProps = sizeof(propIDs) / sizeof(propIDs[0]);\r
+            if (!_options.NumMatchFinderCyclesDefined)\r
+              numProps--;\r
+            CMyComPtr<ICompressSetCoderProperties> setCoderProperties;\r
+            _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties);\r
+            if (setCoderProperties)\r
+            {\r
+              RINOK(setCoderProperties->SetCoderProperties(propIDs, props, numProps));\r
+            }\r
+          }\r
+          else if (method == NFileHeader::NCompressionMethod::kBZip2)\r
+          {\r
+            NWindows::NCOM::CPropVariant props[] =\r
+            {\r
+              _options.DicSize,\r
+              _options.NumPasses\r
+              #ifndef _7ZIP_ST\r
+              , _options.NumThreads\r
+              #endif\r
+            };\r
+            PROPID propIDs[] =\r
+            {\r
+              NCoderPropID::kDictionarySize,\r
+              NCoderPropID::kNumPasses\r
+              #ifndef _7ZIP_ST\r
+              , NCoderPropID::kNumThreads\r
+              #endif\r
+            };\r
+            CMyComPtr<ICompressSetCoderProperties> setCoderProperties;\r
+            _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties);\r
+            if (setCoderProperties)\r
+            {\r
+              RINOK(setCoderProperties->SetCoderProperties(propIDs, props, sizeof(propIDs) / sizeof(propIDs[0])));\r
+            }\r
+          }\r
+          }\r
+        }\r
+        CMyComPtr<ISequentialOutStream> outStreamNew;\r
+        if (_options.PasswordIsDefined)\r
+          outStreamNew = _cryptoStream;\r
+        else\r
+          outStreamNew = outStream;\r
+        if (_compressExtractVersion > opRes.ExtractVersion)\r
+          opRes.ExtractVersion = _compressExtractVersion;\r
+        RINOK(_compressEncoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress));\r
+        break;\r
+      }\r
+    }\r
+\r
+    RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize));\r
+\r
+    if (inCrcStreamSpec != 0)\r
+    {\r
+      opRes.CRC = inCrcStreamSpec->GetCRC();\r
+      opRes.UnpackSize = inCrcStreamSpec->GetSize();\r
+    }\r
+    else\r
+    {\r
+      opRes.CRC = inSecCrcStreamSpec->GetCRC();\r
+      opRes.UnpackSize = inSecCrcStreamSpec->GetSize();\r
+    }\r
+\r
+    if (_options.PasswordIsDefined)\r
+    {\r
+      if (opRes.PackSize < opRes.UnpackSize +\r
+          (_options.IsAesMode ? _filterAesSpec->GetHeaderSize() : NCrypto::NZip::kHeaderSize))\r
+        break;\r
+    }\r
+    else if (opRes.PackSize < opRes.UnpackSize)\r
+      break;\r
+  }\r
+  if (_options.IsAesMode)\r
+  {\r
+    RINOK(_filterAesSpec->WriteFooter(outStream));\r
+    RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize));\r
+  }\r
+  opRes.Method = method;\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.h b/CPP/7zip/Archive/Zip/ZipAddCommon.h
new file mode 100755 (executable)
index 0000000..7c379cc
--- /dev/null
@@ -0,0 +1,56 @@
+// ZipAddCommon.h\r
+\r
+#ifndef __ZIP_ADD_COMMON_H\r
+#define __ZIP_ADD_COMMON_H\r
+\r
+#include "../../ICoder.h"\r
+#include "../../IProgress.h"\r
+\r
+#include "../../Common/CreateCoder.h"\r
+#include "../../Common/FilterCoder.h"\r
+\r
+#include "../../Compress/CopyCoder.h"\r
+\r
+#include "../../Crypto/ZipCrypto.h"\r
+#include "../../Crypto/WzAes.h"\r
+\r
+#include "ZipCompressionMode.h"\r
+\r
+namespace NArchive {\r
+namespace NZip {\r
+\r
+struct CCompressingResult\r
+{\r
+  UInt64 UnpackSize;\r
+  UInt64 PackSize;\r
+  UInt32 CRC;\r
+  UInt16 Method;\r
+  Byte ExtractVersion;\r
+};\r
+\r
+class CAddCommon\r
+{\r
+  CCompressionMethodMode _options;\r
+  NCompress::CCopyCoder *_copyCoderSpec;\r
+  CMyComPtr<ICompressCoder> _copyCoder;\r
+\r
+  CMyComPtr<ICompressCoder> _compressEncoder;\r
+  Byte _compressExtractVersion;\r
+\r
+  CFilterCoder *_cryptoStreamSpec;\r
+  CMyComPtr<ISequentialOutStream> _cryptoStream;\r
+\r
+  NCrypto::NZip::CEncoder *_filterSpec;\r
+  NCrypto::NWzAes::CEncoder *_filterAesSpec;\r
+\r
+public:\r
+  CAddCommon(const CCompressionMethodMode &options);\r
+  HRESULT Compress(\r
+      DECL_EXTERNAL_CODECS_LOC_VARS\r
+      ISequentialInStream *inStream, IOutStream *outStream,\r
+      ICompressProgressInfo *progress, CCompressingResult &operationResult);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Zip/ZipCompressionMode.h b/CPP/7zip/Archive/Zip/ZipCompressionMode.h
new file mode 100755 (executable)
index 0000000..6713473
--- /dev/null
@@ -0,0 +1,42 @@
+// CompressionMode.h\r
+\r
+#ifndef __ZIP_COMPRESSION_MODE_H\r
+#define __ZIP_COMPRESSION_MODE_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+namespace NArchive {\r
+namespace NZip {\r
+\r
+struct CCompressionMethodMode\r
+{\r
+  CRecordVector<Byte> MethodSequence;\r
+  UString MatchFinder;\r
+  UInt32 Algo;\r
+  UInt32 NumPasses;\r
+  UInt32 NumFastBytes;\r
+  bool NumMatchFinderCyclesDefined;\r
+  UInt32 NumMatchFinderCycles;\r
+  UInt32 DicSize;\r
+  UInt32 MemSize;\r
+  UInt32 Order;\r
+\r
+  #ifndef _7ZIP_ST\r
+  UInt32 NumThreads;\r
+  #endif\r
+  bool PasswordIsDefined;\r
+  AString Password;\r
+  bool IsAesMode;\r
+  Byte AesKeyMode;\r
+  \r
+  CCompressionMethodMode():\r
+      NumMatchFinderCyclesDefined(false),\r
+      PasswordIsDefined(false),\r
+      IsAesMode(false),\r
+      AesKeyMode(3)\r
+      {}\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp
new file mode 100755 (executable)
index 0000000..4b257f1
--- /dev/null
@@ -0,0 +1,822 @@
+// ZipHandler.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/IntToString.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../../IPassword.h"\r
+\r
+#include "../../Common/FilterCoder.h"\r
+#include "../../Common/ProgressUtils.h"\r
+#include "../../Common/StreamObjects.h"\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "../../Compress/CopyCoder.h"\r
+#include "../../Compress/LzmaDecoder.h"\r
+#include "../../Compress/ImplodeDecoder.h"\r
+#include "../../Compress/PpmdZip.h"\r
+#include "../../Compress/ShrinkDecoder.h"\r
+\r
+#include "../../Crypto/WzAes.h"\r
+#include "../../Crypto/ZipCrypto.h"\r
+#include "../../Crypto/ZipStrong.h"\r
+\r
+#include "../Common/ItemNameUtils.h"\r
+#include "../Common/OutStreamWithCRC.h"\r
+\r
+#include "ZipHandler.h"\r
+\r
+using namespace NWindows;\r
+\r
+namespace NArchive {\r
+namespace NZip {\r
+\r
+static const CMethodId kMethodId_ZipBase = 0x040100;\r
+static const CMethodId kMethodId_BZip2 = 0x040202;\r
+\r
+static const char *kHostOS[] =\r
+{\r
+  "FAT",\r
+  "AMIGA",\r
+  "VMS",\r
+  "Unix",\r
+  "VM/CMS",\r
+  "Atari",\r
+  "HPFS",\r
+  "Macintosh",\r
+  "Z-System",\r
+  "CP/M",\r
+  "TOPS-20",\r
+  "NTFS",\r
+  "SMS/QDOS",\r
+  "Acorn",\r
+  "VFAT",\r
+  "MVS",\r
+  "BeOS",\r
+  "Tandem",\r
+  "OS/400",\r
+  "OS/X"\r
+};\r
+\r
+static const char *kUnknownOS = "Unknown";\r
+\r
+static const char *kMethods[] =\r
+{\r
+  "Store",\r
+  "Shrink",\r
+  "Reduced1",\r
+  "Reduced2",\r
+  "Reduced3",\r
+  "Reduced4",\r
+  "Implode",\r
+  "Tokenizing",\r
+  "Deflate",\r
+  "Deflate64",\r
+  "PKImploding"\r
+};\r
+\r
+static const char *kBZip2Method = "BZip2";\r
+static const char *kLZMAMethod = "LZMA";\r
+static const char *kJpegMethod = "Jpeg";\r
+static const char *kWavPackMethod = "WavPack";\r
+static const char *kPPMdMethod = "PPMd";\r
+static const char *kAESMethod = "AES";\r
+static const char *kZipCryptoMethod = "ZipCrypto";\r
+static const char *kStrongCryptoMethod = "StrongCrypto";\r
+\r
+static struct CStrongCryptoPair\r
+{\r
+  UInt16 Id;\r
+  const char *Name;\r
+} g_StrongCryptoPairs[] =\r
+{\r
+  { NStrongCryptoFlags::kDES, "DES" },\r
+  { NStrongCryptoFlags::kRC2old, "RC2a" },\r
+  { NStrongCryptoFlags::k3DES168, "3DES-168" },\r
+  { NStrongCryptoFlags::k3DES112, "3DES-112" },\r
+  { NStrongCryptoFlags::kAES128, "pkAES-128" },\r
+  { NStrongCryptoFlags::kAES192, "pkAES-192" },\r
+  { NStrongCryptoFlags::kAES256, "pkAES-256" },\r
+  { NStrongCryptoFlags::kRC2, "RC2" },\r
+  { NStrongCryptoFlags::kBlowfish, "Blowfish" },\r
+  { NStrongCryptoFlags::kTwofish, "Twofish" },\r
+  { NStrongCryptoFlags::kRC4, "RC4" }\r
+};\r
+\r
+static STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidIsDir, VT_BOOL},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidCTime, VT_FILETIME},\r
+  { NULL, kpidATime, VT_FILETIME},\r
+  { NULL, kpidAttrib, VT_UI4},\r
+  { NULL, kpidEncrypted, VT_BOOL},\r
+  { NULL, kpidComment, VT_BSTR},\r
+  { NULL, kpidCRC, VT_UI4},\r
+  { NULL, kpidMethod, VT_BSTR},\r
+  { NULL, kpidHostOS, VT_BSTR},\r
+  { NULL, kpidUnpackVer, VT_UI4}\r
+};\r
+\r
+static STATPROPSTG kArcProps[] =\r
+{\r
+  { NULL, kpidBit64, VT_BOOL},\r
+  { NULL, kpidComment, VT_BSTR},\r
+  { NULL, kpidPhySize, VT_UI8},\r
+  { NULL, kpidOffset, VT_UI8}\r
+};\r
+\r
+CHandler::CHandler()\r
+{\r
+  InitMethodProperties();\r
+}\r
+\r
+static AString BytesToString(const CByteBuffer &data)\r
+{\r
+  AString s;\r
+  int size = (int)data.GetCapacity();\r
+  if (size > 0)\r
+  {\r
+    char *p = s.GetBuffer(size + 1);\r
+    memcpy(p, (const Byte *)data, size);\r
+    p[size] = '\0';\r
+    s.ReleaseBuffer();\r
+  }\r
+  return s;\r
+}\r
+\r
+IMP_IInArchive_Props\r
+IMP_IInArchive_ArcProps\r
+\r
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidBit64:  if (m_Archive.IsZip64) prop = m_Archive.IsZip64; break;\r
+    case kpidComment:  prop = MultiByteToUnicodeString(BytesToString(m_Archive.ArcInfo.Comment), CP_ACP); break;\r
+    case kpidPhySize:  prop = m_Archive.ArcInfo.GetPhySize(); break;\r
+    case kpidOffset:  if (m_Archive.ArcInfo.StartPosition != 0) prop = m_Archive.ArcInfo.StartPosition; break;\r
+  }\r
+  prop.Detach(value);\r
+  COM_TRY_END\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = m_Items.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  const CItemEx &item = m_Items[index];\r
+  switch(propID)\r
+  {\r
+    case kpidPath:  prop = NItemName::GetOSName2(item.GetUnicodeString(item.Name)); break;\r
+    case kpidIsDir:  prop = item.IsDir(); break;\r
+    case kpidSize:  prop = item.UnPackSize; break;\r
+    case kpidPackSize:  prop = item.PackSize; break;\r
+    case kpidTimeType:\r
+    {\r
+      FILETIME ft;\r
+      UInt32 unixTime;\r
+      if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, ft))\r
+        prop = (UInt32)NFileTimeType::kWindows;\r
+      else if (item.CentralExtra.GetUnixTime(NFileHeader::NUnixTime::kMTime, unixTime))\r
+        prop = (UInt32)NFileTimeType::kUnix;\r
+      else\r
+        prop = (UInt32)NFileTimeType::kDOS;\r
+      break;\r
+    }\r
+    case kpidCTime:\r
+    {\r
+      FILETIME ft;\r
+      if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kCTime, ft))\r
+        prop = ft;\r
+      break;\r
+    }\r
+    case kpidATime:\r
+    {\r
+      FILETIME ft;\r
+      if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kATime, ft))\r
+        prop = ft;\r
+      break;\r
+    }\r
+    case kpidMTime:\r
+    {\r
+      FILETIME utc;\r
+      if (!item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utc))\r
+      {\r
+        UInt32 unixTime;\r
+        if (item.CentralExtra.GetUnixTime(NFileHeader::NUnixTime::kMTime, unixTime))\r
+          NTime::UnixTimeToFileTime(unixTime, utc);\r
+        else\r
+        {\r
+          FILETIME localFileTime;\r
+          if (!NTime::DosTimeToFileTime(item.Time, localFileTime) ||\r
+              !LocalFileTimeToFileTime(&localFileTime, &utc))\r
+            utc.dwHighDateTime = utc.dwLowDateTime = 0;\r
+        }\r
+      }\r
+      prop = utc;\r
+      break;\r
+    }\r
+    case kpidAttrib:  prop = item.GetWinAttributes(); break;\r
+    case kpidEncrypted:  prop = item.IsEncrypted(); break;\r
+    case kpidComment:  prop = item.GetUnicodeString(BytesToString(item.Comment)); break;\r
+    case kpidCRC:  if (item.IsThereCrc()) prop = item.FileCRC; break;\r
+    case kpidMethod:\r
+    {\r
+      UInt16 methodId = item.CompressionMethod;\r
+      AString method;\r
+      if (item.IsEncrypted())\r
+      {\r
+        if (methodId == NFileHeader::NCompressionMethod::kWzAES)\r
+        {\r
+          method = kAESMethod;\r
+          CWzAesExtraField aesField;\r
+          if (item.CentralExtra.GetWzAesField(aesField))\r
+          {\r
+            method += '-';\r
+            char s[32];\r
+            ConvertUInt64ToString((aesField.Strength + 1) * 64 , s);\r
+            method += s;\r
+            method += ' ';\r
+            methodId = aesField.Method;\r
+          }\r
+        }\r
+        else\r
+        {\r
+          if (item.IsStrongEncrypted())\r
+          {\r
+            CStrongCryptoField f;\r
+            bool finded = false;\r
+            if (item.CentralExtra.GetStrongCryptoField(f))\r
+            {\r
+              for (int i = 0; i < sizeof(g_StrongCryptoPairs) / sizeof(g_StrongCryptoPairs[0]); i++)\r
+              {\r
+                const CStrongCryptoPair &pair = g_StrongCryptoPairs[i];\r
+                if (f.AlgId == pair.Id)\r
+                {\r
+                  method += pair.Name;\r
+                  finded = true;\r
+                  break;\r
+                }\r
+              }\r
+            }\r
+            if (!finded)\r
+              method += kStrongCryptoMethod;\r
+          }\r
+          else\r
+            method += kZipCryptoMethod;\r
+          method += ' ';\r
+        }\r
+      }\r
+      if (methodId < sizeof(kMethods) / sizeof(kMethods[0]))\r
+        method += kMethods[methodId];\r
+      else switch (methodId)\r
+      {\r
+        case NFileHeader::NCompressionMethod::kLZMA:\r
+          method += kLZMAMethod;\r
+          if (item.IsLzmaEOS())\r
+            method += ":EOS";\r
+          break;\r
+        case NFileHeader::NCompressionMethod::kBZip2: method += kBZip2Method; break;\r
+        case NFileHeader::NCompressionMethod::kJpeg: method += kJpegMethod; break;\r
+        case NFileHeader::NCompressionMethod::kWavPack: method += kWavPackMethod; break;\r
+        case NFileHeader::NCompressionMethod::kPPMd: method += kPPMdMethod; break;\r
+        default:\r
+        {\r
+          char s[32];\r
+          ConvertUInt64ToString(methodId, s);\r
+          method += s;\r
+        }\r
+      }\r
+      prop = method;\r
+      break;\r
+    }\r
+    case kpidHostOS:\r
+      prop = (item.MadeByVersion.HostOS < sizeof(kHostOS) / sizeof(kHostOS[0])) ?\r
+        (kHostOS[item.MadeByVersion.HostOS]) : kUnknownOS;\r
+      break;\r
+    case kpidUnpackVer:\r
+      prop = (UInt32)item.ExtractVersion.Version;\r
+      break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+class CProgressImp: public CProgressVirt\r
+{\r
+  CMyComPtr<IArchiveOpenCallback> _callback;\r
+public:\r
+  STDMETHOD(SetTotal)(UInt64 numFiles);\r
+  STDMETHOD(SetCompleted)(UInt64 numFiles);\r
+  CProgressImp(IArchiveOpenCallback *callback): _callback(callback) {}\r
+};\r
+\r
+STDMETHODIMP CProgressImp::SetTotal(UInt64 numFiles)\r
+{\r
+  if (_callback)\r
+    return _callback->SetTotal(&numFiles, NULL);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CProgressImp::SetCompleted(UInt64 numFiles)\r
+{\r
+  if (_callback)\r
+    return _callback->SetCompleted(&numFiles, NULL);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::Open(IInStream *inStream,\r
+    const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback)\r
+{\r
+  COM_TRY_BEGIN\r
+  try\r
+  {\r
+    Close();\r
+    RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));\r
+    RINOK(m_Archive.Open(inStream, maxCheckStartPosition));\r
+    CProgressImp progressImp(callback);\r
+    return m_Archive.ReadHeaders(m_Items, &progressImp);\r
+  }\r
+  catch(const CInArchiveException &) { Close(); return S_FALSE; }\r
+  catch(...) { Close(); throw; }\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CHandler::Close()\r
+{\r
+  m_Items.Clear();\r
+  m_Archive.Close();\r
+  return S_OK;\r
+}\r
+\r
+//////////////////////////////////////\r
+// CHandler::DecompressItems\r
+\r
+class CLzmaDecoder:\r
+  public ICompressCoder,\r
+  public CMyUnknownImp\r
+{\r
+  NCompress::NLzma::CDecoder *DecoderSpec;\r
+  CMyComPtr<ICompressCoder> Decoder;\r
+public:\r
+  CLzmaDecoder();\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+  MY_UNKNOWN_IMP\r
+};\r
+\r
+CLzmaDecoder::CLzmaDecoder()\r
+{\r
+  DecoderSpec = new NCompress::NLzma::CDecoder;\r
+  Decoder = DecoderSpec;\r
+}\r
+\r
+HRESULT CLzmaDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  Byte buf[9];\r
+  RINOK(ReadStream_FALSE(inStream, buf, 9));\r
+  if (buf[2] != 5 || buf[3] != 0)\r
+    return E_NOTIMPL;\r
+  RINOK(DecoderSpec->SetDecoderProperties2(buf + 4, 5));\r
+  return Decoder->Code(inStream, outStream, NULL, outSize, progress);\r
+}\r
+\r
+struct CMethodItem\r
+{\r
+  UInt16 ZipMethod;\r
+  CMyComPtr<ICompressCoder> Coder;\r
+};\r
+\r
+class CZipDecoder\r
+{\r
+  NCrypto::NZip::CDecoder *_zipCryptoDecoderSpec;\r
+  NCrypto::NZipStrong::CDecoder *_pkAesDecoderSpec;\r
+  NCrypto::NWzAes::CDecoder *_wzAesDecoderSpec;\r
+\r
+  CMyComPtr<ICompressFilter> _zipCryptoDecoder;\r
+  CMyComPtr<ICompressFilter> _pkAesDecoder;\r
+  CMyComPtr<ICompressFilter> _wzAesDecoder;\r
+\r
+  CFilterCoder *filterStreamSpec;\r
+  CMyComPtr<ISequentialInStream> filterStream;\r
+  CMyComPtr<ICryptoGetTextPassword> getTextPassword;\r
+  CObjectVector<CMethodItem> methodItems;\r
+\r
+public:\r
+  CZipDecoder():\r
+      _zipCryptoDecoderSpec(0),\r
+      _pkAesDecoderSpec(0),\r
+      _wzAesDecoderSpec(0),\r
+      filterStreamSpec(0) {}\r
+\r
+  HRESULT Decode(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    CInArchive &archive, const CItemEx &item,\r
+    ISequentialOutStream *realOutStream,\r
+    IArchiveExtractCallback *extractCallback,\r
+    ICompressProgressInfo *compressProgress,\r
+    UInt32 numThreads, Int32 &res);\r
+};\r
+\r
+HRESULT CZipDecoder::Decode(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    CInArchive &archive, const CItemEx &item,\r
+    ISequentialOutStream *realOutStream,\r
+    IArchiveExtractCallback *extractCallback,\r
+    ICompressProgressInfo *compressProgress,\r
+    UInt32 numThreads, Int32 &res)\r
+{\r
+  res = NExtract::NOperationResult::kDataError;\r
+  CInStreamReleaser inStreamReleaser;\r
+\r
+  bool needCRC = true;\r
+  bool wzAesMode = false;\r
+  bool pkAesMode = false;\r
+  UInt16 methodId = item.CompressionMethod;\r
+  if (item.IsEncrypted())\r
+  {\r
+    if (item.IsStrongEncrypted())\r
+    {\r
+      CStrongCryptoField f;\r
+      if (item.CentralExtra.GetStrongCryptoField(f))\r
+      {\r
+        pkAesMode = true;\r
+      }\r
+      if (!pkAesMode)\r
+      {\r
+        res = NExtract::NOperationResult::kUnSupportedMethod;\r
+        return S_OK;\r
+      }\r
+    }\r
+    if (methodId == NFileHeader::NCompressionMethod::kWzAES)\r
+    {\r
+      CWzAesExtraField aesField;\r
+      if (item.CentralExtra.GetWzAesField(aesField))\r
+      {\r
+        wzAesMode = true;\r
+        needCRC = aesField.NeedCrc();\r
+      }\r
+    }\r
+  }\r
+    \r
+  COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;\r
+  CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;\r
+  outStreamSpec->SetStream(realOutStream);\r
+  outStreamSpec->Init(needCRC);\r
+  \r
+  UInt64 authenticationPos;\r
+  \r
+  CMyComPtr<ISequentialInStream> inStream;\r
+  {\r
+    UInt64 packSize = item.PackSize;\r
+    if (wzAesMode)\r
+    {\r
+      if (packSize < NCrypto::NWzAes::kMacSize)\r
+        return S_OK;\r
+      packSize -= NCrypto::NWzAes::kMacSize;\r
+    }\r
+    UInt64 dataPos = item.GetDataPosition();\r
+    inStream.Attach(archive.CreateLimitedStream(dataPos, packSize));\r
+    authenticationPos = dataPos + packSize;\r
+  }\r
+  \r
+  CMyComPtr<ICompressFilter> cryptoFilter;\r
+  if (item.IsEncrypted())\r
+  {\r
+    if (wzAesMode)\r
+    {\r
+      CWzAesExtraField aesField;\r
+      if (!item.CentralExtra.GetWzAesField(aesField))\r
+        return S_OK;\r
+      methodId = aesField.Method;\r
+      if (!_wzAesDecoder)\r
+      {\r
+        _wzAesDecoderSpec = new NCrypto::NWzAes::CDecoder;\r
+        _wzAesDecoder = _wzAesDecoderSpec;\r
+      }\r
+      cryptoFilter = _wzAesDecoder;\r
+      Byte properties = aesField.Strength;\r
+      RINOK(_wzAesDecoderSpec->SetDecoderProperties2(&properties, 1));\r
+    }\r
+    else if (pkAesMode)\r
+    {\r
+      if (!_pkAesDecoder)\r
+      {\r
+        _pkAesDecoderSpec = new NCrypto::NZipStrong::CDecoder;\r
+        _pkAesDecoder = _pkAesDecoderSpec;\r
+      }\r
+      cryptoFilter = _pkAesDecoder;\r
+    }\r
+    else\r
+    {\r
+      if (!_zipCryptoDecoder)\r
+      {\r
+        _zipCryptoDecoderSpec = new NCrypto::NZip::CDecoder;\r
+        _zipCryptoDecoder = _zipCryptoDecoderSpec;\r
+      }\r
+      cryptoFilter = _zipCryptoDecoder;\r
+    }\r
+    CMyComPtr<ICryptoSetPassword> cryptoSetPassword;\r
+    RINOK(cryptoFilter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));\r
+    \r
+    if (!getTextPassword)\r
+      extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);\r
+    \r
+    if (getTextPassword)\r
+    {\r
+      CMyComBSTR password;\r
+      RINOK(getTextPassword->CryptoGetTextPassword(&password));\r
+      AString charPassword;\r
+      if (wzAesMode || pkAesMode)\r
+      {\r
+        charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_ACP);\r
+        /*\r
+        for (int i = 0;; i++)\r
+        {\r
+          wchar_t c = password[i];\r
+          if (c == 0)\r
+            break;\r
+          if (c >= 0x80)\r
+          {\r
+            res = NExtract::NOperationResult::kDataError;\r
+            return S_OK;\r
+          }\r
+          charPassword += (char)c;\r
+        }\r
+        */\r
+      }\r
+      else\r
+      {\r
+        // we use OEM. WinZip/Windows probably use ANSI for some files\r
+        charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP);\r
+      }\r
+      HRESULT result = cryptoSetPassword->CryptoSetPassword(\r
+        (const Byte *)(const char *)charPassword, charPassword.Length());\r
+      if (result != S_OK)\r
+        return S_OK;\r
+    }\r
+    else\r
+    {\r
+      RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));\r
+    }\r
+  }\r
+  \r
+  int m;\r
+  for (m = 0; m < methodItems.Size(); m++)\r
+    if (methodItems[m].ZipMethod == methodId)\r
+      break;\r
+\r
+  if (m == methodItems.Size())\r
+  {\r
+    CMethodItem mi;\r
+    mi.ZipMethod = methodId;\r
+    if (methodId == NFileHeader::NCompressionMethod::kStored)\r
+      mi.Coder = new NCompress::CCopyCoder;\r
+    else if (methodId == NFileHeader::NCompressionMethod::kShrunk)\r
+      mi.Coder = new NCompress::NShrink::CDecoder;\r
+    else if (methodId == NFileHeader::NCompressionMethod::kImploded)\r
+      mi.Coder = new NCompress::NImplode::NDecoder::CCoder;\r
+    else if (methodId == NFileHeader::NCompressionMethod::kLZMA)\r
+      mi.Coder = new CLzmaDecoder;\r
+    else if (methodId == NFileHeader::NCompressionMethod::kPPMd)\r
+      mi.Coder = new NCompress::NPpmdZip::CDecoder(true);\r
+    else\r
+    {\r
+      CMethodId szMethodID;\r
+      if (methodId == NFileHeader::NCompressionMethod::kBZip2)\r
+        szMethodID = kMethodId_BZip2;\r
+      else\r
+      {\r
+        if (methodId > 0xFF)\r
+        {\r
+          res = NExtract::NOperationResult::kUnSupportedMethod;\r
+          return S_OK;\r
+        }\r
+        szMethodID = kMethodId_ZipBase + (Byte)methodId;\r
+      }\r
+\r
+      RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS szMethodID, mi.Coder, false));\r
+\r
+      if (mi.Coder == 0)\r
+      {\r
+        res = NExtract::NOperationResult::kUnSupportedMethod;\r
+        return S_OK;\r
+      }\r
+    }\r
+    m = methodItems.Add(mi);\r
+  }\r
+  ICompressCoder *coder = methodItems[m].Coder;\r
+  \r
+  {\r
+    CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;\r
+    coder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);\r
+    if (setDecoderProperties)\r
+    {\r
+      Byte properties = (Byte)item.Flags;\r
+      RINOK(setDecoderProperties->SetDecoderProperties2(&properties, 1));\r
+    }\r
+  }\r
+  \r
+  #ifndef _7ZIP_ST\r
+  {\r
+    CMyComPtr<ICompressSetCoderMt> setCoderMt;\r
+    coder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);\r
+    if (setCoderMt)\r
+    {\r
+      RINOK(setCoderMt->SetNumberOfThreads(numThreads));\r
+    }\r
+  }\r
+  #endif\r
+  \r
+  {\r
+    HRESULT result = S_OK;\r
+    CMyComPtr<ISequentialInStream> inStreamNew;\r
+    if (item.IsEncrypted())\r
+    {\r
+      if (!filterStream)\r
+      {\r
+        filterStreamSpec = new CFilterCoder;\r
+        filterStream = filterStreamSpec;\r
+      }\r
+      filterStreamSpec->Filter = cryptoFilter;\r
+      if (wzAesMode)\r
+      {\r
+        result = _wzAesDecoderSpec->ReadHeader(inStream);\r
+      }\r
+      else if (pkAesMode)\r
+      {\r
+        result =_pkAesDecoderSpec->ReadHeader(inStream, item.FileCRC, item.UnPackSize);\r
+        if (result == S_OK)\r
+        {\r
+          bool passwOK;\r
+          result = _pkAesDecoderSpec->CheckPassword(passwOK);\r
+          if (result == S_OK && !passwOK)\r
+            result = S_FALSE;\r
+        }\r
+      }\r
+      else\r
+      {\r
+        result = _zipCryptoDecoderSpec->ReadHeader(inStream);\r
+      }\r
+\r
+      if (result == S_OK)\r
+      {\r
+        RINOK(filterStreamSpec->SetInStream(inStream));\r
+        inStreamReleaser.FilterCoder = filterStreamSpec;\r
+        inStreamNew = filterStream;\r
+        if (wzAesMode)\r
+        {\r
+          if (!_wzAesDecoderSpec->CheckPasswordVerifyCode())\r
+            result = S_FALSE;\r
+        }\r
+      }\r
+    }\r
+    else\r
+      inStreamNew = inStream;\r
+    if (result == S_OK)\r
+      result = coder->Code(inStreamNew, outStream, NULL, &item.UnPackSize, compressProgress);\r
+    if (result == S_FALSE)\r
+      return S_OK;\r
+    if (result == E_NOTIMPL)\r
+    {\r
+      res = NExtract::NOperationResult::kUnSupportedMethod;\r
+      return S_OK;\r
+    }\r
+\r
+    RINOK(result);\r
+  }\r
+  bool crcOK = true;\r
+  bool authOk = true;\r
+  if (needCRC)\r
+    crcOK = (outStreamSpec->GetCRC() == item.FileCRC);\r
+  if (wzAesMode)\r
+  {\r
+    inStream.Attach(archive.CreateLimitedStream(authenticationPos, NCrypto::NWzAes::kMacSize));\r
+    if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK)\r
+      authOk = false;\r
+  }\r
+  \r
+  res = ((crcOK && authOk) ?\r
+    NExtract::NOperationResult::kOK :\r
+    NExtract::NOperationResult::kCRCError);\r
+  return S_OK;\r
+}\r
+\r
+\r
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,\r
+    Int32 testMode, IArchiveExtractCallback *extractCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  CZipDecoder myDecoder;\r
+  UInt64 totalUnPacked = 0, totalPacked = 0;\r
+  bool allFilesMode = (numItems == (UInt32)-1);\r
+  if (allFilesMode)\r
+    numItems = m_Items.Size();\r
+  if(numItems == 0)\r
+    return S_OK;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    const CItemEx &item = m_Items[allFilesMode ? i : indices[i]];\r
+    totalUnPacked += item.UnPackSize;\r
+    totalPacked += item.PackSize;\r
+  }\r
+  RINOK(extractCallback->SetTotal(totalUnPacked));\r
+\r
+  UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0;\r
+  UInt64 currentItemUnPacked, currentItemPacked;\r
+  \r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(extractCallback, false);\r
+\r
+  for (i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked,\r
+      currentTotalPacked += currentItemPacked)\r
+  {\r
+    currentItemUnPacked = 0;\r
+    currentItemPacked = 0;\r
+\r
+    lps->InSize = currentTotalPacked;\r
+    lps->OutSize = currentTotalUnPacked;\r
+    RINOK(lps->SetCur());\r
+\r
+    CMyComPtr<ISequentialOutStream> realOutStream;\r
+    Int32 askMode = testMode ?\r
+        NExtract::NAskMode::kTest :\r
+        NExtract::NAskMode::kExtract;\r
+    Int32 index = allFilesMode ? i : indices[i];\r
+\r
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));\r
+\r
+    CItemEx item = m_Items[index];\r
+    if (!item.FromLocal)\r
+    {\r
+      HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item);\r
+      if (res == S_FALSE)\r
+      {\r
+        if (item.IsDir() || realOutStream || testMode)\r
+        {\r
+          RINOK(extractCallback->PrepareOperation(askMode));\r
+          realOutStream.Release();\r
+          RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));\r
+        }\r
+        continue;\r
+      }\r
+      RINOK(res);\r
+    }\r
+\r
+    if (item.IsDir() || item.IgnoreItem())\r
+    {\r
+      // if (!testMode)\r
+      {\r
+        RINOK(extractCallback->PrepareOperation(askMode));\r
+        realOutStream.Release();\r
+        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));\r
+      }\r
+      continue;\r
+    }\r
+\r
+    currentItemUnPacked = item.UnPackSize;\r
+    currentItemPacked = item.PackSize;\r
+\r
+    if (!testMode && !realOutStream)\r
+      continue;\r
+\r
+    RINOK(extractCallback->PrepareOperation(askMode));\r
+\r
+    Int32 res;\r
+    RINOK(myDecoder.Decode(\r
+        EXTERNAL_CODECS_VARS\r
+        m_Archive, item, realOutStream, extractCallback,\r
+        progress, _numThreads, res));\r
+    realOutStream.Release();\r
+    \r
+    RINOK(extractCallback->SetOperationResult(res))\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+IMPL_ISetCompressCodecsInfo\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h
new file mode 100755 (executable)
index 0000000..48f07a0
--- /dev/null
@@ -0,0 +1,101 @@
+// Zip/Handler.h\r
+\r
+#ifndef __ZIP_HANDLER_H\r
+#define __ZIP_HANDLER_H\r
+\r
+#include "Common/DynamicBuffer.h"\r
+#include "../../ICoder.h"\r
+#include "../IArchive.h"\r
+\r
+#include "../../Common/CreateCoder.h"\r
+\r
+#include "ZipIn.h"\r
+#include "ZipCompressionMode.h"\r
+\r
+#ifndef _7ZIP_ST\r
+#include "../../../Windows/System.h"\r
+#endif\r
+\r
+namespace NArchive {\r
+namespace NZip {\r
+\r
+class CHandler:\r
+  public IInArchive,\r
+  public IOutArchive,\r
+  public ISetProperties,\r
+  PUBLIC_ISetCompressCodecsInfo\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_QUERYINTERFACE_BEGIN2(IInArchive)\r
+  MY_QUERYINTERFACE_ENTRY(IOutArchive)\r
+  MY_QUERYINTERFACE_ENTRY(ISetProperties)\r
+  QUERY_ENTRY_ISetCompressCodecsInfo\r
+  MY_QUERYINTERFACE_END\r
+  MY_ADDREF_RELEASE\r
+\r
+  INTERFACE_IInArchive(;)\r
+  INTERFACE_IOutArchive(;)\r
+\r
+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties);\r
+\r
+  DECL_ISetCompressCodecsInfo\r
+\r
+  CHandler();\r
+private:\r
+  CObjectVector<CItemEx> m_Items;\r
+  CInArchive m_Archive;\r
+\r
+  int m_Level;\r
+  int m_MainMethod;\r
+  UInt32 m_DicSize;\r
+  UInt32 m_Algo;\r
+  UInt32 m_NumPasses;\r
+  UInt32 m_NumFastBytes;\r
+  UInt32 m_NumMatchFinderCycles;\r
+  UInt32 m_MemSize;\r
+  UInt32 m_Order;\r
+\r
+  bool m_NumMatchFinderCyclesDefined;\r
+\r
+  bool m_ForceAesMode;\r
+  bool m_IsAesMode;\r
+  Byte m_AesKeyMode;\r
+\r
+  bool m_WriteNtfsTimeExtra;\r
+  bool m_ForceLocal;\r
+  bool m_ForceUtf8;\r
+\r
+  #ifndef _7ZIP_ST\r
+  UInt32 _numThreads;\r
+  #endif\r
+\r
+  DECL_EXTERNAL_CODECS_VARS\r
+\r
+  void InitMethodProperties()\r
+  {\r
+    m_Level = -1;\r
+    m_MainMethod = -1;\r
+    m_Algo =\r
+    m_DicSize =\r
+    m_NumPasses =\r
+    m_NumFastBytes =\r
+    m_Order =\r
+    m_MemSize =\r
+    m_NumMatchFinderCycles = 0xFFFFFFFF;\r
+    m_NumMatchFinderCyclesDefined = false;\r
+    m_ForceAesMode = false;\r
+    m_IsAesMode = false;\r
+    m_AesKeyMode = 3; // aes-256\r
+    m_WriteNtfsTimeExtra = true;\r
+    m_ForceLocal = false;\r
+    m_ForceUtf8 = false;\r
+    #ifndef _7ZIP_ST\r
+    _numThreads = NWindows::NSystem::GetNumberOfProcessors();;\r
+    #endif\r
+  }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
new file mode 100755 (executable)
index 0000000..ceb03cd
--- /dev/null
@@ -0,0 +1,531 @@
+// ZipHandlerOut.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/StringConvert.h"\r
+#include "Common/StringToInt.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../../IPassword.h"\r
+\r
+#include "../../Common/OutBuffer.h"\r
+\r
+#include "../../Crypto/WzAes.h"\r
+\r
+#include "../Common/ItemNameUtils.h"\r
+#include "../Common/ParseProperties.h"\r
+\r
+#include "ZipHandler.h"\r
+#include "ZipUpdate.h"\r
+\r
+using namespace NWindows;\r
+using namespace NCOM;\r
+using namespace NTime;\r
+\r
+namespace NArchive {\r
+namespace NZip {\r
+\r
+static const UInt32 kLzAlgoX1 = 0;\r
+static const UInt32 kLzAlgoX5 = 1;\r
+\r
+static const UInt32 kDeflateNumPassesX1  = 1;\r
+static const UInt32 kDeflateNumPassesX7  = 3;\r
+static const UInt32 kDeflateNumPassesX9  = 10;\r
+\r
+static const UInt32 kDeflateNumFastBytesX1 = 32;\r
+static const UInt32 kDeflateNumFastBytesX7 = 64;\r
+static const UInt32 kDeflateNumFastBytesX9 = 128;\r
+\r
+static const wchar_t *kLzmaMatchFinderX1 = L"HC4";\r
+static const wchar_t *kLzmaMatchFinderX5 = L"BT4";\r
+\r
+static const UInt32 kLzmaNumFastBytesX1 = 32;\r
+static const UInt32 kLzmaNumFastBytesX7 = 64;\r
+\r
+static const UInt32 kLzmaDicSizeX1 = 1 << 16;\r
+static const UInt32 kLzmaDicSizeX3 = 1 << 20;\r
+static const UInt32 kLzmaDicSizeX5 = 1 << 24;\r
+static const UInt32 kLzmaDicSizeX7 = 1 << 25;\r
+static const UInt32 kLzmaDicSizeX9 = 1 << 26;\r
+\r
+static const UInt32 kBZip2NumPassesX1 = 1;\r
+static const UInt32 kBZip2NumPassesX7 = 2;\r
+static const UInt32 kBZip2NumPassesX9 = 7;\r
+\r
+static const UInt32 kBZip2DicSizeX1 = 100000;\r
+static const UInt32 kBZip2DicSizeX3 = 500000;\r
+static const UInt32 kBZip2DicSizeX5 = 900000;\r
+\r
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)\r
+{\r
+  *timeType = NFileTimeType::kDOS;\r
+  return S_OK;\r
+}\r
+\r
+static bool IsAsciiString(const UString &s)\r
+{\r
+  for (int i = 0; i < s.Length(); i++)\r
+  {\r
+    wchar_t c = s[i];\r
+    if (c < 0x20 || c > 0x7F)\r
+      return false;\r
+  }\r
+  return true;\r
+}\r
+\r
+#define COM_TRY_BEGIN2 try {\r
+#define COM_TRY_END2 } \\r
+catch(const CSystemException &e) { return e.ErrorCode; } \\r
+catch(...) { return E_OUTOFMEMORY; }\r
+\r
+static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propID, FILETIME &filetime)\r
+{\r
+  filetime.dwHighDateTime = filetime.dwLowDateTime = 0;\r
+  NCOM::CPropVariant prop;\r
+  RINOK(callback->GetProperty(index, propID, &prop));\r
+  if (prop.vt == VT_FILETIME)\r
+    filetime = prop.filetime;\r
+  else if (prop.vt != VT_EMPTY)\r
+    return E_INVALIDARG;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\r
+    IArchiveUpdateCallback *callback)\r
+{\r
+  COM_TRY_BEGIN2\r
+  CObjectVector<CUpdateItem> updateItems;\r
+  bool thereAreAesUpdates = false;\r
+  for (UInt32 i = 0; i < numItems; i++)\r
+  {\r
+    CUpdateItem ui;\r
+    Int32 newData;\r
+    Int32 newProperties;\r
+    UInt32 indexInArchive;\r
+    if (!callback)\r
+      return E_FAIL;\r
+    RINOK(callback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive));\r
+    ui.NewProperties = IntToBool(newProperties);\r
+    ui.NewData = IntToBool(newData);\r
+    ui.IndexInArchive = indexInArchive;\r
+    ui.IndexInClient = i;\r
+    bool existInArchive = (indexInArchive != (UInt32)-1);\r
+    if (existInArchive && newData)\r
+      if (m_Items[indexInArchive].IsAesEncrypted())\r
+        thereAreAesUpdates = true;\r
+\r
+    if (IntToBool(newProperties))\r
+    {\r
+      UString name;\r
+      {\r
+        NCOM::CPropVariant prop;\r
+        RINOK(callback->GetProperty(i, kpidAttrib, &prop));\r
+        if (prop.vt == VT_EMPTY)\r
+          ui.Attributes = 0;\r
+        else if (prop.vt != VT_UI4)\r
+          return E_INVALIDARG;\r
+        else\r
+          ui.Attributes = prop.ulVal;\r
+      }\r
+\r
+      {\r
+        NCOM::CPropVariant prop;\r
+        RINOK(callback->GetProperty(i, kpidPath, &prop));\r
+        if (prop.vt == VT_EMPTY)\r
+          name.Empty();\r
+        else if (prop.vt != VT_BSTR)\r
+          return E_INVALIDARG;\r
+        else\r
+          name = prop.bstrVal;\r
+      }\r
+      {\r
+        NCOM::CPropVariant prop;\r
+        RINOK(callback->GetProperty(i, kpidIsDir, &prop));\r
+        if (prop.vt == VT_EMPTY)\r
+          ui.IsDir = false;\r
+        else if (prop.vt != VT_BOOL)\r
+          return E_INVALIDARG;\r
+        else\r
+          ui.IsDir = (prop.boolVal != VARIANT_FALSE);\r
+      }\r
+\r
+      {\r
+        CPropVariant prop;\r
+        RINOK(callback->GetProperty(i, kpidTimeType, &prop));\r
+        if (prop.vt == VT_UI4)\r
+          ui.NtfsTimeIsDefined = (prop.ulVal == NFileTimeType::kWindows);\r
+        else\r
+          ui.NtfsTimeIsDefined = m_WriteNtfsTimeExtra;\r
+      }\r
+      RINOK(GetTime(callback, i, kpidMTime, ui.NtfsMTime));\r
+      RINOK(GetTime(callback, i, kpidATime, ui.NtfsATime));\r
+      RINOK(GetTime(callback, i, kpidCTime, ui.NtfsCTime));\r
+\r
+      {\r
+        FILETIME localFileTime = { 0, 0 };\r
+        if (ui.NtfsMTime.dwHighDateTime != 0 ||\r
+            ui.NtfsMTime.dwLowDateTime != 0)\r
+          if (!FileTimeToLocalFileTime(&ui.NtfsMTime, &localFileTime))\r
+            return E_INVALIDARG;\r
+        FileTimeToDosTime(localFileTime, ui.Time);\r
+      }\r
+\r
+      name = NItemName::MakeLegalName(name);\r
+      bool needSlash = ui.IsDir;\r
+      const wchar_t kSlash = L'/';\r
+      if (!name.IsEmpty())\r
+      {\r
+        if (name[name.Length() - 1] == kSlash)\r
+        {\r
+          if (!ui.IsDir)\r
+            return E_INVALIDARG;\r
+          needSlash = false;\r
+        }\r
+      }\r
+      if (needSlash)\r
+        name += kSlash;\r
+\r
+      bool tryUtf8 = true;\r
+      if (m_ForceLocal || !m_ForceUtf8)\r
+      {\r
+        bool defaultCharWasUsed;\r
+        ui.Name = UnicodeStringToMultiByte(name, CP_OEMCP, '_', defaultCharWasUsed);\r
+        tryUtf8 = (!m_ForceLocal && (defaultCharWasUsed ||\r
+          MultiByteToUnicodeString(ui.Name, CP_OEMCP) != name));\r
+      }\r
+\r
+      if (tryUtf8)\r
+      {\r
+        int i;\r
+        for (i = 0; i < name.Length() && (unsigned)name[i] < 0x80; i++);\r
+        ui.IsUtf8 = (i != name.Length());\r
+        if (!ConvertUnicodeToUTF8(name, ui.Name))\r
+          return E_INVALIDARG;\r
+      }\r
+\r
+      if (ui.Name.Length() >= (1 << 16))\r
+        return E_INVALIDARG;\r
+\r
+      ui.IndexInClient = i;\r
+      /*\r
+      if (existInArchive)\r
+      {\r
+        const CItemEx &itemInfo = m_Items[indexInArchive];\r
+        // ui.Commented = itemInfo.IsCommented();\r
+        ui.Commented = false;\r
+        if (ui.Commented)\r
+        {\r
+          ui.CommentRange.Position = itemInfo.GetCommentPosition();\r
+          ui.CommentRange.Size  = itemInfo.CommentSize;\r
+        }\r
+      }\r
+      else\r
+        ui.Commented = false;\r
+      */\r
+    }\r
+    if (IntToBool(newData))\r
+    {\r
+      UInt64 size;\r
+      {\r
+        NCOM::CPropVariant prop;\r
+        RINOK(callback->GetProperty(i, kpidSize, &prop));\r
+        if (prop.vt != VT_UI8)\r
+          return E_INVALIDARG;\r
+        size = prop.uhVal.QuadPart;\r
+      }\r
+      ui.Size = size;\r
+    }\r
+    updateItems.Add(ui);\r
+  }\r
+\r
+  CMyComPtr<ICryptoGetTextPassword2> getTextPassword;\r
+  {\r
+    CMyComPtr<IArchiveUpdateCallback> udateCallBack2(callback);\r
+    udateCallBack2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword);\r
+  }\r
+  CCompressionMethodMode options;\r
+\r
+  if (getTextPassword)\r
+  {\r
+    CMyComBSTR password;\r
+    Int32 passwordIsDefined;\r
+    RINOK(getTextPassword->CryptoGetTextPassword2(&passwordIsDefined, &password));\r
+    options.PasswordIsDefined = IntToBool(passwordIsDefined);\r
+    if (options.PasswordIsDefined)\r
+    {\r
+      options.IsAesMode = (m_ForceAesMode ? m_IsAesMode : thereAreAesUpdates);\r
+      options.AesKeyMode = m_AesKeyMode;\r
+\r
+      if (!IsAsciiString((const wchar_t *)password))\r
+        return E_INVALIDARG;\r
+      if (options.IsAesMode)\r
+      {\r
+        if (options.Password.Length() > NCrypto::NWzAes::kPasswordSizeMax)\r
+          return E_INVALIDARG;\r
+      }\r
+      options.Password = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP);\r
+    }\r
+  }\r
+  else\r
+    options.PasswordIsDefined = false;\r
+\r
+  int level = m_Level;\r
+  if (level < 0)\r
+    level = 5;\r
+  \r
+  Byte mainMethod;\r
+  if (m_MainMethod < 0)\r
+    mainMethod = (Byte)(((level == 0) ?\r
+        NFileHeader::NCompressionMethod::kStored :\r
+        NFileHeader::NCompressionMethod::kDeflated));\r
+  else\r
+    mainMethod = (Byte)m_MainMethod;\r
+  options.MethodSequence.Add(mainMethod);\r
+  if (mainMethod != NFileHeader::NCompressionMethod::kStored)\r
+    options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStored);\r
+  bool isDeflate = (mainMethod == NFileHeader::NCompressionMethod::kDeflated) ||\r
+      (mainMethod == NFileHeader::NCompressionMethod::kDeflated64);\r
+  bool isLZMA = (mainMethod == NFileHeader::NCompressionMethod::kLZMA);\r
+  bool isLz = (isLZMA || isDeflate);\r
+  options.NumPasses = m_NumPasses;\r
+  options.DicSize = m_DicSize;\r
+  options.NumFastBytes = m_NumFastBytes;\r
+  options.NumMatchFinderCycles = m_NumMatchFinderCycles;\r
+  options.NumMatchFinderCyclesDefined = m_NumMatchFinderCyclesDefined;\r
+  options.Algo = m_Algo;\r
+  options.MemSize = m_MemSize;\r
+  options.Order = m_Order;\r
+  #ifndef _7ZIP_ST\r
+  options.NumThreads = _numThreads;\r
+  #endif\r
+  if (isLz)\r
+  {\r
+    if (isDeflate)\r
+    {\r
+      if (options.NumPasses == 0xFFFFFFFF)\r
+        options.NumPasses = (level >= 9 ? kDeflateNumPassesX9 :\r
+                            (level >= 7 ? kDeflateNumPassesX7 :\r
+                                          kDeflateNumPassesX1));\r
+      if (options.NumFastBytes == 0xFFFFFFFF)\r
+        options.NumFastBytes = (level >= 9 ? kDeflateNumFastBytesX9 :\r
+                               (level >= 7 ? kDeflateNumFastBytesX7 :\r
+                                             kDeflateNumFastBytesX1));\r
+    }\r
+    else if (isLZMA)\r
+    {\r
+      if (options.DicSize == 0xFFFFFFFF)\r
+        options.DicSize =\r
+          (level >= 9 ? kLzmaDicSizeX9 :\r
+          (level >= 7 ? kLzmaDicSizeX7 :\r
+          (level >= 5 ? kLzmaDicSizeX5 :\r
+          (level >= 3 ? kLzmaDicSizeX3 :\r
+                        kLzmaDicSizeX1))));\r
+\r
+      if (options.NumFastBytes == 0xFFFFFFFF)\r
+        options.NumFastBytes = (level >= 7 ? kLzmaNumFastBytesX7 :\r
+                                             kLzmaNumFastBytesX1);\r
+\r
+      options.MatchFinder =\r
+        (level >= 5 ? kLzmaMatchFinderX5 :\r
+                      kLzmaMatchFinderX1);\r
+    }\r
+\r
+    if (options.Algo == 0xFFFFFFFF)\r
+        options.Algo = (level >= 5 ? kLzAlgoX5 :\r
+                                     kLzAlgoX1);\r
+  }\r
+  if (mainMethod == NFileHeader::NCompressionMethod::kBZip2)\r
+  {\r
+    if (options.NumPasses == 0xFFFFFFFF)\r
+      options.NumPasses = (level >= 9 ? kBZip2NumPassesX9 :\r
+                          (level >= 7 ? kBZip2NumPassesX7 :\r
+                                        kBZip2NumPassesX1));\r
+    if (options.DicSize == 0xFFFFFFFF)\r
+      options.DicSize = (level >= 5 ? kBZip2DicSizeX5 :\r
+                        (level >= 3 ? kBZip2DicSizeX3 :\r
+                                      kBZip2DicSizeX1));\r
+  }\r
+  if (mainMethod == NFileHeader::NCompressionMethod::kPPMd)\r
+  {\r
+    int level2 = level;\r
+    if (level2 < 1) level2 = 1;\r
+    if (level2 > 9) level2 = 9;\r
+\r
+    if (options.MemSize == 0xFFFFFFFF)\r
+      options.MemSize = (1 << (19 + (level2 > 8 ? 8 : level2)));\r
+\r
+    if (options.Order == 0xFFFFFFFF)\r
+      options.Order = 3 + level2;\r
+\r
+    if (options.Algo == 0xFFFFFFFF)\r
+      options.Algo = (level2 >= 7 ? 1 : 0);\r
+  }\r
+\r
+  return Update(\r
+      EXTERNAL_CODECS_VARS\r
+      m_Items, updateItems, outStream,\r
+      m_Archive.IsOpen() ? &m_Archive : NULL, &options, callback);\r
+  COM_TRY_END2\r
+}\r
+\r
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)\r
+{\r
+  #ifndef _7ZIP_ST\r
+  const UInt32 numProcessors = NSystem::GetNumberOfProcessors();\r
+  _numThreads = numProcessors;\r
+  #endif\r
+  InitMethodProperties();\r
+  for (int i = 0; i < numProperties; i++)\r
+  {\r
+    UString name = UString(names[i]);\r
+    name.MakeUpper();\r
+    if (name.IsEmpty())\r
+      return E_INVALIDARG;\r
+\r
+    const PROPVARIANT &prop = values[i];\r
+\r
+    if (name[0] == L'X')\r
+    {\r
+      UInt32 level = 9;\r
+      RINOK(ParsePropValue(name.Mid(1), prop, level));\r
+      m_Level = level;\r
+      continue;\r
+    }\r
+    else if (name == L"M")\r
+    {\r
+      if (prop.vt == VT_BSTR)\r
+      {\r
+        UString m = prop.bstrVal;\r
+        m.MakeUpper();\r
+        if (m == L"COPY") m_MainMethod = NFileHeader::NCompressionMethod::kStored;\r
+        else if (m == L"DEFLATE") m_MainMethod = NFileHeader::NCompressionMethod::kDeflated;\r
+        else if (m == L"DEFLATE64") m_MainMethod = NFileHeader::NCompressionMethod::kDeflated64;\r
+        else if (m == L"BZIP2") m_MainMethod = NFileHeader::NCompressionMethod::kBZip2;\r
+        else if (m == L"LZMA") m_MainMethod = NFileHeader::NCompressionMethod::kLZMA;\r
+        else if (m == L"PPMD") m_MainMethod = NFileHeader::NCompressionMethod::kPPMd;\r
+        else return E_INVALIDARG;\r
+      }\r
+      else if (prop.vt == VT_UI4)\r
+      {\r
+        switch(prop.ulVal)\r
+        {\r
+          case NFileHeader::NCompressionMethod::kStored:\r
+          case NFileHeader::NCompressionMethod::kDeflated:\r
+          case NFileHeader::NCompressionMethod::kDeflated64:\r
+          case NFileHeader::NCompressionMethod::kBZip2:\r
+          case NFileHeader::NCompressionMethod::kLZMA:\r
+            m_MainMethod = (Byte)prop.ulVal;\r
+            break;\r
+          default:\r
+            return E_INVALIDARG;\r
+        }\r
+      }\r
+      else\r
+        return E_INVALIDARG;\r
+    }\r
+    else if (name.Left(2) == L"EM")\r
+    {\r
+      if (prop.vt == VT_BSTR)\r
+      {\r
+        UString valueString = prop.bstrVal;\r
+        valueString.MakeUpper();\r
+        if (valueString.Left(3) == L"AES")\r
+        {\r
+          valueString = valueString.Mid(3);\r
+          if (valueString == L"128")\r
+            m_AesKeyMode = 1;\r
+          else if (valueString == L"192")\r
+            m_AesKeyMode = 2;\r
+          else if (valueString == L"256" || valueString.IsEmpty())\r
+            m_AesKeyMode = 3;\r
+          else\r
+            return E_INVALIDARG;\r
+          m_IsAesMode = true;\r
+          m_ForceAesMode = true;\r
+        }\r
+        else if (valueString == L"ZIPCRYPTO")\r
+        {\r
+          m_IsAesMode = false;\r
+          m_ForceAesMode = true;\r
+        }\r
+        else\r
+          return E_INVALIDARG;\r
+      }\r
+      else\r
+        return E_INVALIDARG;\r
+    }\r
+    else if (name[0] == L'D')\r
+    {\r
+      UInt32 dicSize = kBZip2DicSizeX5;\r
+      RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize));\r
+      m_DicSize = dicSize;\r
+    }\r
+    else if (name.Left(3) == L"MEM")\r
+    {\r
+      UInt32 memSize = 1 << 24;\r
+      RINOK(ParsePropDictionaryValue(name.Mid(3), prop, memSize));\r
+      m_MemSize = memSize;\r
+    }\r
+    else if (name[0] == L'O')\r
+    {\r
+      UInt32 order = 8;\r
+      RINOK(ParsePropValue(name.Mid(1), prop, order));\r
+      m_Order = order;\r
+    }\r
+    else if (name.Left(4) == L"PASS")\r
+    {\r
+      UInt32 num = kDeflateNumPassesX9;\r
+      RINOK(ParsePropValue(name.Mid(4), prop, num));\r
+      m_NumPasses = num;\r
+    }\r
+    else if (name.Left(2) == L"FB")\r
+    {\r
+      UInt32 num = kDeflateNumFastBytesX9;\r
+      RINOK(ParsePropValue(name.Mid(2), prop, num));\r
+      m_NumFastBytes = num;\r
+    }\r
+    else if (name.Left(2) == L"MC")\r
+    {\r
+      UInt32 num = 0xFFFFFFFF;\r
+      RINOK(ParsePropValue(name.Mid(2), prop, num));\r
+      m_NumMatchFinderCycles = num;\r
+      m_NumMatchFinderCyclesDefined = true;\r
+    }\r
+    else if (name.Left(2) == L"MT")\r
+    {\r
+      #ifndef _7ZIP_ST\r
+      RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads));\r
+      #endif\r
+    }\r
+    else if (name.Left(1) == L"A")\r
+    {\r
+      UInt32 num = kLzAlgoX5;\r
+      RINOK(ParsePropValue(name.Mid(1), prop, num));\r
+      m_Algo = num;\r
+    }\r
+    else if (name.CompareNoCase(L"TC") == 0)\r
+    {\r
+      RINOK(SetBoolProperty(m_WriteNtfsTimeExtra, prop));\r
+    }\r
+    else if (name.CompareNoCase(L"CL") == 0)\r
+    {\r
+      RINOK(SetBoolProperty(m_ForceLocal, prop));\r
+      if (m_ForceLocal)\r
+        m_ForceUtf8 = false;\r
+    }\r
+    else if (name.CompareNoCase(L"CU") == 0)\r
+    {\r
+      RINOK(SetBoolProperty(m_ForceUtf8, prop));\r
+      if (m_ForceUtf8)\r
+        m_ForceLocal = false;\r
+    }\r
+    else\r
+      return E_INVALIDARG;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Zip/ZipHeader.cpp b/CPP/7zip/Archive/Zip/ZipHeader.cpp
new file mode 100755 (executable)
index 0000000..27fe244
--- /dev/null
@@ -0,0 +1,36 @@
+// Archive/Zip/Header.h\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "ZipHeader.h"\r
+\r
+namespace NArchive {\r
+namespace NZip {\r
+\r
+namespace NSignature\r
+{\r
+  UInt32 kLocalFileHeader   = 0x04034B50 + 1;\r
+  UInt32 kDataDescriptor    = 0x08074B50 + 1;\r
+  UInt32 kCentralFileHeader = 0x02014B50 + 1;\r
+  UInt32 kEndOfCentralDir   = 0x06054B50 + 1;\r
+  UInt32 kZip64EndOfCentralDir   = 0x06064B50 + 1;\r
+  UInt32 kZip64EndOfCentralDirLocator   = 0x07064B50 + 1;\r
+  \r
+  class CMarkersInitializer\r
+  {\r
+  public:\r
+    CMarkersInitializer()\r
+    {\r
+      kLocalFileHeader--;\r
+      kDataDescriptor--;\r
+      kCentralFileHeader--;\r
+      kEndOfCentralDir--;\r
+      kZip64EndOfCentralDir--;\r
+      kZip64EndOfCentralDirLocator--;\r
+    }\r
+  };\r
+  static CMarkersInitializer g_MarkerInitializer;\r
+}\r
+\r
+}}\r
+\r
diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h
new file mode 100755 (executable)
index 0000000..4989daf
--- /dev/null
@@ -0,0 +1,284 @@
+// Archive/Zip/Header.h\r
+\r
+#ifndef __ARCHIVE_ZIP_HEADER_H\r
+#define __ARCHIVE_ZIP_HEADER_H\r
+\r
+#include "Common/Types.h"\r
+\r
+namespace NArchive {\r
+namespace NZip {\r
+\r
+namespace NSignature\r
+{\r
+  extern UInt32 kLocalFileHeader;\r
+  extern UInt32 kDataDescriptor;\r
+  extern UInt32 kCentralFileHeader;\r
+  extern UInt32 kEndOfCentralDir;\r
+  extern UInt32 kZip64EndOfCentralDir;\r
+  extern UInt32 kZip64EndOfCentralDirLocator;\r
+  \r
+  static const UInt32 kMarkerSize = 4;\r
+}\r
+\r
+const UInt32 kEcdSize = 22;\r
+const UInt32 kZip64EcdSize = 44;\r
+const UInt32 kZip64EcdLocatorSize = 20;\r
+/*\r
+struct CEndOfCentralDirectoryRecord\r
+{\r
+  UInt16 ThisDiskNumber;\r
+  UInt16 StartCentralDirectoryDiskNumber;\r
+  UInt16 NumEntriesInCentaralDirectoryOnThisDisk;\r
+  UInt16 NumEntriesInCentaralDirectory;\r
+  UInt32 CentralDirectorySize;\r
+  UInt32 CentralDirectoryStartOffset;\r
+  UInt16 CommentSize;\r
+};\r
+\r
+struct CEndOfCentralDirectoryRecordFull\r
+{\r
+  UInt32 Signature;\r
+  CEndOfCentralDirectoryRecord Header;\r
+};\r
+*/\r
+\r
+namespace NFileHeader\r
+{\r
+  /*\r
+  struct CVersion\r
+  {\r
+    Byte Version;\r
+    Byte HostOS;\r
+  };\r
+  */\r
+  \r
+  namespace NCompressionMethod\r
+  {\r
+    enum EType\r
+    {\r
+      kStored = 0,\r
+      kShrunk = 1,\r
+      kReduced1 = 2,\r
+      kReduced2 = 3,\r
+      kReduced3 = 4,\r
+      kReduced4 = 5,\r
+      kImploded = 6,\r
+      kReservedTokenizing = 7, // reserved for tokenizing\r
+      kDeflated = 8,\r
+      kDeflated64 = 9,\r
+      kPKImploding = 10,\r
+      \r
+      kBZip2 = 12,\r
+      kLZMA = 14,\r
+      kTerse = 18,\r
+      kLz77 = 19,\r
+      kJpeg = 0x60,\r
+      kWavPack = 0x61,\r
+      kPPMd = 0x62,\r
+      kWzAES = 0x63\r
+    };\r
+    const int kNumCompressionMethods = 11;\r
+    const Byte kMadeByProgramVersion = 63;\r
+    \r
+    const Byte kExtractVersion_Default = 10;\r
+    const Byte kExtractVersion_Dir = 20;\r
+    const Byte kExtractVersion_ZipCrypto = 20;\r
+    const Byte kExtractVersion_Deflate = 20;\r
+    const Byte kExtractVersion_Deflate64 = 21;\r
+    const Byte kExtractVersion_Zip64 = 45;\r
+    const Byte kExtractVersion_BZip2 = 46;\r
+    const Byte kExtractVersion_Aes = 51;\r
+    const Byte kExtractVersion_LZMA = 63;\r
+    const Byte kExtractVersion_PPMd = 63;\r
+    \r
+    // const Byte kSupportedVersion   = 20;\r
+  }\r
+\r
+  namespace NExtraID\r
+  {\r
+    enum\r
+    {\r
+      kZip64 = 0x01,\r
+      kNTFS = 0x0A,\r
+      kStrongEncrypt = 0x17,\r
+      kUnixTime = 0x5455,\r
+      kWzAES = 0x9901\r
+    };\r
+  }\r
+\r
+  namespace NNtfsExtra\r
+  {\r
+    const UInt16 kTagTime = 1;\r
+    enum\r
+    {\r
+      kMTime = 0,\r
+      kATime,\r
+      kCTime\r
+    };\r
+  }\r
+\r
+  namespace NUnixTime\r
+  {\r
+    enum\r
+    {\r
+      kMTime = 0,\r
+      kATime,\r
+      kCTime\r
+    };\r
+  }\r
+\r
+  const UInt32 kLocalBlockSize = 26;\r
+  /*\r
+  struct CLocalBlock\r
+  {\r
+    CVersion ExtractVersion;\r
+    \r
+    UInt16 Flags;\r
+    UInt16 CompressionMethod;\r
+    UInt32 Time;\r
+    UInt32 FileCRC;\r
+    UInt32 PackSize;\r
+    UInt32 UnPackSize;\r
+    UInt16 NameSize;\r
+    UInt16 ExtraSize;\r
+  };\r
+  */\r
+\r
+  const UInt32 kDataDescriptorSize = 16;\r
+  // const UInt32 kDataDescriptor64Size = 16 + 8;\r
+  /*\r
+  struct CDataDescriptor\r
+  {\r
+    UInt32 Signature;\r
+    UInt32 FileCRC;\r
+    UInt32 PackSize;\r
+    UInt32 UnPackSize;\r
+  };\r
+\r
+  struct CLocalBlockFull\r
+  {\r
+    UInt32 Signature;\r
+    CLocalBlock Header;\r
+  };\r
+  */\r
+  \r
+  const UInt32 kCentralBlockSize = 42;\r
+  /*\r
+  struct CBlock\r
+  {\r
+    CVersion MadeByVersion;\r
+    CVersion ExtractVersion;\r
+    UInt16 Flags;\r
+    UInt16 CompressionMethod;\r
+    UInt32 Time;\r
+    UInt32 FileCRC;\r
+    UInt32 PackSize;\r
+    UInt32 UnPackSize;\r
+    UInt16 NameSize;\r
+    UInt16 ExtraSize;\r
+    UInt16 CommentSize;\r
+    UInt16 DiskNumberStart;\r
+    UInt16 InternalAttributes;\r
+    UInt32 ExternalAttributes;\r
+    UInt32 LocalHeaderOffset;\r
+  };\r
+  \r
+  struct CBlockFull\r
+  {\r
+    UInt32 Signature;\r
+    CBlock Header;\r
+  };\r
+  */\r
+\r
+  namespace NFlags\r
+  {\r
+    const int kEncrypted = 1 << 0;\r
+    const int kLzmaEOS = 1 << 1;\r
+    const int kDescriptorUsedMask = 1 << 3;\r
+    const int kStrongEncrypted = 1 << 6;\r
+    const int kUtf8 = 1 << 11;\r
+\r
+    const int kImplodeDictionarySizeMask = 1 << 1;\r
+    const int kImplodeLiteralsOnMask     = 1 << 2;\r
+    \r
+    const int kDeflateTypeBitStart = 1;\r
+    const int kNumDeflateTypeBits = 2;\r
+    const int kNumDeflateTypes = (1 << kNumDeflateTypeBits);\r
+    const int kDeflateTypeMask = (1 << kNumDeflateTypeBits) - 1;\r
+  }\r
+  \r
+  namespace NHostOS\r
+  {\r
+    enum EEnum\r
+    {\r
+        kFAT      = 0,\r
+        kAMIGA    = 1,\r
+        kVMS      = 2,  // VAX/VMS\r
+        kUnix     = 3,\r
+        kVM_CMS   = 4,\r
+        kAtari    = 5,  // what if it's a minix filesystem? [cjh]\r
+        kHPFS     = 6,  // filesystem used by OS/2 (and NT 3.x)\r
+        kMac      = 7,\r
+        kZ_System = 8,\r
+        kCPM      = 9,\r
+        kTOPS20   = 10, // pkzip 2.50 NTFS\r
+        kNTFS     = 11, // filesystem used by Windows NT\r
+        kQDOS     = 12, // SMS/QDOS\r
+        kAcorn    = 13, // Archimedes Acorn RISC OS\r
+        kVFAT     = 14, // filesystem used by Windows 95, NT\r
+        kMVS      = 15,\r
+        kBeOS     = 16, // hybrid POSIX/database filesystem\r
+        kTandem   = 17,\r
+        kOS400    = 18,\r
+        kOSX      = 19\r
+    };\r
+  }\r
+  namespace NUnixAttribute\r
+  {\r
+    const UInt32 kIFMT   =   0170000;     /* Unix file type mask */\r
+    \r
+    const UInt32 kIFDIR  =   0040000;     /* Unix directory */\r
+    const UInt32 kIFREG  =   0100000;     /* Unix regular file */\r
+    const UInt32 kIFSOCK =   0140000;     /* Unix socket (BSD, not SysV or Amiga) */\r
+    const UInt32 kIFLNK  =   0120000;     /* Unix symbolic link (not SysV, Amiga) */\r
+    const UInt32 kIFBLK  =   0060000;     /* Unix block special       (not Amiga) */\r
+    const UInt32 kIFCHR  =   0020000;     /* Unix character special   (not Amiga) */\r
+    const UInt32 kIFIFO  =   0010000;     /* Unix fifo    (BCC, not MSC or Amiga) */\r
+    \r
+    const UInt32 kISUID  =   04000;       /* Unix set user id on execution */\r
+    const UInt32 kISGID  =   02000;       /* Unix set group id on execution */\r
+    const UInt32 kISVTX  =   01000;       /* Unix directory permissions control */\r
+    const UInt32 kENFMT  =   kISGID;   /* Unix record locking enforcement flag */\r
+    const UInt32 kIRWXU  =   00700;       /* Unix read, write, execute: owner */\r
+    const UInt32 kIRUSR  =   00400;       /* Unix read permission: owner */\r
+    const UInt32 kIWUSR  =   00200;       /* Unix write permission: owner */\r
+    const UInt32 kIXUSR  =   00100;       /* Unix execute permission: owner */\r
+    const UInt32 kIRWXG  =   00070;       /* Unix read, write, execute: group */\r
+    const UInt32 kIRGRP  =   00040;       /* Unix read permission: group */\r
+    const UInt32 kIWGRP  =   00020;       /* Unix write permission: group */\r
+    const UInt32 kIXGRP  =   00010;       /* Unix execute permission: group */\r
+    const UInt32 kIRWXO  =   00007;       /* Unix read, write, execute: other */\r
+    const UInt32 kIROTH  =   00004;       /* Unix read permission: other */\r
+    const UInt32 kIWOTH  =   00002;       /* Unix write permission: other */\r
+    const UInt32 kIXOTH  =   00001;       /* Unix execute permission: other */\r
+  }\r
+  \r
+  namespace NAmigaAttribute\r
+  {\r
+    const UInt32 kIFMT     = 06000;       /* Amiga file type mask */\r
+    const UInt32 kIFDIR    = 04000;       /* Amiga directory */\r
+    const UInt32 kIFREG    = 02000;       /* Amiga regular file */\r
+    const UInt32 kIHIDDEN  = 00200;       /* to be supported in AmigaDOS 3.x */\r
+    const UInt32 kISCRIPT  = 00100;       /* executable script (text command file) */\r
+    const UInt32 kIPURE    = 00040;       /* allow loading into resident memory */\r
+    const UInt32 kIARCHIVE = 00020;       /* not modified since bit was last set */\r
+    const UInt32 kIREAD    = 00010;       /* can be opened for reading */\r
+    const UInt32 kIWRITE   = 00004;       /* can be opened for writing */\r
+    const UInt32 kIEXECUTE = 00002;       /* executable image, a loadable runfile */\r
+    const UInt32 kIDELETE  = 00001;      /* can be deleted */\r
+  }\r
+}\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp
new file mode 100755 (executable)
index 0000000..639efd0
--- /dev/null
@@ -0,0 +1,893 @@
+// Archive/ZipIn.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/CpuArch.h"\r
+\r
+#include "Common/DynamicBuffer.h"\r
+\r
+#include "../../Common/LimitedStreams.h"\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "ZipIn.h"\r
+\r
+#define Get16(p) GetUi16(p)\r
+#define Get32(p) GetUi32(p)\r
+#define Get64(p) GetUi64(p)\r
+\r
+namespace NArchive {\r
+namespace NZip {\r
\r
+HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit)\r
+{\r
+  _inBufMode = false;\r
+  Close();\r
+  RINOK(stream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition));\r
+  m_Position = m_StreamStartPosition;\r
+  RINOK(FindAndReadMarker(stream, searchHeaderSizeLimit));\r
+  RINOK(stream->Seek(m_Position, STREAM_SEEK_SET, NULL));\r
+  m_Stream = stream;\r
+  return S_OK;\r
+}\r
+\r
+void CInArchive::Close()\r
+{\r
+  _inBuffer.ReleaseStream();\r
+  m_Stream.Release();\r
+}\r
+\r
+HRESULT CInArchive::Seek(UInt64 offset)\r
+{\r
+  return m_Stream->Seek(offset, STREAM_SEEK_SET, NULL);\r
+}\r
+\r
+//////////////////////////////////////\r
+// Markers\r
+\r
+static inline bool TestMarkerCandidate(const Byte *p, UInt32 &value)\r
+{\r
+  value = Get32(p);\r
+  return\r
+    (value == NSignature::kLocalFileHeader) ||\r
+    (value == NSignature::kEndOfCentralDir);\r
+}\r
+\r
+static const UInt32 kNumMarkerAddtionalBytes = 2;\r
+static inline bool TestMarkerCandidate2(const Byte *p, UInt32 &value)\r
+{\r
+  value = Get32(p);\r
+  if (value == NSignature::kEndOfCentralDir)\r
+    return (Get16(p + 4) == 0);\r
+  return (value == NSignature::kLocalFileHeader && p[4] < 128);\r
+}\r
+\r
+HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit)\r
+{\r
+  ArcInfo.Clear();\r
+  m_Position = m_StreamStartPosition;\r
+\r
+  Byte marker[NSignature::kMarkerSize];\r
+  RINOK(ReadStream_FALSE(stream, marker, NSignature::kMarkerSize));\r
+  m_Position += NSignature::kMarkerSize;\r
+  if (TestMarkerCandidate(marker, m_Signature))\r
+    return S_OK;\r
+\r
+  CByteDynamicBuffer dynamicBuffer;\r
+  const UInt32 kSearchMarkerBufferSize = 0x10000;\r
+  dynamicBuffer.EnsureCapacity(kSearchMarkerBufferSize);\r
+  Byte *buffer = dynamicBuffer;\r
+  UInt32 numBytesPrev = NSignature::kMarkerSize - 1;\r
+  memcpy(buffer, marker + 1, numBytesPrev);\r
+  UInt64 curTestPos = m_StreamStartPosition + 1;\r
+  for (;;)\r
+  {\r
+    if (searchHeaderSizeLimit != NULL)\r
+      if (curTestPos - m_StreamStartPosition > *searchHeaderSizeLimit)\r
+        break;\r
+    size_t numReadBytes = kSearchMarkerBufferSize - numBytesPrev;\r
+    RINOK(ReadStream(stream, buffer + numBytesPrev, &numReadBytes));\r
+    m_Position += numReadBytes;\r
+    UInt32 numBytesInBuffer = numBytesPrev + (UInt32)numReadBytes;\r
+    const UInt32 kMarker2Size = NSignature::kMarkerSize + kNumMarkerAddtionalBytes;\r
+    if (numBytesInBuffer < kMarker2Size)\r
+      break;\r
+    UInt32 numTests = numBytesInBuffer - kMarker2Size + 1;\r
+    for (UInt32 pos = 0; pos < numTests; pos++)\r
+    {\r
+      if (buffer[pos] != 0x50)\r
+        continue;\r
+      if (TestMarkerCandidate2(buffer + pos, m_Signature))\r
+      {\r
+        curTestPos += pos;\r
+        ArcInfo.StartPosition = curTestPos;\r
+        m_Position = curTestPos + NSignature::kMarkerSize;\r
+        return S_OK;\r
+      }\r
+    }\r
+    curTestPos += numTests;\r
+    numBytesPrev = numBytesInBuffer - numTests;\r
+    memmove(buffer, buffer + numTests, numBytesPrev);\r
+  }\r
+  return S_FALSE;\r
+}\r
+\r
+HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  size_t realProcessedSize = size;\r
+  HRESULT result = S_OK;\r
+  if (_inBufMode)\r
+  {\r
+    try { realProcessedSize = _inBuffer.ReadBytes((Byte *)data, size); }\r
+    catch (const CInBufferException &e) { return e.ErrorCode; }\r
+  }\r
+  else\r
+    result = ReadStream(m_Stream, data, &realProcessedSize);\r
+  if (processedSize != NULL)\r
+    *processedSize = (UInt32)realProcessedSize;\r
+  m_Position += realProcessedSize;\r
+  return result;\r
+}\r
+\r
+void CInArchive::Skip(UInt64 num)\r
+{\r
+  for (UInt64 i = 0; i < num; i++)\r
+    ReadByte();\r
+}\r
+\r
+void CInArchive::IncreaseRealPosition(UInt64 addValue)\r
+{\r
+  if (m_Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position) != S_OK)\r
+    throw CInArchiveException(CInArchiveException::kSeekStreamError);\r
+}\r
+\r
+bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size)\r
+{\r
+  UInt32 realProcessedSize;\r
+  if (ReadBytes(data, size, &realProcessedSize) != S_OK)\r
+    throw CInArchiveException(CInArchiveException::kReadStreamError);\r
+  return (realProcessedSize == size);\r
+}\r
+\r
+void CInArchive::SafeReadBytes(void *data, UInt32 size)\r
+{\r
+  if (!ReadBytesAndTestSize(data, size))\r
+    throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);\r
+}\r
+\r
+void CInArchive::ReadBuffer(CByteBuffer &buffer, UInt32 size)\r
+{\r
+  buffer.SetCapacity(size);\r
+  if (size > 0)\r
+    SafeReadBytes(buffer, size);\r
+}\r
+\r
+Byte CInArchive::ReadByte()\r
+{\r
+  Byte b;\r
+  SafeReadBytes(&b, 1);\r
+  return b;\r
+}\r
+\r
+UInt16 CInArchive::ReadUInt16()\r
+{\r
+  Byte buf[2];\r
+  SafeReadBytes(buf, 2);\r
+  return Get16(buf);\r
+}\r
+\r
+UInt32 CInArchive::ReadUInt32()\r
+{\r
+  Byte buf[4];\r
+  SafeReadBytes(buf, 4);\r
+  return Get32(buf);\r
+}\r
+\r
+UInt64 CInArchive::ReadUInt64()\r
+{\r
+  Byte buf[8];\r
+  SafeReadBytes(buf, 8);\r
+  return Get64(buf);\r
+}\r
+\r
+bool CInArchive::ReadUInt32(UInt32 &value)\r
+{\r
+  Byte buf[4];\r
+  if (!ReadBytesAndTestSize(buf, 4))\r
+    return false;\r
+  value = Get32(buf);\r
+  return true;\r
+}\r
+\r
+void CInArchive::ReadFileName(UInt32 nameSize, AString &dest)\r
+{\r
+  if (nameSize == 0)\r
+    dest.Empty();\r
+  char *p = dest.GetBuffer((int)nameSize);\r
+  SafeReadBytes(p, nameSize);\r
+  p[nameSize] = 0;\r
+  dest.ReleaseBuffer();\r
+}\r
+\r
+void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock,\r
+    UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber)\r
+{\r
+  extraBlock.Clear();\r
+  UInt32 remain = extraSize;\r
+  while(remain >= 4)\r
+  {\r
+    CExtraSubBlock subBlock;\r
+    subBlock.ID = ReadUInt16();\r
+    UInt32 dataSize = ReadUInt16();\r
+    remain -= 4;\r
+    if (dataSize > remain) // it's bug\r
+      dataSize = remain;\r
+    if (subBlock.ID == NFileHeader::NExtraID::kZip64)\r
+    {\r
+      if (unpackSize == 0xFFFFFFFF)\r
+      {\r
+        if (dataSize < 8)\r
+          break;\r
+        unpackSize = ReadUInt64();\r
+        remain -= 8;\r
+        dataSize -= 8;\r
+      }\r
+      if (packSize == 0xFFFFFFFF)\r
+      {\r
+        if (dataSize < 8)\r
+          break;\r
+        packSize = ReadUInt64();\r
+        remain -= 8;\r
+        dataSize -= 8;\r
+      }\r
+      if (localHeaderOffset == 0xFFFFFFFF)\r
+      {\r
+        if (dataSize < 8)\r
+          break;\r
+        localHeaderOffset = ReadUInt64();\r
+        remain -= 8;\r
+        dataSize -= 8;\r
+      }\r
+      if (diskStartNumber == 0xFFFF)\r
+      {\r
+        if (dataSize < 4)\r
+          break;\r
+        diskStartNumber = ReadUInt32();\r
+        remain -= 4;\r
+        dataSize -= 4;\r
+      }\r
+      for (UInt32 i = 0; i < dataSize; i++)\r
+        ReadByte();\r
+    }\r
+    else\r
+    {\r
+      ReadBuffer(subBlock.Data, dataSize);\r
+      extraBlock.SubBlocks.Add(subBlock);\r
+    }\r
+    remain -= dataSize;\r
+  }\r
+  Skip(remain);\r
+}\r
+\r
+HRESULT CInArchive::ReadLocalItem(CItemEx &item)\r
+{\r
+  const int kBufSize = 26;\r
+  Byte p[kBufSize];\r
+  SafeReadBytes(p, kBufSize);\r
+\r
+  item.ExtractVersion.Version = p[0];\r
+  item.ExtractVersion.HostOS = p[1];\r
+  item.Flags = Get16(p + 2);\r
+  item.CompressionMethod = Get16(p + 4);\r
+  item.Time = Get32(p + 6);\r
+  item.FileCRC = Get32(p + 10);\r
+  item.PackSize = Get32(p + 14);\r
+  item.UnPackSize = Get32(p + 18);\r
+  UInt32 fileNameSize = Get16(p + 22);\r
+  item.LocalExtraSize = Get16(p + 24);\r
+  ReadFileName(fileNameSize, item.Name);\r
+  item.FileHeaderWithNameSize = 4 + NFileHeader::kLocalBlockSize + fileNameSize;\r
+  if (item.LocalExtraSize > 0)\r
+  {\r
+    UInt64 localHeaderOffset = 0;\r
+    UInt32 diskStartNumber = 0;\r
+    ReadExtra(item.LocalExtraSize, item.LocalExtra, item.UnPackSize, item.PackSize,\r
+      localHeaderOffset, diskStartNumber);\r
+  }\r
+  /*\r
+  if (item.IsDir())\r
+    item.UnPackSize = 0;       // check It\r
+  */\r
+  return S_OK;\r
+}\r
+\r
+static bool FlagsAreSame(CItem &i1, CItem &i2)\r
+{\r
+  if (i1.CompressionMethod != i2.CompressionMethod)\r
+    return false;\r
+  // i1.Time\r
+\r
+  if (i1.Flags == i2.Flags)\r
+    return true;\r
+  UInt32 mask = 0xFFFF;\r
+  switch(i1.CompressionMethod)\r
+  {\r
+    case NFileHeader::NCompressionMethod::kDeflated:\r
+      mask = 0x7FF9;\r
+      break;\r
+    default:\r
+      if (i1.CompressionMethod <= NFileHeader::NCompressionMethod::kImploded)\r
+        mask = 0x7FFF;\r
+  }\r
+  return ((i1.Flags & mask) == (i2.Flags & mask));\r
+}\r
+\r
+HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item)\r
+{\r
+  if (item.FromLocal)\r
+    return S_OK;\r
+  try\r
+  {\r
+    RINOK(Seek(ArcInfo.Base + item.LocalHeaderPosition));\r
+    CItemEx localItem;\r
+    if (ReadUInt32() != NSignature::kLocalFileHeader)\r
+      return S_FALSE;\r
+    RINOK(ReadLocalItem(localItem));\r
+    if (!FlagsAreSame(item, localItem))\r
+      return S_FALSE;\r
+\r
+    if ((!localItem.HasDescriptor() &&\r
+          (\r
+            item.FileCRC != localItem.FileCRC ||\r
+            item.PackSize != localItem.PackSize ||\r
+            item.UnPackSize != localItem.UnPackSize\r
+          )\r
+        ) ||\r
+        item.Name.Length() != localItem.Name.Length()\r
+        )\r
+      return S_FALSE;\r
+    item.FileHeaderWithNameSize = localItem.FileHeaderWithNameSize;\r
+    item.LocalExtraSize = localItem.LocalExtraSize;\r
+    item.LocalExtra = localItem.LocalExtra;\r
+    item.FromLocal = true;\r
+  }\r
+  catch(...) { return S_FALSE; }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item)\r
+{\r
+  if (item.HasDescriptor())\r
+  {\r
+    const int kBufferSize = (1 << 12);\r
+    Byte buffer[kBufferSize];\r
+    \r
+    UInt32 numBytesInBuffer = 0;\r
+    UInt32 packedSize = 0;\r
+    \r
+    bool descriptorWasFound = false;\r
+    for (;;)\r
+    {\r
+      UInt32 processedSize;\r
+      RINOK(ReadBytes(buffer + numBytesInBuffer, kBufferSize - numBytesInBuffer, &processedSize));\r
+      numBytesInBuffer += processedSize;\r
+      if (numBytesInBuffer < NFileHeader::kDataDescriptorSize)\r
+        return S_FALSE;\r
+      UInt32 i;\r
+      for (i = 0; i <= numBytesInBuffer - NFileHeader::kDataDescriptorSize; i++)\r
+      {\r
+        // descriptorSignature field is Info-ZIP's extension\r
+        // to Zip specification.\r
+        UInt32 descriptorSignature = Get32(buffer + i);\r
+        \r
+        // !!!! It must be fixed for Zip64 archives\r
+        UInt32 descriptorPackSize = Get32(buffer + i + 8);\r
+        if (descriptorSignature== NSignature::kDataDescriptor && descriptorPackSize == packedSize + i)\r
+        {\r
+          descriptorWasFound = true;\r
+          item.FileCRC = Get32(buffer + i + 4);\r
+          item.PackSize = descriptorPackSize;\r
+          item.UnPackSize = Get32(buffer + i + 12);\r
+          IncreaseRealPosition(Int64(Int32(0 - (numBytesInBuffer - i - NFileHeader::kDataDescriptorSize))));\r
+          break;\r
+        }\r
+      }\r
+      if (descriptorWasFound)\r
+        break;\r
+      packedSize += i;\r
+      int j;\r
+      for (j = 0; i < numBytesInBuffer; i++, j++)\r
+        buffer[j] = buffer[i];\r
+      numBytesInBuffer = j;\r
+    }\r
+  }\r
+  else\r
+    IncreaseRealPosition(item.PackSize);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item)\r
+{\r
+  if (item.FromLocal)\r
+    return S_OK;\r
+  try\r
+  {\r
+    RINOK(ReadLocalItemAfterCdItem(item));\r
+    if (item.HasDescriptor())\r
+    {\r
+      RINOK(Seek(ArcInfo.Base + item.GetDataPosition() + item.PackSize));\r
+      if (ReadUInt32() != NSignature::kDataDescriptor)\r
+        return S_FALSE;\r
+      UInt32 crc = ReadUInt32();\r
+      UInt64 packSize, unpackSize;\r
+\r
+      /*\r
+      if (IsZip64)\r
+      {\r
+        packSize = ReadUInt64();\r
+        unpackSize = ReadUInt64();\r
+      }\r
+      else\r
+      */\r
+      {\r
+        packSize = ReadUInt32();\r
+        unpackSize = ReadUInt32();\r
+      }\r
+\r
+      if (crc != item.FileCRC || item.PackSize != packSize || item.UnPackSize != unpackSize)\r
+        return S_FALSE;\r
+    }\r
+  }\r
+  catch(...) { return S_FALSE; }\r
+  return S_OK;\r
+}\r
+  \r
+HRESULT CInArchive::ReadCdItem(CItemEx &item)\r
+{\r
+  item.FromCentral = true;\r
+  const int kBufSize = 42;\r
+  Byte p[kBufSize];\r
+  SafeReadBytes(p, kBufSize);\r
+  item.MadeByVersion.Version = p[0];\r
+  item.MadeByVersion.HostOS = p[1];\r
+  item.ExtractVersion.Version = p[2];\r
+  item.ExtractVersion.HostOS = p[3];\r
+  item.Flags = Get16(p + 4);\r
+  item.CompressionMethod = Get16(p + 6);\r
+  item.Time = Get32(p + 8);\r
+  item.FileCRC = Get32(p + 12);\r
+  item.PackSize = Get32(p + 16);\r
+  item.UnPackSize = Get32(p + 20);\r
+  UInt16 headerNameSize = Get16(p + 24);\r
+  UInt16 headerExtraSize = Get16(p + 26);\r
+  UInt16 headerCommentSize = Get16(p + 28);\r
+  UInt32 headerDiskNumberStart = Get16(p + 30);\r
+  item.InternalAttributes = Get16(p + 32);\r
+  item.ExternalAttributes = Get32(p + 34);\r
+  item.LocalHeaderPosition = Get32(p + 38);\r
+  ReadFileName(headerNameSize, item.Name);\r
+  \r
+  if (headerExtraSize > 0)\r
+  {\r
+    ReadExtra(headerExtraSize, item.CentralExtra, item.UnPackSize, item.PackSize,\r
+        item.LocalHeaderPosition, headerDiskNumberStart);\r
+  }\r
+\r
+  if (headerDiskNumberStart != 0)\r
+    throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);\r
+  \r
+  // May be these strings must be deleted\r
+  /*\r
+  if (item.IsDir())\r
+    item.UnPackSize = 0;\r
+  */\r
+  \r
+  ReadBuffer(item.Comment, headerCommentSize);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo)\r
+{\r
+  RINOK(Seek(offset));\r
+  const UInt32 kEcd64Size = 56;\r
+  Byte buf[kEcd64Size];\r
+  if (!ReadBytesAndTestSize(buf, kEcd64Size))\r
+    return S_FALSE;\r
+  if (Get32(buf) != NSignature::kZip64EndOfCentralDir)\r
+    return S_FALSE;\r
+  // cdInfo.NumEntries = Get64(buf + 24);\r
+  cdInfo.Size = Get64(buf + 40);\r
+  cdInfo.Offset = Get64(buf + 48);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CInArchive::FindCd(CCdInfo &cdInfo)\r
+{\r
+  UInt64 endPosition;\r
+  RINOK(m_Stream->Seek(0, STREAM_SEEK_END, &endPosition));\r
+  const UInt32 kBufSizeMax = (1 << 16) + kEcdSize + kZip64EcdLocatorSize;\r
+  CByteBuffer byteBuffer;\r
+  byteBuffer.SetCapacity(kBufSizeMax);\r
+  Byte *buf = byteBuffer;\r
+  UInt32 bufSize = (endPosition < kBufSizeMax) ? (UInt32)endPosition : kBufSizeMax;\r
+  if (bufSize < kEcdSize)\r
+    return S_FALSE;\r
+  UInt64 startPosition = endPosition - bufSize;\r
+  RINOK(m_Stream->Seek(startPosition, STREAM_SEEK_SET, &m_Position));\r
+  if (m_Position != startPosition)\r
+    return S_FALSE;\r
+  if (!ReadBytesAndTestSize(buf, bufSize))\r
+    return S_FALSE;\r
+  for (int i = (int)(bufSize - kEcdSize); i >= 0; i--)\r
+  {\r
+    if (Get32(buf + i) == NSignature::kEndOfCentralDir)\r
+    {\r
+      if (i >= kZip64EcdLocatorSize)\r
+      {\r
+        const Byte *locator = buf + i - kZip64EcdLocatorSize;\r
+        if (Get32(locator) == NSignature::kZip64EndOfCentralDirLocator)\r
+        {\r
+          UInt64 ecd64Offset = Get64(locator + 8);\r
+          if (TryEcd64(ecd64Offset, cdInfo) == S_OK)\r
+            return S_OK;\r
+          if (TryEcd64(ArcInfo.StartPosition + ecd64Offset, cdInfo) == S_OK)\r
+          {\r
+            ArcInfo.Base = ArcInfo.StartPosition;\r
+            return S_OK;\r
+          }\r
+        }\r
+      }\r
+      if (Get32(buf + i + 4) == 0)\r
+      {\r
+        // cdInfo.NumEntries = GetUInt16(buf + i + 10);\r
+        cdInfo.Size = Get32(buf + i + 12);\r
+        cdInfo.Offset = Get32(buf + i + 16);\r
+        UInt64 curPos = endPosition - bufSize + i;\r
+        UInt64 cdEnd = cdInfo.Size + cdInfo.Offset;\r
+        if (curPos != cdEnd)\r
+        {\r
+          /*\r
+          if (cdInfo.Offset <= 16 && cdInfo.Size != 0)\r
+          {\r
+            // here we support some rare ZIP files with Central directory at the start\r
+            ArcInfo.Base = 0;\r
+          }\r
+          else\r
+          */\r
+            ArcInfo.Base = curPos - cdEnd;\r
+        }\r
+        return S_OK;\r
+      }\r
+    }\r
+  }\r
+  return S_FALSE;\r
+}\r
+\r
+HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, UInt64 cdOffset, UInt64 cdSize, CProgressVirt *progress)\r
+{\r
+  items.Clear();\r
+  RINOK(m_Stream->Seek(cdOffset, STREAM_SEEK_SET, &m_Position));\r
+  if (m_Position != cdOffset)\r
+    return S_FALSE;\r
+\r
+  if (!_inBuffer.Create(1 << 15))\r
+    return E_OUTOFMEMORY;\r
+  _inBuffer.SetStream(m_Stream);\r
+  _inBuffer.Init();\r
+  _inBufMode = true;\r
+\r
+  while(m_Position - cdOffset < cdSize)\r
+  {\r
+    if (ReadUInt32() != NSignature::kCentralFileHeader)\r
+      return S_FALSE;\r
+    CItemEx cdItem;\r
+    RINOK(ReadCdItem(cdItem));\r
+    items.Add(cdItem);\r
+    if (progress && items.Size() % 1000 == 0)\r
+      RINOK(progress->SetCompleted(items.Size()));\r
+  }\r
+  return (m_Position - cdOffset == cdSize) ? S_OK : S_FALSE;\r
+}\r
+\r
+HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt64 &cdOffset, UInt64 &cdSize, CProgressVirt *progress)\r
+{\r
+  ArcInfo.Base = 0;\r
+  CCdInfo cdInfo;\r
+  RINOK(FindCd(cdInfo));\r
+  HRESULT res = S_FALSE;\r
+  cdSize = cdInfo.Size;\r
+  cdOffset = cdInfo.Offset;\r
+  res = TryReadCd(items, ArcInfo.Base + cdOffset, cdSize, progress);\r
+  if (res == S_FALSE && ArcInfo.Base == 0)\r
+  {\r
+    res = TryReadCd(items, cdInfo.Offset + ArcInfo.StartPosition, cdSize, progress);\r
+    if (res == S_OK)\r
+      ArcInfo.Base = ArcInfo.StartPosition;\r
+  }\r
+  if (!ReadUInt32(m_Signature))\r
+    return S_FALSE;\r
+  return res;\r
+}\r
+\r
+HRESULT CInArchive::ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt *progress, UInt64 &cdOffset, int &numCdItems)\r
+{\r
+  items.Clear();\r
+  numCdItems = 0;\r
+  while (m_Signature == NSignature::kLocalFileHeader)\r
+  {\r
+    // FSeek points to next byte after signature\r
+    // NFileHeader::CLocalBlock localHeader;\r
+    CItemEx item;\r
+    item.LocalHeaderPosition = m_Position - m_StreamStartPosition - 4; // points to signature;\r
+    RINOK(ReadLocalItem(item));\r
+    item.FromLocal = true;\r
+    ReadLocalItemDescriptor(item);\r
+    items.Add(item);\r
+    if (progress && items.Size() % 100 == 0)\r
+      RINOK(progress->SetCompleted(items.Size()));\r
+    if (!ReadUInt32(m_Signature))\r
+      break;\r
+  }\r
+  cdOffset = m_Position - 4;\r
+  int i;\r
+  for (i = 0; i < items.Size(); i++, numCdItems++)\r
+  {\r
+    if (progress && i % 1000 == 0)\r
+      RINOK(progress->SetCompleted(items.Size()));\r
+    if (m_Signature == NSignature::kEndOfCentralDir)\r
+      break;\r
+\r
+    if (m_Signature != NSignature::kCentralFileHeader)\r
+      return S_FALSE;\r
+\r
+    CItemEx cdItem;\r
+    RINOK(ReadCdItem(cdItem));\r
+\r
+    if (i == 0)\r
+    {\r
+      int j;\r
+      for (j = 0; j < items.Size(); j++)\r
+      {\r
+        CItemEx &item = items[j];\r
+        if (item.Name == cdItem.Name)\r
+        {\r
+          ArcInfo.Base = item.LocalHeaderPosition - cdItem.LocalHeaderPosition;\r
+          break;\r
+        }\r
+      }\r
+      if (j == items.Size())\r
+        return S_FALSE;\r
+    }\r
+\r
+    int index;\r
+    int left = 0, right = items.Size();\r
+    for (;;)\r
+    {\r
+      if (left >= right)\r
+        return S_FALSE;\r
+      index = (left + right) / 2;\r
+      UInt64 position = items[index].LocalHeaderPosition - ArcInfo.Base;\r
+      if (cdItem.LocalHeaderPosition == position)\r
+        break;\r
+      if (cdItem.LocalHeaderPosition < position)\r
+        right = index;\r
+      else\r
+        left = index + 1;\r
+    }\r
+    CItemEx &item = items[index];\r
+    // item.LocalHeaderPosition = cdItem.LocalHeaderPosition;\r
+    item.MadeByVersion = cdItem.MadeByVersion;\r
+    item.CentralExtra = cdItem.CentralExtra;\r
+\r
+    if (\r
+        // item.ExtractVersion != cdItem.ExtractVersion ||\r
+        !FlagsAreSame(item, cdItem) ||\r
+        item.FileCRC != cdItem.FileCRC)\r
+      return S_FALSE;\r
+\r
+    if (item.Name.Length() != cdItem.Name.Length() ||\r
+        item.PackSize != cdItem.PackSize ||\r
+        item.UnPackSize != cdItem.UnPackSize\r
+      )\r
+      return S_FALSE;\r
+    item.Name = cdItem.Name;\r
+    item.InternalAttributes = cdItem.InternalAttributes;\r
+    item.ExternalAttributes = cdItem.ExternalAttributes;\r
+    item.Comment = cdItem.Comment;\r
+    item.FromCentral = cdItem.FromCentral;\r
+    if (!ReadUInt32(m_Signature))\r
+      return S_FALSE;\r
+  }\r
+  for (i = 0; i < items.Size(); i++)\r
+    items[i].LocalHeaderPosition -= ArcInfo.Base;\r
+  return S_OK;\r
+}\r
+\r
+struct CEcd\r
+{\r
+  UInt16 thisDiskNumber;\r
+  UInt16 startCDDiskNumber;\r
+  UInt16 numEntriesInCDOnThisDisk;\r
+  UInt16 numEntriesInCD;\r
+  UInt32 cdSize;\r
+  UInt32 cdStartOffset;\r
+  UInt16 commentSize;\r
+  void Parse(const Byte *p);\r
+};\r
+\r
+void CEcd::Parse(const Byte *p)\r
+{\r
+  thisDiskNumber = Get16(p);\r
+  startCDDiskNumber = Get16(p + 2);\r
+  numEntriesInCDOnThisDisk = Get16(p + 4);\r
+  numEntriesInCD = Get16(p + 6);\r
+  cdSize = Get32(p + 8);\r
+  cdStartOffset = Get32(p + 12);\r
+  commentSize = Get16(p + 16);\r
+}\r
+\r
+struct CEcd64\r
+{\r
+  UInt16 versionMade;\r
+  UInt16 versionNeedExtract;\r
+  UInt32 thisDiskNumber;\r
+  UInt32 startCDDiskNumber;\r
+  UInt64 numEntriesInCDOnThisDisk;\r
+  UInt64 numEntriesInCD;\r
+  UInt64 cdSize;\r
+  UInt64 cdStartOffset;\r
+  void Parse(const Byte *p);\r
+  CEcd64() { memset(this, 0, sizeof(*this)); }\r
+};\r
+\r
+void CEcd64::Parse(const Byte *p)\r
+{\r
+  versionMade = Get16(p);\r
+  versionNeedExtract = Get16(p + 2);\r
+  thisDiskNumber = Get32(p + 4);\r
+  startCDDiskNumber = Get32(p + 8);\r
+  numEntriesInCDOnThisDisk = Get64(p + 12);\r
+  numEntriesInCD = Get64(p + 20);\r
+  cdSize = Get64(p + 28);\r
+  cdStartOffset = Get64(p + 36);\r
+}\r
+\r
+#define COPY_ECD_ITEM_16(n) if (!isZip64 || ecd. n != 0xFFFF)     ecd64. n = ecd. n;\r
+#define COPY_ECD_ITEM_32(n) if (!isZip64 || ecd. n != 0xFFFFFFFF) ecd64. n = ecd. n;\r
+\r
+HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress)\r
+{\r
+  // m_Signature must be kLocalFileHeaderSignature or\r
+  // kEndOfCentralDirSignature\r
+  // m_Position points to next byte after signature\r
+\r
+  IsZip64 = false;\r
+  items.Clear();\r
+\r
+  UInt64 cdSize, cdStartOffset;\r
+  HRESULT res;\r
+  try\r
+  {\r
+    res = ReadCd(items, cdStartOffset, cdSize, progress);\r
+  }\r
+  catch(CInArchiveException &)\r
+  {\r
+    res = S_FALSE;\r
+  }\r
+  if (res != S_FALSE && res != S_OK)\r
+    return res;\r
+\r
+  /*\r
+  if (res != S_OK)\r
+    return res;\r
+  res = S_FALSE;\r
+  */\r
+\r
+  int numCdItems = items.Size();\r
+  if (res == S_FALSE)\r
+  {\r
+    _inBufMode = false;\r
+    ArcInfo.Base = 0;\r
+    RINOK(m_Stream->Seek(ArcInfo.StartPosition, STREAM_SEEK_SET, &m_Position));\r
+    if (m_Position != ArcInfo.StartPosition)\r
+      return S_FALSE;\r
+    if (!ReadUInt32(m_Signature))\r
+      return S_FALSE;\r
+    RINOK(ReadLocalsAndCd(items, progress, cdStartOffset, numCdItems));\r
+    cdSize = (m_Position - 4) - cdStartOffset;\r
+    cdStartOffset -= ArcInfo.Base;\r
+  }\r
+\r
+  CEcd64 ecd64;\r
+  bool isZip64 = false;\r
+  UInt64 zip64EcdStartOffset = m_Position - 4 - ArcInfo.Base;\r
+  if (m_Signature == NSignature::kZip64EndOfCentralDir)\r
+  {\r
+    IsZip64 = isZip64 = true;\r
+    UInt64 recordSize = ReadUInt64();\r
+\r
+    const int kBufSize = kZip64EcdSize;\r
+    Byte buf[kBufSize];\r
+    SafeReadBytes(buf, kBufSize);\r
+    ecd64.Parse(buf);\r
+\r
+    Skip(recordSize - kZip64EcdSize);\r
+    if (!ReadUInt32(m_Signature))\r
+      return S_FALSE;\r
+    if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0)\r
+      throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);\r
+    if (ecd64.numEntriesInCDOnThisDisk != numCdItems ||\r
+        ecd64.numEntriesInCD != numCdItems ||\r
+        ecd64.cdSize != cdSize ||\r
+        (ecd64.cdStartOffset != cdStartOffset &&\r
+        (!items.IsEmpty())))\r
+      return S_FALSE;\r
+  }\r
+  if (m_Signature == NSignature::kZip64EndOfCentralDirLocator)\r
+  {\r
+    /* UInt32 startEndCDDiskNumber = */ ReadUInt32();\r
+    UInt64 endCDStartOffset = ReadUInt64();\r
+    /* UInt32 numberOfDisks = */ ReadUInt32();\r
+    if (zip64EcdStartOffset != endCDStartOffset)\r
+      return S_FALSE;\r
+    if (!ReadUInt32(m_Signature))\r
+      return S_FALSE;\r
+  }\r
+  if (m_Signature != NSignature::kEndOfCentralDir)\r
+    return S_FALSE;\r
+\r
+  const int kBufSize = kEcdSize - 4;\r
+  Byte buf[kBufSize];\r
+  SafeReadBytes(buf, kBufSize);\r
+  CEcd ecd;\r
+  ecd.Parse(buf);\r
+\r
+  COPY_ECD_ITEM_16(thisDiskNumber);\r
+  COPY_ECD_ITEM_16(startCDDiskNumber);\r
+  COPY_ECD_ITEM_16(numEntriesInCDOnThisDisk);\r
+  COPY_ECD_ITEM_16(numEntriesInCD);\r
+  COPY_ECD_ITEM_32(cdSize);\r
+  COPY_ECD_ITEM_32(cdStartOffset);\r
+\r
+  ReadBuffer(ArcInfo.Comment, ecd.commentSize);\r
+\r
+  if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0)\r
+    throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);\r
+  if ((UInt16)ecd64.numEntriesInCDOnThisDisk != ((UInt16)numCdItems) ||\r
+      (UInt16)ecd64.numEntriesInCD != ((UInt16)numCdItems) ||\r
+      (UInt32)ecd64.cdSize != (UInt32)cdSize ||\r
+      ((UInt32)(ecd64.cdStartOffset) != (UInt32)cdStartOffset &&\r
+        (!items.IsEmpty())))\r
+    return S_FALSE;\r
+  \r
+  _inBufMode = false;\r
+  _inBuffer.Free();\r
+  IsOkHeaders = (numCdItems == items.Size());\r
+  ArcInfo.FinishPosition = m_Position;\r
+  return S_OK;\r
+}\r
+\r
+ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size)\r
+{\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<ISequentialInStream> stream(streamSpec);\r
+  SeekInArchive(ArcInfo.Base + position);\r
+  streamSpec->SetStream(m_Stream);\r
+  streamSpec->Init(size);\r
+  return stream.Detach();\r
+}\r
+\r
+IInStream* CInArchive::CreateStream()\r
+{\r
+  CMyComPtr<IInStream> stream = m_Stream;\r
+  return stream.Detach();\r
+}\r
+\r
+bool CInArchive::SeekInArchive(UInt64 position)\r
+{\r
+  UInt64 newPosition;\r
+  if (m_Stream->Seek(position, STREAM_SEEK_SET, &newPosition) != S_OK)\r
+    return false;\r
+  return (newPosition == position);\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h
new file mode 100755 (executable)
index 0000000..86fe6b8
--- /dev/null
@@ -0,0 +1,125 @@
+// Archive/ZipIn.h\r
+\r
+#ifndef __ZIP_IN_H\r
+#define __ZIP_IN_H\r
+\r
+#include "Common/MyCom.h"\r
+\r
+#include "../../IStream.h"\r
+\r
+#include "../../Common/InBuffer.h"\r
+\r
+#include "ZipHeader.h"\r
+#include "ZipItemEx.h"\r
+\r
+namespace NArchive {\r
+namespace NZip {\r
+  \r
+class CInArchiveException\r
+{\r
+public:\r
+  enum ECauseType\r
+  {\r
+    kUnexpectedEndOfArchive = 0,\r
+    kArchiceHeaderCRCError,\r
+    kFileHeaderCRCError,\r
+    kIncorrectArchive,\r
+    kDataDescroptorsAreNotSupported,\r
+    kMultiVolumeArchiveAreNotSupported,\r
+    kReadStreamError,\r
+    kSeekStreamError\r
+  }\r
+  Cause;\r
+  CInArchiveException(ECauseType cause): Cause(cause) {}\r
+};\r
+\r
+class CInArchiveInfo\r
+{\r
+public:\r
+  UInt64 Base;\r
+  UInt64 StartPosition;\r
+  UInt64 FinishPosition;\r
+  CByteBuffer Comment;\r
+\r
+  CInArchiveInfo(): Base(0), StartPosition(0) {}\r
+  UInt64 GetPhySize() const { return FinishPosition - StartPosition; }\r
+  void Clear()\r
+  {\r
+    Base = 0;\r
+    StartPosition = 0;\r
+    Comment.SetCapacity(0);\r
+  }\r
+};\r
+\r
+class CProgressVirt\r
+{\r
+public:\r
+  STDMETHOD(SetTotal)(UInt64 numFiles) PURE;\r
+  STDMETHOD(SetCompleted)(UInt64 numFiles) PURE;\r
+};\r
+\r
+struct CCdInfo\r
+{\r
+  // UInt64 NumEntries;\r
+  UInt64 Size;\r
+  UInt64 Offset;\r
+};\r
+\r
+class CInArchive\r
+{\r
+  CMyComPtr<IInStream> m_Stream;\r
+  UInt32 m_Signature;\r
+  UInt64 m_StreamStartPosition;\r
+  UInt64 m_Position;\r
\r
+  bool _inBufMode;\r
+  CInBuffer _inBuffer;\r
+  \r
+  HRESULT Seek(UInt64 offset);\r
+\r
+  HRESULT FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit);\r
+  void ReadFileName(UInt32 nameSize, AString &dest);\r
+  \r
+  HRESULT ReadBytes(void *data, UInt32 size, UInt32 *processedSize);\r
+  bool ReadBytesAndTestSize(void *data, UInt32 size);\r
+  void SafeReadBytes(void *data, UInt32 size);\r
+  void ReadBuffer(CByteBuffer &buffer, UInt32 size);\r
+  Byte ReadByte();\r
+  UInt16 ReadUInt16();\r
+  UInt32 ReadUInt32();\r
+  UInt64 ReadUInt64();\r
+  bool ReadUInt32(UInt32 &signature);\r
+  \r
+  void Skip(UInt64 num);\r
+  void IncreaseRealPosition(UInt64 addValue);\r
\r
+  void ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock,\r
+      UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber);\r
+  HRESULT ReadLocalItem(CItemEx &item);\r
+  HRESULT ReadLocalItemDescriptor(CItemEx &item);\r
+  HRESULT ReadCdItem(CItemEx &item);\r
+  HRESULT TryEcd64(UInt64 offset, CCdInfo &cdInfo);\r
+  HRESULT FindCd(CCdInfo &cdInfo);\r
+  HRESULT TryReadCd(CObjectVector<CItemEx> &items, UInt64 cdOffset, UInt64 cdSize, CProgressVirt *progress);\r
+  HRESULT ReadCd(CObjectVector<CItemEx> &items, UInt64 &cdOffset, UInt64 &cdSize, CProgressVirt *progress);\r
+  HRESULT ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt *progress, UInt64 &cdOffset, int &numCdItems);\r
+public:\r
+  CInArchiveInfo ArcInfo;\r
+  bool IsZip64;\r
+  bool IsOkHeaders;\r
+\r
+  HRESULT ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress);\r
+  HRESULT ReadLocalItemAfterCdItem(CItemEx &item);\r
+  HRESULT ReadLocalItemAfterCdItemFull(CItemEx &item);\r
+  HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit);\r
+  void Close();\r
+  bool SeekInArchive(UInt64 position);\r
+  ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size);\r
+  IInStream* CreateStream();\r
+\r
+  bool IsOpen() const { return m_Stream != NULL; }\r
+};\r
+  \r
+}}\r
+  \r
+#endif\r
diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp
new file mode 100755 (executable)
index 0000000..df4a379
--- /dev/null
@@ -0,0 +1,172 @@
+// Archive/ZipItem.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "ZipHeader.h"\r
+#include "ZipItem.h"\r
+#include "../Common/ItemNameUtils.h"\r
+#include "../../../../C/CpuArch.h"\r
+\r
+namespace NArchive {\r
+namespace NZip {\r
+\r
+bool operator==(const CVersion &v1, const CVersion &v2)\r
+{\r
+  return (v1.Version == v2.Version) && (v1.HostOS == v2.HostOS);\r
+}\r
+\r
+bool operator!=(const CVersion &v1, const CVersion &v2)\r
+{\r
+  return !(v1 == v2);\r
+}\r
+\r
+bool CExtraSubBlock::ExtractNtfsTime(int index, FILETIME &ft) const\r
+{\r
+  ft.dwHighDateTime = ft.dwLowDateTime = 0;\r
+  UInt32 size = (UInt32)Data.GetCapacity();\r
+  if (ID != NFileHeader::NExtraID::kNTFS || size < 32)\r
+    return false;\r
+  const Byte *p = (const Byte *)Data;\r
+  p += 4; // for reserved\r
+  size -= 4;\r
+  while (size > 4)\r
+  {\r
+    UInt16 tag = GetUi16(p);\r
+    UInt32 attrSize = GetUi16(p + 2);\r
+    p += 4;\r
+    size -= 4;\r
+    if (attrSize > size)\r
+      attrSize = size;\r
+    \r
+    if (tag == NFileHeader::NNtfsExtra::kTagTime && attrSize >= 24)\r
+    {\r
+      p += 8 * index;\r
+      ft.dwLowDateTime = GetUi32(p);\r
+      ft.dwHighDateTime = GetUi32(p + 4);\r
+      return true;\r
+    }\r
+    p += attrSize;\r
+    size -= attrSize;\r
+  }\r
+  return false;\r
+}\r
+\r
+bool CExtraSubBlock::ExtractUnixTime(int index, UInt32 &res) const\r
+{\r
+  res = 0;\r
+  UInt32 size = (UInt32)Data.GetCapacity();\r
+  if (ID != NFileHeader::NExtraID::kUnixTime || size < 5)\r
+    return false;\r
+  const Byte *p = (const Byte *)Data;\r
+  Byte flags = *p++;\r
+  size--;\r
+  for (int i = 0; i < 3; i++)\r
+    if ((flags & (1 << i)) != 0)\r
+    {\r
+      if (size < 4)\r
+        return false;\r
+      if (index == i)\r
+      {\r
+        res = GetUi32(p);\r
+        return true;\r
+      }\r
+      p += 4;\r
+      size -= 4;\r
+    }\r
+  return false;\r
+}\r
+\r
+bool CLocalItem::IsDir() const\r
+{\r
+  return NItemName::HasTailSlash(Name, GetCodePage());\r
+}\r
+\r
+bool CItem::IsDir() const\r
+{\r
+  if (NItemName::HasTailSlash(Name, GetCodePage()))\r
+    return true;\r
+  if (!FromCentral)\r
+    return false;\r
+  WORD highAttributes = WORD((ExternalAttributes >> 16 ) & 0xFFFF);\r
+  switch(MadeByVersion.HostOS)\r
+  {\r
+    case NFileHeader::NHostOS::kAMIGA:\r
+      switch (highAttributes & NFileHeader::NAmigaAttribute::kIFMT)\r
+      {\r
+        case NFileHeader::NAmigaAttribute::kIFDIR: return true;\r
+        case NFileHeader::NAmigaAttribute::kIFREG: return false;\r
+        default: return false; // change it throw kUnknownAttributes;\r
+      }\r
+    case NFileHeader::NHostOS::kFAT:\r
+    case NFileHeader::NHostOS::kNTFS:\r
+    case NFileHeader::NHostOS::kHPFS:\r
+    case NFileHeader::NHostOS::kVFAT:\r
+      return ((ExternalAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);\r
+    case NFileHeader::NHostOS::kAtari:\r
+    case NFileHeader::NHostOS::kMac:\r
+    case NFileHeader::NHostOS::kVMS:\r
+    case NFileHeader::NHostOS::kVM_CMS:\r
+    case NFileHeader::NHostOS::kAcorn:\r
+    case NFileHeader::NHostOS::kMVS:\r
+      return false; // change it throw kUnknownAttributes;\r
+    default:\r
+      /*\r
+      switch (highAttributes & NFileHeader::NUnixAttribute::kIFMT)\r
+      {\r
+        case NFileHeader::NUnixAttribute::kIFDIR:\r
+          return true;\r
+        default:\r
+          return false;\r
+      }\r
+      */\r
+      return false;\r
+  }\r
+}\r
+\r
+UInt32 CLocalItem::GetWinAttributes() const\r
+{\r
+  DWORD winAttributes = 0;\r
+  if (IsDir())\r
+    winAttributes |= FILE_ATTRIBUTE_DIRECTORY;\r
+  return winAttributes;\r
+}\r
+\r
+UInt32 CItem::GetWinAttributes() const\r
+{\r
+  DWORD winAttributes = 0;\r
+  switch(MadeByVersion.HostOS)\r
+  {\r
+    case NFileHeader::NHostOS::kFAT:\r
+    case NFileHeader::NHostOS::kNTFS:\r
+      if (FromCentral)\r
+        winAttributes = ExternalAttributes;\r
+      break;\r
+    default:\r
+      winAttributes = 0; // must be converted from unix value;\r
+  }\r
+  if (IsDir())       // test it;\r
+    winAttributes |= FILE_ATTRIBUTE_DIRECTORY;\r
+  return winAttributes;\r
+}\r
+\r
+void CLocalItem::SetFlagBits(int startBitNumber, int numBits, int value)\r
+{\r
+  UInt16 mask = (UInt16)(((1 << numBits) - 1) << startBitNumber);\r
+  Flags &= ~mask;\r
+  Flags |= value << startBitNumber;\r
+}\r
+\r
+void CLocalItem::SetBitMask(int bitMask, bool enable)\r
+{\r
+  if(enable)\r
+    Flags |= bitMask;\r
+  else\r
+    Flags &= ~bitMask;\r
+}\r
+\r
+void CLocalItem::SetEncrypted(bool encrypted)\r
+  { SetBitMask(NFileHeader::NFlags::kEncrypted, encrypted); }\r
+void CLocalItem::SetUtf8(bool isUtf8)\r
+  { SetBitMask(NFileHeader::NFlags::kUtf8, isUtf8); }\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h
new file mode 100755 (executable)
index 0000000..b9cc524
--- /dev/null
@@ -0,0 +1,281 @@
+// Archive/ZipItem.h\r
+\r
+#ifndef __ARCHIVE_ZIP_ITEM_H\r
+#define __ARCHIVE_ZIP_ITEM_H\r
+\r
+#include "Common/Types.h"\r
+#include "Common/MyString.h"\r
+#include "Common/Buffer.h"\r
+#include "Common/UTFConvert.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "ZipHeader.h"\r
+\r
+namespace NArchive {\r
+namespace NZip {\r
+\r
+struct CVersion\r
+{\r
+  Byte Version;\r
+  Byte HostOS;\r
+};\r
+\r
+bool operator==(const CVersion &v1, const CVersion &v2);\r
+bool operator!=(const CVersion &v1, const CVersion &v2);\r
+\r
+struct CExtraSubBlock\r
+{\r
+  UInt16 ID;\r
+  CByteBuffer Data;\r
+  bool ExtractNtfsTime(int index, FILETIME &ft) const;\r
+  bool ExtractUnixTime(int index, UInt32 &res) const;\r
+};\r
+\r
+struct CWzAesExtraField\r
+{\r
+  UInt16 VendorVersion; // 0x0001 - AE-1, 0x0002 - AE-2,\r
+  // UInt16 VendorId; // "AE"\r
+  Byte Strength; // 1 - 128-bit , 2 - 192-bit , 3 - 256-bit\r
+  UInt16 Method;\r
+\r
+  CWzAesExtraField(): VendorVersion(2), Strength(3), Method(0) {}\r
+\r
+  bool NeedCrc() const { return (VendorVersion == 1); }\r
+\r
+  bool ParseFromSubBlock(const CExtraSubBlock &sb)\r
+  {\r
+    if (sb.ID != NFileHeader::NExtraID::kWzAES)\r
+      return false;\r
+    if (sb.Data.GetCapacity() < 7)\r
+      return false;\r
+    const Byte *p = (const Byte *)sb.Data;\r
+    VendorVersion = (((UInt16)p[1]) << 8) | p[0];\r
+    if (p[2] != 'A' || p[3] != 'E')\r
+      return false;\r
+    Strength = p[4];\r
+    Method = (((UInt16)p[6]) << 16) | p[5];\r
+    return true;\r
+  }\r
+  void SetSubBlock(CExtraSubBlock &sb) const\r
+  {\r
+    sb.Data.SetCapacity(7);\r
+    sb.ID = NFileHeader::NExtraID::kWzAES;\r
+    Byte *p = (Byte *)sb.Data;\r
+    p[0] = (Byte)VendorVersion;\r
+    p[1] = (Byte)(VendorVersion >> 8);\r
+    p[2] = 'A';\r
+    p[3] = 'E';\r
+    p[4] = Strength;\r
+    p[5] = (Byte)Method;\r
+    p[6] = (Byte)(Method >> 8);\r
+  }\r
+};\r
+\r
+namespace NStrongCryptoFlags\r
+{\r
+  const UInt16 kDES = 0x6601;\r
+  const UInt16 kRC2old = 0x6602;\r
+  const UInt16 k3DES168 = 0x6603;\r
+  const UInt16 k3DES112 = 0x6609;\r
+  const UInt16 kAES128 = 0x660E;\r
+  const UInt16 kAES192 = 0x660F;\r
+  const UInt16 kAES256 = 0x6610;\r
+  const UInt16 kRC2 = 0x6702;\r
+  const UInt16 kBlowfish = 0x6720;\r
+  const UInt16 kTwofish = 0x6721;\r
+  const UInt16 kRC4 = 0x6801;\r
+}\r
+\r
+struct CStrongCryptoField\r
+{\r
+  UInt16 Format;\r
+  UInt16 AlgId;\r
+  UInt16 BitLen;\r
+  UInt16 Flags;\r
+\r
+  bool ParseFromSubBlock(const CExtraSubBlock &sb)\r
+  {\r
+    if (sb.ID != NFileHeader::NExtraID::kStrongEncrypt)\r
+      return false;\r
+    const Byte *p = (const Byte *)sb.Data;\r
+    if (sb.Data.GetCapacity() < 8)\r
+      return false;\r
+    Format = (((UInt16)p[1]) << 8) | p[0];\r
+    AlgId  = (((UInt16)p[3]) << 8) | p[2];\r
+    BitLen = (((UInt16)p[5]) << 8) | p[4];\r
+    Flags  = (((UInt16)p[7]) << 8) | p[6];\r
+    return (Format == 2);\r
+  }\r
+};\r
+\r
+struct CExtraBlock\r
+{\r
+  CObjectVector<CExtraSubBlock> SubBlocks;\r
+  void Clear() { SubBlocks.Clear(); }\r
+  size_t GetSize() const\r
+  {\r
+    size_t res = 0;\r
+    for (int i = 0; i < SubBlocks.Size(); i++)\r
+      res += SubBlocks[i].Data.GetCapacity() + 2 + 2;\r
+    return res;\r
+  }\r
+  bool GetWzAesField(CWzAesExtraField &aesField) const\r
+  {\r
+    for (int i = 0; i < SubBlocks.Size(); i++)\r
+      if (aesField.ParseFromSubBlock(SubBlocks[i]))\r
+        return true;\r
+    return false;\r
+  }\r
+\r
+  bool GetStrongCryptoField(CStrongCryptoField &f) const\r
+  {\r
+    for (int i = 0; i < SubBlocks.Size(); i++)\r
+      if (f.ParseFromSubBlock(SubBlocks[i]))\r
+        return true;\r
+    return false;\r
+  }\r
+\r
+  bool HasWzAesField() const\r
+  {\r
+    CWzAesExtraField aesField;\r
+    return GetWzAesField(aesField);\r
+  }\r
+\r
+  bool GetNtfsTime(int index, FILETIME &ft) const\r
+  {\r
+    for (int i = 0; i < SubBlocks.Size(); i++)\r
+    {\r
+      const CExtraSubBlock &sb = SubBlocks[i];\r
+      if (sb.ID == NFileHeader::NExtraID::kNTFS)\r
+        return sb.ExtractNtfsTime(index, ft);\r
+    }\r
+    return false;\r
+  }\r
+\r
+  bool GetUnixTime(int index, UInt32 &res) const\r
+  {\r
+    for (int i = 0; i < SubBlocks.Size(); i++)\r
+    {\r
+      const CExtraSubBlock &sb = SubBlocks[i];\r
+      if (sb.ID == NFileHeader::NExtraID::kUnixTime)\r
+        return sb.ExtractUnixTime(index, res);\r
+    }\r
+    return false;\r
+  }\r
+\r
+  /*\r
+  bool HasStrongCryptoField() const\r
+  {\r
+    CStrongCryptoField f;\r
+    return GetStrongCryptoField(f);\r
+  }\r
+  */\r
+\r
+  void RemoveUnknownSubBlocks()\r
+  {\r
+    for (int i = SubBlocks.Size() - 1; i >= 0; i--)\r
+      if (SubBlocks[i].ID != NFileHeader::NExtraID::kWzAES)\r
+        SubBlocks.Delete(i);\r
+  }\r
+};\r
+\r
+\r
+class CLocalItem\r
+{\r
+public:\r
+  CVersion ExtractVersion;\r
+  UInt16 Flags;\r
+  UInt16 CompressionMethod;\r
+  UInt32 Time;\r
+  UInt32 FileCRC;\r
+  UInt64 PackSize;\r
+  UInt64 UnPackSize;\r
+  \r
+  AString Name;\r
+\r
+  CExtraBlock LocalExtra;\r
+\r
+  bool IsUtf8() const { return (Flags & NFileHeader::NFlags::kUtf8) != 0; }\r
+  \r
+  bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kEncrypted) != 0; }\r
+  bool IsStrongEncrypted() const { return IsEncrypted() && (Flags & NFileHeader::NFlags::kStrongEncrypted) != 0; };\r
+  bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || CompressionMethod == NFileHeader::NCompressionMethod::kWzAES); };\r
+  \r
+  bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; }\r
+  \r
+  bool IsDir() const;\r
+  bool IgnoreItem() const { return false; }\r
+  UInt32 GetWinAttributes() const;\r
+  \r
+  bool HasDescriptor() const  { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; }\r
+\r
+  UString GetUnicodeString(const AString &s) const\r
+  {\r
+    UString res;\r
+    if (IsUtf8())\r
+      if (!ConvertUTF8ToUnicode(s, res))\r
+        res.Empty();\r
+    if (res.IsEmpty())\r
+      res = MultiByteToUnicodeString(s, GetCodePage());\r
+    return res;\r
+  }\r
+  \r
+private:\r
+  void SetFlagBits(int startBitNumber, int numBits, int value);\r
+  void SetBitMask(int bitMask, bool enable);\r
+public:\r
+  void ClearFlags() { Flags = 0; }\r
+  void SetEncrypted(bool encrypted);\r
+  void SetUtf8(bool isUtf8);\r
+\r
+  WORD GetCodePage() const { return  CP_OEMCP; }\r
+};\r
+\r
+class CItem: public CLocalItem\r
+{\r
+public:\r
+  CVersion MadeByVersion;\r
+  UInt16 InternalAttributes;\r
+  UInt32 ExternalAttributes;\r
+  \r
+  UInt64 LocalHeaderPosition;\r
+  \r
+  FILETIME NtfsMTime;\r
+  FILETIME NtfsATime;\r
+  FILETIME NtfsCTime;\r
+\r
+  CExtraBlock CentralExtra;\r
+  CByteBuffer Comment;\r
+\r
+  bool FromLocal;\r
+  bool FromCentral;\r
+  bool NtfsTimeIsDefined;\r
+  \r
+  bool IsDir() const;\r
+  UInt32 GetWinAttributes() const;\r
+\r
+  bool IsThereCrc() const\r
+  {\r
+    if (CompressionMethod == NFileHeader::NCompressionMethod::kWzAES)\r
+    {\r
+      CWzAesExtraField aesField;\r
+      if (CentralExtra.GetWzAesField(aesField))\r
+        return aesField.NeedCrc();\r
+    }\r
+    return (FileCRC != 0 || !IsDir());\r
+  }\r
+  \r
+  WORD GetCodePage() const\r
+  {\r
+    return (WORD)((MadeByVersion.HostOS == NFileHeader::NHostOS::kFAT\r
+        || MadeByVersion.HostOS == NFileHeader::NHostOS::kNTFS\r
+        ) ? CP_OEMCP : CP_ACP);\r
+  }\r
+  CItem() : FromLocal(false), FromCentral(false), NtfsTimeIsDefined(false) {}\r
+};\r
+\r
+}}\r
+\r
+#endif\r
+\r
+\r
diff --git a/CPP/7zip/Archive/Zip/ZipItemEx.h b/CPP/7zip/Archive/Zip/ZipItemEx.h
new file mode 100755 (executable)
index 0000000..0d74edd
--- /dev/null
@@ -0,0 +1,34 @@
+// Archive/ZipItemEx.h\r
+\r
+#ifndef __ARCHIVE_ZIP_ITEMEX_H\r
+#define __ARCHIVE_ZIP_ITEMEX_H\r
+\r
+#include "ZipHeader.h"\r
+#include "ZipItem.h"\r
+\r
+namespace NArchive {\r
+namespace NZip {\r
+  \r
+class CItemEx: public CItem\r
+{\r
+public:\r
+  UInt32 FileHeaderWithNameSize;\r
+  UInt16 LocalExtraSize;\r
+  \r
+  UInt64 GetLocalFullSize() const\r
+    { return FileHeaderWithNameSize + LocalExtraSize + PackSize +\r
+      (HasDescriptor() ? NFileHeader::kDataDescriptorSize : 0); };\r
+  /*\r
+  UInt64 GetLocalFullSize(bool isZip64) const\r
+    { return FileHeaderWithNameSize + LocalExtraSize + PackSize +\r
+    (HasDescriptor() ? (isZip64 ? NFileHeader::kDataDescriptor64Size : NFileHeader::kDataDescriptorSize) : 0); };\r
+  */\r
+  UInt64 GetLocalExtraPosition() const\r
+    { return LocalHeaderPosition + FileHeaderWithNameSize; };\r
+  UInt64 GetDataPosition() const\r
+    { return GetLocalExtraPosition() + LocalExtraSize; };\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Zip/ZipOut.cpp b/CPP/7zip/Archive/Zip/ZipOut.cpp
new file mode 100755 (executable)
index 0000000..c8157b9
--- /dev/null
@@ -0,0 +1,289 @@
+// ZipOut.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/OffsetStream.h"\r
+\r
+#include "ZipOut.h"\r
+\r
+namespace NArchive {\r
+namespace NZip {\r
+\r
+void COutArchive::Create(IOutStream *outStream)\r
+{\r
+  if (!m_OutBuffer.Create(1 << 16))\r
+    throw CSystemException(E_OUTOFMEMORY);\r
+  m_Stream = outStream;\r
+  m_OutBuffer.SetStream(outStream);\r
+  m_OutBuffer.Init();\r
+  m_BasePosition = 0;\r
+}\r
+\r
+void COutArchive::MoveBasePosition(UInt64 distanceToMove)\r
+{\r
+  m_BasePosition += distanceToMove; // test overflow\r
+}\r
+\r
+void COutArchive::PrepareWriteCompressedDataZip64(UInt16 fileNameLength, bool isZip64, bool aesEncryption)\r
+{\r
+  m_IsZip64 = isZip64;\r
+  m_ExtraSize = isZip64 ? (4 + 8 + 8) : 0;\r
+  if (aesEncryption)\r
+    m_ExtraSize += 4 + 7;\r
+  m_LocalFileHeaderSize = 4 + NFileHeader::kLocalBlockSize + fileNameLength + m_ExtraSize;\r
+}\r
+\r
+void COutArchive::PrepareWriteCompressedData(UInt16 fileNameLength, UInt64 unPackSize, bool aesEncryption)\r
+{\r
+  // We test it to 0xF8000000 to support case when compressed size\r
+  // can be larger than uncompressed size.\r
+  PrepareWriteCompressedDataZip64(fileNameLength, unPackSize >= 0xF8000000, aesEncryption);\r
+}\r
+\r
+void COutArchive::PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize, bool aesEncryption)\r
+{\r
+  bool isUnPack64 = unPackSize >= 0xFFFFFFFF;\r
+  bool isPack64 = packSize >= 0xFFFFFFFF;\r
+  bool isZip64 = isPack64 || isUnPack64;\r
+  PrepareWriteCompressedDataZip64(fileNameLength, isZip64, aesEncryption);\r
+}\r
+\r
+void COutArchive::WriteBytes(const void *buffer, UInt32 size)\r
+{\r
+  m_OutBuffer.WriteBytes(buffer, size);\r
+  m_BasePosition += size;\r
+}\r
+\r
+void COutArchive::WriteByte(Byte b)\r
+{\r
+  WriteBytes(&b, 1);\r
+}\r
+\r
+void COutArchive::WriteUInt16(UInt16 value)\r
+{\r
+  for (int i = 0; i < 2; i++)\r
+  {\r
+    WriteByte((Byte)value);\r
+    value >>= 8;\r
+  }\r
+}\r
+\r
+void COutArchive::WriteUInt32(UInt32 value)\r
+{\r
+  for (int i = 0; i < 4; i++)\r
+  {\r
+    WriteByte((Byte)value);\r
+    value >>= 8;\r
+  }\r
+}\r
+\r
+void COutArchive::WriteUInt64(UInt64 value)\r
+{\r
+  for (int i = 0; i < 8; i++)\r
+  {\r
+    WriteByte((Byte)value);\r
+    value >>= 8;\r
+  }\r
+}\r
+\r
+void COutArchive::WriteExtra(const CExtraBlock &extra)\r
+{\r
+  if (extra.SubBlocks.Size() != 0)\r
+  {\r
+    for (int i = 0; i < extra.SubBlocks.Size(); i++)\r
+    {\r
+      const CExtraSubBlock &subBlock = extra.SubBlocks[i];\r
+      WriteUInt16(subBlock.ID);\r
+      WriteUInt16((UInt16)subBlock.Data.GetCapacity());\r
+      WriteBytes(subBlock.Data, (UInt32)subBlock.Data.GetCapacity());\r
+    }\r
+  }\r
+}\r
+\r
+void COutArchive::SeekTo(UInt64 offset)\r
+{\r
+  HRESULT res = m_Stream->Seek(offset, STREAM_SEEK_SET, NULL);\r
+  if (res != S_OK)\r
+    throw CSystemException(res);\r
+}\r
+\r
+void COutArchive::WriteLocalHeader(const CLocalItem &item)\r
+{\r
+  SeekTo(m_BasePosition);\r
+  \r
+  bool isZip64 = m_IsZip64 || item.PackSize >= 0xFFFFFFFF || item.UnPackSize >= 0xFFFFFFFF;\r
+  \r
+  WriteUInt32(NSignature::kLocalFileHeader);\r
+  {\r
+    Byte ver = item.ExtractVersion.Version;\r
+    if (isZip64 && ver < NFileHeader::NCompressionMethod::kExtractVersion_Zip64)\r
+      ver = NFileHeader::NCompressionMethod::kExtractVersion_Zip64;\r
+    WriteByte(ver);\r
+  }\r
+  WriteByte(item.ExtractVersion.HostOS);\r
+  WriteUInt16(item.Flags);\r
+  WriteUInt16(item.CompressionMethod);\r
+  WriteUInt32(item.Time);\r
+  WriteUInt32(item.FileCRC);\r
+  WriteUInt32(isZip64 ? 0xFFFFFFFF: (UInt32)item.PackSize);\r
+  WriteUInt32(isZip64 ? 0xFFFFFFFF: (UInt32)item.UnPackSize);\r
+  WriteUInt16((UInt16)item.Name.Length());\r
+  {\r
+    UInt16 localExtraSize = (UInt16)((isZip64 ? (4 + 16): 0) + item.LocalExtra.GetSize());\r
+    if (localExtraSize > m_ExtraSize)\r
+      throw CSystemException(E_FAIL);\r
+  }\r
+  WriteUInt16((UInt16)m_ExtraSize); // test it;\r
+  WriteBytes((const char *)item.Name, item.Name.Length());\r
+\r
+  UInt32 extraPos = 0;\r
+  if (isZip64)\r
+  {\r
+    extraPos += 4 + 16;\r
+    WriteUInt16(NFileHeader::NExtraID::kZip64);\r
+    WriteUInt16(16);\r
+    WriteUInt64(item.UnPackSize);\r
+    WriteUInt64(item.PackSize);\r
+  }\r
+\r
+  WriteExtra(item.LocalExtra);\r
+  extraPos += (UInt32)item.LocalExtra.GetSize();\r
+  for (; extraPos < m_ExtraSize; extraPos++)\r
+    WriteByte(0);\r
+\r
+  m_OutBuffer.FlushWithCheck();\r
+  MoveBasePosition(item.PackSize);\r
+  SeekTo(m_BasePosition);\r
+}\r
+\r
+void COutArchive::WriteCentralHeader(const CItem &item)\r
+{\r
+  bool isUnPack64 = item.UnPackSize >= 0xFFFFFFFF;\r
+  bool isPack64 = item.PackSize >= 0xFFFFFFFF;\r
+  bool isPosition64 = item.LocalHeaderPosition >= 0xFFFFFFFF;\r
+  bool isZip64  = isPack64 || isUnPack64 || isPosition64;\r
+  \r
+  WriteUInt32(NSignature::kCentralFileHeader);\r
+  WriteByte(item.MadeByVersion.Version);\r
+  WriteByte(item.MadeByVersion.HostOS);\r
+  {\r
+    Byte ver = item.ExtractVersion.Version;\r
+    if (isZip64 && ver < NFileHeader::NCompressionMethod::kExtractVersion_Zip64)\r
+      ver = NFileHeader::NCompressionMethod::kExtractVersion_Zip64;\r
+    WriteByte(ver);\r
+  }\r
+  WriteByte(item.ExtractVersion.HostOS);\r
+  WriteUInt16(item.Flags);\r
+  WriteUInt16(item.CompressionMethod);\r
+  WriteUInt32(item.Time);\r
+  WriteUInt32(item.FileCRC);\r
+  WriteUInt32(isPack64 ? 0xFFFFFFFF: (UInt32)item.PackSize);\r
+  WriteUInt32(isUnPack64 ? 0xFFFFFFFF: (UInt32)item.UnPackSize);\r
+  WriteUInt16((UInt16)item.Name.Length());\r
+  UInt16 zip64ExtraSize = (UInt16)((isUnPack64 ? 8: 0) +  (isPack64 ? 8: 0) + (isPosition64 ? 8: 0));\r
+  const UInt16 kNtfsExtraSize = 4 + 2 + 2 + (3 * 8);\r
+  UInt16 centralExtraSize = (UInt16)(isZip64 ? (4 + zip64ExtraSize) : 0) + (item.NtfsTimeIsDefined ? (4 + kNtfsExtraSize) : 0);\r
+  centralExtraSize = (UInt16)(centralExtraSize + item.CentralExtra.GetSize());\r
+  WriteUInt16(centralExtraSize); // test it;\r
+  WriteUInt16((UInt16)item.Comment.GetCapacity());\r
+  WriteUInt16(0); // DiskNumberStart;\r
+  WriteUInt16(item.InternalAttributes);\r
+  WriteUInt32(item.ExternalAttributes);\r
+  WriteUInt32(isPosition64 ? 0xFFFFFFFF: (UInt32)item.LocalHeaderPosition);\r
+  WriteBytes((const char *)item.Name, item.Name.Length());\r
+  if (isZip64)\r
+  {\r
+    WriteUInt16(NFileHeader::NExtraID::kZip64);\r
+    WriteUInt16(zip64ExtraSize);\r
+    if(isUnPack64)\r
+      WriteUInt64(item.UnPackSize);\r
+    if(isPack64)\r
+      WriteUInt64(item.PackSize);\r
+    if(isPosition64)\r
+      WriteUInt64(item.LocalHeaderPosition);\r
+  }\r
+  if (item.NtfsTimeIsDefined)\r
+  {\r
+    WriteUInt16(NFileHeader::NExtraID::kNTFS);\r
+    WriteUInt16(kNtfsExtraSize);\r
+    WriteUInt32(0); // reserved\r
+    WriteUInt16(NFileHeader::NNtfsExtra::kTagTime);\r
+    WriteUInt16(8 * 3);\r
+    WriteUInt32(item.NtfsMTime.dwLowDateTime);\r
+    WriteUInt32(item.NtfsMTime.dwHighDateTime);\r
+    WriteUInt32(item.NtfsATime.dwLowDateTime);\r
+    WriteUInt32(item.NtfsATime.dwHighDateTime);\r
+    WriteUInt32(item.NtfsCTime.dwLowDateTime);\r
+    WriteUInt32(item.NtfsCTime.dwHighDateTime);\r
+  }\r
+  WriteExtra(item.CentralExtra);\r
+  if (item.Comment.GetCapacity() > 0)\r
+    WriteBytes(item.Comment, (UInt32)item.Comment.GetCapacity());\r
+}\r
+\r
+void COutArchive::WriteCentralDir(const CObjectVector<CItem> &items, const CByteBuffer *comment)\r
+{\r
+  SeekTo(m_BasePosition);\r
+  \r
+  UInt64 cdOffset = GetCurrentPosition();\r
+  for(int i = 0; i < items.Size(); i++)\r
+    WriteCentralHeader(items[i]);\r
+  UInt64 cd64EndOffset = GetCurrentPosition();\r
+  UInt64 cdSize = cd64EndOffset - cdOffset;\r
+  bool cdOffset64 = cdOffset >= 0xFFFFFFFF;\r
+  bool cdSize64 = cdSize >= 0xFFFFFFFF;\r
+  bool items64 = items.Size() >= 0xFFFF;\r
+  bool isZip64 = (cdOffset64 || cdSize64 || items64);\r
+\r
+  if (isZip64)\r
+  {\r
+    WriteUInt32(NSignature::kZip64EndOfCentralDir);\r
+    WriteUInt64(kZip64EcdSize); // ThisDiskNumber = 0;\r
+    WriteUInt16(45); // version\r
+    WriteUInt16(45); // version\r
+    WriteUInt32(0); // ThisDiskNumber = 0;\r
+    WriteUInt32(0); // StartCentralDirectoryDiskNumber;;\r
+    WriteUInt64((UInt64)items.Size());\r
+    WriteUInt64((UInt64)items.Size());\r
+    WriteUInt64((UInt64)cdSize);\r
+    WriteUInt64((UInt64)cdOffset);\r
+\r
+    WriteUInt32(NSignature::kZip64EndOfCentralDirLocator);\r
+    WriteUInt32(0); // number of the disk with the start of the zip64 end of central directory\r
+    WriteUInt64(cd64EndOffset);\r
+    WriteUInt32(1); // total number of disks\r
+  }\r
+  WriteUInt32(NSignature::kEndOfCentralDir);\r
+  WriteUInt16(0); // ThisDiskNumber = 0;\r
+  WriteUInt16(0); // StartCentralDirectoryDiskNumber;\r
+  WriteUInt16((UInt16)(items64 ? 0xFFFF: items.Size()));\r
+  WriteUInt16((UInt16)(items64 ? 0xFFFF: items.Size()));\r
+  WriteUInt32(cdSize64 ? 0xFFFFFFFF: (UInt32)cdSize);\r
+  WriteUInt32(cdOffset64 ? 0xFFFFFFFF: (UInt32)cdOffset);\r
+  UInt32 commentSize = (UInt32)(comment ? comment->GetCapacity() : 0);\r
+  WriteUInt16((UInt16)commentSize);\r
+  if (commentSize > 0)\r
+    WriteBytes((const Byte *)*comment, commentSize);\r
+  m_OutBuffer.FlushWithCheck();\r
+}\r
+\r
+void COutArchive::CreateStreamForCompressing(IOutStream **outStream)\r
+{\r
+  COffsetOutStream *streamSpec = new COffsetOutStream;\r
+  CMyComPtr<IOutStream> tempStream(streamSpec);\r
+  streamSpec->Init(m_Stream, m_BasePosition + m_LocalFileHeaderSize);\r
+  *outStream = tempStream.Detach();\r
+}\r
+\r
+void COutArchive::SeekToPackedDataPosition()\r
+{\r
+  SeekTo(m_BasePosition + m_LocalFileHeaderSize);\r
+}\r
+\r
+void COutArchive::CreateStreamForCopying(ISequentialOutStream **outStream)\r
+{\r
+  CMyComPtr<ISequentialOutStream> tempStream(m_Stream);\r
+  *outStream = tempStream.Detach();\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Zip/ZipOut.h b/CPP/7zip/Archive/Zip/ZipOut.h
new file mode 100755 (executable)
index 0000000..327eef2
--- /dev/null
@@ -0,0 +1,56 @@
+// ZipOut.h\r
+\r
+#ifndef __ZIP_OUT_H\r
+#define __ZIP_OUT_H\r
+\r
+#include "Common/MyCom.h"\r
+\r
+#include "../../IStream.h"\r
+#include "../../Common/OutBuffer.h"\r
+\r
+#include "ZipItem.h"\r
+\r
+namespace NArchive {\r
+namespace NZip {\r
+\r
+// can throw CSystemException and COutBufferException\r
+  \r
+class COutArchive\r
+{\r
+  CMyComPtr<IOutStream> m_Stream;\r
+  COutBuffer m_OutBuffer;\r
+\r
+  UInt64 m_BasePosition;\r
+  UInt32 m_LocalFileHeaderSize;\r
+  UInt32 m_ExtraSize;\r
+  bool m_IsZip64;\r
+\r
+  void WriteBytes(const void *buffer, UInt32 size);\r
+  void WriteByte(Byte b);\r
+  void WriteUInt16(UInt16 value);\r
+  void WriteUInt32(UInt32 value);\r
+  void WriteUInt64(UInt64 value);\r
+\r
+  void WriteExtraHeader(const CItem &item);\r
+  void WriteCentralHeader(const CItem &item);\r
+  void WriteExtra(const CExtraBlock &extra);\r
+  void SeekTo(UInt64 offset);\r
+public:\r
+  void Create(IOutStream *outStream);\r
+  void MoveBasePosition(UInt64 distanceToMove);\r
+  UInt64 GetCurrentPosition() const { return m_BasePosition; };\r
+  void PrepareWriteCompressedDataZip64(UInt16 fileNameLength, bool isZip64, bool aesEncryption);\r
+  void PrepareWriteCompressedData(UInt16 fileNameLength, UInt64 unPackSize, bool aesEncryption);\r
+  void PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize, bool aesEncryption);\r
+  void WriteLocalHeader(const CLocalItem &item);\r
+\r
+  void WriteCentralDir(const CObjectVector<CItem> &items, const CByteBuffer *comment);\r
+\r
+  void CreateStreamForCompressing(IOutStream **outStream);\r
+  void CreateStreamForCopying(ISequentialOutStream **outStream);\r
+  void SeekToPackedDataPosition();\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/Zip/ZipRegister.cpp b/CPP/7zip/Archive/Zip/ZipRegister.cpp
new file mode 100755 (executable)
index 0000000..e97a679
--- /dev/null
@@ -0,0 +1,18 @@
+// ZipRegister.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/RegisterArc.h"\r
+\r
+#include "ZipHandler.h"\r
+static IInArchive *CreateArc() { return new NArchive::NZip::CHandler; }\r
+#ifndef EXTRACT_ONLY\r
+static IOutArchive *CreateArcOut() { return new NArchive::NZip::CHandler; }\r
+#else\r
+#define CreateArcOut 0\r
+#endif\r
+\r
+static CArcInfo g_ArcInfo =\r
+  { L"zip", L"zip jar xpi odt ods docx xlsx", 0, 1, { 0x50, 0x4B, 0x03, 0x04 }, 4, false, CreateArc, CreateArcOut };\r
+\r
+REGISTER_ARC(Zip)\r
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
new file mode 100755 (executable)
index 0000000..9327158
--- /dev/null
@@ -0,0 +1,1068 @@
+// ZipUpdate.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/Alloc.h"\r
+\r
+#include "Common/AutoPtr.h"\r
+#include "Common/Defs.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/Defs.h"\r
+#include "Windows/Thread.h"\r
+\r
+#include "../../Common/CreateCoder.h"\r
+#include "../../Common/LimitedStreams.h"\r
+#include "../../Common/OutMemStream.h"\r
+#include "../../Common/ProgressUtils.h"\r
+#ifndef _7ZIP_ST\r
+#include "../../Common/ProgressMt.h"\r
+#endif\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "../../Compress/CopyCoder.h"\r
+\r
+#include "ZipAddCommon.h"\r
+#include "ZipOut.h"\r
+#include "ZipUpdate.h"\r
+\r
+using namespace NWindows;\r
+using namespace NSynchronization;\r
+\r
+namespace NArchive {\r
+namespace NZip {\r
+\r
+static const Byte kHostOS =\r
+  #ifdef _WIN32\r
+  NFileHeader::NHostOS::kFAT;\r
+  #else\r
+  NFileHeader::NHostOS::kUnix;\r
+  #endif\r
+\r
+static const Byte kMadeByHostOS = kHostOS;\r
+static const Byte kExtractHostOS = kHostOS;\r
+\r
+static const Byte kMethodForDirectory = NFileHeader::NCompressionMethod::kStored;\r
+\r
+static HRESULT CopyBlockToArchive(ISequentialInStream *inStream,\r
+    COutArchive &outArchive, ICompressProgressInfo *progress)\r
+{\r
+  CMyComPtr<ISequentialOutStream> outStream;\r
+  outArchive.CreateStreamForCopying(&outStream);\r
+  return NCompress::CopyStream(inStream, outStream, progress);\r
+}\r
+\r
+static HRESULT WriteRange(IInStream *inStream, COutArchive &outArchive,\r
+    const CUpdateRange &range, ICompressProgressInfo *progress)\r
+{\r
+  UInt64 position;\r
+  RINOK(inStream->Seek(range.Position, STREAM_SEEK_SET, &position));\r
+\r
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\r
+  CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec);\r
+  streamSpec->SetStream(inStream);\r
+  streamSpec->Init(range.Size);\r
+\r
+  RINOK(CopyBlockToArchive(inStreamLimited, outArchive, progress));\r
+  return progress->SetRatioInfo(&range.Size, &range.Size);\r
+}\r
+\r
+static void SetFileHeader(\r
+    COutArchive &archive,\r
+    const CCompressionMethodMode &options,\r
+    const CUpdateItem &ui,\r
+    CItem &item)\r
+{\r
+  item.UnPackSize = ui.Size;\r
+  bool isDir;\r
+\r
+  item.ClearFlags();\r
+\r
+  if (ui.NewProperties)\r
+  {\r
+    isDir = ui.IsDir;\r
+    item.Name = ui.Name;\r
+    item.SetUtf8(ui.IsUtf8);\r
+    item.ExternalAttributes = ui.Attributes;\r
+    item.Time = ui.Time;\r
+    item.NtfsMTime = ui.NtfsMTime;\r
+    item.NtfsATime = ui.NtfsATime;\r
+    item.NtfsCTime = ui.NtfsCTime;\r
+    item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined;\r
+  }\r
+  else\r
+    isDir = item.IsDir();\r
+\r
+  item.LocalHeaderPosition = archive.GetCurrentPosition();\r
+  item.MadeByVersion.HostOS = kMadeByHostOS;\r
+  item.MadeByVersion.Version = NFileHeader::NCompressionMethod::kMadeByProgramVersion;\r
+  \r
+  item.ExtractVersion.HostOS = kExtractHostOS;\r
+\r
+  item.InternalAttributes = 0; // test it\r
+  item.SetEncrypted(!isDir && options.PasswordIsDefined);\r
+  if (isDir)\r
+  {\r
+    item.ExtractVersion.Version = NFileHeader::NCompressionMethod::kExtractVersion_Dir;\r
+    item.CompressionMethod = kMethodForDirectory;\r
+    item.PackSize = 0;\r
+    item.FileCRC = 0; // test it\r
+  }\r
+}\r
+\r
+static void SetItemInfoFromCompressingResult(const CCompressingResult &compressingResult,\r
+    bool isAesMode, Byte aesKeyMode, CItem &item)\r
+{\r
+  item.ExtractVersion.Version = compressingResult.ExtractVersion;\r
+  item.CompressionMethod = compressingResult.Method;\r
+  item.FileCRC = compressingResult.CRC;\r
+  item.UnPackSize = compressingResult.UnpackSize;\r
+  item.PackSize = compressingResult.PackSize;\r
+\r
+  item.LocalExtra.Clear();\r
+  item.CentralExtra.Clear();\r
+\r
+  if (isAesMode)\r
+  {\r
+    CWzAesExtraField wzAesField;\r
+    wzAesField.Strength = aesKeyMode;\r
+    wzAesField.Method = compressingResult.Method;\r
+    item.CompressionMethod = NFileHeader::NCompressionMethod::kWzAES;\r
+    item.FileCRC = 0;\r
+    CExtraSubBlock sb;\r
+    wzAesField.SetSubBlock(sb);\r
+    item.LocalExtra.SubBlocks.Add(sb);\r
+    item.CentralExtra.SubBlocks.Add(sb);\r
+  }\r
+}\r
+\r
+#ifndef _7ZIP_ST\r
+\r
+static THREAD_FUNC_DECL CoderThread(void *threadCoderInfo);\r
+\r
+struct CThreadInfo\r
+{\r
+  #ifdef EXTERNAL_CODECS\r
+  CMyComPtr<ICompressCodecsInfo> _codecsInfo;\r
+  const CObjectVector<CCodecInfoEx> *_externalCodecs;\r
+  #endif\r
+\r
+  NWindows::CThread Thread;\r
+  NWindows::NSynchronization::CAutoResetEvent CompressEvent;\r
+  NWindows::NSynchronization::CAutoResetEvent CompressionCompletedEvent;\r
+  bool ExitThread;\r
+\r
+  CMtCompressProgress *ProgressSpec;\r
+  CMyComPtr<ICompressProgressInfo> Progress;\r
+\r
+  COutMemStream *OutStreamSpec;\r
+  CMyComPtr<IOutStream> OutStream;\r
+  CMyComPtr<ISequentialInStream> InStream;\r
+\r
+  CAddCommon Coder;\r
+  HRESULT Result;\r
+  CCompressingResult CompressingResult;\r
+\r
+  bool IsFree;\r
+  UInt32 UpdateIndex;\r
+\r
+  CThreadInfo(const CCompressionMethodMode &options):\r
+      ExitThread(false),\r
+      ProgressSpec(0),\r
+      OutStreamSpec(0),\r
+      Coder(options)\r
+  {}\r
+  \r
+  HRESULT CreateEvents()\r
+  {\r
+    RINOK(CompressEvent.CreateIfNotCreated());\r
+    return CompressionCompletedEvent.CreateIfNotCreated();\r
+  }\r
+  HRes CreateThread() { return Thread.Create(CoderThread, this); }\r
+\r
+  void WaitAndCode();\r
+  void StopWaitClose()\r
+  {\r
+    ExitThread = true;\r
+    if (OutStreamSpec != 0)\r
+      OutStreamSpec->StopWriting(E_ABORT);\r
+    if (CompressEvent.IsCreated())\r
+      CompressEvent.Set();\r
+    Thread.Wait();\r
+    Thread.Close();\r
+  }\r
+\r
+};\r
+\r
+void CThreadInfo::WaitAndCode()\r
+{\r
+  for (;;)\r
+  {\r
+    CompressEvent.Lock();\r
+    if (ExitThread)\r
+      return;\r
+    Result = Coder.Compress(\r
+        #ifdef EXTERNAL_CODECS\r
+        _codecsInfo, _externalCodecs,\r
+        #endif\r
+        InStream, OutStream, Progress, CompressingResult);\r
+    if (Result == S_OK && Progress)\r
+      Result = Progress->SetRatioInfo(&CompressingResult.UnpackSize, &CompressingResult.PackSize);\r
+    CompressionCompletedEvent.Set();\r
+  }\r
+}\r
+\r
+static THREAD_FUNC_DECL CoderThread(void *threadCoderInfo)\r
+{\r
+  ((CThreadInfo *)threadCoderInfo)->WaitAndCode();\r
+  return 0;\r
+}\r
+\r
+class CThreads\r
+{\r
+public:\r
+  CObjectVector<CThreadInfo> Threads;\r
+  ~CThreads()\r
+  {\r
+    for (int i = 0; i < Threads.Size(); i++)\r
+      Threads[i].StopWaitClose();\r
+  }\r
+};\r
+\r
+struct CMemBlocks2: public CMemLockBlocks\r
+{\r
+  CCompressingResult CompressingResult;\r
+  bool Defined;\r
+  bool Skip;\r
+  CMemBlocks2(): Defined(false), Skip(false) {}\r
+};\r
+\r
+class CMemRefs\r
+{\r
+public:\r
+  CMemBlockManagerMt *Manager;\r
+  CObjectVector<CMemBlocks2> Refs;\r
+  CMemRefs(CMemBlockManagerMt *manager): Manager(manager) {} ;\r
+  ~CMemRefs()\r
+  {\r
+    for (int i = 0; i < Refs.Size(); i++)\r
+      Refs[i].FreeOpt(Manager);\r
+  }\r
+};\r
+\r
+class CMtProgressMixer2:\r
+  public ICompressProgressInfo,\r
+  public CMyUnknownImp\r
+{\r
+  UInt64 ProgressOffset;\r
+  UInt64 InSizes[2];\r
+  UInt64 OutSizes[2];\r
+  CMyComPtr<IProgress> Progress;\r
+  CMyComPtr<ICompressProgressInfo> RatioProgress;\r
+  bool _inSizeIsMain;\r
+public:\r
+  NWindows::NSynchronization::CCriticalSection CriticalSection;\r
+  MY_UNKNOWN_IMP\r
+  void Create(IProgress *progress, bool inSizeIsMain);\r
+  void SetProgressOffset(UInt64 progressOffset);\r
+  HRESULT SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize);\r
+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);\r
+};\r
+\r
+void CMtProgressMixer2::Create(IProgress *progress, bool inSizeIsMain)\r
+{\r
+  Progress = progress;\r
+  Progress.QueryInterface(IID_ICompressProgressInfo, &RatioProgress);\r
+  _inSizeIsMain = inSizeIsMain;\r
+  ProgressOffset = InSizes[0] = InSizes[1] = OutSizes[0] = OutSizes[1] = 0;\r
+}\r
+\r
+void CMtProgressMixer2::SetProgressOffset(UInt64 progressOffset)\r
+{\r
+  CriticalSection.Enter();\r
+  InSizes[1] = OutSizes[1] = 0;\r
+  ProgressOffset = progressOffset;\r
+  CriticalSection.Leave();\r
+}\r
+\r
+HRESULT CMtProgressMixer2::SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize)\r
+{\r
+  NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);\r
+  if (index == 0 && RatioProgress)\r
+  {\r
+    RINOK(RatioProgress->SetRatioInfo(inSize, outSize));\r
+  }\r
+  if (inSize != 0)\r
+    InSizes[index] = *inSize;\r
+  if (outSize != 0)\r
+    OutSizes[index] = *outSize;\r
+  UInt64 v = ProgressOffset + (_inSizeIsMain  ?\r
+      (InSizes[0] + InSizes[1]) :\r
+      (OutSizes[0] + OutSizes[1]));\r
+  return Progress->SetCompleted(&v);\r
+}\r
+\r
+STDMETHODIMP CMtProgressMixer2::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)\r
+{\r
+  return SetRatioInfo(0, inSize, outSize);\r
+}\r
+\r
+class CMtProgressMixer:\r
+  public ICompressProgressInfo,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  CMtProgressMixer2 *Mixer2;\r
+  CMyComPtr<ICompressProgressInfo> RatioProgress;\r
+  void Create(IProgress *progress, bool inSizeIsMain);\r
+  MY_UNKNOWN_IMP\r
+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);\r
+};\r
+\r
+void CMtProgressMixer::Create(IProgress *progress, bool inSizeIsMain)\r
+{\r
+  Mixer2 = new CMtProgressMixer2;\r
+  RatioProgress = Mixer2;\r
+  Mixer2->Create(progress, inSizeIsMain);\r
+}\r
+\r
+STDMETHODIMP CMtProgressMixer::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)\r
+{\r
+  return Mixer2->SetRatioInfo(1, inSize, outSize);\r
+}\r
+\r
+\r
+#endif\r
+\r
+\r
+static HRESULT UpdateItemOldData(COutArchive &archive,\r
+    IInStream *inStream,\r
+    const CUpdateItem &ui, CItemEx &item,\r
+    /* bool izZip64, */\r
+    ICompressProgressInfo *progress,\r
+    UInt64 &complexity)\r
+{\r
+  if (ui.NewProperties)\r
+  {\r
+    if (item.HasDescriptor())\r
+      return E_NOTIMPL;\r
+    \r
+    // use old name size.\r
+    // CUpdateRange range(item.GetLocalExtraPosition(), item.LocalExtraSize + item.PackSize);\r
+    CUpdateRange range(item.GetDataPosition(), item.PackSize);\r
+    \r
+    // item.ExternalAttributes = ui.Attributes;\r
+    // Test it\r
+    item.Name = ui.Name;\r
+    item.SetUtf8(ui.IsUtf8);\r
+    item.Time = ui.Time;\r
+    item.NtfsMTime = ui.NtfsMTime;\r
+    item.NtfsATime = ui.NtfsATime;\r
+    item.NtfsCTime = ui.NtfsCTime;\r
+    item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined;\r
+\r
+    item.CentralExtra.RemoveUnknownSubBlocks();\r
+    item.LocalExtra.RemoveUnknownSubBlocks();\r
+    \r
+    archive.PrepareWriteCompressedData2((UInt16)item.Name.Length(), item.UnPackSize, item.PackSize, item.LocalExtra.HasWzAesField());\r
+    item.LocalHeaderPosition = archive.GetCurrentPosition();\r
+    archive.SeekToPackedDataPosition();\r
+    RINOK(WriteRange(inStream, archive, range, progress));\r
+    complexity += range.Size;\r
+    archive.WriteLocalHeader(item);\r
+  }\r
+  else\r
+  {\r
+    CUpdateRange range(item.LocalHeaderPosition, item.GetLocalFullSize());\r
+    \r
+    // set new header position\r
+    item.LocalHeaderPosition = archive.GetCurrentPosition();\r
+    \r
+    RINOK(WriteRange(inStream, archive, range, progress));\r
+    complexity += range.Size;\r
+    archive.MoveBasePosition(range.Size);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+static void WriteDirHeader(COutArchive &archive, const CCompressionMethodMode *options,\r
+    const CUpdateItem &ui, CItemEx &item)\r
+{\r
+  SetFileHeader(archive, *options, ui, item);\r
+  archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), ui.Size, options->IsAesMode);\r
+  archive.WriteLocalHeader(item);\r
+}\r
+\r
+static HRESULT Update2St(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    COutArchive &archive,\r
+    CInArchive *inArchive,\r
+    IInStream *inStream,\r
+    const CObjectVector<CItemEx> &inputItems,\r
+    const CObjectVector<CUpdateItem> &updateItems,\r
+    const CCompressionMethodMode *options,\r
+    const CByteBuffer *comment,\r
+    IArchiveUpdateCallback *updateCallback)\r
+{\r
+  CLocalProgress *lps = new CLocalProgress;\r
+  CMyComPtr<ICompressProgressInfo> progress = lps;\r
+  lps->Init(updateCallback, true);\r
+\r
+  CAddCommon compressor(*options);\r
+  \r
+  CObjectVector<CItem> items;\r
+  UInt64 unpackSizeTotal = 0, packSizeTotal = 0;\r
+\r
+  for (int itemIndex = 0; itemIndex < updateItems.Size(); itemIndex++)\r
+  {\r
+    lps->InSize = unpackSizeTotal;\r
+    lps->OutSize = packSizeTotal;\r
+    RINOK(lps->SetCur());\r
+    const CUpdateItem &ui = updateItems[itemIndex];\r
+    CItemEx item;\r
+    if (!ui.NewProperties || !ui.NewData)\r
+    {\r
+      item = inputItems[ui.IndexInArchive];\r
+      if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK)\r
+        return E_NOTIMPL;\r
+    }\r
+\r
+    if (ui.NewData)\r
+    {\r
+      bool isDir = ((ui.NewProperties) ? ui.IsDir : item.IsDir());\r
+      if (isDir)\r
+      {\r
+        WriteDirHeader(archive, options, ui, item);\r
+      }\r
+      else\r
+      {\r
+        CMyComPtr<ISequentialInStream> fileInStream;\r
+        HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream);\r
+        if (res == S_FALSE)\r
+        {\r
+          lps->ProgressOffset += ui.Size;\r
+          RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));\r
+          continue;\r
+        }\r
+        RINOK(res);\r
+\r
+        // file Size can be 64-bit !!!\r
+        SetFileHeader(archive, *options, ui, item);\r
+        archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), ui.Size, options->IsAesMode);\r
+        CCompressingResult compressingResult;\r
+        CMyComPtr<IOutStream> outStream;\r
+        archive.CreateStreamForCompressing(&outStream);\r
+        RINOK(compressor.Compress(\r
+            EXTERNAL_CODECS_LOC_VARS\r
+            fileInStream, outStream, progress, compressingResult));\r
+        SetItemInfoFromCompressingResult(compressingResult, options->IsAesMode, options->AesKeyMode, item);\r
+        archive.WriteLocalHeader(item);\r
+        RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));\r
+        unpackSizeTotal += item.UnPackSize;\r
+        packSizeTotal += item.PackSize;\r
+      }\r
+    }\r
+    else\r
+    {\r
+      UInt64 complexity = 0;\r
+      lps->SendRatio = false;\r
+      RINOK(UpdateItemOldData(archive, inStream, ui, item, progress, complexity));\r
+      lps->SendRatio = true;\r
+      lps->ProgressOffset += complexity;\r
+    }\r
+    items.Add(item);\r
+    lps->ProgressOffset += NFileHeader::kLocalBlockSize;\r
+  }\r
+  archive.WriteCentralDir(items, comment);\r
+  return S_OK;\r
+}\r
+\r
+static HRESULT Update2(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    COutArchive &archive,\r
+    CInArchive *inArchive,\r
+    IInStream *inStream,\r
+    const CObjectVector<CItemEx> &inputItems,\r
+    const CObjectVector<CUpdateItem> &updateItems,\r
+    const CCompressionMethodMode *options,\r
+    const CByteBuffer *comment,\r
+    IArchiveUpdateCallback *updateCallback)\r
+{\r
+  UInt64 complexity = 0;\r
+  UInt64 numFilesToCompress = 0;\r
+  UInt64 numBytesToCompress = 0;\r
\r
+  int i;\r
+  for(i = 0; i < updateItems.Size(); i++)\r
+  {\r
+    const CUpdateItem &ui = updateItems[i];\r
+    if (ui.NewData)\r
+    {\r
+      complexity += ui.Size;\r
+      numBytesToCompress += ui.Size;\r
+      numFilesToCompress++;\r
+      /*\r
+      if (ui.Commented)\r
+        complexity += ui.CommentRange.Size;\r
+      */\r
+    }\r
+    else\r
+    {\r
+      CItemEx inputItem = inputItems[ui.IndexInArchive];\r
+      if (inArchive->ReadLocalItemAfterCdItemFull(inputItem) != S_OK)\r
+        return E_NOTIMPL;\r
+      complexity += inputItem.GetLocalFullSize();\r
+      // complexity += inputItem.GetCentralExtraPlusCommentSize();\r
+    }\r
+    complexity += NFileHeader::kLocalBlockSize;\r
+    complexity += NFileHeader::kCentralBlockSize;\r
+  }\r
+\r
+  if (comment)\r
+    complexity += comment->GetCapacity();\r
+  complexity++; // end of central\r
+  updateCallback->SetTotal(complexity);\r
+\r
+  CAddCommon compressor(*options);\r
+  \r
+  complexity = 0;\r
+  \r
+  #ifndef _7ZIP_ST\r
+\r
+  const size_t kNumMaxThreads = (1 << 10);\r
+  UInt32 numThreads = options->NumThreads;\r
+  if (numThreads > kNumMaxThreads)\r
+    numThreads = kNumMaxThreads;\r
+  \r
+  const size_t kMemPerThread = (1 << 25);\r
+  const size_t kBlockSize = 1 << 16;\r
+\r
+  CCompressionMethodMode options2;\r
+  if (options != 0)\r
+    options2 = *options;\r
+\r
+  bool mtMode = ((options != 0) && (numThreads > 1));\r
+\r
+  if (numFilesToCompress <= 1)\r
+    mtMode = false;\r
+\r
+  if (mtMode)\r
+  {\r
+    Byte method = options->MethodSequence.Front();\r
+    if (method == NFileHeader::NCompressionMethod::kStored && !options->PasswordIsDefined)\r
+      mtMode = false;\r
+    if (method == NFileHeader::NCompressionMethod::kBZip2)\r
+    {\r
+      UInt64 averageSize = numBytesToCompress / numFilesToCompress;\r
+      UInt32 blockSize = options->DicSize;\r
+      if (blockSize == 0)\r
+        blockSize = 1;\r
+      UInt64 averageNumberOfBlocks = averageSize / blockSize;\r
+      UInt32 numBZip2Threads = 32;\r
+      if (averageNumberOfBlocks < numBZip2Threads)\r
+        numBZip2Threads = (UInt32)averageNumberOfBlocks;\r
+      if (numBZip2Threads < 1)\r
+        numBZip2Threads = 1;\r
+      numThreads = numThreads / numBZip2Threads;\r
+      options2.NumThreads = numBZip2Threads;\r
+      if (numThreads <= 1)\r
+        mtMode = false;\r
+    }\r
+    if (method == NFileHeader::NCompressionMethod::kLZMA)\r
+    {\r
+      UInt32 numLZMAThreads = (options->Algo > 0 ? 2 : 1);\r
+      numThreads /= numLZMAThreads;\r
+      options2.NumThreads = numLZMAThreads;\r
+      if (numThreads <= 1)\r
+        mtMode = false;\r
+    }\r
+  }\r
+\r
+  if (!mtMode)\r
+  #endif\r
+    return Update2St(\r
+        EXTERNAL_CODECS_LOC_VARS\r
+        archive, inArchive,inStream,\r
+        inputItems, updateItems, options, comment, updateCallback);\r
+\r
+\r
+  #ifndef _7ZIP_ST\r
+\r
+  CObjectVector<CItem> items;\r
+\r
+  CMtProgressMixer *mtProgressMixerSpec = new CMtProgressMixer;\r
+  CMyComPtr<ICompressProgressInfo> progress = mtProgressMixerSpec;\r
+  mtProgressMixerSpec->Create(updateCallback, true);\r
+\r
+  CMtCompressProgressMixer mtCompressProgressMixer;\r
+  mtCompressProgressMixer.Init(numThreads, mtProgressMixerSpec->RatioProgress);\r
+\r
+  CMemBlockManagerMt memManager(kBlockSize);\r
+  CMemRefs refs(&memManager);\r
+\r
+  CThreads threads;\r
+  CRecordVector<HANDLE> compressingCompletedEvents;\r
+  CRecordVector<int> threadIndices;  // list threads in order of updateItems\r
+\r
+  {\r
+    RINOK(memManager.AllocateSpaceAlways((size_t)numThreads * (kMemPerThread / kBlockSize)));\r
+    for(i = 0; i < updateItems.Size(); i++)\r
+      refs.Refs.Add(CMemBlocks2());\r
+\r
+    UInt32 i;\r
+    for (i = 0; i < numThreads; i++)\r
+      threads.Threads.Add(CThreadInfo(options2));\r
+\r
+    for (i = 0; i < numThreads; i++)\r
+    {\r
+      CThreadInfo &threadInfo = threads.Threads[i];\r
+      #ifdef EXTERNAL_CODECS\r
+      threadInfo._codecsInfo = codecsInfo;\r
+      threadInfo._externalCodecs = externalCodecs;\r
+      #endif\r
+      RINOK(threadInfo.CreateEvents());\r
+      threadInfo.OutStreamSpec = new COutMemStream(&memManager);\r
+      RINOK(threadInfo.OutStreamSpec->CreateEvents());\r
+      threadInfo.OutStream = threadInfo.OutStreamSpec;\r
+      threadInfo.IsFree = true;\r
+      threadInfo.ProgressSpec = new CMtCompressProgress();\r
+      threadInfo.Progress = threadInfo.ProgressSpec;\r
+      threadInfo.ProgressSpec->Init(&mtCompressProgressMixer, (int)i);\r
+      RINOK(threadInfo.CreateThread());\r
+    }\r
+  }\r
+  int mtItemIndex = 0;\r
+\r
+  int itemIndex = 0;\r
+  int lastRealStreamItemIndex = -1;\r
+\r
+  while (itemIndex < updateItems.Size())\r
+  {\r
+    if ((UInt32)threadIndices.Size() < numThreads && mtItemIndex < updateItems.Size())\r
+    {\r
+      const CUpdateItem &ui = updateItems[mtItemIndex++];\r
+      if (!ui.NewData)\r
+        continue;\r
+      CItemEx item;\r
+      if (ui.NewProperties)\r
+      {\r
+        if (ui.IsDir)\r
+          continue;\r
+      }\r
+      else\r
+      {\r
+        item = inputItems[ui.IndexInArchive];\r
+        if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK)\r
+          return E_NOTIMPL;\r
+        if (item.IsDir())\r
+          continue;\r
+      }\r
+      CMyComPtr<ISequentialInStream> fileInStream;\r
+      {\r
+        NWindows::NSynchronization::CCriticalSectionLock lock(mtProgressMixerSpec->Mixer2->CriticalSection);\r
+        HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream);\r
+        if (res == S_FALSE)\r
+        {\r
+          complexity += ui.Size;\r
+          complexity += NFileHeader::kLocalBlockSize;\r
+          mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity);\r
+          RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));\r
+          refs.Refs[mtItemIndex - 1].Skip = true;\r
+          continue;\r
+        }\r
+        RINOK(res);\r
+        RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));\r
+      }\r
+\r
+      for (UInt32 i = 0; i < numThreads; i++)\r
+      {\r
+        CThreadInfo &threadInfo = threads.Threads[i];\r
+        if (threadInfo.IsFree)\r
+        {\r
+          threadInfo.IsFree = false;\r
+          threadInfo.InStream = fileInStream;\r
+\r
+          // !!!!! we must release ref before sending event\r
+          // BUG was here in v4.43 and v4.44. It could change ref counter in two threads in same time\r
+          fileInStream.Release();\r
+\r
+          threadInfo.OutStreamSpec->Init();\r
+          threadInfo.ProgressSpec->Reinit();\r
+          threadInfo.CompressEvent.Set();\r
+          threadInfo.UpdateIndex = mtItemIndex - 1;\r
+\r
+          compressingCompletedEvents.Add(threadInfo.CompressionCompletedEvent);\r
+          threadIndices.Add(i);\r
+          break;\r
+        }\r
+      }\r
+      continue;\r
+    }\r
+    \r
+    if (refs.Refs[itemIndex].Skip)\r
+    {\r
+      itemIndex++;\r
+      continue;\r
+    }\r
+\r
+    const CUpdateItem &ui = updateItems[itemIndex];\r
+\r
+    CItemEx item;\r
+    if (!ui.NewProperties || !ui.NewData)\r
+    {\r
+      item = inputItems[ui.IndexInArchive];\r
+      if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK)\r
+        return E_NOTIMPL;\r
+    }\r
+\r
+    if (ui.NewData)\r
+    {\r
+      bool isDir = ((ui.NewProperties) ? ui.IsDir : item.IsDir());\r
+      if (isDir)\r
+      {\r
+        WriteDirHeader(archive, options, ui, item);\r
+      }\r
+      else\r
+      {\r
+        if (lastRealStreamItemIndex < itemIndex)\r
+        {\r
+          lastRealStreamItemIndex = itemIndex;\r
+          SetFileHeader(archive, *options, ui, item);\r
+          // file Size can be 64-bit !!!\r
+          archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), ui.Size, options->IsAesMode);\r
+        }\r
+\r
+        CMemBlocks2 &memRef = refs.Refs[itemIndex];\r
+        if (memRef.Defined)\r
+        {\r
+          CMyComPtr<IOutStream> outStream;\r
+          archive.CreateStreamForCompressing(&outStream);\r
+          memRef.WriteToStream(memManager.GetBlockSize(), outStream);\r
+          SetItemInfoFromCompressingResult(memRef.CompressingResult,\r
+              options->IsAesMode, options->AesKeyMode, item);\r
+          SetFileHeader(archive, *options, ui, item);\r
+          archive.WriteLocalHeader(item);\r
+          // RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));\r
+          memRef.FreeOpt(&memManager);\r
+        }\r
+        else\r
+        {\r
+          {\r
+            CThreadInfo &thread = threads.Threads[threadIndices.Front()];\r
+            if (!thread.OutStreamSpec->WasUnlockEventSent())\r
+            {\r
+              CMyComPtr<IOutStream> outStream;\r
+              archive.CreateStreamForCompressing(&outStream);\r
+              thread.OutStreamSpec->SetOutStream(outStream);\r
+              thread.OutStreamSpec->SetRealStreamMode();\r
+            }\r
+          }\r
+\r
+          DWORD result = ::WaitForMultipleObjects(compressingCompletedEvents.Size(),\r
+              &compressingCompletedEvents.Front(), FALSE, INFINITE);\r
+          int t = (int)(result - WAIT_OBJECT_0);\r
+          CThreadInfo &threadInfo = threads.Threads[threadIndices[t]];\r
+          threadInfo.InStream.Release();\r
+          threadInfo.IsFree = true;\r
+          RINOK(threadInfo.Result);\r
+          threadIndices.Delete(t);\r
+          compressingCompletedEvents.Delete(t);\r
+          if (t == 0)\r
+          {\r
+            RINOK(threadInfo.OutStreamSpec->WriteToRealStream());\r
+            threadInfo.OutStreamSpec->ReleaseOutStream();\r
+            SetItemInfoFromCompressingResult(threadInfo.CompressingResult,\r
+                options->IsAesMode, options->AesKeyMode, item);\r
+            SetFileHeader(archive, *options, ui, item);\r
+            archive.WriteLocalHeader(item);\r
+          }\r
+          else\r
+          {\r
+            CMemBlocks2 &memRef = refs.Refs[threadInfo.UpdateIndex];\r
+            threadInfo.OutStreamSpec->DetachData(memRef);\r
+            memRef.CompressingResult = threadInfo.CompressingResult;\r
+            memRef.Defined = true;\r
+            continue;\r
+          }\r
+        }\r
+      }\r
+    }\r
+    else\r
+    {\r
+      RINOK(UpdateItemOldData(archive, inStream, ui, item, progress, complexity));\r
+    }\r
+    items.Add(item);\r
+    complexity += NFileHeader::kLocalBlockSize;\r
+    mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity);\r
+    itemIndex++;\r
+  }\r
+  archive.WriteCentralDir(items, comment);\r
+  return S_OK;\r
+  #endif\r
+}\r
+\r
+static const size_t kCacheBlockSize = (1 << 20);\r
+static const size_t kCacheSize = (kCacheBlockSize << 2);\r
+static const size_t kCacheMask = (kCacheSize - 1);\r
+\r
+class CCacheOutStream:\r
+  public IOutStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<IOutStream> _stream;\r
+  Byte *_cache;\r
+  UInt64 _virtPos;\r
+  UInt64 _virtSize;\r
+  UInt64 _phyPos;\r
+  UInt64 _phySize; // <= _virtSize\r
+  UInt64 _cachedPos; // (_cachedPos + _cachedSize) <= _virtSize\r
+  size_t _cachedSize;\r
+\r
+  HRESULT MyWrite(size_t size);\r
+  HRESULT MyWriteBlock()\r
+  {\r
+    return MyWrite(kCacheBlockSize - ((size_t)_cachedPos & (kCacheBlockSize - 1)));\r
+  }\r
+  HRESULT FlushCache();\r
+public:\r
+  CCacheOutStream(): _cache(0) {}\r
+  ~CCacheOutStream();\r
+  bool Allocate();\r
+  HRESULT Init(IOutStream *stream);\r
+  \r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);\r
+  STDMETHOD(SetSize)(UInt64 newSize);\r
+};\r
+\r
+bool CCacheOutStream::Allocate()\r
+{\r
+  if (!_cache)\r
+    _cache = (Byte *)::MidAlloc(kCacheSize);\r
+  return (_cache != NULL);\r
+}\r
+\r
+HRESULT CCacheOutStream::Init(IOutStream *stream)\r
+{\r
+  _virtPos = _phyPos = 0;\r
+  _stream = stream;\r
+  RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &_virtPos));\r
+  RINOK(_stream->Seek(0, STREAM_SEEK_END, &_virtSize));\r
+  RINOK(_stream->Seek(_virtPos, STREAM_SEEK_SET, &_virtPos));\r
+  _phyPos = _virtPos;\r
+  _phySize = _virtSize;\r
+  _cachedPos = 0;\r
+  _cachedSize = 0;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CCacheOutStream::MyWrite(size_t size)\r
+{\r
+  while (size != 0 && _cachedSize != 0)\r
+  {\r
+    if (_phyPos != _cachedPos)\r
+    {\r
+      RINOK(_stream->Seek(_cachedPos, STREAM_SEEK_SET, &_phyPos));\r
+    }\r
+    size_t pos = (size_t)_cachedPos & kCacheMask;\r
+    size_t curSize = MyMin(kCacheSize - pos, _cachedSize);\r
+    curSize = MyMin(curSize, size);\r
+    RINOK(WriteStream(_stream, _cache + pos, curSize));\r
+    _phyPos += curSize;\r
+    if (_phySize < _phyPos)\r
+      _phySize = _phyPos;\r
+    _cachedPos += curSize;\r
+    _cachedSize -= curSize;\r
+    size -= curSize;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CCacheOutStream::FlushCache()\r
+{\r
+  return MyWrite(_cachedSize);\r
+}\r
+\r
+CCacheOutStream::~CCacheOutStream()\r
+{\r
+  FlushCache();\r
+  if (_virtSize != _phySize)\r
+    _stream->SetSize(_virtSize);\r
+  if (_virtPos != _phyPos)\r
+    _stream->Seek(_virtPos, STREAM_SEEK_SET, NULL);\r
+  ::MidFree(_cache);\r
+}\r
+\r
+STDMETHODIMP CCacheOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize)\r
+    *processedSize = 0;\r
+  if (size == 0)\r
+    return S_OK;\r
+\r
+  UInt64 zerosStart = _virtPos;\r
+  if (_cachedSize != 0)\r
+  {\r
+    if (_virtPos < _cachedPos)\r
+    {\r
+      RINOK(FlushCache());\r
+    }\r
+    else\r
+    {\r
+      UInt64 cachedEnd = _cachedPos + _cachedSize;\r
+      if (cachedEnd < _virtPos)\r
+      {\r
+        if (cachedEnd < _phySize)\r
+        {\r
+          RINOK(FlushCache());\r
+        }\r
+        else\r
+          zerosStart = cachedEnd;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (_cachedSize == 0 && _phySize < _virtPos)\r
+    _cachedPos = zerosStart = _phySize;\r
+\r
+  if (zerosStart != _virtPos)\r
+  {\r
+    // write zeros to [cachedEnd ... _virtPos)\r
+    \r
+    for (;;)\r
+    {\r
+      UInt64 cachedEnd = _cachedPos + _cachedSize;\r
+      size_t endPos = (size_t)cachedEnd & kCacheMask;\r
+      size_t curSize = kCacheSize - endPos;\r
+      if (curSize > _virtPos - cachedEnd)\r
+        curSize = (size_t)(_virtPos - cachedEnd);\r
+      if (curSize == 0)\r
+        break;\r
+      while (curSize > (kCacheSize - _cachedSize))\r
+      {\r
+        RINOK(MyWriteBlock());\r
+      }\r
+      memset(_cache + endPos, 0, curSize);\r
+      _cachedSize += curSize;\r
+    }\r
+  }\r
+\r
+  if (_cachedSize == 0)\r
+    _cachedPos = _virtPos;\r
+\r
+  size_t pos = (size_t)_virtPos & kCacheMask;\r
+  size = (UInt32)MyMin((size_t)size, kCacheSize - pos);\r
+  UInt64 cachedEnd = _cachedPos + _cachedSize;\r
+  if (_virtPos != cachedEnd) // _virtPos < cachedEnd\r
+    size = (UInt32)MyMin((size_t)size, (size_t)(cachedEnd - _virtPos));\r
+  else\r
+  {\r
+    // _virtPos == cachedEnd\r
+    if (_cachedSize == kCacheSize)\r
+    {\r
+      RINOK(MyWriteBlock());\r
+    }\r
+    size_t startPos = (size_t)_cachedPos & kCacheMask;\r
+    if (startPos > pos)\r
+      size = (UInt32)MyMin((size_t)size, (size_t)(startPos - pos));\r
+    _cachedSize += size;\r
+  }\r
+  memcpy(_cache + pos, data, size);\r
+  if (processedSize)\r
+    *processedSize = size;\r
+  _virtPos += size;\r
+  if (_virtSize < _virtPos)\r
+    _virtSize = _virtPos;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CCacheOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)\r
+{\r
+  switch(seekOrigin)\r
+  {\r
+    case STREAM_SEEK_SET: _virtPos = offset; break;\r
+    case STREAM_SEEK_CUR: _virtPos += offset; break;\r
+    case STREAM_SEEK_END: _virtPos = _virtSize + offset; break;\r
+    default: return STG_E_INVALIDFUNCTION;\r
+  }\r
+  if (newPosition)\r
+    *newPosition = _virtPos;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CCacheOutStream::SetSize(UInt64 newSize)\r
+{\r
+  _virtSize = newSize;\r
+  if (newSize < _phySize)\r
+  {\r
+    RINOK(_stream->SetSize(newSize));\r
+    _phySize = newSize;\r
+  }\r
+  if (newSize <= _cachedPos)\r
+  {\r
+    _cachedSize = 0;\r
+    _cachedPos = newSize;\r
+  }\r
+  if (newSize < _cachedPos + _cachedSize)\r
+    _cachedSize = (size_t)(newSize - _cachedPos);\r
+  return S_OK;\r
+}\r
+\r
+\r
+HRESULT Update(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    const CObjectVector<CItemEx> &inputItems,\r
+    const CObjectVector<CUpdateItem> &updateItems,\r
+    ISequentialOutStream *seqOutStream,\r
+    CInArchive *inArchive,\r
+    CCompressionMethodMode *compressionMethodMode,\r
+    IArchiveUpdateCallback *updateCallback)\r
+{\r
+  CMyComPtr<IOutStream> outStream;\r
+  {\r
+    CMyComPtr<IOutStream> outStreamReal;\r
+    seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStreamReal);\r
+    if (!outStreamReal)\r
+      return E_NOTIMPL;\r
+    CCacheOutStream *cacheStream = new CCacheOutStream();\r
+    outStream = cacheStream;\r
+    if (!cacheStream->Allocate())\r
+      return E_OUTOFMEMORY;\r
+    RINOK(cacheStream->Init(outStreamReal));\r
+  }\r
+\r
+  if (inArchive)\r
+  {\r
+    if (inArchive->ArcInfo.Base != 0 ||\r
+        inArchive->ArcInfo.StartPosition != 0 ||\r
+        !inArchive->IsOkHeaders)\r
+      return E_NOTIMPL;\r
+  }\r
+  \r
+  COutArchive outArchive;\r
+  outArchive.Create(outStream);\r
+  /*\r
+  if (inArchive && inArchive->ArcInfo.StartPosition > 0)\r
+  {\r
+    CMyComPtr<ISequentialInStream> inStream;\r
+    inStream.Attach(inArchive->CreateLimitedStream(0, inArchive->ArcInfo.StartPosition));\r
+    RINOK(CopyBlockToArchive(inStream, outArchive, NULL));\r
+    outArchive.MoveBasePosition(inArchive->ArcInfo.StartPosition);\r
+  }\r
+  */\r
+  CMyComPtr<IInStream> inStream;\r
+  if (inArchive)\r
+    inStream.Attach(inArchive->CreateStream());\r
+\r
+  return Update2(\r
+      EXTERNAL_CODECS_LOC_VARS\r
+      outArchive, inArchive, inStream,\r
+      inputItems, updateItems,\r
+      compressionMethodMode,\r
+      inArchive ? &inArchive->ArcInfo.Comment : NULL,\r
+      updateCallback);\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.h b/CPP/7zip/Archive/Zip/ZipUpdate.h
new file mode 100755 (executable)
index 0000000..75b4781
--- /dev/null
@@ -0,0 +1,58 @@
+// Zip/Update.h\r
+\r
+#ifndef __ZIP_UPDATE_H\r
+#define __ZIP_UPDATE_H\r
+\r
+#include "../../ICoder.h"\r
+#include "../IArchive.h"\r
+\r
+#include "../../Common/CreateCoder.h"\r
+\r
+#include "ZipCompressionMode.h"\r
+#include "ZipIn.h"\r
+\r
+namespace NArchive {\r
+namespace NZip {\r
+\r
+struct CUpdateRange\r
+{\r
+  UInt64 Position;\r
+  UInt64 Size;\r
+  CUpdateRange() {};\r
+  CUpdateRange(UInt64 position, UInt64 size): Position(position), Size(size) {};\r
+};\r
+\r
+struct CUpdateItem\r
+{\r
+  bool NewData;\r
+  bool NewProperties;\r
+  bool IsDir;\r
+  bool NtfsTimeIsDefined;\r
+  bool IsUtf8;\r
+  int IndexInArchive;\r
+  int IndexInClient;\r
+  UInt32 Attributes;\r
+  UInt32 Time;\r
+  UInt64 Size;\r
+  AString Name;\r
+  // bool Commented;\r
+  // CUpdateRange CommentRange;\r
+  FILETIME NtfsMTime;\r
+  FILETIME NtfsATime;\r
+  FILETIME NtfsCTime;\r
+\r
+  CUpdateItem(): NtfsTimeIsDefined(false), IsUtf8(false), Size(0) {}\r
+};\r
+\r
+HRESULT Update(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    const CObjectVector<CItemEx> &inputItems,\r
+    const CObjectVector<CUpdateItem> &updateItems,\r
+    ISequentialOutStream *seqOutStream,\r
+    CInArchive *inArchive,\r
+    CCompressionMethodMode *compressionMethodMode,\r
+    IArchiveUpdateCallback *updateCallback);\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Archive/makefile b/CPP/7zip/Archive/makefile
new file mode 100755 (executable)
index 0000000..96d8d78
--- /dev/null
@@ -0,0 +1,23 @@
+DIRS =  \\r
+  7z\~ \\r
+  Arj\~ \\r
+  BZip2\~ \\r
+  Cab\~ \\r
+  Chm\~ \\r
+  Cpio\~ \\r
+  Deb\~ \\r
+  GZip\~ \\r
+  Iso\~ \\r
+  Lzh\~ \\r
+  Nsis\~ \\r
+  Rar\~ \\r
+  RPM\~ \\r
+  Split\~ \\r
+  Tar\~ \\r
+  Z\~ \\r
+  Zip\~ \\r
+\r
+all: $(DIRS)\r
+\r
+$(DIRS):\r
+!include "../SubBuild.mak"\r
diff --git a/CPP/7zip/Asm.mak b/CPP/7zip/Asm.mak
new file mode 100755 (executable)
index 0000000..0284903
--- /dev/null
@@ -0,0 +1,7 @@
+!IF "$(CPU)" == "ARM"\r
+$(ASM_OBJS): ../../../../Asm/Arm/$(*B).asm\r
+       $(COMPL_ASM)\r
+!ELSEIF "$(CPU)" != "IA64" && "$(CPU)" != "MIPS"\r
+$(ASM_OBJS): ../../../../Asm/x86/$(*B).asm\r
+       $(COMPL_ASM)\r
+!ENDIF\r
diff --git a/CPP/7zip/Bundles/Alone/Alone.dsp b/CPP/7zip/Bundles/Alone/Alone.dsp
new file mode 100755 (executable)
index 0000000..5a4e097
--- /dev/null
@@ -0,0 +1,2928 @@
+# Microsoft Developer Studio Project File - Name="Alone" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=Alone - Win32 DebugU\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "Alone.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "Alone.mak" CFG="Alone - Win32 DebugU"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "Alone - Win32 Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "Alone - Win32 Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "Alone - Win32 ReleaseU" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "Alone - Win32 DebugU" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
+# 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\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# 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\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
+# 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\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x419 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# 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\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "ReleaseU"\r
+# PROP BASE Intermediate_Dir "ReleaseU"\r
+# PROP BASE Ignore_Export_Lib 0\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "ReleaseU"\r
+# PROP Intermediate_Dir "ReleaseU"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# 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\r
+# 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\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# SUBTRACT BASE LINK32 /pdb:none\r
+# 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\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "DebugU"\r
+# PROP BASE Intermediate_Dir "DebugU"\r
+# PROP BASE Ignore_Export_Lib 0\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "DebugU"\r
+# PROP Intermediate_Dir "DebugU"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# 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\r
+# 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\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x419 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# 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\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "Alone - Win32 Release"\r
+# Name "Alone - Win32 Debug"\r
+# Name "Alone - Win32 ReleaseU"\r
+# Name "Alone - Win32 DebugU"\r
+# Begin Group "Console"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\ArError.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\BenchCon.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\BenchCon.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\CompressionMode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\ConsoleClose.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\ConsoleClose.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\ExtractCallbackConsole.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\List.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\List.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\Main.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\MainAr.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\OpenCallbackConsole.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\PercentPrinter.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\PercentPrinter.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\UpdateCallbackConsole.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\UpdateCallbackConsole.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\UserInputUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\UserInputUtils.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Spec"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\resource.rc\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.cpp\r
+# ADD CPP /Yc"StdAfx.h"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\AutoPtr.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Buffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CommandLineParser.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CommandLineParser.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\ComTry.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Defs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\DynamicBuffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\ListFileUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\ListFileUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyCom.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyException.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyGuidDef.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyInitGuid.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyUnknown.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StdInStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StdInStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StdOutStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StdOutStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringToInt.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringToInt.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Types.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\UTFConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\UTFConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Windows"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Defs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Device.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Handle.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\MemoryLock.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\MemoryLock.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantConversions.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantConversions.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\System.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\System.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Thread.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Time.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Time.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "7zip Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CrossThreadProgress.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CWrappers.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CWrappers.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilePathAutoRename.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilePathAutoRename.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\InBuffer.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\InBuffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\InOutTempBuffer.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\InOutTempBuffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LimitedStreams.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LimitedStreams.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LockedStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LockedStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\MemBlocks.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\MethodId.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\MethodId.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\MethodProps.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\MethodProps.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OffsetStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OffsetStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OutBuffer.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OutBuffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OutMemStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OutMemStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressMt.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressMt.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamBinder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamBinder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamObjects.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamObjects.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\VirtThread.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\VirtThread.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Compress"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "BZip2"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BZip2Crc.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BZip2Crc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BZip2Decoder.cpp\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BZip2Decoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BZip2Encoder.cpp\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BZip2Encoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BZip2Register.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Copy"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Deflate"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Deflate64Register.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\DeflateConst.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\DeflateDecoder.cpp\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\DeflateDecoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\DeflateEncoder.cpp\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\DeflateEncoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\DeflateExtConst.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\DeflateRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Huffman"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\HuffmanDecoder.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Implode"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ImplodeDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ImplodeDecoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ImplodeHuffmanDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ImplodeHuffmanDecoder.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "LZMA"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzma2Decoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzma2Decoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzma2Encoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzma2Encoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzma2Register.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaDecoder.cpp\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaDecoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaEncoder.cpp\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaEncoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "PPMd"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdContext.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdDecode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdDecoder.cpp\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdDecoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdEncode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdEncoder.cpp\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdEncoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdSubAlloc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdType.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdZip.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdZip.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "RangeCoder"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\RangeCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\RangeCoderBit.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\RangeCoderBitTree.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\RangeCoderOpt.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Shrink"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ShrinkDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ShrinkDecoder.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Z"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ZDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ZDecoder.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "BWT"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Mtf8.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "LZX"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzx.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzx86Converter.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzx86Converter.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzxDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzxDecoder.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Quantum"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\QuantumDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\QuantumDecoder.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Bcj2Coder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Bcj2Coder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Bcj2Register.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BcjCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BcjCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BcjRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BitlDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BitlDecoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BitlEncoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BitmDecoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BitmEncoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BranchCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BranchCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BranchMisc.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BranchMisc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BranchRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ByteSwap.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ByteSwap.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\DeltaFilter.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzOutWindow.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzOutWindow.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Archive"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "7z"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zCompressionMode.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zCompressionMode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zDecode.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zDecode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zEncode.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zEncode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zExtract.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zFolderInStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zFolderInStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zFolderOutStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHandlerOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHeader.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHeader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zItem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zOut.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zProperties.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zProperties.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zSpecStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zSpecStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zUpdate.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zUpdate.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "tar"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarHandlerOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarHeader.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarHeader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarItem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarOut.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarUpdate.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarUpdate.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "zip"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipAddCommon.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipAddCommon.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipCompressionMode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipHandlerOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipHeader.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipHeader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipItem.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipItem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipItemEx.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipOut.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipUpdate.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipUpdate.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Archive Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderLoader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2MT.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\DummyOutStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\DummyOutStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\FindSignature.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\FindSignature.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\HandlerOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\HandlerOut.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\InStreamWithCRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\InStreamWithCRC.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\ItemNameUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\ItemNameUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\MultiStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\MultiStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\ParseProperties.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\ParseProperties.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "cab"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabBlockInStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabBlockInStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabHeader.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabHeader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabItem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Bz2Handler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\DeflateProps.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\DeflateProps.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\GzHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\LzmaHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\SplitHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\XzHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\ZHandler.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "UI Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveCommandLine.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveCommandLine.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveExtractCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\Bench.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\Bench.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\DefaultName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\DefaultName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\EnumDirItems.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\EnumDirItems.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\Extract.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\Extract.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ExtractingFilePath.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ExtractingFilePath.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\LoadCodecs.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\LoadCodecs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\OpenArchive.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\OpenArchive.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\PropIDUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\PropIDUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\SetProperties.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\SetProperties.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\SortUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\SortUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\TempFiles.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\TempFiles.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\Update.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\Update.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\UpdateAction.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\UpdateAction.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\UpdateCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\UpdateCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\UpdatePair.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\UpdatePair.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\UpdateProduce.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\UpdateProduce.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\WorkDir.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\WorkDir.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Crypto"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\7zAes.cpp\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\7zAes.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\7zAesRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\HmacSha1.cpp\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\HmacSha1.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\MyAes.cpp\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\MyAes.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\Pbkdf2HmacSha1.cpp\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\Pbkdf2HmacSha1.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\RandGen.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\RandGen.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\Sha1.cpp\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\Sha1.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\WzAes.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\WzAes.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\ZipCrypto.cpp\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O1\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# ADD CPP /O1\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\ZipCrypto.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\ZipStrong.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\ZipStrong.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "7-zip"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\ICoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\IMyUnknown.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\IPassword.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\IProgress.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\IStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\PropID.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "C"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "Xz"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Xz.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Xz.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\XzCrc64.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\XzCrc64.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\XzDec.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\XzEnc.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\XzEnc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\XzIn.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrcOpt.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zStream.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Aes.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Aes.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\AesOpt.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Bcj2.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Bcj2.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Bra.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Bra.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Bra86.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\BraIA64.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\BwtSort.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\BwtSort.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Delta.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Delta.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\HuffEnc.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\HuffEnc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\IStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzFind.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzFind.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzFindMt.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzFindMt.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzHash.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Lzma2Dec.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Lzma2Dec.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Lzma2Enc.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Lzma2Enc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzmaDec.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzmaDec.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzmaEnc.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzmaEnc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\MtCoder.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\MtCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd7.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd7.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd7Dec.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd7Enc.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd8.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd8.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd8Dec.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd8Enc.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\RotateDefs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sha256.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sha256.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sort.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sort.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.c\r
+\r
+!IF  "$(CFG)" == "Alone - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Types.h\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/CPP/7zip/Bundles/Alone/Alone.dsw b/CPP/7zip/Bundles/Alone/Alone.dsw
new file mode 100755 (executable)
index 0000000..036aab4
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "Alone"=.\Alone.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/CPP/7zip/Bundles/Alone/StdAfx.cpp b/CPP/7zip/Bundles/Alone/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..c6d3b1f
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/Bundles/Alone/StdAfx.h b/CPP/7zip/Bundles/Alone/StdAfx.h
new file mode 100755 (executable)
index 0000000..a4e6173
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+#include "../../../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Bundles/Alone/afxres.h b/CPP/7zip/Bundles/Alone/afxres.h
new file mode 100755 (executable)
index 0000000..f646cce
--- /dev/null
@@ -0,0 +1 @@
+#include <winresrc.h>\r
diff --git a/CPP/7zip/Bundles/Alone/makefile b/CPP/7zip/Bundles/Alone/makefile
new file mode 100755 (executable)
index 0000000..ce1c8f7
--- /dev/null
@@ -0,0 +1,308 @@
+PROG = 7za.exe\r
+MY_CONSOLE = 1\r
+CFLAGS = $(CFLAGS) -I ../../../\r
+\r
+!IFNDEF UNDER_CE\r
+CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -D_7ZIP_LARGE_PAGES -DSUPPORT_DEVICE_FILE\r
+!ENDIF\r
+\r
+CONSOLE_OBJS = \\r
+  $O\BenchCon.obj \\r
+  $O\ConsoleClose.obj \\r
+  $O\ExtractCallbackConsole.obj \\r
+  $O\List.obj \\r
+  $O\Main.obj \\r
+  $O\MainAr.obj \\r
+  $O\OpenCallbackConsole.obj \\r
+  $O\PercentPrinter.obj \\r
+  $O\UpdateCallbackConsole.obj \\r
+  $O\UserInputUtils.obj \\r
+\r
+COMMON_OBJS = \\r
+  $O\CommandLineParser.obj \\r
+  $O\CRC.obj \\r
+  $O\IntToString.obj \\r
+  $O\ListFileUtils.obj \\r
+  $O\NewHandler.obj \\r
+  $O\StdInStream.obj \\r
+  $O\StdOutStream.obj \\r
+  $O\MyString.obj \\r
+  $O\StringConvert.obj \\r
+  $O\StringToInt.obj \\r
+  $O\UTFConvert.obj \\r
+  $O\MyVector.obj \\r
+  $O\Wildcard.obj \\r
+\r
+WIN_OBJS = \\r
+  $O\DLL.obj \\r
+  $O\Error.obj \\r
+  $O\FileDir.obj \\r
+  $O\FileFind.obj \\r
+  $O\FileIO.obj \\r
+  $O\FileName.obj \\r
+  $O\MemoryLock.obj \\r
+  $O\PropVariant.obj \\r
+  $O\PropVariantConversions.obj \\r
+  $O\Synchronization.obj \\r
+  $O\System.obj \\r
+  $O\Time.obj \\r
+\r
+7ZIP_COMMON_OBJS = \\r
+  $O\CreateCoder.obj \\r
+  $O\CWrappers.obj \\r
+  $O\FilePathAutoRename.obj \\r
+  $O\FileStreams.obj \\r
+  $O\FilterCoder.obj \\r
+  $O\InBuffer.obj \\r
+  $O\InOutTempBuffer.obj \\r
+  $O\LimitedStreams.obj \\r
+  $O\LockedStream.obj \\r
+  $O\MemBlocks.obj \\r
+  $O\MethodId.obj \\r
+  $O\MethodProps.obj \\r
+  $O\OffsetStream.obj \\r
+  $O\OutBuffer.obj \\r
+  $O\OutMemStream.obj \\r
+  $O\ProgressMt.obj \\r
+  $O\ProgressUtils.obj \\r
+  $O\StreamBinder.obj \\r
+  $O\StreamObjects.obj \\r
+  $O\StreamUtils.obj \\r
+  $O\VirtThread.obj \\r
+\r
+UI_COMMON_OBJS = \\r
+  $O\ArchiveCommandLine.obj \\r
+  $O\ArchiveExtractCallback.obj \\r
+  $O\ArchiveOpenCallback.obj \\r
+  $O\Bench.obj \\r
+  $O\DefaultName.obj \\r
+  $O\EnumDirItems.obj \\r
+  $O\Extract.obj \\r
+  $O\ExtractingFilePath.obj \\r
+  $O\LoadCodecs.obj \\r
+  $O\OpenArchive.obj \\r
+  $O\PropIDUtils.obj \\r
+  $O\SetProperties.obj \\r
+  $O\SortUtils.obj \\r
+  $O\TempFiles.obj \\r
+  $O\Update.obj \\r
+  $O\UpdateAction.obj \\r
+  $O\UpdateCallback.obj \\r
+  $O\UpdatePair.obj \\r
+  $O\UpdateProduce.obj \\r
+  $O\WorkDir.obj \\r
+\r
+AR_OBJS = \\r
+  $O\Bz2Handler.obj \\r
+  $O\DeflateProps.obj \\r
+  $O\GzHandler.obj \\r
+  $O\LzmaHandler.obj \\r
+  $O\SplitHandler.obj \\r
+  $O\XzHandler.obj \\r
+  $O\ZHandler.obj \\r
+\r
+AR_COMMON_OBJS = \\r
+  $O\CoderMixer2.obj \\r
+  $O\CoderMixer2MT.obj \\r
+  $O\CrossThreadProgress.obj \\r
+  $O\DummyOutStream.obj \\r
+  $O\FindSignature.obj \\r
+  $O\HandlerOut.obj \\r
+  $O\InStreamWithCRC.obj \\r
+  $O\ItemNameUtils.obj \\r
+  $O\MultiStream.obj \\r
+  $O\OutStreamWithCRC.obj \\r
+  $O\ParseProperties.obj \\r
+\r
+\r
+7Z_OBJS = \\r
+  $O\7zCompressionMode.obj \\r
+  $O\7zDecode.obj \\r
+  $O\7zEncode.obj \\r
+  $O\7zExtract.obj \\r
+  $O\7zFolderInStream.obj \\r
+  $O\7zFolderOutStream.obj \\r
+  $O\7zHandler.obj \\r
+  $O\7zHandlerOut.obj \\r
+  $O\7zHeader.obj \\r
+  $O\7zIn.obj \\r
+  $O\7zOut.obj \\r
+  $O\7zProperties.obj \\r
+  $O\7zSpecStream.obj \\r
+  $O\7zUpdate.obj \\r
+  $O\7zRegister.obj \\r
+\r
+CAB_OBJS = \\r
+  $O\CabBlockInStream.obj \\r
+  $O\CabHandler.obj \\r
+  $O\CabHeader.obj \\r
+  $O\CabIn.obj \\r
+  $O\CabRegister.obj \\r
+\r
+TAR_OBJS = \\r
+  $O\TarHandler.obj \\r
+  $O\TarHandlerOut.obj \\r
+  $O\TarHeader.obj \\r
+  $O\TarIn.obj \\r
+  $O\TarOut.obj \\r
+  $O\TarUpdate.obj \\r
+  $O\TarRegister.obj \\r
+\r
+ZIP_OBJS = \\r
+  $O\ZipAddCommon.obj \\r
+  $O\ZipHandler.obj \\r
+  $O\ZipHandlerOut.obj \\r
+  $O\ZipHeader.obj \\r
+  $O\ZipIn.obj \\r
+  $O\ZipItem.obj \\r
+  $O\ZipOut.obj \\r
+  $O\ZipUpdate.obj \\r
+  $O\ZipRegister.obj \\r
+\r
+\r
+COMPRESS_OBJS = \\r
+  $O\Bcj2Coder.obj \\r
+  $O\Bcj2Register.obj \\r
+  $O\BcjCoder.obj \\r
+  $O\BcjRegister.obj \\r
+  $O\BitlDecoder.obj \\r
+  $O\BranchCoder.obj \\r
+  $O\BranchMisc.obj \\r
+  $O\BranchRegister.obj \\r
+  $O\ByteSwap.obj \\r
+  $O\BZip2CRC.obj \\r
+  $O\BZip2Decoder.obj \\r
+  $O\BZip2Encoder.obj \\r
+  $O\BZip2Register.obj \\r
+  $O\CopyCoder.obj \\r
+  $O\CopyRegister.obj \\r
+  $O\Deflate64Register.obj \\r
+  $O\DeflateDecoder.obj \\r
+  $O\DeflateEncoder.obj \\r
+  $O\DeflateRegister.obj \\r
+  $O\DeltaFilter.obj \\r
+  $O\ImplodeDecoder.obj \\r
+  $O\ImplodeHuffmanDecoder.obj \\r
+  $O\Lzma2Decoder.obj \\r
+  $O\Lzma2Encoder.obj \\r
+  $O\Lzma2Register.obj \\r
+  $O\LzmaDecoder.obj \\r
+  $O\LzmaEncoder.obj \\r
+  $O\LzmaRegister.obj \\r
+  $O\LzOutWindow.obj \\r
+  $O\Lzx86Converter.obj \\r
+  $O\LzxDecoder.obj \\r
+  $O\PpmdDecoder.obj \\r
+  $O\PpmdEncoder.obj \\r
+  $O\PpmdRegister.obj \\r
+  $O\PpmdZip.obj \\r
+  $O\QuantumDecoder.obj \\r
+  $O\ShrinkDecoder.obj \\r
+  $O\ZDecoder.obj \\r
+\r
+CRYPTO_OBJS = \\r
+  $O\7zAes.obj \\r
+  $O\7zAesRegister.obj \\r
+  $O\HmacSha1.obj \\r
+  $O\MyAes.obj \\r
+  $O\Pbkdf2HmacSha1.obj \\r
+  $O\RandGen.obj \\r
+  $O\Sha1.obj \\r
+  $O\WzAes.obj \\r
+  $O\ZipCrypto.obj \\r
+  $O\ZipStrong.obj \\r
+\r
+C_OBJS = \\r
+  $O\7zStream.obj \\r
+  $O\Alloc.obj \\r
+  $O\Bra.obj \\r
+  $O\Bra86.obj \\r
+  $O\BraIA64.obj \\r
+  $O\BwtSort.obj \\r
+  $O\CpuArch.obj \\r
+  $O\Delta.obj \\r
+  $O\HuffEnc.obj \\r
+  $O\LzFind.obj \\r
+  $O\LzFindMt.obj \\r
+  $O\Lzma2Dec.obj \\r
+  $O\Lzma2Enc.obj \\r
+  $O\LzmaDec.obj \\r
+  $O\LzmaEnc.obj \\r
+  $O\MtCoder.obj \\r
+  $O\Ppmd7.obj \\r
+  $O\Ppmd7Dec.obj \\r
+  $O\Ppmd7Enc.obj \\r
+  $O\Ppmd8.obj \\r
+  $O\Ppmd8Dec.obj \\r
+  $O\Ppmd8Enc.obj \\r
+  $O\Sha256.obj \\r
+  $O\Sort.obj \\r
+  $O\Threads.obj \\r
+  $O\Xz.obj \\r
+  $O\XzCrc64.obj \\r
+  $O\XzDec.obj \\r
+  $O\XzEnc.obj \\r
+  $O\XzIn.obj \\r
+\r
+!include "../../Aes.mak"\r
+!include "../../Crc.mak"\r
+\r
+OBJS = \\r
+  $O\StdAfx.obj \\r
+  $(CONSOLE_OBJS) \\r
+  $(COMMON_OBJS) \\r
+  $(COMMON_OBJS_O2) \\r
+  $(WIN_OBJS) \\r
+  $(7ZIP_COMMON_OBJS) \\r
+  $(UI_COMMON_OBJS) \\r
+  $(AR_OBJS) \\r
+  $(AR_COMMON_OBJS) \\r
+  $(7Z_OBJS) \\r
+  $(CAB_OBJS) \\r
+  $(TAR_OBJS) \\r
+  $(ZIP_OBJS) \\r
+  $(COMPRESS_OBJS) \\r
+  $(LZMA_BENCH_OBJS) \\r
+  $(CRYPTO_OBJS) \\r
+  $(C_OBJS) \\r
+  $(ASM_OBJS) \\r
+  $O\resource.res\r
+\r
+\r
+!include "../../../Build.mak"\r
+\r
+$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(COMMON_OBJS): ../../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_OBJS): ../../../Windows/$(*B).cpp\r
+       $(COMPL)\r
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_OBJS): ../../Archive/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(7Z_OBJS): ../../Archive/7z/$(*B).cpp\r
+       $(COMPL)\r
+$(CAB_OBJS): ../../Archive/Cab/$(*B).cpp\r
+       $(COMPL)\r
+$(TAR_OBJS): ../../Archive/Tar/$(*B).cpp\r
+       $(COMPL)\r
+$(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp\r
+       $(COMPL_O2)\r
+\r
+$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp\r
+       $(COMPL_O2)\r
+\r
+$(C_OBJS): ../../../../C/$(*B).c\r
+       $(COMPL_O2)\r
+\r
+!include "../../Asm.mak"\r
diff --git a/CPP/7zip/Bundles/Alone/resource.rc b/CPP/7zip/Bundles/Alone/resource.rc
new file mode 100755 (executable)
index 0000000..9b81707
--- /dev/null
@@ -0,0 +1,3 @@
+#include "../../MyVersionInfo.rc"\r
+\r
+MY_VERSION_INFO_APP("7-Zip Standalone Console", "7za")\r
diff --git a/CPP/7zip/Bundles/Alone7z/StdAfx.cpp b/CPP/7zip/Bundles/Alone7z/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..c6d3b1f
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/Bundles/Alone7z/StdAfx.h b/CPP/7zip/Bundles/Alone7z/StdAfx.h
new file mode 100755 (executable)
index 0000000..a4e6173
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+#include "../../../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Bundles/Alone7z/makefile b/CPP/7zip/Bundles/Alone7z/makefile
new file mode 100755 (executable)
index 0000000..3132895
--- /dev/null
@@ -0,0 +1,213 @@
+PROG = 7zr.exe\r
+MY_CONSOLE = 1\r
+CFLAGS = $(CFLAGS) -I ../../../ \\r
+  -D_NO_CRYPTO \\r
+\r
+!IFNDEF UNDER_CE\r
+CFLAGS = $(CFLAGS) -DWIN_LONG_PATH\r
+!ENDIF\r
+\r
+CONSOLE_OBJS = \\r
+  $O\BenchCon.obj \\r
+  $O\ConsoleClose.obj \\r
+  $O\ExtractCallbackConsole.obj \\r
+  $O\List.obj \\r
+  $O\Main.obj \\r
+  $O\MainAr.obj \\r
+  $O\OpenCallbackConsole.obj \\r
+  $O\PercentPrinter.obj \\r
+  $O\UpdateCallbackConsole.obj \\r
+  $O\UserInputUtils.obj \\r
+\r
+COMMON_OBJS = \\r
+  $O\CommandLineParser.obj \\r
+  $O\CRC.obj \\r
+  $O\IntToString.obj \\r
+  $O\ListFileUtils.obj \\r
+  $O\NewHandler.obj \\r
+  $O\StdInStream.obj \\r
+  $O\StdOutStream.obj \\r
+  $O\MyString.obj \\r
+  $O\StringConvert.obj \\r
+  $O\StringToInt.obj \\r
+  $O\UTFConvert.obj \\r
+  $O\MyVector.obj \\r
+  $O\Wildcard.obj \\r
+\r
+WIN_OBJS = \\r
+  $O\DLL.obj \\r
+  $O\Error.obj \\r
+  $O\FileDir.obj \\r
+  $O\FileFind.obj \\r
+  $O\FileIO.obj \\r
+  $O\FileName.obj \\r
+  $O\MemoryLock.obj \\r
+  $O\PropVariant.obj \\r
+  $O\PropVariantConversions.obj \\r
+  $O\Synchronization.obj \\r
+  $O\System.obj \\r
+  $O\Time.obj \\r
+\r
+7ZIP_COMMON_OBJS = \\r
+  $O\CreateCoder.obj \\r
+  $O\CWrappers.obj \\r
+  $O\FilePathAutoRename.obj \\r
+  $O\FileStreams.obj \\r
+  $O\InBuffer.obj \\r
+  $O\InOutTempBuffer.obj \\r
+  $O\FilterCoder.obj \\r
+  $O\LimitedStreams.obj \\r
+  $O\LockedStream.obj \\r
+  $O\MethodId.obj \\r
+  $O\MethodProps.obj \\r
+  $O\OffsetStream.obj \\r
+  $O\OutBuffer.obj \\r
+  $O\ProgressUtils.obj \\r
+  $O\StreamBinder.obj \\r
+  $O\StreamObjects.obj \\r
+  $O\StreamUtils.obj \\r
+  $O\VirtThread.obj \\r
+\r
+UI_COMMON_OBJS = \\r
+  $O\ArchiveCommandLine.obj \\r
+  $O\ArchiveExtractCallback.obj \\r
+  $O\ArchiveOpenCallback.obj \\r
+  $O\Bench.obj \\r
+  $O\DefaultName.obj \\r
+  $O\EnumDirItems.obj \\r
+  $O\Extract.obj \\r
+  $O\ExtractingFilePath.obj \\r
+  $O\LoadCodecs.obj \\r
+  $O\OpenArchive.obj \\r
+  $O\PropIDUtils.obj \\r
+  $O\SetProperties.obj \\r
+  $O\SortUtils.obj \\r
+  $O\TempFiles.obj \\r
+  $O\Update.obj \\r
+  $O\UpdateAction.obj \\r
+  $O\UpdateCallback.obj \\r
+  $O\UpdatePair.obj \\r
+  $O\UpdateProduce.obj \\r
+  $O\WorkDir.obj \\r
+\r
+AR_OBJS = \\r
+  $O\LzmaHandler.obj \\r
+  $O\SplitHandler.obj \\r
+  $O\XzHandler.obj \\r
+\r
+AR_COMMON_OBJS = \\r
+  $O\CoderMixer2.obj \\r
+  $O\CoderMixer2MT.obj \\r
+  $O\CrossThreadProgress.obj \\r
+  $O\DummyOutStream.obj \\r
+  $O\HandlerOut.obj \\r
+  $O\InStreamWithCRC.obj \\r
+  $O\ItemNameUtils.obj \\r
+  $O\MultiStream.obj \\r
+  $O\OutStreamWithCRC.obj \\r
+  $O\ParseProperties.obj \\r
+\r
+\r
+7Z_OBJS = \\r
+  $O\7zCompressionMode.obj \\r
+  $O\7zDecode.obj \\r
+  $O\7zEncode.obj \\r
+  $O\7zExtract.obj \\r
+  $O\7zFolderInStream.obj \\r
+  $O\7zFolderOutStream.obj \\r
+  $O\7zHandler.obj \\r
+  $O\7zHandlerOut.obj \\r
+  $O\7zHeader.obj \\r
+  $O\7zIn.obj \\r
+  $O\7zOut.obj \\r
+  $O\7zProperties.obj \\r
+  $O\7zRegister.obj \\r
+  $O\7zSpecStream.obj \\r
+  $O\7zUpdate.obj \\r
+\r
+COMPRESS_OBJS = \\r
+  $O\Bcj2Coder.obj \\r
+  $O\Bcj2Register.obj \\r
+  $O\BcjCoder.obj \\r
+  $O\BcjRegister.obj \\r
+  $O\BranchCoder.obj \\r
+  $O\BranchMisc.obj \\r
+  $O\BranchRegister.obj \\r
+  $O\ByteSwap.obj \\r
+  $O\CopyCoder.obj \\r
+  $O\CopyRegister.obj \\r
+  $O\DeltaFilter.obj \\r
+  $O\Lzma2Decoder.obj \\r
+  $O\Lzma2Encoder.obj \\r
+  $O\Lzma2Register.obj \\r
+  $O\LzmaDecoder.obj \\r
+  $O\LzmaEncoder.obj \\r
+  $O\LzmaRegister.obj \\r
+\r
+C_OBJS = \\r
+  $O\7zStream.obj \\r
+  $O\Alloc.obj \\r
+  $O\Bra.obj \\r
+  $O\Bra86.obj \\r
+  $O\BraIA64.obj \\r
+  $O\CpuArch.obj \\r
+  $O\Delta.obj \\r
+  $O\LzFind.obj \\r
+  $O\LzFindMt.obj \\r
+  $O\Lzma2Dec.obj \\r
+  $O\Lzma2Enc.obj \\r
+  $O\LzmaDec.obj \\r
+  $O\LzmaEnc.obj \\r
+  $O\MtCoder.obj \\r
+  $O\Sha256.obj \\r
+  $O\Threads.obj \\r
+  $O\Xz.obj \\r
+  $O\XzCrc64.obj \\r
+  $O\XzDec.obj \\r
+  $O\XzEnc.obj \\r
+  $O\XzIn.obj \\r
+\r
+!include "../../Crc.mak"\r
+\r
+OBJS = \\r
+  $O\StdAfx.obj \\r
+  $(CONSOLE_OBJS) \\r
+  $(COMMON_OBJS) \\r
+  $(WIN_OBJS) \\r
+  $(7ZIP_COMMON_OBJS) \\r
+  $(UI_COMMON_OBJS) \\r
+  $(AR_OBJS) \\r
+  $(AR_COMMON_OBJS) \\r
+  $(7Z_OBJS) \\r
+  $(COMPRESS_OBJS) \\r
+  $(C_OBJS) \\r
+  $(ASM_OBJS) \\r
+  $O\resource.res\r
+\r
+\r
+!include "../../../Build.mak"\r
+\r
+$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(COMMON_OBJS): ../../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_OBJS): ../../../Windows/$(*B).cpp\r
+       $(COMPL)\r
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_OBJS): ../../Archive/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(7Z_OBJS): ../../Archive/7z/$(*B).cpp\r
+       $(COMPL)\r
+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp\r
+       $(COMPL_O2)\r
+$(C_OBJS): ../../../../C/$(*B).c\r
+       $(COMPL_O2)\r
+\r
+!include "../../Asm.mak"\r
diff --git a/CPP/7zip/Bundles/Alone7z/resource.rc b/CPP/7zip/Bundles/Alone7z/resource.rc
new file mode 100755 (executable)
index 0000000..0f90dfb
--- /dev/null
@@ -0,0 +1,3 @@
+#include "../../MyVersionInfo.rc"\r
+\r
+MY_VERSION_INFO_APP("7-Zip Standalone Console", "7zr")\r
diff --git a/CPP/7zip/Bundles/Fm/FM.dsp b/CPP/7zip/Bundles/Fm/FM.dsp
new file mode 100755 (executable)
index 0000000..8564f4c
--- /dev/null
@@ -0,0 +1,1726 @@
+# Microsoft Developer Studio Project File - Name="FM" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Application" 0x0101\r
+\r
+CFG=FM - Win32 DebugU\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "FM.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "FM.mak" CFG="FM - Win32 DebugU"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "FM - Win32 Release" (based on "Win32 (x86) Application")\r
+!MESSAGE "FM - Win32 Debug" (based on "Win32 (x86) Application")\r
+!MESSAGE "FM - Win32 ReleaseU" (based on "Win32 (x86) Application")\r
+!MESSAGE "FM - Win32 DebugU" (based on "Win32 (x86) Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+MTL=midl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "FM - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c\r
+# 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\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /opt:NOWIN98\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c\r
+# 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\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /pdbtype:sept\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 ReleaseU"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "ReleaseU"\r
+# PROP BASE Intermediate_Dir "ReleaseU"\r
+# PROP BASE Ignore_Export_Lib 0\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "ReleaseU"\r
+# PROP Intermediate_Dir "ReleaseU"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /c\r
+# 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\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /opt:NOWIN98\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 DebugU"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "DebugU"\r
+# PROP BASE Intermediate_Dir "DebugU"\r
+# PROP BASE Ignore_Export_Lib 0\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "DebugU"\r
+# PROP Intermediate_Dir "DebugU"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c\r
+# 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\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "FM - Win32 Release"\r
+# Name "FM - Win32 Debug"\r
+# Name "FM - Win32 ReleaseU"\r
+# Name "FM - Win32 DebugU"\r
+# Begin Group "Spec"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\7zipLogo.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\add.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\ClassDefs.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\Copy.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\Delete.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\Extract.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\FM.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\Move.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\Parent.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\Properties.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\resource.rc\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\StdAfx.cpp\r
+# ADD CPP /Yc"StdAfx.h"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\StdAfx.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\Test.bmp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Archive"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\IArchive.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Folders"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\FSDrives.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\FSDrives.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\FSFolder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\FSFolder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\FSFolderCopy.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\IFolder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\NetFolder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\NetFolder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\RootFolder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\RootFolder.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Registry"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\RegistryAssociations.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\RegistryAssociations.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\RegistryPlugins.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\RegistryPlugins.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\RegistryUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\RegistryUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\ViewSettings.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\ViewSettings.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Panel"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\App.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\App.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\AppState.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\EnumFormatEtc.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\EnumFormatEtc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\FileFolderPluginOpen.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\FileFolderPluginOpen.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\Panel.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\Panel.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PanelCopy.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PanelCrc.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PanelDrag.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PanelFolderChange.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PanelItemOpen.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PanelItems.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PanelKey.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PanelListNotify.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PanelMenu.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PanelOperations.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PanelSelect.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PanelSort.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PanelSplitFile.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Dialog"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "Options"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\EditPage.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\EditPage.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\FoldersPage.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\FoldersPage.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\LangPage.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\LangPage.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\MenuPage.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\MenuPage.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\OptionsDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\SettingsPage.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\SettingsPage.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\SystemPage.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\SystemPage.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\AboutDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\AboutDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\BrowseDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\BrowseDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\ComboDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\ComboDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\CopyDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\CopyDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\DialogSize.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\ListViewDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\ListViewDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\MessagesDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\MessagesDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\OverwriteDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\OverwriteDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PasswordDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PasswordDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\ProgressDialog2.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\ProgressDialog2.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\SplitDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\SplitDialog.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "FM Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\ExtractCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\ExtractCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\FormatUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\FormatUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\HelpUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\HelpUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\LangUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\LangUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\ProgramLocation.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\ProgramLocation.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\UpdateCallback100.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\UpdateCallback100.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "7-Zip Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilePathAutoRename.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilePathAutoRename.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamObjects.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamObjects.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "C"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrcOpt.c\r
+\r
+!IF  "$(CFG)" == "FM - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 ReleaseU"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.c\r
+\r
+!IF  "$(CFG)" == "FM - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 ReleaseU"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sha256.c\r
+\r
+!IF  "$(CFG)" == "FM - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sha256.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sort.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sort.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Windows"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "Control"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ComboBox.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ComboBox.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\CommandBar.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Dialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Dialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Edit.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ImageList.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ListView.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ListView.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ProgressBar.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\PropertyPage.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\PropertyPage.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ReBar.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Static.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\StatusBar.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ToolBar.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Trackbar.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Window2.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Window2.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Clipboard.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Clipboard.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\COM.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\CommonDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\CommonDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Defs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Device.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileMapping.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileSystem.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileSystem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Handle.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Memory.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Memory.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\MemoryLock.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\MemoryLock.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Menu.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Menu.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Net.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Net.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Process.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Process.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantConversions.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantConversions.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Registry.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Registry.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\ResourceString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\ResourceString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Security.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Security.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Shell.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Shell.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\System.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\System.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Thread.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Time.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Time.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Timer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Window.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Window.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Buffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CommandLineParser.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CommandLineParser.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\ComTry.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Defs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\DynamicBuffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Exception.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Lang.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Lang.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\ListFileUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\ListFileUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyCom.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Random.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Random.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringToInt.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringToInt.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\TextConfig.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\TextConfig.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Types.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\UTFConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\UTFConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "UI"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "UI Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveCommandLine.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveCommandLine.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveExtractCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\Bench.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\Bench.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\CompressCall.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\CompressCall2.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\DefaultName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\DefaultName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\DirItem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\EnumDirItems.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\EnumDirItems.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ExitCode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\Extract.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\Extract.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ExtractingFilePath.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ExtractingFilePath.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ExtractMode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\IFileExtractCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\LoadCodecs.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\LoadCodecs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\OpenArchive.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\OpenArchive.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\Property.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\PropIDUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\PropIDUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\SetProperties.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\SetProperties.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\SortUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\SortUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\StdAfx.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\TempFiles.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\TempFiles.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\Update.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\Update.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\UpdateAction.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\UpdateAction.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\UpdateCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\UpdateCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\UpdatePair.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\UpdatePair.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\UpdateProduce.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\UpdateProduce.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\WorkDir.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\WorkDir.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ZipRegistry.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ZipRegistry.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Agent"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Agent\Agent.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Agent\Agent.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Agent\AgentOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Agent\AgentProxy.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Agent\AgentProxy.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Agent\ArchiveFolder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Agent\ArchiveFolderOpen.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Agent\ArchiveFolderOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Agent\IFolderArchive.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Agent\UpdateCallbackAgent.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Agent\UpdateCallbackAgent.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Explorer"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Explorer\ContextMenu.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Explorer\ContextMenu.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Explorer\MyMessages.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Explorer\MyMessages.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Explorer\RegistryContextMenu.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Explorer\RegistryContextMenu.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "GUI"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\GUI\BenchmarkDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\GUI\BenchmarkDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\GUI\BenchmarkDialogRes.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\GUI\CompressDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\GUI\CompressDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\GUI\ExtractDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\GUI\ExtractDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\GUI\ExtractGUI.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\GUI\ExtractGUI.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\GUI\UpdateCallbackGUI.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\GUI\UpdateCallbackGUI.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\GUI\UpdateGUI.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\GUI\UpdateGUI.h\r
+# End Source File\r
+# End Group\r
+# End Group\r
+# Begin Group "Compress"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyCoder.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Interface"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\ICoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\IDecl.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\IPassword.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\IProgress.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\7zFM.exe.manifest\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\7zipLogo.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\Add2.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\Copy2.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\Delete2.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\Extract2.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\FilePlugins.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\FilePlugins.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\FM.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\Info.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\Info2.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\Move2.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\MyCom2.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\MyLoadMenu.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\MyLoadMenu.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\OpenCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\OpenCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PluginInterface.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PluginLoader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PropertyName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PropertyName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\resource.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\SplitUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\SplitUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\StringUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\StringUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\SysIconUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\SysIconUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\Test2.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\TextPairs.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\TextPairs.h\r
+# End Source File\r
+# End Target\r
+# End Project\r
diff --git a/CPP/7zip/Bundles/Fm/FM.dsw b/CPP/7zip/Bundles/Fm/FM.dsw
new file mode 100755 (executable)
index 0000000..38f65d2
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "FM"=.\FM.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/CPP/7zip/Bundles/Fm/StdAfx.cpp b/CPP/7zip/Bundles/Fm/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..c6d3b1f
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/Bundles/Fm/StdAfx.h b/CPP/7zip/Bundles/Fm/StdAfx.h
new file mode 100755 (executable)
index 0000000..a9ae92e
--- /dev/null
@@ -0,0 +1,23 @@
+// stdafx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#define _WIN32_WINNT 0x0400\r
+\r
+// it's for Windows NT supporting (MENUITEMINFOW)\r
+#define WINVER 0x0400\r
+\r
+#include <windows.h>\r
+#include <stdio.h>\r
+#include <commctrl.h>\r
+#include <ShlObj.h>\r
+#include <limits.h>\r
+#include <tchar.h>\r
+#include <shlwapi.h>\r
+\r
+// #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers\r
+\r
+#include "Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Bundles/Fm/makefile b/CPP/7zip/Bundles/Fm/makefile
new file mode 100755 (executable)
index 0000000..2c55e27
--- /dev/null
@@ -0,0 +1,535 @@
+PROG = 7zFM.exe\r
+CFLAGS = $(CFLAGS) -I ../../../ \\r
+  -DLANG \\r
+  -DNEW_FOLDER_INTERFACE \\r
+  -DEXTERNAL_CODECS \\r
+\r
+!IFDEF UNDER_CE\r
+LIBS = $(LIBS) ceshell.lib Commctrl.lib\r
+!ELSE\r
+LIBS = $(LIBS) comctl32.lib htmlhelp.lib comdlg32.lib Mpr.lib Gdi32.lib\r
+CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -DSUPPORT_DEVICE_FILE\r
+!ENDIF\r
+\r
+FM_OBJS = \\r
+  $O\App.obj \\r
+  $O\BrowseDialog.obj \\r
+  $O\ClassDefs.obj \\r
+  $O\EnumFormatEtc.obj \\r
+  $O\ExtractCallback.obj \\r
+  $O\FileFolderPluginOpen.obj \\r
+  $O\FilePlugins.obj \\r
+  $O\FM.obj \\r
+  $O\FoldersPage.obj \\r
+  $O\FormatUtils.obj \\r
+  $O\FSFolder.obj \\r
+  $O\FSFolderCopy.obj \\r
+  $O\HelpUtils.obj \\r
+  $O\LangUtils.obj \\r
+  $O\MenuPage.obj \\r
+  $O\MyLoadMenu.obj \\r
+  $O\OpenCallback.obj \\r
+  $O\OptionsDialog.obj \\r
+  $O\Panel.obj \\r
+  $O\PanelCopy.obj \\r
+  $O\PanelCrc.obj \\r
+  $O\PanelDrag.obj \\r
+  $O\PanelFolderChange.obj \\r
+  $O\PanelItemOpen.obj \\r
+  $O\PanelItems.obj \\r
+  $O\PanelKey.obj \\r
+  $O\PanelListNotify.obj \\r
+  $O\PanelMenu.obj \\r
+  $O\PanelOperations.obj \\r
+  $O\PanelSelect.obj \\r
+  $O\PanelSort.obj \\r
+  $O\PanelSplitFile.obj \\r
+  $O\ProgramLocation.obj \\r
+  $O\PropertyName.obj \\r
+  $O\RegistryAssociations.obj \\r
+  $O\RegistryPlugins.obj \\r
+  $O\RegistryUtils.obj \\r
+  $O\RootFolder.obj \\r
+  $O\SplitUtils.obj \\r
+  $O\StringUtils.obj \\r
+  $O\SysIconUtils.obj \\r
+  $O\TextPairs.obj \\r
+  $O\UpdateCallback100.obj \\r
+  $O\ViewSettings.obj \\r
+  $O\AboutDialog.obj \\r
+  $O\ComboDialog.obj \\r
+  $O\CopyDialog.obj \\r
+  $O\EditPage.obj \\r
+  $O\LangPage.obj \\r
+  $O\ListViewDialog.obj \\r
+  $O\MessagesDialog.obj \\r
+  $O\OverwriteDialog.obj \\r
+  $O\PasswordDialog.obj \\r
+  $O\ProgressDialog2.obj \\r
+  $O\SettingsPage.obj \\r
+  $O\SplitDialog.obj \\r
+  $O\SystemPage.obj \\r
+\r
+COMMON_OBJS = \\r
+  $O\CommandLineParser.obj \\r
+  $O\CRC.obj \\r
+  $O\IntToString.obj \\r
+  $O\Lang.obj \\r
+  $O\ListFileUtils.obj \\r
+  $O\MyMap.obj \\r
+  $O\MyString.obj \\r
+  $O\MyVector.obj \\r
+  $O\MyXml.obj \\r
+  $O\NewHandler.obj \\r
+  $O\Random.obj \\r
+  $O\StringConvert.obj \\r
+  $O\StringToInt.obj \\r
+  $O\TextConfig.obj \\r
+  $O\UTFConvert.obj \\r
+  $O\Wildcard.obj \\r
+\r
+WIN_OBJS = \\r
+  $O\Clipboard.obj \\r
+  $O\DLL.obj \\r
+  $O\Error.obj \\r
+  $O\FileDir.obj \\r
+  $O\FileFind.obj \\r
+  $O\FileIO.obj \\r
+  $O\FileName.obj \\r
+  $O\Memory.obj \\r
+  $O\MemoryLock.obj \\r
+  $O\Menu.obj \\r
+  $O\Process.obj \\r
+  $O\PropVariant.obj \\r
+  $O\PropVariantConversions.obj \\r
+  $O\PropVariantUtils.obj \\r
+  $O\Registry.obj \\r
+  $O\ResourceString.obj \\r
+  $O\Shell.obj \\r
+  $O\Synchronization.obj \\r
+  $O\System.obj \\r
+  $O\Time.obj \\r
+  $O\Window.obj \\r
+\r
+!IFNDEF UNDER_CE\r
+\r
+FM_OBJS = $(FM_OBJS) \\r
+  $O\FSDrives.obj \\r
+  $O\NetFolder.obj \\r
+\r
+WIN_OBJS = $(WIN_OBJS) \\r
+  $O\CommonDialog.obj \\r
+  $O\FileSystem.obj \\r
+  $O\Net.obj \\r
+  $O\Security.obj \\r
+\r
+!ENDIF\r
+\r
+\r
+WIN_CTRL_OBJS = \\r
+  $O\ComboBox.obj \\r
+  $O\Dialog.obj \\r
+  $O\ListView.obj \\r
+  $O\PropertyPage.obj \\r
+  $O\Window2.obj \\r
+\r
+7ZIP_COMMON_OBJS = \\r
+  $O\CreateCoder.obj \\r
+  $O\CWrappers.obj \\r
+  $O\FilePathAutoRename.obj \\r
+  $O\FileStreams.obj \\r
+  $O\FilterCoder.obj \\r
+  $O\InBuffer.obj \\r
+  $O\InOutTempBuffer.obj \\r
+  $O\LimitedStreams.obj \\r
+  $O\LockedStream.obj \\r
+  $O\MemBlocks.obj \\r
+  $O\MethodId.obj \\r
+  $O\MethodProps.obj \\r
+  $O\OffsetStream.obj \\r
+  $O\OutBuffer.obj \\r
+  $O\OutMemStream.obj \\r
+  $O\ProgressMt.obj \\r
+  $O\ProgressUtils.obj \\r
+  $O\StreamBinder.obj \\r
+  $O\StreamObjects.obj \\r
+  $O\StreamUtils.obj \\r
+  $O\VirtThread.obj \\r
+\r
+AR_OBJS = \\r
+  $O\ArjHandler.obj \\r
+  $O\Bz2Handler.obj \\r
+  $O\CpioHandler.obj \\r
+  $O\CramfsHandler.obj \\r
+  $O\DebHandler.obj \\r
+  $O\DeflateProps.obj \\r
+  $O\DmgHandler.obj \\r
+  $O\ElfHandler.obj \\r
+  $O\FatHandler.obj \\r
+  $O\FlvHandler.obj \\r
+  $O\GzHandler.obj \\r
+  $O\LzhHandler.obj \\r
+  $O\LzmaHandler.obj \\r
+  $O\MachoHandler.obj \\r
+  $O\MbrHandler.obj \\r
+  $O\MslzHandler.obj \\r
+  $O\MubHandler.obj \\r
+  $O\NtfsHandler.obj \\r
+  $O\PeHandler.obj \\r
+  $O\PpmdHandler.obj \\r
+  $O\RpmHandler.obj \\r
+  $O\SplitHandler.obj \\r
+  $O\SquashfsHandler.obj \\r
+  $O\SwfHandler.obj \\r
+  $O\VhdHandler.obj \\r
+  $O\XarHandler.obj \\r
+  $O\XzHandler.obj \\r
+  $O\ZHandler.obj \\r
+\r
+AR_COMMON_OBJS = \\r
+  $O\CoderMixer2.obj \\r
+  $O\CoderMixer2MT.obj \\r
+  $O\CrossThreadProgress.obj \\r
+  $O\DummyOutStream.obj \\r
+  $O\FindSignature.obj \\r
+  $O\InStreamWithCRC.obj \\r
+  $O\ItemNameUtils.obj \\r
+  $O\MultiStream.obj \\r
+  $O\OutStreamWithCRC.obj \\r
+  $O\OutStreamWithSha1.obj \\r
+  $O\HandlerOut.obj \\r
+  $O\ParseProperties.obj \\r
+\r
+UI_COMMON_OBJS = \\r
+  $O\ArchiveCommandLine.obj \\r
+  $O\ArchiveExtractCallback.obj \\r
+  $O\ArchiveName.obj \\r
+  $O\ArchiveOpenCallback.obj \\r
+  $O\Bench.obj \\r
+  $O\CompressCall2.obj \\r
+  $O\DefaultName.obj \\r
+  $O\EnumDirItems.obj \\r
+  $O\Extract.obj \\r
+  $O\ExtractingFilePath.obj \\r
+  $O\LoadCodecs.obj \\r
+  $O\OpenArchive.obj \\r
+  $O\PropIDUtils.obj \\r
+  $O\SetProperties.obj \\r
+  $O\SortUtils.obj \\r
+  $O\TempFiles.obj \\r
+  $O\Update.obj \\r
+  $O\UpdateAction.obj \\r
+  $O\UpdateCallback.obj \\r
+  $O\UpdatePair.obj \\r
+  $O\UpdateProduce.obj \\r
+  $O\WorkDir.obj \\r
+  $O\ZipRegistry.obj \\r
+\r
+AGENT_OBJS = \\r
+  $O\Agent.obj \\r
+  $O\AgentOut.obj \\r
+  $O\AgentProxy.obj \\r
+  $O\ArchiveFolder.obj \\r
+  $O\ArchiveFolderOpen.obj \\r
+  $O\ArchiveFolderOut.obj \\r
+  $O\UpdateCallbackAgent.obj \\r
+\r
+EXPLORER_OBJS = \\r
+  $O\ContextMenu.obj \\r
+  $O\MyMessages.obj \\r
+  $O\RegistryContextMenu.obj \\r
+\r
+GUI_OBJS = \\r
+  $O\BenchmarkDialog.obj \\r
+  $O\CompressDialog.obj \\r
+  $O\ExtractDialog.obj \\r
+  $O\ExtractGUI.obj \\r
+  $O\UpdateCallbackGUI.obj \\r
+  $O\UpdateGUI.obj \\r
+\r
+\r
+7Z_OBJS = \\r
+  $O\7zCompressionMode.obj \\r
+  $O\7zDecode.obj \\r
+  $O\7zEncode.obj \\r
+  $O\7zExtract.obj \\r
+  $O\7zFolderInStream.obj \\r
+  $O\7zFolderOutStream.obj \\r
+  $O\7zHandler.obj \\r
+  $O\7zHandlerOut.obj \\r
+  $O\7zHeader.obj \\r
+  $O\7zIn.obj \\r
+  $O\7zOut.obj \\r
+  $O\7zProperties.obj \\r
+  $O\7zSpecStream.obj \\r
+  $O\7zUpdate.obj \\r
+  $O\7zRegister.obj \\r
+\r
+CAB_OBJS = \\r
+  $O\CabBlockInStream.obj \\r
+  $O\CabHandler.obj \\r
+  $O\CabHeader.obj \\r
+  $O\CabIn.obj \\r
+  $O\CabRegister.obj \\r
+\r
+CHM_OBJS = \\r
+  $O\ChmHandler.obj \\r
+  $O\ChmHeader.obj \\r
+  $O\ChmIn.obj \\r
+  $O\ChmRegister.obj \\r
+\r
+COM_OBJS = \\r
+  $O\ComHandler.obj \\r
+  $O\ComIn.obj \\r
+  $O\ComRegister.obj \\r
+\r
+HFS_OBJS = \\r
+  $O\HfsHandler.obj \\r
+  $O\HfsIn.obj \\r
+  $O\HfsRegister.obj \\r
+\r
+ISO_OBJS = \\r
+  $O\IsoHandler.obj \\r
+  $O\IsoHeader.obj \\r
+  $O\IsoIn.obj \\r
+  $O\IsoRegister.obj \\r
+\r
+NSIS_OBJS = \\r
+  $O\NsisDecode.obj \\r
+  $O\NsisHandler.obj \\r
+  $O\NsisIn.obj \\r
+  $O\NsisRegister.obj \\r
+\r
+RAR_OBJS = \\r
+  $O\RarHandler.obj \\r
+  $O\RarHeader.obj \\r
+  $O\RarIn.obj \\r
+  $O\RarItem.obj \\r
+  $O\RarVolumeInStream.obj \\r
+  $O\RarRegister.obj \\r
+\r
+TAR_OBJS = \\r
+  $O\TarHandler.obj \\r
+  $O\TarHandlerOut.obj \\r
+  $O\TarHeader.obj \\r
+  $O\TarIn.obj \\r
+  $O\TarOut.obj \\r
+  $O\TarUpdate.obj \\r
+  $O\TarRegister.obj \\r
+\r
+UDF_OBJS = \\r
+  $O\UdfHandler.obj \\r
+  $O\UdfIn.obj \\r
+  $O\UdfRegister.obj \\r
+\r
+WIM_OBJS = \\r
+  $O\WimHandler.obj \\r
+  $O\WimHandlerOut.obj \\r
+  $O\WimIn.obj \\r
+  $O\WimRegister.obj \\r
+\r
+ZIP_OBJS = \\r
+  $O\ZipAddCommon.obj \\r
+  $O\ZipHandler.obj \\r
+  $O\ZipHandlerOut.obj \\r
+  $O\ZipHeader.obj \\r
+  $O\ZipIn.obj \\r
+  $O\ZipItem.obj \\r
+  $O\ZipOut.obj \\r
+  $O\ZipUpdate.obj \\r
+  $O\ZipRegister.obj \\r
+\r
+COMPRESS_OBJS = \\r
+  $O\ArjDecoder1.obj \\r
+  $O\ArjDecoder2.obj \\r
+  $O\Bcj2Coder.obj \\r
+  $O\Bcj2Register.obj \\r
+  $O\BcjCoder.obj \\r
+  $O\BcjRegister.obj \\r
+  $O\BitlDecoder.obj \\r
+  $O\BranchCoder.obj \\r
+  $O\BranchMisc.obj \\r
+  $O\BranchRegister.obj \\r
+  $O\ByteSwap.obj \\r
+  $O\BZip2Crc.obj \\r
+  $O\BZip2Decoder.obj \\r
+  $O\BZip2Encoder.obj \\r
+  $O\BZip2Register.obj \\r
+  $O\CopyCoder.obj \\r
+  $O\CopyRegister.obj \\r
+  $O\Deflate64Register.obj \\r
+  $O\DeflateDecoder.obj \\r
+  $O\DeflateEncoder.obj \\r
+  $O\DeflateRegister.obj \\r
+  $O\DeltaFilter.obj \\r
+  $O\ImplodeDecoder.obj \\r
+  $O\ImplodeHuffmanDecoder.obj \\r
+  $O\LzhDecoder.obj \\r
+  $O\Lzma2Decoder.obj \\r
+  $O\Lzma2Encoder.obj \\r
+  $O\Lzma2Register.obj \\r
+  $O\LzmaDecoder.obj \\r
+  $O\LzmaEncoder.obj \\r
+  $O\LzmaRegister.obj \\r
+  $O\LzOutWindow.obj \\r
+  $O\Lzx86Converter.obj \\r
+  $O\LzxDecoder.obj \\r
+  $O\PpmdDecoder.obj \\r
+  $O\PpmdEncoder.obj \\r
+  $O\PpmdRegister.obj \\r
+  $O\PpmdZip.obj \\r
+  $O\QuantumDecoder.obj \\r
+  $O\Rar1Decoder.obj \\r
+  $O\Rar2Decoder.obj \\r
+  $O\Rar3Decoder.obj \\r
+  $O\Rar3Vm.obj \\r
+  $O\RarCodecsRegister.obj \\r
+  $O\ShrinkDecoder.obj \\r
+  $O\ZlibDecoder.obj \\r
+  $O\ZlibEncoder.obj \\r
+  $O\ZDecoder.obj \\r
+\r
+CRYPTO_OBJS = \\r
+  $O\7zAes.obj \\r
+  $O\7zAesRegister.obj \\r
+  $O\HmacSha1.obj \\r
+  $O\MyAes.obj \\r
+  $O\Pbkdf2HmacSha1.obj \\r
+  $O\RandGen.obj \\r
+  $O\Rar20Crypto.obj \\r
+  $O\RarAes.obj \\r
+  $O\Sha1.obj \\r
+  $O\WzAes.obj \\r
+  $O\ZipCrypto.obj \\r
+  $O\ZipStrong.obj \\r
+\r
+\r
+C_OBJS = \\r
+  $O\7zBuf2.obj \\r
+  $O\7zStream.obj \\r
+  $O\Alloc.obj \\r
+  $O\Bra.obj \\r
+  $O\Bra86.obj \\r
+  $O\BraIA64.obj \\r
+  $O\BwtSort.obj \\r
+  $O\CpuArch.obj \\r
+  $O\Delta.obj \\r
+  $O\HuffEnc.obj \\r
+  $O\LzFind.obj \\r
+  $O\LzFindMt.obj \\r
+  $O\Lzma2Dec.obj \\r
+  $O\Lzma2Enc.obj \\r
+  $O\LzmaDec.obj \\r
+  $O\LzmaEnc.obj \\r
+  $O\MtCoder.obj \\r
+  $O\Ppmd7.obj \\r
+  $O\Ppmd7Dec.obj \\r
+  $O\Ppmd7Enc.obj \\r
+  $O\Ppmd8.obj \\r
+  $O\Ppmd8Dec.obj \\r
+  $O\Ppmd8Enc.obj \\r
+  $O\Sha256.obj \\r
+  $O\Sort.obj \\r
+  $O\Threads.obj \\r
+  $O\Xz.obj \\r
+  $O\XzCrc64.obj \\r
+  $O\XzDec.obj \\r
+  $O\XzEnc.obj \\r
+  $O\XzIn.obj \\r
+\r
+!include "../../Aes.mak"\r
+!include "../../Crc.mak"\r
+\r
+OBJS = \\r
+  $O\StdAfx.obj \\r
+  $(FM_OBJS)\\r
+  $(COMMON_OBJS) \\r
+  $(WIN_OBJS) \\r
+  $(WIN_CTRL_OBJS) \\r
+  $(7ZIP_COMMON_OBJS) \\r
+  $(AR_OBJS) \\r
+  $(AR_COMMON_OBJS) \\r
+  $(UI_COMMON_OBJS) \\r
+  $(AGENT_OBJS) \\r
+  $(EXPLORER_OBJS) \\r
+  $(GUI_OBJS) \\r
+  $(7Z_OBJS) \\r
+  $(CAB_OBJS) \\r
+  $(CHM_OBJS) \\r
+  $(COM_OBJS) \\r
+  $(HFS_OBJS) \\r
+  $(ISO_OBJS) \\r
+  $(NSIS_OBJS) \\r
+  $(RAR_OBJS) \\r
+  $(TAR_OBJS) \\r
+  $(UDF_OBJS) \\r
+  $(WIM_OBJS) \\r
+  $(ZIP_OBJS) \\r
+  $(COMPRESS_OBJS) \\r
+  $(CRYPTO_OBJS) \\r
+  $(C_OBJS) \\r
+  $(ASM_OBJS) \\r
+  $O\resource.res \\r
+\r
+!include "../../../Build.mak"\r
+\r
+$(FM_OBJS): ../../UI/FileManager/$(*B).cpp\r
+       $(COMPL)\r
+$(COMMON_OBJS): ../../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_OBJS): ../../../Windows/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp\r
+       $(COMPL)\r
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(AR_OBJS): ../../Archive/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(7Z_OBJS): ../../Archive/7z/$(*B).cpp\r
+       $(COMPL)\r
+$(CAB_OBJS): ../../Archive/Cab/$(*B).cpp\r
+       $(COMPL)\r
+$(CHM_OBJS): ../../Archive/Chm/$(*B).cpp\r
+       $(COMPL)\r
+$(COM_OBJS): ../../Archive/Com/$(*B).cpp\r
+       $(COMPL)\r
+$(HFS_OBJS): ../../Archive/Hfs/$(*B).cpp\r
+       $(COMPL)\r
+$(ISO_OBJS): ../../Archive/Iso/$(*B).cpp\r
+       $(COMPL)\r
+$(NSIS_OBJS): ../../Archive/Nsis/$(*B).cpp\r
+       $(COMPL)\r
+$(RAR_OBJS): ../../Archive/Rar/$(*B).cpp\r
+       $(COMPL)\r
+$(TAR_OBJS): ../../Archive/Tar/$(*B).cpp\r
+       $(COMPL)\r
+$(UDF_OBJS): ../../Archive/Udf/$(*B).cpp\r
+       $(COMPL)\r
+$(WIM_OBJS): ../../Archive/Wim/$(*B).cpp\r
+       $(COMPL)\r
+$(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp\r
+       $(COMPL_O2)\r
+\r
+$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp\r
+       $(COMPL_O2)\r
+\r
+$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp\r
+       $(COMPL)\r
+$(AGENT_OBJS): ../../UI/Agent/$(*B).cpp\r
+       $(COMPL)\r
+$(EXPLORER_OBJS): ../../UI/Explorer/$(*B).cpp\r
+       $(COMPL)\r
+$(GUI_OBJS): ../../UI/GUI/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(C_OBJS): ../../../../C/$(*B).c\r
+       $(COMPL_O2)\r
+\r
+!include "../../Asm.mak"\r
diff --git a/CPP/7zip/Bundles/Fm/resource.rc b/CPP/7zip/Bundles/Fm/resource.rc
new file mode 100755 (executable)
index 0000000..218e6d0
--- /dev/null
@@ -0,0 +1,7 @@
+#include "../../UI/FileManager/resource.rc"\r
+#include "../../UI/GUI/resource2.rc"\r
+\r
+STRINGTABLE\r
+BEGIN\r
+  100 "7z zip bz2 bzip2 tbz2 tbz rar arj z taz lzh lha cab iso 001 rpm deb cpio tar gz gzip tgz tpz4 wim swm lzma dmg hfs xar vhd fat ntfs xz"\r
+END\r
diff --git a/CPP/7zip/Bundles/Format7z/StdAfx.cpp b/CPP/7zip/Bundles/Format7z/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..c6d3b1f
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/Bundles/Format7z/StdAfx.h b/CPP/7zip/Bundles/Format7z/StdAfx.h
new file mode 100755 (executable)
index 0000000..a4e6173
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+#include "../../../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Bundles/Format7z/makefile b/CPP/7zip/Bundles/Format7z/makefile
new file mode 100755 (executable)
index 0000000..14293e4
--- /dev/null
@@ -0,0 +1,181 @@
+PROG = 7za.dll\r
+DEF_FILE = ../../Archive/Archive2.def\r
+CFLAGS = $(CFLAGS) -I ../../../ \\r
+  -DDEFLATE_EXTRACT_ONLY \\r
+  -DBZIP2_EXTRACT_ONLY \\r
+\r
+COMMON_OBJS = \\r
+  $O\CRC.obj \\r
+  $O\IntToString.obj \\r
+  $O\NewHandler.obj \\r
+  $O\MyString.obj \\r
+  $O\StringConvert.obj \\r
+  $O\StringToInt.obj \\r
+  $O\MyVector.obj \\r
+  $O\Wildcard.obj \\r
+\r
+WIN_OBJS = \\r
+  $O\FileDir.obj \\r
+  $O\FileFind.obj \\r
+  $O\FileIO.obj \\r
+  $O\PropVariant.obj \\r
+  $O\Synchronization.obj \\r
+  $O\System.obj \\r
+\r
+7ZIP_COMMON_OBJS = \\r
+  $O\CreateCoder.obj \\r
+  $O\CWrappers.obj \\r
+  $O\InBuffer.obj \\r
+  $O\InOutTempBuffer.obj \\r
+  $O\FilterCoder.obj \\r
+  $O\LimitedStreams.obj \\r
+  $O\LockedStream.obj \\r
+  $O\MethodId.obj \\r
+  $O\MethodProps.obj \\r
+  $O\OutBuffer.obj \\r
+  $O\ProgressUtils.obj \\r
+  $O\StreamBinder.obj \\r
+  $O\StreamObjects.obj \\r
+  $O\StreamUtils.obj \\r
+  $O\VirtThread.obj \\r
+\r
+AR_OBJS = \\r
+  $O\ArchiveExports.obj \\r
+  $O\DllExports2.obj \\r
+\r
+AR_COMMON_OBJS = \\r
+  $O\CoderMixer2.obj \\r
+  $O\CoderMixer2MT.obj \\r
+  $O\CrossThreadProgress.obj \\r
+  $O\HandlerOut.obj \\r
+  $O\InStreamWithCRC.obj \\r
+  $O\ItemNameUtils.obj \\r
+  $O\OutStreamWithCRC.obj \\r
+  $O\ParseProperties.obj \\r
+\r
+\r
+7Z_OBJS = \\r
+  $O\7zCompressionMode.obj \\r
+  $O\7zDecode.obj \\r
+  $O\7zEncode.obj \\r
+  $O\7zExtract.obj \\r
+  $O\7zFolderInStream.obj \\r
+  $O\7zFolderOutStream.obj \\r
+  $O\7zHandler.obj \\r
+  $O\7zHandlerOut.obj \\r
+  $O\7zHeader.obj \\r
+  $O\7zIn.obj \\r
+  $O\7zOut.obj \\r
+  $O\7zProperties.obj \\r
+  $O\7zSpecStream.obj \\r
+  $O\7zUpdate.obj \\r
+  $O\7zRegister.obj \\r
+\r
+\r
+COMPRESS_OBJS = \\r
+  $O\CodecExports.obj \\r
+  $O\Bcj2Coder.obj \\r
+  $O\Bcj2Register.obj \\r
+  $O\BcjCoder.obj \\r
+  $O\BcjRegister.obj \\r
+  $O\BitlDecoder.obj \\r
+  $O\BranchCoder.obj \\r
+  $O\BranchMisc.obj \\r
+  $O\BranchRegister.obj \\r
+  $O\ByteSwap.obj \\r
+  $O\BZip2Crc.obj \\r
+  $O\BZip2Decoder.obj \\r
+  $O\BZip2Encoder.obj \\r
+  $O\BZip2Register.obj \\r
+  $O\CopyCoder.obj \\r
+  $O\CopyRegister.obj \\r
+  $O\DeflateDecoder.obj \\r
+  $O\DeflateEncoder.obj \\r
+  $O\DeflateRegister.obj \\r
+  $O\DeltaFilter.obj \\r
+  $O\Lzma2Decoder.obj \\r
+  $O\Lzma2Encoder.obj \\r
+  $O\Lzma2Register.obj \\r
+  $O\LzmaDecoder.obj \\r
+  $O\LzmaEncoder.obj \\r
+  $O\LzmaRegister.obj \\r
+  $O\LzOutWindow.obj \\r
+  $O\PpmdDecoder.obj \\r
+  $O\PpmdEncoder.obj \\r
+  $O\PpmdRegister.obj \\r
+\r
+CRYPTO_OBJS = \\r
+  $O\7zAes.obj \\r
+  $O\7zAesRegister.obj \\r
+  $O\MyAes.obj \\r
+  $O\RandGen.obj \\r
+  $O\Sha1.obj \\r
+\r
+C_OBJS = \\r
+  $O\Alloc.obj \\r
+  $O\Bra.obj \\r
+  $O\Bra86.obj \\r
+  $O\BraIA64.obj \\r
+  $O\BwtSort.obj \\r
+  $O\CpuArch.obj \\r
+  $O\Delta.obj \\r
+  $O\HuffEnc.obj \\r
+  $O\LzFind.obj \\r
+  $O\LzFindMt.obj \\r
+  $O\Lzma2Dec.obj \\r
+  $O\Lzma2Enc.obj \\r
+  $O\LzmaDec.obj \\r
+  $O\LzmaEnc.obj \\r
+  $O\MtCoder.obj \\r
+  $O\Ppmd7.obj \\r
+  $O\Ppmd7Dec.obj \\r
+  $O\Ppmd7Enc.obj \\r
+  $O\Sha256.obj \\r
+  $O\Sort.obj \\r
+  $O\Threads.obj \\r
+\r
+!include "../../Aes.mak"\r
+!include "../../Crc.mak"\r
+\r
+OBJS = \\r
+  $O\StdAfx.obj \\r
+  $(CONSOLE_OBJS) \\r
+  $(COMMON_OBJS) \\r
+  $(WIN_OBJS) \\r
+  $(7ZIP_COMMON_OBJS) \\r
+  $(AR_OBJS) \\r
+  $(AR_COMMON_OBJS) \\r
+  $(7Z_OBJS) \\r
+  $(COMPRESS_OBJS) \\r
+  $(CRYPTO_OBJS) \\r
+  $(C_OBJS) \\r
+  $(ASM_OBJS) \\r
+  $O\resource.res\r
+\r
+\r
+!include "../../../Build.mak"\r
+\r
+$(COMMON_OBJS): ../../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_OBJS): ../../../Windows/$(*B).cpp\r
+       $(COMPL)\r
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_OBJS): ../../Archive/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(7Z_OBJS): ../../Archive/7z/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp\r
+       $(COMPL_O2)\r
+\r
+$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp\r
+       $(COMPL_O2)\r
+\r
+$(C_OBJS): ../../../../C/$(*B).c\r
+       $(COMPL_O2)\r
+\r
+!include "../../Asm.mak"\r
diff --git a/CPP/7zip/Bundles/Format7z/resource.rc b/CPP/7zip/Bundles/Format7z/resource.rc
new file mode 100755 (executable)
index 0000000..53d6be0
--- /dev/null
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"\r
+\r
+MY_VERSION_INFO_DLL("7z Standalone Plugin", "7za")\r
+\r
+101  ICON  "../../Archive/Icons/7z.ico"\r
diff --git a/CPP/7zip/Bundles/Format7zExtract/StdAfx.cpp b/CPP/7zip/Bundles/Format7zExtract/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..c6d3b1f
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/Bundles/Format7zExtract/StdAfx.h b/CPP/7zip/Bundles/Format7zExtract/StdAfx.h
new file mode 100755 (executable)
index 0000000..a4e6173
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+#include "../../../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Bundles/Format7zExtract/makefile b/CPP/7zip/Bundles/Format7zExtract/makefile
new file mode 100755 (executable)
index 0000000..ee883ca
--- /dev/null
@@ -0,0 +1,150 @@
+PROG = 7zxa.dll\r
+DEF_FILE = ../../Archive/Archive2.def\r
+CFLAGS = $(CFLAGS) -I ../../../ \\r
+  -DEXTRACT_ONLY \\r
+\r
+COMMON_OBJS = \\r
+  $O\CRC.obj \\r
+  $O\IntToString.obj \\r
+  $O\NewHandler.obj \\r
+  $O\MyString.obj \\r
+  $O\StringConvert.obj \\r
+  $O\StringToInt.obj \\r
+  $O\MyVector.obj \\r
+  $O\Wildcard.obj \\r
+\r
+WIN_OBJS = \\r
+  $O\PropVariant.obj \\r
+  $O\Synchronization.obj \\r
+  $O\System.obj \\r
+\r
+7ZIP_COMMON_OBJS = \\r
+  $O\CreateCoder.obj \\r
+  $O\CWrappers.obj \\r
+  $O\InBuffer.obj \\r
+  $O\FilterCoder.obj \\r
+  $O\LimitedStreams.obj \\r
+  $O\LockedStream.obj \\r
+  $O\MethodId.obj \\r
+  $O\OutBuffer.obj \\r
+  $O\ProgressUtils.obj \\r
+  $O\StreamBinder.obj \\r
+  $O\StreamObjects.obj \\r
+  $O\StreamUtils.obj \\r
+  $O\VirtThread.obj \\r
+\r
+AR_OBJS = \\r
+  $O\ArchiveExports.obj \\r
+  $O\DllExports2.obj \\r
+\r
+AR_COMMON_OBJS = \\r
+  $O\CoderMixer2.obj \\r
+  $O\CoderMixer2MT.obj \\r
+  $O\CrossThreadProgress.obj \\r
+  $O\ItemNameUtils.obj \\r
+  $O\OutStreamWithCRC.obj \\r
+  $O\ParseProperties.obj \\r
+\r
+7Z_OBJS = \\r
+  $O\7zCompressionMode.obj \\r
+  $O\7zDecode.obj \\r
+  $O\7zExtract.obj \\r
+  $O\7zFolderOutStream.obj \\r
+  $O\7zHandler.obj \\r
+  $O\7zHeader.obj \\r
+  $O\7zIn.obj \\r
+  $O\7zProperties.obj \\r
+  $O\7zRegister.obj \\r
+\r
+\r
+COMPRESS_OBJS = \\r
+  $O\CodecExports.obj \\r
+  $O\Bcj2Coder.obj \\r
+  $O\Bcj2Register.obj \\r
+  $O\BcjCoder.obj \\r
+  $O\BcjRegister.obj \\r
+  $O\BitlDecoder.obj \\r
+  $O\BranchCoder.obj \\r
+  $O\BranchMisc.obj \\r
+  $O\BranchRegister.obj \\r
+  $O\ByteSwap.obj \\r
+  $O\BZip2Crc.obj \\r
+  $O\BZip2Decoder.obj \\r
+  $O\BZip2Register.obj \\r
+  $O\CopyCoder.obj \\r
+  $O\CopyRegister.obj \\r
+  $O\DeflateDecoder.obj \\r
+  $O\DeflateRegister.obj \\r
+  $O\DeltaFilter.obj \\r
+  $O\Lzma2Decoder.obj \\r
+  $O\Lzma2Register.obj \\r
+  $O\LzmaDecoder.obj \\r
+  $O\LzmaRegister.obj \\r
+  $O\LzOutWindow.obj \\r
+  $O\PpmdDecoder.obj \\r
+  $O\PpmdRegister.obj \\r
+\r
+CRYPTO_OBJS = \\r
+  $O\7zAes.obj \\r
+  $O\7zAesRegister.obj \\r
+  $O\MyAes.obj \\r
+\r
+C_OBJS = \\r
+  $O\Alloc.obj \\r
+  $O\Bra.obj \\r
+  $O\Bra86.obj \\r
+  $O\BraIA64.obj \\r
+  $O\CpuArch.obj \\r
+  $O\Delta.obj \\r
+  $O\Lzma2Dec.obj \\r
+  $O\LzmaDec.obj \\r
+  $O\Ppmd7.obj \\r
+  $O\Ppmd7Dec.obj \\r
+  $O\Sha256.obj \\r
+  $O\Threads.obj \\r
+\r
+!include "../../Aes.mak"\r
+!include "../../Crc.mak"\r
+\r
+OBJS = \\r
+  $O\StdAfx.obj \\r
+  $(CONSOLE_OBJS) \\r
+  $(COMMON_OBJS) \\r
+  $(WIN_OBJS) \\r
+  $(7ZIP_COMMON_OBJS) \\r
+  $(AR_OBJS) \\r
+  $(AR_COMMON_OBJS) \\r
+  $(7Z_OBJS) \\r
+  $(COMPRESS_OBJS) \\r
+  $(CRYPTO_OBJS) \\r
+  $(C_OBJS) \\r
+  $(ASM_OBJS) \\r
+  $O\resource.res\r
+\r
+\r
+!include "../../../Build.mak"\r
+\r
+$(COMMON_OBJS): ../../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_OBJS): ../../../Windows/$(*B).cpp\r
+       $(COMPL)\r
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_OBJS): ../../Archive/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(7Z_OBJS): ../../Archive/7z/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp\r
+       $(COMPL_O2)\r
+\r
+$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp\r
+       $(COMPL_O2)\r
+\r
+$(C_OBJS): ../../../../C/$(*B).c\r
+       $(COMPL_O2)\r
+\r
+!include "../../Asm.mak"\r
diff --git a/CPP/7zip/Bundles/Format7zExtract/resource.rc b/CPP/7zip/Bundles/Format7zExtract/resource.rc
new file mode 100755 (executable)
index 0000000..e85e7e9
--- /dev/null
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"\r
+\r
+MY_VERSION_INFO_DLL("7z Standalone Extracting Plugin", "7zxa")\r
+\r
+101  ICON  "../../Archive/Icons/7z.ico"\r
diff --git a/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp b/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..c6d3b1f
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h b/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h
new file mode 100755 (executable)
index 0000000..a4e6173
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+#include "../../../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Bundles/Format7zExtractR/makefile b/CPP/7zip/Bundles/Format7zExtractR/makefile
new file mode 100755 (executable)
index 0000000..34a9bb3
--- /dev/null
@@ -0,0 +1,132 @@
+PROG = 7zxr.dll\r
+DEF_FILE = ../../Archive/Archive2.def\r
+CFLAGS = $(CFLAGS) -I ../../../ \\r
+  -DEXTRACT_ONLY \\r
+  -D_NO_CRYPTO\r
+\r
+COMMON_OBJS = \\r
+  $O\CRC.obj \\r
+  $O\IntToString.obj \\r
+  $O\NewHandler.obj \\r
+  $O\MyString.obj \\r
+  $O\StringConvert.obj \\r
+  $O\StringToInt.obj \\r
+  $O\MyVector.obj \\r
+  $O\Wildcard.obj \\r
+\r
+WIN_OBJS = \\r
+  $O\PropVariant.obj \\r
+  $O\Synchronization.obj \\r
+  $O\System.obj \\r
+\r
+7ZIP_COMMON_OBJS = \\r
+  $O\CreateCoder.obj \\r
+  $O\CWrappers.obj \\r
+  $O\InBuffer.obj \\r
+  $O\FilterCoder.obj \\r
+  $O\LimitedStreams.obj \\r
+  $O\LockedStream.obj \\r
+  $O\MethodId.obj \\r
+  $O\MethodProps.obj \\r
+  $O\OutBuffer.obj \\r
+  $O\ProgressUtils.obj \\r
+  $O\StreamBinder.obj \\r
+  $O\StreamObjects.obj \\r
+  $O\StreamUtils.obj \\r
+  $O\VirtThread.obj \\r
+\r
+AR_OBJS = \\r
+  $O\ArchiveExports.obj \\r
+  $O\DllExports2.obj \\r
+\r
+AR_COMMON_OBJS = \\r
+  $O\CoderMixer2.obj \\r
+  $O\CoderMixer2MT.obj \\r
+  $O\CrossThreadProgress.obj \\r
+  $O\HandlerOut.obj \\r
+  $O\ItemNameUtils.obj \\r
+  $O\OutStreamWithCRC.obj \\r
+  $O\ParseProperties.obj \\r
+\r
+\r
+7Z_OBJS = \\r
+  $O\7zCompressionMode.obj \\r
+  $O\7zDecode.obj \\r
+  $O\7zExtract.obj \\r
+  $O\7zFolderOutStream.obj \\r
+  $O\7zHandler.obj \\r
+  $O\7zHeader.obj \\r
+  $O\7zIn.obj \\r
+  $O\7zProperties.obj \\r
+  $O\7zRegister.obj \\r
+\r
+\r
+COMPRESS_OBJS = \\r
+  $O\CodecExports.obj \\r
+  $O\Bcj2Coder.obj \\r
+  $O\Bcj2Register.obj \\r
+  $O\BcjCoder.obj \\r
+  $O\BcjRegister.obj \\r
+  $O\BranchCoder.obj \\r
+  $O\BranchMisc.obj \\r
+  $O\BranchRegister.obj \\r
+  $O\ByteSwap.obj \\r
+  $O\CopyCoder.obj \\r
+  $O\CopyRegister.obj \\r
+  $O\DeltaFilter.obj \\r
+  $O\Lzma2Decoder.obj \\r
+  $O\Lzma2Register.obj \\r
+  $O\LzmaDecoder.obj \\r
+  $O\LzmaRegister.obj \\r
+\r
+C_OBJS = \\r
+  $O\Alloc.obj \\r
+  $O\Bra.obj \\r
+  $O\Bra86.obj \\r
+  $O\BraIA64.obj \\r
+  $O\CpuArch.obj \\r
+  $O\Delta.obj \\r
+  $O\Lzma2Dec.obj \\r
+  $O\LzmaDec.obj \\r
+  $O\Threads.obj \\r
+\r
+!include "../../Crc.mak"\r
+\r
+OBJS = \\r
+  $O\StdAfx.obj \\r
+  $(CONSOLE_OBJS) \\r
+  $(COMMON_OBJS) \\r
+  $(WIN_OBJS) \\r
+  $(7ZIP_COMMON_OBJS) \\r
+  $(AR_OBJS) \\r
+  $(AR_COMMON_OBJS) \\r
+  $(7Z_OBJS) \\r
+  $(COMPRESS_OBJS) \\r
+  $(C_OBJS) \\r
+  $(ASM_OBJS) \\r
+  $O\resource.res\r
+\r
+\r
+!include "../../../Build.mak"\r
+\r
+$(COMMON_OBJS): ../../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_OBJS): ../../../Windows/$(*B).cpp\r
+       $(COMPL)\r
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_OBJS): ../../Archive/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(7Z_OBJS): ../../Archive/7z/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp\r
+       $(COMPL_O2)\r
+\r
+$(C_OBJS): ../../../../C/$(*B).c\r
+       $(COMPL_O2)\r
+\r
+!include "../../Asm.mak"\r
diff --git a/CPP/7zip/Bundles/Format7zExtractR/resource.rc b/CPP/7zip/Bundles/Format7zExtractR/resource.rc
new file mode 100755 (executable)
index 0000000..652c4a1
--- /dev/null
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"\r
+\r
+MY_VERSION_INFO_DLL("7z Standalone Extracting Plugin", "7zxr")\r
+\r
+101  ICON  "../../Archive/Icons/7z.ico"\r
diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp
new file mode 100755 (executable)
index 0000000..92c9a30
--- /dev/null
@@ -0,0 +1,2627 @@
+# Microsoft Developer Studio Project File - Name="7z" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
+\r
+CFG=7z - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "Format7z.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "Format7z.mak" CFG="7z - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "7z - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE "7z - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+MTL=midl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 1\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /YX /FD /c\r
+# 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\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-Zip\7z.dll" /opt:NOWIN98\r
+# SUBTRACT LINK32 /pdb:none /debug\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 1\r
+# PROP Target_Dir ""\r
+# 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\r
+# 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\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x419 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-Zip\7z.dll" /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "7z - Win32 Release"\r
+# Name "7z - Win32 Debug"\r
+# Begin Group "Spec"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "Icons"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\7z.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\arj.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\bz2.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\cab.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\cpio.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\deb.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\dmg.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\fat.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\gz.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\hfs.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\iso.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\lzh.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\lzma.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\ntfs.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\rar.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\rpm.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\split.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\squashfs.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\tar.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\vhd.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\wim.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\xar.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\xz.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\z.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Icons\zip.ico\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Archive2.def\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\ArchiveExports.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CodecExports.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\DllExports2.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\resource.rc\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.cpp\r
+# ADD CPP /Yc"StdAfx.h"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Buffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\DynamicBuffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyCom.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyException.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyInitGuid.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyMap.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyMap.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyUnknown.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyWindows.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyXml.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyXml.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringToInt.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringToInt.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Types.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\UTFConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\UTFConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Compress"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "PPMD"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdDecoder.cpp\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdDecoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdEncoder.cpp\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdEncoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdSubAlloc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdType.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Bit Coder"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BitlDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BitlDecoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BitlEncoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BitmDecoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BitmEncoder.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Rar Compress"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Rar1Decoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Rar1Decoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Rar2Decoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Rar2Decoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Rar3Decoder.cpp\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Rar3Decoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Rar3Vm.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Rar3Vm.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\RarCodecsRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "BZip2 Compress"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BZip2Const.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BZip2Crc.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BZip2Crc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BZip2Decoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BZip2Decoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BZip2Encoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BZip2Encoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BZip2Register.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Mtf8.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Zip Compress"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Deflate64Register.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\DeflateConst.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\DeflateDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\DeflateDecoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\DeflateEncoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\DeflateEncoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\DeflateRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ImplodeDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ImplodeDecoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ImplodeHuffmanDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ImplodeHuffmanDecoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdZip.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdZip.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ShrinkDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ShrinkDecoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ZlibDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ZlibDecoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ZlibEncoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ZlibEncoder.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "7z Compress"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Bcj2Coder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Bcj2Coder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Bcj2Register.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BcjCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BcjCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BcjRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BranchCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BranchCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BranchMisc.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BranchMisc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BranchRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ByteSwap.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzma2Decoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzma2Decoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzma2Encoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzma2Encoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzma2Register.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaDecoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaEncoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaEncoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\RangeCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\RangeCoderBit.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Cab Compress"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzx.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzx86Converter.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzx86Converter.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzxDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzxDecoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\QuantumDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\QuantumDecoder.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ArjDecoder1.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ArjDecoder1.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ArjDecoder2.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ArjDecoder2.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\DeltaFilter.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\HuffmanDecoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzhDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzhDecoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzOutWindow.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzOutWindow.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ZDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\ZDecoder.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Crypto"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\7zAes.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\7zAes.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\7zAesRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\HmacSha1.cpp\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\HmacSha1.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\MyAes.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\MyAes.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\Pbkdf2HmacSha1.cpp\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\Pbkdf2HmacSha1.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\RandGen.cpp\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\RandGen.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\Rar20Crypto.cpp\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\Rar20Crypto.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\RarAes.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\RarAes.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\Sha1.cpp\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\Sha1.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\WzAes.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\WzAes.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\ZipCrypto.cpp\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\ZipCrypto.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\ZipStrong.cpp\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\ZipStrong.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "7zip Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CWrappers.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CWrappers.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\InBuffer.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\InBuffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\InOutTempBuffer.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\InOutTempBuffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LimitedStreams.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LimitedStreams.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LockedStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LockedStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\MemBlocks.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\MemBlocks.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\MethodId.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\MethodId.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\MethodProps.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\MethodProps.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OffsetStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OffsetStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OutBuffer.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OutBuffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OutMemStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OutMemStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressMt.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressMt.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\RegisterArc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\RegisterCodec.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamBinder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamBinder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamObjects.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamObjects.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\VirtThread.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\VirtThread.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "C"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "xz"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Xz.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /W4\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# ADD CPP /W4 /WX\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Xz.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\XzCrc64.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /W4 /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# ADD CPP /W4 /WX\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\XzCrc64.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\XzDec.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /W4\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# ADD CPP /W4 /WX\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\XzEnc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\XzEnc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\XzIn.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /W4\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# ADD CPP /W4 /WX\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zBuf2.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zStream.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Aes.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Aes.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Bra.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Bra.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Bra86.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\BraIA64.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\BwtSort.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\BwtSort.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Delta.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Delta.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\HuffEnc.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\HuffEnc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzFind.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzFind.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzFindMt.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzFindMt.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzHash.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Lzma2Dec.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Lzma2Dec.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Lzma2Enc.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Lzma2Enc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzmaDec.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzmaDec.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzmaEnc.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzmaEnc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\MtCoder.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\MtCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd7.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd7.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd7Dec.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd7Enc.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd8.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd8.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd8Dec.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd8Enc.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\RotateDefs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sha256.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sha256.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sort.c\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sort.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Types.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Archive"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "7z"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zCompressionMode.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zCompressionMode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zDecode.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zDecode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zEncode.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zEncode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zExtract.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zFolderInStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zFolderInStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zFolderOutStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHandlerOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHeader.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHeader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zItem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zOut.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zProperties.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zProperties.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zSpecStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zSpecStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zUpdate.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zUpdate.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zUpdateItem.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Rar"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Rar\RarHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Rar\RarHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Rar\RarHeader.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Rar\RarHeader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Rar\RarIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Rar\RarIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Rar\RarItem.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Rar\RarItem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Rar\RarRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Rar\RarVolumeInStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Rar\RarVolumeInStream.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Cab"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabBlockInStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabBlockInStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabHeader.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabHeader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabItem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Cab\CabRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Chm"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Chm\ChmHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Chm\ChmHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Chm\ChmHeader.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Chm\ChmHeader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Chm\ChmIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Chm\ChmIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Chm\ChmRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Archive common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2MT.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\DummyOutStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\DummyOutStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\FindSignature.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\FindSignature.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\HandlerOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\HandlerOut.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\InStreamWithCRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\InStreamWithCRC.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\ItemNameUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\ItemNameUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\MultiStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\MultiStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithSha1.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithSha1.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\ParseProperties.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\ParseProperties.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Iso"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Iso\IsoHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Iso\IsoHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Iso\IsoHeader.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Iso\IsoHeader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Iso\IsoIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Iso\IsoIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Iso\IsoItem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Iso\IsoRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Nsis"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Nsis\NsisDecode.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Nsis\NsisDecode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Nsis\NsisHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Nsis\NsisHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Nsis\NsisIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Nsis\NsisIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Nsis\NsisRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Tar"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarHandlerOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarHeader.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarHeader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarItem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarOut.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarUpdate.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Tar\TarUpdate.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Zip"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipAddCommon.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipAddCommon.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipCompressionMode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipHandlerOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipHeader.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipHeader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipItem.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipItem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipItemEx.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipOut.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipUpdate.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Zip\ZipUpdate.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Wim"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Wim\WimHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Wim\WimHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Wim\WimHandlerOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Wim\WimIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Wim\WimIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Wim\WimRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Com"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Com\ComHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Com\ComHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Com\ComIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Com\ComIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Com\ComRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Hfs"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Hfs\HfsHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Hfs\HfsHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Hfs\HfsIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Hfs\HfsIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Hfs\HfsRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Udf"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Udf\UdfHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Udf\UdfHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Udf\UdfIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Udf\UdfIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Udf\UdfRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\ApmHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\ArjHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Bz2Handler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\CpioHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\CramfsHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\DebHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\DeflateProps.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\DeflateProps.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\DmgHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\ElfHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\FatHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\FlvHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\GzHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\IArchive.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\LzhHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\LzmaHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\MachoHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\MbrHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\MslzHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\MubHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\NtfsHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\PeHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\PpmdHandler.cpp\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\RpmHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\SplitHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\SquashfsHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\SwfHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\VhdHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\XarHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\XzHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\ZHandler.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "7zip"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\ICoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\IDecl.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\IPassword.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\IProgress.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\IStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\PropID.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Windows"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\System.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\System.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Thread.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Time.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Time.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Asm"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\Asm\x86\7zAsm.asm\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\Asm\x86\7zCrcOpt.asm\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# Begin Custom Build\r
+OutDir=.\Release\r
+InputPath=..\..\..\..\Asm\x86\7zCrcOpt.asm\r
+InputName=7zCrcOpt\r
+\r
+"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+       ml.exe -c -Fo$(OutDir)\$(InputName).obj $(InputPath)\r
+\r
+# End Custom Build\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# Begin Custom Build\r
+OutDir=.\Debug\r
+InputPath=..\..\..\..\Asm\x86\7zCrcOpt.asm\r
+InputName=7zCrcOpt\r
+\r
+"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+       ml.exe -c -omf -Fo$(OutDir)\$(InputName).obj $(InputPath)\r
+\r
+# End Custom Build\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\Asm\x86\AesOpt.asm\r
+\r
+!IF  "$(CFG)" == "7z - Win32 Release"\r
+\r
+# PROP Ignore_Default_Tool 1\r
+# Begin Custom Build\r
+OutDir=.\Release\r
+InputPath=..\..\..\..\Asm\x86\AesOpt.asm\r
+InputName=AesOpt\r
+\r
+"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+       ml.exe -c -Fo$(OutDir)\$(InputName).obj $(InputPath)\r
+\r
+# End Custom Build\r
+\r
+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"\r
+\r
+# PROP Ignore_Default_Tool 1\r
+# Begin Custom Build\r
+OutDir=.\Debug\r
+InputPath=..\..\..\..\Asm\x86\AesOpt.asm\r
+InputName=AesOpt\r
+\r
+"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+       ml.exe -c -omf -WX -W3 -Fo$(OutDir)\$(InputName).obj $(InputPath)\r
+\r
+# End Custom Build\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsw b/CPP/7zip/Bundles/Format7zF/Format7z.dsw
new file mode 100755 (executable)
index 0000000..bb68d25
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "7z"=.\Format7z.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/CPP/7zip/Bundles/Format7zF/StdAfx.cpp b/CPP/7zip/Bundles/Format7zF/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..c6d3b1f
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/Bundles/Format7zF/StdAfx.h b/CPP/7zip/Bundles/Format7zF/StdAfx.h
new file mode 100755 (executable)
index 0000000..a4e6173
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+#include "../../../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Bundles/Format7zF/makefile b/CPP/7zip/Bundles/Format7zF/makefile
new file mode 100755 (executable)
index 0000000..6327ba5
--- /dev/null
@@ -0,0 +1,369 @@
+PROG = 7z.dll\r
+DEF_FILE = ../../Archive/Archive2.def\r
+CFLAGS = $(CFLAGS) -I ../../../ \\r
+  -DEXTERNAL_CODECS \\r
+\r
+!IFNDEF UNDER_CE\r
+CFLAGS = $(CFLAGS) -D_7ZIP_LARGE_PAGES\r
+!ENDIF\r
+\r
+COMMON_OBJS = \\r
+  $O\CRC.obj \\r
+  $O\IntToString.obj \\r
+  $O\MyMap.obj \\r
+  $O\MyString.obj \\r
+  $O\MyVector.obj \\r
+  $O\MyXml.obj \\r
+  $O\NewHandler.obj \\r
+  $O\StringConvert.obj \\r
+  $O\StringToInt.obj \\r
+  $O\UTFConvert.obj \\r
+  $O\Wildcard.obj \\r
+\r
+WIN_OBJS = \\r
+  $O\FileDir.obj \\r
+  $O\FileFind.obj \\r
+  $O\FileIO.obj \\r
+  $O\PropVariant.obj \\r
+  $O\PropVariantUtils.obj \\r
+  $O\Synchronization.obj \\r
+  $O\System.obj \\r
+  $O\Time.obj \\r
+\r
+7ZIP_COMMON_OBJS = \\r
+  $O\CreateCoder.obj \\r
+  $O\CWrappers.obj \\r
+  $O\InBuffer.obj \\r
+  $O\InOutTempBuffer.obj \\r
+  $O\FilterCoder.obj \\r
+  $O\LimitedStreams.obj \\r
+  $O\LockedStream.obj \\r
+  $O\MemBlocks.obj \\r
+  $O\MethodId.obj \\r
+  $O\MethodProps.obj \\r
+  $O\OffsetStream.obj \\r
+  $O\OutBuffer.obj \\r
+  $O\OutMemStream.obj \\r
+  $O\ProgressMt.obj \\r
+  $O\ProgressUtils.obj \\r
+  $O\StreamBinder.obj \\r
+  $O\StreamObjects.obj \\r
+  $O\StreamUtils.obj \\r
+  $O\VirtThread.obj \\r
+\r
+AR_OBJS = \\r
+  $O\ArchiveExports.obj \\r
+  $O\DllExports2.obj \\r
+  $O\ApmHandler.obj \\r
+  $O\ArjHandler.obj \\r
+  $O\Bz2Handler.obj \\r
+  $O\CpioHandler.obj \\r
+  $O\CramfsHandler.obj \\r
+  $O\DebHandler.obj \\r
+  $O\DeflateProps.obj \\r
+  $O\DmgHandler.obj \\r
+  $O\ElfHandler.obj \\r
+  $O\FatHandler.obj \\r
+  $O\FlvHandler.obj \\r
+  $O\GzHandler.obj \\r
+  $O\LzhHandler.obj \\r
+  $O\LzmaHandler.obj \\r
+  $O\MachoHandler.obj \\r
+  $O\MbrHandler.obj \\r
+  $O\MslzHandler.obj \\r
+  $O\MubHandler.obj \\r
+  $O\NtfsHandler.obj \\r
+  $O\PeHandler.obj \\r
+  $O\PpmdHandler.obj \\r
+  $O\RpmHandler.obj \\r
+  $O\SplitHandler.obj \\r
+  $O\SwfHandler.obj \\r
+  $O\SquashfsHandler.obj \\r
+  $O\VhdHandler.obj \\r
+  $O\XarHandler.obj \\r
+  $O\XzHandler.obj \\r
+  $O\ZHandler.obj \\r
+\r
+AR_COMMON_OBJS = \\r
+  $O\CoderMixer2.obj \\r
+  $O\CoderMixer2MT.obj \\r
+  $O\CrossThreadProgress.obj \\r
+  $O\DummyOutStream.obj \\r
+  $O\FindSignature.obj \\r
+  $O\InStreamWithCRC.obj \\r
+  $O\ItemNameUtils.obj \\r
+  $O\MultiStream.obj \\r
+  $O\OutStreamWithCRC.obj \\r
+  $O\OutStreamWithSha1.obj \\r
+  $O\HandlerOut.obj \\r
+  $O\ParseProperties.obj \\r
+\r
+\r
+7Z_OBJS = \\r
+  $O\7zCompressionMode.obj \\r
+  $O\7zDecode.obj \\r
+  $O\7zEncode.obj \\r
+  $O\7zExtract.obj \\r
+  $O\7zFolderInStream.obj \\r
+  $O\7zFolderOutStream.obj \\r
+  $O\7zHandler.obj \\r
+  $O\7zHandlerOut.obj \\r
+  $O\7zHeader.obj \\r
+  $O\7zIn.obj \\r
+  $O\7zOut.obj \\r
+  $O\7zProperties.obj \\r
+  $O\7zSpecStream.obj \\r
+  $O\7zUpdate.obj \\r
+  $O\7zRegister.obj \\r
+\r
+CAB_OBJS = \\r
+  $O\CabBlockInStream.obj \\r
+  $O\CabHandler.obj \\r
+  $O\CabHeader.obj \\r
+  $O\CabIn.obj \\r
+  $O\CabRegister.obj \\r
+\r
+CHM_OBJS = \\r
+  $O\ChmHandler.obj \\r
+  $O\ChmHeader.obj \\r
+  $O\ChmIn.obj \\r
+  $O\ChmRegister.obj \\r
+\r
+COM_OBJS = \\r
+  $O\ComHandler.obj \\r
+  $O\ComIn.obj \\r
+  $O\ComRegister.obj \\r
+\r
+HFS_OBJS = \\r
+  $O\HfsHandler.obj \\r
+  $O\HfsIn.obj \\r
+  $O\HfsRegister.obj \\r
+\r
+ISO_OBJS = \\r
+  $O\IsoHandler.obj \\r
+  $O\IsoHeader.obj \\r
+  $O\IsoIn.obj \\r
+  $O\IsoRegister.obj \\r
+\r
+NSIS_OBJS = \\r
+  $O\NsisDecode.obj \\r
+  $O\NsisHandler.obj \\r
+  $O\NsisIn.obj \\r
+  $O\NsisRegister.obj \\r
+\r
+RAR_OBJS = \\r
+  $O\RarHandler.obj \\r
+  $O\RarHeader.obj \\r
+  $O\RarIn.obj \\r
+  $O\RarItem.obj \\r
+  $O\RarVolumeInStream.obj \\r
+  $O\RarRegister.obj \\r
+\r
+TAR_OBJS = \\r
+  $O\TarHandler.obj \\r
+  $O\TarHandlerOut.obj \\r
+  $O\TarHeader.obj \\r
+  $O\TarIn.obj \\r
+  $O\TarOut.obj \\r
+  $O\TarUpdate.obj \\r
+  $O\TarRegister.obj \\r
+\r
+UDF_OBJS = \\r
+  $O\UdfHandler.obj \\r
+  $O\UdfIn.obj \\r
+  $O\UdfRegister.obj \\r
+\r
+WIM_OBJS = \\r
+  $O\WimHandler.obj \\r
+  $O\WimHandlerOut.obj \\r
+  $O\WimIn.obj \\r
+  $O\WimRegister.obj \\r
+\r
+ZIP_OBJS = \\r
+  $O\ZipAddCommon.obj \\r
+  $O\ZipHandler.obj \\r
+  $O\ZipHandlerOut.obj \\r
+  $O\ZipHeader.obj \\r
+  $O\ZipIn.obj \\r
+  $O\ZipItem.obj \\r
+  $O\ZipOut.obj \\r
+  $O\ZipUpdate.obj \\r
+  $O\ZipRegister.obj \\r
+\r
+COMPRESS_OBJS = \\r
+  $O\CodecExports.obj \\r
+  $O\ArjDecoder1.obj \\r
+  $O\ArjDecoder2.obj \\r
+  $O\Bcj2Coder.obj \\r
+  $O\Bcj2Register.obj \\r
+  $O\BcjCoder.obj \\r
+  $O\BcjRegister.obj \\r
+  $O\BitlDecoder.obj \\r
+  $O\BranchCoder.obj \\r
+  $O\BranchMisc.obj \\r
+  $O\BranchRegister.obj \\r
+  $O\ByteSwap.obj \\r
+  $O\BZip2Crc.obj \\r
+  $O\BZip2Decoder.obj \\r
+  $O\BZip2Encoder.obj \\r
+  $O\BZip2Register.obj \\r
+  $O\CopyCoder.obj \\r
+  $O\CopyRegister.obj \\r
+  $O\Deflate64Register.obj \\r
+  $O\DeflateDecoder.obj \\r
+  $O\DeflateEncoder.obj \\r
+  $O\DeflateRegister.obj \\r
+  $O\DeltaFilter.obj \\r
+  $O\ImplodeDecoder.obj \\r
+  $O\ImplodeHuffmanDecoder.obj \\r
+  $O\LzhDecoder.obj \\r
+  $O\Lzma2Decoder.obj \\r
+  $O\Lzma2Encoder.obj \\r
+  $O\Lzma2Register.obj \\r
+  $O\LzmaDecoder.obj \\r
+  $O\LzmaEncoder.obj \\r
+  $O\LzmaRegister.obj \\r
+  $O\LzOutWindow.obj \\r
+  $O\Lzx86Converter.obj \\r
+  $O\LzxDecoder.obj \\r
+  $O\PpmdDecoder.obj \\r
+  $O\PpmdEncoder.obj \\r
+  $O\PpmdRegister.obj \\r
+  $O\PpmdZip.obj \\r
+  $O\QuantumDecoder.obj \\r
+  $O\Rar1Decoder.obj \\r
+  $O\Rar2Decoder.obj \\r
+  $O\Rar3Decoder.obj \\r
+  $O\Rar3Vm.obj \\r
+  $O\RarCodecsRegister.obj \\r
+  $O\ShrinkDecoder.obj \\r
+  $O\ZlibDecoder.obj \\r
+  $O\ZlibEncoder.obj \\r
+  $O\ZDecoder.obj \\r
+\r
+CRYPTO_OBJS = \\r
+  $O\7zAes.obj \\r
+  $O\7zAesRegister.obj \\r
+  $O\HmacSha1.obj \\r
+  $O\MyAes.obj \\r
+  $O\Pbkdf2HmacSha1.obj \\r
+  $O\RandGen.obj \\r
+  $O\Rar20Crypto.obj \\r
+  $O\RarAes.obj \\r
+  $O\Sha1.obj \\r
+  $O\WzAes.obj \\r
+  $O\ZipCrypto.obj \\r
+  $O\ZipStrong.obj \\r
+\r
+\r
+C_OBJS = \\r
+  $O\7zBuf2.obj \\r
+  $O\7zStream.obj \\r
+  $O\Alloc.obj \\r
+  $O\Bra.obj \\r
+  $O\Bra86.obj \\r
+  $O\BraIA64.obj \\r
+  $O\BwtSort.obj \\r
+  $O\CpuArch.obj \\r
+  $O\Delta.obj \\r
+  $O\HuffEnc.obj \\r
+  $O\LzFind.obj \\r
+  $O\LzFindMt.obj \\r
+  $O\Lzma2Dec.obj \\r
+  $O\Lzma2Enc.obj \\r
+  $O\LzmaDec.obj \\r
+  $O\LzmaEnc.obj \\r
+  $O\MtCoder.obj \\r
+  $O\Ppmd7.obj \\r
+  $O\Ppmd7Dec.obj \\r
+  $O\Ppmd7Enc.obj \\r
+  $O\Ppmd8.obj \\r
+  $O\Ppmd8Dec.obj \\r
+  $O\Ppmd8Enc.obj \\r
+  $O\Sha256.obj \\r
+  $O\Sort.obj \\r
+  $O\Threads.obj \\r
+  $O\Xz.obj \\r
+  $O\XzCrc64.obj \\r
+  $O\XzDec.obj \\r
+  $O\XzEnc.obj \\r
+  $O\XzIn.obj \\r
+\r
+!include "../../Aes.mak"\r
+!include "../../Crc.mak"\r
+\r
+OBJS = \\r
+  $O\StdAfx.obj \\r
+  $(CONSOLE_OBJS) \\r
+  $(COMMON_OBJS) \\r
+  $(WIN_OBJS) \\r
+  $(7ZIP_COMMON_OBJS) \\r
+  $(AR_OBJS) \\r
+  $(AR_COMMON_OBJS) \\r
+  $(7Z_OBJS) \\r
+  $(CAB_OBJS) \\r
+  $(CHM_OBJS) \\r
+  $(COM_OBJS) \\r
+  $(HFS_OBJS) \\r
+  $(ISO_OBJS) \\r
+  $(NSIS_OBJS) \\r
+  $(RAR_OBJS) \\r
+  $(TAR_OBJS) \\r
+  $(UDF_OBJS) \\r
+  $(WIM_OBJS) \\r
+  $(ZIP_OBJS) \\r
+  $(COMPRESS_OBJS) \\r
+  $(CRYPTO_OBJS) \\r
+  $(C_OBJS) \\r
+  $(ASM_OBJS) \\r
+  $O\resource.res\r
+\r
+\r
+!include "../../../Build.mak"\r
+\r
+$(COMMON_OBJS): ../../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_OBJS): ../../../Windows/$(*B).cpp\r
+       $(COMPL)\r
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_OBJS): ../../Archive/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(7Z_OBJS): ../../Archive/7z/$(*B).cpp\r
+       $(COMPL)\r
+$(CAB_OBJS): ../../Archive/Cab/$(*B).cpp\r
+       $(COMPL)\r
+$(CHM_OBJS): ../../Archive/Chm/$(*B).cpp\r
+       $(COMPL)\r
+$(COM_OBJS): ../../Archive/Com/$(*B).cpp\r
+       $(COMPL)\r
+$(HFS_OBJS): ../../Archive/Hfs/$(*B).cpp\r
+       $(COMPL)\r
+$(ISO_OBJS): ../../Archive/Iso/$(*B).cpp\r
+       $(COMPL)\r
+$(NSIS_OBJS): ../../Archive/Nsis/$(*B).cpp\r
+       $(COMPL)\r
+$(RAR_OBJS): ../../Archive/Rar/$(*B).cpp\r
+       $(COMPL)\r
+$(TAR_OBJS): ../../Archive/Tar/$(*B).cpp\r
+       $(COMPL)\r
+$(UDF_OBJS): ../../Archive/Udf/$(*B).cpp\r
+       $(COMPL)\r
+$(WIM_OBJS): ../../Archive/Wim/$(*B).cpp\r
+       $(COMPL)\r
+$(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp\r
+       $(COMPL_O2)\r
+\r
+$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp\r
+       $(COMPL_O2)\r
+\r
+$(C_OBJS): ../../../../C/$(*B).c\r
+       $(COMPL_O2)\r
+\r
+!include "../../Asm.mak"\r
diff --git a/CPP/7zip/Bundles/Format7zF/resource.rc b/CPP/7zip/Bundles/Format7zF/resource.rc
new file mode 100755 (executable)
index 0000000..2920e5e
--- /dev/null
@@ -0,0 +1,37 @@
+#include "../../MyVersionInfo.rc"\r
+\r
+MY_VERSION_INFO_DLL("7z Standalone Plugin", "7za")\r
+\r
+\r
+0  ICON  "../../Archive/Icons/7z.ico"\r
+1  ICON  "../../Archive/Icons/zip.ico"\r
+2  ICON  "../../Archive/Icons/bz2.ico"\r
+3  ICON  "../../Archive/Icons/rar.ico"\r
+4  ICON  "../../Archive/Icons/arj.ico"\r
+5  ICON  "../../Archive/Icons/z.ico"\r
+6  ICON  "../../Archive/Icons/lzh.ico"\r
+7  ICON  "../../Archive/Icons/cab.ico"\r
+8  ICON  "../../Archive/Icons/iso.ico"\r
+9  ICON  "../../Archive/Icons/split.ico"\r
+10  ICON  "../../Archive/Icons/rpm.ico"\r
+11  ICON  "../../Archive/Icons/deb.ico"\r
+12  ICON  "../../Archive/Icons/cpio.ico"\r
+13  ICON  "../../Archive/Icons/tar.ico"\r
+14  ICON  "../../Archive/Icons/gz.ico"\r
+15  ICON  "../../Archive/Icons/wim.ico"\r
+16  ICON  "../../Archive/Icons/lzma.ico"\r
+17  ICON  "../../Archive/Icons/dmg.ico"\r
+18  ICON  "../../Archive/Icons/hfs.ico"\r
+19  ICON  "../../Archive/Icons/xar.ico"\r
+20  ICON  "../../Archive/Icons/vhd.ico"\r
+21  ICON  "../../Archive/Icons/fat.ico"\r
+22  ICON  "../../Archive/Icons/ntfs.ico"\r
+23  ICON  "../../Archive/Icons/xz.ico"\r
+24  ICON  "../../Archive/Icons/squashfs.ico"\r
+\r
+\r
+\r
+STRINGTABLE\r
+BEGIN\r
+  100 "7z:0 zip:1 bz2:2 bzip2:2 tbz2:2 tbz:2 rar:3 arj:4 z:5 taz:5 lzh:6 lha:6 cab:7 iso:8 001:9 rpm:10 deb:11 cpio:12 tar:13 gz:14 gzip:14 tgz:14 tpz:14 wim:15 swm:15 lzma:16 dmg:17 hfs:18 xar:19 vhd:20 fat:21 ntfs:22 xz:23 txz:23 squashfs:24"\r
+END\r
diff --git a/CPP/7zip/Bundles/Format7zR/StdAfx.cpp b/CPP/7zip/Bundles/Format7zR/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..c6d3b1f
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/Bundles/Format7zR/StdAfx.h b/CPP/7zip/Bundles/Format7zR/StdAfx.h
new file mode 100755 (executable)
index 0000000..a4e6173
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+#include "../../../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Bundles/Format7zR/makefile b/CPP/7zip/Bundles/Format7zR/makefile
new file mode 100755 (executable)
index 0000000..65d1f65
--- /dev/null
@@ -0,0 +1,149 @@
+PROG = 7zra.dll\r
+DEF_FILE = ../../Archive/Archive2.def\r
+CFLAGS = $(CFLAGS) -I ../../../ \\r
+  -D_NO_CRYPTO\r
+\r
+COMMON_OBJS = \\r
+  $O\CRC.obj \\r
+  $O\IntToString.obj \\r
+  $O\NewHandler.obj \\r
+  $O\MyString.obj \\r
+  $O\StringConvert.obj \\r
+  $O\StringToInt.obj \\r
+  $O\MyVector.obj \\r
+  $O\Wildcard.obj \\r
+\r
+WIN_OBJS = \\r
+  $O\FileDir.obj \\r
+  $O\FileFind.obj \\r
+  $O\FileIO.obj \\r
+  $O\PropVariant.obj \\r
+  $O\Synchronization.obj \\r
+  $O\System.obj \\r
+\r
+7ZIP_COMMON_OBJS = \\r
+  $O\CreateCoder.obj \\r
+  $O\CWrappers.obj \\r
+  $O\InBuffer.obj \\r
+  $O\InOutTempBuffer.obj \\r
+  $O\FilterCoder.obj \\r
+  $O\LimitedStreams.obj \\r
+  $O\LockedStream.obj \\r
+  $O\MethodId.obj \\r
+  $O\MethodProps.obj \\r
+  $O\OutBuffer.obj \\r
+  $O\ProgressUtils.obj \\r
+  $O\StreamBinder.obj \\r
+  $O\StreamObjects.obj \\r
+  $O\StreamUtils.obj \\r
+  $O\VirtThread.obj \\r
+\r
+AR_OBJS = \\r
+  $O\ArchiveExports.obj \\r
+  $O\DllExports2.obj \\r
+\r
+AR_COMMON_OBJS = \\r
+  $O\CoderMixer2.obj \\r
+  $O\CoderMixer2MT.obj \\r
+  $O\CrossThreadProgress.obj \\r
+  $O\HandlerOut.obj \\r
+  $O\InStreamWithCRC.obj \\r
+  $O\ItemNameUtils.obj \\r
+  $O\OutStreamWithCRC.obj \\r
+  $O\ParseProperties.obj \\r
+\r
+\r
+7Z_OBJS = \\r
+  $O\7zCompressionMode.obj \\r
+  $O\7zDecode.obj \\r
+  $O\7zEncode.obj \\r
+  $O\7zExtract.obj \\r
+  $O\7zFolderInStream.obj \\r
+  $O\7zFolderOutStream.obj \\r
+  $O\7zHandler.obj \\r
+  $O\7zHandlerOut.obj \\r
+  $O\7zHeader.obj \\r
+  $O\7zIn.obj \\r
+  $O\7zOut.obj \\r
+  $O\7zProperties.obj \\r
+  $O\7zSpecStream.obj \\r
+  $O\7zUpdate.obj \\r
+  $O\7zRegister.obj \\r
+\r
+\r
+COMPRESS_OBJS = \\r
+  $O\CodecExports.obj \\r
+  $O\Bcj2Coder.obj \\r
+  $O\Bcj2Register.obj \\r
+  $O\BcjCoder.obj \\r
+  $O\BcjRegister.obj \\r
+  $O\BranchCoder.obj \\r
+  $O\BranchMisc.obj \\r
+  $O\BranchRegister.obj \\r
+  $O\ByteSwap.obj \\r
+  $O\CopyCoder.obj \\r
+  $O\CopyRegister.obj \\r
+  $O\DeltaFilter.obj \\r
+  $O\Lzma2Decoder.obj \\r
+  $O\Lzma2Encoder.obj \\r
+  $O\Lzma2Register.obj \\r
+  $O\LzmaDecoder.obj \\r
+  $O\LzmaEncoder.obj \\r
+  $O\LzmaRegister.obj \\r
+\r
+C_OBJS = \\r
+  $O\Alloc.obj \\r
+  $O\Bra.obj \\r
+  $O\Bra86.obj \\r
+  $O\BraIA64.obj \\r
+  $O\CpuArch.obj \\r
+  $O\Delta.obj \\r
+  $O\LzFind.obj \\r
+  $O\LzFindMt.obj \\r
+  $O\Lzma2Dec.obj \\r
+  $O\Lzma2Enc.obj \\r
+  $O\LzmaDec.obj \\r
+  $O\LzmaEnc.obj \\r
+  $O\MtCoder.obj \\r
+  $O\Threads.obj \\r
+\r
+!include "../../Crc.mak"\r
+\r
+OBJS = \\r
+  $O\StdAfx.obj \\r
+  $(CONSOLE_OBJS) \\r
+  $(COMMON_OBJS) \\r
+  $(WIN_OBJS) \\r
+  $(7ZIP_COMMON_OBJS) \\r
+  $(AR_OBJS) \\r
+  $(AR_COMMON_OBJS) \\r
+  $(7Z_OBJS) \\r
+  $(COMPRESS_OBJS) \\r
+  $(C_OBJS) \\r
+  $(ASM_OBJS) \\r
+  $O\resource.res\r
+\r
+\r
+!include "../../../Build.mak"\r
+\r
+$(COMMON_OBJS): ../../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_OBJS): ../../../Windows/$(*B).cpp\r
+       $(COMPL)\r
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_OBJS): ../../Archive/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(7Z_OBJS): ../../Archive/7z/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp\r
+       $(COMPL_O2)\r
+\r
+$(C_OBJS): ../../../../C/$(*B).c\r
+       $(COMPL_O2)\r
+\r
+!include "../../Asm.mak"\r
diff --git a/CPP/7zip/Bundles/Format7zR/resource.rc b/CPP/7zip/Bundles/Format7zR/resource.rc
new file mode 100755 (executable)
index 0000000..b67ef0c
--- /dev/null
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"\r
+\r
+MY_VERSION_INFO_DLL("7z Standalone Plugin", "7zr")\r
+\r
+101  ICON  "../../Archive/Icons/7z.ico"\r
diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
new file mode 100755 (executable)
index 0000000..1f759b4
--- /dev/null
@@ -0,0 +1,525 @@
+// LzmaAlone.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include <stdio.h>\r
+\r
+#if (defined(_WIN32) || defined(OS2) || defined(MSDOS)) && !defined(UNDER_CE)\r
+#include <fcntl.h>\r
+#include <io.h>\r
+#define MY_SET_BINARY_MODE(file) _setmode(_fileno(file), O_BINARY)\r
+#else\r
+#define MY_SET_BINARY_MODE(file)\r
+#endif\r
+\r
+// #include "../../../Common/MyWindows.h"\r
+#include "../../../Common/MyInitGuid.h"\r
+\r
+#include "../../../../C/7zVersion.h"\r
+#include "../../../../C/Alloc.h"\r
+#include "../../../../C/Lzma86.h"\r
+\r
+#include "../../../Windows/NtCheck.h"\r
+\r
+#ifndef _7ZIP_ST\r
+#include "../../../Windows/System.h"\r
+#endif\r
+\r
+#include "../../../Common/CommandLineParser.h"\r
+#include "../../../Common/StringConvert.h"\r
+#include "../../../Common/StringToInt.h"\r
+\r
+#include "../../Common/FileStreams.h"\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "../../Compress/LzmaDecoder.h"\r
+#include "../../Compress/LzmaEncoder.h"\r
+\r
+#include "../../UI/Console/BenchCon.h"\r
+\r
+\r
+using namespace NCommandLineParser;\r
+\r
+static const char *kCantAllocate = "Can not allocate memory";\r
+static const char *kReadError = "Read error";\r
+static const char *kWriteError = "Write error";\r
+\r
+namespace NKey {\r
+enum Enum\r
+{\r
+  kHelp1 = 0,\r
+  kHelp2,\r
+  kAlgo,\r
+  kDict,\r
+  kFb,\r
+  kMc,\r
+  kLc,\r
+  kLp,\r
+  kPb,\r
+  kMatchFinder,\r
+  kMultiThread,\r
+  kEOS,\r
+  kStdIn,\r
+  kStdOut,\r
+  kFilter86\r
+};\r
+}\r
+\r
+static const CSwitchForm kSwitchForms[] =\r
+{\r
+  { L"?",  NSwitchType::kSimple, false },\r
+  { L"H",  NSwitchType::kSimple, false },\r
+  { L"A", NSwitchType::kUnLimitedPostString, false, 1 },\r
+  { L"D", NSwitchType::kUnLimitedPostString, false, 1 },\r
+  { L"FB", NSwitchType::kUnLimitedPostString, false, 1 },\r
+  { L"MC", NSwitchType::kUnLimitedPostString, false, 1 },\r
+  { L"LC", NSwitchType::kUnLimitedPostString, false, 1 },\r
+  { L"LP", NSwitchType::kUnLimitedPostString, false, 1 },\r
+  { L"PB", NSwitchType::kUnLimitedPostString, false, 1 },\r
+  { L"MF", NSwitchType::kUnLimitedPostString, false, 1 },\r
+  { L"MT", NSwitchType::kUnLimitedPostString, false, 0 },\r
+  { L"EOS", NSwitchType::kSimple, false },\r
+  { L"SI",  NSwitchType::kSimple, false },\r
+  { L"SO",  NSwitchType::kSimple, false },\r
+  { L"F86",  NSwitchType::kPostChar, false, 0, 0, L"+" }\r
+};\r
+\r
+static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]);\r
+\r
+static void PrintMessage(const char *s)\r
+{\r
+  fputs(s, stderr);\r
+}\r
+\r
+static void PrintHelp()\r
+{\r
+  PrintMessage("\nUsage:  LZMA <e|d> inputFile outputFile [<switches>...]\n"\r
+             "  e: encode file\n"\r
+             "  d: decode file\n"\r
+             "  b: Benchmark\n"\r
+    "<Switches>\n"\r
+    "  -a{N}:  set compression mode - [0, 1], default: 1 (max)\n"\r
+    "  -d{N}:  set dictionary size - [12, 30], default: 23 (8MB)\n"\r
+    "  -fb{N}: set number of fast bytes - [5, 273], default: 128\n"\r
+    "  -mc{N}: set number of cycles for match finder\n"\r
+    "  -lc{N}: set number of literal context bits - [0, 8], default: 3\n"\r
+    "  -lp{N}: set number of literal pos bits - [0, 4], default: 0\n"\r
+    "  -pb{N}: set number of pos bits - [0, 4], default: 2\n"\r
+    "  -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4\n"\r
+    "  -mt{N}: set number of CPU threads\n"\r
+    "  -eos:   write End Of Stream marker\n"\r
+    "  -si:    read data from stdin\n"\r
+    "  -so:    write data to stdout\n"\r
+    );\r
+}\r
+\r
+static void PrintHelpAndExit(const char *s)\r
+{\r
+  fprintf(stderr, "\nError: %s\n\n", s);\r
+  PrintHelp();\r
+  throw -1;\r
+}\r
+\r
+static void IncorrectCommand()\r
+{\r
+  PrintHelpAndExit("Incorrect command");\r
+}\r
+\r
+static void WriteArgumentsToStringList(int numArgs, const char *args[], UStringVector &strings)\r
+{\r
+  for (int i = 1; i < numArgs; i++)\r
+    strings.Add(MultiByteToUnicodeString(args[i]));\r
+}\r
+\r
+static bool GetNumber(const wchar_t *s, UInt32 &value)\r
+{\r
+  value = 0;\r
+  if (MyStringLen(s) == 0)\r
+    return false;\r
+  const wchar_t *end;\r
+  UInt64 res = ConvertStringToUInt64(s, &end);\r
+  if (*end != L'\0')\r
+    return false;\r
+  if (res > 0xFFFFFFFF)\r
+    return false;\r
+  value = UInt32(res);\r
+  return true;\r
+}\r
+\r
+static void ParseUInt32(const CParser &parser, int index, UInt32 &res)\r
+{\r
+  if (parser[index].ThereIs)\r
+    if (!GetNumber(parser[index].PostStrings[0], res))\r
+      IncorrectCommand();\r
+}\r
+\r
+#define NT_CHECK_FAIL_ACTION PrintMessage("Unsupported Windows version"); return 1;\r
+\r
+int main2(int numArgs, const char *args[])\r
+{\r
+  NT_CHECK\r
+\r
+  PrintMessage("\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n");\r
+\r
+  if (numArgs == 1)\r
+  {\r
+    PrintHelp();\r
+    return 0;\r
+  }\r
+\r
+  bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4);\r
+  if (unsupportedTypes)\r
+  {\r
+    PrintMessage("Unsupported base types. Edit Common/Types.h and recompile");\r
+    return 1;\r
+  }\r
+\r
+  UStringVector commandStrings;\r
+  WriteArgumentsToStringList(numArgs, args, commandStrings);\r
+  CParser parser(kNumSwitches);\r
+  try\r
+  {\r
+    parser.ParseStrings(kSwitchForms, commandStrings);\r
+  }\r
+  catch(...)\r
+  {\r
+    IncorrectCommand();\r
+  }\r
+\r
+  if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)\r
+  {\r
+    PrintHelp();\r
+    return 0;\r
+  }\r
+  const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;\r
+\r
+  int paramIndex = 0;\r
+  if (paramIndex >= nonSwitchStrings.Size())\r
+    IncorrectCommand();\r
+  const UString &command = nonSwitchStrings[paramIndex++];\r
+\r
+  bool dictDefined = false;\r
+  UInt32 dict = (UInt32)-1;\r
+  if(parser[NKey::kDict].ThereIs)\r
+  {\r
+    UInt32 dicLog;\r
+    if (!GetNumber(parser[NKey::kDict].PostStrings[0], dicLog))\r
+      IncorrectCommand();\r
+    dict = 1 << dicLog;\r
+    dictDefined = true;\r
+  }\r
+  UString mf = L"BT4";\r
+  if (parser[NKey::kMatchFinder].ThereIs)\r
+    mf = parser[NKey::kMatchFinder].PostStrings[0];\r
+\r
+  UInt32 numThreads = (UInt32)-1;\r
+\r
+  #ifndef _7ZIP_ST\r
+  if (parser[NKey::kMultiThread].ThereIs)\r
+  {\r
+    UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();\r
+    const UString &s = parser[NKey::kMultiThread].PostStrings[0];\r
+    if (s.IsEmpty())\r
+      numThreads = numCPUs;\r
+    else\r
+      if (!GetNumber(s, numThreads))\r
+        IncorrectCommand();\r
+  }\r
+  #endif\r
+\r
+  if (command.CompareNoCase(L"b") == 0)\r
+  {\r
+    const UInt32 kNumDefaultItereations = 1;\r
+    UInt32 numIterations = kNumDefaultItereations;\r
+    {\r
+      if (paramIndex < nonSwitchStrings.Size())\r
+        if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations))\r
+          numIterations = kNumDefaultItereations;\r
+    }\r
+    return LzmaBenchCon(stderr, numIterations, numThreads, dict);\r
+  }\r
+\r
+  if (numThreads == (UInt32)-1)\r
+    numThreads = 1;\r
+\r
+  bool encodeMode = false;\r
+  if (command.CompareNoCase(L"e") == 0)\r
+    encodeMode = true;\r
+  else if (command.CompareNoCase(L"d") == 0)\r
+    encodeMode = false;\r
+  else\r
+    IncorrectCommand();\r
+\r
+  bool stdInMode = parser[NKey::kStdIn].ThereIs;\r
+  bool stdOutMode = parser[NKey::kStdOut].ThereIs;\r
+\r
+  CMyComPtr<ISequentialInStream> inStream;\r
+  CInFileStream *inStreamSpec = 0;\r
+  if (stdInMode)\r
+  {\r
+    inStream = new CStdInFileStream;\r
+    MY_SET_BINARY_MODE(stdin);\r
+  }\r
+  else\r
+  {\r
+    if (paramIndex >= nonSwitchStrings.Size())\r
+      IncorrectCommand();\r
+    const UString &inputName = nonSwitchStrings[paramIndex++];\r
+    inStreamSpec = new CInFileStream;\r
+    inStream = inStreamSpec;\r
+    if (!inStreamSpec->Open(GetSystemString(inputName)))\r
+    {\r
+      fprintf(stderr, "\nError: can not open input file %s\n",\r
+          (const char *)GetOemString(inputName));\r
+      return 1;\r
+    }\r
+  }\r
+\r
+  CMyComPtr<ISequentialOutStream> outStream;\r
+  COutFileStream *outStreamSpec = NULL;\r
+  if (stdOutMode)\r
+  {\r
+    outStream = new CStdOutFileStream;\r
+    MY_SET_BINARY_MODE(stdout);\r
+  }\r
+  else\r
+  {\r
+    if (paramIndex >= nonSwitchStrings.Size())\r
+      IncorrectCommand();\r
+    const UString &outputName = nonSwitchStrings[paramIndex++];\r
+    outStreamSpec = new COutFileStream;\r
+    outStream = outStreamSpec;\r
+    if (!outStreamSpec->Create(GetSystemString(outputName), true))\r
+    {\r
+      fprintf(stderr, "\nError: can not open output file %s\n",\r
+        (const char *)GetOemString(outputName));\r
+      return 1;\r
+    }\r
+  }\r
+\r
+  if (parser[NKey::kFilter86].ThereIs)\r
+  {\r
+    // -f86 switch is for x86 filtered mode: BCJ + LZMA.\r
+    if (parser[NKey::kEOS].ThereIs || stdInMode)\r
+      throw "Can not use stdin in this mode";\r
+    UInt64 fileSize;\r
+    inStreamSpec->File.GetLength(fileSize);\r
+    if (fileSize > 0xF0000000)\r
+      throw "File is too big";\r
+    size_t inSize = (size_t)fileSize;\r
+    Byte *inBuffer = 0;\r
+    if (inSize != 0)\r
+    {\r
+      inBuffer = (Byte *)MyAlloc((size_t)inSize);\r
+      if (inBuffer == 0)\r
+        throw kCantAllocate;\r
+    }\r
+    \r
+    if (ReadStream_FAIL(inStream, inBuffer, inSize) != S_OK)\r
+      throw "Can not read";\r
+\r
+    Byte *outBuffer = 0;\r
+    size_t outSize;\r
+    if (encodeMode)\r
+    {\r
+      // we allocate 105% of original size for output buffer\r
+      outSize = (size_t)fileSize / 20 * 21 + (1 << 16);\r
+      if (outSize != 0)\r
+      {\r
+        outBuffer = (Byte *)MyAlloc((size_t)outSize);\r
+        if (outBuffer == 0)\r
+          throw kCantAllocate;\r
+      }\r
+      if (!dictDefined)\r
+        dict = 1 << 23;\r
+      int res = Lzma86_Encode(outBuffer, &outSize, inBuffer, inSize,\r
+          5, dict, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO);\r
+      if (res != 0)\r
+      {\r
+        fprintf(stderr, "\nEncoder error = %d\n", (int)res);\r
+        return 1;\r
+      }\r
+    }\r
+    else\r
+    {\r
+      UInt64 outSize64;\r
+      if (Lzma86_GetUnpackSize(inBuffer, inSize, &outSize64) != 0)\r
+        throw "data error";\r
+      outSize = (size_t)outSize64;\r
+      if (outSize != outSize64)\r
+        throw "too big";\r
+      if (outSize != 0)\r
+      {\r
+        outBuffer = (Byte *)MyAlloc(outSize);\r
+        if (outBuffer == 0)\r
+          throw kCantAllocate;\r
+      }\r
+      int res = Lzma86_Decode(outBuffer, &outSize, inBuffer, &inSize);\r
+      if (inSize != (size_t)fileSize)\r
+        throw "incorrect processed size";\r
+      if (res != 0)\r
+        throw "LzmaDecoder error";\r
+    }\r
+    if (WriteStream(outStream, outBuffer, outSize) != S_OK)\r
+      throw kWriteError;\r
+    MyFree(outBuffer);\r
+    MyFree(inBuffer);\r
+    return 0;\r
+  }\r
+\r
+\r
+  UInt64 fileSize;\r
+  if (encodeMode)\r
+  {\r
+    NCompress::NLzma::CEncoder *encoderSpec = new NCompress::NLzma::CEncoder;\r
+    CMyComPtr<ICompressCoder> encoder = encoderSpec;\r
+\r
+    if (!dictDefined)\r
+      dict = 1 << 23;\r
+\r
+    UInt32 pb = 2;\r
+    UInt32 lc = 3; // = 0; for 32-bit data\r
+    UInt32 lp = 0; // = 2; for 32-bit data\r
+    UInt32 algo = 1;\r
+    UInt32 fb = 128;\r
+    UInt32 mc = 16 + fb / 2;\r
+    bool mcDefined = false;\r
+\r
+    bool eos = parser[NKey::kEOS].ThereIs || stdInMode;\r
\r
+    ParseUInt32(parser, NKey::kAlgo, algo);\r
+    ParseUInt32(parser, NKey::kFb, fb);\r
+    ParseUInt32(parser, NKey::kLc, lc);\r
+    ParseUInt32(parser, NKey::kLp, lp);\r
+    ParseUInt32(parser, NKey::kPb, pb);\r
+\r
+    mcDefined = parser[NKey::kMc].ThereIs;\r
+    if (mcDefined)\r
+      if (!GetNumber(parser[NKey::kMc].PostStrings[0], mc))\r
+        IncorrectCommand();\r
+    \r
+    PROPID propIDs[] =\r
+    {\r
+      NCoderPropID::kDictionarySize,\r
+      NCoderPropID::kPosStateBits,\r
+      NCoderPropID::kLitContextBits,\r
+      NCoderPropID::kLitPosBits,\r
+      NCoderPropID::kAlgorithm,\r
+      NCoderPropID::kNumFastBytes,\r
+      NCoderPropID::kMatchFinder,\r
+      NCoderPropID::kEndMarker,\r
+      NCoderPropID::kNumThreads,\r
+      NCoderPropID::kMatchFinderCycles,\r
+    };\r
+    const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]);\r
+\r
+    PROPVARIANT props[kNumPropsMax];\r
+    for (int p = 0; p < 6; p++)\r
+      props[p].vt = VT_UI4;\r
+\r
+    props[0].ulVal = (UInt32)dict;\r
+    props[1].ulVal = (UInt32)pb;\r
+    props[2].ulVal = (UInt32)lc;\r
+    props[3].ulVal = (UInt32)lp;\r
+    props[4].ulVal = (UInt32)algo;\r
+    props[5].ulVal = (UInt32)fb;\r
+\r
+    props[6].vt = VT_BSTR;\r
+    props[6].bstrVal = const_cast<BSTR>((const wchar_t *)mf);\r
+\r
+    props[7].vt = VT_BOOL;\r
+    props[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE;\r
+\r
+    props[8].vt = VT_UI4;\r
+    props[8].ulVal = (UInt32)numThreads;\r
+\r
+    // it must be last in property list\r
+    props[9].vt = VT_UI4;\r
+    props[9].ulVal = (UInt32)mc;\r
+\r
+    int numProps = kNumPropsMax;\r
+    if (!mcDefined)\r
+      numProps--;\r
+\r
+    if (encoderSpec->SetCoderProperties(propIDs, props, numProps) != S_OK)\r
+      IncorrectCommand();\r
+    encoderSpec->WriteCoderProperties(outStream);\r
+\r
+    if (eos || stdInMode)\r
+      fileSize = (UInt64)(Int64)-1;\r
+    else\r
+      inStreamSpec->File.GetLength(fileSize);\r
+\r
+    for (int i = 0; i < 8; i++)\r
+    {\r
+      Byte b = Byte(fileSize >> (8 * i));\r
+      if (outStream->Write(&b, 1, 0) != S_OK)\r
+      {\r
+        PrintMessage(kWriteError);\r
+        return 1;\r
+      }\r
+    }\r
+    HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0);\r
+    if (result == E_OUTOFMEMORY)\r
+    {\r
+      PrintMessage("\nError: Can not allocate memory\n");\r
+      return 1;\r
+    }\r
+    else if (result != S_OK)\r
+    {\r
+      fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result);\r
+      return 1;\r
+    }\r
+  }\r
+  else\r
+  {\r
+    NCompress::NLzma::CDecoder *decoderSpec = new NCompress::NLzma::CDecoder;\r
+    CMyComPtr<ICompressCoder> decoder = decoderSpec;\r
+    decoderSpec->FinishStream = true;\r
+    const UInt32 kPropertiesSize = 5;\r
+    Byte header[kPropertiesSize + 8];\r
+    if (ReadStream_FALSE(inStream, header, kPropertiesSize + 8) != S_OK)\r
+    {\r
+      PrintMessage(kReadError);\r
+      return 1;\r
+    }\r
+    if (decoderSpec->SetDecoderProperties2(header, kPropertiesSize) != S_OK)\r
+    {\r
+      PrintMessage("SetDecoderProperties error");\r
+      return 1;\r
+    }\r
+    fileSize = 0;\r
+    for (int i = 0; i < 8; i++)\r
+      fileSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i);\r
+\r
+    if (decoder->Code(inStream, outStream, 0, (fileSize == (UInt64)(Int64)-1) ? 0 : &fileSize, 0) != S_OK)\r
+    {\r
+      PrintMessage("Decoder error");\r
+      return 1;\r
+    }\r
+  }\r
+  if (outStreamSpec != NULL)\r
+  {\r
+    if (outStreamSpec->Close() != S_OK)\r
+    {\r
+      PrintMessage("File closing error");\r
+      return 1;\r
+    }\r
+  }\r
+  return 0;\r
+}\r
+\r
+int MY_CDECL main(int numArgs, const char *args[])\r
+{\r
+  try { return main2(numArgs, args); }\r
+  catch(const char *s)\r
+  {\r
+    fprintf(stderr, "\nError: %s\n", s);\r
+    return 1;\r
+  }\r
+  catch(...)\r
+  {\r
+    PrintMessage("\nError\n");\r
+    return 1;\r
+  }\r
+}\r
diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp
new file mode 100755 (executable)
index 0000000..edac514
--- /dev/null
@@ -0,0 +1,457 @@
+# Microsoft Developer Studio Project File - Name="LzmaCon" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=LzmaCon - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "LzmaCon.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "LzmaCon.mak" CFG="LzmaCon - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "LzmaCon - Win32 Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "LzmaCon - Win32 Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "LzmaCon - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
+# ADD CPP /nologo /Gr /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /c\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"C:\Util\lzma.exe"\r
+\r
+!ELSEIF  "$(CFG)" == "LzmaCon - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x419 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\Util\lzma.exe" /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "LzmaCon - Win32 Release"\r
+# Name "LzmaCon - Win32 Debug"\r
+# Begin Group "Spec"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.cpp\r
+# ADD CPP /Yc"StdAfx.h"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Compress"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaDecoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaEncoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaEncoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Windows"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\System.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\System.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Thread.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CommandLineParser.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CommandLineParser.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\ComTry.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Defs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyCom.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyUnknown.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyWindows.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyWindows.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringToInt.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringToInt.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Types.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "7zip Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CWrappers.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CWrappers.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "UI Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\Bench.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\Bench.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\LoadCodecs.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\LoadCodecs.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Console"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\BenchCon.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\BenchCon.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\ConsoleClose.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\ConsoleClose.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "C"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrcOpt.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Bra.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Bra.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Bra86.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\BraIA64.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzFind.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzFind.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzFindMt.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzFindMt.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzHash.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Lzma86.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Lzma86Dec.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Lzma86Enc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzmaDec.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzmaDec.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzmaEnc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzmaEnc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Types.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=.\LzmaAlone.cpp\r
+# End Source File\r
+# End Target\r
+# End Project\r
diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw
new file mode 100755 (executable)
index 0000000..c6a6662
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "LzmaCon"=.\LzmaCon.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp b/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..c6d3b1f
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/Bundles/LzmaCon/StdAfx.h b/CPP/7zip/Bundles/LzmaCon/StdAfx.h
new file mode 100755 (executable)
index 0000000..83fdd22
--- /dev/null
@@ -0,0 +1,8 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Bundles/LzmaCon/makefile b/CPP/7zip/Bundles/LzmaCon/makefile
new file mode 100755 (executable)
index 0000000..b0b84f1
--- /dev/null
@@ -0,0 +1,87 @@
+PROG = lzma.exe\r
+MY_CONSOLE = 1\r
+CFLAGS = $(CFLAGS)\r
+\r
+LZMA_OBJS = \\r
+  $O\LzmaAlone.obj \\r
+\r
+COMPRESS_OBJS = \\r
+  $O\LzmaDecoder.obj \\r
+  $O\LzmaEncoder.obj \\r
+  $O\LzmaRegister.obj \\r
+\r
+COMMON_OBJS = \\r
+  $O\CommandLineParser.obj \\r
+  $O\CRC.obj \\r
+  $O\IntToString.obj \\r
+  $O\MyString.obj \\r
+  $O\StringConvert.obj \\r
+  $O\StringToInt.obj \\r
+  $O\MyVector.obj\r
+\r
+WIN_OBJS = \\r
+  $O\FileIO.obj \\r
+  $O\System.obj\r
+\r
+7ZIP_COMMON_OBJS = \\r
+  $O\CWrappers.obj \\r
+  $O\CreateCoder.obj \\r
+  $O\FileStreams.obj \\r
+  $O\FilterCoder.obj \\r
+  $O\OutBuffer.obj \\r
+  $O\StreamUtils.obj \\r
+\r
+UI_COMMON_OBJS = \\r
+  $O\Bench.obj \\r
+\r
+CONSOLE_OBJS = \\r
+  $O\ConsoleClose.obj \\r
+  $O\BenchCon.obj \\r
+\r
+C_OBJS = \\r
+  $O\Alloc.obj \\r
+  $O\Bra86.obj \\r
+  $O\CpuArch.obj \\r
+  $O\LzFind.obj \\r
+  $O\LzFindMt.obj \\r
+  $O\Lzma86Dec.obj \\r
+  $O\Lzma86Enc.obj \\r
+  $O\LzmaDec.obj \\r
+  $O\LzmaEnc.obj \\r
+  $O\Threads.obj \\r
+\r
+!include "../../Crc.mak"\r
+\r
+OBJS = \\r
+  $O\StdAfx.obj \\r
+  $(LZMA_OBJS) \\r
+  $(COMPRESS_OBJS) \\r
+  $(COMMON_OBJS) \\r
+  $(WIN_OBJS) \\r
+  $(7ZIP_COMMON_OBJS) \\r
+  $(UI_COMMON_OBJS) \\r
+  $(CONSOLE_OBJS) \\r
+  $(C_OBJS) \\r
+  $(ASM_OBJS) \\r
+\r
+!include "../../../Build.mak"\r
+\r
+\r
+$(LZMA_OBJS): $(*B).cpp\r
+       $(COMPL)\r
+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp\r
+       $(COMPL_O2)\r
+$(COMMON_OBJS): ../../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_OBJS): ../../../Windows/$(*B).cpp\r
+       $(COMPL)\r
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp\r
+       $(COMPL)\r
+$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp\r
+       $(COMPL)\r
+$(C_OBJS): ../../../../C/$(*B).c\r
+       $(COMPL_O2)\r
+\r
+!include "../../Asm.mak"\r
diff --git a/CPP/7zip/Bundles/LzmaCon/makefile.gcc b/CPP/7zip/Bundles/LzmaCon/makefile.gcc
new file mode 100755 (executable)
index 0000000..59a70de
--- /dev/null
@@ -0,0 +1,155 @@
+PROG = lzma\r
+CXX = g++ -O2 -Wall\r
+CXX_C = gcc -O2 -Wall\r
+LIB = -lm\r
+RM = rm -f\r
+CFLAGS = -c -D_7ZIP_ST\r
+\r
+ifdef SystemDrive\r
+IS_MINGW = 1\r
+endif\r
+\r
+ifdef IS_MINGW\r
+FILE_IO =FileIO\r
+FILE_IO_2 =Windows/$(FILE_IO)\r
+LIB2 = -luuid\r
+else\r
+FILE_IO =C_FileIO\r
+FILE_IO_2 =Common/$(FILE_IO)\r
+endif\r
+\r
+OBJS = \\r
+  LzmaAlone.o \\r
+  Bench.o \\r
+  BenchCon.o \\r
+  ConsoleClose.o \\r
+  LzmaDecoder.o \\r
+  LzmaEncoder.o \\r
+  LzmaRegister.o \\r
+  CreateCoder.o \\r
+  CWrappers.o \\r
+  FileStreams.o \\r
+  FilterCoder.o \\r
+  StreamUtils.o \\r
+  $(FILE_IO).o \\r
+  CommandLineParser.o \\r
+  CRC.o \\r
+  IntToString.o \\r
+  MyString.o \\r
+  StringConvert.o \\r
+  StringToInt.o \\r
+  MyVector.o \\r
+  7zCrc.o \\r
+  7zCrcOpt.o \\r
+  Alloc.o \\r
+  Bra86.o \\r
+  CpuArch.o \\r
+  LzFind.o \\r
+  LzmaDec.o \\r
+  LzmaEnc.o \\r
+  Lzma86Dec.o \\r
+  Lzma86Enc.o \\r
+\r
+\r
+all: $(PROG)\r
+\r
+$(PROG): $(OBJS)\r
+       $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2)\r
+\r
+LzmaAlone.o: LzmaAlone.cpp\r
+       $(CXX) $(CFLAGS) LzmaAlone.cpp\r
+\r
+Bench.o: ../../UI/Common/Bench.cpp\r
+       $(CXX) $(CFLAGS) ../../UI/Common/Bench.cpp\r
+\r
+BenchCon.o: ../../UI/Console/BenchCon.cpp\r
+       $(CXX) $(CFLAGS) ../../UI/Console/BenchCon.cpp\r
+\r
+ConsoleClose.o: ../../UI/Console/ConsoleClose.cpp\r
+       $(CXX) $(CFLAGS) ../../UI/Console/ConsoleClose.cpp\r
+\r
+LzmaDecoder.o: ../../Compress/LzmaDecoder.cpp\r
+       $(CXX) $(CFLAGS) ../../Compress/LzmaDecoder.cpp\r
+\r
+LzmaEncoder.o: ../../Compress/LzmaEncoder.cpp\r
+       $(CXX) $(CFLAGS) ../../Compress/LzmaEncoder.cpp\r
+\r
+LzmaRegister.o: ../../Compress/LzmaRegister.cpp\r
+       $(CXX) $(CFLAGS) ../../Compress/LzmaRegister.cpp\r
+\r
+CreateCoder.o: ../../Common/CreateCoder.cpp\r
+       $(CXX) $(CFLAGS) ../../Common/CreateCoder.cpp\r
+\r
+CWrappers.o: ../../Common/CWrappers.cpp\r
+       $(CXX) $(CFLAGS) ../../Common/CWrappers.cpp\r
+\r
+FileStreams.o: ../../Common/FileStreams.cpp\r
+       $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp\r
+\r
+FilterCoder.o: ../../Common/FilterCoder.cpp\r
+       $(CXX) $(CFLAGS) ../../Common/FilterCoder.cpp\r
+\r
+StreamUtils.o: ../../Common/StreamUtils.cpp\r
+       $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp\r
+\r
+$(FILE_IO).o: ../../../$(FILE_IO_2).cpp\r
+       $(CXX) $(CFLAGS) ../../../$(FILE_IO_2).cpp\r
+\r
+\r
+CommandLineParser.o: ../../../Common/CommandLineParser.cpp\r
+       $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp\r
+\r
+CRC.o: ../../../Common/CRC.cpp\r
+       $(CXX) $(CFLAGS) ../../../Common/CRC.cpp\r
+\r
+MyWindows.o: ../../../Common/MyWindows.cpp\r
+       $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp\r
+\r
+IntToString.o: ../../../Common/IntToString.cpp\r
+       $(CXX) $(CFLAGS) ../../../Common/IntToString.cpp\r
+\r
+MyString.o: ../../../Common/MyString.cpp\r
+       $(CXX) $(CFLAGS) ../../../Common/MyString.cpp\r
+\r
+StringConvert.o: ../../../Common/StringConvert.cpp\r
+       $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp\r
+\r
+StringToInt.o: ../../../Common/StringToInt.cpp\r
+       $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp\r
+\r
+MyVector.o: ../../../Common/MyVector.cpp\r
+       $(CXX) $(CFLAGS) ../../../Common/MyVector.cpp\r
+\r
+7zCrc.o: ../../../../C/7zCrc.c\r
+       $(CXX_C) $(CFLAGS) ../../../../C/7zCrc.c\r
+\r
+7zCrcOpt.o: ../../../../C/7zCrcOpt.c\r
+       $(CXX_C) $(CFLAGS) ../../../../C/7zCrcOpt.c\r
+\r
+Alloc.o: ../../../../C/Alloc.c\r
+       $(CXX_C) $(CFLAGS) ../../../../C/Alloc.c\r
+\r
+Bra86.o: ../../../../C/Bra86.c\r
+       $(CXX_C) $(CFLAGS) ../../../../C/Bra86.c\r
+\r
+CpuArch.o: ../../../../C/CpuArch.c\r
+       $(CXX_C) $(CFLAGS) ../../../../C/CpuArch.c\r
+\r
+LzFind.o: ../../../../C/LzFind.c\r
+       $(CXX_C) $(CFLAGS) ../../../../C/LzFind.c\r
+\r
+LzmaDec.o: ../../../../C/LzmaDec.c\r
+       $(CXX_C) $(CFLAGS) ../../../../C/LzmaDec.c\r
+\r
+LzmaEnc.o: ../../../../C/LzmaEnc.c\r
+       $(CXX_C) $(CFLAGS) ../../../../C/LzmaEnc.c\r
+\r
+Lzma86Dec.o: ../../../../C/Lzma86Dec.c\r
+       $(CXX_C) $(CFLAGS) ../../../../C/Lzma86Dec.c\r
+\r
+Lzma86Enc.o: ../../../../C/Lzma86Enc.c\r
+       $(CXX_C) $(CFLAGS) ../../../../C/Lzma86Enc.c\r
+\r
+clean:\r
+       -$(RM) $(PROG) $(OBJS)\r
+\r
diff --git a/CPP/7zip/Bundles/SFXCon/7z.ico b/CPP/7zip/Bundles/SFXCon/7z.ico
new file mode 100755 (executable)
index 0000000..47ffb78
Binary files /dev/null and b/CPP/7zip/Bundles/SFXCon/7z.ico differ
diff --git a/CPP/7zip/Bundles/SFXCon/Main.cpp b/CPP/7zip/Bundles/SFXCon/Main.cpp
new file mode 100755 (executable)
index 0000000..d285c48
--- /dev/null
@@ -0,0 +1,444 @@
+// Main.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/MyInitGuid.h"\r
+\r
+#include "Common/CommandLineParser.h"\r
+#include "Common/MyException.h"\r
+\r
+#ifdef _WIN32\r
+#include "Windows/DLL.h"\r
+#include "Windows/FileDir.h"\r
+#endif\r
+\r
+#include "../../UI/Common/ExitCode.h"\r
+#include "../../UI/Common/Extract.h"\r
+\r
+#include "../../UI/Console/ExtractCallbackConsole.h"\r
+#include "../../UI/Console/List.h"\r
+#include "../../UI/Console/OpenCallbackConsole.h"\r
+\r
+#include "../../MyVersion.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+using namespace NCommandLineParser;\r
+\r
+int g_CodePage = -1;\r
+extern CStdOutStream *g_StdStream;\r
+\r
+static const char *kCopyrightString =\r
+"\n7-Zip SFX " MY_VERSION_COPYRIGHT_DATE "\n";\r
+\r
+static const int kNumSwitches = 6;\r
+\r
+namespace NKey {\r
+enum Enum\r
+{\r
+  kHelp1 = 0,\r
+  kHelp2,\r
+  kDisablePercents,\r
+  kYes,\r
+  kPassword,\r
+  kOutputDir\r
+};\r
+\r
+}\r
+\r
+namespace NRecursedType {\r
+enum EEnum\r
+{\r
+  kRecursed,\r
+  kWildCardOnlyRecursed,\r
+  kNonRecursed\r
+};\r
+}\r
+/*\r
+static const char kRecursedIDChar = 'R';\r
+static const wchar_t *kRecursedPostCharSet = L"0-";\r
+\r
+namespace NRecursedPostCharIndex {\r
+  enum EEnum\r
+  {\r
+    kWildCardRecursionOnly = 0,\r
+    kNoRecursion = 1\r
+  };\r
+}\r
+\r
+static const char kFileListID = '@';\r
+static const char kImmediateNameID = '!';\r
+\r
+static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be\r
+static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be\r
+*/\r
+static const CSwitchForm kSwitchForms[kNumSwitches] =\r
+  {\r
+    { L"?",  NSwitchType::kSimple, false },\r
+    { L"H",  NSwitchType::kSimple, false },\r
+    { L"BD", NSwitchType::kSimple, false },\r
+    { L"Y",  NSwitchType::kSimple, false },\r
+    { L"P",  NSwitchType::kUnLimitedPostString, false, 1 },\r
+    { L"O",  NSwitchType::kUnLimitedPostString, false, 1 },\r
+  };\r
+\r
+static const int kNumCommandForms = 3;\r
+\r
+namespace NCommandType {\r
+enum EEnum\r
+{\r
+  kTest = 0,\r
+  // kExtract,\r
+  kFullExtract,\r
+  kList\r
+};\r
+\r
+}\r
+\r
+static const CCommandForm commandForms[kNumCommandForms] =\r
+{\r
+  { L"T", false },\r
+  // { "E", false },\r
+  { L"X", false },\r
+  { L"L", false }\r
+};\r
+\r
+static const NRecursedType::EEnum kCommandRecursedDefault[kNumCommandForms] =\r
+{\r
+  NRecursedType::kRecursed\r
+};\r
+\r
+// static const bool kTestExtractRecursedDefault = true;\r
+// static const bool kAddRecursedDefault = false;\r
+\r
+static const wchar_t *kUniversalWildcard = L"*";\r
+static const int kCommandIndex = 0;\r
+\r
+static const char *kHelpString =\r
+    "\nUsage: 7zSFX [<command>] [<switches>...]\n"\r
+    "\n"\r
+    "<Commands>\n"\r
+    "  l: List contents of archive\n"\r
+    "  t: Test integrity of archive\n"\r
+    "  x: eXtract files with full pathname (default)\n"\r
+    "<Switches>\n"\r
+    // "  -bd Disable percentage indicator\n"\r
+    "  -o{Directory}: set Output directory\n"\r
+    "  -p{Password}: set Password\n"\r
+    "  -y: assume Yes on all queries\n";\r
+\r
+\r
+// ---------------------------\r
+// exception messages\r
+\r
+static const char *kUserErrorMessage  = "Incorrect command line"; // NExitCode::kUserError\r
+// static const char *kIncorrectListFile = "Incorrect wildcard in listfile";\r
+static const char *kIncorrectWildCardInCommandLine  = "Incorrect wildcard in command line";\r
+\r
+// static const CSysString kFileIsNotArchiveMessageBefore = "File \"";\r
+// static const CSysString kFileIsNotArchiveMessageAfter = "\" is not archive";\r
+\r
+// static const char *kProcessArchiveMessage = " archive: ";\r
+\r
+static const char *kCantFindSFX = " cannot find sfx";\r
+\r
+\r
+struct CArchiveCommand\r
+{\r
+  NCommandType::EEnum CommandType;\r
+  NRecursedType::EEnum DefaultRecursedType() const;\r
+};\r
+\r
+NRecursedType::EEnum CArchiveCommand::DefaultRecursedType() const\r
+{\r
+  return kCommandRecursedDefault[CommandType];\r
+}\r
+\r
+void PrintHelp(void)\r
+{\r
+  g_StdOut << kHelpString;\r
+}\r
+\r
+static void ShowMessageAndThrowException(const char *message, NExitCode::EEnum code)\r
+{\r
+  g_StdOut << message << endl;\r
+  throw code;\r
+}\r
+\r
+static void PrintHelpAndExit() // yyy\r
+{\r
+  PrintHelp();\r
+  ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError);\r
+}\r
+\r
+bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command)\r
+{\r
+  UString commandStringUpper = commandString;\r
+  commandStringUpper.MakeUpper();\r
+  UString postString;\r
+  int commandIndex = ParseCommand(kNumCommandForms, commandForms, commandStringUpper,\r
+      postString) ;\r
+  if (commandIndex < 0)\r
+    return false;\r
+  command.CommandType = (NCommandType::EEnum)commandIndex;\r
+  return true;\r
+}\r
+\r
+// ------------------------------------------------------------------\r
+// filenames functions\r
+\r
+static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor,\r
+    const UString &name, bool include, NRecursedType::EEnum type)\r
+{\r
+  /*\r
+  if (!IsWildCardFilePathLegal(name))\r
+    return false;\r
+  */\r
+  bool isWildCard = DoesNameContainWildCard(name);\r
+  bool recursed = false;\r
+\r
+  switch (type)\r
+  {\r
+    case NRecursedType::kWildCardOnlyRecursed:\r
+      recursed = isWildCard;\r
+      break;\r
+    case NRecursedType::kRecursed:\r
+      recursed = true;\r
+      break;\r
+    case NRecursedType::kNonRecursed:\r
+      recursed = false;\r
+      break;\r
+  }\r
+  wildcardCensor.AddItem(include, name, recursed);\r
+  return true;\r
+}\r
+\r
+void AddCommandLineWildCardToCensor(NWildcard::CCensor &wildcardCensor,\r
+    const UString &name, bool include, NRecursedType::EEnum type)\r
+{\r
+  if (!AddNameToCensor(wildcardCensor, name, include, type))\r
+    ShowMessageAndThrowException(kIncorrectWildCardInCommandLine, NExitCode::kUserError);\r
+}\r
+\r
+void AddToCensorFromNonSwitchesStrings(NWildcard::CCensor &wildcardCensor,\r
+    const UStringVector & /* nonSwitchStrings */, NRecursedType::EEnum type,\r
+    bool /* thereAreSwitchIncludeWildCards */)\r
+{\r
+  AddCommandLineWildCardToCensor(wildcardCensor, kUniversalWildcard, true, type);\r
+}\r
+\r
+\r
+#ifndef _WIN32\r
+static void GetArguments(int numArgs, const char *args[], UStringVector &parts)\r
+{\r
+  parts.Clear();\r
+  for (int i = 0; i < numArgs; i++)\r
+  {\r
+    UString s = MultiByteToUnicodeString(args[i]);\r
+    parts.Add(s);\r
+  }\r
+}\r
+#endif\r
+\r
+int Main2(\r
+  #ifndef _WIN32\r
+  int numArgs, const char *args[]\r
+  #endif\r
+)\r
+{\r
+  #if defined(_WIN32) && !defined(UNDER_CE)\r
+  SetFileApisToOEM();\r
+  #endif\r
+  \r
+  g_StdOut << kCopyrightString;\r
+\r
+  UStringVector commandStrings;\r
+  #ifdef _WIN32\r
+  NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);\r
+  #else\r
+  GetArguments(numArgs, args, commandStrings);\r
+  #endif\r
+\r
+  #ifdef _WIN32\r
+  \r
+  UString arcPath;\r
+  {\r
+    UString path;\r
+    NDLL::MyGetModuleFileName(NULL, path);\r
+    int fileNamePartStartIndex;\r
+    if (!NDirectory::MyGetFullPathName(path, arcPath, fileNamePartStartIndex))\r
+    {\r
+      g_StdOut << "GetFullPathName Error";\r
+      return NExitCode::kFatalError;\r
+    }\r
+  }\r
+\r
+  #else\r
+\r
+  UString arcPath = commandStrings.Front();\r
+\r
+  #endif\r
+\r
+  commandStrings.Delete(0);\r
+\r
+  NCommandLineParser::CParser parser(kNumSwitches);\r
+  try\r
+  {\r
+    parser.ParseStrings(kSwitchForms, commandStrings);\r
+  }\r
+  catch(...)\r
+  {\r
+    PrintHelpAndExit();\r
+  }\r
+\r
+  if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)\r
+  {\r
+    PrintHelp();\r
+    return 0;\r
+  }\r
+  const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;\r
+\r
+  int numNonSwitchStrings = nonSwitchStrings.Size();\r
+\r
+  CArchiveCommand command;\r
+  if (numNonSwitchStrings == 0)\r
+    command.CommandType = NCommandType::kFullExtract;\r
+  else\r
+  {\r
+    if (numNonSwitchStrings > 1)\r
+      PrintHelpAndExit();\r
+    if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], command))\r
+      PrintHelpAndExit();\r
+  }\r
+\r
+\r
+  NRecursedType::EEnum recursedType;\r
+  recursedType = command.DefaultRecursedType();\r
+\r
+  NWildcard::CCensor wildcardCensor;\r
+  \r
+  bool thereAreSwitchIncludeWildCards;\r
+  thereAreSwitchIncludeWildCards = false;\r
+  AddToCensorFromNonSwitchesStrings(wildcardCensor, nonSwitchStrings, recursedType,\r
+      thereAreSwitchIncludeWildCards);\r
+\r
+  bool yesToAll = parser[NKey::kYes].ThereIs;\r
+\r
+  // NExtractMode::EEnum extractMode;\r
+  // bool isExtractGroupCommand = command.IsFromExtractGroup(extractMode);\r
+\r
+  bool passwordEnabled = parser[NKey::kPassword].ThereIs;\r
+\r
+  UString password;\r
+  if(passwordEnabled)\r
+    password = parser[NKey::kPassword].PostStrings[0];\r
+\r
+  if (!NFind::DoesFileExist(arcPath))\r
+    throw kCantFindSFX;\r
+  \r
+  UString outputDir;\r
+  if (parser[NKey::kOutputDir].ThereIs)\r
+  {\r
+    outputDir = parser[NKey::kOutputDir].PostStrings[0];\r
+    NName::NormalizeDirPathPrefix(outputDir);\r
+  }\r
+\r
+  {\r
+    UStringVector v1, v2;\r
+    v1.Add(arcPath);\r
+    v2.Add(arcPath);\r
+    const NWildcard::CCensorNode &wildcardCensorHead =\r
+      wildcardCensor.Pairs.Front().Head;\r
+\r
+    CCodecs *codecs = new CCodecs;\r
+    CMyComPtr<\r
+      #ifdef EXTERNAL_CODECS\r
+      ICompressCodecsInfo\r
+      #else\r
+      IUnknown\r
+      #endif\r
+      > compressCodecsInfo = codecs;\r
+    HRESULT result = codecs->Load();\r
+    if (result != S_OK)\r
+      throw CSystemException(result);\r
+\r
+    if(command.CommandType != NCommandType::kList)\r
+    {\r
+      CExtractCallbackConsole *ecs = new CExtractCallbackConsole;\r
+      CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;\r
+      ecs->OutStream = g_StdStream;\r
+\r
+      #ifndef _NO_CRYPTO\r
+      ecs->PasswordIsDefined = passwordEnabled;\r
+      ecs->Password = password;\r
+      #endif\r
+\r
+      ecs->Init();\r
+\r
+      COpenCallbackConsole openCallback;\r
+      openCallback.OutStream = g_StdStream;\r
+\r
+      #ifndef _NO_CRYPTO\r
+      openCallback.PasswordIsDefined = passwordEnabled;\r
+      openCallback.Password = password;\r
+      #endif\r
+\r
+      CExtractOptions eo;\r
+      eo.StdOutMode = false;\r
+      eo.PathMode = NExtract::NPathMode::kFullPathnames;\r
+      eo.TestMode = command.CommandType == NCommandType::kTest;\r
+      eo.OverwriteMode = yesToAll ?\r
+          NExtract::NOverwriteMode::kWithoutPrompt :\r
+          NExtract::NOverwriteMode::kAskBefore;\r
+      eo.OutputDir = outputDir;\r
+      eo.YesToAll = yesToAll;\r
+\r
+      UString errorMessage;\r
+      CDecompressStat stat;\r
+      HRESULT result = DecompressArchives(\r
+          codecs, CIntVector(),\r
+          v1, v2,\r
+          wildcardCensorHead,\r
+          eo, &openCallback, ecs, errorMessage, stat);\r
+      if (!errorMessage.IsEmpty())\r
+      {\r
+        (*g_StdStream) << endl << "Error: " << errorMessage;;\r
+        if (result == S_OK)\r
+          result = E_FAIL;\r
+      }\r
+\r
+      if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0)\r
+      {\r
+        if (ecs->NumArchiveErrors != 0)\r
+          (*g_StdStream) << endl << "Archive Errors: " << ecs->NumArchiveErrors << endl;\r
+        if (ecs->NumFileErrors != 0)\r
+          (*g_StdStream) << endl << "Sub items Errors: " << ecs->NumFileErrors << endl;\r
+        return NExitCode::kFatalError;\r
+      }\r
+      if (result != S_OK)\r
+        throw CSystemException(result);\r
+    }\r
+    else\r
+    {\r
+      UInt64 numErrors = 0;\r
+      HRESULT result = ListArchives(\r
+          codecs, CIntVector(),\r
+          false,\r
+          v1, v2,\r
+          wildcardCensorHead,\r
+          true, false,\r
+          #ifndef _NO_CRYPTO\r
+          passwordEnabled, password,\r
+          #endif\r
+          numErrors);\r
+      if (numErrors > 0)\r
+      {\r
+        g_StdOut << endl << "Errors: " << numErrors;\r
+        return NExitCode::kFatalError;\r
+      }\r
+      if (result != S_OK)\r
+        throw CSystemException(result);\r
+    }\r
+  }\r
+  return 0;\r
+}\r
diff --git a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp
new file mode 100755 (executable)
index 0000000..39d943f
--- /dev/null
@@ -0,0 +1,821 @@
+# Microsoft Developer Studio Project File - Name="SFXCon" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=SFXCon - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "SFXCon.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "SFXCon.mak" CFG="SFXCon - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "SFXCon - Win32 Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "SFXCon - Win32 Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "SFXCon - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
+# 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\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# 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\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "SFXCon - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
+# 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\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x419 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# 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\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "SFXCon - Win32 Release"\r
+# Name "SFXCon - Win32 Debug"\r
+# Begin Group "Spec"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\resource.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\resource.rc\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.cpp\r
+# ADD CPP /Yc"StdAfx.h"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Archive Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2MT.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CrossThreadProgress.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\ItemNameUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\ItemNameUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Console"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\ConsoleClose.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\ConsoleClose.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\ExtractCallbackConsole.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\List.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\List.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\MainAr.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\OpenCallbackConsole.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\UserInputUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Console\UserInputUtils.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "7z"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zDecode.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zDecode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zExtract.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zFolderOutStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHeader.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHeader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zItem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Compress"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Bcj2Coder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Bcj2Register.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BcjCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BcjRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BranchCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzma2Decoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzma2Register.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Crypto"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\7zAes.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\7zAes.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\7zAesRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\MyAes.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\MyAes.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Windows"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantConversions.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantConversions.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CommandLineParser.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CommandLineParser.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CRC.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StdInStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StdInStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StdOutStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StdOutStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\UTFConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\UTFConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "7zip Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CWrappers.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CWrappers.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilePathAutoRename.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilePathAutoRename.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\InBuffer.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\InBuffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LimitedStreams.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LimitedStreams.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LockedStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LockedStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OffsetStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OffsetStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OutBuffer.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OutBuffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamBinder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamBinder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamObjects.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamObjects.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\VirtThread.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\VirtThread.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "UI"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "UI Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveExtractCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\DefaultName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\DefaultName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ExitCode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\Extract.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\Extract.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ExtractingFilePath.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ExtractingFilePath.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ExtractMode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\LoadCodecs.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\LoadCodecs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\OpenArchive.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\OpenArchive.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\PropIDUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\PropIDUtils.h\r
+# End Source File\r
+# End Group\r
+# End Group\r
+# Begin Group "C"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrcOpt.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Aes.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Aes.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\AesOpt.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Bra.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Bra86.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Lzma2Dec.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Lzma2Dec.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzmaDec.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzmaDec.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd7.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd7.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd7Dec.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sha256.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sha256.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=.\7z.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Main.cpp\r
+# End Source File\r
+# End Target\r
+# End Project\r
diff --git a/CPP/7zip/Bundles/SFXCon/SFXCon.dsw b/CPP/7zip/Bundles/SFXCon/SFXCon.dsw
new file mode 100755 (executable)
index 0000000..bfbc2b7
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "SFXCon"=.\SFXCon.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/CPP/7zip/Bundles/SFXCon/StdAfx.cpp b/CPP/7zip/Bundles/SFXCon/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..c6d3b1f
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/Bundles/SFXCon/StdAfx.h b/CPP/7zip/Bundles/SFXCon/StdAfx.h
new file mode 100755 (executable)
index 0000000..a4e6173
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+#include "../../../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Bundles/SFXCon/makefile b/CPP/7zip/Bundles/SFXCon/makefile
new file mode 100755 (executable)
index 0000000..2d06dc7
--- /dev/null
@@ -0,0 +1,164 @@
+PROG = 7zCon.sfx\r
+MY_CONSOLE = 1\r
+CFLAGS = $(CFLAGS) -I ../../../ \\r
+  -DEXTRACT_ONLY \\r
+  -DNO_READ_FROM_CODER \\r
+  -D_SFX \\r
+\r
+SFX_CONSOLE_OBJS = \\r
+  $O\Main.obj \\r
+\r
+CONSOLE_OBJS = \\r
+  $O\ConsoleClose.obj \\r
+  $O\ExtractCallbackConsole.obj \\r
+  $O\List.obj \\r
+  $O\MainAr.obj \\r
+  $O\OpenCallbackConsole.obj \\r
+  $O\UserInputUtils.obj \\r
+\r
+COMMON_OBJS = \\r
+  $O\CommandLineParser.obj \\r
+  $O\CRC.obj \\r
+  $O\IntToString.obj \\r
+  $O\NewHandler.obj \\r
+  $O\StdInStream.obj \\r
+  $O\StdOutStream.obj \\r
+  $O\MyString.obj \\r
+  $O\StringConvert.obj \\r
+  $O\MyVector.obj \\r
+  $O\Wildcard.obj \\r
+  $O\UTFConvert.obj \\r
+\r
+WIN_OBJS = \\r
+  $O\DLL.obj \\r
+  $O\Error.obj \\r
+  $O\FileDir.obj \\r
+  $O\FileFind.obj \\r
+  $O\FileIO.obj \\r
+  $O\FileName.obj \\r
+  $O\PropVariant.obj \\r
+  $O\PropVariantConversions.obj \\r
+  $O\Synchronization.obj \\r
+\r
+7ZIP_COMMON_OBJS = \\r
+  $O\CreateCoder.obj \\r
+  $O\CWrappers.obj \\r
+  $O\FilePathAutoRename.obj \\r
+  $O\FileStreams.obj \\r
+  $O\InBuffer.obj \\r
+  $O\FilterCoder.obj \\r
+  $O\LimitedStreams.obj \\r
+  $O\LockedStream.obj \\r
+  $O\OutBuffer.obj \\r
+  $O\ProgressUtils.obj \\r
+  $O\StreamBinder.obj \\r
+  $O\StreamObjects.obj \\r
+  $O\StreamUtils.obj \\r
+  $O\VirtThread.obj \\r
+\r
+UI_COMMON_OBJS = \\r
+  $O\ArchiveExtractCallback.obj \\r
+  $O\ArchiveOpenCallback.obj \\r
+  $O\DefaultName.obj \\r
+  $O\LoadCodecs.obj \\r
+  $O\Extract.obj \\r
+  $O\ExtractingFilePath.obj \\r
+  $O\OpenArchive.obj \\r
+  $O\PropIDUtils.obj \\r
+\r
+AR_COMMON_OBJS = \\r
+  $O\CoderMixer2.obj \\r
+  $O\CoderMixer2MT.obj \\r
+  $O\CrossThreadProgress.obj \\r
+  $O\ItemNameUtils.obj \\r
+  $O\OutStreamWithCRC.obj \\r
+\r
+\r
+7Z_OBJS = \\r
+  $O\7zDecode.obj \\r
+  $O\7zExtract.obj \\r
+  $O\7zFolderOutStream.obj \\r
+  $O\7zHandler.obj \\r
+  $O\7zHeader.obj \\r
+  $O\7zIn.obj \\r
+  $O\7zRegister.obj \\r
+\r
+COMPRESS_OBJS = \\r
+  $O\BranchCoder.obj \\r
+  $O\Bcj2Coder.obj \\r
+  $O\Bcj2Register.obj \\r
+  $O\BcjCoder.obj \\r
+  $O\BcjRegister.obj \\r
+  $O\CopyCoder.obj \\r
+  $O\CopyRegister.obj \\r
+  $O\Lzma2Decoder.obj \\r
+  $O\Lzma2Register.obj \\r
+  $O\LzmaDecoder.obj \\r
+  $O\LzmaRegister.obj \\r
+  $O\PpmdDecoder.obj \\r
+  $O\PpmdRegister.obj \\r
+\r
+CRYPTO_OBJS = \\r
+  $O\7zAes.obj \\r
+  $O\7zAesRegister.obj \\r
+  $O\MyAes.obj \\r
+\r
+C_OBJS = \\r
+  $O\Alloc.obj \\r
+  $O\Bra86.obj \\r
+  $O\CpuArch.obj \\r
+  $O\Lzma2Dec.obj \\r
+  $O\LzmaDec.obj \\r
+  $O\Ppmd7.obj \\r
+  $O\Ppmd7Dec.obj \\r
+  $O\Sha256.obj \\r
+  $O\Threads.obj \\r
+\r
+!include "../../Aes.mak"\r
+!include "../../Crc.mak"\r
+\r
+OBJS = \\r
+  $O\StdAfx.obj \\r
+  $(SFX_CONSOLE_OBJS) \\r
+  $(CONSOLE_OBJS) \\r
+  $(COMMON_OBJS) \\r
+  $(WIN_OBJS) \\r
+  $(7ZIP_COMMON_OBJS) \\r
+  $(UI_COMMON_OBJS) \\r
+  $(AR_COMMON_OBJS) \\r
+  $(7Z_OBJS) \\r
+  $(COMPRESS_OBJS) \\r
+  $(CRYPTO_OBJS) \\r
+  $(C_OBJS) \\r
+  $(ASM_OBJS) \\r
+  $O\resource.res\r
+\r
+\r
+!include "../../../Build.mak"\r
+\r
+$(SFX_CONSOLE_OBJS): $(*B).cpp\r
+       $(COMPL)\r
+\r
+$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp\r
+       $(COMPL)\r
+$(COMMON_OBJS): ../../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_OBJS): ../../../Windows/$(*B).cpp\r
+       $(COMPL)\r
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(7Z_OBJS): ../../Archive/7z/$(*B).cpp\r
+       $(COMPL)\r
+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp\r
+       $(COMPL)\r
+$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp\r
+       $(COMPL)\r
+$(C_OBJS): ../../../../C/$(*B).c\r
+       $(COMPL_O2)\r
+\r
+!include "../../Asm.mak"\r
diff --git a/CPP/7zip/Bundles/SFXCon/resource.rc b/CPP/7zip/Bundles/SFXCon/resource.rc
new file mode 100755 (executable)
index 0000000..97882cd
--- /dev/null
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"\r
+\r
+MY_VERSION_INFO_APP("7z Console SFX", "7z.sfx")\r
+\r
+101 ICON "7z.ico"
\ No newline at end of file
diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp
new file mode 100755 (executable)
index 0000000..6863056
--- /dev/null
@@ -0,0 +1,236 @@
+// ExtractCallback.h\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/Wildcard.h"\r
+\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileFind.h"\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "ExtractCallback.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+\r
+static LPCWSTR kCantDeleteFile = L"Can not delete output file";\r
+static LPCWSTR kCantOpenFile = L"Can not open output file";\r
+static LPCWSTR kUnsupportedMethod = L"Unsupported Method";\r
+\r
+void CExtractCallbackImp::Init(IInArchive *archiveHandler,\r
+    const UString &directoryPath,\r
+    const UString &itemDefaultName,\r
+    const FILETIME &defaultMTime,\r
+    UInt32 defaultAttributes)\r
+{\r
+  _message.Empty();\r
+  _isCorrupt = false;\r
+  _itemDefaultName = itemDefaultName;\r
+  _defaultMTime = defaultMTime;\r
+  _defaultAttributes = defaultAttributes;\r
+  _archiveHandler = archiveHandler;\r
+  _directoryPath = directoryPath;\r
+  NName::NormalizeDirPathPrefix(_directoryPath);\r
+}\r
+\r
+HRESULT CExtractCallbackImp::Open_CheckBreak()\r
+{\r
+  #ifndef _NO_PROGRESS\r
+  return ProgressDialog.Sync.ProcessStopAndPause();\r
+  #else\r
+  return S_OK;\r
+  #endif\r
+}\r
+\r
+HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)\r
+{\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)\r
+{\r
+  #ifndef _NO_PROGRESS\r
+  return ProgressDialog.Sync.ProcessStopAndPause();\r
+  #else\r
+  return S_OK;\r
+  #endif\r
+}\r
+\r
+STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 size)\r
+{\r
+  #ifndef _NO_PROGRESS\r
+  ProgressDialog.Sync.SetProgress(size, 0);\r
+  #endif\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *completeValue)\r
+{\r
+  #ifndef _NO_PROGRESS\r
+  RINOK(ProgressDialog.Sync.ProcessStopAndPause());\r
+  if (completeValue != NULL)\r
+    ProgressDialog.Sync.SetPos(*completeValue);\r
+  #endif\r
+  return S_OK;\r
+}\r
+\r
+void CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathParts)\r
+{\r
+  UString fullPath = _directoryPath;\r
+  for(int i = 0; i < dirPathParts.Size(); i++)\r
+  {\r
+    fullPath += dirPathParts[i];\r
+    NDirectory::MyCreateDirectory(fullPath);\r
+    fullPath += NName::kDirDelimiter;\r
+  }\r
+}\r
+\r
+STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index,\r
+    ISequentialOutStream **outStream, Int32 askExtractMode)\r
+{\r
+  #ifndef _NO_PROGRESS\r
+  if (ProgressDialog.Sync.GetStopped())\r
+    return E_ABORT;\r
+  #endif\r
+  _outFileStream.Release();\r
+  NCOM::CPropVariant propVariantName;\r
+  RINOK(_archiveHandler->GetProperty(index, kpidPath, &propVariantName));\r
+  UString fullPath;\r
+  if (propVariantName.vt == VT_EMPTY)\r
+    fullPath = _itemDefaultName;\r
+  else\r
+  {\r
+    if (propVariantName.vt != VT_BSTR)\r
+      return E_FAIL;\r
+    fullPath = propVariantName.bstrVal;\r
+  }\r
+  _filePath = fullPath;\r
+\r
+  if (askExtractMode == NArchive::NExtract::NAskMode::kExtract)\r
+  {\r
+    NCOM::CPropVariant prop;\r
+    RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop));\r
+    if (prop.vt == VT_EMPTY)\r
+      _processedFileInfo.Attributes = _defaultAttributes;\r
+    else\r
+    {\r
+      if (prop.vt != VT_UI4)\r
+        return E_FAIL;\r
+      _processedFileInfo.Attributes = prop.ulVal;\r
+    }\r
+\r
+    RINOK(_archiveHandler->GetProperty(index, kpidIsDir, &prop));\r
+    _processedFileInfo.IsDir = VARIANT_BOOLToBool(prop.boolVal);\r
+\r
+    bool isAnti = false;\r
+    {\r
+      NCOM::CPropVariant propTemp;\r
+      RINOK(_archiveHandler->GetProperty(index, kpidIsAnti, &propTemp));\r
+      if (propTemp.vt == VT_BOOL)\r
+        isAnti = VARIANT_BOOLToBool(propTemp.boolVal);\r
+    }\r
+\r
+    RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop));\r
+    switch(prop.vt)\r
+    {\r
+      case VT_EMPTY: _processedFileInfo.MTime = _defaultMTime; break;\r
+      case VT_FILETIME: _processedFileInfo.MTime = prop.filetime; break;\r
+      default: return E_FAIL;\r
+    }\r
+\r
+    UStringVector pathParts;\r
+    SplitPathToParts(fullPath, pathParts);\r
+    if (pathParts.IsEmpty())\r
+      return E_FAIL;\r
+\r
+    UString processedPath = fullPath;\r
+\r
+    if (!_processedFileInfo.IsDir)\r
+      pathParts.DeleteBack();\r
+    if (!pathParts.IsEmpty())\r
+    {\r
+      if (!isAnti)\r
+        CreateComplexDirectory(pathParts);\r
+    }\r
+\r
+    UString fullProcessedPath = _directoryPath + processedPath;\r
+\r
+    if (_processedFileInfo.IsDir)\r
+    {\r
+      _diskFilePath = fullProcessedPath;\r
+\r
+      if (isAnti)\r
+        NDirectory::MyRemoveDirectory(_diskFilePath);\r
+      else\r
+        NDirectory::SetDirTime(_diskFilePath, NULL, NULL, &_processedFileInfo.MTime);\r
+      return S_OK;\r
+    }\r
+\r
+    NFind::CFileInfoW fileInfo;\r
+    if (fileInfo.Find(fullProcessedPath))\r
+    {\r
+      if (!NDirectory::DeleteFileAlways(fullProcessedPath))\r
+      {\r
+        _message = kCantDeleteFile;\r
+        return E_FAIL;\r
+      }\r
+    }\r
+\r
+    if (!isAnti)\r
+    {\r
+      _outFileStreamSpec = new COutFileStream;\r
+      CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);\r
+      if (!_outFileStreamSpec->Create(fullProcessedPath, true))\r
+      {\r
+        _message = kCantOpenFile;\r
+        return E_FAIL;\r
+      }\r
+      _outFileStream = outStreamLoc;\r
+      *outStream = outStreamLoc.Detach();\r
+    }\r
+    _diskFilePath = fullProcessedPath;\r
+  }\r
+  else\r
+  {\r
+    *outStream = NULL;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtractCallbackImp::PrepareOperation(Int32 askExtractMode)\r
+{\r
+  _extractMode = (askExtractMode == NArchive::NExtract::NAskMode::kExtract);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 resultEOperationResult)\r
+{\r
+  switch(resultEOperationResult)\r
+  {\r
+    case NArchive::NExtract::NOperationResult::kOK:\r
+      break;\r
+\r
+    default:\r
+    {\r
+      _outFileStream.Release();\r
+      switch(resultEOperationResult)\r
+      {\r
+        case NArchive::NExtract::NOperationResult::kUnSupportedMethod:\r
+          _message = kUnsupportedMethod;\r
+          break;\r
+        default:\r
+          _isCorrupt = true;\r
+      }\r
+      return E_FAIL;\r
+    }\r
+  }\r
+  if (_outFileStream != NULL)\r
+  {\r
+    _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime);\r
+    RINOK(_outFileStreamSpec->Close());\r
+  }\r
+  _outFileStream.Release();\r
+  if (_extractMode)\r
+    NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes);\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractCallback.h b/CPP/7zip/Bundles/SFXSetup/ExtractCallback.h
new file mode 100755 (executable)
index 0000000..8cac0c3
--- /dev/null
@@ -0,0 +1,88 @@
+// ExtractCallback.h\r
+\r
+#ifndef __EXTRACT_CALLBACK_H\r
+#define __EXTRACT_CALLBACK_H\r
+\r
+#include "resource.h"\r
+\r
+#include "Windows/ResourceString.h"\r
+\r
+#include "../../Archive/IArchive.h"\r
+\r
+#include "../../Common/FileStreams.h"\r
+#include "../../ICoder.h"\r
+\r
+#ifndef _NO_PROGRESS\r
+#include "../../UI/FileManager/ProgressDialog.h"\r
+#endif\r
+#include "../../UI/Common/ArchiveOpenCallback.h"\r
+\r
+class CExtractCallbackImp:\r
+  public IArchiveExtractCallback,\r
+  public IOpenCallbackUI,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  \r
+  MY_UNKNOWN_IMP\r
+\r
+  INTERFACE_IArchiveExtractCallback(;)\r
+  INTERFACE_IOpenCallbackUI(;)\r
+\r
+private:\r
+  CMyComPtr<IInArchive> _archiveHandler;\r
+  UString _directoryPath;\r
+  UString _filePath;\r
+  UString _diskFilePath;\r
+\r
+  bool _extractMode;\r
+  struct CProcessedFileInfo\r
+  {\r
+    FILETIME MTime;\r
+    bool IsDir;\r
+    UInt32 Attributes;\r
+  } _processedFileInfo;\r
+\r
+  COutFileStream *_outFileStreamSpec;\r
+  CMyComPtr<ISequentialOutStream> _outFileStream;\r
+\r
+  UString _itemDefaultName;\r
+  FILETIME _defaultMTime;\r
+  UInt32 _defaultAttributes;\r
+\r
+  void CreateComplexDirectory(const UStringVector &dirPathParts);\r
+public:\r
+  #ifndef _NO_PROGRESS\r
+  CProgressDialog ProgressDialog;\r
+  #endif\r
+\r
+  bool _isCorrupt;\r
+  UString _message;\r
+\r
+  void Init(IInArchive *archiveHandler,\r
+    const UString &directoryPath,\r
+    const UString &itemDefaultName,\r
+    const FILETIME &defaultMTime,\r
+    UInt32 defaultAttributes);\r
+\r
+  #ifndef _NO_PROGRESS\r
+  HRESULT StartProgressDialog(const UString &title, NWindows::CThread &thread)\r
+  {\r
+    ProgressDialog.Create(title, thread, 0);\r
+    {\r
+      #ifdef LANG\r
+      ProgressDialog.SetText(LangLoadString(IDS_PROGRESS_EXTRACTING, 0x02000890));\r
+      #else\r
+      ProgressDialog.SetText(NWindows::MyLoadStringW(IDS_PROGRESS_EXTRACTING));\r
+      #endif\r
+    }\r
+\r
+    ProgressDialog.Show(SW_SHOWNORMAL);\r
+    return S_OK;\r
+  }\r
+  virtual ~CExtractCallbackImp() { ProgressDialog.Destroy(); }\r
+  #endif\r
+\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp
new file mode 100755 (executable)
index 0000000..ca400b4
--- /dev/null
@@ -0,0 +1,130 @@
+// ExtractEngine.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/FileDir.h"\r
+#include "Windows/Thread.h"\r
+\r
+#include "../../UI/Common/OpenArchive.h"\r
+\r
+#include "../../UI/FileManager/FormatUtils.h"\r
+\r
+#include "ExtractCallback.h"\r
+#include "ExtractEngine.h"\r
+\r
+using namespace NWindows;\r
+\r
+static LPCWSTR kCantFindArchive = L"Can not find archive file";\r
+static LPCWSTR kCantOpenArchive = L"Can not open the file as archive";\r
+\r
+struct CThreadExtracting\r
+{\r
+  CCodecs *Codecs;\r
+  UString FileName;\r
+  UString DestFolder;\r
+\r
+  CExtractCallbackImp *ExtractCallbackSpec;\r
+  CMyComPtr<IArchiveExtractCallback> ExtractCallback;\r
+\r
+  CArchiveLink ArchiveLink;\r
+  HRESULT Result;\r
+  UString ErrorMessage;\r
+\r
+  void Process2()\r
+  {\r
+    NFile::NFind::CFileInfoW fi;\r
+    if (!fi.Find(FileName))\r
+    {\r
+      ErrorMessage = kCantFindArchive;\r
+      Result = E_FAIL;\r
+      return;\r
+    }\r
+    \r
+    Result = ArchiveLink.Open2(Codecs, CIntVector(), false, NULL, FileName, ExtractCallbackSpec);\r
+    if (Result != S_OK)\r
+    {\r
+      if (Result != S_OK)\r
+        ErrorMessage = kCantOpenArchive;\r
+      return;\r
+    }\r
+\r
+    UString dirPath = DestFolder;\r
+    NFile::NName::NormalizeDirPathPrefix(dirPath);\r
+    \r
+    if (!NFile::NDirectory::CreateComplexDirectory(dirPath))\r
+    {\r
+      ErrorMessage = MyFormatNew(IDS_CANNOT_CREATE_FOLDER,\r
+        #ifdef LANG\r
+        0x02000603,\r
+        #endif\r
+        dirPath);\r
+      Result = E_FAIL;\r
+      return;\r
+    }\r
+\r
+    ExtractCallbackSpec->Init(ArchiveLink.GetArchive(), dirPath, L"Default", fi.MTime, 0);\r
+\r
+    Result = ArchiveLink.GetArchive()->Extract(0, (UInt32)-1 , BoolToInt(false), ExtractCallback);\r
+  }\r
+\r
+  void Process()\r
+  {\r
+    try\r
+    {\r
+      #ifndef _NO_PROGRESS\r
+      CProgressCloser closer(ExtractCallbackSpec->ProgressDialog);\r
+      #endif\r
+      Process2();\r
+    }\r
+    catch(...) { Result = E_FAIL; }\r
+  }\r
+  \r
+  static THREAD_FUNC_DECL MyThreadFunction(void *param)\r
+  {\r
+    ((CThreadExtracting *)param)->Process();\r
+    return 0;\r
+  }\r
+};\r
+\r
+HRESULT ExtractArchive(CCodecs *codecs,const UString &fileName, const UString &destFolder,\r
+    bool showProgress, bool &isCorrupt, UString &errorMessage)\r
+{\r
+  isCorrupt = false;\r
+  CThreadExtracting t;\r
+\r
+  t.Codecs = codecs;\r
+  t.FileName = fileName;\r
+  t.DestFolder = destFolder;\r
+\r
+  t.ExtractCallbackSpec = new CExtractCallbackImp;\r
+  t.ExtractCallback = t.ExtractCallbackSpec;\r
+  \r
+  #ifndef _NO_PROGRESS\r
+\r
+  if (showProgress)\r
+  {\r
+    t.ExtractCallbackSpec->ProgressDialog.IconID = IDI_ICON;\r
+    NWindows::CThread thread;\r
+    RINOK(thread.Create(CThreadExtracting::MyThreadFunction, &t));\r
+    \r
+    UString title;\r
+    #ifdef LANG\r
+    title = LangLoadString(IDS_PROGRESS_EXTRACTING, 0x02000890);\r
+    #else\r
+    title = NWindows::MyLoadStringW(IDS_PROGRESS_EXTRACTING);\r
+    #endif\r
+    t.ExtractCallbackSpec->StartProgressDialog(title, thread);\r
+  }\r
+  else\r
+\r
+  #endif\r
+  {\r
+    t.Process2();\r
+  }\r
+\r
+  errorMessage = t.ErrorMessage;\r
+  if (errorMessage.IsEmpty())\r
+    errorMessage = t.ExtractCallbackSpec->_message;\r
+  isCorrupt = t.ExtractCallbackSpec->_isCorrupt;\r
+  return t.Result;\r
+}\r
diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h
new file mode 100755 (executable)
index 0000000..40170ef
--- /dev/null
@@ -0,0 +1,11 @@
+// ExtractEngine.h\r
+\r
+#ifndef __EXTRACTENGINE_H\r
+#define __EXTRACTENGINE_H\r
+\r
+#include "../../UI/Common/LoadCodecs.h"\r
+\r
+HRESULT ExtractArchive(CCodecs *codecs, const UString &fileName, const UString &destFolder,\r
+    bool showProgress, bool &isCorrupt,  UString &errorMessage);\r
+\r
+#endif\r
diff --git a/CPP/7zip/Bundles/SFXSetup/Main.cpp b/CPP/7zip/Bundles/SFXSetup/Main.cpp
new file mode 100755 (executable)
index 0000000..225e140
--- /dev/null
@@ -0,0 +1,336 @@
+// Main.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/MyInitGuid.h"\r
+\r
+#include "Common/CommandLineParser.h"\r
+#include "Common/StringConvert.h"\r
+#include "Common/TextConfig.h"\r
+\r
+#include "Windows/DLL.h"\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileFind.h"\r
+#include "Windows/FileIO.h"\r
+#include "Windows/NtCheck.h"\r
+#include "Windows/ResourceString.h"\r
+\r
+#include "../../UI/Explorer/MyMessages.h"\r
+\r
+#include "ExtractEngine.h"\r
+\r
+#include "resource.h"\r
+\r
+using namespace NWindows;\r
+\r
+HINSTANCE g_hInstance;\r
+\r
+static LPCTSTR kTempDirPrefix = TEXT("7zS");\r
+\r
+#define _SHELL_EXECUTE\r
+\r
+static bool ReadDataString(LPCWSTR fileName, LPCSTR startID,\r
+    LPCSTR endID, AString &stringResult)\r
+{\r
+  stringResult.Empty();\r
+  NFile::NIO::CInFile inFile;\r
+  if (!inFile.Open(fileName))\r
+    return false;\r
+  const int kBufferSize = (1 << 12);\r
+\r
+  Byte buffer[kBufferSize];\r
+  int signatureStartSize = MyStringLen(startID);\r
+  int signatureEndSize = MyStringLen(endID);\r
+  \r
+  UInt32 numBytesPrev = 0;\r
+  bool writeMode = false;\r
+  UInt64 posTotal = 0;\r
+  for (;;)\r
+  {\r
+    if (posTotal > (1 << 20))\r
+      return (stringResult.IsEmpty());\r
+    UInt32 numReadBytes = kBufferSize - numBytesPrev;\r
+    UInt32 processedSize;\r
+    if (!inFile.Read(buffer + numBytesPrev, numReadBytes, processedSize))\r
+      return false;\r
+    if (processedSize == 0)\r
+      return true;\r
+    UInt32 numBytesInBuffer = numBytesPrev + processedSize;\r
+    UInt32 pos = 0;\r
+    for (;;)\r
+    {\r
+      if (writeMode)\r
+      {\r
+        if (pos > numBytesInBuffer - signatureEndSize)\r
+          break;\r
+        if (memcmp(buffer + pos, endID, signatureEndSize) == 0)\r
+          return true;\r
+        char b = buffer[pos];\r
+        if (b == 0)\r
+          return false;\r
+        stringResult += b;\r
+        pos++;\r
+      }\r
+      else\r
+      {\r
+        if (pos > numBytesInBuffer - signatureStartSize)\r
+          break;\r
+        if (memcmp(buffer + pos, startID, signatureStartSize) == 0)\r
+        {\r
+          writeMode = true;\r
+          pos += signatureStartSize;\r
+        }\r
+        else\r
+          pos++;\r
+      }\r
+    }\r
+    numBytesPrev = numBytesInBuffer - pos;\r
+    posTotal += pos;\r
+    memmove(buffer, buffer + pos, numBytesPrev);\r
+  }\r
+}\r
+\r
+static char kStartID[] = ",!@Install@!UTF-8!";\r
+static char kEndID[] = ",!@InstallEnd@!";\r
+\r
+class CInstallIDInit\r
+{\r
+public:\r
+  CInstallIDInit()\r
+  {\r
+    kStartID[0] = ';';\r
+    kEndID[0] = ';';\r
+  };\r
+} g_CInstallIDInit;\r
+\r
+\r
+#ifndef UNDER_CE\r
+class CCurrentDirRestorer\r
+{\r
+  CSysString m_CurrentDirectory;\r
+public:\r
+  CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); }\r
+  ~CCurrentDirRestorer() { RestoreDirectory();}\r
+  bool RestoreDirectory() { return BOOLToBool(::SetCurrentDirectory(m_CurrentDirectory)); }\r
+};\r
+#endif\r
+\r
+#define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return 1;\r
+\r
+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,\r
+    #ifdef UNDER_CE\r
+    LPWSTR\r
+    #else\r
+    LPSTR\r
+    #endif\r
+    /* lpCmdLine */,int /* nCmdShow */)\r
+{\r
+  g_hInstance = (HINSTANCE)hInstance;\r
+\r
+  NT_CHECK\r
+\r
+  // InitCommonControls();\r
+\r
+  UString archiveName, switches;\r
+  #ifdef _SHELL_EXECUTE\r
+  UString executeFile, executeParameters;\r
+  #endif\r
+  NCommandLineParser::SplitCommandLine(GetCommandLineW(), archiveName, switches);\r
+\r
+  UString fullPath;\r
+  NDLL::MyGetModuleFileName(g_hInstance, fullPath);\r
+\r
+  switches.Trim();\r
+  bool assumeYes = false;\r
+  if (switches.Left(2).CompareNoCase(UString(L"-y")) == 0)\r
+  {\r
+    assumeYes = true;\r
+    switches = switches.Mid(2);\r
+    switches.Trim();\r
+  }\r
+\r
+  AString config;\r
+  if (!ReadDataString(fullPath, kStartID, kEndID, config))\r
+  {\r
+    if (!assumeYes)\r
+      ShowErrorMessage(L"Can't load config info");\r
+    return 1;\r
+  }\r
+\r
+  UString dirPrefix = L"." WSTRING_PATH_SEPARATOR;\r
+  UString appLaunched;\r
+  bool showProgress = true;\r
+  if (!config.IsEmpty())\r
+  {\r
+    CObjectVector<CTextConfigPair> pairs;\r
+    if (!GetTextConfig(config, pairs))\r
+    {\r
+      if (!assumeYes)\r
+        ShowErrorMessage(L"Config failed");\r
+      return 1;\r
+    }\r
+    UString friendlyName = GetTextConfigValue(pairs, L"Title");\r
+    UString installPrompt = GetTextConfigValue(pairs, L"BeginPrompt");\r
+    UString progress = GetTextConfigValue(pairs, L"Progress");\r
+    if (progress.CompareNoCase(L"no") == 0)\r
+      showProgress = false;\r
+    int index = FindTextConfigItem(pairs, L"Directory");\r
+    if (index >= 0)\r
+      dirPrefix = pairs[index].String;\r
+    if (!installPrompt.IsEmpty() && !assumeYes)\r
+    {\r
+      if (MessageBoxW(0, installPrompt, friendlyName, MB_YESNO |\r
+          MB_ICONQUESTION) != IDYES)\r
+        return 0;\r
+    }\r
+    appLaunched = GetTextConfigValue(pairs, L"RunProgram");\r
+    \r
+    #ifdef _SHELL_EXECUTE\r
+    executeFile = GetTextConfigValue(pairs, L"ExecuteFile");\r
+    executeParameters = GetTextConfigValue(pairs, L"ExecuteParameters") + switches;\r
+    #endif\r
+  }\r
+\r
+  NFile::NDirectory::CTempDirectory tempDir;\r
+  if (!tempDir.Create(kTempDirPrefix))\r
+  {\r
+    if (!assumeYes)\r
+      ShowErrorMessage(L"Can not create temp folder archive");\r
+    return 1;\r
+  }\r
+\r
+  CCodecs *codecs = new CCodecs;\r
+  CMyComPtr<IUnknown> compressCodecsInfo = codecs;\r
+  HRESULT result = codecs->Load();\r
+  if (result != S_OK)\r
+  {\r
+    ShowErrorMessage(L"Can not load codecs");\r
+    return 1;\r
+  }\r
+\r
+  UString tempDirPath = GetUnicodeString(tempDir.GetPath());\r
+  {\r
+    bool isCorrupt = false;\r
+    UString errorMessage;\r
+    HRESULT result = ExtractArchive(codecs, fullPath, tempDirPath, showProgress,\r
+      isCorrupt, errorMessage);\r
+    \r
+    if (result != S_OK)\r
+    {\r
+      if (!assumeYes)\r
+      {\r
+        if (result == S_FALSE || isCorrupt)\r
+        {\r
+          errorMessage = NWindows::MyLoadStringW(IDS_EXTRACTION_ERROR_MESSAGE);\r
+          result = E_FAIL;\r
+        }\r
+        if (result != E_ABORT && !errorMessage.IsEmpty())\r
+          ::MessageBoxW(0, errorMessage, NWindows::MyLoadStringW(IDS_EXTRACTION_ERROR_TITLE), MB_ICONERROR);\r
+      }\r
+      return 1;\r
+    }\r
+  }\r
+\r
+  #ifndef UNDER_CE\r
+  CCurrentDirRestorer currentDirRestorer;\r
+  if (!SetCurrentDirectory(tempDir.GetPath()))\r
+    return 1;\r
+  #endif\r
+  \r
+  HANDLE hProcess = 0;\r
+#ifdef _SHELL_EXECUTE\r
+  if (!executeFile.IsEmpty())\r
+  {\r
+    CSysString filePath = GetSystemString(executeFile);\r
+    SHELLEXECUTEINFO execInfo;\r
+    execInfo.cbSize = sizeof(execInfo);\r
+    execInfo.fMask = SEE_MASK_NOCLOSEPROCESS\r
+      #ifndef UNDER_CE\r
+      | SEE_MASK_FLAG_DDEWAIT\r
+      #endif\r
+      ;\r
+    execInfo.hwnd = NULL;\r
+    execInfo.lpVerb = NULL;\r
+    execInfo.lpFile = filePath;\r
+\r
+    if (!switches.IsEmpty())\r
+      executeParameters += switches;\r
+\r
+    CSysString parametersSys = GetSystemString(executeParameters);\r
+    if (parametersSys.IsEmpty())\r
+      execInfo.lpParameters = NULL;\r
+    else\r
+      execInfo.lpParameters = parametersSys;\r
+\r
+    execInfo.lpDirectory = NULL;\r
+    execInfo.nShow = SW_SHOWNORMAL;\r
+    execInfo.hProcess = 0;\r
+    /* BOOL success = */ ::ShellExecuteEx(&execInfo);\r
+    UINT32 result = (UINT32)(UINT_PTR)execInfo.hInstApp;\r
+    if(result <= 32)\r
+    {\r
+      if (!assumeYes)\r
+        ShowErrorMessage(L"Can not open file");\r
+      return 1;\r
+    }\r
+    hProcess = execInfo.hProcess;\r
+  }\r
+  else\r
+#endif\r
+  {\r
+    if (appLaunched.IsEmpty())\r
+    {\r
+      appLaunched = L"setup.exe";\r
+      if (!NFile::NFind::DoesFileExist(GetSystemString(appLaunched)))\r
+      {\r
+        if (!assumeYes)\r
+          ShowErrorMessage(L"Can not find setup.exe");\r
+        return 1;\r
+      }\r
+    }\r
+    \r
+    {\r
+      UString s2 = tempDirPath;\r
+      NFile::NName::NormalizeDirPathPrefix(s2);\r
+      appLaunched.Replace(L"%%T" WSTRING_PATH_SEPARATOR, s2);\r
+    }\r
+    \r
+    appLaunched.Replace(L"%%T", tempDirPath);\r
+\r
+    if (!switches.IsEmpty())\r
+    {\r
+      appLaunched += L' ';\r
+      appLaunched += switches;\r
+    }\r
+    STARTUPINFO startupInfo;\r
+    startupInfo.cb = sizeof(startupInfo);\r
+    startupInfo.lpReserved = 0;\r
+    startupInfo.lpDesktop = 0;\r
+    startupInfo.lpTitle = 0;\r
+    startupInfo.dwFlags = 0;\r
+    startupInfo.cbReserved2 = 0;\r
+    startupInfo.lpReserved2 = 0;\r
+    \r
+    PROCESS_INFORMATION processInformation;\r
+    \r
+    CSysString appLaunchedSys = GetSystemString(dirPrefix + appLaunched);\r
+    \r
+    BOOL createResult = CreateProcess(NULL, (LPTSTR)(LPCTSTR)appLaunchedSys,\r
+      NULL, NULL, FALSE, 0, NULL, NULL /*tempDir.GetPath() */,\r
+      &startupInfo, &processInformation);\r
+    if (createResult == 0)\r
+    {\r
+      if (!assumeYes)\r
+        ShowLastErrorMessage();\r
+      return 1;\r
+    }\r
+    ::CloseHandle(processInformation.hThread);\r
+    hProcess = processInformation.hProcess;\r
+  }\r
+  if (hProcess != 0)\r
+  {\r
+    WaitForSingleObject(hProcess, INFINITE);\r
+    ::CloseHandle(hProcess);\r
+  }\r
+  return 0;\r
+}\r
diff --git a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp
new file mode 100755 (executable)
index 0000000..dd71b26
--- /dev/null
@@ -0,0 +1,748 @@
+# Microsoft Developer Studio Project File - Name="SFXSetup" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Application" 0x0101\r
+\r
+CFG=SFXSetup - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "SFXSetup.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "SFXSetup.mak" CFG="SFXSetup - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "SFXSetup - Win32 Release" (based on "Win32 (x86) Application")\r
+!MESSAGE "SFXSetup - Win32 Debug" (based on "Win32 (x86) Application")\r
+!MESSAGE "SFXSetup - Win32 ReleaseD" (based on "Win32 (x86) Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+MTL=midl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "SFXSetup - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c\r
+# 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\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386\r
+# ADD LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7zS.sfx" /opt:NOWIN98\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "SFXSetup - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c\r
+# 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\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x419 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\UTIL\7zSfxS.exe" /pdbtype:sept\r
+\r
+!ELSEIF  "$(CFG)" == "SFXSetup - Win32 ReleaseD"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "ReleaseD"\r
+# PROP BASE Intermediate_Dir "ReleaseD"\r
+# PROP BASE Ignore_Export_Lib 0\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "ReleaseD"\r
+# PROP Intermediate_Dir "ReleaseD"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# 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\r
+# 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\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\UTIL\7zWinSR.exe"\r
+# SUBTRACT BASE LINK32 /debug /nodefaultlib\r
+# ADD LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7zSD.sfx" /opt:NOWIN98\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "SFXSetup - Win32 Release"\r
+# Name "SFXSetup - Win32 Debug"\r
+# Name "SFXSetup - Win32 ReleaseD"\r
+# Begin Group "Spec"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\resource.rc\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.cpp\r
+# ADD CPP /Yc"StdAfx.h"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Interface"\r
+\r
+# PROP Default_Filter ""\r
+# End Group\r
+# Begin Group "7z"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zDecode.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zDecode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zExtract.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zFolderOutStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHeader.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHeader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zItem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Archive Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2MT.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CrossThreadProgress.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\ItemNameUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\ItemNameUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Compress"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Bcj2Coder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Bcj2Register.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BcjCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BcjRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BranchCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzma2Decoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzma2Decoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzma2Register.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CommandLineParser.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CommandLineParser.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CRC.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\TextConfig.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\TextConfig.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\UTFConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\UTFConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Windows"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "Control"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Dialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Dialog.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\ResourceString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\ResourceString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Window.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Window.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "7z Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\InBuffer.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\InBuffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LimitedStreams.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LimitedStreams.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LockedStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LockedStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OutBuffer.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OutBuffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamBinder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamBinder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamObjects.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamObjects.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\VirtThread.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\VirtThread.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "UI"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "Explorer"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Explorer\MyMessages.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Explorer\MyMessages.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "UI Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\DefaultName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\DefaultName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ExtractMode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\LoadCodecs.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\LoadCodecs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\OpenArchive.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\OpenArchive.h\r
+# End Source File\r
+# End Group\r
+# End Group\r
+# Begin Group "File Manager"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\FormatUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\FormatUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\ProgressDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\ProgressDialog.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "C"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrcOpt.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Bra.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Bra86.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Lzma2Dec.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Lzma2Dec.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzmaDec.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzmaDec.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=.\ExtractCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ExtractCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ExtractEngine.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ExtractEngine.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Main.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\setup.ico\r
+# End Source File\r
+# End Target\r
+# End Project\r
diff --git a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw
new file mode 100755 (executable)
index 0000000..2970370
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "SFXSetup"=.\SFXSetup.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp b/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..c6d3b1f
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/Bundles/SFXSetup/StdAfx.h b/CPP/7zip/Bundles/SFXSetup/StdAfx.h
new file mode 100755 (executable)
index 0000000..8553620
--- /dev/null
@@ -0,0 +1,10 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+#include "../../../Common/NewHandler.h"\r
+#include <commctrl.h>\r
+\r
+#endif\r
diff --git a/CPP/7zip/Bundles/SFXSetup/makefile b/CPP/7zip/Bundles/SFXSetup/makefile
new file mode 100755 (executable)
index 0000000..0e3d4ec
--- /dev/null
@@ -0,0 +1,153 @@
+PROG = 7zS.sfx\r
+CFLAGS = $(CFLAGS) -I ../../../ \\r
+  -DNO_REGISTRY \\r
+  -DEXTRACT_ONLY \\r
+  -DNO_READ_FROM_CODER \\r
+  -D_SFX \\r
+  -D_NO_CRYPTO \\r
+\r
+SFX_WIN_OBJS = \\r
+  $O\Main.obj \\r
+  $O\ExtractCallback.obj \\r
+  $O\ExtractEngine.obj \\r
+\r
+COMMON_OBJS = \\r
+  $O\CommandLineParser.obj \\r
+  $O\CRC.obj \\r
+  $O\IntToString.obj \\r
+  $O\NewHandler.obj \\r
+  $O\MyString.obj \\r
+  $O\StringConvert.obj \\r
+  $O\TextConfig.obj \\r
+  $O\UTFConvert.obj \\r
+  $O\MyVector.obj \\r
+  $O\Wildcard.obj \\r
+\r
+WIN_OBJS = \\r
+  $O\DLL.obj \\r
+  $O\Error.obj \\r
+  $O\FileDir.obj \\r
+  $O\FileFind.obj \\r
+  $O\FileIO.obj \\r
+  $O\FileName.obj \\r
+  $O\PropVariant.obj \\r
+  $O\ResourceString.obj \\r
+  $O\Synchronization.obj \\r
+  $O\Window.obj \\r
+\r
+WIN_CTRL_OBJS = \\r
+  $O\Dialog.obj \\r
+\r
+7ZIP_COMMON_OBJS = \\r
+  $O\CreateCoder.obj \\r
+  $O\FileStreams.obj \\r
+  $O\InBuffer.obj \\r
+  $O\FilterCoder.obj \\r
+  $O\LimitedStreams.obj \\r
+  $O\LockedStream.obj \\r
+  $O\OutBuffer.obj \\r
+  $O\ProgressUtils.obj \\r
+  $O\StreamBinder.obj \\r
+  $O\StreamObjects.obj \\r
+  $O\StreamUtils.obj \\r
+  $O\VirtThread.obj \\r
+\r
+UI_COMMON_OBJS = \\r
+  $O\ArchiveOpenCallback.obj \\r
+  $O\DefaultName.obj \\r
+  $O\LoadCodecs.obj \\r
+  $O\OpenArchive.obj \\r
+\r
+FM_OBJS = \\r
+  $O\FormatUtils.obj \\r
+  $O\ProgressDialog.obj \\r
+\r
+AR_COMMON_OBJS = \\r
+  $O\CoderMixer2.obj \\r
+  $O\CoderMixer2MT.obj \\r
+  $O\CrossThreadProgress.obj \\r
+  $O\ItemNameUtils.obj \\r
+  $O\OutStreamWithCRC.obj \\r
+\r
+7Z_OBJS = \\r
+  $O\7zDecode.obj \\r
+  $O\7zExtract.obj \\r
+  $O\7zFolderOutStream.obj \\r
+  $O\7zHandler.obj \\r
+  $O\7zHeader.obj \\r
+  $O\7zIn.obj \\r
+  $O\7zRegister.obj \\r
+\r
+COMPRESS_OBJS = \\r
+  $O\BranchCoder.obj \\r
+  $O\Bcj2Coder.obj \\r
+  $O\Bcj2Register.obj \\r
+  $O\BcjCoder.obj \\r
+  $O\BcjRegister.obj \\r
+  $O\CopyCoder.obj \\r
+  $O\CopyRegister.obj \\r
+  $O\Lzma2Decoder.obj \\r
+  $O\Lzma2Register.obj \\r
+  $O\LzmaDecoder.obj \\r
+  $O\LzmaRegister.obj \\r
+\r
+C_OBJS = \\r
+  $O\Alloc.obj \\r
+  $O\Bra86.obj \\r
+  $O\CpuArch.obj \\r
+  $O\Lzma2Dec.obj \\r
+  $O\LzmaDec.obj \\r
+  $O\Threads.obj \\r
+\r
+!include "../../Crc.mak"\r
+\r
+OBJS = \\r
+  $O\StdAfx.obj \\r
+  $(SFX_WIN_OBJS) \\r
+  $(COMMON_OBJS) \\r
+  $(WIN_OBJS) \\r
+  $(WIN_CTRL_OBJS) \\r
+  $(7ZIP_COMMON_OBJS) \\r
+  $(UI_COMMON_OBJS) \\r
+  $(FM_OBJS)\\r
+  $(AR_COMMON_OBJS) \\r
+  $(7Z_OBJS) \\r
+  $(COMPRESS_OBJS) \\r
+  $O\MyMessages.obj \\r
+  $(C_OBJS) \\r
+  $(ASM_OBJS) \\r
+  $O\resource.res\r
+\r
+\r
+!include "../../../Build.mak"\r
+\r
+$(SFX_WIN_OBJS): $(*B).cpp\r
+       $(COMPL)\r
+\r
+$(COMMON_OBJS): ../../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_OBJS): ../../../Windows/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp\r
+       $(COMPL)\r
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp\r
+       $(COMPL)\r
+$(FM_OBJS): ../../UI/FileManager//$(*B).cpp\r
+       $(COMPL)\r
+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(7Z_OBJS): ../../Archive/7z/$(*B).cpp\r
+       $(COMPL)\r
+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$O\MyMessages.obj: ../../UI/Explorer/MyMessages.cpp\r
+       $(COMPL)\r
+\r
+$(C_OBJS): ../../../../C/$(*B).c\r
+       $(COMPL_O2)\r
+\r
+!include "../../Asm.mak"\r
diff --git a/CPP/7zip/Bundles/SFXSetup/resource.h b/CPP/7zip/Bundles/SFXSetup/resource.h
new file mode 100755 (executable)
index 0000000..b1e7082
--- /dev/null
@@ -0,0 +1,6 @@
+#define IDI_ICON                        1\r
+\r
+#define IDS_EXTRACTION_ERROR_TITLE      7\r
+#define IDS_EXTRACTION_ERROR_MESSAGE    8\r
+#define IDS_CANNOT_CREATE_FOLDER        9\r
+#define IDS_PROGRESS_EXTRACTING         69\r
diff --git a/CPP/7zip/Bundles/SFXSetup/resource.rc b/CPP/7zip/Bundles/SFXSetup/resource.rc
new file mode 100755 (executable)
index 0000000..8230224
--- /dev/null
@@ -0,0 +1,16 @@
+#include "../../MyVersionInfo.rc"\r
+#include "resource.h"\r
+\r
+MY_VERSION_INFO_APP("7z Setup SFX", "7zS.sfx")\r
+\r
+IDI_ICON  ICON "setup.ico"\r
+\r
+STRINGTABLE\r
+BEGIN\r
+  IDS_EXTRACTION_ERROR_TITLE "Extraction Failed"\r
+  IDS_EXTRACTION_ERROR_MESSAGE "File is corrupt"\r
+  IDS_CANNOT_CREATE_FOLDER "Cannot create folder '{0}'"\r
+  IDS_PROGRESS_EXTRACTING "Extracting"\r
+END\r
+\r
+#include "../../UI/FileManager/ProgressDialog.rc"\r
diff --git a/CPP/7zip/Bundles/SFXSetup/setup.ico b/CPP/7zip/Bundles/SFXSetup/setup.ico
new file mode 100755 (executable)
index 0000000..bb455be
Binary files /dev/null and b/CPP/7zip/Bundles/SFXSetup/setup.ico differ
diff --git a/CPP/7zip/Bundles/SFXWin/7z.ico b/CPP/7zip/Bundles/SFXWin/7z.ico
new file mode 100755 (executable)
index 0000000..47ffb78
Binary files /dev/null and b/CPP/7zip/Bundles/SFXWin/7z.ico differ
diff --git a/CPP/7zip/Bundles/SFXWin/Main.cpp b/CPP/7zip/Bundles/SFXWin/Main.cpp
new file mode 100755 (executable)
index 0000000..dc74a81
--- /dev/null
@@ -0,0 +1,173 @@
+// Main.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/MyInitGuid.h"\r
+\r
+#include "Common/CommandLineParser.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/DLL.h"\r
+#include "Windows/Error.h"\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileName.h"\r
+#include "Windows/NtCheck.h"\r
+#include "Windows/ResourceString.h"\r
+\r
+#include "../../ICoder.h"\r
+#include "../../IPassword.h"\r
+#include "../../Archive/IArchive.h"\r
+#include "../../UI/Common/Extract.h"\r
+#include "../../UI/Common/ExitCode.h"\r
+#include "../../UI/Explorer/MyMessages.h"\r
+#include "../../UI/GUI/ExtractGUI.h"\r
+#include "../../UI/GUI/ExtractRes.h"\r
+\r
+HINSTANCE g_hInstance;\r
+\r
+#ifdef UNDER_CE\r
+bool g_LVN_ITEMACTIVATE_Support = true;\r
+#endif\r
+\r
+static const wchar_t *kUnknownExceptionMessage = L"ERROR: Unknown Error!";\r
+\r
+void ErrorMessageForHRESULT(HRESULT res)\r
+{\r
+  ShowErrorMessage(HResultToMessage(res));\r
+}\r
+\r
+int APIENTRY WinMain2()\r
+{\r
+  UString password;\r
+  bool assumeYes = false;\r
+  bool outputFolderDefined = false;\r
+  UString outputFolder;\r
+  UStringVector commandStrings;\r
+  NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);\r
+\r
+  #ifndef UNDER_CE\r
+  if (commandStrings.Size() > 0)\r
+    commandStrings.Delete(0);\r
+  #endif\r
+\r
+  for (int i = 0; i < commandStrings.Size(); i++)\r
+  {\r
+    const UString &s = commandStrings[i];\r
+    if (s.CompareNoCase(L"-y") == 0)\r
+      assumeYes = true;\r
+    else if (s.Left(2).CompareNoCase(L"-o") == 0)\r
+    {\r
+      outputFolder = s.Mid(2);\r
+      NWindows::NFile::NName::NormalizeDirPathPrefix(outputFolder);\r
+      outputFolderDefined = !outputFolder.IsEmpty();\r
+    }\r
+    else if (s.Left(2).CompareNoCase(L"-p") == 0)\r
+    {\r
+      password = s.Mid(2);\r
+    }\r
+  }\r
+\r
+  UString path;\r
+  NWindows::NDLL::MyGetModuleFileName(g_hInstance, path);\r
+\r
+  UString fullPath;\r
+  int fileNamePartStartIndex;\r
+  if (!NWindows::NFile::NDirectory::MyGetFullPathName(path, fullPath, fileNamePartStartIndex))\r
+  {\r
+    ShowErrorMessage(L"Error 1329484");\r
+    return 1;\r
+  }\r
+\r
+  CCodecs *codecs = new CCodecs;\r
+  CMyComPtr<IUnknown> compressCodecsInfo = codecs;\r
+  HRESULT result = codecs->Load();\r
+  if (result != S_OK)\r
+  {\r
+    ErrorMessageForHRESULT(result);\r
+    return 1;\r
+  }\r
+\r
+  // COpenCallbackGUI openCallback;\r
+\r
+  // openCallback.PasswordIsDefined = !password.IsEmpty();\r
+  // openCallback.Password = password;\r
+\r
+  CExtractCallbackImp *ecs = new CExtractCallbackImp;\r
+  CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;\r
+  ecs->Init();\r
+\r
+  #ifndef _NO_CRYPTO\r
+  ecs->PasswordIsDefined = !password.IsEmpty();\r
+  ecs->Password = password;\r
+  #endif\r
+\r
+  CExtractOptions eo;\r
+  eo.OutputDir = outputFolderDefined ? outputFolder :\r
+      fullPath.Left(fileNamePartStartIndex);\r
+  eo.YesToAll = assumeYes;\r
+  eo.OverwriteMode = assumeYes ?\r
+      NExtract::NOverwriteMode::kWithoutPrompt :\r
+      NExtract::NOverwriteMode::kAskBefore;\r
+  eo.PathMode = NExtract::NPathMode::kFullPathnames;\r
+  eo.TestMode = false;\r
+  \r
+  UStringVector v1, v2;\r
+  v1.Add(fullPath);\r
+  v2.Add(fullPath);\r
+  NWildcard::CCensorNode wildcardCensor;\r
+  wildcardCensor.AddItem(true, L"*", true, true, true);\r
+\r
+  bool messageWasDisplayed = false;\r
+  result = ExtractGUI(codecs, CIntVector(), v1, v2,\r
+      wildcardCensor, eo, (assumeYes ? false: true), messageWasDisplayed, ecs);\r
+\r
+  if (result == S_OK)\r
+  {\r
+    if (!ecs->IsOK())\r
+      return NExitCode::kFatalError;\r
+    return 0;\r
+  }\r
+  if (result == E_ABORT)\r
+    return NExitCode::kUserBreak;\r
+  if (!messageWasDisplayed)\r
+  {\r
+    if (result == S_FALSE)\r
+      ShowErrorMessage(L"Error in archive");\r
+    else\r
+      ErrorMessageForHRESULT(result);\r
+  }\r
+  if (result == E_OUTOFMEMORY)\r
+    return NExitCode::kMemoryError;\r
+  return NExitCode::kFatalError;\r
+}\r
+\r
+#define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return NExitCode::kFatalError;\r
+\r
+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,\r
+  #ifdef UNDER_CE\r
+  LPWSTR\r
+  #else\r
+  LPSTR\r
+  #endif\r
+  /* lpCmdLine */, int /* nCmdShow */)\r
+{\r
+  g_hInstance = (HINSTANCE)hInstance;\r
+\r
+  NT_CHECK\r
+\r
+  try\r
+  {\r
+    return WinMain2();\r
+  }\r
+  catch(const CNewException &)\r
+  {\r
+    ErrorMessageForHRESULT(E_OUTOFMEMORY);\r
+    return NExitCode::kMemoryError;\r
+  }\r
+  catch(...)\r
+  {\r
+    ShowErrorMessage(kUnknownExceptionMessage);\r
+    return NExitCode::kFatalError;\r
+  }\r
+}\r
+\r
diff --git a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
new file mode 100755 (executable)
index 0000000..0859483
--- /dev/null
@@ -0,0 +1,885 @@
+# Microsoft Developer Studio Project File - Name="SFXWin" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Application" 0x0101\r
+\r
+CFG=SFXWin - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "SFXWin.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "SFXWin.mak" CFG="SFXWin - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "SFXWin - Win32 Release" (based on "Win32 (x86) Application")\r
+!MESSAGE "SFXWin - Win32 Debug" (based on "Win32 (x86) Application")\r
+!MESSAGE "SFXWin - Win32 ReleaseD" (based on "Win32 (x86) Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+MTL=midl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "SFXWin - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c\r
+# 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\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7z.sfx" /opt:NOWIN98\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "SFXWin - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c\r
+# 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\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x419 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# 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\r
+\r
+!ELSEIF  "$(CFG)" == "SFXWin - Win32 ReleaseD"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "SFXWin___Win32_ReleaseD"\r
+# PROP BASE Intermediate_Dir "SFXWin___Win32_ReleaseD"\r
+# PROP BASE Ignore_Export_Lib 0\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "SFXWin___Win32_ReleaseD"\r
+# PROP Intermediate_Dir "SFXWin___Win32_ReleaseD"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# 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\r
+# 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\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7z.sfx" /opt:NOWIN98\r
+# SUBTRACT BASE LINK32 /pdb:none\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7zD.sfx" /opt:NOWIN98\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "SFXWin - Win32 Release"\r
+# Name "SFXWin - Win32 Debug"\r
+# Name "SFXWin - Win32 ReleaseD"\r
+# Begin Group "Spec"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.cpp\r
+# ADD CPP /Yc"StdAfx.h"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "7z"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zDecode.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zDecode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zExtract.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zFolderOutStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHeader.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zHeader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zIn.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zIn.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\7z\7zRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Archive Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CoderMixer2MT.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\CrossThreadProgress.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\ItemNameUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\ItemNameUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Compress"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Bcj2Coder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Bcj2Register.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BcjCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BcjRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\BranchCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzma2Decoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\Lzma2Register.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\LzmaRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdDecoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\PpmdRegister.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Crypto"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\7zAes.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\7zAes.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\7zAesRegister.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\MyAes.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Crypto\MyAes.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Dialogs"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\MessagesDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\MessagesDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\OverwriteDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\OverwriteDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PasswordDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\PasswordDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\ProgressDialog2.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\ProgressDialog2.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "7zip Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CWrappers.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CWrappers.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilePathAutoRename.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilePathAutoRename.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\InBuffer.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\InBuffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LimitedStreams.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LimitedStreams.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LockedStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\LockedStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OutBuffer.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\OutBuffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamBinder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamBinder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamObjects.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamObjects.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\VirtThread.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\VirtThread.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "File Manager"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\ExtractCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\ExtractCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\FormatUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\FileManager\FormatUtils.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Windows"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "Control"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Dialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Dialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ListView.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ListView.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantConversions.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantConversions.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\ResourceString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\ResourceString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Shell.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Shell.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Window.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Window.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CommandLineParser.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CommandLineParser.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CRC.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "UI"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "UI Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveExtractCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\DefaultName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\DefaultName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\Extract.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\Extract.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ExtractingFilePath.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\ExtractingFilePath.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\LoadCodecs.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\LoadCodecs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\OpenArchive.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Common\OpenArchive.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "GUI"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\GUI\ExtractDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\GUI\ExtractDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\GUI\ExtractGUI.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\GUI\ExtractGUI.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Explorer"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Explorer\MyMessages.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\UI\Explorer\MyMessages.h\r
+# End Source File\r
+# End Group\r
+# End Group\r
+# Begin Group "C"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrcOpt.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Aes.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Aes.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\AesOpt.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Bra.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Bra86.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Lzma2Dec.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Lzma2Dec.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzmaDec.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\LzmaDec.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd7.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd7.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Ppmd7Dec.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sha256.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=.\7z.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7z1.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Main.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\resource.rc\r
+# End Source File\r
+# End Target\r
+# End Project\r
diff --git a/CPP/7zip/Bundles/SFXWin/SFXWin.dsw b/CPP/7zip/Bundles/SFXWin/SFXWin.dsw
new file mode 100755 (executable)
index 0000000..6695803
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "SFXWin"=.\SFXWin.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/CPP/7zip/Bundles/SFXWin/StdAfx.cpp b/CPP/7zip/Bundles/SFXWin/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..c6d3b1f
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/Bundles/SFXWin/StdAfx.h b/CPP/7zip/Bundles/SFXWin/StdAfx.h
new file mode 100755 (executable)
index 0000000..0ae3720
--- /dev/null
@@ -0,0 +1,12 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+#include "../../../Common/NewHandler.h"\r
+\r
+#include <commctrl.h>\r
+#include <ShlObj.h>\r
+\r
+#endif\r
diff --git a/CPP/7zip/Bundles/SFXWin/makefile b/CPP/7zip/Bundles/SFXWin/makefile
new file mode 100755 (executable)
index 0000000..86c1384
--- /dev/null
@@ -0,0 +1,191 @@
+PROG = 7z.sfx\r
+CFLAGS = $(CFLAGS) -I ../../../ \\r
+  -DNO_REGISTRY \\r
+  -DEXTRACT_ONLY \\r
+  -DNO_READ_FROM_CODER \\r
+  -D_SFX \\r
+\r
+!IFDEF UNDER_CE\r
+LIBS = $(LIBS) ceshell.lib Commctrl.lib\r
+!ELSE\r
+LIBS = $(LIBS) comctl32.lib comdlg32.lib\r
+!ENDIF\r
+\r
+SFX_WIN_OBJS = \\r
+  $O\Main.obj \\r
+\r
+GUI_OBJS = \\r
+  $O\ExtractDialog.obj \\r
+  $O\ExtractGUI.obj \\r
+\r
+COMMON_OBJS = \\r
+  $O\CRC.obj \\r
+  $O\CommandLineParser.obj \\r
+  $O\IntToString.obj \\r
+  $O\NewHandler.obj \\r
+  $O\MyString.obj \\r
+  $O\StringConvert.obj \\r
+  $O\MyVector.obj \\r
+  $O\Wildcard.obj \\r
+\r
+WIN_OBJS = \\r
+  $O\DLL.obj \\r
+  $O\Error.obj \\r
+  $O\FileDir.obj \\r
+  $O\FileFind.obj \\r
+  $O\FileIO.obj \\r
+  $O\FileName.obj \\r
+  $O\PropVariant.obj \\r
+  $O\PropVariantConversions.obj \\r
+  $O\ResourceString.obj \\r
+  $O\Shell.obj \\r
+  $O\Synchronization.obj \\r
+  $O\Window.obj \\r
+\r
+WIN_CTRL_OBJS = \\r
+  $O\Dialog.obj \\r
+  $O\ListView.obj \\r
+\r
+7ZIP_COMMON_OBJS = \\r
+  $O\CreateCoder.obj \\r
+  $O\CWrappers.obj \\r
+  $O\FilePathAutoRename.obj \\r
+  $O\FileStreams.obj \\r
+  $O\InBuffer.obj \\r
+  $O\FilterCoder.obj \\r
+  $O\LimitedStreams.obj \\r
+  $O\LockedStream.obj \\r
+  $O\OutBuffer.obj \\r
+  $O\ProgressUtils.obj \\r
+  $O\StreamBinder.obj \\r
+  $O\StreamObjects.obj \\r
+  $O\StreamUtils.obj \\r
+  $O\VirtThread.obj \\r
+\r
+UI_COMMON_OBJS = \\r
+  $O\ArchiveExtractCallback.obj \\r
+  $O\ArchiveOpenCallback.obj \\r
+  $O\DefaultName.obj \\r
+  $O\Extract.obj \\r
+  $O\ExtractingFilePath.obj \\r
+  $O\LoadCodecs.obj \\r
+  $O\OpenArchive.obj \\r
+\r
+FM_OBJS = \\r
+  $O\ExtractCallback.obj \\r
+  $O\FormatUtils.obj \\r
+  $O\OverwriteDialog.obj \\r
+  $O\PasswordDialog.obj \\r
+  $O\ProgressDialog2.obj \\r
+\r
+!IFDEF UNDER_CE\r
+FM_OBJS = $(FM_OBJS) \\r
+  $O\BrowseDialog.obj \\r
+  $O\SysIconUtils.obj \\r
+!ENDIF\r
+\r
+AR_COMMON_OBJS = \\r
+  $O\CoderMixer2.obj \\r
+  $O\CoderMixer2MT.obj \\r
+  $O\CrossThreadProgress.obj \\r
+  $O\ItemNameUtils.obj \\r
+  $O\OutStreamWithCRC.obj \\r
+\r
+7Z_OBJS = \\r
+  $O\7zDecode.obj \\r
+  $O\7zExtract.obj \\r
+  $O\7zFolderOutStream.obj \\r
+  $O\7zHandler.obj \\r
+  $O\7zHeader.obj \\r
+  $O\7zIn.obj \\r
+  $O\7zRegister.obj \\r
+\r
+COMPRESS_OBJS = \\r
+  $O\BranchCoder.obj \\r
+  $O\Bcj2Coder.obj \\r
+  $O\Bcj2Register.obj \\r
+  $O\BcjCoder.obj \\r
+  $O\BcjRegister.obj \\r
+  $O\CopyCoder.obj \\r
+  $O\CopyRegister.obj \\r
+  $O\Lzma2Decoder.obj \\r
+  $O\Lzma2Register.obj \\r
+  $O\LzmaDecoder.obj \\r
+  $O\LzmaRegister.obj \\r
+  $O\PpmdDecoder.obj \\r
+  $O\PpmdRegister.obj \\r
+\r
+CRYPTO_OBJS = \\r
+  $O\7zAes.obj \\r
+  $O\7zAesRegister.obj \\r
+  $O\MyAes.obj \\r
+  \r
+C_OBJS = \\r
+  $O\Alloc.obj \\r
+  $O\Bra86.obj \\r
+  $O\CpuArch.obj \\r
+  $O\Lzma2Dec.obj \\r
+  $O\LzmaDec.obj \\r
+  $O\Ppmd7.obj \\r
+  $O\Ppmd7Dec.obj \\r
+  $O\Sha256.obj \\r
+  $O\Threads.obj \\r
+\r
+!include "../../Aes.mak"\r
+!include "../../Crc.mak"\r
+\r
+OBJS = \\r
+  $O\StdAfx.obj \\r
+  $(SFX_WIN_OBJS) \\r
+  $(GUI_OBJS) \\r
+  $(COMMON_OBJS) \\r
+  $(WIN_OBJS) \\r
+  $(WIN_CTRL_OBJS) \\r
+  $(7ZIP_COMMON_OBJS) \\r
+  $(UI_COMMON_OBJS) \\r
+  $(FM_OBJS)\\r
+  $(AR_COMMON_OBJS) \\r
+  $(7Z_OBJS) \\r
+  $(COMPRESS_OBJS) \\r
+  $(CRYPTO_OBJS) \\r
+  $O\MyMessages.obj \\r
+  $(C_OBJS) \\r
+  $(ASM_OBJS) \\r
+  $O\resource.res\r
+\r
+\r
+!include "../../../Build.mak"\r
+\r
+$(SFX_WIN_OBJS): $(*B).cpp\r
+       $(COMPL)\r
+\r
+$(GUI_OBJS): ../../UI/GUI/$(*B).cpp\r
+       $(COMPL)\r
+$(COMMON_OBJS): ../../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_OBJS): ../../../Windows/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp\r
+       $(COMPL)\r
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp\r
+       $(COMPL)\r
+$(FM_OBJS): ../../UI/FileManager/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$(7Z_OBJS): ../../Archive/7z/$(*B).cpp\r
+       $(COMPL)\r
+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp\r
+       $(COMPL)\r
+$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$O\MyMessages.obj: ../../UI/Explorer/MyMessages.cpp\r
+       $(COMPL)\r
+$(C_OBJS): ../../../../C/$(*B).c\r
+       $(COMPL_O2)\r
+\r
+!include "../../Asm.mak"\r
diff --git a/CPP/7zip/Bundles/SFXWin/resource.h b/CPP/7zip/Bundles/SFXWin/resource.h
new file mode 100755 (executable)
index 0000000..1c36de1
--- /dev/null
@@ -0,0 +1 @@
+#define IDI_ICON                        1\r
diff --git a/CPP/7zip/Bundles/SFXWin/resource.rc b/CPP/7zip/Bundles/SFXWin/resource.rc
new file mode 100755 (executable)
index 0000000..fb8e783
--- /dev/null
@@ -0,0 +1,43 @@
+#include "../../MyVersionInfo.rc"\r
+#include "../../GuiCommon.rc"\r
+#include "../../UI/GUI/ExtractDialogRes.h"\r
+#include "resource.h"\r
+\r
+MY_VERSION_INFO_APP("7z SFX", "7z.sfx")\r
+\r
+#define xc 240\r
+#define yc 64\r
+\r
+IDI_ICON ICON "7z.ico"\r
+\r
+IDD_DIALOG_EXTRACT  MY_DIALOG\r
+CAPTION "7-Zip self-extracting archive"\r
+BEGIN\r
+  LTEXT          "E&xtract to:", IDC_STATIC_EXTRACT_EXTRACT_TO, m, m, xc, 8\r
+  EDITTEXT       IDC_EXTRACT_COMBO_PATH, m, 21, xc - bxsDots - 12, 14, ES_AUTOHSCROLL\r
+  PUSHBUTTON     "...", IDC_EXTRACT_BUTTON_SET_PATH, xs - m - bxsDots, 20, bxsDots, bys, WS_GROUP\r
+  DEFPUSHBUTTON  "Extract", IDOK, bx2, by, bxs, bys, WS_GROUP\r
+  PUSHBUTTON     "Cancel", IDCANCEL, bx1, by, bxs, bys\r
+END\r
+\r
+#ifdef UNDER_CE\r
+\r
+#undef xc\r
+#define xc 144\r
+\r
+IDD_DIALOG_EXTRACT_2  MY_DIALOG\r
+CAPTION "7-Zip self-extracting archive"\r
+BEGIN\r
+  LTEXT          "E&xtract to:", IDC_STATIC_EXTRACT_EXTRACT_TO, m, m, xc - bxsDots - 12, 8\r
+  EDITTEXT       IDC_EXTRACT_COMBO_PATH, m, m + bys + 4, xc, 14, ES_AUTOHSCROLL\r
+  PUSHBUTTON     "...", IDC_EXTRACT_BUTTON_SET_PATH, xs - m - bxsDots, m, bxsDots, bys, WS_GROUP\r
+  DEFPUSHBUTTON  "Extract", IDOK, bx2, by, bxs, bys, WS_GROUP\r
+  PUSHBUTTON     "Cancel", IDCANCEL, bx1, by, bxs, bys\r
+END\r
+\r
+#endif\r
+\r
+#include "../../UI/FileManager/OverwriteDialog.rc"\r
+#include "../../UI/FileManager/PasswordDialog.rc"\r
+#include "../../UI/FileManager/ProgressDialog2.rc"\r
+#include "../../UI/GUI/Extract.rc"\r
diff --git a/CPP/7zip/Bundles/makefile b/CPP/7zip/Bundles/makefile
new file mode 100755 (executable)
index 0000000..e869ee4
--- /dev/null
@@ -0,0 +1,18 @@
+DIRS = \\r
+  Alone\~ \\r
+  Alone7z\~ \\r
+  Fm\~ \\r
+  Format7z\~ \\r
+  Format7zF\~ \\r
+  Format7zR\~ \\r
+  Format7zExtract\~ \\r
+  Format7zExtractR\~ \\r
+  LzmaCon\~ \\r
+  SFXCon\~ \\r
+  SFXSetup\~ \\r
+  SFXWin\~ \\r
+  \r
+all: $(DIRS)\r
+\r
+$(DIRS):\r
+!include "../SubBuild.mak"\r
diff --git a/CPP/7zip/Common/CWrappers.cpp b/CPP/7zip/Common/CWrappers.cpp
new file mode 100755 (executable)
index 0000000..66b8449
--- /dev/null
@@ -0,0 +1,226 @@
+// CWrappers.h\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+\r
+#include "CWrappers.h"\r
+\r
+#include "StreamUtils.h"\r
+\r
+#define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1)\r
+\r
+#define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x)\r
+\r
+static SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize)\r
+{\r
+  CCompressProgressWrap *p = (CCompressProgressWrap *)pp;\r
+  p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize));\r
+  return (SRes)p->Res;\r
+}\r
+\r
+CCompressProgressWrap::CCompressProgressWrap(ICompressProgressInfo *progress)\r
+{\r
+  p.Progress = CompressProgress;\r
+  Progress = progress;\r
+  Res = SZ_OK;\r
+}\r
+\r
+static const UInt32 kStreamStepSize = (UInt32)1 << 31;\r
+\r
+SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes)\r
+{\r
+  switch(res)\r
+  {\r
+    case S_OK: return SZ_OK;\r
+    case E_OUTOFMEMORY: return SZ_ERROR_MEM;\r
+    case E_INVALIDARG: return SZ_ERROR_PARAM;\r
+    case E_ABORT: return SZ_ERROR_PROGRESS;\r
+    case S_FALSE: return SZ_ERROR_DATA;\r
+  }\r
+  return defaultRes;\r
+}\r
+\r
+static SRes MyRead(void *object, void *data, size_t *size)\r
+{\r
+  CSeqInStreamWrap *p = (CSeqInStreamWrap *)object;\r
+  UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize);\r
+  p->Res = (p->Stream->Read(data, curSize, &curSize));\r
+  *size = curSize;\r
+  if (p->Res == S_OK)\r
+    return SZ_OK;\r
+  return HRESULT_To_SRes(p->Res, SZ_ERROR_READ);\r
+}\r
+\r
+static size_t MyWrite(void *object, const void *data, size_t size)\r
+{\r
+  CSeqOutStreamWrap *p = (CSeqOutStreamWrap *)object;\r
+  if (p->Stream)\r
+  {\r
+    p->Res = WriteStream(p->Stream, data, size);\r
+    if (p->Res != 0)\r
+      return 0;\r
+  }\r
+  else\r
+    p->Res = S_OK;\r
+  p->Processed += size;\r
+  return size;\r
+}\r
+\r
+CSeqInStreamWrap::CSeqInStreamWrap(ISequentialInStream *stream)\r
+{\r
+  p.Read = MyRead;\r
+  Stream = stream;\r
+}\r
+\r
+CSeqOutStreamWrap::CSeqOutStreamWrap(ISequentialOutStream *stream)\r
+{\r
+  p.Write = MyWrite;\r
+  Stream = stream;\r
+  Res = SZ_OK;\r
+  Processed = 0;\r
+}\r
+\r
+HRESULT SResToHRESULT(SRes res)\r
+{\r
+  switch(res)\r
+  {\r
+    case SZ_OK: return S_OK;\r
+    case SZ_ERROR_MEM: return E_OUTOFMEMORY;\r
+    case SZ_ERROR_PARAM: return E_INVALIDARG;\r
+    case SZ_ERROR_PROGRESS: return E_ABORT;\r
+    case SZ_ERROR_DATA: return S_FALSE;\r
+  }\r
+  return E_FAIL;\r
+}\r
+\r
+static SRes InStreamWrap_Read(void *pp, void *data, size_t *size)\r
+{\r
+  CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp;\r
+  UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize);\r
+  p->Res = p->Stream->Read(data, curSize, &curSize);\r
+  *size = curSize;\r
+  return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ;\r
+}\r
+\r
+static SRes InStreamWrap_Seek(void *pp, Int64 *offset, ESzSeek origin)\r
+{\r
+  CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp;\r
+  UInt32 moveMethod;\r
+  switch(origin)\r
+  {\r
+    case SZ_SEEK_SET: moveMethod = STREAM_SEEK_SET; break;\r
+    case SZ_SEEK_CUR: moveMethod = STREAM_SEEK_CUR; break;\r
+    case SZ_SEEK_END: moveMethod = STREAM_SEEK_END; break;\r
+    default: return SZ_ERROR_PARAM;\r
+  }\r
+  UInt64 newPosition;\r
+  p->Res = p->Stream->Seek(*offset, moveMethod, &newPosition);\r
+  *offset = (Int64)newPosition;\r
+  return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ;\r
+}\r
+\r
+CSeekInStreamWrap::CSeekInStreamWrap(IInStream *stream)\r
+{\r
+  Stream = stream;\r
+  p.Read = InStreamWrap_Read;\r
+  p.Seek = InStreamWrap_Seek;\r
+  Res = S_OK;\r
+}\r
+\r
+\r
+/* ---------- CByteInBufWrap ---------- */\r
+\r
+void CByteInBufWrap::Free()\r
+{\r
+  ::MidFree(Buf);\r
+  Buf = 0;\r
+}\r
+\r
+bool CByteInBufWrap::Alloc(UInt32 size)\r
+{\r
+  if (Buf == 0 || size != Size)\r
+  {\r
+    Free();\r
+    Lim = Cur = Buf = (Byte *)::MidAlloc((size_t)size);\r
+    Size = size;\r
+  }\r
+  return (Buf != 0);\r
+}\r
+\r
+Byte CByteInBufWrap::ReadByteFromNewBlock()\r
+{\r
+  if (Res == S_OK)\r
+  {\r
+    UInt32 avail;\r
+    Processed += (Cur - Buf);\r
+    Res = Stream->Read(Buf, Size, &avail);\r
+    Cur = Buf;\r
+    Lim = Buf + avail;\r
+    if (avail != 0)\r
+      return *Cur++;\r
+  }\r
+  Extra = true;\r
+  return 0;\r
+}\r
+\r
+static Byte Wrap_ReadByte(void *pp)\r
+{\r
+  CByteInBufWrap *p = (CByteInBufWrap *)pp;\r
+  if (p->Cur != p->Lim)\r
+    return *p->Cur++;\r
+  return p->ReadByteFromNewBlock();\r
+}\r
+\r
+CByteInBufWrap::CByteInBufWrap(): Buf(0)\r
+{\r
+  p.Read = Wrap_ReadByte;\r
+}\r
+\r
+\r
+/* ---------- CByteOutBufWrap ---------- */\r
+\r
+void CByteOutBufWrap::Free()\r
+{\r
+  ::MidFree(Buf);\r
+  Buf = 0;\r
+}\r
+\r
+bool CByteOutBufWrap::Alloc(size_t size)\r
+{\r
+  if (Buf == 0 || size != Size)\r
+  {\r
+    Free();\r
+    Buf = (Byte *)::MidAlloc(size);\r
+    Size = size;\r
+  }\r
+  return (Buf != 0);\r
+}\r
+\r
+HRESULT CByteOutBufWrap::Flush()\r
+{\r
+  if (Res == S_OK)\r
+  {\r
+    size_t size = (Cur - Buf);\r
+    Res = WriteStream(Stream, Buf, size);\r
+    if (Res == S_OK)\r
+      Processed += size;\r
+    Cur = Buf;\r
+  }\r
+  return Res;\r
+}\r
+\r
+static void Wrap_WriteByte(void *pp, Byte b)\r
+{\r
+  CByteOutBufWrap *p = (CByteOutBufWrap *)pp;\r
+  Byte *dest = p->Cur;\r
+  *dest = b;\r
+  p->Cur = ++dest;\r
+  if (dest == p->Lim)\r
+    p->Flush();\r
+}\r
+\r
+CByteOutBufWrap::CByteOutBufWrap(): Buf(0)\r
+{\r
+  p.Write = Wrap_WriteByte;\r
+}\r
diff --git a/CPP/7zip/Common/CWrappers.h b/CPP/7zip/Common/CWrappers.h
new file mode 100755 (executable)
index 0000000..dd4197c
--- /dev/null
@@ -0,0 +1,109 @@
+// CWrappers.h\r
+\r
+#ifndef __C_WRAPPERS_H\r
+#define __C_WRAPPERS_H\r
+\r
+#include "../ICoder.h"\r
+#include "../../Common/MyCom.h"\r
+\r
+struct CCompressProgressWrap\r
+{\r
+  ICompressProgress p;\r
+  ICompressProgressInfo *Progress;\r
+  HRESULT Res;\r
+  CCompressProgressWrap(ICompressProgressInfo *progress);\r
+};\r
+\r
+struct CSeqInStreamWrap\r
+{\r
+  ISeqInStream p;\r
+  ISequentialInStream *Stream;\r
+  HRESULT Res;\r
+  CSeqInStreamWrap(ISequentialInStream *stream);\r
+};\r
+\r
+struct CSeekInStreamWrap\r
+{\r
+  ISeekInStream p;\r
+  IInStream *Stream;\r
+  HRESULT Res;\r
+  CSeekInStreamWrap(IInStream *stream);\r
+};\r
+\r
+struct CSeqOutStreamWrap\r
+{\r
+  ISeqOutStream p;\r
+  ISequentialOutStream *Stream;\r
+  HRESULT Res;\r
+  UInt64 Processed;\r
+  CSeqOutStreamWrap(ISequentialOutStream *stream);\r
+};\r
+\r
+HRESULT SResToHRESULT(SRes res);\r
+\r
+struct CByteInBufWrap\r
+{\r
+  IByteIn p;\r
+  const Byte *Cur;\r
+  const Byte *Lim;\r
+  Byte *Buf;\r
+  UInt32 Size;\r
+  ISequentialInStream *Stream;\r
+  UInt64 Processed;\r
+  bool Extra;\r
+  HRESULT Res;\r
+  \r
+  CByteInBufWrap();\r
+  ~CByteInBufWrap() { Free();  }\r
+  void Free();\r
+  bool Alloc(UInt32 size);\r
+  void Init()\r
+  {\r
+    Lim = Cur = Buf;\r
+    Processed = 0;\r
+    Extra = false;\r
+    Res = S_OK;\r
+  }\r
+  UInt64 GetProcessed() const { return Processed + (Cur - Buf); }\r
+  Byte ReadByteFromNewBlock();\r
+  Byte ReadByte()\r
+  {\r
+    if (Cur != Lim)\r
+      return *Cur++;\r
+    return ReadByteFromNewBlock();\r
+  }\r
+};\r
+\r
+struct CByteOutBufWrap\r
+{\r
+  IByteOut p;\r
+  Byte *Cur;\r
+  const Byte *Lim;\r
+  Byte *Buf;\r
+  size_t Size;\r
+  ISequentialOutStream *Stream;\r
+  UInt64 Processed;\r
+  HRESULT Res;\r
+  \r
+  CByteOutBufWrap();\r
+  ~CByteOutBufWrap() { Free();  }\r
+  void Free();\r
+  bool Alloc(size_t size);\r
+  void Init()\r
+  {\r
+    Cur = Buf;\r
+    Lim = Buf + Size;\r
+    Processed = 0;\r
+    Res = S_OK;\r
+  }\r
+  UInt64 GetProcessed() const { return Processed + (Cur - Buf); }\r
+  HRESULT Flush();\r
+  void WriteByte(Byte b)\r
+  {\r
+    *Cur++ = b;\r
+    if (Cur == Lim)\r
+      Flush();\r
+  }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/CreateCoder.cpp b/CPP/7zip/Common/CreateCoder.cpp
new file mode 100755 (executable)
index 0000000..55bad3c
--- /dev/null
@@ -0,0 +1,293 @@
+// CreateCoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Windows/Defs.h"\r
+#include "../../Windows/PropVariant.h"\r
+\r
+#include "CreateCoder.h"\r
+\r
+#include "FilterCoder.h"\r
+#include "RegisterCodec.h"\r
+\r
+static const unsigned int kNumCodecsMax = 64;\r
+unsigned int g_NumCodecs = 0;\r
+const CCodecInfo *g_Codecs[kNumCodecsMax];\r
+void RegisterCodec(const CCodecInfo *codecInfo)\r
+{\r
+  if (g_NumCodecs < kNumCodecsMax)\r
+    g_Codecs[g_NumCodecs++] = codecInfo;\r
+}\r
+\r
+#ifdef EXTERNAL_CODECS\r
+static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res)\r
+{\r
+  NWindows::NCOM::CPropVariant prop;\r
+  RINOK(codecsInfo->GetProperty(index, propID, &prop));\r
+  if (prop.vt == VT_EMPTY)\r
+    res = 1;\r
+  else if (prop.vt == VT_UI4)\r
+    res = prop.ulVal;\r
+  else\r
+    return E_INVALIDARG;\r
+  return S_OK;\r
+}\r
+\r
+static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res)\r
+{\r
+  NWindows::NCOM::CPropVariant prop;\r
+  RINOK(codecsInfo->GetProperty(index, propID, &prop));\r
+  if (prop.vt == VT_EMPTY)\r
+    res = true;\r
+  else if (prop.vt == VT_BOOL)\r
+    res = VARIANT_BOOLToBool(prop.boolVal);\r
+  else\r
+    return E_INVALIDARG;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs)\r
+{\r
+  UInt32 num;\r
+  RINOK(codecsInfo->GetNumberOfMethods(&num));\r
+  for (UInt32 i = 0; i < num; i++)\r
+  {\r
+    CCodecInfoEx info;\r
+    NWindows::NCOM::CPropVariant prop;\r
+    RINOK(codecsInfo->GetProperty(i, NMethodPropID::kID, &prop));\r
+    // if (prop.vt != VT_BSTR)\r
+    // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal);\r
+    // memmove(info.Id.ID, prop.bstrVal, info.Id.IDSize);\r
+    if (prop.vt != VT_UI8)\r
+    {\r
+      continue; // old Interface\r
+      // return E_INVALIDARG;\r
+    }\r
+    info.Id = prop.uhVal.QuadPart;\r
+    prop.Clear();\r
+    \r
+    RINOK(codecsInfo->GetProperty(i, NMethodPropID::kName, &prop));\r
+    if (prop.vt == VT_BSTR)\r
+      info.Name = prop.bstrVal;\r
+    else if (prop.vt != VT_EMPTY)\r
+      return E_INVALIDARG;;\r
+    \r
+    RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kInStreams, info.NumInStreams));\r
+    RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kOutStreams, info.NumOutStreams));\r
+    RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned));\r
+    RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned));\r
+    \r
+    externalCodecs.Add(info);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+#endif\r
+\r
+bool FindMethod(\r
+  #ifdef EXTERNAL_CODECS\r
+  ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs,\r
+  #endif\r
+  const UString &name,\r
+  CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams)\r
+{\r
+  UInt32 i;\r
+  for (i = 0; i < g_NumCodecs; i++)\r
+  {\r
+    const CCodecInfo &codec = *g_Codecs[i];\r
+    if (name.CompareNoCase(codec.Name) == 0)\r
+    {\r
+      methodId = codec.Id;\r
+      numInStreams = codec.NumInStreams;\r
+      numOutStreams = 1;\r
+      return true;\r
+    }\r
+  }\r
+  #ifdef EXTERNAL_CODECS\r
+  if (externalCodecs)\r
+    for (i = 0; i < (UInt32)externalCodecs->Size(); i++)\r
+    {\r
+      const CCodecInfoEx &codec = (*externalCodecs)[i];\r
+      if (codec.Name.CompareNoCase(name) == 0)\r
+      {\r
+        methodId = codec.Id;\r
+        numInStreams = codec.NumInStreams;\r
+        numOutStreams = codec.NumOutStreams;\r
+        return true;\r
+      }\r
+    }\r
+  #endif\r
+  return false;\r
+}\r
+\r
+bool FindMethod(\r
+  #ifdef EXTERNAL_CODECS\r
+  ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs,\r
+  #endif\r
+  CMethodId methodId, UString &name)\r
+{\r
+  UInt32 i;\r
+  for (i = 0; i < g_NumCodecs; i++)\r
+  {\r
+    const CCodecInfo &codec = *g_Codecs[i];\r
+    if (methodId == codec.Id)\r
+    {\r
+      name = codec.Name;\r
+      return true;\r
+    }\r
+  }\r
+  #ifdef EXTERNAL_CODECS\r
+  if (externalCodecs)\r
+    for (i = 0; i < (UInt32)externalCodecs->Size(); i++)\r
+    {\r
+      const CCodecInfoEx &codec = (*externalCodecs)[i];\r
+      if (methodId == codec.Id)\r
+      {\r
+        name = codec.Name;\r
+        return true;\r
+      }\r
+    }\r
+  #endif\r
+  return false;\r
+}\r
+\r
+HRESULT CreateCoder(\r
+  DECL_EXTERNAL_CODECS_LOC_VARS\r
+  CMethodId methodId,\r
+  CMyComPtr<ICompressFilter> &filter,\r
+  CMyComPtr<ICompressCoder> &coder,\r
+  CMyComPtr<ICompressCoder2> &coder2,\r
+  bool encode, bool onlyCoder)\r
+{\r
+  bool created = false;\r
+  UInt32 i;\r
+  for (i = 0; i < g_NumCodecs; i++)\r
+  {\r
+    const CCodecInfo &codec = *g_Codecs[i];\r
+    if (codec.Id == methodId)\r
+    {\r
+      if (encode)\r
+      {\r
+        if (codec.CreateEncoder)\r
+        {\r
+          void *p = codec.CreateEncoder();\r
+          if (codec.IsFilter) filter = (ICompressFilter *)p;\r
+          else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p;\r
+          else coder2 = (ICompressCoder2 *)p;\r
+          created = (p != 0);\r
+          break;\r
+        }\r
+      }\r
+      else\r
+        if (codec.CreateDecoder)\r
+        {\r
+          void *p = codec.CreateDecoder();\r
+          if (codec.IsFilter) filter = (ICompressFilter *)p;\r
+          else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p;\r
+          else coder2 = (ICompressCoder2 *)p;\r
+          created = (p != 0);\r
+          break;\r
+        }\r
+    }\r
+  }\r
+\r
+  #ifdef EXTERNAL_CODECS\r
+  if (!created && externalCodecs)\r
+    for (i = 0; i < (UInt32)externalCodecs->Size(); i++)\r
+    {\r
+      const CCodecInfoEx &codec = (*externalCodecs)[i];\r
+      if (codec.Id == methodId)\r
+      {\r
+        if (encode)\r
+        {\r
+          if (codec.EncoderIsAssigned)\r
+          {\r
+            if (codec.IsSimpleCodec())\r
+            {\r
+              HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder);\r
+              if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE)\r
+                return result;\r
+              if (!coder)\r
+              {\r
+                RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter));\r
+              }\r
+            }\r
+            else\r
+            {\r
+              RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2));\r
+            }\r
+            break;\r
+          }\r
+        }\r
+        else\r
+          if (codec.DecoderIsAssigned)\r
+          {\r
+            if (codec.IsSimpleCodec())\r
+            {\r
+              HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder);\r
+              if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE)\r
+                return result;\r
+              if (!coder)\r
+              {\r
+                RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter));\r
+              }\r
+            }\r
+            else\r
+            {\r
+              RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2));\r
+            }\r
+            break;\r
+          }\r
+      }\r
+    }\r
+  #endif\r
+\r
+  if (onlyCoder && filter)\r
+  {\r
+    CFilterCoder *coderSpec = new CFilterCoder;\r
+    coder = coderSpec;\r
+    coderSpec->Filter = filter;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CreateCoder(\r
+  DECL_EXTERNAL_CODECS_LOC_VARS\r
+  CMethodId methodId,\r
+  CMyComPtr<ICompressCoder> &coder,\r
+  CMyComPtr<ICompressCoder2> &coder2,\r
+  bool encode)\r
+{\r
+  CMyComPtr<ICompressFilter> filter;\r
+  return CreateCoder(\r
+    EXTERNAL_CODECS_LOC_VARS\r
+    methodId,\r
+    filter, coder, coder2, encode, true);\r
+}\r
+\r
+HRESULT CreateCoder(\r
+  DECL_EXTERNAL_CODECS_LOC_VARS\r
+  CMethodId methodId,\r
+  CMyComPtr<ICompressCoder> &coder, bool encode)\r
+{\r
+  CMyComPtr<ICompressFilter> filter;\r
+  CMyComPtr<ICompressCoder2> coder2;\r
+  return CreateCoder(\r
+    EXTERNAL_CODECS_LOC_VARS\r
+    methodId,\r
+    coder, coder2, encode);\r
+}\r
+\r
+HRESULT CreateFilter(\r
+  DECL_EXTERNAL_CODECS_LOC_VARS\r
+  CMethodId methodId,\r
+  CMyComPtr<ICompressFilter> &filter,\r
+  bool encode)\r
+{\r
+  CMyComPtr<ICompressCoder> coder;\r
+  CMyComPtr<ICompressCoder2> coder2;\r
+  return CreateCoder(\r
+    EXTERNAL_CODECS_LOC_VARS\r
+    methodId,\r
+    filter, coder, coder2, encode, false);\r
+}\r
diff --git a/CPP/7zip/Common/CreateCoder.h b/CPP/7zip/Common/CreateCoder.h
new file mode 100755 (executable)
index 0000000..9a59d45
--- /dev/null
@@ -0,0 +1,98 @@
+// CreateCoder.h\r
+\r
+#ifndef __CREATE_CODER_H\r
+#define __CREATE_CODER_H\r
+\r
+#include "../../Common/MyCom.h"\r
+#include "../../Common/MyString.h"\r
+#include "../ICoder.h"\r
+\r
+#include "MethodId.h"\r
+\r
+#ifdef EXTERNAL_CODECS\r
+\r
+struct CCodecInfoEx\r
+{\r
+  UString Name;\r
+  CMethodId Id;\r
+  UInt32 NumInStreams;\r
+  UInt32 NumOutStreams;\r
+  bool EncoderIsAssigned;\r
+  bool DecoderIsAssigned;\r
+  bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; }\r
+  CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {}\r
+};\r
+\r
+HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs);\r
+\r
+#define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo,\r
+#define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo)\r
+#define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo);\r
+#define IMPL_ISetCompressCodecsInfo2(x) \\r
+STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \\r
+  COM_TRY_BEGIN _codecsInfo = compressCodecsInfo;  return LoadExternalCodecs(_codecsInfo, _externalCodecs); COM_TRY_END }\r
+#define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler)\r
+\r
+#define EXTERNAL_CODECS_VARS2 _codecsInfo, &_externalCodecs\r
+\r
+#define DECL_EXTERNAL_CODECS_VARS CMyComPtr<ICompressCodecsInfo> _codecsInfo; CObjectVector<CCodecInfoEx> _externalCodecs;\r
+#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2,\r
+\r
+#define DECL_EXTERNAL_CODECS_LOC_VARS2 ICompressCodecsInfo *codecsInfo, const CObjectVector<CCodecInfoEx> *externalCodecs\r
+#define EXTERNAL_CODECS_LOC_VARS2 codecsInfo, externalCodecs\r
+\r
+#define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2,\r
+#define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2,\r
+\r
+#else\r
+\r
+#define PUBLIC_ISetCompressCodecsInfo\r
+#define QUERY_ENTRY_ISetCompressCodecsInfo\r
+#define DECL_ISetCompressCodecsInfo\r
+#define IMPL_ISetCompressCodecsInfo\r
+#define EXTERNAL_CODECS_VARS2\r
+#define DECL_EXTERNAL_CODECS_VARS\r
+#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2\r
+#define DECL_EXTERNAL_CODECS_LOC_VARS2\r
+#define EXTERNAL_CODECS_LOC_VARS2\r
+#define DECL_EXTERNAL_CODECS_LOC_VARS\r
+#define EXTERNAL_CODECS_LOC_VARS\r
+\r
+#endif\r
+\r
+bool FindMethod(\r
+  DECL_EXTERNAL_CODECS_LOC_VARS\r
+  const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams);\r
+\r
+bool FindMethod(\r
+  DECL_EXTERNAL_CODECS_LOC_VARS\r
+  CMethodId methodId, UString &name);\r
+\r
+\r
+HRESULT CreateCoder(\r
+  DECL_EXTERNAL_CODECS_LOC_VARS\r
+  CMethodId methodId,\r
+  CMyComPtr<ICompressFilter> &filter,\r
+  CMyComPtr<ICompressCoder> &coder,\r
+  CMyComPtr<ICompressCoder2> &coder2,\r
+  bool encode, bool onlyCoder);\r
+\r
+HRESULT CreateCoder(\r
+  DECL_EXTERNAL_CODECS_LOC_VARS\r
+  CMethodId methodId,\r
+  CMyComPtr<ICompressCoder> &coder,\r
+  CMyComPtr<ICompressCoder2> &coder2,\r
+  bool encode);\r
+\r
+HRESULT CreateCoder(\r
+  DECL_EXTERNAL_CODECS_LOC_VARS\r
+  CMethodId methodId,\r
+  CMyComPtr<ICompressCoder> &coder, bool encode);\r
+\r
+HRESULT CreateFilter(\r
+  DECL_EXTERNAL_CODECS_LOC_VARS\r
+  CMethodId methodId,\r
+  CMyComPtr<ICompressFilter> &filter,\r
+  bool encode);\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/FilePathAutoRename.cpp b/CPP/7zip/Common/FilePathAutoRename.cpp
new file mode 100755 (executable)
index 0000000..d357c5b
--- /dev/null
@@ -0,0 +1,55 @@
+// FilePathAutoRename.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/Defs.h"\r
+#include "Common/IntToString.h"\r
+\r
+#include "Windows/FileFind.h"\r
+\r
+#include "FilePathAutoRename.h"\r
+\r
+using namespace NWindows;\r
+\r
+static bool MakeAutoName(const UString &name,\r
+    const UString &extension, unsigned value, UString &path)\r
+{\r
+  wchar_t number[16];\r
+  ConvertUInt32ToString(value, number);\r
+  path = name;\r
+  path += number;\r
+  path += extension;\r
+  return NFile::NFind::DoesFileOrDirExist(path);\r
+}\r
+\r
+bool AutoRenamePath(UString &fullProcessedPath)\r
+{\r
+  UString path;\r
+  int dotPos = fullProcessedPath.ReverseFind(L'.');\r
+\r
+  int slashPos = fullProcessedPath.ReverseFind(L'/');\r
+  #ifdef _WIN32\r
+  int slash1Pos = fullProcessedPath.ReverseFind(L'\\');\r
+  slashPos = MyMax(slashPos, slash1Pos);\r
+  #endif\r
+\r
+  UString name, extension;\r
+  if (dotPos > slashPos && dotPos > 0)\r
+  {\r
+    name = fullProcessedPath.Left(dotPos);\r
+    extension = fullProcessedPath.Mid(dotPos);\r
+  }\r
+  else\r
+    name = fullProcessedPath;\r
+  name += L'_';\r
+  unsigned left = 1, right = (1 << 30);\r
+  while (left != right)\r
+  {\r
+    unsigned mid = (left + right) / 2;\r
+    if (MakeAutoName(name, extension, mid, path))\r
+      left = mid + 1;\r
+    else\r
+      right = mid;\r
+  }\r
+  return !MakeAutoName(name, extension, right, fullProcessedPath);\r
+}\r
diff --git a/CPP/7zip/Common/FilePathAutoRename.h b/CPP/7zip/Common/FilePathAutoRename.h
new file mode 100755 (executable)
index 0000000..4303962
--- /dev/null
@@ -0,0 +1,10 @@
+// Util/FilePathAutoRename.h\r
+\r
+#ifndef __FILEPATHAUTORENAME_H\r
+#define __FILEPATHAUTORENAME_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+bool AutoRenamePath(UString &fullProcessedPath);\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp
new file mode 100755 (executable)
index 0000000..de49911
--- /dev/null
@@ -0,0 +1,422 @@
+// FileStreams.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#ifndef _WIN32\r
+#include <fcntl.h>\r
+#include <unistd.h>\r
+#include <errno.h>\r
+#endif\r
+\r
+#ifdef SUPPORT_DEVICE_FILE\r
+#include "../../../C/Alloc.h"\r
+#include "../../Common/Defs.h"\r
+#endif\r
+\r
+#include "FileStreams.h"\r
+\r
+static inline HRESULT ConvertBoolToHRESULT(bool result)\r
+{\r
+  #ifdef _WIN32\r
+  if (result)\r
+    return S_OK;\r
+  DWORD lastError = ::GetLastError();\r
+  if (lastError == 0)\r
+    return E_FAIL;\r
+  return HRESULT_FROM_WIN32(lastError);\r
+  #else\r
+  return result ? S_OK: E_FAIL;\r
+  #endif\r
+}\r
+\r
+bool CInFileStream::Open(LPCTSTR fileName)\r
+{\r
+  return File.Open(fileName);\r
+}\r
+\r
+#ifdef USE_WIN_FILE\r
+#ifndef _UNICODE\r
+bool CInFileStream::Open(LPCWSTR fileName)\r
+{\r
+  return File.Open(fileName);\r
+}\r
+#endif\r
+#endif\r
+\r
+bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite)\r
+{\r
+  return File.OpenShared(fileName, shareForWrite);\r
+}\r
+\r
+#ifdef USE_WIN_FILE\r
+#ifndef _UNICODE\r
+bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite)\r
+{\r
+  return File.OpenShared(fileName, shareForWrite);\r
+}\r
+#endif\r
+#endif\r
+\r
+#ifdef SUPPORT_DEVICE_FILE\r
+\r
+static const UInt32 kClusterSize = 1 << 18;\r
+CInFileStream::CInFileStream():\r
+  VirtPos(0),\r
+  PhyPos(0),\r
+  Buffer(0),\r
+  BufferSize(0)\r
+{\r
+}\r
+\r
+#endif\r
+\r
+CInFileStream::~CInFileStream()\r
+{\r
+  #ifdef SUPPORT_DEVICE_FILE\r
+  MidFree(Buffer);\r
+  #endif\r
+}\r
+\r
+STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  #ifdef USE_WIN_FILE\r
+  \r
+  #ifdef SUPPORT_DEVICE_FILE\r
+  if (processedSize != NULL)\r
+    *processedSize = 0;\r
+  if (size == 0)\r
+    return S_OK;\r
+  if (File.IsDeviceFile)\r
+  {\r
+    if (File.LengthDefined)\r
+    {\r
+      if (VirtPos >= File.Length)\r
+        return VirtPos == File.Length ? S_OK : E_FAIL;\r
+      UInt64 rem = File.Length - VirtPos;\r
+      if (size > rem)\r
+        size = (UInt32)rem;\r
+    }\r
+    for (;;)\r
+    {\r
+      const UInt32 mask = kClusterSize - 1;\r
+      UInt64 mask2 = ~(UInt64)mask;\r
+      UInt64 alignedPos = VirtPos & mask2;\r
+      if (BufferSize > 0 && BufferStartPos == alignedPos)\r
+      {\r
+        UInt32 pos = (UInt32)VirtPos & mask;\r
+        if (pos >= BufferSize)\r
+          return S_OK;\r
+        UInt32 rem = MyMin(BufferSize - pos, size);\r
+        memcpy(data, Buffer + pos, rem);\r
+        VirtPos += rem;\r
+        if (processedSize != NULL)\r
+          *processedSize += rem;\r
+        return S_OK;\r
+      }\r
+      \r
+      bool useBuffer = false;\r
+      if ((VirtPos & mask) != 0 || ((ptrdiff_t)data & mask) != 0 )\r
+        useBuffer = true;\r
+      else\r
+      {\r
+        UInt64 end = VirtPos + size;\r
+        if ((end & mask) != 0)\r
+        {\r
+          end &= mask2;\r
+          if (end <= VirtPos)\r
+            useBuffer = true;\r
+          else\r
+            size = (UInt32)(end - VirtPos);\r
+        }\r
+      }\r
+      if (!useBuffer)\r
+        break;\r
+      if (alignedPos != PhyPos)\r
+      {\r
+        UInt64 realNewPosition;\r
+        bool result = File.Seek(alignedPos, FILE_BEGIN, realNewPosition);\r
+        if (!result)\r
+          return ConvertBoolToHRESULT(result);\r
+        PhyPos = realNewPosition;\r
+      }\r
+\r
+      BufferStartPos = alignedPos;\r
+      UInt32 readSize = kClusterSize;\r
+      if (File.LengthDefined)\r
+        readSize = (UInt32)MyMin(File.Length - PhyPos, (UInt64)kClusterSize);\r
+\r
+      if (Buffer == 0)\r
+      {\r
+        Buffer = (Byte *)MidAlloc(kClusterSize);\r
+        if (Buffer == 0)\r
+          return E_OUTOFMEMORY;\r
+      }\r
+      bool result = File.Read1(Buffer, readSize, BufferSize);\r
+      if (!result)\r
+        return ConvertBoolToHRESULT(result);\r
+\r
+      if (BufferSize == 0)\r
+        return S_OK;\r
+      PhyPos += BufferSize;\r
+    }\r
+\r
+    if (VirtPos != PhyPos)\r
+    {\r
+      UInt64 realNewPosition;\r
+      bool result = File.Seek(VirtPos, FILE_BEGIN, realNewPosition);\r
+      if (!result)\r
+        return ConvertBoolToHRESULT(result);\r
+      PhyPos = VirtPos = realNewPosition;\r
+    }\r
+  }\r
+  #endif\r
+\r
+  UInt32 realProcessedSize;\r
+  bool result = File.ReadPart(data, size, realProcessedSize);\r
+  if (processedSize != NULL)\r
+    *processedSize = realProcessedSize;\r
+  #ifdef SUPPORT_DEVICE_FILE\r
+  VirtPos += realProcessedSize;\r
+  PhyPos += realProcessedSize;\r
+  #endif\r
+  return ConvertBoolToHRESULT(result);\r
+  \r
+  #else\r
+  \r
+  if (processedSize != NULL)\r
+    *processedSize = 0;\r
+  ssize_t res = File.Read(data, (size_t)size);\r
+  if (res == -1)\r
+    return E_FAIL;\r
+  if (processedSize != NULL)\r
+    *processedSize = (UInt32)res;\r
+  return S_OK;\r
+\r
+  #endif\r
+}\r
+\r
+#ifdef UNDER_CE\r
+STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  size_t s2 = fread(data, 1, size, stdout);\r
+  if (processedSize != 0)\r
+    *processedSize = s2;\r
+  return (s2 = size) ? S_OK : E_FAIL;\r
+}\r
+#else\r
+STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  #ifdef _WIN32\r
+  \r
+  DWORD realProcessedSize;\r
+  UInt32 sizeTemp = (1 << 20);\r
+  if (sizeTemp > size)\r
+    sizeTemp = size;\r
+  BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, sizeTemp, &realProcessedSize, NULL);\r
+  if (processedSize != NULL)\r
+    *processedSize = realProcessedSize;\r
+  if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE)\r
+    return S_OK;\r
+  return ConvertBoolToHRESULT(res != FALSE);\r
+  \r
+  #else\r
+\r
+  if (processedSize != NULL)\r
+    *processedSize = 0;\r
+  ssize_t res;\r
+  do\r
+  {\r
+    res = read(0, data, (size_t)size);\r
+  }\r
+  while (res < 0 && (errno == EINTR));\r
+  if (res == -1)\r
+    return E_FAIL;\r
+  if (processedSize != NULL)\r
+    *processedSize = (UInt32)res;\r
+  return S_OK;\r
+  \r
+  #endif\r
+}\r
+  \r
+#endif\r
+\r
+STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin,\r
+    UInt64 *newPosition)\r
+{\r
+  if (seekOrigin >= 3)\r
+    return STG_E_INVALIDFUNCTION;\r
+\r
+  #ifdef USE_WIN_FILE\r
+\r
+  #ifdef SUPPORT_DEVICE_FILE\r
+  if (File.IsDeviceFile)\r
+  {\r
+    UInt64 newVirtPos = offset;\r
+    switch(seekOrigin)\r
+    {\r
+      case STREAM_SEEK_SET: break;\r
+      case STREAM_SEEK_CUR: newVirtPos += VirtPos; break;\r
+      case STREAM_SEEK_END: newVirtPos += File.Length; break;\r
+      default: return STG_E_INVALIDFUNCTION;\r
+    }\r
+    VirtPos = newVirtPos;\r
+    if (newPosition)\r
+      *newPosition = newVirtPos;\r
+    return S_OK;\r
+  }\r
+  #endif\r
+  \r
+  UInt64 realNewPosition;\r
+  bool result = File.Seek(offset, seekOrigin, realNewPosition);\r
+  \r
+  #ifdef SUPPORT_DEVICE_FILE\r
+  PhyPos = VirtPos = realNewPosition;\r
+  #endif\r
+\r
+  if (newPosition != NULL)\r
+    *newPosition = realNewPosition;\r
+  return ConvertBoolToHRESULT(result);\r
+  \r
+  #else\r
+  \r
+  off_t res = File.Seek(offset, seekOrigin);\r
+  if (res == -1)\r
+    return E_FAIL;\r
+  if (newPosition != NULL)\r
+    *newPosition = (UInt64)res;\r
+  return S_OK;\r
+  \r
+  #endif\r
+}\r
+\r
+STDMETHODIMP CInFileStream::GetSize(UInt64 *size)\r
+{\r
+  return ConvertBoolToHRESULT(File.GetLength(*size));\r
+}\r
+\r
+\r
+//////////////////////////\r
+// COutFileStream\r
+\r
+HRESULT COutFileStream::Close()\r
+{\r
+  return ConvertBoolToHRESULT(File.Close());\r
+}\r
+\r
+STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  #ifdef USE_WIN_FILE\r
+\r
+  UInt32 realProcessedSize;\r
+  bool result = File.WritePart(data, size, realProcessedSize);\r
+  ProcessedSize += realProcessedSize;\r
+  if (processedSize != NULL)\r
+    *processedSize = realProcessedSize;\r
+  return ConvertBoolToHRESULT(result);\r
+  \r
+  #else\r
+  \r
+  if (processedSize != NULL)\r
+    *processedSize = 0;\r
+  ssize_t res = File.Write(data, (size_t)size);\r
+  if (res == -1)\r
+    return E_FAIL;\r
+  if (processedSize != NULL)\r
+    *processedSize = (UInt32)res;\r
+  ProcessedSize += res;\r
+  return S_OK;\r
+  \r
+  #endif\r
+}\r
+  \r
+STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)\r
+{\r
+  if (seekOrigin >= 3)\r
+    return STG_E_INVALIDFUNCTION;\r
+  #ifdef USE_WIN_FILE\r
+\r
+  UInt64 realNewPosition;\r
+  bool result = File.Seek(offset, seekOrigin, realNewPosition);\r
+  if (newPosition != NULL)\r
+    *newPosition = realNewPosition;\r
+  return ConvertBoolToHRESULT(result);\r
+  \r
+  #else\r
+  \r
+  off_t res = File.Seek(offset, seekOrigin);\r
+  if (res == -1)\r
+    return E_FAIL;\r
+  if (newPosition != NULL)\r
+    *newPosition = (UInt64)res;\r
+  return S_OK;\r
+  \r
+  #endif\r
+}\r
+\r
+STDMETHODIMP COutFileStream::SetSize(UInt64 newSize)\r
+{\r
+  #ifdef USE_WIN_FILE\r
+  UInt64 currentPos;\r
+  if (!File.Seek(0, FILE_CURRENT, currentPos))\r
+    return E_FAIL;\r
+  bool result = File.SetLength(newSize);\r
+  UInt64 currentPos2;\r
+  result = result && File.Seek(currentPos, currentPos2);\r
+  return result ? S_OK : E_FAIL;\r
+  #else\r
+  return E_FAIL;\r
+  #endif\r
+}\r
+\r
+#ifdef UNDER_CE\r
+STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  size_t s2 = fwrite(data, 1, size, stdout);\r
+  if (processedSize != 0)\r
+    *processedSize = s2;\r
+  return (s2 = size) ? S_OK : E_FAIL;\r
+}\r
+#else\r
+STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize != NULL)\r
+    *processedSize = 0;\r
+\r
+  #ifdef _WIN32\r
+  UInt32 realProcessedSize;\r
+  BOOL res = TRUE;\r
+  if (size > 0)\r
+  {\r
+    // Seems that Windows doesn't like big amounts writing to stdout.\r
+    // So we limit portions by 32KB.\r
+    UInt32 sizeTemp = (1 << 15);\r
+    if (sizeTemp > size)\r
+      sizeTemp = size;\r
+    res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),\r
+        data, sizeTemp, (DWORD *)&realProcessedSize, NULL);\r
+    size -= realProcessedSize;\r
+    data = (const void *)((const Byte *)data + realProcessedSize);\r
+    if (processedSize != NULL)\r
+      *processedSize += realProcessedSize;\r
+  }\r
+  return ConvertBoolToHRESULT(res != FALSE);\r
+\r
+  #else\r
+  \r
+  ssize_t res;\r
+  do\r
+  {\r
+    res = write(1, data, (size_t)size);\r
+  }\r
+  while (res < 0 && (errno == EINTR));\r
+  if (res == -1)\r
+    return E_FAIL;\r
+  if (processedSize != NULL)\r
+    *processedSize = (UInt32)res;\r
+  return S_OK;\r
+  \r
+  return S_OK;\r
+  #endif\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/FileStreams.h b/CPP/7zip/Common/FileStreams.h
new file mode 100755 (executable)
index 0000000..f979294
--- /dev/null
@@ -0,0 +1,144 @@
+// FileStreams.h\r
+\r
+#ifndef __FILESTREAMS_H\r
+#define __FILESTREAMS_H\r
+\r
+#ifdef _WIN32\r
+#define USE_WIN_FILE\r
+#endif\r
+\r
+#ifdef USE_WIN_FILE\r
+#include "../../Windows/FileIO.h"\r
+#else\r
+#include "../../Common/C_FileIO.h"\r
+#endif\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../IStream.h"\r
+\r
+class CInFileStream:\r
+  public IInStream,\r
+  public IStreamGetSize,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  #ifdef USE_WIN_FILE\r
+  NWindows::NFile::NIO::CInFile File;\r
+  #ifdef SUPPORT_DEVICE_FILE\r
+  UInt64 VirtPos;\r
+  UInt64 PhyPos;\r
+  UInt64 BufferStartPos;\r
+  Byte *Buffer;\r
+  UInt32 BufferSize;\r
+  #endif\r
+  #else\r
+  NC::NFile::NIO::CInFile File;\r
+  #endif\r
+  virtual ~CInFileStream();\r
+\r
+  #ifdef SUPPORT_DEVICE_FILE\r
+  CInFileStream();\r
+  #endif\r
+  \r
+  bool Open(LPCTSTR fileName);\r
+  #ifdef USE_WIN_FILE\r
+  #ifndef _UNICODE\r
+  bool Open(LPCWSTR fileName);\r
+  #endif\r
+  #endif\r
+\r
+  bool OpenShared(LPCTSTR fileName, bool shareForWrite);\r
+  #ifdef USE_WIN_FILE\r
+  #ifndef _UNICODE\r
+  bool OpenShared(LPCWSTR fileName, bool shareForWrite);\r
+  #endif\r
+  #endif\r
+\r
+  MY_UNKNOWN_IMP2(IInStream, IStreamGetSize)\r
+\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);\r
+\r
+  STDMETHOD(GetSize)(UInt64 *size);\r
+};\r
+\r
+class CStdInFileStream:\r
+  public ISequentialInStream,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP\r
+\r
+  virtual ~CStdInFileStream() {}\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+};\r
+\r
+class COutFileStream:\r
+  public IOutStream,\r
+  public CMyUnknownImp\r
+{\r
+  #ifdef USE_WIN_FILE\r
+  NWindows::NFile::NIO::COutFile File;\r
+  #else\r
+  NC::NFile::NIO::COutFile File;\r
+  #endif\r
+public:\r
+  virtual ~COutFileStream() {}\r
+  bool Create(LPCTSTR fileName, bool createAlways)\r
+  {\r
+    ProcessedSize = 0;\r
+    return File.Create(fileName, createAlways);\r
+  }\r
+  bool Open(LPCTSTR fileName, DWORD creationDisposition)\r
+  {\r
+    ProcessedSize = 0;\r
+    return File.Open(fileName, creationDisposition);\r
+  }\r
+  #ifdef USE_WIN_FILE\r
+  #ifndef _UNICODE\r
+  bool Create(LPCWSTR fileName, bool createAlways)\r
+  {\r
+    ProcessedSize = 0;\r
+    return File.Create(fileName, createAlways);\r
+  }\r
+  bool Open(LPCWSTR fileName, DWORD creationDisposition)\r
+  {\r
+    ProcessedSize = 0;\r
+    return File.Open(fileName, creationDisposition);\r
+  }\r
+  #endif\r
+  #endif\r
+\r
+  HRESULT Close();\r
+  \r
+  UInt64 ProcessedSize;\r
+\r
+  #ifdef USE_WIN_FILE\r
+  bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)\r
+  {\r
+    return File.SetTime(cTime, aTime, mTime);\r
+  }\r
+  bool SetMTime(const FILETIME *mTime) {  return File.SetMTime(mTime); }\r
+  #endif\r
+\r
+\r
+  MY_UNKNOWN_IMP1(IOutStream)\r
+\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);\r
+  STDMETHOD(SetSize)(UInt64 newSize);\r
+};\r
+\r
+class CStdOutFileStream:\r
+  public ISequentialOutStream,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP\r
+\r
+  virtual ~CStdOutFileStream() {}\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/FilterCoder.cpp b/CPP/7zip/Common/FilterCoder.cpp
new file mode 100755 (executable)
index 0000000..03a2aa0
--- /dev/null
@@ -0,0 +1,247 @@
+// FilterCoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+\r
+#include "../../Common/Defs.h"\r
+\r
+#include "FilterCoder.h"\r
+#include "StreamUtils.h"\r
+\r
+static const UInt32 kBufferSize = 1 << 17;\r
+\r
+CFilterCoder::CFilterCoder()\r
+{\r
+  _buffer = (Byte *)::MidAlloc(kBufferSize);\r
+  if (_buffer == 0)\r
+    throw 1;\r
+}\r
+\r
+CFilterCoder::~CFilterCoder()\r
+{\r
+  ::MidFree(_buffer);\r
+}\r
+\r
+HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size)\r
+{\r
+  if (_outSizeIsDefined)\r
+  {\r
+    UInt64 remSize = _outSize - _nowPos64;\r
+    if (size > remSize)\r
+      size = (UInt32)remSize;\r
+  }\r
+  RINOK(WriteStream(outStream, _buffer, size));\r
+  _nowPos64 += size;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  RINOK(Init());\r
+  UInt32 bufferPos = 0;\r
+  _outSizeIsDefined = (outSize != 0);\r
+  if (_outSizeIsDefined)\r
+    _outSize = *outSize;\r
+\r
+  while (!_outSizeIsDefined || _nowPos64 < _outSize)\r
+  {\r
+    size_t processedSize = kBufferSize - bufferPos;\r
+    \r
+    // Change it: It can be optimized using ReadPart\r
+    RINOK(ReadStream(inStream, _buffer + bufferPos, &processedSize));\r
+    \r
+    UInt32 endPos = bufferPos + (UInt32)processedSize;\r
+\r
+    bufferPos = Filter->Filter(_buffer, endPos);\r
+    if (bufferPos > endPos)\r
+    {\r
+      for (; endPos < bufferPos; endPos++)\r
+        _buffer[endPos] = 0;\r
+      bufferPos = Filter->Filter(_buffer, endPos);\r
+    }\r
+\r
+    if (bufferPos == 0)\r
+    {\r
+      if (endPos == 0)\r
+        return S_OK;\r
+      return WriteWithLimit(outStream, endPos);\r
+    }\r
+    RINOK(WriteWithLimit(outStream, bufferPos));\r
+    if (progress != NULL)\r
+    {\r
+      RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64));\r
+    }\r
+    UInt32 i = 0;\r
+    while (bufferPos < endPos)\r
+      _buffer[i++] = _buffer[bufferPos++];\r
+    bufferPos = i;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream)\r
+{\r
+  _bufferPos = 0;\r
+  _outStream = outStream;\r
+  return Init();\r
+}\r
+\r
+STDMETHODIMP CFilterCoder::ReleaseOutStream()\r
+{\r
+  _outStream.Release();\r
+  return S_OK;\r
+}\r
+\r
+\r
+STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize != NULL)\r
+    *processedSize = 0;\r
+  while (size > 0)\r
+  {\r
+    UInt32 sizeTemp = MyMin(size, kBufferSize - _bufferPos);\r
+    memcpy(_buffer + _bufferPos, data, sizeTemp);\r
+    size -= sizeTemp;\r
+    if (processedSize != NULL)\r
+      *processedSize += sizeTemp;\r
+    data = (const Byte *)data + sizeTemp;\r
+    UInt32 endPos = _bufferPos + sizeTemp;\r
+    _bufferPos = Filter->Filter(_buffer, endPos);\r
+    if (_bufferPos == 0)\r
+    {\r
+      _bufferPos = endPos;\r
+      break;\r
+    }\r
+    if (_bufferPos > endPos)\r
+    {\r
+      if (size != 0)\r
+        return E_FAIL;\r
+      break;\r
+    }\r
+    RINOK(WriteWithLimit(_outStream, _bufferPos));\r
+    UInt32 i = 0;\r
+    while (_bufferPos < endPos)\r
+      _buffer[i++] = _buffer[_bufferPos++];\r
+    _bufferPos = i;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFilterCoder::Flush()\r
+{\r
+  if (_bufferPos != 0)\r
+  {\r
+    // _buffer contains only data refused by previous Filter->Filter call.\r
+    UInt32 endPos = Filter->Filter(_buffer, _bufferPos);\r
+    if (endPos > _bufferPos)\r
+    {\r
+      for (; _bufferPos < endPos; _bufferPos++)\r
+        _buffer[_bufferPos] = 0;\r
+      if (Filter->Filter(_buffer, endPos) != endPos)\r
+        return E_FAIL;\r
+    }\r
+    RINOK(WriteWithLimit(_outStream, _bufferPos));\r
+    _bufferPos = 0;\r
+  }\r
+  CMyComPtr<IOutStreamFlush> flush;\r
+  _outStream.QueryInterface(IID_IOutStreamFlush, &flush);\r
+  if (flush)\r
+    return flush->Flush();\r
+  return S_OK;\r
+}\r
+\r
+\r
+STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream)\r
+{\r
+  _convertedPosBegin = _convertedPosEnd = _bufferPos = 0;\r
+  _inStream = inStream;\r
+  return Init();\r
+}\r
+\r
+STDMETHODIMP CFilterCoder::ReleaseInStream()\r
+{\r
+  _inStream.Release();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize != NULL)\r
+    *processedSize = 0;\r
+  while (size > 0)\r
+  {\r
+    if (_convertedPosBegin != _convertedPosEnd)\r
+    {\r
+      UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin);\r
+      memcpy(data, _buffer + _convertedPosBegin, sizeTemp);\r
+      _convertedPosBegin += sizeTemp;\r
+      data = (void *)((Byte *)data + sizeTemp);\r
+      size -= sizeTemp;\r
+      if (processedSize != NULL)\r
+        *processedSize += sizeTemp;\r
+      break;\r
+    }\r
+    UInt32 i;\r
+    for (i = 0; _convertedPosEnd + i < _bufferPos; i++)\r
+      _buffer[i] = _buffer[_convertedPosEnd + i];\r
+    _bufferPos = i;\r
+    _convertedPosBegin = _convertedPosEnd = 0;\r
+    size_t processedSizeTemp = kBufferSize - _bufferPos;\r
+    RINOK(ReadStream(_inStream, _buffer + _bufferPos, &processedSizeTemp));\r
+    _bufferPos += (UInt32)processedSizeTemp;\r
+    _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);\r
+    if (_convertedPosEnd == 0)\r
+    {\r
+      if (_bufferPos == 0)\r
+        break;\r
+      _convertedPosEnd = _bufferPos; // check it\r
+      continue;\r
+    }\r
+    if (_convertedPosEnd > _bufferPos)\r
+    {\r
+      for (; _bufferPos < _convertedPosEnd; _bufferPos++)\r
+        _buffer[_bufferPos] = 0;\r
+      _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+#ifndef _NO_CRYPTO\r
+STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)\r
+{\r
+  return _setPassword->CryptoSetPassword(data, size);\r
+}\r
+#endif\r
+\r
+#ifndef EXTRACT_ONLY\r
+STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs,\r
+      const PROPVARIANT *properties, UInt32 numProperties)\r
+{\r
+  return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties);\r
+}\r
+\r
+STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)\r
+{\r
+  return _writeCoderProperties->WriteCoderProperties(outStream);\r
+}\r
+\r
+/*\r
+STDMETHODIMP CFilterCoder::ResetSalt()\r
+{\r
+  return _CryptoResetSalt->ResetSalt();\r
+}\r
+*/\r
+\r
+STDMETHODIMP CFilterCoder::ResetInitVector()\r
+{\r
+  return _CryptoResetInitVector->ResetInitVector();\r
+}\r
+#endif\r
+\r
+STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size)\r
+{\r
+  return _setDecoderProperties->SetDecoderProperties2(data, size);\r
+}\r
diff --git a/CPP/7zip/Common/FilterCoder.h b/CPP/7zip/Common/FilterCoder.h
new file mode 100755 (executable)
index 0000000..1b0125d
--- /dev/null
@@ -0,0 +1,128 @@
+// FilterCoder.h\r
+\r
+#ifndef __FILTER_CODER_H\r
+#define __FILTER_CODER_H\r
+\r
+#include "../../Common/MyCom.h"\r
+#include "../ICoder.h"\r
+#include "../IPassword.h"\r
+\r
+#define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) if (iid == IID_ ## i) \\r
+{ if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \\r
+*outObject = (void *)(i *)this; AddRef(); return S_OK; }\r
+\r
+class CFilterCoder:\r
+  public ICompressCoder,\r
+  public ICompressSetInStream,\r
+  public ISequentialInStream,\r
+  public ICompressSetOutStream,\r
+  public ISequentialOutStream,\r
+  public IOutStreamFlush,\r
+\r
+  #ifndef _NO_CRYPTO\r
+  public ICryptoSetPassword,\r
+  #endif\r
+  #ifndef EXTRACT_ONLY\r
+  public ICompressSetCoderProperties,\r
+  public ICompressWriteCoderProperties,\r
+  // public ICryptoResetSalt,\r
+  public ICryptoResetInitVector,\r
+  #endif\r
+  public ICompressSetDecoderProperties2,\r
+  public CMyUnknownImp\r
+{\r
+protected:\r
+  Byte *_buffer;\r
+  CMyComPtr<ISequentialInStream> _inStream;\r
+  CMyComPtr<ISequentialOutStream> _outStream;\r
+  UInt32 _bufferPos;\r
+  UInt32 _convertedPosBegin;\r
+  UInt32 _convertedPosEnd;\r
+  bool _outSizeIsDefined;\r
+  UInt64 _outSize;\r
+  UInt64 _nowPos64;\r
+\r
+  HRESULT Init()\r
+  {\r
+    _nowPos64 = 0;\r
+    _outSizeIsDefined = false;\r
+    return Filter->Init();\r
+  }\r
+\r
+  CMyComPtr<ICryptoSetPassword> _setPassword;\r
+  #ifndef EXTRACT_ONLY\r
+  CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties;\r
+  CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties;\r
+  // CMyComPtr<ICryptoResetSalt> _CryptoResetSalt;\r
+  CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector;\r
+  #endif\r
+  CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties;\r
+public:\r
+  CMyComPtr<ICompressFilter> Filter;\r
+\r
+  CFilterCoder();\r
+  ~CFilterCoder();\r
+  HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size);\r
+\r
+public:\r
+  MY_QUERYINTERFACE_BEGIN2(ICompressCoder)\r
+    MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)\r
+    MY_QUERYINTERFACE_ENTRY(ISequentialInStream)\r
+    MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream)\r
+    MY_QUERYINTERFACE_ENTRY(ISequentialOutStream)\r
+    MY_QUERYINTERFACE_ENTRY(IOutStreamFlush)\r
+\r
+    #ifndef _NO_CRYPTO\r
+    MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword)\r
+    #endif\r
+\r
+    #ifndef EXTRACT_ONLY\r
+    MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties)\r
+    MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties)\r
+    // MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt)\r
+    MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector)\r
+    #endif\r
+\r
+    MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties)\r
+  MY_QUERYINTERFACE_END\r
+  MY_ADDREF_RELEASE\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+  STDMETHOD(ReleaseInStream)();\r
+  STDMETHOD(SetInStream)(ISequentialInStream *inStream);\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \\r
+  STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);\r
+  STDMETHOD(ReleaseOutStream)();\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(Flush)();\r
+\r
+  #ifndef _NO_CRYPTO\r
+  STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);\r
+  #endif\r
+  #ifndef EXTRACT_ONLY\r
+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs,\r
+      const PROPVARIANT *properties, UInt32 numProperties);\r
+  STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);\r
+  // STDMETHOD(ResetSalt)();\r
+  STDMETHOD(ResetInitVector)();\r
+  #endif\r
+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);\r
+};\r
+\r
+class CInStreamReleaser\r
+{\r
+public:\r
+  CFilterCoder *FilterCoder;\r
+  CInStreamReleaser(): FilterCoder(0) {}\r
+  ~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); }\r
+};\r
+\r
+class COutStreamReleaser\r
+{\r
+public:\r
+  CFilterCoder *FilterCoder;\r
+  COutStreamReleaser(): FilterCoder(0) {}\r
+  ~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/InBuffer.cpp b/CPP/7zip/Common/InBuffer.cpp
new file mode 100755 (executable)
index 0000000..3f84f48
--- /dev/null
@@ -0,0 +1,83 @@
+// InBuffer.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+\r
+#include "InBuffer.h"\r
+\r
+CInBuffer::CInBuffer():\r
+  _buffer(0),\r
+  _bufferLimit(0),\r
+  _bufferBase(0),\r
+  _stream(0),\r
+  _bufferSize(0)\r
+{}\r
+\r
+bool CInBuffer::Create(UInt32 bufferSize)\r
+{\r
+  const UInt32 kMinBlockSize = 1;\r
+  if (bufferSize < kMinBlockSize)\r
+    bufferSize = kMinBlockSize;\r
+  if (_bufferBase != 0 && _bufferSize == bufferSize)\r
+    return true;\r
+  Free();\r
+  _bufferSize = bufferSize;\r
+  _bufferBase = (Byte *)::MidAlloc(bufferSize);\r
+  return (_bufferBase != 0);\r
+}\r
+\r
+void CInBuffer::Free()\r
+{\r
+  ::MidFree(_bufferBase);\r
+  _bufferBase = 0;\r
+}\r
+\r
+void CInBuffer::SetStream(ISequentialInStream *stream)\r
+{\r
+  _stream = stream;\r
+}\r
+\r
+void CInBuffer::Init()\r
+{\r
+  _processedSize = 0;\r
+  _buffer = _bufferBase;\r
+  _bufferLimit = _buffer;\r
+  _wasFinished = false;\r
+  #ifdef _NO_EXCEPTIONS\r
+  ErrorCode = S_OK;\r
+  #endif\r
+}\r
+\r
+bool CInBuffer::ReadBlock()\r
+{\r
+  #ifdef _NO_EXCEPTIONS\r
+  if (ErrorCode != S_OK)\r
+    return false;\r
+  #endif\r
+  if (_wasFinished)\r
+    return false;\r
+  _processedSize += (_buffer - _bufferBase);\r
+  UInt32 numProcessedBytes;\r
+  HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes);\r
+  #ifdef _NO_EXCEPTIONS\r
+  ErrorCode = result;\r
+  #else\r
+  if (result != S_OK)\r
+    throw CInBufferException(result);\r
+  #endif\r
+  _buffer = _bufferBase;\r
+  _bufferLimit = _buffer + numProcessedBytes;\r
+  _wasFinished = (numProcessedBytes == 0);\r
+  return (!_wasFinished);\r
+}\r
+\r
+Byte CInBuffer::ReadBlock2()\r
+{\r
+  if (!ReadBlock())\r
+  {\r
+    _processedSize++;\r
+    return 0xFF;\r
+  }\r
+  return *_buffer++;\r
+}\r
diff --git a/CPP/7zip/Common/InBuffer.h b/CPP/7zip/Common/InBuffer.h
new file mode 100755 (executable)
index 0000000..cdd50f1
--- /dev/null
@@ -0,0 +1,81 @@
+// InBuffer.h\r
+\r
+#ifndef __INBUFFER_H\r
+#define __INBUFFER_H\r
+\r
+#include "../IStream.h"\r
+#include "../../Common/MyCom.h"\r
+#include "../../Common/MyException.h"\r
+\r
+#ifndef _NO_EXCEPTIONS\r
+struct CInBufferException: public CSystemException\r
+{\r
+  CInBufferException(HRESULT errorCode): CSystemException(errorCode) {}\r
+};\r
+#endif\r
+\r
+class CInBuffer\r
+{\r
+  Byte *_buffer;\r
+  Byte *_bufferLimit;\r
+  Byte *_bufferBase;\r
+  CMyComPtr<ISequentialInStream> _stream;\r
+  UInt64 _processedSize;\r
+  UInt32 _bufferSize;\r
+  bool _wasFinished;\r
+\r
+  bool ReadBlock();\r
+  Byte ReadBlock2();\r
+\r
+public:\r
+  #ifdef _NO_EXCEPTIONS\r
+  HRESULT ErrorCode;\r
+  #endif\r
+\r
+  CInBuffer();\r
+  ~CInBuffer() { Free(); }\r
+\r
+  bool Create(UInt32 bufferSize);\r
+  void Free();\r
+  \r
+  void SetStream(ISequentialInStream *stream);\r
+  void Init();\r
+  void ReleaseStream() { _stream.Release(); }\r
+\r
+  bool ReadByte(Byte &b)\r
+  {\r
+    if (_buffer >= _bufferLimit)\r
+      if (!ReadBlock())\r
+        return false;\r
+    b = *_buffer++;\r
+    return true;\r
+  }\r
+  Byte ReadByte()\r
+  {\r
+    if (_buffer >= _bufferLimit)\r
+      return ReadBlock2();\r
+    return *_buffer++;\r
+  }\r
+  UInt32 ReadBytes(Byte *buf, UInt32 size)\r
+  {\r
+    if ((UInt32)(_bufferLimit - _buffer) >= size)\r
+    {\r
+      for (UInt32 i = 0; i < size; i++)\r
+        buf[i] = _buffer[i];\r
+      _buffer += size;\r
+      return size;\r
+    }\r
+    for (UInt32 i = 0; i < size; i++)\r
+    {\r
+      if (_buffer >= _bufferLimit)\r
+        if (!ReadBlock())\r
+          return i;\r
+      buf[i] = *_buffer++;\r
+    }\r
+    return size;\r
+  }\r
+  UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); }\r
+  bool WasFinished() const { return _wasFinished; }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/InMemStream.cpp b/CPP/7zip/Common/InMemStream.cpp
new file mode 100755 (executable)
index 0000000..d39ccf5
--- /dev/null
@@ -0,0 +1,222 @@
+// InMemStream.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include <stdio.h>\r
+\r
+#include "Windows/Thread.h"\r
+\r
+#include "InMemStream.h"\r
+#include "../../Common/Defs.h"\r
+\r
+void CStreamInfo::Free(IInMemStreamMtCallback *callback)\r
+{\r
+  for (int i = 0; i < Blocks.Size(); i++)\r
+  {\r
+    callback->FreeBlock(Blocks[i]);\r
+    Blocks[i] = 0;\r
+  }\r
+}\r
+\r
+bool CInMemStreamMt::Create(int numSubStreams, UInt64 subStreamSize)\r
+{\r
+  Free();\r
+  _subStreamSize = subStreamSize;\r
+  size_t blockSize = Callback->GetBlockSize();\r
+  for (int i = 0; i < numSubStreams; i++)\r
+  {\r
+    _streams.Add(CStreamInfo());\r
+    CStreamInfo &blocks = _streams.Back();\r
+    blocks.Create();\r
+    for (UInt64 j = 0; (UInt64)j * blockSize < _subStreamSize; j++)\r
+      blocks.Blocks.Add(0);\r
+  }\r
+  if (!_streamIndexAllocator.AllocateList(numSubStreams))\r
+    return false;\r
+  return true;\r
+}\r
+\r
+void CInMemStreamMt::Free()\r
+{\r
+  while(_streams.Size() > 0)\r
+  {\r
+    _streams.Back().Free(Callback);\r
+    _streams.DeleteBack();\r
+  }\r
+}\r
+\r
+HRESULT CInMemStreamMt::Read()\r
+{\r
+  for (;;)\r
+  {\r
+    // printf("\n_streamIndexAllocator.AllocateItem\n");\r
+    int index = _streamIndexAllocator.AllocateItem();\r
+    /*\r
+    if (_stopReading)\r
+      return E_ABORT;\r
+    */\r
+    // printf("\nread Index = %d\n", index);\r
+    CStreamInfo &blocks = _streams[index];\r
+    blocks.Init();\r
+    Callback->AddStreamIndexToQueue(index);\r
+\r
+    for (;;)\r
+    {\r
+      const Byte *p = (const Byte *)blocks.Blocks[blocks.LastBlockIndex];\r
+      if (p == 0)\r
+      {\r
+        void **pp = &blocks.Blocks[blocks.LastBlockIndex];\r
+        HRESULT res = Callback->AllocateBlock(pp);\r
+        p = (const Byte *)*pp;\r
+        RINOK(res);\r
+        if (p == 0)\r
+          return E_FAIL;\r
+      }\r
+      size_t blockSize = Callback->GetBlockSize();\r
+      UInt32 curSize = (UInt32)(blockSize - blocks.LastBlockPos);\r
+      UInt32 realProcessedSize;\r
+      UInt64 pos64 = (UInt64)blocks.LastBlockIndex * blockSize + blocks.LastBlockPos;\r
+      if (curSize > _subStreamSize - pos64)\r
+        curSize = (UInt32)(_subStreamSize - pos64);\r
+      RINOK(_stream->Read((void *)(p + blocks.LastBlockPos), curSize, &realProcessedSize));\r
+\r
+      blocks.Cs->Enter();\r
+      if (realProcessedSize == 0)\r
+      {\r
+        blocks.StreamWasFinished = true;\r
+        blocks.CanReadEvent->Set();\r
+        blocks.Cs->Leave();\r
+\r
+        Callback->AddStreamIndexToQueue(-1);\r
+        return S_OK;\r
+      }\r
+      \r
+      blocks.LastBlockPos += realProcessedSize;\r
+      if (blocks.LastBlockPos == blockSize)\r
+      {\r
+        blocks.LastBlockPos = 0;\r
+        blocks.LastBlockIndex++;\r
+      }\r
+      pos64 += realProcessedSize;\r
+      if (pos64 >= _subStreamSize)\r
+        blocks.StreamWasFinished = true;\r
+      blocks.CanReadEvent->Set();\r
+      blocks.Cs->Leave();\r
+      if (pos64 >= _subStreamSize)\r
+        break;\r
+    }\r
+  }\r
+}\r
+\r
+static THREAD_FUNC_DECL CoderThread(void *threadCoderInfo)\r
+{\r
+  ((CInMemStreamMt *)threadCoderInfo)->ReadResult = ((CInMemStreamMt *)threadCoderInfo)->Read();\r
+  return 0;\r
+}\r
+\r
+HRes CInMemStreamMt::StartReadThread()\r
+{\r
+  // _stopReading = false;\r
+  NWindows::CThread Thread;\r
+  return Thread.Create(CoderThread, this);\r
+}\r
+\r
+void CInMemStreamMt::FreeSubStream(int subStreamIndex)\r
+{\r
+  // printf("\nFreeSubStream\n");\r
+  _streams[subStreamIndex].Free(Callback);\r
+  _streamIndexAllocator.FreeItem(subStreamIndex);\r
+  // printf("\nFreeSubStream end\n");\r
+}\r
+\r
+HRESULT CInMemStreamMt::ReadSubStream(int subStreamIndex, void *data, UInt32 size, UInt32 *processedSize, bool keepData)\r
+{\r
+  if (processedSize != NULL)\r
+    *processedSize = 0;\r
+  CStreamInfo &blocks = _streams[subStreamIndex];\r
+  while (size > 0)\r
+  {\r
+    if (blocks.CurBlockPos == Callback->GetBlockSize())\r
+    {\r
+      blocks.CurBlockPos = 0;\r
+      blocks.CurBlockIndex++;\r
+    }\r
+    UInt32 curSize;\r
+    UInt32 curPos = blocks.CurBlockPos;\r
+    \r
+    blocks.Cs->Enter();\r
+    if (blocks.CurBlockIndex == blocks.LastBlockIndex)\r
+    {\r
+      curSize = blocks.LastBlockPos - curPos;\r
+      if (curSize == 0)\r
+      {\r
+        if (blocks.StreamWasFinished)\r
+        {\r
+          blocks.Cs->Leave();\r
+          void *p = blocks.Blocks[blocks.CurBlockIndex];\r
+          if (p != 0 && !keepData)\r
+          {\r
+            Callback->FreeBlock(p);\r
+            blocks.Blocks[blocks.CurBlockIndex] = 0;\r
+          }\r
+          return S_OK;\r
+        }\r
+        blocks.CanReadEvent->Reset();\r
+        blocks.Cs->Leave();\r
+        // printf("\nBlock Lock\n");\r
+        blocks.CanReadEvent->Lock();\r
+        // printf("\nAfter Lock\n");\r
+        if (blocks.ExitResult != S_OK)\r
+          return blocks.ExitResult;\r
+        continue;\r
+      }\r
+    }\r
+    else\r
+      curSize = Callback->GetBlockSize() - curPos;\r
+    blocks.Cs->Leave();\r
+    \r
+    if (curSize > size)\r
+      curSize = size;\r
+    void *p = blocks.Blocks[blocks.CurBlockIndex];\r
+    memmove(data, (const Byte *)p + curPos, curSize);\r
+    data = (void *)((Byte *)data + curSize);\r
+    size -= curSize;\r
+    if (processedSize != NULL)\r
+      *processedSize += curSize;\r
+    curPos += curSize;\r
+    \r
+    bool needFree = false;\r
+    blocks.CurBlockPos = curPos;\r
+\r
+    if (curPos == Callback->GetBlockSize())\r
+      needFree = true;\r
+    blocks.Cs->Enter();\r
+    if (blocks.CurBlockIndex == blocks.LastBlockIndex &&\r
+        blocks.CurBlockPos == blocks.LastBlockPos &&\r
+        blocks.StreamWasFinished)\r
+      needFree = true;\r
+    blocks.Cs->Leave();\r
+\r
+    if (needFree && !keepData)\r
+    {\r
+      Callback->FreeBlock(p);\r
+      blocks.Blocks[blocks.CurBlockIndex] = 0;\r
+    }\r
+    return S_OK;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CInMemStream::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  UInt32 realProcessedSize;\r
+  HRESULT result = mtStream->ReadSubStream(Index, data, size, &realProcessedSize, _keepData);\r
+  if (processedSize != NULL)\r
+    *processedSize = realProcessedSize;\r
+  if (realProcessedSize != 0)\r
+  {\r
+    // printf("\ns = %d\n", Index);\r
+  }\r
+  _size += realProcessedSize;\r
+  return result;\r
+}\r
diff --git a/CPP/7zip/Common/InMemStream.h b/CPP/7zip/Common/InMemStream.h
new file mode 100755 (executable)
index 0000000..e2e9fb3
--- /dev/null
@@ -0,0 +1,284 @@
+// InMemStream.h\r
+\r
+#ifndef __IN_MEM_STREAM_H\r
+#define __IN_MEM_STREAM_H\r
+\r
+#include <stdio.h>\r
+\r
+#include "../../../C/Alloc.h"\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "MemBlocks.h"\r
+\r
+class CIntListCheck\r
+{\r
+protected:\r
+  int *_data;\r
+public:\r
+  CIntListCheck(): _data(0) {}\r
+  ~CIntListCheck() { FreeList(); }\r
+  \r
+  bool AllocateList(int numItems)\r
+  {\r
+    FreeList();\r
+    if (numItems == 0)\r
+      return true;\r
+    _data = (int *)::MyAlloc(numItems * sizeof(int));\r
+    return (_data != 0);\r
+  }\r
+  \r
+  void FreeList()\r
+  {\r
+    ::MyFree(_data);\r
+    _data = 0;\r
+  }\r
+};\r
+\r
+\r
+class CResourceList : public CIntListCheck\r
+{\r
+  int _headFree;\r
+public:\r
+  CResourceList(): _headFree(-1) {}\r
+  \r
+  bool AllocateList(int numItems)\r
+  {\r
+    FreeList();\r
+    if (numItems == 0)\r
+      return true;\r
+    if (!CIntListCheck::AllocateList(numItems))\r
+      return false;\r
+    for (int i = 0; i < numItems; i++)\r
+      _data[i] = i + 1;\r
+    _data[numItems - 1] = -1;\r
+    _headFree = 0;\r
+    return true;\r
+  }\r
+  \r
+  void FreeList()\r
+  {\r
+    CIntListCheck::FreeList();\r
+    _headFree = -1;\r
+  }\r
+  \r
+  int AllocateItem()\r
+  {\r
+    int res = _headFree;\r
+    if (res >= 0)\r
+      _headFree = _data[res];\r
+    return res;\r
+  }\r
+  \r
+  void FreeItem(int index)\r
+  {\r
+    if (index < 0)\r
+      return;\r
+    _data[index] = _headFree;\r
+    _headFree = index;\r
+  }\r
+};\r
+\r
+class CResourceListMt: public CResourceList\r
+{\r
+  NWindows::NSynchronization::CCriticalSection _criticalSection;\r
+public:\r
+  NWindows::NSynchronization::CSemaphore Semaphore;\r
+\r
+  HRes AllocateList(int numItems)\r
+  {\r
+    if (!CResourceList::AllocateList(numItems))\r
+      return E_OUTOFMEMORY;\r
+    Semaphore.Close();\r
+    return Semaphore.Create(numItems, numItems);\r
+  }\r
+\r
+  int AllocateItem()\r
+  {\r
+    Semaphore.Lock();\r
+    _criticalSection.Enter();\r
+    int res = CResourceList::AllocateItem();\r
+    _criticalSection.Leave();\r
+    return res;\r
+  }\r
+  \r
+  void FreeItem(int index)\r
+  {\r
+    if (index < 0)\r
+      return;\r
+    _criticalSection.Enter();\r
+    CResourceList::FreeItem(index);\r
+    _criticalSection.Leave();\r
+    Semaphore.Release();\r
+  }\r
+};\r
+\r
+class CIntQueueMt: public CIntListCheck\r
+{\r
+  int _numItems;\r
+  int _head;\r
+  int _cur;\r
+public:\r
+  CIntQueueMt(): _numItems(0), _head(0),  _cur(0) {}\r
+  NWindows::NSynchronization::CSemaphore Semaphore;\r
+\r
+  HRes AllocateList(int numItems)\r
+  {\r
+    FreeList();\r
+    if (numItems == 0)\r
+      return S_OK;\r
+    if (!CIntListCheck::AllocateList(numItems))\r
+      return E_OUTOFMEMORY;\r
+    _numItems = numItems;\r
+    return Semaphore.Create(0, numItems);\r
+  }\r
+\r
+  void FreeList()\r
+  {\r
+    CIntListCheck::FreeList();\r
+    _numItems = 0;\r
+    _head = 0;\r
+    _cur = 0;\r
+  }\r
+\r
+  void AddItem(int value)\r
+  {\r
+    _data[_head++] = value;\r
+    if (_head == _numItems)\r
+      _head = 0;\r
+    Semaphore.Release();\r
+    // printf("\nRelease prev = %d\n", previousCount);\r
+  }\r
+  \r
+  int GetItem()\r
+  {\r
+    // Semaphore.Lock();\r
+    int res = _data[_cur++];\r
+    if (_cur == _numItems)\r
+      _cur = 0;\r
+    return res;\r
+  }\r
+};\r
+\r
+struct IInMemStreamMtCallback\r
+{\r
+  // must be same for all calls\r
+  virtual size_t GetBlockSize() = 0;\r
+  \r
+  // Out:\r
+  //  result != S_OK stops Reading\r
+  //   if *p = 0, result must be != S_OK;\r
+  // Locking is allowed\r
+  virtual HRESULT AllocateBlock(void **p) = 0;\r
+\r
+  virtual void FreeBlock(void *p) = 0;\r
+\r
+  // It must allow to add at least numSubStreams + 1 ,\r
+  // where numSubStreams is value from CInMemStreamMt::Create\r
+  // value -1 means End of stream\r
+  // Locking is not allowed\r
+  virtual void AddStreamIndexToQueue(int index) = 0;\r
+};\r
+\r
+struct CStreamInfo\r
+{\r
+  CRecordVector<void *> Blocks;\r
+\r
+  int LastBlockIndex;\r
+  size_t LastBlockPos;\r
+  bool StreamWasFinished;\r
+\r
+  int CurBlockIndex;\r
+  size_t CurBlockPos;\r
+\r
+  NWindows::NSynchronization::CCriticalSection *Cs;\r
+  NWindows::NSynchronization::CManualResetEvent *CanReadEvent;\r
+\r
+  HRESULT ExitResult;\r
+\r
+  CStreamInfo(): Cs(0), CanReadEvent(0), StreamWasFinished(false) { }\r
+  ~CStreamInfo()\r
+  {\r
+    delete Cs;\r
+    delete CanReadEvent;\r
+    // Free();\r
+  }\r
+  void Create()\r
+  {\r
+    Cs = new NWindows::NSynchronization::CCriticalSection;\r
+    CanReadEvent = new NWindows::NSynchronization::CManualResetEvent;\r
+  }\r
+\r
+  void Free(IInMemStreamMtCallback *callback);\r
+  void Init()\r
+  {\r
+    LastBlockIndex = CurBlockIndex = 0;\r
+    CurBlockPos = LastBlockPos = 0;\r
+    StreamWasFinished = false;\r
+    ExitResult = S_OK;\r
+  }\r
+\r
+  // res must be != S_OK\r
+  void Exit(HRESULT res)\r
+  {\r
+    ExitResult = res;\r
+    CanReadEvent->Set();\r
+  }\r
+};\r
+\r
+\r
+class CInMemStreamMt\r
+{\r
+  CMyComPtr<ISequentialInStream> _stream;\r
+  NWindows::NSynchronization::CCriticalSection CS;\r
+  CObjectVector<CStreamInfo> _streams;\r
+  int _nextFreeStreamIndex;\r
+  int _currentStreamIndex;\r
+  UInt64 _subStreamSize;\r
+\r
+  CResourceListMt _streamIndexAllocator;\r
+\r
+  // bool _stopReading;\r
+\r
+public:\r
+  HRESULT Read();\r
+  HRESULT ReadResult;\r
+  IInMemStreamMtCallback *Callback;\r
+  void FreeSubStream(int subStreamIndex);\r
+  HRESULT ReadSubStream(int subStreamIndex, void *data, UInt32 size, UInt32 *processedSize, bool keepData);\r
+\r
+  // numSubStreams: min = 1, good min = numThreads\r
+  bool Create(int numSubStreams, UInt64 subStreamSize);\r
+  ~CInMemStreamMt() { Free(); }\r
+  void SetStream(ISequentialInStream *stream) { _stream = stream; }\r
+  \r
+  // to stop reading you must implement\r
+  // returning Error in IInMemStreamMtCallback::AllocateBlock\r
+  // and then you must free at least one substream\r
+  HRes StartReadThread();\r
+\r
+  void Free();\r
+\r
+  // you must free at least one substream after that function to unlock waiting.\r
+  // void StopReading() { _stopReading = true; }\r
+};\r
+\r
+class CInMemStream:\r
+  public ISequentialInStream,\r
+  public CMyUnknownImp\r
+{\r
+  UInt64 _size;\r
+  bool _keepData;\r
+public:\r
+  int Index;\r
+  CInMemStreamMt *mtStream;\r
+  void Init(bool keepData = false)\r
+  {\r
+    _size = 0; _keepData = keepData ;\r
+  }\r
+  MY_UNKNOWN_IMP\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  UInt64 GetSize() const { return _size; }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/InOutTempBuffer.cpp b/CPP/7zip/Common/InOutTempBuffer.cpp
new file mode 100755 (executable)
index 0000000..13a7696
--- /dev/null
@@ -0,0 +1,122 @@
+// InOutTempBuffer.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/7zCrc.h"\r
+\r
+#include "InOutTempBuffer.h"\r
+#include "StreamUtils.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+using namespace NDirectory;\r
+\r
+static const UInt32 kTempBufSize = (1 << 20);\r
+\r
+static LPCTSTR kTempFilePrefixString = TEXT("7zt");\r
+\r
+CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { }\r
+\r
+void CInOutTempBuffer::Create()\r
+{\r
+  if (!_buf)\r
+    _buf = new Byte[kTempBufSize];\r
+}\r
+\r
+CInOutTempBuffer::~CInOutTempBuffer()\r
+{\r
+  delete []_buf;\r
+}\r
+\r
+void CInOutTempBuffer::InitWriting()\r
+{\r
+  _bufPos = 0;\r
+  _tempFileCreated = false;\r
+  _size = 0;\r
+  _crc = CRC_INIT_VAL;\r
+}\r
+\r
+bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size)\r
+{\r
+  if (size == 0)\r
+    return true;\r
+  if (!_tempFileCreated)\r
+  {\r
+    CSysString tempDirPath;\r
+    if (!MyGetTempPath(tempDirPath))\r
+      return false;\r
+    if (_tempFile.Create(tempDirPath, kTempFilePrefixString, _tempFileName) == 0)\r
+      return false;\r
+    if (!_outFile.Create(_tempFileName, true))\r
+      return false;\r
+    _tempFileCreated = true;\r
+  }\r
+  UInt32 processed;\r
+  if (!_outFile.Write(data, size, processed))\r
+    return false;\r
+  _crc = CrcUpdate(_crc, data, processed);\r
+  _size += processed;\r
+  return (processed == size);\r
+}\r
+\r
+bool CInOutTempBuffer::Write(const void *data, UInt32 size)\r
+{\r
+  if (_bufPos < kTempBufSize)\r
+  {\r
+    UInt32 cur = MyMin(kTempBufSize - _bufPos, size);\r
+    memcpy(_buf + _bufPos, data, cur);\r
+    _crc = CrcUpdate(_crc, data, cur);\r
+    _bufPos += cur;\r
+    size -= cur;\r
+    data = ((const Byte *)data) + cur;\r
+    _size += cur;\r
+  }\r
+  return WriteToFile(data, size);\r
+}\r
+\r
+HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream)\r
+{\r
+  if (!_outFile.Close())\r
+    return E_FAIL;\r
+\r
+  UInt64 size = 0;\r
+  UInt32 crc = CRC_INIT_VAL;\r
+\r
+  if (_bufPos > 0)\r
+  {\r
+    RINOK(WriteStream(stream, _buf, _bufPos));\r
+    crc = CrcUpdate(crc, _buf, _bufPos);\r
+    size += _bufPos;\r
+  }\r
+  if (_tempFileCreated)\r
+  {\r
+    NIO::CInFile inFile;\r
+    if (!inFile.Open(_tempFileName))\r
+      return E_FAIL;\r
+    while (size < _size)\r
+    {\r
+      UInt32 processed;\r
+      if (!inFile.ReadPart(_buf, kTempBufSize, processed))\r
+        return E_FAIL;\r
+      if (processed == 0)\r
+        break;\r
+      RINOK(WriteStream(stream, _buf, processed));\r
+      crc = CrcUpdate(crc, _buf, processed);\r
+      size += processed;\r
+    }\r
+  }\r
+  return (_crc == crc && size == _size) ? S_OK : E_FAIL;\r
+}\r
+\r
+STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processed)\r
+{\r
+  if (!_buf->Write(data, size))\r
+  {\r
+    if (processed != NULL)\r
+      *processed = 0;\r
+    return E_FAIL;\r
+  }\r
+  if (processed != NULL)\r
+    *processed = size;\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/Common/InOutTempBuffer.h b/CPP/7zip/Common/InOutTempBuffer.h
new file mode 100755 (executable)
index 0000000..a69bc85
--- /dev/null
@@ -0,0 +1,48 @@
+// InOutTempBuffer.h\r
+\r
+#ifndef __IN_OUT_TEMP_BUFFER_H\r
+#define __IN_OUT_TEMP_BUFFER_H\r
+\r
+#include "../../Common/MyCom.h"\r
+#include "../../Windows/FileDir.h"\r
+#include "../../Windows/FileIO.h"\r
+\r
+#include "../IStream.h"\r
+\r
+class CInOutTempBuffer\r
+{\r
+  NWindows::NFile::NDirectory::CTempFile _tempFile;\r
+  NWindows::NFile::NIO::COutFile _outFile;\r
+  Byte *_buf;\r
+  UInt32 _bufPos;\r
+  CSysString _tempFileName;\r
+  bool _tempFileCreated;\r
+  UInt64 _size;\r
+  UInt32 _crc;\r
+\r
+  bool WriteToFile(const void *data, UInt32 size);\r
+public:\r
+  CInOutTempBuffer();\r
+  ~CInOutTempBuffer();\r
+  void Create();\r
+\r
+  void InitWriting();\r
+  bool Write(const void *data, UInt32 size);\r
+\r
+  HRESULT WriteToStream(ISequentialOutStream *stream);\r
+  UInt64 GetDataSize() const { return _size; }\r
+};\r
+\r
+class CSequentialOutTempBufferImp:\r
+  public ISequentialOutStream,\r
+  public CMyUnknownImp\r
+{\r
+  CInOutTempBuffer *_buf;\r
+public:\r
+  void Init(CInOutTempBuffer *buffer)  { _buf = buffer; }\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp
new file mode 100755 (executable)
index 0000000..dd2d2d5
--- /dev/null
@@ -0,0 +1,154 @@
+// LimitedStreams.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "LimitedStreams.h"\r
+#include "../../Common/Defs.h"\r
+\r
+STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  UInt32 realProcessedSize = 0;\r
+  UInt32 sizeToRead = (UInt32)MyMin((_size - _pos), (UInt64)size);\r
+  HRESULT result = S_OK;\r
+  if (sizeToRead > 0)\r
+  {\r
+    result = _stream->Read(data, sizeToRead, &realProcessedSize);\r
+    _pos += realProcessedSize;\r
+    if (realProcessedSize == 0)\r
+      _wasFinished = true;\r
+  }\r
+  if (processedSize != NULL)\r
+    *processedSize = realProcessedSize;\r
+  return result;\r
+}\r
+\r
+STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize != NULL)\r
+    *processedSize = 0;\r
+  if (_virtPos >= _size)\r
+    return (_virtPos == _size) ? S_OK: E_FAIL;\r
+  UInt64 rem = _size - _virtPos;\r
+  if (rem < size)\r
+    size = (UInt32)rem;\r
+  UInt64 newPos = _startOffset + _virtPos;\r
+  if (newPos != _physPos)\r
+  {\r
+    _physPos = newPos;\r
+    RINOK(SeekToPhys());\r
+  }\r
+  HRESULT res = _stream->Read(data, size, &size);\r
+  if (processedSize != NULL)\r
+    *processedSize = size;\r
+  _physPos += size;\r
+  _virtPos += size;\r
+  return res;\r
+}\r
+\r
+STDMETHODIMP CLimitedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)\r
+{\r
+  switch(seekOrigin)\r
+  {\r
+    case STREAM_SEEK_SET: _virtPos = offset; break;\r
+    case STREAM_SEEK_CUR: _virtPos += offset; break;\r
+    case STREAM_SEEK_END: _virtPos = _size + offset; break;\r
+    default: return STG_E_INVALIDFUNCTION;\r
+  }\r
+  if (newPosition)\r
+    *newPosition = _virtPos;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize != NULL)\r
+    *processedSize = 0;\r
+  if (_virtPos >= Size)\r
+    return (_virtPos == Size) ? S_OK: E_FAIL;\r
+\r
+  if (_curRem == 0)\r
+  {\r
+    UInt32 blockSize = (UInt32)1 << BlockSizeLog;\r
+    UInt32 virtBlock = (UInt32)(_virtPos >> BlockSizeLog);\r
+    UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1);\r
+    UInt32 phyBlock = Vector[virtBlock];\r
+    UInt64 newPos = StartOffset + ((UInt64)phyBlock << BlockSizeLog) + offsetInBlock;\r
+    if (newPos != _physPos)\r
+    {\r
+      _physPos = newPos;\r
+      RINOK(SeekToPhys());\r
+    }\r
+    _curRem = blockSize - offsetInBlock;\r
+    for (int i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++)\r
+      _curRem += (UInt32)1 << BlockSizeLog;\r
+    UInt64 rem = Size - _virtPos;\r
+    if (_curRem > rem)\r
+      _curRem = (UInt32)rem;\r
+  }\r
+  if (size > _curRem)\r
+    size = _curRem;\r
+  HRESULT res = Stream->Read(data, size, &size);\r
+  if (processedSize != NULL)\r
+    *processedSize = size;\r
+  _physPos += size;\r
+  _virtPos += size;\r
+  _curRem -= size;\r
+  return res;\r
+}\r
\r
+STDMETHODIMP CClusterInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)\r
+{\r
+  UInt64 newVirtPos = offset;\r
+  switch(seekOrigin)\r
+  {\r
+    case STREAM_SEEK_SET: break;\r
+    case STREAM_SEEK_CUR: newVirtPos += _virtPos; break;\r
+    case STREAM_SEEK_END: newVirtPos += Size; break;\r
+    default: return STG_E_INVALIDFUNCTION;\r
+  }\r
+  if (_virtPos != newVirtPos)\r
+    _curRem = 0;\r
+  _virtPos = newVirtPos;\r
+  if (newPosition)\r
+    *newPosition = newVirtPos;\r
+  return S_OK;\r
+}\r
+\r
+\r
+HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream)\r
+{\r
+  *resStream = 0;\r
+  CLimitedInStream *streamSpec = new CLimitedInStream;\r
+  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;\r
+  streamSpec->SetStream(inStream);\r
+  RINOK(streamSpec->InitAndSeek(pos, size));\r
+  streamSpec->SeekToStart();\r
+  *resStream = streamTemp.Detach();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  HRESULT result = S_OK;\r
+  if (processedSize != NULL)\r
+    *processedSize = 0;\r
+  if (size > _size)\r
+  {\r
+    if (_size == 0)\r
+    {\r
+      _overflow = true;\r
+      if (!_overflowIsAllowed)\r
+        return E_FAIL;\r
+      if (processedSize != NULL)\r
+        *processedSize = size;\r
+      return S_OK;\r
+    }\r
+    size = (UInt32)_size;\r
+  }\r
+  if (_stream)\r
+    result = _stream->Write(data, size, &size);\r
+  _size -= size;\r
+  if (processedSize != NULL)\r
+    *processedSize = size;\r
+  return result;\r
+}\r
diff --git a/CPP/7zip/Common/LimitedStreams.h b/CPP/7zip/Common/LimitedStreams.h
new file mode 100755 (executable)
index 0000000..caec98f
--- /dev/null
@@ -0,0 +1,125 @@
+// LimitedStreams.h\r
+\r
+#ifndef __LIMITED_STREAMS_H\r
+#define __LIMITED_STREAMS_H\r
+\r
+#include "../../Common/MyCom.h"\r
+#include "../../Common/MyVector.h"\r
+#include "../IStream.h"\r
+\r
+class CLimitedSequentialInStream:\r
+  public ISequentialInStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<ISequentialInStream> _stream;\r
+  UInt64 _size;\r
+  UInt64 _pos;\r
+  bool _wasFinished;\r
+public:\r
+  void SetStream(ISequentialInStream *stream) { _stream = stream; }\r
+  void ReleaseStream() { _stream.Release(); }\r
+  void Init(UInt64 streamSize)\r
+  {\r
+    _size = streamSize;\r
+    _pos = 0;\r
+    _wasFinished = false;\r
+  }\r
\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  UInt64 GetSize() const { return _pos; }\r
+  bool WasFinished() const { return _wasFinished; }\r
+};\r
+\r
+class CLimitedInStream:\r
+  public IInStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<IInStream> _stream;\r
+  UInt64 _virtPos;\r
+  UInt64 _physPos;\r
+  UInt64 _size;\r
+  UInt64 _startOffset;\r
+\r
+  HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }\r
+public:\r
+  void SetStream(IInStream *stream) { _stream = stream; }\r
+  HRESULT InitAndSeek(UInt64 startOffset, UInt64 size)\r
+  {\r
+    _startOffset = startOffset;\r
+    _physPos = startOffset;\r
+    _virtPos = 0;\r
+    _size = size;\r
+    return SeekToPhys();\r
+  }\r
\r
+  MY_UNKNOWN_IMP1(IInStream)\r
+\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);\r
+\r
+  HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); }\r
+};\r
+\r
+class CClusterInStream:\r
+  public IInStream,\r
+  public CMyUnknownImp\r
+{\r
+  UInt64 _virtPos;\r
+  UInt64 _physPos;\r
+  UInt32 _curRem;\r
+public:\r
+  CMyComPtr<IInStream> Stream;\r
+  UInt64 StartOffset;\r
+  UInt64 Size;\r
+  int BlockSizeLog;\r
+  CRecordVector<UInt32> Vector;\r
+\r
+  HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }\r
+\r
+  HRESULT InitAndSeek()\r
+  {\r
+    _curRem = 0;\r
+    _virtPos = 0;\r
+    _physPos = StartOffset;\r
+    if (Vector.Size() > 0)\r
+    {\r
+      _physPos = StartOffset + (Vector[0] << BlockSizeLog);\r
+      return SeekToPhys();\r
+    }\r
+    return S_OK;\r
+  }\r
+\r
+  MY_UNKNOWN_IMP1(IInStream)\r
+\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);\r
+};\r
+\r
+HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream);\r
+\r
+class CLimitedSequentialOutStream:\r
+  public ISequentialOutStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<ISequentialOutStream> _stream;\r
+  UInt64 _size;\r
+  bool _overflow;\r
+  bool _overflowIsAllowed;\r
+public:\r
+  MY_UNKNOWN_IMP\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+  void SetStream(ISequentialOutStream *stream) { _stream = stream; }\r
+  void ReleaseStream() { _stream.Release(); }\r
+  void Init(UInt64 size, bool overflowIsAllowed = false)\r
+  {\r
+    _size = size;\r
+    _overflow = false;\r
+    _overflowIsAllowed = overflowIsAllowed;\r
+  }\r
+  bool IsFinishedOK() const { return (_size == 0 && !_overflow); }\r
+  UInt64 GetRem() const { return _size; }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/LockedStream.cpp b/CPP/7zip/Common/LockedStream.cpp
new file mode 100755 (executable)
index 0000000..d1bbf6d
--- /dev/null
@@ -0,0 +1,23 @@
+// LockedStream.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "LockedStream.h"\r
+\r
+HRESULT CLockedInStream::Read(UInt64 startPos, void *data, UInt32 size,\r
+  UInt32 *processedSize)\r
+{\r
+  NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);\r
+  RINOK(_stream->Seek(startPos, STREAM_SEEK_SET, NULL));\r
+  return _stream->Read(data, size, processedSize);\r
+}\r
+\r
+STDMETHODIMP CLockedSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  UInt32 realProcessedSize = 0;\r
+  HRESULT result = _lockedInStream->Read(_pos, data, size, &realProcessedSize);\r
+  _pos += realProcessedSize;\r
+  if (processedSize != NULL)\r
+    *processedSize = realProcessedSize;\r
+  return result;\r
+}\r
diff --git a/CPP/7zip/Common/LockedStream.h b/CPP/7zip/Common/LockedStream.h
new file mode 100755 (executable)
index 0000000..e12e22a
--- /dev/null
@@ -0,0 +1,38 @@
+// LockedStream.h\r
+\r
+#ifndef __LOCKEDSTREAM_H\r
+#define __LOCKEDSTREAM_H\r
+\r
+#include "../../Windows/Synchronization.h"\r
+#include "../../Common/MyCom.h"\r
+#include "../IStream.h"\r
+\r
+class CLockedInStream\r
+{\r
+  CMyComPtr<IInStream> _stream;\r
+  NWindows::NSynchronization::CCriticalSection _criticalSection;\r
+public:\r
+  void Init(IInStream *stream)\r
+    { _stream = stream; }\r
+  HRESULT Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize);\r
+};\r
+\r
+class CLockedSequentialInStreamImp:\r
+  public ISequentialInStream,\r
+  public CMyUnknownImp\r
+{\r
+  CLockedInStream *_lockedInStream;\r
+  UInt64 _pos;\r
+public:\r
+  void Init(CLockedInStream *lockedInStream, UInt64 startPos)\r
+  {\r
+    _lockedInStream = lockedInStream;\r
+    _pos = startPos;\r
+  }\r
+\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/MemBlocks.cpp b/CPP/7zip/Common/MemBlocks.cpp
new file mode 100755 (executable)
index 0000000..b7bcb56
--- /dev/null
@@ -0,0 +1,183 @@
+// MemBlocks.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+\r
+#include "MemBlocks.h"\r
+#include "StreamUtils.h"\r
+\r
+bool CMemBlockManager::AllocateSpace(size_t numBlocks)\r
+{\r
+  FreeSpace();\r
+  if (_blockSize < sizeof(void *) || numBlocks < 1)\r
+    return false;\r
+  size_t totalSize = numBlocks * _blockSize;\r
+  if (totalSize / _blockSize != numBlocks)\r
+    return false;\r
+  _data = ::MidAlloc(totalSize);\r
+  if (_data == 0)\r
+    return false;\r
+  Byte *p = (Byte *)_data;\r
+  for (size_t i = 0; i + 1 < numBlocks; i++, p += _blockSize)\r
+    *(Byte **)p = (p + _blockSize);\r
+  *(Byte **)p = 0;\r
+  _headFree = _data;\r
+  return true;\r
+}\r
+\r
+void CMemBlockManager::FreeSpace()\r
+{\r
+  ::MidFree(_data);\r
+  _data = 0;\r
+  _headFree= 0;\r
+}\r
+\r
+void *CMemBlockManager::AllocateBlock()\r
+{\r
+  if (_headFree == 0)\r
+    return 0;\r
+  void *p = _headFree;\r
+  _headFree = *(void **)_headFree;\r
+  return p;\r
+}\r
+\r
+void CMemBlockManager::FreeBlock(void *p)\r
+{\r
+  if (p == 0)\r
+    return;\r
+  *(void **)p = _headFree;\r
+  _headFree = p;\r
+}\r
+\r
+\r
+HRes CMemBlockManagerMt::AllocateSpace(size_t numBlocks, size_t numNoLockBlocks)\r
+{\r
+  if (numNoLockBlocks > numBlocks)\r
+    return E_INVALIDARG;\r
+  if (!CMemBlockManager::AllocateSpace(numBlocks))\r
+    return E_OUTOFMEMORY;\r
+  size_t numLockBlocks = numBlocks - numNoLockBlocks;\r
+  Semaphore.Close();\r
+  return Semaphore.Create((LONG)numLockBlocks, (LONG)numLockBlocks);\r
+}\r
+\r
+HRes CMemBlockManagerMt::AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks)\r
+{\r
+  if (numNoLockBlocks > desiredNumberOfBlocks)\r
+    return E_INVALIDARG;\r
+  for (;;)\r
+  {\r
+    if (AllocateSpace(desiredNumberOfBlocks, numNoLockBlocks) == 0)\r
+      return 0;\r
+    if (desiredNumberOfBlocks == numNoLockBlocks)\r
+      return E_OUTOFMEMORY;\r
+    desiredNumberOfBlocks = numNoLockBlocks + ((desiredNumberOfBlocks - numNoLockBlocks) >> 1);\r
+  }\r
+}\r
+\r
+void CMemBlockManagerMt::FreeSpace()\r
+{\r
+  Semaphore.Close();\r
+  CMemBlockManager::FreeSpace();\r
+}\r
+\r
+void *CMemBlockManagerMt::AllocateBlock()\r
+{\r
+  // Semaphore.Lock();\r
+  NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);\r
+  return CMemBlockManager::AllocateBlock();\r
+}\r
+\r
+void CMemBlockManagerMt::FreeBlock(void *p, bool lockMode)\r
+{\r
+  if (p == 0)\r
+    return;\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);\r
+    CMemBlockManager::FreeBlock(p);\r
+  }\r
+  if (lockMode)\r
+    Semaphore.Release();\r
+}\r
+\r
+void CMemBlocks::Free(CMemBlockManagerMt *manager)\r
+{\r
+  while(Blocks.Size() > 0)\r
+  {\r
+    manager->FreeBlock(Blocks.Back());\r
+    Blocks.DeleteBack();\r
+  }\r
+  TotalSize = 0;\r
+}\r
+\r
+void CMemBlocks::FreeOpt(CMemBlockManagerMt *manager)\r
+{\r
+  Free(manager);\r
+  Blocks.ClearAndFree();\r
+}\r
+\r
+HRESULT CMemBlocks::WriteToStream(size_t blockSize, ISequentialOutStream *outStream) const\r
+{\r
+  UInt64 totalSize = TotalSize;\r
+  for (int blockIndex = 0; totalSize > 0; blockIndex++)\r
+  {\r
+    UInt32 curSize = (UInt32)blockSize;\r
+    if (totalSize < curSize)\r
+      curSize = (UInt32)totalSize;\r
+    if (blockIndex >= Blocks.Size())\r
+      return E_FAIL;\r
+    RINOK(WriteStream(outStream, Blocks[blockIndex], curSize));\r
+    totalSize -= curSize;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+\r
+void CMemLockBlocks::FreeBlock(int index, CMemBlockManagerMt *memManager)\r
+{\r
+  memManager->FreeBlock(Blocks[index], LockMode);\r
+  Blocks[index] = 0;\r
+}\r
+\r
+void CMemLockBlocks::Free(CMemBlockManagerMt *memManager)\r
+{\r
+  while (Blocks.Size() > 0)\r
+  {\r
+    FreeBlock(Blocks.Size() - 1, memManager);\r
+    Blocks.DeleteBack();\r
+  }\r
+  TotalSize = 0;\r
+}\r
+\r
+HRes CMemLockBlocks::SwitchToNoLockMode(CMemBlockManagerMt *memManager)\r
+{\r
+  if (LockMode)\r
+  {\r
+    if (Blocks.Size() > 0)\r
+    {\r
+      RINOK(memManager->ReleaseLockedBlocks(Blocks.Size()));\r
+    }\r
+    LockMode = false;\r
+  }\r
+  return 0;\r
+}\r
+\r
+void CMemLockBlocks::Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager)\r
+{\r
+  blocks.Free(memManager);\r
+  blocks.LockMode = LockMode;\r
+  UInt64 totalSize = 0;\r
+  size_t blockSize = memManager->GetBlockSize();\r
+  for (int i = 0; i < Blocks.Size(); i++)\r
+  {\r
+    if (totalSize < TotalSize)\r
+      blocks.Blocks.Add(Blocks[i]);\r
+    else\r
+      FreeBlock(i, memManager);\r
+    Blocks[i] = 0;\r
+    totalSize += blockSize;\r
+  }\r
+  blocks.TotalSize = TotalSize;\r
+  Free(memManager);\r
+}\r
diff --git a/CPP/7zip/Common/MemBlocks.h b/CPP/7zip/Common/MemBlocks.h
new file mode 100755 (executable)
index 0000000..b0cdcf6
--- /dev/null
@@ -0,0 +1,71 @@
+// MemBlocks.h\r
+\r
+#ifndef __MEM_BLOCKS_H\r
+#define __MEM_BLOCKS_H\r
+\r
+#include "Common/MyVector.h"\r
+\r
+#include "Windows/Synchronization.h"\r
+\r
+#include "../IStream.h"\r
+\r
+class CMemBlockManager\r
+{\r
+  void *_data;\r
+  size_t _blockSize;\r
+  void *_headFree;\r
+public:\r
+  CMemBlockManager(size_t blockSize = (1 << 20)): _data(0), _blockSize(blockSize), _headFree(0) {}\r
+  ~CMemBlockManager() { FreeSpace(); }\r
+\r
+  bool AllocateSpace(size_t numBlocks);\r
+  void FreeSpace();\r
+  size_t GetBlockSize() const { return _blockSize; }\r
+  void *AllocateBlock();\r
+  void FreeBlock(void *p);\r
+};\r
+\r
+\r
+class CMemBlockManagerMt: public CMemBlockManager\r
+{\r
+  NWindows::NSynchronization::CCriticalSection _criticalSection;\r
+public:\r
+  NWindows::NSynchronization::CSemaphore Semaphore;\r
+\r
+  CMemBlockManagerMt(size_t blockSize = (1 << 20)): CMemBlockManager(blockSize) {}\r
+  ~CMemBlockManagerMt() { FreeSpace(); }\r
+\r
+  HRes AllocateSpace(size_t numBlocks, size_t numNoLockBlocks = 0);\r
+  HRes AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks = 0);\r
+  void FreeSpace();\r
+  void *AllocateBlock();\r
+  void FreeBlock(void *p, bool lockMode = true);\r
+  HRes ReleaseLockedBlocks(int number) { return Semaphore.Release(number); }\r
+};\r
+\r
+\r
+class CMemBlocks\r
+{\r
+  void Free(CMemBlockManagerMt *manager);\r
+public:\r
+  CRecordVector<void *> Blocks;\r
+  UInt64 TotalSize;\r
+  \r
+  CMemBlocks(): TotalSize(0) {}\r
+\r
+  void FreeOpt(CMemBlockManagerMt *manager);\r
+  HRESULT WriteToStream(size_t blockSize, ISequentialOutStream *outStream) const;\r
+};\r
+\r
+struct CMemLockBlocks: public CMemBlocks\r
+{\r
+  bool LockMode;\r
+\r
+  CMemLockBlocks(): LockMode(true) {};\r
+  void Free(CMemBlockManagerMt *memManager);\r
+  void FreeBlock(int index, CMemBlockManagerMt *memManager);\r
+  HRes SwitchToNoLockMode(CMemBlockManagerMt *memManager);\r
+  void Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/MethodId.cpp b/CPP/7zip/Common/MethodId.cpp
new file mode 100755 (executable)
index 0000000..705cc4d
--- /dev/null
@@ -0,0 +1,27 @@
+// MethodId.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "MethodId.h"\r
+#include "../../Common/MyString.h"\r
+\r
+static inline wchar_t GetHex(Byte value)\r
+{\r
+  return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10)));\r
+}\r
+\r
+UString ConvertMethodIdToString(UInt64 id)\r
+{\r
+  wchar_t s[32];\r
+  int len = 32;\r
+  s[--len] = 0;\r
+  do\r
+  {\r
+    s[--len] = GetHex((Byte)id & 0xF);\r
+    id >>= 4;\r
+    s[--len] = GetHex((Byte)id & 0xF);\r
+    id >>= 4;\r
+  }\r
+  while (id != 0);\r
+  return s + len;\r
+}\r
diff --git a/CPP/7zip/Common/MethodId.h b/CPP/7zip/Common/MethodId.h
new file mode 100755 (executable)
index 0000000..9551723
--- /dev/null
@@ -0,0 +1,10 @@
+// MethodId.h\r
+\r
+#ifndef __7Z_METHOD_ID_H\r
+#define __7Z_METHOD_ID_H\r
+\r
+#include "../../Common/Types.h"\r
+\r
+typedef UInt64 CMethodId;\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp
new file mode 100755 (executable)
index 0000000..937708e
--- /dev/null
@@ -0,0 +1,99 @@
+// MethodProps.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "MethodProps.h"\r
+\r
+static const UInt64 k_LZMA = 0x030101;\r
+static const UInt64 k_LZMA2 = 0x21;\r
+\r
+HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder)\r
+{\r
+  bool tryReduce = false;\r
+  UInt32 reducedDictionarySize = 1 << 10;\r
+  if (inSizeForReduce != 0 && (method.Id == k_LZMA || method.Id == k_LZMA2))\r
+  {\r
+    for (;;)\r
+    {\r
+      const UInt32 step = (reducedDictionarySize >> 1);\r
+      if (reducedDictionarySize >= *inSizeForReduce)\r
+      {\r
+        tryReduce = true;\r
+        break;\r
+      }\r
+      reducedDictionarySize += step;\r
+      if (reducedDictionarySize >= *inSizeForReduce)\r
+      {\r
+        tryReduce = true;\r
+        break;\r
+      }\r
+      if (reducedDictionarySize >= ((UInt32)3 << 30))\r
+        break;\r
+      reducedDictionarySize += step;\r
+    }\r
+  }\r
+\r
+  {\r
+    int numProps = method.Props.Size();\r
+    CMyComPtr<ICompressSetCoderProperties> setCoderProperties;\r
+    coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties);\r
+    if (setCoderProperties == NULL)\r
+    {\r
+      if (numProps != 0)\r
+        return E_INVALIDARG;\r
+    }\r
+    else\r
+    {\r
+      CRecordVector<PROPID> propIDs;\r
+      NWindows::NCOM::CPropVariant *values = new NWindows::NCOM::CPropVariant[numProps];\r
+      HRESULT res = S_OK;\r
+      try\r
+      {\r
+        for (int i = 0; i < numProps; i++)\r
+        {\r
+          const CProp &prop = method.Props[i];\r
+          propIDs.Add(prop.Id);\r
+          NWindows::NCOM::CPropVariant &value = values[i];\r
+          value = prop.Value;\r
+          // if (tryReduce && prop.Id == NCoderPropID::kDictionarySize && value.vt == VT_UI4 && reducedDictionarySize < value.ulVal)\r
+          if (tryReduce)\r
+            if (prop.Id == NCoderPropID::kDictionarySize)\r
+              if (value.vt == VT_UI4)\r
+                if (reducedDictionarySize < value.ulVal)\r
+            value.ulVal = reducedDictionarySize;\r
+        }\r
+        CMyComPtr<ICompressSetCoderProperties> setCoderProperties;\r
+        coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties);\r
+        res = setCoderProperties->SetCoderProperties(&propIDs.Front(), values, numProps);\r
+      }\r
+      catch(...)\r
+      {\r
+        delete []values;\r
+        throw;\r
+      }\r
+      delete []values;\r
+      RINOK(res);\r
+    }\r
+  }\r
\r
+  /*\r
+  CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;\r
+  coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);\r
+  if (writeCoderProperties != NULL)\r
+  {\r
+    CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp;\r
+    CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\r
+    outStreamSpec->Init();\r
+    RINOK(writeCoderProperties->WriteCoderProperties(outStream));\r
+    size_t size = outStreamSpec->GetSize();\r
+    filterProps.SetCapacity(size);\r
+    memmove(filterProps, outStreamSpec->GetBuffer(), size);\r
+  }\r
+  */\r
+  return S_OK;\r
+}\r
+\r
diff --git a/CPP/7zip/Common/MethodProps.h b/CPP/7zip/Common/MethodProps.h
new file mode 100755 (executable)
index 0000000..75b87f1
--- /dev/null
@@ -0,0 +1,41 @@
+// MethodProps.h\r
+\r
+#ifndef __7Z_METHOD_PROPS_H\r
+#define __7Z_METHOD_PROPS_H\r
+\r
+#include "../../Common/MyVector.h"\r
+\r
+#include "../../Windows/PropVariant.h"\r
+\r
+#include "MethodId.h"\r
+\r
+struct CProp\r
+{\r
+  PROPID Id;\r
+  NWindows::NCOM::CPropVariant Value;\r
+};\r
+\r
+struct CMethod\r
+{\r
+  CMethodId Id;\r
+  CObjectVector<CProp> Props;\r
+};\r
+\r
+struct CMethodsMode\r
+{\r
+  CObjectVector<CMethod> Methods;\r
+  #ifndef _7ZIP_ST\r
+  UInt32 NumThreads;\r
+  #endif\r
+\r
+  CMethodsMode()\r
+      #ifndef _7ZIP_ST\r
+      : NumThreads(1)\r
+      #endif\r
+  {}\r
+  bool IsEmpty() const { return Methods.IsEmpty() ; }\r
+};\r
+\r
+HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder);\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/OffsetStream.cpp b/CPP/7zip/Common/OffsetStream.cpp
new file mode 100755 (executable)
index 0000000..f10f54c
--- /dev/null
@@ -0,0 +1,35 @@
+// OffsetStream.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/Defs.h"\r
+#include "OffsetStream.h"\r
+\r
+HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset)\r
+{\r
+  _offset = offset;\r
+  _stream = stream;\r
+  return _stream->Seek(offset, STREAM_SEEK_SET, NULL);\r
+}\r
+\r
+STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  return _stream->Write(data, size, processedSize);\r
+}\r
+\r
+STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin,\r
+    UInt64 *newPosition)\r
+{\r
+  UInt64 absoluteNewPosition;\r
+  if (seekOrigin == STREAM_SEEK_SET)\r
+    offset += _offset;\r
+  HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition);\r
+  if (newPosition != NULL)\r
+    *newPosition = absoluteNewPosition - _offset;\r
+  return result;\r
+}\r
+\r
+STDMETHODIMP COffsetOutStream::SetSize(UInt64 newSize)\r
+{\r
+  return _stream->SetSize(_offset + newSize);\r
+}\r
diff --git a/CPP/7zip/Common/OffsetStream.h b/CPP/7zip/Common/OffsetStream.h
new file mode 100755 (executable)
index 0000000..972a8ce
--- /dev/null
@@ -0,0 +1,25 @@
+// OffsetStream.h\r
+\r
+#ifndef __OFFSETSTREAM_H\r
+#define __OFFSETSTREAM_H\r
+\r
+#include "Common/MyCom.h"\r
+#include "../IStream.h"\r
+\r
+class COffsetOutStream:\r
+  public IOutStream,\r
+  public CMyUnknownImp\r
+{\r
+  UInt64 _offset;\r
+  CMyComPtr<IOutStream> _stream;\r
+public:\r
+  HRESULT Init(IOutStream *stream, UInt64 offset);\r
+  \r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);\r
+  STDMETHOD(SetSize)(UInt64 newSize);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/OutBuffer.cpp b/CPP/7zip/Common/OutBuffer.cpp
new file mode 100755 (executable)
index 0000000..4e55f55
--- /dev/null
@@ -0,0 +1,116 @@
+// OutBuffer.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+\r
+#include "OutBuffer.h"\r
+\r
+bool COutBuffer::Create(UInt32 bufferSize)\r
+{\r
+  const UInt32 kMinBlockSize = 1;\r
+  if (bufferSize < kMinBlockSize)\r
+    bufferSize = kMinBlockSize;\r
+  if (_buffer != 0 && _bufferSize == bufferSize)\r
+    return true;\r
+  Free();\r
+  _bufferSize = bufferSize;\r
+  _buffer = (Byte *)::MidAlloc(bufferSize);\r
+  return (_buffer != 0);\r
+}\r
+\r
+void COutBuffer::Free()\r
+{\r
+  ::MidFree(_buffer);\r
+  _buffer = 0;\r
+}\r
+\r
+void COutBuffer::SetStream(ISequentialOutStream *stream)\r
+{\r
+  _stream = stream;\r
+}\r
+\r
+void COutBuffer::Init()\r
+{\r
+  _streamPos = 0;\r
+  _limitPos = _bufferSize;\r
+  _pos = 0;\r
+  _processedSize = 0;\r
+  _overDict = false;\r
+  #ifdef _NO_EXCEPTIONS\r
+  ErrorCode = S_OK;\r
+  #endif\r
+}\r
+\r
+UInt64 COutBuffer::GetProcessedSize() const\r
+{\r
+  UInt64 res = _processedSize + _pos - _streamPos;\r
+  if (_streamPos > _pos)\r
+    res += _bufferSize;\r
+  return res;\r
+}\r
+\r
+\r
+HRESULT COutBuffer::FlushPart()\r
+{\r
+  // _streamPos < _bufferSize\r
+  UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos);\r
+  HRESULT result = S_OK;\r
+  #ifdef _NO_EXCEPTIONS\r
+  result = ErrorCode;\r
+  #endif\r
+  if (_buffer2 != 0)\r
+  {\r
+    memmove(_buffer2, _buffer + _streamPos, size);\r
+    _buffer2 += size;\r
+  }\r
+\r
+  if (_stream != 0\r
+      #ifdef _NO_EXCEPTIONS\r
+      && (ErrorCode == S_OK)\r
+      #endif\r
+     )\r
+  {\r
+    UInt32 processedSize = 0;\r
+    result = _stream->Write(_buffer + _streamPos, size, &processedSize);\r
+    size = processedSize;\r
+  }\r
+  _streamPos += size;\r
+  if (_streamPos == _bufferSize)\r
+    _streamPos = 0;\r
+  if (_pos == _bufferSize)\r
+  {\r
+    _overDict = true;\r
+    _pos = 0;\r
+  }\r
+  _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize;\r
+  _processedSize += size;\r
+  return result;\r
+}\r
+\r
+HRESULT COutBuffer::Flush()\r
+{\r
+  #ifdef _NO_EXCEPTIONS\r
+  if (ErrorCode != S_OK)\r
+    return ErrorCode;\r
+  #endif\r
+\r
+  while(_streamPos != _pos)\r
+  {\r
+    HRESULT result = FlushPart();\r
+    if (result != S_OK)\r
+      return result;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+void COutBuffer::FlushWithCheck()\r
+{\r
+  HRESULT result = Flush();\r
+  #ifdef _NO_EXCEPTIONS\r
+  ErrorCode = result;\r
+  #else\r
+  if (result != S_OK)\r
+    throw COutBufferException(result);\r
+  #endif\r
+}\r
diff --git a/CPP/7zip/Common/OutBuffer.h b/CPP/7zip/Common/OutBuffer.h
new file mode 100755 (executable)
index 0000000..e2e76ad
--- /dev/null
@@ -0,0 +1,64 @@
+// OutBuffer.h\r
+\r
+#ifndef __OUTBUFFER_H\r
+#define __OUTBUFFER_H\r
+\r
+#include "../IStream.h"\r
+#include "../../Common/MyCom.h"\r
+#include "../../Common/MyException.h"\r
+\r
+#ifndef _NO_EXCEPTIONS\r
+struct COutBufferException: public CSystemException\r
+{\r
+  COutBufferException(HRESULT errorCode): CSystemException(errorCode) {}\r
+};\r
+#endif\r
+\r
+class COutBuffer\r
+{\r
+protected:\r
+  Byte *_buffer;\r
+  UInt32 _pos;\r
+  UInt32 _limitPos;\r
+  UInt32 _streamPos;\r
+  UInt32 _bufferSize;\r
+  CMyComPtr<ISequentialOutStream> _stream;\r
+  UInt64 _processedSize;\r
+  Byte  *_buffer2;\r
+  bool _overDict;\r
+\r
+  HRESULT FlushPart();\r
+public:\r
+  #ifdef _NO_EXCEPTIONS\r
+  HRESULT ErrorCode;\r
+  #endif\r
+\r
+  COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {}\r
+  ~COutBuffer() { Free(); }\r
+  \r
+  bool Create(UInt32 bufferSize);\r
+  void Free();\r
+\r
+  void SetMemStream(Byte *buffer) { _buffer2 = buffer; }\r
+  void SetStream(ISequentialOutStream *stream);\r
+  void Init();\r
+  HRESULT Flush();\r
+  void FlushWithCheck();\r
+  void ReleaseStream() {  _stream.Release(); }\r
+\r
+  void WriteByte(Byte b)\r
+  {\r
+    _buffer[_pos++] = b;\r
+    if(_pos == _limitPos)\r
+      FlushWithCheck();\r
+  }\r
+  void WriteBytes(const void *data, size_t size)\r
+  {\r
+    for (size_t i = 0; i < size; i++)\r
+      WriteByte(((const Byte *)data)[i]);\r
+  }\r
+\r
+  UInt64 GetProcessedSize() const;\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/OutMemStream.cpp b/CPP/7zip/Common/OutMemStream.cpp
new file mode 100755 (executable)
index 0000000..22ba984
--- /dev/null
@@ -0,0 +1,142 @@
+// OutMemStream.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "OutMemStream.h"\r
+\r
+void COutMemStream::Free()\r
+{\r
+  Blocks.Free(_memManager);\r
+  Blocks.LockMode = true;\r
+}\r
+\r
+void COutMemStream::Init()\r
+{\r
+  WriteToRealStreamEvent.Reset();\r
+  _unlockEventWasSent = false;\r
+  _realStreamMode = false;\r
+  Free();\r
+  _curBlockPos = 0;\r
+  _curBlockIndex = 0;\r
+}\r
+\r
+void COutMemStream::DetachData(CMemLockBlocks &blocks)\r
+{\r
+  Blocks.Detach(blocks, _memManager);\r
+  Free();\r
+}\r
+\r
+\r
+HRESULT COutMemStream::WriteToRealStream()\r
+{\r
+  RINOK(Blocks.WriteToStream(_memManager->GetBlockSize(), OutSeqStream));\r
+  Blocks.Free(_memManager);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (_realStreamMode)\r
+    return OutSeqStream->Write(data, size, processedSize);\r
+  if (processedSize != 0)\r
+    *processedSize = 0;\r
+  while(size != 0)\r
+  {\r
+    if ((int)_curBlockIndex < Blocks.Blocks.Size())\r
+    {\r
+      Byte *p = (Byte *)Blocks.Blocks[(int)_curBlockIndex] + _curBlockPos;\r
+      size_t curSize = _memManager->GetBlockSize() - _curBlockPos;\r
+      if (size < curSize)\r
+        curSize = size;\r
+      memmove(p, data, curSize);\r
+      if (processedSize != 0)\r
+        *processedSize += (UInt32)curSize;\r
+      data = (const void *)((const Byte *)data + curSize);\r
+      size -= (UInt32)curSize;\r
+      _curBlockPos += curSize;\r
+\r
+      UInt64 pos64 = GetPos();\r
+      if (pos64 > Blocks.TotalSize)\r
+        Blocks.TotalSize = pos64;\r
+      if (_curBlockPos == _memManager->GetBlockSize())\r
+      {\r
+        _curBlockIndex++;\r
+        _curBlockPos = 0;\r
+      }\r
+      continue;\r
+    }\r
+    HANDLE events[3] = { StopWritingEvent, WriteToRealStreamEvent, /* NoLockEvent, */ _memManager->Semaphore };\r
+    DWORD waitResult = ::WaitForMultipleObjects((Blocks.LockMode ? 3 : 2), events, FALSE, INFINITE);\r
+    switch (waitResult)\r
+    {\r
+      case (WAIT_OBJECT_0 + 0):\r
+        return StopWriteResult;\r
+      case (WAIT_OBJECT_0 + 1):\r
+      {\r
+        _realStreamMode = true;\r
+        RINOK(WriteToRealStream());\r
+        UInt32 processedSize2;\r
+        HRESULT res = OutSeqStream->Write(data, size, &processedSize2);\r
+        if (processedSize != 0)\r
+          *processedSize += processedSize2;\r
+        return res;\r
+      }\r
+      /*\r
+      case (WAIT_OBJECT_0 + 2):\r
+      {\r
+        // it has bug: no write.\r
+        if (!Blocks.SwitchToNoLockMode(_memManager))\r
+          return E_FAIL;\r
+        break;\r
+      }\r
+      */\r
+      case (WAIT_OBJECT_0 + 2):\r
+        break;\r
+      default:\r
+        return E_FAIL;\r
+    }\r
+    Blocks.Blocks.Add(_memManager->AllocateBlock());\r
+    if (Blocks.Blocks.Back() == 0)\r
+      return E_FAIL;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP COutMemStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)\r
+{\r
+  if (_realStreamMode)\r
+  {\r
+    if (!OutStream)\r
+      return E_FAIL;\r
+    return OutStream->Seek(offset, seekOrigin, newPosition);\r
+  }\r
+  if (seekOrigin == STREAM_SEEK_CUR)\r
+  {\r
+    if (offset != 0)\r
+      return E_NOTIMPL;\r
+  }\r
+  else if (seekOrigin == STREAM_SEEK_SET)\r
+  {\r
+    if (offset != 0)\r
+      return E_NOTIMPL;\r
+    _curBlockIndex = 0;\r
+    _curBlockPos = 0;\r
+  }\r
+  else\r
+    return E_NOTIMPL;\r
+  if (newPosition != 0)\r
+    *newPosition = GetPos();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP COutMemStream::SetSize(UInt64 newSize)\r
+{\r
+  if (_realStreamMode)\r
+  {\r
+    if (!OutStream)\r
+      return E_FAIL;\r
+    return OutStream->SetSize(newSize);\r
+  }\r
+  Blocks.TotalSize = newSize;\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/Common/OutMemStream.h b/CPP/7zip/Common/OutMemStream.h
new file mode 100755 (executable)
index 0000000..3037903
--- /dev/null
@@ -0,0 +1,96 @@
+// OutMemStream.h\r
+\r
+#ifndef __OUTMEMSTREAM_H\r
+#define __OUTMEMSTREAM_H\r
+\r
+#include "Common/MyCom.h"\r
+#include "MemBlocks.h"\r
+\r
+class COutMemStream:\r
+  public IOutStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMemBlockManagerMt *_memManager;\r
+  size_t _curBlockIndex;\r
+  size_t _curBlockPos;\r
+  bool _realStreamMode;\r
+\r
+  bool _unlockEventWasSent;\r
+  NWindows::NSynchronization::CAutoResetEvent StopWritingEvent;\r
+  NWindows::NSynchronization::CAutoResetEvent WriteToRealStreamEvent;\r
+  // NWindows::NSynchronization::CAutoResetEvent NoLockEvent;\r
+\r
+  HRESULT StopWriteResult;\r
+  CMemLockBlocks Blocks;\r
+\r
+  UInt64 GetPos() const { return (UInt64)_curBlockIndex * _memManager->GetBlockSize() + _curBlockPos; }\r
+\r
+  CMyComPtr<ISequentialOutStream> OutSeqStream;\r
+  CMyComPtr<IOutStream> OutStream;\r
+\r
+public:\r
+\r
+  HRes CreateEvents()\r
+  {\r
+    RINOK(StopWritingEvent.CreateIfNotCreated());\r
+    return WriteToRealStreamEvent.CreateIfNotCreated();\r
+  }\r
+\r
+  void SetOutStream(IOutStream *outStream)\r
+  {\r
+    OutStream = outStream;\r
+    OutSeqStream = outStream;\r
+  }\r
+\r
+  void SetSeqOutStream(ISequentialOutStream *outStream)\r
+  {\r
+    OutStream = NULL;\r
+    OutSeqStream = outStream;\r
+  }\r
+\r
+  void ReleaseOutStream()\r
+  {\r
+    OutStream.Release();\r
+    OutSeqStream.Release();\r
+  }\r
+\r
+  COutMemStream(CMemBlockManagerMt *memManager): _memManager(memManager)  { }\r
+\r
+  ~COutMemStream() { Free(); }\r
+  void Free();\r
+\r
+  void Init();\r
+  HRESULT WriteToRealStream();\r
+\r
+  void DetachData(CMemLockBlocks &blocks);\r
+\r
+  bool WasUnlockEventSent() const { return _unlockEventWasSent; }\r
+\r
+  void SetRealStreamMode()\r
+  {\r
+    _unlockEventWasSent = true;\r
+    WriteToRealStreamEvent.Set();\r
+  }\r
+\r
+  /*\r
+  void SetNoLockMode()\r
+  {\r
+    _unlockEventWasSent = true;\r
+    NoLockEvent.Set();\r
+  }\r
+  */\r
+\r
+  void StopWriting(HRESULT res)\r
+  {\r
+    StopWriteResult = res;\r
+    StopWritingEvent.Set();\r
+  }\r
+\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);\r
+  STDMETHOD(SetSize)(UInt64 newSize);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/ProgressMt.cpp b/CPP/7zip/Common/ProgressMt.cpp
new file mode 100755 (executable)
index 0000000..e1e7f38
--- /dev/null
@@ -0,0 +1,53 @@
+// ProgressMt.h\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "ProgressMt.h"\r
+\r
+void CMtCompressProgressMixer::Init(int numItems, ICompressProgressInfo *progress)\r
+{\r
+  NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);\r
+  InSizes.Clear();\r
+  OutSizes.Clear();\r
+  for (int i = 0; i < numItems; i++)\r
+  {\r
+    InSizes.Add(0);\r
+    OutSizes.Add(0);\r
+  }\r
+  TotalInSize = 0;\r
+  TotalOutSize = 0;\r
+  _progress = progress;\r
+}\r
+\r
+void CMtCompressProgressMixer::Reinit(int index)\r
+{\r
+  NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);\r
+  InSizes[index] = 0;\r
+  OutSizes[index] = 0;\r
+}\r
+\r
+HRESULT CMtCompressProgressMixer::SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize)\r
+{\r
+  NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);\r
+  if (inSize != 0)\r
+  {\r
+    UInt64 diff = *inSize - InSizes[index];\r
+    InSizes[index] = *inSize;\r
+    TotalInSize += diff;\r
+  }\r
+  if (outSize != 0)\r
+  {\r
+    UInt64 diff = *outSize - OutSizes[index];\r
+    OutSizes[index] = *outSize;\r
+    TotalOutSize += diff;\r
+  }\r
+  if (_progress)\r
+    return _progress->SetRatioInfo(&TotalInSize, &TotalOutSize);\r
+  return S_OK;\r
+}\r
+\r
+\r
+STDMETHODIMP CMtCompressProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)\r
+{\r
+  return _progress->SetRatioInfo(_index, inSize, outSize);\r
+}\r
diff --git a/CPP/7zip/Common/ProgressMt.h b/CPP/7zip/Common/ProgressMt.h
new file mode 100755 (executable)
index 0000000..4eeb02a
--- /dev/null
@@ -0,0 +1,46 @@
+// ProgressMt.h\r
+\r
+#ifndef __PROGRESSMT_H\r
+#define __PROGRESSMT_H\r
+\r
+#include "../../Common/MyCom.h"\r
+#include "../../Common/MyVector.h"\r
+#include "../../Windows/Synchronization.h"\r
+\r
+#include "../ICoder.h"\r
+#include "../IProgress.h"\r
+\r
+class CMtCompressProgressMixer\r
+{\r
+  CMyComPtr<ICompressProgressInfo> _progress;\r
+  CRecordVector<UInt64> InSizes;\r
+  CRecordVector<UInt64> OutSizes;\r
+  UInt64 TotalInSize;\r
+  UInt64 TotalOutSize;\r
+public:\r
+  NWindows::NSynchronization::CCriticalSection CriticalSection;\r
+  void Init(int numItems, ICompressProgressInfo *progress);\r
+  void Reinit(int index);\r
+  HRESULT SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize);\r
+};\r
+\r
+class CMtCompressProgress:\r
+  public ICompressProgressInfo,\r
+  public CMyUnknownImp\r
+{\r
+  CMtCompressProgressMixer *_progress;\r
+  int _index;\r
+public:\r
+  void Init(CMtCompressProgressMixer *progress, int index)\r
+  {\r
+    _progress = progress;\r
+    _index = index;\r
+  }\r
+  void Reinit() { _progress->Reinit(_index); }\r
+\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/ProgressUtils.cpp b/CPP/7zip/Common/ProgressUtils.cpp
new file mode 100755 (executable)
index 0000000..84a3eaf
--- /dev/null
@@ -0,0 +1,42 @@
+// ProgressUtils.h\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "ProgressUtils.h"\r
+\r
+CLocalProgress::CLocalProgress()\r
+{\r
+  ProgressOffset = InSize = OutSize = 0;\r
+  SendRatio = SendProgress = true;\r
+}\r
+\r
+void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain)\r
+{\r
+  _ratioProgress.Release();\r
+  _progress = progress;\r
+  _progress.QueryInterface(IID_ICompressProgressInfo, &_ratioProgress);\r
+  _inSizeIsMain = inSizeIsMain;\r
+}\r
+\r
+STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)\r
+{\r
+  UInt64 inSizeNew = InSize, outSizeNew = OutSize;\r
+  if (inSize)\r
+    inSizeNew += (*inSize);\r
+  if (outSize)\r
+    outSizeNew += (*outSize);\r
+  if (SendRatio && _ratioProgress)\r
+  {\r
+    RINOK(_ratioProgress->SetRatioInfo(&inSizeNew, &outSizeNew));\r
+  }\r
+  inSizeNew += ProgressOffset;\r
+  outSizeNew += ProgressOffset;\r
+  if (SendProgress)\r
+    return _progress->SetCompleted(_inSizeIsMain ? &inSizeNew : &outSizeNew);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CLocalProgress::SetCur()\r
+{\r
+  return SetRatioInfo(NULL, NULL);\r
+}\r
diff --git a/CPP/7zip/Common/ProgressUtils.h b/CPP/7zip/Common/ProgressUtils.h
new file mode 100755 (executable)
index 0000000..c620484
--- /dev/null
@@ -0,0 +1,34 @@
+// ProgressUtils.h\r
+\r
+#ifndef __PROGRESSUTILS_H\r
+#define __PROGRESSUTILS_H\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+#include "../IProgress.h"\r
+\r
+class CLocalProgress:\r
+  public ICompressProgressInfo,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<IProgress> _progress;\r
+  CMyComPtr<ICompressProgressInfo> _ratioProgress;\r
+  bool _inSizeIsMain;\r
+public:\r
+  UInt64 ProgressOffset;\r
+  UInt64 InSize;\r
+  UInt64 OutSize;\r
+  bool SendRatio;\r
+  bool SendProgress;\r
+\r
+  CLocalProgress();\r
+  void Init(IProgress *progress, bool inSizeIsMain);\r
+  HRESULT SetCur();\r
+\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/RegisterArc.h b/CPP/7zip/Common/RegisterArc.h
new file mode 100755 (executable)
index 0000000..7066325
--- /dev/null
@@ -0,0 +1,32 @@
+// RegisterArc.h\r
+\r
+#ifndef __REGISTER_ARC_H\r
+#define __REGISTER_ARC_H\r
+\r
+#include "../Archive/IArchive.h"\r
+\r
+typedef IInArchive * (*CreateInArchiveP)();\r
+typedef IOutArchive * (*CreateOutArchiveP)();\r
+\r
+struct CArcInfo\r
+{\r
+  const wchar_t *Name;\r
+  const wchar_t *Ext;\r
+  const wchar_t *AddExt;\r
+  Byte ClassId;\r
+  Byte Signature[16];\r
+  int SignatureSize;\r
+  bool KeepName;\r
+  CreateInArchiveP CreateInArchive;\r
+  CreateOutArchiveP CreateOutArchive;\r
+};\r
+\r
+void RegisterArc(const CArcInfo *arcInfo);\r
+\r
+#define REGISTER_ARC_NAME(x) CRegister ## x\r
+\r
+#define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \\r
+    REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \\r
+    static REGISTER_ARC_NAME(x) g_RegisterArc;\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/RegisterCodec.h b/CPP/7zip/Common/RegisterCodec.h
new file mode 100755 (executable)
index 0000000..c59ab66
--- /dev/null
@@ -0,0 +1,33 @@
+// RegisterCodec.h\r
+\r
+#ifndef __REGISTERCODEC_H\r
+#define __REGISTERCODEC_H\r
+\r
+#include "../Common/MethodId.h"\r
+\r
+typedef void * (*CreateCodecP)();\r
+struct CCodecInfo\r
+{\r
+  CreateCodecP CreateDecoder;\r
+  CreateCodecP CreateEncoder;\r
+  CMethodId Id;\r
+  const wchar_t *Name;\r
+  UInt32 NumInStreams;\r
+  bool IsFilter;\r
+};\r
+\r
+void RegisterCodec(const CCodecInfo *codecInfo);\r
+\r
+#define REGISTER_CODEC_NAME(x) CRegisterCodec ## x\r
+\r
+#define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \\r
+    REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \\r
+    static REGISTER_CODEC_NAME(x) g_RegisterCodec;\r
+\r
+#define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x\r
+#define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \\r
+    REGISTER_CODECS_NAME(x)() { for (int i = 0; i < sizeof(g_CodecsInfo) / sizeof(g_CodecsInfo[0]); i++) \\r
+    RegisterCodec(&g_CodecsInfo[i]); }}; \\r
+    static REGISTER_CODECS_NAME(x) g_RegisterCodecs;\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/StdAfx.h b/CPP/7zip/Common/StdAfx.h
new file mode 100755 (executable)
index 0000000..f56e92f
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../Common/MyWindows.h"\r
+#include "../../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/StreamBinder.cpp b/CPP/7zip/Common/StreamBinder.cpp
new file mode 100755 (executable)
index 0000000..cb3bf99
--- /dev/null
@@ -0,0 +1,150 @@
+// StreamBinder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "StreamBinder.h"\r
+#include "../../Common/Defs.h"\r
+#include "../../Common/MyCom.h"\r
+\r
+using namespace NWindows;\r
+using namespace NSynchronization;\r
+\r
+class CSequentialInStreamForBinder:\r
+  public ISequentialInStream,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+private:\r
+  CStreamBinder *m_StreamBinder;\r
+public:\r
+  ~CSequentialInStreamForBinder() { m_StreamBinder->CloseRead(); }\r
+  void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; }\r
+};\r
+\r
+STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+  { return m_StreamBinder->Read(data, size, processedSize); }\r
+\r
+class CSequentialOutStreamForBinder:\r
+  public ISequentialOutStream,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+\r
+private:\r
+  CStreamBinder *m_StreamBinder;\r
+public:\r
+  ~CSequentialOutStreamForBinder() {  m_StreamBinder->CloseWrite(); }\r
+  void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; }\r
+};\r
+\r
+STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+  { return m_StreamBinder->Write(data, size, processedSize); }\r
+\r
+\r
+//////////////////////////\r
+// CStreamBinder\r
+// (_thereAreBytesToReadEvent && _bufferSize == 0) means that stream is finished.\r
+\r
+HRes CStreamBinder::CreateEvents()\r
+{\r
+  RINOK(_allBytesAreWritenEvent.Create(true));\r
+  RINOK(_thereAreBytesToReadEvent.Create());\r
+  return _readStreamIsClosedEvent.Create();\r
+}\r
+\r
+void CStreamBinder::ReInit()\r
+{\r
+  _thereAreBytesToReadEvent.Reset();\r
+  _readStreamIsClosedEvent.Reset();\r
+  ProcessedSize = 0;\r
+}\r
+\r
+\r
+  \r
+void CStreamBinder::CreateStreams(ISequentialInStream **inStream,\r
+      ISequentialOutStream **outStream)\r
+{\r
+  CSequentialInStreamForBinder *inStreamSpec = new\r
+      CSequentialInStreamForBinder;\r
+  CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);\r
+  inStreamSpec->SetBinder(this);\r
+  *inStream = inStreamLoc.Detach();\r
+\r
+  CSequentialOutStreamForBinder *outStreamSpec = new\r
+      CSequentialOutStreamForBinder;\r
+  CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec);\r
+  outStreamSpec->SetBinder(this);\r
+  *outStream = outStreamLoc.Detach();\r
+\r
+  _buffer = NULL;\r
+  _bufferSize= 0;\r
+  ProcessedSize = 0;\r
+}\r
+\r
+HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  UInt32 sizeToRead = size;\r
+  if (size > 0)\r
+  {\r
+    RINOK(_thereAreBytesToReadEvent.Lock());\r
+    sizeToRead = MyMin(_bufferSize, size);\r
+    if (_bufferSize > 0)\r
+    {\r
+      memcpy(data, _buffer, sizeToRead);\r
+      _buffer = ((const Byte *)_buffer) + sizeToRead;\r
+      _bufferSize -= sizeToRead;\r
+      if (_bufferSize == 0)\r
+      {\r
+        _thereAreBytesToReadEvent.Reset();\r
+        _allBytesAreWritenEvent.Set();\r
+      }\r
+    }\r
+  }\r
+  if (processedSize != NULL)\r
+    *processedSize = sizeToRead;\r
+  ProcessedSize += sizeToRead;\r
+  return S_OK;\r
+}\r
+\r
+void CStreamBinder::CloseRead()\r
+{\r
+  _readStreamIsClosedEvent.Set();\r
+}\r
+\r
+HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (size > 0)\r
+  {\r
+    _buffer = data;\r
+    _bufferSize = size;\r
+    _allBytesAreWritenEvent.Reset();\r
+    _thereAreBytesToReadEvent.Set();\r
+\r
+    HANDLE events[2];\r
+    events[0] = _allBytesAreWritenEvent;\r
+    events[1] = _readStreamIsClosedEvent;\r
+    DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);\r
+    if (waitResult != WAIT_OBJECT_0 + 0)\r
+    {\r
+      // ReadingWasClosed = true;\r
+      return S_FALSE;\r
+    }\r
+    // if(!_allBytesAreWritenEvent.Lock())\r
+    //   return E_FAIL;\r
+  }\r
+  if (processedSize != NULL)\r
+    *processedSize = size;\r
+  return S_OK;\r
+}\r
+\r
+void CStreamBinder::CloseWrite()\r
+{\r
+  // _bufferSize must be = 0\r
+  _thereAreBytesToReadEvent.Set();\r
+}\r
diff --git a/CPP/7zip/Common/StreamBinder.h b/CPP/7zip/Common/StreamBinder.h
new file mode 100755 (executable)
index 0000000..b5d6c0d
--- /dev/null
@@ -0,0 +1,32 @@
+// StreamBinder.h\r
+\r
+#ifndef __STREAMBINDER_H\r
+#define __STREAMBINDER_H\r
+\r
+#include "../IStream.h"\r
+#include "../../Windows/Synchronization.h"\r
+\r
+class CStreamBinder\r
+{\r
+  NWindows::NSynchronization::CManualResetEvent _allBytesAreWritenEvent;\r
+  NWindows::NSynchronization::CManualResetEvent _thereAreBytesToReadEvent;\r
+  NWindows::NSynchronization::CManualResetEvent _readStreamIsClosedEvent;\r
+  UInt32 _bufferSize;\r
+  const void *_buffer;\r
+public:\r
+  // bool ReadingWasClosed;\r
+  UInt64 ProcessedSize;\r
+  CStreamBinder() {}\r
+  HRes CreateEvents();\r
+\r
+  void CreateStreams(ISequentialInStream **inStream,\r
+      ISequentialOutStream **outStream);\r
+  HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);\r
+  void CloseRead();\r
+\r
+  HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize);\r
+  void CloseWrite();\r
+  void ReInit();\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/StreamObjects.cpp b/CPP/7zip/Common/StreamObjects.cpp
new file mode 100755 (executable)
index 0000000..a18f1bc
--- /dev/null
@@ -0,0 +1,221 @@
+// StreamObjects.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+\r
+#include "StreamObjects.h"\r
+\r
+STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize)\r
+    *processedSize = 0;\r
+  if (size == 0)\r
+    return S_OK;\r
+  if (_pos > _size)\r
+    return E_FAIL;\r
+  size_t rem = _size - (size_t)_pos;\r
+  if (rem > size)\r
+    rem = (size_t)size;\r
+  memcpy(data, _data + (size_t)_pos, rem);\r
+  _pos += rem;\r
+  if (processedSize)\r
+    *processedSize = (UInt32)rem;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)\r
+{\r
+  switch(seekOrigin)\r
+  {\r
+    case STREAM_SEEK_SET: _pos = offset; break;\r
+    case STREAM_SEEK_CUR: _pos += offset; break;\r
+    case STREAM_SEEK_END: _pos = _size + offset; break;\r
+    default: return STG_E_INVALIDFUNCTION;\r
+  }\r
+  if (newPosition)\r
+    *newPosition = _pos;\r
+  return S_OK;\r
+}\r
+\r
+void CByteDynBuffer::Free()\r
+{\r
+  free(_buf);\r
+  _buf = 0;\r
+  _capacity = 0;\r
+}\r
+\r
+bool CByteDynBuffer::EnsureCapacity(size_t cap)\r
+{\r
+  if (cap <= _capacity)\r
+    return true;\r
+  size_t delta;\r
+  if (_capacity > 64)\r
+    delta = _capacity / 4;\r
+  else if (_capacity > 8)\r
+    delta = 16;\r
+  else\r
+    delta = 4;\r
+  cap = MyMax(_capacity + delta, cap);\r
+  Byte *buf = (Byte *)realloc(_buf, cap);\r
+  if (!buf)\r
+    return false;\r
+  _buf = buf;\r
+  _capacity = cap;\r
+  return true;\r
+}\r
+\r
+Byte *CDynBufSeqOutStream::GetBufPtrForWriting(size_t addSize)\r
+{\r
+  addSize += _size;\r
+  if (addSize < _size)\r
+    return NULL;\r
+  if (!_buffer.EnsureCapacity(addSize))\r
+    return NULL;\r
+  return (Byte *)_buffer + _size;\r
+}\r
+\r
+void CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const\r
+{\r
+  dest.SetCapacity(_size);\r
+  memcpy(dest, _buffer, _size);\r
+}\r
+\r
+STDMETHODIMP CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize)\r
+    *processedSize = 0;\r
+  if (size == 0)\r
+    return S_OK;\r
+  Byte *buf = GetBufPtrForWriting(size);\r
+  if (!buf)\r
+    return E_OUTOFMEMORY;\r
+  memcpy(buf, data, size);\r
+  UpdateSize(size);\r
+  if (processedSize)\r
+    *processedSize = size;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CBufPtrSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  size_t rem = _size - _pos;\r
+  if (rem > size)\r
+    rem = (size_t)size;\r
+  memcpy(_buffer + _pos, data, rem);\r
+  _pos += rem;\r
+  if (processedSize)\r
+    *processedSize = (UInt32)rem;\r
+  return (rem != 0 || size == 0) ? S_OK : E_FAIL;\r
+}\r
+\r
+STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  UInt32 realProcessedSize;\r
+  HRESULT result = _stream->Write(data, size, &realProcessedSize);\r
+  _size += realProcessedSize;\r
+  if (processedSize)\r
+    *processedSize = realProcessedSize;\r
+  return result;\r
+}\r
+\r
+static const UInt64 kEmptyTag = (UInt64)(Int64)-1;\r
+\r
+void CCachedInStream::Free()\r
+{\r
+  MyFree(_tags);\r
+  _tags = 0;\r
+  MidFree(_data);\r
+  _data = 0;\r
+}\r
+\r
+bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog)\r
+{\r
+  unsigned sizeLog = blockSizeLog + numBlocksLog;\r
+  if (sizeLog >= sizeof(size_t) * 8)\r
+    return false;\r
+  size_t dataSize = (size_t)1 << sizeLog;\r
+  if (_data == 0 || dataSize != _dataSize)\r
+  {\r
+    MidFree(_data);\r
+    _data = (Byte *)MidAlloc(dataSize);\r
+    if (_data == 0)\r
+      return false;\r
+    _dataSize = dataSize;\r
+  }\r
+  if (_tags == 0 || numBlocksLog != _numBlocksLog)\r
+  {\r
+    MyFree(_tags);\r
+    _tags = (UInt64 *)MyAlloc(sizeof(UInt64) << numBlocksLog);\r
+    if (_tags == 0)\r
+      return false;\r
+    _numBlocksLog = numBlocksLog;\r
+  }\r
+  _blockSizeLog = blockSizeLog;\r
+  return true;\r
+}\r
+\r
+void CCachedInStream::Init(UInt64 size)\r
+{\r
+  _size = size;\r
+  _pos = 0;\r
+  size_t numBlocks = (size_t)1 << _numBlocksLog;\r
+  for (size_t i = 0; i < numBlocks; i++)\r
+    _tags[i] = kEmptyTag;\r
+}\r
+\r
+STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize)\r
+    *processedSize = 0;\r
+  if (size == 0)\r
+    return S_OK;\r
+  if (_pos > _size)\r
+    return E_FAIL;\r
+\r
+  {\r
+    UInt64 rem = _size - _pos;\r
+    if (size > rem)\r
+      size = (UInt32)rem;\r
+  }\r
+\r
+  while (size != 0)\r
+  {\r
+    UInt64 cacheTag = _pos >> _blockSizeLog;\r
+    size_t cacheIndex = (size_t)cacheTag & (((size_t)1 << _numBlocksLog) - 1);\r
+    Byte *p = _data + (cacheIndex << _blockSizeLog);\r
+    if (_tags[cacheIndex] != cacheTag)\r
+    {\r
+      UInt64 remInBlock = _size - (cacheTag << _blockSizeLog);\r
+      size_t blockSize = (size_t)1 << _blockSizeLog;\r
+      if (blockSize > remInBlock)\r
+        blockSize = (size_t)remInBlock;\r
+      RINOK(ReadBlock(cacheTag, p, blockSize));\r
+      _tags[cacheIndex] = cacheTag;\r
+    }\r
+    size_t offset = (size_t)_pos & (((size_t)1 << _blockSizeLog) - 1);\r
+    UInt32 cur = (UInt32)MyMin(((size_t)1 << _blockSizeLog) - offset, (size_t)size);\r
+    memcpy(data, p + offset, cur);\r
+    if (processedSize)\r
+      *processedSize += cur;\r
+    data = (void *)((const Byte *)data + cur);\r
+    _pos += cur;\r
+    size -= cur;\r
+  }\r
+\r
+  return S_OK;\r
+}\r
\r
+STDMETHODIMP CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)\r
+{\r
+  switch(seekOrigin)\r
+  {\r
+    case STREAM_SEEK_SET: _pos = offset; break;\r
+    case STREAM_SEEK_CUR: _pos = _pos + offset; break;\r
+    case STREAM_SEEK_END: _pos = _size + offset; break;\r
+    default: return STG_E_INVALIDFUNCTION;\r
+  }\r
+  if (newPosition != 0)\r
+    *newPosition = _pos;\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/Common/StreamObjects.h b/CPP/7zip/Common/StreamObjects.h
new file mode 100755 (executable)
index 0000000..ed1532c
--- /dev/null
@@ -0,0 +1,135 @@
+// StreamObjects.h\r
+\r
+#ifndef __STREAM_OBJECTS_H\r
+#define __STREAM_OBJECTS_H\r
+\r
+#include "../../Common/Buffer.h"\r
+#include "../../Common/MyCom.h"\r
+#include "../IStream.h"\r
+\r
+struct CReferenceBuf:\r
+  public IUnknown,\r
+  public CMyUnknownImp\r
+{\r
+  CByteBuffer Buf;\r
+  MY_UNKNOWN_IMP\r
+};\r
+\r
+class CBufInStream:\r
+  public IInStream,\r
+  public CMyUnknownImp\r
+{\r
+  const Byte *_data;\r
+  UInt64 _pos;\r
+  size_t _size;\r
+  CMyComPtr<IUnknown> _ref;\r
+public:\r
+  void Init(const Byte *data, size_t size, IUnknown *ref = 0)\r
+  {\r
+    _data = data;\r
+    _size = size;\r
+    _pos = 0;\r
+    _ref = ref;\r
+  }\r
+  void Init(CReferenceBuf *ref) { Init(ref->Buf, ref->Buf.GetCapacity(), ref); }\r
+\r
+  MY_UNKNOWN_IMP1(IInStream)\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);\r
+};\r
+\r
+class CByteDynBuffer\r
+{\r
+  size_t _capacity;\r
+  Byte *_buf;\r
+public:\r
+  CByteDynBuffer(): _capacity(0), _buf(0) {};\r
+  // there is no copy constructor. So don't copy this object.\r
+  ~CByteDynBuffer() { Free(); }\r
+  void Free();\r
+  size_t GetCapacity() const { return  _capacity; }\r
+  operator Byte*() const { return _buf; };\r
+  operator const Byte*() const { return _buf; };\r
+  bool EnsureCapacity(size_t capacity);\r
+};\r
+\r
+class CDynBufSeqOutStream:\r
+  public ISequentialOutStream,\r
+  public CMyUnknownImp\r
+{\r
+  CByteDynBuffer _buffer;\r
+  size_t _size;\r
+public:\r
+  CDynBufSeqOutStream(): _size(0) {}\r
+  void Init() { _size = 0;  }\r
+  size_t GetSize() const { return _size; }\r
+  const Byte *GetBuffer() const { return _buffer; }\r
+  void CopyToBuffer(CByteBuffer &dest) const;\r
+  Byte *GetBufPtrForWriting(size_t addSize);\r
+  void UpdateSize(size_t addSize) { _size += addSize; }\r
+\r
+  MY_UNKNOWN_IMP\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+};\r
+\r
+class CBufPtrSeqOutStream:\r
+  public ISequentialOutStream,\r
+  public CMyUnknownImp\r
+{\r
+  Byte *_buffer;\r
+  size_t _size;\r
+  size_t _pos;\r
+public:\r
+  void Init(Byte *buffer, size_t size)\r
+  {\r
+    _buffer = buffer;\r
+    _pos = 0;\r
+    _size = size;\r
+  }\r
+  size_t GetPos() const { return _pos; }\r
+\r
+  MY_UNKNOWN_IMP\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+};\r
+\r
+class CSequentialOutStreamSizeCount:\r
+  public ISequentialOutStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<ISequentialOutStream> _stream;\r
+  UInt64 _size;\r
+public:\r
+  void SetStream(ISequentialOutStream *stream) { _stream = stream; }\r
+  void Init() { _size = 0; }\r
+  UInt64 GetSize() const { return _size; }\r
+\r
+  MY_UNKNOWN_IMP\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+};\r
+\r
+class CCachedInStream:\r
+  public IInStream,\r
+  public CMyUnknownImp\r
+{\r
+  UInt64 *_tags;\r
+  Byte *_data;\r
+  size_t _dataSize;\r
+  unsigned _blockSizeLog;\r
+  unsigned _numBlocksLog;\r
+  UInt64 _size;\r
+  UInt64 _pos;\r
+protected:\r
+  virtual HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) = 0;\r
+public:\r
+  CCachedInStream(): _tags(0), _data(0) {}\r
+  virtual ~CCachedInStream() { Free(); } // the destructor must be virtual (release calls it) !!!\r
+  void Free();\r
+  bool Alloc(unsigned blockSizeLog, unsigned numBlocksLog);\r
+  void Init(UInt64 size);\r
+\r
+  MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/StreamUtils.cpp b/CPP/7zip/Common/StreamUtils.cpp
new file mode 100755 (executable)
index 0000000..57ff4ee
--- /dev/null
@@ -0,0 +1,56 @@
+// StreamUtils.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "StreamUtils.h"\r
+\r
+static const UInt32 kBlockSize = ((UInt32)1 << 31);\r
+\r
+HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSize)\r
+{\r
+  size_t size = *processedSize;\r
+  *processedSize = 0;\r
+  while (size != 0)\r
+  {\r
+    UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize;\r
+    UInt32 processedSizeLoc;\r
+    HRESULT res = stream->Read(data, curSize, &processedSizeLoc);\r
+    *processedSize += processedSizeLoc;\r
+    data = (void *)((Byte *)data + processedSizeLoc);\r
+    size -= processedSizeLoc;\r
+    RINOK(res);\r
+    if (processedSizeLoc == 0)\r
+      return S_OK;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size)\r
+{\r
+  size_t processedSize = size;\r
+  RINOK(ReadStream(stream, data, &processedSize));\r
+  return (size == processedSize) ? S_OK : S_FALSE;\r
+}\r
+\r
+HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size)\r
+{\r
+  size_t processedSize = size;\r
+  RINOK(ReadStream(stream, data, &processedSize));\r
+  return (size == processedSize) ? S_OK : E_FAIL;\r
+}\r
+\r
+HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size)\r
+{\r
+  while (size != 0)\r
+  {\r
+    UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize;\r
+    UInt32 processedSizeLoc;\r
+    HRESULT res = stream->Write(data, curSize, &processedSizeLoc);\r
+    data = (const void *)((const Byte *)data + processedSizeLoc);\r
+    size -= processedSizeLoc;\r
+    RINOK(res);\r
+    if (processedSizeLoc == 0)\r
+      return E_FAIL;\r
+  }\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/Common/StreamUtils.h b/CPP/7zip/Common/StreamUtils.h
new file mode 100755 (executable)
index 0000000..30535ab
--- /dev/null
@@ -0,0 +1,13 @@
+// StreamUtils.h\r
+\r
+#ifndef __STREAMUTILS_H\r
+#define __STREAMUTILS_H\r
+\r
+#include "../IStream.h"\r
+\r
+HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size);\r
+HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size);\r
+HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size);\r
+HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size);\r
+\r
+#endif\r
diff --git a/CPP/7zip/Common/VirtThread.cpp b/CPP/7zip/Common/VirtThread.cpp
new file mode 100755 (executable)
index 0000000..c07caba
--- /dev/null
@@ -0,0 +1,46 @@
+// VirtThread.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "VirtThread.h"\r
+\r
+static THREAD_FUNC_DECL CoderThread(void *p)\r
+{\r
+  for (;;)\r
+  {\r
+    CVirtThread *t = (CVirtThread *)p;\r
+    t->StartEvent.Lock();\r
+    if (t->ExitEvent)\r
+      return 0;\r
+    t->Execute();\r
+    t->FinishedEvent.Set();\r
+  }\r
+}\r
+\r
+WRes CVirtThread::Create()\r
+{\r
+  RINOK(StartEvent.CreateIfNotCreated());\r
+  RINOK(FinishedEvent.CreateIfNotCreated());\r
+  StartEvent.Reset();\r
+  FinishedEvent.Reset();\r
+  ExitEvent = false;\r
+  if (Thread.IsCreated())\r
+    return S_OK;\r
+  return Thread.Create(CoderThread, this);\r
+}\r
+\r
+void CVirtThread::Start()\r
+{\r
+  ExitEvent = false;\r
+  StartEvent.Set();\r
+}\r
+\r
+CVirtThread::~CVirtThread()\r
+{\r
+  ExitEvent = true;\r
+  if (StartEvent.IsCreated())\r
+    StartEvent.Set();\r
+  if (Thread.IsCreated())\r
+    Thread.Wait();\r
+}\r
+\r
diff --git a/CPP/7zip/Common/VirtThread.h b/CPP/7zip/Common/VirtThread.h
new file mode 100755 (executable)
index 0000000..bfc10dc
--- /dev/null
@@ -0,0 +1,23 @@
+// VirtThread.h\r
+\r
+#ifndef __VIRTTHREAD_H\r
+#define __VIRTTHREAD_H\r
+\r
+#include "../../Windows/Synchronization.h"\r
+#include "../../Windows/Thread.h"\r
+\r
+struct CVirtThread\r
+{\r
+  NWindows::NSynchronization::CAutoResetEvent StartEvent;\r
+  NWindows::NSynchronization::CAutoResetEvent FinishedEvent;\r
+  NWindows::CThread Thread;\r
+  bool ExitEvent;\r
+\r
+  ~CVirtThread();\r
+  WRes Create();\r
+  void Start();\r
+  void WaitFinish() { FinishedEvent.Lock(); }\r
+  virtual void Execute() = 0;\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/ArjDecoder1.cpp b/CPP/7zip/Compress/ArjDecoder1.cpp
new file mode 100755 (executable)
index 0000000..9dff536
--- /dev/null
@@ -0,0 +1,309 @@
+// ArjDecoder1.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "ArjDecoder1.h"\r
+\r
+namespace NCompress{\r
+namespace NArj {\r
+namespace NDecoder1 {\r
+\r
+static const UInt32 kHistorySize = 26624;\r
+static const UInt32 kMatchMinLen = 3;\r
+static const UInt32 kMatchMaxLen = 256;\r
+\r
+// static const UInt32 kNC = 255 + kMatchMaxLen + 2 - kMatchMinLen;\r
+\r
+void CCoder::MakeTable(int nchar, Byte *bitlen, int tablebits,\r
+    UInt32 *table, int tablesize)\r
+{\r
+  UInt32 count[17], weight[17], start[18], *p;\r
+  UInt32 i, k, len, ch, jutbits, avail, nextcode, mask;\r
+  \r
+  for (i = 1; i <= 16; i++)\r
+    count[i] = 0;\r
+  for (i = 0; (int)i < nchar; i++)\r
+    count[bitlen[i]]++;\r
+  \r
+  start[1] = 0;\r
+  for (i = 1; i <= 16; i++)\r
+    start[i + 1] = start[i] + (count[i] << (16 - i));\r
+  if (start[17] != (UInt32) (1 << 16))\r
+    throw "Data error";\r
+  \r
+  jutbits = 16 - tablebits;\r
+  for (i = 1; (int)i <= tablebits; i++)\r
+  {\r
+    start[i] >>= jutbits;\r
+    weight[i] = 1 << (tablebits - i);\r
+  }\r
+  while (i <= 16)\r
+  {\r
+    weight[i] = 1 << (16 - i);\r
+    i++;\r
+  }\r
+  \r
+  i = start[tablebits + 1] >> jutbits;\r
+  if (i != (UInt32) (1 << 16))\r
+  {\r
+    k = 1 << tablebits;\r
+    while (i != k)\r
+      table[i++] = 0;\r
+  }\r
+  \r
+  avail = nchar;\r
+  mask = 1 << (15 - tablebits);\r
+  for (ch = 0; (int)ch < nchar; ch++)\r
+  {\r
+    if ((len = bitlen[ch]) == 0)\r
+      continue;\r
+    k = start[len];\r
+    nextcode = k + weight[len];\r
+    if ((int)len <= tablebits)\r
+    {\r
+      if (nextcode > (UInt32)tablesize)\r
+        throw "Data error";\r
+      for (i = start[len]; i < nextcode; i++)\r
+        table[i] = ch;\r
+    }\r
+    else\r
+    {\r
+      p = &table[k >> jutbits];\r
+      i = len - tablebits;\r
+      while (i != 0)\r
+      {\r
+        if (*p == 0)\r
+        {\r
+          right[avail] = left[avail] = 0;\r
+          *p = avail++;\r
+        }\r
+        if (k & mask)\r
+          p = &right[*p];\r
+        else\r
+          p = &left[*p];\r
+        k <<= 1;\r
+        i--;\r
+      }\r
+      *p = ch;\r
+    }\r
+    start[len] = nextcode;\r
+  }\r
+}\r
+\r
+void CCoder::read_pt_len(int nn, int nbit, int i_special)\r
+{\r
+  UInt32 n = m_InBitStream.ReadBits(nbit);\r
+  if (n == 0)\r
+  {\r
+    UInt32 c = m_InBitStream.ReadBits(nbit);\r
+    int i;\r
+    for (i = 0; i < nn; i++)\r
+      pt_len[i] = 0;\r
+    for (i = 0; i < 256; i++)\r
+      pt_table[i] = c;\r
+  }\r
+  else\r
+  {\r
+    UInt32 i = 0;\r
+    while (i < n)\r
+    {\r
+      UInt32 bitBuf = m_InBitStream.GetValue(16);\r
+      int c = bitBuf >> 13;\r
+      if (c == 7)\r
+      {\r
+        UInt32 mask = 1 << (12);\r
+        while (mask & bitBuf)\r
+        {\r
+          mask >>= 1;\r
+          c++;\r
+        }\r
+      }\r
+      m_InBitStream.MovePos((c < 7) ? 3 : (int)(c - 3));\r
+      pt_len[i++] = (Byte)c;\r
+      if (i == (UInt32)i_special)\r
+      {\r
+        c = m_InBitStream.ReadBits(2);\r
+        while (--c >= 0)\r
+          pt_len[i++] = 0;\r
+      }\r
+    }\r
+    while (i < (UInt32)nn)\r
+      pt_len[i++] = 0;\r
+    MakeTable(nn, pt_len, 8, pt_table, PTABLESIZE);\r
+  }\r
+}\r
+\r
+void CCoder::read_c_len()\r
+{\r
+  int i, c, n;\r
+  UInt32 mask;\r
+  \r
+  n = m_InBitStream.ReadBits(CBIT);\r
+  if (n == 0)\r
+  {\r
+    c = m_InBitStream.ReadBits(CBIT);\r
+    for (i = 0; i < NC; i++)\r
+      c_len[i] = 0;\r
+    for (i = 0; i < CTABLESIZE; i++)\r
+      c_table[i] = c;\r
+  }\r
+  else\r
+  {\r
+    i = 0;\r
+    while (i < n)\r
+    {\r
+      UInt32 bitBuf = m_InBitStream.GetValue(16);\r
+      c = pt_table[bitBuf >> (8)];\r
+      if (c >= NT)\r
+      {\r
+        mask = 1 << (7);\r
+        do\r
+        {\r
+          if (bitBuf & mask)\r
+            c = right[c];\r
+          else\r
+            c = left[c];\r
+          mask >>= 1;\r
+        } while (c >= NT);\r
+      }\r
+      m_InBitStream.MovePos((int)(pt_len[c]));\r
+      if (c <= 2)\r
+      {\r
+        if (c == 0)\r
+          c = 1;\r
+        else if (c == 1)\r
+          c = m_InBitStream.ReadBits(4) + 3;\r
+        else\r
+          c = m_InBitStream.ReadBits(CBIT) + 20;\r
+        while (--c >= 0)\r
+          c_len[i++] = 0;\r
+      }\r
+      else\r
+        c_len[i++] = (Byte)(c - 2);\r
+    }\r
+    while (i < NC)\r
+      c_len[i++] = 0;\r
+    MakeTable(NC, c_len, 12, c_table, CTABLESIZE);\r
+  }\r
+}\r
+\r
+UInt32 CCoder::decode_c()\r
+{\r
+  UInt32 j, mask;\r
+  UInt32 bitbuf = m_InBitStream.GetValue(16);\r
+  j = c_table[bitbuf >> 4];\r
+  if (j >= NC)\r
+  {\r
+    mask = 1 << (3);\r
+    do\r
+    {\r
+      if (bitbuf & mask)\r
+        j = right[j];\r
+      else\r
+        j = left[j];\r
+      mask >>= 1;\r
+    } while (j >= NC);\r
+  }\r
+  m_InBitStream.MovePos((int)(c_len[j]));\r
+  return j;\r
+}\r
+\r
+UInt32 CCoder::decode_p()\r
+{\r
+  UInt32 j, mask;\r
+  UInt32 bitbuf = m_InBitStream.GetValue(16);\r
+  j = pt_table[bitbuf >> (8)];\r
+  if (j >= NP)\r
+  {\r
+    mask = 1 << (7);\r
+    do\r
+    {\r
+      if (bitbuf & mask)\r
+        j = right[j];\r
+      else\r
+        j = left[j];\r
+      mask >>= 1;\r
+    } while (j >= NP);\r
+  }\r
+  m_InBitStream.MovePos((int)(pt_len[j]));\r
+  if (j != 0)\r
+  {\r
+    j--;\r
+    j = (1 << j) + m_InBitStream.ReadBits((int)j);\r
+  }\r
+  return j;\r
+}\r
+\r
+\r
+HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  if (outSize == NULL)\r
+    return E_INVALIDARG;\r
+\r
+  if (!m_OutWindowStream.Create(kHistorySize))\r
+    return E_OUTOFMEMORY;\r
+  if (!m_InBitStream.Create(1 << 20))\r
+    return E_OUTOFMEMORY;\r
+\r
+  // check it\r
+  for (int i = 0; i < CTABLESIZE; i++)\r
+    c_table[i] = 0;\r
+\r
+  UInt64 pos = 0;\r
+  m_OutWindowStream.SetStream(outStream);\r
+  m_OutWindowStream.Init(false);\r
+  m_InBitStream.SetStream(inStream);\r
+  m_InBitStream.Init();\r
+  \r
+  CCoderReleaser coderReleaser(this);\r
+\r
+  UInt32 blockSize = 0;\r
+\r
+  while(pos < *outSize)\r
+  {\r
+    if (blockSize == 0)\r
+    {\r
+      if (progress != NULL)\r
+      {\r
+        UInt64 packSize = m_InBitStream.GetProcessedSize();\r
+        RINOK(progress->SetRatioInfo(&packSize, &pos));\r
+      }\r
+      blockSize = m_InBitStream.ReadBits(16);\r
+      read_pt_len(NT, TBIT, 3);\r
+      read_c_len();\r
+      read_pt_len(NP, PBIT, -1);\r
+    }\r
+    blockSize--;\r
+\r
+    UInt32 number = decode_c();\r
+    if (number < 256)\r
+    {\r
+      m_OutWindowStream.PutByte((Byte)number);\r
+      pos++;\r
+      continue;\r
+    }\r
+    else\r
+    {\r
+      UInt32 len = number - 256 + kMatchMinLen;\r
+      UInt32 distance = decode_p();\r
+      if (distance >= pos)\r
+        return S_FALSE;\r
+      m_OutWindowStream.CopyBlock(distance, len);\r
+        pos += len;\r
+    }\r
+  }\r
+  coderReleaser.NeedFlush = false;\r
+  return m_OutWindowStream.Flush();\r
+}\r
+\r
+STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  try { return CodeReal(inStream, outStream, inSize, outSize, progress);}\r
+  catch(const CInBufferException &e) { return e.ErrorCode; }\r
+  catch(const CLzOutWindowException &e) { return e.ErrorCode; }\r
+  catch(...) { return S_FALSE; }\r
+}\r
+\r
+}}}\r
diff --git a/CPP/7zip/Compress/ArjDecoder1.h b/CPP/7zip/Compress/ArjDecoder1.h
new file mode 100755 (executable)
index 0000000..f33cb36
--- /dev/null
@@ -0,0 +1,98 @@
+// ArjDecoder1.h\r
+\r
+#ifndef __COMPRESS_ARJ_DECODER1_H\r
+#define __COMPRESS_ARJ_DECODER1_H\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "../Common/InBuffer.h"\r
+\r
+#include "BitmDecoder.h"\r
+#include "LzOutWindow.h"\r
+\r
+namespace NCompress {\r
+namespace NArj {\r
+namespace NDecoder1 {\r
+\r
+#define CODE_BIT          16\r
+\r
+#define THRESHOLD    3\r
+#define DDICSIZ      26624\r
+#define MAXDICBIT   16\r
+#define MATCHBIT     8\r
+#define MAXMATCH   256\r
+#define NC          (0xFF + MAXMATCH + 2 - THRESHOLD)\r
+#define NP          (MAXDICBIT + 1)\r
+#define CBIT         9\r
+#define NT          (CODE_BIT + 3)\r
+#define PBIT         5\r
+#define TBIT         5\r
+\r
+#if NT > NP\r
+#define NPT NT\r
+#else\r
+#define NPT NP\r
+#endif\r
+\r
+#define CTABLESIZE  4096\r
+#define PTABLESIZE   256\r
+\r
+\r
+class CCoder :\r
+  public ICompressCoder,\r
+  public CMyUnknownImp\r
+{\r
+  CLzOutWindow m_OutWindowStream;\r
+  NBitm::CDecoder<CInBuffer> m_InBitStream;\r
+\r
+  UInt32 left[2 * NC - 1];\r
+  UInt32 right[2 * NC - 1];\r
+  Byte c_len[NC];\r
+  Byte pt_len[NPT];\r
+\r
+  UInt32 c_table[CTABLESIZE];\r
+  UInt32 pt_table[PTABLESIZE];\r
+  \r
+  void ReleaseStreams()\r
+  {\r
+    m_OutWindowStream.ReleaseStream();\r
+    m_InBitStream.ReleaseStream();\r
+  }\r
+\r
+  class CCoderReleaser\r
+  {\r
+    CCoder *m_Coder;\r
+  public:\r
+    bool NeedFlush;\r
+    CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {}\r
+    ~CCoderReleaser()\r
+    {\r
+      if (NeedFlush)\r
+        m_Coder->m_OutWindowStream.Flush();\r
+      m_Coder->ReleaseStreams();\r
+    }\r
+  };\r
+  friend class CCoderReleaser;\r
+\r
+  void MakeTable(int nchar, Byte *bitlen, int tablebits, UInt32 *table, int tablesize);\r
+  \r
+  void read_c_len();\r
+  void read_pt_len(int nn, int nbit, int i_special);\r
+  UInt32 decode_c();\r
+  UInt32 decode_p();\r
+\r
+  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+public:\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+};\r
+\r
+}}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/ArjDecoder2.cpp b/CPP/7zip/Compress/ArjDecoder2.cpp
new file mode 100755 (executable)
index 0000000..9cde081
--- /dev/null
@@ -0,0 +1,90 @@
+// ArjDecoder2.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "ArjDecoder2.h"\r
+\r
+namespace NCompress{\r
+namespace NArj {\r
+namespace NDecoder2 {\r
+\r
+static const UInt32 kHistorySize = 26624;\r
+static const UInt32 kMatchMinLen = 3;\r
+\r
+HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo * /* progress */)\r
+{\r
+  if (outSize == NULL)\r
+    return E_INVALIDARG;\r
+\r
+  if (!m_OutWindowStream.Create(kHistorySize))\r
+    return E_OUTOFMEMORY;\r
+  if (!m_InBitStream.Create(1 << 20))\r
+    return E_OUTOFMEMORY;\r
+\r
+  UInt64 pos = 0;\r
+  m_OutWindowStream.SetStream(outStream);\r
+  m_OutWindowStream.Init(false);\r
+  m_InBitStream.SetStream(inStream);\r
+  m_InBitStream.Init();\r
+  CCoderReleaser coderReleaser(this);\r
+\r
+  while(pos < *outSize)\r
+  {\r
+    const UInt32 kStartWidth = 0;\r
+    const UInt32 kStopWidth = 7;\r
+    UInt32 power = 1 << kStartWidth;\r
+    UInt32 width;\r
+    UInt32 len = 0;\r
+    for (width = kStartWidth; width < kStopWidth; width++)\r
+    {\r
+      if (m_InBitStream.ReadBits(1) == 0)\r
+        break;\r
+      len += power;\r
+      power <<= 1;\r
+    }\r
+    if (width != 0)\r
+      len += m_InBitStream.ReadBits(width);\r
+    if (len == 0)\r
+    {\r
+      m_OutWindowStream.PutByte((Byte)m_InBitStream.ReadBits(8));\r
+      pos++;\r
+      continue;\r
+    }\r
+    else\r
+    {\r
+      len = len - 1 + kMatchMinLen;\r
+      const UInt32 kStartWidth = 9;\r
+      const UInt32 kStopWidth = 13;\r
+      UInt32 power = 1 << kStartWidth;\r
+      UInt32 width;\r
+      UInt32 distance = 0;\r
+      for (width = kStartWidth; width < kStopWidth; width++)\r
+      {\r
+        if (m_InBitStream.ReadBits(1) == 0)\r
+          break;\r
+        distance += power;\r
+        power <<= 1;\r
+      }\r
+      if (width != 0)\r
+        distance += m_InBitStream.ReadBits(width);\r
+      if (distance >= pos)\r
+        return S_FALSE;\r
+      m_OutWindowStream.CopyBlock(distance, len);\r
+        pos += len;\r
+    }\r
+  }\r
+  coderReleaser.NeedFlush = false;\r
+  return m_OutWindowStream.Flush();\r
+}\r
+\r
+STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  try { return CodeReal(inStream, outStream, inSize, outSize, progress);}\r
+  catch(const CInBufferException &e) { return e.ErrorCode; }\r
+  catch(const CLzOutWindowException &e) { return e.ErrorCode; }\r
+  catch(...) { return S_FALSE; }\r
+}\r
+\r
+}}}\r
diff --git a/CPP/7zip/Compress/ArjDecoder2.h b/CPP/7zip/Compress/ArjDecoder2.h
new file mode 100755 (executable)
index 0000000..4e947e2
--- /dev/null
@@ -0,0 +1,59 @@
+// ArjDecoder2.h\r
+\r
+#ifndef __COMPRESS_ARJ_DECODER2_H\r
+#define __COMPRESS_ARJ_DECODER2_H\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "../Common/InBuffer.h"\r
+\r
+#include "BitmDecoder.h"\r
+#include "LzOutWindow.h"\r
+\r
+namespace NCompress {\r
+namespace NArj {\r
+namespace NDecoder2 {\r
+\r
+class CCoder :\r
+  public ICompressCoder,\r
+  public CMyUnknownImp\r
+{\r
+  CLzOutWindow m_OutWindowStream;\r
+  NBitm::CDecoder<CInBuffer> m_InBitStream;\r
+  \r
+  void ReleaseStreams()\r
+  {\r
+    m_OutWindowStream.ReleaseStream();\r
+    m_InBitStream.ReleaseStream();\r
+  }\r
+\r
+  class CCoderReleaser\r
+  {\r
+    CCoder *m_Coder;\r
+  public:\r
+    bool NeedFlush;\r
+    CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {}\r
+    ~CCoderReleaser()\r
+    {\r
+      if (NeedFlush)\r
+        m_Coder->m_OutWindowStream.Flush();\r
+      m_Coder->ReleaseStreams();\r
+    }\r
+  };\r
+  friend class CCoderReleaser;\r
+\r
+  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+public:\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+};\r
+\r
+}}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/BZip2Const.h b/CPP/7zip/Compress/BZip2Const.h
new file mode 100755 (executable)
index 0000000..fe0c53f
--- /dev/null
@@ -0,0 +1,54 @@
+// Compress/BZip2Const.h\r
+\r
+#ifndef __COMPRESS_BZIP2_CONST_H\r
+#define __COMPRESS_BZIP2_CONST_H\r
+\r
+namespace NCompress {\r
+namespace NBZip2 {\r
+\r
+const Byte kArSig0 = 'B';\r
+const Byte kArSig1 = 'Z';\r
+const Byte kArSig2 = 'h';\r
+const Byte kArSig3 = '0';\r
+\r
+const Byte kFinSig0 = 0x17;\r
+const Byte kFinSig1 = 0x72;\r
+const Byte kFinSig2 = 0x45;\r
+const Byte kFinSig3 = 0x38;\r
+const Byte kFinSig4 = 0x50;\r
+const Byte kFinSig5 = 0x90;\r
+\r
+const Byte kBlockSig0 = 0x31;\r
+const Byte kBlockSig1 = 0x41;\r
+const Byte kBlockSig2 = 0x59;\r
+const Byte kBlockSig3 = 0x26;\r
+const Byte kBlockSig4 = 0x53;\r
+const Byte kBlockSig5 = 0x59;\r
+\r
+const int kNumOrigBits = 24;\r
+\r
+const int kNumTablesBits = 3;\r
+const int kNumTablesMin = 2;\r
+const int kNumTablesMax = 6;\r
+\r
+const int kNumLevelsBits = 5;\r
+\r
+const int kMaxHuffmanLen = 20; // Check it\r
+\r
+const int kMaxAlphaSize = 258;\r
+\r
+const int kGroupSize = 50;\r
+\r
+const int kBlockSizeMultMin = 1;\r
+const int kBlockSizeMultMax = 9;\r
+const UInt32 kBlockSizeStep = 100000;\r
+const UInt32 kBlockSizeMax = kBlockSizeMultMax * kBlockSizeStep;\r
+\r
+const int kNumSelectorsBits = 15;\r
+const UInt32 kNumSelectorsMax = (2 + (kBlockSizeMax / kGroupSize));\r
+\r
+const int kRleModeRepSize = 4;\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/BZip2Crc.cpp b/CPP/7zip/Compress/BZip2Crc.cpp
new file mode 100755 (executable)
index 0000000..2a8277c
--- /dev/null
@@ -0,0 +1,26 @@
+// BZip2Crc.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "BZip2Crc.h"\r
+\r
+UInt32 CBZip2Crc::Table[256];\r
+\r
+static const UInt32 kBZip2CrcPoly = 0x04c11db7;  /* AUTODIN II, Ethernet, & FDDI */\r
+\r
+void CBZip2Crc::InitTable()\r
+{\r
+  for (UInt32 i = 0; i < 256; i++)\r
+  {\r
+    UInt32 r = (i << 24);\r
+    for (int j = 8; j > 0; j--)\r
+      r = (r & 0x80000000) ? ((r << 1) ^ kBZip2CrcPoly) : (r << 1);\r
+    Table[i] = r;\r
+  }\r
+}\r
+\r
+class CBZip2CrcTableInit\r
+{\r
+public:\r
+  CBZip2CrcTableInit() { CBZip2Crc::InitTable(); }\r
+} g_BZip2CrcTableInit;\r
diff --git a/CPP/7zip/Compress/BZip2Crc.h b/CPP/7zip/Compress/BZip2Crc.h
new file mode 100755 (executable)
index 0000000..ad1322f
--- /dev/null
@@ -0,0 +1,31 @@
+// BZip2Crc.h\r
+\r
+#ifndef __BZIP2_CRC_H\r
+#define __BZIP2_CRC_H\r
+\r
+#include "Common/Types.h"\r
+\r
+class CBZip2Crc\r
+{\r
+  UInt32 _value;\r
+  static UInt32 Table[256];\r
+public:\r
+  static void InitTable();\r
+  CBZip2Crc(): _value(0xFFFFFFFF) {};\r
+  void Init() { _value = 0xFFFFFFFF; }\r
+  void UpdateByte(Byte b) { _value = Table[(_value >> 24) ^ b] ^ (_value << 8); }\r
+  void UpdateByte(unsigned int b) { _value = Table[(_value >> 24) ^ b] ^ (_value << 8); }\r
+  UInt32 GetDigest() const { return _value ^ 0xFFFFFFFF; }\r
+};\r
+\r
+class CBZip2CombinedCrc\r
+{\r
+  UInt32 _value;\r
+public:\r
+  CBZip2CombinedCrc():  _value(0){};\r
+  void Init() { _value = 0; }\r
+  void Update(UInt32 v) { _value = ((_value << 1) | (_value >> 31)) ^ v; }\r
+  UInt32 GetDigest() const { return _value ; }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/BZip2Decoder.cpp b/CPP/7zip/Compress/BZip2Decoder.cpp
new file mode 100755 (executable)
index 0000000..b2bebb3
--- /dev/null
@@ -0,0 +1,943 @@
+// BZip2Decoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+\r
+#include "BZip2Decoder.h"\r
+#include "Mtf8.h"\r
+\r
+namespace NCompress {\r
+namespace NBZip2 {\r
+\r
+#undef NO_INLINE\r
+#define NO_INLINE\r
+  \r
+static const UInt32 kNumThreadsMax = 4;\r
+\r
+static const UInt32 kBufferSize = (1 << 17);\r
+\r
+static const UInt16 kRandNums[512] = {\r
+   619, 720, 127, 481, 931, 816, 813, 233, 566, 247,\r
+   985, 724, 205, 454, 863, 491, 741, 242, 949, 214,\r
+   733, 859, 335, 708, 621, 574, 73, 654, 730, 472,\r
+   419, 436, 278, 496, 867, 210, 399, 680, 480, 51,\r
+   878, 465, 811, 169, 869, 675, 611, 697, 867, 561,\r
+   862, 687, 507, 283, 482, 129, 807, 591, 733, 623,\r
+   150, 238, 59, 379, 684, 877, 625, 169, 643, 105,\r
+   170, 607, 520, 932, 727, 476, 693, 425, 174, 647,\r
+   73, 122, 335, 530, 442, 853, 695, 249, 445, 515,\r
+   909, 545, 703, 919, 874, 474, 882, 500, 594, 612,\r
+   641, 801, 220, 162, 819, 984, 589, 513, 495, 799,\r
+   161, 604, 958, 533, 221, 400, 386, 867, 600, 782,\r
+   382, 596, 414, 171, 516, 375, 682, 485, 911, 276,\r
+   98, 553, 163, 354, 666, 933, 424, 341, 533, 870,\r
+   227, 730, 475, 186, 263, 647, 537, 686, 600, 224,\r
+   469, 68, 770, 919, 190, 373, 294, 822, 808, 206,\r
+   184, 943, 795, 384, 383, 461, 404, 758, 839, 887,\r
+   715, 67, 618, 276, 204, 918, 873, 777, 604, 560,\r
+   951, 160, 578, 722, 79, 804, 96, 409, 713, 940,\r
+   652, 934, 970, 447, 318, 353, 859, 672, 112, 785,\r
+   645, 863, 803, 350, 139, 93, 354, 99, 820, 908,\r
+   609, 772, 154, 274, 580, 184, 79, 626, 630, 742,\r
+   653, 282, 762, 623, 680, 81, 927, 626, 789, 125,\r
+   411, 521, 938, 300, 821, 78, 343, 175, 128, 250,\r
+   170, 774, 972, 275, 999, 639, 495, 78, 352, 126,\r
+   857, 956, 358, 619, 580, 124, 737, 594, 701, 612,\r
+   669, 112, 134, 694, 363, 992, 809, 743, 168, 974,\r
+   944, 375, 748, 52, 600, 747, 642, 182, 862, 81,\r
+   344, 805, 988, 739, 511, 655, 814, 334, 249, 515,\r
+   897, 955, 664, 981, 649, 113, 974, 459, 893, 228,\r
+   433, 837, 553, 268, 926, 240, 102, 654, 459, 51,\r
+   686, 754, 806, 760, 493, 403, 415, 394, 687, 700,\r
+   946, 670, 656, 610, 738, 392, 760, 799, 887, 653,\r
+   978, 321, 576, 617, 626, 502, 894, 679, 243, 440,\r
+   680, 879, 194, 572, 640, 724, 926, 56, 204, 700,\r
+   707, 151, 457, 449, 797, 195, 791, 558, 945, 679,\r
+   297, 59, 87, 824, 713, 663, 412, 693, 342, 606,\r
+   134, 108, 571, 364, 631, 212, 174, 643, 304, 329,\r
+   343, 97, 430, 751, 497, 314, 983, 374, 822, 928,\r
+   140, 206, 73, 263, 980, 736, 876, 478, 430, 305,\r
+   170, 514, 364, 692, 829, 82, 855, 953, 676, 246,\r
+   369, 970, 294, 750, 807, 827, 150, 790, 288, 923,\r
+   804, 378, 215, 828, 592, 281, 565, 555, 710, 82,\r
+   896, 831, 547, 261, 524, 462, 293, 465, 502, 56,\r
+   661, 821, 976, 991, 658, 869, 905, 758, 745, 193,\r
+   768, 550, 608, 933, 378, 286, 215, 979, 792, 961,\r
+   61, 688, 793, 644, 986, 403, 106, 366, 905, 644,\r
+   372, 567, 466, 434, 645, 210, 389, 550, 919, 135,\r
+   780, 773, 635, 389, 707, 100, 626, 958, 165, 504,\r
+   920, 176, 193, 713, 857, 265, 203, 50, 668, 108,\r
+   645, 990, 626, 197, 510, 357, 358, 850, 858, 364,\r
+   936, 638\r
+};\r
+\r
+bool CState::Alloc()\r
+{\r
+  if (!Counters)\r
+    Counters = (UInt32 *)::BigAlloc((256 + kBlockSizeMax) * sizeof(UInt32));\r
+  return (Counters != 0);\r
+}\r
+\r
+void CState::Free()\r
+{\r
+  ::BigFree(Counters);\r
+  Counters = 0;\r
+}\r
+\r
+UInt32 CDecoder::ReadBits(unsigned numBits) { return m_InStream.ReadBits(numBits); }\r
+Byte CDecoder::ReadByte() {return (Byte)ReadBits(8); }\r
+bool CDecoder::ReadBit() { return ReadBits(1) != 0; }\r
+\r
+UInt32 CDecoder::ReadCrc()\r
+{\r
+  UInt32 crc = 0;\r
+  for (int i = 0; i < 4; i++)\r
+  {\r
+    crc <<= 8;\r
+    crc |= ReadByte();\r
+  }\r
+  return crc;\r
+}\r
+\r
+static UInt32 NO_INLINE ReadBits(NBitm::CDecoder<CInBuffer> *m_InStream, unsigned num)\r
+{\r
+  return m_InStream->ReadBits(num);\r
+}\r
+\r
+static UInt32 NO_INLINE ReadBit(NBitm::CDecoder<CInBuffer> *m_InStream)\r
+{\r
+  return m_InStream->ReadBits(1);\r
+}\r
+\r
+static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder<CInBuffer> *m_InStream,\r
+    UInt32 *CharCounters, UInt32 blockSizeMax, Byte *m_Selectors, CHuffmanDecoder *m_HuffmanDecoders,\r
+    UInt32 *blockSizeRes, UInt32 *origPtrRes, bool *randRes)\r
+{\r
+  if (randRes)\r
+    *randRes = ReadBit(m_InStream) ? true : false;\r
+  *origPtrRes = ReadBits(m_InStream, kNumOrigBits);\r
+  \r
+  // in original code it compares OrigPtr to (UInt32)(10 + blockSizeMax)) : why ?\r
+  if (*origPtrRes >= blockSizeMax)\r
+    return S_FALSE;\r
+\r
+  CMtf8Decoder mtf;\r
+  mtf.StartInit();\r
+  \r
+  int numInUse = 0;\r
+  {\r
+    Byte inUse16[16];\r
+    int i;\r
+    for (i = 0; i < 16; i++)\r
+      inUse16[i] = (Byte)ReadBit(m_InStream);\r
+    for (i = 0; i < 256; i++)\r
+      if (inUse16[i >> 4])\r
+      {\r
+        if (ReadBit(m_InStream))\r
+          mtf.Add(numInUse++, (Byte)i);\r
+      }\r
+    if (numInUse == 0)\r
+      return S_FALSE;\r
+    // mtf.Init(numInUse);\r
+  }\r
+  int alphaSize = numInUse + 2;\r
+\r
+  int numTables = ReadBits(m_InStream, kNumTablesBits);\r
+  if (numTables < kNumTablesMin || numTables > kNumTablesMax)\r
+    return S_FALSE;\r
+  \r
+  UInt32 numSelectors = ReadBits(m_InStream, kNumSelectorsBits);\r
+  if (numSelectors < 1 || numSelectors > kNumSelectorsMax)\r
+    return S_FALSE;\r
+\r
+  {\r
+    Byte mtfPos[kNumTablesMax];\r
+    int t = 0;\r
+    do\r
+      mtfPos[t] = (Byte)t;\r
+    while(++t < numTables);\r
+    UInt32 i = 0;\r
+    do\r
+    {\r
+      int j = 0;\r
+      while (ReadBit(m_InStream))\r
+        if (++j >= numTables)\r
+          return S_FALSE;\r
+      Byte tmp = mtfPos[j];\r
+      for (;j > 0; j--)\r
+        mtfPos[j] = mtfPos[j - 1];\r
+      m_Selectors[i] = mtfPos[0] = tmp;\r
+    }\r
+    while(++i < numSelectors);\r
+  }\r
+\r
+  int t = 0;\r
+  do\r
+  {\r
+    Byte lens[kMaxAlphaSize];\r
+    int len = (int)ReadBits(m_InStream, kNumLevelsBits);\r
+    int i;\r
+    for (i = 0; i < alphaSize; i++)\r
+    {\r
+      for (;;)\r
+      {\r
+        if (len < 1 || len > kMaxHuffmanLen)\r
+          return S_FALSE;\r
+        if (!ReadBit(m_InStream))\r
+          break;\r
+        len += 1 - (int)(ReadBit(m_InStream) << 1);\r
+      }\r
+      lens[i] = (Byte)len;\r
+    }\r
+    for (; i < kMaxAlphaSize; i++)\r
+      lens[i] = 0;\r
+    if(!m_HuffmanDecoders[t].SetCodeLengths(lens))\r
+      return S_FALSE;\r
+  }\r
+  while(++t < numTables);\r
+\r
+  {\r
+    for (int i = 0; i < 256; i++)\r
+      CharCounters[i] = 0;\r
+  }\r
+  \r
+  UInt32 blockSize = 0;\r
+  {\r
+    UInt32 groupIndex = 0;\r
+    UInt32 groupSize = 0;\r
+    CHuffmanDecoder *huffmanDecoder = 0;\r
+    int runPower = 0;\r
+    UInt32 runCounter = 0;\r
+    \r
+    for (;;)\r
+    {\r
+      if (groupSize == 0)\r
+      {\r
+        if (groupIndex >= numSelectors)\r
+          return S_FALSE;\r
+        groupSize = kGroupSize;\r
+        huffmanDecoder = &m_HuffmanDecoders[m_Selectors[groupIndex++]];\r
+      }\r
+      groupSize--;\r
+        \r
+      UInt32 nextSym = huffmanDecoder->DecodeSymbol(m_InStream);\r
+      \r
+      if (nextSym < 2)\r
+      {\r
+        runCounter += ((UInt32)(nextSym + 1) << runPower++);\r
+        if (blockSizeMax - blockSize < runCounter)\r
+          return S_FALSE;\r
+        continue;\r
+      }\r
+      if (runCounter != 0)\r
+      {\r
+        UInt32 b = (UInt32)mtf.GetHead();\r
+        CharCounters[b] += runCounter;\r
+        do\r
+          CharCounters[256 + blockSize++] = b;\r
+        while(--runCounter != 0);\r
+        runPower = 0;\r
+      }\r
+      if (nextSym <= (UInt32)numInUse)\r
+      {\r
+        UInt32 b = (UInt32)mtf.GetAndMove((int)nextSym - 1);\r
+        if (blockSize >= blockSizeMax)\r
+          return S_FALSE;\r
+        CharCounters[b]++;\r
+        CharCounters[256 + blockSize++] = b;\r
+      }\r
+      else if (nextSym == (UInt32)numInUse + 1)\r
+        break;\r
+      else\r
+        return S_FALSE;\r
+    }\r
+  }\r
+  *blockSizeRes = blockSize;\r
+  return (*origPtrRes < blockSize) ? S_OK : S_FALSE;\r
+}\r
+\r
+static void NO_INLINE DecodeBlock1(UInt32 *charCounters, UInt32 blockSize)\r
+{\r
+  {\r
+    UInt32 sum = 0;\r
+    for (UInt32 i = 0; i < 256; i++)\r
+    {\r
+      sum += charCounters[i];\r
+      charCounters[i] = sum - charCounters[i];\r
+    }\r
+  }\r
+  \r
+  UInt32 *tt = charCounters + 256;\r
+  // Compute the T^(-1) vector\r
+  UInt32 i = 0;\r
+  do\r
+    tt[charCounters[tt[i] & 0xFF]++] |= (i << 8);\r
+  while(++i < blockSize);\r
+}\r
+\r
+static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32 OrigPtr, COutBuffer &m_OutStream)\r
+{\r
+  CBZip2Crc crc;\r
+\r
+  // it's for speed optimization: prefetch & prevByte_init;\r
+  UInt32 tPos = tt[tt[OrigPtr] >> 8];\r
+  unsigned prevByte = (unsigned)(tPos & 0xFF);\r
+  \r
+  unsigned numReps = 0;\r
+\r
+  do\r
+  {\r
+    unsigned b = (unsigned)(tPos & 0xFF);\r
+    tPos = tt[tPos >> 8];\r
+    \r
+    if (numReps == kRleModeRepSize)\r
+    {\r
+      for (; b > 0; b--)\r
+      {\r
+        crc.UpdateByte(prevByte);\r
+        m_OutStream.WriteByte((Byte)prevByte);\r
+      }\r
+      numReps = 0;\r
+      continue;\r
+    }\r
+    if (b != prevByte)\r
+      numReps = 0;\r
+    numReps++;\r
+    prevByte = b;\r
+    crc.UpdateByte(b);\r
+    m_OutStream.WriteByte((Byte)b);\r
+\r
+    /*\r
+    prevByte = b;\r
+    crc.UpdateByte(b);\r
+    m_OutStream.WriteByte((Byte)b);\r
+    for (; --blockSize != 0;)\r
+    {\r
+      b = (unsigned)(tPos & 0xFF);\r
+      tPos = tt[tPos >> 8];\r
+      crc.UpdateByte(b);\r
+      m_OutStream.WriteByte((Byte)b);\r
+      if (b != prevByte)\r
+      {\r
+        prevByte = b;\r
+        continue;\r
+      }\r
+      if (--blockSize == 0)\r
+        break;\r
+      \r
+      b = (unsigned)(tPos & 0xFF);\r
+      tPos = tt[tPos >> 8];\r
+      crc.UpdateByte(b);\r
+      m_OutStream.WriteByte((Byte)b);\r
+      if (b != prevByte)\r
+      {\r
+        prevByte = b;\r
+        continue;\r
+      }\r
+      if (--blockSize == 0)\r
+        break;\r
+      \r
+      b = (unsigned)(tPos & 0xFF);\r
+      tPos = tt[tPos >> 8];\r
+      crc.UpdateByte(b);\r
+      m_OutStream.WriteByte((Byte)b);\r
+      if (b != prevByte)\r
+      {\r
+        prevByte = b;\r
+        continue;\r
+      }\r
+      --blockSize;\r
+      break;\r
+    }\r
+    if (blockSize == 0)\r
+      break;\r
+\r
+    b = (unsigned)(tPos & 0xFF);\r
+    tPos = tt[tPos >> 8];\r
+    \r
+    for (; b > 0; b--)\r
+    {\r
+      crc.UpdateByte(prevByte);\r
+      m_OutStream.WriteByte((Byte)prevByte);\r
+    }\r
+    */\r
+  }\r
+  while(--blockSize != 0);\r
+  return crc.GetDigest();\r
+}\r
+\r
+static UInt32 NO_INLINE DecodeBlock2Rand(const UInt32 *tt, UInt32 blockSize, UInt32 OrigPtr, COutBuffer &m_OutStream)\r
+{\r
+  CBZip2Crc crc;\r
+  \r
+  UInt32 randIndex = 1;\r
+  UInt32 randToGo = kRandNums[0] - 2;\r
+  \r
+  unsigned numReps = 0;\r
+\r
+  // it's for speed optimization: prefetch & prevByte_init;\r
+  UInt32 tPos = tt[tt[OrigPtr] >> 8];\r
+  unsigned prevByte = (unsigned)(tPos & 0xFF);\r
+  \r
+  do\r
+  {\r
+    unsigned b = (unsigned)(tPos & 0xFF);\r
+    tPos = tt[tPos >> 8];\r
+    \r
+    {\r
+      if (randToGo == 0)\r
+      {\r
+        b ^= 1;\r
+        randToGo = kRandNums[randIndex++];\r
+        randIndex &= 0x1FF;\r
+      }\r
+      randToGo--;\r
+    }\r
+    \r
+    if (numReps == kRleModeRepSize)\r
+    {\r
+      for (; b > 0; b--)\r
+      {\r
+        crc.UpdateByte(prevByte);\r
+        m_OutStream.WriteByte((Byte)prevByte);\r
+      }\r
+      numReps = 0;\r
+      continue;\r
+    }\r
+    if (b != prevByte)\r
+      numReps = 0;\r
+    numReps++;\r
+    prevByte = b;\r
+    crc.UpdateByte(b);\r
+    m_OutStream.WriteByte((Byte)b);\r
+  }\r
+  while(--blockSize != 0);\r
+  return crc.GetDigest();\r
+}\r
+\r
+\r
+CDecoder::CDecoder()\r
+{\r
+  #ifndef _7ZIP_ST\r
+  m_States = 0;\r
+  m_NumThreadsPrev = 0;\r
+  NumThreads = 1;\r
+  #endif\r
+  _needInStreamInit = true;\r
+}\r
+\r
+#ifndef _7ZIP_ST\r
+\r
+CDecoder::~CDecoder()\r
+{\r
+  Free();\r
+}\r
+\r
+#define RINOK_THREAD(x) { WRes __result_ = (x); if(__result_ != 0) return __result_; }\r
+\r
+HRESULT CDecoder::Create()\r
+{\r
+  RINOK_THREAD(CanProcessEvent.CreateIfNotCreated());\r
+  RINOK_THREAD(CanStartWaitingEvent.CreateIfNotCreated());\r
+  if (m_States != 0 && m_NumThreadsPrev == NumThreads)\r
+    return S_OK;\r
+  Free();\r
+  MtMode = (NumThreads > 1);\r
+  m_NumThreadsPrev = NumThreads;\r
+  try\r
+  {\r
+    m_States = new CState[NumThreads];\r
+    if (!m_States)\r
+      return E_OUTOFMEMORY;\r
+  }\r
+  catch(...) { return E_OUTOFMEMORY; }\r
+  for (UInt32 t = 0; t < NumThreads; t++)\r
+  {\r
+    CState &ti = m_States[t];\r
+    ti.Decoder = this;\r
+    if (MtMode)\r
+    {\r
+      HRESULT res = ti.Create();\r
+      if (res != S_OK)\r
+      {\r
+        NumThreads = t;\r
+        Free();\r
+        return res;\r
+      }\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+void CDecoder::Free()\r
+{\r
+  if (!m_States)\r
+    return;\r
+  CloseThreads = true;\r
+  CanProcessEvent.Set();\r
+  for (UInt32 t = 0; t < NumThreads; t++)\r
+  {\r
+    CState &s = m_States[t];\r
+    if (MtMode)\r
+      s.Thread.Wait();\r
+    s.Free();\r
+  }\r
+  delete []m_States;\r
+  m_States = 0;\r
+}\r
+\r
+#endif\r
+\r
+HRESULT CDecoder::ReadSignatures(bool &wasFinished, UInt32 &crc)\r
+{\r
+  wasFinished = false;\r
+  Byte s[6];\r
+  for (int i = 0; i < 6; i++)\r
+    s[i] = ReadByte();\r
+  crc = ReadCrc();\r
+  if (s[0] == kFinSig0)\r
+  {\r
+    if (s[1] != kFinSig1 ||\r
+        s[2] != kFinSig2 ||\r
+        s[3] != kFinSig3 ||\r
+        s[4] != kFinSig4 ||\r
+        s[5] != kFinSig5)\r
+      return S_FALSE;\r
+    \r
+    wasFinished = true;\r
+    return (crc == CombinedCrc.GetDigest()) ? S_OK : S_FALSE;\r
+  }\r
+  if (s[0] != kBlockSig0 ||\r
+      s[1] != kBlockSig1 ||\r
+      s[2] != kBlockSig2 ||\r
+      s[3] != kBlockSig3 ||\r
+      s[4] != kBlockSig4 ||\r
+      s[5] != kBlockSig5)\r
+    return S_FALSE;\r
+  CombinedCrc.Update(crc);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CDecoder::DecodeFile(bool &isBZ, ICompressProgressInfo *progress)\r
+{\r
+  Progress = progress;\r
+  #ifndef _7ZIP_ST\r
+  RINOK(Create());\r
+  for (UInt32 t = 0; t < NumThreads; t++)\r
+  {\r
+    CState &s = m_States[t];\r
+    if (!s.Alloc())\r
+      return E_OUTOFMEMORY;\r
+    if (MtMode)\r
+    {\r
+      RINOK(s.StreamWasFinishedEvent.Reset());\r
+      RINOK(s.WaitingWasStartedEvent.Reset());\r
+      RINOK(s.CanWriteEvent.Reset());\r
+    }\r
+  }\r
+  #else\r
+  if (!m_States[0].Alloc())\r
+    return E_OUTOFMEMORY;\r
+  #endif\r
+\r
+  isBZ = false;\r
+  Byte s[6];\r
+  int i;\r
+  for (i = 0; i < 4; i++)\r
+    s[i] = ReadByte();\r
+  if (s[0] != kArSig0 ||\r
+      s[1] != kArSig1 ||\r
+      s[2] != kArSig2 ||\r
+      s[3] <= kArSig3 ||\r
+      s[3] > kArSig3 + kBlockSizeMultMax)\r
+    return S_OK;\r
+  isBZ = true;\r
+  UInt32 dicSize = (UInt32)(s[3] - kArSig3) * kBlockSizeStep;\r
+\r
+  CombinedCrc.Init();\r
+  #ifndef _7ZIP_ST\r
+  if (MtMode)\r
+  {\r
+    NextBlockIndex = 0;\r
+    StreamWasFinished1 = StreamWasFinished2 = false;\r
+    CloseThreads = false;\r
+    CanStartWaitingEvent.Reset();\r
+    m_States[0].CanWriteEvent.Set();\r
+    BlockSizeMax = dicSize;\r
+    Result1 = Result2 = S_OK;\r
+    CanProcessEvent.Set();\r
+    UInt32 t;\r
+    for (t = 0; t < NumThreads; t++)\r
+      m_States[t].StreamWasFinishedEvent.Lock();\r
+    CanProcessEvent.Reset();\r
+    CanStartWaitingEvent.Set();\r
+    for (t = 0; t < NumThreads; t++)\r
+      m_States[t].WaitingWasStartedEvent.Lock();\r
+    CanStartWaitingEvent.Reset();\r
+    RINOK(Result2);\r
+    RINOK(Result1);\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    CState &state = m_States[0];\r
+    for (;;)\r
+    {\r
+      RINOK(SetRatioProgress(m_InStream.GetProcessedSize()));\r
+      bool wasFinished;\r
+      UInt32 crc;\r
+      RINOK(ReadSignatures(wasFinished, crc));\r
+      if (wasFinished)\r
+        return S_OK;\r
+\r
+      UInt32 blockSize, origPtr;\r
+      bool randMode;\r
+      RINOK(ReadBlock(&m_InStream, state.Counters, dicSize,\r
+        m_Selectors, m_HuffmanDecoders,\r
+        &blockSize, &origPtr, &randMode));\r
+      DecodeBlock1(state.Counters, blockSize);\r
+      if ((randMode ?\r
+          DecodeBlock2Rand(state.Counters + 256, blockSize, origPtr, m_OutStream) :\r
+          DecodeBlock2(state.Counters + 256, blockSize, origPtr, m_OutStream)) != crc)\r
+        return S_FALSE;\r
+    }\r
+  }\r
+  return SetRatioProgress(m_InStream.GetProcessedSize());\r
+}\r
+\r
+HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    bool &isBZ, ICompressProgressInfo *progress)\r
+{\r
+  isBZ = false;\r
+  try\r
+  {\r
+\r
+  if (!m_InStream.Create(kBufferSize))\r
+    return E_OUTOFMEMORY;\r
+  if (!m_OutStream.Create(kBufferSize))\r
+    return E_OUTOFMEMORY;\r
+\r
+  if (inStream)\r
+    m_InStream.SetStream(inStream);\r
+\r
+  CDecoderFlusher flusher(this, inStream != NULL);\r
+\r
+  if (_needInStreamInit)\r
+  {\r
+    m_InStream.Init();\r
+    _needInStreamInit = false;\r
+  }\r
+  _inStart = m_InStream.GetProcessedSize();\r
+\r
+  m_InStream.AlignToByte();\r
+\r
+  m_OutStream.SetStream(outStream);\r
+  m_OutStream.Init();\r
+\r
+  RINOK(DecodeFile(isBZ, progress));\r
+  flusher.NeedFlush = false;\r
+  return Flush();\r
+\r
+  }\r
+  catch(const CInBufferException &e)  { return e.ErrorCode; }\r
+  catch(const COutBufferException &e) { return e.ErrorCode; }\r
+  catch(...) { return E_FAIL; }\r
+}\r
+\r
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)\r
+{\r
+  _needInStreamInit = true;\r
+  bool isBZ;\r
+  RINOK(CodeReal(inStream, outStream, isBZ, progress));\r
+  return isBZ ? S_OK : S_FALSE;\r
+}\r
+\r
+HRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, bool &isBZ, ICompressProgressInfo *progress)\r
+{\r
+  return CodeReal(NULL, outStream, isBZ, progress);\r
+}\r
+\r
+STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { m_InStream.SetStream(inStream); return S_OK; }\r
+STDMETHODIMP CDecoder::ReleaseInStream() { m_InStream.ReleaseStream(); return S_OK; }\r
+\r
+#ifndef _7ZIP_ST\r
+\r
+static THREAD_FUNC_DECL MFThread(void *p) { ((CState *)p)->ThreadFunc(); return 0; }\r
+\r
+HRESULT CState::Create()\r
+{\r
+  RINOK_THREAD(StreamWasFinishedEvent.CreateIfNotCreated());\r
+  RINOK_THREAD(WaitingWasStartedEvent.CreateIfNotCreated());\r
+  RINOK_THREAD(CanWriteEvent.CreateIfNotCreated());\r
+  RINOK_THREAD(Thread.Create(MFThread, this));\r
+  return S_OK;\r
+}\r
+\r
+void CState::FinishStream()\r
+{\r
+  Decoder->StreamWasFinished1 = true;\r
+  StreamWasFinishedEvent.Set();\r
+  Decoder->CS.Leave();\r
+  Decoder->CanStartWaitingEvent.Lock();\r
+  WaitingWasStartedEvent.Set();\r
+}\r
+\r
+void CState::ThreadFunc()\r
+{\r
+  for (;;)\r
+  {\r
+    Decoder->CanProcessEvent.Lock();\r
+    Decoder->CS.Enter();\r
+    if (Decoder->CloseThreads)\r
+    {\r
+      Decoder->CS.Leave();\r
+      return;\r
+    }\r
+    if (Decoder->StreamWasFinished1)\r
+    {\r
+      FinishStream();\r
+      continue;\r
+    }\r
+    HRESULT res = S_OK;\r
+\r
+    UInt32 blockIndex = Decoder->NextBlockIndex;\r
+    UInt32 nextBlockIndex = blockIndex + 1;\r
+    if (nextBlockIndex == Decoder->NumThreads)\r
+      nextBlockIndex = 0;\r
+    Decoder->NextBlockIndex = nextBlockIndex;\r
+    UInt32 crc;\r
+    UInt64 packSize = 0;\r
+    UInt32 blockSize = 0, origPtr = 0;\r
+    bool randMode = false;\r
+\r
+    try\r
+    {\r
+      bool wasFinished;\r
+      res = Decoder->ReadSignatures(wasFinished, crc);\r
+      if (res != S_OK)\r
+      {\r
+        Decoder->Result1 = res;\r
+        FinishStream();\r
+        continue;\r
+      }\r
+      if (wasFinished)\r
+      {\r
+        Decoder->Result1 = res;\r
+        FinishStream();\r
+        continue;\r
+      }\r
+\r
+      res = ReadBlock(&Decoder->m_InStream, Counters, Decoder->BlockSizeMax,\r
+          Decoder->m_Selectors, Decoder->m_HuffmanDecoders,\r
+          &blockSize, &origPtr, &randMode);\r
+      if (res != S_OK)\r
+      {\r
+        Decoder->Result1 = res;\r
+        FinishStream();\r
+        continue;\r
+      }\r
+      packSize = Decoder->m_InStream.GetProcessedSize();\r
+    }\r
+    catch(const CInBufferException &e) { res = e.ErrorCode;  if (res != S_OK) res = E_FAIL; }\r
+    catch(...) { res = E_FAIL; }\r
+    if (res != S_OK)\r
+    {\r
+      Decoder->Result1 = res;\r
+      FinishStream();\r
+      continue;\r
+    }\r
+\r
+    Decoder->CS.Leave();\r
+\r
+    DecodeBlock1(Counters, blockSize);\r
+\r
+    bool needFinish = true;\r
+    try\r
+    {\r
+      Decoder->m_States[blockIndex].CanWriteEvent.Lock();\r
+      needFinish = Decoder->StreamWasFinished2;\r
+      if (!needFinish)\r
+      {\r
+        if ((randMode ?\r
+            DecodeBlock2Rand(Counters + 256, blockSize, origPtr, Decoder->m_OutStream) :\r
+            DecodeBlock2(Counters + 256, blockSize, origPtr, Decoder->m_OutStream)) == crc)\r
+          res = Decoder->SetRatioProgress(packSize);\r
+        else\r
+          res = S_FALSE;\r
+      }\r
+    }\r
+    catch(const COutBufferException &e) { res = e.ErrorCode; if (res != S_OK) res = E_FAIL; }\r
+    catch(...) { res = E_FAIL; }\r
+    if (res != S_OK)\r
+    {\r
+      Decoder->Result2 = res;\r
+      Decoder->StreamWasFinished2 = true;\r
+    }\r
+    Decoder->m_States[nextBlockIndex].CanWriteEvent.Set();\r
+    if (res != S_OK || needFinish)\r
+    {\r
+      StreamWasFinishedEvent.Set();\r
+      Decoder->CanStartWaitingEvent.Lock();\r
+      WaitingWasStartedEvent.Set();\r
+    }\r
+  }\r
+}\r
+\r
+STDMETHODIMP CDecoder::SetNumberOfThreads(UInt32 numThreads)\r
+{\r
+  NumThreads = numThreads;\r
+  if (NumThreads < 1)\r
+    NumThreads = 1;\r
+  if (NumThreads > kNumThreadsMax)\r
+    NumThreads = kNumThreadsMax;\r
+  return S_OK;\r
+}\r
+\r
+#endif\r
+\r
+HRESULT CDecoder::SetRatioProgress(UInt64 packSize)\r
+{\r
+  if (!Progress)\r
+    return S_OK;\r
+  packSize -= _inStart;\r
+  UInt64 unpackSize = m_OutStream.GetProcessedSize();\r
+  return Progress->SetRatioInfo(&packSize, &unpackSize);\r
+}\r
+\r
+\r
+// ---------- NSIS ----------\r
+\r
+enum\r
+{\r
+  NSIS_STATE_INIT,\r
+  NSIS_STATE_NEW_BLOCK,\r
+  NSIS_STATE_DATA,\r
+  NSIS_STATE_FINISHED,\r
+  NSIS_STATE_ERROR\r
+};\r
+\r
+STDMETHODIMP CNsisDecoder::SetInStream(ISequentialInStream *inStream) { m_InStream.SetStream(inStream); return S_OK; }\r
+STDMETHODIMP CNsisDecoder::ReleaseInStream() { m_InStream.ReleaseStream(); return S_OK; }\r
+\r
+STDMETHODIMP CNsisDecoder::SetOutStreamSize(const UInt64 * /* outSize */)\r
+{\r
+  _nsisState = NSIS_STATE_INIT;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CNsisDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  try {\r
+\r
+  *processedSize = 0;\r
+  if (_nsisState == NSIS_STATE_FINISHED)\r
+    return S_OK;\r
+  if (_nsisState == NSIS_STATE_ERROR)\r
+    return S_FALSE;\r
+  if (size == 0)\r
+    return S_OK;\r
+\r
+  CState &state = m_State;\r
+\r
+  if (_nsisState == NSIS_STATE_INIT)\r
+  {\r
+    if (!m_InStream.Create(kBufferSize))\r
+      return E_OUTOFMEMORY;\r
+    if (!state.Alloc())\r
+      return E_OUTOFMEMORY;\r
+    m_InStream.Init();\r
+    _nsisState = NSIS_STATE_NEW_BLOCK;\r
+  }\r
+\r
+  if (_nsisState == NSIS_STATE_NEW_BLOCK)\r
+  {\r
+    Byte b = (Byte)m_InStream.ReadBits(8);\r
+    if (b == kFinSig0)\r
+    {\r
+      _nsisState = NSIS_STATE_FINISHED;\r
+      return S_OK;\r
+    }\r
+    if (b != kBlockSig0)\r
+    {\r
+      _nsisState = NSIS_STATE_ERROR;\r
+      return S_FALSE;\r
+    }\r
+    UInt32 origPtr;\r
+    RINOK(ReadBlock(&m_InStream, state.Counters, 9 * kBlockSizeStep,\r
+        m_Selectors, m_HuffmanDecoders, &_blockSize, &origPtr, NULL));\r
+    DecodeBlock1(state.Counters, _blockSize);\r
+    const UInt32 *tt = state.Counters + 256;\r
+    _tPos = tt[tt[origPtr] >> 8];\r
+    _prevByte = (unsigned)(_tPos & 0xFF);\r
+    _numReps = 0;\r
+    _repRem = 0;\r
+    _nsisState = NSIS_STATE_DATA;\r
+  }\r
+\r
+  UInt32 tPos = _tPos;\r
+  unsigned prevByte = _prevByte;\r
+  unsigned numReps = _numReps;\r
+  UInt32 blockSize = _blockSize;\r
+  const UInt32 *tt = state.Counters + 256;\r
+\r
+  while (_repRem)\r
+  {\r
+    _repRem--;\r
+    *(Byte *)data = (Byte)prevByte;\r
+    data = (Byte *)data + 1;\r
+    (*processedSize)++;\r
+    if (--size == 0)\r
+      return S_OK;\r
+  }\r
+\r
+  if (blockSize == 0)\r
+  {\r
+    _nsisState = NSIS_STATE_NEW_BLOCK;\r
+    return S_OK;\r
+  }\r
+\r
+  do\r
+  {\r
+    unsigned b = (unsigned)(tPos & 0xFF);\r
+    tPos = tt[tPos >> 8];\r
+    blockSize--;\r
+    \r
+    if (numReps == kRleModeRepSize)\r
+    {\r
+      numReps = 0;\r
+      while (b)\r
+      {\r
+        b--;\r
+        *(Byte *)data = (Byte)prevByte;\r
+        data = (Byte *)data + 1;\r
+        (*processedSize)++;\r
+        if (--size == 0)\r
+          break;\r
+      }\r
+      _repRem = b;\r
+      continue;\r
+    }\r
+    if (b != prevByte)\r
+      numReps = 0;\r
+    numReps++;\r
+    prevByte = b;\r
+    *(Byte *)data = (Byte)b;\r
+    data = (Byte *)data + 1;\r
+    (*processedSize)++;\r
+    size--;\r
+  }\r
+  while (size && blockSize);\r
+  _tPos = tPos;\r
+  _prevByte = prevByte;\r
+  _numReps = numReps;\r
+  _blockSize = blockSize;\r
+  return S_OK;\r
+\r
+  }\r
+  catch(const CInBufferException &e)  { return e.ErrorCode; }\r
+  catch(...) { return S_FALSE; }\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Compress/BZip2Decoder.h b/CPP/7zip/Compress/BZip2Decoder.h
new file mode 100755 (executable)
index 0000000..822a287
--- /dev/null
@@ -0,0 +1,205 @@
+// Compress/BZip2Decoder.h\r
+\r
+#ifndef __COMPRESS_BZIP2_DECODER_H\r
+#define __COMPRESS_BZIP2_DECODER_H\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#ifndef _7ZIP_ST\r
+#include "../../Windows/Synchronization.h"\r
+#include "../../Windows/Thread.h"\r
+#endif\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "../Common/InBuffer.h"\r
+#include "../Common/OutBuffer.h"\r
+\r
+#include "BitmDecoder.h"\r
+#include "BZip2Const.h"\r
+#include "BZip2Crc.h"\r
+#include "HuffmanDecoder.h"\r
+\r
+namespace NCompress {\r
+namespace NBZip2 {\r
+\r
+typedef NCompress::NHuffman::CDecoder<kMaxHuffmanLen, kMaxAlphaSize> CHuffmanDecoder;\r
+\r
+class CDecoder;\r
+\r
+struct CState\r
+{\r
+  UInt32 *Counters;\r
+\r
+  #ifndef _7ZIP_ST\r
+\r
+  CDecoder *Decoder;\r
+  NWindows::CThread Thread;\r
+  bool m_OptimizeNumTables;\r
+\r
+  NWindows::NSynchronization::CAutoResetEvent StreamWasFinishedEvent;\r
+  NWindows::NSynchronization::CAutoResetEvent WaitingWasStartedEvent;\r
+\r
+  // it's not member of this thread. We just need one event per thread\r
+  NWindows::NSynchronization::CAutoResetEvent CanWriteEvent;\r
+\r
+  Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size.\r
+\r
+  HRESULT Create();\r
+  void FinishStream();\r
+  void ThreadFunc();\r
+\r
+  #endif\r
+\r
+  CState(): Counters(0) {}\r
+  ~CState() { Free(); }\r
+  bool Alloc();\r
+  void Free();\r
+};\r
+\r
+class CDecoder :\r
+  public ICompressCoder,\r
+  #ifndef _7ZIP_ST\r
+  public ICompressSetCoderMt,\r
+  #endif\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  COutBuffer m_OutStream;\r
+  Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size.\r
+  NBitm::CDecoder<CInBuffer> m_InStream;\r
+  Byte m_Selectors[kNumSelectorsMax];\r
+  CHuffmanDecoder m_HuffmanDecoders[kNumTablesMax];\r
+  UInt64 _inStart;\r
+\r
+private:\r
+\r
+  bool _needInStreamInit;\r
+\r
+  UInt32 ReadBits(unsigned numBits);\r
+  Byte ReadByte();\r
+  bool ReadBit();\r
+  UInt32 ReadCrc();\r
+  HRESULT DecodeFile(bool &isBZ, ICompressProgressInfo *progress);\r
+  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      bool &isBZ, ICompressProgressInfo *progress);\r
+  class CDecoderFlusher\r
+  {\r
+    CDecoder *_decoder;\r
+  public:\r
+    bool NeedFlush;\r
+    bool ReleaseInStream;\r
+    CDecoderFlusher(CDecoder *decoder, bool releaseInStream):\r
+      _decoder(decoder),\r
+      ReleaseInStream(releaseInStream),\r
+      NeedFlush(true) {}\r
+    ~CDecoderFlusher()\r
+    {\r
+      if (NeedFlush)\r
+        _decoder->Flush();\r
+      _decoder->ReleaseStreams(ReleaseInStream);\r
+    }\r
+  };\r
+\r
+public:\r
+  CBZip2CombinedCrc CombinedCrc;\r
+  ICompressProgressInfo *Progress;\r
+\r
+  #ifndef _7ZIP_ST\r
+  CState *m_States;\r
+  UInt32 m_NumThreadsPrev;\r
+\r
+  NWindows::NSynchronization::CManualResetEvent CanProcessEvent;\r
+  NWindows::NSynchronization::CCriticalSection CS;\r
+  UInt32 NumThreads;\r
+  bool MtMode;\r
+  UInt32 NextBlockIndex;\r
+  bool CloseThreads;\r
+  bool StreamWasFinished1;\r
+  bool StreamWasFinished2;\r
+  NWindows::NSynchronization::CManualResetEvent CanStartWaitingEvent;\r
+\r
+  HRESULT Result1;\r
+  HRESULT Result2;\r
+\r
+  UInt32 BlockSizeMax;\r
+  ~CDecoder();\r
+  HRESULT Create();\r
+  void Free();\r
+\r
+  #else\r
+  CState m_States[1];\r
+  #endif\r
+\r
+  CDecoder();\r
+\r
+  HRESULT SetRatioProgress(UInt64 packSize);\r
+  HRESULT ReadSignatures(bool &wasFinished, UInt32 &crc);\r
+\r
+  HRESULT Flush() { return m_OutStream.Flush(); }\r
+  void ReleaseStreams(bool releaseInStream)\r
+  {\r
+    if (releaseInStream)\r
+      m_InStream.ReleaseStream();\r
+    m_OutStream.ReleaseStream();\r
+  }\r
+\r
+  MY_QUERYINTERFACE_BEGIN2(ICompressCoder)\r
+  #ifndef _7ZIP_ST\r
+  MY_QUERYINTERFACE_ENTRY(ICompressSetCoderMt)\r
+  #endif\r
+\r
+  MY_QUERYINTERFACE_END\r
+  MY_ADDREF_RELEASE\r
+\r
+  \r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+  STDMETHOD(SetInStream)(ISequentialInStream *inStream);\r
+  STDMETHOD(ReleaseInStream)();\r
+\r
+  HRESULT CodeResume(ISequentialOutStream *outStream, bool &isBZ, ICompressProgressInfo *progress);\r
+  UInt64 GetInputProcessedSize() const { return m_InStream.GetProcessedSize(); }\r
+  \r
+  #ifndef _7ZIP_ST\r
+  STDMETHOD(SetNumberOfThreads)(UInt32 numThreads);\r
+  #endif\r
+};\r
+\r
+\r
+class CNsisDecoder :\r
+  public ISequentialInStream,\r
+  public ICompressSetInStream,\r
+  public ICompressSetOutStreamSize,\r
+  public CMyUnknownImp\r
+{\r
+  NBitm::CDecoder<CInBuffer> m_InStream;\r
+  Byte m_Selectors[kNumSelectorsMax];\r
+  CHuffmanDecoder m_HuffmanDecoders[kNumTablesMax];\r
+  CState m_State;\r
+  \r
+  int _nsisState;\r
+  UInt32 _tPos;\r
+  unsigned _prevByte;\r
+  unsigned _repRem;\r
+  unsigned _numReps;\r
+  UInt32 _blockSize;\r
+\r
+public:\r
+\r
+  MY_QUERYINTERFACE_BEGIN2(ISequentialInStream)\r
+  MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)\r
+  MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)\r
+  MY_QUERYINTERFACE_END\r
+  MY_ADDREF_RELEASE\r
+\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(SetInStream)(ISequentialInStream *inStream);\r
+  STDMETHOD(ReleaseInStream)();\r
+  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/BZip2Encoder.cpp b/CPP/7zip/Compress/BZip2Encoder.cpp
new file mode 100755 (executable)
index 0000000..165713e
--- /dev/null
@@ -0,0 +1,895 @@
+// BZip2Encoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+#include "../../../C/BwtSort.h"\r
+#include "../../../C/HuffEnc.h"\r
+\r
+#include "BZip2Crc.h"\r
+#include "BZip2Encoder.h"\r
+#include "Mtf8.h"\r
+\r
+namespace NCompress {\r
+namespace NBZip2 {\r
+\r
+const int kMaxHuffmanLenForEncoding = 16; // it must be < kMaxHuffmanLen = 20\r
+\r
+static const UInt32 kBufferSize = (1 << 17);\r
+static const int kNumHuffPasses = 4;\r
+\r
+bool CThreadInfo::Alloc()\r
+{\r
+  if (m_BlockSorterIndex == 0)\r
+  {\r
+    m_BlockSorterIndex = (UInt32 *)::BigAlloc(BLOCK_SORT_BUF_SIZE(kBlockSizeMax) * sizeof(UInt32));\r
+    if (m_BlockSorterIndex == 0)\r
+      return false;\r
+  }\r
+\r
+  if (m_Block == 0)\r
+  {\r
+    m_Block = (Byte *)::MidAlloc(kBlockSizeMax * 5 + kBlockSizeMax / 10 + (20 << 10));\r
+    if (m_Block == 0)\r
+      return false;\r
+    m_MtfArray = m_Block + kBlockSizeMax;\r
+    m_TempArray = m_MtfArray + kBlockSizeMax * 2 + 2;\r
+  }\r
+  return true;\r
+}\r
+\r
+void CThreadInfo::Free()\r
+{\r
+  ::BigFree(m_BlockSorterIndex);\r
+  m_BlockSorterIndex = 0;\r
+  ::MidFree(m_Block);\r
+  m_Block = 0;\r
+}\r
+\r
+#ifndef _7ZIP_ST\r
+\r
+static THREAD_FUNC_DECL MFThread(void *threadCoderInfo)\r
+{\r
+  return ((CThreadInfo *)threadCoderInfo)->ThreadFunc();\r
+}\r
+\r
+#define RINOK_THREAD(x) { WRes __result_ = (x); if(__result_ != 0) return __result_; }\r
+\r
+HRESULT CThreadInfo::Create()\r
+{\r
+  RINOK_THREAD(StreamWasFinishedEvent.Create());\r
+  RINOK_THREAD(WaitingWasStartedEvent.Create());\r
+  RINOK_THREAD(CanWriteEvent.Create());\r
+  RINOK_THREAD(Thread.Create(MFThread, this));\r
+  return S_OK;\r
+}\r
+\r
+void CThreadInfo::FinishStream(bool needLeave)\r
+{\r
+  Encoder->StreamWasFinished = true;\r
+  StreamWasFinishedEvent.Set();\r
+  if (needLeave)\r
+    Encoder->CS.Leave();\r
+  Encoder->CanStartWaitingEvent.Lock();\r
+  WaitingWasStartedEvent.Set();\r
+}\r
+\r
+DWORD CThreadInfo::ThreadFunc()\r
+{\r
+  for (;;)\r
+  {\r
+    Encoder->CanProcessEvent.Lock();\r
+    Encoder->CS.Enter();\r
+    if (Encoder->CloseThreads)\r
+    {\r
+      Encoder->CS.Leave();\r
+      return 0;\r
+    }\r
+    if (Encoder->StreamWasFinished)\r
+    {\r
+      FinishStream(true);\r
+      continue;\r
+    }\r
+    HRESULT res = S_OK;\r
+    bool needLeave = true;\r
+    try\r
+    {\r
+      UInt32 blockSize = Encoder->ReadRleBlock(m_Block);\r
+      m_PackSize = Encoder->m_InStream.GetProcessedSize();\r
+      m_BlockIndex = Encoder->NextBlockIndex;\r
+      if (++Encoder->NextBlockIndex == Encoder->NumThreads)\r
+        Encoder->NextBlockIndex = 0;\r
+      if (blockSize == 0)\r
+      {\r
+        FinishStream(true);\r
+        continue;\r
+      }\r
+      Encoder->CS.Leave();\r
+      needLeave = false;\r
+      res = EncodeBlock3(blockSize);\r
+    }\r
+    catch(const CInBufferException &e)  { res = e.ErrorCode; }\r
+    catch(const COutBufferException &e) { res = e.ErrorCode; }\r
+    catch(...) { res = E_FAIL; }\r
+    if (res != S_OK)\r
+    {\r
+      Encoder->Result = res;\r
+      FinishStream(needLeave);\r
+      continue;\r
+    }\r
+  }\r
+}\r
+\r
+#endif\r
+\r
+CEncoder::CEncoder():\r
+  NumPasses(1),\r
+  m_OptimizeNumTables(false),\r
+  m_BlockSizeMult(kBlockSizeMultMax)\r
+{\r
+  #ifndef _7ZIP_ST\r
+  ThreadsInfo = 0;\r
+  m_NumThreadsPrev = 0;\r
+  NumThreads = 1;\r
+  #endif\r
+}\r
+\r
+#ifndef _7ZIP_ST\r
+CEncoder::~CEncoder()\r
+{\r
+  Free();\r
+}\r
+\r
+HRESULT CEncoder::Create()\r
+{\r
+  RINOK_THREAD(CanProcessEvent.CreateIfNotCreated());\r
+  RINOK_THREAD(CanStartWaitingEvent.CreateIfNotCreated());\r
+  if (ThreadsInfo != 0 && m_NumThreadsPrev == NumThreads)\r
+    return S_OK;\r
+  try\r
+  {\r
+    Free();\r
+    MtMode = (NumThreads > 1);\r
+    m_NumThreadsPrev = NumThreads;\r
+    ThreadsInfo = new CThreadInfo[NumThreads];\r
+    if (ThreadsInfo == 0)\r
+      return E_OUTOFMEMORY;\r
+  }\r
+  catch(...) { return E_OUTOFMEMORY; }\r
+  for (UInt32 t = 0; t < NumThreads; t++)\r
+  {\r
+    CThreadInfo &ti = ThreadsInfo[t];\r
+    ti.Encoder = this;\r
+    if (MtMode)\r
+    {\r
+      HRESULT res = ti.Create();\r
+      if (res != S_OK)\r
+      {\r
+        NumThreads = t;\r
+        Free();\r
+        return res;\r
+      }\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+void CEncoder::Free()\r
+{\r
+  if (!ThreadsInfo)\r
+    return;\r
+  CloseThreads = true;\r
+  CanProcessEvent.Set();\r
+  for (UInt32 t = 0; t < NumThreads; t++)\r
+  {\r
+    CThreadInfo &ti = ThreadsInfo[t];\r
+    if (MtMode)\r
+      ti.Thread.Wait();\r
+    ti.Free();\r
+  }\r
+  delete []ThreadsInfo;\r
+  ThreadsInfo = 0;\r
+}\r
+#endif\r
+\r
+UInt32 CEncoder::ReadRleBlock(Byte *buffer)\r
+{\r
+  UInt32 i = 0;\r
+  Byte prevByte;\r
+  if (m_InStream.ReadByte(prevByte))\r
+  {\r
+    UInt32 blockSize = m_BlockSizeMult * kBlockSizeStep - 1;\r
+    int numReps = 1;\r
+    buffer[i++] = prevByte;\r
+    while (i < blockSize) // "- 1" to support RLE\r
+    {\r
+      Byte b;\r
+      if (!m_InStream.ReadByte(b))\r
+        break;\r
+      if (b != prevByte)\r
+      {\r
+        if (numReps >= kRleModeRepSize)\r
+          buffer[i++] = (Byte)(numReps - kRleModeRepSize);\r
+        buffer[i++] = b;\r
+        numReps = 1;\r
+        prevByte = b;\r
+        continue;\r
+      }\r
+      numReps++;\r
+      if (numReps <= kRleModeRepSize)\r
+        buffer[i++] = b;\r
+      else if (numReps == kRleModeRepSize + 255)\r
+      {\r
+        buffer[i++] = (Byte)(numReps - kRleModeRepSize);\r
+        numReps = 0;\r
+      }\r
+    }\r
+    // it's to support original BZip2 decoder\r
+    if (numReps >= kRleModeRepSize)\r
+      buffer[i++] = (Byte)(numReps - kRleModeRepSize);\r
+  }\r
+  return i;\r
+}\r
+\r
+void CThreadInfo::WriteBits2(UInt32 value, UInt32 numBits)\r
+  { m_OutStreamCurrent->WriteBits(value, numBits); }\r
+void CThreadInfo::WriteByte2(Byte b) { WriteBits2(b , 8); }\r
+void CThreadInfo::WriteBit2(bool v) { WriteBits2((v ? 1 : 0), 1); }\r
+void CThreadInfo::WriteCrc2(UInt32 v)\r
+{\r
+  for (int i = 0; i < 4; i++)\r
+    WriteByte2(((Byte)(v >> (24 - i * 8))));\r
+}\r
+\r
+void CEncoder::WriteBits(UInt32 value, UInt32 numBits)\r
+  { m_OutStream.WriteBits(value, numBits); }\r
+void CEncoder::WriteByte(Byte b) { WriteBits(b , 8); }\r
+void CEncoder::WriteBit(bool v) { WriteBits((v ? 1 : 0), 1); }\r
+void CEncoder::WriteCrc(UInt32 v)\r
+{\r
+  for (int i = 0; i < 4; i++)\r
+    WriteByte(((Byte)(v >> (24 - i * 8))));\r
+}\r
+\r
+\r
+// blockSize > 0\r
+void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)\r
+{\r
+  WriteBit2(false); // Randomised = false\r
+  \r
+  {\r
+    UInt32 origPtr = BlockSort(m_BlockSorterIndex, block, blockSize);\r
+    // if (m_BlockSorterIndex[origPtr] != 0) throw 1;\r
+    m_BlockSorterIndex[origPtr] = blockSize;\r
+    WriteBits2(origPtr, kNumOrigBits);\r
+  }\r
+\r
+  CMtf8Encoder mtf;\r
+  int numInUse = 0;\r
+  {\r
+    bool inUse[256];\r
+    bool inUse16[16];\r
+    UInt32 i;\r
+    for (i = 0; i < 256; i++)\r
+      inUse[i] = false;\r
+    for (i = 0; i < 16; i++)\r
+      inUse16[i] = false;\r
+    for (i = 0; i < blockSize; i++)\r
+      inUse[block[i]] = true;\r
+    for (i = 0; i < 256; i++)\r
+      if (inUse[i])\r
+      {\r
+        inUse16[i >> 4] = true;\r
+        mtf.Buf[numInUse++] = (Byte)i;\r
+      }\r
+    for (i = 0; i < 16; i++)\r
+      WriteBit2(inUse16[i]);\r
+    for (i = 0; i < 256; i++)\r
+      if (inUse16[i >> 4])\r
+        WriteBit2(inUse[i]);\r
+  }\r
+  int alphaSize = numInUse + 2;\r
+\r
+  Byte *mtfs = m_MtfArray;\r
+  UInt32 mtfArraySize = 0;\r
+  UInt32 symbolCounts[kMaxAlphaSize];\r
+  {\r
+    for (int i = 0; i < kMaxAlphaSize; i++)\r
+      symbolCounts[i] = 0;\r
+  }\r
+\r
+  {\r
+    UInt32 rleSize = 0;\r
+    UInt32 i = 0;\r
+    const UInt32 *bsIndex = m_BlockSorterIndex;\r
+    block--;\r
+    do\r
+    {\r
+      int pos = mtf.FindAndMove(block[bsIndex[i]]);\r
+      if (pos == 0)\r
+        rleSize++;\r
+      else\r
+      {\r
+        while (rleSize != 0)\r
+        {\r
+          rleSize--;\r
+          mtfs[mtfArraySize++] = (Byte)(rleSize & 1);\r
+          symbolCounts[rleSize & 1]++;\r
+          rleSize >>= 1;\r
+        }\r
+        if (pos >= 0xFE)\r
+        {\r
+          mtfs[mtfArraySize++] = 0xFF;\r
+          mtfs[mtfArraySize++] = (Byte)(pos - 0xFE);\r
+        }\r
+        else\r
+          mtfs[mtfArraySize++] = (Byte)(pos + 1);\r
+        symbolCounts[pos + 1]++;\r
+      }\r
+    }\r
+    while (++i < blockSize);\r
+\r
+    while (rleSize != 0)\r
+    {\r
+      rleSize--;\r
+      mtfs[mtfArraySize++] = (Byte)(rleSize & 1);\r
+      symbolCounts[rleSize & 1]++;\r
+      rleSize >>= 1;\r
+    }\r
+\r
+    if (alphaSize < 256)\r
+      mtfs[mtfArraySize++] = (Byte)(alphaSize - 1);\r
+    else\r
+    {\r
+      mtfs[mtfArraySize++] = 0xFF;\r
+      mtfs[mtfArraySize++] = (Byte)(alphaSize - 256);\r
+    }\r
+    symbolCounts[alphaSize - 1]++;\r
+  }\r
+\r
+  UInt32 numSymbols = 0;\r
+  {\r
+    for (int i = 0; i < kMaxAlphaSize; i++)\r
+      numSymbols += symbolCounts[i];\r
+  }\r
+\r
+  int bestNumTables = kNumTablesMin;\r
+  UInt32 bestPrice = 0xFFFFFFFF;\r
+  UInt32 startPos = m_OutStreamCurrent->GetPos();\r
+  Byte startCurByte = m_OutStreamCurrent->GetCurByte();\r
+  for (int nt = kNumTablesMin; nt <= kNumTablesMax + 1; nt++)\r
+  {\r
+    int numTables;\r
+\r
+    if(m_OptimizeNumTables)\r
+    {\r
+      m_OutStreamCurrent->SetPos(startPos);\r
+      m_OutStreamCurrent->SetCurState((startPos & 7), startCurByte);\r
+      if (nt <= kNumTablesMax)\r
+        numTables = nt;\r
+      else\r
+        numTables = bestNumTables;\r
+    }\r
+    else\r
+    {\r
+      if (numSymbols < 200)  numTables = 2;\r
+      else if (numSymbols < 600) numTables = 3;\r
+      else if (numSymbols < 1200) numTables = 4;\r
+      else if (numSymbols < 2400) numTables = 5;\r
+      else numTables = 6;\r
+    }\r
+\r
+    WriteBits2(numTables, kNumTablesBits);\r
+    \r
+    UInt32 numSelectors = (numSymbols + kGroupSize - 1) / kGroupSize;\r
+    WriteBits2(numSelectors, kNumSelectorsBits);\r
+    \r
+    {\r
+      UInt32 remFreq = numSymbols;\r
+      int gs = 0;\r
+      int t = numTables;\r
+      do\r
+      {\r
+        UInt32 tFreq = remFreq / t;\r
+        int ge = gs;\r
+        UInt32 aFreq = 0;\r
+        while (aFreq < tFreq) //  && ge < alphaSize)\r
+          aFreq += symbolCounts[ge++];\r
+        \r
+        if (ge - 1 > gs && t != numTables && t != 1 && (((numTables - t) & 1) == 1))\r
+          aFreq -= symbolCounts[--ge];\r
+        \r
+        Byte *lens = Lens[t - 1];\r
+        int i = 0;\r
+        do\r
+          lens[i] = (i >= gs && i < ge) ? 0 : 1;\r
+        while (++i < alphaSize);\r
+        gs = ge;\r
+        remFreq -= aFreq;\r
+      }\r
+      while(--t != 0);\r
+    }\r
+    \r
+    \r
+    for (int pass = 0; pass < kNumHuffPasses; pass++)\r
+    {\r
+      {\r
+        int t = 0;\r
+        do\r
+          memset(Freqs[t], 0, sizeof(Freqs[t]));\r
+        while(++t < numTables);\r
+      }\r
+      \r
+      {\r
+        UInt32 mtfPos = 0;\r
+        UInt32 g = 0;\r
+        do\r
+        {\r
+          UInt32 symbols[kGroupSize];\r
+          int i = 0;\r
+          do\r
+          {\r
+            UInt32 symbol = mtfs[mtfPos++];\r
+            if (symbol >= 0xFF)\r
+              symbol += mtfs[mtfPos++];\r
+            symbols[i] = symbol;\r
+          }\r
+          while (++i < kGroupSize && mtfPos < mtfArraySize);\r
+          \r
+          UInt32 bestPrice = 0xFFFFFFFF;\r
+          int t = 0;\r
+          do\r
+          {\r
+            const Byte *lens = Lens[t];\r
+            UInt32 price = 0;\r
+            int j = 0;\r
+            do\r
+              price += lens[symbols[j]];\r
+            while (++j < i);\r
+            if (price < bestPrice)\r
+            {\r
+              m_Selectors[g] = (Byte)t;\r
+              bestPrice = price;\r
+            }\r
+          }\r
+          while(++t < numTables);\r
+          UInt32 *freqs = Freqs[m_Selectors[g++]];\r
+          int j = 0;\r
+          do\r
+            freqs[symbols[j]]++;\r
+          while (++j < i);\r
+        }\r
+        while (mtfPos < mtfArraySize);\r
+      }\r
+      \r
+      int t = 0;\r
+      do\r
+      {\r
+        UInt32 *freqs = Freqs[t];\r
+        int i = 0;\r
+        do\r
+          if (freqs[i] == 0)\r
+            freqs[i] = 1;\r
+        while(++i < alphaSize);\r
+        Huffman_Generate(freqs, Codes[t], Lens[t], kMaxAlphaSize, kMaxHuffmanLenForEncoding);\r
+      }\r
+      while(++t < numTables);\r
+    }\r
+    \r
+    {\r
+      Byte mtfSel[kNumTablesMax];\r
+      {\r
+        int t = 0;\r
+        do\r
+          mtfSel[t] = (Byte)t;\r
+        while(++t < numTables);\r
+      }\r
+      \r
+      UInt32 i = 0;\r
+      do\r
+      {\r
+        Byte sel = m_Selectors[i];\r
+        int pos;\r
+        for (pos = 0; mtfSel[pos] != sel; pos++)\r
+          WriteBit2(true);\r
+        WriteBit2(false);\r
+        for (; pos > 0; pos--)\r
+          mtfSel[pos] = mtfSel[pos - 1];\r
+        mtfSel[0] = sel;\r
+      }\r
+      while(++i < numSelectors);\r
+    }\r
+    \r
+    {\r
+      int t = 0;\r
+      do\r
+      {\r
+        const Byte *lens = Lens[t];\r
+        UInt32 len = lens[0];\r
+        WriteBits2(len, kNumLevelsBits);\r
+        int i = 0;\r
+        do\r
+        {\r
+          UInt32 level = lens[i];\r
+          while (len != level)\r
+          {\r
+            WriteBit2(true);\r
+            if (len < level)\r
+            {\r
+              WriteBit2(false);\r
+              len++;\r
+            }\r
+            else\r
+            {\r
+              WriteBit2(true);\r
+              len--;\r
+            }\r
+          }\r
+          WriteBit2(false);\r
+        }\r
+        while (++i < alphaSize);\r
+      }\r
+      while(++t < numTables);\r
+    }\r
+    \r
+    {\r
+      UInt32 groupSize = 0;\r
+      UInt32 groupIndex = 0;\r
+      const Byte *lens = 0;\r
+      const UInt32 *codes = 0;\r
+      UInt32 mtfPos = 0;\r
+      do\r
+      {\r
+        UInt32 symbol = mtfs[mtfPos++];\r
+        if (symbol >= 0xFF)\r
+          symbol += mtfs[mtfPos++];\r
+        if (groupSize == 0)\r
+        {\r
+          groupSize = kGroupSize;\r
+          int t = m_Selectors[groupIndex++];\r
+          lens = Lens[t];\r
+          codes = Codes[t];\r
+        }\r
+        groupSize--;\r
+        m_OutStreamCurrent->WriteBits(codes[symbol], lens[symbol]);\r
+      }\r
+      while (mtfPos < mtfArraySize);\r
+    }\r
+\r
+    if (!m_OptimizeNumTables)\r
+      break;\r
+    UInt32 price = m_OutStreamCurrent->GetPos() - startPos;\r
+    if (price <= bestPrice)\r
+    {\r
+      if (nt == kNumTablesMax)\r
+        break;\r
+      bestPrice = price;\r
+      bestNumTables = nt;\r
+    }\r
+  }\r
+}\r
+\r
+// blockSize > 0\r
+UInt32 CThreadInfo::EncodeBlockWithHeaders(const Byte *block, UInt32 blockSize)\r
+{\r
+  WriteByte2(kBlockSig0);\r
+  WriteByte2(kBlockSig1);\r
+  WriteByte2(kBlockSig2);\r
+  WriteByte2(kBlockSig3);\r
+  WriteByte2(kBlockSig4);\r
+  WriteByte2(kBlockSig5);\r
+\r
+  CBZip2Crc crc;\r
+  int numReps = 0;\r
+  Byte prevByte = block[0];\r
+  UInt32 i = 0;\r
+  do\r
+  {\r
+    Byte b = block[i];\r
+    if (numReps == kRleModeRepSize)\r
+    {\r
+      for (; b > 0; b--)\r
+        crc.UpdateByte(prevByte);\r
+      numReps = 0;\r
+      continue;\r
+    }\r
+    if (prevByte == b)\r
+      numReps++;\r
+    else\r
+    {\r
+      numReps = 1;\r
+      prevByte = b;\r
+    }\r
+    crc.UpdateByte(b);\r
+  }\r
+  while (++i < blockSize);\r
+  UInt32 crcRes = crc.GetDigest();\r
+  WriteCrc2(crcRes);\r
+  EncodeBlock(block, blockSize);\r
+  return crcRes;\r
+}\r
+\r
+void CThreadInfo::EncodeBlock2(const Byte *block, UInt32 blockSize, UInt32 numPasses)\r
+{\r
+  UInt32 numCrcs = m_NumCrcs;\r
+  bool needCompare = false;\r
+\r
+  UInt32 startBytePos = m_OutStreamCurrent->GetBytePos();\r
+  UInt32 startPos = m_OutStreamCurrent->GetPos();\r
+  Byte startCurByte = m_OutStreamCurrent->GetCurByte();\r
+  Byte endCurByte = 0;\r
+  UInt32 endPos = 0;\r
+  if (numPasses > 1 && blockSize >= (1 << 10))\r
+  {\r
+    UInt32 blockSize0 = blockSize / 2;\r
+    for (;(block[blockSize0] == block[blockSize0 - 1] ||\r
+          block[blockSize0 - 1] == block[blockSize0 - 2]) &&\r
+          blockSize0 < blockSize; blockSize0++);\r
+    if (blockSize0 < blockSize)\r
+    {\r
+      EncodeBlock2(block, blockSize0, numPasses - 1);\r
+      EncodeBlock2(block + blockSize0, blockSize - blockSize0, numPasses - 1);\r
+      endPos = m_OutStreamCurrent->GetPos();\r
+      endCurByte = m_OutStreamCurrent->GetCurByte();\r
+      if ((endPos & 7) > 0)\r
+        WriteBits2(0, 8 - (endPos & 7));\r
+      m_OutStreamCurrent->SetCurState((startPos & 7), startCurByte);\r
+      needCompare = true;\r
+    }\r
+  }\r
+\r
+  UInt32 startBytePos2 = m_OutStreamCurrent->GetBytePos();\r
+  UInt32 startPos2 = m_OutStreamCurrent->GetPos();\r
+  UInt32 crcVal = EncodeBlockWithHeaders(block, blockSize);\r
+  UInt32 endPos2 = m_OutStreamCurrent->GetPos();\r
+\r
+  if (needCompare)\r
+  {\r
+    UInt32 size2 = endPos2 - startPos2;\r
+    if (size2 < endPos - startPos)\r
+    {\r
+      UInt32 numBytes = m_OutStreamCurrent->GetBytePos() - startBytePos2;\r
+      Byte *buffer = m_OutStreamCurrent->GetStream();\r
+      for (UInt32 i = 0; i < numBytes; i++)\r
+        buffer[startBytePos + i] = buffer[startBytePos2 + i];\r
+      m_OutStreamCurrent->SetPos(startPos + endPos2 - startPos2);\r
+      m_NumCrcs = numCrcs;\r
+      m_CRCs[m_NumCrcs++] = crcVal;\r
+    }\r
+    else\r
+    {\r
+      m_OutStreamCurrent->SetPos(endPos);\r
+      m_OutStreamCurrent->SetCurState((endPos & 7), endCurByte);\r
+    }\r
+  }\r
+  else\r
+  {\r
+    m_NumCrcs = numCrcs;\r
+    m_CRCs[m_NumCrcs++] = crcVal;\r
+  }\r
+}\r
+\r
+HRESULT CThreadInfo::EncodeBlock3(UInt32 blockSize)\r
+{\r
+  CMsbfEncoderTemp outStreamTemp;\r
+  outStreamTemp.SetStream(m_TempArray);\r
+  outStreamTemp.Init();\r
+  m_OutStreamCurrent = &outStreamTemp;\r
+\r
+  m_NumCrcs = 0;\r
+\r
+  EncodeBlock2(m_Block, blockSize, Encoder->NumPasses);\r
+\r
+  #ifndef _7ZIP_ST\r
+  if (Encoder->MtMode)\r
+    Encoder->ThreadsInfo[m_BlockIndex].CanWriteEvent.Lock();\r
+  #endif\r
+  for (UInt32 i = 0; i < m_NumCrcs; i++)\r
+    Encoder->CombinedCrc.Update(m_CRCs[i]);\r
+  Encoder->WriteBytes(m_TempArray, outStreamTemp.GetPos(), outStreamTemp.GetCurByte());\r
+  HRESULT res = S_OK;\r
+  #ifndef _7ZIP_ST\r
+  if (Encoder->MtMode)\r
+  {\r
+    UInt32 blockIndex = m_BlockIndex + 1;\r
+    if (blockIndex == Encoder->NumThreads)\r
+      blockIndex = 0;\r
+\r
+    if (Encoder->Progress)\r
+    {\r
+      UInt64 unpackSize = Encoder->m_OutStream.GetProcessedSize();\r
+      res = Encoder->Progress->SetRatioInfo(&m_PackSize, &unpackSize);\r
+    }\r
+\r
+    Encoder->ThreadsInfo[blockIndex].CanWriteEvent.Set();\r
+  }\r
+  #endif\r
+  return res;\r
+}\r
+\r
+void CEncoder::WriteBytes(const Byte *data, UInt32 sizeInBits, Byte lastByte)\r
+{\r
+  UInt32 bytesSize = (sizeInBits / 8);\r
+  for (UInt32 i = 0; i < bytesSize; i++)\r
+    m_OutStream.WriteBits(data[i], 8);\r
+  WriteBits(lastByte, (sizeInBits & 7));\r
+}\r
+\r
+\r
+HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)\r
+{\r
+  #ifndef _7ZIP_ST\r
+  Progress = progress;\r
+  RINOK(Create());\r
+  for (UInt32 t = 0; t < NumThreads; t++)\r
+  #endif\r
+  {\r
+    #ifndef _7ZIP_ST\r
+    CThreadInfo &ti = ThreadsInfo[t];\r
+    if (MtMode)\r
+    {\r
+      RINOK(ti.StreamWasFinishedEvent.Reset());\r
+      RINOK(ti.WaitingWasStartedEvent.Reset());\r
+      RINOK(ti.CanWriteEvent.Reset());\r
+    }\r
+    #else\r
+    CThreadInfo &ti = ThreadsInfo;\r
+    ti.Encoder = this;\r
+    #endif\r
+\r
+    ti.m_OptimizeNumTables = m_OptimizeNumTables;\r
+\r
+    if (!ti.Alloc())\r
+      return E_OUTOFMEMORY;\r
+  }\r
+\r
+\r
+  if (!m_InStream.Create(kBufferSize))\r
+    return E_OUTOFMEMORY;\r
+  if (!m_OutStream.Create(kBufferSize))\r
+    return E_OUTOFMEMORY;\r
+\r
+\r
+  m_InStream.SetStream(inStream);\r
+  m_InStream.Init();\r
+\r
+  m_OutStream.SetStream(outStream);\r
+  m_OutStream.Init();\r
+\r
+  CFlusher flusher(this);\r
+\r
+  CombinedCrc.Init();\r
+  #ifndef _7ZIP_ST\r
+  NextBlockIndex = 0;\r
+  StreamWasFinished = false;\r
+  CloseThreads = false;\r
+  CanStartWaitingEvent.Reset();\r
+  #endif\r
+\r
+  WriteByte(kArSig0);\r
+  WriteByte(kArSig1);\r
+  WriteByte(kArSig2);\r
+  WriteByte((Byte)(kArSig3 + m_BlockSizeMult));\r
+\r
+  #ifndef _7ZIP_ST\r
+\r
+  if (MtMode)\r
+  {\r
+    ThreadsInfo[0].CanWriteEvent.Set();\r
+    Result = S_OK;\r
+    CanProcessEvent.Set();\r
+    UInt32 t;\r
+    for (t = 0; t < NumThreads; t++)\r
+      ThreadsInfo[t].StreamWasFinishedEvent.Lock();\r
+    CanProcessEvent.Reset();\r
+    CanStartWaitingEvent.Set();\r
+    for (t = 0; t < NumThreads; t++)\r
+      ThreadsInfo[t].WaitingWasStartedEvent.Lock();\r
+    CanStartWaitingEvent.Reset();\r
+    RINOK(Result);\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    for (;;)\r
+    {\r
+      CThreadInfo &ti =\r
+      #ifndef _7ZIP_ST\r
+      ThreadsInfo[0];\r
+      #else\r
+      ThreadsInfo;\r
+      #endif\r
+      UInt32 blockSize = ReadRleBlock(ti.m_Block);\r
+      if (blockSize == 0)\r
+        break;\r
+      RINOK(ti.EncodeBlock3(blockSize));\r
+      if (progress)\r
+      {\r
+        UInt64 packSize = m_InStream.GetProcessedSize();\r
+        UInt64 unpackSize = m_OutStream.GetProcessedSize();\r
+        RINOK(progress->SetRatioInfo(&packSize, &unpackSize));\r
+      }\r
+    }\r
+  }\r
+  WriteByte(kFinSig0);\r
+  WriteByte(kFinSig1);\r
+  WriteByte(kFinSig2);\r
+  WriteByte(kFinSig3);\r
+  WriteByte(kFinSig4);\r
+  WriteByte(kFinSig5);\r
+\r
+  WriteCrc(CombinedCrc.GetDigest());\r
+  return Flush();\r
+}\r
+\r
+STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  try { return CodeReal(inStream, outStream, inSize, outSize, progress); }\r
+  catch(const CInBufferException &e) { return e.ErrorCode; }\r
+  catch(const COutBufferException &e) { return e.ErrorCode; }\r
+  catch(...) { return S_FALSE; }\r
+}\r
+\r
+HRESULT CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)\r
+{\r
+  for(UInt32 i = 0; i < numProps; i++)\r
+  {\r
+    const PROPVARIANT &prop = props[i];\r
+    switch(propIDs[i])\r
+    {\r
+      case NCoderPropID::kNumPasses:\r
+      {\r
+        if (prop.vt != VT_UI4)\r
+          return E_INVALIDARG;\r
+        UInt32 numPasses = prop.ulVal;\r
+        if (numPasses == 0)\r
+          numPasses = 1;\r
+        if (numPasses > kNumPassesMax)\r
+          numPasses = kNumPassesMax;\r
+        NumPasses = numPasses;\r
+        m_OptimizeNumTables = (NumPasses > 1);\r
+        break;\r
+      }\r
+      case NCoderPropID::kDictionarySize:\r
+      {\r
+        if (prop.vt != VT_UI4)\r
+          return E_INVALIDARG;\r
+        UInt32 dictionary = prop.ulVal / kBlockSizeStep;\r
+        if (dictionary < kBlockSizeMultMin)\r
+          dictionary = kBlockSizeMultMin;\r
+        else if (dictionary > kBlockSizeMultMax)\r
+          dictionary = kBlockSizeMultMax;\r
+        m_BlockSizeMult = dictionary;\r
+        break;\r
+      }\r
+      case NCoderPropID::kNumThreads:\r
+      {\r
+        #ifndef _7ZIP_ST\r
+        if (prop.vt != VT_UI4)\r
+          return E_INVALIDARG;\r
+        NumThreads = prop.ulVal;\r
+        if (NumThreads < 1)\r
+          NumThreads = 1;\r
+        #endif\r
+        break;\r
+      }\r
+      default:\r
+        return E_INVALIDARG;\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+#ifndef _7ZIP_ST\r
+STDMETHODIMP CEncoder::SetNumberOfThreads(UInt32 numThreads)\r
+{\r
+  NumThreads = numThreads;\r
+  if (NumThreads < 1)\r
+    NumThreads = 1;\r
+  return S_OK;\r
+}\r
+#endif\r
+\r
+}}\r
diff --git a/CPP/7zip/Compress/BZip2Encoder.h b/CPP/7zip/Compress/BZip2Encoder.h
new file mode 100755 (executable)
index 0000000..287ec50
--- /dev/null
@@ -0,0 +1,245 @@
+// BZip2Encoder.h\r
+\r
+#ifndef __COMPRESS_BZIP2_ENCODER_H\r
+#define __COMPRESS_BZIP2_ENCODER_H\r
+\r
+#include "../../Common/Defs.h"\r
+#include "../../Common/MyCom.h"\r
+\r
+#ifndef _7ZIP_ST\r
+#include "../../Windows/Synchronization.h"\r
+#include "../../Windows/Thread.h"\r
+#endif\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "../Common/InBuffer.h"\r
+#include "../Common/OutBuffer.h"\r
+\r
+#include "BitmEncoder.h"\r
+#include "BZip2Const.h"\r
+#include "BZip2Crc.h"\r
+\r
+namespace NCompress {\r
+namespace NBZip2 {\r
+\r
+class CMsbfEncoderTemp\r
+{\r
+  UInt32 m_Pos;\r
+  int m_BitPos;\r
+  Byte m_CurByte;\r
+  Byte *Buffer;\r
+public:\r
+  void SetStream(Byte *buffer) { Buffer = buffer;  }\r
+  Byte *GetStream() const { return Buffer; }\r
+\r
+  void Init()\r
+  {\r
+    m_Pos = 0;\r
+    m_BitPos = 8;\r
+    m_CurByte = 0;\r
+  }\r
+\r
+  void Flush()\r
+  {\r
+    if (m_BitPos < 8)\r
+      WriteBits(0, m_BitPos);\r
+  }\r
+\r
+  void WriteBits(UInt32 value, int numBits)\r
+  {\r
+    while (numBits > 0)\r
+    {\r
+      int numNewBits = MyMin(numBits, m_BitPos);\r
+      numBits -= numNewBits;\r
+      \r
+      m_CurByte <<= numNewBits;\r
+      UInt32 newBits = value >> numBits;\r
+      m_CurByte |= Byte(newBits);\r
+      value -= (newBits << numBits);\r
+      \r
+      m_BitPos -= numNewBits;\r
+      \r
+      if (m_BitPos == 0)\r
+      {\r
+       Buffer[m_Pos++] = m_CurByte;\r
+        m_BitPos = 8;\r
+      }\r
+    }\r
+  }\r
+  \r
+  UInt32 GetBytePos() const { return m_Pos ; }\r
+  UInt32 GetPos() const { return m_Pos * 8 + (8 - m_BitPos); }\r
+  Byte GetCurByte() const { return m_CurByte; }\r
+  void SetPos(UInt32 bitPos)\r
+  {\r
+    m_Pos = bitPos / 8;\r
+    m_BitPos = 8 - ((int)bitPos & 7);\r
+  }\r
+  void SetCurState(int bitPos, Byte curByte)\r
+  {\r
+    m_BitPos = 8 - bitPos;\r
+    m_CurByte = curByte;\r
+  }\r
+};\r
+\r
+class CEncoder;\r
+\r
+const int kNumPassesMax = 10;\r
+\r
+class CThreadInfo\r
+{\r
+public:\r
+  Byte *m_Block;\r
+private:\r
+  Byte *m_MtfArray;\r
+  Byte *m_TempArray;\r
+  UInt32 *m_BlockSorterIndex;\r
+\r
+  CMsbfEncoderTemp *m_OutStreamCurrent;\r
+\r
+  Byte Lens[kNumTablesMax][kMaxAlphaSize];\r
+  UInt32 Freqs[kNumTablesMax][kMaxAlphaSize];\r
+  UInt32 Codes[kNumTablesMax][kMaxAlphaSize];\r
+\r
+  Byte m_Selectors[kNumSelectorsMax];\r
+\r
+  UInt32 m_CRCs[1 << kNumPassesMax];\r
+  UInt32 m_NumCrcs;\r
+\r
+  UInt32 m_BlockIndex;\r
+\r
+  void WriteBits2(UInt32 value, UInt32 numBits);\r
+  void WriteByte2(Byte b);\r
+  void WriteBit2(bool v);\r
+  void WriteCrc2(UInt32 v);\r
+\r
+  void EncodeBlock(const Byte *block, UInt32 blockSize);\r
+  UInt32 EncodeBlockWithHeaders(const Byte *block, UInt32 blockSize);\r
+  void EncodeBlock2(const Byte *block, UInt32 blockSize, UInt32 numPasses);\r
+public:\r
+  bool m_OptimizeNumTables;\r
+  CEncoder *Encoder;\r
+  #ifndef _7ZIP_ST\r
+  NWindows::CThread Thread;\r
+\r
+  NWindows::NSynchronization::CAutoResetEvent StreamWasFinishedEvent;\r
+  NWindows::NSynchronization::CAutoResetEvent WaitingWasStartedEvent;\r
+\r
+  // it's not member of this thread. We just need one event per thread\r
+  NWindows::NSynchronization::CAutoResetEvent CanWriteEvent;\r
+\r
+  UInt64 m_PackSize;\r
+\r
+  Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size.\r
+  HRESULT Create();\r
+  void FinishStream(bool needLeave);\r
+  DWORD ThreadFunc();\r
+  #endif\r
+\r
+  CThreadInfo(): m_BlockSorterIndex(0), m_Block(0) {}\r
+  ~CThreadInfo() { Free(); }\r
+  bool Alloc();\r
+  void Free();\r
+\r
+  HRESULT EncodeBlock3(UInt32 blockSize);\r
+};\r
+\r
+class CEncoder :\r
+  public ICompressCoder,\r
+  public ICompressSetCoderProperties,\r
+  #ifndef _7ZIP_ST\r
+  public ICompressSetCoderMt,\r
+  #endif\r
+  public CMyUnknownImp\r
+{\r
+  UInt32 m_BlockSizeMult;\r
+  bool m_OptimizeNumTables;\r
+\r
+  UInt32 m_NumPassesPrev;\r
+\r
+  UInt32 m_NumThreadsPrev;\r
+public:\r
+  CInBuffer m_InStream;\r
+  Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size.\r
+  CBitmEncoder<COutBuffer> m_OutStream;\r
+  UInt32 NumPasses;\r
+  CBZip2CombinedCrc CombinedCrc;\r
+\r
+  #ifndef _7ZIP_ST\r
+  CThreadInfo *ThreadsInfo;\r
+  NWindows::NSynchronization::CManualResetEvent CanProcessEvent;\r
+  NWindows::NSynchronization::CCriticalSection CS;\r
+  UInt32 NumThreads;\r
+  bool MtMode;\r
+  UInt32 NextBlockIndex;\r
+\r
+  bool CloseThreads;\r
+  bool StreamWasFinished;\r
+  NWindows::NSynchronization::CManualResetEvent CanStartWaitingEvent;\r
+\r
+  HRESULT Result;\r
+  ICompressProgressInfo *Progress;\r
+  #else\r
+  CThreadInfo ThreadsInfo;\r
+  #endif\r
+\r
+  UInt32 ReadRleBlock(Byte *buffer);\r
+  void WriteBytes(const Byte *data, UInt32 sizeInBits, Byte lastByte);\r
+\r
+  void WriteBits(UInt32 value, UInt32 numBits);\r
+  void WriteByte(Byte b);\r
+  void WriteBit(bool v);\r
+  void WriteCrc(UInt32 v);\r
+\r
+  #ifndef _7ZIP_ST\r
+  HRESULT Create();\r
+  void Free();\r
+  #endif\r
+\r
+public:\r
+  CEncoder();\r
+  #ifndef _7ZIP_ST\r
+  ~CEncoder();\r
+  #endif\r
+\r
+  HRESULT Flush() { return m_OutStream.Flush(); }\r
+  \r
+  void ReleaseStreams()\r
+  {\r
+    m_InStream.ReleaseStream();\r
+    m_OutStream.ReleaseStream();\r
+  }\r
+\r
+  class CFlusher\r
+  {\r
+    CEncoder *_coder;\r
+  public:\r
+    CFlusher(CEncoder *coder): _coder(coder) {}\r
+    ~CFlusher()\r
+    {\r
+      _coder->ReleaseStreams();\r
+    }\r
+  };\r
+\r
+  #ifndef _7ZIP_ST\r
+  MY_UNKNOWN_IMP2(ICompressSetCoderMt, ICompressSetCoderProperties)\r
+  #else\r
+  MY_UNKNOWN_IMP1(ICompressSetCoderProperties)\r
+  #endif\r
+\r
+  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);\r
+\r
+  #ifndef _7ZIP_ST\r
+  STDMETHOD(SetNumberOfThreads)(UInt32 numThreads);\r
+  #endif\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/BZip2Register.cpp b/CPP/7zip/Compress/BZip2Register.cpp
new file mode 100755 (executable)
index 0000000..f10e594
--- /dev/null
@@ -0,0 +1,20 @@
+// BZip2Register.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../Common/RegisterCodec.h"\r
+\r
+#include "BZip2Decoder.h"\r
+\r
+static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NBZip2::CDecoder); }\r
+#if !defined(EXTRACT_ONLY) && !defined(BZIP2_EXTRACT_ONLY)\r
+#include "BZip2Encoder.h"\r
+static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NBZip2::CEncoder);  }\r
+#else\r
+#define CreateCodecOut 0\r
+#endif\r
+\r
+static CCodecInfo g_CodecInfo =\r
+  { CreateCodec, CreateCodecOut, 0x040202, L"BZip2", 1, false };\r
+\r
+REGISTER_CODEC(BZip2)\r
diff --git a/CPP/7zip/Compress/Bcj2Coder.cpp b/CPP/7zip/Compress/Bcj2Coder.cpp
new file mode 100755 (executable)
index 0000000..05590e7
--- /dev/null
@@ -0,0 +1,386 @@
+// Bcj2Coder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+\r
+#include "Bcj2Coder.h"\r
+\r
+namespace NCompress {\r
+namespace NBcj2 {\r
+\r
+inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); }\r
+inline bool IsJ(Byte b0, Byte b1) { return ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)); }\r
+inline unsigned GetIndex(Byte b0, Byte b1) { return ((b1 == 0xE8) ? b0 : ((b1 == 0xE9) ? 256 : 257)); }\r
+\r
+#ifndef EXTRACT_ONLY\r
+\r
+static const int kBufferSize = 1 << 17;\r
+\r
+static bool inline Test86MSByte(Byte b)\r
+{\r
+  return (b == 0 || b == 0xFF);\r
+}\r
+\r
+bool CEncoder::Create()\r
+{\r
+  if (!_mainStream.Create(1 << 18))\r
+    return false;\r
+  if (!_callStream.Create(1 << 18))\r
+    return false;\r
+  if (!_jumpStream.Create(1 << 18))\r
+    return false;\r
+  if (!_rangeEncoder.Create(1 << 20))\r
+    return false;\r
+  if (_buffer == 0)\r
+  {\r
+    _buffer = (Byte *)MidAlloc(kBufferSize);\r
+    if (_buffer == 0)\r
+      return false;\r
+  }\r
+  return true;\r
+}\r
+\r
+CEncoder::~CEncoder()\r
+{\r
+  ::MidFree(_buffer);\r
+}\r
+\r
+HRESULT CEncoder::Flush()\r
+{\r
+  RINOK(_mainStream.Flush());\r
+  RINOK(_callStream.Flush());\r
+  RINOK(_jumpStream.Flush());\r
+  _rangeEncoder.FlushData();\r
+  return _rangeEncoder.FlushStream();\r
+}\r
+\r
+const UInt32 kDefaultLimit = (1 << 24);\r
+\r
+HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,\r
+    ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams,\r
+    ICompressProgressInfo *progress)\r
+{\r
+  if (numInStreams != 1 || numOutStreams != 4)\r
+    return E_INVALIDARG;\r
+\r
+  if (!Create())\r
+    return E_OUTOFMEMORY;\r
+\r
+  bool sizeIsDefined = false;\r
+  UInt64 inSize = 0;\r
+  if (inSizes != NULL)\r
+    if (inSizes[0] != NULL)\r
+    {\r
+      inSize = *inSizes[0];\r
+      if (inSize <= kDefaultLimit)\r
+        sizeIsDefined = true;\r
+    }\r
+\r
+  CCoderReleaser releaser(this);\r
+\r
+  ISequentialInStream *inStream = inStreams[0];\r
+\r
+  _mainStream.SetStream(outStreams[0]);\r
+  _mainStream.Init();\r
+  _callStream.SetStream(outStreams[1]);\r
+  _callStream.Init();\r
+  _jumpStream.SetStream(outStreams[2]);\r
+  _jumpStream.Init();\r
+  _rangeEncoder.SetStream(outStreams[3]);\r
+  _rangeEncoder.Init();\r
+  for (int i = 0; i < 256 + 2; i++)\r
+    _statusEncoder[i].Init();\r
+\r
+  CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize;\r
+  {\r
+    inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize);\r
+  }\r
+\r
+  UInt32 nowPos = 0;\r
+  UInt64 nowPos64 = 0;\r
+  UInt32 bufferPos = 0;\r
+\r
+  Byte prevByte = 0;\r
+\r
+  UInt64 subStreamIndex = 0;\r
+  UInt64 subStreamStartPos  = 0;\r
+  UInt64 subStreamEndPos = 0;\r
+\r
+  for (;;)\r
+  {\r
+    UInt32 processedSize = 0;\r
+    for (;;)\r
+    {\r
+      UInt32 size = kBufferSize - (bufferPos + processedSize);\r
+      UInt32 processedSizeLoc;\r
+      if (size == 0)\r
+        break;\r
+      RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc));\r
+      if (processedSizeLoc == 0)\r
+        break;\r
+      processedSize += processedSizeLoc;\r
+    }\r
+    UInt32 endPos = bufferPos + processedSize;\r
+    \r
+    if (endPos < 5)\r
+    {\r
+      // change it\r
+      for (bufferPos = 0; bufferPos < endPos; bufferPos++)\r
+      {\r
+        Byte b = _buffer[bufferPos];\r
+        _mainStream.WriteByte(b);\r
+        UInt32 index;\r
+        if (b == 0xE8)\r
+          index = prevByte;\r
+        else if (b == 0xE9)\r
+          index = 256;\r
+        else if (IsJcc(prevByte, b))\r
+          index = 257;\r
+        else\r
+        {\r
+          prevByte = b;\r
+          continue;\r
+        }\r
+        _statusEncoder[index].Encode(&_rangeEncoder, 0);\r
+        prevByte = b;\r
+      }\r
+      return Flush();\r
+    }\r
+\r
+    bufferPos = 0;\r
+\r
+    UInt32 limit = endPos - 5;\r
+    while(bufferPos <= limit)\r
+    {\r
+      Byte b = _buffer[bufferPos];\r
+      _mainStream.WriteByte(b);\r
+      if (!IsJ(prevByte, b))\r
+      {\r
+        bufferPos++;\r
+        prevByte = b;\r
+        continue;\r
+      }\r
+      Byte nextByte = _buffer[bufferPos + 4];\r
+      UInt32 src =\r
+        (UInt32(nextByte) << 24) |\r
+        (UInt32(_buffer[bufferPos + 3]) << 16) |\r
+        (UInt32(_buffer[bufferPos + 2]) << 8) |\r
+        (_buffer[bufferPos + 1]);\r
+      UInt32 dest = (nowPos + bufferPos + 5) + src;\r
+      // if (Test86MSByte(nextByte))\r
+      bool convert;\r
+      if (getSubStreamSize != NULL)\r
+      {\r
+        UInt64 currentPos = (nowPos64 + bufferPos);\r
+        while (subStreamEndPos < currentPos)\r
+        {\r
+          UInt64 subStreamSize;\r
+          HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize);\r
+          if (result == S_OK)\r
+          {\r
+            subStreamStartPos = subStreamEndPos;\r
+            subStreamEndPos += subStreamSize;\r
+            subStreamIndex++;\r
+          }\r
+          else if (result == S_FALSE || result == E_NOTIMPL)\r
+          {\r
+            getSubStreamSize.Release();\r
+            subStreamStartPos = 0;\r
+            subStreamEndPos = subStreamStartPos - 1;\r
+          }\r
+          else\r
+            return result;\r
+        }\r
+        if (getSubStreamSize == NULL)\r
+        {\r
+          if (sizeIsDefined)\r
+            convert = (dest < inSize);\r
+          else\r
+            convert = Test86MSByte(nextByte);\r
+        }\r
+        else if (subStreamEndPos - subStreamStartPos > kDefaultLimit)\r
+          convert = Test86MSByte(nextByte);\r
+        else\r
+        {\r
+          UInt64 dest64 = (currentPos + 5) + Int64(Int32(src));\r
+          convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos);\r
+        }\r
+      }\r
+      else if (sizeIsDefined)\r
+        convert = (dest < inSize);\r
+      else\r
+        convert = Test86MSByte(nextByte);\r
+      unsigned index = GetIndex(prevByte, b);\r
+      if (convert)\r
+      {\r
+        _statusEncoder[index].Encode(&_rangeEncoder, 1);\r
+        bufferPos += 5;\r
+        COutBuffer &s = (b == 0xE8) ? _callStream : _jumpStream;\r
+        for (int i = 24; i >= 0; i -= 8)\r
+          s.WriteByte((Byte)(dest >> i));\r
+        prevByte = nextByte;\r
+      }\r
+      else\r
+      {\r
+        _statusEncoder[index].Encode(&_rangeEncoder, 0);\r
+        bufferPos++;\r
+        prevByte = b;\r
+      }\r
+    }\r
+    nowPos += bufferPos;\r
+    nowPos64 += bufferPos;\r
+\r
+    if (progress != NULL)\r
+    {\r
+      /*\r
+      const UInt64 compressedSize =\r
+        _mainStream.GetProcessedSize() +\r
+        _callStream.GetProcessedSize() +\r
+        _jumpStream.GetProcessedSize() +\r
+        _rangeEncoder.GetProcessedSize();\r
+      */\r
+      RINOK(progress->SetRatioInfo(&nowPos64, NULL));\r
+    }\r
\r
+    UInt32 i = 0;\r
+    while(bufferPos < endPos)\r
+      _buffer[i++] = _buffer[bufferPos++];\r
+    bufferPos = i;\r
+  }\r
+}\r
+\r
+STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,\r
+    ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,\r
+    ICompressProgressInfo *progress)\r
+{\r
+  try\r
+  {\r
+    return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress);\r
+  }\r
+  catch(const COutBufferException &e) { return e.ErrorCode; }\r
+  catch(...) { return S_FALSE; }\r
+}\r
+\r
+#endif\r
+\r
+\r
+STDMETHODIMP CDecoder::SetInBufSize(UInt32 streamIndex, UInt32 size) { _inBufSizes[streamIndex] = size; return S_OK; }\r
+STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; }\r
+\r
+CDecoder::CDecoder():\r
+  _outBufSize(1 << 16)\r
+{\r
+  _inBufSizes[0] = 1 << 20;\r
+  _inBufSizes[1] = 1 << 20;\r
+  _inBufSizes[2] = 1 << 20;\r
+  _inBufSizes[3] = 1 << 20;\r
+}\r
+\r
+HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams,\r
+    ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams,\r
+    ICompressProgressInfo *progress)\r
+{\r
+  if (numInStreams != 4 || numOutStreams != 1)\r
+    return E_INVALIDARG;\r
+\r
+  if (!_mainInStream.Create(_inBufSizes[0]))\r
+    return E_OUTOFMEMORY;\r
+  if (!_callStream.Create(_inBufSizes[1]))\r
+    return E_OUTOFMEMORY;\r
+  if (!_jumpStream.Create(_inBufSizes[2]))\r
+    return E_OUTOFMEMORY;\r
+  if (!_rangeDecoder.Create(_inBufSizes[3]))\r
+    return E_OUTOFMEMORY;\r
+  if (!_outStream.Create(_outBufSize))\r
+    return E_OUTOFMEMORY;\r
+\r
+  CCoderReleaser releaser(this);\r
+\r
+  _mainInStream.SetStream(inStreams[0]);\r
+  _callStream.SetStream(inStreams[1]);\r
+  _jumpStream.SetStream(inStreams[2]);\r
+  _rangeDecoder.SetStream(inStreams[3]);\r
+  _outStream.SetStream(outStreams[0]);\r
+\r
+  _mainInStream.Init();\r
+  _callStream.Init();\r
+  _jumpStream.Init();\r
+  _rangeDecoder.Init();\r
+  _outStream.Init();\r
+\r
+  for (int i = 0; i < 256 + 2; i++)\r
+    _statusDecoder[i].Init();\r
+\r
+  Byte prevByte = 0;\r
+  UInt32 processedBytes = 0;\r
+  for (;;)\r
+  {\r
+    if (processedBytes >= (1 << 20) && progress != NULL)\r
+    {\r
+      /*\r
+      const UInt64 compressedSize =\r
+        _mainInStream.GetProcessedSize() +\r
+        _callStream.GetProcessedSize() +\r
+        _jumpStream.GetProcessedSize() +\r
+        _rangeDecoder.GetProcessedSize();\r
+      */\r
+      const UInt64 nowPos64 = _outStream.GetProcessedSize();\r
+      RINOK(progress->SetRatioInfo(NULL, &nowPos64));\r
+      processedBytes = 0;\r
+    }\r
+    UInt32 i;\r
+    Byte b = 0;\r
+    const UInt32 kBurstSize = (1 << 18);\r
+    for (i = 0; i < kBurstSize; i++)\r
+    {\r
+      if (!_mainInStream.ReadByte(b))\r
+        return Flush();\r
+      _outStream.WriteByte(b);\r
+      if (IsJ(prevByte, b))\r
+        break;\r
+      prevByte = b;\r
+    }\r
+    processedBytes += i;\r
+    if (i == kBurstSize)\r
+      continue;\r
+    unsigned index = GetIndex(prevByte, b);\r
+    if (_statusDecoder[index].Decode(&_rangeDecoder) == 1)\r
+    {\r
+      UInt32 src = 0;\r
+      CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream;\r
+      for (int i = 0; i < 4; i++)\r
+      {\r
+        Byte b0;\r
+        if(!s.ReadByte(b0))\r
+          return S_FALSE;\r
+        src <<= 8;\r
+        src |= ((UInt32)b0);\r
+      }\r
+      UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ;\r
+      _outStream.WriteByte((Byte)(dest));\r
+      _outStream.WriteByte((Byte)(dest >> 8));\r
+      _outStream.WriteByte((Byte)(dest >> 16));\r
+      _outStream.WriteByte((Byte)(dest >> 24));\r
+      prevByte = (Byte)(dest >> 24);\r
+      processedBytes += 4;\r
+    }\r
+    else\r
+      prevByte = b;\r
+  }\r
+}\r
+\r
+STDMETHODIMP CDecoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,\r
+    ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,\r
+    ICompressProgressInfo *progress)\r
+{\r
+  try\r
+  {\r
+    return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress);\r
+  }\r
+  catch(const CInBufferException &e) { return e.ErrorCode; }\r
+  catch(const COutBufferException &e) { return e.ErrorCode; }\r
+  catch(...) { return S_FALSE; }\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Compress/Bcj2Coder.h b/CPP/7zip/Compress/Bcj2Coder.h
new file mode 100755 (executable)
index 0000000..c8f0893
--- /dev/null
@@ -0,0 +1,115 @@
+// Bcj2Coder.h\r
+\r
+#ifndef __COMPRESS_BCJ2_CODER_H\r
+#define __COMPRESS_BCJ2_CODER_H\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "RangeCoderBit.h"\r
+\r
+namespace NCompress {\r
+namespace NBcj2 {\r
+\r
+const int kNumMoveBits = 5;\r
+\r
+#ifndef EXTRACT_ONLY\r
+\r
+class CEncoder:\r
+  public ICompressCoder2,\r
+  public CMyUnknownImp\r
+{\r
+  Byte *_buffer;\r
+  bool Create();\r
+\r
+  COutBuffer _mainStream;\r
+  COutBuffer _callStream;\r
+  COutBuffer _jumpStream;\r
+  NCompress::NRangeCoder::CEncoder _rangeEncoder;\r
+  NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusEncoder[256 + 2];\r
+\r
+  HRESULT Flush();\r
+public:\r
+  void ReleaseStreams()\r
+  {\r
+    _mainStream.ReleaseStream();\r
+    _callStream.ReleaseStream();\r
+    _jumpStream.ReleaseStream();\r
+    _rangeEncoder.ReleaseStream();\r
+  }\r
+\r
+  class CCoderReleaser\r
+  {\r
+    CEncoder *_coder;\r
+  public:\r
+    CCoderReleaser(CEncoder *coder): _coder(coder) {}\r
+    ~CCoderReleaser() {  _coder->ReleaseStreams(); }\r
+  };\r
+\r
+public:\r
+  MY_UNKNOWN_IMP\r
+\r
+  HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,\r
+      ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,\r
+      ICompressProgressInfo *progress);\r
+  STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,\r
+      ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,\r
+      ICompressProgressInfo *progress);\r
+  CEncoder(): _buffer(0) {};\r
+  ~CEncoder();\r
+};\r
+\r
+#endif\r
+\r
+class CDecoder:\r
+  public ICompressCoder2,\r
+  public ICompressSetBufSize,\r
+  public CMyUnknownImp\r
+{\r
+  CInBuffer _mainInStream;\r
+  CInBuffer _callStream;\r
+  CInBuffer _jumpStream;\r
+  NCompress::NRangeCoder::CDecoder _rangeDecoder;\r
+  NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusDecoder[256 + 2];\r
+\r
+  COutBuffer _outStream;\r
+  UInt32 _inBufSizes[4];\r
+  UInt32 _outBufSize;\r
+\r
+public:\r
+  void ReleaseStreams()\r
+  {\r
+    _mainInStream.ReleaseStream();\r
+    _callStream.ReleaseStream();\r
+    _jumpStream.ReleaseStream();\r
+    _rangeDecoder.ReleaseStream();\r
+    _outStream.ReleaseStream();\r
+  }\r
+\r
+  HRESULT Flush() { return _outStream.Flush(); }\r
+  class CCoderReleaser\r
+  {\r
+    CDecoder *_coder;\r
+  public:\r
+    CCoderReleaser(CDecoder *coder): _coder(coder) {}\r
+    ~CCoderReleaser()  { _coder->ReleaseStreams(); }\r
+  };\r
+\r
+public:\r
+  MY_UNKNOWN_IMP1(ICompressSetBufSize);\r
+  HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,\r
+      ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,\r
+      ICompressProgressInfo *progress);\r
+  STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,\r
+      ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,\r
+      ICompressProgressInfo *progress);\r
+\r
+  STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);\r
+  STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);\r
+  CDecoder();\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/Bcj2Register.cpp b/CPP/7zip/Compress/Bcj2Register.cpp
new file mode 100755 (executable)
index 0000000..b063f3f
--- /dev/null
@@ -0,0 +1,19 @@
+// Bcj2Register.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../Common/RegisterCodec.h"\r
+\r
+#include "Bcj2Coder.h"\r
+\r
+static void *CreateCodec() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CDecoder()); }\r
+#ifndef EXTRACT_ONLY\r
+static void *CreateCodecOut() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CEncoder());  }\r
+#else\r
+#define CreateCodecOut 0\r
+#endif\r
+\r
+static CCodecInfo g_CodecInfo =\r
+  { CreateCodec, CreateCodecOut, 0x0303011B, L"BCJ2", 4, false };\r
+\r
+REGISTER_CODEC(BCJ2)\r
diff --git a/CPP/7zip/Compress/BcjCoder.cpp b/CPP/7zip/Compress/BcjCoder.cpp
new file mode 100755 (executable)
index 0000000..108c573
--- /dev/null
@@ -0,0 +1,15 @@
+// BcjCoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "BcjCoder.h"\r
+\r
+UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size)\r
+{\r
+  return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 1);\r
+}\r
+\r
+UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size)\r
+{\r
+  return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 0);\r
+}\r
diff --git a/CPP/7zip/Compress/BcjCoder.h b/CPP/7zip/Compress/BcjCoder.h
new file mode 100755 (executable)
index 0000000..c86d5fc
--- /dev/null
@@ -0,0 +1,19 @@
+// BcjCoder.h\r
+\r
+#ifndef __COMPRESS_BCJ_CODER_H\r
+#define __COMPRESS_BCJ_CODER_H\r
+\r
+#include "../../../C/Bra.h"\r
+\r
+#include "BranchCoder.h"\r
+\r
+struct CBranch86\r
+{\r
+  UInt32 _prevMask;\r
+  void x86Init() { x86_Convert_Init(_prevMask); }\r
+};\r
+\r
+MyClassB(BCJ_x86, 0x01, 3, CBranch86 ,\r
+    virtual void SubInit() { x86Init(); })\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/BcjRegister.cpp b/CPP/7zip/Compress/BcjRegister.cpp
new file mode 100755 (executable)
index 0000000..09e53c6
--- /dev/null
@@ -0,0 +1,19 @@
+// BcjRegister.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../Common/RegisterCodec.h"\r
+\r
+#include "BcjCoder.h"\r
+\r
+static void *CreateCodec() { return (void *)(ICompressFilter *)(new CBCJ_x86_Decoder()); }\r
+#ifndef EXTRACT_ONLY\r
+static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new CBCJ_x86_Encoder());  }\r
+#else\r
+#define CreateCodecOut 0\r
+#endif\r
+\r
+static CCodecInfo g_CodecInfo =\r
+  { CreateCodec, CreateCodecOut, 0x03030103, L"BCJ", 1, true };\r
+\r
+REGISTER_CODEC(BCJ)\r
diff --git a/CPP/7zip/Compress/BitlDecoder.cpp b/CPP/7zip/Compress/BitlDecoder.cpp
new file mode 100755 (executable)
index 0000000..6022e8b
--- /dev/null
@@ -0,0 +1,24 @@
+// BitlDecoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "BitlDecoder.h"\r
+\r
+namespace NBitl {\r
+\r
+Byte kInvertTable[256];\r
+\r
+struct CInverterTableInitializer\r
+{\r
+  CInverterTableInitializer()\r
+  {\r
+    for (int i = 0; i < 256; i++)\r
+    {\r
+      int x = ((i & 0x55) << 1) | ((i & 0xAA) >> 1);\r
+      x = ((x & 0x33) << 2) | ((x & 0xCC) >> 2);\r
+      kInvertTable[i] = (Byte)(((x & 0x0F) << 4) | ((x & 0xF0) >> 4));\r
+    }\r
+  }\r
+} g_InverterTableInitializer;\r
+\r
+}\r
diff --git a/CPP/7zip/Compress/BitlDecoder.h b/CPP/7zip/Compress/BitlDecoder.h
new file mode 100755 (executable)
index 0000000..99ee24f
--- /dev/null
@@ -0,0 +1,141 @@
+// BitlDecoder.h -- the Least Significant Bit of byte is First\r
+\r
+#ifndef __BITL_DECODER_H\r
+#define __BITL_DECODER_H\r
+\r
+#include "../IStream.h"\r
+\r
+namespace NBitl {\r
+\r
+const unsigned kNumBigValueBits = 8 * 4;\r
+const unsigned kNumValueBytes = 3;\r
+const unsigned kNumValueBits = 8  * kNumValueBytes;\r
+\r
+const UInt32 kMask = (1 << kNumValueBits) - 1;\r
+\r
+extern Byte kInvertTable[256];\r
+\r
+template<class TInByte>\r
+class CBaseDecoder\r
+{\r
+protected:\r
+  unsigned m_BitPos;\r
+  UInt32 m_Value;\r
+  TInByte m_Stream;\r
+public:\r
+  UInt32 NumExtraBytes;\r
+  bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }\r
+  void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream); }\r
+  void ReleaseStream() { m_Stream.ReleaseStream(); }\r
+  void Init()\r
+  {\r
+    m_Stream.Init();\r
+    m_BitPos = kNumBigValueBits;\r
+    m_Value = 0;\r
+    NumExtraBytes = 0;\r
+  }\r
+  UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() + NumExtraBytes - (kNumBigValueBits - m_BitPos) / 8; }\r
+\r
+  void Normalize()\r
+  {\r
+    for (; m_BitPos >= 8; m_BitPos -= 8)\r
+    {\r
+      Byte b = 0;\r
+      if (!m_Stream.ReadByte(b))\r
+      {\r
+        b = 0xFF; // check it\r
+        NumExtraBytes++;\r
+      }\r
+      m_Value = (b << (kNumBigValueBits - m_BitPos)) | m_Value;\r
+    }\r
+  }\r
+  \r
+  UInt32 ReadBits(unsigned numBits)\r
+  {\r
+    Normalize();\r
+    UInt32 res = m_Value & ((1 << numBits) - 1);\r
+    m_BitPos += numBits;\r
+    m_Value >>= numBits;\r
+    return res;\r
+  }\r
+\r
+  bool ExtraBitsWereRead() const\r
+  {\r
+    if (NumExtraBytes == 0)\r
+      return false;\r
+    return ((UInt32)(kNumBigValueBits - m_BitPos) < (NumExtraBytes << 3));\r
+  }\r
+};\r
+\r
+template<class TInByte>\r
+class CDecoder: public CBaseDecoder<TInByte>\r
+{\r
+  UInt32 m_NormalValue;\r
+\r
+public:\r
+  void Init()\r
+  {\r
+    CBaseDecoder<TInByte>::Init();\r
+    m_NormalValue = 0;\r
+  }\r
+\r
+  void Normalize()\r
+  {\r
+    for (; this->m_BitPos >= 8; this->m_BitPos -= 8)\r
+    {\r
+      Byte b = 0;\r
+      if (!this->m_Stream.ReadByte(b))\r
+      {\r
+        b = 0xFF; // check it\r
+        this->NumExtraBytes++;\r
+      }\r
+      m_NormalValue = (b << (kNumBigValueBits - this->m_BitPos)) | m_NormalValue;\r
+      this->m_Value = (this->m_Value << 8) | kInvertTable[b];\r
+    }\r
+  }\r
+  \r
+  UInt32 GetValue(unsigned numBits)\r
+  {\r
+    Normalize();\r
+    return ((this->m_Value >> (8 - this->m_BitPos)) & kMask) >> (kNumValueBits - numBits);\r
+  }\r
+\r
+  void MovePos(unsigned numBits)\r
+  {\r
+    this->m_BitPos += numBits;\r
+    m_NormalValue >>= numBits;\r
+  }\r
+  \r
+  UInt32 ReadBits(unsigned numBits)\r
+  {\r
+    Normalize();\r
+    UInt32 res = m_NormalValue & ((1 << numBits) - 1);\r
+    MovePos(numBits);\r
+    return res;\r
+  }\r
+\r
+  void AlignToByte() { MovePos((32 - this->m_BitPos) & 7); }\r
+\r
+  Byte ReadByte()\r
+  {\r
+    if (this->m_BitPos == kNumBigValueBits)\r
+    {\r
+      Byte b = 0;\r
+      if (!this->m_Stream.ReadByte(b))\r
+      {\r
+        b = 0xFF;\r
+        this->NumExtraBytes++;\r
+      }\r
+      return b;\r
+    }\r
+    {\r
+      Byte b = (Byte)(m_NormalValue & 0xFF);\r
+      MovePos(8);\r
+      return b;\r
+    }\r
+  }\r
+};\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/BitlEncoder.h b/CPP/7zip/Compress/BitlEncoder.h
new file mode 100755 (executable)
index 0000000..2169092
--- /dev/null
@@ -0,0 +1,57 @@
+// BitlEncoder.h -- the Least Significant Bit of byte is First\r
+\r
+#ifndef __BITL_ENCODER_H\r
+#define __BITL_ENCODER_H\r
+\r
+#include "../Common/OutBuffer.h"\r
+\r
+class CBitlEncoder\r
+{\r
+  COutBuffer m_Stream;\r
+  unsigned m_BitPos;\r
+  Byte m_CurByte;\r
+public:\r
+  bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }\r
+  void SetStream(ISequentialOutStream *outStream) { m_Stream.SetStream(outStream); }\r
+  void ReleaseStream() { m_Stream.ReleaseStream(); }\r
+  UInt32 GetBitPosition() const { return (8 - m_BitPos); }\r
+  UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() + (8 - m_BitPos + 7) /8; }\r
+  void Init()\r
+  {\r
+    m_Stream.Init();\r
+    m_BitPos = 8;\r
+    m_CurByte = 0;\r
+  }\r
+  HRESULT Flush()\r
+  {\r
+    FlushByte();\r
+    return m_Stream.Flush();\r
+  }\r
+  void FlushByte()\r
+  {\r
+    if (m_BitPos < 8)\r
+      m_Stream.WriteByte(m_CurByte);\r
+    m_BitPos = 8;\r
+    m_CurByte = 0;\r
+  }\r
+  void WriteBits(UInt32 value, unsigned numBits)\r
+  {\r
+    while (numBits > 0)\r
+    {\r
+      if (numBits < m_BitPos)\r
+      {\r
+        m_CurByte |= (value & ((1 << numBits) - 1)) << (8 - m_BitPos);\r
+        m_BitPos -= numBits;\r
+        return;\r
+      }\r
+      numBits -= m_BitPos;\r
+      m_Stream.WriteByte((Byte)(m_CurByte | (value << (8 - m_BitPos))));\r
+      value >>= m_BitPos;\r
+      m_BitPos = 8;\r
+      m_CurByte = 0;\r
+    }\r
+  }\r
+  void WriteByte(Byte b) { m_Stream.WriteByte(b);}\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/BitmDecoder.h b/CPP/7zip/Compress/BitmDecoder.h
new file mode 100755 (executable)
index 0000000..e44dfe3
--- /dev/null
@@ -0,0 +1,66 @@
+// BitmDecoder.h -- the Most Significant Bit of byte is First\r
+\r
+#ifndef __BITM_DECODER_H\r
+#define __BITM_DECODER_H\r
+\r
+#include "../IStream.h"\r
+\r
+namespace NBitm {\r
+\r
+const unsigned kNumBigValueBits = 8 * 4;\r
+const unsigned kNumValueBytes = 3;\r
+const unsigned kNumValueBits = 8  * kNumValueBytes;\r
+\r
+const UInt32 kMask = (1 << kNumValueBits) - 1;\r
+\r
+template<class TInByte>\r
+class CDecoder\r
+{\r
+  unsigned m_BitPos;\r
+  UInt32 m_Value;\r
+public:\r
+  TInByte m_Stream;\r
+  bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }\r
+  void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream);}\r
+  void ReleaseStream() { m_Stream.ReleaseStream();}\r
+\r
+  void Init()\r
+  {\r
+    m_Stream.Init();\r
+    m_BitPos = kNumBigValueBits;\r
+    Normalize();\r
+  }\r
+  \r
+  UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() - (kNumBigValueBits - m_BitPos) / 8; }\r
+  \r
+  void Normalize()\r
+  {\r
+    for (;m_BitPos >= 8; m_BitPos -= 8)\r
+      m_Value = (m_Value << 8) | m_Stream.ReadByte();\r
+  }\r
+\r
+  UInt32 GetValue(unsigned numBits) const\r
+  {\r
+    // return (m_Value << m_BitPos) >> (kNumBigValueBits - numBits);\r
+    return ((m_Value >> (8 - m_BitPos)) & kMask) >> (kNumValueBits - numBits);\r
+  }\r
+  \r
+  void MovePos(unsigned numBits)\r
+  {\r
+    m_BitPos += numBits;\r
+    Normalize();\r
+  }\r
+  \r
+  UInt32 ReadBits(unsigned numBits)\r
+  {\r
+    UInt32 res = GetValue(numBits);\r
+    MovePos(numBits);\r
+    return res;\r
+  }\r
+\r
+  void AlignToByte() { MovePos((32 - m_BitPos) & 7); }\r
+};\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/BitmEncoder.h b/CPP/7zip/Compress/BitmEncoder.h
new file mode 100755 (executable)
index 0000000..e7d7cc1
--- /dev/null
@@ -0,0 +1,50 @@
+// BitmEncoder.h -- the Most Significant Bit of byte is First\r
+\r
+#ifndef __BITM_ENCODER_H\r
+#define __BITM_ENCODER_H\r
+\r
+#include "../IStream.h"\r
+\r
+template<class TOutByte>\r
+class CBitmEncoder\r
+{\r
+  TOutByte m_Stream;\r
+  unsigned m_BitPos;\r
+  Byte m_CurByte;\r
+public:\r
+  bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }\r
+  void SetStream(ISequentialOutStream *outStream) { m_Stream.SetStream(outStream);}\r
+  void ReleaseStream() { m_Stream.ReleaseStream(); }\r
+  UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() + (8 - m_BitPos + 7) / 8; }\r
+  void Init()\r
+  {\r
+    m_Stream.Init();\r
+    m_BitPos = 8;\r
+    m_CurByte = 0;\r
+  }\r
+  HRESULT Flush()\r
+  {\r
+    if (m_BitPos < 8)\r
+      WriteBits(0, m_BitPos);\r
+    return m_Stream.Flush();\r
+  }\r
+  void WriteBits(UInt32 value, unsigned numBits)\r
+  {\r
+    while (numBits > 0)\r
+    {\r
+      if (numBits < m_BitPos)\r
+      {\r
+        m_CurByte |= ((Byte)value << (m_BitPos -= numBits));\r
+        return;\r
+      }\r
+      numBits -= m_BitPos;\r
+      UInt32 newBits = (value >> numBits);\r
+      value -= (newBits << numBits);\r
+      m_Stream.WriteByte((Byte)(m_CurByte | newBits));\r
+      m_BitPos = 8;\r
+      m_CurByte = 0;\r
+    }\r
+  }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/BranchCoder.cpp b/CPP/7zip/Compress/BranchCoder.cpp
new file mode 100755 (executable)
index 0000000..6cacc66
--- /dev/null
@@ -0,0 +1,19 @@
+// BranchCoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "BranchCoder.h"\r
+\r
+STDMETHODIMP CBranchConverter::Init()\r
+{\r
+  _bufferPos = 0;\r
+  SubInit();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size)\r
+{\r
+  UInt32 processedSize = SubFilter(data, size);\r
+  _bufferPos += processedSize;\r
+  return processedSize;\r
+}\r
diff --git a/CPP/7zip/Compress/BranchCoder.h b/CPP/7zip/Compress/BranchCoder.h
new file mode 100755 (executable)
index 0000000..473286a
--- /dev/null
@@ -0,0 +1,44 @@
+// BranchCoder.h\r
+\r
+#ifndef __COMPRESS_BRANCH_CODER_H\r
+#define __COMPRESS_BRANCH_CODER_H\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+class CBranchConverter:\r
+  public ICompressFilter,\r
+  public CMyUnknownImp\r
+{\r
+protected:\r
+  UInt32 _bufferPos;\r
+  virtual void SubInit() {}\r
+  virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0;\r
+public:\r
+  MY_UNKNOWN_IMP;\r
+  STDMETHOD(Init)();\r
+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);\r
+};\r
+\r
+#define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \\r
+  { public: UInt32 SubFilter(Byte *data, UInt32 size); };\r
+\r
+#define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \\r
+  { public: UInt32 SubFilter(Byte *data, UInt32 size); };\r
+\r
+#define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \\r
+  { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT};\r
+\r
+#define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \\r
+  { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT};\r
+\r
+#define MyClassA(Name, id, subId)  \\r
+MyClassEncoderA(Name ## _Encoder) \\r
+MyClassDecoderA(Name ## _Decoder)\r
+\r
+#define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT)  \\r
+MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \\r
+MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT)\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/BranchMisc.cpp b/CPP/7zip/Compress/BranchMisc.cpp
new file mode 100755 (executable)
index 0000000..1a46bb1
--- /dev/null
@@ -0,0 +1,37 @@
+// BranchMisc.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Bra.h"\r
+\r
+#include "BranchMisc.h"\r
+\r
+UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size)\r
+  { return (UInt32)::ARM_Convert(data, size, _bufferPos, 1); }\r
+\r
+UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size)\r
+  { return (UInt32)::ARM_Convert(data, size, _bufferPos, 0); }\r
+\r
+UInt32 CBC_ARMT_Encoder::SubFilter(Byte *data, UInt32 size)\r
+  { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 1); }\r
+\r
+UInt32 CBC_ARMT_Decoder::SubFilter(Byte *data, UInt32 size)\r
+  { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 0); }\r
+\r
+UInt32 CBC_PPC_Encoder::SubFilter(Byte *data, UInt32 size)\r
+  { return (UInt32)::PPC_Convert(data, size, _bufferPos, 1); }\r
+\r
+UInt32 CBC_PPC_Decoder::SubFilter(Byte *data, UInt32 size)\r
+  { return (UInt32)::PPC_Convert(data, size, _bufferPos, 0); }\r
+\r
+UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size)\r
+  { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 1); }\r
+\r
+UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size)\r
+  { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 0); }\r
+\r
+UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size)\r
+  { return (UInt32)::IA64_Convert(data, size, _bufferPos, 1); }\r
+\r
+UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size)\r
+  {  return (UInt32)::IA64_Convert(data, size, _bufferPos, 0); }\r
diff --git a/CPP/7zip/Compress/BranchMisc.h b/CPP/7zip/Compress/BranchMisc.h
new file mode 100755 (executable)
index 0000000..053e923
--- /dev/null
@@ -0,0 +1,14 @@
+// BranchMisc.h\r
+\r
+#ifndef __COMPRESS_BRANCH_MISC_H\r
+#define __COMPRESS_BRANCH_MISC_H\r
+\r
+#include "BranchCoder.h"\r
+\r
+MyClassA(BC_ARM,   0x05, 1)\r
+MyClassA(BC_ARMT,  0x07, 1)\r
+MyClassA(BC_PPC,   0x02, 5)\r
+MyClassA(BC_SPARC, 0x08, 5)\r
+MyClassA(BC_IA64,  0x04, 1)\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/BranchRegister.cpp b/CPP/7zip/Compress/BranchRegister.cpp
new file mode 100755 (executable)
index 0000000..bc55dd6
--- /dev/null
@@ -0,0 +1,30 @@
+// BranchRegister.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../Common/RegisterCodec.h"\r
+\r
+#include "BranchMisc.h"\r
+\r
+#define CREATE_CODEC(x) \\r
+  static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## _Decoder); } \\r
+  static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## _Encoder); }\r
+\r
+CREATE_CODEC(BC_PPC)\r
+CREATE_CODEC(BC_IA64)\r
+CREATE_CODEC(BC_ARM)\r
+CREATE_CODEC(BC_ARMT)\r
+CREATE_CODEC(BC_SPARC)\r
+\r
+#define METHOD_ITEM(x, id1, id2, name) { CreateCodec ## x, CreateCodec ## x ## Out, 0x03030000 + (id1 * 256) + id2, name, 1, true  }\r
+\r
+static CCodecInfo g_CodecsInfo[] =\r
+{\r
+  METHOD_ITEM(BC_PPC,   0x02, 0x05, L"PPC"),\r
+  METHOD_ITEM(BC_IA64,  0x04, 1, L"IA64"),\r
+  METHOD_ITEM(BC_ARM,   0x05, 1, L"ARM"),\r
+  METHOD_ITEM(BC_ARMT,  0x07, 1, L"ARMT"),\r
+  METHOD_ITEM(BC_SPARC, 0x08, 0x05, L"SPARC")\r
+};\r
+\r
+REGISTER_CODECS(Branch)\r
diff --git a/CPP/7zip/Compress/ByteSwap.cpp b/CPP/7zip/Compress/ByteSwap.cpp
new file mode 100755 (executable)
index 0000000..7f028fb
--- /dev/null
@@ -0,0 +1,73 @@
+// ByteSwap.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "../Common/RegisterCodec.h"\r
+\r
+class CByteSwap2:\r
+  public ICompressFilter,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP\r
+  STDMETHOD(Init)();\r
+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);\r
+};\r
+\r
+class CByteSwap4:\r
+  public ICompressFilter,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP\r
+  STDMETHOD(Init)();\r
+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);\r
+};\r
+\r
+STDMETHODIMP CByteSwap2::Init() { return S_OK; }\r
+\r
+STDMETHODIMP_(UInt32) CByteSwap2::Filter(Byte *data, UInt32 size)\r
+{\r
+  const UInt32 kStep = 2;\r
+  UInt32 i;\r
+  for (i = 0; i + kStep <= size; i += kStep)\r
+  {\r
+    Byte b = data[i];\r
+    data[i] = data[i + 1];\r
+    data[i + 1] = b;\r
+  }\r
+  return i;\r
+}\r
+\r
+STDMETHODIMP CByteSwap4::Init() { return S_OK; }\r
+\r
+STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size)\r
+{\r
+  const UInt32 kStep = 4;\r
+  UInt32 i;\r
+  for (i = 0; i + kStep <= size; i += kStep)\r
+  {\r
+    Byte b0 = data[i];\r
+    Byte b1 = data[i + 1];\r
+    data[i] = data[i + 3];\r
+    data[i + 1] = data[i + 2];\r
+    data[i + 2] = b1;\r
+    data[i + 3] = b0;\r
+  }\r
+  return i;\r
+}\r
+\r
+static void *CreateCodec2() { return (void *)(ICompressFilter *)(new CByteSwap2); }\r
+static void *CreateCodec4() { return (void *)(ICompressFilter *)(new CByteSwap4); }\r
+\r
+static CCodecInfo g_CodecsInfo[] =\r
+{\r
+  { CreateCodec2, CreateCodec2, 0x020302, L"Swap2", 1, true },\r
+  { CreateCodec4, CreateCodec4, 0x020304, L"Swap4", 1, true }\r
+};\r
+\r
+REGISTER_CODECS(ByteSwap)\r
diff --git a/CPP/7zip/Compress/Codec.def b/CPP/7zip/Compress/Codec.def
new file mode 100755 (executable)
index 0000000..aab87ef
--- /dev/null
@@ -0,0 +1,4 @@
+EXPORTS\r
+  CreateObject PRIVATE\r
+  GetNumberOfMethods PRIVATE\r
+  GetMethodProperty PRIVATE\r
diff --git a/CPP/7zip/Compress/CodecExports.cpp b/CPP/7zip/Compress/CodecExports.cpp
new file mode 100755 (executable)
index 0000000..84a27cf
--- /dev/null
@@ -0,0 +1,160 @@
+// CodecExports.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/ComTry.h"\r
+\r
+#include "../../Windows/PropVariant.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "../Common/RegisterCodec.h"\r
+\r
+extern unsigned int g_NumCodecs;\r
+extern const CCodecInfo *g_Codecs[];\r
+\r
+static const UInt16 kDecodeId = 0x2790;\r
+\r
+DEFINE_GUID(CLSID_CCodec,\r
+0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);\r
+\r
+static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value)\r
+{\r
+  if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)\r
+    value->vt = VT_BSTR;\r
+  return S_OK;\r
+}\r
+\r
+static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)\r
+{\r
+  return SetPropString((const char *)&guid, sizeof(GUID), value);\r
+}\r
+\r
+static HRESULT SetClassID(CMethodId id, bool encode, PROPVARIANT *value)\r
+{\r
+  GUID clsId = CLSID_CCodec;\r
+  for (int i = 0; i < sizeof(id); i++, id >>= 8)\r
+    clsId.Data4[i] = (Byte)(id & 0xFF);\r
+  if (encode)\r
+    clsId.Data3++;\r
+  return SetPropGUID(clsId, value);\r
+}\r
+\r
+static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilter, bool &encode, int &index)\r
+{\r
+  index = -1;\r
+  if (clsID->Data1 != CLSID_CCodec.Data1 ||\r
+      clsID->Data2 != CLSID_CCodec.Data2 ||\r
+      (clsID->Data3 & ~1) != kDecodeId)\r
+    return S_OK;\r
+  encode = (clsID->Data3 != kDecodeId);\r
+  UInt64 id = 0;\r
+  for (int j = 0; j < 8; j++)\r
+    id |= ((UInt64)clsID->Data4[j]) << (8 * j);\r
+  for (unsigned i = 0; i < g_NumCodecs; i++)\r
+  {\r
+    const CCodecInfo &codec = *g_Codecs[i];\r
+    if (id != codec.Id || encode && !codec.CreateEncoder || !encode && !codec.CreateDecoder)\r
+      continue;\r
+    if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter ||\r
+        codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2)\r
+      return E_NOINTERFACE;\r
+    index = i;\r
+    return S_OK;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject)\r
+{\r
+  COM_TRY_BEGIN\r
+  *outObject = 0;\r
+  bool isCoder = (*iid == IID_ICompressCoder) != 0;\r
+  bool isCoder2 = (*iid == IID_ICompressCoder2) != 0;\r
+  bool isFilter = (*iid == IID_ICompressFilter) != 0;\r
+  const CCodecInfo &codec = *g_Codecs[index];\r
+  if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter ||\r
+      codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2)\r
+    return E_NOINTERFACE;\r
+  if (encode)\r
+  {\r
+    if (!codec.CreateEncoder)\r
+      return CLASS_E_CLASSNOTAVAILABLE;\r
+    *outObject = codec.CreateEncoder();\r
+  }\r
+  else\r
+  {\r
+    if (!codec.CreateDecoder)\r
+      return CLASS_E_CLASSNOTAVAILABLE;\r
+    *outObject = codec.CreateDecoder();\r
+  }\r
+  if (isCoder)\r
+    ((ICompressCoder *)*outObject)->AddRef();\r
+  else if (isCoder2)\r
+    ((ICompressCoder2 *)*outObject)->AddRef();\r
+  else\r
+    ((ICompressFilter *)*outObject)->AddRef();\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject)\r
+{\r
+  *outObject = 0;\r
+  bool isCoder = (*iid == IID_ICompressCoder) != 0;\r
+  bool isCoder2 = (*iid == IID_ICompressCoder2) != 0;\r
+  bool isFilter = (*iid == IID_ICompressFilter) != 0;\r
+  if (!isCoder && !isCoder2 && !isFilter)\r
+    return E_NOINTERFACE;\r
+  bool encode;\r
+  int codecIndex;\r
+  HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex);\r
+  if (res != S_OK)\r
+    return res;\r
+  if (codecIndex < 0)\r
+    return CLASS_E_CLASSNOTAVAILABLE;\r
+  return CreateCoder2(encode, codecIndex, iid, outObject);\r
+}\r
+\r
+STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)\r
+{\r
+  ::VariantClear((VARIANTARG *)value);\r
+  const CCodecInfo &codec = *g_Codecs[codecIndex];\r
+  switch(propID)\r
+  {\r
+    case NMethodPropID::kID:\r
+    {\r
+      value->uhVal.QuadPart = (UInt64)codec.Id;\r
+      value->vt = VT_UI8;\r
+      break;\r
+    }\r
+    case NMethodPropID::kName:\r
+      if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0)\r
+        value->vt = VT_BSTR;\r
+      break;\r
+    case NMethodPropID::kDecoder:\r
+      if (codec.CreateDecoder)\r
+        return SetClassID(codec.Id, false, value);\r
+      break;\r
+    case NMethodPropID::kEncoder:\r
+      if (codec.CreateEncoder)\r
+        return SetClassID(codec.Id, true, value);\r
+      break;\r
+    case NMethodPropID::kInStreams:\r
+    {\r
+      if (codec.NumInStreams != 1)\r
+      {\r
+        value->vt = VT_UI4;\r
+        value->ulVal = (ULONG)codec.NumInStreams;\r
+      }\r
+      break;\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDAPI GetNumberOfMethods(UINT32 *numCodecs)\r
+{\r
+  *numCodecs = g_NumCodecs;\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/Compress/CopyCoder.cpp b/CPP/7zip/Compress/CopyCoder.cpp
new file mode 100755 (executable)
index 0000000..da15d04
--- /dev/null
@@ -0,0 +1,67 @@
+// Compress/CopyCoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "CopyCoder.h"\r
+\r
+namespace NCompress {\r
+\r
+static const UInt32 kBufferSize = 1 << 17;\r
+\r
+CCopyCoder::~CCopyCoder()\r
+{\r
+  ::MidFree(_buffer);\r
+}\r
+\r
+STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream,\r
+    ISequentialOutStream *outStream,\r
+    const UInt64 * /* inSize */, const UInt64 *outSize,\r
+    ICompressProgressInfo *progress)\r
+{\r
+  if (_buffer == 0)\r
+  {\r
+    _buffer = (Byte *)::MidAlloc(kBufferSize);\r
+    if (_buffer == 0)\r
+      return E_OUTOFMEMORY;\r
+  }\r
+\r
+  TotalSize = 0;\r
+  for (;;)\r
+  {\r
+    UInt32 size = kBufferSize;\r
+    if (outSize != 0)\r
+      if (size > *outSize - TotalSize)\r
+        size = (UInt32)(*outSize - TotalSize);\r
+    RINOK(inStream->Read(_buffer, size, &size));\r
+    if (size == 0)\r
+      break;\r
+    if (outStream)\r
+    {\r
+      RINOK(WriteStream(outStream, _buffer, size));\r
+    }\r
+    TotalSize += size;\r
+    if (progress != NULL)\r
+    {\r
+      RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize));\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value)\r
+{\r
+  *value = TotalSize;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)\r
+{\r
+  CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;\r
+  return copyCoder->Code(inStream, outStream, NULL, NULL, progress);\r
+}\r
+\r
+}\r
diff --git a/CPP/7zip/Compress/CopyCoder.h b/CPP/7zip/Compress/CopyCoder.h
new file mode 100755 (executable)
index 0000000..16c42ee
--- /dev/null
@@ -0,0 +1,34 @@
+// Compress/CopyCoder.h\r
+\r
+#ifndef __COMPRESS_COPY_CODER_H\r
+#define __COMPRESS_COPY_CODER_H\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+namespace NCompress {\r
+\r
+class CCopyCoder:\r
+  public ICompressCoder,\r
+  public ICompressGetInStreamProcessedSize,\r
+  public CMyUnknownImp\r
+{\r
+  Byte *_buffer;\r
+public:\r
+  UInt64 TotalSize;\r
+  CCopyCoder(): TotalSize(0), _buffer(0) {};\r
+  ~CCopyCoder();\r
+\r
+  MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize)\r
+\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+  STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);\r
+};\r
+\r
+HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress);\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/CopyRegister.cpp b/CPP/7zip/Compress/CopyRegister.cpp
new file mode 100755 (executable)
index 0000000..3ef2459
--- /dev/null
@@ -0,0 +1,14 @@
+// CopyRegister.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../Common/RegisterCodec.h"\r
+\r
+#include "CopyCoder.h"\r
+\r
+static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::CCopyCoder); }\r
+\r
+static CCodecInfo g_CodecInfo =\r
+{ CreateCodec, CreateCodec, 0x00, L"Copy", 1, false };\r
+\r
+REGISTER_CODEC(Copy)\r
diff --git a/CPP/7zip/Compress/Deflate64Register.cpp b/CPP/7zip/Compress/Deflate64Register.cpp
new file mode 100755 (executable)
index 0000000..6d6a904
--- /dev/null
@@ -0,0 +1,20 @@
+// Deflate64Register.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../Common/RegisterCodec.h"\r
+\r
+#include "DeflateDecoder.h"\r
+\r
+static void *CreateCodecDeflate64() { return (void *)(ICompressCoder *)(new NCompress::NDeflate::NDecoder::CCOMCoder64); }\r
+#if !defined(EXTRACT_ONLY) && !defined(DEFLATE_EXTRACT_ONLY)\r
+#include "DeflateEncoder.h"\r
+static void *CreateCodecOutDeflate64() { return (void *)(ICompressCoder *)(new NCompress::NDeflate::NEncoder::CCOMCoder64);  }\r
+#else\r
+#define CreateCodecOutDeflate64 0\r
+#endif\r
+\r
+static CCodecInfo g_CodecInfo =\r
+  { CreateCodecDeflate64, CreateCodecOutDeflate64, 0x040109, L"Deflate64", 1, false };\r
+\r
+REGISTER_CODEC(Deflate64)\r
diff --git a/CPP/7zip/Compress/DeflateConst.h b/CPP/7zip/Compress/DeflateConst.h
new file mode 100755 (executable)
index 0000000..b5c28d7
--- /dev/null
@@ -0,0 +1,134 @@
+// DeflateConst.h\r
+\r
+#ifndef __DEFLATE_CONST_H\r
+#define __DEFLATE_CONST_H\r
+\r
+namespace NCompress {\r
+namespace NDeflate {\r
+\r
+const int kNumHuffmanBits = 15;\r
+\r
+const UInt32 kHistorySize32 = (1 << 15);\r
+const UInt32 kHistorySize64 = (1 << 16);\r
+\r
+const UInt32 kDistTableSize32 = 30;\r
+const UInt32 kDistTableSize64 = 32;\r
+  \r
+const UInt32 kNumLenSymbols32 = 256;\r
+const UInt32 kNumLenSymbols64 = 255; // don't change it. It must be <= 255.\r
+const UInt32 kNumLenSymbolsMax = kNumLenSymbols32;\r
+  \r
+const UInt32 kNumLenSlots = 29;\r
+\r
+const UInt32 kFixedDistTableSize = 32;\r
+const UInt32 kFixedLenTableSize = 31;\r
+\r
+const UInt32 kSymbolEndOfBlock = 0x100;\r
+const UInt32 kSymbolMatch = kSymbolEndOfBlock + 1;\r
+\r
+const UInt32 kMainTableSize = kSymbolMatch + kNumLenSlots;\r
+const UInt32 kFixedMainTableSize = kSymbolMatch + kFixedLenTableSize;\r
+\r
+const UInt32 kLevelTableSize = 19;\r
+\r
+const UInt32 kTableDirectLevels = 16;\r
+const UInt32 kTableLevelRepNumber = kTableDirectLevels;\r
+const UInt32 kTableLevel0Number = kTableLevelRepNumber + 1;\r
+const UInt32 kTableLevel0Number2 = kTableLevel0Number + 1;\r
+\r
+const UInt32 kLevelMask = 0xF;\r
+\r
+const Byte kLenStart32[kFixedLenTableSize] =\r
+  {0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224, 255, 0, 0};\r
+const Byte kLenStart64[kFixedLenTableSize] =\r
+  {0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224, 0, 0, 0};\r
+\r
+const Byte kLenDirectBits32[kFixedLenTableSize] =\r
+  {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,  4,  5,  5,  5,  5, 0, 0, 0};\r
+const Byte kLenDirectBits64[kFixedLenTableSize] =\r
+  {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};\r
+\r
+const UInt32 kDistStart[kDistTableSize64]  =\r
+  {0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,\r
+  1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768,49152};\r
+const Byte kDistDirectBits[kDistTableSize64] =\r
+  {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};\r
+\r
+const Byte kLevelDirectBits[3] = {2, 3, 7};\r
+\r
+const Byte kCodeLengthAlphabetOrder[kLevelTableSize] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};\r
+\r
+const UInt32 kMatchMinLen = 3;\r
+const UInt32 kMatchMaxLen32 = kNumLenSymbols32 + kMatchMinLen - 1; //256 + 2\r
+const UInt32 kMatchMaxLen64 = kNumLenSymbols64 + kMatchMinLen - 1; //255 + 2\r
+const UInt32 kMatchMaxLen = kMatchMaxLen32;\r
+\r
+const int kFinalBlockFieldSize = 1;\r
+\r
+namespace NFinalBlockField\r
+{\r
+  enum\r
+  {\r
+    kNotFinalBlock = 0,\r
+    kFinalBlock = 1\r
+  };\r
+}\r
+\r
+const int kBlockTypeFieldSize = 2;\r
+\r
+namespace NBlockType\r
+{\r
+  enum\r
+  {\r
+    kStored = 0,\r
+    kFixedHuffman = 1,\r
+    kDynamicHuffman = 2\r
+  };\r
+}\r
+\r
+const int kNumLenCodesFieldSize = 5;\r
+const int kNumDistCodesFieldSize = 5;\r
+const int kNumLevelCodesFieldSize = 4;\r
+\r
+const UInt32 kNumLitLenCodesMin = 257;\r
+const UInt32 kNumDistCodesMin = 1;\r
+const UInt32 kNumLevelCodesMin = 4;\r
+\r
+const int kLevelFieldSize = 3;\r
+\r
+const int kStoredBlockLengthFieldSize = 16;\r
+\r
+struct CLevels\r
+{\r
+  Byte litLenLevels[kFixedMainTableSize];\r
+  Byte distLevels[kFixedDistTableSize];\r
+\r
+  void SubClear()\r
+  {\r
+    UInt32 i;\r
+    for(i = kNumLitLenCodesMin; i < kFixedMainTableSize; i++)\r
+      litLenLevels[i] = 0;\r
+    for(i = 0; i < kFixedDistTableSize; i++)\r
+      distLevels[i] = 0;\r
+  }\r
+\r
+  void SetFixedLevels()\r
+  {\r
+    int i;\r
+    \r
+    for (i = 0; i < 144; i++)\r
+      litLenLevels[i] = 8;\r
+    for (; i < 256; i++)\r
+      litLenLevels[i] = 9;\r
+    for (; i < 280; i++)\r
+      litLenLevels[i] = 7;\r
+    for (; i < 288; i++)\r
+      litLenLevels[i] = 8;\r
+    for (i = 0; i < kFixedDistTableSize; i++)  // test it: InfoZip only uses kDistTableSize\r
+      distLevels[i] = 5;\r
+  }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/DeflateDecoder.cpp b/CPP/7zip/Compress/DeflateDecoder.cpp
new file mode 100755 (executable)
index 0000000..1f1f333
--- /dev/null
@@ -0,0 +1,353 @@
+// DeflateDecoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "DeflateDecoder.h"\r
+\r
+namespace NCompress {\r
+namespace NDeflate {\r
+namespace NDecoder {\r
+\r
+static const int kLenIdFinished = -1;\r
+static const int kLenIdNeedInit = -2;\r
+\r
+CCoder::CCoder(bool deflate64Mode, bool deflateNSIS):\r
+    _deflate64Mode(deflate64Mode),\r
+    _deflateNSIS(deflateNSIS),\r
+    _keepHistory(false),\r
+    _needInitInStream(true),\r
+    ZlibMode(false) {}\r
+\r
+UInt32 CCoder::ReadBits(int numBits)\r
+{\r
+  return m_InBitStream.ReadBits(numBits);\r
+}\r
+\r
+bool CCoder::DeCodeLevelTable(Byte *values, int numSymbols)\r
+{\r
+  int i = 0;\r
+  do\r
+  {\r
+    UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);\r
+    if (number < kTableDirectLevels)\r
+      values[i++] = (Byte)number;\r
+    else if (number < kLevelTableSize)\r
+    {\r
+      if (number == kTableLevelRepNumber)\r
+      {\r
+        if (i == 0)\r
+          return false;\r
+        int num = ReadBits(2) + 3;\r
+        for (; num > 0 && i < numSymbols; num--, i++)\r
+          values[i] = values[i - 1];\r
+      }\r
+      else\r
+      {\r
+        int num;\r
+        if (number == kTableLevel0Number)\r
+          num = ReadBits(3) + 3;\r
+        else\r
+          num = ReadBits(7) + 11;\r
+        for (;num > 0 && i < numSymbols; num--)\r
+          values[i++] = 0;\r
+      }\r
+    }\r
+    else\r
+      return false;\r
+  }\r
+  while(i < numSymbols);\r
+  return true;\r
+}\r
+\r
+#define RIF(x) { if (!(x)) return false; }\r
+\r
+bool CCoder::ReadTables(void)\r
+{\r
+  m_FinalBlock = (ReadBits(kFinalBlockFieldSize) == NFinalBlockField::kFinalBlock);\r
+  UInt32 blockType = ReadBits(kBlockTypeFieldSize);\r
+  if (blockType > NBlockType::kDynamicHuffman)\r
+    return false;\r
+\r
+  if (blockType == NBlockType::kStored)\r
+  {\r
+    m_StoredMode = true;\r
+    m_InBitStream.AlignToByte();\r
+    m_StoredBlockSize = ReadBits(kStoredBlockLengthFieldSize);\r
+    if (_deflateNSIS)\r
+      return true;\r
+    return (m_StoredBlockSize == (UInt16)~ReadBits(kStoredBlockLengthFieldSize));\r
+  }\r
+\r
+  m_StoredMode = false;\r
+\r
+  CLevels levels;\r
+  if (blockType == NBlockType::kFixedHuffman)\r
+  {\r
+    levels.SetFixedLevels();\r
+    _numDistLevels = _deflate64Mode ? kDistTableSize64 : kDistTableSize32;\r
+  }\r
+  else\r
+  {\r
+    int numLitLenLevels = ReadBits(kNumLenCodesFieldSize) + kNumLitLenCodesMin;\r
+    _numDistLevels = ReadBits(kNumDistCodesFieldSize) + kNumDistCodesMin;\r
+    int numLevelCodes = ReadBits(kNumLevelCodesFieldSize) + kNumLevelCodesMin;\r
+\r
+    if (!_deflate64Mode)\r
+      if (_numDistLevels > kDistTableSize32)\r
+        return false;\r
+    \r
+    Byte levelLevels[kLevelTableSize];\r
+    for (int i = 0; i < kLevelTableSize; i++)\r
+    {\r
+      int position = kCodeLengthAlphabetOrder[i];\r
+      if(i < numLevelCodes)\r
+        levelLevels[position] = (Byte)ReadBits(kLevelFieldSize);\r
+      else\r
+        levelLevels[position] = 0;\r
+    }\r
+    \r
+    RIF(m_LevelDecoder.SetCodeLengths(levelLevels));\r
+    \r
+    Byte tmpLevels[kFixedMainTableSize + kFixedDistTableSize];\r
+    if (!DeCodeLevelTable(tmpLevels, numLitLenLevels + _numDistLevels))\r
+      return false;\r
+\r
+    levels.SubClear();\r
+    memcpy(levels.litLenLevels, tmpLevels, numLitLenLevels);\r
+    memcpy(levels.distLevels, tmpLevels + numLitLenLevels, _numDistLevels);\r
+  }\r
+  RIF(m_MainDecoder.SetCodeLengths(levels.litLenLevels));\r
+  return m_DistDecoder.SetCodeLengths(levels.distLevels);\r
+}\r
+\r
+HRESULT CCoder::CodeSpec(UInt32 curSize)\r
+{\r
+  if (_remainLen == kLenIdFinished)\r
+    return S_OK;\r
+  if (_remainLen == kLenIdNeedInit)\r
+  {\r
+    if (!_keepHistory)\r
+      if (!m_OutWindowStream.Create(_deflate64Mode ? kHistorySize64: kHistorySize32))\r
+        return E_OUTOFMEMORY;\r
+    RINOK(InitInStream(_needInitInStream));\r
+    m_OutWindowStream.Init(_keepHistory);\r
+    m_FinalBlock = false;\r
+    _remainLen = 0;\r
+    _needReadTable = true;\r
+  }\r
+\r
+  if (curSize == 0)\r
+    return S_OK;\r
+\r
+  while(_remainLen > 0 && curSize > 0)\r
+  {\r
+    _remainLen--;\r
+    Byte b = m_OutWindowStream.GetByte(_rep0);\r
+    m_OutWindowStream.PutByte(b);\r
+    curSize--;\r
+  }\r
+\r
+  while(curSize > 0)\r
+  {\r
+    if (_needReadTable)\r
+    {\r
+      if (m_FinalBlock)\r
+      {\r
+        _remainLen = kLenIdFinished;\r
+        break;\r
+      }\r
+      if (!ReadTables())\r
+        return S_FALSE;\r
+      _needReadTable = false;\r
+    }\r
+\r
+    if(m_StoredMode)\r
+    {\r
+      for (; m_StoredBlockSize > 0 && curSize > 0; m_StoredBlockSize--, curSize--)\r
+        m_OutWindowStream.PutByte(m_InBitStream.ReadByte());\r
+      _needReadTable = (m_StoredBlockSize == 0);\r
+      continue;\r
+    }\r
+    while(curSize > 0)\r
+    {\r
+      if (m_InBitStream.NumExtraBytes > 4)\r
+        return S_FALSE;\r
+\r
+      UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);\r
+      if (number < 0x100)\r
+      {\r
+        m_OutWindowStream.PutByte((Byte)number);\r
+        curSize--;\r
+        continue;\r
+      }\r
+      else if (number == kSymbolEndOfBlock)\r
+      {\r
+        _needReadTable = true;\r
+        break;\r
+      }\r
+      else if (number < kMainTableSize)\r
+      {\r
+        number -= kSymbolMatch;\r
+        UInt32 len;\r
+        {\r
+          int numBits;\r
+          if (_deflate64Mode)\r
+          {\r
+            len = kLenStart64[number];\r
+            numBits = kLenDirectBits64[number];\r
+          }\r
+          else\r
+          {\r
+            len = kLenStart32[number];\r
+            numBits = kLenDirectBits32[number];\r
+          }\r
+          len += kMatchMinLen + m_InBitStream.ReadBits(numBits);\r
+        }\r
+        UInt32 locLen = len;\r
+        if (locLen > curSize)\r
+          locLen = (UInt32)curSize;\r
+        number = m_DistDecoder.DecodeSymbol(&m_InBitStream);\r
+        if (number >= _numDistLevels)\r
+          return S_FALSE;\r
+        UInt32 distance = kDistStart[number] + m_InBitStream.ReadBits(kDistDirectBits[number]);\r
+        if (!m_OutWindowStream.CopyBlock(distance, locLen))\r
+          return S_FALSE;\r
+        curSize -= locLen;\r
+        len -= locLen;\r
+        if (len != 0)\r
+        {\r
+          _remainLen = (Int32)len;\r
+          _rep0 = distance;\r
+          break;\r
+        }\r
+      }\r
+      else\r
+        return S_FALSE;\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+#ifdef _NO_EXCEPTIONS\r
+\r
+#define DEFLATE_TRY_BEGIN\r
+#define DEFLATE_TRY_END\r
+\r
+#else\r
+\r
+#define DEFLATE_TRY_BEGIN try {\r
+#define DEFLATE_TRY_END } \\r
+  catch(const CInBufferException &e)  { return e.ErrorCode; } \\r
+  catch(const CLzOutWindowException &e)  { return e.ErrorCode; } \\r
+  catch(...) { return S_FALSE; }\r
+\r
+#endif\r
+\r
+HRESULT CCoder::CodeReal(ISequentialOutStream *outStream,\r
+      const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  DEFLATE_TRY_BEGIN\r
+  m_OutWindowStream.SetStream(outStream);\r
+  CCoderReleaser flusher(this);\r
+\r
+  const UInt64 inStart = _needInitInStream ? 0 : m_InBitStream.GetProcessedSize();\r
+  const UInt64 start = m_OutWindowStream.GetProcessedSize();\r
+  for (;;)\r
+  {\r
+    UInt32 curSize = 1 << 18;\r
+    if (outSize != 0)\r
+    {\r
+      const UInt64 rem = *outSize - (m_OutWindowStream.GetProcessedSize() - start);\r
+      if (curSize > rem)\r
+        curSize = (UInt32)rem;\r
+    }\r
+    if (curSize == 0)\r
+      break;\r
+    RINOK(CodeSpec(curSize));\r
+    if (_remainLen == kLenIdFinished)\r
+      break;\r
+    if (progress != NULL)\r
+    {\r
+      const UInt64 inSize = m_InBitStream.GetProcessedSize() - inStart;\r
+      const UInt64 nowPos64 = m_OutWindowStream.GetProcessedSize() - start;\r
+      RINOK(progress->SetRatioInfo(&inSize, &nowPos64));\r
+    }\r
+  }\r
+  if (_remainLen == kLenIdFinished && ZlibMode)\r
+  {\r
+    m_InBitStream.AlignToByte();\r
+    for (int i = 0; i < 4; i++)\r
+      ZlibFooter[i] = m_InBitStream.ReadByte();\r
+  }\r
+  flusher.NeedFlush = false;\r
+  HRESULT res = Flush();\r
+  if (res == S_OK && InputEofError())\r
+    return S_FALSE;\r
+  return res;\r
+  DEFLATE_TRY_END\r
+}\r
+\r
+HRESULT CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  SetInStream(inStream);\r
+  SetOutStreamSize(outSize);\r
+  HRESULT res = CodeReal(outStream, outSize, progress);\r
+  ReleaseInStream();\r
+  return res;\r
+}\r
+\r
+STDMETHODIMP CCoder::GetInStreamProcessedSize(UInt64 *value)\r
+{\r
+  if (value == NULL)\r
+    return E_INVALIDARG;\r
+  *value = m_InBitStream.GetProcessedSize();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CCoder::SetInStream(ISequentialInStream *inStream)\r
+{\r
+  m_InBitStream.SetStream(inStream);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CCoder::ReleaseInStream()\r
+{\r
+  m_InBitStream.ReleaseStream();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CCoder::SetOutStreamSize(const UInt64 * /* outSize */)\r
+{\r
+  _remainLen = kLenIdNeedInit;\r
+  _needInitInStream = true;\r
+  m_OutWindowStream.Init(_keepHistory);\r
+  return S_OK;\r
+}\r
+\r
+#ifndef NO_READ_FROM_CODER\r
+\r
+STDMETHODIMP CCoder::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  DEFLATE_TRY_BEGIN\r
+  if (processedSize)\r
+    *processedSize = 0;\r
+  const UInt64 startPos = m_OutWindowStream.GetProcessedSize();\r
+  m_OutWindowStream.SetMemStream((Byte *)data);\r
+  RINOK(CodeSpec(size));\r
+  if (processedSize)\r
+    *processedSize = (UInt32)(m_OutWindowStream.GetProcessedSize() - startPos);\r
+  return Flush();\r
+  DEFLATE_TRY_END\r
+}\r
+\r
+#endif\r
+\r
+STDMETHODIMP CCoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  _remainLen = kLenIdNeedInit;\r
+  m_OutWindowStream.Init(_keepHistory);\r
+  return CodeReal(outStream, outSize, progress);\r
+}\r
+\r
+}}}\r
diff --git a/CPP/7zip/Compress/DeflateDecoder.h b/CPP/7zip/Compress/DeflateDecoder.h
new file mode 100755 (executable)
index 0000000..1cc5890
--- /dev/null
@@ -0,0 +1,157 @@
+// DeflateDecoder.h\r
+\r
+#ifndef __DEFLATE_DECODER_H\r
+#define __DEFLATE_DECODER_H\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "../Common/InBuffer.h"\r
+\r
+#include "BitlDecoder.h"\r
+#include "DeflateConst.h"\r
+#include "HuffmanDecoder.h"\r
+#include "LzOutWindow.h"\r
+\r
+namespace NCompress {\r
+namespace NDeflate {\r
+namespace NDecoder {\r
+\r
+class CCoder:\r
+  public ICompressCoder,\r
+  public ICompressGetInStreamProcessedSize,\r
+  #ifndef NO_READ_FROM_CODER\r
+  public ICompressSetInStream,\r
+  public ICompressSetOutStreamSize,\r
+  public ISequentialInStream,\r
+  #endif\r
+  public CMyUnknownImp\r
+{\r
+  CLzOutWindow m_OutWindowStream;\r
+  NBitl::CDecoder<CInBuffer> m_InBitStream;\r
+  NCompress::NHuffman::CDecoder<kNumHuffmanBits, kFixedMainTableSize> m_MainDecoder;\r
+  NCompress::NHuffman::CDecoder<kNumHuffmanBits, kFixedDistTableSize> m_DistDecoder;\r
+  NCompress::NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder;\r
+\r
+  UInt32 m_StoredBlockSize;\r
+\r
+  bool m_FinalBlock;\r
+  bool m_StoredMode;\r
+  UInt32 _numDistLevels;\r
+\r
+\r
+  bool _deflateNSIS;\r
+  bool _deflate64Mode;\r
+  bool _keepHistory;\r
+  bool _needInitInStream;\r
+  Int32 _remainLen;\r
+  UInt32 _rep0;\r
+  bool _needReadTable;\r
+\r
+  UInt32 ReadBits(int numBits);\r
+\r
+  bool DeCodeLevelTable(Byte *values, int numSymbols);\r
+  bool ReadTables();\r
+  \r
+  HRESULT Flush() { return m_OutWindowStream.Flush(); }\r
+  class CCoderReleaser\r
+  {\r
+    CCoder *_coder;\r
+  public:\r
+    bool NeedFlush;\r
+    CCoderReleaser(CCoder *coder): _coder(coder), NeedFlush(true) {}\r
+    ~CCoderReleaser()\r
+    {\r
+      if (NeedFlush)\r
+        _coder->Flush();\r
+      _coder->ReleaseOutStream();\r
+    }\r
+  };\r
+  friend class CCoderReleaser;\r
+\r
+  HRESULT CodeSpec(UInt32 curSize);\r
+public:\r
+  bool ZlibMode;\r
+  Byte ZlibFooter[4];\r
+\r
+  CCoder(bool deflate64Mode, bool deflateNSIS = false);\r
+  virtual ~CCoder() {};\r
+\r
+  void SetKeepHistory(bool keepHistory) { _keepHistory = keepHistory; }\r
+\r
+  void ReleaseOutStream()\r
+  {\r
+    m_OutWindowStream.ReleaseStream();\r
+  }\r
+\r
+  HRESULT CodeReal(ISequentialOutStream *outStream,\r
+      const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+  #ifndef NO_READ_FROM_CODER\r
+  MY_UNKNOWN_IMP4(\r
+      ICompressGetInStreamProcessedSize,\r
+      ICompressSetInStream,\r
+      ICompressSetOutStreamSize,\r
+      ISequentialInStream\r
+      )\r
+  #else\r
+  MY_UNKNOWN_IMP1(\r
+      ICompressGetInStreamProcessedSize)\r
+  #endif\r
+\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+  STDMETHOD(SetInStream)(ISequentialInStream *inStream);\r
+  STDMETHOD(ReleaseInStream)();\r
+  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);\r
+  \r
+  #ifndef NO_READ_FROM_CODER\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  #endif\r
+\r
+  STDMETHOD(CodeResume)(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+  HRESULT InitInStream(bool needInit)\r
+  {\r
+    if (!m_InBitStream.Create(1 << 17))\r
+      return E_OUTOFMEMORY;\r
+    if (needInit)\r
+    {\r
+      m_InBitStream.Init();\r
+      _needInitInStream = false;\r
+    }\r
+    return S_OK;\r
+  }\r
+\r
+  void AlignToByte() { m_InBitStream.AlignToByte(); }\r
+  Byte ReadByte() { return (Byte)m_InBitStream.ReadBits(8); }\r
+  bool InputEofError() const { return m_InBitStream.ExtraBitsWereRead(); }\r
+  UInt64 GetInputProcessedSize() const { return m_InBitStream.GetProcessedSize(); }\r
+\r
+  // IGetInStreamProcessedSize\r
+  STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);\r
+};\r
+\r
+class CCOMCoder : public CCoder\r
+{\r
+public:\r
+  CCOMCoder(): CCoder(false) {}\r
+};\r
+\r
+class CNsisCOMCoder : public CCoder\r
+{\r
+public:\r
+  CNsisCOMCoder(): CCoder(false, true) {}\r
+};\r
+\r
+class CCOMCoder64 : public CCoder\r
+{\r
+public:\r
+  CCOMCoder64(): CCoder(true) {}\r
+};\r
+\r
+}}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/DeflateEncoder.cpp b/CPP/7zip/Compress/DeflateEncoder.cpp
new file mode 100755 (executable)
index 0000000..f2a51f1
--- /dev/null
@@ -0,0 +1,986 @@
+// DeflateEncoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+#include "../../../C/HuffEnc.h"\r
+\r
+#include "Common/ComTry.h"\r
+\r
+#include "DeflateEncoder.h"\r
+\r
+#undef NO_INLINE\r
+\r
+#ifdef _MSC_VER\r
+#define NO_INLINE MY_NO_INLINE\r
+#else\r
+#define NO_INLINE\r
+#endif\r
+\r
+namespace NCompress {\r
+namespace NDeflate {\r
+namespace NEncoder {\r
+\r
+const int kNumDivPassesMax = 10; // [0, 16); ratio/speed/ram tradeoff; use big value for better compression ratio.\r
+const UInt32 kNumTables = (1 << kNumDivPassesMax);\r
+\r
+static UInt32 kFixedHuffmanCodeBlockSizeMax = (1 << 8); // [0, (1 << 32)); ratio/speed tradeoff; use big value for better compression ratio.\r
+static UInt32 kDivideCodeBlockSizeMin = (1 << 7); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio.\r
+static UInt32 kDivideBlockSizeMin = (1 << 6); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio.\r
+\r
+static const UInt32 kMaxUncompressedBlockSize = ((1 << 16) - 1) * 1; // [1, (1 << 32))\r
+static const UInt32 kMatchArraySize = kMaxUncompressedBlockSize * 10; // [kMatchMaxLen * 2, (1 << 32))\r
+static const UInt32 kMatchArrayLimit = kMatchArraySize - kMatchMaxLen * 4 * sizeof(UInt16);\r
+static const UInt32 kBlockUncompressedSizeThreshold = kMaxUncompressedBlockSize -\r
+    kMatchMaxLen - kNumOpts;\r
+\r
+static const int kMaxCodeBitLength = 11;\r
+static const int kMaxLevelBitLength = 7;\r
+\r
+static Byte kNoLiteralStatPrice = 11;\r
+static Byte kNoLenStatPrice = 11;\r
+static Byte kNoPosStatPrice = 6;\r
+\r
+static Byte g_LenSlots[kNumLenSymbolsMax];\r
+static Byte g_FastPos[1 << 9];\r
+\r
+class CFastPosInit\r
+{\r
+public:\r
+  CFastPosInit()\r
+  {\r
+    int i;\r
+    for(i = 0; i < kNumLenSlots; i++)\r
+    {\r
+      int c = kLenStart32[i];\r
+      int j = 1 << kLenDirectBits32[i];\r
+      for(int k = 0; k < j; k++, c++)\r
+        g_LenSlots[c] = (Byte)i;\r
+    }\r
+    \r
+    const int kFastSlots = 18;\r
+    int c = 0;\r
+    for (Byte slotFast = 0; slotFast < kFastSlots; slotFast++)\r
+    {\r
+      UInt32 k = (1 << kDistDirectBits[slotFast]);\r
+      for (UInt32 j = 0; j < k; j++, c++)\r
+        g_FastPos[c] = slotFast;\r
+    }\r
+  }\r
+};\r
+\r
+static CFastPosInit g_FastPosInit;\r
+\r
+\r
+inline UInt32 GetPosSlot(UInt32 pos)\r
+{\r
+  if (pos < 0x200)\r
+    return g_FastPos[pos];\r
+  return g_FastPos[pos >> 8] + 16;\r
+}\r
+\r
+static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }\r
+static void SzFree(void *p, void *address) { p = p; MyFree(address); }\r
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };\r
+\r
+CCoder::CCoder(bool deflate64Mode):\r
+  m_Deflate64Mode(deflate64Mode),\r
+  m_NumPasses(1),\r
+  m_NumDivPasses(1),\r
+  m_NumFastBytes(32),\r
+  _fastMode(false),\r
+  _btMode(true),\r
+  m_OnePosMatchesMemory(0),\r
+  m_DistanceMemory(0),\r
+  m_Created(false),\r
+  m_Values(0),\r
+  m_Tables(0),\r
+  m_MatchFinderCycles(0)\r
+  // m_SetMfPasses(0)\r
+{\r
+  m_MatchMaxLen = deflate64Mode ? kMatchMaxLen64 : kMatchMaxLen32;\r
+  m_NumLenCombinations = deflate64Mode ? kNumLenSymbols64 : kNumLenSymbols32;\r
+  m_LenStart = deflate64Mode ? kLenStart64 : kLenStart32;\r
+  m_LenDirectBits = deflate64Mode ? kLenDirectBits64 : kLenDirectBits32;\r
+  MatchFinder_Construct(&_lzInWindow);\r
+}\r
+\r
+HRESULT CCoder::Create()\r
+{\r
+  COM_TRY_BEGIN\r
+  if (m_Values == 0)\r
+  {\r
+    m_Values = (CCodeValue *)MyAlloc((kMaxUncompressedBlockSize) * sizeof(CCodeValue));\r
+    if (m_Values == 0)\r
+      return E_OUTOFMEMORY;\r
+  }\r
+  if (m_Tables == 0)\r
+  {\r
+    m_Tables = (CTables *)MyAlloc((kNumTables) * sizeof(CTables));\r
+    if (m_Tables == 0)\r
+      return E_OUTOFMEMORY;\r
+  }\r
+\r
+  if (m_IsMultiPass)\r
+  {\r
+    if (m_OnePosMatchesMemory == 0)\r
+    {\r
+      m_OnePosMatchesMemory = (UInt16 *)::MidAlloc(kMatchArraySize * sizeof(UInt16));\r
+      if (m_OnePosMatchesMemory == 0)\r
+        return E_OUTOFMEMORY;\r
+    }\r
+  }\r
+  else\r
+  {\r
+    if (m_DistanceMemory == 0)\r
+    {\r
+      m_DistanceMemory = (UInt16 *)MyAlloc((kMatchMaxLen + 2) * 2 * sizeof(UInt16));\r
+      if (m_DistanceMemory == 0)\r
+        return E_OUTOFMEMORY;\r
+      m_MatchDistances = m_DistanceMemory;\r
+    }\r
+  }\r
+\r
+  if (!m_Created)\r
+  {\r
+    _lzInWindow.btMode = _btMode ? 1 : 0;\r
+    _lzInWindow.numHashBytes = 3;\r
+    if (!MatchFinder_Create(&_lzInWindow,\r
+        m_Deflate64Mode ? kHistorySize64 : kHistorySize32,\r
+        kNumOpts + kMaxUncompressedBlockSize,\r
+        m_NumFastBytes, m_MatchMaxLen - m_NumFastBytes, &g_Alloc))\r
+      return E_OUTOFMEMORY;\r
+    if (!m_OutStream.Create(1 << 20))\r
+      return E_OUTOFMEMORY;\r
+  }\r
+  if (m_MatchFinderCycles != 0)\r
+    _lzInWindow.cutValue = m_MatchFinderCycles;\r
+  m_Created = true;\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+HRESULT CCoder::BaseSetEncoderProperties2(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)\r
+{\r
+  for (UInt32 i = 0; i < numProps; i++)\r
+  {\r
+    const PROPVARIANT &prop = props[i];\r
+    switch(propIDs[i])\r
+    {\r
+      case NCoderPropID::kNumPasses:\r
+        if (prop.vt != VT_UI4)\r
+          return E_INVALIDARG;\r
+        m_NumDivPasses = prop.ulVal;\r
+        if (m_NumDivPasses == 0)\r
+          m_NumDivPasses = 1;\r
+        if (m_NumDivPasses == 1)\r
+          m_NumPasses = 1;\r
+        else if (m_NumDivPasses <= kNumDivPassesMax)\r
+          m_NumPasses = 2;\r
+        else\r
+        {\r
+          m_NumPasses = 2 + (m_NumDivPasses - kNumDivPassesMax);\r
+          m_NumDivPasses = kNumDivPassesMax;\r
+        }\r
+        break;\r
+      case NCoderPropID::kNumFastBytes:\r
+        if (prop.vt != VT_UI4)\r
+          return E_INVALIDARG;\r
+        m_NumFastBytes = prop.ulVal;\r
+        if(m_NumFastBytes < kMatchMinLen || m_NumFastBytes > m_MatchMaxLen)\r
+          return E_INVALIDARG;\r
+        break;\r
+      case NCoderPropID::kMatchFinderCycles:\r
+      {\r
+        if (prop.vt != VT_UI4)\r
+          return E_INVALIDARG;\r
+        m_MatchFinderCycles = prop.ulVal;\r
+        break;\r
+      }\r
+      case NCoderPropID::kAlgorithm:\r
+      {\r
+        if (prop.vt != VT_UI4)\r
+          return E_INVALIDARG;\r
+        UInt32 maximize = prop.ulVal;\r
+        _fastMode = (maximize == 0);\r
+        _btMode = !_fastMode;\r
+        break;\r
+      }\r
+      default:\r
+        return E_INVALIDARG;\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+  \r
+void CCoder::Free()\r
+{\r
+  ::MidFree(m_OnePosMatchesMemory); m_OnePosMatchesMemory = 0;\r
+  ::MyFree(m_DistanceMemory); m_DistanceMemory = 0;\r
+  ::MyFree(m_Values); m_Values = 0;\r
+  ::MyFree(m_Tables); m_Tables = 0;\r
+}\r
+\r
+CCoder::~CCoder()\r
+{\r
+  Free();\r
+  MatchFinder_Free(&_lzInWindow, &g_Alloc);\r
+}\r
+\r
+NO_INLINE void CCoder::GetMatches()\r
+{\r
+  if (m_IsMultiPass)\r
+  {\r
+    m_MatchDistances = m_OnePosMatchesMemory + m_Pos;\r
+    if (m_SecondPass)\r
+    {\r
+      m_Pos += *m_MatchDistances + 1;\r
+      return;\r
+    }\r
+  }\r
+\r
+  UInt32 distanceTmp[kMatchMaxLen * 2 + 3];\r
+  \r
+  UInt32 numPairs = (_btMode) ?\r
+      Bt3Zip_MatchFinder_GetMatches(&_lzInWindow, distanceTmp):\r
+      Hc3Zip_MatchFinder_GetMatches(&_lzInWindow, distanceTmp);\r
+\r
+  *m_MatchDistances = (UInt16)numPairs;\r
+   \r
+  if (numPairs > 0)\r
+  {\r
+    UInt32 i;\r
+    for(i = 0; i < numPairs; i += 2)\r
+    {\r
+      m_MatchDistances[i + 1] = (UInt16)distanceTmp[i];\r
+      m_MatchDistances[i + 2] = (UInt16)distanceTmp[i + 1];\r
+    }\r
+    UInt32 len = distanceTmp[numPairs - 2];\r
+    if (len == m_NumFastBytes && m_NumFastBytes != m_MatchMaxLen)\r
+    {\r
+      UInt32 numAvail = Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) + 1;\r
+      const Byte *pby = Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) - 1;\r
+      const Byte *pby2 = pby - (distanceTmp[numPairs - 1] + 1);\r
+      if (numAvail > m_MatchMaxLen)\r
+        numAvail = m_MatchMaxLen;\r
+      for (; len < numAvail && pby[len] == pby2[len]; len++);\r
+      m_MatchDistances[i - 1] = (UInt16)len;\r
+    }\r
+  }\r
+  if (m_IsMultiPass)\r
+    m_Pos += numPairs + 1;\r
+  if (!m_SecondPass)\r
+    m_AdditionalOffset++;\r
+}\r
+\r
+void CCoder::MovePos(UInt32 num)\r
+{\r
+  if (!m_SecondPass && num > 0)\r
+  {\r
+    if (_btMode)\r
+      Bt3Zip_MatchFinder_Skip(&_lzInWindow, num);\r
+    else\r
+      Hc3Zip_MatchFinder_Skip(&_lzInWindow, num);\r
+    m_AdditionalOffset += num;\r
+  }\r
+}\r
+\r
+static const UInt32 kIfinityPrice = 0xFFFFFFF;\r
+\r
+NO_INLINE UInt32 CCoder::Backward(UInt32 &backRes, UInt32 cur)\r
+{\r
+  m_OptimumEndIndex = cur;\r
+  UInt32 posMem = m_Optimum[cur].PosPrev;\r
+  UInt16 backMem = m_Optimum[cur].BackPrev;\r
+  do\r
+  {\r
+    UInt32 posPrev = posMem;\r
+    UInt16 backCur = backMem;\r
+    backMem = m_Optimum[posPrev].BackPrev;\r
+    posMem = m_Optimum[posPrev].PosPrev;\r
+    m_Optimum[posPrev].BackPrev = backCur;\r
+    m_Optimum[posPrev].PosPrev = (UInt16)cur;\r
+    cur = posPrev;\r
+  }\r
+  while(cur > 0);\r
+  backRes = m_Optimum[0].BackPrev;\r
+  m_OptimumCurrentIndex = m_Optimum[0].PosPrev;\r
+  return m_OptimumCurrentIndex;\r
+}\r
+\r
+NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes)\r
+{\r
+  if(m_OptimumEndIndex != m_OptimumCurrentIndex)\r
+  {\r
+    UInt32 len = m_Optimum[m_OptimumCurrentIndex].PosPrev - m_OptimumCurrentIndex;\r
+    backRes = m_Optimum[m_OptimumCurrentIndex].BackPrev;\r
+    m_OptimumCurrentIndex = m_Optimum[m_OptimumCurrentIndex].PosPrev;\r
+    return len;\r
+  }\r
+  m_OptimumCurrentIndex = m_OptimumEndIndex = 0;\r
+  \r
+  GetMatches();\r
+\r
+  UInt32 numDistancePairs = m_MatchDistances[0];\r
+  if(numDistancePairs == 0)\r
+    return 1;\r
+\r
+  const UInt16 *matchDistances = m_MatchDistances + 1;\r
+  UInt32 lenMain = matchDistances[numDistancePairs - 2];\r
+\r
+  if(lenMain > m_NumFastBytes)\r
+  {\r
+    backRes = matchDistances[numDistancePairs - 1];\r
+    MovePos(lenMain - 1);\r
+    return lenMain;\r
+  }\r
+  m_Optimum[1].Price = m_LiteralPrices[Inline_MatchFinder_GetIndexByte(&_lzInWindow, 0 - m_AdditionalOffset)];\r
+  m_Optimum[1].PosPrev = 0;\r
+\r
+  m_Optimum[2].Price = kIfinityPrice;\r
+  m_Optimum[2].PosPrev = 1;\r
+\r
+\r
+  UInt32 offs = 0;\r
+  for(UInt32 i = kMatchMinLen; i <= lenMain; i++)\r
+  {\r
+    UInt32 distance = matchDistances[offs + 1];\r
+    m_Optimum[i].PosPrev = 0;\r
+    m_Optimum[i].BackPrev = (UInt16)distance;\r
+    m_Optimum[i].Price = m_LenPrices[i - kMatchMinLen] + m_PosPrices[GetPosSlot(distance)];\r
+    if (i == matchDistances[offs])\r
+      offs += 2;\r
+  }\r
+\r
+  UInt32 cur = 0;\r
+  UInt32 lenEnd = lenMain;\r
+  for (;;)\r
+  {\r
+    ++cur;\r
+    if(cur == lenEnd || cur == kNumOptsBase || m_Pos >= kMatchArrayLimit)\r
+      return Backward(backRes, cur);\r
+    GetMatches();\r
+    matchDistances = m_MatchDistances + 1;\r
+\r
+    UInt32 numDistancePairs = m_MatchDistances[0];\r
+    UInt32 newLen = 0;\r
+    if(numDistancePairs != 0)\r
+    {\r
+      newLen = matchDistances[numDistancePairs - 2];\r
+      if(newLen > m_NumFastBytes)\r
+      {\r
+        UInt32 len = Backward(backRes, cur);\r
+        m_Optimum[cur].BackPrev = matchDistances[numDistancePairs - 1];\r
+        m_OptimumEndIndex = cur + newLen;\r
+        m_Optimum[cur].PosPrev = (UInt16)m_OptimumEndIndex;\r
+        MovePos(newLen - 1);\r
+        return len;\r
+      }\r
+    }\r
+    UInt32 curPrice = m_Optimum[cur].Price;\r
+    UInt32 curAnd1Price = curPrice + m_LiteralPrices[Inline_MatchFinder_GetIndexByte(&_lzInWindow, cur - m_AdditionalOffset)];\r
+    COptimal &optimum = m_Optimum[cur + 1];\r
+    if (curAnd1Price < optimum.Price)\r
+    {\r
+      optimum.Price = curAnd1Price;\r
+      optimum.PosPrev = (UInt16)cur;\r
+    }\r
+    if(numDistancePairs == 0)\r
+      continue;\r
+    while(lenEnd < cur + newLen)\r
+      m_Optimum[++lenEnd].Price = kIfinityPrice;\r
+    offs = 0;\r
+    UInt32 distance = matchDistances[offs + 1];\r
+    curPrice += m_PosPrices[GetPosSlot(distance)];\r
+    for(UInt32 lenTest = kMatchMinLen; ; lenTest++)\r
+    {\r
+      UInt32 curAndLenPrice = curPrice + m_LenPrices[lenTest - kMatchMinLen];\r
+      COptimal &optimum = m_Optimum[cur + lenTest];\r
+      if (curAndLenPrice < optimum.Price)\r
+      {\r
+        optimum.Price = curAndLenPrice;\r
+        optimum.PosPrev = (UInt16)cur;\r
+        optimum.BackPrev = (UInt16)distance;\r
+      }\r
+      if (lenTest == matchDistances[offs])\r
+      {\r
+        offs += 2;\r
+        if (offs == numDistancePairs)\r
+          break;\r
+        curPrice -= m_PosPrices[GetPosSlot(distance)];\r
+        distance = matchDistances[offs + 1];\r
+        curPrice += m_PosPrices[GetPosSlot(distance)];\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+UInt32 CCoder::GetOptimalFast(UInt32 &backRes)\r
+{\r
+  GetMatches();\r
+  UInt32 numDistancePairs = m_MatchDistances[0];\r
+  if (numDistancePairs == 0)\r
+    return 1;\r
+  UInt32 lenMain = m_MatchDistances[numDistancePairs - 1];\r
+  backRes = m_MatchDistances[numDistancePairs];\r
+  MovePos(lenMain - 1);\r
+  return lenMain;\r
+}\r
+\r
+void CTables::InitStructures()\r
+{\r
+  UInt32 i;\r
+  for(i = 0; i < 256; i++)\r
+    litLenLevels[i] = 8;\r
+  litLenLevels[i++] = 13;\r
+  for(;i < kFixedMainTableSize; i++)\r
+    litLenLevels[i] = 5;\r
+  for(i = 0; i < kFixedDistTableSize; i++)\r
+    distLevels[i] = 5;\r
+}\r
+\r
+NO_INLINE void CCoder::LevelTableDummy(const Byte *levels, int numLevels, UInt32 *freqs)\r
+{\r
+  int prevLen = 0xFF;\r
+  int nextLen = levels[0];\r
+  int count = 0;\r
+  int maxCount = 7;\r
+  int minCount = 4;\r
+  if (nextLen == 0)\r
+  {\r
+    maxCount = 138;\r
+    minCount = 3;\r
+  }\r
+  for (int n = 0; n < numLevels; n++)\r
+  {\r
+    int curLen = nextLen;\r
+    nextLen = (n < numLevels - 1) ? levels[n + 1] : 0xFF;\r
+    count++;\r
+    if (count < maxCount && curLen == nextLen)\r
+      continue;\r
+    \r
+    if (count < minCount)\r
+      freqs[curLen] += (UInt32)count;\r
+    else if (curLen != 0)\r
+    {\r
+      if (curLen != prevLen)\r
+      {\r
+        freqs[curLen]++;\r
+        count--;\r
+      }\r
+      freqs[kTableLevelRepNumber]++;\r
+    }\r
+    else if (count <= 10)\r
+      freqs[kTableLevel0Number]++;\r
+    else\r
+      freqs[kTableLevel0Number2]++;\r
+\r
+    count = 0;\r
+    prevLen = curLen;\r
+    \r
+    if (nextLen == 0)\r
+    {\r
+      maxCount = 138;\r
+      minCount = 3;\r
+    }\r
+    else if (curLen == nextLen)\r
+    {\r
+      maxCount = 6;\r
+      minCount = 3;\r
+    }\r
+    else\r
+    {\r
+      maxCount = 7;\r
+      minCount = 4;\r
+    }\r
+  }\r
+}\r
+\r
+NO_INLINE void CCoder::WriteBits(UInt32 value, int numBits)\r
+{\r
+  m_OutStream.WriteBits(value, numBits);\r
+}\r
+\r
+#define WRITE_HF2(codes, lens, i) m_OutStream.WriteBits(codes[i], lens[i])\r
+#define WRITE_HF(i) WriteBits(codes[i], lens[i])\r
+\r
+NO_INLINE void CCoder::LevelTableCode(const Byte *levels, int numLevels, const Byte *lens, const UInt32 *codes)\r
+{\r
+  int prevLen = 0xFF;\r
+  int nextLen = levels[0];\r
+  int count = 0;\r
+  int maxCount = 7;\r
+  int minCount = 4;\r
+  if (nextLen == 0)\r
+  {\r
+    maxCount = 138;\r
+    minCount = 3;\r
+  }\r
+  for (int n = 0; n < numLevels; n++)\r
+  {\r
+    int curLen = nextLen;\r
+    nextLen = (n < numLevels - 1) ? levels[n + 1] : 0xFF;\r
+    count++;\r
+    if (count < maxCount && curLen == nextLen)\r
+      continue;\r
+    \r
+    if (count < minCount)\r
+      for(int i = 0; i < count; i++)\r
+        WRITE_HF(curLen);\r
+    else if (curLen != 0)\r
+    {\r
+      if (curLen != prevLen)\r
+      {\r
+        WRITE_HF(curLen);\r
+        count--;\r
+      }\r
+      WRITE_HF(kTableLevelRepNumber);\r
+      WriteBits(count - 3, 2);\r
+    }\r
+    else if (count <= 10)\r
+    {\r
+      WRITE_HF(kTableLevel0Number);\r
+      WriteBits(count - 3, 3);\r
+    }\r
+    else\r
+    {\r
+      WRITE_HF(kTableLevel0Number2);\r
+      WriteBits(count - 11, 7);\r
+    }\r
+\r
+    count = 0;\r
+    prevLen = curLen;\r
+    \r
+    if (nextLen == 0)\r
+    {\r
+      maxCount = 138;\r
+      minCount = 3;\r
+    }\r
+    else if (curLen == nextLen)\r
+    {\r
+      maxCount = 6;\r
+      minCount = 3;\r
+    }\r
+    else\r
+    {\r
+      maxCount = 7;\r
+      minCount = 4;\r
+    }\r
+  }\r
+}\r
+\r
+NO_INLINE void CCoder::MakeTables(unsigned maxHuffLen)\r
+{\r
+  Huffman_Generate(mainFreqs, mainCodes, m_NewLevels.litLenLevels, kFixedMainTableSize, maxHuffLen);\r
+  Huffman_Generate(distFreqs, distCodes, m_NewLevels.distLevels, kDistTableSize64, maxHuffLen);\r
+}\r
+\r
+NO_INLINE UInt32 Huffman_GetPrice(const UInt32 *freqs, const Byte *lens, UInt32 num)\r
+{\r
+  UInt32 price = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < num; i++)\r
+    price += lens[i] * freqs[i];\r
+  return price;\r
+}\r
+\r
+NO_INLINE UInt32 Huffman_GetPrice_Spec(const UInt32 *freqs, const Byte *lens, UInt32 num, const Byte *extraBits, UInt32 extraBase)\r
+{\r
+  return Huffman_GetPrice(freqs, lens, num) +\r
+    Huffman_GetPrice(freqs + extraBase, extraBits, num - extraBase);\r
+}\r
+\r
+NO_INLINE UInt32 CCoder::GetLzBlockPrice() const\r
+{\r
+  return\r
+    Huffman_GetPrice_Spec(mainFreqs, m_NewLevels.litLenLevels, kFixedMainTableSize, m_LenDirectBits, kSymbolMatch) +\r
+    Huffman_GetPrice_Spec(distFreqs, m_NewLevels.distLevels, kDistTableSize64, kDistDirectBits, 0);\r
+}\r
+\r
+NO_INLINE void CCoder::TryBlock()\r
+{\r
+  memset(mainFreqs, 0, sizeof(mainFreqs));\r
+  memset(distFreqs, 0, sizeof(distFreqs));\r
+\r
+  m_ValueIndex = 0;\r
+  UInt32 blockSize = BlockSizeRes;\r
+  BlockSizeRes = 0;\r
+  for (;;)\r
+  {\r
+    if (m_OptimumCurrentIndex == m_OptimumEndIndex)\r
+    {\r
+      if (m_Pos >= kMatchArrayLimit || BlockSizeRes >= blockSize || !m_SecondPass &&\r
+          ((Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) == 0) || m_ValueIndex >= m_ValueBlockSize))\r
+        break;\r
+    }\r
+    UInt32 pos;\r
+    UInt32 len;\r
+    if (_fastMode)\r
+      len = GetOptimalFast(pos);\r
+    else\r
+      len = GetOptimal(pos);\r
+    CCodeValue &codeValue = m_Values[m_ValueIndex++];\r
+    if (len >= kMatchMinLen)\r
+    {\r
+      UInt32 newLen = len - kMatchMinLen;\r
+      codeValue.Len = (UInt16)newLen;\r
+      mainFreqs[kSymbolMatch + g_LenSlots[newLen]]++;\r
+      codeValue.Pos = (UInt16)pos;\r
+      distFreqs[GetPosSlot(pos)]++;\r
+    }\r
+    else\r
+    {\r
+      Byte b = Inline_MatchFinder_GetIndexByte(&_lzInWindow, 0 - m_AdditionalOffset);\r
+      mainFreqs[b]++;\r
+      codeValue.SetAsLiteral();\r
+      codeValue.Pos = b;\r
+    }\r
+    m_AdditionalOffset -= len;\r
+    BlockSizeRes += len;\r
+  }\r
+  mainFreqs[kSymbolEndOfBlock]++;\r
+  m_AdditionalOffset += BlockSizeRes;\r
+  m_SecondPass = true;\r
+}\r
+\r
+NO_INLINE void CCoder::SetPrices(const CLevels &levels)\r
+{\r
+  if (_fastMode)\r
+    return;\r
+  UInt32 i;\r
+  for(i = 0; i < 256; i++)\r
+  {\r
+    Byte price = levels.litLenLevels[i];\r
+    m_LiteralPrices[i] = ((price != 0) ? price : kNoLiteralStatPrice);\r
+  }\r
+  \r
+  for(i = 0; i < m_NumLenCombinations; i++)\r
+  {\r
+    UInt32 slot = g_LenSlots[i];\r
+    Byte price = levels.litLenLevels[kSymbolMatch + slot];\r
+    m_LenPrices[i] = (Byte)(((price != 0) ? price : kNoLenStatPrice) + m_LenDirectBits[slot]);\r
+  }\r
+  \r
+  for(i = 0; i < kDistTableSize64; i++)\r
+  {\r
+    Byte price = levels.distLevels[i];\r
+    m_PosPrices[i] = (Byte)(((price != 0) ? price: kNoPosStatPrice) + kDistDirectBits[i]);\r
+  }\r
+}\r
+\r
+NO_INLINE void Huffman_ReverseBits(UInt32 *codes, const Byte *lens, UInt32 num)\r
+{\r
+  for (UInt32 i = 0; i < num; i++)\r
+  {\r
+    UInt32 x = codes[i];\r
+    x = ((x & 0x5555) << 1) | ((x & 0xAAAA) >> 1);\r
+    x = ((x & 0x3333) << 2) | ((x & 0xCCCC) >> 2);\r
+    x = ((x & 0x0F0F) << 4) | ((x & 0xF0F0) >> 4);\r
+    codes[i] = (((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8)) >> (16 - lens[i]);\r
+  }\r
+}\r
+\r
+NO_INLINE void CCoder::WriteBlock()\r
+{\r
+  Huffman_ReverseBits(mainCodes, m_NewLevels.litLenLevels, kFixedMainTableSize);\r
+  Huffman_ReverseBits(distCodes, m_NewLevels.distLevels, kDistTableSize64);\r
+\r
+  for (UInt32 i = 0; i < m_ValueIndex; i++)\r
+  {\r
+    const CCodeValue &codeValue = m_Values[i];\r
+    if (codeValue.IsLiteral())\r
+      WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, codeValue.Pos);\r
+    else\r
+    {\r
+      UInt32 len = codeValue.Len;\r
+      UInt32 lenSlot = g_LenSlots[len];\r
+      WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, kSymbolMatch + lenSlot);\r
+      m_OutStream.WriteBits(len - m_LenStart[lenSlot], m_LenDirectBits[lenSlot]);\r
+      UInt32 dist = codeValue.Pos;\r
+      UInt32 posSlot = GetPosSlot(dist);\r
+      WRITE_HF2(distCodes, m_NewLevels.distLevels, posSlot);\r
+      m_OutStream.WriteBits(dist - kDistStart[posSlot], kDistDirectBits[posSlot]);\r
+    }\r
+  }\r
+  WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, kSymbolEndOfBlock);\r
+}\r
+\r
+static UInt32 GetStorePrice(UInt32 blockSize, int bitPosition)\r
+{\r
+  UInt32 price = 0;\r
+  do\r
+  {\r
+    UInt32 nextBitPosition = (bitPosition + kFinalBlockFieldSize + kBlockTypeFieldSize) & 7;\r
+    int numBitsForAlign = nextBitPosition > 0 ? (8 - nextBitPosition): 0;\r
+    UInt32 curBlockSize = (blockSize < (1 << 16)) ? blockSize : (1 << 16) - 1;\r
+    price += kFinalBlockFieldSize + kBlockTypeFieldSize + numBitsForAlign + (2 + 2) * 8 + curBlockSize * 8;\r
+    bitPosition = 0;\r
+    blockSize -= curBlockSize;\r
+  }\r
+  while(blockSize != 0);\r
+  return price;\r
+}\r
+\r
+void CCoder::WriteStoreBlock(UInt32 blockSize, UInt32 additionalOffset, bool finalBlock)\r
+{\r
+  do\r
+  {\r
+    UInt32 curBlockSize = (blockSize < (1 << 16)) ? blockSize : (1 << 16) - 1;\r
+    blockSize -= curBlockSize;\r
+    WriteBits((finalBlock && (blockSize == 0) ? NFinalBlockField::kFinalBlock: NFinalBlockField::kNotFinalBlock), kFinalBlockFieldSize);\r
+    WriteBits(NBlockType::kStored, kBlockTypeFieldSize);\r
+    m_OutStream.FlushByte();\r
+    WriteBits((UInt16)curBlockSize, kStoredBlockLengthFieldSize);\r
+    WriteBits((UInt16)~curBlockSize, kStoredBlockLengthFieldSize);\r
+    const Byte *data = Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow)- additionalOffset;\r
+    for(UInt32 i = 0; i < curBlockSize; i++)\r
+      m_OutStream.WriteByte(data[i]);\r
+    additionalOffset -= curBlockSize;\r
+  }\r
+  while(blockSize != 0);\r
+}\r
+\r
+NO_INLINE UInt32 CCoder::TryDynBlock(int tableIndex, UInt32 numPasses)\r
+{\r
+  CTables &t = m_Tables[tableIndex];\r
+  BlockSizeRes = t.BlockSizeRes;\r
+  UInt32 posTemp = t.m_Pos;\r
+  SetPrices(t);\r
+\r
+  for (UInt32 p = 0; p < numPasses; p++)\r
+  {\r
+    m_Pos = posTemp;\r
+    TryBlock();\r
+    unsigned numHuffBits =\r
+        (m_ValueIndex > 18000 ? 12 :\r
+        (m_ValueIndex >  7000 ? 11 :\r
+        (m_ValueIndex >  2000 ? 10 : 9)));\r
+    MakeTables(numHuffBits);\r
+    SetPrices(m_NewLevels);\r
+  }\r
+\r
+  (CLevels &)t = m_NewLevels;\r
+\r
+  m_NumLitLenLevels = kMainTableSize;\r
+  while(m_NumLitLenLevels > kNumLitLenCodesMin && m_NewLevels.litLenLevels[m_NumLitLenLevels - 1] == 0)\r
+    m_NumLitLenLevels--;\r
+  \r
+  m_NumDistLevels = kDistTableSize64;\r
+  while(m_NumDistLevels > kNumDistCodesMin && m_NewLevels.distLevels[m_NumDistLevels - 1] == 0)\r
+    m_NumDistLevels--;\r
+  \r
+  UInt32 levelFreqs[kLevelTableSize];\r
+  memset(levelFreqs, 0, sizeof(levelFreqs));\r
+\r
+  LevelTableDummy(m_NewLevels.litLenLevels, m_NumLitLenLevels, levelFreqs);\r
+  LevelTableDummy(m_NewLevels.distLevels, m_NumDistLevels, levelFreqs);\r
+  \r
+  Huffman_Generate(levelFreqs, levelCodes, levelLens, kLevelTableSize, kMaxLevelBitLength);\r
+  \r
+  m_NumLevelCodes = kNumLevelCodesMin;\r
+  for (UInt32 i = 0; i < kLevelTableSize; i++)\r
+  {\r
+    Byte level = levelLens[kCodeLengthAlphabetOrder[i]];\r
+    if (level > 0 && i >= m_NumLevelCodes)\r
+      m_NumLevelCodes = i + 1;\r
+    m_LevelLevels[i] = level;\r
+  }\r
+  \r
+  return GetLzBlockPrice() +\r
+      Huffman_GetPrice_Spec(levelFreqs, levelLens, kLevelTableSize, kLevelDirectBits, kTableDirectLevels) +\r
+      kNumLenCodesFieldSize + kNumDistCodesFieldSize + kNumLevelCodesFieldSize +\r
+      m_NumLevelCodes * kLevelFieldSize + kFinalBlockFieldSize + kBlockTypeFieldSize;\r
+}\r
+\r
+NO_INLINE UInt32 CCoder::TryFixedBlock(int tableIndex)\r
+{\r
+  CTables &t = m_Tables[tableIndex];\r
+  BlockSizeRes = t.BlockSizeRes;\r
+  m_Pos = t.m_Pos;\r
+  m_NewLevels.SetFixedLevels();\r
+  SetPrices(m_NewLevels);\r
+  TryBlock();\r
+  return kFinalBlockFieldSize + kBlockTypeFieldSize + GetLzBlockPrice();\r
+}\r
+\r
+NO_INLINE UInt32 CCoder::GetBlockPrice(int tableIndex, int numDivPasses)\r
+{\r
+  CTables &t = m_Tables[tableIndex];\r
+  t.StaticMode = false;\r
+  UInt32 price = TryDynBlock(tableIndex, m_NumPasses);\r
+  t.BlockSizeRes = BlockSizeRes;\r
+  UInt32 numValues = m_ValueIndex;\r
+  UInt32 posTemp = m_Pos;\r
+  UInt32 additionalOffsetEnd = m_AdditionalOffset;\r
+  \r
+  if (m_CheckStatic && m_ValueIndex <= kFixedHuffmanCodeBlockSizeMax)\r
+  {\r
+    const UInt32 fixedPrice = TryFixedBlock(tableIndex);\r
+    t.StaticMode = (fixedPrice < price);\r
+    if (t.StaticMode)\r
+      price = fixedPrice;\r
+  }\r
+\r
+  const UInt32 storePrice = GetStorePrice(BlockSizeRes, 0); // bitPosition\r
+  t.StoreMode = (storePrice <= price);\r
+  if (t.StoreMode)\r
+    price = storePrice;\r
+\r
+  t.UseSubBlocks = false;\r
+\r
+  if (numDivPasses > 1 && numValues >= kDivideCodeBlockSizeMin)\r
+  {\r
+    CTables &t0 = m_Tables[(tableIndex << 1)];\r
+    (CLevels &)t0 = t;\r
+    t0.BlockSizeRes = t.BlockSizeRes >> 1;\r
+    t0.m_Pos = t.m_Pos;\r
+    UInt32 subPrice = GetBlockPrice((tableIndex << 1), numDivPasses - 1);\r
+\r
+    UInt32 blockSize2 = t.BlockSizeRes - t0.BlockSizeRes;\r
+    if (t0.BlockSizeRes >= kDivideBlockSizeMin && blockSize2 >= kDivideBlockSizeMin)\r
+    {\r
+      CTables &t1 = m_Tables[(tableIndex << 1) + 1];\r
+      (CLevels &)t1 = t;\r
+      t1.BlockSizeRes = blockSize2;\r
+      t1.m_Pos = m_Pos;\r
+      m_AdditionalOffset -= t0.BlockSizeRes;\r
+      subPrice += GetBlockPrice((tableIndex << 1) + 1, numDivPasses - 1);\r
+      t.UseSubBlocks = (subPrice < price);\r
+      if (t.UseSubBlocks)\r
+        price = subPrice;\r
+    }\r
+  }\r
+  m_AdditionalOffset = additionalOffsetEnd;\r
+  m_Pos = posTemp;\r
+  return price;\r
+}\r
+\r
+void CCoder::CodeBlock(int tableIndex, bool finalBlock)\r
+{\r
+  CTables &t = m_Tables[tableIndex];\r
+  if (t.UseSubBlocks)\r
+  {\r
+    CodeBlock((tableIndex << 1), false);\r
+    CodeBlock((tableIndex << 1) + 1, finalBlock);\r
+  }\r
+  else\r
+  {\r
+    if (t.StoreMode)\r
+      WriteStoreBlock(t.BlockSizeRes, m_AdditionalOffset, finalBlock);\r
+    else\r
+    {\r
+      WriteBits((finalBlock ? NFinalBlockField::kFinalBlock: NFinalBlockField::kNotFinalBlock), kFinalBlockFieldSize);\r
+      if (t.StaticMode)\r
+      {\r
+        WriteBits(NBlockType::kFixedHuffman, kBlockTypeFieldSize);\r
+        TryFixedBlock(tableIndex);\r
+        int i;\r
+        const int kMaxStaticHuffLen = 9;\r
+        for (i = 0; i < kFixedMainTableSize; i++)\r
+          mainFreqs[i] = (UInt32)1 << (kMaxStaticHuffLen - m_NewLevels.litLenLevels[i]);\r
+        for (i = 0; i < kFixedDistTableSize; i++)\r
+          distFreqs[i] = (UInt32)1 << (kMaxStaticHuffLen - m_NewLevels.distLevels[i]);\r
+        MakeTables(kMaxStaticHuffLen);\r
+      }\r
+      else\r
+      {\r
+        if (m_NumDivPasses > 1 || m_CheckStatic)\r
+          TryDynBlock(tableIndex, 1);\r
+        WriteBits(NBlockType::kDynamicHuffman, kBlockTypeFieldSize);\r
+        WriteBits(m_NumLitLenLevels - kNumLitLenCodesMin, kNumLenCodesFieldSize);\r
+        WriteBits(m_NumDistLevels - kNumDistCodesMin, kNumDistCodesFieldSize);\r
+        WriteBits(m_NumLevelCodes - kNumLevelCodesMin, kNumLevelCodesFieldSize);\r
+        \r
+        for (UInt32 i = 0; i < m_NumLevelCodes; i++)\r
+          WriteBits(m_LevelLevels[i], kLevelFieldSize);\r
+        \r
+        Huffman_ReverseBits(levelCodes, levelLens, kLevelTableSize);\r
+        LevelTableCode(m_NewLevels.litLenLevels, m_NumLitLenLevels, levelLens, levelCodes);\r
+        LevelTableCode(m_NewLevels.distLevels, m_NumDistLevels, levelLens, levelCodes);\r
+      }\r
+      WriteBlock();\r
+    }\r
+    m_AdditionalOffset -= t.BlockSizeRes;\r
+  }\r
+}\r
+\r
+SRes Read(void *object, void *data, size_t *size)\r
+{\r
+  const UInt32 kStepSize = (UInt32)1 << 31;\r
+  UInt32 curSize = ((*size < kStepSize) ? (UInt32)*size : kStepSize);\r
+  HRESULT res = ((CSeqInStream *)object)->RealStream->Read(data, curSize, &curSize);\r
+  *size = curSize;\r
+  return (SRes)res;\r
+}\r
+\r
+HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 * /* inSize */ , const UInt64 * /* outSize */ , ICompressProgressInfo *progress)\r
+{\r
+  m_CheckStatic = (m_NumPasses != 1 || m_NumDivPasses != 1);\r
+  m_IsMultiPass = (m_CheckStatic || (m_NumPasses != 1 || m_NumDivPasses != 1));\r
+\r
+  RINOK(Create());\r
+\r
+  m_ValueBlockSize = (7 << 10) + (1 << 12) * m_NumDivPasses;\r
+\r
+  UInt64 nowPos = 0;\r
+\r
+  _seqInStream.RealStream = inStream;\r
+  _seqInStream.SeqInStream.Read = Read;\r
+  _lzInWindow.stream = &_seqInStream.SeqInStream;\r
+\r
+  MatchFinder_Init(&_lzInWindow);\r
+  m_OutStream.SetStream(outStream);\r
+  m_OutStream.Init();\r
+\r
+  CCoderReleaser coderReleaser(this);\r
+\r
+  m_OptimumEndIndex = m_OptimumCurrentIndex = 0;\r
+\r
+  CTables &t = m_Tables[1];\r
+  t.m_Pos = 0;\r
+  t.InitStructures();\r
+\r
+  m_AdditionalOffset = 0;\r
+  do\r
+  {\r
+    t.BlockSizeRes = kBlockUncompressedSizeThreshold;\r
+    m_SecondPass = false;\r
+    GetBlockPrice(1, m_NumDivPasses);\r
+    CodeBlock(1, Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) == 0);\r
+    nowPos += m_Tables[1].BlockSizeRes;\r
+    if (progress != NULL)\r
+    {\r
+      UInt64 packSize = m_OutStream.GetProcessedSize();\r
+      RINOK(progress->SetRatioInfo(&nowPos, &packSize));\r
+    }\r
+  }\r
+  while (Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) != 0);\r
+  if (_lzInWindow.result != SZ_OK)\r
+    return _lzInWindow.result;\r
+  return m_OutStream.Flush();\r
+}\r
+\r
+HRESULT CCoder::BaseCode(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  try { return CodeReal(inStream, outStream, inSize, outSize, progress); }\r
+  catch(const COutBufferException &e) { return e.ErrorCode; }\r
+  catch(...) { return E_FAIL; }\r
+}\r
+\r
+STDMETHODIMP CCOMCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+  { return BaseCode(inStream, outStream, inSize, outSize, progress); }\r
+\r
+STDMETHODIMP CCOMCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)\r
+  { return BaseSetEncoderProperties2(propIDs, props, numProps); }\r
+\r
+STDMETHODIMP CCOMCoder64::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+  { return BaseCode(inStream, outStream, inSize, outSize, progress); }\r
+\r
+STDMETHODIMP CCOMCoder64::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)\r
+  { return BaseSetEncoderProperties2(propIDs, props, numProps); }\r
+\r
+}}}\r
diff --git a/CPP/7zip/Compress/DeflateEncoder.h b/CPP/7zip/Compress/DeflateEncoder.h
new file mode 100755 (executable)
index 0000000..7ad262b
--- /dev/null
@@ -0,0 +1,211 @@
+// DeflateEncoder.h\r
+\r
+#ifndef __DEFLATE_ENCODER_H\r
+#define __DEFLATE_ENCODER_H\r
+\r
+#include "../../../C/LzFind.h"\r
+\r
+#include "Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "BitlEncoder.h"\r
+#include "DeflateConst.h"\r
+\r
+namespace NCompress {\r
+namespace NDeflate {\r
+namespace NEncoder {\r
+\r
+struct CCodeValue\r
+{\r
+  UInt16 Len;\r
+  UInt16 Pos;\r
+  void SetAsLiteral() { Len = (1 << 15); }\r
+  bool IsLiteral() const { return (Len >= (1 << 15)); }\r
+};\r
+\r
+struct COptimal\r
+{\r
+  UInt32 Price;\r
+  UInt16 PosPrev;\r
+  UInt16 BackPrev;\r
+};\r
+\r
+const UInt32 kNumOptsBase = 1 << 12;\r
+const UInt32 kNumOpts = kNumOptsBase + kMatchMaxLen;\r
+\r
+class CCoder;\r
+\r
+struct CTables: public CLevels\r
+{\r
+  bool UseSubBlocks;\r
+  bool StoreMode;\r
+  bool StaticMode;\r
+  UInt32 BlockSizeRes;\r
+  UInt32 m_Pos;\r
+  void InitStructures();\r
+};\r
+\r
+typedef struct _CSeqInStream\r
+{\r
+  ISeqInStream SeqInStream;\r
+  CMyComPtr<ISequentialInStream> RealStream;\r
+} CSeqInStream;\r
+\r
+class CCoder\r
+{\r
+  CMatchFinder _lzInWindow;\r
+  CBitlEncoder m_OutStream;\r
+\r
+  CSeqInStream _seqInStream;\r
+\r
+public:\r
+  CCodeValue *m_Values;\r
+\r
+  UInt16 *m_MatchDistances;\r
+  UInt32 m_NumFastBytes;\r
+  bool _fastMode;\r
+  bool _btMode;\r
+\r
+  UInt16 *m_OnePosMatchesMemory;\r
+  UInt16 *m_DistanceMemory;\r
+\r
+  UInt32 m_Pos;\r
+\r
+  int m_NumPasses;\r
+  int m_NumDivPasses;\r
+  bool m_CheckStatic;\r
+  bool m_IsMultiPass;\r
+  UInt32 m_ValueBlockSize;\r
+\r
+  UInt32 m_NumLenCombinations;\r
+  UInt32 m_MatchMaxLen;\r
+  const Byte *m_LenStart;\r
+  const Byte *m_LenDirectBits;\r
+\r
+  bool m_Created;\r
+  bool m_Deflate64Mode;\r
+\r
+  Byte m_LevelLevels[kLevelTableSize];\r
+  int m_NumLitLenLevels;\r
+  int m_NumDistLevels;\r
+  UInt32 m_NumLevelCodes;\r
+  UInt32 m_ValueIndex;\r
+\r
+  bool m_SecondPass;\r
+  UInt32 m_AdditionalOffset;\r
+\r
+  UInt32 m_OptimumEndIndex;\r
+  UInt32 m_OptimumCurrentIndex;\r
+  \r
+  Byte  m_LiteralPrices[256];\r
+  Byte  m_LenPrices[kNumLenSymbolsMax];\r
+  Byte  m_PosPrices[kDistTableSize64];\r
+\r
+  CLevels m_NewLevels;\r
+  UInt32 mainFreqs[kFixedMainTableSize];\r
+  UInt32 distFreqs[kDistTableSize64];\r
+  UInt32 mainCodes[kFixedMainTableSize];\r
+  UInt32 distCodes[kDistTableSize64];\r
+  UInt32 levelCodes[kLevelTableSize];\r
+  Byte levelLens[kLevelTableSize];\r
+\r
+  UInt32 BlockSizeRes;\r
+\r
+  CTables *m_Tables;\r
+  COptimal m_Optimum[kNumOpts];\r
+\r
+  UInt32 m_MatchFinderCycles;\r
+  // IMatchFinderSetNumPasses *m_SetMfPasses;\r
+\r
+  void GetMatches();\r
+  void MovePos(UInt32 num);\r
+  UInt32 Backward(UInt32 &backRes, UInt32 cur);\r
+  UInt32 GetOptimal(UInt32 &backRes);\r
+  UInt32 GetOptimalFast(UInt32 &backRes);\r
+\r
+  void LevelTableDummy(const Byte *levels, int numLevels, UInt32 *freqs);\r
+\r
+  void WriteBits(UInt32 value, int numBits);\r
+  void LevelTableCode(const Byte *levels, int numLevels, const Byte *lens, const UInt32 *codes);\r
+\r
+  void MakeTables(unsigned maxHuffLen);\r
+  UInt32 GetLzBlockPrice() const;\r
+  void TryBlock();\r
+  UInt32 TryDynBlock(int tableIndex, UInt32 numPasses);\r
+\r
+  UInt32 TryFixedBlock(int tableIndex);\r
+\r
+  void SetPrices(const CLevels &levels);\r
+  void WriteBlock();\r
+\r
+  HRESULT Create();\r
+  void Free();\r
+\r
+  void WriteStoreBlock(UInt32 blockSize, UInt32 additionalOffset, bool finalBlock);\r
+  void WriteTables(bool writeMode, bool finalBlock);\r
+  \r
+  void WriteBlockData(bool writeMode, bool finalBlock);\r
+\r
+  void ReleaseStreams()\r
+  {\r
+    _seqInStream.RealStream.Release();\r
+    m_OutStream.ReleaseStream();\r
+  }\r
+  class CCoderReleaser\r
+  {\r
+    CCoder *m_Coder;\r
+  public:\r
+    CCoderReleaser(CCoder *coder): m_Coder(coder) {}\r
+    ~CCoderReleaser() { m_Coder->ReleaseStreams(); }\r
+  };\r
+  friend class CCoderReleaser;\r
+\r
+  UInt32 GetBlockPrice(int tableIndex, int numDivPasses);\r
+  void CodeBlock(int tableIndex, bool finalBlock);\r
+\r
+public:\r
+  CCoder(bool deflate64Mode = false);\r
+  ~CCoder();\r
+\r
+  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+  HRESULT BaseCode(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+  HRESULT BaseSetEncoderProperties2(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);\r
+};\r
+\r
+\r
+class CCOMCoder :\r
+  public ICompressCoder,\r
+  public ICompressSetCoderProperties,\r
+  public CMyUnknownImp,\r
+  public CCoder\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP1(ICompressSetCoderProperties)\r
+  CCOMCoder(): CCoder(false) {};\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);\r
+};\r
+\r
+class CCOMCoder64 :\r
+  public ICompressCoder,\r
+  public ICompressSetCoderProperties,\r
+  public CMyUnknownImp,\r
+  public CCoder\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP1(ICompressSetCoderProperties)\r
+  CCOMCoder64(): CCoder(true) {};\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);\r
+};\r
+\r
+}}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/DeflateRegister.cpp b/CPP/7zip/Compress/DeflateRegister.cpp
new file mode 100755 (executable)
index 0000000..d8a9c8d
--- /dev/null
@@ -0,0 +1,21 @@
+// DeflateRegister.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../Common/RegisterCodec.h"\r
+\r
+#include "DeflateDecoder.h"\r
+\r
+static void *CreateCodecDeflate() { return (void *)(ICompressCoder *)(new NCompress::NDeflate::NDecoder::CCOMCoder); }\r
+\r
+#if !defined(EXTRACT_ONLY) && !defined(DEFLATE_EXTRACT_ONLY)\r
+#include "DeflateEncoder.h"\r
+static void *CreateCodecOutDeflate() { return (void *)(ICompressCoder *)(new NCompress::NDeflate::NEncoder::CCOMCoder);  }\r
+#else\r
+#define CreateCodecOutDeflate 0\r
+#endif\r
+\r
+static CCodecInfo g_CodecInfo =\r
+  { CreateCodecDeflate,   CreateCodecOutDeflate,   0x040108, L"Deflate", 1, false };\r
+\r
+REGISTER_CODEC(Deflate)\r
diff --git a/CPP/7zip/Compress/DeltaFilter.cpp b/CPP/7zip/Compress/DeltaFilter.cpp
new file mode 100755 (executable)
index 0000000..e7e3822
--- /dev/null
@@ -0,0 +1,112 @@
+// DeltaFilter.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Delta.h"\r
+\r
+#include "../Common/RegisterCodec.h"\r
+\r
+#include "BranchCoder.h"\r
+\r
+struct CDelta\r
+{\r
+  unsigned _delta;\r
+  Byte _state[DELTA_STATE_SIZE];\r
+  CDelta(): _delta(1) {}\r
+  void DeltaInit() { Delta_Init(_state); }\r
+};\r
+\r
+class CDeltaEncoder:\r
+  public ICompressFilter,\r
+  public ICompressSetCoderProperties,\r
+  public ICompressWriteCoderProperties,\r
+  CDelta,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties)\r
+  STDMETHOD(Init)();\r
+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);\r
+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);\r
+  STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);\r
+};\r
+\r
+class CDeltaDecoder:\r
+  public ICompressFilter,\r
+  public ICompressSetDecoderProperties2,\r
+  CDelta,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)\r
+  STDMETHOD(Init)();\r
+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);\r
+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);\r
+};\r
+\r
+STDMETHODIMP CDeltaEncoder::Init()\r
+{\r
+  DeltaInit();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP_(UInt32) CDeltaEncoder::Filter(Byte *data, UInt32 size)\r
+{\r
+  Delta_Encode(_state, _delta, data, size);\r
+  return size;\r
+}\r
+\r
+STDMETHODIMP CDeltaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)\r
+{\r
+  UInt32 delta = _delta;\r
+  for (UInt32 i = 0; i < numProps; i++)\r
+  {\r
+    const PROPVARIANT &prop = props[i];\r
+    if (propIDs[i] != NCoderPropID::kDefaultProp || prop.vt != VT_UI4 || prop.ulVal < 1 || prop.ulVal > 256)\r
+      return E_INVALIDARG;\r
+    delta = prop.ulVal;\r
+  }\r
+  _delta = delta;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CDeltaEncoder::WriteCoderProperties(ISequentialOutStream *outStream)\r
+{\r
+  Byte prop = (Byte)(_delta - 1);\r
+  return outStream->Write(&prop, 1, NULL);\r
+}\r
+\r
+STDMETHODIMP CDeltaDecoder::Init()\r
+{\r
+  DeltaInit();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP_(UInt32) CDeltaDecoder::Filter(Byte *data, UInt32 size)\r
+{\r
+  Delta_Decode(_state, _delta, data, size);\r
+  return size;\r
+}\r
+\r
+STDMETHODIMP CDeltaDecoder::SetDecoderProperties2(const Byte *props, UInt32 size)\r
+{\r
+  if (size != 1)\r
+    return E_INVALIDARG;\r
+  _delta = (unsigned)props[0] + 1;\r
+  return S_OK;\r
+}\r
+\r
+#define CREATE_CODEC(x) \\r
+  static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## Decoder); } \\r
+  static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## Encoder); }\r
+\r
+CREATE_CODEC(Delta)\r
+\r
+#define METHOD_ITEM(x, id, name) { CreateCodec ## x, CreateCodec ## x ## Out, id, name, 1, true  }\r
+\r
+static CCodecInfo g_CodecsInfo[] =\r
+{\r
+  METHOD_ITEM(Delta, 3, L"Delta")\r
+};\r
+\r
+REGISTER_CODECS(Delta)\r
diff --git a/CPP/7zip/Compress/DllExports.cpp b/CPP/7zip/Compress/DllExports.cpp
new file mode 100755 (executable)
index 0000000..9b04f89
--- /dev/null
@@ -0,0 +1,45 @@
+// DllExports.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/MyInitGuid.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "../Common/RegisterCodec.h"\r
+\r
+static const unsigned int kNumCodecsMax = 32;\r
+unsigned int g_NumCodecs = 0;\r
+const CCodecInfo *g_Codecs[kNumCodecsMax];\r
+void RegisterCodec(const CCodecInfo *codecInfo)\r
+{\r
+  if (g_NumCodecs < kNumCodecsMax)\r
+    g_Codecs[g_NumCodecs++] = codecInfo;\r
+}\r
+\r
+#ifdef _WIN32\r
+extern "C"\r
+BOOL WINAPI DllMain(\r
+  #ifdef UNDER_CE\r
+  HANDLE\r
+  #else\r
+  HINSTANCE\r
+  #endif\r
+  , DWORD /* dwReason */, LPVOID /*lpReserved*/)\r
+{\r
+  return TRUE;\r
+}\r
+#endif\r
+\r
+static const UInt16 kDecodeId = 0x2790;\r
+\r
+DEFINE_GUID(CLSID_CCodec,\r
+0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);\r
+\r
+STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject);\r
+\r
+STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)\r
+{\r
+  return CreateCoder(clsid, iid, outObject);\r
+}\r
+\r
diff --git a/CPP/7zip/Compress/DllExports2.cpp b/CPP/7zip/Compress/DllExports2.cpp
new file mode 100755 (executable)
index 0000000..774b582
--- /dev/null
@@ -0,0 +1,28 @@
+// DllExports.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/MyInitGuid.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "../Common/RegisterCodec.h"\r
+\r
+extern "C"\r
+BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /*lpReserved*/)\r
+{\r
+  return TRUE;\r
+}\r
+\r
+static const UInt16 kDecodeId = 0x2790;\r
+\r
+DEFINE_GUID(CLSID_CCodec,\r
+0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);\r
+\r
+STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject);\r
+\r
+STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)\r
+{\r
+  return CreateCoder(clsid, iid, outObject);\r
+}\r
+\r
diff --git a/CPP/7zip/Compress/HuffmanDecoder.h b/CPP/7zip/Compress/HuffmanDecoder.h
new file mode 100755 (executable)
index 0000000..f71a582
--- /dev/null
@@ -0,0 +1,89 @@
+// Compress/HuffmanDecoder.h\r
+\r
+#ifndef __COMPRESS_HUFFMAN_DECODER_H\r
+#define __COMPRESS_HUFFMAN_DECODER_H\r
+\r
+#include "../../Common/Types.h"\r
+\r
+namespace NCompress {\r
+namespace NHuffman {\r
+\r
+const int kNumTableBits = 9;\r
+\r
+template <int kNumBitsMax, UInt32 m_NumSymbols>\r
+class CDecoder\r
+{\r
+  UInt32 m_Limits[kNumBitsMax + 1];     // m_Limits[i] = value limit for symbols with length = i\r
+  UInt32 m_Positions[kNumBitsMax + 1];  // m_Positions[i] = index in m_Symbols[] of first symbol with length = i\r
+  UInt32 m_Symbols[m_NumSymbols];\r
+  Byte m_Lengths[1 << kNumTableBits];   // Table oh length for short codes.\r
+\r
+public:\r
+  \r
+  bool SetCodeLengths(const Byte *codeLengths)\r
+  {\r
+    int lenCounts[kNumBitsMax + 1];\r
+    UInt32 tmpPositions[kNumBitsMax + 1];\r
+    int i;\r
+    for(i = 1; i <= kNumBitsMax; i++)\r
+      lenCounts[i] = 0;\r
+    UInt32 symbol;\r
+    for (symbol = 0; symbol < m_NumSymbols; symbol++)\r
+    {\r
+      int len = codeLengths[symbol];\r
+      if (len > kNumBitsMax)\r
+        return false;\r
+      lenCounts[len]++;\r
+      m_Symbols[symbol] = 0xFFFFFFFF;\r
+    }\r
+    lenCounts[0] = 0;\r
+    m_Positions[0] = m_Limits[0] = 0;\r
+    UInt32 startPos = 0;\r
+    UInt32 index = 0;\r
+    const UInt32 kMaxValue = (1 << kNumBitsMax);\r
+    for (i = 1; i <= kNumBitsMax; i++)\r
+    {\r
+      startPos += lenCounts[i] << (kNumBitsMax - i);\r
+      if (startPos > kMaxValue)\r
+        return false;\r
+      m_Limits[i] = (i == kNumBitsMax) ? kMaxValue : startPos;\r
+      m_Positions[i] = m_Positions[i - 1] + lenCounts[i - 1];\r
+      tmpPositions[i] = m_Positions[i];\r
+      if(i <= kNumTableBits)\r
+      {\r
+        UInt32 limit = (m_Limits[i] >> (kNumBitsMax - kNumTableBits));\r
+        for (; index < limit; index++)\r
+          m_Lengths[index] = (Byte)i;\r
+      }\r
+    }\r
+    for (symbol = 0; symbol < m_NumSymbols; symbol++)\r
+    {\r
+      int len = codeLengths[symbol];\r
+      if (len != 0)\r
+        m_Symbols[tmpPositions[len]++] = symbol;\r
+    }\r
+    return true;\r
+  }\r
+\r
+  template <class TBitDecoder>\r
+  UInt32 DecodeSymbol(TBitDecoder *bitStream)\r
+  {\r
+    int numBits;\r
+    UInt32 value = bitStream->GetValue(kNumBitsMax);\r
+    if (value < m_Limits[kNumTableBits])\r
+      numBits = m_Lengths[value >> (kNumBitsMax - kNumTableBits)];\r
+    else\r
+      for (numBits = kNumTableBits + 1; value >= m_Limits[numBits]; numBits++);\r
+    bitStream->MovePos(numBits);\r
+    UInt32 index = m_Positions[numBits] +\r
+      ((value - m_Limits[numBits - 1]) >> (kNumBitsMax - numBits));\r
+    if (index >= m_NumSymbols)\r
+      // throw CDecoderException(); // test it\r
+      return 0xFFFFFFFF;\r
+    return m_Symbols[index];\r
+  }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/ImplodeDecoder.cpp b/CPP/7zip/Compress/ImplodeDecoder.cpp
new file mode 100755 (executable)
index 0000000..6c5e362
--- /dev/null
@@ -0,0 +1,219 @@
+// Implode/Decoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "ImplodeDecoder.h"\r
+#include "Common/Defs.h"\r
+\r
+namespace NCompress {\r
+namespace NImplode {\r
+namespace NDecoder {\r
+\r
+class CException\r
+{\r
+public:\r
+  enum ECauseType\r
+  {\r
+    kData\r
+  } m_Cause;\r
+  CException(ECauseType cause): m_Cause(cause) {}\r
+};\r
+\r
+static const int kNumDistanceLowDirectBitsForBigDict = 7;\r
+static const int kNumDistanceLowDirectBitsForSmallDict = 6;\r
+\r
+static const int kNumBitsInByte = 8;\r
+\r
+// static const int kLevelStructuresNumberFieldSize = kNumBitsInByte;\r
+static const int kLevelStructuresNumberAdditionalValue = 1;\r
+\r
+static const int kNumLevelStructureLevelBits = 4;\r
+static const int kLevelStructureLevelAdditionalValue = 1;\r
+\r
+static const int kNumLevelStructureRepNumberBits = 4;\r
+static const int kLevelStructureRepNumberAdditionalValue = 1;\r
+\r
+\r
+static const int kLiteralTableSize = (1 << kNumBitsInByte);\r
+static const int kDistanceTableSize = 64;\r
+static const int kLengthTableSize = 64;\r
+\r
+static const UInt32 kHistorySize =\r
+    (1 << MyMax(kNumDistanceLowDirectBitsForBigDict,\r
+                kNumDistanceLowDirectBitsForSmallDict)) *\r
+    kDistanceTableSize; // = 8 KB;\r
+\r
+static const int kNumAdditionalLengthBits = 8;\r
+\r
+static const UInt32 kMatchMinLenWhenLiteralsOn = 3;\r
+static const UInt32 kMatchMinLenWhenLiteralsOff = 2;\r
+\r
+static const UInt32 kMatchMinLenMax = MyMax(kMatchMinLenWhenLiteralsOn,\r
+    kMatchMinLenWhenLiteralsOff);  // 3\r
+\r
+// static const UInt32 kMatchMaxLenMax = kMatchMinLenMax + (kLengthTableSize - 1) + (1 << kNumAdditionalLengthBits) - 1;  // or 2\r
+\r
+enum\r
+{\r
+  kMatchId = 0,\r
+  kLiteralId = 1\r
+};\r
+\r
+\r
+CCoder::CCoder():\r
+  m_LiteralDecoder(kLiteralTableSize),\r
+  m_LengthDecoder(kLengthTableSize),\r
+  m_DistanceDecoder(kDistanceTableSize)\r
+{\r
+}\r
+\r
+void CCoder::ReleaseStreams()\r
+{\r
+  m_OutWindowStream.ReleaseStream();\r
+  m_InBitStream.ReleaseStream();\r
+}\r
+\r
+bool CCoder::ReadLevelItems(NImplode::NHuffman::CDecoder &decoder,\r
+    Byte *levels, int numLevelItems)\r
+{\r
+  int numCodedStructures = m_InBitStream.ReadBits(kNumBitsInByte) +\r
+      kLevelStructuresNumberAdditionalValue;\r
+  int currentIndex = 0;\r
+  for(int i = 0; i < numCodedStructures; i++)\r
+  {\r
+    int level = m_InBitStream.ReadBits(kNumLevelStructureLevelBits) +\r
+      kLevelStructureLevelAdditionalValue;\r
+    int rep = m_InBitStream.ReadBits(kNumLevelStructureRepNumberBits) +\r
+      kLevelStructureRepNumberAdditionalValue;\r
+    if (currentIndex + rep > numLevelItems)\r
+      throw CException(CException::kData);\r
+    for(int j = 0; j < rep; j++)\r
+      levels[currentIndex++] = (Byte)level;\r
+  }\r
+  if (currentIndex != numLevelItems)\r
+    return false;\r
+  return decoder.SetCodeLengths(levels);\r
+}\r
+\r
+\r
+bool CCoder::ReadTables(void)\r
+{\r
+  if (m_LiteralsOn)\r
+  {\r
+    Byte literalLevels[kLiteralTableSize];\r
+    if (!ReadLevelItems(m_LiteralDecoder, literalLevels, kLiteralTableSize))\r
+      return false;\r
+  }\r
+\r
+  Byte lengthLevels[kLengthTableSize];\r
+  if (!ReadLevelItems(m_LengthDecoder, lengthLevels, kLengthTableSize))\r
+    return false;\r
+\r
+  Byte distanceLevels[kDistanceTableSize];\r
+  return ReadLevelItems(m_DistanceDecoder, distanceLevels, kDistanceTableSize);\r
+}\r
+\r
+class CCoderReleaser\r
+{\r
+  CCoder *m_Coder;\r
+public:\r
+  CCoderReleaser(CCoder *coder): m_Coder(coder) {}\r
+  ~CCoderReleaser() { m_Coder->ReleaseStreams(); }\r
+};\r
+\r
+HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  if (!m_InBitStream.Create(1 << 20))\r
+    return E_OUTOFMEMORY;\r
+  if (!m_OutWindowStream.Create(kHistorySize))\r
+    return E_OUTOFMEMORY;\r
+  if (outSize == NULL)\r
+    return E_INVALIDARG;\r
+  UInt64 pos = 0, unPackSize = *outSize;\r
+\r
+  m_OutWindowStream.SetStream(outStream);\r
+  m_OutWindowStream.Init(false);\r
+  m_InBitStream.SetStream(inStream);\r
+  m_InBitStream.Init();\r
+  CCoderReleaser coderReleaser(this);\r
+\r
+  if (!ReadTables())\r
+    return S_FALSE;\r
+  \r
+  while(pos < unPackSize)\r
+  {\r
+    if (progress != NULL && pos % (1 << 16) == 0)\r
+    {\r
+      UInt64 packSize = m_InBitStream.GetProcessedSize();\r
+      RINOK(progress->SetRatioInfo(&packSize, &pos));\r
+    }\r
+    if(m_InBitStream.ReadBits(1) == kMatchId) // match\r
+    {\r
+      UInt32 lowDistBits = m_InBitStream.ReadBits(m_NumDistanceLowDirectBits);\r
+      UInt32 distance = m_DistanceDecoder.DecodeSymbol(&m_InBitStream);\r
+      if (distance >= kDistanceTableSize)\r
+        return S_FALSE;\r
+      distance = (distance << m_NumDistanceLowDirectBits) + lowDistBits;\r
+      UInt32 lengthSymbol = m_LengthDecoder.DecodeSymbol(&m_InBitStream);\r
+      if (lengthSymbol >= kLengthTableSize)\r
+        return S_FALSE;\r
+      UInt32 length = lengthSymbol + m_MinMatchLength;\r
+      if (lengthSymbol == kLengthTableSize - 1) // special symbol  = 63\r
+        length += m_InBitStream.ReadBits(kNumAdditionalLengthBits);\r
+      while(distance >= pos && length > 0)\r
+      {\r
+        m_OutWindowStream.PutByte(0);\r
+        pos++;\r
+        length--;\r
+      }\r
+      if (length > 0)\r
+        m_OutWindowStream.CopyBlock(distance, length);\r
+      pos += length;\r
+    }\r
+    else\r
+    {\r
+      Byte b;\r
+      if (m_LiteralsOn)\r
+      {\r
+        UInt32 temp = m_LiteralDecoder.DecodeSymbol(&m_InBitStream);\r
+        if (temp >= kLiteralTableSize)\r
+          return S_FALSE;\r
+        b = (Byte)temp;\r
+      }\r
+      else\r
+        b = (Byte)m_InBitStream.ReadBits(kNumBitsInByte);\r
+      m_OutWindowStream.PutByte(b);\r
+      pos++;\r
+    }\r
+  }\r
+  if (pos > unPackSize)\r
+    return S_FALSE;\r
+  return m_OutWindowStream.Flush();\r
+}\r
+\r
+STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  try { return CodeReal(inStream, outStream, inSize, outSize, progress);  }\r
+  catch(const CLzOutWindowException &e) { return e.ErrorCode; }\r
+  catch(...) { return S_FALSE; }\r
+}\r
+\r
+STDMETHODIMP CCoder::SetDecoderProperties2(const Byte *data, UInt32 size)\r
+{\r
+  if (size < 1)\r
+    return E_INVALIDARG;\r
+  Byte flag = data[0];\r
+  m_BigDictionaryOn = ((flag & 2) != 0);\r
+  m_NumDistanceLowDirectBits = m_BigDictionaryOn ?\r
+      kNumDistanceLowDirectBitsForBigDict:\r
+      kNumDistanceLowDirectBitsForSmallDict;\r
+  m_LiteralsOn = ((flag & 4) != 0);\r
+  m_MinMatchLength = m_LiteralsOn ?\r
+      kMatchMinLenWhenLiteralsOn :\r
+      kMatchMinLenWhenLiteralsOff;\r
+  return S_OK;\r
+}\r
+\r
+}}}\r
diff --git a/CPP/7zip/Compress/ImplodeDecoder.h b/CPP/7zip/Compress/ImplodeDecoder.h
new file mode 100755 (executable)
index 0000000..2b45f05
--- /dev/null
@@ -0,0 +1,57 @@
+// ImplodeDecoder.h\r
+\r
+#ifndef __COMPRESS_IMPLODE_DECODER_H\r
+#define __COMPRESS_IMPLODE_DECODER_H\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "ImplodeHuffmanDecoder.h"\r
+#include "LzOutWindow.h"\r
+\r
+namespace NCompress {\r
+namespace NImplode {\r
+namespace NDecoder {\r
+\r
+class CCoder:\r
+  public ICompressCoder,\r
+  public ICompressSetDecoderProperties2,\r
+  public CMyUnknownImp\r
+{\r
+  CLzOutWindow m_OutWindowStream;\r
+  NBitl::CDecoder<CInBuffer> m_InBitStream;\r
+  \r
+  NImplode::NHuffman::CDecoder m_LiteralDecoder;\r
+  NImplode::NHuffman::CDecoder m_LengthDecoder;\r
+  NImplode::NHuffman::CDecoder m_DistanceDecoder;\r
+\r
+  bool m_BigDictionaryOn;\r
+  bool m_LiteralsOn;\r
+\r
+  int m_NumDistanceLowDirectBits;\r
+  UInt32 m_MinMatchLength;\r
+\r
+  bool ReadLevelItems(NImplode::NHuffman::CDecoder &table, Byte *levels, int numLevelItems);\r
+  bool ReadTables();\r
+  void DeCodeLevelTable(Byte *newLevels, int numLevels);\r
+public:\r
+  CCoder();\r
+\r
+  MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)\r
+\r
+  void ReleaseStreams();\r
+  HRESULT Flush() { return m_OutWindowStream.Flush(); }\r
+\r
+  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);\r
+};\r
+\r
+}}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp b/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp
new file mode 100755 (executable)
index 0000000..c7a1634
--- /dev/null
@@ -0,0 +1,89 @@
+// ImplodeHuffmanDecoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "ImplodeHuffmanDecoder.h"\r
+\r
+namespace NCompress {\r
+namespace NImplode {\r
+namespace NHuffman {\r
+\r
+CDecoder::CDecoder(UInt32 numSymbols):\r
+  m_NumSymbols(numSymbols)\r
+{\r
+  m_Symbols = new UInt32[m_NumSymbols];\r
+}\r
+\r
+CDecoder::~CDecoder()\r
+{\r
+  delete []m_Symbols;\r
+}\r
+\r
+bool CDecoder::SetCodeLengths(const Byte *codeLengths)\r
+{\r
+  // int lenCounts[kNumBitsInLongestCode + 1], tmpPositions[kNumBitsInLongestCode + 1];\r
+  int lenCounts[kNumBitsInLongestCode + 2], tmpPositions[kNumBitsInLongestCode + 1];\r
+  int i;\r
+  for(i = 0; i <= kNumBitsInLongestCode; i++)\r
+    lenCounts[i] = 0;\r
+  UInt32 symbolIndex;\r
+  for (symbolIndex = 0; symbolIndex < m_NumSymbols; symbolIndex++)\r
+    lenCounts[codeLengths[symbolIndex]]++;\r
+  // lenCounts[0] = 0;\r
+  \r
+  // tmpPositions[0] = m_Positions[0] = m_Limitits[0] = 0;\r
+  m_Limitits[kNumBitsInLongestCode + 1] = 0;\r
+  m_Positions[kNumBitsInLongestCode + 1] = 0;\r
+  lenCounts[kNumBitsInLongestCode + 1] =  0;\r
+\r
+\r
+  UInt32 startPos = 0;\r
+  static const UInt32 kMaxValue = (1 << kNumBitsInLongestCode);\r
+\r
+  for (i = kNumBitsInLongestCode; i > 0; i--)\r
+  {\r
+    startPos += lenCounts[i] << (kNumBitsInLongestCode - i);\r
+    if (startPos > kMaxValue)\r
+      return false;\r
+    m_Limitits[i] = startPos;\r
+    m_Positions[i] = m_Positions[i + 1] + lenCounts[i + 1];\r
+    tmpPositions[i] = m_Positions[i] + lenCounts[i];\r
+\r
+  }\r
+\r
+  // if _ZIP_MODE do not throw exception for trees containing only one node\r
+  // #ifndef _ZIP_MODE\r
+  if (startPos != kMaxValue)\r
+    return false;\r
+  // #endif\r
+\r
+  for (symbolIndex = 0; symbolIndex < m_NumSymbols; symbolIndex++)\r
+    if (codeLengths[symbolIndex] != 0)\r
+      m_Symbols[--tmpPositions[codeLengths[symbolIndex]]] = symbolIndex;\r
+  return true;\r
+}\r
+\r
+UInt32 CDecoder::DecodeSymbol(CInBit *inStream)\r
+{\r
+  UInt32 numBits = 0;\r
+  UInt32 value = inStream->GetValue(kNumBitsInLongestCode);\r
+  int i;\r
+  for(i = kNumBitsInLongestCode; i > 0; i--)\r
+  {\r
+    if (value < m_Limitits[i])\r
+    {\r
+      numBits = i;\r
+      break;\r
+    }\r
+  }\r
+  if (i == 0)\r
+    return 0xFFFFFFFF;\r
+  inStream->MovePos(numBits);\r
+  UInt32 index = m_Positions[numBits] +\r
+      ((value - m_Limitits[numBits + 1]) >> (kNumBitsInLongestCode - numBits));\r
+  if (index >= m_NumSymbols)\r
+    return 0xFFFFFFFF;\r
+  return m_Symbols[index];\r
+}\r
+\r
+}}}\r
diff --git a/CPP/7zip/Compress/ImplodeHuffmanDecoder.h b/CPP/7zip/Compress/ImplodeHuffmanDecoder.h
new file mode 100755 (executable)
index 0000000..8936c09
--- /dev/null
@@ -0,0 +1,34 @@
+// ImplodeHuffmanDecoder.h\r
+\r
+#ifndef __IMPLODE_HUFFMAN_DECODER_H\r
+#define __IMPLODE_HUFFMAN_DECODER_H\r
+\r
+#include "../Common/InBuffer.h"\r
+\r
+#include "BitlDecoder.h"\r
+\r
+namespace NCompress {\r
+namespace NImplode {\r
+namespace NHuffman {\r
+\r
+const int kNumBitsInLongestCode = 16;\r
+\r
+typedef NBitl::CDecoder<CInBuffer> CInBit;\r
+\r
+class CDecoder\r
+{\r
+  UInt32 m_Limitits[kNumBitsInLongestCode + 2]; // m_Limitits[i] = value limit for symbols with length = i\r
+  UInt32 m_Positions[kNumBitsInLongestCode + 2];   // m_Positions[i] = index in m_Symbols[] of first symbol with length = i\r
+  UInt32 m_NumSymbols; // number of symbols in m_Symbols\r
+  UInt32 *m_Symbols; // symbols: at first with len=1 then 2, ... 15.\r
+public:\r
+  CDecoder(UInt32 numSymbols);\r
+  ~CDecoder();\r
+  \r
+  bool SetCodeLengths(const Byte *codeLengths);\r
+  UInt32 DecodeSymbol(CInBit *inStream);\r
+};\r
+\r
+}}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/LzOutWindow.cpp b/CPP/7zip/Compress/LzOutWindow.cpp
new file mode 100755 (executable)
index 0000000..b047894
--- /dev/null
@@ -0,0 +1,14 @@
+// LzOutWindow.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "LzOutWindow.h"\r
+\r
+void CLzOutWindow::Init(bool solid)\r
+{\r
+  if (!solid)\r
+    COutBuffer::Init();\r
+  #ifdef _NO_EXCEPTIONS\r
+  ErrorCode = S_OK;\r
+  #endif\r
+}\r
diff --git a/CPP/7zip/Compress/LzOutWindow.h b/CPP/7zip/Compress/LzOutWindow.h
new file mode 100755 (executable)
index 0000000..bbec7ad
--- /dev/null
@@ -0,0 +1,66 @@
+// LzOutWindow.h\r
+\r
+#ifndef __LZ_OUT_WINDOW_H\r
+#define __LZ_OUT_WINDOW_H\r
+\r
+#include "../IStream.h"\r
+\r
+#include "../Common/OutBuffer.h"\r
+\r
+#ifndef _NO_EXCEPTIONS\r
+typedef COutBufferException CLzOutWindowException;\r
+#endif\r
+\r
+class CLzOutWindow: public COutBuffer\r
+{\r
+public:\r
+  void Init(bool solid = false);\r
+  \r
+  // distance >= 0, len > 0,\r
+  bool CopyBlock(UInt32 distance, UInt32 len)\r
+  {\r
+    UInt32 pos = _pos - distance - 1;\r
+    if (distance >= _pos)\r
+    {\r
+      if (!_overDict || distance >= _bufferSize)\r
+        return false;\r
+      pos += _bufferSize;\r
+    }\r
+    if (_limitPos - _pos > len && _bufferSize - pos > len)\r
+    {\r
+      const Byte *src = _buffer + pos;\r
+      Byte *dest = _buffer + _pos;\r
+      _pos += len;\r
+      do\r
+        *dest++ = *src++;\r
+      while(--len != 0);\r
+    }\r
+    else do\r
+    {\r
+      if (pos == _bufferSize)\r
+        pos = 0;\r
+      _buffer[_pos++] = _buffer[pos++];\r
+      if (_pos == _limitPos)\r
+        FlushWithCheck();\r
+    }\r
+    while(--len != 0);\r
+    return true;\r
+  }\r
+  \r
+  void PutByte(Byte b)\r
+  {\r
+    _buffer[_pos++] = b;\r
+    if (_pos == _limitPos)\r
+      FlushWithCheck();\r
+  }\r
+  \r
+  Byte GetByte(UInt32 distance) const\r
+  {\r
+    UInt32 pos = _pos - distance - 1;\r
+    if (pos >= _bufferSize)\r
+      pos += _bufferSize;\r
+    return _buffer[pos];\r
+  }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/LzhDecoder.cpp b/CPP/7zip/Compress/LzhDecoder.cpp
new file mode 100755 (executable)
index 0000000..e1591f4
--- /dev/null
@@ -0,0 +1,220 @@
+// LzhDecoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "LzhDecoder.h"\r
+\r
+#include "Windows/Defs.h"\r
+\r
+namespace NCompress{\r
+namespace NLzh {\r
+namespace NDecoder {\r
+\r
+static const UInt32 kHistorySize = (1 << 16);\r
+\r
+static const int kBlockSizeBits = 16;\r
+static const int kNumCBits = 9;\r
+static const int kNumLevelBits = 5; // smallest integer such that (1 << kNumLevelBits) > kNumLevelSymbols/\r
+\r
+UInt32 CCoder::ReadBits(int numBits) {  return m_InBitStream.ReadBits(numBits); }\r
+\r
+HRESULT CCoder::ReadLevelTable()\r
+{\r
+  int n = ReadBits(kNumLevelBits);\r
+  if (n == 0)\r
+  {\r
+    m_LevelHuffman.Symbol = ReadBits(kNumLevelBits);\r
+    if (m_LevelHuffman.Symbol >= kNumLevelSymbols)\r
+      return S_FALSE;\r
+  }\r
+  else\r
+  {\r
+    if (n > kNumLevelSymbols)\r
+      return S_FALSE;\r
+    m_LevelHuffman.Symbol = -1;\r
+    Byte lens[kNumLevelSymbols];\r
+    int i = 0;\r
+    while (i < n)\r
+    {\r
+      int c = m_InBitStream.ReadBits(3);\r
+      if (c == 7)\r
+        while (ReadBits(1))\r
+          if (c++ > kMaxHuffmanLen)\r
+            return S_FALSE;\r
+      lens[i++] = (Byte)c;\r
+      if (i == kNumSpecLevelSymbols)\r
+      {\r
+        c = ReadBits(2);\r
+        while (--c >= 0)\r
+          lens[i++] = 0;\r
+      }\r
+    }\r
+    while (i < kNumLevelSymbols)\r
+      lens[i++] = 0;\r
+    m_LevelHuffman.SetCodeLengths(lens);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CCoder::ReadPTable(int numBits)\r
+{\r
+  int n = ReadBits(numBits);\r
+  if (n == 0)\r
+  {\r
+    m_PHuffmanDecoder.Symbol = ReadBits(numBits);\r
+    if (m_PHuffmanDecoder.Symbol >= kNumDistanceSymbols)\r
+      return S_FALSE;\r
+  }\r
+  else\r
+  {\r
+    if (n > kNumDistanceSymbols)\r
+      return S_FALSE;\r
+    m_PHuffmanDecoder.Symbol = -1;\r
+    Byte lens[kNumDistanceSymbols];\r
+    int i = 0;\r
+    while (i < n)\r
+    {\r
+      int c = m_InBitStream.ReadBits(3);\r
+      if (c == 7)\r
+        while (ReadBits(1))\r
+        {\r
+          if (c > kMaxHuffmanLen)\r
+            return S_FALSE;\r
+          c++;\r
+        }\r
+      lens[i++] = (Byte)c;\r
+    }\r
+    while (i < kNumDistanceSymbols)\r
+      lens[i++] = 0;\r
+    m_PHuffmanDecoder.SetCodeLengths(lens);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CCoder::ReadCTable()\r
+{\r
+  int n = ReadBits(kNumCBits);\r
+  if (n == 0)\r
+  {\r
+    m_CHuffmanDecoder.Symbol = ReadBits(kNumCBits);\r
+    if (m_CHuffmanDecoder.Symbol >= kNumCSymbols)\r
+      return S_FALSE;\r
+  }\r
+  else\r
+  {\r
+    if (n > kNumCSymbols)\r
+      return S_FALSE;\r
+    m_CHuffmanDecoder.Symbol = -1;\r
+    Byte lens[kNumCSymbols];\r
+    int i = 0;\r
+    while (i < n)\r
+    {\r
+      int c = m_LevelHuffman.Decode(&m_InBitStream);\r
+      if (c < kNumSpecLevelSymbols)\r
+      {\r
+        if (c == 0)\r
+          c = 1;\r
+        else if (c == 1)\r
+          c = ReadBits(4) + 3;\r
+        else\r
+          c = ReadBits(kNumCBits) + 20;\r
+        while (--c >= 0)\r
+        {\r
+          if (i > kNumCSymbols)\r
+            return S_FALSE;\r
+          lens[i++] = 0;\r
+        }\r
+      }\r
+      else\r
+        lens[i++] = (Byte)(c - 2);\r
+    }\r
+    while (i < kNumCSymbols)\r
+      lens[i++] = 0;\r
+    m_CHuffmanDecoder.SetCodeLengths(lens);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream,\r
+    ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize,\r
+    ICompressProgressInfo *progress)\r
+{\r
+  if (outSize == NULL)\r
+    return E_INVALIDARG;\r
+\r
+  if (!m_OutWindowStream.Create(kHistorySize))\r
+    return E_OUTOFMEMORY;\r
+  if (!m_InBitStream.Create(1 << 20))\r
+    return E_OUTOFMEMORY;\r
+\r
+  UInt64 pos = 0;\r
+  m_OutWindowStream.SetStream(outStream);\r
+  m_OutWindowStream.Init(false);\r
+  m_InBitStream.SetStream(inStream);\r
+  m_InBitStream.Init();\r
+  \r
+  CCoderReleaser coderReleaser(this);\r
+\r
+  int pbit;\r
+  if (m_NumDictBits <= 13)\r
+    pbit = 4;\r
+  else\r
+    pbit = 5;\r
+\r
+  UInt32 blockSize = 0;\r
+\r
+  while(pos < *outSize)\r
+  {\r
+    // for (i = 0; i < dictSize; i++) dtext[i] = 0x20;\r
+    \r
+    if (blockSize == 0)\r
+    {\r
+      if (progress != NULL)\r
+      {\r
+        UInt64 packSize = m_InBitStream.GetProcessedSize();\r
+        RINOK(progress->SetRatioInfo(&packSize, &pos));\r
+      }\r
+      blockSize = ReadBits(kBlockSizeBits);\r
+      ReadLevelTable();\r
+      ReadCTable();\r
+      RINOK(ReadPTable(pbit));\r
+    }\r
+    blockSize--;\r
+    UInt32 c = m_CHuffmanDecoder.Decode(&m_InBitStream);\r
+    if (c < 256)\r
+    {\r
+      m_OutWindowStream.PutByte((Byte)c);\r
+      pos++;\r
+    }\r
+    else if (c >= kNumCSymbols)\r
+      return S_FALSE;\r
+    else\r
+    {\r
+      // offset = (interface->method == LARC_METHOD_NUM) ? 0x100 - 2 : 0x100 - 3;\r
+      UInt32 len  = c - 256 + kMinMatch;\r
+      UInt32 distance = m_PHuffmanDecoder.Decode(&m_InBitStream);\r
+      if (distance != 0)\r
+        distance = (1 << (distance - 1)) + ReadBits(distance - 1);\r
+      if (distance >= pos)\r
+        return S_FALSE;\r
+      if (pos + len > *outSize)\r
+        len = (UInt32)(*outSize - pos);\r
+      pos += len;\r
+      m_OutWindowStream.CopyBlock(distance, len);\r
+    }\r
+  }\r
+  coderReleaser.NeedFlush = false;\r
+  return m_OutWindowStream.Flush();\r
+}\r
+\r
+STDMETHODIMP CCoder::Code(ISequentialInStream *inStream,\r
+    ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,\r
+    ICompressProgressInfo *progress)\r
+{\r
+  try { return CodeReal(inStream, outStream, inSize, outSize, progress);}\r
+  catch(const CInBufferException &e) { return e.ErrorCode; }\r
+  catch(const CLzOutWindowException &e) { return e.ErrorCode; }\r
+  catch(...) { return S_FALSE; }\r
+}\r
+\r
+}}}\r
diff --git a/CPP/7zip/Compress/LzhDecoder.h b/CPP/7zip/Compress/LzhDecoder.h
new file mode 100755 (executable)
index 0000000..3048797
--- /dev/null
@@ -0,0 +1,106 @@
+// LzhDecoder.h\r
+\r
+#ifndef __COMPRESS_LZH_DECODER_H\r
+#define __COMPRESS_LZH_DECODER_H\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "../Common/InBuffer.h"\r
+\r
+#include "BitmDecoder.h"\r
+#include "HuffmanDecoder.h"\r
+#include "LzOutWindow.h"\r
+\r
+namespace NCompress {\r
+namespace NLzh {\r
+namespace NDecoder {\r
+\r
+const int kMaxHuffmanLen = 16; // Check it\r
+\r
+const int kNumSpecLevelSymbols = 3;\r
+const int kNumLevelSymbols = kNumSpecLevelSymbols + kMaxHuffmanLen;\r
+\r
+const int kDictBitsMax = 16;\r
+const int kNumDistanceSymbols = kDictBitsMax + 1;\r
+\r
+const int kMaxMatch = 256;\r
+const int kMinMatch = 3;\r
+const int kNumCSymbols = 256 + kMaxMatch + 2 - kMinMatch;\r
+\r
+template <UInt32 m_NumSymbols>\r
+class CHuffmanDecoder:public NCompress::NHuffman::CDecoder<kMaxHuffmanLen, m_NumSymbols>\r
+{\r
+public:\r
+  int Symbol;\r
+  template <class TBitDecoder>\r
+  UInt32 Decode(TBitDecoder *bitStream)\r
+  {\r
+    if (Symbol >= 0)\r
+      return (UInt32)Symbol;\r
+    return DecodeSymbol(bitStream);\r
+  }\r
+};\r
+\r
+class CCoder :\r
+  public ICompressCoder,\r
+  public CMyUnknownImp\r
+{\r
+  CLzOutWindow m_OutWindowStream;\r
+  NBitm::CDecoder<CInBuffer> m_InBitStream;\r
+\r
+  int m_NumDictBits;\r
+\r
+  CHuffmanDecoder<kNumLevelSymbols> m_LevelHuffman;\r
+  CHuffmanDecoder<kNumDistanceSymbols> m_PHuffmanDecoder;\r
+  CHuffmanDecoder<kNumCSymbols> m_CHuffmanDecoder;\r
+\r
+  void ReleaseStreams()\r
+  {\r
+    m_OutWindowStream.ReleaseStream();\r
+    m_InBitStream.ReleaseStream();\r
+  }\r
+\r
+  class CCoderReleaser\r
+  {\r
+    CCoder *m_Coder;\r
+  public:\r
+    bool NeedFlush;\r
+    CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {}\r
+    ~CCoderReleaser()\r
+    {\r
+      if (NeedFlush)\r
+        m_Coder->m_OutWindowStream.Flush();\r
+      m_Coder->ReleaseStreams();\r
+    }\r
+  };\r
+  friend class CCoderReleaser;\r
+\r
+  void MakeTable(int nchar, Byte *bitlen, int tablebits,\r
+      UInt32 *table, int tablesize);\r
+  \r
+  UInt32 ReadBits(int numBits);\r
+  HRESULT ReadLevelTable();\r
+  HRESULT ReadPTable(int numBits);\r
+  HRESULT ReadCTable();\r
+\r
+public:\r
+  \r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(CodeReal)(ISequentialInStream *inStream,\r
+      ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,\r
+      ICompressProgressInfo *progress);\r
+\r
+  STDMETHOD(Code)(ISequentialInStream *inStream,\r
+      ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,\r
+      ICompressProgressInfo *progress);\r
+\r
+  void SetDictionary(int numDictBits) { m_NumDictBits = numDictBits; }\r
+  CCoder(): m_NumDictBits(0) {}\r
+};\r
+\r
+}}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/Lzma2Decoder.cpp b/CPP/7zip/Compress/Lzma2Decoder.cpp
new file mode 100755 (executable)
index 0000000..8d3d830
--- /dev/null
@@ -0,0 +1,189 @@
+// Lzma2Decoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "Lzma2Decoder.h"\r
+\r
+static HRESULT SResToHRESULT(SRes res)\r
+{\r
+  switch(res)\r
+  {\r
+    case SZ_OK: return S_OK;\r
+    case SZ_ERROR_MEM: return E_OUTOFMEMORY;\r
+    case SZ_ERROR_PARAM: return E_INVALIDARG;\r
+    // case SZ_ERROR_PROGRESS: return E_ABORT;\r
+    case SZ_ERROR_DATA: return S_FALSE;\r
+  }\r
+  return E_FAIL;\r
+}\r
+\r
+namespace NCompress {\r
+namespace NLzma2 {\r
+\r
+static const UInt32 kInBufSize = 1 << 20;\r
+\r
+CDecoder::CDecoder(): _inBuf(0), _outSizeDefined(false)\r
+{\r
+  Lzma2Dec_Construct(&_state);\r
+}\r
+\r
+static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }\r
+static void SzFree(void *p, void *address) { p = p; MyFree(address); }\r
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };\r
+\r
+CDecoder::~CDecoder()\r
+{\r
+  Lzma2Dec_Free(&_state, &g_Alloc);\r
+  MyFree(_inBuf);\r
+}\r
+\r
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)\r
+{\r
+  if (size != 1) return SZ_ERROR_UNSUPPORTED;\r
+  RINOK(SResToHRESULT(Lzma2Dec_Allocate(&_state, prop[0], &g_Alloc)));\r
+  if (_inBuf == 0)\r
+  {\r
+    _inBuf = (Byte *)MyAlloc(kInBufSize);\r
+    if (_inBuf == 0)\r
+      return E_OUTOFMEMORY;\r
+  }\r
+\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _inSizeProcessed; return S_OK; }\r
+STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; }\r
+STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; }\r
+\r
+STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)\r
+{\r
+  _outSizeDefined = (outSize != NULL);\r
+  if (_outSizeDefined)\r
+    _outSize = *outSize;\r
+\r
+  Lzma2Dec_Init(&_state);\r
+  \r
+  _inPos = _inSize = 0;\r
+  _inSizeProcessed = _outSizeProcessed = 0;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,\r
+    ISequentialOutStream *outStream, const UInt64 * /* inSize */,\r
+    const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  if (_inBuf == 0)\r
+    return S_FALSE;\r
+  SetOutStreamSize(outSize);\r
+\r
+  for (;;)\r
+  {\r
+    if (_inPos == _inSize)\r
+    {\r
+      _inPos = _inSize = 0;\r
+      RINOK(inStream->Read(_inBuf, kInBufSize, &_inSize));\r
+    }\r
+\r
+    SizeT dicPos = _state.decoder.dicPos;\r
+    SizeT curSize = _state.decoder.dicBufSize - dicPos;\r
+    const UInt32 kStepSize = ((UInt32)1 << 22);\r
+    if (curSize > kStepSize)\r
+      curSize = (SizeT)kStepSize;\r
+    \r
+    ELzmaFinishMode finishMode = LZMA_FINISH_ANY;\r
+    if (_outSizeDefined)\r
+    {\r
+      const UInt64 rem = _outSize - _outSizeProcessed;\r
+      if (rem < curSize)\r
+      {\r
+        curSize = (SizeT)rem;\r
+        /*\r
+        // finishMode = LZMA_FINISH_END;\r
+        we can't use LZMA_FINISH_END here to allow partial decoding\r
+        */\r
+      }\r
+    }\r
+\r
+    SizeT inSizeProcessed = _inSize - _inPos;\r
+    ELzmaStatus status;\r
+    SRes res = Lzma2Dec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status);\r
+\r
+    _inPos += (UInt32)inSizeProcessed;\r
+    _inSizeProcessed += inSizeProcessed;\r
+    SizeT outSizeProcessed = _state.decoder.dicPos - dicPos;\r
+    _outSizeProcessed += outSizeProcessed;\r
+\r
+    bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0);\r
+    bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize);\r
+\r
+    if (res != 0 || _state.decoder.dicPos == _state.decoder.dicBufSize || finished || stopDecoding)\r
+    {\r
+      HRESULT res2 = WriteStream(outStream, _state.decoder.dic, _state.decoder.dicPos);\r
+      if (res != 0)\r
+        return S_FALSE;\r
+      RINOK(res2);\r
+      if (stopDecoding)\r
+        return S_OK;\r
+      if (finished)\r
+        return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE);\r
+    }\r
+    if (_state.decoder.dicPos == _state.decoder.dicBufSize)\r
+      _state.decoder.dicPos = 0;\r
+\r
+    if (progress != NULL)\r
+    {\r
+      RINOK(progress->SetRatioInfo(&_inSizeProcessed, &_outSizeProcessed));\r
+    }\r
+  }\r
+}\r
+\r
+#ifndef NO_READ_FROM_CODER\r
+\r
+STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize)\r
+    *processedSize = 0;\r
+  do\r
+  {\r
+    if (_inPos == _inSize)\r
+    {\r
+      _inPos = _inSize = 0;\r
+      RINOK(_inStream->Read(_inBuf, kInBufSize, &_inSize));\r
+    }\r
+    {\r
+      SizeT inProcessed = _inSize - _inPos;\r
+\r
+      if (_outSizeDefined)\r
+      {\r
+        const UInt64 rem = _outSize - _outSizeProcessed;\r
+        if (rem < size)\r
+          size = (UInt32)rem;\r
+      }\r
+\r
+      SizeT outProcessed = size;\r
+      ELzmaStatus status;\r
+      SRes res = Lzma2Dec_DecodeToBuf(&_state, (Byte *)data, &outProcessed,\r
+          _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status);\r
+      _inPos += (UInt32)inProcessed;\r
+      _inSizeProcessed += inProcessed;\r
+      _outSizeProcessed += outProcessed;\r
+      size -= (UInt32)outProcessed;\r
+      data = (Byte *)data + outProcessed;\r
+      if (processedSize)\r
+        *processedSize += (UInt32)outProcessed;\r
+      RINOK(SResToHRESULT(res));\r
+      if (inProcessed == 0 && outProcessed == 0)\r
+        return S_OK;\r
+    }\r
+  }\r
+  while (size != 0);\r
+  return S_OK;\r
+}\r
+\r
+#endif\r
+\r
+}}\r
diff --git a/CPP/7zip/Compress/Lzma2Decoder.h b/CPP/7zip/Compress/Lzma2Decoder.h
new file mode 100755 (executable)
index 0000000..3540097
--- /dev/null
@@ -0,0 +1,73 @@
+// Lzma2Decoder.h\r
+\r
+#ifndef __LZMA2_DECODER_H\r
+#define __LZMA2_DECODER_H\r
+\r
+#include "../../../C/Lzma2Dec.h"\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+namespace NCompress {\r
+namespace NLzma2 {\r
+\r
+class CDecoder:\r
+  public ICompressCoder,\r
+  public ICompressSetDecoderProperties2,\r
+  public ICompressGetInStreamProcessedSize,\r
+  #ifndef NO_READ_FROM_CODER\r
+  public ICompressSetInStream,\r
+  public ICompressSetOutStreamSize,\r
+  public ISequentialInStream,\r
+  #endif\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<ISequentialInStream> _inStream;\r
+  Byte *_inBuf;\r
+  UInt32 _inPos;\r
+  UInt32 _inSize;\r
+  CLzma2Dec _state;\r
+  bool _outSizeDefined;\r
+  UInt64 _outSize;\r
+  UInt64 _inSizeProcessed;\r
+  UInt64 _outSizeProcessed;\r
+public:\r
+\r
+  #ifndef NO_READ_FROM_CODER\r
+  MY_UNKNOWN_IMP5(\r
+      ICompressSetDecoderProperties2,\r
+      ICompressGetInStreamProcessedSize,\r
+      ICompressSetInStream,\r
+      ICompressSetOutStreamSize,\r
+      ISequentialInStream)\r
+  #else\r
+  MY_UNKNOWN_IMP2(\r
+      ICompressSetDecoderProperties2,\r
+      ICompressGetInStreamProcessedSize)\r
+  #endif\r
+\r
+  STDMETHOD(Code)(ISequentialInStream *inStream,\r
+      ISequentialOutStream *outStream, const UInt64 *_inSize, const UInt64 *outSize,\r
+      ICompressProgressInfo *progress);\r
+\r
+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);\r
+\r
+  STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);\r
+\r
+  STDMETHOD(SetInStream)(ISequentialInStream *inStream);\r
+  STDMETHOD(ReleaseInStream)();\r
+  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);\r
+\r
+  #ifndef NO_READ_FROM_CODER\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  #endif\r
+\r
+  CDecoder();\r
+  virtual ~CDecoder();\r
+\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/Lzma2Encoder.cpp b/CPP/7zip/Compress/Lzma2Encoder.cpp
new file mode 100755 (executable)
index 0000000..871f146
--- /dev/null
@@ -0,0 +1,94 @@
+// Lzma2Encoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+\r
+#include "../Common/CWrappers.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "Lzma2Encoder.h"\r
+\r
+namespace NCompress {\r
+\r
+namespace NLzma {\r
+\r
+HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep);\r
+\r
+}\r
+\r
+namespace NLzma2 {\r
+\r
+static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }\r
+static void SzBigFree(void *, void *address) { BigFree(address); }\r
+static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };\r
+\r
+static void *SzAlloc(void *, size_t size) { return MyAlloc(size); }\r
+static void SzFree(void *, void *address) { MyFree(address); }\r
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };\r
+\r
+CEncoder::CEncoder()\r
+{\r
+  _encoder = 0;\r
+  _encoder = Lzma2Enc_Create(&g_Alloc, &g_BigAlloc);\r
+  if (_encoder == 0)\r
+    throw 1;\r
+}\r
+\r
+CEncoder::~CEncoder()\r
+{\r
+  if (_encoder != 0)\r
+    Lzma2Enc_Destroy(_encoder);\r
+}\r
+\r
+HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props)\r
+{\r
+  switch (propID)\r
+  {\r
+    case NCoderPropID::kBlockSize:\r
+      if (prop.vt != VT_UI4) return E_INVALIDARG; lzma2Props.blockSize = prop.ulVal; break;\r
+    case NCoderPropID::kNumThreads:\r
+      if (prop.vt != VT_UI4) return E_INVALIDARG; lzma2Props.numTotalThreads = (int)(prop.ulVal); break;\r
+    default:\r
+      RINOK(NLzma::SetLzmaProp(propID, prop, lzma2Props.lzmaProps));\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,\r
+    const PROPVARIANT *coderProps, UInt32 numProps)\r
+{\r
+  CLzma2EncProps lzma2Props;\r
+  Lzma2EncProps_Init(&lzma2Props);\r
+\r
+  for (UInt32 i = 0; i < numProps; i++)\r
+  {\r
+    RINOK(SetLzma2Prop(propIDs[i], coderProps[i], lzma2Props));\r
+  }\r
+  return SResToHRESULT(Lzma2Enc_SetProps(_encoder, &lzma2Props));\r
+}\r
+\r
+STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)\r
+{\r
+  Byte prop = Lzma2Enc_WriteProperties(_encoder);\r
+  return WriteStream(outStream, &prop, 1);\r
+}\r
+\r
+STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)\r
+{\r
+  CSeqInStreamWrap inWrap(inStream);\r
+  CSeqOutStreamWrap outWrap(outStream);\r
+  CCompressProgressWrap progressWrap(progress);\r
+\r
+  SRes res = Lzma2Enc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL);\r
+  if (res == SZ_ERROR_READ && inWrap.Res != S_OK)\r
+    return inWrap.Res;\r
+  if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK)\r
+    return outWrap.Res;\r
+  if (res == SZ_ERROR_PROGRESS && progressWrap.Res != S_OK)\r
+    return progressWrap.Res;\r
+  return SResToHRESULT(res);\r
+}\r
+  \r
+}}\r
diff --git a/CPP/7zip/Compress/Lzma2Encoder.h b/CPP/7zip/Compress/Lzma2Encoder.h
new file mode 100755 (executable)
index 0000000..fc43702
--- /dev/null
@@ -0,0 +1,36 @@
+// Lzma2Encoder.h\r
+\r
+#ifndef __LZMA2_ENCODER_H\r
+#define __LZMA2_ENCODER_H\r
+\r
+#include "../../../C/Lzma2Enc.h"\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+namespace NCompress {\r
+namespace NLzma2 {\r
+\r
+class CEncoder:\r
+  public ICompressCoder,\r
+  public ICompressSetCoderProperties,\r
+  public ICompressWriteCoderProperties,\r
+  public CMyUnknownImp\r
+{\r
+  CLzma2EncHandle _encoder;\r
+public:\r
+  MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties)\r
\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);\r
+  STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);\r
+\r
+  CEncoder();\r
+  virtual ~CEncoder();\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/Lzma2Register.cpp b/CPP/7zip/Compress/Lzma2Register.cpp
new file mode 100755 (executable)
index 0000000..28430b4
--- /dev/null
@@ -0,0 +1,20 @@
+// Lzma2Register.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../Common/RegisterCodec.h"\r
+\r
+#include "Lzma2Decoder.h"\r
+\r
+static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLzma2::CDecoder); }\r
+#ifndef EXTRACT_ONLY\r
+#include "Lzma2Encoder.h"\r
+static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLzma2::CEncoder);  }\r
+#else\r
+#define CreateCodecOut 0\r
+#endif\r
+\r
+static CCodecInfo g_CodecInfo =\r
+  { CreateCodec, CreateCodecOut, 0x21, L"LZMA2", 1, false };\r
+\r
+REGISTER_CODEC(LZMA2)\r
diff --git a/CPP/7zip/Compress/LzmaDecoder.cpp b/CPP/7zip/Compress/LzmaDecoder.cpp
new file mode 100755 (executable)
index 0000000..9f15fdb
--- /dev/null
@@ -0,0 +1,252 @@
+// LzmaDecoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "LzmaDecoder.h"\r
+\r
+static HRESULT SResToHRESULT(SRes res)\r
+{\r
+  switch(res)\r
+  {\r
+    case SZ_OK: return S_OK;\r
+    case SZ_ERROR_MEM: return E_OUTOFMEMORY;\r
+    case SZ_ERROR_PARAM: return E_INVALIDARG;\r
+    case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;\r
+    case SZ_ERROR_DATA: return S_FALSE;\r
+  }\r
+  return E_FAIL;\r
+}\r
+\r
+namespace NCompress {\r
+namespace NLzma {\r
+\r
+CDecoder::CDecoder(): _inBuf(0), _propsWereSet(false), _outSizeDefined(false),\r
+  _inBufSize(1 << 20),\r
+  _outBufSize(1 << 22),\r
+  FinishStream(false)\r
+{\r
+  _inSizeProcessed = 0;\r
+  _inPos = _inSize = 0;\r
+  LzmaDec_Construct(&_state);\r
+}\r
+\r
+static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }\r
+static void SzFree(void *p, void *address) { p = p; MyFree(address); }\r
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };\r
+\r
+CDecoder::~CDecoder()\r
+{\r
+  LzmaDec_Free(&_state, &g_Alloc);\r
+  MyFree(_inBuf);\r
+}\r
+\r
+STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; }\r
+STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; }\r
+\r
+HRESULT CDecoder::CreateInputBuffer()\r
+{\r
+  if (_inBuf == 0 || _inBufSize != _inBufSizeAllocated)\r
+  {\r
+    MyFree(_inBuf);\r
+    _inBuf = (Byte *)MyAlloc(_inBufSize);\r
+    if (_inBuf == 0)\r
+      return E_OUTOFMEMORY;\r
+    _inBufSizeAllocated = _inBufSize;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)\r
+{\r
+  RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_Alloc)));\r
+  _propsWereSet = true;\r
+  return CreateInputBuffer();\r
+}\r
+\r
+void CDecoder::SetOutStreamSizeResume(const UInt64 *outSize)\r
+{\r
+  _outSizeDefined = (outSize != NULL);\r
+  if (_outSizeDefined)\r
+    _outSize = *outSize;\r
+  _outSizeProcessed = 0;\r
+  _wrPos = 0;\r
+  LzmaDec_Init(&_state);\r
+}\r
+\r
+STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)\r
+{\r
+  _inSizeProcessed = 0;\r
+  _inPos = _inSize = 0;\r
+  SetOutStreamSizeResume(outSize);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)\r
+{\r
+  if (_inBuf == 0 || !_propsWereSet)\r
+    return S_FALSE;\r
+\r
+  UInt64 startInProgress = _inSizeProcessed;\r
+\r
+  SizeT next = (_state.dicBufSize - _state.dicPos < _outBufSize) ? _state.dicBufSize : (_state.dicPos + _outBufSize);\r
+  for (;;)\r
+  {\r
+    if (_inPos == _inSize)\r
+    {\r
+      _inPos = _inSize = 0;\r
+      RINOK(inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize));\r
+    }\r
+\r
+    SizeT dicPos = _state.dicPos;\r
+    SizeT curSize = next - dicPos;\r
+    \r
+    ELzmaFinishMode finishMode = LZMA_FINISH_ANY;\r
+    if (_outSizeDefined)\r
+    {\r
+      const UInt64 rem = _outSize - _outSizeProcessed;\r
+      if (rem <= curSize)\r
+      {\r
+        curSize = (SizeT)rem;\r
+        if (FinishStream)\r
+          finishMode = LZMA_FINISH_END;\r
+      }\r
+    }\r
+\r
+    SizeT inSizeProcessed = _inSize - _inPos;\r
+    ELzmaStatus status;\r
+    SRes res = LzmaDec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status);\r
+\r
+    _inPos += (UInt32)inSizeProcessed;\r
+    _inSizeProcessed += inSizeProcessed;\r
+    SizeT outSizeProcessed = _state.dicPos - dicPos;\r
+    _outSizeProcessed += outSizeProcessed;\r
+\r
+    bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0);\r
+    bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize);\r
+\r
+    if (res != 0 || _state.dicPos == next || finished || stopDecoding)\r
+    {\r
+      HRESULT res2 = WriteStream(outStream, _state.dic + _wrPos, _state.dicPos - _wrPos);\r
+\r
+      _wrPos = _state.dicPos;\r
+      if (_state.dicPos == _state.dicBufSize)\r
+      {\r
+        _state.dicPos = 0;\r
+        _wrPos = 0;\r
+      }\r
+      next = (_state.dicBufSize - _state.dicPos < _outBufSize) ? _state.dicBufSize : (_state.dicPos + _outBufSize);\r
+\r
+      if (res != 0)\r
+        return S_FALSE;\r
+      RINOK(res2);\r
+      if (stopDecoding)\r
+        return S_OK;\r
+      if (finished)\r
+        return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE);\r
+    }\r
+    if (progress)\r
+    {\r
+      UInt64 inSize = _inSizeProcessed - startInProgress;\r
+      RINOK(progress->SetRatioInfo(&inSize, &_outSizeProcessed));\r
+    }\r
+  }\r
+}\r
+\r
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  if (_inBuf == 0)\r
+    return E_INVALIDARG;\r
+  SetOutStreamSize(outSize);\r
+  return CodeSpec(inStream, outStream, progress);\r
+}\r
+\r
+#ifndef NO_READ_FROM_CODER\r
+\r
+STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; }\r
+STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; }\r
+\r
+STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize)\r
+    *processedSize = 0;\r
+  do\r
+  {\r
+    if (_inPos == _inSize)\r
+    {\r
+      _inPos = _inSize = 0;\r
+      RINOK(_inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize));\r
+    }\r
+    {\r
+      SizeT inProcessed = _inSize - _inPos;\r
+\r
+      if (_outSizeDefined)\r
+      {\r
+        const UInt64 rem = _outSize - _outSizeProcessed;\r
+        if (rem < size)\r
+          size = (UInt32)rem;\r
+      }\r
+\r
+      SizeT outProcessed = size;\r
+      ELzmaStatus status;\r
+      SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed,\r
+          _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status);\r
+      _inPos += (UInt32)inProcessed;\r
+      _inSizeProcessed += inProcessed;\r
+      _outSizeProcessed += outProcessed;\r
+      size -= (UInt32)outProcessed;\r
+      data = (Byte *)data + outProcessed;\r
+      if (processedSize)\r
+        *processedSize += (UInt32)outProcessed;\r
+      RINOK(SResToHRESULT(res));\r
+      if (inProcessed == 0 && outProcessed == 0)\r
+        return S_OK;\r
+    }\r
+  }\r
+  while (size != 0);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  SetOutStreamSizeResume(outSize);\r
+  return CodeSpec(_inStream, outStream, progress);\r
+}\r
+\r
+HRESULT CDecoder::ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  RINOK(CreateInputBuffer());\r
+  if (processedSize)\r
+    *processedSize = 0;\r
+  while (size > 0)\r
+  {\r
+    if (_inPos == _inSize)\r
+    {\r
+      _inPos = _inSize = 0;\r
+      RINOK(_inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize));\r
+      if (_inSize == 0)\r
+        break;\r
+    }\r
+    {\r
+      UInt32 curSize = _inSize - _inPos;\r
+      if (curSize > size)\r
+        curSize = size;\r
+      memcpy(data, _inBuf + _inPos, curSize);\r
+      _inPos += curSize;\r
+      _inSizeProcessed += curSize;\r
+      size -= curSize;\r
+      data = (Byte *)data + curSize;\r
+      if (processedSize)\r
+        *processedSize += curSize;\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+#endif\r
+\r
+}}\r
diff --git a/CPP/7zip/Compress/LzmaDecoder.h b/CPP/7zip/Compress/LzmaDecoder.h
new file mode 100755 (executable)
index 0000000..801a77b
--- /dev/null
@@ -0,0 +1,84 @@
+// LzmaDecoder.h\r
+\r
+#ifndef __LZMA_DECODER_H\r
+#define __LZMA_DECODER_H\r
+\r
+#include "../../../C/LzmaDec.h"\r
+\r
+#include "../../Common/MyCom.h"\r
+#include "../ICoder.h"\r
+\r
+namespace NCompress {\r
+namespace NLzma {\r
+\r
+class CDecoder:\r
+  public ICompressCoder,\r
+  public ICompressSetDecoderProperties2,\r
+  public ICompressSetBufSize,\r
+  #ifndef NO_READ_FROM_CODER\r
+  public ICompressSetInStream,\r
+  public ICompressSetOutStreamSize,\r
+  public ISequentialInStream,\r
+  #endif\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<ISequentialInStream> _inStream;\r
+  Byte *_inBuf;\r
+  UInt32 _inPos;\r
+  UInt32 _inSize;\r
+  CLzmaDec _state;\r
+  bool _propsWereSet;\r
+  bool _outSizeDefined;\r
+  UInt64 _outSize;\r
+  UInt64 _inSizeProcessed;\r
+  UInt64 _outSizeProcessed;\r
+\r
+  UInt32 _inBufSizeAllocated;\r
+  UInt32 _inBufSize;\r
+  UInt32 _outBufSize;\r
+  SizeT _wrPos;\r
+\r
+  HRESULT CreateInputBuffer();\r
+  HRESULT CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress);\r
+  void SetOutStreamSizeResume(const UInt64 *outSize);\r
+\r
+public:\r
+  MY_QUERYINTERFACE_BEGIN2(ICompressCoder)\r
+  MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2)\r
+  MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize)\r
+  #ifndef NO_READ_FROM_CODER\r
+  MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)\r
+  MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)\r
+  MY_QUERYINTERFACE_ENTRY(ISequentialInStream)\r
+  #endif\r
+  MY_QUERYINTERFACE_END\r
+  MY_ADDREF_RELEASE\r
+\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);\r
+  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);\r
+  STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);\r
+  STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);\r
+\r
+  #ifndef NO_READ_FROM_CODER\r
+  \r
+  STDMETHOD(SetInStream)(ISequentialInStream *inStream);\r
+  STDMETHOD(ReleaseInStream)();\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+\r
+  HRESULT CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+  HRESULT ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize);\r
+  UInt64 GetInputProcessedSize() const { return _inSizeProcessed; }\r
+\r
+  #endif\r
+\r
+  bool FinishStream;\r
+\r
+  CDecoder();\r
+  virtual ~CDecoder();\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/LzmaEncoder.cpp b/CPP/7zip/Compress/LzmaEncoder.cpp
new file mode 100755 (executable)
index 0000000..aa96c0e
--- /dev/null
@@ -0,0 +1,149 @@
+// LzmaEncoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+\r
+#include "../Common/CWrappers.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "LzmaEncoder.h"\r
+\r
+namespace NCompress {\r
+namespace NLzma {\r
+\r
+static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }\r
+static void SzBigFree(void *, void *address) { BigFree(address); }\r
+static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };\r
+\r
+static void *SzAlloc(void *, size_t size) { return MyAlloc(size); }\r
+static void SzFree(void *, void *address) { MyFree(address); }\r
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };\r
+\r
+CEncoder::CEncoder()\r
+{\r
+  _encoder = 0;\r
+  _encoder = LzmaEnc_Create(&g_Alloc);\r
+  if (_encoder == 0)\r
+    throw 1;\r
+}\r
+\r
+CEncoder::~CEncoder()\r
+{\r
+  if (_encoder != 0)\r
+    LzmaEnc_Destroy(_encoder, &g_Alloc, &g_BigAlloc);\r
+}\r
+\r
+inline wchar_t GetUpperChar(wchar_t c)\r
+{\r
+  if (c >= 'a' && c <= 'z')\r
+    c -= 0x20;\r
+  return c;\r
+}\r
+\r
+static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes)\r
+{\r
+  wchar_t c = GetUpperChar(*s++);\r
+  if (c == L'H')\r
+  {\r
+    if (GetUpperChar(*s++) != L'C')\r
+      return 0;\r
+    int numHashBytesLoc = (int)(*s++ - L'0');\r
+    if (numHashBytesLoc < 4 || numHashBytesLoc > 4)\r
+      return 0;\r
+    if (*s++ != 0)\r
+      return 0;\r
+    *btMode = 0;\r
+    *numHashBytes = numHashBytesLoc;\r
+    return 1;\r
+  }\r
+  if (c != L'B')\r
+    return 0;\r
+\r
+  if (GetUpperChar(*s++) != L'T')\r
+    return 0;\r
+  int numHashBytesLoc = (int)(*s++ - L'0');\r
+  if (numHashBytesLoc < 2 || numHashBytesLoc > 4)\r
+    return 0;\r
+  c = GetUpperChar(*s++);\r
+  if (c != L'\0')\r
+    return 0;\r
+  *btMode = 1;\r
+  *numHashBytes = numHashBytesLoc;\r
+  return 1;\r
+}\r
+\r
+HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep)\r
+{\r
+  if (propID == NCoderPropID::kMatchFinder)\r
+  {\r
+    if (prop.vt != VT_BSTR)\r
+      return E_INVALIDARG;\r
+    return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG;\r
+  }\r
+  if (prop.vt != VT_UI4)\r
+    return E_INVALIDARG;\r
+  UInt32 v = prop.ulVal;\r
+  switch (propID)\r
+  {\r
+    case NCoderPropID::kNumFastBytes: ep.fb = v; break;\r
+    case NCoderPropID::kMatchFinderCycles: ep.mc = v; break;\r
+    case NCoderPropID::kAlgorithm: ep.algo = v; break;\r
+    case NCoderPropID::kDictionarySize: ep.dictSize = v; break;\r
+    case NCoderPropID::kPosStateBits: ep.pb = v; break;\r
+    case NCoderPropID::kLitPosBits: ep.lp = v; break;\r
+    case NCoderPropID::kLitContextBits: ep.lc = v; break;\r
+    default: return E_INVALIDARG;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,\r
+    const PROPVARIANT *coderProps, UInt32 numProps)\r
+{\r
+  CLzmaEncProps props;\r
+  LzmaEncProps_Init(&props);\r
+\r
+  for (UInt32 i = 0; i < numProps; i++)\r
+  {\r
+    const PROPVARIANT &prop = coderProps[i];\r
+    PROPID propID = propIDs[i];\r
+    switch (propID)\r
+    {\r
+      case NCoderPropID::kEndMarker:\r
+        if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal == VARIANT_TRUE); break;\r
+      case NCoderPropID::kNumThreads:\r
+        if (prop.vt != VT_UI4) return E_INVALIDARG; props.numThreads = prop.ulVal; break;\r
+      default:\r
+        RINOK(SetLzmaProp(propID, prop, props));\r
+    }\r
+  }\r
+  return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props));\r
+}\r
+\r
+STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)\r
+{\r
+  Byte props[LZMA_PROPS_SIZE];\r
+  size_t size = LZMA_PROPS_SIZE;\r
+  RINOK(LzmaEnc_WriteProperties(_encoder, props, &size));\r
+  return WriteStream(outStream, props, size);\r
+}\r
+\r
+STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)\r
+{\r
+  CSeqInStreamWrap inWrap(inStream);\r
+  CSeqOutStreamWrap outWrap(outStream);\r
+  CCompressProgressWrap progressWrap(progress);\r
+\r
+  SRes res = LzmaEnc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL, &g_Alloc, &g_BigAlloc);\r
+  if (res == SZ_ERROR_READ && inWrap.Res != S_OK)\r
+    return inWrap.Res;\r
+  if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK)\r
+    return outWrap.Res;\r
+  if (res == SZ_ERROR_PROGRESS && progressWrap.Res != S_OK)\r
+    return progressWrap.Res;\r
+  return SResToHRESULT(res);\r
+}\r
+  \r
+}}\r
diff --git a/CPP/7zip/Compress/LzmaEncoder.h b/CPP/7zip/Compress/LzmaEncoder.h
new file mode 100755 (executable)
index 0000000..c3e8961
--- /dev/null
@@ -0,0 +1,36 @@
+// LzmaEncoder.h\r
+\r
+#ifndef __LZMA_ENCODER_H\r
+#define __LZMA_ENCODER_H\r
+\r
+#include "../../../C/LzmaEnc.h"\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+namespace NCompress {\r
+namespace NLzma {\r
+\r
+class CEncoder:\r
+  public ICompressCoder,\r
+  public ICompressSetCoderProperties,\r
+  public ICompressWriteCoderProperties,\r
+  public CMyUnknownImp\r
+{\r
+  CLzmaEncHandle _encoder;\r
+public:\r
+  MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties)\r
+    \r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);\r
+  STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);\r
+\r
+  CEncoder();\r
+  virtual ~CEncoder();\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/LzmaRegister.cpp b/CPP/7zip/Compress/LzmaRegister.cpp
new file mode 100755 (executable)
index 0000000..9c67eaf
--- /dev/null
@@ -0,0 +1,20 @@
+// LzmaRegister.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../Common/RegisterCodec.h"\r
+\r
+#include "LzmaDecoder.h"\r
+\r
+static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CDecoder); }\r
+#ifndef EXTRACT_ONLY\r
+#include "LzmaEncoder.h"\r
+static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CEncoder);  }\r
+#else\r
+#define CreateCodecOut 0\r
+#endif\r
+\r
+static CCodecInfo g_CodecInfo =\r
+  { CreateCodec, CreateCodecOut, 0x030101, L"LZMA", 1, false };\r
+\r
+REGISTER_CODEC(LZMA)\r
diff --git a/CPP/7zip/Compress/Lzx.h b/CPP/7zip/Compress/Lzx.h
new file mode 100755 (executable)
index 0000000..4d4ba84
--- /dev/null
@@ -0,0 +1,61 @@
+// Lzx.h\r
+\r
+#ifndef __COMPRESS_LZX_H\r
+#define __COMPRESS_LZX_H\r
+\r
+namespace NCompress {\r
+namespace NLzx {\r
+\r
+const unsigned kNumHuffmanBits = 16;\r
+const UInt32 kNumRepDistances = 3;\r
+\r
+const UInt32 kNumLenSlots = 8;\r
+const UInt32 kMatchMinLen = 2;\r
+const UInt32 kNumLenSymbols = 249;\r
+const UInt32 kMatchMaxLen = kMatchMinLen + (kNumLenSlots - 1) + kNumLenSymbols - 1;\r
+\r
+const unsigned kNumAlignBits = 3;\r
+const UInt32 kAlignTableSize = 1 << kNumAlignBits;\r
+\r
+const UInt32 kNumPosSlots = 50;\r
+const UInt32 kNumPosLenSlots = kNumPosSlots * kNumLenSlots;\r
+\r
+const UInt32 kMainTableSize = 256 + kNumPosLenSlots;\r
+const UInt32 kLevelTableSize = 20;\r
+const UInt32 kMaxTableSize = kMainTableSize;\r
+\r
+const unsigned kNumBlockTypeBits = 3;\r
+const unsigned kBlockTypeVerbatim = 1;\r
+const unsigned kBlockTypeAligned = 2;\r
+const unsigned kBlockTypeUncompressed = 3;\r
+\r
+const unsigned kUncompressedBlockSizeNumBits = 24;\r
+\r
+const unsigned kNumBitsForPreTreeLevel = 4;\r
+\r
+const unsigned kLevelSymbolZeros = 17;\r
+const unsigned kLevelSymbolZerosBig = 18;\r
+const unsigned kLevelSymbolSame = 19;\r
+\r
+const unsigned kLevelSymbolZerosStartValue = 4;\r
+const unsigned kLevelSymbolZerosNumBits = 4;\r
+\r
+const unsigned kLevelSymbolZerosBigStartValue = kLevelSymbolZerosStartValue +\r
+    (1 << kLevelSymbolZerosNumBits);\r
+const unsigned kLevelSymbolZerosBigNumBits = 5;\r
+\r
+const unsigned kLevelSymbolSameNumBits = 1;\r
+const unsigned kLevelSymbolSameStartValue = 4;\r
+\r
+const unsigned kNumBitsForAlignLevel = 3;\r
+  \r
+const unsigned kNumDictionaryBitsMin = 15;\r
+const unsigned kNumDictionaryBitsMax = 21;\r
+const UInt32 kDictionarySizeMax = (1 << kNumDictionaryBitsMax);\r
+\r
+const unsigned kNumLinearPosSlotBits = 17;\r
+const UInt32 kNumPowerPosSlots = 0x26;\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/Lzx86Converter.cpp b/CPP/7zip/Compress/Lzx86Converter.cpp
new file mode 100755 (executable)
index 0000000..c74a7fa
--- /dev/null
@@ -0,0 +1,90 @@
+// Lzx86Converter.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/Defs.h"\r
+\r
+#include "Lzx86Converter.h"\r
+\r
+namespace NCompress {\r
+namespace NLzx {\r
+\r
+static const int kResidue = 6 + 4;\r
+\r
+void Cx86ConvertOutStream::MakeTranslation()\r
+{\r
+  if (m_Pos <= kResidue)\r
+    return;\r
+  UInt32 numBytes = m_Pos - kResidue;\r
+  Byte *buffer = m_Buffer;\r
+  for (UInt32 i = 0; i < numBytes;)\r
+  {\r
+    if (buffer[i++] == 0xE8)\r
+    {\r
+      Int32 absValue = 0;\r
+      int j;\r
+      for(j = 0; j < 4; j++)\r
+        absValue += (UInt32)buffer[i + j] << (j * 8);\r
+      Int32 pos = (Int32)(m_ProcessedSize + i - 1);\r
+      if (absValue >= -pos && absValue < (Int32)m_TranslationSize)\r
+      {\r
+        UInt32 offset = (absValue >= 0) ?\r
+            absValue - pos :\r
+            absValue + m_TranslationSize;\r
+        for(j = 0; j < 4; j++)\r
+        {\r
+          buffer[i + j] = (Byte)(offset & 0xFF);\r
+          offset >>= 8;\r
+        }\r
+      }\r
+      i += 4;\r
+    }\r
+  }\r
+}\r
+\r
+STDMETHODIMP Cx86ConvertOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize != NULL)\r
+    *processedSize = 0;\r
+  if (!m_TranslationMode)\r
+    return m_Stream->Write(data, size, processedSize);\r
+  UInt32 realProcessedSize = 0;\r
+  while (realProcessedSize < size)\r
+  {\r
+    UInt32 writeSize = MyMin(size - realProcessedSize, kUncompressedBlockSize - m_Pos);\r
+    memmove(m_Buffer + m_Pos, (const Byte *)data + realProcessedSize, writeSize);\r
+    m_Pos += writeSize;\r
+    realProcessedSize += writeSize;\r
+    if (m_Pos == kUncompressedBlockSize)\r
+    {\r
+      RINOK(Flush());\r
+    }\r
+  }\r
+  if (processedSize != NULL)\r
+    *processedSize = realProcessedSize;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT Cx86ConvertOutStream::Flush()\r
+{\r
+  if (m_Pos == 0)\r
+    return S_OK;\r
+  if (m_TranslationMode)\r
+    MakeTranslation();\r
+  UInt32 pos = 0;\r
+  do\r
+  {\r
+    UInt32 processed;\r
+    RINOK(m_Stream->Write(m_Buffer + pos, m_Pos - pos, &processed));\r
+    if (processed == 0)\r
+      return E_FAIL;\r
+    pos += processed;\r
+  }\r
+  while(pos < m_Pos);\r
+  m_ProcessedSize += m_Pos;\r
+  m_Pos = 0;\r
+  m_TranslationMode = (m_TranslationMode && (m_ProcessedSize < (1 << 30)));\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Compress/Lzx86Converter.h b/CPP/7zip/Compress/Lzx86Converter.h
new file mode 100755 (executable)
index 0000000..a373e8b
--- /dev/null
@@ -0,0 +1,46 @@
+// Lzx86Converter.h\r
+\r
+#ifndef __LZX_86_CONVERTER_H\r
+#define __LZX_86_CONVERTER_H\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../IStream.h"\r
+\r
+namespace NCompress {\r
+namespace NLzx {\r
+\r
+const int kUncompressedBlockSize = 1 << 15;\r
+\r
+class Cx86ConvertOutStream:\r
+  public ISequentialOutStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<ISequentialOutStream> m_Stream;\r
+  UInt32 m_ProcessedSize;\r
+  UInt32 m_Pos;\r
+  UInt32 m_TranslationSize;\r
+  bool m_TranslationMode;\r
+  Byte m_Buffer[kUncompressedBlockSize];\r
+\r
+  void MakeTranslation();\r
+public:\r
+  void SetStream(ISequentialOutStream *outStream) { m_Stream = outStream; }\r
+  void ReleaseStream() { m_Stream.Release(); }\r
+  void Init(bool translationMode, UInt32 translationSize)\r
+  {\r
+    m_TranslationMode = translationMode;\r
+    m_TranslationSize = translationSize;\r
+    m_ProcessedSize = 0;\r
+    m_Pos = 0;\r
+  }\r
+  HRESULT Flush();\r
+\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/LzxDecoder.cpp b/CPP/7zip/Compress/LzxDecoder.cpp
new file mode 100755 (executable)
index 0000000..1c08feb
--- /dev/null
@@ -0,0 +1,387 @@
+// LzxDecoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/Defs.h"\r
+\r
+#include "LzxDecoder.h"\r
+\r
+namespace NCompress {\r
+namespace NLzx {\r
+\r
+const int kLenIdNeedInit = -2;\r
+\r
+CDecoder::CDecoder(bool wimMode):\r
+  _keepHistory(false),\r
+  _skipByte(false),\r
+  _wimMode(wimMode)\r
+{\r
+  m_x86ConvertOutStreamSpec = new Cx86ConvertOutStream;\r
+  m_x86ConvertOutStream = m_x86ConvertOutStreamSpec;\r
+}\r
+\r
+void CDecoder::ReleaseStreams()\r
+{\r
+  m_OutWindowStream.ReleaseStream();\r
+  m_InBitStream.ReleaseStream();\r
+  m_x86ConvertOutStreamSpec->ReleaseStream();\r
+}\r
+\r
+STDMETHODIMP CDecoder::Flush()\r
+{\r
+  RINOK(m_OutWindowStream.Flush());\r
+  return m_x86ConvertOutStreamSpec->Flush();\r
+}\r
+\r
+UInt32 CDecoder::ReadBits(unsigned numBits) { return m_InBitStream.ReadBits(numBits); }\r
+\r
+#define RIF(x) { if (!(x)) return false; }\r
+\r
+bool CDecoder::ReadTable(Byte *lastLevels, Byte *newLevels, UInt32 numSymbols)\r
+{\r
+  Byte levelLevels[kLevelTableSize];\r
+  UInt32 i;\r
+  for (i = 0; i < kLevelTableSize; i++)\r
+    levelLevels[i] = (Byte)ReadBits(kNumBitsForPreTreeLevel);\r
+  RIF(m_LevelDecoder.SetCodeLengths(levelLevels));\r
+  unsigned num = 0;\r
+  Byte symbol = 0;\r
+  for (i = 0; i < numSymbols;)\r
+  {\r
+    if (num != 0)\r
+    {\r
+      lastLevels[i] = newLevels[i] = symbol;\r
+      i++;\r
+      num--;\r
+      continue;\r
+    }\r
+    UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);\r
+    if (number == kLevelSymbolZeros)\r
+    {\r
+      num = kLevelSymbolZerosStartValue + (unsigned)ReadBits(kLevelSymbolZerosNumBits);\r
+      symbol = 0;\r
+    }\r
+    else if (number == kLevelSymbolZerosBig)\r
+    {\r
+      num = kLevelSymbolZerosBigStartValue + (unsigned)ReadBits(kLevelSymbolZerosBigNumBits);\r
+      symbol = 0;\r
+    }\r
+    else if (number == kLevelSymbolSame || number <= kNumHuffmanBits)\r
+    {\r
+      if (number <= kNumHuffmanBits)\r
+        num = 1;\r
+      else\r
+      {\r
+        num = kLevelSymbolSameStartValue + (unsigned)ReadBits(kLevelSymbolSameNumBits);\r
+        number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);\r
+        if (number > kNumHuffmanBits)\r
+          return false;\r
+      }\r
+      symbol = Byte((17 + lastLevels[i] - number) % (kNumHuffmanBits + 1));\r
+    }\r
+    else\r
+      return false;\r
+  }\r
+  return true;\r
+}\r
+\r
+bool CDecoder::ReadTables(void)\r
+{\r
+  Byte newLevels[kMaxTableSize];\r
+  {\r
+    if (_skipByte)\r
+      m_InBitStream.DirectReadByte();\r
+    m_InBitStream.Normalize();\r
+\r
+    unsigned blockType = (unsigned)ReadBits(kNumBlockTypeBits);\r
+    if (blockType > kBlockTypeUncompressed)\r
+      return false;\r
+    if (_wimMode)\r
+      if (ReadBits(1) == 1)\r
+        m_UnCompressedBlockSize = (1 << 15);\r
+      else\r
+        m_UnCompressedBlockSize = ReadBits(16);\r
+    else\r
+      m_UnCompressedBlockSize = m_InBitStream.ReadBitsBig(kUncompressedBlockSizeNumBits);\r
+\r
+    m_IsUncompressedBlock = (blockType == kBlockTypeUncompressed);\r
+\r
+    _skipByte = (m_IsUncompressedBlock && ((m_UnCompressedBlockSize & 1) != 0));\r
+\r
+    if (m_IsUncompressedBlock)\r
+    {\r
+      ReadBits(16 - m_InBitStream.GetBitPosition());\r
+      if (!m_InBitStream.ReadUInt32(m_RepDistances[0]))\r
+        return false;\r
+      m_RepDistances[0]--;\r
+      for (unsigned i = 1; i < kNumRepDistances; i++)\r
+      {\r
+        UInt32 rep = 0;\r
+        for (unsigned j = 0; j < 4; j++)\r
+          rep |= (UInt32)m_InBitStream.DirectReadByte() << (8 * j);\r
+        m_RepDistances[i] = rep - 1;\r
+      }\r
+      return true;\r
+    }\r
+    m_AlignIsUsed = (blockType == kBlockTypeAligned);\r
+    if (m_AlignIsUsed)\r
+    {\r
+      for (unsigned i = 0; i < kAlignTableSize; i++)\r
+        newLevels[i] = (Byte)ReadBits(kNumBitsForAlignLevel);\r
+      RIF(m_AlignDecoder.SetCodeLengths(newLevels));\r
+    }\r
+  }\r
+\r
+  RIF(ReadTable(m_LastMainLevels, newLevels, 256));\r
+  RIF(ReadTable(m_LastMainLevels + 256, newLevels + 256, m_NumPosLenSlots));\r
+  for (UInt32 i = 256 + m_NumPosLenSlots; i < kMainTableSize; i++)\r
+    newLevels[i] = 0;\r
+  RIF(m_MainDecoder.SetCodeLengths(newLevels));\r
+\r
+  RIF(ReadTable(m_LastLenLevels, newLevels, kNumLenSymbols));\r
+  return m_LenDecoder.SetCodeLengths(newLevels);\r
+}\r
+\r
+class CDecoderFlusher\r
+{\r
+  CDecoder *m_Decoder;\r
+public:\r
+  bool NeedFlush;\r
+  CDecoderFlusher(CDecoder *decoder): m_Decoder(decoder), NeedFlush(true) {}\r
+  ~CDecoderFlusher()\r
+  {\r
+    if (NeedFlush)\r
+      m_Decoder->Flush();\r
+    m_Decoder->ReleaseStreams();\r
+  }\r
+};\r
+\r
+\r
+void CDecoder::ClearPrevLevels()\r
+{\r
+  unsigned i;\r
+  for (i = 0; i < kMainTableSize; i++)\r
+    m_LastMainLevels[i] = 0;\r
+  for (i = 0; i < kNumLenSymbols; i++)\r
+    m_LastLenLevels[i] = 0;\r
+}\r
+\r
+\r
+HRESULT CDecoder::CodeSpec(UInt32 curSize)\r
+{\r
+  if (_remainLen == kLenIdNeedInit)\r
+  {\r
+    _remainLen = 0;\r
+    m_InBitStream.Init();\r
+    if (!_keepHistory || !m_IsUncompressedBlock)\r
+      m_InBitStream.Normalize();\r
+    if (!_keepHistory)\r
+    {\r
+      _skipByte = false;\r
+      m_UnCompressedBlockSize = 0;\r
+      ClearPrevLevels();\r
+      UInt32 i86TranslationSize = 12000000;\r
+      bool translationMode = true;\r
+      if (!_wimMode)\r
+      {\r
+        translationMode = (ReadBits(1) != 0);\r
+        if (translationMode)\r
+        {\r
+          i86TranslationSize = ReadBits(16) << 16;\r
+          i86TranslationSize |= ReadBits(16);\r
+        }\r
+      }\r
+      m_x86ConvertOutStreamSpec->Init(translationMode, i86TranslationSize);\r
+      \r
+      for (unsigned i = 0 ; i < kNumRepDistances; i++)\r
+        m_RepDistances[i] = 0;\r
+    }\r
+  }\r
+\r
+  while (_remainLen > 0 && curSize > 0)\r
+  {\r
+    m_OutWindowStream.PutByte(m_OutWindowStream.GetByte(m_RepDistances[0]));\r
+    _remainLen--;\r
+    curSize--;\r
+  }\r
+\r
+  while (curSize > 0)\r
+  {\r
+    if (m_UnCompressedBlockSize == 0)\r
+      if (!ReadTables())\r
+        return S_FALSE;\r
+    UInt32 next = (Int32)MyMin(m_UnCompressedBlockSize, curSize);\r
+    curSize -= next;\r
+    m_UnCompressedBlockSize -= next;\r
+    if (m_IsUncompressedBlock)\r
+    {\r
+      while (next > 0)\r
+      {\r
+        m_OutWindowStream.PutByte(m_InBitStream.DirectReadByte());\r
+        next--;\r
+      }\r
+    }\r
+    else while (next > 0)\r
+    {\r
+      UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);\r
+      if (number < 256)\r
+      {\r
+        m_OutWindowStream.PutByte((Byte)number);\r
+        next--;\r
+      }\r
+      else\r
+      {\r
+        UInt32 posLenSlot = number - 256;\r
+        if (posLenSlot >= m_NumPosLenSlots)\r
+          return S_FALSE;\r
+        UInt32 posSlot = posLenSlot / kNumLenSlots;\r
+        UInt32 lenSlot = posLenSlot % kNumLenSlots;\r
+        UInt32 len = kMatchMinLen + lenSlot;\r
+        if (lenSlot == kNumLenSlots - 1)\r
+        {\r
+          UInt32 lenTemp = m_LenDecoder.DecodeSymbol(&m_InBitStream);\r
+          if (lenTemp >= kNumLenSymbols)\r
+            return S_FALSE;\r
+          len += lenTemp;\r
+        }\r
+        \r
+        if (posSlot < kNumRepDistances)\r
+        {\r
+          UInt32 distance = m_RepDistances[posSlot];\r
+          m_RepDistances[posSlot] = m_RepDistances[0];\r
+          m_RepDistances[0] = distance;\r
+        }\r
+        else\r
+        {\r
+          UInt32 distance;\r
+          unsigned numDirectBits;\r
+          if (posSlot < kNumPowerPosSlots)\r
+          {\r
+            numDirectBits = (unsigned)(posSlot >> 1) - 1;\r
+            distance = ((2 | (posSlot & 1)) << numDirectBits);\r
+          }\r
+          else\r
+          {\r
+            numDirectBits = kNumLinearPosSlotBits;\r
+            distance = ((posSlot - 0x22) << kNumLinearPosSlotBits);\r
+          }\r
+\r
+          if (m_AlignIsUsed && numDirectBits >= kNumAlignBits)\r
+          {\r
+            distance += (m_InBitStream.ReadBits(numDirectBits - kNumAlignBits) << kNumAlignBits);\r
+            UInt32 alignTemp = m_AlignDecoder.DecodeSymbol(&m_InBitStream);\r
+            if (alignTemp >= kAlignTableSize)\r
+              return S_FALSE;\r
+            distance += alignTemp;\r
+          }\r
+          else\r
+            distance += m_InBitStream.ReadBits(numDirectBits);\r
+          m_RepDistances[2] = m_RepDistances[1];\r
+          m_RepDistances[1] = m_RepDistances[0];\r
+          m_RepDistances[0] = distance - kNumRepDistances;\r
+        }\r
+\r
+        UInt32 locLen = len;\r
+        if (locLen > next)\r
+          locLen = next;\r
+\r
+        if (!m_OutWindowStream.CopyBlock(m_RepDistances[0], locLen))\r
+          return S_FALSE;\r
+\r
+        len -= locLen;\r
+        next -= locLen;\r
+        if (len != 0)\r
+        {\r
+          _remainLen = (int)len;\r
+          return S_OK;\r
+        }\r
+      }\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  if (outSize == NULL)\r
+    return E_INVALIDARG;\r
+  UInt64 size = *outSize;\r
+\r
+  RINOK(SetInStream(inStream));\r
+  m_x86ConvertOutStreamSpec->SetStream(outStream);\r
+  m_OutWindowStream.SetStream(m_x86ConvertOutStream);\r
+  RINOK(SetOutStreamSize(outSize));\r
+\r
+  CDecoderFlusher flusher(this);\r
+\r
+  const UInt64 start = m_OutWindowStream.GetProcessedSize();\r
+  for (;;)\r
+  {\r
+    UInt32 curSize = 1 << 18;\r
+    UInt64 rem = size - (m_OutWindowStream.GetProcessedSize() - start);\r
+    if (curSize > rem)\r
+      curSize = (UInt32)rem;\r
+    if (curSize == 0)\r
+      break;\r
+    RINOK(CodeSpec(curSize));\r
+    if (progress != NULL)\r
+    {\r
+      UInt64 inSize = m_InBitStream.GetProcessedSize();\r
+      UInt64 nowPos64 = m_OutWindowStream.GetProcessedSize() - start;\r
+      RINOK(progress->SetRatioInfo(&inSize, &nowPos64));\r
+    }\r
+  }\r
+  flusher.NeedFlush = false;\r
+  return Flush();\r
+}\r
+\r
+HRESULT CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  try { return CodeReal(inStream, outStream, inSize, outSize, progress); }\r
+  catch(const CLzOutWindowException &e) { return e.ErrorCode; }\r
+  catch(...) { return S_FALSE; }\r
+}\r
+\r
+STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)\r
+{\r
+  m_InBitStream.SetStream(inStream);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CDecoder::ReleaseInStream()\r
+{\r
+  m_InBitStream.ReleaseStream();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)\r
+{\r
+  if (outSize == NULL)\r
+    return E_FAIL;\r
+  _remainLen = kLenIdNeedInit;\r
+  m_OutWindowStream.Init(_keepHistory);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CDecoder::SetParams(unsigned numDictBits)\r
+{\r
+  if (numDictBits < kNumDictionaryBitsMin || numDictBits > kNumDictionaryBitsMax)\r
+    return E_INVALIDARG;\r
+  UInt32 numPosSlots;\r
+  if (numDictBits < 20)\r
+    numPosSlots = 30 + (numDictBits - 15) * 2;\r
+  else if (numDictBits == 20)\r
+    numPosSlots = 42;\r
+  else\r
+    numPosSlots = 50;\r
+  m_NumPosLenSlots = numPosSlots * kNumLenSlots;\r
+  if (!m_OutWindowStream.Create(kDictionarySizeMax))\r
+    return E_OUTOFMEMORY;\r
+  if (!m_InBitStream.Create(1 << 16))\r
+    return E_OUTOFMEMORY;\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Compress/LzxDecoder.h b/CPP/7zip/Compress/LzxDecoder.h
new file mode 100755 (executable)
index 0000000..0cb9aff
--- /dev/null
@@ -0,0 +1,159 @@
+// LzxDecoder.h\r
+\r
+#ifndef __LZX_DECODER_H\r
+#define __LZX_DECODER_H\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "../Common/InBuffer.h"\r
+\r
+#include "HuffmanDecoder.h"\r
+#include "LzOutWindow.h"\r
+#include "Lzx.h"\r
+#include "Lzx86Converter.h"\r
+\r
+namespace NCompress {\r
+namespace NLzx {\r
+\r
+namespace NBitStream {\r
+\r
+const unsigned kNumBigValueBits = 8 * 4;\r
+const unsigned kNumValueBits = 17;\r
+const UInt32 kBitDecoderValueMask = (1 << kNumValueBits) - 1;\r
+\r
+class CDecoder\r
+{\r
+  CInBuffer m_Stream;\r
+  UInt32 m_Value;\r
+  unsigned m_BitPos;\r
+public:\r
+  CDecoder() {}\r
+  bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }\r
+\r
+  void SetStream(ISequentialInStream *s) { m_Stream.SetStream(s); }\r
+  void ReleaseStream() { m_Stream.ReleaseStream(); }\r
+\r
+  void Init()\r
+  {\r
+    m_Stream.Init();\r
+    m_BitPos = kNumBigValueBits;\r
+  }\r
+\r
+  UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() - (kNumBigValueBits - m_BitPos) / 8; }\r
+  \r
+  unsigned GetBitPosition() const { return m_BitPos & 0xF; }\r
+\r
+  void Normalize()\r
+  {\r
+    for (; m_BitPos >= 16; m_BitPos -= 16)\r
+    {\r
+      Byte b0 = m_Stream.ReadByte();\r
+      Byte b1 = m_Stream.ReadByte();\r
+      m_Value = (m_Value << 8) | b1;\r
+      m_Value = (m_Value << 8) | b0;\r
+    }\r
+  }\r
+\r
+  UInt32 GetValue(unsigned numBits) const\r
+  {\r
+    return ((m_Value >> ((32 - kNumValueBits) - m_BitPos)) & kBitDecoderValueMask) >> (kNumValueBits - numBits);\r
+  }\r
+  \r
+  void MovePos(unsigned numBits)\r
+  {\r
+    m_BitPos += numBits;\r
+    Normalize();\r
+  }\r
+\r
+  UInt32 ReadBits(unsigned numBits)\r
+  {\r
+    UInt32 res = GetValue(numBits);\r
+    MovePos(numBits);\r
+    return res;\r
+  }\r
+\r
+  UInt32 ReadBitsBig(unsigned numBits)\r
+  {\r
+    unsigned numBits0 = numBits / 2;\r
+    unsigned numBits1 = numBits - numBits0;\r
+    UInt32 res = ReadBits(numBits0) << numBits1;\r
+    return res + ReadBits(numBits1);\r
+  }\r
+\r
+  bool ReadUInt32(UInt32 &v)\r
+  {\r
+    if (m_BitPos != 0)\r
+      return false;\r
+    v = ((m_Value >> 16) & 0xFFFF) | ((m_Value << 16) & 0xFFFF0000);\r
+    m_BitPos = kNumBigValueBits;\r
+    return true;\r
+  }\r
+\r
+  Byte DirectReadByte() { return m_Stream.ReadByte(); }\r
+\r
+};\r
+}\r
+\r
+class CDecoder :\r
+  public ICompressCoder,\r
+  public CMyUnknownImp\r
+{\r
+  NBitStream::CDecoder m_InBitStream;\r
+  CLzOutWindow m_OutWindowStream;\r
+\r
+  UInt32 m_RepDistances[kNumRepDistances];\r
+  UInt32 m_NumPosLenSlots;\r
+\r
+  bool m_IsUncompressedBlock;\r
+  bool m_AlignIsUsed;\r
+\r
+  NCompress::NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder;\r
+  NCompress::NHuffman::CDecoder<kNumHuffmanBits, kNumLenSymbols> m_LenDecoder;\r
+  NCompress::NHuffman::CDecoder<kNumHuffmanBits, kAlignTableSize> m_AlignDecoder;\r
+  NCompress::NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder;\r
+\r
+  Byte m_LastMainLevels[kMainTableSize];\r
+  Byte m_LastLenLevels[kNumLenSymbols];\r
+\r
+  Cx86ConvertOutStream *m_x86ConvertOutStreamSpec;\r
+  CMyComPtr<ISequentialOutStream> m_x86ConvertOutStream;\r
+\r
+  UInt32 m_UnCompressedBlockSize;\r
+\r
+  bool _keepHistory;\r
+  int _remainLen;\r
+  bool _skipByte;\r
+\r
+  bool _wimMode;\r
+\r
+  UInt32 ReadBits(unsigned numBits);\r
+  bool ReadTable(Byte *lastLevels, Byte *newLevels, UInt32 numSymbols);\r
+  bool ReadTables();\r
+  void ClearPrevLevels();\r
+\r
+  HRESULT CodeSpec(UInt32 size);\r
+\r
+  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+public:\r
+  CDecoder(bool wimMode = false);\r
+\r
+  MY_UNKNOWN_IMP\r
+\r
+  void ReleaseStreams();\r
+  STDMETHOD(Flush)();\r
+\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+  STDMETHOD(SetInStream)(ISequentialInStream *inStream);\r
+  STDMETHOD(ReleaseInStream)();\r
+  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);\r
+\r
+  HRESULT SetParams(unsigned numDictBits);\r
+  void SetKeepHistory(bool keepHistory) {  _keepHistory = keepHistory; }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/Mtf8.h b/CPP/7zip/Compress/Mtf8.h
new file mode 100755 (executable)
index 0000000..c667e3d
--- /dev/null
@@ -0,0 +1,193 @@
+// Mtf8.h\r
+\r
+#ifndef __COMPRESS_MTF8_H\r
+#define __COMPRESS_MTF8_H\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "../../Common/Types.h"\r
+\r
+namespace NCompress {\r
+\r
+struct CMtf8Encoder\r
+{\r
+  Byte Buf[256];\r
+\r
+  int FindAndMove(Byte v)\r
+  {\r
+    int pos;\r
+    for (pos = 0; Buf[pos] != v; pos++);\r
+    int resPos = pos;\r
+    for (; pos >= 8; pos -= 8)\r
+    {\r
+      Buf[pos] = Buf[pos - 1];\r
+      Buf[pos - 1] = Buf[pos - 2];\r
+      Buf[pos - 2] = Buf[pos - 3];\r
+      Buf[pos - 3] = Buf[pos - 4];\r
+      Buf[pos - 4] = Buf[pos - 5];\r
+      Buf[pos - 5] = Buf[pos - 6];\r
+      Buf[pos - 6] = Buf[pos - 7];\r
+      Buf[pos - 7] = Buf[pos - 8];\r
+    }\r
+    for (; pos > 0; pos--)\r
+      Buf[pos] = Buf[pos - 1];\r
+    Buf[0] = v;\r
+    return resPos;\r
+  }\r
+};\r
+\r
+/*\r
+struct CMtf8Decoder\r
+{\r
+  Byte Buf[256];\r
+\r
+  void Init(int) {};\r
+  Byte GetHead() const { return Buf[0]; }\r
+  Byte GetAndMove(int pos)\r
+  {\r
+    Byte res = Buf[pos];\r
+    for (; pos >= 8; pos -= 8)\r
+    {\r
+      Buf[pos] = Buf[pos - 1];\r
+      Buf[pos - 1] = Buf[pos - 2];\r
+      Buf[pos - 2] = Buf[pos - 3];\r
+      Buf[pos - 3] = Buf[pos - 4];\r
+      Buf[pos - 4] = Buf[pos - 5];\r
+      Buf[pos - 5] = Buf[pos - 6];\r
+      Buf[pos - 6] = Buf[pos - 7];\r
+      Buf[pos - 7] = Buf[pos - 8];\r
+    }\r
+    for (; pos > 0; pos--)\r
+      Buf[pos] = Buf[pos - 1];\r
+    Buf[0] = res;\r
+    return res;\r
+  }\r
+};\r
+*/\r
+\r
+#ifdef MY_CPU_64BIT\r
+typedef UInt64 CMtfVar;\r
+#define MTF_MOVS 3\r
+#else\r
+typedef UInt32 CMtfVar;\r
+#define MTF_MOVS 2\r
+#endif\r
+\r
+#define MTF_MASK ((1 << MTF_MOVS) - 1)\r
+\r
+\r
+struct CMtf8Decoder\r
+{\r
+  CMtfVar Buf[256 >> MTF_MOVS];\r
+\r
+  void StartInit() { memset(Buf, 0, sizeof(Buf)); }\r
+  void Add(unsigned int pos, Byte val) { Buf[pos >> MTF_MOVS] |= ((CMtfVar)val << ((pos & MTF_MASK) << 3));  }\r
+  Byte GetHead() const { return (Byte)Buf[0]; }\r
+  Byte GetAndMove(unsigned int pos)\r
+  {\r
+    UInt32 lim = ((UInt32)pos >> MTF_MOVS);\r
+    pos = (pos & MTF_MASK) << 3;\r
+    CMtfVar prev = (Buf[lim] >> pos) & 0xFF;\r
+\r
+    UInt32 i = 0;\r
+    if ((lim & 1) != 0)\r
+    {\r
+      CMtfVar next = Buf[0];\r
+      Buf[0] = (next << 8) | prev;\r
+      prev = (next >> (MTF_MASK << 3));\r
+      i = 1;\r
+      lim -= 1;\r
+    }\r
+    for (; i < lim; i += 2)\r
+    {\r
+      CMtfVar n0 = Buf[i];\r
+      CMtfVar n1 = Buf[i + 1];\r
+      Buf[i    ] = (n0 << 8) | prev;\r
+      Buf[i + 1] = (n1 << 8) | (n0 >> (MTF_MASK << 3));\r
+      prev = (n1 >> (MTF_MASK << 3));\r
+    }\r
+    CMtfVar next = Buf[i];\r
+    CMtfVar mask = (((CMtfVar)0x100 << pos) - 1);\r
+    Buf[i] = (next & ~mask) | (((next << 8) | prev) & mask);\r
+    return (Byte)Buf[0];\r
+  }\r
+};\r
+\r
+/*\r
+const int kSmallSize = 64;\r
+class CMtf8Decoder\r
+{\r
+  Byte SmallBuffer[kSmallSize];\r
+  int SmallSize;\r
+  Byte Counts[16];\r
+  int Size;\r
+public:\r
+  Byte Buf[256];\r
+\r
+  Byte GetHead() const\r
+  {\r
+    if (SmallSize > 0)\r
+      return SmallBuffer[kSmallSize - SmallSize];\r
+    return Buf[0];\r
+  }\r
+\r
+  void Init(int size)\r
+  {\r
+    Size = size;\r
+    SmallSize = 0;\r
+    for (int i = 0; i < 16; i++)\r
+    {\r
+      Counts[i] = ((size >= 16) ? 16 : size);\r
+      size -= Counts[i];\r
+    }\r
+  }\r
+\r
+  Byte GetAndMove(int pos)\r
+  {\r
+    if (pos < SmallSize)\r
+    {\r
+      Byte *p = SmallBuffer + kSmallSize - SmallSize;\r
+      Byte res = p[pos];\r
+      for (; pos > 0; pos--)\r
+        p[pos] = p[pos - 1];\r
+      SmallBuffer[kSmallSize - SmallSize] = res;\r
+      return res;\r
+    }\r
+    if (SmallSize == kSmallSize)\r
+    {\r
+      int i = Size - 1;\r
+      int g = 16;\r
+      do\r
+      {\r
+        g--;\r
+        int offset = (g << 4);\r
+        for (int t = Counts[g] - 1; t >= 0; t--, i--)\r
+          Buf[i] = Buf[offset + t];\r
+      }\r
+      while(g != 0);\r
+      \r
+      for (i = kSmallSize - 1; i >= 0; i--)\r
+        Buf[i] = SmallBuffer[i];\r
+      Init(Size);\r
+    }\r
+    pos -= SmallSize;\r
+    int g;\r
+    for (g = 0; pos >= Counts[g]; g++)\r
+      pos -= Counts[g];\r
+    int offset = (g << 4);\r
+    Byte res = Buf[offset + pos];\r
+    for (pos; pos < 16 - 1; pos++)\r
+      Buf[offset + pos] = Buf[offset + pos + 1];\r
+    \r
+    SmallSize++;\r
+    SmallBuffer[kSmallSize - SmallSize] = res;\r
+\r
+    Counts[g]--;\r
+    return res;\r
+  }\r
+};\r
+*/\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/PpmdDecoder.cpp b/CPP/7zip/Compress/PpmdDecoder.cpp
new file mode 100755 (executable)
index 0000000..2373185
--- /dev/null
@@ -0,0 +1,167 @@
+// PpmdDecoder.cpp\r
+// 2009-03-11 : Igor Pavlov : Public domain\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "PpmdDecoder.h"\r
+\r
+namespace NCompress {\r
+namespace NPpmd {\r
+\r
+static const UInt32 kBufSize = (1 << 20);\r
+\r
+enum\r
+{\r
+  kStatus_NeedInit,\r
+  kStatus_Normal,\r
+  kStatus_Finished,\r
+  kStatus_Error\r
+};\r
+\r
+static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }\r
+static void SzBigFree(void *, void *address) { BigFree(address); }\r
+static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };\r
+\r
+CDecoder::~CDecoder()\r
+{\r
+  ::MidFree(_outBuf);\r
+  Ppmd7_Free(&_ppmd, &g_BigAlloc);\r
+}\r
+\r
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size)\r
+{\r
+  if (size < 5)\r
+    return E_INVALIDARG;\r
+  _order = props[0];\r
+  UInt32 memSize = GetUi32(props + 1);\r
+  if (_order < PPMD7_MIN_ORDER ||\r
+      _order > PPMD7_MAX_ORDER ||\r
+      memSize < PPMD7_MIN_MEM_SIZE ||\r
+      memSize > PPMD7_MAX_MEM_SIZE)\r
+    return E_NOTIMPL;\r
+  if (!_inStream.Alloc(1 << 20))\r
+    return E_OUTOFMEMORY;\r
+  if (!Ppmd7_Alloc(&_ppmd, memSize, &g_BigAlloc))\r
+    return E_OUTOFMEMORY;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size)\r
+{\r
+  switch(_status)\r
+  {\r
+    case kStatus_Finished: return S_OK;\r
+    case kStatus_Error: return S_FALSE;\r
+    case kStatus_NeedInit:\r
+      _inStream.Init();\r
+      if (!Ppmd7z_RangeDec_Init(&_rangeDec))\r
+      {\r
+        _status = kStatus_Error;\r
+        return S_FALSE;\r
+      }\r
+      _status = kStatus_Normal;\r
+      Ppmd7_Init(&_ppmd, _order);\r
+      break;\r
+  }\r
+  if (_outSizeDefined)\r
+  {\r
+    const UInt64 rem = _outSize - _processedSize;\r
+    if (size > rem)\r
+      size = (UInt32)rem;\r
+  }\r
+\r
+  UInt32 i;\r
+  int sym = 0;\r
+  for (i = 0; i != size; i++)\r
+  {\r
+    sym = Ppmd7_DecodeSymbol(&_ppmd, &_rangeDec.p);\r
+    if (_inStream.Extra || sym < 0)\r
+      break;\r
+    memStream[i] = (Byte)sym;\r
+  }\r
+\r
+  _processedSize += i;\r
+  if (_inStream.Extra)\r
+  {\r
+    _status = kStatus_Error;\r
+    return _inStream.Res;\r
+  }\r
+  if (sym < 0)\r
+    _status = (sym < -1) ? kStatus_Error : kStatus_Finished;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  if (!_outBuf)\r
+  {\r
+    _outBuf = (Byte *)::MidAlloc(kBufSize);\r
+    if (!_outBuf)\r
+      return E_OUTOFMEMORY;\r
+  }\r
+  \r
+  _inStream.Stream = inStream;\r
+  SetOutStreamSize(outSize);\r
+\r
+  do\r
+  {\r
+    const UInt64 startPos = _processedSize;\r
+    HRESULT res = CodeSpec(_outBuf, kBufSize);\r
+    size_t processed = (size_t)(_processedSize - startPos);\r
+    RINOK(WriteStream(outStream, _outBuf, processed));\r
+    RINOK(res);\r
+    if (_status == kStatus_Finished)\r
+      break;\r
+    if (progress)\r
+    {\r
+      UInt64 inSize = _inStream.GetProcessed();\r
+      RINOK(progress->SetRatioInfo(&inSize, &_processedSize));\r
+    }\r
+  }\r
+  while (!_outSizeDefined || _processedSize < _outSize);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)\r
+{\r
+  _outSizeDefined = (outSize != NULL);\r
+  if (_outSizeDefined)\r
+    _outSize = *outSize;\r
+  _processedSize = 0;\r
+  _status = kStatus_NeedInit;\r
+  return S_OK;\r
+}\r
+\r
+#ifndef NO_READ_FROM_CODER\r
+\r
+STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)\r
+{\r
+  InSeqStream = inStream;\r
+  _inStream.Stream = inStream;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CDecoder::ReleaseInStream()\r
+{\r
+  InSeqStream.Release();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  const UInt64 startPos = _processedSize;\r
+  HRESULT res = CodeSpec((Byte *)data, size);\r
+  if (processedSize)\r
+    *processedSize = (UInt32)(_processedSize - startPos);\r
+  return res;\r
+}\r
+\r
+#endif\r
+\r
+}}\r
diff --git a/CPP/7zip/Compress/PpmdDecoder.h b/CPP/7zip/Compress/PpmdDecoder.h
new file mode 100755 (executable)
index 0000000..c61d1d0
--- /dev/null
@@ -0,0 +1,78 @@
+// PpmdDecoder.h\r
+// 2009-03-11 : Igor Pavlov : Public domain\r
+\r
+#ifndef __COMPRESS_PPMD_DECODER_H\r
+#define __COMPRESS_PPMD_DECODER_H\r
+\r
+#include "../../../C/Ppmd7.h"\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../Common/CWrappers.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+namespace NCompress {\r
+namespace NPpmd {\r
+\r
+class CDecoder :\r
+  public ICompressCoder,\r
+  public ICompressSetDecoderProperties2,\r
+  #ifndef NO_READ_FROM_CODER\r
+  public ICompressSetInStream,\r
+  public ICompressSetOutStreamSize,\r
+  public ISequentialInStream,\r
+  #endif\r
+  public CMyUnknownImp\r
+{\r
+  Byte *_outBuf;\r
+  CPpmd7z_RangeDec _rangeDec;\r
+  CByteInBufWrap _inStream;\r
+  CPpmd7 _ppmd;\r
+\r
+  Byte _order;\r
+  bool _outSizeDefined;\r
+  int _status;\r
+  UInt64 _outSize;\r
+  UInt64 _processedSize;\r
+\r
+  HRESULT CodeSpec(Byte *memStream, UInt32 size);\r
+\r
+public:\r
+\r
+  #ifndef NO_READ_FROM_CODER\r
+  CMyComPtr<ISequentialInStream> InSeqStream;\r
+  MY_UNKNOWN_IMP4(\r
+      ICompressSetDecoderProperties2,\r
+      ICompressSetInStream,\r
+      ICompressSetOutStreamSize,\r
+      ISequentialInStream)\r
+  #else\r
+  MY_UNKNOWN_IMP1(\r
+      ICompressSetDecoderProperties2)\r
+  #endif\r
+\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);\r
+  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);\r
+\r
+  #ifndef NO_READ_FROM_CODER\r
+  STDMETHOD(SetInStream)(ISequentialInStream *inStream);\r
+  STDMETHOD(ReleaseInStream)();\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  #endif\r
+\r
+  CDecoder(): _outBuf(NULL), _outSizeDefined(false)\r
+  {\r
+    Ppmd7z_RangeDec_CreateVTable(&_rangeDec);\r
+    _rangeDec.Stream = &_inStream.p;\r
+    Ppmd7_Construct(&_ppmd);\r
+  }\r
+\r
+  ~CDecoder();\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/PpmdEncoder.cpp b/CPP/7zip/Compress/PpmdEncoder.cpp
new file mode 100755 (executable)
index 0000000..3a8df78
--- /dev/null
@@ -0,0 +1,119 @@
+// PpmdEncoder.cpp\r
+// 2009-03-11 : Igor Pavlov : Public domain\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "PpmdEncoder.h"\r
+\r
+namespace NCompress {\r
+namespace NPpmd {\r
+\r
+static const UInt32 kBufSize = (1 << 20);\r
+\r
+static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }\r
+static void SzBigFree(void *, void *address) { BigFree(address); }\r
+static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };\r
+\r
+CEncoder::CEncoder():\r
+  _inBuf(NULL),\r
+  _usedMemSize(1 << 24),\r
+  _order(6)\r
+{\r
+  _rangeEnc.Stream = &_outStream.p;\r
+  Ppmd7_Construct(&_ppmd);\r
+}\r
+\r
+CEncoder::~CEncoder()\r
+{\r
+  ::MidFree(_inBuf);\r
+  Ppmd7_Free(&_ppmd, &g_BigAlloc);\r
+}\r
+\r
+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)\r
+{\r
+  for (UInt32 i = 0; i < numProps; i++)\r
+  {\r
+    const PROPVARIANT &prop = props[i];\r
+    if (prop.vt != VT_UI4)\r
+      return E_INVALIDARG;\r
+    UInt32 v = (UInt32)prop.ulVal;\r
+    switch(propIDs[i])\r
+    {\r
+      case NCoderPropID::kUsedMemorySize:\r
+        if (v < (1 << 16) || v > PPMD7_MAX_MEM_SIZE || (v & 3) != 0)\r
+          return E_INVALIDARG;\r
+        _usedMemSize = v;\r
+        break;\r
+      case NCoderPropID::kOrder:\r
+        if (v < 2 || v > 32)\r
+          return E_INVALIDARG;\r
+        _order = (Byte)v;\r
+        break;\r
+      default:\r
+        return E_INVALIDARG;\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)\r
+{\r
+  const UInt32 kPropSize = 5;\r
+  Byte props[kPropSize];\r
+  props[0] = _order;\r
+  SetUi32(props + 1, _usedMemSize);\r
+  return WriteStream(outStream, props, kPropSize);\r
+}\r
+\r
+HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)\r
+{\r
+  if (!_inBuf)\r
+  {\r
+    _inBuf = (Byte *)::MidAlloc(kBufSize);\r
+    if (!_inBuf)\r
+      return E_OUTOFMEMORY;\r
+  }\r
+  if (!_outStream.Alloc(1 << 20))\r
+    return E_OUTOFMEMORY;\r
+  if (!Ppmd7_Alloc(&_ppmd, _usedMemSize, &g_BigAlloc))\r
+    return E_OUTOFMEMORY;\r
+\r
+  _outStream.Stream = outStream;\r
+  _outStream.Init();\r
+\r
+  Ppmd7z_RangeEnc_Init(&_rangeEnc);\r
+  Ppmd7_Init(&_ppmd, _order);\r
+\r
+  UInt64 processed = 0;\r
+  for (;;)\r
+  {\r
+    UInt32 size;\r
+    RINOK(inStream->Read(_inBuf, kBufSize, &size));\r
+    if (size == 0)\r
+    {\r
+      // We don't write EndMark in PPMD-7z.\r
+      // Ppmd7_EncodeSymbol(&_ppmd, &_rangeEnc, -1);\r
+      Ppmd7z_RangeEnc_FlushData(&_rangeEnc);\r
+      return _outStream.Flush();\r
+    }\r
+    for (UInt32 i = 0; i < size; i++)\r
+    {\r
+      Ppmd7_EncodeSymbol(&_ppmd, &_rangeEnc, _inBuf[i]);\r
+      RINOK(_outStream.Res);\r
+    }\r
+    processed += size;\r
+    if (progress)\r
+    {\r
+      UInt64 outSize = _outStream.GetProcessed();\r
+      RINOK(progress->SetRatioInfo(&processed, &outSize));\r
+    }\r
+  }\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Compress/PpmdEncoder.h b/CPP/7zip/Compress/PpmdEncoder.h
new file mode 100755 (executable)
index 0000000..9feb93d
--- /dev/null
@@ -0,0 +1,48 @@
+// PpmdEncoder.h\r
+// 2009-03-11 : Igor Pavlov : Public domain\r
+\r
+#ifndef __COMPRESS_PPMD_ENCODER_H\r
+#define __COMPRESS_PPMD_ENCODER_H\r
+\r
+#include "../../../C/Ppmd7.h"\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "../Common/CWrappers.h"\r
+\r
+namespace NCompress {\r
+namespace NPpmd {\r
+\r
+class CEncoder :\r
+  public ICompressCoder,\r
+  public ICompressSetCoderProperties,\r
+  public ICompressWriteCoderProperties,\r
+  public CMyUnknownImp\r
+{\r
+  Byte *_inBuf;\r
+  CByteOutBufWrap _outStream;\r
+  CPpmd7z_RangeEnc _rangeEnc;\r
+  CPpmd7 _ppmd;\r
+\r
+  UInt32 _usedMemSize;\r
+  Byte _order;\r
+\r
+public:\r
+  MY_UNKNOWN_IMP2(\r
+      ICompressSetCoderProperties,\r
+      ICompressWriteCoderProperties)\r
+\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);\r
+  STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);\r
+\r
+  CEncoder();\r
+  ~CEncoder();\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/PpmdRegister.cpp b/CPP/7zip/Compress/PpmdRegister.cpp
new file mode 100755 (executable)
index 0000000..e2fd007
--- /dev/null
@@ -0,0 +1,21 @@
+// PpmdRegister.cpp\r
+// 2009-05-30 : Igor Pavlov : Public domain\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../Common/RegisterCodec.h"\r
+\r
+#include "PpmdDecoder.h"\r
+\r
+static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NPpmd::CDecoder); }\r
+#ifndef EXTRACT_ONLY\r
+#include "PpmdEncoder.h"\r
+static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NPpmd::CEncoder);  }\r
+#else\r
+#define CreateCodecOut 0\r
+#endif\r
+\r
+static CCodecInfo g_CodecInfo =\r
+  { CreateCodec, CreateCodecOut, 0x030401, L"PPMD", 1, false };\r
+\r
+REGISTER_CODEC(PPMD)\r
diff --git a/CPP/7zip/Compress/PpmdZip.cpp b/CPP/7zip/Compress/PpmdZip.cpp
new file mode 100755 (executable)
index 0000000..6356e87
--- /dev/null
@@ -0,0 +1,223 @@
+// PpmdZip.cpp\r
+// 2010-03-24 : Igor Pavlov : Public domain\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "PpmdZip.h"\r
+\r
+namespace NCompress {\r
+namespace NPpmdZip {\r
+\r
+static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }\r
+static void SzBigFree(void *, void *address) { BigFree(address); }\r
+static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };\r
+\r
+CDecoder::CDecoder(bool fullFileMode):\r
+  _fullFileMode(fullFileMode)\r
+{\r
+  _ppmd.Stream.In = &_inStream.p;\r
+  Ppmd8_Construct(&_ppmd);\r
+}\r
+\r
+CDecoder::~CDecoder()\r
+{\r
+  Ppmd8_Free(&_ppmd, &g_BigAlloc);\r
+}\r
+\r
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  if (!_outStream.Alloc())\r
+    return E_OUTOFMEMORY;\r
+  if (!_inStream.Alloc(1 << 20))\r
+    return E_OUTOFMEMORY;\r
+\r
+  _inStream.Stream = inStream;\r
+  _inStream.Init();\r
+\r
+  {\r
+    Byte buf[2];\r
+    for (int i = 0; i < 2; i++)\r
+      buf[i] = _inStream.ReadByte();\r
+    if (_inStream.Extra)\r
+      return S_FALSE;\r
+    \r
+    UInt32 val = GetUi16(buf);\r
+    UInt32 order = (val & 0xF) + 1;\r
+    UInt32 mem = ((val >> 4) & 0xFF) + 1;\r
+    UInt32 restor = (val >> 12);\r
+    if (order < 2 || restor > 2)\r
+      return S_FALSE;\r
+    \r
+    #ifndef PPMD8_FREEZE_SUPPORT\r
+    if (restor == 2)\r
+      return E_NOTIMPL;\r
+    #endif\r
+    \r
+    if (!Ppmd8_Alloc(&_ppmd, mem << 20, &g_BigAlloc))\r
+      return E_OUTOFMEMORY;\r
+    \r
+    if (!Ppmd8_RangeDec_Init(&_ppmd))\r
+      return S_FALSE;\r
+    Ppmd8_Init(&_ppmd, order, restor);\r
+  }\r
+\r
+  bool wasFinished = false;\r
+  UInt64 processedSize = 0;\r
+  while (!outSize || processedSize < *outSize)\r
+  {\r
+    size_t size = kBufSize;\r
+    if (outSize != NULL)\r
+    {\r
+      const UInt64 rem = *outSize - processedSize;\r
+      if (size > rem)\r
+        size = (size_t)rem;\r
+    }\r
+    Byte *data = _outStream.Buf;\r
+    size_t i = 0;\r
+    int sym = 0;\r
+    do\r
+    {\r
+      sym = Ppmd8_DecodeSymbol(&_ppmd);\r
+      if (_inStream.Extra || sym < 0)\r
+        break;\r
+      data[i] = (Byte)sym;\r
+    }\r
+    while (++i != size);\r
+    processedSize += i;\r
+\r
+    RINOK(WriteStream(outStream, _outStream.Buf, i));\r
+\r
+    RINOK(_inStream.Res);\r
+    if (_inStream.Extra)\r
+      return S_FALSE;\r
+\r
+    if (sym < 0)\r
+    {\r
+      if (sym != -1)\r
+        return S_FALSE;\r
+      wasFinished = true;\r
+      break;\r
+    }\r
+    if (progress)\r
+    {\r
+      UInt64 inSize = _inStream.GetProcessed();\r
+      RINOK(progress->SetRatioInfo(&inSize, &processedSize));\r
+    }\r
+  }\r
+  RINOK(_inStream.Res);\r
+  if (_fullFileMode)\r
+  {\r
+    if (!wasFinished)\r
+    {\r
+      int res = Ppmd8_DecodeSymbol(&_ppmd);\r
+      RINOK(_inStream.Res);\r
+      if (_inStream.Extra || res != -1)\r
+        return S_FALSE;\r
+    }\r
+    if (!Ppmd8_RangeDec_IsFinishedOK(&_ppmd))\r
+      return S_FALSE;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+\r
+// ---------- Encoder ----------\r
+\r
+CEncoder::~CEncoder()\r
+{\r
+  Ppmd8_Free(&_ppmd, &g_BigAlloc);\r
+}\r
+\r
+HRESULT CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)\r
+{\r
+  for (UInt32 i = 0; i < numProps; i++)\r
+  {\r
+    const PROPVARIANT &prop = props[i];\r
+    if (prop.vt != VT_UI4)\r
+      return E_INVALIDARG;\r
+    UInt32 v = (UInt32)prop.ulVal;\r
+    switch(propIDs[i])\r
+    {\r
+      case NCoderPropID::kAlgorithm:\r
+        if (v > 1)\r
+          return E_INVALIDARG;\r
+        _restor = v;\r
+        break;\r
+      case NCoderPropID::kUsedMemorySize:\r
+        if (v < (1 << 20) || v > (1 << 28))\r
+          return E_INVALIDARG;\r
+        _usedMemInMB = v >> 20;\r
+        break;\r
+      case NCoderPropID::kOrder:\r
+        if (v < PPMD8_MIN_ORDER || v > PPMD8_MAX_ORDER)\r
+          return E_INVALIDARG;\r
+        _order = (Byte)v;\r
+        break;\r
+      default:\r
+        return E_INVALIDARG;\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+CEncoder::CEncoder():\r
+  _usedMemInMB(16),\r
+  _order(6),\r
+  _restor(PPMD8_RESTORE_METHOD_RESTART)\r
+{\r
+  _ppmd.Stream.Out = &_outStream.p;\r
+  Ppmd8_Construct(&_ppmd);\r
+}\r
+\r
+HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)\r
+{\r
+  if (!_inStream.Alloc())\r
+    return E_OUTOFMEMORY;\r
+  if (!_outStream.Alloc(1 << 20))\r
+    return E_OUTOFMEMORY;\r
+  if (!Ppmd8_Alloc(&_ppmd, _usedMemInMB << 20, &g_BigAlloc))\r
+    return E_OUTOFMEMORY;\r
+\r
+  _outStream.Stream = outStream;\r
+  _outStream.Init();\r
+\r
+  Ppmd8_RangeEnc_Init(&_ppmd);\r
+  Ppmd8_Init(&_ppmd, _order, _restor);\r
+\r
+  UInt32 val = (UInt32)((_order - 1) + ((_usedMemInMB - 1) << 4) + (_restor << 12));\r
+  _outStream.WriteByte((Byte)(val & 0xFF));\r
+  _outStream.WriteByte((Byte)(val >> 8));\r
+  RINOK(_outStream.Res);\r
+\r
+  UInt64 processed = 0;\r
+  for (;;)\r
+  {\r
+    UInt32 size;\r
+    RINOK(inStream->Read(_inStream.Buf, kBufSize, &size));\r
+    if (size == 0)\r
+    {\r
+      Ppmd8_EncodeSymbol(&_ppmd, -1);\r
+      Ppmd8_RangeEnc_FlushData(&_ppmd);\r
+      return _outStream.Flush();\r
+    }\r
+    for (UInt32 i = 0; i < size; i++)\r
+    {\r
+      Ppmd8_EncodeSymbol(&_ppmd, _inStream.Buf[i]);\r
+      RINOK(_outStream.Res);\r
+    }\r
+    processed += size;\r
+    if (progress != NULL)\r
+    {\r
+      UInt64 outSize = _outStream.GetProcessed();\r
+      RINOK(progress->SetRatioInfo(&processed, &outSize));\r
+    }\r
+  }\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Compress/PpmdZip.h b/CPP/7zip/Compress/PpmdZip.h
new file mode 100755 (executable)
index 0000000..5614de2
--- /dev/null
@@ -0,0 +1,72 @@
+// PpmdZip.h\r
+// 2010-03-11 : Igor Pavlov : Public domain\r
+\r
+#ifndef __COMPRESS_PPMD_ZIP_H\r
+#define __COMPRESS_PPMD_ZIP_H\r
+\r
+#include "../../../C/Alloc.h"\r
+#include "../../../C/Ppmd8.h"\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../Common/CWrappers.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+namespace NCompress {\r
+namespace NPpmdZip {\r
+\r
+static const UInt32 kBufSize = (1 << 20);\r
+\r
+struct CBuf\r
+{\r
+  Byte *Buf;\r
+  \r
+  CBuf(): Buf(0) {}\r
+  ~CBuf() { ::MidFree(Buf); }\r
+  bool Alloc()\r
+  {\r
+    if (!Buf)\r
+      Buf = (Byte *)::MidAlloc(kBufSize);\r
+    return (Buf != 0);\r
+  }\r
+};\r
+\r
+class CDecoder :\r
+  public ICompressCoder,\r
+  public CMyUnknownImp\r
+{\r
+  CByteInBufWrap _inStream;\r
+  CBuf _outStream;\r
+  CPpmd8 _ppmd;\r
+  bool _fullFileMode;\r
+public:\r
+  MY_UNKNOWN_IMP\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+  CDecoder(bool fullFileMode);\r
+  ~CDecoder();\r
+};\r
+\r
+class CEncoder :\r
+  public ICompressCoder,\r
+  public CMyUnknownImp\r
+{\r
+  CByteOutBufWrap _outStream;\r
+  CBuf _inStream;\r
+  CPpmd8 _ppmd;\r
+  UInt32 _usedMemInMB;\r
+  unsigned _order;\r
+  unsigned _restor;\r
+public:\r
+  MY_UNKNOWN_IMP\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+  HRESULT SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);\r
+  CEncoder();\r
+  ~CEncoder();\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/QuantumDecoder.cpp b/CPP/7zip/Compress/QuantumDecoder.cpp
new file mode 100755 (executable)
index 0000000..e80f403
--- /dev/null
@@ -0,0 +1,175 @@
+// QuantumDecoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../Common/Defs.h"\r
+\r
+#include "QuantumDecoder.h"\r
+\r
+namespace NCompress {\r
+namespace NQuantum {\r
+\r
+static const int kLenIdNeedInit = -2;\r
+\r
+static const unsigned kNumLenSymbols = 27;\r
+static const unsigned kMatchMinLen = 3;\r
+static const unsigned kNumSimplePosSlots = 4;\r
+static const unsigned kNumSimpleLenSlots = 6;\r
+\r
+void CDecoder::Init()\r
+{\r
+  m_Selector.Init(kNumSelectors);\r
+  unsigned i;\r
+  for (i = 0; i < kNumLitSelectors; i++)\r
+    m_Literals[i].Init(kNumLitSymbols);\r
+  unsigned numItems = (_numDictBits == 0 ? 1 : (_numDictBits << 1));\r
+  const unsigned kNumPosSymbolsMax[kNumMatchSelectors] = { 24, 36, 42 };\r
+  for (i = 0; i < kNumMatchSelectors; i++)\r
+    m_PosSlot[i].Init(MyMin(numItems, kNumPosSymbolsMax[i]));\r
+  m_LenSlot.Init(kNumLenSymbols);\r
+}\r
+\r
+HRESULT CDecoder::CodeSpec(UInt32 curSize)\r
+{\r
+  if (_remainLen == kLenIdNeedInit)\r
+  {\r
+    if (!_keepHistory)\r
+    {\r
+      if (!_outWindowStream.Create((UInt32)1 << _numDictBits))\r
+        return E_OUTOFMEMORY;\r
+      Init();\r
+    }\r
+    if (!_rangeDecoder.Create(1 << 20))\r
+      return E_OUTOFMEMORY;\r
+    _rangeDecoder.Init();\r
+    _remainLen = 0;\r
+  }\r
+  if (curSize == 0)\r
+    return S_OK;\r
+\r
+  while (_remainLen > 0 && curSize > 0)\r
+  {\r
+    _remainLen--;\r
+    Byte b = _outWindowStream.GetByte(_rep0);\r
+    _outWindowStream.PutByte(b);\r
+    curSize--;\r
+  }\r
+\r
+  while (curSize > 0)\r
+  {\r
+    if (_rangeDecoder.Stream.WasFinished())\r
+      return S_FALSE;\r
+\r
+    unsigned selector = m_Selector.Decode(&_rangeDecoder);\r
+    if (selector < kNumLitSelectors)\r
+    {\r
+      Byte b = (Byte)((selector << (8 - kNumLitSelectorBits)) + m_Literals[selector].Decode(&_rangeDecoder));\r
+      _outWindowStream.PutByte(b);\r
+      curSize--;\r
+    }\r
+    else\r
+    {\r
+      selector -= kNumLitSelectors;\r
+      unsigned len = selector + kMatchMinLen;\r
+      if (selector == 2)\r
+      {\r
+        unsigned lenSlot = m_LenSlot.Decode(&_rangeDecoder);\r
+        if (lenSlot >= kNumSimpleLenSlots)\r
+        {\r
+          lenSlot -= 2;\r
+          int numDirectBits = (int)(lenSlot >> 2);\r
+          len +=  ((4 | (lenSlot & 3)) << numDirectBits) - 2;\r
+          if (numDirectBits < 6)\r
+            len += _rangeDecoder.Stream.ReadBits(numDirectBits);\r
+        }\r
+        else\r
+          len += lenSlot;\r
+      }\r
+      UInt32 rep0 = m_PosSlot[selector].Decode(&_rangeDecoder);\r
+      if (rep0 >= kNumSimplePosSlots)\r
+      {\r
+        int numDirectBits = (int)((rep0 >> 1) - 1);\r
+        rep0 = ((2 | (rep0 & 1)) << numDirectBits) + _rangeDecoder.Stream.ReadBits(numDirectBits);\r
+      }\r
+      unsigned locLen = len;\r
+      if (len > curSize)\r
+        locLen = (unsigned)curSize;\r
+      if (!_outWindowStream.CopyBlock(rep0, locLen))\r
+        return S_FALSE;\r
+      curSize -= locLen;\r
+      len -= locLen;\r
+      if (len != 0)\r
+      {\r
+        _remainLen = (int)len;\r
+        _rep0 = rep0;\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  return _rangeDecoder.Stream.WasFinished() ? S_FALSE : S_OK;\r
+}\r
+\r
+HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  if (outSize == NULL)\r
+    return E_INVALIDARG;\r
+  UInt64 size = *outSize;\r
+\r
+  SetInStream(inStream);\r
+  _outWindowStream.SetStream(outStream);\r
+  SetOutStreamSize(outSize);\r
+  CDecoderFlusher flusher(this);\r
+\r
+  const UInt64 start = _outWindowStream.GetProcessedSize();\r
+  for (;;)\r
+  {\r
+    UInt32 curSize = 1 << 18;\r
+    UInt64 rem = size - (_outWindowStream.GetProcessedSize() - start);\r
+    if (curSize > rem)\r
+      curSize = (UInt32)rem;\r
+    if (curSize == 0)\r
+      break;\r
+    RINOK(CodeSpec(curSize));\r
+    if (progress != NULL)\r
+    {\r
+      UInt64 inSize = _rangeDecoder.GetProcessedSize();\r
+      UInt64 nowPos64 = _outWindowStream.GetProcessedSize() - start;\r
+      RINOK(progress->SetRatioInfo(&inSize, &nowPos64));\r
+    }\r
+  }\r
+  flusher.NeedFlush = false;\r
+  return Flush();\r
+}\r
+\r
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  try  { return CodeReal(inStream, outStream, inSize, outSize, progress); }\r
+  catch(const CInBufferException &e)  { return e.ErrorCode; }\r
+  catch(const CLzOutWindowException &e)  { return e.ErrorCode; }\r
+  catch(...) { return S_FALSE; }\r
+}\r
+\r
+STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)\r
+{\r
+  _rangeDecoder.SetStream(inStream);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CDecoder::ReleaseInStream()\r
+{\r
+  _rangeDecoder.ReleaseStream();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)\r
+{\r
+  if (outSize == NULL)\r
+    return E_FAIL;\r
+  _remainLen = kLenIdNeedInit;\r
+  _outWindowStream.Init(_keepHistory);\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Compress/QuantumDecoder.h b/CPP/7zip/Compress/QuantumDecoder.h
new file mode 100755 (executable)
index 0000000..585eeef
--- /dev/null
@@ -0,0 +1,264 @@
+// QuantumDecoder.h\r
+\r
+#ifndef __COMPRESS_QUANTUM_DECODER_H\r
+#define __COMPRESS_QUANTUM_DECODER_H\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "../Common/InBuffer.h"\r
+\r
+#include "LzOutWindow.h"\r
+\r
+namespace NCompress {\r
+namespace NQuantum {\r
+\r
+class CStreamBitDecoder\r
+{\r
+  UInt32 Value;\r
+  CInBuffer Stream;\r
+public:\r
+  bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }\r
+  void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); }\r
+  void ReleaseStream() { Stream.ReleaseStream(); }\r
+\r
+  void Finish() { Value = 0x10000; }\r
+\r
+  void Init()\r
+  {\r
+    Stream.Init();\r
+    Value = 0x10000;\r
+  }\r
+\r
+  UInt64 GetProcessedSize() const { return Stream.GetProcessedSize(); }\r
+  bool WasFinished() const { return Stream.WasFinished(); }\r
+  \r
+  UInt32 ReadBit()\r
+  {\r
+    if (Value >= 0x10000)\r
+      Value = 0x100 | Stream.ReadByte();\r
+    UInt32 res = (Value >> 7) & 1;\r
+    Value <<= 1;\r
+    return res;\r
+  }\r
+\r
+  UInt32 ReadBits(int numBits) // numBits > 0\r
+  {\r
+    UInt32 res = 0;\r
+    do\r
+      res = (res << 1) | ReadBit();\r
+    while (--numBits != 0);\r
+    return res;\r
+  }\r
+};\r
+\r
+const unsigned kNumLitSelectorBits = 2;\r
+const unsigned kNumLitSelectors = (1 << kNumLitSelectorBits);\r
+const unsigned kNumLitSymbols = 1 << (8 - kNumLitSelectorBits);\r
+const unsigned kNumMatchSelectors = 3;\r
+const unsigned kNumSelectors = kNumLitSelectors + kNumMatchSelectors;\r
+const unsigned kNumSymbolsMax = kNumLitSymbols; // 64\r
+\r
+namespace NRangeCoder {\r
+\r
+class CDecoder\r
+{\r
+  UInt32 Low;\r
+  UInt32 Range;\r
+  UInt32 Code;\r
+public:\r
+  CStreamBitDecoder Stream;\r
+  bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }\r
+  void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); }\r
+  void ReleaseStream() { Stream.ReleaseStream(); }\r
+\r
+  void Init()\r
+  {\r
+    Stream.Init();\r
+    Low = 0;\r
+    Range = 0x10000;\r
+    Code = Stream.ReadBits(16);\r
+  }\r
+\r
+  void Finish()\r
+  {\r
+    // we need these extra two Bit_reads\r
+    Stream.ReadBit();\r
+    Stream.ReadBit();\r
+    Stream.Finish();\r
+  }\r
+\r
+  UInt64 GetProcessedSize() const { return Stream.GetProcessedSize(); }\r
+\r
+  UInt32 GetThreshold(UInt32 total) const\r
+  {\r
+    return ((Code + 1) * total - 1) / Range; // & 0xFFFF is not required;\r
+  }\r
+\r
+  void Decode(UInt32 start, UInt32 end, UInt32 total)\r
+  {\r
+    UInt32 high = Low + end * Range / total - 1;\r
+    UInt32 offset = start * Range / total;\r
+    Code -= offset;\r
+    Low += offset;\r
+    for (;;)\r
+    {\r
+      if ((Low & 0x8000) != (high & 0x8000))\r
+      {\r
+        if ((Low & 0x4000) == 0 || (high & 0x4000) != 0)\r
+          break;\r
+        Low &= 0x3FFF;\r
+        high |= 0x4000;\r
+      }\r
+      Low = (Low << 1) & 0xFFFF;\r
+      high = ((high << 1) | 1) & 0xFFFF;\r
+      Code = ((Code << 1) | Stream.ReadBit());\r
+    }\r
+    Range = high - Low + 1;\r
+  }\r
+};\r
+\r
+const UInt16 kUpdateStep = 8;\r
+const UInt16 kFreqSumMax = 3800;\r
+const UInt16 kReorderCountStart = 4;\r
+const UInt16 kReorderCount = 50;\r
+\r
+class CModelDecoder\r
+{\r
+  unsigned NumItems;\r
+  unsigned ReorderCount;\r
+  UInt16 Freqs[kNumSymbolsMax + 1];\r
+  Byte Values[kNumSymbolsMax];\r
+public:\r
+  void Init(unsigned numItems)\r
+  {\r
+    NumItems = numItems;\r
+    ReorderCount = kReorderCountStart;\r
+    for (unsigned i = 0; i < numItems; i++)\r
+    {\r
+      Freqs[i] = (UInt16)(numItems - i);\r
+      Values[i] = (Byte)i;\r
+    }\r
+    Freqs[numItems] = 0;\r
+  }\r
+  \r
+  unsigned Decode(CDecoder *rangeDecoder)\r
+  {\r
+    UInt32 threshold = rangeDecoder->GetThreshold(Freqs[0]);\r
+    unsigned i;\r
+    for (i = 1; Freqs[i] > threshold; i++);\r
+    rangeDecoder->Decode(Freqs[i], Freqs[i - 1], Freqs[0]);\r
+    unsigned res = Values[--i];\r
+    do\r
+      Freqs[i] += kUpdateStep;\r
+    while (i-- != 0);\r
+\r
+    if (Freqs[0] > kFreqSumMax)\r
+    {\r
+      if (--ReorderCount == 0)\r
+      {\r
+        ReorderCount = kReorderCount;\r
+        for (i = 0; i < NumItems; i++)\r
+          Freqs[i] = (UInt16)(((Freqs[i] - Freqs[i + 1]) + 1) >> 1);\r
+        for (i = 0; i < NumItems - 1; i++)\r
+          for (unsigned j = i + 1; j < NumItems; j++)\r
+            if (Freqs[i] < Freqs[j])\r
+            {\r
+              UInt16 tmpFreq = Freqs[i];\r
+              Byte tmpVal = Values[i];\r
+              Freqs[i] = Freqs[j];\r
+              Values[i] = Values[j];\r
+              Freqs[j] = tmpFreq;\r
+              Values[j] = tmpVal;\r
+            }\r
+        do\r
+          Freqs[i] = (UInt16)(Freqs[i] + Freqs[i + 1]);\r
+        while (i-- != 0);\r
+      }\r
+      else\r
+      {\r
+        i = NumItems - 1;\r
+        do\r
+        {\r
+          Freqs[i] >>= 1;\r
+          if (Freqs[i] <= Freqs[i + 1])\r
+            Freqs[i] = (UInt16)(Freqs[i + 1] + 1);\r
+        }\r
+        while (i-- != 0);\r
+      }\r
+    }\r
+    return res;\r
+  }\r
+};\r
+\r
+}\r
+\r
+class CDecoder:\r
+  public ICompressCoder,\r
+  public ICompressSetInStream,\r
+  public ICompressSetOutStreamSize,\r
+  public CMyUnknownImp\r
+{\r
+  CLzOutWindow _outWindowStream;\r
+  NRangeCoder::CDecoder _rangeDecoder;\r
+\r
+  UInt64 _outSize;\r
+  int _remainLen; // -1 means end of stream. // -2 means need Init\r
+  UInt32 _rep0;\r
+\r
+  int _numDictBits;\r
+  bool _keepHistory;\r
+\r
+  NRangeCoder::CModelDecoder m_Selector;\r
+  NRangeCoder::CModelDecoder m_Literals[kNumLitSelectors];\r
+  NRangeCoder::CModelDecoder m_PosSlot[kNumMatchSelectors];\r
+  NRangeCoder::CModelDecoder m_LenSlot;\r
+  void Init();\r
+  HRESULT CodeSpec(UInt32 size);\r
+public:\r
+  MY_UNKNOWN_IMP2(\r
+      ICompressSetInStream,\r
+      ICompressSetOutStreamSize)\r
+\r
+  void ReleaseStreams()\r
+  {\r
+    _outWindowStream.ReleaseStream();\r
+    ReleaseInStream();\r
+  }\r
+\r
+  class CDecoderFlusher\r
+  {\r
+    CDecoder *_decoder;\r
+  public:\r
+    bool NeedFlush;\r
+    CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {}\r
+    ~CDecoderFlusher()\r
+    {\r
+      if (NeedFlush)\r
+        _decoder->Flush();\r
+      _decoder->ReleaseStreams();\r
+    }\r
+  };\r
+\r
+  HRESULT Flush() {  return _outWindowStream.Flush(); }\r
+\r
+  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+  \r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+  STDMETHOD(SetInStream)(ISequentialInStream *inStream);\r
+  STDMETHOD(ReleaseInStream)();\r
+  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);\r
+\r
+  void SetParams(int numDictBits) { _numDictBits = numDictBits; }\r
+  void SetKeepHistory(bool keepHistory) { _keepHistory = keepHistory; }\r
+  CDecoder(): _keepHistory(false) {}\r
+  virtual ~CDecoder() {}\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/RangeCoder.h b/CPP/7zip/Compress/RangeCoder.h
new file mode 100755 (executable)
index 0000000..e9e8e32
--- /dev/null
@@ -0,0 +1,205 @@
+// Compress/RangeCoder.h\r
+// 2009-05-30 : Igor Pavlov : Public domain\r
+\r
+#ifndef __COMPRESS_RANGE_CODER_H\r
+#define __COMPRESS_RANGE_CODER_H\r
+\r
+#include "../Common/InBuffer.h"\r
+#include "../Common/OutBuffer.h"\r
+\r
+namespace NCompress {\r
+namespace NRangeCoder {\r
+\r
+const int kNumTopBits = 24;\r
+const UInt32 kTopValue = (1 << kNumTopBits);\r
+\r
+class CEncoder\r
+{\r
+  UInt32 _cacheSize;\r
+  Byte _cache;\r
+public:\r
+  UInt64 Low;\r
+  UInt32 Range;\r
+  COutBuffer Stream;\r
+  bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }\r
+\r
+  void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); }\r
+  void Init()\r
+  {\r
+    Stream.Init();\r
+    Low = 0;\r
+    Range = 0xFFFFFFFF;\r
+    _cacheSize = 1;\r
+    _cache = 0;\r
+  }\r
+\r
+  void FlushData()\r
+  {\r
+    // Low += 1;\r
+    for(int i = 0; i < 5; i++)\r
+      ShiftLow();\r
+  }\r
+\r
+  HRESULT FlushStream() { return Stream.Flush();  }\r
+\r
+  void ReleaseStream() { Stream.ReleaseStream(); }\r
+\r
+  void Encode(UInt32 start, UInt32 size, UInt32 total)\r
+  {\r
+    Low += start * (Range /= total);\r
+    Range *= size;\r
+    while (Range < kTopValue)\r
+    {\r
+      Range <<= 8;\r
+      ShiftLow();\r
+    }\r
+  }\r
+\r
+  void ShiftLow()\r
+  {\r
+    if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0)\r
+    {\r
+      Byte temp = _cache;\r
+      do\r
+      {\r
+        Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32)));\r
+        temp = 0xFF;\r
+      }\r
+      while(--_cacheSize != 0);\r
+      _cache = (Byte)((UInt32)Low >> 24);\r
+    }\r
+    _cacheSize++;\r
+    Low = (UInt32)Low << 8;\r
+  }\r
+  \r
+  void EncodeDirectBits(UInt32 value, int numBits)\r
+  {\r
+    for (numBits--; numBits >= 0; numBits--)\r
+    {\r
+      Range >>= 1;\r
+      Low += Range & (0 - ((value >> numBits) & 1));\r
+      if (Range < kTopValue)\r
+      {\r
+        Range <<= 8;\r
+        ShiftLow();\r
+      }\r
+    }\r
+  }\r
+\r
+  void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol)\r
+  {\r
+    UInt32 newBound = (Range >> numTotalBits) * size0;\r
+    if (symbol == 0)\r
+      Range = newBound;\r
+    else\r
+    {\r
+      Low += newBound;\r
+      Range -= newBound;\r
+    }\r
+    while (Range < kTopValue)\r
+    {\r
+      Range <<= 8;\r
+      ShiftLow();\r
+    }\r
+  }\r
+\r
+  UInt64 GetProcessedSize() {  return Stream.GetProcessedSize() + _cacheSize + 4; }\r
+};\r
+\r
+class CDecoder\r
+{\r
+public:\r
+  CInBuffer Stream;\r
+  UInt32 Range;\r
+  UInt32 Code;\r
+  bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }\r
+\r
+  void Normalize()\r
+  {\r
+    while (Range < kTopValue)\r
+    {\r
+      Code = (Code << 8) | Stream.ReadByte();\r
+      Range <<= 8;\r
+    }\r
+  }\r
+  \r
+  void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); }\r
+  void Init()\r
+  {\r
+    Stream.Init();\r
+    Code = 0;\r
+    Range = 0xFFFFFFFF;\r
+    for(int i = 0; i < 5; i++)\r
+      Code = (Code << 8) | Stream.ReadByte();\r
+  }\r
+\r
+  void ReleaseStream() { Stream.ReleaseStream(); }\r
+\r
+  UInt32 GetThreshold(UInt32 total)\r
+  {\r
+    return (Code) / ( Range /= total);\r
+  }\r
+\r
+  void Decode(UInt32 start, UInt32 size)\r
+  {\r
+    Code -= start * Range;\r
+    Range *= size;\r
+    Normalize();\r
+  }\r
+\r
+  UInt32 DecodeDirectBits(int numTotalBits)\r
+  {\r
+    UInt32 range = Range;\r
+    UInt32 code = Code;\r
+    UInt32 result = 0;\r
+    for (int i = numTotalBits; i != 0; i--)\r
+    {\r
+      range >>= 1;\r
+      /*\r
+      result <<= 1;\r
+      if (code >= range)\r
+      {\r
+        code -= range;\r
+        result |= 1;\r
+      }\r
+      */\r
+      UInt32 t = (code - range) >> 31;\r
+      code -= range & (t - 1);\r
+      result = (result << 1) | (1 - t);\r
+\r
+      if (range < kTopValue)\r
+      {\r
+        code = (code << 8) | Stream.ReadByte();\r
+        range <<= 8;\r
+      }\r
+    }\r
+    Range = range;\r
+    Code = code;\r
+    return result;\r
+  }\r
+\r
+  UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits)\r
+  {\r
+    UInt32 newBound = (Range >> numTotalBits) * size0;\r
+    UInt32 symbol;\r
+    if (Code < newBound)\r
+    {\r
+      symbol = 0;\r
+      Range = newBound;\r
+    }\r
+    else\r
+    {\r
+      symbol = 1;\r
+      Code -= newBound;\r
+      Range -= newBound;\r
+    }\r
+    Normalize();\r
+    return symbol;\r
+  }\r
+\r
+  UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/RangeCoderBit.h b/CPP/7zip/Compress/RangeCoderBit.h
new file mode 100755 (executable)
index 0000000..f06408c
--- /dev/null
@@ -0,0 +1,114 @@
+// Compress/RangeCoderBit.h\r
+// 2009-05-30 : Igor Pavlov : Public domain\r
+\r
+#ifndef __COMPRESS_RANGE_CODER_BIT_H\r
+#define __COMPRESS_RANGE_CODER_BIT_H\r
+\r
+#include "RangeCoder.h"\r
+\r
+namespace NCompress {\r
+namespace NRangeCoder {\r
+\r
+const int kNumBitModelTotalBits  = 11;\r
+const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits);\r
+\r
+const int kNumMoveReducingBits = 4;\r
+\r
+const int kNumBitPriceShiftBits = 4;\r
+const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits;\r
+\r
+extern UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];\r
+\r
+template <int numMoveBits>\r
+class CBitModel\r
+{\r
+public:\r
+  UInt32 Prob;\r
+  void UpdateModel(UInt32 symbol)\r
+  {\r
+    /*\r
+    Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits;\r
+    Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits);\r
+    */\r
+    if (symbol == 0)\r
+      Prob += (kBitModelTotal - Prob) >> numMoveBits;\r
+    else\r
+      Prob -= (Prob) >> numMoveBits;\r
+  }\r
+public:\r
+  void Init() { Prob = kBitModelTotal / 2; }\r
+};\r
+\r
+template <int numMoveBits>\r
+class CBitEncoder: public CBitModel<numMoveBits>\r
+{\r
+public:\r
+  void Encode(CEncoder *encoder, UInt32 symbol)\r
+  {\r
+    /*\r
+    encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol);\r
+    this->UpdateModel(symbol);\r
+    */\r
+    UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob;\r
+    if (symbol == 0)\r
+    {\r
+      encoder->Range = newBound;\r
+      this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;\r
+    }\r
+    else\r
+    {\r
+      encoder->Low += newBound;\r
+      encoder->Range -= newBound;\r
+      this->Prob -= (this->Prob) >> numMoveBits;\r
+    }\r
+    if (encoder->Range < kTopValue)\r
+    {\r
+      encoder->Range <<= 8;\r
+      encoder->ShiftLow();\r
+    }\r
+  }\r
+  UInt32 GetPrice(UInt32 symbol) const\r
+  {\r
+    return ProbPrices[(this->Prob ^ ((-(int)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];\r
+  }\r
+  UInt32 GetPrice0() const { return ProbPrices[this->Prob >> kNumMoveReducingBits]; }\r
+  UInt32 GetPrice1() const { return ProbPrices[(this->Prob ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]; }\r
+};\r
+\r
+\r
+template <int numMoveBits>\r
+class CBitDecoder: public CBitModel<numMoveBits>\r
+{\r
+public:\r
+  UInt32 Decode(CDecoder *decoder)\r
+  {\r
+    UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob;\r
+    if (decoder->Code < newBound)\r
+    {\r
+      decoder->Range = newBound;\r
+      this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;\r
+      if (decoder->Range < kTopValue)\r
+      {\r
+        decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();\r
+        decoder->Range <<= 8;\r
+      }\r
+      return 0;\r
+    }\r
+    else\r
+    {\r
+      decoder->Range -= newBound;\r
+      decoder->Code -= newBound;\r
+      this->Prob -= (this->Prob) >> numMoveBits;\r
+      if (decoder->Range < kTopValue)\r
+      {\r
+        decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();\r
+        decoder->Range <<= 8;\r
+      }\r
+      return 1;\r
+    }\r
+  }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/Rar1Decoder.cpp b/CPP/7zip/Compress/Rar1Decoder.cpp
new file mode 100755 (executable)
index 0000000..25fb2c0
--- /dev/null
@@ -0,0 +1,480 @@
+// Rar1Decoder.cpp\r
+// According to unRAR license, this code may not be used to develop\r
+// a program that creates RAR archives\r
\r
+#include "StdAfx.h"\r
+\r
+#include "Rar1Decoder.h"\r
+\r
+namespace NCompress {\r
+namespace NRar1 {\r
+\r
+static UInt32 PosL1[]={0,0,0,2,3,5,7,11,16,20,24,32,32, 256};\r
+static UInt32 PosL2[]={0,0,0,0,5,7,9,13,18,22,26,34,36, 256};\r
+static UInt32 PosHf0[]={0,0,0,0,0,8,16,24,33,33,33,33,33, 257};\r
+static UInt32 PosHf1[]={0,0,0,0,0,0,4,44,60,76,80,80,127, 257};\r
+static UInt32 PosHf2[]={0,0,0,0,0,0,2,7,53,117,233, 257,0};\r
+static UInt32 PosHf3[]={0,0,0,0,0,0,0,2,16,218,251, 257,0};\r
+static UInt32 PosHf4[]={0,0,0,0,0,0,0,0,0,255, 257,0,0};\r
+\r
+static const UInt32 kHistorySize = (1 << 16);\r
+\r
+class CCoderReleaser\r
+{\r
+  CDecoder *m_Coder;\r
+public:\r
+  CCoderReleaser(CDecoder *coder): m_Coder(coder) {}\r
+  ~CCoderReleaser() { m_Coder->ReleaseStreams(); }\r
+};\r
+\r
+CDecoder::CDecoder(): m_IsSolid(false) { }\r
+\r
+void CDecoder::InitStructures()\r
+{\r
+  for(int i = 0; i < kNumRepDists; i++)\r
+    m_RepDists[i] = 0;\r
+  m_RepDistPtr = 0;\r
+  LastLength = 0;\r
+  LastDist = 0;\r
+}\r
+\r
+UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); }\r
+\r
+HRESULT CDecoder::CopyBlock(UInt32 distance, UInt32 len)\r
+{\r
+  if (len == 0)\r
+    return S_FALSE;\r
+  m_UnpackSize -= len;\r
+  return m_OutWindowStream.CopyBlock(distance, len) ? S_OK : S_FALSE;\r
+}\r
+\r
+\r
+UInt32 CDecoder::DecodeNum(const UInt32 *posTab)\r
+{\r
+  UInt32 startPos = 2;\r
+  UInt32 num = m_InBitStream.GetValue(12);\r
+  for (;;)\r
+  {\r
+    UInt32 cur = (posTab[startPos + 1] - posTab[startPos]) << (12 - startPos);\r
+    if (num < cur)\r
+      break;\r
+    startPos++;\r
+    num -= cur;\r
+  }\r
+  m_InBitStream.MovePos(startPos);\r
+  return((num >> (12 - startPos)) + posTab[startPos]);\r
+}\r
+\r
+static Byte kShortLen1[]  = {1,3,4,4,5,6,7,8,8,4,4,5,6,6 };\r
+static Byte kShortLen1a[] = {1,4,4,4,5,6,7,8,8,4,4,5,6,6,4 };\r
+static Byte kShortLen2[]  = {2,3,3,3,4,4,5,6,6,4,4,5,6,6 };\r
+static Byte kShortLen2a[] = {2,3,3,4,4,4,5,6,6,4,4,5,6,6,4 };\r
+static UInt32 kShortXor1[] = {0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0};\r
+static UInt32 kShortXor2[] = {0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0};\r
+\r
+HRESULT CDecoder::ShortLZ()\r
+{\r
+  UInt32 len, saveLen, dist;\r
+  int distancePlace;\r
+  Byte *kShortLen;\r
+  const UInt32 *kShortXor;\r
+  NumHuf = 0;\r
+\r
+  if (LCount == 2)\r
+  {\r
+    if (ReadBits(1))\r
+      return CopyBlock(LastDist, LastLength);\r
+    LCount = 0;\r
+  }\r
+\r
+  UInt32 bitField = m_InBitStream.GetValue(8);\r
+\r
+  if (AvrLn1 < 37)\r
+  {\r
+    kShortLen = Buf60 ? kShortLen1a : kShortLen1;\r
+    kShortXor = kShortXor1;\r
+  }\r
+  else\r
+  {\r
+    kShortLen = Buf60 ? kShortLen2a : kShortLen2;\r
+    kShortXor = kShortXor2;\r
+  }\r
+\r
+  for (len = 0; ((bitField ^ kShortXor[len]) & (~(0xff >> kShortLen[len]))) != 0; len++);\r
+  m_InBitStream.MovePos(kShortLen[len]);\r
+\r
+  if (len >= 9)\r
+  {\r
+    if (len == 9)\r
+    {\r
+      LCount++;\r
+      return CopyBlock(LastDist, LastLength);\r
+    }\r
+    if (len == 14)\r
+    {\r
+      LCount = 0;\r
+      len = DecodeNum(PosL2) + 5;\r
+      dist = 0x8000 + ReadBits(15) - 1;\r
+      LastLength = len;\r
+      LastDist = dist;\r
+      return CopyBlock(dist, len);\r
+    }\r
+\r
+    LCount = 0;\r
+    saveLen = len;\r
+    dist = m_RepDists[(m_RepDistPtr - (len - 9)) & 3];\r
+    len = DecodeNum(PosL1) + 2;\r
+    if (len == 0x101 && saveLen == 10)\r
+    {\r
+      Buf60 ^= 1;\r
+      return S_OK;\r
+    }\r
+    if (dist >= 256)\r
+      len++;\r
+    if (dist >= MaxDist3 - 1)\r
+      len++;\r
+  }\r
+  else\r
+  {\r
+    LCount = 0;\r
+    AvrLn1 += len;\r
+    AvrLn1 -= AvrLn1 >> 4;\r
+    \r
+    distancePlace = DecodeNum(PosHf2) & 0xff;\r
+    dist = ChSetA[distancePlace];\r
+    if (--distancePlace != -1)\r
+    {\r
+      PlaceA[dist]--;\r
+      UInt32 lastDistance = ChSetA[distancePlace];\r
+      PlaceA[lastDistance]++;\r
+      ChSetA[distancePlace + 1] = lastDistance;\r
+      ChSetA[distancePlace] = dist;\r
+    }\r
+    len += 2;\r
+  }\r
+  m_RepDists[m_RepDistPtr++] = dist;\r
+  m_RepDistPtr &= 3;\r
+  LastLength = len;\r
+  LastDist = dist;\r
+  return CopyBlock(dist, len);\r
+}\r
+\r
+\r
+HRESULT CDecoder::LongLZ()\r
+{\r
+  UInt32 len;\r
+  UInt32 dist;\r
+  UInt32 distancePlace, newDistancePlace;\r
+  UInt32 oldAvr2, oldAvr3;\r
+\r
+  NumHuf = 0;\r
+  Nlzb += 16;\r
+  if (Nlzb > 0xff)\r
+  {\r
+    Nlzb = 0x90;\r
+    Nhfb >>= 1;\r
+  }\r
+  oldAvr2=AvrLn2;\r
+\r
+  if (AvrLn2 >= 122)\r
+    len = DecodeNum(PosL2);\r
+  else if (AvrLn2 >= 64)\r
+    len = DecodeNum(PosL1);\r
+  else\r
+  {\r
+    UInt32 bitField = m_InBitStream.GetValue(16);\r
+    if (bitField < 0x100)\r
+    {\r
+      len = bitField;\r
+      m_InBitStream.MovePos(16);\r
+    }\r
+    else\r
+    {\r
+      for (len = 0; ((bitField << len) & 0x8000) == 0; len++)\r
+        ;\r
+      m_InBitStream.MovePos(len + 1);\r
+    }\r
+  }\r
+\r
+  AvrLn2 += len;\r
+  AvrLn2 -= AvrLn2 >> 5;\r
+\r
+  if (AvrPlcB > 0x28ff)\r
+    distancePlace = DecodeNum(PosHf2);\r
+  else if (AvrPlcB > 0x6ff)\r
+    distancePlace = DecodeNum(PosHf1);\r
+  else\r
+    distancePlace = DecodeNum(PosHf0);\r
+\r
+  AvrPlcB += distancePlace;\r
+  AvrPlcB -= AvrPlcB >> 8;\r
+  for (;;)\r
+  {\r
+    dist = ChSetB[distancePlace & 0xff];\r
+    newDistancePlace = NToPlB[dist++ & 0xff]++;\r
+    if (!(dist & 0xff))\r
+      CorrHuff(ChSetB,NToPlB);\r
+    else\r
+      break;\r
+  }\r
+\r
+  ChSetB[distancePlace] = ChSetB[newDistancePlace];\r
+  ChSetB[newDistancePlace] = dist;\r
+\r
+  dist = ((dist & 0xff00) >> 1) | ReadBits(7);\r
+\r
+  oldAvr3 = AvrLn3;\r
+  if (len != 1 && len != 4)\r
+    if (len == 0 && dist <= MaxDist3)\r
+    {\r
+      AvrLn3++;\r
+      AvrLn3 -= AvrLn3 >> 8;\r
+    }\r
+    else\r
+      if (AvrLn3 > 0)\r
+        AvrLn3--;\r
+  len += 3;\r
+  if (dist >= MaxDist3)\r
+    len++;\r
+  if (dist <= 256)\r
+    len += 8;\r
+  if (oldAvr3 > 0xb0 || AvrPlc >= 0x2a00 && oldAvr2 < 0x40)\r
+    MaxDist3 = 0x7f00;\r
+  else\r
+    MaxDist3 = 0x2001;\r
+  m_RepDists[m_RepDistPtr++] = --dist;\r
+  m_RepDistPtr &= 3;\r
+  LastLength = len;\r
+  LastDist = dist;\r
+  return CopyBlock(dist, len);\r
+}\r
+\r
+\r
+HRESULT CDecoder::HuffDecode()\r
+{\r
+  UInt32 curByte, newBytePlace;\r
+  UInt32 len;\r
+  UInt32 dist;\r
+  int bytePlace;\r
+\r
+  if      (AvrPlc > 0x75ff)  bytePlace = DecodeNum(PosHf4);\r
+  else if (AvrPlc > 0x5dff)  bytePlace = DecodeNum(PosHf3);\r
+  else if (AvrPlc > 0x35ff)  bytePlace = DecodeNum(PosHf2);\r
+  else if (AvrPlc > 0x0dff)  bytePlace = DecodeNum(PosHf1);\r
+  else                       bytePlace = DecodeNum(PosHf0);\r
+  if (StMode)\r
+  {\r
+    if (--bytePlace == -1)\r
+    {\r
+      if (ReadBits(1))\r
+      {\r
+        NumHuf = StMode = 0;\r
+        return S_OK;\r
+      }\r
+      else\r
+      {\r
+        len = (ReadBits(1)) ? 4 : 3;\r
+        dist = DecodeNum(PosHf2);\r
+        dist = (dist << 5) | ReadBits(5);\r
+        return CopyBlock(dist - 1, len);\r
+      }\r
+    }\r
+  }\r
+  else if (NumHuf++ >= 16 && FlagsCnt == 0)\r
+    StMode = 1;\r
+  bytePlace &= 0xff;\r
+  AvrPlc += bytePlace;\r
+  AvrPlc -= AvrPlc >> 8;\r
+  Nhfb+=16;\r
+  if (Nhfb > 0xff)\r
+  {\r
+    Nhfb=0x90;\r
+    Nlzb >>= 1;\r
+  }\r
+\r
+  m_UnpackSize --;\r
+  m_OutWindowStream.PutByte((Byte)(ChSet[bytePlace] >> 8));\r
+\r
+  for (;;)\r
+  {\r
+    curByte = ChSet[bytePlace];\r
+    newBytePlace = NToPl[curByte++ & 0xff]++;\r
+    if ((curByte & 0xff) > 0xa1)\r
+      CorrHuff(ChSet, NToPl);\r
+    else\r
+      break;\r
+  }\r
+\r
+  ChSet[bytePlace] = ChSet[newBytePlace];\r
+  ChSet[newBytePlace] = curByte;\r
+  return S_OK;\r
+}\r
+\r
+\r
+void CDecoder::GetFlagsBuf()\r
+{\r
+  UInt32 flags, newFlagsPlace;\r
+  UInt32 flagsPlace = DecodeNum(PosHf2);\r
+\r
+  for (;;)\r
+  {\r
+    flags = ChSetC[flagsPlace];\r
+    FlagBuf = flags >> 8;\r
+    newFlagsPlace = NToPlC[flags++ & 0xff]++;\r
+    if ((flags & 0xff) != 0)\r
+      break;\r
+    CorrHuff(ChSetC, NToPlC);\r
+  }\r
+\r
+  ChSetC[flagsPlace] = ChSetC[newFlagsPlace];\r
+  ChSetC[newFlagsPlace] = flags;\r
+}\r
+\r
+void CDecoder::InitData()\r
+{\r
+  if (!m_IsSolid)\r
+  {\r
+    AvrPlcB = AvrLn1 = AvrLn2 = AvrLn3 = NumHuf = Buf60 = 0;\r
+    AvrPlc = 0x3500;\r
+    MaxDist3 = 0x2001;\r
+    Nhfb = Nlzb = 0x80;\r
+  }\r
+  FlagsCnt = 0;\r
+  FlagBuf = 0;\r
+  StMode = 0;\r
+  LCount = 0;\r
+}\r
+\r
+void CDecoder::CorrHuff(UInt32 *CharSet,UInt32 *NumToPlace)\r
+{\r
+  int i;\r
+  for (i = 7; i >= 0; i--)\r
+    for (int j = 0; j < 32; j++, CharSet++)\r
+      *CharSet = (*CharSet & ~0xff) | i;\r
+  memset(NumToPlace, 0, sizeof(NToPl));\r
+  for (i = 6; i >= 0; i--)\r
+    NumToPlace[i] = (7 - i) * 32;\r
+}\r
+\r
+void CDecoder::InitHuff()\r
+{\r
+  for (UInt32 i = 0; i < 256; i++)\r
+  {\r
+    Place[i] = PlaceA[i] = PlaceB[i] = i;\r
+    PlaceC[i] = (~i + 1) & 0xff;\r
+    ChSet[i] = ChSetB[i] = i << 8;\r
+    ChSetA[i] = i;\r
+    ChSetC[i] = ((~i + 1) & 0xff) << 8;\r
+  }\r
+  memset(NToPl, 0, sizeof(NToPl));\r
+  memset(NToPlB, 0, sizeof(NToPlB));\r
+  memset(NToPlC, 0, sizeof(NToPlC));\r
+  CorrHuff(ChSetB, NToPlB);\r
+}\r
+\r
+HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo * /* progress */)\r
+{\r
+  if (inSize == NULL || outSize == NULL)\r
+    return E_INVALIDARG;\r
+\r
+  if (!m_OutWindowStream.Create(kHistorySize))\r
+    return E_OUTOFMEMORY;\r
+  if (!m_InBitStream.Create(1 << 20))\r
+    return E_OUTOFMEMORY;\r
+\r
+  m_UnpackSize = (Int64)*outSize;\r
+  m_OutWindowStream.SetStream(outStream);\r
+  m_OutWindowStream.Init(m_IsSolid);\r
+  m_InBitStream.SetStream(inStream);\r
+  m_InBitStream.Init();\r
+\r
+  CCoderReleaser coderReleaser(this);\r
+  InitData();\r
+  if (!m_IsSolid)\r
+  {\r
+    InitStructures();\r
+    InitHuff();\r
+  }\r
+  if (m_UnpackSize > 0)\r
+  {\r
+    GetFlagsBuf();\r
+    FlagsCnt = 8;\r
+  }\r
+\r
+  while (m_UnpackSize > 0)\r
+  {\r
+    if (StMode)\r
+    {\r
+      RINOK(HuffDecode());\r
+      continue;\r
+    }\r
+\r
+    if (--FlagsCnt < 0)\r
+    {\r
+      GetFlagsBuf();\r
+      FlagsCnt=7;\r
+    }\r
+\r
+    if (FlagBuf & 0x80)\r
+    {\r
+      FlagBuf <<= 1;\r
+      if (Nlzb > Nhfb)\r
+      {\r
+        RINOK(LongLZ());\r
+      }\r
+      else\r
+      {\r
+        RINOK(HuffDecode());\r
+      }\r
+    }\r
+    else\r
+    {\r
+      FlagBuf <<= 1;\r
+      if (--FlagsCnt < 0)\r
+      {\r
+        GetFlagsBuf();\r
+        FlagsCnt = 7;\r
+      }\r
+      if (FlagBuf & 0x80)\r
+      {\r
+        FlagBuf <<= 1;\r
+        if (Nlzb > Nhfb)\r
+        {\r
+          RINOK(HuffDecode());\r
+        }\r
+        else\r
+        {\r
+          RINOK(LongLZ());\r
+        }\r
+      }\r
+      else\r
+      {\r
+        FlagBuf <<= 1;\r
+        RINOK(ShortLZ());\r
+      }\r
+    }\r
+  }\r
+  if (m_UnpackSize < 0)\r
+    return S_FALSE;\r
+  return m_OutWindowStream.Flush();\r
+}\r
+\r
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  try { return CodeReal(inStream, outStream, inSize, outSize, progress); }\r
+  catch(const CInBufferException &e) { return e.ErrorCode; }\r
+  catch(const CLzOutWindowException &e) { return e.ErrorCode; }\r
+  catch(...) { return S_FALSE; }\r
+}\r
+\r
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)\r
+{\r
+  if (size < 1)\r
+    return E_INVALIDARG;\r
+  m_IsSolid = (data[0] != 0);\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Compress/Rar1Decoder.h b/CPP/7zip/Compress/Rar1Decoder.h
new file mode 100755 (executable)
index 0000000..1b960e4
--- /dev/null
@@ -0,0 +1,88 @@
+// Rar1Decoder.h\r
+// According to unRAR license, this code may not be used to develop\r
+// a program that creates RAR archives\r
+\r
+#ifndef __COMPRESS_RAR1_DECODER_H\r
+#define __COMPRESS_RAR1_DECODER_H\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "../Common/InBuffer.h"\r
+\r
+#include "BitmDecoder.h"\r
+#include "HuffmanDecoder.h"\r
+#include "LzOutWindow.h"\r
+\r
+namespace NCompress {\r
+namespace NRar1 {\r
+\r
+const UInt32 kNumRepDists = 4;\r
+\r
+typedef NBitm::CDecoder<CInBuffer> CBitDecoder;\r
+\r
+class CDecoder :\r
+  public ICompressCoder,\r
+  public ICompressSetDecoderProperties2,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  CLzOutWindow m_OutWindowStream;\r
+  CBitDecoder m_InBitStream;\r
+\r
+  UInt32 m_RepDists[kNumRepDists];\r
+  UInt32 m_RepDistPtr;\r
+\r
+  UInt32 LastDist;\r
+  UInt32 LastLength;\r
+\r
+  Int64 m_UnpackSize;\r
+  bool m_IsSolid;\r
+\r
+  UInt32 ReadBits(int numBits);\r
+  HRESULT CopyBlock(UInt32 distance, UInt32 len);\r
+\r
+  UInt32 DecodeNum(const UInt32 *posTab);\r
+  HRESULT ShortLZ();\r
+  HRESULT LongLZ();\r
+  HRESULT HuffDecode();\r
+  void GetFlagsBuf();\r
+  void InitData();\r
+  void InitHuff();\r
+  void CorrHuff(UInt32 *CharSet, UInt32 *NumToPlace);\r
+  void OldUnpWriteBuf();\r
+  \r
+  UInt32 ChSet[256],ChSetA[256],ChSetB[256],ChSetC[256];\r
+  UInt32 Place[256],PlaceA[256],PlaceB[256],PlaceC[256];\r
+  UInt32 NToPl[256],NToPlB[256],NToPlC[256];\r
+  UInt32 FlagBuf,AvrPlc,AvrPlcB,AvrLn1,AvrLn2,AvrLn3;\r
+  int Buf60,NumHuf,StMode,LCount,FlagsCnt;\r
+  UInt32 Nhfb,Nlzb,MaxDist3;\r
+\r
+  void InitStructures();\r
+\r
+  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+public:\r
+  CDecoder();\r
+\r
+  MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)\r
+\r
+  void ReleaseStreams()\r
+  {\r
+    m_OutWindowStream.ReleaseStream();\r
+    m_InBitStream.ReleaseStream();\r
+  }\r
+\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);\r
+\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/Rar2Decoder.cpp b/CPP/7zip/Compress/Rar2Decoder.cpp
new file mode 100755 (executable)
index 0000000..742e628
--- /dev/null
@@ -0,0 +1,391 @@
+// Rar2Decoder.cpp\r
+// According to unRAR license, this code may not be used to develop\r
+// a program that creates RAR archives\r
\r
+#include "StdAfx.h"\r
+\r
+#include "Rar2Decoder.h"\r
+\r
+namespace NCompress {\r
+namespace NRar2 {\r
+\r
+namespace NMultimedia {\r
+\r
+Byte CFilter::Decode(int &channelDelta, Byte deltaByte)\r
+{\r
+  D4 = D3;\r
+  D3 = D2;\r
+  D2 = LastDelta - D1;\r
+  D1 = LastDelta;\r
+  int predictedValue = ((8 * LastChar + K1 * D1 + K2 * D2 + K3 * D3 + K4 * D4 + K5 * channelDelta) >> 3);\r
+\r
+  Byte realValue = (Byte)(predictedValue - deltaByte);\r
+  int i = ((int)(signed char)deltaByte) << 3;\r
+\r
+  Dif[0] += abs(i);\r
+  Dif[1] += abs(i - D1);\r
+  Dif[2] += abs(i + D1);\r
+  Dif[3] += abs(i - D2);\r
+  Dif[4] += abs(i + D2);\r
+  Dif[5] += abs(i - D3);\r
+  Dif[6] += abs(i + D3);\r
+  Dif[7] += abs(i - D4);\r
+  Dif[8] += abs(i + D4);\r
+  Dif[9] += abs(i - channelDelta);\r
+  Dif[10] += abs(i + channelDelta);\r
+\r
+  channelDelta = LastDelta = (signed char)(realValue - LastChar);\r
+  LastChar = realValue;\r
+\r
+  if (((++ByteCount) & 0x1F) == 0)\r
+  {\r
+    UInt32 minDif = Dif[0];\r
+    UInt32 numMinDif = 0;\r
+    Dif[0] = 0;\r
+    for (i = 1; i < sizeof(Dif) / sizeof(Dif[0]); i++)\r
+    {\r
+      if (Dif[i] < minDif)\r
+      {\r
+        minDif = Dif[i];\r
+        numMinDif = i;\r
+      }\r
+      Dif[i] = 0;\r
+    }\r
+    switch(numMinDif)\r
+    {\r
+      case 1: if (K1 >= -16) K1--; break;\r
+      case 2: if (K1 <   16) K1++; break;\r
+      case 3: if (K2 >= -16) K2--; break;\r
+      case 4: if (K2 <   16) K2++; break;\r
+      case 5: if (K3 >= -16) K3--; break;\r
+      case 6: if (K3 <   16) K3++; break;\r
+      case 7: if (K4 >= -16) K4--; break;\r
+      case 8: if (K4 <   16) K4++; break;\r
+      case 9: if (K5 >= -16) K5--; break;\r
+      case 10:if (K5 <   16) K5++; break;\r
+    }\r
+  }\r
+  return realValue;\r
+}\r
+}\r
+\r
+static const char *kNumberErrorMessage = "Number error";\r
+\r
+static const UInt32 kHistorySize = 1 << 20;\r
+\r
+static const int kNumStats = 11;\r
+\r
+static const UInt32 kWindowReservSize = (1 << 22) + 256;\r
+\r
+CDecoder::CDecoder():\r
+  m_IsSolid(false)\r
+{\r
+}\r
+\r
+void CDecoder::InitStructures()\r
+{\r
+  m_MmFilter.Init();\r
+  for(int i = 0; i < kNumRepDists; i++)\r
+    m_RepDists[i] = 0;\r
+  m_RepDistPtr = 0;\r
+  m_LastLength = 0;\r
+  memset(m_LastLevels, 0, kMaxTableSize);\r
+}\r
+\r
+UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); }\r
+\r
+#define RIF(x) { if (!(x)) return false; }\r
+\r
+bool CDecoder::ReadTables(void)\r
+{\r
+  Byte levelLevels[kLevelTableSize];\r
+  Byte newLevels[kMaxTableSize];\r
+  m_AudioMode = (ReadBits(1) == 1);\r
+\r
+  if (ReadBits(1) == 0)\r
+    memset(m_LastLevels, 0, kMaxTableSize);\r
+  int numLevels;\r
+  if (m_AudioMode)\r
+  {\r
+    m_NumChannels = ReadBits(2) + 1;\r
+    if (m_MmFilter.CurrentChannel >= m_NumChannels)\r
+      m_MmFilter.CurrentChannel = 0;\r
+    numLevels = m_NumChannels * kMMTableSize;\r
+  }\r
+  else\r
+    numLevels = kHeapTablesSizesSum;\r
\r
+  int i;\r
+  for (i = 0; i < kLevelTableSize; i++)\r
+    levelLevels[i] = (Byte)ReadBits(4);\r
+  RIF(m_LevelDecoder.SetCodeLengths(levelLevels));\r
+  i = 0;\r
+  while (i < numLevels)\r
+  {\r
+    UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);\r
+    if (number < kTableDirectLevels)\r
+    {\r
+      newLevels[i] = (Byte)((number + m_LastLevels[i]) & kLevelMask);\r
+      i++;\r
+    }\r
+    else\r
+    {\r
+      if (number == kTableLevelRepNumber)\r
+      {\r
+        int t = ReadBits(2) + 3;\r
+        for (int reps = t; reps > 0 && i < numLevels ; reps--, i++)\r
+          newLevels[i] = newLevels[i - 1];\r
+      }\r
+      else\r
+      {\r
+        int num;\r
+        if (number == kTableLevel0Number)\r
+          num = ReadBits(3) + 3;\r
+        else if (number == kTableLevel0Number2)\r
+          num = ReadBits(7) + 11;\r
+        else\r
+          return false;\r
+        for (;num > 0 && i < numLevels; num--)\r
+          newLevels[i++] = 0;\r
+      }\r
+    }\r
+  }\r
+  if (m_AudioMode)\r
+    for (i = 0; i < m_NumChannels; i++)\r
+    {\r
+      RIF(m_MMDecoders[i].SetCodeLengths(&newLevels[i * kMMTableSize]));\r
+    }\r
+  else\r
+  {\r
+    RIF(m_MainDecoder.SetCodeLengths(&newLevels[0]));\r
+    RIF(m_DistDecoder.SetCodeLengths(&newLevels[kMainTableSize]));\r
+    RIF(m_LenDecoder.SetCodeLengths(&newLevels[kMainTableSize + kDistTableSize]));\r
+  }\r
+  memcpy(m_LastLevels, newLevels, kMaxTableSize);\r
+  return true;\r
+}\r
+\r
+bool CDecoder::ReadLastTables()\r
+{\r
+  // it differs a little from pure RAR sources;\r
+  // UInt64 ttt = m_InBitStream.GetProcessedSize() + 2;\r
+  // + 2 works for: return 0xFF; in CInBuffer::ReadByte.\r
+  if (m_InBitStream.GetProcessedSize() + 7 <= m_PackSize) // test it: probably incorrect;\r
+  // if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: probably incorrect;\r
+    if (m_AudioMode)\r
+    {\r
+      UInt32 symbol = m_MMDecoders[m_MmFilter.CurrentChannel].DecodeSymbol(&m_InBitStream);\r
+      if (symbol == 256)\r
+        return ReadTables();\r
+      if (symbol >= kMMTableSize)\r
+        return false;\r
+    }\r
+    else\r
+    {\r
+      UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);\r
+      if (number == kReadTableNumber)\r
+        return ReadTables();\r
+      if (number >= kMainTableSize)\r
+        return false;\r
+    }\r
+  return true;\r
+}\r
+\r
+class CCoderReleaser\r
+{\r
+  CDecoder *m_Coder;\r
+public:\r
+  CCoderReleaser(CDecoder *coder): m_Coder(coder) {}\r
+  ~CCoderReleaser()\r
+  {\r
+    m_Coder->ReleaseStreams();\r
+  }\r
+};\r
+\r
+bool CDecoder::DecodeMm(UInt32 pos)\r
+{\r
+  while (pos-- > 0)\r
+  {\r
+    UInt32 symbol = m_MMDecoders[m_MmFilter.CurrentChannel].DecodeSymbol(&m_InBitStream);\r
+    if (symbol == 256)\r
+      return true;\r
+    if (symbol >= kMMTableSize)\r
+      return false;\r
+    /*\r
+    Byte byPredict = m_Predictor.Predict();\r
+    Byte byReal = (Byte)(byPredict - (Byte)symbol);\r
+    m_Predictor.Update(byReal, byPredict);\r
+    */\r
+    Byte byReal = m_MmFilter.Decode((Byte)symbol);\r
+    m_OutWindowStream.PutByte(byReal);\r
+    if (++m_MmFilter.CurrentChannel == m_NumChannels)\r
+      m_MmFilter.CurrentChannel = 0;\r
+  }\r
+  return true;\r
+}\r
+\r
+bool CDecoder::DecodeLz(Int32 pos)\r
+{\r
+  while (pos > 0)\r
+  {\r
+    UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);\r
+    UInt32 length, distance;\r
+    if (number < 256)\r
+    {\r
+      m_OutWindowStream.PutByte(Byte(number));\r
+      pos--;\r
+      continue;\r
+    }\r
+    else if (number >= kMatchNumber)\r
+    {\r
+      number -= kMatchNumber;\r
+      length = kNormalMatchMinLen + UInt32(kLenStart[number]) +\r
+        m_InBitStream.ReadBits(kLenDirectBits[number]);\r
+      number = m_DistDecoder.DecodeSymbol(&m_InBitStream);\r
+      if (number >= kDistTableSize)\r
+        return false;\r
+      distance = kDistStart[number] + m_InBitStream.ReadBits(kDistDirectBits[number]);\r
+      if (distance >= kDistLimit3)\r
+      {\r
+        length += 2 - ((distance - kDistLimit4) >> 31);\r
+        // length++;\r
+        // if (distance >= kDistLimit4)\r
+        //  length++;\r
+      }\r
+    }\r
+    else if (number == kRepBothNumber)\r
+    {\r
+      length = m_LastLength;\r
+      if (length == 0)\r
+        return false;\r
+      distance = m_RepDists[(m_RepDistPtr + 4 - 1) & 3];\r
+    }\r
+    else if (number < kLen2Number)\r
+    {\r
+      distance = m_RepDists[(m_RepDistPtr - (number - kRepNumber + 1)) & 3];\r
+      number = m_LenDecoder.DecodeSymbol(&m_InBitStream);\r
+      if (number >= kLenTableSize)\r
+        return false;\r
+      length = 2 + kLenStart[number] + m_InBitStream.ReadBits(kLenDirectBits[number]);\r
+      if (distance >= kDistLimit2)\r
+      {\r
+        length++;\r
+        if (distance >= kDistLimit3)\r
+        {\r
+          length += 2 - ((distance - kDistLimit4) >> 31);\r
+          // length++;\r
+          // if (distance >= kDistLimit4)\r
+          //   length++;\r
+        }\r
+      }\r
+    }\r
+    else if (number < kReadTableNumber)\r
+    {\r
+      number -= kLen2Number;\r
+      distance = kLen2DistStarts[number] +\r
+        m_InBitStream.ReadBits(kLen2DistDirectBits[number]);\r
+      length = 2;\r
+    }\r
+    else if (number == kReadTableNumber)\r
+      return true;\r
+    else\r
+      return false;\r
+    m_RepDists[m_RepDistPtr++ & 3] = distance;\r
+    m_LastLength = length;\r
+    if (!m_OutWindowStream.CopyBlock(distance, length))\r
+      return false;\r
+    pos -= length;\r
+  }\r
+  return true;\r
+}\r
+\r
+HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  if (inSize == NULL || outSize == NULL)\r
+    return E_INVALIDARG;\r
+\r
+  if (!m_OutWindowStream.Create(kHistorySize))\r
+    return E_OUTOFMEMORY;\r
+  if (!m_InBitStream.Create(1 << 20))\r
+    return E_OUTOFMEMORY;\r
+\r
+  m_PackSize = *inSize;\r
+\r
+  UInt64 pos = 0, unPackSize = *outSize;\r
+  \r
+  m_OutWindowStream.SetStream(outStream);\r
+  m_OutWindowStream.Init(m_IsSolid);\r
+  m_InBitStream.SetStream(inStream);\r
+  m_InBitStream.Init();\r
+\r
+  CCoderReleaser coderReleaser(this);\r
+  if (!m_IsSolid)\r
+  {\r
+    InitStructures();\r
+    if (unPackSize == 0)\r
+    {\r
+      if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: probably incorrect;\r
+        if (!ReadTables())\r
+          return S_FALSE;\r
+      return S_OK;\r
+    }\r
+    if (!ReadTables())\r
+      return S_FALSE;\r
+  }\r
+\r
+  UInt64 startPos = m_OutWindowStream.GetProcessedSize();\r
+  while(pos < unPackSize)\r
+  {\r
+    UInt32 blockSize = 1 << 20;\r
+    if (blockSize > unPackSize - pos)\r
+      blockSize = (UInt32)(unPackSize - pos);\r
+    UInt64 blockStartPos = m_OutWindowStream.GetProcessedSize();\r
+    if (m_AudioMode)\r
+    {\r
+      if (!DecodeMm(blockSize))\r
+        return S_FALSE;\r
+    }\r
+    else\r
+    {\r
+      if (!DecodeLz((Int32)blockSize))\r
+        return S_FALSE;\r
+    }\r
+    UInt64 globalPos = m_OutWindowStream.GetProcessedSize();\r
+    pos = globalPos - blockStartPos;\r
+    if (pos < blockSize)\r
+      if (!ReadTables())\r
+        return S_FALSE;\r
+    pos = globalPos - startPos;\r
+    if (progress != 0)\r
+    {\r
+      UInt64 packSize = m_InBitStream.GetProcessedSize();\r
+      RINOK(progress->SetRatioInfo(&packSize, &pos));\r
+    }\r
+  }\r
+  if (pos > unPackSize)\r
+    return S_FALSE;\r
+\r
+  if (!ReadLastTables())\r
+    return S_FALSE;\r
+  return m_OutWindowStream.Flush();\r
+}\r
+\r
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  try { return CodeReal(inStream, outStream, inSize, outSize, progress); }\r
+  catch(const CInBufferException &e) { return e.ErrorCode; }\r
+  catch(const CLzOutWindowException &e) { return e.ErrorCode; }\r
+  catch(...) { return S_FALSE; }\r
+}\r
+\r
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)\r
+{\r
+  if (size < 1)\r
+    return E_INVALIDARG;\r
+  m_IsSolid = (data[0] != 0);\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Compress/Rar2Decoder.h b/CPP/7zip/Compress/Rar2Decoder.h
new file mode 100755 (executable)
index 0000000..65cc973
--- /dev/null
@@ -0,0 +1,174 @@
+// Rar2Decoder.h\r
+// According to unRAR license, this code may not be used to develop\r
+// a program that creates RAR archives\r
+\r
+#ifndef __COMPRESS_RAR2_DECODER_H\r
+#define __COMPRESS_RAR2_DECODER_H\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "../Common/InBuffer.h"\r
+\r
+#include "BitmDecoder.h"\r
+#include "HuffmanDecoder.h"\r
+#include "LzOutWindow.h"\r
+\r
+namespace NCompress {\r
+namespace NRar2 {\r
+\r
+const UInt32 kNumRepDists = 4;\r
+const UInt32 kDistTableSize = 48;\r
+\r
+const int kMMTableSize = 256 + 1;\r
+\r
+const UInt32 kMainTableSize = 298;\r
+const UInt32 kLenTableSize = 28;\r
+\r
+const UInt32 kDistTableStart = kMainTableSize;\r
+const UInt32 kLenTableStart = kDistTableStart + kDistTableSize;\r
+\r
+const UInt32 kHeapTablesSizesSum = kMainTableSize + kDistTableSize + kLenTableSize;\r
+\r
+const UInt32 kLevelTableSize = 19;\r
+\r
+const UInt32 kMMTablesSizesSum = kMMTableSize * 4;\r
+\r
+const UInt32 kMaxTableSize = kMMTablesSizesSum;\r
+\r
+const UInt32 kTableDirectLevels = 16;\r
+const UInt32 kTableLevelRepNumber = kTableDirectLevels;\r
+const UInt32 kTableLevel0Number = kTableLevelRepNumber + 1;\r
+const UInt32 kTableLevel0Number2 = kTableLevel0Number + 1;\r
+\r
+const UInt32 kLevelMask = 0xF;\r
+\r
+\r
+const UInt32 kRepBothNumber = 256;\r
+const UInt32 kRepNumber = kRepBothNumber + 1;\r
+const UInt32 kLen2Number = kRepNumber + 4;\r
+\r
+const UInt32 kLen2NumNumbers = 8;\r
+const UInt32 kReadTableNumber = kLen2Number + kLen2NumNumbers;\r
+const UInt32 kMatchNumber = kReadTableNumber + 1;\r
+\r
+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};\r
+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};\r
+\r
+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};\r
+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};\r
+\r
+const Byte kLevelDirectBits[kLevelTableSize] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7};\r
+\r
+const Byte kLen2DistStarts[kLen2NumNumbers]={0,4,8,16,32,64,128,192};\r
+const Byte kLen2DistDirectBits[kLen2NumNumbers]={2,2,3, 4, 5, 6,  6,  6};\r
+\r
+const UInt32 kDistLimit2 = 0x101 - 1;\r
+const UInt32 kDistLimit3 = 0x2000 - 1;\r
+const UInt32 kDistLimit4 = 0x40000 - 1;\r
+\r
+const UInt32 kMatchMaxLen = 255 + 2;\r
+const UInt32 kMatchMaxLenMax = 255 + 5;\r
+const UInt32 kNormalMatchMinLen = 3;\r
+\r
+namespace NMultimedia {\r
+\r
+struct CFilter\r
+{\r
+  int K1,K2,K3,K4,K5;\r
+  int D1,D2,D3,D4;\r
+  int LastDelta;\r
+  UInt32 Dif[11];\r
+  UInt32 ByteCount;\r
+  int LastChar;\r
+\r
+  Byte Decode(int &channelDelta, Byte delta);\r
+\r
+  void Init() { memset(this, 0, sizeof(*this)); }\r
+\r
+};\r
+\r
+const int kNumChanelsMax = 4;\r
+\r
+class CFilter2\r
+{\r
+public:\r
+  CFilter  m_Filters[kNumChanelsMax];\r
+  int m_ChannelDelta;\r
+  int CurrentChannel;\r
+\r
+  void Init() { memset(this, 0, sizeof(*this)); }\r
+  Byte Decode(Byte delta)\r
+  {\r
+    return m_Filters[CurrentChannel].Decode(m_ChannelDelta, delta);\r
+  }\r
+\r
+};\r
+\r
+}\r
+\r
+typedef NBitm::CDecoder<CInBuffer> CBitDecoder;\r
+\r
+const int kNumHuffmanBits = 15;\r
+\r
+class CDecoder :\r
+  public ICompressCoder,\r
+  public ICompressSetDecoderProperties2,\r
+  public CMyUnknownImp\r
+{\r
+  CLzOutWindow m_OutWindowStream;\r
+  CBitDecoder m_InBitStream;\r
+  NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder;\r
+  NHuffman::CDecoder<kNumHuffmanBits, kDistTableSize> m_DistDecoder;\r
+  NHuffman::CDecoder<kNumHuffmanBits, kLenTableSize> m_LenDecoder;\r
+  NHuffman::CDecoder<kNumHuffmanBits, kMMTableSize> m_MMDecoders[NMultimedia::kNumChanelsMax];\r
+  NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder;\r
+\r
+  bool m_AudioMode;\r
+\r
+  NMultimedia::CFilter2 m_MmFilter;\r
+  int m_NumChannels;\r
+\r
+  UInt32 m_RepDists[kNumRepDists];\r
+  UInt32 m_RepDistPtr;\r
+\r
+  UInt32 m_LastLength;\r
+  \r
+  Byte m_LastLevels[kMaxTableSize];\r
+\r
+  UInt64 m_PackSize;\r
+  bool m_IsSolid;\r
+\r
+  void InitStructures();\r
+  UInt32 ReadBits(int numBits);\r
+  bool ReadTables();\r
+  bool ReadLastTables();\r
+\r
+  bool DecodeMm(UInt32 pos);\r
+  bool DecodeLz(Int32 pos);\r
+\r
+  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+public:\r
+  CDecoder();\r
+\r
+  MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)\r
+\r
+  void ReleaseStreams()\r
+  {\r
+    m_OutWindowStream.ReleaseStream();\r
+    m_InBitStream.ReleaseStream();\r
+  }\r
+\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);\r
+\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp
new file mode 100755 (executable)
index 0000000..fd76212
--- /dev/null
@@ -0,0 +1,897 @@
+// Rar3Decoder.cpp\r
+// According to unRAR license, this code may not be used to develop\r
+// a program that creates RAR archives\r
+\r
+/* This code uses Carryless rangecoder (1999): Dmitry Subbotin : Public domain */\r
\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "Rar3Decoder.h"\r
+\r
+namespace NCompress {\r
+namespace NRar3 {\r
+\r
+static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }\r
+static void SzBigFree(void *, void *address) { BigFree(address); }\r
+static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };\r
+\r
+static const UInt32 kNumAlignReps = 15;\r
+\r
+static const UInt32 kSymbolReadTable = 256;\r
+static const UInt32 kSymbolRep = 259;\r
+static const UInt32 kSymbolLen2 = kSymbolRep + kNumReps;\r
+\r
+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};\r
+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};\r
+\r
+static const Byte kDistDirectBits[kDistTableSize] =\r
+  {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,\r
+  16,16,16,16,16,16,16,16,16,16,16,16,16,16,\r
+  18,18,18,18,18,18,18,18,18,18,18,18};\r
+\r
+static const Byte kLevelDirectBits[kLevelTableSize] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};\r
+\r
+static const Byte kLen2DistStarts[kNumLen2Symbols]={0,4,8,16,32,64,128,192};\r
+static const Byte kLen2DistDirectBits[kNumLen2Symbols]={2,2,3, 4, 5, 6,  6,  6};\r
+\r
+static const UInt32 kDistLimit3 = 0x2000 - 2;\r
+static const UInt32 kDistLimit4 = 0x40000 - 2;\r
+\r
+static const UInt32 kNormalMatchMinLen = 3;\r
+\r
+static const UInt32 kVmDataSizeMax = 1 << 16;\r
+static const UInt32 kVmCodeSizeMax = 1 << 16;\r
+\r
+extern "C" {\r
+\r
+static UInt32 Range_GetThreshold(void *pp, UInt32 total)\r
+{\r
+  CRangeDecoder *p = (CRangeDecoder *)pp;\r
+  return p->Code / (p->Range /= total);\r
+}\r
+\r
+static void Range_Decode(void *pp, UInt32 start, UInt32 size)\r
+{\r
+  CRangeDecoder *p = (CRangeDecoder *)pp;\r
+  start *= p->Range;\r
+  p->Low += start;\r
+  p->Code -= start;\r
+  p->Range *= size;\r
+  p->Normalize();\r
+}\r
+\r
+static UInt32 Range_DecodeBit(void *pp, UInt32 size0)\r
+{\r
+  CRangeDecoder *p = (CRangeDecoder *)pp;\r
+  if (p->Code / (p->Range >>= 14) < size0)\r
+  {\r
+    Range_Decode(p, 0, size0);\r
+    return 0;\r
+  }\r
+  else\r
+  {\r
+    Range_Decode(p, size0, (1 << 14) - size0);\r
+    return 1;\r
+  }\r
+}\r
+\r
+}\r
+\r
+CRangeDecoder::CRangeDecoder()\r
+{\r
+  s.GetThreshold = Range_GetThreshold;\r
+  s.Decode = Range_Decode;\r
+  s.DecodeBit = Range_DecodeBit;\r
+}\r
+\r
+CDecoder::CDecoder():\r
+  _window(0),\r
+  _winPos(0),\r
+  _wrPtr(0),\r
+  _lzSize(0),\r
+  _writtenFileSize(0),\r
+  _vmData(0),\r
+  _vmCode(0),\r
+  m_IsSolid(false)\r
+{\r
+  Ppmd7_Construct(&_ppmd);\r
+}\r
+\r
+CDecoder::~CDecoder()\r
+{\r
+  InitFilters();\r
+  ::MidFree(_vmData);\r
+  ::MidFree(_window);\r
+  Ppmd7_Free(&_ppmd, &g_BigAlloc);\r
+}\r
+\r
+HRESULT CDecoder::WriteDataToStream(const Byte *data, UInt32 size)\r
+{\r
+  return WriteStream(_outStream, data, size);\r
+}\r
+\r
+HRESULT CDecoder::WriteData(const Byte *data, UInt32 size)\r
+{\r
+  HRESULT res = S_OK;\r
+  if (_writtenFileSize < _unpackSize)\r
+  {\r
+    UInt32 curSize = size;\r
+    UInt64 remain = _unpackSize - _writtenFileSize;\r
+    if (remain < curSize)\r
+      curSize = (UInt32)remain;\r
+    res = WriteDataToStream(data, curSize);\r
+  }\r
+  _writtenFileSize += size;\r
+  return res;\r
+}\r
+\r
+HRESULT CDecoder::WriteArea(UInt32 startPtr, UInt32 endPtr)\r
+{\r
+  if (startPtr <= endPtr)\r
+    return WriteData(_window + startPtr, endPtr - startPtr);\r
+  RINOK(WriteData(_window + startPtr, kWindowSize - startPtr));\r
+  return WriteData(_window, endPtr);\r
+}\r
+\r
+void CDecoder::ExecuteFilter(int tempFilterIndex, NVm::CBlockRef &outBlockRef)\r
+{\r
+  CTempFilter *tempFilter = _tempFilters[tempFilterIndex];\r
+  tempFilter->InitR[6] = (UInt32)_writtenFileSize;\r
+  NVm::SetValue32(&tempFilter->GlobalData[0x24], (UInt32)_writtenFileSize);\r
+  NVm::SetValue32(&tempFilter->GlobalData[0x28], (UInt32)(_writtenFileSize >> 32));\r
+  CFilter *filter = _filters[tempFilter->FilterIndex];\r
+  _vm.Execute(filter, tempFilter, outBlockRef, filter->GlobalData);\r
+  delete tempFilter;\r
+  _tempFilters[tempFilterIndex] = 0;\r
+}\r
+\r
+HRESULT CDecoder::WriteBuf()\r
+{\r
+  UInt32 writtenBorder = _wrPtr;\r
+  UInt32 writeSize = (_winPos - writtenBorder) & kWindowMask;\r
+  for (int i = 0; i < _tempFilters.Size(); i++)\r
+  {\r
+    CTempFilter *filter = _tempFilters[i];\r
+    if (filter == NULL)\r
+      continue;\r
+    if (filter->NextWindow)\r
+    {\r
+      filter->NextWindow = false;\r
+      continue;\r
+    }\r
+    UInt32 blockStart = filter->BlockStart;\r
+    UInt32 blockSize = filter->BlockSize;\r
+    if (((blockStart - writtenBorder) & kWindowMask) < writeSize)\r
+    {\r
+      if (writtenBorder != blockStart)\r
+      {\r
+        RINOK(WriteArea(writtenBorder, blockStart));\r
+        writtenBorder = blockStart;\r
+        writeSize = (_winPos - writtenBorder) & kWindowMask;\r
+      }\r
+      if (blockSize <= writeSize)\r
+      {\r
+        UInt32 blockEnd = (blockStart + blockSize) & kWindowMask;\r
+        if (blockStart < blockEnd || blockEnd == 0)\r
+          _vm.SetMemory(0, _window + blockStart, blockSize);\r
+        else\r
+        {\r
+          UInt32 tailSize = kWindowSize - blockStart;\r
+          _vm.SetMemory(0, _window + blockStart, tailSize);\r
+          _vm.SetMemory(tailSize, _window, blockEnd);\r
+        }\r
+        NVm::CBlockRef outBlockRef;\r
+        ExecuteFilter(i, outBlockRef);\r
+        while (i + 1 < _tempFilters.Size())\r
+        {\r
+          CTempFilter *nextFilter = _tempFilters[i + 1];\r
+          if (nextFilter == NULL || nextFilter->BlockStart != blockStart ||\r
+              nextFilter->BlockSize != outBlockRef.Size || nextFilter->NextWindow)\r
+            break;\r
+          _vm.SetMemory(0, _vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size);\r
+          ExecuteFilter(++i, outBlockRef);\r
+        }\r
+        WriteDataToStream(_vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size);\r
+        _writtenFileSize += outBlockRef.Size;\r
+        writtenBorder = blockEnd;\r
+        writeSize = (_winPos - writtenBorder) & kWindowMask;\r
+      }\r
+      else\r
+      {\r
+        for (int j = i; j < _tempFilters.Size(); j++)\r
+        {\r
+          CTempFilter *filter = _tempFilters[j];\r
+          if (filter != NULL && filter->NextWindow)\r
+            filter->NextWindow = false;\r
+        }\r
+        _wrPtr = writtenBorder;\r
+        return S_OK; // check it\r
+      }\r
+    }\r
+  }\r
+      \r
+  _wrPtr = _winPos;\r
+  return WriteArea(writtenBorder, _winPos);\r
+}\r
+\r
+void CDecoder::InitFilters()\r
+{\r
+  _lastFilter = 0;\r
+  int i;\r
+  for (i = 0; i < _tempFilters.Size(); i++)\r
+    delete _tempFilters[i];\r
+  _tempFilters.Clear();\r
+  for (i = 0; i < _filters.Size(); i++)\r
+    delete _filters[i];\r
+  _filters.Clear();\r
+}\r
+\r
+bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)\r
+{\r
+  CMemBitDecoder inp;\r
+  inp.Init(_vmData, codeSize);\r
+\r
+  UInt32 filterIndex;\r
+  if (firstByte & 0x80)\r
+  {\r
+    filterIndex = NVm::ReadEncodedUInt32(inp);\r
+    if (filterIndex == 0)\r
+      InitFilters();\r
+    else\r
+      filterIndex--;\r
+  }\r
+  else\r
+    filterIndex = _lastFilter;\r
+  if (filterIndex > (UInt32)_filters.Size())\r
+    return false;\r
+  _lastFilter = filterIndex;\r
+  bool newFilter = (filterIndex == (UInt32)_filters.Size());\r
+\r
+  CFilter *filter;\r
+  if (newFilter)\r
+  {\r
+    // check if too many filters\r
+    if (filterIndex > 1024)\r
+      return false;\r
+    filter = new CFilter;\r
+    _filters.Add(filter);\r
+  }\r
+  else\r
+  {\r
+    filter = _filters[filterIndex];\r
+    filter->ExecCount++;\r
+  }\r
+\r
+  int numEmptyItems = 0;\r
+  int i;\r
+  for (i = 0; i < _tempFilters.Size(); i++)\r
+  {\r
+    _tempFilters[i - numEmptyItems] = _tempFilters[i];\r
+    if (_tempFilters[i] == NULL)\r
+      numEmptyItems++;\r
+    if (numEmptyItems > 0)\r
+      _tempFilters[i] = NULL;\r
+  }\r
+  if (numEmptyItems == 0)\r
+  {\r
+    _tempFilters.Add(NULL);\r
+    numEmptyItems = 1;\r
+  }\r
+  CTempFilter *tempFilter = new CTempFilter;\r
+  _tempFilters[_tempFilters.Size() - numEmptyItems] = tempFilter;\r
+  tempFilter->FilterIndex = filterIndex;\r
+  tempFilter->ExecCount = filter->ExecCount;\r
\r
+  UInt32 blockStart = NVm::ReadEncodedUInt32(inp);\r
+  if (firstByte & 0x40)\r
+    blockStart += 258;\r
+  tempFilter->BlockStart = (blockStart + _winPos) & kWindowMask;\r
+  if (firstByte & 0x20)\r
+    filter->BlockSize = NVm::ReadEncodedUInt32(inp);\r
+  tempFilter->BlockSize = filter->BlockSize;\r
+  tempFilter->NextWindow = _wrPtr != _winPos && ((_wrPtr - _winPos) & kWindowMask) <= blockStart;\r
+\r
+  memset(tempFilter->InitR, 0, sizeof(tempFilter->InitR));\r
+  tempFilter->InitR[3] = NVm::kGlobalOffset;\r
+  tempFilter->InitR[4] = tempFilter->BlockSize;\r
+  tempFilter->InitR[5] = tempFilter->ExecCount;\r
+  if (firstByte & 0x10)\r
+  {\r
+    UInt32 initMask = inp.ReadBits(NVm::kNumGpRegs);\r
+    for (int i = 0; i < NVm::kNumGpRegs; i++)\r
+      if (initMask & (1 << i))\r
+        tempFilter->InitR[i] = NVm::ReadEncodedUInt32(inp);\r
+  }\r
+  if (newFilter)\r
+  {\r
+    UInt32 vmCodeSize = NVm::ReadEncodedUInt32(inp);\r
+    if (vmCodeSize >= kVmCodeSizeMax || vmCodeSize == 0)\r
+      return false;\r
+    for (UInt32 i = 0; i < vmCodeSize; i++)\r
+      _vmCode[i] = (Byte)inp.ReadBits(8);\r
+    _vm.PrepareProgram(_vmCode, vmCodeSize, filter);\r
+  }\r
+\r
+  tempFilter->AllocateEmptyFixedGlobal();\r
+\r
+  Byte *globalData = &tempFilter->GlobalData[0];\r
+  for (i = 0; i < NVm::kNumGpRegs; i++)\r
+    NVm::SetValue32(&globalData[i * 4], tempFilter->InitR[i]);\r
+  NVm::SetValue32(&globalData[NVm::NGlobalOffset::kBlockSize], tempFilter->BlockSize);\r
+  NVm::SetValue32(&globalData[NVm::NGlobalOffset::kBlockPos], 0); // It was commented. why?\r
+  NVm::SetValue32(&globalData[NVm::NGlobalOffset::kExecCount], tempFilter->ExecCount);\r
+\r
+  if (firstByte & 8)\r
+  {\r
+    UInt32 dataSize = NVm::ReadEncodedUInt32(inp);\r
+    if (dataSize > NVm::kGlobalSize - NVm::kFixedGlobalSize)\r
+      return false;\r
+    CRecordVector<Byte> &globalData = tempFilter->GlobalData;\r
+    int requredSize = (int)(dataSize + NVm::kFixedGlobalSize);\r
+    if (globalData.Size() < requredSize)\r
+    {\r
+      globalData.Reserve(requredSize);\r
+      for (; globalData.Size() < requredSize; i++)\r
+        globalData.Add(0);\r
+    }\r
+    for (UInt32 i = 0; i < dataSize; i++)\r
+      globalData[NVm::kFixedGlobalSize + i] = (Byte)inp.ReadBits(8);\r
+  }\r
+  return true;\r
+}\r
+\r
+bool CDecoder::ReadVmCodeLZ()\r
+{\r
+  UInt32 firstByte = ReadBits(8);\r
+  UInt32 length = (firstByte & 7) + 1;\r
+  if (length == 7)\r
+    length = ReadBits(8) + 7;\r
+  else if (length == 8)\r
+    length = ReadBits(16);\r
+  if (length > kVmDataSizeMax)\r
+    return false;\r
+  for (UInt32 i = 0; i < length; i++)\r
+    _vmData[i] = (Byte)ReadBits(8);\r
+  return AddVmCode(firstByte, length);\r
+}\r
+\r
+bool CDecoder::ReadVmCodePPM()\r
+{\r
+  int firstByte = DecodePpmSymbol();\r
+  if (firstByte < 0)\r
+    return false;\r
+  UInt32 length = (firstByte & 7) + 1;\r
+  if (length == 7)\r
+  {\r
+    int b1 = DecodePpmSymbol();\r
+    if (b1 < 0)\r
+      return false;\r
+    length = b1 + 7;\r
+  }\r
+  else if (length == 8)\r
+  {\r
+    int b1 = DecodePpmSymbol();\r
+    if (b1 < 0)\r
+      return false;\r
+    int b2 = DecodePpmSymbol();\r
+    if (b2 < 0)\r
+      return false;\r
+    length = b1 * 256 + b2;\r
+  }\r
+  if (length > kVmDataSizeMax)\r
+    return false;\r
+  for (UInt32 i = 0; i < length; i++)\r
+  {\r
+    int b = DecodePpmSymbol();\r
+    if (b < 0)\r
+      return false;\r
+    _vmData[i] = (Byte)b;\r
+  }\r
+  return AddVmCode(firstByte, length);\r
+}\r
+\r
+#define RIF(x) { if (!(x)) return S_FALSE; }\r
+\r
+UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.bitDecoder.ReadBits(numBits); }\r
+\r
+/////////////////////////////////////////////////\r
+// PPM\r
+\r
+HRESULT CDecoder::InitPPM()\r
+{\r
+  Byte maxOrder = (Byte)ReadBits(7);\r
+\r
+  bool reset = ((maxOrder & 0x20) != 0);\r
+  int maxMB = 0;\r
+  if (reset)\r
+    maxMB = (Byte)ReadBits(8);\r
+  else\r
+  {\r
+    if (PpmError || !Ppmd7_WasAllocated(&_ppmd))\r
+      return S_FALSE;\r
+  }\r
+  if (maxOrder & 0x40)\r
+    PpmEscChar = (Byte)ReadBits(8);\r
+  m_InBitStream.InitRangeCoder();\r
+  /*\r
+  if (m_InBitStream.m_BitPos != 0)\r
+    return S_FALSE;\r
+  */\r
+  if (reset)\r
+  {\r
+    PpmError = true;\r
+    maxOrder = (maxOrder & 0x1F) + 1;\r
+    if (maxOrder > 16)\r
+      maxOrder = 16 + (maxOrder - 16) * 3;\r
+    if (maxOrder == 1)\r
+    {\r
+      Ppmd7_Free(&_ppmd, &g_BigAlloc);\r
+      return S_FALSE;\r
+    }\r
+    if (!Ppmd7_Alloc(&_ppmd, (maxMB + 1) << 20, &g_BigAlloc))\r
+      return E_OUTOFMEMORY;\r
+    Ppmd7_Init(&_ppmd, maxOrder);\r
+    PpmError = false;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+int CDecoder::DecodePpmSymbol() { return Ppmd7_DecodeSymbol(&_ppmd, &m_InBitStream.s); }\r
+\r
+HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing)\r
+{\r
+  keepDecompressing = false;\r
+  if (PpmError)\r
+    return S_FALSE;\r
+  do\r
+  {\r
+    if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos)\r
+    {\r
+      RINOK(WriteBuf());\r
+      if (_writtenFileSize > _unpackSize)\r
+      {\r
+        keepDecompressing = false;\r
+        return S_OK;\r
+      }\r
+    }\r
+    int c = DecodePpmSymbol();\r
+    if (c < 0)\r
+    {\r
+      PpmError = true;\r
+      return S_FALSE;\r
+    }\r
+    if (c == PpmEscChar)\r
+    {\r
+      int nextCh = DecodePpmSymbol();\r
+      if (nextCh < 0)\r
+      {\r
+        PpmError = true;\r
+        return S_FALSE;\r
+      }\r
+      if (nextCh == 0)\r
+        return ReadTables(keepDecompressing);\r
+      if (nextCh == 2 || nextCh == -1)\r
+        return S_OK;\r
+      if (nextCh == 3)\r
+      {\r
+        if (!ReadVmCodePPM())\r
+        {\r
+          PpmError = true;\r
+          return S_FALSE;\r
+        }\r
+        continue;\r
+      }\r
+      if (nextCh == 4 || nextCh == 5)\r
+      {\r
+        UInt32 distance = 0;\r
+        UInt32 length = 4;\r
+        if (nextCh == 4)\r
+        {\r
+          for (int i = 0; i < 3; i++)\r
+          {\r
+            int c = DecodePpmSymbol();\r
+            if (c < 0)\r
+            {\r
+              PpmError = true;\r
+              return S_FALSE;\r
+            }\r
+            distance = (distance << 8) + (Byte)c;\r
+          }\r
+          distance++;\r
+          length += 28;\r
+        }\r
+        int c = DecodePpmSymbol();\r
+        if (c < 0)\r
+        {\r
+          PpmError = true;\r
+          return S_FALSE;\r
+        }\r
+        length += c;\r
+        if (distance >= _lzSize)\r
+          return S_FALSE;\r
+        CopyBlock(distance, length);\r
+        num -= (Int32)length;\r
+        continue;\r
+      }\r
+    }\r
+    PutByte((Byte)c);\r
+    num--;\r
+  }\r
+  while (num >= 0);\r
+  keepDecompressing = true;\r
+  return S_OK;\r
+}\r
+\r
+/////////////////////////////////////////////////\r
+// LZ\r
+\r
+HRESULT CDecoder::ReadTables(bool &keepDecompressing)\r
+{\r
+  keepDecompressing = true;\r
+  ReadBits((8 - m_InBitStream.bitDecoder.GetBitPosition()) & 7);\r
+  if (ReadBits(1) != 0)\r
+  {\r
+    _lzMode = false;\r
+    return InitPPM();\r
+  }\r
+\r
+  _lzMode = true;\r
+  PrevAlignBits = 0;\r
+  PrevAlignCount = 0;\r
+\r
+  Byte levelLevels[kLevelTableSize];\r
+  Byte newLevels[kTablesSizesSum];\r
+\r
+  if (ReadBits(1) == 0)\r
+    memset(m_LastLevels, 0, kTablesSizesSum);\r
+\r
+  int i;\r
+  for (i = 0; i < kLevelTableSize; i++)\r
+  {\r
+    UInt32 length = ReadBits(4);\r
+    if (length == 15)\r
+    {\r
+      UInt32 zeroCount = ReadBits(4);\r
+      if (zeroCount != 0)\r
+      {\r
+        zeroCount += 2;\r
+        while (zeroCount-- > 0 && i < kLevelTableSize)\r
+          levelLevels[i++]=0;\r
+        i--;\r
+        continue;\r
+      }\r
+    }\r
+    levelLevels[i] = (Byte)length;\r
+  }\r
+  RIF(m_LevelDecoder.SetCodeLengths(levelLevels));\r
+  i = 0;\r
+  while (i < kTablesSizesSum)\r
+  {\r
+    UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream.bitDecoder);\r
+    if (number < 16)\r
+    {\r
+      newLevels[i] = Byte((number + m_LastLevels[i]) & 15);\r
+      i++;\r
+    }\r
+    else if (number > kLevelTableSize)\r
+      return S_FALSE;\r
+    else\r
+    {\r
+      int num;\r
+      if (((number - 16) & 1) == 0)\r
+        num = ReadBits(3) + 3;\r
+      else\r
+        num = ReadBits(7) + 11;\r
+      if (number < 18)\r
+      {\r
+        if (i == 0)\r
+          return S_FALSE;\r
+        for (; num > 0 && i < kTablesSizesSum; num--, i++)\r
+          newLevels[i] = newLevels[i - 1];\r
+      }\r
+      else\r
+      {\r
+        for (; num > 0 && i < kTablesSizesSum; num--)\r
+          newLevels[i++] = 0;\r
+      }\r
+    }\r
+  }\r
+  TablesRead = true;\r
+\r
+  // original code has check here:\r
+  /*\r
+  if (InAddr > ReadTop)\r
+  {\r
+    keepDecompressing = false;\r
+    return true;\r
+  }\r
+  */\r
+\r
+  RIF(m_MainDecoder.SetCodeLengths(&newLevels[0]));\r
+  RIF(m_DistDecoder.SetCodeLengths(&newLevels[kMainTableSize]));\r
+  RIF(m_AlignDecoder.SetCodeLengths(&newLevels[kMainTableSize + kDistTableSize]));\r
+  RIF(m_LenDecoder.SetCodeLengths(&newLevels[kMainTableSize + kDistTableSize + kAlignTableSize]));\r
+\r
+  memcpy(m_LastLevels, newLevels, kTablesSizesSum);\r
+  return S_OK;\r
+}\r
+\r
+class CCoderReleaser\r
+{\r
+  CDecoder *m_Coder;\r
+public:\r
+  CCoderReleaser(CDecoder *coder): m_Coder(coder) {}\r
+  ~CCoderReleaser()\r
+  {\r
+    m_Coder->ReleaseStreams();\r
+  }\r
+};\r
+\r
+HRESULT CDecoder::ReadEndOfBlock(bool &keepDecompressing)\r
+{\r
+  if (ReadBits(1) != 0)\r
+  {\r
+    // old file\r
+    TablesRead = false;\r
+    return ReadTables(keepDecompressing);\r
+  }\r
+  // new file\r
+  keepDecompressing = false;\r
+  TablesRead = (ReadBits(1) == 0);\r
+  return S_OK;\r
+}\r
+\r
+UInt32 kDistStart[kDistTableSize];\r
+\r
+class CDistInit\r
+{\r
+public:\r
+  CDistInit() { Init(); }\r
+  void Init()\r
+  {\r
+    UInt32 start = 0;\r
+    for (UInt32 i = 0; i < kDistTableSize; i++)\r
+    {\r
+      kDistStart[i] = start;\r
+      start += (1 << kDistDirectBits[i]);\r
+    }\r
+  }\r
+} g_DistInit;\r
+\r
+HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)\r
+{\r
+  UInt32 rep0 = _reps[0];\r
+  UInt32 rep1 = _reps[1];\r
+  UInt32 rep2 = _reps[2];\r
+  UInt32 rep3 = _reps[3];\r
+  UInt32 length = _lastLength;\r
+  for (;;)\r
+  {\r
+    if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos)\r
+    {\r
+      RINOK(WriteBuf());\r
+      if (_writtenFileSize > _unpackSize)\r
+      {\r
+        keepDecompressing = false;\r
+        return S_OK;\r
+      }\r
+    }\r
+    UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream.bitDecoder);\r
+    if (number < 256)\r
+    {\r
+      PutByte((Byte)number);\r
+      continue;\r
+    }\r
+    else if (number == kSymbolReadTable)\r
+    {\r
+      RINOK(ReadEndOfBlock(keepDecompressing));\r
+      break;\r
+    }\r
+    else if (number == 257)\r
+    {\r
+      if (!ReadVmCodeLZ())\r
+        return S_FALSE;\r
+      continue;\r
+    }\r
+    else if (number == 258)\r
+    {\r
+      if (length == 0)\r
+        return S_FALSE;\r
+    }\r
+    else if (number < kSymbolRep + 4)\r
+    {\r
+      if (number != kSymbolRep)\r
+      {\r
+        UInt32 distance;\r
+        if (number == kSymbolRep + 1)\r
+          distance = rep1;\r
+        else\r
+        {\r
+          if (number == kSymbolRep + 2)\r
+            distance = rep2;\r
+          else\r
+          {\r
+            distance = rep3;\r
+            rep3 = rep2;\r
+          }\r
+          rep2 = rep1;\r
+        }\r
+        rep1 = rep0;\r
+        rep0 = distance;\r
+      }\r
+\r
+      UInt32 number = m_LenDecoder.DecodeSymbol(&m_InBitStream.bitDecoder);\r
+      if (number >= kLenTableSize)\r
+        return S_FALSE;\r
+      length = 2 + kLenStart[number] + m_InBitStream.bitDecoder.ReadBits(kLenDirectBits[number]);\r
+    }\r
+    else\r
+    {\r
+      rep3 = rep2;\r
+      rep2 = rep1;\r
+      rep1 = rep0;\r
+      if (number < 271)\r
+      {\r
+        number -= 263;\r
+        rep0 = kLen2DistStarts[number] + m_InBitStream.bitDecoder.ReadBits(kLen2DistDirectBits[number]);\r
+        length = 2;\r
+      }\r
+      else if (number < 299)\r
+      {\r
+        number -= 271;\r
+        length = kNormalMatchMinLen + (UInt32)kLenStart[number] + m_InBitStream.bitDecoder.ReadBits(kLenDirectBits[number]);\r
+        UInt32 number = m_DistDecoder.DecodeSymbol(&m_InBitStream.bitDecoder);\r
+        if (number >= kDistTableSize)\r
+          return S_FALSE;\r
+        rep0 = kDistStart[number];\r
+        int numBits = kDistDirectBits[number];\r
+        if (number >= (kNumAlignBits * 2) + 2)\r
+        {\r
+          if (numBits > kNumAlignBits)\r
+            rep0 += (m_InBitStream.bitDecoder.ReadBits(numBits - kNumAlignBits) << kNumAlignBits);\r
+          if (PrevAlignCount > 0)\r
+          {\r
+            PrevAlignCount--;\r
+            rep0 += PrevAlignBits;\r
+          }\r
+          else\r
+          {\r
+            UInt32 number = m_AlignDecoder.DecodeSymbol(&m_InBitStream.bitDecoder);\r
+            if (number < (1 << kNumAlignBits))\r
+            {\r
+              rep0 += number;\r
+              PrevAlignBits = number;\r
+            }\r
+            else if (number  == (1 << kNumAlignBits))\r
+            {\r
+              PrevAlignCount = kNumAlignReps;\r
+              rep0 += PrevAlignBits;\r
+            }\r
+            else\r
+              return S_FALSE;\r
+          }\r
+        }\r
+        else\r
+          rep0 += m_InBitStream.bitDecoder.ReadBits(numBits);\r
+        length += ((kDistLimit4 - rep0) >> 31) + ((kDistLimit3 - rep0) >> 31);\r
+      }\r
+      else\r
+        return S_FALSE;\r
+    }\r
+    if (rep0 >= _lzSize)\r
+      return S_FALSE;\r
+    CopyBlock(rep0, length);\r
+  }\r
+  _reps[0] = rep0;\r
+  _reps[1] = rep1;\r
+  _reps[2] = rep2;\r
+  _reps[3] = rep3;\r
+  _lastLength = length;\r
+\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)\r
+{\r
+  _writtenFileSize = 0;\r
+  if (!m_IsSolid)\r
+  {\r
+    _lzSize = 0;\r
+    _winPos = 0;\r
+    _wrPtr = 0;\r
+    for (int i = 0; i < kNumReps; i++)\r
+      _reps[i] = 0;\r
+    _lastLength = 0;\r
+    memset(m_LastLevels, 0, kTablesSizesSum);\r
+    TablesRead = false;\r
+    PpmEscChar = 2;\r
+    PpmError = true;\r
+    InitFilters();\r
+  }\r
+  if (!m_IsSolid || !TablesRead)\r
+  {\r
+    bool keepDecompressing;\r
+    RINOK(ReadTables(keepDecompressing));\r
+    if (!keepDecompressing)\r
+      return S_OK;\r
+  }\r
+\r
+  for (;;)\r
+  {\r
+    bool keepDecompressing;\r
+    if (_lzMode)\r
+    {\r
+      RINOK(DecodeLZ(keepDecompressing))\r
+    }\r
+    else\r
+    {\r
+      RINOK(DecodePPM(1 << 18, keepDecompressing))\r
+    }\r
+    UInt64 packSize = m_InBitStream.bitDecoder.GetProcessedSize();\r
+    RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize));\r
+    if (!keepDecompressing)\r
+      break;\r
+  }\r
+  RINOK(WriteBuf());\r
+  UInt64 packSize = m_InBitStream.bitDecoder.GetProcessedSize();\r
+  RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize));\r
+  if (_writtenFileSize < _unpackSize)\r
+    return S_FALSE;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  try\r
+  {\r
+    if (inSize == NULL || outSize == NULL)\r
+      return E_INVALIDARG;\r
+\r
+    if (_vmData == 0)\r
+    {\r
+      _vmData = (Byte *)::MidAlloc(kVmDataSizeMax + kVmCodeSizeMax);\r
+      if (_vmData == 0)\r
+        return E_OUTOFMEMORY;\r
+      _vmCode = _vmData + kVmDataSizeMax;\r
+    }\r
+    \r
+    if (_window == 0)\r
+    {\r
+      _window = (Byte *)::MidAlloc(kWindowSize);\r
+      if (_window == 0)\r
+        return E_OUTOFMEMORY;\r
+    }\r
+    if (!m_InBitStream.bitDecoder.Create(1 << 20))\r
+      return E_OUTOFMEMORY;\r
+    if (!_vm.Create())\r
+      return E_OUTOFMEMORY;\r
+\r
+    \r
+    m_InBitStream.bitDecoder.SetStream(inStream);\r
+    m_InBitStream.bitDecoder.Init();\r
+    _outStream = outStream;\r
+   \r
+    CCoderReleaser coderReleaser(this);\r
+    _unpackSize = *outSize;\r
+    return CodeReal(progress);\r
+  }\r
+  catch(const CInBufferException &e)  { return e.ErrorCode; }\r
+  catch(...) { return S_FALSE; }\r
+  // CNewException is possible here. But probably CNewException is caused\r
+  // by error in data stream.\r
+}\r
+\r
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)\r
+{\r
+  if (size < 1)\r
+    return E_INVALIDARG;\r
+  m_IsSolid = (data[0] != 0);\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Compress/Rar3Decoder.h b/CPP/7zip/Compress/Rar3Decoder.h
new file mode 100755 (executable)
index 0000000..634f157
--- /dev/null
@@ -0,0 +1,267 @@
+// Rar3Decoder.h\r
+// According to unRAR license, this code may not be used to develop\r
+// a program that creates RAR archives\r
+\r
+/* This code uses Carryless rangecoder (1999): Dmitry Subbotin : Public domain */\r
+\r
+#ifndef __COMPRESS_RAR3_DECODER_H\r
+#define __COMPRESS_RAR3_DECODER_H\r
+\r
+#include "../../../C/Ppmd7.h"\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+#include "../Common/InBuffer.h"\r
+\r
+#include "BitmDecoder.h"\r
+#include "HuffmanDecoder.h"\r
+#include "Rar3Vm.h"\r
+\r
+namespace NCompress {\r
+namespace NRar3 {\r
+\r
+const UInt32 kWindowSize = 1 << 22;\r
+const UInt32 kWindowMask = (kWindowSize - 1);\r
+\r
+const UInt32 kNumReps = 4;\r
+const UInt32 kNumLen2Symbols = 8;\r
+const UInt32 kLenTableSize = 28;\r
+const UInt32 kMainTableSize = 256 + 1 + 1 + 1 + kNumReps + kNumLen2Symbols + kLenTableSize;\r
+const UInt32 kDistTableSize = 60;\r
+\r
+const int kNumAlignBits = 4;\r
+const UInt32 kAlignTableSize = (1 << kNumAlignBits) + 1;\r
+\r
+const UInt32 kLevelTableSize = 20;\r
+\r
+const UInt32 kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize + kLenTableSize;\r
+\r
+class CBitDecoder\r
+{\r
+  UInt32 m_Value;\r
+  unsigned m_BitPos;\r
+public:\r
+  CInBuffer m_Stream;\r
+  bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }\r
+  void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream);}\r
+  void ReleaseStream() { m_Stream.ReleaseStream();}\r
+\r
+  void Init()\r
+  {\r
+    m_Stream.Init();\r
+    m_BitPos = 0;\r
+    m_Value = 0;\r
+  }\r
+  \r
+  UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() - (m_BitPos) / 8; }\r
+  UInt32 GetBitPosition() const { return ((8 - m_BitPos) & 7); }\r
+  \r
+  UInt32 GetValue(unsigned numBits)\r
+  {\r
+    if (m_BitPos < numBits)\r
+    {\r
+      m_BitPos += 8;\r
+      m_Value = (m_Value << 8) | m_Stream.ReadByte();\r
+      if (m_BitPos < numBits)\r
+      {\r
+        m_BitPos += 8;\r
+        m_Value = (m_Value << 8) | m_Stream.ReadByte();\r
+      }\r
+    }\r
+    return m_Value >> (m_BitPos - numBits);\r
+  }\r
+  \r
+  void MovePos(unsigned numBits)\r
+  {\r
+    m_BitPos -= numBits;\r
+    m_Value = m_Value & ((1 << m_BitPos) - 1);\r
+  }\r
+  \r
+  UInt32 ReadBits(unsigned numBits)\r
+  {\r
+    UInt32 res = GetValue(numBits);\r
+    MovePos(numBits);\r
+    return res;\r
+  }\r
+};\r
+\r
+const UInt32 kTopValue = (1 << 24);\r
+const UInt32 kBot = (1 << 15);\r
+\r
+struct CRangeDecoder\r
+{\r
+  IPpmd7_RangeDec s;\r
+  UInt32 Range;\r
+  UInt32 Code;\r
+  UInt32 Low;\r
+  CBitDecoder bitDecoder;\r
+  SRes Res;\r
+\r
+public:\r
+  void InitRangeCoder()\r
+  {\r
+    Code = 0;\r
+    Low = 0;\r
+    Range = 0xFFFFFFFF;\r
+    for (int i = 0; i < 4; i++)\r
+      Code = (Code << 8) | bitDecoder.ReadBits(8);\r
+  }\r
+\r
+  void Normalize()\r
+  {\r
+    while ((Low ^ (Low + Range)) < kTopValue ||\r
+       Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1))\r
+    {\r
+      Code = (Code << 8) | bitDecoder.m_Stream.ReadByte();\r
+      Range <<= 8;\r
+      Low <<= 8;\r
+    }\r
+  }\r
+\r
+  CRangeDecoder();\r
+};\r
+\r
+struct CFilter: public NVm::CProgram\r
+{\r
+  CRecordVector<Byte> GlobalData;\r
+  UInt32 BlockStart;\r
+  UInt32 BlockSize;\r
+  UInt32 ExecCount;\r
+  CFilter(): BlockStart(0), BlockSize(0), ExecCount(0) {}\r
+};\r
+\r
+struct CTempFilter: public NVm::CProgramInitState\r
+{\r
+  UInt32 BlockStart;\r
+  UInt32 BlockSize;\r
+  UInt32 ExecCount;\r
+  bool NextWindow;\r
+  \r
+  UInt32 FilterIndex;\r
+};\r
+\r
+const int kNumHuffmanBits = 15;\r
+\r
+class CDecoder:\r
+  public ICompressCoder,\r
+  public ICompressSetDecoderProperties2,\r
+  public CMyUnknownImp\r
+{\r
+  CRangeDecoder m_InBitStream;\r
+  Byte *_window;\r
+  UInt32 _winPos;\r
+  UInt32 _wrPtr;\r
+  UInt64 _lzSize;\r
+  UInt64 _unpackSize;\r
+  UInt64 _writtenFileSize; // if it's > _unpackSize, then _unpackSize only written\r
+  CMyComPtr<ISequentialOutStream> _outStream;\r
+  NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder;\r
+  NHuffman::CDecoder<kNumHuffmanBits, kDistTableSize> m_DistDecoder;\r
+  NHuffman::CDecoder<kNumHuffmanBits, kAlignTableSize> m_AlignDecoder;\r
+  NHuffman::CDecoder<kNumHuffmanBits, kLenTableSize> m_LenDecoder;\r
+  NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder;\r
+\r
+  UInt32 _reps[kNumReps];\r
+  UInt32 _lastLength;\r
+  \r
+  Byte m_LastLevels[kTablesSizesSum];\r
+\r
+  Byte *_vmData;\r
+  Byte *_vmCode;\r
+  NVm::CVm _vm;\r
+  CRecordVector<CFilter *> _filters;\r
+  CRecordVector<CTempFilter *>  _tempFilters;\r
+  UInt32 _lastFilter;\r
+\r
+  bool m_IsSolid;\r
+\r
+  bool _lzMode;\r
+\r
+  UInt32 PrevAlignBits;\r
+  UInt32 PrevAlignCount;\r
+\r
+  bool TablesRead;\r
+\r
+  CPpmd7 _ppmd;\r
+  int PpmEscChar;\r
+  bool PpmError;\r
+  \r
+  HRESULT WriteDataToStream(const Byte *data, UInt32 size);\r
+  HRESULT WriteData(const Byte *data, UInt32 size);\r
+  HRESULT WriteArea(UInt32 startPtr, UInt32 endPtr);\r
+  void ExecuteFilter(int tempFilterIndex, NVm::CBlockRef &outBlockRef);\r
+  HRESULT WriteBuf();\r
+\r
+  void InitFilters();\r
+  bool AddVmCode(UInt32 firstByte, UInt32 codeSize);\r
+  bool ReadVmCodeLZ();\r
+  bool ReadVmCodePPM();\r
+  \r
+  UInt32 ReadBits(int numBits);\r
+\r
+  HRESULT InitPPM();\r
+  int DecodePpmSymbol();\r
+  HRESULT DecodePPM(Int32 num, bool &keepDecompressing);\r
+\r
+  HRESULT ReadTables(bool &keepDecompressing);\r
+  HRESULT ReadEndOfBlock(bool &keepDecompressing);\r
+  HRESULT DecodeLZ(bool &keepDecompressing);\r
+  HRESULT CodeReal(ICompressProgressInfo *progress);\r
+public:\r
+  CDecoder();\r
+  ~CDecoder();\r
+\r
+  MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)\r
+\r
+  void ReleaseStreams()\r
+  {\r
+    _outStream.Release();\r
+    m_InBitStream.bitDecoder.ReleaseStream();\r
+  }\r
+\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);\r
+\r
+  void CopyBlock(UInt32 distance, UInt32 len)\r
+  {\r
+    _lzSize += len;\r
+    UInt32 pos = (_winPos - distance - 1) & kWindowMask;\r
+    Byte *window = _window;\r
+    UInt32 winPos = _winPos;\r
+    if (kWindowSize - winPos > len && kWindowSize - pos > len)\r
+    {\r
+      const Byte *src = window + pos;\r
+      Byte *dest = window + winPos;\r
+      _winPos += len;\r
+      do\r
+        *dest++ = *src++;\r
+      while(--len != 0);\r
+      return;\r
+    }\r
+    do\r
+    {\r
+      window[winPos] = window[pos];\r
+      winPos = (winPos + 1) & kWindowMask;\r
+      pos = (pos + 1) & kWindowMask;\r
+    }\r
+    while(--len != 0);\r
+    _winPos = winPos;\r
+  }\r
+  \r
+  void PutByte(Byte b)\r
+  {\r
+    _window[_winPos] = b;\r
+    _winPos = (_winPos + 1) & kWindowMask;\r
+    _lzSize++;\r
+  }\r
+\r
+\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/Rar3Vm.cpp b/CPP/7zip/Compress/Rar3Vm.cpp
new file mode 100755 (executable)
index 0000000..9e28614
--- /dev/null
@@ -0,0 +1,1091 @@
+// Rar3Vm.cpp\r
+// According to unRAR license, this code may not be used to develop\r
+// a program that creates RAR archives\r
+\r
+/*\r
+Note:\r
+  Due to performance considerations Rar VM may set Flags C incorrectly\r
+  for some operands (SHL x, 0, ... ).\r
+  Check implementation of concrete VM command\r
+  to see if it sets flags right.\r
+*/\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/7zCrc.h"\r
+#include "../../../C/Alloc.h"\r
+\r
+#include "Rar3Vm.h"\r
+\r
+namespace NCompress {\r
+namespace NRar3 {\r
+\r
+UInt32 CMemBitDecoder::ReadBits(int numBits)\r
+{\r
+  UInt32 res = 0;\r
+  for (;;)\r
+  {\r
+    Byte b = _bitPos < _bitSize ? _data[_bitPos >> 3] : 0;\r
+    int avail = (int)(8 - (_bitPos & 7));\r
+    if (numBits <= avail)\r
+    {\r
+      _bitPos += numBits;\r
+      return res | (b >> (avail - numBits)) & ((1 << numBits) - 1);\r
+    }\r
+    numBits -= avail;\r
+    res |= (UInt32)(b & ((1 << avail) - 1)) << numBits;\r
+    _bitPos += avail;\r
+  }\r
+}\r
+\r
+UInt32 CMemBitDecoder::ReadBit() { return ReadBits(1); }\r
+\r
+namespace NVm {\r
+\r
+static const UInt32 kStackRegIndex = kNumRegs - 1;\r
+\r
+static const UInt32 FLAG_C = 1;\r
+static const UInt32 FLAG_Z = 2;\r
+static const UInt32 FLAG_S = 0x80000000;\r
+\r
+static const Byte CF_OP0 = 0;\r
+static const Byte CF_OP1 = 1;\r
+static const Byte CF_OP2 = 2;\r
+static const Byte CF_OPMASK = 3;\r
+static const Byte CF_BYTEMODE = 4;\r
+static const Byte CF_JUMP = 8;\r
+static const Byte CF_PROC = 16;\r
+static const Byte CF_USEFLAGS = 32;\r
+static const Byte CF_CHFLAGS = 64;\r
+\r
+static Byte kCmdFlags[]=\r
+{\r
+  /* CMD_MOV   */ CF_OP2 | CF_BYTEMODE,\r
+  /* CMD_CMP   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\r
+  /* CMD_ADD   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\r
+  /* CMD_SUB   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\r
+  /* CMD_JZ    */ CF_OP1 | CF_JUMP | CF_USEFLAGS,\r
+  /* CMD_JNZ   */ CF_OP1 | CF_JUMP | CF_USEFLAGS,\r
+  /* CMD_INC   */ CF_OP1 | CF_BYTEMODE | CF_CHFLAGS,\r
+  /* CMD_DEC   */ CF_OP1 | CF_BYTEMODE | CF_CHFLAGS,\r
+  /* CMD_JMP   */ CF_OP1 | CF_JUMP,\r
+  /* CMD_XOR   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\r
+  /* CMD_AND   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\r
+  /* CMD_OR    */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\r
+  /* CMD_TEST  */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\r
+  /* CMD_JS    */ CF_OP1 | CF_JUMP | CF_USEFLAGS,\r
+  /* CMD_JNS   */ CF_OP1 | CF_JUMP | CF_USEFLAGS,\r
+  /* CMD_JB    */ CF_OP1 | CF_JUMP | CF_USEFLAGS,\r
+  /* CMD_JBE   */ CF_OP1 | CF_JUMP | CF_USEFLAGS,\r
+  /* CMD_JA    */ CF_OP1 | CF_JUMP | CF_USEFLAGS,\r
+  /* CMD_JAE   */ CF_OP1 | CF_JUMP | CF_USEFLAGS,\r
+  /* CMD_PUSH  */ CF_OP1,\r
+  /* CMD_POP   */ CF_OP1,\r
+  /* CMD_CALL  */ CF_OP1 | CF_PROC,\r
+  /* CMD_RET   */ CF_OP0 | CF_PROC,\r
+  /* CMD_NOT   */ CF_OP1 | CF_BYTEMODE,\r
+  /* CMD_SHL   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\r
+  /* CMD_SHR   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\r
+  /* CMD_SAR   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\r
+  /* CMD_NEG   */ CF_OP1 | CF_BYTEMODE | CF_CHFLAGS,\r
+  /* CMD_PUSHA */ CF_OP0,\r
+  /* CMD_POPA  */ CF_OP0,\r
+  /* CMD_PUSHF */ CF_OP0 | CF_USEFLAGS,\r
+  /* CMD_POPF  */ CF_OP0 | CF_CHFLAGS,\r
+  /* CMD_MOVZX */ CF_OP2,\r
+  /* CMD_MOVSX */ CF_OP2,\r
+  /* CMD_XCHG  */ CF_OP2 | CF_BYTEMODE,\r
+  /* CMD_MUL   */ CF_OP2 | CF_BYTEMODE,\r
+  /* CMD_DIV   */ CF_OP2 | CF_BYTEMODE,\r
+  /* CMD_ADC   */ CF_OP2 | CF_BYTEMODE | CF_USEFLAGS | CF_CHFLAGS ,\r
+  /* CMD_SBB   */ CF_OP2 | CF_BYTEMODE | CF_USEFLAGS | CF_CHFLAGS ,\r
+  /* CMD_PRINT */ CF_OP0\r
+};\r
+\r
+CVm::CVm(): Mem(NULL) {}\r
+\r
+bool CVm::Create()\r
+{\r
+  if (Mem == NULL)\r
+    Mem = (Byte *)::MyAlloc(kSpaceSize + 4);\r
+  return (Mem != NULL);\r
+}\r
+\r
+CVm::~CVm()\r
+{\r
+  ::MyFree(Mem);\r
+}\r
+\r
+// CVm::Execute can change CProgram object: it clears progarm if VM returns error.\r
+\r
+bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,\r
+    CBlockRef &outBlockRef, CRecordVector<Byte> &outGlobalData)\r
+{\r
+  memcpy(R, initState->InitR, sizeof(initState->InitR));\r
+  R[kStackRegIndex] = kSpaceSize;\r
+  R[kNumRegs] = 0;\r
+  Flags = 0;\r
+\r
+  UInt32 globalSize = MyMin((UInt32)initState->GlobalData.Size(), kGlobalSize);\r
+  if (globalSize != 0)\r
+    memcpy(Mem + kGlobalOffset, &initState->GlobalData[0], globalSize);\r
+  UInt32 staticSize = MyMin((UInt32)prg->StaticData.Size(), kGlobalSize - globalSize);\r
+  if (staticSize != 0)\r
+    memcpy(Mem + kGlobalOffset + globalSize, &prg->StaticData[0], staticSize);\r
+\r
+  bool res = true;\r
+  #ifdef RARVM_STANDARD_FILTERS\r
+  if (prg->StandardFilterIndex >= 0)\r
+    ExecuteStandardFilter(prg->StandardFilterIndex);\r
+  else\r
+  #endif\r
+  {\r
+    res = ExecuteCode(prg);\r
+    if (!res)\r
+      prg->Commands[0].OpCode = CMD_RET;\r
+  }\r
+  UInt32 newBlockPos = GetFixedGlobalValue32(NGlobalOffset::kBlockPos) & kSpaceMask;\r
+  UInt32 newBlockSize = GetFixedGlobalValue32(NGlobalOffset::kBlockSize) & kSpaceMask;\r
+  if (newBlockPos + newBlockSize >= kSpaceSize)\r
+    newBlockPos = newBlockSize = 0;\r
+  outBlockRef.Offset = newBlockPos;\r
+  outBlockRef.Size = newBlockSize;\r
+\r
+  outGlobalData.Clear();\r
+  UInt32 dataSize = GetFixedGlobalValue32(NGlobalOffset::kGlobalMemOutSize);\r
+  dataSize = MyMin(dataSize, kGlobalSize - kFixedGlobalSize);\r
+  if (dataSize != 0)\r
+  {\r
+    dataSize += kFixedGlobalSize;\r
+    outGlobalData.Reserve(dataSize);\r
+    for (UInt32 i = 0; i < dataSize; i++)\r
+      outGlobalData.Add(Mem[kGlobalOffset + i]);\r
+  }\r
+  return res;\r
+}\r
+\r
+\r
+#define SET_IP(IP) \\r
+  if ((IP) >= numCommands) return true; \\r
+  if (--maxOpCount <= 0) return false; \\r
+  cmd = commands + (IP);\r
+\r
+#define GET_FLAG_S_B(res) (((res) & 0x80) ? FLAG_S : 0)\r
+#define SET_IP_OP1 { UInt32 val = GetOperand32(&cmd->Op1); SET_IP(val); }\r
+#define FLAGS_UPDATE_SZ Flags = res == 0 ? FLAG_Z : res & FLAG_S\r
+#define FLAGS_UPDATE_SZ_B Flags = (res & 0xFF) == 0 ? FLAG_Z : GET_FLAG_S_B(res)\r
+\r
+UInt32 CVm::GetOperand32(const COperand *op) const\r
+{\r
+  switch(op->Type)\r
+  {\r
+    case OP_TYPE_REG: return R[op->Data];\r
+    case OP_TYPE_REGMEM: return GetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask]);\r
+    default: return op->Data;\r
+  }\r
+}\r
+\r
+void CVm::SetOperand32(const COperand *op, UInt32 val)\r
+{\r
+  switch(op->Type)\r
+  {\r
+    case OP_TYPE_REG: R[op->Data] = val; return;\r
+    case OP_TYPE_REGMEM: SetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask], val); return;\r
+  }\r
+}\r
+\r
+Byte CVm::GetOperand8(const COperand *op) const\r
+{\r
+  switch(op->Type)\r
+  {\r
+    case OP_TYPE_REG: return (Byte)R[op->Data];\r
+    case OP_TYPE_REGMEM: return Mem[(op->Base + R[op->Data]) & kSpaceMask];;\r
+    default: return (Byte)op->Data;\r
+  }\r
+}\r
+\r
+void CVm::SetOperand8(const COperand *op, Byte val)\r
+{\r
+  switch(op->Type)\r
+  {\r
+    case OP_TYPE_REG: R[op->Data] = (R[op->Data] & 0xFFFFFF00) | val; return;\r
+    case OP_TYPE_REGMEM: Mem[(op->Base + R[op->Data]) & kSpaceMask] = val; return;\r
+  }\r
+}\r
+\r
+UInt32 CVm::GetOperand(bool byteMode, const COperand *op) const\r
+{\r
+  if (byteMode)\r
+    return GetOperand8(op);\r
+  return GetOperand32(op);\r
+}\r
+\r
+void CVm::SetOperand(bool byteMode, const COperand *op, UInt32 val)\r
+{\r
+  if (byteMode)\r
+    SetOperand8(op, (Byte)(val & 0xFF));\r
+  else\r
+    SetOperand32(op, val);\r
+}\r
+\r
+bool CVm::ExecuteCode(const CProgram *prg)\r
+{\r
+  Int32 maxOpCount = 25000000;\r
+  const CCommand *commands = &prg->Commands[0];\r
+  const CCommand *cmd = commands;\r
+  UInt32 numCommands = prg->Commands.Size();\r
+  for (;;)\r
+  {\r
+    switch(cmd->OpCode)\r
+    {\r
+      #ifndef RARVM_NO_VM\r
+      \r
+      case CMD_MOV:\r
+        SetOperand32(&cmd->Op1, GetOperand32(&cmd->Op2));\r
+        break;\r
+      case CMD_MOVB:\r
+        SetOperand8(&cmd->Op1, GetOperand8(&cmd->Op2));\r
+        break;\r
+      case CMD_CMP:\r
+        {\r
+          UInt32 v1 = GetOperand32(&cmd->Op1);\r
+          UInt32 res = v1 - GetOperand32(&cmd->Op2);\r
+          Flags = res == 0 ? FLAG_Z : (res > v1) | (res & FLAG_S);\r
+        }\r
+        break;\r
+      case CMD_CMPB:\r
+        {\r
+          Byte v1 = GetOperand8(&cmd->Op1);\r
+          Byte res = v1 - GetOperand8(&cmd->Op2);\r
+          res &= 0xFF;\r
+          Flags = res == 0 ? FLAG_Z : (res > v1) | GET_FLAG_S_B(res);\r
+        }\r
+        break;\r
+      case CMD_ADD:\r
+        {\r
+          UInt32 v1 = GetOperand32(&cmd->Op1);\r
+          UInt32 res = v1 + GetOperand32(&cmd->Op2);\r
+          SetOperand32(&cmd->Op1, res);\r
+          Flags = (res < v1) | (res == 0 ? FLAG_Z : (res & FLAG_S));\r
+        }\r
+        break;\r
+      case CMD_ADDB:\r
+        {\r
+          Byte v1 = GetOperand8(&cmd->Op1);\r
+          Byte res = v1 + GetOperand8(&cmd->Op2);\r
+          res &= 0xFF;\r
+          SetOperand8(&cmd->Op1, (Byte)res);\r
+          Flags = (res < v1) | (res == 0 ? FLAG_Z : GET_FLAG_S_B(res));\r
+        }\r
+        break;\r
+      case CMD_ADC:\r
+        {\r
+          UInt32 v1 = GetOperand(cmd->ByteMode, &cmd->Op1);\r
+          UInt32 FC = (Flags & FLAG_C);\r
+          UInt32 res = v1 + GetOperand(cmd->ByteMode, &cmd->Op2) + FC;\r
+          if (cmd->ByteMode)\r
+            res &= 0xFF;\r
+          SetOperand(cmd->ByteMode, &cmd->Op1, res);\r
+          Flags = (res < v1 || res == v1 && FC) | (res == 0 ? FLAG_Z : (res & FLAG_S));\r
+        }\r
+        break;\r
+      case CMD_SUB:\r
+        {\r
+          UInt32 v1 = GetOperand32(&cmd->Op1);\r
+          UInt32 res = v1 - GetOperand32(&cmd->Op2);\r
+          SetOperand32(&cmd->Op1, res);\r
+          Flags = res == 0 ? FLAG_Z : (res > v1) | (res & FLAG_S);\r
+        }\r
+        break;\r
+      case CMD_SUBB:\r
+        {\r
+          UInt32 v1 = GetOperand8(&cmd->Op1);\r
+          UInt32 res = v1 - GetOperand8(&cmd->Op2);\r
+          SetOperand8(&cmd->Op1, (Byte)res);\r
+          Flags = res == 0 ? FLAG_Z : (res > v1) | (res & FLAG_S);\r
+        }\r
+        break;\r
+      case CMD_SBB:\r
+        {\r
+          UInt32 v1 = GetOperand(cmd->ByteMode, &cmd->Op1);\r
+          UInt32 FC = (Flags & FLAG_C);\r
+          UInt32 res = v1 - GetOperand(cmd->ByteMode, &cmd->Op2) - FC;\r
+          // Flags = res == 0 ? FLAG_Z : (res > v1 || res == v1 && FC) | (res & FLAG_S);\r
+          if (cmd->ByteMode)\r
+            res &= 0xFF;\r
+          SetOperand(cmd->ByteMode, &cmd->Op1, res);\r
+          Flags = (res > v1 || res == v1 && FC) | (res == 0 ? FLAG_Z : (res & FLAG_S));\r
+        }\r
+        break;\r
+      case CMD_INC:\r
+        {\r
+          UInt32 res = GetOperand32(&cmd->Op1) + 1;\r
+          SetOperand32(&cmd->Op1, res);\r
+          FLAGS_UPDATE_SZ;\r
+        }\r
+        break;\r
+      case CMD_INCB:\r
+        {\r
+          Byte res = GetOperand8(&cmd->Op1) + 1;\r
+          SetOperand8(&cmd->Op1, res);;\r
+          FLAGS_UPDATE_SZ_B;\r
+        }\r
+        break;\r
+      case CMD_DEC:\r
+        {\r
+          UInt32 res = GetOperand32(&cmd->Op1) - 1;\r
+          SetOperand32(&cmd->Op1, res);\r
+          FLAGS_UPDATE_SZ;\r
+        }\r
+        break;\r
+      case CMD_DECB:\r
+        {\r
+          Byte res = GetOperand8(&cmd->Op1) - 1;\r
+          SetOperand8(&cmd->Op1, res);;\r
+          FLAGS_UPDATE_SZ_B;\r
+        }\r
+        break;\r
+      case CMD_XOR:\r
+        {\r
+          UInt32 res = GetOperand32(&cmd->Op1) ^ GetOperand32(&cmd->Op2);\r
+          SetOperand32(&cmd->Op1, res);\r
+          FLAGS_UPDATE_SZ;\r
+        }\r
+        break;\r
+      case CMD_XORB:\r
+        {\r
+          Byte res = GetOperand8(&cmd->Op1) ^ GetOperand8(&cmd->Op2);\r
+          SetOperand8(&cmd->Op1, res);\r
+          FLAGS_UPDATE_SZ_B;\r
+        }\r
+        break;\r
+      case CMD_AND:\r
+        {\r
+          UInt32 res = GetOperand32(&cmd->Op1) & GetOperand32(&cmd->Op2);\r
+          SetOperand32(&cmd->Op1, res);\r
+          FLAGS_UPDATE_SZ;\r
+        }\r
+        break;\r
+      case CMD_ANDB:\r
+        {\r
+          Byte res = GetOperand8(&cmd->Op1) & GetOperand8(&cmd->Op2);\r
+          SetOperand8(&cmd->Op1, res);\r
+          FLAGS_UPDATE_SZ_B;\r
+        }\r
+        break;\r
+      case CMD_OR:\r
+        {\r
+          UInt32 res = GetOperand32(&cmd->Op1) | GetOperand32(&cmd->Op2);\r
+          SetOperand32(&cmd->Op1, res);\r
+          FLAGS_UPDATE_SZ;\r
+        }\r
+        break;\r
+      case CMD_ORB:\r
+        {\r
+          Byte res = GetOperand8(&cmd->Op1) | GetOperand8(&cmd->Op2);\r
+          SetOperand8(&cmd->Op1, res);\r
+          FLAGS_UPDATE_SZ_B;\r
+        }\r
+        break;\r
+      case CMD_TEST:\r
+        {\r
+          UInt32 res = GetOperand32(&cmd->Op1) & GetOperand32(&cmd->Op2);\r
+          FLAGS_UPDATE_SZ;\r
+        }\r
+        break;\r
+      case CMD_TESTB:\r
+        {\r
+          Byte res = GetOperand8(&cmd->Op1) & GetOperand8(&cmd->Op2);\r
+          FLAGS_UPDATE_SZ_B;\r
+        }\r
+        break;\r
+      case CMD_NOT:\r
+        SetOperand(cmd->ByteMode, &cmd->Op1, ~GetOperand(cmd->ByteMode, &cmd->Op1));\r
+        break;\r
+      case CMD_NEG:\r
+        {\r
+          UInt32 res = 0 - GetOperand32(&cmd->Op1);\r
+          SetOperand32(&cmd->Op1, res);\r
+          Flags = res == 0 ? FLAG_Z : FLAG_C | (res & FLAG_S);\r
+        }\r
+        break;\r
+      case CMD_NEGB:\r
+        {\r
+          Byte res = (Byte)(0 - GetOperand8(&cmd->Op1));\r
+          SetOperand8(&cmd->Op1, res);\r
+          Flags = res == 0 ? FLAG_Z : FLAG_C | GET_FLAG_S_B(res);\r
+        }\r
+        break;\r
+\r
+      case CMD_SHL:\r
+        {\r
+          UInt32 v1 = GetOperand32(&cmd->Op1);\r
+          int v2 = (int)GetOperand32(&cmd->Op2);\r
+          UInt32 res = v1 << v2;\r
+          SetOperand32(&cmd->Op1, res);\r
+          Flags = (res == 0 ? FLAG_Z : (res & FLAG_S)) | ((v1 << (v2 - 1)) & 0x80000000 ? FLAG_C : 0);\r
+        }\r
+        break;\r
+      case CMD_SHLB:\r
+        {\r
+          Byte v1 = GetOperand8(&cmd->Op1);\r
+          int v2 = (int)GetOperand8(&cmd->Op2);\r
+          Byte res = (Byte)(v1 << v2);\r
+          SetOperand8(&cmd->Op1, res);\r
+          Flags = (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)) | ((v1 << (v2 - 1)) & 0x80 ? FLAG_C : 0);\r
+        }\r
+        break;\r
+      case CMD_SHR:\r
+        {\r
+          UInt32 v1 = GetOperand32(&cmd->Op1);\r
+          int v2 = (int)GetOperand32(&cmd->Op2);\r
+          UInt32 res = v1 >> v2;\r
+          SetOperand32(&cmd->Op1, res);\r
+          Flags = (res == 0 ? FLAG_Z : (res & FLAG_S)) | ((v1 >> (v2 - 1)) & FLAG_C);\r
+        }\r
+        break;\r
+      case CMD_SHRB:\r
+        {\r
+          Byte v1 = GetOperand8(&cmd->Op1);\r
+          int v2 = (int)GetOperand8(&cmd->Op2);\r
+          Byte res = (Byte)(v1 >> v2);\r
+          SetOperand8(&cmd->Op1, res);\r
+          Flags = (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)) | ((v1 >> (v2 - 1)) & FLAG_C);\r
+        }\r
+        break;\r
+      case CMD_SAR:\r
+        {\r
+          UInt32 v1 = GetOperand32(&cmd->Op1);\r
+          int v2 = (int)GetOperand32(&cmd->Op2);\r
+          UInt32 res = UInt32(((Int32)v1) >> v2);\r
+          SetOperand32(&cmd->Op1, res);\r
+          Flags= (res == 0 ? FLAG_Z : (res & FLAG_S)) | ((v1 >> (v2 - 1)) & FLAG_C);\r
+        }\r
+        break;\r
+      case CMD_SARB:\r
+        {\r
+          Byte v1 = GetOperand8(&cmd->Op1);\r
+          int v2 = (int)GetOperand8(&cmd->Op2);\r
+          Byte res = (Byte)(((signed char)v1) >> v2);\r
+          SetOperand8(&cmd->Op1, res);\r
+          Flags= (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)) | ((v1 >> (v2 - 1)) & FLAG_C);\r
+        }\r
+        break;\r
+\r
+      case CMD_JMP:\r
+        SET_IP_OP1;\r
+        continue;\r
+      case CMD_JZ:\r
+        if ((Flags & FLAG_Z) != 0)\r
+        {\r
+          SET_IP_OP1;\r
+          continue;\r
+        }\r
+        break;\r
+      case CMD_JNZ:\r
+        if ((Flags & FLAG_Z) == 0)\r
+        {\r
+          SET_IP_OP1;\r
+          continue;\r
+        }\r
+        break;\r
+      case CMD_JS:\r
+        if ((Flags & FLAG_S) != 0)\r
+        {\r
+          SET_IP_OP1;\r
+          continue;\r
+        }\r
+        break;\r
+      case CMD_JNS:\r
+        if ((Flags & FLAG_S) == 0)\r
+        {\r
+          SET_IP_OP1;\r
+          continue;\r
+        }\r
+        break;\r
+      case CMD_JB:\r
+        if ((Flags & FLAG_C) != 0)\r
+        {\r
+          SET_IP_OP1;\r
+          continue;\r
+        }\r
+        break;\r
+      case CMD_JBE:\r
+        if ((Flags & (FLAG_C | FLAG_Z)) != 0)\r
+        {\r
+          SET_IP_OP1;\r
+          continue;\r
+        }\r
+        break;\r
+      case CMD_JA:\r
+        if ((Flags & (FLAG_C | FLAG_Z)) == 0)\r
+        {\r
+          SET_IP_OP1;\r
+          continue;\r
+        }\r
+        break;\r
+      case CMD_JAE:\r
+        if ((Flags & FLAG_C) == 0)\r
+        {\r
+          SET_IP_OP1;\r
+          continue;\r
+        }\r
+        break;\r
+      \r
+      case CMD_PUSH:\r
+        R[kStackRegIndex] -= 4;\r
+        SetValue32(&Mem[R[kStackRegIndex] & kSpaceMask], GetOperand32(&cmd->Op1));\r
+        break;\r
+      case CMD_POP:\r
+        SetOperand32(&cmd->Op1, GetValue32(&Mem[R[kStackRegIndex] & kSpaceMask]));\r
+        R[kStackRegIndex] += 4;\r
+        break;\r
+      case CMD_CALL:\r
+        R[kStackRegIndex] -= 4;\r
+        SetValue32(&Mem[R[kStackRegIndex] & kSpaceMask], (UInt32)(cmd - commands + 1));\r
+        SET_IP_OP1;\r
+        continue;\r
+\r
+      case CMD_PUSHA:\r
+        {\r
+          for (UInt32 i = 0, SP = R[kStackRegIndex] - 4; i < kNumRegs; i++, SP -= 4)\r
+            SetValue32(&Mem[SP & kSpaceMask], R[i]);\r
+          R[kStackRegIndex] -= kNumRegs * 4;\r
+        }\r
+        break;\r
+      case CMD_POPA:\r
+        {\r
+          for (UInt32 i = 0, SP = R[kStackRegIndex]; i < kNumRegs; i++, SP += 4)\r
+            R[kStackRegIndex - i] = GetValue32(&Mem[SP & kSpaceMask]);\r
+        }\r
+        break;\r
+      case CMD_PUSHF:\r
+        R[kStackRegIndex] -= 4;\r
+        SetValue32(&Mem[R[kStackRegIndex]&kSpaceMask], Flags);\r
+        break;\r
+      case CMD_POPF:\r
+        Flags = GetValue32(&Mem[R[kStackRegIndex] & kSpaceMask]);\r
+        R[kStackRegIndex] += 4;\r
+        break;\r
+      \r
+      case CMD_MOVZX:\r
+        SetOperand32(&cmd->Op1, GetOperand8(&cmd->Op2));\r
+        break;\r
+      case CMD_MOVSX:\r
+        SetOperand32(&cmd->Op1, (UInt32)(Int32)(signed char)GetOperand8(&cmd->Op2));\r
+        break;\r
+      case CMD_XCHG:\r
+        {\r
+          UInt32 v1 = GetOperand(cmd->ByteMode, &cmd->Op1);\r
+          SetOperand(cmd->ByteMode, &cmd->Op1, GetOperand(cmd->ByteMode, &cmd->Op2));\r
+          SetOperand(cmd->ByteMode, &cmd->Op2, v1);\r
+        }\r
+        break;\r
+      case CMD_MUL:\r
+        {\r
+          UInt32 res = GetOperand32(&cmd->Op1) * GetOperand32(&cmd->Op2);\r
+          SetOperand32(&cmd->Op1, res);\r
+        }\r
+        break;\r
+      case CMD_MULB:\r
+        {\r
+          Byte res = GetOperand8(&cmd->Op1) * GetOperand8(&cmd->Op2);\r
+          SetOperand8(&cmd->Op1, res);\r
+        }\r
+        break;\r
+      case CMD_DIV:\r
+        {\r
+          UInt32 divider = GetOperand(cmd->ByteMode, &cmd->Op2);\r
+          if (divider != 0)\r
+          {\r
+            UInt32 res = GetOperand(cmd->ByteMode, &cmd->Op1) / divider;\r
+            SetOperand(cmd->ByteMode, &cmd->Op1, res);\r
+          }\r
+        }\r
+        break;\r
+      \r
+      #endif\r
+      \r
+      case CMD_RET:\r
+        {\r
+          if (R[kStackRegIndex] >= kSpaceSize)\r
+            return true;\r
+          UInt32 ip = GetValue32(&Mem[R[kStackRegIndex] & kSpaceMask]);\r
+          SET_IP(ip);\r
+          R[kStackRegIndex] += 4;\r
+          continue;\r
+        }\r
+      case CMD_PRINT:\r
+        break;\r
+    }\r
+    cmd++;\r
+    --maxOpCount;\r
+  }\r
+}\r
+\r
+\r
+//////////////////////////////////////////////////////\r
+// Read program\r
+\r
+UInt32 ReadEncodedUInt32(CMemBitDecoder &inp)\r
+{\r
+  switch(inp.ReadBits(2))\r
+  {\r
+    case 0:\r
+      return inp.ReadBits(4);\r
+    case 1:\r
+    {\r
+      UInt32 v = inp.ReadBits(4);\r
+      if (v == 0)\r
+        return 0xFFFFFF00 | inp.ReadBits(8);\r
+      else\r
+        return (v << 4) | inp.ReadBits(4);\r
+    }\r
+    case 2:\r
+      return inp.ReadBits(16);\r
+    default:\r
+      return inp.ReadBits(32);\r
+  }\r
+}\r
+\r
+void CVm::DecodeArg(CMemBitDecoder &inp, COperand &op, bool byteMode)\r
+{\r
+  if (inp.ReadBit())\r
+  {\r
+    op.Type = OP_TYPE_REG;\r
+    op.Data = inp.ReadBits(kNumRegBits);\r
+  }\r
+  else if (inp.ReadBit() == 0)\r
+  {\r
+    op.Type = OP_TYPE_INT;\r
+    if (byteMode)\r
+      op.Data = inp.ReadBits(8);\r
+    else\r
+      op.Data = ReadEncodedUInt32(inp);\r
+  }\r
+  else\r
+  {\r
+    op.Type = OP_TYPE_REGMEM;\r
+    if (inp.ReadBit() == 0)\r
+    {\r
+      op.Data = inp.ReadBits(kNumRegBits);\r
+      op.Base = 0;\r
+    }\r
+    else\r
+    {\r
+      if (inp.ReadBit() == 0)\r
+        op.Data = inp.ReadBits(kNumRegBits);\r
+      else\r
+        op.Data = kNumRegs;\r
+      op.Base = ReadEncodedUInt32(inp);\r
+    }\r
+  }\r
+}\r
+\r
+void CVm::ReadVmProgram(const Byte *code, UInt32 codeSize, CProgram *prg)\r
+{\r
+  CMemBitDecoder inp;\r
+  inp.Init(code, codeSize);\r
+\r
+  prg->StaticData.Clear();\r
+  if (inp.ReadBit())\r
+  {\r
+    UInt32 dataSize = ReadEncodedUInt32(inp) + 1;\r
+    for (UInt32 i = 0; inp.Avail() && i < dataSize; i++)\r
+      prg->StaticData.Add((Byte)inp.ReadBits(8));\r
+  }\r
+  while (inp.Avail())\r
+  {\r
+    prg->Commands.Add(CCommand());\r
+    CCommand *cmd = &prg->Commands.Back();\r
+    if (inp.ReadBit() == 0)\r
+      cmd->OpCode = (ECommand)inp.ReadBits(3);\r
+    else\r
+      cmd->OpCode = (ECommand)(8 + inp.ReadBits(5));\r
+    if (kCmdFlags[cmd->OpCode] & CF_BYTEMODE)\r
+      cmd->ByteMode = (inp.ReadBit()) ? true : false;\r
+    else\r
+      cmd->ByteMode = 0;\r
+    int opNum = (kCmdFlags[cmd->OpCode] & CF_OPMASK);\r
+    if (opNum > 0)\r
+    {\r
+      DecodeArg(inp, cmd->Op1, cmd->ByteMode);\r
+      if (opNum == 2)\r
+        DecodeArg(inp, cmd->Op2, cmd->ByteMode);\r
+      else\r
+      {\r
+        if (cmd->Op1.Type == OP_TYPE_INT && (kCmdFlags[cmd->OpCode] & (CF_JUMP | CF_PROC)))\r
+        {\r
+          int Distance = cmd->Op1.Data;\r
+          if (Distance >= 256)\r
+            Distance -= 256;\r
+          else\r
+          {\r
+            if (Distance >= 136)\r
+              Distance -= 264;\r
+            else if (Distance >= 16)\r
+              Distance -= 8;\r
+            else if (Distance >= 8)\r
+              Distance -= 16;\r
+            Distance += prg->Commands.Size() - 1;\r
+          }\r
+          cmd->Op1.Data = Distance;\r
+        }\r
+      }\r
+    }\r
+    if (cmd->ByteMode)\r
+    {\r
+      switch (cmd->OpCode)\r
+      {\r
+        case CMD_MOV: cmd->OpCode = CMD_MOVB; break;\r
+        case CMD_CMP: cmd->OpCode = CMD_CMPB; break;\r
+        case CMD_ADD: cmd->OpCode = CMD_ADDB; break;\r
+        case CMD_SUB: cmd->OpCode = CMD_SUBB; break;\r
+        case CMD_INC: cmd->OpCode = CMD_INCB; break;\r
+        case CMD_DEC: cmd->OpCode = CMD_DECB; break;\r
+        case CMD_XOR: cmd->OpCode = CMD_XORB; break;\r
+        case CMD_AND: cmd->OpCode = CMD_ANDB; break;\r
+        case CMD_OR: cmd->OpCode = CMD_ORB; break;\r
+        case CMD_TEST: cmd->OpCode = CMD_TESTB; break;\r
+        case CMD_NEG: cmd->OpCode = CMD_NEGB; break;\r
+        case CMD_SHL: cmd->OpCode = CMD_SHLB; break;\r
+        case CMD_SHR: cmd->OpCode = CMD_SHRB; break;\r
+        case CMD_SAR: cmd->OpCode = CMD_SARB; break;\r
+        case CMD_MUL: cmd->OpCode = CMD_MULB; break;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+#ifdef RARVM_STANDARD_FILTERS\r
+\r
+enum EStandardFilter\r
+{\r
+  SF_E8,\r
+  SF_E8E9,\r
+  SF_ITANIUM,\r
+  SF_RGB,\r
+  SF_AUDIO,\r
+  SF_DELTA,\r
+  SF_UPCASE\r
+};\r
+\r
+struct StandardFilterSignature\r
+{\r
+  UInt32 Length;\r
+  UInt32 CRC;\r
+  EStandardFilter Type;\r
+}\r
+kStdFilters[]=\r
+{\r
+  {  53, 0xad576887, SF_E8 },\r
+  {  57, 0x3cd7e57e, SF_E8E9 },\r
+  { 120, 0x3769893f, SF_ITANIUM },\r
+  {  29, 0x0e06077d, SF_DELTA },\r
+  { 149, 0x1c2c5dc8, SF_RGB },\r
+  { 216, 0xbc85e701, SF_AUDIO },\r
+  {  40, 0x46b9c560, SF_UPCASE }\r
+};\r
+\r
+static int FindStandardFilter(const Byte *code, UInt32 codeSize)\r
+{\r
+  UInt32 crc = CrcCalc(code, codeSize);\r
+  for (int i = 0; i < sizeof(kStdFilters) / sizeof(kStdFilters[0]); i++)\r
+  {\r
+    StandardFilterSignature &sfs = kStdFilters[i];\r
+    if (sfs.CRC == crc && sfs.Length == codeSize)\r
+      return i;\r
+  }\r
+  return -1;\r
+}\r
+\r
+#endif\r
+\r
+void CVm::PrepareProgram(const Byte *code, UInt32 codeSize, CProgram *prg)\r
+{\r
+  Byte xorSum = 0;\r
+  for (UInt32 i = 1; i < codeSize; i++)\r
+    xorSum ^= code[i];\r
+\r
+  prg->Commands.Clear();\r
+  #ifdef RARVM_STANDARD_FILTERS\r
+  prg->StandardFilterIndex = -1;\r
+  #endif\r
+\r
+  if (xorSum == code[0] && codeSize > 0)\r
+  {\r
+    #ifdef RARVM_STANDARD_FILTERS\r
+    prg->StandardFilterIndex = FindStandardFilter(code, codeSize);\r
+    if (prg->StandardFilterIndex >= 0)\r
+      return;\r
+    #endif\r
+    // 1 byte for checksum\r
+    ReadVmProgram(code + 1, codeSize - 1, prg);\r
+  }\r
+  prg->Commands.Add(CCommand());\r
+  CCommand *cmd = &prg->Commands.Back();\r
+  cmd->OpCode = CMD_RET;\r
+}\r
+\r
+void CVm::SetMemory(UInt32 pos, const Byte *data, UInt32 dataSize)\r
+{\r
+  if (pos < kSpaceSize && data != Mem + pos)\r
+    memmove(Mem + pos, data, MyMin(dataSize, kSpaceSize - pos));\r
+}\r
+\r
+#ifdef RARVM_STANDARD_FILTERS\r
+\r
+static void E8E9Decode(Byte *data, UInt32 dataSize, UInt32 fileOffset, bool e9)\r
+{\r
+  if (dataSize <= 4)\r
+    return;\r
+  dataSize -= 4;\r
+  const UInt32 kFileSize = 0x1000000;\r
+  Byte cmpByte2 = (e9 ? 0xE9 : 0xE8);\r
+  for (UInt32 curPos = 0; curPos < dataSize;)\r
+  {\r
+    Byte curByte = *(data++);\r
+    curPos++;\r
+    if (curByte == 0xE8 || curByte == cmpByte2)\r
+    {\r
+      UInt32 offset = curPos + fileOffset;\r
+      UInt32 addr = (Int32)GetValue32(data);\r
+      if (addr < kFileSize)\r
+        SetValue32(data, addr - offset);\r
+      else if ((Int32)addr < 0 && (Int32)(addr + offset) >= 0)\r
+        SetValue32(data, addr + kFileSize);\r
+      data += 4;\r
+      curPos += 4;\r
+    }\r
+  }\r
+}\r
+\r
+static inline UInt32 ItaniumGetOpType(const Byte *data, int bitPos)\r
+{\r
+  return (data[(unsigned int)bitPos >> 3] >> (bitPos & 7)) & 0xF;\r
+}\r
+\r
+\r
+static void ItaniumDecode(Byte *data, UInt32 dataSize, UInt32 fileOffset)\r
+{\r
+  UInt32 curPos = 0;\r
+  fileOffset >>= 4;\r
+  while (curPos < dataSize - 21)\r
+  {\r
+    int b = (data[0] & 0x1F) - 0x10;\r
+    if (b >= 0)\r
+    {\r
+      static Byte kCmdMasks[16] = {4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0};\r
+      Byte cmdMask = kCmdMasks[b];\r
+      if (cmdMask != 0)\r
+        for (int i = 0; i < 3; i++)\r
+          if (cmdMask & (1 << i))\r
+          {\r
+            int startPos = i * 41 + 18;\r
+            if (ItaniumGetOpType(data, startPos + 24) == 5)\r
+            {\r
+              const UInt32 kMask = 0xFFFFF;\r
+              Byte *p = data + ((unsigned int)startPos >> 3);\r
+              UInt32 bitField =  ((UInt32)p[0]) | ((UInt32)p[1] <<  8) | ((UInt32)p[2] << 16);\r
+              int inBit = (startPos & 7);\r
+              UInt32 offset = (bitField >> inBit) & kMask;\r
+              UInt32 andMask = ~(kMask << inBit);\r
+              bitField = ((offset - fileOffset) & kMask) << inBit;\r
+              for (int j = 0; j < 3; j++)\r
+              {\r
+                p[j] &= andMask;\r
+                p[j] |= bitField;\r
+                andMask >>= 8;\r
+                bitField >>= 8;\r
+              }\r
+            }\r
+          }\r
+    }\r
+    data += 16;\r
+    curPos += 16;\r
+    fileOffset++;\r
+  }\r
+}\r
+\r
+static void DeltaDecode(Byte *data, UInt32 dataSize, UInt32 numChannels)\r
+{\r
+  UInt32 srcPos = 0;\r
+  UInt32 border = dataSize * 2;\r
+  for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++)\r
+  {\r
+    Byte prevByte = 0;\r
+    for (UInt32 destPos = dataSize + curChannel; destPos < border; destPos += numChannels)\r
+      data[destPos] = (prevByte = prevByte - data[srcPos++]);\r
+  }\r
+}\r
+\r
+static void RgbDecode(Byte *srcData, UInt32 dataSize, UInt32 width, UInt32 posR)\r
+{\r
+  Byte *destData = srcData + dataSize;\r
+  const UInt32 numChannels = 3;\r
+  for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++)\r
+  {\r
+    Byte prevByte = 0;\r
+    \r
+    for (UInt32 i = curChannel; i < dataSize; i+= numChannels)\r
+    {\r
+      unsigned int predicted;\r
+      if (i < width)\r
+        predicted = prevByte;\r
+      else\r
+      {\r
+        unsigned int upperLeftByte = destData[i - width];\r
+        unsigned int upperByte = destData[i - width + 3];\r
+        predicted = prevByte + upperByte - upperLeftByte;\r
+        int pa = abs((int)(predicted - prevByte));\r
+        int pb = abs((int)(predicted - upperByte));\r
+        int pc = abs((int)(predicted - upperLeftByte));\r
+        if (pa <= pb && pa <= pc)\r
+          predicted = prevByte;\r
+        else\r
+          if (pb <= pc)\r
+            predicted = upperByte;\r
+          else\r
+            predicted = upperLeftByte;\r
+      }\r
+      destData[i] = prevByte = (Byte)(predicted - *(srcData++));\r
+    }\r
+  }\r
+  if (dataSize < 3)\r
+    return;\r
+  for (UInt32 i = posR, border = dataSize - 2; i < border; i += 3)\r
+  {\r
+    Byte g = destData[i + 1];\r
+    destData[i] = destData[i] + g;\r
+    destData[i + 2] = destData[i + 2] + g;\r
+  }\r
+}\r
+\r
+static void AudioDecode(Byte *srcData, UInt32 dataSize, UInt32 numChannels)\r
+{\r
+  Byte *destData = srcData + dataSize;\r
+  for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++)\r
+  {\r
+    UInt32 prevByte = 0, prevDelta = 0, dif[7];\r
+    Int32 D1 = 0, D2 = 0, D3;\r
+    Int32 K1 = 0, K2 = 0, K3 = 0;\r
+    memset(dif, 0, sizeof(dif));\r
+    \r
+    for (UInt32 i = curChannel, byteCount = 0; i < dataSize; i += numChannels, byteCount++)\r
+    {\r
+      D3 = D2;\r
+      D2 = prevDelta - D1;\r
+      D1 = prevDelta;\r
+      \r
+      UInt32 predicted = 8 * prevByte + K1 * D1 + K2 * D2 + K3 * D3;\r
+      predicted = (predicted >> 3) & 0xFF;\r
+      \r
+      UInt32 curByte = *(srcData++);\r
+      \r
+      predicted -= curByte;\r
+      destData[i] = (Byte)predicted;\r
+      prevDelta = (UInt32)(Int32)(signed char)(predicted - prevByte);\r
+      prevByte = predicted;\r
+      \r
+      Int32 D = ((Int32)(signed char)curByte) << 3;\r
+      \r
+      dif[0] += abs(D);\r
+      dif[1] += abs(D - D1);\r
+      dif[2] += abs(D + D1);\r
+      dif[3] += abs(D - D2);\r
+      dif[4] += abs(D + D2);\r
+      dif[5] += abs(D - D3);\r
+      dif[6] += abs(D + D3);\r
+      \r
+      if ((byteCount & 0x1F) == 0)\r
+      {\r
+        UInt32 minDif = dif[0], numMinDif = 0;\r
+        dif[0] = 0;\r
+        for (int j = 1; j < sizeof(dif) / sizeof(dif[0]); j++)\r
+        {\r
+          if (dif[j] < minDif)\r
+          {\r
+            minDif = dif[j];\r
+            numMinDif = j;\r
+          }\r
+          dif[j] = 0;\r
+        }\r
+        switch (numMinDif)\r
+        {\r
+          case 1: if (K1 >= -16) K1--; break;\r
+          case 2: if (K1 <   16) K1++; break;\r
+          case 3: if (K2 >= -16) K2--; break;\r
+          case 4: if (K2 <   16) K2++; break;\r
+          case 5: if (K3 >= -16) K3--; break;\r
+          case 6: if (K3 <   16) K3++; break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+static UInt32 UpCaseDecode(Byte *data, UInt32 dataSize)\r
+{\r
+  UInt32 srcPos = 0, destPos = dataSize;\r
+  while (srcPos < dataSize)\r
+  {\r
+    Byte curByte = data[srcPos++];\r
+    if (curByte == 2 && (curByte = data[srcPos++]) != 2)\r
+      curByte -= 32;\r
+    data[destPos++] = curByte;\r
+  }\r
+  return destPos - dataSize;\r
+}\r
+\r
+void CVm::ExecuteStandardFilter(int filterIndex)\r
+{\r
+  UInt32 dataSize = R[4];\r
+  if (dataSize >= kGlobalOffset)\r
+    return;\r
+  EStandardFilter filterType = kStdFilters[filterIndex].Type;\r
+\r
+  switch (filterType)\r
+  {\r
+    case SF_E8:\r
+    case SF_E8E9:\r
+      E8E9Decode(Mem, dataSize, R[6], (filterType == SF_E8E9));\r
+      break;\r
+    case SF_ITANIUM:\r
+      ItaniumDecode(Mem, dataSize, R[6]);\r
+      break;\r
+    case SF_DELTA:\r
+      if (dataSize >= kGlobalOffset / 2)\r
+        break;\r
+      SetBlockPos(dataSize);\r
+      DeltaDecode(Mem, dataSize, R[0]);\r
+      break;\r
+    case SF_RGB:\r
+      if (dataSize >= kGlobalOffset / 2)\r
+        break;\r
+      {\r
+        UInt32 width = R[0];\r
+        if (width <= 3)\r
+          break;\r
+        SetBlockPos(dataSize);\r
+        RgbDecode(Mem, dataSize, width, R[1]);\r
+      }\r
+      break;\r
+    case SF_AUDIO:\r
+      if (dataSize >= kGlobalOffset / 2)\r
+        break;\r
+      SetBlockPos(dataSize);\r
+      AudioDecode(Mem, dataSize, R[0]);\r
+      break;\r
+    case SF_UPCASE:\r
+      if (dataSize >= kGlobalOffset / 2)\r
+        break;\r
+      UInt32 destSize = UpCaseDecode(Mem, dataSize);\r
+      SetBlockSize(destSize);\r
+      SetBlockPos(dataSize);\r
+      break;\r
+  }\r
+}\r
+\r
+#endif\r
+\r
+}}}\r
diff --git a/CPP/7zip/Compress/Rar3Vm.h b/CPP/7zip/Compress/Rar3Vm.h
new file mode 100755 (executable)
index 0000000..0d16e42
--- /dev/null
@@ -0,0 +1,179 @@
+// Rar3Vm.h\r
+// According to unRAR license, this code may not be used to develop\r
+// a program that creates RAR archives\r
+\r
+#ifndef __COMPRESS_RAR3_VM_H\r
+#define __COMPRESS_RAR3_VM_H\r
+\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "Common/MyVector.h"\r
+#include "Common/Types.h"\r
+\r
+#define RARVM_STANDARD_FILTERS\r
+\r
+namespace NCompress {\r
+namespace NRar3 {\r
+\r
+class CMemBitDecoder\r
+{\r
+  const Byte *_data;\r
+  UInt32 _bitSize;\r
+  UInt32 _bitPos;\r
+public:\r
+  void Init(const Byte *data, UInt32 byteSize)\r
+  {\r
+    _data = data;\r
+    _bitSize = (byteSize << 3);\r
+    _bitPos = 0;\r
+  }\r
+  UInt32 ReadBits(int numBits);\r
+  UInt32 ReadBit();\r
+  bool Avail() const { return (_bitPos < _bitSize); }\r
+};\r
+\r
+namespace NVm {\r
+\r
+inline UInt32 GetValue32(const void *addr) { return GetUi32(addr); }\r
+inline void SetValue32(void *addr, UInt32 value) { SetUi32(addr, value); }\r
+\r
+UInt32 ReadEncodedUInt32(CMemBitDecoder &inp);\r
+\r
+const int kNumRegBits = 3;\r
+const UInt32 kNumRegs = 1 << kNumRegBits;\r
+const UInt32 kNumGpRegs = kNumRegs - 1;\r
+\r
+const UInt32 kSpaceSize = 0x40000;\r
+const UInt32 kSpaceMask = kSpaceSize -1;\r
+const UInt32 kGlobalOffset = 0x3C000;\r
+const UInt32 kGlobalSize = 0x2000;\r
+const UInt32 kFixedGlobalSize = 64;\r
+\r
+namespace NGlobalOffset\r
+{\r
+  const UInt32 kBlockSize = 0x1C;\r
+  const UInt32 kBlockPos  = 0x20;\r
+  const UInt32 kExecCount = 0x2C;\r
+  const UInt32 kGlobalMemOutSize = 0x30;\r
+}\r
+\r
+enum ECommand\r
+{\r
+  CMD_MOV,  CMD_CMP,  CMD_ADD,  CMD_SUB,  CMD_JZ,   CMD_JNZ,  CMD_INC,  CMD_DEC,\r
+  CMD_JMP,  CMD_XOR,  CMD_AND,  CMD_OR,   CMD_TEST, CMD_JS,   CMD_JNS,  CMD_JB,\r
+  CMD_JBE,  CMD_JA,   CMD_JAE,  CMD_PUSH, CMD_POP,  CMD_CALL, CMD_RET,  CMD_NOT,\r
+  CMD_SHL,  CMD_SHR,  CMD_SAR,  CMD_NEG,  CMD_PUSHA,CMD_POPA, CMD_PUSHF,CMD_POPF,\r
+  CMD_MOVZX,CMD_MOVSX,CMD_XCHG, CMD_MUL,  CMD_DIV,  CMD_ADC,  CMD_SBB,  CMD_PRINT,\r
+\r
+  CMD_MOVB, CMD_CMPB, CMD_ADDB, CMD_SUBB, CMD_INCB, CMD_DECB,\r
+  CMD_XORB, CMD_ANDB, CMD_ORB,  CMD_TESTB,CMD_NEGB,\r
+  CMD_SHLB, CMD_SHRB, CMD_SARB, CMD_MULB\r
+};\r
+\r
+enum EOpType {OP_TYPE_REG, OP_TYPE_INT, OP_TYPE_REGMEM, OP_TYPE_NONE};\r
+\r
+// Addr in COperand object can link (point) to CVm object!!!\r
+\r
+struct COperand\r
+{\r
+  EOpType Type;\r
+  UInt32 Data;\r
+  UInt32 Base;\r
+  COperand(): Type(OP_TYPE_NONE), Data(0), Base(0) {}\r
+};\r
+\r
+struct CCommand\r
+{\r
+  ECommand OpCode;\r
+  bool ByteMode;\r
+  COperand Op1, Op2;\r
+};\r
+\r
+struct CBlockRef\r
+{\r
+  UInt32 Offset;\r
+  UInt32 Size;\r
+};\r
+\r
+struct CProgram\r
+{\r
+  CRecordVector<CCommand> Commands;\r
+  #ifdef RARVM_STANDARD_FILTERS\r
+  int StandardFilterIndex;\r
+  #endif\r
+  CRecordVector<Byte> StaticData;\r
+};\r
+\r
+struct CProgramInitState\r
+{\r
+  UInt32 InitR[kNumGpRegs];\r
+  CRecordVector<Byte> GlobalData;\r
+\r
+  void AllocateEmptyFixedGlobal()\r
+  {\r
+    GlobalData.Clear();\r
+    GlobalData.Reserve(NVm::kFixedGlobalSize);\r
+    for (UInt32 i = 0; i < NVm::kFixedGlobalSize; i++)\r
+      GlobalData.Add(0);\r
+  }\r
+};\r
+\r
+class CVm\r
+{\r
+  static UInt32 GetValue(bool byteMode, const void *addr)\r
+  {\r
+    if (byteMode)\r
+      return(*(const Byte *)addr);\r
+    else\r
+      return GetUi32(addr);\r
+  }\r
+\r
+  static void SetValue(bool byteMode, void *addr, UInt32 value)\r
+  {\r
+    if (byteMode)\r
+      *(Byte *)addr = (Byte)value;\r
+    else\r
+      SetUi32(addr, value);\r
+  }\r
+\r
+  UInt32 GetFixedGlobalValue32(UInt32 globalOffset) { return GetValue(false, &Mem[kGlobalOffset + globalOffset]); }\r
+\r
+  void SetBlockSize(UInt32 v) { SetValue(&Mem[kGlobalOffset + NGlobalOffset::kBlockSize], v); }\r
+  void SetBlockPos(UInt32 v) { SetValue(&Mem[kGlobalOffset + NGlobalOffset::kBlockPos], v); }\r
+public:\r
+  static void SetValue(void *addr, UInt32 value) { SetValue(false, addr, value); }\r
+private:\r
+  UInt32 GetOperand32(const COperand *op) const;\r
+  void SetOperand32(const COperand *op, UInt32 val);\r
+  Byte GetOperand8(const COperand *op) const;\r
+  void SetOperand8(const COperand *op, Byte val);\r
+  UInt32 GetOperand(bool byteMode, const COperand *op) const;\r
+  void SetOperand(bool byteMode, const COperand *op, UInt32 val);\r
+\r
+  void DecodeArg(CMemBitDecoder &inp, COperand &op, bool byteMode);\r
+  \r
+  bool ExecuteCode(const CProgram *prg);\r
+  \r
+  #ifdef RARVM_STANDARD_FILTERS\r
+  void ExecuteStandardFilter(int filterIndex);\r
+  #endif\r
+  \r
+  Byte *Mem;\r
+  UInt32 R[kNumRegs + 1]; // R[kNumRegs] = 0 always (speed optimization)\r
+  UInt32 Flags;\r
+  void ReadVmProgram(const Byte *code, UInt32 codeSize, CProgram *prg);\r
+public:\r
+  CVm();\r
+  ~CVm();\r
+  bool Create();\r
+  void PrepareProgram(const Byte *code, UInt32 codeSize, CProgram *prg);\r
+  void SetMemory(UInt32 pos, const Byte *data, UInt32 dataSize);\r
+  bool Execute(CProgram *prg, const CProgramInitState *initState,\r
+      CBlockRef &outBlockRef, CRecordVector<Byte> &outGlobalData);\r
+  const Byte *GetDataPointer(UInt32 offset) const { return Mem + offset; }\r
+\r
+};\r
+\r
+#endif\r
+\r
+}}}\r
diff --git a/CPP/7zip/Compress/RarCodecsRegister.cpp b/CPP/7zip/Compress/RarCodecsRegister.cpp
new file mode 100755 (executable)
index 0000000..cb6242b
--- /dev/null
@@ -0,0 +1,26 @@
+// RarCodecsRegister.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../Common/RegisterCodec.h"\r
+\r
+#include "Rar1Decoder.h"\r
+#include "Rar2Decoder.h"\r
+#include "Rar3Decoder.h"\r
+\r
+#define CREATE_CODEC(x) static void *CreateCodec ## x() { return (void *)(ICompressCoder *)(new NCompress::NRar ## x::CDecoder); }\r
+\r
+CREATE_CODEC(1)\r
+CREATE_CODEC(2)\r
+CREATE_CODEC(3)\r
+\r
+#define RAR_CODEC(x, name) { CreateCodec ## x, 0, 0x040300 + x, L"Rar" name, 1, false }\r
+\r
+static CCodecInfo g_CodecsInfo[] =\r
+{\r
+  RAR_CODEC(1, L"1"),\r
+  RAR_CODEC(2, L"2"),\r
+  RAR_CODEC(3, L"3"),\r
+};\r
+\r
+REGISTER_CODECS(Rar)\r
diff --git a/CPP/7zip/Compress/ShrinkDecoder.cpp b/CPP/7zip/Compress/ShrinkDecoder.cpp
new file mode 100755 (executable)
index 0000000..d4e06fe
--- /dev/null
@@ -0,0 +1,145 @@
+// ShrinkDecoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+\r
+#include "../Common/InBuffer.h"\r
+#include "../Common/OutBuffer.h"\r
+\r
+#include "BitlDecoder.h"\r
+#include "ShrinkDecoder.h"\r
+\r
+namespace NCompress {\r
+namespace NShrink {\r
+\r
+static const UInt32 kBufferSize = (1 << 20);\r
+static const int kNumMinBits = 9;\r
+\r
+HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)\r
+{\r
+  NBitl::CBaseDecoder<CInBuffer> inBuffer;\r
+  COutBuffer outBuffer;\r
+\r
+  if (!inBuffer.Create(kBufferSize))\r
+    return E_OUTOFMEMORY;\r
+  inBuffer.SetStream(inStream);\r
+  inBuffer.Init();\r
+\r
+  if (!outBuffer.Create(kBufferSize))\r
+    return E_OUTOFMEMORY;\r
+  outBuffer.SetStream(outStream);\r
+  outBuffer.Init();\r
+\r
+  UInt64 prevPos = 0;\r
+  int numBits = kNumMinBits;\r
+  UInt32 head = 257;\r
+  bool needPrev = false;\r
+  UInt32 lastSymbol = 0;\r
+\r
+  int i;\r
+  for (i = 0; i < kNumItems; i++)\r
+    _parents[i] = 0;\r
+  for (i = 0; i < kNumItems; i++)\r
+    _suffixes[i] = 0;\r
+  for (i = 0; i < 257; i++)\r
+    _isFree[i] = false;\r
+  for (; i < kNumItems; i++)\r
+    _isFree[i] = true;\r
+\r
+  for (;;)\r
+  {\r
+    UInt32 symbol = inBuffer.ReadBits(numBits);\r
+    if (inBuffer.ExtraBitsWereRead())\r
+      break;\r
+    if (_isFree[symbol])\r
+      return S_FALSE;\r
+    if (symbol == 256)\r
+    {\r
+      UInt32 symbol = inBuffer.ReadBits(numBits);\r
+      if (symbol == 1)\r
+      {\r
+        if (numBits < kNumMaxBits)\r
+          numBits++;\r
+      }\r
+      else if (symbol == 2)\r
+      {\r
+        if (needPrev)\r
+          _isFree[head - 1] = true;\r
+        for (i = 257; i < kNumItems; i++)\r
+          _isParent[i] = false;\r
+        for (i = 257; i < kNumItems; i++)\r
+          if (!_isFree[i])\r
+            _isParent[_parents[i]] = true;\r
+        for (i = 257; i < kNumItems; i++)\r
+          if (!_isParent[i])\r
+            _isFree[i] = true;\r
+        head = 257;\r
+        while (head < kNumItems && !_isFree[head])\r
+          head++;\r
+        if (head < kNumItems)\r
+        {\r
+          needPrev = true;\r
+          _isFree[head] = false;\r
+          _parents[head] = (UInt16)lastSymbol;\r
+          head++;\r
+        }\r
+      }\r
+      else\r
+        return S_FALSE;\r
+      continue;\r
+    }\r
+    UInt32 cur = symbol;\r
+    i = 0;\r
+    int corectionIndex = -1;\r
+    while (cur >= 256)\r
+    {\r
+      if (cur == head - 1)\r
+        corectionIndex = i;\r
+      _stack[i++] = _suffixes[cur];\r
+      cur = _parents[cur];\r
+    }\r
+    _stack[i++] = (Byte)cur;\r
+    if (needPrev)\r
+    {\r
+      _suffixes[head - 1] = (Byte)cur;\r
+      if (corectionIndex >= 0)\r
+        _stack[corectionIndex] = (Byte)cur;\r
+    }\r
+    while (i > 0)\r
+      outBuffer.WriteByte((_stack[--i]));\r
+    while (head < kNumItems && !_isFree[head])\r
+      head++;\r
+    if (head < kNumItems)\r
+    {\r
+      needPrev = true;\r
+      _isFree[head] = false;\r
+      _parents[head] = (UInt16)symbol;\r
+      head++;\r
+    }\r
+    else\r
+      needPrev = false;\r
+    lastSymbol = symbol;\r
+\r
+    UInt64 nowPos = outBuffer.GetProcessedSize();\r
+    if (progress != NULL && nowPos - prevPos > (1 << 18))\r
+    {\r
+      prevPos = nowPos;\r
+      UInt64 packSize = inBuffer.GetProcessedSize();\r
+      RINOK(progress->SetRatioInfo(&packSize, &nowPos));\r
+    }\r
+  }\r
+  return outBuffer.Flush();\r
+}\r
+\r
+STDMETHODIMP CDecoder ::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *inSize, const UInt64 *outSize,    ICompressProgressInfo *progress)\r
+{\r
+  try { return CodeReal(inStream, outStream, inSize, outSize, progress); }\r
+  catch(const CInBufferException &e) { return e.ErrorCode; }\r
+  catch(const COutBufferException &e) { return e.ErrorCode; }\r
+  catch(...) { return S_FALSE; }\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Compress/ShrinkDecoder.h b/CPP/7zip/Compress/ShrinkDecoder.h
new file mode 100755 (executable)
index 0000000..00f4164
--- /dev/null
@@ -0,0 +1,38 @@
+// ShrinkDecoder.h\r
+\r
+#ifndef __COMPRESS_SHRINK_DECODER_H\r
+#define __COMPRESS_SHRINK_DECODER_H\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+namespace NCompress {\r
+namespace NShrink {\r
+\r
+const int kNumMaxBits = 13;\r
+const UInt32 kNumItems = 1 << kNumMaxBits;\r
+\r
+class CDecoder :\r
+  public ICompressCoder,\r
+  public CMyUnknownImp\r
+{\r
+  UInt16 _parents[kNumItems];\r
+  Byte _suffixes[kNumItems];\r
+  Byte _stack[kNumItems];\r
+  bool _isFree[kNumItems];\r
+  bool _isParent[kNumItems];\r
+\r
+public:\r
+  MY_UNKNOWN_IMP\r
+\r
+  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+  \r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/StdAfx.h b/CPP/7zip/Compress/StdAfx.h
new file mode 100755 (executable)
index 0000000..c28ffce
--- /dev/null
@@ -0,0 +1,8 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../Common/MyWindows.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/ZDecoder.cpp b/CPP/7zip/Compress/ZDecoder.cpp
new file mode 100755 (executable)
index 0000000..55c20df
--- /dev/null
@@ -0,0 +1,159 @@
+// ZDecoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Alloc.h"\r
+\r
+#include "../Common/InBuffer.h"\r
+#include "../Common/OutBuffer.h"\r
+\r
+#include "ZDecoder.h"\r
+\r
+namespace NCompress {\r
+namespace NZ {\r
+\r
+static const UInt32 kBufferSize = (1 << 20);\r
+static const Byte kNumBitsMask = 0x1F;\r
+static const Byte kBlockModeMask = 0x80;\r
+static const int kNumMinBits = 9;\r
+static const int kNumMaxBits = 16;\r
+\r
+void CDecoder::Free()\r
+{\r
+  MyFree(_parents); _parents = 0;\r
+  MyFree(_suffixes); _suffixes = 0;\r
+  MyFree(_stack); _stack = 0;\r
+}\r
+\r
+CDecoder::~CDecoder() { Free(); }\r
+\r
+HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)\r
+{\r
+  CInBuffer inBuffer;\r
+  COutBuffer outBuffer;\r
+\r
+  if (!inBuffer.Create(kBufferSize))\r
+    return E_OUTOFMEMORY;\r
+  inBuffer.SetStream(inStream);\r
+  inBuffer.Init();\r
+\r
+  if (!outBuffer.Create(kBufferSize))\r
+    return E_OUTOFMEMORY;\r
+  outBuffer.SetStream(outStream);\r
+  outBuffer.Init();\r
+\r
+  int maxbits = _properties & kNumBitsMask;\r
+  if (maxbits < kNumMinBits || maxbits > kNumMaxBits)\r
+    return S_FALSE;\r
+  UInt32 numItems = 1 << maxbits;\r
+  bool blockMode = ((_properties & kBlockModeMask) != 0);\r
+\r
+  if (maxbits != _numMaxBits || _parents == 0 || _suffixes == 0 || _stack == 0)\r
+  {\r
+    Free();\r
+    _parents = (UInt16 *)MyAlloc(numItems * sizeof(UInt16)); if (_parents == 0) return E_OUTOFMEMORY;\r
+    _suffixes = (Byte *)MyAlloc(numItems * sizeof(Byte)); if (_suffixes == 0) return E_OUTOFMEMORY;\r
+    _stack = (Byte *)MyAlloc(numItems * sizeof(Byte)); if (_stack == 0) return E_OUTOFMEMORY;\r
+    _numMaxBits = maxbits;\r
+  }\r
+\r
+  UInt64 prevPos = 0;\r
+  int numBits = kNumMinBits;\r
+  UInt32 head = blockMode ? 257 : 256;\r
+\r
+  bool needPrev = false;\r
+\r
+  unsigned bitPos = 0;\r
+  unsigned numBufBits = 0;\r
+\r
+  Byte buf[kNumMaxBits + 4];\r
+\r
+  _parents[256] = 0; // virus protection\r
+  _suffixes[256] = 0;\r
+\r
+  for (;;)\r
+  {\r
+    if (numBufBits == bitPos)\r
+    {\r
+      numBufBits = (unsigned)inBuffer.ReadBytes(buf, numBits) * 8;\r
+      bitPos = 0;\r
+      UInt64 nowPos = outBuffer.GetProcessedSize();\r
+      if (progress != NULL && nowPos - prevPos >= (1 << 18))\r
+      {\r
+        prevPos = nowPos;\r
+        UInt64 packSize = inBuffer.GetProcessedSize();\r
+        RINOK(progress->SetRatioInfo(&packSize, &nowPos));\r
+      }\r
+    }\r
+    unsigned bytePos = bitPos >> 3;\r
+    UInt32 symbol = buf[bytePos] | ((UInt32)buf[bytePos + 1] << 8) | ((UInt32)buf[bytePos + 2] << 16);\r
+    symbol >>= (bitPos & 7);\r
+    symbol &= (1 << numBits) - 1;\r
+    bitPos += numBits;\r
+    if (bitPos > numBufBits)\r
+      break;\r
+    if (symbol >= head)\r
+      return S_FALSE;\r
+    if (blockMode && symbol == 256)\r
+    {\r
+      numBufBits = bitPos = 0;\r
+      numBits = kNumMinBits;\r
+      head = 257;\r
+      needPrev = false;\r
+      continue;\r
+    }\r
+    UInt32 cur = symbol;\r
+    int i = 0;\r
+    while (cur >= 256)\r
+    {\r
+      _stack[i++] = _suffixes[cur];\r
+      cur = _parents[cur];\r
+    }\r
+    _stack[i++] = (Byte)cur;\r
+    if (needPrev)\r
+    {\r
+      _suffixes[head - 1] = (Byte)cur;\r
+      if (symbol == head - 1)\r
+        _stack[0] = (Byte)cur;\r
+    }\r
+    do\r
+      outBuffer.WriteByte((_stack[--i]));\r
+    while (i > 0);\r
+    if (head < numItems)\r
+    {\r
+      needPrev = true;\r
+      _parents[head++] = (UInt16)symbol;\r
+      if (head > ((UInt32)1 << numBits))\r
+      {\r
+        if (numBits < maxbits)\r
+        {\r
+          numBufBits = bitPos = 0;\r
+          numBits++;\r
+        }\r
+      }\r
+    }\r
+    else\r
+      needPrev = false;\r
+  }\r
+  return outBuffer.Flush();\r
+}\r
+\r
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  try { return CodeReal(inStream, outStream, inSize, outSize, progress); }\r
+  catch(const CInBufferException &e) { return e.ErrorCode; }\r
+  catch(const COutBufferException &e) { return e.ErrorCode; }\r
+  catch(...) { return S_FALSE; }\r
+}\r
+\r
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)\r
+{\r
+  if (size < 1)\r
+    return E_INVALIDARG;\r
+  _properties = data[0];\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Compress/ZDecoder.h b/CPP/7zip/Compress/ZDecoder.h
new file mode 100755 (executable)
index 0000000..6a6ed06
--- /dev/null
@@ -0,0 +1,42 @@
+// ZDecoder.h\r
+\r
+#ifndef __COMPRESS_Z_DECODER_H\r
+#define __COMPRESS_Z_DECODER_H\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+namespace NCompress {\r
+namespace NZ {\r
+\r
+class CDecoder:\r
+  public ICompressCoder,\r
+  public ICompressSetDecoderProperties2,\r
+  public CMyUnknownImp\r
+{\r
+  UInt16 *_parents;\r
+  Byte *_suffixes;\r
+  Byte *_stack;\r
+  Byte _properties;\r
+  int _numMaxBits;\r
+\r
+public:\r
+  CDecoder(): _parents(0), _suffixes(0), _stack(0), _properties(0), _numMaxBits(0) {};\r
+  ~CDecoder();\r
+  void Free();\r
+\r
+  MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)\r
+\r
+  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/ZlibDecoder.cpp b/CPP/7zip/Compress/ZlibDecoder.cpp
new file mode 100755 (executable)
index 0000000..9cdce21
--- /dev/null
@@ -0,0 +1,89 @@
+// ZlibDecoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "ZlibDecoder.h"\r
+\r
+namespace NCompress {\r
+namespace NZlib {\r
+\r
+#define DEFLATE_TRY_BEGIN try {\r
+#define DEFLATE_TRY_END } catch(...) { return S_FALSE; }\r
+\r
+#define ADLER_MOD 65521\r
+#define ADLER_LOOP_MAX 5550\r
+\r
+UInt32 Adler32_Update(UInt32 adler, const Byte *buf, size_t size)\r
+{\r
+  UInt32 a = adler & 0xFFFF;\r
+  UInt32 b = (adler >> 16) & 0xFFFF;\r
+  while (size > 0)\r
+  {\r
+    unsigned curSize = (size > ADLER_LOOP_MAX) ? ADLER_LOOP_MAX : (unsigned )size;\r
+    unsigned i;\r
+    for (i = 0; i < curSize; i++)\r
+    {\r
+      a += buf[i];\r
+      b += a;\r
+    }\r
+    buf += curSize;\r
+    size -= curSize;\r
+    a %= ADLER_MOD;\r
+    b %= ADLER_MOD;\r
+  }\r
+  return (b << 16) + a;\r
+}\r
+\r
+STDMETHODIMP COutStreamWithAdler::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  HRESULT result = _stream->Write(data, size, &size);\r
+  _adler = Adler32_Update(_adler, (const Byte *)data, size);\r
+  if (processedSize != NULL)\r
+    *processedSize = size;\r
+  return result;\r
+}\r
+\r
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\r
+{\r
+  DEFLATE_TRY_BEGIN\r
+  if (!AdlerStream)\r
+    AdlerStream = AdlerSpec = new COutStreamWithAdler;\r
+  if (!DeflateDecoder)\r
+  {\r
+    DeflateDecoderSpec = new NDeflate::NDecoder::CCOMCoder;\r
+    DeflateDecoderSpec->ZlibMode = true;\r
+    DeflateDecoder = DeflateDecoderSpec;\r
+  }\r
+\r
+  Byte buf[2];\r
+  RINOK(ReadStream_FALSE(inStream, buf, 2));\r
+  int method = buf[0] & 0xF;\r
+  if (method != 8)\r
+    return S_FALSE;\r
+  // int dicSize = buf[0] >> 4;\r
+  if ((((UInt32)buf[0] << 8) + buf[1]) % 31 != 0)\r
+    return S_FALSE;\r
+  if ((buf[1] & 0x20) != 0) // dictPresent\r
+    return S_FALSE;\r
+  // int level = (buf[1] >> 6);\r
+\r
+  AdlerSpec->SetStream(outStream);\r
+  AdlerSpec->Init();\r
+  HRESULT res = DeflateDecoder->Code(inStream, AdlerStream, inSize, outSize, progress);\r
+  AdlerSpec->ReleaseStream();\r
+\r
+  if (res == S_OK)\r
+  {\r
+    const Byte *p = DeflateDecoderSpec->ZlibFooter;\r
+    UInt32 adler = ((UInt32)p[0] << 24) | ((UInt32)p[1] << 16) | ((UInt32)p[2] << 8) | p[3];\r
+    if (adler != AdlerSpec->GetAdler())\r
+      return S_FALSE;\r
+  }\r
+  return res;\r
+  DEFLATE_TRY_END\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Compress/ZlibDecoder.h b/CPP/7zip/Compress/ZlibDecoder.h
new file mode 100755 (executable)
index 0000000..f6c7c0b
--- /dev/null
@@ -0,0 +1,48 @@
+// ZlibDecoder.h\r
+\r
+#ifndef __ZLIB_DECODER_H\r
+#define __ZLIB_DECODER_H\r
+\r
+#include "DeflateDecoder.h"\r
+\r
+namespace NCompress {\r
+namespace NZlib {\r
+\r
+const UInt32 ADLER_INIT_VAL = 1;\r
+\r
+class COutStreamWithAdler:\r
+  public ISequentialOutStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<ISequentialOutStream> _stream;\r
+  UInt32 _adler;\r
+public:\r
+  MY_UNKNOWN_IMP\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+  void SetStream(ISequentialOutStream *stream) { _stream = stream; }\r
+  void ReleaseStream() { _stream.Release(); }\r
+  void Init() { _adler = ADLER_INIT_VAL; }\r
+  UInt32 GetAdler() const { return _adler; }\r
+};\r
+\r
+class CDecoder:\r
+  public ICompressCoder,\r
+  public CMyUnknownImp\r
+{\r
+  COutStreamWithAdler *AdlerSpec;\r
+  CMyComPtr<ISequentialOutStream> AdlerStream;\r
+  \r
+  NCompress::NDeflate::NDecoder::CCOMCoder *DeflateDecoderSpec;\r
+  CMyComPtr<ICompressCoder> DeflateDecoder;\r
+public:\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+\r
+  UInt64 GetInputProcessedSize() const { return DeflateDecoderSpec->GetInputProcessedSize() + 2; }\r
+\r
+  MY_UNKNOWN_IMP\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/ZlibEncoder.cpp b/CPP/7zip/Compress/ZlibEncoder.cpp
new file mode 100755 (executable)
index 0000000..e023b74
--- /dev/null
@@ -0,0 +1,61 @@
+// ZlibEncoder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "ZlibEncoder.h"\r
+\r
+namespace NCompress {\r
+namespace NZlib {\r
+\r
+#define DEFLATE_TRY_BEGIN try {\r
+#define DEFLATE_TRY_END } catch(...) { return S_FALSE; }\r
+\r
+UInt32 Adler32_Update(UInt32 adler, const Byte *buf, size_t size);\r
+\r
+STDMETHODIMP CInStreamWithAdler::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  HRESULT result = _stream->Read(data, size, &size);\r
+  _adler = Adler32_Update(_adler, (const Byte *)data, size);\r
+  _size += size;\r
+  if (processedSize != NULL)\r
+    *processedSize = size;\r
+  return result;\r
+}\r
+\r
+void CEncoder::Create()\r
+{\r
+  if (!DeflateEncoder)\r
+    DeflateEncoder = DeflateEncoderSpec = new NDeflate::NEncoder::CCOMCoder;\r
+}\r
+\r
+STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+    const UInt64 *inSize, const UInt64 * /* outSize */, ICompressProgressInfo *progress)\r
+{\r
+  DEFLATE_TRY_BEGIN\r
+  if (!AdlerStream)\r
+    AdlerStream = AdlerSpec = new CInStreamWithAdler;\r
+  Create();\r
+\r
+  {\r
+    Byte buf[2] = { 0x78, 0xDA };\r
+    RINOK(WriteStream(outStream, buf, 2));\r
+  }\r
+\r
+  AdlerSpec->SetStream(inStream);\r
+  AdlerSpec->Init();\r
+  HRESULT res = DeflateEncoder->Code(AdlerStream, outStream, inSize, NULL, progress);\r
+  AdlerSpec->ReleaseStream();\r
+\r
+  RINOK(res);\r
+\r
+  {\r
+    UInt32 a = AdlerSpec->GetAdler();\r
+    Byte buf[4] = { (Byte)(a >> 24), (Byte)(a >> 16), (Byte)(a >> 8), (Byte)(a) };\r
+    return WriteStream(outStream, buf, 4);\r
+  }\r
+  DEFLATE_TRY_END\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Compress/ZlibEncoder.h b/CPP/7zip/Compress/ZlibEncoder.h
new file mode 100755 (executable)
index 0000000..3cac950
--- /dev/null
@@ -0,0 +1,48 @@
+// ZlibEncoder.h\r
+\r
+#ifndef __ZLIB_ENCODER_H\r
+#define __ZLIB_ENCODER_H\r
+\r
+#include "DeflateEncoder.h"\r
+\r
+namespace NCompress {\r
+namespace NZlib {\r
+\r
+class CInStreamWithAdler:\r
+  public ISequentialInStream,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<ISequentialInStream> _stream;\r
+  UInt32 _adler;\r
+  UInt64 _size;\r
+public:\r
+  MY_UNKNOWN_IMP\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+  void SetStream(ISequentialInStream *stream) { _stream = stream; }\r
+  void ReleaseStream() { _stream.Release(); }\r
+  void Init() { _adler = 1; _size = 0; } // ADLER_INIT_VAL\r
+  UInt32 GetAdler() const { return _adler; }\r
+  UInt64 GetSize() const { return _size; }\r
+};\r
+\r
+class CEncoder:\r
+  public ICompressCoder,\r
+  public CMyUnknownImp\r
+{\r
+  CInStreamWithAdler *AdlerSpec;\r
+  CMyComPtr<ISequentialInStream> AdlerStream;\r
+  CMyComPtr<ICompressCoder> DeflateEncoder;\r
+public:\r
+  NCompress::NDeflate::NEncoder::CCOMCoder *DeflateEncoderSpec;\r
+  \r
+  void Create();\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\r
+  UInt64 GetInputProcessedSize() const { return AdlerSpec->GetSize(); }\r
+\r
+  MY_UNKNOWN_IMP\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Compress/makefile b/CPP/7zip/Compress/makefile
new file mode 100755 (executable)
index 0000000..9be1878
--- /dev/null
@@ -0,0 +1,7 @@
+DIRS = \\r
+  LZMA_Alone\~ \\r
+  \r
+all: $(DIRS)\r
+\r
+$(DIRS):\r
+!include "../SubBuild.mak"\r
diff --git a/CPP/7zip/Crc.mak b/CPP/7zip/Crc.mak
new file mode 100755 (executable)
index 0000000..444f8fe
--- /dev/null
@@ -0,0 +1,8 @@
+C_OBJS = $(C_OBJS) \\r
+  $O\7zCrc.obj\r
+!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS"\r
+C_OBJS = $(C_OBJS) \\r
+!ELSE\r
+ASM_OBJS = $(ASM_OBJS) \\r
+!ENDIF\r
+  $O\7zCrcOpt.obj\r
diff --git a/CPP/7zip/Crypto/7zAes.cpp b/CPP/7zip/Crypto/7zAes.cpp
new file mode 100755 (executable)
index 0000000..aca5c29
--- /dev/null
@@ -0,0 +1,244 @@
+// 7zAes.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/Sha256.h"\r
+\r
+#include "Windows/Synchronization.h"\r
+\r
+#include "../Common/StreamObjects.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "7zAes.h"\r
+#include "MyAes.h"\r
+\r
+#ifndef EXTRACT_ONLY\r
+#include "RandGen.h"\r
+#endif\r
+\r
+using namespace NWindows;\r
+\r
+namespace NCrypto {\r
+namespace NSevenZ {\r
+\r
+bool CKeyInfo::IsEqualTo(const CKeyInfo &a) const\r
+{\r
+  if (SaltSize != a.SaltSize || NumCyclesPower != a.NumCyclesPower)\r
+    return false;\r
+  for (UInt32 i = 0; i < SaltSize; i++)\r
+    if (Salt[i] != a.Salt[i])\r
+      return false;\r
+  return (Password == a.Password);\r
+}\r
+\r
+void CKeyInfo::CalculateDigest()\r
+{\r
+  if (NumCyclesPower == 0x3F)\r
+  {\r
+    UInt32 pos;\r
+    for (pos = 0; pos < SaltSize; pos++)\r
+      Key[pos] = Salt[pos];\r
+    for (UInt32 i = 0; i < Password.GetCapacity() && pos < kKeySize; i++)\r
+      Key[pos++] = Password[i];\r
+    for (; pos < kKeySize; pos++)\r
+      Key[pos] = 0;\r
+  }\r
+  else\r
+  {\r
+    CSha256 sha;\r
+    Sha256_Init(&sha);\r
+    const UInt64 numRounds = (UInt64)1 << NumCyclesPower;\r
+    Byte temp[8] = { 0,0,0,0,0,0,0,0 };\r
+    for (UInt64 round = 0; round < numRounds; round++)\r
+    {\r
+      Sha256_Update(&sha, Salt, (size_t)SaltSize);\r
+      Sha256_Update(&sha, Password, Password.GetCapacity());\r
+      Sha256_Update(&sha, temp, 8);\r
+      for (int i = 0; i < 8; i++)\r
+        if (++(temp[i]) != 0)\r
+          break;\r
+    }\r
+    Sha256_Final(&sha, Key);\r
+  }\r
+}\r
+\r
+bool CKeyInfoCache::Find(CKeyInfo &key)\r
+{\r
+  for (int i = 0; i < Keys.Size(); i++)\r
+  {\r
+    const CKeyInfo &cached = Keys[i];\r
+    if (key.IsEqualTo(cached))\r
+    {\r
+      for (int j = 0; j < kKeySize; j++)\r
+        key.Key[j] = cached.Key[j];\r
+      if (i != 0)\r
+      {\r
+        Keys.Insert(0, cached);\r
+        Keys.Delete(i+1);\r
+      }\r
+      return true;\r
+    }\r
+  }\r
+  return false;\r
+}\r
+\r
+void CKeyInfoCache::Add(CKeyInfo &key)\r
+{\r
+  if (Find(key))\r
+    return;\r
+  if (Keys.Size() >= Size)\r
+    Keys.DeleteBack();\r
+  Keys.Insert(0, key);\r
+}\r
+\r
+static CKeyInfoCache g_GlobalKeyCache(32);\r
+static NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection;\r
+\r
+CBase::CBase():\r
+  _cachedKeys(16),\r
+  _ivSize(0)\r
+{\r
+  for (int i = 0; i < sizeof(_iv); i++)\r
+    _iv[i] = 0;\r
+}\r
+\r
+void CBase::CalculateDigest()\r
+{\r
+  NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection);\r
+  if (_cachedKeys.Find(_key))\r
+    g_GlobalKeyCache.Add(_key);\r
+  else\r
+  {\r
+    if (!g_GlobalKeyCache.Find(_key))\r
+    {\r
+      _key.CalculateDigest();\r
+      g_GlobalKeyCache.Add(_key);\r
+    }\r
+    _cachedKeys.Add(_key);\r
+  }\r
+}\r
+\r
+#ifndef EXTRACT_ONLY\r
+\r
+/*\r
+STDMETHODIMP CEncoder::ResetSalt()\r
+{\r
+  _key.SaltSize = 4;\r
+  g_RandomGenerator.Generate(_key.Salt, _key.SaltSize);\r
+  return S_OK;\r
+}\r
+*/\r
+\r
+STDMETHODIMP CEncoder::ResetInitVector()\r
+{\r
+  _ivSize = 8;\r
+  g_RandomGenerator.Generate(_iv, (unsigned)_ivSize);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)\r
+{\r
+   // _key.Init();\r
+   for (UInt32 i = _ivSize; i < sizeof(_iv); i++)\r
+    _iv[i] = 0;\r
+\r
+  UInt32 ivSize = _ivSize;\r
+  \r
+  // _key.NumCyclesPower = 0x3F;\r
+  _key.NumCyclesPower = 19;\r
+\r
+  Byte firstByte = (Byte)(_key.NumCyclesPower |\r
+    (((_key.SaltSize == 0) ? 0 : 1) << 7) |\r
+    (((ivSize == 0) ? 0 : 1) << 6));\r
+  RINOK(outStream->Write(&firstByte, 1, NULL));\r
+  if (_key.SaltSize == 0 && ivSize == 0)\r
+    return S_OK;\r
+  Byte saltSizeSpec = (Byte)((_key.SaltSize == 0) ? 0 : (_key.SaltSize - 1));\r
+  Byte ivSizeSpec = (Byte)((ivSize == 0) ? 0 : (ivSize - 1));\r
+  Byte secondByte = (Byte)(((saltSizeSpec) << 4) | ivSizeSpec);\r
+  RINOK(outStream->Write(&secondByte, 1, NULL));\r
+  if (_key.SaltSize > 0)\r
+  {\r
+    RINOK(WriteStream(outStream, _key.Salt, _key.SaltSize));\r
+  }\r
+  if (ivSize > 0)\r
+  {\r
+    RINOK(WriteStream(outStream, _iv, ivSize));\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CEncoder::CreateFilter()\r
+{\r
+  _aesFilter = new CAesCbcEncoder;\r
+  return S_OK;\r
+}\r
+\r
+#endif\r
+\r
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)\r
+{\r
+  _key.Init();\r
+  UInt32 i;\r
+  for (i = 0; i < sizeof(_iv); i++)\r
+    _iv[i] = 0;\r
+  if (size == 0)\r
+    return S_OK;\r
+  UInt32 pos = 0;\r
+  Byte firstByte = data[pos++];\r
+\r
+  _key.NumCyclesPower = firstByte & 0x3F;\r
+  if ((firstByte & 0xC0) == 0)\r
+    return S_OK;\r
+  _key.SaltSize = (firstByte >> 7) & 1;\r
+  UInt32 ivSize = (firstByte >> 6) & 1;\r
+\r
+  if (pos >= size)\r
+    return E_INVALIDARG;\r
+  Byte secondByte = data[pos++];\r
+  \r
+  _key.SaltSize += (secondByte >> 4);\r
+  ivSize += (secondByte & 0x0F);\r
+  \r
+  if (pos + _key.SaltSize + ivSize > size)\r
+    return E_INVALIDARG;\r
+  for (i = 0; i < _key.SaltSize; i++)\r
+    _key.Salt[i] = data[pos++];\r
+  for (i = 0; i < ivSize; i++)\r
+    _iv[i] = data[pos++];\r
+  return (_key.NumCyclesPower <= 24) ? S_OK :  E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)\r
+{\r
+  _key.Password.SetCapacity((size_t)size);\r
+  memcpy(_key.Password, data, (size_t)size);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CBaseCoder::Init()\r
+{\r
+  CalculateDigest();\r
+  if (_aesFilter == 0)\r
+  {\r
+    RINOK(CreateFilter());\r
+  }\r
+  CMyComPtr<ICryptoProperties> cp;\r
+  RINOK(_aesFilter.QueryInterface(IID_ICryptoProperties, &cp));\r
+  RINOK(cp->SetKey(_key.Key, sizeof(_key.Key)));\r
+  RINOK(cp->SetInitVector(_iv, sizeof(_iv)));\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP_(UInt32) CBaseCoder::Filter(Byte *data, UInt32 size)\r
+{\r
+  return _aesFilter->Filter(data, size);\r
+}\r
+\r
+HRESULT CDecoder::CreateFilter()\r
+{\r
+  _aesFilter = new CAesCbcDecoder;\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Crypto/7zAes.h b/CPP/7zip/Crypto/7zAes.h
new file mode 100755 (executable)
index 0000000..08da666
--- /dev/null
@@ -0,0 +1,117 @@
+// 7zAes.h\r
+\r
+#ifndef __CRYPTO_7Z_AES_H\r
+#define __CRYPTO_7Z_AES_H\r
+\r
+#include "Common/Buffer.h"\r
+#include "Common/MyCom.h"\r
+#include "Common/MyVector.h"\r
+\r
+#include "../ICoder.h"\r
+#include "../IPassword.h"\r
+\r
+namespace NCrypto {\r
+namespace NSevenZ {\r
+\r
+const int kKeySize = 32;\r
+\r
+class CKeyInfo\r
+{\r
+public:\r
+  int NumCyclesPower;\r
+  UInt32 SaltSize;\r
+  Byte Salt[16];\r
+  CByteBuffer Password;\r
+  Byte Key[kKeySize];\r
+\r
+  bool IsEqualTo(const CKeyInfo &a) const;\r
+  void CalculateDigest();\r
+\r
+  CKeyInfo() { Init(); }\r
+  void Init()\r
+  {\r
+    NumCyclesPower = 0;\r
+    SaltSize = 0;\r
+    for (int i = 0; i < sizeof(Salt); i++)\r
+      Salt[i] = 0;\r
+  }\r
+};\r
+\r
+class CKeyInfoCache\r
+{\r
+  int Size;\r
+  CObjectVector<CKeyInfo> Keys;\r
+public:\r
+  CKeyInfoCache(int size): Size(size) {}\r
+  bool Find(CKeyInfo &key);\r
+  // HRESULT Calculate(CKeyInfo &key);\r
+  void Add(CKeyInfo &key);\r
+};\r
+\r
+class CBase\r
+{\r
+  CKeyInfoCache _cachedKeys;\r
+protected:\r
+  CKeyInfo _key;\r
+  Byte _iv[16];\r
+  UInt32 _ivSize;\r
+  void CalculateDigest();\r
+  CBase();\r
+};\r
+\r
+class CBaseCoder:\r
+  public ICompressFilter,\r
+  public ICryptoSetPassword,\r
+  public CMyUnknownImp,\r
+  public CBase\r
+{\r
+protected:\r
+  CMyComPtr<ICompressFilter> _aesFilter;\r
+\r
+  virtual HRESULT CreateFilter() = 0;\r
+  #ifndef CRYPTO_AES\r
+  HRESULT CreateFilterFromDLL(REFCLSID clsID);\r
+  #endif\r
+public:\r
+  STDMETHOD(Init)();\r
+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);\r
+  \r
+  STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);\r
+};\r
+\r
+#ifndef EXTRACT_ONLY\r
+\r
+class CEncoder:\r
+  public CBaseCoder,\r
+  public ICompressWriteCoderProperties,\r
+  // public ICryptoResetSalt,\r
+  public ICryptoResetInitVector\r
+{\r
+  virtual HRESULT CreateFilter();\r
+public:\r
+  MY_UNKNOWN_IMP3(\r
+      ICryptoSetPassword,\r
+      ICompressWriteCoderProperties,\r
+      // ICryptoResetSalt,\r
+      ICryptoResetInitVector)\r
+  STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);\r
+  // STDMETHOD(ResetSalt)();\r
+  STDMETHOD(ResetInitVector)();\r
+};\r
+#endif\r
+\r
+class CDecoder:\r
+  public CBaseCoder,\r
+  public ICompressSetDecoderProperties2\r
+{\r
+  virtual HRESULT CreateFilter();\r
+public:\r
+  MY_UNKNOWN_IMP2(\r
+      ICryptoSetPassword,\r
+      ICompressSetDecoderProperties2)\r
+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Crypto/7zAesRegister.cpp b/CPP/7zip/Crypto/7zAesRegister.cpp
new file mode 100755 (executable)
index 0000000..87f8ae9
--- /dev/null
@@ -0,0 +1,18 @@
+// 7zAesRegister.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../Common/RegisterCodec.h"\r
+#include "7zAes.h"\r
+\r
+static void *CreateCodec() { return (void *)(ICompressFilter *)(new NCrypto::NSevenZ::CDecoder()); }\r
+#ifndef EXTRACT_ONLY\r
+static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new NCrypto::NSevenZ::CEncoder()); }\r
+#else\r
+#define CreateCodecOut 0\r
+#endif\r
+\r
+static CCodecInfo g_CodecInfo =\r
+  { CreateCodec, CreateCodecOut, 0x06F10701, L"7zAES", 1, true };\r
+\r
+REGISTER_CODEC(7zAES)\r
diff --git a/CPP/7zip/Crypto/Codec.def b/CPP/7zip/Crypto/Codec.def
new file mode 100755 (executable)
index 0000000..aab87ef
--- /dev/null
@@ -0,0 +1,4 @@
+EXPORTS\r
+  CreateObject PRIVATE\r
+  GetNumberOfMethods PRIVATE\r
+  GetMethodProperty PRIVATE\r
diff --git a/CPP/7zip/Crypto/HmacSha1.cpp b/CPP/7zip/Crypto/HmacSha1.cpp
new file mode 100755 (executable)
index 0000000..09621e9
--- /dev/null
@@ -0,0 +1,109 @@
+// HmacSha1.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "HmacSha1.h"\r
+\r
+namespace NCrypto {\r
+namespace NSha1 {\r
+\r
+void CHmac::SetKey(const Byte *key, size_t keySize)\r
+{\r
+  Byte keyTemp[kBlockSize];\r
+  size_t i;\r
+  for (i = 0; i < kBlockSize; i++)\r
+    keyTemp[i] = 0;\r
+  if(keySize > kBlockSize)\r
+  {\r
+    _sha.Init();\r
+    _sha.Update(key, keySize);\r
+    _sha.Final(keyTemp);\r
+    keySize = kDigestSize;\r
+  }\r
+  else\r
+    for (i = 0; i < keySize; i++)\r
+      keyTemp[i] = key[i];\r
+  for (i = 0; i < kBlockSize; i++)\r
+    keyTemp[i] ^= 0x36;\r
+  _sha.Init();\r
+  _sha.Update(keyTemp, kBlockSize);\r
+  for (i = 0; i < kBlockSize; i++)\r
+    keyTemp[i] ^= 0x36 ^ 0x5C;\r
+  _sha2.Init();\r
+  _sha2.Update(keyTemp, kBlockSize);\r
+}\r
+\r
+void CHmac::Final(Byte *mac, size_t macSize)\r
+{\r
+  Byte digest[kDigestSize];\r
+  _sha.Final(digest);\r
+  _sha2.Update(digest, kDigestSize);\r
+  _sha2.Final(digest);\r
+  for(size_t i = 0; i < macSize; i++)\r
+    mac[i] = digest[i];\r
+}\r
+\r
+\r
+void CHmac32::SetKey(const Byte *key, size_t keySize)\r
+{\r
+  UInt32 keyTemp[kBlockSizeInWords];\r
+  size_t i;\r
+  for (i = 0; i < kBlockSizeInWords; i++)\r
+    keyTemp[i] = 0;\r
+  if(keySize > kBlockSize)\r
+  {\r
+    CContext sha;\r
+    sha.Init();\r
+    sha.Update(key, keySize);\r
+    Byte digest[kDigestSize];\r
+    sha.Final(digest);\r
+    \r
+    for (int i = 0 ; i < kDigestSizeInWords; i++)\r
+      keyTemp[i] =\r
+          ((UInt32)(digest[i * 4 + 0]) << 24) |\r
+          ((UInt32)(digest[i * 4 + 1]) << 16) |\r
+          ((UInt32)(digest[i * 4 + 2]) <<  8) |\r
+          ((UInt32)(digest[i * 4 + 3]));\r
+    keySize = kDigestSizeInWords;\r
+  }\r
+  else\r
+    for (size_t i = 0; i < keySize; i++)\r
+      keyTemp[i / 4] |= (key[i] << (24 - 8 * (i & 3)));\r
+  for (i = 0; i < kBlockSizeInWords; i++)\r
+    keyTemp[i] ^= 0x36363636;\r
+  _sha.Init();\r
+  _sha.Update(keyTemp, kBlockSizeInWords);\r
+  for (i = 0; i < kBlockSizeInWords; i++)\r
+    keyTemp[i] ^= 0x36363636 ^ 0x5C5C5C5C;\r
+  _sha2.Init();\r
+  _sha2.Update(keyTemp, kBlockSizeInWords);\r
+}\r
+\r
+void CHmac32::Final(UInt32 *mac, size_t macSize)\r
+{\r
+  UInt32 digest[kDigestSizeInWords];\r
+  _sha.Final(digest);\r
+  _sha2.Update(digest, kDigestSizeInWords);\r
+  _sha2.Final(digest);\r
+  for(size_t i = 0; i < macSize; i++)\r
+    mac[i] = digest[i];\r
+}\r
+\r
+void CHmac32::GetLoopXorDigest(UInt32 *mac, UInt32 numIteration)\r
+{\r
+  UInt32 block[kBlockSizeInWords];\r
+  UInt32 block2[kBlockSizeInWords];\r
+  _sha.PrepareBlock(block, kDigestSizeInWords);\r
+  _sha2.PrepareBlock(block2, kDigestSizeInWords);\r
+  for(unsigned int s = 0; s < kDigestSizeInWords; s++)\r
+    block[s] = mac[s];\r
+  for(UInt32 i = 0; i < numIteration; i++)\r
+  {\r
+    _sha.GetBlockDigest(block, block2);\r
+    _sha2.GetBlockDigest(block2, block);\r
+    for (unsigned int s = 0; s < kDigestSizeInWords; s++)\r
+      mac[s] ^= block[s];\r
+  }\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Crypto/HmacSha1.h b/CPP/7zip/Crypto/HmacSha1.h
new file mode 100755 (executable)
index 0000000..2b12340
--- /dev/null
@@ -0,0 +1,39 @@
+// HmacSha1.h\r
+// Implements HMAC-SHA-1 (RFC2104, FIPS-198)\r
+\r
+#ifndef __CRYPTO_HMAC_SHA1_H\r
+#define __CRYPTO_HMAC_SHA1_H\r
+\r
+#include "Sha1.h"\r
+\r
+namespace NCrypto {\r
+namespace NSha1 {\r
+\r
+// Use:  SetKey(key, keySize); for () Update(data, size); Final(mac, macSize);\r
+\r
+class CHmac\r
+{\r
+  CContext _sha;\r
+  CContext _sha2;\r
+public:\r
+  void SetKey(const Byte *key, size_t keySize);\r
+  void Update(const Byte *data, size_t dataSize) { _sha.Update(data, dataSize); }\r
+  void Final(Byte *mac, size_t macSize = kDigestSize);\r
+};\r
+\r
+class CHmac32\r
+{\r
+  CContext32 _sha;\r
+  CContext32 _sha2;\r
+public:\r
+  void SetKey(const Byte *key, size_t keySize);\r
+  void Update(const UInt32 *data, size_t dataSize) { _sha.Update(data, dataSize); }\r
+  void Final(UInt32 *mac, size_t macSize = kDigestSizeInWords);\r
+  \r
+  // It'sa for hmac function. in,out: mac[kDigestSizeInWords].\r
+  void GetLoopXorDigest(UInt32 *mac, UInt32 numIteration);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Crypto/MyAes.cpp b/CPP/7zip/Crypto/MyAes.cpp
new file mode 100755 (executable)
index 0000000..150cbfa
--- /dev/null
@@ -0,0 +1,48 @@
+// Crypto/MyAes.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "MyAes.h"\r
+\r
+namespace NCrypto {\r
+\r
+struct CAesTabInit { CAesTabInit() { AesGenTables();} } g_AesTabInit;\r
+\r
+CAesCbcCoder::CAesCbcCoder()\r
+{\r
+  _offset = ((0 - (unsigned)(ptrdiff_t)_aes) & 0xF) / sizeof(UInt32);\r
+}\r
+\r
+STDMETHODIMP CAesCbcCoder::Init() { return S_OK; }\r
+\r
+STDMETHODIMP_(UInt32) CAesCbcCoder::Filter(Byte *data, UInt32 size)\r
+{\r
+  if (size == 0)\r
+    return 0;\r
+  if (size < AES_BLOCK_SIZE)\r
+    return AES_BLOCK_SIZE;\r
+  size >>= 4;\r
+  _codeFunc(_aes + _offset, data, size);\r
+  return size << 4;\r
+}\r
+\r
+STDMETHODIMP CAesCbcCoder::SetKey(const Byte *data, UInt32 size)\r
+{\r
+  if ((size & 0x7) != 0 || size < 16 || size > 32)\r
+    return E_INVALIDARG;\r
+  _setKeyFunc(_aes + _offset + 4, data, size);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CAesCbcCoder::SetInitVector(const Byte *data, UInt32 size)\r
+{\r
+  if (size != AES_BLOCK_SIZE)\r
+    return E_INVALIDARG;\r
+  AesCbc_Init(_aes + _offset, data);\r
+  return S_OK;\r
+}\r
+\r
+CAesCbcEncoder::CAesCbcEncoder() { _codeFunc = g_AesCbc_Encode; _setKeyFunc = Aes_SetKey_Enc; }\r
+CAesCbcDecoder::CAesCbcDecoder() { _codeFunc = g_AesCbc_Decode; _setKeyFunc = Aes_SetKey_Dec; }\r
+\r
+}\r
diff --git a/CPP/7zip/Crypto/MyAes.h b/CPP/7zip/Crypto/MyAes.h
new file mode 100755 (executable)
index 0000000..ab38536
--- /dev/null
@@ -0,0 +1,38 @@
+// Crypto/MyAes.h\r
+\r
+#ifndef __CRYPTO_MY_AES_H\r
+#define __CRYPTO_MY_AES_H\r
+\r
+#include "../../../C/Aes.h"\r
+\r
+#include "../../Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+\r
+namespace NCrypto {\r
+\r
+class CAesCbcCoder:\r
+  public ICompressFilter,\r
+  public ICryptoProperties,\r
+  public CMyUnknownImp\r
+{\r
+protected:\r
+  AES_CODE_FUNC _codeFunc;\r
+  AES_SET_KEY_FUNC _setKeyFunc;\r
+  unsigned _offset;\r
+  UInt32 _aes[AES_NUM_IVMRK_WORDS + 3];\r
+public:\r
+  CAesCbcCoder();\r
+  MY_UNKNOWN_IMP1(ICryptoProperties)\r
+  STDMETHOD(Init)();\r
+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);\r
+  STDMETHOD(SetKey)(const Byte *data, UInt32 size);\r
+  STDMETHOD(SetInitVector)(const Byte *data, UInt32 size);\r
+};\r
+\r
+struct CAesCbcEncoder: public CAesCbcCoder { CAesCbcEncoder(); };\r
+struct CAesCbcDecoder: public CAesCbcCoder { CAesCbcDecoder(); };\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp b/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp
new file mode 100755 (executable)
index 0000000..0ac6dc6
--- /dev/null
@@ -0,0 +1,83 @@
+// Pbkdf2HmacSha1.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "HmacSha1.h"\r
+\r
+namespace NCrypto {\r
+namespace NSha1 {\r
+\r
+void Pbkdf2Hmac(const Byte *pwd, size_t pwdSize, const Byte *salt, size_t saltSize,\r
+    UInt32 numIterations, Byte *key, size_t keySize)\r
+{\r
+  CHmac baseCtx;\r
+  baseCtx.SetKey(pwd, pwdSize);\r
+  for (UInt32 i = 1; keySize > 0; i++)\r
+  {\r
+    CHmac ctx = baseCtx;\r
+    ctx.Update(salt, saltSize);\r
+    Byte u[kDigestSize] = { (Byte)(i >> 24), (Byte)(i >> 16), (Byte)(i >> 8), (Byte)(i) };\r
+    const unsigned int curSize = (keySize < kDigestSize) ? (unsigned int)keySize : kDigestSize;\r
+    ctx.Update(u, 4);\r
+    ctx.Final(u, kDigestSize);\r
+\r
+    unsigned int s;\r
+    for (s = 0; s < curSize; s++)\r
+      key[s] = u[s];\r
+    \r
+    for (UInt32 j = numIterations; j > 1; j--)\r
+    {\r
+      ctx = baseCtx;\r
+      ctx.Update(u, kDigestSize);\r
+      ctx.Final(u, kDigestSize);\r
+      for (s = 0; s < curSize; s++)\r
+        key[s] ^= u[s];\r
+    }\r
+\r
+    key += curSize;\r
+    keySize -= curSize;\r
+  }\r
+}\r
+\r
+void Pbkdf2Hmac32(const Byte *pwd, size_t pwdSize, const UInt32 *salt, size_t saltSize,\r
+    UInt32 numIterations, UInt32 *key, size_t keySize)\r
+{\r
+  CHmac32 baseCtx;\r
+  baseCtx.SetKey(pwd, pwdSize);\r
+  for (UInt32 i = 1; keySize > 0; i++)\r
+  {\r
+    CHmac32 ctx = baseCtx;\r
+    ctx.Update(salt, saltSize);\r
+    UInt32 u[kDigestSizeInWords] = { i };\r
+    const unsigned int curSize = (keySize < kDigestSizeInWords) ? (unsigned int)keySize : kDigestSizeInWords;\r
+    ctx.Update(u, 1);\r
+    ctx.Final(u, kDigestSizeInWords);\r
+\r
+    // Speed-optimized code start\r
+    ctx = baseCtx;\r
+    ctx.GetLoopXorDigest(u, numIterations - 1);\r
+    // Speed-optimized code end\r
+    \r
+    unsigned int s;\r
+    for (s = 0; s < curSize; s++)\r
+      key[s] = u[s];\r
+    \r
+    /*\r
+    // Default code start\r
+    for (UInt32 j = numIterations; j > 1; j--)\r
+    {\r
+      ctx = baseCtx;\r
+      ctx.Update(u, kDigestSizeInWords);\r
+      ctx.Final(u, kDigestSizeInWords);\r
+      for (s = 0; s < curSize; s++)\r
+        key[s] ^= u[s];\r
+    }\r
+    // Default code end\r
+    */\r
+\r
+    key += curSize;\r
+    keySize -= curSize;\r
+  }\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Crypto/Pbkdf2HmacSha1.h b/CPP/7zip/Crypto/Pbkdf2HmacSha1.h
new file mode 100755 (executable)
index 0000000..ea5d99f
--- /dev/null
@@ -0,0 +1,21 @@
+// Pbkdf2HmacSha1.h\r
+// Password-Based Key Derivation Function (RFC 2898, PKCS #5) based on HMAC-SHA-1\r
+\r
+#ifndef __CRYPTO_PBKDF2_HMAC_SHA1_H\r
+#define __CRYPTO_PBKDF2_HMAC_SHA1_H\r
+\r
+#include <stddef.h>\r
+#include "../../Common/Types.h"\r
+\r
+namespace NCrypto {\r
+namespace NSha1 {\r
+\r
+void Pbkdf2Hmac(const Byte *pwd, size_t pwdSize, const Byte *salt, size_t saltSize,\r
+    UInt32 numIterations, Byte *key, size_t keySize);\r
+\r
+void Pbkdf2Hmac32(const Byte *pwd, size_t pwdSize, const UInt32 *salt, size_t saltSize,\r
+    UInt32 numIterations, UInt32 *key, size_t keySize);\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Crypto/RandGen.cpp b/CPP/7zip/Crypto/RandGen.cpp
new file mode 100755 (executable)
index 0000000..66b3231
--- /dev/null
@@ -0,0 +1,107 @@
+// RandGen.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include <stdio.h>\r
+#include "Windows/Synchronization.h"\r
+#include "RandGen.h"\r
+\r
+#ifndef _WIN32\r
+#include <unistd.h>\r
+#define USE_POSIX_TIME\r
+#define USE_POSIX_TIME2\r
+#endif\r
+\r
+#ifdef USE_POSIX_TIME\r
+#include <time.h>\r
+#ifdef USE_POSIX_TIME2\r
+#include <sys/time.h>\r
+#endif\r
+#endif\r
+\r
+// This is not very good random number generator.\r
+// Please use it only for salt.\r
+// First generated data block depends from timer and processID.\r
+// Other generated data blocks depend from previous state\r
+// Maybe it's possible to restore original timer value from generated value.\r
+\r
+void CRandomGenerator::Init()\r
+{\r
+  NCrypto::NSha1::CContext hash;\r
+  hash.Init();\r
+\r
+  #ifdef _WIN32\r
+  DWORD w = ::GetCurrentProcessId();\r
+  hash.Update((const Byte *)&w, sizeof(w));\r
+  w = ::GetCurrentThreadId();\r
+  hash.Update((const Byte *)&w, sizeof(w));\r
+  #else\r
+  pid_t pid = getpid();\r
+  hash.Update((const Byte *)&pid, sizeof(pid));\r
+  pid = getppid();\r
+  hash.Update((const Byte *)&pid, sizeof(pid));\r
+  #endif\r
+\r
+  for (int i = 0; i < 1000; i++)\r
+  {\r
+    #ifdef _WIN32\r
+    LARGE_INTEGER v;\r
+    if (::QueryPerformanceCounter(&v))\r
+      hash.Update((const Byte *)&v.QuadPart, sizeof(v.QuadPart));\r
+    #endif\r
+\r
+    #ifdef USE_POSIX_TIME\r
+    #ifdef USE_POSIX_TIME2\r
+    timeval v;\r
+    if (gettimeofday(&v, 0) == 0)\r
+    {\r
+      hash.Update((const Byte *)&v.tv_sec, sizeof(v.tv_sec));\r
+      hash.Update((const Byte *)&v.tv_usec, sizeof(v.tv_usec));\r
+    }\r
+    #endif\r
+    time_t v2 = time(NULL);\r
+    hash.Update((const Byte *)&v2, sizeof(v2));\r
+    #endif\r
+\r
+    DWORD tickCount = ::GetTickCount();\r
+    hash.Update((const Byte *)&tickCount, sizeof(tickCount));\r
+    \r
+    for (int j = 0; j < 100; j++)\r
+    {\r
+      hash.Final(_buff);\r
+      hash.Init();\r
+      hash.Update(_buff, NCrypto::NSha1::kDigestSize);\r
+    }\r
+  }\r
+  hash.Final(_buff);\r
+  _needInit = false;\r
+}\r
+\r
+static NWindows::NSynchronization::CCriticalSection g_CriticalSection;\r
+\r
+void CRandomGenerator::Generate(Byte *data, unsigned int size)\r
+{\r
+  g_CriticalSection.Enter();\r
+  if (_needInit)\r
+    Init();\r
+  while (size > 0)\r
+  {\r
+    NCrypto::NSha1::CContext hash;\r
+    \r
+    hash.Init();\r
+    hash.Update(_buff, NCrypto::NSha1::kDigestSize);\r
+    hash.Final(_buff);\r
+    \r
+    hash.Init();\r
+    UInt32 salt = 0xF672ABD1;\r
+    hash.Update((const Byte *)&salt, sizeof(salt));\r
+    hash.Update(_buff, NCrypto::NSha1::kDigestSize);\r
+    Byte buff[NCrypto::NSha1::kDigestSize];\r
+    hash.Final(buff);\r
+    for (unsigned int i = 0; i < NCrypto::NSha1::kDigestSize && size > 0; i++, size--)\r
+      *data++ = buff[i];\r
+  }\r
+  g_CriticalSection.Leave();\r
+}\r
+\r
+CRandomGenerator g_RandomGenerator;\r
diff --git a/CPP/7zip/Crypto/RandGen.h b/CPP/7zip/Crypto/RandGen.h
new file mode 100755 (executable)
index 0000000..a457897
--- /dev/null
@@ -0,0 +1,21 @@
+// RandGen.h\r
+\r
+#ifndef __CRYPTO_RAND_GEN_H\r
+#define __CRYPTO_RAND_GEN_H\r
+\r
+#include "Sha1.h"\r
+\r
+class CRandomGenerator\r
+{\r
+  Byte _buff[NCrypto::NSha1::kDigestSize];\r
+  bool _needInit;\r
+\r
+  void Init();\r
+public:\r
+  CRandomGenerator(): _needInit(true) {};\r
+  void Generate(Byte *data, unsigned size);\r
+};\r
+\r
+extern CRandomGenerator g_RandomGenerator;\r
+\r
+#endif\r
diff --git a/CPP/7zip/Crypto/Rar20Crypto.cpp b/CPP/7zip/Crypto/Rar20Crypto.cpp
new file mode 100755 (executable)
index 0000000..1ea8433
--- /dev/null
@@ -0,0 +1,133 @@
+// Crypto/Rar20Crypto.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/7zCrc.h"\r
+#include "../../../C/CpuArch.h"\r
+#include "../../../C/RotateDefs.h"\r
+\r
+#include "Rar20Crypto.h"\r
+\r
+namespace NCrypto {\r
+namespace NRar20 {\r
+\r
+static const int kNumRounds = 32;\r
+\r
+static const Byte InitSubstTable[256] = {\r
+  215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221,  2, 42,\r
+  232,  1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137,\r
+  255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86,  6,\r
+   71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235,\r
+  107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36,\r
+  158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251,\r
+   97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11,\r
+  164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51,\r
+  207,120,189,210,  8,226, 41, 72,183,203,135,165,166, 60, 98,  7,\r
+  122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80,\r
+  131,  3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129,\r
+  224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10,\r
+  118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45,  4,148,108,\r
+  161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225,\r
+    0, 46,169,186, 68, 95,237, 65, 53,208,253,168,  9, 18,100, 52,\r
+  116,184,160, 96,109, 37, 30,106,140,104,150,  5,204,117,112, 84\r
+};\r
+\r
+void CData::UpdateKeys(const Byte *data)\r
+{\r
+  for (int i = 0; i < 16; i += 4)\r
+    for (int j = 0; j < 4; j++)\r
+      Keys[j] ^= g_CrcTable[data[i + j]];\r
+}\r
+\r
+static void Swap(Byte *b1, Byte *b2)\r
+{\r
+  Byte b = *b1;\r
+  *b1 = *b2;\r
+  *b2 = b;\r
+}\r
+\r
+void CData::SetPassword(const Byte *password, UInt32 passwordLen)\r
+{\r
+  Keys[0] = 0xD3A3B879L;\r
+  Keys[1] = 0x3F6D12F7L;\r
+  Keys[2] = 0x7515A235L;\r
+  Keys[3] = 0xA4E7F123L;\r
+  \r
+  Byte psw[256];\r
+  memset(psw, 0, sizeof(psw));\r
+  memcpy(psw, password, passwordLen);\r
+  memcpy(SubstTable, InitSubstTable, sizeof(SubstTable));\r
+\r
+  for (UInt32 j = 0; j < 256; j++)\r
+    for (UInt32 i = 0; i < passwordLen; i += 2)\r
+    {\r
+      UInt32 n2 = (Byte)g_CrcTable[(psw[i + 1] + j) & 0xFF];\r
+      UInt32 n1 = (Byte)g_CrcTable[(psw[i] - j) & 0xFF];\r
+      for (UInt32 k = 1; (n1 & 0xFF) != n2; n1++, k++)\r
+        Swap(&SubstTable[n1 & 0xFF], &SubstTable[(n1 + i + k) & 0xFF]);\r
+    }\r
+  for (UInt32 i = 0; i < passwordLen; i+= 16)\r
+    EncryptBlock(&psw[i]);\r
+}\r
+\r
+void CData::CryptBlock(Byte *buf, bool encrypt)\r
+{\r
+  Byte inBuf[16];\r
+  UInt32 A, B, C, D, T, TA, TB;\r
+\r
+  A = GetUi32(buf +  0) ^ Keys[0];\r
+  B = GetUi32(buf +  4) ^ Keys[1];\r
+  C = GetUi32(buf +  8) ^ Keys[2];\r
+  D = GetUi32(buf + 12) ^ Keys[3];\r
+\r
+  if (!encrypt)\r
+    memcpy(inBuf, buf, sizeof(inBuf));\r
+  \r
+  for (int i = 0; i < kNumRounds; i++)\r
+  {\r
+    UInt32 key = Keys[(encrypt ? i : (kNumRounds - 1 - i)) & 3];\r
+    T = ((C + rotlFixed(D, 11)) ^ key);\r
+    TA = A ^ SubstLong(T);\r
+    T = ((D ^ rotlFixed(C, 17)) + key);\r
+    TB = B ^ SubstLong(T);\r
+    A = C;\r
+    B = D;\r
+    C = TA;\r
+    D = TB;\r
+  }\r
+\r
+  SetUi32(buf +  0, C ^ Keys[0]);\r
+  SetUi32(buf +  4, D ^ Keys[1]);\r
+  SetUi32(buf +  8, A ^ Keys[2]);\r
+  SetUi32(buf + 12, B ^ Keys[3]);\r
+\r
+  UpdateKeys(encrypt ? buf : inBuf);\r
+}\r
+\r
+STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size)\r
+{\r
+  _cipher.SetPassword(data, size);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CDecoder::Init()\r
+{\r
+  return S_OK;\r
+}\r
+\r
+static const UInt32 kBlockSize = 16;\r
+\r
+STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)\r
+{\r
+  if (size == 0)\r
+    return 0;\r
+  if (size < kBlockSize)\r
+    return kBlockSize;\r
+  UInt32 i;\r
+  size -= kBlockSize;\r
+  for (i = 0; i <= size; i += kBlockSize)\r
+    _cipher.DecryptBlock(data + i);\r
+  return i;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Crypto/Rar20Crypto.h b/CPP/7zip/Crypto/Rar20Crypto.h
new file mode 100755 (executable)
index 0000000..36f5590
--- /dev/null
@@ -0,0 +1,50 @@
+// Crypto/Rar20Crypto.h\r
+\r
+#ifndef __CRYPTO_RAR20_CRYPTO_H\r
+#define __CRYPTO_RAR20_CRYPTO_H\r
+\r
+#include "Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+#include "../IPassword.h"\r
+\r
+namespace NCrypto {\r
+namespace NRar20 {\r
+\r
+class CData\r
+{\r
+  Byte SubstTable[256];\r
+  UInt32 Keys[4];\r
+  \r
+  UInt32 SubstLong(UInt32 t)\r
+  {\r
+    return (UInt32)SubstTable[(int)t & 255] |\r
+           ((UInt32)SubstTable[(int)(t >> 8) & 255] << 8) |\r
+           ((UInt32)SubstTable[(int)(t >> 16) & 255] << 16) |\r
+           ((UInt32)SubstTable[(int)(t >> 24) & 255] << 24);\r
+  }\r
+  void UpdateKeys(const Byte *data);\r
+  void CryptBlock(Byte *buf, bool encrypt);\r
+public:\r
+  void EncryptBlock(Byte *buf) { CryptBlock(buf, true); }\r
+  void DecryptBlock(Byte *buf) { CryptBlock(buf, false); }\r
+  void SetPassword(const Byte *password, UInt32 passwordLen);\r
+};\r
+\r
+class CDecoder:\r
+  public ICompressFilter,\r
+  public ICryptoSetPassword,\r
+  public CMyUnknownImp\r
+{\r
+  CData _cipher;\r
+public:\r
+  MY_UNKNOWN_IMP1(ICryptoSetPassword)\r
+\r
+  STDMETHOD(Init)();\r
+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);\r
+  STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Crypto/RarAes.cpp b/CPP/7zip/Crypto/RarAes.cpp
new file mode 100755 (executable)
index 0000000..a6a4642
--- /dev/null
@@ -0,0 +1,134 @@
+// Crypto/RarAes.cpp\r
+// Note: you must include MyAes.cpp to project to initialize AES tables\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "RarAes.h"\r
+#include "Sha1.h"\r
+\r
+namespace NCrypto {\r
+namespace NRar29 {\r
+\r
+CDecoder::CDecoder():\r
+  _thereIsSalt(false),\r
+  _needCalculate(true),\r
+  _rar350Mode(false)\r
+{\r
+  for (int i = 0; i < sizeof(_salt); i++)\r
+    _salt[i] = 0;\r
+}\r
+\r
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)\r
+{\r
+  bool thereIsSaltPrev = _thereIsSalt;\r
+  _thereIsSalt = false;\r
+  if (size == 0)\r
+    return S_OK;\r
+  if (size < 8)\r
+    return E_INVALIDARG;\r
+  _thereIsSalt = true;\r
+  bool same = false;\r
+  if (_thereIsSalt == thereIsSaltPrev)\r
+  {\r
+    same = true;\r
+    if (_thereIsSalt)\r
+    {\r
+      for (unsigned i = 0; i < sizeof(_salt); i++)\r
+        if (_salt[i] != data[i])\r
+        {\r
+          same = false;\r
+          break;\r
+        }\r
+    }\r
+  }\r
+  for (unsigned i = 0; i < sizeof(_salt); i++)\r
+    _salt[i] = data[i];\r
+  if (!_needCalculate && !same)\r
+    _needCalculate = true;\r
+  return S_OK;\r
+}\r
+\r
+static const unsigned kMaxPasswordLength = 127 * 2;\r
+\r
+STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size)\r
+{\r
+  if (size > kMaxPasswordLength)\r
+    size = kMaxPasswordLength;\r
+  bool same = false;\r
+  if (size == buffer.GetCapacity())\r
+  {\r
+    same = true;\r
+    for (UInt32 i = 0; i < size; i++)\r
+      if (data[i] != buffer[i])\r
+      {\r
+        same = false;\r
+        break;\r
+      }\r
+  }\r
+  if (!_needCalculate && !same)\r
+    _needCalculate = true;\r
+  buffer.SetCapacity(size);\r
+  memcpy(buffer, data, size);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CDecoder::Init()\r
+{\r
+  Calculate();\r
+  SetKey(aesKey, kRarAesKeySize);\r
+  AesCbc_Init(_aes + _offset, _aesInit);\r
+  return S_OK;\r
+}\r
+\r
+void CDecoder::Calculate()\r
+{\r
+  if (_needCalculate)\r
+  {\r
+    const unsigned kSaltSize = 8;\r
+    \r
+    Byte rawPassword[kMaxPasswordLength + kSaltSize];\r
+    \r
+    memcpy(rawPassword, buffer, buffer.GetCapacity());\r
+    \r
+    size_t rawLength = buffer.GetCapacity();\r
+    \r
+    if (_thereIsSalt)\r
+    {\r
+      memcpy(rawPassword + rawLength, _salt, kSaltSize);\r
+      rawLength += kSaltSize;\r
+    }\r
+    \r
+    NSha1::CContext sha;\r
+    sha.Init();\r
+\r
+    // rar reverts hash for sha.\r
+    const unsigned kNumRounds = (1 << 18);\r
+    unsigned i;\r
+    for (i = 0; i < kNumRounds; i++)\r
+    {\r
+      sha.UpdateRar(rawPassword, rawLength, _rar350Mode);\r
+      Byte pswNum[3] = { (Byte)i, (Byte)(i >> 8), (Byte)(i >> 16) };\r
+      sha.UpdateRar(pswNum, 3, _rar350Mode);\r
+      if (i % (kNumRounds / 16) == 0)\r
+      {\r
+        NSha1::CContext shaTemp = sha;\r
+        Byte digest[NSha1::kDigestSize];\r
+        shaTemp.Final(digest);\r
+        _aesInit[i / (kNumRounds / 16)] = (Byte)digest[4 * 4 + 3];\r
+      }\r
+    }\r
+    /*\r
+    // it's test message for sha\r
+    const char *message = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";\r
+    sha.Update((const Byte *)message, strlen(message));\r
+    */\r
+    Byte digest[20];\r
+    sha.Final(digest);\r
+    for (i = 0; i < 4; i++)\r
+      for (unsigned j = 0; j < 4; j++)\r
+        aesKey[i * 4 + j] = (digest[i * 4 + 3 - j]);\r
+  }\r
+  _needCalculate = false;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Crypto/RarAes.h b/CPP/7zip/Crypto/RarAes.h
new file mode 100755 (executable)
index 0000000..e1cc4bc
--- /dev/null
@@ -0,0 +1,47 @@
+// Crypto/RarAes.h\r
+\r
+#ifndef __CRYPTO_RAR_AES_H\r
+#define __CRYPTO_RAR_AES_H\r
+\r
+#include "../../../C/Aes.h"\r
+\r
+#include "Common/Buffer.h"\r
+\r
+#include "../IPassword.h"\r
+\r
+#include "MyAes.h"\r
+\r
+namespace NCrypto {\r
+namespace NRar29 {\r
+\r
+const UInt32 kRarAesKeySize = 16;\r
+\r
+class CDecoder:\r
+  public CAesCbcDecoder,\r
+  public ICompressSetDecoderProperties2,\r
+  public ICryptoSetPassword\r
+{\r
+  Byte _salt[8];\r
+  bool _thereIsSalt;\r
+  CByteBuffer buffer;\r
+  Byte aesKey[kRarAesKeySize];\r
+  Byte _aesInit[AES_BLOCK_SIZE];\r
+  bool _needCalculate;\r
+  bool _rar350Mode;\r
+\r
+  void Calculate();\r
+public:\r
+  MY_UNKNOWN_IMP2(\r
+    ICryptoSetPassword,\r
+    ICompressSetDecoderProperties2)\r
+  STDMETHOD(Init)();\r
+  STDMETHOD(CryptoSetPassword)(const Byte *aData, UInt32 aSize);\r
+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);\r
+\r
+  CDecoder();\r
+  void SetRar350Mode(bool rar350Mode) { _rar350Mode = rar350Mode; }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Crypto/Sha1.cpp b/CPP/7zip/Crypto/Sha1.cpp
new file mode 100755 (executable)
index 0000000..cc8bf4f
--- /dev/null
@@ -0,0 +1,229 @@
+// Crypto/Sha1.cpp\r
+// This file is based on public domain\r
+// Steve Reid and Wei Dai's code from Crypto++\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/RotateDefs.h"\r
+\r
+#include "Sha1.h"\r
+\r
+namespace NCrypto {\r
+namespace NSha1 {\r
+\r
+// define it for speed optimization\r
+// #define _SHA1_UNROLL\r
+\r
+static const unsigned kNumW =\r
+  #ifdef _SHA1_UNROLL\r
+  16;\r
+  #else\r
+  80;\r
+  #endif\r
+  \r
+\r
+#define w0(i) (W[(i)] = data[(i)])\r
+\r
+#ifdef _SHA1_UNROLL\r
+#define w1(i) (W[(i)&15] = rotlFixed(W[((i)-3)&15] ^ W[((i)-8)&15] ^ W[((i)-14)&15] ^ W[((i)-16)&15], 1))\r
+#else\r
+#define w1(i) (W[(i)] = rotlFixed(W[(i)-3] ^ W[(i)-8] ^ W[(i)-14] ^ W[(i)-16], 1))\r
+#endif\r
+\r
+#define f1(x,y,z) (z^(x&(y^z)))\r
+#define f2(x,y,z) (x^y^z)\r
+#define f3(x,y,z) ((x&y)|(z&(x|y)))\r
+#define f4(x,y,z) (x^y^z)\r
+\r
+#define RK1(a,b,c,d,e,i, f, w, k) e += f(b,c,d) + w(i) + k + rotlFixed(a,5); b = rotlFixed(b,30);\r
+\r
+#define R0(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f1, w0, 0x5A827999)\r
+#define R1(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f1, w1, 0x5A827999)\r
+#define R2(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f2, w1, 0x6ED9EBA1)\r
+#define R3(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f3, w1, 0x8F1BBCDC)\r
+#define R4(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f4, w1, 0xCA62C1D6)\r
+\r
+#define RX_1_4(rx1, rx4, i) rx1(a,b,c,d,e,i); rx4(e,a,b,c,d,i+1); rx4(d,e,a,b,c,i+2); rx4(c,d,e,a,b,i+3); rx4(b,c,d,e,a,i+4);\r
+#define RX_5(rx, i) RX_1_4(rx, rx, i);\r
+\r
+void CContextBase::Init()\r
+{\r
+  _state[0] = 0x67452301;\r
+  _state[1] = 0xEFCDAB89;\r
+  _state[2] = 0x98BADCFE;\r
+  _state[3] = 0x10325476;\r
+  _state[4] = 0xC3D2E1F0;\r
+  _count = 0;\r
+}\r
+\r
+void CContextBase::GetBlockDigest(UInt32 *data, UInt32 *destDigest, bool returnRes)\r
+{\r
+  UInt32 a, b, c, d, e;\r
+  UInt32 W[kNumW];\r
+\r
+  a = _state[0];\r
+  b = _state[1];\r
+  c = _state[2];\r
+  d = _state[3];\r
+  e = _state[4];\r
+  #ifdef _SHA1_UNROLL\r
+  RX_5(R0, 0); RX_5(R0, 5); RX_5(R0, 10);\r
+  #else\r
+  int i;\r
+  for (i = 0; i < 15; i += 5) { RX_5(R0, i); }\r
+  #endif\r
+\r
+  RX_1_4(R0, R1, 15);\r
+\r
+\r
+  #ifdef _SHA1_UNROLL\r
+  RX_5(R2, 20); RX_5(R2, 25); RX_5(R2, 30); RX_5(R2, 35);\r
+  RX_5(R3, 40); RX_5(R3, 45); RX_5(R3, 50); RX_5(R3, 55);\r
+  RX_5(R4, 60); RX_5(R4, 65); RX_5(R4, 70); RX_5(R4, 75);\r
+  #else\r
+  i = 20;\r
+  for (; i < 40; i += 5) { RX_5(R2, i); }\r
+  for (; i < 60; i += 5) { RX_5(R3, i); }\r
+  for (; i < 80; i += 5) { RX_5(R4, i); }\r
+  #endif\r
+\r
+  destDigest[0] = _state[0] + a;\r
+  destDigest[1] = _state[1] + b;\r
+  destDigest[2] = _state[2] + c;\r
+  destDigest[3] = _state[3] + d;\r
+  destDigest[4] = _state[4] + e;\r
+\r
+  if (returnRes)\r
+    for (int i = 0 ; i < 16; i++)\r
+      data[i] = W[kNumW - 16 + i];\r
+  \r
+  // Wipe variables\r
+  // a = b = c = d = e = 0;\r
+}\r
+\r
+void CContextBase::PrepareBlock(UInt32 *block, unsigned size) const\r
+{\r
+  unsigned curBufferPos = size & 0xF;\r
+  block[curBufferPos++] = 0x80000000;\r
+  while (curBufferPos != (16 - 2))\r
+    block[curBufferPos++] = 0;\r
+  const UInt64 lenInBits = (_count << 9) + ((UInt64)size << 5);\r
+  block[curBufferPos++] = (UInt32)(lenInBits >> 32);\r
+  block[curBufferPos++] = (UInt32)(lenInBits);\r
+}\r
+\r
+void CContext::Update(const Byte *data, size_t size)\r
+{\r
+  unsigned curBufferPos = _count2;\r
+  while (size--)\r
+  {\r
+    int pos = (int)(curBufferPos & 3);\r
+    if (pos == 0)\r
+      _buffer[curBufferPos >> 2] = 0;\r
+    _buffer[curBufferPos >> 2] |= ((UInt32)*data++) << (8 * (3 - pos));\r
+    if (++curBufferPos == kBlockSize)\r
+    {\r
+      curBufferPos = 0;\r
+      CContextBase::UpdateBlock(_buffer, false);\r
+    }\r
+  }\r
+  _count2 = curBufferPos;\r
+}\r
+\r
+void CContext::UpdateRar(Byte *data, size_t size, bool rar350Mode)\r
+{\r
+  bool returnRes = false;\r
+  unsigned curBufferPos = _count2;\r
+  while (size--)\r
+  {\r
+    int pos = (int)(curBufferPos & 3);\r
+    if (pos == 0)\r
+      _buffer[curBufferPos >> 2] = 0;\r
+    _buffer[curBufferPos >> 2] |= ((UInt32)*data++) << (8 * (3 - pos));\r
+    if (++curBufferPos == kBlockSize)\r
+    {\r
+      curBufferPos = 0;\r
+      CContextBase::UpdateBlock(_buffer, returnRes);\r
+      if (returnRes)\r
+        for (int i = 0; i < kBlockSizeInWords; i++)\r
+        {\r
+          UInt32 d = _buffer[i];\r
+          data[i * 4 + 0 - kBlockSize] = (Byte)(d);\r
+          data[i * 4 + 1 - kBlockSize] = (Byte)(d >>  8);\r
+          data[i * 4 + 2 - kBlockSize] = (Byte)(d >> 16);\r
+          data[i * 4 + 3 - kBlockSize] = (Byte)(d >> 24);\r
+        }\r
+      returnRes = rar350Mode;\r
+    }\r
+  }\r
+  _count2 = curBufferPos;\r
+}\r
+\r
+void CContext::Final(Byte *digest)\r
+{\r
+  const UInt64 lenInBits = (_count << 9) + ((UInt64)_count2 << 3);\r
+  unsigned curBufferPos = _count2;\r
+  int pos = (int)(curBufferPos & 3);\r
+  curBufferPos >>= 2;\r
+  if (pos == 0)\r
+    _buffer[curBufferPos] = 0;\r
+  _buffer[curBufferPos++] |= ((UInt32)0x80) << (8 * (3 - pos));\r
+\r
+  while (curBufferPos != (16 - 2))\r
+  {\r
+    curBufferPos &= 0xF;\r
+    if (curBufferPos == 0)\r
+      UpdateBlock();\r
+    _buffer[curBufferPos++] = 0;\r
+  }\r
+  _buffer[curBufferPos++] = (UInt32)(lenInBits >> 32);\r
+  _buffer[curBufferPos++] = (UInt32)(lenInBits);\r
+  UpdateBlock();\r
+\r
+  int i;\r
+  for (i = 0; i < kDigestSizeInWords; i++)\r
+  {\r
+    UInt32 state = _state[i] & 0xFFFFFFFF;\r
+    *digest++ = (Byte)(state >> 24);\r
+    *digest++ = (Byte)(state >> 16);\r
+    *digest++ = (Byte)(state >> 8);\r
+    *digest++ = (Byte)(state);\r
+  }\r
+  Init();\r
+}\r
+\r
+///////////////////////////\r
+// Words version\r
+\r
+void CContext32::Update(const UInt32 *data, size_t size)\r
+{\r
+  while (size--)\r
+  {\r
+    _buffer[_count2++] = *data++;\r
+    if (_count2 == kBlockSizeInWords)\r
+    {\r
+      _count2 = 0;\r
+      UpdateBlock();\r
+    }\r
+  }\r
+}\r
+\r
+void CContext32::Final(UInt32 *digest)\r
+{\r
+  const UInt64 lenInBits = (_count << 9) + ((UInt64)_count2 << 5);\r
+  unsigned curBufferPos = _count2;\r
+  _buffer[curBufferPos++] = 0x80000000;\r
+  while (curBufferPos != (16 - 2))\r
+  {\r
+    curBufferPos &= 0xF;\r
+    if (curBufferPos == 0)\r
+      UpdateBlock();\r
+    _buffer[curBufferPos++] = 0;\r
+  }\r
+  _buffer[curBufferPos++] = (UInt32)(lenInBits >> 32);\r
+  _buffer[curBufferPos++] = (UInt32)(lenInBits);\r
+  GetBlockDigest(_buffer, digest);\r
+  Init();\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Crypto/Sha1.h b/CPP/7zip/Crypto/Sha1.h
new file mode 100755 (executable)
index 0000000..1317c53
--- /dev/null
@@ -0,0 +1,68 @@
+// Crypto/Sha1.h\r
+// This file is based on public domain\r
+// Steve Reid and Wei Dai's code from Crypto++\r
+\r
+#ifndef __CRYPTO_SHA1_H\r
+#define __CRYPTO_SHA1_H\r
+\r
+#include <stddef.h>\r
+#include "../../Common/Types.h"\r
+\r
+// Sha1 implementation in RAR before version 3.60 has bug:\r
+// it changes data bytes in some cases.\r
+// So this class supports both versions: normal_SHA and rar3Mode\r
+\r
+namespace NCrypto {\r
+namespace NSha1 {\r
+\r
+const unsigned kBlockSize = 64;\r
+const unsigned kDigestSize = 20;\r
+\r
+const unsigned kBlockSizeInWords = (kBlockSize >> 2);\r
+const unsigned kDigestSizeInWords = (kDigestSize >> 2);\r
+\r
+class CContextBase\r
+{\r
+protected:\r
+  UInt32 _state[5];\r
+  UInt64 _count;\r
+  void UpdateBlock(UInt32 *data, bool returnRes = false)\r
+  {\r
+    GetBlockDigest(data, _state, returnRes);\r
+    _count++;\r
+  }\r
+public:\r
+  void Init();\r
+  void GetBlockDigest(UInt32 *blockData, UInt32 *destDigest, bool returnRes = false);\r
+  // PrepareBlock can be used only when size <= 13. size in Words\r
+  void PrepareBlock(UInt32 *block, unsigned int size) const;\r
+};\r
+\r
+class CContextBase2: public CContextBase\r
+{\r
+protected:\r
+  unsigned _count2;\r
+  UInt32 _buffer[kBlockSizeInWords];\r
+  void UpdateBlock() { CContextBase::UpdateBlock(_buffer); }\r
+public:\r
+  void Init() { CContextBase::Init(); _count2 = 0; }\r
+};\r
+\r
+class CContext: public CContextBase2\r
+{\r
+public:\r
+  void Update(const Byte *data, size_t size);\r
+  void UpdateRar(Byte *data, size_t size, bool rar350Mode);\r
+  void Final(Byte *digest);\r
+};\r
+\r
+class CContext32: public CContextBase2\r
+{\r
+public:\r
+  void Update(const UInt32 *data, size_t size);\r
+  void Final(UInt32 *digest);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Crypto/StdAfx.h b/CPP/7zip/Crypto/StdAfx.h
new file mode 100755 (executable)
index 0000000..c28ffce
--- /dev/null
@@ -0,0 +1,8 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../Common/MyWindows.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/Crypto/WzAes.cpp b/CPP/7zip/Crypto/WzAes.cpp
new file mode 100755 (executable)
index 0000000..7a037d9
--- /dev/null
@@ -0,0 +1,221 @@
+// Crypto/WzAes.cpp\r
+/*\r
+This code implements Brian Gladman's scheme\r
+specified in password Based File Encryption Utility.\r
+\r
+Note: you must include MyAes.cpp to project to initialize AES tables\r
+*/\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../Common/StreamObjects.h"\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "Pbkdf2HmacSha1.h"\r
+#include "RandGen.h"\r
+#include "WzAes.h"\r
+\r
+// define it if you don't want to use speed-optimized version of Pbkdf2HmacSha1\r
+// #define _NO_WZAES_OPTIMIZATIONS\r
+\r
+namespace NCrypto {\r
+namespace NWzAes {\r
+\r
+const unsigned kAesKeySizeMax = 32;\r
+\r
+static const UInt32 kNumKeyGenIterations = 1000;\r
+\r
+STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)\r
+{\r
+  if(size > kPasswordSizeMax)\r
+    return E_INVALIDARG;\r
+  _key.Password.SetCapacity(size);\r
+  memcpy(_key.Password, data, size);\r
+  return S_OK;\r
+}\r
+\r
+#ifndef _NO_WZAES_OPTIMIZATIONS\r
+\r
+static void BytesToBeUInt32s(const Byte *src, UInt32 *dest, unsigned destSize)\r
+{\r
+  for (unsigned i = 0; i < destSize; i++)\r
+      dest[i] =\r
+          ((UInt32)(src[i * 4 + 0]) << 24) |\r
+          ((UInt32)(src[i * 4 + 1]) << 16) |\r
+          ((UInt32)(src[i * 4 + 2]) <<  8) |\r
+          ((UInt32)(src[i * 4 + 3]));\r
+}\r
+\r
+#endif\r
+\r
+STDMETHODIMP CBaseCoder::Init()\r
+{\r
+  UInt32 keySize = _key.GetKeySize();\r
+  UInt32 keysTotalSize = 2 * keySize + kPwdVerifCodeSize;\r
+  Byte buf[2 * kAesKeySizeMax + kPwdVerifCodeSize];\r
+  \r
+  // for (unsigned ii = 0; ii < 1000; ii++)\r
+  {\r
+    #ifdef _NO_WZAES_OPTIMIZATIONS\r
+\r
+    NSha1::Pbkdf2Hmac(\r
+      _key.Password, _key.Password.GetCapacity(),\r
+      _key.Salt, _key.GetSaltSize(),\r
+      kNumKeyGenIterations,\r
+      buf, keysTotalSize);\r
+\r
+    #else\r
+\r
+    UInt32 buf32[(2 * kAesKeySizeMax + kPwdVerifCodeSize + 3) / 4];\r
+    UInt32 key32SizeTotal = (keysTotalSize + 3) / 4;\r
+    UInt32 salt[kSaltSizeMax * 4];\r
+    UInt32 saltSizeInWords = _key.GetSaltSize() / 4;\r
+    BytesToBeUInt32s(_key.Salt, salt, saltSizeInWords);\r
+    NSha1::Pbkdf2Hmac32(\r
+      _key.Password, _key.Password.GetCapacity(),\r
+      salt, saltSizeInWords,\r
+      kNumKeyGenIterations,\r
+      buf32, key32SizeTotal);\r
+    for (UInt32 j = 0; j < keysTotalSize; j++)\r
+      buf[j] = (Byte)(buf32[j / 4] >> (24 - 8 * (j & 3)));\r
+    \r
+    #endif\r
+  }\r
+\r
+  _hmac.SetKey(buf + keySize, keySize);\r
+  memcpy(_key.PwdVerifComputed, buf + 2 * keySize, kPwdVerifCodeSize);\r
+\r
+  AesCtr2_Init(&_aes);\r
+  Aes_SetKey_Enc(_aes.aes + _aes.offset + 8, buf, keySize);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CEncoder::WriteHeader(ISequentialOutStream *outStream)\r
+{\r
+  UInt32 saltSize = _key.GetSaltSize();\r
+  g_RandomGenerator.Generate(_key.Salt, saltSize);\r
+  Init();\r
+  RINOK(WriteStream(outStream, _key.Salt, saltSize));\r
+  return WriteStream(outStream, _key.PwdVerifComputed, kPwdVerifCodeSize);\r
+}\r
+\r
+HRESULT CEncoder::WriteFooter(ISequentialOutStream *outStream)\r
+{\r
+  Byte mac[kMacSize];\r
+  _hmac.Final(mac, kMacSize);\r
+  return WriteStream(outStream, mac, kMacSize);\r
+}\r
+\r
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)\r
+{\r
+  if (size != 1)\r
+    return E_INVALIDARG;\r
+  _key.Init();\r
+  return SetKeyMode(data[0]) ? S_OK : E_INVALIDARG;\r
+}\r
+\r
+HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream)\r
+{\r
+  UInt32 saltSize = _key.GetSaltSize();\r
+  UInt32 extraSize = saltSize + kPwdVerifCodeSize;\r
+  Byte temp[kSaltSizeMax + kPwdVerifCodeSize];\r
+  RINOK(ReadStream_FAIL(inStream, temp, extraSize));\r
+  UInt32 i;\r
+  for (i = 0; i < saltSize; i++)\r
+    _key.Salt[i] = temp[i];\r
+  for (i = 0; i < kPwdVerifCodeSize; i++)\r
+    _pwdVerifFromArchive[i] = temp[saltSize + i];\r
+  return S_OK;\r
+}\r
+\r
+static bool CompareArrays(const Byte *p1, const Byte *p2, UInt32 size)\r
+{\r
+  for (UInt32 i = 0; i < size; i++)\r
+    if (p1[i] != p2[i])\r
+      return false;\r
+  return true;\r
+}\r
+\r
+bool CDecoder::CheckPasswordVerifyCode()\r
+{\r
+  return CompareArrays(_key.PwdVerifComputed, _pwdVerifFromArchive, kPwdVerifCodeSize);\r
+}\r
+\r
+HRESULT CDecoder::CheckMac(ISequentialInStream *inStream, bool &isOK)\r
+{\r
+  isOK = false;\r
+  Byte mac1[kMacSize];\r
+  RINOK(ReadStream_FAIL(inStream, mac1, kMacSize));\r
+  Byte mac2[kMacSize];\r
+  _hmac.Final(mac2, kMacSize);\r
+  isOK = CompareArrays(mac1, mac2, kMacSize);\r
+  return S_OK;\r
+}\r
+\r
+CAesCtr2::CAesCtr2()\r
+{\r
+  offset = ((0 - (unsigned)(ptrdiff_t)aes) & 0xF) / sizeof(UInt32);\r
+}\r
+\r
+void AesCtr2_Init(CAesCtr2 *p)\r
+{\r
+  UInt32 *ctr = p->aes + p->offset + 4;\r
+  unsigned i;\r
+  for (i = 0; i < 4; i++)\r
+    ctr[i] = 0;\r
+  p->pos = AES_BLOCK_SIZE;\r
+}\r
+\r
+void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size)\r
+{\r
+  unsigned pos = p->pos;\r
+  UInt32 *buf32 = p->aes + p->offset;\r
+  if (size == 0)\r
+    return;\r
+  if (pos != AES_BLOCK_SIZE)\r
+  {\r
+    const Byte *buf = (const Byte *)buf32;\r
+    do\r
+      *data++ ^= buf[pos++];\r
+    while (--size != 0 && pos != AES_BLOCK_SIZE);\r
+  }\r
+  if (size >= 16)\r
+  {\r
+    SizeT size2 = size >> 4;\r
+    g_AesCtr_Code(buf32 + 4, data, size2);\r
+    size2 <<= 4;\r
+    data += size2;\r
+    size -= size2;\r
+    pos = AES_BLOCK_SIZE;\r
+  }\r
+  if (size != 0)\r
+  {\r
+    unsigned j;\r
+    const Byte *buf;\r
+    for (j = 0; j < 4; j++)\r
+      buf32[j] = 0;\r
+    g_AesCtr_Code(buf32 + 4, (Byte *)buf32, 1);\r
+    buf = (const Byte *)buf32;\r
+    pos = 0;\r
+    do\r
+      *data++ ^= buf[pos++];\r
+    while (--size != 0 && pos != AES_BLOCK_SIZE);\r
+  }\r
+  p->pos = pos;\r
+}\r
+\r
+STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size)\r
+{\r
+  AesCtr2_Code(&_aes, data, size);\r
+  _hmac.Update(data, size);\r
+  return size;\r
+}\r
+\r
+STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)\r
+{\r
+  _hmac.Update(data, size);\r
+  AesCtr2_Code(&_aes, data, size);\r
+  return size;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Crypto/WzAes.h b/CPP/7zip/Crypto/WzAes.h
new file mode 100755 (executable)
index 0000000..c6672c6
--- /dev/null
@@ -0,0 +1,125 @@
+// Crypto/WzAes.h\r
+/*\r
+This code implements Brian Gladman's scheme\r
+specified in password Based File Encryption Utility:\r
+  - AES encryption (128,192,256-bit) in Counter (CTR) mode.\r
+  - HMAC-SHA1 authentication for encrypted data (10 bytes)\r
+  - Keys are derived by PPKDF2(RFC2898)-HMAC-SHA1 from ASCII password and\r
+    Salt (saltSize = aesKeySize / 2).\r
+  - 2 bytes contain Password Verifier's Code\r
+*/\r
+\r
+#ifndef __CRYPTO_WZ_AES_H\r
+#define __CRYPTO_WZ_AES_H\r
+\r
+#include "../../../C/Aes.h"\r
+\r
+#include "Common/Buffer.h"\r
+#include "Common/MyCom.h"\r
+#include "Common/MyVector.h"\r
+\r
+#include "../ICoder.h"\r
+#include "../IPassword.h"\r
+\r
+#include "HmacSha1.h"\r
+\r
+namespace NCrypto {\r
+namespace NWzAes {\r
+\r
+const unsigned kSaltSizeMax = 16;\r
+const unsigned kMacSize = 10;\r
+\r
+const UInt32 kPasswordSizeMax = 99; // 128;\r
+\r
+// Password Verification Code Size\r
+const unsigned kPwdVerifCodeSize = 2;\r
+\r
+enum EKeySizeMode\r
+{\r
+  kKeySizeMode_AES128 = 1,\r
+  kKeySizeMode_AES192 = 2,\r
+  kKeySizeMode_AES256 = 3\r
+};\r
+\r
+class CKeyInfo\r
+{\r
+public:\r
+  EKeySizeMode KeySizeMode;\r
+  Byte Salt[kSaltSizeMax];\r
+  Byte PwdVerifComputed[kPwdVerifCodeSize];\r
+\r
+  CByteBuffer Password;\r
+\r
+  UInt32 GetKeySize() const  { return (8 * (KeySizeMode & 3) + 8); }\r
+  UInt32 GetSaltSize() const { return (4 * (KeySizeMode & 3) + 4); }\r
+\r
+  CKeyInfo() { Init(); }\r
+  void Init() { KeySizeMode = kKeySizeMode_AES256; }\r
+};\r
+\r
+struct CAesCtr2\r
+{\r
+  unsigned pos;\r
+  unsigned offset;\r
+  UInt32 aes[4 + AES_NUM_IVMRK_WORDS + 3];\r
+  CAesCtr2();\r
+};\r
+\r
+void AesCtr2_Init(CAesCtr2 *p);\r
+void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size);\r
+\r
+class CBaseCoder:\r
+  public ICompressFilter,\r
+  public ICryptoSetPassword,\r
+  public CMyUnknownImp\r
+{\r
+protected:\r
+  CKeyInfo _key;\r
+  NSha1::CHmac _hmac;\r
+  Byte _pwdVerifFromArchive[kPwdVerifCodeSize];\r
+  CAesCtr2 _aes;\r
+\r
+public:\r
+  STDMETHOD(Init)();\r
+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) = 0;\r
+  \r
+  STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);\r
+\r
+  UInt32 GetHeaderSize() const { return _key.GetSaltSize() + kPwdVerifCodeSize; }\r
+  bool SetKeyMode(unsigned mode)\r
+  {\r
+    if (mode < kKeySizeMode_AES128 || mode > kKeySizeMode_AES256)\r
+      return false;\r
+    _key.KeySizeMode = (EKeySizeMode)mode;\r
+    return true;\r
+  }\r
+};\r
+\r
+class CEncoder:\r
+  public CBaseCoder\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP1(ICryptoSetPassword)\r
+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);\r
+  HRESULT WriteHeader(ISequentialOutStream *outStream);\r
+  HRESULT WriteFooter(ISequentialOutStream *outStream);\r
+};\r
+\r
+class CDecoder:\r
+  public CBaseCoder,\r
+  public ICompressSetDecoderProperties2\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP2(\r
+      ICryptoSetPassword,\r
+      ICompressSetDecoderProperties2)\r
+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);\r
+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);\r
+  HRESULT ReadHeader(ISequentialInStream *inStream);\r
+  bool CheckPasswordVerifyCode();\r
+  HRESULT CheckMac(ISequentialInStream *inStream, bool &isOK);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Crypto/ZipCrypto.cpp b/CPP/7zip/Crypto/ZipCrypto.cpp
new file mode 100755 (executable)
index 0000000..13f7f06
--- /dev/null
@@ -0,0 +1,88 @@
+// Crypto/ZipCrypto.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/7zCrc.h"\r
+\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "RandGen.h"\r
+#include "ZipCrypto.h"\r
+\r
+namespace NCrypto {\r
+namespace NZip {\r
+\r
+void CCipher::UpdateKeys(Byte b)\r
+{\r
+  Keys[0] = CRC_UPDATE_BYTE(Keys[0], b);\r
+  Keys[1] = (Keys[1] + (Keys[0] & 0xFF)) * 0x8088405 + 1;\r
+  Keys[2] = CRC_UPDATE_BYTE(Keys[2], (Byte)(Keys[1] >> 24));\r
+}\r
+\r
+STDMETHODIMP CCipher::CryptoSetPassword(const Byte *password, UInt32 passwordLen)\r
+{\r
+  Keys[0] = 0x12345678;\r
+  Keys[1] = 0x23456789;\r
+  Keys[2] = 0x34567890;\r
+  UInt32 i;\r
+  for (i = 0; i < passwordLen; i++)\r
+    UpdateKeys(password[i]);\r
+  for (i = 0; i < 3; i++)\r
+    Keys2[i] = Keys[i];\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CCipher::Init()\r
+{\r
+  return S_OK;\r
+}\r
+\r
+Byte CCipher::DecryptByteSpec()\r
+{\r
+  UInt32 temp = Keys[2] | 2;\r
+  return (Byte)((temp * (temp ^ 1)) >> 8);\r
+}\r
+\r
+HRESULT CEncoder::WriteHeader(ISequentialOutStream *outStream, UInt32 crc)\r
+{\r
+  Byte h[kHeaderSize];\r
+  g_RandomGenerator.Generate(h, kHeaderSize - 2);\r
+  h[kHeaderSize - 1] = (Byte)(crc >> 24);\r
+  h[kHeaderSize - 2] = (Byte)(crc >> 16);\r
+  RestoreKeys();\r
+  Filter(h, kHeaderSize);\r
+  return WriteStream(outStream, h, kHeaderSize);\r
+}\r
+\r
+STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size)\r
+{\r
+  for (UInt32 i = 0; i < size; i++)\r
+  {\r
+    Byte b = data[i];\r
+    data[i] = (Byte)(b ^ DecryptByteSpec());;\r
+    UpdateKeys(b);\r
+  }\r
+  return size;\r
+}\r
+\r
+HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream)\r
+{\r
+  Byte h[kHeaderSize];\r
+  RINOK(ReadStream_FAIL(inStream, h, kHeaderSize));\r
+  RestoreKeys();\r
+  Filter(h, kHeaderSize);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)\r
+{\r
+  for (UInt32 i = 0; i < size; i++)\r
+  {\r
+    Byte c = (Byte)(data[i] ^ DecryptByteSpec());\r
+    UpdateKeys(c);\r
+    data[i] = c;\r
+  }\r
+  return size;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Crypto/ZipCrypto.h b/CPP/7zip/Crypto/ZipCrypto.h
new file mode 100755 (executable)
index 0000000..16a2515
--- /dev/null
@@ -0,0 +1,56 @@
+// Crypto/ZipCrypto.h\r
+\r
+#ifndef __CRYPTO_ZIP_CRYPTO_H\r
+#define __CRYPTO_ZIP_CRYPTO_H\r
+\r
+#include "Common/MyCom.h"\r
+\r
+#include "../ICoder.h"\r
+#include "../IPassword.h"\r
+\r
+namespace NCrypto {\r
+namespace NZip {\r
+\r
+const unsigned kHeaderSize = 12;\r
+\r
+class CCipher:\r
+  public ICompressFilter,\r
+  public ICryptoSetPassword,\r
+  public CMyUnknownImp\r
+{\r
+  UInt32 Keys[3];\r
+  UInt32 Keys2[3];\r
+\r
+protected:\r
+  void UpdateKeys(Byte b);\r
+  Byte DecryptByteSpec();\r
+  void RestoreKeys()\r
+  {\r
+    for (int i = 0; i < 3; i++)\r
+      Keys[i] = Keys2[i];\r
+  }\r
+\r
+public:\r
+  STDMETHOD(Init)();\r
+  STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);\r
+};\r
+\r
+class CEncoder: public CCipher\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP1(ICryptoSetPassword)\r
+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);\r
+  HRESULT WriteHeader(ISequentialOutStream *outStream, UInt32 crc);\r
+};\r
+\r
+class CDecoder: public CCipher\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP1(ICryptoSetPassword)\r
+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);\r
+  HRESULT ReadHeader(ISequentialInStream *inStream);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/Crypto/ZipStrong.cpp b/CPP/7zip/Crypto/ZipStrong.cpp
new file mode 100755 (executable)
index 0000000..c9b370e
--- /dev/null
@@ -0,0 +1,164 @@
+// Crypto/ZipStrong.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../C/7zCrc.h"\r
+#include "../../../C/CpuArch.h"\r
+\r
+#include "../Common/StreamUtils.h"\r
+\r
+#include "MyAes.h"\r
+#include "Sha1.h"\r
+#include "ZipStrong.h"\r
+\r
+namespace NCrypto {\r
+namespace NZipStrong {\r
+\r
+static const UInt16 kAES128 = 0x660E;\r
+\r
+// DeriveKey* function is similar to CryptDeriveKey() from Windows.\r
+// But MSDN tells that we need such scheme only if\r
+// "the required key length is longer than the hash value"\r
+// but ZipStrong uses it always.\r
+\r
+static void DeriveKey2(const Byte *digest, Byte c, Byte *dest)\r
+{\r
+  Byte buf[64];\r
+  memset(buf, c, 64);\r
+  for (unsigned i = 0; i < NSha1::kDigestSize; i++)\r
+    buf[i] ^= digest[i];\r
+  NSha1::CContext sha;\r
+  sha.Init();\r
+  sha.Update(buf, 64);\r
+  sha.Final(dest);\r
+}\r
\r
+static void DeriveKey(NSha1::CContext &sha, Byte *key)\r
+{\r
+  Byte digest[NSha1::kDigestSize];\r
+  sha.Final(digest);\r
+  Byte temp[NSha1::kDigestSize * 2];\r
+  DeriveKey2(digest, 0x36, temp);\r
+  DeriveKey2(digest, 0x5C, temp + NSha1::kDigestSize);\r
+  memcpy(key, temp, 32);\r
+}\r
+\r
+void CKeyInfo::SetPassword(const Byte *data, UInt32 size)\r
+{\r
+  NSha1::CContext sha;\r
+  sha.Init();\r
+  sha.Update(data, size);\r
+  DeriveKey(sha, MasterKey);\r
+}\r
+\r
+STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)\r
+{\r
+  _key.SetPassword(data, size);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream, UInt32 /* crc */, UInt64 /* unpackSize */)\r
+{\r
+  Byte temp[4];\r
+  RINOK(ReadStream_FALSE(inStream, temp, 2));\r
+  _ivSize = GetUi16(temp);\r
+  if (_ivSize == 0)\r
+  {\r
+    return E_NOTIMPL;\r
+    /*\r
+    SetUi32(_iv, crc);\r
+    for (int i = 0; i < 8; i++)\r
+     _iv[4 + i] = (Byte)(unpackSize >> (8 * i));\r
+    SetUi32(_iv + 12, 0);\r
+    */\r
+  }\r
+  else if (_ivSize == 16)\r
+  {\r
+    RINOK(ReadStream_FALSE(inStream, _iv, _ivSize));\r
+  }\r
+  else\r
+    return E_NOTIMPL;\r
+  RINOK(ReadStream_FALSE(inStream, temp, 4));\r
+  _remSize = GetUi32(temp);\r
+  const UInt32 kAlign = 16;\r
+  if (_remSize < 16 || _remSize > (1 << 18))\r
+    return E_NOTIMPL;\r
+  if (_remSize + kAlign > _buf.GetCapacity())\r
+  {\r
+    _buf.Free();\r
+    _buf.SetCapacity(_remSize + kAlign);\r
+    _bufAligned = (Byte *)((ptrdiff_t)((Byte *)_buf + kAlign - 1) & ~(ptrdiff_t)(kAlign - 1));\r
+  }\r
+  return ReadStream_FALSE(inStream, _bufAligned, _remSize);\r
+}\r
+\r
+HRESULT CDecoder::CheckPassword(bool &passwOK)\r
+{\r
+  passwOK = false;\r
+  if (_remSize < 16)\r
+    return E_NOTIMPL;\r
+  Byte *p = _bufAligned;\r
+  UInt16 format = GetUi16(p);\r
+  if (format != 3)\r
+    return E_NOTIMPL;\r
+  UInt16 algId = GetUi16(p + 2);\r
+  if (algId < kAES128)\r
+    return E_NOTIMPL;\r
+  algId -= kAES128;\r
+  if (algId > 2)\r
+    return E_NOTIMPL;\r
+  UInt16 bitLen = GetUi16(p + 4);\r
+  UInt16 flags = GetUi16(p + 6);\r
+  if (algId * 64 + 128 != bitLen)\r
+    return E_NOTIMPL;\r
+  _key.KeySize = 16 + algId * 8;\r
+  if ((flags & 1) == 0)\r
+    return E_NOTIMPL;\r
+  if ((flags & 0x4000) != 0)\r
+  {\r
+    // Use 3DES\r
+    return E_NOTIMPL;\r
+  }\r
+\r
+  UInt32 rdSize = GetUi16(p + 8);\r
+  if ((rdSize & 0xF) != 0 || rdSize + 16 > _remSize)\r
+    return E_NOTIMPL;\r
+  memmove(p, p + 10, rdSize);\r
+  Byte *validData = p + rdSize + 16;\r
+  if (GetUi32(validData - 6) != 0) // reserved\r
+    return E_NOTIMPL;\r
+  UInt32 validSize = GetUi16(validData - 2);\r
+  if ((validSize & 0xF) != 0 || 16 + rdSize + validSize != _remSize)\r
+    return E_NOTIMPL;\r
+\r
+\r
+  {\r
+    RINOK(SetKey(_key.MasterKey, _key.KeySize));\r
+    RINOK(SetInitVector(_iv, 16));\r
+    Init();\r
+    Filter(p, rdSize);\r
+  }\r
+\r
+  Byte fileKey[32];\r
+  NSha1::CContext sha;\r
+  sha.Init();\r
+  sha.Update(_iv, 16);\r
+  sha.Update(p, rdSize - 16); // we don't use last 16 bytes (PAD bytes)\r
+  DeriveKey(sha, fileKey);\r
+  \r
+  RINOK(SetKey(fileKey, _key.KeySize));\r
+  RINOK(SetInitVector(_iv, 16));\r
+  Init();\r
+  Filter(validData, validSize);\r
+\r
+  if (validSize < 4)\r
+    return E_NOTIMPL;\r
+  validSize -= 4;\r
+  if (GetUi32(validData + validSize) != CrcCalc(validData, validSize))\r
+    return S_OK;\r
+  passwOK = true;\r
+  Init();\r
+  return S_OK;\r
+}\r
+\r
+}}\r
diff --git a/CPP/7zip/Crypto/ZipStrong.h b/CPP/7zip/Crypto/ZipStrong.h
new file mode 100755 (executable)
index 0000000..f3f7d6d
--- /dev/null
@@ -0,0 +1,47 @@
+// Crypto/ZipStrong.h\r
+\r
+#ifndef __CRYPTO_ZIP_STRONG_H\r
+#define __CRYPTO_ZIP_STRONG_H\r
+\r
+#include "Common/Buffer.h"\r
+\r
+#include "../IPassword.h"\r
+\r
+#include "MyAes.h"\r
+\r
+namespace NCrypto {\r
+namespace NZipStrong {\r
+\r
+struct CKeyInfo\r
+{\r
+  Byte MasterKey[32];\r
+  UInt32 KeySize;\r
+  void SetPassword(const Byte *data, UInt32 size);\r
+};\r
+\r
+class CBaseCoder:\r
+  public CAesCbcDecoder,\r
+  public ICryptoSetPassword\r
+{\r
+protected:\r
+  CKeyInfo _key;\r
+  CByteBuffer _buf;\r
+  Byte *_bufAligned;\r
+public:\r
+  STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);\r
+};\r
+\r
+class CDecoder: public CBaseCoder\r
+{\r
+  UInt32 _ivSize;\r
+  Byte _iv[16];\r
+  UInt32 _remSize;\r
+public:\r
+  MY_UNKNOWN_IMP1(ICryptoSetPassword)\r
+  HRESULT ReadHeader(ISequentialInStream *inStream, UInt32 crc, UInt64 unpackSize);\r
+  HRESULT CheckPassword(bool &passwOK);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/7zip/GuiCommon.rc b/CPP/7zip/GuiCommon.rc
new file mode 100755 (executable)
index 0000000..5280b4b
--- /dev/null
@@ -0,0 +1,70 @@
+#include <winnt.h>\r
+#include <WinUser.h>\r
+#include <CommCtrl.h>\r
+\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r
+\r
+#undef m\r
+#undef bxs\r
+#undef bys\r
+#undef bxsDots\r
+#undef y\r
+#undef xc\r
+#undef yc\r
+#undef xs\r
+#undef ys\r
+#undef bx\r
+#undef bx1\r
+#undef bx2\r
+#undef bx3\r
+#undef by\r
+#undef by1\r
+#undef by2\r
+#undef by3\r
+#undef gSpace\r
+#undef gSize\r
+#undef marg2\r
+#undef marg3\r
+\r
+#define m 8\r
+#define bxs 64\r
+#define bys 16\r
+#define bxsDots 20\r
+\r
+#define xs (xc + m + m)\r
+#define ys (yc + m + m)\r
+\r
+#define bx1 (xs - m - bxs)\r
+#define bx2 (bx1 - m - bxs)\r
+#define bx3 (bx2 - m - bxs)\r
+#define bx bx1\r
+\r
+#define by1 (ys - m - bys)\r
+#define by2 (by1 - m - bys)\r
+#define by by1\r
+\r
+\r
+#define MY_MODAL_DIALOG_STYLE  STYLE  DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
+\r
+#define MY_MODAL_RESIZE_DIALOG_STYLE  MY_MODAL_DIALOG_STYLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX | WS_THICKFRAME\r
+\r
+#define MY_PAGE_STYLE  STYLE  WS_CHILD | WS_DISABLED | WS_CAPTION\r
+\r
+#define MY_FONT  FONT 8, "MS Shell Dlg"\r
+\r
+#define SMALL_PAGE_SIZE_X 120\r
+\r
+#define MY_DIALOG         DIALOG 0, 0, xs, ys  MY_MODAL_DIALOG_STYLE  MY_FONT\r
+#define MY_RESIZE_DIALOG  DIALOG 0, 0, xs, ys  MY_MODAL_RESIZE_DIALOG_STYLE  MY_FONT\r
+#define MY_PAGE           DIALOG 0, 0, xs, ys  MY_PAGE_STYLE  MY_FONT\r
+\r
+#define OK_CANCEL \\r
+  DEFPUSHBUTTON  "OK",     IDOK,     bx2, by, bxs, bys \\r
+  PUSHBUTTON     "Cancel", IDCANCEL, bx1, by, bxs, bys\r
+\r
+\r
+#define MY_COMBO  CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
+#define MY_COMBO_SORTED  MY_COMBO | CBS_SORT\r
+#define MY_COMBO_WITH_EDIT  CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP \r
+\r
+#define MY_CHECKBOX "Button", BS_AUTOCHECKBOX | WS_TABSTOP\r
diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt
new file mode 100755 (executable)
index 0000000..cbd45a4
--- /dev/null
@@ -0,0 +1,170 @@
+{23170F69-40C1-278A-0000-00yy00xx0000}\r
+\r
+00 IProgress.h\r
+\r
+  05  IProgress\r
+\r
+01 IFolderArchive.h\r
+\r
+  05  IArchiveFolder\r
+  // 06  IInFolderArchive // old\r
+  07  IFileExtractCallback.h::IFolderArchiveExtractCallback\r
+  0A  IOutFolderArchive\r
+  0B  IFolderArchiveUpdateCallback\r
+  0C  Agent.h::IArchiveFolderInternal\r
+  0D\r
+  0E  IInFolderArchive\r
+\r
+03 IStream.h\r
+\r
+  01  ISequentialInStream\r
+  02  ISequentialOutStream\r
+  03  IInStream\r
+  04  IOutStream\r
+  06  IStreamGetSize\r
+  07  IOutStreamFlush\r
+\r
+\r
+04 ICoder.h\r
+\r
+  04  ICompressProgressInfo\r
+  05  ICompressCoder\r
+  18  ICompressCoder2\r
+  20  ICompressSetCoderProperties\r
+  21  ICompressSetDecoderProperties //\r
+  22  ICompressSetDecoderProperties2\r
+  23  ICompressWriteCoderProperties\r
+  24  ICompressGetInStreamProcessedSize\r
+  25  ICompressSetCoderMt\r
+  30  ICompressGetSubStreamSize\r
+  31  ICompressSetInStream\r
+  32  ICompressSetOutStream\r
+  33  ICompressSetInStreamSize\r
+  34  ICompressSetOutStreamSize\r
+  35  ICompressSetBufSize\r
+  40  ICompressFilter\r
+  60  ICompressCodecsInfo\r
+  61  ISetCompressCodecsInfo\r
+  80  ICryptoProperties\r
+  88  ICryptoResetSalt\r
+  8C  ICryptoResetInitVector\r
+  90  ICryptoSetPassword\r
+  A0  ICryptoSetCRC\r
+\r
+\r
+05 IPassword.h\r
+\r
+  10 ICryptoGetTextPassword\r
+  11 ICryptoGetTextPassword2\r
+\r
+\r
+06 IArchive.h\r
+\r
+  03  ISetProperties\r
+\r
+  10  IArchiveOpenCallback\r
+  20  IArchiveExtractCallback\r
+  30  IArchiveOpenVolumeCallback\r
+  40  IInArchiveGetStream\r
+  50  IArchiveOpenSetSubArchiveName\r
+  60  IInArchive\r
+  61  IArchiveOpenSeq\r
+\r
+  80  IArchiveUpdateCallback\r
+  82  IArchiveUpdateCallback2\r
+  A0  IOutArchive\r
+\r
+\r
+\r
+08 IFolder.h\r
+\r
+  00 IFolderFolder\r
+  01 IEnumProperties\r
+  02 IFolderGetTypeID\r
+  03 IFolderGetPath\r
+  04 IFolderWasChanged\r
+  05 // IFolderReload\r
+  06 IFolderOperations\r
+  07 IFolderGetSystemIconIndex\r
+  08 IFolderGetItemFullSize\r
+  09 IFolderClone\r
+  0A IFolderSetFlatMode\r
+  0B IFolderOperationsExtractCallback\r
+  0C // \r
+  0D // \r
+  0E IFolderProperties\r
+  0F \r
+  10 IFolderArcProps\r
+  11 IGetFolderArcProps\r
+\r
+\r
+09 IFolder.h :: FOLDER_MANAGER_INTERFACE\r
+\r
+  00 - 04 // old IFolderManager\r
+  05 IFolderManager\r
+\r
+\r
+// 0A PluginInterface.h\r
+  00 IInitContextMenu\r
+  01 IPluginOptionsCallback\r
+  02 IPluginOptions\r
+\r
+\r
+Handler GUIDs:\r
+\r
+{23170F69-40C1-278A-1000-000110xx0000}\r
+\r
+  01 Zip\r
+  02 BZip2\r
+  03 Rar\r
+  04 Arj\r
+  05 Z\r
+  06 Lzh\r
+  07 7z\r
+  08 Cab\r
+  09 Nsis\r
+  0A lzma\r
+  0B lzma86\r
+  0C xz\r
+  0D ppmd\r
+\r
+  D2 SquashFS\r
+  D3 CramFS\r
+  D4 APM\r
+  D5 Mslz\r
+  D6 Flv\r
+  D7 Swf\r
+  D8 Swfc\r
+  D9 Ntfs\r
+  DA Fat\r
+  DB Mbr\r
+  DC Vhd\r
+  DD Pe\r
+  DE Elf\r
+  DF Mach-O\r
+  E0 Udf\r
+  E1 Xar\r
+  E2 Mub\r
+  E3 Hfs\r
+  E4 Dmg\r
+  E5 Compound\r
+  E6 Wim\r
+  E7 Iso\r
+  E8 Bkf\r
+  E9 Chm\r
+  EA Split\r
+  EB Rpm\r
+  EC Deb\r
+  ED Cpio\r
+  EE Tar\r
+  EF GZip\r
+\r
+{23170F69-40C1-278A-1000-000100030000} CAgentArchiveHandle\r
+{23170F69-40C1-278A-1000-000100020000} ContextMenu.h::CZipContextMenu\r
+\r
+{23170F69-40C1-278B- old codecs clsids\r
+\r
+{23170F69-40C1-278D-1000-000100020000} OptionsDialog.h::CLSID_CSevenZipOptions\r
+\r
+{23170F69-40C1-2790-id} Codec Decoders\r
+{23170F69-40C1-2791-id} Codec Encoders\r
diff --git a/CPP/7zip/ICoder.h b/CPP/7zip/ICoder.h
new file mode 100755 (executable)
index 0000000..cb74f98
--- /dev/null
@@ -0,0 +1,186 @@
+// ICoder.h\r
+\r
+#ifndef __ICODER_H\r
+#define __ICODER_H\r
+\r
+#include "IStream.h"\r
+\r
+#define CODER_INTERFACE(i, x) DECL_INTERFACE(i, 4, x)\r
+\r
+CODER_INTERFACE(ICompressProgressInfo, 0x04)\r
+{\r
+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressCoder, 0x05)\r
+{\r
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,\r
+      const UInt64 *inSize, const UInt64 *outSize,\r
+      ICompressProgressInfo *progress) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressCoder2, 0x18)\r
+{\r
+  STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,\r
+      ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,\r
+      ICompressProgressInfo *progress) PURE;\r
+};\r
+\r
+namespace NCoderPropID\r
+{\r
+  enum EEnum\r
+  {\r
+    kDefaultProp = 0,\r
+    kDictionarySize,\r
+    kUsedMemorySize,\r
+    kOrder,\r
+    kBlockSize,\r
+    kPosStateBits,\r
+    kLitContextBits,\r
+    kLitPosBits,\r
+    kNumFastBytes,\r
+    kMatchFinder,\r
+    kMatchFinderCycles,\r
+    kNumPasses,\r
+    kAlgorithm,\r
+    kNumThreads,\r
+    kEndMarker\r
+  };\r
+}\r
+\r
+CODER_INTERFACE(ICompressSetCoderProperties, 0x20)\r
+{\r
+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) PURE;\r
+};\r
+\r
+/*\r
+CODER_INTERFACE(ICompressSetCoderProperties, 0x21)\r
+{\r
+  STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE;\r
+};\r
+*/\r
+\r
+CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22)\r
+{\r
+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressWriteCoderProperties, 0x23)\r
+{\r
+  STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24)\r
+{\r
+  STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressSetCoderMt, 0x25)\r
+{\r
+  STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressGetSubStreamSize, 0x30)\r
+{\r
+  STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressSetInStream, 0x31)\r
+{\r
+  STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE;\r
+  STDMETHOD(ReleaseInStream)() PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressSetOutStream, 0x32)\r
+{\r
+  STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE;\r
+  STDMETHOD(ReleaseOutStream)() PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressSetInStreamSize, 0x33)\r
+{\r
+  STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressSetOutStreamSize, 0x34)\r
+{\r
+  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressSetBufSize, 0x35)\r
+{\r
+  STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size) PURE;\r
+  STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICompressFilter, 0x40)\r
+{\r
+  STDMETHOD(Init)() PURE;\r
+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE;\r
+  // Filter converts as most as possible bytes\r
+  // Filter return outSize (UInt32)\r
+  // if (outSize <= size): Filter have converted outSize bytes\r
+  // if (outSize > size): Filter have not converted anything.\r
+  //      and it needs at least outSize bytes to convert one block\r
+  //      (it's for crypto block algorithms).\r
+};\r
+\r
+CODER_INTERFACE(ICompressCodecsInfo, 0x60)\r
+{\r
+  STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods) PURE;\r
+  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE;\r
+  STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder) PURE;\r
+  STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder) PURE;\r
+};\r
+CODER_INTERFACE(ISetCompressCodecsInfo, 0x61)\r
+{\r
+  STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICryptoProperties, 0x80)\r
+{\r
+  STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE;\r
+  STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE;\r
+};\r
+\r
+/*\r
+CODER_INTERFACE(ICryptoResetSalt, 0x88)\r
+{\r
+  STDMETHOD(ResetSalt)() PURE;\r
+};\r
+*/\r
+\r
+CODER_INTERFACE(ICryptoResetInitVector, 0x8C)\r
+{\r
+  STDMETHOD(ResetInitVector)() PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICryptoSetPassword, 0x90)\r
+{\r
+  STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE;\r
+};\r
+\r
+CODER_INTERFACE(ICryptoSetCRC, 0xA0)\r
+{\r
+  STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE;\r
+};\r
+\r
+//////////////////////\r
+// It's for DLL file\r
+namespace NMethodPropID\r
+{\r
+  enum EEnum\r
+  {\r
+    kID,\r
+    kName,\r
+    kDecoder,\r
+    kEncoder,\r
+    kInStreams,\r
+    kOutStreams,\r
+    kDescription,\r
+    kDecoderIsAssigned,\r
+    kEncoderIsAssigned\r
+  };\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/IDecl.h b/CPP/7zip/IDecl.h
new file mode 100755 (executable)
index 0000000..768bbe7
--- /dev/null
@@ -0,0 +1,15 @@
+// IDecl.h\r
+\r
+#ifndef __IDECL_H\r
+#define __IDECL_H\r
+\r
+#include "../Common/MyUnknown.h"\r
+\r
+#define DECL_INTERFACE_SUB(i, base, groupId, subId) \\r
+DEFINE_GUID(IID_ ## i, \\r
+0x23170F69, 0x40C1, 0x278A, 0, 0, 0, (groupId), 0, (subId), 0, 0); \\r
+struct i: public base\r
+\r
+#define DECL_INTERFACE(i, groupId, subId) DECL_INTERFACE_SUB(i, IUnknown, groupId, subId)\r
+\r
+#endif\r
diff --git a/CPP/7zip/IPassword.h b/CPP/7zip/IPassword.h
new file mode 100755 (executable)
index 0000000..5679d84
--- /dev/null
@@ -0,0 +1,24 @@
+// IPassword.h\r
+\r
+#ifndef __IPASSWORD_H\r
+#define __IPASSWORD_H\r
+\r
+#include "../Common/MyUnknown.h"\r
+#include "../Common/Types.h"\r
+\r
+#include "IDecl.h"\r
+\r
+#define PASSWORD_INTERFACE(i, x) DECL_INTERFACE(i, 5, x)\r
+\r
+PASSWORD_INTERFACE(ICryptoGetTextPassword, 0x10)\r
+{\r
+  STDMETHOD(CryptoGetTextPassword)(BSTR *password) PURE;\r
+};\r
+\r
+PASSWORD_INTERFACE(ICryptoGetTextPassword2, 0x11)\r
+{\r
+  STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password) PURE;\r
+};\r
+\r
+#endif\r
+\r
diff --git a/CPP/7zip/IProgress.h b/CPP/7zip/IProgress.h
new file mode 100755 (executable)
index 0000000..09486ba
--- /dev/null
@@ -0,0 +1,33 @@
+// Interface/IProgress.h\r
+\r
+#ifndef __IPROGRESS_H\r
+#define __IPROGRESS_H\r
+\r
+#include "../Common/MyUnknown.h"\r
+#include "../Common/Types.h"\r
+\r
+#include "IDecl.h"\r
+\r
+#define INTERFACE_IProgress(x) \\r
+  STDMETHOD(SetTotal)(UInt64 total) x; \\r
+  STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \\r
+\r
+DECL_INTERFACE(IProgress, 0, 5)\r
+{\r
+  INTERFACE_IProgress(PURE)\r
+};\r
+\r
+/*\r
+// {23170F69-40C1-278A-0000-000000050002}\r
+DEFINE_GUID(IID_IProgress2,\r
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02);\r
+MIDL_INTERFACE("23170F69-40C1-278A-0000-000000050002")\r
+IProgress2: public IUnknown\r
+{\r
+public:\r
+  STDMETHOD(SetTotal)(const UInt64 *total) PURE;\r
+  STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE;\r
+};\r
+*/\r
+\r
+#endif\r
diff --git a/CPP/7zip/IStream.h b/CPP/7zip/IStream.h
new file mode 100755 (executable)
index 0000000..89f02f5
--- /dev/null
@@ -0,0 +1,58 @@
+// IStream.h\r
+\r
+#ifndef __ISTREAM_H\r
+#define __ISTREAM_H\r
+\r
+#include "../Common/MyUnknown.h"\r
+#include "../Common/Types.h"\r
+\r
+#include "IDecl.h"\r
+\r
+#define STREAM_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 3, x)\r
+#define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x)\r
+\r
+STREAM_INTERFACE(ISequentialInStream, 0x01)\r
+{\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE;\r
+  /*\r
+  Out: if size != 0, return_value = S_OK and (*processedSize == 0),\r
+    then there are no more bytes in stream.\r
+  if (size > 0) && there are bytes in stream,\r
+  this function must read at least 1 byte.\r
+  This function is allowed to read less than number of remaining bytes in stream.\r
+  You must call Read function in loop, if you need exact amount of data\r
+  */\r
+};\r
+\r
+STREAM_INTERFACE(ISequentialOutStream, 0x02)\r
+{\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE;\r
+  /*\r
+  if (size > 0) this function must write at least 1 byte.\r
+  This function is allowed to write less than "size".\r
+  You must call Write function in loop, if you need to write exact amount of data\r
+  */\r
+};\r
+\r
+STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03)\r
+{\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;\r
+};\r
+\r
+STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04)\r
+{\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;\r
+  STDMETHOD(SetSize)(UInt64 newSize) PURE;\r
+};\r
+\r
+STREAM_INTERFACE(IStreamGetSize, 0x06)\r
+{\r
+  STDMETHOD(GetSize)(UInt64 *size) PURE;\r
+};\r
+\r
+STREAM_INTERFACE(IOutStreamFlush, 0x07)\r
+{\r
+  STDMETHOD(Flush)() PURE;\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/MyVersion.h b/CPP/7zip/MyVersion.h
new file mode 100755 (executable)
index 0000000..f549249
--- /dev/null
@@ -0,0 +1,8 @@
+#define MY_VER_MAJOR 9\r
+#define MY_VER_MINOR 20\r
+#define MY_VER_BUILD 0\r
+#define MY_VERSION "9.20"\r
+#define MY_7ZIP_VERSION "7-Zip 9.20"\r
+#define MY_DATE "2010-11-18"\r
+#define MY_COPYRIGHT "Copyright (c) 1999-2010 Igor Pavlov"\r
+#define MY_VERSION_COPYRIGHT_DATE MY_VERSION "  " MY_COPYRIGHT "  " MY_DATE\r
diff --git a/CPP/7zip/MyVersionInfo.rc b/CPP/7zip/MyVersionInfo.rc
new file mode 100755 (executable)
index 0000000..84e4ac3
--- /dev/null
@@ -0,0 +1,52 @@
+#define MY_VS_FFI_FILEFLAGSMASK  0x0000003FL\r
+#define MY_VOS_NT_WINDOWS32  0x00040004L\r
+#define MY_VOS_CE_WINDOWS32  0x00050004L\r
+\r
+#define MY_VFT_APP  0x00000001L\r
+#define MY_VFT_DLL  0x00000002L\r
+\r
+// #include <WinVer.h>\r
+#include "MyVersion.h"\r
+\r
+#define MY_VER MY_VER_MAJOR,MY_VER_MINOR,MY_VER_BUILD,0\r
+\r
+#ifdef DEBUG\r
+#define DBG_FL VS_FF_DEBUG\r
+#else\r
+#define DBG_FL 0\r
+#endif\r
+\r
+#define MY_VERSION_INFO(fileType, descr, intName, origName)  \\r
+LANGUAGE 9, 1 \\r
+1 VERSIONINFO \\r
+  FILEVERSION MY_VER \\r
+  PRODUCTVERSION MY_VER \\r
+  FILEFLAGSMASK MY_VS_FFI_FILEFLAGSMASK \\r
+  FILEFLAGS DBG_FL \\r
+  FILEOS MY_VOS_NT_WINDOWS32 \\r
+  FILETYPE fileType \\r
+  FILESUBTYPE 0x0L \\r
+BEGIN \\r
+    BLOCK "StringFileInfo" \\r
+    BEGIN  \\r
+        BLOCK "040904b0" \\r
+        BEGIN \\r
+            VALUE "CompanyName", "Igor Pavlov" \\r
+            VALUE "FileDescription", descr \\r
+            VALUE "FileVersion", MY_VERSION  \\r
+            VALUE "InternalName", intName \\r
+            VALUE "LegalCopyright", MY_COPYRIGHT \\r
+            VALUE "OriginalFilename", origName \\r
+            VALUE "ProductName", "7-Zip" \\r
+            VALUE "ProductVersion", MY_VERSION \\r
+        END \\r
+    END \\r
+    BLOCK "VarFileInfo" \\r
+    BEGIN \\r
+        VALUE "Translation", 0x409, 1200 \\r
+    END \\r
+END\r
+\r
+#define MY_VERSION_INFO_APP(descr, intName) MY_VERSION_INFO(MY_VFT_APP, descr, intName, intName ".exe")\r
+\r
+#define MY_VERSION_INFO_DLL(descr, intName) MY_VERSION_INFO(MY_VFT_DLL, descr, intName, intName ".dll")\r
diff --git a/CPP/7zip/PropID.h b/CPP/7zip/PropID.h
new file mode 100755 (executable)
index 0000000..1aabc65
--- /dev/null
@@ -0,0 +1,76 @@
+// PropID.h\r
+\r
+#ifndef __7ZIP_PROPID_H\r
+#define __7ZIP_PROPID_H\r
+\r
+enum\r
+{\r
+  kpidNoProperty = 0,\r
+  kpidMainSubfile = 1,\r
+  kpidHandlerItemIndex = 2,\r
+  kpidPath,\r
+  kpidName,\r
+  kpidExtension,\r
+  kpidIsDir,\r
+  kpidSize,\r
+  kpidPackSize,\r
+  kpidAttrib,\r
+  kpidCTime,\r
+  kpidATime,\r
+  kpidMTime,\r
+  kpidSolid,\r
+  kpidCommented,\r
+  kpidEncrypted,\r
+  kpidSplitBefore,\r
+  kpidSplitAfter,\r
+  kpidDictionarySize,\r
+  kpidCRC,\r
+  kpidType,\r
+  kpidIsAnti,\r
+  kpidMethod,\r
+  kpidHostOS,\r
+  kpidFileSystem,\r
+  kpidUser,\r
+  kpidGroup,\r
+  kpidBlock,\r
+  kpidComment,\r
+  kpidPosition,\r
+  kpidPrefix,\r
+  kpidNumSubDirs,\r
+  kpidNumSubFiles,\r
+  kpidUnpackVer,\r
+  kpidVolume,\r
+  kpidIsVolume,\r
+  kpidOffset,\r
+  kpidLinks,\r
+  kpidNumBlocks,\r
+  kpidNumVolumes,\r
+  kpidTimeType,\r
+  kpidBit64,\r
+  kpidBigEndian,\r
+  kpidCpu,\r
+  kpidPhySize,\r
+  kpidHeadersSize,\r
+  kpidChecksum,\r
+  kpidCharacts,\r
+  kpidVa,\r
+  kpidId,\r
+  kpidShortName,\r
+  kpidCreatorApp,\r
+  kpidSectorSize,\r
+  kpidPosixAttrib,\r
+  kpidLink,\r
+  kpidError,\r
+\r
+  kpidTotalSize = 0x1100,\r
+  kpidFreeSpace,\r
+  kpidClusterSize,\r
+  kpidVolumeName,\r
+\r
+  kpidLocalName = 0x1200,\r
+  kpidProvider,\r
+\r
+  kpidUserDefined = 0x10000\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/SubBuild.mak b/CPP/7zip/SubBuild.mak
new file mode 100755 (executable)
index 0000000..0c49d3b
--- /dev/null
@@ -0,0 +1,3 @@
+       cd $(@D)\r
+       $(MAKE) -nologo $(TARGETS)\r
+       cd ..\r
diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp
new file mode 100755 (executable)
index 0000000..acbedcb
--- /dev/null
@@ -0,0 +1,645 @@
+// Agent.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/Sort.h"\r
+\r
+#include "Common/ComTry.h"\r
+\r
+#include "../Common/ArchiveExtractCallback.h"\r
+\r
+#include "Agent.h"\r
+\r
+using namespace NWindows;\r
+\r
+STDMETHODIMP CAgentFolder::GetAgentFolder(CAgentFolder **agentFolder)\r
+{\r
+  *agentFolder = this;\r
+  return S_OK;\r
+}\r
+\r
+void CAgentFolder::LoadFolder(CProxyFolder *folder)\r
+{\r
+  int i;\r
+  CProxyItem item;\r
+  item.Folder = folder;\r
+  for (i = 0; i < folder->Folders.Size(); i++)\r
+  {\r
+    item.Index = i;\r
+    _items.Add(item);\r
+    LoadFolder(&folder->Folders[i]);\r
+  }\r
+  int start = folder->Folders.Size();\r
+  for (i = 0; i < folder->Files.Size(); i++)\r
+  {\r
+    item.Index = start + i;\r
+    _items.Add(item);\r
+  }\r
+}\r
+\r
+STDMETHODIMP CAgentFolder::LoadItems()\r
+{\r
+  if (!_agentSpec->_archiveLink.IsOpen)\r
+    return E_FAIL;\r
+  _items.Clear();\r
+  if (_flatMode)\r
+    LoadFolder(_proxyFolderItem);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CAgentFolder::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  if (_flatMode)\r
+    *numItems = _items.Size();\r
+  else\r
+    *numItems = _proxyFolderItem->Folders.Size() +_proxyFolderItem->Files.Size();\r
+  return S_OK;\r
+}\r
+\r
+UString CAgentFolder::GetName(UInt32 index) const\r
+{\r
+  UInt32 realIndex;\r
+  const CProxyFolder *folder;\r
+  if (_flatMode)\r
+  {\r
+    const CProxyItem &item = _items[index];\r
+    folder = item.Folder;\r
+    realIndex = item.Index;\r
+  }\r
+  else\r
+  {\r
+    folder = _proxyFolderItem;\r
+    realIndex = index;\r
+  }\r
+\r
+  if (realIndex < (UInt32)folder->Folders.Size())\r
+    return folder->Folders[realIndex].Name;\r
+  return folder->Files[realIndex - folder->Folders.Size()].Name;\r
+}\r
+\r
+UString CAgentFolder::GetPrefix(UInt32 index) const\r
+{\r
+  if (!_flatMode)\r
+    return UString();\r
+  const CProxyItem &item = _items[index];\r
+  const CProxyFolder *folder = item.Folder;\r
+  UString path;\r
+  while (folder != _proxyFolderItem)\r
+  {\r
+    path = folder->Name + UString(WCHAR_PATH_SEPARATOR) + path;\r
+    folder = folder->Parent;\r
+  }\r
+  return path;\r
+}\r
+\r
+UString CAgentFolder::GetFullPathPrefixPlusPrefix(UInt32 index) const\r
+{\r
+  return _proxyFolderItem->GetFullPathPrefix() + GetPrefix(index);\r
+}\r
+\r
+void CAgentFolder::GetPrefixIfAny(UInt32 index, NCOM::CPropVariant &prop) const\r
+{\r
+  if (!_flatMode)\r
+    return;\r
+  prop = GetPrefix(index);\r
+}\r
+\r
+\r
+STDMETHODIMP CAgentFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  const CProxyFolder *folder;\r
+  UInt32 realIndex;\r
+  if (_flatMode)\r
+  {\r
+    const CProxyItem &item = _items[itemIndex];\r
+    folder = item.Folder;\r
+    realIndex = item.Index;\r
+  }\r
+  else\r
+  {\r
+    folder = _proxyFolderItem;\r
+    realIndex = itemIndex;\r
+  }\r
+\r
+  if (realIndex < (UInt32)folder->Folders.Size())\r
+  {\r
+    const CProxyFolder &item = folder->Folders[realIndex];\r
+    if (!_flatMode && propID == kpidSize)\r
+      prop = item.Size;\r
+    else if (!_flatMode && propID == kpidPackSize)\r
+      prop = item.PackSize;\r
+    else\r
+    switch(propID)\r
+    {\r
+      case kpidIsDir:      prop = true; break;\r
+      case kpidNumSubDirs: prop = item.NumSubFolders; break;\r
+      case kpidNumSubFiles:   prop = item.NumSubFiles; break;\r
+      case kpidName:          prop = item.Name; break;\r
+      case kpidCRC:\r
+      {\r
+        if (item.IsLeaf)\r
+        {\r
+          RINOK(_agentSpec->GetArchive()->GetProperty(item.Index, propID, value));\r
+        }\r
+        if (item.CrcIsDefined && value->vt == VT_EMPTY)\r
+          prop = item.Crc;\r
+        break;\r
+      }\r
+      case kpidPrefix: GetPrefixIfAny(itemIndex, prop); break;\r
+\r
+      default:\r
+        if (item.IsLeaf)\r
+          return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value);\r
+    }\r
+  }\r
+  else\r
+  {\r
+    realIndex -= folder->Folders.Size();\r
+    const CProxyFile &item = folder->Files[realIndex];\r
+    switch(propID)\r
+    {\r
+      case kpidIsDir: prop = false; break;\r
+      case kpidName: prop = item.Name; break;\r
+      case kpidPrefix: GetPrefixIfAny(itemIndex, prop); break;\r
+      default:\r
+        return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value);\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CAgentFolder::BindToFolder(CProxyFolder *folder, IFolderFolder **resultFolder)\r
+{\r
+  CMyComPtr<IFolderFolder> parentFolder;\r
+  if (folder->Parent != _proxyFolderItem)\r
+  {\r
+    RINOK(BindToFolder(folder->Parent, &parentFolder));\r
+  }\r
+  else\r
+    parentFolder = this;\r
+  CAgentFolder *folderSpec = new CAgentFolder;\r
+  CMyComPtr<IFolderFolder> agentFolder = folderSpec;\r
+  folderSpec->Init(_proxyArchive, folder, parentFolder, _agentSpec);\r
+  *resultFolder = agentFolder.Detach();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CAgentFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder)\r
+{\r
+  COM_TRY_BEGIN\r
+\r
+  CProxyFolder *folder;\r
+  UInt32 realIndex;\r
+  if (_flatMode)\r
+  {\r
+    const CProxyItem &item = _items[index];\r
+    folder = item.Folder;\r
+    realIndex = item.Index;\r
+  }\r
+  else\r
+  {\r
+    folder = _proxyFolderItem;\r
+    realIndex = index;\r
+  }\r
+  if (realIndex >= (UInt32)folder->Folders.Size())\r
+    return E_INVALIDARG;\r
+  return BindToFolder(&folder->Folders[realIndex], resultFolder);\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CAgentFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder)\r
+{\r
+  COM_TRY_BEGIN\r
+  int index = _proxyFolderItem->FindDirSubItemIndex(name);\r
+  if (index < 0)\r
+    return E_INVALIDARG;\r
+  return BindToFolder(index, resultFolder);\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CAgentFolder::BindToParentFolder(IFolderFolder **resultFolder)\r
+{\r
+  COM_TRY_BEGIN\r
+  CMyComPtr<IFolderFolder> parentFolder = _parentFolder;\r
+  *resultFolder = parentFolder.Detach();\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CAgentFolder::GetStream(UInt32 index, ISequentialInStream **stream)\r
+{\r
+  CMyComPtr<IInArchiveGetStream> getStream;\r
+  _agentSpec->GetArchive()->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream);\r
+  if (!getStream)\r
+    return S_OK;\r
+\r
+  const CProxyFolder *folder;\r
+  UInt32 realIndex;\r
+  if (_flatMode)\r
+  {\r
+    const CProxyItem &item = _items[index];\r
+    folder = item.Folder;\r
+    realIndex = item.Index;\r
+  }\r
+  else\r
+  {\r
+    folder = _proxyFolderItem;\r
+    realIndex = index;\r
+  }\r
+\r
+  UInt32 indexInArchive;\r
+  if (realIndex < (UInt32)folder->Folders.Size())\r
+  {\r
+    const CProxyFolder &item = folder->Folders[realIndex];\r
+    if (!item.IsLeaf)\r
+      return S_OK;\r
+    indexInArchive = item.Index;\r
+  }\r
+  else\r
+    indexInArchive = folder->Files[realIndex - folder->Folders.Size()].Index;\r
+  return getStream->GetStream(indexInArchive, stream);\r
+}\r
+\r
+STATPROPSTG kProperties[] =\r
+{\r
+  { NULL, kpidNumSubDirs, VT_UI4},\r
+  { NULL, kpidNumSubFiles, VT_UI4},\r
+  { NULL, kpidPrefix, VT_BSTR}\r
+};\r
+\r
+static const UInt32 kNumProperties = sizeof(kProperties) / sizeof(kProperties[0]);\r
+\r
+struct CArchiveItemPropertyTemp\r
+{\r
+  UString Name;\r
+  PROPID ID;\r
+  VARTYPE Type;\r
+};\r
+\r
+STDMETHODIMP CAgentFolder::GetNumberOfProperties(UInt32 *numProps)\r
+{\r
+  COM_TRY_BEGIN\r
+  RINOK(_agentSpec->GetArchive()->GetNumberOfProperties(numProps));\r
+  *numProps += kNumProperties;\r
+  if (!_flatMode)\r
+    (*numProps)--;\r
+  if (!_agentSpec->_proxyArchive->ThereIsPathProp)\r
+    (*numProps)++;\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)\r
+{\r
+  COM_TRY_BEGIN\r
+  UInt32 numProps;\r
+  _agentSpec->GetArchive()->GetNumberOfProperties(&numProps);\r
+  if (!_agentSpec->_proxyArchive->ThereIsPathProp)\r
+  {\r
+    if (index == 0)\r
+    {\r
+      *propID = kpidName;\r
+      *varType = VT_BSTR;\r
+      *name = 0;\r
+      return S_OK;\r
+    }\r
+    index--;\r
+  }\r
+\r
+  if (index < numProps)\r
+  {\r
+    RINOK(_agentSpec->GetArchive()->GetPropertyInfo(index, name, propID, varType));\r
+    if (*propID == kpidPath)\r
+      *propID = kpidName;\r
+  }\r
+  else\r
+  {\r
+    const STATPROPSTG &srcItem = kProperties[index - numProps];\r
+    *propID = srcItem.propid;\r
+    *varType = srcItem.vt;\r
+    *name = 0;\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STATPROPSTG kFolderProps[] =\r
+{\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidNumSubDirs, VT_UI4},\r
+  { NULL, kpidNumSubFiles, VT_UI4},\r
+  { NULL, kpidCRC, VT_UI4}\r
+};\r
+\r
+static const UInt32 kNumFolderProps = sizeof(kFolderProps) / sizeof(kFolderProps[0]);\r
+\r
+STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidSize:         prop = _proxyFolderItem->Size; break;\r
+    case kpidPackSize:     prop = _proxyFolderItem->PackSize; break;\r
+    case kpidNumSubDirs:   prop = _proxyFolderItem->NumSubFolders; break;\r
+    case kpidNumSubFiles:  prop = _proxyFolderItem->NumSubFiles; break;\r
+    case kpidName:         prop = _proxyFolderItem->Name; break;\r
+    case kpidPath:         prop = _proxyFolderItem->GetFullPathPrefix(); break;\r
+    case kpidType: prop = UString(L"7-Zip.") + _agentSpec->ArchiveType; break;\r
+    case kpidCRC: if (_proxyFolderItem->CrcIsDefined) prop = _proxyFolderItem->Crc; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CAgentFolder::GetNumberOfFolderProperties(UInt32 *numProps)\r
+{\r
+  *numProps = kNumFolderProps;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CAgentFolder::GetFolderPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)\r
+{\r
+  // if (index < kNumFolderProps)\r
+  {\r
+    const STATPROPSTG &srcItem = kFolderProps[index];\r
+    *propID = srcItem.propid;\r
+    *varType = srcItem.vt;\r
+    *name = 0;\r
+    return S_OK;\r
+  }\r
+}\r
+\r
+STDMETHODIMP CAgentFolder::GetFolderArcProps(IFolderArcProps **object)\r
+{\r
+  CMyComPtr<IFolderArcProps> temp = _agentSpec;\r
+  *object = temp.Detach();\r
+  return S_OK;\r
+}\r
+\r
+#ifdef NEW_FOLDER_INTERFACE\r
+\r
+STDMETHODIMP CAgentFolder::SetFlatMode(Int32 flatMode)\r
+{\r
+  _flatMode = IntToBool(flatMode);\r
+  return S_OK;\r
+}\r
+\r
+#endif\r
+\r
+void CAgentFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const\r
+{\r
+  if (!_flatMode)\r
+  {\r
+    _proxyFolderItem->GetRealIndices(indices, numItems, realIndices);\r
+    return;\r
+  }\r
+  realIndices.Clear();\r
+  for(UInt32 i = 0; i < numItems; i++)\r
+  {\r
+    const CProxyItem &item = _items[indices[i]];\r
+    const CProxyFolder *folder = item.Folder;\r
+    UInt32 realIndex = item.Index;\r
+    if (realIndex < (UInt32)folder->Folders.Size())\r
+      continue;\r
+    realIndices.Add(folder->Files[realIndex - folder->Folders.Size()].Index);\r
+  }\r
+  HeapSort(&realIndices.Front(), realIndices.Size());\r
+}\r
+\r
+STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices,\r
+    UInt32 numItems,\r
+    NExtract::NPathMode::EEnum pathMode,\r
+    NExtract::NOverwriteMode::EEnum overwriteMode,\r
+    const wchar_t *path,\r
+    Int32 testMode,\r
+    IFolderArchiveExtractCallback *extractCallback2)\r
+{\r
+  COM_TRY_BEGIN\r
+  CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;\r
+  CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;\r
+  UStringVector pathParts;\r
+  CProxyFolder *currentProxyFolder = _proxyFolderItem;\r
+  while (currentProxyFolder->Parent)\r
+  {\r
+    pathParts.Insert(0, currentProxyFolder->Name);\r
+    currentProxyFolder = currentProxyFolder->Parent;\r
+  }\r
+  \r
+  /*\r
+  if (_flatMode)\r
+    pathMode = NExtract::NPathMode::kNoPathnames;\r
+  */\r
+\r
+  extractCallbackSpec->InitForMulti(false, pathMode, overwriteMode);\r
+\r
+  extractCallbackSpec->Init(NULL, &_agentSpec->GetArc(),\r
+      extractCallback2,\r
+      false, testMode ? true : false, false,\r
+      (path ? path : L""),\r
+      pathParts,\r
+      (UInt64)(Int64)-1);\r
+  CUIntVector realIndices;\r
+  GetRealIndices(indices, numItems, realIndices);\r
+  return _agentSpec->GetArchive()->Extract(&realIndices.Front(),\r
+      realIndices.Size(), testMode, extractCallback);\r
+  COM_TRY_END\r
+}\r
+\r
+/////////////////////////////////////////\r
+// CAgent\r
+\r
+CAgent::CAgent():\r
+  _proxyArchive(NULL),\r
+  _codecs(0)\r
+{\r
+}\r
+\r
+CAgent::~CAgent()\r
+{\r
+  if (_proxyArchive != NULL)\r
+    delete _proxyArchive;\r
+}\r
+\r
+STDMETHODIMP CAgent::Open(\r
+    IInStream *inStream,\r
+    const wchar_t *filePath,\r
+    const wchar_t *arcFormat,\r
+    BSTR *archiveType,\r
+    IArchiveOpenCallback *openArchiveCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  _archiveFilePath = filePath;\r
+  NFile::NFind::CFileInfoW fi;\r
+  if (!inStream)\r
+  {\r
+    if (!fi.Find(_archiveFilePath))\r
+      return ::GetLastError();\r
+    if (fi.IsDir())\r
+      return E_FAIL;\r
+  }\r
+  CArcInfoEx archiverInfo0, archiverInfo1;\r
+\r
+  _compressCodecsInfo.Release();\r
+  _codecs = new CCodecs;\r
+  _compressCodecsInfo = _codecs;\r
+  RINOK(_codecs->Load());\r
+\r
+  CIntVector formatIndices;\r
+  if (!_codecs->FindFormatForArchiveType(arcFormat, formatIndices))\r
+    return S_FALSE;\r
+\r
+  RINOK(_archiveLink.Open(_codecs, formatIndices, false, inStream, _archiveFilePath, openArchiveCallback));\r
+\r
+  CArc &arc = _archiveLink.Arcs.Back();\r
+  if (!inStream)\r
+  {\r
+    arc.MTimeDefined = !fi.IsDevice;\r
+    arc.MTime = fi.MTime;\r
+  }\r
+\r
+  ArchiveType = _codecs->Formats[arc.FormatIndex].Name;\r
+  if (archiveType == 0)\r
+    return S_OK;\r
+  return StringToBstr(ArchiveType, archiveType);\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CAgent::ReOpen(IArchiveOpenCallback *openArchiveCallback)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (_proxyArchive != NULL)\r
+  {\r
+    delete _proxyArchive;\r
+    _proxyArchive = NULL;\r
+  }\r
+  RINOK(_archiveLink.ReOpen(_codecs, _archiveFilePath, openArchiveCallback));\r
+  return ReadItems();\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CAgent::Close()\r
+{\r
+  COM_TRY_BEGIN\r
+  return _archiveLink.Close();\r
+  COM_TRY_END\r
+}\r
+\r
+/*\r
+STDMETHODIMP CAgent::EnumProperties(IEnumSTATPROPSTG **EnumProperties)\r
+{\r
+  return _archive->EnumProperties(EnumProperties);\r
+}\r
+*/\r
+\r
+HRESULT CAgent::ReadItems()\r
+{\r
+  if (_proxyArchive != NULL)\r
+    return S_OK;\r
+  _proxyArchive = new CProxyArchive();\r
+  return _proxyArchive->Load(GetArc(), NULL);\r
+}\r
+\r
+STDMETHODIMP CAgent::BindToRootFolder(IFolderFolder **resultFolder)\r
+{\r
+  COM_TRY_BEGIN\r
+  RINOK(ReadItems());\r
+  CAgentFolder *folderSpec = new CAgentFolder;\r
+  CMyComPtr<IFolderFolder> rootFolder = folderSpec;\r
+  folderSpec->Init(_proxyArchive, &_proxyArchive->RootFolder, NULL, this);\r
+  *resultFolder = rootFolder.Detach();\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+\r
+STDMETHODIMP CAgent::Extract(\r
+    NExtract::NPathMode::EEnum pathMode,\r
+    NExtract::NOverwriteMode::EEnum overwriteMode,\r
+    const wchar_t *path,\r
+    Int32 testMode,\r
+    IFolderArchiveExtractCallback *extractCallback2)\r
+{\r
+  COM_TRY_BEGIN\r
+  CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;\r
+  CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;\r
+  extractCallbackSpec->InitForMulti(false, pathMode, overwriteMode);\r
+  extractCallbackSpec->Init(NULL, &GetArc(),\r
+      extractCallback2,\r
+      false, testMode ? true : false, false,\r
+      path,\r
+      UStringVector(),\r
+      (UInt64)(Int64)-1);\r
+  return GetArchive()->Extract(0, (UInt32)(Int32)-1, testMode, extractCallback);\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CAgent::GetNumberOfProperties(UInt32 *numProps)\r
+{\r
+  COM_TRY_BEGIN\r
+  return GetArchive()->GetNumberOfProperties(numProps);\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CAgent::GetPropertyInfo(UInt32 index,\r
+      BSTR *name, PROPID *propID, VARTYPE *varType)\r
+{\r
+  COM_TRY_BEGIN\r
+  RINOK(GetArchive()->GetPropertyInfo(index, name, propID, varType));\r
+  if (*propID == kpidPath)\r
+    *propID = kpidName;\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CAgent::GetArcNumLevels(UInt32 *numLevels)\r
+{\r
+  *numLevels = _archiveLink.Arcs.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CAgent::GetArcProp(UInt32 level, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  CArc &arc = _archiveLink.Arcs[level];\r
+  switch(propID)\r
+  {\r
+    case kpidType: prop = GetTypeOfArc(arc); break;\r
+    case kpidPath: prop = arc.Path; break;\r
+    default: return arc.Archive->GetArchiveProperty(propID, value);\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CAgent::GetArcNumProps(UInt32 level, UInt32 *numProps)\r
+{\r
+  return _archiveLink.Arcs[level].Archive->GetNumberOfArchiveProperties(numProps);\r
+}\r
+\r
+STDMETHODIMP CAgent::GetArcPropInfo(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)\r
+{\r
+  return _archiveLink.Arcs[level].Archive->GetArchivePropertyInfo(index, name, propID, varType);\r
+}\r
+\r
+// MainItemProperty\r
+STDMETHODIMP CAgent::GetArcProp2(UInt32 level, PROPID propID, PROPVARIANT *value)\r
+{\r
+  return _archiveLink.Arcs[level - 1].Archive->GetProperty(_archiveLink.Arcs[level].SubfileIndex, propID, value);\r
+}\r
+\r
+STDMETHODIMP CAgent::GetArcNumProps2(UInt32 level, UInt32 *numProps)\r
+{\r
+  return _archiveLink.Arcs[level - 1].Archive->GetNumberOfProperties(numProps);\r
+}\r
+\r
+STDMETHODIMP CAgent::GetArcPropInfo2(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)\r
+{\r
+  return _archiveLink.Arcs[level - 1].Archive->GetPropertyInfo(index, name, propID, varType);\r
+}\r
diff --git a/CPP/7zip/UI/Agent/Agent.h b/CPP/7zip/UI/Agent/Agent.h
new file mode 100755 (executable)
index 0000000..38d5f47
--- /dev/null
@@ -0,0 +1,251 @@
+// Agent/Agent.h\r
+\r
+#ifndef __AGENT_AGENT_H\r
+#define __AGENT_AGENT_H\r
+\r
+#include "Common/MyCom.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../Common/OpenArchive.h"\r
+#include "../Common/UpdateAction.h"\r
+\r
+#ifdef NEW_FOLDER_INTERFACE\r
+#include "../FileManager/IFolder.h"\r
+#include "../Common/LoadCodecs.h"\r
+#endif\r
+\r
+#include "AgentProxy.h"\r
+#include "IFolderArchive.h"\r
+\r
+class CAgentFolder;\r
+\r
+DECL_INTERFACE(IArchiveFolderInternal, 0x01, 0xC)\r
+{\r
+  STDMETHOD(GetAgentFolder)(CAgentFolder **agentFolder) PURE;\r
+};\r
+\r
+struct CProxyItem\r
+{\r
+  CProxyFolder *Folder;\r
+  UInt32 Index;\r
+};\r
+\r
+class CAgent;\r
+\r
+class CAgentFolder:\r
+  public IFolderFolder,\r
+  public IFolderProperties,\r
+  public IGetFolderArcProps,\r
+  public IArchiveFolder,\r
+  public IArchiveFolderInternal,\r
+  public IInArchiveGetStream,\r
+#ifdef NEW_FOLDER_INTERFACE\r
+  public IFolderOperations,\r
+  public IFolderSetFlatMode,\r
+#endif\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+\r
+  MY_QUERYINTERFACE_BEGIN2(IFolderFolder)\r
+    MY_QUERYINTERFACE_ENTRY(IFolderProperties)\r
+    MY_QUERYINTERFACE_ENTRY(IGetFolderArcProps)\r
+    MY_QUERYINTERFACE_ENTRY(IArchiveFolder)\r
+    MY_QUERYINTERFACE_ENTRY(IArchiveFolderInternal)\r
+    MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream)\r
+  #ifdef NEW_FOLDER_INTERFACE\r
+    MY_QUERYINTERFACE_ENTRY(IFolderOperations)\r
+    MY_QUERYINTERFACE_ENTRY(IFolderSetFlatMode)\r
+  #endif\r
+  MY_QUERYINTERFACE_END\r
+  MY_ADDREF_RELEASE\r
+\r
+  void LoadFolder(CProxyFolder *folder);\r
+  HRESULT BindToFolder(CProxyFolder *folder, IFolderFolder **resultFolder);\r
+  void GetRealIndices(const UINT32 *indices, UINT32 numItems, CUIntVector &realIndices) const;\r
+\r
+  INTERFACE_FolderFolder(;)\r
+  INTERFACE_FolderProperties(;)\r
+\r
+  STDMETHOD(GetFolderArcProps)(IFolderArcProps **object);\r
+\r
+  // IArchiveFolder\r
+  STDMETHOD(Extract)(const UINT32 *indices, UINT32 numItems,\r
+      NExtract::NPathMode::EEnum pathMode,\r
+      NExtract::NOverwriteMode::EEnum overwriteMode,\r
+      const wchar_t *path,\r
+      Int32 testMode,\r
+      IFolderArchiveExtractCallback *extractCallback);\r
+  \r
+  STDMETHOD(GetAgentFolder)(CAgentFolder **agentFolder);\r
+\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);\r
+\r
+  #ifdef NEW_FOLDER_INTERFACE\r
+  INTERFACE_FolderOperations(;)\r
+\r
+  STDMETHOD(SetFlatMode)(Int32 flatMode);\r
+  #endif\r
+\r
+  CAgentFolder(): _proxyFolderItem(NULL), _flatMode(0) {}\r
+\r
+  void Init(CProxyArchive *proxyHandler,\r
+      CProxyFolder *proxyFolderItem,\r
+      IFolderFolder *parentFolder,\r
+      CAgent *agent)\r
+  {\r
+    _proxyArchive = proxyHandler;\r
+    _proxyFolderItem = proxyFolderItem;\r
+    _parentFolder = parentFolder;\r
+    _agent = (IInFolderArchive *)agent;\r
+    _agentSpec = agent;\r
+  }\r
+\r
+  void GetPathParts(UStringVector &pathParts);\r
+  HRESULT CommonUpdateOperation(\r
+      bool deleteOperation,\r
+      bool createFolderOperation,\r
+      bool renameOperation,\r
+      const wchar_t *newItemName,\r
+      const NUpdateArchive::CActionSet *actionSet,\r
+      const UINT32 *indices, UINT32 numItems,\r
+      IFolderArchiveUpdateCallback *updateCallback100);\r
+\r
+\r
+  UString GetPrefix(UInt32 index) const;\r
+  UString GetName(UInt32 index) const;\r
+  UString GetFullPathPrefixPlusPrefix(UInt32 index) const;\r
+  void GetPrefixIfAny(UInt32 index, NWindows::NCOM::CPropVariant &propVariant) const;\r
+\r
+public:\r
+  CProxyArchive *_proxyArchive;\r
+  CProxyFolder *_proxyFolderItem;\r
+  CMyComPtr<IFolderFolder> _parentFolder;\r
+  CMyComPtr<IInFolderArchive> _agent;\r
+  CAgent *_agentSpec;\r
+\r
+  CRecordVector<CProxyItem> _items;\r
+  bool _flatMode;\r
+private:\r
+};\r
+\r
+class CAgent:\r
+  public IInFolderArchive,\r
+  public IFolderArcProps,\r
+  #ifndef EXTRACT_ONLY\r
+  public IOutFolderArchive,\r
+  public ISetProperties,\r
+  #endif\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+\r
+  MY_QUERYINTERFACE_BEGIN2(IInFolderArchive)\r
+    MY_QUERYINTERFACE_ENTRY(IFolderArcProps)\r
+  #ifndef EXTRACT_ONLY\r
+    MY_QUERYINTERFACE_ENTRY(IOutFolderArchive)\r
+    MY_QUERYINTERFACE_ENTRY(ISetProperties)\r
+  #endif\r
+  MY_QUERYINTERFACE_END\r
+  MY_ADDREF_RELEASE\r
+\r
+  INTERFACE_IInFolderArchive(;)\r
+  INTERFACE_IFolderArcProps(;)\r
+\r
+  #ifndef EXTRACT_ONLY\r
+  INTERFACE_IOutFolderArchive(;)\r
+\r
+  HRESULT CommonUpdate(\r
+      const wchar_t *newArchiveName,\r
+      int numUpdateItems,\r
+      IArchiveUpdateCallback *updateCallback);\r
+  \r
+  HRESULT CreateFolder(\r
+    const wchar_t *newArchiveName,\r
+    const wchar_t *folderName,\r
+    IFolderArchiveUpdateCallback *updateCallback100);\r
+\r
+  HRESULT RenameItem(\r
+    const wchar_t *newArchiveName,\r
+    const UINT32 *indices, UINT32 numItems,\r
+    const wchar_t *newItemName,\r
+    IFolderArchiveUpdateCallback *updateCallback100);\r
+\r
+  // ISetProperties\r
+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties);\r
+  #endif\r
+\r
+  CCodecs *_codecs;\r
+  CMyComPtr<ICompressCodecsInfo> _compressCodecsInfo;\r
+\r
+  CAgent();\r
+  ~CAgent();\r
+private:\r
+  HRESULT ReadItems();\r
+public:\r
+  CProxyArchive *_proxyArchive;\r
+  CArchiveLink _archiveLink;\r
+\r
+\r
+  UString ArchiveType;\r
+\r
+  UStringVector _names;\r
+  UString _folderPrefix;\r
+\r
+  UString _archiveNamePrefix;\r
+  CAgentFolder *_agentFolder;\r
+\r
+  UString _archiveFilePath;\r
+\r
+  #ifndef EXTRACT_ONLY\r
+  CObjectVector<UString> m_PropNames;\r
+  CObjectVector<NWindows::NCOM::CPropVariant> m_PropValues;\r
+  #endif\r
+\r
+  const CArc &GetArc() { return _archiveLink.Arcs.Back(); }\r
+  IInArchive *GetArchive() { if ( _archiveLink.Arcs.IsEmpty()) return 0; return GetArc().Archive; }\r
+  bool CanUpdate() const { return _archiveLink.Arcs.Size() <= 1; }\r
+\r
+  UString GetTypeOfArc(const CArc &arc) const { return  _codecs->Formats[arc.FormatIndex].Name; }\r
+  UString GetErrorMessage() const\r
+  {\r
+    UString s;\r
+    for (int i = _archiveLink.Arcs.Size() - 1; i >= 0; i--)\r
+    {\r
+      const CArc &arc = _archiveLink.Arcs[i];\r
+      if (arc.ErrorMessage.IsEmpty())\r
+        continue;\r
+      if (!s.IsEmpty())\r
+        s += L"--------------------\n";\r
+      s += arc.ErrorMessage;\r
+      s += L"\n\n[";\r
+      s += GetTypeOfArc(arc);\r
+      s += L"] ";\r
+      s += arc.Path;\r
+      s += L"\n";\r
+    }\r
+    return s;\r
+  }\r
+};\r
+\r
+#ifdef NEW_FOLDER_INTERFACE\r
+class CArchiveFolderManager:\r
+  public IFolderManager,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP1(IFolderManager)\r
+\r
+  INTERFACE_IFolderManager(;)\r
+\r
+  CArchiveFolderManager(): _codecs(0) {}\r
+private:\r
+  void LoadFormats();\r
+  int FindFormat(const UString &type);\r
+  CCodecs *_codecs;\r
+  CMyComPtr<ICompressCodecsInfo> _compressCodecsInfo;\r
+};\r
+#endif\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp
new file mode 100755 (executable)
index 0000000..8486697
--- /dev/null
@@ -0,0 +1,533 @@
+// AgentOut.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/FileDir.h"\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/PropVariantConversions.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../../Compress/CopyCoder.h"\r
+\r
+#include "../../Common/FileStreams.h"\r
+\r
+#include "../Common/EnumDirItems.h"\r
+#include "../Common/OpenArchive.h"\r
+#include "../Common/UpdateCallback.h"\r
+#include "../Common/UpdatePair.h"\r
+\r
+#include "Agent.h"\r
+#include "UpdateCallbackAgent.h"\r
+\r
+using namespace NWindows;\r
+using namespace NCOM;\r
+\r
+STDMETHODIMP CAgent::SetFolder(IFolderFolder *folder)\r
+{\r
+  _archiveNamePrefix.Empty();\r
+  if (folder == NULL)\r
+  {\r
+    _agentFolder = NULL;\r
+    return S_OK;\r
+  }\r
+  else\r
+  {\r
+    CMyComPtr<IFolderFolder> archiveFolder = folder;\r
+    CMyComPtr<IArchiveFolderInternal> archiveFolderInternal;\r
+    RINOK(archiveFolder.QueryInterface(IID_IArchiveFolderInternal, &archiveFolderInternal));\r
+    RINOK(archiveFolderInternal->GetAgentFolder(&_agentFolder));\r
+  }\r
+\r
+  UStringVector pathParts;\r
+  pathParts.Clear();\r
+  CMyComPtr<IFolderFolder> folderItem = folder;\r
+  if (folderItem != NULL)\r
+    for (;;)\r
+    {\r
+      CMyComPtr<IFolderFolder> newFolder;\r
+      folderItem->BindToParentFolder(&newFolder);\r
+      if (newFolder == NULL)\r
+        break;\r
+\r
+      NCOM::CPropVariant prop;\r
+      if (folderItem->GetFolderProperty(kpidName, &prop) == S_OK)\r
+        if (prop.vt == VT_BSTR)\r
+          pathParts.Insert(0, (const wchar_t *)prop.bstrVal);\r
+      folderItem = newFolder;\r
+    }\r
+\r
+  for (int i = 0; i < pathParts.Size(); i++)\r
+  {\r
+    _archiveNamePrefix += pathParts[i];\r
+    _archiveNamePrefix += WCHAR_PATH_SEPARATOR;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CAgent::SetFiles(const wchar_t *folderPrefix,\r
+    const wchar_t **names, UInt32 numNames)\r
+{\r
+  _folderPrefix = folderPrefix;\r
+  _names.Clear();\r
+  _names.Reserve(numNames);\r
+  for (UInt32 i = 0; i < numNames; i++)\r
+    _names.Add(names[i]);\r
+  return S_OK;\r
+}\r
+\r
+static HRESULT EnumerateArchiveItems(CAgent *agent,\r
+    const CProxyFolder &item,\r
+    const UString &prefix,\r
+    CObjectVector<CArcItem> &arcItems)\r
+{\r
+  int i;\r
+  for (i = 0; i < item.Files.Size(); i++)\r
+  {\r
+    const CProxyFile &fileItem = item.Files[i];\r
+    CArcItem ai;\r
+    RINOK(agent->GetArc().GetItemMTime(fileItem.Index, ai.MTime, ai.MTimeDefined));\r
+\r
+    CPropVariant property;\r
+    agent->GetArchive()->GetProperty(fileItem.Index, kpidSize, &property);\r
+    ai.SizeDefined = (property.vt != VT_EMPTY);\r
+    if (ai.SizeDefined)\r
+      ai.Size = ConvertPropVariantToUInt64(property);\r
+    ai.IsDir = false;\r
+    ai.Name = prefix + fileItem.Name;\r
+    ai.Censored = true; // test it\r
+    ai.IndexInServer = fileItem.Index;\r
+    arcItems.Add(ai);\r
+  }\r
+  for (i = 0; i < item.Folders.Size(); i++)\r
+  {\r
+    const CProxyFolder &dirItem = item.Folders[i];\r
+    UString fullName = prefix + dirItem.Name;\r
+    if (dirItem.IsLeaf)\r
+    {\r
+      CArcItem ai;\r
+      RINOK(agent->GetArc().GetItemMTime(dirItem.Index, ai.MTime, ai.MTimeDefined));\r
+      ai.IsDir = true;\r
+      ai.SizeDefined = false;\r
+      ai.Name = fullName;\r
+      ai.Censored = true; // test it\r
+      ai.IndexInServer = dirItem.Index;\r
+      arcItems.Add(ai);\r
+    }\r
+    RINOK(EnumerateArchiveItems(agent, dirItem, fullName + UString(WCHAR_PATH_SEPARATOR), arcItems));\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+struct CAgUpCallbackImp: public IUpdateProduceCallback\r
+{\r
+  const CObjectVector<CArcItem> *_arcItems;\r
+  IFolderArchiveUpdateCallback *_callback;\r
+  \r
+  CAgUpCallbackImp(const CObjectVector<CArcItem> *a,\r
+      IFolderArchiveUpdateCallback *callback): _arcItems(a), _callback(callback) {}\r
+  HRESULT ShowDeleteFile(int arcIndex);\r
+};\r
+\r
+HRESULT CAgUpCallbackImp::ShowDeleteFile(int arcIndex)\r
+{\r
+  return _callback->DeleteOperation((*_arcItems)[arcIndex].Name);\r
+}\r
+\r
+STDMETHODIMP CAgent::DoOperation(\r
+    CCodecs *codecs,\r
+    int formatIndex,\r
+    const wchar_t *newArchiveName,\r
+    const Byte *stateActions,\r
+    const wchar_t *sfxModule,\r
+    IFolderArchiveUpdateCallback *updateCallback100)\r
+{\r
+  if (!CanUpdate())\r
+    return E_NOTIMPL;\r
+  NUpdateArchive::CActionSet actionSet;\r
+  int i;\r
+  for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)\r
+    actionSet.StateActions[i] = (NUpdateArchive::NPairAction::EEnum)stateActions[i];\r
+\r
+  CDirItems dirItems;\r
+\r
+  {\r
+    UString folderPrefix = _folderPrefix;\r
+    NFile::NName::NormalizeDirPathPrefix(folderPrefix);\r
+    UStringVector errorPaths;\r
+    CRecordVector<DWORD> errorCodes;\r
+    dirItems.EnumerateDirItems2(folderPrefix, _archiveNamePrefix, _names, errorPaths, errorCodes);\r
+    if (errorCodes.Size() > 0)\r
+      return errorCodes.Front();\r
+  }\r
+\r
+  CMyComPtr<IOutArchive> outArchive;\r
+  if (GetArchive())\r
+  {\r
+    RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive));\r
+  }\r
+  else\r
+  {\r
+    if (formatIndex < 0)\r
+      return E_FAIL;\r
+    RINOK(codecs->CreateOutArchive(formatIndex, outArchive));\r
+    #ifdef EXTERNAL_CODECS\r
+    {\r
+      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;\r
+      outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);\r
+      if (setCompressCodecsInfo)\r
+      {\r
+        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs));\r
+      }\r
+    }\r
+    #endif\r
+\r
+  }\r
+\r
+  NFileTimeType::EEnum fileTimeType;\r
+  UInt32 value;\r
+  RINOK(outArchive->GetFileTimeType(&value));\r
+\r
+  switch(value)\r
+  {\r
+    case NFileTimeType::kWindows:\r
+    case NFileTimeType::kDOS:\r
+    case NFileTimeType::kUnix:\r
+      fileTimeType = NFileTimeType::EEnum(value);\r
+      break;\r
+    default:\r
+      return E_FAIL;\r
+  }\r
+\r
+\r
+  CObjectVector<CArcItem> arcItems;\r
+  if (GetArchive())\r
+  {\r
+    RINOK(ReadItems());\r
+    EnumerateArchiveItems(this, _proxyArchive->RootFolder, L"", arcItems);\r
+  }\r
+\r
+  CRecordVector<CUpdatePair2> updatePairs2;\r
+\r
+  {\r
+    CRecordVector<CUpdatePair> updatePairs;\r
+    GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs);\r
+    CAgUpCallbackImp upCallback(&arcItems, updateCallback100);\r
+    UpdateProduce(updatePairs, actionSet, updatePairs2, &upCallback);\r
+  }\r
+\r
+  UInt32 numFiles = 0;\r
+  for (i = 0; i < updatePairs2.Size(); i++)\r
+    if (updatePairs2[i].NewData)\r
+      numFiles++;\r
+  \r
+  if (updateCallback100)\r
+  {\r
+    RINOK(updateCallback100->SetNumFiles(numFiles));\r
+  }\r
+  \r
+  CUpdateCallbackAgent updateCallbackAgent;\r
+  updateCallbackAgent.SetCallback(updateCallback100);\r
+  CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;\r
+  CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec );\r
+\r
+  updateCallbackSpec->DirItems = &dirItems;\r
+  updateCallbackSpec->ArcItems = &arcItems;\r
+  updateCallbackSpec->UpdatePairs = &updatePairs2;\r
+  updateCallbackSpec->Archive = GetArchive();\r
+  updateCallbackSpec->Callback = &updateCallbackAgent;\r
+\r
+  COutFileStream *outStreamSpec = new COutFileStream;\r
+  CMyComPtr<IOutStream> outStream(outStreamSpec);\r
+  UString archiveName = newArchiveName;\r
+  {\r
+    UString resultPath;\r
+    int pos;\r
+    if (!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos))\r
+      return E_FAIL;\r
+    NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));\r
+  }\r
+  if (!outStreamSpec->Create(archiveName, true))\r
+  {\r
+    // ShowLastErrorMessage();\r
+    return E_FAIL;\r
+  }\r
+  \r
+  CMyComPtr<ISetProperties> setProperties;\r
+  if (outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties) == S_OK)\r
+  {\r
+    if (m_PropNames.Size() == 0)\r
+    {\r
+      RINOK(setProperties->SetProperties(0, 0, 0));\r
+    }\r
+    else\r
+    {\r
+      CRecordVector<const wchar_t *> names;\r
+      for(i = 0; i < m_PropNames.Size(); i++)\r
+        names.Add((const wchar_t *)m_PropNames[i]);\r
+\r
+      NWindows::NCOM::CPropVariant *propValues = new NWindows::NCOM::CPropVariant[m_PropValues.Size()];\r
+      try\r
+      {\r
+        for (int i = 0; i < m_PropValues.Size(); i++)\r
+          propValues[i] = m_PropValues[i];\r
+        RINOK(setProperties->SetProperties(&names.Front(), propValues, names.Size()));\r
+      }\r
+      catch(...)\r
+      {\r
+        delete []propValues;\r
+        return E_FAIL;\r
+      }\r
+      delete []propValues;\r
+    }\r
+  }\r
+  m_PropNames.Clear();\r
+  m_PropValues.Clear();\r
+\r
+  if (sfxModule != NULL)\r
+  {\r
+    CInFileStream *sfxStreamSpec = new CInFileStream;\r
+    CMyComPtr<IInStream> sfxStream(sfxStreamSpec);\r
+    if (!sfxStreamSpec->Open(sfxModule))\r
+      return E_FAIL;\r
+      // throw "Can't open sfx module";\r
+    RINOK(NCompress::CopyStream(sfxStream, outStream, NULL));\r
+  }\r
+\r
+  RINOK(outArchive->UpdateItems(outStream, updatePairs2.Size(),updateCallback));\r
+  return outStreamSpec->Close();\r
+}\r
+\r
+STDMETHODIMP CAgent::DoOperation2(\r
+    const wchar_t *newArchiveName,\r
+    const Byte *stateActions,\r
+    const wchar_t *sfxModule,\r
+    IFolderArchiveUpdateCallback *updateCallback100)\r
+{\r
+  return DoOperation(_codecs, -1, newArchiveName,\r
+    stateActions, sfxModule, updateCallback100);\r
+}\r
+\r
+HRESULT CAgent::CommonUpdate(\r
+    const wchar_t *newArchiveName,\r
+    int numUpdateItems,\r
+    IArchiveUpdateCallback *updateCallback)\r
+{\r
+  if (!CanUpdate())\r
+    return E_NOTIMPL;\r
+  CMyComPtr<IOutArchive> outArchive;\r
+  RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive));\r
+\r
+  COutFileStream *outStreamSpec = new COutFileStream;\r
+  CMyComPtr<IOutStream> outStream(outStreamSpec);\r
+\r
+  UString archiveName = newArchiveName;\r
+  {\r
+    UString resultPath;\r
+    int pos;\r
+    if (!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos))\r
+      throw 141716;\r
+    NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));\r
+  }\r
+\r
+  /*\r
+  bool isOK = false;\r
+  for (int i = 0; i < (1 << 16); i++)\r
+  {\r
+    resultName = newArchiveName;\r
+    if (i > 0)\r
+    {\r
+      wchar_t s[16];\r
+      ConvertUInt32ToString(i, s);\r
+      resultName += s;\r
+    }\r
+    if (outStreamSpec->Open(realPath))\r
+    {\r
+      isOK = true;\r
+      break;\r
+    }\r
+    if (::GetLastError() != ERROR_FILE_EXISTS)\r
+      return ::GetLastError();\r
+  }\r
+  if (!isOK)\r
+    return ::GetLastError();\r
+  */\r
+  if (!outStreamSpec->Create(archiveName, true))\r
+  {\r
+    // ShowLastErrorMessage();\r
+    return E_FAIL;\r
+  }\r
+  \r
+  RINOK(outArchive->UpdateItems(outStream, numUpdateItems, updateCallback));\r
+  return outStreamSpec->Close();\r
+}\r
+\r
+\r
+STDMETHODIMP CAgent::DeleteItems(\r
+    const wchar_t *newArchiveName,\r
+    const UInt32 *indices, UInt32 numItems,\r
+    IFolderArchiveUpdateCallback *updateCallback100)\r
+{\r
+  if (!CanUpdate())\r
+    return E_NOTIMPL;\r
+  CUpdateCallbackAgent updateCallbackAgent;\r
+  updateCallbackAgent.SetCallback(updateCallback100);\r
+  CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;\r
+  CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);\r
+  \r
+  CUIntVector realIndices;\r
+  _agentFolder->GetRealIndices(indices, numItems, realIndices);\r
+  CRecordVector<CUpdatePair2> updatePairs;\r
+  int curIndex = 0;\r
+  UInt32 numItemsInArchive;\r
+  RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive));\r
+  for (UInt32 i = 0; i < numItemsInArchive; i++)\r
+  {\r
+    if (curIndex < realIndices.Size())\r
+      if (realIndices[curIndex] == i)\r
+      {\r
+        curIndex++;\r
+        continue;\r
+      }\r
+    CUpdatePair2 up2;\r
+    up2.NewData = up2.NewProps = false;\r
+    up2.IsAnti = false; // check it. Maybe it can be undefined\r
+    up2.ArcIndex = i;\r
+    updatePairs.Add(up2);\r
+  }\r
+  updateCallbackSpec->UpdatePairs = &updatePairs;\r
+  updateCallbackSpec->Archive = GetArchive();\r
+  updateCallbackSpec->Callback = &updateCallbackAgent;\r
+  return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback);\r
+}\r
+\r
+HRESULT CAgent::CreateFolder(\r
+    const wchar_t *newArchiveName,\r
+    const wchar_t *folderName,\r
+    IFolderArchiveUpdateCallback *updateCallback100)\r
+{\r
+  if (!CanUpdate())\r
+    return E_NOTIMPL;\r
+  CUpdateCallbackAgent updateCallbackAgent;\r
+  updateCallbackAgent.SetCallback(updateCallback100);\r
+  CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;\r
+  CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);\r
+\r
+  CRecordVector<CUpdatePair2> updatePairs;\r
+  UInt32 numItemsInArchive;\r
+  RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive));\r
+  for (UInt32 i = 0; i < numItemsInArchive; i++)\r
+  {\r
+    CUpdatePair2 up2;\r
+    up2.NewData = up2.NewProps = false;\r
+    up2.IsAnti = false;  // check it.\r
+    up2.ArcIndex = i;\r
+    updatePairs.Add(up2);\r
+  }\r
+  CUpdatePair2 up2;\r
+  up2.NewData = up2.NewProps = true;\r
+  up2.IsAnti = false;\r
+  up2.DirIndex = 0;\r
+\r
+  updatePairs.Add(up2);\r
+\r
+  updatePairs.ReserveDown();\r
+\r
+  CDirItems dirItems;\r
+  CDirItem di;\r
+\r
+  di.Attrib = FILE_ATTRIBUTE_DIRECTORY;\r
+  di.Size = 0;\r
+  di.Name = _agentFolder->_proxyFolderItem->GetFullPathPrefix() + folderName;\r
+\r
+  FILETIME ft;\r
+  NTime::GetCurUtcFileTime(ft);\r
+  di.CTime = di.ATime = di.MTime = ft;\r
+\r
+  dirItems.Items.Add(di);\r
+\r
+  updateCallbackSpec->Callback = &updateCallbackAgent;\r
+  updateCallbackSpec->DirItems = &dirItems;\r
+  updateCallbackSpec->UpdatePairs = &updatePairs;\r
+  updateCallbackSpec->Archive = GetArchive();\r
+  return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback);\r
+}\r
+\r
+\r
+HRESULT CAgent::RenameItem(\r
+    const wchar_t *newArchiveName,\r
+    const UInt32 *indices, UInt32 numItems,\r
+    const wchar_t *newItemName,\r
+    IFolderArchiveUpdateCallback *updateCallback100)\r
+{\r
+  if (!CanUpdate())\r
+    return E_NOTIMPL;\r
+  if (numItems != 1)\r
+    return E_INVALIDARG;\r
+  CUpdateCallbackAgent updateCallbackAgent;\r
+  updateCallbackAgent.SetCallback(updateCallback100);\r
+  CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;\r
+  CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);\r
+  \r
+  CUIntVector realIndices;\r
+  _agentFolder->GetRealIndices(indices, numItems, realIndices);\r
+\r
+  UString fullPrefix = _agentFolder->GetFullPathPrefixPlusPrefix(indices[0]);\r
+  UString oldItemPath = fullPrefix + _agentFolder->GetName(indices[0]);\r
+  UString newItemPath = fullPrefix + newItemName;\r
+\r
+  CRecordVector<CUpdatePair2> updatePairs;\r
+  UStringVector newNames;\r
+\r
+  int curIndex = 0;\r
+  UInt32 numItemsInArchive;\r
+  RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive));\r
+  for (UInt32 i = 0; i < numItemsInArchive; i++)\r
+  {\r
+    if (curIndex < realIndices.Size())\r
+      if (realIndices[curIndex] == i)\r
+      {\r
+        CUpdatePair2 up2;\r
+        up2.NewData = false;\r
+        up2.NewProps = true;\r
+        RINOK(GetArc().IsItemAnti(i, up2.IsAnti));\r
+        up2.ArcIndex = i;\r
+\r
+        UString oldFullPath;\r
+        RINOK(GetArc().GetItemPath(i, oldFullPath));\r
+\r
+        if (oldItemPath.CompareNoCase(oldFullPath.Left(oldItemPath.Length())) != 0)\r
+          return E_INVALIDARG;\r
+\r
+        up2.NewNameIndex = newNames.Add(newItemPath + oldFullPath.Mid(oldItemPath.Length()));\r
+        updatePairs.Add(up2);\r
+        curIndex++;\r
+        continue;\r
+      }\r
+    CUpdatePair2 up2;\r
+    up2.NewData = up2.NewProps = false;\r
+    up2.IsAnti = false;\r
+    up2.ArcIndex = i;\r
+    updatePairs.Add(up2);\r
+  }\r
+  updateCallbackSpec->Callback = &updateCallbackAgent;\r
+  updateCallbackSpec->UpdatePairs = &updatePairs;\r
+  updateCallbackSpec->NewNames = &newNames;\r
+  updateCallbackSpec->Archive = GetArchive();\r
+  return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback);\r
+}\r
+\r
+STDMETHODIMP CAgent::SetProperties(const wchar_t **names,\r
+    const PROPVARIANT *values, Int32 numProperties)\r
+{\r
+  m_PropNames.Clear();\r
+  m_PropValues.Clear();\r
+  for (int i = 0; i < numProperties; i++)\r
+  {\r
+    m_PropNames.Add(names[i]);\r
+    m_PropValues.Add(values[i]);\r
+  }\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp
new file mode 100755 (executable)
index 0000000..3040fcc
--- /dev/null
@@ -0,0 +1,246 @@
+// AgentProxy.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/Sort.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/PropVariantConversions.h"\r
+\r
+#include "../Common/OpenArchive.h"\r
+\r
+#include "AgentProxy.h"\r
+\r
+using namespace NWindows;\r
+\r
+int CProxyFolder::FindDirSubItemIndex(const UString &name, int &insertPos) const\r
+{\r
+  int left = 0, right = Folders.Size();\r
+  for (;;)\r
+  {\r
+    if (left == right)\r
+    {\r
+      insertPos = left;\r
+      return -1;\r
+    }\r
+    int mid = (left + right) / 2;\r
+    int compare = name.CompareNoCase(Folders[mid].Name);\r
+    if (compare == 0)\r
+      return mid;\r
+    if (compare < 0)\r
+      right = mid;\r
+    else\r
+      left = mid + 1;\r
+  }\r
+}\r
+\r
+int CProxyFolder::FindDirSubItemIndex(const UString &name) const\r
+{\r
+  int insertPos;\r
+  return FindDirSubItemIndex(name, insertPos);\r
+}\r
+\r
+void CProxyFolder::AddFileSubItem(UInt32 index, const UString &name)\r
+{\r
+  Files.Add(CProxyFile());\r
+  Files.Back().Name = name;\r
+  Files.Back().Index = index;\r
+}\r
+\r
+CProxyFolder* CProxyFolder::AddDirSubItem(UInt32 index, bool leaf, const UString &name)\r
+{\r
+  int insertPos;\r
+  int folderIndex = FindDirSubItemIndex(name, insertPos);\r
+  if (folderIndex >= 0)\r
+  {\r
+    CProxyFolder *item = &Folders[folderIndex];\r
+    if (leaf)\r
+    {\r
+      item->Index = index;\r
+      item->IsLeaf = true;\r
+    }\r
+    return item;\r
+  }\r
+  Folders.Insert(insertPos, CProxyFolder());\r
+  CProxyFolder *item = &Folders[insertPos];\r
+  item->Name = name;\r
+  item->Index = index;\r
+  item->Parent = this;\r
+  item->IsLeaf = leaf;\r
+  return item;\r
+}\r
+\r
+void CProxyFolder::Clear()\r
+{\r
+  Folders.Clear();\r
+  Files.Clear();\r
+}\r
+\r
+void CProxyFolder::GetPathParts(UStringVector &pathParts) const\r
+{\r
+  pathParts.Clear();\r
+  UString result;\r
+  const CProxyFolder *current = this;\r
+  while (current->Parent != NULL)\r
+  {\r
+    pathParts.Insert(0, (const wchar_t *)current->Name);\r
+    current = current->Parent;\r
+  }\r
+}\r
+\r
+UString CProxyFolder::GetFullPathPrefix() const\r
+{\r
+  UString result;\r
+  const CProxyFolder *current = this;\r
+  while (current->Parent != NULL)\r
+  {\r
+    result = current->Name + UString(WCHAR_PATH_SEPARATOR) + result;\r
+    current = current->Parent;\r
+  }\r
+  return result;\r
+}\r
+\r
+UString CProxyFolder::GetItemName(UInt32 index) const\r
+{\r
+  if (index < (UInt32)Folders.Size())\r
+    return Folders[index].Name;\r
+  return Files[index - Folders.Size()].Name;\r
+}\r
+\r
+void CProxyFolder::AddRealIndices(CUIntVector &realIndices) const\r
+{\r
+  if (IsLeaf)\r
+    realIndices.Add(Index);\r
+  int i;\r
+  for (i = 0; i < Folders.Size(); i++)\r
+    Folders[i].AddRealIndices(realIndices);\r
+  for (i = 0; i < Files.Size(); i++)\r
+    realIndices.Add(Files[i].Index);\r
+}\r
+\r
+void CProxyFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const\r
+{\r
+  realIndices.Clear();\r
+  for (UInt32 i = 0; i < numItems; i++)\r
+  {\r
+    int index = indices[i];\r
+    int numDirItems = Folders.Size();\r
+    if (index < numDirItems)\r
+      Folders[index].AddRealIndices(realIndices);\r
+    else\r
+      realIndices.Add(Files[index - numDirItems].Index);\r
+  }\r
+  HeapSort(&realIndices.Front(), realIndices.Size());\r
+}\r
+\r
+///////////////////////////////////////////////\r
+// CProxyArchive\r
+\r
+static UInt64 GetSize(IInArchive *archive, UInt32 index, PROPID propID)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  if (archive->GetProperty(index, propID, &prop) == S_OK)\r
+    if (prop.vt != VT_EMPTY)\r
+      return ConvertPropVariantToUInt64(prop);\r
+  return 0;\r
+}\r
+\r
+void CProxyFolder::CalculateSizes(IInArchive *archive)\r
+{\r
+  Size = PackSize = 0;\r
+  NumSubFolders = Folders.Size();\r
+  NumSubFiles = Files.Size();\r
+  CrcIsDefined = true;\r
+  Crc = 0;\r
+  int i;\r
+  for (i = 0; i < Files.Size(); i++)\r
+  {\r
+    UInt32 index = Files[i].Index;\r
+    Size += GetSize(archive, index, kpidSize);\r
+    PackSize += GetSize(archive, index, kpidPackSize);\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      if (archive->GetProperty(index, kpidCRC, &prop) == S_OK && prop.vt == VT_UI4)\r
+        Crc += prop.ulVal;\r
+      else\r
+        CrcIsDefined = false;\r
+    }\r
+  }\r
+  for (i = 0; i < Folders.Size(); i++)\r
+  {\r
+    CProxyFolder &f = Folders[i];\r
+    f.CalculateSizes(archive);\r
+    Size += f.Size;\r
+    PackSize += f.PackSize;\r
+    NumSubFiles += f.NumSubFiles;\r
+    NumSubFolders += f.NumSubFolders;\r
+    Crc += f.Crc;\r
+    if (!f.CrcIsDefined)\r
+      CrcIsDefined = false;\r
+  }\r
+}\r
+\r
+HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress)\r
+{\r
+  RootFolder.Clear();\r
+  IInArchive *archive = arc.Archive;\r
+  {\r
+    ThereIsPathProp = false;\r
+    UInt32 numProps;\r
+    archive->GetNumberOfProperties(&numProps);\r
+    for (UInt32 i = 0; i < numProps; i++)\r
+    {\r
+      CMyComBSTR name;\r
+      PROPID propID;\r
+      VARTYPE varType;\r
+      RINOK(archive->GetPropertyInfo(i, &name, &propID, &varType));\r
+      if (propID == kpidPath)\r
+      {\r
+        ThereIsPathProp = true;\r
+        break;\r
+      }\r
+    }\r
+  }\r
+\r
+  UInt32 numItems;\r
+  RINOK(archive->GetNumberOfItems(&numItems));\r
+  if (progress != NULL)\r
+  {\r
+    UInt64 totalItems = numItems;\r
+    RINOK(progress->SetTotal(totalItems));\r
+  }\r
+  UString fileName;\r
+  for (UInt32 i = 0; i < numItems; i++)\r
+  {\r
+    if (progress != NULL && (i & 0xFFFFF) == 0)\r
+    {\r
+      UInt64 currentItemIndex = i;\r
+      RINOK(progress->SetCompleted(&currentItemIndex));\r
+    }\r
+    UString filePath;\r
+    RINOK(arc.GetItemPath(i, filePath));\r
+    CProxyFolder *curItem = &RootFolder;\r
+    int len = filePath.Length();\r
+    fileName.Empty();\r
+    for (int j = 0; j < len; j++)\r
+    {\r
+      wchar_t c = filePath[j];\r
+      if (c == WCHAR_PATH_SEPARATOR || c == L'/')\r
+      {\r
+        curItem = curItem->AddDirSubItem((UInt32)(Int32)-1, false, fileName);\r
+        fileName.Empty();\r
+      }\r
+      else\r
+        fileName += c;\r
+    }\r
+\r
+    bool isFolder;\r
+    RINOK(IsArchiveItemFolder(archive, i, isFolder));\r
+    if (isFolder)\r
+      curItem->AddDirSubItem(i, true, fileName);\r
+    else\r
+      curItem->AddFileSubItem(i, fileName);\r
+  }\r
+  RootFolder.CalculateSizes(archive);\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/UI/Agent/AgentProxy.h b/CPP/7zip/UI/Agent/AgentProxy.h
new file mode 100755 (executable)
index 0000000..4a6cab7
--- /dev/null
@@ -0,0 +1,53 @@
+// AgentProxy.h\r
+\r
+#ifndef __AGENT_PROXY_H\r
+#define __AGENT_PROXY_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+#include "../Common/OpenArchive.h"\r
+\r
+struct CProxyFile\r
+{\r
+  UInt32 Index;\r
+  UString Name;\r
+};\r
+\r
+struct CProxyFolder: public CProxyFile\r
+{\r
+  CProxyFolder *Parent;\r
+  CObjectVector<CProxyFolder> Folders;\r
+  CObjectVector<CProxyFile> Files;\r
+  bool IsLeaf;\r
+\r
+  bool CrcIsDefined;\r
+  UInt64 Size;\r
+  UInt64 PackSize;\r
+  UInt32 Crc;\r
+  UInt32 NumSubFolders;\r
+  UInt32 NumSubFiles;\r
+\r
+  CProxyFolder(): Parent(NULL) {};\r
+  int FindDirSubItemIndex(const UString &name, int &insertPos) const;\r
+  int FindDirSubItemIndex(const UString &name) const;\r
+  CProxyFolder* AddDirSubItem(UInt32 index, bool leaf, const UString &name);\r
+  void AddFileSubItem(UInt32 index, const UString &name);\r
+  void Clear();\r
+\r
+  void GetPathParts(UStringVector &pathParts) const;\r
+  UString GetFullPathPrefix() const;\r
+  UString GetItemName(UInt32 index) const;\r
+  void AddRealIndices(CUIntVector &realIndices) const;\r
+  void GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const;\r
+  void CalculateSizes(IInArchive *archive);\r
+};\r
+\r
+struct CProxyArchive\r
+{\r
+  CProxyFolder RootFolder;\r
+  bool ThereIsPathProp;\r
+\r
+  HRESULT Load(const CArc &arc, IProgress *progress);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Agent/ArchiveFolder.cpp b/CPP/7zip/UI/Agent/ArchiveFolder.cpp
new file mode 100755 (executable)
index 0000000..0b75e5b
--- /dev/null
@@ -0,0 +1,59 @@
+// Agent/ArchiveFolder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+\r
+#include "../Common/ArchiveExtractCallback.h"\r
+\r
+#include "Agent.h"\r
+\r
+using namespace NWindows;\r
+using namespace NCOM;\r
+\r
+STDMETHODIMP CAgentFolder::CopyTo(const UInt32 *indices, UInt32 numItems,\r
+    const wchar_t *path, IFolderOperationsExtractCallback *callback)\r
+{\r
+  COM_TRY_BEGIN\r
+  CArchiveExtractCallback *extractCallbackSpec = new\r
+      CArchiveExtractCallback;\r
+  CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;\r
+  UStringVector pathParts;\r
+  CProxyFolder *currentProxyFolder = _proxyFolderItem;\r
+  while (currentProxyFolder->Parent)\r
+  {\r
+    pathParts.Insert(0, currentProxyFolder->Name);\r
+    currentProxyFolder = currentProxyFolder->Parent;\r
+  }\r
+\r
+  CMyComPtr<IFolderArchiveExtractCallback> extractCallback2;\r
+  {\r
+    CMyComPtr<IFolderOperationsExtractCallback> callbackWrap = callback;\r
+    RINOK(callbackWrap.QueryInterface(\r
+        IID_IFolderArchiveExtractCallback, &extractCallback2));\r
+  }\r
+\r
+  NExtract::NPathMode::EEnum pathMode = _flatMode ?\r
+      NExtract::NPathMode::kNoPathnames :\r
+      NExtract::NPathMode::kCurrentPathnames;\r
+\r
+  extractCallbackSpec->InitForMulti(false, pathMode, NExtract::NOverwriteMode::kAskBefore);\r
+  extractCallbackSpec->Init(NULL, &_agentSpec->GetArc(),\r
+      extractCallback2,\r
+      false, false, false,\r
+      path,\r
+      pathParts,\r
+      (UInt64)(Int64)-1);\r
+  CUIntVector realIndices;\r
+  GetRealIndices(indices, numItems, realIndices);\r
+  return _agentSpec->GetArchive()->Extract(&realIndices.Front(),\r
+      realIndices.Size(), BoolToInt(false), extractCallback);\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CAgentFolder::MoveTo(const UInt32 * /* indices */, UInt32 /* numItems */,\r
+    const wchar_t * /* path */, IFolderOperationsExtractCallback * /* callback */)\r
+{\r
+  return E_NOTIMPL;\r
+}\r
+\r
diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp
new file mode 100755 (executable)
index 0000000..d78e1bb
--- /dev/null
@@ -0,0 +1,142 @@
+// Zip/ArchiveFolder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Agent.h"\r
+\r
+#include "Common/StringConvert.h"\r
+\r
+extern HINSTANCE g_hInstance;\r
+\r
+static inline UINT GetCurrentFileCodePage()\r
+{\r
+  #ifdef UNDER_CE\r
+  return CP_ACP;\r
+  #else\r
+  return AreFileApisANSI() ? CP_ACP : CP_OEMCP;\r
+  #endif\r
+}\r
+\r
+void CArchiveFolderManager::LoadFormats()\r
+{\r
+  if (!_codecs)\r
+  {\r
+    _compressCodecsInfo = _codecs = new CCodecs;\r
+    _codecs->Load();\r
+  }\r
+}\r
+\r
+int CArchiveFolderManager::FindFormat(const UString &type)\r
+{\r
+  for (int i = 0; i < _codecs->Formats.Size(); i++)\r
+    if (type.CompareNoCase(_codecs->Formats[i].Name) == 0)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+STDMETHODIMP CArchiveFolderManager::OpenFolderFile(IInStream *inStream,\r
+    const wchar_t *filePath, const wchar_t *arcFormat,\r
+    IFolderFolder **resultFolder, IProgress *progress)\r
+{\r
+  CMyComPtr<IArchiveOpenCallback> openArchiveCallback;\r
+  if (progress != 0)\r
+  {\r
+    CMyComPtr<IProgress> progressWrapper = progress;\r
+    progressWrapper.QueryInterface(IID_IArchiveOpenCallback, &openArchiveCallback);\r
+  }\r
+  CAgent *agent = new CAgent();\r
+  CMyComPtr<IInFolderArchive> archive = agent;\r
+  RINOK(agent->Open(inStream, filePath, arcFormat, NULL, openArchiveCallback));\r
+  return agent->BindToRootFolder(resultFolder);\r
+}\r
+\r
+/*\r
+HRESULT CAgent::FolderReOpen(\r
+    IArchiveOpenCallback *openArchiveCallback)\r
+{\r
+  return ReOpenArchive(_archive, _archiveFilePath);\r
+}\r
+*/\r
+\r
+\r
+/*\r
+STDMETHODIMP CArchiveFolderManager::GetExtensions(const wchar_t *type, BSTR *extensions)\r
+{\r
+  *extensions = 0;\r
+  int formatIndex = FindFormat(type);\r
+  if (formatIndex <  0)\r
+    return E_INVALIDARG;\r
+  // Exts[0].Ext;\r
+  return StringToBstr(_codecs.Formats[formatIndex].GetAllExtensions(), extensions);\r
+}\r
+*/\r
+\r
+static void AddIconExt(const CCodecIcons &lib, UString &dest)\r
+{\r
+  for (int j = 0; j < lib.IconPairs.Size(); j++)\r
+  {\r
+    if (!dest.IsEmpty())\r
+      dest += L' ';\r
+    dest += lib.IconPairs[j].Ext;\r
+  }\r
+}\r
+\r
+STDMETHODIMP CArchiveFolderManager::GetExtensions(BSTR *extensions)\r
+{\r
+  LoadFormats();\r
+  *extensions = 0;\r
+  UString res;\r
+  for (int i = 0; i < _codecs->Libs.Size(); i++)\r
+    AddIconExt(_codecs->Libs[i], res);\r
+  AddIconExt(_codecs->InternalIcons, res);\r
+  return StringToBstr(res, extensions);\r
+}\r
+\r
+STDMETHODIMP CArchiveFolderManager::GetIconPath(const wchar_t *ext, BSTR *iconPath, Int32 *iconIndex)\r
+{\r
+  LoadFormats();\r
+  *iconPath = 0;\r
+  *iconIndex = 0;\r
+  for (int i = 0; i < _codecs->Libs.Size(); i++)\r
+  {\r
+    const CCodecLib &lib = _codecs->Libs[i];\r
+    int ii;\r
+    if (lib.FindIconIndex(ext, ii))\r
+    {\r
+      *iconIndex = ii;\r
+      return StringToBstr(GetUnicodeString(lib.Path, GetCurrentFileCodePage()), iconPath);\r
+    }\r
+  }\r
+  int ii;\r
+  if (_codecs->InternalIcons.FindIconIndex(ext, ii))\r
+  {\r
+    *iconIndex = ii;\r
+    UString path;\r
+    NWindows::NDLL::MyGetModuleFileName(g_hInstance, path);\r
+    return StringToBstr(path, iconPath);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+/*\r
+STDMETHODIMP CArchiveFolderManager::GetTypes(BSTR *types)\r
+{\r
+  LoadFormats();\r
+  UString typesStrings;\r
+  for(int i = 0; i < _codecs.Formats.Size(); i++)\r
+  {\r
+    const CArcInfoEx &ai = _codecs.Formats[i];\r
+    if (ai.AssociateExts.Size() == 0)\r
+      continue;\r
+    if (i != 0)\r
+      typesStrings += L' ';\r
+    typesStrings += ai.Name;\r
+  }\r
+  return StringToBstr(typesStrings, types);\r
+}\r
+STDMETHODIMP CArchiveFolderManager::CreateFolderFile(const wchar_t * type,\r
+    const wchar_t * filePath, IProgress progress)\r
+{\r
+  return E_NOTIMPL;\r
+}\r
+*/\r
diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp
new file mode 100755 (executable)
index 0000000..5767346
--- /dev/null
@@ -0,0 +1,214 @@
+// FolderOut.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+\r
+#include "Windows/FileDir.h"\r
+\r
+#include "../Common/WorkDir.h"\r
+\r
+#include "Agent.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+using namespace NDirectory;\r
+\r
+static LPCWSTR kTempArcivePrefix = L"7zA";\r
+\r
+void CAgentFolder::GetPathParts(UStringVector &pathParts)\r
+{\r
+  _proxyFolderItem->GetPathParts(pathParts);\r
+}\r
+\r
+HRESULT CAgentFolder::CommonUpdateOperation(\r
+    bool deleteOperation,\r
+    bool createFolderOperation,\r
+    bool renameOperation,\r
+    const wchar_t *newItemName,\r
+    const NUpdateArchive::CActionSet *actionSet,\r
+    const UINT32 *indices, UINT32 numItems,\r
+    IFolderArchiveUpdateCallback *updateCallback100)\r
+{\r
+  NWorkDir::CInfo workDirInfo;\r
+  workDirInfo.Load();\r
+  UString archiveFilePath  = _agentSpec->_archiveFilePath;\r
+  UString workDir = GetWorkDir(workDirInfo, archiveFilePath);\r
+  CreateComplexDirectory(workDir);\r
+\r
+  CTempFileW tempFile;\r
+  UString tempFileName;\r
+  if (tempFile.Create(workDir, kTempArcivePrefix, tempFileName) == 0)\r
+    return E_FAIL;\r
+\r
+  /*\r
+  if (SetOutProperties(anOutArchive, aCompressionInfo.Method) != S_OK)\r
+    return NFileOperationReturnCode::kError;\r
+  */\r
+  \r
+  ////////////////////////////\r
+  // Save FolderItem;\r
+\r
+  UStringVector pathParts;\r
+  GetPathParts(pathParts);\r
+\r
+  HRESULT result;\r
+  if (deleteOperation)\r
+    result = _agentSpec->DeleteItems(tempFileName,\r
+        indices, numItems, updateCallback100);\r
+  else if (createFolderOperation)\r
+  {\r
+    result = _agentSpec->CreateFolder(tempFileName,\r
+        newItemName, updateCallback100);\r
+  }\r
+  else if (renameOperation)\r
+  {\r
+    result = _agentSpec->RenameItem(\r
+        tempFileName,\r
+        indices, numItems,\r
+        newItemName,\r
+        updateCallback100);\r
+  }\r
+  else\r
+  {\r
+    Byte actionSetByte[NUpdateArchive::NPairState::kNumValues];\r
+    for (int i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)\r
+      actionSetByte[i] = (Byte)actionSet->StateActions[i];\r
+    result = _agentSpec->DoOperation2(tempFileName, actionSetByte, NULL, updateCallback100);\r
+  }\r
+  \r
+  if (result != S_OK)\r
+    return result;\r
+\r
+  _agentSpec->Close();\r
+  \r
+  // m_FolderItem = NULL;\r
+  \r
+  if (NFind::DoesFileExist(archiveFilePath))\r
+    if (!DeleteFileAlways(archiveFilePath))\r
+      return GetLastError();\r
+\r
+  tempFile.DisableDeleting();\r
+  if (!MyMoveFile(tempFileName, archiveFilePath))\r
+    return GetLastError();\r
+\r
+  {\r
+    CMyComPtr<IArchiveOpenCallback> openCallback;\r
+    if (updateCallback100)\r
+    {\r
+      RINOK(updateCallback100->QueryInterface(IID_IArchiveOpenCallback, (void **)&openCallback));\r
+    }\r
+    RINOK(_agentSpec->ReOpen(openCallback));\r
+  }\r
+   \r
+  ////////////////////////////\r
+  // Restore FolderItem;\r
+\r
+  CMyComPtr<IFolderFolder> archiveFolder;\r
+  RINOK(_agentSpec->BindToRootFolder(&archiveFolder));\r
+  for (int i = 0; i < pathParts.Size(); i++)\r
+  {\r
+    CMyComPtr<IFolderFolder> newFolder;\r
+    archiveFolder->BindToFolder(pathParts[i], &newFolder);\r
+    if(!newFolder)\r
+      break;\r
+    archiveFolder = newFolder;\r
+  }\r
+\r
+  CMyComPtr<IArchiveFolderInternal> archiveFolderInternal;\r
+  RINOK(archiveFolder.QueryInterface(IID_IArchiveFolderInternal, &archiveFolderInternal));\r
+  CAgentFolder *agentFolder;\r
+  RINOK(archiveFolderInternal->GetAgentFolder(&agentFolder));\r
+  _proxyFolderItem = agentFolder->_proxyFolderItem;\r
+  _proxyArchive = agentFolder->_proxyArchive;\r
+  _parentFolder = agentFolder->_parentFolder;\r
+\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CAgentFolder::CopyFrom(\r
+    const wchar_t *fromFolderPath, // test it\r
+    const wchar_t **itemsPaths,\r
+    UINT32 numItems,\r
+    IProgress *progress)\r
+{\r
+  COM_TRY_BEGIN\r
+  CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;\r
+  if (progress != 0)\r
+  {\r
+    RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&updateCallback100));\r
+  }\r
+  try\r
+  {\r
+    RINOK(_agentSpec->SetFiles(fromFolderPath, itemsPaths, numItems));\r
+    RINOK(_agentSpec->SetFolder(this));\r
+    return CommonUpdateOperation(false, false, false, NULL,\r
+      &NUpdateArchive::kAddActionSet, 0, 0, updateCallback100);\r
+  }\r
+  catch(const UString &s)\r
+  {\r
+    RINOK(updateCallback100->UpdateErrorMessage(UString(L"Error: ") + s));\r
+    return E_FAIL;\r
+  }\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CAgentFolder::Delete(const UINT32 *indices, UINT32 numItems, IProgress *progress)\r
+{\r
+  COM_TRY_BEGIN\r
+  RINOK(_agentSpec->SetFolder(this));\r
+  CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;\r
+  if (progress != 0)\r
+  {\r
+    CMyComPtr<IProgress> progressWrapper = progress;\r
+    RINOK(progressWrapper.QueryInterface(\r
+        IID_IFolderArchiveUpdateCallback, &updateCallback100));\r
+  }\r
+  return CommonUpdateOperation(true, false, false, NULL,\r
+    &NUpdateArchive::kDeleteActionSet, indices, numItems, updateCallback100);\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CAgentFolder::CreateFolder(const wchar_t *name, IProgress *progress)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (_proxyFolderItem->FindDirSubItemIndex(name) >= 0)\r
+    return ERROR_ALREADY_EXISTS;\r
+  RINOK(_agentSpec->SetFolder(this));\r
+  CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;\r
+  if (progress != 0)\r
+  {\r
+    CMyComPtr<IProgress> progressWrapper = progress;\r
+    RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100));\r
+  }\r
+  return CommonUpdateOperation(false, true, false, name, NULL, NULL, 0, updateCallback100);\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CAgentFolder::Rename(UINT32 index, const wchar_t *newName, IProgress *progress)\r
+{\r
+  COM_TRY_BEGIN\r
+  CUIntVector indices;\r
+  indices.Add(index);\r
+  RINOK(_agentSpec->SetFolder(this));\r
+  CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;\r
+  if (progress != 0)\r
+  {\r
+    CMyComPtr<IProgress> progressWrapper = progress;\r
+    RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100));\r
+  }\r
+  return CommonUpdateOperation(false, false, true, newName, NULL, &indices.Front(),\r
+      indices.Size(), updateCallback100);\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CAgentFolder::CreateFile(const wchar_t * /* name */, IProgress * /* progress */)\r
+{\r
+  return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CAgentFolder::SetProperty(UINT32 /* index */, PROPID /* propID */,\r
+    const PROPVARIANT * /* value */, IProgress * /* progress */)\r
+{\r
+  return E_NOTIMPL;\r
+}\r
diff --git a/CPP/7zip/UI/Agent/IFolderArchive.h b/CPP/7zip/UI/Agent/IFolderArchive.h
new file mode 100755 (executable)
index 0000000..38fdf6e
--- /dev/null
@@ -0,0 +1,73 @@
+// IFolderArchive.h\r
+\r
+#ifndef __IFOLDER_ARCHIVE_H\r
+#define __IFOLDER_ARCHIVE_H\r
+\r
+#include "../../IDecl.h"\r
+#include "../../Archive/IArchive.h"\r
+#include "../../UI/Common/LoadCodecs.h"\r
+#include "../../UI/FileManager/IFolder.h"\r
+\r
+#include "../Common/ExtractMode.h"\r
+#include "../Common/IFileExtractCallback.h"\r
+\r
+#define FOLDER_ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 0x01, x)\r
+#define FOLDER_ARCHIVE_INTERFACE(i, x) FOLDER_ARCHIVE_INTERFACE_SUB(i, IUnknown, x)\r
+\r
+#define INTERFACE_IArchiveFolder(x) \\r
+  STDMETHOD(Extract)(const UInt32 *indices, UInt32 numItems, \\r
+      NExtract::NPathMode::EEnum pathMode, \\r
+      NExtract::NOverwriteMode::EEnum overwriteMode, \\r
+      const wchar_t *path, Int32 testMode, \\r
+      IFolderArchiveExtractCallback *extractCallback2) x; \\r
+\r
+FOLDER_ARCHIVE_INTERFACE(IArchiveFolder, 0x05)\r
+{\r
+  INTERFACE_IArchiveFolder(PURE)\r
+};\r
+\r
+#define INTERFACE_IInFolderArchive(x) \\r
+  STDMETHOD(Open)(IInStream *inStream, const wchar_t *filePath, const wchar_t *arcFormat, BSTR *archiveTypeRes, IArchiveOpenCallback *openArchiveCallback) x; \\r
+  STDMETHOD(ReOpen)(IArchiveOpenCallback *openArchiveCallback) x; \\r
+  STDMETHOD(Close)() x; \\r
+  STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \\r
+  STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \\r
+  STDMETHOD(BindToRootFolder)(IFolderFolder **resultFolder) x; \\r
+  STDMETHOD(Extract)(NExtract::NPathMode::EEnum pathMode, \\r
+      NExtract::NOverwriteMode::EEnum overwriteMode, const wchar_t *path, \\r
+      Int32 testMode, IFolderArchiveExtractCallback *extractCallback2) x; \\r
+\r
+FOLDER_ARCHIVE_INTERFACE(IInFolderArchive, 0x0E)\r
+{\r
+  INTERFACE_IInFolderArchive(PURE)\r
+};\r
+\r
+#define INTERFACE_IFolderArchiveUpdateCallback(x) \\r
+  STDMETHOD(CompressOperation)(const wchar_t *name) x; \\r
+  STDMETHOD(DeleteOperation)(const wchar_t *name) x; \\r
+  STDMETHOD(OperationResult)(Int32 operationResult) x; \\r
+  STDMETHOD(UpdateErrorMessage)(const wchar_t *message) x; \\r
+  STDMETHOD(SetNumFiles)(UInt64 numFiles) x; \\r
+\r
+FOLDER_ARCHIVE_INTERFACE_SUB(IFolderArchiveUpdateCallback, IProgress, 0x0B)\r
+{\r
+  INTERFACE_IFolderArchiveUpdateCallback(PURE)\r
+};\r
+\r
+#define INTERFACE_IOutFolderArchive(x) \\r
+  STDMETHOD(SetFolder)(IFolderFolder *folder) x; \\r
+  STDMETHOD(SetFiles)(const wchar_t *folderPrefix, const wchar_t **names, UInt32 numNames) x; \\r
+  STDMETHOD(DeleteItems)(const wchar_t *newArchiveName, \\r
+      const UInt32 *indices, UInt32 numItems, IFolderArchiveUpdateCallback *updateCallback) x; \\r
+  STDMETHOD(DoOperation)(CCodecs *codecs, int index, \\r
+      const wchar_t *newArchiveName, const Byte *stateActions, const wchar_t *sfxModule, \\r
+      IFolderArchiveUpdateCallback *updateCallback) x; \\r
+  STDMETHOD(DoOperation2)(const wchar_t *newArchiveName, const Byte *stateActions, \\r
+      const wchar_t *sfxModule, IFolderArchiveUpdateCallback *updateCallback) x; \\r
+\r
+FOLDER_ARCHIVE_INTERFACE(IOutFolderArchive, 0x0A)\r
+{\r
+  INTERFACE_IOutFolderArchive(PURE)\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp
new file mode 100755 (executable)
index 0000000..7bb234e
--- /dev/null
@@ -0,0 +1,121 @@
+// UpdateCallbackAgent.h\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/Error.h"\r
+#include "Common/IntToString.h"\r
+\r
+#include "UpdateCallbackAgent.h"\r
+\r
+using namespace NWindows;\r
+\r
+void CUpdateCallbackAgent::SetCallback(IFolderArchiveUpdateCallback *callback)\r
+{\r
+  Callback = callback;\r
+  _compressProgress.Release();\r
+  if (Callback)\r
+    Callback.QueryInterface(IID_ICompressProgressInfo, &_compressProgress);\r
+}\r
+\r
+HRESULT CUpdateCallbackAgent::SetNumFiles(UInt64 numFiles)\r
+{\r
+  if (Callback)\r
+    return Callback->SetNumFiles(numFiles);\r
+  return S_OK;\r
+}\r
+\r
+\r
+HRESULT CUpdateCallbackAgent::SetTotal(UINT64 size)\r
+{\r
+  if (Callback)\r
+    return Callback->SetTotal(size);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackAgent::SetCompleted(const UINT64 *completeValue)\r
+{\r
+  if (Callback)\r
+    return Callback->SetCompleted(completeValue);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackAgent::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)\r
+{\r
+  if (_compressProgress)\r
+    return _compressProgress->SetRatioInfo(inSize, outSize);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackAgent::CheckBreak()\r
+{\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackAgent::Finilize()\r
+{\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackAgent::OpenFileError(const wchar_t *name, DWORD systemError)\r
+{\r
+  // if (systemError == ERROR_SHARING_VIOLATION)\r
+  {\r
+    if (Callback)\r
+    {\r
+      RINOK(Callback->UpdateErrorMessage(\r
+        UString(L"WARNING: ") +\r
+        NError::MyFormatMessageW(systemError) +\r
+        UString(L": ") +\r
+        UString(name)));\r
+      return S_FALSE;\r
+    }\r
+  }\r
+  // FailedFiles.Add(name);\r
+  return systemError;\r
+}\r
+\r
+HRESULT CUpdateCallbackAgent::GetStream(const wchar_t *name, bool /* isAnti */)\r
+{\r
+  if (Callback)\r
+    return Callback->CompressOperation(name);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackAgent::SetOperationResult(Int32 operationResult)\r
+{\r
+  if (Callback)\r
+    return Callback->OperationResult(operationResult);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackAgent::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)\r
+{\r
+  *password = NULL;\r
+  *passwordIsDefined = BoolToInt(false);\r
+  if (!_cryptoGetTextPassword)\r
+  {\r
+    if (!Callback)\r
+      return S_OK;\r
+    Callback.QueryInterface(IID_ICryptoGetTextPassword2, &_cryptoGetTextPassword);\r
+    if (!_cryptoGetTextPassword)\r
+      return S_OK;\r
+  }\r
+  return _cryptoGetTextPassword->CryptoGetTextPassword2(passwordIsDefined, password);\r
+}\r
+\r
+HRESULT CUpdateCallbackAgent::CryptoGetTextPassword(BSTR *password)\r
+{\r
+  *password = NULL;\r
+  CMyComPtr<ICryptoGetTextPassword> getTextPassword;\r
+  Callback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);\r
+  if (!getTextPassword)\r
+    return E_NOTIMPL;\r
+  return getTextPassword->CryptoGetTextPassword(password);\r
+}\r
+\r
+/*\r
+HRESULT CUpdateCallbackAgent::ShowDeleteFile(const wchar_t *name)\r
+{\r
+  return Callback->DeleteOperation(name);\r
+}\r
+*/\r
diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.h b/CPP/7zip/UI/Agent/UpdateCallbackAgent.h
new file mode 100755 (executable)
index 0000000..53d09ff
--- /dev/null
@@ -0,0 +1,19 @@
+// UpdateCallbackAgent.h\r
+\r
+#ifndef __UPDATECALLBACKAGENT_H\r
+#define __UPDATECALLBACKAGENT_H\r
+\r
+#include "../Common/UpdateCallback.h"\r
+#include "IFolderArchive.h"\r
+\r
+class CUpdateCallbackAgent: public IUpdateCallbackUI\r
+{\r
+  INTERFACE_IUpdateCallbackUI(;)\r
+  CMyComPtr<ICryptoGetTextPassword2> _cryptoGetTextPassword;\r
+  CMyComPtr<IFolderArchiveUpdateCallback> Callback;\r
+  CMyComPtr<ICompressProgressInfo> _compressProgress;\r
+public:\r
+  void SetCallback(IFolderArchiveUpdateCallback *callback);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp
new file mode 100755 (executable)
index 0000000..7001fe8
--- /dev/null
@@ -0,0 +1,871 @@
+// Client7z.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/MyInitGuid.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/DLL.h"\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileFind.h"\r
+#include "Windows/FileName.h"\r
+#include "Windows/NtCheck.h"\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/PropVariantConversions.h"\r
+\r
+#include "../../Common/FileStreams.h"\r
+\r
+#include "../../Archive/IArchive.h"\r
+\r
+#include "../../IPassword.h"\r
+#include "../../MyVersion.h"\r
+\r
+// use another CLSIDs, if you want to support other formats (zip, rar, ...).\r
+// {23170F69-40C1-278A-1000-000110070000}\r
+DEFINE_GUID(CLSID_CFormat7z,\r
+  0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00);\r
+\r
+using namespace NWindows;\r
+\r
+#define kDllName "7z.dll"\r
+\r
+static const char *kCopyrightString = MY_7ZIP_VERSION\r
+" ("  kDllName " client) "\r
+MY_COPYRIGHT " " MY_DATE;\r
+\r
+static const char *kHelpString =\r
+"Usage: Client7z.exe [a | l | x ] archive.7z [fileName ...]\n"\r
+"Examples:\n"\r
+"  Client7z.exe a archive.7z f1.txt f2.txt  : compress two files to archive.7z\n"\r
+"  Client7z.exe l archive.7z   : List contents of archive.7z\n"\r
+"  Client7z.exe x archive.7z   : eXtract files from archive.7z\n";\r
+\r
+\r
+typedef UINT32 (WINAPI * CreateObjectFunc)(\r
+    const GUID *clsID,\r
+    const GUID *interfaceID,\r
+    void **outObject);\r
+\r
+\r
+void PrintString(const UString &s)\r
+{\r
+  printf("%s", (LPCSTR)GetOemString(s));\r
+}\r
+\r
+void PrintString(const AString &s)\r
+{\r
+  printf("%s", (LPCSTR)s);\r
+}\r
+\r
+void PrintNewLine()\r
+{\r
+  PrintString("\n");\r
+}\r
+\r
+void PrintStringLn(const AString &s)\r
+{\r
+  PrintString(s);\r
+  PrintNewLine();\r
+}\r
+\r
+void PrintError(const AString &s)\r
+{\r
+  PrintNewLine();\r
+  PrintString(s);\r
+  PrintNewLine();\r
+}\r
+\r
+static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  RINOK(archive->GetProperty(index, propID, &prop));\r
+  if (prop.vt == VT_BOOL)\r
+    result = VARIANT_BOOLToBool(prop.boolVal);\r
+  else if (prop.vt == VT_EMPTY)\r
+    result = false;\r
+  else\r
+    return E_FAIL;\r
+  return S_OK;\r
+}\r
+\r
+static HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result)\r
+{\r
+  return IsArchiveItemProp(archive, index, kpidIsDir, result);\r
+}\r
+\r
+\r
+static const wchar_t *kEmptyFileAlias = L"[Content]";\r
+\r
+\r
+//////////////////////////////////////////////////////////////\r
+// Archive Open callback class\r
+\r
+\r
+class CArchiveOpenCallback:\r
+  public IArchiveOpenCallback,\r
+  public ICryptoGetTextPassword,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP1(ICryptoGetTextPassword)\r
+\r
+  STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes);\r
+  STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes);\r
+\r
+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);\r
+\r
+  bool PasswordIsDefined;\r
+  UString Password;\r
+\r
+  CArchiveOpenCallback() : PasswordIsDefined(false) {}\r
+};\r
+\r
+STDMETHODIMP CArchiveOpenCallback::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */)\r
+{\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CArchiveOpenCallback::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */)\r
+{\r
+  return S_OK;\r
+}\r
+  \r
+STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password)\r
+{\r
+  if (!PasswordIsDefined)\r
+  {\r
+    // You can ask real password here from user\r
+    // Password = GetPassword(OutStream);\r
+    // PasswordIsDefined = true;\r
+    PrintError("Password is not defined");\r
+    return E_ABORT;\r
+  }\r
+  return StringToBstr(Password, password);\r
+}\r
+\r
+\r
+//////////////////////////////////////////////////////////////\r
+// Archive Extracting callback class\r
+\r
+static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file ";\r
+\r
+static const char *kTestingString    =  "Testing     ";\r
+static const char *kExtractingString =  "Extracting  ";\r
+static const char *kSkippingString   =  "Skipping    ";\r
+\r
+static const char *kUnsupportedMethod = "Unsupported Method";\r
+static const char *kCRCFailed = "CRC Failed";\r
+static const char *kDataError = "Data Error";\r
+static const char *kUnknownError = "Unknown Error";\r
+\r
+class CArchiveExtractCallback:\r
+  public IArchiveExtractCallback,\r
+  public ICryptoGetTextPassword,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP1(ICryptoGetTextPassword)\r
+\r
+  // IProgress\r
+  STDMETHOD(SetTotal)(UInt64 size);\r
+  STDMETHOD(SetCompleted)(const UInt64 *completeValue);\r
+\r
+  // IArchiveExtractCallback\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode);\r
+  STDMETHOD(PrepareOperation)(Int32 askExtractMode);\r
+  STDMETHOD(SetOperationResult)(Int32 resultEOperationResult);\r
+\r
+  // ICryptoGetTextPassword\r
+  STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword);\r
+\r
+private:\r
+  CMyComPtr<IInArchive> _archiveHandler;\r
+  UString _directoryPath;  // Output directory\r
+  UString _filePath;       // name inside arcvhive\r
+  UString _diskFilePath;   // full path to file on disk\r
+  bool _extractMode;\r
+  struct CProcessedFileInfo\r
+  {\r
+    FILETIME MTime;\r
+    UInt32 Attrib;\r
+    bool isDir;\r
+    bool AttribDefined;\r
+    bool MTimeDefined;\r
+  } _processedFileInfo;\r
+\r
+  COutFileStream *_outFileStreamSpec;\r
+  CMyComPtr<ISequentialOutStream> _outFileStream;\r
+\r
+public:\r
+  void Init(IInArchive *archiveHandler, const UString &directoryPath);\r
+\r
+  UInt64 NumErrors;\r
+  bool PasswordIsDefined;\r
+  UString Password;\r
+\r
+  CArchiveExtractCallback() : PasswordIsDefined(false) {}\r
+};\r
+\r
+void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const UString &directoryPath)\r
+{\r
+  NumErrors = 0;\r
+  _archiveHandler = archiveHandler;\r
+  _directoryPath = directoryPath;\r
+  NFile::NName::NormalizeDirPathPrefix(_directoryPath);\r
+}\r
+\r
+STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 /* size */)\r
+{\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 * /* completeValue */)\r
+{\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index,\r
+    ISequentialOutStream **outStream, Int32 askExtractMode)\r
+{\r
+  *outStream = 0;\r
+  _outFileStream.Release();\r
+\r
+  {\r
+    // Get Name\r
+    NCOM::CPropVariant prop;\r
+    RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop));\r
+    \r
+    UString fullPath;\r
+    if (prop.vt == VT_EMPTY)\r
+      fullPath = kEmptyFileAlias;\r
+    else\r
+    {\r
+      if (prop.vt != VT_BSTR)\r
+        return E_FAIL;\r
+      fullPath = prop.bstrVal;\r
+    }\r
+    _filePath = fullPath;\r
+  }\r
+\r
+  if (askExtractMode != NArchive::NExtract::NAskMode::kExtract)\r
+    return S_OK;\r
+\r
+  {\r
+    // Get Attrib\r
+    NCOM::CPropVariant prop;\r
+    RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop));\r
+    if (prop.vt == VT_EMPTY)\r
+    {\r
+      _processedFileInfo.Attrib = 0;\r
+      _processedFileInfo.AttribDefined = false;\r
+    }\r
+    else\r
+    {\r
+      if (prop.vt != VT_UI4)\r
+        return E_FAIL;\r
+      _processedFileInfo.Attrib = prop.ulVal;\r
+      _processedFileInfo.AttribDefined = true;\r
+    }\r
+  }\r
+\r
+  RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.isDir));\r
+\r
+  {\r
+    // Get Modified Time\r
+    NCOM::CPropVariant prop;\r
+    RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop));\r
+    _processedFileInfo.MTimeDefined = false;\r
+    switch(prop.vt)\r
+    {\r
+      case VT_EMPTY:\r
+        // _processedFileInfo.MTime = _utcMTimeDefault;\r
+        break;\r
+      case VT_FILETIME:\r
+        _processedFileInfo.MTime = prop.filetime;\r
+        _processedFileInfo.MTimeDefined = true;\r
+        break;\r
+      default:\r
+        return E_FAIL;\r
+    }\r
+\r
+  }\r
+  {\r
+    // Get Size\r
+    NCOM::CPropVariant prop;\r
+    RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop));\r
+    bool newFileSizeDefined = (prop.vt != VT_EMPTY);\r
+    UInt64 newFileSize;\r
+    if (newFileSizeDefined)\r
+      newFileSize = ConvertPropVariantToUInt64(prop);\r
+  }\r
+\r
+  \r
+  {\r
+    // Create folders for file\r
+    int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+    if (slashPos >= 0)\r
+      NFile::NDirectory::CreateComplexDirectory(_directoryPath + _filePath.Left(slashPos));\r
+  }\r
+\r
+  UString fullProcessedPath = _directoryPath + _filePath;\r
+  _diskFilePath = fullProcessedPath;\r
+\r
+  if (_processedFileInfo.isDir)\r
+  {\r
+    NFile::NDirectory::CreateComplexDirectory(fullProcessedPath);\r
+  }\r
+  else\r
+  {\r
+    NFile::NFind::CFileInfoW fi;\r
+    if (fi.Find(fullProcessedPath))\r
+    {\r
+      if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath))\r
+      {\r
+        PrintString(UString(kCantDeleteOutputFile) + fullProcessedPath);\r
+        return E_ABORT;\r
+      }\r
+    }\r
+    \r
+    _outFileStreamSpec = new COutFileStream;\r
+    CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);\r
+    if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS))\r
+    {\r
+      PrintString((UString)L"can not open output file " + fullProcessedPath);\r
+      return E_ABORT;\r
+    }\r
+    _outFileStream = outStreamLoc;\r
+    *outStream = outStreamLoc.Detach();\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)\r
+{\r
+  _extractMode = false;\r
+  switch (askExtractMode)\r
+  {\r
+    case NArchive::NExtract::NAskMode::kExtract:  _extractMode = true; break;\r
+  };\r
+  switch (askExtractMode)\r
+  {\r
+    case NArchive::NExtract::NAskMode::kExtract:  PrintString(kExtractingString); break;\r
+    case NArchive::NExtract::NAskMode::kTest:  PrintString(kTestingString); break;\r
+    case NArchive::NExtract::NAskMode::kSkip:  PrintString(kSkippingString); break;\r
+  };\r
+  PrintString(_filePath);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)\r
+{\r
+  switch(operationResult)\r
+  {\r
+    case NArchive::NExtract::NOperationResult::kOK:\r
+      break;\r
+    default:\r
+    {\r
+      NumErrors++;\r
+      PrintString("     ");\r
+      switch(operationResult)\r
+      {\r
+        case NArchive::NExtract::NOperationResult::kUnSupportedMethod:\r
+          PrintString(kUnsupportedMethod);\r
+          break;\r
+        case NArchive::NExtract::NOperationResult::kCRCError:\r
+          PrintString(kCRCFailed);\r
+          break;\r
+        case NArchive::NExtract::NOperationResult::kDataError:\r
+          PrintString(kDataError);\r
+          break;\r
+        default:\r
+          PrintString(kUnknownError);\r
+      }\r
+    }\r
+  }\r
+\r
+  if (_outFileStream != NULL)\r
+  {\r
+    if (_processedFileInfo.MTimeDefined)\r
+      _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime);\r
+    RINOK(_outFileStreamSpec->Close());\r
+  }\r
+  _outFileStream.Release();\r
+  if (_extractMode && _processedFileInfo.AttribDefined)\r
+    NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attrib);\r
+  PrintNewLine();\r
+  return S_OK;\r
+}\r
+\r
+\r
+STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)\r
+{\r
+  if (!PasswordIsDefined)\r
+  {\r
+    // You can ask real password here from user\r
+    // Password = GetPassword(OutStream);\r
+    // PasswordIsDefined = true;\r
+    PrintError("Password is not defined");\r
+    return E_ABORT;\r
+  }\r
+  return StringToBstr(Password, password);\r
+}\r
+\r
+\r
+\r
+//////////////////////////////////////////////////////////////\r
+// Archive Creating callback class\r
+\r
+struct CDirItem\r
+{\r
+  UInt64 Size;\r
+  FILETIME CTime;\r
+  FILETIME ATime;\r
+  FILETIME MTime;\r
+  UString Name;\r
+  UString FullPath;\r
+  UInt32 Attrib;\r
+\r
+  bool isDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; }\r
+};\r
+\r
+class CArchiveUpdateCallback:\r
+  public IArchiveUpdateCallback2,\r
+  public ICryptoGetTextPassword2,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2)\r
+\r
+  // IProgress\r
+  STDMETHOD(SetTotal)(UInt64 size);\r
+  STDMETHOD(SetCompleted)(const UInt64 *completeValue);\r
+\r
+  // IUpdateCallback2\r
+  STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator);\r
+  STDMETHOD(GetUpdateItemInfo)(UInt32 index,\r
+      Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive);\r
+  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);\r
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream);\r
+  STDMETHOD(SetOperationResult)(Int32 operationResult);\r
+  STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size);\r
+  STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream);\r
+\r
+  STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);\r
+\r
+public:\r
+  CRecordVector<UInt64> VolumesSizes;\r
+  UString VolName;\r
+  UString VolExt;\r
+\r
+  UString DirPrefix;\r
+  const CObjectVector<CDirItem> *DirItems;\r
+\r
+  bool PasswordIsDefined;\r
+  UString Password;\r
+  bool AskPassword;\r
+\r
+  bool m_NeedBeClosed;\r
+\r
+  UStringVector FailedFiles;\r
+  CRecordVector<HRESULT> FailedCodes;\r
+\r
+  CArchiveUpdateCallback(): PasswordIsDefined(false), AskPassword(false), DirItems(0) {};\r
+\r
+  ~CArchiveUpdateCallback() { Finilize(); }\r
+  HRESULT Finilize();\r
+\r
+  void Init(const CObjectVector<CDirItem> *dirItems)\r
+  {\r
+    DirItems = dirItems;\r
+    m_NeedBeClosed = false;\r
+    FailedFiles.Clear();\r
+    FailedCodes.Clear();\r
+  }\r
+};\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 /* size */)\r
+{\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 * /* completeValue */)\r
+{\r
+  return S_OK;\r
+}\r
+\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG ** /* enumerator */)\r
+{\r
+  return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */,\r
+      Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)\r
+{\r
+  if (newData != NULL)\r
+    *newData = BoolToInt(true);\r
+  if (newProperties != NULL)\r
+    *newProperties = BoolToInt(true);\r
+  if (indexInArchive != NULL)\r
+    *indexInArchive = (UInt32)-1;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  NWindows::NCOM::CPropVariant prop;\r
+  \r
+  if (propID == kpidIsAnti)\r
+  {\r
+    prop = false;\r
+    prop.Detach(value);\r
+    return S_OK;\r
+  }\r
+\r
+  {\r
+    const CDirItem &dirItem = (*DirItems)[index];\r
+    switch(propID)\r
+    {\r
+      case kpidPath:  prop = dirItem.Name; break;\r
+      case kpidIsDir:  prop = dirItem.isDir(); break;\r
+      case kpidSize:  prop = dirItem.Size; break;\r
+      case kpidAttrib:  prop = dirItem.Attrib; break;\r
+      case kpidCTime:  prop = dirItem.CTime; break;\r
+      case kpidATime:  prop = dirItem.ATime; break;\r
+      case kpidMTime:  prop = dirItem.MTime; break;\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CArchiveUpdateCallback::Finilize()\r
+{\r
+  if (m_NeedBeClosed)\r
+  {\r
+    PrintNewLine();\r
+    m_NeedBeClosed = false;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+static void GetStream2(const wchar_t *name)\r
+{\r
+  PrintString("Compressing  ");\r
+  if (name[0] == 0)\r
+    name = kEmptyFileAlias;\r
+  PrintString(name);\r
+}\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)\r
+{\r
+  RINOK(Finilize());\r
+\r
+  const CDirItem &dirItem = (*DirItems)[index];\r
+  GetStream2(dirItem.Name);\r
\r
+  if (dirItem.isDir())\r
+    return S_OK;\r
+\r
+  {\r
+    CInFileStream *inStreamSpec = new CInFileStream;\r
+    CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);\r
+    UString path = DirPrefix + dirItem.FullPath;\r
+    if (!inStreamSpec->Open(path))\r
+    {\r
+      DWORD sysError = ::GetLastError();\r
+      FailedCodes.Add(sysError);\r
+      FailedFiles.Add(path);\r
+      // if (systemError == ERROR_SHARING_VIOLATION)\r
+      {\r
+        PrintNewLine();\r
+        PrintError("WARNING: can't open file");\r
+        // PrintString(NError::MyFormatMessageW(systemError));\r
+        return S_FALSE;\r
+      }\r
+      // return sysError;\r
+    }\r
+    *inStream = inStreamLoc.Detach();\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 /* operationResult */)\r
+{\r
+  m_NeedBeClosed = true;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)\r
+{\r
+  if (VolumesSizes.Size() == 0)\r
+    return S_FALSE;\r
+  if (index >= (UInt32)VolumesSizes.Size())\r
+    index = VolumesSizes.Size() - 1;\r
+  *size = VolumesSizes[index];\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)\r
+{\r
+  wchar_t temp[16];\r
+  ConvertUInt32ToString(index + 1, temp);\r
+  UString res = temp;\r
+  while (res.Length() < 2)\r
+    res = UString(L'0') + res;\r
+  UString fileName = VolName;\r
+  fileName += L'.';\r
+  fileName += res;\r
+  fileName += VolExt;\r
+  COutFileStream *streamSpec = new COutFileStream;\r
+  CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);\r
+  if (!streamSpec->Create(fileName, false))\r
+    return ::GetLastError();\r
+  *volumeStream = streamLoc.Detach();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)\r
+{\r
+  if (!PasswordIsDefined)\r
+  {\r
+    if (AskPassword)\r
+    {\r
+      // You can ask real password here from user\r
+      // Password = GetPassword(OutStream);\r
+      // PasswordIsDefined = true;\r
+      PrintError("Password is not defined");\r
+      return E_ABORT;\r
+    }\r
+  }\r
+  *passwordIsDefined = BoolToInt(PasswordIsDefined);\r
+  return StringToBstr(Password, password);\r
+}\r
+\r
+\r
+\r
+//////////////////////////////////////////////////////////////////////////\r
+// Main function\r
+\r
+#define NT_CHECK_FAIL_ACTION PrintError("Unsupported Windows version"); return 1;\r
+\r
+int MY_CDECL main(int numArgs, const char *args[])\r
+{\r
+  NT_CHECK\r
+\r
+  PrintStringLn(kCopyrightString);\r
+\r
+  if (numArgs < 3)\r
+  {\r
+    PrintStringLn(kHelpString);\r
+    return 1;\r
+  }\r
+  NWindows::NDLL::CLibrary lib;\r
+  if (!lib.Load(TEXT(kDllName)))\r
+  {\r
+    PrintError("Can not load 7-zip library");\r
+    return 1;\r
+  }\r
+  CreateObjectFunc createObjectFunc = (CreateObjectFunc)lib.GetProc("CreateObject");\r
+  if (createObjectFunc == 0)\r
+  {\r
+    PrintError("Can not get CreateObject");\r
+    return 1;\r
+  }\r
+\r
+  char c;\r
+  {\r
+    AString command = args[1];\r
+    if (command.Length() != 1)\r
+    {\r
+      PrintError("incorrect command");\r
+      return 1;\r
+    }\r
+    c = MyCharLower(command[0]);\r
+  }\r
+  UString archiveName = GetUnicodeString(args[2]);\r
+  if (c == 'a')\r
+  {\r
+    // create archive command\r
+    if (numArgs < 4)\r
+    {\r
+      PrintStringLn(kHelpString);\r
+      return 1;\r
+    }\r
+    CObjectVector<CDirItem> dirItems;\r
+    int i;\r
+    for (i = 3; i < numArgs; i++)\r
+    {\r
+      CDirItem di;\r
+      UString name = GetUnicodeString(args[i]);\r
+      \r
+      NFile::NFind::CFileInfoW fi;\r
+      if (!fi.Find(name))\r
+      {\r
+        PrintString(UString(L"Can't find file") + name);\r
+        return 1;\r
+      }\r
+\r
+      di.Attrib = fi.Attrib;\r
+      di.Size = fi.Size;\r
+      di.CTime = fi.CTime;\r
+      di.ATime = fi.ATime;\r
+      di.MTime = fi.MTime;\r
+      di.Name = name;\r
+      di.FullPath = name;\r
+      dirItems.Add(di);\r
+    }\r
+    COutFileStream *outFileStreamSpec = new COutFileStream;\r
+    CMyComPtr<IOutStream> outFileStream = outFileStreamSpec;\r
+    if (!outFileStreamSpec->Create(archiveName, false))\r
+    {\r
+      PrintError("can't create archive file");\r
+      return 1;\r
+    }\r
+\r
+    CMyComPtr<IOutArchive> outArchive;\r
+    if (createObjectFunc(&CLSID_CFormat7z, &IID_IOutArchive, (void **)&outArchive) != S_OK)\r
+    {\r
+      PrintError("Can not get class object");\r
+      return 1;\r
+    }\r
+\r
+    CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;\r
+    CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec);\r
+    updateCallbackSpec->Init(&dirItems);\r
+    // updateCallbackSpec->PasswordIsDefined = true;\r
+    // updateCallbackSpec->Password = L"1";\r
+\r
+    /*\r
+    {\r
+      const wchar_t *names[] =\r
+      {\r
+        L"s",\r
+        L"x"\r
+      };\r
+      const int kNumProps = sizeof(names) / sizeof(names[0]);\r
+      NWindows::NCOM::CPropVariant values[kNumProps] =\r
+      {\r
+        false,    // solid mode OFF\r
+        (UInt32)9 // compression level = 9 - ultra\r
+      };\r
+      CMyComPtr<ISetProperties> setProperties;\r
+      outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties);\r
+      if (!setProperties)\r
+      {\r
+        PrintError("ISetProperties unsupported");\r
+        return 1;\r
+      }\r
+      RINOK(setProperties->SetProperties(names, values, kNumProps));\r
+    }\r
+    */\r
+    \r
+    HRESULT result = outArchive->UpdateItems(outFileStream, dirItems.Size(), updateCallback);\r
+    updateCallbackSpec->Finilize();\r
+    if (result != S_OK)\r
+    {\r
+      PrintError("Update Error");\r
+      return 1;\r
+    }\r
+    for (i = 0; i < updateCallbackSpec->FailedFiles.Size(); i++)\r
+    {\r
+      PrintNewLine();\r
+      PrintString((UString)L"Error for file: " + updateCallbackSpec->FailedFiles[i]);\r
+    }\r
+    if (updateCallbackSpec->FailedFiles.Size() != 0)\r
+      return 1;\r
+  }\r
+  else\r
+  {\r
+    if (numArgs != 3)\r
+    {\r
+      PrintStringLn(kHelpString);\r
+      return 1;\r
+    }\r
+\r
+    bool listCommand;\r
+    if (c == 'l')\r
+      listCommand = true;\r
+    else if (c == 'x')\r
+      listCommand = false;\r
+    else\r
+    {\r
+      PrintError("incorrect command");\r
+      return 1;\r
+    }\r
+  \r
+    CMyComPtr<IInArchive> archive;\r
+    if (createObjectFunc(&CLSID_CFormat7z, &IID_IInArchive, (void **)&archive) != S_OK)\r
+    {\r
+      PrintError("Can not get class object");\r
+      return 1;\r
+    }\r
+    \r
+    CInFileStream *fileSpec = new CInFileStream;\r
+    CMyComPtr<IInStream> file = fileSpec;\r
+    \r
+    if (!fileSpec->Open(archiveName))\r
+    {\r
+      PrintError("Can not open archive file");\r
+      return 1;\r
+    }\r
+\r
+    {\r
+      CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback;\r
+      CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec);\r
+      openCallbackSpec->PasswordIsDefined = false;\r
+      // openCallbackSpec->PasswordIsDefined = true;\r
+      // openCallbackSpec->Password = L"1";\r
+      \r
+      if (archive->Open(file, 0, openCallback) != S_OK)\r
+      {\r
+        PrintError("Can not open archive");\r
+        return 1;\r
+      }\r
+    }\r
+    \r
+    if (listCommand)\r
+    {\r
+      // List command\r
+      UInt32 numItems = 0;\r
+      archive->GetNumberOfItems(&numItems);\r
+      for (UInt32 i = 0; i < numItems; i++)\r
+      {\r
+        {\r
+          // Get uncompressed size of file\r
+          NWindows::NCOM::CPropVariant prop;\r
+          archive->GetProperty(i, kpidSize, &prop);\r
+          UString s = ConvertPropVariantToString(prop);\r
+          PrintString(s);\r
+          PrintString("  ");\r
+        }\r
+        {\r
+          // Get name of file\r
+          NWindows::NCOM::CPropVariant prop;\r
+          archive->GetProperty(i, kpidPath, &prop);\r
+          UString s = ConvertPropVariantToString(prop);\r
+          PrintString(s);\r
+        }\r
+        PrintString("\n");\r
+      }\r
+    }\r
+    else\r
+    {\r
+      // Extract command\r
+      CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;\r
+      CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);\r
+      extractCallbackSpec->Init(archive, L""); // second parameter is output folder path\r
+      extractCallbackSpec->PasswordIsDefined = false;\r
+      // extractCallbackSpec->PasswordIsDefined = true;\r
+      // extractCallbackSpec->Password = L"1";\r
+      HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback);\r
+      if (result != S_OK)\r
+      {\r
+        PrintError("Extract Error");\r
+        return 1;\r
+      }\r
+    }\r
+  }\r
+  return 0;\r
+}\r
diff --git a/CPP/7zip/UI/Client7z/Client7z.dsp b/CPP/7zip/UI/Client7z/Client7z.dsp
new file mode 100755 (executable)
index 0000000..34eb42b
--- /dev/null
@@ -0,0 +1,226 @@
+# Microsoft Developer Studio Project File - Name="Client7z" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=Client7z - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "Client7z.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "Client7z.mak" CFG="Client7z - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "Client7z - Win32 Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "Client7z - Win32 Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "Client7z - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c\r
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# 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\r
+\r
+!ELSEIF  "$(CFG)" == "Client7z - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c\r
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x419 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# 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\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "Client7z - Win32 Release"\r
+# Name "Client7z - Win32 Debug"\r
+# Begin Group "Spec"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.cpp\r
+# ADD CPP /Yc"stdafx.h"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Windows"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantConversions.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantConversions.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "7zip Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=.\Client7z.cpp\r
+# End Source File\r
+# End Target\r
+# End Project\r
diff --git a/CPP/7zip/UI/Client7z/Client7z.dsw b/CPP/7zip/UI/Client7z/Client7z.dsw
new file mode 100755 (executable)
index 0000000..4c26851
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "Client7z"=.\Client7z.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/CPP/7zip/UI/Client7z/StdAfx.cpp b/CPP/7zip/UI/Client7z/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..c6d3b1f
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/UI/Client7z/StdAfx.h b/CPP/7zip/UI/Client7z/StdAfx.h
new file mode 100755 (executable)
index 0000000..2edddf4
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include <windows.h>\r
+#include <stdio.h>\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Client7z/makefile b/CPP/7zip/UI/Client7z/makefile
new file mode 100755 (executable)
index 0000000..e3a8239
--- /dev/null
@@ -0,0 +1,45 @@
+PROG = 7z.exe\r
+MY_CONSOLE = 1\r
+CFLAGS = $(CFLAGS) -I ../../../\r
+\r
+CONSOLE_OBJS = \\r
+  $O\Client7z.obj \\r
+\r
+COMMON_OBJS = \\r
+  $O\IntToString.obj \\r
+  $O\NewHandler.obj \\r
+  $O\MyString.obj \\r
+  $O\StringConvert.obj \\r
+  $O\StringToInt.obj \\r
+  $O\MyVector.obj \\r
+  $O\Wildcard.obj \\r
+\r
+WIN_OBJS = \\r
+  $O\DLL.obj \\r
+  $O\FileDir.obj \\r
+  $O\FileFind.obj \\r
+  $O\FileIO.obj \\r
+  $O\FileName.obj \\r
+  $O\PropVariant.obj \\r
+  $O\PropVariantConversions.obj \\r
+\r
+7ZIP_COMMON_OBJS = \\r
+  $O\FileStreams.obj \\r
+\r
+OBJS = \\r
+  $O\StdAfx.obj \\r
+  $(CONSOLE_OBJS) \\r
+  $(COMMON_OBJS) \\r
+  $(WIN_OBJS) \\r
+  $(7ZIP_COMMON_OBJS) \\r
+\r
+!include "../../../Build.mak"\r
+\r
+$(CONSOLE_OBJS): $(*B).cpp\r
+       $(COMPL)\r
+$(COMMON_OBJS): ../../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_OBJS): ../../../Windows/$(*B).cpp\r
+       $(COMPL)\r
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp\r
+       $(COMPL)\r
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
new file mode 100755 (executable)
index 0000000..7fd012b
--- /dev/null
@@ -0,0 +1,1042 @@
+// ArchiveCommandLine.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#ifdef _WIN32\r
+#ifndef UNDER_CE\r
+#include <io.h>\r
+#endif\r
+#endif\r
+#include <stdio.h>\r
+\r
+#include "Common/ListFileUtils.h"\r
+#include "Common/StringConvert.h"\r
+#include "Common/StringToInt.h"\r
+\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileName.h"\r
+#ifdef _WIN32\r
+#include "Windows/FileMapping.h"\r
+#include "Windows/Synchronization.h"\r
+#endif\r
+\r
+#include "ArchiveCommandLine.h"\r
+#include "EnumDirItems.h"\r
+#include "SortUtils.h"\r
+#include "Update.h"\r
+#include "UpdateAction.h"\r
+\r
+extern bool g_CaseSensitive;\r
+\r
+#ifdef UNDER_CE\r
+\r
+#define MY_IS_TERMINAL(x) false;\r
+\r
+#else\r
+\r
+#if _MSC_VER >= 1400\r
+#define MY_isatty_fileno(x) _isatty(_fileno(x))\r
+#else\r
+#define MY_isatty_fileno(x) isatty(fileno(x))\r
+#endif\r
+\r
+#define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0);\r
+\r
+#endif\r
+\r
+using namespace NCommandLineParser;\r
+using namespace NWindows;\r
+using namespace NFile;\r
+\r
+int g_CodePage = -1;\r
+\r
+namespace NKey {\r
+enum Enum\r
+{\r
+  kHelp1 = 0,\r
+  kHelp2,\r
+  kHelp3,\r
+  kDisableHeaders,\r
+  kDisablePercents,\r
+  kArchiveType,\r
+  kYes,\r
+  #ifndef _NO_CRYPTO\r
+  kPassword,\r
+  #endif\r
+  kProperty,\r
+  kOutputDir,\r
+  kWorkingDir,\r
+  kInclude,\r
+  kExclude,\r
+  kArInclude,\r
+  kArExclude,\r
+  kNoArName,\r
+  kUpdate,\r
+  kVolume,\r
+  kRecursed,\r
+  kSfx,\r
+  kStdIn,\r
+  kStdOut,\r
+  kOverwrite,\r
+  kEmail,\r
+  kShowDialog,\r
+  kLargePages,\r
+  kListfileCharSet,\r
+  kConsoleCharSet,\r
+  kTechMode,\r
+  kShareForWrite,\r
+  kCaseSensitive,\r
+  kCalcCrc\r
+};\r
+\r
+}\r
+\r
+\r
+static const wchar_t kRecursedIDChar = 'R';\r
+static const wchar_t *kRecursedPostCharSet = L"0-";\r
+\r
+namespace NRecursedPostCharIndex {\r
+  enum EEnum\r
+  {\r
+    kWildCardRecursionOnly = 0,\r
+    kNoRecursion = 1\r
+  };\r
+}\r
+\r
+static const char kImmediateNameID = '!';\r
+static const char kMapNameID = '#';\r
+static const char kFileListID = '@';\r
+\r
+static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be\r
+static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be\r
+\r
+static const wchar_t *kOverwritePostCharSet = L"asut";\r
+\r
+NExtract::NOverwriteMode::EEnum k_OverwriteModes[] =\r
+{\r
+  NExtract::NOverwriteMode::kWithoutPrompt,\r
+  NExtract::NOverwriteMode::kSkipExisting,\r
+  NExtract::NOverwriteMode::kAutoRename,\r
+  NExtract::NOverwriteMode::kAutoRenameExisting\r
+};\r
+\r
+static const CSwitchForm kSwitchForms[] =\r
+  {\r
+    { L"?",  NSwitchType::kSimple, false },\r
+    { L"H",  NSwitchType::kSimple, false },\r
+    { L"-HELP",  NSwitchType::kSimple, false },\r
+    { L"BA", NSwitchType::kSimple, false },\r
+    { L"BD", NSwitchType::kSimple, false },\r
+    { L"T",  NSwitchType::kUnLimitedPostString, false, 1 },\r
+    { L"Y",  NSwitchType::kSimple, false },\r
+    #ifndef _NO_CRYPTO\r
+    { L"P",  NSwitchType::kUnLimitedPostString, false, 0 },\r
+    #endif\r
+    { L"M",  NSwitchType::kUnLimitedPostString, true, 1 },\r
+    { L"O",  NSwitchType::kUnLimitedPostString, false, 1 },\r
+    { L"W",  NSwitchType::kUnLimitedPostString, false, 0 },\r
+    { L"I",  NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},\r
+    { L"X",  NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},\r
+    { L"AI", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},\r
+    { L"AX", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},\r
+    { L"AN", NSwitchType::kSimple, false },\r
+    { L"U",  NSwitchType::kUnLimitedPostString, true, 1},\r
+    { L"V",  NSwitchType::kUnLimitedPostString, true, 1},\r
+    { L"R",  NSwitchType::kPostChar, false, 0, 0, kRecursedPostCharSet },\r
+    { L"SFX", NSwitchType::kUnLimitedPostString, false, 0 },\r
+    { L"SI", NSwitchType::kUnLimitedPostString, false, 0 },\r
+    { L"SO", NSwitchType::kSimple, false, 0 },\r
+    { L"AO", NSwitchType::kPostChar, false, 1, 1, kOverwritePostCharSet},\r
+    { L"SEML", NSwitchType::kUnLimitedPostString, false, 0},\r
+    { L"AD",  NSwitchType::kSimple, false },\r
+    { L"SLP", NSwitchType::kUnLimitedPostString, false, 0},\r
+    { L"SCS", NSwitchType::kUnLimitedPostString, false, 0},\r
+    { L"SCC", NSwitchType::kUnLimitedPostString, false, 0},\r
+    { L"SLT", NSwitchType::kSimple, false },\r
+    { L"SSW", NSwitchType::kSimple, false },\r
+    { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" },\r
+    { L"SCRC", NSwitchType::kSimple, false }\r
+  };\r
+\r
+static const CCommandForm g_CommandForms[] =\r
+{\r
+  { L"A", false },\r
+  { L"U", false },\r
+  { L"D", false },\r
+  { L"T", false },\r
+  { L"E", false },\r
+  { L"X", false },\r
+  { L"L", false },\r
+  { L"B", false },\r
+  { L"I", false }\r
+};\r
+\r
+static const int kNumCommandForms = sizeof(g_CommandForms) /  sizeof(g_CommandForms[0]);\r
+\r
+static const wchar_t *kUniversalWildcard = L"*";\r
+static const int kMinNonSwitchWords = 1;\r
+static const int kCommandIndex = 0;\r
+\r
+// ---------------------------\r
+// exception messages\r
+\r
+static const char *kUserErrorMessage  = "Incorrect command line";\r
+static const char *kCannotFindListFile = "Cannot find listfile";\r
+static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch.";\r
+static const char *kIncorrectWildCardInListFile = "Incorrect wildcard in listfile";\r
+static const char *kIncorrectWildCardInCommandLine  = "Incorrect wildcard in command line";\r
+static const char *kTerminalOutError = "I won't write compressed data to a terminal";\r
+static const char *kSameTerminalError = "I won't write data and program's messages to same terminal";\r
+static const char *kEmptyFilePath = "Empty file path";\r
+\r
+static void ThrowException(const char *errorMessage)\r
+{\r
+  throw CArchiveCommandLineException(errorMessage);\r
+}\r
+\r
+static void ThrowUserErrorException()\r
+{\r
+  ThrowException(kUserErrorMessage);\r
+}\r
+\r
+// ---------------------------\r
+\r
+bool CArchiveCommand::IsFromExtractGroup() const\r
+{\r
+  switch(CommandType)\r
+  {\r
+    case NCommandType::kTest:\r
+    case NCommandType::kExtract:\r
+    case NCommandType::kFullExtract:\r
+      return true;\r
+    default:\r
+      return false;\r
+  }\r
+}\r
+\r
+NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const\r
+{\r
+  switch(CommandType)\r
+  {\r
+    case NCommandType::kTest:\r
+    case NCommandType::kFullExtract:\r
+      return NExtract::NPathMode::kFullPathnames;\r
+    default:\r
+      return NExtract::NPathMode::kNoPathnames;\r
+  }\r
+}\r
+\r
+bool CArchiveCommand::IsFromUpdateGroup() const\r
+{\r
+  return (CommandType == NCommandType::kAdd ||\r
+    CommandType == NCommandType::kUpdate ||\r
+    CommandType == NCommandType::kDelete);\r
+}\r
+\r
+static NRecursedType::EEnum GetRecursedTypeFromIndex(int index)\r
+{\r
+  switch (index)\r
+  {\r
+    case NRecursedPostCharIndex::kWildCardRecursionOnly:\r
+      return NRecursedType::kWildCardOnlyRecursed;\r
+    case NRecursedPostCharIndex::kNoRecursion:\r
+      return NRecursedType::kNonRecursed;\r
+    default:\r
+      return NRecursedType::kRecursed;\r
+  }\r
+}\r
+\r
+static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command)\r
+{\r
+  UString commandStringUpper = commandString;\r
+  commandStringUpper.MakeUpper();\r
+  UString postString;\r
+  int commandIndex = ParseCommand(kNumCommandForms, g_CommandForms, commandStringUpper,\r
+      postString) ;\r
+  if (commandIndex < 0)\r
+    return false;\r
+  command.CommandType = (NCommandType::EEnum)commandIndex;\r
+  return true;\r
+}\r
+\r
+// ------------------------------------------------------------------\r
+// filenames functions\r
+\r
+static void AddNameToCensor(NWildcard::CCensor &wildcardCensor,\r
+    const UString &name, bool include, NRecursedType::EEnum type)\r
+{\r
+  bool recursed = false;\r
+\r
+  switch (type)\r
+  {\r
+    case NRecursedType::kWildCardOnlyRecursed:\r
+      recursed = DoesNameContainWildCard(name);\r
+      break;\r
+    case NRecursedType::kRecursed:\r
+      recursed = true;\r
+      break;\r
+  }\r
+  wildcardCensor.AddItem(include, name, recursed);\r
+}\r
+\r
+static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor,\r
+    LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage)\r
+{\r
+  UStringVector names;\r
+  if (!NFind::DoesFileExist(fileName))\r
+    throw kCannotFindListFile;\r
+  if (!ReadNamesFromListFile(fileName, names, codePage))\r
+    throw kIncorrectListFile;\r
+  for (int i = 0; i < names.Size(); i++)\r
+    AddNameToCensor(wildcardCensor, names[i], include, type);\r
+}\r
+\r
+static void AddToCensorFromNonSwitchesStrings(\r
+    int startIndex,\r
+    NWildcard::CCensor &wildcardCensor,\r
+    const UStringVector &nonSwitchStrings, NRecursedType::EEnum type,\r
+    bool thereAreSwitchIncludes, UINT codePage)\r
+{\r
+  if (nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes))\r
+    AddNameToCensor(wildcardCensor, kUniversalWildcard, true, type);\r
+  for (int i = startIndex; i < nonSwitchStrings.Size(); i++)\r
+  {\r
+    const UString &s = nonSwitchStrings[i];\r
+    if (s.IsEmpty())\r
+      throw kEmptyFilePath;\r
+    if (s[0] == kFileListID)\r
+      AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage);\r
+    else\r
+      AddNameToCensor(wildcardCensor, s, true, type);\r
+  }\r
+}\r
+\r
+#ifdef _WIN32\r
+static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor,\r
+    const UString &switchParam, bool include,\r
+    NRecursedType::EEnum commonRecursedType)\r
+{\r
+  int splitPos = switchParam.Find(L':');\r
+  if (splitPos < 0)\r
+    ThrowUserErrorException();\r
+  UString mappingName = switchParam.Left(splitPos);\r
+  \r
+  UString switchParam2 = switchParam.Mid(splitPos + 1);\r
+  splitPos = switchParam2.Find(L':');\r
+  if (splitPos < 0)\r
+    ThrowUserErrorException();\r
+  \r
+  UString mappingSize = switchParam2.Left(splitPos);\r
+  UString eventName = switchParam2.Mid(splitPos + 1);\r
+  \r
+  UInt64 dataSize64 = ConvertStringToUInt64(mappingSize, NULL);\r
+  UInt32 dataSize = (UInt32)dataSize64;\r
+  {\r
+    CFileMapping fileMapping;\r
+    if (fileMapping.Open(FILE_MAP_READ, GetSystemString(mappingName)) != 0)\r
+      ThrowException("Can not open mapping");\r
+    LPVOID data = fileMapping.Map(FILE_MAP_READ, 0, dataSize);\r
+    if (data == NULL)\r
+      ThrowException("MapViewOfFile error");\r
+    try\r
+    {\r
+      const wchar_t *curData = (const wchar_t *)data;\r
+      if (*curData != 0)\r
+        ThrowException("Incorrect mapping data");\r
+      UInt32 numChars = dataSize / sizeof(wchar_t);\r
+      UString name;\r
+      for (UInt32 i = 1; i < numChars; i++)\r
+      {\r
+        wchar_t c = curData[i];\r
+        if (c == L'\0')\r
+        {\r
+          AddNameToCensor(wildcardCensor, name, include, commonRecursedType);\r
+          name.Empty();\r
+        }\r
+        else\r
+          name += c;\r
+      }\r
+      if (!name.IsEmpty())\r
+        ThrowException("data error");\r
+    }\r
+    catch(...)\r
+    {\r
+      UnmapViewOfFile(data);\r
+      throw;\r
+    }\r
+    UnmapViewOfFile(data);\r
+  }\r
+  \r
+  {\r
+    NSynchronization::CManualResetEvent event;\r
+    if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName)) == S_OK)\r
+      event.Set();\r
+  }\r
+}\r
+#endif\r
+\r
+static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor,\r
+    const UStringVector &strings, bool include,\r
+    NRecursedType::EEnum commonRecursedType, UINT codePage)\r
+{\r
+  for (int i = 0; i < strings.Size(); i++)\r
+  {\r
+    const UString &name = strings[i];\r
+    NRecursedType::EEnum recursedType;\r
+    int pos = 0;\r
+    if (name.Length() < kSomeCludePostStringMinSize)\r
+      ThrowUserErrorException();\r
+    if (::MyCharUpper(name[pos]) == kRecursedIDChar)\r
+    {\r
+      pos++;\r
+      int index = UString(kRecursedPostCharSet).Find(name[pos]);\r
+      recursedType = GetRecursedTypeFromIndex(index);\r
+      if (index >= 0)\r
+        pos++;\r
+    }\r
+    else\r
+      recursedType = commonRecursedType;\r
+    if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize)\r
+      ThrowUserErrorException();\r
+    UString tail = name.Mid(pos + 1);\r
+    if (name[pos] == kImmediateNameID)\r
+      AddNameToCensor(wildcardCensor, tail, include, recursedType);\r
+    else if (name[pos] == kFileListID)\r
+      AddToCensorFromListFile(wildcardCensor, tail, include, recursedType, codePage);\r
+    #ifdef _WIN32\r
+    else if (name[pos] == kMapNameID)\r
+      ParseMapWithPaths(wildcardCensor, tail, include, recursedType);\r
+    #endif\r
+    else\r
+      ThrowUserErrorException();\r
+  }\r
+}\r
+\r
+#ifdef _WIN32\r
+\r
+// This code converts all short file names to long file names.\r
+\r
+static void ConvertToLongName(const UString &prefix, UString &name)\r
+{\r
+  if (name.IsEmpty() || DoesNameContainWildCard(name))\r
+    return;\r
+  NFind::CFileInfoW fi;\r
+  if (fi.Find(prefix + name))\r
+    name = fi.Name;\r
+}\r
+\r
+static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items)\r
+{\r
+  for (int i = 0; i < items.Size(); i++)\r
+  {\r
+    NWildcard::CItem &item = items[i];\r
+    if (item.Recursive || item.PathParts.Size() != 1)\r
+      continue;\r
+    ConvertToLongName(prefix, item.PathParts.Front());\r
+  }\r
+}\r
+\r
+static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node)\r
+{\r
+  ConvertToLongNames(prefix, node.IncludeItems);\r
+  ConvertToLongNames(prefix, node.ExcludeItems);\r
+  int i;\r
+  for (i = 0; i < node.SubNodes.Size(); i++)\r
+    ConvertToLongName(prefix, node.SubNodes[i].Name);\r
+  // mix folders with same name\r
+  for (i = 0; i < node.SubNodes.Size(); i++)\r
+  {\r
+    NWildcard::CCensorNode &nextNode1 = node.SubNodes[i];\r
+    for (int j = i + 1; j < node.SubNodes.Size();)\r
+    {\r
+      const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j];\r
+      if (nextNode1.Name.CompareNoCase(nextNode2.Name) == 0)\r
+      {\r
+        nextNode1.IncludeItems += nextNode2.IncludeItems;\r
+        nextNode1.ExcludeItems += nextNode2.ExcludeItems;\r
+        node.SubNodes.Delete(j);\r
+      }\r
+      else\r
+        j++;\r
+    }\r
+  }\r
+  for (i = 0; i < node.SubNodes.Size(); i++)\r
+  {\r
+    NWildcard::CCensorNode &nextNode = node.SubNodes[i];\r
+    ConvertToLongNames(prefix + nextNode.Name + wchar_t(NFile::NName::kDirDelimiter), nextNode);\r
+  }\r
+}\r
+\r
+static void ConvertToLongNames(NWildcard::CCensor &censor)\r
+{\r
+  for (int i = 0; i < censor.Pairs.Size(); i++)\r
+  {\r
+    NWildcard::CPair &pair = censor.Pairs[i];\r
+    ConvertToLongNames(pair.Prefix, pair.Head);\r
+  }\r
+}\r
+\r
+#endif\r
+\r
+static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i)\r
+{\r
+  switch(i)\r
+  {\r
+    case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore;\r
+    case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy;\r
+    case NUpdateArchive::NPairAction::kCompress: return NUpdateArchive::NPairAction::kCompress;\r
+    case NUpdateArchive::NPairAction::kCompressAsAnti: return NUpdateArchive::NPairAction::kCompressAsAnti;\r
+  }\r
+  throw 98111603;\r
+}\r
+\r
+const UString kUpdatePairStateIDSet = L"PQRXYZW";\r
+const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1};\r
+\r
+const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti\r
+\r
+const wchar_t *kUpdateIgnoreItselfPostStringID = L"-";\r
+const wchar_t kUpdateNewArchivePostCharID = '!';\r
+\r
+\r
+static bool ParseUpdateCommandString2(const UString &command,\r
+    NUpdateArchive::CActionSet &actionSet, UString &postString)\r
+{\r
+  for (int i = 0; i < command.Length();)\r
+  {\r
+    wchar_t c = MyCharUpper(command[i]);\r
+    int statePos = kUpdatePairStateIDSet.Find(c);\r
+    if (statePos < 0)\r
+    {\r
+      postString = command.Mid(i);\r
+      return true;\r
+    }\r
+    i++;\r
+    if (i >= command.Length())\r
+      return false;\r
+    int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i]));\r
+    if (actionPos < 0)\r
+      return false;\r
+    actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos);\r
+    if (kUpdatePairStateNotSupportedActions[statePos] == actionPos)\r
+      return false;\r
+    i++;\r
+  }\r
+  postString.Empty();\r
+  return true;\r
+}\r
+\r
+static void ParseUpdateCommandString(CUpdateOptions &options,\r
+    const UStringVector &updatePostStrings,\r
+    const NUpdateArchive::CActionSet &defaultActionSet)\r
+{\r
+  for (int i = 0; i < updatePostStrings.Size(); i++)\r
+  {\r
+    const UString &updateString = updatePostStrings[i];\r
+    if (updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0)\r
+    {\r
+      if (options.UpdateArchiveItself)\r
+      {\r
+        options.UpdateArchiveItself = false;\r
+        options.Commands.Delete(0);\r
+      }\r
+    }\r
+    else\r
+    {\r
+      NUpdateArchive::CActionSet actionSet = defaultActionSet;\r
+\r
+      UString postString;\r
+      if (!ParseUpdateCommandString2(updateString, actionSet, postString))\r
+        ThrowUserErrorException();\r
+      if (postString.IsEmpty())\r
+      {\r
+        if (options.UpdateArchiveItself)\r
+          options.Commands[0].ActionSet = actionSet;\r
+      }\r
+      else\r
+      {\r
+        if (MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID)\r
+          ThrowUserErrorException();\r
+        CUpdateArchiveCommand uc;\r
+        UString archivePath = postString.Mid(1);\r
+        if (archivePath.IsEmpty())\r
+          ThrowUserErrorException();\r
+        uc.UserArchivePath = archivePath;\r
+        uc.ActionSet = actionSet;\r
+        options.Commands.Add(uc);\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+static const char kByteSymbol = 'B';\r
+static const char kKiloSymbol = 'K';\r
+static const char kMegaSymbol = 'M';\r
+static const char kGigaSymbol = 'G';\r
+\r
+static bool ParseComplexSize(const UString &src, UInt64 &result)\r
+{\r
+  UString s = src;\r
+  s.MakeUpper();\r
+\r
+  const wchar_t *start = s;\r
+  const wchar_t *end;\r
+  UInt64 number = ConvertStringToUInt64(start, &end);\r
+  int numDigits = (int)(end - start);\r
+  if (numDigits == 0 || s.Length() > numDigits + 1)\r
+    return false;\r
+  if (s.Length() == numDigits)\r
+  {\r
+    result = number;\r
+    return true;\r
+  }\r
+  int numBits;\r
+  switch (s[numDigits])\r
+  {\r
+    case kByteSymbol:\r
+      result = number;\r
+      return true;\r
+    case kKiloSymbol:\r
+      numBits = 10;\r
+      break;\r
+    case kMegaSymbol:\r
+      numBits = 20;\r
+      break;\r
+    case kGigaSymbol:\r
+      numBits = 30;\r
+      break;\r
+    default:\r
+      return false;\r
+  }\r
+  if (number >= ((UInt64)1 << (64 - numBits)))\r
+    return false;\r
+  result = number << numBits;\r
+  return true;\r
+}\r
+\r
+static void SetAddCommandOptions(\r
+    NCommandType::EEnum commandType,\r
+    const CParser &parser,\r
+    CUpdateOptions &options)\r
+{\r
+  NUpdateArchive::CActionSet defaultActionSet;\r
+  switch(commandType)\r
+  {\r
+    case NCommandType::kAdd:\r
+      defaultActionSet = NUpdateArchive::kAddActionSet;\r
+      break;\r
+    case NCommandType::kDelete:\r
+      defaultActionSet = NUpdateArchive::kDeleteActionSet;\r
+      break;\r
+    default:\r
+      defaultActionSet = NUpdateArchive::kUpdateActionSet;\r
+  }\r
+  \r
+  options.UpdateArchiveItself = true;\r
+  \r
+  options.Commands.Clear();\r
+  CUpdateArchiveCommand updateMainCommand;\r
+  updateMainCommand.ActionSet = defaultActionSet;\r
+  options.Commands.Add(updateMainCommand);\r
+  if (parser[NKey::kUpdate].ThereIs)\r
+    ParseUpdateCommandString(options, parser[NKey::kUpdate].PostStrings,\r
+        defaultActionSet);\r
+  if (parser[NKey::kWorkingDir].ThereIs)\r
+  {\r
+    const UString &postString = parser[NKey::kWorkingDir].PostStrings[0];\r
+    if (postString.IsEmpty())\r
+      NDirectory::MyGetTempPath(options.WorkingDir);\r
+    else\r
+      options.WorkingDir = postString;\r
+  }\r
+  options.SfxMode = parser[NKey::kSfx].ThereIs;\r
+  if (options.SfxMode)\r
+    options.SfxModule = parser[NKey::kSfx].PostStrings[0];\r
+\r
+  if (parser[NKey::kVolume].ThereIs)\r
+  {\r
+    const UStringVector &sv = parser[NKey::kVolume].PostStrings;\r
+    for (int i = 0; i < sv.Size(); i++)\r
+    {\r
+      UInt64 size;\r
+      if (!ParseComplexSize(sv[i], size))\r
+        ThrowException("Incorrect volume size");\r
+      options.VolumesSizes.Add(size);\r
+    }\r
+  }\r
+}\r
+\r
+static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &properties)\r
+{\r
+  if (parser[NKey::kProperty].ThereIs)\r
+  {\r
+    // options.MethodMode.Properties.Clear();\r
+    for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++)\r
+    {\r
+      CProperty property;\r
+      const UString &postString = parser[NKey::kProperty].PostStrings[i];\r
+      int index = postString.Find(L'=');\r
+      if (index < 0)\r
+        property.Name = postString;\r
+      else\r
+      {\r
+        property.Name = postString.Left(index);\r
+        property.Value = postString.Mid(index + 1);\r
+      }\r
+      properties.Add(property);\r
+    }\r
+  }\r
+}\r
+\r
+CArchiveCommandLineParser::CArchiveCommandLineParser():\r
+  parser(sizeof(kSwitchForms) / sizeof(kSwitchForms[0])) {}\r
+\r
+void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings,\r
+    CArchiveCommandLineOptions &options)\r
+{\r
+  try\r
+  {\r
+    parser.ParseStrings(kSwitchForms, commandStrings);\r
+  }\r
+  catch(...)\r
+  {\r
+    ThrowUserErrorException();\r
+  }\r
+\r
+  options.IsInTerminal = MY_IS_TERMINAL(stdin);\r
+  options.IsStdOutTerminal = MY_IS_TERMINAL(stdout);\r
+  options.IsStdErrTerminal = MY_IS_TERMINAL(stderr);\r
+  options.StdInMode = parser[NKey::kStdIn].ThereIs;\r
+  options.StdOutMode = parser[NKey::kStdOut].ThereIs;\r
+  options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs;\r
+  options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs  || parser[NKey::kHelp3].ThereIs;\r
+\r
+  #ifdef _WIN32\r
+  options.LargePages = false;\r
+  if (parser[NKey::kLargePages].ThereIs)\r
+  {\r
+    const UString &postString = parser[NKey::kLargePages].PostStrings.Front();\r
+    if (postString.IsEmpty())\r
+      options.LargePages = true;\r
+  }\r
+  #endif\r
+}\r
+\r
+struct CCodePagePair\r
+{\r
+  const wchar_t *Name;\r
+  UINT CodePage;\r
+};\r
+\r
+static CCodePagePair g_CodePagePairs[] =\r
+{\r
+  { L"UTF-8", CP_UTF8 },\r
+  { L"WIN", CP_ACP },\r
+  { L"DOS", CP_OEMCP }\r
+};\r
+\r
+static int FindCharset(const NCommandLineParser::CParser &parser, int keyIndex, int defaultVal)\r
+{\r
+  if (!parser[keyIndex].ThereIs)\r
+    return defaultVal;\r
+\r
+  UString name = parser[keyIndex].PostStrings.Back();\r
+  name.MakeUpper();\r
+  int i;\r
+  for (i = 0; i < sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]); i++)\r
+  {\r
+    const CCodePagePair &pair = g_CodePagePairs[i];\r
+    if (name.Compare(pair.Name) == 0)\r
+      return pair.CodePage;\r
+  }\r
+  if (i == sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]))\r
+    ThrowUserErrorException();\r
+  return -1;\r
+}\r
+\r
+static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v)\r
+{\r
+  const wchar_t *end;\r
+  UInt64 number = ConvertStringToUInt64(s, &end);\r
+  if (*end != 0)\r
+    return false;\r
+  if (number > (UInt32)0xFFFFFFFF)\r
+    return false;\r
+  v = (UInt32)number;\r
+  return true;\r
+}\r
+\r
+void EnumerateDirItemsAndSort(NWildcard::CCensor &wildcardCensor,\r
+    UStringVector &sortedPaths,\r
+    UStringVector &sortedFullPaths)\r
+{\r
+  UStringVector paths;\r
+  {\r
+    CDirItems dirItems;\r
+    {\r
+      UStringVector errorPaths;\r
+      CRecordVector<DWORD> errorCodes;\r
+      HRESULT res = EnumerateItems(wildcardCensor, dirItems, NULL, errorPaths, errorCodes);\r
+      if (res != S_OK || errorPaths.Size() > 0)\r
+        throw "cannot find archive";\r
+    }\r
+    for (int i = 0; i < dirItems.Items.Size(); i++)\r
+    {\r
+      const CDirItem &dirItem = dirItems.Items[i];\r
+      if (!dirItem.IsDir())\r
+        paths.Add(dirItems.GetPhyPath(i));\r
+    }\r
+  }\r
+  \r
+  if (paths.Size() == 0)\r
+    throw "there is no such archive";\r
+  \r
+  UStringVector fullPaths;\r
+  \r
+  int i;\r
+  for (i = 0; i < paths.Size(); i++)\r
+  {\r
+    UString fullPath;\r
+    NFile::NDirectory::MyGetFullPathName(paths[i], fullPath);\r
+    fullPaths.Add(fullPath);\r
+  }\r
+  CIntVector indices;\r
+  SortFileNames(fullPaths, indices);\r
+  sortedPaths.Reserve(indices.Size());\r
+  sortedFullPaths.Reserve(indices.Size());\r
+  for (i = 0; i < indices.Size(); i++)\r
+  {\r
+    int index = indices[i];\r
+    sortedPaths.Add(paths[index]);\r
+    sortedFullPaths.Add(fullPaths[index]);\r
+  }\r
+}\r
+\r
+void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options)\r
+{\r
+  const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;\r
+  int numNonSwitchStrings = nonSwitchStrings.Size();\r
+  if (numNonSwitchStrings < kMinNonSwitchWords)\r
+    ThrowUserErrorException();\r
+\r
+  if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command))\r
+    ThrowUserErrorException();\r
+\r
+  options.TechMode = parser[NKey::kTechMode].ThereIs;\r
+  options.CalcCrc = parser[NKey::kCalcCrc].ThereIs;\r
+\r
+  if (parser[NKey::kCaseSensitive].ThereIs)\r
+    g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0);\r
+\r
+  NRecursedType::EEnum recursedType;\r
+  if (parser[NKey::kRecursed].ThereIs)\r
+    recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex);\r
+  else\r
+    recursedType = NRecursedType::kNonRecursed;\r
+\r
+  g_CodePage = FindCharset(parser, NKey::kConsoleCharSet, -1);\r
+  UINT codePage = FindCharset(parser, NKey::kListfileCharSet, CP_UTF8);\r
+\r
+  bool thereAreSwitchIncludes = false;\r
+  if (parser[NKey::kInclude].ThereIs)\r
+  {\r
+    thereAreSwitchIncludes = true;\r
+    AddSwitchWildCardsToCensor(options.WildcardCensor,\r
+        parser[NKey::kInclude].PostStrings, true, recursedType, codePage);\r
+  }\r
+  if (parser[NKey::kExclude].ThereIs)\r
+    AddSwitchWildCardsToCensor(options.WildcardCensor,\r
+        parser[NKey::kExclude].PostStrings, false, recursedType, codePage);\r
\r
+  int curCommandIndex = kCommandIndex + 1;\r
+  bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs &&\r
+      options.Command.CommandType != NCommandType::kBenchmark &&\r
+      options.Command.CommandType != NCommandType::kInfo;\r
+\r
+  bool isExtractGroupCommand = options.Command.IsFromExtractGroup();\r
+  bool isExtractOrList = isExtractGroupCommand || options.Command.CommandType == NCommandType::kList;\r
+\r
+  if (isExtractOrList && options.StdInMode)\r
+    thereIsArchiveName = false;\r
+\r
+  if (thereIsArchiveName)\r
+  {\r
+    if (curCommandIndex >= numNonSwitchStrings)\r
+      ThrowUserErrorException();\r
+    options.ArchiveName = nonSwitchStrings[curCommandIndex++];\r
+    if (options.ArchiveName.IsEmpty())\r
+      ThrowUserErrorException();\r
+  }\r
+\r
+  AddToCensorFromNonSwitchesStrings(\r
+      curCommandIndex, options.WildcardCensor,\r
+      nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage);\r
+\r
+  options.YesToAll = parser[NKey::kYes].ThereIs;\r
+\r
+\r
+  #ifndef _NO_CRYPTO\r
+  options.PasswordEnabled = parser[NKey::kPassword].ThereIs;\r
+  if (options.PasswordEnabled)\r
+    options.Password = parser[NKey::kPassword].PostStrings[0];\r
+  #endif\r
+\r
+  options.ShowDialog = parser[NKey::kShowDialog].ThereIs;\r
+\r
+  if (parser[NKey::kArchiveType].ThereIs)\r
+    options.ArcType = parser[NKey::kArchiveType].PostStrings[0];\r
+\r
+  if (isExtractOrList)\r
+  {\r
+    if (!options.WildcardCensor.AllAreRelative())\r
+      ThrowException("Cannot use absolute pathnames for this command");\r
+\r
+    NWildcard::CCensor archiveWildcardCensor;\r
+\r
+    if (parser[NKey::kArInclude].ThereIs)\r
+      AddSwitchWildCardsToCensor(archiveWildcardCensor,\r
+          parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage);\r
+    if (parser[NKey::kArExclude].ThereIs)\r
+      AddSwitchWildCardsToCensor(archiveWildcardCensor,\r
+          parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage);\r
+\r
+    if (thereIsArchiveName)\r
+      AddNameToCensor(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed);\r
+\r
+    #ifdef _WIN32\r
+    ConvertToLongNames(archiveWildcardCensor);\r
+    #endif\r
+\r
+    archiveWildcardCensor.ExtendExclude();\r
+\r
+    if (options.StdInMode)\r
+    {\r
+      UString arcName = parser[NKey::kStdIn].PostStrings.Front();\r
+      options.ArchivePathsSorted.Add(arcName);\r
+      options.ArchivePathsFullSorted.Add(arcName);\r
+    }\r
+    else\r
+    {\r
+      EnumerateDirItemsAndSort(archiveWildcardCensor,\r
+        options.ArchivePathsSorted,\r
+        options.ArchivePathsFullSorted);\r
+    }\r
+    \r
+    if (isExtractGroupCommand)\r
+    {\r
+      SetMethodOptions(parser, options.ExtractProperties);\r
+      if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal)\r
+        throw kSameTerminalError;\r
+      if (parser[NKey::kOutputDir].ThereIs)\r
+      {\r
+        options.OutputDir = parser[NKey::kOutputDir].PostStrings[0];\r
+        NFile::NName::NormalizeDirPathPrefix(options.OutputDir);\r
+      }\r
+\r
+      options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore;\r
+      if (parser[NKey::kOverwrite].ThereIs)\r
+        options.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex];\r
+      else if (options.YesToAll)\r
+        options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;\r
+    }\r
+  }\r
+  else if (options.Command.IsFromUpdateGroup())\r
+  {\r
+    CUpdateOptions &updateOptions = options.UpdateOptions;\r
+\r
+    SetAddCommandOptions(options.Command.CommandType, parser, updateOptions);\r
+    \r
+    SetMethodOptions(parser, updateOptions.MethodMode.Properties);\r
+\r
+    if (parser[NKey::kShareForWrite].ThereIs)\r
+      updateOptions.OpenShareForWrite = true;\r
+\r
+    options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs;\r
+\r
+    if (options.EnablePercents)\r
+    {\r
+      if ((options.StdOutMode && !options.IsStdErrTerminal) ||\r
+         (!options.StdOutMode && !options.IsStdOutTerminal))\r
+        options.EnablePercents = false;\r
+    }\r
+\r
+    updateOptions.EMailMode = parser[NKey::kEmail].ThereIs;\r
+    if (updateOptions.EMailMode)\r
+    {\r
+      updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front();\r
+      if (updateOptions.EMailAddress.Length() > 0)\r
+        if (updateOptions.EMailAddress[0] == L'.')\r
+        {\r
+          updateOptions.EMailRemoveAfter = true;\r
+          updateOptions.EMailAddress.Delete(0);\r
+        }\r
+    }\r
+\r
+    updateOptions.StdOutMode = options.StdOutMode;\r
+    updateOptions.StdInMode = options.StdInMode;\r
+\r
+    if (updateOptions.StdOutMode && updateOptions.EMailMode)\r
+      throw "stdout mode and email mode cannot be combined";\r
+    if (updateOptions.StdOutMode && options.IsStdOutTerminal)\r
+      throw kTerminalOutError;\r
+    if (updateOptions.StdInMode)\r
+      updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front();\r
+\r
+    #ifdef _WIN32\r
+    ConvertToLongNames(options.WildcardCensor);\r
+    #endif\r
+  }\r
+  else if (options.Command.CommandType == NCommandType::kBenchmark)\r
+  {\r
+    options.NumThreads = (UInt32)-1;\r
+    options.DictionarySize = (UInt32)-1;\r
+    options.NumIterations = 1;\r
+    if (curCommandIndex < numNonSwitchStrings)\r
+    {\r
+      if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations))\r
+        ThrowUserErrorException();\r
+    }\r
+    for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++)\r
+    {\r
+      UString postString = parser[NKey::kProperty].PostStrings[i];\r
+      postString.MakeUpper();\r
+      if (postString.Length() < 2)\r
+        ThrowUserErrorException();\r
+      if (postString[0] == 'D')\r
+      {\r
+        int pos = 1;\r
+        if (postString[pos] == '=')\r
+          pos++;\r
+        UInt32 logSize;\r
+        if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize))\r
+          ThrowUserErrorException();\r
+        if (logSize > 31)\r
+          ThrowUserErrorException();\r
+        options.DictionarySize = 1 << logSize;\r
+      }\r
+      else if (postString[0] == 'M' && postString[1] == 'T' )\r
+      {\r
+        int pos = 2;\r
+        if (postString[pos] == '=')\r
+          pos++;\r
+        if (postString[pos] != 0)\r
+          if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options.NumThreads))\r
+            ThrowUserErrorException();\r
+      }\r
+      else if (postString[0] == 'M' && postString[1] == '=' )\r
+      {\r
+        int pos = 2;\r
+        if (postString[pos] != 0)\r
+          options.Method = postString.Mid(2);\r
+      }\r
+      else\r
+        ThrowUserErrorException();\r
+    }\r
+  }\r
+  else if (options.Command.CommandType == NCommandType::kInfo)\r
+  {\r
+  }\r
+  else\r
+    ThrowUserErrorException();\r
+  options.WildcardCensor.ExtendExclude();\r
+}\r
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.h b/CPP/7zip/UI/Common/ArchiveCommandLine.h
new file mode 100755 (executable)
index 0000000..491689e
--- /dev/null
@@ -0,0 +1,111 @@
+// ArchiveCommandLine.h\r
+\r
+#ifndef __ARCHIVE_COMMAND_LINE_H\r
+#define __ARCHIVE_COMMAND_LINE_H\r
+\r
+#include "Common/CommandLineParser.h"\r
+#include "Common/Wildcard.h"\r
+\r
+#include "Extract.h"\r
+#include "Update.h"\r
+\r
+struct CArchiveCommandLineException: public AString\r
+{\r
+  CArchiveCommandLineException(const char *errorMessage): AString(errorMessage) {}\r
+};\r
+\r
+namespace NCommandType { enum EEnum\r
+{\r
+  kAdd = 0,\r
+  kUpdate,\r
+  kDelete,\r
+  kTest,\r
+  kExtract,\r
+  kFullExtract,\r
+  kList,\r
+  kBenchmark,\r
+  kInfo\r
+};}\r
+\r
+namespace NRecursedType { enum EEnum\r
+{\r
+  kRecursed,\r
+  kWildCardOnlyRecursed,\r
+  kNonRecursed\r
+};}\r
+\r
+struct CArchiveCommand\r
+{\r
+  NCommandType::EEnum CommandType;\r
+  bool IsFromExtractGroup() const;\r
+  bool IsFromUpdateGroup() const;\r
+  bool IsTestMode() const { return CommandType == NCommandType::kTest; }\r
+  NExtract::NPathMode::EEnum GetPathMode() const;\r
+};\r
+\r
+struct CArchiveCommandLineOptions\r
+{\r
+  bool HelpMode;\r
+\r
+  #ifdef _WIN32\r
+  bool LargePages;\r
+  #endif\r
+\r
+  bool IsInTerminal;\r
+  bool IsStdOutTerminal;\r
+  bool IsStdErrTerminal;\r
+  bool StdInMode;\r
+  bool StdOutMode;\r
+  bool EnableHeaders;\r
+\r
+  bool YesToAll;\r
+  bool ShowDialog;\r
+  // NWildcard::CCensor ArchiveWildcardCensor;\r
+  NWildcard::CCensor WildcardCensor;\r
+\r
+  CArchiveCommand Command;\r
+  UString ArchiveName;\r
+\r
+  #ifndef _NO_CRYPTO\r
+  bool PasswordEnabled;\r
+  UString Password;\r
+  #endif\r
+\r
+  bool TechMode;\r
+  // Extract\r
+  bool CalcCrc;\r
+  bool AppendName;\r
+  UString OutputDir;\r
+  NExtract::NOverwriteMode::EEnum OverwriteMode;\r
+  UStringVector ArchivePathsSorted;\r
+  UStringVector ArchivePathsFullSorted;\r
+  CObjectVector<CProperty> ExtractProperties;\r
+\r
+  CUpdateOptions UpdateOptions;\r
+  UString ArcType;\r
+  bool EnablePercents;\r
+\r
+  // Benchmark\r
+  UInt32 NumIterations;\r
+  UInt32 NumThreads;\r
+  UInt32 DictionarySize;\r
+  UString Method;\r
+\r
+\r
+  CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {};\r
+};\r
+\r
+class CArchiveCommandLineParser\r
+{\r
+  NCommandLineParser::CParser parser;\r
+public:\r
+  CArchiveCommandLineParser();\r
+  void Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options);\r
+  void Parse2(CArchiveCommandLineOptions &options);\r
+};\r
+\r
+void EnumerateDirItemsAndSort(NWildcard::CCensor &wildcardCensor,\r
+    UStringVector &sortedPaths,\r
+    UStringVector &sortedFullPaths);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
new file mode 100755 (executable)
index 0000000..2a322c5
--- /dev/null
@@ -0,0 +1,488 @@
+// ArchiveExtractCallback.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/Wildcard.h"\r
+\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileFind.h"\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/PropVariantConversions.h"\r
+\r
+#include "../../Common/FilePathAutoRename.h"\r
+\r
+#include "../Common/ExtractingFilePath.h"\r
+\r
+#include "ArchiveExtractCallback.h"\r
+\r
+using namespace NWindows;\r
+\r
+static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto name";\r
+static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file ";\r
+static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file ";\r
+\r
+void CArchiveExtractCallback::Init(\r
+    const NWildcard::CCensorNode *wildcardCensor,\r
+    const CArc *arc,\r
+    IFolderArchiveExtractCallback *extractCallback2,\r
+    bool stdOutMode, bool testMode, bool crcMode,\r
+    const UString &directoryPath,\r
+    const UStringVector &removePathParts,\r
+    UInt64 packSize)\r
+{\r
+  _wildcardCensor = wildcardCensor;\r
+\r
+  _stdOutMode = stdOutMode;\r
+  _testMode = testMode;\r
+  _crcMode = crcMode;\r
+  _unpTotal = 1;\r
+  _packTotal = packSize;\r
+\r
+  _extractCallback2 = extractCallback2;\r
+  _compressProgress.Release();\r
+  _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress);\r
+\r
+  LocalProgressSpec->Init(extractCallback2, true);\r
+  LocalProgressSpec->SendProgress = false;\r
+\r
\r
+  _removePathParts = removePathParts;\r
+  _arc = arc;\r
+  _directoryPath = directoryPath;\r
+  NFile::NName::NormalizeDirPathPrefix(_directoryPath);\r
+}\r
+\r
+STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size)\r
+{\r
+  COM_TRY_BEGIN\r
+  _unpTotal = size;\r
+  if (!_multiArchives && _extractCallback2)\r
+    return _extractCallback2->SetTotal(size);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+static void NormalizeVals(UInt64 &v1, UInt64 &v2)\r
+{\r
+  const UInt64 kMax = (UInt64)1 << 31;\r
+  while (v1 > kMax)\r
+  {\r
+    v1 >>= 1;\r
+    v2 >>= 1;\r
+  }\r
+}\r
+\r
+static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal)\r
+{\r
+  NormalizeVals(packTotal, unpTotal);\r
+  NormalizeVals(unpCur, unpTotal);\r
+  if (unpTotal == 0)\r
+    unpTotal = 1;\r
+  return unpCur * packTotal / unpTotal;\r
+}\r
+\r
+STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (!_extractCallback2)\r
+    return S_OK;\r
+\r
+  if (_multiArchives)\r
+  {\r
+    if (completeValue != NULL)\r
+    {\r
+      UInt64 packCur = LocalProgressSpec->InSize + MyMultDiv64(*completeValue, _unpTotal, _packTotal);\r
+      return _extractCallback2->SetCompleted(&packCur);\r
+    }\r
+  }\r
+  return _extractCallback2->SetCompleted(completeValue);\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)\r
+{\r
+  COM_TRY_BEGIN\r
+  return _localProgress->SetRatioInfo(inSize, outSize);\r
+  COM_TRY_END\r
+}\r
+\r
+void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath)\r
+{\r
+  fullPath = _directoryPath;\r
+  for (int i = 0; i < dirPathParts.Size(); i++)\r
+  {\r
+    if (i > 0)\r
+      fullPath += wchar_t(NFile::NName::kDirDelimiter);\r
+    fullPath += dirPathParts[i];\r
+    NFile::NDirectory::MyCreateDirectory(fullPath);\r
+  }\r
+}\r
+\r
+HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined)\r
+{\r
+  filetimeIsDefined = false;\r
+  NCOM::CPropVariant prop;\r
+  RINOK(_arc->Archive->GetProperty(index, propID, &prop));\r
+  if (prop.vt == VT_FILETIME)\r
+  {\r
+    filetime = prop.filetime;\r
+    filetimeIsDefined = (filetime.dwHighDateTime != 0 || filetime.dwLowDateTime != 0);\r
+  }\r
+  else if (prop.vt != VT_EMPTY)\r
+    return E_FAIL;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CArchiveExtractCallback::GetUnpackSize()\r
+{\r
+  NCOM::CPropVariant prop;\r
+  RINOK(_arc->Archive->GetProperty(_index, kpidSize, &prop));\r
+  _curSizeDefined = (prop.vt != VT_EMPTY);\r
+  if (_curSizeDefined)\r
+    _curSize = ConvertPropVariantToUInt64(prop);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)\r
+{\r
+  COM_TRY_BEGIN\r
+  _crcStream.Release();\r
+  *outStream = 0;\r
+  _outFileStream.Release();\r
+\r
+  _encrypted = false;\r
+  _isSplit = false;\r
+  _curSize = 0;\r
+  _curSizeDefined = false;\r
+  _index = index;\r
+\r
+  UString fullPath;\r
+\r
+  IInArchive *archive = _arc->Archive;\r
+  RINOK(_arc->GetItemPath(index, fullPath));\r
+  RINOK(IsArchiveItemFolder(archive, index, _fi.IsDir));\r
+\r
+  _filePath = fullPath;\r
+\r
+  {\r
+    NCOM::CPropVariant prop;\r
+    RINOK(archive->GetProperty(index, kpidPosition, &prop));\r
+    if (prop.vt != VT_EMPTY)\r
+    {\r
+      if (prop.vt != VT_UI8)\r
+        return E_FAIL;\r
+      _position = prop.uhVal.QuadPart;\r
+      _isSplit = true;\r
+    }\r
+  }\r
+    \r
+  RINOK(GetArchiveItemBoolProp(archive, index, kpidEncrypted, _encrypted));\r
+\r
+  RINOK(GetUnpackSize());\r
+\r
+  if (_wildcardCensor)\r
+  {\r
+    if (!_wildcardCensor->CheckPath(fullPath, !_fi.IsDir))\r
+      return S_OK;\r
+  }\r
+\r
+  if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)\r
+  {\r
+    if (_stdOutMode)\r
+    {\r
+      CMyComPtr<ISequentialOutStream> outStreamLoc = new CStdOutFileStream;\r
+      *outStream = outStreamLoc.Detach();\r
+      return S_OK;\r
+    }\r
+\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      RINOK(archive->GetProperty(index, kpidAttrib, &prop));\r
+      if (prop.vt == VT_UI4)\r
+      {\r
+        _fi.Attrib = prop.ulVal;\r
+        _fi.AttribDefined = true;\r
+      }\r
+      else if (prop.vt == VT_EMPTY)\r
+        _fi.AttribDefined = false;\r
+      else\r
+        return E_FAIL;\r
+    }\r
+\r
+    RINOK(GetTime(index, kpidCTime, _fi.CTime, _fi.CTimeDefined));\r
+    RINOK(GetTime(index, kpidATime, _fi.ATime, _fi.ATimeDefined));\r
+    RINOK(GetTime(index, kpidMTime, _fi.MTime, _fi.MTimeDefined));\r
+\r
+    bool isAnti = false;\r
+    RINOK(_arc->IsItemAnti(index, isAnti));\r
+\r
+    UStringVector pathParts;\r
+    SplitPathToParts(fullPath, pathParts);\r
+    \r
+    if (pathParts.IsEmpty())\r
+      return E_FAIL;\r
+    int numRemovePathParts = 0;\r
+    switch(_pathMode)\r
+    {\r
+      case NExtract::NPathMode::kFullPathnames:\r
+        break;\r
+      case NExtract::NPathMode::kCurrentPathnames:\r
+      {\r
+        numRemovePathParts = _removePathParts.Size();\r
+        if (pathParts.Size() <= numRemovePathParts)\r
+          return E_FAIL;\r
+        for (int i = 0; i < numRemovePathParts; i++)\r
+          if (_removePathParts[i].CompareNoCase(pathParts[i]) != 0)\r
+            return E_FAIL;\r
+        break;\r
+      }\r
+      case NExtract::NPathMode::kNoPathnames:\r
+      {\r
+        numRemovePathParts = pathParts.Size() - 1;\r
+        break;\r
+      }\r
+    }\r
+    pathParts.Delete(0, numRemovePathParts);\r
+    MakeCorrectPath(pathParts);\r
+    UString processedPath = MakePathNameFromParts(pathParts);\r
+    if (!isAnti)\r
+    {\r
+      if (!_fi.IsDir)\r
+      {\r
+        if (!pathParts.IsEmpty())\r
+          pathParts.DeleteBack();\r
+      }\r
+    \r
+      if (!pathParts.IsEmpty())\r
+      {\r
+        UString fullPathNew;\r
+        CreateComplexDirectory(pathParts, fullPathNew);\r
+        if (_fi.IsDir)\r
+          NFile::NDirectory::SetDirTime(fullPathNew,\r
+            (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,\r
+            (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,\r
+            (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));\r
+      }\r
+    }\r
+\r
+\r
+    UString fullProcessedPath = _directoryPath + processedPath;\r
+\r
+    if (_fi.IsDir)\r
+    {\r
+      _diskFilePath = fullProcessedPath;\r
+      if (isAnti)\r
+        NFile::NDirectory::MyRemoveDirectory(_diskFilePath);\r
+      return S_OK;\r
+    }\r
+\r
+    if (!_isSplit)\r
+    {\r
+    NFile::NFind::CFileInfoW fileInfo;\r
+    if (fileInfo.Find(fullProcessedPath))\r
+    {\r
+      switch(_overwriteMode)\r
+      {\r
+        case NExtract::NOverwriteMode::kSkipExisting:\r
+          return S_OK;\r
+        case NExtract::NOverwriteMode::kAskBefore:\r
+        {\r
+          Int32 overwiteResult;\r
+          RINOK(_extractCallback2->AskOverwrite(\r
+              fullProcessedPath, &fileInfo.MTime, &fileInfo.Size, fullPath,\r
+              _fi.MTimeDefined ? &_fi.MTime : NULL,\r
+              _curSizeDefined ? &_curSize : NULL,\r
+              &overwiteResult))\r
+\r
+          switch(overwiteResult)\r
+          {\r
+            case NOverwriteAnswer::kCancel:\r
+              return E_ABORT;\r
+            case NOverwriteAnswer::kNo:\r
+              return S_OK;\r
+            case NOverwriteAnswer::kNoToAll:\r
+              _overwriteMode = NExtract::NOverwriteMode::kSkipExisting;\r
+              return S_OK;\r
+            case NOverwriteAnswer::kYesToAll:\r
+              _overwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;\r
+              break;\r
+            case NOverwriteAnswer::kYes:\r
+              break;\r
+            case NOverwriteAnswer::kAutoRename:\r
+              _overwriteMode = NExtract::NOverwriteMode::kAutoRename;\r
+              break;\r
+            default:\r
+              return E_FAIL;\r
+          }\r
+        }\r
+      }\r
+      if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename)\r
+      {\r
+        if (!AutoRenamePath(fullProcessedPath))\r
+        {\r
+          UString message = UString(kCantAutoRename) + fullProcessedPath;\r
+          RINOK(_extractCallback2->MessageError(message));\r
+          return E_FAIL;\r
+        }\r
+      }\r
+      else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting)\r
+      {\r
+        UString existPath = fullProcessedPath;\r
+        if (!AutoRenamePath(existPath))\r
+        {\r
+          UString message = kCantAutoRename + fullProcessedPath;\r
+          RINOK(_extractCallback2->MessageError(message));\r
+          return E_FAIL;\r
+        }\r
+        if (!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath))\r
+        {\r
+          UString message = UString(kCantRenameFile) + fullProcessedPath;\r
+          RINOK(_extractCallback2->MessageError(message));\r
+          return E_FAIL;\r
+        }\r
+      }\r
+      else\r
+        if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath))\r
+        {\r
+          UString message = UString(kCantDeleteOutputFile) +  fullProcessedPath;\r
+          RINOK(_extractCallback2->MessageError(message));\r
+          return S_OK;\r
+          // return E_FAIL;\r
+        }\r
+    }\r
+    }\r
+    if (!isAnti)\r
+    {\r
+      _outFileStreamSpec = new COutFileStream;\r
+      CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);\r
+      if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS))\r
+      {\r
+        // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit)\r
+        {\r
+          UString message = L"can not open output file " + fullProcessedPath;\r
+          RINOK(_extractCallback2->MessageError(message));\r
+          return S_OK;\r
+        }\r
+      }\r
+      if (_isSplit)\r
+      {\r
+        RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL));\r
+      }\r
+      _outFileStream = outStreamLoc;\r
+      *outStream = outStreamLoc.Detach();\r
+    }\r
+    _diskFilePath = fullProcessedPath;\r
+  }\r
+  else\r
+  {\r
+    *outStream = NULL;\r
+  }\r
+  if (_crcMode)\r
+  {\r
+    _crcStreamSpec = new COutStreamWithCRC;\r
+    _crcStream = _crcStreamSpec;\r
+    CMyComPtr<ISequentialOutStream> crcStream = _crcStreamSpec;\r
+    _crcStreamSpec->SetStream(*outStream);\r
+    if (*outStream)\r
+      (*outStream)->Release();\r
+    *outStream = crcStream.Detach();\r
+    _crcStreamSpec->Init(true);\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)\r
+{\r
+  COM_TRY_BEGIN\r
+  _extractMode = false;\r
+  switch (askExtractMode)\r
+  {\r
+    case NArchive::NExtract::NAskMode::kExtract:\r
+      if (_testMode)\r
+        askExtractMode = NArchive::NExtract::NAskMode::kTest;\r
+      else\r
+        _extractMode = true;\r
+      break;\r
+  };\r
+  return _extractCallback2->PrepareOperation(_filePath, _fi.IsDir,\r
+      askExtractMode, _isSplit ? &_position: 0);\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)\r
+{\r
+  COM_TRY_BEGIN\r
+  switch(operationResult)\r
+  {\r
+    case NArchive::NExtract::NOperationResult::kOK:\r
+    case NArchive::NExtract::NOperationResult::kUnSupportedMethod:\r
+    case NArchive::NExtract::NOperationResult::kCRCError:\r
+    case NArchive::NExtract::NOperationResult::kDataError:\r
+      break;\r
+    default:\r
+      _outFileStream.Release();\r
+      return E_FAIL;\r
+  }\r
+  if (_crcStream)\r
+  {\r
+    CrcSum += _crcStreamSpec->GetCRC();\r
+    _curSize = _crcStreamSpec->GetSize();\r
+    _curSizeDefined = true;\r
+    _crcStream.Release();\r
+  }\r
+  if (_outFileStream)\r
+  {\r
+    _outFileStreamSpec->SetTime(\r
+        (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,\r
+        (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,\r
+        (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));\r
+    _curSize = _outFileStreamSpec->ProcessedSize;\r
+    _curSizeDefined = true;\r
+    RINOK(_outFileStreamSpec->Close());\r
+    _outFileStream.Release();\r
+  }\r
+  if (!_curSizeDefined)\r
+    GetUnpackSize();\r
+  if (_curSizeDefined)\r
+    UnpackSize += _curSize;\r
+  if (_fi.IsDir)\r
+    NumFolders++;\r
+  else\r
+    NumFiles++;\r
+\r
+  if (_extractMode && _fi.AttribDefined)\r
+    NFile::NDirectory::MySetFileAttributes(_diskFilePath, _fi.Attrib);\r
+  RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted));\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+/*\r
+STDMETHODIMP CArchiveExtractCallback::GetInStream(\r
+    const wchar_t *name, ISequentialInStream **inStream)\r
+{\r
+  COM_TRY_BEGIN\r
+  CInFileStream *inFile = new CInFileStream;\r
+  CMyComPtr<ISequentialInStream> inStreamTemp = inFile;\r
+  if (!inFile->Open(_srcDirectoryPrefix + name))\r
+    return ::GetLastError();\r
+  *inStream = inStreamTemp.Detach();\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+*/\r
+\r
+STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (!_cryptoGetTextPassword)\r
+  {\r
+    RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword,\r
+        &_cryptoGetTextPassword));\r
+  }\r
+  return _cryptoGetTextPassword->CryptoGetTextPassword(password);\r
+  COM_TRY_END\r
+}\r
+\r
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
new file mode 100755 (executable)
index 0000000..b7a6a47
--- /dev/null
@@ -0,0 +1,143 @@
+// ArchiveExtractCallback.h\r
+\r
+#ifndef __ARCHIVE_EXTRACT_CALLBACK_H\r
+#define __ARCHIVE_EXTRACT_CALLBACK_H\r
+\r
+#include "Common/MyCom.h"\r
+#include "Common/Wildcard.h"\r
+\r
+#include "../../IPassword.h"\r
+\r
+#include "../../Common/FileStreams.h"\r
+#include "../../Common/ProgressUtils.h"\r
+\r
+#include "../../Archive/IArchive.h"\r
+\r
+#include "../../Archive/Common/OutStreamWithCRC.h"\r
+\r
+#include "ExtractMode.h"\r
+#include "IFileExtractCallback.h"\r
+#include "OpenArchive.h"\r
+\r
+class CArchiveExtractCallback:\r
+  public IArchiveExtractCallback,\r
+  // public IArchiveVolumeExtractCallback,\r
+  public ICryptoGetTextPassword,\r
+  public ICompressProgressInfo,\r
+  public CMyUnknownImp\r
+{\r
+  const CArc *_arc;\r
+  const NWildcard::CCensorNode *_wildcardCensor;\r
+  CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;\r
+  CMyComPtr<ICompressProgressInfo> _compressProgress;\r
+  CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;\r
+  UString _directoryPath;\r
+  NExtract::NPathMode::EEnum _pathMode;\r
+  NExtract::NOverwriteMode::EEnum _overwriteMode;\r
+\r
+  UString _diskFilePath;\r
+  UString _filePath;\r
+  UInt64 _position;\r
+  bool _isSplit;\r
+\r
+  bool _extractMode;\r
+\r
+  bool WriteCTime;\r
+  bool WriteATime;\r
+  bool WriteMTime;\r
+\r
+  bool _encrypted;\r
+\r
+  struct CProcessedFileInfo\r
+  {\r
+    FILETIME CTime;\r
+    FILETIME ATime;\r
+    FILETIME MTime;\r
+    UInt32 Attrib;\r
+  \r
+    bool CTimeDefined;\r
+    bool ATimeDefined;\r
+    bool MTimeDefined;\r
+    bool AttribDefined;\r
+\r
+    bool IsDir;\r
+  } _fi;\r
+\r
+  UInt32 _index;\r
+  UInt64 _curSize;\r
+  bool _curSizeDefined;\r
+  COutFileStream *_outFileStreamSpec;\r
+  CMyComPtr<ISequentialOutStream> _outFileStream;\r
+\r
+  COutStreamWithCRC *_crcStreamSpec;\r
+  CMyComPtr<ISequentialOutStream> _crcStream;\r
+\r
+  UStringVector _removePathParts;\r
+\r
+  bool _stdOutMode;\r
+  bool _testMode;\r
+  bool _crcMode;\r
+  bool _multiArchives;\r
+\r
+  CMyComPtr<ICompressProgressInfo> _localProgress;\r
+  UInt64 _packTotal;\r
+  UInt64 _unpTotal;\r
+\r
+  void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath);\r
+  HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);\r
+  HRESULT GetUnpackSize();\r
+\r
+public:\r
+\r
+  CLocalProgress *LocalProgressSpec;\r
+\r
+  UInt64 NumFolders;\r
+  UInt64 NumFiles;\r
+  UInt64 UnpackSize;\r
+  UInt32 CrcSum;\r
+  \r
+  MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo)\r
+  // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback)\r
+\r
+  INTERFACE_IArchiveExtractCallback(;)\r
+\r
+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);\r
+\r
+  // IArchiveVolumeExtractCallback\r
+  // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream);\r
+\r
+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);\r
+\r
+  CArchiveExtractCallback():\r
+      WriteCTime(true),\r
+      WriteATime(true),\r
+      WriteMTime(true),\r
+      _multiArchives(false)\r
+  {\r
+    LocalProgressSpec = new CLocalProgress();\r
+    _localProgress = LocalProgressSpec;\r
+  }\r
+\r
+  void InitForMulti(bool multiArchives,\r
+      NExtract::NPathMode::EEnum pathMode,\r
+      NExtract::NOverwriteMode::EEnum overwriteMode)\r
+  {\r
+    _multiArchives = multiArchives;\r
+    _pathMode = pathMode;\r
+    _overwriteMode = overwriteMode;\r
+    NumFolders = NumFiles = UnpackSize = 0;\r
+    CrcSum = 0;\r
+  }\r
+\r
+  void Init(\r
+      const NWildcard::CCensorNode *wildcardCensor,\r
+      const CArc *arc,\r
+      IFolderArchiveExtractCallback *extractCallback2,\r
+      bool stdOutMode, bool testMode, bool crcMode,\r
+      const UString &directoryPath,\r
+      const UStringVector &removePathParts,\r
+      UInt64 packSize);\r
+\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/ArchiveName.cpp b/CPP/7zip/UI/Common/ArchiveName.cpp
new file mode 100755 (executable)
index 0000000..c62c7f1
--- /dev/null
@@ -0,0 +1,54 @@
+// ArchiveName.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileFind.h"\r
+\r
+#include "ExtractingFilePath.h"\r
+\r
+using namespace NWindows;\r
+\r
+static UString CreateArchiveName2(const UString &srcName, bool fromPrev, bool keepName)\r
+{\r
+  UString resultName = L"Archive";\r
+  if (fromPrev)\r
+  {\r
+    UString dirPrefix;\r
+    if (NFile::NDirectory::GetOnlyDirPrefix(srcName, dirPrefix))\r
+    {\r
+      if (dirPrefix.Length() > 0)\r
+        if (dirPrefix[dirPrefix.Length() - 1] == WCHAR_PATH_SEPARATOR)\r
+        {\r
+          dirPrefix.Delete(dirPrefix.Length() - 1);\r
+          NFile::NFind::CFileInfoW fileInfo;\r
+          if (fileInfo.Find(dirPrefix))\r
+            resultName = fileInfo.Name;\r
+        }\r
+    }\r
+  }\r
+  else\r
+  {\r
+    NFile::NFind::CFileInfoW fileInfo;\r
+    if (!fileInfo.Find(srcName))\r
+      // return resultName;\r
+      return srcName;\r
+    resultName = fileInfo.Name;\r
+    if (!fileInfo.IsDir() && !keepName)\r
+    {\r
+      int dotPos = resultName.ReverseFind('.');\r
+      if (dotPos > 0)\r
+      {\r
+        UString archiveName2 = resultName.Left(dotPos);\r
+        if (archiveName2.ReverseFind('.') < 0)\r
+          resultName = archiveName2;\r
+      }\r
+    }\r
+  }\r
+  return resultName;\r
+}\r
+\r
+UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName)\r
+{\r
+  return GetCorrectFsPath(CreateArchiveName2(srcName, fromPrev, keepName));\r
+}\r
diff --git a/CPP/7zip/UI/Common/ArchiveName.h b/CPP/7zip/UI/Common/ArchiveName.h
new file mode 100755 (executable)
index 0000000..ba18eea
--- /dev/null
@@ -0,0 +1,10 @@
+// ArchiveName.h\r
+\r
+#ifndef __ARCHIVENAME_H\r
+#define __ARCHIVENAME_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
new file mode 100755 (executable)
index 0000000..bb8b6cc
--- /dev/null
@@ -0,0 +1,133 @@
+// ArchiveOpenCallback.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/StringConvert.h"\r
+#include "Common/ComTry.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../../Common/FileStreams.h"\r
+\r
+#include "ArchiveOpenCallback.h"\r
+\r
+using namespace NWindows;\r
+\r
+STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (ReOpenCallback)\r
+    return ReOpenCallback->SetTotal(files, bytes);\r
+  if (!Callback)\r
+    return S_OK;\r
+  return Callback->Open_SetTotal(files, bytes);\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (ReOpenCallback)\r
+    return ReOpenCallback->SetCompleted(files, bytes);\r
+  if (!Callback)\r
+    return S_OK;\r
+  return Callback->Open_SetCompleted(files, bytes);\r
+  COM_TRY_END\r
+}\r
+  \r
+STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NCOM::CPropVariant prop;\r
+  if (_subArchiveMode)\r
+    switch(propID)\r
+    {\r
+      case kpidName: prop = _subArchiveName; break;\r
+    }\r
+  else\r
+    switch(propID)\r
+    {\r
+      case kpidName:  prop = _fileInfo.Name; break;\r
+      case kpidIsDir:  prop = _fileInfo.IsDir(); break;\r
+      case kpidSize:  prop = _fileInfo.Size; break;\r
+      case kpidAttrib:  prop = (UInt32)_fileInfo.Attrib; break;\r
+      case kpidCTime:  prop = _fileInfo.CTime; break;\r
+      case kpidATime:  prop = _fileInfo.ATime; break;\r
+      case kpidMTime:  prop = _fileInfo.MTime; break;\r
+    }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+int COpenCallbackImp::FindName(const UString &name)\r
+{\r
+  for (int i = 0; i < FileNames.Size(); i++)\r
+    if (name.CompareNoCase(FileNames[i]) == 0)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+struct CInFileStreamVol: public CInFileStream\r
+{\r
+  UString Name;\r
+  COpenCallbackImp *OpenCallbackImp;\r
+  CMyComPtr<IArchiveOpenCallback> OpenCallbackRef;\r
+  ~CInFileStreamVol()\r
+  {\r
+    if (OpenCallbackRef)\r
+    {\r
+      int index = OpenCallbackImp->FindName(Name);\r
+      if (index >= 0)\r
+        OpenCallbackImp->FileNames.Delete(index);\r
+    }\r
+  }\r
+};\r
+\r
+STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (_subArchiveMode)\r
+    return S_FALSE;\r
+  if (Callback)\r
+  {\r
+    RINOK(Callback->Open_CheckBreak());\r
+  }\r
+  *inStream = NULL;\r
+  UString fullPath = _folderPrefix + name;\r
+  if (!_fileInfo.Find(fullPath))\r
+    return S_FALSE;\r
+  if (_fileInfo.IsDir())\r
+    return S_FALSE;\r
+  CInFileStreamVol *inFile = new CInFileStreamVol;\r
+  CMyComPtr<IInStream> inStreamTemp = inFile;\r
+  if (!inFile->Open(fullPath))\r
+    return ::GetLastError();\r
+  *inStream = inStreamTemp.Detach();\r
+  inFile->Name = name;\r
+  inFile->OpenCallbackImp = this;\r
+  inFile->OpenCallbackRef = this;\r
+  FileNames.Add(name);\r
+  TotalSize += _fileInfo.Size;\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+#ifndef _NO_CRYPTO\r
+STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password)\r
+{\r
+  COM_TRY_BEGIN\r
+  if (ReOpenCallback)\r
+  {\r
+    CMyComPtr<ICryptoGetTextPassword> getTextPassword;\r
+    ReOpenCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);\r
+    if (getTextPassword)\r
+      return getTextPassword->CryptoGetTextPassword(password);\r
+  }\r
+  if (!Callback)\r
+    return E_NOTIMPL;\r
+  return Callback->Open_CryptoGetTextPassword(password);\r
+  COM_TRY_END\r
+}\r
+#endif\r
+  \r
diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/CPP/7zip/UI/Common/ArchiveOpenCallback.h
new file mode 100755 (executable)
index 0000000..a60fca3
--- /dev/null
@@ -0,0 +1,103 @@
+// ArchiveOpenCallback.h\r
+\r
+#ifndef __ARCHIVE_OPEN_CALLBACK_H\r
+#define __ARCHIVE_OPEN_CALLBACK_H\r
+\r
+#include "Common/MyCom.h"\r
+#include "Common/MyString.h"\r
+\r
+#include "Windows/FileFind.h"\r
+\r
+#ifndef _NO_CRYPTO\r
+#include "../../IPassword.h"\r
+#endif\r
+#include "../../Archive/IArchive.h"\r
+\r
+#ifdef _NO_CRYPTO\r
+\r
+#define INTERFACE_IOpenCallbackUI_Crypto(x)\r
+\r
+#else\r
+\r
+#define INTERFACE_IOpenCallbackUI_Crypto(x) \\r
+  virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x; \\r
+  virtual HRESULT Open_GetPasswordIfAny(UString &password) x; \\r
+  virtual bool Open_WasPasswordAsked() x; \\r
+  virtual void Open_ClearPasswordWasAskedFlag() x; \\r
+  \r
+#endif\r
+\r
+#define INTERFACE_IOpenCallbackUI(x) \\r
+  virtual HRESULT Open_CheckBreak() x; \\r
+  virtual HRESULT Open_SetTotal(const UInt64 *files, const UInt64 *bytes) x; \\r
+  virtual HRESULT Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) x; \\r
+  INTERFACE_IOpenCallbackUI_Crypto(x)\r
+\r
+struct IOpenCallbackUI\r
+{\r
+  INTERFACE_IOpenCallbackUI(=0)\r
+};\r
+\r
+class COpenCallbackImp:\r
+  public IArchiveOpenCallback,\r
+  public IArchiveOpenVolumeCallback,\r
+  public IArchiveOpenSetSubArchiveName,\r
+  #ifndef _NO_CRYPTO\r
+  public ICryptoGetTextPassword,\r
+  #endif\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  #ifndef _NO_CRYPTO\r
+  MY_UNKNOWN_IMP3(\r
+      IArchiveOpenVolumeCallback,\r
+      ICryptoGetTextPassword,\r
+      IArchiveOpenSetSubArchiveName\r
+      )\r
+  #else\r
+  MY_UNKNOWN_IMP2(\r
+      IArchiveOpenVolumeCallback,\r
+      IArchiveOpenSetSubArchiveName\r
+      )\r
+  #endif\r
+\r
+  INTERFACE_IArchiveOpenCallback(;)\r
+  INTERFACE_IArchiveOpenVolumeCallback(;)\r
+\r
+  #ifndef _NO_CRYPTO\r
+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);\r
+  #endif\r
+\r
+  STDMETHOD(SetSubArchiveName(const wchar_t *name))\r
+  {\r
+    _subArchiveMode = true;\r
+    _subArchiveName = name;\r
+    TotalSize = 0;\r
+    return  S_OK;\r
+  }\r
+\r
+private:\r
+  UString _folderPrefix;\r
+  NWindows::NFile::NFind::CFileInfoW _fileInfo;\r
+  bool _subArchiveMode;\r
+  UString _subArchiveName;\r
+public:\r
+  UStringVector FileNames;\r
+  IOpenCallbackUI *Callback;\r
+  CMyComPtr<IArchiveOpenCallback> ReOpenCallback;\r
+  UInt64 TotalSize;\r
+\r
+  COpenCallbackImp(): Callback(NULL) {}\r
+  void Init(const UString &folderPrefix, const UString &fileName)\r
+  {\r
+    _folderPrefix = folderPrefix;\r
+    if (!_fileInfo.Find(_folderPrefix + fileName))\r
+      throw 1;\r
+    FileNames.Clear();\r
+    _subArchiveMode = false;\r
+    TotalSize = 0;\r
+  }\r
+  int FindName(const UString &name);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp
new file mode 100755 (executable)
index 0000000..0c85695
--- /dev/null
@@ -0,0 +1,1028 @@
+// Bench.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Bench.h"\r
+\r
+#ifndef _WIN32\r
+#define USE_POSIX_TIME\r
+#define USE_POSIX_TIME2\r
+#endif\r
+\r
+#ifdef USE_POSIX_TIME\r
+#include <time.h>\r
+#ifdef USE_POSIX_TIME2\r
+#include <sys/time.h>\r
+#endif\r
+#endif\r
+\r
+#ifdef _WIN32\r
+#define USE_ALLOCA\r
+#endif\r
+\r
+#ifdef USE_ALLOCA\r
+#ifdef _WIN32\r
+#include <malloc.h>\r
+#else\r
+#include <stdlib.h>\r
+#endif\r
+#endif\r
+\r
+#include "../../../../C/7zCrc.h"\r
+#include "../../../../C/Alloc.h"\r
+\r
+#ifndef _7ZIP_ST\r
+#include "../../../Windows/Synchronization.h"\r
+#include "../../../Windows/Thread.h"\r
+#endif\r
+\r
+#include "../../../Windows/PropVariant.h"\r
+\r
+static const UInt32 kUncompressMinBlockSize =\r
+#ifdef UNDER_CE\r
+1 << 24;\r
+#else\r
+1 << 26;\r
+#endif\r
+\r
+static const UInt32 kCrcBlockSize =\r
+#ifdef UNDER_CE\r
+1 << 25;\r
+#else\r
+1 << 30;\r
+#endif\r
+\r
+static const UInt32 kAdditionalSize = (1 << 16);\r
+static const UInt32 kCompressedAdditionalSize = (1 << 10);\r
+static const UInt32 kMaxLzmaPropSize = 5;\r
+\r
+class CBaseRandomGenerator\r
+{\r
+  UInt32 A1;\r
+  UInt32 A2;\r
+public:\r
+  CBaseRandomGenerator() { Init(); }\r
+  void Init() { A1 = 362436069; A2 = 521288629;}\r
+  UInt32 GetRnd()\r
+  {\r
+    return\r
+      ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) +\r
+      ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) );\r
+  }\r
+};\r
+\r
+class CBenchBuffer\r
+{\r
+public:\r
+  size_t BufferSize;\r
+  Byte *Buffer;\r
+  CBenchBuffer(): Buffer(0) {}\r
+  virtual ~CBenchBuffer() { Free(); }\r
+  void Free()\r
+  {\r
+    ::MidFree(Buffer);\r
+    Buffer = 0;\r
+  }\r
+  bool Alloc(size_t bufferSize)\r
+  {\r
+    if (Buffer != 0 && BufferSize == bufferSize)\r
+      return true;\r
+    Free();\r
+    Buffer = (Byte *)::MidAlloc(bufferSize);\r
+    BufferSize = bufferSize;\r
+    return (Buffer != 0);\r
+  }\r
+};\r
+\r
+class CBenchRandomGenerator: public CBenchBuffer\r
+{\r
+  CBaseRandomGenerator *RG;\r
+public:\r
+  void Set(CBaseRandomGenerator *rg) { RG = rg; }\r
+  UInt32 GetVal(UInt32 &res, int numBits)\r
+  {\r
+    UInt32 val = res & (((UInt32)1 << numBits) - 1);\r
+    res >>= numBits;\r
+    return val;\r
+  }\r
+  UInt32 GetLen(UInt32 &res)\r
+  {\r
+    UInt32 len = GetVal(res, 2);\r
+    return GetVal(res, 1 + len);\r
+  }\r
+  void Generate()\r
+  {\r
+    UInt32 pos = 0;\r
+    UInt32 rep0 = 1;\r
+    while (pos < BufferSize)\r
+    {\r
+      UInt32 res = RG->GetRnd();\r
+      res >>= 1;\r
+      if (GetVal(res, 1) == 0 || pos < 1024)\r
+        Buffer[pos++] = (Byte)(res & 0xFF);\r
+      else\r
+      {\r
+        UInt32 len;\r
+        len = 1 + GetLen(res);\r
+        if (GetVal(res, 3) != 0)\r
+        {\r
+          len += GetLen(res);\r
+          do\r
+          {\r
+            UInt32 ppp = GetVal(res, 5) + 6;\r
+            res = RG->GetRnd();\r
+            if (ppp > 30)\r
+              continue;\r
+            rep0 = /* (1 << ppp) +*/  GetVal(res, ppp);\r
+            res = RG->GetRnd();\r
+          }\r
+          while (rep0 >= pos);\r
+          rep0++;\r
+        }\r
+\r
+        for (UInt32 i = 0; i < len && pos < BufferSize; i++, pos++)\r
+          Buffer[pos] = Buffer[pos - rep0];\r
+      }\r
+    }\r
+  }\r
+};\r
+\r
+\r
+class CBenchmarkInStream:\r
+  public ISequentialInStream,\r
+  public CMyUnknownImp\r
+{\r
+  const Byte *Data;\r
+  size_t Pos;\r
+  size_t Size;\r
+public:\r
+  MY_UNKNOWN_IMP\r
+  void Init(const Byte *data, size_t size)\r
+  {\r
+    Data = data;\r
+    Size = size;\r
+    Pos = 0;\r
+  }\r
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);\r
+};\r
+\r
+STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  size_t remain = Size - Pos;\r
+  UInt32 kMaxBlockSize = (1 << 20);\r
+  if (size > kMaxBlockSize)\r
+    size = kMaxBlockSize;\r
+  if (size > remain)\r
+    size = (UInt32)remain;\r
+  for (UInt32 i = 0; i < size; i++)\r
+    ((Byte *)data)[i] = Data[Pos + i];\r
+  Pos += size;\r
+  if(processedSize != NULL)\r
+    *processedSize = size;\r
+  return S_OK;\r
+}\r
+  \r
+class CBenchmarkOutStream:\r
+  public ISequentialOutStream,\r
+  public CBenchBuffer,\r
+  public CMyUnknownImp\r
+{\r
+  // bool _overflow;\r
+public:\r
+  UInt32 Pos;\r
+  // CBenchmarkOutStream(): _overflow(false) {}\r
+  void Init()\r
+  {\r
+    // _overflow = false;\r
+    Pos = 0;\r
+  }\r
+  MY_UNKNOWN_IMP\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+};\r
+\r
+STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  size_t curSize = BufferSize - Pos;\r
+  if (curSize > size)\r
+    curSize = size;\r
+  memcpy(Buffer + Pos, data, curSize);\r
+  Pos += (UInt32)curSize;\r
+  if(processedSize != NULL)\r
+    *processedSize = (UInt32)curSize;\r
+  if (curSize != size)\r
+  {\r
+    // _overflow = true;\r
+    return E_FAIL;\r
+  }\r
+  return S_OK;\r
+}\r
+  \r
+class CCrcOutStream:\r
+  public ISequentialOutStream,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  UInt32 Crc;\r
+  MY_UNKNOWN_IMP\r
+  void Init() { Crc = CRC_INIT_VAL; }\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+};\r
+\r
+STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  Crc = CrcUpdate(Crc, data, size);\r
+  if (processedSize != NULL)\r
+    *processedSize = size;\r
+  return S_OK;\r
+}\r
+  \r
+static UInt64 GetTimeCount()\r
+{\r
+  #ifdef USE_POSIX_TIME\r
+  #ifdef USE_POSIX_TIME2\r
+  timeval v;\r
+  if (gettimeofday(&v, 0) == 0)\r
+    return (UInt64)(v.tv_sec) * 1000000 + v.tv_usec;\r
+  return (UInt64)time(NULL) * 1000000;\r
+  #else\r
+  return time(NULL);\r
+  #endif\r
+  #else\r
+  /*\r
+  LARGE_INTEGER value;\r
+  if (::QueryPerformanceCounter(&value))\r
+    return value.QuadPart;\r
+  */\r
+  return GetTickCount();\r
+  #endif\r
+}\r
+\r
+static UInt64 GetFreq()\r
+{\r
+  #ifdef USE_POSIX_TIME\r
+  #ifdef USE_POSIX_TIME2\r
+  return 1000000;\r
+  #else\r
+  return 1;\r
+  #endif\r
+  #else\r
+  /*\r
+  LARGE_INTEGER value;\r
+  if (::QueryPerformanceFrequency(&value))\r
+    return value.QuadPart;\r
+  */\r
+  return 1000;\r
+  #endif\r
+}\r
+\r
+#ifndef USE_POSIX_TIME\r
+static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; }\r
+#endif\r
+\r
+static UInt64 GetUserTime()\r
+{\r
+  #ifdef USE_POSIX_TIME\r
+  return clock();\r
+  #else\r
+  FILETIME creationTime, exitTime, kernelTime, userTime;\r
+  if (\r
+  #ifdef UNDER_CE\r
+    ::GetThreadTimes(::GetCurrentThread()\r
+  #else\r
+    ::GetProcessTimes(::GetCurrentProcess()\r
+  #endif\r
+    , &creationTime, &exitTime, &kernelTime, &userTime) != 0)\r
+    return GetTime64(userTime) + GetTime64(kernelTime);\r
+  return (UInt64)GetTickCount() * 10000;\r
+  #endif\r
+}\r
+\r
+static UInt64 GetUserFreq()\r
+{\r
+  #ifdef USE_POSIX_TIME\r
+  return CLOCKS_PER_SEC;\r
+  #else\r
+  return 10000000;\r
+  #endif\r
+}\r
+\r
+class CBenchProgressStatus\r
+{\r
+  #ifndef _7ZIP_ST\r
+  NWindows::NSynchronization::CCriticalSection CS;\r
+  #endif\r
+public:\r
+  HRESULT Res;\r
+  bool EncodeMode;\r
+  void SetResult(HRESULT res)\r
+  {\r
+    #ifndef _7ZIP_ST\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(CS);\r
+    #endif\r
+    Res = res;\r
+  }\r
+  HRESULT GetResult()\r
+  {\r
+    #ifndef _7ZIP_ST\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(CS);\r
+    #endif\r
+    return Res;\r
+  }\r
+};\r
+\r
+class CBenchProgressInfo:\r
+  public ICompressProgressInfo,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  CBenchProgressStatus *Status;\r
+  CBenchInfo BenchInfo;\r
+  HRESULT Res;\r
+  IBenchCallback *callback;\r
+  CBenchProgressInfo(): callback(0) {}\r
+  MY_UNKNOWN_IMP\r
+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);\r
+};\r
+\r
+static void SetStartTime(CBenchInfo &bi)\r
+{\r
+  bi.GlobalFreq = GetFreq();\r
+  bi.UserFreq = GetUserFreq();\r
+  bi.GlobalTime = ::GetTimeCount();\r
+  bi.UserTime = ::GetUserTime();\r
+}\r
+\r
+static void SetFinishTime(const CBenchInfo &biStart, CBenchInfo &dest)\r
+{\r
+  dest.GlobalFreq = GetFreq();\r
+  dest.UserFreq = GetUserFreq();\r
+  dest.GlobalTime = ::GetTimeCount() - biStart.GlobalTime;\r
+  dest.UserTime = ::GetUserTime() - biStart.UserTime;\r
+}\r
+\r
+STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)\r
+{\r
+  HRESULT res = Status->GetResult();\r
+  if (res != S_OK)\r
+    return res;\r
+  if (!callback)\r
+    return res;\r
+  CBenchInfo info = BenchInfo;\r
+  SetFinishTime(BenchInfo, info);\r
+  if (Status->EncodeMode)\r
+  {\r
+    info.UnpackSize = *inSize;\r
+    info.PackSize = *outSize;\r
+    res = callback->SetEncodeResult(info, false);\r
+  }\r
+  else\r
+  {\r
+    info.PackSize = BenchInfo.PackSize + *inSize;\r
+    info.UnpackSize = BenchInfo.UnpackSize + *outSize;\r
+    res = callback->SetDecodeResult(info, false);\r
+  }\r
+  if (res != S_OK)\r
+    Status->SetResult(res);\r
+  return res;\r
+}\r
+\r
+static const int kSubBits = 8;\r
+\r
+static UInt32 GetLogSize(UInt32 size)\r
+{\r
+  for (int i = kSubBits; i < 32; i++)\r
+    for (UInt32 j = 0; j < (1 << kSubBits); j++)\r
+      if (size <= (((UInt32)1) << i) + (j << (i - kSubBits)))\r
+        return (i << kSubBits) + j;\r
+  return (32 << kSubBits);\r
+}\r
+\r
+static void NormalizeVals(UInt64 &v1, UInt64 &v2)\r
+{\r
+  while (v1 > 1000000)\r
+  {\r
+    v1 >>= 1;\r
+    v2 >>= 1;\r
+  }\r
+}\r
+\r
+UInt64 GetUsage(const CBenchInfo &info)\r
+{\r
+  UInt64 userTime = info.UserTime;\r
+  UInt64 userFreq = info.UserFreq;\r
+  UInt64 globalTime = info.GlobalTime;\r
+  UInt64 globalFreq = info.GlobalFreq;\r
+  NormalizeVals(userTime, userFreq);\r
+  NormalizeVals(globalFreq, globalTime);\r
+  if (userFreq == 0)\r
+    userFreq = 1;\r
+  if (globalTime == 0)\r
+    globalTime = 1;\r
+  return userTime * globalFreq * 1000000 / userFreq / globalTime;\r
+}\r
+\r
+UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating)\r
+{\r
+  UInt64 userTime = info.UserTime;\r
+  UInt64 userFreq = info.UserFreq;\r
+  UInt64 globalTime = info.GlobalTime;\r
+  UInt64 globalFreq = info.GlobalFreq;\r
+  NormalizeVals(userFreq, userTime);\r
+  NormalizeVals(globalTime, globalFreq);\r
+  if (globalFreq == 0)\r
+    globalFreq = 1;\r
+  if (userTime == 0)\r
+    userTime = 1;\r
+  return userFreq * globalTime / globalFreq *  rating / userTime;\r
+}\r
+\r
+static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq)\r
+{\r
+  UInt64 elTime = elapsedTime;\r
+  NormalizeVals(freq, elTime);\r
+  if (elTime == 0)\r
+    elTime = 1;\r
+  return value * freq / elTime;\r
+}\r
+\r
+UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size)\r
+{\r
+  UInt64 t = GetLogSize(dictionarySize) - (kBenchMinDicLogSize << kSubBits);\r
+  UInt64 numCommandsForOne = 870 + ((t * t * 5) >> (2 * kSubBits));\r
+  UInt64 numCommands = (UInt64)(size) * numCommandsForOne;\r
+  return MyMultDiv64(numCommands, elapsedTime, freq);\r
+}\r
+\r
+UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations)\r
+{\r
+  UInt64 numCommands = (inSize * 200 + outSize * 4) * numIterations;\r
+  return MyMultDiv64(numCommands, elapsedTime, freq);\r
+}\r
+\r
+struct CEncoderInfo;\r
+\r
+struct CEncoderInfo\r
+{\r
+  #ifndef _7ZIP_ST\r
+  NWindows::CThread thread[2];\r
+  #endif\r
+  CMyComPtr<ICompressCoder> encoder;\r
+  CBenchProgressInfo *progressInfoSpec[2];\r
+  CMyComPtr<ICompressProgressInfo> progressInfo[2];\r
+  UInt32 NumIterations;\r
+  #ifdef USE_ALLOCA\r
+  size_t AllocaSize;\r
+  #endif\r
+\r
+  struct CDecoderInfo\r
+  {\r
+    CEncoderInfo *Encoder;\r
+    UInt32 DecoderIndex;\r
+    #ifdef USE_ALLOCA\r
+    size_t AllocaSize;\r
+    #endif\r
+    bool CallbackMode;\r
+  };\r
+  CDecoderInfo decodersInfo[2];\r
+\r
+  CMyComPtr<ICompressCoder> decoders[2];\r
+  HRESULT Results[2];\r
+  CBenchmarkOutStream *outStreamSpec;\r
+  CMyComPtr<ISequentialOutStream> outStream;\r
+  IBenchCallback *callback;\r
+  UInt32 crc;\r
+  UInt32 kBufferSize;\r
+  UInt32 compressedSize;\r
+  CBenchRandomGenerator rg;\r
+  CBenchmarkOutStream *propStreamSpec;\r
+  CMyComPtr<ISequentialOutStream> propStream;\r
+  HRESULT Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rg);\r
+  HRESULT Encode();\r
+  HRESULT Decode(UInt32 decoderIndex);\r
+\r
+  CEncoderInfo(): outStreamSpec(0), callback(0), propStreamSpec(0) {}\r
+\r
+  #ifndef _7ZIP_ST\r
+  static THREAD_FUNC_DECL EncodeThreadFunction(void *param)\r
+  {\r
+    CEncoderInfo *encoder = (CEncoderInfo *)param;\r
+    #ifdef USE_ALLOCA\r
+    alloca(encoder->AllocaSize);\r
+    #endif\r
+    HRESULT res = encoder->Encode();\r
+    encoder->Results[0] = res;\r
+    if (res != S_OK)\r
+      encoder->progressInfoSpec[0]->Status->SetResult(res);\r
+\r
+    return 0;\r
+  }\r
+  static THREAD_FUNC_DECL DecodeThreadFunction(void *param)\r
+  {\r
+    CDecoderInfo *decoder = (CDecoderInfo *)param;\r
+    #ifdef USE_ALLOCA\r
+    alloca(decoder->AllocaSize);\r
+    #endif\r
+    CEncoderInfo *encoder = decoder->Encoder;\r
+    encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex);\r
+    return 0;\r
+  }\r
+\r
+  HRESULT CreateEncoderThread()\r
+  {\r
+    return thread[0].Create(EncodeThreadFunction, this);\r
+  }\r
+\r
+  HRESULT CreateDecoderThread(int index, bool callbackMode\r
+      #ifdef USE_ALLOCA\r
+      , size_t allocaSize\r
+      #endif\r
+      )\r
+  {\r
+    CDecoderInfo &decoder = decodersInfo[index];\r
+    decoder.DecoderIndex = index;\r
+    decoder.Encoder = this;\r
+    #ifdef USE_ALLOCA\r
+    decoder.AllocaSize = allocaSize;\r
+    #endif\r
+    decoder.CallbackMode = callbackMode;\r
+    return thread[index].Create(DecodeThreadFunction, &decoder);\r
+  }\r
+  #endif\r
+};\r
+\r
+HRESULT CEncoderInfo::Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rgLoc)\r
+{\r
+  rg.Set(rgLoc);\r
+  kBufferSize = dictionarySize + kAdditionalSize;\r
+  UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;\r
+  if (!rg.Alloc(kBufferSize))\r
+    return E_OUTOFMEMORY;\r
+  rg.Generate();\r
+  crc = CrcCalc(rg.Buffer, rg.BufferSize);\r
+\r
+  outStreamSpec = new CBenchmarkOutStream;\r
+  if (!outStreamSpec->Alloc(kCompressedBufferSize))\r
+    return E_OUTOFMEMORY;\r
+\r
+  outStream = outStreamSpec;\r
+\r
+  propStreamSpec = 0;\r
+  if (!propStream)\r
+  {\r
+    propStreamSpec = new CBenchmarkOutStream;\r
+    propStream = propStreamSpec;\r
+  }\r
+  if (!propStreamSpec->Alloc(kMaxLzmaPropSize))\r
+    return E_OUTOFMEMORY;\r
+  propStreamSpec->Init();\r
+  \r
+  PROPID propIDs[] =\r
+  {\r
+    NCoderPropID::kDictionarySize,\r
+    NCoderPropID::kNumThreads\r
+  };\r
+  const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);\r
+  PROPVARIANT props[kNumProps];\r
+  props[0].vt = VT_UI4;\r
+  props[0].ulVal = dictionarySize;\r
+\r
+  props[1].vt = VT_UI4;\r
+  props[1].ulVal = numThreads;\r
+\r
+  {\r
+    CMyComPtr<ICompressSetCoderProperties> setCoderProperties;\r
+    RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties));\r
+    if (!setCoderProperties)\r
+      return E_FAIL;\r
+    RINOK(setCoderProperties->SetCoderProperties(propIDs, props, kNumProps));\r
+\r
+    CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;\r
+    encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties);\r
+    if (writeCoderProperties)\r
+    {\r
+      RINOK(writeCoderProperties->WriteCoderProperties(propStream));\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CEncoderInfo::Encode()\r
+{\r
+  CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;\r
+  CMyComPtr<ISequentialInStream> inStream = inStreamSpec;\r
+  inStreamSpec->Init(rg.Buffer, rg.BufferSize);\r
+  outStreamSpec->Init();\r
+\r
+  RINOK(encoder->Code(inStream, outStream, 0, 0, progressInfo[0]));\r
+  compressedSize = outStreamSpec->Pos;\r
+  encoder.Release();\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CEncoderInfo::Decode(UInt32 decoderIndex)\r
+{\r
+  CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;\r
+  CMyComPtr<ISequentialInStream> inStream = inStreamSpec;\r
+  CMyComPtr<ICompressCoder> &decoder = decoders[decoderIndex];\r
+\r
+  CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties;\r
+  decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties);\r
+  if (!compressSetDecoderProperties)\r
+    return E_FAIL;\r
+\r
+  CCrcOutStream *crcOutStreamSpec = new CCrcOutStream;\r
+  CMyComPtr<ISequentialOutStream> crcOutStream = crcOutStreamSpec;\r
+    \r
+  CBenchProgressInfo *pi = progressInfoSpec[decoderIndex];\r
+  pi->BenchInfo.UnpackSize = 0;\r
+  pi->BenchInfo.PackSize = 0;\r
+\r
+  for (UInt32 j = 0; j < NumIterations; j++)\r
+  {\r
+    inStreamSpec->Init(outStreamSpec->Buffer, compressedSize);\r
+    crcOutStreamSpec->Init();\r
+    \r
+    RINOK(compressSetDecoderProperties->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos));\r
+    UInt64 outSize = kBufferSize;\r
+    RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex]));\r
+    if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc)\r
+      return S_FALSE;\r
+    pi->BenchInfo.UnpackSize += kBufferSize;\r
+    pi->BenchInfo.PackSize += compressedSize;\r
+  }\r
+  decoder.Release();\r
+  return S_OK;\r
+}\r
+\r
+static const UInt32 kNumThreadsMax = (1 << 16);\r
+\r
+struct CBenchEncoders\r
+{\r
+  CEncoderInfo *encoders;\r
+  CBenchEncoders(UInt32 num): encoders(0) { encoders = new CEncoderInfo[num]; }\r
+  ~CBenchEncoders() { delete []encoders; }\r
+};\r
+\r
+HRESULT LzmaBench(\r
+  DECL_EXTERNAL_CODECS_LOC_VARS\r
+  UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback)\r
+{\r
+  UInt32 numEncoderThreads =\r
+    #ifndef _7ZIP_ST\r
+    (numThreads > 1 ? numThreads / 2 : 1);\r
+    #else\r
+    1;\r
+    #endif\r
+  UInt32 numSubDecoderThreads =\r
+    #ifndef _7ZIP_ST\r
+    (numThreads > 1 ? 2 : 1);\r
+    #else\r
+    1;\r
+    #endif\r
+  if (dictionarySize < (1 << kBenchMinDicLogSize) || numThreads < 1 || numEncoderThreads > kNumThreadsMax)\r
+  {\r
+    return E_INVALIDARG;\r
+  }\r
+\r
+  CBenchEncoders encodersSpec(numEncoderThreads);\r
+  CEncoderInfo *encoders = encodersSpec.encoders;\r
+\r
+\r
+  UInt32 i;\r
+  for (i = 0; i < numEncoderThreads; i++)\r
+  {\r
+    CEncoderInfo &encoder = encoders[i];\r
+    encoder.callback = (i == 0) ? callback : 0;\r
+\r
+    const UInt32 kLzmaId = 0x030101;\r
+    RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS kLzmaId, encoder.encoder, true));\r
+    if (!encoder.encoder)\r
+      return E_NOTIMPL;\r
+    for (UInt32 j = 0; j < numSubDecoderThreads; j++)\r
+    {\r
+      RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS kLzmaId, encoder.decoders[j], false));\r
+      if (!encoder.decoders[j])\r
+        return E_NOTIMPL;\r
+    }\r
+  }\r
+\r
+  CBaseRandomGenerator rg;\r
+  rg.Init();\r
+  for (i = 0; i < numEncoderThreads; i++)\r
+  {\r
+    RINOK(encoders[i].Init(dictionarySize, numThreads, &rg));\r
+  }\r
+\r
+  CBenchProgressStatus status;\r
+  status.Res = S_OK;\r
+  status.EncodeMode = true;\r
+\r
+  for (i = 0; i < numEncoderThreads; i++)\r
+  {\r
+    CEncoderInfo &encoder = encoders[i];\r
+    for (int j = 0; j < 2; j++)\r
+    {\r
+      encoder.progressInfo[j] = encoder.progressInfoSpec[j] = new CBenchProgressInfo;\r
+      encoder.progressInfoSpec[j]->Status = &status;\r
+    }\r
+    if (i == 0)\r
+    {\r
+      encoder.progressInfoSpec[0]->callback = callback;\r
+      encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numEncoderThreads;\r
+      SetStartTime(encoder.progressInfoSpec[0]->BenchInfo);\r
+    }\r
+\r
+    #ifndef _7ZIP_ST\r
+    if (numEncoderThreads > 1)\r
+    {\r
+      #ifdef USE_ALLOCA\r
+      encoder.AllocaSize = (i * 16 * 21) & 0x7FF;\r
+      #endif\r
+      RINOK(encoder.CreateEncoderThread())\r
+    }\r
+    else\r
+    #endif\r
+    {\r
+      RINOK(encoder.Encode());\r
+    }\r
+  }\r
+  #ifndef _7ZIP_ST\r
+  if (numEncoderThreads > 1)\r
+    for (i = 0; i < numEncoderThreads; i++)\r
+      encoders[i].thread[0].Wait();\r
+  #endif\r
+\r
+  RINOK(status.Res);\r
+\r
+  CBenchInfo info;\r
+\r
+  SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info);\r
+  info.UnpackSize = 0;\r
+  info.PackSize = 0;\r
+  info.NumIterations = 1; // progressInfoSpec->NumIterations;\r
+  for (i = 0; i < numEncoderThreads; i++)\r
+  {\r
+    CEncoderInfo &encoder = encoders[i];\r
+    info.UnpackSize += encoder.kBufferSize;\r
+    info.PackSize += encoder.compressedSize;\r
+  }\r
+  RINOK(callback->SetEncodeResult(info, true));\r
+\r
+\r
+  status.Res = S_OK;\r
+  status.EncodeMode = false;\r
+\r
+  UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads;\r
+  for (i = 0; i < numEncoderThreads; i++)\r
+  {\r
+    CEncoderInfo &encoder = encoders[i];\r
+    encoder.NumIterations = 2 + kUncompressMinBlockSize / encoder.kBufferSize;\r
+\r
+    if (i == 0)\r
+    {\r
+      encoder.progressInfoSpec[0]->callback = callback;\r
+      encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numDecoderThreads;\r
+      SetStartTime(encoder.progressInfoSpec[0]->BenchInfo);\r
+    }\r
+\r
+    #ifndef _7ZIP_ST\r
+    if (numDecoderThreads > 1)\r
+    {\r
+      for (UInt32 j = 0; j < numSubDecoderThreads; j++)\r
+      {\r
+        HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0)\r
+            #ifdef USE_ALLOCA\r
+            , ((i * numSubDecoderThreads + j) * 16 * 21) & 0x7FF\r
+            #endif\r
+            );\r
+        RINOK(res);\r
+      }\r
+    }\r
+    else\r
+    #endif\r
+    {\r
+      RINOK(encoder.Decode(0));\r
+    }\r
+  }\r
+  #ifndef _7ZIP_ST\r
+  HRESULT res = S_OK;\r
+  if (numDecoderThreads > 1)\r
+    for (i = 0; i < numEncoderThreads; i++)\r
+      for (UInt32 j = 0; j < numSubDecoderThreads; j++)\r
+      {\r
+        CEncoderInfo &encoder = encoders[i];\r
+        encoder.thread[j].Wait();\r
+        if (encoder.Results[j] != S_OK)\r
+          res = encoder.Results[j];\r
+      }\r
+  RINOK(res);\r
+  #endif\r
+  RINOK(status.Res);\r
+  SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info);\r
+  #ifndef _7ZIP_ST\r
+  #ifdef UNDER_CE\r
+  if (numDecoderThreads > 1)\r
+    for (i = 0; i < numEncoderThreads; i++)\r
+      for (UInt32 j = 0; j < numSubDecoderThreads; j++)\r
+      {\r
+        FILETIME creationTime, exitTime, kernelTime, userTime;\r
+        if (::GetThreadTimes(encoders[i].thread[j], &creationTime, &exitTime, &kernelTime, &userTime) != 0)\r
+          info.UserTime += GetTime64(userTime) + GetTime64(kernelTime);\r
+      }\r
+  #endif\r
+  #endif\r
+  info.UnpackSize = 0;\r
+  info.PackSize = 0;\r
+  info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations;\r
+  for (i = 0; i < numEncoderThreads; i++)\r
+  {\r
+    CEncoderInfo &encoder = encoders[i];\r
+    info.UnpackSize += encoder.kBufferSize;\r
+    info.PackSize += encoder.compressedSize;\r
+  }\r
+  RINOK(callback->SetDecodeResult(info, false));\r
+  RINOK(callback->SetDecodeResult(info, true));\r
+  return S_OK;\r
+}\r
+\r
+\r
+inline UInt64 GetLZMAUsage(bool multiThread, UInt32 dictionary)\r
+{\r
+  UInt32 hs = dictionary - 1;\r
+  hs |= (hs >> 1);\r
+  hs |= (hs >> 2);\r
+  hs |= (hs >> 4);\r
+  hs |= (hs >> 8);\r
+  hs >>= 1;\r
+  hs |= 0xFFFF;\r
+  if (hs > (1 << 24))\r
+    hs >>= 1;\r
+  hs++;\r
+  return ((hs + (1 << 16)) + (UInt64)dictionary * 2) * 4 + (UInt64)dictionary * 3 / 2 +\r
+      (1 << 20) + (multiThread ? (6 << 20) : 0);\r
+}\r
+\r
+UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary)\r
+{\r
+  const UInt32 kBufferSize = dictionary;\r
+  const UInt32 kCompressedBufferSize = (kBufferSize / 2);\r
+  UInt32 numSubThreads = (numThreads > 1) ? 2 : 1;\r
+  UInt32 numBigThreads = numThreads / numSubThreads;\r
+  return (kBufferSize + kCompressedBufferSize +\r
+    GetLZMAUsage((numThreads > 1), dictionary) + (2 << 20)) * numBigThreads;\r
+}\r
+\r
+static bool CrcBig(const void *data, UInt32 size, UInt32 numCycles, UInt32 crcBase)\r
+{\r
+  for (UInt32 i = 0; i < numCycles; i++)\r
+    if (CrcCalc(data, size) != crcBase)\r
+      return false;\r
+  return true;\r
+}\r
+\r
+#ifndef _7ZIP_ST\r
+struct CCrcInfo\r
+{\r
+  NWindows::CThread Thread;\r
+  const Byte *Data;\r
+  UInt32 Size;\r
+  UInt32 NumCycles;\r
+  UInt32 Crc;\r
+  bool Res;\r
+  void Wait()\r
+  {\r
+    Thread.Wait();\r
+    Thread.Close();\r
+  }\r
+};\r
+\r
+static THREAD_FUNC_DECL CrcThreadFunction(void *param)\r
+{\r
+  CCrcInfo *p = (CCrcInfo *)param;\r
+  p->Res = CrcBig(p->Data, p->Size, p->NumCycles, p->Crc);\r
+  return 0;\r
+}\r
+\r
+struct CCrcThreads\r
+{\r
+  UInt32 NumThreads;\r
+  CCrcInfo *Items;\r
+  CCrcThreads(): Items(0), NumThreads(0) {}\r
+  void WaitAll()\r
+  {\r
+    for (UInt32 i = 0; i < NumThreads; i++)\r
+      Items[i].Wait();\r
+    NumThreads = 0;\r
+  }\r
+  ~CCrcThreads()\r
+  {\r
+    WaitAll();\r
+    delete []Items;\r
+  }\r
+};\r
+#endif\r
+\r
+static UInt32 CrcCalc1(const Byte *buf, UInt32 size)\r
+{\r
+  UInt32 crc = CRC_INIT_VAL;;\r
+  for (UInt32 i = 0; i < size; i++)\r
+    crc = CRC_UPDATE_BYTE(crc, buf[i]);\r
+  return CRC_GET_DIGEST(crc);\r
+}\r
+\r
+static void RandGen(Byte *buf, UInt32 size, CBaseRandomGenerator &RG)\r
+{\r
+  for (UInt32 i = 0; i < size; i++)\r
+    buf[i] = (Byte)RG.GetRnd();\r
+}\r
+\r
+static UInt32 RandGenCrc(Byte *buf, UInt32 size, CBaseRandomGenerator &RG)\r
+{\r
+  RandGen(buf, size, RG);\r
+  return CrcCalc1(buf, size);\r
+}\r
+\r
+bool CrcInternalTest()\r
+{\r
+  CBenchBuffer buffer;\r
+  const UInt32 kBufferSize0 = (1 << 8);\r
+  const UInt32 kBufferSize1 = (1 << 10);\r
+  const UInt32 kCheckSize = (1 << 5);\r
+  if (!buffer.Alloc(kBufferSize0 + kBufferSize1))\r
+    return false;\r
+  Byte *buf = buffer.Buffer;\r
+  UInt32 i;\r
+  for (i = 0; i < kBufferSize0; i++)\r
+    buf[i] = (Byte)i;\r
+  UInt32 crc1 = CrcCalc1(buf, kBufferSize0);\r
+  if (crc1 != 0x29058C73)\r
+    return false;\r
+  CBaseRandomGenerator RG;\r
+  RandGen(buf + kBufferSize0, kBufferSize1, RG);\r
+  for (i = 0; i < kBufferSize0 + kBufferSize1 - kCheckSize; i++)\r
+    for (UInt32 j = 0; j < kCheckSize; j++)\r
+      if (CrcCalc1(buf + i, j) != CrcCalc(buf + i, j))\r
+        return false;\r
+  return true;\r
+}\r
+\r
+HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed)\r
+{\r
+  if (numThreads == 0)\r
+    numThreads = 1;\r
+\r
+  CBenchBuffer buffer;\r
+  size_t totalSize = (size_t)bufferSize * numThreads;\r
+  if (totalSize / numThreads != bufferSize)\r
+    return E_OUTOFMEMORY;\r
+  if (!buffer.Alloc(totalSize))\r
+    return E_OUTOFMEMORY;\r
+\r
+  Byte *buf = buffer.Buffer;\r
+  CBaseRandomGenerator RG;\r
+  UInt32 numCycles = (kCrcBlockSize) / ((bufferSize >> 2) + 1) + 1;\r
+\r
+  UInt64 timeVal;\r
+  #ifndef _7ZIP_ST\r
+  CCrcThreads threads;\r
+  if (numThreads > 1)\r
+  {\r
+    threads.Items = new CCrcInfo[numThreads];\r
+    UInt32 i;\r
+    for (i = 0; i < numThreads; i++)\r
+    {\r
+      CCrcInfo &info = threads.Items[i];\r
+      Byte *data = buf + (size_t)bufferSize * i;\r
+      info.Data = data;\r
+      info.NumCycles = numCycles;\r
+      info.Size = bufferSize;\r
+      info.Crc = RandGenCrc(data, bufferSize, RG);\r
+    }\r
+    timeVal = GetTimeCount();\r
+    for (i = 0; i < numThreads; i++)\r
+    {\r
+      CCrcInfo &info = threads.Items[i];\r
+      RINOK(info.Thread.Create(CrcThreadFunction, &info));\r
+      threads.NumThreads++;\r
+    }\r
+    threads.WaitAll();\r
+    for (i = 0; i < numThreads; i++)\r
+      if (!threads.Items[i].Res)\r
+        return S_FALSE;\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    UInt32 crc = RandGenCrc(buf, bufferSize, RG);\r
+    timeVal = GetTimeCount();\r
+    if (!CrcBig(buf, bufferSize, numCycles, crc))\r
+      return S_FALSE;\r
+  }\r
+  timeVal = GetTimeCount() - timeVal;\r
+  if (timeVal == 0)\r
+    timeVal = 1;\r
+\r
+  UInt64 size = (UInt64)numCycles * totalSize;\r
+  speed = MyMultDiv64(size, timeVal, GetFreq());\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/UI/Common/Bench.h b/CPP/7zip/UI/Common/Bench.h
new file mode 100755 (executable)
index 0000000..f6e8064
--- /dev/null
@@ -0,0 +1,42 @@
+// Bench.h\r
+\r
+#ifndef __7ZIP_BENCH_H\r
+#define __7ZIP_BENCH_H\r
+\r
+#include "../../Common/CreateCoder.h"\r
+\r
+struct CBenchInfo\r
+{\r
+  UInt64 GlobalTime;\r
+  UInt64 GlobalFreq;\r
+  UInt64 UserTime;\r
+  UInt64 UserFreq;\r
+  UInt64 UnpackSize;\r
+  UInt64 PackSize;\r
+  UInt32 NumIterations;\r
+  CBenchInfo(): NumIterations(0) {}\r
+};\r
+\r
+struct IBenchCallback\r
+{\r
+  virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0;\r
+  virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0;\r
+};\r
+\r
+UInt64 GetUsage(const CBenchInfo &benchOnfo);\r
+UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating);\r
+UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size);\r
+UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations);\r
+\r
+HRESULT LzmaBench(\r
+  DECL_EXTERNAL_CODECS_LOC_VARS\r
+  UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback);\r
+\r
+const int kBenchMinDicLogSize = 18;\r
+\r
+UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary);\r
+\r
+bool CrcInternalTest();\r
+HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/CompressCall.cpp b/CPP/7zip/UI/Common/CompressCall.cpp
new file mode 100755 (executable)
index 0000000..5d591a0
--- /dev/null
@@ -0,0 +1,246 @@
+// CompressCall.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/MyCom.h"\r
+#include "Common/Random.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileMapping.h"\r
+#include "Windows/Process.h"\r
+#include "Windows/Synchronization.h"\r
+\r
+#include "../FileManager/ProgramLocation.h"\r
+#include "../FileManager/RegistryUtils.h"\r
+\r
+#include "CompressCall.h"\r
+\r
+using namespace NWindows;\r
+\r
+#define MY_TRY_BEGIN try {\r
+#define MY_TRY_FINISH } \\r
+  catch(...) { ErrorMessageHRESULT(E_FAIL); return E_FAIL; }\r
+\r
+static LPCWSTR kShowDialogSwitch = L" -ad";\r
+static LPCWSTR kEmailSwitch = L" -seml.";\r
+static LPCWSTR kIncludeSwitch = L" -i";\r
+static LPCWSTR kArchiveTypeSwitch = L" -t";\r
+static LPCWSTR kArcIncludeSwitches = L" -an -ai";\r
+static LPCWSTR kStopSwitchParsing = L" --";\r
+static LPCWSTR kLargePagesDisable = L" -slp-";\r
+\r
+UString GetQuotedString(const UString &s)\r
+{\r
+  return UString(L'\"') + s + UString(L'\"');\r
+}\r
+static void ErrorMessage(LPCWSTR message)\r
+{\r
+  MessageBoxW(g_HWND, message, L"7-Zip", MB_ICONERROR | MB_OK);\r
+}\r
+\r
+static void ErrorMessageHRESULT(HRESULT res, LPCWSTR s = NULL)\r
+{\r
+  UString s2 = HResultToMessage(res);\r
+  if (s)\r
+  {\r
+    s2 += L'\n';\r
+    s2 += s;\r
+  }\r
+  ErrorMessage(s2);\r
+}\r
+\r
+static HRESULT MyCreateProcess(LPCWSTR imageName, const UString &params,\r
+    LPCWSTR curDir, bool waitFinish,\r
+    NSynchronization::CBaseEvent *event)\r
+{\r
+  CProcess process;\r
+  WRes res = process.Create(imageName, params, curDir);\r
+  if (res != 0)\r
+  {\r
+    ErrorMessageHRESULT(res, imageName);\r
+    return res;\r
+  }\r
+  if (waitFinish)\r
+    process.Wait();\r
+  else if (event != NULL)\r
+  {\r
+    HANDLE handles[] = { process, *event };\r
+    ::WaitForMultipleObjects(sizeof(handles) / sizeof(handles[0]), handles, FALSE, INFINITE);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+static void AddLagePagesSwitch(UString &params)\r
+{\r
+  if (!ReadLockMemoryEnable())\r
+    params += kLargePagesDisable;\r
+}\r
+\r
+static UString Get7zGuiPath()\r
+{\r
+  UString path;\r
+  GetProgramFolderPath(path);\r
+  return path + L"7zG.exe";\r
+}\r
+\r
+class CRandNameGenerator\r
+{\r
+  CRandom _random;\r
+public:\r
+  CRandNameGenerator() { _random.Init(); }\r
+  UString GenerateName()\r
+  {\r
+    wchar_t temp[16];\r
+    ConvertUInt32ToString((UInt32)_random.Generate(), temp);\r
+    return temp;\r
+  }\r
+};\r
+\r
+static HRESULT CreateMap(const UStringVector &names,\r
+    CFileMapping &fileMapping, NSynchronization::CManualResetEvent &event,\r
+    UString &params)\r
+{\r
+  UInt32 totalSize = 1;\r
+  for (int i = 0; i < names.Size(); i++)\r
+    totalSize += (names[i].Length() + 1);\r
+  totalSize *= sizeof(wchar_t);\r
+  \r
+  CRandNameGenerator random;\r
+\r
+  UString mappingName;\r
+  for (;;)\r
+  {\r
+    mappingName = L"7zMap" + random.GenerateName();\r
+\r
+    WRes res = fileMapping.Create(PAGE_READWRITE, totalSize, GetSystemString(mappingName));\r
+    if (fileMapping.IsCreated() && res == 0)\r
+      break;\r
+    if (res != ERROR_ALREADY_EXISTS)\r
+      return res;\r
+    fileMapping.Close();\r
+  }\r
+  \r
+  UString eventName;\r
+  for (;;)\r
+  {\r
+    eventName = L"7zEvent" + random.GenerateName();\r
+    WRes res = event.CreateWithName(false, GetSystemString(eventName));\r
+    if (event.IsCreated() && res == 0)\r
+      break;\r
+    if (res != ERROR_ALREADY_EXISTS)\r
+      return res;\r
+    event.Close();\r
+  }\r
+\r
+  params += L'#';\r
+  params += mappingName;\r
+  params += L':';\r
+  wchar_t temp[16];\r
+  ConvertUInt32ToString(totalSize, temp);\r
+  params += temp;\r
+  \r
+  params += L':';\r
+  params += eventName;\r
+\r
+  LPVOID data = fileMapping.Map(FILE_MAP_WRITE, 0, totalSize);\r
+  if (data == NULL)\r
+    return E_FAIL;\r
+  CFileUnmapper unmapper(data);\r
+  {\r
+    wchar_t *cur = (wchar_t *)data;\r
+    *cur++ = 0;\r
+    for (int i = 0; i < names.Size(); i++)\r
+    {\r
+      const UString &s = names[i];\r
+      int len = s.Length() + 1;\r
+      memcpy(cur, (const wchar_t *)s, len * sizeof(wchar_t));\r
+      cur += len;\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CompressFiles(\r
+    const UString &arcPathPrefix,\r
+    const UString &arcName,\r
+    const UString &arcType,\r
+    const UStringVector &names,\r
+    bool email, bool showDialog, bool waitFinish)\r
+{\r
+  MY_TRY_BEGIN\r
+  UString params = L'a';\r
+  \r
+  CFileMapping fileMapping;\r
+  NSynchronization::CManualResetEvent event;\r
+  params += kIncludeSwitch;\r
+  RINOK(CreateMap(names, fileMapping, event, params));\r
+\r
+  if (!arcType.IsEmpty())\r
+  {\r
+    params += kArchiveTypeSwitch;\r
+    params += arcType;\r
+  }\r
+\r
+  if (email)\r
+    params += kEmailSwitch;\r
+\r
+  if (showDialog)\r
+    params += kShowDialogSwitch;\r
+\r
+  AddLagePagesSwitch(params);\r
+\r
+  params += kStopSwitchParsing;\r
+  params += L' ';\r
+  \r
+  params += GetQuotedString(\r
+    #ifdef UNDER_CE\r
+    arcPathPrefix +\r
+    #endif\r
+    arcName);\r
+  \r
+  return MyCreateProcess(Get7zGuiPath(), params,\r
+      (arcPathPrefix.IsEmpty()? 0: (LPCWSTR)arcPathPrefix), waitFinish, &event);\r
+  MY_TRY_FINISH\r
+}\r
+\r
+static HRESULT ExtractGroupCommand(const UStringVector &arcPaths, UString &params)\r
+{\r
+  AddLagePagesSwitch(params);\r
+  params += kArcIncludeSwitches;\r
+  CFileMapping fileMapping;\r
+  NSynchronization::CManualResetEvent event;\r
+  RINOK(CreateMap(arcPaths, fileMapping, event, params));\r
+  return MyCreateProcess(Get7zGuiPath(), params, 0, false, &event);\r
+}\r
+\r
+HRESULT ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog)\r
+{\r
+  MY_TRY_BEGIN\r
+  UString params = L'x';\r
+  if (!outFolder.IsEmpty())\r
+  {\r
+    params += L" -o";\r
+    params += GetQuotedString(outFolder);\r
+  }\r
+  if (showDialog)\r
+    params += kShowDialogSwitch;\r
+  return ExtractGroupCommand(arcPaths, params);\r
+  MY_TRY_FINISH\r
+}\r
+\r
+HRESULT TestArchives(const UStringVector &arcPaths)\r
+{\r
+  MY_TRY_BEGIN\r
+  UString params = L't';\r
+  return ExtractGroupCommand(arcPaths, params);\r
+  MY_TRY_FINISH\r
+}\r
+\r
+HRESULT Benchmark()\r
+{\r
+  MY_TRY_BEGIN\r
+  return MyCreateProcess(Get7zGuiPath(), L'b', 0, false, NULL);\r
+  MY_TRY_FINISH\r
+}\r
diff --git a/CPP/7zip/UI/Common/CompressCall.h b/CPP/7zip/UI/Common/CompressCall.h
new file mode 100755 (executable)
index 0000000..8cb4241
--- /dev/null
@@ -0,0 +1,24 @@
+// CompressCall.h\r
+\r
+#ifndef __COMPRESS_CALL_H\r
+#define __COMPRESS_CALL_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+UString GetQuotedString(const UString &s);\r
+\r
+extern HWND g_HWND;\r
+UString HResultToMessage(HRESULT errorCode);\r
+\r
+HRESULT CompressFiles(\r
+    const UString &arcPathPrefix,\r
+    const UString &arcName,\r
+    const UString &arcType,\r
+    const UStringVector &names,\r
+    bool email, bool showDialog, bool waitFinish);\r
+\r
+HRESULT ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog);\r
+HRESULT TestArchives(const UStringVector &arcPaths);\r
+HRESULT Benchmark();\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/CompressCall2.cpp b/CPP/7zip/UI/Common/CompressCall2.cpp
new file mode 100755 (executable)
index 0000000..913afd8
--- /dev/null
@@ -0,0 +1,178 @@
+// CompressCall.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/MyException.h"\r
+\r
+#include "../../UI/common/ArchiveCommandLine.h"\r
+\r
+#include "../../UI/GUI/BenchmarkDialog.h"\r
+#include "../../UI/GUI/ExtractGUI.h"\r
+#include "../../UI/GUI/UpdateGUI.h"\r
+\r
+#include "../../UI/GUI/ExtractRes.h"\r
+\r
+#include "CompressCall.h"\r
+\r
+#define MY_TRY_BEGIN try {\r
+#define MY_TRY_FINISH } \\r
+  catch(CSystemException &e) { result = e.ErrorCode; } \\r
+  catch(...) { result = E_FAIL; } \\r
+  if (result != S_OK && result != E_ABORT) \\r
+    ErrorMessageHRESULT(result);\r
+\r
+#define CREATE_CODECS \\r
+  CCodecs *codecs = new CCodecs; \\r
+  CMyComPtr<IUnknown> compressCodecsInfo = codecs; \\r
+  result = codecs->Load(); \\r
+  if (result != S_OK) \\r
+    throw CSystemException(result);\r
+\r
+UString GetQuotedString(const UString &s)\r
+{\r
+  return UString(L'\"') + s + UString(L'\"');\r
+}\r
+\r
+static void ErrorMessage(LPCWSTR message)\r
+{\r
+  MessageBoxW(g_HWND, message, L"7-Zip", MB_ICONERROR);\r
+}\r
+\r
+static void ErrorMessageHRESULT(HRESULT res)\r
+{\r
+  ErrorMessage(HResultToMessage(res));\r
+}\r
+\r
+static void ErrorLangMessage(UINT resourceID, UInt32 langID)\r
+{\r
+  ErrorMessage(LangString(resourceID, langID));\r
+}\r
+\r
+HRESULT CompressFiles(\r
+    const UString &arcPathPrefix,\r
+    const UString &arcName,\r
+    const UString &arcType,\r
+    const UStringVector &names,\r
+    bool email, bool showDialog, bool /* waitFinish */)\r
+{\r
+  HRESULT result;\r
+  MY_TRY_BEGIN\r
+  CREATE_CODECS\r
+\r
+  CUpdateCallbackGUI callback;\r
+  \r
+  callback.Init();\r
+\r
+  CUpdateOptions uo;\r
+  uo.EMailMode = email;\r
+  uo.SetAddActionCommand();\r
+\r
+  CIntVector formatIndices;\r
+  if (!codecs->FindFormatForArchiveType(arcType, formatIndices))\r
+  {\r
+    ErrorLangMessage(IDS_UNSUPPORTED_ARCHIVE_TYPE, 0x0200060D);\r
+    return E_FAIL;\r
+  }\r
+  if (!uo.Init(codecs, formatIndices, arcPathPrefix + arcName))\r
+  {\r
+    ErrorLangMessage(IDS_UPDATE_NOT_SUPPORTED, 0x02000601);\r
+    return E_FAIL;\r
+  }\r
+\r
+  NWildcard::CCensor censor;\r
+  for (int i = 0; i < names.Size(); i++)\r
+    censor.AddItem(true, names[i], false);\r
+\r
+  bool messageWasDisplayed = false;\r
+  result = UpdateGUI(codecs, censor, uo, showDialog, messageWasDisplayed, &callback, g_HWND);\r
+  \r
+  if (result != S_OK)\r
+  {\r
+    if (result != E_ABORT && messageWasDisplayed)\r
+      return E_FAIL;\r
+    throw CSystemException(result);\r
+  }\r
+  if (callback.FailedFiles.Size() > 0)\r
+  {\r
+    if (!messageWasDisplayed)\r
+      throw CSystemException(E_FAIL);\r
+    return E_FAIL;\r
+  }\r
+  MY_TRY_FINISH\r
+  return S_OK;\r
+}\r
+\r
+static HRESULT ExtractGroupCommand(const UStringVector &arcPaths,\r
+    bool showDialog, const UString &outFolder, bool testMode)\r
+{\r
+  HRESULT result;\r
+  MY_TRY_BEGIN\r
+  CREATE_CODECS\r
+\r
+  CExtractOptions eo;\r
+  eo.OutputDir = outFolder;\r
+  eo.TestMode = testMode;\r
+\r
+  CExtractCallbackImp *ecs = new CExtractCallbackImp;\r
+  CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;\r
+  \r
+  ecs->Init();\r
+  \r
+  // eo.CalcCrc = options.CalcCrc;\r
+  \r
+  UStringVector arcPathsSorted;\r
+  UStringVector arcFullPathsSorted;\r
+  {\r
+    NWildcard::CCensor acrCensor;\r
+    for (int i = 0; i < arcPaths.Size(); i++)\r
+      acrCensor.AddItem(true, arcPaths[i], false);\r
+    EnumerateDirItemsAndSort(acrCensor, arcPathsSorted, arcFullPathsSorted);\r
+  }\r
+  \r
+  CIntVector formatIndices;\r
+\r
+  NWildcard::CCensor censor;\r
+  censor.AddItem(true, L"*", false);\r
+  \r
+  bool messageWasDisplayed = false;\r
+  result = ExtractGUI(codecs, formatIndices, arcPathsSorted, arcFullPathsSorted,\r
+      censor.Pairs.Front().Head, eo, showDialog, messageWasDisplayed, ecs, g_HWND);\r
+  if (result != S_OK)\r
+  {\r
+    if (result != E_ABORT && messageWasDisplayed)\r
+      return E_FAIL;\r
+    throw CSystemException(result);\r
+  }\r
+  return ecs->IsOK() ? S_OK : E_FAIL;\r
+  MY_TRY_FINISH\r
+  return result;\r
+}\r
+\r
+HRESULT ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog)\r
+{\r
+  return ExtractGroupCommand(arcPaths, showDialog, outFolder, false);\r
+}\r
+\r
+HRESULT TestArchives(const UStringVector &arcPaths)\r
+{\r
+  return ExtractGroupCommand(arcPaths, true, UString(), true);\r
+}\r
+\r
+HRESULT Benchmark()\r
+{\r
+  HRESULT result;\r
+  MY_TRY_BEGIN\r
+  CREATE_CODECS\r
+\r
+  #ifdef EXTERNAL_CODECS\r
+  CObjectVector<CCodecInfoEx> externalCodecs;\r
+  RINOK(LoadExternalCodecs(codecs, externalCodecs));\r
+  #endif\r
+  result = Benchmark(\r
+      #ifdef EXTERNAL_CODECS\r
+      codecs, &externalCodecs,\r
+      #endif\r
+      (UInt32)-1, (UInt32)-1, g_HWND);\r
+  MY_TRY_FINISH\r
+  return result;\r
+}\r
diff --git a/CPP/7zip/UI/Common/DefaultName.cpp b/CPP/7zip/UI/Common/DefaultName.cpp
new file mode 100755 (executable)
index 0000000..5c46500
--- /dev/null
@@ -0,0 +1,35 @@
+// DefaultName.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "DefaultName.h"\r
+\r
+static UString GetDefaultName3(const UString &fileName,\r
+    const UString &extension, const UString &addSubExtension)\r
+{\r
+  int extLength = extension.Length();\r
+  int fileNameLength = fileName.Length();\r
+  if (fileNameLength > extLength + 1)\r
+  {\r
+    int dotPos = fileNameLength - (extLength + 1);\r
+    if (fileName[dotPos] == '.')\r
+      if (extension.CompareNoCase(fileName.Mid(dotPos + 1)) == 0)\r
+        return fileName.Left(dotPos) + addSubExtension;\r
+  }\r
+  int dotPos = fileName.ReverseFind(L'.');\r
+  if (dotPos > 0)\r
+    return fileName.Left(dotPos) + addSubExtension;\r
+\r
+  if (addSubExtension.IsEmpty())\r
+    return fileName + L"~";\r
+  else\r
+    return fileName + addSubExtension;\r
+}\r
+\r
+UString GetDefaultName2(const UString &fileName,\r
+    const UString &extension, const UString &addSubExtension)\r
+{\r
+  UString name = GetDefaultName3(fileName, extension, addSubExtension);\r
+  name.TrimRight();\r
+  return name;\r
+}\r
diff --git a/CPP/7zip/UI/Common/DefaultName.h b/CPP/7zip/UI/Common/DefaultName.h
new file mode 100755 (executable)
index 0000000..3989a1f
--- /dev/null
@@ -0,0 +1,11 @@
+// DefaultName.h\r
+\r
+#ifndef __DEFAULTNAME_H\r
+#define __DEFAULTNAME_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+UString GetDefaultName2(const UString &fileName,\r
+    const UString &extension, const UString &addSubExtension);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h
new file mode 100755 (executable)
index 0000000..e10d6b9
--- /dev/null
@@ -0,0 +1,69 @@
+// DirItem.h\r
+\r
+#ifndef __DIR_ITEM_H\r
+#define __DIR_ITEM_H\r
+\r
+#include "Common/MyString.h"\r
+#include "Common/Types.h"\r
+#include "../../Archive/IArchive.h"\r
+\r
+struct CDirItem\r
+{\r
+  UInt64 Size;\r
+  FILETIME CTime;\r
+  FILETIME ATime;\r
+  FILETIME MTime;\r
+  UString Name;\r
+  UInt32 Attrib;\r
+  int PhyParent;\r
+  int LogParent;\r
+  \r
+  CDirItem(): PhyParent(-1), LogParent(-1) {}\r
+  bool IsDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; }\r
+};\r
+\r
+class CDirItems\r
+{\r
+  UStringVector Prefixes;\r
+  CIntVector PhyParents;\r
+  CIntVector LogParents;\r
+\r
+  UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const;\r
+public:\r
+  CObjectVector<CDirItem> Items;\r
+\r
+  int GetNumFolders() const { return Prefixes.Size(); }\r
+  UString GetPhyPath(int index) const;\r
+  UString GetLogPath(int index) const;\r
+\r
+  int AddPrefix(int phyParent, int logParent, const UString &prefix);\r
+  void DeleteLastPrefix();\r
+\r
+  void EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix,\r
+    UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes);\r
+\r
+  void EnumerateDirItems2(\r
+    const UString &phyPrefix,\r
+    const UString &logPrefix,\r
+    const UStringVector &filePaths,\r
+    UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes);\r
+\r
+  void ReserveDown();\r
+};\r
+\r
+struct CArcItem\r
+{\r
+  UInt64 Size;\r
+  FILETIME MTime;\r
+  UString Name;\r
+  bool IsDir;\r
+  bool SizeDefined;\r
+  bool MTimeDefined;\r
+  bool Censored;\r
+  UInt32 IndexInServer;\r
+  int TimeType;\r
+  \r
+  CArcItem(): IsDir(false), SizeDefined(false), MTimeDefined(false), Censored(false), TimeType(-1) {}\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp
new file mode 100755 (executable)
index 0000000..61ecaba
--- /dev/null
@@ -0,0 +1,361 @@
+// EnumDirItems.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "EnumDirItems.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+using namespace NName;\r
+\r
+void AddDirFileInfo(int phyParent, int logParent,\r
+    const NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems)\r
+{\r
+  CDirItem di;\r
+  di.Size = fi.Size;\r
+  di.CTime = fi.CTime;\r
+  di.ATime = fi.ATime;\r
+  di.MTime = fi.MTime;\r
+  di.Attrib = fi.Attrib;\r
+  di.PhyParent = phyParent;\r
+  di.LogParent = logParent;\r
+  di.Name = fi.Name;\r
+  dirItems.Add(di);\r
+}\r
+\r
+UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const\r
+{\r
+  UString path;\r
+  int len = name.Length();\r
+  int i;\r
+  for (i = index; i >= 0; i = parents[i])\r
+    len += Prefixes[i].Length();\r
+  int totalLen = len;\r
+  wchar_t *p = path.GetBuffer(len);\r
+  p[len] = 0;\r
+  len -= name.Length();\r
+  memcpy(p + len, (const wchar_t *)name, name.Length() * sizeof(wchar_t));\r
+  for (i = index; i >= 0; i = parents[i])\r
+  {\r
+    const UString &s = Prefixes[i];\r
+    len -= s.Length();\r
+    memcpy(p + len, (const wchar_t *)s, s.Length() * sizeof(wchar_t));\r
+  }\r
+  path.ReleaseBuffer(totalLen);\r
+  return path;\r
+}\r
+\r
+UString CDirItems::GetPhyPath(int index) const\r
+{\r
+  const CDirItem &di = Items[index];\r
+  return GetPrefixesPath(PhyParents, di.PhyParent, di.Name);\r
+}\r
+\r
+UString CDirItems::GetLogPath(int index) const\r
+{\r
+  const CDirItem &di = Items[index];\r
+  return GetPrefixesPath(LogParents, di.LogParent, di.Name);\r
+}\r
+\r
+void CDirItems::ReserveDown()\r
+{\r
+  Prefixes.ReserveDown();\r
+  PhyParents.ReserveDown();\r
+  LogParents.ReserveDown();\r
+  Items.ReserveDown();\r
+}\r
+\r
+int CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix)\r
+{\r
+  PhyParents.Add(phyParent);\r
+  LogParents.Add(logParent);\r
+  return Prefixes.Add(prefix);\r
+}\r
+\r
+void CDirItems::DeleteLastPrefix()\r
+{\r
+  PhyParents.DeleteBack();\r
+  LogParents.DeleteBack();\r
+  Prefixes.DeleteBack();\r
+}\r
+\r
+void CDirItems::EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix,\r
+    UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes)\r
+{\r
+  NFind::CEnumeratorW enumerator(phyPrefix + (wchar_t)kAnyStringWildcard);\r
+  for (;;)\r
+  {\r
+    NFind::CFileInfoW fi;\r
+    bool found;\r
+    if (!enumerator.Next(fi, found))\r
+    {\r
+      errorCodes.Add(::GetLastError());\r
+      errorPaths.Add(phyPrefix);\r
+      return;\r
+    }\r
+    if (!found)\r
+      break;\r
+    AddDirFileInfo(phyParent, logParent, fi, Items);\r
+    if (fi.IsDir())\r
+    {\r
+      const UString name2 = fi.Name + (wchar_t)kDirDelimiter;\r
+      int parent = AddPrefix(phyParent, logParent, name2);\r
+      EnumerateDirectory(parent, parent, phyPrefix + name2, errorPaths, errorCodes);\r
+    }\r
+  }\r
+}\r
+\r
+void CDirItems::EnumerateDirItems2(const UString &phyPrefix, const UString &logPrefix,\r
+    const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes)\r
+{\r
+  int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, phyPrefix);\r
+  int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix);\r
+\r
+  for (int i = 0; i < filePaths.Size(); i++)\r
+  {\r
+    const UString &filePath = filePaths[i];\r
+    NFind::CFileInfoW fi;\r
+    const UString phyPath = phyPrefix + filePath;\r
+    if (!fi.Find(phyPath))\r
+    {\r
+      errorCodes.Add(::GetLastError());\r
+      errorPaths.Add(phyPath);\r
+      continue;\r
+    }\r
+    int delimiter = filePath.ReverseFind((wchar_t)kDirDelimiter);\r
+    UString phyPrefixCur;\r
+    int phyParentCur = phyParent;\r
+    if (delimiter >= 0)\r
+    {\r
+      phyPrefixCur = filePath.Left(delimiter + 1);\r
+      phyParentCur = AddPrefix(phyParent, logParent, phyPrefixCur);\r
+    }\r
+    AddDirFileInfo(phyParentCur, logParent, fi, Items);\r
+    if (fi.IsDir())\r
+    {\r
+      const UString name2 = fi.Name + (wchar_t)kDirDelimiter;\r
+      int parent = AddPrefix(phyParentCur, logParent, name2);\r
+      EnumerateDirectory(parent, parent, phyPrefix + phyPrefixCur + name2, errorPaths, errorCodes);\r
+    }\r
+  }\r
+  ReserveDown();\r
+}\r
+\r
+static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode,\r
+    int phyParent, int logParent, const UString &phyPrefix,\r
+    const UStringVector &addArchivePrefix,\r
+    CDirItems &dirItems,\r
+    bool enterToSubFolders,\r
+    IEnumDirItemCallback *callback,\r
+    UStringVector &errorPaths,\r
+    CRecordVector<DWORD> &errorCodes);\r
+\r
+static HRESULT EnumerateDirItems_Spec(const NWildcard::CCensorNode &curNode,\r
+    int phyParent, int logParent, const UString &curFolderName,\r
+    const UString &phyPrefix,\r
+    const UStringVector &addArchivePrefix,\r
+    CDirItems &dirItems,\r
+    bool enterToSubFolders,\r
+    IEnumDirItemCallback *callback,\r
+    UStringVector &errorPaths,\r
+    CRecordVector<DWORD> &errorCodes)\r
+  \r
+{\r
+  const UString name2 = curFolderName + (wchar_t)kDirDelimiter;\r
+  int parent = dirItems.AddPrefix(phyParent, logParent, name2);\r
+  int numItems = dirItems.Items.Size();\r
+  HRESULT res = EnumerateDirItems(curNode, parent, parent, phyPrefix + name2,\r
+    addArchivePrefix, dirItems, enterToSubFolders, callback, errorPaths, errorCodes);\r
+  if (numItems == dirItems.Items.Size())\r
+    dirItems.DeleteLastPrefix();\r
+  return res;\r
+}\r
+\r
+\r
+static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode,\r
+    int phyParent, int logParent, const UString &phyPrefix,\r
+    const UStringVector &addArchivePrefix,  // prefix from curNode\r
+    CDirItems &dirItems,\r
+    bool enterToSubFolders,\r
+    IEnumDirItemCallback *callback,\r
+    UStringVector &errorPaths,\r
+    CRecordVector<DWORD> &errorCodes)\r
+{\r
+  if (!enterToSubFolders)\r
+    if (curNode.NeedCheckSubDirs())\r
+      enterToSubFolders = true;\r
+  if (callback)\r
+    RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix));\r
+\r
+  // try direct_names case at first\r
+  if (addArchivePrefix.IsEmpty() && !enterToSubFolders)\r
+  {\r
+    // check that all names are direct\r
+    int i;\r
+    for (i = 0; i < curNode.IncludeItems.Size(); i++)\r
+    {\r
+      const NWildcard::CItem &item = curNode.IncludeItems[i];\r
+      if (item.Recursive || item.PathParts.Size() != 1)\r
+        break;\r
+      const UString &name = item.PathParts.Front();\r
+      if (name.IsEmpty() || DoesNameContainWildCard(name))\r
+        break;\r
+    }\r
+    if (i == curNode.IncludeItems.Size())\r
+    {\r
+      // all names are direct (no wildcards)\r
+      // so we don't need file_system's dir enumerator\r
+      CRecordVector<bool> needEnterVector;\r
+      for (i = 0; i < curNode.IncludeItems.Size(); i++)\r
+      {\r
+        const NWildcard::CItem &item = curNode.IncludeItems[i];\r
+        const UString &name = item.PathParts.Front();\r
+        const UString fullPath = phyPrefix + name;\r
+        NFind::CFileInfoW fi;\r
+        if (!fi.Find(fullPath))\r
+        {\r
+          errorCodes.Add(::GetLastError());\r
+          errorPaths.Add(fullPath);\r
+          continue;\r
+        }\r
+        bool isDir = fi.IsDir();\r
+        if (isDir && !item.ForDir || !isDir && !item.ForFile)\r
+        {\r
+          errorCodes.Add((DWORD)E_FAIL);\r
+          errorPaths.Add(fullPath);\r
+          continue;\r
+        }\r
+        {\r
+          UStringVector pathParts;\r
+          pathParts.Add(fi.Name);\r
+          if (curNode.CheckPathToRoot(false, pathParts, !isDir))\r
+            continue;\r
+        }\r
+        AddDirFileInfo(phyParent, logParent, fi, dirItems.Items);\r
+        if (!isDir)\r
+          continue;\r
+        \r
+        UStringVector addArchivePrefixNew;\r
+        const NWildcard::CCensorNode *nextNode = 0;\r
+        int index = curNode.FindSubNode(name);\r
+        if (index >= 0)\r
+        {\r
+          for (int t = needEnterVector.Size(); t <= index; t++)\r
+            needEnterVector.Add(true);\r
+          needEnterVector[index] = false;\r
+          nextNode = &curNode.SubNodes[index];\r
+        }\r
+        else\r
+        {\r
+          nextNode = &curNode;\r
+          addArchivePrefixNew.Add(name); // don't change it to fi.Name. It's for shortnames support\r
+        }\r
+\r
+        RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix,\r
+            addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes));\r
+      }\r
+      for (i = 0; i < curNode.SubNodes.Size(); i++)\r
+      {\r
+        if (i < needEnterVector.Size())\r
+          if (!needEnterVector[i])\r
+            continue;\r
+        const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i];\r
+        const UString fullPath = phyPrefix + nextNode.Name;\r
+        NFind::CFileInfoW fi;\r
+        if (!fi.Find(fullPath))\r
+        {\r
+          if (!nextNode.AreThereIncludeItems())\r
+            continue;\r
+          errorCodes.Add(::GetLastError());\r
+          errorPaths.Add(fullPath);\r
+          continue;\r
+        }\r
+        if (!fi.IsDir())\r
+        {\r
+          errorCodes.Add((DWORD)E_FAIL);\r
+          errorPaths.Add(fullPath);\r
+          continue;\r
+        }\r
+\r
+        RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix,\r
+            UStringVector(), dirItems, false, callback, errorPaths, errorCodes));\r
+      }\r
+      return S_OK;\r
+    }\r
+  }\r
+\r
+\r
+  NFind::CEnumeratorW enumerator(phyPrefix + wchar_t(kAnyStringWildcard));\r
+  for (int ttt = 0; ; ttt++)\r
+  {\r
+    NFind::CFileInfoW fi;\r
+    bool found;\r
+    if (!enumerator.Next(fi, found))\r
+    {\r
+      errorCodes.Add(::GetLastError());\r
+      errorPaths.Add(phyPrefix);\r
+      break;\r
+    }\r
+    if (!found)\r
+      break;\r
+\r
+    if (callback && (ttt & 0xFF) == 0xFF)\r
+      RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix));\r
+    const UString &name = fi.Name;\r
+    bool enterToSubFolders2 = enterToSubFolders;\r
+    UStringVector addArchivePrefixNew = addArchivePrefix;\r
+    addArchivePrefixNew.Add(name);\r
+    {\r
+      UStringVector addArchivePrefixNewTemp(addArchivePrefixNew);\r
+      if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir()))\r
+        continue;\r
+    }\r
+    if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir()))\r
+    {\r
+      AddDirFileInfo(phyParent, logParent, fi, dirItems.Items);\r
+      if (fi.IsDir())\r
+        enterToSubFolders2 = true;\r
+    }\r
+    if (!fi.IsDir())\r
+      continue;\r
+\r
+    const NWildcard::CCensorNode *nextNode = 0;\r
+    if (addArchivePrefix.IsEmpty())\r
+    {\r
+      int index = curNode.FindSubNode(name);\r
+      if (index >= 0)\r
+        nextNode = &curNode.SubNodes[index];\r
+    }\r
+    if (!enterToSubFolders2 && nextNode == 0)\r
+      continue;\r
+\r
+    addArchivePrefixNew = addArchivePrefix;\r
+    if (nextNode == 0)\r
+    {\r
+      nextNode = &curNode;\r
+      addArchivePrefixNew.Add(name);\r
+    }\r
+\r
+    RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, name, phyPrefix,\r
+        addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes));\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT EnumerateItems(\r
+    const NWildcard::CCensor &censor,\r
+    CDirItems &dirItems,\r
+    IEnumDirItemCallback *callback,\r
+    UStringVector &errorPaths,\r
+    CRecordVector<DWORD> &errorCodes)\r
+{\r
+  for (int i = 0; i < censor.Pairs.Size(); i++)\r
+  {\r
+    const NWildcard::CPair &pair = censor.Pairs[i];\r
+    int phyParent = pair.Prefix.IsEmpty() ? -1 : dirItems.AddPrefix(-1, -1, pair.Prefix);\r
+    RINOK(EnumerateDirItems(pair.Head, phyParent, -1, pair.Prefix, UStringVector(), dirItems, false,\r
+        callback, errorPaths, errorCodes));\r
+  }\r
+  dirItems.ReserveDown();\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/UI/Common/EnumDirItems.h b/CPP/7zip/UI/Common/EnumDirItems.h
new file mode 100755 (executable)
index 0000000..835ae02
--- /dev/null
@@ -0,0 +1,25 @@
+// EnumDirItems.h\r
+\r
+#ifndef __ENUM_DIR_ITEMS_H\r
+#define __ENUM_DIR_ITEMS_H\r
+\r
+#include "Common/Wildcard.h"\r
+#include "Windows/FileFind.h"\r
+#include "DirItem.h"\r
+\r
+void AddDirFileInfo(int phyParent, int logParent,\r
+    const NWindows::NFile::NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems);\r
+\r
+struct IEnumDirItemCallback\r
+{\r
+  virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) = 0;\r
+};\r
+\r
+HRESULT EnumerateItems(\r
+    const NWildcard::CCensor &censor,\r
+    CDirItems &dirItems,\r
+    IEnumDirItemCallback *callback,\r
+    UStringVector &errorPaths,\r
+    CRecordVector<DWORD> &errorCodes);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/ExitCode.h b/CPP/7zip/UI/Common/ExitCode.h
new file mode 100755 (executable)
index 0000000..d03ec6d
--- /dev/null
@@ -0,0 +1,27 @@
+// ExitCode.h\r
+\r
+#ifndef __EXIT_CODE_H\r
+#define __EXIT_CODE_H\r
+\r
+namespace NExitCode {\r
+\r
+enum EEnum {\r
+\r
+  kSuccess       = 0,     // Successful operation\r
+  kWarning       = 1,     // Non fatal error(s) occurred\r
+  kFatalError    = 2,     // A fatal error occurred\r
+  // kCRCError      = 3,     // A CRC error occurred when unpacking\r
+  // kLockedArchive = 4,     // Attempt to modify an archive previously locked\r
+  // kWriteError    = 5,     // Write to disk error\r
+  // kOpenError     = 6,     // Open file error\r
+  kUserError     = 7,     // Command line option error\r
+  kMemoryError   = 8,     // Not enough memory for operation\r
+  // kCreateFileError = 9,     // Create file error\r
+  \r
+  kUserBreak     = 255   // User stopped the process\r
+\r
+};\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp
new file mode 100755 (executable)
index 0000000..2f5a293
--- /dev/null
@@ -0,0 +1,263 @@
+// Extract.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include <stdio.h>\r
+\r
+#include "Windows/FileDir.h"\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/PropVariantConversions.h"\r
+\r
+#include "../Common/ExtractingFilePath.h"\r
+\r
+#include "Extract.h"\r
+#include "SetProperties.h"\r
+\r
+using namespace NWindows;\r
+\r
+static HRESULT DecompressArchive(\r
+    const CArc &arc,\r
+    UInt64 packSize,\r
+    const NWildcard::CCensorNode &wildcardCensor,\r
+    const CExtractOptions &options,\r
+    IExtractCallbackUI *callback,\r
+    CArchiveExtractCallback *extractCallbackSpec,\r
+    UString &errorMessage,\r
+    UInt64 &stdInProcessed)\r
+{\r
+  stdInProcessed = 0;\r
+  IInArchive *archive = arc.Archive;\r
+  CRecordVector<UInt32> realIndices;\r
+  if (!options.StdInMode)\r
+  {\r
+    UInt32 numItems;\r
+    RINOK(archive->GetNumberOfItems(&numItems));\r
+    \r
+    for (UInt32 i = 0; i < numItems; i++)\r
+    {\r
+      UString filePath;\r
+      RINOK(arc.GetItemPath(i, filePath));\r
+      bool isFolder;\r
+      RINOK(IsArchiveItemFolder(archive, i, isFolder));\r
+      if (!wildcardCensor.CheckPath(filePath, !isFolder))\r
+        continue;\r
+      realIndices.Add(i);\r
+    }\r
+    if (realIndices.Size() == 0)\r
+    {\r
+      callback->ThereAreNoFiles();\r
+      return S_OK;\r
+    }\r
+  }\r
+\r
+  UStringVector removePathParts;\r
+\r
+  UString outDir = options.OutputDir;\r
+  outDir.Replace(L"*", GetCorrectFsPath(arc.DefaultName));\r
+  #ifdef _WIN32\r
+  // GetCorrectFullFsPath doesn't like "..".\r
+  // outDir.TrimRight();\r
+  // outDir = GetCorrectFullFsPath(outDir);\r
+  #endif\r
+\r
+  if (!outDir.IsEmpty())\r
+    if (!NFile::NDirectory::CreateComplexDirectory(outDir))\r
+    {\r
+      HRESULT res = ::GetLastError();\r
+      if (res == S_OK)\r
+        res = E_FAIL;\r
+      errorMessage = ((UString)L"Can not create output directory ") + outDir;\r
+      return res;\r
+    }\r
+\r
+  extractCallbackSpec->Init(\r
+      options.StdInMode ? &wildcardCensor : NULL,\r
+      &arc,\r
+      callback,\r
+      options.StdOutMode, options.TestMode, options.CalcCrc,\r
+      outDir,\r
+      removePathParts,\r
+      packSize);\r
+\r
+  #if !defined(_7ZIP_ST) && !defined(_SFX)\r
+  RINOK(SetProperties(archive, options.Properties));\r
+  #endif\r
+\r
+  HRESULT result;\r
+  Int32 testMode = (options.TestMode && !options.CalcCrc) ? 1: 0;\r
+  if (options.StdInMode)\r
+  {\r
+    result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, extractCallbackSpec);\r
+    NCOM::CPropVariant prop;\r
+    if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK)\r
+      if (prop.vt == VT_UI8 || prop.vt == VT_UI4)\r
+        stdInProcessed = ConvertPropVariantToUInt64(prop);\r
+  }\r
+  else\r
+    result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, extractCallbackSpec);\r
+\r
+  return callback->ExtractResult(result);\r
+}\r
+\r
+HRESULT DecompressArchives(\r
+    CCodecs *codecs, const CIntVector &formatIndices,\r
+    UStringVector &arcPaths, UStringVector &arcPathsFull,\r
+    const NWildcard::CCensorNode &wildcardCensor,\r
+    const CExtractOptions &options,\r
+    IOpenCallbackUI *openCallback,\r
+    IExtractCallbackUI *extractCallback,\r
+    UString &errorMessage,\r
+    CDecompressStat &stat)\r
+{\r
+  stat.Clear();\r
+  int i;\r
+  UInt64 totalPackSize = 0;\r
+  CRecordVector<UInt64> archiveSizes;\r
+\r
+  int numArcs = options.StdInMode ? 1 : arcPaths.Size();\r
+\r
+  for (i = 0; i < numArcs; i++)\r
+  {\r
+    NFile::NFind::CFileInfoW fi;\r
+    fi.Size = 0;\r
+    if (!options.StdInMode)\r
+    {\r
+      const UString &arcPath = arcPaths[i];\r
+      if (!fi.Find(arcPath))\r
+        throw "there is no such archive";\r
+      if (fi.IsDir())\r
+        throw "can't decompress folder";\r
+    }\r
+    archiveSizes.Add(fi.Size);\r
+    totalPackSize += fi.Size;\r
+  }\r
+  CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;\r
+  CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec);\r
+  bool multi = (numArcs > 1);\r
+  extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode);\r
+  if (multi)\r
+  {\r
+    RINOK(extractCallback->SetTotal(totalPackSize));\r
+  }\r
+  for (i = 0; i < numArcs; i++)\r
+  {\r
+    const UString &arcPath = arcPaths[i];\r
+    NFile::NFind::CFileInfoW fi;\r
+    if (options.StdInMode)\r
+    {\r
+      fi.Size = 0;\r
+      fi.Attrib = 0;\r
+    }\r
+    else\r
+    {\r
+      if (!fi.Find(arcPath) || fi.IsDir())\r
+        throw "there is no such archive";\r
+    }\r
+\r
+    #ifndef _NO_CRYPTO\r
+    openCallback->Open_ClearPasswordWasAskedFlag();\r
+    #endif\r
+\r
+    RINOK(extractCallback->BeforeOpen(arcPath));\r
+    CArchiveLink archiveLink;\r
+\r
+    CIntVector formatIndices2 = formatIndices;\r
+    #ifndef _SFX\r
+    if (formatIndices.IsEmpty())\r
+    {\r
+      int pos = arcPath.ReverseFind(L'.');\r
+      if (pos >= 0)\r
+      {\r
+        UString s = arcPath.Mid(pos + 1);\r
+        int index = codecs->FindFormatForExtension(s);\r
+        if (index >= 0 && s == L"001")\r
+        {\r
+          s = arcPath.Left(pos);\r
+          pos = s.ReverseFind(L'.');\r
+          if (pos >= 0)\r
+          {\r
+            int index2 = codecs->FindFormatForExtension(s.Mid(pos + 1));\r
+            if (index2 >= 0 && s.CompareNoCase(L"rar") != 0)\r
+            {\r
+              formatIndices2.Add(index2);\r
+              formatIndices2.Add(index);\r
+            }\r
+          }\r
+        }\r
+      }\r
+    }\r
+    #endif\r
+    HRESULT result = archiveLink.Open2(codecs, formatIndices2, options.StdInMode, NULL, arcPath, openCallback);\r
+    if (result == E_ABORT)\r
+      return result;\r
+\r
+    bool crypted = false;\r
+    #ifndef _NO_CRYPTO\r
+    crypted = openCallback->Open_WasPasswordAsked();\r
+    #endif\r
+\r
+    RINOK(extractCallback->OpenResult(arcPath, result, crypted));\r
+    if (result != S_OK)\r
+      continue;\r
+\r
+    if (!options.StdInMode)\r
+    for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)\r
+    {\r
+      int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]);\r
+      if (index >= 0 && index > i)\r
+      {\r
+        arcPaths.Delete(index);\r
+        arcPathsFull.Delete(index);\r
+        totalPackSize -= archiveSizes[index];\r
+        archiveSizes.Delete(index);\r
+        numArcs = arcPaths.Size();\r
+      }\r
+    }\r
+    if (archiveLink.VolumePaths.Size() != 0)\r
+    {\r
+      totalPackSize += archiveLink.VolumesSize;\r
+      RINOK(extractCallback->SetTotal(totalPackSize));\r
+    }\r
+\r
+    #ifndef _NO_CRYPTO\r
+    UString password;\r
+    RINOK(openCallback->Open_GetPasswordIfAny(password));\r
+    if (!password.IsEmpty())\r
+    {\r
+      RINOK(extractCallback->SetPassword(password));\r
+    }\r
+    #endif\r
+\r
+    for (int v = 0; v < archiveLink.Arcs.Size(); v++)\r
+    {\r
+      const UString &s = archiveLink.Arcs[v].ErrorMessage;\r
+      if (!s.IsEmpty())\r
+      {\r
+        RINOK(extractCallback->MessageError(s));\r
+      }\r
+    }\r
+\r
+    CArc &arc = archiveLink.Arcs.Back();\r
+    arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice);\r
+    arc.MTime = fi.MTime;\r
+\r
+    UInt64 packProcessed;\r
+    RINOK(DecompressArchive(arc,\r
+        fi.Size + archiveLink.VolumesSize,\r
+        wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage, packProcessed));\r
+    if (!options.StdInMode)\r
+      packProcessed = fi.Size + archiveLink.VolumesSize;\r
+    extractCallbackSpec->LocalProgressSpec->InSize += packProcessed;\r
+    extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize;\r
+    if (!errorMessage.IsEmpty())\r
+      return E_FAIL;\r
+  }\r
+  stat.NumFolders = extractCallbackSpec->NumFolders;\r
+  stat.NumFiles = extractCallbackSpec->NumFiles;\r
+  stat.UnpackSize = extractCallbackSpec->UnpackSize;\r
+  stat.CrcSum = extractCallbackSpec->CrcSum;\r
+\r
+  stat.NumArchives = arcPaths.Size();\r
+  stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize;\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/UI/Common/Extract.h b/CPP/7zip/UI/Common/Extract.h
new file mode 100755 (executable)
index 0000000..70926d7
--- /dev/null
@@ -0,0 +1,76 @@
+// Extract.h\r
+\r
+#ifndef __EXTRACT_H\r
+#define __EXTRACT_H\r
+\r
+#include "Windows/FileFind.h"\r
+\r
+#include "../../Archive/IArchive.h"\r
+\r
+#include "ArchiveExtractCallback.h"\r
+#include "ArchiveOpenCallback.h"\r
+#include "ExtractMode.h"\r
+#include "Property.h"\r
+\r
+#include "../Common/LoadCodecs.h"\r
+\r
+struct CExtractOptions\r
+{\r
+  bool StdInMode;\r
+  bool StdOutMode;\r
+  bool YesToAll;\r
+  bool TestMode;\r
+  bool CalcCrc;\r
+  NExtract::NPathMode::EEnum PathMode;\r
+  NExtract::NOverwriteMode::EEnum OverwriteMode;\r
+  UString OutputDir;\r
+  \r
+  // bool ShowDialog;\r
+  // bool PasswordEnabled;\r
+  // UString Password;\r
+  #if !defined(_7ZIP_ST) && !defined(_SFX)\r
+  CObjectVector<CProperty> Properties;\r
+  #endif\r
+\r
+  #ifdef EXTERNAL_CODECS\r
+  CCodecs *Codecs;\r
+  #endif\r
+\r
+  CExtractOptions():\r
+      StdInMode(false),\r
+      StdOutMode(false),\r
+      YesToAll(false),\r
+      TestMode(false),\r
+      CalcCrc(false),\r
+      PathMode(NExtract::NPathMode::kFullPathnames),\r
+      OverwriteMode(NExtract::NOverwriteMode::kAskBefore)\r
+      {}\r
+};\r
+\r
+struct CDecompressStat\r
+{\r
+  UInt64 NumArchives;\r
+  UInt64 UnpackSize;\r
+  UInt64 PackSize;\r
+  UInt64 NumFolders;\r
+  UInt64 NumFiles;\r
+  UInt32 CrcSum;\r
+\r
+  void Clear()\r
+  {\r
+    NumArchives = UnpackSize = PackSize = NumFolders = NumFiles = 0;\r
+    CrcSum = 0;\r
+  }\r
+};\r
+\r
+HRESULT DecompressArchives(\r
+    CCodecs *codecs, const CIntVector &formatIndices,\r
+    UStringVector &archivePaths, UStringVector &archivePathsFull,\r
+    const NWildcard::CCensorNode &wildcardCensor,\r
+    const CExtractOptions &options,\r
+    IOpenCallbackUI *openCallback,\r
+    IExtractCallbackUI *extractCallback,\r
+    UString &errorMessage,\r
+    CDecompressStat &stat);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/ExtractMode.h b/CPP/7zip/UI/Common/ExtractMode.h
new file mode 100755 (executable)
index 0000000..44c4053
--- /dev/null
@@ -0,0 +1,31 @@
+// ExtractMode.h\r
+\r
+#ifndef __EXTRACT_MODE_H\r
+#define __EXTRACT_MODE_H\r
+\r
+namespace NExtract {\r
+  \r
+  namespace NPathMode\r
+  {\r
+    enum EEnum\r
+    {\r
+      kFullPathnames,\r
+      kCurrentPathnames,\r
+      kNoPathnames\r
+    };\r
+  }\r
+  \r
+  namespace NOverwriteMode\r
+  {\r
+    enum EEnum\r
+    {\r
+      kAskBefore,\r
+      kWithoutPrompt,\r
+      kSkipExisting,\r
+      kAutoRename,\r
+      kAutoRenameExisting\r
+    };\r
+  }\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp
new file mode 100755 (executable)
index 0000000..604148a
--- /dev/null
@@ -0,0 +1,142 @@
+// ExtractingFilePath.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/Types.h"\r
+\r
+#include "Common/Wildcard.h"\r
+\r
+#include "ExtractingFilePath.h"\r
+\r
+static UString ReplaceIncorrectChars(const UString &s)\r
+{\r
+  #ifdef _WIN32\r
+  UString res;\r
+  for (int i = 0; i < s.Length(); i++)\r
+  {\r
+    wchar_t c = s[i];\r
+    if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>'  || c == '|' || c == ':' || c == '"')\r
+      c = '_';\r
+    res += c;\r
+  }\r
+  res.TrimRight();\r
+  while (!res.IsEmpty() && res[res.Length() - 1] == '.')\r
+    res.Delete(res.Length() - 1);\r
+  return res;\r
+  #else\r
+  return s;\r
+  #endif\r
+}\r
+\r
+#ifdef _WIN32\r
+static const wchar_t *g_ReservedNames[] =\r
+{\r
+  L"CON", L"PRN", L"AUX", L"NUL"\r
+};\r
+\r
+static bool CheckTail(const UString &name, int len)\r
+{\r
+  int dotPos = name.Find(L'.');\r
+  if (dotPos < 0)\r
+    dotPos = name.Length();\r
+  UString s = name.Left(dotPos);\r
+  s.TrimRight();\r
+  return (s.Length() != len);\r
+}\r
+\r
+static bool CheckNameNum(const UString &name, const wchar_t *reservedName)\r
+{\r
+  int len = MyStringLen(reservedName);\r
+  if (name.Length() <= len)\r
+    return true;\r
+  if (name.Left(len).CompareNoCase(reservedName) != 0)\r
+    return true;\r
+  wchar_t c = name[len];\r
+  if (c < L'0' || c > L'9')\r
+    return true;\r
+  return CheckTail(name, len + 1);\r
+}\r
+\r
+static bool IsSupportedName(const UString &name)\r
+{\r
+  for (int i = 0; i < sizeof(g_ReservedNames) / sizeof(g_ReservedNames[0]); i++)\r
+  {\r
+    const wchar_t *reservedName = g_ReservedNames[i];\r
+    int len = MyStringLen(reservedName);\r
+    if (name.Length() < len)\r
+      continue;\r
+    if (name.Left(len).CompareNoCase(reservedName) != 0)\r
+      continue;\r
+    if (!CheckTail(name, len))\r
+      return false;\r
+  }\r
+  if (!CheckNameNum(name, L"COM"))\r
+    return false;\r
+  return CheckNameNum(name, L"LPT");\r
+}\r
+#endif\r
+\r
+static UString GetCorrectFileName(const UString &path)\r
+{\r
+  if (path == L".." || path == L".")\r
+    return UString();\r
+  return ReplaceIncorrectChars(path);\r
+}\r
+\r
+void MakeCorrectPath(UStringVector &pathParts)\r
+{\r
+  for (int i = 0; i < pathParts.Size();)\r
+  {\r
+    UString &s = pathParts[i];\r
+    s = GetCorrectFileName(s);\r
+    if (s.IsEmpty())\r
+      pathParts.Delete(i);\r
+    else\r
+    {\r
+      #ifdef _WIN32\r
+      if (!IsSupportedName(s))\r
+        s = (UString)L"_" + s;\r
+      #endif\r
+      i++;\r
+    }\r
+  }\r
+}\r
+\r
+UString MakePathNameFromParts(const UStringVector &parts)\r
+{\r
+  UString result;\r
+  for (int i = 0; i < parts.Size(); i++)\r
+  {\r
+    if (i != 0)\r
+      result += WCHAR_PATH_SEPARATOR;\r
+    result += parts[i];\r
+  }\r
+  return result;\r
+}\r
+\r
+UString GetCorrectFsPath(const UString &path)\r
+{\r
+  UString res = GetCorrectFileName(path);\r
+  #ifdef _WIN32\r
+  if (!IsSupportedName(res))\r
+    res = (UString)L"_" + res;\r
+  #endif\r
+  return res;\r
+}\r
+  \r
+UString GetCorrectFullFsPath(const UString &path)\r
+{\r
+  UStringVector parts;\r
+  SplitPathToParts(path, parts);\r
+  for (int i = 0; i < parts.Size(); i++)\r
+  {\r
+    UString &s = parts[i];\r
+    #ifdef _WIN32\r
+    while (!s.IsEmpty() && s[s.Length() - 1] == '.')\r
+      s.Delete(s.Length() - 1);\r
+    if (!IsSupportedName(s))\r
+      s = (UString)L"_" + s;\r
+    #endif\r
+  }\r
+  return MakePathNameFromParts(parts);\r
+}\r
diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.h b/CPP/7zip/UI/Common/ExtractingFilePath.h
new file mode 100755 (executable)
index 0000000..54bdc72
--- /dev/null
@@ -0,0 +1,13 @@
+// ExtractingFilePath.h\r
+\r
+#ifndef __EXTRACTING_FILE_PATH_H\r
+#define __EXTRACTING_FILE_PATH_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+UString MakePathNameFromParts(const UStringVector &parts);\r
+void MakeCorrectPath(UStringVector &pathParts);\r
+UString GetCorrectFsPath(const UString &path);\r
+UString GetCorrectFullFsPath(const UString &path);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/IFileExtractCallback.h b/CPP/7zip/UI/Common/IFileExtractCallback.h
new file mode 100755 (executable)
index 0000000..5aff92f
--- /dev/null
@@ -0,0 +1,46 @@
+// IFileExtractCallback.h\r
+\r
+#ifndef __IFILEEXTRACTCALLBACK_H\r
+#define __IFILEEXTRACTCALLBACK_H\r
+\r
+#include "Common/MyString.h"\r
+#include "../../IDecl.h"\r
+\r
+namespace NOverwriteAnswer\r
+{\r
+  enum EEnum\r
+  {\r
+    kYes,\r
+    kYesToAll,\r
+    kNo,\r
+    kNoToAll,\r
+    kAutoRename,\r
+    kCancel\r
+  };\r
+}\r
+\r
+DECL_INTERFACE_SUB(IFolderArchiveExtractCallback, IProgress, 0x01, 0x07)\r
+{\r
+public:\r
+  STDMETHOD(AskOverwrite)(\r
+      const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,\r
+      const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,\r
+      Int32 *answer) PURE;\r
+  STDMETHOD(PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position) PURE;\r
+  STDMETHOD(MessageError)(const wchar_t *message) PURE;\r
+  STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted) PURE;\r
+};\r
+\r
+struct IExtractCallbackUI: IFolderArchiveExtractCallback\r
+{\r
+  virtual HRESULT BeforeOpen(const wchar_t *name) = 0;\r
+  virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted) = 0;\r
+  virtual HRESULT ThereAreNoFiles() = 0;\r
+  virtual HRESULT ExtractResult(HRESULT result) = 0;\r
+\r
+  #ifndef _NO_CRYPTO\r
+  virtual HRESULT SetPassword(const UString &password) = 0;\r
+  #endif\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp
new file mode 100755 (executable)
index 0000000..67a0cc7
--- /dev/null
@@ -0,0 +1,681 @@
+// LoadCodecs.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "LoadCodecs.h"\r
+\r
+#include "../../../Common/MyCom.h"\r
+#ifdef NEW_FOLDER_INTERFACE\r
+#include "../../../Common/StringToInt.h"\r
+#endif\r
+#include "../../../Windows/PropVariant.h"\r
+\r
+#include "../../ICoder.h"\r
+#include "../../Common/RegisterArc.h"\r
+\r
+#ifdef EXTERNAL_CODECS\r
+#include "../../../Windows/FileFind.h"\r
+#include "../../../Windows/DLL.h"\r
+#ifdef NEW_FOLDER_INTERFACE\r
+#include "../../../Windows/ResourceString.h"\r
+static const UINT kIconTypesResId = 100;\r
+#endif\r
+\r
+#ifdef _WIN32\r
+#include "Windows/Registry.h"\r
+#endif\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+\r
+#ifdef _WIN32\r
+extern HINSTANCE g_hInstance;\r
+#endif\r
+\r
+static CSysString GetLibraryFolderPrefix()\r
+{\r
+  #ifdef _WIN32\r
+  TCHAR fullPath[MAX_PATH + 1];\r
+  ::GetModuleFileName(g_hInstance, fullPath, MAX_PATH);\r
+  CSysString path = fullPath;\r
+  int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));\r
+  return path.Left(pos + 1);\r
+  #else\r
+  return CSysString(); // FIX IT\r
+  #endif\r
+}\r
+\r
+#define kCodecsFolderName TEXT("Codecs")\r
+#define kFormatsFolderName TEXT("Formats")\r
+static const TCHAR *kMainDll = TEXT("7z.dll");\r
+\r
+#ifdef _WIN32\r
+static LPCTSTR kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip");\r
+static LPCTSTR kProgramPathValue = TEXT("Path");\r
+static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path)\r
+{\r
+  NRegistry::CKey key;\r
+  if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS)\r
+    if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS)\r
+    {\r
+      NName::NormalizeDirPathPrefix(path);\r
+      return true;\r
+    }\r
+  return false;\r
+}\r
+\r
+#endif\r
+\r
+CSysString GetBaseFolderPrefixFromRegistry()\r
+{\r
+  CSysString moduleFolderPrefix = GetLibraryFolderPrefix();\r
+  #ifdef _WIN32\r
+  if (!NFind::DoesFileExist(moduleFolderPrefix + kMainDll) &&\r
+      !NFind::DoesDirExist(moduleFolderPrefix + kCodecsFolderName) &&\r
+      !NFind::DoesDirExist(moduleFolderPrefix + kFormatsFolderName))\r
+  {\r
+    CSysString path;\r
+    if (ReadPathFromRegistry(HKEY_CURRENT_USER, path))\r
+      return path;\r
+    if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path))\r
+      return path;\r
+  }\r
+  #endif\r
+  return moduleFolderPrefix;\r
+}\r
+\r
+typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods);\r
+typedef UInt32 (WINAPI *GetNumberOfFormatsFunc)(UInt32 *numFormats);\r
+typedef UInt32 (WINAPI *GetHandlerPropertyFunc)(PROPID propID, PROPVARIANT *value);\r
+typedef UInt32 (WINAPI *GetHandlerPropertyFunc2)(UInt32 index, PROPID propID, PROPVARIANT *value);\r
+typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *iid, void **outObject);\r
+typedef UInt32 (WINAPI *SetLargePageModeFunc)();\r
+\r
+\r
+static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index,\r
+    PROPID propId, CLSID &clsId, bool &isAssigned)\r
+{\r
+  NWindows::NCOM::CPropVariant prop;\r
+  isAssigned = false;\r
+  RINOK(getMethodProperty(index, propId, &prop));\r
+  if (prop.vt == VT_BSTR)\r
+  {\r
+    isAssigned = true;\r
+    clsId = *(const GUID *)prop.bstrVal;\r
+  }\r
+  else if (prop.vt != VT_EMPTY)\r
+    return E_FAIL;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CCodecs::LoadCodecs()\r
+{\r
+  CCodecLib &lib = Libs.Back();\r
+  lib.GetMethodProperty = (GetMethodPropertyFunc)lib.Lib.GetProc("GetMethodProperty");\r
+  if (lib.GetMethodProperty == NULL)\r
+    return S_OK;\r
+\r
+  UInt32 numMethods = 1;\r
+  GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)lib.Lib.GetProc("GetNumberOfMethods");\r
+  if (getNumberOfMethodsFunc != NULL)\r
+  {\r
+    RINOK(getNumberOfMethodsFunc(&numMethods));\r
+  }\r
+\r
+  for(UInt32 i = 0; i < numMethods; i++)\r
+  {\r
+    CDllCodecInfo info;\r
+    info.LibIndex = Libs.Size() - 1;\r
+    info.CodecIndex = i;\r
+\r
+    RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned));\r
+    RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned));\r
+\r
+    Codecs.Add(info);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+static HRESULT ReadProp(\r
+    GetHandlerPropertyFunc getProp,\r
+    GetHandlerPropertyFunc2 getProp2,\r
+    UInt32 index, PROPID propID, NCOM::CPropVariant &prop)\r
+{\r
+  if (getProp2)\r
+    return getProp2(index, propID, &prop);;\r
+  return getProp(propID, &prop);\r
+}\r
+\r
+static HRESULT ReadBoolProp(\r
+    GetHandlerPropertyFunc getProp,\r
+    GetHandlerPropertyFunc2 getProp2,\r
+    UInt32 index, PROPID propID, bool &res)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  RINOK(ReadProp(getProp, getProp2, index, propID, prop));\r
+  if (prop.vt == VT_BOOL)\r
+    res = VARIANT_BOOLToBool(prop.boolVal);\r
+  else if (prop.vt != VT_EMPTY)\r
+    return E_FAIL;\r
+  return S_OK;\r
+}\r
+\r
+static HRESULT ReadStringProp(\r
+    GetHandlerPropertyFunc getProp,\r
+    GetHandlerPropertyFunc2 getProp2,\r
+    UInt32 index, PROPID propID, UString &res)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  RINOK(ReadProp(getProp, getProp2, index, propID, prop));\r
+  if (prop.vt == VT_BSTR)\r
+    res = prop.bstrVal;\r
+  else if (prop.vt != VT_EMPTY)\r
+    return E_FAIL;\r
+  return S_OK;\r
+}\r
+\r
+#endif\r
+\r
+static const unsigned int kNumArcsMax = 48;\r
+static unsigned int g_NumArcs = 0;\r
+static const CArcInfo *g_Arcs[kNumArcsMax];\r
+void RegisterArc(const CArcInfo *arcInfo)\r
+{\r
+  if (g_NumArcs < kNumArcsMax)\r
+    g_Arcs[g_NumArcs++] = arcInfo;\r
+}\r
+\r
+static void SplitString(const UString &srcString, UStringVector &destStrings)\r
+{\r
+  destStrings.Clear();\r
+  UString s;\r
+  int len = srcString.Length();\r
+  if (len == 0)\r
+    return;\r
+  for (int i = 0; i < len; i++)\r
+  {\r
+    wchar_t c = srcString[i];\r
+    if (c == L' ')\r
+    {\r
+      if (!s.IsEmpty())\r
+      {\r
+        destStrings.Add(s);\r
+        s.Empty();\r
+      }\r
+    }\r
+    else\r
+      s += c;\r
+  }\r
+  if (!s.IsEmpty())\r
+    destStrings.Add(s);\r
+}\r
+\r
+void CArcInfoEx::AddExts(const wchar_t *ext, const wchar_t *addExt)\r
+{\r
+  UStringVector exts, addExts;\r
+  if (ext != 0)\r
+    SplitString(ext, exts);\r
+  if (addExt != 0)\r
+    SplitString(addExt, addExts);\r
+  for (int i = 0; i < exts.Size(); i++)\r
+  {\r
+    CArcExtInfo extInfo;\r
+    extInfo.Ext = exts[i];\r
+    if (i < addExts.Size())\r
+    {\r
+      extInfo.AddExt = addExts[i];\r
+      if (extInfo.AddExt == L"*")\r
+        extInfo.AddExt.Empty();\r
+    }\r
+    Exts.Add(extInfo);\r
+  }\r
+}\r
+\r
+#ifdef EXTERNAL_CODECS\r
+\r
+HRESULT CCodecs::LoadFormats()\r
+{\r
+  const NDLL::CLibrary &lib = Libs.Back().Lib;\r
+  GetHandlerPropertyFunc getProp = 0;\r
+  GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2)lib.GetProc("GetHandlerProperty2");\r
+  if (getProp2 == NULL)\r
+  {\r
+    getProp = (GetHandlerPropertyFunc)lib.GetProc("GetHandlerProperty");\r
+    if (getProp == NULL)\r
+      return S_OK;\r
+  }\r
+\r
+  UInt32 numFormats = 1;\r
+  GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc)lib.GetProc("GetNumberOfFormats");\r
+  if (getNumberOfFormats != NULL)\r
+  {\r
+    RINOK(getNumberOfFormats(&numFormats));\r
+  }\r
+  if (getProp2 == NULL)\r
+    numFormats = 1;\r
+\r
+  for(UInt32 i = 0; i < numFormats; i++)\r
+  {\r
+    CArcInfoEx item;\r
+    item.LibIndex = Libs.Size() - 1;\r
+    item.FormatIndex = i;\r
+\r
+    RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kName, item.Name));\r
+\r
+    NCOM::CPropVariant prop;\r
+    if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK)\r
+      continue;\r
+    if (prop.vt != VT_BSTR)\r
+      continue;\r
+    item.ClassID = *(const GUID *)prop.bstrVal;\r
+    prop.Clear();\r
+\r
+    UString ext, addExt;\r
+    RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext));\r
+    RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt));\r
+    item.AddExts(ext, addExt);\r
+\r
+    ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, item.UpdateEnabled);\r
+    if (item.UpdateEnabled)\r
+      ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, item.KeepName);\r
+    \r
+    if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK)\r
+      if (prop.vt == VT_BSTR)\r
+      {\r
+        UINT len = ::SysStringByteLen(prop.bstrVal);\r
+        item.StartSignature.SetCapacity(len);\r
+        memmove(item.StartSignature, prop.bstrVal, len);\r
+      }\r
+    Formats.Add(item);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+#ifdef NEW_FOLDER_INTERFACE\r
+void CCodecIcons::LoadIcons(HMODULE m)\r
+{\r
+  UString iconTypes = MyLoadStringW(m, kIconTypesResId);\r
+  UStringVector pairs;\r
+  SplitString(iconTypes, pairs);\r
+  for (int i = 0; i < pairs.Size(); i++)\r
+  {\r
+    const UString &s = pairs[i];\r
+    int pos = s.Find(L':');\r
+    CIconPair iconPair;\r
+    iconPair.IconIndex = -1;\r
+    if (pos < 0)\r
+      pos = s.Length();\r
+    else\r
+    {\r
+      UString num = s.Mid(pos + 1);\r
+      if (!num.IsEmpty())\r
+      {\r
+        const wchar_t *end;\r
+        iconPair.IconIndex = (UInt32)ConvertStringToUInt64(num, &end);\r
+        if (*end != L'\0')\r
+          continue;\r
+      }\r
+    }\r
+    iconPair.Ext = s.Left(pos);\r
+    IconPairs.Add(iconPair);\r
+  }\r
+}\r
+\r
+bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const\r
+{\r
+  iconIndex = -1;\r
+  for (int i = 0; i < IconPairs.Size(); i++)\r
+  {\r
+    const CIconPair &pair = IconPairs[i];\r
+    if (ext.CompareNoCase(pair.Ext) == 0)\r
+    {\r
+      iconIndex = pair.IconIndex;\r
+      return true;\r
+    }\r
+  }\r
+  return false;\r
+}\r
+#endif\r
+\r
+#ifdef _7ZIP_LARGE_PAGES\r
+extern "C"\r
+{\r
+  extern SIZE_T g_LargePageSize;\r
+}\r
+#endif\r
+\r
+HRESULT CCodecs::LoadDll(const CSysString &dllPath, bool needCheckDll)\r
+{\r
+  if (needCheckDll)\r
+  {\r
+    NDLL::CLibrary library;\r
+    if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE))\r
+      return S_OK;\r
+  }\r
+  Libs.Add(CCodecLib());\r
+  CCodecLib &lib = Libs.Back();\r
+  #ifdef NEW_FOLDER_INTERFACE\r
+  lib.Path = dllPath;\r
+  #endif\r
+  bool used = false;\r
+  HRESULT res = S_OK;\r
+  if (lib.Lib.Load(dllPath))\r
+  {\r
+    #ifdef NEW_FOLDER_INTERFACE\r
+    lib.LoadIcons();\r
+    #endif\r
+\r
+    #ifdef _7ZIP_LARGE_PAGES\r
+    if (g_LargePageSize != 0)\r
+    {\r
+      SetLargePageModeFunc setLargePageMode = (SetLargePageModeFunc)lib.Lib.GetProc("SetLargePageMode");\r
+      if (setLargePageMode != 0)\r
+        setLargePageMode();\r
+    }\r
+    #endif\r
+\r
+    lib.CreateObject = (CreateObjectFunc)lib.Lib.GetProc("CreateObject");\r
+    if (lib.CreateObject != 0)\r
+    {\r
+      int startSize = Codecs.Size();\r
+      res = LoadCodecs();\r
+      used = (Codecs.Size() != startSize);\r
+      if (res == S_OK)\r
+      {\r
+        startSize = Formats.Size();\r
+        res = LoadFormats();\r
+        used = used || (Formats.Size() != startSize);\r
+      }\r
+    }\r
+  }\r
+  if (!used)\r
+    Libs.DeleteBack();\r
+  return res;\r
+}\r
+\r
+HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix)\r
+{\r
+  NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*")));\r
+  NFile::NFind::CFileInfo fi;\r
+  while (enumerator.Next(fi))\r
+  {\r
+    if (fi.IsDir())\r
+      continue;\r
+    RINOK(LoadDll(folderPrefix + fi.Name, true));\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+#endif\r
+\r
+#ifndef _SFX\r
+static inline void SetBuffer(CByteBuffer &bb, const Byte *data, int size)\r
+{\r
+  bb.SetCapacity(size);\r
+  memmove((Byte *)bb, data, size);\r
+}\r
+#endif\r
+\r
+HRESULT CCodecs::Load()\r
+{\r
+  #ifdef NEW_FOLDER_INTERFACE\r
+  InternalIcons.LoadIcons(g_hInstance);\r
+  #endif\r
+\r
+  Formats.Clear();\r
+  #ifdef EXTERNAL_CODECS\r
+  Codecs.Clear();\r
+  #endif\r
+  for (UInt32 i = 0; i < g_NumArcs; i++)\r
+  {\r
+    const CArcInfo &arc = *g_Arcs[i];\r
+    CArcInfoEx item;\r
+    item.Name = arc.Name;\r
+    item.CreateInArchive = arc.CreateInArchive;\r
+    item.CreateOutArchive = arc.CreateOutArchive;\r
+    item.AddExts(arc.Ext, arc.AddExt);\r
+    item.UpdateEnabled = (arc.CreateOutArchive != 0);\r
+    item.KeepName = arc.KeepName;\r
+\r
+    #ifndef _SFX\r
+    SetBuffer(item.StartSignature, arc.Signature, arc.SignatureSize);\r
+    #endif\r
+    Formats.Add(item);\r
+  }\r
+  #ifdef EXTERNAL_CODECS\r
+  const CSysString baseFolder = GetBaseFolderPrefixFromRegistry();\r
+  RINOK(LoadDll(baseFolder + kMainDll, false));\r
+  RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName TEXT(STRING_PATH_SEPARATOR)));\r
+  RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName TEXT(STRING_PATH_SEPARATOR)));\r
+  #endif\r
+  return S_OK;\r
+}\r
+\r
+#ifndef _SFX\r
+\r
+int CCodecs::FindFormatForArchiveName(const UString &arcPath) const\r
+{\r
+  int slashPos1 = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+  int slashPos2 = arcPath.ReverseFind(L'.');\r
+  int dotPos = arcPath.ReverseFind(L'.');\r
+  if (dotPos < 0 || dotPos < slashPos1 || dotPos < slashPos2)\r
+    return -1;\r
+  UString ext = arcPath.Mid(dotPos + 1);\r
+  for (int i = 0; i < Formats.Size(); i++)\r
+  {\r
+    const CArcInfoEx &arc = Formats[i];\r
+    if (!arc.UpdateEnabled)\r
+      continue;\r
+    if (arc.FindExtension(ext) >= 0)\r
+      return i;\r
+  }\r
+  return -1;\r
+}\r
+\r
+int CCodecs::FindFormatForExtension(const UString &ext) const\r
+{\r
+  if (ext.IsEmpty())\r
+    return -1;\r
+  for (int i = 0; i < Formats.Size(); i++)\r
+    if (Formats[i].FindExtension(ext) >= 0)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+int CCodecs::FindFormatForArchiveType(const UString &arcType) const\r
+{\r
+  for (int i = 0; i < Formats.Size(); i++)\r
+    if (Formats[i].Name.CompareNoCase(arcType) == 0)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const\r
+{\r
+  formatIndices.Clear();\r
+  for (int pos = 0; pos < arcType.Length();)\r
+  {\r
+    int pos2 = arcType.Find('.', pos);\r
+    if (pos2 < 0)\r
+      pos2 = arcType.Length();\r
+    const UString name = arcType.Mid(pos, pos2 - pos);\r
+    int index = FindFormatForArchiveType(name);\r
+    if (index < 0 && name != L"*")\r
+    {\r
+      formatIndices.Clear();\r
+      return false;\r
+    }\r
+    formatIndices.Add(index);\r
+    pos = pos2 + 1;\r
+  }\r
+  return true;\r
+}\r
+\r
+#endif\r
+\r
+#ifdef EXTERNAL_CODECS\r
+\r
+#ifdef EXPORT_CODECS\r
+extern unsigned int g_NumCodecs;\r
+STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject);\r
+STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);\r
+// STDAPI GetNumberOfMethods(UInt32 *numCodecs);\r
+#endif\r
+\r
+STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods)\r
+{\r
+  *numMethods =\r
+      #ifdef EXPORT_CODECS\r
+      g_NumCodecs +\r
+      #endif\r
+      Codecs.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  #ifdef EXPORT_CODECS\r
+  if (index < g_NumCodecs)\r
+    return GetMethodProperty(index, propID, value);\r
+  #endif\r
+\r
+  const CDllCodecInfo &ci = Codecs[index\r
+      #ifdef EXPORT_CODECS\r
+      - g_NumCodecs\r
+      #endif\r
+      ];\r
+\r
+  if (propID == NMethodPropID::kDecoderIsAssigned)\r
+  {\r
+    NWindows::NCOM::CPropVariant propVariant;\r
+    propVariant = ci.DecoderIsAssigned;\r
+    propVariant.Detach(value);\r
+    return S_OK;\r
+  }\r
+  if (propID == NMethodPropID::kEncoderIsAssigned)\r
+  {\r
+    NWindows::NCOM::CPropVariant propVariant;\r
+    propVariant = ci.EncoderIsAssigned;\r
+    propVariant.Detach(value);\r
+    return S_OK;\r
+  }\r
+  return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value);\r
+}\r
+\r
+STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder)\r
+{\r
+  #ifdef EXPORT_CODECS\r
+  if (index < g_NumCodecs)\r
+    return CreateCoder2(false, index, iid, coder);\r
+  #endif\r
+  const CDllCodecInfo &ci = Codecs[index\r
+      #ifdef EXPORT_CODECS\r
+      - g_NumCodecs\r
+      #endif\r
+      ];\r
+  if (ci.DecoderIsAssigned)\r
+    return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder)\r
+{\r
+  #ifdef EXPORT_CODECS\r
+  if (index < g_NumCodecs)\r
+    return CreateCoder2(true, index, iid, coder);\r
+  #endif\r
+  const CDllCodecInfo &ci = Codecs[index\r
+      #ifdef EXPORT_CODECS\r
+      - g_NumCodecs\r
+      #endif\r
+      ];\r
+  if (ci.EncoderIsAssigned)\r
+    return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CCodecs::CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const\r
+{\r
+  for (int i = 0; i < Codecs.Size(); i++)\r
+  {\r
+    const CDllCodecInfo &codec = Codecs[i];\r
+    if (encode && !codec.EncoderIsAssigned || !encode && !codec.DecoderIsAssigned)\r
+      continue;\r
+    const CCodecLib &lib = Libs[codec.LibIndex];\r
+    UString res;\r
+    NWindows::NCOM::CPropVariant prop;\r
+    RINOK(lib.GetMethodProperty(codec.CodecIndex, NMethodPropID::kName, &prop));\r
+    if (prop.vt == VT_BSTR)\r
+      res = prop.bstrVal;\r
+    else if (prop.vt != VT_EMPTY)\r
+      continue;\r
+    if (name.CompareNoCase(res) == 0)\r
+      return lib.CreateObject(encode ? &codec.Encoder : &codec.Decoder, &IID_ICompressCoder, (void **)&coder);\r
+  }\r
+  return CLASS_E_CLASSNOTAVAILABLE;\r
+}\r
+\r
+int CCodecs::GetCodecLibIndex(UInt32 index)\r
+{\r
+  #ifdef EXPORT_CODECS\r
+  if (index < g_NumCodecs)\r
+    return -1;\r
+  #endif\r
+  #ifdef EXTERNAL_CODECS\r
+  const CDllCodecInfo &ci = Codecs[index\r
+      #ifdef EXPORT_CODECS\r
+      - g_NumCodecs\r
+      #endif\r
+      ];\r
+  return ci.LibIndex;\r
+  #else\r
+  return -1;\r
+  #endif\r
+}\r
+\r
+bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index)\r
+{\r
+  #ifdef EXPORT_CODECS\r
+  if (index < g_NumCodecs)\r
+  {\r
+    NWindows::NCOM::CPropVariant prop;\r
+    if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK)\r
+      if (prop.vt != VT_EMPTY)\r
+        return true;\r
+    return false;\r
+  }\r
+  #endif\r
+  #ifdef EXTERNAL_CODECS\r
+  const CDllCodecInfo &ci = Codecs[index\r
+      #ifdef EXPORT_CODECS\r
+      - g_NumCodecs\r
+      #endif\r
+      ];\r
+  return ci.EncoderIsAssigned;\r
+  #else\r
+  return false;\r
+  #endif\r
+}\r
+\r
+HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id)\r
+{\r
+  UString s;\r
+  NWindows::NCOM::CPropVariant prop;\r
+  RINOK(GetProperty(index, NMethodPropID::kID, &prop));\r
+  if (prop.vt != VT_UI8)\r
+    return E_INVALIDARG;\r
+  id = prop.uhVal.QuadPart;\r
+  return S_OK;\r
+}\r
+\r
+UString CCodecs::GetCodecName(UInt32 index)\r
+{\r
+  UString s;\r
+  NWindows::NCOM::CPropVariant prop;\r
+  if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK)\r
+    if (prop.vt == VT_BSTR)\r
+      s = prop.bstrVal;\r
+  return s;\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/LoadCodecs.h b/CPP/7zip/UI/Common/LoadCodecs.h
new file mode 100755 (executable)
index 0000000..5630b59
--- /dev/null
@@ -0,0 +1,235 @@
+// LoadCodecs.h\r
+\r
+#ifndef __LOADCODECS_H\r
+#define __LOADCODECS_H\r
+\r
+#include "../../../Common/Types.h"\r
+#include "../../../Common/MyCom.h"\r
+#include "../../../Common/MyString.h"\r
+#include "../../../Common/Buffer.h"\r
+#include "../../ICoder.h"\r
+\r
+#ifdef EXTERNAL_CODECS\r
+#include "../../../Windows/DLL.h"\r
+#endif\r
+\r
+struct CDllCodecInfo\r
+{\r
+  CLSID Encoder;\r
+  CLSID Decoder;\r
+  bool EncoderIsAssigned;\r
+  bool DecoderIsAssigned;\r
+  int LibIndex;\r
+  UInt32 CodecIndex;\r
+};\r
+\r
+#include "../../Archive/IArchive.h"\r
+\r
+typedef IInArchive * (*CreateInArchiveP)();\r
+typedef IOutArchive * (*CreateOutArchiveP)();\r
+\r
+struct CArcExtInfo\r
+{\r
+  UString Ext;\r
+  UString AddExt;\r
+  CArcExtInfo() {}\r
+  CArcExtInfo(const UString &ext): Ext(ext) {}\r
+  CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {}\r
+};\r
+\r
+\r
+struct CArcInfoEx\r
+{\r
+  #ifdef EXTERNAL_CODECS\r
+  int LibIndex;\r
+  UInt32 FormatIndex;\r
+  CLSID ClassID;\r
+  #endif\r
+  bool UpdateEnabled;\r
+  CreateInArchiveP CreateInArchive;\r
+  CreateOutArchiveP CreateOutArchive;\r
+  UString Name;\r
+  CObjectVector<CArcExtInfo> Exts;\r
+  #ifndef _SFX\r
+  CByteBuffer StartSignature;\r
+  // CByteBuffer FinishSignature;\r
+  #ifdef NEW_FOLDER_INTERFACE\r
+  UStringVector AssociateExts;\r
+  #endif\r
+  #endif\r
+  bool KeepName;\r
+  UString GetMainExt() const\r
+  {\r
+    if (Exts.IsEmpty())\r
+      return UString();\r
+    return Exts[0].Ext;\r
+  }\r
+  int FindExtension(const UString &ext) const\r
+  {\r
+    for (int i = 0; i < Exts.Size(); i++)\r
+      if (ext.CompareNoCase(Exts[i].Ext) == 0)\r
+        return i;\r
+    return -1;\r
+  }\r
+  UString GetAllExtensions() const\r
+  {\r
+    UString s;\r
+    for (int i = 0; i < Exts.Size(); i++)\r
+    {\r
+      if (i > 0)\r
+        s += ' ';\r
+      s += Exts[i].Ext;\r
+    }\r
+    return s;\r
+  }\r
+\r
+  void AddExts(const wchar_t* ext, const wchar_t* addExt);\r
+\r
+  CArcInfoEx():\r
+    #ifdef EXTERNAL_CODECS\r
+    LibIndex(-1),\r
+    #endif\r
+    UpdateEnabled(false),\r
+    CreateInArchive(0), CreateOutArchive(0),\r
+    KeepName(false)\r
+    #ifndef _SFX\r
+    #endif\r
+  {}\r
+};\r
+\r
+#ifdef EXTERNAL_CODECS\r
+typedef UInt32 (WINAPI *GetMethodPropertyFunc)(UInt32 index, PROPID propID, PROPVARIANT *value);\r
+typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *interfaceID, void **outObject);\r
+\r
+\r
+#ifdef NEW_FOLDER_INTERFACE\r
+struct CCodecIcons\r
+{\r
+  struct CIconPair\r
+  {\r
+    UString Ext;\r
+    int IconIndex;\r
+  };\r
+  CObjectVector<CIconPair> IconPairs;\r
+  void LoadIcons(HMODULE m);\r
+  bool FindIconIndex(const UString &ext, int &iconIndex) const;\r
+};\r
+#endif\r
+\r
+struct CCodecLib\r
+#ifdef NEW_FOLDER_INTERFACE\r
+: public CCodecIcons\r
+#endif\r
+{\r
+  NWindows::NDLL::CLibrary Lib;\r
+  GetMethodPropertyFunc GetMethodProperty;\r
+  CreateObjectFunc CreateObject;\r
+  #ifdef NEW_FOLDER_INTERFACE\r
+  CSysString Path;\r
+  void LoadIcons() { CCodecIcons::LoadIcons((HMODULE)Lib); }\r
+  #endif\r
+  CCodecLib(): GetMethodProperty(0) {}\r
+};\r
+#endif\r
+\r
+class CCodecs:\r
+  #ifdef EXTERNAL_CODECS\r
+  public ICompressCodecsInfo,\r
+  #else\r
+  public IUnknown,\r
+  #endif\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  #ifdef EXTERNAL_CODECS\r
+  CObjectVector<CCodecLib> Libs;\r
+  CObjectVector<CDllCodecInfo> Codecs;\r
+\r
+  #ifdef NEW_FOLDER_INTERFACE\r
+  CCodecIcons InternalIcons;\r
+  #endif\r
+\r
+  HRESULT LoadCodecs();\r
+  HRESULT LoadFormats();\r
+  HRESULT LoadDll(const CSysString &path, bool needCheckDll);\r
+  HRESULT LoadDllsFromFolder(const CSysString &folderPrefix);\r
+\r
+  HRESULT CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const\r
+  {\r
+    return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive);\r
+  }\r
+  #endif\r
+\r
+public:\r
+  CObjectVector<CArcInfoEx> Formats;\r
+  HRESULT Load();\r
+  \r
+  #ifndef _SFX\r
+  int FindFormatForArchiveName(const UString &arcPath) const;\r
+  int FindFormatForExtension(const UString &ext) const;\r
+  int FindFormatForArchiveType(const UString &arcType) const;\r
+  bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const;\r
+  #endif\r
+\r
+  MY_UNKNOWN_IMP\r
+\r
+  #ifdef EXTERNAL_CODECS\r
+  STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods);\r
+  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);\r
+  STDMETHOD(CreateDecoder)(UInt32 index, const GUID *interfaceID, void **coder);\r
+  STDMETHOD(CreateEncoder)(UInt32 index, const GUID *interfaceID, void **coder);\r
+  #endif\r
+\r
+  int GetCodecLibIndex(UInt32 index);\r
+  bool GetCodecEncoderIsAssigned(UInt32 index);\r
+  HRESULT GetCodecId(UInt32 index, UInt64 &id);\r
+  UString GetCodecName(UInt32 index);\r
+\r
+  HRESULT CreateInArchive(int formatIndex, CMyComPtr<IInArchive> &archive) const\r
+  {\r
+    const CArcInfoEx &ai = Formats[formatIndex];\r
+    #ifdef EXTERNAL_CODECS\r
+    if (ai.LibIndex < 0)\r
+    #endif\r
+    {\r
+      archive = ai.CreateInArchive();\r
+      return S_OK;\r
+    }\r
+    #ifdef EXTERNAL_CODECS\r
+    return CreateArchiveHandler(ai, (void **)&archive, false);\r
+    #endif\r
+  }\r
+  HRESULT CreateOutArchive(int formatIndex, CMyComPtr<IOutArchive> &archive) const\r
+  {\r
+    const CArcInfoEx &ai = Formats[formatIndex];\r
+    #ifdef EXTERNAL_CODECS\r
+    if (ai.LibIndex < 0)\r
+    #endif\r
+    {\r
+      archive = ai.CreateOutArchive();\r
+      return S_OK;\r
+    }\r
+    #ifdef EXTERNAL_CODECS\r
+    return CreateArchiveHandler(ai, (void **)&archive, true);\r
+    #endif\r
+  }\r
+  int FindOutFormatFromName(const UString &name) const\r
+  {\r
+    for (int i = 0; i < Formats.Size(); i++)\r
+    {\r
+      const CArcInfoEx &arc = Formats[i];\r
+      if (!arc.UpdateEnabled)\r
+        continue;\r
+      if (arc.Name.CompareNoCase(name) == 0)\r
+        return i;\r
+    }\r
+    return -1;\r
+  }\r
+\r
+  #ifdef EXTERNAL_CODECS\r
+  HRESULT CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const;\r
+  #endif\r
+\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp
new file mode 100755 (executable)
index 0000000..c489e0a
--- /dev/null
@@ -0,0 +1,536 @@
+// OpenArchive.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/Wildcard.h"\r
+\r
+#include "Windows/FileDir.h"\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../../Common/FileStreams.h"\r
+#include "../../Common/StreamUtils.h"\r
+\r
+#include "DefaultName.h"\r
+#include "OpenArchive.h"\r
+\r
+using namespace NWindows;\r
+\r
+// Static-SFX (for Linux) can be big.\r
+const UInt64 kMaxCheckStartPosition = 1 << 22;\r
+\r
+HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  result = false;\r
+  RINOK(archive->GetProperty(index, propID, &prop));\r
+  if (prop.vt == VT_BOOL)\r
+    result = VARIANT_BOOLToBool(prop.boolVal);\r
+  else if (prop.vt != VT_EMPTY)\r
+    return E_FAIL;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result)\r
+{\r
+  return GetArchiveItemBoolProp(archive, index, kpidIsDir, result);\r
+}\r
+\r
+HRESULT CArc::GetItemPath(UInt32 index, UString &result) const\r
+{\r
+  {\r
+    NCOM::CPropVariant prop;\r
+    RINOK(Archive->GetProperty(index, kpidPath, &prop));\r
+    if (prop.vt == VT_BSTR)\r
+      result = prop.bstrVal;\r
+    else if (prop.vt == VT_EMPTY)\r
+      result.Empty();\r
+    else\r
+      return E_FAIL;\r
+  }\r
+  if (result.IsEmpty())\r
+  {\r
+    result = DefaultName;\r
+    NCOM::CPropVariant prop;\r
+    RINOK(Archive->GetProperty(index, kpidExtension, &prop));\r
+    if (prop.vt == VT_BSTR)\r
+    {\r
+      result += L'.';\r
+      result += prop.bstrVal;\r
+    }\r
+    else if (prop.vt != VT_EMPTY)\r
+      return E_FAIL;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CArc::GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const\r
+{\r
+  NCOM::CPropVariant prop;\r
+  defined = false;\r
+  ft.dwHighDateTime = ft.dwLowDateTime = 0;\r
+  RINOK(Archive->GetProperty(index, kpidMTime, &prop));\r
+  if (prop.vt == VT_FILETIME)\r
+  {\r
+    ft = prop.filetime;\r
+    defined = true;\r
+  }\r
+  else if (prop.vt != VT_EMPTY)\r
+    return E_FAIL;\r
+  else if (MTimeDefined)\r
+  {\r
+    ft = MTime;\r
+    defined = true;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+#ifndef _SFX\r
+static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size)\r
+{\r
+  for (size_t i = 0; i < size; i++)\r
+    if (p1[i] != p2[i])\r
+      return false;\r
+  return true;\r
+}\r
+#endif\r
+\r
+#ifdef UNDER_CE\r
+static const int kNumHashBytes = 1;\r
+#define HASH_VAL(buf, pos) ((buf)[pos])\r
+#else\r
+static const int kNumHashBytes = 2;\r
+#define HASH_VAL(buf, pos) ((buf)[pos] | ((UInt32)(buf)[pos + 1] << 8))\r
+#endif\r
+\r
+\r
+HRESULT CArc::OpenStream(\r
+    CCodecs *codecs,\r
+    int formatIndex,\r
+    IInStream *stream,\r
+    ISequentialInStream *seqStream,\r
+    IArchiveOpenCallback *callback)\r
+{\r
+  Archive.Release();\r
+  ErrorMessage.Empty();\r
+  const UString fileName = ExtractFileNameFromPath(Path);\r
+  UString extension;\r
+  {\r
+    int dotPos = fileName.ReverseFind(L'.');\r
+    if (dotPos >= 0)\r
+      extension = fileName.Mid(dotPos + 1);\r
+  }\r
+  CIntVector orderIndices;\r
+  if (formatIndex >= 0)\r
+    orderIndices.Add(formatIndex);\r
+  else\r
+  {\r
+\r
+  int i;\r
+  int numFinded = 0;\r
+  for (i = 0; i < codecs->Formats.Size(); i++)\r
+    if (codecs->Formats[i].FindExtension(extension) >= 0)\r
+      orderIndices.Insert(numFinded++, i);\r
+    else\r
+      orderIndices.Add(i);\r
+  \r
+  if (!stream)\r
+  {\r
+    if (numFinded != 1)\r
+      return E_NOTIMPL;\r
+    orderIndices.DeleteFrom(1);\r
+  }\r
+\r
+  #ifndef _SFX\r
+  if (orderIndices.Size() >= 2 && (numFinded == 0 || extension.CompareNoCase(L"exe") == 0))\r
+  {\r
+    CIntVector orderIndices2;\r
+    CByteBuffer byteBuffer;\r
+    const size_t kBufferSize = (1 << 21);\r
+    byteBuffer.SetCapacity(kBufferSize);\r
+    RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));\r
+    size_t processedSize = kBufferSize;\r
+    RINOK(ReadStream(stream, byteBuffer, &processedSize));\r
+    if (processedSize == 0)\r
+      return S_FALSE;\r
+\r
+    const Byte *buf = byteBuffer;\r
+    CByteBuffer hashBuffer;\r
+    const UInt32 kNumVals = 1 << (kNumHashBytes * 8);\r
+    hashBuffer.SetCapacity(kNumVals);\r
+    Byte *hash = hashBuffer;\r
+    memset(hash, 0xFF, kNumVals);\r
+    Byte prevs[256];\r
+    if (orderIndices.Size() >= 256)\r
+      return S_FALSE;\r
+    int i;\r
+    for (i = 0; i < orderIndices.Size(); i++)\r
+    {\r
+      const CArcInfoEx &ai = codecs->Formats[orderIndices[i]];\r
+      const CByteBuffer &sig = ai.StartSignature;\r
+      if (sig.GetCapacity() < kNumHashBytes)\r
+        continue;\r
+      UInt32 v = HASH_VAL(sig, 0);\r
+      prevs[i] = hash[v];\r
+      hash[v] = (Byte)i;\r
+    }\r
+\r
+    processedSize -= (kNumHashBytes - 1);\r
+    for (UInt32 pos = 0; pos < processedSize; pos++)\r
+    {\r
+      for (; pos < processedSize && hash[HASH_VAL(buf, pos)] == 0xFF; pos++);\r
+      if (pos == processedSize)\r
+        break;\r
+      UInt32 v = HASH_VAL(buf, pos);\r
+      Byte *ptr = &hash[v];\r
+      int i = *ptr;\r
+      do\r
+      {\r
+        int index = orderIndices[i];\r
+        const CArcInfoEx &ai = codecs->Formats[index];\r
+        const CByteBuffer &sig = ai.StartSignature;\r
+        if (sig.GetCapacity() != 0 && pos + sig.GetCapacity() <= processedSize + (kNumHashBytes - 1) &&\r
+            TestSignature(buf + pos, sig, sig.GetCapacity()))\r
+        {\r
+          orderIndices2.Add(index);\r
+          orderIndices[i] = 0xFF;\r
+          *ptr = prevs[i];\r
+        }\r
+        else\r
+          ptr = &prevs[i];\r
+        i = *ptr;\r
+      }\r
+      while (i != 0xFF);\r
+    }\r
+    \r
+    for (i = 0; i < orderIndices.Size(); i++)\r
+    {\r
+      int val = orderIndices[i];\r
+      if (val != 0xFF)\r
+        orderIndices2.Add(val);\r
+    }\r
+    orderIndices = orderIndices2;\r
+  }\r
+  else if (extension == L"000" || extension == L"001")\r
+  {\r
+    CByteBuffer byteBuffer;\r
+    const size_t kBufferSize = (1 << 10);\r
+    byteBuffer.SetCapacity(kBufferSize);\r
+    Byte *buffer = byteBuffer;\r
+    RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));\r
+    size_t processedSize = kBufferSize;\r
+    RINOK(ReadStream(stream, buffer, &processedSize));\r
+    if (processedSize >= 16)\r
+    {\r
+      Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00};\r
+      if (TestSignature(buffer, kRarHeader, 7) && buffer[9] == 0x73 && (buffer[10] & 1) != 0)\r
+      {\r
+        for (int i = 0; i < orderIndices.Size(); i++)\r
+        {\r
+          int index = orderIndices[i];\r
+          const CArcInfoEx &ai = codecs->Formats[index];\r
+          if (ai.Name.CompareNoCase(L"rar") != 0)\r
+            continue;\r
+          orderIndices.Delete(i--);\r
+          orderIndices.Insert(0, index);\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+  if (orderIndices.Size() >= 2)\r
+  {\r
+    int isoIndex = codecs->FindFormatForArchiveType(L"iso");\r
+    int udfIndex = codecs->FindFormatForArchiveType(L"udf");\r
+    int iIso = -1;\r
+    int iUdf = -1;\r
+    for (int i = 0; i < orderIndices.Size(); i++)\r
+    {\r
+      if (orderIndices[i] == isoIndex) iIso = i;\r
+      if (orderIndices[i] == udfIndex) iUdf = i;\r
+    }\r
+    if (iUdf > iIso && iIso >= 0)\r
+    {\r
+      orderIndices[iUdf] = isoIndex;\r
+      orderIndices[iIso] = udfIndex;\r
+    }\r
+  }\r
+\r
+  #endif\r
+  }\r
+\r
+  for (int i = 0; i < orderIndices.Size(); i++)\r
+  {\r
+    if (stream)\r
+    {\r
+      RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));\r
+    }\r
+    CMyComPtr<IInArchive> archive;\r
+\r
+    FormatIndex = orderIndices[i];\r
+    RINOK(codecs->CreateInArchive(FormatIndex, archive));\r
+    if (!archive)\r
+      continue;\r
+\r
+    #ifdef EXTERNAL_CODECS\r
+    {\r
+      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;\r
+      archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);\r
+      if (setCompressCodecsInfo)\r
+      {\r
+        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs));\r
+      }\r
+    }\r
+    #endif\r
+\r
+    // OutputDebugStringW(codecs->Formats[FormatIndex].Name);\r
+\r
+    HRESULT result;\r
+    if (stream)\r
+      result = archive->Open(stream, &kMaxCheckStartPosition, callback);\r
+    else\r
+    {\r
+      CMyComPtr<IArchiveOpenSeq> openSeq;\r
+      archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq);\r
+      if (!openSeq)\r
+        return E_NOTIMPL;\r
+      result = openSeq->OpenSeq(seqStream);\r
+    }\r
+\r
+    if (result == S_FALSE)\r
+      continue;\r
+    RINOK(result);\r
+\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      archive->GetArchiveProperty(kpidError, &prop);\r
+      if (prop.vt != VT_EMPTY)\r
+        ErrorMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown error";\r
+    }\r
+    \r
+    Archive = archive;\r
+    const CArcInfoEx &format = codecs->Formats[FormatIndex];\r
+    if (format.Exts.Size() == 0)\r
+      DefaultName = GetDefaultName2(fileName, L"", L"");\r
+    else\r
+    {\r
+      int subExtIndex = format.FindExtension(extension);\r
+      if (subExtIndex < 0)\r
+        subExtIndex = 0;\r
+      const CArcExtInfo &extInfo = format.Exts[subExtIndex];\r
+      DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt);\r
+    }\r
+    return S_OK;\r
+  }\r
+  return S_FALSE;\r
+}\r
+\r
+HRESULT CArc::OpenStreamOrFile(\r
+    CCodecs *codecs,\r
+    int formatIndex,\r
+    bool stdInMode,\r
+    IInStream *stream,\r
+    IArchiveOpenCallback *callback)\r
+{\r
+  CMyComPtr<IInStream> fileStream;\r
+  CMyComPtr<ISequentialInStream> seqStream;\r
+  if (stdInMode)\r
+    seqStream = new CStdInFileStream;\r
+  else if (!stream)\r
+  {\r
+    CInFileStream *fileStreamSpec = new CInFileStream;\r
+    fileStream = fileStreamSpec;\r
+    if (!fileStreamSpec->Open(Path))\r
+      return GetLastError();\r
+    stream = fileStream;\r
+  }\r
+\r
+  /*\r
+  if (callback)\r
+  {\r
+    UInt64 fileSize;\r
+    RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize));\r
+    RINOK(callback->SetTotal(NULL, &fileSize))\r
+  }\r
+  */\r
+\r
+  return OpenStream(codecs, formatIndex, stream, seqStream, callback);\r
+}\r
+\r
+HRESULT CArchiveLink::Close()\r
+{\r
+  for (int i = Arcs.Size() - 1;  i >= 0; i--)\r
+  {\r
+    RINOK(Arcs[i].Archive->Close());\r
+  }\r
+  IsOpen = false;\r
+  return S_OK;\r
+}\r
+\r
+void CArchiveLink::Release()\r
+{\r
+  while (!Arcs.IsEmpty())\r
+    Arcs.DeleteBack();\r
+}\r
+\r
+HRESULT CArchiveLink::Open(\r
+    CCodecs *codecs,\r
+    const CIntVector &formatIndices,\r
+    bool stdInMode,\r
+    IInStream *stream,\r
+    const UString &filePath,\r
+    IArchiveOpenCallback *callback)\r
+{\r
+  Release();\r
+  if (formatIndices.Size() >= 32)\r
+    return E_NOTIMPL;\r
+  \r
+  HRESULT resSpec;\r
+\r
+  for (;;)\r
+  {\r
+    resSpec = S_OK;\r
+    int formatIndex = -1;\r
+    if (formatIndices.Size() >= 1)\r
+    {\r
+      if (Arcs.Size() >= formatIndices.Size())\r
+        break;\r
+      formatIndex = formatIndices[formatIndices.Size() - Arcs.Size() - 1];\r
+    }\r
+    else if (Arcs.Size() >= 32)\r
+      break;\r
+\r
+    if (Arcs.IsEmpty())\r
+    {\r
+      CArc arc;\r
+      arc.Path = filePath;\r
+      arc.SubfileIndex = (UInt32)(Int32)-1;\r
+      RINOK(arc.OpenStreamOrFile(codecs, formatIndex, stdInMode, stream, callback));\r
+      Arcs.Add(arc);\r
+      continue;\r
+    }\r
+    \r
+    const CArc &arc = Arcs.Back();\r
+    \r
+    resSpec = (formatIndices.Size() == 0 ? S_OK : E_NOTIMPL);\r
+    \r
+    UInt32 mainSubfile;\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      RINOK(arc.Archive->GetArchiveProperty(kpidMainSubfile, &prop));\r
+      if (prop.vt == VT_UI4)\r
+        mainSubfile = prop.ulVal;\r
+      else\r
+        break;\r
+      UInt32 numItems;\r
+      RINOK(arc.Archive->GetNumberOfItems(&numItems));\r
+      if (mainSubfile >= numItems)\r
+        break;\r
+    }\r
+\r
+  \r
+    CMyComPtr<IInArchiveGetStream> getStream;\r
+    if (arc.Archive->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream) != S_OK || !getStream)\r
+      break;\r
+    \r
+    CMyComPtr<ISequentialInStream> subSeqStream;\r
+    if (getStream->GetStream(mainSubfile, &subSeqStream) != S_OK || !subSeqStream)\r
+      break;\r
+    \r
+    CMyComPtr<IInStream> subStream;\r
+    if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK || !subStream)\r
+      break;\r
+    \r
+    CArc arc2;\r
+    RINOK(arc.GetItemPath(mainSubfile, arc2.Path));\r
+    \r
+    CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName;\r
+    callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName);\r
+    if (setSubArchiveName)\r
+      setSubArchiveName->SetSubArchiveName(arc2.Path);\r
+    \r
+    arc2.SubfileIndex = mainSubfile;\r
+    HRESULT result = arc2.OpenStream(codecs, formatIndex, subStream, NULL, callback);\r
+    resSpec = (formatIndices.Size() == 0 ? S_OK : S_FALSE);\r
+    if (result == S_FALSE)\r
+      break;\r
+    RINOK(result);\r
+    RINOK(arc.GetItemMTime(mainSubfile, arc2.MTime, arc2.MTimeDefined));\r
+    Arcs.Add(arc2);\r
+  }\r
+  IsOpen = !Arcs.IsEmpty();\r
+  return S_OK;\r
+}\r
+\r
+static void SetCallback(const UString &filePath,\r
+    IOpenCallbackUI *callbackUI,\r
+    IArchiveOpenCallback *reOpenCallback,\r
+    CMyComPtr<IArchiveOpenCallback> &callback)\r
+{\r
+  COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;\r
+  callback = openCallbackSpec;\r
+  openCallbackSpec->Callback = callbackUI;\r
+  openCallbackSpec->ReOpenCallback = reOpenCallback;\r
+\r
+  UString fullName;\r
+  int fileNamePartStartIndex;\r
+  NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex);\r
+  openCallbackSpec->Init(\r
+      fullName.Left(fileNamePartStartIndex),\r
+      fullName.Mid(fileNamePartStartIndex));\r
+}\r
+\r
+HRESULT CArchiveLink::Open2(CCodecs *codecs,\r
+    const CIntVector &formatIndices,\r
+    bool stdInMode,\r
+    IInStream *stream,\r
+    const UString &filePath,\r
+    IOpenCallbackUI *callbackUI)\r
+{\r
+  VolumesSize = 0;\r
+  COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;\r
+  CMyComPtr<IArchiveOpenCallback> callback = openCallbackSpec;\r
+  openCallbackSpec->Callback = callbackUI;\r
+\r
+  UString fullName, prefix, name;\r
+  if (!stream && !stdInMode)\r
+  {\r
+    int fileNamePartStartIndex;\r
+    if (!NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex))\r
+      return GetLastError();\r
+    prefix = fullName.Left(fileNamePartStartIndex);\r
+    name = fullName.Mid(fileNamePartStartIndex);\r
+    openCallbackSpec->Init(prefix, name);\r
+  }\r
+  else\r
+  {\r
+    openCallbackSpec->SetSubArchiveName(filePath);\r
+  }\r
+\r
+  RINOK(Open(codecs, formatIndices, stdInMode, stream, filePath, callback));\r
+  VolumePaths.Add(prefix + name);\r
+  for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++)\r
+    VolumePaths.Add(prefix + openCallbackSpec->FileNames[i]);\r
+  VolumesSize = openCallbackSpec->TotalSize;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CArchiveLink::ReOpen(CCodecs *codecs, const UString &filePath,\r
+    IArchiveOpenCallback *callback)\r
+{\r
+  if (Arcs.Size() > 1)\r
+    return E_NOTIMPL;\r
+\r
+  if (Arcs.Size() == 0)\r
+    return Open2(codecs, CIntVector(), false, NULL, filePath, 0);\r
+\r
+  CMyComPtr<IArchiveOpenCallback> openCallbackNew;\r
+  SetCallback(filePath, NULL, callback, openCallbackNew);\r
+\r
+  CInFileStream *fileStreamSpec = new CInFileStream;\r
+  CMyComPtr<IInStream> stream(fileStreamSpec);\r
+  if (!fileStreamSpec->Open(filePath))\r
+    return GetLastError();\r
+  HRESULT res = GetArchive()->Open(stream, &kMaxCheckStartPosition, callback);\r
+  IsOpen = (res == S_OK);\r
+  return res;\r
+}\r
diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h
new file mode 100755 (executable)
index 0000000..18ca0ea
--- /dev/null
@@ -0,0 +1,87 @@
+// OpenArchive.h\r
+\r
+#ifndef __OPEN_ARCHIVE_H\r
+#define __OPEN_ARCHIVE_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+#include "Windows/FileFind.h"\r
+\r
+#include "../../Archive/IArchive.h"\r
+\r
+#include "ArchiveOpenCallback.h"\r
+#include "LoadCodecs.h"\r
+\r
+HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result);\r
+HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result);\r
+\r
+struct CArc\r
+{\r
+  CMyComPtr<IInArchive> Archive;\r
+  UString Path;\r
+  UString DefaultName;\r
+  int FormatIndex;\r
+  int SubfileIndex;\r
+  FILETIME MTime;\r
+  bool MTimeDefined;\r
+  UString ErrorMessage;\r
+\r
+  CArc(): MTimeDefined(false) {}\r
+\r
+  HRESULT GetItemPath(UInt32 index, UString &result) const;\r
+  HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const;\r
+  HRESULT IsItemAnti(UInt32 index, bool &result) const\r
+    { return GetArchiveItemBoolProp(Archive, index, kpidIsAnti, result); }\r
+\r
+  HRESULT OpenStream(\r
+    CCodecs *codecs,\r
+    int formatIndex,\r
+    IInStream *stream,\r
+    ISequentialInStream *seqStream,\r
+    IArchiveOpenCallback *callback);\r
+\r
+  HRESULT OpenStreamOrFile(\r
+    CCodecs *codecs,\r
+    int formatIndex,\r
+    bool stdInMode,\r
+    IInStream *stream,\r
+    IArchiveOpenCallback *callback);\r
+};\r
+\r
+struct CArchiveLink\r
+{\r
+  CObjectVector<CArc> Arcs;\r
+  UStringVector VolumePaths;\r
+  UInt64 VolumesSize;\r
+  bool IsOpen;\r
+\r
+  CArchiveLink(): VolumesSize(0), IsOpen(false) {}\r
+  HRESULT Close();\r
+  void Release();\r
+  ~CArchiveLink() { Release(); }\r
+\r
+  IInArchive *GetArchive() const { return Arcs.Back().Archive; }\r
+\r
+  HRESULT Open(\r
+    CCodecs *codecs,\r
+    const CIntVector &formatIndices,\r
+    bool stdInMode,\r
+    IInStream *stream,\r
+    const UString &filePath,\r
+    IArchiveOpenCallback *callback);\r
+\r
+  HRESULT Open2(\r
+    CCodecs *codecs,\r
+    const CIntVector &formatIndices,\r
+    bool stdInMode,\r
+    IInStream *stream,\r
+    const UString &filePath,\r
+    IOpenCallbackUI *callbackUI);\r
+\r
+  HRESULT ReOpen(\r
+    CCodecs *codecs,\r
+    const UString &filePath,\r
+    IArchiveOpenCallback *callback);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp
new file mode 100755 (executable)
index 0000000..4a9e294
--- /dev/null
@@ -0,0 +1,120 @@
+// PropIDUtils.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+\r
+#include "Windows/FileFind.h"\r
+#include "Windows/PropVariantConversions.h"\r
+\r
+#include "../../PropID.h"\r
+\r
+#include "PropIDUtils.h"\r
+\r
+using namespace NWindows;\r
+\r
+void ConvertUInt32ToHex(UInt32 value, wchar_t *s)\r
+{\r
+  for (int i = 0; i < 8; i++)\r
+  {\r
+    int t = value & 0xF;\r
+    value >>= 4;\r
+    s[7 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10)));\r
+  }\r
+  s[8] = L'\0';\r
+}\r
+\r
+static const char g_WinAttrib[17] = "RHS8DAdNTsrCOnE_";\r
+/*\r
+0 READONLY\r
+1 HIDDEN\r
+3 SYSTEM\r
+\r
+4 DIRECTORY\r
+5 ARCHIVE\r
+6 DEVICE\r
+7 NORMAL\r
+8 TEMPORARY\r
+9 SPARSE_FILE\r
+10 REPARSE_POINT\r
+11 COMPRESSED\r
+12 OFFLINE\r
+13 NOT_CONTENT_INDEXED\r
+14 ENCRYPTED\r
+\r
+16 VIRTUAL\r
+*/\r
+\r
+static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' };\r
+#define MY_ATTR_CHAR(a, n, c) ((a )& (1 << (n))) ? c : L'-';\r
+\r
+UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool full)\r
+{\r
+  switch(propID)\r
+  {\r
+    case kpidCTime:\r
+    case kpidATime:\r
+    case kpidMTime:\r
+    {\r
+      if (prop.vt != VT_FILETIME)\r
+        break;\r
+      FILETIME localFileTime;\r
+      if ((prop.filetime.dwHighDateTime == 0 &&\r
+          prop.filetime.dwLowDateTime == 0) ||\r
+          !::FileTimeToLocalFileTime(&prop.filetime, &localFileTime))\r
+        return UString();\r
+      return ConvertFileTimeToString(localFileTime, true, full);\r
+    }\r
+    case kpidCRC:\r
+    {\r
+      if (prop.vt != VT_UI4)\r
+        break;\r
+      wchar_t temp[12];\r
+      ConvertUInt32ToHex(prop.ulVal, temp);\r
+      return temp;\r
+    }\r
+    case kpidAttrib:\r
+    {\r
+      if (prop.vt != VT_UI4)\r
+        break;\r
+      UInt32 a = prop.ulVal;\r
+      wchar_t sz[32];\r
+      int pos = 0;\r
+      for (int i = 0; i < 16; i++)\r
+        if (a & (1 << i) && i != 7)\r
+          sz[pos++] = g_WinAttrib[i];\r
+      sz[pos] = '\0';\r
+      return sz;\r
+    }\r
+    case kpidPosixAttrib:\r
+    {\r
+      if (prop.vt != VT_UI4)\r
+        break;\r
+      UString res;\r
+      UInt32 a = prop.ulVal;\r
+      wchar_t temp[16];\r
+\r
+      temp[0] = kPosixTypes[(a >> 12) & 0xF];\r
+      for (int i = 6; i >= 0; i -= 3)\r
+      {\r
+        temp[7 - i] = MY_ATTR_CHAR(a, i + 2, L'r');\r
+        temp[8 - i] = MY_ATTR_CHAR(a, i + 1, L'w');\r
+        temp[9 - i] = MY_ATTR_CHAR(a, i + 0, L'x');\r
+      }\r
+      if ((a & 0x800) != 0) temp[3] = ((a & (1 << 6)) ? 's' : 'S');\r
+      if ((a & 0x400) != 0) temp[6] = ((a & (1 << 3)) ? 's' : 'S');\r
+      if ((a & 0x200) != 0) temp[9] = ((a & (1 << 0)) ? 't' : 'T');\r
+      temp[10] = 0;\r
+      res = temp;\r
+\r
+      a &= ~(UInt32)0xFFFF;\r
+      if (a != 0)\r
+      {\r
+        ConvertUInt32ToHex(a, temp);\r
+        res = UString(temp) + L' ' + res;\r
+      }\r
+      return res;\r
+    }\r
+  }\r
+  return ConvertPropVariantToString(prop);\r
+}\r
diff --git a/CPP/7zip/UI/Common/PropIDUtils.h b/CPP/7zip/UI/Common/PropIDUtils.h
new file mode 100755 (executable)
index 0000000..05c09e7
--- /dev/null
@@ -0,0 +1,12 @@
+// PropIDUtils.h\r
+\r
+#ifndef __PROPID_UTILS_H\r
+#define __PROPID_UTILS_H\r
+\r
+#include "Common/MyString.h"\r
+#include "Common/Types.h"\r
+\r
+void ConvertUInt32ToHex(UInt32 value, wchar_t *s);\r
+UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full = true);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/Property.h b/CPP/7zip/UI/Common/Property.h
new file mode 100755 (executable)
index 0000000..5253d52
--- /dev/null
@@ -0,0 +1,14 @@
+// Property.h\r
+\r
+#ifndef __PROPERTY_H\r
+#define __PROPERTY_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+struct CProperty\r
+{\r
+  UString Name;\r
+  UString Value;\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/SetProperties.cpp b/CPP/7zip/UI/Common/SetProperties.cpp
new file mode 100755 (executable)
index 0000000..b3347ce
--- /dev/null
@@ -0,0 +1,79 @@
+// SetProperties.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "SetProperties.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Common/MyString.h"\r
+#include "Common/StringToInt.h"\r
+#include "Common/MyCom.h"\r
+\r
+#include "../../Archive/IArchive.h"\r
+\r
+using namespace NWindows;\r
+using namespace NCOM;\r
+\r
+static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop)\r
+{\r
+  const wchar_t *endPtr;\r
+  UInt64 result = ConvertStringToUInt64(s, &endPtr);\r
+  if (endPtr - (const wchar_t *)s != s.Length())\r
+    prop = s;\r
+  else if (result <= 0xFFFFFFFF)\r
+    prop = (UInt32)result;\r
+  else\r
+    prop = result;\r
+}\r
+\r
+HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties)\r
+{\r
+  if (properties.IsEmpty())\r
+    return S_OK;\r
+  CMyComPtr<ISetProperties> setProperties;\r
+  unknown->QueryInterface(IID_ISetProperties, (void **)&setProperties);\r
+  if (!setProperties)\r
+    return S_OK;\r
+\r
+  UStringVector realNames;\r
+  CPropVariant *values = new CPropVariant[properties.Size()];\r
+  try\r
+  {\r
+    int i;\r
+    for(i = 0; i < properties.Size(); i++)\r
+    {\r
+      const CProperty &property = properties[i];\r
+      NCOM::CPropVariant propVariant;\r
+      UString name = property.Name;\r
+      if (property.Value.IsEmpty())\r
+      {\r
+        if (!name.IsEmpty())\r
+        {\r
+          wchar_t c = name[name.Length() - 1];\r
+          if (c == L'-')\r
+            propVariant = false;\r
+          else if (c == L'+')\r
+            propVariant = true;\r
+          if (propVariant.vt != VT_EMPTY)\r
+            name = name.Left(name.Length() - 1);\r
+        }\r
+      }\r
+      else\r
+        ParseNumberString(property.Value, propVariant);\r
+      realNames.Add(name);\r
+      values[i] = propVariant;\r
+    }\r
+    CRecordVector<const wchar_t *> names;\r
+    for(i = 0; i < realNames.Size(); i++)\r
+      names.Add((const wchar_t *)realNames[i]);\r
+    \r
+    RINOK(setProperties->SetProperties(&names.Front(), values, names.Size()));\r
+  }\r
+  catch(...)\r
+  {\r
+    delete []values;\r
+    throw;\r
+  }\r
+  delete []values;\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/UI/Common/SetProperties.h b/CPP/7zip/UI/Common/SetProperties.h
new file mode 100755 (executable)
index 0000000..64c947c
--- /dev/null
@@ -0,0 +1,10 @@
+// SetProperties.h\r
+\r
+#ifndef __SETPROPERTIES_H\r
+#define __SETPROPERTIES_H\r
+\r
+#include "Property.h"\r
+\r
+HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/SortUtils.cpp b/CPP/7zip/UI/Common/SortUtils.cpp
new file mode 100755 (executable)
index 0000000..039adfa
--- /dev/null
@@ -0,0 +1,22 @@
+// SortUtils.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "SortUtils.h"\r
+#include "Common/Wildcard.h"\r
+\r
+static int CompareStrings(const int *p1, const int *p2, void *param)\r
+{\r
+  const UStringVector &strings = *(const UStringVector *)param;\r
+  return CompareFileNames(strings[*p1], strings[*p2]);\r
+}\r
+\r
+void SortFileNames(const UStringVector &strings, CIntVector &indices)\r
+{\r
+  indices.Clear();\r
+  int numItems = strings.Size();\r
+  indices.Reserve(numItems);\r
+  for(int i = 0; i < numItems; i++)\r
+    indices.Add(i);\r
+  indices.Sort(CompareStrings, (void *)&strings);\r
+}\r
diff --git a/CPP/7zip/UI/Common/SortUtils.h b/CPP/7zip/UI/Common/SortUtils.h
new file mode 100755 (executable)
index 0000000..4835f11
--- /dev/null
@@ -0,0 +1,10 @@
+// SortUtils.h\r
+\r
+#ifndef __SORTUTLS_H\r
+#define __SORTUTLS_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+void SortFileNames(const UStringVector &strings, CIntVector &indices);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/StdAfx.h b/CPP/7zip/UI/Common/StdAfx.h
new file mode 100755 (executable)
index 0000000..ab2617e
--- /dev/null
@@ -0,0 +1,9 @@
+// stdafx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+#include "../../../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/TempFiles.cpp b/CPP/7zip/UI/Common/TempFiles.cpp
new file mode 100755 (executable)
index 0000000..48fb4e7
--- /dev/null
@@ -0,0 +1,22 @@
+// TempFiles.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "TempFiles.h"\r
+\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileIO.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+\r
+void CTempFiles::Clear()\r
+{\r
+  while(!Paths.IsEmpty())\r
+  {\r
+    NDirectory::DeleteFileAlways((LPCWSTR)Paths.Back());\r
+    Paths.DeleteBack();\r
+  }\r
+}\r
+\r
+\r
diff --git a/CPP/7zip/UI/Common/TempFiles.h b/CPP/7zip/UI/Common/TempFiles.h
new file mode 100755 (executable)
index 0000000..9e8e131
--- /dev/null
@@ -0,0 +1,16 @@
+// TempFiles.h\r
+\r
+#ifndef __TEMPFILES_H\r
+#define __TEMPFILES_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+class CTempFiles\r
+{\r
+  void Clear();\r
+public:\r
+  UStringVector Paths;\r
+  ~CTempFiles() { Clear(); }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp
new file mode 100755 (executable)
index 0000000..2e1cca0
--- /dev/null
@@ -0,0 +1,910 @@
+// Update.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Update.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#ifdef _WIN32\r
+#include "Windows/DLL.h"\r
+#endif\r
+\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileFind.h"\r
+#include "Windows/FileName.h"\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/PropVariantConversions.h"\r
+#include "Windows/Time.h"\r
+\r
+#include "../../Common/FileStreams.h"\r
+\r
+#include "../../Compress/CopyCoder.h"\r
+\r
+#include "../Common/DirItem.h"\r
+#include "../Common/EnumDirItems.h"\r
+#include "../Common/OpenArchive.h"\r
+#include "../Common/UpdateProduce.h"\r
+\r
+#include "EnumDirItems.h"\r
+#include "SetProperties.h"\r
+#include "TempFiles.h"\r
+#include "UpdateCallback.h"\r
+\r
+static const char *kUpdateIsNotSupoorted =\r
+  "update operations are not supported for this archive";\r
+\r
+using namespace NWindows;\r
+using namespace NCOM;\r
+using namespace NFile;\r
+using namespace NName;\r
+\r
+static const wchar_t *kTempFolderPrefix = L"7zE";\r
+\r
+using namespace NUpdateArchive;\r
+\r
+class COutMultiVolStream:\r
+  public IOutStream,\r
+  public CMyUnknownImp\r
+{\r
+  int _streamIndex; // required stream\r
+  UInt64 _offsetPos; // offset from start of _streamIndex index\r
+  UInt64 _absPos;\r
+  UInt64 _length;\r
+\r
+  struct CSubStreamInfo\r
+  {\r
+    COutFileStream *StreamSpec;\r
+    CMyComPtr<IOutStream> Stream;\r
+    UString Name;\r
+    UInt64 Pos;\r
+    UInt64 RealSize;\r
+  };\r
+  CObjectVector<CSubStreamInfo> Streams;\r
+public:\r
+  // CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;\r
+  CRecordVector<UInt64> Sizes;\r
+  UString Prefix;\r
+  CTempFiles *TempFiles;\r
+\r
+  void Init()\r
+  {\r
+    _streamIndex = 0;\r
+    _offsetPos = 0;\r
+    _absPos = 0;\r
+    _length = 0;\r
+  }\r
+\r
+  HRESULT Close();\r
+\r
+  MY_UNKNOWN_IMP1(IOutStream)\r
+\r
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);\r
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);\r
+  STDMETHOD(SetSize)(UInt64 newSize);\r
+};\r
+\r
+// static NSynchronization::CCriticalSection g_TempPathsCS;\r
+\r
+HRESULT COutMultiVolStream::Close()\r
+{\r
+  HRESULT res = S_OK;\r
+  for (int i = 0; i < Streams.Size(); i++)\r
+  {\r
+    CSubStreamInfo &s = Streams[i];\r
+    if (s.StreamSpec)\r
+    {\r
+      HRESULT res2 = s.StreamSpec->Close();\r
+      if (res2 != S_OK)\r
+        res = res2;\r
+    }\r
+  }\r
+  return res;\r
+}\r
+\r
+STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize)\r
+{\r
+  if (processedSize != NULL)\r
+    *processedSize = 0;\r
+  while(size > 0)\r
+  {\r
+    if (_streamIndex >= Streams.Size())\r
+    {\r
+      CSubStreamInfo subStream;\r
+\r
+      wchar_t temp[16];\r
+      ConvertUInt32ToString(_streamIndex + 1, temp);\r
+      UString res = temp;\r
+      while (res.Length() < 3)\r
+        res = UString(L'0') + res;\r
+      UString name = Prefix + res;\r
+      subStream.StreamSpec = new COutFileStream;\r
+      subStream.Stream = subStream.StreamSpec;\r
+      if (!subStream.StreamSpec->Create(name, false))\r
+        return ::GetLastError();\r
+      {\r
+        // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS);\r
+        TempFiles->Paths.Add(name);\r
+      }\r
+\r
+      subStream.Pos = 0;\r
+      subStream.RealSize = 0;\r
+      subStream.Name = name;\r
+      Streams.Add(subStream);\r
+      continue;\r
+    }\r
+    CSubStreamInfo &subStream = Streams[_streamIndex];\r
+\r
+    int index = _streamIndex;\r
+    if (index >= Sizes.Size())\r
+      index = Sizes.Size() - 1;\r
+    UInt64 volSize = Sizes[index];\r
+\r
+    if (_offsetPos >= volSize)\r
+    {\r
+      _offsetPos -= volSize;\r
+      _streamIndex++;\r
+      continue;\r
+    }\r
+    if (_offsetPos != subStream.Pos)\r
+    {\r
+      // CMyComPtr<IOutStream> outStream;\r
+      // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));\r
+      RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));\r
+      subStream.Pos = _offsetPos;\r
+    }\r
+\r
+    UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos);\r
+    UInt32 realProcessed;\r
+    RINOK(subStream.Stream->Write(data, curSize, &realProcessed));\r
+    data = (void *)((Byte *)data + realProcessed);\r
+    size -= realProcessed;\r
+    subStream.Pos += realProcessed;\r
+    _offsetPos += realProcessed;\r
+    _absPos += realProcessed;\r
+    if (_absPos > _length)\r
+      _length = _absPos;\r
+    if (_offsetPos > subStream.RealSize)\r
+      subStream.RealSize = _offsetPos;\r
+    if (processedSize != NULL)\r
+      *processedSize += realProcessed;\r
+    if (subStream.Pos == volSize)\r
+    {\r
+      _streamIndex++;\r
+      _offsetPos = 0;\r
+    }\r
+    if (realProcessed == 0 && curSize != 0)\r
+      return E_FAIL;\r
+    break;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)\r
+{\r
+  if (seekOrigin >= 3)\r
+    return STG_E_INVALIDFUNCTION;\r
+  switch(seekOrigin)\r
+  {\r
+    case STREAM_SEEK_SET:\r
+      _absPos = offset;\r
+      break;\r
+    case STREAM_SEEK_CUR:\r
+      _absPos += offset;\r
+      break;\r
+    case STREAM_SEEK_END:\r
+      _absPos = _length + offset;\r
+      break;\r
+  }\r
+  _offsetPos = _absPos;\r
+  if (newPosition != NULL)\r
+    *newPosition = _absPos;\r
+  _streamIndex = 0;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP COutMultiVolStream::SetSize(UInt64 newSize)\r
+{\r
+  if (newSize < 0)\r
+    return E_INVALIDARG;\r
+  int i = 0;\r
+  while (i < Streams.Size())\r
+  {\r
+    CSubStreamInfo &subStream = Streams[i++];\r
+    if ((UInt64)newSize < subStream.RealSize)\r
+    {\r
+      RINOK(subStream.Stream->SetSize(newSize));\r
+      subStream.RealSize = newSize;\r
+      break;\r
+    }\r
+    newSize -= subStream.RealSize;\r
+  }\r
+  while (i < Streams.Size())\r
+  {\r
+    {\r
+      CSubStreamInfo &subStream = Streams.Back();\r
+      subStream.Stream.Release();\r
+      NDirectory::DeleteFileAlways(subStream.Name);\r
+    }\r
+    Streams.DeleteBack();\r
+  }\r
+  _offsetPos = _absPos;\r
+  _streamIndex = 0;\r
+  _length = newSize;\r
+  return S_OK;\r
+}\r
+\r
+static const wchar_t *kDefaultArchiveType = L"7z";\r
+static const wchar_t *kSFXExtension =\r
+  #ifdef _WIN32\r
+    L"exe";\r
+  #else\r
+    L"";\r
+  #endif\r
+\r
+bool CUpdateOptions::Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath)\r
+{\r
+  if (formatIndices.Size() > 1)\r
+    return false;\r
+  int arcTypeIndex = -1;\r
+  if (formatIndices.Size() != 0)\r
+    arcTypeIndex = formatIndices[0];\r
+  if (arcTypeIndex >= 0)\r
+    MethodMode.FormatIndex = arcTypeIndex;\r
+  else\r
+  {\r
+    MethodMode.FormatIndex = codecs->FindFormatForArchiveName(arcPath);\r
+    // It works incorrectly for update command if archive has some non-default extension!\r
+    if (MethodMode.FormatIndex < 0)\r
+      MethodMode.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArchiveType);\r
+  }\r
+  if (MethodMode.FormatIndex < 0)\r
+    return false;\r
+  const CArcInfoEx &arcInfo = codecs->Formats[MethodMode.FormatIndex];\r
+  if (!arcInfo.UpdateEnabled)\r
+    return false;\r
+  UString typeExt = arcInfo.GetMainExt();\r
+  UString ext = typeExt;\r
+  if (SfxMode)\r
+    ext = kSFXExtension;\r
+  ArchivePath.BaseExtension = ext;\r
+  ArchivePath.VolExtension = typeExt;\r
+  ArchivePath.ParseFromPath(arcPath);\r
+  for (int i = 0; i < Commands.Size(); i++)\r
+  {\r
+    CUpdateArchiveCommand &uc = Commands[i];\r
+    uc.ArchivePath.BaseExtension = ext;\r
+    uc.ArchivePath.VolExtension = typeExt;\r
+    uc.ArchivePath.ParseFromPath(uc.UserArchivePath);\r
+  }\r
+  return true;\r
+}\r
+\r
+/*\r
+struct CUpdateProduceCallbackImp: public IUpdateProduceCallback\r
+{\r
+  const CObjectVector<CArcItem> *_arcItems;\r
+  IUpdateCallbackUI *_callback;\r
+  \r
+  CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a,\r
+      IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {}\r
+  virtual HRESULT ShowDeleteFile(int arcIndex);\r
+};\r
+\r
+HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(int arcIndex)\r
+{\r
+  return _callback->ShowDeleteFile((*_arcItems)[arcIndex].Name);\r
+}\r
+*/\r
+\r
+static HRESULT Compress(\r
+    CCodecs *codecs,\r
+    const CActionSet &actionSet,\r
+    IInArchive *archive,\r
+    const CCompressionMethodMode &compressionMethod,\r
+    CArchivePath &archivePath,\r
+    const CObjectVector<CArcItem> &arcItems,\r
+    bool shareForWrite,\r
+    bool stdInMode,\r
+    /* const UString & stdInFileName, */\r
+    bool stdOutMode,\r
+    const CDirItems &dirItems,\r
+    bool sfxMode,\r
+    const UString &sfxModule,\r
+    const CRecordVector<UInt64> &volumesSizes,\r
+    CTempFiles &tempFiles,\r
+    CUpdateErrorInfo &errorInfo,\r
+    IUpdateCallbackUI *callback)\r
+{\r
+  CMyComPtr<IOutArchive> outArchive;\r
+  if (archive != NULL)\r
+  {\r
+    CMyComPtr<IInArchive> archive2 = archive;\r
+    HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive);\r
+    if (result != S_OK)\r
+      throw kUpdateIsNotSupoorted;\r
+  }\r
+  else\r
+  {\r
+    RINOK(codecs->CreateOutArchive(compressionMethod.FormatIndex, outArchive));\r
+\r
+    #ifdef EXTERNAL_CODECS\r
+    {\r
+      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;\r
+      outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);\r
+      if (setCompressCodecsInfo)\r
+      {\r
+        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs));\r
+      }\r
+    }\r
+    #endif\r
+  }\r
+  if (outArchive == 0)\r
+    throw kUpdateIsNotSupoorted;\r
+  \r
+  NFileTimeType::EEnum fileTimeType;\r
+  UInt32 value;\r
+  RINOK(outArchive->GetFileTimeType(&value));\r
+\r
+  switch(value)\r
+  {\r
+    case NFileTimeType::kWindows:\r
+    case NFileTimeType::kUnix:\r
+    case NFileTimeType::kDOS:\r
+      fileTimeType = (NFileTimeType::EEnum)value;\r
+      break;\r
+    default:\r
+      return E_FAIL;\r
+  }\r
+\r
+  CRecordVector<CUpdatePair2> updatePairs2;\r
+\r
+  {\r
+    CRecordVector<CUpdatePair> updatePairs;\r
+    GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!!\r
+    // CUpdateProduceCallbackImp upCallback(&arcItems, callback);\r
+    UpdateProduce(updatePairs, actionSet, updatePairs2, NULL /* &upCallback */);\r
+  }\r
+\r
+  UInt32 numFiles = 0;\r
+  for (int i = 0; i < updatePairs2.Size(); i++)\r
+    if (updatePairs2[i].NewData)\r
+      numFiles++;\r
+  \r
+  RINOK(callback->SetNumFiles(numFiles));\r
+\r
+  \r
+  CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;\r
+  CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);\r
+  \r
+  updateCallbackSpec->ShareForWrite = shareForWrite;\r
+  updateCallbackSpec->StdInMode = stdInMode;\r
+  updateCallbackSpec->Callback = callback;\r
+  updateCallbackSpec->DirItems = &dirItems;\r
+  updateCallbackSpec->ArcItems = &arcItems;\r
+  updateCallbackSpec->UpdatePairs = &updatePairs2;\r
+\r
+  CMyComPtr<ISequentialOutStream> outStream;\r
+\r
+  if (!stdOutMode)\r
+  {\r
+    UString resultPath;\r
+    int pos;\r
+    if (!NFile::NDirectory::MyGetFullPathName(archivePath.GetFinalPath(), resultPath, pos))\r
+      throw 1417161;\r
+    NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));\r
+  }\r
+\r
+  COutFileStream *outStreamSpec = NULL;\r
+  COutMultiVolStream *volStreamSpec = NULL;\r
+\r
+  if (volumesSizes.Size() == 0)\r
+  {\r
+    if (stdOutMode)\r
+      outStream = new CStdOutFileStream;\r
+    else\r
+    {\r
+      outStreamSpec = new COutFileStream;\r
+      outStream = outStreamSpec;\r
+      bool isOK = false;\r
+      UString realPath;\r
+      for (int i = 0; i < (1 << 16); i++)\r
+      {\r
+        if (archivePath.Temp)\r
+        {\r
+          if (i > 0)\r
+          {\r
+            wchar_t s[16];\r
+            ConvertUInt32ToString(i, s);\r
+            archivePath.TempPostfix = s;\r
+          }\r
+          realPath = archivePath.GetTempPath();\r
+        }\r
+        else\r
+          realPath = archivePath.GetFinalPath();\r
+        if (outStreamSpec->Create(realPath, false))\r
+        {\r
+          tempFiles.Paths.Add(realPath);\r
+          isOK = true;\r
+          break;\r
+        }\r
+        if (::GetLastError() != ERROR_FILE_EXISTS)\r
+          break;\r
+        if (!archivePath.Temp)\r
+          break;\r
+      }\r
+      if (!isOK)\r
+      {\r
+        errorInfo.SystemError = ::GetLastError();\r
+        errorInfo.FileName = realPath;\r
+        errorInfo.Message = L"7-Zip cannot open file";\r
+        return E_FAIL;\r
+      }\r
+    }\r
+  }\r
+  else\r
+  {\r
+    if (stdOutMode)\r
+      return E_FAIL;\r
+    volStreamSpec = new COutMultiVolStream;\r
+    outStream = volStreamSpec;\r
+    volStreamSpec->Sizes = volumesSizes;\r
+    volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L".");\r
+    volStreamSpec->TempFiles = &tempFiles;\r
+    volStreamSpec->Init();\r
+\r
+    /*\r
+    updateCallbackSpec->VolumesSizes = volumesSizes;\r
+    updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name;\r
+    if (!archivePath.VolExtension.IsEmpty())\r
+      updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension;\r
+    */\r
+  }\r
+\r
+  RINOK(SetProperties(outArchive, compressionMethod.Properties));\r
+\r
+  if (sfxMode)\r
+  {\r
+    CInFileStream *sfxStreamSpec = new CInFileStream;\r
+    CMyComPtr<IInStream> sfxStream(sfxStreamSpec);\r
+    if (!sfxStreamSpec->Open(sfxModule))\r
+    {\r
+      errorInfo.SystemError = ::GetLastError();\r
+      errorInfo.Message = L"7-Zip cannot open SFX module";\r
+      errorInfo.FileName = sfxModule;\r
+      return E_FAIL;\r
+    }\r
+\r
+    CMyComPtr<ISequentialOutStream> sfxOutStream;\r
+    COutFileStream *outStreamSpec = NULL;\r
+    if (volumesSizes.Size() == 0)\r
+      sfxOutStream = outStream;\r
+    else\r
+    {\r
+      outStreamSpec = new COutFileStream;\r
+      sfxOutStream = outStreamSpec;\r
+      UString realPath = archivePath.GetFinalPath();\r
+      if (!outStreamSpec->Create(realPath, false))\r
+      {\r
+        errorInfo.SystemError = ::GetLastError();\r
+        errorInfo.FileName = realPath;\r
+        errorInfo.Message = L"7-Zip cannot open file";\r
+        return E_FAIL;\r
+      }\r
+    }\r
+    RINOK(NCompress::CopyStream(sfxStream, sfxOutStream, NULL));\r
+    if (outStreamSpec)\r
+    {\r
+      RINOK(outStreamSpec->Close());\r
+    }\r
+  }\r
+\r
+  HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(), updateCallback);\r
+  callback->Finilize();\r
+  RINOK(result);\r
+  if (outStreamSpec)\r
+    result = outStreamSpec->Close();\r
+  else if (volStreamSpec)\r
+    result = volStreamSpec->Close();\r
+  return result;\r
+}\r
+\r
+HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor,\r
+    const CArc &arc,\r
+    CObjectVector<CArcItem> &arcItems)\r
+{\r
+  arcItems.Clear();\r
+  UInt32 numItems;\r
+  IInArchive *archive = arc.Archive;\r
+  RINOK(archive->GetNumberOfItems(&numItems));\r
+  arcItems.Reserve(numItems);\r
+  for (UInt32 i = 0; i < numItems; i++)\r
+  {\r
+    CArcItem ai;\r
+\r
+    RINOK(arc.GetItemPath(i, ai.Name));\r
+    RINOK(IsArchiveItemFolder(archive, i, ai.IsDir));\r
+    ai.Censored = censor.CheckPath(ai.Name, !ai.IsDir);\r
+    RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined));\r
+\r
+    {\r
+      CPropVariant prop;\r
+      RINOK(archive->GetProperty(i, kpidSize, &prop));\r
+      ai.SizeDefined = (prop.vt != VT_EMPTY);\r
+      if (ai.SizeDefined)\r
+        ai.Size = ConvertPropVariantToUInt64(prop);\r
+    }\r
+\r
+    {\r
+      CPropVariant prop;\r
+      RINOK(archive->GetProperty(i, kpidTimeType, &prop));\r
+      if (prop.vt == VT_UI4)\r
+      {\r
+        ai.TimeType = (int)(NFileTimeType::EEnum)prop.ulVal;\r
+        switch(ai.TimeType)\r
+        {\r
+          case NFileTimeType::kWindows:\r
+          case NFileTimeType::kUnix:\r
+          case NFileTimeType::kDOS:\r
+            break;\r
+          default:\r
+            return E_FAIL;\r
+        }\r
+      }\r
+    }\r
+\r
+    ai.IndexInServer = i;\r
+    arcItems.Add(ai);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+\r
+static HRESULT UpdateWithItemLists(\r
+    CCodecs *codecs,\r
+    CUpdateOptions &options,\r
+    IInArchive *archive,\r
+    const CObjectVector<CArcItem> &arcItems,\r
+    CDirItems &dirItems,\r
+    CTempFiles &tempFiles,\r
+    CUpdateErrorInfo &errorInfo,\r
+    IUpdateCallbackUI2 *callback)\r
+{\r
+  for(int i = 0; i < options.Commands.Size(); i++)\r
+  {\r
+    CUpdateArchiveCommand &command = options.Commands[i];\r
+    if (options.StdOutMode)\r
+    {\r
+      RINOK(callback->StartArchive(L"stdout", archive != 0));\r
+    }\r
+    else\r
+    {\r
+      RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(),\r
+          i == 0 && options.UpdateArchiveItself && archive != 0));\r
+    }\r
+\r
+    RINOK(Compress(\r
+        codecs,\r
+        command.ActionSet, archive,\r
+        options.MethodMode,\r
+        command.ArchivePath,\r
+        arcItems,\r
+        options.OpenShareForWrite,\r
+        options.StdInMode,\r
+        /* options.StdInFileName, */\r
+        options.StdOutMode,\r
+        dirItems,\r
+        options.SfxMode, options.SfxModule,\r
+        options.VolumesSizes,\r
+        tempFiles,\r
+        errorInfo, callback));\r
+\r
+    RINOK(callback->FinishArchive());\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+#if defined(_WIN32) && !defined(UNDER_CE)\r
+class CCurrentDirRestorer\r
+{\r
+  UString _path;\r
+public:\r
+  CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(_path); }\r
+  ~CCurrentDirRestorer() { RestoreDirectory();}\r
+  bool RestoreDirectory() { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(_path)); }\r
+};\r
+#endif\r
+\r
+struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback\r
+{\r
+  IUpdateCallbackUI2 *Callback;\r
+  HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path)\r
+  {\r
+    return Callback->ScanProgress(numFolders, numFiles, path);\r
+  }\r
+};\r
+\r
+#ifdef _WIN32\r
+typedef ULONG (FAR PASCAL MY_MAPISENDDOCUMENTS)(\r
+  ULONG_PTR ulUIParam,\r
+  LPSTR lpszDelimChar,\r
+  LPSTR lpszFilePaths,\r
+  LPSTR lpszFileNames,\r
+  ULONG ulReserved\r
+);\r
+typedef MY_MAPISENDDOCUMENTS FAR *MY_LPMAPISENDDOCUMENTS;\r
+#endif\r
+\r
+HRESULT UpdateArchive(\r
+    CCodecs *codecs,\r
+    const NWildcard::CCensor &censor,\r
+    CUpdateOptions &options,\r
+    CUpdateErrorInfo &errorInfo,\r
+    IOpenCallbackUI *openCallback,\r
+    IUpdateCallbackUI2 *callback)\r
+{\r
+  if (options.StdOutMode && options.EMailMode)\r
+    return E_FAIL;\r
+\r
+  if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode))\r
+    return E_NOTIMPL;\r
+\r
+  if (options.SfxMode)\r
+  {\r
+    CProperty property;\r
+    property.Name = L"rsfx";\r
+    property.Value = L"on";\r
+    options.MethodMode.Properties.Add(property);\r
+    if (options.SfxModule.IsEmpty())\r
+    {\r
+      errorInfo.Message = L"SFX file is not specified";\r
+      return E_FAIL;\r
+    }\r
+    UString name = options.SfxModule;\r
+    #ifdef UNDER_CE\r
+    if (!NFind::DoesFileExist(name))\r
+    #else\r
+    if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule))\r
+    #endif\r
+    {\r
+      errorInfo.SystemError = ::GetLastError();\r
+      errorInfo.Message = L"7-Zip cannot find specified SFX module";\r
+      errorInfo.FileName = name;\r
+      return E_FAIL;\r
+    }\r
+  }\r
+\r
+\r
+  CArchiveLink arcLink;\r
+  const UString arcPath = options.ArchivePath.GetFinalPath();\r
+\r
+  if (!options.ArchivePath.OriginalPath.IsEmpty())\r
+  {\r
+    NFind::CFileInfoW fi;\r
+    if (fi.Find(arcPath))\r
+    {\r
+      if (fi.IsDir())\r
+        throw "there is no such archive";\r
+      if (options.VolumesSizes.Size() > 0)\r
+        return E_NOTIMPL;\r
+      CIntVector formatIndices;\r
+      if (options.MethodMode.FormatIndex >= 0)\r
+        formatIndices.Add(options.MethodMode.FormatIndex);\r
+      HRESULT result = arcLink.Open2(codecs, formatIndices, false, NULL, arcPath, openCallback);\r
+      if (result == E_ABORT)\r
+        return result;\r
+      RINOK(callback->OpenResult(arcPath, result));\r
+      RINOK(result);\r
+      if (arcLink.VolumePaths.Size() > 1)\r
+      {\r
+        errorInfo.SystemError = (DWORD)E_NOTIMPL;\r
+        errorInfo.Message = L"Updating for multivolume archives is not implemented";\r
+        return E_NOTIMPL;\r
+      }\r
+      \r
+      CArc &arc = arcLink.Arcs.Back();\r
+      arc.MTimeDefined = !fi.IsDevice;\r
+      arc.MTime = fi.MTime;\r
+    }\r
+  }\r
+  else\r
+  {\r
+    /*\r
+    if (archiveType.IsEmpty())\r
+      throw "type of archive is not specified";\r
+    */\r
+  }\r
+\r
+  CDirItems dirItems;\r
+  if (options.StdInMode)\r
+  {\r
+    CDirItem di;\r
+    di.Name = options.StdInFileName;\r
+    di.Size = (UInt64)(Int64)-1;\r
+    di.Attrib = 0;\r
+    NTime::GetCurUtcFileTime(di.MTime);\r
+    di.CTime = di.ATime = di.MTime;\r
+    dirItems.Items.Add(di);\r
+  }\r
+  else\r
+  {\r
+    bool needScanning = false;\r
+    for(int i = 0; i < options.Commands.Size(); i++)\r
+      if (options.Commands[i].ActionSet.NeedScanning())\r
+        needScanning = true;\r
+    if (needScanning)\r
+    {\r
+      CEnumDirItemUpdateCallback enumCallback;\r
+      enumCallback.Callback = callback;\r
+      RINOK(callback->StartScanning());\r
+      UStringVector errorPaths;\r
+      CRecordVector<DWORD> errorCodes;\r
+      HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes);\r
+      for (int i = 0; i < errorPaths.Size(); i++)\r
+      {\r
+        RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i]));\r
+      }\r
+      if (res != S_OK)\r
+      {\r
+        if (res != E_ABORT)\r
+          errorInfo.Message = L"Scanning error";\r
+        return res;\r
+      }\r
+      RINOK(callback->FinishScanning());\r
+    }\r
+  }\r
+\r
+  UString tempDirPrefix;\r
+  bool usesTempDir = false;\r
+  \r
+  #ifdef _WIN32\r
+  NDirectory::CTempDirectoryW tempDirectory;\r
+  if (options.EMailMode && options.EMailRemoveAfter)\r
+  {\r
+    tempDirectory.Create(kTempFolderPrefix);\r
+    tempDirPrefix = tempDirectory.GetPath();\r
+    NormalizeDirPathPrefix(tempDirPrefix);\r
+    usesTempDir = true;\r
+  }\r
+  #endif\r
+\r
+  CTempFiles tempFiles;\r
+\r
+  bool createTempFile = false;\r
+\r
+  bool thereIsInArchive = arcLink.IsOpen;\r
+\r
+  if (!options.StdOutMode && options.UpdateArchiveItself)\r
+  {\r
+    CArchivePath &ap = options.Commands[0].ArchivePath;\r
+    ap = options.ArchivePath;\r
+    // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty())\r
+    if ((thereIsInArchive || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0)\r
+    {\r
+      createTempFile = true;\r
+      ap.Temp = true;\r
+      if (!options.WorkingDir.IsEmpty())\r
+      {\r
+        ap.TempPrefix = options.WorkingDir;\r
+        NormalizeDirPathPrefix(ap.TempPrefix);\r
+      }\r
+    }\r
+  }\r
+\r
+  for(int i = 0; i < options.Commands.Size(); i++)\r
+  {\r
+    CArchivePath &ap = options.Commands[i].ArchivePath;\r
+    if (usesTempDir)\r
+    {\r
+      // Check it\r
+      ap.Prefix = tempDirPrefix;\r
+      // ap.Temp = true;\r
+      // ap.TempPrefix = tempDirPrefix;\r
+    }\r
+    if (!options.StdOutMode &&\r
+        (i > 0 || !createTempFile))\r
+    {\r
+      const UString &path = ap.GetFinalPath();\r
+      if (NFind::DoesFileOrDirExist(path))\r
+      {\r
+        errorInfo.SystemError = 0;\r
+        errorInfo.Message = L"The file already exists";\r
+        errorInfo.FileName = path;\r
+        return E_FAIL;\r
+      }\r
+    }\r
+  }\r
+\r
+  CObjectVector<CArcItem> arcItems;\r
+  if (thereIsInArchive)\r
+  {\r
+    RINOK(EnumerateInArchiveItems(censor, arcLink.Arcs.Back(), arcItems));\r
+  }\r
+\r
+  RINOK(UpdateWithItemLists(codecs, options,\r
+      thereIsInArchive ? arcLink.GetArchive() : 0,\r
+      arcItems, dirItems,\r
+      tempFiles, errorInfo, callback));\r
+\r
+  if (thereIsInArchive)\r
+  {\r
+    RINOK(arcLink.Close());\r
+    arcLink.Release();\r
+  }\r
+\r
+  tempFiles.Paths.Clear();\r
+  if (createTempFile)\r
+  {\r
+    try\r
+    {\r
+      CArchivePath &ap = options.Commands[0].ArchivePath;\r
+      const UString &tempPath = ap.GetTempPath();\r
+      if (thereIsInArchive)\r
+        if (!NDirectory::DeleteFileAlways(arcPath))\r
+        {\r
+          errorInfo.SystemError = ::GetLastError();\r
+          errorInfo.Message = L"7-Zip cannot delete the file";\r
+          errorInfo.FileName = arcPath;\r
+          return E_FAIL;\r
+        }\r
+      if (!NDirectory::MyMoveFile(tempPath, arcPath))\r
+      {\r
+        errorInfo.SystemError = ::GetLastError();\r
+        errorInfo.Message = L"7-Zip cannot move the file";\r
+        errorInfo.FileName = tempPath;\r
+        errorInfo.FileName2 = arcPath;\r
+        return E_FAIL;\r
+      }\r
+    }\r
+    catch(...)\r
+    {\r
+      throw;\r
+    }\r
+  }\r
+\r
+  #if defined(_WIN32) && !defined(UNDER_CE)\r
+  if (options.EMailMode)\r
+  {\r
+    NDLL::CLibrary mapiLib;\r
+    if (!mapiLib.Load(TEXT("Mapi32.dll")))\r
+    {\r
+      errorInfo.SystemError = ::GetLastError();\r
+      errorInfo.Message = L"7-Zip cannot load Mapi32.dll";\r
+      return E_FAIL;\r
+    }\r
+    MY_LPMAPISENDDOCUMENTS fnSend = (MY_LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments");\r
+    if (fnSend == 0)\r
+    {\r
+      errorInfo.SystemError = ::GetLastError();\r
+      errorInfo.Message = L"7-Zip cannot find MAPISendDocuments function";\r
+      return E_FAIL;\r
+    }\r
+    UStringVector fullPaths;\r
+    int i;\r
+    for(i = 0; i < options.Commands.Size(); i++)\r
+    {\r
+      CArchivePath &ap = options.Commands[i].ArchivePath;\r
+      UString arcPath;\r
+      if (!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath))\r
+      {\r
+        errorInfo.SystemError = ::GetLastError();\r
+        errorInfo.Message = L"GetFullPathName error";\r
+        return E_FAIL;\r
+      }\r
+      fullPaths.Add(arcPath);\r
+    }\r
+    CCurrentDirRestorer curDirRestorer;\r
+    for(i = 0; i < fullPaths.Size(); i++)\r
+    {\r
+      UString arcPath = fullPaths[i];\r
+      UString fileName = ExtractFileNameFromPath(arcPath);\r
+      AString path = GetAnsiString(arcPath);\r
+      AString name = GetAnsiString(fileName);\r
+      // Warning!!! MAPISendDocuments function changes Current directory\r
+      fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);\r
+    }\r
+  }\r
+  #endif\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/UI/Common/Update.h b/CPP/7zip/UI/Common/Update.h
new file mode 100755 (executable)
index 0000000..6bc85b5
--- /dev/null
@@ -0,0 +1,175 @@
+// Update.h\r
+\r
+#ifndef __COMMON_UPDATE_H\r
+#define __COMMON_UPDATE_H\r
+\r
+#include "Common/Wildcard.h"\r
+\r
+#include "ArchiveOpenCallback.h"\r
+#include "LoadCodecs.h"\r
+#include "Property.h"\r
+#include "UpdateAction.h"\r
+#include "UpdateCallback.h"\r
+\r
+struct CArchivePath\r
+{\r
+  UString OriginalPath;\r
+\r
+  UString Prefix;   // path(folder) prefix including slash\r
+  UString Name; // base name\r
+  UString BaseExtension; // archive type extension or "exe" extension\r
+  UString VolExtension;  // archive type extension for volumes\r
+\r
+  bool Temp;\r
+  UString TempPrefix;  // path(folder) for temp location\r
+  UString TempPostfix;\r
+\r
+  CArchivePath(): Temp(false) {};\r
+  \r
+  void ParseFromPath(const UString &path)\r
+  {\r
+    OriginalPath = path;\r
+\r
+    SplitPathToParts(path, Prefix, Name);\r
+    int dotPos = Name.ReverseFind(L'.');\r
+    if (dotPos < 0)\r
+      return;\r
+    if (dotPos == Name.Length() - 1)\r
+    {\r
+      Name = Name.Left(dotPos);\r
+      BaseExtension.Empty();\r
+      return;\r
+    }\r
+    if (BaseExtension.CompareNoCase(Name.Mid(dotPos + 1)) == 0)\r
+    {\r
+      BaseExtension = Name.Mid(dotPos + 1);\r
+      Name = Name.Left(dotPos);\r
+    }\r
+    else\r
+      BaseExtension.Empty();\r
+  }\r
+\r
+  UString GetPathWithoutExt() const\r
+  {\r
+    return Prefix + Name;\r
+  }\r
+\r
+  UString GetFinalPath() const\r
+  {\r
+    UString path = GetPathWithoutExt();\r
+    if (!BaseExtension.IsEmpty())\r
+      path += UString(L'.') + BaseExtension;\r
+    return path;\r
+  }\r
+\r
+  \r
+  UString GetTempPath() const\r
+  {\r
+    UString path = TempPrefix + Name;\r
+    if (!BaseExtension.IsEmpty())\r
+      path += UString(L'.') + BaseExtension;\r
+    path += L".tmp";\r
+    path += TempPostfix;\r
+    return path;\r
+  }\r
+};\r
+\r
+struct CUpdateArchiveCommand\r
+{\r
+  UString UserArchivePath;\r
+  CArchivePath ArchivePath;\r
+  NUpdateArchive::CActionSet ActionSet;\r
+};\r
+\r
+struct CCompressionMethodMode\r
+{\r
+  int FormatIndex;\r
+  CObjectVector<CProperty> Properties;\r
+  CCompressionMethodMode(): FormatIndex(-1) {}\r
+};\r
+\r
+struct CUpdateOptions\r
+{\r
+  CCompressionMethodMode MethodMode;\r
+\r
+  CObjectVector<CUpdateArchiveCommand> Commands;\r
+  bool UpdateArchiveItself;\r
+  CArchivePath ArchivePath;\r
+  \r
+  bool SfxMode;\r
+  UString SfxModule;\r
+  \r
+  bool OpenShareForWrite;\r
+\r
+  bool StdInMode;\r
+  UString StdInFileName;\r
+  bool StdOutMode;\r
+  \r
+  bool EMailMode;\r
+  bool EMailRemoveAfter;\r
+  UString EMailAddress;\r
+\r
+  UString WorkingDir;\r
+\r
+  bool Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath);\r
+\r
+  CUpdateOptions():\r
+    UpdateArchiveItself(true),\r
+    SfxMode(false),\r
+    StdInMode(false),\r
+    StdOutMode(false),\r
+    EMailMode(false),\r
+    EMailRemoveAfter(false),\r
+    OpenShareForWrite(false)\r
+      {};\r
+\r
+  void SetAddActionCommand()\r
+  {\r
+    Commands.Clear();\r
+    CUpdateArchiveCommand c;\r
+    c.ActionSet = NUpdateArchive::kAddActionSet;\r
+    Commands.Add(c);\r
+  }\r
+\r
+  CRecordVector<UInt64> VolumesSizes;\r
+};\r
+\r
+struct CErrorInfo\r
+{\r
+  DWORD SystemError;\r
+  UString FileName;\r
+  UString FileName2;\r
+  UString Message;\r
+  // UStringVector ErrorPaths;\r
+  // CRecordVector<DWORD> ErrorCodes;\r
+  CErrorInfo(): SystemError(0) {};\r
+};\r
+\r
+struct CUpdateErrorInfo: public CErrorInfo\r
+{\r
+};\r
+\r
+#define INTERFACE_IUpdateCallbackUI2(x) \\r
+  INTERFACE_IUpdateCallbackUI(x) \\r
+  virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) x; \\r
+  virtual HRESULT StartScanning() x; \\r
+  virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) x; \\r
+  virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \\r
+  virtual HRESULT FinishScanning() x; \\r
+  virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \\r
+  virtual HRESULT FinishArchive() x; \\r
+\r
+struct IUpdateCallbackUI2: public IUpdateCallbackUI\r
+{\r
+  INTERFACE_IUpdateCallbackUI2(=0)\r
+};\r
+\r
+HRESULT UpdateArchive(\r
+    CCodecs *codecs,\r
+    const NWildcard::CCensor &censor,\r
+    CUpdateOptions &options,\r
+    CUpdateErrorInfo &errorInfo,\r
+    IOpenCallbackUI *openCallback,\r
+    IUpdateCallbackUI2 *callback);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/UpdateAction.cpp b/CPP/7zip/UI/Common/UpdateAction.cpp
new file mode 100755 (executable)
index 0000000..2e3dd62
--- /dev/null
@@ -0,0 +1,64 @@
+// UpdateAction.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "UpdateAction.h"\r
+\r
+namespace NUpdateArchive {\r
+\r
+const CActionSet kAddActionSet =\r
+{{\r
+  NPairAction::kCopy,\r
+  NPairAction::kCopy,\r
+  NPairAction::kCompress,\r
+  NPairAction::kCompress,\r
+  NPairAction::kCompress,\r
+  NPairAction::kCompress,\r
+  NPairAction::kCompress\r
+}};\r
+\r
+const CActionSet kUpdateActionSet =\r
+{{\r
+  NPairAction::kCopy,\r
+  NPairAction::kCopy,\r
+  NPairAction::kCompress,\r
+  NPairAction::kCopy,\r
+  NPairAction::kCompress,\r
+  NPairAction::kCopy,\r
+  NPairAction::kCompress\r
+}};\r
+\r
+const CActionSet kFreshActionSet =\r
+{{\r
+  NPairAction::kCopy,\r
+  NPairAction::kCopy,\r
+  NPairAction::kIgnore,\r
+  NPairAction::kCopy,\r
+  NPairAction::kCompress,\r
+  NPairAction::kCopy,\r
+  NPairAction::kCompress\r
+}};\r
+\r
+const CActionSet kSynchronizeActionSet =\r
+{{\r
+  NPairAction::kCopy,\r
+  NPairAction::kIgnore,\r
+  NPairAction::kCompress,\r
+  NPairAction::kCopy,\r
+  NPairAction::kCompress,\r
+  NPairAction::kCopy,\r
+  NPairAction::kCompress,\r
+}};\r
+\r
+const CActionSet kDeleteActionSet =\r
+{{\r
+  NPairAction::kCopy,\r
+  NPairAction::kIgnore,\r
+  NPairAction::kIgnore,\r
+  NPairAction::kIgnore,\r
+  NPairAction::kIgnore,\r
+  NPairAction::kIgnore,\r
+  NPairAction::kIgnore\r
+}};\r
+\r
+}\r
diff --git a/CPP/7zip/UI/Common/UpdateAction.h b/CPP/7zip/UI/Common/UpdateAction.h
new file mode 100755 (executable)
index 0000000..7ad57ce
--- /dev/null
@@ -0,0 +1,57 @@
+// UpdateAction.h\r
+\r
+#ifndef __UPDATE_ACTION_H\r
+#define __UPDATE_ACTION_H\r
+\r
+namespace NUpdateArchive {\r
+\r
+  namespace NPairState\r
+  {\r
+    const int kNumValues = 7;\r
+    enum EEnum\r
+    {\r
+      kNotMasked = 0,\r
+      kOnlyInArchive,\r
+      kOnlyOnDisk,\r
+      kNewInArchive,\r
+      kOldInArchive,\r
+      kSameFiles,\r
+      kUnknowNewerFiles\r
+    };\r
+  }\r
\r
+  namespace NPairAction\r
+  {\r
+    enum EEnum\r
+    {\r
+      kIgnore = 0,\r
+      kCopy,\r
+      kCompress,\r
+      kCompressAsAnti\r
+    };\r
+  }\r
+  \r
+  struct CActionSet\r
+  {\r
+    NPairAction::EEnum StateActions[NPairState::kNumValues];\r
+    bool NeedScanning() const\r
+    {\r
+      int i;\r
+      for (i = 0; i < NPairState::kNumValues; i++)\r
+        if (StateActions[i] == NPairAction::kCompress)\r
+          return true;\r
+      for (i = 1; i < NPairState::kNumValues; i++)\r
+        if (StateActions[i] != NPairAction::kIgnore)\r
+          return true;\r
+      return false;\r
+    }\r
+  };\r
+  \r
+  extern const CActionSet kAddActionSet;\r
+  extern const CActionSet kUpdateActionSet;\r
+  extern const CActionSet kFreshActionSet;\r
+  extern const CActionSet kSynchronizeActionSet;\r
+  extern const CActionSet kDeleteActionSet;\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp
new file mode 100755 (executable)
index 0000000..55c9374
--- /dev/null
@@ -0,0 +1,249 @@
+// UpdateCallback.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/Defs.h"\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../../Common/FileStreams.h"\r
+\r
+#include "UpdateCallback.h"\r
+\r
+using namespace NWindows;\r
+\r
+CArchiveUpdateCallback::CArchiveUpdateCallback():\r
+  Callback(0),\r
+  ShareForWrite(false),\r
+  StdInMode(false),\r
+  DirItems(0),\r
+  ArcItems(0),\r
+  UpdatePairs(0),\r
+  NewNames(0)\r
+  {}\r
+\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size)\r
+{\r
+  COM_TRY_BEGIN\r
+  return Callback->SetTotal(size);\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue)\r
+{\r
+  COM_TRY_BEGIN\r
+  return Callback->SetCompleted(completeValue);\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)\r
+{\r
+  COM_TRY_BEGIN\r
+  return Callback->SetRatioInfo(inSize, outSize);\r
+  COM_TRY_END\r
+}\r
+\r
+\r
+/*\r
+STATPROPSTG kProperties[] =\r
+{\r
+  { NULL, kpidPath, VT_BSTR},\r
+  { NULL, kpidIsDir, VT_BOOL},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidCTime, VT_FILETIME},\r
+  { NULL, kpidATime, VT_FILETIME},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidAttrib, VT_UI4},\r
+  { NULL, kpidIsAnti, VT_BOOL}\r
+};\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **)\r
+{\r
+  return CStatPropEnumerator::CreateEnumerator(kProperties, sizeof(kProperties) / sizeof(kProperties[0]), enumerator);\r
+}\r
+*/\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index,\r
+      Int32 *newData, Int32 *newProps, UInt32 *indexInArchive)\r
+{\r
+  COM_TRY_BEGIN\r
+  RINOK(Callback->CheckBreak());\r
+  const CUpdatePair2 &up = (*UpdatePairs)[index];\r
+  if (newData != NULL) *newData = BoolToInt(up.NewData);\r
+  if (newProps != NULL) *newProps = BoolToInt(up.NewProps);\r
+  if (indexInArchive != NULL)\r
+  {\r
+    *indexInArchive = (UInt32)-1;\r
+    if (up.ExistInArchive())\r
+      *indexInArchive = (ArcItems == 0) ? up.ArcIndex : (*ArcItems)[up.ArcIndex].IndexInServer;\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  const CUpdatePair2 &up = (*UpdatePairs)[index];\r
+  NWindows::NCOM::CPropVariant prop;\r
+  \r
+  if (propID == kpidIsAnti)\r
+  {\r
+    prop = up.IsAnti;\r
+    prop.Detach(value);\r
+    return S_OK;\r
+  }\r
+\r
+  if (up.IsAnti)\r
+  {\r
+    switch(propID)\r
+    {\r
+      case kpidIsDir:\r
+      case kpidPath:\r
+        break;\r
+      case kpidSize:\r
+        prop = (UInt64)0;\r
+        prop.Detach(value);\r
+        return S_OK;\r
+      default:\r
+        prop.Detach(value);\r
+        return S_OK;\r
+    }\r
+  }\r
+  \r
+  if (up.ExistOnDisk())\r
+  {\r
+    const CDirItem &di = DirItems->Items[up.DirIndex];\r
+    switch(propID)\r
+    {\r
+      case kpidPath:  prop = DirItems->GetLogPath(up.DirIndex); break;\r
+      case kpidIsDir:  prop = di.IsDir(); break;\r
+      case kpidSize:  prop = di.Size; break;\r
+      case kpidAttrib:  prop = di.Attrib; break;\r
+      case kpidCTime:  prop = di.CTime; break;\r
+      case kpidATime:  prop = di.ATime; break;\r
+      case kpidMTime:  prop = di.MTime; break;\r
+    }\r
+  }\r
+  else\r
+  {\r
+    if (propID == kpidPath)\r
+    {\r
+      if (up.NewNameIndex >= 0)\r
+      {\r
+        prop = (*NewNames)[up.NewNameIndex];\r
+        prop.Detach(value);\r
+        return S_OK;\r
+      }\r
+    }\r
+    if (up.ExistInArchive() && Archive)\r
+    {\r
+      UInt32 indexInArchive;\r
+      if (ArcItems == 0)\r
+        indexInArchive = up.ArcIndex;\r
+      else\r
+        indexInArchive = (*ArcItems)[up.ArcIndex].IndexInServer;\r
+      return Archive->GetProperty(indexInArchive, propID, value);\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)\r
+{\r
+  COM_TRY_BEGIN\r
+  const CUpdatePair2 &up = (*UpdatePairs)[index];\r
+  if (!up.NewData)\r
+    return E_FAIL;\r
+  \r
+  RINOK(Callback->CheckBreak());\r
+  RINOK(Callback->Finilize());\r
+\r
+  if (up.IsAnti)\r
+  {\r
+    return Callback->GetStream((*ArcItems)[up.ArcIndex].Name, true);\r
+  }\r
+  const CDirItem &di = DirItems->Items[up.DirIndex];\r
+  RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), false));\r
\r
+  if (di.IsDir())\r
+    return S_OK;\r
+\r
+  if (StdInMode)\r
+  {\r
+    CStdInFileStream *inStreamSpec = new CStdInFileStream;\r
+    CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);\r
+    *inStream = inStreamLoc.Detach();\r
+  }\r
+  else\r
+  {\r
+    CInFileStream *inStreamSpec = new CInFileStream;\r
+    CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);\r
+    const UString path = DirItems->GetPhyPath(up.DirIndex);\r
+    if (!inStreamSpec->OpenShared(path, ShareForWrite))\r
+    {\r
+      return Callback->OpenFileError(path, ::GetLastError());\r
+    }\r
+    *inStream = inStreamLoc.Detach();\r
+  }\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult)\r
+{\r
+  COM_TRY_BEGIN\r
+  return Callback->SetOperationResult(operationResult);\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)\r
+{\r
+  if (VolumesSizes.Size() == 0)\r
+    return S_FALSE;\r
+  if (index >= (UInt32)VolumesSizes.Size())\r
+    index = VolumesSizes.Size() - 1;\r
+  *size = VolumesSizes[index];\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)\r
+{\r
+  COM_TRY_BEGIN\r
+  wchar_t temp[16];\r
+  ConvertUInt32ToString(index + 1, temp);\r
+  UString res = temp;\r
+  while (res.Length() < 2)\r
+    res = UString(L'0') + res;\r
+  UString fileName = VolName;\r
+  fileName += L'.';\r
+  fileName += res;\r
+  fileName += VolExt;\r
+  COutFileStream *streamSpec = new COutFileStream;\r
+  CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);\r
+  if (!streamSpec->Create(fileName, false))\r
+    return ::GetLastError();\r
+  *volumeStream = streamLoc.Detach();\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)\r
+{\r
+  COM_TRY_BEGIN\r
+  return Callback->CryptoGetTextPassword2(passwordIsDefined, password);\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword(BSTR *password)\r
+{\r
+  COM_TRY_BEGIN\r
+  return Callback->CryptoGetTextPassword(password);\r
+  COM_TRY_END\r
+}\r
diff --git a/CPP/7zip/UI/Common/UpdateCallback.h b/CPP/7zip/UI/Common/UpdateCallback.h
new file mode 100755 (executable)
index 0000000..2785ee9
--- /dev/null
@@ -0,0 +1,74 @@
+// UpdateCallback.h\r
+\r
+#ifndef __UPDATECALLBACK_H\r
+#define __UPDATECALLBACK_H\r
+\r
+#include "Common/MyCom.h"\r
+#include "Common/MyString.h"\r
+\r
+#include "../../IPassword.h"\r
+#include "../../ICoder.h"\r
+\r
+#include "../Common/UpdatePair.h"\r
+#include "../Common/UpdateProduce.h"\r
+\r
+#define INTERFACE_IUpdateCallbackUI(x) \\r
+  virtual HRESULT SetTotal(UInt64 size) x; \\r
+  virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \\r
+  virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \\r
+  virtual HRESULT CheckBreak() x; \\r
+  virtual HRESULT Finilize() x; \\r
+  virtual HRESULT SetNumFiles(UInt64 numFiles) x; \\r
+  virtual HRESULT GetStream(const wchar_t *name, bool isAnti) x; \\r
+  virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \\r
+  virtual HRESULT SetOperationResult(Int32 operationResult) x; \\r
+  virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \\r
+  virtual HRESULT CryptoGetTextPassword(BSTR *password) x; \\r
+  /* virtual HRESULT ShowDeleteFile(const wchar_t *name) x; */ \\r
+  /* virtual HRESULT CloseProgress() { return S_OK; }; */\r
+\r
+struct IUpdateCallbackUI\r
+{\r
+  INTERFACE_IUpdateCallbackUI(=0)\r
+};\r
+\r
+class CArchiveUpdateCallback:\r
+  public IArchiveUpdateCallback2,\r
+  public ICryptoGetTextPassword2,\r
+  public ICryptoGetTextPassword,\r
+  public ICompressProgressInfo,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP4(\r
+      IArchiveUpdateCallback2,\r
+      ICryptoGetTextPassword2,\r
+      ICryptoGetTextPassword,\r
+      ICompressProgressInfo)\r
+\r
+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);\r
+\r
+  INTERFACE_IArchiveUpdateCallback2(;)\r
+\r
+  STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);\r
+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);\r
+\r
+public:\r
+  CRecordVector<UInt64> VolumesSizes;\r
+  UString VolName;\r
+  UString VolExt;\r
+\r
+  IUpdateCallbackUI *Callback;\r
+\r
+  bool ShareForWrite;\r
+  bool StdInMode;\r
+  const CDirItems *DirItems;\r
+  const CObjectVector<CArcItem> *ArcItems;\r
+  const CRecordVector<CUpdatePair2> *UpdatePairs;\r
+  const UStringVector *NewNames;\r
+  CMyComPtr<IInArchive> Archive;\r
+\r
+  CArchiveUpdateCallback();\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/UpdatePair.cpp b/CPP/7zip/UI/Common/UpdatePair.cpp
new file mode 100755 (executable)
index 0000000..812bff8
--- /dev/null
@@ -0,0 +1,158 @@
+// UpdatePair.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include <time.h>\r
+\r
+#include "Common/Defs.h"\r
+#include "Common/Wildcard.h"\r
+\r
+#include "Windows/Time.h"\r
+\r
+#include "SortUtils.h"\r
+#include "UpdatePair.h"\r
+\r
+using namespace NWindows;\r
+using namespace NTime;\r
+\r
+static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2)\r
+{\r
+  switch(fileTimeType)\r
+  {\r
+    case NFileTimeType::kWindows:\r
+      return ::CompareFileTime(&time1, &time2);\r
+    case NFileTimeType::kUnix:\r
+      {\r
+        UInt32 unixTime1, unixTime2;\r
+        FileTimeToUnixTime(time1, unixTime1);\r
+        FileTimeToUnixTime(time2, unixTime2);\r
+        return MyCompare(unixTime1, unixTime2);\r
+      }\r
+    case NFileTimeType::kDOS:\r
+      {\r
+        UInt32 dosTime1, dosTime2;\r
+        FileTimeToDosTime(time1, dosTime1);\r
+        FileTimeToDosTime(time2, dosTime2);\r
+        return MyCompare(dosTime1, dosTime2);\r
+      }\r
+  }\r
+  throw 4191618;\r
+}\r
+\r
+static const wchar_t *kDuplicateFileNameMessage = L"Duplicate filename:";\r
+static const wchar_t *kNotCensoredCollisionMessaged = L"Internal file name collision (file on disk, file in archive):";\r
+\r
+static void ThrowError(const UString &message, const UString &s1, const UString &s2)\r
+{\r
+  UString m = message;\r
+  m += L'\n';\r
+  m += s1;\r
+  m += L'\n';\r
+  m += s2;\r
+  throw m;\r
+}\r
+\r
+static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices)\r
+{\r
+  for(int i = 0; i + 1 < indices.Size(); i++)\r
+    if (CompareFileNames(strings[indices[i]], strings[indices[i + 1]]) == 0)\r
+      ThrowError(kDuplicateFileNameMessage, strings[indices[i]], strings[indices[i + 1]]);\r
+}\r
+\r
+void GetUpdatePairInfoList(\r
+    const CDirItems &dirItems,\r
+    const CObjectVector<CArcItem> &arcItems,\r
+    NFileTimeType::EEnum fileTimeType,\r
+    CRecordVector<CUpdatePair> &updatePairs)\r
+{\r
+  CIntVector dirIndices, arcIndices;\r
+  \r
+  int numDirItems = dirItems.Items.Size();\r
+  int numArcItems = arcItems.Size();\r
+  \r
+  \r
+  {\r
+    UStringVector arcNames;\r
+    arcNames.Reserve(numArcItems);\r
+    for (int i = 0; i < numArcItems; i++)\r
+      arcNames.Add(arcItems[i].Name);\r
+    SortFileNames(arcNames, arcIndices);\r
+    TestDuplicateString(arcNames, arcIndices);\r
+  }\r
+\r
+  UStringVector dirNames;\r
+  {\r
+    dirNames.Reserve(numDirItems);\r
+    for (int i = 0; i < numDirItems; i++)\r
+      dirNames.Add(dirItems.GetLogPath(i));\r
+    SortFileNames(dirNames, dirIndices);\r
+    TestDuplicateString(dirNames, dirIndices);\r
+  }\r
+  \r
+  int dirIndex = 0, arcIndex = 0;\r
+  while (dirIndex < numDirItems && arcIndex < numArcItems)\r
+  {\r
+    CUpdatePair pair;\r
+    int dirIndex2 = dirIndices[dirIndex];\r
+    int arcIndex2 = arcIndices[arcIndex];\r
+    const CDirItem &di = dirItems.Items[dirIndex2];\r
+    const CArcItem &ai = arcItems[arcIndex2];\r
+    int compareResult = CompareFileNames(dirNames[dirIndex2], ai.Name);\r
+    if (compareResult < 0)\r
+    {\r
+      pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;\r
+      pair.DirIndex = dirIndex2;\r
+      dirIndex++;\r
+    }\r
+    else if (compareResult > 0)\r
+    {\r
+      pair.State = ai.Censored ?\r
+          NUpdateArchive::NPairState::kOnlyInArchive:\r
+          NUpdateArchive::NPairState::kNotMasked;\r
+      pair.ArcIndex = arcIndex2;\r
+      arcIndex++;\r
+    }\r
+    else\r
+    {\r
+      if (!ai.Censored)\r
+        ThrowError(kNotCensoredCollisionMessaged, dirNames[dirIndex2], ai.Name);\r
+      pair.DirIndex = dirIndex2;\r
+      pair.ArcIndex = arcIndex2;\r
+      switch (ai.MTimeDefined ? MyCompareTime(\r
+          ai.TimeType != - 1 ? (NFileTimeType::EEnum)ai.TimeType : fileTimeType,\r
+          di.MTime, ai.MTime): 0)\r
+      {\r
+        case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break;\r
+        case 1:  pair.State = NUpdateArchive::NPairState::kOldInArchive; break;\r
+        default:\r
+          pair.State = (ai.SizeDefined && di.Size == ai.Size) ?\r
+              NUpdateArchive::NPairState::kSameFiles :\r
+              NUpdateArchive::NPairState::kUnknowNewerFiles;\r
+      }\r
+      dirIndex++;\r
+      arcIndex++;\r
+    }\r
+    updatePairs.Add(pair);\r
+  }\r
+\r
+  for (; dirIndex < numDirItems; dirIndex++)\r
+  {\r
+    CUpdatePair pair;\r
+    pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;\r
+    pair.DirIndex = dirIndices[dirIndex];\r
+    updatePairs.Add(pair);\r
+  }\r
+  \r
+  for (; arcIndex < numArcItems; arcIndex++)\r
+  {\r
+    CUpdatePair pair;\r
+    int arcIndex2 = arcIndices[arcIndex];\r
+    pair.State = arcItems[arcIndex2].Censored ?\r
+        NUpdateArchive::NPairState::kOnlyInArchive:\r
+        NUpdateArchive::NPairState::kNotMasked;\r
+    pair.ArcIndex = arcIndex2;\r
+    updatePairs.Add(pair);\r
+  }\r
+\r
+  updatePairs.ReserveDown();\r
+}\r
diff --git a/CPP/7zip/UI/Common/UpdatePair.h b/CPP/7zip/UI/Common/UpdatePair.h
new file mode 100755 (executable)
index 0000000..5ee2665
--- /dev/null
@@ -0,0 +1,25 @@
+// UpdatePair.h\r
+\r
+#ifndef __UPDATE_PAIR_H\r
+#define __UPDATE_PAIR_H\r
+\r
+#include "DirItem.h"\r
+#include "UpdateAction.h"\r
+\r
+#include "../../Archive/IArchive.h"\r
+\r
+struct CUpdatePair\r
+{\r
+  NUpdateArchive::NPairState::EEnum State;\r
+  int ArcIndex;\r
+  int DirIndex;\r
+  CUpdatePair(): ArcIndex(-1), DirIndex(-1) {}\r
+};\r
+\r
+void GetUpdatePairInfoList(\r
+    const CDirItems &dirItems,\r
+    const CObjectVector<CArcItem> &arcItems,\r
+    NFileTimeType::EEnum fileTimeType,\r
+    CRecordVector<CUpdatePair> &updatePairs);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/UpdateProduce.cpp b/CPP/7zip/UI/Common/UpdateProduce.cpp
new file mode 100755 (executable)
index 0000000..3ba677d
--- /dev/null
@@ -0,0 +1,58 @@
+// UpdateProduce.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "UpdateProduce.h"\r
+\r
+using namespace NUpdateArchive;\r
+\r
+static const char *kUpdateActionSetCollision = "Internal collision in update action set";\r
+\r
+void UpdateProduce(\r
+    const CRecordVector<CUpdatePair> &updatePairs,\r
+    const CActionSet &actionSet,\r
+    CRecordVector<CUpdatePair2> &operationChain,\r
+    IUpdateProduceCallback *callback)\r
+{\r
+  for (int i = 0; i < updatePairs.Size(); i++)\r
+  {\r
+    const CUpdatePair &pair = updatePairs[i];\r
+\r
+    CUpdatePair2 up2;\r
+    up2.IsAnti = false;\r
+    up2.DirIndex = pair.DirIndex;\r
+    up2.ArcIndex = pair.ArcIndex;\r
+    up2.NewData = up2.NewProps = true;\r
+    \r
+    switch(actionSet.StateActions[pair.State])\r
+    {\r
+      case NPairAction::kIgnore:\r
+        /*\r
+        if (pair.State != NPairState::kOnlyOnDisk)\r
+          IgnoreArchiveItem(m_ArchiveItems[pair.ArcIndex]);\r
+        // cout << "deleting";\r
+        */\r
+        if (callback)\r
+          callback->ShowDeleteFile(pair.ArcIndex);\r
+        continue;\r
+\r
+      case NPairAction::kCopy:\r
+        if (pair.State == NPairState::kOnlyOnDisk)\r
+          throw kUpdateActionSetCollision;\r
+        up2.NewData = up2.NewProps = false;\r
+        break;\r
+      \r
+      case NPairAction::kCompress:\r
+        if (pair.State == NPairState::kOnlyInArchive ||\r
+            pair.State == NPairState::kNotMasked)\r
+          throw kUpdateActionSetCollision;\r
+        break;\r
+      \r
+      case NPairAction::kCompressAsAnti:\r
+        up2.IsAnti = true;\r
+        break;\r
+    }\r
+    operationChain.Add(up2);\r
+  }\r
+  operationChain.ReserveDown();\r
+}\r
diff --git a/CPP/7zip/UI/Common/UpdateProduce.h b/CPP/7zip/UI/Common/UpdateProduce.h
new file mode 100755 (executable)
index 0000000..c511caf
--- /dev/null
@@ -0,0 +1,35 @@
+// UpdateProduce.h\r
+\r
+#ifndef __UPDATE_PRODUCE_H\r
+#define __UPDATE_PRODUCE_H\r
+\r
+#include "UpdatePair.h"\r
+\r
+struct CUpdatePair2\r
+{\r
+  bool NewData;\r
+  bool NewProps;\r
+  bool IsAnti;\r
+  \r
+  int DirIndex;\r
+  int ArcIndex;\r
+  int NewNameIndex;\r
+\r
+  bool ExistOnDisk() const { return DirIndex != -1; }\r
+  bool ExistInArchive() const { return ArcIndex != -1; }\r
+\r
+  CUpdatePair2(): IsAnti(false), DirIndex(-1), ArcIndex(-1), NewNameIndex(-1) {}\r
+};\r
+\r
+struct IUpdateProduceCallback\r
+{\r
+  virtual HRESULT ShowDeleteFile(int arcIndex) = 0;\r
+};\r
+\r
+void UpdateProduce(\r
+    const CRecordVector<CUpdatePair> &updatePairs,\r
+    const NUpdateArchive::CActionSet &actionSet,\r
+    CRecordVector<CUpdatePair2> &operationChain,\r
+    IUpdateProduceCallback *callback);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/WorkDir.cpp b/CPP/7zip/UI/Common/WorkDir.cpp
new file mode 100755 (executable)
index 0000000..2989632
--- /dev/null
@@ -0,0 +1,59 @@
+// WorkDir.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/StringConvert.h"\r
+#include "Common/Wildcard.h"\r
+\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileName.h"\r
+\r
+#include "WorkDir.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+\r
+UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path)\r
+{\r
+  NWorkDir::NMode::EEnum mode = workDirInfo.Mode;\r
+  #ifndef UNDER_CE\r
+  if (workDirInfo.ForRemovableOnly)\r
+  {\r
+    mode = NWorkDir::NMode::kCurrent;\r
+    UString prefix = path.Left(3);\r
+    if (prefix[1] == L':' && prefix[2] == L'\\')\r
+    {\r
+      UINT driveType = GetDriveType(GetSystemString(prefix, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP));\r
+      if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE)\r
+        mode = workDirInfo.Mode;\r
+    }\r
+    /*\r
+    CParsedPath parsedPath;\r
+    parsedPath.ParsePath(archiveName);\r
+    UINT driveType = GetDriveType(parsedPath.Prefix);\r
+    if ((driveType != DRIVE_CDROM) && (driveType != DRIVE_REMOVABLE))\r
+      mode = NZipSettings::NWorkDir::NMode::kCurrent;\r
+    */\r
+  }\r
+  #endif\r
+  switch(mode)\r
+  {\r
+    case NWorkDir::NMode::kCurrent:\r
+    {\r
+      return ExtractDirPrefixFromPath(path);\r
+    }\r
+    case NWorkDir::NMode::kSpecified:\r
+    {\r
+      UString tempDir = workDirInfo.Path;\r
+      NName::NormalizeDirPathPrefix(tempDir);\r
+      return tempDir;\r
+    }\r
+    default:\r
+    {\r
+      UString tempDir;\r
+      if (!NDirectory::MyGetTempPath(tempDir))\r
+        throw 141717;\r
+      return tempDir;\r
+    }\r
+  }\r
+}\r
diff --git a/CPP/7zip/UI/Common/WorkDir.h b/CPP/7zip/UI/Common/WorkDir.h
new file mode 100755 (executable)
index 0000000..8208f3a
--- /dev/null
@@ -0,0 +1,10 @@
+// WorkDir.h\r
+\r
+#ifndef __WORKDIR_H\r
+#define __WORKDIR_H\r
+\r
+#include "ZipRegistry.h"\r
+\r
+UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp
new file mode 100755 (executable)
index 0000000..be9776d
--- /dev/null
@@ -0,0 +1,293 @@
+// ZipRegistry.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/FileDir.h"\r
+#include "Windows/Registry.h"\r
+#include "Windows/Synchronization.h"\r
+\r
+#include "ZipRegistry.h"\r
+\r
+using namespace NWindows;\r
+using namespace NRegistry;\r
+\r
+static NSynchronization::CCriticalSection g_CS;\r
+#define CS_LOCK NSynchronization::CCriticalSectionLock lock(g_CS);\r
+\r
+static const TCHAR *kCuPrefix = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") TEXT(STRING_PATH_SEPARATOR);\r
+\r
+static CSysString GetKeyPath(const CSysString &path) { return kCuPrefix + path; }\r
+\r
+static LONG OpenMainKey(CKey &key, LPCTSTR keyName)\r
+{\r
+  return key.Open(HKEY_CURRENT_USER, GetKeyPath(keyName), KEY_READ);\r
+}\r
+\r
+static LONG CreateMainKey(CKey &key, LPCTSTR keyName)\r
+{\r
+  return key.Create(HKEY_CURRENT_USER, GetKeyPath(keyName));\r
+}\r
+\r
+namespace NExtract\r
+{\r
+\r
+static const TCHAR *kKeyName = TEXT("Extraction");\r
+\r
+static const TCHAR *kExtractMode = TEXT("ExtractMode");\r
+static const TCHAR *kOverwriteMode = TEXT("OverwriteMode");\r
+static const TCHAR *kShowPassword = TEXT("ShowPassword");\r
+static const TCHAR *kPathHistory = TEXT("PathHistory");\r
+\r
+void CInfo::Save() const\r
+{\r
+  CS_LOCK\r
+  CKey key;\r
+  CreateMainKey(key, kKeyName);\r
+  key.SetValue(kExtractMode, (UInt32)PathMode);\r
+  key.SetValue(kOverwriteMode, (UInt32)OverwriteMode);\r
+  key.SetValue(kShowPassword, ShowPassword);\r
+  key.RecurseDeleteKey(kPathHistory);\r
+  key.SetValue_Strings(kPathHistory, Paths);\r
+}\r
+\r
+\r
+void CInfo::Load()\r
+{\r
+  PathMode = NPathMode::kCurrentPathnames;\r
+  OverwriteMode = NOverwriteMode::kAskBefore;\r
+  ShowPassword = false;\r
+  Paths.Clear();\r
+\r
+  CS_LOCK\r
+  CKey key;\r
+  if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS)\r
+    return;\r
+  \r
+  key.GetValue_Strings(kPathHistory, Paths);\r
+  UInt32 v;\r
+  if (key.QueryValue(kExtractMode, v) == ERROR_SUCCESS && v <= NPathMode::kNoPathnames)\r
+    PathMode = (NPathMode::EEnum)v;\r
+  if (key.QueryValue(kOverwriteMode, v) == ERROR_SUCCESS && v <= NOverwriteMode::kAutoRenameExisting)\r
+    OverwriteMode = (NOverwriteMode::EEnum)v;\r
+  key.GetValue_IfOk(kShowPassword, ShowPassword);\r
+}\r
+\r
+}\r
+\r
+namespace NCompression\r
+{\r
+\r
+static const TCHAR *kKeyName = TEXT("Compression");\r
+\r
+static const TCHAR *kArcHistory = TEXT("ArcHistory");\r
+static const WCHAR *kArchiver = L"Archiver";\r
+static const TCHAR *kShowPassword = TEXT("ShowPassword");\r
+static const TCHAR *kEncryptHeaders = TEXT("EncryptHeaders");\r
+\r
+static const TCHAR *kOptionsKeyName = TEXT("Options");\r
+\r
+static const TCHAR *kLevel = TEXT("Level");\r
+static const TCHAR *kDictionary = TEXT("Dictionary");\r
+static const TCHAR *kOrder = TEXT("Order");\r
+static const TCHAR *kBlockSize = TEXT("BlockSize");\r
+static const TCHAR *kNumThreads = TEXT("NumThreads");\r
+static const WCHAR *kMethod = L"Method";\r
+static const WCHAR *kOptions = L"Options";\r
+static const WCHAR *kEncryptionMethod = L"EncryptionMethod";\r
+\r
+static void SetRegString(CKey &key, const WCHAR *name, const UString &value)\r
+{\r
+  if (value.IsEmpty())\r
+    key.DeleteValue(name);\r
+  else\r
+    key.SetValue(name, value);\r
+}\r
+\r
+static void SetRegUInt32(CKey &key, const TCHAR *name, UInt32 value)\r
+{\r
+  if (value == (UInt32)-1)\r
+    key.DeleteValue(name);\r
+  else\r
+    key.SetValue(name, value);\r
+}\r
+\r
+static void GetRegString(CKey &key, const WCHAR *name, UString &value)\r
+{\r
+  if (key.QueryValue(name, value) != ERROR_SUCCESS)\r
+    value.Empty();\r
+}\r
+\r
+static void GetRegUInt32(CKey &key, const TCHAR *name, UInt32 &value)\r
+{\r
+  if (key.QueryValue(name, value) != ERROR_SUCCESS)\r
+    value = (UInt32)-1;\r
+}\r
+\r
+void CInfo::Save() const\r
+{\r
+  CS_LOCK\r
+\r
+  CKey key;\r
+  CreateMainKey(key, kKeyName);\r
+  key.SetValue(kLevel, (UInt32)Level);\r
+  key.SetValue(kArchiver, ArcType);\r
+  key.SetValue(kShowPassword, ShowPassword);\r
+  key.SetValue(kEncryptHeaders, EncryptHeaders);\r
+  key.RecurseDeleteKey(kArcHistory);\r
+  key.SetValue_Strings(kArcHistory, ArcPaths);\r
+\r
+  key.RecurseDeleteKey(kOptionsKeyName);\r
+  {\r
+    CKey optionsKey;\r
+    optionsKey.Create(key, kOptionsKeyName);\r
+    for (int i = 0; i < Formats.Size(); i++)\r
+    {\r
+      const CFormatOptions &fo = Formats[i];\r
+      CKey fk;\r
+      fk.Create(optionsKey, fo.FormatID);\r
+      \r
+      SetRegUInt32(fk, kLevel, fo.Level);\r
+      SetRegUInt32(fk, kDictionary, fo.Dictionary);\r
+      SetRegUInt32(fk, kOrder, fo.Order);\r
+      SetRegUInt32(fk, kBlockSize, fo.BlockLogSize);\r
+      SetRegUInt32(fk, kNumThreads, fo.NumThreads);\r
+\r
+      SetRegString(fk, kMethod, fo.Method);\r
+      SetRegString(fk, kOptions, fo.Options);\r
+      SetRegString(fk, kEncryptionMethod, fo.EncryptionMethod);\r
+    }\r
+  }\r
+}\r
+\r
+void CInfo::Load()\r
+{\r
+  ArcPaths.Clear();\r
+  Formats.Clear();\r
+\r
+  Level = 5;\r
+  ArcType = L"7z";\r
+  ShowPassword = false;\r
+  EncryptHeaders = false;\r
+\r
+  CS_LOCK\r
+  CKey key;\r
+\r
+  if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS)\r
+    return;\r
+\r
+  key.GetValue_Strings(kArcHistory, ArcPaths);\r
+  \r
+  {\r
+    CKey optionsKey;\r
+    if (optionsKey.Open(key, kOptionsKeyName, KEY_READ) == ERROR_SUCCESS)\r
+    {\r
+      CSysStringVector formatIDs;\r
+      optionsKey.EnumKeys(formatIDs);\r
+      for (int i = 0; i < formatIDs.Size(); i++)\r
+      {\r
+        CKey fk;\r
+        CFormatOptions fo;\r
+        fo.FormatID = formatIDs[i];\r
+        if (fk.Open(optionsKey, fo.FormatID, KEY_READ) == ERROR_SUCCESS)\r
+        {\r
+          GetRegString(fk, kOptions, fo.Options);\r
+          GetRegString(fk, kMethod, fo.Method);\r
+          GetRegString(fk, kEncryptionMethod, fo.EncryptionMethod);\r
+\r
+          GetRegUInt32(fk, kLevel, fo.Level);\r
+          GetRegUInt32(fk, kDictionary, fo.Dictionary);\r
+          GetRegUInt32(fk, kOrder, fo.Order);\r
+          GetRegUInt32(fk, kBlockSize, fo.BlockLogSize);\r
+          GetRegUInt32(fk, kNumThreads, fo.NumThreads);\r
+\r
+          Formats.Add(fo);\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  UString a;\r
+  if (key.QueryValue(kArchiver, a) == ERROR_SUCCESS)\r
+    ArcType = a;\r
+  key.GetValue_IfOk(kLevel, Level);\r
+  key.GetValue_IfOk(kShowPassword, ShowPassword);\r
+  key.GetValue_IfOk(kEncryptHeaders, EncryptHeaders);\r
+}\r
+\r
+}\r
+\r
+static const TCHAR *kOptionsInfoKeyName = TEXT("Options");\r
+\r
+namespace NWorkDir\r
+{\r
+static const TCHAR *kWorkDirType = TEXT("WorkDirType");\r
+static const WCHAR *kWorkDirPath = L"WorkDirPath";\r
+static const TCHAR *kTempRemovableOnly = TEXT("TempRemovableOnly");\r
+\r
+\r
+void CInfo::Save()const\r
+{\r
+  CS_LOCK\r
+  CKey key;\r
+  CreateMainKey(key, kOptionsInfoKeyName);\r
+  key.SetValue(kWorkDirType, (UInt32)Mode);\r
+  key.SetValue(kWorkDirPath, Path);\r
+  key.SetValue(kTempRemovableOnly, ForRemovableOnly);\r
+}\r
+\r
+void CInfo::Load()\r
+{\r
+  SetDefault();\r
+\r
+  CS_LOCK\r
+  CKey key;\r
+  if (OpenMainKey(key, kOptionsInfoKeyName) != ERROR_SUCCESS)\r
+    return;\r
+\r
+  UInt32 dirType;\r
+  if (key.QueryValue(kWorkDirType, dirType) != ERROR_SUCCESS)\r
+    return;\r
+  switch (dirType)\r
+  {\r
+    case NMode::kSystem:\r
+    case NMode::kCurrent:\r
+    case NMode::kSpecified:\r
+      Mode = (NMode::EEnum)dirType;\r
+  }\r
+  if (key.QueryValue(kWorkDirPath, Path) != ERROR_SUCCESS)\r
+  {\r
+    Path.Empty();\r
+    if (Mode == NMode::kSpecified)\r
+      Mode = NMode::kSystem;\r
+  }\r
+  key.GetValue_IfOk(kTempRemovableOnly, ForRemovableOnly);\r
+}\r
+\r
+}\r
+\r
+static const TCHAR *kCascadedMenu = TEXT("CascadedMenu");\r
+static const TCHAR *kContextMenu = TEXT("ContextMenu");\r
+\r
+void CContextMenuInfo::Save() const\r
+{\r
+  CS_LOCK\r
+  CKey key;\r
+  CreateMainKey(key, kOptionsInfoKeyName);\r
+  key.SetValue(kCascadedMenu, Cascaded);\r
+  key.SetValue(kContextMenu, Flags);\r
+}\r
+\r
+void CContextMenuInfo::Load()\r
+{\r
+  Cascaded = true;\r
+  Flags = (UInt32)-1;\r
+  CS_LOCK\r
+  CKey key;\r
+  if (OpenMainKey(key, kOptionsInfoKeyName) != ERROR_SUCCESS)\r
+    return;\r
+  key.GetValue_IfOk(kCascadedMenu, Cascaded);\r
+  key.GetValue_IfOk(kContextMenu, Flags);\r
+}\r
diff --git a/CPP/7zip/UI/Common/ZipRegistry.h b/CPP/7zip/UI/Common/ZipRegistry.h
new file mode 100755 (executable)
index 0000000..1760d9b
--- /dev/null
@@ -0,0 +1,105 @@
+// ZipRegistry.h\r
+\r
+#ifndef __ZIP_REGISTRY_H\r
+#define __ZIP_REGISTRY_H\r
+\r
+#include "Common/MyString.h"\r
+#include "Common/Types.h"\r
+\r
+#include "ExtractMode.h"\r
+\r
+namespace NExtract\r
+{\r
+  struct CInfo\r
+  {\r
+    NPathMode::EEnum PathMode;\r
+    NOverwriteMode::EEnum OverwriteMode;\r
+    bool ShowPassword;\r
+    UStringVector Paths;\r
+\r
+    void Save() const;\r
+    void Load();\r
+  };\r
+}\r
+\r
+namespace NCompression\r
+{\r
+  struct CFormatOptions\r
+  {\r
+    UInt32 Level;\r
+    UInt32 Dictionary;\r
+    UInt32 Order;\r
+    UInt32 BlockLogSize;\r
+    UInt32 NumThreads;\r
+    \r
+    CSysString FormatID;\r
+    UString Method;\r
+    UString Options;\r
+    UString EncryptionMethod;\r
+\r
+    void ResetForLevelChange()\r
+    {\r
+      BlockLogSize = NumThreads = Level = Dictionary = Order = UInt32(-1);\r
+      Method.Empty();\r
+      // Options.Empty();\r
+      // EncryptionMethod.Empty();\r
+    }\r
+    CFormatOptions() { ResetForLevelChange(); }\r
+  };\r
+\r
+  struct CInfo\r
+  {\r
+    UInt32 Level;\r
+    bool ShowPassword;\r
+    bool EncryptHeaders;\r
+    UString ArcType;\r
+    UStringVector ArcPaths;\r
+\r
+    CObjectVector<CFormatOptions> Formats;\r
+\r
+    void Save() const;\r
+    void Load();\r
+  };\r
+}\r
+\r
+namespace NWorkDir\r
+{\r
+  namespace NMode\r
+  {\r
+    enum EEnum\r
+    {\r
+      kSystem,\r
+      kCurrent,\r
+      kSpecified\r
+    };\r
+  }\r
+  struct CInfo\r
+  {\r
+    NMode::EEnum Mode;\r
+    UString Path;\r
+    bool ForRemovableOnly;\r
+\r
+    void SetForRemovableOnlyDefault() { ForRemovableOnly = true; }\r
+    void SetDefault()\r
+    {\r
+      Mode = NMode::kSystem;\r
+      Path.Empty();\r
+      SetForRemovableOnlyDefault();\r
+    }\r
+\r
+    void Save() const;\r
+    void Load();\r
+  };\r
+}\r
+\r
+\r
+struct CContextMenuInfo\r
+{\r
+  bool Cascaded;\r
+  UInt32 Flags;\r
+\r
+  void Save() const;\r
+  void Load();\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Console/BenchCon.cpp b/CPP/7zip/UI/Console/BenchCon.cpp
new file mode 100755 (executable)
index 0000000..a31d8e0
--- /dev/null
@@ -0,0 +1,297 @@
+// BenchCon.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../Common/IntToString.h"\r
+#include "../../../Common/MyCom.h"\r
+\r
+#if !defined(_7ZIP_ST) || defined(_WIN32)\r
+#include "../../../Windows/System.h"\r
+#endif\r
+\r
+#include "../Common/Bench.h"\r
+\r
+#include "BenchCon.h"\r
+#include "ConsoleClose.h"\r
+\r
+struct CTotalBenchRes\r
+{\r
+  UInt64 NumIterations;\r
+  UInt64 Rating;\r
+  UInt64 Usage;\r
+  UInt64 RPU;\r
+  void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; }\r
+  void Normalize()\r
+  {\r
+    if (NumIterations == 0)\r
+      return;\r
+    Rating /= NumIterations;\r
+    Usage /= NumIterations;\r
+    RPU /= NumIterations;\r
+    NumIterations = 1;\r
+  }\r
+  void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2)\r
+  {\r
+    Rating = (r1.Rating + r2.Rating) / 2;\r
+    Usage = (r1.Usage + r2.Usage) / 2;\r
+    RPU = (r1.RPU + r2.RPU) / 2;\r
+    NumIterations = (r1.NumIterations + r2.NumIterations) / 2;\r
+  }\r
+};\r
+\r
+struct CBenchCallback: public IBenchCallback\r
+{\r
+  CTotalBenchRes EncodeRes;\r
+  CTotalBenchRes DecodeRes;\r
+  FILE *f;\r
+  void Init() { EncodeRes.Init(); DecodeRes.Init(); }\r
+  void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); }\r
+  UInt32 dictionarySize;\r
+  HRESULT SetEncodeResult(const CBenchInfo &info, bool final);\r
+  HRESULT SetDecodeResult(const CBenchInfo &info, bool final);\r
+};\r
+\r
+static void NormalizeVals(UInt64 &v1, UInt64 &v2)\r
+{\r
+  while (v1 > 1000000)\r
+  {\r
+    v1 >>= 1;\r
+    v2 >>= 1;\r
+  }\r
+}\r
+\r
+static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq)\r
+{\r
+  UInt64 elTime = elapsedTime;\r
+  NormalizeVals(freq, elTime);\r
+  if (elTime == 0)\r
+    elTime = 1;\r
+  return value * freq / elTime;\r
+}\r
+\r
+static void PrintNumber(FILE *f, UInt64 value, int size)\r
+{\r
+  char s[32];\r
+  ConvertUInt64ToString(value, s);\r
+  fprintf(f, " ");\r
+  for (int len = (int)strlen(s); len < size; len++)\r
+    fprintf(f, " ");\r
+  fputs(s, f);\r
+}\r
+\r
+static void PrintRating(FILE *f, UInt64 rating)\r
+{\r
+  PrintNumber(f, rating / 1000000, 6);\r
+}\r
+\r
+static void PrintResults(FILE *f, UInt64 usage, UInt64 rpu, UInt64 rating)\r
+{\r
+  PrintNumber(f, (usage + 5000) / 10000, 5);\r
+  PrintRating(f, rpu);\r
+  PrintRating(f, rating);\r
+}\r
+\r
+\r
+static void PrintResults(FILE *f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res)\r
+{\r
+  UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq);\r
+  PrintNumber(f, speed / 1024, 7);\r
+  UInt64 usage = GetUsage(info);\r
+  UInt64 rpu = GetRatingPerUsage(info, rating);\r
+  PrintResults(f, usage, rpu, rating);\r
+  res.NumIterations++;\r
+  res.RPU += rpu;\r
+  res.Rating += rating;\r
+  res.Usage += usage;\r
+}\r
+\r
+static void PrintTotals(FILE *f, const CTotalBenchRes &res)\r
+{\r
+  fprintf(f, "       ");\r
+  PrintResults(f, res.Usage, res.RPU, res.Rating);\r
+}\r
+\r
+\r
+HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final)\r
+{\r
+  if (NConsoleClose::TestBreakSignal())\r
+    return E_ABORT;\r
+  if (final)\r
+  {\r
+    UInt64 rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, info.UnpackSize);\r
+    PrintResults(f, info, rating, EncodeRes);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+static const char *kSep = "  | ";\r
+\r
+\r
+HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final)\r
+{\r
+  if (NConsoleClose::TestBreakSignal())\r
+    return E_ABORT;\r
+  if (final)\r
+  {\r
+    UInt64 rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations);\r
+    fputs(kSep, f);\r
+    CBenchInfo info2 = info;\r
+    info2.UnpackSize *= info2.NumIterations;\r
+    info2.PackSize *= info2.NumIterations;\r
+    info2.NumIterations = 1;\r
+    PrintResults(f, info2, rating, DecodeRes);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+static void PrintRequirements(FILE *f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads)\r
+{\r
+  fprintf(f, "\nRAM %s ", sizeString);\r
+  PrintNumber(f, (size >> 20), 5);\r
+  fprintf(f, " MB,  # %s %3d", threadsString, (unsigned int)numThreads);\r
+}\r
+\r
+HRESULT LzmaBenchCon(\r
+  DECL_EXTERNAL_CODECS_LOC_VARS\r
+  FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary)\r
+{\r
+  if (!CrcInternalTest())\r
+    return S_FALSE;\r
+  #ifndef _7ZIP_ST\r
+  UInt64 ramSize = NWindows::NSystem::GetRamSize();  //\r
+  UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();\r
+  PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs);\r
+  if (numThreads == (UInt32)-1)\r
+    numThreads = numCPUs;\r
+  if (numThreads > 1)\r
+    numThreads &= ~1;\r
+  if (dictionary == (UInt32)-1)\r
+  {\r
+    int dicSizeLog;\r
+    for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--)\r
+      if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize)\r
+        break;\r
+    dictionary = (1 << dicSizeLog);\r
+  }\r
+  #else\r
+  if (dictionary == (UInt32)-1)\r
+    dictionary = (1 << 22);\r
+  numThreads = 1;\r
+  #endif\r
+\r
+  PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dictionary), "Benchmark threads:   ", numThreads);\r
+\r
+  CBenchCallback callback;\r
+  callback.Init();\r
+  callback.f = f;\r
+  \r
+  fprintf(f, "\n\nDict        Compressing          |        Decompressing\n   ");\r
+  int j;\r
+  for (j = 0; j < 2; j++)\r
+  {\r
+    fprintf(f, "   Speed Usage    R/U Rating");\r
+    if (j == 0)\r
+      fputs(kSep, f);\r
+  }\r
+  fprintf(f, "\n   ");\r
+  for (j = 0; j < 2; j++)\r
+  {\r
+    fprintf(f, "    KB/s     %%   MIPS   MIPS");\r
+    if (j == 0)\r
+      fputs(kSep, f);\r
+  }\r
+  fprintf(f, "\n\n");\r
+  for (UInt32 i = 0; i < numIterations; i++)\r
+  {\r
+    const int kStartDicLog = 22;\r
+    int pow = (dictionary < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog;\r
+    while (((UInt32)1 << pow) > dictionary)\r
+      pow--;\r
+    for (; ((UInt32)1 << pow) <= dictionary; pow++)\r
+    {\r
+      fprintf(f, "%2d:", pow);\r
+      callback.dictionarySize = (UInt32)1 << pow;\r
+      HRESULT res = LzmaBench(\r
+        EXTERNAL_CODECS_LOC_VARS\r
+        numThreads, callback.dictionarySize, &callback);\r
+      fprintf(f, "\n");\r
+      RINOK(res);\r
+    }\r
+  }\r
+  callback.Normalize();\r
+  fprintf(f, "----------------------------------------------------------------\nAvr:");\r
+  PrintTotals(f, callback.EncodeRes);\r
+  fprintf(f, "     ");\r
+  PrintTotals(f, callback.DecodeRes);\r
+  fprintf(f, "\nTot:");\r
+  CTotalBenchRes midRes;\r
+  midRes.SetMid(callback.EncodeRes, callback.DecodeRes);\r
+  PrintTotals(f, midRes);\r
+  fprintf(f, "\n");\r
+  return S_OK;\r
+}\r
+\r
+struct CTempValues\r
+{\r
+  UInt64 *Values;\r
+  CTempValues(UInt32 num) { Values = new UInt64[num]; }\r
+  ~CTempValues() { delete []Values; }\r
+};\r
+\r
+HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary)\r
+{\r
+  if (!CrcInternalTest())\r
+    return S_FALSE;\r
+\r
+  #ifndef _7ZIP_ST\r
+  UInt64 ramSize = NWindows::NSystem::GetRamSize();\r
+  UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();\r
+  PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs);\r
+  if (numThreads == (UInt32)-1)\r
+    numThreads = numCPUs;\r
+  #else\r
+  numThreads = 1;\r
+  #endif\r
+  if (dictionary == (UInt32)-1)\r
+    dictionary = (1 << 24);\r
+\r
+  CTempValues speedTotals(numThreads);\r
+  fprintf(f, "\n\nSize");\r
+  for (UInt32 ti = 0; ti < numThreads; ti++)\r
+  {\r
+    fprintf(f, " %5d", ti + 1);\r
+    speedTotals.Values[ti] = 0;\r
+  }\r
+  fprintf(f, "\n\n");\r
+\r
+  UInt64 numSteps = 0;\r
+  for (UInt32 i = 0; i < numIterations; i++)\r
+  {\r
+    for (int pow = 10; pow < 32; pow++)\r
+    {\r
+      UInt32 bufSize = (UInt32)1 << pow;\r
+      if (bufSize > dictionary)\r
+        break;\r
+      fprintf(f, "%2d: ", pow);\r
+      UInt64 speed;\r
+      for (UInt32 ti = 0; ti < numThreads; ti++)\r
+      {\r
+        if (NConsoleClose::TestBreakSignal())\r
+          return E_ABORT;\r
+        RINOK(CrcBench(ti + 1, bufSize, speed));\r
+        PrintNumber(f, (speed >> 20), 5);\r
+        speedTotals.Values[ti] += speed;\r
+      }\r
+      fprintf(f, "\n");\r
+      numSteps++;\r
+    }\r
+  }\r
+  if (numSteps != 0)\r
+  {\r
+    fprintf(f, "\nAvg:");\r
+    for (UInt32 ti = 0; ti < numThreads; ti++)\r
+      PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5);\r
+    fprintf(f, "\n");\r
+  }\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/UI/Console/BenchCon.h b/CPP/7zip/UI/Console/BenchCon.h
new file mode 100755 (executable)
index 0000000..c5eafbf
--- /dev/null
@@ -0,0 +1,16 @@
+// BenchCon.h\r
+\r
+#ifndef __BENCH_CON_H\r
+#define __BENCH_CON_H\r
+\r
+#include <stdio.h>\r
+\r
+#include "../../Common/CreateCoder.h"\r
+\r
+HRESULT LzmaBenchCon(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary);\r
+\r
+HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Console/Console.dsp b/CPP/7zip/UI/Console/Console.dsp
new file mode 100755 (executable)
index 0000000..f58accd
--- /dev/null
@@ -0,0 +1,845 @@
+# Microsoft Developer Studio Project File - Name="Console" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=Console - Win32 DebugU\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "Console.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "Console.mak" CFG="Console - Win32 DebugU"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "Console - Win32 Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "Console - Win32 Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "Console - Win32 ReleaseU" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "Console - Win32 DebugU" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "Console - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
+# 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\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# 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\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "Console - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
+# 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\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x419 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# 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\r
+\r
+!ELSEIF  "$(CFG)" == "Console - Win32 ReleaseU"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Console___Win32_ReleaseU"\r
+# PROP BASE Intermediate_Dir "Console___Win32_ReleaseU"\r
+# PROP BASE Ignore_Export_Lib 0\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "ReleaseU"\r
+# PROP Intermediate_Dir "ReleaseU"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /Gz /MD /W3 /GX /O1 /I "../../../" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /c\r
+# 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\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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"\r
+# 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\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "Console - Win32 DebugU"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Console___Win32_DebugU"\r
+# PROP BASE Intermediate_Dir "Console___Win32_DebugU"\r
+# PROP BASE Ignore_Export_Lib 0\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "DebugU"\r
+# PROP Intermediate_Dir "DebugU"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# 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\r
+# 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\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x419 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# 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\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "Console - Win32 Release"\r
+# Name "Console - Win32 Debug"\r
+# Name "Console - Win32 ReleaseU"\r
+# Name "Console - Win32 DebugU"\r
+# Begin Group "Spec"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\resource.rc\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.cpp\r
+# ADD CPP /Yc"StdAfx.h"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Console"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\BenchCon.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\BenchCon.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ConsoleClose.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ConsoleClose.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ExtractCallbackConsole.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ExtractCallbackConsole.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\List.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\List.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Main.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\MainAr.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\OpenCallbackConsole.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\OpenCallbackConsole.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PercentPrinter.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PercentPrinter.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\UpdateCallbackConsole.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\UpdateCallbackConsole.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\UserInputUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\UserInputUtils.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Windows"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\MemoryLock.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\MemoryLock.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\NtCheck.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantConversions.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantConversions.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Registry.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Registry.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\System.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\System.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Time.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Time.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Buffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CommandLineParser.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CommandLineParser.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\ComTry.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Defs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\ListFileUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\ListFileUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyCom.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StdInStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StdInStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StdOutStream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StdOutStream.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringToInt.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringToInt.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\UTFConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\UTFConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "UI Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveCommandLine.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveCommandLine.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveExtractCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveExtractCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveOpenCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveOpenCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\Bench.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\Bench.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\DefaultName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\DefaultName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\DirItem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\EnumDirItems.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\EnumDirItems.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ExitCode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\Extract.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\Extract.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ExtractingFilePath.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ExtractingFilePath.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\IFileExtractCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\LoadCodecs.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\LoadCodecs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\OpenArchive.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\OpenArchive.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\Property.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\PropIDUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\PropIDUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\SetProperties.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\SetProperties.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\SortUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\SortUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\TempFiles.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\TempFiles.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\Update.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\Update.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateAction.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateAction.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdatePair.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdatePair.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateProduce.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateProduce.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\WorkDir.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\WorkDir.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ZipRegistry.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "7-zip Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilePathAutoRename.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilePathAutoRename.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\RegisterArc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Compress"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyCoder.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "C"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.c\r
+\r
+!IF  "$(CFG)" == "Console - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Console - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Console - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "Console - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "ArchiveCommon"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Asm"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\Asm\x86\7zAsm.asm\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\Asm\x86\7zCrcOpt.asm\r
+\r
+!IF  "$(CFG)" == "Console - Win32 Release"\r
+\r
+# Begin Custom Build\r
+OutDir=.\Release\r
+InputPath=..\..\..\..\Asm\x86\7zCrcOpt.asm\r
+InputName=7zCrcOpt\r
+\r
+"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+       ml.exe -c -Fo$(OutDir)\$(InputName).obj $(InputPath)\r
+\r
+# End Custom Build\r
+\r
+!ELSEIF  "$(CFG)" == "Console - Win32 Debug"\r
+\r
+# Begin Custom Build\r
+OutDir=.\Debug\r
+InputPath=..\..\..\..\Asm\x86\7zCrcOpt.asm\r
+InputName=7zCrcOpt\r
+\r
+"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+       ml.exe -c -omf -Fo$(OutDir)\$(InputName).obj $(InputPath)\r
+\r
+# End Custom Build\r
+\r
+!ELSEIF  "$(CFG)" == "Console - Win32 ReleaseU"\r
+\r
+# Begin Custom Build\r
+OutDir=.\ReleaseU\r
+InputPath=..\..\..\..\Asm\x86\7zCrcOpt.asm\r
+InputName=7zCrcOpt\r
+\r
+"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+       ml.exe -c -Fo$(OutDir)\$(InputName).obj $(InputPath)\r
+\r
+# End Custom Build\r
+\r
+!ELSEIF  "$(CFG)" == "Console - Win32 DebugU"\r
+\r
+# Begin Custom Build\r
+OutDir=.\DebugU\r
+InputPath=..\..\..\..\Asm\x86\7zCrcOpt.asm\r
+InputName=7zCrcOpt\r
+\r
+"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+       ml.exe -c -omf -Fo$(OutDir)\$(InputName).obj $(InputPath)\r
+\r
+# End Custom Build\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/CPP/7zip/UI/Console/Console.dsw b/CPP/7zip/UI/Console/Console.dsw
new file mode 100755 (executable)
index 0000000..6e37f11
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "Console"=".\Console.dsp" - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/CPP/7zip/UI/Console/ConsoleClose.cpp b/CPP/7zip/UI/Console/ConsoleClose.cpp
new file mode 100755 (executable)
index 0000000..9fbad17
--- /dev/null
@@ -0,0 +1,73 @@
+// ConsoleClose.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "ConsoleClose.h"\r
+\r
+static int g_BreakCounter = 0;\r
+static const int kBreakAbortThreshold = 2;\r
+\r
+namespace NConsoleClose {\r
+\r
+#if !defined(UNDER_CE) && defined(_WIN32)\r
+static BOOL WINAPI HandlerRoutine(DWORD ctrlType)\r
+{\r
+  if (ctrlType == CTRL_LOGOFF_EVENT)\r
+  {\r
+    // printf("\nCTRL_LOGOFF_EVENT\n");\r
+    return TRUE;\r
+  }\r
+\r
+  g_BreakCounter++;\r
+  if (g_BreakCounter < kBreakAbortThreshold)\r
+    return TRUE;\r
+  return FALSE;\r
+  /*\r
+  switch(ctrlType)\r
+  {\r
+    case CTRL_C_EVENT:\r
+    case CTRL_BREAK_EVENT:\r
+      if (g_BreakCounter < kBreakAbortThreshold)\r
+      return TRUE;\r
+  }\r
+  return FALSE;\r
+  */\r
+}\r
+#endif\r
+\r
+bool TestBreakSignal()\r
+{\r
+  #ifdef UNDER_CE\r
+  return false;\r
+  #else\r
+  /*\r
+  if (g_BreakCounter > 0)\r
+    return true;\r
+  */\r
+  return (g_BreakCounter > 0);\r
+  #endif\r
+}\r
+\r
+void CheckCtrlBreak()\r
+{\r
+  if (TestBreakSignal())\r
+    throw CCtrlBreakException();\r
+}\r
+\r
+CCtrlHandlerSetter::CCtrlHandlerSetter()\r
+{\r
+  #if !defined(UNDER_CE) && defined(_WIN32)\r
+  if(!SetConsoleCtrlHandler(HandlerRoutine, TRUE))\r
+    throw "SetConsoleCtrlHandler fails";\r
+  #endif\r
+}\r
+\r
+CCtrlHandlerSetter::~CCtrlHandlerSetter()\r
+{\r
+  #if !defined(UNDER_CE) && defined(_WIN32)\r
+  if(!SetConsoleCtrlHandler(HandlerRoutine, FALSE))\r
+    throw "SetConsoleCtrlHandler fails";\r
+  #endif\r
+}\r
+\r
+}\r
diff --git a/CPP/7zip/UI/Console/ConsoleClose.h b/CPP/7zip/UI/Console/ConsoleClose.h
new file mode 100755 (executable)
index 0000000..7101018
--- /dev/null
@@ -0,0 +1,24 @@
+// ConsoleCloseUtils.h\r
+\r
+#ifndef __CONSOLECLOSEUTILS_H\r
+#define __CONSOLECLOSEUTILS_H\r
+\r
+namespace NConsoleClose {\r
+\r
+bool TestBreakSignal();\r
+\r
+class CCtrlHandlerSetter\r
+{\r
+public:\r
+  CCtrlHandlerSetter();\r
+  virtual ~CCtrlHandlerSetter();\r
+};\r
+\r
+class CCtrlBreakException\r
+{};\r
+\r
+void CheckCtrlBreak();\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
new file mode 100755 (executable)
index 0000000..278b069
--- /dev/null
@@ -0,0 +1,228 @@
+// ExtractCallbackConsole.h\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "ExtractCallbackConsole.h"\r
+#include "UserInputUtils.h"\r
+#include "ConsoleClose.h"\r
+\r
+#include "Common/Wildcard.h"\r
+\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileFind.h"\r
+#include "Windows/Time.h"\r
+#include "Windows/Defs.h"\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Error.h"\r
+#include "Windows/PropVariantConversions.h"\r
+\r
+#include "../../Common/FilePathAutoRename.h"\r
+\r
+#include "../Common/ExtractingFilePath.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+using namespace NDirectory;\r
+\r
+static const char *kTestString    =  "Testing     ";\r
+static const char *kExtractString =  "Extracting  ";\r
+static const char *kSkipString   =  "Skipping    ";\r
+\r
+// static const char *kCantAutoRename = "can not create file with auto name\n";\r
+// static const char *kCantRenameFile = "can not rename existing file\n";\r
+// static const char *kCantDeleteOutputFile = "can not delete output file ";\r
+static const char *kError = "ERROR: ";\r
+static const char *kMemoryExceptionMessage = "Can't allocate required memory!";\r
+\r
+static const char *kProcessing = "Processing archive: ";\r
+static const char *kEverythingIsOk = "Everything is Ok";\r
+static const char *kNoFiles = "No files to process";\r
+\r
+static const char *kUnsupportedMethod = "Unsupported Method";\r
+static const char *kCrcFailed = "CRC Failed";\r
+static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?";\r
+static const char *kDataError = "Data Error";\r
+static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?";\r
+static const char *kUnknownError = "Unknown Error";\r
+\r
+STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64)\r
+{\r
+  if (NConsoleClose::TestBreakSignal())\r
+    return E_ABORT;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *)\r
+{\r
+  if (NConsoleClose::TestBreakSignal())\r
+    return E_ABORT;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtractCallbackConsole::AskOverwrite(\r
+    const wchar_t *existName, const FILETIME *, const UInt64 *,\r
+    const wchar_t *newName, const FILETIME *, const UInt64 *,\r
+    Int32 *answer)\r
+{\r
+  (*OutStream) << "file " << existName <<\r
+    "\nalready exists. Overwrite with " << endl;\r
+  (*OutStream) << newName;\r
+  \r
+  NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream);\r
+  \r
+  switch(overwriteAnswer)\r
+  {\r
+    case NUserAnswerMode::kQuit:  return E_ABORT;\r
+    case NUserAnswerMode::kNo:     *answer = NOverwriteAnswer::kNo; break;\r
+    case NUserAnswerMode::kNoAll:  *answer = NOverwriteAnswer::kNoToAll; break;\r
+    case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break;\r
+    case NUserAnswerMode::kYes:    *answer = NOverwriteAnswer::kYes; break;\r
+    case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break;\r
+    default: return E_FAIL;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position)\r
+{\r
+  switch (askExtractMode)\r
+  {\r
+    case NArchive::NExtract::NAskMode::kExtract: (*OutStream) << kExtractString; break;\r
+    case NArchive::NExtract::NAskMode::kTest:    (*OutStream) << kTestString; break;\r
+    case NArchive::NExtract::NAskMode::kSkip:    (*OutStream) << kSkipString; break;\r
+  };\r
+  (*OutStream) << name;\r
+  if (position != 0)\r
+    (*OutStream) << " <" << *position << ">";\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message)\r
+{\r
+  (*OutStream) << message << endl;\r
+  NumFileErrorsInCurrentArchive++;\r
+  NumFileErrors++;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted)\r
+{\r
+  switch(operationResult)\r
+  {\r
+    case NArchive::NExtract::NOperationResult::kOK:\r
+      break;\r
+    default:\r
+    {\r
+      NumFileErrorsInCurrentArchive++;\r
+      NumFileErrors++;\r
+      (*OutStream) << "     ";\r
+      switch(operationResult)\r
+      {\r
+        case NArchive::NExtract::NOperationResult::kUnSupportedMethod:\r
+          (*OutStream) << kUnsupportedMethod;\r
+          break;\r
+        case NArchive::NExtract::NOperationResult::kCRCError:\r
+          (*OutStream) << (encrypted ? kCrcFailedEncrypted: kCrcFailed);\r
+          break;\r
+        case NArchive::NExtract::NOperationResult::kDataError:\r
+          (*OutStream) << (encrypted ? kDataErrorEncrypted : kDataError);\r
+          break;\r
+        default:\r
+          (*OutStream) << kUnknownError;\r
+      }\r
+    }\r
+  }\r
+  (*OutStream) << endl;\r
+  return S_OK;\r
+}\r
+\r
+#ifndef _NO_CRYPTO\r
+\r
+HRESULT CExtractCallbackConsole::SetPassword(const UString &password)\r
+{\r
+  PasswordIsDefined = true;\r
+  Password = password;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password)\r
+{\r
+  if (!PasswordIsDefined)\r
+  {\r
+    Password = GetPassword(OutStream);\r
+    PasswordIsDefined = true;\r
+  }\r
+  return StringToBstr(Password, password);\r
+}\r
+\r
+#endif\r
+\r
+HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name)\r
+{\r
+  NumArchives++;\r
+  NumFileErrorsInCurrentArchive = 0;\r
+  (*OutStream) << endl << kProcessing << name << endl;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted)\r
+{\r
+  (*OutStream) << endl;\r
+  if (result != S_OK)\r
+  {\r
+    (*OutStream) << "Error: ";\r
+    if (result == S_FALSE)\r
+    {\r
+      (*OutStream) << (encrypted ?\r
+        "Can not open encrypted archive. Wrong password?" :\r
+        "Can not open file as archive");\r
+    }\r
+    else\r
+    {\r
+      if (result == E_OUTOFMEMORY)\r
+        (*OutStream) << "Can't allocate required memory";\r
+      else\r
+        (*OutStream) << NError::MyFormatMessage(result);\r
+    }\r
+    (*OutStream) << endl;\r
+    NumArchiveErrors++;\r
+  }\r
+  return S_OK;\r
+}\r
+  \r
+HRESULT CExtractCallbackConsole::ThereAreNoFiles()\r
+{\r
+  (*OutStream) << endl << kNoFiles << endl;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result)\r
+{\r
+  if (result == S_OK)\r
+  {\r
+    (*OutStream) << endl;\r
+    if (NumFileErrorsInCurrentArchive == 0)\r
+      (*OutStream) << kEverythingIsOk << endl;\r
+    else\r
+    {\r
+      NumArchiveErrors++;\r
+      (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrentArchive << endl;\r
+    }\r
+  }\r
+  if (result == S_OK)\r
+    return result;\r
+  NumArchiveErrors++;\r
+  if (result == E_ABORT || result == ERROR_DISK_FULL)\r
+    return result;\r
+  (*OutStream) << endl << kError;\r
+  if (result == E_OUTOFMEMORY)\r
+    (*OutStream) << kMemoryExceptionMessage;\r
+  else\r
+  {\r
+    UString message;\r
+    NError::MyFormatMessage(result, message);\r
+    (*OutStream) << message;\r
+  }\r
+  (*OutStream) << endl;\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.h b/CPP/7zip/UI/Console/ExtractCallbackConsole.h
new file mode 100755 (executable)
index 0000000..7086527
--- /dev/null
@@ -0,0 +1,73 @@
+// ExtractCallbackConsole.h\r
+\r
+#ifndef __EXTRACTCALLBACKCONSOLE_H\r
+#define __EXTRACTCALLBACKCONSOLE_H\r
+\r
+#include "Common/MyString.h"\r
+#include "Common/StdOutStream.h"\r
+#include "../../Common/FileStreams.h"\r
+#include "../../IPassword.h"\r
+#include "../../Archive/IArchive.h"\r
+#include "../Common/ArchiveExtractCallback.h"\r
+\r
+class CExtractCallbackConsole:\r
+  public IExtractCallbackUI,\r
+  #ifndef _NO_CRYPTO\r
+  public ICryptoGetTextPassword,\r
+  #endif\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback)\r
+  #ifndef _NO_CRYPTO\r
+  MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)\r
+  #endif\r
+  MY_QUERYINTERFACE_END\r
+  MY_ADDREF_RELEASE\r
+\r
+  STDMETHOD(SetTotal)(UInt64 total);\r
+  STDMETHOD(SetCompleted)(const UInt64 *completeValue);\r
+\r
+  // IFolderArchiveExtractCallback\r
+  STDMETHOD(AskOverwrite)(\r
+      const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,\r
+      const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,\r
+      Int32 *answer);\r
+  STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position);\r
+\r
+  STDMETHOD(MessageError)(const wchar_t *message);\r
+  STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted);\r
+\r
+  HRESULT BeforeOpen(const wchar_t *name);\r
+  HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted);\r
+  HRESULT ThereAreNoFiles();\r
+  HRESULT ExtractResult(HRESULT result);\r
+\r
\r
+  #ifndef _NO_CRYPTO\r
+  HRESULT SetPassword(const UString &password);\r
+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);\r
+\r
+  bool PasswordIsDefined;\r
+  UString Password;\r
+\r
+  #endif\r
+  \r
+  UInt64 NumArchives;\r
+  UInt64 NumArchiveErrors;\r
+  UInt64 NumFileErrors;\r
+  UInt64 NumFileErrorsInCurrentArchive;\r
+\r
+  CStdOutStream *OutStream;\r
+\r
+  void Init()\r
+  {\r
+    NumArchives = 0;\r
+    NumArchiveErrors = 0;\r
+    NumFileErrors = 0;\r
+    NumFileErrorsInCurrentArchive = 0;\r
+  }\r
+\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp
new file mode 100755 (executable)
index 0000000..298adbd
--- /dev/null
@@ -0,0 +1,654 @@
+// List.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/MyCom.h"\r
+#include "Common/StdOutStream.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/Error.h"\r
+#include "Windows/FileDir.h"\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/PropVariantConversions.h"\r
+\r
+#include "../../Archive/IArchive.h"\r
+\r
+#include "../Common/OpenArchive.h"\r
+#include "../Common/PropIDUtils.h"\r
+\r
+#include "ConsoleClose.h"\r
+#include "List.h"\r
+#include "OpenCallbackConsole.h"\r
+\r
+using namespace NWindows;\r
+\r
+struct CPropIdToName\r
+{\r
+  PROPID PropID;\r
+  const wchar_t *Name;\r
+};\r
+\r
+static const CPropIdToName kPropIdToName[] =\r
+{\r
+  { kpidPath, L"Path" },\r
+  { kpidName, L"Name" },\r
+  { kpidIsDir, L"Folder" },\r
+  { kpidSize, L"Size" },\r
+  { kpidPackSize, L"Packed Size" },\r
+  { kpidAttrib, L"Attributes" },\r
+  { kpidCTime, L"Created" },\r
+  { kpidATime, L"Accessed" },\r
+  { kpidMTime, L"Modified" },\r
+  { kpidSolid, L"Solid" },\r
+  { kpidCommented, L"Commented" },\r
+  { kpidEncrypted, L"Encrypted" },\r
+  { kpidSplitBefore, L"Split Before" },\r
+  { kpidSplitAfter, L"Split After" },\r
+  { kpidDictionarySize, L"Dictionary Size" },\r
+  { kpidCRC, L"CRC" },\r
+  { kpidType, L"Type" },\r
+  { kpidIsAnti, L"Anti" },\r
+  { kpidMethod, L"Method" },\r
+  { kpidHostOS, L"Host OS" },\r
+  { kpidFileSystem, L"File System" },\r
+  { kpidUser, L"User" },\r
+  { kpidGroup, L"Group" },\r
+  { kpidBlock, L"Block" },\r
+  { kpidComment, L"Comment" },\r
+  { kpidPosition, L"Position" },\r
+  { kpidPrefix, L"Prefix" },\r
+  { kpidNumSubDirs, L"Folders" },\r
+  { kpidNumSubFiles, L"Files" },\r
+  { kpidUnpackVer, L"Version" },\r
+  { kpidVolume, L"Volume" },\r
+  { kpidIsVolume, L"Multivolume" },\r
+  { kpidOffset, L"Offset" },\r
+  { kpidLinks, L"Links" },\r
+  { kpidNumBlocks, L"Blocks" },\r
+  { kpidNumVolumes, L"Volumes" },\r
+\r
+  { kpidBit64, L"64-bit" },\r
+  { kpidBigEndian, L"Big-endian" },\r
+  { kpidCpu, L"CPU" },\r
+  { kpidPhySize, L"Physical Size" },\r
+  { kpidHeadersSize, L"Headers Size" },\r
+  { kpidChecksum, L"Checksum" },\r
+  { kpidCharacts, L"Characteristics" },\r
+  { kpidVa, L"Virtual Address" },\r
+  { kpidId, L"ID" },\r
+  { kpidShortName, L"Short Name" },\r
+  { kpidCreatorApp, L"Creator Application"},\r
+  { kpidSectorSize, L"Sector Size" },\r
+  { kpidPosixAttrib, L"Mode" },\r
+  { kpidLink, L"Link" },\r
+  { kpidError, L"Error" },\r
+\r
+  { kpidTotalSize, L"Total Size" },\r
+  { kpidFreeSpace, L"Free Space" },\r
+  { kpidClusterSize, L"Cluster Size" },\r
+  { kpidVolumeName, L"Label" }\r
+};\r
+\r
+static const char kEmptyAttribChar = '.';\r
+\r
+static const char *kListing = "Listing archive: ";\r
+static const wchar_t *kFilesMessage = L"files";\r
+static const wchar_t *kDirsMessage = L"folders";\r
+\r
+static void GetAttribString(DWORD wa, bool isDir, char *s)\r
+{\r
+  s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : kEmptyAttribChar;\r
+  s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar;\r
+  s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar;\r
+  s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar;\r
+  s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar;\r
+  s[5] = '\0';\r
+}\r
+\r
+enum EAdjustment\r
+{\r
+  kLeft,\r
+  kCenter,\r
+  kRight\r
+};\r
+\r
+struct CFieldInfo\r
+{\r
+  PROPID PropID;\r
+  UString Name;\r
+  EAdjustment TitleAdjustment;\r
+  EAdjustment TextAdjustment;\r
+  int PrefixSpacesWidth;\r
+  int Width;\r
+};\r
+\r
+struct CFieldInfoInit\r
+{\r
+  PROPID PropID;\r
+  const wchar_t *Name;\r
+  EAdjustment TitleAdjustment;\r
+  EAdjustment TextAdjustment;\r
+  int PrefixSpacesWidth;\r
+  int Width;\r
+};\r
+\r
+static CFieldInfoInit kStandardFieldTable[] =\r
+{\r
+  { kpidMTime, L"   Date      Time", kLeft, kLeft, 0, 19 },\r
+  { kpidAttrib, L"Attr", kRight, kCenter, 1, 5 },\r
+  { kpidSize, L"Size", kRight, kRight, 1, 12 },\r
+  { kpidPackSize, L"Compressed", kRight, kRight, 1, 12 },\r
+  { kpidPath, L"Name", kLeft, kLeft, 2, 24 }\r
+};\r
+\r
+static void PrintSpaces(int numSpaces)\r
+{\r
+  for (int i = 0; i < numSpaces; i++)\r
+    g_StdOut << ' ';\r
+}\r
+\r
+static void PrintString(EAdjustment adjustment, int width, const UString &textString)\r
+{\r
+  const int numSpaces = width - textString.Length();\r
+  int numLeftSpaces = 0;\r
+  switch (adjustment)\r
+  {\r
+    case kLeft:\r
+      numLeftSpaces = 0;\r
+      break;\r
+    case kCenter:\r
+      numLeftSpaces = numSpaces / 2;\r
+      break;\r
+    case kRight:\r
+      numLeftSpaces = numSpaces;\r
+      break;\r
+  }\r
+  PrintSpaces(numLeftSpaces);\r
+  g_StdOut << textString;\r
+  PrintSpaces(numSpaces - numLeftSpaces);\r
+}\r
+\r
+class CFieldPrinter\r
+{\r
+  CObjectVector<CFieldInfo> _fields;\r
+public:\r
+  void Clear() { _fields.Clear(); }\r
+  void Init(const CFieldInfoInit *standardFieldTable, int numItems);\r
+  HRESULT Init(IInArchive *archive);\r
+  void PrintTitle();\r
+  void PrintTitleLines();\r
+  HRESULT PrintItemInfo(const CArc &arc, UInt32 index, bool techMode);\r
+  HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs,\r
+      const UInt64 *size, const UInt64 *compressedSize);\r
+};\r
+\r
+void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems)\r
+{\r
+  Clear();\r
+  for (int i = 0; i < numItems; i++)\r
+  {\r
+    CFieldInfo fieldInfo;\r
+    const CFieldInfoInit &fieldInfoInit = standardFieldTable[i];\r
+    fieldInfo.PropID = fieldInfoInit.PropID;\r
+    fieldInfo.Name = fieldInfoInit.Name;\r
+    fieldInfo.TitleAdjustment = fieldInfoInit.TitleAdjustment;\r
+    fieldInfo.TextAdjustment = fieldInfoInit.TextAdjustment;\r
+    fieldInfo.PrefixSpacesWidth = fieldInfoInit.PrefixSpacesWidth;\r
+    fieldInfo.Width = fieldInfoInit.Width;\r
+    _fields.Add(fieldInfo);\r
+  }\r
+}\r
+\r
+static UString GetPropName(PROPID propID, BSTR name)\r
+{\r
+  for (int i = 0; i < sizeof(kPropIdToName) / sizeof(kPropIdToName[0]); i++)\r
+  {\r
+    const CPropIdToName &propIdToName = kPropIdToName[i];\r
+    if (propIdToName.PropID == propID)\r
+      return propIdToName.Name;\r
+  }\r
+  if (name)\r
+    return name;\r
+  wchar_t s[16];\r
+  ConvertUInt32ToString(propID, s);\r
+  return s;\r
+}\r
+\r
+HRESULT CFieldPrinter::Init(IInArchive *archive)\r
+{\r
+  Clear();\r
+  UInt32 numProps;\r
+  RINOK(archive->GetNumberOfProperties(&numProps));\r
+  for (UInt32 i = 0; i < numProps; i++)\r
+  {\r
+    CMyComBSTR name;\r
+    PROPID propID;\r
+    VARTYPE vt;\r
+    RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt));\r
+    CFieldInfo fieldInfo;\r
+    fieldInfo.PropID = propID;\r
+    fieldInfo.Name = GetPropName(propID, name);\r
+    _fields.Add(fieldInfo);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+void CFieldPrinter::PrintTitle()\r
+{\r
+  for (int i = 0; i < _fields.Size(); i++)\r
+  {\r
+    const CFieldInfo &fieldInfo = _fields[i];\r
+    PrintSpaces(fieldInfo.PrefixSpacesWidth);\r
+    PrintString(fieldInfo.TitleAdjustment,\r
+      ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name);\r
+  }\r
+}\r
+\r
+void CFieldPrinter::PrintTitleLines()\r
+{\r
+  for (int i = 0; i < _fields.Size(); i++)\r
+  {\r
+    const CFieldInfo &fieldInfo = _fields[i];\r
+    PrintSpaces(fieldInfo.PrefixSpacesWidth);\r
+    for (int i = 0; i < fieldInfo.Width; i++)\r
+      g_StdOut << '-';\r
+  }\r
+}\r
+\r
+\r
+static BOOL IsFileTimeZero(CONST FILETIME *lpFileTime)\r
+{\r
+  return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0);\r
+}\r
+\r
+static const char *kEmptyTimeString = "                   ";\r
+static void PrintTime(const NCOM::CPropVariant &prop)\r
+{\r
+  if (prop.vt != VT_FILETIME)\r
+    throw "incorrect item";\r
+  if (IsFileTimeZero(&prop.filetime))\r
+    g_StdOut << kEmptyTimeString;\r
+  else\r
+  {\r
+    FILETIME localFileTime;\r
+    if (!FileTimeToLocalFileTime(&prop.filetime, &localFileTime))\r
+      throw "FileTimeToLocalFileTime error";\r
+    char s[32];\r
+    if (ConvertFileTimeToString(localFileTime, s, true, true))\r
+      g_StdOut << s;\r
+    else\r
+      g_StdOut << kEmptyTimeString;\r
+  }\r
+}\r
+\r
+HRESULT CFieldPrinter::PrintItemInfo(const CArc &arc, UInt32 index, bool techMode)\r
+{\r
+  /*\r
+  if (techMode)\r
+  {\r
+    g_StdOut << "Index = ";\r
+    g_StdOut << (UInt64)index;\r
+    g_StdOut << endl;\r
+  }\r
+  */\r
+  for (int i = 0; i < _fields.Size(); i++)\r
+  {\r
+    const CFieldInfo &fieldInfo = _fields[i];\r
+    if (!techMode)\r
+      PrintSpaces(fieldInfo.PrefixSpacesWidth);\r
+\r
+    NCOM::CPropVariant prop;\r
+    if (fieldInfo.PropID == kpidPath)\r
+    {\r
+      UString s;\r
+      RINOK(arc.GetItemPath(index, s));\r
+      prop = s;\r
+    }\r
+    else\r
+    {\r
+      RINOK(arc.Archive->GetProperty(index, fieldInfo.PropID, &prop));\r
+    }\r
+    if (techMode)\r
+    {\r
+      g_StdOut << fieldInfo.Name << " = ";\r
+    }\r
+    int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width;\r
+    if (fieldInfo.PropID == kpidAttrib && (prop.vt == VT_EMPTY || prop.vt == VT_UI4))\r
+    {\r
+      UInt32 attrib = (prop.vt == VT_EMPTY) ? 0 : prop.ulVal;\r
+      bool isFolder;\r
+      RINOK(IsArchiveItemFolder(arc.Archive, index, isFolder));\r
+      char s[8];\r
+      GetAttribString(attrib, isFolder, s);\r
+      g_StdOut << s;\r
+    }\r
+    else if (prop.vt == VT_EMPTY)\r
+    {\r
+      if (!techMode)\r
+        PrintSpaces(width);\r
+    }\r
+    else if (fieldInfo.PropID == kpidMTime)\r
+    {\r
+      PrintTime(prop);\r
+    }\r
+    else if (prop.vt == VT_BSTR)\r
+    {\r
+      if (techMode)\r
+        g_StdOut << prop.bstrVal;\r
+      else\r
+        PrintString(fieldInfo.TextAdjustment, width, prop.bstrVal);\r
+    }\r
+    else\r
+    {\r
+      UString s = ConvertPropertyToString(prop, fieldInfo.PropID);\r
+      s.Replace(wchar_t(0xA), L' ');\r
+      s.Replace(wchar_t(0xD), L' ');\r
+\r
+      if (techMode)\r
+        g_StdOut << s;\r
+      else\r
+        PrintString(fieldInfo.TextAdjustment, width, s);\r
+    }\r
+    if (techMode)\r
+      g_StdOut << endl;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+static void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value)\r
+{\r
+  wchar_t textString[32] = { 0 };\r
+  if (value != NULL)\r
+    ConvertUInt64ToString(*value, textString);\r
+  PrintString(adjustment, width, textString);\r
+}\r
+\r
+\r
+HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs,\r
+    const UInt64 *size, const UInt64 *compressedSize)\r
+{\r
+  for (int i = 0; i < _fields.Size(); i++)\r
+  {\r
+    const CFieldInfo &fieldInfo = _fields[i];\r
+    PrintSpaces(fieldInfo.PrefixSpacesWidth);\r
+    NCOM::CPropVariant prop;\r
+    if (fieldInfo.PropID == kpidSize)\r
+      PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, size);\r
+    else if (fieldInfo.PropID == kpidPackSize)\r
+      PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, compressedSize);\r
+    else if (fieldInfo.PropID == kpidPath)\r
+    {\r
+      wchar_t textString[32];\r
+      ConvertUInt64ToString(numFiles, textString);\r
+      UString temp = textString;\r
+      temp += L" ";\r
+      temp += kFilesMessage;\r
+      temp += L", ";\r
+      ConvertUInt64ToString(numDirs, textString);\r
+      temp += textString;\r
+      temp += L" ";\r
+      temp += kDirsMessage;\r
+      PrintString(fieldInfo.TextAdjustment, 0, temp);\r
+    }\r
+    else\r
+      PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L"");\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  if (archive->GetProperty(index, propID, &prop) != S_OK)\r
+    throw "GetPropertyValue error";\r
+  if (prop.vt == VT_EMPTY)\r
+    return false;\r
+  value = ConvertPropVariantToUInt64(prop);\r
+  return true;\r
+}\r
+\r
+static void PrintPropPair(const wchar_t *name, const wchar_t *value)\r
+{\r
+  g_StdOut << name << " = " << value << endl;\r
+}\r
+\r
+HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices,\r
+    bool stdInMode,\r
+    UStringVector &arcPaths, UStringVector &arcPathsFull,\r
+    const NWildcard::CCensorNode &wildcardCensor,\r
+    bool enableHeaders, bool techMode,\r
+    #ifndef _NO_CRYPTO\r
+    bool &passwordEnabled, UString &password,\r
+    #endif\r
+    UInt64 &numErrors)\r
+{\r
+  numErrors = 0;\r
+  CFieldPrinter fieldPrinter;\r
+  if (!techMode)\r
+    fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0]));\r
+\r
+  UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0;\r
+  UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0;\r
+  int numArcs = /* stdInMode ? 1 : */ arcPaths.Size();\r
+  for (int i = 0; i < numArcs; i++)\r
+  {\r
+    const UString &archiveName = arcPaths[i];\r
+    UInt64 arcPackSize = 0;\r
+    if (!stdInMode)\r
+    {\r
+      NFile::NFind::CFileInfoW fi;\r
+      if (!fi.Find(archiveName) || fi.IsDir())\r
+      {\r
+        g_StdOut << endl << "Error: " << archiveName << " is not file" << endl;\r
+        numErrors++;\r
+        continue;\r
+      }\r
+      arcPackSize = fi.Size;\r
+    }\r
+\r
+    CArchiveLink archiveLink;\r
+\r
+    COpenCallbackConsole openCallback;\r
+    openCallback.OutStream = &g_StdOut;\r
+\r
+    #ifndef _NO_CRYPTO\r
+\r
+    openCallback.PasswordIsDefined = passwordEnabled;\r
+    openCallback.Password = password;\r
+\r
+    #endif\r
+\r
+    HRESULT result = archiveLink.Open2(codecs, formatIndices, stdInMode, NULL, archiveName, &openCallback);\r
+    if (result != S_OK)\r
+    {\r
+      if (result == E_ABORT)\r
+        return result;\r
+      g_StdOut << endl << "Error: " << archiveName << ": ";\r
+      if (result == S_FALSE)\r
+      {\r
+        #ifndef _NO_CRYPTO\r
+        if (openCallback.Open_WasPasswordAsked())\r
+          g_StdOut << "Can not open encrypted archive. Wrong password?";\r
+        else\r
+        #endif\r
+          g_StdOut << "Can not open file as archive";\r
+      }\r
+      else if (result == E_OUTOFMEMORY)\r
+        g_StdOut << "Can't allocate required memory";\r
+      else\r
+        g_StdOut << NError::MyFormatMessage(result);\r
+      g_StdOut << endl;\r
+      numErrors++;\r
+      continue;\r
+    }\r
+\r
+    if (!stdInMode)\r
+    for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)\r
+    {\r
+      int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]);\r
+      if (index >= 0 && index > i)\r
+      {\r
+        arcPaths.Delete(index);\r
+        arcPathsFull.Delete(index);\r
+        numArcs = arcPaths.Size();\r
+      }\r
+    }\r
+\r
+    if (enableHeaders)\r
+    {\r
+      g_StdOut << endl << kListing << archiveName << endl << endl;\r
+\r
+      for (int i = 0; i < archiveLink.Arcs.Size(); i++)\r
+      {\r
+        const CArc &arc = archiveLink.Arcs[i];\r
+        \r
+        g_StdOut << "--\n";\r
+        PrintPropPair(L"Path", arc.Path);\r
+        PrintPropPair(L"Type", codecs->Formats[arc.FormatIndex].Name);\r
+        if (!arc.ErrorMessage.IsEmpty())\r
+          PrintPropPair(L"Error", arc.ErrorMessage);\r
+        UInt32 numProps;\r
+        IInArchive *archive = arc.Archive;\r
+        if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK)\r
+        {\r
+          for (UInt32 j = 0; j < numProps; j++)\r
+          {\r
+            CMyComBSTR name;\r
+            PROPID propID;\r
+            VARTYPE vt;\r
+            RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt));\r
+            NCOM::CPropVariant prop;\r
+            RINOK(archive->GetArchiveProperty(propID, &prop));\r
+            UString s = ConvertPropertyToString(prop, propID);\r
+            if (!s.IsEmpty())\r
+              PrintPropPair(GetPropName(propID, name), s);\r
+          }\r
+        }\r
+        if (i != archiveLink.Arcs.Size() - 1)\r
+        {\r
+          UInt32 numProps;\r
+          g_StdOut << "----\n";\r
+          if (archive->GetNumberOfProperties(&numProps) == S_OK)\r
+          {\r
+            UInt32 mainIndex = archiveLink.Arcs[i + 1].SubfileIndex;\r
+            for (UInt32 j = 0; j < numProps; j++)\r
+            {\r
+              CMyComBSTR name;\r
+              PROPID propID;\r
+              VARTYPE vt;\r
+              RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt));\r
+              NCOM::CPropVariant prop;\r
+              RINOK(archive->GetProperty(mainIndex, propID, &prop));\r
+              UString s = ConvertPropertyToString(prop, propID);\r
+              if (!s.IsEmpty())\r
+                PrintPropPair(GetPropName(propID, name), s);\r
+            }\r
+          }\r
+        }\r
+        \r
+      }\r
+      g_StdOut << endl;\r
+      if (techMode)\r
+        g_StdOut << "----------\n";\r
+    }\r
+\r
+    if (enableHeaders && !techMode)\r
+    {\r
+      fieldPrinter.PrintTitle();\r
+      g_StdOut << endl;\r
+      fieldPrinter.PrintTitleLines();\r
+      g_StdOut << endl;\r
+    }\r
+\r
+    const CArc &arc = archiveLink.Arcs.Back();\r
+    IInArchive *archive = arc.Archive;\r
+    if (techMode)\r
+    {\r
+      RINOK(fieldPrinter.Init(archive));\r
+    }\r
+    UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0;\r
+    UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0;\r
+    UInt32 numItems;\r
+    RINOK(archive->GetNumberOfItems(&numItems));\r
+    for (UInt32 i = 0; i < numItems; i++)\r
+    {\r
+      if (NConsoleClose::TestBreakSignal())\r
+        return E_ABORT;\r
+\r
+      UString filePath;\r
+      HRESULT res = arc.GetItemPath(i, filePath);\r
+      if (stdInMode && res == E_INVALIDARG)\r
+        break;\r
+      RINOK(res);\r
+\r
+      bool isFolder;\r
+      RINOK(IsArchiveItemFolder(archive, i, isFolder));\r
+      if (!wildcardCensor.CheckPath(filePath, !isFolder))\r
+        continue;\r
+      \r
+      fieldPrinter.PrintItemInfo(arc, i, techMode);\r
+      \r
+      UInt64 packSize, unpackSize;\r
+      if (!GetUInt64Value(archive, i, kpidSize, unpackSize))\r
+        unpackSize = 0;\r
+      else\r
+        totalUnPackSizePointer = &totalUnPackSize;\r
+      if (!GetUInt64Value(archive, i, kpidPackSize, packSize))\r
+        packSize = 0;\r
+      else\r
+        totalPackSizePointer = &totalPackSize;\r
+      \r
+      g_StdOut << endl;\r
+\r
+      if (isFolder)\r
+        numDirs++;\r
+      else\r
+        numFiles++;\r
+      totalPackSize += packSize;\r
+      totalUnPackSize += unpackSize;\r
+    }\r
+\r
+    if (!stdInMode && totalPackSizePointer == 0)\r
+    {\r
+      if (archiveLink.VolumePaths.Size() != 0)\r
+        arcPackSize += archiveLink.VolumesSize;\r
+      totalPackSize = (numFiles == 0) ? 0 : arcPackSize;\r
+      totalPackSizePointer = &totalPackSize;\r
+    }\r
+    if (totalUnPackSizePointer == 0 && numFiles == 0)\r
+    {\r
+      totalUnPackSize = 0;\r
+      totalUnPackSizePointer = &totalUnPackSize;\r
+    }\r
+    if (enableHeaders && !techMode)\r
+    {\r
+      fieldPrinter.PrintTitleLines();\r
+      g_StdOut << endl;\r
+      fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer);\r
+      g_StdOut << endl;\r
+    }\r
+    if (totalPackSizePointer != 0)\r
+    {\r
+      totalPackSizePointer2 = &totalPackSize2;\r
+      totalPackSize2 += totalPackSize;\r
+    }\r
+    if (totalUnPackSizePointer != 0)\r
+    {\r
+      totalUnPackSizePointer2 = &totalUnPackSize2;\r
+      totalUnPackSize2 += totalUnPackSize;\r
+    }\r
+    numFiles2 += numFiles;\r
+    numDirs2 += numDirs;\r
+  }\r
+  if (enableHeaders && !techMode && numArcs > 1)\r
+  {\r
+    g_StdOut << endl;\r
+    fieldPrinter.PrintTitleLines();\r
+    g_StdOut << endl;\r
+    fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2);\r
+    g_StdOut << endl;\r
+    g_StdOut << "Archives: " << numArcs << endl;\r
+  }\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/UI/Console/List.h b/CPP/7zip/UI/Console/List.h
new file mode 100755 (executable)
index 0000000..7ea02cc
--- /dev/null
@@ -0,0 +1,20 @@
+// List.h\r
+\r
+#ifndef __LIST_H\r
+#define __LIST_H\r
+\r
+#include "Common/Wildcard.h"\r
+#include "../Common/LoadCodecs.h"\r
+\r
+HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices,\r
+    bool stdInMode,\r
+    UStringVector &archivePaths, UStringVector &archivePathsFull,\r
+    const NWildcard::CCensorNode &wildcardCensor,\r
+    bool enableHeaders, bool techMode,\r
+    #ifndef _NO_CRYPTO\r
+    bool &passwordEnabled, UString &password,\r
+    #endif\r
+    UInt64 &errors);\r
+\r
+#endif\r
+\r
diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp
new file mode 100755 (executable)
index 0000000..8946772
--- /dev/null
@@ -0,0 +1,598 @@
+// Main.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES)\r
+#include "../../../../C/Alloc.h"\r
+#endif\r
+\r
+#include "Common/MyInitGuid.h"\r
+\r
+#include "Common/CommandLineParser.h"\r
+#include "Common/IntToString.h"\r
+#include "Common/MyException.h"\r
+#include "Common/StdOutStream.h"\r
+#include "Common/StringConvert.h"\r
+#include "Common/StringToInt.h"\r
+\r
+#include "Windows/Error.h"\r
+#ifdef _WIN32\r
+#include "Windows/MemoryLock.h"\r
+#endif\r
+\r
+#include "../Common/ArchiveCommandLine.h"\r
+#include "../Common/ExitCode.h"\r
+#include "../Common/Extract.h"\r
+#ifdef EXTERNAL_CODECS\r
+#include "../Common/LoadCodecs.h"\r
+#endif\r
+\r
+#include "BenchCon.h"\r
+#include "ExtractCallbackConsole.h"\r
+#include "List.h"\r
+#include "OpenCallbackConsole.h"\r
+#include "UpdateCallbackConsole.h"\r
+\r
+#include "../../MyVersion.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+using namespace NCommandLineParser;\r
+\r
+HINSTANCE g_hInstance = 0;\r
+extern CStdOutStream *g_StdStream;\r
+\r
+static const char *kCopyrightString = "\n7-Zip"\r
+#ifndef EXTERNAL_CODECS\r
+" (A)"\r
+#endif\r
+\r
+#ifdef _WIN64\r
+" [64]"\r
+#endif\r
+\r
+" " MY_VERSION_COPYRIGHT_DATE "\n";\r
+\r
+static const char *kHelpString =\r
+    "\nUsage: 7z"\r
+#ifdef _NO_CRYPTO\r
+    "r"\r
+#else\r
+#ifndef EXTERNAL_CODECS\r
+    "a"\r
+#endif\r
+#endif\r
+    " <command> [<switches>...] <archive_name> [<file_names>...]\n"\r
+    "       [<@listfiles...>]\n"\r
+    "\n"\r
+    "<Commands>\n"\r
+    "  a: Add files to archive\n"\r
+    "  b: Benchmark\n"\r
+    "  d: Delete files from archive\n"\r
+    "  e: Extract files from archive (without using directory names)\n"\r
+    "  l: List contents of archive\n"\r
+//    "  l[a|t][f]: List contents of archive\n"\r
+//    "    a - with Additional fields\n"\r
+//    "    t - with all fields\n"\r
+//    "    f - with Full pathnames\n"\r
+    "  t: Test integrity of archive\n"\r
+    "  u: Update files to archive\n"\r
+    "  x: eXtract files with full paths\n"\r
+    "<Switches>\n"\r
+    "  -ai[r[-|0]]{@listfile|!wildcard}: Include archives\n"\r
+    "  -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives\n"\r
+    "  -bd: Disable percentage indicator\n"\r
+    "  -i[r[-|0]]{@listfile|!wildcard}: Include filenames\n"\r
+    "  -m{Parameters}: set compression Method\n"\r
+    "  -o{Directory}: set Output directory\n"\r
+    #ifndef _NO_CRYPTO\r
+    "  -p{Password}: set Password\n"\r
+    #endif\r
+    "  -r[-|0]: Recurse subdirectories\n"\r
+    "  -scs{UTF-8 | WIN | DOS}: set charset for list files\n"\r
+    "  -sfx[{name}]: Create SFX archive\n"\r
+    "  -si[{name}]: read data from stdin\n"\r
+    "  -slt: show technical information for l (List) command\n"\r
+    "  -so: write data to stdout\n"\r
+    "  -ssc[-]: set sensitive case mode\n"\r
+    "  -ssw: compress shared files\n"\r
+    "  -t{Type}: Set type of archive\n"\r
+    "  -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options\n"\r
+    "  -v{Size}[b|k|m|g]: Create volumes\n"\r
+    "  -w[{path}]: assign Work directory. Empty path means a temporary directory\n"\r
+    "  -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames\n"\r
+    "  -y: assume Yes on all queries\n";\r
+\r
+// ---------------------------\r
+// exception messages\r
+\r
+static const char *kEverythingIsOk = "Everything is Ok";\r
+static const char *kUserErrorMessage = "Incorrect command line";\r
+static const char *kNoFormats = "7-Zip cannot find the code that works with archives.";\r
+static const char *kUnsupportedArcTypeMessage = "Unsupported archive type";\r
+\r
+static const wchar_t *kDefaultSfxModule = L"7zCon.sfx";\r
+\r
+static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code)\r
+{\r
+  s << message << endl;\r
+  throw code;\r
+}\r
+\r
+static void PrintHelpAndExit(CStdOutStream &s)\r
+{\r
+  s << kHelpString;\r
+  ShowMessageAndThrowException(s, kUserErrorMessage, NExitCode::kUserError);\r
+}\r
+\r
+#ifndef _WIN32\r
+static void GetArguments(int numArgs, const char *args[], UStringVector &parts)\r
+{\r
+  parts.Clear();\r
+  for (int i = 0; i < numArgs; i++)\r
+  {\r
+    UString s = MultiByteToUnicodeString(args[i]);\r
+    parts.Add(s);\r
+  }\r
+}\r
+#endif\r
+\r
+static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp)\r
+{\r
+  s << kCopyrightString;\r
+  // s << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << "\n";\r
+  if (needHelp)\r
+    s << kHelpString;\r
+}\r
+\r
+#ifdef EXTERNAL_CODECS\r
+static void PrintString(CStdOutStream &stdStream, const AString &s, int size)\r
+{\r
+  int len = s.Length();\r
+  stdStream << s;\r
+  for (int i = len; i < size; i++)\r
+    stdStream << ' ';\r
+}\r
+#endif\r
+\r
+static void PrintString(CStdOutStream &stdStream, const UString &s, int size)\r
+{\r
+  int len = s.Length();\r
+  stdStream << s;\r
+  for (int i = len; i < size; i++)\r
+    stdStream << ' ';\r
+}\r
+\r
+static inline char GetHex(Byte value)\r
+{\r
+  return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));\r
+}\r
+\r
+int Main2(\r
+  #ifndef _WIN32\r
+  int numArgs, const char *args[]\r
+  #endif\r
+)\r
+{\r
+  #if defined(_WIN32) && !defined(UNDER_CE)\r
+  SetFileApisToOEM();\r
+  #endif\r
+  \r
+  UStringVector commandStrings;\r
+  #ifdef _WIN32\r
+  NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);\r
+  #else\r
+  GetArguments(numArgs, args, commandStrings);\r
+  #endif\r
+\r
+  if (commandStrings.Size() == 1)\r
+  {\r
+    ShowCopyrightAndHelp(g_StdOut, true);\r
+    return 0;\r
+  }\r
+  commandStrings.Delete(0);\r
+\r
+  CArchiveCommandLineOptions options;\r
+\r
+  CArchiveCommandLineParser parser;\r
+\r
+  parser.Parse1(commandStrings, options);\r
+\r
+  if (options.HelpMode)\r
+  {\r
+    ShowCopyrightAndHelp(g_StdOut, true);\r
+    return 0;\r
+  }\r
+\r
+  #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)\r
+  if (options.LargePages)\r
+  {\r
+    SetLargePageSize();\r
+    NSecurity::EnableLockMemoryPrivilege();\r
+  }\r
+  #endif\r
+\r
+  CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut;\r
+  g_StdStream = &stdStream;\r
+\r
+  if (options.EnableHeaders)\r
+    ShowCopyrightAndHelp(stdStream, false);\r
+\r
+  parser.Parse2(options);\r
+\r
+  CCodecs *codecs = new CCodecs;\r
+  CMyComPtr<\r
+    #ifdef EXTERNAL_CODECS\r
+    ICompressCodecsInfo\r
+    #else\r
+    IUnknown\r
+    #endif\r
+    > compressCodecsInfo = codecs;\r
+  HRESULT result = codecs->Load();\r
+  if (result != S_OK)\r
+    throw CSystemException(result);\r
+\r
+  bool isExtractGroupCommand = options.Command.IsFromExtractGroup();\r
+\r
+  if (codecs->Formats.Size() == 0 &&\r
+        (isExtractGroupCommand ||\r
+        options.Command.CommandType == NCommandType::kList ||\r
+        options.Command.IsFromUpdateGroup()))\r
+    throw kNoFormats;\r
+\r
+  CIntVector formatIndices;\r
+  if (!codecs->FindFormatForArchiveType(options.ArcType, formatIndices))\r
+    throw kUnsupportedArcTypeMessage;\r
+\r
+  if (options.Command.CommandType == NCommandType::kInfo)\r
+  {\r
+    stdStream << endl << "Formats:" << endl;\r
+    int i;\r
+    for (i = 0; i < codecs->Formats.Size(); i++)\r
+    {\r
+      const CArcInfoEx &arc = codecs->Formats[i];\r
+      #ifdef EXTERNAL_CODECS\r
+      if (arc.LibIndex >= 0)\r
+      {\r
+        char s[16];\r
+        ConvertUInt32ToString(arc.LibIndex, s);\r
+        PrintString(stdStream, s, 2);\r
+      }\r
+      else\r
+      #endif\r
+        stdStream << "  ";\r
+      stdStream << ' ';\r
+      stdStream << (char)(arc.UpdateEnabled ? 'C' : ' ');\r
+      stdStream << (char)(arc.KeepName ? 'K' : ' ');\r
+      stdStream << "  ";\r
+      PrintString(stdStream, arc.Name, 6);\r
+      stdStream << "  ";\r
+      UString s;\r
+      for (int t = 0; t < arc.Exts.Size(); t++)\r
+      {\r
+        const CArcExtInfo &ext = arc.Exts[t];\r
+        s += ext.Ext;\r
+        if (!ext.AddExt.IsEmpty())\r
+        {\r
+          s += L" (";\r
+          s += ext.AddExt;\r
+          s += L')';\r
+        }\r
+        s += L' ';\r
+      }\r
+      PrintString(stdStream, s, 14);\r
+      stdStream << "  ";\r
+      const CByteBuffer &sig = arc.StartSignature;\r
+      for (size_t j = 0; j < sig.GetCapacity(); j++)\r
+      {\r
+        Byte b = sig[j];\r
+        if (b > 0x20 && b < 0x80)\r
+        {\r
+          stdStream << (char)b;\r
+        }\r
+        else\r
+        {\r
+          stdStream << GetHex((Byte)((b >> 4) & 0xF));\r
+          stdStream << GetHex((Byte)(b & 0xF));\r
+        }\r
+        stdStream << ' ';\r
+      }\r
+      stdStream << endl;\r
+    }\r
+    stdStream << endl << "Codecs:" << endl;\r
+\r
+    #ifdef EXTERNAL_CODECS\r
+    UInt32 numMethods;\r
+    if (codecs->GetNumberOfMethods(&numMethods) == S_OK)\r
+    for (UInt32 j = 0; j < numMethods; j++)\r
+    {\r
+      int libIndex = codecs->GetCodecLibIndex(j);\r
+      if (libIndex >= 0)\r
+      {\r
+        char s[16];\r
+        ConvertUInt32ToString(libIndex, s);\r
+        PrintString(stdStream, s, 2);\r
+      }\r
+      else\r
+        stdStream << "  ";\r
+      stdStream << ' ';\r
+      stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' ');\r
+      UInt64 id;\r
+      stdStream << "  ";\r
+      HRESULT res = codecs->GetCodecId(j, id);\r
+      if (res != S_OK)\r
+        id = (UInt64)(Int64)-1;\r
+      char s[32];\r
+      ConvertUInt64ToString(id, s, 16);\r
+      PrintString(stdStream, s, 8);\r
+      stdStream << "  ";\r
+      PrintString(stdStream, codecs->GetCodecName(j), 11);\r
+      stdStream << endl;\r
+      /*\r
+      if (res != S_OK)\r
+        throw "incorrect Codec ID";\r
+      */\r
+    }\r
+    #endif\r
+    return S_OK;\r
+  }\r
+  else if (options.Command.CommandType == NCommandType::kBenchmark)\r
+  {\r
+    if (options.Method.CompareNoCase(L"CRC") == 0)\r
+    {\r
+      HRESULT res = CrcBenchCon((FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize);\r
+      if (res != S_OK)\r
+      {\r
+        if (res == S_FALSE)\r
+        {\r
+          stdStream << "\nCRC Error\n";\r
+          return NExitCode::kFatalError;\r
+        }\r
+        throw CSystemException(res);\r
+      }\r
+    }\r
+    else\r
+    {\r
+      HRESULT res;\r
+      #ifdef EXTERNAL_CODECS\r
+      CObjectVector<CCodecInfoEx> externalCodecs;\r
+      res = LoadExternalCodecs(compressCodecsInfo, externalCodecs);\r
+      if (res != S_OK)\r
+        throw CSystemException(res);\r
+      #endif\r
+      res = LzmaBenchCon(\r
+          #ifdef EXTERNAL_CODECS\r
+          compressCodecsInfo, &externalCodecs,\r
+          #endif\r
+        (FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize);\r
+      if (res != S_OK)\r
+      {\r
+        if (res == S_FALSE)\r
+        {\r
+          stdStream << "\nDecoding Error\n";\r
+          return NExitCode::kFatalError;\r
+        }\r
+        throw CSystemException(res);\r
+      }\r
+    }\r
+  }\r
+  else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList)\r
+  {\r
+    if (isExtractGroupCommand)\r
+    {\r
+      CExtractCallbackConsole *ecs = new CExtractCallbackConsole;\r
+      CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;\r
+\r
+      ecs->OutStream = &stdStream;\r
+\r
+      #ifndef _NO_CRYPTO\r
+      ecs->PasswordIsDefined = options.PasswordEnabled;\r
+      ecs->Password = options.Password;\r
+      #endif\r
+\r
+      ecs->Init();\r
+\r
+      COpenCallbackConsole openCallback;\r
+      openCallback.OutStream = &stdStream;\r
+\r
+      #ifndef _NO_CRYPTO\r
+      openCallback.PasswordIsDefined = options.PasswordEnabled;\r
+      openCallback.Password = options.Password;\r
+      #endif\r
+\r
+      CExtractOptions eo;\r
+      eo.StdInMode = options.StdInMode;\r
+      eo.StdOutMode = options.StdOutMode;\r
+      eo.PathMode = options.Command.GetPathMode();\r
+      eo.TestMode = options.Command.IsTestMode();\r
+      eo.OverwriteMode = options.OverwriteMode;\r
+      eo.OutputDir = options.OutputDir;\r
+      eo.YesToAll = options.YesToAll;\r
+      eo.CalcCrc = options.CalcCrc;\r
+      #if !defined(_7ZIP_ST) && !defined(_SFX)\r
+      eo.Properties = options.ExtractProperties;\r
+      #endif\r
+      UString errorMessage;\r
+      CDecompressStat stat;\r
+      HRESULT result = DecompressArchives(\r
+          codecs,\r
+          formatIndices,\r
+          options.ArchivePathsSorted,\r
+          options.ArchivePathsFullSorted,\r
+          options.WildcardCensor.Pairs.Front().Head,\r
+          eo, &openCallback, ecs, errorMessage, stat);\r
+      if (!errorMessage.IsEmpty())\r
+      {\r
+        stdStream << endl << "Error: " << errorMessage;\r
+        if (result == S_OK)\r
+          result = E_FAIL;\r
+      }\r
+\r
+      stdStream << endl;\r
+      if (ecs->NumArchives > 1)\r
+        stdStream << "Archives: " << ecs->NumArchives << endl;\r
+      if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0)\r
+      {\r
+        if (ecs->NumArchives > 1)\r
+        {\r
+          stdStream << endl;\r
+          if (ecs->NumArchiveErrors != 0)\r
+            stdStream << "Archive Errors: " << ecs->NumArchiveErrors << endl;\r
+          if (ecs->NumFileErrors != 0)\r
+            stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl;\r
+        }\r
+        if (result != S_OK)\r
+          throw CSystemException(result);\r
+        return NExitCode::kFatalError;\r
+      }\r
+      if (result != S_OK)\r
+        throw CSystemException(result);\r
+      if (stat.NumFolders != 0)\r
+        stdStream << "Folders: " << stat.NumFolders << endl;\r
+      if (stat.NumFiles != 1 || stat.NumFolders != 0)\r
+          stdStream << "Files: " << stat.NumFiles << endl;\r
+      stdStream\r
+           << "Size:       " << stat.UnpackSize << endl\r
+           << "Compressed: " << stat.PackSize << endl;\r
+      if (options.CalcCrc)\r
+      {\r
+        char s[16];\r
+        ConvertUInt32ToHexWithZeros(stat.CrcSum, s);\r
+        stdStream << "CRC: " << s << endl;\r
+      }\r
+    }\r
+    else\r
+    {\r
+      UInt64 numErrors = 0;\r
+      HRESULT result = ListArchives(\r
+          codecs,\r
+          formatIndices,\r
+          options.StdInMode,\r
+          options.ArchivePathsSorted,\r
+          options.ArchivePathsFullSorted,\r
+          options.WildcardCensor.Pairs.Front().Head,\r
+          options.EnableHeaders,\r
+          options.TechMode,\r
+          #ifndef _NO_CRYPTO\r
+          options.PasswordEnabled,\r
+          options.Password,\r
+          #endif\r
+          numErrors);\r
+      if (numErrors > 0)\r
+      {\r
+        g_StdOut << endl << "Errors: " << numErrors;\r
+        return NExitCode::kFatalError;\r
+      }\r
+      if (result != S_OK)\r
+        throw CSystemException(result);\r
+    }\r
+  }\r
+  else if (options.Command.IsFromUpdateGroup())\r
+  {\r
+    CUpdateOptions &uo = options.UpdateOptions;\r
+    if (uo.SfxMode && uo.SfxModule.IsEmpty())\r
+      uo.SfxModule = kDefaultSfxModule;\r
+\r
+    COpenCallbackConsole openCallback;\r
+    openCallback.OutStream = &stdStream;\r
+\r
+    #ifndef _NO_CRYPTO\r
+    bool passwordIsDefined =\r
+        options.PasswordEnabled && !options.Password.IsEmpty();\r
+    openCallback.PasswordIsDefined = passwordIsDefined;\r
+    openCallback.Password = options.Password;\r
+    #endif\r
+\r
+    CUpdateCallbackConsole callback;\r
+    callback.EnablePercents = options.EnablePercents;\r
+\r
+    #ifndef _NO_CRYPTO\r
+    callback.PasswordIsDefined = passwordIsDefined;\r
+    callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty();\r
+    callback.Password = options.Password;\r
+    #endif\r
+    callback.StdOutMode = uo.StdOutMode;\r
+    callback.Init(&stdStream);\r
+\r
+    CUpdateErrorInfo errorInfo;\r
+\r
+    if (!uo.Init(codecs, formatIndices, options.ArchiveName))\r
+      throw kUnsupportedArcTypeMessage;\r
+    HRESULT result = UpdateArchive(codecs,\r
+        options.WildcardCensor, uo,\r
+        errorInfo, &openCallback, &callback);\r
+\r
+    int exitCode = NExitCode::kSuccess;\r
+    if (callback.CantFindFiles.Size() > 0)\r
+    {\r
+      stdStream << endl;\r
+      stdStream << "WARNINGS for files:" << endl << endl;\r
+      int numErrors = callback.CantFindFiles.Size();\r
+      for (int i = 0; i < numErrors; i++)\r
+      {\r
+        stdStream << callback.CantFindFiles[i] << " : ";\r
+        stdStream << NError::MyFormatMessageW(callback.CantFindCodes[i]) << endl;\r
+      }\r
+      stdStream << "----------------" << endl;\r
+      stdStream << "WARNING: Cannot find " << numErrors << " file";\r
+      if (numErrors > 1)\r
+        stdStream << "s";\r
+      stdStream << endl;\r
+      exitCode = NExitCode::kWarning;\r
+    }\r
+\r
+    if (result != S_OK)\r
+    {\r
+      UString message;\r
+      if (!errorInfo.Message.IsEmpty())\r
+      {\r
+        message += errorInfo.Message;\r
+        message += L"\n";\r
+      }\r
+      if (!errorInfo.FileName.IsEmpty())\r
+      {\r
+        message += errorInfo.FileName;\r
+        message += L"\n";\r
+      }\r
+      if (!errorInfo.FileName2.IsEmpty())\r
+      {\r
+        message += errorInfo.FileName2;\r
+        message += L"\n";\r
+      }\r
+      if (errorInfo.SystemError != 0)\r
+      {\r
+        message += NError::MyFormatMessageW(errorInfo.SystemError);\r
+        message += L"\n";\r
+      }\r
+      if (!message.IsEmpty())\r
+        stdStream << L"\nError:\n" << message;\r
+      throw CSystemException(result);\r
+    }\r
+    int numErrors = callback.FailedFiles.Size();\r
+    if (numErrors == 0)\r
+    {\r
+      if (callback.CantFindFiles.Size() == 0)\r
+        stdStream << kEverythingIsOk << endl;\r
+    }\r
+    else\r
+    {\r
+      stdStream << endl;\r
+      stdStream << "WARNINGS for files:" << endl << endl;\r
+      for (int i = 0; i < numErrors; i++)\r
+      {\r
+        stdStream << callback.FailedFiles[i] << " : ";\r
+        stdStream << NError::MyFormatMessageW(callback.FailedCodes[i]) << endl;\r
+      }\r
+      stdStream << "----------------" << endl;\r
+      stdStream << "WARNING: Cannot open " << numErrors << " file";\r
+      if (numErrors > 1)\r
+        stdStream << "s";\r
+      stdStream << endl;\r
+      exitCode = NExitCode::kWarning;\r
+    }\r
+    return exitCode;\r
+  }\r
+  else\r
+    PrintHelpAndExit(stdStream);\r
+  return 0;\r
+}\r
diff --git a/CPP/7zip/UI/Console/MainAr.cpp b/CPP/7zip/UI/Console/MainAr.cpp
new file mode 100755 (executable)
index 0000000..b6681b4
--- /dev/null
@@ -0,0 +1,125 @@
+// MainAr.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/MyException.h"\r
+#include "Common/StdOutStream.h"\r
+\r
+#include "Windows/Error.h"\r
+#include "Windows/NtCheck.h"\r
+\r
+#include "../Common/ArchiveCommandLine.h"\r
+#include "../Common/ExitCode.h"\r
+\r
+#include "ConsoleClose.h"\r
+\r
+using namespace NWindows;\r
+\r
+CStdOutStream *g_StdStream = 0;\r
+\r
+extern int Main2(\r
+  #ifndef _WIN32\r
+  int numArgs, const char *args[]\r
+  #endif\r
+);\r
+\r
+static const char *kExceptionErrorMessage = "\n\nError:\n";\r
+static const char *kUserBreak  = "\nBreak signaled\n";\r
+static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n";\r
+static const char *kUnknownExceptionMessage = "\n\nUnknown Error\n";\r
+static const char *kInternalExceptionMessage = "\n\nInternal Error #";\r
+\r
+#define NT_CHECK_FAIL_ACTION (*g_StdStream) << "Unsupported Windows version"; return NExitCode::kFatalError;\r
+\r
+int MY_CDECL main\r
+(\r
+  #ifndef _WIN32\r
+  int numArgs, const char *args[]\r
+  #endif\r
+)\r
+{\r
+  g_StdStream = &g_StdOut;\r
+\r
+  NT_CHECK\r
+\r
+  NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter;\r
+  int res = 0;\r
+  try\r
+  {\r
+    res = Main2(\r
+    #ifndef _WIN32\r
+    numArgs, args\r
+    #endif\r
+    );\r
+  }\r
+  catch(const CNewException &)\r
+  {\r
+    (*g_StdStream) << kMemoryExceptionMessage;\r
+    return (NExitCode::kMemoryError);\r
+  }\r
+  catch(const NConsoleClose::CCtrlBreakException &)\r
+  {\r
+    (*g_StdStream) << endl << kUserBreak;\r
+    return (NExitCode::kUserBreak);\r
+  }\r
+  catch(const CArchiveCommandLineException &e)\r
+  {\r
+    (*g_StdStream) << kExceptionErrorMessage << e << endl;\r
+    return (NExitCode::kUserError);\r
+  }\r
+  catch(const CSystemException &systemError)\r
+  {\r
+    if (systemError.ErrorCode == E_OUTOFMEMORY)\r
+    {\r
+      (*g_StdStream) << kMemoryExceptionMessage;\r
+      return (NExitCode::kMemoryError);\r
+    }\r
+    if (systemError.ErrorCode == E_ABORT)\r
+    {\r
+      (*g_StdStream) << endl << kUserBreak;\r
+      return (NExitCode::kUserBreak);\r
+    }\r
+    UString message;\r
+    NError::MyFormatMessage(systemError.ErrorCode, message);\r
+    (*g_StdStream) << endl << endl << "System error:" << endl << message << endl;\r
+    return (NExitCode::kFatalError);\r
+  }\r
+  catch(NExitCode::EEnum &exitCode)\r
+  {\r
+    (*g_StdStream) << kInternalExceptionMessage << exitCode << endl;\r
+    return (exitCode);\r
+  }\r
+  /*\r
+  catch(const NExitCode::CMultipleErrors &multipleErrors)\r
+  {\r
+    (*g_StdStream) << endl << multipleErrors.NumErrors << " errors" << endl;\r
+    return (NExitCode::kFatalError);\r
+  }\r
+  */\r
+  catch(const UString &s)\r
+  {\r
+    (*g_StdStream) << kExceptionErrorMessage << s << endl;\r
+    return (NExitCode::kFatalError);\r
+  }\r
+  catch(const AString &s)\r
+  {\r
+    (*g_StdStream) << kExceptionErrorMessage << s << endl;\r
+    return (NExitCode::kFatalError);\r
+  }\r
+  catch(const char *s)\r
+  {\r
+    (*g_StdStream) << kExceptionErrorMessage << s << endl;\r
+    return (NExitCode::kFatalError);\r
+  }\r
+  catch(int t)\r
+  {\r
+    (*g_StdStream) << kInternalExceptionMessage << t << endl;\r
+    return (NExitCode::kFatalError);\r
+  }\r
+  catch(...)\r
+  {\r
+    (*g_StdStream) << kUnknownExceptionMessage;\r
+    return (NExitCode::kFatalError);\r
+  }\r
+  return  res;\r
+}\r
diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.cpp b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
new file mode 100755 (executable)
index 0000000..986a592
--- /dev/null
@@ -0,0 +1,58 @@
+// OpenCallbackConsole.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "OpenCallbackConsole.h"\r
+\r
+#include "ConsoleClose.h"\r
+#include "UserInputUtils.h"\r
+\r
+HRESULT COpenCallbackConsole::Open_CheckBreak()\r
+{\r
+  if (NConsoleClose::TestBreakSignal())\r
+    return E_ABORT;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *, const UInt64 *)\r
+{\r
+  return Open_CheckBreak();\r
+}\r
+\r
+HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *, const UInt64 *)\r
+{\r
+  return Open_CheckBreak();\r
+}\r
\r
+#ifndef _NO_CRYPTO\r
+\r
+HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password)\r
+{\r
+  PasswordWasAsked = true;\r
+  RINOK(Open_CheckBreak());\r
+  if (!PasswordIsDefined)\r
+  {\r
+    Password = GetPassword(OutStream);\r
+    PasswordIsDefined = true;\r
+  }\r
+  return StringToBstr(Password, password);\r
+}\r
+\r
+HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(UString &password)\r
+{\r
+  if (PasswordIsDefined)\r
+    password = Password;\r
+  return S_OK;\r
+}\r
+\r
+bool COpenCallbackConsole::Open_WasPasswordAsked()\r
+{\r
+  return PasswordWasAsked;\r
+}\r
+\r
+void COpenCallbackConsole::Open_ClearPasswordWasAskedFlag()\r
+{\r
+  PasswordWasAsked = false;\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.h b/CPP/7zip/UI/Console/OpenCallbackConsole.h
new file mode 100755 (executable)
index 0000000..99e8c04
--- /dev/null
@@ -0,0 +1,24 @@
+// OpenCallbackConsole.h\r
+\r
+#ifndef __OPENCALLBACKCONSOLE_H\r
+#define __OPENCALLBACKCONSOLE_H\r
+\r
+#include "Common/StdOutStream.h"\r
+#include "../Common/ArchiveOpenCallback.h"\r
+\r
+class COpenCallbackConsole: public IOpenCallbackUI\r
+{\r
+public:\r
+  INTERFACE_IOpenCallbackUI(;)\r
+  \r
+  CStdOutStream *OutStream;\r
+\r
+  #ifndef _NO_CRYPTO\r
+  bool PasswordIsDefined;\r
+  bool PasswordWasAsked;\r
+  UString Password;\r
+  COpenCallbackConsole(): PasswordIsDefined(false), PasswordWasAsked(false) {}\r
+  #endif\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Console/PercentPrinter.cpp b/CPP/7zip/UI/Console/PercentPrinter.cpp
new file mode 100755 (executable)
index 0000000..111ae25
--- /dev/null
@@ -0,0 +1,90 @@
+// PercentPrinter.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/MyString.h"\r
+\r
+#include "PercentPrinter.h"\r
+\r
+const int kPaddingSize = 2;\r
+const int kPercentsSize = 4;\r
+const int kMaxExtraSize = kPaddingSize + 32 + kPercentsSize;\r
+\r
+static void ClearPrev(char *p, int num)\r
+{\r
+  int i;\r
+  for (i = 0; i < num; i++) *p++ = '\b';\r
+  for (i = 0; i < num; i++) *p++ = ' ';\r
+  for (i = 0; i < num; i++) *p++ = '\b';\r
+  *p = '\0';\r
+}\r
+\r
+void CPercentPrinter::ClosePrint()\r
+{\r
+  if (m_NumExtraChars == 0)\r
+    return;\r
+  char s[kMaxExtraSize * 3 + 1];\r
+  ClearPrev(s, m_NumExtraChars);\r
+  (*OutStream) << s;\r
+  m_NumExtraChars = 0;\r
+}\r
+\r
+void CPercentPrinter::PrintString(const char *s)\r
+{\r
+  ClosePrint();\r
+  (*OutStream) << s;\r
+}\r
+\r
+void CPercentPrinter::PrintString(const wchar_t *s)\r
+{\r
+  ClosePrint();\r
+  (*OutStream) << s;\r
+}\r
+\r
+void CPercentPrinter::PrintNewLine()\r
+{\r
+  ClosePrint();\r
+  (*OutStream) << "\n";\r
+}\r
+\r
+void CPercentPrinter::RePrintRatio()\r
+{\r
+  char s[32];\r
+  ConvertUInt64ToString(((m_Total == 0) ? 0 : (m_CurValue * 100 / m_Total)), s);\r
+  int size = (int)strlen(s);\r
+  s[size++] = '%';\r
+  s[size] = '\0';\r
+\r
+  int extraSize = kPaddingSize + MyMax(size, kPercentsSize);\r
+  if (extraSize < m_NumExtraChars)\r
+    extraSize = m_NumExtraChars;\r
+\r
+  char fullString[kMaxExtraSize * 3];\r
+  char *p = fullString;\r
+  int i;\r
+  if (m_NumExtraChars == 0)\r
+  {\r
+    for (i = 0; i < extraSize; i++)\r
+      *p++ = ' ';\r
+    m_NumExtraChars = extraSize;\r
+  }\r
+\r
+  for (i = 0; i < m_NumExtraChars; i++)\r
+    *p++ = '\b';\r
+  m_NumExtraChars = extraSize;\r
+  for (; size < m_NumExtraChars; size++)\r
+    *p++ = ' ';\r
+  MyStringCopy(p, s);\r
+  (*OutStream) << fullString;\r
+  OutStream->Flush();\r
+  m_PrevValue = m_CurValue;\r
+}\r
+\r
+void CPercentPrinter::PrintRatio()\r
+{\r
+  if (m_CurValue < m_PrevValue + m_MinStepSize &&\r
+      m_CurValue + m_MinStepSize > m_PrevValue && m_NumExtraChars != 0)\r
+    return;\r
+  RePrintRatio();\r
+}\r
diff --git a/CPP/7zip/UI/Console/PercentPrinter.h b/CPP/7zip/UI/Console/PercentPrinter.h
new file mode 100755 (executable)
index 0000000..212e11e
--- /dev/null
@@ -0,0 +1,31 @@
+// PercentPrinter.h\r
+\r
+#ifndef __PERCENTPRINTER_H\r
+#define __PERCENTPRINTER_H\r
+\r
+#include "Common/Types.h"\r
+#include "Common/StdOutStream.h"\r
+\r
+class CPercentPrinter\r
+{\r
+  UInt64 m_MinStepSize;\r
+  UInt64 m_PrevValue;\r
+  UInt64 m_CurValue;\r
+  UInt64 m_Total;\r
+  int m_NumExtraChars;\r
+public:\r
+  CStdOutStream *OutStream;\r
+\r
+  CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize),\r
+      m_PrevValue(0), m_CurValue(0), m_Total(1), m_NumExtraChars(0) {}\r
+  void SetTotal(UInt64 total) { m_Total = total; m_PrevValue = 0; }\r
+  void SetRatio(UInt64 doneValue) { m_CurValue = doneValue; }\r
+  void PrintString(const char *s);\r
+  void PrintString(const wchar_t *s);\r
+  void PrintNewLine();\r
+  void ClosePrint();\r
+  void RePrintRatio();\r
+  void PrintRatio();\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Console/StdAfx.cpp b/CPP/7zip/UI/Console/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..c6d3b1f
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/UI/Console/StdAfx.h b/CPP/7zip/UI/Console/StdAfx.h
new file mode 100755 (executable)
index 0000000..a4e6173
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../../Common/MyWindows.h"\r
+#include "../../../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
new file mode 100755 (executable)
index 0000000..c482676
--- /dev/null
@@ -0,0 +1,261 @@
+// UpdateCallbackConsole.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "UpdateCallbackConsole.h"\r
+\r
+#include "Windows/Error.h"\r
+#ifndef _7ZIP_ST\r
+#include "Windows/Synchronization.h"\r
+#endif\r
+\r
+#include "ConsoleClose.h"\r
+#include "UserInputUtils.h"\r
+\r
+using namespace NWindows;\r
+\r
+#ifndef _7ZIP_ST\r
+static NSynchronization::CCriticalSection g_CriticalSection;\r
+#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\r
+#else\r
+#define MT_LOCK\r
+#endif\r
+\r
+static const wchar_t *kEmptyFileAlias = L"[Content]";\r
+\r
+static const char *kCreatingArchiveMessage = "Creating archive ";\r
+static const char *kUpdatingArchiveMessage = "Updating archive ";\r
+static const char *kScanningMessage = "Scanning";\r
+\r
+\r
+HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result)\r
+{\r
+  (*OutStream) << endl;\r
+  if (result != S_OK)\r
+    (*OutStream) << "Error: " << name << " is not supported archive" << endl;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackConsole::StartScanning()\r
+{\r
+  (*OutStream) << kScanningMessage;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, const wchar_t * /* path */)\r
+{\r
+  return CheckBreak();\r
+}\r
+\r
+HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError)\r
+{\r
+  CantFindFiles.Add(name);\r
+  CantFindCodes.Add(systemError);\r
+  // m_PercentPrinter.ClosePrint();\r
+  if (!m_WarningsMode)\r
+  {\r
+    (*OutStream) << endl << endl;\r
+    m_PercentPrinter.PrintNewLine();\r
+    m_WarningsMode = true;\r
+  }\r
+  m_PercentPrinter.PrintString(name);\r
+  m_PercentPrinter.PrintString(":  WARNING: ");\r
+  m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError));\r
+  m_PercentPrinter.PrintNewLine();\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackConsole::FinishScanning()\r
+{\r
+  (*OutStream) << endl << endl;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating)\r
+{\r
+  if(updating)\r
+    (*OutStream) << kUpdatingArchiveMessage;\r
+  else\r
+    (*OutStream) << kCreatingArchiveMessage;\r
+  if (name != 0)\r
+    (*OutStream) << name;\r
+  else\r
+    (*OutStream) << "StdOut";\r
+  (*OutStream) << endl << endl;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackConsole::FinishArchive()\r
+{\r
+  (*OutStream) << endl;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackConsole::CheckBreak()\r
+{\r
+  if (NConsoleClose::TestBreakSignal())\r
+    return E_ABORT;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackConsole::Finilize()\r
+{\r
+  MT_LOCK\r
+  if (m_NeedBeClosed)\r
+  {\r
+    if (EnablePercents)\r
+    {\r
+      m_PercentPrinter.ClosePrint();\r
+    }\r
+    if (!StdOutMode && m_NeedNewLine)\r
+    {\r
+      m_PercentPrinter.PrintNewLine();\r
+      m_NeedNewLine = false;\r
+    }\r
+    m_NeedBeClosed = false;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackConsole::SetNumFiles(UInt64 /* numFiles */)\r
+{\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size)\r
+{\r
+  MT_LOCK\r
+  if (EnablePercents)\r
+    m_PercentPrinter.SetTotal(size);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue)\r
+{\r
+  MT_LOCK\r
+  if (completeValue != NULL)\r
+  {\r
+    if (EnablePercents)\r
+    {\r
+      m_PercentPrinter.SetRatio(*completeValue);\r
+      m_PercentPrinter.PrintRatio();\r
+      m_NeedBeClosed = true;\r
+    }\r
+  }\r
+  if (NConsoleClose::TestBreakSignal())\r
+    return E_ABORT;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */)\r
+{\r
+  if (NConsoleClose::TestBreakSignal())\r
+    return E_ABORT;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isAnti)\r
+{\r
+  MT_LOCK\r
+  if (StdOutMode)\r
+    return S_OK;\r
+  if(isAnti)\r
+    m_PercentPrinter.PrintString("Anti item    ");\r
+  else\r
+    m_PercentPrinter.PrintString("Compressing  ");\r
+  if (name[0] == 0)\r
+    name = kEmptyFileAlias;\r
+  m_PercentPrinter.PrintString(name);\r
+  if (EnablePercents)\r
+    m_PercentPrinter.RePrintRatio();\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError)\r
+{\r
+  MT_LOCK\r
+  FailedCodes.Add(systemError);\r
+  FailedFiles.Add(name);\r
+  // if (systemError == ERROR_SHARING_VIOLATION)\r
+  {\r
+    m_PercentPrinter.ClosePrint();\r
+    m_PercentPrinter.PrintNewLine();\r
+    m_PercentPrinter.PrintString("WARNING: ");\r
+    m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError));\r
+    return S_FALSE;\r
+  }\r
+  // return systemError;\r
+}\r
+\r
+HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 )\r
+{\r
+  m_NeedBeClosed = true;\r
+  m_NeedNewLine = true;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)\r
+{\r
+  *password = NULL;\r
+\r
+  #ifdef _NO_CRYPTO\r
+\r
+  *passwordIsDefined = false;\r
+  return S_OK;\r
+  \r
+  #else\r
+  \r
+  if (!PasswordIsDefined)\r
+  {\r
+    if (AskPassword)\r
+    {\r
+      Password = GetPassword(OutStream);\r
+      PasswordIsDefined = true;\r
+    }\r
+  }\r
+  *passwordIsDefined = BoolToInt(PasswordIsDefined);\r
+  return StringToBstr(Password, password);\r
+  \r
+  #endif\r
+}\r
+\r
+HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password)\r
+{\r
+  *password = NULL;\r
+\r
+  #ifdef _NO_CRYPTO\r
+\r
+  return E_NOTIMPL;\r
+  \r
+  #else\r
+  \r
+  if (!PasswordIsDefined)\r
+  {\r
+    {\r
+      Password = GetPassword(OutStream);\r
+      PasswordIsDefined = true;\r
+    }\r
+  }\r
+  return StringToBstr(Password, password);\r
+  \r
+  #endif\r
+}\r
+\r
+/*\r
+HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name)\r
+{\r
+  // MT_LOCK\r
+  if (StdOutMode)\r
+    return S_OK;\r
+  RINOK(Finilize());\r
+  m_PercentPrinter.PrintString("Deleting  ");\r
+  if (name[0] == 0)\r
+    name = kEmptyFileAlias;\r
+  m_PercentPrinter.PrintString(name);\r
+  if (EnablePercents)\r
+    m_PercentPrinter.RePrintRatio();\r
+  m_NeedBeClosed = true;\r
+  m_NeedNewLine = true;\r
+  return S_OK;\r
+}\r
+*/\r
diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.h b/CPP/7zip/UI/Console/UpdateCallbackConsole.h
new file mode 100755 (executable)
index 0000000..59581f3
--- /dev/null
@@ -0,0 +1,62 @@
+// UpdateCallbackConsole.h\r
+\r
+#ifndef __UPDATE_CALLBACK_CONSOLE_H\r
+#define __UPDATE_CALLBACK_CONSOLE_H\r
+\r
+#include "Common/StdOutStream.h"\r
+\r
+#include "../Common/Update.h"\r
+\r
+#include "PercentPrinter.h"\r
+\r
+class CUpdateCallbackConsole: public IUpdateCallbackUI2\r
+{\r
+  CPercentPrinter m_PercentPrinter;\r
+  bool m_NeedBeClosed;\r
+  bool m_NeedNewLine;\r
+\r
+  bool m_WarningsMode;\r
+\r
+  CStdOutStream *OutStream;\r
+public:\r
+  bool EnablePercents;\r
+  bool StdOutMode;\r
+\r
+  #ifndef _NO_CRYPTO\r
+  bool PasswordIsDefined;\r
+  UString Password;\r
+  bool AskPassword;\r
+  #endif\r
+\r
+  CUpdateCallbackConsole():\r
+      m_PercentPrinter(1 << 16),\r
+      #ifndef _NO_CRYPTO\r
+      PasswordIsDefined(false),\r
+      AskPassword(false),\r
+      #endif\r
+      StdOutMode(false),\r
+      EnablePercents(true),\r
+      m_WarningsMode(false)\r
+      {}\r
+  \r
+  ~CUpdateCallbackConsole() { Finilize(); }\r
+  void Init(CStdOutStream *outStream)\r
+  {\r
+    m_NeedBeClosed = false;\r
+    m_NeedNewLine = false;\r
+    FailedFiles.Clear();\r
+    FailedCodes.Clear();\r
+    OutStream = outStream;\r
+    m_PercentPrinter.OutStream = outStream;\r
+  }\r
+\r
+  INTERFACE_IUpdateCallbackUI2(;)\r
+\r
+  UStringVector FailedFiles;\r
+  CRecordVector<HRESULT> FailedCodes;\r
+\r
+  UStringVector CantFindFiles;\r
+  CRecordVector<HRESULT> CantFindCodes;\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Console/UserInputUtils.cpp b/CPP/7zip/UI/Console/UserInputUtils.cpp
new file mode 100755 (executable)
index 0000000..68481c2
--- /dev/null
@@ -0,0 +1,87 @@
+// UserInputUtils.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/StdInStream.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "UserInputUtils.h"\r
+\r
+static const char kYes = 'Y';\r
+static const char kNo = 'N';\r
+static const char kYesAll = 'A';\r
+static const char kNoAll = 'S';\r
+static const char kAutoRenameAll = 'U';\r
+static const char kQuit = 'Q';\r
+\r
+static const char *kFirstQuestionMessage = "?\n";\r
+static const char *kHelpQuestionMessage =\r
+  "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? ";\r
+\r
+// return true if pressed Quite;\r
+\r
+NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream)\r
+{\r
+  (*outStream) << kFirstQuestionMessage;\r
+  for (;;)\r
+  {\r
+    (*outStream) << kHelpQuestionMessage;\r
+    outStream->Flush();\r
+    AString scannedString = g_StdIn.ScanStringUntilNewLine();\r
+    scannedString.Trim();\r
+    if (!scannedString.IsEmpty())\r
+      switch(\r
+        ::MyCharUpper(\r
+        #ifdef UNDER_CE\r
+        (wchar_t)\r
+        #endif\r
+        scannedString[0]))\r
+      {\r
+        case kYes:\r
+          return NUserAnswerMode::kYes;\r
+        case kNo:\r
+          return NUserAnswerMode::kNo;\r
+        case kYesAll:\r
+          return NUserAnswerMode::kYesAll;\r
+        case kNoAll:\r
+          return NUserAnswerMode::kNoAll;\r
+        case kAutoRenameAll:\r
+          return NUserAnswerMode::kAutoRenameAll;\r
+        case kQuit:\r
+          return NUserAnswerMode::kQuit;\r
+      }\r
+  }\r
+}\r
+\r
+#ifdef _WIN32\r
+#ifndef UNDER_CE\r
+#define MY_DISABLE_ECHO\r
+#endif\r
+#endif\r
+\r
+UString GetPassword(CStdOutStream *outStream)\r
+{\r
+  (*outStream) << "\nEnter password"\r
+      #ifdef MY_DISABLE_ECHO\r
+      " (will not be echoed)"\r
+      #endif\r
+      ":";\r
+  outStream->Flush();\r
+\r
+  #ifdef MY_DISABLE_ECHO\r
+  HANDLE console = GetStdHandle(STD_INPUT_HANDLE);\r
+  bool wasChanged = false;\r
+  DWORD mode = 0;\r
+  if (console != INVALID_HANDLE_VALUE && console != 0)\r
+    if (GetConsoleMode(console, &mode))\r
+      wasChanged = (SetConsoleMode(console, mode & ~ENABLE_ECHO_INPUT) != 0);\r
+  UString res = g_StdIn.ScanUStringUntilNewLine();\r
+  if (wasChanged)\r
+    SetConsoleMode(console, mode);\r
+  (*outStream) << "\n";\r
+  outStream->Flush();\r
+  return res;\r
+  #else\r
+  return g_StdIn.ScanUStringUntilNewLine();\r
+  #endif\r
+}\r
diff --git a/CPP/7zip/UI/Console/UserInputUtils.h b/CPP/7zip/UI/Console/UserInputUtils.h
new file mode 100755 (executable)
index 0000000..3740ad7
--- /dev/null
@@ -0,0 +1,24 @@
+// UserInputUtils.h\r
+\r
+#ifndef __USERINPUTUTILS_H\r
+#define __USERINPUTUTILS_H\r
+\r
+#include "Common/StdOutStream.h"\r
+\r
+namespace NUserAnswerMode {\r
+\r
+enum EEnum\r
+{\r
+  kYes,\r
+  kNo,\r
+  kYesAll,\r
+  kNoAll,\r
+  kAutoRenameAll,\r
+  kQuit\r
+};\r
+}\r
+\r
+NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream);\r
+UString GetPassword(CStdOutStream *outStream);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Console/makefile b/CPP/7zip/UI/Console/makefile
new file mode 100755 (executable)
index 0000000..0d40eb5
--- /dev/null
@@ -0,0 +1,124 @@
+PROG = 7z.exe\r
+MY_CONSOLE = 1\r
+CFLAGS = $(CFLAGS) -I ../../../  \\r
+  -DEXTERNAL_CODECS \\r
+\r
+!IFNDEF UNDER_CE\r
+CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -D_7ZIP_LARGE_PAGES -DSUPPORT_DEVICE_FILE\r
+!ENDIF\r
+\r
+\r
+CONSOLE_OBJS = \\r
+  $O\ConsoleClose.obj \\r
+  $O\ExtractCallbackConsole.obj \\r
+  $O\List.obj \\r
+  $O\BenchCon.obj \\r
+  $O\Main.obj \\r
+  $O\MainAr.obj \\r
+  $O\OpenCallbackConsole.obj \\r
+  $O\PercentPrinter.obj \\r
+  $O\UpdateCallbackConsole.obj \\r
+  $O\UserInputUtils.obj \\r
+\r
+COMMON_OBJS = \\r
+  $O\CommandLineParser.obj \\r
+  $O\CRC.obj \\r
+  $O\IntToString.obj \\r
+  $O\ListFileUtils.obj \\r
+  $O\NewHandler.obj \\r
+  $O\StdInStream.obj \\r
+  $O\StdOutStream.obj \\r
+  $O\MyString.obj \\r
+  $O\StringConvert.obj \\r
+  $O\StringToInt.obj \\r
+  $O\UTFConvert.obj \\r
+  $O\MyVector.obj \\r
+  $O\Wildcard.obj \\r
+\r
+WIN_OBJS = \\r
+  $O\DLL.obj \\r
+  $O\Error.obj \\r
+  $O\FileDir.obj \\r
+  $O\FileFind.obj \\r
+  $O\FileIO.obj \\r
+  $O\FileName.obj \\r
+  $O\MemoryLock.obj \\r
+  $O\PropVariant.obj \\r
+  $O\PropVariantConversions.obj \\r
+  $O\Registry.obj \\r
+  $O\System.obj \\r
+  $O\Time.obj \\r
+\r
+7ZIP_COMMON_OBJS = \\r
+  $O\CreateCoder.obj \\r
+  $O\FilePathAutoRename.obj \\r
+  $O\FileStreams.obj \\r
+  $O\FilterCoder.obj \\r
+  $O\ProgressUtils.obj \\r
+  $O\StreamUtils.obj \\r
+\r
+UI_COMMON_OBJS = \\r
+  $O\ArchiveCommandLine.obj \\r
+  $O\ArchiveExtractCallback.obj \\r
+  $O\ArchiveOpenCallback.obj \\r
+  $O\DefaultName.obj \\r
+  $O\EnumDirItems.obj \\r
+  $O\Extract.obj \\r
+  $O\ExtractingFilePath.obj \\r
+  $O\Bench.obj \\r
+  $O\LoadCodecs.obj \\r
+  $O\OpenArchive.obj \\r
+  $O\PropIDUtils.obj \\r
+  $O\SetProperties.obj \\r
+  $O\SortUtils.obj \\r
+  $O\TempFiles.obj \\r
+  $O\Update.obj \\r
+  $O\UpdateAction.obj \\r
+  $O\UpdateCallback.obj \\r
+  $O\UpdatePair.obj \\r
+  $O\UpdateProduce.obj \\r
+  $O\WorkDir.obj \\r
+\r
+AR_COMMON_OBJS = \\r
+  $O\OutStreamWithCRC.obj \\r
+\r
+C_OBJS = \\r
+  $O\Alloc.obj \\r
+  $O\CpuArch.obj \\r
+  $O\Threads.obj \\r
+\r
+!include "../../Crc.mak"\r
+\r
+OBJS = \\r
+  $O\StdAfx.obj \\r
+  $(CONSOLE_OBJS) \\r
+  $(COMMON_OBJS) \\r
+  $(WIN_OBJS) \\r
+  $(7ZIP_COMMON_OBJS) \\r
+  $(UI_COMMON_OBJS) \\r
+  $(AR_COMMON_OBJS) \\r
+  $O\CopyCoder.obj \\r
+  $(C_OBJS) \\r
+  $(ASM_OBJS) \\r
+  $O\resource.res\r
+\r
+!include "../../../Build.mak"\r
+\r
+$(CONSOLE_OBJS): $(*B).cpp\r
+       $(COMPL)\r
+$(COMMON_OBJS): ../../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_OBJS): ../../../Windows/$(*B).cpp\r
+       $(COMPL)\r
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(UI_COMMON_OBJS): ../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp\r
+       $(COMPL)\r
+$O\CopyCoder.obj: ../../Compress/$(*B).cpp\r
+       $(COMPL)\r
+$(C_OBJS): ../../../../C/$(*B).c\r
+       $(COMPL_O2)\r
+\r
+!include "../../Asm.mak"\r
diff --git a/CPP/7zip/UI/Console/resource.rc b/CPP/7zip/UI/Console/resource.rc
new file mode 100755 (executable)
index 0000000..20dfee1
--- /dev/null
@@ -0,0 +1,3 @@
+#include "../../MyVersionInfo.rc"\r
+\r
+MY_VERSION_INFO_APP("7-Zip Console", "7z")\r
diff --git a/CPP/7zip/UI/Explorer/7-zip.dll.manifest b/CPP/7zip/UI/Explorer/7-zip.dll.manifest
new file mode 100755 (executable)
index 0000000..9276dfb
--- /dev/null
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="7-Zip.7-Zip.7-zip" type="win32"/><description>7-Zip Extension.</description><dependency> <dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/></dependentAssembly></dependency></assembly>\r
diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp
new file mode 100755 (executable)
index 0000000..b6d7d10
--- /dev/null
@@ -0,0 +1,829 @@
+// ContextMenu.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "ContextMenu.h"\r
+\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/COM.h"\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileFind.h"\r
+#include "Windows/Memory.h"\r
+#include "Windows/Menu.h"\r
+#include "Windows/Process.h"\r
+#include "Windows/Shell.h"\r
+\r
+#include "../Common/ArchiveName.h"\r
+#include "../Common/CompressCall.h"\r
+#include "../Common/ExtractingFilePath.h"\r
+#include "../Common/ZipRegistry.h"\r
+\r
+#include "../FileManager/FormatUtils.h"\r
+#include "../FileManager/ProgramLocation.h"\r
+\r
+#ifdef LANG\r
+#include "../FileManager/LangUtils.h"\r
+#endif\r
+\r
+#include "ContextMenuFlags.h"\r
+#include "MyMessages.h"\r
+\r
+#include "resource.h"\r
+\r
+using namespace NWindows;\r
+\r
+\r
+#ifndef UNDER_CE\r
+#define EMAIL_SUPPORT 1\r
+#endif\r
+\r
+extern LONG g_DllRefCount;\r
+    \r
+CZipContextMenu::CZipContextMenu()  { InterlockedIncrement(&g_DllRefCount); }\r
+CZipContextMenu::~CZipContextMenu() { InterlockedDecrement(&g_DllRefCount); }\r
+\r
+HRESULT CZipContextMenu::GetFileNames(LPDATAOBJECT dataObject, UStringVector &fileNames)\r
+{\r
+  #ifndef UNDER_CE\r
+  fileNames.Clear();\r
+  if (dataObject == NULL)\r
+    return E_FAIL;\r
+  FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};\r
+  NCOM::CStgMedium stgMedium;\r
+  HRESULT result = dataObject->GetData(&fmte, &stgMedium);\r
+  if (result != S_OK)\r
+    return result;\r
+  stgMedium._mustBeReleased = true;\r
+\r
+  NShell::CDrop drop(false);\r
+  NMemory::CGlobalLock globalLock(stgMedium->hGlobal);\r
+  drop.Attach((HDROP)globalLock.GetPointer());\r
+  drop.QueryFileNames(fileNames);\r
+  #endif\r
+  return S_OK;\r
+}\r
+\r
+// IShellExtInit\r
+\r
+STDMETHODIMP CZipContextMenu::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT dataObject, HKEY /* hkeyProgID */)\r
+{\r
+  // OutputDebugString(TEXT("::Initialize\r\n"));\r
+  _dropMode = false;\r
+  _dropPath.Empty();\r
+  if (pidlFolder != 0)\r
+  {\r
+    #ifndef UNDER_CE\r
+    if (NShell::GetPathFromIDList(pidlFolder, _dropPath))\r
+    {\r
+      // OutputDebugString(path);\r
+      // OutputDebugString(TEXT("\r\n"));\r
+      NFile::NName::NormalizeDirPathPrefix(_dropPath);\r
+      _dropMode = !_dropPath.IsEmpty();\r
+    }\r
+    else\r
+    #endif\r
+      _dropPath.Empty();\r
+  }\r
+\r
+  /*\r
+  m_IsFolder = false;\r
+  if (pidlFolder == 0)\r
+  */\r
+  // pidlFolder is NULL :(\r
+  return GetFileNames(dataObject, _fileNames);\r
+}\r
+\r
+HRESULT CZipContextMenu::InitContextMenu(const wchar_t * /* folder */, const wchar_t **names, UInt32 numFiles)\r
+{\r
+  _fileNames.Clear();\r
+  for (UInt32 i = 0; i < numFiles; i++)\r
+    _fileNames.Add(names[i]);\r
+  _dropMode = false;\r
+  return S_OK;\r
+}\r
+\r
+\r
+/////////////////////////////\r
+// IContextMenu\r
+\r
+static LPCWSTR kMainVerb = L"SevenZip";\r
+\r
+/*\r
+static LPCTSTR kOpenVerb = TEXT("SevenOpen");\r
+static LPCTSTR kExtractVerb = TEXT("SevenExtract");\r
+static LPCTSTR kExtractHereVerb = TEXT("SevenExtractHere");\r
+static LPCTSTR kExtractToVerb = TEXT("SevenExtractTo");\r
+static LPCTSTR kTestVerb = TEXT("SevenTest");\r
+static LPCTSTR kCompressVerb = TEXT("SevenCompress");\r
+static LPCTSTR kCompressToVerb = TEXT("SevenCompressTo");\r
+static LPCTSTR kCompressEmailVerb = TEXT("SevenCompressEmail");\r
+static LPCTSTR kCompressToEmailVerb = TEXT("SevenCompressToEmail");\r
+*/\r
+\r
+struct CContextMenuCommand\r
+{\r
+  UInt32 flag;\r
+  CZipContextMenu::ECommandInternalID CommandInternalID;\r
+  LPCWSTR Verb;\r
+  UINT ResourceID;\r
+  UINT ResourceHelpID;\r
+  UInt32 LangID;\r
+};\r
+\r
+static CContextMenuCommand g_Commands[] =\r
+{\r
+  {\r
+    NContextMenuFlags::kOpen,\r
+    CZipContextMenu::kOpen,\r
+    L"Open",\r
+    IDS_CONTEXT_OPEN,\r
+    IDS_CONTEXT_OPEN_HELP,\r
+    0x02000103\r
+  },\r
+  {\r
+    NContextMenuFlags::kExtract,\r
+    CZipContextMenu::kExtract,\r
+    L"Extract",\r
+    IDS_CONTEXT_EXTRACT,\r
+    IDS_CONTEXT_EXTRACT_HELP,\r
+    0x02000105\r
+  },\r
+  {\r
+    NContextMenuFlags::kExtractHere,\r
+    CZipContextMenu::kExtractHere,\r
+    L"ExtractHere",\r
+    IDS_CONTEXT_EXTRACT_HERE,\r
+    IDS_CONTEXT_EXTRACT_HERE_HELP,\r
+    0x0200010B\r
+  },\r
+  {\r
+    NContextMenuFlags::kExtractTo,\r
+    CZipContextMenu::kExtractTo,\r
+    L"ExtractTo",\r
+    IDS_CONTEXT_EXTRACT_TO,\r
+    IDS_CONTEXT_EXTRACT_TO_HELP,\r
+    0x0200010D\r
+  },\r
+  {\r
+    NContextMenuFlags::kTest,\r
+    CZipContextMenu::kTest,\r
+    L"Test",\r
+    IDS_CONTEXT_TEST,\r
+    IDS_CONTEXT_TEST_HELP,\r
+    0x02000109\r
+  },\r
+  {\r
+    NContextMenuFlags::kCompress,\r
+    CZipContextMenu::kCompress,\r
+    L"Compress",\r
+    IDS_CONTEXT_COMPRESS,\r
+    IDS_CONTEXT_COMPRESS_HELP,\r
+    0x02000107,\r
+  },\r
+  {\r
+    NContextMenuFlags::kCompressEmail,\r
+    CZipContextMenu::kCompressEmail,\r
+    L"CompressEmail",\r
+    IDS_CONTEXT_COMPRESS_EMAIL,\r
+    IDS_CONTEXT_COMPRESS_EMAIL_HELP,\r
+    0x02000111\r
+  },\r
+  {\r
+    NContextMenuFlags::kCompressTo7z,\r
+    CZipContextMenu::kCompressTo7z,\r
+    L"CompressTo7z",\r
+    IDS_CONTEXT_COMPRESS_TO,\r
+    IDS_CONTEXT_COMPRESS_TO_HELP,\r
+    0x0200010F\r
+  },\r
+  {\r
+    NContextMenuFlags::kCompressTo7zEmail,\r
+    CZipContextMenu::kCompressTo7zEmail,\r
+    L"CompressTo7zEmail",\r
+    IDS_CONTEXT_COMPRESS_TO_EMAIL,\r
+    IDS_CONTEXT_COMPRESS_TO_EMAIL_HELP,\r
+    0x02000113\r
+  },\r
+  {\r
+    NContextMenuFlags::kCompressToZip,\r
+    CZipContextMenu::kCompressToZip,\r
+    L"CompressToZip",\r
+    IDS_CONTEXT_COMPRESS_TO,\r
+    IDS_CONTEXT_COMPRESS_TO_HELP,\r
+    0x0200010F\r
+  },\r
+  {\r
+    NContextMenuFlags::kCompressToZipEmail,\r
+    CZipContextMenu::kCompressToZipEmail,\r
+    L"CompressToZipEmail",\r
+    IDS_CONTEXT_COMPRESS_TO_EMAIL,\r
+    IDS_CONTEXT_COMPRESS_TO_EMAIL_HELP,\r
+    0x02000113\r
+  }\r
+};\r
+\r
+static int FindCommand(CZipContextMenu::ECommandInternalID &id)\r
+{\r
+  for (int i = 0; i < sizeof(g_Commands) / sizeof(g_Commands[0]); i++)\r
+    if (g_Commands[i].CommandInternalID == id)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+void CZipContextMenu::FillCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &commandMapItem)\r
+{\r
+  int i = FindCommand(id);\r
+  if (i < 0)\r
+    return;\r
+  const CContextMenuCommand &command = g_Commands[i];\r
+  commandMapItem.CommandInternalID = command.CommandInternalID;\r
+  commandMapItem.Verb = (UString)kMainVerb + (UString)command.Verb;\r
+  commandMapItem.HelpString = LangString(command.ResourceHelpID, command.LangID + 1);\r
+  mainString = LangString(command.ResourceID, command.LangID);\r
+}\r
+\r
+static bool MyInsertMenu(CMenu &menu, int pos, UINT id, const UString &s)\r
+{\r
+  CMenuItem menuItem;\r
+  menuItem.fType = MFT_STRING;\r
+  menuItem.fMask = MIIM_TYPE | MIIM_ID;\r
+  menuItem.wID = id;\r
+  menuItem.StringValue = s;\r
+  return menu.InsertItem(pos, true, menuItem);\r
+}\r
+\r
+static const wchar_t *kArcExts[] =\r
+{\r
+  L"7z",\r
+  L"bz2",\r
+  L"gz",\r
+  L"rar",\r
+  L"zip"\r
+};\r
+\r
+static bool IsItArcExt(const UString &ext2)\r
+{\r
+  UString ext = ext2;\r
+  ext.MakeLower();\r
+  for (int i = 0; i < sizeof(kArcExts) / sizeof(kArcExts[0]); i++)\r
+    if (ext.Compare(kArcExts[i]) == 0)\r
+      return true;\r
+  return false;\r
+}\r
+\r
+static UString GetSubFolderNameForExtract(const UString &archiveName)\r
+{\r
+  int dotPos = archiveName.ReverseFind(L'.');\r
+  if (dotPos < 0)\r
+    return archiveName + UString(L"~");\r
+  const UString ext = archiveName.Mid(dotPos + 1);\r
+  UString res = archiveName.Left(dotPos);\r
+  res.TrimRight();\r
+  dotPos = res.ReverseFind(L'.');\r
+  if (dotPos > 0)\r
+  {\r
+    const UString ext2 = res.Mid(dotPos + 1);\r
+    if (ext.CompareNoCase(L"rar") == 0 &&\r
+        (ext2.CompareNoCase(L"part001") == 0 ||\r
+         ext2.CompareNoCase(L"part01") == 0 ||\r
+         ext2.CompareNoCase(L"part1") == 0) ||\r
+        IsItArcExt(ext2) && ext.CompareNoCase(L"001") == 0)\r
+      res = res.Left(dotPos);\r
+    res.TrimRight();\r
+  }\r
+  return GetCorrectFullFsPath(res);\r
+}\r
+\r
+static UString GetReducedString(const UString &s)\r
+{\r
+  const int kMaxSize = 64;\r
+  if (s.Length() < kMaxSize)\r
+    return s;\r
+  const int kFirstPartSize = kMaxSize / 2;\r
+  return s.Left(kFirstPartSize) + UString(L" ... ") + s.Right(kMaxSize - kFirstPartSize);\r
+}\r
+\r
+static UString GetQuotedReducedString(const UString &s)\r
+{\r
+  UString s2 = GetReducedString(s);\r
+  s2.Replace(L"&", L"&&");\r
+  return GetQuotedString(s2);\r
+}\r
+\r
+static const char *kExtractExludeExtensions =\r
+  " 3gp"\r
+  " aac ans ape asc asm asp aspx avi awk"\r
+  " bas bat bmp"\r
+  " c cs cls clw cmd cpp csproj css ctl cxx"\r
+  " def dep dlg dsp dsw"\r
+  " eps"\r
+  " f f77 f90 f95 fla flac frm"\r
+  " gif"\r
+  " h hpp hta htm html hxx"\r
+  " ico idl inc ini inl"\r
+  " java jpeg jpg js"\r
+  " la"\r
+  " mak manifest wmv mov mp3 mp4 mpe mpeg mpg m4a"\r
+  " ofr ogg"\r
+  " pac pas pdf php php3 php4 php5 phptml pl pm png ps py pyo"\r
+  " ra rb rc reg rka rm rtf"\r
+  " sed sh shn shtml sln sql srt swa"\r
+  " tcl tex tiff tta txt"\r
+  " vb vcproj vbs"\r
+  " wav wma wv"\r
+  " xml xsd xsl xslt"\r
+  " ";\r
+\r
+static const char *kNoOpenAsExtensions =\r
+  " 7z arj bz2 cab chm cpio dmg flv gz lha lzh lzma rar swm tar tbz2 tgz wim xar xz z zip ";\r
+\r
+static bool FindExt(const char *p, const UString &name)\r
+{\r
+  int extPos = name.ReverseFind('.');\r
+  if (extPos < 0)\r
+    return false;\r
+  UString ext = name.Mid(extPos + 1);\r
+  ext.MakeLower();\r
+  AString ext2 = UnicodeStringToMultiByte(ext);\r
+  for (int i = 0; p[i] != 0;)\r
+  {\r
+    int j;\r
+    for (j = i; p[j] != ' '; j++);\r
+    if (ext2.Length() == j - i && memcmp(p + i, (const char *)ext2, ext2.Length()) == 0)\r
+      return true;\r
+    i = j + 1;\r
+  }\r
+  return false;\r
+}\r
+\r
+static bool DoNeedExtract(const UString &name)\r
+{\r
+  return !FindExt(kExtractExludeExtensions, name);\r
+}\r
+\r
+STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,\r
+      UINT commandIDFirst, UINT commandIDLast, UINT flags)\r
+{\r
+  LoadLangOneTime();\r
+  if (_fileNames.Size() == 0)\r
+    return E_FAIL;\r
+  UINT currentCommandID = commandIDFirst;\r
+  if ((flags & 0x000F) != CMF_NORMAL  &&\r
+      (flags & CMF_VERBSONLY) == 0 &&\r
+      (flags & CMF_EXPLORE) == 0)\r
+    return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID);\r
+\r
+  _commandMap.Clear();\r
+\r
+  CMenu popupMenu;\r
+  CMenuDestroyer menuDestroyer;\r
+\r
+  CContextMenuInfo ci;\r
+  ci.Load();\r
+  MENUITEMINFO menuItem;\r
+  UINT subIndex = indexMenu;\r
+  if (ci.Cascaded)\r
+  {\r
+    CCommandMapItem commandMapItem;\r
+    if (!popupMenu.CreatePopup())\r
+      return E_FAIL;\r
+    menuDestroyer.Attach(popupMenu);\r
+    commandMapItem.CommandInternalID = kCommandNULL;\r
+    commandMapItem.Verb = kMainVerb;\r
+    commandMapItem.HelpString = LangString(IDS_CONTEXT_CAPTION_HELP, 0x02000102);\r
+    _commandMap.Add(commandMapItem);\r
+    \r
+    menuItem.wID = currentCommandID++;\r
+    subIndex = 0;\r
+  }\r
+  else\r
+  {\r
+    popupMenu.Attach(hMenu);\r
+  }\r
+\r
+  UInt32 contextMenuFlags = ci.Flags;\r
+\r
+  UString mainString;\r
+  if (_fileNames.Size() == 1 && currentCommandID + 6 <= commandIDLast)\r
+  {\r
+    const UString &fileName = _fileNames.Front();\r
+    UString folderPrefix;\r
+    NFile::NDirectory::GetOnlyDirPrefix(fileName, folderPrefix);\r
+   \r
+    NFile::NFind::CFileInfoW fileInfo;\r
+    if (!fileInfo.Find(fileName))\r
+      return E_FAIL;\r
+    if (!fileInfo.IsDir() && DoNeedExtract(fileInfo.Name))\r
+    {\r
+      // Open\r
+      bool thereIsMainOpenItem = ((contextMenuFlags & NContextMenuFlags::kOpen) != 0);\r
+      if (thereIsMainOpenItem)\r
+      {\r
+        CCommandMapItem commandMapItem;\r
+        FillCommand(kOpen, mainString, commandMapItem);\r
+        MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);\r
+        _commandMap.Add(commandMapItem);\r
+      }\r
+      if ((contextMenuFlags & NContextMenuFlags::kOpenAs) != 0 &&\r
+          (!thereIsMainOpenItem || !FindExt(kNoOpenAsExtensions, fileInfo.Name)))\r
+      {\r
+        CMenu subMenu;\r
+        if (subMenu.CreatePopup())\r
+        {\r
+          CCommandMapItem commandMapItem;\r
+          \r
+          CMenuItem menuItem;\r
+          menuItem.fType = MFT_STRING;\r
+          menuItem.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID;\r
+          menuItem.wID = currentCommandID++;\r
+          menuItem.hSubMenu = subMenu;\r
+          menuItem.StringValue = LangString(IDS_CONTEXT_OPEN, 0x02000103);\r
+          popupMenu.InsertItem(subIndex++, true, menuItem);\r
+          \r
+          commandMapItem.CommandInternalID = kCommandNULL;\r
+          commandMapItem.Verb = kMainVerb;\r
+          commandMapItem.HelpString = LangString(IDS_CONTEXT_OPEN_HELP, 0x02000104);\r
+          _commandMap.Add(commandMapItem);\r
+          \r
+          UINT subIndex2 = 0;\r
+          const wchar_t *exts[] = { L"", L"*", L"7z", L"zip", L"cab", L"rar" };\r
+          for (int i = (thereIsMainOpenItem ? 1 : 0); i < sizeof(exts) / sizeof(exts[0]); i++)\r
+          {\r
+            CCommandMapItem commandMapItem;\r
+            if (i == 0)\r
+              FillCommand(kOpen, mainString, commandMapItem);\r
+            else\r
+            {\r
+              mainString = exts[i];\r
+              commandMapItem.CommandInternalID = kOpen;\r
+              commandMapItem.Verb = (UString)kMainVerb + L".Open." + mainString;\r
+              commandMapItem.HelpString = mainString;\r
+              commandMapItem.ArcType = mainString;\r
+            }\r
+            MyInsertMenu(subMenu, subIndex2++, currentCommandID++, mainString);\r
+            _commandMap.Add(commandMapItem);\r
+          }\r
+          subMenu.Detach();\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (_fileNames.Size() > 0 && currentCommandID + 10 <= commandIDLast)\r
+  {\r
+    bool needExtract = false;\r
+    for(int i = 0; i < _fileNames.Size(); i++)\r
+    {\r
+      NFile::NFind::CFileInfoW fileInfo;\r
+      if (!fileInfo.Find(_fileNames[i]))\r
+        return E_FAIL;\r
+      if (!fileInfo.IsDir() && DoNeedExtract(fileInfo.Name))\r
+        needExtract = true;\r
+    }\r
+    const UString &fileName = _fileNames.Front();\r
+    if (needExtract)\r
+    {\r
+      UString folderPrefix;\r
+      NFile::NDirectory::GetOnlyDirPrefix(fileName, folderPrefix);\r
+      NFile::NFind::CFileInfoW fileInfo;\r
+      if (!fileInfo.Find(fileName))\r
+        return E_FAIL;\r
+      // Extract\r
+      if ((contextMenuFlags & NContextMenuFlags::kExtract) != 0)\r
+      {\r
+        CCommandMapItem commandMapItem;\r
+        FillCommand(kExtract, mainString, commandMapItem);\r
+        if (_dropMode)\r
+          commandMapItem.Folder = _dropPath;\r
+        else\r
+          commandMapItem.Folder = folderPrefix;\r
+        commandMapItem.Folder += GetSubFolderNameForExtract(fileInfo.Name) + UString(WCHAR_PATH_SEPARATOR);\r
+        MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);\r
+        _commandMap.Add(commandMapItem);\r
+      }\r
+\r
+      // Extract Here\r
+      if ((contextMenuFlags & NContextMenuFlags::kExtractHere) != 0)\r
+      {\r
+        CCommandMapItem commandMapItem;\r
+        FillCommand(kExtractHere, mainString, commandMapItem);\r
+        MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);\r
+        if (_dropMode)\r
+          commandMapItem.Folder = _dropPath;\r
+        else\r
+          commandMapItem.Folder = folderPrefix;\r
+        _commandMap.Add(commandMapItem);\r
+      }\r
+\r
+      // Extract To\r
+      if ((contextMenuFlags & NContextMenuFlags::kExtractTo) != 0)\r
+      {\r
+        CCommandMapItem commandMapItem;\r
+        UString s;\r
+        FillCommand(kExtractTo, s, commandMapItem);\r
+        UString folder;\r
+        if (_fileNames.Size() == 1)\r
+          folder = GetSubFolderNameForExtract(fileInfo.Name);\r
+        else\r
+          folder = L'*';\r
+        if (_dropMode)\r
+          commandMapItem.Folder = _dropPath;\r
+        else\r
+          commandMapItem.Folder = folderPrefix;\r
+        commandMapItem.Folder += folder;\r
+        s = MyFormatNew(s, GetQuotedReducedString(folder + UString(WCHAR_PATH_SEPARATOR)));\r
+        MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);\r
+        _commandMap.Add(commandMapItem);\r
+      }\r
+      // Test\r
+      if ((contextMenuFlags & NContextMenuFlags::kTest) != 0)\r
+      {\r
+        CCommandMapItem commandMapItem;\r
+        FillCommand(kTest, mainString, commandMapItem);\r
+        MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);\r
+        _commandMap.Add(commandMapItem);\r
+      }\r
+    }\r
+    UString archiveName = CreateArchiveName(fileName, _fileNames.Size() > 1, false);\r
+    UString archiveName7z = archiveName + L".7z";\r
+    UString archiveNameZip = archiveName + L".zip";\r
+    UString archivePathPrefix;\r
+    NFile::NDirectory::GetOnlyDirPrefix(fileName, archivePathPrefix);\r
+\r
+    // Compress\r
+    if ((contextMenuFlags & NContextMenuFlags::kCompress) != 0)\r
+    {\r
+      CCommandMapItem commandMapItem;\r
+      if (_dropMode)\r
+        commandMapItem.Folder = _dropPath;\r
+      else\r
+        commandMapItem.Folder = archivePathPrefix;\r
+      commandMapItem.ArcName = archiveName;\r
+      FillCommand(kCompress, mainString, commandMapItem);\r
+      MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);\r
+      _commandMap.Add(commandMapItem);\r
+    }\r
+\r
+    #ifdef EMAIL_SUPPORT\r
+    // CompressEmail\r
+    if ((contextMenuFlags & NContextMenuFlags::kCompressEmail) != 0 && !_dropMode)\r
+    {\r
+      CCommandMapItem commandMapItem;\r
+      commandMapItem.ArcName = archiveName;\r
+      FillCommand(kCompressEmail, mainString, commandMapItem);\r
+      MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);\r
+      _commandMap.Add(commandMapItem);\r
+    }\r
+    #endif\r
+\r
+    // CompressTo7z\r
+    if (contextMenuFlags & NContextMenuFlags::kCompressTo7z)\r
+    {\r
+      CCommandMapItem commandMapItem;\r
+      UString s;\r
+      FillCommand(kCompressTo7z, s, commandMapItem);\r
+      if (_dropMode)\r
+        commandMapItem.Folder = _dropPath;\r
+      else\r
+        commandMapItem.Folder = archivePathPrefix;\r
+      commandMapItem.ArcName = archiveName7z;\r
+      commandMapItem.ArcType = L"7z";\r
+      s = MyFormatNew(s, GetQuotedReducedString(archiveName7z));\r
+      MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);\r
+      _commandMap.Add(commandMapItem);\r
+    }\r
+\r
+    #ifdef EMAIL_SUPPORT\r
+    // CompressTo7zEmail\r
+    if ((contextMenuFlags & NContextMenuFlags::kCompressTo7zEmail) != 0  && !_dropMode)\r
+    {\r
+      CCommandMapItem commandMapItem;\r
+      UString s;\r
+      FillCommand(kCompressTo7zEmail, s, commandMapItem);\r
+      commandMapItem.ArcName = archiveName7z;\r
+      commandMapItem.ArcType = L"7z";\r
+      s = MyFormatNew(s, GetQuotedReducedString(archiveName7z));\r
+      MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);\r
+      _commandMap.Add(commandMapItem);\r
+    }\r
+    #endif\r
+\r
+    // CompressToZip\r
+    if (contextMenuFlags & NContextMenuFlags::kCompressToZip)\r
+    {\r
+      CCommandMapItem commandMapItem;\r
+      UString s;\r
+      FillCommand(kCompressToZip, s, commandMapItem);\r
+      if (_dropMode)\r
+        commandMapItem.Folder = _dropPath;\r
+      else\r
+        commandMapItem.Folder = archivePathPrefix;\r
+      commandMapItem.ArcName = archiveNameZip;\r
+      commandMapItem.ArcType = L"zip";\r
+      s = MyFormatNew(s, GetQuotedReducedString(archiveNameZip));\r
+      MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);\r
+      _commandMap.Add(commandMapItem);\r
+    }\r
+\r
+    #ifdef EMAIL_SUPPORT\r
+    // CompressToZipEmail\r
+    if ((contextMenuFlags & NContextMenuFlags::kCompressToZipEmail) != 0  && !_dropMode)\r
+    {\r
+      CCommandMapItem commandMapItem;\r
+      UString s;\r
+      FillCommand(kCompressToZipEmail, s, commandMapItem);\r
+      commandMapItem.ArcName = archiveNameZip;\r
+      commandMapItem.ArcType = L"zip";\r
+      s = MyFormatNew(s, GetQuotedReducedString(archiveNameZip));\r
+      MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);\r
+      _commandMap.Add(commandMapItem);\r
+    }\r
+    #endif\r
+  }\r
+\r
+\r
+  // don't use InsertMenu:  See MSDN:\r
+  // PRB: Duplicate Menu Items In the File Menu For a Shell Context Menu Extension\r
+  // ID: Q214477\r
+\r
+  if (ci.Cascaded)\r
+  {\r
+    CMenuItem menuItem;\r
+    menuItem.fType = MFT_STRING;\r
+    menuItem.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID;\r
+    menuItem.wID = currentCommandID++;\r
+    menuItem.hSubMenu = popupMenu.Detach();\r
+    menuDestroyer.Disable();\r
+    menuItem.StringValue = LangString(IDS_CONTEXT_POPUP_CAPTION, 0x02000101);\r
+    CMenu menu;\r
+    menu.Attach(hMenu);\r
+    menu.InsertItem(indexMenu++, true, menuItem);\r
+  }\r
+\r
+  return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID - commandIDFirst);\r
+}\r
+\r
+\r
+int CZipContextMenu::FindVerb(const UString &verb)\r
+{\r
+  for(int i = 0; i < _commandMap.Size(); i++)\r
+    if (_commandMap[i].Verb.Compare(verb) == 0)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+static UString Get7zFmPath()\r
+{\r
+  UString path;\r
+  GetProgramFolderPath(path);\r
+  return path + L"7zFM.exe";\r
+}\r
+\r
+STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo)\r
+{\r
+  // ::OutputDebugStringA("1");\r
+  int commandOffset;\r
+\r
+  // It's fix for bug: crashing in XP. See example in MSDN: "Creating Context Menu Handlers".\r
+\r
+  #ifndef UNDER_CE\r
+  if (commandInfo->cbSize == sizeof(CMINVOKECOMMANDINFOEX) &&\r
+      (commandInfo->fMask & CMIC_MASK_UNICODE) != 0)\r
+  {\r
+    LPCMINVOKECOMMANDINFOEX commandInfoEx = (LPCMINVOKECOMMANDINFOEX)commandInfo;\r
+    if (HIWORD(commandInfoEx->lpVerbW) == 0)\r
+      commandOffset = LOWORD(commandInfo->lpVerb);\r
+    else\r
+      commandOffset = FindVerb(commandInfoEx->lpVerbW);\r
+  }\r
+  else\r
+  #endif\r
+    if (HIWORD(commandInfo->lpVerb) == 0)\r
+      commandOffset = LOWORD(commandInfo->lpVerb);\r
+    else\r
+      commandOffset = FindVerb(GetUnicodeString(commandInfo->lpVerb));\r
+\r
+  if (commandOffset < 0 || commandOffset >= _commandMap.Size())\r
+    return E_FAIL;\r
+\r
+  const CCommandMapItem commandMapItem = _commandMap[commandOffset];\r
+  ECommandInternalID cmdID = commandMapItem.CommandInternalID;\r
+\r
+  try\r
+  {\r
+    switch(cmdID)\r
+    {\r
+      case kOpen:\r
+      {\r
+        UString params;\r
+        params = GetQuotedString(_fileNames[0]);\r
+        if (commandMapItem.ArcType)\r
+        {\r
+          params += L" -t";\r
+          params += commandMapItem.ArcType;\r
+        }\r
+        MyCreateProcess(Get7zFmPath(), params);\r
+        break;\r
+      }\r
+      case kExtract:\r
+      case kExtractHere:\r
+      case kExtractTo:\r
+      {\r
+        ExtractArchives(_fileNames, commandMapItem.Folder, (cmdID == kExtract));\r
+        break;\r
+      }\r
+      case kTest:\r
+      {\r
+        TestArchives(_fileNames);\r
+        break;\r
+      }\r
+      case kCompress:\r
+      case kCompressEmail:\r
+      case kCompressTo7z:\r
+      case kCompressTo7zEmail:\r
+      case kCompressToZip:\r
+      case kCompressToZipEmail:\r
+      {\r
+        bool email =\r
+            (cmdID == kCompressEmail) ||\r
+            (cmdID == kCompressTo7zEmail) ||\r
+            (cmdID == kCompressToZipEmail);\r
+        bool showDialog =\r
+            (cmdID == kCompress) ||\r
+            (cmdID == kCompressEmail);\r
+        CompressFiles(commandMapItem.Folder,\r
+            commandMapItem.ArcName, commandMapItem.ArcType,\r
+            _fileNames, email, showDialog, false);\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  catch(...)\r
+  {\r
+    ::MessageBoxW(0, L"Error", L"7-Zip", MB_ICONERROR);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+static void MyCopyString(void *dest, const wchar_t *src, bool writeInUnicode)\r
+{\r
+  if (writeInUnicode)\r
+  {\r
+    MyStringCopy((wchar_t *)dest, src);\r
+  }\r
+  else\r
+    MyStringCopy((char *)dest, (const char *)GetAnsiString(src));\r
+}\r
+\r
+STDMETHODIMP CZipContextMenu::GetCommandString(UINT_PTR commandOffset, UINT uType,\r
+    UINT * /* pwReserved */ , LPSTR pszName, UINT /* cchMax */)\r
+{\r
+  int cmdOffset = (int)commandOffset;\r
+  switch(uType)\r
+  {\r
+    #ifdef UNDER_CE\r
+    case GCS_VALIDATE:\r
+    #else\r
+    case GCS_VALIDATEA:\r
+    case GCS_VALIDATEW:\r
+    #endif\r
+      if (cmdOffset < 0 || cmdOffset >= _commandMap.Size())\r
+        return S_FALSE;\r
+      else\r
+        return S_OK;\r
+  }\r
+  if (cmdOffset < 0 || cmdOffset >= _commandMap.Size())\r
+    return E_FAIL;\r
+  #ifdef UNDER_CE\r
+  if (uType == GCS_HELPTEXT)\r
+  #else\r
+  if (uType == GCS_HELPTEXTA || uType == GCS_HELPTEXTW)\r
+  #endif\r
+  {\r
+    MyCopyString(pszName, _commandMap[cmdOffset].HelpString,\r
+      #ifdef UNDER_CE\r
+      true\r
+      #else\r
+      uType == GCS_HELPTEXTW\r
+      #endif\r
+      );\r
+    return NO_ERROR;\r
+  }\r
+  #ifdef UNDER_CE\r
+  if (uType == GCS_VERB)\r
+  #else\r
+  if (uType == GCS_VERBA || uType == GCS_VERBW)\r
+  #endif\r
+  {\r
+    MyCopyString(pszName, _commandMap[cmdOffset].Verb,\r
+      #ifdef UNDER_CE\r
+      true\r
+      #else\r
+      uType == GCS_VERBW\r
+      #endif\r
+      );\r
+    return NO_ERROR;\r
+  }\r
+  return E_FAIL;\r
+}\r
diff --git a/CPP/7zip/UI/Explorer/ContextMenu.h b/CPP/7zip/UI/Explorer/ContextMenu.h
new file mode 100755 (executable)
index 0000000..f6cb464
--- /dev/null
@@ -0,0 +1,70 @@
+// ContextMenu.h\r
+\r
+#ifndef __CONTEXT_MENU_H\r
+#define __CONTEXT_MENU_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+#include "../FileManager/MyCom2.h"\r
+\r
+class CZipContextMenu:\r
+  public IContextMenu,\r
+  public IShellExtInit,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+\r
+  enum ECommandInternalID\r
+  {\r
+    kCommandNULL,\r
+    kOpen,\r
+    kExtract,\r
+    kExtractHere,\r
+    kExtractTo,\r
+    kTest,\r
+    kCompress,\r
+    kCompressEmail,\r
+    kCompressTo7z,\r
+    kCompressTo7zEmail,\r
+    kCompressToZip,\r
+    kCompressToZipEmail\r
+  };\r
+  \r
+  MY_UNKNOWN_IMP2_MT(IContextMenu, IShellExtInit)\r
+\r
+  // IShellExtInit\r
+  STDMETHOD(Initialize)(LPCITEMIDLIST pidlFolder, LPDATAOBJECT dataObject, HKEY hkeyProgID);\r
+\r
+  // IContextMenu\r
+  STDMETHOD(QueryContextMenu)(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);\r
+  STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO lpici);\r
+  STDMETHOD(GetCommandString)(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax);\r
+\r
+  HRESULT InitContextMenu(const wchar_t *folder, const wchar_t **names, UINT32 numFiles);\r
+\r
+  CZipContextMenu();\r
+  ~CZipContextMenu();\r
+\r
+private:\r
+\r
+  struct CCommandMapItem\r
+  {\r
+    ECommandInternalID CommandInternalID;\r
+    UString Verb;\r
+    UString HelpString;\r
+    UString Folder;\r
+    UString ArcName;\r
+    UString ArcType;\r
+  };\r
+\r
+  UStringVector _fileNames;\r
+  bool _dropMode;\r
+  UString _dropPath;\r
+  CObjectVector<CCommandMapItem> _commandMap;\r
+\r
+  HRESULT GetFileNames(LPDATAOBJECT dataObject, UStringVector &fileNames);\r
+  int FindVerb(const UString &verb);\r
+  void FillCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &commandMapItem);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Explorer/ContextMenuFlags.h b/CPP/7zip/UI/Explorer/ContextMenuFlags.h
new file mode 100755 (executable)
index 0000000..19d1d12
--- /dev/null
@@ -0,0 +1,24 @@
+// ContextMenuFlags.h\r
+\r
+#ifndef __CONTEXT_MENU_FLAGS_H\r
+#define __CONTEXT_MENU_FLAGS_H\r
+\r
+namespace NContextMenuFlags\r
+{\r
+  const UInt32 kExtract = 1 << 0;\r
+  const UInt32 kExtractHere = 1 << 1;\r
+  const UInt32 kExtractTo = 1 << 2;\r
+\r
+  const UInt32 kTest = 1 << 4;\r
+  const UInt32 kOpen = 1 << 5;\r
+  const UInt32 kOpenAs = 1 << 6;\r
+\r
+  const UInt32 kCompress = 1 << 8;\r
+  const UInt32 kCompressTo7z = 1 << 9;\r
+  const UInt32 kCompressEmail = 1 << 10;\r
+  const UInt32 kCompressTo7zEmail = 1 << 11;\r
+  const UInt32 kCompressToZip = 1 << 12;\r
+  const UInt32 kCompressToZipEmail = 1 << 13;\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Explorer/DllExports.cpp b/CPP/7zip/UI/Explorer/DllExports.cpp
new file mode 100755 (executable)
index 0000000..4ad2863
--- /dev/null
@@ -0,0 +1,265 @@
+// DLLExports.cpp\r
+//\r
+// Notes:\r
+// Win2000:\r
+// If I register at HKCR\Folder\ShellEx then DLL is locked.\r
+// otherwise it unloads after explorer closing.\r
+// but if I call menu for desktop items it's locked all the time\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/MyInitGuid.h"\r
+\r
+#include <ShlGuid.h>\r
+#include <OleCtl.h>\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/DLL.h"\r
+#include "Windows/Error.h"\r
+#include "Windows/NtCheck.h"\r
+#include "Windows/Registry.h"\r
+\r
+#include "../FileManager/IFolder.h"\r
+#include "../FileManager/LangUtils.h"\r
+\r
+#include "ContextMenu.h"\r
+\r
+// {23170F69-40C1-278A-1000-000100020000}\r
+DEFINE_GUID(CLSID_CZipContextMenu,\r
+0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00);\r
+\r
+using namespace NWindows;\r
+\r
+HINSTANCE g_hInstance = 0;\r
+HWND g_HWND = 0;\r
+\r
+UString HResultToMessage(HRESULT errorCode)\r
+{\r
+  UString message;\r
+  if (!NError::MyFormatMessage(errorCode, message))\r
+    message.Empty();\r
+  if (message.IsEmpty())\r
+    message = L"Error";\r
+  return message;\r
+}\r
+\r
+LONG g_DllRefCount = 0; // Reference count of this DLL.\r
+\r
+static LPCWSTR kShellExtName = L"7-Zip Shell Extension";\r
+static LPCTSTR kClsidMask = TEXT("CLSID\\%s");\r
+static LPCTSTR kClsidInprocMask = TEXT("CLSID\\%s\\InprocServer32");\r
+static LPCTSTR kApprovedKeyPath = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved");\r
+\r
+// #define ODS(sz) OutputDebugString(L#sz)\r
+\r
+class CShellExtClassFactory:\r
+  public IClassFactory,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  CShellExtClassFactory() { InterlockedIncrement(&g_DllRefCount); }\r
+  ~CShellExtClassFactory() { InterlockedDecrement(&g_DllRefCount); }\r
+\r
+  MY_UNKNOWN_IMP1_MT(IClassFactory)\r
+  \r
+  STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, void**);\r
+  STDMETHODIMP LockServer(BOOL);\r
+};\r
+\r
+STDMETHODIMP CShellExtClassFactory::CreateInstance(LPUNKNOWN pUnkOuter,\r
+    REFIID riid, void **ppvObj)\r
+{\r
+  // ODS("CShellExtClassFactory::CreateInstance()\r\n");\r
+  *ppvObj = NULL;\r
+  if (pUnkOuter)\r
+    return CLASS_E_NOAGGREGATION;\r
+  \r
+  CZipContextMenu *shellExt;\r
+  try\r
+  {\r
+    shellExt = new CZipContextMenu();\r
+  }\r
+  catch(...) { return E_OUTOFMEMORY; }\r
+  if (shellExt == NULL)\r
+    return E_OUTOFMEMORY;\r
+  \r
+  HRESULT res = shellExt->QueryInterface(riid, ppvObj);\r
+  if (res != S_OK)\r
+    delete shellExt;\r
+  return res;\r
+}\r
+\r
+\r
+STDMETHODIMP CShellExtClassFactory::LockServer(BOOL /* fLock */)\r
+{\r
+  return S_OK; // Check it\r
+}\r
+\r
+\r
+#define NT_CHECK_FAIL_ACTION return FALSE;\r
+\r
+extern "C"\r
+BOOL WINAPI DllMain(\r
+  #ifdef UNDER_CE\r
+  HANDLE hInstance\r
+  #else\r
+  HINSTANCE hInstance\r
+  #endif\r
+  , DWORD dwReason, LPVOID)\r
+{\r
+  if (dwReason == DLL_PROCESS_ATTACH)\r
+  {\r
+    g_hInstance = (HINSTANCE)hInstance;\r
+    // ODS("In DLLMain, DLL_PROCESS_ATTACH\r\n");\r
+    NT_CHECK\r
+  }\r
+  else if (dwReason == DLL_PROCESS_DETACH)\r
+  {\r
+    // ODS("In DLLMain, DLL_PROCESS_DETACH\r\n");\r
+  }\r
+  return TRUE;\r
+}\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Used to determine whether the DLL can be unloaded by OLE\r
+\r
+STDAPI DllCanUnloadNow(void)\r
+{\r
+  // ODS("In DLLCanUnloadNow\r\n");\r
+  return (g_DllRefCount == 0 ? S_OK : S_FALSE);\r
+}\r
+\r
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)\r
+{\r
+  // ODS("In DllGetClassObject\r\n");\r
+  *ppv = NULL;\r
+  if (IsEqualIID(rclsid, CLSID_CZipContextMenu))\r
+  {\r
+    CShellExtClassFactory *cf;\r
+    try\r
+    {\r
+      cf = new CShellExtClassFactory;\r
+    }\r
+    catch(...) { return E_OUTOFMEMORY; }\r
+    if (cf == 0)\r
+      return E_OUTOFMEMORY;\r
+    HRESULT res = cf->QueryInterface(riid, ppv);\r
+    if (res != S_OK)\r
+      delete cf;\r
+    return res;\r
+  }\r
+  return CLASS_E_CLASSNOTAVAILABLE;\r
+  // return _Module.GetClassObject(rclsid, riid, ppv);\r
+}\r
+\r
+static BOOL GetStringFromIID(CLSID clsid, LPTSTR s, int size)\r
+{\r
+  LPWSTR pwsz;\r
+  if (StringFromIID(clsid, &pwsz) != S_OK)\r
+    return FALSE;\r
+  if (!pwsz)\r
+    return FALSE;\r
+  #ifdef UNICODE\r
+  for (int i = 0; i < size; i++)\r
+  {\r
+    s[i] = pwsz[i];\r
+    if (pwsz[i] == 0)\r
+      break;\r
+  }\r
+  s[size - 1] = 0;\r
+  #else\r
+  WideCharToMultiByte(CP_ACP, 0, pwsz, -1, s, size, NULL, NULL);\r
+  #endif\r
+  CoTaskMemFree(pwsz);\r
+  s[size - 1] = 0;\r
+  return TRUE;\r
+}\r
+\r
+typedef struct\r
+{\r
+  HKEY hRootKey;\r
+  LPCTSTR SubKey;\r
+  LPCWSTR ValueName;\r
+  LPCWSTR Data;\r
+} CRegItem;\r
+\r
+static BOOL RegisterServer(CLSID clsid, LPCWSTR title)\r
+{\r
+  TCHAR clsidString[MAX_PATH];\r
+  if (!GetStringFromIID(clsid, clsidString, MAX_PATH))\r
+    return FALSE;\r
+  \r
+  UString modulePath;\r
+  if (!NDLL::MyGetModuleFileName(g_hInstance, modulePath))\r
+    return FALSE;\r
+  \r
+  CRegItem clsidEntries[] =\r
+  {\r
+    HKEY_CLASSES_ROOT, kClsidMask,        NULL,              title,\r
+    HKEY_CLASSES_ROOT, kClsidInprocMask,  NULL,              modulePath,\r
+    HKEY_CLASSES_ROOT, kClsidInprocMask,  L"ThreadingModel", L"Apartment",\r
+    NULL,              NULL,              NULL,              NULL\r
+  };\r
+  \r
+  //register the CLSID entries\r
+  for (int i = 0; clsidEntries[i].hRootKey; i++)\r
+  {\r
+    TCHAR subKey[MAX_PATH];\r
+    const CRegItem &r = clsidEntries[i];\r
+    wsprintf(subKey, r.SubKey, clsidString);\r
+    NRegistry::CKey key;\r
+    if (key.Create(r.hRootKey, subKey, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE) != NOERROR)\r
+      return FALSE;\r
+    key.SetValue(clsidEntries[i].ValueName, clsidEntries[i].Data);\r
+  }\r
\r
+  #if !defined(_WIN64) && !defined(UNDER_CE)\r
+  if (IsItWindowsNT())\r
+  #endif\r
+  {\r
+    NRegistry::CKey key;\r
+    if (key.Create(HKEY_LOCAL_MACHINE, kApprovedKeyPath, NULL,\r
+        REG_OPTION_NON_VOLATILE, KEY_WRITE) == NOERROR)\r
+      key.SetValue(GetUnicodeString(clsidString), title);\r
+  }\r
+  return TRUE;\r
+}\r
+\r
+STDAPI DllRegisterServer(void)\r
+{\r
+  return RegisterServer(CLSID_CZipContextMenu, kShellExtName) ?  S_OK: SELFREG_E_CLASS;\r
+}\r
+\r
+static BOOL UnregisterServer(CLSID clsid)\r
+{\r
+  TCHAR clsidString[MAX_PATH];\r
+  if (!GetStringFromIID(clsid, clsidString, MAX_PATH))\r
+    return FALSE;\r
+\r
+  TCHAR subKey[MAX_PATH];\r
+  wsprintf(subKey, kClsidInprocMask, clsidString);\r
+  RegDeleteKey(HKEY_CLASSES_ROOT, subKey);\r
+  \r
+  wsprintf (subKey, kClsidMask, clsidString);\r
+  RegDeleteKey(HKEY_CLASSES_ROOT, subKey);\r
+\r
+  #if !defined(_WIN64) && !defined(UNDER_CE)\r
+  if (IsItWindowsNT())\r
+  #endif\r
+  {\r
+    HKEY hKey;\r
+    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, kApprovedKeyPath, 0, KEY_SET_VALUE, &hKey) == NOERROR)\r
+    {\r
+      RegDeleteValue(hKey, clsidString);\r
+      RegCloseKey(hKey);\r
+    }\r
+  }\r
+  return TRUE;\r
+}\r
+\r
+STDAPI DllUnregisterServer(void)\r
+{\r
+  return UnregisterServer(CLSID_CZipContextMenu) ? S_OK: SELFREG_E_CLASS;\r
+}\r
diff --git a/CPP/7zip/UI/Explorer/Explorer.def b/CPP/7zip/UI/Explorer/Explorer.def
new file mode 100755 (executable)
index 0000000..5374c37
--- /dev/null
@@ -0,0 +1,9 @@
+; 7-zip.def\r
+\r
+LIBRARY "7-zip"\r
+\r
+EXPORTS\r
+  DllCanUnloadNow PRIVATE\r
+  DllGetClassObject PRIVATE\r
+  DllRegisterServer PRIVATE\r
+  DllUnregisterServer PRIVATE\r
diff --git a/CPP/7zip/UI/Explorer/Explorer.dsp b/CPP/7zip/UI/Explorer/Explorer.dsp
new file mode 100755 (executable)
index 0000000..e8fbc3a
--- /dev/null
@@ -0,0 +1,558 @@
+# Microsoft Developer Studio Project File - Name="Explorer" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
+\r
+CFG=Explorer - Win32 DebugU\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "Explorer.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "Explorer.mak" CFG="Explorer - Win32 DebugU"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "Explorer - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE "Explorer - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE "Explorer - Win32 ReleaseU" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE "Explorer - Win32 DebugU" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+MTL=midl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "Explorer - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 1\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXPLORER_EXPORTS" /YX /FD /c\r
+# 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\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /opt:NOWIN98\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "Explorer - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 1\r
+# PROP Target_Dir ""\r
+# 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\r
+# 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\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x419 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /pdbtype:sept\r
+\r
+!ELSEIF  "$(CFG)" == "Explorer - Win32 ReleaseU"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "ReleaseU"\r
+# PROP BASE Intermediate_Dir "ReleaseU"\r
+# PROP BASE Ignore_Export_Lib 1\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "ReleaseU"\r
+# PROP Intermediate_Dir "ReleaseU"\r
+# PROP Ignore_Export_Lib 1\r
+# PROP Target_Dir ""\r
+# 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\r
+# 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\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /opt:NOWIN98\r
+# SUBTRACT BASE LINK32 /pdb:none\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zipn.dll" /opt:NOWIN98\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "Explorer - Win32 DebugU"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "DebugU"\r
+# PROP BASE Intermediate_Dir "DebugU"\r
+# PROP BASE Ignore_Export_Lib 1\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "DebugU"\r
+# PROP Intermediate_Dir "DebugU"\r
+# PROP Ignore_Export_Lib 1\r
+# PROP Target_Dir ""\r
+# 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\r
+# 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\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x419 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "Explorer - Win32 Release"\r
+# Name "Explorer - Win32 Debug"\r
+# Name "Explorer - Win32 ReleaseU"\r
+# Name "Explorer - Win32 DebugU"\r
+# Begin Group "Spec"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\DllExports.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Explorer.def\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\resource.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\resource.rc\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.cpp\r
+# ADD CPP /Yc"StdAfx.h"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "UI Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\CompressCall.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\CompressCall.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ExtractingFilePath.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ExtractingFilePath.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ZipRegistry.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ZipRegistry.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Engine"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\ContextMenu.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ContextMenu.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\MyMessages.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\MyMessages.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "FileManager"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\FormatUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\FormatUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\HelpUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\HelpUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\IFolder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\LangUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\LangUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\ProgramLocation.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\ProgramLocation.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\RegistryUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\RegistryUtils.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "C"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Lang.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Lang.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyCom.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Random.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Random.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringToInt.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringToInt.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\TextConfig.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\TextConfig.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Types.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\UTFConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\UTFConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Windows"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "Control"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Dialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Dialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ListView.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ListView.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\PropertyPage.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\PropertyPage.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileMapping.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Memory.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Memory.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Menu.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Menu.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Process.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Process.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Registry.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Registry.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\ResourceString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\ResourceString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Shell.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Shell.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Window.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Window.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=".\7-zip.dll.manifest"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ContextMenuFlags.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\RegistryContextMenu.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\RegistryContextMenu.h\r
+# End Source File\r
+# End Target\r
+# End Project\r
diff --git a/CPP/7zip/UI/Explorer/Explorer.dsw b/CPP/7zip/UI/Explorer/Explorer.dsw
new file mode 100755 (executable)
index 0000000..38275b1
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "Explorer"=".\Explorer.dsp" - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/CPP/7zip/UI/Explorer/MyMessages.cpp b/CPP/7zip/UI/Explorer/MyMessages.cpp
new file mode 100755 (executable)
index 0000000..b8dc9dc
--- /dev/null
@@ -0,0 +1,58 @@
+// MyMessages.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "MyMessages.h"\r
+\r
+#include "Windows/Error.h"\r
+#include "Windows/ResourceString.h"\r
+\r
+#ifdef LANG\r
+#include "../FileManager/LangUtils.h"\r
+#endif\r
+\r
+using namespace NWindows;\r
+\r
+void ShowErrorMessage(HWND window, LPCWSTR message)\r
+{\r
+  ::MessageBoxW(window, message, L"7-Zip", MB_OK | MB_ICONSTOP);\r
+}\r
+\r
+void ShowErrorMessageHwndRes(HWND window, UINT resID\r
+    #ifdef LANG\r
+    , UInt32 langID\r
+    #endif\r
+    )\r
+{\r
+  ShowErrorMessage(window,\r
+  #ifdef LANG\r
+  LangString(resID, langID)\r
+  #else\r
+  MyLoadStringW(resID)\r
+  #endif\r
+  );\r
+}\r
+\r
+void ShowErrorMessageRes(UINT resID\r
+    #ifdef LANG\r
+    , UInt32 langID\r
+    #endif\r
+    )\r
+{\r
+  ShowErrorMessageHwndRes(0, resID\r
+  #ifdef LANG\r
+  , langID\r
+  #endif\r
+  );\r
+}\r
+\r
+void ShowErrorMessageDWORD(HWND window, DWORD errorCode)\r
+{\r
+  ShowErrorMessage(window, NError::MyFormatMessageW(errorCode));\r
+}\r
+\r
+void ShowLastErrorMessage(HWND window)\r
+{\r
+  ShowErrorMessageDWORD(window, ::GetLastError());\r
+}\r
+\r
diff --git a/CPP/7zip/UI/Explorer/MyMessages.h b/CPP/7zip/UI/Explorer/MyMessages.h
new file mode 100755 (executable)
index 0000000..3d38562
--- /dev/null
@@ -0,0 +1,28 @@
+// MyMessages.h\r
+\r
+#ifndef __MYMESSAGES_H\r
+#define __MYMESSAGES_H\r
+\r
+#include "Common/MyString.h"\r
+#include "Common/Types.h"\r
+\r
+void ShowErrorMessage(HWND window, LPCWSTR message);\r
+inline void ShowErrorMessage(LPCWSTR message) { ShowErrorMessage(0, message); }\r
+\r
+void ShowErrorMessageHwndRes(HWND window, UINT resID\r
+    #ifdef LANG\r
+    , UInt32 langID\r
+    #endif\r
+    );\r
+\r
+void ShowErrorMessageRes(UINT resID\r
+    #ifdef LANG\r
+    , UInt32 langID\r
+    #endif\r
+    );\r
+\r
+// void ShowErrorMessageDWORD(HWND window, DWORD errorCode);\r
+// inline void ErrorMessageDWORD(DWORD errorCode) { ShowErrorMessageDWORD(0, errorCode); }\r
+void ShowLastErrorMessage(HWND window = 0);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Explorer/OptionsDialog.cpp b/CPP/7zip/UI/Explorer/OptionsDialog.cpp
new file mode 100755 (executable)
index 0000000..1c97a1d
--- /dev/null
@@ -0,0 +1,71 @@
+// OptionsDialog.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/Control/PropertyPage.h"\r
+\r
+#include "../FileManager/DialogSize.h"\r
+#include "../FileManager/LangUtils.h"\r
+\r
+#include "FoldersPage.h"\r
+#include "FoldersPageRes.h"\r
+#include "OptionsDialog.h"\r
+#include "MenuPage.h"\r
+#include "MenuPageRes.h"\r
+\r
+#include "resource.h"\r
+\r
+using namespace NWindows;\r
+\r
+static INT_PTR OptionsDialog(HWND hwndOwner)\r
+{\r
+  CMenuPage systemPage;\r
+  CFoldersPage foldersPage;\r
+  UINT32 langIDs[] = { 0x01000300, 0x01000200};\r
+\r
+  BIG_DIALOG_SIZE(200, 200);\r
+  UINT pageIDs[] = { SIZED_DIALOG(IDD_MENU), SIZED_DIALOG(IDD_FOLDERS) };\r
+  NControl::CPropertyPage *pagePinters[] = { &systemPage, &foldersPage };\r
+  CObjectVector<NControl::CPageInfo> pages;\r
+  const int kNumPages = sizeof(langIDs) / sizeof(langIDs[0]);\r
+  for (int i = 0; i < kNumPages; i++)\r
+  {\r
+    NControl::CPageInfo page;\r
+    page.Title = LangString(langIDs[i]);\r
+    page.ID = pageIDs[i];\r
+    page.Page = pagePinters[i];\r
+    pages.Add(page);\r
+  }\r
+  return NControl::MyPropertySheet(pages, hwndOwner,\r
+    LangString(IDS_CONFIG_DIALOG_CAPTION, 0x01000000));\r
+}\r
+\r
+STDMETHODIMP CSevenZipOptions::PluginOptions(HWND hWnd,\r
+    IPluginOptionsCallback * /* callback */)\r
+{\r
+  /*\r
+  CComBSTR programPath;\r
+  RINOK(callback->GetProgramPath(programName)));\r
+  */\r
+  OptionsDialog(hWnd);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CSevenZipOptions::GetFileExtensions(BSTR * /* extensions */)\r
+{\r
+  /*\r
+  UString extStrings;\r
+  CObjectVector<NZipRootRegistry::CArchiverInfo> formats;\r
+  NZipRootRegistry::ReadArchiverInfoList(formats);\r
+  for(int i = 0; i < formats.Size(); i++)\r
+  {\r
+    if (i != 0)\r
+      extStrings += L' ';\r
+    extStrings += formats[i].Extension;\r
+  }\r
+  CComBSTR valueTemp = extStrings;\r
+  *extensions = valueTemp.Detach();\r
+  return S_OK;\r
+  */\r
+  return E_NOTIMPL;\r
+}\r
diff --git a/CPP/7zip/UI/Explorer/OptionsDialog.h b/CPP/7zip/UI/Explorer/OptionsDialog.h
new file mode 100755 (executable)
index 0000000..e39d457
--- /dev/null
@@ -0,0 +1,23 @@
+// OptionsDialog.h\r
+\r
+#ifndef __SEVENZIP_OPTIONSDIALOG_H\r
+#define __SEVENZIP_OPTIONSDIALOG_H\r
+\r
+#include "../FileManager/PluginInterface.h"\r
+#include "Common/MyCom.h"\r
+\r
+// {23170F69-40C1-278D-1000-000100020000}\r
+DEFINE_GUID(CLSID_CSevenZipOptions,\r
+  0x23170F69, 0x40C1, 0x278D, 0x10, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00);\r
+\r
+class CSevenZipOptions:\r
+  public IPluginOptions,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP\r
+  STDMETHOD(PluginOptions)(HWND hWnd, IPluginOptionsCallback *callback);\r
+  STDMETHOD(GetFileExtensions)(BSTR *extensions);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp b/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp
new file mode 100755 (executable)
index 0000000..f3322c7
--- /dev/null
@@ -0,0 +1,116 @@
+// RegistryContextMenu.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/Registry.h"\r
+#include "Windows/Synchronization.h"\r
+\r
+#include "RegistryContextMenu.h"\r
+\r
+using namespace NWindows;\r
+using namespace NRegistry;\r
+\r
+namespace NZipRootRegistry {\r
+  \r
+#ifndef UNDER_CE\r
+\r
+static NSynchronization::CCriticalSection g_CS;\r
+  \r
+static const TCHAR *kContextMenuKeyName  = TEXT("\\shellex\\ContextMenuHandlers\\7-Zip");\r
+static const TCHAR *kDragDropMenuKeyName = TEXT("\\shellex\\DragDropHandlers\\7-Zip");\r
+\r
+static const TCHAR *kExtensionCLSID = TEXT("{23170F69-40C1-278A-1000-000100020000}");\r
+\r
+static const TCHAR *kRootKeyNameForFile = TEXT("*");\r
+static const TCHAR *kRootKeyNameForFolder = TEXT("Folder");\r
+static const TCHAR *kRootKeyNameForDirectory = TEXT("Directory");\r
+static const TCHAR *kRootKeyNameForDrive = TEXT("Drive");\r
+\r
+static CSysString GetFullContextMenuKeyName(const CSysString &keyName)\r
+  { return (keyName + kContextMenuKeyName); }\r
+\r
+static CSysString GetFullDragDropMenuKeyName(const CSysString &keyName)\r
+  { return (keyName + kDragDropMenuKeyName); }\r
+\r
+static bool CheckHandlerCommon(const CSysString &keyName)\r
+{\r
+  NSynchronization::CCriticalSectionLock lock(g_CS);\r
+  CKey key;\r
+  if (key.Open(HKEY_CLASSES_ROOT, keyName, KEY_READ) != ERROR_SUCCESS)\r
+    return false;\r
+  CSysString value;\r
+  if (key.QueryValue(NULL, value) != ERROR_SUCCESS)\r
+    return false;\r
+  value.MakeUpper();\r
+  return (value.Compare(kExtensionCLSID) == 0);\r
+}\r
+\r
+bool CheckContextMenuHandler()\r
+{\r
+  return\r
+    // CheckHandlerCommon(GetFullContextMenuKeyName(kRootKeyNameForFolder)) &&\r
+    CheckHandlerCommon(GetFullContextMenuKeyName(kRootKeyNameForDirectory))  &&\r
+    CheckHandlerCommon(GetFullContextMenuKeyName(kRootKeyNameForFile)) &&\r
+    CheckHandlerCommon(GetFullDragDropMenuKeyName(kRootKeyNameForDirectory))  &&\r
+    CheckHandlerCommon(GetFullDragDropMenuKeyName(kRootKeyNameForDrive));\r
+}\r
+\r
+static void DeleteContextMenuHandlerCommon(const CSysString &keyName)\r
+{\r
+  CKey rootKey;\r
+  rootKey.Attach(HKEY_CLASSES_ROOT);\r
+  rootKey.RecurseDeleteKey(GetFullContextMenuKeyName(keyName));\r
+  rootKey.Detach();\r
+}\r
+\r
+static void DeleteDragDropMenuHandlerCommon(const CSysString &keyName)\r
+{\r
+  CKey rootKey;\r
+  rootKey.Attach(HKEY_CLASSES_ROOT);\r
+  rootKey.RecurseDeleteKey(GetFullDragDropMenuKeyName(keyName));\r
+  rootKey.Detach();\r
+}\r
+\r
+void DeleteContextMenuHandler()\r
+{\r
+  DeleteContextMenuHandlerCommon(kRootKeyNameForFile);\r
+  DeleteContextMenuHandlerCommon(kRootKeyNameForFolder);\r
+  DeleteContextMenuHandlerCommon(kRootKeyNameForDirectory);\r
+  DeleteContextMenuHandlerCommon(kRootKeyNameForDrive);\r
+  DeleteDragDropMenuHandlerCommon(kRootKeyNameForFile);\r
+  DeleteDragDropMenuHandlerCommon(kRootKeyNameForFolder);\r
+  DeleteDragDropMenuHandlerCommon(kRootKeyNameForDirectory);\r
+  DeleteDragDropMenuHandlerCommon(kRootKeyNameForDrive);\r
+}\r
+\r
+static void AddContextMenuHandlerCommon(const CSysString &keyName)\r
+{\r
+  DeleteContextMenuHandlerCommon(keyName);\r
+  NSynchronization::CCriticalSectionLock lock(g_CS);\r
+  CKey key;\r
+  key.Create(HKEY_CLASSES_ROOT, GetFullContextMenuKeyName(keyName));\r
+  key.SetValue(NULL, kExtensionCLSID);\r
+}\r
+\r
+static void AddDragDropMenuHandlerCommon(const CSysString &keyName)\r
+{\r
+  DeleteDragDropMenuHandlerCommon(keyName);\r
+  NSynchronization::CCriticalSectionLock lock(g_CS);\r
+  CKey key;\r
+  key.Create(HKEY_CLASSES_ROOT, GetFullDragDropMenuKeyName(keyName));\r
+  key.SetValue(NULL, kExtensionCLSID);\r
+}\r
+\r
+void AddContextMenuHandler()\r
+{\r
+  AddContextMenuHandlerCommon(kRootKeyNameForFile);\r
+  // AddContextMenuHandlerCommon(kRootKeyNameForFolder);\r
+  AddContextMenuHandlerCommon(kRootKeyNameForDirectory);\r
+\r
+  AddDragDropMenuHandlerCommon(kRootKeyNameForDirectory);\r
+  AddDragDropMenuHandlerCommon(kRootKeyNameForDrive);\r
+}\r
+\r
+#endif\r
+\r
+}\r
diff --git a/CPP/7zip/UI/Explorer/RegistryContextMenu.h b/CPP/7zip/UI/Explorer/RegistryContextMenu.h
new file mode 100755 (executable)
index 0000000..5ea0fda
--- /dev/null
@@ -0,0 +1,16 @@
+// RegistryContextMenu.h\r
+\r
+#ifndef __REGISTRY_CONTEXT_MENU_H\r
+#define __REGISTRY_CONTEXT_MENU_H\r
+\r
+namespace NZipRootRegistry {\r
+\r
+#ifndef UNDER_CE\r
+  bool CheckContextMenuHandler();\r
+  void AddContextMenuHandler();\r
+  void DeleteContextMenuHandler();\r
+#endif\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Explorer/StdAfx.cpp b/CPP/7zip/UI/Explorer/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..2b852f2
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "stdafx.h"\r
diff --git a/CPP/7zip/UI/Explorer/StdAfx.h b/CPP/7zip/UI/Explorer/StdAfx.h
new file mode 100755 (executable)
index 0000000..b636632
--- /dev/null
@@ -0,0 +1,24 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#define _WIN32_WINNT 0x0400\r
+// it's hack for Windows NT supporting\r
+#define WINVER 0x0400\r
+\r
+// #define _WIN32_IE 0x0500\r
+#include <windows.h>\r
+#include <CommCtrl.h>\r
+#include <shlobj.h>\r
+#include <tchar.h>\r
+\r
+#include <stddef.h>\r
+#include <string.h>\r
+#include <wchar.h>\r
+\r
+#include <shlguid.h>\r
+\r
+#include "Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Explorer/makefile b/CPP/7zip/UI/Explorer/makefile
new file mode 100755 (executable)
index 0000000..33787ac
--- /dev/null
@@ -0,0 +1,101 @@
+PROG = 7-zip.dll\r
+DEF_FILE = Explorer.def\r
+CFLAGS = $(CFLAGS) -I ../../../ \\r
+  -DLANG \\r
+\r
+!IFDEF UNDER_CE\r
+LIBS = $(LIBS) Commctrl.lib\r
+!ELSE\r
+LIBS = $(LIBS) comctl32.lib htmlhelp.lib comdlg32.lib Mpr.lib Gdi32.lib\r
+CFLAGS = $(CFLAGS) -DWIN_LONG_PATH\r
+!ENDIF\r
+\r
+EXPLORER_OBJS = \\r
+  $O\DllExports.obj \\r
+  $O\ContextMenu.obj \\r
+  $O\MyMessages.obj \\r
+  $O\RegistryContextMenu.obj \\r
+\r
+COMMON_OBJS = \\r
+  $O\IntToString.obj \\r
+  $O\Lang.obj \\r
+  $O\MyString.obj \\r
+  $O\MyVector.obj \\r
+  $O\NewHandler.obj \\r
+  $O\Random.obj \\r
+  $O\StringConvert.obj \\r
+  $O\StringToInt.obj \\r
+  $O\TextConfig.obj \\r
+  $O\UTFConvert.obj \\r
+  $O\Wildcard.obj \\r
+\r
+WIN_OBJS = \\r
+  $O\DLL.obj \\r
+  $O\Error.obj \\r
+  $O\FileDir.obj \\r
+  $O\FileFind.obj \\r
+  $O\FileIO.obj \\r
+  $O\FileName.obj \\r
+  $O\Menu.obj \\r
+  $O\Process.obj \\r
+  $O\Registry.obj \\r
+  $O\ResourceString.obj \\r
+  $O\Shell.obj \\r
+  $O\Synchronization.obj \\r
+  $O\Window.obj \\r
+\r
+!IFDEF UNDER_CE\r
+\r
+WIN_OBJS = $(WIN_OBJS) \\r
+  $O\CommonDialog.obj \\r
+\r
+!ENDIF\r
+\r
+WIN_CTRL_OBJS = \\r
+  $O\Dialog.obj \\r
+  $O\ListView.obj \\r
+  $O\PropertyPage.obj \\r
+\r
+UI_COMMON_OBJS = \\r
+  $O\ArchiveName.obj \\r
+  $O\CompressCall.obj \\r
+  $O\ExtractingFilePath.obj \\r
+  $O\ZipRegistry.obj \\r
+\r
+FM_COMMON_OBJS = \\r
+  $O\FormatUtils.obj \\r
+  $O\HelpUtils.obj \\r
+  $O\LangUtils.obj \\r
+  $O\ProgramLocation.obj \\r
+  $O\RegistryUtils.obj \\r
+\r
+C_OBJS = \\r
+  $O\Threads.obj \\r
+\r
+OBJS = \\r
+  $O\StdAfx.obj \\r
+  $(EXPLORER_OBJS) \\r
+  $(COMMON_OBJS) \\r
+  $(WIN_OBJS) \\r
+  $(WIN_CTRL_OBJS) \\r
+  $(UI_COMMON_OBJS) \\r
+  $(FM_COMMON_OBJS)\\r
+  $(C_OBJS) \\r
+  $O\resource.res\r
+\r
+!include "../../../Build.mak"\r
+\r
+$(EXPLORER_OBJS): $(*B).cpp\r
+       $(COMPL)\r
+$(COMMON_OBJS): ../../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_OBJS): ../../../Windows/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp\r
+       $(COMPL)\r
+$(UI_COMMON_OBJS): ../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(FM_COMMON_OBJS): ../FileManager/$(*B).cpp\r
+       $(COMPL)\r
+$(C_OBJS): ../../../../C/$(*B).c\r
+       $(COMPL_O2)\r
diff --git a/CPP/7zip/UI/Explorer/resource.h b/CPP/7zip/UI/Explorer/resource.h
new file mode 100755 (executable)
index 0000000..f3446df
--- /dev/null
@@ -0,0 +1,28 @@
+#define IDS_CONTEXT_EXTRACT             142\r
+#define IDS_CONTEXT_EXTRACT_HELP        143\r
+#define IDS_CONTEXT_COMPRESS            144\r
+#define IDS_CONTEXT_COMPRESS_HELP       145\r
+#define IDS_CONTEXT_OPEN                146\r
+#define IDS_CONTEXT_OPEN_HELP           147\r
+#define IDS_CONTEXT_TEST                148\r
+#define IDS_CONTEXT_TEST_HELP           149\r
+#define IDS_CONTEXT_CAPTION_HELP        150\r
+#define IDS_CONTEXT_POPUP_CAPTION       151\r
+                                   \r
+#define IDS_CONTEXT_EXTRACT_HERE           152\r
+#define IDS_CONTEXT_EXTRACT_HERE_HELP      153\r
+\r
+#define IDS_CONTEXT_EXTRACT_TO           154\r
+#define IDS_CONTEXT_EXTRACT_TO_HELP      155\r
+\r
+#define IDS_CONTEXT_COMPRESS_TO          156\r
+#define IDS_CONTEXT_COMPRESS_TO_HELP     157\r
+\r
+#define IDS_CONTEXT_COMPRESS_EMAIL       158\r
+#define IDS_CONTEXT_COMPRESS_EMAIL_HELP  159\r
+\r
+#define IDS_CONTEXT_COMPRESS_TO_EMAIL       160\r
+#define IDS_CONTEXT_COMPRESS_TO_EMAIL_HELP  161\r
+\r
+#define IDS_CONTEXT_FOLDER  170\r
+#define IDS_CONTEXT_ARCHIVE 171\r
diff --git a/CPP/7zip/UI/Explorer/resource.rc b/CPP/7zip/UI/Explorer/resource.rc
new file mode 100755 (executable)
index 0000000..684eb6e
--- /dev/null
@@ -0,0 +1,8 @@
+#include "../../MyVersionInfo.rc"\r
+#include "resource2.rc"\r
+\r
+MY_VERSION_INFO_DLL("7-Zip Shell Extension", "7-zip")\r
+\r
+#ifndef UNDER_CE\r
+1 24 MOVEABLE PURE "7-zip.dll.manifest"\r
+#endif\r
diff --git a/CPP/7zip/UI/Explorer/resource2.rc b/CPP/7zip/UI/Explorer/resource2.rc
new file mode 100755 (executable)
index 0000000..eddfe60
--- /dev/null
@@ -0,0 +1,27 @@
+#include "resource.h"\r
+\r
+STRINGTABLE\r
+BEGIN\r
+  IDS_CONTEXT_EXTRACT     "Extract files..."\r
+  IDS_CONTEXT_EXTRACT_HELP "Extracts files from the selected archive."\r
+  IDS_CONTEXT_COMPRESS    "Add to archive..."\r
+  IDS_CONTEXT_COMPRESS_HELP "Adds the selected items to archive."\r
+  IDS_CONTEXT_OPEN        "Open archive"\r
+  IDS_CONTEXT_OPEN_HELP   "Opens the selected archive."\r
+  IDS_CONTEXT_TEST        "Test archive"\r
+  IDS_CONTEXT_TEST_HELP   "Tests integrity of the selected archive."\r
+  IDS_CONTEXT_CAPTION_HELP "7-Zip commands"\r
+  IDS_CONTEXT_POPUP_CAPTION "7-Zip"\r
+  IDS_CONTEXT_EXTRACT_HERE "Extract Here"\r
+  IDS_CONTEXT_EXTRACT_HERE_HELP "Extracts files from the selected archive to current folder."\r
+  IDS_CONTEXT_EXTRACT_TO  "Extract to {0}"\r
+  IDS_CONTEXT_EXTRACT_TO_HELP "Extracts files to subfolder."\r
+  IDS_CONTEXT_COMPRESS_TO "Add to {0}"\r
+  IDS_CONTEXT_COMPRESS_TO_HELP "Adds the selected items to archive."\r
+  IDS_CONTEXT_COMPRESS_EMAIL "Compress and email..."\r
+  IDS_CONTEXT_COMPRESS_EMAIL_HELP "Compresses the selected items to archive and sends archive via email."\r
+  IDS_CONTEXT_COMPRESS_TO_EMAIL "Compress to {0} and email"\r
+  IDS_CONTEXT_COMPRESS_TO_EMAIL_HELP "Compresses the selected items to archive and sends archive via email."\r
+  IDS_CONTEXT_FOLDER      "<Folder>"\r
+  IDS_CONTEXT_ARCHIVE     "<Archive>"\r
+END\r
diff --git a/CPP/7zip/UI/Far/ExtractEngine.cpp b/CPP/7zip/UI/Far/ExtractEngine.cpp
new file mode 100755 (executable)
index 0000000..6e2b39c
--- /dev/null
@@ -0,0 +1,176 @@
+// ExtractEngine.h\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/StringConvert.h"\r
+\r
+#include "ExtractEngine.h"\r
+#include "FarUtils.h"\r
+#include "Messages.h"\r
+#include "OverwriteDialog.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFar;\r
+\r
+extern void PrintMessage(const char *message);\r
+\r
+CExtractCallBackImp::~CExtractCallBackImp()\r
+{\r
+}\r
+\r
+void CExtractCallBackImp::Init(\r
+    UINT codePage,\r
+    CProgressBox *progressBox,\r
+    bool passwordIsDefined,\r
+    const UString &password)\r
+{\r
+  m_PasswordIsDefined = passwordIsDefined;\r
+  m_Password = password;\r
+  m_CodePage = codePage;\r
+  m_ProgressBox = progressBox;\r
+}\r
+\r
+STDMETHODIMP CExtractCallBackImp::SetTotal(UInt64 size)\r
+{\r
+  _total = size;\r
+  _totalIsDefined = true;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtractCallBackImp::SetCompleted(const UInt64 *completeValue)\r
+{\r
+  if (WasEscPressed())\r
+    return E_ABORT;\r
+  _processedIsDefined = (completeValue != NULL);\r
+  if (_processedIsDefined)\r
+    _processed = *completeValue;\r
+  if (m_ProgressBox != 0)\r
+    m_ProgressBox->Progress(\r
+      _totalIsDefined ? &_total: NULL,\r
+      _processedIsDefined ? &_processed: NULL, AString());\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtractCallBackImp::AskOverwrite(\r
+    const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,\r
+    const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,\r
+    Int32 *answer)\r
+{\r
+  NOverwriteDialog::CFileInfo oldFileInfo, newFileInfo;\r
+  oldFileInfo.TimeIsDefined = (existTime != 0);\r
+  if (oldFileInfo.TimeIsDefined)\r
+    oldFileInfo.Time = *existTime;\r
+  oldFileInfo.SizeIsDefined = (existSize != NULL);\r
+  if (oldFileInfo.SizeIsDefined)\r
+    oldFileInfo.Size = *existSize;\r
+  oldFileInfo.Name = existName;\r
+\r
+  newFileInfo.TimeIsDefined = (newTime != 0);\r
+  if (newFileInfo.TimeIsDefined)\r
+    newFileInfo.Time = *newTime;\r
+  newFileInfo.SizeIsDefined = (newSize != NULL);\r
+  if (newFileInfo.SizeIsDefined)\r
+    newFileInfo.Size = *newSize;\r
+  newFileInfo.Name = newName;\r
+  \r
+  NOverwriteDialog::NResult::EEnum result =\r
+    NOverwriteDialog::Execute(oldFileInfo, newFileInfo);\r
+  \r
+  switch(result)\r
+  {\r
+  case NOverwriteDialog::NResult::kCancel:\r
+    // *answer = NOverwriteAnswer::kCancel;\r
+    // break;\r
+    return E_ABORT;\r
+  case NOverwriteDialog::NResult::kNo:\r
+    *answer = NOverwriteAnswer::kNo;\r
+    break;\r
+  case NOverwriteDialog::NResult::kNoToAll:\r
+    *answer = NOverwriteAnswer::kNoToAll;\r
+    break;\r
+  case NOverwriteDialog::NResult::kYesToAll:\r
+    *answer = NOverwriteAnswer::kYesToAll;\r
+    break;\r
+  case NOverwriteDialog::NResult::kYes:\r
+    *answer = NOverwriteAnswer::kYes;\r
+    break;\r
+  case NOverwriteDialog::NResult::kAutoRename:\r
+    *answer = NOverwriteAnswer::kAutoRename;\r
+    break;\r
+  default:\r
+    return E_FAIL;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtractCallBackImp::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 /* askExtractMode */, const UInt64 * /* position */)\r
+{\r
+  if (WasEscPressed())\r
+    return E_ABORT;\r
+  m_CurrentFilePath = name;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtractCallBackImp::MessageError(const wchar_t *message)\r
+{\r
+  AString s = UnicodeStringToMultiByte(message, CP_OEMCP);\r
+  if (g_StartupInfo.ShowMessage((const char *)s) == -1)\r
+    return E_ABORT;\r
+  return S_OK;\r
+}\r
+\r
+static void ReduceString(UString &s, int size)\r
+{\r
+  if (s.Length() > size)\r
+    s = s.Left(size / 2) + UString(L" ... ") + s.Right(size / 2);\r
+}\r
+\r
+STDMETHODIMP CExtractCallBackImp::SetOperationResult(Int32 operationResult, bool encrypted)\r
+{\r
+  switch(operationResult)\r
+  {\r
+    case NArchive::NExtract::NOperationResult::kOK:\r
+      break;\r
+    default:\r
+    {\r
+      UINT idMessage;\r
+      switch(operationResult)\r
+      {\r
+        case NArchive::NExtract::NOperationResult::kUnSupportedMethod:\r
+          idMessage = NMessageID::kExtractUnsupportedMethod;\r
+          break;\r
+        case NArchive::NExtract::NOperationResult::kCRCError:\r
+          idMessage = encrypted ?\r
+            NMessageID::kExtractCRCFailedEncrypted :\r
+            NMessageID::kExtractCRCFailed;\r
+          break;\r
+        case NArchive::NExtract::NOperationResult::kDataError:\r
+          idMessage = encrypted ?\r
+            NMessageID::kExtractDataErrorEncrypted :\r
+            NMessageID::kExtractDataError;\r
+          break;\r
+        default:\r
+          return E_FAIL;\r
+      }\r
+      UString name = m_CurrentFilePath;\r
+      ReduceString(name, 70);\r
+      AString s = g_StartupInfo.GetMsgString(idMessage);\r
+      s.Replace(" '%s'", "");\r
+      if (g_StartupInfo.ShowMessageLines(s + (AString)("\n") + UnicodeStringToMultiByte(name, m_CodePage)) == -1)\r
+        return E_ABORT;\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+extern HRESULT GetPassword(UString &password);\r
+\r
+STDMETHODIMP CExtractCallBackImp::CryptoGetTextPassword(BSTR *password)\r
+{\r
+  if (!m_PasswordIsDefined)\r
+  {\r
+    RINOK(GetPassword(m_Password));\r
+    m_PasswordIsDefined = true;\r
+  }\r
+  return StringToBstr(m_Password, password);\r
+}\r
diff --git a/CPP/7zip/UI/Far/ExtractEngine.h b/CPP/7zip/UI/Far/ExtractEngine.h
new file mode 100755 (executable)
index 0000000..797089f
--- /dev/null
@@ -0,0 +1,68 @@
+// ExtractEngine.h\r
+\r
+#ifndef __EXTRACTENGINE_H\r
+#define __EXTRACTENGINE_H\r
+\r
+#include "Common/MyCom.h"\r
+#include "Common/MyString.h"\r
+\r
+#include "../../IPassword.h"\r
+#include "../Agent/IFolderArchive.h"\r
+\r
+#include "ProgressBox.h"\r
+\r
+class CExtractCallBackImp:\r
+  public IFolderArchiveExtractCallback,\r
+  public ICryptoGetTextPassword,\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP1(ICryptoGetTextPassword)\r
+\r
+  // IProgress\r
+  STDMETHOD(SetTotal)(UInt64 size);\r
+  STDMETHOD(SetCompleted)(const UInt64 *completeValue);\r
+\r
+  // IExtractCallBack\r
+  STDMETHOD(AskOverwrite)(\r
+      const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,\r
+      const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,\r
+      Int32 *result);\r
+  STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position);\r
+\r
+  STDMETHOD(MessageError)(const wchar_t *message);\r
+  STDMETHOD(SetOperationResult)(Int32 resultEOperationResult, bool encrypted);\r
+  // ICryptoGetTextPassword\r
+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);\r
+\r
+private:\r
+  UInt64 _total;\r
+  UInt64 _processed;\r
+  \r
+  bool _totalIsDefined;\r
+  bool _processedIsDefined;\r
+\r
+  UString m_CurrentFilePath;\r
+\r
+  CProgressBox *m_ProgressBox;\r
+  UINT m_CodePage;\r
+\r
+  bool m_PasswordIsDefined;\r
+  UString m_Password;\r
+\r
+  void CreateComplexDirectory(const UStringVector &dirPathParts);\r
+  /*\r
+  void GetPropertyValue(LPITEMIDLIST anItemIDList, PROPID aPropId,\r
+      PROPVARIANT *aValue);\r
+  bool IsEncrypted(LPITEMIDLIST anItemIDList);\r
+  */\r
+  void AddErrorMessage(LPCTSTR message);\r
+public:\r
+  CExtractCallBackImp(): _totalIsDefined(false), _processedIsDefined(false) {}\r
+  ~CExtractCallBackImp();\r
+  void Init(UINT codePage,\r
+      CProgressBox *progressBox,\r
+      bool passwordIsDefined, const UString &password);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Far/Far.def b/CPP/7zip/UI/Far/Far.def
new file mode 100755 (executable)
index 0000000..9dd3930
--- /dev/null
@@ -0,0 +1,34 @@
+; 7-ZipFar.def : Declares the module parameters for the DLL.\r
+\r
+LIBRARY      "7-ZipFar"\r
+\r
+EXPORTS\r
+  SetStartupInfo\r
+  OpenPlugin\r
+  OpenFilePlugin\r
+  ClosePlugin\r
+  GetFindData\r
+  FreeFindData\r
+  SetDirectory\r
+  GetPluginInfo\r
+  Configure\r
+  GetOpenPluginInfo\r
+  GetFiles\r
+  PutFiles\r
+  DeleteFiles\r
+  ProcessKey\r
+\r
+  ;SetStartupInfoW\r
+  ;OpenPluginW\r
+  ;OpenFilePluginW\r
+  ;ClosePluginW\r
+  ;GetFindDataW\r
+  ;FreeFindDataW\r
+  ;SetDirectoryW\r
+  ;GetPluginInfoW\r
+  ;ConfigureW\r
+  ;GetOpenPluginInfoW\r
+  ;GetFilesW\r
+  ;PutFilesW\r
+  ;DeleteFilesW\r
+  ;ProcessKeyW\r
diff --git a/CPP/7zip/UI/Far/Far.dsp b/CPP/7zip/UI/Far/Far.dsp
new file mode 100755 (executable)
index 0000000..cf55e20
--- /dev/null
@@ -0,0 +1,627 @@
+# Microsoft Developer Studio Project File - Name="Far" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
+\r
+CFG=Far - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "Far.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "Far.mak" CFG="Far - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "Far - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE "Far - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+MTL=midl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "Far - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 1\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /YX /FD /c\r
+# 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\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\Far\Plugins\7-Zip\7-ZipFar.dll" /opt:NOWIN98\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "Far - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 1\r
+# PROP Target_Dir ""\r
+# 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\r
+# 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\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x419 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\Far\Plugins\7-Zip\7-ZipFar.dll" /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "Far - Win32 Release"\r
+# Name "Far - Win32 Debug"\r
+# Begin Group "Spec"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\Far.def\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\resource.rc\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.cpp\r
+# ADD CPP /Yc"StdAfx.h"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Plugin"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\ExtractEngine.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ExtractEngine.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Main.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Messages.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\OverwriteDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\OverwriteDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Plugin.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Plugin.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PluginDelete.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PluginRead.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PluginWrite.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\resource.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\UpdateCallback100.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\UpdateCallback100.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Far"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\FarPlugin.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\FarUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\FarUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ProgressBox.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ProgressBox.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Windows"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Defs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantConversions.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantConversions.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Registry.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Registry.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Time.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "UI Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveExtractCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveExtractCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveOpenCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveOpenCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\DefaultName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\DefaultName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\DirItem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\EnumDirItems.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\EnumDirItems.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ExtractingFilePath.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ExtractingFilePath.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ExtractMode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\HandlerLoader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\LoadCodecs.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\LoadCodecs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\OpenArchive.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\OpenArchive.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\PropIDUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\PropIDUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\SortUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\SortUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateAction.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateAction.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdatePair.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdatePair.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateProduce.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateProduce.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\WorkDir.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\WorkDir.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ZipRegistry.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ZipRegistry.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Agent"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\Agent\Agent.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Agent\Agent.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Agent\AgentOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Agent\AgentProxy.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Agent\AgentProxy.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Agent\IFolderArchive.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Agent\UpdateCallbackAgent.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Agent\UpdateCallbackAgent.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Compress"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyCoder.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "7-zip Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilePathAutoRename.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilePathAutoRename.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "C"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrcOpt.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sort.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sort.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Arc Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.h\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/CPP/7zip/UI/Far/Far.dsw b/CPP/7zip/UI/Far/Far.dsw
new file mode 100755 (executable)
index 0000000..ed52003
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "Far"=.\Far.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/CPP/7zip/UI/Far/FarPlugin.h b/CPP/7zip/UI/Far/FarPlugin.h
new file mode 100755 (executable)
index 0000000..6f583e8
--- /dev/null
@@ -0,0 +1,519 @@
+// FarPlugin.h\r
+\r
+// #include "plugin.hpp"\r
+\r
+const int kInfoPanelLineSize = 80;\r
+\r
+// #define __FAR_PLUGIN_H\r
+\r
+#ifdef UNDER_CE\r
+typedef struct _CHAR_INFO {\r
+    union {\r
+        WCHAR UnicodeChar;\r
+        CHAR   AsciiChar;\r
+    } Char;\r
+    WORD Attributes;\r
+} CHAR_INFO, *PCHAR_INFO;\r
+#endif\r
+\r
+#ifndef __FAR_PLUGIN_H\r
+#define __FAR_PLUGIN_H\r
+\r
+#ifndef _WIN64\r
+#if defined(__BORLANDC__) && (__BORLANDC <= 0x520)\r
+  #pragma option -a1\r
+#elif defined(__GNUC__) || (defined(__WATCOMC__) && (__WATCOMC__ < 1100))\r
+  #pragma pack(1)\r
+#else\r
+  #pragma pack(push,1)\r
+#endif\r
+#endif\r
+\r
+  #if _MSC_VER\r
+    #define _export\r
+  #endif\r
+\r
+#define NM 260\r
+\r
+struct FarFindData\r
+{\r
+  DWORD dwFileAttributes;\r
+  FILETIME ftCreationTime;\r
+  FILETIME ftLastAccessTime;\r
+  FILETIME ftLastWriteTime;\r
+  DWORD nFileSizeHigh;\r
+  DWORD nFileSizeLow;\r
+  DWORD dwReserved0;\r
+  DWORD dwReserved1;\r
+  char cFileName[ MAX_PATH ];\r
+  char cAlternateFileName[ 14 ];\r
+};\r
+\r
+struct PluginPanelItem\r
+{\r
+  FarFindData FindData;\r
+  DWORD PackSizeHigh;\r
+  DWORD PackSize;\r
+  DWORD Flags;\r
+  DWORD NumberOfLinks;\r
+  char *Description;\r
+  char *Owner;\r
+  char **CustomColumnData;\r
+  int CustomColumnNumber;\r
+  DWORD_PTR UserData;\r
+  DWORD CRC32;\r
+  DWORD_PTR Reserved[2];\r
+};\r
+\r
+#define PPIF_PROCESSDESCR 0x80000000\r
+#define PPIF_SELECTED     0x40000000\r
+#define PPIF_USERDATA     0x20000000\r
+\r
+enum {\r
+  FMENU_SHOWAMPERSAND=1,\r
+  FMENU_WRAPMODE=2,\r
+  FMENU_AUTOHIGHLIGHT=4,\r
+  FMENU_REVERSEAUTOHIGHLIGHT=8\r
+};\r
+\r
+\r
+typedef int (WINAPI *FARAPIMENU)(\r
+  INT_PTR PluginNumber,\r
+  int X,\r
+  int Y,\r
+  int MaxHeight,\r
+  unsigned int Flags,\r
+  char *Title,\r
+  char *Bottom,\r
+  char *HelpTopic,\r
+  int *BreakKeys,\r
+  int *BreakCode,\r
+  struct FarMenuItem *Item,\r
+  int ItemsNumber\r
+);\r
+\r
+typedef int (WINAPI *FARAPIDIALOG)(\r
+  INT_PTR PluginNumber,\r
+  int X1,\r
+  int Y1,\r
+  int X2,\r
+  int Y2,\r
+  char *HelpTopic,\r
+  struct FarDialogItem *Item,\r
+  int ItemsNumber\r
+);\r
+\r
+enum {\r
+  FMSG_WARNING=1,\r
+  FMSG_ERRORTYPE=2,\r
+  FMSG_KEEPBACKGROUND=4,\r
+  FMSG_DOWN=8,\r
+  FMSG_LEFTALIGN=16\r
+};\r
+\r
+typedef int (WINAPI *FARAPIMESSAGE)(\r
+  INT_PTR PluginNumber,\r
+  unsigned int Flags,\r
+  char *HelpTopic,\r
+  char **Items,\r
+  int ItemsNumber,\r
+  int ButtonsNumber\r
+);\r
+\r
+typedef char* (WINAPI *FARAPIGETMSG)(\r
+  INT_PTR PluginNumber,\r
+  int MsgId\r
+);\r
+\r
+\r
+enum DialogItemTypes {\r
+  DI_TEXT,\r
+  DI_VTEXT,\r
+  DI_SINGLEBOX,\r
+  DI_DOUBLEBOX,\r
+  DI_EDIT,\r
+  DI_PSWEDIT,\r
+  DI_FIXEDIT,\r
+  DI_BUTTON,\r
+  DI_CHECKBOX,\r
+  DI_RADIOBUTTON\r
+};\r
+\r
+enum FarDialogItemFlags {\r
+  DIF_COLORMASK       =    0xff,\r
+  DIF_SETCOLOR        =   0x100,\r
+  DIF_BOXCOLOR        =   0x200,\r
+  DIF_GROUP           =   0x400,\r
+  DIF_LEFTTEXT        =   0x800,\r
+  DIF_MOVESELECT      =  0x1000,\r
+  DIF_SHOWAMPERSAND   =  0x2000,\r
+  DIF_CENTERGROUP     =  0x4000,\r
+  DIF_NOBRACKETS      =  0x8000,\r
+  DIF_SEPARATOR       = 0x10000,\r
+  DIF_EDITOR          = 0x20000,\r
+  DIF_HISTORY         = 0x40000\r
+};\r
+\r
+struct FarDialogItem\r
+{\r
+  int Type;\r
+  int X1,Y1,X2,Y2;\r
+  int Focus;\r
+  union\r
+  {\r
+    int Selected;\r
+    const char *History;\r
+    const char *Mask;\r
+    struct FarList *ListItems;\r
+    int  ListPos;\r
+    CHAR_INFO *VBuf;\r
+  };\r
+  unsigned int Flags;\r
+  int DefaultButton;\r
+  char Data[512];\r
+};\r
+\r
+\r
+struct FarMenuItem\r
+{\r
+  char Text[128];\r
+  int Selected;\r
+  int Checked;\r
+  int Separator;\r
+};\r
+\r
+\r
+enum {FCTL_CLOSEPLUGIN,FCTL_GETPANELINFO,FCTL_GETANOTHERPANELINFO,\r
+      FCTL_UPDATEPANEL,FCTL_UPDATEANOTHERPANEL,\r
+      FCTL_REDRAWPANEL,FCTL_REDRAWANOTHERPANEL,\r
+      FCTL_SETANOTHERPANELDIR,FCTL_GETCMDLINE,FCTL_SETCMDLINE,\r
+      FCTL_SETSELECTION,FCTL_SETANOTHERSELECTION,\r
+      FCTL_SETVIEWMODE,FCTL_SETANOTHERVIEWMODE,FCTL_INSERTCMDLINE,\r
+      FCTL_SETUSERSCREEN,FCTL_SETPANELDIR,FCTL_SETCMDLINEPOS,\r
+      FCTL_GETCMDLINEPOS\r
+};\r
+\r
+enum {PTYPE_FILEPANEL,PTYPE_TREEPANEL,PTYPE_QVIEWPANEL,PTYPE_INFOPANEL};\r
+\r
+struct PanelInfo\r
+{\r
+  int PanelType;\r
+  int Plugin;\r
+  RECT PanelRect;\r
+  struct PluginPanelItem *PanelItems;\r
+  int ItemsNumber;\r
+  struct PluginPanelItem *SelectedItems;\r
+  int SelectedItemsNumber;\r
+  int CurrentItem;\r
+  int TopPanelItem;\r
+  int Visible;\r
+  int Focus;\r
+  int ViewMode;\r
+  char ColumnTypes[80];\r
+  char ColumnWidths[80];\r
+  char CurDir[NM];\r
+  int ShortNames;\r
+  int SortMode;\r
+  DWORD Flags;\r
+  DWORD Reserved;\r
+};\r
+\r
+\r
+struct PanelRedrawInfo\r
+{\r
+  int CurrentItem;\r
+  int TopPanelItem;\r
+};\r
+\r
+\r
+typedef int (WINAPI *FARAPICONTROL)(\r
+  HANDLE hPlugin,\r
+  int Command,\r
+  void *Param\r
+);\r
+\r
+typedef HANDLE (WINAPI *FARAPISAVESCREEN)(int X1,int Y1,int X2,int Y2);\r
+\r
+typedef void (WINAPI *FARAPIRESTORESCREEN)(HANDLE hScreen);\r
+\r
+typedef int (WINAPI *FARAPIGETDIRLIST)(\r
+  char *Dir,\r
+  struct PluginPanelItem **pPanelItem,\r
+  int *pItemsNumber\r
+);\r
+\r
+typedef int (WINAPI *FARAPIGETPLUGINDIRLIST)(\r
+  INT_PTR PluginNumber,\r
+  HANDLE hPlugin,\r
+  char *Dir,\r
+  struct PluginPanelItem **pPanelItem,\r
+  int *pItemsNumber\r
+);\r
+\r
+typedef void (WINAPI *FARAPIFREEDIRLIST)(struct PluginPanelItem *PanelItem);\r
+\r
+enum VIEWER_FLAGS {\r
+  VF_NONMODAL=1,VF_DELETEONCLOSE=2\r
+};\r
+\r
+typedef int (WINAPI *FARAPIVIEWER)(\r
+  char *FileName,\r
+  char *Title,\r
+  int X1,\r
+  int Y1,\r
+  int X2,\r
+  int Y2,\r
+  DWORD Flags\r
+);\r
+\r
+typedef int (WINAPI *FARAPIEDITOR)(\r
+  char *FileName,\r
+  char *Title,\r
+  int X1,\r
+  int Y1,\r
+  int X2,\r
+  int Y2,\r
+  DWORD Flags,\r
+  int StartLine,\r
+  int StartChar\r
+);\r
+\r
+typedef int (WINAPI *FARAPICMPNAME)(\r
+  char *Pattern,\r
+  char *String,\r
+  int SkipPath\r
+);\r
+\r
+\r
+#define FCT_DETECT 0x40000000\r
+\r
+struct CharTableSet\r
+{\r
+  char DecodeTable[256];\r
+  char EncodeTable[256];\r
+  char UpperTable[256];\r
+  char LowerTable[256];\r
+  char TableName[128];\r
+};\r
+\r
+typedef int (WINAPI *FARAPICHARTABLE)(\r
+  int Command,\r
+  char *Buffer,\r
+  int BufferSize\r
+);\r
+\r
+typedef void (WINAPI *FARAPITEXT)(\r
+  int X,\r
+  int Y,\r
+  int Color,\r
+  char *Str\r
+);\r
+\r
+\r
+typedef int (WINAPI *FARAPIEDITORCONTROL)(\r
+  int Command,\r
+  void *Param\r
+);\r
+\r
+struct PluginStartupInfo\r
+{\r
+  int StructSize;\r
+  char ModuleName[NM];\r
+  INT_PTR ModuleNumber;\r
+  char *RootKey;\r
+  FARAPIMENU Menu;\r
+  FARAPIDIALOG Dialog;\r
+  FARAPIMESSAGE Message;\r
+  FARAPIGETMSG GetMsg;\r
+  FARAPICONTROL Control;\r
+  FARAPISAVESCREEN SaveScreen;\r
+  FARAPIRESTORESCREEN RestoreScreen;\r
+  FARAPIGETDIRLIST GetDirList;\r
+  FARAPIGETPLUGINDIRLIST GetPluginDirList;\r
+  FARAPIFREEDIRLIST FreeDirList;\r
+  FARAPIVIEWER Viewer;\r
+  FARAPIEDITOR Editor;\r
+  FARAPICMPNAME CmpName;\r
+  FARAPICHARTABLE CharTable;\r
+  FARAPITEXT Text;\r
+  FARAPIEDITORCONTROL EditorControl;\r
+};\r
+\r
+\r
+enum PLUGIN_FLAGS {\r
+  PF_PRELOAD        = 0x0001,\r
+  PF_DISABLEPANELS  = 0x0002,\r
+  PF_EDITOR         = 0x0004,\r
+  PF_VIEWER         = 0x0008\r
+};\r
+\r
+\r
+struct PluginInfo\r
+{\r
+  int StructSize;\r
+  DWORD Flags;\r
+  char **DiskMenuStrings;\r
+  int *DiskMenuNumbers;\r
+  int DiskMenuStringsNumber;\r
+  char **PluginMenuStrings;\r
+  int PluginMenuStringsNumber;\r
+  char **PluginConfigStrings;\r
+  int PluginConfigStringsNumber;\r
+  char *CommandPrefix;\r
+};\r
+\r
+struct InfoPanelLine\r
+{\r
+  char Text[kInfoPanelLineSize];\r
+  char Data[kInfoPanelLineSize];\r
+  int Separator;\r
+};\r
+\r
+\r
+struct PanelMode\r
+{\r
+  char *ColumnTypes;\r
+  char *ColumnWidths;\r
+  char **ColumnTitles;\r
+  int FullScreen;\r
+  int DetailedStatus;\r
+  int AlignExtensions;\r
+  int CaseConversion;\r
+  char *StatusColumnTypes;\r
+  char *StatusColumnWidths;\r
+  DWORD Reserved[2];\r
+};\r
+\r
+\r
+enum OPENPLUGININFO_FLAGS {\r
+  OPIF_USEFILTER               = 0x0001,\r
+  OPIF_USESORTGROUPS           = 0x0002,\r
+  OPIF_USEHIGHLIGHTING         = 0x0004,\r
+  OPIF_ADDDOTS                 = 0x0008,\r
+  OPIF_RAWSELECTION            = 0x0010,\r
+  OPIF_REALNAMES               = 0x0020,\r
+  OPIF_SHOWNAMESONLY           = 0x0040,\r
+  OPIF_SHOWRIGHTALIGNNAMES     = 0x0080,\r
+  OPIF_SHOWPRESERVECASE        = 0x0100,\r
+  OPIF_FINDFOLDERS             = 0x0200,\r
+  OPIF_COMPAREFATTIME          = 0x0400,\r
+  OPIF_EXTERNALGET             = 0x0800,\r
+  OPIF_EXTERNALPUT             = 0x1000,\r
+  OPIF_EXTERNALDELETE          = 0x2000,\r
+  OPIF_EXTERNALMKDIR           = 0x4000,\r
+  OPIF_USEATTRHIGHLIGHTING     = 0x8000\r
+};\r
+\r
+\r
+enum OPENPLUGININFO_SORTMODES {\r
+  SM_DEFAULT,SM_UNSORTED,SM_NAME,SM_EXT,SM_MTIME,SM_CTIME,\r
+  SM_ATIME,SM_SIZE,SM_DESCR,SM_OWNER,SM_COMPRESSEDSIZE,SM_NUMLINKS\r
+};\r
+\r
+\r
+struct KeyBarTitles\r
+{\r
+  char *Titles[12];\r
+  char *CtrlTitles[12];\r
+  char *AltTitles[12];\r
+  char *ShiftTitles[12];\r
+};\r
+\r
+\r
+struct OpenPluginInfo\r
+{\r
+  int StructSize;\r
+  DWORD Flags;\r
+  char *HostFile;\r
+  char *CurDir;\r
+  char *Format;\r
+  char *PanelTitle;\r
+  struct InfoPanelLine *InfoLines;\r
+  int InfoLinesNumber;\r
+  char **DescrFiles;\r
+  int DescrFilesNumber;\r
+  struct PanelMode *PanelModesArray;\r
+  int PanelModesNumber;\r
+  int StartPanelMode;\r
+  int StartSortMode;\r
+  int StartSortOrder;\r
+  struct KeyBarTitles *KeyBar;\r
+  char *ShortcutData;\r
+};\r
+\r
+enum {\r
+  OPEN_DISKMENU,\r
+  OPEN_PLUGINSMENU,\r
+  OPEN_FINDLIST,\r
+  OPEN_SHORTCUT,\r
+  OPEN_COMMANDLINE,\r
+  OPEN_EDITOR,\r
+  OPEN_VIEWER\r
+};\r
+\r
+enum {PKF_CONTROL=1,PKF_ALT=2,PKF_SHIFT=4};\r
+\r
+enum FAR_EVENTS {\r
+  FE_CHANGEVIEWMODE,\r
+  FE_REDRAW,\r
+  FE_IDLE,\r
+  FE_CLOSE,\r
+  FE_BREAK,\r
+  FE_COMMAND\r
+};\r
+\r
+enum OPERATION_MODES {\r
+  OPM_SILENT=1,\r
+  OPM_FIND=2,\r
+  OPM_VIEW=4,\r
+  OPM_EDIT=8,\r
+  OPM_TOPLEVEL=16,\r
+  OPM_DESCR=32\r
+};\r
+\r
+#ifndef _WIN64\r
+#if defined(__BORLANDC__) && (__BORLANDC <= 0x520)\r
+  #pragma option -a.\r
+#elif defined(__GNUC__) || (defined(__WATCOMC__) && (__WATCOMC__ < 1100))\r
+  #pragma pack()\r
+#else\r
+  #pragma pack(pop)\r
+#endif\r
+#endif\r
+\r
+/*\r
+EXTERN_C_BEGIN\r
+\r
+  void   WINAPI _export ClosePluginW(HANDLE hPlugin);\r
+  int    WINAPI _export CompareW(HANDLE hPlugin,const struct PluginPanelItem *Item1,const struct PluginPanelItem *Item2,unsigned int Mode);\r
+  int    WINAPI _export ConfigureW(int ItemNumber);\r
+  int    WINAPI _export DeleteFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode);\r
+  void   WINAPI _export ExitFARW(void);\r
+  void   WINAPI _export FreeFindDataW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber);\r
+  void   WINAPI _export FreeVirtualFindDataW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber);\r
+  int    WINAPI _export GetFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int Move,const wchar_t **DestPath,int OpMode);\r
+  int    WINAPI _export GetFindDataW(HANDLE hPlugin,struct PluginPanelItem **pPanelItem,int *pItemsNumber,int OpMode);\r
+  int    WINAPI _export GetMinFarVersionW(void);\r
+  void   WINAPI _export GetOpenPluginInfoW(HANDLE hPlugin,struct OpenPluginInfo *Info);\r
+  void   WINAPI _export GetPluginInfoW(struct PluginInfo *Info);\r
+  int    WINAPI _export GetVirtualFindDataW(HANDLE hPlugin,struct PluginPanelItem **pPanelItem,int *pItemsNumber,const wchar_t *Path);\r
+  int    WINAPI _export MakeDirectoryW(HANDLE hPlugin,const wchar_t **Name,int OpMode);\r
+  HANDLE WINAPI _export OpenFilePluginW(const wchar_t *Name,const unsigned char *Data,int DataSize,int OpMode);\r
+  HANDLE WINAPI _export OpenPluginW(int OpenFrom,INT_PTR Item);\r
+  int    WINAPI _export ProcessDialogEventW(int Event,void *Param);\r
+  int    WINAPI _export ProcessEditorEventW(int Event,void *Param);\r
+  int    WINAPI _export ProcessEditorInputW(const INPUT_RECORD *Rec);\r
+  int    WINAPI _export ProcessEventW(HANDLE hPlugin,int Event,void *Param);\r
+  int    WINAPI _export ProcessHostFileW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode);\r
+  int    WINAPI _export ProcessKeyW(HANDLE hPlugin,int Key,unsigned int ControlState);\r
+  int    WINAPI _export ProcessSynchroEventW(int Event,void *Param);\r
+  int    WINAPI _export ProcessViewerEventW(int Event,void *Param);\r
+  int    WINAPI _export PutFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int Move,const wchar_t *SrcPath,int OpMode);\r
+  int    WINAPI _export SetDirectoryW(HANDLE hPlugin,const wchar_t *Dir,int OpMode);\r
+  int    WINAPI _export SetFindListW(HANDLE hPlugin,const struct PluginPanelItem *PanelItem,int ItemsNumber);\r
+  void   WINAPI _export SetStartupInfoW(const struct PluginStartupInfo *Info);\r
+\r
+EXTERN_C_END\r
+*/\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Far/FarUtils.cpp b/CPP/7zip/UI/Far/FarUtils.cpp
new file mode 100755 (executable)
index 0000000..cfdeb1b
--- /dev/null
@@ -0,0 +1,464 @@
+// FarUtils.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/StringConvert.h"\r
+\r
+#ifndef UNDER_CE\r
+#include "Windows/Console.h"\r
+#endif\r
+#include "Windows/Defs.h"\r
+#include "Windows/Error.h"\r
+\r
+#include "FarUtils.h"\r
+\r
+using namespace NWindows;\r
+\r
+namespace NFar {\r
+\r
+CStartupInfo g_StartupInfo;\r
+\r
+void CStartupInfo::Init(const PluginStartupInfo &pluginStartupInfo,\r
+    const CSysString &pluginNameForRegestry)\r
+{\r
+  m_Data = pluginStartupInfo;\r
+  m_RegistryPath = GetSystemString(pluginStartupInfo.RootKey);\r
+  m_RegistryPath += TEXT('\\');\r
+  m_RegistryPath += pluginNameForRegestry;\r
+}\r
+\r
+const char *CStartupInfo::GetMsgString(int messageId)\r
+{\r
+  return (const char*)m_Data.GetMsg(m_Data.ModuleNumber, messageId);\r
+}\r
+\r
+int CStartupInfo::ShowMessage(unsigned int flags,\r
+    const char *helpTopic, const char **items, int numItems, int numButtons)\r
+{\r
+  return m_Data.Message(m_Data.ModuleNumber, flags, (char *)helpTopic,\r
+    (char **)items, numItems, numButtons);\r
+}\r
+\r
+namespace NMessageID\r
+{\r
+  enum\r
+  {\r
+    kOk,\r
+    kCancel,\r
+    kWarning,\r
+    kError\r
+  };\r
+}\r
+\r
+int CStartupInfo::ShowMessage(const char *message)\r
+{\r
+  const char *items[]= { GetMsgString(NMessageID::kError), message, GetMsgString(NMessageID::kOk) };\r
+  return ShowMessage(FMSG_WARNING, NULL, items, sizeof(items) / sizeof(items[0]), 1);\r
+}\r
+\r
+static void SplitString(const AString &srcString, AStringVector &destStrings)\r
+{\r
+  destStrings.Clear();\r
+  AString string;\r
+  int len = srcString.Length();\r
+  if (len == 0)\r
+    return;\r
+  for (int i = 0; i < len; i++)\r
+  {\r
+    char c = srcString[i];\r
+    if (c == '\n')\r
+    {\r
+      if (!string.IsEmpty())\r
+      {\r
+        destStrings.Add(string);\r
+        string.Empty();\r
+      }\r
+    }\r
+    else\r
+      string += c;\r
+  }\r
+  if (!string.IsEmpty())\r
+    destStrings.Add(string);\r
+}\r
+\r
+int CStartupInfo::ShowMessageLines(const char *message)\r
+{\r
+  AStringVector strings;\r
+  SplitString(message, strings);\r
+  const int kNumStringsMax = 20;\r
+  const char *items[kNumStringsMax + 1] = { GetMsgString(NMessageID::kError) };\r
+  int pos = 1;\r
+  for (int i = 0; i < strings.Size() && pos < kNumStringsMax; i++)\r
+    items[pos++] = strings[i];\r
+  items[pos++] = GetMsgString(NMessageID::kOk);\r
+\r
+  return ShowMessage(FMSG_WARNING, NULL, items, pos, 1);\r
+}\r
+\r
+int CStartupInfo::ShowMessage(int messageId)\r
+{\r
+  return ShowMessage(GetMsgString(messageId));\r
+}\r
+\r
+int CStartupInfo::ShowDialog(int X1, int Y1, int X2, int Y2,\r
+    const char *helpTopic, struct FarDialogItem *items, int numItems)\r
+{\r
+  return m_Data.Dialog(m_Data.ModuleNumber, X1, Y1, X2, Y2, (char *)helpTopic,\r
+      items, numItems);\r
+}\r
+\r
+int CStartupInfo::ShowDialog(int sizeX, int sizeY,\r
+    const char *helpTopic, struct FarDialogItem *items, int numItems)\r
+{\r
+  return ShowDialog(-1, -1, sizeX, sizeY, helpTopic, items, numItems);\r
+}\r
+\r
+inline static BOOL GetBOOLValue(bool v) { return (v? TRUE: FALSE); }\r
+\r
+void CStartupInfo::InitDialogItems(const CInitDialogItem  *srcItems,\r
+    FarDialogItem *destItems, int numItems)\r
+{\r
+  for (int i = 0; i < numItems; i++)\r
+  {\r
+    const CInitDialogItem &srcItem = srcItems[i];\r
+    FarDialogItem &destItem = destItems[i];\r
+\r
+    destItem.Type = srcItem.Type;\r
+    destItem.X1 = srcItem.X1;\r
+    destItem.Y1 = srcItem.Y1;\r
+    destItem.X2 = srcItem.X2;\r
+    destItem.Y2 = srcItem.Y2;\r
+    destItem.Focus = GetBOOLValue(srcItem.Focus);\r
+    if(srcItem.HistoryName != NULL)\r
+      destItem.History = srcItem.HistoryName;\r
+    else\r
+      destItem.Selected = GetBOOLValue(srcItem.Selected);\r
+    destItem.Flags = srcItem.Flags;\r
+    destItem.DefaultButton = GetBOOLValue(srcItem.DefaultButton);\r
+\r
+    if(srcItem.DataMessageId < 0)\r
+      MyStringCopy(destItem.Data, srcItem.DataString);\r
+    else\r
+      MyStringCopy(destItem.Data, GetMsgString(srcItem.DataMessageId));\r
+\r
+    /*\r
+    if ((unsigned int)Init[i].Data < 0xFFF)\r
+      MyStringCopy(destItem.Data, GetMsg((unsigned int)srcItem.Data));\r
+    else\r
+      MyStringCopy(destItem.Data,srcItem.Data);\r
+    */\r
+  }\r
+}\r
+\r
+// --------------------------------------------\r
+\r
+HANDLE CStartupInfo::SaveScreen(int X1, int Y1, int X2, int Y2)\r
+{\r
+  return m_Data.SaveScreen(X1, Y1, X2, Y2);\r
+}\r
+\r
+HANDLE CStartupInfo::SaveScreen()\r
+{\r
+  return SaveScreen(0, 0, -1, -1);\r
+}\r
+\r
+void CStartupInfo::RestoreScreen(HANDLE handle)\r
+{\r
+  m_Data.RestoreScreen(handle);\r
+}\r
+\r
+const TCHAR kRegestryKeyDelimiter = TEXT('\'');\r
+\r
+CSysString CStartupInfo::GetFullKeyName(const CSysString &keyName) const\r
+{\r
+  return (keyName.IsEmpty()) ? m_RegistryPath:\r
+    (m_RegistryPath + kRegestryKeyDelimiter + keyName);\r
+}\r
+\r
+\r
+LONG CStartupInfo::CreateRegKey(HKEY parentKey,\r
+    const CSysString &keyName, NRegistry::CKey &destKey) const\r
+{\r
+  return destKey.Create(parentKey, GetFullKeyName(keyName));\r
+}\r
+\r
+LONG CStartupInfo::OpenRegKey(HKEY parentKey,\r
+    const CSysString &keyName, NRegistry::CKey &destKey) const\r
+{\r
+  return destKey.Open(parentKey, GetFullKeyName(keyName));\r
+}\r
+\r
+void CStartupInfo::SetRegKeyValue(HKEY parentKey, const CSysString &keyName,\r
+    LPCTSTR valueName, LPCTSTR value) const\r
+{\r
+  NRegistry::CKey regKey;\r
+  CreateRegKey(parentKey, keyName, regKey);\r
+  regKey.SetValue(valueName, value);\r
+}\r
+\r
+void CStartupInfo::SetRegKeyValue(HKEY parentKey, const CSysString &keyName,\r
+    LPCTSTR valueName, UINT32 value) const\r
+{\r
+  NRegistry::CKey regKey;\r
+  CreateRegKey(parentKey, keyName, regKey);\r
+  regKey.SetValue(valueName, value);\r
+}\r
+\r
+void CStartupInfo::SetRegKeyValue(HKEY parentKey, const CSysString &keyName,\r
+    LPCTSTR valueName, bool value) const\r
+{\r
+  NRegistry::CKey regKey;\r
+  CreateRegKey(parentKey, keyName, regKey);\r
+  regKey.SetValue(valueName, value);\r
+}\r
+\r
+CSysString CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyName,\r
+    LPCTSTR valueName, const CSysString &valueDefault) const\r
+{\r
+  NRegistry::CKey regKey;\r
+  if (OpenRegKey(parentKey, keyName, regKey) != ERROR_SUCCESS)\r
+    return valueDefault;\r
+  \r
+  CSysString value;\r
+  if(regKey.QueryValue(valueName, value) != ERROR_SUCCESS)\r
+    return valueDefault;\r
+  \r
+  return value;\r
+}\r
+\r
+UINT32 CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyName,\r
+    LPCTSTR valueName, UINT32 valueDefault) const\r
+{\r
+  NRegistry::CKey regKey;\r
+  if (OpenRegKey(parentKey, keyName, regKey) != ERROR_SUCCESS)\r
+    return valueDefault;\r
+  \r
+  UINT32 value;\r
+  if(regKey.QueryValue(valueName, value) != ERROR_SUCCESS)\r
+    return valueDefault;\r
+  \r
+  return value;\r
+}\r
+\r
+bool CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyName,\r
+    LPCTSTR valueName, bool valueDefault) const\r
+{\r
+  NRegistry::CKey regKey;\r
+  if (OpenRegKey(parentKey, keyName, regKey) != ERROR_SUCCESS)\r
+    return valueDefault;\r
+  \r
+  bool value;\r
+  if(regKey.QueryValue(valueName, value) != ERROR_SUCCESS)\r
+    return valueDefault;\r
+  \r
+  return value;\r
+}\r
+\r
+bool CStartupInfo::Control(HANDLE pluginHandle, int command, void *param)\r
+{\r
+  return BOOLToBool(m_Data.Control(pluginHandle, command, param));\r
+}\r
+\r
+bool CStartupInfo::ControlRequestActivePanel(int command, void *param)\r
+{\r
+  return Control(INVALID_HANDLE_VALUE, command, param);\r
+}\r
+\r
+bool CStartupInfo::ControlGetActivePanelInfo(PanelInfo &panelInfo)\r
+{\r
+  return ControlRequestActivePanel(FCTL_GETPANELINFO, &panelInfo);\r
+}\r
+\r
+bool CStartupInfo::ControlSetSelection(const PanelInfo &panelInfo)\r
+{\r
+  return ControlRequestActivePanel(FCTL_SETSELECTION, (void *)&panelInfo);\r
+}\r
+\r
+bool CStartupInfo::ControlGetActivePanelCurrentItemInfo(\r
+    PluginPanelItem &pluginPanelItem)\r
+{\r
+  PanelInfo panelInfo;\r
+  if(!ControlGetActivePanelInfo(panelInfo))\r
+    return false;\r
+  if(panelInfo.ItemsNumber <= 0)\r
+    throw "There are no items";\r
+  pluginPanelItem = panelInfo.PanelItems[panelInfo.CurrentItem];\r
+  return true;\r
+}\r
+\r
+bool CStartupInfo::ControlGetActivePanelSelectedOrCurrentItems(\r
+    CObjectVector<PluginPanelItem> &pluginPanelItems)\r
+{\r
+  pluginPanelItems.Clear();\r
+  PanelInfo panelInfo;\r
+  if(!ControlGetActivePanelInfo(panelInfo))\r
+    return false;\r
+  if(panelInfo.ItemsNumber <= 0)\r
+    throw "There are no items";\r
+  if (panelInfo.SelectedItemsNumber == 0)\r
+    pluginPanelItems.Add(panelInfo.PanelItems[panelInfo.CurrentItem]);\r
+  else\r
+    for (int i = 0; i < panelInfo.SelectedItemsNumber; i++)\r
+      pluginPanelItems.Add(panelInfo.SelectedItems[i]);\r
+  return true;\r
+}\r
+\r
+bool CStartupInfo::ControlClearPanelSelection()\r
+{\r
+  PanelInfo panelInfo;\r
+  if(!ControlGetActivePanelInfo(panelInfo))\r
+    return false;\r
+  for (int i = 0; i < panelInfo.ItemsNumber; i++)\r
+    panelInfo.PanelItems[i].Flags &= ~PPIF_SELECTED;\r
+  return ControlSetSelection(panelInfo);\r
+}\r
+\r
+////////////////////////////////////////////////\r
+// menu function\r
+\r
+int CStartupInfo::Menu(\r
+    int x,\r
+    int y,\r
+    int maxHeight,\r
+    unsigned int flags,\r
+    const char *title,\r
+    const char *aBottom,\r
+    const char *helpTopic,\r
+    int *breakKeys,\r
+    int *breakCode,\r
+    struct FarMenuItem *items,\r
+    int numItems)\r
+{\r
+  return m_Data.Menu(m_Data.ModuleNumber, x, y, maxHeight, flags, (char *)title,\r
+      (char *)aBottom, (char *)helpTopic, breakKeys, breakCode, items, numItems);\r
+}\r
+\r
+int CStartupInfo::Menu(\r
+    unsigned int flags,\r
+    const char *title,\r
+    const char *helpTopic,\r
+    struct FarMenuItem *items,\r
+    int numItems)\r
+{\r
+  return Menu(-1, -1, 0, flags, title, NULL, helpTopic, NULL,\r
+      NULL, items, numItems);\r
+}\r
+\r
+int CStartupInfo::Menu(\r
+    unsigned int flags,\r
+    const char *title,\r
+    const char *helpTopic,\r
+    const CSysStringVector &items,\r
+    int selectedItem)\r
+{\r
+  CRecordVector<FarMenuItem> farMenuItems;\r
+  for(int i = 0; i < items.Size(); i++)\r
+  {\r
+    FarMenuItem item;\r
+    item.Checked = 0;\r
+    item.Separator = 0;\r
+    item.Selected = (i == selectedItem);\r
+    CSysString reducedString = items[i].Left(sizeof(item.Text) / sizeof(item.Text[0]) - 1);\r
+    MyStringCopy(item.Text, (const char *)GetOemString(reducedString));\r
+    farMenuItems.Add(item);\r
+  }\r
+  return Menu(flags, title, helpTopic, &farMenuItems.Front(), farMenuItems.Size());\r
+}\r
+\r
+\r
+//////////////////////////////////\r
+// CScreenRestorer\r
+\r
+CScreenRestorer::~CScreenRestorer()\r
+{\r
+  Restore();\r
+}\r
+void CScreenRestorer::Save()\r
+{\r
+  if(m_Saved)\r
+    return;\r
+  m_HANDLE = g_StartupInfo.SaveScreen();\r
+  m_Saved = true;\r
+}\r
+\r
+void CScreenRestorer::Restore()\r
+{\r
+  if(m_Saved)\r
+  {\r
+    g_StartupInfo.RestoreScreen(m_HANDLE);\r
+    m_Saved = false;\r
+  }\r
+};\r
+\r
+static AString DWORDToString(DWORD number)\r
+{\r
+  char buffer[32];\r
+  _ultoa(number, buffer, 10);\r
+  return buffer;\r
+}\r
+\r
+void PrintErrorMessage(const char *message, int code)\r
+{\r
+  AString tmp = message;\r
+  tmp += " #";\r
+  tmp += DWORDToString(code);\r
+  g_StartupInfo.ShowMessage(tmp);\r
+}\r
+\r
+void PrintErrorMessage(const char *message, const char *text)\r
+{\r
+  AString tmp = message;\r
+  tmp += ":\n";\r
+  tmp += text;\r
+  g_StartupInfo.ShowMessageLines(tmp);\r
+}\r
+\r
+void PrintErrorMessage(const char *message, const wchar_t *text)\r
+{\r
+  PrintErrorMessage(message, UnicodeStringToMultiByte(text, CP_OEMCP));\r
+}\r
+\r
+bool WasEscPressed()\r
+{\r
+  #ifdef UNDER_CE\r
+  return false;\r
+  #else\r
+  NConsole::CIn inConsole;\r
+  HANDLE handle = ::GetStdHandle(STD_INPUT_HANDLE);\r
+  if(handle == INVALID_HANDLE_VALUE)\r
+    return true;\r
+  inConsole.Attach(handle);\r
+  for (;;)\r
+  {\r
+    DWORD numEvents;\r
+    if(!inConsole.GetNumberOfEvents(numEvents))\r
+      return true;\r
+    if(numEvents == 0)\r
+      return false;\r
+\r
+    INPUT_RECORD event;\r
+    if(!inConsole.ReadEvent(event, numEvents))\r
+      return true;\r
+    if (event.EventType == KEY_EVENT &&\r
+        event.Event.KeyEvent.bKeyDown &&\r
+        event.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)\r
+      return true;\r
+  }\r
+  #endif\r
+}\r
+\r
+void ShowErrorMessage(DWORD errorCode)\r
+{\r
+  UString message;\r
+  NError::MyFormatMessage(errorCode, message);\r
+  message.Replace(L"\x0D", L"");\r
+  message.Replace(L"\x0A", L" ");\r
+  g_StartupInfo.ShowMessage(UnicodeStringToMultiByte(message, CP_OEMCP));\r
+}\r
+\r
+void ShowLastErrorMessage()\r
+{\r
+  ShowErrorMessage(::GetLastError());\r
+}\r
+\r
+}\r
diff --git a/CPP/7zip/UI/Far/FarUtils.h b/CPP/7zip/UI/Far/FarUtils.h
new file mode 100755 (executable)
index 0000000..52578dc
--- /dev/null
@@ -0,0 +1,187 @@
+// FarUtils.h\r
+\r
+#ifndef __FARUTILS_H\r
+#define __FARUTILS_H\r
+\r
+#include "FarPlugin.h"\r
+#include "Windows/Registry.h"\r
+\r
+namespace NFar {\r
+\r
+namespace NFileOperationReturnCode\r
+{\r
+  enum EEnum\r
+  {\r
+    kInterruptedByUser = -1,\r
+    kError = 0,\r
+    kSuccess = 1\r
+  };\r
+}\r
+\r
+namespace NEditorReturnCode\r
+{\r
+  enum EEnum\r
+  {\r
+    kOpenError = 0,\r
+    kFileWasChanged = 1,\r
+    kFileWasNotChanged = 2,\r
+    kInterruptedByUser = 3\r
+  };\r
+}\r
+\r
+struct CInitDialogItem\r
+{\r
+  DialogItemTypes Type;\r
+  int X1,Y1,X2,Y2;\r
+  bool Focus;\r
+  bool Selected;\r
+  unsigned int Flags; //FarDialogItemFlags Flags;\r
+  bool DefaultButton;\r
+  int DataMessageId;\r
+  const char *DataString;\r
+  const char *HistoryName;\r
+  // void InitToFarDialogItem(struct FarDialogItem &anItemDest);\r
+};\r
+\r
+class CStartupInfo\r
+{\r
+  PluginStartupInfo m_Data;\r
+  CSysString m_RegistryPath;\r
+\r
+  CSysString GetFullKeyName(const CSysString &keyName) const;\r
+  LONG CreateRegKey(HKEY parentKey,\r
+    const CSysString &keyName, NWindows::NRegistry::CKey &destKey) const;\r
+  LONG OpenRegKey(HKEY parentKey,\r
+    const CSysString &keyName, NWindows::NRegistry::CKey &destKey) const;\r
+\r
+public:\r
+  void Init(const PluginStartupInfo &pluginStartupInfo,\r
+      const CSysString &pluginNameForRegestry);\r
+  const char *GetMsgString(int messageId);\r
+  int ShowMessage(unsigned int flags, const char *helpTopic,\r
+      const char **items, int numItems, int numButtons);\r
+  int ShowMessage(const char *message);\r
+  int ShowMessageLines(const char *message);\r
+  int ShowMessage(int messageId);\r
+\r
+  int ShowDialog(int X1, int Y1, int X2, int Y2,\r
+      const char *helpTopic, struct FarDialogItem *items, int numItems);\r
+  int ShowDialog(int sizeX, int sizeY,\r
+      const char *helpTopic, struct FarDialogItem *items, int numItems);\r
+\r
+  void InitDialogItems(const CInitDialogItem *srcItems,\r
+      FarDialogItem *destItems, int numItems);\r
+  \r
+  HANDLE SaveScreen(int X1, int Y1, int X2, int Y2);\r
+  HANDLE SaveScreen();\r
+  void RestoreScreen(HANDLE handle);\r
+\r
+  void SetRegKeyValue(HKEY parentKey, const CSysString &keyName,\r
+      const LPCTSTR valueName, LPCTSTR value) const;\r
+  void SetRegKeyValue(HKEY hRoot, const CSysString &keyName,\r
+      const LPCTSTR valueName, UINT32 value) const;\r
+  void SetRegKeyValue(HKEY hRoot, const CSysString &keyName,\r
+      const LPCTSTR valueName, bool value) const;\r
+\r
+  CSysString QueryRegKeyValue(HKEY parentKey, const CSysString &keyName,\r
+      LPCTSTR valueName, const CSysString &valueDefault) const;\r
+\r
+  UINT32 QueryRegKeyValue(HKEY parentKey, const CSysString &keyName,\r
+      LPCTSTR valueName, UINT32 valueDefault) const;\r
+\r
+  bool QueryRegKeyValue(HKEY parentKey, const CSysString &keyName,\r
+      LPCTSTR valueName, bool valueDefault) const;\r
+\r
+  bool Control(HANDLE plugin, int command, void *param);\r
+  bool ControlRequestActivePanel(int command, void *param);\r
+  bool ControlGetActivePanelInfo(PanelInfo &panelInfo);\r
+  bool ControlSetSelection(const PanelInfo &panelInfo);\r
+  bool ControlGetActivePanelCurrentItemInfo(PluginPanelItem &pluginPanelItem);\r
+  bool ControlGetActivePanelSelectedOrCurrentItems(\r
+      CObjectVector<PluginPanelItem> &pluginPanelItems);\r
+\r
+  bool ControlClearPanelSelection();\r
+\r
+  int Menu(\r
+      int x,\r
+      int y,\r
+      int maxHeight,\r
+      unsigned int flags,\r
+      const char *title,\r
+      const char *aBottom,\r
+      const char *helpTopic,\r
+      int *breakKeys,\r
+      int *breakCode,\r
+      FarMenuItem *items,\r
+      int numItems);\r
+  int Menu(\r
+      unsigned int flags,\r
+      const char *title,\r
+      const char *helpTopic,\r
+      FarMenuItem *items,\r
+      int numItems);\r
+\r
+  int Menu(\r
+      unsigned int flags,\r
+      const char *title,\r
+      const char *helpTopic,\r
+      const CSysStringVector &items,\r
+      int selectedItem);\r
+\r
+  int Editor(const char *fileName, const char *title,\r
+      int X1, int Y1, int X2, int Y2, DWORD flags, int startLine, int startChar)\r
+      { return m_Data.Editor((char *)fileName, (char *)title, X1, Y1, X2, Y2,\r
+        flags, startLine, startChar); }\r
+  int Editor(const char *fileName)\r
+      { return Editor(fileName, NULL, 0, 0, -1, -1, 0, -1, -1); }\r
+\r
+  int Viewer(const char *fileName, const char *title,\r
+      int X1, int Y1, int X2, int Y2, DWORD flags)\r
+      { return m_Data.Viewer((char *)fileName, (char *)title, X1, Y1, X2, Y2, flags); }\r
+  int Viewer(const char *fileName)\r
+      { return Viewer(fileName, NULL, 0, 0, -1, -1, VF_NONMODAL); }\r
+\r
+};\r
+\r
+class CScreenRestorer\r
+{\r
+  bool m_Saved;\r
+  HANDLE m_HANDLE;\r
+public:\r
+  CScreenRestorer(): m_Saved(false){};\r
+  ~CScreenRestorer();\r
+  void Save();\r
+  void Restore();\r
+};\r
+\r
+\r
+extern CStartupInfo g_StartupInfo;\r
+\r
+void PrintErrorMessage(const char *message, int code);\r
+void PrintErrorMessage(const char *message, const char *text);\r
+void PrintErrorMessage(const char *message, const wchar_t *text);\r
+\r
+#define  MY_TRY_BEGIN   try\\r
+  {\r
+\r
+#define  MY_TRY_END1(x)     }\\r
+  catch(int n) { PrintErrorMessage(x, n);  return; }\\r
+  catch(const CSysString &s) { PrintErrorMessage(x, s); return; }\\r
+  catch(const char *s) { PrintErrorMessage(x, s); return; }\\r
+  catch(...) { g_StartupInfo.ShowMessage(x);  return; }\r
+\r
+#define  MY_TRY_END2(x, y)     }\\r
+  catch(int n) { PrintErrorMessage(x, n); return y; }\\r
+  catch(const AString &s) { PrintErrorMessage(x, s); return y; }\\r
+  catch(const char *s) { PrintErrorMessage(x, s); return y; }\\r
+  catch(const UString &s) { PrintErrorMessage(x, s); return y; }\\r
+  catch(const wchar_t *s) { PrintErrorMessage(x, s); return y; }\\r
+  catch(...) { g_StartupInfo.ShowMessage(x); return y; }\r
+\r
+bool WasEscPressed();\r
+void ShowErrorMessage(DWORD errorCode);\r
+void ShowLastErrorMessage();\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Far/Main.cpp b/CPP/7zip/UI/Far/Main.cpp
new file mode 100755 (executable)
index 0000000..1f4d89d
--- /dev/null
@@ -0,0 +1,612 @@
+// Test Align for updating !!!!!!!!!!!!!!!!!!\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/MyInitGuid.h"\r
+\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/FileDir.h"\r
+#include "Windows/NtCheck.h"\r
+\r
+#include "../../Common/FileStreams.h"\r
+\r
+#include "../Agent/Agent.h"\r
+\r
+#include "Messages.h"\r
+#include "Plugin.h"\r
+#include "ProgressBox.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFar;\r
+\r
+static const char *kCommandPrefix = "7-zip";\r
+static const TCHAR *kRegisrtryMainKeyName = TEXT("");\r
+static const TCHAR *kRegisrtryValueNameEnabled = TEXT("UsedByDefault3");\r
+static const char *kHelpTopicConfig =  "Config";\r
+static bool kPluginEnabledDefault = true;\r
+\r
+HINSTANCE g_hInstance;\r
+\r
+#define NT_CHECK_FAIL_ACTION return FALSE;\r
+\r
+BOOL WINAPI DllMain(\r
+  #ifdef UNDER_CE\r
+  HANDLE\r
+  #else\r
+  HINSTANCE\r
+  #endif\r
+  hInstance, DWORD dwReason, LPVOID)\r
+{\r
+  if (dwReason == DLL_PROCESS_ATTACH)\r
+  {\r
+    g_hInstance = (HINSTANCE)hInstance;\r
+    NT_CHECK\r
+  }\r
+  return TRUE;\r
+}\r
+\r
+static struct COptions\r
+{\r
+  bool Enabled;\r
+} g_Options;\r
+\r
+static const TCHAR *kPliginNameForRegestry = TEXT("7-ZIP");\r
+\r
+EXTERN_C void WINAPI SetStartupInfo(const PluginStartupInfo *info)\r
+{\r
+  MY_TRY_BEGIN;\r
+  g_StartupInfo.Init(*info, kPliginNameForRegestry);\r
+  g_Options.Enabled = g_StartupInfo.QueryRegKeyValue(\r
+      HKEY_CURRENT_USER, kRegisrtryMainKeyName,\r
+      kRegisrtryValueNameEnabled, kPluginEnabledDefault);\r
+  MY_TRY_END1("SetStartupInfo");\r
+}\r
+\r
+class COpenArchiveCallback:\r
+  public IArchiveOpenCallback,\r
+  public IArchiveOpenVolumeCallback,\r
+  public IProgress,\r
+  public ICryptoGetTextPassword,\r
+  public CMyUnknownImp\r
+{\r
+  DWORD m_StartTickValue;\r
+  bool m_MessageBoxIsShown;\r
+\r
+  CProgressBox _progressBox;\r
+\r
+  UInt64 _numFilesTotal;\r
+  UInt64 _numFilesCur;\r
+  UInt64 _numBytesTotal;\r
+  UInt64 _numBytesCur;\r
+\r
+  bool _numFilesTotalDefined;\r
+  bool _numFilesCurDefined;\r
+  bool _numBytesTotalDefined;\r
+  bool _numBytesCurDefined;\r
+\r
+  DWORD m_PrevTickCount;\r
+\r
+  NWindows::NFile::NFind::CFileInfoW _fileInfo;\r
+public:\r
+  bool PasswordIsDefined;\r
+  UString Password;\r
+\r
+  UString _folderPrefix;\r
+\r
+public:\r
+  MY_UNKNOWN_IMP3(\r
+     IArchiveOpenVolumeCallback,\r
+     IProgress,\r
+     ICryptoGetTextPassword\r
+    )\r
+\r
+  // IProgress\r
+  STDMETHOD(SetTotal)(UInt64 total);\r
+  STDMETHOD(SetCompleted)(const UInt64 *aCompleteValue);\r
+\r
+  // IArchiveOpenCallback\r
+  STDMETHOD(SetTotal)(const UInt64 *numFiles, const UInt64 *numBytes);\r
+  STDMETHOD(SetCompleted)(const UInt64 *numFiles, const UInt64 *numBytes);\r
+\r
+  // IArchiveOpenVolumeCallback\r
+  STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value);\r
+  STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream);\r
+\r
+  // ICryptoGetTextPassword\r
+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);\r
+\r
+  void Init()\r
+  {\r
+    PasswordIsDefined = false;\r
+\r
+    _numFilesTotalDefined = false;\r
+    _numFilesCurDefined = false;\r
+    _numBytesTotalDefined = false;\r
+    _numBytesCurDefined = false;\r
+\r
+    m_MessageBoxIsShown = false;\r
+    m_PrevTickCount = GetTickCount();\r
+  }\r
+  void ShowMessage();\r
+\r
+  void LoadFileInfo(const UString &folderPrefix, const UString &fileName)\r
+  {\r
+    _folderPrefix = folderPrefix;\r
+    if (!_fileInfo.Find(_folderPrefix + fileName))\r
+      throw 1;\r
+  }\r
+};\r
+\r
+void COpenArchiveCallback::ShowMessage()\r
+{\r
+  DWORD currentTime = GetTickCount();\r
+  if (!m_MessageBoxIsShown)\r
+  {\r
+    if (currentTime - m_PrevTickCount < 100)\r
+      return;\r
+    _progressBox.Init(\r
+        // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),\r
+        g_StartupInfo.GetMsgString(NMessageID::kReading), 48);\r
+\r
+    m_MessageBoxIsShown = true;\r
+  }\r
+  else\r
+  {\r
+    if (currentTime - m_PrevTickCount < 200)\r
+      return;\r
+  }\r
+  m_PrevTickCount = currentTime;\r
+\r
+  UInt64 total = 0, cur = 0;\r
+  bool curIsDefined = false, totalIsDefined = false;\r
+\r
+  char message[256] = { 0 };\r
+  if (_numFilesCurDefined)\r
+    ConvertUInt64ToStringAligned(_numFilesCur, message, 5);\r
+\r
+  if (_numFilesTotalDefined)\r
+  {\r
+    strcat(message, " / ");\r
+    ConvertUInt64ToStringAligned(_numFilesTotal, message + strlen(message), 5);\r
+    total = _numFilesTotal;\r
+    totalIsDefined = true;\r
+    if (_numFilesCurDefined)\r
+    {\r
+      cur = _numFilesCur;\r
+      curIsDefined = true;\r
+    }\r
+  }\r
+  else if (_numBytesTotalDefined)\r
+  {\r
+    total = _numBytesTotal;\r
+    totalIsDefined = true;\r
+    if (_numBytesCurDefined)\r
+    {\r
+      cur = _numBytesCur;\r
+      curIsDefined = true;\r
+    }\r
+  }\r
+  _progressBox.Progress(\r
+      totalIsDefined ? &total: NULL,\r
+      curIsDefined ? &cur: NULL,\r
+      message);\r
+}\r
+\r
+STDMETHODIMP COpenArchiveCallback::SetTotal(const UInt64 *numFiles, const UInt64 *numBytes)\r
+{\r
+  if (WasEscPressed())\r
+    return E_ABORT;\r
+  \r
+  _numFilesTotalDefined = (numFiles != NULL);\r
+  if (_numFilesTotalDefined)\r
+    _numFilesTotal = *numFiles;\r
+\r
+  _numBytesTotalDefined = (numBytes != NULL);\r
+  if (_numBytesTotalDefined)\r
+    _numBytesTotal = *numBytes;\r
+\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP COpenArchiveCallback::SetCompleted(const UInt64 *numFiles, const UInt64 *numBytes)\r
+{\r
+  if (WasEscPressed())\r
+    return E_ABORT;\r
+\r
+  _numFilesCurDefined = (numFiles != NULL);\r
+  if (_numFilesCurDefined)\r
+    _numFilesCur = *numFiles;\r
+\r
+  _numBytesCurDefined = (numBytes != NULL);\r
+  if (_numBytesCurDefined)\r
+    _numBytesCur = *numBytes;\r
+\r
+  // if (*numFiles % 100 != 0)\r
+  //   return S_OK;\r
+  ShowMessage();\r
+  return S_OK;\r
+}\r
+\r
+\r
+STDMETHODIMP COpenArchiveCallback::SetTotal(const UInt64 /* total */)\r
+{\r
+  if (WasEscPressed())\r
+    return E_ABORT;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP COpenArchiveCallback::SetCompleted(const UInt64 *completed)\r
+{\r
+  if (WasEscPressed())\r
+    return E_ABORT;\r
+  if (completed == NULL)\r
+    return S_OK;\r
+  ShowMessage();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **inStream)\r
+{\r
+  if (WasEscPressed())\r
+    return E_ABORT;\r
+  *inStream = NULL;\r
+  UString fullPath = _folderPrefix + name;\r
+  if (!_fileInfo.Find(fullPath))\r
+    return S_FALSE;\r
+  if (_fileInfo.IsDir())\r
+    return S_FALSE;\r
+  CInFileStream *inFile = new CInFileStream;\r
+  CMyComPtr<IInStream> inStreamTemp = inFile;\r
+  if (!inFile->Open(fullPath))\r
+    return ::GetLastError();\r
+  *inStream = inStreamTemp.Detach();\r
+  return S_OK;\r
+}\r
+\r
+\r
+STDMETHODIMP COpenArchiveCallback::GetProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidName:  prop = GetUnicodeString(_fileInfo.Name, CP_OEMCP); break;\r
+    case kpidIsDir:  prop = _fileInfo.IsDir(); break;\r
+    case kpidSize:  prop = _fileInfo.Size; break;\r
+    case kpidAttrib:  prop = (UInt32)_fileInfo.Attrib; break;\r
+    case kpidCTime:  prop = _fileInfo.CTime; break;\r
+    case kpidATime:  prop = _fileInfo.ATime; break;\r
+    case kpidMTime:  prop = _fileInfo.MTime; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT GetPassword(UString &password)\r
+{\r
+  if (WasEscPressed())\r
+    return E_ABORT;\r
+  password.Empty();\r
+  CInitDialogItem initItems[]=\r
+  {\r
+    { DI_DOUBLEBOX, 3, 1, 72, 4, false, false, 0, false,  NMessageID::kGetPasswordTitle, NULL, NULL },\r
+    { DI_TEXT, 5, 2, 0, 0, false, false, DIF_SHOWAMPERSAND, false, NMessageID::kEnterPasswordForFile, NULL, NULL },\r
+    { DI_PSWEDIT, 5, 3, 70, 3, true, false, 0, true, -1, "", NULL }\r
+  };\r
+  \r
+  const int kNumItems = sizeof(initItems)/sizeof(initItems[0]);\r
+  FarDialogItem dialogItems[kNumItems];\r
+  g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumItems);\r
+  \r
+  // sprintf(DialogItems[1].Data,GetMsg(MGetPasswordForFile),FileName);\r
+  if (g_StartupInfo.ShowDialog(76, 6, NULL, dialogItems, kNumItems) < 0)\r
+    return (E_ABORT);\r
+\r
+  AString oemPassword = dialogItems[2].Data;\r
+  password = MultiByteToUnicodeString(oemPassword, CP_OEMCP);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP COpenArchiveCallback::CryptoGetTextPassword(BSTR *password)\r
+{\r
+  if (!PasswordIsDefined)\r
+  {\r
+    RINOK(GetPassword(Password));\r
+    PasswordIsDefined = true;\r
+  }\r
+  return StringToBstr(Password, password);\r
+}\r
+\r
+/*\r
+HRESULT OpenArchive(const CSysString &fileName,\r
+    IInFolderArchive **archiveHandlerResult,\r
+    CArchiverInfo &archiverInfoResult,\r
+    UString &defaultName,\r
+    IArchiveOpenCallback *openArchiveCallback)\r
+{\r
+  HRESULT OpenArchive(const CSysString &fileName,\r
+    IInArchive **archive,\r
+    CArchiverInfo &archiverInfoResult,\r
+    IArchiveOpenCallback *openArchiveCallback);\r
+}\r
+*/\r
+\r
+static HANDLE MyOpenFilePluginW(const wchar_t *name)\r
+{\r
+  UString normalizedName = name;\r
+  normalizedName.Trim();\r
+  UString fullName;\r
+  int fileNamePartStartIndex;\r
+  NFile::NDirectory::MyGetFullPathName(normalizedName, fullName, fileNamePartStartIndex);\r
+  NFile::NFind::CFileInfoW fileInfo;\r
+  if (!fileInfo.Find(fullName))\r
+    return INVALID_HANDLE_VALUE;\r
+  if (fileInfo.IsDir())\r
+     return INVALID_HANDLE_VALUE;\r
+\r
+\r
+  CMyComPtr<IInFolderArchive> archiveHandler;\r
+\r
+  // CArchiverInfo archiverInfoResult;\r
+  // ::OutputDebugStringA("before OpenArchive\n");\r
+  \r
+  CScreenRestorer screenRestorer;\r
+  {\r
+    screenRestorer.Save();\r
+  }\r
+\r
+  COpenArchiveCallback *openArchiveCallbackSpec = new COpenArchiveCallback;\r
+  CMyComPtr<IArchiveOpenCallback> openArchiveCallback = openArchiveCallbackSpec;\r
+\r
+  // if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0)\r
+  openArchiveCallbackSpec->Init();\r
+  openArchiveCallbackSpec->LoadFileInfo(\r
+      fullName.Left(fileNamePartStartIndex),\r
+      fullName.Mid(fileNamePartStartIndex));\r
+  \r
+  // ::OutputDebugStringA("before OpenArchive\n");\r
+  \r
+  CAgent *agent = new CAgent;\r
+  archiveHandler = agent;\r
+  CMyComBSTR archiveType;\r
+  HRESULT result = archiveHandler->Open(NULL,\r
+      GetUnicodeString(fullName, CP_OEMCP), UString(), &archiveType, openArchiveCallback);\r
+  /*\r
+  HRESULT result = ::OpenArchive(fullName, &archiveHandler,\r
+      archiverInfoResult, defaultName, openArchiveCallback);\r
+  */\r
+  if (result != S_OK)\r
+  {\r
+    if (result == E_ABORT)\r
+      return (HANDLE)-2;\r
+    return INVALID_HANDLE_VALUE;\r
+  }\r
+\r
+  UString errorMessage = agent->GetErrorMessage();\r
+  if (!errorMessage.IsEmpty())\r
+    PrintErrorMessage("7-Zip", UnicodeStringToMultiByte(errorMessage, CP_OEMCP));\r
+\r
+  // ::OutputDebugStringA("after OpenArchive\n");\r
+\r
+  CPlugin *plugin = new CPlugin(\r
+      fullName,\r
+      // defaultName,\r
+      archiveHandler,\r
+      (const wchar_t *)archiveType\r
+      );\r
+  if (plugin == NULL)\r
+    return(INVALID_HANDLE_VALUE);\r
+  plugin->PasswordIsDefined = openArchiveCallbackSpec->PasswordIsDefined;\r
+  plugin->Password = openArchiveCallbackSpec->Password;\r
+\r
+  return (HANDLE)(plugin);\r
+}\r
+\r
+static HANDLE MyOpenFilePlugin(const char *name)\r
+{\r
+  UINT codePage =\r
+  #ifdef UNDER_CE\r
+    CP_OEMCP;\r
+  #else\r
+    ::AreFileApisANSI() ? CP_ACP : CP_OEMCP;\r
+  #endif\r
+  return MyOpenFilePluginW(GetUnicodeString(name, codePage));\r
+}\r
+\r
+EXTERN_C HANDLE WINAPI OpenFilePlugin(char *name, const unsigned char * /* data */, int /* dataSize */)\r
+{\r
+  MY_TRY_BEGIN;\r
+  if (name == NULL || (!g_Options.Enabled))\r
+  {\r
+    // if (!Opt.ProcessShiftF1)\r
+      return(INVALID_HANDLE_VALUE);\r
+  }\r
+  return MyOpenFilePlugin(name);\r
+  MY_TRY_END2("OpenFilePlugin", INVALID_HANDLE_VALUE);\r
+}\r
+\r
+/*\r
+EXTERN_C HANDLE WINAPI OpenFilePluginW(const wchar_t *name,const unsigned char *Data,int DataSize,int OpMode)\r
+{\r
+  MY_TRY_BEGIN;\r
+  if (name == NULL || (!g_Options.Enabled))\r
+  {\r
+    // if (!Opt.ProcessShiftF1)\r
+      return(INVALID_HANDLE_VALUE);\r
+  }\r
+  return MyOpenFilePluginW(name);\r
+  ::OutputDebugStringA("OpenFilePluginW\n");\r
+  MY_TRY_END2("OpenFilePluginW", INVALID_HANDLE_VALUE);\r
+}\r
+*/\r
+\r
+EXTERN_C HANDLE WINAPI OpenPlugin(int openFrom, INT_PTR item)\r
+{\r
+  MY_TRY_BEGIN;\r
+  if(openFrom == OPEN_COMMANDLINE)\r
+  {\r
+    AString fileName = (const char *)item;\r
+    if(fileName.IsEmpty())\r
+      return INVALID_HANDLE_VALUE;\r
+    if (fileName.Length() >= 2 &&\r
+        fileName[0] == '\"' && fileName[fileName.Length() - 1] == '\"')\r
+      fileName = fileName.Mid(1, fileName.Length() - 2);\r
+\r
+    return MyOpenFilePlugin(fileName);\r
+  }\r
+  if(openFrom == OPEN_PLUGINSMENU)\r
+  {\r
+    switch(item)\r
+    {\r
+      case 0:\r
+      {\r
+        PluginPanelItem pluginPanelItem;\r
+        if(!g_StartupInfo.ControlGetActivePanelCurrentItemInfo(pluginPanelItem))\r
+          throw 142134;\r
+        return MyOpenFilePlugin(pluginPanelItem.FindData.cFileName);\r
+      }\r
+      case 1:\r
+      {\r
+        CObjectVector<PluginPanelItem> pluginPanelItem;\r
+        if(!g_StartupInfo.ControlGetActivePanelSelectedOrCurrentItems(pluginPanelItem))\r
+          throw 142134;\r
+        if (CompressFiles(pluginPanelItem) == S_OK)\r
+        {\r
+          /* int t = */ g_StartupInfo.ControlClearPanelSelection();\r
+          g_StartupInfo.ControlRequestActivePanel(FCTL_UPDATEPANEL, NULL);\r
+          g_StartupInfo.ControlRequestActivePanel(FCTL_REDRAWPANEL, NULL);\r
+          g_StartupInfo.ControlRequestActivePanel(FCTL_UPDATEANOTHERPANEL, NULL);\r
+          g_StartupInfo.ControlRequestActivePanel(FCTL_REDRAWANOTHERPANEL, NULL);\r
+        }\r
+        return INVALID_HANDLE_VALUE;\r
+      }\r
+      default:\r
+        throw 4282215;\r
+    }\r
+  }\r
+  return INVALID_HANDLE_VALUE;\r
+  MY_TRY_END2("OpenPlugin", INVALID_HANDLE_VALUE);\r
+}\r
+\r
+EXTERN_C void WINAPI ClosePlugin(HANDLE plugin)\r
+{\r
+  MY_TRY_BEGIN;\r
+  delete (CPlugin *)plugin;\r
+  MY_TRY_END1("ClosePlugin");\r
+}\r
+\r
+EXTERN_C int WINAPI GetFindData(HANDLE plugin, struct PluginPanelItem **panelItems, int *itemsNumber, int opMode)\r
+{\r
+  MY_TRY_BEGIN;\r
+  return(((CPlugin *)plugin)->GetFindData(panelItems, itemsNumber, opMode));\r
+  MY_TRY_END2("GetFindData", FALSE);\r
+}\r
+\r
+EXTERN_C void WINAPI FreeFindData(HANDLE plugin, struct PluginPanelItem *panelItems, int itemsNumber)\r
+{\r
+  MY_TRY_BEGIN;\r
+  ((CPlugin *)plugin)->FreeFindData(panelItems, itemsNumber);\r
+  MY_TRY_END1("FreeFindData");\r
+}\r
+\r
+EXTERN_C int WINAPI GetFiles(HANDLE plugin, struct PluginPanelItem *panelItems,\r
+    int itemsNumber, int move, char *destPath, int opMode)\r
+{\r
+  MY_TRY_BEGIN;\r
+  return(((CPlugin *)plugin)->GetFiles(panelItems, itemsNumber, move, destPath, opMode));\r
+  MY_TRY_END2("GetFiles", NFileOperationReturnCode::kError);\r
+}\r
+\r
+EXTERN_C int WINAPI SetDirectory(HANDLE plugin, const char *dir, int opMode)\r
+{\r
+  MY_TRY_BEGIN;\r
+  return(((CPlugin *)plugin)->SetDirectory(dir, opMode));\r
+  MY_TRY_END2("SetDirectory", FALSE);\r
+}\r
+\r
+EXTERN_C void WINAPI GetPluginInfo(struct PluginInfo *info)\r
+{\r
+  MY_TRY_BEGIN;\r
+\r
+  info->StructSize = sizeof(*info);\r
+  info->Flags = 0;\r
+  info->DiskMenuStrings = NULL;\r
+  info->DiskMenuNumbers = NULL;\r
+  info->DiskMenuStringsNumber = 0;\r
+  static const char *pluginMenuStrings[2];\r
+  pluginMenuStrings[0] = g_StartupInfo.GetMsgString(NMessageID::kOpenArchiveMenuString);\r
+  pluginMenuStrings[1] = g_StartupInfo.GetMsgString(NMessageID::kCreateArchiveMenuString);\r
+  info->PluginMenuStrings = (char **)pluginMenuStrings;\r
+  info->PluginMenuStringsNumber = 2;\r
+  static const char *pluginCfgStrings[1];\r
+  pluginCfgStrings[0] = g_StartupInfo.GetMsgString(NMessageID::kOpenArchiveMenuString);\r
+  info->PluginConfigStrings = (char **)pluginCfgStrings;\r
+  info->PluginConfigStringsNumber = sizeof(pluginCfgStrings) / sizeof(pluginCfgStrings[0]);\r
+  info->CommandPrefix = (char *)kCommandPrefix;\r
+  MY_TRY_END1("GetPluginInfo");\r
+}\r
+\r
+EXTERN_C int WINAPI Configure(int /* itemNumber */)\r
+{\r
+  MY_TRY_BEGIN;\r
+\r
+  const int kEnabledCheckBoxIndex = 1;\r
+\r
+  const int kYSize = 7;\r
+\r
+  struct CInitDialogItem initItems[]=\r
+  {\r
+    { DI_DOUBLEBOX, 3, 1, 72, kYSize - 2, false, false, 0, false, NMessageID::kConfigTitle, NULL, NULL },\r
+    { DI_CHECKBOX, 5, 2, 0, 0, true, g_Options.Enabled, 0, false, NMessageID::kConfigPluginEnabled, NULL, NULL },\r
+    { DI_TEXT, 5, 3, 0, 0, false, false, DIF_BOXCOLOR | DIF_SEPARATOR, false, -1, "", NULL },\r
+    { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kOk, NULL, NULL },\r
+    { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kCancel, NULL, NULL },\r
+  };\r
+\r
+  const int kNumDialogItems = sizeof(initItems) / sizeof(initItems[0]);\r
+  const int kOkButtonIndex = kNumDialogItems - 2;\r
+\r
+  FarDialogItem dialogItems[kNumDialogItems];\r
+  g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems);\r
+\r
+  int askCode = g_StartupInfo.ShowDialog(76, kYSize,\r
+      kHelpTopicConfig, dialogItems, kNumDialogItems);\r
+\r
+  if (askCode != kOkButtonIndex)\r
+    return (FALSE);\r
+\r
+  g_Options.Enabled = BOOLToBool(dialogItems[kEnabledCheckBoxIndex].Selected);\r
+\r
+  g_StartupInfo.SetRegKeyValue(HKEY_CURRENT_USER, kRegisrtryMainKeyName,\r
+      kRegisrtryValueNameEnabled, g_Options.Enabled);\r
+  return(TRUE);\r
+  MY_TRY_END2("Configure", FALSE);\r
+}\r
+\r
+EXTERN_C void WINAPI GetOpenPluginInfo(HANDLE plugin,struct OpenPluginInfo *info)\r
+{\r
+  MY_TRY_BEGIN;\r
+  ((CPlugin *)plugin)->GetOpenPluginInfo(info);\r
+  MY_TRY_END1("GetOpenPluginInfo");\r
+}\r
+\r
+EXTERN_C int WINAPI PutFiles(HANDLE plugin, struct PluginPanelItem *panelItems, int itemsNumber, int move, int opMode)\r
+{\r
+  MY_TRY_BEGIN;\r
+  return(((CPlugin *)plugin)->PutFiles(panelItems, itemsNumber, move, opMode));\r
+  MY_TRY_END2("PutFiles", NFileOperationReturnCode::kError);\r
+}\r
+\r
+EXTERN_C int WINAPI DeleteFiles(HANDLE plugin, PluginPanelItem *panelItems, int itemsNumber, int opMode)\r
+{\r
+  MY_TRY_BEGIN;\r
+  return(((CPlugin *)plugin)->DeleteFiles(panelItems, itemsNumber, opMode));\r
+  MY_TRY_END2("DeleteFiles", FALSE);\r
+}\r
+\r
+EXTERN_C int WINAPI ProcessKey(HANDLE plugin, int key, unsigned int controlState)\r
+{\r
+  MY_TRY_BEGIN;\r
+  return (((CPlugin *)plugin)->ProcessKey(key, controlState));\r
+  MY_TRY_END2("ProcessKey", FALSE);\r
+}\r
diff --git a/CPP/7zip/UI/Far/Messages.h b/CPP/7zip/UI/Far/Messages.h
new file mode 100755 (executable)
index 0000000..b2aadf5
--- /dev/null
@@ -0,0 +1,184 @@
+// SevenZip/ Messages.h\r
+\r
+#ifndef __SEVENZIP_MESSAGES_H\r
+#define __SEVENZIP_MESSAGES_H\r
+\r
+namespace NMessageID {\r
+\r
+enum EEnum\r
+{\r
+  kOk,\r
+  kCancel,\r
+\r
+  kWarning,\r
+  kError,\r
+\r
+  kArchiveType,\r
+\r
+  kProperties,\r
+\r
+  kYes,\r
+  kNo,\r
+  \r
+  kPath,\r
+  kName,\r
+  kExtension,\r
+  kIsFolder,\r
+  kSize,\r
+  kPackSize,\r
+  kAttributes,\r
+  kCTime,\r
+  kATime,\r
+  kMTime,\r
+  kSolid,\r
+  kCommented,\r
+  kEncrypted,\r
+  kSplitBefore,\r
+  kSplitAfter,\r
+  kDictionarySize,\r
+  kCRC,\r
+  kType,\r
+  kAnti,\r
+  kMethod,\r
+  kHostOS,\r
+  kFileSystem,\r
+  kUser,\r
+  kGroup,\r
+  kBlock,\r
+  kComment,\r
+  kPosition,\r
+  kNumSubFolders,\r
+  kNumSubFiles,\r
+  kUnpackVer,\r
+  kVolume,\r
+  kIsVolume,\r
+  kOffset,\r
+  kLinks,\r
+  kNumBlocks,\r
+  kNumVolumes,\r
+\r
+  kBit64,\r
+  kBigEndian,\r
+  kCpu,\r
+  kPhySize,\r
+  kHeadersSize,\r
+  kChecksum,\r
+  kCharacts,\r
+  kVa,\r
+  kId,\r
+  kShortName,\r
+  kCreatorApp,\r
+  kSectorSize,\r
+  kPosixAttrib,\r
+  kLink,\r
+\r
+  kTotalSize,\r
+  kFreeSpace,\r
+  kClusterSize,\r
+  kLabel,\r
+\r
+  kGetPasswordTitle,\r
+  kEnterPasswordForFile,\r
+\r
+  kExtractTitle,\r
+  kExtractTo,\r
+\r
+  kExtractPathMode,\r
+  kExtractPathFull,\r
+  kExtractPathCurrent,\r
+  kExtractPathNo,\r
+\r
+  kExtractOwerwriteMode,\r
+  kExtractOwerwriteAsk,\r
+  kExtractOwerwritePrompt,\r
+  kExtractOwerwriteSkip,\r
+  kExtractOwerwriteAutoRename,\r
+  kExtractOwerwriteAutoRenameExisting,\r
+\r
+  kExtractFilesMode,\r
+  kExtractFilesSelected,\r
+  kExtractFilesAll,\r
+\r
+  kExtractPassword,\r
+\r
+  kExtractExtract,\r
+  kExtractCancel,\r
+\r
+  kExtractCanNotOpenOutputFile,\r
+\r
+  kExtractUnsupportedMethod,\r
+  kExtractCRCFailed,\r
+  kExtractDataError,\r
+  kExtractCRCFailedEncrypted,\r
+  kExtractDataErrorEncrypted,\r
+\r
+  kOverwriteTitle,\r
+  kOverwriteMessage1,\r
+  kOverwriteMessageWouldYouLike,\r
+  kOverwriteMessageWithtTisOne,\r
+\r
+  kOverwriteBytes,\r
+  kOverwriteModifiedOn,\r
+\r
+  kOverwriteYes,\r
+  kOverwriteYesToAll,\r
+  kOverwriteNo,\r
+  kOverwriteNoToAll,\r
+  kOverwriteAutoRename,\r
+  kOverwriteCancel,\r
+\r
+  kUpdateNotSupportedForThisArchive,\r
+\r
+  kDeleteTitle,\r
+  kDeleteFile,\r
+  kDeleteFiles,\r
+  kDeleteNumberOfFiles,\r
+  kDeleteDelete,\r
+  kDeleteCancel,\r
+\r
+  kUpdateTitle,\r
+  kUpdateAddToArchive,\r
+\r
+  kUpdateMethod,\r
+  kUpdateMethodStore,\r
+  kUpdateMethodFastest,\r
+  kUpdateMethodFast,\r
+  kUpdateMethodNormal,\r
+  kUpdateMethodMaximum,\r
+  kUpdateMethodUltra,\r
+\r
+  kUpdateMode,\r
+  kUpdateModeAdd,\r
+  kUpdateModeUpdate,\r
+  kUpdateModeFreshen,\r
+  kUpdateModeSynchronize,\r
+\r
+  kUpdateAdd,\r
+  kUpdateSelectArchiver,\r
+\r
+  kUpdateSelectArchiverMenuTitle,\r
+\r
+  // kArcReadFiles,\r
+  \r
+  kWaitTitle,\r
+  \r
+  kReading,\r
+  kExtracting,\r
+  kDeleting,\r
+  kUpdating,\r
+  \r
+  // kReadingList,\r
+\r
+  kMoveIsNotSupported,\r
+\r
+  kOpenArchiveMenuString,\r
+  kCreateArchiveMenuString,\r
+\r
+  kConfigTitle,\r
+  \r
+  kConfigPluginEnabled\r
+};\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Far/OverwriteDialog.cpp b/CPP/7zip/UI/Far/OverwriteDialog.cpp
new file mode 100755 (executable)
index 0000000..9e4911d
--- /dev/null
@@ -0,0 +1,112 @@
+// OverwriteDialog.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include <stdio.h>\r
+\r
+#include "OverwriteDialog.h"\r
+\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/FileName.h"\r
+#include "Windows/Defs.h"\r
+#include "Windows/PropVariantConversions.h"\r
+\r
+#include "FarUtils.h"\r
+#include "Messages.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFar;\r
+\r
+namespace NOverwriteDialog {\r
+\r
+struct CFileInfoStrings\r
+{\r
+  AString Size;\r
+  AString Time;\r
+};\r
+\r
+void SetFileInfoStrings(const CFileInfo &fileInfo,\r
+    CFileInfoStrings &fileInfoStrings)\r
+{\r
+  char buffer[256];\r
+\r
+  if (fileInfo.SizeIsDefined)\r
+  {\r
+    sprintf(buffer, "%I64u ", fileInfo.Size);\r
+    fileInfoStrings.Size = buffer;\r
+    fileInfoStrings.Size += g_StartupInfo.GetMsgString(NMessageID::kOverwriteBytes);\r
+  }\r
+  else\r
+  {\r
+    fileInfoStrings.Size = "";\r
+  }\r
+\r
+  FILETIME localFileTime;\r
+  fileInfoStrings.Time.Empty();\r
+  if (fileInfo.TimeIsDefined)\r
+  {\r
+    if (!FileTimeToLocalFileTime(&fileInfo.Time, &localFileTime))\r
+      throw 4190402;\r
+    UString timeString = ConvertFileTimeToString(localFileTime);\r
+    fileInfoStrings.Time = g_StartupInfo.GetMsgString(NMessageID::kOverwriteModifiedOn);\r
+    fileInfoStrings.Time += " ";\r
+    fileInfoStrings.Time += UnicodeStringToMultiByte(timeString, CP_OEMCP);\r
+  }\r
+}\r
+\r
+NResult::EEnum Execute(const CFileInfo &oldFileInfo, const CFileInfo &newFileInfo)\r
+{\r
+  const int kYSize = 20;\r
+  const int kXSize = 76;\r
+  \r
+  CFileInfoStrings oldFileInfoStrings;\r
+  CFileInfoStrings newFileInfoStrings;\r
+\r
+  SetFileInfoStrings(oldFileInfo, oldFileInfoStrings);\r
+  SetFileInfoStrings(newFileInfo, newFileInfoStrings);\r
+\r
+  AString oldName = UnicodeStringToMultiByte(oldFileInfo.Name, CP_OEMCP);\r
+  AString newName = UnicodeStringToMultiByte(newFileInfo.Name, CP_OEMCP);\r
+\r
+  struct CInitDialogItem initItems[]={\r
+    { DI_DOUBLEBOX, 3, 1, kXSize - 4, kYSize - 2, false, false, 0, false, NMessageID::kOverwriteTitle, NULL, NULL },\r
+    { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, NMessageID::kOverwriteMessage1, NULL, NULL },\r
+    \r
+    { DI_TEXT, 3, 3, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL  },\r
+    \r
+    { DI_TEXT, 5, 4, 0, 0, false, false, 0, false, NMessageID::kOverwriteMessageWouldYouLike, NULL, NULL },\r
+\r
+    { DI_TEXT, 7, 6, 0, 0, false, false, 0, false,  -1, oldName, NULL },\r
+    { DI_TEXT, 7, 7, 0, 0, false, false, 0, false,  -1, oldFileInfoStrings.Size, NULL },\r
+    { DI_TEXT, 7, 8, 0, 0, false, false, 0, false,  -1, oldFileInfoStrings.Time, NULL },\r
+\r
+    { DI_TEXT, 5, 10, 0, 0, false, false, 0, false, NMessageID::kOverwriteMessageWithtTisOne, NULL, NULL },\r
+    \r
+    { DI_TEXT, 7, 12, 0, 0, false, false, 0, false,  -1, newName, NULL },\r
+    { DI_TEXT, 7, 13, 0, 0, false, false, 0, false,  -1, newFileInfoStrings.Size, NULL },\r
+    { DI_TEXT, 7, 14, 0, 0, false, false, 0, false,  -1, newFileInfoStrings.Time, NULL },\r
+\r
+    { DI_TEXT, 3, kYSize - 5, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL  },\r
+        \r
+    { DI_BUTTON, 0, kYSize - 4, 0, 0, true, false, DIF_CENTERGROUP, true, NMessageID::kOverwriteYes, NULL, NULL  },\r
+    { DI_BUTTON, 0, kYSize - 4, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteYesToAll, NULL, NULL  },\r
+    { DI_BUTTON, 0, kYSize - 4, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteNo, NULL, NULL  },\r
+    { DI_BUTTON, 0, kYSize - 4, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteNoToAll, NULL, NULL  },\r
+    { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteAutoRename, NULL, NULL  },\r
+    { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteCancel, NULL, NULL  }\r
+  };\r
+  \r
+  const int kNumDialogItems = sizeof(initItems) / sizeof(initItems[0]);\r
+  FarDialogItem aDialogItems[kNumDialogItems];\r
+  g_StartupInfo.InitDialogItems(initItems, aDialogItems, kNumDialogItems);\r
+  int anAskCode = g_StartupInfo.ShowDialog(kXSize, kYSize,\r
+      NULL, aDialogItems, kNumDialogItems);\r
+  const int kButtonStartPos = kNumDialogItems - 6;\r
+  if (anAskCode >= kButtonStartPos && anAskCode < kNumDialogItems)\r
+    return NResult::EEnum(anAskCode - kButtonStartPos);\r
+  return NResult::kCancel;\r
+}\r
+\r
+}\r
+\r
diff --git a/CPP/7zip/UI/Far/OverwriteDialog.h b/CPP/7zip/UI/Far/OverwriteDialog.h
new file mode 100755 (executable)
index 0000000..76625f4
--- /dev/null
@@ -0,0 +1,37 @@
+// OverwriteDialog.h\r
+\r
+#ifndef OVERWRITEDIALOG_H\r
+#define OVERWRITEDIALOG_H\r
+\r
+#include "Common/MyString.h"\r
+#include "Common/Types.h"\r
+\r
+namespace NOverwriteDialog {\r
+\r
+struct CFileInfo\r
+{\r
+  bool SizeIsDefined;\r
+  bool TimeIsDefined;\r
+  UInt64 Size;\r
+  FILETIME Time;\r
+  UString Name;\r
+};\r
+\r
+namespace NResult\r
+{\r
+  enum EEnum\r
+  {\r
+    kYes,\r
+    kYesToAll,\r
+    kNo,\r
+    kNoToAll,\r
+    kAutoRename,\r
+    kCancel\r
+  };\r
+}\r
+\r
+NResult::EEnum Execute(const CFileInfo &oldFileInfo, const CFileInfo &newFileInfo);\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Far/Plugin.cpp b/CPP/7zip/UI/Far/Plugin.cpp
new file mode 100755 (executable)
index 0000000..6263149
--- /dev/null
@@ -0,0 +1,871 @@
+// Plugin.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+#include "Common/Wildcard.h"\r
+\r
+#include "Windows/FileDir.h"\r
+#include "Windows/PropVariantConversions.h"\r
+\r
+#include "../Common/PropIDUtils.h"\r
+\r
+#include "FarUtils.h"\r
+#include "Messages.h"\r
+#include "Plugin.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFar;\r
+\r
+CPlugin::CPlugin(const UString &fileName, IInFolderArchive *archiveHandler, UString archiveTypeName):\r
+    m_ArchiveHandler(archiveHandler),\r
+    m_FileName(fileName),\r
+    _archiveTypeName(archiveTypeName)\r
+{\r
+  if (!m_FileInfo.Find(m_FileName))\r
+    throw "error";\r
+  archiveHandler->BindToRootFolder(&_folder);\r
+}\r
+\r
+CPlugin::~CPlugin() {}\r
+\r
+static void MyGetFileTime(IFolderFolder *anArchiveFolder, UInt32 itemIndex,\r
+    PROPID propID, FILETIME &fileTime)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  if (anArchiveFolder->GetProperty(itemIndex, propID, &prop) != S_OK)\r
+    throw 271932;\r
+  if (prop.vt == VT_EMPTY)\r
+  {\r
+    fileTime.dwHighDateTime = 0;\r
+    fileTime.dwLowDateTime = 0;\r
+  }\r
+  else\r
+  {\r
+    if (prop.vt != VT_FILETIME)\r
+      throw 4191730;\r
+    fileTime = prop.filetime;\r
+  }\r
+}\r
+\r
+#define kDotsReplaceString "[[..]]"\r
+#define kDotsReplaceStringU L"[[..]]"\r
+  \r
+static void CopyStrLimited(char *dest, const AString &src, int len)\r
+{\r
+  len--;\r
+  if (src.Length() < len)\r
+    len = src.Length();\r
+  memcpy(dest, src, sizeof(dest[0]) * len);\r
+  dest[len] = 0;\r
+}\r
+\r
+#define COPY_STR_LIMITED(dest, src) CopyStrLimited(dest, src, sizeof(dest) / sizeof(dest[0]))\r
+\r
+void CPlugin::ReadPluginPanelItem(PluginPanelItem &panelItem, UInt32 itemIndex)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  if (_folder->GetProperty(itemIndex, kpidName, &prop) != S_OK)\r
+    throw 271932;\r
+\r
+  if (prop.vt != VT_BSTR)\r
+    throw 272340;\r
+\r
+  AString oemString = UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP);\r
+  if (oemString == "..")\r
+    oemString = kDotsReplaceString;\r
+\r
+  COPY_STR_LIMITED(panelItem.FindData.cFileName, oemString);\r
+  panelItem.FindData.cAlternateFileName[0] = 0;\r
+\r
+  if (_folder->GetProperty(itemIndex, kpidAttrib, &prop) != S_OK)\r
+    throw 271932;\r
+  if (prop.vt == VT_UI4)\r
+    panelItem.FindData.dwFileAttributes  = prop.ulVal;\r
+  else if (prop.vt == VT_EMPTY)\r
+    panelItem.FindData.dwFileAttributes = m_FileInfo.Attrib;\r
+  else\r
+    throw 21631;\r
+\r
+  if (_folder->GetProperty(itemIndex, kpidIsDir, &prop) != S_OK)\r
+    throw 271932;\r
+  if (prop.vt == VT_BOOL)\r
+  {\r
+    if (VARIANT_BOOLToBool(prop.boolVal))\r
+      panelItem.FindData.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;\r
+  }\r
+  else if (prop.vt != VT_EMPTY)\r
+    throw 21632;\r
+\r
+  if (_folder->GetProperty(itemIndex, kpidSize, &prop) != S_OK)\r
+    throw 271932;\r
+  UInt64 length;\r
+  if (prop.vt == VT_EMPTY)\r
+    length = 0;\r
+  else\r
+    length = ::ConvertPropVariantToUInt64(prop);\r
+  panelItem.FindData.nFileSizeLow = (UInt32)length;\r
+  panelItem.FindData.nFileSizeHigh = (UInt32)(length >> 32);\r
+\r
+  MyGetFileTime(_folder, itemIndex, kpidCTime, panelItem.FindData.ftCreationTime);\r
+  MyGetFileTime(_folder, itemIndex, kpidATime, panelItem.FindData.ftLastAccessTime);\r
+  MyGetFileTime(_folder, itemIndex, kpidMTime, panelItem.FindData.ftLastWriteTime);\r
+\r
+  if (panelItem.FindData.ftLastWriteTime.dwHighDateTime == 0 &&\r
+      panelItem.FindData.ftLastWriteTime.dwLowDateTime == 0)\r
+    panelItem.FindData.ftLastWriteTime = m_FileInfo.MTime;\r
+\r
+  if (_folder->GetProperty(itemIndex, kpidPackSize, &prop) != S_OK)\r
+    throw 271932;\r
+  if (prop.vt == VT_EMPTY)\r
+    length = 0;\r
+  else\r
+    length = ::ConvertPropVariantToUInt64(prop);\r
+  panelItem.PackSize = UInt32(length);\r
+  panelItem.PackSizeHigh = UInt32(length >> 32);\r
+\r
+  panelItem.Flags = 0;\r
+  panelItem.NumberOfLinks = 0;\r
+\r
+  panelItem.Description = NULL;\r
+  panelItem.Owner = NULL;\r
+  panelItem.CustomColumnData = NULL;\r
+  panelItem.CustomColumnNumber = 0;\r
+\r
+  panelItem.CRC32 = 0;\r
+  panelItem.Reserved[0] = 0;\r
+  panelItem.Reserved[1] = 0;\r
+}\r
+\r
+int CPlugin::GetFindData(PluginPanelItem **panelItems, int *itemsNumber, int opMode)\r
+{\r
+  // CScreenRestorer screenRestorer;\r
+  if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0)\r
+  {\r
+    /*\r
+    screenRestorer.Save();\r
+    const char *msgItems[]=\r
+    {\r
+      g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),\r
+        g_StartupInfo.GetMsgString(NMessageID::kReadingList)\r
+    };\r
+    g_StartupInfo.ShowMessage(0, NULL, msgItems,\r
+      sizeof(msgItems) / sizeof(msgItems[0]), 0);\r
+    */\r
+  }\r
+\r
+  UInt32 numItems;\r
+  _folder->GetNumberOfItems(&numItems);\r
+  *panelItems = new PluginPanelItem[numItems];\r
+  try\r
+  {\r
+    for (UInt32 i = 0; i < numItems; i++)\r
+    {\r
+      PluginPanelItem &panelItem = (*panelItems)[i];\r
+      ReadPluginPanelItem(panelItem, i);\r
+      panelItem.UserData = i;\r
+    }\r
+  }\r
+  catch(...)\r
+  {\r
+    delete [](*panelItems);\r
+    throw;\r
+  }\r
+  *itemsNumber = numItems;\r
+  return(TRUE);\r
+}\r
+\r
+void CPlugin::FreeFindData(struct PluginPanelItem *panelItems, int itemsNumber)\r
+{\r
+  for (int i = 0; i < itemsNumber; i++)\r
+    if (panelItems[i].Description != NULL)\r
+      delete []panelItems[i].Description;\r
+  delete []panelItems;\r
+}\r
+\r
+void CPlugin::EnterToDirectory(const UString &dirName)\r
+{\r
+  CMyComPtr<IFolderFolder> newFolder;\r
+  UString s = dirName;\r
+  if (dirName == kDotsReplaceStringU)\r
+    s = L"..";\r
+  _folder->BindToFolder(s, &newFolder);\r
+  if (newFolder == NULL)\r
+    if (dirName.IsEmpty())\r
+      return;\r
+    else\r
+      throw 40325;\r
+  _folder = newFolder;\r
+}\r
+\r
+int CPlugin::SetDirectory(const char *aszDir, int /* opMode */)\r
+{\r
+  UString path = MultiByteToUnicodeString(aszDir, CP_OEMCP);\r
+  if (path == WSTRING_PATH_SEPARATOR)\r
+  {\r
+    _folder.Release();\r
+    m_ArchiveHandler->BindToRootFolder(&_folder);\r
+  }\r
+  else if (path == L"..")\r
+  {\r
+    CMyComPtr<IFolderFolder> newFolder;\r
+    _folder->BindToParentFolder(&newFolder);\r
+    if (newFolder == NULL)\r
+      throw 40312;\r
+    _folder = newFolder;\r
+  }\r
+  else if (path.IsEmpty())\r
+    EnterToDirectory(path);\r
+  else\r
+  {\r
+    if (path[0] == WCHAR_PATH_SEPARATOR)\r
+    {\r
+      _folder.Release();\r
+      m_ArchiveHandler->BindToRootFolder(&_folder);\r
+      path = path.Mid(1);\r
+    }\r
+    UStringVector pathParts;\r
+    SplitPathToParts(path, pathParts);\r
+    for (int i = 0; i < pathParts.Size(); i++)\r
+      EnterToDirectory(pathParts[i]);\r
+  }\r
+  GetCurrentDir();\r
+  return TRUE;\r
+}\r
+\r
+void CPlugin::GetPathParts(UStringVector &pathParts)\r
+{\r
+  pathParts.Clear();\r
+  CMyComPtr<IFolderFolder> folderItem = _folder;\r
+  for (;;)\r
+  {\r
+    CMyComPtr<IFolderFolder> newFolder;\r
+    folderItem->BindToParentFolder(&newFolder);\r
+    if (newFolder == NULL)\r
+      break;\r
+    NCOM::CPropVariant prop;\r
+    if (folderItem->GetFolderProperty(kpidName, &prop) == S_OK)\r
+      if (prop.vt == VT_BSTR)\r
+        pathParts.Insert(0, (const wchar_t *)prop.bstrVal);\r
+    folderItem = newFolder;\r
+  }\r
+}\r
+\r
+void CPlugin::GetCurrentDir()\r
+{\r
+  m_CurrentDir.Empty();\r
+  UStringVector pathParts;\r
+  GetPathParts(pathParts);\r
+  for (int i = 0; i < pathParts.Size(); i++)\r
+  {\r
+    m_CurrentDir += WCHAR_PATH_SEPARATOR;\r
+    m_CurrentDir += pathParts[i];\r
+  }\r
+}\r
+\r
+static char *kPluginFormatName = "7-ZIP";\r
+\r
+\r
+struct CPROPIDToName\r
+{\r
+  PROPID PropID;\r
+  int PluginID;\r
+};\r
+\r
+static CPROPIDToName kPROPIDToName[] =\r
+{\r
+  { kpidPath, NMessageID::kPath },\r
+  { kpidName, NMessageID::kName },\r
+  { kpidExtension, NMessageID::kExtension },\r
+  { kpidIsDir, NMessageID::kIsFolder },\r
+  { kpidSize, NMessageID::kSize },\r
+  { kpidPackSize, NMessageID::kPackSize },\r
+  { kpidAttrib, NMessageID::kAttributes },\r
+  { kpidCTime, NMessageID::kCTime },\r
+  { kpidATime, NMessageID::kATime },\r
+  { kpidMTime, NMessageID::kMTime },\r
+  { kpidSolid, NMessageID::kSolid },\r
+  { kpidCommented, NMessageID::kCommented },\r
+  { kpidEncrypted, NMessageID::kEncrypted },\r
+  { kpidSplitBefore, NMessageID::kSplitBefore },\r
+  { kpidSplitAfter, NMessageID::kSplitAfter },\r
+  { kpidDictionarySize, NMessageID::kDictionarySize },\r
+  { kpidCRC, NMessageID::kCRC },\r
+  { kpidType, NMessageID::kType },\r
+  { kpidIsAnti, NMessageID::kAnti },\r
+  { kpidMethod, NMessageID::kMethod },\r
+  { kpidHostOS, NMessageID::kHostOS },\r
+  { kpidFileSystem, NMessageID::kFileSystem },\r
+  { kpidUser, NMessageID::kUser },\r
+  { kpidGroup, NMessageID::kGroup },\r
+  { kpidBlock, NMessageID::kBlock },\r
+  { kpidComment, NMessageID::kComment },\r
+  { kpidPosition, NMessageID::kPosition },\r
+  { kpidNumSubDirs, NMessageID::kNumSubFolders },\r
+  { kpidNumSubFiles, NMessageID::kNumSubFiles },\r
+  { kpidUnpackVer, NMessageID::kUnpackVer },\r
+  { kpidVolume, NMessageID::kVolume },\r
+  { kpidIsVolume, NMessageID::kIsVolume },\r
+  { kpidOffset, NMessageID::kOffset },\r
+  { kpidLinks, NMessageID::kLinks },\r
+  { kpidNumBlocks, NMessageID::kNumBlocks },\r
+  { kpidNumVolumes, NMessageID::kNumVolumes },\r
+  \r
+  { kpidBit64, NMessageID::kBit64 },\r
+  { kpidBigEndian, NMessageID::kBigEndian },\r
+  { kpidCpu, NMessageID::kCpu },\r
+  { kpidPhySize, NMessageID::kPhySize },\r
+  { kpidHeadersSize, NMessageID::kHeadersSize },\r
+  { kpidChecksum, NMessageID::kChecksum },\r
+  { kpidCharacts, NMessageID::kCharacts },\r
+  { kpidVa, NMessageID::kVa },\r
+  { kpidId, NMessageID::kId },\r
+  { kpidShortName, NMessageID::kShortName},\r
+  { kpidCreatorApp, NMessageID::kCreatorApp },\r
+  { kpidSectorSize, NMessageID::kSectorSize },\r
+  { kpidPosixAttrib, NMessageID::kPosixAttrib },\r
+  { kpidLink, NMessageID::kLink },\r
+  { kpidError, NMessageID::kError },\r
+  \r
+  { kpidTotalSize, NMessageID::kTotalSize },\r
+  { kpidFreeSpace, NMessageID::kFreeSpace },\r
+  { kpidClusterSize, NMessageID::kClusterSize },\r
+  { kpidVolumeName, NMessageID::kLabel }\r
+};\r
+\r
+static const int kNumPROPIDToName = sizeof(kPROPIDToName) /  sizeof(kPROPIDToName[0]);\r
+\r
+static int FindPropertyToName(PROPID propID)\r
+{\r
+  for (int i = 0; i < kNumPROPIDToName; i++)\r
+    if (kPROPIDToName[i].PropID == propID)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+/*\r
+struct CPropertyIDInfo\r
+{\r
+  PROPID PropID;\r
+  const char *FarID;\r
+  int Width;\r
+  // char CharID;\r
+};\r
+\r
+static CPropertyIDInfo kPropertyIDInfos[] =\r
+{\r
+  { kpidName, "N", 0},\r
+  { kpidSize, "S", 8},\r
+  { kpidPackedSize, "P", 8},\r
+  { kpidAttrib, "A", 0},\r
+  { kpidCTime, "DC", 14},\r
+  { kpidATime, "DA", 14},\r
+  { kpidMTime, "DM", 14},\r
+  \r
+  { kpidSolid, NULL, 0, 'S'},\r
+  { kpidEncrypted, NULL, 0, 'P'}\r
+\r
+  { kpidDictionarySize, IDS_PROPERTY_DICTIONARY_SIZE },\r
+  { kpidSplitBefore, NULL, 'B'},\r
+  { kpidSplitAfter, NULL, 'A'},\r
+  { kpidComment, , NULL, 'C'},\r
+  { kpidCRC, IDS_PROPERTY_CRC }\r
+  // { kpidType, L"Type" }\r
+};\r
+\r
+static const int kNumPropertyIDInfos = sizeof(kPropertyIDInfos) /\r
+    sizeof(kPropertyIDInfos[0]);\r
+\r
+static int FindPropertyInfo(PROPID propID)\r
+{\r
+  for (int i = 0; i < kNumPropertyIDInfos; i++)\r
+    if (kPropertyIDInfos[i].PropID == propID)\r
+      return i;\r
+  return -1;\r
+}\r
+*/\r
+\r
+// char *g_Titles[] = { "a", "f", "v" };\r
+/*\r
+static void SmartAddToString(AString &destString, const char *srcString)\r
+{\r
+  if (!destString.IsEmpty())\r
+    destString += ',';\r
+  destString += srcString;\r
+}\r
+*/\r
+\r
+/*\r
+void CPlugin::AddColumn(PROPID propID)\r
+{\r
+  int index = FindPropertyInfo(propID);\r
+  if (index >= 0)\r
+  {\r
+    for (int i = 0; i < m_ProxyHandler->m_InternalProperties.Size(); i++)\r
+    {\r
+      const CArchiveItemProperty &aHandlerProperty = m_ProxyHandler->m_InternalProperties[i];\r
+      if (aHandlerProperty.ID == propID)\r
+        break;\r
+    }\r
+    if (i == m_ProxyHandler->m_InternalProperties.Size())\r
+      return;\r
+\r
+    const CPropertyIDInfo &propertyIDInfo = kPropertyIDInfos[index];\r
+    SmartAddToString(PanelModeColumnTypes, propertyIDInfo.FarID);\r
+    char tmp[32];\r
+    itoa(propertyIDInfo.Width, tmp, 10);\r
+    SmartAddToString(PanelModeColumnWidths, tmp);\r
+    return;\r
+  }\r
+}\r
+*/\r
+\r
+static AString GetNameOfProp(PROPID propID, const wchar_t *name)\r
+{\r
+  int index = FindPropertyToName(propID);\r
+  if (index < 0)\r
+  {\r
+    if (name)\r
+      return UnicodeStringToMultiByte((const wchar_t *)name, CP_OEMCP);\r
+    char s[32];\r
+    ConvertUInt64ToString(propID, s);\r
+    return s;\r
+  }\r
+  return g_StartupInfo.GetMsgString(kPROPIDToName[index].PluginID);\r
+}\r
+\r
+static AString GetNameOfProp2(PROPID propID, const wchar_t *name)\r
+{\r
+  AString s = GetNameOfProp(propID, name);\r
+  if (s.Length() > (kInfoPanelLineSize - 1))\r
+    s = s.Left(kInfoPanelLineSize - 1);\r
+  return s;\r
+}\r
+\r
+static AString ConvertSizeToString(UInt64 value)\r
+{\r
+  char s[32];\r
+  ConvertUInt64ToString(value, s);\r
+  int i = MyStringLen(s);\r
+  int pos = sizeof(s) / sizeof(s[0]);\r
+  s[--pos] = L'\0';\r
+  while (i > 3)\r
+  {\r
+    s[--pos] = s[--i];\r
+    s[--pos] = s[--i];\r
+    s[--pos] = s[--i];\r
+    s[--pos] = ' ';\r
+  }\r
+  while (i > 0)\r
+    s[--pos] = s[--i];\r
+  return s + pos;\r
+}\r
+\r
+static AString PropToString(const NCOM::CPropVariant &prop, PROPID propID)\r
+{\r
+  AString s;\r
+\r
+  if (prop.vt == VT_BSTR)\r
+    s = UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP);\r
+  else if (prop.vt == VT_BOOL)\r
+  {\r
+    int messageID = VARIANT_BOOLToBool(prop.boolVal) ?\r
+      NMessageID::kYes : NMessageID::kNo;\r
+    return g_StartupInfo.GetMsgString(messageID);\r
+  }\r
+  else if (prop.vt != VT_EMPTY)\r
+  {\r
+    if ((\r
+        propID == kpidSize ||\r
+        propID == kpidPackSize ||\r
+        propID == kpidNumSubDirs ||\r
+        propID == kpidNumSubFiles ||\r
+        propID == kpidNumBlocks ||\r
+        propID == kpidPhySize ||\r
+        propID == kpidHeadersSize ||\r
+        propID == kpidClusterSize\r
+        ) && (prop.vt == VT_UI8 || prop.vt == VT_UI4))\r
+      s = ConvertSizeToString(ConvertPropVariantToUInt64(prop));\r
+    else\r
+      s = UnicodeStringToMultiByte(ConvertPropertyToString(prop, propID), CP_OEMCP);\r
+  }\r
+  s.Replace((char)0xA, ' ');\r
+  s.Replace((char)0xD, ' ');\r
+  return s;\r
+}\r
+\r
+static AString PropToString2(const NCOM::CPropVariant &prop, PROPID propID)\r
+{\r
+  AString s = PropToString(prop, propID);\r
+  if (s.Length() > (kInfoPanelLineSize - 1))\r
+    s = s.Left(kInfoPanelLineSize - 1);\r
+  return s;\r
+}\r
+\r
+static void AddPropertyString(InfoPanelLine *lines, int &numItems, PROPID propID, const wchar_t *name,\r
+    const NCOM::CPropVariant &prop)\r
+{\r
+  if (prop.vt != VT_EMPTY)\r
+  {\r
+    AString val = PropToString2(prop, propID);\r
+    if (!val.IsEmpty())\r
+    {\r
+      InfoPanelLine &item = lines[numItems++];\r
+      COPY_STR_LIMITED(item.Text, GetNameOfProp2(propID, name));\r
+      COPY_STR_LIMITED(item.Data, val);\r
+    }\r
+  }\r
+}\r
+\r
+static void InsertSeparator(InfoPanelLine *lines, int &numItems)\r
+{\r
+  if (numItems < kNumInfoLinesMax)\r
+  {\r
+    InfoPanelLine &item = lines[numItems++];\r
+    MyStringCopy(item.Text, "");\r
+    MyStringCopy(item.Data, "");\r
+    item.Separator = TRUE;\r
+  }\r
+}\r
+\r
+void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info)\r
+{\r
+  info->StructSize = sizeof(*info);\r
+  info->Flags = OPIF_USEFILTER | OPIF_USESORTGROUPS| OPIF_USEHIGHLIGHTING|\r
+              OPIF_ADDDOTS | OPIF_COMPAREFATTIME;\r
+\r
+  COPY_STR_LIMITED(m_FileNameBuffer, UnicodeStringToMultiByte(m_FileName, CP_OEMCP));\r
+  info->HostFile = m_FileNameBuffer; // test it it is not static\r
+  \r
+  COPY_STR_LIMITED(m_CurrentDirBuffer, UnicodeStringToMultiByte(m_CurrentDir, CP_OEMCP));\r
+  info->CurDir = m_CurrentDirBuffer;\r
+\r
+  info->Format = kPluginFormatName;\r
+\r
+  UString name;\r
+  {\r
+    UString fullName;\r
+    int index;\r
+    NFile::NDirectory::MyGetFullPathName(m_FileName, fullName, index);\r
+    name = fullName.Mid(index);\r
+  }\r
+\r
+  m_PannelTitle =\r
+      UString(L' ') +\r
+      _archiveTypeName +\r
+      UString(L':') +\r
+      name +\r
+      UString(L' ');\r
+  if (!m_CurrentDir.IsEmpty())\r
+  {\r
+    // m_PannelTitle += '\\';\r
+    m_PannelTitle += m_CurrentDir;\r
+  }\r
\r
+  COPY_STR_LIMITED(m_PannelTitleBuffer, UnicodeStringToMultiByte(m_PannelTitle, CP_OEMCP));\r
+  info->PanelTitle = m_PannelTitleBuffer;\r
+\r
+  memset(m_InfoLines, 0, sizeof(m_InfoLines));\r
+  MyStringCopy(m_InfoLines[0].Text, "");\r
+  m_InfoLines[0].Separator = TRUE;\r
+\r
+  MyStringCopy(m_InfoLines[1].Text, g_StartupInfo.GetMsgString(NMessageID::kArchiveType));\r
+  MyStringCopy(m_InfoLines[1].Data, (const char *)UnicodeStringToMultiByte(_archiveTypeName, CP_OEMCP));\r
+\r
+  int numItems = 2;\r
+\r
+  {\r
+    CMyComPtr<IFolderProperties> folderProperties;\r
+    _folder.QueryInterface(IID_IFolderProperties, &folderProperties);\r
+    if (folderProperties)\r
+    {\r
+      UInt32 numProps;\r
+      if (folderProperties->GetNumberOfFolderProperties(&numProps) == S_OK)\r
+      {\r
+        for (UInt32 i = 0; i < numProps && numItems < kNumInfoLinesMax; i++)\r
+        {\r
+          CMyComBSTR name;\r
+          PROPID propID;\r
+          VARTYPE vt;\r
+          if (folderProperties->GetFolderPropertyInfo(i, &name, &propID, &vt) != S_OK)\r
+            continue;\r
+          NCOM::CPropVariant prop;\r
+          if (_folder->GetFolderProperty(propID, &prop) != S_OK || prop.vt == VT_EMPTY)\r
+            continue;\r
+          \r
+          InfoPanelLine &item = m_InfoLines[numItems++];\r
+          COPY_STR_LIMITED(item.Text, GetNameOfProp2(propID, name));\r
+          COPY_STR_LIMITED(item.Data, PropToString2(prop, propID));\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  /*\r
+  if (numItems < kNumInfoLinesMax)\r
+  {\r
+    InsertSeparator(m_InfoLines, numItems);\r
+  }\r
+  */\r
+\r
+  {\r
+    CMyComPtr<IGetFolderArcProps> getFolderArcProps;\r
+    _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps);\r
+    if (getFolderArcProps)\r
+    {\r
+      CMyComPtr<IFolderArcProps> getProps;\r
+      getFolderArcProps->GetFolderArcProps(&getProps);\r
+      if (getProps)\r
+      {\r
+        UInt32 numLevels;\r
+        if (getProps->GetArcNumLevels(&numLevels) != S_OK)\r
+          numLevels = 0;\r
+        for (UInt32 level2 = 0; level2 < numLevels; level2++)\r
+        {\r
+          {\r
+            UInt32 level = numLevels - 1 - level2;\r
+            UInt32 numProps;\r
+            if (getProps->GetArcNumProps(level, &numProps) == S_OK)\r
+            {\r
+              InsertSeparator(m_InfoLines, numItems);\r
+              for (Int32 i = -3; i < (Int32)numProps && numItems < kNumInfoLinesMax; i++)\r
+              {\r
+                CMyComBSTR name;\r
+                PROPID propID;\r
+                VARTYPE vt;\r
+                switch (i)\r
+                {\r
+                  case -3: propID = kpidPath; break;\r
+                  case -2: propID = kpidType; break;\r
+                  case -1: propID = kpidError; break;\r
+                  default:\r
+                    if (getProps->GetArcPropInfo(level, i, &name, &propID, &vt) != S_OK)\r
+                      continue;\r
+                }\r
+                NCOM::CPropVariant prop;\r
+                if (getProps->GetArcProp(level, propID, &prop) != S_OK)\r
+                  continue;\r
+                AddPropertyString(m_InfoLines, numItems, propID, name, prop);\r
+              }\r
+            }\r
+          }\r
+          if (level2 != numLevels - 1)\r
+          {\r
+            UInt32 level = numLevels - 1 - level2;\r
+            UInt32 numProps;\r
+            if (getProps->GetArcNumProps2(level, &numProps) == S_OK)\r
+            {\r
+              InsertSeparator(m_InfoLines, numItems);\r
+              for (Int32 i = 0; i < (Int32)numProps && numItems < kNumInfoLinesMax; i++)\r
+              {\r
+                CMyComBSTR name;\r
+                PROPID propID;\r
+                VARTYPE vt;\r
+                if (getProps->GetArcPropInfo2(level, i, &name, &propID, &vt) != S_OK)\r
+                  continue;\r
+                NCOM::CPropVariant prop;\r
+                if (getProps->GetArcProp2(level, propID, &prop) != S_OK)\r
+                  continue;\r
+                AddPropertyString(m_InfoLines, numItems, propID, name, prop);\r
+              }\r
+            }\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  //m_InfoLines[1].Separator = 0;\r
+\r
+  info->InfoLines = m_InfoLines;\r
+  info->InfoLinesNumber = numItems;\r
+\r
+  \r
+  info->DescrFiles = NULL;\r
+  info->DescrFilesNumber = 0;\r
+\r
+  PanelModeColumnTypes.Empty();\r
+  PanelModeColumnWidths.Empty();\r
+\r
+  /*\r
+  AddColumn(kpidName);\r
+  AddColumn(kpidSize);\r
+  AddColumn(kpidPackedSize);\r
+  AddColumn(kpidMTime);\r
+  AddColumn(kpidCTime);\r
+  AddColumn(kpidATime);\r
+  AddColumn(kpidAttrib);\r
+  \r
+  PanelMode.ColumnTypes = (char *)(const char *)PanelModeColumnTypes;\r
+  PanelMode.ColumnWidths = (char *)(const char *)PanelModeColumnWidths;\r
+  PanelMode.ColumnTitles = NULL;\r
+  PanelMode.FullScreen = TRUE;\r
+  PanelMode.DetailedStatus = FALSE;\r
+  PanelMode.AlignExtensions = FALSE;\r
+  PanelMode.CaseConversion = FALSE;\r
+  PanelMode.StatusColumnTypes = "N";\r
+  PanelMode.StatusColumnWidths = "0";\r
+  PanelMode.Reserved[0] = 0;\r
+  PanelMode.Reserved[1] = 0;\r
+\r
+  info->PanelModesArray = &PanelMode;\r
+  info->PanelModesNumber = 1;\r
+  */\r
+\r
+  info->PanelModesArray = NULL;\r
+  info->PanelModesNumber = 0;\r
+\r
+  info->StartPanelMode = 0;\r
+  info->StartSortMode = 0;\r
+  info->KeyBar = NULL;\r
+  info->ShortcutData = NULL;\r
+}\r
+\r
+struct CArchiveItemProperty\r
+{\r
+  AString Name;\r
+  PROPID ID;\r
+  VARTYPE Type;\r
+};\r
+\r
+HRESULT CPlugin::ShowAttributesWindow()\r
+{\r
+  PluginPanelItem pluginPanelItem;\r
+  if (!g_StartupInfo.ControlGetActivePanelCurrentItemInfo(pluginPanelItem))\r
+    return S_FALSE;\r
+  if (strcmp(pluginPanelItem.FindData.cFileName, "..") == 0 &&\r
+        NFile::NFind::NAttributes::IsDir(pluginPanelItem.FindData.dwFileAttributes))\r
+    return S_FALSE;\r
+  int itemIndex = (int)pluginPanelItem.UserData;\r
+\r
+  CObjectVector<CArchiveItemProperty> properties;\r
+  UInt32 numProps;\r
+  RINOK(_folder->GetNumberOfProperties(&numProps));\r
+  int i;\r
+  for (i = 0; i < (int)numProps; i++)\r
+  {\r
+    CMyComBSTR name;\r
+    PROPID propID;\r
+    VARTYPE vt;\r
+    RINOK(_folder->GetPropertyInfo(i, &name, &propID, &vt));\r
+    CArchiveItemProperty prop;\r
+    prop.Type = vt;\r
+    prop.ID = propID;\r
+    if (prop.ID  == kpidPath)\r
+      prop.ID  = kpidName;\r
+    prop.Name = GetNameOfProp(propID, name);\r
+    properties.Add(prop);\r
+  }\r
+\r
+  int size = 2;\r
+  CRecordVector<CInitDialogItem> initDialogItems;\r
+  \r
+  int xSize = 70;\r
+  CInitDialogItem idi =\r
+  { DI_DOUBLEBOX, 3, 1, xSize - 4, size - 2, false, false, 0, false, NMessageID::kProperties, NULL, NULL };\r
+  initDialogItems.Add(idi);\r
+  AStringVector values;\r
+\r
+  for (i = 0; i < properties.Size(); i++)\r
+  {\r
+    const CArchiveItemProperty &property = properties[i];\r
+\r
+    CInitDialogItem idi =\r
+      { DI_TEXT, 5, 3 + i, 0, 0, false, false, 0, false, 0, NULL, NULL };\r
+    int index = FindPropertyToName(property.ID);\r
+    if (index < 0)\r
+    {\r
+      idi.DataMessageId = -1;\r
+      idi.DataString = property.Name;\r
+    }\r
+    else\r
+      idi.DataMessageId = kPROPIDToName[index].PluginID;\r
+    initDialogItems.Add(idi);\r
+    \r
+    NCOM::CPropVariant prop;\r
+    RINOK(_folder->GetProperty(itemIndex, property.ID, &prop));\r
+    AString s = PropToString(prop, property.ID);\r
+    values.Add(s);\r
+    \r
+    {\r
+      CInitDialogItem idi =\r
+      { DI_TEXT, 30, 3 + i, 0, 0, false, false, 0, false, -1, NULL, NULL };\r
+      initDialogItems.Add(idi);\r
+    }\r
+  }\r
+\r
+  int numLines = values.Size();\r
+  for (i = 0; i < numLines; i++)\r
+  {\r
+    CInitDialogItem &idi = initDialogItems[1 + i * 2 + 1];\r
+    idi.DataString = values[i];\r
+  }\r
+  \r
+  int numDialogItems = initDialogItems.Size();\r
+  \r
+  CRecordVector<FarDialogItem> dialogItems;\r
+  dialogItems.Reserve(numDialogItems);\r
+  for (i = 0; i < numDialogItems; i++)\r
+    dialogItems.Add(FarDialogItem());\r
+  g_StartupInfo.InitDialogItems(&initDialogItems.Front(),\r
+      &dialogItems.Front(), numDialogItems);\r
+  \r
+  int maxLen = 0;\r
+  for (i = 0; i < numLines; i++)\r
+  {\r
+    FarDialogItem &dialogItem = dialogItems[1 + i * 2];\r
+    int len = (int)strlen(dialogItem.Data);\r
+    if (len > maxLen)\r
+      maxLen = len;\r
+  }\r
+  int maxLen2 = 0;\r
+  const int kSpace = 10;\r
+  for (i = 0; i < numLines; i++)\r
+  {\r
+    FarDialogItem &dialogItem = dialogItems[1 + i * 2 + 1];\r
+    int len = (int)strlen(dialogItem.Data);\r
+    if (len > maxLen2)\r
+      maxLen2 = len;\r
+    dialogItem.X1 = maxLen + kSpace;\r
+  }\r
+  size = numLines + 6;\r
+  xSize = maxLen + kSpace + maxLen2 + 5;\r
+  FarDialogItem &firstDialogItem = dialogItems.Front();\r
+  firstDialogItem.Y2 = size - 2;\r
+  firstDialogItem.X2 = xSize - 4;\r
+  \r
+  /* int askCode = */ g_StartupInfo.ShowDialog(xSize, size, NULL, &dialogItems.Front(), numDialogItems);\r
+  return S_OK;\r
+}\r
+\r
+int CPlugin::ProcessKey(int key, unsigned int controlState)\r
+{\r
+  if (controlState == PKF_CONTROL && key == 'A')\r
+  {\r
+    HRESULT result = ShowAttributesWindow();\r
+    if (result == S_OK)\r
+      return TRUE;\r
+    if (result == S_FALSE)\r
+      return FALSE;\r
+    throw "Error";\r
+  }\r
+  if ((controlState & PKF_ALT) != 0 && key == VK_F6)\r
+  {\r
+    UString folderPath;\r
+    if (!NFile::NDirectory::GetOnlyDirPrefix(m_FileName, folderPath))\r
+      return FALSE;\r
+    PanelInfo panelInfo;\r
+    g_StartupInfo.ControlGetActivePanelInfo(panelInfo);\r
+    GetFilesReal(panelInfo.SelectedItems,\r
+        panelInfo.SelectedItemsNumber, FALSE,\r
+        UnicodeStringToMultiByte(folderPath, CP_OEMCP), OPM_SILENT, true);\r
+    g_StartupInfo.Control(this, FCTL_UPDATEPANEL, NULL);\r
+    g_StartupInfo.Control(this, FCTL_REDRAWPANEL, NULL);\r
+    g_StartupInfo.Control(this, FCTL_UPDATEANOTHERPANEL, NULL);\r
+    g_StartupInfo.Control(this, FCTL_REDRAWANOTHERPANEL, NULL);\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
diff --git a/CPP/7zip/UI/Far/Plugin.h b/CPP/7zip/UI/Far/Plugin.h
new file mode 100755 (executable)
index 0000000..f48d00b
--- /dev/null
@@ -0,0 +1,88 @@
+// 7zip/Far/Plugin.h\r
+\r
+#ifndef __7ZIP_FAR_PLUGIN_H\r
+#define __7ZIP_FAR_PLUGIN_H\r
+\r
+#include "Common/MyCom.h"\r
+\r
+#include "Windows/COM.h"\r
+#include "Windows/FileFind.h"\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../Agent/IFolderArchive.h"\r
+\r
+#include "FarUtils.h"\r
+\r
+const UInt32 kNumInfoLinesMax = 64;\r
+\r
+class CPlugin\r
+{\r
+  NWindows::NCOM::CComInitializer m_ComInitializer;\r
+  UString m_CurrentDir;\r
+\r
+  UString m_PannelTitle;\r
+  \r
+  InfoPanelLine m_InfoLines[kNumInfoLinesMax];\r
+\r
+  char m_FileNameBuffer[1024];\r
+  char m_CurrentDirBuffer[1024];\r
+  char m_PannelTitleBuffer[1024];\r
+\r
+  AString PanelModeColumnTypes;\r
+  AString PanelModeColumnWidths;\r
+  PanelMode PanelMode;\r
+  void AddColumn(PROPID aPropID);\r
+\r
+  void EnterToDirectory(const UString &dirName);\r
+  void GetPathParts(UStringVector &pathParts);\r
+  void GetCurrentDir();\r
+public:\r
+  UString m_FileName;\r
+  NWindows::NFile::NFind::CFileInfoW m_FileInfo;\r
+\r
+  CMyComPtr<IInFolderArchive> m_ArchiveHandler;\r
+  CMyComPtr<IFolderFolder> _folder;\r
+  \r
+  UString _archiveTypeName;\r
+\r
+  bool PasswordIsDefined;\r
+  UString Password;\r
+\r
+  CPlugin(const UString &fileName, IInFolderArchive *archiveHandler, UString archiveTypeName);\r
+  ~CPlugin();\r
+\r
+  void ReadPluginPanelItem(PluginPanelItem &panelItem, UInt32 itemIndex);\r
+\r
+  int GetFindData(PluginPanelItem **panelItems,int *itemsNumber,int opMode);\r
+  void FreeFindData(PluginPanelItem *panelItem,int ItemsNumber);\r
+  int SetDirectory(const char *aszDir, int opMode);\r
+  void GetOpenPluginInfo(struct OpenPluginInfo *info);\r
+  int DeleteFiles(PluginPanelItem *panelItems, int itemsNumber, int opMode);\r
+\r
+  HRESULT ExtractFiles(\r
+      bool decompressAllItems,\r
+      const UInt32 *indices,\r
+      UInt32 numIndices,\r
+      bool silent,\r
+      NExtract::NPathMode::EEnum pathMode,\r
+      NExtract::NOverwriteMode::EEnum overwriteMode,\r
+      const UString &destPath,\r
+      bool passwordIsDefined, const UString &password);\r
+\r
+  NFar::NFileOperationReturnCode::EEnum GetFiles(struct PluginPanelItem *panelItem, int itemsNumber,\r
+      int move, char *destPath, int opMode);\r
+  \r
+  NFar::NFileOperationReturnCode::EEnum GetFilesReal(struct PluginPanelItem *panelItems,\r
+      int itemsNumber, int move, const char *_aDestPath, int opMode, bool showBox);\r
+\r
+  NFar::NFileOperationReturnCode::EEnum PutFiles(struct PluginPanelItem *panelItems, int itemsNumber,\r
+      int move, int opMode);\r
+\r
+  HRESULT ShowAttributesWindow();\r
+\r
+  int ProcessKey(int key, unsigned int controlState);\r
+};\r
+\r
+HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Far/PluginCommon.cpp b/CPP/7zip/UI/Far/PluginCommon.cpp
new file mode 100755 (executable)
index 0000000..53ad88f
--- /dev/null
@@ -0,0 +1,50 @@
+// SevenZip/Plugin.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Plugin.h"\r
+\r
+/*\r
+void CPlugin::AddRealIndexOfFile(const CArchiveFolderItem &aFolder,\r
+    int anIndexInVector, vector<int> &aRealIndexes)\r
+{\r
+  const CArchiveFolderFileItem &anItem = aFolder.m_FileSubItems[anIndexInVector];\r
+  int aHandlerItemIndex = m_ProxyHandler->GetHandlerItemIndex(anItem.m_Properties);\r
+  if(aHandlerItemIndex < 0)\r
+    throw "error";\r
+  aRealIndexes.push_back(aHandlerItemIndex);\r
+}\r
+\r
+void CPlugin::AddRealIndexes(const CArchiveFolderItem &anItem,\r
+    vector<int> &aRealIndexes)\r
+{\r
+  int aHandlerItemIndex = m_ProxyHandler->GetHandlerItemIndex(anItem.m_Properties);\r
+  if(aHandlerItemIndex >= 0) // test -1 value\r
+     aRealIndexes.push_back(aHandlerItemIndex);\r
+  for(int i = 0; i < anItem.m_DirSubItems.Size(); i++)\r
+    AddRealIndexes(anItem.m_DirSubItems[i], aRealIndexes);\r
+  for(i = 0; i < anItem.m_FileSubItems.Size(); i++)\r
+    AddRealIndexOfFile(anItem, i , aRealIndexes);\r
+}\r
+\r
+\r
+void CPlugin::GetRealIndexes(PluginPanelItem *aPanelItems, int anItemsNumber,\r
+    vector<int> &aRealIndexes)\r
+{\r
+  aRealIndexes.clear();\r
+  for(int i = 0; i < anItemsNumber; i++)\r
+  {\r
+    int anIndex = aPanelItems[i].UserData;\r
+    if (anIndex < m_FolderItem->m_DirSubItems.Size())\r
+    {\r
+      const CArchiveFolderItem &anItem = m_FolderItem->m_DirSubItems[anIndex];\r
+      AddRealIndexes(anItem, aRealIndexes);\r
+    }\r
+    else\r
+      AddRealIndexOfFile(*m_FolderItem, anIndex - m_FolderItem->m_DirSubItems.Size(),\r
+          aRealIndexes);\r
+  }\r
+  sort(aRealIndexes.begin(), aRealIndexes.end());\r
+}\r
+\r
+*/\r
diff --git a/CPP/7zip/UI/Far/PluginDelete.cpp b/CPP/7zip/UI/Far/PluginDelete.cpp
new file mode 100755 (executable)
index 0000000..b50576b
--- /dev/null
@@ -0,0 +1,161 @@
+// PluginDelete.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/FileDir.h"\r
+\r
+#include "../Common/WorkDir.h"\r
+\r
+#include "Messages.h"\r
+#include "Plugin.h"\r
+#include "UpdateCallback100.h"\r
+\r
+using namespace NFar;\r
+using namespace NWindows;\r
+using namespace NFile;\r
+using namespace NDirectory;\r
+\r
+static LPCWSTR kTempArchivePrefix = L"7zA";\r
+\r
+int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode)\r
+{\r
+  if (numItems == 0)\r
+    return FALSE;\r
+  /*\r
+  if (!m_ArchiverInfo.UpdateEnabled)\r
+  {\r
+    g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);\r
+    return FALSE;\r
+  }\r
+  */\r
+  if ((opMode & OPM_SILENT) == 0)\r
+  {\r
+    const char *msgItems[]=\r
+    {\r
+      g_StartupInfo.GetMsgString(NMessageID::kDeleteTitle),\r
+      g_StartupInfo.GetMsgString(NMessageID::kDeleteFiles),\r
+      g_StartupInfo.GetMsgString(NMessageID::kDeleteDelete),\r
+      g_StartupInfo.GetMsgString(NMessageID::kDeleteCancel)\r
+    };\r
+    char msg[1024];\r
+    if (numItems == 1)\r
+    {\r
+      sprintf(msg, g_StartupInfo.GetMsgString(NMessageID::kDeleteFile), panelItems[0].FindData.cFileName);\r
+      msgItems[1] = msg;\r
+    }\r
+    else if (numItems > 1)\r
+    {\r
+      sprintf(msg, g_StartupInfo.GetMsgString(NMessageID::kDeleteNumberOfFiles),\r
+          numItems);\r
+      msgItems[1] = msg;\r
+    }\r
+    if (g_StartupInfo.ShowMessage(FMSG_WARNING, NULL, msgItems,\r
+        sizeof(msgItems) / sizeof(msgItems[0]), 2) != 0)\r
+      return (FALSE);\r
+  }\r
+\r
+  CScreenRestorer screenRestorer;\r
+  CProgressBox progressBox;\r
+  CProgressBox *progressBoxPointer = NULL;\r
+  if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0)\r
+  {\r
+    screenRestorer.Save();\r
+\r
+    progressBoxPointer = &progressBox;\r
+    progressBox.Init(\r
+        // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),\r
+        g_StartupInfo.GetMsgString(NMessageID::kDeleting), 48);\r
+  }\r
+\r
+  NWorkDir::CInfo workDirInfo;\r
+  workDirInfo.Load();\r
+\r
+  UString workDir = GetWorkDir(workDirInfo, m_FileName);\r
+  CreateComplexDirectory(workDir);\r
+\r
+  CTempFileW tempFile;\r
+  UString tempFileName;\r
+  if (tempFile.Create(workDir, kTempArchivePrefix, tempFileName) == 0)\r
+    return FALSE;\r
+\r
+\r
+  CRecordVector<UINT32> indices;\r
+  indices.Reserve(numItems);\r
+  int i;\r
+  for (i = 0; i < numItems; i++)\r
+    indices.Add((UINT32)panelItems[i].UserData);\r
+\r
+  ////////////////////////////\r
+  // Save _folder;\r
+\r
+  UStringVector pathVector;\r
+  GetPathParts(pathVector);\r
+  \r
+  CMyComPtr<IOutFolderArchive> outArchive;\r
+  HRESULT result = m_ArchiveHandler.QueryInterface(IID_IOutFolderArchive, &outArchive);\r
+  if (result != S_OK)\r
+  {\r
+    g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);\r
+    return FALSE;\r
+  }\r
+  outArchive->SetFolder(_folder);\r
+\r
+  CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp;\r
+  CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec );\r
+  \r
+  updateCallbackSpec->Init(/* m_ArchiveHandler, */ progressBoxPointer);\r
+\r
+\r
+  result = outArchive->DeleteItems(\r
+      tempFileName,\r
+      &indices.Front(), indices.Size(),\r
+      updateCallback);\r
+  updateCallback.Release();\r
+  outArchive.Release();\r
+\r
+  if (result != S_OK)\r
+  {\r
+    ShowErrorMessage(result);\r
+    return FALSE;\r
+  }\r
+\r
+  _folder.Release();\r
+  m_ArchiveHandler->Close();\r
+  \r
+  if (!DeleteFileAlways(m_FileName))\r
+  {\r
+    ShowLastErrorMessage();\r
+    return FALSE;\r
+  }\r
+\r
+  tempFile.DisableDeleting();\r
+  if (!MyMoveFile(tempFileName, m_FileName))\r
+  {\r
+    ShowLastErrorMessage();\r
+    return FALSE;\r
+  }\r
+  \r
+  result = m_ArchiveHandler->ReOpen(NULL);\r
+  if (result != S_OK)\r
+  {\r
+    ShowErrorMessage(result);\r
+    return FALSE;\r
+  }\r
+\r
\r
+  ////////////////////////////\r
+  // Restore _folder;\r
+\r
+  m_ArchiveHandler->BindToRootFolder(&_folder);\r
+  for (i = 0; i < pathVector.Size(); i++)\r
+  {\r
+    CMyComPtr<IFolderFolder> newFolder;\r
+    _folder->BindToFolder(pathVector[i], &newFolder);\r
+    if (!newFolder)\r
+      break;\r
+    _folder = newFolder;\r
+  }\r
+  GetCurrentDir();\r
+\r
+  return TRUE;\r
+}\r
diff --git a/CPP/7zip/UI/Far/PluginRead.cpp b/CPP/7zip/UI/Far/PluginRead.cpp
new file mode 100755 (executable)
index 0000000..0725010
--- /dev/null
@@ -0,0 +1,286 @@
+// PluginRead.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Plugin.h"\r
+\r
+#include "Messages.h"\r
+\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/FileName.h"\r
+#include "Windows/FileFind.h"\r
+#include "Windows/FileDir.h"\r
+#include "Windows/Defs.h"\r
+\r
+#include "../Common/ZipRegistry.h"\r
+\r
+#include "ExtractEngine.h"\r
+\r
+using namespace NFar;\r
+using namespace NWindows;\r
+\r
+static const char *kHelpTopicExtrFromSevenZip =  "Extract";\r
+\r
+static const char kDirDelimiter = '\\';\r
+\r
+static const char *kExractPathHistoryName  = "7-ZipExtractPath";\r
+\r
+HRESULT CPlugin::ExtractFiles(\r
+    bool decompressAllItems,\r
+    const UINT32 *indices,\r
+    UINT32 numIndices,\r
+    bool silent,\r
+    NExtract::NPathMode::EEnum pathMode,\r
+    NExtract::NOverwriteMode::EEnum overwriteMode,\r
+    const UString &destPath,\r
+    bool passwordIsDefined, const UString &password)\r
+{\r
+  CScreenRestorer screenRestorer;\r
+  CProgressBox progressBox;\r
+  CProgressBox *progressBoxPointer = NULL;\r
+  if (!silent)\r
+  {\r
+    screenRestorer.Save();\r
+\r
+    progressBoxPointer = &progressBox;\r
+    progressBox.Init(\r
+        // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),\r
+        g_StartupInfo.GetMsgString(NMessageID::kExtracting), 48);\r
+  }\r
+\r
+\r
+  CExtractCallBackImp *extractCallbackSpec = new CExtractCallBackImp;\r
+  CMyComPtr<IFolderArchiveExtractCallback> extractCallback(extractCallbackSpec);\r
+  \r
+  extractCallbackSpec->Init(\r
+      CP_OEMCP,\r
+      progressBoxPointer,\r
+      /*\r
+      GetDefaultName(m_FileName, m_ArchiverInfo.Extension),\r
+      m_FileInfo.MTime, m_FileInfo.Attributes,\r
+      */\r
+      passwordIsDefined, password);\r
+\r
+  if (decompressAllItems)\r
+    return m_ArchiveHandler->Extract(pathMode, overwriteMode,\r
+        destPath, BoolToInt(false), extractCallback);\r
+  else\r
+  {\r
+    CMyComPtr<IArchiveFolder> archiveFolder;\r
+    _folder.QueryInterface(IID_IArchiveFolder, &archiveFolder);\r
+\r
+    return archiveFolder->Extract(indices, numIndices, pathMode, overwriteMode,\r
+        destPath, BoolToInt(false), extractCallback);\r
+  }\r
+}\r
+\r
+NFileOperationReturnCode::EEnum CPlugin::GetFiles(struct PluginPanelItem *panelItems,\r
+    int itemsNumber, int move, char *destPath, int opMode)\r
+{\r
+  return GetFilesReal(panelItems, itemsNumber, move,\r
+      destPath, opMode, (opMode & OPM_SILENT) == 0);\r
+}\r
+\r
+NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *panelItems,\r
+    int itemsNumber, int move, const char *destPathLoc, int opMode, bool showBox)\r
+{\r
+  if (move != 0)\r
+  {\r
+    g_StartupInfo.ShowMessage(NMessageID::kMoveIsNotSupported);\r
+    return NFileOperationReturnCode::kError;\r
+  }\r
+\r
+  AString destPath = destPathLoc;\r
+  UString destPathU = GetUnicodeString(destPath, CP_OEMCP);\r
+  NFile::NName::NormalizeDirPathPrefix(destPathU);\r
+  destPath = UnicodeStringToMultiByte(destPathU, CP_OEMCP);\r
+\r
+  bool extractSelectedFiles = true;\r
+  \r
+  NExtract::CInfo extractionInfo;\r
+  extractionInfo.PathMode = NExtract::NPathMode::kCurrentPathnames;\r
+  extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;\r
+\r
+  bool silent = (opMode & OPM_SILENT) != 0;\r
+  bool decompressAllItems = false;\r
+  UString password = Password;\r
+  bool passwordIsDefined = PasswordIsDefined;\r
+\r
+  if (!silent)\r
+  {\r
+    const int kPathIndex = 2;\r
+\r
+    extractionInfo.Load();\r
+\r
+    const int kPathModeRadioIndex = 4;\r
+    const int kOverwriteModeRadioIndex = kPathModeRadioIndex + 4;\r
+    const int kNumOverwriteOptions = 6;\r
+    const int kFilesModeIndex = kOverwriteModeRadioIndex + kNumOverwriteOptions;\r
+    const int kXSize = 76;\r
+    const int kYSize = 19;\r
+    const int kPasswordYPos = 12;\r
+    \r
+    const int kXMid = kXSize / 2;\r
+\r
+    AString oemPassword = UnicodeStringToMultiByte(password, CP_OEMCP);\r
+    \r
+    struct CInitDialogItem initItems[]={\r
+      { DI_DOUBLEBOX, 3, 1, kXSize - 4, kYSize - 2, false, false, 0, false, NMessageID::kExtractTitle, NULL, NULL },\r
+      { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, NMessageID::kExtractTo, NULL, NULL },\r
+      \r
+      { DI_EDIT, 5, 3, kXSize - 6, 3, true, false, DIF_HISTORY, false, -1, destPath, kExractPathHistoryName},\r
+      // { DI_EDIT, 5, 3, kXSize - 6, 3, true, false, 0, false, -1, destPath, NULL},\r
+      \r
+      { DI_SINGLEBOX, 4, 5, kXMid - 2, 5 + 4, false, false, 0, false, NMessageID::kExtractPathMode, NULL, NULL },\r
+      { DI_RADIOBUTTON, 6, 6, 0, 0, false,\r
+          extractionInfo.PathMode == NExtract::NPathMode::kFullPathnames,\r
+          DIF_GROUP, false, NMessageID::kExtractPathFull, NULL, NULL },\r
+      { DI_RADIOBUTTON, 6, 7, 0, 0, false,\r
+          extractionInfo.PathMode == NExtract::NPathMode::kCurrentPathnames,\r
+          0, false, NMessageID::kExtractPathCurrent, NULL, NULL },\r
+      { DI_RADIOBUTTON, 6, 8, 0, 0, false,\r
+          extractionInfo.PathMode == NExtract::NPathMode::kNoPathnames,\r
+          false, 0, NMessageID::kExtractPathNo, NULL, NULL },\r
+      \r
+      { DI_SINGLEBOX, kXMid, 5, kXSize - 6, 5 + kNumOverwriteOptions, false, false, 0, false, NMessageID::kExtractOwerwriteMode, NULL, NULL },\r
+      { DI_RADIOBUTTON, kXMid + 2, 6, 0, 0, false,\r
+          extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kAskBefore,\r
+          DIF_GROUP, false, NMessageID::kExtractOwerwriteAsk, NULL, NULL },\r
+      { DI_RADIOBUTTON, kXMid + 2, 7, 0, 0, false,\r
+          extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kWithoutPrompt,\r
+          0, false, NMessageID::kExtractOwerwritePrompt, NULL, NULL },\r
+      { DI_RADIOBUTTON, kXMid + 2, 8, 0, 0, false,\r
+          extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kSkipExisting,\r
+          0, false, NMessageID::kExtractOwerwriteSkip, NULL, NULL },\r
+      { DI_RADIOBUTTON, kXMid + 2, 9, 0, 0, false,\r
+          extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kAutoRename,\r
+          0, false, NMessageID::kExtractOwerwriteAutoRename, NULL, NULL },\r
+      { DI_RADIOBUTTON, kXMid + 2, 10, 0, 0, false,\r
+          extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting,\r
+          0, false, NMessageID::kExtractOwerwriteAutoRenameExisting, NULL, NULL },\r
+      \r
+      { DI_SINGLEBOX, 4, 10, kXMid- 2, 10 + 3, false, false, 0, false, NMessageID::kExtractFilesMode, NULL, NULL },\r
+      { DI_RADIOBUTTON, 6, 11, 0, 0, false, true, DIF_GROUP, false, NMessageID::kExtractFilesSelected, NULL, NULL },\r
+      { DI_RADIOBUTTON, 6, 12, 0, 0, false, false, 0, false, NMessageID::kExtractFilesAll, NULL, NULL },\r
+      \r
+      { DI_SINGLEBOX, kXMid, kPasswordYPos, kXSize - 6, kPasswordYPos + 2, false, false, 0, false, NMessageID::kExtractPassword, NULL, NULL },\r
+      { DI_PSWEDIT, kXMid + 2, kPasswordYPos + 1, kXSize - 8, 12, false, false, 0, false, -1, oemPassword, NULL},\r
+      \r
+      { DI_TEXT, 3, kYSize - 4, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL  },\r
+      \r
+      \r
+      { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kExtractExtract, NULL, NULL  },\r
+      { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kExtractCancel, NULL, NULL  }\r
+    };\r
+   \r
+    const int kNumDialogItems = sizeof(initItems) / sizeof(initItems[0]);\r
+    const int kOkButtonIndex = kNumDialogItems - 2;\r
+    const int kPasswordIndex = kNumDialogItems - 4;\r
+\r
+    FarDialogItem dialogItems[kNumDialogItems];\r
+    g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems);\r
+    for (;;)\r
+    {\r
+      int askCode = g_StartupInfo.ShowDialog(kXSize, kYSize,\r
+        kHelpTopicExtrFromSevenZip, dialogItems, kNumDialogItems);\r
+      if (askCode != kOkButtonIndex)\r
+        return NFileOperationReturnCode::kInterruptedByUser;\r
+      destPath = dialogItems[kPathIndex].Data;\r
+      destPathU = GetUnicodeString(destPath, CP_OEMCP);\r
+      destPathU.Trim();\r
+      if (destPathU.IsEmpty())\r
+      {\r
+        #ifdef UNDER_CE\r
+        destPathU = L"\\";\r
+        #else\r
+        if (!NFile::NDirectory::MyGetCurrentDirectory(destPathU))\r
+          throw 318016;\r
+        NFile::NName::NormalizeDirPathPrefix(destPathU);\r
+        #endif\r
+        break;\r
+      }\r
+      else\r
+      {\r
+        if (destPathU.Back() == kDirDelimiter)\r
+          break;\r
+      }\r
+      g_StartupInfo.ShowMessage("You must specify directory path");\r
+    }\r
+\r
+    if (dialogItems[kPathModeRadioIndex].Selected)\r
+      extractionInfo.PathMode = NExtract::NPathMode::kFullPathnames;\r
+    else if (dialogItems[kPathModeRadioIndex + 1].Selected)\r
+      extractionInfo.PathMode = NExtract::NPathMode::kCurrentPathnames;\r
+    else if (dialogItems[kPathModeRadioIndex + 2].Selected)\r
+      extractionInfo.PathMode = NExtract::NPathMode::kNoPathnames;\r
+    else\r
+      throw 31806;\r
+\r
+    if (dialogItems[kOverwriteModeRadioIndex].Selected)\r
+      extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kAskBefore;\r
+    else if (dialogItems[kOverwriteModeRadioIndex + 1].Selected)\r
+      extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;\r
+    else if (dialogItems[kOverwriteModeRadioIndex + 2].Selected)\r
+      extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kSkipExisting;\r
+    else if (dialogItems[kOverwriteModeRadioIndex + 3].Selected)\r
+      extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kAutoRename;\r
+    else if (dialogItems[kOverwriteModeRadioIndex + 4].Selected)\r
+      extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kAutoRenameExisting;\r
+    else\r
+      throw 31806;\r
+    \r
+    if (dialogItems[kFilesModeIndex].Selected)\r
+      decompressAllItems = false;\r
+    else if (dialogItems[kFilesModeIndex + 1].Selected)\r
+      decompressAllItems = true;\r
+    else\r
+      throw 31806;\r
+\r
+    extractionInfo.Save();\r
+\r
+    if (dialogItems[kFilesModeIndex].Selected)\r
+      extractSelectedFiles = true;\r
+    else if (dialogItems[kFilesModeIndex + 1].Selected)\r
+      extractSelectedFiles = false;\r
+    else\r
+      throw 31806;\r
+\r
+    oemPassword = dialogItems[kPasswordIndex].Data;\r
+    password = MultiByteToUnicodeString(oemPassword, CP_OEMCP);\r
+    passwordIsDefined = !password.IsEmpty();\r
+  }\r
+\r
+  NFile::NDirectory::CreateComplexDirectory(destPathU);\r
+\r
+  /*\r
+  vector<int> realIndices;\r
+  if (!decompressAllItems)\r
+    GetRealIndexes(panelItems, itemsNumber, realIndices);\r
+  */\r
+  CRecordVector<UINT32> indices;\r
+  indices.Reserve(itemsNumber);\r
+  for (int i = 0; i < itemsNumber; i++)\r
+    indices.Add((UINT32)panelItems[i].UserData);\r
+\r
+  HRESULT result = ExtractFiles(decompressAllItems, &indices.Front(), itemsNumber,\r
+      !showBox, extractionInfo.PathMode, extractionInfo.OverwriteMode,\r
+      destPathU,\r
+      passwordIsDefined, password);\r
+  // HRESULT result = ExtractFiles(decompressAllItems, realIndices, !showBox,\r
+  //     extractionInfo, destPath, passwordIsDefined, password);\r
+  if (result != S_OK)\r
+  {\r
+    if (result == E_ABORT)\r
+      return NFileOperationReturnCode::kInterruptedByUser;\r
+    ShowErrorMessage(result);\r
+    return NFileOperationReturnCode::kError;\r
+  }\r
+\r
+  // if (move != 0)\r
+  // {\r
+  //   if (DeleteFiles(panelItems, itemsNumber, opMode) == FALSE)\r
+  //     return NFileOperationReturnCode::kError;\r
+  // }\r
+  return NFileOperationReturnCode::kSuccess;\r
+}\r
diff --git a/CPP/7zip/UI/Far/PluginWrite.cpp b/CPP/7zip/UI/Far/PluginWrite.cpp
new file mode 100755 (executable)
index 0000000..ad6c29b
--- /dev/null
@@ -0,0 +1,780 @@
+// PluginWrite.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Plugin.h"\r
+\r
+#include "Common/Wildcard.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileName.h"\r
+#include "Windows/FileFind.h"\r
+#include "Windows/Defs.h"\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../Common/ZipRegistry.h"\r
+#include "../Common/WorkDir.h"\r
+#include "../Common/OpenArchive.h"\r
+\r
+#include "../Agent/Agent.h"\r
+\r
+#include "ProgressBox.h"\r
+#include "Messages.h"\r
+#include "UpdateCallback100.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+using namespace NDirectory;\r
+using namespace NFar;\r
+\r
+using namespace NUpdateArchive;\r
+\r
+static const char *kHelpTopic =  "Update";\r
+\r
+static LPCWSTR kTempArcivePrefix = L"7zA";\r
+\r
+static const char *kArchiveHistoryKeyName = "7-ZipArcName";\r
+\r
+static UINT32 g_MethodMap[] = { 0, 1, 3, 5, 7, 9 };\r
+\r
+static HRESULT SetOutProperties(IOutFolderArchive *outArchive, UINT32 method)\r
+{\r
+  CMyComPtr<ISetProperties> setProperties;\r
+  if (outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties) == S_OK)\r
+  {\r
+    UStringVector realNames;\r
+    realNames.Add(UString(L"x"));\r
+    NCOM::CPropVariant value = (UInt32)method;\r
+    CRecordVector<const wchar_t *> names;\r
+    for(int i = 0; i < realNames.Size(); i++)\r
+      names.Add(realNames[i]);\r
+    RINOK(setProperties->SetProperties(&names.Front(), &value, names.Size()));\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+NFileOperationReturnCode::EEnum CPlugin::PutFiles(\r
+  struct PluginPanelItem *panelItems, int numItems,\r
+  int moveMode, int opMode)\r
+{\r
+  if(moveMode != 0)\r
+  {\r
+    g_StartupInfo.ShowMessage(NMessageID::kMoveIsNotSupported);\r
+    return NFileOperationReturnCode::kError;\r
+  }\r
+  if (numItems == 0)\r
+    return NFileOperationReturnCode::kError;\r
+\r
+  /*\r
+  if (!m_ArchiverInfo.UpdateEnabled)\r
+  {\r
+    g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);\r
+    return NFileOperationReturnCode::kError;\r
+  }\r
+  */\r
+\r
+  const int kYSize = 14;\r
+  const int kXMid = 38;\r
+\r
+  NCompression::CInfo compressionInfo;\r
+  compressionInfo.Load();\r
+\r
+  int methodIndex = 0;\r
+  int i;\r
+  for (i = sizeof(g_MethodMap) / sizeof(g_MethodMap[0]) - 1; i >= 0; i--)\r
+    if (compressionInfo.Level >= g_MethodMap[i])\r
+    {\r
+      methodIndex = i;\r
+      break;\r
+    }\r
+\r
+  const int kMethodRadioIndex = 2;\r
+  const int kModeRadioIndex = kMethodRadioIndex + 7;\r
+\r
+  struct CInitDialogItem initItems[]={\r
+    { DI_DOUBLEBOX, 3, 1, 72, kYSize - 2, false, false, 0, false, NMessageID::kUpdateTitle, NULL, NULL },\r
+    { DI_SINGLEBOX, 4, 2, kXMid - 2, 2 + 7, false, false, 0, false, NMessageID::kUpdateMethod, NULL, NULL },\r
+    { DI_RADIOBUTTON, 6, 3, 0, 0, methodIndex == 0, methodIndex == 0,\r
+        DIF_GROUP, false, NMessageID::kUpdateMethodStore, NULL, NULL },\r
+    { DI_RADIOBUTTON, 6, 4, 0, 0, methodIndex == 1, methodIndex == 1,\r
+        0, false, NMessageID::kUpdateMethodFastest, NULL, NULL },\r
+    { DI_RADIOBUTTON, 6, 5, 0, 0, methodIndex == 2, methodIndex == 2,\r
+        0, false, NMessageID::kUpdateMethodFast, NULL, NULL },\r
+    { DI_RADIOBUTTON, 6, 6, 0, 0, methodIndex == 3, methodIndex == 3,\r
+        0, false, NMessageID::kUpdateMethodNormal, NULL, NULL },\r
+    { DI_RADIOBUTTON, 6, 7, 0, 0, methodIndex == 4, methodIndex == 4,\r
+        0, false, NMessageID::kUpdateMethodMaximum, NULL, NULL },\r
+    { DI_RADIOBUTTON, 6, 8, 0, 0, methodIndex == 5, methodIndex == 5,\r
+        0, false, NMessageID::kUpdateMethodUltra, NULL, NULL },\r
+    \r
+    { DI_SINGLEBOX, kXMid, 2, 70, 2 + 5, false, false, 0, false, NMessageID::kUpdateMode, NULL, NULL },\r
+    { DI_RADIOBUTTON, kXMid + 2, 3, 0, 0, false, true,\r
+        DIF_GROUP, false, NMessageID::kUpdateModeAdd, NULL, NULL },\r
+    { DI_RADIOBUTTON, kXMid + 2, 4, 0, 0, false, false,\r
+        0, false, NMessageID::kUpdateModeUpdate, NULL, NULL },\r
+    { DI_RADIOBUTTON, kXMid + 2, 5, 0, 0, false, false,\r
+        0, false, NMessageID::kUpdateModeFreshen, NULL, NULL },\r
+    { DI_RADIOBUTTON, kXMid + 2, 6, 0, 0, false, false,\r
+        0, false, NMessageID::kUpdateModeSynchronize, NULL, NULL },\r
+  \r
+    { DI_TEXT, 3, kYSize - 4, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL  },\r
+    \r
+    { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kUpdateAdd, NULL, NULL  },\r
+    { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kCancel, NULL, NULL  }\r
+  };\r
+  \r
+  const int kNumDialogItems = sizeof(initItems) / sizeof(initItems[0]);\r
+  const int kOkButtonIndex = kNumDialogItems - 2;\r
+  FarDialogItem dialogItems[kNumDialogItems];\r
+  g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems);\r
+  int askCode = g_StartupInfo.ShowDialog(76, kYSize,\r
+      kHelpTopic, dialogItems, kNumDialogItems);\r
+  if (askCode != kOkButtonIndex)\r
+    return NFileOperationReturnCode::kInterruptedByUser;\r
+\r
+  compressionInfo.Level = g_MethodMap[0];\r
+  for (i = 0; i < sizeof(g_MethodMap)/ sizeof(g_MethodMap[0]); i++)\r
+    if (dialogItems[kMethodRadioIndex + i].Selected)\r
+      compressionInfo.Level = g_MethodMap[i];\r
+\r
+  const CActionSet *actionSet;\r
+\r
+  if (dialogItems[kModeRadioIndex].Selected)\r
+    actionSet = &kAddActionSet;\r
+  else if (dialogItems[kModeRadioIndex + 1].Selected)\r
+    actionSet = &kUpdateActionSet;\r
+  else if (dialogItems[kModeRadioIndex + 2].Selected)\r
+    actionSet = &kFreshActionSet;\r
+  else if (dialogItems[kModeRadioIndex + 3].Selected)\r
+    actionSet = &kSynchronizeActionSet;\r
+  else\r
+    throw 51751;\r
+\r
+  compressionInfo.Save();\r
+\r
+  NWorkDir::CInfo workDirInfo;\r
+  workDirInfo.Load();\r
+  UString workDir = GetWorkDir(workDirInfo, m_FileName);\r
+  CreateComplexDirectory(workDir);\r
+\r
+  CTempFileW tempFile;\r
+  UString tempFileName;\r
+  if (tempFile.Create(workDir, kTempArcivePrefix, tempFileName) == 0)\r
+    return NFileOperationReturnCode::kError;\r
+\r
+\r
+  /*\r
+  CSysStringVector fileNames;\r
+  for(int i = 0; i < numItems; i++)\r
+  {\r
+    const PluginPanelItem &panelItem = panelItems[i];\r
+    CSysString fullName;\r
+    if (!MyGetFullPathName(panelItem.FindData.cFileName, fullName))\r
+      return NFileOperationReturnCode::kError;\r
+    fileNames.Add(fullName);\r
+  }\r
+  */\r
+\r
+  CScreenRestorer screenRestorer;\r
+  CProgressBox progressBox;\r
+  CProgressBox *progressBoxPointer = NULL;\r
+  if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0)\r
+  {\r
+    screenRestorer.Save();\r
+\r
+    progressBoxPointer = &progressBox;\r
+    progressBox.Init(\r
+        // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),\r
+        g_StartupInfo.GetMsgString(NMessageID::kUpdating), 48);\r
+  }\r
\r
+  ////////////////////////////\r
+  // Save FolderItem;\r
+  UStringVector aPathVector;\r
+  GetPathParts(aPathVector);\r
+  \r
+  /*\r
+  UString anArchivePrefix;\r
+  for(i = aPathVector.Size() - 1; i >= 0; i--)\r
+  {\r
+    anArchivePrefix += aPathVector[i];\r
+    anArchivePrefix += wchar_t(NName::kDirDelimiter);\r
+  }\r
+  /////////////////////////////////\r
+  */\r
+\r
+  UStringVector fileNames;\r
+  fileNames.Reserve(numItems);\r
+  for(i = 0; i < numItems; i++)\r
+    fileNames.Add(MultiByteToUnicodeString(panelItems[i].FindData.cFileName, CP_OEMCP));\r
+  CRecordVector<const wchar_t *> fileNamePointers;\r
+  fileNamePointers.Reserve(numItems);\r
+  for(i = 0; i < numItems; i++)\r
+    fileNamePointers.Add(fileNames[i]);\r
+\r
+  CMyComPtr<IOutFolderArchive> outArchive;\r
+  HRESULT result = m_ArchiveHandler.QueryInterface(IID_IOutFolderArchive, &outArchive);\r
+  if(result != S_OK)\r
+  {\r
+    g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);\r
+    return NFileOperationReturnCode::kError;\r
+  }\r
+  outArchive->SetFolder(_folder);\r
+\r
+  // CSysString aCurrentFolder;\r
+  // MyGetCurrentDirectory(aCurrentFolder);\r
+  // outArchive->SetFiles(MultiByteToUnicodeString(aCurrentFolder, CP_OEMCP),\r
+  outArchive->SetFiles(L"",\r
+      &fileNamePointers.Front(), fileNamePointers.Size());\r
+  BYTE actionSetByte[NUpdateArchive::NPairState::kNumValues];\r
+  for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)\r
+    actionSetByte[i] = (BYTE)actionSet->StateActions[i];\r
+\r
+  CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp;\r
+  CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec );\r
+  \r
+  updateCallbackSpec->Init(/* m_ArchiveHandler, */ progressBoxPointer);\r
+\r
+  if (SetOutProperties(outArchive, compressionInfo.Level) != S_OK)\r
+    return NFileOperationReturnCode::kError;\r
+\r
+  result = outArchive->DoOperation2(tempFileName, actionSetByte, NULL, updateCallback);\r
+  updateCallback.Release();\r
+  outArchive.Release();\r
+\r
+  /*\r
+  HRESULT result = Compress(fileNames, anArchivePrefix, *actionSet,\r
+      m_ProxyHandler.get(),\r
+      m_ArchiverInfo.ClassID, compressionInfo.Method == 0,\r
+      compressionInfo.Method == 2, tempFileName, progressBoxPointer);\r
+  */\r
+\r
+  if (result != S_OK)\r
+  {\r
+    ShowErrorMessage(result);\r
+    return NFileOperationReturnCode::kError;\r
+  }\r
+\r
+  _folder.Release();\r
+  m_ArchiveHandler->Close();\r
+  \r
+  // m_FolderItem = NULL;\r
+  \r
+  if (!DeleteFileAlways(m_FileName))\r
+  {\r
+    ShowLastErrorMessage();\r
+    return NFileOperationReturnCode::kError;\r
+  }\r
+\r
+  tempFile.DisableDeleting();\r
+  if (!MyMoveFile(tempFileName, m_FileName))\r
+  {\r
+    ShowLastErrorMessage();\r
+    return NFileOperationReturnCode::kError;\r
+  }\r
+  \r
+  m_ArchiveHandler->ReOpen(NULL);\r
+  if (result != S_OK)\r
+  {\r
+    ShowErrorMessage(result);\r
+    return NFileOperationReturnCode::kError;\r
+  }\r
+\r
+  /*\r
+  if(m_ProxyHandler->ReInit(NULL) != S_OK)\r
+    return NFileOperationReturnCode::kError;\r
+  */\r
+  \r
+  ////////////////////////////\r
+  // Restore FolderItem;\r
+\r
+  m_ArchiveHandler->BindToRootFolder(&_folder);\r
+  for (i = 0; i < aPathVector.Size(); i++)\r
+  {\r
+    CMyComPtr<IFolderFolder> newFolder;\r
+    _folder->BindToFolder(aPathVector[i], &newFolder);\r
+    if(!newFolder  )\r
+      break;\r
+    _folder = newFolder;\r
+  }\r
+\r
+  /*\r
+  if(moveMode != 0)\r
+  {\r
+    for(int i = 0; i < numItems; i++)\r
+    {\r
+      const PluginPanelItem &aPluginPanelItem = panelItems[i];\r
+      bool result;\r
+      if(NFile::NFind::NAttributes::IsDir(aPluginPanelItem.FindData.dwFileAttributes))\r
+        result = NFile::NDirectory::RemoveDirectoryWithSubItems(\r
+           aPluginPanelItem.FindData.cFileName);\r
+      else\r
+        result = NFile::NDirectory::DeleteFileAlways(\r
+           aPluginPanelItem.FindData.cFileName);\r
+      if(!result)\r
+        return NFileOperationReturnCode::kError;\r
+    }\r
+  }\r
+  */\r
+  return NFileOperationReturnCode::kSuccess;\r
+}\r
+\r
+namespace NPathType\r
+{\r
+  enum EEnum\r
+  {\r
+    kLocal,\r
+    kUNC\r
+  };\r
+  EEnum GetPathType(const UString &path);\r
+}\r
+\r
+struct CParsedPath\r
+{\r
+  UString Prefix; // Disk or UNC with slash\r
+  UStringVector PathParts;\r
+  void ParsePath(const UString &path);\r
+  UString MergePath() const;\r
+};\r
+\r
+static const wchar_t kDirDelimiter = WCHAR_PATH_SEPARATOR;\r
+static const wchar_t kDiskDelimiter = L':';\r
+\r
+namespace NPathType\r
+{\r
+  EEnum GetPathType(const UString &path)\r
+  {\r
+    if (path.Length() <= 2)\r
+      return kLocal;\r
+    if (path[0] == kDirDelimiter && path[1] == kDirDelimiter)\r
+      return kUNC;\r
+    return kLocal;\r
+  }\r
+}\r
+\r
+void CParsedPath::ParsePath(const UString &path)\r
+{\r
+  int curPos = 0;\r
+  switch (NPathType::GetPathType(path))\r
+  {\r
+    case NPathType::kLocal:\r
+    {\r
+      int posDiskDelimiter = path.Find(kDiskDelimiter);\r
+      if(posDiskDelimiter >= 0)\r
+      {\r
+        curPos = posDiskDelimiter + 1;\r
+        if (path.Length() > curPos)\r
+          if(path[curPos] == kDirDelimiter)\r
+            curPos++;\r
+      }\r
+      break;\r
+    }\r
+    case NPathType::kUNC:\r
+    {\r
+      int curPos = path.Find(kDirDelimiter, 2);\r
+      if(curPos < 0)\r
+        curPos = path.Length();\r
+      else\r
+        curPos++;\r
+    }\r
+  }\r
+  Prefix = path.Left(curPos);\r
+  SplitPathToParts(path.Mid(curPos), PathParts);\r
+}\r
+\r
+UString CParsedPath::MergePath() const\r
+{\r
+  UString result = Prefix;\r
+  for(int i = 0; i < PathParts.Size(); i++)\r
+  {\r
+    if (i != 0)\r
+      result += kDirDelimiter;\r
+    result += PathParts[i];\r
+  }\r
+  return result;\r
+}\r
+\r
+\r
+/*\r
+// {23170F69-40C1-278A-1000-000100030000}\r
+DEFINE_GUID(CLSID_CAgentArchiveHandler,\r
+  0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00);\r
+*/\r
+\r
+HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)\r
+{\r
+  if (pluginPanelItems.Size() == 0)\r
+    return E_FAIL;\r
+\r
+  UStringVector fileNames;\r
+  int i;\r
+  for(i = 0; i < pluginPanelItems.Size(); i++)\r
+  {\r
+    const PluginPanelItem &panelItem = pluginPanelItems[i];\r
+    UString fullName;\r
+    if (strcmp(panelItem.FindData.cFileName, "..") == 0 &&\r
+        NFind::NAttributes::IsDir(panelItem.FindData.dwFileAttributes))\r
+      return E_FAIL;\r
+    if (strcmp(panelItem.FindData.cFileName, ".") == 0 &&\r
+        NFind::NAttributes::IsDir(panelItem.FindData.dwFileAttributes))\r
+      return E_FAIL;\r
+    UString fileNameUnicode = MultiByteToUnicodeString(panelItem.FindData.cFileName, CP_OEMCP);\r
+    if (!MyGetFullPathName(fileNameUnicode, fullName))\r
+      return E_FAIL;\r
+    fileNames.Add(fullName);\r
+  }\r
+\r
+  NCompression::CInfo compressionInfo;\r
+  compressionInfo.Load();\r
+  \r
+  int archiverIndex = 0;\r
+\r
+  CCodecs *codecs = new CCodecs;\r
+  CMyComPtr<ICompressCodecsInfo> compressCodecsInfo = codecs;\r
+  if (codecs->Load() != S_OK)\r
+    throw "Can't load 7-Zip codecs";\r
+  {\r
+    for (int i = 0; i < codecs->Formats.Size(); i++)\r
+    {\r
+      const CArcInfoEx &arcInfo = codecs->Formats[i];\r
+      if (arcInfo.UpdateEnabled)\r
+      {\r
+        if (archiverIndex == -1)\r
+          archiverIndex = i;\r
+        if (arcInfo.Name.CompareNoCase(compressionInfo.ArcType) == 0)\r
+          archiverIndex = i;\r
+      }\r
+    }\r
+  }\r
+\r
+\r
+  UString resultPath;\r
+  {\r
+    CParsedPath parsedPath;\r
+    parsedPath.ParsePath(fileNames.Front());\r
+    if(parsedPath.PathParts.Size() == 0)\r
+      return E_FAIL;\r
+    if (fileNames.Size() == 1 || parsedPath.PathParts.Size() == 1)\r
+    {\r
+      // CSysString pureName, dot, extension;\r
+      resultPath = parsedPath.PathParts.Back();\r
+    }\r
+    else\r
+    {\r
+      parsedPath.PathParts.DeleteBack();\r
+      resultPath = parsedPath.PathParts.Back();\r
+    }\r
+  }\r
+  UString archiveNameSrc = resultPath;\r
+  UString archiveName = archiveNameSrc;\r
+\r
+  const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex];\r
+  int prevFormat = archiverIndex;\r
\r
+  if (!arcInfo.KeepName)\r
+  {\r
+    int dotPos = archiveName.ReverseFind('.');\r
+    int slashPos = MyMax(archiveName.ReverseFind('\\'), archiveName.ReverseFind('/'));\r
+    if (dotPos > slashPos)\r
+      archiveName = archiveName.Left(dotPos);\r
+  }\r
+  archiveName += L'.';\r
+  archiveName += arcInfo.GetMainExt();\r
+  \r
+  const CActionSet *actionSet = &kAddActionSet;\r
+\r
+  for (;;)\r
+  {\r
+    AString archiveNameA = UnicodeStringToMultiByte(archiveName, CP_OEMCP);\r
+    const int kYSize = 16;\r
+    const int kXMid = 38;\r
+  \r
+    const int kArchiveNameIndex = 2;\r
+    const int kMethodRadioIndex = kArchiveNameIndex + 2;\r
+    const int kModeRadioIndex = kMethodRadioIndex + 7;\r
+\r
+    const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex];\r
+\r
+    char updateAddToArchiveString[512];\r
+    const AString s = UnicodeStringToMultiByte(arcInfo.Name, CP_OEMCP);\r
+\r
+    sprintf(updateAddToArchiveString,\r
+        g_StartupInfo.GetMsgString(NMessageID::kUpdateAddToArchive), (const char *)s);\r
+\r
+    int methodIndex = 0;\r
+    int i;\r
+    for (i = sizeof(g_MethodMap) / sizeof(g_MethodMap[0]) - 1; i >= 0; i--)\r
+      if (compressionInfo.Level >= g_MethodMap[i])\r
+      {\r
+        methodIndex = i;\r
+        break;\r
+      }\r
+\r
+    struct CInitDialogItem initItems[]=\r
+    {\r
+      { DI_DOUBLEBOX, 3, 1, 72, kYSize - 2, false, false, 0, false, NMessageID::kUpdateTitle, NULL, NULL },\r
+\r
+      { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, -1, updateAddToArchiveString, NULL },\r
+      \r
+      { DI_EDIT, 5, 3, 70, 3, true, false, DIF_HISTORY, false, -1, archiveNameA, kArchiveHistoryKeyName},\r
+      // { DI_EDIT, 5, 3, 70, 3, true, false, 0, false, -1, archiveName, NULL},\r
+      \r
+      { DI_SINGLEBOX, 4, 4, kXMid - 2, 4 + 7, false, false, 0, false, NMessageID::kUpdateMethod, NULL, NULL },\r
+      { DI_RADIOBUTTON, 6, 5, 0, 0, false, methodIndex == 0,\r
+          DIF_GROUP, false, NMessageID::kUpdateMethodStore, NULL, NULL },\r
+      { DI_RADIOBUTTON, 6, 6, 0, 0, false, methodIndex == 1,\r
+          0, false, NMessageID::kUpdateMethodFastest, NULL, NULL },\r
+      { DI_RADIOBUTTON, 6, 7, 0, 0, false, methodIndex == 2,\r
+          0, false, NMessageID::kUpdateMethodFast, NULL, NULL },\r
+      { DI_RADIOBUTTON, 6, 8, 0, 0, false, methodIndex == 3,\r
+          0, false, NMessageID::kUpdateMethodNormal, NULL, NULL },\r
+      { DI_RADIOBUTTON, 6, 9, 0, 0, false, methodIndex == 4,\r
+          false, 0, NMessageID::kUpdateMethodMaximum, NULL, NULL },\r
+      { DI_RADIOBUTTON, 6, 10, 0, 0, false, methodIndex == 5,\r
+          false, 0, NMessageID::kUpdateMethodUltra, NULL, NULL },\r
+      \r
+      { DI_SINGLEBOX, kXMid, 4, 70, 4 + 5, false, false, 0, false, NMessageID::kUpdateMode, NULL, NULL },\r
+      { DI_RADIOBUTTON, kXMid + 2, 5, 0, 0, false,\r
+          actionSet == &kAddActionSet,\r
+          DIF_GROUP, false, NMessageID::kUpdateModeAdd, NULL, NULL },\r
+      { DI_RADIOBUTTON, kXMid + 2, 6, 0, 0, false,\r
+          actionSet == &kUpdateActionSet,\r
+          0, false, NMessageID::kUpdateModeUpdate, NULL, NULL },\r
+      { DI_RADIOBUTTON, kXMid + 2, 7, 0, 0, false,\r
+          actionSet == &kFreshActionSet,\r
+          0, false, NMessageID::kUpdateModeFreshen, NULL, NULL },\r
+      { DI_RADIOBUTTON, kXMid + 2, 8, 0, 0, false,\r
+          actionSet == &kSynchronizeActionSet,\r
+          0, false, NMessageID::kUpdateModeSynchronize, NULL, NULL },\r
+      \r
+      { DI_TEXT, 3, kYSize - 4, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL  },\r
+      \r
+      { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kUpdateAdd, NULL, NULL  },\r
+      { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kUpdateSelectArchiver, NULL, NULL  },\r
+      { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kCancel, NULL, NULL  }\r
+    };\r
+\r
+    const int kNumDialogItems = sizeof(initItems) / sizeof(initItems[0]);\r
+    \r
+    const int kOkButtonIndex = kNumDialogItems - 3;\r
+    const int kSelectarchiverButtonIndex = kNumDialogItems - 2;\r
+\r
+    FarDialogItem dialogItems[kNumDialogItems];\r
+    g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems);\r
+    int askCode = g_StartupInfo.ShowDialog(76, kYSize,\r
+        kHelpTopic, dialogItems, kNumDialogItems);\r
+\r
+    archiveNameA = dialogItems[kArchiveNameIndex].Data;\r
+    archiveNameA.Trim();\r
+    archiveName = MultiByteToUnicodeString(archiveNameA, CP_OEMCP);\r
+\r
+    compressionInfo.Level = g_MethodMap[0];\r
+    for (i = 0; i < sizeof(g_MethodMap)/ sizeof(g_MethodMap[0]); i++)\r
+      if (dialogItems[kMethodRadioIndex + i].Selected)\r
+        compressionInfo.Level = g_MethodMap[i];\r
+\r
+    if (dialogItems[kModeRadioIndex].Selected)\r
+      actionSet = &kAddActionSet;\r
+    else if (dialogItems[kModeRadioIndex + 1].Selected)\r
+      actionSet = &kUpdateActionSet;\r
+    else if (dialogItems[kModeRadioIndex + 2].Selected)\r
+      actionSet = &kFreshActionSet;\r
+    else if (dialogItems[kModeRadioIndex + 3].Selected)\r
+      actionSet = &kSynchronizeActionSet;\r
+    else\r
+      throw 51751;\r
+\r
+    if (askCode == kSelectarchiverButtonIndex)\r
+    {\r
+      CIntVector indices;\r
+      CSysStringVector archiverNames;\r
+      for(int i = 0; i < codecs->Formats.Size(); i++)\r
+      {\r
+        const CArcInfoEx &arc = codecs->Formats[i];\r
+        if (arc.UpdateEnabled)\r
+        {\r
+          indices.Add(i);\r
+          archiverNames.Add(GetSystemString(arc.Name, CP_OEMCP));\r
+        }\r
+      }\r
+    \r
+      int index = g_StartupInfo.Menu(FMENU_AUTOHIGHLIGHT,\r
+          g_StartupInfo.GetMsgString(NMessageID::kUpdateSelectArchiverMenuTitle),\r
+          NULL, archiverNames, archiverIndex);\r
+      if(index >= 0)\r
+      {\r
+        const CArcInfoEx &prevArchiverInfo = codecs->Formats[prevFormat];\r
+        if (prevArchiverInfo.KeepName)\r
+        {\r
+          const UString &prevExtension = prevArchiverInfo.GetMainExt();\r
+          const int prevExtensionLen = prevExtension.Length();\r
+          if (archiveName.Right(prevExtensionLen).CompareNoCase(prevExtension) == 0)\r
+          {\r
+            int pos = archiveName.Length() - prevExtensionLen;\r
+            if (pos > 1)\r
+            {\r
+              int dotPos = archiveName.ReverseFind('.');\r
+              if (dotPos == pos - 1)\r
+                archiveName = archiveName.Left(dotPos);\r
+            }\r
+          }\r
+        }\r
+\r
+        archiverIndex = indices[index];\r
+        const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex];\r
+        prevFormat = archiverIndex;\r
+        \r
+        if (arcInfo.KeepName)\r
+          archiveName = archiveNameSrc;\r
+        else\r
+        {\r
+          int dotPos = archiveName.ReverseFind('.');\r
+          int slashPos = MyMax(archiveName.ReverseFind('\\'), archiveName.ReverseFind('/'));\r
+          if (dotPos > slashPos)\r
+            archiveName = archiveName.Left(dotPos);\r
+        }\r
+        archiveName += L'.';\r
+        archiveName += arcInfo.GetMainExt();\r
+      }\r
+      continue;\r
+    }\r
+\r
+    if (askCode != kOkButtonIndex)\r
+      return E_ABORT;\r
+    \r
+    break;\r
+  }\r
+\r
+  const CArcInfoEx &archiverInfoFinal = codecs->Formats[archiverIndex];\r
+  compressionInfo.ArcType = archiverInfoFinal.Name;\r
+  compressionInfo.Save();\r
+\r
+  NWorkDir::CInfo workDirInfo;\r
+  workDirInfo.Load();\r
+\r
+  UString fullArchiveName;\r
+  if (!MyGetFullPathName(archiveName, fullArchiveName))\r
+    return E_FAIL;\r
+   \r
+  UString workDir = GetWorkDir(workDirInfo, fullArchiveName);\r
+  CreateComplexDirectory(workDir);\r
+\r
+  CTempFileW tempFile;\r
+  UString tempFileName;\r
+  if (tempFile.Create(workDir, kTempArcivePrefix, tempFileName) == 0)\r
+    return E_FAIL;\r
+\r
+\r
+  CScreenRestorer screenRestorer;\r
+  CProgressBox progressBox;\r
+  CProgressBox *progressBoxPointer = NULL;\r
+\r
+  screenRestorer.Save();\r
+\r
+  progressBoxPointer = &progressBox;\r
+  progressBox.Init(\r
+      // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),\r
+      g_StartupInfo.GetMsgString(NMessageID::kUpdating), 48);\r
+\r
+\r
+  NFind::CFileInfoW fileInfo;\r
+\r
+  CMyComPtr<IOutFolderArchive> outArchive;\r
+\r
+  CMyComPtr<IInFolderArchive> archiveHandler;\r
+  if(fileInfo.Find(fullArchiveName))\r
+  {\r
+    if (fileInfo.IsDir())\r
+      throw "There is Directory with such name";\r
+\r
+    CAgent *agentSpec = new CAgent;\r
+    archiveHandler = agentSpec;\r
+    // CLSID realClassID;\r
+    CMyComBSTR archiveType;\r
+    RINOK(agentSpec->Open(NULL,\r
+        GetUnicodeString(fullArchiveName, CP_OEMCP), UString(),\r
+        // &realClassID,\r
+        &archiveType,\r
+        NULL));\r
+\r
+    if (archiverInfoFinal.Name.CompareNoCase((const wchar_t *)archiveType) != 0)\r
+      throw "Type of existing archive differs from specified type";\r
+    HRESULT result = archiveHandler.QueryInterface(\r
+        IID_IOutFolderArchive, &outArchive);\r
+    if(result != S_OK)\r
+    {\r
+      g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);\r
+      return E_FAIL;\r
+    }\r
+  }\r
+  else\r
+  {\r
+    // HRESULT result = outArchive.CoCreateInstance(classID);\r
+    CAgent *agentSpec = new CAgent;\r
+    outArchive = agentSpec;\r
+\r
+    /*\r
+    HRESULT result = outArchive.CoCreateInstance(CLSID_CAgentArchiveHandler);\r
+    if (result != S_OK)\r
+    {\r
+      g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);\r
+      return E_FAIL;\r
+    }\r
+    */\r
+  }\r
+\r
+  CRecordVector<const wchar_t *> fileNamePointers;\r
+  fileNamePointers.Reserve(fileNames.Size());\r
+  for(i = 0; i < fileNames.Size(); i++)\r
+    fileNamePointers.Add(fileNames[i]);\r
+\r
+  outArchive->SetFolder(NULL);\r
+  // CSysString aCurrentFolder;\r
+  // MyGetCurrentDirectory(aCurrentFolder);\r
+  // outArchive->SetFiles(MultiByteToUnicodeString(aCurrentFolder, CP_OEMCP),\r
+  outArchive->SetFiles(L"",\r
+    &fileNamePointers.Front(), fileNamePointers.Size());\r
+  BYTE actionSetByte[NUpdateArchive::NPairState::kNumValues];\r
+  for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)\r
+    actionSetByte[i] = (BYTE)actionSet->StateActions[i];\r
+\r
+  CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp;\r
+  CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec );\r
+  \r
+  updateCallbackSpec->Init(/* archiveHandler, */ progressBoxPointer);\r
+\r
+\r
+  RINOK(SetOutProperties(outArchive, compressionInfo.Level));\r
+\r
+  HRESULT result = outArchive->DoOperation(\r
+      codecs, archiverIndex,\r
+      tempFileName, actionSetByte,\r
+      NULL, updateCallback);\r
+  updateCallback.Release();\r
+  outArchive.Release();\r
+\r
+  if (result != S_OK)\r
+  {\r
+    ShowErrorMessage(result);\r
+    return result;\r
+  }\r
\r
+  if(archiveHandler)\r
+  {\r
+    archiveHandler->Close();\r
+    if (!DeleteFileAlways(fullArchiveName))\r
+    {\r
+      ShowLastErrorMessage();\r
+      return NFileOperationReturnCode::kError;\r
+    }\r
+  }\r
+  tempFile.DisableDeleting();\r
+  if (!MyMoveFile(tempFileName, fullArchiveName))\r
+  {\r
+    ShowLastErrorMessage();\r
+    return E_FAIL;\r
+  }\r
+  \r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/UI/Far/ProgressBox.cpp b/CPP/7zip/UI/Far/ProgressBox.cpp
new file mode 100755 (executable)
index 0000000..35d3f2d
--- /dev/null
@@ -0,0 +1,112 @@
+// ProgressBox.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include <stdio.h>\r
+\r
+#include "ProgressBox.h"\r
+#include "Common/IntToString.h"\r
+#include "FarUtils.h"\r
+\r
+static void CopySpaces(char *dest, int numSpaces)\r
+{\r
+  int i;\r
+  for (i = 0; i < numSpaces; i++)\r
+    dest[i] = ' ';\r
+  dest[i] = '\0';\r
+}\r
+\r
+void ConvertUInt64ToStringAligned(UInt64 value, char *s, int alignSize)\r
+{\r
+  char temp[32];\r
+  ConvertUInt64ToString(value, temp);\r
+  int len = (int)strlen(temp);\r
+  int numSpaces = 0;\r
+  if (len < alignSize)\r
+  {\r
+    numSpaces = alignSize - len;\r
+    CopySpaces(s, numSpaces);\r
+  }\r
+  strcpy(s + numSpaces, temp);\r
+}\r
+\r
+\r
+// ---------- CMessageBox ----------\r
+\r
+static const int kMaxLen = 255;\r
+\r
+void CMessageBox::Init(const AString &title, int width)\r
+{\r
+  _title = title;\r
+  _width = MyMin(width, kMaxLen);\r
+}\r
+\r
+void CMessageBox::ShowMessages(const char *strings[], int numStrings)\r
+{\r
+  const int kNumStaticStrings = 1;\r
+  const int kNumStringsMax = 10;\r
+\r
+  if (numStrings > kNumStringsMax)\r
+    numStrings = kNumStringsMax;\r
+\r
+  const char *msgItems[kNumStaticStrings + kNumStringsMax];\r
+  msgItems[0] = _title;\r
+\r
+  char formattedMessages[kNumStringsMax][kMaxLen + 1];\r
+\r
+  for (int i = 0; i < numStrings; i++)\r
+  {\r
+    char *formattedMessage = formattedMessages[i];\r
+    const char *s = strings[i];\r
+    int len = (int)strlen(s);\r
+    if (len < kMaxLen)\r
+    {\r
+      int size = MyMax(_width, len);\r
+      int startPos = (size - len) / 2;\r
+      CopySpaces(formattedMessage, startPos);\r
+      strcpy(formattedMessage + startPos, s);\r
+      CopySpaces(formattedMessage + startPos + len, size - startPos - len);\r
+    }\r
+    else\r
+    {\r
+      strncpy(formattedMessage, s, kMaxLen);\r
+      formattedMessage[kMaxLen] = 0;\r
+    }\r
+    msgItems[kNumStaticStrings + i] = formattedMessage;\r
+  }\r
+  NFar::g_StartupInfo.ShowMessage(0, NULL, msgItems, kNumStaticStrings + numStrings, 0);\r
+}\r
+\r
+\r
+// ---------- CProgressBox ----------\r
+\r
+void CProgressBox::Init(const AString &title, int width)\r
+{\r
+  CMessageBox::Init(title, width);\r
+  _prevMessage.Empty();\r
+  _prevPercentMessage.Empty();\r
+  _wasShown = false;\r
+}\r
+\r
+void CProgressBox::Progress(const UInt64 *total, const UInt64 *completed, const AString &message)\r
+{\r
+  AString percentMessage;\r
+  if (total != 0 && completed != 0)\r
+  {\r
+    UInt64 totalVal = *total;\r
+    if (totalVal == 0)\r
+      totalVal = 1;\r
+    char buf[32];\r
+    ConvertUInt64ToStringAligned(*completed * 100 / totalVal, buf, 3);\r
+    strcat(buf, "%");\r
+    percentMessage = buf;\r
+  }\r
+  if (message != _prevMessage || percentMessage != _prevPercentMessage || !_wasShown)\r
+  {\r
+    _prevMessage = message;\r
+    _prevPercentMessage = percentMessage;\r
+    const char *strings[] = { message, percentMessage };\r
+    ShowMessages(strings, sizeof(strings) / sizeof(strings[0]));\r
+    _wasShown = true;\r
+  }\r
+}\r
diff --git a/CPP/7zip/UI/Far/ProgressBox.h b/CPP/7zip/UI/Far/ProgressBox.h
new file mode 100755 (executable)
index 0000000..a83df87
--- /dev/null
@@ -0,0 +1,30 @@
+// ProgressBox.h\r
+\r
+#ifndef __PROGRESSBOX_H\r
+#define __PROGRESSBOX_H\r
+\r
+#include "Common/MyString.h"\r
+#include "Common/Types.h"\r
+\r
+void ConvertUInt64ToStringAligned(UInt64 value, char *s, int alignSize);\r
+\r
+class CMessageBox\r
+{\r
+  AString _title;\r
+  int _width;\r
+public:\r
+  void Init(const AString &title, int width);\r
+  void ShowMessages(const char *strings[], int numStrings);\r
+};\r
+\r
+class CProgressBox: public CMessageBox\r
+{\r
+  AString _prevMessage;\r
+  AString _prevPercentMessage;\r
+  bool _wasShown;\r
+public:\r
+  void Init(const AString &title, int width);\r
+  void Progress(const UInt64 *total, const UInt64 *completed, const AString &message);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Far/StdAfx.cpp b/CPP/7zip/UI/Far/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..c6d3b1f
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/UI/Far/StdAfx.h b/CPP/7zip/UI/Far/StdAfx.h
new file mode 100755 (executable)
index 0000000..0986203
--- /dev/null
@@ -0,0 +1,13 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#define _CRT_SECURE_NO_DEPRECATE\r
+#include <windows.h>\r
+#include <stdio.h>\r
+\r
+#include "Common/NewHandler.h"\r
+\r
+#endif\r
+\r
diff --git a/CPP/7zip/UI/Far/UpdateCallback100.cpp b/CPP/7zip/UI/Far/UpdateCallback100.cpp
new file mode 100755 (executable)
index 0000000..a93890d
--- /dev/null
@@ -0,0 +1,66 @@
+// UpdateCallback.h\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "UpdateCallback100.h"\r
+\r
+#include "Common/Defs.h"\r
+#include "Common/StringConvert.h"\r
+#include "FarUtils.h"\r
+\r
+using namespace NFar;\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::SetNumFiles(UInt64 /* numFiles */)\r
+{\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::SetTotal(UInt64 size)\r
+{\r
+  _total = size;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::SetCompleted(const UInt64 *completeValue)\r
+{\r
+  if (WasEscPressed())\r
+    return E_ABORT;\r
+  if (_progressBox != 0)\r
+    _progressBox->Progress(&_total, completeValue, AString());\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::CompressOperation(const wchar_t* /* name */)\r
+{\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::DeleteOperation(const wchar_t* /* name */)\r
+{\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::OperationResult(Int32 /* opRes */)\r
+{\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::UpdateErrorMessage(const wchar_t *message)\r
+{\r
+  if (g_StartupInfo.ShowMessage(UnicodeStringToMultiByte(message, CP_OEMCP)) == -1)\r
+    return E_ABORT;\r
+  return S_OK;\r
+}\r
+\r
+extern HRESULT GetPassword(UString &password);\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password)\r
+{\r
+  *password = NULL;\r
+  if (!m_PasswordIsDefined)\r
+  {\r
+    RINOK(GetPassword(m_Password));\r
+    m_PasswordIsDefined = true;\r
+  }\r
+  return StringToBstr(m_Password, password);\r
+}\r
diff --git a/CPP/7zip/UI/Far/UpdateCallback100.h b/CPP/7zip/UI/Far/UpdateCallback100.h
new file mode 100755 (executable)
index 0000000..dd7ff54
--- /dev/null
@@ -0,0 +1,43 @@
+// UpdateCallback.h\r
+\r
+#ifndef __UPDATE_CALLBACK_H\r
+#define __UPDATE_CALLBACK_H\r
+\r
+#include "Common/MyCom.h"\r
+\r
+#include "../Agent/IFolderArchive.h"\r
+\r
+#include "../../IPassword.h"\r
+\r
+#include "ProgressBox.h"\r
+\r
+class CUpdateCallback100Imp:\r
+  public IFolderArchiveUpdateCallback,\r
+  public ICryptoGetTextPassword,\r
+  public CMyUnknownImp\r
+{\r
+  // CMyComPtr<IInFolderArchive> _archiveHandler;\r
+  CProgressBox *_progressBox;\r
+  UInt64 _total;\r
+  bool m_PasswordIsDefined;\r
+  UString m_Password;\r
+\r
+public:\r
+  MY_UNKNOWN_IMP1(ICryptoGetTextPassword)\r
+\r
+  INTERFACE_IProgress(;)\r
+  INTERFACE_IFolderArchiveUpdateCallback(;)\r
+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);\r
+\r
+  CUpdateCallback100Imp(): _total(0) {}\r
+  void Init(/* IInFolderArchive *archiveHandler, */ CProgressBox *progressBox)\r
+  {\r
+    // _archiveHandler = archiveHandler;\r
+    _progressBox = progressBox;\r
+    m_PasswordIsDefined = false;\r
+  }\r
+};\r
+\r
+\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/Far/makefile b/CPP/7zip/UI/Far/makefile
new file mode 100755 (executable)
index 0000000..785b2ef
--- /dev/null
@@ -0,0 +1,119 @@
+PROG = 7-ZipFar.dll\r
+DEF_FILE = Far.def\r
+CFLAGS = $(CFLAGS) -I ../../../ \\r
+  -DEXTERNAL_CODECS\r
+\r
+!IFNDEF UNDER_CE\r
+CFLAGS = $(CFLAGS) -DWIN_LONG_PATH\r
+!ENDIF\r
+\r
+FAR_OBJS = \\r
+  $O\ExtractEngine.obj \\r
+  $O\FarUtils.obj \\r
+  $O\Main.obj \\r
+  $O\OverwriteDialog.obj \\r
+  $O\Plugin.obj \\r
+  $O\PluginCommon.obj \\r
+  $O\PluginDelete.obj \\r
+  $O\PluginRead.obj \\r
+  $O\PluginWrite.obj \\r
+  $O\ProgressBox.obj \\r
+  $O\UpdateCallback100.obj \\r
+\r
+COMMON_OBJS = \\r
+  $O\IntToString.obj \\r
+  $O\NewHandler.obj \\r
+  $O\MyString.obj \\r
+  $O\StringConvert.obj \\r
+  $O\StringToInt.obj \\r
+  $O\MyVector.obj \\r
+  $O\Wildcard.obj \\r
+\r
+WIN_OBJS = \\r
+  $O\DLL.obj \\r
+  $O\Error.obj \\r
+  $O\FileDir.obj \\r
+  $O\FileFind.obj \\r
+  $O\FileIO.obj \\r
+  $O\FileName.obj \\r
+  $O\PropVariant.obj \\r
+  $O\PropVariantConversions.obj \\r
+  $O\Registry.obj \\r
+  $O\Synchronization.obj \\r
+  $O\Time.obj \\r
+\r
+7ZIP_COMMON_OBJS = \\r
+  $O\FilePathAutoRename.obj \\r
+  $O\FileStreams.obj \\r
+  $O\ProgressUtils.obj \\r
+  $O\StreamUtils.obj \\r
+\r
+UI_COMMON_OBJS = \\r
+  $O\ArchiveExtractCallback.obj \\r
+  $O\ArchiveOpenCallback.obj \\r
+  $O\DefaultName.obj \\r
+  $O\EnumDirItems.obj \\r
+  $O\ExtractingFilePath.obj \\r
+  $O\LoadCodecs.obj \\r
+  $O\OpenArchive.obj \\r
+  $O\PropIDUtils.obj \\r
+  $O\SortUtils.obj \\r
+  $O\UpdateAction.obj \\r
+  $O\UpdateCallback.obj \\r
+  $O\UpdatePair.obj \\r
+  $O\UpdateProduce.obj \\r
+  $O\WorkDir.obj \\r
+  $O\ZipRegistry.obj \\r
+\r
+AR_COMMON_OBJS = \\r
+  $O\OutStreamWithCRC.obj \\r
+\r
+AGENT_OBJS = \\r
+  $O\Agent.obj \\r
+  $O\AgentOut.obj \\r
+  $O\AgentProxy.obj \\r
+  $O\UpdateCallbackAgent.obj \\r
+\r
+C_OBJS = \\r
+  $O\Alloc.obj \\r
+  $O\CpuArch.obj \\r
+  $O\Sort.obj \\r
+  $O\Threads.obj \\r
+\r
+!include "../../Crc.mak"\r
+\r
+OBJS = \\r
+  $O\StdAfx.obj \\r
+  $(FAR_OBJS) \\r
+  $(COMMON_OBJS) \\r
+  $(WIN_OBJS) \\r
+  $(7ZIP_COMMON_OBJS) \\r
+  $(UI_COMMON_OBJS) \\r
+  $(AR_COMMON_OBJS) \\r
+  $(AGENT_OBJS) \\r
+  $O\CopyCoder.obj \\r
+  $(C_OBJS) \\r
+  $(ASM_OBJS) \\r
+  $O\resource.res\r
+\r
+!include "../../../Build.mak"\r
+\r
+$(FAR_OBJS): $(*B).cpp\r
+       $(COMPL)\r
+$(COMMON_OBJS): ../../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_OBJS): ../../../Windows/$(*B).cpp\r
+       $(COMPL)\r
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(UI_COMMON_OBJS): ../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp\r
+       $(COMPL)\r
+$(AGENT_OBJS): ../Agent/$(*B).cpp\r
+       $(COMPL)\r
+$O\CopyCoder.obj: ../../Compress/$(*B).cpp\r
+       $(COMPL)\r
+$(C_OBJS): ../../../../C/$(*B).c\r
+       $(COMPL_O2)\r
+!include "../../Asm.mak"\r
diff --git a/CPP/7zip/UI/Far/resource.rc b/CPP/7zip/UI/Far/resource.rc
new file mode 100755 (executable)
index 0000000..7d04d2d
--- /dev/null
@@ -0,0 +1,3 @@
+#include "../../MyVersionInfo.rc"\r
+\r
+MY_VERSION_INFO_DLL("7-Zip Plugin for FAR Manager", "7-ZipFar")\r
diff --git a/CPP/7zip/UI/FileManager/7zFM.exe.manifest b/CPP/7zip/UI/FileManager/7zFM.exe.manifest
new file mode 100755 (executable)
index 0000000..75af2e1
--- /dev/null
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="7-Zip.7-Zip.7zFM" type="win32"/><description>7-Zip File manager.</description><dependency> <dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/></dependentAssembly></dependency></assembly>\r
diff --git a/CPP/7zip/UI/FileManager/7zipLogo.ico b/CPP/7zip/UI/FileManager/7zipLogo.ico
new file mode 100755 (executable)
index 0000000..973241c
Binary files /dev/null and b/CPP/7zip/UI/FileManager/7zipLogo.ico differ
diff --git a/CPP/7zip/UI/FileManager/AboutDialog.cpp b/CPP/7zip/UI/FileManager/AboutDialog.cpp
new file mode 100755 (executable)
index 0000000..2c58a0d
--- /dev/null
@@ -0,0 +1,64 @@
+// AboutDialog.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "AboutDialog.h"\r
+#include "HelpUtils.h"\r
+#include "LangUtils.h"\r
+\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDC_ABOUT_STATIC_REGISTER_INFO, 0x01000103 },\r
+  { IDC_ABOUT_BUTTON_SUPPORT, 0x01000104 },\r
+  { IDC_ABOUT_BUTTON_REGISTER, 0x01000105 },\r
+  { IDOK, 0x02000702 }\r
+};\r
+\r
+#define MY_HOME_PAGE TEXT("http://www.7-zip.org/")\r
+\r
+static LPCTSTR kHomePageURL     = MY_HOME_PAGE;\r
+/*\r
+static LPCTSTR kRegisterPageURL = MY_HOME_PAGE TEXT("register.html");\r
+static LPCTSTR kSupportPageURL  = MY_HOME_PAGE TEXT("support.html");\r
+*/\r
+static LPCWSTR kHelpTopic = L"start.htm";\r
+\r
+bool CAboutDialog::OnInit()\r
+{\r
+  LangSetWindowText(HWND(*this), 0x01000100);\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+  NormalizePosition();\r
+  return CModalDialog::OnInit();\r
+}\r
+\r
+void CAboutDialog::OnHelp()\r
+{\r
+  ShowHelpWindow(NULL, kHelpTopic);\r
+}\r
+\r
+bool CAboutDialog::OnButtonClicked(int buttonID, HWND buttonHWND)\r
+{\r
+  LPCTSTR url;\r
+  switch(buttonID)\r
+  {\r
+    case IDC_ABOUT_BUTTON_HOMEPAGE: url = kHomePageURL; break;\r
+    /*\r
+    case IDC_ABOUT_BUTTON_REGISTER: url = kRegisterPageURL; break;\r
+    case IDC_ABOUT_BUTTON_SUPPORT: url = kSupportPageURL; break;\r
+    */\r
+    default:\r
+      return CModalDialog::OnButtonClicked(buttonID, buttonHWND);\r
+  }\r
+\r
+  #ifdef UNDER_CE\r
+  SHELLEXECUTEINFO s;\r
+  memset(&s, 0, sizeof(s));\r
+  s.cbSize = sizeof(s);\r
+  s.lpFile = url;\r
+  ::ShellExecuteEx(&s);\r
+  #else\r
+  ::ShellExecute(NULL, NULL, url, NULL, NULL, SW_SHOWNORMAL);\r
+  #endif\r
+\r
+  return true;\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/AboutDialog.h b/CPP/7zip/UI/FileManager/AboutDialog.h
new file mode 100755 (executable)
index 0000000..4abd82b
--- /dev/null
@@ -0,0 +1,18 @@
+// AboutDialog.h\r
\r
+#ifndef __ABOUTDIALOG_H\r
+#define __ABOUTDIALOG_H\r
+\r
+#include "AboutDialogRes.h"\r
+#include "Windows/Control/Dialog.h"\r
+\r
+class CAboutDialog: public NWindows::NControl::CModalDialog\r
+{\r
+public:\r
+  virtual bool OnInit();\r
+  virtual void OnHelp();\r
+  virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);\r
+  INT_PTR Create(HWND wndParent = 0) { return CModalDialog::Create(IDD_ABOUT, wndParent); }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/AboutDialog.rc b/CPP/7zip/UI/FileManager/AboutDialog.rc
new file mode 100755 (executable)
index 0000000..f35ade2
--- /dev/null
@@ -0,0 +1,26 @@
+#include "AboutDialogRes.h"\r
+#include "../../GuiCommon.rc"\r
+#include "../../MyVersion.h"\r
+\r
+#define xc 144\r
+#define yc 144\r
+\r
+#define y 80\r
+\r
+IDI_LOGO ICON "../../UI/FileManager/7zipLogo.ico"\r
+\r
+#ifndef SS_REALSIZEIMAGE\r
+#define SS_REALSIZEIMAGE 0x800\r
+#endif\r
+\r
+IDD_ABOUT MY_DIALOG\r
+CAPTION "About 7-Zip"\r
+{\r
+  DEFPUSHBUTTON  "OK", IDOK, bx1, by, bxs, bys\r
+  PUSHBUTTON  "www.7-zip.org", IDC_ABOUT_BUTTON_HOMEPAGE, bx2, by, bxs, bys\r
+  ICON   IDI_LOGO, -1, m, m, 32, 32, SS_REALSIZEIMAGE\r
+  LTEXT  MY_7ZIP_VERSION, -1, m, 54, xc, 8\r
+  LTEXT  MY_COPYRIGHT, -1, m, 67, xc, 8\r
+  LTEXT  "7-Zip is free software",\r
+         IDC_ABOUT_STATIC_REGISTER_INFO, m, y, xc, (by - y - 1)\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/AboutDialogRes.h b/CPP/7zip/UI/FileManager/AboutDialogRes.h
new file mode 100755 (executable)
index 0000000..3341d72
--- /dev/null
@@ -0,0 +1,6 @@
+#define IDD_ABOUT                       507\r
+#define IDI_LOGO                        138\r
+#define IDC_ABOUT_STATIC_REGISTER_INFO  1010\r
+#define IDC_ABOUT_BUTTON_HOMEPAGE       1020\r
+#define IDC_ABOUT_BUTTON_SUPPORT        1021\r
+#define IDC_ABOUT_BUTTON_REGISTER       1022\r
diff --git a/CPP/7zip/UI/FileManager/Add.bmp b/CPP/7zip/UI/FileManager/Add.bmp
new file mode 100755 (executable)
index 0000000..a8577fc
Binary files /dev/null and b/CPP/7zip/UI/FileManager/Add.bmp differ
diff --git a/CPP/7zip/UI/FileManager/Add2.bmp b/CPP/7zip/UI/FileManager/Add2.bmp
new file mode 100755 (executable)
index 0000000..252fc25
Binary files /dev/null and b/CPP/7zip/UI/FileManager/Add2.bmp differ
diff --git a/CPP/7zip/UI/FileManager/App.cpp b/CPP/7zip/UI/FileManager/App.cpp
new file mode 100755 (executable)
index 0000000..fb16e17
--- /dev/null
@@ -0,0 +1,827 @@
+// App.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "resource.h"\r
+#include "OverwriteDialogRes.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/COM.h"\r
+#include "Windows/Error.h"\r
+#include "Windows/FileDir.h"\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/PropVariantConversions.h"\r
+#include "Windows/Thread.h"\r
+\r
+#include "App.h"\r
+#include "CopyDialog.h"\r
+#include "ExtractCallback.h"\r
+#include "FormatUtils.h"\r
+#include "IFolder.h"\r
+#include "LangUtils.h"\r
+#include "RegistryUtils.h"\r
+#include "ViewSettings.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+using namespace NFind;\r
+\r
+extern DWORD g_ComCtl32Version;\r
+extern HINSTANCE g_hInstance;\r
+\r
+static LPCWSTR kTempDirPrefix = L"7zE";\r
+\r
+void CPanelCallbackImp::OnTab()\r
+{\r
+  if (g_App.NumPanels != 1)\r
+    _app->Panels[1 - _index].SetFocusToList();\r
+  _app->RefreshTitle();\r
+}\r
+\r
+void CPanelCallbackImp::SetFocusToPath(int index)\r
+{\r
+  int newPanelIndex = index;\r
+  if (g_App.NumPanels == 1)\r
+    newPanelIndex = g_App.LastFocusedPanel;\r
+  _app->RefreshTitle();\r
+  _app->Panels[newPanelIndex]._headerComboBox.SetFocus();\r
+  _app->Panels[newPanelIndex]._headerComboBox.ShowDropDown();\r
+}\r
+\r
+\r
+void CPanelCallbackImp::OnCopy(bool move, bool copyToSame) { _app->OnCopy(move, copyToSame, _index); }\r
+void CPanelCallbackImp::OnSetSameFolder() { _app->OnSetSameFolder(_index); }\r
+void CPanelCallbackImp::OnSetSubFolder()  { _app->OnSetSubFolder(_index); }\r
+void CPanelCallbackImp::PanelWasFocused() { _app->SetFocusedPanel(_index); _app->RefreshTitle(_index); }\r
+void CPanelCallbackImp::DragBegin() { _app->DragBegin(_index); }\r
+void CPanelCallbackImp::DragEnd() { _app->DragEnd(); }\r
+void CPanelCallbackImp::RefreshTitle(bool always) { _app->RefreshTitle(_index, always); }\r
+\r
+void CApp::SetListSettings()\r
+{\r
+  bool showDots = ReadShowDots();\r
+  bool showRealFileIcons = ReadShowRealFileIcons();\r
+\r
+  DWORD extendedStyle = LVS_EX_HEADERDRAGDROP;\r
+  if (ReadFullRow())\r
+    extendedStyle |= LVS_EX_FULLROWSELECT;\r
+  if (ReadShowGrid())\r
+    extendedStyle |= LVS_EX_GRIDLINES;\r
+  bool mySelectionMode = ReadAlternativeSelection();\r
+  \r
+  if (ReadSingleClick())\r
+  {\r
+    extendedStyle |= LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT;\r
+    /*\r
+    if (ReadUnderline())\r
+      extendedStyle |= LVS_EX_UNDERLINEHOT;\r
+    */\r
+  }\r
+\r
+  for (int i = 0; i < kNumPanelsMax; i++)\r
+  {\r
+    CPanel &panel = Panels[i];\r
+    panel._mySelectMode = mySelectionMode;\r
+    panel._showDots = showDots;\r
+    panel._showRealFileIcons = showRealFileIcons;\r
+    panel._exStyle = extendedStyle;\r
+\r
+    DWORD style = (DWORD)panel._listView.GetStyle();\r
+    if (mySelectionMode)\r
+      style |= LVS_SINGLESEL;\r
+    else\r
+      style &= ~LVS_SINGLESEL;\r
+    panel._listView.SetStyle(style);\r
+    panel.SetExtendedStyle();\r
+  }\r
+}\r
+\r
+void CApp::SetShowSystemMenu()\r
+{\r
+  ShowSystemMenu = ReadShowSystemMenu();\r
+}\r
+\r
+#ifndef ILC_COLOR32\r
+#define ILC_COLOR32 0x0020\r
+#endif\r
+\r
+HRESULT CApp::CreateOnePanel(int panelIndex, const UString &mainPath, const UString &arcFormat,\r
+  bool &archiveIsOpened, bool &encrypted)\r
+{\r
+  if (PanelsCreated[panelIndex])\r
+    return S_OK;\r
+  m_PanelCallbackImp[panelIndex].Init(this, panelIndex);\r
+  UString path;\r
+  if (mainPath.IsEmpty())\r
+  {\r
+    if (!::ReadPanelPath(panelIndex, path))\r
+      path.Empty();\r
+  }\r
+  else\r
+    path = mainPath;\r
+  int id = 1000 + 100 * panelIndex;\r
+  RINOK(Panels[panelIndex].Create(_window, _window,\r
+      id, path, arcFormat, &m_PanelCallbackImp[panelIndex], &AppState, archiveIsOpened, encrypted));\r
+  PanelsCreated[panelIndex] = true;\r
+  return S_OK;\r
+}\r
+\r
+static void CreateToolbar(HWND parent,\r
+    NWindows::NControl::CImageList &imageList,\r
+    NWindows::NControl::CToolBar &toolBar,\r
+    bool largeButtons)\r
+{\r
+  toolBar.Attach(::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, 0\r
+      | WS_CHILD\r
+      | WS_VISIBLE\r
+      | TBSTYLE_FLAT\r
+      | TBSTYLE_TOOLTIPS\r
+      | TBSTYLE_WRAPABLE\r
+      // | TBSTYLE_AUTOSIZE\r
+      // | CCS_NORESIZE\r
+      #ifdef UNDER_CE\r
+      | CCS_NODIVIDER\r
+      | CCS_NOPARENTALIGN\r
+      #endif\r
+      ,0,0,0,0, parent, NULL, g_hInstance, NULL));\r
+\r
+  // TB_BUTTONSTRUCTSIZE message, which is required for\r
+  // backward compatibility.\r
+  toolBar.ButtonStructSize();\r
+\r
+  imageList.Create(\r
+      largeButtons ? 48: 24,\r
+      largeButtons ? 36: 24,\r
+      ILC_MASK | ILC_COLOR32, 0, 0);\r
+  toolBar.SetImageList(0, imageList);\r
+}\r
+\r
+struct CButtonInfo\r
+{\r
+  int CommandID;\r
+  UINT BitmapResID;\r
+  UINT Bitmap2ResID;\r
+  UINT StringResID;\r
+  UInt32 LangID;\r
+  UString GetText() const { return LangString(StringResID, LangID); }\r
+};\r
+\r
+static CButtonInfo g_StandardButtons[] =\r
+{\r
+  { IDM_COPY_TO, IDB_COPY, IDB_COPY2, IDS_BUTTON_COPY, 0x03020420},\r
+  { IDM_MOVE_TO, IDB_MOVE, IDB_MOVE2, IDS_BUTTON_MOVE, 0x03020421},\r
+  { IDM_DELETE, IDB_DELETE, IDB_DELETE2, IDS_BUTTON_DELETE, 0x03020422} ,\r
+  { IDM_FILE_PROPERTIES, IDB_INFO, IDB_INFO2, IDS_BUTTON_INFO, 0x03020423}\r
+};\r
+\r
+static CButtonInfo g_ArchiveButtons[] =\r
+{\r
+  { kAddCommand, IDB_ADD, IDB_ADD2, IDS_ADD, 0x03020400},\r
+  { kExtractCommand, IDB_EXTRACT, IDB_EXTRACT2, IDS_EXTRACT, 0x03020401},\r
+  { kTestCommand , IDB_TEST, IDB_TEST2, IDS_TEST, 0x03020402}\r
+};\r
+\r
+static bool SetButtonText(int commandID, CButtonInfo *buttons, int numButtons, UString &s)\r
+{\r
+  for (int i = 0; i < numButtons; i++)\r
+  {\r
+    const CButtonInfo &b = buttons[i];\r
+    if (b.CommandID == commandID)\r
+    {\r
+      s = b.GetText();\r
+      return true;\r
+    }\r
+  }\r
+  return false;\r
+}\r
+\r
+static void SetButtonText(int commandID, UString &s)\r
+{\r
+  if (SetButtonText(commandID, g_StandardButtons,\r
+      sizeof(g_StandardButtons) / sizeof(g_StandardButtons[0]), s))\r
+    return;\r
+  SetButtonText(commandID, g_ArchiveButtons,\r
+      sizeof(g_ArchiveButtons) / sizeof(g_ArchiveButtons[0]), s);\r
+}\r
+\r
+static void AddButton(\r
+    NControl::CImageList &imageList,\r
+    NControl::CToolBar &toolBar,\r
+    CButtonInfo &butInfo, bool showText, bool large)\r
+{\r
+  TBBUTTON but;\r
+  but.iBitmap = 0;\r
+  but.idCommand = butInfo.CommandID;\r
+  but.fsState = TBSTATE_ENABLED;\r
+  but.fsStyle = TBSTYLE_BUTTON;\r
+  but.dwData = 0;\r
+\r
+  UString s = butInfo.GetText();\r
+  but.iString = 0;\r
+  if (showText)\r
+    but.iString = (INT_PTR)(LPCWSTR)s;\r
+\r
+  but.iBitmap = imageList.GetImageCount();\r
+  HBITMAP b = ::LoadBitmap(g_hInstance,\r
+      large ?\r
+      MAKEINTRESOURCE(butInfo.BitmapResID):\r
+      MAKEINTRESOURCE(butInfo.Bitmap2ResID));\r
+  if (b != 0)\r
+  {\r
+    imageList.AddMasked(b, RGB(255, 0, 255));\r
+    ::DeleteObject(b);\r
+  }\r
+  #ifdef _UNICODE\r
+  toolBar.AddButton(1, &but);\r
+  #else\r
+  toolBar.AddButtonW(1, &but);\r
+  #endif\r
+}\r
+\r
+void CApp::ReloadToolbars()\r
+{\r
+  _buttonsImageList.Destroy();\r
+  _toolBar.Destroy();\r
+\r
+\r
+  if (ShowArchiveToolbar || ShowStandardToolbar)\r
+  {\r
+    CreateToolbar(_window, _buttonsImageList, _toolBar, LargeButtons);\r
+    int i;\r
+    if (ShowArchiveToolbar)\r
+      for (i = 0; i < sizeof(g_ArchiveButtons) / sizeof(g_ArchiveButtons[0]); i++)\r
+        AddButton(_buttonsImageList, _toolBar, g_ArchiveButtons[i], ShowButtonsLables, LargeButtons);\r
+    if (ShowStandardToolbar)\r
+      for (i = 0; i < sizeof(g_StandardButtons) / sizeof(g_StandardButtons[0]); i++)\r
+        AddButton(_buttonsImageList, _toolBar, g_StandardButtons[i], ShowButtonsLables, LargeButtons);\r
+\r
+    _toolBar.AutoSize();\r
+  }\r
+}\r
+\r
+void CApp::SaveToolbarChanges()\r
+{\r
+  SaveToolbar();\r
+  ReloadToolbars();\r
+  MoveSubWindows();\r
+}\r
+\r
+void MyLoadMenu();\r
+\r
+HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool &archiveIsOpened, bool &encrypted)\r
+{\r
+  _window.Attach(hwnd);\r
+  #ifdef UNDER_CE\r
+  _commandBar.Create(g_hInstance, hwnd, 1);\r
+  #endif\r
+  MyLoadMenu();\r
+  #ifdef UNDER_CE\r
+  _commandBar.AutoSize();\r
+  #endif\r
+\r
+  ReadToolbar();\r
+  ReloadToolbars();\r
+\r
+  int i;\r
+  for (i = 0; i < kNumPanelsMax; i++)\r
+    PanelsCreated[i] = false;\r
+\r
+  AppState.Read();\r
+  SetListSettings();\r
+  SetShowSystemMenu();\r
+  if (LastFocusedPanel >= kNumPanelsMax)\r
+    LastFocusedPanel = 0;\r
+\r
+  CListMode listMode;\r
+  ReadListMode(listMode);\r
+  for (i = 0; i < kNumPanelsMax; i++)\r
+  {\r
+    CPanel &panel = Panels[i];\r
+    panel._ListViewMode = listMode.Panels[i];\r
+    panel._xSize = xSizes[i];\r
+    panel._flatModeForArc = ReadFlatView(i);\r
+  }\r
+  for (i = 0; i < kNumPanelsMax; i++)\r
+    if (NumPanels > 1 || i == LastFocusedPanel)\r
+    {\r
+      if (NumPanels == 1)\r
+        Panels[i]._xSize = xSizes[0] + xSizes[1];\r
+      bool archiveIsOpened2 = false;\r
+      bool encrypted2 = false;\r
+      bool mainPanel = (i == LastFocusedPanel);\r
+      RINOK(CreateOnePanel(i, mainPanel ? mainPath : L"", arcFormat, archiveIsOpened2, encrypted2));\r
+      if (mainPanel)\r
+      {\r
+        archiveIsOpened = archiveIsOpened2;\r
+        encrypted = encrypted2;\r
+      }\r
+    }\r
+  SetFocusedPanel(LastFocusedPanel);\r
+  Panels[LastFocusedPanel].SetFocusToList();\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CApp::SwitchOnOffOnePanel()\r
+{\r
+  if (NumPanels == 1)\r
+  {\r
+    NumPanels++;\r
+    bool archiveIsOpened, encrypted;\r
+    RINOK(CreateOnePanel(1 - LastFocusedPanel, UString(), UString(), archiveIsOpened, encrypted));\r
+    Panels[1 - LastFocusedPanel].Enable(true);\r
+    Panels[1 - LastFocusedPanel].Show(SW_SHOWNORMAL);\r
+  }\r
+  else\r
+  {\r
+    NumPanels--;\r
+    Panels[1 - LastFocusedPanel].Enable(false);\r
+    Panels[1 - LastFocusedPanel].Show(SW_HIDE);\r
+  }\r
+  MoveSubWindows();\r
+  return S_OK;\r
+}\r
+\r
+void CApp::Save()\r
+{\r
+  AppState.Save();\r
+  CListMode listMode;\r
+  for (int i = 0; i < kNumPanelsMax; i++)\r
+  {\r
+    const CPanel &panel = Panels[i];\r
+    UString path;\r
+    if (panel._parentFolders.IsEmpty())\r
+      path = panel._currentFolderPrefix;\r
+    else\r
+      path = GetFolderPath(panel._parentFolders[0].ParentFolder);\r
+    SavePanelPath(i, path);\r
+    listMode.Panels[i] = panel.GetListViewMode();\r
+    SaveFlatView(i, panel._flatModeForArc);\r
+  }\r
+  SaveListMode(listMode);\r
+}\r
+\r
+void CApp::Release()\r
+{\r
+  // It's for unloading COM dll's: don't change it.\r
+  for (int i = 0; i < kNumPanelsMax; i++)\r
+    Panels[i].Release();\r
+}\r
+\r
+// reduces path to part that exists on disk\r
+static void ReducePathToRealFileSystemPath(UString &path)\r
+{\r
+  while (!path.IsEmpty())\r
+  {\r
+    if (NFind::DoesDirExist(path))\r
+    {\r
+      NName::NormalizeDirPathPrefix(path);\r
+      break;\r
+    }\r
+    int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+    if (pos < 0)\r
+      path.Empty();\r
+    else\r
+    {\r
+      path = path.Left(pos + 1);\r
+      if (path.Length() == 3 && path[1] == L':')\r
+        break;\r
+      if (path.Length() > 2 && path[0] == '\\' && path[1] == '\\')\r
+      {\r
+        int nextPos = path.Find(WCHAR_PATH_SEPARATOR, 2); // pos after \\COMPNAME\r
+        if (nextPos > 0 && path.Find(WCHAR_PATH_SEPARATOR, nextPos + 1) == pos)\r
+          break;\r
+      }\r
+      path = path.Left(pos);\r
+    }\r
+  }\r
+}\r
+\r
+// return true for dir\, if dir exist\r
+static bool CheckFolderPath(const UString &path)\r
+{\r
+  UString pathReduced = path;\r
+  ReducePathToRealFileSystemPath(pathReduced);\r
+  return (pathReduced == path);\r
+}\r
+\r
+static bool IsPathAbsolute(const UString &path)\r
+{\r
+  if (path.Length() >= 1 && path[0] == WCHAR_PATH_SEPARATOR)\r
+    return true;\r
+  #ifdef _WIN32\r
+  if (path.Length() >= 3 && path[1] == L':' && path[2] == L'\\')\r
+    return true;\r
+  #endif\r
+  return false;\r
+}\r
+\r
+extern UString ConvertSizeToString(UInt64 value);\r
+\r
+static UString AddSizeValue(UInt64 size)\r
+{\r
+  return MyFormatNew(IDS_FILE_SIZE, 0x02000982, ConvertSizeToString(size));\r
+}\r
+\r
+static void AddValuePair1(UINT resourceID, UInt32 langID, UInt64 size, UString &s)\r
+{\r
+  s += LangString(resourceID, langID);\r
+  s += L" ";\r
+  s += AddSizeValue(size);\r
+  s += L"\n";\r
+}\r
+\r
+void AddValuePair2(UINT resourceID, UInt32 langID, UInt64 num, UInt64 size, UString &s)\r
+{\r
+  if (num == 0)\r
+    return;\r
+  s += LangString(resourceID, langID);\r
+  s += L" ";\r
+  s += ConvertSizeToString(num);\r
+\r
+  if (size != (UInt64)(Int64)-1)\r
+  {\r
+    s += L"    ( ";\r
+    s += AddSizeValue(size);\r
+    s += L" )";\r
+  }\r
+  s += L"\n";\r
+}\r
+\r
+static void AddPropValueToSum(IFolderFolder *folder, int index, PROPID propID, UInt64 &sum)\r
+{\r
+  if (sum == (UInt64)(Int64)-1)\r
+    return;\r
+  NCOM::CPropVariant prop;\r
+  folder->GetProperty(index, propID, &prop);\r
+  switch(prop.vt)\r
+  {\r
+    case VT_UI4:\r
+    case VT_UI8:\r
+      sum += ConvertPropVariantToUInt64(prop);\r
+      break;\r
+    default:\r
+      sum = (UInt64)(Int64)-1;\r
+  }\r
+}\r
+\r
+UString CPanel::GetItemsInfoString(const CRecordVector<UInt32> &indices)\r
+{\r
+  UString info;\r
+  UInt64 numDirs, numFiles, filesSize, foldersSize;\r
+  numDirs = numFiles = filesSize = foldersSize = 0;\r
+  int i;\r
+  for (i = 0; i < indices.Size(); i++)\r
+  {\r
+    int index = indices[i];\r
+    if (IsItemFolder(index))\r
+    {\r
+      AddPropValueToSum(_folder, index, kpidSize, foldersSize);\r
+      numDirs++;\r
+    }\r
+    else\r
+    {\r
+      AddPropValueToSum(_folder, index, kpidSize, filesSize);\r
+      numFiles++;\r
+    }\r
+  }\r
+\r
+  AddValuePair2(IDS_FOLDERS_COLON, 0x02000321, numDirs, foldersSize, info);\r
+  AddValuePair2(IDS_FILES_COLON, 0x02000320, numFiles, filesSize, info);\r
+  int numDefined = ((foldersSize != (UInt64)(Int64)-1) && foldersSize != 0) ? 1: 0;\r
+  numDefined += ((filesSize != (UInt64)(Int64)-1) && filesSize != 0) ? 1: 0;\r
+  if (numDefined == 2)\r
+    AddValuePair1(IDS_SIZE_COLON, 0x02000322, filesSize + foldersSize, info);\r
+  \r
+  info += L"\n";\r
+  info += _currentFolderPrefix;\r
+  \r
+  for (i = 0; i < indices.Size() && i < kCopyDialog_NumInfoLines - 6; i++)\r
+  {\r
+    info += L"\n  ";\r
+    int index = indices[i];\r
+    info += GetItemRelPath(index);\r
+    if (IsItemFolder(index))\r
+      info += WCHAR_PATH_SEPARATOR;\r
+  }\r
+  if (i != indices.Size())\r
+    info += L"\n  ...";\r
+  return info;\r
+}\r
+\r
+void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)\r
+{\r
+  int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);\r
+  CPanel &srcPanel = Panels[srcPanelIndex];\r
+  CPanel &destPanel = Panels[destPanelIndex];\r
+\r
+  CPanel::CDisableTimerProcessing disableTimerProcessing1(destPanel);\r
+  CPanel::CDisableTimerProcessing disableTimerProcessing2(srcPanel);\r
+\r
+  if (!srcPanel.DoesItSupportOperations())\r
+  {\r
+    srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);\r
+    return;\r
+  }\r
+\r
+  CRecordVector<UInt32> indices;\r
+  UString destPath;\r
+  bool useDestPanel = false;\r
+\r
+  {\r
+    if (copyToSame)\r
+    {\r
+      int focusedItem = srcPanel._listView.GetFocusedItem();\r
+      if (focusedItem < 0)\r
+        return;\r
+      int realIndex = srcPanel.GetRealItemIndex(focusedItem);\r
+      if (realIndex == kParentIndex)\r
+        return;\r
+      indices.Add(realIndex);\r
+      destPath = srcPanel.GetItemName(realIndex);\r
+    }\r
+    else\r
+    {\r
+      srcPanel.GetOperatedIndicesSmart(indices);\r
+      if (indices.Size() == 0)\r
+        return;\r
+      destPath = destPanel._currentFolderPrefix;\r
+      if (NumPanels == 1)\r
+        ReducePathToRealFileSystemPath(destPath);\r
+    }\r
+\r
+    CCopyDialog copyDialog;\r
+    UStringVector copyFolders;\r
+    ReadCopyHistory(copyFolders);\r
+\r
+    copyDialog.Strings = copyFolders;\r
+    copyDialog.Value = destPath;\r
+    \r
+    copyDialog.Title = move ?\r
+        LangString(IDS_MOVE, 0x03020202):\r
+        LangString(IDS_COPY, 0x03020201);\r
+    copyDialog.Static = move ?\r
+        LangString(IDS_MOVE_TO, 0x03020204):\r
+        LangString(IDS_COPY_TO, 0x03020203);\r
+\r
+    copyDialog.Info = srcPanel.GetItemsInfoString(indices);\r
+\r
+    if (copyDialog.Create(srcPanel.GetParent()) == IDCANCEL)\r
+      return;\r
+\r
+    destPath = copyDialog.Value;\r
+\r
+    if (destPath.IsEmpty())\r
+    {\r
+      srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);\r
+      return;\r
+    }\r
+\r
+    if (!IsPathAbsolute(destPath))\r
+    {\r
+      if (!srcPanel.IsFSFolder())\r
+      {\r
+        srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);\r
+        return;\r
+      }\r
+      destPath = srcPanel._currentFolderPrefix + destPath;\r
+    }\r
+\r
+    #ifndef UNDER_CE\r
+    if (destPath.Length() > 0 && destPath[0] == '\\')\r
+      if (destPath.Length() == 1 || destPath[1] != '\\')\r
+      {\r
+        srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);\r
+        return;\r
+      }\r
+    #endif\r
+\r
+    if (indices.Size() > 1 ||\r
+        (!destPath.IsEmpty() && destPath.Back() == WCHAR_PATH_SEPARATOR) ||\r
+        NFind::DoesDirExist(destPath) ||\r
+        srcPanel.IsArcFolder())\r
+    {\r
+      NDirectory::CreateComplexDirectory(destPath);\r
+      NName::NormalizeDirPathPrefix(destPath);\r
+      if (!CheckFolderPath(destPath))\r
+      {\r
+        if (NumPanels < 2 || destPath != destPanel._currentFolderPrefix || !destPanel.DoesItSupportOperations())\r
+        {\r
+          srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);\r
+          return;\r
+        }\r
+        useDestPanel = true;\r
+      }\r
+    }\r
+    else\r
+    {\r
+      int pos = destPath.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+      if (pos >= 0)\r
+      {\r
+        UString prefix = destPath.Left(pos + 1);\r
+        NDirectory::CreateComplexDirectory(prefix);\r
+        if (!CheckFolderPath(prefix))\r
+        {\r
+          srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);\r
+          return;\r
+        }\r
+      }\r
+    }\r
+\r
+    AddUniqueStringToHeadOfList(copyFolders, destPath);\r
+    while (copyFolders.Size() > 20)\r
+      copyFolders.DeleteBack();\r
+    SaveCopyHistory(copyFolders);\r
+  }\r
+\r
+  /*\r
+  if (destPath == destPanel._currentFolderPrefix)\r
+  {\r
+    if (destPanel.GetFolderTypeID() == L"PhysDrive")\r
+      useDestPanel = true;\r
+  }\r
+  */\r
+\r
+  bool useSrcPanel = (!useDestPanel || !srcPanel.IsFsOrDrivesFolder() || destPanel.IsFSFolder());\r
+  bool useTemp = useSrcPanel && useDestPanel;\r
+  NFile::NDirectory::CTempDirectoryW tempDirectory;\r
+  UString tempDirPrefix;\r
+  if (useTemp)\r
+  {\r
+    tempDirectory.Create(kTempDirPrefix);\r
+    tempDirPrefix = tempDirectory.GetPath();\r
+    NFile::NName::NormalizeDirPathPrefix(tempDirPrefix);\r
+  }\r
+\r
+  CSelectedState srcSelState;\r
+  CSelectedState destSelState;\r
+  srcPanel.SaveSelectedState(srcSelState);\r
+  destPanel.SaveSelectedState(destSelState);\r
+\r
+  HRESULT result;\r
+  if (useSrcPanel)\r
+  {\r
+    UString folder = useTemp ? tempDirPrefix : destPath;\r
+    result = srcPanel.CopyTo(indices, folder, move, true, 0);\r
+    if (result != S_OK)\r
+    {\r
+      disableTimerProcessing1.Restore();\r
+      disableTimerProcessing2.Restore();\r
+      // For Password:\r
+      srcPanel.SetFocusToList();\r
+      if (result != E_ABORT)\r
+        srcPanel.MessageBoxError(result, L"Error");\r
+      return;\r
+    }\r
+  }\r
+  \r
+  if (useDestPanel)\r
+  {\r
+    UStringVector filePaths;\r
+    UString folderPrefix;\r
+    if (useTemp)\r
+      folderPrefix = tempDirPrefix;\r
+    else\r
+      folderPrefix = srcPanel._currentFolderPrefix;\r
+    filePaths.Reserve(indices.Size());\r
+    for (int i = 0; i < indices.Size(); i++)\r
+      filePaths.Add(srcPanel.GetItemRelPath(indices[i]));\r
+\r
+    result = destPanel.CopyFrom(folderPrefix, filePaths, true, 0);\r
+\r
+    if (result != S_OK)\r
+    {\r
+      disableTimerProcessing1.Restore();\r
+      disableTimerProcessing2.Restore();\r
+      // For Password:\r
+      srcPanel.SetFocusToList();\r
+      if (result != E_ABORT)\r
+        srcPanel.MessageBoxError(result, L"Error");\r
+      return;\r
+    }\r
+  }\r
+\r
+  RefreshTitleAlways();\r
+  if (copyToSame || move)\r
+  {\r
+    srcPanel.RefreshListCtrl(srcSelState);\r
+  }\r
+  if (!copyToSame)\r
+  {\r
+    destPanel.RefreshListCtrl(destSelState);\r
+    srcPanel.KillSelection();\r
+  }\r
+  disableTimerProcessing1.Restore();\r
+  disableTimerProcessing2.Restore();\r
+  srcPanel.SetFocusToList();\r
+}\r
+\r
+void CApp::OnSetSameFolder(int srcPanelIndex)\r
+{\r
+  if (NumPanels <= 1)\r
+    return;\r
+  const CPanel &srcPanel = Panels[srcPanelIndex];\r
+  CPanel &destPanel = Panels[1 - srcPanelIndex];\r
+  destPanel.BindToPathAndRefresh(srcPanel._currentFolderPrefix);\r
+}\r
+\r
+void CApp::OnSetSubFolder(int srcPanelIndex)\r
+{\r
+  if (NumPanels <= 1)\r
+    return;\r
+  const CPanel &srcPanel = Panels[srcPanelIndex];\r
+  CPanel &destPanel = Panels[1 - srcPanelIndex];\r
+\r
+  int focusedItem = srcPanel._listView.GetFocusedItem();\r
+  if (focusedItem < 0)\r
+    return;\r
+  int realIndex = srcPanel.GetRealItemIndex(focusedItem);\r
+  if (!srcPanel.IsItemFolder(realIndex))\r
+    return;\r
+\r
+  // destPanel.BindToFolder(srcPanel._currentFolderPrefix + srcPanel.GetItemName(realIndex) + WCHAR_PATH_SEPARATOR);\r
+\r
+  CMyComPtr<IFolderFolder> newFolder;\r
+  if (realIndex == kParentIndex)\r
+  {\r
+    if (srcPanel._folder->BindToParentFolder(&newFolder) != S_OK)\r
+      return;\r
+  }\r
+  else\r
+  {\r
+    if (srcPanel._folder->BindToFolder(realIndex, &newFolder) != S_OK)\r
+      return;\r
+  }\r
+  destPanel.CloseOpenFolders();\r
+  destPanel._folder = newFolder;\r
+  destPanel.RefreshListCtrl();\r
+}\r
+\r
+/*\r
+int CApp::GetFocusedPanelIndex() const\r
+{\r
+  return LastFocusedPanel;\r
+  HWND hwnd = ::GetFocus();\r
+  for (;;)\r
+  {\r
+    if (hwnd == 0)\r
+      return 0;\r
+    for (int i = 0; i < kNumPanelsMax; i++)\r
+    {\r
+      if (PanelsCreated[i] &&\r
+          ((HWND)Panels[i] == hwnd || Panels[i]._listView == hwnd))\r
+        return i;\r
+    }\r
+    hwnd = GetParent(hwnd);\r
+  }\r
+}\r
+*/\r
+\r
+static UString g_ToolTipBuffer;\r
+static CSysString g_ToolTipBufferSys;\r
+\r
+void CApp::OnNotify(int /* ctrlID */, LPNMHDR pnmh)\r
+{\r
+  {\r
+    if (pnmh->code == TTN_GETDISPINFO)\r
+    {\r
+      LPNMTTDISPINFO info = (LPNMTTDISPINFO)pnmh;\r
+      info->hinst = 0;\r
+      g_ToolTipBuffer.Empty();\r
+      SetButtonText((int)info->hdr.idFrom, g_ToolTipBuffer);\r
+      g_ToolTipBufferSys = GetSystemString(g_ToolTipBuffer);\r
+      info->lpszText = (LPTSTR)(LPCTSTR)g_ToolTipBufferSys;\r
+      return;\r
+    }\r
+    #ifndef _UNICODE\r
+    if (pnmh->code == TTN_GETDISPINFOW)\r
+    {\r
+      LPNMTTDISPINFOW info = (LPNMTTDISPINFOW)pnmh;\r
+      info->hinst = 0;\r
+      g_ToolTipBuffer.Empty();\r
+      SetButtonText((int)info->hdr.idFrom, g_ToolTipBuffer);\r
+      info->lpszText = (LPWSTR)(LPCWSTR)g_ToolTipBuffer;\r
+      return;\r
+    }\r
+    #endif\r
+  }\r
+}\r
+\r
+void CApp::RefreshTitle(bool always)\r
+{\r
+  UString path = GetFocusedPanel()._currentFolderPrefix;\r
+  if (path.IsEmpty())\r
+    path += LangString(IDS_APP_TITLE, 0x03000000);\r
+  if (!always && path == PrevTitle)\r
+    return;\r
+  PrevTitle = path;\r
+  NWindows::MySetWindowText(_window, path);\r
+}\r
+\r
+void CApp::RefreshTitle(int panelIndex, bool always)\r
+{\r
+  if (panelIndex != GetFocusedPanelIndex())\r
+    return;\r
+  RefreshTitle(always);\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/App.h b/CPP/7zip/UI/FileManager/App.h
new file mode 100755 (executable)
index 0000000..335d6eb
--- /dev/null
@@ -0,0 +1,315 @@
+// App.h\r
+\r
+#ifndef __APP_H\r
+#define __APP_H\r
+\r
+#include "Windows/Control/CommandBar.h"\r
+#include "Windows/Control/ImageList.h"\r
+\r
+#include "AppState.h"\r
+#include "Panel.h"\r
+\r
+class CApp;\r
+\r
+extern CApp g_App;\r
+extern HWND g_HWND;\r
+\r
+const int kNumPanelsMax = 2;\r
+\r
+extern bool g_IsSmallScreen;\r
+\r
+enum\r
+{\r
+  kAddCommand = kToolbarStartID,\r
+  kExtractCommand,\r
+  kTestCommand\r
+};\r
+\r
+class CPanelCallbackImp: public CPanelCallback\r
+{\r
+  CApp *_app;\r
+  int _index;\r
+public:\r
+  void Init(CApp *app, int index)\r
+  {\r
+    _app = app;\r
+    _index = index;\r
+  }\r
+  virtual void OnTab();\r
+  virtual void SetFocusToPath(int index);\r
+  virtual void OnCopy(bool move, bool copyToSame);\r
+  virtual void OnSetSameFolder();\r
+  virtual void OnSetSubFolder();\r
+  virtual void PanelWasFocused();\r
+  virtual void DragBegin();\r
+  virtual void DragEnd();\r
+  virtual void RefreshTitle(bool always);\r
+};\r
+\r
+class CApp;\r
+\r
+class CDropTarget:\r
+  public IDropTarget,\r
+  public CMyUnknownImp\r
+{\r
+  CMyComPtr<IDataObject> m_DataObject;\r
+  UStringVector m_SourcePaths;\r
+  int m_SelectionIndex;\r
+  bool m_DropIsAllowed;      // = true, if data contain fillist\r
+  bool m_PanelDropIsAllowed; // = false, if current target_panel is source_panel.\r
+                             // check it only if m_DropIsAllowed == true\r
+  int m_SubFolderIndex;\r
+  UString m_SubFolderName;\r
+\r
+  CPanel *m_Panel;\r
+  bool m_IsAppTarget;        // true, if we want to drop to app window (not to panel).\r
+\r
+  bool m_SetPathIsOK;\r
+\r
+  bool IsItSameDrive() const;\r
+\r
+  void QueryGetData(IDataObject *dataObject);\r
+  bool IsFsFolderPath() const;\r
+  DWORD GetEffect(DWORD keyState, POINTL pt, DWORD allowedEffect);\r
+  void RemoveSelection();\r
+  void PositionCursor(POINTL ptl);\r
+  UString GetTargetPath() const;\r
+  bool SetPath(bool enablePath) const;\r
+  bool SetPath();\r
+\r
+public:\r
+  MY_UNKNOWN_IMP1_MT(IDropTarget)\r
+  STDMETHOD(DragEnter)(IDataObject * dataObject, DWORD keyState, POINTL pt, DWORD *effect);\r
+  STDMETHOD(DragOver)(DWORD keyState, POINTL pt, DWORD * effect);\r
+  STDMETHOD(DragLeave)();\r
+  STDMETHOD(Drop)(IDataObject * dataObject, DWORD keyState, POINTL pt, DWORD *effect);\r
+\r
+  CDropTarget():\r
+      TargetPanelIndex(-1),\r
+      SrcPanelIndex(-1),\r
+      m_IsAppTarget(false),\r
+      m_Panel(0),\r
+      App(0),\r
+      m_PanelDropIsAllowed(false),\r
+      m_DropIsAllowed(false),\r
+      m_SelectionIndex(-1),\r
+      m_SubFolderIndex(-1),\r
+      m_SetPathIsOK(false) {}\r
+\r
+  CApp *App;\r
+  int SrcPanelIndex;              // index of D&D source_panel\r
+  int TargetPanelIndex;           // what panel to use as target_panel of Application\r
+};\r
+\r
+class CApp\r
+{\r
+public:\r
+  NWindows::CWindow _window;\r
+  bool ShowSystemMenu;\r
+  int NumPanels;\r
+  int LastFocusedPanel;\r
+\r
+  bool ShowStandardToolbar;\r
+  bool ShowArchiveToolbar;\r
+  bool ShowButtonsLables;\r
+  bool LargeButtons;\r
+\r
+  CAppState AppState;\r
+  CPanelCallbackImp m_PanelCallbackImp[kNumPanelsMax];\r
+  CPanel Panels[kNumPanelsMax];\r
+  bool PanelsCreated[kNumPanelsMax];\r
+\r
+  NWindows::NControl::CImageList _buttonsImageList;\r
+\r
+  #ifdef UNDER_CE\r
+  NWindows::NControl::CCommandBar _commandBar;\r
+  #endif\r
+  NWindows::NControl::CToolBar _toolBar;\r
+\r
+  CDropTarget *_dropTargetSpec;\r
+  CMyComPtr<IDropTarget> _dropTarget;\r
+\r
+  CApp(): _window(0), NumPanels(2), LastFocusedPanel(0) {}\r
+\r
+  void CreateDragTarget()\r
+  {\r
+    _dropTargetSpec = new CDropTarget();\r
+    _dropTarget = _dropTargetSpec;\r
+    _dropTargetSpec->App = (this);\r
+  }\r
+\r
+  void SetFocusedPanel(int index)\r
+  {\r
+    LastFocusedPanel = index;\r
+    _dropTargetSpec->TargetPanelIndex = LastFocusedPanel;\r
+  }\r
+\r
+  void DragBegin(int panelIndex)\r
+  {\r
+    _dropTargetSpec->TargetPanelIndex = (NumPanels > 1) ? 1 - panelIndex : panelIndex;\r
+    _dropTargetSpec->SrcPanelIndex = panelIndex;\r
+  }\r
+\r
+  void DragEnd()\r
+  {\r
+    _dropTargetSpec->TargetPanelIndex = LastFocusedPanel;\r
+    _dropTargetSpec->SrcPanelIndex = -1;\r
+  }\r
+\r
+  \r
+  void OnCopy(bool move, bool copyToSame, int srcPanelIndex);\r
+  void OnSetSameFolder(int srcPanelIndex);\r
+  void OnSetSubFolder(int srcPanelIndex);\r
+\r
+  HRESULT CreateOnePanel(int panelIndex, const UString &mainPath, const UString &arcFormat, bool &archiveIsOpened, bool &encrypted);\r
+  HRESULT Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool &archiveIsOpened, bool &encrypted);\r
+  void Read();\r
+  void Save();\r
+  void Release();\r
+\r
+  // void SetFocus(int panelIndex) { Panels[panelIndex].SetFocusToList(); }\r
+  void SetFocusToLastItem() { Panels[LastFocusedPanel].SetFocusToLastRememberedItem(); }\r
+  int GetFocusedPanelIndex() const { return LastFocusedPanel; }\r
+  bool IsPanelVisible(int index) const { return (NumPanels > 1 || index == LastFocusedPanel); }\r
+  CPanel &GetFocusedPanel() { return Panels[GetFocusedPanelIndex()]; }\r
+\r
+  // File Menu\r
+  void OpenItem() { GetFocusedPanel().OpenSelectedItems(true); }\r
+  void OpenItemInside() { GetFocusedPanel().OpenFocusedItemAsInternal(); }\r
+  void OpenItemOutside() { GetFocusedPanel().OpenSelectedItems(false); }\r
+  void EditItem() { GetFocusedPanel().EditItem(); }\r
+  void Rename() { GetFocusedPanel().RenameFile(); }\r
+  void CopyTo() { OnCopy(false, false, GetFocusedPanelIndex()); }\r
+  void MoveTo() { OnCopy(true, false, GetFocusedPanelIndex()); }\r
+  void Delete(bool toRecycleBin) { GetFocusedPanel().DeleteItems(toRecycleBin); }\r
+  void CalculateCrc();\r
+  void DiffFiles();\r
+  void Split();\r
+  void Combine();\r
+  void Properties() { GetFocusedPanel().Properties(); }\r
+  void Comment() { GetFocusedPanel().ChangeComment(); }\r
+\r
+  void CreateFolder() { GetFocusedPanel().CreateFolder(); }\r
+  void CreateFile() { GetFocusedPanel().CreateFile(); }\r
+\r
+  // Edit\r
+  void EditCut() { GetFocusedPanel().EditCut(); }\r
+  void EditCopy() { GetFocusedPanel().EditCopy(); }\r
+  void EditPaste() { GetFocusedPanel().EditPaste(); }\r
+\r
+  void SelectAll(bool selectMode) { GetFocusedPanel().SelectAll(selectMode); }\r
+  void InvertSelection() { GetFocusedPanel().InvertSelection(); }\r
+  void SelectSpec(bool selectMode) { GetFocusedPanel().SelectSpec(selectMode); }\r
+  void SelectByType(bool selectMode) { GetFocusedPanel().SelectByType(selectMode); }\r
+\r
+  void RefreshStatusBar() { GetFocusedPanel().RefreshStatusBar(); }\r
+\r
+  void SetListViewMode(UInt32 index) { GetFocusedPanel().SetListViewMode(index); }\r
+  UInt32 GetListViewMode() { return GetFocusedPanel().GetListViewMode(); }\r
+  PROPID GetSortID() { return GetFocusedPanel().GetSortID(); }\r
+\r
+  void SortItemsWithPropID(PROPID propID) { GetFocusedPanel().SortItemsWithPropID(propID); }\r
+\r
+  void OpenRootFolder() { GetFocusedPanel().OpenDrivesFolder(); }\r
+  void OpenParentFolder() { GetFocusedPanel().OpenParentFolder(); }\r
+  void FoldersHistory() { GetFocusedPanel().FoldersHistory(); }\r
+  void RefreshView() { GetFocusedPanel().OnReload(); }\r
+  void RefreshAllPanels()\r
+  {\r
+    for (int i = 0; i < NumPanels; i++)\r
+    {\r
+      int index = i;\r
+      if (NumPanels == 1)\r
+        index = LastFocusedPanel;\r
+      Panels[index].OnReload();\r
+    }\r
+  }\r
+\r
+  /*\r
+  void SysIconsWereChanged()\r
+  {\r
+    for (int i = 0; i < NumPanels; i++)\r
+    {\r
+      int index = i;\r
+      if (NumPanels == 1)\r
+        index = LastFocusedPanel;\r
+      Panels[index].SysIconsWereChanged();\r
+    }\r
+  }\r
+  */\r
+\r
+  void SetListSettings();\r
+  void SetShowSystemMenu();\r
+  HRESULT SwitchOnOffOnePanel();\r
+  bool GetFlatMode() { return Panels[LastFocusedPanel].GetFlatMode(); }\r
+  void ChangeFlatMode() { Panels[LastFocusedPanel].ChangeFlatMode(); }\r
+\r
+  void OpenBookmark(int index) { GetFocusedPanel().OpenBookmark(index); }\r
+  void SetBookmark(int index) { GetFocusedPanel().SetBookmark(index); }\r
+\r
+  void ReloadToolbars();\r
+  void ReadToolbar()\r
+  {\r
+    UInt32 mask = ReadToolbarsMask();\r
+    if (mask & ((UInt32)1 << 31))\r
+    {\r
+      ShowButtonsLables = !g_IsSmallScreen;\r
+      LargeButtons = false;\r
+      ShowStandardToolbar = ShowArchiveToolbar = true;\r
+    }\r
+    else\r
+    {\r
+      ShowButtonsLables = ((mask & 1) != 0);\r
+      LargeButtons = ((mask & 2) != 0);\r
+      ShowStandardToolbar = ((mask & 4) != 0);\r
+      ShowArchiveToolbar  = ((mask & 8) != 0);\r
+    }\r
+  }\r
+  void SaveToolbar()\r
+  {\r
+    UInt32 mask = 0;\r
+    if (ShowButtonsLables) mask |= 1;\r
+    if (LargeButtons) mask |= 2;\r
+    if (ShowStandardToolbar) mask |= 4;\r
+    if (ShowArchiveToolbar) mask |= 8;\r
+    SaveToolbarsMask(mask);\r
+  }\r
+  \r
+  void SaveToolbarChanges();\r
+\r
+  void SwitchStandardToolbar()\r
+  {\r
+    ShowStandardToolbar = !ShowStandardToolbar;\r
+    SaveToolbarChanges();\r
+  }\r
+  void SwitchArchiveToolbar()\r
+  {\r
+    ShowArchiveToolbar = !ShowArchiveToolbar;\r
+    SaveToolbarChanges();\r
+  }\r
+  void SwitchButtonsLables()\r
+  {\r
+    ShowButtonsLables = !ShowButtonsLables;\r
+    SaveToolbarChanges();\r
+  }\r
+  void SwitchLargeButtons()\r
+  {\r
+    LargeButtons = !LargeButtons;\r
+    SaveToolbarChanges();\r
+  }\r
+\r
+  void AddToArchive() { GetFocusedPanel().AddToArchive(); }\r
+  void ExtractArchives() { GetFocusedPanel().ExtractArchives(); }\r
+  void TestArchives() { GetFocusedPanel().TestArchives(); }\r
+\r
+  void OnNotify(int ctrlID, LPNMHDR pnmh);\r
+\r
+  UString PrevTitle;\r
+  void RefreshTitle(bool always = false);\r
+  void RefreshTitleAlways() { RefreshTitle(true); }\r
+  void RefreshTitle(int panelIndex, bool always = false);\r
+\r
+  void MoveSubWindows();\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/AppState.h b/CPP/7zip/UI/FileManager/AppState.h
new file mode 100755 (executable)
index 0000000..3e86759
--- /dev/null
@@ -0,0 +1,114 @@
+// AppState.h\r
+\r
+#ifndef __APP_STATE_H\r
+#define __APP_STATE_H\r
+\r
+#include "Windows/Synchronization.h"\r
+\r
+#include "ViewSettings.h"\r
+\r
+void inline AddUniqueStringToHead(UStringVector &list,\r
+    const UString &string)\r
+{\r
+  for(int i = 0; i < list.Size();)\r
+    if (string.CompareNoCase(list[i]) == 0)\r
+      list.Delete(i);\r
+    else\r
+      i++;\r
+  list.Insert(0, string);\r
+}\r
+\r
+class CFastFolders\r
+{\r
+  NWindows::NSynchronization::CCriticalSection _criticalSection;\r
+public:\r
+  UStringVector Strings;\r
+  void SetString(int index, const UString &string)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);\r
+    while(Strings.Size() <= index)\r
+      Strings.Add(UString());\r
+    Strings[index] = string;\r
+  }\r
+  UString GetString(int index)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);\r
+    if (index >= Strings.Size())\r
+      return UString();\r
+    return Strings[index];\r
+  }\r
+  void Save()\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);\r
+    SaveFastFolders(Strings);\r
+  }\r
+  void Read()\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);\r
+    ReadFastFolders(Strings);\r
+  }\r
+};\r
+\r
+class CFolderHistory\r
+{\r
+  NWindows::NSynchronization::CCriticalSection _criticalSection;\r
+  UStringVector Strings;\r
+  void Normalize()\r
+  {\r
+    const int kMaxSize = 100;\r
+    if (Strings.Size() > kMaxSize)\r
+      Strings.Delete(kMaxSize, Strings.Size() - kMaxSize);\r
+  }\r
+  \r
+public:\r
+  \r
+  void GetList(UStringVector &foldersHistory)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);\r
+    foldersHistory = Strings;\r
+  }\r
+  \r
+  void AddString(const UString &string)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);\r
+    AddUniqueStringToHead(Strings, string);\r
+    Normalize();\r
+  }\r
+  \r
+  void RemoveAll()\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);\r
+    Strings.Clear();\r
+  }\r
+  \r
+  void Save()\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);\r
+    SaveFolderHistory(Strings);\r
+  }\r
+  \r
+  void Read()\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);\r
+    ReadFolderHistory(Strings);\r
+    Normalize();\r
+  }\r
+};\r
+\r
+struct CAppState\r
+{\r
+  CFastFolders FastFolders;\r
+  CFolderHistory FolderHistory;\r
+  void Save()\r
+  {\r
+    FastFolders.Save();\r
+    FolderHistory.Save();\r
+  }\r
+  void Read()\r
+  {\r
+    FastFolders.Read();\r
+    FolderHistory.Read();\r
+  }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp
new file mode 100755 (executable)
index 0000000..af9839b
--- /dev/null
@@ -0,0 +1,514 @@
+// BrowseDialog.cpp\r
\r
+#include "StdAfx.h"\r
+\r
+#ifdef UNDER_CE\r
+\r
+#include "Common/IntToString.h"\r
+\r
+#include "Windows/PropVariantConversions.h"\r
+\r
+#include "BrowseDialog.h"\r
+#include "LangUtils.h"\r
+#include "PropertyNameRes.h"\r
+\r
+#ifndef _SFX\r
+#include "RegistryUtils.h"\r
+#endif\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+using namespace NFind;\r
+\r
+extern bool g_LVN_ITEMACTIVATE_Support;\r
+\r
+static const int kParentIndex = -1;\r
+\r
+#ifdef LANG\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDOK, 0x02000702 },\r
+  { IDCANCEL, 0x02000710 }\r
+};\r
+#endif\r
+\r
+static bool GetParentPath(const UString &path2, UString &dest, UString &focused)\r
+{\r
+  UString path = path2;\r
+  dest.Empty();\r
+  if (path.IsEmpty())\r
+    return false;\r
+  if (path.Back() == WCHAR_PATH_SEPARATOR)\r
+    path.DeleteBack();\r
+  if (path.IsEmpty())\r
+    return false;\r
+  int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+  if (pos < 0 || path.Back() == WCHAR_PATH_SEPARATOR)\r
+    return false;\r
+  focused = path.Mid(pos + 1);\r
+  dest = path.Left(pos + 1);\r
+  return true;\r
+}\r
+\r
+bool CBrowseDialog::OnInit()\r
+{\r
+  #ifdef LANG\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+  #endif\r
+  if (!Title.IsEmpty())\r
+    SetText(Title);\r
+  _list.Attach(GetItem(IDC_BROWSE_LIST));\r
+\r
+  #ifndef UNDER_CE\r
+  _list.SetUnicodeFormat(true);\r
+  #endif\r
+\r
+  #ifndef _SFX\r
+  if (ReadSingleClick())\r
+    _list.SetExtendedListViewStyle(LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT);\r
+  _showDots = ReadShowDots();\r
+  #endif\r
+\r
+  _list.SetImageList(GetSysImageList(true), LVSIL_SMALL);\r
+  _list.SetImageList(GetSysImageList(false), LVSIL_NORMAL);\r
+\r
+  _list.InsertColumn(0, LangStringSpec(IDS_PROP_NAME, 0x02000204), 100);\r
+  _list.InsertColumn(1, LangStringSpec(IDS_PROP_MTIME, 0x0200020C), 100);\r
+  {\r
+    LV_COLUMNW column;\r
+    column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;\r
+    column.fmt = LVCFMT_RIGHT;\r
+    column.iSubItem = 2;\r
+    UString s = LangStringSpec(IDS_PROP_SIZE, 0x02000207);\r
+    column.pszText = (wchar_t *)(const wchar_t *)s;\r
+    _list.InsertColumn(2, &column);\r
+\r
+    // _list.InsertColumn(2, LangStringSpec(IDS_PROP_SIZE, 0x02000207), 100);\r
+  }\r
+\r
+  _list.InsertItem(0, L"12345678901234567");\r
+  _list.SetSubItem(0, 1, L"2009-09-09");\r
+  _list.SetSubItem(0, 2, L"9999 MB");\r
+  for (int i = 0; i < 3; i++)\r
+    _list.SetColumnWidthAuto(i);\r
+  _list.DeleteAllItems();\r
+  \r
+  UString selectedName;\r
+  if (!FolderMode)\r
+  {\r
+    int pos = Path.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+    if (pos >= 0 && Path.Back() != WCHAR_PATH_SEPARATOR)\r
+    {\r
+      selectedName = Path.Mid(pos + 1);\r
+      Path = Path.Left(pos + 1);\r
+    }\r
+  }\r
+  _ascending = true;\r
+  _sortIndex = 0;\r
+\r
+  NormalizeSize();\r
+\r
+  while (Reload(Path, selectedName) != S_OK)\r
+  {\r
+    UString parent;\r
+    if (!GetParentPath(Path, parent, selectedName))\r
+      break;\r
+    selectedName.Empty();\r
+    Path = parent;\r
+  }\r
+\r
+  return CModalDialog::OnInit();\r
+}\r
+\r
+bool CBrowseDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)\r
+{\r
+  int mx, my;\r
+  {\r
+    RECT rect;\r
+    GetClientRectOfItem(IDC_BROWSE_PARENT, rect);\r
+    mx = rect.left;\r
+    my = rect.top;\r
+  }\r
+  InvalidateRect(NULL);\r
+\r
+  {\r
+    RECT rect;\r
+    GetClientRectOfItem(IDC_BROWSE_PATH, rect);\r
+    MoveItem(IDC_BROWSE_PATH, rect.left, rect.top, xSize - mx - rect.left, RECT_SIZE_Y(rect));\r
+  }\r
+\r
+  int bx1, bx2, by;\r
+  GetItemSizes(IDCANCEL, bx1, by);\r
+  GetItemSizes(IDOK, bx2, by);\r
+  int y = ySize - my - by;\r
+  int x = xSize - mx - bx1;\r
+  MoveItem(IDCANCEL, x, y, bx1, by);\r
+  MoveItem(IDOK, x - mx - bx2, y, bx2, by);\r
+\r
+  {\r
+    RECT rect;\r
+    GetClientRectOfItem(IDC_BROWSE_LIST, rect);\r
+    _list.Move(rect.left, rect.top, xSize - mx - rect.left, y - my - rect.top);\r
+  }\r
+  return false;\r
+}\r
+\r
+static UString ConvertSizeToStringShort(UInt64 value)\r
+{\r
+  wchar_t s[32];\r
+  wchar_t c = L'\0', c2 = L'\0';\r
+  if (value < (UInt64)10000)\r
+  {\r
+    c = L'\0';\r
+    c2 = L'\0';\r
+  }\r
+  else if (value < ((UInt64)10000 << 10))\r
+  {\r
+    value >>= 10;\r
+    c = L'K';\r
+  }\r
+  else if (value < ((UInt64)10000 << 20))\r
+  {\r
+    value >>= 20;\r
+    c = L'M';\r
+  }\r
+  else\r
+  {\r
+    value >>= 30;\r
+    c = L'G';\r
+  }\r
+  ConvertUInt64ToString(value, s);\r
+  int p = MyStringLen(s);\r
+  if (c != 0)\r
+    s[p++] = L' ';\r
+  s[p++] = c;\r
+  s[p++] = c2;\r
+  s[p++] = L'\0';\r
+  return s;\r
+}\r
+\r
+int CBrowseDialog::CompareItems(LPARAM lParam1, LPARAM lParam2)\r
+{\r
+  if (lParam1 == kParentIndex) return -1;\r
+  if (lParam2 == kParentIndex) return 1;\r
+  const CFileInfoW &f1 = _files[(int)lParam1];\r
+  const CFileInfoW &f2 = _files[(int)lParam2];\r
+\r
+  bool isDir1 = f1.IsDir();\r
+  bool isDir2 = f2.IsDir();\r
+  \r
+  if (isDir1 && !isDir2) return -1;\r
+  if (isDir2 && !isDir1) return 1;\r
+  \r
+  int result = 0;\r
+  switch(_sortIndex)\r
+  {\r
+    case 0: result = f1.Name.CompareNoCase(f2.Name); break;\r
+    case 1: result = CompareFileTime(&f1.MTime, &f2.MTime); break;\r
+    case 2: result = MyCompare(f1.Size, f2.Size); break;\r
+  }\r
+  return _ascending ? result: (-result);\r
+}\r
+\r
+static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)\r
+{\r
+  if (lpData == NULL)\r
+    return 0;\r
+  return ((CBrowseDialog*)lpData)->CompareItems(lParam1, lParam2);\r
+}\r
+\r
+static HRESULT GetNormalizedError()\r
+{\r
+  HRESULT errorCode = GetLastError();\r
+  return (errorCode == 0) ? 1 : errorCode;\r
+}\r
+\r
+HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selectedName)\r
+{\r
+  CEnumeratorW enumerator(pathPrefix + L'*');\r
+  CObjectVector<CFileInfoW> files;\r
+  for (;;)\r
+  {\r
+    bool found;\r
+    CFileInfoW fi;\r
+    if (!enumerator.Next(fi, found))\r
+      return GetNormalizedError();\r
+    if (!found)\r
+      break;\r
+    files.Add(fi);\r
+  }\r
+\r
+  Path = pathPrefix;\r
+\r
+  _files = files;\r
+\r
+  SetItemText(IDC_BROWSE_PATH, Path);\r
+  _list.SetRedraw(false);\r
+  _list.DeleteAllItems();\r
+\r
+  if (!Path.IsEmpty() && Path.Back() != WCHAR_PATH_SEPARATOR)\r
+    Path += WCHAR_PATH_SEPARATOR;\r
+\r
+  LVITEMW item;\r
+\r
+  int index = 0;\r
+  int cursorIndex = -1;\r
+\r
+  #ifndef _SFX\r
+  if (_showDots)\r
+  {\r
+    UString itemName = L"..";\r
+    item.iItem = index;\r
+    if (selectedName.IsEmpty())\r
+      cursorIndex = item.iItem;\r
+    item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;\r
+    int subItem = 0;\r
+    item.iSubItem = subItem++;\r
+    item.lParam = kParentIndex;\r
+    item.pszText = (wchar_t *)(const wchar_t *)itemName;\r
+    item.iImage = _extToIconMap.GetIconIndex(FILE_ATTRIBUTE_DIRECTORY, Path);\r
+    if (item.iImage < 0)\r
+      item.iImage = 0;\r
+    _list.InsertItem(&item);\r
+    _list.SetSubItem(index, subItem++, L"");\r
+    _list.SetSubItem(index, subItem++, L"");\r
+    index++;\r
+  }\r
+  #endif\r
+\r
+  for (int i = 0; i < _files.Size(); i++)\r
+  {\r
+    const CFileInfoW &fi = _files[i];\r
+    item.iItem = index;\r
+    if (fi.Name.CompareNoCase(selectedName) == 0)\r
+      cursorIndex = item.iItem;\r
+    item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;\r
+    int subItem = 0;\r
+    item.iSubItem = subItem++;\r
+    item.lParam = i;\r
+    item.pszText = (wchar_t *)(const wchar_t *)fi.Name;\r
+    item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, Path + fi.Name);\r
+    if (item.iImage < 0)\r
+      item.iImage = 0;\r
+    _list.InsertItem(&item);\r
+    {\r
+      FILETIME ft;\r
+      UString s;\r
+      if (FileTimeToLocalFileTime(&fi.MTime, &ft))\r
+        s = ConvertFileTimeToString(ft, false, false);\r
+      _list.SetSubItem(index, subItem++, s);\r
+    }\r
+    {\r
+      UString s;\r
+      if (!fi.IsDir())\r
+        s = ConvertSizeToStringShort(fi.Size);\r
+      _list.SetSubItem(index, subItem++, s);\r
+    }\r
+    index++;\r
+  }\r
+\r
+  if (_list.GetItemCount() > 0 && cursorIndex >= 0)\r
+    _list.SetItemState_FocusedSelected(cursorIndex);\r
+  _list.SortItems(CompareItems2, (LPARAM)this);\r
+  if (_list.GetItemCount() > 0 && cursorIndex < 0)\r
+    _list.SetItemState(0, LVIS_FOCUSED, LVIS_FOCUSED);\r
+  _list.EnsureVisible(_list.GetFocusedItem(), false);\r
+  _list.SetRedraw(true);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CBrowseDialog::Reload()\r
+{\r
+  UString selectedCur;\r
+  int index = _list.GetNextSelectedItem(-1);\r
+  if (index >= 0)\r
+  {\r
+    int fileIndex = GetRealItemIndex(index);\r
+    if (fileIndex != kParentIndex)\r
+      selectedCur = _files[fileIndex].Name;\r
+  }\r
+  return Reload(Path, selectedCur);\r
+}\r
+\r
+void CBrowseDialog::OpenParentFolder()\r
+{\r
+  UString parent, selected;\r
+  if (GetParentPath(Path, parent, selected))\r
+    Reload(parent, selected);\r
+}\r
+\r
+extern UString HResultToMessage(HRESULT errorCode);\r
+\r
+bool CBrowseDialog::OnNotify(UINT /* controlID */, LPNMHDR header)\r
+{\r
+  if (header->hwndFrom != _list)\r
+    return false;\r
+  switch(header->code)\r
+  {\r
+    case LVN_ITEMACTIVATE:\r
+      if (g_LVN_ITEMACTIVATE_Support)\r
+      {\r
+        OnItemEnter();\r
+        return true;\r
+      }\r
+      break;\r
+    case NM_DBLCLK:\r
+    case NM_RETURN: // probabably it's unused\r
+      if (!g_LVN_ITEMACTIVATE_Support)\r
+      {\r
+        OnItemEnter();\r
+        return true;\r
+      }\r
+      break;\r
+    case LVN_COLUMNCLICK:\r
+    {\r
+      int index = LPNMLISTVIEW(header)->iSubItem;\r
+      if (index == _sortIndex)\r
+        _ascending = !_ascending;\r
+      else\r
+      {\r
+        _ascending = (index == 0);\r
+        _sortIndex = index;\r
+      }\r
+      Reload();\r
+      return false;\r
+    }\r
+    case LVN_KEYDOWN:\r
+    {\r
+      LRESULT result;\r
+      bool boolResult = OnKeyDown(LPNMLVKEYDOWN(header), result);\r
+      return boolResult;\r
+    }\r
+  }\r
+  return false;\r
+}\r
+\r
+bool CBrowseDialog::OnKeyDown(LPNMLVKEYDOWN keyDownInfo, LRESULT &result)\r
+{\r
+  bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0;\r
+  result = 0;\r
+\r
+  switch(keyDownInfo->wVKey)\r
+  {\r
+    case VK_BACK:\r
+      OpenParentFolder();\r
+      return true;\r
+    case 'R':\r
+      if (ctrl)\r
+      {\r
+        Reload();\r
+        return true;\r
+      }\r
+      return false;\r
+  }\r
+  return false;\r
+}\r
+\r
+bool CBrowseDialog::OnButtonClicked(int buttonID, HWND buttonHWND)\r
+{\r
+  switch(buttonID)\r
+  {\r
+    case IDC_BROWSE_PARENT:\r
+      OpenParentFolder();\r
+      return true;\r
+  }\r
+  return CModalDialog::OnButtonClicked(buttonID, buttonHWND);\r
+}\r
+\r
+void CBrowseDialog::ShowError(LPCWSTR s) { MessageBoxW(*this, s, L"7-Zip", MB_ICONERROR); }\r
+\r
+void CBrowseDialog::ShowSelectError()\r
+{\r
+  ShowError(FolderMode ?\r
+      L"You must select some folder":\r
+      L"You must select some file");\r
+}\r
+\r
+void CBrowseDialog::FinishOnOK()\r
+{\r
+  int index = _list.GetNextSelectedItem(-1);\r
+  if (index < 0)\r
+  {\r
+    if (!FolderMode)\r
+    {\r
+      ShowSelectError();\r
+      return;\r
+    }\r
+  }\r
+  else\r
+  {\r
+    int fileIndex = GetRealItemIndex(index);\r
+    if (fileIndex == kParentIndex)\r
+    {\r
+      OpenParentFolder();\r
+      return;\r
+    }\r
+    const CFileInfoW &file = _files[fileIndex];\r
+    if (file.IsDir() != FolderMode)\r
+    {\r
+      ShowSelectError();\r
+      return;\r
+    }\r
+    Path += file.Name;\r
+  }\r
+  End(IDOK);\r
+}\r
+\r
+void CBrowseDialog::OnItemEnter()\r
+{\r
+  int index = _list.GetNextSelectedItem(-1);\r
+  if (index < 0)\r
+    return;\r
+  int fileIndex = GetRealItemIndex(index);\r
+  if (fileIndex == kParentIndex)\r
+    OpenParentFolder();\r
+  else\r
+  {\r
+    const CFileInfoW &file = _files[fileIndex];\r
+    if (!file.IsDir())\r
+    {\r
+      if (!FolderMode)\r
+        FinishOnOK();\r
+      else\r
+        ShowSelectError();\r
+      return;\r
+    }\r
+    HRESULT res = Reload(Path + file.Name + WCHAR_PATH_SEPARATOR, L"");\r
+    if (res != S_OK)\r
+      ShowError(HResultToMessage(res));\r
+  }\r
+}\r
+\r
+void CBrowseDialog::OnOK()\r
+{\r
+  if (GetFocus() == _list)\r
+  {\r
+    OnItemEnter();\r
+    return;\r
+  }\r
+  FinishOnOK();\r
+}\r
+\r
+static bool MyBrowse(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath, bool folderMode)\r
+{\r
+  CBrowseDialog dialog;\r
+  dialog.Title = title;\r
+  dialog.Path = initialFolder;\r
+  dialog.FolderMode = folderMode;\r
+  if (dialog.Create(owner) != IDOK)\r
+    return false;\r
+  resultPath = dialog.Path;\r
+  return true;\r
+}\r
+\r
+bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath)\r
+{\r
+  return MyBrowse(owner, title, initialFolder, resultPath, true);\r
+}\r
+\r
+bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR initialFolder, LPCWSTR, UString &resultPath)\r
+{\r
+  return MyBrowse(owner, title, initialFolder, resultPath, false);\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.h b/CPP/7zip/UI/FileManager/BrowseDialog.h
new file mode 100755 (executable)
index 0000000..624db1c
--- /dev/null
@@ -0,0 +1,77 @@
+// BrowseDialog.h\r
+\r
+#ifndef __BROWSE_DIALOG_H\r
+#define __BROWSE_DIALOG_H\r
+\r
+#ifdef UNDER_CE\r
+\r
+#include "Windows/FileFind.h"\r
+\r
+#include "Windows/Control/Dialog.h"\r
+#include "Windows/Control/ListView.h"\r
+\r
+#include "BrowseDialogRes.h"\r
+#include "SysIconUtils.h"\r
+\r
+class CBrowseDialog: public NWindows::NControl::CModalDialog\r
+{\r
+  NWindows::NControl::CListView _list;\r
+  CObjectVector<NWindows::NFile::NFind::CFileInfoW> _files;\r
+  CExtToIconMap _extToIconMap;\r
+  int _sortIndex;\r
+  bool _ascending;\r
+  bool _showDots;\r
+\r
+  virtual bool OnInit();\r
+  virtual bool OnSize(WPARAM wParam, int xSize, int ySize);\r
+  virtual bool OnNotify(UINT controlID, LPNMHDR header);\r
+  virtual void OnOK();\r
+\r
+  virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);\r
+  virtual bool OnKeyDown(LPNMLVKEYDOWN keyDownInfo, LRESULT &result);\r
+\r
+  void FinishOnOK();\r
+  HRESULT Reload(const UString &pathPrefix, const UString &selectedName);\r
+  HRESULT Reload();\r
+  void OpenParentFolder();\r
+\r
+  void OnItemEnter();\r
+\r
+  int GetRealItemIndex(int indexInListView) const\r
+  {\r
+    LPARAM param;\r
+    if (!_list.GetItemParam(indexInListView, param))\r
+      return (int)-1;\r
+    return (int)param;\r
+  }\r
+\r
+  void ShowError(LPCWSTR s);\r
+  void ShowSelectError();\r
+public:\r
+  UString Title;\r
+  UString Path;\r
+  bool FolderMode;\r
+\r
+  CBrowseDialog(): FolderMode(true), _showDots(false) {}\r
+\r
+  INT_PTR Create(HWND parent = 0) { return CModalDialog::Create(IDD_DIALOG_BROWSE, parent); }\r
+  int CompareItems(LPARAM lParam1, LPARAM lParam2);\r
+};\r
+\r
+bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath);\r
+bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR initialFolder, LPCWSTR s, UString &resultPath);\r
+\r
+#else\r
+\r
+#include "Windows/CommonDialog.h"\r
+#include "Windows/Shell.h"\r
+\r
+#define MyBrowseForFolder(h, title, initialFolder, resultPath) \\r
+  NShell::BrowseForFolder(h, title, initialFolder, resultPath)\r
+\r
+#define MyBrowseForFile(h, title, initialFolder, s, resultPath) \\r
+  MyGetOpenFileName(h, title, initialFolder, s, resultPath)\r
+\r
+#endif\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.rc b/CPP/7zip/UI/FileManager/BrowseDialog.rc
new file mode 100755 (executable)
index 0000000..e299ddc
--- /dev/null
@@ -0,0 +1,17 @@
+#include "BrowseDialogRes.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#define xc 180\r
+#define yc 160\r
+\r
+IDD_DIALOG_BROWSE  MY_RESIZE_DIALOG\r
+CAPTION "7-Zip: Browse"\r
+{\r
+  LTEXT   "", IDC_BROWSE_PATH, m + 20, m + 3, xc - 20, 8\r
+  CONTROL "List1", IDC_BROWSE_LIST, "SysListView32",\r
+          LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_SINGLESEL | WS_BORDER | WS_TABSTOP,\r
+          m, m + 16, xc, yc - bys - m - 16\r
+  PUSHBUTTON  "OK",     IDOK,     bx2, by, bxs, bys\r
+  PUSHBUTTON  "Cancel", IDCANCEL, bx1, by, bxs, bys\r
+  PUSHBUTTON  "..", IDC_BROWSE_PARENT, m, m, 16, 14\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/BrowseDialogRes.h b/CPP/7zip/UI/FileManager/BrowseDialogRes.h
new file mode 100755 (executable)
index 0000000..17afcb1
--- /dev/null
@@ -0,0 +1,4 @@
+#define IDD_DIALOG_BROWSE             509\r
+#define IDC_BROWSE_LIST               1000\r
+#define IDC_BROWSE_PATH               1001\r
+#define IDC_BROWSE_PARENT             1002\r
diff --git a/CPP/7zip/UI/FileManager/ClassDefs.cpp b/CPP/7zip/UI/FileManager/ClassDefs.cpp
new file mode 100755 (executable)
index 0000000..c1e06d9
--- /dev/null
@@ -0,0 +1,7 @@
+// ClassDefs.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/MyInitGuid.h"\r
+\r
+#include "../Agent/Agent.h"\r
diff --git a/CPP/7zip/UI/FileManager/ComboDialog.cpp b/CPP/7zip/UI/FileManager/ComboDialog.cpp
new file mode 100755 (executable)
index 0000000..5195e61
--- /dev/null
@@ -0,0 +1,72 @@
+// ComboDialog.cpp\r
+\r
+#include "StdAfx.h"\r
+#include "ComboDialog.h"\r
+\r
+#include "Windows/Control/Static.h"\r
+\r
+#ifdef LANG\r
+#include "LangUtils.h"\r
+#endif\r
+\r
+using namespace NWindows;\r
+\r
+#ifdef LANG\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDOK, 0x02000702 },\r
+  { IDCANCEL, 0x02000710 }\r
+};\r
+#endif\r
+\r
+bool CComboDialog::OnInit()\r
+{\r
+  #ifdef LANG\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+  #endif\r
+  _comboBox.Attach(GetItem(IDC_COMBO_COMBO));\r
+\r
+  /*\r
+  // why it doesn't work ?\r
+  DWORD style = _comboBox.GetStyle();\r
+  if (Sorted)\r
+    style |= CBS_SORT;\r
+  else\r
+    style &= ~CBS_SORT;\r
+  _comboBox.SetStyle(style);\r
+  */\r
+  SetText(Title);\r
+  \r
+  NControl::CStatic staticContol;\r
+  staticContol.Attach(GetItem(IDC_COMBO_STATIC));\r
+  staticContol.SetText(Static);\r
+  _comboBox.SetText(Value);\r
+  for(int i = 0; i < Strings.Size(); i++)\r
+    _comboBox.AddString(Strings[i]);\r
+  NormalizeSize();\r
+  return CModalDialog::OnInit();\r
+}\r
+\r
+bool CComboDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)\r
+{\r
+  int mx, my;\r
+  GetMargins(8, mx, my);\r
+  int bx1, bx2, by;\r
+  GetItemSizes(IDCANCEL, bx1, by);\r
+  GetItemSizes(IDOK, bx2, by);\r
+  int y = ySize - my - by;\r
+  int x = xSize - mx - bx1;\r
+\r
+  InvalidateRect(NULL);\r
+\r
+  MoveItem(IDCANCEL, x, y, bx1, by);\r
+  MoveItem(IDOK, x - mx - bx2, y, bx2, by);\r
+  ChangeSubWindowSizeX(_comboBox, xSize - mx * 2);\r
+  return false;\r
+}\r
+\r
+void CComboDialog::OnOK()\r
+{\r
+  _comboBox.GetText(Value);\r
+  CModalDialog::OnOK();\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/ComboDialog.h b/CPP/7zip/UI/FileManager/ComboDialog.h
new file mode 100755 (executable)
index 0000000..5c30b08
--- /dev/null
@@ -0,0 +1,27 @@
+// ComboDialog.h\r
+\r
+#ifndef __COMBO_DIALOG_H\r
+#define __COMBO_DIALOG_H\r
+\r
+#include "Windows/Control/ComboBox.h"\r
+#include "Windows/Control/Dialog.h"\r
+\r
+#include "ComboDialogRes.h"\r
+\r
+class CComboDialog: public NWindows::NControl::CModalDialog\r
+{\r
+  NWindows::NControl::CComboBox _comboBox;\r
+  virtual void OnOK();\r
+  virtual bool OnInit();\r
+  virtual bool OnSize(WPARAM wParam, int xSize, int ySize);\r
+public:\r
+  // bool Sorted;\r
+  UString Title;\r
+  UString Static;\r
+  UString Value;\r
+  UStringVector Strings;\r
+  // CComboDialog(): Sorted(false) {};\r
+  INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_DIALOG_COMBO, parentWindow); }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/ComboDialog.rc b/CPP/7zip/UI/FileManager/ComboDialog.rc
new file mode 100755 (executable)
index 0000000..7016710
--- /dev/null
@@ -0,0 +1,13 @@
+#include "ComboDialogRes.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#define xc 240\r
+#define yc 64\r
+\r
+IDD_DIALOG_COMBO  MY_RESIZE_DIALOG\r
+CAPTION "Combo"\r
+{\r
+  LTEXT      "", IDC_COMBO_STATIC, m, m, xc, 8\r
+  COMBOBOX       IDC_COMBO_COMBO,  m, 20, xc, 65, MY_COMBO_WITH_EDIT\r
+  OK_CANCEL\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/ComboDialogRes.h b/CPP/7zip/UI/FileManager/ComboDialogRes.h
new file mode 100755 (executable)
index 0000000..d887d67
--- /dev/null
@@ -0,0 +1,4 @@
+#define IDD_DIALOG_COMBO                505\r
+\r
+#define IDC_COMBO_STATIC                1000\r
+#define IDC_COMBO_COMBO                 1001\r
diff --git a/CPP/7zip/UI/FileManager/Copy.bmp b/CPP/7zip/UI/FileManager/Copy.bmp
new file mode 100755 (executable)
index 0000000..0f28a32
Binary files /dev/null and b/CPP/7zip/UI/FileManager/Copy.bmp differ
diff --git a/CPP/7zip/UI/FileManager/Copy2.bmp b/CPP/7zip/UI/FileManager/Copy2.bmp
new file mode 100755 (executable)
index 0000000..ba88ded
Binary files /dev/null and b/CPP/7zip/UI/FileManager/Copy2.bmp differ
diff --git a/CPP/7zip/UI/FileManager/CopyDialog.cpp b/CPP/7zip/UI/FileManager/CopyDialog.cpp
new file mode 100755 (executable)
index 0000000..40b5dd1
--- /dev/null
@@ -0,0 +1,114 @@
+// CopyDialog.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/FileName.h"\r
+\r
+#include "Windows/Control/Static.h"\r
+\r
+#include "BrowseDialog.h"\r
+#include "CopyDialog.h"\r
+\r
+#ifdef LANG\r
+#include "LangUtils.h"\r
+#endif\r
+\r
+using namespace NWindows;\r
+\r
+#ifdef LANG\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDOK, 0x02000702 },\r
+  { IDCANCEL, 0x02000710 }\r
+};\r
+#endif\r
+\r
+bool CCopyDialog::OnInit()\r
+{\r
+  #ifdef LANG\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+  #endif\r
+  _path.Attach(GetItem(IDC_COPY_COMBO));\r
+  SetText(Title);\r
+\r
+  NControl::CStatic staticContol;\r
+  staticContol.Attach(GetItem(IDC_COPY_STATIC));\r
+  staticContol.SetText(Static);\r
+  #ifdef UNDER_CE\r
+  // we do it, since WinCE selects Value\something instead of Value !!!!\r
+  _path.AddString(Value);\r
+  #endif\r
+  for (int i = 0; i < Strings.Size(); i++)\r
+    _path.AddString(Strings[i]);\r
+  _path.SetText(Value);\r
+  SetItemText(IDC_COPY_INFO, Info);\r
+  NormalizeSize(true);\r
+  return CModalDialog::OnInit();\r
+}\r
+\r
+bool CCopyDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)\r
+{\r
+  int mx, my;\r
+  GetMargins(8, mx, my);\r
+  int bx1, bx2, by;\r
+  GetItemSizes(IDCANCEL, bx1, by);\r
+  GetItemSizes(IDOK, bx2, by);\r
+  int y = ySize - my - by;\r
+  int x = xSize - mx - bx1;\r
+\r
+  InvalidateRect(NULL);\r
+\r
+  {\r
+    RECT rect;\r
+    GetClientRectOfItem(IDC_COPY_SET_PATH, rect);\r
+    int bx = rect.right - rect.left;\r
+    MoveItem(IDC_COPY_SET_PATH, xSize - mx - bx, rect.top, bx, rect.bottom - rect.top);\r
+    ChangeSubWindowSizeX(_path, xSize - mx - mx - bx - mx);\r
+  }\r
+\r
+  {\r
+    RECT rect;\r
+    GetClientRectOfItem(IDC_COPY_INFO, rect);\r
+    NControl::CStatic staticContol;\r
+    staticContol.Attach(GetItem(IDC_COPY_INFO));\r
+    int yPos = rect.top;\r
+    staticContol.Move(mx, yPos, xSize - mx * 2, y - 2 - yPos);\r
+  }\r
+\r
+  MoveItem(IDCANCEL, x, y, bx1, by);\r
+  MoveItem(IDOK, x - mx - bx2, y, bx2, by);\r
+\r
+  return false;\r
+}\r
+\r
+bool CCopyDialog::OnButtonClicked(int buttonID, HWND buttonHWND)\r
+{\r
+  switch(buttonID)\r
+  {\r
+    case IDC_COPY_SET_PATH:\r
+      OnButtonSetPath();\r
+      return true;\r
+  }\r
+  return CModalDialog::OnButtonClicked(buttonID, buttonHWND);\r
+}\r
+\r
+void CCopyDialog::OnButtonSetPath()\r
+{\r
+  UString currentPath;\r
+  _path.GetText(currentPath);\r
+\r
+  UString title = LangStringSpec(IDS_SET_FOLDER, 0x03020209);\r
+\r
+  UString resultPath;\r
+  if (!MyBrowseForFolder(HWND(*this), title, currentPath, resultPath))\r
+    return;\r
+  NFile::NName::NormalizeDirPathPrefix(resultPath);\r
+  _path.SetCurSel(-1);\r
+  _path.SetText(resultPath);\r
+}\r
+\r
+void CCopyDialog::OnOK()\r
+{\r
+  _path.GetText(Value);\r
+  CModalDialog::OnOK();\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/CopyDialog.h b/CPP/7zip/UI/FileManager/CopyDialog.h
new file mode 100755 (executable)
index 0000000..eec5a58
--- /dev/null
@@ -0,0 +1,31 @@
+// CopyDialog.h\r
+\r
+#ifndef __COPY_DIALOG_H\r
+#define __COPY_DIALOG_H\r
+\r
+#include "Windows/Control/ComboBox.h"\r
+#include "Windows/Control/Dialog.h"\r
+\r
+#include "CopyDialogRes.h"\r
+\r
+const int kCopyDialog_NumInfoLines = 11;\r
+\r
+class CCopyDialog: public NWindows::NControl::CModalDialog\r
+{\r
+  NWindows::NControl::CComboBox _path;\r
+  virtual void OnOK();\r
+  virtual bool OnInit();\r
+  virtual bool OnSize(WPARAM wParam, int xSize, int ySize);\r
+  void OnButtonSetPath();\r
+  bool OnButtonClicked(int buttonID, HWND buttonHWND);\r
+public:\r
+  UString Title;\r
+  UString Static;\r
+  UString Value;\r
+  UString Info;\r
+  UStringVector Strings;\r
+\r
+  INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_DIALOG_COPY, parentWindow); }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/CopyDialog.rc b/CPP/7zip/UI/FileManager/CopyDialog.rc
new file mode 100755 (executable)
index 0000000..13fc9eb
--- /dev/null
@@ -0,0 +1,17 @@
+#include "CopyDialogRes.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#define xc 320\r
+#define yc 144\r
+\r
+#define y 40\r
+\r
+IDD_DIALOG_COPY  MY_RESIZE_DIALOG\r
+CAPTION "Copy"\r
+{\r
+  LTEXT       "",    IDC_COPY_STATIC,   m, m, xc, 8\r
+  COMBOBOX           IDC_COPY_COMBO,    m, 20, xc - bxsDots - m, 65, MY_COMBO_WITH_EDIT\r
+  PUSHBUTTON  "...", IDC_COPY_SET_PATH, xs - m - bxsDots, 18, bxsDots, bys, WS_GROUP\r
+  LTEXT       "",    IDC_COPY_INFO,     m, y, xc, by - y - 1, SS_NOPREFIX | SS_LEFTNOWORDWRAP\r
+  OK_CANCEL\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/CopyDialogRes.h b/CPP/7zip/UI/FileManager/CopyDialogRes.h
new file mode 100755 (executable)
index 0000000..32999ff
--- /dev/null
@@ -0,0 +1,8 @@
+#define IDD_DIALOG_COPY                506\r
+\r
+#define IDC_COPY_STATIC                1000\r
+#define IDC_COPY_COMBO                 1001\r
+#define IDC_COPY_SET_PATH              1002\r
+#define IDC_COPY_INFO                  1003\r
+\r
+#define IDS_SET_FOLDER  210\r
diff --git a/CPP/7zip/UI/FileManager/Delete.bmp b/CPP/7zip/UI/FileManager/Delete.bmp
new file mode 100755 (executable)
index 0000000..d1004d8
Binary files /dev/null and b/CPP/7zip/UI/FileManager/Delete.bmp differ
diff --git a/CPP/7zip/UI/FileManager/Delete2.bmp b/CPP/7zip/UI/FileManager/Delete2.bmp
new file mode 100755 (executable)
index 0000000..60e08c6
Binary files /dev/null and b/CPP/7zip/UI/FileManager/Delete2.bmp differ
diff --git a/CPP/7zip/UI/FileManager/DialogSize.h b/CPP/7zip/UI/FileManager/DialogSize.h
new file mode 100755 (executable)
index 0000000..f17728c
--- /dev/null
@@ -0,0 +1,16 @@
+// DialogSize.h\r
+\r
+#ifndef __DIALOG_SIZE_H\r
+#define __DIALOG_SIZE_H\r
+\r
+#include "Windows/Control/Dialog.h"\r
+\r
+#ifdef UNDER_CE\r
+#define BIG_DIALOG_SIZE(x, y) bool isBig = NWindows::NControl::IsDialogSizeOK(x, y);\r
+#define SIZED_DIALOG(big) (isBig ? big : big ## _2)\r
+#else\r
+#define BIG_DIALOG_SIZE(x, y)\r
+#define SIZED_DIALOG(big) big\r
+#endif\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/EditPage.cpp b/CPP/7zip/UI/FileManager/EditPage.cpp
new file mode 100755 (executable)
index 0000000..e43ba54
--- /dev/null
@@ -0,0 +1,99 @@
+// EditPage.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "EditPage.h"\r
+#include "EditPageRes.h"\r
+\r
+#include "BrowseDialog.h"\r
+#include "HelpUtils.h"\r
+#include "LangUtils.h"\r
+#include "RegistryUtils.h"\r
+\r
+using namespace NWindows;\r
+\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDC_EDIT_STATIC_EDITOR, 0x03010201},\r
+  { IDC_EDIT_STATIC_DIFF, 0x03010202}\r
+};\r
+\r
+static LPCWSTR kEditTopic = L"FM/options.htm#editor";\r
+\r
+bool CEditPage::OnInit()\r
+{\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+\r
+  _editor.Attach(GetItem(IDC_EDIT_EDIT_EDITOR));\r
+  _diff.Attach(GetItem(IDC_EDIT_EDIT_DIFF));\r
+  \r
+  {\r
+    UString path;\r
+    ReadRegEditor(path);\r
+    _editor.SetText(path);\r
+  }\r
+  {\r
+    UString path;\r
+    ReadRegDiff(path);\r
+    _diff.SetText(path);\r
+  }\r
+  return CPropertyPage::OnInit();\r
+}\r
+\r
+LONG CEditPage::OnApply()\r
+{\r
+  {\r
+    UString path;\r
+    _editor.GetText(path);\r
+    SaveRegEditor(path);\r
+  }\r
+  {\r
+    UString path;\r
+    _diff.GetText(path);\r
+    SaveRegDiff(path);\r
+  }\r
+  return PSNRET_NOERROR;\r
+}\r
+\r
+void CEditPage::OnNotifyHelp()\r
+{\r
+  ShowHelpWindow(NULL, kEditTopic);\r
+}\r
+\r
+static void Edit_BrowseForFile(NWindows::NControl::CEdit &edit, HWND hwnd)\r
+{\r
+  UString path;\r
+  edit.GetText(path);\r
+  UString resPath;\r
+  if (MyBrowseForFile(hwnd, 0, path, L"*.exe", resPath))\r
+  {\r
+    edit.SetText(resPath);\r
+    // Changed();\r
+  }\r
+}\r
+\r
+bool CEditPage::OnButtonClicked(int buttonID, HWND buttonHWND)\r
+{\r
+  switch (buttonID)\r
+  {\r
+    case IDC_EDIT_BUTTON_EDITOR:\r
+      Edit_BrowseForFile(_editor, *this);\r
+      return true;\r
+    case IDC_EDIT_BUTTON_DIFF:\r
+      Edit_BrowseForFile(_diff, *this);\r
+      return true;\r
+  }\r
+  return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);\r
+}\r
+\r
+bool CEditPage::OnCommand(int code, int itemID, LPARAM param)\r
+{\r
+  if (code == EN_CHANGE &&\r
+      (itemID == IDC_EDIT_EDIT_EDITOR ||\r
+      itemID == IDC_EDIT_EDIT_DIFF))\r
+  {\r
+    Changed();\r
+    return true;\r
+  }\r
+  return CPropertyPage::OnCommand(code, itemID, param);\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/EditPage.h b/CPP/7zip/UI/FileManager/EditPage.h
new file mode 100755 (executable)
index 0000000..0b27787
--- /dev/null
@@ -0,0 +1,21 @@
+// EditPage.h\r
\r
+#ifndef __EDIT_PAGE_H\r
+#define __EDIT_PAGE_H\r
+\r
+#include "Windows/Control/PropertyPage.h"\r
+#include "Windows/Control/Edit.h"\r
+\r
+class CEditPage: public NWindows::NControl::CPropertyPage\r
+{\r
+  NWindows::NControl::CEdit _editor;\r
+  NWindows::NControl::CEdit _diff;\r
+public:\r
+  virtual bool OnInit();\r
+  virtual void OnNotifyHelp();\r
+  virtual bool OnCommand(int code, int itemID, LPARAM param);\r
+  virtual LONG OnApply();\r
+  virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/EditPage.rc b/CPP/7zip/UI/FileManager/EditPage.rc
new file mode 100755 (executable)
index 0000000..65929ca
--- /dev/null
@@ -0,0 +1,19 @@
+#include "EditPageRes.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#define xc 200\r
+#define yc 80\r
+\r
+IDD_EDIT  MY_PAGE\r
+#include "EditPage2.rc"\r
+\r
+#ifdef UNDER_CE\r
+\r
+#undef xc\r
+\r
+#define xc SMALL_PAGE_SIZE_X\r
+\r
+IDD_EDIT_2  MY_PAGE\r
+#include "EditPage2.rc"\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/EditPage2.rc b/CPP/7zip/UI/FileManager/EditPage2.rc
new file mode 100755 (executable)
index 0000000..14c0329
--- /dev/null
@@ -0,0 +1,9 @@
+CAPTION "Editor"\r
+{\r
+  LTEXT       "&Editor:", IDC_EDIT_STATIC_EDITOR, m, m, xc, 8\r
+  EDITTEXT    IDC_EDIT_EDIT_EDITOR, m, 20, xc - m - bxsDots, 14, ES_AUTOHSCROLL\r
+  PUSHBUTTON  "...", IDC_EDIT_BUTTON_EDITOR, xs - m - bxsDots, 19, bxsDots, bys\r
+  LTEXT       "&Diff:", IDC_EDIT_STATIC_DIFF, m, 40, xc, 8\r
+  EDITTEXT    IDC_EDIT_EDIT_DIFF, m, 52, xc - m - bxsDots, 14, ES_AUTOHSCROLL\r
+  PUSHBUTTON  "...", IDC_EDIT_BUTTON_DIFF, xs - m - bxsDots, 51, bxsDots, bys\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/EditPageRes.h b/CPP/7zip/UI/FileManager/EditPageRes.h
new file mode 100755 (executable)
index 0000000..f17f092
--- /dev/null
@@ -0,0 +1,10 @@
+#define IDD_EDIT                 542\r
+#define IDD_EDIT_2               642\r
+\r
+#define IDC_EDIT_STATIC_EDITOR  1000\r
+#define IDC_EDIT_EDIT_EDITOR    1001\r
+#define IDC_EDIT_BUTTON_EDITOR  1002\r
+\r
+#define IDC_EDIT_STATIC_DIFF    1010\r
+#define IDC_EDIT_EDIT_DIFF      1011\r
+#define IDC_EDIT_BUTTON_DIFF    1012\r
diff --git a/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp b/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp
new file mode 100755 (executable)
index 0000000..60bc650
--- /dev/null
@@ -0,0 +1,108 @@
+// EnumFormatEtc.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "EnumFormatEtc.h"\r
+#include "MyCom2.h"\r
+\r
+class CEnumFormatEtc :\r
+public IEnumFORMATETC,\r
+public CMyUnknownImp\r
+{\r
+public:\r
+  MY_UNKNOWN_IMP1_MT(IEnumFORMATETC)\r
+    \r
+  STDMETHOD(Next)(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched);\r
+  STDMETHOD(Skip)(ULONG celt);\r
+  STDMETHOD(Reset)(void);\r
+  STDMETHOD(Clone)(IEnumFORMATETC **ppEnumFormatEtc);\r
+  \r
+  CEnumFormatEtc(const FORMATETC *pFormatEtc, ULONG numFormats);\r
+  ~CEnumFormatEtc();\r
+  \r
+private:\r
+  LONG m_RefCount;\r
+  ULONG m_NumFormats;\r
+  FORMATETC *m_Formats;\r
+  ULONG m_Index;\r
+};\r
+\r
+static void DeepCopyFormatEtc(FORMATETC *dest, const FORMATETC *src)\r
+{\r
+  *dest = *src;\r
+  if(src->ptd)\r
+  {\r
+    dest->ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE));\r
+    *(dest->ptd) = *(src->ptd);\r
+  }\r
+}\r
+\r
+CEnumFormatEtc::CEnumFormatEtc(const FORMATETC *pFormatEtc, ULONG numFormats)\r
+{\r
+  m_RefCount = 1;\r
+  m_Index = 0;\r
+  m_NumFormats = 0;\r
+  m_Formats = new FORMATETC[numFormats];\r
+  if(m_Formats)\r
+  {\r
+    m_NumFormats = numFormats;\r
+    for(ULONG i = 0; i < numFormats; i++)\r
+      DeepCopyFormatEtc(&m_Formats[i], &pFormatEtc[i]);\r
+  }\r
+}\r
+\r
+CEnumFormatEtc::~CEnumFormatEtc()\r
+{\r
+  if(m_Formats)\r
+  {\r
+    for(ULONG i = 0; i < m_NumFormats; i++)\r
+      if(m_Formats[i].ptd)\r
+        CoTaskMemFree(m_Formats[i].ptd);\r
+      delete[]m_Formats;\r
+  }\r
+}\r
+\r
+STDMETHODIMP CEnumFormatEtc::Next(ULONG celt, FORMATETC *pFormatEtc, ULONG *pceltFetched)\r
+{\r
+  ULONG copied  = 0;\r
+  if(celt == 0 || pFormatEtc == 0)\r
+    return E_INVALIDARG;\r
+  while(m_Index < m_NumFormats && copied < celt)\r
+  {\r
+    DeepCopyFormatEtc(&pFormatEtc[copied], &m_Formats[m_Index]);\r
+    copied++;\r
+    m_Index++;\r
+  }\r
+  if(pceltFetched != 0)\r
+    *pceltFetched = copied;\r
+  return (copied == celt) ? S_OK : S_FALSE;\r
+}\r
+\r
+STDMETHODIMP CEnumFormatEtc::Skip(ULONG celt)\r
+{\r
+  m_Index += celt;\r
+  return (m_Index <= m_NumFormats) ? S_OK : S_FALSE;\r
+}\r
+\r
+STDMETHODIMP CEnumFormatEtc::Reset(void)\r
+{\r
+  m_Index = 0;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CEnumFormatEtc::Clone(IEnumFORMATETC ** ppEnumFormatEtc)\r
+{\r
+  HRESULT hResult = CreateEnumFormatEtc(m_NumFormats, m_Formats, ppEnumFormatEtc);\r
+  if(hResult == S_OK)\r
+    ((CEnumFormatEtc *)*ppEnumFormatEtc)->m_Index = m_Index;\r
+  return hResult;\r
+}\r
+\r
+// replacement for SHCreateStdEnumFmtEtc\r
+HRESULT CreateEnumFormatEtc(UINT numFormats, const FORMATETC *formats, IEnumFORMATETC **enumFormat)\r
+{\r
+  if(numFormats == 0 || formats == 0 || enumFormat == 0)\r
+    return E_INVALIDARG;\r
+  *enumFormat = new CEnumFormatEtc(formats, numFormats);\r
+  return (*enumFormat) ? S_OK : E_OUTOFMEMORY;\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/EnumFormatEtc.h b/CPP/7zip/UI/FileManager/EnumFormatEtc.h
new file mode 100755 (executable)
index 0000000..f1aed49
--- /dev/null
@@ -0,0 +1,10 @@
+// EnumFormatEtc.h\r
+\r
+#ifndef __ENUMFORMATETC_H\r
+#define __ENUMFORMATETC_H\r
+\r
+#include <windows.h>\r
+\r
+HRESULT CreateEnumFormatEtc(UINT numFormats, const FORMATETC *formats, IEnumFORMATETC **enumFormat);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/Extract.bmp b/CPP/7zip/UI/FileManager/Extract.bmp
new file mode 100755 (executable)
index 0000000..0aeba92
Binary files /dev/null and b/CPP/7zip/UI/FileManager/Extract.bmp differ
diff --git a/CPP/7zip/UI/FileManager/Extract2.bmp b/CPP/7zip/UI/FileManager/Extract2.bmp
new file mode 100755 (executable)
index 0000000..a7e5775
Binary files /dev/null and b/CPP/7zip/UI/FileManager/Extract2.bmp differ
diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/CPP/7zip/UI/FileManager/ExtractCallback.cpp
new file mode 100755 (executable)
index 0000000..b786d2f
--- /dev/null
@@ -0,0 +1,453 @@
+// ExtractCallback.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/Error.h"\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileFind.h"\r
+\r
+#include "../../Common/FilePathAutoRename.h"\r
+\r
+#include "../GUI/ExtractRes.h"\r
+\r
+#include "ExtractCallback.h"\r
+#include "FormatUtils.h"\r
+#include "OverwriteDialog.h"\r
+#ifndef _NO_CRYPTO\r
+#include "PasswordDialog.h"\r
+#endif\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+using namespace NFind;\r
+\r
+CExtractCallbackImp::~CExtractCallbackImp() {}\r
+\r
+void CExtractCallbackImp::Init()\r
+{\r
+  NumArchiveErrors = 0;\r
+  ThereAreMessageErrors = false;\r
+  #ifndef _SFX\r
+  NumFolders = NumFiles = 0;\r
+  NeedAddFile = false;\r
+  #endif\r
+}\r
+\r
+void CExtractCallbackImp::AddErrorMessage(LPCWSTR message)\r
+{\r
+  ThereAreMessageErrors = true;\r
+  ProgressDialog->Sync.AddErrorMessage(message);\r
+}\r
+\r
+STDMETHODIMP CExtractCallbackImp::SetNumFiles(UInt64\r
+  #ifndef _SFX\r
+  numFiles\r
+  #endif\r
+  )\r
+{\r
+  #ifndef _SFX\r
+  ProgressDialog->Sync.SetNumFilesTotal(numFiles);\r
+  #endif\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 total)\r
+{\r
+  ProgressDialog->Sync.SetProgress(total, 0);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *value)\r
+{\r
+  RINOK(ProgressDialog->Sync.ProcessStopAndPause());\r
+  if (value != NULL)\r
+    ProgressDialog->Sync.SetPos(*value);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CExtractCallbackImp::Open_CheckBreak()\r
+{\r
+  return ProgressDialog->Sync.ProcessStopAndPause();\r
+}\r
+\r
+HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)\r
+{\r
+  // if (numFiles != NULL) ProgressDialog->Sync.SetNumFilesTotal(*numFiles);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)\r
+{\r
+  RINOK(ProgressDialog->Sync.ProcessStopAndPause());\r
+  // if (numFiles != NULL) ProgressDialog->Sync.SetNumFilesCur(*numFiles);\r
+  return S_OK;\r
+}\r
+\r
+#ifndef _NO_CRYPTO\r
+\r
+HRESULT CExtractCallbackImp::Open_CryptoGetTextPassword(BSTR *password)\r
+{\r
+  return CryptoGetTextPassword(password);\r
+}\r
+\r
+HRESULT CExtractCallbackImp::Open_GetPasswordIfAny(UString &password)\r
+{\r
+  if (PasswordIsDefined)\r
+    password = Password;\r
+  return S_OK;\r
+}\r
+\r
+bool CExtractCallbackImp::Open_WasPasswordAsked()\r
+{\r
+  return PasswordWasAsked;\r
+}\r
+\r
+void CExtractCallbackImp::Open_ClearPasswordWasAskedFlag()\r
+{\r
+  PasswordWasAsked = false;\r
+}\r
+\r
+#endif\r
+\r
+\r
+#ifndef _SFX\r
+STDMETHODIMP CExtractCallbackImp::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)\r
+{\r
+  ProgressDialog->Sync.SetRatioInfo(inSize, outSize);\r
+  return S_OK;\r
+}\r
+#endif\r
+\r
+/*\r
+STDMETHODIMP CExtractCallbackImp::SetTotalFiles(UInt64 total)\r
+{\r
+  ProgressDialog->Sync.SetNumFilesTotal(total);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtractCallbackImp::SetCompletedFiles(const UInt64 *value)\r
+{\r
+  if (value != NULL)\r
+    ProgressDialog->Sync.SetNumFilesCur(*value);\r
+  return S_OK;\r
+}\r
+*/\r
+\r
+STDMETHODIMP CExtractCallbackImp::AskOverwrite(\r
+    const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,\r
+    const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,\r
+    Int32 *answer)\r
+{\r
+  COverwriteDialog dialog;\r
+\r
+  dialog.OldFileInfo.SetTime(existTime);\r
+  dialog.OldFileInfo.SetSize(existSize);\r
+  dialog.OldFileInfo.Name = existName;\r
+\r
+  dialog.NewFileInfo.SetTime(newTime);\r
+  dialog.NewFileInfo.SetSize(newSize);\r
+  dialog.NewFileInfo.Name = newName;\r
+  \r
+  ProgressDialog->WaitCreating();\r
+  INT_PTR writeAnswer = dialog.Create(*ProgressDialog);\r
+  \r
+  switch(writeAnswer)\r
+  {\r
+    case IDCANCEL: *answer = NOverwriteAnswer::kCancel; return E_ABORT;\r
+    case IDYES: *answer = NOverwriteAnswer::kYes; break;\r
+    case IDNO: *answer = NOverwriteAnswer::kNo; break;\r
+    case IDC_BUTTON_OVERWRITE_YES_TO_ALL: *answer = NOverwriteAnswer::kYesToAll; break;\r
+    case IDC_BUTTON_OVERWRITE_NO_TO_ALL: *answer = NOverwriteAnswer::kNoToAll; break;\r
+    case IDC_BUTTON_OVERWRITE_AUTO_RENAME: *answer = NOverwriteAnswer::kAutoRename; break;\r
+    default: return E_FAIL;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+\r
+STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, bool isFolder, Int32 /* askExtractMode */, const UInt64 * /* position */)\r
+{\r
+  _isFolder = isFolder;\r
+  return SetCurrentFilePath2(name);\r
+}\r
+\r
+STDMETHODIMP CExtractCallbackImp::MessageError(const wchar_t *message)\r
+{\r
+  AddErrorMessage(message);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtractCallbackImp::ShowMessage(const wchar_t *message)\r
+{\r
+  AddErrorMessage(message);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 operationResult, bool encrypted)\r
+{\r
+  switch(operationResult)\r
+  {\r
+    case NArchive::NExtract::NOperationResult::kOK:\r
+      break;\r
+    default:\r
+    {\r
+      UINT messageID;\r
+      UInt32 langID;\r
+      switch(operationResult)\r
+      {\r
+        case NArchive::NExtract::NOperationResult::kUnSupportedMethod:\r
+          messageID = IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_UNSUPPORTED_METHOD;\r
+          langID = 0x02000A91;\r
+          break;\r
+        case NArchive::NExtract::NOperationResult::kDataError:\r
+          messageID = encrypted ?\r
+              IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED:\r
+              IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR;\r
+          langID = encrypted ? 0x02000A94 : 0x02000A92;\r
+          break;\r
+        case NArchive::NExtract::NOperationResult::kCRCError:\r
+          messageID = encrypted ?\r
+              IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC_ENCRYPTED:\r
+              IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC;\r
+          langID = encrypted ? 0x02000A95 : 0x02000A93;\r
+          break;\r
+        default:\r
+          return E_FAIL;\r
+      }\r
+      if (_needWriteArchivePath)\r
+      {\r
+        if (!_currentArchivePath.IsEmpty())\r
+          AddErrorMessage(_currentArchivePath);\r
+        _needWriteArchivePath = false;\r
+      }\r
+      AddErrorMessage(\r
+        MyFormatNew(messageID,\r
+          #ifdef LANG\r
+          langID,\r
+          #endif\r
+          _currentFilePath));\r
+    }\r
+  }\r
+  #ifndef _SFX\r
+  if (_isFolder)\r
+    NumFolders++;\r
+  else\r
+    NumFiles++;\r
+  ProgressDialog->Sync.SetNumFilesCur(NumFiles);\r
+  #endif\r
+  return S_OK;\r
+}\r
+\r
+////////////////////////////////////////\r
+// IExtractCallbackUI\r
+\r
+HRESULT CExtractCallbackImp::BeforeOpen(const wchar_t *name)\r
+{\r
+  #ifndef _SFX\r
+  ProgressDialog->Sync.SetTitleFileName(name);\r
+  #endif\r
+  _currentArchivePath = name;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CExtractCallbackImp::SetCurrentFilePath2(const wchar_t *path)\r
+{\r
+  _currentFilePath = path;\r
+  #ifndef _SFX\r
+  ProgressDialog->Sync.SetCurrentFileName(path);\r
+  #endif\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CExtractCallbackImp::SetCurrentFilePath(const wchar_t *path)\r
+{\r
+  #ifndef _SFX\r
+  if (NeedAddFile)\r
+    NumFiles++;\r
+  NeedAddFile = true;\r
+  ProgressDialog->Sync.SetNumFilesCur(NumFiles);\r
+  #endif\r
+  return SetCurrentFilePath2(path);\r
+}\r
+\r
+HRESULT CExtractCallbackImp::OpenResult(const wchar_t *name, HRESULT result, bool encrypted)\r
+{\r
+  if (result != S_OK)\r
+  {\r
+    UString message;\r
+    if (result == S_FALSE)\r
+    {\r
+      message = MyFormatNew(encrypted ? IDS_CANT_OPEN_ENCRYPTED_ARCHIVE : IDS_CANT_OPEN_ARCHIVE,\r
+        #ifdef LANG\r
+        (encrypted ? 0x0200060A : 0x02000609),\r
+        #endif\r
+        name);\r
+    }\r
+    else\r
+    {\r
+      message = name;\r
+      message += L": ";\r
+      UString message2;\r
+      if (result == E_OUTOFMEMORY)\r
+        message2 =\r
+        #ifdef LANG\r
+        LangString(IDS_MEM_ERROR, 0x0200060B);\r
+        #else\r
+        MyLoadStringW(IDS_MEM_ERROR);\r
+        #endif\r
+      else\r
+        NError::MyFormatMessage(result, message2);\r
+      message += message2;\r
+    }\r
+    MessageError(message);\r
+    NumArchiveErrors++;\r
+  }\r
+  _currentArchivePath = name;\r
+  _needWriteArchivePath = true;\r
+  return S_OK;\r
+}\r
+  \r
+HRESULT CExtractCallbackImp::ThereAreNoFiles()\r
+{\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CExtractCallbackImp::ExtractResult(HRESULT result)\r
+{\r
+  if (result == S_OK)\r
+    return result;\r
+  NumArchiveErrors++;\r
+  if (result == E_ABORT || result == ERROR_DISK_FULL)\r
+    return result;\r
+  MessageError(_currentFilePath);\r
+  MessageError(NError::MyFormatMessageW(result));\r
+  return S_OK;\r
+}\r
+\r
+#ifndef _NO_CRYPTO\r
+\r
+HRESULT CExtractCallbackImp::SetPassword(const UString &password)\r
+{\r
+  PasswordIsDefined = true;\r
+  Password = password;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CExtractCallbackImp::CryptoGetTextPassword(BSTR *password)\r
+{\r
+  PasswordWasAsked = true;\r
+  if (!PasswordIsDefined)\r
+  {\r
+    CPasswordDialog dialog;\r
+    ProgressDialog->WaitCreating();\r
+    if (dialog.Create(*ProgressDialog) == IDCANCEL)\r
+      return E_ABORT;\r
+    Password = dialog.Password;\r
+    PasswordIsDefined = true;\r
+  }\r
+  return StringToBstr(Password, password);\r
+}\r
+\r
+#endif\r
+\r
+// IExtractCallBack3\r
+STDMETHODIMP CExtractCallbackImp::AskWrite(\r
+    const wchar_t *srcPath, Int32 srcIsFolder,\r
+    const FILETIME *srcTime, const UInt64 *srcSize,\r
+    const wchar_t *destPath,\r
+    BSTR *destPathResult,\r
+    Int32 *writeAnswer)\r
+{\r
+  UString destPathResultTemp = destPath;\r
+\r
+  // RINOK(StringToBstr(destPath, destPathResult));\r
+\r
+  *destPathResult = 0;\r
+  *writeAnswer = BoolToInt(false);\r
+\r
+  UString destPathSpec = destPath;\r
+  UString destPathSys = destPathSpec;\r
+  bool srcIsFolderSpec = IntToBool(srcIsFolder);\r
+  CFileInfoW destFileInfo;\r
+  if (destFileInfo.Find(destPathSys))\r
+  {\r
+    if (srcIsFolderSpec)\r
+    {\r
+      if (!destFileInfo.IsDir())\r
+      {\r
+        UString message = UString(L"can not replace file \'")\r
+          + destPathSpec +\r
+          UString(L"\' with folder with same name");\r
+        RINOK(MessageError(message));\r
+        return E_ABORT;\r
+      }\r
+      *writeAnswer = BoolToInt(false);\r
+      return S_OK;\r
+    }\r
+    if (destFileInfo.IsDir())\r
+    {\r
+      UString message = UString(L"can not replace folder \'")\r
+          + destPathSpec +\r
+          UString(L"\' with file with same name");\r
+      RINOK(MessageError(message));\r
+      return E_FAIL;\r
+    }\r
+\r
+    switch(OverwriteMode)\r
+    {\r
+      case NExtract::NOverwriteMode::kSkipExisting:\r
+        return S_OK;\r
+      case NExtract::NOverwriteMode::kAskBefore:\r
+      {\r
+        Int32 overwiteResult;\r
+        RINOK(AskOverwrite(\r
+            destPathSpec,\r
+            &destFileInfo.MTime, &destFileInfo.Size,\r
+            srcPath,\r
+            srcTime, srcSize,\r
+            &overwiteResult));\r
+          switch(overwiteResult)\r
+        {\r
+          case NOverwriteAnswer::kCancel:\r
+            return E_ABORT;\r
+          case NOverwriteAnswer::kNo:\r
+            return S_OK;\r
+          case NOverwriteAnswer::kNoToAll:\r
+            OverwriteMode = NExtract::NOverwriteMode::kSkipExisting;\r
+            return S_OK;\r
+          case NOverwriteAnswer::kYesToAll:\r
+            OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;\r
+            break;\r
+          case NOverwriteAnswer::kYes:\r
+            break;\r
+          case NOverwriteAnswer::kAutoRename:\r
+            OverwriteMode = NExtract::NOverwriteMode::kAutoRename;\r
+            break;\r
+          default:\r
+            return E_FAIL;\r
+        }\r
+      }\r
+    }\r
+    if (OverwriteMode == NExtract::NOverwriteMode::kAutoRename)\r
+    {\r
+      if (!AutoRenamePath(destPathSys))\r
+      {\r
+        UString message = UString(L"can not create name of file ")\r
+            + destPathSys;\r
+        RINOK(MessageError(message));\r
+        return E_ABORT;\r
+      }\r
+      destPathResultTemp = destPathSys;\r
+    }\r
+    else\r
+      if (!NFile::NDirectory::DeleteFileAlways(destPathSys))\r
+      {\r
+        UString message = UString(L"can not delete output file ")\r
+            + destPathSys;\r
+        RINOK(MessageError(message));\r
+        return E_ABORT;\r
+      }\r
+  }\r
+  *writeAnswer = BoolToInt(true);\r
+  return StringToBstr(destPathResultTemp, destPathResult);\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.h b/CPP/7zip/UI/FileManager/ExtractCallback.h
new file mode 100755 (executable)
index 0000000..bb13d98
--- /dev/null
@@ -0,0 +1,138 @@
+// ExtractCallback.h\r
+\r
+#ifndef __EXTRACT_CALLBACK_H\r
+#define __EXTRACT_CALLBACK_H\r
+\r
+#include "Common/MyCom.h"\r
+\r
+#include "Windows/ResourceString.h"\r
+\r
+#include "../Agent/IFolderArchive.h"\r
+#include "../Common/ArchiveOpenCallback.h"\r
+\r
+#ifndef _NO_CRYPTO\r
+#include "../../IPassword.h"\r
+#endif\r
+\r
+#include "IFolder.h"\r
+\r
+#include "ProgressDialog2.h"\r
+\r
+#ifdef LANG\r
+#include "LangUtils.h"\r
+#endif\r
+\r
+class CExtractCallbackImp:\r
+  public IExtractCallbackUI,\r
+  public IOpenCallbackUI,\r
+  public IFolderOperationsExtractCallback,\r
+  // public IFolderArchiveExtractCallback, // mkultiple from IProgress\r
+  #ifndef _SFX\r
+  public ICompressProgressInfo,\r
+  #endif\r
+  #ifndef _NO_CRYPTO\r
+  public ICryptoGetTextPassword,\r
+  #endif\r
+  public CMyUnknownImp\r
+{\r
+public:\r
+  MY_QUERYINTERFACE_BEGIN2(IFolderOperationsExtractCallback)\r
+  MY_QUERYINTERFACE_ENTRY(IFolderArchiveExtractCallback)\r
+  #ifndef _SFX\r
+  MY_QUERYINTERFACE_ENTRY(ICompressProgressInfo)\r
+  #endif\r
+  #ifndef _NO_CRYPTO\r
+  MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)\r
+  #endif\r
+  MY_QUERYINTERFACE_END\r
+  MY_ADDREF_RELEASE\r
+\r
+  #ifndef _SFX\r
+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);\r
+  #endif\r
+\r
+  INTERFACE_IProgress(;)\r
+  INTERFACE_IOpenCallbackUI(;)\r
+\r
+  // IFolderArchiveExtractCallback\r
+  // STDMETHOD(SetTotalFiles)(UInt64 total);\r
+  // STDMETHOD(SetCompletedFiles)(const UInt64 *value);\r
+  STDMETHOD(AskOverwrite)(\r
+      const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,\r
+      const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,\r
+      Int32 *answer);\r
+  STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position);\r
+\r
+  STDMETHOD(MessageError)(const wchar_t *message);\r
+  STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted);\r
+\r
+  // IExtractCallbackUI\r
+  \r
+  HRESULT BeforeOpen(const wchar_t *name);\r
+  HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted);\r
+  HRESULT ThereAreNoFiles();\r
+  HRESULT ExtractResult(HRESULT result);\r
+\r
+  #ifndef _NO_CRYPTO\r
+  HRESULT SetPassword(const UString &password);\r
+  #endif\r
+\r
+  // IFolderOperationsExtractCallback\r
+  STDMETHOD(AskWrite)(\r
+      const wchar_t *srcPath,\r
+      Int32 srcIsFolder,\r
+      const FILETIME *srcTime,\r
+      const UInt64 *srcSize,\r
+      const wchar_t *destPathRequest,\r
+      BSTR *destPathResult,\r
+      Int32 *writeAnswer);\r
+  STDMETHOD(ShowMessage)(const wchar_t *message);\r
+  STDMETHOD(SetCurrentFilePath)(const wchar_t *filePath);\r
+  STDMETHOD(SetNumFiles)(UInt64 numFiles);\r
+\r
+  // ICryptoGetTextPassword\r
+  #ifndef _NO_CRYPTO\r
+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);\r
+  #endif\r
+\r
+private:\r
+  UString _currentArchivePath;\r
+  bool _needWriteArchivePath;\r
+\r
+  UString _currentFilePath;\r
+  bool _isFolder;\r
+\r
+  HRESULT SetCurrentFilePath2(const wchar_t *filePath);\r
+  void AddErrorMessage(LPCWSTR message);\r
+public:\r
+  CProgressDialog *ProgressDialog;\r
+  #ifndef _SFX\r
+  UInt64 NumFolders;\r
+  UInt64 NumFiles;\r
+  bool NeedAddFile;\r
+  #endif\r
+  UInt32 NumArchiveErrors;\r
+  bool ThereAreMessageErrors;\r
+  NExtract::NOverwriteMode::EEnum OverwriteMode;\r
+\r
+  #ifndef _NO_CRYPTO\r
+  bool PasswordIsDefined;\r
+  bool PasswordWasAsked;\r
+  UString Password;\r
+  #endif\r
+\r
+  CExtractCallbackImp():\r
+    #ifndef _NO_CRYPTO\r
+    PasswordIsDefined(false),\r
+    PasswordWasAsked(false),\r
+    #endif\r
+    OverwriteMode(NExtract::NOverwriteMode::kAskBefore)\r
+    {}\r
+   \r
+  ~CExtractCallbackImp();\r
+  void Init();\r
+\r
+  bool IsOK() const { return NumArchiveErrors == 0 && !ThereAreMessageErrors; }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/FM.cpp b/CPP/7zip/UI/FileManager/FM.cpp
new file mode 100755 (executable)
index 0000000..279c4a4
--- /dev/null
@@ -0,0 +1,855 @@
+// FM.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/Alloc.h"\r
+\r
+#include "Windows/Error.h"\r
+#include "Windows/MemoryLock.h"\r
+#include "Windows/NtCheck.h"\r
+\r
+#ifndef UNDER_CE\r
+#include "Windows/Security.h"\r
+#endif\r
+\r
+#include "../GUI/ExtractRes.h"\r
+\r
+#include "resource.h"\r
+\r
+#include "App.h"\r
+#include "FormatUtils.h"\r
+#include "LangUtils.h"\r
+#include "MyLoadMenu.h"\r
+#include "Panel.h"\r
+#include "RegistryUtils.h"\r
+#include "StringUtils.h"\r
+#include "ViewSettings.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+using namespace NFind;\r
+\r
+#define MAX_LOADSTRING 100\r
+\r
+#define MENU_HEIGHT 26\r
+\r
+HINSTANCE g_hInstance;\r
+HWND g_HWND;\r
+bool g_OpenArchive = false;\r
+static UString g_MainPath;\r
+static UString g_ArcFormat;\r
+static bool g_Maximized = false;\r
+\r
+#ifndef UNDER_CE\r
+DWORD g_ComCtl32Version;\r
+#endif\r
+\r
+bool g_IsSmallScreen = false;\r
+\r
+bool g_LVN_ITEMACTIVATE_Support = true;\r
+// LVN_ITEMACTIVATE replaces both NM_DBLCLK & NM_RETURN\r
+// Windows 2000\r
+// NT/98 + IE 3 (g_ComCtl32Version >= 4.70)\r
+\r
+\r
+const int kNumDefaultPanels = 1;\r
+\r
+const int kSplitterWidth = 4;\r
+int kSplitterRateMax = 1 << 16;\r
+int kPanelSizeMin = 120;\r
+\r
+// bool OnMenuCommand(HWND hWnd, int id);\r
+\r
+class CSplitterPos\r
+{\r
+  int _ratio; // 10000 is max\r
+  int _pos;\r
+  int _fullWidth;\r
+  void SetRatioFromPos(HWND hWnd)\r
+    { _ratio = (_pos + kSplitterWidth / 2) * kSplitterRateMax /\r
+        MyMax(GetWidth(hWnd), 1); }\r
+public:\r
+  int GetPos() const\r
+    { return _pos; }\r
+  int GetWidth(HWND hWnd) const\r
+  {\r
+    RECT rect;\r
+    ::GetClientRect(hWnd, &rect);\r
+    return rect.right;\r
+  }\r
+  void SetRatio(HWND hWnd, int aRatio)\r
+  {\r
+    _ratio = aRatio;\r
+    SetPosFromRatio(hWnd);\r
+  }\r
+  void SetPosPure(HWND hWnd, int pos)\r
+  {\r
+    int posMax = GetWidth(hWnd) - kSplitterWidth;\r
+    if (posMax < kPanelSizeMin * 2)\r
+      pos = posMax / 2;\r
+    else\r
+    {\r
+      if (pos > posMax - kPanelSizeMin)\r
+        pos = posMax - kPanelSizeMin;\r
+      else if (pos < kPanelSizeMin)\r
+        pos = kPanelSizeMin;\r
+    }\r
+    _pos = pos;\r
+  }\r
+  void SetPos(HWND hWnd, int pos)\r
+  {\r
+    _fullWidth = GetWidth(hWnd);\r
+    SetPosPure(hWnd, pos);\r
+    SetRatioFromPos(hWnd);\r
+  }\r
+  void SetPosFromRatio(HWND hWnd)\r
+  {\r
+    int fullWidth = GetWidth(hWnd);\r
+    if (_fullWidth != fullWidth && fullWidth != 0)\r
+    {\r
+      _fullWidth = fullWidth;\r
+      SetPosPure(hWnd, GetWidth(hWnd) * _ratio / kSplitterRateMax - kSplitterWidth / 2);\r
+    }\r
+  }\r
+};\r
+\r
+static bool g_CanChangeSplitter = false;\r
+static UINT32 g_SplitterPos = 0;\r
+static CSplitterPos g_Splitter;\r
+static bool g_PanelsInfoDefined = false;\r
+\r
+static int g_StartCaptureMousePos;\r
+static int g_StartCaptureSplitterPos;\r
+\r
+CApp g_App;\r
+\r
+LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);\r
+\r
+const wchar_t *kWindowClass = L"FM";\r
+\r
+#ifdef UNDER_CE\r
+#define WS_OVERLAPPEDWINDOW ( \\r
+  WS_OVERLAPPED   | \\r
+  WS_CAPTION      | \\r
+  WS_SYSMENU      | \\r
+  WS_THICKFRAME   | \\r
+  WS_MINIMIZEBOX  | \\r
+  WS_MAXIMIZEBOX)\r
+#endif\r
+\r
+//  FUNCTION: InitInstance(HANDLE, int)\r
+BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)\r
+{\r
+  CWindow wnd;\r
+\r
+  g_hInstance = hInstance;\r
+\r
+  ReloadLangSmart();\r
+\r
+  // LoadString(hInstance, IDS_CLASS, windowClass, MAX_LOADSTRING);\r
+\r
+  // LoadString(hInstance, IDS_APP_TITLE, title, MAX_LOADSTRING);\r
+  UString title = LangString(IDS_APP_TITLE, 0x03000000);\r
+\r
+  /*\r
+  //If it is already running, then focus on the window\r
+  hWnd = FindWindow(windowClass, title);\r
+  if (hWnd)\r
+  {\r
+    SetForegroundWindow ((HWND) (((DWORD)hWnd) | 0x01));\r
+    return 0;\r
+  }\r
+  */\r
+\r
+  WNDCLASSW wc;\r
+\r
+  // wc.style = CS_HREDRAW | CS_VREDRAW;\r
+  wc.style = 0;\r
+  wc.lpfnWndProc = (WNDPROC) WndProc;\r
+  wc.cbClsExtra = 0;\r
+  wc.cbWndExtra = 0;\r
+  wc.hInstance = hInstance;\r
+  wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON));\r
+\r
+  // wc.hCursor = LoadCursor (NULL, IDC_ARROW);\r
+  wc.hCursor = ::LoadCursor(0, IDC_SIZEWE);\r
+  // wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);\r
+  wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);\r
+\r
+  wc.lpszMenuName =\r
+    #ifdef UNDER_CE\r
+    0\r
+    #else\r
+    MAKEINTRESOURCEW(IDM_MENU)\r
+    #endif\r
+    ;\r
+\r
+  wc.lpszClassName = kWindowClass;\r
+\r
+  MyRegisterClass(&wc);\r
+\r
+  // RECT rect;\r
+  // GetClientRect(hWnd, &rect);\r
+\r
+  DWORD style = WS_OVERLAPPEDWINDOW;\r
+  // DWORD style = 0;\r
+  \r
+  RECT rect;\r
+  bool maximized = false;\r
+  int x , y, xSize, ySize;\r
+  x = y = xSize = ySize = CW_USEDEFAULT;\r
+  bool windowPosIsRead = ReadWindowSize(rect, maximized);\r
+\r
+  if (windowPosIsRead)\r
+  {\r
+    // x = rect.left;\r
+    // y = rect.top;\r
+    xSize = rect.right - rect.left;\r
+    ySize = rect.bottom - rect.top;\r
+  }\r
+\r
+  UINT32 numPanels, currentPanel;\r
+  g_PanelsInfoDefined = ReadPanelsInfo(numPanels, currentPanel, g_SplitterPos);\r
+  if (g_PanelsInfoDefined)\r
+  {\r
+    if (numPanels < 1 || numPanels > 2)\r
+      numPanels = kNumDefaultPanels;\r
+    if (currentPanel >= 2)\r
+      currentPanel = 0;\r
+  }\r
+  else\r
+  {\r
+    numPanels = kNumDefaultPanels;\r
+    currentPanel = 0;\r
+  }\r
+  g_App.NumPanels = numPanels;\r
+  g_App.LastFocusedPanel = currentPanel;\r
+\r
+  if (!wnd.Create(kWindowClass, title, style,\r
+    x, y, xSize, ySize, NULL, NULL, hInstance, NULL))\r
+    return FALSE;\r
+\r
+  if (nCmdShow == SW_SHOWNORMAL ||\r
+      nCmdShow == SW_SHOW\r
+      #ifndef UNDER_CE\r
+      || nCmdShow == SW_SHOWDEFAULT\r
+      #endif\r
+      )\r
+  {\r
+    if (maximized)\r
+      nCmdShow = SW_SHOWMAXIMIZED;\r
+    else\r
+      nCmdShow = SW_SHOWNORMAL;\r
+  }\r
+\r
+  if (nCmdShow == SW_SHOWMAXIMIZED)\r
+    g_Maximized = true;\r
+\r
+  #ifndef UNDER_CE\r
+  WINDOWPLACEMENT placement;\r
+  placement.length = sizeof(placement);\r
+  if (wnd.GetPlacement(&placement))\r
+  {\r
+    if (windowPosIsRead)\r
+      placement.rcNormalPosition = rect;\r
+    placement.showCmd = nCmdShow;\r
+    wnd.SetPlacement(&placement);\r
+  }\r
+  else\r
+  #endif\r
+    wnd.Show(nCmdShow);\r
+\r
+  return TRUE;\r
+}\r
+\r
+/*\r
+static void GetCommands(const UString &aCommandLine, UString &aCommands)\r
+{\r
+  UString aProgramName;\r
+  aCommands.Empty();\r
+  bool aQuoteMode = false;\r
+  for (int i = 0; i < aCommandLine.Length(); i++)\r
+  {\r
+    wchar_t aChar = aCommandLine[i];\r
+    if (aChar == L'\"')\r
+      aQuoteMode = !aQuoteMode;\r
+    else if (aChar == L' ' && !aQuoteMode)\r
+    {\r
+      if (!aQuoteMode)\r
+      {\r
+        i++;\r
+        break;\r
+      }\r
+    }\r
+    else\r
+      aProgramName += aChar;\r
+  }\r
+  aCommands = aCommandLine.Mid(i);\r
+}\r
+*/\r
+\r
+#ifndef UNDER_CE\r
+static DWORD GetDllVersion(LPCTSTR lpszDllName)\r
+{\r
+  HINSTANCE hinstDll;\r
+  DWORD dwVersion = 0;\r
+  hinstDll = LoadLibrary(lpszDllName);\r
+  if (hinstDll)\r
+  {\r
+    DLLGETVERSIONPROC pDllGetVersion;\r
+    pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion");\r
+    \r
+    /*Because some DLLs might not implement this function, you\r
+    must test for it explicitly. Depending on the particular\r
+    DLL, the lack of a DllGetVersion function can be a useful\r
+    indicator of the version.\r
+    */\r
+    if (pDllGetVersion)\r
+    {\r
+      DLLVERSIONINFO dvi;\r
+      HRESULT hr;\r
+      \r
+      ZeroMemory(&dvi, sizeof(dvi));\r
+      dvi.cbSize = sizeof(dvi);\r
+      \r
+      hr = (*pDllGetVersion)(&dvi);\r
+      \r
+      if (SUCCEEDED(hr))\r
+      {\r
+        dwVersion = MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion);\r
+      }\r
+    }\r
+    FreeLibrary(hinstDll);\r
+  }\r
+  return dwVersion;\r
+}\r
+#endif\r
+\r
+/*\r
+#ifndef _WIN64\r
+typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);\r
+\r
+static bool IsWow64()\r
+{\r
+  LPFN_ISWOW64PROCESS  fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(\r
+      GetModuleHandle("kernel32"), "IsWow64Process");\r
+  if (fnIsWow64Process == NULL)\r
+    return false;\r
+  BOOL isWow;\r
+  if (!fnIsWow64Process(GetCurrentProcess(),&isWow))\r
+    return false;\r
+  return isWow != FALSE;\r
+}\r
+#endif\r
+*/\r
+\r
+bool IsLargePageSupported()\r
+{\r
+  #ifdef _WIN64\r
+  return true;\r
+  #else\r
+  OSVERSIONINFO versionInfo;\r
+  versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);\r
+  if (!::GetVersionEx(&versionInfo))\r
+    return false;\r
+  if (versionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || versionInfo.dwMajorVersion < 5)\r
+    return false;\r
+  if (versionInfo.dwMajorVersion > 5)\r
+    return true;\r
+  if (versionInfo.dwMinorVersion < 1)\r
+    return false;\r
+  if (versionInfo.dwMinorVersion > 1)\r
+    return true;\r
+  // return IsWow64();\r
+  return false;\r
+  #endif\r
+}\r
+\r
+#ifndef UNDER_CE\r
+static void SetMemoryLock()\r
+{\r
+  if (!IsLargePageSupported())\r
+    return;\r
+  // if (ReadLockMemoryAdd())\r
+    NSecurity::AddLockMemoryPrivilege();\r
+\r
+  if (ReadLockMemoryEnable())\r
+    NSecurity::EnableLockMemoryPrivilege();\r
+}\r
+#endif\r
+\r
+/*\r
+static const int kNumSwitches = 1;\r
+\r
+namespace NKey {\r
+enum Enum\r
+{\r
+  kOpenArachive = 0\r
+};\r
+\r
+}\r
+\r
+static const CSwitchForm kSwitchForms[kNumSwitches] =\r
+  {\r
+    { L"SOA", NSwitchType::kSimple, false },\r
+  };\r
+*/\r
+\r
+// int APIENTRY WinMain2(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, LPSTR /* lpCmdLine */, int /* nCmdShow */);\r
+\r
+#define NT_CHECK_FAIL_ACTION MessageBoxW(0, L"Unsupported Windows version", L"7-zip", MB_ICONERROR); return 1;\r
+\r
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,\r
+    #ifdef UNDER_CE\r
+    LPWSTR\r
+    #else\r
+    LPSTR\r
+    #endif\r
+    /* lpCmdLine */, int nCmdShow)\r
+{\r
+  #ifdef _WIN32\r
+\r
+  NT_CHECK\r
+  SetLargePageSize();\r
+\r
+  #endif\r
+\r
+  InitCommonControls();\r
+\r
+  #ifndef UNDER_CE\r
+  g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll"));\r
+  g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4));\r
+  #endif\r
+\r
+  g_IsSmallScreen = !NWindows::NControl::IsDialogSizeOK(200, 200);\r
+\r
+  // OleInitialize is required for drag and drop.\r
+  #ifndef UNDER_CE\r
+  OleInitialize(NULL);\r
+  #endif\r
+  // Maybe needs CoInitializeEx also ?\r
+  // NCOM::CComInitializer comInitializer;\r
+\r
+  UString commandsString;\r
+  // MessageBoxW(0, GetCommandLineW(), L"", 0);\r
+\r
+  #ifdef UNDER_CE\r
+  commandsString = GetCommandLineW();\r
+  #else\r
+  UString programString;\r
+  SplitStringToTwoStrings(GetCommandLineW(), programString, commandsString);\r
+  #endif\r
+\r
+  commandsString.Trim();\r
+  UString paramString, tailString;\r
+  SplitStringToTwoStrings(commandsString, paramString, tailString);\r
+  paramString.Trim();\r
+  tailString.Trim();\r
+  if (tailString.Left(2) == L"-t")\r
+    g_ArcFormat = tailString.Mid(2);\r
+  if (!paramString.IsEmpty())\r
+  {\r
+    g_MainPath = paramString;\r
+    // return WinMain2(hInstance, hPrevInstance, lpCmdLine, nCmdShow);\r
+\r
+    // MessageBoxW(0, paramString, L"", 0);\r
+  }\r
+  /*\r
+  UStringVector commandStrings;\r
+  NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);\r
+  NCommandLineParser::CParser parser(kNumSwitches);\r
+  try\r
+  {\r
+    parser.ParseStrings(kSwitchForms, commandStrings);\r
+    const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;\r
+    if (nonSwitchStrings.Size() > 1)\r
+    {\r
+      g_MainPath = nonSwitchStrings[1];\r
+      // g_OpenArchive = parser[NKey::kOpenArachive].ThereIs;\r
+      CFileInfoW fileInfo;\r
+      if (FindFile(g_MainPath, fileInfo))\r
+      {\r
+        if (!fileInfo.IsDir())\r
+          g_OpenArchive = true;\r
+      }\r
+    }\r
+  }\r
+  catch(...) { }\r
+  */\r
+\r
+\r
+  #ifndef UNDER_CE\r
+  SetMemoryLock();\r
+  #endif\r
+\r
+  MSG msg;\r
+  if (!InitInstance (hInstance, nCmdShow))\r
+    return FALSE;\r
+\r
+  #ifndef _UNICODE\r
+  if (g_IsNT)\r
+  {\r
+    HACCEL hAccels = LoadAcceleratorsW(hInstance, MAKEINTRESOURCEW(IDR_ACCELERATOR1));\r
+    while (GetMessageW(&msg, NULL, 0, 0))\r
+    {\r
+      if (TranslateAcceleratorW(g_HWND, hAccels, &msg) == 0)\r
+      {\r
+        TranslateMessage(&msg);\r
+        DispatchMessageW(&msg);\r
+      }\r
+    }\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    HACCEL hAccels = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));\r
+    while (GetMessage(&msg, NULL, 0, 0))\r
+    {\r
+      if (TranslateAccelerator(g_HWND, hAccels, &msg) == 0)\r
+      {\r
+        // if (g_Hwnd != NULL || !IsDialogMessage(g_Hwnd, &msg))\r
+        // if (!IsDialogMessage(g_Hwnd, &msg))\r
+        TranslateMessage(&msg);\r
+        DispatchMessage(&msg);\r
+      }\r
+    }\r
+  }\r
+\r
+  g_HWND = 0;\r
+  #ifndef UNDER_CE\r
+  OleUninitialize();\r
+  #endif\r
+  return (int)msg.wParam;\r
+}\r
+\r
+static void SaveWindowInfo(HWND aWnd)\r
+{\r
+  #ifdef UNDER_CE\r
+  RECT rect;\r
+  if (!::GetWindowRect(aWnd, &rect))\r
+    return;\r
+  SaveWindowSize(rect, g_Maximized);\r
+  #else\r
+  WINDOWPLACEMENT placement;\r
+  placement.length = sizeof(placement);\r
+  if (!::GetWindowPlacement(aWnd, &placement))\r
+    return;\r
+  SaveWindowSize(placement.rcNormalPosition, BOOLToBool(::IsZoomed(aWnd)));\r
+  #endif\r
+  SavePanelsInfo(g_App.NumPanels, g_App.LastFocusedPanel, g_Splitter.GetPos());\r
+}\r
+\r
+static void ExecuteCommand(UINT commandID)\r
+{\r
+  CPanel::CDisableTimerProcessing disableTimerProcessing1(g_App.Panels[0]);\r
+  CPanel::CDisableTimerProcessing disableTimerProcessing2(g_App.Panels[1]);\r
+\r
+  switch (commandID)\r
+  {\r
+    case kAddCommand: g_App.AddToArchive(); break;\r
+    case kExtractCommand: g_App.ExtractArchives(); break;\r
+    case kTestCommand: g_App.TestArchives(); break;\r
+  }\r
+}\r
+\r
+LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+  int wmId, wmEvent;\r
+  switch (message)\r
+  {\r
+    case WM_COMMAND:\r
+      wmId    = LOWORD(wParam);\r
+      wmEvent = HIWORD(wParam);\r
+      if ((HWND) lParam != NULL && wmEvent != 0)\r
+        break;\r
+      if (wmId >= kToolbarStartID)\r
+      {\r
+        ExecuteCommand(wmId);\r
+        return 0;\r
+      }\r
+      if (OnMenuCommand(hWnd, wmId))\r
+        return 0;\r
+      break;\r
+    case WM_INITMENUPOPUP:\r
+      OnMenuActivating(hWnd, HMENU(wParam), LOWORD(lParam));\r
+      break;\r
+\r
+    /*\r
+    It doesn't help\r
+    case WM_EXITMENULOOP:\r
+      {\r
+        OnMenuUnActivating(hWnd);\r
+        break;\r
+      }\r
+    case WM_UNINITMENUPOPUP:\r
+      OnMenuUnActivating(hWnd, HMENU(wParam), lParam);\r
+      break;\r
+    */\r
+\r
+    case WM_CREATE:\r
+    {\r
+      g_HWND = hWnd;\r
+      /*\r
+      INITCOMMONCONTROLSEX icex;\r
+      icex.dwSize = sizeof(INITCOMMONCONTROLSEX);\r
+      icex.dwICC  = ICC_BAR_CLASSES;\r
+      InitCommonControlsEx(&icex);\r
+      \r
+      // Toolbar buttons used to create the first 4 buttons.\r
+      TBBUTTON tbb [ ] =\r
+      {\r
+        // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0},\r
+        // {VIEW_PARENTFOLDER, kParentFolderID, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0},\r
+          // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0},\r
+        {VIEW_NEWFOLDER, ID_FILE_CREATEFOLDER, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0},\r
+      };\r
+      \r
+      int baseID = 100;\r
+      NWindows::NControl::CToolBar aToolBar;\r
+      aToolBar.Attach(::CreateToolbarEx (hWnd,\r
+        WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS, //  | TBSTYLE_FLAT\r
+        baseID + 2, 11,\r
+        (HINSTANCE)HINST_COMMCTRL, IDB_VIEW_SMALL_COLOR,\r
+        (LPCTBBUTTON)&tbb, sizeof(tbb) / sizeof(tbb[0]),\r
+        0, 0, 100, 30, sizeof (TBBUTTON)));\r
+      */\r
+      // HCURSOR cursor = ::LoadCursor(0, IDC_SIZEWE);\r
+      // ::SetCursor(cursor);\r
+\r
+      if (g_PanelsInfoDefined)\r
+        g_Splitter.SetPos(hWnd, g_SplitterPos);\r
+      else\r
+      {\r
+        g_Splitter.SetRatio(hWnd, kSplitterRateMax / 2);\r
+        g_SplitterPos = g_Splitter.GetPos();\r
+      }\r
+\r
+      RECT rect;\r
+      ::GetClientRect(hWnd, &rect);\r
+      int xSize = rect.right;\r
+      int xSizes[2];\r
+      xSizes[0] = g_Splitter.GetPos();\r
+      xSizes[1] = xSize - kSplitterWidth - xSizes[0];\r
+      if (xSizes[1] < 0)\r
+        xSizes[1] = 0;\r
+\r
+      g_App.CreateDragTarget();\r
+      bool archiveIsOpened;\r
+      bool encrypted;\r
+      bool needOpenFile = false;\r
+      if (!g_MainPath.IsEmpty() /* && g_OpenArchive */)\r
+      {\r
+        if (NFile::NFind::DoesFileExist(g_MainPath))\r
+          needOpenFile = true;\r
+      }\r
+      HRESULT res = g_App.Create(hWnd, g_MainPath, g_ArcFormat, xSizes, archiveIsOpened, encrypted);\r
+\r
+      if (res == E_ABORT)\r
+      {\r
+        return -1;\r
+      }\r
+      if (needOpenFile && !archiveIsOpened || res != S_OK)\r
+      {\r
+        UString message = L"Error";\r
+        if (res == S_FALSE || res == S_OK)\r
+        {\r
+          if (encrypted)\r
+            message = MyFormatNew(IDS_CANT_OPEN_ENCRYPTED_ARCHIVE, 0x0200060A, g_MainPath);\r
+          else\r
+            message = MyFormatNew(IDS_CANT_OPEN_ARCHIVE, 0x02000609, g_MainPath);\r
+        }\r
+        else\r
+        {\r
+          if (res != S_OK)\r
+          {\r
+            if (res == E_OUTOFMEMORY)\r
+              message = LangString(IDS_MEM_ERROR, 0x0200060B);\r
+            else\r
+              if (!NError::MyFormatMessage(res, message))\r
+                message = L"Error";\r
+          }\r
+        }\r
+        MessageBoxW(0, message, L"7-zip", MB_ICONERROR);\r
+        return -1;\r
+      }\r
+      // g_SplitterPos = 0;\r
+\r
+      // ::DragAcceptFiles(hWnd, TRUE);\r
+      RegisterDragDrop(hWnd, g_App._dropTarget);\r
+\r
+      break;\r
+    }\r
+    case WM_DESTROY:\r
+    {\r
+      // ::DragAcceptFiles(hWnd, FALSE);\r
+      RevokeDragDrop(hWnd);\r
+      g_App._dropTarget.Release();\r
+\r
+      g_App.Save();\r
+      g_App.Release();\r
+      SaveWindowInfo(hWnd);\r
+      PostQuitMessage(0);\r
+      break;\r
+    }\r
+    /*\r
+    case WM_MOVE:\r
+    {\r
+      break;\r
+    }\r
+    */\r
+    case WM_LBUTTONDOWN:\r
+      g_StartCaptureMousePos = LOWORD(lParam);\r
+      g_StartCaptureSplitterPos = g_Splitter.GetPos();\r
+      ::SetCapture(hWnd);\r
+      break;\r
+    case WM_LBUTTONUP:\r
+    {\r
+      ::ReleaseCapture();\r
+      break;\r
+    }\r
+    case WM_MOUSEMOVE:\r
+    {\r
+      if ((wParam & MK_LBUTTON) != 0 && ::GetCapture() == hWnd)\r
+      {\r
+        g_Splitter.SetPos(hWnd, g_StartCaptureSplitterPos +\r
+            (short)LOWORD(lParam) - g_StartCaptureMousePos);\r
+        g_App.MoveSubWindows();\r
+      }\r
+      break;\r
+    }\r
+\r
+    case WM_SIZE:\r
+    {\r
+      if (g_CanChangeSplitter)\r
+        g_Splitter.SetPosFromRatio(hWnd);\r
+      else\r
+      {\r
+        g_Splitter.SetPos(hWnd, g_SplitterPos );\r
+        g_CanChangeSplitter = true;\r
+      }\r
+      \r
+      g_Maximized = (wParam == SIZE_MAXIMIZED) || (wParam == SIZE_MAXSHOW);\r
+\r
+      g_App.MoveSubWindows();\r
+      /*\r
+      int xSize = LOWORD(lParam);\r
+      int ySize = HIWORD(lParam);\r
+      // int xSplitter = 2;\r
+      int xWidth = g_SplitPos;\r
+      // int xSplitPos = xWidth;\r
+      g_Panel[0]._listView.MoveWindow(0, 0, xWidth, ySize);\r
+      g_Panel[1]._listView.MoveWindow(xSize - xWidth, 0, xWidth, ySize);\r
+      */\r
+      return 0;\r
+      break;\r
+    }\r
+    case WM_SETFOCUS:\r
+      // g_App.SetFocus(g_App.LastFocusedPanel);\r
+      g_App.SetFocusToLastItem();\r
+      break;\r
+    /*\r
+    case WM_ACTIVATE:\r
+    {\r
+      int fActive = LOWORD(wParam);\r
+      switch (fActive)\r
+      {\r
+        case WA_INACTIVE:\r
+        {\r
+          // g_FocusIndex = g_App.LastFocusedPanel;\r
+          // g_App.LastFocusedPanel = g_App.GetFocusedPanelIndex();\r
+          // return 0;\r
+        }\r
+      }\r
+      break;\r
+    }\r
+    */\r
+    /*\r
+    case kLangWasChangedMessage:\r
+      MyLoadMenu();\r
+      return 0;\r
+    */\r
+      \r
+    /*\r
+    case WM_SETTINGCHANGE:\r
+      break;\r
+    */\r
+    case WM_NOTIFY:\r
+    {\r
+      g_App.OnNotify((int)wParam, (LPNMHDR)lParam);\r
+      break;\r
+    }\r
+    /*\r
+    case WM_DROPFILES:\r
+    {\r
+      g_App.GetFocusedPanel().CompressDropFiles((HDROP)wParam);\r
+      return 0 ;\r
+    }\r
+    */\r
+  }\r
+  #ifndef _UNICODE\r
+  if (g_IsNT)\r
+    return DefWindowProcW(hWnd, message, wParam, lParam);\r
+  else\r
+  #endif\r
+    return DefWindowProc(hWnd, message, wParam, lParam);\r
+\r
+}\r
+\r
+static int Window_GetRealHeight(NWindows::CWindow &w)\r
+{\r
+  RECT rect;\r
+  w.GetWindowRect(&rect);\r
+  int res = rect.bottom - rect.top;\r
+  #ifndef UNDER_CE\r
+  WINDOWPLACEMENT placement;\r
+  if (w.GetPlacement(&placement))\r
+    res += placement.rcNormalPosition.top;\r
+  #endif\r
+  return res;\r
+}\r
+\r
+void CApp::MoveSubWindows()\r
+{\r
+  HWND hWnd = _window;\r
+  RECT rect;\r
+  if (hWnd == 0)\r
+    return;\r
+  ::GetClientRect(hWnd, &rect);\r
+  int xSize = rect.right;\r
+  if (xSize == 0)\r
+    return;\r
+  int headerSize = 0;\r
+  #ifdef UNDER_CE\r
+  _commandBar.AutoSize();\r
+  {\r
+    _commandBar.Show(true); // maybe we need it for\r
+    headerSize += _commandBar.Height();\r
+  }\r
+  #endif\r
+  if (_toolBar)\r
+  {\r
+    _toolBar.AutoSize();\r
+    #ifdef UNDER_CE\r
+    int h2 = Window_GetRealHeight(_toolBar);\r
+    _toolBar.Move(0, headerSize, xSize, h2);\r
+    #endif\r
+    headerSize += Window_GetRealHeight(_toolBar);\r
+  }\r
+  int ySize = MyMax((int)(rect.bottom - headerSize), 0);\r
+  \r
+  if (NumPanels > 1)\r
+  {\r
+    Panels[0].Move(0, headerSize, g_Splitter.GetPos(), ySize);\r
+    int xWidth1 = g_Splitter.GetPos() + kSplitterWidth;\r
+    Panels[1].Move(xWidth1, headerSize, xSize - xWidth1, ySize);\r
+  }\r
+  else\r
+  {\r
+    /*\r
+    int otherPanel = 1 - LastFocusedPanel;\r
+    if (PanelsCreated[otherPanel])\r
+      Panels[otherPanel].Move(0, headerSize, 0, ySize);\r
+    */\r
+    Panels[LastFocusedPanel].Move(0, headerSize, xSize, ySize);\r
+  }\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/FM.dsp b/CPP/7zip/UI/FileManager/FM.dsp
new file mode 100755 (executable)
index 0000000..113db8b
--- /dev/null
@@ -0,0 +1,1576 @@
+# Microsoft Developer Studio Project File - Name="FM" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Application" 0x0101\r
+\r
+CFG=FM - Win32 DebugU\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "FM.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "FM.mak" CFG="FM - Win32 DebugU"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "FM - Win32 Release" (based on "Win32 (x86) Application")\r
+!MESSAGE "FM - Win32 Debug" (based on "Win32 (x86) Application")\r
+!MESSAGE "FM - Win32 ReleaseU" (based on "Win32 (x86) Application")\r
+!MESSAGE "FM - Win32 DebugU" (based on "Win32 (x86) Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+MTL=midl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "FM - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c\r
+# 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\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /opt:NOWIN98\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c\r
+# 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\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /pdbtype:sept\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 ReleaseU"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "ReleaseU"\r
+# PROP BASE Intermediate_Dir "ReleaseU"\r
+# PROP BASE Ignore_Export_Lib 0\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "ReleaseU"\r
+# PROP Intermediate_Dir "ReleaseU"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /c\r
+# 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\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /opt:NOWIN98\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 DebugU"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "DebugU"\r
+# PROP BASE Intermediate_Dir "DebugU"\r
+# PROP BASE Ignore_Export_Lib 0\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "DebugU"\r
+# PROP Intermediate_Dir "DebugU"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c\r
+# 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\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "FM - Win32 Release"\r
+# Name "FM - Win32 Debug"\r
+# Name "FM - Win32 ReleaseU"\r
+# Name "FM - Win32 DebugU"\r
+# Begin Group "Spec"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\7zipLogo.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\add.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ClassDefs.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Copy.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Delete.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Extract.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\FM.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Move.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Parent.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Properties.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\resource.rc\r
+# ADD BASE RSC /l 0x419\r
+# ADD RSC /l 0x409\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.cpp\r
+# ADD CPP /Yc"StdAfx.h"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Test.bmp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Archive"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\IArchive.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Folders"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\FSDrives.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\FSDrives.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\FSFolder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\FSFolder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\FSFolderCopy.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\IFolder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\NetFolder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\NetFolder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\RootFolder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\RootFolder.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Registry"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\RegistryAssociations.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\RegistryAssociations.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\RegistryPlugins.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\RegistryPlugins.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\RegistryUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\RegistryUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ViewSettings.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ViewSettings.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Panel"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\App.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\App.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\AppState.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\EnumFormatEtc.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\EnumFormatEtc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\FileFolderPluginOpen.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\FileFolderPluginOpen.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Panel.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Panel.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PanelCopy.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PanelCrc.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PanelDrag.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PanelFolderChange.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PanelItemOpen.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PanelItems.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PanelKey.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PanelListNotify.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PanelMenu.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PanelOperations.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PanelSelect.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PanelSort.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PanelSplitFile.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Dialog"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "Options"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\EditPage.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\EditPage.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\FoldersPage.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\FoldersPage.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\LangPage.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\LangPage.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\MenuPage.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\MenuPage.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\OptionsDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\SettingsPage.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\SettingsPage.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\SystemPage.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\SystemPage.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=.\AboutDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\AboutDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\BrowseDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\BrowseDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ComboDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ComboDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=CopyDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=CopyDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\DialogSize.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ListViewDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ListViewDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=MessagesDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=MessagesDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=OverwriteDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=OverwriteDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PasswordDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PasswordDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ProgressDialog2.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ProgressDialog2.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\SplitDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\SplitDialog.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "FM Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\ExtractCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ExtractCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\FormatUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\FormatUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\HelpUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\HelpUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\LangUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\LangUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ProgramLocation.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ProgramLocation.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\UpdateCallback100.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\UpdateCallback100.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "7-Zip Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilePathAutoRename.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilePathAutoRename.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamObjects.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamObjects.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "C"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrcOpt.c\r
+\r
+!IF  "$(CFG)" == "FM - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 ReleaseU"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.c\r
+\r
+!IF  "$(CFG)" == "FM - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 ReleaseU"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sha256.c\r
+\r
+!IF  "$(CFG)" == "FM - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "FM - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sha256.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sort.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Sort.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Windows"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "Control"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ComboBox.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ComboBox.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\CommandBar.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Dialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Dialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Edit.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ImageList.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ListView.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ListView.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ProgressBar.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\PropertyPage.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\PropertyPage.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ReBar.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Static.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\StatusBar.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ToolBar.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Trackbar.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Window2.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Window2.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Clipboard.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Clipboard.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\COM.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\CommonDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\CommonDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Defs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Device.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileMapping.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileSystem.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileSystem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Handle.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Memory.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Memory.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\MemoryLock.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\MemoryLock.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Menu.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Menu.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Net.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Net.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Process.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Process.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantConversions.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantConversions.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Registry.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Registry.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\ResourceString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\ResourceString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Security.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Security.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Shell.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Shell.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Thread.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Time.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Time.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Timer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Window.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Window.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Buffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\ComTry.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Defs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\DynamicBuffer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Exception.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Lang.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Lang.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyCom.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Random.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Random.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringToInt.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringToInt.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\TextConfig.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\TextConfig.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Types.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\UTFConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\UTFConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "UI"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "UI Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveExtractCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveExtractCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveOpenCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveOpenCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\CompressCall.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\CompressCall.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\DefaultName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\DefaultName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\DirItem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\EnumDirItems.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\EnumDirItems.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ExitCode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ExtractingFilePath.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ExtractingFilePath.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ExtractMode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\IFileExtractCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\LoadCodecs.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\LoadCodecs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\OpenArchive.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\OpenArchive.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\Property.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\PropIDUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\PropIDUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\SortUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\SortUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\StdAfx.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateAction.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateAction.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdatePair.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdatePair.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateProduce.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateProduce.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\WorkDir.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\WorkDir.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ZipRegistry.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ZipRegistry.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Agent"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\Agent\Agent.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Agent\Agent.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Agent\AgentOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Agent\AgentProxy.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Agent\AgentProxy.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Agent\ArchiveFolder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Agent\ArchiveFolderOpen.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Agent\ArchiveFolderOut.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Agent\IFolderArchive.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Agent\UpdateCallbackAgent.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Agent\UpdateCallbackAgent.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Explorer"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\Explorer\ContextMenu.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Explorer\ContextMenu.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Explorer\RegistryContextMenu.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Explorer\RegistryContextMenu.h\r
+# End Source File\r
+# End Group\r
+# End Group\r
+# Begin Group "Compress"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyCoder.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Interface"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\ICoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\IDecl.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\IPassword.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\IProgress.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=.\7zFM.exe.manifest\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\7zipLogo.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Add2.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Copy2.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Delete2.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Extract2.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\FilePlugins.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\FilePlugins.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\FM.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Info.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Info2.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Move2.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\MyCom2.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\MyLoadMenu.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\MyLoadMenu.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\OpenCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\OpenCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PluginInterface.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PluginLoader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PropertyName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\PropertyName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\resource.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\SplitUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\SplitUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StringUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StringUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\SysIconUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\SysIconUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\Test2.bmp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\TextPairs.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\TextPairs.h\r
+# End Source File\r
+# End Target\r
+# End Project\r
diff --git a/CPP/7zip/UI/FileManager/FM.dsw b/CPP/7zip/UI/FileManager/FM.dsw
new file mode 100755 (executable)
index 0000000..38f65d2
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "FM"=.\FM.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/CPP/7zip/UI/FileManager/FM.ico b/CPP/7zip/UI/FileManager/FM.ico
new file mode 100755 (executable)
index 0000000..3a0a34d
Binary files /dev/null and b/CPP/7zip/UI/FileManager/FM.ico differ
diff --git a/CPP/7zip/UI/FileManager/FSDrives.cpp b/CPP/7zip/UI/FileManager/FSDrives.cpp
new file mode 100755 (executable)
index 0000000..2daf41a
--- /dev/null
@@ -0,0 +1,420 @@
+// FSDrives.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/Alloc.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/Defs.h"\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileIO.h"\r
+#include "Windows/FileSystem.h"\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../../PropID.h"\r
+\r
+#include "FSDrives.h"\r
+#include "FSFolder.h"\r
+#include "LangUtils.h"\r
+#include "SysIconUtils.h"\r
+\r
+#include "resource.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+using namespace NFind;\r
+\r
+static const wchar_t *kVolPrefix = L"\\\\.\\";\r
+\r
+UString CDriveInfo::GetDeviceFileIoName() const\r
+{\r
+  return kVolPrefix + Name;\r
+}\r
+\r
+struct CPhysTempBuffer\r
+{\r
+  void *buffer;\r
+  CPhysTempBuffer(): buffer(0) {}\r
+  ~CPhysTempBuffer() { MidFree(buffer); }\r
+};\r
+\r
+static HRESULT CopyFileSpec(LPCWSTR fromPath, LPCWSTR toPath, bool writeToDisk, UInt64 fileSize,\r
+    UInt32 bufferSize, UInt64 progressStart, IProgress *progress)\r
+{\r
+  NFile::NIO::CInFile inFile;\r
+  if (!inFile.Open(fromPath))\r
+    return GetLastError();\r
+  if (fileSize == (UInt64)(Int64)-1)\r
+  {\r
+    if (!inFile.GetLength(fileSize))\r
+      ::GetLastError();\r
+  }\r
+  NFile::NIO::COutFile outFile;\r
+  if (writeToDisk)\r
+  {\r
+    if (!outFile.Open(toPath, FILE_SHARE_WRITE, OPEN_EXISTING, 0))\r
+      return GetLastError();\r
+  }\r
+  else\r
+    if (!outFile.Create(toPath, true))\r
+      return GetLastError();\r
+  CPhysTempBuffer tempBuffer;\r
+  tempBuffer.buffer = MidAlloc(bufferSize);\r
+  if (tempBuffer.buffer == 0)\r
+    return E_OUTOFMEMORY;\r
\r
+  for (UInt64 pos = 0; pos < fileSize;)\r
+  {\r
+    UInt64 progressCur = progressStart + pos;\r
+    RINOK(progress->SetCompleted(&progressCur));\r
+    UInt64 rem = fileSize - pos;\r
+    UInt32 curSize = (UInt32)MyMin(rem, (UInt64)bufferSize);\r
+    UInt32 processedSize;\r
+    if (!inFile.Read(tempBuffer.buffer, curSize, processedSize))\r
+      return GetLastError();\r
+    if (processedSize == 0)\r
+      break;\r
+    curSize = processedSize;\r
+    if (writeToDisk)\r
+    {\r
+      const UInt32 kMask = 0x1FF;\r
+      curSize = (curSize + kMask) & ~kMask;\r
+      if (curSize > bufferSize)\r
+        return E_FAIL;\r
+    }\r
+\r
+    if (!outFile.Write(tempBuffer.buffer, curSize, processedSize))\r
+      return GetLastError();\r
+    if (curSize != processedSize)\r
+      return E_FAIL;\r
+    pos += curSize;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+static const STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidName, VT_BSTR},\r
+  { NULL, kpidTotalSize, VT_UI8},\r
+  { NULL, kpidFreeSpace, VT_UI8},\r
+  { NULL, kpidType, VT_BSTR},\r
+  { NULL, kpidVolumeName, VT_BSTR},\r
+  { NULL, kpidFileSystem, VT_BSTR},\r
+  { NULL, kpidClusterSize, VT_UI8}\r
+};\r
+\r
+static const char *kDriveTypes[] =\r
+{\r
+  "Unknown",\r
+  "No Root Dir",\r
+  "Removable",\r
+  "Fixed",\r
+  "Remote",\r
+  "CD-ROM",\r
+  "RAM disk"\r
+};\r
+\r
+STDMETHODIMP CFSDrives::LoadItems()\r
+{\r
+  _drives.Clear();\r
+\r
+  UStringVector driveStrings;\r
+  MyGetLogicalDriveStrings(driveStrings);\r
+  for (int i = 0; i < driveStrings.Size(); i++)\r
+  {\r
+    CDriveInfo di;\r
+\r
+    const UString &driveName = driveStrings[i];\r
+\r
+    di.FullSystemName = driveName;\r
+\r
+    di.Name = di.FullSystemName.Left(di.FullSystemName.Length() - 1);\r
+    di.ClusterSize = 0;\r
+    di.DriveSize = 0;\r
+    di.FreeSpace = 0;\r
+    di.DriveType = NFile::NSystem::MyGetDriveType(driveName);\r
+    bool needRead = true;\r
+    if (di.DriveType == DRIVE_CDROM || di.DriveType == DRIVE_REMOVABLE)\r
+    {\r
+      /*\r
+      DWORD dwSerialNumber;`\r
+      if (!::GetVolumeInformation(di.FullSystemName,\r
+          NULL, 0, &dwSerialNumber, NULL, NULL, NULL, 0))\r
+      */\r
+      di.KnownSizes = false;\r
+      {\r
+        needRead = false;\r
+      }\r
+    }\r
+    if (needRead)\r
+    {\r
+      UString volumeName, fileSystemName;\r
+      DWORD volumeSerialNumber, maximumComponentLength, fileSystemFlags;\r
+      NFile::NSystem::MyGetVolumeInformation(driveName,\r
+          volumeName,\r
+          &volumeSerialNumber, &maximumComponentLength, &fileSystemFlags,\r
+          fileSystemName);\r
+      di.VolumeName = volumeName;\r
+      di.FileSystemName = fileSystemName;\r
+\r
+      NFile::NSystem::MyGetDiskFreeSpace(driveName,\r
+          di.ClusterSize, di.DriveSize, di.FreeSpace);\r
+      di.KnownSizes = true;\r
+    }\r
+    _drives.Add(di);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFSDrives::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _drives.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFSDrives::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value)\r
+{\r
+  if (itemIndex >= (UInt32)_drives.Size())\r
+    return E_INVALIDARG;\r
+  NCOM::CPropVariant prop;\r
+  const CDriveInfo &di = _drives[itemIndex];\r
+  switch(propID)\r
+  {\r
+    case kpidIsDir:  prop = !_volumeMode; break;\r
+    case kpidName:  prop = di.Name; break;\r
+    case kpidTotalSize:   if (di.KnownSizes) prop = di.DriveSize; break;\r
+    case kpidFreeSpace:   if (di.KnownSizes) prop = di.FreeSpace; break;\r
+    case kpidClusterSize: if (di.KnownSizes) prop = di.ClusterSize; break;\r
+    case kpidType:\r
+      if (di.DriveType < sizeof(kDriveTypes) / sizeof(kDriveTypes[0]))\r
+        prop = kDriveTypes[di.DriveType];\r
+      break;\r
+    case kpidVolumeName:  prop = di.VolumeName; break;\r
+    case kpidFileSystem:  prop = di.FileSystemName; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CFSDrives::BindToFolderSpec(const wchar_t *name, IFolderFolder **resultFolder)\r
+{\r
+  *resultFolder = 0;\r
+  if (_volumeMode)\r
+    return S_OK;\r
+  NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;\r
+  CMyComPtr<IFolderFolder> subFolder = fsFolderSpec;\r
+  RINOK(fsFolderSpec->Init(name, 0));\r
+  *resultFolder = subFolder.Detach();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFSDrives::BindToFolder(UInt32 index, IFolderFolder **resultFolder)\r
+{\r
+  *resultFolder = 0;\r
+  if (index >= (UInt32)_drives.Size())\r
+    return E_INVALIDARG;\r
+  const CDriveInfo &di = _drives[index];\r
+  /*\r
+  if (_volumeMode)\r
+  {\r
+    *resultFolder = 0;\r
+    CPhysDriveFolder *folderSpec = new CPhysDriveFolder;\r
+    CMyComPtr<IFolderFolder> subFolder = folderSpec;\r
+    RINOK(folderSpec->Init(di.Name));\r
+    *resultFolder = subFolder.Detach();\r
+    return S_OK;\r
+  }\r
+  */\r
+  return BindToFolderSpec(di.FullSystemName, resultFolder);\r
+}\r
+\r
+STDMETHODIMP CFSDrives::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder)\r
+{\r
+  return BindToFolderSpec(name, resultFolder);\r
+}\r
+\r
+STDMETHODIMP CFSDrives::BindToParentFolder(IFolderFolder **resultFolder)\r
+{\r
+  *resultFolder = 0;\r
+  return S_OK;\r
+}\r
+\r
+IMP_IFolderFolder_Props(CFSDrives)\r
+\r
+STDMETHODIMP CFSDrives::GetFolderProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidType: prop = L"FSDrives"; break;\r
+    case kpidPath:\r
+      if (_volumeMode)\r
+        prop = kVolPrefix;\r
+      else\r
+        prop = LangString(IDS_COMPUTER, 0x03020300) + UString(WCHAR_PATH_SEPARATOR);\r
+      break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+\r
+STDMETHODIMP CFSDrives::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)\r
+{\r
+  *iconIndex = 0;\r
+  const CDriveInfo &di = _drives[index];\r
+  int iconIndexTemp;\r
+  if (GetRealIconIndex(di.FullSystemName, 0, iconIndexTemp) != 0)\r
+  {\r
+    *iconIndex = iconIndexTemp;\r
+    return S_OK;\r
+  }\r
+  return GetLastError();\r
+}\r
+\r
+UString CFSDrives::GetExt(int index) const\r
+{\r
+  const CDriveInfo &di = _drives[index];\r
+  const wchar_t *ext = NULL;\r
+  if (di.DriveType == DRIVE_CDROM)\r
+    ext = L"iso";\r
+  else if (di.FileSystemName.Find(L"NTFS") >= 0)\r
+    ext = L"ntfs";\r
+  else if (di.FileSystemName.Find(L"FAT") >= 0)\r
+    ext = L"fat";\r
+  else\r
+    ext = L"img";\r
+  return (UString)L'.' + ext;\r
+}\r
+\r
+HRESULT CFSDrives::GetLength(int index, UInt64 &length) const\r
+{\r
+  NFile::NIO::CInFile inFile;\r
+  if (!inFile.Open(_drives[index].GetDeviceFileIoName()))\r
+    return GetLastError();\r
+  if (!inFile.LengthDefined)\r
+    return E_FAIL;\r
+  length = inFile.Length;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFSDrives::CopyTo(const UInt32 *indices, UInt32 numItems,\r
+    const wchar_t *path, IFolderOperationsExtractCallback *callback)\r
+{\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  \r
+  if (!_volumeMode)\r
+    return E_NOTIMPL;\r
+\r
+  UInt64 totalSize = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    const CDriveInfo &di = _drives[indices[i]];\r
+    if (di.KnownSizes)\r
+      totalSize += di.DriveSize;\r
+  }\r
+  RINOK(callback->SetTotal(totalSize));\r
+  RINOK(callback->SetNumFiles(numItems));\r
+  \r
+  UString destPath = path;\r
+  if (destPath.IsEmpty())\r
+    return E_INVALIDARG;\r
+  bool directName = (destPath[destPath.Length() - 1] != WCHAR_PATH_SEPARATOR);\r
+  if (directName)\r
+  {\r
+    if (numItems > 1)\r
+      return E_INVALIDARG;\r
+  }\r
+\r
+  UInt64 completedSize = 0;\r
+  RINOK(callback->SetCompleted(&completedSize));\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    int index = indices[i];\r
+    const CDriveInfo &di = _drives[index];\r
+    UString destPath2 = destPath;\r
+    UString name = di.Name;\r
+    if (!directName)\r
+    {\r
+      UString destName = name;\r
+      if (!destName.IsEmpty() && destName[destName.Length() - 1] == L':')\r
+      {\r
+        destName.Delete(destName.Length() - 1);\r
+        destName += GetExt(index);\r
+      }\r
+      destPath2 += destName;\r
+    }\r
+    UString srcPath = di.GetDeviceFileIoName();\r
+\r
+    UInt64 fileSize = 0;\r
+    if (GetLength(index, fileSize) != S_OK)\r
+    {\r
+      return E_FAIL;\r
+    }\r
+    if (!di.KnownSizes)\r
+      totalSize += fileSize;\r
+    RINOK(callback->SetTotal(totalSize));\r
+    \r
+    Int32 writeAskResult;\r
+    CMyComBSTR destPathResult;\r
+    RINOK(callback->AskWrite(srcPath, BoolToInt(false), NULL, &fileSize,\r
+      destPath2, &destPathResult, &writeAskResult));\r
+    if (!IntToBool(writeAskResult))\r
+      continue;\r
+    \r
+    RINOK(callback->SetCurrentFilePath(srcPath));\r
+    \r
+    static const UInt32 kBufferSize = (4 << 20);\r
+    UInt32 bufferSize = (di.DriveType == DRIVE_REMOVABLE) ? (18 << 10) * 4 : kBufferSize;\r
+    RINOK(CopyFileSpec(srcPath, destPathResult, false, fileSize, bufferSize, completedSize, callback));\r
+    completedSize += fileSize;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFSDrives::MoveTo(\r
+    const UInt32 * /* indices */,\r
+    UInt32 /* numItems */,\r
+    const wchar_t * /* path */,\r
+    IFolderOperationsExtractCallback * /* callback */)\r
+{\r
+  return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CFSDrives::CopyFrom(const wchar_t * /* fromFolderPath */,\r
+    const wchar_t ** /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */)\r
+{\r
+  return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CFSDrives::CreateFolder(const wchar_t * /* name */, IProgress * /* progress */)\r
+{\r
+  return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CFSDrives::CreateFile(const wchar_t * /* name */, IProgress * /* progress */)\r
+{\r
+  return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CFSDrives::Rename(UInt32 /* index */, const wchar_t * /* newName */, IProgress * /* progress */)\r
+{\r
+  return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CFSDrives::Delete(const UInt32 * /* indices */, UInt32 /* numItems */, IProgress * /* progress */)\r
+{\r
+  return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CFSDrives::SetProperty(UInt32 /* index */, PROPID /* propID */,\r
+    const PROPVARIANT * /* value */, IProgress * /* progress */)\r
+{\r
+  return E_NOTIMPL;\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/FSDrives.h b/CPP/7zip/UI/FileManager/FSDrives.h
new file mode 100755 (executable)
index 0000000..8513688
--- /dev/null
@@ -0,0 +1,53 @@
+// FSDrives.h\r
+\r
+#ifndef __FS_DRIVES_H\r
+#define __FS_DRIVES_H\r
+\r
+#include "Common/MyCom.h"\r
+#include "Common/MyString.h"\r
+\r
+#include "IFolder.h"\r
+\r
+struct CDriveInfo\r
+{\r
+  UString Name;\r
+  UString FullSystemName;\r
+  bool KnownSizes;\r
+  UInt64 DriveSize;\r
+  UInt64 FreeSpace;\r
+  UInt64 ClusterSize;\r
+  // UString Type;\r
+  UString VolumeName;\r
+  UString FileSystemName;\r
+  UINT DriveType;\r
+\r
+  UString GetDeviceFileIoName() const;\r
+};\r
+\r
+class CFSDrives:\r
+  public IFolderFolder,\r
+  public IFolderOperations,\r
+  public IFolderGetSystemIconIndex,\r
+  public CMyUnknownImp\r
+{\r
+  CObjectVector<CDriveInfo> _drives;\r
+  bool _volumeMode;\r
+\r
+  HRESULT BindToFolderSpec(const wchar_t *name, IFolderFolder **resultFolder);\r
+  UString GetExt(int index) const;\r
+  HRESULT GetLength(int index, UInt64 &length) const;\r
+public:\r
+  MY_UNKNOWN_IMP2(IFolderGetSystemIconIndex, IFolderOperations)\r
+\r
+  INTERFACE_FolderFolder(;)\r
+  INTERFACE_FolderOperations(;)\r
+\r
+  STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex);\r
+\r
+  void Init(bool volMode = false)\r
+  {\r
+    _volumeMode = volMode;\r
+  }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/FSFolder.cpp b/CPP/7zip/UI/FileManager/FSFolder.cpp
new file mode 100755 (executable)
index 0000000..5664ccf
--- /dev/null
@@ -0,0 +1,665 @@
+// FSFolder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/ComTry.h"\r
+#include "Common/StringConvert.h"\r
+#include "Common/UTFConvert.h"\r
+\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileIO.h"\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../../PropID.h"\r
+\r
+#include "FSDrives.h"\r
+#include "FSFolder.h"\r
+\r
+#ifndef UNDER_CE\r
+#include "NetFolder.h"\r
+#endif\r
+\r
+#include "SysIconUtils.h"\r
+\r
+namespace NWindows {\r
+namespace NFile {\r
+\r
+bool GetLongPath(LPCWSTR path, UString &longPath);\r
+\r
+}}\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+using namespace NFind;\r
+\r
+namespace NFsFolder {\r
+\r
+static STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidName, VT_BSTR},\r
+  { NULL, kpidSize, VT_UI8},\r
+  { NULL, kpidMTime, VT_FILETIME},\r
+  { NULL, kpidCTime, VT_FILETIME},\r
+  { NULL, kpidATime, VT_FILETIME},\r
+  { NULL, kpidAttrib, VT_UI4},\r
+  { NULL, kpidPackSize, VT_UI8},\r
+  { NULL, kpidComment, VT_BSTR},\r
+  { NULL, kpidPrefix, VT_BSTR}\r
+};\r
+\r
+HRESULT CFSFolder::Init(const UString &path, IFolderFolder *parentFolder)\r
+{\r
+  _parentFolder = parentFolder;\r
+  _path = path;\r
+\r
+  _findChangeNotification.FindFirst(_path, false,\r
+      FILE_NOTIFY_CHANGE_FILE_NAME |\r
+      FILE_NOTIFY_CHANGE_DIR_NAME |\r
+      FILE_NOTIFY_CHANGE_ATTRIBUTES |\r
+      FILE_NOTIFY_CHANGE_SIZE |\r
+      FILE_NOTIFY_CHANGE_LAST_WRITE /*|\r
+      FILE_NOTIFY_CHANGE_LAST_ACCESS |\r
+      FILE_NOTIFY_CHANGE_CREATION |\r
+      FILE_NOTIFY_CHANGE_SECURITY */);\r
+  if (!_findChangeNotification.IsHandleAllocated())\r
+  {\r
+    DWORD lastError = GetLastError();\r
+    CFindFile findFile;\r
+    CFileInfoW fi;\r
+    if (!findFile.FindFirst(_path + UString(L"*"), fi))\r
+      return lastError;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT GetFolderSize(const UString &path, UInt64 &numFolders, UInt64 &numFiles, UInt64 &size, IProgress *progress)\r
+{\r
+  RINOK(progress->SetCompleted(NULL));\r
+  numFiles = numFolders = size = 0;\r
+  CEnumeratorW enumerator(path + UString(WSTRING_PATH_SEPARATOR L"*"));\r
+  CFileInfoW fi;\r
+  while (enumerator.Next(fi))\r
+  {\r
+    if (fi.IsDir())\r
+    {\r
+      UInt64 subFolders, subFiles, subSize;\r
+      RINOK(GetFolderSize(path + UString(WCHAR_PATH_SEPARATOR) + fi.Name, subFolders, subFiles, subSize, progress));\r
+      numFolders += subFolders;\r
+      numFolders++;\r
+      numFiles += subFiles;\r
+      size += subSize;\r
+    }\r
+    else\r
+    {\r
+      numFiles++;\r
+      size += fi.Size;\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CFSFolder::LoadSubItems(CDirItem &dirItem, const UString &path)\r
+{\r
+  {\r
+    CEnumeratorW enumerator(path + L"*");\r
+    CDirItem fi;\r
+    while (enumerator.Next(fi))\r
+    {\r
+      #ifndef UNDER_CE\r
+      fi.CompressedSizeIsDefined = false;\r
+      /*\r
+      if (!GetCompressedFileSize(_path + fi.Name,\r
+      fi.CompressedSize))\r
+      fi.CompressedSize = fi.Size;\r
+      */\r
+      #endif\r
+      if (fi.IsDir())\r
+      {\r
+        // fi.Size = GetFolderSize(_path + fi.Name);\r
+        fi.Size = 0;\r
+      }\r
+      dirItem.Files.Add(fi);\r
+    }\r
+  }\r
+  if (!_flatMode)\r
+    return S_OK;\r
+\r
+  for (int i = 0; i < dirItem.Files.Size(); i++)\r
+  {\r
+    CDirItem &item = dirItem.Files[i];\r
+    if (item.IsDir())\r
+      LoadSubItems(item, path + item.Name + WCHAR_PATH_SEPARATOR);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+void CFSFolder::AddRefs(CDirItem &dirItem)\r
+{\r
+  int i;\r
+  for (i = 0; i < dirItem.Files.Size(); i++)\r
+  {\r
+    CDirItem &item = dirItem.Files[i];\r
+    item.Parent = &dirItem;\r
+    _refs.Add(&item);\r
+  }\r
+  if (!_flatMode)\r
+    return;\r
+  for (i = 0; i < dirItem.Files.Size(); i++)\r
+  {\r
+    CDirItem &item = dirItem.Files[i];\r
+    if (item.IsDir())\r
+      AddRefs(item);\r
+  }\r
+}\r
+\r
+STDMETHODIMP CFSFolder::LoadItems()\r
+{\r
+  // OutputDebugString(TEXT("Start\n"));\r
+  Int32 dummy;\r
+  WasChanged(&dummy);\r
+  Clear();\r
+  RINOK(LoadSubItems(_root, _path));\r
+  AddRefs(_root);\r
+\r
+  // OutputDebugString(TEXT("Finish\n"));\r
+  _commentsAreLoaded = false;\r
+  return S_OK;\r
+}\r
+\r
+static const wchar_t *kDescriptionFileName = L"descript.ion";\r
+\r
+bool CFSFolder::LoadComments()\r
+{\r
+  if (_commentsAreLoaded)\r
+    return true;\r
+  _comments.Clear();\r
+  _commentsAreLoaded = true;\r
+  NIO::CInFile file;\r
+  if (!file.Open(_path + kDescriptionFileName))\r
+    return false;\r
+  UInt64 length;\r
+  if (!file.GetLength(length))\r
+    return false;\r
+  if (length >= (1 << 28))\r
+    return false;\r
+  AString s;\r
+  char *p = s.GetBuffer((int)((size_t)length + 1));\r
+  UInt32 processedSize;\r
+  file.Read(p, (UInt32)length, processedSize);\r
+  p[length] = 0;\r
+  s.ReleaseBuffer();\r
+  if (processedSize != length)\r
+    return false;\r
+  file.Close();\r
+  UString unicodeString;\r
+  if (!ConvertUTF8ToUnicode(s, unicodeString))\r
+    return false;\r
+  return _comments.ReadFromString(unicodeString);\r
+}\r
+\r
+static bool IsAscii(const UString &testString)\r
+{\r
+  for (int i = 0; i < testString.Length(); i++)\r
+    if (testString[i] >= 0x80)\r
+      return false;\r
+  return true;\r
+}\r
+\r
+bool CFSFolder::SaveComments()\r
+{\r
+  NIO::COutFile file;\r
+  if (!file.Create(_path + kDescriptionFileName, true))\r
+    return false;\r
+  UString unicodeString;\r
+  _comments.SaveToString(unicodeString);\r
+  AString utfString;\r
+  ConvertUnicodeToUTF8(unicodeString, utfString);\r
+  UInt32 processedSize;\r
+  if (!IsAscii(unicodeString))\r
+  {\r
+    Byte bom [] = { 0xEF, 0xBB, 0xBF, 0x0D, 0x0A };\r
+    file.Write(bom , sizeof(bom), processedSize);\r
+  }\r
+  file.Write(utfString, utfString.Length(), processedSize);\r
+  _commentsAreLoaded = false;\r
+  return true;\r
+}\r
+\r
+STDMETHODIMP CFSFolder::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _refs.Size();\r
+  return S_OK;\r
+}\r
+\r
+/*\r
+STDMETHODIMP CFSFolder::GetNumberOfSubFolders(UInt32 *numSubFolders)\r
+{\r
+  UInt32 numSubFoldersLoc = 0;\r
+  for (int i = 0; i < _files.Size(); i++)\r
+    if (_files[i].IsDir())\r
+      numSubFoldersLoc++;\r
+  *numSubFolders = numSubFoldersLoc;\r
+  return S_OK;\r
+}\r
+*/\r
+\r
+#ifndef UNDER_CE\r
+static bool MyGetCompressedFileSizeW(LPCWSTR fileName, UInt64 &size)\r
+{\r
+  DWORD highPart;\r
+  DWORD lowPart = ::GetCompressedFileSizeW(fileName, &highPart);\r
+  if (lowPart == INVALID_FILE_SIZE && ::GetLastError() != NO_ERROR)\r
+  {\r
+    #ifdef WIN_LONG_PATH\r
+    {\r
+      UString longPath;\r
+      if (GetLongPath(fileName, longPath))\r
+        lowPart = ::GetCompressedFileSizeW(longPath, &highPart);\r
+    }\r
+    #endif\r
+    if (lowPart == INVALID_FILE_SIZE && ::GetLastError() != NO_ERROR)\r
+      return false;\r
+  }\r
+  size = (UInt64(highPart) << 32) | lowPart;\r
+  return true;\r
+}\r
+#endif\r
+\r
+STDMETHODIMP CFSFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  if (itemIndex >= (UInt32)_refs.Size())\r
+    return E_INVALIDARG;\r
+  CDirItem &fi = *_refs[itemIndex];\r
+  switch(propID)\r
+  {\r
+    case kpidIsDir: prop = fi.IsDir(); break;\r
+    case kpidName: prop = fi.Name; break;\r
+    case kpidSize: if (!fi.IsDir()) prop = fi.Size; break;\r
+    case kpidPackSize:\r
+      #ifdef UNDER_CE\r
+      prop = fi.Size;\r
+      #else\r
+      if (!fi.CompressedSizeIsDefined)\r
+      {\r
+        fi.CompressedSizeIsDefined = true;\r
+        if (fi.IsDir () ||\r
+            !MyGetCompressedFileSizeW(_path + GetRelPath(fi), fi.CompressedSize))\r
+          fi.CompressedSize = fi.Size;\r
+      }\r
+      prop = fi.CompressedSize;\r
+      #endif\r
+      break;\r
+    case kpidAttrib: prop = (UInt32)fi.Attrib; break;\r
+    case kpidCTime: prop = fi.CTime; break;\r
+    case kpidATime: prop = fi.ATime; break;\r
+    case kpidMTime: prop = fi.MTime; break;\r
+    case kpidComment:\r
+    {\r
+      LoadComments();\r
+      UString comment;\r
+      if (_comments.GetValue(GetRelPath(fi), comment))\r
+        prop = comment;\r
+      break;\r
+    }\r
+    case kpidPrefix:\r
+    {\r
+      if (_flatMode)\r
+        prop = GetPrefix(fi);\r
+      break;\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CFSFolder::BindToFolderSpec(const wchar_t *name, IFolderFolder **resultFolder)\r
+{\r
+  *resultFolder = 0;\r
+  CFSFolder *folderSpec = new CFSFolder;\r
+  CMyComPtr<IFolderFolder> subFolder = folderSpec;\r
+  RINOK(folderSpec->Init(_path + name + UString(WCHAR_PATH_SEPARATOR), 0));\r
+  *resultFolder = subFolder.Detach();\r
+  return S_OK;\r
+}\r
+\r
+UString CFSFolder::GetPrefix(const CDirItem &item) const\r
+{\r
+  UString path;\r
+  CDirItem *cur = item.Parent;\r
+  while (cur->Parent != 0)\r
+  {\r
+    path = cur->Name + UString(WCHAR_PATH_SEPARATOR) + path;\r
+    cur = cur->Parent;\r
+  }\r
+  return path;\r
+}\r
+\r
+UString CFSFolder::GetRelPath(const CDirItem &item) const\r
+{\r
+  return GetPrefix(item) + item.Name;\r
+}\r
+\r
+STDMETHODIMP CFSFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder)\r
+{\r
+  *resultFolder = 0;\r
+  const CDirItem &fi = *_refs[index];\r
+  if (!fi.IsDir())\r
+    return E_INVALIDARG;\r
+  return BindToFolderSpec(GetRelPath(fi), resultFolder);\r
+}\r
+\r
+STDMETHODIMP CFSFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder)\r
+{\r
+  return BindToFolderSpec(name, resultFolder);\r
+}\r
+\r
+STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder)\r
+{\r
+  *resultFolder = 0;\r
+  if (_parentFolder)\r
+  {\r
+    CMyComPtr<IFolderFolder> parentFolder = _parentFolder;\r
+    *resultFolder = parentFolder.Detach();\r
+    return S_OK;\r
+  }\r
+  if (_path.IsEmpty())\r
+    return E_INVALIDARG;\r
+  int pos = _path.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+  if (pos < 0 || pos != _path.Length() - 1)\r
+    return E_FAIL;\r
+  UString parentPath = _path.Left(pos);\r
+  pos = parentPath.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+  if (pos < 0)\r
+  {\r
+    #ifdef UNDER_CE\r
+    *resultFolder = 0;\r
+    #else\r
+    CFSDrives *drivesFolderSpec = new CFSDrives;\r
+    CMyComPtr<IFolderFolder> drivesFolder = drivesFolderSpec;\r
+    drivesFolderSpec->Init();\r
+    *resultFolder = drivesFolder.Detach();\r
+    #endif\r
+    return S_OK;\r
+  }\r
+  UString parentPathReduced = parentPath.Left(pos);\r
+  parentPath = parentPath.Left(pos + 1);\r
+  #ifndef UNDER_CE\r
+  pos = parentPathReduced.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+  if (pos == 1)\r
+  {\r
+    if (parentPath[0] != WCHAR_PATH_SEPARATOR)\r
+      return E_FAIL;\r
+    CNetFolder *netFolderSpec = new CNetFolder;\r
+    CMyComPtr<IFolderFolder> netFolder = netFolderSpec;\r
+    netFolderSpec->Init(parentPath);\r
+    *resultFolder = netFolder.Detach();\r
+    return S_OK;\r
+  }\r
+  #endif\r
+  CFSFolder *parentFolderSpec = new CFSFolder;\r
+  CMyComPtr<IFolderFolder> parentFolder = parentFolderSpec;\r
+  RINOK(parentFolderSpec->Init(parentPath, 0));\r
+  *resultFolder = parentFolder.Detach();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFSFolder::GetNumberOfProperties(UInt32 *numProperties)\r
+{\r
+  *numProperties = sizeof(kProps) / sizeof(kProps[0]);\r
+  if (!_flatMode)\r
+    (*numProperties)--;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFSFolder::GetPropertyInfo IMP_IFolderFolder_GetProp(kProps)\r
+\r
+STDMETHODIMP CFSFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  COM_TRY_BEGIN\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidType: prop = L"FSFolder"; break;\r
+    case kpidPath: prop = _path; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+  COM_TRY_END\r
+}\r
+\r
+STDMETHODIMP CFSFolder::WasChanged(Int32 *wasChanged)\r
+{\r
+  bool wasChangedMain = false;\r
+  for (;;)\r
+  {\r
+    if (!_findChangeNotification.IsHandleAllocated())\r
+    {\r
+      *wasChanged = BoolToInt(false);\r
+      return S_OK;\r
+    }\r
+\r
+    DWORD waitResult = ::WaitForSingleObject(_findChangeNotification, 0);\r
+    bool wasChangedLoc = (waitResult == WAIT_OBJECT_0);\r
+    if (wasChangedLoc)\r
+    {\r
+      _findChangeNotification.FindNext();\r
+      wasChangedMain = true;\r
+    }\r
+    else\r
+      break;\r
+  }\r
+  *wasChanged = BoolToInt(wasChangedMain);\r
+  return S_OK;\r
+}\r
\r
+STDMETHODIMP CFSFolder::Clone(IFolderFolder **resultFolder)\r
+{\r
+  CFSFolder *fsFolderSpec = new CFSFolder;\r
+  CMyComPtr<IFolderFolder> folderNew = fsFolderSpec;\r
+  fsFolderSpec->Init(_path, 0);\r
+  *resultFolder = folderNew.Detach();\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CFSFolder::GetItemsFullSize(const UInt32 *indices, UInt32 numItems,\r
+    UInt64 &numFolders, UInt64 &numFiles, UInt64 &size, IProgress *progress)\r
+{\r
+  numFiles = numFolders = size = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    int index = indices[i];\r
+    if (index >= _refs.Size())\r
+      return E_INVALIDARG;\r
+    const CDirItem &fi = *_refs[index];\r
+    if (fi.IsDir())\r
+    {\r
+      UInt64 subFolders, subFiles, subSize;\r
+      RINOK(GetFolderSize(_path + GetRelPath(fi), subFolders, subFiles, subSize, progress));\r
+      numFolders += subFolders;\r
+      numFolders++;\r
+      numFiles += subFiles;\r
+      size += subSize;\r
+    }\r
+    else\r
+    {\r
+      numFiles++;\r
+      size += fi.Size;\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CFSFolder::GetItemFullSize(int index, UInt64 &size, IProgress *progress)\r
+{\r
+  const CDirItem &fi = *_refs[index];\r
+  if (fi.IsDir())\r
+  {\r
+    /*\r
+    CMyComPtr<IFolderFolder> subFolder;\r
+    RINOK(BindToFolder(index, &subFolder));\r
+    CMyComPtr<IFolderReload> aFolderReload;\r
+    subFolder.QueryInterface(&aFolderReload);\r
+    aFolderReload->Reload();\r
+    UInt32 numItems;\r
+    RINOK(subFolder->GetNumberOfItems(&numItems));\r
+    CMyComPtr<IFolderGetItemFullSize> aGetItemFullSize;\r
+    subFolder.QueryInterface(&aGetItemFullSize);\r
+    for (UInt32 i = 0; i < numItems; i++)\r
+    {\r
+      UInt64 size;\r
+      RINOK(aGetItemFullSize->GetItemFullSize(i, &size));\r
+      *totalSize += size;\r
+    }\r
+    */\r
+    UInt64 numFolders, numFiles;\r
+    return GetFolderSize(_path + GetRelPath(fi), numFolders, numFiles, size, progress);\r
+  }\r
+  size = fi.Size;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFSFolder::GetItemFullSize(UInt32 index, PROPVARIANT *value, IProgress *progress)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  if (index >= (UInt32)_refs.Size())\r
+    return E_INVALIDARG;\r
+  UInt64 size = 0;\r
+  HRESULT result = GetItemFullSize(index, size, progress);\r
+  prop = size;\r
+  prop.Detach(value);\r
+  return result;\r
+}\r
+\r
+HRESULT CFSFolder::GetComplexName(const wchar_t *name, UString &resultPath)\r
+{\r
+  UString newName = name;\r
+  resultPath = _path + newName;\r
+  if (newName.Length() < 1)\r
+    return S_OK;\r
+  if (newName[0] == WCHAR_PATH_SEPARATOR)\r
+  {\r
+    resultPath = newName;\r
+    return S_OK;\r
+  }\r
+  if (newName.Length() < 2)\r
+    return S_OK;\r
+  if (newName[1] == L':')\r
+    resultPath = newName;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFSFolder::CreateFolder(const wchar_t *name, IProgress * /* progress */)\r
+{\r
+  UString processedName;\r
+  RINOK(GetComplexName(name, processedName));\r
+  if(NDirectory::MyCreateDirectory(processedName))\r
+    return S_OK;\r
+  if(::GetLastError() == ERROR_ALREADY_EXISTS)\r
+    return ::GetLastError();\r
+  if (!NDirectory::CreateComplexDirectory(processedName))\r
+    return ::GetLastError();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFSFolder::CreateFile(const wchar_t *name, IProgress * /* progress */)\r
+{\r
+  UString processedName;\r
+  RINOK(GetComplexName(name, processedName));\r
+  NIO::COutFile outFile;\r
+  if (!outFile.Create(processedName, false))\r
+    return ::GetLastError();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFSFolder::Rename(UInt32 index, const wchar_t *newName, IProgress * /* progress */)\r
+{\r
+  const CDirItem &fi = *_refs[index];\r
+  const UString fullPrefix = _path + GetPrefix(fi);\r
+  if (!NDirectory::MyMoveFile(fullPrefix + fi.Name, fullPrefix + newName))\r
+    return GetLastError();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFSFolder::Delete(const UInt32 *indices, UInt32 numItems,IProgress *progress)\r
+{\r
+  RINOK(progress->SetTotal(numItems));\r
+  for (UInt32 i = 0; i < numItems; i++)\r
+  {\r
+    const CDirItem &fi = *_refs[indices[i]];\r
+    const UString fullPath = _path + GetRelPath(fi);\r
+    bool result;\r
+    if (fi.IsDir())\r
+      result = NDirectory::RemoveDirectoryWithSubItems(fullPath);\r
+    else\r
+      result = NDirectory::DeleteFileAlways(fullPath);\r
+    if (!result)\r
+      return GetLastError();\r
+    UInt64 completed = i;\r
+    RINOK(progress->SetCompleted(&completed));\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFSFolder::SetProperty(UInt32 index, PROPID propID,\r
+    const PROPVARIANT *value, IProgress * /* progress */)\r
+{\r
+  if (index >= (UInt32)_refs.Size())\r
+    return E_INVALIDARG;\r
+  CDirItem &fi = *_refs[index];\r
+  if (fi.Parent->Parent != 0)\r
+    return E_NOTIMPL;\r
+  switch(propID)\r
+  {\r
+    case kpidComment:\r
+    {\r
+      UString filename = fi.Name;\r
+      filename.Trim();\r
+      if (value->vt == VT_EMPTY)\r
+        _comments.DeletePair(filename);\r
+      else if (value->vt == VT_BSTR)\r
+      {\r
+        CTextPair pair;\r
+        pair.ID = filename;\r
+        pair.ID.Trim();\r
+        pair.Value = value->bstrVal;\r
+        pair.Value.Trim();\r
+        if (pair.Value.IsEmpty())\r
+          _comments.DeletePair(filename);\r
+        else\r
+          _comments.AddPair(pair);\r
+      }\r
+      else\r
+        return E_INVALIDARG;\r
+      SaveComments();\r
+      break;\r
+    }\r
+    default:\r
+      return E_NOTIMPL;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFSFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)\r
+{\r
+  if (index >= (UInt32)_refs.Size())\r
+    return E_INVALIDARG;\r
+  const CDirItem &fi = *_refs[index];\r
+  *iconIndex = 0;\r
+  int iconIndexTemp;\r
+  if (GetRealIconIndex(_path + GetRelPath(fi), fi.Attrib, iconIndexTemp) != 0)\r
+  {\r
+    *iconIndex = iconIndexTemp;\r
+    return S_OK;\r
+  }\r
+  return GetLastError();\r
+}\r
+\r
+STDMETHODIMP CFSFolder::SetFlatMode(Int32 flatMode)\r
+{\r
+  _flatMode = IntToBool(flatMode);\r
+  return S_OK;\r
+}\r
+\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/FSFolder.h b/CPP/7zip/UI/FileManager/FSFolder.h
new file mode 100755 (executable)
index 0000000..23797e0
--- /dev/null
@@ -0,0 +1,123 @@
+// FSFolder.h\r
+\r
+#ifndef __FSFOLDER_H\r
+#define __FSFOLDER_H\r
+\r
+#include "Common/MyCom.h"\r
+\r
+#include "Windows/FileFind.h"\r
+\r
+#include "IFolder.h"\r
+#include "TextPairs.h"\r
+\r
+namespace NFsFolder {\r
+\r
+class CFSFolder;\r
+\r
+struct CFileInfoEx: public NWindows::NFile::NFind::CFileInfoW\r
+{\r
+  #ifndef UNDER_CE\r
+  bool CompressedSizeIsDefined;\r
+  UInt64 CompressedSize;\r
+  #endif\r
+};\r
+\r
+struct CDirItem;\r
+\r
+struct CDirItem: public CFileInfoEx\r
+{\r
+  CDirItem *Parent;\r
+  CObjectVector<CDirItem> Files;\r
+\r
+  CDirItem(): Parent(0) {}\r
+  void Clear()\r
+  {\r
+    Files.Clear();\r
+    Parent = 0;\r
+  }\r
+};\r
+\r
+class CFSFolder:\r
+  public IFolderFolder,\r
+  public IFolderWasChanged,\r
+  public IFolderOperations,\r
+  // public IFolderOperationsDeleteToRecycleBin,\r
+  public IFolderGetItemFullSize,\r
+  public IFolderClone,\r
+  public IFolderGetSystemIconIndex,\r
+  public IFolderSetFlatMode,\r
+  public CMyUnknownImp\r
+{\r
+  UInt64 GetSizeOfItem(int anIndex) const;\r
+public:\r
+  MY_QUERYINTERFACE_BEGIN2(IFolderFolder)\r
+    MY_QUERYINTERFACE_ENTRY(IFolderWasChanged)\r
+    // MY_QUERYINTERFACE_ENTRY(IFolderOperationsDeleteToRecycleBin)\r
+    MY_QUERYINTERFACE_ENTRY(IFolderOperations)\r
+    MY_QUERYINTERFACE_ENTRY(IFolderGetItemFullSize)\r
+    MY_QUERYINTERFACE_ENTRY(IFolderClone)\r
+    MY_QUERYINTERFACE_ENTRY(IFolderGetSystemIconIndex)\r
+    MY_QUERYINTERFACE_ENTRY(IFolderSetFlatMode)\r
+  MY_QUERYINTERFACE_END\r
+  MY_ADDREF_RELEASE\r
+\r
+\r
+  INTERFACE_FolderFolder(;)\r
+  INTERFACE_FolderOperations(;)\r
+\r
+  STDMETHOD(WasChanged)(Int32 *wasChanged);\r
+  STDMETHOD(Clone)(IFolderFolder **resultFolder);\r
+  STDMETHOD(GetItemFullSize)(UInt32 index, PROPVARIANT *value, IProgress *progress);\r
+\r
+  STDMETHOD(SetFlatMode)(Int32 flatMode);\r
+\r
+  STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex);\r
+\r
+private:\r
+  UString _path;\r
+  CDirItem _root;\r
+  CRecordVector<CDirItem *> _refs;\r
+\r
+  CMyComPtr<IFolderFolder> _parentFolder;\r
+\r
+  bool _commentsAreLoaded;\r
+  CPairsStorage _comments;\r
+\r
+  bool _flatMode;\r
+\r
+  NWindows::NFile::NFind::CFindChangeNotification _findChangeNotification;\r
+\r
+  HRESULT GetItemsFullSize(const UInt32 *indices, UInt32 numItems,\r
+      UInt64 &numFolders, UInt64 &numFiles, UInt64 &size, IProgress *progress);\r
+  HRESULT GetItemFullSize(int index, UInt64 &size, IProgress *progress);\r
+  HRESULT GetComplexName(const wchar_t *name, UString &resultPath);\r
+  HRESULT BindToFolderSpec(const wchar_t *name, IFolderFolder **resultFolder);\r
+\r
+  bool LoadComments();\r
+  bool SaveComments();\r
+  HRESULT LoadSubItems(CDirItem &dirItem, const UString &path);\r
+  void AddRefs(CDirItem &dirItem);\r
+public:\r
+  HRESULT Init(const UString &path, IFolderFolder *parentFolder);\r
+  #ifdef UNDER_CE\r
+  HRESULT InitToRoot() { return Init(L"\\", NULL); }\r
+  #endif\r
+\r
+  CFSFolder() : _flatMode(false) {}\r
+\r
+  UString GetPrefix(const CDirItem &item) const;\r
+  UString GetRelPath(const CDirItem &item) const;\r
+  UString GetRelPath(UInt32 index) const { return GetRelPath(*_refs[index]); }\r
+\r
+  void Clear()\r
+  {\r
+    _root.Clear();\r
+    _refs.Clear();\r
+  }\r
+};\r
+\r
+HRESULT GetFolderSize(const UString &path, UInt64 &numFolders, UInt64 &numFiles, UInt64 &size, IProgress *progress);\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
new file mode 100755 (executable)
index 0000000..3cd14a6
--- /dev/null
@@ -0,0 +1,547 @@
+// FSFolderCopy.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include <Winbase.h>\r
+\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/DLL.h"\r
+#include "Windows/Error.h"\r
+#include "Windows/FileDir.h"\r
+\r
+#include "../../Common/FilePathAutoRename.h"\r
+\r
+#include "FSFolder.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+using namespace NFind;\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+namespace NFsFolder {\r
+\r
+/*\r
+static bool IsItWindows2000orHigher()\r
+{\r
+  OSVERSIONINFO versionInfo;\r
+  versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);\r
+  if (!::GetVersionEx(&versionInfo))\r
+    return false;\r
+  return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) &&\r
+      (versionInfo.dwMajorVersion >= 5);\r
+}\r
+*/\r
+\r
+struct CProgressInfo\r
+{\r
+  UInt64 StartPos;\r
+  IProgress *Progress;\r
+};\r
+\r
+#ifndef PROGRESS_CONTINUE\r
+\r
+#define PROGRESS_CONTINUE 0\r
+#define PROGRESS_CANCEL 1\r
+\r
+#define COPY_FILE_FAIL_IF_EXISTS 0x00000001\r
+\r
+typedef\r
+DWORD\r
+(WINAPI* LPPROGRESS_ROUTINE)(\r
+    LARGE_INTEGER TotalFileSize,\r
+    LARGE_INTEGER TotalBytesTransferred,\r
+    LARGE_INTEGER StreamSize,\r
+    LARGE_INTEGER StreamBytesTransferred,\r
+    DWORD dwStreamNumber,\r
+    DWORD dwCallbackReason,\r
+    HANDLE hSourceFile,\r
+    HANDLE hDestinationFile,\r
+    LPVOID lpData\r
+    );\r
+\r
+#endif\r
+\r
+static DWORD CALLBACK CopyProgressRoutine(\r
+  LARGE_INTEGER /* TotalFileSize */,          // file size\r
+  LARGE_INTEGER TotalBytesTransferred,  // bytes transferred\r
+  LARGE_INTEGER /* StreamSize */,             // bytes in stream\r
+  LARGE_INTEGER /* StreamBytesTransferred */, // bytes transferred for stream\r
+  DWORD /* dwStreamNumber */,                 // current stream\r
+  DWORD /* dwCallbackReason */,               // callback reason\r
+  HANDLE /* hSourceFile */,                   // handle to source file\r
+  HANDLE /* hDestinationFile */,              // handle to destination file\r
+  LPVOID lpData                         // from CopyFileEx\r
+)\r
+{\r
+  CProgressInfo &progressInfo = *(CProgressInfo *)lpData;\r
+  UInt64 completed = progressInfo.StartPos + TotalBytesTransferred.QuadPart;\r
+  if (progressInfo.Progress->SetCompleted(&completed) != S_OK)\r
+    return PROGRESS_CANCEL;\r
+  return PROGRESS_CONTINUE;\r
+}\r
+\r
+typedef BOOL (WINAPI * CopyFileExPointer)(\r
+    IN LPCSTR lpExistingFileName,\r
+    IN LPCSTR lpNewFileName,\r
+    IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,\r
+    IN LPVOID lpData OPTIONAL,\r
+    IN LPBOOL pbCancel OPTIONAL,\r
+    IN DWORD dwCopyFlags\r
+    );\r
+\r
+typedef BOOL (WINAPI * CopyFileExPointerW)(\r
+    IN LPCWSTR lpExistingFileName,\r
+    IN LPCWSTR lpNewFileName,\r
+    IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,\r
+    IN LPVOID lpData OPTIONAL,\r
+    IN LPBOOL pbCancel OPTIONAL,\r
+    IN DWORD dwCopyFlags\r
+    );\r
+\r
+#ifndef _UNICODE\r
+static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }\r
+static CSysString GetSysPath(LPCWSTR sysPath)\r
+  { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); }\r
+#endif\r
+\r
+static bool MyCopyFile(LPCWSTR existingFile, LPCWSTR newFile, IProgress *progress, UInt64 &completedSize)\r
+{\r
+  CProgressInfo progressInfo;\r
+  progressInfo.Progress = progress;\r
+  progressInfo.StartPos = completedSize;\r
+  BOOL CancelFlag = FALSE;\r
+  #ifndef _UNICODE\r
+  if (g_IsNT)\r
+  #endif\r
+  {\r
+    const wchar_t *k_DllName =\r
+        #ifdef UNDER_CE\r
+        L"coredll.dll"\r
+        #else\r
+        L"kernel32.dll"\r
+        #endif\r
+        ;\r
+    CopyFileExPointerW copyFunctionW = (CopyFileExPointerW)\r
+        My_GetProcAddress(::GetModuleHandleW(k_DllName), "CopyFileExW");\r
+    if (copyFunctionW == 0)\r
+      return BOOLToBool(::CopyFileW(existingFile, newFile, TRUE));\r
+    if (copyFunctionW(existingFile, newFile, CopyProgressRoutine,\r
+        &progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS))\r
+      return true;\r
+    #ifdef WIN_LONG_PATH\r
+    UString longPathExisting, longPathNew;\r
+    if (!NDirectory::GetLongPaths(existingFile, newFile, longPathExisting, longPathNew))\r
+      return false;\r
+    if (copyFunctionW(longPathExisting, longPathNew, CopyProgressRoutine,\r
+        &progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS))\r
+      return true;\r
+    #endif\r
+    return false;\r
+  }\r
+  #ifndef _UNICODE\r
+  else\r
+  {\r
+    CopyFileExPointer copyFunction = (CopyFileExPointer)\r
+        ::GetProcAddress(::GetModuleHandleA("kernel32.dll"),\r
+        "CopyFileExA");\r
+    if (copyFunction != 0)\r
+    {\r
+      if (copyFunction(GetSysPath(existingFile), GetSysPath(newFile),\r
+          CopyProgressRoutine,&progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS))\r
+        return true;\r
+      if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)\r
+        return false;\r
+    }\r
+    return BOOLToBool(::CopyFile(GetSysPath(existingFile), GetSysPath(newFile), TRUE));\r
+  }\r
+  #endif\r
+}\r
+\r
+typedef BOOL (WINAPI * MoveFileWithProgressPointer)(\r
+    IN LPCWSTR lpExistingFileName,\r
+    IN LPCWSTR lpNewFileName,\r
+    IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,\r
+    IN LPVOID lpData OPTIONAL,\r
+    IN DWORD dwFlags\r
+    );\r
+\r
+static bool MyMoveFile(LPCWSTR existingFile, LPCWSTR newFile, IProgress *progress, UInt64 &completedSize)\r
+{\r
+  #ifndef UNDER_CE\r
+  // if (IsItWindows2000orHigher())\r
+  // {\r
+    CProgressInfo progressInfo;\r
+    progressInfo.Progress = progress;\r
+    progressInfo.StartPos = completedSize;\r
+\r
+    MoveFileWithProgressPointer moveFunction = (MoveFileWithProgressPointer)\r
+        My_GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")),\r
+        "MoveFileWithProgressW");\r
+    if (moveFunction != 0)\r
+    {\r
+      if (moveFunction(\r
+          existingFile, newFile, CopyProgressRoutine,\r
+          &progressInfo, MOVEFILE_COPY_ALLOWED))\r
+        return true;\r
+      if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)\r
+      {\r
+        #ifdef WIN_LONG_PATH\r
+        UString longPathExisting, longPathNew;\r
+        if (!NDirectory::GetLongPaths(existingFile, newFile, longPathExisting, longPathNew))\r
+          return false;\r
+        if (moveFunction(longPathExisting, longPathNew, CopyProgressRoutine,\r
+            &progressInfo, MOVEFILE_COPY_ALLOWED))\r
+          return true;\r
+        #endif\r
+        if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)\r
+          return false;\r
+      }\r
+    }\r
+  // }\r
+  // else\r
+  #endif\r
+    return NDirectory::MyMoveFile(existingFile, newFile);\r
+}\r
+\r
+static HRESULT MyCopyFile(\r
+    const UString &srcPath,\r
+    const CFileInfoW &srcFileInfo,\r
+    const UString &destPathSpec,\r
+    IFolderOperationsExtractCallback *callback,\r
+    UInt64 &completedSize)\r
+{\r
+  UString destPath = destPathSpec;\r
+  if (destPath.CompareNoCase(srcPath) == 0)\r
+  {\r
+    UString message = UString(L"can not move file \'") + destPath + UString(L"\' onto itself");\r
+    RINOK(callback->ShowMessage(message));\r
+    return E_ABORT;\r
+  }\r
+\r
+  Int32 writeAskResult;\r
+  CMyComBSTR destPathResult;\r
+  RINOK(callback->AskWrite(\r
+      srcPath,\r
+      BoolToInt(false),\r
+      &srcFileInfo.MTime, &srcFileInfo.Size,\r
+      destPath,\r
+      &destPathResult,\r
+      &writeAskResult));\r
+  if (IntToBool(writeAskResult))\r
+  {\r
+    UString destPathNew = UString(destPathResult);\r
+    RINOK(callback->SetCurrentFilePath(srcPath));\r
+    if (!MyCopyFile(srcPath, destPathNew, callback, completedSize))\r
+    {\r
+      UString message = NError::MyFormatMessageW(GetLastError()) +\r
+        UString(L" \'") +\r
+        UString(destPathNew) +\r
+        UString(L"\'");\r
+      RINOK(callback->ShowMessage(message));\r
+      return E_ABORT;\r
+    }\r
+  }\r
+  completedSize += srcFileInfo.Size;\r
+  return callback->SetCompleted(&completedSize);\r
+}\r
+\r
+static UString CombinePath(const UString &folderPath, const UString &fileName)\r
+{\r
+  return folderPath + UString(WCHAR_PATH_SEPARATOR) + fileName;\r
+}\r
+\r
+static HRESULT CopyFolder(\r
+    const UString &srcPath,\r
+    const UString &destPathSpec,\r
+    IFolderOperationsExtractCallback *callback,\r
+    UInt64 &completedSize)\r
+{\r
+  RINOK(callback->SetCompleted(&completedSize));\r
+\r
+  const UString destPath = destPathSpec;\r
+  int len = srcPath.Length();\r
+  if (destPath.Length() >= len && srcPath.CompareNoCase(destPath.Left(len)) == 0)\r
+  {\r
+    if (destPath.Length() == len || destPath[len] == WCHAR_PATH_SEPARATOR)\r
+    {\r
+      UString message = UString(L"can not copy folder \'") +\r
+          destPath + UString(L"\' onto itself");\r
+      RINOK(callback->ShowMessage(message));\r
+      return E_ABORT;\r
+    }\r
+  }\r
+\r
+  if (!NDirectory::CreateComplexDirectory(destPath))\r
+  {\r
+    UString message = UString(L"can not create folder ") + destPath;\r
+    RINOK(callback->ShowMessage(message));\r
+    return E_ABORT;\r
+  }\r
+  CEnumeratorW enumerator(CombinePath(srcPath, L"*"));\r
+  CFileInfoEx fi;\r
+  while (enumerator.Next(fi))\r
+  {\r
+    const UString srcPath2 = CombinePath(srcPath, fi.Name);\r
+    const UString destPath2 = CombinePath(destPath, fi.Name);\r
+    if (fi.IsDir())\r
+    {\r
+      RINOK(CopyFolder(srcPath2, destPath2, callback, completedSize))\r
+    }\r
+    else\r
+    {\r
+      RINOK(MyCopyFile(srcPath2, fi, destPath2, callback, completedSize));\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFSFolder::CopyTo(const UInt32 *indices, UInt32 numItems,\r
+    const wchar_t *path, IFolderOperationsExtractCallback *callback)\r
+{\r
+  if (numItems == 0)\r
+    return S_OK;\r
+  \r
+  UInt64 numFolders, numFiles, totalSize;\r
+  GetItemsFullSize(indices, numItems, numFolders, numFiles, totalSize, callback);\r
+  RINOK(callback->SetTotal(totalSize));\r
+  RINOK(callback->SetNumFiles(numFiles));\r
+  \r
+  UString destPath = path;\r
+  if (destPath.IsEmpty())\r
+    return E_INVALIDARG;\r
+  bool directName = (destPath[destPath.Length() - 1] != WCHAR_PATH_SEPARATOR);\r
+  if (directName)\r
+  {\r
+    if (numItems > 1)\r
+      return E_INVALIDARG;\r
+  }\r
+    /*\r
+    // doesn't work in network\r
+  else\r
+    if (!NDirectory::CreateComplexDirectory(destPath)))\r
+    {\r
+      DWORD lastError = ::GetLastError();\r
+      UString message = UString(L"can not create folder ") +\r
+        destPath;\r
+      RINOK(callback->ShowMessage(message));\r
+      return E_ABORT;\r
+    }\r
+    */\r
+\r
+  UInt64 completedSize = 0;\r
+  RINOK(callback->SetCompleted(&completedSize));\r
+  for (UInt32 i = 0; i < numItems; i++)\r
+  {\r
+    const CDirItem &fi = *_refs[indices[i]];\r
+    UString destPath2 = destPath;\r
+    if (!directName)\r
+      destPath2 += fi.Name;\r
+    UString srcPath = _path + GetPrefix(fi) + fi.Name;\r
+    if (fi.IsDir())\r
+    {\r
+      RINOK(CopyFolder(srcPath, destPath2, callback, completedSize));\r
+    }\r
+    else\r
+    {\r
+      RINOK(MyCopyFile(srcPath, fi, destPath2, callback, completedSize));\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+/////////////////////////////////////////////////\r
+// Move Operations\r
+\r
+HRESULT MyMoveFile(\r
+    const UString &srcPath,\r
+    const CFileInfoW &srcFileInfo,\r
+    const UString &destPathSpec,\r
+    IFolderOperationsExtractCallback *callback,\r
+    UInt64 &completedSize)\r
+{\r
+  UString destPath = destPathSpec;\r
+  if (destPath.CompareNoCase(srcPath) == 0)\r
+  {\r
+    UString message = UString(L"can not move file \'")\r
+         + destPath +\r
+        UString(L"\' onto itself");\r
+        RINOK(callback->ShowMessage(message));\r
+    return E_ABORT;\r
+  }\r
+\r
+  Int32 writeAskResult;\r
+  CMyComBSTR destPathResult;\r
+  RINOK(callback->AskWrite(\r
+      srcPath,\r
+      BoolToInt(false),\r
+      &srcFileInfo.MTime, &srcFileInfo.Size,\r
+      destPath,\r
+      &destPathResult,\r
+      &writeAskResult));\r
+  if (IntToBool(writeAskResult))\r
+  {\r
+    UString destPathNew = UString(destPathResult);\r
+    RINOK(callback->SetCurrentFilePath(srcPath));\r
+    if (!MyMoveFile(srcPath, destPathNew, callback, completedSize))\r
+    {\r
+      UString message = UString(L"can not move to file ") + destPathNew;\r
+      RINOK(callback->ShowMessage(message));\r
+    }\r
+  }\r
+  completedSize += srcFileInfo.Size;\r
+  RINOK(callback->SetCompleted(&completedSize));\r
+  return S_OK;\r
+}\r
+\r
+HRESULT MyMoveFolder(\r
+    const UString &srcPath,\r
+    const UString &destPathSpec,\r
+    IFolderOperationsExtractCallback *callback,\r
+    UInt64 &completedSize)\r
+{\r
+  UString destPath = destPathSpec;\r
+  int len = srcPath.Length();\r
+  if (destPath.Length() >= len && srcPath.CompareNoCase(destPath.Left(len)) == 0)\r
+  {\r
+    if (destPath.Length() == len || destPath[len] == WCHAR_PATH_SEPARATOR)\r
+    {\r
+      UString message = UString(L"can not move folder \'") +\r
+          destPath + UString(L"\' onto itself");\r
+      RINOK(callback->ShowMessage(message));\r
+      return E_ABORT;\r
+    }\r
+  }\r
+\r
+  if (MyMoveFile(srcPath, destPath, callback, completedSize))\r
+    return S_OK;\r
+\r
+  if (!NDirectory::CreateComplexDirectory(destPath))\r
+  {\r
+    UString message = UString(L"can not create folder ") +  destPath;\r
+    RINOK(callback->ShowMessage(message));\r
+    return E_ABORT;\r
+  }\r
+  {\r
+    CEnumeratorW enumerator(CombinePath(srcPath, L"*"));\r
+    CFileInfoEx fi;\r
+    while (enumerator.Next(fi))\r
+    {\r
+      const UString srcPath2 = CombinePath(srcPath, fi.Name);\r
+      const UString destPath2 = CombinePath(destPath, fi.Name);\r
+      if (fi.IsDir())\r
+      {\r
+        RINOK(MyMoveFolder(srcPath2, destPath2, callback, completedSize));\r
+      }\r
+      else\r
+      {\r
+        RINOK(MyMoveFile(srcPath2, fi, destPath2, callback, completedSize));\r
+      }\r
+    }\r
+  }\r
+  if (!NDirectory::MyRemoveDirectory(srcPath))\r
+  {\r
+    UString message = UString(L"can not remove folder") + srcPath;\r
+    RINOK(callback->ShowMessage(message));\r
+    return E_ABORT;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFSFolder::MoveTo(\r
+    const UInt32 *indices,\r
+    UInt32 numItems,\r
+    const wchar_t *path,\r
+    IFolderOperationsExtractCallback *callback)\r
+{\r
+  if (numItems == 0)\r
+    return S_OK;\r
+\r
+  UInt64 numFolders, numFiles, totalSize;\r
+  GetItemsFullSize(indices, numItems, numFolders, numFiles, totalSize, callback);\r
+  RINOK(callback->SetTotal(totalSize));\r
+  RINOK(callback->SetNumFiles(numFiles));\r
+\r
+  UString destPath = path;\r
+  if (destPath.IsEmpty())\r
+    return E_INVALIDARG;\r
+  bool directName = (destPath[destPath.Length() - 1] != WCHAR_PATH_SEPARATOR);\r
+  if (directName)\r
+  {\r
+    if (numItems > 1)\r
+      return E_INVALIDARG;\r
+  }\r
+  else\r
+    if (!NDirectory::CreateComplexDirectory(destPath))\r
+    {\r
+      UString message = UString(L"can not create folder ") +\r
+        destPath;\r
+      RINOK(callback->ShowMessage(message));\r
+      return E_ABORT;\r
+    }\r
+\r
+  UInt64 completedSize = 0;\r
+  RINOK(callback->SetCompleted(&completedSize));\r
+  for (UInt32 i = 0; i < numItems; i++)\r
+  {\r
+    const CDirItem &fi = *_refs[indices[i]];\r
+    UString destPath2 = destPath;\r
+    if (!directName)\r
+      destPath2 += fi.Name;\r
+    UString srcPath = _path + GetPrefix(fi) + fi.Name;\r
+    if (fi.IsDir())\r
+    {\r
+      RINOK(MyMoveFolder(srcPath, destPath2, callback, completedSize));\r
+    }\r
+    else\r
+    {\r
+      RINOK(MyMoveFile(srcPath, fi, destPath2, callback, completedSize));\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CFSFolder::CopyFrom(const wchar_t * /* fromFolderPath */,\r
+    const wchar_t ** /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */)\r
+{\r
+  /*\r
+  UInt64 numFolders, numFiles, totalSize;\r
+  numFiles = numFolders = totalSize = 0;\r
+  UInt32 i;\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    UString path = (UString)fromFolderPath + itemsPaths[i];\r
+\r
+    CFileInfoW fi;\r
+    if (!FindFile(path, fi))\r
+      return ::GetLastError();\r
+    if (fi.IsDir())\r
+    {\r
+      UInt64 subFolders, subFiles, subSize;\r
+      RINOK(GetFolderSize(CombinePath(path, fi.Name), subFolders, subFiles, subSize, progress));\r
+      numFolders += subFolders;\r
+      numFolders++;\r
+      numFiles += subFiles;\r
+      totalSize += subSize;\r
+    }\r
+    else\r
+    {\r
+      numFiles++;\r
+      totalSize += fi.Size;\r
+    }\r
+  }\r
+  RINOK(progress->SetTotal(totalSize));\r
+  RINOK(callback->SetNumFiles(numFiles));\r
+  for (i = 0; i < numItems; i++)\r
+  {\r
+    UString path = (UString)fromFolderPath + itemsPaths[i];\r
+  }\r
+  return S_OK;\r
+  */\r
+  return E_NOTIMPL;\r
+}\r
+\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp
new file mode 100755 (executable)
index 0000000..9a598ce
--- /dev/null
@@ -0,0 +1,166 @@
+// FileFolderPluginOpen.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "resource.h"\r
+\r
+#include "Windows/Thread.h"\r
+\r
+#include "../Agent/Agent.h"\r
+\r
+#include "LangUtils.h"\r
+#include "OpenCallback.h"\r
+#include "PluginLoader.h"\r
+#include "RegistryAssociations.h"\r
+#include "RegistryPlugins.h"\r
+\r
+using namespace NWindows;\r
+using namespace NRegistryAssociations;\r
+\r
+struct CThreadArchiveOpen\r
+{\r
+  UString Path;\r
+  UString ArcFormat;\r
+  CMyComPtr<IInStream> InStream;\r
+  CMyComPtr<IFolderManager> FolderManager;\r
+  CMyComPtr<IProgress> OpenCallback;\r
+  COpenArchiveCallback *OpenCallbackSpec;\r
+\r
+  CMyComPtr<IFolderFolder> Folder;\r
+  HRESULT Result;\r
+\r
+  void Process()\r
+  {\r
+    try\r
+    {\r
+      CProgressCloser closer(OpenCallbackSpec->ProgressDialog);\r
+      Result = FolderManager->OpenFolderFile(InStream, Path, ArcFormat, &Folder, OpenCallback);\r
+    }\r
+    catch(...) { Result = E_FAIL; }\r
+  }\r
+  \r
+  static THREAD_FUNC_DECL MyThreadFunction(void *param)\r
+  {\r
+    ((CThreadArchiveOpen *)param)->Process();\r
+    return 0;\r
+  }\r
+};\r
+\r
+/*\r
+static int FindPlugin(const CObjectVector<CPluginInfo> &plugins, const UString &pluginName)\r
+{\r
+  for (int i = 0; i < plugins.Size(); i++)\r
+    if (plugins[i].Name.CompareNoCase(pluginName) == 0)\r
+      return i;\r
+  return -1;\r
+}\r
+*/\r
+\r
+HRESULT OpenFileFolderPlugin(\r
+    IInStream *inStream,\r
+    const UString &path,\r
+    const UString &arcFormat,\r
+    HMODULE *module,\r
+    IFolderFolder **resultFolder,\r
+    HWND parentWindow,\r
+    bool &encrypted, UString &password)\r
+{\r
+  CObjectVector<CPluginInfo> plugins;\r
+  ReadFileFolderPluginInfoList(plugins);\r
+\r
+  UString extension, name, pureName, dot;\r
+\r
+  int slashPos = path.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+  UString dirPrefix;\r
+  UString fileName;\r
+  if (slashPos >= 0)\r
+  {\r
+    dirPrefix = path.Left(slashPos + 1);\r
+    fileName = path.Mid(slashPos + 1);\r
+  }\r
+  else\r
+    fileName = path;\r
+\r
+  NFile::NName::SplitNameToPureNameAndExtension(fileName, pureName, dot, extension);\r
+\r
+  /*\r
+  if (!extension.IsEmpty())\r
+  {\r
+    CExtInfo extInfo;\r
+    if (ReadInternalAssociation(extension, extInfo))\r
+    {\r
+      for (int i = extInfo.Plugins.Size() - 1; i >= 0; i--)\r
+      {\r
+        int pluginIndex = FindPlugin(plugins, extInfo.Plugins[i]);\r
+        if (pluginIndex >= 0)\r
+        {\r
+          const CPluginInfo plugin = plugins[pluginIndex];\r
+          plugins.Delete(pluginIndex);\r
+          plugins.Insert(0, plugin);\r
+        }\r
+      }\r
+    }\r
+  }\r
+  */\r
+\r
+  for (int i = 0; i < plugins.Size(); i++)\r
+  {\r
+    const CPluginInfo &plugin = plugins[i];\r
+    if (!plugin.ClassIDDefined)\r
+      continue;\r
+    CPluginLibrary library;\r
+\r
+    CThreadArchiveOpen t;\r
+\r
+    if (plugin.FilePath.IsEmpty())\r
+      t.FolderManager = new CArchiveFolderManager;\r
+    else if (library.LoadAndCreateManager(plugin.FilePath, plugin.ClassID, &t.FolderManager) != S_OK)\r
+      continue;\r
+\r
+    t.OpenCallbackSpec = new COpenArchiveCallback;\r
+    t.OpenCallback = t.OpenCallbackSpec;\r
+    t.OpenCallbackSpec->PasswordIsDefined = encrypted;\r
+    t.OpenCallbackSpec->Password = password;\r
+    t.OpenCallbackSpec->ParentWindow = parentWindow;\r
+\r
+    if (inStream)\r
+      t.OpenCallbackSpec->SetSubArchiveName(fileName);\r
+    else\r
+      t.OpenCallbackSpec->LoadFileInfo(dirPrefix, fileName);\r
+\r
+    t.InStream = inStream;\r
+    t.Path = path;\r
+    t.ArcFormat = arcFormat;\r
+\r
+    UString progressTitle = LangString(IDS_OPENNING, 0x03020283);\r
+    t.OpenCallbackSpec->ProgressDialog.MainWindow = parentWindow;\r
+    t.OpenCallbackSpec->ProgressDialog.MainTitle = LangString(IDS_APP_TITLE, 0x03000000);\r
+    t.OpenCallbackSpec->ProgressDialog.MainAddTitle = progressTitle + UString(L" ");\r
+    t.OpenCallbackSpec->ProgressDialog.WaitMode = true;\r
+\r
+    {\r
+      NWindows::CThread thread;\r
+      RINOK(thread.Create(CThreadArchiveOpen::MyThreadFunction, &t));\r
+      t.OpenCallbackSpec->StartProgressDialog(progressTitle, thread);\r
+    }\r
+\r
+    if (t.Result == E_ABORT)\r
+      return t.Result;\r
+\r
+    if (t.Result == S_OK)\r
+    {\r
+      // if (openCallbackSpec->PasswordWasAsked)\r
+      {\r
+        encrypted = t.OpenCallbackSpec->PasswordIsDefined;\r
+        password = t.OpenCallbackSpec->Password;\r
+      }\r
+      *module = library.Detach();\r
+      *resultFolder = t.Folder.Detach();\r
+      return S_OK;\r
+    }\r
+    \r
+    if (t.Result != S_FALSE)\r
+      return t.Result;\r
+  }\r
+  return S_FALSE;\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h
new file mode 100755 (executable)
index 0000000..9aeac42
--- /dev/null
@@ -0,0 +1,9 @@
+// FileFolderPluginOpen.h\r
+\r
+#ifndef __FILE_FOLDER_PLUGIN_OPEN_H\r
+#define __FILE_FOLDER_PLUGIN_OPEN_H\r
+\r
+HRESULT OpenFileFolderPlugin(IInStream *inStream, const UString &path, const UString &arcFormat,\r
+    HMODULE *module, IFolderFolder **resultFolder, HWND parentWindow, bool &encrypted, UString &password);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/FilePlugins.cpp b/CPP/7zip/UI/FileManager/FilePlugins.cpp
new file mode 100755 (executable)
index 0000000..f5bb703
--- /dev/null
@@ -0,0 +1,119 @@
+// FilePlugins.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/MyCom.h"\r
+\r
+#include "../Agent/Agent.h"\r
+\r
+#include "FilePlugins.h"\r
+#include "PluginLoader.h"\r
+#include "StringUtils.h"\r
+\r
+using namespace NRegistryAssociations;\r
+\r
+int CExtDatabase::FindExtInfoBig(const UString &ext)\r
+{\r
+  for (int i = 0; i < ExtBigItems.Size(); i++)\r
+    if (ExtBigItems[i].Ext.CompareNoCase(ext) == 0)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+int CExtDatabase::FindPlugin(const UString &plugin)\r
+{\r
+  for (int i = 0; i < Plugins.Size(); i++)\r
+    if (Plugins[i].Name.CompareNoCase(plugin) == 0)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+void CExtDatabase::Read()\r
+{\r
+  /*\r
+  CObjectVector<CExtInfo> extItems;\r
+  ReadInternalAssociations(extItems);\r
+  */\r
+  ReadFileFolderPluginInfoList(Plugins);\r
+  /*\r
+  for (int i = 0; i < extItems.Size(); i++)\r
+  {\r
+    const CExtInfo &extInfo = extItems[i];\r
+    CExtInfoBig extInfoBig;\r
+    extInfoBig.Ext = extInfo.Ext;\r
+    extInfoBig.Associated = false;\r
+    for (int p = 0; p < extInfo.Plugins.Size(); p++)\r
+    {\r
+      int pluginIndex = FindPlugin(extInfo.Plugins[p]);\r
+      if (pluginIndex >= 0)\r
+        extInfoBig.PluginsPairs.Add(CPluginEnabledPair(pluginIndex, true));\r
+    }\r
+    ExtBigItems.Add(extInfoBig);\r
+  }\r
+  */\r
+  for (int pluginIndex = 0; pluginIndex < Plugins.Size(); pluginIndex++)\r
+  {\r
+    const CPluginInfo &pluginInfo = Plugins[pluginIndex];\r
+\r
+    CPluginLibrary pluginLibrary;\r
+    CMyComPtr<IFolderManager> folderManager;\r
+\r
+    if (pluginInfo.FilePath.IsEmpty())\r
+      folderManager = new CArchiveFolderManager;\r
+    else if (pluginLibrary.LoadAndCreateManager(pluginInfo.FilePath,\r
+         pluginInfo.ClassID, &folderManager) != S_OK)\r
+      continue;\r
+    CMyComBSTR extBSTR;\r
+    if (folderManager->GetExtensions(&extBSTR) != S_OK)\r
+      return;\r
+    const UString ext2 = (const wchar_t *)extBSTR;\r
+    UStringVector exts;\r
+    SplitString(ext2, exts);\r
+    for (int i = 0; i < exts.Size(); i++)\r
+    {\r
+      const UString &ext = exts[i];\r
+      #ifdef UNDER_CE\r
+      if (ext == L"cab")\r
+        continue;\r
+      #endif\r
+      int index = FindExtInfoBig(ext);\r
+      if (index < 0)\r
+      {\r
+        CExtInfoBig extInfo;\r
+        extInfo.PluginsPairs.Add(CPluginEnabledPair(pluginIndex, false));\r
+        extInfo.Associated = false;\r
+        extInfo.Ext = ext;\r
+        ExtBigItems.Add(extInfo);\r
+      }\r
+      else\r
+      {\r
+        CExtInfoBig &extInfo = ExtBigItems[index];\r
+        int pluginIndexIndex = extInfo.FindPlugin(pluginIndex);\r
+        if (pluginIndexIndex < 0)\r
+          extInfo.PluginsPairs.Add(CPluginEnabledPair(pluginIndex, false));\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+void CExtDatabase::Save()\r
+{\r
+  /*\r
+  CObjectVector<CExtInfo> extItems;\r
+  for (int i = 0; i < ExtBigItems.Size(); i++)\r
+  {\r
+    const CExtInfoBig &extInfoBig = ExtBigItems[i];\r
+    CExtInfo extInfo;\r
+    // extInfo.Enabled = extInfoBig.Associated;\r
+    extInfo.Ext = extInfoBig.Ext;\r
+    for (int p = 0; p < extInfoBig.PluginsPairs.Size(); p++)\r
+    {\r
+      CPluginEnabledPair pluginPair = extInfoBig.PluginsPairs[p];\r
+      if (pluginPair.Enabled)\r
+        extInfo.Plugins.Add(Plugins[pluginPair.Index].Name);\r
+    }\r
+    extItems.Add(extInfo);\r
+  }\r
+  WriteInternalAssociations(extItems);\r
+  */\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/FilePlugins.h b/CPP/7zip/UI/FileManager/FilePlugins.h
new file mode 100755 (executable)
index 0000000..2258e27
--- /dev/null
@@ -0,0 +1,54 @@
+// FilePlugins.h\r
+\r
+#ifndef __FILEPLUGINS_H\r
+#define __FILEPLUGINS_H\r
+\r
+#include "RegistryPlugins.h"\r
+#include "RegistryAssociations.h"\r
+\r
+struct CPluginEnabledPair\r
+{\r
+  int Index;\r
+  bool Enabled;\r
+  CPluginEnabledPair(int index, bool enabled): Index(index),Enabled(enabled) {}\r
+};\r
+\r
+struct CExtInfoBig\r
+{\r
+  UString Ext;\r
+  bool Associated;\r
+  CRecordVector<CPluginEnabledPair> PluginsPairs;\r
+  int FindPlugin(int pluginIndex)\r
+  {\r
+    for (int i = 0; i < PluginsPairs.Size(); i++)\r
+      if (PluginsPairs[i].Index == pluginIndex)\r
+        return i;\r
+    return -1;\r
+  }\r
+};\r
+\r
+class CExtDatabase\r
+{\r
+public:\r
+  CObjectVector<CExtInfoBig> ExtBigItems;\r
+  CObjectVector<CPluginInfo> Plugins;\r
+  int FindExtInfoBig(const UString &ext);\r
+  int FindPlugin(const UString &plugin);\r
+\r
+  UString GetMainPluginNameForExtItem(int extIndex) const\r
+  {\r
+    const CExtInfoBig &extInfo = ExtBigItems[extIndex];\r
+    if (extInfo.PluginsPairs.IsEmpty())\r
+      return UString();\r
+    else\r
+      return Plugins[extInfo.PluginsPairs.Front().Index].Name;\r
+  }\r
+\r
+  void Read();\r
+  void Save();\r
+};\r
+\r
+\r
+#endif\r
+\r
+\r
diff --git a/CPP/7zip/UI/FileManager/FoldersPage.cpp b/CPP/7zip/UI/FileManager/FoldersPage.cpp
new file mode 100755 (executable)
index 0000000..1469ca2
--- /dev/null
@@ -0,0 +1,151 @@
+// FoldersPage.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "FoldersPageRes.h"\r
+#include "FoldersPage.h"\r
+\r
+#include "../FileManager/BrowseDialog.h"\r
+#include "../FileManager/HelpUtils.h"\r
+#include "../FileManager/LangUtils.h"\r
+\r
+using namespace NWindows;\r
+\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDC_FOLDERS_STATIC_WORKING_FOLDER,    0x01000210 },\r
+  { IDC_FOLDERS_WORK_RADIO_SYSTEM,        0x01000211 },\r
+  { IDC_FOLDERS_WORK_RADIO_CURRENT,       0x01000212 },\r
+  { IDC_FOLDERS_WORK_RADIO_SPECIFIED,     0x01000213 },\r
+  { IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE, 0x01000214 }\r
+};\r
+\r
+static const int kWorkModeButtons[] =\r
+{\r
+  IDC_FOLDERS_WORK_RADIO_SYSTEM,\r
+  IDC_FOLDERS_WORK_RADIO_CURRENT,\r
+  IDC_FOLDERS_WORK_RADIO_SPECIFIED\r
+};\r
+\r
+static const int kNumWorkModeButtons = sizeof(kWorkModeButtons) / sizeof(kWorkModeButtons[0]);\r
\r
+bool CFoldersPage::OnInit()\r
+{\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+  m_WorkDirInfo.Load();\r
+\r
+  CheckButton(IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE, m_WorkDirInfo.ForRemovableOnly);\r
+  \r
+  CheckRadioButton(kWorkModeButtons[0], kWorkModeButtons[kNumWorkModeButtons - 1],\r
+      kWorkModeButtons[m_WorkDirInfo.Mode]);\r
+\r
+  m_WorkPath.Init(*this, IDC_FOLDERS_WORK_EDIT_PATH);\r
+  m_ButtonSetWorkPath.Init(*this, IDC_FOLDERS_WORK_BUTTON_PATH);\r
+\r
+  m_WorkPath.SetText(m_WorkDirInfo.Path);\r
+\r
+  MyEnableControls();\r
+  \r
+  return CPropertyPage::OnInit();\r
+}\r
+\r
+int CFoldersPage::GetWorkMode() const\r
+{\r
+  for (int i = 0; i < kNumWorkModeButtons; i++)\r
+    if(IsButtonCheckedBool(kWorkModeButtons[i]))\r
+      return i;\r
+  throw 0;\r
+}\r
+\r
+void CFoldersPage::MyEnableControls()\r
+{\r
+  bool enablePath = (GetWorkMode() == NWorkDir::NMode::kSpecified);\r
+  m_WorkPath.Enable(enablePath);\r
+  m_ButtonSetWorkPath.Enable(enablePath);\r
+}\r
+\r
+void CFoldersPage::GetWorkDir(NWorkDir::CInfo &workDirInfo)\r
+{\r
+  m_WorkPath.GetText(workDirInfo.Path);\r
+  workDirInfo.ForRemovableOnly = IsButtonCheckedBool(IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE);\r
+  workDirInfo.Mode = NWorkDir::NMode::EEnum(GetWorkMode());\r
+}\r
+\r
+/*\r
+bool CFoldersPage::WasChanged()\r
+{\r
+  NWorkDir::CInfo workDirInfo;\r
+  GetWorkDir(workDirInfo);\r
+  return (workDirInfo.Mode != m_WorkDirInfo.Mode ||\r
+      workDirInfo.ForRemovableOnly != m_WorkDirInfo.ForRemovableOnly ||\r
+      workDirInfo.Path.Compare(m_WorkDirInfo.Path) != 0);\r
+}\r
+*/\r
+\r
+void CFoldersPage::ModifiedEvent()\r
+{\r
+  Changed();\r
+  /*\r
+  if (WasChanged())\r
+    Changed();\r
+  else\r
+    UnChanged();\r
+  */\r
+}\r
+\r
+bool CFoldersPage::OnButtonClicked(int buttonID, HWND buttonHWND)\r
+{\r
+  for (int i = 0; i < kNumWorkModeButtons; i++)\r
+    if (buttonID == kWorkModeButtons[i])\r
+    {\r
+      MyEnableControls();\r
+      ModifiedEvent();\r
+      return true;\r
+    }\r
+  switch(buttonID)\r
+  {\r
+    case IDC_FOLDERS_WORK_BUTTON_PATH:\r
+      OnFoldersWorkButtonPath();\r
+      break;\r
+    case IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE:\r
+      break;\r
+    default:\r
+      return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);\r
+  }\r
+  ModifiedEvent();\r
+  return true;\r
+}\r
+\r
+bool CFoldersPage::OnCommand(int code, int itemID, LPARAM lParam)\r
+{\r
+  if (code == EN_CHANGE && itemID == IDC_FOLDERS_WORK_EDIT_PATH)\r
+  {\r
+    ModifiedEvent();\r
+    return true;\r
+  }\r
+  return CPropertyPage::OnCommand(code, itemID, lParam);\r
+}\r
+\r
+void CFoldersPage::OnFoldersWorkButtonPath()\r
+{\r
+  UString currentPath;\r
+  m_WorkPath.GetText(currentPath);\r
+  UString title = LangString(IDS_FOLDERS_SET_WORK_PATH_TITLE, 0x01000281);\r
+  UString resultPath;\r
+  if (MyBrowseForFolder(HWND(*this), title, currentPath, resultPath))\r
+    m_WorkPath.SetText(resultPath);\r
+}\r
+\r
+LONG CFoldersPage::OnApply()\r
+{\r
+  GetWorkDir(m_WorkDirInfo);\r
+  m_WorkDirInfo.Save();\r
+  return PSNRET_NOERROR;\r
+}\r
+\r
+static LPCWSTR kFoldersTopic = L"fm/plugins/7-zip/options.htm#folders";\r
+\r
+void CFoldersPage::OnNotifyHelp()\r
+{\r
+  ShowHelpWindow(NULL, kFoldersTopic);\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/FoldersPage.h b/CPP/7zip/UI/FileManager/FoldersPage.h
new file mode 100755 (executable)
index 0000000..531bcfc
--- /dev/null
@@ -0,0 +1,29 @@
+// FoldersPage.h\r
\r
+#ifndef __FOLDERS_PAGE_H\r
+#define __FOLDERS_PAGE_H\r
+\r
+#include "Windows/Control/PropertyPage.h"\r
+\r
+#include "../Common/ZipRegistry.h"\r
+\r
+class CFoldersPage : public NWindows::NControl::CPropertyPage\r
+{\r
+  NWorkDir::CInfo m_WorkDirInfo;\r
+\r
+  void MyEnableControls();\r
+  void ModifiedEvent();\r
+  NWindows::NControl::CDialogChildControl m_WorkPath;\r
+  NWindows::NControl::CDialogChildControl m_ButtonSetWorkPath;\r
+  void OnFoldersWorkButtonPath();\r
+  int GetWorkMode() const;\r
+  void GetWorkDir(NWorkDir::CInfo &workDirInfo);\r
+  // bool WasChanged();\r
+  virtual bool OnInit();\r
+  virtual bool OnCommand(int code, int itemID, LPARAM lParam);\r
+  virtual void OnNotifyHelp();\r
+  virtual LONG OnApply();\r
+  virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/FoldersPage.rc b/CPP/7zip/UI/FileManager/FoldersPage.rc
new file mode 100755 (executable)
index 0000000..0e5b3e9
--- /dev/null
@@ -0,0 +1,23 @@
+#include "FoldersPageRes.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#define xc 196\r
+#define yc 100\r
+\r
+IDD_FOLDERS  MY_PAGE\r
+#include "FoldersPage2.rc"\r
+\r
+#ifdef UNDER_CE\r
+\r
+#undef xc\r
+#define xc SMALL_PAGE_SIZE_X\r
+\r
+IDD_FOLDERS_2  MY_PAGE\r
+#include "FoldersPage2.rc"\r
+\r
+#endif\r
+\r
+STRINGTABLE\r
+BEGIN\r
+  IDS_FOLDERS_SET_WORK_PATH_TITLE  "Specify a location for temporary archive files."\r
+END\r
diff --git a/CPP/7zip/UI/FileManager/FoldersPage2.rc b/CPP/7zip/UI/FileManager/FoldersPage2.rc
new file mode 100755 (executable)
index 0000000..e5c10e4
--- /dev/null
@@ -0,0 +1,16 @@
+CAPTION "Folders"\r
+BEGIN\r
+  // GROUPBOX   "&Working folder", IDC_FOLDERS_STATIC_WORKING_FOLDER, m, m, xc, 98\r
+\r
+  LTEXT      "&Working folder", IDC_FOLDERS_STATIC_WORKING_FOLDER, m, m, xc, 8\r
+  CONTROL    "&System temp folder", IDC_FOLDERS_WORK_RADIO_SYSTEM,    "Button", BS_AUTORADIOBUTTON | WS_GROUP,\r
+             m, 20, xc, 10\r
+  CONTROL    "&Current",            IDC_FOLDERS_WORK_RADIO_CURRENT,   "Button", BS_AUTORADIOBUTTON,\r
+             m, 34, xc, 10\r
+  CONTROL    "Specified:",          IDC_FOLDERS_WORK_RADIO_SPECIFIED, "Button", BS_AUTORADIOBUTTON,\r
+             m, 48, xc, 10\r
+  EDITTEXT   IDC_FOLDERS_WORK_EDIT_PATH, m + m, 62, xc - m - m - bxsDots, 14, ES_AUTOHSCROLL\r
+  PUSHBUTTON "...", IDC_FOLDERS_WORK_BUTTON_PATH, xs - m - bxsDots, 61, bxsDots, bys\r
+  CONTROL    "Use for removable drives only", IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE, MY_CHECKBOX,\r
+             m, 86, xc, 10\r
+END\r
diff --git a/CPP/7zip/UI/FileManager/FoldersPageRes.h b/CPP/7zip/UI/FileManager/FoldersPageRes.h
new file mode 100755 (executable)
index 0000000..3cd6742
--- /dev/null
@@ -0,0 +1,13 @@
+#define IDD_FOLDERS 571\r
+#define IDD_FOLDERS_2 671\r
+\r
+#define IDS_FOLDERS_SET_WORK_PATH_TITLE  877\r
+\r
+#define IDC_FOLDERS_STATIC_WORKING_FOLDER 1001\r
+\r
+#define IDC_FOLDERS_WORK_RADIO_SYSTEM    1011\r
+#define IDC_FOLDERS_WORK_RADIO_CURRENT   1012\r
+#define IDC_FOLDERS_WORK_RADIO_SPECIFIED 1013\r
+#define IDC_FOLDERS_WORK_EDIT_PATH       1014\r
+#define IDC_FOLDERS_WORK_BUTTON_PATH     1015\r
+#define IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE 1017\r
diff --git a/CPP/7zip/UI/FileManager/FormatUtils.cpp b/CPP/7zip/UI/FileManager/FormatUtils.cpp
new file mode 100755 (executable)
index 0000000..0f20a5b
--- /dev/null
@@ -0,0 +1,40 @@
+// FormatUtils.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "FormatUtils.h"\r
+#include "Common/IntToString.h"\r
+#include "Windows/ResourceString.h"\r
+\r
+#ifdef LANG\r
+#include "LangUtils.h"\r
+#endif\r
+\r
+UString NumberToString(UInt64 number)\r
+{\r
+  wchar_t numberString[32];\r
+  ConvertUInt64ToString(number, numberString);\r
+  return numberString;\r
+}\r
+\r
+UString MyFormatNew(const UString &format, const UString &argument)\r
+{\r
+  UString result = format;\r
+  result.Replace(L"{0}", argument);\r
+  return result;\r
+}\r
+\r
+UString MyFormatNew(UINT resourceID,\r
+    #ifdef LANG\r
+    UInt32 langID,\r
+    #endif\r
+    const UString &argument)\r
+{\r
+  return MyFormatNew(\r
+    #ifdef LANG\r
+    LangString(resourceID, langID),\r
+    #else\r
+    NWindows::MyLoadStringW(resourceID),\r
+    #endif\r
+    argument);\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/FormatUtils.h b/CPP/7zip/UI/FileManager/FormatUtils.h
new file mode 100755 (executable)
index 0000000..84d72ad
--- /dev/null
@@ -0,0 +1,18 @@
+// FormatUtils.h\r
+\r
+#ifndef __FORMATUTILS_H\r
+#define __FORMATUTILS_H\r
+\r
+#include "Common/Types.h"\r
+#include "Common/MyString.h"\r
+\r
+UString NumberToString(UInt64 number);\r
+\r
+UString MyFormatNew(const UString &format, const UString &argument);\r
+UString MyFormatNew(UINT resourceID,\r
+    #ifdef LANG\r
+    UInt32 langID,\r
+    #endif\r
+    const UString &argument);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/HelpUtils.cpp b/CPP/7zip/UI/FileManager/HelpUtils.cpp
new file mode 100755 (executable)
index 0000000..f92835e
--- /dev/null
@@ -0,0 +1,27 @@
+// HelpUtils.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include <HtmlHelp.h>\r
+\r
+#include "Common/StringConvert.h"\r
+#include "HelpUtils.h"\r
+#include "ProgramLocation.h"\r
+\r
+static LPCWSTR kHelpFileName = L"7-zip.chm::/";\r
+\r
+#ifdef UNDER_CE\r
+void ShowHelpWindow(HWND, LPCWSTR)\r
+{\r
+}\r
+#else\r
+void ShowHelpWindow(HWND hwnd, LPCWSTR topicFile)\r
+{\r
+  UString path;\r
+  if (!::GetProgramFolderPath(path))\r
+    return;\r
+  path += kHelpFileName;\r
+  path += topicFile;\r
+  HtmlHelp(hwnd, GetSystemString(path), HH_DISPLAY_TOPIC, NULL);\r
+}\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/HelpUtils.h b/CPP/7zip/UI/FileManager/HelpUtils.h
new file mode 100755 (executable)
index 0000000..fd6fb42
--- /dev/null
@@ -0,0 +1,10 @@
+// HelpUtils.h\r
+\r
+#ifndef __HELPUTILS_H\r
+#define __HELPUTILS_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+void ShowHelpWindow(HWND hwnd, LPCWSTR topicFile);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/IFolder.h b/CPP/7zip/UI/FileManager/IFolder.h
new file mode 100755 (executable)
index 0000000..118c42d
--- /dev/null
@@ -0,0 +1,161 @@
+// IFolder.h\r
+\r
+#ifndef __IFOLDER_H\r
+#define __IFOLDER_H\r
+\r
+#include "../../IProgress.h"\r
+#include "../../IStream.h"\r
+\r
+#define FOLDER_INTERFACE_SUB(i, b, x) DECL_INTERFACE_SUB(i, b, 8, x)\r
+#define FOLDER_INTERFACE(i, x) FOLDER_INTERFACE_SUB(i, IUnknown, x)\r
+\r
+namespace NPlugin\r
+{\r
+  enum\r
+  {\r
+    kName = 0,\r
+    kType,\r
+    kClassID,\r
+    kOptionsClassID\r
+  };\r
+}\r
+\r
+#define INTERFACE_FolderFolder(x) \\r
+  STDMETHOD(LoadItems)() x; \\r
+  STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \\r
+  STDMETHOD(GetProperty)(UInt32 itemIndex, PROPID propID, PROPVARIANT *value) x; \\r
+  STDMETHOD(BindToFolder)(UInt32 index, IFolderFolder **resultFolder) x; \\r
+  STDMETHOD(BindToFolder)(const wchar_t *name, IFolderFolder **resultFolder) x; \\r
+  STDMETHOD(BindToParentFolder)(IFolderFolder **resultFolder) x; \\r
+  STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \\r
+  STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \\r
+  STDMETHOD(GetFolderProperty)(PROPID propID, PROPVARIANT *value) x; \\r
+\r
+FOLDER_INTERFACE(IFolderFolder, 0x00)\r
+{\r
+  INTERFACE_FolderFolder(PURE)\r
+};\r
+\r
+FOLDER_INTERFACE(IFolderWasChanged, 0x04)\r
+{\r
+  STDMETHOD(WasChanged)(Int32 *wasChanged) PURE;\r
+};\r
+\r
+FOLDER_INTERFACE_SUB(IFolderOperationsExtractCallback, IProgress, 0x0B)\r
+{\r
+  // STDMETHOD(SetTotalFiles)(UInt64 total) PURE;\r
+  // STDMETHOD(SetCompletedFiles)(const UInt64 *completedValue) PURE;\r
+  STDMETHOD(AskWrite)(\r
+      const wchar_t *srcPath,\r
+      Int32 srcIsFolder,\r
+      const FILETIME *srcTime,\r
+      const UInt64 *srcSize,\r
+      const wchar_t *destPathRequest,\r
+      BSTR *destPathResult,\r
+      Int32 *writeAnswer) PURE;\r
+  STDMETHOD(ShowMessage)(const wchar_t *message) PURE;\r
+  STDMETHOD(SetCurrentFilePath)(const wchar_t *filePath) PURE;\r
+  STDMETHOD(SetNumFiles)(UInt64 numFiles) PURE;\r
+};\r
+\r
+#define INTERFACE_FolderOperations(x) \\r
+  STDMETHOD(CreateFolder)(const wchar_t *name, IProgress *progress) x; \\r
+  STDMETHOD(CreateFile)(const wchar_t *name, IProgress *progress) x; \\r
+  STDMETHOD(Rename)(UInt32 index, const wchar_t *newName, IProgress *progress) x; \\r
+  STDMETHOD(Delete)(const UInt32 *indices, UInt32 numItems, IProgress *progress) x; \\r
+  STDMETHOD(CopyTo)(const UInt32 *indices, UInt32 numItems, \\r
+      const wchar_t *path, IFolderOperationsExtractCallback *callback) x; \\r
+  STDMETHOD(MoveTo)(const UInt32 *indices, UInt32 numItems, \\r
+      const wchar_t *path, IFolderOperationsExtractCallback *callback) x; \\r
+  STDMETHOD(CopyFrom)(const wchar_t *fromFolderPath, \\r
+      const wchar_t **itemsPaths, UInt32 numItems, IProgress *progress) x; \\r
+  STDMETHOD(SetProperty)(UInt32 index, PROPID propID, const PROPVARIANT *value, IProgress *progress) x; \\r
+\r
+FOLDER_INTERFACE(IFolderOperations, 0x06)\r
+{\r
+  INTERFACE_FolderOperations(PURE)\r
+};\r
+\r
+/*\r
+FOLDER_INTERFACE2(IFolderOperationsDeleteToRecycleBin, 0x06, 0x03)\r
+{\r
+  STDMETHOD(DeleteToRecycleBin)(const UInt32 *indices, UInt32 numItems, IProgress *progress) PURE;\r
+};\r
+*/\r
+\r
+FOLDER_INTERFACE(IFolderGetSystemIconIndex, 0x07)\r
+{\r
+  STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex) PURE;\r
+};\r
+\r
+FOLDER_INTERFACE(IFolderGetItemFullSize, 0x08)\r
+{\r
+  STDMETHOD(GetItemFullSize)(UInt32 index, PROPVARIANT *value, IProgress *progress) PURE;\r
+};\r
+\r
+FOLDER_INTERFACE(IFolderClone, 0x09)\r
+{\r
+  STDMETHOD(Clone)(IFolderFolder **resultFolder) PURE;\r
+};\r
+\r
+FOLDER_INTERFACE(IFolderSetFlatMode, 0x0A)\r
+{\r
+  STDMETHOD(SetFlatMode)(Int32 flatMode) PURE;\r
+};\r
+\r
+#define INTERFACE_FolderProperties(x) \\r
+  STDMETHOD(GetNumberOfFolderProperties)(UInt32 *numProperties) x; \\r
+  STDMETHOD(GetFolderPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \\r
+\r
+FOLDER_INTERFACE(IFolderProperties, 0x0E)\r
+{\r
+  INTERFACE_FolderProperties(PURE)\r
+};\r
+\r
+#define INTERFACE_IFolderArcProps(x) \\r
+  STDMETHOD(GetArcNumLevels)(UInt32 *numLevels) x; \\r
+  STDMETHOD(GetArcProp)(UInt32 level, PROPID propID, PROPVARIANT *value) x; \\r
+  STDMETHOD(GetArcNumProps)(UInt32 level, UInt32 *numProps) x; \\r
+  STDMETHOD(GetArcPropInfo)(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \\r
+  STDMETHOD(GetArcProp2)(UInt32 level, PROPID propID, PROPVARIANT *value) x; \\r
+  STDMETHOD(GetArcNumProps2)(UInt32 level, UInt32 *numProps) x; \\r
+  STDMETHOD(GetArcPropInfo2)(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \\r
+\r
+FOLDER_INTERFACE(IFolderArcProps, 0x10)\r
+{\r
+  INTERFACE_IFolderArcProps(PURE)\r
+};\r
+\r
+FOLDER_INTERFACE(IGetFolderArcProps, 0x11)\r
+{\r
+  STDMETHOD(GetFolderArcProps)(IFolderArcProps **object) PURE;\r
+};\r
+\r
+#define FOLDER_MANAGER_INTERFACE(i, x)  DECL_INTERFACE(i, 9, x)\r
+\r
+#define INTERFACE_IFolderManager(x) \\r
+  STDMETHOD(OpenFolderFile)(IInStream *inStream, const wchar_t *filePath, const wchar_t *arcFormat, IFolderFolder **resultFolder, IProgress *progress) x; \\r
+  STDMETHOD(GetExtensions)(BSTR *extensions) x; \\r
+  STDMETHOD(GetIconPath)(const wchar_t *ext, BSTR *iconPath, Int32 *iconIndex) x; \\r
+  \r
+  // STDMETHOD(GetTypes)(BSTR *types) PURE;\r
+  // STDMETHOD(CreateFolderFile)(const wchar_t *type, const wchar_t *filePath, IProgress *progress) PURE;\r
+            \r
+FOLDER_MANAGER_INTERFACE(IFolderManager, 0x05)\r
+{\r
+  INTERFACE_IFolderManager(PURE);\r
+};\r
+\r
+\r
+#define IMP_IFolderFolder_GetProp(k) \\r
+  (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \\r
+    { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \\r
+    const STATPROPSTG &srcItem = k[index]; \\r
+    *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \\r
+\r
+#define IMP_IFolderFolder_Props(c) \\r
+  STDMETHODIMP c::GetNumberOfProperties(UInt32 *numProperties) \\r
+    { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \\r
+  STDMETHODIMP c::GetPropertyInfo IMP_IFolderFolder_GetProp(kProps)\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/Info.bmp b/CPP/7zip/UI/FileManager/Info.bmp
new file mode 100755 (executable)
index 0000000..d769a66
Binary files /dev/null and b/CPP/7zip/UI/FileManager/Info.bmp differ
diff --git a/CPP/7zip/UI/FileManager/Info2.bmp b/CPP/7zip/UI/FileManager/Info2.bmp
new file mode 100755 (executable)
index 0000000..af724d2
Binary files /dev/null and b/CPP/7zip/UI/FileManager/Info2.bmp differ
diff --git a/CPP/7zip/UI/FileManager/LangPage.cpp b/CPP/7zip/UI/FileManager/LangPage.cpp
new file mode 100755 (executable)
index 0000000..629bb7d
--- /dev/null
@@ -0,0 +1,83 @@
+// LangPage.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/ResourceString.h"\r
+\r
+#include "HelpUtils.h"\r
+#include "LangPage.h"\r
+#include "LangPageRes.h"\r
+#include "LangUtils.h"\r
+#include "RegistryUtils.h"\r
+\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDC_LANG_STATIC_LANG, 0x01000401}\r
+};\r
+\r
+static LPCWSTR kLangTopic = L"fm/options.htm#language";\r
+\r
+static UString NativeLangString(const UString &s)\r
+{\r
+  return L" (" + s + L')';\r
+}\r
+\r
+bool CLangPage::OnInit()\r
+{\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+\r
+  _langCombo.Attach(GetItem(IDC_LANG_COMBO_LANG));\r
+\r
+  UString s = NWindows::MyLoadStringW(IDS_LANG_ENGLISH) +\r
+      NativeLangString(NWindows::MyLoadStringW(IDS_LANG_NATIVE));\r
+  int index = (int)_langCombo.AddString(s);\r
+  _langCombo.SetItemData(index, _paths.Size());\r
+  _paths.Add(L"-");\r
+  _langCombo.SetCurSel(0);\r
+\r
+  CObjectVector<CLangEx> langs;\r
+  LoadLangs(langs);\r
+  for (int i = 0; i < langs.Size(); i++)\r
+  {\r
+    const CLangEx &lang = langs[i];\r
+    UString name, nationalName;\r
+    if (!lang.Lang.GetMessage(0, name))\r
+      name = lang.ShortName;\r
+    if (lang.Lang.GetMessage(1, nationalName) && !nationalName.IsEmpty())\r
+      name += NativeLangString(nationalName);\r
+\r
+    index = (int)_langCombo.AddString(name);\r
+    _langCombo.SetItemData(index, _paths.Size());\r
+    _paths.Add(lang.ShortName);\r
+    if (g_LangID.CompareNoCase(lang.ShortName) == 0)\r
+      _langCombo.SetCurSel(index);\r
+  }\r
+  return CPropertyPage::OnInit();\r
+}\r
+\r
+LONG CLangPage::OnApply()\r
+{\r
+  int selectedIndex = _langCombo.GetCurSel();\r
+  int pathIndex = (int)_langCombo.GetItemData(selectedIndex);\r
+  SaveRegLang(_paths[pathIndex]);\r
+  ReloadLang();\r
+  LangWasChanged = true;\r
+  return PSNRET_NOERROR;\r
+}\r
+\r
+void CLangPage::OnNotifyHelp()\r
+{\r
+  ShowHelpWindow(NULL, kLangTopic);\r
+}\r
+\r
+bool CLangPage::OnCommand(int code, int itemID, LPARAM param)\r
+{\r
+  if (code == CBN_SELCHANGE && itemID == IDC_LANG_COMBO_LANG)\r
+  {\r
+    Changed();\r
+    return true;\r
+  }\r
+  return CPropertyPage::OnCommand(code, itemID, param);\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/LangPage.h b/CPP/7zip/UI/FileManager/LangPage.h
new file mode 100755 (executable)
index 0000000..8b63469
--- /dev/null
@@ -0,0 +1,22 @@
+// LangPage.h\r
\r
+#ifndef __LANG_PAGE_H\r
+#define __LANG_PAGE_H\r
+\r
+#include "Windows/Control/PropertyPage.h"\r
+#include "Windows/Control/ComboBox.h"\r
+\r
+class CLangPage: public NWindows::NControl::CPropertyPage\r
+{\r
+  NWindows::NControl::CComboBox _langCombo;\r
+  UStringVector _paths;\r
+public:\r
+  bool LangWasChanged;\r
+  CLangPage() { LangWasChanged =  false; }\r
+  virtual bool OnInit();\r
+  virtual void OnNotifyHelp();\r
+  virtual bool OnCommand(int code, int itemID, LPARAM param);\r
+  virtual LONG OnApply();\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/LangPage.rc b/CPP/7zip/UI/FileManager/LangPage.rc
new file mode 100755 (executable)
index 0000000..8134d6f
--- /dev/null
@@ -0,0 +1,37 @@
+#include "LangPageRes.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#define xc 148\r
+#define yc 100\r
+\r
+IDD_LANG  MY_PAGE\r
+CAPTION "Language"\r
+{\r
+  LTEXT     "Language:", IDC_LANG_STATIC_LANG, m, m, xc, 8\r
+  COMBOBOX  IDC_LANG_COMBO_LANG, m, 20, xc, yc - 20, MY_COMBO_SORTED\r
+}\r
+\r
+\r
+#ifdef UNDER_CE\r
+\r
+#undef m\r
+#undef xc\r
+\r
+#define m 4\r
+#define xc (SMALL_PAGE_SIZE_X + 8)\r
+\r
+IDD_LANG_2  MY_PAGE\r
+CAPTION "Language"\r
+{\r
+  LTEXT     "Language:", IDC_LANG_STATIC_LANG, m, m, xc, 8\r
+  COMBOBOX  IDC_LANG_COMBO_LANG, m, 20, xc, yc - 20, MY_COMBO_SORTED\r
+}\r
+\r
+#endif\r
+\r
+\r
+STRINGTABLE\r
+BEGIN\r
+  IDS_LANG_ENGLISH  "English"\r
+  IDS_LANG_NATIVE   "English"\r
+END\r
diff --git a/CPP/7zip/UI/FileManager/LangPageRes.h b/CPP/7zip/UI/FileManager/LangPageRes.h
new file mode 100755 (executable)
index 0000000..fc2dcc7
--- /dev/null
@@ -0,0 +1,8 @@
+#define IDD_LANG           544\r
+#define IDD_LANG_2         644\r
+\r
+#define IDS_LANG_ENGLISH   995\r
+#define IDS_LANG_NATIVE    996\r
+\r
+#define IDC_LANG_STATIC_LANG            1000\r
+#define IDC_LANG_COMBO_LANG             1001\r
diff --git a/CPP/7zip/UI/FileManager/LangUtils.cpp b/CPP/7zip/UI/FileManager/LangUtils.cpp
new file mode 100755 (executable)
index 0000000..5786874
--- /dev/null
@@ -0,0 +1,208 @@
+// LangUtils.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "LangUtils.h"\r
+#include "Common/StringConvert.h"\r
+#include "Common/StringToInt.h"\r
+#include "Windows/Synchronization.h"\r
+#include "Windows/Window.h"\r
+#include "Windows/FileFind.h"\r
+#include "RegistryUtils.h"\r
+#include "ProgramLocation.h"\r
+\r
+using namespace NWindows;\r
+\r
+static CLang g_Lang;\r
+UString g_LangID;\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+void ReloadLang()\r
+{\r
+  ReadRegLang(g_LangID);\r
+  g_Lang.Clear();\r
+  if (!g_LangID.IsEmpty() && g_LangID != L"-")\r
+  {\r
+    UString langPath = g_LangID;\r
+    if (langPath.Find(WCHAR_PATH_SEPARATOR) < 0)\r
+    {\r
+      if (langPath.Find(L'.') < 0)\r
+        langPath += L".txt";\r
+      UString folderPath;\r
+      if (GetProgramFolderPath(folderPath))\r
+        langPath = folderPath + UString(L"Lang" WSTRING_PATH_SEPARATOR) + langPath;\r
+    }\r
+    g_Lang.Open(langPath);\r
+  }\r
+}\r
+\r
+static bool g_Loaded = false;\r
+static NSynchronization::CCriticalSection g_CriticalSection;\r
+\r
+void LoadLangOneTime()\r
+{\r
+  NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\r
+  if (g_Loaded)\r
+    return;\r
+  g_Loaded = true;\r
+  ReloadLang();\r
+}\r
+\r
+void LangSetDlgItemsText(HWND dialogWindow, CIDLangPair *idLangPairs, int numItems)\r
+{\r
+  for (int i = 0; i < numItems; i++)\r
+  {\r
+    const CIDLangPair &idLangPair = idLangPairs[i];\r
+    UString message;\r
+    if (g_Lang.GetMessage(idLangPair.LangID, message))\r
+    {\r
+      NWindows::CWindow window(GetDlgItem(dialogWindow, idLangPair.ControlID));\r
+      window.SetText(message);\r
+    }\r
+  }\r
+}\r
+\r
+void LangSetWindowText(HWND window, UInt32 langID)\r
+{\r
+  UString message;\r
+  if (g_Lang.GetMessage(langID, message))\r
+    MySetWindowText(window, message);\r
+}\r
+\r
+UString LangString(UInt32 langID)\r
+{\r
+  UString message;\r
+  if (g_Lang.GetMessage(langID, message))\r
+    return message;\r
+  return UString();\r
+}\r
+\r
+UString LangString(UINT resourceID, UInt32 langID)\r
+{\r
+  UString message;\r
+  if (g_Lang.GetMessage(langID, message))\r
+    return message;\r
+  return NWindows::MyLoadStringW(resourceID);\r
+}\r
+\r
+void LoadLangs(CObjectVector<CLangEx> &langs)\r
+{\r
+  langs.Clear();\r
+  UString folderPath;\r
+  if (!::GetProgramFolderPath(folderPath))\r
+    return;\r
+  folderPath += L"Lang" WSTRING_PATH_SEPARATOR;\r
+  NWindows::NFile::NFind::CEnumeratorW enumerator(folderPath + L"*.txt");\r
+  NWindows::NFile::NFind::CFileInfoW fileInfo;\r
+  while (enumerator.Next(fileInfo))\r
+  {\r
+    if (fileInfo.IsDir())\r
+      continue;\r
+    CLangEx lang;\r
+    UString filePath = folderPath + fileInfo.Name;\r
+    const int kExtSize = 4;\r
+    const UString ext = fileInfo.Name.Right(kExtSize);\r
+    if (ext.CompareNoCase(L".txt") != 0)\r
+      continue;\r
+    lang.ShortName = fileInfo.Name.Left(fileInfo.Name.Length() - kExtSize);\r
+    if (lang.Lang.Open(filePath))\r
+      langs.Add(lang);\r
+  }\r
+}\r
+\r
+bool SplidID(const UString &id, WORD &primID, WORD &subID)\r
+{\r
+  primID = 0;\r
+  subID = 0;\r
+  const wchar_t *start = id;\r
+  const wchar_t *end;\r
+  UInt64 value = ConvertStringToUInt64(start, &end);\r
+  if (start == end)\r
+    return false;\r
+  primID = (WORD)value;\r
+  if (*end == 0)\r
+    return true;\r
+  if (*end != L'-')\r
+    return false;\r
+  start = end + 1;\r
+  value = ConvertStringToUInt64(start, &end);\r
+  if (start == end)\r
+    return false;\r
+  subID = (WORD)value;\r
+  return (*end == 0);\r
+}\r
+\r
+typedef LANGID (WINAPI *GetUserDefaultUILanguageP)();\r
+\r
+void FindMatchLang(UString &shortName)\r
+{\r
+  shortName.Empty();\r
+\r
+  LANGID SystemDefaultLangID = GetSystemDefaultLangID(); // Lang for non-Unicode in XP64\r
+  LANGID UserDefaultLangID = GetUserDefaultLangID(); // Standarts and formats in XP64\r
+\r
+  if (SystemDefaultLangID != UserDefaultLangID)\r
+    return;\r
+  LANGID langID = UserDefaultLangID;\r
+  /*\r
+  LANGID SystemDefaultUILanguage; // english  in XP64\r
+  LANGID UserDefaultUILanguage; // english  in XP64\r
+\r
+  GetUserDefaultUILanguageP fn = (GetUserDefaultUILanguageP)GetProcAddress(\r
+      GetModuleHandle("kernel32"), "GetUserDefaultUILanguage");\r
+  if (fn != NULL)\r
+    UserDefaultUILanguage = fn();\r
+  fn = (GetUserDefaultUILanguageP)GetProcAddress(\r
+      GetModuleHandle("kernel32"), "GetSystemDefaultUILanguage");\r
+  if (fn != NULL)\r
+    SystemDefaultUILanguage = fn();\r
+  */\r
+\r
+  WORD primLang = (WORD)(PRIMARYLANGID(langID));\r
+  WORD subLang = (WORD)(SUBLANGID(langID));\r
+  CObjectVector<CLangEx> langs;\r
+  LoadLangs(langs);\r
+  for (int i = 0; i < langs.Size(); i++)\r
+  {\r
+    const CLangEx &lang = langs[i];\r
+    UString id;\r
+    if (lang.Lang.GetMessage(0x00000002, id))\r
+    {\r
+      WORD primID;\r
+      WORD subID;\r
+      if (SplidID(id, primID, subID))\r
+        if (primID == primLang)\r
+        {\r
+          if (subID == 0)\r
+            shortName = lang.ShortName;\r
+          if (subLang == subID)\r
+          {\r
+            shortName = lang.ShortName;\r
+            return;\r
+          }\r
+        }\r
+    }\r
+  }\r
+}\r
+\r
+void ReloadLangSmart()\r
+{\r
+  #ifndef _UNICODE\r
+  if (g_IsNT)\r
+  #endif\r
+  {\r
+    ReadRegLang(g_LangID);\r
+    if (g_LangID.IsEmpty())\r
+    {\r
+      UString shortName;\r
+      FindMatchLang(shortName);\r
+      if (shortName.IsEmpty())\r
+        shortName = L"-";\r
+      SaveRegLang(shortName);\r
+    }\r
+  }\r
+  ReloadLang();\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/LangUtils.h b/CPP/7zip/UI/FileManager/LangUtils.h
new file mode 100755 (executable)
index 0000000..8a031be
--- /dev/null
@@ -0,0 +1,41 @@
+// LangUtils.h\r
+\r
+#ifndef __LANGUTILS_H\r
+#define __LANGUTILS_H\r
+\r
+#include "Common/Lang.h"\r
+#include "Windows/ResourceString.h"\r
+\r
+extern UString g_LangID;\r
+\r
+struct CIDLangPair\r
+{\r
+  int ControlID;\r
+  UInt32 LangID;\r
+};\r
+\r
+void ReloadLang();\r
+void LoadLangOneTime();\r
+void ReloadLangSmart();\r
+\r
+struct CLangEx\r
+{\r
+  CLang Lang;\r
+  UString ShortName;\r
+};\r
+\r
+void LoadLangs(CObjectVector<CLangEx> &langs);\r
+\r
+void LangSetDlgItemsText(HWND dialogWindow, CIDLangPair *idLangPairs, int numItems);\r
+void LangSetWindowText(HWND window, UInt32 langID);\r
+\r
+UString LangString(UInt32 langID);\r
+UString LangString(UINT resourceID, UInt32 langID);\r
+\r
+#ifdef LANG\r
+#define LangStringSpec(resourceID, langID) LangString(resourceID, langID)\r
+#else\r
+#define LangStringSpec(resourceID, langID) NWindows::MyLoadStringW(resourceID)\r
+#endif\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/ListViewDialog.cpp b/CPP/7zip/UI/FileManager/ListViewDialog.cpp
new file mode 100755 (executable)
index 0000000..11399f9
--- /dev/null
@@ -0,0 +1,150 @@
+// ListViewDialog.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "ListViewDialog.h"\r
+#include "RegistryUtils.h"\r
+\r
+#ifdef LANG\r
+#include "LangUtils.h"\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDOK, 0x02000702 },\r
+  { IDCANCEL, 0x02000710 }\r
+};\r
+#endif\r
+\r
+bool CListViewDialog::OnInit()\r
+{\r
+  #ifdef LANG\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+  #endif\r
+  _listView.Attach(GetItem(IDC_LISTVIEW_LIST));\r
+\r
+  if (ReadSingleClick())\r
+    _listView.SetExtendedListViewStyle(LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT);\r
+\r
+  SetText(Title);\r
+\r
+  LVCOLUMN columnInfo;\r
+  columnInfo.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM;\r
+  columnInfo.fmt = LVCFMT_LEFT;\r
+  columnInfo.iSubItem = 0;\r
+  columnInfo.cx = 200;\r
+\r
+  _listView.InsertColumn(0, &columnInfo);\r
+\r
+  for (int i = 0; i < Strings.Size(); i++)\r
+    _listView.InsertItem(i, Strings[i]);\r
+\r
+  if (Strings.Size() > 0)\r
+    _listView.SetItemState_FocusedSelected(0);\r
+\r
+  _listView.SetColumnWidthAuto(0);\r
+  StringsWereChanged = false;\r
+\r
+  NormalizeSize();\r
+  return CModalDialog::OnInit();\r
+}\r
+\r
+bool CListViewDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)\r
+{\r
+  int mx, my;\r
+  GetMargins(8, mx, my);\r
+  int bx1, bx2, by;\r
+  GetItemSizes(IDCANCEL, bx1, by);\r
+  GetItemSizes(IDOK, bx2, by);\r
+  int y = ySize - my - by;\r
+  int x = xSize - mx - bx1;\r
+\r
+  /*\r
+  RECT rect;\r
+  GetClientRect(&rect);\r
+  rect.top = y - my;\r
+  InvalidateRect(&rect);\r
+  */\r
+  InvalidateRect(NULL);\r
+\r
+  MoveItem(IDCANCEL, x, y, bx1, by);\r
+  MoveItem(IDOK, x - mx - bx2, y, bx2, by);\r
+  /*\r
+  if (wParam == SIZE_MAXSHOW || wParam == SIZE_MAXIMIZED || wParam == SIZE_MAXHIDE)\r
+    mx = 0;\r
+  */\r
+  _listView.Move(mx, my, xSize - mx * 2, y - my * 2);\r
+  return false;\r
+}\r
+\r
+extern bool g_LVN_ITEMACTIVATE_Support;\r
+\r
+bool CListViewDialog::OnNotify(UINT /* controlID */, LPNMHDR header)\r
+{\r
+  if (header->hwndFrom != _listView)\r
+    return false;\r
+  switch(header->code)\r
+  {\r
+    case LVN_ITEMACTIVATE:\r
+      if (g_LVN_ITEMACTIVATE_Support)\r
+      {\r
+        OnOK();\r
+        return true;\r
+      }\r
+      break;\r
+    case NM_DBLCLK:\r
+    case NM_RETURN: // probabably it's unused\r
+      if (!g_LVN_ITEMACTIVATE_Support)\r
+      {\r
+        OnOK();\r
+        return true;\r
+      }\r
+      break;\r
+\r
+    case LVN_KEYDOWN:\r
+    {\r
+      LPNMLVKEYDOWN keyDownInfo = LPNMLVKEYDOWN(header);\r
+      switch(keyDownInfo->wVKey)\r
+      {\r
+        case VK_DELETE:\r
+        {\r
+          if (!DeleteIsAllowed)\r
+            return false;\r
+          for (;;)\r
+          {\r
+            int index = _listView.GetNextSelectedItem(-1);\r
+            if (index < 0)\r
+              break;\r
+            StringsWereChanged = true;\r
+            _listView.DeleteItem(index);\r
+            Strings.Delete(index);\r
+          }\r
+          int focusedIndex = _listView.GetFocusedItem();\r
+          if (focusedIndex >= 0)\r
+            _listView.SetItemState_FocusedSelected(focusedIndex);\r
+          _listView.SetColumnWidthAuto(0);\r
+          return true;\r
+        }\r
+        case 'A':\r
+        {\r
+          // probably that code is unused ?\r
+          /*\r
+          bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0;\r
+          if (ctrl)\r
+          {\r
+            int numItems = _listView.GetItemCount();\r
+            for (int i = 0; i < numItems; i++)\r
+              _listView.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED);\r
+            return true;\r
+          }\r
+          */\r
+        }\r
+      }\r
+    }\r
+  }\r
+  return false;\r
+}\r
+\r
+void CListViewDialog::OnOK()\r
+{\r
+  FocusedItemIndex = _listView.GetFocusedItem();\r
+  CModalDialog::OnOK();\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/ListViewDialog.h b/CPP/7zip/UI/FileManager/ListViewDialog.h
new file mode 100755 (executable)
index 0000000..997d97f
--- /dev/null
@@ -0,0 +1,30 @@
+// ListViewDialog.h\r
+\r
+#ifndef __LISTVIEW_DIALOG_H\r
+#define __LISTVIEW_DIALOG_H\r
+\r
+#include "Windows/Control/Dialog.h"\r
+#include "Windows/Control/ListView.h"\r
+\r
+#include "ListViewDialogRes.h"\r
+\r
+class CListViewDialog: public NWindows::NControl::CModalDialog\r
+{\r
+  NWindows::NControl::CListView _listView;\r
+  virtual void OnOK();\r
+  virtual bool OnInit();\r
+  virtual bool OnSize(WPARAM wParam, int xSize, int ySize);\r
+  virtual bool OnNotify(UINT controlID, LPNMHDR header);\r
+public:\r
+  UString Title;\r
+  bool DeleteIsAllowed;\r
+  bool StringsWereChanged;\r
+  UStringVector Strings;\r
+  int FocusedItemIndex;\r
+\r
+  INT_PTR Create(HWND wndParent = 0) { return CModalDialog::Create(IDD_DIALOG_LISTVIEW, wndParent); }\r
+\r
+  CListViewDialog(): DeleteIsAllowed(false) {}\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/ListViewDialog.rc b/CPP/7zip/UI/FileManager/ListViewDialog.rc
new file mode 100755 (executable)
index 0000000..e707e52
--- /dev/null
@@ -0,0 +1,14 @@
+#include "ListViewDialogRes.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#define xc 320\r
+#define yc 240\r
+\r
+IDD_DIALOG_LISTVIEW  MY_RESIZE_DIALOG\r
+CAPTION "ListView"\r
+{\r
+  CONTROL  "List1", IDC_LISTVIEW_LIST, "SysListView32", LVS_REPORT | LVS_SHOWSELALWAYS |\r
+            LVS_AUTOARRANGE | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,\r
+            m, m, xc, yc - bys - m\r
+  OK_CANCEL\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/ListViewDialogRes.h b/CPP/7zip/UI/FileManager/ListViewDialogRes.h
new file mode 100755 (executable)
index 0000000..44d366a
--- /dev/null
@@ -0,0 +1,2 @@
+#define IDD_DIALOG_LISTVIEW 508\r
+#define IDC_LISTVIEW_LIST 1000\r
diff --git a/CPP/7zip/UI/FileManager/MenuPage.cpp b/CPP/7zip/UI/FileManager/MenuPage.cpp
new file mode 100755 (executable)
index 0000000..2eb4005
--- /dev/null
@@ -0,0 +1,203 @@
+// MenuPage.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../Common/ZipRegistry.h"\r
+\r
+#include "../Explorer/ContextMenuFlags.h"\r
+#include "../Explorer/RegistryContextMenu.h"\r
+#include "../Explorer/resource.h"\r
+\r
+#include "HelpUtils.h"\r
+#include "LangUtils.h"\r
+#include "MenuPage.h"\r
+#include "MenuPageRes.h"\r
+#include "FormatUtils.h"\r
+\r
+using namespace NContextMenuFlags;\r
+\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, 0x01000301},\r
+  { IDC_SYSTEM_CASCADED_MENU, 0x01000302},\r
+  { IDC_SYSTEM_STATIC_CONTEXT_MENU_ITEMS, 0x01000310}\r
+};\r
+\r
+static LPCWSTR kSystemTopic = L"fm/plugins/7-zip/options.htm#system";\r
+\r
+struct CContextMenuItem\r
+{\r
+  int ControlID;\r
+  UInt32 LangID;\r
+  UInt32 Flag;\r
+};\r
+\r
+static CContextMenuItem kMenuItems[] =\r
+{\r
+  { IDS_CONTEXT_OPEN, 0x02000103, kOpen},\r
+  { IDS_CONTEXT_OPEN, 0x02000103, kOpenAs},\r
+  { IDS_CONTEXT_EXTRACT, 0x02000105, kExtract},\r
+  { IDS_CONTEXT_EXTRACT_HERE, 0x0200010B, kExtractHere },\r
+  { IDS_CONTEXT_EXTRACT_TO, 0x0200010D, kExtractTo },\r
+\r
+  { IDS_CONTEXT_TEST, 0x02000109, kTest},\r
+\r
+  { IDS_CONTEXT_COMPRESS, 0x02000107, kCompress },\r
+  { IDS_CONTEXT_COMPRESS_TO, 0x0200010F, kCompressTo7z },\r
+  { IDS_CONTEXT_COMPRESS_TO, 0x0200010F, kCompressToZip }\r
+\r
+  #ifndef UNDER_CE\r
+  ,\r
+  { IDS_CONTEXT_COMPRESS_EMAIL, 0x02000111, kCompressEmail },\r
+  { IDS_CONTEXT_COMPRESS_TO_EMAIL, 0x02000113, kCompressTo7zEmail },\r
+  { IDS_CONTEXT_COMPRESS_TO_EMAIL, 0x02000113, kCompressToZipEmail }\r
+  #endif\r
+};\r
+\r
+const int kNumMenuItems = sizeof(kMenuItems) / sizeof(kMenuItems[0]);\r
+\r
+bool CMenuPage::OnInit()\r
+{\r
+  _initMode = true;\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+\r
+  #ifdef UNDER_CE\r
+  EnableItem(IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, false);\r
+  #else\r
+  CheckButton(IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, NZipRootRegistry::CheckContextMenuHandler());\r
+  #endif\r
+\r
+  CContextMenuInfo ci;\r
+  ci.Load();\r
+\r
+  CheckButton(IDC_SYSTEM_CASCADED_MENU, ci.Cascaded);\r
+\r
+  _listView.Attach(GetItem(IDC_SYSTEM_OPTIONS_LIST));\r
+\r
+  UInt32 newFlags = LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT;\r
+  _listView.SetExtendedListViewStyle(newFlags, newFlags);\r
+\r
+  _listView.InsertColumn(0, L"", 100);\r
+\r
+  for (int i = 0; i < kNumMenuItems; i++)\r
+  {\r
+    CContextMenuItem &menuItem = kMenuItems[i];\r
+\r
+    UString s = LangString(menuItem.ControlID, menuItem.LangID);\r
+    if (menuItem.Flag == kOpenAs)\r
+      s += L" >";\r
+\r
+    switch(menuItem.ControlID)\r
+    {\r
+      case IDS_CONTEXT_EXTRACT_TO:\r
+      {\r
+        s = MyFormatNew(s, LangString(IDS_CONTEXT_FOLDER, 0x02000140));\r
+        break;\r
+      }\r
+      case IDS_CONTEXT_COMPRESS_TO:\r
+      case IDS_CONTEXT_COMPRESS_TO_EMAIL:\r
+      {\r
+        UString s2 = LangString(IDS_CONTEXT_ARCHIVE, 0x02000141);\r
+        switch(menuItem.Flag)\r
+        {\r
+          case kCompressTo7z:\r
+          case kCompressTo7zEmail:\r
+            s2 += L".7z";\r
+            break;\r
+          case kCompressToZip:\r
+          case kCompressToZipEmail:\r
+            s2 += L".zip";\r
+            break;\r
+        }\r
+        s = MyFormatNew(s, s2);\r
+        break;\r
+      }\r
+    }\r
+\r
+    int itemIndex = _listView.InsertItem(i, s);\r
+    _listView.SetCheckState(itemIndex, ((ci.Flags & menuItem.Flag) != 0));\r
+  }\r
+\r
+  _listView.SetColumnWidthAuto(0);\r
+  _initMode = false;\r
+  return CPropertyPage::OnInit();\r
+}\r
+\r
+#ifndef UNDER_CE\r
+STDAPI DllRegisterServer(void);\r
+STDAPI DllUnregisterServer(void);\r
+HWND g_MenuPageHWND = 0;\r
+#endif\r
+\r
+LONG CMenuPage::OnApply()\r
+{\r
+  #ifndef UNDER_CE\r
+  g_MenuPageHWND = *this;\r
+  if (IsButtonCheckedBool(IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU))\r
+  {\r
+    DllRegisterServer();\r
+    NZipRootRegistry::AddContextMenuHandler();\r
+  }\r
+  else\r
+  {\r
+    DllUnregisterServer();\r
+    NZipRootRegistry::DeleteContextMenuHandler();\r
+  }\r
+  #endif\r
+\r
+  CContextMenuInfo ci;\r
+  ci.Cascaded = IsButtonCheckedBool(IDC_SYSTEM_CASCADED_MENU);\r
+  ci.Flags = 0;\r
+  for (int i = 0; i < kNumMenuItems; i++)\r
+    if (_listView.GetCheckState(i))\r
+      ci.Flags |= kMenuItems[i].Flag;\r
+  ci.Save();\r
+\r
+  return PSNRET_NOERROR;\r
+}\r
+\r
+void CMenuPage::OnNotifyHelp()\r
+{\r
+  ShowHelpWindow(NULL, kSystemTopic);\r
+}\r
+\r
+bool CMenuPage::OnButtonClicked(int buttonID, HWND buttonHWND)\r
+{\r
+  switch(buttonID)\r
+  {\r
+    case IDC_SYSTEM_CASCADED_MENU:\r
+    case IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU:\r
+      Changed();\r
+      return true;\r
+  }\r
+  return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);\r
+\r
+}\r
+\r
+bool CMenuPage::OnNotify(UINT controlID, LPNMHDR lParam)\r
+{\r
+  if (lParam->hwndFrom == HWND(_listView))\r
+  {\r
+    switch(lParam->code)\r
+    {\r
+      case (LVN_ITEMCHANGED):\r
+        return OnItemChanged((const NMLISTVIEW *)lParam);\r
+    }\r
+  }\r
+  return CPropertyPage::OnNotify(controlID, lParam);\r
+}\r
+\r
+\r
+bool CMenuPage::OnItemChanged(const NMLISTVIEW *info)\r
+{\r
+  if (_initMode)\r
+    return true;\r
+  if ((info->uChanged & LVIF_STATE) != 0)\r
+  {\r
+    UINT oldState = info->uOldState & LVIS_STATEIMAGEMASK;\r
+    UINT newState = info->uNewState & LVIS_STATEIMAGEMASK;\r
+    if (oldState != newState)\r
+      Changed();\r
+  }\r
+  return true;\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/MenuPage.h b/CPP/7zip/UI/FileManager/MenuPage.h
new file mode 100755 (executable)
index 0000000..3491844
--- /dev/null
@@ -0,0 +1,25 @@
+// MenuPage.h\r
\r
+#ifndef __MENU_PAGE_H\r
+#define __MENU_PAGE_H\r
+\r
+#include "Windows/Control/PropertyPage.h"\r
+#include "Windows/Control/ListView.h"\r
+\r
+#include "../Common/LoadCodecs.h"\r
+\r
+class CMenuPage: public NWindows::NControl::CPropertyPage\r
+{\r
+  bool _initMode;\r
+  NWindows::NControl::CListView _listView;\r
+\r
+  virtual bool OnInit();\r
+  virtual void OnNotifyHelp();\r
+  virtual bool OnNotify(UINT controlID, LPNMHDR lParam);\r
+  virtual bool OnItemChanged(const NMLISTVIEW *info);\r
+  virtual LONG OnApply();\r
+  virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);\r
+public:\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/MenuPage.rc b/CPP/7zip/UI/FileManager/MenuPage.rc
new file mode 100755 (executable)
index 0000000..72aff73
--- /dev/null
@@ -0,0 +1,24 @@
+#include "MenuPageRes.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#define xc 196\r
+#define yc 174\r
+\r
+IDD_MENU  MY_PAGE\r
+#include "MenuPage2.rc"\r
+\r
+#ifdef UNDER_CE\r
+\r
+#undef m\r
+#undef xc\r
+#undef yc\r
+\r
+#define m 4\r
+#define xc (SMALL_PAGE_SIZE_X + 8)\r
+\r
+#define yc 112\r
+\r
+IDD_MENU_2  MY_PAGE\r
+#include "MenuPage2.rc"\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/MenuPage2.rc b/CPP/7zip/UI/FileManager/MenuPage2.rc
new file mode 100755 (executable)
index 0000000..f0b1415
--- /dev/null
@@ -0,0 +1,14 @@
+#define y 40\r
+\r
+CAPTION "7-Zip"\r
+BEGIN\r
+  CONTROL  "Integrate 7-Zip to shell context menu", IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU,\r
+           MY_CHECKBOX, m, m, xc, 10\r
+  CONTROL  "Cascaded context menu", IDC_SYSTEM_CASCADED_MENU,\r
+           MY_CHECKBOX, m, m + 14, xc, 10\r
+  LTEXT    "Context menu items:", IDC_SYSTEM_STATIC_CONTEXT_MENU_ITEMS,\r
+           m, m + 28, xc, 8\r
+  CONTROL  "List", IDC_SYSTEM_OPTIONS_LIST, "SysListView32",\r
+           LVS_REPORT | LVS_SINGLESEL | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,\r
+           m, m + y, xc, yc - y\r
+END\r
diff --git a/CPP/7zip/UI/FileManager/MenuPageRes.h b/CPP/7zip/UI/FileManager/MenuPageRes.h
new file mode 100755 (executable)
index 0000000..307c835
--- /dev/null
@@ -0,0 +1,7 @@
+#define IDD_MENU 570\r
+#define IDD_MENU_2 670\r
+\r
+#define IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU 1010\r
+#define IDC_SYSTEM_CASCADED_MENU        1011\r
+#define IDC_SYSTEM_STATIC_CONTEXT_MENU_ITEMS 1020\r
+#define IDC_SYSTEM_OPTIONS_LIST         1022\r
diff --git a/CPP/7zip/UI/FileManager/MessagesDialog.cpp b/CPP/7zip/UI/FileManager/MessagesDialog.cpp
new file mode 100755 (executable)
index 0000000..bcbb556
--- /dev/null
@@ -0,0 +1,93 @@
+// MessagesDialog.cpp\r
\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+\r
+#include "Windows/ResourceString.h"\r
+\r
+#include "MessagesDialog.h"\r
+\r
+#ifdef LANG\r
+#include "LangUtils.h"\r
+#endif\r
+\r
+using namespace NWindows;\r
+\r
+#ifdef LANG\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDOK, 0x02000713 }\r
+};\r
+#endif\r
+\r
+void CMessagesDialog::AddMessageDirect(LPCWSTR message)\r
+{\r
+  int itemIndex = _messageList.GetItemCount();\r
+  wchar_t sz[32];\r
+  ConvertInt64ToString(itemIndex, sz);\r
+  _messageList.InsertItem(itemIndex, sz);\r
+  _messageList.SetSubItem(itemIndex, 1, message);\r
+}\r
+\r
+void CMessagesDialog::AddMessage(LPCWSTR message)\r
+{\r
+  UString s = message;\r
+  while (!s.IsEmpty())\r
+  {\r
+    int pos = s.Find(L'\n');\r
+    if (pos < 0)\r
+      break;\r
+    AddMessageDirect(s.Left(pos));\r
+    s.Delete(0, pos + 1);\r
+  }\r
+  AddMessageDirect(s);\r
+}\r
+\r
+bool CMessagesDialog::OnInit()\r
+{\r
+  #ifdef LANG\r
+  LangSetWindowText(HWND(*this), 0x02000A00);\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+  #endif\r
+  _messageList.Attach(GetItem(IDC_MESSAGE_LIST));\r
+\r
+  #ifndef UNDER_CE\r
+  _messageList.SetUnicodeFormat(true);\r
+  #endif\r
+\r
+  _messageList.InsertColumn(0, L"", 30);\r
+\r
+  const UString s =\r
+    #ifdef LANG\r
+    LangString(IDS_MESSAGES_DIALOG_MESSAGE_COLUMN, 0x02000A80);\r
+    #else\r
+    MyLoadStringW(IDS_MESSAGES_DIALOG_MESSAGE_COLUMN);\r
+    #endif\r
+\r
+  _messageList.InsertColumn(1, s, 600);\r
+\r
+  for (int i = 0; i < Messages->Size(); i++)\r
+    AddMessage((*Messages)[i]);\r
+\r
+  _messageList.SetColumnWidthAuto(0);\r
+  _messageList.SetColumnWidthAuto(1);\r
+  NormalizeSize();\r
+  return CModalDialog::OnInit();\r
+}\r
+\r
+bool CMessagesDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)\r
+{\r
+  int mx, my;\r
+  GetMargins(8, mx, my);\r
+  int bx, by;\r
+  GetItemSizes(IDOK, bx, by);\r
+  int y = ySize - my - by;\r
+  int x = xSize - mx - bx;\r
+\r
+  InvalidateRect(NULL);\r
+\r
+  MoveItem(IDOK, x, y, bx, by);\r
+  _messageList.Move(mx, my, xSize - mx * 2, y - my * 2);\r
+  return false;\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/MessagesDialog.h b/CPP/7zip/UI/FileManager/MessagesDialog.h
new file mode 100755 (executable)
index 0000000..7a0db96
--- /dev/null
@@ -0,0 +1,23 @@
+// MessagesDialog.h\r
+\r
+#ifndef __MESSAGES_DIALOG_H\r
+#define __MESSAGES_DIALOG_H\r
+\r
+#include "Windows/Control/Dialog.h"\r
+#include "Windows/Control/ListView.h"\r
+\r
+#include "MessagesDialogRes.h"\r
+\r
+class CMessagesDialog: public NWindows::NControl::CModalDialog\r
+{\r
+  NWindows::NControl::CListView _messageList;\r
+  void AddMessageDirect(LPCWSTR message);\r
+  void AddMessage(LPCWSTR message);\r
+  virtual bool OnInit();\r
+  virtual bool OnSize(WPARAM wParam, int xSize, int ySize);\r
+public:\r
+  const UStringVector *Messages;\r
+  INT_PTR Create(HWND parent = 0) { return CModalDialog::Create(IDD_DIALOG_MESSAGES, parent); }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/MessagesDialog.rc b/CPP/7zip/UI/FileManager/MessagesDialog.rc
new file mode 100755 (executable)
index 0000000..273d852
--- /dev/null
@@ -0,0 +1,14 @@
+#include "MessagesDialogRes.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#define xc 440\r
+#define yc 160\r
+\r
+IDD_DIALOG_MESSAGES  MY_RESIZE_DIALOG\r
+CAPTION "7-Zip: Diagnostic messages"\r
+{\r
+  DEFPUSHBUTTON "&Close", IDOK, bx, by, bxs, bys\r
+  CONTROL "List1", IDC_MESSAGE_LIST, "SysListView32",\r
+          LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,\r
+          m, m, xc, yc - bys - m\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/MessagesDialogRes.h b/CPP/7zip/UI/FileManager/MessagesDialogRes.h
new file mode 100755 (executable)
index 0000000..cfd83ab
--- /dev/null
@@ -0,0 +1,3 @@
+#define IDS_MESSAGES_DIALOG_MESSAGE_COLUMN 503\r
+#define IDD_DIALOG_MESSAGES             503\r
+#define IDC_MESSAGE_LIST                1000\r
diff --git a/CPP/7zip/UI/FileManager/Move.bmp b/CPP/7zip/UI/FileManager/Move.bmp
new file mode 100755 (executable)
index 0000000..eb5f20f
Binary files /dev/null and b/CPP/7zip/UI/FileManager/Move.bmp differ
diff --git a/CPP/7zip/UI/FileManager/Move2.bmp b/CPP/7zip/UI/FileManager/Move2.bmp
new file mode 100755 (executable)
index 0000000..58679ef
Binary files /dev/null and b/CPP/7zip/UI/FileManager/Move2.bmp differ
diff --git a/CPP/7zip/UI/FileManager/MyCom2.h b/CPP/7zip/UI/FileManager/MyCom2.h
new file mode 100755 (executable)
index 0000000..2d36e29
--- /dev/null
@@ -0,0 +1,39 @@
+// MyCom2.h\r
+\r
+#ifndef __MYCOM2_H\r
+#define __MYCOM2_H\r
+\r
+#include "Common/MyCom.h"\r
+\r
+#define MY_ADDREF_RELEASE_MT \\r
+STDMETHOD_(ULONG, AddRef)() { InterlockedIncrement((LONG *)&__m_RefCount); return __m_RefCount; } \\r
+STDMETHOD_(ULONG, Release)() { InterlockedDecrement((LONG *)&__m_RefCount); if (__m_RefCount != 0) \\r
+  return __m_RefCount; delete this; return 0; }\r
+\r
+#define MY_UNKNOWN_IMP_SPEC_MT2(i1, i) \\r
+  MY_QUERYINTERFACE_BEGIN \\r
+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \\r
+  i \\r
+  MY_QUERYINTERFACE_END \\r
+  MY_ADDREF_RELEASE_MT\r
+\r
+\r
+#define MY_UNKNOWN_IMP1_MT(i) MY_UNKNOWN_IMP_SPEC_MT2( \\r
+  i, \\r
+  MY_QUERYINTERFACE_ENTRY(i) \\r
+  )\r
+\r
+#define MY_UNKNOWN_IMP2_MT(i1, i2) MY_UNKNOWN_IMP_SPEC_MT2( \\r
+  i1, \\r
+  MY_QUERYINTERFACE_ENTRY(i1) \\r
+  MY_QUERYINTERFACE_ENTRY(i2) \\r
+  )\r
+\r
+#define MY_UNKNOWN_IMP3_MT(i1, i2, i3) MY_UNKNOWN_IMP_SPEC_MT2( \\r
+  i1, \\r
+  MY_QUERYINTERFACE_ENTRY(i1) \\r
+  MY_QUERYINTERFACE_ENTRY(i2) \\r
+  MY_QUERYINTERFACE_ENTRY(i3) \\r
+  )\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp
new file mode 100755 (executable)
index 0000000..aaa3579
--- /dev/null
@@ -0,0 +1,682 @@
+// MyLoadMenu.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/Menu.h"\r
+#include "Windows/Control/Dialog.h"\r
+\r
+#include "../../PropID.h"\r
+\r
+#include "../Common/CompressCall.h"\r
+\r
+#include "AboutDialog.h"\r
+#include "App.h"\r
+#include "HelpUtils.h"\r
+#include "LangUtils.h"\r
+#include "RegistryUtils.h"\r
+\r
+#include "resource.h"\r
+\r
+using namespace NWindows;\r
+\r
+static const UINT kOpenBookmarkMenuID = 730;\r
+static const UINT kSetBookmarkMenuID = 740;\r
+\r
+extern HINSTANCE g_hInstance;\r
+\r
+static LPCWSTR kFMHelpTopic = L"FM/index.htm";\r
+\r
+extern void OptionsDialog(HWND hwndOwner, HINSTANCE hInstance);\r
+\r
+enum\r
+{\r
+  kMenuIndex_File = 0,\r
+  kMenuIndex_Edit,\r
+  kMenuIndex_View,\r
+  kMenuIndex_Bookmarks\r
+};\r
+\r
+static const UInt32 kTopMenuLangIDs[] =\r
+{\r
+  0x03000102,\r
+  0x03000103,\r
+  0x03000104,\r
+  0x03000107,\r
+  0x03000105,\r
+  0x03000106\r
+};\r
+\r
+static const UInt32 kAddToFavoritesLangID = 0x03000710;\r
+static const UInt32 kToolbarsLangID = 0x03000451;\r
+\r
+static const CIDLangPair kIDLangPairs[] =\r
+{\r
+  // File\r
+  { IDM_FILE_OPEN, 0x03000210 },\r
+  { IDM_FILE_OPEN_INSIDE, 0x03000211 },\r
+  { IDM_FILE_OPEN_OUTSIDE, 0x03000212 },\r
+  { IDM_FILE_VIEW, 0x03000220 },\r
+  { IDM_FILE_EDIT, 0x03000221 },\r
+  { IDM_RENAME, 0x03000230 },\r
+  { IDM_COPY_TO, 0x03000231 },\r
+  { IDM_MOVE_TO, 0x03000232 },\r
+  { IDM_DELETE, 0x03000233 },\r
+  { IDM_FILE_PROPERTIES, 0x03000240 },\r
+  { IDM_FILE_COMMENT, 0x03000241 },\r
+  { IDM_FILE_CRC, 0x03000242 },\r
+  { IDM_FILE_DIFF, 0x03000243 },\r
+  { IDM_FILE_SPLIT, 0x03000270 },\r
+  { IDM_FILE_COMBINE, 0x03000271 },\r
+  { IDM_CREATE_FOLDER, 0x03000250 },\r
+  { IDM_CREATE_FILE, 0x03000251 },\r
+  { IDCLOSE, 0x03000260 },\r
+\r
+  // Edit\r
+  { IDM_EDIT_CUT, 0x03000320 },\r
+  { IDM_EDIT_COPY, 0x03000321 },\r
+  { IDM_EDIT_PASTE, 0x03000322 },\r
+\r
+  { IDM_SELECT_ALL, 0x03000330 },\r
+  { IDM_DESELECT_ALL, 0x03000331 },\r
+  { IDM_INVERT_SELECTION, 0x03000332 },\r
+  { IDM_SELECT, 0x03000333 },\r
+  { IDM_DESELECT, 0x03000334 },\r
+  { IDM_SELECT_BY_TYPE, 0x03000335 },\r
+  { IDM_DESELECT_BY_TYPE, 0x03000336 },\r
+\r
+  { IDM_VIEW_LARGE_ICONS, 0x03000410 },\r
+  { IDM_VIEW_SMALL_ICONS, 0x03000411 },\r
+  { IDM_VIEW_LIST, 0x03000412 },\r
+  { IDM_VIEW_DETAILS, 0x03000413 },\r
+\r
+  { IDM_VIEW_ARANGE_BY_NAME, 0x02000204 },\r
+  { IDM_VIEW_ARANGE_BY_TYPE, 0x02000214 },\r
+  { IDM_VIEW_ARANGE_BY_DATE, 0x0200020C },\r
+  { IDM_VIEW_ARANGE_BY_SIZE, 0x02000207 },\r
+  { IDM_VIEW_ARANGE_NO_SORT, 0x03000420 },\r
+\r
+  { IDM_OPEN_ROOT_FOLDER, 0x03000430 },\r
+  { IDM_OPEN_PARENT_FOLDER, 0x03000431 },\r
+  { IDM_FOLDERS_HISTORY, 0x03000432 },\r
+\r
+  { IDM_VIEW_REFRESH, 0x03000440 },\r
+  \r
+  { IDM_VIEW_FLAT_VIEW, 0x03000449 },\r
+  { IDM_VIEW_TWO_PANELS, 0x03000450 },\r
+  { IDM_VIEW_ARCHIVE_TOOLBAR, 0x03000460 },\r
+  { IDM_VIEW_STANDARD_TOOLBAR, 0x03000461 },\r
+  { IDM_VIEW_TOOLBARS_LARGE_BUTTONS, 0x03000462 },\r
+  { IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT, 0x03000463 },\r
+\r
+  { IDM_OPTIONS, 0x03000510 },\r
+  { IDM_BENCHMARK, 0x03000511 },\r
+  \r
+  { IDM_HELP_CONTENTS, 0x03000610 },\r
+  { IDM_ABOUT, 0x03000620 }\r
+};\r
+\r
+\r
+static int FindLangItem(int ControlID)\r
+{\r
+  for (int i = 0; i < sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]); i++)\r
+    if (kIDLangPairs[i].ControlID == ControlID)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+static int GetSortControlID(PROPID propID)\r
+{\r
+  switch(propID)\r
+  {\r
+    case kpidName: return IDM_VIEW_ARANGE_BY_NAME;\r
+    case kpidExtension: return IDM_VIEW_ARANGE_BY_TYPE;\r
+    case kpidMTime: return IDM_VIEW_ARANGE_BY_DATE;\r
+    case kpidSize: return IDM_VIEW_ARANGE_BY_SIZE;\r
+    case kpidNoProperty: return IDM_VIEW_ARANGE_NO_SORT;\r
+  }\r
+  return -1;\r
+}\r
+\r
+/*\r
+static bool g_IsNew_fMask = true;\r
+\r
+class CInit_fMask\r
+{\r
+public:\r
+  CInit_fMask()\r
+  {\r
+    g_IsNew_fMask = false;\r
+    OSVERSIONINFO vi;\r
+    vi.dwOSVersionInfoSize = sizeof(vi);\r
+    if (::GetVersionEx(&vi))\r
+    {\r
+      g_IsNew_fMask = (vi.dwMajorVersion > 4 ||\r
+        (vi.dwMajorVersion == 4 && vi.dwMinorVersion > 0));\r
+    }\r
+    g_IsNew_fMask = false;\r
+  }\r
+} g_Init_fMask;\r
+\r
+// it's hack for supporting Windows NT\r
+// constants are from WinUser.h\r
+\r
+#if(WINVER < 0x0500)\r
+#define MIIM_STRING      0x00000040\r
+#define MIIM_BITMAP      0x00000080\r
+#define MIIM_FTYPE       0x00000100\r
+#endif\r
+\r
+static UINT Get_fMaskForString()\r
+{\r
+  return g_IsNew_fMask ? MIIM_STRING : MIIM_TYPE;\r
+}\r
+\r
+static UINT Get_fMaskForFTypeAndString()\r
+{\r
+  return g_IsNew_fMask ? (MIIM_STRING | MIIM_FTYPE) : MIIM_TYPE;\r
+}\r
+*/\r
+\r
+static inline UINT Get_fMaskForString() { return MIIM_TYPE; }\r
+static inline UINT Get_fMaskForFTypeAndString() { return MIIM_TYPE; }\r
+\r
+static void MyChangeMenu(HMENU menuLoc, int level, int menuIndex)\r
+{\r
+  CMenu menu;\r
+  menu.Attach(menuLoc);\r
+  for (int i = 0;; i++)\r
+  {\r
+    CMenuItem item;\r
+    item.fMask = Get_fMaskForString() | MIIM_SUBMENU | MIIM_ID;\r
+    item.fType = MFT_STRING;\r
+    if (!menu.GetItem(i, true, item))\r
+      break;\r
+    {\r
+      UString newString;\r
+      if (item.hSubMenu)\r
+      {\r
+        UInt32 langID = 0;\r
+        if (level == 1 && menuIndex == kMenuIndex_Bookmarks)\r
+          langID = kAddToFavoritesLangID;\r
+        else\r
+        {\r
+          MyChangeMenu(item.hSubMenu, level + 1, i);\r
+          if (level == 1 && menuIndex == kMenuIndex_View)\r
+            langID = kToolbarsLangID;\r
+          else if (level == 0 && i < sizeof(kTopMenuLangIDs) / sizeof(kTopMenuLangIDs[0]))\r
+            langID = kTopMenuLangIDs[i];\r
+          else\r
+            continue;\r
+        }\r
+        newString = LangString(langID);\r
+        if (newString.IsEmpty())\r
+          continue;\r
+      }\r
+      else\r
+      {\r
+        int langPos = FindLangItem(item.wID);\r
+        if (langPos < 0)\r
+          continue;\r
+        newString = LangString(kIDLangPairs[langPos].LangID);\r
+        if (newString.IsEmpty())\r
+          continue;\r
+        UString shorcutString = item.StringValue;\r
+        int tabPos = shorcutString.ReverseFind(wchar_t('\t'));\r
+        if (tabPos >= 0)\r
+          newString += shorcutString.Mid(tabPos);\r
+      }\r
+      {\r
+        item.StringValue = newString;\r
+        item.fMask = Get_fMaskForString();\r
+        item.fType = MFT_STRING;\r
+        menu.SetItem(i, true, item);\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+static CMenu g_FileMenu;\r
+\r
+struct CFileMenuDestroyer\r
+{\r
+  ~CFileMenuDestroyer() { if ((HMENU)g_FileMenu != 0) g_FileMenu.Destroy(); }\r
+} g_FileMenuDestroyer;\r
+\r
+\r
+static void CopyMenu(HMENU srcMenuSpec, HMENU destMenuSpec)\r
+{\r
+  CMenu srcMenu;\r
+  srcMenu.Attach(srcMenuSpec);\r
+  CMenu destMenu;\r
+  destMenu.Attach(destMenuSpec);\r
+  int startPos = 0;\r
+  for (int i = 0;; i++)\r
+  {\r
+    CMenuItem item;\r
+    item.fMask = MIIM_STATE | MIIM_ID | Get_fMaskForFTypeAndString();\r
+    item.fType = MFT_STRING;\r
+    if (srcMenu.GetItem(i, true, item))\r
+    {\r
+      if (destMenu.InsertItem(startPos, true, item))\r
+        startPos++;\r
+    }\r
+    else\r
+      break;\r
+  }\r
+}\r
+\r
+void MyLoadMenu()\r
+{\r
+  HMENU baseMenu;\r
+\r
+  #ifdef UNDER_CE\r
+\r
+  HMENU oldMenu = g_App._commandBar.GetMenu(0);\r
+  if (oldMenu)\r
+    ::DestroyMenu(oldMenu);\r
+  BOOL b = g_App._commandBar.InsertMenubar(g_hInstance, IDM_MENU, 0);\r
+  baseMenu = g_App._commandBar.GetMenu(0);\r
+  if (!g_LangID.IsEmpty())\r
+    MyChangeMenu(baseMenu, 0, 0);\r
+  g_App._commandBar.DrawMenuBar(0);\r
\r
+  #else\r
+\r
+  HWND hWnd = g_HWND;\r
+  HMENU oldMenu = ::GetMenu(hWnd);\r
+  ::SetMenu(hWnd, ::LoadMenu(g_hInstance, MAKEINTRESOURCE(IDM_MENU)));\r
+  ::DestroyMenu(oldMenu);\r
+  baseMenu = ::GetMenu(hWnd);\r
+  if (!g_LangID.IsEmpty())\r
+    MyChangeMenu(baseMenu, 0, 0);\r
+  ::DrawMenuBar(hWnd);\r
+\r
+  #endif\r
+\r
+  if ((HMENU)g_FileMenu != 0)\r
+    g_FileMenu.Destroy();\r
+  g_FileMenu.CreatePopup();\r
+  CopyMenu(::GetSubMenu(baseMenu, 0), g_FileMenu);\r
+}\r
+\r
+void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position)\r
+{\r
+  HMENU mainMenu =\r
+    #ifdef UNDER_CE\r
+    g_App._commandBar.GetMenu(0);\r
+    #else\r
+    ::GetMenu(g_HWND)\r
+    #endif\r
+    ;\r
+  if (::GetSubMenu(mainMenu, position) != hMenu)\r
+    return;\r
+  if (position == kMenuIndex_File)\r
+  {\r
+    CMenu menu;\r
+    menu.Attach(hMenu);\r
+    menu.RemoveAllItems();\r
+    g_App.GetFocusedPanel().CreateFileMenu(hMenu);\r
+  }\r
+  else if (position == kMenuIndex_Edit)\r
+  {\r
+    /*\r
+    CMenu menu;\r
+    menu.Attach(hMenu);\r
+    menu.EnableItem(IDM_EDIT_CUT, MF_ENABLED);\r
+    menu.EnableItem(IDM_EDIT_COPY, MF_ENABLED);\r
+    menu.EnableItem(IDM_EDIT_PASTE, IsClipboardFormatAvailableHDROP() ? MF_ENABLED : MF_GRAYED);\r
+    */\r
+  }\r
+  else if (position == kMenuIndex_View)\r
+  {\r
+    // View;\r
+    CMenu menu;\r
+    menu.Attach(hMenu);\r
+    menu.CheckRadioItem(IDM_VIEW_LARGE_ICONS, IDM_VIEW_DETAILS,\r
+      IDM_VIEW_LARGE_ICONS + g_App.GetListViewMode(), MF_BYCOMMAND);\r
+\r
+    menu.CheckRadioItem(IDM_VIEW_ARANGE_BY_NAME, IDM_VIEW_ARANGE_NO_SORT,\r
+        GetSortControlID(g_App.GetSortID()), MF_BYCOMMAND);\r
+    \r
+    menu.CheckItemByID(IDM_VIEW_TWO_PANELS, g_App.NumPanels == 2);\r
+    menu.CheckItemByID(IDM_VIEW_FLAT_VIEW, g_App.GetFlatMode());\r
+    menu.CheckItemByID(IDM_VIEW_ARCHIVE_TOOLBAR, g_App.ShowArchiveToolbar);\r
+    menu.CheckItemByID(IDM_VIEW_STANDARD_TOOLBAR, g_App.ShowStandardToolbar);\r
+    menu.CheckItemByID(IDM_VIEW_TOOLBARS_LARGE_BUTTONS, g_App.LargeButtons);\r
+    menu.CheckItemByID(IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT, g_App.ShowButtonsLables);\r
+  }\r
+  else if (position == kMenuIndex_Bookmarks)\r
+  {\r
+    CMenu menu;\r
+    menu.Attach(hMenu);\r
+\r
+    CMenu subMenu;\r
+    subMenu.Attach(menu.GetSubMenu(0));\r
+    subMenu.RemoveAllItems();\r
+    int i;\r
+    for (i = 0; i < 10; i++)\r
+    {\r
+      UString s = LangString(IDS_BOOKMARK, 0x03000720);\r
+      s += L" ";\r
+      wchar_t c = (wchar_t)(L'0' + i);\r
+      s += c;\r
+      s += L"\tAlt+Shift+";\r
+      s += c;\r
+      subMenu.AppendItem(MF_STRING, kSetBookmarkMenuID + i, s);\r
+    }\r
+\r
+    menu.RemoveAllItemsFrom(2);\r
+\r
+    for (i = 0; i < 10; i++)\r
+    {\r
+      UString path = g_App.AppState.FastFolders.GetString(i);\r
+      const int kMaxSize = 100;\r
+      const int kFirstPartSize = kMaxSize / 2;\r
+      if (path.Length() > kMaxSize)\r
+      {\r
+        path = path.Left(kFirstPartSize) + UString(L" ... ") +\r
+          path.Right(kMaxSize - kFirstPartSize);\r
+      }\r
+      UString s = path;\r
+      if (s.IsEmpty())\r
+        s = L"-";\r
+      s += L"\tAlt+";\r
+      s += (wchar_t)(L'0' + i);\r
+      menu.AppendItem(MF_STRING, kOpenBookmarkMenuID + i, s);\r
+    }\r
+  }\r
+}\r
+\r
+/*\r
+It doesn't help\r
+void OnMenuUnActivating(HWND hWnd, HMENU hMenu, int id)\r
+{\r
+  if (::GetSubMenu(::GetMenu(g_HWND), 0) != hMenu)\r
+    return;\r
+}\r
+*/\r
+\r
+void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu,\r
+    bool isFsFolder, int numItems, bool allAreFiles)\r
+{\r
+  CMenu destMenu;\r
+  destMenu.Attach(hMenu);\r
+\r
+  UString diffPath;\r
+  ReadRegDiff(diffPath);\r
+  \r
+  int numRealItems = startPos;\r
+  for (int i = 0;; i++)\r
+  {\r
+    CMenuItem item;\r
+\r
+    item.fMask = MIIM_STATE | MIIM_ID | Get_fMaskForFTypeAndString();\r
+    item.fType = MFT_STRING;\r
+    if (!g_FileMenu.GetItem(i, true, item))\r
+      break;\r
+    {\r
+      if (!programMenu && item.wID == IDCLOSE)\r
+        continue;\r
+\r
+      if (item.wID == IDM_FILE_DIFF && diffPath.IsEmpty())\r
+        continue;\r
+\r
+      bool isOneFsFile = (isFsFolder && numItems == 1 && allAreFiles);\r
+      bool disable = ((item.wID == IDM_FILE_SPLIT || item.wID == IDM_FILE_COMBINE) && !isOneFsFile);\r
+\r
+      bool isBigScreen = NControl::IsDialogSizeOK(40, 200);\r
+\r
+      if (!isBigScreen && (disable || item.IsSeparator()))\r
+        continue;\r
+      if (destMenu.InsertItem(startPos, true, item))\r
+        startPos++;\r
+      if (disable)\r
+        destMenu.EnableItem(startPos - 1, MF_BYPOSITION | MF_GRAYED);\r
+\r
+      if (!item.IsSeparator())\r
+        numRealItems = startPos;\r
+    }\r
+  }\r
+  destMenu.RemoveAllItemsFrom(numRealItems);\r
+}\r
+\r
+bool ExecuteFileCommand(int id)\r
+{\r
+  if (id >= kPluginMenuStartID)\r
+  {\r
+    g_App.GetFocusedPanel().InvokePluginCommand(id);\r
+    g_App.GetFocusedPanel()._sevenZipContextMenu.Release();\r
+    g_App.GetFocusedPanel()._systemContextMenu.Release();\r
+    return true;\r
+  }\r
+\r
+  switch (id)\r
+  {\r
+    // File\r
+    case IDM_FILE_OPEN:\r
+      g_App.OpenItem();\r
+      break;\r
+    case IDM_FILE_OPEN_INSIDE:\r
+      g_App.OpenItemInside();\r
+      break;\r
+    case IDM_FILE_OPEN_OUTSIDE:\r
+      g_App.OpenItemOutside();\r
+      break;\r
+    case IDM_FILE_VIEW:\r
+      break;\r
+    case IDM_FILE_EDIT:\r
+      g_App.EditItem();\r
+      break;\r
+    case IDM_RENAME:\r
+      g_App.Rename();\r
+      break;\r
+    case IDM_COPY_TO:\r
+      g_App.CopyTo();\r
+      break;\r
+    case IDM_MOVE_TO:\r
+      g_App.MoveTo();\r
+      break;\r
+    case IDM_DELETE:\r
+    {\r
+      bool shift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0;\r
+      g_App.Delete(!shift);\r
+      break;\r
+    }\r
+    case IDM_FILE_CRC:\r
+      g_App.CalculateCrc();\r
+      break;\r
+    case IDM_FILE_DIFF:\r
+      g_App.DiffFiles();\r
+      break;\r
+    case IDM_FILE_SPLIT:\r
+      g_App.Split();\r
+      break;\r
+    case IDM_FILE_COMBINE:\r
+      g_App.Combine();\r
+      break;\r
+    case IDM_FILE_PROPERTIES:\r
+      g_App.Properties();\r
+      break;\r
+    case IDM_FILE_COMMENT:\r
+      g_App.Comment();\r
+      break;\r
+\r
+    case IDM_CREATE_FOLDER:\r
+      g_App.CreateFolder();\r
+      break;\r
+    case IDM_CREATE_FILE:\r
+      g_App.CreateFile();\r
+      break;\r
+    default:\r
+      return false;\r
+  }\r
+  return true;\r
+}\r
+\r
+bool OnMenuCommand(HWND hWnd, int id)\r
+{\r
+  if (ExecuteFileCommand(id))\r
+    return true;\r
+\r
+  switch (id)\r
+  {\r
+    // File\r
+    case IDCLOSE:\r
+      SendMessage(hWnd, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), (LPARAM)hWnd);\r
+      SendMessage (hWnd, WM_CLOSE, 0, 0);\r
+      break;\r
+    \r
+    // Edit\r
+    case IDM_EDIT_CUT:\r
+      g_App.EditCut();\r
+      break;\r
+    case IDM_EDIT_COPY:\r
+      g_App.EditCopy();\r
+      break;\r
+    case IDM_EDIT_PASTE:\r
+      g_App.EditPaste();\r
+      break;\r
+    case IDM_SELECT_ALL:\r
+      g_App.SelectAll(true);\r
+      g_App.RefreshStatusBar();\r
+      break;\r
+    case IDM_DESELECT_ALL:\r
+      g_App.SelectAll(false);\r
+      g_App.RefreshStatusBar();\r
+      break;\r
+    case IDM_INVERT_SELECTION:\r
+      g_App.InvertSelection();\r
+      g_App.RefreshStatusBar();\r
+      break;\r
+    case IDM_SELECT:\r
+      g_App.SelectSpec(true);\r
+      g_App.RefreshStatusBar();\r
+      break;\r
+    case IDM_DESELECT:\r
+      g_App.SelectSpec(false);\r
+      g_App.RefreshStatusBar();\r
+      break;\r
+    case IDM_SELECT_BY_TYPE:\r
+      g_App.SelectByType(true);\r
+      g_App.RefreshStatusBar();\r
+      break;\r
+    case IDM_DESELECT_BY_TYPE:\r
+      g_App.SelectByType(false);\r
+      g_App.RefreshStatusBar();\r
+      break;\r
+\r
+    //View\r
+    case IDM_VIEW_LARGE_ICONS:\r
+    case IDM_VIEW_SMALL_ICONS:\r
+    case IDM_VIEW_LIST:\r
+    case IDM_VIEW_DETAILS:\r
+    {\r
+      UINT index = id - IDM_VIEW_LARGE_ICONS;\r
+      if (index < 4)\r
+      {\r
+        g_App.SetListViewMode(index);\r
+        /*\r
+        CMenu menu;\r
+        menu.Attach(::GetSubMenu(::GetMenu(hWnd), kMenuIndex_View));\r
+        menu.CheckRadioItem(IDM_VIEW_LARGE_ICONS, IDM_VIEW_DETAILS,\r
+            id, MF_BYCOMMAND);\r
+        */\r
+      }\r
+      break;\r
+    }\r
+    case IDM_VIEW_ARANGE_BY_NAME:\r
+    {\r
+      g_App.SortItemsWithPropID(kpidName);\r
+      break;\r
+    }\r
+    case IDM_VIEW_ARANGE_BY_TYPE:\r
+    {\r
+      g_App.SortItemsWithPropID(kpidExtension);\r
+      break;\r
+    }\r
+    case IDM_VIEW_ARANGE_BY_DATE:\r
+    {\r
+      g_App.SortItemsWithPropID(kpidMTime);\r
+      break;\r
+    }\r
+    case IDM_VIEW_ARANGE_BY_SIZE:\r
+    {\r
+      g_App.SortItemsWithPropID(kpidSize);\r
+      break;\r
+    }\r
+    case IDM_VIEW_ARANGE_NO_SORT:\r
+    {\r
+      g_App.SortItemsWithPropID(kpidNoProperty);\r
+      break;\r
+    }\r
+\r
+    case IDM_OPEN_ROOT_FOLDER:\r
+      g_App.OpenRootFolder();\r
+      break;\r
+    case IDM_OPEN_PARENT_FOLDER:\r
+      g_App.OpenParentFolder();\r
+      break;\r
+    case IDM_FOLDERS_HISTORY:\r
+      g_App.FoldersHistory();\r
+      break;\r
+    case IDM_VIEW_REFRESH:\r
+      g_App.RefreshView();\r
+      break;\r
+    case IDM_VIEW_FLAT_VIEW:\r
+      g_App.ChangeFlatMode();\r
+      break;\r
+    case IDM_VIEW_TWO_PANELS:\r
+      g_App.SwitchOnOffOnePanel();\r
+      break;\r
+    case IDM_VIEW_STANDARD_TOOLBAR:\r
+      g_App.SwitchStandardToolbar();\r
+      break;\r
+    case IDM_VIEW_ARCHIVE_TOOLBAR:\r
+      g_App.SwitchArchiveToolbar();\r
+      break;\r
+    case IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT:\r
+      g_App.SwitchButtonsLables();\r
+      break;\r
+    case IDM_VIEW_TOOLBARS_LARGE_BUTTONS:\r
+      g_App.SwitchLargeButtons();\r
+      break;\r
+\r
+    // Tools\r
+    case IDM_OPTIONS:\r
+      OptionsDialog(hWnd, g_hInstance);\r
+      break;\r
+          \r
+    case IDM_BENCHMARK:\r
+    {\r
+      CPanel::CDisableTimerProcessing disableTimerProcessing1(g_App.Panels[0]);\r
+      CPanel::CDisableTimerProcessing disableTimerProcessing2(g_App.Panels[1]);\r
+      Benchmark();\r
+      break;\r
+    }\r
+    // Help\r
+    case IDM_HELP_CONTENTS:\r
+      ShowHelpWindow(NULL, kFMHelpTopic);\r
+      break;\r
+    case IDM_ABOUT:\r
+    {\r
+      CAboutDialog dialog;\r
+      dialog.Create(hWnd);\r
+      break;\r
+    }\r
+    default:\r
+    {\r
+      if (id >= kOpenBookmarkMenuID && id <= kOpenBookmarkMenuID + 9)\r
+      {\r
+        g_App.OpenBookmark(id - kOpenBookmarkMenuID);\r
+        return true;\r
+      }\r
+      else if (id >= kSetBookmarkMenuID && id <= kSetBookmarkMenuID + 9)\r
+      {\r
+        g_App.SetBookmark(id - kSetBookmarkMenuID);\r
+        return true;\r
+      }\r
+      return false;\r
+    }\r
+  }\r
+  return true;\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.h b/CPP/7zip/UI/FileManager/MyLoadMenu.h
new file mode 100755 (executable)
index 0000000..5353d94
--- /dev/null
@@ -0,0 +1,16 @@
+// MyLoadMenu.h\r
+\r
+#ifndef __MY_LOAD_MENU_H\r
+#define __MY_LOAD_MENU_H\r
+\r
+void OnMenuActivating(HWND hWnd, HMENU hMenu, int position);\r
+// void OnMenuUnActivating(HWND hWnd, HMENU hMenu, int id);\r
+// void OnMenuUnActivating(HWND hWnd);\r
+\r
+bool OnMenuCommand(HWND hWnd, int id);\r
+void MyLoadMenu();\r
+void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu,\r
+    bool isFsFolder, int numItems, bool allAreFiles);\r
+bool ExecuteFileCommand(int id);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/NetFolder.cpp b/CPP/7zip/UI/FileManager/NetFolder.cpp
new file mode 100755 (executable)
index 0000000..adf6e5b
--- /dev/null
@@ -0,0 +1,272 @@
+// NetFolder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../../PropID.h"\r
+\r
+#include "FSFolder.h"\r
+#include "NetFolder.h"\r
+#include "SysIconUtils.h"\r
+\r
+using namespace NWindows;\r
+using namespace NNet;\r
+\r
+static const STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidName, VT_BSTR},\r
+  { NULL, kpidLocalName, VT_BSTR},\r
+  { NULL, kpidComment, VT_BSTR},\r
+  { NULL, kpidProvider, VT_BSTR}\r
+};\r
+\r
+void CNetFolder::Init(const UString &path)\r
+{\r
+  /*\r
+  if (path.Length() > 2)\r
+  {\r
+    if (path[0] == L'\\' && path[1] == L'\\')\r
+    {\r
+      CResource netResource;\r
+      netResource.RemoteName = GetSystemString(path.Left(path.Length() - 1));\r
+      netResource.Scope = RESOURCE_GLOBALNET;\r
+      netResource.Type = RESOURCETYPE_DISK;\r
+      netResource.DisplayType = RESOURCEDISPLAYTYPE_SERVER;\r
+      netResource.Usage = RESOURCEUSAGE_CONTAINER;\r
+      Init(&netResource, 0, path);\r
+      return;\r
+    }\r
+  }\r
+  Init(0, 0 , L"");\r
+  */\r
+  CResourceW resource;\r
+  resource.RemoteNameIsDefined = true;\r
+  resource.RemoteName = path.Left(path.Length() - 1);\r
+  resource.ProviderIsDefined = false;\r
+  resource.LocalNameIsDefined = false;\r
+  resource.CommentIsDefined = false;\r
+  resource.Type = RESOURCETYPE_DISK;\r
+  resource.Scope = RESOURCE_GLOBALNET;\r
+  resource.Usage = 0;\r
+  resource.DisplayType = 0;\r
+  CResourceW destResource;\r
+  UString systemPathPart;\r
+  DWORD result = GetResourceInformation(resource, destResource, systemPathPart);\r
+  if (result == NO_ERROR)\r
+    Init(&destResource, 0, path);\r
+  else\r
+    Init(0, 0 , L"");\r
+  return;\r
+}\r
+\r
+void CNetFolder::Init(const NWindows::NNet::CResourceW *netResource,\r
+      IFolderFolder *parentFolder, const UString &path)\r
+{\r
+  _path = path;\r
+  if (netResource == 0)\r
+    _netResourcePointer = 0;\r
+  else\r
+  {\r
+    _netResource = *netResource;\r
+    _netResourcePointer = &_netResource;\r
+\r
+    // if (_netResource.DisplayType == RESOURCEDISPLAYTYPE_SERVER)\r
+    _path = _netResource.RemoteName + WCHAR_PATH_SEPARATOR;\r
+  }\r
+  _parentFolder = parentFolder;\r
+}\r
+\r
+STDMETHODIMP CNetFolder::LoadItems()\r
+{\r
+  _items.Clear();\r
+  CEnum enumerator;\r
+\r
+  for (;;)\r
+  {\r
+    DWORD result = enumerator.Open(\r
+      RESOURCE_GLOBALNET,\r
+      RESOURCETYPE_DISK,\r
+      0,        // enumerate all resources\r
+      _netResourcePointer\r
+      );\r
+    if (result == NO_ERROR)\r
+      break;\r
+    if (result != ERROR_ACCESS_DENIED)\r
+      return result;\r
+    if (_netResourcePointer != 0)\r
+    result = AddConnection2(_netResource,\r
+        0, 0, CONNECT_INTERACTIVE);\r
+    if (result != NO_ERROR)\r
+      return result;\r
+  }\r
+\r
+  for (;;)\r
+  {\r
+    CResourceEx resource;\r
+    DWORD result = enumerator.Next(resource);\r
+    if (result == NO_ERROR)\r
+    {\r
+      if (!resource.RemoteNameIsDefined) // For Win 98, I don't know what's wrong\r
+        resource.RemoteName = resource.Comment;\r
+      resource.Name = resource.RemoteName;\r
+      int pos = resource.Name.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+      if (pos >= 0)\r
+      {\r
+        // _path = resource.Name.Left(pos + 1);\r
+        resource.Name = resource.Name.Mid(pos + 1);\r
+      }\r
+      _items.Add(resource);\r
+    }\r
+    else if (result == ERROR_NO_MORE_ITEMS)\r
+      break;\r
+    else\r
+      return result;\r
+  }\r
+\r
+  /*\r
+  It's too slow for some systems.\r
+  if (_netResourcePointer && _netResource.DisplayType == RESOURCEDISPLAYTYPE_SERVER)\r
+  {\r
+    for (char c = 'a'; c <= 'z'; c++)\r
+    {\r
+      CResourceEx resource;\r
+      resource.Name = UString(wchar_t(c)) + L'$';\r
+      resource.RemoteNameIsDefined = true;\r
+      resource.RemoteName = _path + resource.Name;\r
+\r
+      NFile::NFind::CFindFile findFile;\r
+      NFile::NFind::CFileInfoW fileInfo;\r
+      if (!findFile.FindFirst(resource.RemoteName + UString(WCHAR_PATH_SEPARATOR) + UString(L"*"), fileInfo))\r
+        continue;\r
+      resource.Usage = RESOURCEUSAGE_CONNECTABLE;\r
+      resource.LocalNameIsDefined = false;\r
+      resource.CommentIsDefined = false;\r
+      resource.ProviderIsDefined = false;\r
+      _items.Add(resource);\r
+    }\r
+  }\r
+  */\r
+  return S_OK;\r
+}\r
+\r
+\r
+STDMETHODIMP CNetFolder::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = _items.Size();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CNetFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  const CResourceEx &item = _items[itemIndex];\r
+  switch(propID)\r
+  {\r
+    case kpidIsDir:  prop = true; break;\r
+    case kpidName:\r
+      // if (item.RemoteNameIsDefined)\r
+        prop = item.Name;\r
+      break;\r
+    case kpidLocalName:  if (item.LocalNameIsDefined) prop = item.LocalName; break;\r
+    case kpidComment: if (item.CommentIsDefined) prop = item.Comment; break;\r
+    case kpidProvider: if (item.ProviderIsDefined) prop = item.Provider; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CNetFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder)\r
+{\r
+  *resultFolder = 0;\r
+  const CResourceEx &resource = _items[index];\r
+  if (resource.Usage == RESOURCEUSAGE_CONNECTABLE ||\r
+      resource.DisplayType == RESOURCEDISPLAYTYPE_SHARE)\r
+  {\r
+    NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;\r
+    CMyComPtr<IFolderFolder> subFolder = fsFolderSpec;\r
+    RINOK(fsFolderSpec->Init(resource.RemoteName + WCHAR_PATH_SEPARATOR, this));\r
+    *resultFolder = subFolder.Detach();\r
+  }\r
+  else\r
+  {\r
+    CNetFolder *netFolder = new CNetFolder;\r
+    CMyComPtr<IFolderFolder> subFolder = netFolder;\r
+    netFolder->Init(&resource, this, resource.Name + WCHAR_PATH_SEPARATOR);\r
+    *resultFolder = subFolder.Detach();\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CNetFolder::BindToFolder(const wchar_t * /* name */, IFolderFolder ** /* resultFolder */)\r
+{\r
+  return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CNetFolder::BindToParentFolder(IFolderFolder **resultFolder)\r
+{\r
+  *resultFolder = 0;\r
+  if (_parentFolder)\r
+  {\r
+    CMyComPtr<IFolderFolder> parentFolder = _parentFolder;\r
+    *resultFolder = parentFolder.Detach();\r
+    return S_OK;\r
+  }\r
+  if (_netResourcePointer != 0)\r
+  {\r
+    CResourceW resourceParent;\r
+    DWORD result = GetResourceParent(_netResource, resourceParent);\r
+    if (result != NO_ERROR)\r
+      return result;\r
+    if (!_netResource.RemoteNameIsDefined)\r
+      return S_OK;\r
+\r
+    CNetFolder *netFolder = new CNetFolder;\r
+    CMyComPtr<IFolderFolder> subFolder = netFolder;\r
+    netFolder->Init(&resourceParent, 0, WCHAR_PATH_SEPARATOR);\r
+    *resultFolder = subFolder.Detach();\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+IMP_IFolderFolder_Props(CNetFolder)\r
+\r
+STDMETHODIMP CNetFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidType: prop = L"NetFolder"; break;\r
+    case kpidPath: prop = _path; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CNetFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)\r
+{\r
+  if (index >= (UInt32)_items.Size())\r
+    return E_INVALIDARG;\r
+  *iconIndex = 0;\r
+  const CResourceW &resource = _items[index];\r
+  int iconIndexTemp;\r
+  if (resource.DisplayType == RESOURCEDISPLAYTYPE_SERVER ||\r
+      resource.Usage == RESOURCEUSAGE_CONNECTABLE)\r
+  {\r
+    if (GetRealIconIndex(resource.RemoteName, 0, iconIndexTemp))\r
+    {\r
+      *iconIndex = iconIndexTemp;\r
+      return S_OK;\r
+    }\r
+  }\r
+  else\r
+  {\r
+    if (GetRealIconIndex(TEXT(""), FILE_ATTRIBUTE_DIRECTORY, iconIndexTemp))\r
+    {\r
+      *iconIndex = iconIndexTemp;\r
+      return S_OK;\r
+    }\r
+    // *anIconIndex = GetRealIconIndex(0, L"\\\\HOME");\r
+  }\r
+  return GetLastError();\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/NetFolder.h b/CPP/7zip/UI/FileManager/NetFolder.h
new file mode 100755 (executable)
index 0000000..3fc1cdb
--- /dev/null
@@ -0,0 +1,40 @@
+// NetFolder.h\r
+\r
+#ifndef __NET_FOLDER_H\r
+#define __NET_FOLDER_H\r
+\r
+#include "Common/MyCom.h"\r
+\r
+#include "Windows/Net.h"\r
+\r
+#include "IFolder.h"\r
+\r
+struct CResourceEx: public NWindows::NNet::CResourceW\r
+{\r
+  UString Name;\r
+};\r
+\r
+class CNetFolder:\r
+  public IFolderFolder,\r
+  public IFolderGetSystemIconIndex,\r
+  public CMyUnknownImp\r
+{\r
+  NWindows::NNet::CResourceW _netResource;\r
+  NWindows::NNet::CResourceW *_netResourcePointer;\r
+\r
+  CObjectVector<CResourceEx> _items;\r
+\r
+  CMyComPtr<IFolderFolder> _parentFolder;\r
+  UString _path;\r
+public:\r
+  MY_UNKNOWN_IMP1(IFolderGetSystemIconIndex)\r
+  INTERFACE_FolderFolder(;)\r
+  STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex);\r
+\r
+  CNetFolder(): _netResourcePointer(0) {}\r
+  void Init(const UString &path);\r
+  void Init(const NWindows::NNet::CResourceW *netResource,\r
+      IFolderFolder *parentFolder, const UString &path);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/OpenCallback.cpp b/CPP/7zip/UI/FileManager/OpenCallback.cpp
new file mode 100755 (executable)
index 0000000..08c3adf
--- /dev/null
@@ -0,0 +1,123 @@
+// OpenCallback.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../../Common/FileStreams.h"\r
+\r
+#include "OpenCallback.h"\r
+#include "PasswordDialog.h"\r
+\r
+using namespace NWindows;\r
+\r
+STDMETHODIMP COpenArchiveCallback::SetTotal(const UInt64 *numFiles, const UInt64 *numBytes)\r
+{\r
+  RINOK(ProgressDialog.Sync.ProcessStopAndPause());\r
+  {\r
+    NSynchronization::CCriticalSectionLock lock(_criticalSection);\r
+    if (numFiles != NULL)\r
+    {\r
+      ProgressDialog.Sync.SetNumFilesTotal(*numFiles);\r
+      ProgressDialog.Sync.SetBytesProgressMode(false);\r
+    }\r
+    if (numBytes != NULL)\r
+      ProgressDialog.Sync.SetNumBytesTotal(*numBytes);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP COpenArchiveCallback::SetCompleted(const UInt64 *numFiles, const UInt64 *numBytes)\r
+{\r
+  RINOK(ProgressDialog.Sync.ProcessStopAndPause());\r
+  NSynchronization::CCriticalSectionLock lock(_criticalSection);\r
+  if (numFiles != NULL)\r
+    ProgressDialog.Sync.SetNumFilesCur(*numFiles);\r
+  if (numBytes != NULL)\r
+    ProgressDialog.Sync.SetPos(*numBytes);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP COpenArchiveCallback::SetTotal(const UInt64 total)\r
+{\r
+  RINOK(ProgressDialog.Sync.ProcessStopAndPause());\r
+  ProgressDialog.Sync.SetNumBytesTotal(total);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP COpenArchiveCallback::SetCompleted(const UInt64 *completed)\r
+{\r
+  RINOK(ProgressDialog.Sync.ProcessStopAndPause());\r
+  if (completed != NULL)\r
+    ProgressDialog.Sync.SetPos(*completed);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP COpenArchiveCallback::GetProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  if (_subArchiveMode)\r
+  {\r
+    switch(propID)\r
+    {\r
+      case kpidName: prop = _subArchiveName; break;\r
+    }\r
+  }\r
+  else\r
+  {\r
+    switch(propID)\r
+    {\r
+      case kpidName:  prop = _fileInfo.Name; break;\r
+      case kpidIsDir:  prop = _fileInfo.IsDir(); break;\r
+      case kpidSize:  prop = _fileInfo.Size; break;\r
+      case kpidAttrib:  prop = (UInt32)_fileInfo.Attrib; break;\r
+      case kpidCTime:  prop = _fileInfo.CTime; break;\r
+      case kpidATime:  prop = _fileInfo.ATime; break;\r
+      case kpidMTime:  prop = _fileInfo.MTime; break;\r
+    }\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name,\r
+    IInStream **inStream)\r
+{\r
+  *inStream = NULL;\r
+  if (_subArchiveMode)\r
+    return S_FALSE;\r
+\r
+  NFile::NFind::CFileInfoW fileInfo;\r
+\r
+  UString fullPath = _folderPrefix + name;\r
+  if (!fileInfo.Find(fullPath))\r
+    return S_FALSE;\r
+  _fileInfo = fileInfo;\r
+  if (_fileInfo.IsDir())\r
+    return S_FALSE;\r
+  CInFileStream *inFile = new CInFileStream;\r
+  CMyComPtr<IInStream> inStreamTemp = inFile;\r
+  if (!inFile->Open(fullPath))\r
+    return ::GetLastError();\r
+  *inStream = inStreamTemp.Detach();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP COpenArchiveCallback::CryptoGetTextPassword(BSTR *password)\r
+{\r
+  PasswordWasAsked = true;\r
+  if (!PasswordIsDefined)\r
+  {\r
+    CPasswordDialog dialog;\r
+   \r
+    ProgressDialog.WaitCreating();\r
+    if (dialog.Create(ProgressDialog) == IDCANCEL)\r
+      return E_ABORT;\r
+\r
+    Password = dialog.Password;\r
+    PasswordIsDefined = true;\r
+  }\r
+  return StringToBstr(Password, password);\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/OpenCallback.h b/CPP/7zip/UI/FileManager/OpenCallback.h
new file mode 100755 (executable)
index 0000000..31ef1f2
--- /dev/null
@@ -0,0 +1,92 @@
+// OpenCallback.h\r
+\r
+#ifndef __OPENCALLBACK_H\r
+#define __OPENCALLBACK_H\r
+\r
+#include "Common/MyCom.h"\r
+#include "Common/MyString.h"\r
+\r
+#include "Windows/FileFind.h"\r
+\r
+#include "../../IPassword.h"\r
+\r
+#include "../../Archive/IArchive.h"\r
+\r
+#ifdef _SFX\r
+#include "ProgressDialog.h"\r
+#else\r
+#include "ProgressDialog2.h"\r
+#endif\r
+\r
+\r
+class COpenArchiveCallback:\r
+  public IArchiveOpenCallback,\r
+  public IArchiveOpenVolumeCallback,\r
+  public IArchiveOpenSetSubArchiveName,\r
+  public IProgress,\r
+  public ICryptoGetTextPassword,\r
+  public CMyUnknownImp\r
+{\r
+  UString _folderPrefix;\r
+  NWindows::NFile::NFind::CFileInfoW _fileInfo;\r
+  NWindows::NSynchronization::CCriticalSection _criticalSection;\r
+  bool _subArchiveMode;\r
+  UString _subArchiveName;\r
+\r
+public:\r
+  bool PasswordIsDefined;\r
+  bool PasswordWasAsked;\r
+  UString Password;\r
+  HWND ParentWindow;\r
+  CProgressDialog ProgressDialog;\r
+\r
+  MY_UNKNOWN_IMP5(\r
+    IArchiveOpenCallback,\r
+    IArchiveOpenVolumeCallback,\r
+    IArchiveOpenSetSubArchiveName,\r
+    IProgress,\r
+    ICryptoGetTextPassword)\r
+\r
+  INTERFACE_IProgress(;)\r
+  INTERFACE_IArchiveOpenCallback(;)\r
+  INTERFACE_IArchiveOpenVolumeCallback(;)\r
+\r
+  // ICryptoGetTextPassword\r
+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);\r
+\r
+  STDMETHOD(SetSubArchiveName(const wchar_t *name))\r
+  {\r
+    _subArchiveMode = true;\r
+    _subArchiveName = name;\r
+    return  S_OK;\r
+  }\r
+\r
+  COpenArchiveCallback():\r
+    ParentWindow(0)\r
+  {\r
+    _subArchiveMode = false;\r
+    PasswordIsDefined = false;\r
+    PasswordWasAsked = false;\r
+  }\r
+  /*\r
+  void Init()\r
+  {\r
+    PasswordIsDefined = false;\r
+    _subArchiveMode = false;\r
+  }\r
+  */\r
+  void LoadFileInfo(const UString &folderPrefix, const UString &fileName)\r
+  {\r
+    _folderPrefix = folderPrefix;\r
+    if (!_fileInfo.Find(_folderPrefix + fileName))\r
+      throw 1;\r
+  }\r
+  void ShowMessage(const UInt64 *completed);\r
+\r
+  INT_PTR StartProgressDialog(const UString &title, NWindows::CThread &thread)\r
+  {\r
+    return ProgressDialog.Create(title, thread, ParentWindow);\r
+  }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/OptionsDialog.cpp b/CPP/7zip/UI/FileManager/OptionsDialog.cpp
new file mode 100755 (executable)
index 0000000..db237cd
--- /dev/null
@@ -0,0 +1,145 @@
+// OptionsDialog.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/Control/Dialog.h"\r
+#include "Windows/Control/PropertyPage.h"\r
+\r
+#include "DialogSize.h"\r
+#include "EditPage.h"\r
+#include "EditPageRes.h"\r
+#include "FoldersPage.h"\r
+#include "FoldersPageRes.h"\r
+#include "LangPage.h"\r
+#include "LangPageRes.h"\r
+#include "MenuPage.h"\r
+#include "MenuPageRes.h"\r
+// #include "PluginsPage.h"\r
+// #include "PluginsPageRes.h"\r
+#include "SettingsPage.h"\r
+#include "SettingsPageRes.h"\r
+#include "SystemPage.h"\r
+#include "SystemPageRes.h"\r
+\r
+#include "App.h"\r
+#include "LangUtils.h"\r
+#include "MyLoadMenu.h"\r
+#include "ProgramLocation.h"\r
+\r
+#include "resource.h"\r
+\r
+using namespace NWindows;\r
+\r
+#ifndef UNDER_CE\r
+typedef UINT32 (WINAPI * DllRegisterServerPtr)();\r
+\r
+extern HWND g_MenuPageHWND;\r
+\r
+static void ShowMenuErrorMessage(const wchar_t *m)\r
+{\r
+  MessageBoxW(g_MenuPageHWND, m, L"7-Zip", MB_ICONERROR);\r
+}\r
+\r
+static int DllRegisterServer2(const char *name)\r
+{\r
+  NWindows::NDLL::CLibrary lib;\r
+\r
+  UString prefix;\r
+  GetProgramFolderPath(prefix);\r
+  if (!lib.Load(prefix + L"7-zip.dll"))\r
+  {\r
+    ShowMenuErrorMessage(L"7-Zip cannot load 7-zip.dll");\r
+    return E_FAIL;\r
+  }\r
+  DllRegisterServerPtr f = (DllRegisterServerPtr)lib.GetProc(name);\r
+  if (f == NULL)\r
+  {\r
+    ShowMenuErrorMessage(L"Incorrect plugin");\r
+    return E_FAIL;\r
+  }\r
+  HRESULT res = f();\r
+  if (res != S_OK)\r
+    ShowMenuErrorMessage(HResultToMessage(res));\r
+  return (int)res;\r
+}\r
+\r
+STDAPI DllRegisterServer(void)\r
+{\r
+  #ifdef UNDER_CE\r
+  return S_OK;\r
+  #else\r
+  return DllRegisterServer2("DllRegisterServer");\r
+  #endif\r
+}\r
+\r
+STDAPI DllUnregisterServer(void)\r
+{\r
+  #ifdef UNDER_CE\r
+  return S_OK;\r
+  #else\r
+  return DllRegisterServer2("DllUnregisterServer");\r
+  #endif\r
+}\r
+\r
+#endif\r
+\r
+void OptionsDialog(HWND hwndOwner, HINSTANCE /* hInstance */)\r
+{\r
+  CSystemPage systemPage;\r
+  // CPluginsPage pluginsPage;\r
+  CEditPage editPage;\r
+  CSettingsPage settingsPage;\r
+  CLangPage langPage;\r
+  CMenuPage menuPage;\r
+  CFoldersPage foldersPage;\r
+\r
+  CObjectVector<NControl::CPageInfo> pages;\r
+  UINT32 langIDs[] = { 0x03010300,\r
+    // 0x03010100,\r
+    0xFFFFFFFF,\r
+    0x01000200, 0x03010200, 0x03010400, 0x01000400};\r
+  \r
+  BIG_DIALOG_SIZE(200, 200);\r
+\r
+  UINT pageIDs[] = {\r
+      SIZED_DIALOG(IDD_SYSTEM),\r
+      // IDD_PLUGINS,\r
+      SIZED_DIALOG(IDD_MENU),\r
+      SIZED_DIALOG(IDD_FOLDERS),\r
+      SIZED_DIALOG(IDD_EDIT),\r
+      SIZED_DIALOG(IDD_SETTINGS),\r
+      SIZED_DIALOG(IDD_LANG) };\r
+  NControl::CPropertyPage *pagePinters[] = { &systemPage,  &menuPage, &foldersPage, &editPage, &settingsPage, &langPage };\r
+  const int kNumPages = sizeof(langIDs) / sizeof(langIDs[0]);\r
+  for (int i = 0; i < kNumPages; i++)\r
+  {\r
+    NControl::CPageInfo page;\r
+    page.Title = LangString(langIDs[i]);\r
+    page.ID = pageIDs[i];\r
+    page.Page = pagePinters[i];\r
+    pages.Add(page);\r
+  }\r
+\r
+  INT_PTR res = NControl::MyPropertySheet(pages, hwndOwner, LangString(IDS_OPTIONS, 0x03010000));\r
+  if (res != -1 && res != 0)\r
+  {\r
+    if (langPage.LangWasChanged)\r
+    {\r
+      g_App._window.SetText(LangString(IDS_APP_TITLE, 0x03000000));\r
+      MyLoadMenu();\r
+      g_App.ReloadToolbars();\r
+      g_App.MoveSubWindows();\r
+    }\r
+    /*\r
+    if (systemPage.WasChanged)\r
+    {\r
+      // probably it doesn't work, since image list is locked?\r
+      g_App.SysIconsWereChanged();\r
+    }\r
+    */\r
+    g_App.SetListSettings();\r
+    g_App.SetShowSystemMenu();\r
+    g_App.RefreshAllPanels();\r
+    // ::PostMessage(hwndOwner, kLangWasChangedMessage, 0 , 0);\r
+  }\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
new file mode 100755 (executable)
index 0000000..17d2712
--- /dev/null
@@ -0,0 +1,137 @@
+// OverwriteDialog.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/FileName.h"\r
+#include "Windows/Defs.h"\r
+#include "Windows/ResourceString.h"\r
+#include "Windows/Control/Static.h"\r
+#include "Windows/PropVariantConversions.h"\r
+\r
+#include "FormatUtils.h"\r
+#include "OverwriteDialog.h"\r
+\r
+// #include "../resource.h"\r
+\r
+#ifdef LANG\r
+#include "LangUtils.h"\r
+#endif\r
+\r
+using namespace NWindows;\r
+\r
+#ifdef LANG\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDC_STATIC_OVERWRITE_HEADER,         0x02000901},\r
+  { IDC_STATIC_OVERWRITE_QUESTION_BEGIN, 0x02000902 },\r
+  { IDC_STATIC_OVERWRITE_QUESTION_END,   0x02000903 },\r
+  { IDYES, 0x02000705 },\r
+  { IDC_BUTTON_OVERWRITE_YES_TO_ALL, 0x02000707 },\r
+  { IDNO,  0x02000709 },\r
+  { IDC_BUTTON_OVERWRITE_NO_TO_ALL,0x0200070B },\r
+  { IDC_BUTTON_OVERWRITE_AUTO_RENAME, 0x02000911 },\r
+  { IDCANCEL, 0x02000711 }\r
+};\r
+#endif\r
+\r
+static const int kCurrentFileNameSizeLimit = 82;\r
+static const int kCurrentFileNameSizeLimit2 = 30;\r
+\r
+void COverwriteDialog::ReduceString(UString &s)\r
+{\r
+  int size = _isBig ? kCurrentFileNameSizeLimit : kCurrentFileNameSizeLimit2;\r
+  if (s.Length() > size)\r
+    s = s.Left(size / 2) + UString(L" ... ") + s.Right(size / 2);\r
+}\r
+\r
+void COverwriteDialog::SetFileInfoControl(int textID, int iconID,\r
+    const NOverwriteDialog::CFileInfo &fileInfo)\r
+{\r
+  UString sizeString;\r
+  if (fileInfo.SizeIsDefined)\r
+    sizeString = MyFormatNew(IDS_FILE_SIZE,\r
+        #ifdef LANG\r
+        0x02000982,\r
+        #endif\r
+        NumberToString(fileInfo.Size));\r
+\r
+  const UString &fileName = fileInfo.Name;\r
+  int slashPos = fileName.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+  UString s1, s2;\r
+  if (slashPos >= 0)\r
+  {\r
+    s1 = fileName.Left(slashPos + 1);\r
+    s2 = fileName.Mid(slashPos + 1);\r
+  }\r
+  else\r
+    s2 = fileName;\r
+  ReduceString(s1);\r
+  ReduceString(s2);\r
+  \r
+  UString fullString = s1 + L'\n' + s2;\r
+  fullString += L'\n';\r
+  fullString += sizeString;\r
+  fullString += L'\n';\r
+\r
+  if (fileInfo.TimeIsDefined)\r
+  {\r
+    UString timeString;\r
+    FILETIME localFileTime;\r
+    if (!FileTimeToLocalFileTime(&fileInfo.Time, &localFileTime))\r
+      throw 4190402;\r
+    timeString = ConvertFileTimeToString(localFileTime);\r
+\r
+    fullString +=\r
+    #ifdef LANG\r
+    LangString(IDS_FILE_MODIFIED, 0x02000983);\r
+    #else\r
+    MyLoadStringW(IDS_FILE_MODIFIED);\r
+    #endif\r
+\r
+    fullString += L" ";\r
+    fullString += timeString;\r
+  }\r
+\r
+  NWindows::NControl::CDialogChildControl control;\r
+  control.Init(*this, textID);\r
+  control.SetText(fullString);\r
+\r
+  SHFILEINFO shellFileInfo;\r
+  if (::SHGetFileInfo(\r
+      GetSystemString(fileInfo.Name), FILE_ATTRIBUTE_NORMAL, &shellFileInfo,\r
+      sizeof(shellFileInfo), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES | SHGFI_LARGEICON))\r
+  {\r
+    NControl::CStatic staticContol;\r
+    staticContol.Attach(GetItem(iconID));\r
+    staticContol.SetIcon(shellFileInfo.hIcon);\r
+  }\r
+}\r
+\r
+bool COverwriteDialog::OnInit()\r
+{\r
+  #ifdef LANG\r
+  LangSetWindowText(HWND(*this), 0x02000900);\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+  #endif\r
+  SetFileInfoControl(IDC_STATIC_OVERWRITE_OLD_FILE_SIZE_TIME, IDC_STATIC_OVERWRITE_OLD_FILE_ICON, OldFileInfo);\r
+  SetFileInfoControl(IDC_STATIC_OVERWRITE_NEW_FILE_SIZE_TIME, IDC_STATIC_OVERWRITE_NEW_FILE_ICON, NewFileInfo);\r
+  NormalizePosition();\r
+  return CModalDialog::OnInit();\r
+}\r
+\r
+bool COverwriteDialog::OnButtonClicked(int buttonID, HWND buttonHWND)\r
+{\r
+  switch(buttonID)\r
+  {\r
+    case IDYES:\r
+    case IDC_BUTTON_OVERWRITE_YES_TO_ALL:\r
+    case IDNO:\r
+    case IDC_BUTTON_OVERWRITE_NO_TO_ALL:\r
+    case IDC_BUTTON_OVERWRITE_AUTO_RENAME:\r
+      End(buttonID);\r
+      return true;\r
+  }\r
+  return CModalDialog::OnButtonClicked(buttonID, buttonHWND);\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.h b/CPP/7zip/UI/FileManager/OverwriteDialog.h
new file mode 100755 (executable)
index 0000000..3fef9b2
--- /dev/null
@@ -0,0 +1,71 @@
+// OverwriteDialog.h\r
+\r
+#ifndef __OVERWRITE_DIALOG_H\r
+#define __OVERWRITE_DIALOG_H\r
+\r
+#include "Common/Types.h"\r
+\r
+#include "Windows/Control/Dialog.h"\r
+\r
+#include "DialogSize.h"\r
+#include "OverwriteDialogRes.h"\r
+\r
+namespace NOverwriteDialog\r
+{\r
+  struct CFileInfo\r
+  {\r
+    bool SizeIsDefined;\r
+    bool TimeIsDefined;\r
+    UInt64 Size;\r
+    FILETIME Time;\r
+    UString Name;\r
+    \r
+    void SetTime(const FILETIME *t)\r
+    {\r
+      if (t == 0)\r
+        TimeIsDefined = false;\r
+      else\r
+      {\r
+        TimeIsDefined = true;\r
+        Time = *t;\r
+      }\r
+    }\r
+    void SetSize(const UInt64 *size)\r
+    {\r
+      if (size == 0)\r
+        SizeIsDefined = false;\r
+      else\r
+      {\r
+        SizeIsDefined = true;\r
+        Size = *size;\r
+      }\r
+    }\r
+  };\r
+}\r
+\r
+class COverwriteDialog: public NWindows::NControl::CModalDialog\r
+{\r
+  bool _isBig;\r
+\r
+  void SetFileInfoControl(int textID, int iconID, const NOverwriteDialog::CFileInfo &fileInfo);\r
+  virtual bool OnInit();\r
+  bool OnButtonClicked(int buttonID, HWND buttonHWND);\r
+  void ReduceString(UString &s);\r
+\r
+public:\r
+  INT_PTR Create(HWND parent = 0)\r
+  {\r
+    BIG_DIALOG_SIZE(280, 200);\r
+    #ifdef UNDER_CE\r
+    _isBig = isBig;\r
+    #else\r
+    _isBig = true;\r
+    #endif\r
+    return CModalDialog::Create(SIZED_DIALOG(IDD_DIALOG_OVERWRITE), parent);\r
+  }\r
+\r
+  NOverwriteDialog::CFileInfo OldFileInfo;\r
+  NOverwriteDialog::CFileInfo NewFileInfo;\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.rc b/CPP/7zip/UI/FileManager/OverwriteDialog.rc
new file mode 100755 (executable)
index 0000000..55a08fc
--- /dev/null
@@ -0,0 +1,92 @@
+#include "OverwriteDialogRes.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#define xc 280\r
+#define yc 200\r
+\r
+#undef iconSize\r
+#define iconSize 24\r
+\r
+#undef x\r
+#undef fx\r
+#undef fy\r
+#define x (m + iconSize + m)\r
+#define fx (xc - iconSize - m)\r
+#define fy 50\r
+\r
+#define bSizeBig 104\r
+#undef bx1\r
+#define bx1 (xs - m - bSizeBig)\r
+\r
+IDD_DIALOG_OVERWRITE MY_DIALOG\r
+CAPTION "Confirm File Replace"\r
+BEGIN\r
+  LTEXT "Destination folder already contains processed file.", IDC_STATIC_OVERWRITE_HEADER, m, 7, xc, 8\r
+  LTEXT "Would you like to replace the existing file", IDC_STATIC_OVERWRITE_QUESTION_BEGIN, m, 28, xc, 8\r
+  \r
+  ICON  "", IDC_STATIC_OVERWRITE_OLD_FILE_ICON,             m,  44, iconSize, iconSize\r
+  LTEXT "", IDC_STATIC_OVERWRITE_OLD_FILE_SIZE_TIME,        x,  44, fx, fy, SS_NOPREFIX\r
+  \r
+  LTEXT "with this one?",IDC_STATIC_OVERWRITE_QUESTION_END, m,  98, xc, 8\r
+\r
+  ICON  "",IDC_STATIC_OVERWRITE_NEW_FILE_ICON,              m, 114, iconSize, iconSize\r
+  LTEXT "",IDC_STATIC_OVERWRITE_NEW_FILE_SIZE_TIME,         x, 114, fx, fy, SS_NOPREFIX\r
+  \r
+  PUSHBUTTON "&Yes",         IDYES,                            bx3, by2, bxs, bys\r
+  PUSHBUTTON "Yes to &All",  IDC_BUTTON_OVERWRITE_YES_TO_ALL,  bx2, by2, bxs, bys\r
+  PUSHBUTTON "A&uto Rename", IDC_BUTTON_OVERWRITE_AUTO_RENAME, bx1, by2, bSizeBig, bys\r
+  PUSHBUTTON "&No",          IDNO,                             bx3, by1, bxs, bys\r
+  PUSHBUTTON "No to A&ll",   IDC_BUTTON_OVERWRITE_NO_TO_ALL,   bx2, by1, bxs, bys\r
+  PUSHBUTTON "&Cancel",      IDCANCEL,                xs - m - bxs, by1, bxs, bys\r
+END\r
+\r
+\r
+#ifdef UNDER_CE\r
+\r
+#undef m\r
+#undef xc\r
+#undef yc\r
+\r
+#define m 4\r
+#define xc 152\r
+#define yc 144\r
+\r
+#undef fy\r
+#define fy 40\r
+\r
+#undef  bxs\r
+#define bxs 48\r
+\r
+#undef bx1\r
+\r
+#define bx1 (xs - m - bxs)\r
+\r
+IDD_DIALOG_OVERWRITE_2 MY_DIALOG\r
+CAPTION "Confirm File Replace"\r
+BEGIN\r
+  LTEXT "Would you like to replace the existing file", IDC_STATIC_OVERWRITE_QUESTION_BEGIN, m, m, xc, 8\r
+  \r
+  ICON  "", IDC_STATIC_OVERWRITE_OLD_FILE_ICON,             m,  20, iconSize, iconSize\r
+  LTEXT "", IDC_STATIC_OVERWRITE_OLD_FILE_SIZE_TIME,        x,  20, fx, fy, SS_NOPREFIX\r
+  \r
+  LTEXT "with this one?",IDC_STATIC_OVERWRITE_QUESTION_END, m,  60, xc, 8\r
+\r
+  ICON  "",IDC_STATIC_OVERWRITE_NEW_FILE_ICON,              m,  72, iconSize, iconSize\r
+  LTEXT "",IDC_STATIC_OVERWRITE_NEW_FILE_SIZE_TIME,         x,  72, fx, fy, SS_NOPREFIX\r
+  \r
+  PUSHBUTTON "&Yes",         IDYES,                            bx3, by2, bxs, bys\r
+  PUSHBUTTON "Yes to &All",  IDC_BUTTON_OVERWRITE_YES_TO_ALL,  bx2, by2, bxs, bys\r
+  PUSHBUTTON "A&uto Rename", IDC_BUTTON_OVERWRITE_AUTO_RENAME, bx1, by2, bxs, bys\r
+  PUSHBUTTON "&No",          IDNO,                             bx3, by1, bxs, bys\r
+  PUSHBUTTON "No to A&ll",   IDC_BUTTON_OVERWRITE_NO_TO_ALL,   bx2, by1, bxs, bys\r
+  PUSHBUTTON "&Cancel",      IDCANCEL,                         bx1, by1, bxs, bys\r
+END\r
+\r
+#endif\r
+\r
+\r
+STRINGTABLE\r
+BEGIN\r
+  IDS_FILE_MODIFIED "modified on"\r
+  IDS_FILE_SIZE     "{0} bytes"\r
+END\r
diff --git a/CPP/7zip/UI/FileManager/OverwriteDialogRes.h b/CPP/7zip/UI/FileManager/OverwriteDialogRes.h
new file mode 100755 (executable)
index 0000000..42699db
--- /dev/null
@@ -0,0 +1,20 @@
+#define IDD_DIALOG_OVERWRITE             502\r
+#define IDD_DIALOG_OVERWRITE_2           602\r
+\r
+#define IDS_FILE_MODIFIED               600\r
+#define IDS_FILE_SIZE                   601\r
+\r
+#define IDC_STATIC_OVERWRITE_HEADER     1000\r
+\r
+#define IDC_STATIC_OVERWRITE_QUESTION_BEGIN 1001\r
+#define IDC_STATIC_OVERWRITE_QUESTION_END 1002\r
+\r
+#define IDC_STATIC_OVERWRITE_OLD_FILE_ICON 1003\r
+#define IDC_STATIC_OVERWRITE_NEW_FILE_ICON 1004\r
+\r
+#define IDC_STATIC_OVERWRITE_OLD_FILE_SIZE_TIME 1005\r
+#define IDC_STATIC_OVERWRITE_NEW_FILE_SIZE_TIME 1006\r
+\r
+#define IDC_BUTTON_OVERWRITE_YES_TO_ALL 1010\r
+#define IDC_BUTTON_OVERWRITE_NO_TO_ALL  1011\r
+#define IDC_BUTTON_OVERWRITE_AUTO_RENAME 1012\r
diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp
new file mode 100755 (executable)
index 0000000..3106b84
--- /dev/null
@@ -0,0 +1,991 @@
+// Panel.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include <Windowsx.h>\r
+\r
+#include "Common/Defs.h"\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/Error.h"\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Thread.h"\r
+\r
+#include "../../PropID.h"\r
+\r
+#include "resource.h"\r
+#include "../GUI/ExtractRes.h"\r
+\r
+#include "../Common/ArchiveName.h"\r
+#include "../Common/CompressCall.h"\r
+\r
+#include "../Agent/IFolderArchive.h"\r
+\r
+#include "App.h"\r
+#include "ExtractCallback.h"\r
+#include "FSFolder.h"\r
+#include "FormatUtils.h"\r
+#include "Panel.h"\r
+#include "RootFolder.h"\r
+\r
+\r
+using namespace NWindows;\r
+using namespace NControl;\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+static const UINT_PTR kTimerID = 1;\r
+static const UINT kTimerElapse = 1000;\r
+\r
+static DWORD kStyles[4] = { LVS_ICON, LVS_SMALLICON, LVS_LIST, LVS_REPORT };\r
+\r
+// static const int kCreateFolderID = 101;\r
+// static const UINT kFileChangeNotifyMessage = WM_APP;\r
+\r
+extern HINSTANCE g_hInstance;\r
+extern DWORD g_ComCtl32Version;\r
+\r
+void CPanel::Release()\r
+{\r
+  // It's for unloading COM dll's: don't change it.\r
+  CloseOpenFolders();\r
+  _sevenZipContextMenu.Release();\r
+  _systemContextMenu.Release();\r
+}\r
+\r
+CPanel::~CPanel()\r
+{\r
+  CloseOpenFolders();\r
+}\r
+\r
+HWND CPanel::GetParent()\r
+{\r
+  HWND h = CWindow2::GetParent();\r
+  return (h == 0) ? _mainWindow : h;\r
+}\r
+\r
+static LPCWSTR kClassName = L"7-Zip::Panel";\r
+\r
+\r
+HRESULT CPanel::Create(HWND mainWindow, HWND parentWindow, UINT id,\r
+    const UString &currentFolderPrefix,\r
+    const UString &arcFormat,\r
+    CPanelCallback *panelCallback, CAppState *appState,\r
+    bool &archiveIsOpened, bool &encrypted)\r
+{\r
+  _mainWindow = mainWindow;\r
+  _processTimer = true;\r
+  _processNotify = true;\r
+\r
+  _panelCallback = panelCallback;\r
+  _appState = appState;\r
+  // _index = index;\r
+  _baseID = id;\r
+  _comboBoxID = _baseID + 3;\r
+  _statusBarID = _comboBoxID + 1;\r
+\r
+  UString cfp = currentFolderPrefix;\r
+\r
+  if (!currentFolderPrefix.IsEmpty())\r
+    if (currentFolderPrefix[0] == L'.')\r
+      if (!NFile::NDirectory::MyGetFullPathName(currentFolderPrefix, cfp))\r
+        cfp = currentFolderPrefix;\r
+  RINOK(BindToPath(cfp, arcFormat, archiveIsOpened, encrypted));\r
+\r
+  if (!CreateEx(0, kClassName, 0, WS_CHILD | WS_VISIBLE,\r
+      0, 0, _xSize, 260,\r
+      parentWindow, (HMENU)(UINT_PTR)id, g_hInstance))\r
+    return E_FAIL;\r
+  return S_OK;\r
+}\r
+\r
+LRESULT CPanel::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+  switch(message)\r
+  {\r
+    case kShiftSelectMessage:\r
+      OnShiftSelectMessage();\r
+      return 0;\r
+    case kReLoadMessage:\r
+      RefreshListCtrl(_selectedState);\r
+      return 0;\r
+    case kSetFocusToListView:\r
+      _listView.SetFocus();\r
+      return 0;\r
+    case kOpenItemChanged:\r
+      return OnOpenItemChanged(lParam);\r
+    case kRefreshStatusBar:\r
+      OnRefreshStatusBar();\r
+      return 0;\r
+    case kRefreshHeaderComboBox:\r
+      LoadFullPathAndShow();\r
+      return 0;\r
+    case WM_TIMER:\r
+      OnTimer();\r
+      return 0;\r
+    case WM_CONTEXTMENU:\r
+      if (OnContextMenu(HANDLE(wParam), GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)))\r
+        return 0;\r
+      break;\r
+    /*\r
+    case WM_DROPFILES:\r
+      CompressDropFiles(HDROP(wParam));\r
+      return 0;\r
+    */\r
+  }\r
+  return CWindow2::OnMessage(message, wParam, lParam);\r
+}\r
+\r
+static LRESULT APIENTRY ListViewSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+  CWindow tempDialog(hwnd);\r
+  CMyListView *w = (CMyListView *)(tempDialog.GetUserDataLongPtr());\r
+  if (w == NULL)\r
+    return 0;\r
+  return w->OnMessage(message, wParam, lParam);\r
+}\r
+\r
+LRESULT CMyListView::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+  if (message == WM_CHAR)\r
+  {\r
+    UINT scanCode = (UINT)((lParam >> 16) & 0xFF);\r
+    bool extended = ((lParam & 0x1000000) != 0);\r
+    UINT virtualKey = MapVirtualKey(scanCode, 1);\r
+    if (virtualKey == VK_MULTIPLY || virtualKey == VK_ADD ||\r
+        virtualKey == VK_SUBTRACT)\r
+      return 0;\r
+    if ((wParam == '/' && extended)\r
+        || wParam == '\\' || wParam == '/')\r
+    {\r
+      _panel->OpenDrivesFolder();\r
+      return 0;\r
+    }\r
+  }\r
+  else if (message == WM_SYSCHAR)\r
+  {\r
+    // For Alt+Enter Beep disabling\r
+    UINT scanCode = (UINT)(lParam >> 16) & 0xFF;\r
+    UINT virtualKey = MapVirtualKey(scanCode, 1);\r
+    if (virtualKey == VK_RETURN || virtualKey == VK_MULTIPLY ||\r
+        virtualKey == VK_ADD || virtualKey == VK_SUBTRACT)\r
+      return 0;\r
+  }\r
+  /*\r
+  else if (message == WM_SYSKEYDOWN)\r
+  {\r
+    // return 0;\r
+  }\r
+  */\r
+  else if (message == WM_KEYDOWN)\r
+  {\r
+    bool alt = (::GetKeyState(VK_MENU) & 0x8000) != 0;\r
+    bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0;\r
+    // bool leftCtrl = (::GetKeyState(VK_LCONTROL) & 0x8000) != 0;\r
+    // bool RightCtrl = (::GetKeyState(VK_RCONTROL) & 0x8000) != 0;\r
+    bool shift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0;\r
+    switch(wParam)\r
+    {\r
+      /*\r
+      case VK_RETURN:\r
+      {\r
+        if (shift && !alt && !ctrl)\r
+        {\r
+          _panel->OpenSelectedItems(false);\r
+          return 0;\r
+        }\r
+        break;\r
+      }\r
+      */\r
+      case VK_NEXT:\r
+      {\r
+        if (ctrl && !alt && !shift)\r
+        {\r
+          _panel->OpenFocusedItemAsInternal();\r
+          return 0;\r
+        }\r
+        break;\r
+      }\r
+      case VK_PRIOR:\r
+      if (ctrl && !alt && !shift)\r
+      {\r
+        _panel->OpenParentFolder();\r
+        return 0;\r
+      }\r
+    }\r
+  }\r
+  #ifdef UNDER_CE\r
+  else if (message == WM_KEYUP)\r
+  {\r
+    if (wParam == VK_F2) // it's VK_TSOFT2\r
+    {\r
+      // Activate Menu\r
+      ::PostMessage(g_HWND, WM_SYSCOMMAND, SC_KEYMENU, 0);\r
+      return 0;\r
+    }\r
+  }\r
+  #endif\r
+  else if (message == WM_SETFOCUS)\r
+  {\r
+    _panel->_lastFocusedIsList = true;\r
+    _panel->_panelCallback->PanelWasFocused();\r
+  }\r
+  #ifndef _UNICODE\r
+  if (g_IsNT)\r
+    return CallWindowProcW(_origWindowProc, *this, message, wParam, lParam);\r
+  else\r
+  #endif\r
+    return CallWindowProc(_origWindowProc, *this, message, wParam, lParam);\r
+}\r
+\r
+/*\r
+static LRESULT APIENTRY ComboBoxSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+  CWindow tempDialog(hwnd);\r
+  CMyComboBox *w = (CMyComboBox *)(tempDialog.GetUserDataLongPtr());\r
+  if (w == NULL)\r
+    return 0;\r
+  return w->OnMessage(message, wParam, lParam);\r
+}\r
+\r
+LRESULT CMyComboBox::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+  return CallWindowProc(_origWindowProc, *this, message, wParam, lParam);\r
+}\r
+*/\r
+static LRESULT APIENTRY ComboBoxEditSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+  CWindow tempDialog(hwnd);\r
+  CMyComboBoxEdit *w = (CMyComboBoxEdit *)(tempDialog.GetUserDataLongPtr());\r
+  if (w == NULL)\r
+    return 0;\r
+  return w->OnMessage(message, wParam, lParam);\r
+}\r
+\r
+LRESULT CMyComboBoxEdit::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+  // See MSDN / Subclassing a Combo Box / Creating a Combo-box Toolbar\r
+  switch (message)\r
+  {\r
+    case WM_SYSKEYDOWN:\r
+      switch (wParam)\r
+      {\r
+        case VK_F1:\r
+        case VK_F2:\r
+        {\r
+          // check ALT\r
+          if ((lParam & (1<<29)) == 0)\r
+            break;\r
+          bool alt = (::GetKeyState(VK_MENU) & 0x8000) != 0;\r
+          bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0;\r
+          bool shift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0;\r
+          if (alt && !ctrl && !shift)\r
+          {\r
+            _panel->_panelCallback->SetFocusToPath(wParam == VK_F1 ? 0 : 1);\r
+            return 0;\r
+          }\r
+          break;\r
+        }\r
+      }\r
+      break;\r
+    case WM_KEYDOWN:\r
+      switch (wParam)\r
+      {\r
+        case VK_TAB:\r
+          // SendMessage(hwndMain, WM_ENTER, 0, 0);\r
+          _panel->SetFocusToList();\r
+          return 0;\r
+        case VK_F9:\r
+        {\r
+          bool alt = (::GetKeyState(VK_MENU) & 0x8000) != 0;\r
+          bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0;\r
+          bool shift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0;\r
+          if (!alt && !ctrl && !shift)\r
+          {\r
+            g_App.SwitchOnOffOnePanel();;\r
+            return 0;\r
+          }\r
+          break;\r
+        }\r
+      }\r
+      break;\r
+    case WM_CHAR:\r
+      switch (wParam)\r
+      {\r
+        case VK_TAB:\r
+        case VK_ESCAPE:\r
+          return 0;\r
+      }\r
+  }\r
+  #ifndef _UNICODE\r
+  if (g_IsNT)\r
+    return CallWindowProcW(_origWindowProc, *this, message, wParam, lParam);\r
+  else\r
+  #endif\r
+    return CallWindowProc(_origWindowProc, *this, message, wParam, lParam);\r
+}\r
+\r
+bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */)\r
+{\r
+  // _virtualMode = false;\r
+  // _sortIndex = 0;\r
+  _sortID = kpidName;\r
+  _ascending = true;\r
+  _lastFocusedIsList = true;\r
+\r
+  DWORD style = WS_CHILD | WS_VISIBLE; //  | WS_BORDER ; // | LVS_SHAREIMAGELISTS; //  | LVS_SHOWSELALWAYS;;\r
+\r
+  style |= LVS_SHAREIMAGELISTS;\r
+  // style  |= LVS_AUTOARRANGE;\r
+  style |= WS_CLIPCHILDREN;\r
+  style |= WS_CLIPSIBLINGS;\r
+\r
+  const UInt32 kNumListModes = sizeof(kStyles) / sizeof(kStyles[0]);\r
+  if (_ListViewMode >= kNumListModes)\r
+    _ListViewMode = kNumListModes - 1;\r
+\r
+  style |= kStyles[_ListViewMode]\r
+    | WS_TABSTOP\r
+    | LVS_EDITLABELS;\r
+  if (_mySelectMode)\r
+    style |= LVS_SINGLESEL;\r
+\r
+  /*\r
+  if (_virtualMode)\r
+    style |= LVS_OWNERDATA;\r
+  */\r
+\r
+  DWORD exStyle;\r
+  exStyle = WS_EX_CLIENTEDGE;\r
+\r
+  if (!_listView.CreateEx(exStyle, style, 0, 0, 116, 260,\r
+      HWND(*this), (HMENU)(UINT_PTR)(_baseID + 1), g_hInstance, NULL))\r
+    return false;\r
+\r
+  #ifndef UNDER_CE\r
+  _listView.SetUnicodeFormat(true);\r
+  #endif\r
+\r
+  _listView.SetUserDataLongPtr(LONG_PTR(&_listView));\r
+  _listView._panel = this;\r
+\r
+   #ifndef _UNICODE\r
+   if(g_IsNT)\r
+     _listView._origWindowProc =\r
+      (WNDPROC)_listView.SetLongPtrW(GWLP_WNDPROC, LONG_PTR(ListViewSubclassProc));\r
+   else\r
+   #endif\r
+     _listView._origWindowProc =\r
+      (WNDPROC)_listView.SetLongPtr(GWLP_WNDPROC, LONG_PTR(ListViewSubclassProc));\r
+\r
+  _listView.SetImageList(GetSysImageList(true), LVSIL_SMALL);\r
+  _listView.SetImageList(GetSysImageList(false), LVSIL_NORMAL);\r
+\r
+  // _exStyle |= LVS_EX_HEADERDRAGDROP;\r
+  // DWORD extendedStyle = _listView.GetExtendedListViewStyle();\r
+  // extendedStyle |= _exStyle;\r
+  //  _listView.SetExtendedListViewStyle(extendedStyle);\r
+  SetExtendedStyle();\r
+\r
+  _listView.Show(SW_SHOW);\r
+  _listView.InvalidateRect(NULL, true);\r
+  _listView.Update();\r
+  \r
+  // Ensure that the common control DLL is loaded.\r
+  INITCOMMONCONTROLSEX icex;\r
+\r
+  icex.dwSize = sizeof(INITCOMMONCONTROLSEX);\r
+  icex.dwICC  = ICC_BAR_CLASSES;\r
+  InitCommonControlsEx(&icex);\r
+\r
+  TBBUTTON tbb [ ] =\r
+  {\r
+    // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0},\r
+    {VIEW_PARENTFOLDER, kParentFolderID, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0},\r
+    // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0},\r
+    // {VIEW_NEWFOLDER, kCreateFolderID, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0},\r
+  };\r
+\r
+  #ifndef UNDER_CE\r
+  if (g_ComCtl32Version >= MAKELONG(71, 4))\r
+  #endif\r
+  {\r
+    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);\r
+    icex.dwICC  = ICC_COOL_CLASSES | ICC_BAR_CLASSES;\r
+    InitCommonControlsEx(&icex);\r
+    \r
+    _headerReBar.Attach(::CreateWindowEx(WS_EX_TOOLWINDOW,\r
+      REBARCLASSNAME,\r
+      NULL, WS_VISIBLE | WS_BORDER | WS_CHILD |\r
+      WS_CLIPCHILDREN | WS_CLIPSIBLINGS\r
+      | CCS_NODIVIDER\r
+      // | CCS_NOPARENTALIGN\r
+      | CCS_TOP\r
+      | RBS_VARHEIGHT\r
+      | RBS_BANDBORDERS\r
+      ,0,0,0,0, HWND(*this), NULL, g_hInstance, NULL));\r
+  }\r
+\r
+  DWORD toolbarStyle =  WS_CHILD | WS_VISIBLE ;\r
+  if (_headerReBar)\r
+  {\r
+    toolbarStyle |= 0\r
+      // | WS_CLIPCHILDREN\r
+      // | WS_CLIPSIBLINGS\r
+\r
+      | TBSTYLE_TOOLTIPS\r
+      | CCS_NODIVIDER\r
+      | CCS_NORESIZE\r
+      | TBSTYLE_FLAT\r
+      ;\r
+  }\r
+\r
+  _headerToolBar.Attach(::CreateToolbarEx ((*this), toolbarStyle,\r
+      _baseID + 2, 11,\r
+      (HINSTANCE)HINST_COMMCTRL,\r
+      IDB_VIEW_SMALL_COLOR,\r
+      (LPCTBBUTTON)&tbb, sizeof(tbb) / sizeof(tbb[0]),\r
+      0, 0, 0, 0, sizeof (TBBUTTON)));\r
+\r
+  #ifndef UNDER_CE\r
+  // Load ComboBoxEx class\r
+  icex.dwSize = sizeof(INITCOMMONCONTROLSEX);\r
+  icex.dwICC = ICC_USEREX_CLASSES;\r
+  InitCommonControlsEx(&icex);\r
+  #endif\r
+  \r
+  _headerComboBox.CreateEx(0,\r
+      #ifdef UNDER_CE\r
+      WC_COMBOBOXW\r
+      #else\r
+      WC_COMBOBOXEXW\r
+      #endif\r
+      , NULL,\r
+    WS_BORDER | WS_VISIBLE |WS_CHILD | CBS_DROPDOWN | CBS_AUTOHSCROLL,\r
+      0, 0, 100, 520,\r
+      ((_headerReBar == 0) ? HWND(*this) : _headerToolBar),\r
+      (HMENU)(UINT_PTR)(_comboBoxID),\r
+      g_hInstance, NULL);\r
+  #ifndef UNDER_CE\r
+  _headerComboBox.SetUnicodeFormat(true);\r
+\r
+  _headerComboBox.SetImageList(GetSysImageList(true));\r
+\r
+  _headerComboBox.SetExtendedStyle(CBES_EX_PATHWORDBREAKPROC, CBES_EX_PATHWORDBREAKPROC);\r
+\r
+  /*\r
+  _headerComboBox.SetUserDataLongPtr(LONG_PTR(&_headerComboBox));\r
+  _headerComboBox._panel = this;\r
+  _headerComboBox._origWindowProc =\r
+      (WNDPROC)_headerComboBox.SetLongPtr(GWLP_WNDPROC,\r
+      LONG_PTR(ComboBoxSubclassProc));\r
+  */\r
+  _comboBoxEdit.Attach(_headerComboBox.GetEditControl());\r
+\r
+  // _comboBoxEdit.SendMessage(CCM_SETUNICODEFORMAT, (WPARAM)(BOOL)TRUE, 0);\r
+\r
+  _comboBoxEdit.SetUserDataLongPtr(LONG_PTR(&_comboBoxEdit));\r
+  _comboBoxEdit._panel = this;\r
+   #ifndef _UNICODE\r
+   if(g_IsNT)\r
+     _comboBoxEdit._origWindowProc =\r
+      (WNDPROC)_comboBoxEdit.SetLongPtrW(GWLP_WNDPROC, LONG_PTR(ComboBoxEditSubclassProc));\r
+   else\r
+   #endif\r
+     _comboBoxEdit._origWindowProc =\r
+      (WNDPROC)_comboBoxEdit.SetLongPtr(GWLP_WNDPROC, LONG_PTR(ComboBoxEditSubclassProc));\r
+\r
+  #endif\r
+\r
+  if (_headerReBar)\r
+  {\r
+    REBARINFO     rbi;\r
+    rbi.cbSize = sizeof(REBARINFO);  // Required when using this struct.\r
+    rbi.fMask  = 0;\r
+    rbi.himl   = (HIMAGELIST)NULL;\r
+    _headerReBar.SetBarInfo(&rbi);\r
+    \r
+    // Send the TB_BUTTONSTRUCTSIZE message, which is required for\r
+    // backward compatibility.\r
+    // _headerToolBar.SendMessage(TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);\r
+    SIZE size;\r
+    _headerToolBar.GetMaxSize(&size);\r
+    \r
+    REBARBANDINFO rbBand;\r
+    rbBand.cbSize = sizeof(REBARBANDINFO);  // Required\r
+    rbBand.fMask = RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE;\r
+    rbBand.fStyle = RBBS_NOGRIPPER;\r
+    rbBand.cxMinChild = size.cx;\r
+    rbBand.cyMinChild = size.cy;\r
+    rbBand.cyChild = size.cy;\r
+    rbBand.cx = size.cx;\r
+    rbBand.hwndChild  = _headerToolBar;\r
+    _headerReBar.InsertBand(-1, &rbBand);\r
+\r
+    RECT rc;\r
+    ::GetWindowRect(_headerComboBox, &rc);\r
+    rbBand.cxMinChild = 30;\r
+    rbBand.cyMinChild = rc.bottom - rc.top;\r
+    rbBand.cx = 1000;\r
+    rbBand.hwndChild  = _headerComboBox;\r
+    _headerReBar.InsertBand(-1, &rbBand);\r
+    // _headerReBar.MaximizeBand(1, false);\r
+  }\r
+\r
+  _statusBar.Create(WS_CHILD | WS_VISIBLE, L"Status", (*this), _statusBarID);\r
+  // _statusBar2.Create(WS_CHILD | WS_VISIBLE, L"Status", (*this), _statusBarID + 1);\r
+\r
+  int sizes[] = {150, 250, 350, -1};\r
+  _statusBar.SetParts(4, sizes);\r
+  // _statusBar2.SetParts(5, sizes);\r
+\r
+  /*\r
+  RECT rect;\r
+  GetClientRect(&rect);\r
+  OnSize(0, rect.right - rect.left, rect.top - rect.bottom);\r
+  */\r
+\r
+  SetTimer(kTimerID, kTimerElapse);\r
+\r
+  // InitListCtrl();\r
+  RefreshListCtrl();\r
+  RefreshStatusBar();\r
+  \r
+  return true;\r
+}\r
+\r
+void CPanel::OnDestroy()\r
+{\r
+  SaveListViewInfo();\r
+  CWindow2::OnDestroy();\r
+}\r
+\r
+void CPanel::ChangeWindowSize(int xSize, int ySize)\r
+{\r
+  if ((HWND)*this == 0)\r
+    return;\r
+  int kHeaderSize;\r
+  int kStatusBarSize;\r
+  // int kStatusBar2Size;\r
+  RECT rect;\r
+  if (_headerReBar)\r
+    _headerReBar.GetWindowRect(&rect);\r
+  else\r
+    _headerToolBar.GetWindowRect(&rect);\r
+\r
+  kHeaderSize = rect.bottom - rect.top;\r
+\r
+  _statusBar.GetWindowRect(&rect);\r
+  kStatusBarSize = rect.bottom - rect.top;\r
+  \r
+  // _statusBar2.GetWindowRect(&rect);\r
+  // kStatusBar2Size = rect.bottom - rect.top;\r
\r
+  int yListViewSize = MyMax(ySize - kHeaderSize - kStatusBarSize, 0);\r
+  const int kStartXPos = 32;\r
+  if (_headerReBar)\r
+  {\r
+  }\r
+  else\r
+  {\r
+    _headerToolBar.Move(0, 0, xSize, 0);\r
+    _headerComboBox.Move(kStartXPos, 2,\r
+        MyMax(xSize - kStartXPos - 10, kStartXPos), 0);\r
+  }\r
+  _listView.Move(0, kHeaderSize, xSize, yListViewSize);\r
+  _statusBar.Move(0, kHeaderSize + yListViewSize, xSize, kStatusBarSize);\r
+  // _statusBar2.MoveWindow(0, kHeaderSize + yListViewSize + kStatusBarSize, xSize, kStatusBar2Size);\r
+  // _statusBar.MoveWindow(0, 100, xSize, kStatusBarSize);\r
+  // _statusBar2.MoveWindow(0, 200, xSize, kStatusBar2Size);\r
+}\r
+\r
+bool CPanel::OnSize(WPARAM /* wParam */, int xSize, int ySize)\r
+{\r
+  if ((HWND)*this == 0)\r
+    return true;\r
+  if (_headerReBar)\r
+    _headerReBar.Move(0, 0, xSize, 0);\r
+  ChangeWindowSize(xSize, ySize);\r
+  return true;\r
+}\r
+\r
+bool CPanel::OnNotifyReBar(LPNMHDR header, LRESULT & /* result */)\r
+{\r
+  switch(header->code)\r
+  {\r
+    case RBN_HEIGHTCHANGE:\r
+    {\r
+      RECT rect;\r
+      GetWindowRect(&rect);\r
+      ChangeWindowSize(rect.right - rect.left, rect.bottom - rect.top);\r
+      return false;\r
+    }\r
+  }\r
+  return false;\r
+}\r
+\r
+bool CPanel::OnNotify(UINT /* controlID */, LPNMHDR header, LRESULT &result)\r
+{\r
+  if (!_processNotify)\r
+    return false;\r
+  if (header->hwndFrom == _headerComboBox)\r
+    return OnNotifyComboBox(header, result);\r
+  else if (header->hwndFrom == _headerReBar)\r
+    return OnNotifyReBar(header, result);\r
+  // if (header->hwndFrom == _listView)\r
+  else if (header->hwndFrom == _listView)\r
+    return OnNotifyList(header, result);\r
+  else if (::GetParent(header->hwndFrom) == _listView &&\r
+      header->code == NM_RCLICK)\r
+    return OnRightClick((MY_NMLISTVIEW_NMITEMACTIVATE *)header, result);\r
+  return false;\r
+}\r
+\r
+bool CPanel::OnCommand(int code, int itemID, LPARAM lParam, LRESULT &result)\r
+{\r
+  if (itemID == kParentFolderID)\r
+  {\r
+    OpenParentFolder();\r
+    result = 0;\r
+    return true;\r
+  }\r
+  /*\r
+  if (itemID == kCreateFolderID)\r
+  {\r
+    CreateFolder();\r
+    result = 0;\r
+    return true;\r
+  }\r
+  */\r
+  if (itemID == _comboBoxID)\r
+  {\r
+    if (OnComboBoxCommand(code, lParam, result))\r
+      return true;\r
+  }\r
+  return CWindow2::OnCommand(code, itemID, lParam, result);\r
+}\r
+\r
+void CPanel::MessageBoxInfo(LPCWSTR message, LPCWSTR caption)\r
+  { ::MessageBoxW(HWND(*this), message, caption, MB_OK); }\r
+void CPanel::MessageBox(LPCWSTR message, LPCWSTR caption)\r
+  { ::MessageBoxW(HWND(*this), message, caption, MB_OK | MB_ICONSTOP); }\r
+void CPanel::MessageBox(LPCWSTR message)\r
+  { MessageBox(message, L"7-Zip"); }\r
+void CPanel::MessageBoxMyError(LPCWSTR message)\r
+  { MessageBox(message, L"Error"); }\r
+\r
+\r
+void CPanel::MessageBoxError(HRESULT errorCode, LPCWSTR caption)\r
+{\r
+  MessageBox(HResultToMessage(errorCode), caption);\r
+}\r
+\r
+void CPanel::MessageBoxError(HRESULT errorCode)\r
+  { MessageBoxError(errorCode, L"7-Zip"); }\r
+void CPanel::MessageBoxLastError(LPCWSTR caption)\r
+  { MessageBoxError(::GetLastError(), caption); }\r
+void CPanel::MessageBoxLastError()\r
+  { MessageBoxLastError(L"Error"); }\r
+\r
+void CPanel::MessageBoxErrorLang(UINT resourceID, UInt32 langID)\r
+  { MessageBox(LangString(resourceID, langID)); }\r
+\r
+\r
+void CPanel::SetFocusToList()\r
+{\r
+  _listView.SetFocus();\r
+  // SetCurrentPathText();\r
+}\r
+\r
+void CPanel::SetFocusToLastRememberedItem()\r
+{\r
+  if (_lastFocusedIsList)\r
+    SetFocusToList();\r
+  else\r
+    _headerComboBox.SetFocus();\r
+}\r
+\r
+UString CPanel::GetFolderTypeID() const\r
+{\r
+  NCOM::CPropVariant prop;\r
+  if (_folder->GetFolderProperty(kpidType, &prop) == S_OK)\r
+    if (prop.vt == VT_BSTR)\r
+      return (const wchar_t *)prop.bstrVal;\r
+  return L"";\r
+}\r
+\r
+bool CPanel::IsFolderTypeEqTo(const wchar_t *s) const\r
+{\r
+  return GetFolderTypeID() == s;\r
+}\r
+\r
+bool CPanel::IsRootFolder() const { return IsFolderTypeEqTo(L"RootFolder"); }\r
+bool CPanel::IsFSFolder() const { return IsFolderTypeEqTo(L"FSFolder"); }\r
+bool CPanel::IsFSDrivesFolder() const { return IsFolderTypeEqTo(L"FSDrives"); }\r
+bool CPanel::IsArcFolder() const\r
+{\r
+  UString s = GetFolderTypeID();\r
+  return s.Left(5) == L"7-Zip";\r
+}\r
+\r
+UString CPanel::GetFsPath() const\r
+{\r
+  if (IsFSDrivesFolder() && !IsDeviceDrivesPrefix())\r
+    return UString();\r
+  return _currentFolderPrefix;\r
+}\r
+\r
+UString CPanel::GetDriveOrNetworkPrefix() const\r
+{\r
+  if (!IsFSFolder())\r
+    return UString();\r
+  UString drive = GetFsPath();\r
+  if (drive.Length() < 3)\r
+    return UString();\r
+  if (drive[0] == L'\\' && drive[1] == L'\\')\r
+  {\r
+    // if network\r
+    int pos = drive.Find(L'\\', 2);\r
+    if (pos < 0)\r
+      return UString();\r
+    pos = drive.Find(L'\\', pos + 1);\r
+    if (pos < 0)\r
+      return UString();\r
+    return drive.Left(pos + 1);\r
+  }\r
+  if (drive[1] != L':' || drive[2] != L'\\')\r
+    return UString();\r
+  return drive.Left(3);\r
+}\r
+\r
+bool CPanel::DoesItSupportOperations() const\r
+{\r
+  CMyComPtr<IFolderOperations> folderOperations;\r
+  return _folder.QueryInterface(IID_IFolderOperations, &folderOperations) == S_OK;\r
+}\r
+\r
+void CPanel::SetListViewMode(UInt32 index)\r
+{\r
+  if (index >= 4)\r
+    return;\r
+  _ListViewMode = index;\r
+  DWORD oldStyle = (DWORD)_listView.GetStyle();\r
+  DWORD newStyle = kStyles[index];\r
+  if ((oldStyle & LVS_TYPEMASK) != newStyle)\r
+    _listView.SetStyle((oldStyle & ~LVS_TYPEMASK) | newStyle);\r
+  // RefreshListCtrlSaveFocused();\r
+}\r
+\r
+void CPanel::ChangeFlatMode()\r
+{\r
+  _flatMode = !_flatMode;\r
+  if (_parentFolders.Size() > 0)\r
+    _flatModeForArc = _flatMode;\r
+  else\r
+    _flatModeForDisk = _flatMode;\r
+  RefreshListCtrlSaveFocused();\r
+}\r
+\r
+\r
+void CPanel::RefreshStatusBar()\r
+{\r
+  PostMessage(kRefreshStatusBar);\r
+}\r
+\r
+void CPanel::AddToArchive()\r
+{\r
+  CRecordVector<UInt32> indices;\r
+  GetOperatedItemIndices(indices);\r
+  if (!IsFsOrDrivesFolder())\r
+  {\r
+    MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);\r
+    return;\r
+  }\r
+  if (indices.Size() == 0)\r
+  {\r
+    MessageBoxErrorLang(IDS_SELECT_FILES, 0x03020A03);\r
+    return;\r
+  }\r
+  UStringVector names;\r
+\r
+  UString curPrefix = _currentFolderPrefix;\r
+  UString destCurDirPrefix = _currentFolderPrefix;\r
+  if (IsFSDrivesFolder())\r
+  {\r
+    destCurDirPrefix = ROOT_FS_FOLDER;\r
+    if (!IsDeviceDrivesPrefix())\r
+      curPrefix.Empty();\r
+  }\r
+\r
+  for (int i = 0; i < indices.Size(); i++)\r
+    names.Add(curPrefix + GetItemRelPath(indices[i]));\r
+  const UString archiveName = CreateArchiveName(names.Front(), (names.Size() > 1), false);\r
+  HRESULT res = CompressFiles(destCurDirPrefix, archiveName, L"", names, false, true, false);\r
+  if (res != S_OK)\r
+  {\r
+    if (destCurDirPrefix.Length() >= MAX_PATH)\r
+      MessageBoxErrorLang(IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER, 0x03020A01);\r
+  }\r
+  // KillSelection();\r
+}\r
+\r
+static UString GetSubFolderNameForExtract(const UString &archiveName)\r
+{\r
+  int slashPos = archiveName.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+  int dotPos = archiveName.ReverseFind(L'.');\r
+  if (dotPos < 0 || slashPos > dotPos)\r
+    return archiveName + UString(L"~");\r
+  UString res = archiveName.Left(dotPos);\r
+  res.TrimRight();\r
+  return res;\r
+}\r
+\r
+void CPanel::GetFilePaths(const CRecordVector<UInt32> &indices, UStringVector &paths)\r
+{\r
+  for (int i = 0; i < indices.Size(); i++)\r
+  {\r
+    int index = indices[i];\r
+    if (IsItemFolder(index))\r
+    {\r
+      paths.Clear();\r
+      break;\r
+    }\r
+    paths.Add(GetItemFullPath(index));\r
+  }\r
+  if (paths.Size() == 0)\r
+  {\r
+    MessageBoxErrorLang(IDS_SELECT_FILES, 0x03020A03);\r
+    return;\r
+  }\r
+}\r
+\r
+void CPanel::ExtractArchives()\r
+{\r
+  if (_parentFolders.Size() > 0)\r
+  {\r
+    _panelCallback->OnCopy(false, false);\r
+    return;\r
+  }\r
+  CRecordVector<UInt32> indices;\r
+  GetOperatedItemIndices(indices);\r
+  UStringVector paths;\r
+  GetFilePaths(indices, paths);\r
+  if (paths.IsEmpty())\r
+    return;\r
+  UString folderName;\r
+  if (indices.Size() == 1)\r
+    folderName = GetSubFolderNameForExtract(GetItemRelPath(indices[0]));\r
+  else\r
+    folderName = L"*";\r
+  ::ExtractArchives(paths, _currentFolderPrefix + folderName + UString(WCHAR_PATH_SEPARATOR), true);\r
+}\r
+\r
+static void AddValuePair(UINT resourceID, UInt32 langID, UInt64 value, UString &s)\r
+{\r
+  wchar_t sz[32];\r
+  s += LangString(resourceID, langID);\r
+  s += L' ';\r
+  ConvertUInt64ToString(value, sz);\r
+  s += sz;\r
+  s += L'\n';\r
+}\r
+\r
+class CThreadTest: public CProgressThreadVirt\r
+{\r
+  HRESULT ProcessVirt();\r
+public:\r
+  CRecordVector<UInt32> Indices;\r
+  CExtractCallbackImp *ExtractCallbackSpec;\r
+  CMyComPtr<IFolderArchiveExtractCallback> ExtractCallback;\r
+  CMyComPtr<IArchiveFolder> ArchiveFolder;\r
+};\r
+\r
+HRESULT CThreadTest::ProcessVirt()\r
+{\r
+  RINOK(ArchiveFolder->Extract(&Indices[0], Indices.Size(),\r
+      NExtract::NPathMode::kFullPathnames, NExtract::NOverwriteMode::kAskBefore,\r
+      NULL, BoolToInt(true), ExtractCallback));\r
+  if (ExtractCallbackSpec->IsOK())\r
+  {\r
+    UString s;\r
+    AddValuePair(IDS_FOLDERS_COLON, 0x02000321, ExtractCallbackSpec->NumFolders, s);\r
+    AddValuePair(IDS_FILES_COLON, 0x02000320, ExtractCallbackSpec->NumFiles, s);\r
+    // AddSizePair(IDS_SIZE_COLON, 0x02000322, Stat.UnpackSize, s);\r
+    // AddSizePair(IDS_COMPRESSED_COLON, 0x02000323, Stat.PackSize, s);\r
+    s += L'\n';\r
+    s += LangString(IDS_MESSAGE_NO_ERRORS, 0x02000608);\r
+    OkMessage = s;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+/*\r
+static void AddSizePair(UINT resourceID, UInt32 langID, UInt64 value, UString &s)\r
+{\r
+  wchar_t sz[32];\r
+  s += LangString(resourceID, langID);\r
+  s += L" ";\r
+  ConvertUInt64ToString(value, sz);\r
+  s += sz;\r
+  ConvertUInt64ToString(value >> 20, sz);\r
+  s += L" (";\r
+  s += sz;\r
+  s += L" MB)";\r
+  s += L'\n';\r
+}\r
+*/\r
+\r
+void CPanel::TestArchives()\r
+{\r
+  CRecordVector<UInt32> indices;\r
+  GetOperatedIndicesSmart(indices);\r
+  CMyComPtr<IArchiveFolder> archiveFolder;\r
+  _folder.QueryInterface(IID_IArchiveFolder, &archiveFolder);\r
+  if (archiveFolder)\r
+  {\r
+    {\r
+    CThreadTest extracter;\r
+\r
+    extracter.ArchiveFolder = archiveFolder;\r
+    extracter.ExtractCallbackSpec = new CExtractCallbackImp;\r
+    extracter.ExtractCallback = extracter.ExtractCallbackSpec;\r
+    extracter.ExtractCallbackSpec->ProgressDialog = &extracter.ProgressDialog;\r
+\r
+    if (indices.IsEmpty())\r
+      return;\r
+\r
+    extracter.Indices = indices;\r
+    \r
+    UString title = LangString(IDS_PROGRESS_TESTING, 0x02000F90);\r
+    UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000);\r
+    \r
+    extracter.ProgressDialog.CompressingMode = false;\r
+    extracter.ProgressDialog.MainWindow = GetParent();\r
+    extracter.ProgressDialog.MainTitle = progressWindowTitle;\r
+    extracter.ProgressDialog.MainAddTitle = title + L" ";\r
+    \r
+    extracter.ExtractCallbackSpec->OverwriteMode = NExtract::NOverwriteMode::kAskBefore;\r
+    extracter.ExtractCallbackSpec->Init();\r
+    \r
+    if (extracter.Create(title, GetParent()) != S_OK)\r
+      return;\r
+    \r
+    }\r
+    RefreshTitleAlways();\r
+    return;\r
+  }\r
+\r
+  if (!IsFSFolder())\r
+  {\r
+    MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);\r
+    return;\r
+  }\r
+  UStringVector paths;\r
+  GetFilePaths(indices, paths);\r
+  if (paths.IsEmpty())\r
+    return;\r
+  ::TestArchives(paths);\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h
new file mode 100755 (executable)
index 0000000..2f1bcde
--- /dev/null
@@ -0,0 +1,629 @@
+// Panel.h\r
+\r
+#ifndef __PANEL_H\r
+#define __PANEL_H\r
+\r
+#include "../../../../C/Alloc.h"\r
+\r
+#include "Common/MyCom.h"\r
+\r
+#include "Windows/DLL.h"\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileFind.h"\r
+#include "Windows/Handle.h"\r
+#include "Windows/Synchronization.h"\r
+\r
+#include "Windows/Control/ComboBox.h"\r
+#include "Windows/Control/Edit.h"\r
+#include "Windows/Control/ListView.h"\r
+#include "Windows/Control/ReBar.h"\r
+#include "Windows/Control/Static.h"\r
+#include "Windows/Control/StatusBar.h"\r
+#include "Windows/Control/ToolBar.h"\r
+#include "Windows/Control/Window2.h"\r
+\r
+#include "AppState.h"\r
+#include "IFolder.h"\r
+#include "MyCom2.h"\r
+#include "ProgressDialog2.h"\r
+#include "SysIconUtils.h"\r
+\r
+const int kParentFolderID = 100;\r
+const int kPluginMenuStartID = 1000;\r
+const int kToolbarStartID = 2000;\r
+\r
+const int kParentIndex = -1;\r
+\r
+#ifdef UNDER_CE\r
+#define ROOT_FS_FOLDER L"\\"\r
+#else\r
+#define ROOT_FS_FOLDER L"C:\\\\"\r
+#endif\r
+\r
+struct CPanelCallback\r
+{\r
+  virtual void OnTab() = 0;\r
+  virtual void SetFocusToPath(int index) = 0;\r
+  virtual void OnCopy(bool move, bool copyToSame) = 0;\r
+  virtual void OnSetSameFolder() = 0;\r
+  virtual void OnSetSubFolder() = 0;\r
+  virtual void PanelWasFocused() = 0;\r
+  virtual void DragBegin() = 0;\r
+  virtual void DragEnd() = 0;\r
+  virtual void RefreshTitle(bool always) = 0;\r
+};\r
+\r
+void PanelCopyItems();\r
+\r
+struct CItemProperty\r
+{\r
+  UString Name;\r
+  PROPID ID;\r
+  VARTYPE Type;\r
+  int Order;\r
+  bool IsVisible;\r
+  UInt32 Width;\r
+};\r
+\r
+inline bool operator<(const CItemProperty &a1, const CItemProperty &a2)\r
+  { return (a1.Order < a2.Order); }\r
+\r
+inline bool operator==(const CItemProperty &a1, const CItemProperty &a2)\r
+  { return (a1.Order == a2.Order); }\r
+\r
+class CItemProperties: public CObjectVector<CItemProperty>\r
+{\r
+public:\r
+  int FindItemWithID(PROPID id)\r
+  {\r
+    for (int i = 0; i < Size(); i++)\r
+      if ((*this)[i].ID == id)\r
+        return i;\r
+    return -1;\r
+  }\r
+};\r
+\r
+struct CTempFileInfo\r
+{\r
+  UString ItemName;\r
+  UString FolderPath;\r
+  UString FilePath;\r
+  NWindows::NFile::NFind::CFileInfoW FileInfo;\r
+  bool NeedDelete;\r
+\r
+  CTempFileInfo(): NeedDelete(false) {}\r
+  void DeleteDirAndFile() const\r
+  {\r
+    if (NeedDelete)\r
+    {\r
+      NWindows::NFile::NDirectory::DeleteFileAlways(FilePath);\r
+      NWindows::NFile::NDirectory::MyRemoveDirectory(FolderPath);\r
+    }\r
+  }\r
+  bool WasChanged(const NWindows::NFile::NFind::CFileInfoW &newFileInfo) const\r
+  {\r
+    return newFileInfo.Size != FileInfo.Size ||\r
+        CompareFileTime(&newFileInfo.MTime, &FileInfo.MTime) != 0;\r
+  }\r
+};\r
+\r
+struct CFolderLink: public CTempFileInfo\r
+{\r
+  NWindows::NDLL::CLibrary Library;\r
+  CMyComPtr<IFolderFolder> ParentFolder;\r
+  bool UsePassword;\r
+  UString Password;\r
+  bool IsVirtual;\r
+\r
+  UString VirtualPath;\r
+  CFolderLink(): UsePassword(false), IsVirtual(false) {}\r
+\r
+  bool WasChanged(const NWindows::NFile::NFind::CFileInfoW &newFileInfo) const\r
+  {\r
+    return IsVirtual || CTempFileInfo::WasChanged(newFileInfo);\r
+  }\r
+\r
+};\r
+\r
+enum MyMessages\r
+{\r
+  kShiftSelectMessage = WM_USER + 1,\r
+  kReLoadMessage,\r
+  kSetFocusToListView,\r
+  kOpenItemChanged,\r
+  kRefreshStatusBar,\r
+  kRefreshHeaderComboBox\r
+};\r
+\r
+UString GetFolderPath(IFolderFolder * folder);\r
+\r
+class CPanel;\r
+\r
+class CMyListView: public NWindows::NControl::CListView\r
+{\r
+public:\r
+  WNDPROC _origWindowProc;\r
+  CPanel *_panel;\r
+  LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam);\r
+};\r
+\r
+/*\r
+class CMyComboBox: public NWindows::NControl::CComboBoxEx\r
+{\r
+public:\r
+  WNDPROC _origWindowProc;\r
+  CPanel *_panel;\r
+  LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam);\r
+};\r
+*/\r
+class CMyComboBoxEdit: public NWindows::NControl::CEdit\r
+{\r
+public:\r
+  WNDPROC _origWindowProc;\r
+  CPanel *_panel;\r
+  LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam);\r
+};\r
+\r
+struct CSelectedState\r
+{\r
+  int FocusedItem;\r
+  UString FocusedName;\r
+  bool SelectFocused;\r
+  UStringVector SelectedNames;\r
+  CSelectedState(): FocusedItem(-1), SelectFocused(false) {}\r
+};\r
+\r
+#ifdef UNDER_CE\r
+#define MY_NMLISTVIEW_NMITEMACTIVATE NMLISTVIEW\r
+#else\r
+#define MY_NMLISTVIEW_NMITEMACTIVATE NMITEMACTIVATE\r
+#endif\r
+\r
+class CPanel: public NWindows::NControl::CWindow2\r
+{\r
+  CExtToIconMap _extToIconMap;\r
+  UINT _baseID;\r
+  int _comboBoxID;\r
+  UINT _statusBarID;\r
+\r
+  CAppState *_appState;\r
+\r
+  bool OnCommand(int code, int itemID, LPARAM lParam, LRESULT &result);\r
+  LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam);\r
+  virtual bool OnCreate(CREATESTRUCT *createStruct);\r
+  virtual bool OnSize(WPARAM wParam, int xSize, int ySize);\r
+  virtual void OnDestroy();\r
+  virtual bool OnNotify(UINT controlID, LPNMHDR lParam, LRESULT &result);\r
+\r
+  void AddComboBoxItem(const UString &name, int iconIndex, int indent, bool addToList);\r
+\r
+  bool OnComboBoxCommand(UINT code, LPARAM param, LRESULT &result);\r
+  \r
+  #ifndef UNDER_CE\r
+  \r
+  LRESULT OnNotifyComboBoxEnter(const UString &s);\r
+  bool OnNotifyComboBoxEndEdit(PNMCBEENDEDITW info, LRESULT &result);\r
+  #ifndef _UNICODE\r
+  bool OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info, LRESULT &result);\r
+  #endif\r
+\r
+  #endif\r
+\r
+  bool OnNotifyReBar(LPNMHDR lParam, LRESULT &result);\r
+  bool OnNotifyComboBox(LPNMHDR lParam, LRESULT &result);\r
+  void OnItemChanged(NMLISTVIEW *item);\r
+  void OnNotifyActivateItems();\r
+  bool OnNotifyList(LPNMHDR lParam, LRESULT &result);\r
+  void OnDrag(LPNMLISTVIEW nmListView);\r
+  bool OnKeyDown(LPNMLVKEYDOWN keyDownInfo, LRESULT &result);\r
+  BOOL OnBeginLabelEdit(LV_DISPINFOW * lpnmh);\r
+  BOOL OnEndLabelEdit(LV_DISPINFOW * lpnmh);\r
+  void OnColumnClick(LPNMLISTVIEW info);\r
+  bool OnCustomDraw(LPNMLVCUSTOMDRAW lplvcd, LRESULT &result);\r
+\r
+public:\r
+  HWND _mainWindow;\r
+  CPanelCallback *_panelCallback;\r
+\r
+  void SysIconsWereChanged() { _extToIconMap.Clear(); }\r
+\r
+  void DeleteItems(bool toRecycleBin);\r
+  void DeleteItemsInternal(CRecordVector<UInt32> &indices);\r
+  void CreateFolder();\r
+  void CreateFile();\r
+\r
+private:\r
+\r
+  void ChangeWindowSize(int xSize, int ySize);\r
\r
+  HRESULT InitColumns();\r
+  // void InitColumns2(PROPID sortID);\r
+  void InsertColumn(int index);\r
+\r
+  void SetFocusedSelectedItem(int index, bool select);\r
+  HRESULT RefreshListCtrl(const UString &focusedName, int focusedPos, bool selectFocused,\r
+      const UStringVector &selectedNames);\r
+\r
+  void OnShiftSelectMessage();\r
+  void OnArrowWithShift();\r
+\r
+  void OnInsert();\r
+  // void OnUpWithShift();\r
+  // void OnDownWithShift();\r
+public:\r
+  void UpdateSelection();\r
+  void SelectSpec(bool selectMode);\r
+  void SelectByType(bool selectMode);\r
+  void SelectAll(bool selectMode);\r
+  void InvertSelection();\r
+private:\r
+\r
+  // UString GetFileType(UInt32 index);\r
+  LRESULT SetItemText(LVITEMW &item);\r
+\r
+  // CRecordVector<PROPID> m_ColumnsPropIDs;\r
+\r
+public:\r
+  NWindows::NControl::CReBar _headerReBar;\r
+  NWindows::NControl::CToolBar _headerToolBar;\r
+  NWindows::NControl::\r
+    #ifdef UNDER_CE\r
+    CComboBox\r
+    #else\r
+    CComboBoxEx\r
+    #endif\r
+    _headerComboBox;\r
+  UStringVector ComboBoxPaths;\r
+  // CMyComboBox _headerComboBox;\r
+  CMyComboBoxEdit _comboBoxEdit;\r
+  CMyListView _listView;\r
+  NWindows::NControl::CStatusBar _statusBar;\r
+  bool _lastFocusedIsList;\r
+  // NWindows::NControl::CStatusBar _statusBar2;\r
+\r
+  DWORD _exStyle;\r
+  bool _showDots;\r
+  bool _showRealFileIcons;\r
+  // bool _virtualMode;\r
+  // CUIntVector _realIndices;\r
+  bool _enableItemChangeNotify;\r
+  bool _mySelectMode;\r
+  CBoolVector _selectedStatusVector;\r
+\r
+  CSelectedState _selectedState;\r
+\r
+  HWND GetParent();\r
+\r
+  UInt32 GetRealIndex(const LVITEMW &item) const\r
+  {\r
+    /*\r
+    if (_virtualMode)\r
+      return _realIndices[item.iItem];\r
+    */\r
+    return (UInt32)item.lParam;\r
+  }\r
+  int GetRealItemIndex(int indexInListView) const\r
+  {\r
+    /*\r
+    if (_virtualMode)\r
+      return indexInListView;\r
+    */\r
+    LPARAM param;\r
+    if (!_listView.GetItemParam(indexInListView, param))\r
+      throw 1;\r
+    return (int)param;\r
+  }\r
+\r
+  UInt32 _ListViewMode;\r
+  int _xSize;\r
+\r
+  bool _flatMode;\r
+  bool _flatModeForDisk;\r
+  bool _flatModeForArc;\r
+\r
+  bool _dontShowMode;\r
+\r
+\r
+  UString _currentFolderPrefix;\r
+  \r
+  CObjectVector<CFolderLink> _parentFolders;\r
+  NWindows::NDLL::CLibrary _library;\r
+  CMyComPtr<IFolderFolder> _folder;\r
+  // CMyComPtr<IFolderGetSystemIconIndex> _folderGetSystemIconIndex;\r
+\r
+  UStringVector _fastFolders;\r
+\r
+  void GetSelectedNames(UStringVector &selectedNames);\r
+  void SaveSelectedState(CSelectedState &s);\r
+  HRESULT RefreshListCtrl(const CSelectedState &s);\r
+  HRESULT RefreshListCtrlSaveFocused();\r
+\r
+  UString GetItemName(int itemIndex) const;\r
+  UString GetItemPrefix(int itemIndex) const;\r
+  UString GetItemRelPath(int itemIndex) const;\r
+  UString GetItemFullPath(int itemIndex) const;\r
+  bool IsItemFolder(int itemIndex) const;\r
+  UInt64 GetItemSize(int itemIndex) const;\r
+\r
+  ////////////////////////\r
+  // PanelFolderChange.cpp\r
+\r
+  void SetToRootFolder();\r
+  HRESULT BindToPath(const UString &fullPath, const UString &arcFormat, bool &archiveIsOpened, bool &encrypted); // can be prefix\r
+  HRESULT BindToPathAndRefresh(const UString &path);\r
+  void OpenDrivesFolder();\r
+  \r
+  void SetBookmark(int index);\r
+  void OpenBookmark(int index);\r
+  \r
+  void LoadFullPath();\r
+  void LoadFullPathAndShow();\r
+  void FoldersHistory();\r
+  void OpenParentFolder();\r
+  void CloseOpenFolders();\r
+  void OpenRootFolder();\r
+\r
+\r
+  HRESULT Create(HWND mainWindow, HWND parentWindow,\r
+      UINT id,\r
+      const UString &currentFolderPrefix,\r
+      const UString &arcFormat,\r
+      CPanelCallback *panelCallback,\r
+      CAppState *appState, bool &archiveIsOpened, bool &encrypted);\r
+  void SetFocusToList();\r
+  void SetFocusToLastRememberedItem();\r
+\r
+\r
+  void ReadListViewInfo();\r
+  void SaveListViewInfo();\r
+\r
+  CPanel() :\r
+      // _virtualMode(flase),\r
+      _exStyle(0),\r
+      _showDots(false),\r
+      _showRealFileIcons(false),\r
+      _needSaveInfo(false),\r
+      _startGroupSelect(0),\r
+      _selectionIsDefined(false),\r
+      _ListViewMode(3),\r
+      _flatMode(false),\r
+      _flatModeForDisk(false),\r
+      _flatModeForArc(false),\r
+      _xSize(300),\r
+      _mySelectMode(false),\r
+      _enableItemChangeNotify(true),\r
+      _dontShowMode(false)\r
+  {}\r
+\r
+  void SetExtendedStyle()\r
+  {\r
+    if (_listView != 0)\r
+      _listView.SetExtendedListViewStyle(_exStyle);\r
+  }\r
+\r
+\r
+  bool _needSaveInfo;\r
+  UString _typeIDString;\r
+  CListViewInfo _listViewInfo;\r
+  CItemProperties _properties;\r
+  CItemProperties _visibleProperties;\r
+  \r
+  PROPID _sortID;\r
+  // int _sortIndex;\r
+  bool _ascending;\r
+\r
+  void Release();\r
+  ~CPanel();\r
+  void OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate);\r
+  bool OnRightClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate, LRESULT &result);\r
+  void ShowColumnsContextMenu(int x, int y);\r
+\r
+  void OnTimer();\r
+  void OnReload();\r
+  bool OnContextMenu(HANDLE windowHandle, int xPos, int yPos);\r
+\r
+  CMyComPtr<IContextMenu> _sevenZipContextMenu;\r
+  CMyComPtr<IContextMenu> _systemContextMenu;\r
+  HRESULT CreateShellContextMenu(\r
+      const CRecordVector<UInt32> &operatedIndices,\r
+      CMyComPtr<IContextMenu> &systemContextMenu);\r
+  void CreateSystemMenu(HMENU menu,\r
+      const CRecordVector<UInt32> &operatedIndices,\r
+      CMyComPtr<IContextMenu> &systemContextMenu);\r
+  void CreateSevenZipMenu(HMENU menu,\r
+      const CRecordVector<UInt32> &operatedIndices,\r
+      CMyComPtr<IContextMenu> &sevenZipContextMenu);\r
+  void CreateFileMenu(HMENU menu,\r
+      CMyComPtr<IContextMenu> &sevenZipContextMenu,\r
+      CMyComPtr<IContextMenu> &systemContextMenu,\r
+      bool programMenu);\r
+  void CreateFileMenu(HMENU menu);\r
+  bool InvokePluginCommand(int id);\r
+  bool InvokePluginCommand(int id, IContextMenu *sevenZipContextMenu,\r
+      IContextMenu *systemContextMenu);\r
+\r
+  void InvokeSystemCommand(const char *command);\r
+  void Properties();\r
+  void EditCut();\r
+  void EditCopy();\r
+  void EditPaste();\r
+\r
+  int _startGroupSelect;\r
+\r
+  bool _selectionIsDefined;\r
+  bool _selectMark;\r
+  int _prevFocusedItem;\r
+\r
\r
+  // void SortItems(int index);\r
+  void SortItemsWithPropID(PROPID propID);\r
+\r
+  void GetSelectedItemsIndices(CRecordVector<UInt32> &indices) const;\r
+  void GetOperatedItemIndices(CRecordVector<UInt32> &indices) const;\r
+  void GetAllItemIndices(CRecordVector<UInt32> &indices) const;\r
+  void GetOperatedIndicesSmart(CRecordVector<UInt32> &indices) const;\r
+  // void GetOperatedListViewIndices(CRecordVector<UInt32> &indices) const;\r
+  void KillSelection();\r
+\r
+  UString GetFolderTypeID() const;\r
+  bool IsFolderTypeEqTo(const wchar_t *s) const;\r
+  bool IsRootFolder() const;\r
+  bool IsFSFolder() const;\r
+  bool IsFSDrivesFolder() const;\r
+  bool IsArcFolder() const;\r
+  bool IsFsOrDrivesFolder() const { return IsFSFolder() || IsFSDrivesFolder(); }\r
+  bool IsDeviceDrivesPrefix() const { return _currentFolderPrefix == L"\\\\.\\"; }\r
+  bool IsFsOrPureDrivesFolder() const { return IsFSFolder() || (IsFSDrivesFolder() && !IsDeviceDrivesPrefix()); }\r
+\r
+  UString GetFsPath() const;\r
+  UString GetDriveOrNetworkPrefix() const;\r
+\r
+  bool DoesItSupportOperations() const;\r
+\r
+  bool _processTimer;\r
+  bool _processNotify;\r
+\r
+  class CDisableTimerProcessing\r
+  {\r
+    bool _processTimerMem;\r
+    bool _processNotifyMem;\r
+\r
+    CPanel &_panel;\r
+    public:\r
+\r
+    CDisableTimerProcessing(CPanel &panel): _panel(panel)\r
+    {\r
+      Disable();\r
+    }\r
+    void Disable()\r
+    {\r
+      _processTimerMem = _panel._processTimer;\r
+      _processNotifyMem = _panel._processNotify;\r
+      _panel._processTimer = false;\r
+      _panel._processNotify = false;\r
+    }\r
+    void Restore()\r
+    {\r
+      _panel._processTimer = _processTimerMem;\r
+      _panel._processNotify = _processNotifyMem;\r
+    }\r
+    ~CDisableTimerProcessing()\r
+    {\r
+      Restore();\r
+    }\r
+    CDisableTimerProcessing& operator=(const CDisableTimerProcessing &) {; }\r
+  };\r
+\r
+  // bool _passwordIsDefined;\r
+  // UString _password;\r
+\r
+  HRESULT RefreshListCtrl();\r
+\r
+  void MessageBoxInfo(LPCWSTR message, LPCWSTR caption);\r
+  void MessageBox(LPCWSTR message);\r
+  void MessageBox(LPCWSTR message, LPCWSTR caption);\r
+  void MessageBoxMyError(LPCWSTR message);\r
+  void MessageBoxError(HRESULT errorCode, LPCWSTR caption);\r
+  void MessageBoxError(HRESULT errorCode);\r
+  void MessageBoxLastError(LPCWSTR caption);\r
+  void MessageBoxLastError();\r
+\r
+  void MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID, UInt32 langID);\r
+\r
+  void MessageBoxErrorLang(UINT resourceID, UInt32 langID);\r
+\r
+  void OpenFocusedItemAsInternal();\r
+  void OpenSelectedItems(bool internal);\r
+\r
+  void OpenFolderExternal(int index);\r
+\r
+  void OpenFolder(int index);\r
+  HRESULT OpenParentArchiveFolder();\r
+  HRESULT OpenItemAsArchive(IInStream *inStream,\r
+      const CTempFileInfo &tempFileInfo,\r
+      const UString &virtualFilePath,\r
+      const UString &arcFormat,\r
+      bool &encrypted);\r
+  HRESULT OpenItemAsArchive(const UString &name, const UString &arcFormat, bool &encrypted);\r
+  HRESULT OpenItemAsArchive(int index);\r
+  void OpenItemInArchive(int index, bool tryInternal, bool tryExternal,\r
+      bool editMode);\r
+  HRESULT OnOpenItemChanged(const UString &folderPath, const UString &itemName, bool usePassword, const UString &password);\r
+  LRESULT OnOpenItemChanged(LPARAM lParam);\r
+\r
+  void OpenItem(int index, bool tryInternal, bool tryExternal);\r
+  void EditItem();\r
+  void EditItem(int index);\r
+\r
+  void RenameFile();\r
+  void ChangeComment();\r
+\r
+  void SetListViewMode(UInt32 index);\r
+  UInt32 GetListViewMode() const { return _ListViewMode; }\r
+  PROPID GetSortID() const { return _sortID; }\r
+\r
+  void ChangeFlatMode();\r
+  bool GetFlatMode() const { return _flatMode; }\r
+\r
+  void RefreshStatusBar();\r
+  void OnRefreshStatusBar();\r
+\r
+  void AddToArchive();\r
+\r
+  void GetFilePaths(const CRecordVector<UInt32> &indices, UStringVector &paths);\r
+  void ExtractArchives();\r
+  void TestArchives();\r
+\r
+  HRESULT CopyTo(const CRecordVector<UInt32> &indices, const UString &folder,\r
+      bool moveMode, bool showErrorMessages, UStringVector *messages,\r
+      bool &usePassword, UString &password);\r
+\r
+  HRESULT CopyTo(const CRecordVector<UInt32> &indices, const UString &folder,\r
+      bool moveMode, bool showErrorMessages, UStringVector *messages)\r
+  {\r
+    bool usePassword = false;\r
+    UString password;\r
+    if (_parentFolders.Size() > 0)\r
+    {\r
+      const CFolderLink &fl = _parentFolders.Back();\r
+      usePassword = fl.UsePassword;\r
+      password = fl.Password;\r
+    }\r
+    return CopyTo(indices, folder, moveMode, showErrorMessages, messages, usePassword, password);\r
+  }\r
+\r
+  HRESULT CopyFrom(const UString &folderPrefix, const UStringVector &filePaths,\r
+      bool showErrorMessages, UStringVector *messages);\r
+\r
+  void CopyFromNoAsk(const UStringVector &filePaths);\r
+  void CopyFromAsk(const UStringVector &filePaths);\r
+\r
+  // empty folderPath means create new Archive to path of first fileName.\r
+  void DropObject(IDataObject * dataObject, const UString &folderPath);\r
+\r
+  // empty folderPath means create new Archive to path of first fileName.\r
+  void CompressDropFiles(const UStringVector &fileNames, const UString &folderPath);\r
+\r
+  void RefreshTitle(bool always = false) { _panelCallback->RefreshTitle(always);  }\r
+  void RefreshTitleAlways() { RefreshTitle(true);  }\r
+\r
+  UString GetItemsInfoString(const CRecordVector<UInt32> &indices);\r
+};\r
+\r
+class CMyBuffer\r
+{\r
+  void *_data;\r
+public:\r
+  CMyBuffer(): _data(0) {}\r
+  operator void *() { return _data; }\r
+  bool Allocate(size_t size)\r
+  {\r
+    if (_data != 0)\r
+      return false;\r
+    _data = ::MidAlloc(size);\r
+    return _data != 0;\r
+  }\r
+  ~CMyBuffer() { ::MidFree(_data); }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/PanelCopy.cpp b/CPP/7zip/UI/FileManager/PanelCopy.cpp
new file mode 100755 (executable)
index 0000000..20e656e
--- /dev/null
@@ -0,0 +1,227 @@
+// PanelExtract.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Panel.h"\r
+#include "resource.h"\r
+#include "LangUtils.h"\r
+#include "ExtractCallback.h"\r
+#include "Windows/Thread.h"\r
+////////////////////////////////////////////////////////////////\r
+\r
+#include "UpdateCallback100.h"\r
+\r
+using namespace NWindows;\r
+\r
+class CPanelCopyThread: public CProgressThreadVirt\r
+{\r
+  HRESULT ProcessVirt();\r
+public:\r
+  CMyComPtr<IFolderOperations> FolderOperations;\r
+  CRecordVector<UInt32> Indices;\r
+  UString DestPath;\r
+  CExtractCallbackImp *ExtractCallbackSpec;\r
+  CMyComPtr<IFolderOperationsExtractCallback> ExtractCallback;\r
+  HRESULT Result;\r
+  bool MoveMode;\r
+\r
+  CPanelCopyThread(): MoveMode(false), Result(E_FAIL) {}\r
+};\r
+  \r
+HRESULT CPanelCopyThread::ProcessVirt()\r
+{\r
+  if (MoveMode)\r
+    Result = FolderOperations->MoveTo(&Indices.Front(), Indices.Size(), DestPath, ExtractCallback);\r
+  else\r
+    Result = FolderOperations->CopyTo(&Indices.Front(), Indices.Size(), DestPath, ExtractCallback);\r
+  return Result;\r
+}\r
+\r
+HRESULT CPanel::CopyTo(const CRecordVector<UInt32> &indices, const UString &folder,\r
+    bool moveMode, bool showErrorMessages, UStringVector *messages,\r
+    bool &usePassword, UString &password)\r
+{\r
+  CMyComPtr<IFolderOperations> folderOperations;\r
+  if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)\r
+  {\r
+    UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);\r
+    if (showErrorMessages)\r
+      MessageBox(errorMessage);\r
+    else if (messages != 0)\r
+      messages->Add(errorMessage);\r
+    return E_FAIL;\r
+  }\r
+\r
+  HRESULT res;\r
+  {\r
+  CPanelCopyThread extracter;\r
+\r
+  \r
+  extracter.ExtractCallbackSpec = new CExtractCallbackImp;\r
+  extracter.ExtractCallback = extracter.ExtractCallbackSpec;\r
+  extracter.ExtractCallbackSpec->ProgressDialog = &extracter.ProgressDialog;\r
+  extracter.ProgressDialog.CompressingMode = false;\r
+  \r
+  UString title = moveMode ?\r
+      LangString(IDS_MOVING, 0x03020206):\r
+      LangString(IDS_COPYING, 0x03020205);\r
+  UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000);\r
+  \r
+  extracter.ProgressDialog.MainWindow = GetParent();\r
+  extracter.ProgressDialog.MainTitle = progressWindowTitle;\r
+  extracter.ProgressDialog.MainAddTitle = title + L" ";\r
+    \r
+  extracter.ExtractCallbackSpec->OverwriteMode = NExtract::NOverwriteMode::kAskBefore;\r
+  extracter.ExtractCallbackSpec->Init();\r
+  extracter.Indices = indices;\r
+  extracter.DestPath = folder;\r
+  extracter.FolderOperations = folderOperations;\r
+  extracter.MoveMode = moveMode;\r
+\r
+  extracter.ExtractCallbackSpec->PasswordIsDefined = usePassword;\r
+  extracter.ExtractCallbackSpec->Password = password;\r
+  \r
+  RINOK(extracter.Create(title, GetParent()));\r
+  \r
+  if (messages != 0)\r
+    *messages = extracter.ProgressDialog.Sync.Messages;\r
+  res = extracter.Result;\r
+\r
+  if (res == S_OK && extracter.ExtractCallbackSpec->IsOK())\r
+  {\r
+    usePassword = extracter.ExtractCallbackSpec->PasswordIsDefined;\r
+    password = extracter.ExtractCallbackSpec->Password;\r
+  }\r
+  }\r
+  RefreshTitleAlways();\r
+  return res;\r
+}\r
+\r
+\r
+struct CThreadUpdate\r
+{\r
+  CMyComPtr<IFolderOperations> FolderOperations;\r
+  UString FolderPrefix;\r
+  UStringVector FileNames;\r
+  CRecordVector<const wchar_t *> FileNamePointers;\r
+  CProgressDialog ProgressDialog;\r
+  CMyComPtr<IFolderArchiveUpdateCallback> UpdateCallback;\r
+  CUpdateCallback100Imp *UpdateCallbackSpec;\r
+  HRESULT Result;\r
+  \r
+  void Process()\r
+  {\r
+    try\r
+    {\r
+      CProgressCloser closer(ProgressDialog);\r
+      Result = FolderOperations->CopyFrom(\r
+        FolderPrefix,\r
+        &FileNamePointers.Front(),\r
+        FileNamePointers.Size(),\r
+        UpdateCallback);\r
+    }\r
+    catch(...) { Result = E_FAIL; }\r
+  }\r
+  static THREAD_FUNC_DECL MyThreadFunction(void *param)\r
+  {\r
+    ((CThreadUpdate *)param)->Process();\r
+    return 0;\r
+  }\r
+};\r
+\r
+HRESULT CPanel::CopyFrom(const UString &folderPrefix, const UStringVector &filePaths,\r
+    bool showErrorMessages, UStringVector *messages)\r
+{\r
+  CMyComPtr<IFolderOperations> folderOperations;\r
+  _folder.QueryInterface(IID_IFolderOperations, &folderOperations);\r
+  HRESULT res;\r
+  if (!folderOperations)\r
+    res = E_NOINTERFACE;\r
+  else\r
+  {\r
+  CThreadUpdate updater;\r
+  updater.UpdateCallbackSpec = new CUpdateCallback100Imp;\r
+  updater.UpdateCallback = updater.UpdateCallbackSpec;\r
+\r
+  updater.UpdateCallbackSpec->ProgressDialog = &updater.ProgressDialog;\r
+\r
+  UString title = LangString(IDS_COPYING, 0x03020205);\r
+  UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000);\r
+\r
+  updater.ProgressDialog.MainWindow = GetParent();\r
+  updater.ProgressDialog.MainTitle = progressWindowTitle;\r
+  updater.ProgressDialog.MainAddTitle = title + UString(L" ");\r
+  \r
+  updater.UpdateCallbackSpec->Init(false, L"");\r
+  updater.FolderOperations = folderOperations;\r
+  updater.FolderPrefix = folderPrefix;\r
+  updater.FileNames.Reserve(filePaths.Size());\r
+  int i;\r
+  for(i = 0; i < filePaths.Size(); i++)\r
+    updater.FileNames.Add(filePaths[i]);\r
+  updater.FileNamePointers.Reserve(updater.FileNames.Size());\r
+  for(i = 0; i < updater.FileNames.Size(); i++)\r
+    updater.FileNamePointers.Add(updater.FileNames[i]);\r
+\r
+  NWindows::CThread thread;\r
+  RINOK(thread.Create(CThreadUpdate::MyThreadFunction, &updater));\r
+  updater.ProgressDialog.Create(title, thread, GetParent());\r
+  \r
+  if (messages != 0)\r
+    *messages = updater.ProgressDialog.Sync.Messages;\r
+\r
+  res = updater.Result;\r
+  }\r
+\r
+  if (res == E_NOINTERFACE)\r
+  {\r
+    UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);\r
+    if (showErrorMessages)\r
+      MessageBox(errorMessage);\r
+    else if (messages != 0)\r
+      messages->Add(errorMessage);\r
+    return E_ABORT;\r
+  }\r
+\r
+  RefreshTitleAlways();\r
+  return res;\r
+}\r
+\r
+void CPanel::CopyFromNoAsk(const UStringVector &filePaths)\r
+{\r
+  CDisableTimerProcessing disableTimerProcessing(*this);\r
+\r
+  CSelectedState srcSelState;\r
+  SaveSelectedState(srcSelState);\r
+\r
+  HRESULT result = CopyFrom(L"", filePaths, true, 0);\r
+\r
+  if (result != S_OK)\r
+  {\r
+    disableTimerProcessing.Restore();\r
+    // For Password:\r
+    SetFocusToList();\r
+    if (result != E_ABORT)\r
+      MessageBoxError(result);\r
+    return;\r
+  }\r
+\r
+  RefreshListCtrl(srcSelState);\r
+\r
+  disableTimerProcessing.Restore();\r
+  SetFocusToList();\r
+}\r
+\r
+void CPanel::CopyFromAsk(const UStringVector &filePaths)\r
+{\r
+  UString title = LangString(IDS_CONFIRM_FILE_COPY, 0x03020222);\r
+  UString message = LangString(IDS_WANT_TO_COPY_FILES, 0x03020223);\r
+  message += L"\n\'";\r
+  message += _currentFolderPrefix;\r
+  message += L"\' ?";\r
+  int res = ::MessageBoxW(*(this), message, title, MB_YESNOCANCEL | MB_ICONQUESTION);\r
+  if (res != IDYES)\r
+    return;\r
+\r
+  CopyFromNoAsk(filePaths);\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/PanelCrc.cpp b/CPP/7zip/UI/FileManager/PanelCrc.cpp
new file mode 100755 (executable)
index 0000000..cb67088
--- /dev/null
@@ -0,0 +1,342 @@
+// PanelSplitFile.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/7zCrc.h"\r
+#include "../../../../C/Sha256.h"\r
+\r
+#include "Common/IntToString.h"\r
+\r
+#include "Windows/FileFind.h"\r
+#include "Windows/FileIO.h"\r
+#include "Windows/FileName.h"\r
+\r
+#include "OverwriteDialogRes.h"\r
+\r
+#include "App.h"\r
+#include "FormatUtils.h"\r
+#include "LangUtils.h"\r
+\r
+#include "../Common/PropIDUtils.h"\r
+\r
+#include "resource.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+\r
+static const UInt32 kBufSize = (1 << 15);\r
+\r
+struct CDirEnumerator\r
+{\r
+  bool FlatMode;\r
+  UString BasePrefix;\r
+  UStringVector FileNames;\r
+\r
+  CObjectVector<NFind::CEnumeratorW> Enumerators;\r
+  UStringVector Prefixes;\r
+  int Index;\r
+  HRESULT GetNextFile(NFind::CFileInfoW &fileInfo, bool &filled, UString &fullPath);\r
+  void Init();\r
+  \r
+  CDirEnumerator(): FlatMode(false) {};\r
+};\r
+\r
+void CDirEnumerator::Init()\r
+{\r
+  Enumerators.Clear();\r
+  Prefixes.Clear();\r
+  Index = 0;\r
+}\r
+\r
+static HRESULT GetNormalizedError()\r
+{\r
+  HRESULT errorCode = GetLastError();\r
+  return (errorCode == 0) ? E_FAIL : errorCode;\r
+}\r
+\r
+HRESULT CDirEnumerator::GetNextFile(NFind::CFileInfoW &fileInfo, bool &filled, UString &resPath)\r
+{\r
+  filled = false;\r
+  for (;;)\r
+  {\r
+    if (Enumerators.IsEmpty())\r
+    {\r
+      if (Index >= FileNames.Size())\r
+        return S_OK;\r
+      const UString &path = FileNames[Index];\r
+      int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+      resPath.Empty();\r
+      if (pos >= 0)\r
+        resPath = path.Left(pos + 1);\r
+\r
+      #ifdef _WIN32\r
+      // it's for "c:" paths/\r
+      if (BasePrefix.IsEmpty() && path.Length() == 2 && path[1] == ':')\r
+      {\r
+        fileInfo.Name = path;\r
+        fileInfo.Attrib = FILE_ATTRIBUTE_DIRECTORY;\r
+        fileInfo.Size = 0;\r
+      }\r
+      else\r
+      #endif\r
+      if (!fileInfo.Find(BasePrefix + path))\r
+      {\r
+        WRes errorCode = GetNormalizedError();\r
+        resPath = path;\r
+        return errorCode;\r
+      }\r
+      Index++;\r
+      break;\r
+    }\r
+    bool found;\r
+    if (!Enumerators.Back().Next(fileInfo, found))\r
+    {\r
+      HRESULT errorCode = GetNormalizedError();\r
+      resPath = Prefixes.Back();\r
+      return errorCode;\r
+    }\r
+    if (found)\r
+    {\r
+      resPath = Prefixes.Back();\r
+      break;\r
+    }\r
+    Enumerators.DeleteBack();\r
+    Prefixes.DeleteBack();\r
+  }\r
+  resPath += fileInfo.Name;\r
+  if (!FlatMode && fileInfo.IsDir())\r
+  {\r
+    UString prefix = resPath + WCHAR_PATH_SEPARATOR;\r
+    Enumerators.Add(NFind::CEnumeratorW(BasePrefix + prefix + (UString)(wchar_t)NName::kAnyStringWildcard));\r
+    Prefixes.Add(prefix);\r
+  }\r
+  filled = true;\r
+  return S_OK;\r
+}\r
+\r
+static void ConvertByteToHex(unsigned value, wchar_t *s)\r
+{\r
+  for (int i = 0; i < 2; i++)\r
+  {\r
+    unsigned t = value & 0xF;\r
+    value >>= 4;\r
+    s[1 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10)));\r
+  }\r
+}\r
+\r
+class CThreadCrc: public CProgressThreadVirt\r
+{\r
+  UInt64 NumFilesScan;\r
+  UInt64 NumFiles;\r
+  UInt64 NumFolders;\r
+  UInt64 DataSize;\r
+  UInt32 DataCrcSum;\r
+  Byte Sha256Sum[SHA256_DIGEST_SIZE];\r
+  UInt32 DataNameCrcSum;\r
+\r
+  UString GetResultMessage() const;\r
+  HRESULT ProcessVirt();\r
+public:\r
+  CDirEnumerator Enumerator;\r
\r
+};\r
+\r
+UString CThreadCrc::GetResultMessage() const\r
+{\r
+  UString s;\r
+  wchar_t sz[32];\r
+  \r
+  s += LangString(IDS_FILES_COLON, 0x02000320);\r
+  s += L' ';\r
+  ConvertUInt64ToString(NumFiles, sz);\r
+  s += sz;\r
+  s += L'\n';\r
+  \r
+  s += LangString(IDS_FOLDERS_COLON, 0x02000321);\r
+  s += L' ';\r
+  ConvertUInt64ToString(NumFolders, sz);\r
+  s += sz;\r
+  s += L'\n';\r
+  \r
+  s += LangString(IDS_SIZE_COLON, 0x02000322);\r
+  s += L' ';\r
+  ConvertUInt64ToString(DataSize, sz);\r
+  s += MyFormatNew(IDS_FILE_SIZE, 0x02000982, sz);\r
+  s += L'\n';\r
+  \r
+  s += LangString(IDS_CHECKSUM_CRC_DATA, 0x03020721);\r
+  s += L' ';\r
+  ConvertUInt32ToHex(DataCrcSum, sz);\r
+  s += sz;\r
+  s += L'\n';\r
+  \r
+  s += LangString(IDS_CHECKSUM_CRC_DATA_NAMES, 0x03020722);\r
+  s += L' ';\r
+  ConvertUInt32ToHex(DataNameCrcSum, sz);\r
+  s += sz;\r
+  s += L'\n';\r
+  \r
+  if (NumFiles == 1 && NumFilesScan == 1)\r
+  {\r
+    s += L"SHA-256: ";\r
+    for (int i = 0; i < SHA256_DIGEST_SIZE; i++)\r
+    {\r
+      wchar_t s2[4];\r
+      ConvertByteToHex(Sha256Sum[i], s2);\r
+      s2[2] = 0;\r
+      s += s2;\r
+    }\r
+  }\r
+  return s;\r
+}\r
+\r
+HRESULT CThreadCrc::ProcessVirt()\r
+{\r
+  DataSize = NumFolders = NumFiles = NumFilesScan = DataCrcSum = DataNameCrcSum = 0;\r
+  memset(Sha256Sum, 0, SHA256_DIGEST_SIZE);\r
+  // ProgressDialog.WaitCreating();\r
+  \r
+  CMyBuffer bufferObject;\r
+  if (!bufferObject.Allocate(kBufSize))\r
+    return E_OUTOFMEMORY;\r
+  Byte *buffer = (Byte *)(void *)bufferObject;\r
+  \r
+  UInt64 totalSize = 0;\r
+  \r
+  Enumerator.Init();\r
+  \r
+  UString scanningStr = LangString(IDS_SCANNING, 0x03020800);\r
+  scanningStr += L' ';\r
+  \r
+  CProgressSync &sync = ProgressDialog.Sync;\r
+\r
+  for (;;)\r
+  {\r
+    NFind::CFileInfoW fileInfo;\r
+    bool filled;\r
+    UString resPath;\r
+    HRESULT errorCode = Enumerator.GetNextFile(fileInfo, filled, resPath);\r
+    if (errorCode != 0)\r
+    {\r
+      ErrorPath1 = resPath;\r
+      return errorCode;\r
+    }\r
+    if (!filled)\r
+      break;\r
+    if (!fileInfo.IsDir())\r
+    {\r
+      totalSize += fileInfo.Size;\r
+      NumFilesScan++;\r
+    }\r
+    sync.SetCurrentFileName(scanningStr + resPath);\r
+    sync.SetProgress(totalSize, 0);\r
+    RINOK(sync.SetPosAndCheckPaused(0));\r
+  }\r
+  sync.SetNumFilesTotal(NumFilesScan);\r
+  sync.SetProgress(totalSize, 0);\r
+  \r
+  Enumerator.Init();\r
+  \r
+  for (;;)\r
+  {\r
+    NFind::CFileInfoW fileInfo;\r
+    bool filled;\r
+    UString resPath;\r
+    HRESULT errorCode = Enumerator.GetNextFile(fileInfo, filled, resPath);\r
+    if (errorCode != 0)\r
+    {\r
+      ErrorPath1 = resPath;\r
+      return errorCode;\r
+    }\r
+    if (!filled)\r
+      break;\r
+    \r
+    UInt32 crc = CRC_INIT_VAL;\r
+    CSha256 sha256;\r
+    Sha256_Init(&sha256);\r
+    \r
+    if (fileInfo.IsDir())\r
+      NumFolders++;\r
+    else\r
+    {\r
+      NIO::CInFile inFile;\r
+      if (!inFile.Open(Enumerator.BasePrefix + resPath))\r
+      {\r
+        errorCode = GetNormalizedError();\r
+        ErrorPath1 = resPath;\r
+        return errorCode;\r
+      }\r
+      sync.SetCurrentFileName(resPath);\r
+      sync.SetNumFilesCur(NumFiles);\r
+      NumFiles++;\r
+      for (;;)\r
+      {\r
+        UInt32 processedSize;\r
+        if (!inFile.Read(buffer, kBufSize, processedSize))\r
+        {\r
+          errorCode = GetNormalizedError();\r
+          ErrorPath1 = resPath;\r
+          return errorCode;\r
+        }\r
+        if (processedSize == 0)\r
+          break;\r
+        crc = CrcUpdate(crc, buffer, processedSize);\r
+        if (NumFilesScan == 1)\r
+          Sha256_Update(&sha256, buffer, processedSize);\r
+        \r
+        DataSize += processedSize;\r
+        RINOK(sync.SetPosAndCheckPaused(DataSize));\r
+      }\r
+      DataCrcSum += CRC_GET_DIGEST(crc);\r
+      if (NumFilesScan == 1)\r
+        Sha256_Final(&sha256, Sha256Sum);\r
+    }\r
+    for (int i = 0; i < resPath.Length(); i++)\r
+    {\r
+      wchar_t c = resPath[i];\r
+      crc = CRC_UPDATE_BYTE(crc, ((Byte)(c & 0xFF)));\r
+      crc = CRC_UPDATE_BYTE(crc, ((Byte)((c >> 8) & 0xFF)));\r
+    }\r
+    DataNameCrcSum += CRC_GET_DIGEST(crc);\r
+    RINOK(sync.SetPosAndCheckPaused(DataSize));\r
+  }\r
+  sync.SetNumFilesCur(NumFiles);\r
+  OkMessage = GetResultMessage();\r
+  OkMessageTitle = LangString(IDS_CHECKSUM_INFORMATION, 0x03020720);\r
+  return S_OK;\r
+}\r
+\r
+void CApp::CalculateCrc()\r
+{\r
+  int srcPanelIndex = GetFocusedPanelIndex();\r
+  CPanel &srcPanel = Panels[srcPanelIndex];\r
+  if (!srcPanel.IsFsOrDrivesFolder())\r
+  {\r
+    srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);\r
+    return;\r
+  }\r
+  CRecordVector<UInt32> indices;\r
+  srcPanel.GetOperatedItemIndices(indices);\r
+  if (indices.IsEmpty())\r
+    return;\r
+\r
+  {\r
+  CThreadCrc t;\r
+  for (int i = 0; i < indices.Size(); i++)\r
+    t.Enumerator.FileNames.Add(srcPanel.GetItemRelPath(indices[i]));\r
+  t.Enumerator.BasePrefix = srcPanel.GetFsPath();\r
+  t.Enumerator.FlatMode = GetFlatMode();\r
+\r
+  t.ProgressDialog.ShowCompressionInfo = false;\r
+\r
+  UString title = LangString(IDS_CHECKSUM_CALCULATING, 0x03020710);\r
+\r
+  t.ProgressDialog.MainWindow = _window;\r
+  t.ProgressDialog.MainTitle = LangString(IDS_APP_TITLE, 0x03000000);\r
+  t.ProgressDialog.MainAddTitle = title + UString(L' ');\r
+\r
+  if (t.Create(title, _window) != S_OK)\r
+    return;\r
+  }\r
+  RefreshTitleAlways();\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/PanelDrag.cpp b/CPP/7zip/UI/FileManager/PanelDrag.cpp
new file mode 100755 (executable)
index 0000000..cae2746
--- /dev/null
@@ -0,0 +1,800 @@
+// PanelDrag.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#ifdef UNDER_CE\r
+#include <winuserm.h>\r
+#endif\r
+\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/Memory.h"\r
+#include "Windows/FileDir.h"\r
+#include "Windows/Shell.h"\r
+\r
+#include "../Common/ArchiveName.h"\r
+#include "../Common/CompressCall.h"\r
+\r
+#include "MessagesDialog.h"\r
+\r
+#include "App.h"\r
+#include "EnumFormatEtc.h"\r
+\r
+using namespace NWindows;\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+static wchar_t *kTempDirPrefix = L"7zE";\r
+static LPCTSTR kSvenZipSetFolderFormat = TEXT("7-Zip::SetTargetFolder");\r
+\r
+////////////////////////////////////////////////////////\r
+\r
+class CDataObject:\r
+  public IDataObject,\r
+  public CMyUnknownImp\r
+{\r
+private:\r
+  FORMATETC m_Etc;\r
+  UINT m_SetFolderFormat;\r
+\r
+public:\r
+  MY_UNKNOWN_IMP1_MT(IDataObject)\r
+\r
+  STDMETHODIMP GetData(LPFORMATETC pformatetcIn, LPSTGMEDIUM medium);\r
+  STDMETHODIMP GetDataHere(LPFORMATETC pformatetc, LPSTGMEDIUM medium);\r
+  STDMETHODIMP QueryGetData(LPFORMATETC pformatetc );\r
+\r
+  STDMETHODIMP GetCanonicalFormatEtc ( LPFORMATETC /* pformatetc */, LPFORMATETC pformatetcOut)\r
+    { pformatetcOut->ptd = NULL; return ResultFromScode(E_NOTIMPL); }\r
+\r
+  STDMETHODIMP SetData(LPFORMATETC etc, STGMEDIUM *medium, BOOL release);\r
+  STDMETHODIMP EnumFormatEtc(DWORD drection, LPENUMFORMATETC *enumFormatEtc);\r
+  \r
+  STDMETHODIMP DAdvise(FORMATETC * /* etc */, DWORD /* advf */, LPADVISESINK /* pAdvSink */, DWORD * /* pdwConnection */)\r
+    { return OLE_E_ADVISENOTSUPPORTED; }\r
+  STDMETHODIMP DUnadvise(DWORD /* dwConnection */) { return OLE_E_ADVISENOTSUPPORTED; }\r
+  STDMETHODIMP EnumDAdvise( LPENUMSTATDATA * /* ppenumAdvise */) { return OLE_E_ADVISENOTSUPPORTED; }\r
+\r
+  CDataObject();\r
+\r
+  NMemory::CGlobal hGlobal;\r
+  UString Path;\r
+};\r
+\r
+CDataObject::CDataObject()\r
+{\r
+  m_SetFolderFormat = RegisterClipboardFormat(kSvenZipSetFolderFormat);\r
+  m_Etc.cfFormat = CF_HDROP;\r
+  m_Etc.ptd = NULL;\r
+  m_Etc.dwAspect = DVASPECT_CONTENT;\r
+  m_Etc.lindex = -1;\r
+  m_Etc.tymed = TYMED_HGLOBAL;\r
+}\r
+\r
+STDMETHODIMP CDataObject::SetData(LPFORMATETC etc, STGMEDIUM *medium, BOOL /* release */)\r
+{\r
+  if (etc->cfFormat == m_SetFolderFormat && etc->tymed == TYMED_HGLOBAL &&\r
+      etc->dwAspect == DVASPECT_CONTENT && medium->tymed == TYMED_HGLOBAL)\r
+  {\r
+    Path.Empty();\r
+    if (medium->hGlobal == 0)\r
+      return S_OK;\r
+    size_t size = GlobalSize(medium->hGlobal) / sizeof(wchar_t);\r
+    const wchar_t *src = (const wchar_t *)GlobalLock(medium->hGlobal);\r
+    if (src != 0)\r
+    {\r
+      for (size_t i = 0; i < size; i++)\r
+      {\r
+        wchar_t c = src[i];\r
+        if (c == 0)\r
+          break;\r
+        Path += c;\r
+      }\r
+      GlobalUnlock(medium->hGlobal);\r
+      return S_OK;\r
+    }\r
+  }\r
+  return E_NOTIMPL;\r
+}\r
+\r
+static HGLOBAL DuplicateGlobalMem(HGLOBAL srcGlobal)\r
+{\r
+  SIZE_T size = GlobalSize(srcGlobal);\r
+  const void *src = GlobalLock(srcGlobal);\r
+  if (src == 0)\r
+    return 0;\r
+  HGLOBAL destGlobal = GlobalAlloc(GHND | GMEM_SHARE, size);\r
+  if (destGlobal != 0)\r
+  {\r
+    void *dest = GlobalLock(destGlobal);\r
+    if (dest == 0)\r
+    {\r
+      GlobalFree(destGlobal);\r
+      destGlobal = 0;\r
+    }\r
+    else\r
+    {\r
+      memcpy(dest, src, size);\r
+      GlobalUnlock(destGlobal);\r
+    }\r
+  }\r
+  GlobalUnlock(srcGlobal);\r
+  return destGlobal;\r
+}\r
+\r
+STDMETHODIMP CDataObject::GetData(LPFORMATETC etc, LPSTGMEDIUM medium)\r
+{\r
+  RINOK(QueryGetData(etc));\r
+  medium->tymed = m_Etc.tymed;\r
+  medium->pUnkForRelease = 0;\r
+  medium->hGlobal = DuplicateGlobalMem(hGlobal);\r
+  if (medium->hGlobal == 0)\r
+    return E_OUTOFMEMORY;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CDataObject::GetDataHere(LPFORMATETC /* etc */, LPSTGMEDIUM /* medium */)\r
+{\r
+  // Seems Windows doesn't call it, so we will not implement it.\r
+  return E_UNEXPECTED;\r
+}\r
+\r
+\r
+STDMETHODIMP CDataObject::QueryGetData(LPFORMATETC etc)\r
+{\r
+  if ((m_Etc.tymed & etc->tymed) &&\r
+       m_Etc.cfFormat == etc->cfFormat &&\r
+       m_Etc.dwAspect == etc->dwAspect)\r
+    return S_OK;\r
+  return DV_E_FORMATETC;\r
+}\r
+\r
+STDMETHODIMP CDataObject::EnumFormatEtc(DWORD direction, LPENUMFORMATETC FAR* enumFormatEtc)\r
+{\r
+  if (direction != DATADIR_GET)\r
+    return E_NOTIMPL;\r
+  return CreateEnumFormatEtc(1, &m_Etc, enumFormatEtc);\r
+}\r
+\r
+////////////////////////////////////////////////////////\r
+\r
+class CDropSource:\r
+  public IDropSource,\r
+  public CMyUnknownImp\r
+{\r
+  DWORD m_Effect;\r
+public:\r
+  MY_UNKNOWN_IMP1_MT(IDropSource)\r
+  STDMETHOD(QueryContinueDrag)(BOOL escapePressed, DWORD keyState);\r
+  STDMETHOD(GiveFeedback)(DWORD effect);\r
+\r
+\r
+  bool NeedExtract;\r
+  CPanel *Panel;\r
+  CRecordVector<UInt32> Indices;\r
+  UString Folder;\r
+  CDataObject *DataObjectSpec;\r
+  CMyComPtr<IDataObject> DataObject;\r
+  \r
+  bool NeedPostCopy;\r
+  HRESULT Result;\r
+  UStringVector Messages;\r
+\r
+  CDropSource(): NeedPostCopy(false), Panel(0), Result(S_OK), m_Effect(DROPEFFECT_NONE) {}\r
+};\r
+\r
+STDMETHODIMP CDropSource::QueryContinueDrag(BOOL escapePressed, DWORD keyState)\r
+{\r
+  if (escapePressed == TRUE)\r
+    return DRAGDROP_S_CANCEL;\r
+  if ((keyState & MK_LBUTTON) == 0)\r
+  {\r
+    if (m_Effect == DROPEFFECT_NONE)\r
+      return DRAGDROP_S_CANCEL;\r
+    Result = S_OK;\r
+    bool needExtract = NeedExtract;\r
+    // MoveMode = (((keyState & MK_SHIFT) != 0) && MoveIsAllowed);\r
+    if (!DataObjectSpec->Path.IsEmpty())\r
+    {\r
+      needExtract = false;\r
+      NeedPostCopy = true;\r
+    }\r
+    if (needExtract)\r
+    {\r
+      Result = Panel->CopyTo(Indices, Folder,\r
+          false, // moveMode,\r
+          false, // showMessages\r
+          &Messages);\r
+      if (Result != S_OK || !Messages.IsEmpty())\r
+        return DRAGDROP_S_CANCEL;\r
+    }\r
+    return DRAGDROP_S_DROP;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CDropSource::GiveFeedback(DWORD effect)\r
+{\r
+  m_Effect = effect;\r
+  return DRAGDROP_S_USEDEFAULTCURSORS;\r
+}\r
+\r
+static bool CopyNamesToHGlobal(NMemory::CGlobal &hgDrop, const UStringVector &names)\r
+{\r
+  size_t totalLength = 1;\r
+\r
+  #ifndef _UNICODE\r
+  if (!g_IsNT)\r
+  {\r
+    AStringVector namesA;\r
+    int i;\r
+    for (i = 0; i < names.Size(); i++)\r
+      namesA.Add(GetSystemString(names[i]));\r
+    for (i = 0; i < names.Size(); i++)\r
+      totalLength += namesA[i].Length() + 1;\r
+    \r
+    if (!hgDrop.Alloc(GHND | GMEM_SHARE, totalLength * sizeof(CHAR) + sizeof(DROPFILES)))\r
+      return false;\r
+    \r
+    NMemory::CGlobalLock dropLock(hgDrop);\r
+    DROPFILES* dropFiles = (DROPFILES*)dropLock.GetPointer();\r
+    if (dropFiles == 0)\r
+      return false;\r
+    dropFiles->fNC = FALSE;\r
+    dropFiles->pt.x = 0;\r
+    dropFiles->pt.y = 0;\r
+    dropFiles->pFiles = sizeof(DROPFILES);\r
+    dropFiles->fWide = FALSE;\r
+    CHAR *p = (CHAR *)((BYTE *)dropFiles + sizeof(DROPFILES));\r
+    for (i = 0; i < names.Size(); i++)\r
+    {\r
+      const AString &s = namesA[i];\r
+      int fullLength = s.Length() + 1;\r
+      MyStringCopy(p, (const char *)s);\r
+      p += fullLength;\r
+      totalLength -= fullLength;\r
+    }\r
+    *p = 0;\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    int i;\r
+    for (i = 0; i < names.Size(); i++)\r
+      totalLength += names[i].Length() + 1;\r
+    \r
+    if (!hgDrop.Alloc(GHND | GMEM_SHARE, totalLength * sizeof(WCHAR) + sizeof(DROPFILES)))\r
+      return false;\r
+    \r
+    NMemory::CGlobalLock dropLock(hgDrop);\r
+    DROPFILES* dropFiles = (DROPFILES*)dropLock.GetPointer();\r
+    if (dropFiles == 0)\r
+      return false;\r
+    dropFiles->fNC = FALSE;\r
+    dropFiles->pt.x = 0;\r
+    dropFiles->pt.y = 0;\r
+    dropFiles->pFiles = sizeof(DROPFILES);\r
+    dropFiles->fWide = TRUE;\r
+    WCHAR *p = (WCHAR *)((BYTE *)dropFiles + sizeof(DROPFILES));\r
+    for (i = 0; i < names.Size(); i++)\r
+    {\r
+      const UString &s = names[i];\r
+      int fullLength = s.Length() + 1;\r
+      MyStringCopy(p, (const WCHAR *)s);\r
+      p += fullLength;\r
+      totalLength -= fullLength;\r
+    }\r
+    *p = 0;\r
+  }\r
+  return true;\r
+}\r
+\r
+void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */)\r
+{\r
+  CPanel::CDisableTimerProcessing disableTimerProcessing2(*this);\r
+  if (!DoesItSupportOperations())\r
+    return;\r
+  CRecordVector<UInt32> indices;\r
+  GetOperatedItemIndices(indices);\r
+  if (indices.Size() == 0)\r
+    return;\r
+\r
+  // CSelectedState selState;\r
+  // SaveSelectedState(selState);\r
+\r
+  UString dirPrefix;\r
+  NFile::NDirectory::CTempDirectoryW tempDirectory;\r
+\r
+  bool isFSFolder = IsFSFolder();\r
+  if (isFSFolder)\r
+    dirPrefix = _currentFolderPrefix;\r
+  else\r
+  {\r
+    tempDirectory.Create(kTempDirPrefix);\r
+    dirPrefix = tempDirectory.GetPath();\r
+    NFile::NName::NormalizeDirPathPrefix(dirPrefix);\r
+  }\r
+\r
+  CDataObject *dataObjectSpec = new CDataObject;\r
+  CMyComPtr<IDataObject> dataObject = dataObjectSpec;\r
+\r
+  {\r
+    UStringVector names;\r
+    for (int i = 0; i < indices.Size(); i++)\r
+    {\r
+      UInt32 index = indices[i];\r
+      UString s;\r
+      if (isFSFolder)\r
+        s = GetItemRelPath(index);\r
+      else\r
+        s = GetItemName(index);\r
+      names.Add(dirPrefix + s);\r
+    }\r
+    if (!CopyNamesToHGlobal(dataObjectSpec->hGlobal, names))\r
+      return;\r
+  }\r
+\r
+  CDropSource *dropSourceSpec = new CDropSource;\r
+  CMyComPtr<IDropSource> dropSource = dropSourceSpec;\r
+  dropSourceSpec->NeedExtract = !isFSFolder;\r
+  dropSourceSpec->Panel = this;\r
+  dropSourceSpec->Indices = indices;\r
+  dropSourceSpec->Folder = dirPrefix;\r
+  dropSourceSpec->DataObjectSpec = dataObjectSpec;\r
+  dropSourceSpec->DataObject = dataObjectSpec;\r
+\r
+  bool moveIsAllowed = isFSFolder;\r
+\r
+  DWORD effectsOK = DROPEFFECT_COPY;\r
+  if (moveIsAllowed)\r
+    effectsOK |= DROPEFFECT_MOVE;\r
+  DWORD effect;\r
+  _panelCallback->DragBegin();\r
+  HRESULT res = DoDragDrop(dataObject, dropSource, effectsOK, &effect);\r
+  _panelCallback->DragEnd();\r
+  bool canceled = (res == DRAGDROP_S_CANCEL);\r
+  if (res == DRAGDROP_S_DROP)\r
+  {\r
+    res = dropSourceSpec->Result;\r
+    if (dropSourceSpec->NeedPostCopy)\r
+      if (!dataObjectSpec->Path.IsEmpty())\r
+      {\r
+        NFile::NName::NormalizeDirPathPrefix(dataObjectSpec->Path);\r
+        res = CopyTo(indices, dataObjectSpec->Path,\r
+          (effect == DROPEFFECT_MOVE),// dropSourceSpec->MoveMode,\r
+          false, // showErrorMessages\r
+          &dropSourceSpec->Messages);\r
+      }\r
+    /*\r
+    if (effect == DROPEFFECT_MOVE)\r
+      RefreshListCtrl(selState);\r
+    */\r
+  }\r
+  else\r
+  {\r
+    if (res != DRAGDROP_S_CANCEL && res != S_OK)\r
+      MessageBoxError(res);\r
+    res = dropSourceSpec->Result;\r
+  }\r
+\r
+  if (!dropSourceSpec->Messages.IsEmpty())\r
+  {\r
+    CMessagesDialog messagesDialog;\r
+    messagesDialog.Messages = &dropSourceSpec->Messages;\r
+    messagesDialog.Create((*this));\r
+  }\r
+  if (res != S_OK && res != E_ABORT)\r
+    MessageBoxError(res);\r
+  if (res == S_OK && dropSourceSpec->Messages.IsEmpty() && !canceled)\r
+    KillSelection();\r
+}\r
+\r
+void CDropTarget::QueryGetData(IDataObject *dataObject)\r
+{\r
+  FORMATETC etc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };\r
+  m_DropIsAllowed = (dataObject->QueryGetData(&etc) == S_OK);\r
+\r
+}\r
+\r
+static void MySetDropHighlighted(HWND hWnd, int index, bool enable)\r
+{\r
+  LVITEM item;\r
+  item.mask = LVIF_STATE;\r
+  item.iItem = index;\r
+  item.iSubItem = 0;\r
+  item.state = enable ? LVIS_DROPHILITED : 0;\r
+  item.stateMask = LVIS_DROPHILITED;\r
+  item.pszText = 0;\r
+  ListView_SetItem(hWnd, &item);\r
+}\r
+\r
+void CDropTarget::RemoveSelection()\r
+{\r
+  if (m_SelectionIndex >= 0 && m_Panel != 0)\r
+    MySetDropHighlighted(m_Panel->_listView, m_SelectionIndex, false);\r
+  m_SelectionIndex = -1;\r
+}\r
+\r
+#ifdef UNDER_CE\r
+#define ChildWindowFromPointEx(hwndParent, pt, uFlags) ChildWindowFromPoint(hwndParent, pt)\r
+#endif\r
+\r
+void CDropTarget::PositionCursor(POINTL ptl)\r
+{\r
+  m_SubFolderIndex = -1;\r
+  POINT pt;\r
+  pt.x = ptl.x;\r
+  pt.y = ptl.y;\r
+\r
+  RemoveSelection();\r
+  m_IsAppTarget = true;\r
+  m_Panel = NULL;\r
+\r
+  m_PanelDropIsAllowed = true;\r
+  if (!m_DropIsAllowed)\r
+    return;\r
+  {\r
+    POINT pt2 = pt;\r
+    App->_window.ScreenToClient(&pt2);\r
+    for (int i = 0; i < kNumPanelsMax; i++)\r
+      if (App->IsPanelVisible(i))\r
+        if (App->Panels[i].IsEnabled())\r
+          if (ChildWindowFromPointEx(App->_window, pt2,\r
+              CWP_SKIPINVISIBLE | CWP_SKIPDISABLED) == (HWND)App->Panels[i])\r
+          {\r
+            m_Panel = &App->Panels[i];\r
+            m_IsAppTarget = false;\r
+            if (i == SrcPanelIndex)\r
+            {\r
+              m_PanelDropIsAllowed = false;\r
+              return;\r
+            }\r
+            break;\r
+          }\r
+    if (m_IsAppTarget)\r
+    {\r
+      if (TargetPanelIndex >= 0)\r
+        m_Panel = &App->Panels[TargetPanelIndex];\r
+      return;\r
+    }\r
+  }\r
+\r
+  /*\r
+  m_PanelDropIsAllowed = m_Panel->DoesItSupportOperations();\r
+  if (!m_PanelDropIsAllowed)\r
+    return;\r
+  */\r
+\r
+  if (!m_Panel->IsFsOrPureDrivesFolder())\r
+    return;\r
+\r
+  if (WindowFromPoint(pt) != (HWND)m_Panel->_listView)\r
+    return;\r
+\r
+  LVHITTESTINFO info;\r
+  m_Panel->_listView.ScreenToClient(&pt);\r
+  info.pt = pt;\r
+  int index = ListView_HitTest(m_Panel->_listView, &info);\r
+  if (index < 0)\r
+    return;\r
+  int realIndex = m_Panel->GetRealItemIndex(index);\r
+  if (realIndex == kParentIndex)\r
+    return;\r
+  if (!m_Panel->IsItemFolder(realIndex))\r
+    return;\r
+  m_SubFolderIndex = realIndex;\r
+  m_SubFolderName = m_Panel->GetItemName(m_SubFolderIndex);\r
+  MySetDropHighlighted(m_Panel->_listView, index, true);\r
+  m_SelectionIndex = index;\r
+}\r
+\r
+bool CDropTarget::IsFsFolderPath() const\r
+{\r
+  if (!m_IsAppTarget && m_Panel != 0)\r
+    return (m_Panel->IsFSFolder() || (m_Panel->IsFSDrivesFolder() && m_SelectionIndex >= 0));\r
+  return false;\r
+}\r
+\r
+static void ReadUnicodeStrings(const wchar_t *p, size_t size, UStringVector &names)\r
+{\r
+  names.Clear();\r
+  UString name;\r
+  for (;size > 0; size--)\r
+  {\r
+    wchar_t c = *p++;\r
+    if (c == 0)\r
+    {\r
+      if (name.IsEmpty())\r
+        break;\r
+      names.Add(name);\r
+      name.Empty();\r
+    }\r
+    else\r
+      name += c;\r
+  }\r
+}\r
+\r
+static void ReadAnsiStrings(const char *p, size_t size, UStringVector &names)\r
+{\r
+  names.Clear();\r
+  AString name;\r
+  for (;size > 0; size--)\r
+  {\r
+    char c = *p++;\r
+    if (c == 0)\r
+    {\r
+      if (name.IsEmpty())\r
+        break;\r
+      names.Add(GetUnicodeString(name));\r
+      name.Empty();\r
+    }\r
+    else\r
+      name += c;\r
+  }\r
+}\r
+\r
+static void GetNamesFromDataObject(IDataObject *dataObject, UStringVector &names)\r
+{\r
+  names.Clear();\r
+  FORMATETC etc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };\r
+  STGMEDIUM medium;\r
+  HRESULT res = dataObject->GetData(&etc, &medium);\r
+  if (res != S_OK)\r
+    return;\r
+  if (medium.tymed != TYMED_HGLOBAL)\r
+    return;\r
+  {\r
+    NMemory::CGlobal global;\r
+    global.Attach(medium.hGlobal);\r
+    size_t blockSize = GlobalSize(medium.hGlobal);\r
+    NMemory::CGlobalLock dropLock(medium.hGlobal);\r
+    const DROPFILES* dropFiles = (DROPFILES*)dropLock.GetPointer();\r
+    if (dropFiles == 0)\r
+      return;\r
+    if (blockSize < dropFiles->pFiles)\r
+      return;\r
+    size_t size = blockSize - dropFiles->pFiles;\r
+    const void *namesData = (const Byte *)dropFiles + dropFiles->pFiles;\r
+    if (dropFiles->fWide)\r
+      ReadUnicodeStrings((const wchar_t *)namesData, size / sizeof(wchar_t), names);\r
+    else\r
+      ReadAnsiStrings((const char *)namesData, size, names);\r
+  }\r
+}\r
+\r
+bool CDropTarget::IsItSameDrive() const\r
+{\r
+  if (m_Panel == 0)\r
+    return false;\r
+  if (!IsFsFolderPath())\r
+    return false;\r
+  UString drive;\r
+  if (m_Panel->IsFSFolder())\r
+  {\r
+    drive = m_Panel->GetDriveOrNetworkPrefix();\r
+    if (drive.IsEmpty())\r
+      return false;\r
+  }\r
+  else if (m_Panel->IsFSDrivesFolder() && m_SelectionIndex >= 0)\r
+    drive = m_SubFolderName + WCHAR_PATH_SEPARATOR;\r
+  else\r
+    return false;\r
+\r
+  if (m_SourcePaths.Size() == 0)\r
+    return false;\r
+  for (int i = 0; i < m_SourcePaths.Size(); i++)\r
+  {\r
+    const UString &path = m_SourcePaths[i];\r
+    if (drive.CompareNoCase(path.Left(drive.Length())) != 0)\r
+      return false;\r
+  }\r
+  return true;\r
+\r
+}\r
+\r
+DWORD CDropTarget::GetEffect(DWORD keyState, POINTL /* pt */, DWORD allowedEffect)\r
+{\r
+  if (!m_DropIsAllowed || !m_PanelDropIsAllowed)\r
+    return DROPEFFECT_NONE;\r
+\r
+  if (!IsFsFolderPath() || !m_SetPathIsOK)\r
+    allowedEffect &= ~DROPEFFECT_MOVE;\r
+\r
+  DWORD effect = 0;\r
+  if (keyState & MK_CONTROL)\r
+    effect = allowedEffect & DROPEFFECT_COPY;\r
+  else if (keyState & MK_SHIFT)\r
+    effect = allowedEffect & DROPEFFECT_MOVE;\r
+  if (effect == 0)\r
+  {\r
+    if (allowedEffect & DROPEFFECT_COPY)\r
+    effect = DROPEFFECT_COPY;\r
+    if (allowedEffect & DROPEFFECT_MOVE)\r
+    {\r
+      if (IsItSameDrive())\r
+        effect = DROPEFFECT_MOVE;\r
+    }\r
+  }\r
+  if (effect == 0)\r
+    return DROPEFFECT_NONE;\r
+  return effect;\r
+}\r
+\r
+UString CDropTarget::GetTargetPath() const\r
+{\r
+  if (!IsFsFolderPath())\r
+    return UString();\r
+  UString path = m_Panel->_currentFolderPrefix;\r
+  if (m_Panel->IsFSDrivesFolder())\r
+    path.Empty();\r
+  if (m_SubFolderIndex >= 0 && !m_SubFolderName.IsEmpty())\r
+  {\r
+    path += m_SubFolderName;\r
+    path += WCHAR_PATH_SEPARATOR;\r
+  }\r
+  return path;\r
+}\r
+\r
+bool CDropTarget::SetPath(bool enablePath) const\r
+{\r
+  UINT setFolderFormat = RegisterClipboardFormat(kSvenZipSetFolderFormat);\r
+  \r
+  FORMATETC etc = { (CLIPFORMAT)setFolderFormat, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };\r
+  STGMEDIUM medium;\r
+  medium.tymed = etc.tymed;\r
+  medium.pUnkForRelease = 0;\r
+  UString path;\r
+  if (enablePath)\r
+    path = GetTargetPath();\r
+  size_t size = path.Length() + 1;\r
+  medium.hGlobal = GlobalAlloc(GHND | GMEM_SHARE, size * sizeof(wchar_t));\r
+  if (medium.hGlobal == 0)\r
+    return false;\r
+  wchar_t *dest = (wchar_t *)GlobalLock(medium.hGlobal);\r
+  if (dest == 0)\r
+  {\r
+    GlobalUnlock(medium.hGlobal);\r
+    return false;\r
+  }\r
+  MyStringCopy(dest, (const wchar_t *)path);\r
+  GlobalUnlock(medium.hGlobal);\r
+  bool res = m_DataObject->SetData(&etc, &medium, FALSE) == S_OK;\r
+  GlobalFree(medium.hGlobal);\r
+  return res;\r
+}\r
+\r
+bool CDropTarget::SetPath()\r
+{\r
+  m_SetPathIsOK = SetPath(m_DropIsAllowed && m_PanelDropIsAllowed && IsFsFolderPath());\r
+  return m_SetPathIsOK;\r
+}\r
+\r
+STDMETHODIMP CDropTarget::DragEnter(IDataObject * dataObject, DWORD keyState,\r
+      POINTL pt, DWORD *effect)\r
+{\r
+  GetNamesFromDataObject(dataObject, m_SourcePaths);\r
+  QueryGetData(dataObject);\r
+  m_DataObject = dataObject;\r
+  return DragOver(keyState, pt, effect);\r
+}\r
+\r
+\r
+STDMETHODIMP CDropTarget::DragOver(DWORD keyState, POINTL pt, DWORD *effect)\r
+{\r
+  PositionCursor(pt);\r
+  SetPath();\r
+  *effect = GetEffect(keyState, pt, *effect);\r
+  return S_OK;\r
+}\r
+\r
+\r
+STDMETHODIMP CDropTarget::DragLeave()\r
+{\r
+  RemoveSelection();\r
+  SetPath(false);\r
+  m_DataObject.Release();\r
+  return S_OK;\r
+}\r
+\r
+// We suppose that there was ::DragOver for same POINTL_pt before ::Drop\r
+// So SetPath() is same as in Drop.\r
+\r
+STDMETHODIMP CDropTarget::Drop(IDataObject *dataObject, DWORD keyState,\r
+      POINTL pt, DWORD * effect)\r
+{\r
+  QueryGetData(dataObject);\r
+  PositionCursor(pt);\r
+  m_DataObject = dataObject;\r
+  bool needDrop = true;\r
+  if (m_DropIsAllowed && m_PanelDropIsAllowed)\r
+    if (IsFsFolderPath())\r
+      needDrop = !SetPath();\r
+  *effect = GetEffect(keyState, pt, *effect);\r
+  if (m_DropIsAllowed && m_PanelDropIsAllowed)\r
+  {\r
+    if (needDrop)\r
+    {\r
+      UString path = GetTargetPath();\r
+      if (m_IsAppTarget && m_Panel)\r
+        if (m_Panel->IsFSFolder())\r
+          path = m_Panel->_currentFolderPrefix;\r
+      m_Panel->DropObject(dataObject, path);\r
+    }\r
+  }\r
+  RemoveSelection();\r
+  m_DataObject.Release();\r
+  return S_OK;\r
+}\r
+\r
+void CPanel::DropObject(IDataObject *dataObject, const UString &folderPath)\r
+{\r
+  UStringVector names;\r
+  GetNamesFromDataObject(dataObject, names);\r
+  CompressDropFiles(names, folderPath);\r
+}\r
+\r
+/*\r
+void CPanel::CompressDropFiles(HDROP dr)\r
+{\r
+  UStringVector fileNames;\r
+  {\r
+    NShell::CDrop drop(true);\r
+    drop.Attach(dr);\r
+    drop.QueryFileNames(fileNames);\r
+  }\r
+  CompressDropFiles(fileNamesUnicode);\r
+}\r
+*/\r
+\r
+static bool IsFolderInTemp(const UString &path)\r
+{\r
+  UString tempPath;\r
+  if (!NFile::NDirectory::MyGetTempPath(tempPath))\r
+    return false;\r
+  if (tempPath.IsEmpty())\r
+    return false;\r
+  return (tempPath.CompareNoCase(path.Left(tempPath.Length())) == 0);\r
+}\r
+\r
+static bool AreThereNamesFromTemp(const UStringVector &fileNames)\r
+{\r
+  UString tempPath;\r
+  if (!NFile::NDirectory::MyGetTempPath(tempPath))\r
+    return false;\r
+  if (tempPath.IsEmpty())\r
+    return false;\r
+  for (int i = 0; i < fileNames.Size(); i++)\r
+    if (tempPath.CompareNoCase(fileNames[i].Left(tempPath.Length())) == 0)\r
+      return true;\r
+  return false;\r
+}\r
+\r
+void CPanel::CompressDropFiles(const UStringVector &fileNames, const UString &folderPath)\r
+{\r
+  if (fileNames.Size() == 0)\r
+    return;\r
+  bool createNewArchive = true;\r
+  if (!IsFSFolder())\r
+    createNewArchive = !DoesItSupportOperations();\r
+\r
+  if (createNewArchive)\r
+  {\r
+    UString folderPath2 = folderPath;\r
+    if (folderPath2.IsEmpty())\r
+    {\r
+      NFile::NDirectory::GetOnlyDirPrefix(fileNames.Front(), folderPath2);\r
+      if (IsFolderInTemp(folderPath2))\r
+        folderPath2 = ROOT_FS_FOLDER;\r
+    }\r
+    const UString archiveName = CreateArchiveName(fileNames.Front(), (fileNames.Size() > 1), false);\r
+    CompressFiles(folderPath2, archiveName, L"", fileNames,\r
+      false, // email\r
+      true, // showDialog\r
+      AreThereNamesFromTemp(fileNames) // waitFinish\r
+      );\r
+  }\r
+  else\r
+    CopyFromAsk(fileNames);\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
new file mode 100755 (executable)
index 0000000..b03bb67
--- /dev/null
@@ -0,0 +1,613 @@
+// PanelFolderChange.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/StringConvert.h"\r
+#include "Common/Wildcard.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../../PropID.h"\r
+\r
+#ifdef UNDER_CE\r
+#include "FSFolder.h"\r
+#else\r
+#include "FSDrives.h"\r
+#endif\r
+#include "LangUtils.h"\r
+#include "ListViewDialog.h"\r
+#include "Panel.h"\r
+#include "RootFolder.h"\r
+#include "ViewSettings.h"\r
+\r
+#include "resource.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+using namespace NFind;\r
+\r
+void CPanel::SetToRootFolder()\r
+{\r
+  _folder.Release();\r
+  _library.Free();\r
+  CRootFolder *rootFolderSpec = new CRootFolder;\r
+  _folder = rootFolderSpec;\r
+  rootFolderSpec->Init();\r
+}\r
+\r
+HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bool &archiveIsOpened, bool &encrypted)\r
+{\r
+  archiveIsOpened = false;\r
+  encrypted = false;\r
+  CDisableTimerProcessing disableTimerProcessing1(*this);\r
+\r
+  if (_parentFolders.Size() > 0)\r
+  {\r
+    const UString &virtPath = _parentFolders.Back().VirtualPath;\r
+    if (fullPath.Left(virtPath.Length()) == virtPath)\r
+    {\r
+      for (;;)\r
+      {\r
+        CMyComPtr<IFolderFolder> newFolder;\r
+        HRESULT res = _folder->BindToParentFolder(&newFolder);\r
+        if (!newFolder || res != S_OK)\r
+          break;\r
+        _folder = newFolder;\r
+      }\r
+      UStringVector parts;\r
+      SplitPathToParts(fullPath.Mid(virtPath.Length()), parts);\r
+      for (int i = 0; i < parts.Size(); i++)\r
+      {\r
+        const UString &s = parts[i];\r
+        if ((i == 0 || i == parts.Size() - 1) && s.IsEmpty())\r
+          continue;\r
+        CMyComPtr<IFolderFolder> newFolder;\r
+        HRESULT res = _folder->BindToFolder(s, &newFolder);\r
+        if (!newFolder || res != S_OK)\r
+          break;\r
+        _folder = newFolder;\r
+      }\r
+      return S_OK;\r
+    }\r
+  }\r
+\r
+  CloseOpenFolders();\r
+  UString sysPath = fullPath;\r
+  CFileInfoW fileInfo;\r
+  UStringVector reducedParts;\r
+  while (!sysPath.IsEmpty())\r
+  {\r
+    if (fileInfo.Find(sysPath))\r
+      break;\r
+    int pos = sysPath.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+    if (pos < 0)\r
+      sysPath.Empty();\r
+    else\r
+    {\r
+      if (reducedParts.Size() > 0 || pos < sysPath.Length() - 1)\r
+        reducedParts.Add(sysPath.Mid(pos + 1));\r
+      sysPath = sysPath.Left(pos);\r
+    }\r
+  }\r
+  SetToRootFolder();\r
+  CMyComPtr<IFolderFolder> newFolder;\r
+  if (sysPath.IsEmpty())\r
+  {\r
+    if (_folder->BindToFolder(fullPath, &newFolder) == S_OK)\r
+      _folder = newFolder;\r
+  }\r
+  else if (fileInfo.IsDir())\r
+  {\r
+    NName::NormalizeDirPathPrefix(sysPath);\r
+    if (_folder->BindToFolder(sysPath, &newFolder) == S_OK)\r
+      _folder = newFolder;\r
+  }\r
+  else\r
+  {\r
+    UString dirPrefix;\r
+    if (!NDirectory::GetOnlyDirPrefix(sysPath, dirPrefix))\r
+      dirPrefix.Empty();\r
+    if (_folder->BindToFolder(dirPrefix, &newFolder) == S_OK)\r
+    {\r
+      _folder = newFolder;\r
+      LoadFullPath();\r
+      UString fileName;\r
+      if (NDirectory::GetOnlyName(sysPath, fileName))\r
+      {\r
+        HRESULT res = OpenItemAsArchive(fileName, arcFormat, encrypted);\r
+        if (res != S_FALSE)\r
+        {\r
+          RINOK(res);\r
+        }\r
+        /*\r
+        if (res == E_ABORT)\r
+          return res;\r
+        */\r
+        if (res == S_OK)\r
+        {\r
+          archiveIsOpened = true;\r
+          for (int i = reducedParts.Size() - 1; i >= 0; i--)\r
+          {\r
+            CMyComPtr<IFolderFolder> newFolder;\r
+            _folder->BindToFolder(reducedParts[i], &newFolder);\r
+            if (!newFolder)\r
+              break;\r
+            _folder = newFolder;\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CPanel::BindToPathAndRefresh(const UString &path)\r
+{\r
+  CDisableTimerProcessing disableTimerProcessing1(*this);\r
+  bool archiveIsOpened, encrypted;\r
+  RINOK(BindToPath(path, UString(), archiveIsOpened, encrypted));\r
+  RefreshListCtrl(UString(), -1, true, UStringVector());\r
+  return S_OK;\r
+}\r
+\r
+void CPanel::SetBookmark(int index)\r
+{\r
+  _appState->FastFolders.SetString(index, _currentFolderPrefix);\r
+}\r
+\r
+void CPanel::OpenBookmark(int index)\r
+{\r
+  BindToPathAndRefresh(_appState->FastFolders.GetString(index));\r
+}\r
+\r
+UString GetFolderPath(IFolderFolder *folder)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  if (folder->GetFolderProperty(kpidPath, &prop) == S_OK)\r
+    if (prop.vt == VT_BSTR)\r
+      return (wchar_t *)prop.bstrVal;\r
+  return UString();\r
+}\r
+\r
+void CPanel::LoadFullPath()\r
+{\r
+  _currentFolderPrefix.Empty();\r
+  for (int i = 0; i < _parentFolders.Size(); i++)\r
+  {\r
+    const CFolderLink &folderLink = _parentFolders[i];\r
+    _currentFolderPrefix += GetFolderPath(folderLink.ParentFolder);\r
+    _currentFolderPrefix += folderLink.ItemName;\r
+    _currentFolderPrefix += WCHAR_PATH_SEPARATOR;\r
+  }\r
+  if (_folder)\r
+    _currentFolderPrefix += GetFolderPath(_folder);\r
+}\r
+\r
+static int GetRealIconIndex(LPCWSTR path, DWORD attributes)\r
+{\r
+  int index = -1;\r
+  if (GetRealIconIndex(path, attributes, index) != 0)\r
+    return index;\r
+  return -1;\r
+}\r
+\r
+void CPanel::LoadFullPathAndShow()\r
+{\r
+  LoadFullPath();\r
+  _appState->FolderHistory.AddString(_currentFolderPrefix);\r
+\r
+  _headerComboBox.SetText(_currentFolderPrefix);\r
+\r
+  #ifndef UNDER_CE\r
+  COMBOBOXEXITEM item;\r
+  item.mask = 0;\r
+\r
+  UString path = _currentFolderPrefix;\r
+  if (path.Length() >\r
+      #ifdef _WIN32\r
+      3\r
+      #else\r
+      1\r
+      #endif\r
+      && path[path.Length() - 1] == WCHAR_PATH_SEPARATOR)\r
+    path.Delete(path.Length() - 1);\r
+\r
+  CFileInfoW info;\r
+  DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;\r
+  if (info.Find(path))\r
+    attrib = info.Attrib;\r
+  \r
+  item.iImage = GetRealIconIndex(path, attrib);\r
+\r
+  if (item.iImage >= 0)\r
+  {\r
+    item.iSelectedImage = item.iImage;\r
+    item.mask |= (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE);\r
+  }\r
+  item.iItem = -1;\r
+  _headerComboBox.SetItem(&item);\r
+  #endif\r
+\r
+  RefreshTitle();\r
+}\r
+\r
+#ifndef UNDER_CE\r
+LRESULT CPanel::OnNotifyComboBoxEnter(const UString &s)\r
+{\r
+  if (BindToPathAndRefresh(GetUnicodeString(s)) == S_OK)\r
+  {\r
+    PostMessage(kSetFocusToListView);\r
+    return TRUE;\r
+  }\r
+  return FALSE;\r
+}\r
+\r
+bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDITW info, LRESULT &result)\r
+{\r
+  if (info->iWhy == CBENF_ESCAPE)\r
+  {\r
+    _headerComboBox.SetText(_currentFolderPrefix);\r
+    PostMessage(kSetFocusToListView);\r
+    result = FALSE;\r
+    return true;\r
+  }\r
+\r
+  /*\r
+  if (info->iWhy == CBENF_DROPDOWN)\r
+  {\r
+    result = FALSE;\r
+    return true;\r
+  }\r
+  */\r
+\r
+  if (info->iWhy == CBENF_RETURN)\r
+  {\r
+    // When we use Edit control and press Enter.\r
+    UString s;\r
+    _headerComboBox.GetText(s);\r
+    result = OnNotifyComboBoxEnter(s);\r
+    return true;\r
+  }\r
+  return false;\r
+}\r
+#endif\r
+\r
+#ifndef _UNICODE\r
+bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info, LRESULT &result)\r
+{\r
+  if (info->iWhy == CBENF_ESCAPE)\r
+  {\r
+    _headerComboBox.SetText(_currentFolderPrefix);\r
+    PostMessage(kSetFocusToListView);\r
+    result = FALSE;\r
+    return true;\r
+  }\r
+  /*\r
+  if (info->iWhy == CBENF_DROPDOWN)\r
+  {\r
+    result = FALSE;\r
+    return true;\r
+  }\r
+  */\r
+\r
+  if (info->iWhy == CBENF_RETURN)\r
+  {\r
+    UString s;\r
+    _headerComboBox.GetText(s);\r
+    // GetUnicodeString(info->szText)\r
+    result = OnNotifyComboBoxEnter(s);\r
+    return true;\r
+  }\r
+  return false;\r
+}\r
+#endif\r
+\r
+void CPanel::AddComboBoxItem(const UString &name, int iconIndex, int indent, bool addToList)\r
+{\r
+  #ifdef UNDER_CE\r
+\r
+  UString s;\r
+  iconIndex = iconIndex;\r
+  for (int i = 0; i < indent; i++)\r
+    s += L"  ";\r
+  _headerComboBox.AddString(s + name);\r
+  \r
+  #else\r
+  \r
+  COMBOBOXEXITEMW item;\r
+  item.mask = CBEIF_TEXT | CBEIF_INDENT;\r
+  item.iSelectedImage = item.iImage = iconIndex;\r
+  if (iconIndex >= 0)\r
+    item.mask |= (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE);\r
+  item.iItem = -1;\r
+  item.iIndent = indent;\r
+  item.pszText = (LPWSTR)(LPCWSTR)name;\r
+  _headerComboBox.InsertItem(&item);\r
+  \r
+  #endif\r
+\r
+  if (addToList)\r
+    ComboBoxPaths.Add(name);\r
+}\r
+\r
+extern UString RootFolder_GetName_Computer(int &iconIndex);\r
+extern UString RootFolder_GetName_Network(int &iconIndex);\r
+extern UString RootFolder_GetName_Documents(int &iconIndex);\r
+\r
+bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result)\r
+{\r
+  result = FALSE;\r
+  switch(code)\r
+  {\r
+    case CBN_DROPDOWN:\r
+    {\r
+      ComboBoxPaths.Clear();\r
+      _headerComboBox.ResetContent();\r
+      \r
+      int i;\r
+      UStringVector pathParts;\r
+      \r
+      SplitPathToParts(_currentFolderPrefix, pathParts);\r
+      UString sumPass;\r
+      if (!pathParts.IsEmpty())\r
+        pathParts.DeleteBack();\r
+      for (i = 0; i < pathParts.Size(); i++)\r
+      {\r
+        UString name = pathParts[i];\r
+        sumPass += name;\r
+        sumPass += WCHAR_PATH_SEPARATOR;\r
+        CFileInfoW info;\r
+        DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;\r
+        if (info.Find(sumPass))\r
+          attrib = info.Attrib;\r
+        AddComboBoxItem(name.IsEmpty() ? L"\\" : name, GetRealIconIndex(sumPass, attrib), i, false);\r
+        ComboBoxPaths.Add(sumPass);\r
+      }\r
+\r
+      #ifndef UNDER_CE\r
+\r
+      int iconIndex;\r
+      UString name;\r
+      name = RootFolder_GetName_Documents(iconIndex);\r
+      AddComboBoxItem(name, iconIndex, 0, true);\r
+\r
+      name = RootFolder_GetName_Computer(iconIndex);\r
+      AddComboBoxItem(name, iconIndex, 0, true);\r
+        \r
+      UStringVector driveStrings;\r
+      MyGetLogicalDriveStrings(driveStrings);\r
+      for (i = 0; i < driveStrings.Size(); i++)\r
+      {\r
+        UString s = driveStrings[i];\r
+        ComboBoxPaths.Add(s);\r
+        int iconIndex = GetRealIconIndex(s, 0);\r
+        if (s.Length() > 0 && s[s.Length() - 1] == WCHAR_PATH_SEPARATOR)\r
+          s.Delete(s.Length() - 1);\r
+        AddComboBoxItem(s, iconIndex, 1, false);\r
+      }\r
+\r
+      name = RootFolder_GetName_Network(iconIndex);\r
+      AddComboBoxItem(name, iconIndex, 0, true);\r
+\r
+      #endif\r
+    \r
+      return false;\r
+    }\r
+\r
+    case CBN_SELENDOK:\r
+    {\r
+      code = code;\r
+      int index = _headerComboBox.GetCurSel();\r
+      if (index >= 0)\r
+      {\r
+        UString pass = ComboBoxPaths[index];\r
+        _headerComboBox.SetCurSel(-1);\r
+        // _headerComboBox.SetText(pass); // it's fix for seclecting by mouse.\r
+        if (BindToPathAndRefresh(pass) == S_OK)\r
+        {\r
+          PostMessage(kSetFocusToListView);\r
+          #ifdef UNDER_CE\r
+          PostMessage(kRefreshHeaderComboBox);\r
+          #endif\r
+\r
+          return true;\r
+        }\r
+      }\r
+      return false;\r
+    }\r
+    /*\r
+    case CBN_CLOSEUP:\r
+    {\r
+      LoadFullPathAndShow();\r
+      true;\r
+\r
+    }\r
+    case CBN_SELCHANGE:\r
+    {\r
+      // LoadFullPathAndShow();\r
+      return true;\r
+    }\r
+    */\r
+  }\r
+  return false;\r
+}\r
+\r
+bool CPanel::OnNotifyComboBox(LPNMHDR header, LRESULT &result)\r
+{\r
+  #ifndef UNDER_CE\r
+  switch(header->code)\r
+  {\r
+    case CBEN_BEGINEDIT:\r
+    {\r
+      _lastFocusedIsList = false;\r
+      _panelCallback->PanelWasFocused();\r
+      break;\r
+    }\r
+    #ifndef _UNICODE\r
+    case CBEN_ENDEDIT:\r
+    {\r
+      return OnNotifyComboBoxEndEdit((PNMCBEENDEDIT)header, result);\r
+    }\r
+    #endif\r
+    case CBEN_ENDEDITW:\r
+    {\r
+      return OnNotifyComboBoxEndEdit((PNMCBEENDEDITW)header, result);\r
+    }\r
+  }\r
+  #endif\r
+  return false;\r
+}\r
+\r
+\r
+void CPanel::FoldersHistory()\r
+{\r
+  CListViewDialog listViewDialog;\r
+  listViewDialog.DeleteIsAllowed = true;\r
+  listViewDialog.Title = LangString(IDS_FOLDERS_HISTORY, 0x03020260);\r
+  _appState->FolderHistory.GetList(listViewDialog.Strings);\r
+  if (listViewDialog.Create(GetParent()) == IDCANCEL)\r
+    return;\r
+  UString selectString;\r
+  if (listViewDialog.StringsWereChanged)\r
+  {\r
+    _appState->FolderHistory.RemoveAll();\r
+    for (int i = listViewDialog.Strings.Size() - 1; i >= 0; i--)\r
+      _appState->FolderHistory.AddString(listViewDialog.Strings[i]);\r
+    if (listViewDialog.FocusedItemIndex >= 0)\r
+      selectString = listViewDialog.Strings[listViewDialog.FocusedItemIndex];\r
+  }\r
+  else\r
+  {\r
+    if (listViewDialog.FocusedItemIndex >= 0)\r
+      selectString = listViewDialog.Strings[listViewDialog.FocusedItemIndex];\r
+  }\r
+  if (listViewDialog.FocusedItemIndex >= 0)\r
+    BindToPathAndRefresh(selectString);\r
+}\r
+\r
+void CPanel::OpenParentFolder()\r
+{\r
+  LoadFullPath(); // Maybe we don't need it ??\r
+  UString focucedName;\r
+  if (!_currentFolderPrefix.IsEmpty() &&\r
+      _currentFolderPrefix.Back() == WCHAR_PATH_SEPARATOR)\r
+  {\r
+    focucedName = _currentFolderPrefix;\r
+    focucedName.DeleteBack();\r
+    if (focucedName != L"\\\\.")\r
+    {\r
+      int pos = focucedName.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+      if (pos >= 0)\r
+        focucedName = focucedName.Mid(pos + 1);\r
+    }\r
+  }\r
+\r
+  CDisableTimerProcessing disableTimerProcessing1(*this);\r
+  CMyComPtr<IFolderFolder> newFolder;\r
+  _folder->BindToParentFolder(&newFolder);\r
+  if (newFolder)\r
+    _folder = newFolder;\r
+  else\r
+  {\r
+    if (_parentFolders.IsEmpty())\r
+    {\r
+      SetToRootFolder();\r
+      if (focucedName.IsEmpty())\r
+        focucedName = GetItemName(0);\r
+    }\r
+    else\r
+    {\r
+      _folder.Release();\r
+      _library.Free();\r
+      CFolderLink &link = _parentFolders.Back();\r
+      _folder = link.ParentFolder;\r
+      _library.Attach(link.Library.Detach());\r
+      focucedName = link.ItemName;\r
+      if (_parentFolders.Size() > 1)\r
+        OpenParentArchiveFolder();\r
+      _parentFolders.DeleteBack();\r
+      if (_parentFolders.IsEmpty())\r
+        _flatMode = _flatModeForDisk;\r
+    }\r
+  }\r
+\r
+  UStringVector selectedItems;\r
+  /*\r
+  if (!focucedName.IsEmpty())\r
+    selectedItems.Add(focucedName);\r
+  */\r
+  LoadFullPath();\r
+  // ::SetCurrentDirectory(::_currentFolderPrefix);\r
+  RefreshListCtrl(focucedName, -1, true, selectedItems);\r
+  _listView.EnsureVisible(_listView.GetFocusedItem(), false);\r
+  RefreshStatusBar();\r
+}\r
+\r
+void CPanel::CloseOpenFolders()\r
+{\r
+  while (_parentFolders.Size() > 0)\r
+  {\r
+    _folder.Release();\r
+    _library.Free();\r
+    _folder = _parentFolders.Back().ParentFolder;\r
+    _library.Attach(_parentFolders.Back().Library.Detach());\r
+    if (_parentFolders.Size() > 1)\r
+      OpenParentArchiveFolder();\r
+    _parentFolders.DeleteBack();\r
+  }\r
+  _flatMode = _flatModeForDisk;\r
+  _folder.Release();\r
+  _library.Free();\r
+}\r
+\r
+void CPanel::OpenRootFolder()\r
+{\r
+  CDisableTimerProcessing disableTimerProcessing1(*this);\r
+  _parentFolders.Clear();\r
+  SetToRootFolder();\r
+  RefreshListCtrl(UString(), -1, true, UStringVector());\r
+  // ::SetCurrentDirectory(::_currentFolderPrefix);\r
+  /*\r
+  BeforeChangeFolder();\r
+  _currentFolderPrefix.Empty();\r
+  AfterChangeFolder();\r
+  SetCurrentPathText();\r
+  RefreshListCtrl(UString(), 0, UStringVector());\r
+  _listView.EnsureVisible(_listView.GetFocusedItem(), false);\r
+  */\r
+}\r
+\r
+void CPanel::OpenDrivesFolder()\r
+{\r
+  CloseOpenFolders();\r
+  #ifdef UNDER_CE\r
+  NFsFolder::CFSFolder *folderSpec = new NFsFolder::CFSFolder;\r
+  _folder = folderSpec;\r
+  folderSpec->InitToRoot();\r
+  #else\r
+  CFSDrives *folderSpec = new CFSDrives;\r
+  _folder = folderSpec;\r
+  folderSpec->Init();\r
+  #endif\r
+  RefreshListCtrl();\r
+}\r
+\r
+void CPanel::OpenFolder(int index)\r
+{\r
+  if (index == kParentIndex)\r
+  {\r
+    OpenParentFolder();\r
+    return;\r
+  }\r
+  CMyComPtr<IFolderFolder> newFolder;\r
+  _folder->BindToFolder(index, &newFolder);\r
+  if (!newFolder)\r
+    return;\r
+  _folder = newFolder;\r
+  LoadFullPath();\r
+  // ::SetCurrentDirectory(::_currentFolderPrefix);\r
+  RefreshListCtrl();\r
+  UINT state = LVIS_SELECTED;\r
+  _listView.SetItemState(_listView.GetFocusedItem(), state, state);\r
+  _listView.EnsureVisible(_listView.GetFocusedItem(), false);\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
new file mode 100755 (executable)
index 0000000..0fa708f
--- /dev/null
@@ -0,0 +1,757 @@
+// PanelItemOpen.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/AutoPtr.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/Error.h"\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileFind.h"\r
+#include "Windows/Process.h"\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/Thread.h"\r
+\r
+#include "../Common/ExtractingFilePath.h"\r
+\r
+#include "App.h"\r
+\r
+#include "FileFolderPluginOpen.h"\r
+#include "FormatUtils.h"\r
+#include "LangUtils.h"\r
+#include "RegistryUtils.h"\r
+#include "UpdateCallback100.h"\r
+\r
+#include "resource.h"\r
+\r
+using namespace NWindows;\r
+using namespace NSynchronization;\r
+using namespace NFile;\r
+using namespace NDirectory;\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+static wchar_t *kTempDirPrefix = L"7zO";\r
+\r
+\r
+static bool IsNameVirus(const UString &name)\r
+{\r
+  return (name.Find(L"     ") >= 0);\r
+}\r
+\r
+struct CTmpProcessInfo: public CTempFileInfo\r
+{\r
+  HANDLE ProcessHandle;\r
+  HWND Window;\r
+  UString FullPathFolderPrefix;\r
+  bool UsePassword;\r
+  UString Password;\r
+  CTmpProcessInfo(): UsePassword(false) {}\r
+};\r
+\r
+class CTmpProcessInfoRelease\r
+{\r
+  CTmpProcessInfo *_tmpProcessInfo;\r
+public:\r
+  bool _needDelete;\r
+  CTmpProcessInfoRelease(CTmpProcessInfo &tmpProcessInfo):\r
+      _tmpProcessInfo(&tmpProcessInfo), _needDelete(true) {}\r
+  ~CTmpProcessInfoRelease()\r
+  {\r
+    if (_needDelete)\r
+      _tmpProcessInfo->DeleteDirAndFile();\r
+  }\r
+};\r
+\r
+HRESULT CPanel::OpenItemAsArchive(IInStream *inStream,\r
+    const CTempFileInfo &tempFileInfo,\r
+    const UString &virtualFilePath,\r
+    const UString &arcFormat,\r
+    bool &encrypted)\r
+{\r
+  encrypted = false;\r
+  CFolderLink folderLink;\r
+  (CTempFileInfo &)folderLink = tempFileInfo;\r
+  if (inStream)\r
+    folderLink.IsVirtual = true;\r
+  else\r
+  {\r
+    if (!folderLink.FileInfo.Find(folderLink.FilePath))\r
+      return ::GetLastError();\r
+    if (folderLink.FileInfo.IsDir())\r
+      return S_FALSE;\r
+    folderLink.IsVirtual = false;\r
+  }\r
+\r
+  folderLink.VirtualPath = virtualFilePath;\r
+\r
+  CMyComPtr<IFolderFolder> newFolder;\r
+\r
+  // _passwordIsDefined = false;\r
+  // _password.Empty();\r
+\r
+  NDLL::CLibrary library;\r
+\r
+  UString password;\r
+  RINOK(OpenFileFolderPlugin(inStream,\r
+      folderLink.FilePath.IsEmpty() ? virtualFilePath : folderLink.FilePath,\r
+      arcFormat,\r
+      &library, &newFolder, GetParent(), encrypted, password));\r
\r
+  folderLink.Password = password;\r
+  folderLink.UsePassword = encrypted;\r
+\r
+  folderLink.ParentFolder = _folder;\r
+  _parentFolders.Add(folderLink);\r
+  _parentFolders.Back().Library.Attach(_library.Detach());\r
+\r
+  _folder.Release();\r
+  _library.Free();\r
+  _folder = newFolder;\r
+  _library.Attach(library.Detach());\r
+\r
+  _flatMode = _flatModeForArc;\r
+\r
+  CMyComPtr<IGetFolderArcProps> getFolderArcProps;\r
+  _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps);\r
+  if (getFolderArcProps)\r
+  {\r
+    CMyComPtr<IFolderArcProps> arcProps;\r
+    getFolderArcProps->GetFolderArcProps(&arcProps);\r
+    if (arcProps)\r
+    {\r
+      UString s;\r
+      UInt32 numLevels;\r
+      if (arcProps->GetArcNumLevels(&numLevels) != S_OK)\r
+        numLevels = 0;\r
+      for (UInt32 level2 = 0; level2 < numLevels; level2++)\r
+      {\r
+        UInt32 level = numLevels - 1 - level2;\r
+        PROPID propIDs[] = { kpidError, kpidPath, kpidType } ;\r
+        UString values[3];\r
+        for (Int32 i = 0; i < 3; i++)\r
+        {\r
+          CMyComBSTR name;\r
+          NCOM::CPropVariant prop;\r
+          if (arcProps->GetArcProp(level, propIDs[i], &prop) != S_OK)\r
+            continue;\r
+          if (prop.vt != VT_EMPTY)\r
+            values[i] = (prop.vt == VT_BSTR) ? prop.bstrVal : L"?";\r
+        }\r
+        if (!values[0].IsEmpty())\r
+        {\r
+          if (!s.IsEmpty())\r
+            s += L"--------------------\n";\r
+          s += values[0]; s += L"\n\n[";\r
+          s += values[2]; s += L"] ";\r
+          s += values[1]; s += L"\n";\r
+        }\r
+      }\r
+      if (!s.IsEmpty())\r
+        MessageBox(s);\r
+    }\r
+  }\r
+\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CPanel::OpenItemAsArchive(const UString &name, const UString &arcFormat, bool &encrypted)\r
+{\r
+  CTempFileInfo tfi;\r
+  tfi.ItemName = name;\r
+  tfi.FolderPath = _currentFolderPrefix;\r
+  tfi.FilePath = _currentFolderPrefix + name;\r
+  return OpenItemAsArchive(NULL, tfi, _currentFolderPrefix + name, arcFormat, encrypted);\r
+}\r
+\r
+HRESULT CPanel::OpenItemAsArchive(int index)\r
+{\r
+  CDisableTimerProcessing disableTimerProcessing1(*this);\r
+  bool encrypted;\r
+  RINOK(OpenItemAsArchive(GetItemRelPath(index), UString(), encrypted));\r
+  RefreshListCtrl();\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CPanel::OpenParentArchiveFolder()\r
+{\r
+  CDisableTimerProcessing disableTimerProcessing1(*this);\r
+  if (_parentFolders.Size() < 2)\r
+    return S_OK;\r
+  const CFolderLink &folderLink = _parentFolders.Back();\r
+  NFind::CFileInfoW newFileInfo;\r
+  if (newFileInfo.Find(folderLink.FilePath))\r
+  {\r
+    if (folderLink.WasChanged(newFileInfo))\r
+    {\r
+      UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE,\r
+          0x03020280, folderLink.ItemName);\r
+      if (::MessageBoxW(HWND(*this), message, L"7-Zip", MB_OKCANCEL | MB_ICONQUESTION) == IDOK)\r
+      {\r
+        if (OnOpenItemChanged(folderLink.FolderPath, folderLink.ItemName,\r
+            folderLink.UsePassword, folderLink.Password) != S_OK)\r
+        {\r
+          ::MessageBoxW(HWND(*this), MyFormatNew(IDS_CANNOT_UPDATE_FILE,\r
+              0x03020281, folderLink.FilePath), L"7-Zip", MB_OK | MB_ICONSTOP);\r
+          return S_OK;\r
+        }\r
+      }\r
+    }\r
+  }\r
+  folderLink.DeleteDirAndFile();\r
+  return S_OK;\r
+}\r
+\r
+static const char *kStartExtensions =\r
+  #ifdef UNDER_CE\r
+  " cab"\r
+  #endif\r
+  " exe bat com"\r
+  " chm"\r
+  " msi doc xls ppt pps wps wpt wks xlr wdb vsd pub"\r
+\r
+  " docx docm dotx dotm xlsx xlsm xltx xltm xlsb xps"\r
+  " xlam pptx pptm potx potm ppam ppsx ppsm xsn"\r
+  " mpp"\r
+  " msg"\r
+  " dwf"\r
+\r
+  " flv swf"\r
+  \r
+  " odt ods"\r
+  " wb3"\r
+  " pdf"\r
+  " ";\r
+\r
+static bool FindExt(const char *p, const UString &name)\r
+{\r
+  int extPos = name.ReverseFind('.');\r
+  if (extPos < 0)\r
+    return false;\r
+  UString ext = name.Mid(extPos + 1);\r
+  ext.MakeLower();\r
+  AString ext2 = UnicodeStringToMultiByte(ext);\r
+  for (int i = 0; p[i] != 0;)\r
+  {\r
+    int j;\r
+    for (j = i; p[j] != ' '; j++);\r
+    if (ext2.Length() == j - i && memcmp(p + i, (const char *)ext2, ext2.Length()) == 0)\r
+      return true;\r
+    i = j + 1;\r
+  }\r
+  return false;\r
+}\r
+\r
+static bool DoItemAlwaysStart(const UString &name)\r
+{\r
+  return FindExt(kStartExtensions, name);\r
+}\r
+\r
+static UString GetQuotedString(const UString &s)\r
+{\r
+  return UString(L'\"') + s + UString(L'\"');\r
+}\r
+\r
+static HRESULT StartEditApplication(const UString &path, HWND window, CProcess &process)\r
+{\r
+  UString command;\r
+  ReadRegEditor(command);\r
+  if (command.IsEmpty())\r
+  {\r
+    #ifdef UNDER_CE\r
+    command = L"\\Windows\\";\r
+    #else\r
+    if (!MyGetWindowsDirectory(command))\r
+      return 0;\r
+    NFile::NName::NormalizeDirPathPrefix(command);\r
+    #endif\r
+    command += L"notepad.exe";\r
+  }\r
+\r
+  HRESULT res = process.Create(command, GetQuotedString(path), NULL);\r
+  if (res != SZ_OK)\r
+    ::MessageBoxW(window, LangString(IDS_CANNOT_START_EDITOR, 0x03020282), L"7-Zip", MB_OK  | MB_ICONSTOP);\r
+  return res;\r
+}\r
+\r
+void CApp::DiffFiles()\r
+{\r
+  const CPanel &panel = GetFocusedPanel();\r
+  \r
+  CRecordVector<UInt32> indices;\r
+  panel.GetSelectedItemsIndices(indices);\r
+\r
+  UString path1, path2;\r
+  if (indices.Size() == 2)\r
+  {\r
+    path1 = panel.GetItemFullPath(indices[0]);\r
+    path2 = panel.GetItemFullPath(indices[1]);\r
+  }\r
+  else if (indices.Size() == 1 && NumPanels >= 2)\r
+  {\r
+    const CPanel &destPanel = Panels[1 - LastFocusedPanel];\r
+    path1 = panel.GetItemFullPath(indices[0]);\r
+    const UString relPath = panel.GetItemRelPath(indices[0]);\r
+    CRecordVector<UInt32> indices2;\r
+    destPanel.GetSelectedItemsIndices(indices2);\r
+    if (indices2.Size() == 1)\r
+      path2 = destPanel.GetItemFullPath(indices2[0]);\r
+    else\r
+      path2 = destPanel._currentFolderPrefix + relPath;\r
+  }\r
+  else\r
+    return;\r
+\r
+  UString command;\r
+  ReadRegDiff(command);\r
+  if (command.IsEmpty())\r
+    return;\r
+\r
+  UString param = GetQuotedString(path1) + L' ' + GetQuotedString(path2);\r
+\r
+  HRESULT res = MyCreateProcess(command, param);\r
+  if (res == SZ_OK)\r
+    return;\r
+  ::MessageBoxW(_window, LangString(IDS_CANNOT_START_EDITOR, 0x03020282), L"7-Zip", MB_OK  | MB_ICONSTOP);\r
+}\r
+\r
+#ifndef _UNICODE\r
+typedef BOOL (WINAPI * ShellExecuteExWP)(LPSHELLEXECUTEINFOW lpExecInfo);\r
+#endif\r
+\r
+static HRESULT StartApplication(const UString &dir, const UString &path, HWND window, CProcess &process)\r
+{\r
+  UINT32 result;\r
+  #ifndef _UNICODE\r
+  if (g_IsNT)\r
+  {\r
+    SHELLEXECUTEINFOW execInfo;\r
+    execInfo.cbSize = sizeof(execInfo);\r
+    execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT;\r
+    execInfo.hwnd = NULL;\r
+    execInfo.lpVerb = NULL;\r
+    execInfo.lpFile = path;\r
+    execInfo.lpParameters = NULL;\r
+    execInfo.lpDirectory = dir.IsEmpty() ? NULL : (LPCWSTR)dir;\r
+    execInfo.nShow = SW_SHOWNORMAL;\r
+    execInfo.hProcess = 0;\r
+    ShellExecuteExWP shellExecuteExW = (ShellExecuteExWP)\r
+    ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "ShellExecuteExW");\r
+    if (shellExecuteExW == 0)\r
+      return 0;\r
+    shellExecuteExW(&execInfo);\r
+    result = (UINT32)(UINT_PTR)execInfo.hInstApp;\r
+    process.Attach(execInfo.hProcess);\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    SHELLEXECUTEINFO execInfo;\r
+    execInfo.cbSize = sizeof(execInfo);\r
+    execInfo.fMask = SEE_MASK_NOCLOSEPROCESS\r
+      #ifndef UNDER_CE\r
+      | SEE_MASK_FLAG_DDEWAIT\r
+      #endif\r
+      ;\r
+    execInfo.hwnd = NULL;\r
+    execInfo.lpVerb = NULL;\r
+    const CSysString sysPath = GetSystemString(path);\r
+    const CSysString sysDir = GetSystemString(dir);\r
+    execInfo.lpFile = sysPath;\r
+    execInfo.lpParameters = NULL;\r
+    execInfo.lpDirectory =\r
+    #ifdef UNDER_CE\r
+    NULL\r
+    #else\r
+    sysDir.IsEmpty() ? NULL : (LPCTSTR)sysDir\r
+    #endif\r
+    ;\r
+    execInfo.nShow = SW_SHOWNORMAL;\r
+    execInfo.hProcess = 0;\r
+    ::ShellExecuteEx(&execInfo);\r
+    result = (UINT32)(UINT_PTR)execInfo.hInstApp;\r
+    process.Attach(execInfo.hProcess);\r
+  }\r
+  if (result <= 32)\r
+  {\r
+    switch(result)\r
+    {\r
+      case SE_ERR_NOASSOC:\r
+        ::MessageBoxW(window,\r
+          NError::MyFormatMessageW(::GetLastError()),\r
+          // L"There is no application associated with the given file name extension",\r
+          L"7-Zip", MB_OK | MB_ICONSTOP);\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+static void StartApplicationDontWait(const UString &dir, const UString &path, HWND window)\r
+{\r
+  CProcess process;\r
+  StartApplication(dir, path, window, process);\r
+}\r
+\r
+void CPanel::EditItem(int index)\r
+{\r
+  if (!_parentFolders.IsEmpty())\r
+  {\r
+    OpenItemInArchive(index, false, true, true);\r
+    return;\r
+  }\r
+  CProcess process;\r
+  StartEditApplication(GetItemFullPath(index), (HWND)*this, process);\r
+}\r
+\r
+void CPanel::OpenFolderExternal(int index)\r
+{\r
+  UString fsPrefix = GetFsPath();\r
+  UString name;\r
+  if (index == kParentIndex)\r
+  {\r
+    int pos = fsPrefix.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+    if (pos >= 0 && pos == fsPrefix.Length() - 1)\r
+    {\r
+      UString s = fsPrefix.Left(pos);\r
+      pos = s.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+      if (pos >= 0)\r
+        fsPrefix = s.Left(pos + 1);\r
+    }\r
+    name = fsPrefix;\r
+  }\r
+  else\r
+    name = fsPrefix + GetItemRelPath(index) + WCHAR_PATH_SEPARATOR;\r
+  StartApplicationDontWait(fsPrefix, name, (HWND)*this);\r
+}\r
+\r
+void CPanel::OpenItem(int index, bool tryInternal, bool tryExternal)\r
+{\r
+  CDisableTimerProcessing disableTimerProcessing1(*this);\r
+  if (!_parentFolders.IsEmpty())\r
+  {\r
+    OpenItemInArchive(index, tryInternal, tryExternal, false);\r
+    return;\r
+  }\r
+  UString name = GetItemRelPath(index);\r
+  if (IsNameVirus(name))\r
+  {\r
+    MessageBoxErrorLang(IDS_VIRUS, 0x03020284);\r
+    return;\r
+  }\r
+  UString prefix = GetFsPath();\r
+  UString fullPath = prefix + name;\r
+  if (tryInternal)\r
+    if (!tryExternal || !DoItemAlwaysStart(name))\r
+    {\r
+      HRESULT res = OpenItemAsArchive(index);\r
+      if (res == S_OK || res == E_ABORT)\r
+        return;\r
+      if (res != S_FALSE)\r
+      {\r
+        MessageBoxError(res);\r
+        return;\r
+      }\r
+    }\r
+  if (tryExternal)\r
+  {\r
+    // SetCurrentDirectory opens HANDLE to folder!!!\r
+    // NDirectory::MySetCurrentDirectory(prefix);\r
+    StartApplicationDontWait(prefix, fullPath, (HWND)*this);\r
+  }\r
+}\r
+\r
+class CThreadCopyFrom: public CProgressThreadVirt\r
+{\r
+  HRESULT ProcessVirt();\r
+public:\r
+  UString PathPrefix;\r
+  UString Name;\r
+\r
+  CMyComPtr<IFolderOperations> FolderOperations;\r
+  CMyComPtr<IProgress> UpdateCallback;\r
+  CUpdateCallback100Imp *UpdateCallbackSpec;\r
+};\r
+  \r
+HRESULT CThreadCopyFrom::ProcessVirt()\r
+{\r
+  UStringVector fileNames;\r
+  CRecordVector<const wchar_t *> fileNamePointers;\r
+  fileNames.Add(Name);\r
+  fileNamePointers.Add(fileNames[0]);\r
+  return FolderOperations->CopyFrom(PathPrefix, &fileNamePointers.Front(), fileNamePointers.Size(), UpdateCallback);\r
+}\r
+      \r
+HRESULT CPanel::OnOpenItemChanged(const UString &folderPath, const UString &itemName,\r
+    bool usePassword, const UString &password)\r
+{\r
+  CMyComPtr<IFolderOperations> folderOperations;\r
+  if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)\r
+  {\r
+    MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);\r
+    return E_FAIL;\r
+  }\r
+\r
+  CThreadCopyFrom t;\r
+  t.UpdateCallbackSpec = new CUpdateCallback100Imp;\r
+  t.UpdateCallback = t.UpdateCallbackSpec;\r
+  t.UpdateCallbackSpec->ProgressDialog = &t.ProgressDialog;\r
+  t.Name = itemName;\r
+  t.PathPrefix = folderPath;\r
+  NName::NormalizeDirPathPrefix(t.PathPrefix);\r
+  t.FolderOperations = folderOperations;\r
+  t.UpdateCallbackSpec->Init(usePassword, password);\r
+  RINOK(t.Create(itemName, (HWND)*this));\r
+  return t.Result;\r
+}\r
+\r
+LRESULT CPanel::OnOpenItemChanged(LPARAM lParam)\r
+{\r
+  CTmpProcessInfo &tmpProcessInfo = *(CTmpProcessInfo *)lParam;\r
+  // LoadCurrentPath()\r
+  if (tmpProcessInfo.FullPathFolderPrefix != _currentFolderPrefix)\r
+    return 0;\r
+\r
+  CSelectedState state;\r
+  SaveSelectedState(state);\r
+\r
+  HRESULT result = OnOpenItemChanged(tmpProcessInfo.FolderPath, tmpProcessInfo.ItemName,\r
+      tmpProcessInfo.UsePassword, tmpProcessInfo.Password);\r
+  if (result != S_OK)\r
+    return 0;\r
+  RefreshListCtrl(state);\r
+  return 1;\r
+}\r
+\r
+/*\r
+class CTmpProcessInfoList\r
+{\r
+public:\r
+  CObjectVector<CTmpProcessInfo> _items;\r
+} g_TmpProcessInfoList;\r
+*/\r
+\r
+class CExitEventLauncher\r
+{\r
+public:\r
+  NWindows::NSynchronization::CManualResetEvent _exitEvent;\r
+  CExitEventLauncher()\r
+  {\r
+    if (_exitEvent.Create(false) != S_OK)\r
+      throw 9387173;\r
+  };\r
+  ~CExitEventLauncher() {  _exitEvent.Set(); }\r
+} g_ExitEventLauncher;\r
+\r
+static THREAD_FUNC_DECL MyThreadFunction(void *param)\r
+{\r
+  CMyAutoPtr<CTmpProcessInfo> tmpProcessInfoPtr((CTmpProcessInfo *)param);\r
+  const CTmpProcessInfo *tmpProcessInfo = tmpProcessInfoPtr.get();\r
+\r
+  HANDLE hProcess = tmpProcessInfo->ProcessHandle;\r
+  HANDLE events[2] = { g_ExitEventLauncher._exitEvent, hProcess};\r
+  DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);\r
+  ::CloseHandle(hProcess);\r
+  if (waitResult == WAIT_OBJECT_0 + 0)\r
+    return 0;\r
+  if (waitResult != WAIT_OBJECT_0 + 1)\r
+    return 1;\r
+  Sleep(200);\r
+  NFind::CFileInfoW newFileInfo;\r
+  if (newFileInfo.Find(tmpProcessInfo->FilePath))\r
+  {\r
+    if (tmpProcessInfo->WasChanged(newFileInfo))\r
+    {\r
+      UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE,\r
+          0x03020280, tmpProcessInfo->ItemName);\r
+      if (::MessageBoxW(g_HWND, message, L"7-Zip", MB_OKCANCEL | MB_ICONQUESTION) == IDOK)\r
+      {\r
+        if (SendMessage(tmpProcessInfo->Window, kOpenItemChanged, 0, (LONG_PTR)tmpProcessInfo) != 1)\r
+        {\r
+          ::MessageBoxW(g_HWND, MyFormatNew(IDS_CANNOT_UPDATE_FILE,\r
+              0x03020281, tmpProcessInfo->FilePath), L"7-Zip", MB_OK | MB_ICONSTOP);\r
+          return 0;\r
+        }\r
+      }\r
+    }\r
+  }\r
+  tmpProcessInfo->DeleteDirAndFile();\r
+  return 0;\r
+}\r
+\r
+void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bool editMode)\r
+{\r
+  const UString name = GetItemName(index);\r
+  if (IsNameVirus(name))\r
+  {\r
+    MessageBoxErrorLang(IDS_VIRUS, 0x03020284);\r
+    return;\r
+  }\r
+\r
+  CMyComPtr<IFolderOperations> folderOperations;\r
+  if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)\r
+  {\r
+    MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);\r
+    return;\r
+  }\r
+\r
+  bool tryAsArchive = tryInternal && (!tryExternal || !DoItemAlwaysStart(name));\r
+\r
+  UString fullVirtPath = _currentFolderPrefix + name;\r
+\r
+  NFile::NDirectory::CTempDirectoryW tempDirectory;\r
+  tempDirectory.Create(kTempDirPrefix);\r
+  UString tempDir = tempDirectory.GetPath();\r
+  UString tempDirNorm = tempDir;\r
+  NFile::NName::NormalizeDirPathPrefix(tempDirNorm);\r
+\r
+  UString tempFilePath = tempDirNorm + GetCorrectFsPath(name);\r
+\r
+  CTempFileInfo tempFileInfo;\r
+  tempFileInfo.ItemName = name;\r
+  tempFileInfo.FolderPath = tempDir;\r
+  tempFileInfo.FilePath = tempFilePath;\r
+  tempFileInfo.NeedDelete = true;\r
+\r
+  if (tryAsArchive)\r
+  {\r
+    CMyComPtr<IInArchiveGetStream> getStream;\r
+    _folder.QueryInterface(IID_IInArchiveGetStream, &getStream);\r
+    if (getStream)\r
+    {\r
+      CMyComPtr<ISequentialInStream> subSeqStream;\r
+      getStream->GetStream(index, &subSeqStream);\r
+      if (subSeqStream)\r
+      {\r
+        CMyComPtr<IInStream> subStream;\r
+        subSeqStream.QueryInterface(IID_IInStream, &subStream);\r
+        if (subStream)\r
+        {\r
+          bool encrypted;\r
+          if (OpenItemAsArchive(subStream, tempFileInfo, fullVirtPath, UString(), encrypted) == S_OK)\r
+          {\r
+            tempDirectory.DisableDeleting();\r
+            RefreshListCtrl();\r
+            return;\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+\r
+  CRecordVector<UInt32> indices;\r
+  indices.Add(index);\r
+\r
+  UStringVector messages;\r
+\r
+  bool usePassword = false;\r
+  UString password;\r
+  if (_parentFolders.Size() > 0)\r
+  {\r
+    const CFolderLink &fl = _parentFolders.Back();\r
+    usePassword = fl.UsePassword;\r
+    password = fl.Password;\r
+  }\r
+\r
+  HRESULT result = CopyTo(indices, tempDirNorm, false, true, &messages, usePassword, password);\r
+\r
+  if (_parentFolders.Size() > 0)\r
+  {\r
+    CFolderLink &fl = _parentFolders.Back();\r
+    fl.UsePassword = usePassword;\r
+    fl.Password = password;\r
+  }\r
+\r
+  if (!messages.IsEmpty())\r
+    return;\r
+  if (result != S_OK)\r
+  {\r
+    if (result != E_ABORT)\r
+      MessageBoxError(result);\r
+    return;\r
+  }\r
+\r
+\r
+  if (tryAsArchive)\r
+  {\r
+    bool encrypted;\r
+    if (OpenItemAsArchive(NULL, tempFileInfo, fullVirtPath, UString(), encrypted) == S_OK)\r
+    {\r
+      tempDirectory.DisableDeleting();\r
+      RefreshListCtrl();\r
+      return;\r
+    }\r
+  }\r
+\r
+  CMyAutoPtr<CTmpProcessInfo> tmpProcessInfoPtr(new CTmpProcessInfo());\r
+  CTmpProcessInfo *tmpProcessInfo = tmpProcessInfoPtr.get();\r
+  tmpProcessInfo->FolderPath = tempDir;\r
+  tmpProcessInfo->FilePath = tempFilePath;\r
+  tmpProcessInfo->NeedDelete = true;\r
+  tmpProcessInfo->UsePassword = usePassword;\r
+  tmpProcessInfo->Password = password;\r
+\r
+  if (!tmpProcessInfo->FileInfo.Find(tempFilePath))\r
+    return;\r
+\r
+  CTmpProcessInfoRelease tmpProcessInfoRelease(*tmpProcessInfo);\r
+\r
+  if (!tryExternal)\r
+    return;\r
+\r
+  CProcess process;\r
+  HRESULT res;\r
+  if (editMode)\r
+    res = StartEditApplication(tempFilePath, (HWND)*this, process);\r
+  else\r
+    res = StartApplication(tempDirNorm, tempFilePath, (HWND)*this, process);\r
+\r
+  if ((HANDLE)process == 0)\r
+    return;\r
+\r
+  tmpProcessInfo->Window = (HWND)(*this);\r
+  tmpProcessInfo->FullPathFolderPrefix = _currentFolderPrefix;\r
+  tmpProcessInfo->ItemName = name;\r
+  tmpProcessInfo->ProcessHandle = process.Detach();\r
+\r
+  NWindows::CThread thread;\r
+  if (thread.Create(MyThreadFunction, tmpProcessInfo) != S_OK)\r
+    throw 271824;\r
+  tempDirectory.DisableDeleting();\r
+  tmpProcessInfoPtr.release();\r
+  tmpProcessInfoRelease._needDelete = false;\r
+}\r
+\r
+/*\r
+static const UINT64 kTimeLimit = UINT64(10000000) * 3600 * 24;\r
+\r
+static bool CheckDeleteItem(UINT64 currentFileTime, UINT64 folderFileTime)\r
+{\r
+  return (currentFileTime - folderFileTime > kTimeLimit &&\r
+      folderFileTime - currentFileTime > kTimeLimit);\r
+}\r
+\r
+void DeleteOldTempFiles()\r
+{\r
+  UString tempPath;\r
+  if(!NFile::NDirectory::MyGetTempPath(tempPath))\r
+    throw 1;\r
+\r
+  UINT64 currentFileTime;\r
+  NTime::GetCurUtcFileTime(currentFileTime);\r
+  UString searchWildCard = tempPath + kTempDirPrefix + L"*.tmp";\r
+  searchWildCard += WCHAR(NName::kAnyStringWildcard);\r
+  NFind::CEnumeratorW enumerator(searchWildCard);\r
+  NFind::CFileInfoW fileInfo;\r
+  while(enumerator.Next(fileInfo))\r
+  {\r
+    if (!fileInfo.IsDir())\r
+      continue;\r
+    const UINT64 &cTime = *(const UINT64 *)(&fileInfo.CTime);\r
+    if(CheckDeleteItem(cTime, currentFileTime))\r
+      RemoveDirectoryWithSubItems(tempPath + fileInfo.Name);\r
+  }\r
+}\r
+*/\r
diff --git a/CPP/7zip/UI/FileManager/PanelItems.cpp b/CPP/7zip/UI/FileManager/PanelItems.cpp
new file mode 100755 (executable)
index 0000000..d301900
--- /dev/null
@@ -0,0 +1,806 @@
+// PanelItems.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/Sort.h"\r
+\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/Menu.h"\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/PropVariantConversions.h"\r
+\r
+#include "../../PropID.h"\r
+\r
+#include "resource.h"\r
+\r
+#include "LangUtils.h"\r
+#include "Panel.h"\r
+#include "PropertyName.h"\r
+#include "RootFolder.h"\r
+\r
+using namespace NWindows;\r
+\r
+static int GetColumnAlign(PROPID propID, VARTYPE varType)\r
+{\r
+  switch(propID)\r
+  {\r
+    case kpidCTime:\r
+    case kpidATime:\r
+    case kpidMTime:\r
+      return LVCFMT_LEFT;\r
+  }\r
+  switch(varType)\r
+  {\r
+    case VT_UI1:\r
+    case VT_I2:\r
+    case VT_UI2:\r
+    case VT_I4:\r
+    case VT_INT:\r
+    case VT_UI4:\r
+    case VT_UINT:\r
+    case VT_I8:\r
+    case VT_UI8:\r
+    case VT_BOOL:\r
+      return LVCFMT_RIGHT;\r
+    \r
+    case VT_EMPTY:\r
+    case VT_I1:\r
+    case VT_FILETIME:\r
+    case VT_BSTR:\r
+      return LVCFMT_LEFT;\r
+    \r
+    default:\r
+      return LVCFMT_CENTER;\r
+  }\r
+}\r
+\r
+HRESULT CPanel::InitColumns()\r
+{\r
+  if (_needSaveInfo)\r
+    SaveListViewInfo();\r
+\r
+  _listView.DeleteAllItems();\r
+  _selectedStatusVector.Clear();\r
+\r
+  ReadListViewInfo();\r
+\r
+\r
+  PROPID sortID;\r
+  /*\r
+  if (_listViewInfo.SortIndex >= 0)\r
+    sortID = _listViewInfo.Columns[_listViewInfo.SortIndex].PropID;\r
+  */\r
+  sortID  = _listViewInfo.SortID;\r
+\r
+  _ascending = _listViewInfo.Ascending;\r
+\r
+  _properties.Clear();\r
+\r
+  _needSaveInfo = true;\r
+\r
+  UInt32 numProperties;\r
+  _folder->GetNumberOfProperties(&numProperties);\r
+  int i;\r
+  for (i = 0; i < (int)numProperties; i++)\r
+  {\r
+    CMyComBSTR name;\r
+    PROPID propID;\r
+    VARTYPE varType;\r
+\r
+    RINOK(_folder->GetPropertyInfo(i, &name, &propID, &varType));\r
+\r
+    if (propID == kpidIsDir)\r
+      continue;\r
+\r
+    CItemProperty prop;\r
+    prop.Type = varType;\r
+    prop.ID = propID;\r
+    prop.Name = GetNameOfProperty(propID, name);\r
+    prop.Order = -1;\r
+    prop.IsVisible = true;\r
+    prop.Width = 100;\r
+    _properties.Add(prop);\r
+  }\r
+  // InitColumns2(sortID);\r
+\r
+  for (;;)\r
+    if (!_listView.DeleteColumn(0))\r
+      break;\r
+\r
+  int order = 0;\r
+  for (i = 0; i < _listViewInfo.Columns.Size(); i++)\r
+  {\r
+    const CColumnInfo &columnInfo = _listViewInfo.Columns[i];\r
+    int index = _properties.FindItemWithID(columnInfo.PropID);\r
+    if (index >= 0)\r
+    {\r
+      CItemProperty &item = _properties[index];\r
+      item.IsVisible = columnInfo.IsVisible;\r
+      item.Width = columnInfo.Width;\r
+      if (columnInfo.IsVisible)\r
+        item.Order = order++;\r
+      continue;\r
+    }\r
+  }\r
+  for (i = 0; i < _properties.Size(); i++)\r
+  {\r
+    CItemProperty &item = _properties[i];\r
+    if (item.Order < 0)\r
+      item.Order = order++;\r
+  }\r
+\r
+  _visibleProperties.Clear();\r
+  for (i = 0; i < _properties.Size(); i++)\r
+  {\r
+    const CItemProperty &prop = _properties[i];\r
+    if (prop.IsVisible)\r
+      _visibleProperties.Add(prop);\r
+  }\r
+\r
+  // _sortIndex = 0;\r
+  _sortID = kpidName;\r
+  /*\r
+  if (_listViewInfo.SortIndex >= 0)\r
+  {\r
+    int sortIndex = _properties.FindItemWithID(sortID);\r
+    if (sortIndex >= 0)\r
+      _sortIndex = sortIndex;\r
+  }\r
+  */\r
+  _sortID = _listViewInfo.SortID;\r
+\r
+  for (i = 0; i < _visibleProperties.Size(); i++)\r
+  {\r
+    InsertColumn(i);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+void CPanel::InsertColumn(int index)\r
+{\r
+  const CItemProperty &prop = _visibleProperties[index];\r
+  LV_COLUMNW column;\r
+  column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_ORDER;\r
+  column.cx = prop.Width;\r
+  column.fmt = GetColumnAlign(prop.ID, prop.Type);\r
+  column.iOrder = prop.Order;\r
+  column.iSubItem = index;\r
+  column.pszText = const_cast<wchar_t *>((const wchar_t *)prop.Name);\r
+  _listView.InsertColumn(index, &column);\r
+}\r
+\r
+HRESULT CPanel::RefreshListCtrl()\r
+{\r
+  return RefreshListCtrl(UString(), -1, true, UStringVector());\r
+}\r
+\r
+int CALLBACK CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData);\r
+\r
+\r
+void CPanel::GetSelectedNames(UStringVector &selectedNames)\r
+{\r
+  selectedNames.Clear();\r
+\r
+  CRecordVector<UInt32> indices;\r
+  GetSelectedItemsIndices(indices);\r
+  selectedNames.Reserve(indices.Size());\r
+  for (int  i = 0; i < indices.Size(); i++)\r
+    selectedNames.Add(GetItemRelPath(indices[i]));\r
+\r
+  /*\r
+  for (int i = 0; i < _listView.GetItemCount(); i++)\r
+  {\r
+    const int kSize = 1024;\r
+    WCHAR name[kSize + 1];\r
+    LVITEMW item;\r
+    item.iItem = i;\r
+    item.pszText = name;\r
+    item.cchTextMax  = kSize;\r
+    item.iSubItem = 0;\r
+    item.mask = LVIF_TEXT | LVIF_PARAM;\r
+    if (!_listView.GetItem(&item))\r
+      continue;\r
+    int realIndex = GetRealIndex(item);\r
+    if (realIndex == kParentIndex)\r
+      continue;\r
+    if (_selectedStatusVector[realIndex])\r
+      selectedNames.Add(item.pszText);\r
+  }\r
+  */\r
+  selectedNames.Sort();\r
+}\r
+\r
+void CPanel::SaveSelectedState(CSelectedState &s)\r
+{\r
+  s.FocusedName.Empty();\r
+  s.SelectedNames.Clear();\r
+  s.FocusedItem = _listView.GetFocusedItem();\r
+  {\r
+    if (s.FocusedItem >= 0)\r
+    {\r
+      int realIndex = GetRealItemIndex(s.FocusedItem);\r
+      if (realIndex != kParentIndex)\r
+        s.FocusedName = GetItemRelPath(realIndex);\r
+        /*\r
+        const int kSize = 1024;\r
+        WCHAR name[kSize + 1];\r
+        LVITEMW item;\r
+        item.iItem = focusedItem;\r
+        item.pszText = name;\r
+        item.cchTextMax  = kSize;\r
+        item.iSubItem = 0;\r
+        item.mask = LVIF_TEXT;\r
+        if (_listView.GetItem(&item))\r
+        focusedName = item.pszText;\r
+      */\r
+    }\r
+  }\r
+  GetSelectedNames(s.SelectedNames);\r
+}\r
+\r
+HRESULT CPanel::RefreshListCtrl(const CSelectedState &s)\r
+{\r
+  bool selectFocused = s.SelectFocused;\r
+  if (_mySelectMode)\r
+    selectFocused = true;\r
+  return RefreshListCtrl(s.FocusedName, s.FocusedItem, selectFocused, s.SelectedNames);\r
+}\r
+\r
+HRESULT CPanel::RefreshListCtrlSaveFocused()\r
+{\r
+  CSelectedState state;\r
+  SaveSelectedState(state);\r
+  return RefreshListCtrl(state);\r
+}\r
+\r
+void CPanel::SetFocusedSelectedItem(int index, bool select)\r
+{\r
+  UINT state = LVIS_FOCUSED;\r
+  if (select)\r
+    state |= LVIS_SELECTED;\r
+  _listView.SetItemState(index, state, state);\r
+  if (!_mySelectMode && select)\r
+  {\r
+    int realIndex = GetRealItemIndex(index);\r
+    if (realIndex != kParentIndex)\r
+      _selectedStatusVector[realIndex] = true;\r
+  }\r
+}\r
+\r
+HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool selectFocused,\r
+    const UStringVector &selectedNames)\r
+{\r
+  _dontShowMode = false;\r
+  LoadFullPathAndShow();\r
+  // OutputDebugStringA("=======\n");\r
+  // OutputDebugStringA("s1 \n");\r
+  CDisableTimerProcessing timerProcessing(*this);\r
+\r
+  if (focusedPos < 0)\r
+    focusedPos = 0;\r
+\r
+  _listView.SetRedraw(false);\r
+  // m_RedrawEnabled = false;\r
+\r
+  LVITEMW item;\r
+  ZeroMemory(&item, sizeof(item));\r
+  \r
+  _listView.DeleteAllItems();\r
+  _selectedStatusVector.Clear();\r
+  // _realIndices.Clear();\r
+  _startGroupSelect = 0;\r
+\r
+  _selectionIsDefined = false;\r
+  \r
+  // m_Files.Clear();\r
+  // _folder.Release();\r
+\r
+  if (!_folder)\r
+  {\r
+    // throw 1;\r
+    SetToRootFolder();\r
+  }\r
+  \r
+  _headerToolBar.EnableButton(kParentFolderID, !IsRootFolder());\r
+\r
+  CMyComPtr<IFolderSetFlatMode> folderSetFlatMode;\r
+  _folder.QueryInterface(IID_IFolderSetFlatMode, &folderSetFlatMode);\r
+  if (folderSetFlatMode)\r
+    folderSetFlatMode->SetFlatMode(BoolToInt(_flatMode));\r
+\r
+  RINOK(_folder->LoadItems());\r
+  RINOK(InitColumns());\r
+\r
+  // OutputDebugString(TEXT("Start Dir\n"));\r
+  UInt32 numItems;\r
+  _folder->GetNumberOfItems(&numItems);\r
+\r
+  bool showDots = _showDots && !IsRootFolder();\r
+\r
+  _listView.SetItemCount(numItems + (showDots ? 1 : 0));\r
+\r
+  _selectedStatusVector.Reserve(numItems);\r
+  int cursorIndex = -1;\r
+\r
+  CMyComPtr<IFolderGetSystemIconIndex> folderGetSystemIconIndex;\r
+  if (!IsFSFolder() || _showRealFileIcons)\r
+    _folder.QueryInterface(IID_IFolderGetSystemIconIndex, &folderGetSystemIconIndex);\r
+\r
+  if (showDots)\r
+  {\r
+    UString itemName = L"..";\r
+    item.iItem = _listView.GetItemCount();\r
+    if (itemName.CompareNoCase(focusedName) == 0)\r
+      cursorIndex = item.iItem;\r
+    item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;\r
+    int subItem = 0;\r
+    item.iSubItem = subItem++;\r
+    item.lParam = kParentIndex;\r
+    item.pszText = const_cast<wchar_t *>((const wchar_t *)itemName);\r
+    UInt32 attrib = FILE_ATTRIBUTE_DIRECTORY;\r
+    item.iImage = _extToIconMap.GetIconIndex(attrib, itemName);\r
+    if (item.iImage < 0)\r
+      item.iImage = 0;\r
+    if (_listView.InsertItem(&item) == -1)\r
+      return E_FAIL;\r
+  }\r
+  \r
+  // OutputDebugStringA("S1\n");\r
+\r
+  for (UInt32 i = 0; i < numItems; i++)\r
+  {\r
+    UString itemName = GetItemName(i);\r
+    const UString relPath = GetItemRelPath(i);\r
+    if (relPath.CompareNoCase(focusedName) == 0)\r
+      cursorIndex = _listView.GetItemCount();\r
+    bool selected = false;\r
+    if (selectedNames.FindInSorted(relPath) >= 0)\r
+      selected = true;\r
+    _selectedStatusVector.Add(selected);\r
+\r
+    item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;\r
+\r
+    if (!_mySelectMode)\r
+      if (selected)\r
+      {\r
+        item.mask |= LVIF_STATE;\r
+        item.state = LVIS_SELECTED;\r
+      }\r
+  \r
+    int subItem = 0;\r
+    item.iItem = _listView.GetItemCount();\r
+    \r
+    item.iSubItem = subItem++;\r
+    item.lParam = i;\r
+    \r
+    UString correctedName;\r
+    if (itemName.Find(L"     ") >= 0)\r
+    {\r
+      int pos = 0;\r
+      for (;;)\r
+      {\r
+        int posNew = itemName.Find(L"     ", pos);\r
+        if (posNew < 0)\r
+        {\r
+          correctedName += itemName.Mid(pos);\r
+          break;\r
+        }\r
+        correctedName += itemName.Mid(pos, posNew - pos);\r
+        correctedName += L" ... ";\r
+        pos = posNew;\r
+        while (itemName[++pos] == ' ');\r
+      }\r
+      item.pszText = const_cast<wchar_t *>((const wchar_t *)correctedName);\r
+    }\r
+    else\r
+      item.pszText = const_cast<wchar_t *>((const wchar_t *)itemName);\r
+\r
+    NCOM::CPropVariant prop;\r
+    RINOK(_folder->GetProperty(i, kpidAttrib, &prop));\r
+    UInt32 attrib = 0;\r
+    if (prop.vt == VT_UI4)\r
+      attrib = prop.ulVal;\r
+    else if (IsItemFolder(i))\r
+      attrib |= FILE_ATTRIBUTE_DIRECTORY;\r
+\r
+    bool defined  = false;\r
+\r
+    if (folderGetSystemIconIndex)\r
+    {\r
+      folderGetSystemIconIndex->GetSystemIconIndex(i, &item.iImage);\r
+      defined = (item.iImage > 0);\r
+    }\r
+    if (!defined)\r
+    {\r
+      if (_currentFolderPrefix.IsEmpty())\r
+      {\r
+        int iconIndexTemp;\r
+        GetRealIconIndex(itemName + WCHAR_PATH_SEPARATOR, attrib, iconIndexTemp);\r
+        item.iImage = iconIndexTemp;\r
+      }\r
+      else\r
+      {\r
+        item.iImage = _extToIconMap.GetIconIndex(attrib, itemName);\r
+      }\r
+    }\r
+    if (item.iImage < 0)\r
+      item.iImage = 0;\r
+\r
+    if (_listView.InsertItem(&item) == -1)\r
+      return E_FAIL; // error\r
+  }\r
+  // OutputDebugStringA("End2\n");\r
+\r
+  if (_listView.GetItemCount() > 0 && cursorIndex >= 0)\r
+    SetFocusedSelectedItem(cursorIndex, selectFocused);\r
+  _listView.SortItems(CompareItems, (LPARAM)this);\r
+  if (cursorIndex < 0 && _listView.GetItemCount() > 0)\r
+  {\r
+    if (focusedPos >= _listView.GetItemCount())\r
+      focusedPos = _listView.GetItemCount() - 1;\r
+    // we select item only in showDots mode.\r
+    SetFocusedSelectedItem(focusedPos, showDots);\r
+  }\r
+  // m_RedrawEnabled = true;\r
+  _listView.EnsureVisible(_listView.GetFocusedItem(), false);\r
+  _listView.SetRedraw(true);\r
+  _listView.InvalidateRect(NULL, true);\r
+  // OutputDebugStringA("End1\n");\r
+  /*\r
+  _listView.UpdateWindow();\r
+  */\r
+  return S_OK;\r
+}\r
+\r
+void CPanel::GetSelectedItemsIndices(CRecordVector<UInt32> &indices) const\r
+{\r
+  indices.Clear();\r
+  /*\r
+  int itemIndex = -1;\r
+  while ((itemIndex = _listView.GetNextItem(itemIndex, LVNI_SELECTED)) != -1)\r
+  {\r
+    LPARAM param;\r
+    if (_listView.GetItemParam(itemIndex, param))\r
+      indices.Add(param);\r
+  }\r
+  */\r
+  for (int i = 0; i < _selectedStatusVector.Size(); i++)\r
+    if (_selectedStatusVector[i])\r
+      indices.Add(i);\r
+  HeapSort(&indices.Front(), indices.Size());\r
+}\r
+\r
+void CPanel::GetOperatedItemIndices(CRecordVector<UInt32> &indices) const\r
+{\r
+  GetSelectedItemsIndices(indices);\r
+  if (!indices.IsEmpty())\r
+    return;\r
+  if (_listView.GetSelectedCount() == 0)\r
+    return;\r
+  int focusedItem = _listView.GetFocusedItem();\r
+  if (focusedItem >= 0)\r
+  {\r
+    if (_listView.GetItemState(focusedItem, LVIS_SELECTED) == LVIS_SELECTED)\r
+    {\r
+      int realIndex = GetRealItemIndex(focusedItem);\r
+      if (realIndex != kParentIndex)\r
+        indices.Add(realIndex);\r
+    }\r
+  }\r
+}\r
+\r
+void CPanel::GetAllItemIndices(CRecordVector<UInt32> &indices) const\r
+{\r
+  indices.Clear();\r
+  UInt32 numItems;\r
+  if (_folder->GetNumberOfItems(&numItems) == S_OK)\r
+    for (UInt32 i = 0; i < numItems; i++)\r
+      indices.Add(i);\r
+}\r
+\r
+void CPanel::GetOperatedIndicesSmart(CRecordVector<UInt32> &indices) const\r
+{\r
+  GetOperatedItemIndices(indices);\r
+  if (indices.IsEmpty() || (indices.Size() == 1 && indices[0] == (UInt32)(Int32)-1))\r
+    GetAllItemIndices(indices);\r
+}\r
+\r
+/*\r
+void CPanel::GetOperatedListViewIndices(CRecordVector<UInt32> &indices) const\r
+{\r
+  indices.Clear();\r
+  int numItems = _listView.GetItemCount();\r
+  for (int i = 0; i < numItems; i++)\r
+  {\r
+    int realIndex = GetRealItemIndex(i);\r
+    if (realIndex >= 0)\r
+      if (_selectedStatusVector[realIndex])\r
+        indices.Add(i);\r
+  }\r
+  if (indices.IsEmpty())\r
+  {\r
+    int focusedItem = _listView.GetFocusedItem();\r
+      if (focusedItem >= 0)\r
+        indices.Add(focusedItem);\r
+  }\r
+}\r
+*/\r
+\r
+void CPanel::EditItem()\r
+{\r
+  int focusedItem = _listView.GetFocusedItem();\r
+  if (focusedItem < 0)\r
+    return;\r
+  int realIndex = GetRealItemIndex(focusedItem);\r
+  if (realIndex == kParentIndex)\r
+    return;\r
+  if (!IsItemFolder(realIndex))\r
+    EditItem(realIndex);\r
+}\r
+\r
+void CPanel::OpenFocusedItemAsInternal()\r
+{\r
+  int focusedItem = _listView.GetFocusedItem();\r
+  if (focusedItem < 0)\r
+    return;\r
+  int realIndex = GetRealItemIndex(focusedItem);\r
+  if (IsItemFolder(realIndex))\r
+    OpenFolder(realIndex);\r
+  else\r
+    OpenItem(realIndex, true, false);\r
+}\r
+\r
+void CPanel::OpenSelectedItems(bool tryInternal)\r
+{\r
+  CRecordVector<UInt32> indices;\r
+  GetOperatedItemIndices(indices);\r
+  if (indices.Size() > 20)\r
+  {\r
+    MessageBoxErrorLang(IDS_TOO_MANY_ITEMS, 0x02000606);\r
+    return;\r
+  }\r
+  \r
+  int focusedItem = _listView.GetFocusedItem();\r
+  if (focusedItem >= 0)\r
+  {\r
+    int realIndex = GetRealItemIndex(focusedItem);\r
+    if (realIndex == kParentIndex && (tryInternal || indices.Size() == 0) &&\r
+        _listView.GetItemState(focusedItem, LVIS_SELECTED) == LVIS_SELECTED)\r
+      indices.Insert(0, realIndex);\r
+  }\r
+\r
+  bool dirIsStarted = false;\r
+  for (int i = 0; i < indices.Size(); i++)\r
+  {\r
+    UInt32 index = indices[i];\r
+    // CFileInfo &aFile = m_Files[index];\r
+    if (IsItemFolder(index))\r
+    {\r
+      if (!dirIsStarted)\r
+      {\r
+        if (tryInternal)\r
+        {\r
+          OpenFolder(index);\r
+          dirIsStarted = true;\r
+          break;\r
+        }\r
+        else\r
+          OpenFolderExternal(index);\r
+      }\r
+    }\r
+    else\r
+      OpenItem(index, (tryInternal && indices.Size() == 1), true);\r
+  }\r
+}\r
+\r
+UString CPanel::GetItemName(int itemIndex) const\r
+{\r
+  if (itemIndex == kParentIndex)\r
+    return L"..";\r
+  NCOM::CPropVariant prop;\r
+  if (_folder->GetProperty(itemIndex, kpidName, &prop) != S_OK)\r
+    throw 2723400;\r
+  if (prop.vt != VT_BSTR)\r
+    throw 2723401;\r
+  return prop.bstrVal;\r
+}\r
+\r
+UString CPanel::GetItemPrefix(int itemIndex) const\r
+{\r
+  if (itemIndex == kParentIndex)\r
+    return UString();\r
+  NCOM::CPropVariant prop;\r
+  if (_folder->GetProperty(itemIndex, kpidPrefix, &prop) != S_OK)\r
+    throw 2723400;\r
+  UString prefix;\r
+  if (prop.vt == VT_BSTR)\r
+    prefix = prop.bstrVal;\r
+  return prefix;\r
+}\r
+\r
+UString CPanel::GetItemRelPath(int itemIndex) const\r
+{\r
+  return GetItemPrefix(itemIndex) + GetItemName(itemIndex);\r
+}\r
+\r
+UString CPanel::GetItemFullPath(int itemIndex) const\r
+{\r
+  return _currentFolderPrefix + GetItemRelPath(itemIndex);\r
+}\r
+\r
+bool CPanel::IsItemFolder(int itemIndex) const\r
+{\r
+  if (itemIndex == kParentIndex)\r
+    return true;\r
+  NCOM::CPropVariant prop;\r
+  if (_folder->GetProperty(itemIndex, kpidIsDir, &prop) != S_OK)\r
+    throw 2723400;\r
+  if (prop.vt == VT_BOOL)\r
+    return VARIANT_BOOLToBool(prop.boolVal);\r
+  if (prop.vt == VT_EMPTY)\r
+    return false;\r
+  return false;\r
+}\r
+\r
+UINT64 CPanel::GetItemSize(int itemIndex) const\r
+{\r
+  if (itemIndex == kParentIndex)\r
+    return 0;\r
+  NCOM::CPropVariant prop;\r
+  if (_folder->GetProperty(itemIndex, kpidSize, &prop) != S_OK)\r
+    throw 2723400;\r
+  if (prop.vt == VT_EMPTY)\r
+    return 0;\r
+  return ConvertPropVariantToUInt64(prop);\r
+}\r
+\r
+void CPanel::ReadListViewInfo()\r
+{\r
+  _typeIDString = GetFolderTypeID();\r
+  if (!_typeIDString.IsEmpty())\r
+    ::ReadListViewInfo(_typeIDString, _listViewInfo);\r
+}\r
+\r
+void CPanel::SaveListViewInfo()\r
+{\r
+  int i;\r
+  for (i = 0; i < _visibleProperties.Size(); i++)\r
+  {\r
+    CItemProperty &prop = _visibleProperties[i];\r
+    LVCOLUMN winColumnInfo;\r
+    winColumnInfo.mask = LVCF_ORDER | LVCF_WIDTH;\r
+    if (!_listView.GetColumn(i, &winColumnInfo))\r
+      throw 1;\r
+    prop.Order = winColumnInfo.iOrder;\r
+    prop.Width = winColumnInfo.cx;\r
+  }\r
+\r
+  CListViewInfo viewInfo;\r
+  \r
+  // PROPID sortPropID = _properties[_sortIndex].ID;\r
+  PROPID sortPropID = _sortID;\r
+  \r
+  _visibleProperties.Sort();\r
+  for (i = 0; i < _visibleProperties.Size(); i++)\r
+  {\r
+    const CItemProperty &prop = _visibleProperties[i];\r
+    CColumnInfo columnInfo;\r
+    columnInfo.IsVisible = prop.IsVisible;\r
+    columnInfo.PropID = prop.ID;\r
+    columnInfo.Width = prop.Width;\r
+    viewInfo.Columns.Add(columnInfo);\r
+  }\r
+  for (i = 0; i < _properties.Size(); i++)\r
+  {\r
+    const CItemProperty &prop = _properties[i];\r
+    if (!prop.IsVisible)\r
+    {\r
+      CColumnInfo columnInfo;\r
+      columnInfo.IsVisible = prop.IsVisible;\r
+      columnInfo.PropID = prop.ID;\r
+      columnInfo.Width = prop.Width;\r
+      viewInfo.Columns.Add(columnInfo);\r
+    }\r
+  }\r
+  \r
+  // viewInfo.SortIndex = viewInfo.FindColumnWithID(sortPropID);\r
+  viewInfo.SortID = sortPropID;\r
+\r
+  viewInfo.Ascending = _ascending;\r
+  if (!_listViewInfo.IsEqual(viewInfo))\r
+  {\r
+    ::SaveListViewInfo(_typeIDString, viewInfo);\r
+    _listViewInfo = viewInfo;\r
+  }\r
+}\r
+\r
+\r
+bool CPanel::OnRightClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActiveate, LRESULT &result)\r
+{\r
+  if (itemActiveate->hdr.hwndFrom == HWND(_listView))\r
+    return false;\r
+  POINT point;\r
+  ::GetCursorPos(&point);\r
+  ShowColumnsContextMenu(point.x, point.y);\r
+  result = TRUE;\r
+  return true;\r
+}\r
+\r
+void CPanel::ShowColumnsContextMenu(int x, int y)\r
+{\r
+\r
+  CMenu menu;\r
+  CMenuDestroyer menuDestroyer(menu);\r
+\r
+  menu.CreatePopup();\r
+\r
+  const int kCommandStart = 100;\r
+  for (int i = 0; i < _properties.Size(); i++)\r
+  {\r
+    const CItemProperty &prop = _properties[i];\r
+    UINT flags =  MF_STRING;\r
+    if (prop.IsVisible)\r
+      flags |= MF_CHECKED;\r
+    if (i == 0)\r
+      flags |= MF_GRAYED;\r
+    menu.AppendItem(flags, kCommandStart + i, prop.Name);\r
+  }\r
+  int menuResult = menu.Track(TPM_LEFTALIGN | TPM_RETURNCMD | TPM_NONOTIFY, x, y, _listView);\r
+  if (menuResult >= kCommandStart && menuResult <= kCommandStart + _properties.Size())\r
+  {\r
+    int index = menuResult - kCommandStart;\r
+    CItemProperty &prop = _properties[index];\r
+    prop.IsVisible = !prop.IsVisible;\r
+\r
+    if (prop.IsVisible)\r
+    {\r
+      int prevVisibleSize = _visibleProperties.Size();\r
+      prop.Order = prevVisibleSize;\r
+      _visibleProperties.Add(prop);\r
+      InsertColumn(prevVisibleSize);\r
+    }\r
+    else\r
+    {\r
+      int visibleIndex = _visibleProperties.FindItemWithID(prop.ID);\r
+      _visibleProperties.Delete(visibleIndex);\r
+      /*\r
+      if (_sortIndex == index)\r
+      {\r
+        _sortIndex = 0;\r
+        _ascending = true;\r
+      }\r
+      */\r
+      if (_sortID == prop.ID)\r
+      {\r
+        _sortID = kpidName;\r
+        _ascending = true;\r
+      }\r
+\r
+      _listView.DeleteColumn(visibleIndex);\r
+    }\r
+  }\r
+}\r
+\r
+void CPanel::OnReload()\r
+{\r
+  HRESULT res = RefreshListCtrlSaveFocused();\r
+  if (res != S_OK)\r
+    MessageBoxError(res);\r
+  OnRefreshStatusBar();\r
+}\r
+\r
+void CPanel::OnTimer()\r
+{\r
+  if (!_processTimer)\r
+    return;\r
+  CMyComPtr<IFolderWasChanged> folderWasChanged;\r
+  if (_folder.QueryInterface(IID_IFolderWasChanged, &folderWasChanged) != S_OK)\r
+    return;\r
+  Int32 wasChanged;\r
+  if (folderWasChanged->WasChanged(&wasChanged) != S_OK)\r
+    return;\r
+  if (wasChanged == 0)\r
+    return;\r
+  OnReload();\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/PanelKey.cpp b/CPP/7zip/UI/FileManager/PanelKey.cpp
new file mode 100755 (executable)
index 0000000..834bee9
--- /dev/null
@@ -0,0 +1,335 @@
+// PanelKey.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Panel.h"\r
+#include "HelpUtils.h"\r
+\r
+#include "../../PropID.h"\r
+#include "App.h"\r
+\r
+// static LPCWSTR kHelpTopic = L"FM/index.htm";\r
+\r
+struct CVKeyPropIDPair\r
+{\r
+  WORD VKey;\r
+  PROPID PropID;\r
+};\r
+\r
+static CVKeyPropIDPair g_VKeyPropIDPairs[] =\r
+{\r
+  { VK_F3, kpidName },\r
+  { VK_F4, kpidExtension },\r
+  { VK_F5, kpidMTime },\r
+  { VK_F6, kpidSize },\r
+  { VK_F7, kpidNoProperty }\r
+};\r
+\r
+static int FindVKeyPropIDPair(WORD vKey)\r
+{\r
+  for (int i = 0; i < sizeof(g_VKeyPropIDPairs) / sizeof(g_VKeyPropIDPairs[0]); i++)\r
+    if (g_VKeyPropIDPairs[i].VKey == vKey)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+\r
+bool CPanel::OnKeyDown(LPNMLVKEYDOWN keyDownInfo, LRESULT &result)\r
+{\r
+  if (keyDownInfo->wVKey == VK_TAB && keyDownInfo->hdr.hwndFrom == _listView)\r
+  {\r
+    _panelCallback->OnTab();\r
+    return false;\r
+  }\r
+  bool alt = (::GetKeyState(VK_MENU) & 0x8000) != 0;\r
+  bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0;\r
+  // bool leftCtrl = (::GetKeyState(VK_LCONTROL) & 0x8000) != 0;\r
+  bool rightCtrl = (::GetKeyState(VK_RCONTROL) & 0x8000) != 0;\r
+  bool shift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0;\r
+  result = 0;\r
+\r
+  if (keyDownInfo->wVKey >= '0' && keyDownInfo->wVKey <= '9' &&\r
+      (rightCtrl || alt))\r
+  {\r
+    int index = keyDownInfo->wVKey - '0';\r
+    if (shift)\r
+    {\r
+      SetBookmark(index);\r
+      return true;\r
+    }\r
+    else\r
+    {\r
+      OpenBookmark(index);\r
+      return true;\r
+    }\r
+  }\r
+\r
+  if ((keyDownInfo->wVKey == VK_F2 ||\r
+    keyDownInfo->wVKey == VK_F1) && alt && !ctrl && !shift)\r
+  {\r
+    _panelCallback->SetFocusToPath(keyDownInfo->wVKey == VK_F1 ? 0 : 1);\r
+    return true;\r
+  }\r
+\r
+  if ((keyDownInfo->wVKey == VK_F9) && !alt && !ctrl && !shift)\r
+  {\r
+    g_App.SwitchOnOffOnePanel();\r
+  }\r
+\r
+  if(keyDownInfo->wVKey >= VK_F3 && keyDownInfo->wVKey <= VK_F12 && ctrl)\r
+  {\r
+    int index = FindVKeyPropIDPair(keyDownInfo->wVKey);\r
+    if (index >= 0)\r
+      SortItemsWithPropID(g_VKeyPropIDPairs[index].PropID);\r
+  }\r
+\r
+  switch(keyDownInfo->wVKey)\r
+  {\r
+    case VK_SHIFT:\r
+    {\r
+      _selectionIsDefined = false;\r
+      _prevFocusedItem = _listView.GetFocusedItem();\r
+      break;\r
+    }\r
+    /*\r
+    case VK_F1:\r
+    {\r
+      // ShowHelpWindow(NULL, kHelpTopic);\r
+      break;\r
+    }\r
+    */\r
+    case VK_F2:\r
+    {\r
+      if (!alt && !ctrl &&!shift)\r
+      {\r
+        RenameFile();\r
+        return true;\r
+      }\r
+      break;\r
+    }\r
+    case VK_F4:\r
+    {\r
+      if (!alt && !ctrl && !shift)\r
+      {\r
+        EditItem();\r
+        return true;\r
+      }\r
+      if (!alt && !ctrl && shift)\r
+      {\r
+        CreateFile();\r
+        return true;\r
+      }\r
+      break;\r
+    }\r
+    case VK_F5:\r
+    {\r
+      if (!alt && !ctrl)\r
+      {\r
+        _panelCallback->OnCopy(false, shift);\r
+        return true;\r
+      }\r
+      break;\r
+    }\r
+    case VK_F6:\r
+    {\r
+      if (!alt && !ctrl)\r
+      {\r
+        _panelCallback->OnCopy(true, shift);\r
+        return true;\r
+      }\r
+      break;\r
+    }\r
+    /*\r
+    case VK_F7:\r
+    {\r
+      if (!alt && !ctrl && !shift)\r
+      {\r
+        CreateFolder();\r
+        return true;\r
+      }\r
+      break;\r
+    }\r
+    */\r
+    case VK_DELETE:\r
+    {\r
+      DeleteItems(!shift);\r
+      return true;\r
+    }\r
+    case VK_INSERT:\r
+    {\r
+      if (!alt)\r
+      {\r
+        if (ctrl && !shift)\r
+        {\r
+          EditCopy();\r
+          return true;\r
+        }\r
+        if (shift && !ctrl)\r
+        {\r
+          EditPaste();\r
+          return true;\r
+        }\r
+        if (!shift && !ctrl && _mySelectMode)\r
+        {\r
+          OnInsert();\r
+          return true;\r
+        }\r
+      }\r
+      return false;\r
+    }\r
+    case VK_DOWN:\r
+    {\r
+      if(shift)\r
+        OnArrowWithShift();\r
+      return false;\r
+    }\r
+    case VK_UP:\r
+    {\r
+      if (alt)\r
+        _panelCallback->OnSetSameFolder();\r
+      else if(shift)\r
+        OnArrowWithShift();\r
+      return false;\r
+    }\r
+    case VK_RIGHT:\r
+    {\r
+      if (alt)\r
+        _panelCallback->OnSetSubFolder();\r
+      else if(shift)\r
+        OnArrowWithShift();\r
+      return false;\r
+    }\r
+    case VK_LEFT:\r
+    {\r
+      if (alt)\r
+        _panelCallback->OnSetSubFolder();\r
+      else if(shift)\r
+        OnArrowWithShift();\r
+      return false;\r
+    }\r
+    case VK_NEXT:\r
+    {\r
+      if (ctrl && !alt && !shift)\r
+      {\r
+        // EnterToFocused();\r
+        return true;\r
+      }\r
+      break;\r
+    }\r
+    case VK_ADD:\r
+    {\r
+      if (alt)\r
+        SelectByType(true);\r
+      else if (shift)\r
+        SelectAll(true);\r
+      else if(!ctrl)\r
+        SelectSpec(true);\r
+      return true;\r
+    }\r
+    case VK_SUBTRACT:\r
+    {\r
+      if (alt)\r
+        SelectByType(false);\r
+      else if (shift)\r
+        SelectAll(false);\r
+      else\r
+        SelectSpec(false);\r
+      return true;\r
+    }\r
+    /*\r
+    case VK_DELETE:\r
+      CommandDelete();\r
+      return 0;\r
+    case VK_F1:\r
+      CommandHelp();\r
+      return 0;\r
+    */\r
+    case VK_BACK:\r
+      OpenParentFolder();\r
+      return true;\r
+    /*\r
+    case VK_DIVIDE:\r
+    case '\\':\r
+    case '/':\r
+    case VK_OEM_5:\r
+    {\r
+      // OpenRootFolder();\r
+      OpenDrivesFolder();\r
+\r
+      return true;\r
+    }\r
+    */\r
+    case 'A':\r
+      if(ctrl)\r
+      {\r
+        SelectAll(true);\r
+        return true;\r
+      }\r
+      return false;\r
+    case 'X':\r
+      if (ctrl)\r
+      {\r
+        EditCut();\r
+        return true;\r
+      }\r
+      return false;\r
+    case 'C':\r
+      if (ctrl)\r
+      {\r
+        EditCopy();\r
+        return true;\r
+      }\r
+      return false;\r
+    case 'V':\r
+      if (ctrl)\r
+      {\r
+        EditPaste();\r
+        return true;\r
+      }\r
+      return false;\r
+    case 'N':\r
+      if (ctrl)\r
+      {\r
+        CreateFile();\r
+        return true;\r
+      }\r
+      return false;\r
+    case 'R':\r
+      if(ctrl)\r
+      {\r
+        OnReload();\r
+        return true;\r
+      }\r
+      return false;\r
+    case 'Z':\r
+      if(ctrl)\r
+      {\r
+        ChangeComment();\r
+        return true;\r
+      }\r
+      return false;\r
+    case '1':\r
+    case '2':\r
+    case '3':\r
+    case '4':\r
+      if(ctrl)\r
+      {\r
+        int styleIndex = keyDownInfo->wVKey - '1';\r
+        SetListViewMode(styleIndex);\r
+        return true;\r
+      }\r
+      return false;\r
+    case VK_MULTIPLY:\r
+      {\r
+        InvertSelection();\r
+        return true;\r
+      }\r
+    case VK_F12:\r
+      if (alt && !ctrl && !shift)\r
+      {\r
+        FoldersHistory();\r
+        return true;\r
+      }\r
+  }\r
+  return false;\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/PanelListNotify.cpp b/CPP/7zip/UI/FileManager/PanelListNotify.cpp
new file mode 100755 (executable)
index 0000000..efc5f0d
--- /dev/null
@@ -0,0 +1,429 @@
+// PanelListNotify.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "resource.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/PropVariantConversions.h"\r
+\r
+#include "../Common/PropIDUtils.h"\r
+#include "../../PropID.h"\r
+\r
+#include "Panel.h"\r
+#include "FormatUtils.h"\r
+\r
+using namespace NWindows;\r
+\r
+/*\r
+static UString ConvertSizeToStringShort(UInt64 value)\r
+{\r
+  wchar_t s[32];\r
+  wchar_t c, c2 = L'B';\r
+  if (value < (UInt64)10000)\r
+  {\r
+    c = L'B';\r
+    c2 = L'\0';\r
+  }\r
+  else if (value < ((UInt64)10000 << 10))\r
+  {\r
+    value >>= 10;\r
+    c = L'K';\r
+  }\r
+  else if (value < ((UInt64)10000 << 20))\r
+  {\r
+    value >>= 20;\r
+    c = L'M';\r
+  }\r
+  else\r
+  {\r
+    value >>= 30;\r
+    c = L'G';\r
+  }\r
+  ConvertUInt64ToString(value, s);\r
+  int p = MyStringLen(s);\r
+  s[p++] = L' ';\r
+  s[p++] = c;\r
+  s[p++] = c2;\r
+  s[p++] = L'\0';\r
+  return s;\r
+}\r
+*/\r
+\r
+UString ConvertSizeToString(UInt64 value)\r
+{\r
+  wchar_t s[32];\r
+  ConvertUInt64ToString(value, s);\r
+  int i = MyStringLen(s);\r
+  int pos = sizeof(s) / sizeof(s[0]);\r
+  s[--pos] = L'\0';\r
+  while (i > 3)\r
+  {\r
+    s[--pos] = s[--i];\r
+    s[--pos] = s[--i];\r
+    s[--pos] = s[--i];\r
+    s[--pos] = L' ';\r
+  }\r
+  while (i > 0)\r
+    s[--pos] = s[--i];\r
+  return s + pos;\r
+}\r
+\r
+LRESULT CPanel::SetItemText(LVITEMW &item)\r
+{\r
+  if (_dontShowMode)\r
+    return 0;\r
+\r
+  UINT32 realIndex = GetRealIndex(item);\r
+  /*\r
+  if ((item.mask & LVIF_IMAGE) != 0)\r
+  {\r
+    bool defined  = false;\r
+    CComPtr<IFolderGetSystemIconIndex> folderGetSystemIconIndex;\r
+    _folder.QueryInterface(&folderGetSystemIconIndex);\r
+    if (folderGetSystemIconIndex)\r
+    {\r
+      folderGetSystemIconIndex->GetSystemIconIndex(index, &item.iImage);\r
+      defined = (item.iImage > 0);\r
+    }\r
+    if (!defined)\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      _folder->GetProperty(index, kpidAttrib, &prop);\r
+      UINT32 attrib = 0;\r
+      if (prop.vt == VT_UI4)\r
+        attrib = prop.ulVal;\r
+      else if (IsItemFolder(index))\r
+        attrib |= FILE_ATTRIBUTE_DIRECTORY;\r
+      if (_currentFolderPrefix.IsEmpty())\r
+        throw 1;\r
+      else\r
+        item.iImage = _extToIconMap.GetIconIndex(attrib, GetSystemString(GetItemName(index)));\r
+    }\r
+    // item.iImage = 1;\r
+  }\r
+  */\r
+\r
+  if ((item.mask & LVIF_TEXT) == 0)\r
+    return 0;\r
+\r
+  if (realIndex == kParentIndex)\r
+    return 0;\r
+  UString s;\r
+  UINT32 subItemIndex = item.iSubItem;\r
+  PROPID propID = _visibleProperties[subItemIndex].ID;\r
+  /*\r
+  {\r
+    NCOM::CPropVariant property;\r
+    if (propID == kpidType)\r
+      string = GetFileType(index);\r
+    else\r
+    {\r
+      HRESULT result = m_ArchiveFolder->GetProperty(index, propID, &property);\r
+      if (result != S_OK)\r
+      {\r
+        // PrintMessage("GetPropertyValue error");\r
+        return 0;\r
+      }\r
+      string = ConvertPropertyToString(property, propID, false);\r
+    }\r
+  }\r
+  */\r
+  // const NFind::CFileInfo &aFileInfo = m_Files[index];\r
+\r
+  NCOM::CPropVariant prop;\r
+  /*\r
+  bool needRead = true;\r
+  if (propID == kpidSize)\r
+  {\r
+    CComPtr<IFolderGetItemFullSize> getItemFullSize;\r
+    if (_folder.QueryInterface(&getItemFullSize) == S_OK)\r
+    {\r
+      if (getItemFullSize->GetItemFullSize(index, &prop) == S_OK)\r
+        needRead = false;\r
+    }\r
+  }\r
+  if (needRead)\r
+  */\r
+\r
+  HRESULT res = _folder->GetProperty(realIndex, propID, &prop);\r
+  if (res != S_OK)\r
+    s = UString(L"Error: ") + HResultToMessage(res);\r
+  else\r
+  if ((prop.vt == VT_UI8 || prop.vt == VT_UI4) && (\r
+      propID == kpidSize ||\r
+      propID == kpidPackSize ||\r
+      propID == kpidNumSubDirs ||\r
+      propID == kpidNumSubFiles ||\r
+      propID == kpidPosition ||\r
+      propID == kpidNumBlocks ||\r
+      propID == kpidClusterSize ||\r
+      propID == kpidTotalSize ||\r
+      propID == kpidFreeSpace\r
+      ))\r
+    s = ConvertSizeToString(ConvertPropVariantToUInt64(prop));\r
+  else\r
+  {\r
+    s = ConvertPropertyToString(prop, propID, false);\r
+    s.Replace(wchar_t(0xA), L' ');\r
+    s.Replace(wchar_t(0xD), L' ');\r
+  }\r
+  int size = item.cchTextMax;\r
+  if (size > 0)\r
+  {\r
+    if (s.Length() + 1 > size)\r
+      s = s.Left(size - 1);\r
+    MyStringCopy(item.pszText, (const wchar_t *)s);\r
+  }\r
+  return 0;\r
+}\r
+\r
+#ifndef UNDER_CE\r
+extern DWORD g_ComCtl32Version;\r
+#endif\r
+\r
+void CPanel::OnItemChanged(NMLISTVIEW *item)\r
+{\r
+  int index = (int)item->lParam;\r
+  if (index == kParentIndex)\r
+    return;\r
+  bool oldSelected = (item->uOldState & LVIS_SELECTED) != 0;\r
+  bool newSelected = (item->uNewState & LVIS_SELECTED) != 0;\r
+  // Don't change this code. It works only with such check\r
+  if (oldSelected != newSelected)\r
+    _selectedStatusVector[index] = newSelected;\r
+}\r
+\r
+extern bool g_LVN_ITEMACTIVATE_Support;\r
+\r
+void CPanel::OnNotifyActivateItems()\r
+{\r
+  // bool leftCtrl = (::GetKeyState(VK_LCONTROL) & 0x8000) != 0;\r
+  // bool rightCtrl = (::GetKeyState(VK_RCONTROL) & 0x8000) != 0;\r
+  bool alt = (::GetKeyState(VK_MENU) & 0x8000) != 0;\r
+  bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0;\r
+  bool shift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0;\r
+  if (!shift && alt && !ctrl)\r
+    Properties();\r
+  else\r
+    OpenSelectedItems(!shift || alt || ctrl);\r
+}\r
+\r
+bool CPanel::OnNotifyList(LPNMHDR header, LRESULT &result)\r
+{\r
+  switch(header->code)\r
+  {\r
+    case LVN_ITEMCHANGED:\r
+    {\r
+      if (_enableItemChangeNotify)\r
+      {\r
+        if (!_mySelectMode)\r
+          OnItemChanged((LPNMLISTVIEW)header);\r
+        RefreshStatusBar();\r
+      }\r
+      return false;\r
+    }\r
+    /*\r
+\r
+    case LVN_ODSTATECHANGED:\r
+      {\r
+      break;\r
+      }\r
+    */\r
+\r
+    case LVN_GETDISPINFOW:\r
+    {\r
+      LV_DISPINFOW *dispInfo = (LV_DISPINFOW *)header;\r
+\r
+      //is the sub-item information being requested?\r
+\r
+      if ((dispInfo->item.mask & LVIF_TEXT) != 0 ||\r
+        (dispInfo->item.mask & LVIF_IMAGE) != 0)\r
+        SetItemText(dispInfo->item);\r
+      return false;\r
+    }\r
+    case LVN_KEYDOWN:\r
+    {\r
+      bool boolResult = OnKeyDown(LPNMLVKEYDOWN(header), result);\r
+      RefreshStatusBar();\r
+      return boolResult;\r
+    }\r
+\r
+    case LVN_COLUMNCLICK:\r
+      OnColumnClick(LPNMLISTVIEW(header));\r
+      return false;\r
+\r
+    case LVN_ITEMACTIVATE:\r
+      if (g_LVN_ITEMACTIVATE_Support)\r
+      {\r
+        OnNotifyActivateItems();\r
+        return false;\r
+      }\r
+      break;\r
+    case NM_DBLCLK:\r
+    case NM_RETURN:\r
+      if (!g_LVN_ITEMACTIVATE_Support)\r
+      {\r
+        OnNotifyActivateItems();\r
+        return false;\r
+      }\r
+      break;\r
+\r
+    case NM_RCLICK:\r
+      RefreshStatusBar();\r
+      break;\r
+\r
+    /*\r
+      return OnRightClick((LPNMITEMACTIVATE)header, result);\r
+    */\r
+      /*\r
+      case NM_CLICK:\r
+      SendRefreshStatusBarMessage();\r
+      return 0;\r
+      \r
+        // TODO : Handler default action...\r
+        return 0;\r
+        case LVN_ITEMCHANGED:\r
+        {\r
+        NMLISTVIEW *pNMLV = (NMLISTVIEW *) lpnmh;\r
+        SelChange(pNMLV);\r
+        return TRUE;\r
+        }\r
+        case NM_SETFOCUS:\r
+        return onSetFocus(NULL);\r
+        case NM_KILLFOCUS:\r
+        return onKillFocus(NULL);\r
+      */\r
+    case NM_CLICK:\r
+    {\r
+      // we need SetFocusToList, if we drag-select items from other panel.\r
+      SetFocusToList();\r
+      RefreshStatusBar();\r
+      if (_mySelectMode)\r
+        #ifndef UNDER_CE\r
+        if (g_ComCtl32Version >= MAKELONG(71, 4))\r
+        #endif\r
+          OnLeftClick((MY_NMLISTVIEW_NMITEMACTIVATE *)header);\r
+      return false;\r
+    }\r
+    case LVN_BEGINLABELEDITW:\r
+      result = OnBeginLabelEdit((LV_DISPINFOW *)header);\r
+      return true;\r
+    case LVN_ENDLABELEDITW:\r
+      result = OnEndLabelEdit((LV_DISPINFOW *)header);\r
+      return true;\r
+\r
+    case NM_CUSTOMDRAW:\r
+    {\r
+      if (_mySelectMode)\r
+        return OnCustomDraw((LPNMLVCUSTOMDRAW)header, result);\r
+      break;\r
+    }\r
+    case LVN_BEGINDRAG:\r
+    {\r
+      OnDrag((LPNMLISTVIEW)header);\r
+      RefreshStatusBar();\r
+      break;\r
+    }\r
+    // case LVN_BEGINRDRAG:\r
+  }\r
+  return false;\r
+}\r
+\r
+bool CPanel::OnCustomDraw(LPNMLVCUSTOMDRAW lplvcd, LRESULT &result)\r
+{\r
+  switch(lplvcd->nmcd.dwDrawStage)\r
+  {\r
+  case CDDS_PREPAINT :\r
+    result = CDRF_NOTIFYITEMDRAW;\r
+    return true;\r
+    \r
+  case CDDS_ITEMPREPAINT:\r
+    /*\r
+    SelectObject(lplvcd->nmcd.hdc,\r
+    GetFontForItem(lplvcd->nmcd.dwItemSpec,\r
+    lplvcd->nmcd.lItemlParam) );\r
+    lplvcd->clrText = GetColorForItem(lplvcd->nmcd.dwItemSpec,\r
+    lplvcd->nmcd.lItemlParam);\r
+    lplvcd->clrTextBk = GetBkColorForItem(lplvcd->nmcd.dwItemSpec,\r
+    lplvcd->nmcd.lItemlParam);\r
+    */\r
+    int realIndex = (int)lplvcd->nmcd.lItemlParam;\r
+    bool selected = false;\r
+    if (realIndex != kParentIndex)\r
+      selected = _selectedStatusVector[realIndex];\r
+    if (selected)\r
+      lplvcd->clrTextBk = RGB(255, 192, 192);\r
+    // lplvcd->clrText = RGB(255, 0, 128);\r
+    else\r
+      lplvcd->clrTextBk = _listView.GetBkColor();\r
+    // lplvcd->clrText = RGB(0, 0, 0);\r
+    // result = CDRF_NEWFONT;\r
+    result = CDRF_NOTIFYITEMDRAW;\r
+    return true;\r
+    \r
+    // return false;\r
+    // return true;\r
+    /*\r
+    case CDDS_SUBITEM | CDDS_ITEMPREPAINT:\r
+    if (lplvcd->iSubItem == 0)\r
+    {\r
+    // lplvcd->clrText = RGB(255, 0, 0);\r
+    lplvcd->clrTextBk = RGB(192, 192, 192);\r
+    }\r
+    else\r
+    {\r
+    lplvcd->clrText = RGB(0, 0, 0);\r
+    lplvcd->clrTextBk = RGB(255, 255, 255);\r
+    }\r
+    return true;\r
+    */\r
+\r
+        /* At this point, you can change the background colors for the item\r
+        and any subitems and return CDRF_NEWFONT. If the list-view control\r
+        is in report mode, you can simply return CDRF_NOTIFYSUBITEMREDRAW\r
+        to customize the item's subitems individually */\r
+  }\r
+  return false;\r
+}\r
+\r
+void CPanel::OnRefreshStatusBar()\r
+{\r
+  CRecordVector<UINT32> indices;\r
+  GetOperatedItemIndices(indices);\r
+\r
+  _statusBar.SetText(0, MyFormatNew(IDS_N_SELECTED_ITEMS, 0x02000301, NumberToString(indices.Size())));\r
+\r
+  UString selectSizeString;\r
+\r
+  if (indices.Size() > 0)\r
+  {\r
+    UInt64 totalSize = 0;\r
+    for (int i = 0; i < indices.Size(); i++)\r
+      totalSize += GetItemSize(indices[i]);\r
+    selectSizeString = ConvertSizeToString(totalSize);\r
+  }\r
+  _statusBar.SetText(1, selectSizeString);\r
+\r
+  int focusedItem = _listView.GetFocusedItem();\r
+  UString sizeString;\r
+  UString dateString;\r
+  if (focusedItem >= 0 && _listView.GetSelectedCount() > 0)\r
+  {\r
+    int realIndex = GetRealItemIndex(focusedItem);\r
+    if (realIndex != kParentIndex)\r
+    {\r
+      sizeString = ConvertSizeToString(GetItemSize(realIndex));\r
+      NCOM::CPropVariant prop;\r
+      if (_folder->GetProperty(realIndex, kpidMTime, &prop) == S_OK)\r
+        dateString = ConvertPropertyToString(prop, kpidMTime, false);\r
+    }\r
+  }\r
+  _statusBar.SetText(2, sizeString);\r
+  _statusBar.SetText(3, dateString);\r
+  // _statusBar.SetText(4, nameString);\r
+  // _statusBar2.SetText(1, MyFormatNew(L"{0} bytes", NumberToStringW(totalSize)));\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp
new file mode 100755 (executable)
index 0000000..13a3ae1
--- /dev/null
@@ -0,0 +1,679 @@
+#include "StdAfx.h"\r
+\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/COM.h"\r
+#include "Windows/Clipboard.h"\r
+#include "Windows/Menu.h"\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/PropVariantConversions.h"\r
+\r
+#include "../../PropID.h"\r
+#include "../Common/PropIDUtils.h"\r
+#include "../Explorer/ContextMenu.h"\r
+\r
+#include "App.h"\r
+#include "LangUtils.h"\r
+#include "MyLoadMenu.h"\r
+#include "PropertyName.h"\r
+\r
+#include "resource.h"\r
+#include "PropertyNameRes.h"\r
+\r
+using namespace NWindows;\r
+\r
+LONG g_DllRefCount = 0;\r
+\r
+static const UINT kSevenZipStartMenuID = kPluginMenuStartID ;\r
+static const UINT kSystemStartMenuID = kPluginMenuStartID + 100;\r
+\r
+void CPanel::InvokeSystemCommand(const char *command)\r
+{\r
+  NCOM::CComInitializer comInitializer;\r
+  if (!IsFsOrPureDrivesFolder())\r
+    return;\r
+  CRecordVector<UInt32> operatedIndices;\r
+  GetOperatedItemIndices(operatedIndices);\r
+  if (operatedIndices.IsEmpty())\r
+    return;\r
+  CMyComPtr<IContextMenu> contextMenu;\r
+  if (CreateShellContextMenu(operatedIndices, contextMenu) != S_OK)\r
+    return;\r
+\r
+  CMINVOKECOMMANDINFO ci;\r
+  ZeroMemory(&ci, sizeof(ci));\r
+  ci.cbSize = sizeof(CMINVOKECOMMANDINFO);\r
+  ci.hwnd = GetParent();\r
+  ci.lpVerb = command;\r
+  contextMenu->InvokeCommand(&ci);\r
+}\r
+\r
+static const wchar_t *kSeparator = L"----------------------------\n";\r
+static const wchar_t *kSeparatorSmall = L"----\n";\r
+static const wchar_t *kPropValueSeparator = L": ";\r
+\r
+extern UString ConvertSizeToString(UInt64 value);\r
+\r
+static void AddPropertyString(PROPID propID, const wchar_t *nameBSTR,\r
+    const NCOM::CPropVariant &prop, UString &s)\r
+{\r
+  if (prop.vt != VT_EMPTY)\r
+  {\r
+    UString val;\r
+\r
+    if ((prop.vt == VT_UI8 || prop.vt == VT_UI4) && (\r
+        propID == kpidSize ||\r
+        propID == kpidPackSize ||\r
+        propID == kpidNumSubDirs ||\r
+        propID == kpidNumSubFiles ||\r
+        propID == kpidNumBlocks ||\r
+        propID == kpidClusterSize ||\r
+        propID == kpidTotalSize ||\r
+        propID == kpidFreeSpace ||\r
+        propID == kpidPhySize ||\r
+        propID == kpidHeadersSize ||\r
+        propID == kpidFreeSpace\r
+        ))\r
+      val = ConvertSizeToString(ConvertPropVariantToUInt64(prop));\r
+    else\r
+      val = ConvertPropertyToString(prop, propID);\r
+\r
+    if (!val.IsEmpty())\r
+    {\r
+      s += GetNameOfProperty(propID, nameBSTR);\r
+      s += kPropValueSeparator;\r
+      /*\r
+      if (propID == kpidComment)\r
+        s += L'\n';\r
+      */\r
+      s += val;\r
+      s += L'\n';\r
+    }\r
+  }\r
+}\r
+\r
+void CPanel::Properties()\r
+{\r
+  CMyComPtr<IGetFolderArcProps> getFolderArcProps;\r
+  _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps);\r
+  if (!getFolderArcProps)\r
+  {\r
+    InvokeSystemCommand("properties");\r
+    return;\r
+  }\r
+  \r
+  {\r
+    UString message;\r
+\r
+    CRecordVector<UInt32> operatedIndices;\r
+    GetOperatedItemIndices(operatedIndices);\r
+    if (operatedIndices.Size() == 1)\r
+    {\r
+      UInt32 index = operatedIndices[0];\r
+      // message += L"Item:\n";\r
+      UInt32 numProps;\r
+      if (_folder->GetNumberOfProperties(&numProps) == S_OK)\r
+      {\r
+        for (UInt32 i = 0; i < numProps; i++)\r
+        {\r
+          CMyComBSTR name;\r
+          PROPID propID;\r
+          VARTYPE varType;\r
+          \r
+          if (_folder->GetPropertyInfo(i, &name, &propID, &varType) != S_OK)\r
+            continue;\r
+          \r
+          NCOM::CPropVariant prop;\r
+          if (_folder->GetProperty(index, propID, &prop) != S_OK)\r
+            continue;\r
+          AddPropertyString(propID, name, prop, message);\r
+        }\r
+      }\r
+      message += kSeparator;\r
+    }\r
+        \r
+    /*\r
+    message += LangString(IDS_PROP_FILE_TYPE, 0x02000214);\r
+    message += kPropValueSeparator;\r
+    message += GetFolderTypeID();\r
+    message += L"\n";\r
+    */\r
+\r
+    {\r
+      NCOM::CPropVariant prop;\r
+      if (_folder->GetFolderProperty(kpidPath, &prop) == S_OK)\r
+      {\r
+        AddPropertyString(kpidName, L"Path", prop, message);\r
+      }\r
+    }\r
+\r
+    CMyComPtr<IFolderProperties> folderProperties;\r
+    _folder.QueryInterface(IID_IFolderProperties, &folderProperties);\r
+    if (folderProperties)\r
+    {\r
+      UInt32 numProps;\r
+      if (folderProperties->GetNumberOfFolderProperties(&numProps) == S_OK)\r
+      {\r
+        for (UInt32 i = 0; i < numProps; i++)\r
+        {\r
+          CMyComBSTR name;\r
+          PROPID propID;\r
+          VARTYPE vt;\r
+          if (folderProperties->GetFolderPropertyInfo(i, &name, &propID, &vt) != S_OK)\r
+            continue;\r
+          NCOM::CPropVariant prop;\r
+          if (_folder->GetFolderProperty(propID, &prop) != S_OK)\r
+            continue;\r
+          AddPropertyString(propID, name, prop, message);\r
+        }\r
+      }\r
+    }\r
+\r
+    CMyComPtr<IGetFolderArcProps> getFolderArcProps;\r
+    _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps);\r
+    if (getFolderArcProps)\r
+    {\r
+      CMyComPtr<IFolderArcProps> getProps;\r
+      getFolderArcProps->GetFolderArcProps(&getProps);\r
+      if (getProps)\r
+      {\r
+        UInt32 numLevels;\r
+        if (getProps->GetArcNumLevels(&numLevels) != S_OK)\r
+          numLevels = 0;\r
+        for (UInt32 level2 = 0; level2 < numLevels; level2++)\r
+        {\r
+          {\r
+            UInt32 level = numLevels - 1 - level2;\r
+            UInt32 numProps;\r
+            if (getProps->GetArcNumProps(level, &numProps) == S_OK)\r
+            {\r
+              message += kSeparator;\r
+              for (Int32 i = -3; i < (Int32)numProps; i++)\r
+              {\r
+                CMyComBSTR name;\r
+                PROPID propID;\r
+                VARTYPE vt;\r
+                switch (i)\r
+                {\r
+                  case -3: propID = kpidPath; break;\r
+                  case -2: propID = kpidType; break;\r
+                  case -1: propID = kpidError; break;\r
+                  default:\r
+                    if (getProps->GetArcPropInfo(level, i, &name, &propID, &vt) != S_OK)\r
+                      continue;\r
+                }\r
+                NCOM::CPropVariant prop;\r
+                if (getProps->GetArcProp(level, propID, &prop) != S_OK)\r
+                  continue;\r
+                AddPropertyString(propID, name, prop, message);\r
+              }\r
+            }\r
+          }\r
+          if (level2 != numLevels - 1)\r
+          {\r
+            UInt32 level = numLevels - 1 - level2;\r
+            UInt32 numProps;\r
+            if (getProps->GetArcNumProps2(level, &numProps) == S_OK)\r
+            {\r
+              message += kSeparatorSmall;\r
+              for (Int32 i = 0; i < (Int32)numProps; i++)\r
+              {\r
+                CMyComBSTR name;\r
+                PROPID propID;\r
+                VARTYPE vt;\r
+                if (getProps->GetArcPropInfo2(level, i, &name, &propID, &vt) != S_OK)\r
+                  continue;\r
+                NCOM::CPropVariant prop;\r
+                if (getProps->GetArcProp2(level, propID, &prop) != S_OK)\r
+                  continue;\r
+                AddPropertyString(propID, name, prop, message);\r
+              }\r
+            }\r
+          }\r
+        }\r
+      }\r
+    }\r
+    ::MessageBoxW(*(this), message, LangString(IDS_PROPERTIES, 0x03020900), MB_OK);\r
+  }\r
+}\r
+\r
+void CPanel::EditCut()\r
+{\r
+  // InvokeSystemCommand("cut");\r
+}\r
+\r
+void CPanel::EditCopy()\r
+{\r
+  /*\r
+  CMyComPtr<IGetFolderArcProps> getFolderArcProps;\r
+  _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps);\r
+  if (!getFolderArcProps)\r
+  {\r
+    InvokeSystemCommand("copy");\r
+    return;\r
+  }\r
+  */\r
+  UString s;\r
+  CRecordVector<UInt32> indices;\r
+  GetSelectedItemsIndices(indices);\r
+  for (int i = 0; i < indices.Size(); i++)\r
+  {\r
+    if (i > 0)\r
+      s += L"\xD\n";\r
+    s += GetItemName(indices[i]);\r
+  }\r
+  ClipboardSetText(_mainWindow, s);\r
+}\r
+\r
+void CPanel::EditPaste()\r
+{\r
+  /*\r
+  UStringVector names;\r
+  ClipboardGetFileNames(names);\r
+  CopyFromNoAsk(names);\r
+  UString s;\r
+  for (int i = 0; i < names.Size(); i++)\r
+  {\r
+    s += L" ";\r
+    s += names[i];\r
+  }\r
+\r
+  MessageBoxW(0, s, L"", 0);\r
+  */\r
+\r
+  // InvokeSystemCommand("paste");\r
+}\r
+\r
+HRESULT CPanel::CreateShellContextMenu(\r
+    const CRecordVector<UInt32> &operatedIndices,\r
+    CMyComPtr<IContextMenu> &systemContextMenu)\r
+{\r
+  systemContextMenu.Release();\r
+  UString folderPath = GetFsPath();\r
+\r
+  CMyComPtr<IShellFolder> desktopFolder;\r
+  RINOK(::SHGetDesktopFolder(&desktopFolder));\r
+  if (!desktopFolder)\r
+  {\r
+    // ShowMessage("Failed to get Desktop folder.");\r
+    return E_FAIL;\r
+  }\r
+  \r
+  // Separate the file from the folder.\r
+\r
+  \r
+  // Get a pidl for the folder the file\r
+  // is located in.\r
+  LPITEMIDLIST parentPidl;\r
+  DWORD eaten;\r
+  RINOK(desktopFolder->ParseDisplayName(\r
+      GetParent(), 0, (wchar_t *)(const wchar_t *)folderPath,\r
+      &eaten, &parentPidl, 0));\r
+  \r
+  // Get an IShellFolder for the folder\r
+  // the file is located in.\r
+  CMyComPtr<IShellFolder> parentFolder;\r
+  RINOK(desktopFolder->BindToObject(parentPidl,\r
+      0, IID_IShellFolder, (void**)&parentFolder));\r
+  if (!parentFolder)\r
+  {\r
+    // ShowMessage("Invalid file name.");\r
+    return E_FAIL;\r
+  }\r
+  \r
+  // Get a pidl for the file itself.\r
+  CRecordVector<LPITEMIDLIST> pidls;\r
+  pidls.Reserve(operatedIndices.Size());\r
+  for (int i = 0; i < operatedIndices.Size(); i++)\r
+  {\r
+    LPITEMIDLIST pidl;\r
+    UString fileName = GetItemRelPath(operatedIndices[i]);\r
+    if (IsFSDrivesFolder())\r
+      fileName += WCHAR_PATH_SEPARATOR;\r
+    RINOK(parentFolder->ParseDisplayName(GetParent(), 0,\r
+      (wchar_t *)(const wchar_t *)fileName, &eaten, &pidl, 0));\r
+    pidls.Add(pidl);\r
+  }\r
+\r
+  ITEMIDLIST temp;\r
+  if (pidls.Size() == 0)\r
+  {\r
+    temp.mkid.cb = 0;\r
+    /*\r
+    LPITEMIDLIST pidl;\r
+    HRESULT result = parentFolder->ParseDisplayName(GetParent(), 0,\r
+      L"." WSTRING_PATH_SEPARATOR, &eaten, &pidl, 0);\r
+    if (result != NOERROR)\r
+      return;\r
+    */\r
+    pidls.Add(&temp);\r
+  }\r
+\r
+  // Get the IContextMenu for the file.\r
+  CMyComPtr<IContextMenu> cm;\r
+  RINOK( parentFolder->GetUIObjectOf(GetParent(), pidls.Size(),\r
+      (LPCITEMIDLIST *)&pidls.Front(), IID_IContextMenu, 0, (void**)&cm));\r
+  if (!cm)\r
+  {\r
+    // ShowMessage("Unable to get context menu interface.");\r
+    return E_FAIL;\r
+  }\r
+  systemContextMenu = cm;\r
+  return S_OK;\r
+}\r
+\r
+void CPanel::CreateSystemMenu(HMENU menuSpec,\r
+    const CRecordVector<UInt32> &operatedIndices,\r
+    CMyComPtr<IContextMenu> &systemContextMenu)\r
+{\r
+  systemContextMenu.Release();\r
+\r
+  CreateShellContextMenu(operatedIndices, systemContextMenu);\r
+\r
+  if (systemContextMenu == 0)\r
+    return;\r
+  \r
+  // Set up a CMINVOKECOMMANDINFO structure.\r
+  CMINVOKECOMMANDINFO ci;\r
+  ZeroMemory(&ci, sizeof(ci));\r
+  ci.cbSize = sizeof(CMINVOKECOMMANDINFO);\r
+  ci.hwnd = GetParent();\r
+  \r
+  /*\r
+  if (Sender == GoBtn)\r
+  {\r
+    // Verbs that can be used are cut, paste,\r
+    // properties, delete, and so on.\r
+    String action;\r
+    if (CutRb->Checked)\r
+      action = "cut";\r
+    else if (CopyRb->Checked)\r
+      action = "copy";\r
+    else if (DeleteRb->Checked)\r
+      action = "delete";\r
+    else if (PropertiesRb->Checked)\r
+      action = "properties";\r
+    \r
+    ci.lpVerb = action.c_str();\r
+    result = cm->InvokeCommand(&ci);\r
+    if (result)\r
+      ShowMessage(\r
+      "Error copying file to clipboard.");\r
+    \r
+  }\r
+  else\r
+  */\r
+  {\r
+    // HMENU hMenu = CreatePopupMenu();\r
+    CMenu popupMenu;\r
+    // CMenuDestroyer menuDestroyer(popupMenu);\r
+    if(!popupMenu.CreatePopup())\r
+      throw 210503;\r
+\r
+    HMENU hMenu = popupMenu;\r
+\r
+    DWORD Flags = CMF_EXPLORE;\r
+    // Optionally the shell will show the extended\r
+    // context menu on some operating systems when\r
+    // the shift key is held down at the time the\r
+    // context menu is invoked. The following is\r
+    // commented out but you can uncommnent this\r
+    // line to show the extended context menu.\r
+    // Flags |= 0x00000080;\r
+    systemContextMenu->QueryContextMenu(hMenu, 0, kSystemStartMenuID, 0x7FFF, Flags);\r
+    \r
+\r
+    {\r
+      CMenu menu;\r
+      menu.Attach(menuSpec);\r
+      CMenuItem menuItem;\r
+      menuItem.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID;\r
+      menuItem.fType = MFT_STRING;\r
+      menuItem.hSubMenu = popupMenu.Detach();\r
+      // menuDestroyer.Disable();\r
+      menuItem.StringValue = LangString(IDS_SYSTEM, 0x030202A0);\r
+      menu.InsertItem(0, true, menuItem);\r
+    }\r
+    /*\r
+    if (Cmd < 100 && Cmd != 0)\r
+    {\r
+      ci.lpVerb = MAKEINTRESOURCE(Cmd - 1);\r
+      ci.lpParameters = "";\r
+      ci.lpDirectory = "";\r
+      ci.nShow = SW_SHOWNORMAL;\r
+      cm->InvokeCommand(&ci);\r
+    }\r
+    // If Cmd is > 100 then it's one of our\r
+    // inserted menu items.\r
+    else\r
+      // Find the menu item.\r
+      for (int i = 0; i < popupMenu1->Items->Count; i++)\r
+      {\r
+        TMenuItem* menu = popupMenu1->Items->Items[i];\r
+        // Call its OnClick handler.\r
+        if (menu->Command == Cmd - 100)\r
+          menu->OnClick(this);\r
+      }\r
+      // Release the memory allocated for the menu.\r
+      DestroyMenu(hMenu);\r
+    */\r
+  }\r
+}\r
+\r
+void CPanel::CreateFileMenu(HMENU menuSpec)\r
+{\r
+  CreateFileMenu(menuSpec, _sevenZipContextMenu, _systemContextMenu, true);\r
+}\r
+\r
+void CPanel::CreateSevenZipMenu(HMENU menuSpec,\r
+    const CRecordVector<UInt32> &operatedIndices,\r
+    CMyComPtr<IContextMenu> &sevenZipContextMenu)\r
+{\r
+  sevenZipContextMenu.Release();\r
+\r
+  CMenu menu;\r
+  menu.Attach(menuSpec);\r
+  // CMenuDestroyer menuDestroyer(menu);\r
+  // menu.CreatePopup();\r
+\r
+  bool sevenZipMenuCreated = false;\r
+\r
+  CZipContextMenu *contextMenuSpec = new CZipContextMenu;\r
+  CMyComPtr<IContextMenu> contextMenu = contextMenuSpec;\r
+  // if (contextMenu.CoCreateInstance(CLSID_CZipContextMenu, IID_IContextMenu) == S_OK)\r
+  {\r
+    /*\r
+    CMyComPtr<IInitContextMenu> initContextMenu;\r
+    if (contextMenu.QueryInterface(IID_IInitContextMenu, &initContextMenu) != S_OK)\r
+      return;\r
+    */\r
+    UString currentFolderUnicode = _currentFolderPrefix;\r
+    UStringVector names;\r
+    int i;\r
+    for(i = 0; i < operatedIndices.Size(); i++)\r
+      names.Add(currentFolderUnicode + GetItemRelPath(operatedIndices[i]));\r
+    CRecordVector<const wchar_t *> namePointers;\r
+    for(i = 0; i < operatedIndices.Size(); i++)\r
+      namePointers.Add(names[i]);\r
+    \r
+    // NFile::NDirectory::MySetCurrentDirectory(currentFolderUnicode);\r
+    if (contextMenuSpec->InitContextMenu(currentFolderUnicode, &namePointers.Front(),\r
+        operatedIndices.Size()) == S_OK)\r
+    {\r
+      HRESULT res = contextMenu->QueryContextMenu(menu, 0, kSevenZipStartMenuID,\r
+          kSystemStartMenuID - 1, 0);\r
+      sevenZipMenuCreated = (HRESULT_SEVERITY(res) == SEVERITY_SUCCESS);\r
+      if (sevenZipMenuCreated)\r
+        sevenZipContextMenu = contextMenu;\r
+      // int code = HRESULT_CODE(res);\r
+      // int nextItemID = code;\r
+    }\r
+  }\r
+}\r
+\r
+void CPanel::CreateFileMenu(HMENU menuSpec,\r
+    CMyComPtr<IContextMenu> &sevenZipContextMenu,\r
+    CMyComPtr<IContextMenu> &systemContextMenu,\r
+    bool programMenu)\r
+{\r
+  sevenZipContextMenu.Release();\r
+  systemContextMenu.Release();\r
+\r
+  CRecordVector<UInt32> operatedIndices;\r
+  GetOperatedItemIndices(operatedIndices);\r
+\r
+  CMenu menu;\r
+  menu.Attach(menuSpec);\r
+  \r
+  CreateSevenZipMenu(menu, operatedIndices, sevenZipContextMenu);\r
+  if (g_App.ShowSystemMenu)\r
+    CreateSystemMenu(menu, operatedIndices, systemContextMenu);\r
+\r
+  /*\r
+  if (menu.GetItemCount() > 0)\r
+    menu.AppendItem(MF_SEPARATOR, 0, (LPCTSTR)0);\r
+  */\r
+\r
+  int i;\r
+  for (i = 0; i < operatedIndices.Size(); i++)\r
+    if (IsItemFolder(operatedIndices[i]))\r
+      break;\r
+  bool allAreFiles = (i == operatedIndices.Size());\r
+  LoadFileMenu(menu, menu.GetItemCount(), programMenu,\r
+      IsFSFolder(), operatedIndices.Size(), allAreFiles);\r
+}\r
+\r
+bool CPanel::InvokePluginCommand(int id)\r
+{\r
+  return InvokePluginCommand(id, _sevenZipContextMenu, _systemContextMenu);\r
+}\r
+\r
+bool CPanel::InvokePluginCommand(int id,\r
+    IContextMenu *sevenZipContextMenu, IContextMenu *systemContextMenu)\r
+{\r
+  UInt32 offset;\r
+  bool isSystemMenu = (id >= kSystemStartMenuID);\r
+  if (isSystemMenu)\r
+    offset = id  - kSystemStartMenuID;\r
+  else\r
+    offset = id  - kSevenZipStartMenuID;\r
+\r
+  #ifdef UNDER_CE\r
+  CMINVOKECOMMANDINFO\r
+  #else\r
+  CMINVOKECOMMANDINFOEX\r
+  #endif\r
+    commandInfo;\r
+  commandInfo.cbSize = sizeof(commandInfo);\r
+  commandInfo.fMask = 0\r
+  #ifndef UNDER_CE\r
+  | CMIC_MASK_UNICODE\r
+  #endif\r
+  ;\r
+  commandInfo.hwnd = GetParent();\r
+  commandInfo.lpVerb = (LPCSTR)(MAKEINTRESOURCE(offset));\r
+  commandInfo.lpParameters = NULL;\r
+  CSysString currentFolderSys = GetSystemString(_currentFolderPrefix);\r
+  commandInfo.lpDirectory = (LPCSTR)(LPCTSTR)(currentFolderSys);\r
+  commandInfo.nShow = SW_SHOW;\r
+  commandInfo.lpParameters = NULL;\r
+  #ifndef UNDER_CE\r
+  commandInfo.lpTitle = "";\r
+  commandInfo.lpVerbW = (LPCWSTR)(MAKEINTRESOURCEW(offset));\r
+  UString currentFolderUnicode = _currentFolderPrefix;\r
+  commandInfo.lpDirectoryW = currentFolderUnicode;\r
+  commandInfo.lpTitleW = L"";\r
+  // commandInfo.ptInvoke.x = xPos;\r
+  // commandInfo.ptInvoke.y = yPos;\r
+  commandInfo.ptInvoke.x = 0;\r
+  commandInfo.ptInvoke.y = 0;\r
+  #endif\r
+  HRESULT result;\r
+  if (isSystemMenu)\r
+    result = systemContextMenu->InvokeCommand(LPCMINVOKECOMMANDINFO(&commandInfo));\r
+  else\r
+    result = sevenZipContextMenu->InvokeCommand(LPCMINVOKECOMMANDINFO(&commandInfo));\r
+  if (result == NOERROR)\r
+  {\r
+    KillSelection();\r
+    return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+bool CPanel::OnContextMenu(HANDLE windowHandle, int xPos, int yPos)\r
+{\r
+  if (::GetParent((HWND)windowHandle) == _listView)\r
+  {\r
+    ShowColumnsContextMenu(xPos, yPos);\r
+    return true;\r
+  }\r
+\r
+  if (windowHandle != _listView)\r
+    return false;\r
+  /*\r
+  POINT point;\r
+  point.x = xPos;\r
+  point.y = yPos;\r
+  if (!_listView.ScreenToClient(&point))\r
+    return false;\r
+\r
+  LVHITTESTINFO info;\r
+  info.pt = point;\r
+  int index = _listView.HitTest(&info);\r
+  */\r
+\r
+  CRecordVector<UInt32> operatedIndices;\r
+  GetOperatedItemIndices(operatedIndices);\r
+\r
+  if (xPos < 0 || yPos < 0)\r
+  {\r
+    if (operatedIndices.Size() == 0)\r
+    {\r
+      xPos = 0;\r
+      yPos = 0;\r
+    }\r
+    else\r
+    {\r
+      int itemIndex = _listView.GetNextItem(-1, LVNI_FOCUSED);\r
+      if (itemIndex == -1)\r
+        return false;\r
+      RECT rect;\r
+      if (!_listView.GetItemRect(itemIndex, &rect, LVIR_ICON))\r
+        return false;\r
+      xPos = (rect.left + rect.right) / 2;\r
+      yPos = (rect.top + rect.bottom) / 2;\r
+    }\r
+    POINT point = {xPos, yPos};\r
+    _listView.ClientToScreen(&point);\r
+    xPos = point.x;\r
+    yPos = point.y;\r
+  }\r
+\r
+  CMenu menu;\r
+  CMenuDestroyer menuDestroyer(menu);\r
+  menu.CreatePopup();\r
+\r
+  CMyComPtr<IContextMenu> sevenZipContextMenu;\r
+  CMyComPtr<IContextMenu> systemContextMenu;\r
+  CreateFileMenu(menu, sevenZipContextMenu, systemContextMenu, false);\r
+\r
+  int result = menu.Track(TPM_LEFTALIGN\r
+      #ifndef UNDER_CE\r
+      | TPM_RIGHTBUTTON\r
+      #endif\r
+      | TPM_RETURNCMD | TPM_NONOTIFY,\r
+    xPos, yPos, _listView);\r
+\r
+  if (result == 0)\r
+    return true;\r
+\r
+  if (result >= kPluginMenuStartID)\r
+  {\r
+    InvokePluginCommand(result, sevenZipContextMenu, systemContextMenu);\r
+    return true;\r
+  }\r
+  if (ExecuteFileCommand(result))\r
+    return true;\r
+  return true;\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/PanelOperations.cpp b/CPP/7zip/UI/FileManager/PanelOperations.cpp
new file mode 100755 (executable)
index 0000000..864f952
--- /dev/null
@@ -0,0 +1,465 @@
+// PanelOperations.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/DynamicBuffer.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/COM.h"\r
+#include "Windows/FileDir.h"\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/ResourceString.h"\r
+#include "Windows/Thread.h"\r
+\r
+#include "ComboDialog.h"\r
+\r
+#include "FSFolder.h"\r
+#include "FormatUtils.h"\r
+#include "LangUtils.h"\r
+#include "Panel.h"\r
+#include "UpdateCallback100.h"\r
+\r
+#include "resource.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+enum EFolderOpType\r
+{\r
+  FOLDER_TYPE_CREATE_FOLDER = 0,\r
+  FOLDER_TYPE_DELETE = 1,\r
+  FOLDER_TYPE_RENAME = 2\r
+};\r
+\r
+class CThreadFolderOperations: public CProgressThreadVirt\r
+{\r
+  HRESULT ProcessVirt();\r
+public:\r
+  EFolderOpType OpType;\r
+  UString Name;\r
+  UInt32 Index;\r
+  CRecordVector<UInt32> Indices;\r
+\r
+  CMyComPtr<IFolderOperations> FolderOperations;\r
+  CMyComPtr<IProgress> UpdateCallback;\r
+  CUpdateCallback100Imp *UpdateCallbackSpec;\r
+  \r
+  HRESULT Result;\r
+\r
+  CThreadFolderOperations(EFolderOpType opType): OpType(opType), Result(E_FAIL) {}\r
+  HRESULT DoOperation(CPanel &panel, const UString &progressTitle, const UString &titleError);\r
+};\r
+  \r
+HRESULT CThreadFolderOperations::ProcessVirt()\r
+{\r
+  NCOM::CComInitializer comInitializer;\r
+  switch(OpType)\r
+  {\r
+    case FOLDER_TYPE_CREATE_FOLDER:\r
+      Result = FolderOperations->CreateFolder(Name, UpdateCallback);\r
+      break;\r
+    case FOLDER_TYPE_DELETE:\r
+      Result = FolderOperations->Delete(&Indices.Front(), Indices.Size(), UpdateCallback);\r
+      break;\r
+    case FOLDER_TYPE_RENAME:\r
+      Result = FolderOperations->Rename(Index, Name, UpdateCallback);\r
+      break;\r
+    default:\r
+      Result = E_FAIL;\r
+  }\r
+  return Result;\r
+}\r
+\r
+\r
+HRESULT CThreadFolderOperations::DoOperation(CPanel &panel, const UString &progressTitle, const UString &titleError)\r
+{\r
+  UpdateCallbackSpec = new CUpdateCallback100Imp;\r
+  UpdateCallback = UpdateCallbackSpec;\r
+  UpdateCallbackSpec->ProgressDialog = &ProgressDialog;\r
+\r
+  ProgressDialog.WaitMode = true;\r
+  ProgressDialog.Sync.SetErrorMessageTitle(titleError);\r
+  Result = S_OK;\r
+\r
+  bool usePassword = false;\r
+  UString password;\r
+  if (panel._parentFolders.Size() > 0)\r
+  {\r
+    const CFolderLink &fl = panel._parentFolders.Back();\r
+    usePassword = fl.UsePassword;\r
+    password = fl.Password;\r
+  }\r
+\r
+  UpdateCallbackSpec->Init(usePassword, password);\r
+\r
+  ProgressDialog.MainWindow = panel._mainWindow; // panel.GetParent()\r
+  ProgressDialog.MainTitle = LangString(IDS_APP_TITLE, 0x03000000);\r
+  ProgressDialog.MainAddTitle = progressTitle + UString(L" ");\r
+\r
+  RINOK(Create(progressTitle, ProgressDialog.MainWindow));\r
+  return Result;\r
+}\r
+\r
+#ifndef _UNICODE\r
+typedef int (WINAPI * SHFileOperationWP)(LPSHFILEOPSTRUCTW lpFileOp);\r
+#endif\r
+\r
+void CPanel::DeleteItems(bool toRecycleBin)\r
+{\r
+  CPanel::CDisableTimerProcessing disableTimerProcessing2(*this);\r
+  CRecordVector<UInt32> indices;\r
+  GetOperatedItemIndices(indices);\r
+  if (indices.IsEmpty())\r
+    return;\r
+  CSelectedState state;\r
+  SaveSelectedState(state);\r
+\r
+  #ifndef UNDER_CE\r
+  // WM6 / SHFileOperationW doesn't ask user! So we use internal delete\r
+  bool useInternalDelete = false;\r
+  if (IsFSFolder() && toRecycleBin)\r
+  {\r
+    #ifndef _UNICODE\r
+    if (!g_IsNT)\r
+    {\r
+      CDynamicBuffer<CHAR> buffer;\r
+      size_t size = 0;\r
+      for (int i = 0; i < indices.Size(); i++)\r
+      {\r
+        const AString path = GetSystemString(GetFsPath() + GetItemRelPath(indices[i]));\r
+        buffer.EnsureCapacity(size + path.Length() + 1);\r
+        memmove(((CHAR *)buffer) + size, (const CHAR *)path, (path.Length() + 1) * sizeof(CHAR));\r
+        size += path.Length() + 1;\r
+      }\r
+      buffer.EnsureCapacity(size + 1);\r
+      ((CHAR *)buffer)[size]  = 0;\r
+      SHFILEOPSTRUCTA fo;\r
+      fo.hwnd = GetParent();\r
+      fo.wFunc = FO_DELETE;\r
+      fo.pFrom = (const CHAR *)buffer;\r
+      fo.pTo = 0;\r
+      fo.fFlags = 0;\r
+      if (toRecycleBin)\r
+        fo.fFlags |= FOF_ALLOWUNDO;\r
+      // fo.fFlags |= FOF_NOCONFIRMATION;\r
+      // fo.fFlags |= FOF_NOERRORUI;\r
+      // fo.fFlags |= FOF_SILENT;\r
+      // fo.fFlags |= FOF_WANTNUKEWARNING;\r
+      fo.fAnyOperationsAborted = FALSE;\r
+      fo.hNameMappings = 0;\r
+      fo.lpszProgressTitle = 0;\r
+      /* int res = */ ::SHFileOperationA(&fo);\r
+    }\r
+    else\r
+    #endif\r
+    {\r
+      CDynamicBuffer<WCHAR> buffer;\r
+      size_t size = 0;\r
+      int maxLen = 0;\r
+      for (int i = 0; i < indices.Size(); i++)\r
+      {\r
+        // L"\\\\?\\") doesn't work here.\r
+        const UString path = GetFsPath() + GetItemRelPath(indices[i]);\r
+        if (path.Length() > maxLen)\r
+          maxLen = path.Length();\r
+        buffer.EnsureCapacity(size + path.Length() + 1);\r
+        memmove(((WCHAR *)buffer) + size, (const WCHAR *)path, (path.Length() + 1) * sizeof(WCHAR));\r
+        size += path.Length() + 1;\r
+      }\r
+      buffer.EnsureCapacity(size + 1);\r
+      ((WCHAR *)buffer)[size] = 0;\r
+      if (maxLen >= MAX_PATH)\r
+      {\r
+        if (toRecycleBin)\r
+        {\r
+          MessageBoxErrorLang(IDS_ERROR_LONG_PATH_TO_RECYCLE, 0x03020218);\r
+          return;\r
+        }\r
+        useInternalDelete = true;\r
+      }\r
+      else\r
+      {\r
+        SHFILEOPSTRUCTW fo;\r
+        fo.hwnd = GetParent();\r
+        fo.wFunc = FO_DELETE;\r
+        fo.pFrom = (const WCHAR *)buffer;\r
+        fo.pTo = 0;\r
+        fo.fFlags = 0;\r
+        if (toRecycleBin)\r
+          fo.fFlags |= FOF_ALLOWUNDO;\r
+        fo.fAnyOperationsAborted = FALSE;\r
+        fo.hNameMappings = 0;\r
+        fo.lpszProgressTitle = 0;\r
+        int res;\r
+        #ifdef _UNICODE\r
+        res = ::SHFileOperationW(&fo);\r
+        #else\r
+        SHFileOperationWP shFileOperationW = (SHFileOperationWP)\r
+          ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHFileOperationW");\r
+        if (shFileOperationW == 0)\r
+          return;\r
+        res = shFileOperationW(&fo);\r
+        #endif\r
+      }\r
+    }\r
+    /*\r
+    if (fo.fAnyOperationsAborted)\r
+      MessageBoxError(result, LangString(IDS_ERROR_DELETING, 0x03020217));\r
+    */\r
+  }\r
+  else\r
+    useInternalDelete = true;\r
+  if (useInternalDelete)\r
+  #endif\r
+    DeleteItemsInternal(indices);\r
+  RefreshListCtrl(state);\r
+}\r
+\r
+void CPanel::MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID, UInt32 langID)\r
+{\r
+  if (errorCode == E_NOINTERFACE)\r
+    MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);\r
+  else\r
+    MessageBoxError(errorCode, LangString(resourceID, langID));\r
+}\r
+\r
+void CPanel::DeleteItemsInternal(CRecordVector<UInt32> &indices)\r
+{\r
+  CMyComPtr<IFolderOperations> folderOperations;\r
+  if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)\r
+  {\r
+    MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_ERROR_DELETING, 0x03020217);\r
+    return;\r
+  }\r
+\r
+  UString title;\r
+  UString message;\r
+  if (indices.Size() == 1)\r
+  {\r
+    int index = indices[0];\r
+    const UString itemName = GetItemRelPath(index);\r
+    if (IsItemFolder(index))\r
+    {\r
+      title = LangString(IDS_CONFIRM_FOLDER_DELETE, 0x03020211);\r
+      message = MyFormatNew(IDS_WANT_TO_DELETE_FOLDER, 0x03020214, itemName);\r
+    }\r
+    else\r
+    {\r
+      title = LangString(IDS_CONFIRM_FILE_DELETE, 0x03020210);\r
+      message = MyFormatNew(IDS_WANT_TO_DELETE_FILE, 0x03020213, itemName);\r
+    }\r
+  }\r
+  else\r
+  {\r
+    title = LangString(IDS_CONFIRM_ITEMS_DELETE, 0x03020212);\r
+    message = MyFormatNew(IDS_WANT_TO_DELETE_ITEMS, 0x03020215,\r
+        NumberToString(indices.Size()));\r
+  }\r
+  if (::MessageBoxW(GetParent(), message, title, MB_OKCANCEL | MB_ICONQUESTION) != IDOK)\r
+    return;\r
+\r
+  {\r
+    CThreadFolderOperations op(FOLDER_TYPE_DELETE);\r
+    op.FolderOperations = folderOperations;\r
+    op.Indices = indices;\r
+    op.DoOperation(*this,\r
+        LangString(IDS_DELETING, 0x03020216),\r
+        LangString(IDS_ERROR_DELETING, 0x03020217));\r
+  }\r
+  RefreshTitleAlways();\r
+}\r
+\r
+BOOL CPanel::OnBeginLabelEdit(LV_DISPINFOW * lpnmh)\r
+{\r
+  int realIndex = GetRealIndex(lpnmh->item);\r
+  if (realIndex == kParentIndex)\r
+    return TRUE;\r
+  CMyComPtr<IFolderOperations> folderOperations;\r
+  if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)\r
+    return TRUE;\r
+  return FALSE;\r
+}\r
+\r
+BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh)\r
+{\r
+  if (lpnmh->item.pszText == NULL)\r
+    return FALSE;\r
+  CMyComPtr<IFolderOperations> folderOperations;\r
+  if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)\r
+  {\r
+    MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_ERROR_RENAMING, 0x03020221);\r
+    return FALSE;\r
+  }\r
+  const UString newName = lpnmh->item.pszText;\r
+  CPanel::CDisableTimerProcessing disableTimerProcessing2(*this);\r
+\r
+  SaveSelectedState(_selectedState);\r
+\r
+  int realIndex = GetRealIndex(lpnmh->item);\r
+  if (realIndex == kParentIndex)\r
+    return FALSE;\r
+  const UString prefix = GetItemPrefix(realIndex);\r
+\r
+\r
+  {\r
+    CThreadFolderOperations op(FOLDER_TYPE_RENAME);\r
+    op.FolderOperations = folderOperations;\r
+    op.Index = realIndex;\r
+    op.Name = newName;\r
+    HRESULT res = op.DoOperation(*this,\r
+        LangString(IDS_RENAMING, 0x03020220),\r
+        LangString(IDS_ERROR_RENAMING, 0x03020221));\r
+    if (res != S_OK)\r
+      return FALSE;\r
+  }\r
+\r
+  // Can't use RefreshListCtrl here.\r
+  // RefreshListCtrlSaveFocused();\r
+  _selectedState.FocusedName = prefix + newName;\r
+  _selectedState.SelectFocused = true;\r
+\r
+  // We need clear all items to disable GetText before Reload:\r
+  // number of items can change.\r
+  // _listView.DeleteAllItems();\r
+  // But seems it can still call GetText (maybe for current item)\r
+  // so we can't delete items.\r
+\r
+  _dontShowMode = true;\r
+\r
+  PostMessage(kReLoadMessage);\r
+  return TRUE;\r
+}\r
+\r
+void CPanel::CreateFolder()\r
+{\r
+  CMyComPtr<IFolderOperations> folderOperations;\r
+  if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)\r
+  {\r
+    MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_CREATE_FOLDER_ERROR, 0x03020233);\r
+    return;\r
+  }\r
+  CPanel::CDisableTimerProcessing disableTimerProcessing2(*this);\r
+  CSelectedState state;\r
+  SaveSelectedState(state);\r
+  CComboDialog comboDialog;\r
+  comboDialog.Title = LangString(IDS_CREATE_FOLDER, 0x03020230);\r
+  comboDialog.Static = LangString(IDS_CREATE_FOLDER_NAME, 0x03020231);\r
+  comboDialog.Value = LangString(IDS_CREATE_FOLDER_DEFAULT_NAME, /*0x03020232*/ (UInt32)-1);\r
+  if (comboDialog.Create(GetParent()) == IDCANCEL)\r
+    return;\r
+  \r
+  UString newName = comboDialog.Value;\r
+  \r
+  {\r
+    CThreadFolderOperations op(FOLDER_TYPE_CREATE_FOLDER);\r
+    op.FolderOperations = folderOperations;\r
+    op.Name = newName;\r
+    HRESULT res = op.DoOperation(*this,\r
+        LangString(IDS_CREATE_FOLDER, 0x03020230),\r
+        LangString(IDS_CREATE_FOLDER_ERROR, 0x03020233));\r
+    if (res != S_OK)\r
+      return;\r
+  }\r
+  int pos = newName.Find(WCHAR_PATH_SEPARATOR);\r
+  if (pos >= 0)\r
+    newName = newName.Left(pos);\r
+  if (!_mySelectMode)\r
+    state.SelectedNames.Clear();\r
+  state.FocusedName = newName;\r
+  state.SelectFocused = true;\r
+  RefreshTitleAlways();\r
+  RefreshListCtrl(state);\r
+}\r
+\r
+void CPanel::CreateFile()\r
+{\r
+  CMyComPtr<IFolderOperations> folderOperations;\r
+  if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)\r
+  {\r
+    MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_CREATE_FILE_ERROR, 0x03020243);\r
+    return;\r
+  }\r
+  CPanel::CDisableTimerProcessing disableTimerProcessing2(*this);\r
+  CSelectedState state;\r
+  SaveSelectedState(state);\r
+  CComboDialog comboDialog;\r
+  comboDialog.Title = LangString(IDS_CREATE_FILE, 0x03020240);\r
+  comboDialog.Static = LangString(IDS_CREATE_FILE_NAME, 0x03020241);\r
+  comboDialog.Value = LangString(IDS_CREATE_FILE_DEFAULT_NAME, /*0x03020242*/ (UInt32)-1);\r
+  if (comboDialog.Create(GetParent()) == IDCANCEL)\r
+    return;\r
+  UString newName = comboDialog.Value;\r
+  HRESULT result = folderOperations->CreateFile(newName, 0);\r
+  if (result != S_OK)\r
+  {\r
+    MessageBoxErrorForUpdate(result, IDS_CREATE_FILE_ERROR, 0x03020243);\r
+    return;\r
+  }\r
+  int pos = newName.Find(WCHAR_PATH_SEPARATOR);\r
+  if (pos >= 0)\r
+    newName = newName.Left(pos);\r
+  if (!_mySelectMode)\r
+    state.SelectedNames.Clear();\r
+  state.FocusedName = newName;\r
+  state.SelectFocused = true;\r
+  RefreshListCtrl(state);\r
+}\r
+\r
+void CPanel::RenameFile()\r
+{\r
+  int index = _listView.GetFocusedItem();\r
+  if (index >= 0)\r
+    _listView.EditLabel(index);\r
+}\r
+\r
+void CPanel::ChangeComment()\r
+{\r
+  CPanel::CDisableTimerProcessing disableTimerProcessing2(*this);\r
+  int index = _listView.GetFocusedItem();\r
+  if (index < 0)\r
+    return;\r
+  int realIndex = GetRealItemIndex(index);\r
+  if (realIndex == kParentIndex)\r
+    return;\r
+  CSelectedState state;\r
+  SaveSelectedState(state);\r
+  CMyComPtr<IFolderOperations> folderOperations;\r
+  if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)\r
+  {\r
+    MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);\r
+    return;\r
+  }\r
+\r
+  UString comment;\r
+  {\r
+    NCOM::CPropVariant propVariant;\r
+    if (_folder->GetProperty(realIndex, kpidComment, &propVariant) != S_OK)\r
+      return;\r
+    if (propVariant.vt == VT_BSTR)\r
+      comment = propVariant.bstrVal;\r
+    else if (propVariant.vt != VT_EMPTY)\r
+      return;\r
+  }\r
+  UString name = GetItemRelPath(realIndex);\r
+  CComboDialog comboDialog;\r
+  comboDialog.Title = name + L" " + LangString(IDS_COMMENT, 0x03020290);\r
+  comboDialog.Value = comment;\r
+  comboDialog.Static = LangString(IDS_COMMENT2, 0x03020291);\r
+  if (comboDialog.Create(GetParent()) == IDCANCEL)\r
+    return;\r
+  NCOM::CPropVariant propVariant = comboDialog.Value;\r
+\r
+  HRESULT result = folderOperations->SetProperty(realIndex, kpidComment, &propVariant, NULL);\r
+  if (result != S_OK)\r
+  {\r
+    if (result == E_NOINTERFACE)\r
+      MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);\r
+    else\r
+      MessageBoxError(result, L"Set Comment Error");\r
+  }\r
+  RefreshListCtrl(state);\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/PanelSelect.cpp b/CPP/7zip/UI/FileManager/PanelSelect.cpp
new file mode 100755 (executable)
index 0000000..21e5a21
--- /dev/null
@@ -0,0 +1,306 @@
+// PanelSelect.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "resource.h"\r
+\r
+#include "Common/StringConvert.h"\r
+#include "Common/Wildcard.h"\r
+\r
+#include "Panel.h"\r
+\r
+#include "ComboDialog.h"\r
+\r
+#include "LangUtils.h"\r
+\r
+void CPanel::OnShiftSelectMessage()\r
+{\r
+  if (!_mySelectMode)\r
+    return;\r
+  int focusedItem = _listView.GetFocusedItem();\r
+  if (focusedItem < 0)\r
+    return;\r
+  if (!_selectionIsDefined)\r
+    return;\r
+  int startItem = MyMin(focusedItem, _prevFocusedItem);\r
+  int finishItem = MyMax(focusedItem, _prevFocusedItem);\r
+  for (int i = 0; i < _listView.GetItemCount(); i++)\r
+  {\r
+    int realIndex = GetRealItemIndex(i);\r
+    if (realIndex == kParentIndex)\r
+      continue;\r
+    if (i >= startItem && i <= finishItem)\r
+      if (_selectedStatusVector[realIndex] != _selectMark)\r
+      {\r
+        _selectedStatusVector[realIndex] = _selectMark;\r
+        _listView.RedrawItem(i);\r
+      }\r
+  }\r
+  _prevFocusedItem = focusedItem;\r
+}\r
+\r
+void CPanel::OnArrowWithShift()\r
+{\r
+  if (!_mySelectMode)\r
+    return;\r
+  int focusedItem = _listView.GetFocusedItem();\r
+  if (focusedItem < 0)\r
+    return;\r
+  int realIndex = GetRealItemIndex(focusedItem);\r
+  if (_selectionIsDefined)\r
+  {\r
+    if (realIndex != kParentIndex)\r
+      _selectedStatusVector[realIndex] = _selectMark;\r
+  }\r
+  else\r
+  {\r
+    if (realIndex == kParentIndex)\r
+    {\r
+      _selectionIsDefined = true;\r
+      _selectMark = true;\r
+    }\r
+    else\r
+    {\r
+      _selectionIsDefined = true;\r
+      _selectMark = !_selectedStatusVector[realIndex];\r
+      _selectedStatusVector[realIndex] = _selectMark;\r
+    }\r
+  }\r
+  _prevFocusedItem = focusedItem;\r
+  PostMessage(kShiftSelectMessage);\r
+  _listView.RedrawItem(focusedItem);\r
+}\r
+\r
+void CPanel::OnInsert()\r
+{\r
+  /*\r
+  const int kState = CDIS_MARKED; // LVIS_DROPHILITED;\r
+  UINT state = (_listView.GetItemState(focusedItem, LVIS_CUT) == 0) ?\r
+      LVIS_CUT : 0;\r
+  _listView.SetItemState(focusedItem, state, LVIS_CUT);\r
+  // _listView.SetItemState(focusedItem, LVIS_SELECTED, LVIS_SELECTED);\r
+\r
+  */\r
+  int focusedItem = _listView.GetFocusedItem();\r
+  if (focusedItem < 0)\r
+    return;\r
+  int realIndex = GetRealItemIndex(focusedItem);\r
+  bool isSelected = !_selectedStatusVector[realIndex];\r
+  if (realIndex != kParentIndex)\r
+    _selectedStatusVector[realIndex] = isSelected;\r
+  \r
+  if (!_mySelectMode)\r
+    _listView.SetItemState(focusedItem, isSelected ? LVIS_SELECTED: 0, LVIS_SELECTED);\r
+\r
+  _listView.RedrawItem(focusedItem);\r
+\r
+  int nextIndex = focusedItem + 1;\r
+  if (nextIndex < _listView.GetItemCount())\r
+  {\r
+    _listView.SetItemState_FocusedSelected(nextIndex);\r
+    _listView.EnsureVisible(nextIndex, false);\r
+  }\r
+}\r
+\r
+/*\r
+void CPanel::OnUpWithShift()\r
+{\r
+  int focusedItem = _listView.GetFocusedItem();\r
+  if (focusedItem < 0)\r
+    return;\r
+  int index = GetRealItemIndex(focusedItem);\r
+  _selectedStatusVector[index] = !_selectedStatusVector[index];\r
+  _listView.RedrawItem(index);\r
+}\r
+\r
+void CPanel::OnDownWithShift()\r
+{\r
+  int focusedItem = _listView.GetFocusedItem();\r
+  if (focusedItem < 0)\r
+    return;\r
+  int index = GetRealItemIndex(focusedItem);\r
+  _selectedStatusVector[index] = !_selectedStatusVector[index];\r
+  _listView.RedrawItem(index);\r
+}\r
+*/\r
+\r
+void CPanel::UpdateSelection()\r
+{\r
+  if (!_mySelectMode)\r
+  {\r
+    bool enableTemp = _enableItemChangeNotify;\r
+    _enableItemChangeNotify = false;\r
+    int numItems = _listView.GetItemCount();\r
+    for (int i = 0; i < numItems; i++)\r
+    {\r
+      int realIndex = GetRealItemIndex(i);\r
+      if (realIndex != kParentIndex)\r
+      {\r
+        UINT value = 0;\r
+        value = _selectedStatusVector[realIndex] ? LVIS_SELECTED: 0;\r
+        _listView.SetItemState(i, value, LVIS_SELECTED);\r
+      }\r
+    }\r
+    _enableItemChangeNotify = enableTemp;\r
+  }\r
+  _listView.RedrawAllItems();\r
+}\r
+\r
+\r
+void CPanel::SelectSpec(bool selectMode)\r
+{\r
+  CComboDialog comboDialog;\r
+  comboDialog.Title = selectMode ?\r
+      LangString(IDS_SELECT, 0x03020250):\r
+      LangString(IDS_DESELECT, 0x03020251);\r
+  comboDialog.Static = LangString(IDS_SELECT_MASK, 0x03020252);\r
+  comboDialog.Value = L"*";\r
+  if (comboDialog.Create(GetParent()) == IDCANCEL)\r
+    return;\r
+  const UString &mask = comboDialog.Value;\r
+  for (int i = 0; i < _selectedStatusVector.Size(); i++)\r
+    if (CompareWildCardWithName(mask, GetItemName(i)))\r
+       _selectedStatusVector[i] = selectMode;\r
+  UpdateSelection();\r
+}\r
+\r
+void CPanel::SelectByType(bool selectMode)\r
+{\r
+  int focusedItem = _listView.GetFocusedItem();\r
+  if (focusedItem < 0)\r
+    return;\r
+  int realIndex = GetRealItemIndex(focusedItem);\r
+  UString name = GetItemName(realIndex);\r
+  bool isItemFolder = IsItemFolder(realIndex);\r
+\r
+  /*\r
+  UINT32 numItems;\r
+  _folder->GetNumberOfItems(&numItems);\r
+  if ((UInt32)_selectedStatusVector.Size() != numItems)\r
+    throw 11111;\r
+  */\r
+\r
+  if (isItemFolder)\r
+  {\r
+    for (int i = 0; i < _selectedStatusVector.Size(); i++)\r
+      if (IsItemFolder(i) == isItemFolder)\r
+        _selectedStatusVector[i] = selectMode;\r
+  }\r
+  else\r
+  {\r
+    int pos = name.ReverseFind(L'.');\r
+    if (pos < 0)\r
+    {\r
+      for (int i = 0; i < _selectedStatusVector.Size(); i++)\r
+        if (IsItemFolder(i) == isItemFolder && GetItemName(i).ReverseFind(L'.') < 0)\r
+          _selectedStatusVector[i] = selectMode;\r
+    }\r
+    else\r
+    {\r
+      UString mask = UString(L'*') + name.Mid(pos);\r
+      for (int i = 0; i < _selectedStatusVector.Size(); i++)\r
+        if (IsItemFolder(i) == isItemFolder && CompareWildCardWithName(mask, GetItemName(i)))\r
+          _selectedStatusVector[i] = selectMode;\r
+    }\r
+  }\r
+  UpdateSelection();\r
+}\r
+\r
+void CPanel::SelectAll(bool selectMode)\r
+{\r
+  for (int i = 0; i < _selectedStatusVector.Size(); i++)\r
+    _selectedStatusVector[i] = selectMode;\r
+  UpdateSelection();\r
+}\r
+\r
+void CPanel::InvertSelection()\r
+{\r
+  if (!_mySelectMode)\r
+  {\r
+    int numSelected = 0;\r
+    for (int i = 0; i < _selectedStatusVector.Size(); i++)\r
+      if (_selectedStatusVector[i])\r
+        numSelected++;\r
+    if (numSelected == 1)\r
+    {\r
+      int focused = _listView.GetFocusedItem();\r
+      if (focused >= 0)\r
+      {\r
+        int realIndex = GetRealItemIndex(focused);\r
+        if (realIndex >= 0)\r
+          if (_selectedStatusVector[realIndex])\r
+            _selectedStatusVector[realIndex] = false;\r
+      }\r
+    }\r
+  }\r
+  for (int i = 0; i < _selectedStatusVector.Size(); i++)\r
+    _selectedStatusVector[i] = !_selectedStatusVector[i];\r
+  UpdateSelection();\r
+}\r
+\r
+void CPanel::KillSelection()\r
+{\r
+  SelectAll(false);\r
+  if (!_mySelectMode)\r
+  {\r
+    int focused = _listView.GetFocusedItem();\r
+    if (focused >= 0)\r
+    {\r
+      // CPanel::OnItemChanged notify for LVIS_SELECTED change doesn't work here. Why?\r
+      // so we change _selectedStatusVector[realIndex] here.\r
+      int realIndex = GetRealItemIndex(focused);\r
+      if (realIndex != kParentIndex)\r
+        _selectedStatusVector[realIndex] = true;\r
+      _listView.SetItemState(focused, LVIS_SELECTED, LVIS_SELECTED);\r
+    }\r
+  }\r
+}\r
+\r
+void CPanel::OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate)\r
+{\r
+  if (itemActivate->hdr.hwndFrom != HWND(_listView))\r
+    return;\r
+  // It will be work only for Version 4.71 (IE 4);\r
+  int indexInList = itemActivate->iItem;\r
+  if (indexInList < 0)\r
+    return;\r
+  #ifndef UNDER_CE\r
+  if ((itemActivate->uKeyFlags & LVKF_SHIFT) != 0)\r
+  {\r
+    // int focusedIndex = _listView.GetFocusedItem();\r
+    int focusedIndex = _startGroupSelect;\r
+    if (focusedIndex < 0)\r
+      return;\r
+    int startItem = MyMin(focusedIndex, indexInList);\r
+    int finishItem = MyMax(focusedIndex, indexInList);\r
+    for (int i = 0; i < _selectedStatusVector.Size(); i++)\r
+    {\r
+      int realIndex = GetRealItemIndex(i);\r
+      if (realIndex == kParentIndex)\r
+        continue;\r
+      bool selected = (i >= startItem && i <= finishItem);\r
+      if (_selectedStatusVector[realIndex] != selected)\r
+      {\r
+        _selectedStatusVector[realIndex] = selected;\r
+        _listView.RedrawItem(i);\r
+      }\r
+    }\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    _startGroupSelect = indexInList;\r
+    #ifndef UNDER_CE\r
+    if ((itemActivate->uKeyFlags & LVKF_CONTROL) != 0)\r
+    {\r
+      int realIndex = GetRealItemIndex(indexInList);\r
+      if (realIndex != kParentIndex)\r
+      {\r
+        _selectedStatusVector[realIndex] = !_selectedStatusVector[realIndex];\r
+        _listView.RedrawItem(indexInList);\r
+      }\r
+    }\r
+    #endif\r
+  }\r
+  return;\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/PanelSort.cpp b/CPP/7zip/UI/FileManager/PanelSort.cpp
new file mode 100755 (executable)
index 0000000..3f896e0
--- /dev/null
@@ -0,0 +1,160 @@
+// PanelSort.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../../PropID.h"\r
+\r
+#include "Panel.h"\r
+\r
+using namespace NWindows;\r
+\r
+static UString GetExtension(const UString &name)\r
+{\r
+  int dotPos = name.ReverseFind(L'.');\r
+  if (dotPos < 0)\r
+    return UString();\r
+  return name.Mid(dotPos);\r
+}\r
+\r
+int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)\r
+{\r
+  if (lpData == NULL)\r
+    return 0;\r
+  CPanel *panel = (CPanel*)lpData;\r
+  \r
+  switch(panel->_sortID)\r
+  {\r
+    // if (panel->_sortIndex == 0)\r
+    case kpidName:\r
+    {\r
+      const UString name1 = panel->GetItemName((int)lParam1);\r
+      const UString name2 = panel->GetItemName((int)lParam2);\r
+      int res = name1.CompareNoCase(name2);\r
+      /*\r
+      if (res != 0 || !panel->_flatMode)\r
+        return res;\r
+      const UString prefix1 = panel->GetItemPrefix(lParam1);\r
+      const UString prefix2 = panel->GetItemPrefix(lParam2);\r
+      return res = prefix1.CompareNoCase(prefix2);\r
+      */\r
+      return res;\r
+    }\r
+    case kpidNoProperty:\r
+    {\r
+      return MyCompare(lParam1, lParam2);\r
+    }\r
+    case kpidExtension:\r
+    {\r
+      const UString ext1 = GetExtension(panel->GetItemName((int)lParam1));\r
+      const UString ext2 = GetExtension(panel->GetItemName((int)lParam2));\r
+      return ext1.CompareNoCase(ext2);\r
+    }\r
+  }\r
+  /*\r
+  if (panel->_sortIndex == 1)\r
+    return MyCompare(file1.Size, file2.Size);\r
+  return ::CompareFileTime(&file1.MTime, &file2.MTime);\r
+  */\r
+\r
+  // PROPID propID = panel->_properties[panel->_sortIndex].ID;\r
+  PROPID propID = panel->_sortID;\r
+\r
+  NCOM::CPropVariant prop1, prop2;\r
+  // Name must be first property\r
+  panel->_folder->GetProperty((UINT32)lParam1, propID, &prop1);\r
+  panel->_folder->GetProperty((UINT32)lParam2, propID, &prop2);\r
+  if (prop1.vt != prop2.vt)\r
+  {\r
+    return MyCompare(prop1.vt, prop2.vt);\r
+  }\r
+  if (prop1.vt == VT_BSTR)\r
+  {\r
+    return _wcsicmp(prop1.bstrVal, prop2.bstrVal);\r
+  }\r
+  return prop1.Compare(prop2);\r
+  // return 0;\r
+}\r
+\r
+int CALLBACK CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)\r
+{\r
+  if (lpData == NULL) return 0;\r
+  if (lParam1 == kParentIndex) return -1;\r
+  if (lParam2 == kParentIndex) return 1;\r
+\r
+  CPanel *panel = (CPanel*)lpData;\r
+\r
+  bool isDir1 = panel->IsItemFolder((int)lParam1);\r
+  bool isDir2 = panel->IsItemFolder((int)lParam2);\r
+  \r
+  if (isDir1 && !isDir2) return -1;\r
+  if (isDir2 && !isDir1) return 1;\r
+\r
+  int result = CompareItems2(lParam1, lParam2, lpData);\r
+  return panel->_ascending ? result: (-result);\r
+}\r
+\r
+\r
+/*\r
+void CPanel::SortItems(int index)\r
+{\r
+  if (index == _sortIndex)\r
+    _ascending = !_ascending;\r
+  else\r
+  {\r
+    _sortIndex = index;\r
+    _ascending = true;\r
+    switch (_properties[_sortIndex].ID)\r
+    {\r
+      case kpidSize:\r
+      case kpidPackedSize:\r
+      case kpidCTime:\r
+      case kpidATime:\r
+      case kpidMTime:\r
+      _ascending = false;\r
+      break;\r
+    }\r
+  }\r
+  _listView.SortItems(CompareItems, (LPARAM)this);\r
+  _listView.EnsureVisible(_listView.GetFocusedItem(), false);\r
+}\r
+void CPanel::SortItemsWithPropID(PROPID propID)\r
+{\r
+  int index = _properties.FindItemWithID(propID);\r
+  if (index >= 0)\r
+    SortItems(index);\r
+}\r
+*/\r
+void CPanel::SortItemsWithPropID(PROPID propID)\r
+{\r
+  if (propID == _sortID)\r
+    _ascending = !_ascending;\r
+  else\r
+  {\r
+    _sortID = propID;\r
+    _ascending = true;\r
+    switch (propID)\r
+    {\r
+      case kpidSize:\r
+      case kpidPackSize:\r
+      case kpidCTime:\r
+      case kpidATime:\r
+      case kpidMTime:\r
+        _ascending = false;\r
+      break;\r
+    }\r
+  }\r
+  _listView.SortItems(CompareItems, (LPARAM)this);\r
+  _listView.EnsureVisible(_listView.GetFocusedItem(), false);\r
+}\r
+\r
+\r
+void CPanel::OnColumnClick(LPNMLISTVIEW info)\r
+{\r
+  /*\r
+  int index = _properties.FindItemWithID(_visibleProperties[info->iSubItem].ID);\r
+  SortItems(index);\r
+  */\r
+  SortItemsWithPropID(_visibleProperties[info->iSubItem].ID);\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp
new file mode 100755 (executable)
index 0000000..61388d7
--- /dev/null
@@ -0,0 +1,494 @@
+// PanelSplitFile.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+\r
+#include "Windows/Error.h"\r
+#include "Windows/FileIO.h"\r
+#include "Windows/FileFind.h"\r
+\r
+#include "../GUI/ExtractRes.h"\r
+\r
+#include "resource.h"\r
+\r
+#include "App.h"\r
+#include "CopyDialog.h"\r
+#include "FormatUtils.h"\r
+#include "LangUtils.h"\r
+#include "SplitDialog.h"\r
+#include "SplitUtils.h"\r
+\r
+using namespace NWindows;\r
+\r
+static const wchar_t *g_Message_FileWriteError = L"File write error";\r
+\r
+struct CVolSeqName\r
+{\r
+  UString UnchangedPart;\r
+  UString ChangedPart;\r
+  CVolSeqName(): ChangedPart(L"000") {};\r
+\r
+  void SetNumDigits(UInt64 numVolumes)\r
+  {\r
+    ChangedPart = L"000";\r
+    while (numVolumes > 999)\r
+    {\r
+      numVolumes /= 10;\r
+      ChangedPart += L'0';\r
+    }\r
+  }\r
+\r
+  bool ParseName(const UString &name)\r
+  {\r
+    if (name.Right(2) != L"01")\r
+      return false;\r
+    int numLetters = 2;\r
+    while (numLetters < name.Length())\r
+    {\r
+      if (name[name.Length() - numLetters - 1] != '0')\r
+        break;\r
+      numLetters++;\r
+    }\r
+    UnchangedPart = name.Left(name.Length() - numLetters);\r
+    ChangedPart = name.Right(numLetters);\r
+    return true;\r
+  }\r
+\r
+  UString GetNextName()\r
+  {\r
+    UString newName;\r
+    int i;\r
+    int numLetters = ChangedPart.Length();\r
+    for (i = numLetters - 1; i >= 0; i--)\r
+    {\r
+      wchar_t c = ChangedPart[i];\r
+      if (c == L'9')\r
+      {\r
+        c = L'0';\r
+        newName = c + newName;\r
+        if (i == 0)\r
+          newName = UString(L'1') + newName;\r
+        continue;\r
+      }\r
+      c++;\r
+      newName = c + newName;\r
+      i--;\r
+      for (; i >= 0; i--)\r
+        newName = ChangedPart[i] + newName;\r
+      break;\r
+    }\r
+    ChangedPart = newName;\r
+    return UnchangedPart + ChangedPart;\r
+  }\r
+};\r
+\r
+static const UInt32 kBufSize = (1 << 20);\r
+\r
+class CThreadSplit: public CProgressThreadVirt\r
+{\r
+  HRESULT ProcessVirt();\r
+public:\r
+  UString FilePath;\r
+  UString VolBasePath;\r
+  UInt64 NumVolumes;\r
+  CRecordVector<UInt64> VolumeSizes;\r
+};\r
+\r
+HRESULT CThreadSplit::ProcessVirt()\r
+{\r
+  NFile::NIO::CInFile inFile;\r
+  if (!inFile.Open(FilePath))\r
+    return GetLastError();\r
+  NFile::NIO::COutFile outFile;\r
+  CMyBuffer bufferObject;\r
+  if (!bufferObject.Allocate(kBufSize))\r
+    return E_OUTOFMEMORY;\r
+  Byte *buffer = (Byte *)(void *)bufferObject;\r
+  UInt64 curVolSize = 0;\r
+  CVolSeqName seqName;\r
+  seqName.SetNumDigits(NumVolumes);\r
+  UInt64 length;\r
+  if (!inFile.GetLength(length))\r
+    return GetLastError();\r
+  \r
+  CProgressSync &sync = ProgressDialog.Sync;\r
+  sync.SetProgress(length, 0);\r
+  UInt64 pos = 0;\r
+  \r
+  UInt64 numFiles = 0;\r
+  int volIndex = 0;\r
+  \r
+  for (;;)\r
+  {\r
+    UInt64 volSize;\r
+    if (volIndex < VolumeSizes.Size())\r
+      volSize = VolumeSizes[volIndex];\r
+    else\r
+      volSize = VolumeSizes.Back();\r
+    \r
+    UInt32 needSize = (UInt32)(MyMin((UInt64)kBufSize, volSize - curVolSize));\r
+    UInt32 processedSize;\r
+    if (!inFile.Read(buffer, needSize, processedSize))\r
+      return GetLastError();\r
+    if (processedSize == 0)\r
+      break;\r
+    needSize = processedSize;\r
+    if (curVolSize == 0)\r
+    {\r
+      UString name = VolBasePath;\r
+      name += L'.';\r
+      name += seqName.GetNextName();\r
+      sync.SetCurrentFileName(name);\r
+      sync.SetNumFilesCur(numFiles++);\r
+      if (!outFile.Create(name, false))\r
+      {\r
+        HRESULT res = GetLastError();\r
+        ErrorPath1 = name;\r
+        return res;\r
+      }\r
+    }\r
+    if (!outFile.Write(buffer, needSize, processedSize))\r
+      return GetLastError();\r
+    if (needSize != processedSize)\r
+      throw g_Message_FileWriteError;\r
+    curVolSize += processedSize;\r
+    if (curVolSize == volSize)\r
+    {\r
+      outFile.Close();\r
+      if (volIndex < VolumeSizes.Size())\r
+        volIndex++;\r
+      curVolSize = 0;\r
+    }\r
+    pos += processedSize;\r
+    RINOK(sync.SetPosAndCheckPaused(pos));\r
+  }\r
+  sync.SetNumFilesCur(numFiles);\r
+  return S_OK;\r
+}\r
+\r
+void CApp::Split()\r
+{\r
+  int srcPanelIndex = GetFocusedPanelIndex();\r
+  CPanel &srcPanel = Panels[srcPanelIndex];\r
+  if (!srcPanel.IsFSFolder())\r
+  {\r
+    srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);\r
+    return;\r
+  }\r
+  CRecordVector<UInt32> indices;\r
+  srcPanel.GetOperatedItemIndices(indices);\r
+  if (indices.IsEmpty())\r
+    return;\r
+  if (indices.Size() != 1)\r
+  {\r
+    srcPanel.MessageBoxErrorLang(IDS_SELECT_ONE_FILE, 0x03020A02);\r
+    return;\r
+  }\r
+  int index = indices[0];\r
+  if (srcPanel.IsItemFolder(index))\r
+  {\r
+    srcPanel.MessageBoxErrorLang(IDS_SELECT_ONE_FILE, 0x03020A02);\r
+    return;\r
+  }\r
+  const UString itemName = srcPanel.GetItemName(index);\r
+\r
+  UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index);\r
+  UString path = srcPath;\r
+  int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);\r
+  CPanel &destPanel = Panels[destPanelIndex];\r
+  if (NumPanels > 1)\r
+    if (destPanel.IsFSFolder())\r
+      path = destPanel._currentFolderPrefix;\r
+  CSplitDialog splitDialog;\r
+  splitDialog.FilePath = srcPanel.GetItemRelPath(index);\r
+  splitDialog.Path = path;\r
+  if (splitDialog.Create(srcPanel.GetParent()) == IDCANCEL)\r
+    return;\r
+\r
+  NFile::NFind::CFileInfoW fileInfo;\r
+  if (!fileInfo.Find(srcPath + itemName))\r
+  {\r
+    srcPanel.MessageBoxMyError(L"Can not find file");\r
+    return;\r
+  }\r
+  if (fileInfo.Size <= splitDialog.VolumeSizes.Front())\r
+  {\r
+    srcPanel.MessageBoxErrorLang(IDS_SPLIT_VOL_MUST_BE_SMALLER, 0x03020522);\r
+    return;\r
+  }\r
+  const UInt64 numVolumes = GetNumberOfVolumes(fileInfo.Size, splitDialog.VolumeSizes);\r
+  if (numVolumes >= 100)\r
+  {\r
+    wchar_t s[32];\r
+    ConvertUInt64ToString(numVolumes, s);\r
+    if (::MessageBoxW(srcPanel, MyFormatNew(IDS_SPLIT_CONFIRM_MESSAGE, 0x03020521, s),\r
+        LangString(IDS_SPLIT_CONFIRM_TITLE, 0x03020520),\r
+        MB_YESNOCANCEL | MB_ICONQUESTION) != IDYES)\r
+      return;\r
+  }\r
+\r
+  path = splitDialog.Path;\r
+  NFile::NName::NormalizeDirPathPrefix(path);\r
+  if (!NFile::NDirectory::CreateComplexDirectory(path))\r
+  {\r
+    srcPanel.MessageBoxMyError(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, 0x02000603, path));\r
+    return;\r
+  }\r
+\r
+  {\r
+  CThreadSplit spliter;\r
+  spliter.NumVolumes = numVolumes;\r
+\r
+  CProgressDialog &progressDialog = spliter.ProgressDialog;\r
+\r
+  UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000);\r
+  UString title = LangString(IDS_SPLITTING, 0x03020510);\r
+\r
+  progressDialog.ShowCompressionInfo = false;\r
+\r
+  progressDialog.MainWindow = _window;\r
+  progressDialog.MainTitle = progressWindowTitle;\r
+  progressDialog.MainAddTitle = title + UString(L" ");\r
+  progressDialog.Sync.SetTitleFileName(itemName);\r
+\r
+\r
+  spliter.FilePath = srcPath + itemName;\r
+  spliter.VolBasePath = path + itemName;\r
+  spliter.VolumeSizes = splitDialog.VolumeSizes;\r
+  \r
+  // if (splitDialog.VolumeSizes.Size() == 0) return;\r
+\r
+  // CPanel::CDisableTimerProcessing disableTimerProcessing1(srcPanel);\r
+  // CPanel::CDisableTimerProcessing disableTimerProcessing2(destPanel);\r
+\r
+  if (spliter.Create(title, _window) != 0)\r
+    return;\r
+  }\r
+  RefreshTitleAlways();\r
+\r
+\r
+  // disableTimerProcessing1.Restore();\r
+  // disableTimerProcessing2.Restore();\r
+  // srcPanel.SetFocusToList();\r
+  // srcPanel.RefreshListCtrlSaveFocused();\r
+}\r
+\r
+\r
+class CThreadCombine: public CProgressThreadVirt\r
+{\r
+  HRESULT ProcessVirt();\r
+public:\r
+  UString InputDirPrefix;\r
+  UStringVector Names;\r
+  UString OutputPath;\r
+  UInt64 TotalSize;\r
+};\r
+\r
+HRESULT CThreadCombine::ProcessVirt()\r
+{\r
+  NFile::NIO::COutFile outFile;\r
+  if (!outFile.Create(OutputPath, false))\r
+  {\r
+    HRESULT res = GetLastError();\r
+    ErrorPath1 = OutputPath;\r
+    return res;\r
+  }\r
+  \r
+  CProgressSync &sync = ProgressDialog.Sync;\r
+  sync.SetProgress(TotalSize, 0);\r
+  \r
+  CMyBuffer bufferObject;\r
+  if (!bufferObject.Allocate(kBufSize))\r
+    return E_OUTOFMEMORY;\r
+  Byte *buffer = (Byte *)(void *)bufferObject;\r
+  UInt64 pos = 0;\r
+  for (int i = 0; i < Names.Size(); i++)\r
+  {\r
+    NFile::NIO::CInFile inFile;\r
+    const UString nextName = InputDirPrefix + Names[i];\r
+    if (!inFile.Open(nextName))\r
+    {\r
+      HRESULT res = GetLastError();\r
+      ErrorPath1 = nextName;\r
+      return res;\r
+    }\r
+    sync.SetCurrentFileName(nextName);\r
+    for (;;)\r
+    {\r
+      UInt32 processedSize;\r
+      if (!inFile.Read(buffer, kBufSize, processedSize))\r
+      {\r
+        HRESULT res = GetLastError();\r
+        ErrorPath1 = nextName;\r
+        return res;\r
+      }\r
+      if (processedSize == 0)\r
+        break;\r
+      UInt32 needSize = processedSize;\r
+      if (!outFile.Write(buffer, needSize, processedSize))\r
+      {\r
+        HRESULT res = GetLastError();\r
+        ErrorPath1 = OutputPath;\r
+        return res;\r
+      }\r
+      if (needSize != processedSize)\r
+        throw g_Message_FileWriteError;\r
+      pos += processedSize;\r
+      RINOK(sync.SetPosAndCheckPaused(pos));\r
+    }\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+extern void AddValuePair2(UINT resourceID, UInt32 langID, UInt64 num, UInt64 size, UString &s);\r
+\r
+static void AddInfoFileName(const UString &name, UString &dest)\r
+{\r
+  dest += L"\n  ";\r
+  dest += name;\r
+}\r
+\r
+void CApp::Combine()\r
+{\r
+  int srcPanelIndex = GetFocusedPanelIndex();\r
+  CPanel &srcPanel = Panels[srcPanelIndex];\r
+  if (!srcPanel.IsFSFolder())\r
+  {\r
+    srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);\r
+    return;\r
+  }\r
+  CRecordVector<UInt32> indices;\r
+  srcPanel.GetOperatedItemIndices(indices);\r
+  if (indices.IsEmpty())\r
+    return;\r
+  int index = indices[0];\r
+  if (indices.Size() != 1 || srcPanel.IsItemFolder(index))\r
+  {\r
+    srcPanel.MessageBoxErrorLang(IDS_COMBINE_SELECT_ONE_FILE, 0x03020620);\r
+    return;\r
+  }\r
+  const UString itemName = srcPanel.GetItemName(index);\r
+\r
+  UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index);\r
+  UString path = srcPath;\r
+  int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);\r
+  CPanel &destPanel = Panels[destPanelIndex];\r
+  if (NumPanels > 1)\r
+    if (destPanel.IsFSFolder())\r
+      path = destPanel._currentFolderPrefix;\r
+\r
+  CVolSeqName volSeqName;\r
+  if (!volSeqName.ParseName(itemName))\r
+  {\r
+    srcPanel.MessageBoxErrorLang(IDS_COMBINE_CANT_DETECT_SPLIT_FILE, 0x03020621);\r
+    return;\r
+  }\r
+  \r
+  {\r
+  CThreadCombine combiner;\r
+  \r
+  UString nextName = itemName;\r
+  combiner.TotalSize = 0;\r
+  for (;;)\r
+  {\r
+    NFile::NFind::CFileInfoW fileInfo;\r
+    if (!fileInfo.Find(srcPath + nextName) || fileInfo.IsDir())\r
+      break;\r
+    combiner.Names.Add(nextName);\r
+    combiner.TotalSize += fileInfo.Size;\r
+    nextName = volSeqName.GetNextName();\r
+  }\r
+  if (combiner.Names.Size() == 1)\r
+  {\r
+    srcPanel.MessageBoxErrorLang(IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART, 0x03020622);\r
+    return;\r
+  }\r
+  \r
+  if (combiner.TotalSize == 0)\r
+  {\r
+    srcPanel.MessageBoxMyError(L"No data");\r
+    return;\r
+  }\r
+  \r
+  UString info;\r
+  AddValuePair2(IDS_FILES_COLON, 0x02000320, combiner.Names.Size(), combiner.TotalSize, info);\r
+  \r
+  info += L"\n";\r
+  info += srcPath;\r
+  \r
+  int i;\r
+  for (i = 0; i < combiner.Names.Size() && i < 2; i++)\r
+    AddInfoFileName(combiner.Names[i], info);\r
+  if (i != combiner.Names.Size())\r
+  {\r
+    if (i + 1 != combiner.Names.Size())\r
+      AddInfoFileName(L"...", info);\r
+    AddInfoFileName(combiner.Names.Back(), info);\r
+  }\r
+  \r
+  {\r
+    CCopyDialog copyDialog;\r
+    copyDialog.Value = path;\r
+    copyDialog.Title = LangString(IDS_COMBINE, 0x03020600);\r
+    copyDialog.Title += ' ';\r
+    copyDialog.Title += srcPanel.GetItemRelPath(index);\r
+    copyDialog.Static = LangString(IDS_COMBINE_TO, 0x03020601);\r
+    copyDialog.Info = info;\r
+    if (copyDialog.Create(srcPanel.GetParent()) == IDCANCEL)\r
+      return;\r
+    path = copyDialog.Value;\r
+  }\r
+\r
+  NFile::NName::NormalizeDirPathPrefix(path);\r
+  if (!NFile::NDirectory::CreateComplexDirectory(path))\r
+  {\r
+    srcPanel.MessageBoxMyError(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, 0x02000603, path));\r
+    return;\r
+  }\r
+  \r
+  UString outName = volSeqName.UnchangedPart;\r
+  while (!outName.IsEmpty())\r
+  {\r
+    int lastIndex = outName.Length() - 1;\r
+    if (outName[lastIndex] != L'.')\r
+      break;\r
+    outName.Delete(lastIndex);\r
+  }\r
+  if (outName.IsEmpty())\r
+    outName = L"file";\r
+  \r
+  NFile::NFind::CFileInfoW fileInfo;\r
+  UString destFilePath = path + outName;\r
+  combiner.OutputPath = destFilePath;\r
+  if (fileInfo.Find(destFilePath))\r
+  {\r
+    srcPanel.MessageBoxMyError(MyFormatNew(IDS_FILE_EXIST, 0x03020A04, destFilePath));\r
+    return;\r
+  }\r
+  \r
+    CProgressDialog &progressDialog = combiner.ProgressDialog;\r
+    progressDialog.ShowCompressionInfo = false;\r
+  \r
+    UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000);\r
+    UString title = LangString(IDS_COMBINING, 0x03020610);\r
+    \r
+    progressDialog.MainWindow = _window;\r
+    progressDialog.MainTitle = progressWindowTitle;\r
+    progressDialog.MainAddTitle = title + UString(L" ");\r
+    \r
+    combiner.InputDirPrefix = srcPath;\r
+    \r
+    // CPanel::CDisableTimerProcessing disableTimerProcessing1(srcPanel);\r
+    // CPanel::CDisableTimerProcessing disableTimerProcessing2(destPanel);\r
+    \r
+    if (combiner.Create(title, _window) != 0)\r
+      return;\r
+  }\r
+  RefreshTitleAlways();\r
+\r
+  // disableTimerProcessing1.Restore();\r
+  // disableTimerProcessing2.Restore();\r
+  // srcPanel.SetFocusToList();\r
+  // srcPanel.RefreshListCtrlSaveFocused();\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/PasswordDialog.cpp b/CPP/7zip/UI/FileManager/PasswordDialog.cpp
new file mode 100755 (executable)
index 0000000..4c7bf8b
--- /dev/null
@@ -0,0 +1,51 @@
+// PasswordDialog.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "PasswordDialog.h"\r
+\r
+#ifdef LANG\r
+#include "LangUtils.h"\r
+#endif\r
+\r
+#ifdef LANG\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDC_STATIC_PASSWORD_HEADER, 0x02000B01 },\r
+  { IDC_CHECK_PASSWORD_SHOW, 0x02000B02 },\r
+  { IDOK, 0x02000702 },\r
+  { IDCANCEL, 0x02000710 }\r
+};\r
+#endif\r
+\r
+\r
+bool CPasswordDialog::OnInit()\r
+{\r
+  #ifdef LANG\r
+  LangSetWindowText(HWND(*this), 0x02000B00);\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+  #endif\r
+  _passwordControl.Attach(GetItem(IDC_EDIT_PASSWORD));\r
+  _passwordControl.SetText(Password);\r
+  _passwordControl.SetPasswordChar(TEXT('*'));\r
+  return CModalDialog::OnInit();\r
+}\r
+\r
+bool CPasswordDialog::OnButtonClicked(int buttonID, HWND buttonHWND)\r
+{\r
+  if (buttonID == IDC_CHECK_PASSWORD_SHOW)\r
+  {\r
+    _passwordControl.SetPasswordChar(IsButtonCheckedBool(IDC_CHECK_PASSWORD_SHOW) ? 0: TEXT('*'));\r
+    UString password;\r
+    _passwordControl.GetText(password);\r
+    _passwordControl.SetText(password);\r
+    return true;\r
+  }\r
+  return CDialog::OnButtonClicked(buttonID, buttonHWND);\r
+}\r
+\r
+void CPasswordDialog::OnOK()\r
+{\r
+  _passwordControl.GetText(Password);\r
+  CModalDialog::OnOK();\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/PasswordDialog.h b/CPP/7zip/UI/FileManager/PasswordDialog.h
new file mode 100755 (executable)
index 0000000..9f7241f
--- /dev/null
@@ -0,0 +1,21 @@
+// PasswordDialog.h\r
+\r
+#ifndef __PASSWORDDIALOG_H\r
+#define __PASSWORDDIALOG_H\r
+\r
+#include "Windows/Control/Dialog.h"\r
+#include "Windows/Control/Edit.h"\r
+#include "PasswordDialogRes.h"\r
+\r
+class CPasswordDialog: public NWindows::NControl::CModalDialog\r
+{\r
+  NWindows::NControl::CEdit _passwordControl;\r
+  virtual void OnOK();\r
+  virtual bool OnInit();\r
+  virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);\r
+public:\r
+  UString Password;\r
+  INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_DIALOG_PASSWORD, parentWindow); }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/PasswordDialog.rc b/CPP/7zip/UI/FileManager/PasswordDialog.rc
new file mode 100755 (executable)
index 0000000..385ffaa
--- /dev/null
@@ -0,0 +1,14 @@
+#include "PasswordDialogRes.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#define xc 140\r
+#define yc 72\r
+\r
+IDD_DIALOG_PASSWORD MY_DIALOG\r
+CAPTION "Enter password"\r
+BEGIN\r
+  LTEXT    "&Enter password:", IDC_STATIC_PASSWORD_HEADER, m, m, xc, 8\r
+  EDITTEXT  IDC_EDIT_PASSWORD, m, 20, xc, 14, ES_PASSWORD | ES_AUTOHSCROLL\r
+  CONTROL  "&Show password", IDC_CHECK_PASSWORD_SHOW, MY_CHECKBOX, m, 42, xc, 10\r
+  OK_CANCEL\r
+END\r
diff --git a/CPP/7zip/UI/FileManager/PasswordDialogRes.h b/CPP/7zip/UI/FileManager/PasswordDialogRes.h
new file mode 100755 (executable)
index 0000000..7225e57
--- /dev/null
@@ -0,0 +1,4 @@
+#define IDD_DIALOG_PASSWORD             501\r
+#define IDC_STATIC_PASSWORD_HEADER      1000\r
+#define IDC_EDIT_PASSWORD               1001\r
+#define IDC_CHECK_PASSWORD_SHOW         1002\r
diff --git a/CPP/7zip/UI/FileManager/PluginInterface.h b/CPP/7zip/UI/FileManager/PluginInterface.h
new file mode 100755 (executable)
index 0000000..cb8b790
--- /dev/null
@@ -0,0 +1,31 @@
+// PluginInterface.h\r
+\r
+#ifndef __PLUGIN_INTERFACE_H\r
+#define __PLUGIN_INTERFACE_H\r
+\r
+/*\r
+#include "../../../Common/Types.h"\r
+#include "../../IDecl.h"\r
+\r
+#define PLUGIN_INTERFACE(i, x) DECL_INTERFACE(i, 0x0A, x)\r
+\r
+PLUGIN_INTERFACE(IInitContextMenu, 0x00)\r
+{\r
+  STDMETHOD(InitContextMenu)(const wchar_t *folder, const wchar_t **names, UINT32 numFiles) PURE;\r
+};\r
+\r
+PLUGIN_INTERFACE(IPluginOptionsCallback, 0x01)\r
+{\r
+  STDMETHOD(GetProgramFolderPath)(BSTR *value) PURE;\r
+  STDMETHOD(GetProgramPath)(BSTR *value) PURE;\r
+  STDMETHOD(GetRegistryCUPath)(BSTR *value) PURE;\r
+};\r
+\r
+PLUGIN_INTERFACE(IPluginOptions, 0x02)\r
+{\r
+  STDMETHOD(PluginOptions)(HWND hWnd, IPluginOptionsCallback *callback) PURE;\r
+  // STDMETHOD(GetFileExtensions)(BSTR *extensions) PURE;\r
+};\r
+*/\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/PluginLoader.h b/CPP/7zip/UI/FileManager/PluginLoader.h
new file mode 100755 (executable)
index 0000000..895b01d
--- /dev/null
@@ -0,0 +1,28 @@
+// PluginLoader.h\r
+\r
+#ifndef __PLUGIN_LOADER_H\r
+#define __PLUGIN_LOADER_H\r
+\r
+#include "Windows/DLL.h"\r
+\r
+typedef UINT32 (WINAPI * CreateObjectPointer)(const GUID *clsID, const GUID *interfaceID, void **outObject);\r
+\r
+class CPluginLibrary: public NWindows::NDLL::CLibrary\r
+{\r
+public:\r
+  HRESULT CreateManager(REFGUID clsID, IFolderManager **manager)\r
+  {\r
+    CreateObjectPointer createObject = (CreateObjectPointer)GetProc("CreateObject");\r
+    if (createObject == NULL)\r
+      return GetLastError();\r
+    return createObject(&clsID, &IID_IFolderManager, (void **)manager);\r
+  }\r
+  HRESULT LoadAndCreateManager(LPCWSTR filePath, REFGUID clsID, IFolderManager **manager)\r
+  {\r
+    if (!Load(filePath))\r
+      return GetLastError();\r
+    return CreateManager(clsID, manager);\r
+  }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/PluginsPage.cpp b/CPP/7zip/UI/FileManager/PluginsPage.cpp
new file mode 100755 (executable)
index 0000000..ac7afba
--- /dev/null
@@ -0,0 +1,207 @@
+// PluginsPage.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/MyCom.h"\r
+\r
+#include "Windows/DLL.h"\r
+\r
+#include "HelpUtils.h"\r
+#include "LangUtils.h"\r
+#include "PluginsPage.h"\r
+#include "PluginsPageRes.h"\r
+#include "ProgramLocation.h"\r
+#include "PluginInterface.h"\r
+\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDC_PLUGINS_STATIC_PLUGINS, 0x03010101},\r
+  { IDC_PLUGINS_BUTTON_OPTIONS, 0x03010110}\r
+};\r
+\r
+static LPCWSTR kPluginsTopic = L"FM/options.htm#plugins";\r
+\r
+bool CPluginsPage::OnInit()\r
+{\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+\r
+  _listView.Attach(GetItem(IDC_PLUGINS_LIST));\r
+\r
+  UINT32 newFlags = /* LVS_EX_CHECKBOXES | */ LVS_EX_FULLROWSELECT;\r
+  _listView.SetExtendedListViewStyle(newFlags, newFlags);\r
+\r
+  _listView.InsertColumn(0, L"Plugins", 50);\r
+  \r
+  ReadFileFolderPluginInfoList(_plugins);\r
+\r
+  _listView.SetRedraw(false);\r
+  // _listView.DeleteAllItems();\r
+  for (int i = 0; i < _plugins.Size(); i++)\r
+  {\r
+    const CPluginInfo &p = _plugins[i];\r
+    if (!p.OptionsClassIDDefined)\r
+      continue;\r
+    LVITEMW item;\r
+    item.iItem = i;\r
+    item.mask = LVIF_TEXT | LVIF_STATE;\r
+    UString pluginName = p.Name;\r
+    item.pszText = (WCHAR *)(const WCHAR *)pluginName;\r
+    item.state = 0;\r
+    item.stateMask = UINT(-1);\r
+    item.iSubItem = 0;\r
+    _listView.InsertItem(&item);\r
+    _listView.SetCheckState(i, true);\r
+  }\r
+  _listView.SetRedraw(true);\r
+  if (_listView.GetItemCount() > 0)\r
+  {\r
+    UINT state = LVIS_SELECTED | LVIS_FOCUSED;\r
+    _listView.SetItemState(0, state, state);\r
+  }\r
+  _listView.SetColumnWidthAuto(0);\r
+\r
+  return CPropertyPage::OnInit();\r
+}\r
+\r
+LONG CPluginsPage::OnApply()\r
+{\r
+  /*\r
+  int selectedIndex = m_Lang.GetCurSel();\r
+  int aPathIndex = m_Lang.GetItemData(selectedIndex);\r
+  SaveRegLang(m_Paths[aPathIndex]);\r
+  ReloadLang();\r
+  */\r
+  return PSNRET_NOERROR;\r
+}\r
+\r
+void CPluginsPage::OnNotifyHelp()\r
+{\r
+  ShowHelpWindow(NULL, kPluginsTopic);\r
+}\r
+\r
+bool CPluginsPage::OnButtonClicked(int buttonID, HWND buttonHWND)\r
+{\r
+  switch(buttonID)\r
+  {\r
+    case IDC_PLUGINS_BUTTON_OPTIONS:\r
+      OnButtonOptions();\r
+      break;\r
+    default:\r
+      return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);\r
+  }\r
+  return true;\r
+}\r
+\r
+class CPluginOptionsCallback:\r
+  public IPluginOptionsCallback,\r
+  public CMyUnknownImp\r
+{\r
+  UString _pluginName;\r
+public:\r
+  MY_UNKNOWN_IMP\r
+\r
+  STDMETHOD(GetProgramFolderPath)(BSTR *value);\r
+  STDMETHOD(GetProgramPath)(BSTR *Value);\r
+  STDMETHOD(GetRegistryCUPath)(BSTR *Value);\r
+  void Init(const UString &pluginName)\r
+    { _pluginName = pluginName; }\r
+};\r
+\r
+STDMETHODIMP CPluginOptionsCallback::GetProgramFolderPath(BSTR *value)\r
+{\r
+  *value = 0;\r
+  UString folder;\r
+  if (!::GetProgramFolderPath(folder))\r
+    return E_FAIL;\r
+  return StringToBstr(folder, value);\r
+}\r
+\r
+static UString GetDefaultProgramName()\r
+{\r
+  return L"7zFM.exe";\r
+}\r
+\r
+STDMETHODIMP CPluginOptionsCallback::GetProgramPath(BSTR *value)\r
+{\r
+  *value = 0;\r
+  UString folder;\r
+  if (!::GetProgramFolderPath(folder))\r
+    return E_FAIL;\r
+  return StringToBstr(folder + GetDefaultProgramName(), value);\r
+}\r
+\r
+STDMETHODIMP CPluginOptionsCallback::GetRegistryCUPath(BSTR *value)\r
+{\r
+  return StringToBstr(UString(L"Software"\r
+    WSTRING_PATH_SEPARATOR L"7-Zip"\r
+    WSTRING_PATH_SEPARATOR L"FM"\r
+    WSTRING_PATH_SEPARATOR L"Plugins"\r
+    WSTRING_PATH_SEPARATOR) + _pluginName, value);\r
+}\r
+\r
+void CPluginsPage::OnButtonOptions()\r
+{\r
+  int index = _listView.GetSelectionMark();\r
+  if (index < 0)\r
+    return;\r
+\r
+  CPluginInfo pluginInfo = _plugins[index];\r
+  if (!pluginInfo.OptionsClassIDDefined)\r
+  {\r
+    MessageBoxW(HWND(*this), L"There are no options", L"7-Zip", 0);\r
+    return;\r
+  }\r
+  NWindows::NDLL::CLibrary lib;\r
+  CMyComPtr<IPluginOptions> pluginOptions;\r
+  if (!lib.Load(pluginInfo.FilePath))\r
+  {\r
+    MessageBoxW(HWND(*this), L"Can't load plugin", L"7-Zip", 0);\r
+    return;\r
+  }\r
+  typedef UINT32 (WINAPI * CreateObjectPointer)(const GUID *clsID, const GUID *interfaceID, void **outObject);\r
+  CreateObjectPointer createObject = (CreateObjectPointer)lib.GetProc("CreateObject");\r
+  if (createObject == NULL)\r
+  {\r
+    MessageBoxW(HWND(*this), L"Incorrect plugin", L"7-Zip", 0);\r
+    return;\r
+  }\r
+  if (createObject(&pluginInfo.OptionsClassID, &IID_IPluginOptions, (void **)&pluginOptions) != S_OK)\r
+  {\r
+    MessageBoxW(HWND(*this), L"There are no options", L"7-Zip", 0);\r
+    return;\r
+  }\r
+  CPluginOptionsCallback *callbackSpec = new CPluginOptionsCallback;\r
+  CMyComPtr<IPluginOptionsCallback> callback(callbackSpec);\r
+  callbackSpec->Init(pluginInfo.Name);\r
+  pluginOptions->PluginOptions(HWND(*this), callback);\r
+}\r
+\r
+bool CPluginsPage::OnNotify(UINT controlID, LPNMHDR lParam)\r
+{\r
+  if (lParam->hwndFrom == HWND(_listView) && lParam->code == LVN_ITEMCHANGED)\r
+  {\r
+    const NMLISTVIEW *aNMListView = (const NMLISTVIEW *)lParam;\r
+    if ((aNMListView->uChanged & LVIF_STATE) != 0)\r
+    {\r
+      UINT oldState = aNMListView->uOldState & LVIS_STATEIMAGEMASK;\r
+      UINT newState = aNMListView->uNewState & LVIS_STATEIMAGEMASK;\r
+      if (oldState != newState)\r
+        Changed();\r
+    }\r
+    return true;\r
+  }\r
+  return CPropertyPage::OnNotify(controlID, lParam);\r
+}\r
+\r
+/*\r
+bool CPluginsPage::OnCommand(int code, int itemID, LPARAM lParam)\r
+{\r
+  if (code == CBN_SELCHANGE && itemID == IDC_LANG_COMBO_LANG)\r
+  {\r
+    Changed();\r
+    return true;\r
+  }\r
+  return CPropertyPage::OnCommand(code, itemID, lParam);\r
+}\r
+\r
+*/\r
diff --git a/CPP/7zip/UI/FileManager/PluginsPage.h b/CPP/7zip/UI/FileManager/PluginsPage.h
new file mode 100755 (executable)
index 0000000..a265979
--- /dev/null
@@ -0,0 +1,26 @@
+// PluginsPage.h\r
\r
+#include "Windows/Control/ListView.h"\r
+\r
+#ifndef __PLUGINSPAGE_H\r
+#define __PLUGINSPAGE_H\r
+\r
+#include "Windows/Control/PropertyPage.h"\r
+#include "Windows/Control/ComboBox.h"\r
+\r
+#include "RegistryPlugins.h"\r
+\r
+class CPluginsPage: public NWindows::NControl::CPropertyPage\r
+{\r
+  NWindows::NControl::CListView _listView;\r
+  CObjectVector<CPluginInfo> _plugins;\r
+public:\r
+  virtual bool OnInit();\r
+  virtual void OnNotifyHelp();\r
+  virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);\r
+  virtual void OnButtonOptions();\r
+  virtual LONG OnApply();\r
+  virtual bool OnNotify(UINT controlID, LPNMHDR lParam);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/PluginsPage.rc b/CPP/7zip/UI/FileManager/PluginsPage.rc
new file mode 100755 (executable)
index 0000000..598dedf
--- /dev/null
@@ -0,0 +1,15 @@
+#include "PluginsPageRes.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#define xc 96\r
+#define yc 80\r
+\r
+IDD_PLUGINS  MY_PAGE\r
+CAPTION "Plugins"\r
+BEGIN\r
+  LTEXT     "&Plugins:", IDC_PLUGINS_STATIC_PLUGINS, m, m, xc, 8\r
+  CONTROL   "List1", IDC_PLUGINS_LIST, "SysListView32",\r
+            LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,\r
+            m, 20, xc, 40\r
+  PUSHBUTTON  "Options...", IDC_PLUGINS_BUTTON_OPTIONS, m, by, bxs, bys\r
+END\r
diff --git a/CPP/7zip/UI/FileManager/PluginsPageRes.h b/CPP/7zip/UI/FileManager/PluginsPageRes.h
new file mode 100755 (executable)
index 0000000..d7dee12
--- /dev/null
@@ -0,0 +1,4 @@
+#define IDD_PLUGINS                     541\r
+#define IDC_PLUGINS_STATIC_PLUGINS      1000\r
+#define IDC_PLUGINS_LIST                1001\r
+#define IDC_PLUGINS_BUTTON_OPTIONS      1002\r
diff --git a/CPP/7zip/UI/FileManager/ProgramLocation.cpp b/CPP/7zip/UI/FileManager/ProgramLocation.cpp
new file mode 100755 (executable)
index 0000000..a9edf32
--- /dev/null
@@ -0,0 +1,24 @@
+// ProgramLocation.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../../../C/Types.h"\r
+\r
+#include "ProgramLocation.h"\r
+\r
+#include "Windows/DLL.h"\r
+\r
+using namespace NWindows;\r
+\r
+extern HINSTANCE g_hInstance;\r
+\r
+bool GetProgramFolderPath(UString &folder)\r
+{\r
+  if (!NDLL::MyGetModuleFileName(g_hInstance, folder))\r
+    return false;\r
+  int pos = folder.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+  if (pos < 0)\r
+    return false;\r
+  folder = folder.Left(pos + 1);\r
+  return true;\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/ProgramLocation.h b/CPP/7zip/UI/FileManager/ProgramLocation.h
new file mode 100755 (executable)
index 0000000..f3e6e6b
--- /dev/null
@@ -0,0 +1,10 @@
+// ProgramLocation.h\r
+\r
+#ifndef __PROGRAM_LOCATION_H\r
+#define __PROGRAM_LOCATION_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+bool GetProgramFolderPath(UString &folder); // normalized\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.cpp b/CPP/7zip/UI/FileManager/ProgressDialog.cpp
new file mode 100755 (executable)
index 0000000..2361972
--- /dev/null
@@ -0,0 +1,204 @@
+// ProgressDialog.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+\r
+#include "resource.h"\r
+\r
+#include "ProgressDialog.h"\r
+\r
+using namespace NWindows;\r
+\r
+extern HINSTANCE g_hInstance;\r
+\r
+static const UINT_PTR kTimerID = 3;\r
+static const UINT kTimerElapse = 100;\r
+\r
+#ifdef LANG\r
+#include "LangUtils.h"\r
+#endif\r
+\r
+#ifdef LANG\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDCANCEL, 0x02000711 }\r
+};\r
+#endif\r
+\r
+HRESULT CProgressSync::ProcessStopAndPause()\r
+{\r
+  for (;;)\r
+  {\r
+    if (GetStopped())\r
+      return E_ABORT;\r
+    if (!GetPaused())\r
+      break;\r
+    ::Sleep(100);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+#ifndef _SFX\r
+CProgressDialog::~CProgressDialog()\r
+{\r
+  AddToTitle(L"");\r
+}\r
+void CProgressDialog::AddToTitle(LPCWSTR s)\r
+{\r
+  if (MainWindow != 0)\r
+    MySetWindowText(MainWindow, UString(s) + MainTitle);\r
+}\r
+#endif\r
+\r
+\r
+bool CProgressDialog::OnInit()\r
+{\r
+  _range = (UInt64)-1;\r
+  _prevPercentValue = -1;\r
+\r
+  _wasCreated = true;\r
+  _dialogCreatedEvent.Set();\r
+\r
+  #ifdef LANG\r
+  // LangSetWindowText(HWND(*this), 0x02000C00);\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+  #endif\r
+\r
+  m_ProgressBar.Attach(GetItem(IDC_PROGRESS1));\r
+\r
+  if (IconID >= 0)\r
+  {\r
+    HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IconID));\r
+    SetIcon(ICON_BIG, icon);\r
+  }\r
+\r
+  _timer = SetTimer(kTimerID, kTimerElapse);\r
+  SetText(_title);\r
+  CheckNeedClose();\r
+  return CModalDialog::OnInit();\r
+}\r
+\r
+void CProgressDialog::OnCancel() { Sync.SetStopped(true); }\r
+void CProgressDialog::OnOK() { }\r
+\r
+void CProgressDialog::SetRange(UInt64 range)\r
+{\r
+  _range = range;\r
+  _peviousPos = (UInt64)(Int64)-1;\r
+  _converter.Init(range);\r
+  m_ProgressBar.SetRange32(0 , _converter.Count(range)); // Test it for 100%\r
+}\r
+\r
+void CProgressDialog::SetPos(UInt64 pos)\r
+{\r
+  bool redraw = true;\r
+  if (pos < _range && pos > _peviousPos)\r
+  {\r
+    UInt64 posDelta = pos - _peviousPos;\r
+    if (posDelta < (_range >> 10))\r
+      redraw = false;\r
+  }\r
+  if (redraw)\r
+  {\r
+    m_ProgressBar.SetPos(_converter.Count(pos));  // Test it for 100%\r
+    _peviousPos = pos;\r
+  }\r
+}\r
+\r
+bool CProgressDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */)\r
+{\r
+  if (Sync.GetPaused())\r
+    return true;\r
+\r
+  CheckNeedClose();\r
+\r
+  UInt64 total, completed;\r
+  Sync.GetProgress(total, completed);\r
+  if (total != _range)\r
+    SetRange(total);\r
+  SetPos(completed);\r
+\r
+  if (total == 0)\r
+    total = 1;\r
+\r
+  int percentValue = (int)(completed * 100 / total);\r
+  if (percentValue != _prevPercentValue)\r
+  {\r
+    wchar_t s[64];\r
+    ConvertUInt64ToString(percentValue, s);\r
+    UString title = s;\r
+    title += L"% ";\r
+    SetText(title + _title);\r
+    #ifndef _SFX\r
+    AddToTitle(title + MainAddTitle);\r
+    #endif\r
+    _prevPercentValue = percentValue;\r
+  }\r
+  return true;\r
+}\r
+\r
+bool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+  switch(message)\r
+  {\r
+    case kCloseMessage:\r
+    {\r
+      KillTimer(_timer);\r
+      _timer = 0;\r
+      if (_inCancelMessageBox)\r
+      {\r
+        _externalCloseMessageWasReceived = true;\r
+        break;\r
+      }\r
+      return OnExternalCloseMessage();\r
+    }\r
+    /*\r
+    case WM_SETTEXT:\r
+    {\r
+      if (_timer == 0)\r
+        return true;\r
+    }\r
+    */\r
+  }\r
+  return CModalDialog::OnMessage(message, wParam, lParam);\r
+}\r
+\r
+bool CProgressDialog::OnButtonClicked(int buttonID, HWND buttonHWND)\r
+{\r
+  switch(buttonID)\r
+  {\r
+    case IDCANCEL:\r
+    {\r
+      bool paused = Sync.GetPaused();\r
+      Sync.SetPaused(true);\r
+      _inCancelMessageBox = true;\r
+      int res = ::MessageBoxW(HWND(*this), L"Are you sure you want to cancel?", _title, MB_YESNOCANCEL);\r
+      _inCancelMessageBox = false;\r
+      Sync.SetPaused(paused);\r
+      if (res == IDCANCEL || res == IDNO)\r
+      {\r
+        if (_externalCloseMessageWasReceived)\r
+          OnExternalCloseMessage();\r
+        return true;\r
+      }\r
+      break;\r
+    }\r
+  }\r
+  return CModalDialog::OnButtonClicked(buttonID, buttonHWND);\r
+}\r
+\r
+void CProgressDialog::CheckNeedClose()\r
+{\r
+  if (_needClose)\r
+  {\r
+    PostMessage(kCloseMessage);\r
+    _needClose = false;\r
+  }\r
+}\r
+\r
+bool CProgressDialog::OnExternalCloseMessage()\r
+{\r
+  End(0);\r
+  return true;\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.h b/CPP/7zip/UI/FileManager/ProgressDialog.h
new file mode 100755 (executable)
index 0000000..e065bee
--- /dev/null
@@ -0,0 +1,170 @@
+// ProgressDialog.h\r
+\r
+#ifndef __PROGRESS_DIALOG_H\r
+#define __PROGRESS_DIALOG_H\r
+\r
+#include "Windows/Synchronization.h"\r
+#include "Windows/Thread.h"\r
+\r
+#include "Windows/Control/Dialog.h"\r
+#include "Windows/Control/ProgressBar.h"\r
+\r
+#include "ProgressDialogRes.h"\r
+\r
+class CProgressSync\r
+{\r
+  NWindows::NSynchronization::CCriticalSection _cs;\r
+  bool _stopped;\r
+  bool _paused;\r
+  UInt64 _total;\r
+  UInt64 _completed;\r
+public:\r
+  CProgressSync(): _stopped(false), _paused(false), _total(1), _completed(0) {}\r
+\r
+  HRESULT ProcessStopAndPause();\r
+  bool GetStopped()\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    return _stopped;\r
+  }\r
+  void SetStopped(bool value)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    _stopped = value;\r
+  }\r
+  bool GetPaused()\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    return _paused;\r
+  }\r
+  void SetPaused(bool value)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    _paused = value;\r
+  }\r
+  void SetProgress(UInt64 total, UInt64 completed)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    _total = total;\r
+    _completed = completed;\r
+  }\r
+  void SetPos(UInt64 completed)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    _completed = completed;\r
+  }\r
+  void GetProgress(UInt64 &total, UInt64 &completed)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    total = _total;\r
+    completed = _completed;\r
+  }\r
+};\r
+\r
+class CU64ToI32Converter\r
+{\r
+  UInt64 _numShiftBits;\r
+public:\r
+  void Init(UInt64 range)\r
+  {\r
+    // Windows CE doesn't like big number here.\r
+    for (_numShiftBits = 0; range > (1 << 15); _numShiftBits++)\r
+      range >>= 1;\r
+  }\r
+  int Count(UInt64 value) { return int(value >> _numShiftBits); }\r
+};\r
+\r
+class CProgressDialog: public NWindows::NControl::CModalDialog\r
+{\r
+private:\r
+  UINT_PTR _timer;\r
+\r
+  UString _title;\r
+  CU64ToI32Converter _converter;\r
+  UInt64 _peviousPos;\r
+  UInt64 _range;\r
+  NWindows::NControl::CProgressBar m_ProgressBar;\r
+\r
+  int _prevPercentValue;\r
+\r
+  bool _wasCreated;\r
+  bool _needClose;\r
+  bool _inCancelMessageBox;\r
+  bool _externalCloseMessageWasReceived;\r
+\r
+  bool OnTimer(WPARAM timerID, LPARAM callback);\r
+  void SetRange(UInt64 range);\r
+  void SetPos(UInt64 pos);\r
+  virtual bool OnInit();\r
+  virtual void OnCancel();\r
+  virtual void OnOK();\r
+  NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent;\r
+  #ifndef _SFX\r
+  void AddToTitle(LPCWSTR string);\r
+  #endif\r
+  bool OnButtonClicked(int buttonID, HWND buttonHWND);\r
+\r
+  void WaitCreating() { _dialogCreatedEvent.Lock(); }\r
+  void CheckNeedClose();\r
+  bool OnExternalCloseMessage();\r
+public:\r
+  CProgressSync Sync;\r
+  int IconID;\r
+\r
+  #ifndef _SFX\r
+  HWND MainWindow;\r
+  UString MainTitle;\r
+  UString MainAddTitle;\r
+  ~CProgressDialog();\r
+  #endif\r
+\r
+  CProgressDialog(): _timer(0)\r
+    #ifndef _SFX\r
+    ,MainWindow(0)\r
+    #endif\r
+  {\r
+    IconID = -1;\r
+    _wasCreated = false;\r
+    _needClose = false;\r
+    _inCancelMessageBox = false;\r
+    _externalCloseMessageWasReceived = false;\r
+\r
+    if (_dialogCreatedEvent.Create() != S_OK)\r
+      throw 1334987;\r
+  }\r
+\r
+  INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = 0)\r
+  {\r
+    _title = title;\r
+    INT_PTR res = CModalDialog::Create(IDD_DIALOG_PROGRESS, wndParent);\r
+    thread.Wait();\r
+    return res;\r
+  }\r
+\r
+  enum\r
+  {\r
+    kCloseMessage = WM_USER + 1\r
+  };\r
+\r
+  virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);\r
+\r
+  void ProcessWasFinished()\r
+  {\r
+    WaitCreating();\r
+    if (_wasCreated)\r
+      PostMessage(kCloseMessage);\r
+    else\r
+      _needClose = true;\r
+  };\r
+};\r
+\r
+\r
+class CProgressCloser\r
+{\r
+  CProgressDialog *_p;\r
+public:\r
+  CProgressCloser(CProgressDialog &p) : _p(&p) {}\r
+  ~CProgressCloser() { _p->ProcessWasFinished(); }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.rc b/CPP/7zip/UI/FileManager/ProgressDialog.rc
new file mode 100755 (executable)
index 0000000..36317f4
--- /dev/null
@@ -0,0 +1,12 @@
+#include "ProgressDialogRes.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#define xc 172\r
+#define yc 44\r
+\r
+IDD_DIALOG_PROGRESS  MY_DIALOG\r
+CAPTION "Progress"\r
+BEGIN\r
+  PUSHBUTTON  "Cancel", IDCANCEL, bx, by, bxs, bys\r
+  CONTROL     "Progress1", IDC_PROGRESS1, "msctls_progress32", PBS_SMOOTH | WS_BORDER, m, m, xc, 14\r
+END\r
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
new file mode 100755 (executable)
index 0000000..3c418a3
--- /dev/null
@@ -0,0 +1,1009 @@
+// ProgressDialog2.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/Control/Static.h"\r
+#include "Windows/Error.h"\r
+\r
+#include "ProgressDialog2.h"\r
+#include "DialogSize.h"\r
+\r
+#include "ProgressDialog2Res.h"\r
+\r
+#include "../GUI/ExtractRes.h"\r
+\r
+using namespace NWindows;\r
+\r
+extern HINSTANCE g_hInstance;\r
+\r
+static const UINT_PTR kTimerID = 3;\r
+\r
+static const UINT kCloseMessage = WM_USER + 1;\r
+\r
+static const UINT kTimerElapse =\r
+  #ifdef UNDER_CE\r
+  500\r
+  #else\r
+  100\r
+  #endif\r
+  ;\r
+\r
+#include "LangUtils.h"\r
+\r
+#ifdef LANG\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDCANCEL, 0x02000C00 },\r
+  { IDC_PROGRESS_ELAPSED, 0x02000C01 },\r
+  { IDC_PROGRESS_REMAINING, 0x02000C02 },\r
+  { IDC_PROGRESS_TOTAL, 0x02000C03 },\r
+  { IDC_PROGRESS_SPEED, 0x02000C04 },\r
+  { IDC_PROGRESS_UNPACKED, 0x02000C05 },\r
+  { IDC_PROGRESS_PACKED, 0x02000323 },\r
+  { IDC_PROGRESS_RATIO, 0x02000C06 },\r
+  { IDC_PROGRESS_SPEED, 0x02000C04 },\r
+  { IDC_PROGRESS_FILES, 0x02000320 },\r
+  { IDC_PROGRESS_ERRORS, 0x0308000A },\r
+  { IDC_BUTTON_PROGRESS_PRIORITY, 0x02000C10 },\r
+  { IDC_BUTTON_PAUSE, 0x02000C12 },\r
+  { IDCANCEL, 0x02000711 },\r
+};\r
+#endif\r
+\r
+HRESULT CProgressSync::ProcessStopAndPause()\r
+{\r
+  for (;;)\r
+  {\r
+    if (GetStopped())\r
+      return E_ABORT;\r
+    if (!GetPaused())\r
+      break;\r
+    ::Sleep(100);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CProgressSync::SetPosAndCheckPaused(UInt64 completed)\r
+{\r
+  RINOK(ProcessStopAndPause());\r
+  SetPos(completed);\r
+  return S_OK;\r
+}\r
+\r
+\r
+CProgressDialog::CProgressDialog(): _timer(0), CompressingMode(true)\r
+    #ifndef _SFX\r
+    , MainWindow(0)\r
+    #endif\r
+  {\r
+    IconID = -1;\r
+    MessagesDisplayed = false;\r
+    _wasCreated = false;\r
+    _needClose = false;\r
+    _inCancelMessageBox = false;\r
+    _externalCloseMessageWasReceived = false;\r
+\r
+    _numPostedMessages = 0;\r
+    _numAutoSizeMessages = 0;\r
+    _errorsWereDisplayed = false;\r
+    _waitCloseByCancelButton = false;\r
+    _cancelWasPressed = false;\r
+    ShowCompressionInfo = true;\r
+    WaitMode = false;\r
+    if (_dialogCreatedEvent.Create() != S_OK)\r
+      throw 1334987;\r
+    if (_createDialogEvent.Create() != S_OK)\r
+      throw 1334987;\r
+  }\r
+\r
+#ifndef _SFX\r
+CProgressDialog::~CProgressDialog()\r
+{\r
+  AddToTitle(L"");\r
+}\r
+void CProgressDialog::AddToTitle(LPCWSTR s)\r
+{\r
+  if (MainWindow != 0)\r
+  {\r
+    CWindow window(MainWindow);\r
+    window.SetText(s + UString(MainTitle));\r
+  }\r
+}\r
+\r
+#endif\r
+\r
+static const int kTitleFileNameSizeLimit = 36;\r
+static const int kCurrentFileNameSizeLimit = 82;\r
+\r
+static void ReduceString(UString &s, int size)\r
+{\r
+  if (s.Length() > size)\r
+    s = s.Left(size / 2) + UString(L" ... ") + s.Right(size / 2);\r
+}\r
+\r
+void CProgressDialog::EnableErrorsControls(bool enable)\r
+{\r
+  int cmdShow = enable ? SW_SHOW : SW_HIDE;\r
+  ShowItem(IDC_PROGRESS_ERRORS, cmdShow);\r
+  ShowItem(IDC_PROGRESS_ERRORS_VALUE, cmdShow);\r
+  ShowItem(IDC_PROGRESS_LIST, cmdShow);\r
+}\r
+\r
+bool CProgressDialog::OnInit()\r
+{\r
+  _range = (UInt64)(Int64)-1;\r
+  _prevPercentValue = (UInt32)-1;\r
+  _prevElapsedSec = (UInt32)-1;\r
+  _prevRemainingSec = (UInt32)-1;\r
+  _prevSpeed = (UInt32)-1;\r
+  _prevMode = kSpeedBytes;\r
+  _prevTime = ::GetTickCount();\r
+  _elapsedTime = 0;\r
+  _foreground = true;\r
+\r
+  m_ProgressBar.Attach(GetItem(IDC_PROGRESS1));\r
+  _messageList.Attach(GetItem(IDC_PROGRESS_LIST));\r
+\r
+  _wasCreated = true;\r
+  _dialogCreatedEvent.Set();\r
+\r
+  #ifdef LANG\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+  #endif\r
+\r
+\r
+  CWindow window(GetItem(IDC_BUTTON_PROGRESS_PRIORITY));\r
+  window.GetText(backgroundString);\r
+  backgroundedString = backgroundString;\r
+  backgroundedString.Replace(L"&", L"");\r
+\r
+  window = GetItem(IDC_BUTTON_PAUSE);\r
+  window.GetText(pauseString);\r
+\r
+  foregroundString = LangStringSpec(IDS_PROGRESS_FOREGROUND, 0x02000C11);\r
+  continueString = LangStringSpec(IDS_PROGRESS_CONTINUE, 0x02000C13);\r
+  pausedString = LangStringSpec(IDS_PROGRESS_PAUSED, 0x02000C20);\r
+\r
+  SetText(_title);\r
+  SetPauseText();\r
+  SetPriorityText();\r
+\r
+\r
+  #ifndef UNDER_CE\r
+  _messageList.SetUnicodeFormat(true);\r
+  #endif\r
+\r
+  _messageList.InsertColumn(0, L"", 30);\r
+\r
+  const UString s = LangStringSpec(IDS_MESSAGES_DIALOG_MESSAGE_COLUMN, 0x02000A80);\r
+\r
+  _messageList.InsertColumn(1, s, 600);\r
+\r
+  _messageList.SetColumnWidthAuto(0);\r
+  _messageList.SetColumnWidthAuto(1);\r
+\r
+\r
+  EnableErrorsControls(false);\r
+\r
+  GetItemSizes(IDCANCEL, buttonSizeX, buttonSizeY);\r
+  _numReduceSymbols = kCurrentFileNameSizeLimit;\r
+  NormalizeSize(true);\r
+\r
+  if (!ShowCompressionInfo)\r
+  {\r
+    HideItem(IDC_PROGRESS_PACKED);\r
+    HideItem(IDC_PROGRESS_PACKED_VALUE);\r
+    HideItem(IDC_PROGRESS_RATIO);\r
+    HideItem(IDC_PROGRESS_RATIO_VALUE);\r
+  }\r
+\r
+  if (IconID >= 0)\r
+  {\r
+    HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IconID));\r
+    // SetIcon(ICON_SMALL, icon);\r
+    SetIcon(ICON_BIG, icon);\r
+  }\r
+  _timer = SetTimer(kTimerID, kTimerElapse);\r
+  #ifdef UNDER_CE\r
+  Foreground();\r
+  #endif\r
+\r
+  CheckNeedClose();\r
+\r
+  return CModalDialog::OnInit();\r
+}\r
+\r
+bool CProgressDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)\r
+{\r
+  int sY;\r
+  int sStep;\r
+  int mx, my;\r
+  {\r
+    RECT rect;\r
+    GetClientRectOfItem(IDC_PROGRESS_ELAPSED, rect);\r
+    mx = rect.left;\r
+    my = rect.top;\r
+    sY = rect.bottom - rect.top;\r
+    GetClientRectOfItem(IDC_PROGRESS_REMAINING, rect);\r
+    sStep = rect.top - my;\r
+  }\r
+\r
+\r
+  InvalidateRect(NULL);\r
+\r
+  int xSizeClient = xSize - mx * 2;\r
+\r
+  {\r
+    int i;\r
+    for (i = 800; i > 40; i = i * 9 / 10)\r
+      if (Units_To_Pixels_X(i) <= xSizeClient)\r
+        break;\r
+    _numReduceSymbols = i / 4;\r
+  }\r
+\r
+  int yPos = ySize - my - buttonSizeY;\r
+\r
+  ChangeSubWindowSizeX(GetItem(IDC_PROGRESS_FILE_NAME), xSize - mx * 2);\r
+  ChangeSubWindowSizeX(GetItem(IDC_PROGRESS1), xSize - mx * 2);\r
+\r
+  int bSizeX = buttonSizeX;\r
+  int mx2 = mx;\r
+  for (;; mx2--)\r
+  {\r
+    int bSize2 = bSizeX * 3 + mx2 * 2;\r
+    if (bSize2 <= xSizeClient)\r
+      break;\r
+    if (mx2 < 5)\r
+    {\r
+      bSizeX = (xSizeClient - mx2 * 2) / 3;\r
+      break;\r
+    }\r
+  }\r
+  if (bSizeX < 2)\r
+    bSizeX = 2;\r
+\r
+  {\r
+    RECT rect;\r
+    GetClientRectOfItem(IDC_PROGRESS_LIST, rect);\r
+    int y = rect.top;\r
+    int ySize2 = yPos - my - y;\r
+    const int kMinYSize = buttonSizeY + buttonSizeY * 3 / 4;\r
+    int xx = xSize - mx * 2;\r
+    if (ySize2 < kMinYSize)\r
+    {\r
+      ySize2 = kMinYSize;\r
+      if (xx > bSizeX * 2)\r
+        xx -= bSizeX;\r
+    }\r
+\r
+    _messageList.Move(mx, y, xx, ySize2);\r
+  }\r
+\r
+  {\r
+    int xPos = xSize - mx;\r
+    xPos -= bSizeX;\r
+    MoveItem(IDCANCEL, xPos, yPos, bSizeX, buttonSizeY);\r
+    xPos -= (mx2 + bSizeX);\r
+    MoveItem(IDC_BUTTON_PAUSE, xPos, yPos, bSizeX, buttonSizeY);\r
+    xPos -= (mx2 + bSizeX);\r
+    MoveItem(IDC_BUTTON_PROGRESS_PRIORITY, xPos, yPos, bSizeX, buttonSizeY);\r
+  }\r
+\r
+  int valueSize;\r
+  int labelSize;\r
+  int padSize;\r
+\r
+  labelSize = Units_To_Pixels_X(MY_PROGRESS_LABEL_UNITS_MIN);\r
+  valueSize = Units_To_Pixels_X(MY_PROGRESS_VALUE_UNITS);\r
+  padSize = Units_To_Pixels_X(MY_PROGRESS_PAD_UNITS);\r
+  int requiredSize = (labelSize + valueSize) * 2 + padSize;\r
+\r
+  int gSize;\r
+  {\r
+    if (requiredSize < xSizeClient)\r
+    {\r
+      int incr = (xSizeClient - requiredSize) / 3;\r
+      labelSize += incr;\r
+    }\r
+    else\r
+      labelSize = (xSizeClient - valueSize * 2 - padSize) / 2;\r
+    if (labelSize < 0)\r
+      labelSize = 0;\r
+\r
+    gSize = labelSize + valueSize;\r
+    padSize = xSizeClient - gSize * 2;\r
+  }\r
+\r
+  labelSize = gSize - valueSize;\r
+\r
+  UINT IDs[] =\r
+  {\r
+    IDC_PROGRESS_ELAPSED, IDC_PROGRESS_ELAPSED_VALUE,\r
+    IDC_PROGRESS_REMAINING, IDC_PROGRESS_REMAINING_VALUE,\r
+    IDC_PROGRESS_FILES, IDC_PROGRESS_FILES_VALUE,\r
+    IDC_PROGRESS_RATIO, IDC_PROGRESS_RATIO_VALUE,\r
+    IDC_PROGRESS_ERRORS, IDC_PROGRESS_ERRORS_VALUE,\r
+      \r
+    IDC_PROGRESS_TOTAL, IDC_PROGRESS_TOTAL_VALUE,\r
+    IDC_PROGRESS_SPEED, IDC_PROGRESS_SPEED_VALUE,\r
+    IDC_PROGRESS_UNPACKED, IDC_PROGRESS_UNPACKED_VALUE,\r
+    IDC_PROGRESS_PACKED, IDC_PROGRESS_PACKED_VALUE\r
+  };\r
+\r
+  yPos = my;\r
+  for (int i = 0; i < sizeof(IDs) / sizeof(IDs[0]); i += 2)\r
+  {\r
+    int x = mx;\r
+    const int kNumColumn1Items = 5 * 2;\r
+    if (i >= kNumColumn1Items)\r
+    {\r
+      if (i == kNumColumn1Items)\r
+        yPos = my;\r
+      x = mx + gSize + padSize;\r
+    }\r
+    MoveItem(IDs[i], x, yPos, labelSize, sY);\r
+    MoveItem(IDs[i + 1], x + labelSize, yPos, valueSize, sY);\r
+    yPos += sStep;\r
+  }\r
+  return false;\r
+}\r
+\r
+void CProgressDialog::OnCancel() { Sync.SetStopped(true); }\r
+void CProgressDialog::OnOK() { }\r
+\r
+static void ConvertSizeToString(UInt64 value, wchar_t *s)\r
+{\r
+  const wchar_t *kModif = L" KM";\r
+  for (int i = 0; ; i++)\r
+    if (i == 2 || value < (UInt64(10000) << (i * 10)))\r
+    {\r
+      ConvertUInt64ToString(value >> (i * 10), s);\r
+      s += wcslen(s);\r
+      *s++ = ' ';\r
+      if (i != 0)\r
+        *s++ = kModif[i];\r
+      *s++ = L'B';\r
+      *s++ = L'\0';\r
+      return;\r
+    }\r
+}\r
+\r
+void CProgressDialog::SetRange(UInt64 range)\r
+{\r
+  _range = range;\r
+  _previousPos = (UInt64)(Int64)-1;\r
+  _converter.Init(range);\r
+  m_ProgressBar.SetRange32(0, _converter.Count(range));\r
+}\r
+\r
+void CProgressDialog::SetPos(UInt64 pos)\r
+{\r
+  bool redraw = true;\r
+  if (pos < _range && pos > _previousPos)\r
+  {\r
+    if (pos - _previousPos < (_range >> 10))\r
+      redraw = false;\r
+  }\r
+  if(redraw)\r
+  {\r
+    m_ProgressBar.SetPos(_converter.Count(pos)); // Test it for 100%\r
+    _previousPos = pos;\r
+  }\r
+}\r
+\r
+static void GetTimeString(UInt64 timeValue, TCHAR *s)\r
+{\r
+  wsprintf(s, TEXT("%02d:%02d:%02d"),\r
+      UInt32(timeValue / 3600),\r
+      UInt32((timeValue / 60) % 60),\r
+      UInt32(timeValue % 60));\r
+}\r
+\r
+void CProgressDialog::ShowSize(int id, UInt64 value)\r
+{\r
+  wchar_t s[40];\r
+  s[0] = 0;\r
+  if (value != (UInt64)(Int64)-1)\r
+    ConvertSizeToString(value, s);\r
+  SetItemText(id, s);\r
+}\r
+\r
+void CProgressDialog::UpdateStatInfo(bool showAll)\r
+{\r
+  UInt64 total, completed, totalFiles, completedFiles, inSize, outSize;\r
+  bool bytesProgressMode;\r
+  Sync.GetProgress(total, completed, totalFiles, completedFiles, inSize, outSize, bytesProgressMode);\r
+\r
+  UInt32 curTime = ::GetTickCount();\r
+\r
+  UInt64 progressTotal = bytesProgressMode ? total : totalFiles;\r
+  UInt64 progressCompleted = bytesProgressMode ? completed : completedFiles;\r
+\r
+  if (progressTotal != _range)\r
+    SetRange(progressTotal);\r
+  if (progressTotal == (UInt64)(Int64)-1)\r
+  {\r
+    SetPos(0);\r
+    SetRange(progressCompleted);\r
+  }\r
+  else\r
+    SetPos(progressCompleted);\r
+\r
+  wchar_t s[32] = { 0 };\r
+  if (total != (UInt64)(Int64)-1)\r
+    ConvertSizeToString(total, s);\r
+  SetItemText(IDC_PROGRESS_TOTAL_VALUE, s);\r
+\r
+  _elapsedTime += (curTime - _prevTime);\r
+  _prevTime = curTime;\r
+\r
+  UInt32 elapsedSec = _elapsedTime / 1000;\r
+\r
+  bool elapsedChanged = false;\r
+  if (elapsedSec != _prevElapsedSec)\r
+  {\r
+    TCHAR s[40];\r
+    GetTimeString(elapsedSec, s);\r
+    SetItemText(IDC_PROGRESS_ELAPSED_VALUE, s);\r
+    _prevElapsedSec = elapsedSec;\r
+    elapsedChanged = true;\r
+  }\r
+\r
+  if (elapsedChanged || showAll)\r
+  {\r
+    {\r
+      UInt64 numErrors;\r
+\r
+      {\r
+        NWindows::NSynchronization::CCriticalSectionLock lock(Sync._cs);\r
+        numErrors = Sync.Messages.Size();\r
+      }\r
+      if (numErrors > 0)\r
+      {\r
+        UpdateMessagesDialog();\r
+        TCHAR s[40];\r
+        ConvertUInt64ToString(numErrors, s);\r
+        SetItemText(IDC_PROGRESS_ERRORS_VALUE, s);\r
+        if (!_errorsWereDisplayed)\r
+        {\r
+          _errorsWereDisplayed = true;\r
+          EnableErrorsControls(true);\r
+        }\r
+      }\r
+    }\r
+\r
+    if (completed != 0)\r
+    {\r
+\r
+    if (total == (UInt64)(Int64)-1)\r
+    {\r
+      SetItemText(IDC_PROGRESS_REMAINING_VALUE, L"");\r
+    }\r
+    else\r
+    {\r
+      UInt64 remainingTime = 0;\r
+      if (completed < total)\r
+        remainingTime = _elapsedTime * (total - completed)  / completed;\r
+      UInt64 remainingSec = remainingTime / 1000;\r
+      if (remainingSec != _prevRemainingSec)\r
+      {\r
+        TCHAR s[40];\r
+        GetTimeString(remainingSec, s);\r
+        SetItemText(IDC_PROGRESS_REMAINING_VALUE, s);\r
+        _prevRemainingSec = remainingSec;\r
+      }\r
+    }\r
+    {\r
+      UInt32 elapsedTime = (_elapsedTime == 0) ? 1 : _elapsedTime;\r
+      UInt64 speedB = (completed * 1000) / elapsedTime;\r
+      UInt64 speedKB = speedB / 1024;\r
+      UInt64 speedMB = speedKB / 1024;\r
+      const UInt32 kLimit1 = 10;\r
+      TCHAR s[40];\r
+      bool needRedraw = false;\r
+      if (speedMB >= kLimit1)\r
+      {\r
+        if (_prevMode != kSpeedMBytes || speedMB != _prevSpeed)\r
+        {\r
+          ConvertUInt64ToString(speedMB, s);\r
+          lstrcat(s, TEXT(" MB/s"));\r
+          _prevMode = kSpeedMBytes;\r
+          _prevSpeed = speedMB;\r
+          needRedraw = true;\r
+        }\r
+      }\r
+      else if (speedKB >= kLimit1)\r
+      {\r
+        if (_prevMode != kSpeedKBytes || speedKB != _prevSpeed)\r
+        {\r
+          ConvertUInt64ToString(speedKB, s);\r
+          lstrcat(s, TEXT(" KB/s"));\r
+          _prevMode = kSpeedKBytes;\r
+          _prevSpeed = speedKB;\r
+          needRedraw = true;\r
+        }\r
+      }\r
+      else\r
+      {\r
+        if (_prevMode != kSpeedBytes || speedB != _prevSpeed)\r
+        {\r
+          ConvertUInt64ToString(speedB, s);\r
+          lstrcat(s, TEXT(" B/s"));\r
+          _prevMode = kSpeedBytes;\r
+          _prevSpeed = speedB;\r
+          needRedraw = true;\r
+        }\r
+      }\r
+      if (needRedraw)\r
+        SetItemText(IDC_PROGRESS_SPEED_VALUE, s);\r
+    }\r
+    }\r
+\r
+    if (total == 0)\r
+      total = 1;\r
+    UInt32 percentValue = (UInt32)(completed * 100 / total);\r
+    UString titleName;\r
+    Sync.GetTitleFileName(titleName);\r
+    if (percentValue != _prevPercentValue || _prevTitleName != titleName)\r
+    {\r
+      _prevPercentValue = percentValue;\r
+      SetTitleText();\r
+      _prevTitleName = titleName;\r
+    }\r
+    \r
+    TCHAR s[64];\r
+    ConvertUInt64ToString(completedFiles, s);\r
+    if (totalFiles != (UInt64)(Int64)-1)\r
+    {\r
+      lstrcat(s, TEXT(" / "));\r
+      ConvertUInt64ToString(totalFiles, s + lstrlen(s));\r
+    }\r
+    \r
+    SetItemText(IDC_PROGRESS_FILES_VALUE, s);\r
+    \r
+    const UInt64 packSize   = CompressingMode ? outSize : inSize;\r
+    const UInt64 unpackSize = CompressingMode ? inSize : outSize;\r
+\r
+    if (unpackSize == (UInt64)(Int64)-1 && packSize == (UInt64)(Int64)-1)\r
+    {\r
+      ShowSize(IDC_PROGRESS_UNPACKED_VALUE, completed);\r
+      SetItemText(IDC_PROGRESS_PACKED_VALUE, L"");\r
+    }\r
+    else\r
+    {\r
+      ShowSize(IDC_PROGRESS_UNPACKED_VALUE, unpackSize);\r
+      ShowSize(IDC_PROGRESS_PACKED_VALUE, packSize);\r
+      \r
+      if (packSize != (UInt64)(Int64)-1 && unpackSize != (UInt64)(Int64)-1 && unpackSize != 0)\r
+      {\r
+        UInt64 ratio = packSize * 100 / unpackSize;\r
+        ConvertUInt64ToString(ratio, s);\r
+        lstrcat(s, TEXT("%"));\r
+        SetItemText(IDC_PROGRESS_RATIO_VALUE, s);\r
+      }\r
+    }\r
+  }\r
+\r
+\r
+  UString fileName;\r
+  Sync.GetCurrentFileName(fileName);\r
+  if (_prevFileName != fileName)\r
+  {\r
+    int slashPos = fileName.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+    UString s1, s2;\r
+    if (slashPos >= 0)\r
+    {\r
+      s1 = fileName.Left(slashPos + 1);\r
+      s2 = fileName.Mid(slashPos + 1);\r
+    }\r
+    else\r
+      s2 = fileName;\r
+    ReduceString(s1, _numReduceSymbols);\r
+    ReduceString(s2, _numReduceSymbols);\r
+    UString s = s1 + L"\n" + s2;\r
+    SetItemText(IDC_PROGRESS_FILE_NAME, s);\r
+    _prevFileName == fileName;\r
+  }\r
+}\r
+\r
+bool CProgressDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */)\r
+{\r
+  if (Sync.GetPaused())\r
+    return true;\r
+\r
+  CheckNeedClose();\r
+\r
+  UpdateStatInfo(false);\r
+  return true;\r
+}\r
+\r
+struct CWaitCursor\r
+{\r
+  HCURSOR _waitCursor;\r
+  HCURSOR _oldCursor;\r
+  CWaitCursor()\r
+  {\r
+    _waitCursor = LoadCursor(NULL, IDC_WAIT);\r
+    if (_waitCursor != NULL)\r
+      _oldCursor = SetCursor(_waitCursor);\r
+  }\r
+  ~CWaitCursor()\r
+  {\r
+    if (_waitCursor != NULL)\r
+      SetCursor(_oldCursor);\r
+  }\r
+};\r
+\r
+INT_PTR CProgressDialog::Create(const UString &title, NWindows::CThread &thread, HWND wndParent)\r
+{\r
+  INT_PTR res = 0;\r
+  try\r
+  {\r
+    if (WaitMode)\r
+    {\r
+      CWaitCursor waitCursor;\r
+      HANDLE h[] = { thread, _createDialogEvent };\r
+      \r
+      WRes res = WaitForMultipleObjects(sizeof(h) / sizeof(h[0]), h, FALSE,\r
+          #ifdef UNDER_CE\r
+          2500\r
+          #else\r
+          1000\r
+          #endif\r
+          );\r
+      if (res == WAIT_OBJECT_0 && !Sync.ThereIsMessage())\r
+        return 0;\r
+    }\r
+    _title = title;\r
+    BIG_DIALOG_SIZE(360, 192);\r
+    res = CModalDialog::Create(SIZED_DIALOG(IDD_DIALOG_PROGRESS), wndParent);\r
+  }\r
+  catch(...)\r
+  {\r
+    _wasCreated = true;\r
+    _dialogCreatedEvent.Set();\r
+    res = res;\r
+  }\r
+  thread.Wait();\r
+  if (!MessagesDisplayed)\r
+    MessageBoxW(wndParent, L"Progress Error", L"7-Zip", MB_ICONERROR | MB_OK);\r
+  return res;\r
+}\r
+\r
+bool CProgressDialog::OnExternalCloseMessage()\r
+{\r
+  UpdateStatInfo(true);\r
+  \r
+  HideItem(IDC_BUTTON_PROGRESS_PRIORITY);\r
+  HideItem(IDC_BUTTON_PAUSE);\r
+  SetItemText(IDCANCEL, LangStringSpec(IDS_CLOSE, 0x02000713));\r
+  \r
+  bool thereAreMessages;\r
+  UString okMessage;\r
+  UString okMessageTitle;\r
+  UString errorMessage;\r
+  UString errorMessageTitle;\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(Sync._cs);\r
+    errorMessage = Sync.ErrorMessage;\r
+    errorMessageTitle = Sync.ErrorMessageTitle;\r
+    okMessage = Sync.OkMessage;\r
+    okMessageTitle = Sync.OkMessageTitle;\r
+    thereAreMessages = !Sync.Messages.IsEmpty();\r
+  }\r
+  if (!errorMessage.IsEmpty())\r
+  {\r
+    MessagesDisplayed = true;\r
+    if (errorMessageTitle.IsEmpty())\r
+      errorMessageTitle = L"7-Zip";\r
+    MessageBoxW(*this, errorMessage, errorMessageTitle, MB_ICONERROR | MB_OK);\r
+  }\r
+  else if (!thereAreMessages)\r
+  {\r
+    MessagesDisplayed = true;\r
+    if (!okMessage.IsEmpty())\r
+    {\r
+      if (okMessageTitle.IsEmpty())\r
+        okMessageTitle = L"7-Zip";\r
+      MessageBoxW(*this, okMessage, okMessageTitle, MB_OK);\r
+    }\r
+  }\r
+\r
+  if (thereAreMessages && !_cancelWasPressed)\r
+  {\r
+    _waitCloseByCancelButton = true;\r
+    UpdateMessagesDialog();\r
+    return true;\r
+  }\r
+\r
+  End(0);\r
+  return true;\r
+}\r
+\r
+bool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+  switch(message)\r
+  {\r
+    case kCloseMessage:\r
+    {\r
+      KillTimer(_timer);\r
+      _timer = 0;\r
+      if (_inCancelMessageBox)\r
+      {\r
+        _externalCloseMessageWasReceived = true;\r
+        break;\r
+      }\r
+      return OnExternalCloseMessage();\r
+    }\r
+    /*\r
+    case WM_SETTEXT:\r
+    {\r
+      if (_timer == 0)\r
+        return true;\r
+      break;\r
+    }\r
+    */\r
+  }\r
+  return CModalDialog::OnMessage(message, wParam, lParam);\r
+}\r
+\r
+void CProgressDialog::SetTitleText()\r
+{\r
+  UString title;\r
+  if (Sync.GetPaused())\r
+  {\r
+    title = pausedString;\r
+    title += L' ';\r
+  }\r
+  if (_prevPercentValue != (UInt32)-1)\r
+  {\r
+    wchar_t s[64];\r
+    ConvertUInt64ToString(_prevPercentValue, s);\r
+    title += s;\r
+    title += L'%';\r
+  }\r
+  if (!_foreground)\r
+  {\r
+    title += L' ';\r
+    title += backgroundedString;\r
+  }\r
+  title += L' ';\r
+  UString totalTitle = title + _title;\r
+  UString fileName;\r
+  Sync.GetTitleFileName(fileName);\r
+  if (!fileName.IsEmpty())\r
+  {\r
+    ReduceString(fileName, kTitleFileNameSizeLimit);\r
+    totalTitle += L' ';\r
+    totalTitle += fileName;\r
+  }\r
+  SetText(totalTitle);\r
+  #ifndef _SFX\r
+  AddToTitle(title + MainAddTitle);\r
+  #endif\r
+}\r
+\r
+void CProgressDialog::SetPauseText()\r
+{\r
+  SetItemText(IDC_BUTTON_PAUSE, Sync.GetPaused() ?\r
+    continueString : pauseString);\r
+  SetTitleText();\r
+}\r
+\r
+void CProgressDialog::OnPauseButton()\r
+{\r
+  bool paused = !Sync.GetPaused();\r
+  Sync.SetPaused(paused);\r
+  UInt32 curTime = ::GetTickCount();\r
+  if (paused)\r
+    _elapsedTime += (curTime - _prevTime);\r
+  _prevTime = curTime;\r
+  SetPauseText();\r
+}\r
+\r
+void CProgressDialog::SetPriorityText()\r
+{\r
+  SetItemText(IDC_BUTTON_PROGRESS_PRIORITY, _foreground ?\r
+      backgroundString :\r
+      foregroundString);\r
+  SetTitleText();\r
+}\r
+\r
+void CProgressDialog::OnPriorityButton()\r
+{\r
+  _foreground = !_foreground;\r
+  #ifndef UNDER_CE\r
+  SetPriorityClass(GetCurrentProcess(), _foreground ?\r
+    NORMAL_PRIORITY_CLASS: IDLE_PRIORITY_CLASS);\r
+  #endif\r
+  SetPriorityText();\r
+}\r
+\r
+void CProgressDialog::AddMessageDirect(LPCWSTR message)\r
+{\r
+  int itemIndex = _messageList.GetItemCount();\r
+  wchar_t sz[32];\r
+  ConvertInt64ToString(itemIndex, sz);\r
+  _messageList.InsertItem(itemIndex, sz);\r
+  _messageList.SetSubItem(itemIndex, 1, message);\r
+}\r
+\r
+void CProgressDialog::AddMessage(LPCWSTR message)\r
+{\r
+  UString s = message;\r
+  while (!s.IsEmpty())\r
+  {\r
+    int pos = s.Find(L'\n');\r
+    if (pos < 0)\r
+      break;\r
+    AddMessageDirect(s.Left(pos));\r
+    s.Delete(0, pos + 1);\r
+  }\r
+  AddMessageDirect(s);\r
+}\r
+\r
+static unsigned GetNumDigits(UInt32 value)\r
+{\r
+  unsigned i;\r
+  for (i = 0; value >= 10; i++)\r
+    value /= 10;\r
+  return i;\r
+}\r
+\r
+void CProgressDialog::UpdateMessagesDialog()\r
+{\r
+  UStringVector messages;\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(Sync._cs);\r
+    for (int i = _numPostedMessages; i < Sync.Messages.Size(); i++)\r
+      messages.Add(Sync.Messages[i]);\r
+    _numPostedMessages = Sync.Messages.Size();\r
+  }\r
+  if (!messages.IsEmpty())\r
+  {\r
+    for (int i = 0; i < messages.Size(); i++)\r
+      AddMessage(messages[i]);\r
+    if (_numAutoSizeMessages < 256 || GetNumDigits(_numPostedMessages) > GetNumDigits(_numAutoSizeMessages))\r
+    {\r
+      _messageList.SetColumnWidthAuto(0);\r
+      _messageList.SetColumnWidthAuto(1);\r
+      _numAutoSizeMessages = _numPostedMessages;\r
+    }\r
+  }\r
+}\r
+\r
+\r
+bool CProgressDialog::OnButtonClicked(int buttonID, HWND buttonHWND)\r
+{\r
+  switch(buttonID)\r
+  {\r
+    // case IDOK: // if IDCANCEL is not DEFPUSHBUTTON\r
+    case IDCANCEL:\r
+    {\r
+      if (_waitCloseByCancelButton)\r
+      {\r
+        MessagesDisplayed = true;\r
+        End(IDCLOSE);\r
+        break;\r
+      }\r
+        \r
+      bool paused = Sync.GetPaused();\r
+      if (!paused)\r
+        OnPauseButton();\r
+      _inCancelMessageBox = true;\r
+      int res = ::MessageBoxW(HWND(*this),\r
+          LangStringSpec(IDS_PROGRESS_ASK_CANCEL, 0x02000C30),\r
+          _title, MB_YESNOCANCEL);\r
+      _inCancelMessageBox = false;\r
+      if (!paused)\r
+        OnPauseButton();\r
+      if (res == IDCANCEL || res == IDNO)\r
+      {\r
+        if (_externalCloseMessageWasReceived)\r
+          OnExternalCloseMessage();\r
+        return true;\r
+      }\r
+\r
+      _cancelWasPressed = true;\r
+      MessagesDisplayed = true;\r
+      break;\r
+    }\r
+\r
+    case IDC_BUTTON_PAUSE:\r
+      OnPauseButton();\r
+      return true;\r
+    case IDC_BUTTON_PROGRESS_PRIORITY:\r
+      OnPriorityButton();\r
+      return true;\r
+  }\r
+  return CModalDialog::OnButtonClicked(buttonID, buttonHWND);\r
+}\r
+\r
+void CProgressDialog::CheckNeedClose()\r
+{\r
+  if (_needClose)\r
+  {\r
+    PostMessage(kCloseMessage);\r
+    _needClose = false;\r
+  }\r
+}\r
+\r
+void CProgressDialog::ProcessWasFinished()\r
+{\r
+  // Set Window title here.\r
+  if (!WaitMode)\r
+    WaitCreating();\r
+  \r
+  if (_wasCreated)\r
+    PostMessage(kCloseMessage);\r
+  else\r
+    _needClose = true;\r
+}\r
+\r
+\r
+HRESULT CProgressThreadVirt::Create(const UString &title, HWND parentWindow)\r
+{\r
+  NWindows::CThread thread;\r
+  RINOK(thread.Create(MyThreadFunction, this));\r
+  ProgressDialog.Create(title, thread, parentWindow);\r
+  return S_OK;\r
+}\r
+\r
+UString HResultToMessage(HRESULT errorCode)\r
+{\r
+  UString message;\r
+  if (errorCode == E_OUTOFMEMORY)\r
+    message = LangStringSpec(IDS_MEM_ERROR, 0x0200060B);\r
+  else if (!NError::MyFormatMessage(errorCode, message))\r
+    message.Empty();\r
+  if (message.IsEmpty())\r
+    message = L"Error";\r
+  return message;\r
+}\r
+\r
+static void AddMessageToString(UString &dest, const UString &src)\r
+{\r
+  if (!src.IsEmpty())\r
+  {\r
+    if (!dest.IsEmpty())\r
+      dest += L'\n';\r
+    dest += src;\r
+  }\r
+}\r
+\r
+void CProgressThreadVirt::Process()\r
+{\r
+  CProgressCloser closer(ProgressDialog);\r
+  UString m;\r
+  try { Result = ProcessVirt(); }\r
+  catch(const wchar_t *s) { m = s; }\r
+  catch(const UString &s) { m = s; }\r
+  catch(const char *s) { m = GetUnicodeString(s); }\r
+  catch(...) { m = L"Error"; }\r
+  if (Result != E_ABORT)\r
+  {\r
+    if (m.IsEmpty() && Result != S_OK)\r
+      m = HResultToMessage(Result);\r
+  }\r
+  AddMessageToString(m, ErrorMessage);\r
+  AddMessageToString(m, ErrorPath1);\r
+  AddMessageToString(m, ErrorPath2);\r
+\r
+  if (m.IsEmpty())\r
+  {\r
+    if (!OkMessage.IsEmpty())\r
+    {\r
+      ProgressDialog.Sync.SetOkMessageTitle(OkMessageTitle);\r
+      ProgressDialog.Sync.SetOkMessage(OkMessage);\r
+    }\r
+  }\r
+  else\r
+  {\r
+    ProgressDialog.Sync.SetErrorMessage(m);\r
+    if (Result == S_OK)\r
+      Result = E_FAIL;\r
+  }\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.h b/CPP/7zip/UI/FileManager/ProgressDialog2.h
new file mode 100755 (executable)
index 0000000..52b20ce
--- /dev/null
@@ -0,0 +1,359 @@
+// ProgressDialog2.h\r
+\r
+#ifndef __PROGRESS_DIALOG2_H\r
+#define __PROGRESS_DIALOG2_H\r
+\r
+#include "Windows/Synchronization.h"\r
+#include "Windows/Thread.h"\r
+\r
+#include "Windows/Control/Dialog.h"\r
+#include "Windows/Control/ListView.h"\r
+#include "Windows/Control/ProgressBar.h"\r
+\r
+class CProgressSync\r
+{\r
+  bool _stopped;\r
+  bool _paused;\r
+  bool _bytesProgressMode;\r
+\r
+  UInt64 _totalBytes;\r
+  UInt64 _curBytes;\r
+  UInt64 _totalFiles;\r
+  UInt64 _curFiles;\r
+  UInt64 _inSize;\r
+  UInt64 _outSize;\r
+  \r
+  UString _titleFileName;\r
+  UString _currentFileName;\r
+\r
+public:\r
+  UStringVector Messages;\r
+  UString ErrorMessage;\r
+  UString ErrorMessageTitle;\r
+  \r
+  UString OkMessage;\r
+  UString OkMessageTitle;\r
+\r
+  NWindows::NSynchronization::CCriticalSection _cs;\r
+\r
+  CProgressSync():\r
+      _stopped(false), _paused(false),\r
+      _totalBytes((UInt64)(Int64)-1), _curBytes(0),\r
+      _totalFiles((UInt64)(Int64)-1), _curFiles(0),\r
+      _inSize((UInt64)(Int64)-1),\r
+      _outSize((UInt64)(Int64)-1),\r
+      _bytesProgressMode(true)\r
+      {}\r
+\r
+  bool GetStopped()\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    return _stopped;\r
+  }\r
+  void SetStopped(bool value)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    _stopped = value;\r
+  }\r
+  bool GetPaused()\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    return _paused;\r
+  }\r
+  void SetPaused(bool value)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    _paused = value;\r
+  }\r
+  void SetBytesProgressMode(bool bytesProgressMode)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    _bytesProgressMode = bytesProgressMode;\r
+  }\r
+  void SetProgress(UInt64 total, UInt64 completed)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    _totalBytes = total;\r
+    _curBytes = completed;\r
+  }\r
+  void SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    if (inSize)\r
+      _inSize = *inSize;\r
+    if (outSize)\r
+      _outSize = *outSize;\r
+  }\r
+  void SetPos(UInt64 completed)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    _curBytes = completed;\r
+  }\r
+  void SetNumBytesTotal(UInt64 value)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    _totalBytes = value;\r
+  }\r
+  void SetNumFilesTotal(UInt64 value)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    _totalFiles = value;\r
+  }\r
+  void SetNumFilesCur(UInt64 value)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    _curFiles = value;\r
+  }\r
+  HRESULT ProcessStopAndPause();\r
+  HRESULT SetPosAndCheckPaused(UInt64 completed);\r
+  void GetProgress(UInt64 &total, UInt64 &completed,\r
+    UInt64 &totalFiles, UInt64 &curFiles,\r
+    UInt64 &inSize, UInt64 &outSize,\r
+    bool &bytesProgressMode)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    total = _totalBytes;\r
+    completed = _curBytes;\r
+    totalFiles = _totalFiles;\r
+    curFiles = _curFiles;\r
+    inSize = _inSize;\r
+    outSize = _outSize;\r
+    bytesProgressMode = _bytesProgressMode;\r
+  }\r
+  void SetTitleFileName(const UString &fileName)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    _titleFileName = fileName;\r
+  }\r
+  void GetTitleFileName(UString &fileName)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    fileName = _titleFileName;\r
+  }\r
+  void SetCurrentFileName(const UString &fileName)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    _currentFileName = fileName;\r
+  }\r
+  void GetCurrentFileName(UString &fileName)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    fileName = _currentFileName;\r
+  }\r
+\r
+  void AddErrorMessage(LPCWSTR message)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    Messages.Add(message);\r
+  }\r
+\r
+  void SetErrorMessage(const UString &message)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    ErrorMessage = message;\r
+  }\r
+\r
+  void SetOkMessage(const UString &message)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    OkMessage = message;\r
+  }\r
+\r
+  void SetOkMessageTitle(const UString &title)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    OkMessageTitle = title;\r
+  }\r
+\r
+  void SetErrorMessageTitle(const UString &title)\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\r
+    ErrorMessageTitle = title;\r
+  }\r
+\r
+  bool ThereIsMessage() const\r
+  {\r
+    return !Messages.IsEmpty() || !ErrorMessage.IsEmpty() || !OkMessage.IsEmpty();\r
+  }\r
+};\r
+\r
+class CU64ToI32Converter\r
+{\r
+  UInt64 _numShiftBits;\r
+public:\r
+  void Init(UInt64 range)\r
+  {\r
+    // Windows CE doesn't like big number here.\r
+    for (_numShiftBits = 0; range > (1 << 15); _numShiftBits++)\r
+      range >>= 1;\r
+  }\r
+  int Count(UInt64 value) { return int(value >> _numShiftBits); }\r
+};\r
+\r
+enum ESpeedMode\r
+{\r
+  kSpeedBytes,\r
+  kSpeedKBytes,\r
+  kSpeedMBytes\r
+};\r
+\r
+class CProgressDialog: public NWindows::NControl::CModalDialog\r
+{\r
+  UString _prevFileName;\r
+  UString _prevTitleName;\r
+private:\r
+  UString backgroundString;\r
+  UString backgroundedString;\r
+  UString foregroundString;\r
+  UString pauseString;\r
+  UString continueString;\r
+  UString pausedString;\r
+\r
+  int buttonSizeX;\r
+  int buttonSizeY;\r
+\r
+  UINT_PTR _timer;\r
+\r
+  UString _title;\r
+  CU64ToI32Converter _converter;\r
+  UInt64 _previousPos;\r
+  UInt64 _range;\r
+  NWindows::NControl::CProgressBar m_ProgressBar;\r
+  NWindows::NControl::CListView _messageList;\r
+\r
+  UInt32 _prevPercentValue;\r
+  UInt32 _prevTime;\r
+  UInt32 _elapsedTime;\r
+  UInt32 _prevElapsedSec;\r
+  UInt64 _prevRemainingSec;\r
+  ESpeedMode _prevMode;\r
+  UInt64 _prevSpeed;\r
+\r
+  bool _foreground;\r
+\r
+  int _numReduceSymbols;\r
+\r
+  bool _wasCreated;\r
+  bool _needClose;\r
+\r
+  UInt32 _numPostedMessages;\r
+  UInt32 _numAutoSizeMessages;\r
+\r
+  bool _errorsWereDisplayed;\r
+\r
+  bool _waitCloseByCancelButton;\r
+  bool _cancelWasPressed;\r
+  \r
+  bool _inCancelMessageBox;\r
+  bool _externalCloseMessageWasReceived;\r
+\r
+  void UpdateStatInfo(bool showAll);\r
+  bool OnTimer(WPARAM timerID, LPARAM callback);\r
+  void SetRange(UInt64 range);\r
+  void SetPos(UInt64 pos);\r
+  virtual bool OnInit();\r
+  virtual bool OnSize(WPARAM wParam, int xSize, int ySize);\r
+  virtual void OnCancel();\r
+  virtual void OnOK();\r
+  NWindows::NSynchronization::CManualResetEvent _createDialogEvent;\r
+  NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent;\r
+  #ifndef _SFX\r
+  void AddToTitle(LPCWSTR string);\r
+  #endif\r
+\r
+  void SetPauseText();\r
+  void SetPriorityText();\r
+  void OnPauseButton();\r
+  void OnPriorityButton();\r
+  bool OnButtonClicked(int buttonID, HWND buttonHWND);\r
+\r
+  void SetTitleText();\r
+  void ShowSize(int id, UInt64 value);\r
+\r
+  void UpdateMessagesDialog();\r
+\r
+  void AddMessageDirect(LPCWSTR message);\r
+  void AddMessage(LPCWSTR message);\r
+\r
+  bool OnExternalCloseMessage();\r
+  void EnableErrorsControls(bool enable);\r
+\r
+  void ShowAfterMessages(HWND wndParent);\r
+\r
+  void CheckNeedClose();\r
+public:\r
+  CProgressSync Sync;\r
+  bool CompressingMode;\r
+  bool WaitMode;\r
+  bool ShowCompressionInfo;\r
+  bool MessagesDisplayed; // = true if user pressed OK on all messages or there are no messages.\r
+  int IconID;\r
+\r
+  #ifndef _SFX\r
+  HWND MainWindow;\r
+  UString MainTitle;\r
+  UString MainAddTitle;\r
+  ~CProgressDialog();\r
+  #endif\r
+\r
+  CProgressDialog();\r
+  void WaitCreating()\r
+  {\r
+    _createDialogEvent.Set();\r
+    _dialogCreatedEvent.Lock();\r
+  }\r
+\r
+\r
+  INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = 0);\r
+\r
+\r
+  virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);\r
+\r
+  void ProcessWasFinished();\r
+};\r
+\r
+\r
+class CProgressCloser\r
+{\r
+  CProgressDialog *_p;\r
+public:\r
+  CProgressCloser(CProgressDialog &p) : _p(&p) {}\r
+  ~CProgressCloser() { _p->ProcessWasFinished(); }\r
+};\r
+\r
+class CProgressThreadVirt\r
+{\r
+protected:\r
+  UString ErrorMessage;\r
+  UString ErrorPath1;\r
+  UString ErrorPath2;\r
+  UString OkMessage;\r
+  UString OkMessageTitle;\r
+\r
+  // error if any of HRESULT, ErrorMessage, ErrorPath\r
+  virtual HRESULT ProcessVirt() = 0;\r
+  void Process();\r
+public:\r
+  HRESULT Result;\r
+  bool ThreadFinishedOK; // if there is no fatal exception\r
+  CProgressDialog ProgressDialog;\r
+\r
+  static THREAD_FUNC_DECL MyThreadFunction(void *param)\r
+  {\r
+    CProgressThreadVirt *p = (CProgressThreadVirt *)param;\r
+    try\r
+    {\r
+      p->Process();\r
+      p->ThreadFinishedOK = true;\r
+    }\r
+    catch (...) { p->Result = E_FAIL; }\r
+    return 0;\r
+  }\r
+\r
+  HRESULT Create(const UString &title, HWND parentWindow = 0);\r
+  CProgressThreadVirt(): Result(E_FAIL), ThreadFinishedOK(false) {}\r
+};\r
+\r
+UString HResultToMessage(HRESULT errorCode);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.rc b/CPP/7zip/UI/FileManager/ProgressDialog2.rc
new file mode 100755 (executable)
index 0000000..51b7a08
--- /dev/null
@@ -0,0 +1,41 @@
+#include "ProgressDialog2Res.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#undef DIALOG_ID\r
+#define DIALOG_ID  IDD_DIALOG_PROGRESS\r
+#define xc 360\r
+#define k 11\r
+#define z1s 16\r
+\r
+#include "ProgressDialog2a.rc"\r
+\r
+#ifdef UNDER_CE\r
+\r
+#include "../../GuiCommon.rc"\r
+\r
+\r
+#undef DIALOG_ID\r
+#undef m\r
+#undef k\r
+#undef z1s\r
+\r
+#define DIALOG_ID  IDD_DIALOG_PROGRESS_2\r
+#define m 4\r
+#define k 8\r
+#define z1s 12\r
+\r
+#define xc 280\r
+\r
+#include "ProgressDialog2a.rc"\r
+\r
+#endif\r
+\r
+STRINGTABLE DISCARDABLE\r
+{\r
+  IDS_PROGRESS_PAUSED     "Paused"\r
+  IDS_PROGRESS_FOREGROUND "&Foreground"\r
+  IDS_PROGRESS_CONTINUE   "&Continue"\r
+  IDS_PROGRESS_ASK_CANCEL "Are you sure you want to cancel?"\r
+  IDS_CLOSE "&Close"\r
+  IDS_MESSAGES_DIALOG_MESSAGE_COLUMN "Message"\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2Res.h b/CPP/7zip/UI/FileManager/ProgressDialog2Res.h
new file mode 100755 (executable)
index 0000000..2282bc6
--- /dev/null
@@ -0,0 +1,41 @@
+#define IDD_DIALOG_PROGRESS             500\r
+#define IDD_DIALOG_PROGRESS_2           600\r
+\r
+#define IDC_BUTTON_PAUSE                50\r
+#define IDC_BUTTON_PROGRESS_PRIORITY    51\r
+\r
+#define IDS_PROGRESS_PAUSED             700\r
+#define IDS_PROGRESS_FOREGROUND         701\r
+#define IDS_PROGRESS_CONTINUE           702\r
+#define IDS_PROGRESS_ASK_CANCEL         703\r
+#define IDS_CLOSE                       704\r
+#define IDS_MESSAGES_DIALOG_MESSAGE_COLUMN 503\r
+\r
+#define IDC_PROGRESS1                   1000\r
+#define IDC_PROGRESS_ELAPSED            1002\r
+#define IDC_PROGRESS_ELAPSED_VALUE      1003\r
+#define IDC_PROGRESS_REMAINING          1004\r
+#define IDC_PROGRESS_REMAINING_VALUE    1005\r
+#define IDC_PROGRESS_SPEED              1006\r
+#define IDC_PROGRESS_SPEED_VALUE        1007\r
+#define IDC_PROGRESS_TOTAL              1008\r
+#define IDC_PROGRESS_TOTAL_VALUE        1009\r
+#define IDC_PROGRESS_FILE_NAME          1010\r
+\r
+#define IDC_PROGRESS_FILES              1012\r
+#define IDC_PROGRESS_FILES_VALUE        1013\r
+#define IDC_PROGRESS_RATIO              1014\r
+#define IDC_PROGRESS_RATIO_VALUE        1015\r
+#define IDC_PROGRESS_PACKED             1016\r
+#define IDC_PROGRESS_PACKED_VALUE       1017\r
+#define IDC_PROGRESS_UNPACKED           1018\r
+#define IDC_PROGRESS_UNPACKED_VALUE     1019\r
+\r
+#define IDC_PROGRESS_ERRORS         1030\r
+#define IDC_PROGRESS_ERRORS_VALUE   1031\r
+#define IDC_PROGRESS_LIST           1032\r
+\r
+#define MY_PROGRESS_VALUE_UNITS  44\r
+#define MY_PROGRESS_LABEL_UNITS_MIN  60\r
+#define MY_PROGRESS_LABEL_UNITS_START 90\r
+#define MY_PROGRESS_PAD_UNITS  4\r
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2a.rc b/CPP/7zip/UI/FileManager/ProgressDialog2a.rc
new file mode 100755 (executable)
index 0000000..9ae7122
--- /dev/null
@@ -0,0 +1,78 @@
+#undef bxs\r
+#define bxs 80\r
+\r
+#define x0s MY_PROGRESS_LABEL_UNITS_START\r
+#define x1s MY_PROGRESS_VALUE_UNITS\r
+#define x2s MY_PROGRESS_LABEL_UNITS_START\r
+#define x3s MY_PROGRESS_VALUE_UNITS\r
+\r
+#define x1 (m + x0s)\r
+#define x3 (xs - m - x3s)\r
+#define x2 (x3 - x2s)\r
+\r
+#undef y0\r
+#undef y1\r
+#undef y2\r
+#undef y3\r
+#undef y4\r
+\r
+#undef z0\r
+#undef z0z\r
+#undef z1\r
+#undef z2\r
+#undef z2\r
+\r
+#define y0 m\r
+#define y1 (y0 + k)\r
+#define y2 (y1 + k)\r
+#define y3 (y2 + k)\r
+#define y4 (y3 + k)\r
+\r
+#define z2 (y4 + k + 1)\r
+#define z2s 24\r
+\r
+#define z1 (z2 + z2s)\r
+\r
+#define z0 (z1 + z1s + m)\r
+#define z0s 48\r
+\r
+#define yc (z0 + z0s + bys)\r
+\r
+\r
+DIALOG_ID  MY_RESIZE_DIALOG\r
+CAPTION "Progress"\r
+{\r
+  PUSHBUTTON  "&Background", IDC_BUTTON_PROGRESS_PRIORITY,  bx3, by, bxs, bys\r
+  PUSHBUTTON  "&Pause",      IDC_BUTTON_PAUSE,              bx2, by, bxs, bys\r
+  DEFPUSHBUTTON  "Cancel",   IDCANCEL,                      bx1, by, bxs, bys\r
+\r
+  LTEXT  "Elapsed time:",   IDC_PROGRESS_ELAPSED,   m, y0, x0s, 8\r
+  LTEXT  "Remaining time:", IDC_PROGRESS_REMAINING, m, y1, x0s, 8\r
+  LTEXT  "Files:",          IDC_PROGRESS_FILES,     m, y2, x0s, 8\r
+  LTEXT  "Compression ratio:",IDC_PROGRESS_RATIO,   m, y3, x0s, 8\r
+  LTEXT  "Errors:", IDC_PROGRESS_ERRORS,            m, y4, x0s, 8\r
+\r
+  LTEXT  "Total size:",      IDC_PROGRESS_TOTAL,    x2, y0, x2s, 8\r
+  LTEXT  "Speed:",           IDC_PROGRESS_SPEED,    x2, y1, x2s, 8\r
+  LTEXT  "Processed:",       IDC_PROGRESS_UNPACKED, x2, y2, x2s, 8\r
+  LTEXT  "Compressed size:", IDC_PROGRESS_PACKED,   x2, y3, x2s, 8\r
+\r
+  RTEXT  "",  IDC_PROGRESS_ELAPSED_VALUE,   x1, y0, x1s, 8\r
+  RTEXT  "",  IDC_PROGRESS_REMAINING_VALUE, x1, y1, x1s, 8\r
+  RTEXT  "",  IDC_PROGRESS_FILES_VALUE,     x1, y2, x1s, 8\r
+  RTEXT  "",  IDC_PROGRESS_RATIO_VALUE,     x1, y3, x1s, 8\r
+  RTEXT  "", IDC_PROGRESS_ERRORS_VALUE,     x1, y4, x1s, 8\r
+\r
+  RTEXT  "",  IDC_PROGRESS_TOTAL_VALUE,     x3, y0, x3s, 8\r
+  RTEXT  "",  IDC_PROGRESS_SPEED_VALUE,     x3, y1, x3s, 8\r
+  RTEXT  "",  IDC_PROGRESS_UNPACKED_VALUE,  x3, y2, x3s, 8\r
+  RTEXT  "",  IDC_PROGRESS_PACKED_VALUE,    x3, y3, x3s, 8\r
+\r
+  LTEXT  "", IDC_PROGRESS_FILE_NAME, m, z2, xc, z2s, SS_NOPREFIX | SS_LEFTNOWORDWRAP\r
+  CONTROL "Progress1", IDC_PROGRESS1, "msctls_progress32", PBS_SMOOTH | WS_BORDER, m, z1, xc, z1s\r
+\r
+\r
+  CONTROL "List1", IDC_PROGRESS_LIST, "SysListView32",\r
+          LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,\r
+          m, z0, xc, z0s\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/ProgressDialogRes.h b/CPP/7zip/UI/FileManager/ProgressDialogRes.h
new file mode 100755 (executable)
index 0000000..7f98281
--- /dev/null
@@ -0,0 +1,3 @@
+#define IDD_DIALOG_PROGRESS          500\r
+\r
+#define IDC_PROGRESS1                1000\r
diff --git a/CPP/7zip/UI/FileManager/PropertyName.cpp b/CPP/7zip/UI/FileManager/PropertyName.cpp
new file mode 100755 (executable)
index 0000000..a6bac78
--- /dev/null
@@ -0,0 +1,110 @@
+// PropertyName.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+\r
+#include "Windows/ResourceString.h"\r
+\r
+#include "../../PropID.h"\r
+\r
+#include "LangUtils.h"\r
+#include "PropertyName.h"\r
+\r
+#include "resource.h"\r
+#include "PropertyNameRes.h"\r
+\r
+struct CPropertyIDNamePair\r
+{\r
+  PROPID PropID;\r
+  UINT ResourceID;\r
+  UInt32 LangID;\r
+};\r
+\r
+static CPropertyIDNamePair kPropertyIDNamePairs[] =\r
+{\r
+  { kpidPath, IDS_PROP_PATH, 0x02000203 },\r
+  { kpidName, IDS_PROP_NAME, 0x02000204 },\r
+  { kpidExtension, IDS_PROP_EXTENSION, 0x02000205 },\r
+  { kpidIsDir, IDS_PROP_IS_FOLDER, 0x02000206},\r
+  { kpidSize, IDS_PROP_SIZE, 0x02000207},\r
+  { kpidPackSize, IDS_PROP_PACKED_SIZE, 0x02000208 },\r
+  { kpidAttrib, IDS_PROP_ATTRIBUTES, 0x02000209 },\r
+  { kpidCTime, IDS_PROP_CTIME, 0x0200020A },\r
+  { kpidATime, IDS_PROP_ATIME, 0x0200020B },\r
+  { kpidMTime, IDS_PROP_MTIME, 0x0200020C },\r
+  { kpidSolid, IDS_PROP_SOLID, 0x0200020D },\r
+  { kpidCommented, IDS_PROP_C0MMENTED, 0x0200020E },\r
+  { kpidEncrypted, IDS_PROP_ENCRYPTED, 0x0200020F },\r
+  { kpidSplitBefore, IDS_PROP_SPLIT_BEFORE, 0x02000210 },\r
+  { kpidSplitAfter, IDS_PROP_SPLIT_AFTER, 0x02000211 },\r
+  { kpidDictionarySize, IDS_PROP_DICTIONARY_SIZE, 0x02000212 },\r
+  { kpidCRC, IDS_PROP_CRC, 0x02000213 },\r
+  { kpidType, IDS_PROP_FILE_TYPE, 0x02000214},\r
+  { kpidIsAnti, IDS_PROP_ANTI, 0x02000215 },\r
+  { kpidMethod, IDS_PROP_METHOD, 0x02000216 },\r
+  { kpidHostOS, IDS_PROP_HOST_OS, 0x02000217 },\r
+  { kpidFileSystem, IDS_PROP_FILE_SYSTEM, 0x02000218},\r
+  { kpidUser, IDS_PROP_USER, 0x02000219},\r
+  { kpidGroup, IDS_PROP_GROUP, 0x0200021A},\r
+  { kpidBlock, IDS_PROP_BLOCK, 0x0200021B },\r
+  { kpidComment, IDS_PROP_COMMENT, 0x0200021C },\r
+  { kpidPosition, IDS_PROP_POSITION, 0x0200021D },\r
+  { kpidPrefix, IDS_PROP_PREFIX, 0x0200021E },\r
+  { kpidNumSubDirs, IDS_PROP_FOLDERS, 0x0200021F },\r
+  { kpidNumSubFiles, IDS_PROP_FILES, 0x02000220 },\r
+  { kpidUnpackVer, IDS_PROP_VERSION, 0x02000221},\r
+  { kpidVolume, IDS_PROP_VOLUME, 0x02000222},\r
+  { kpidIsVolume, IDS_PROP_IS_VOLUME, 0x02000223},\r
+  { kpidOffset, IDS_PROP_OFFSET, 0x02000224},\r
+  { kpidLinks, IDS_PROP_LINKS, 0x02000225},\r
+  { kpidNumBlocks, IDS_PROP_NUM_BLOCKS, 0x02000226},\r
+  { kpidNumVolumes, IDS_PROP_NUM_VOLUMES, 0x02000227},\r
+\r
+  { kpidBit64, IDS_PROP_BIT64, 0x02000229},\r
+  { kpidBigEndian, IDS_PROP_BIG_ENDIAN, 0x0200022A},\r
+  { kpidCpu, IDS_PROP_CPU, 0x0200022B},\r
+  { kpidPhySize, IDS_PROP_PHY_SIZE, 0x0200022C},\r
+  { kpidHeadersSize, IDS_PROP_HEADERS_SIZE, 0x0200022D},\r
+  { kpidChecksum, IDS_PROP_CHECKSUM, 0x0200022E},\r
+  { kpidCharacts, IDS_PROP_CHARACTS, 0x0200022F},\r
+  { kpidVa, IDS_PROP_VA, 0x02000230},\r
+  { kpidId, IDS_PROP_ID, 0x02000231 },\r
+  { kpidShortName, IDS_PROP_SHORT_NAME, 0x02000232 },\r
+  { kpidCreatorApp, IDS_PROP_CREATOR_APP, 0x02000233 },\r
+  { kpidSectorSize, IDS_PROP_SECTOR_SIZE, 0x02000234 },\r
+  { kpidPosixAttrib, IDS_PROP_POSIX_ATTRIB, 0x02000235 },\r
+  { kpidLink, IDS_PROP_LINK, 0x02000236 },\r
+  { kpidError, IDS_PROP_ERROR, 0x02000605 },\r
\r
+  { kpidTotalSize, IDS_PROP_TOTAL_SIZE, 0x03031100 },\r
+  { kpidFreeSpace, IDS_PROP_FREE_SPACE, 0x03031101 },\r
+  { kpidClusterSize, IDS_PROP_CLUSTER_SIZE, 0x03031102},\r
+  { kpidVolumeName, IDS_PROP_VOLUME_NAME, 0x03031103 },\r
+\r
+  { kpidLocalName, IDS_PROP_LOCAL_NAME, 0x03031200 },\r
+  { kpidProvider, IDS_PROP_PROVIDER, 0x03031201 }\r
+};\r
+\r
+int FindProperty(PROPID propID)\r
+{\r
+  for (int i = 0; i < sizeof(kPropertyIDNamePairs) / sizeof(kPropertyIDNamePairs[0]); i++)\r
+    if (kPropertyIDNamePairs[i].PropID == propID)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+UString GetNameOfProperty(PROPID propID, const wchar_t *name)\r
+{\r
+  int index = FindProperty(propID);\r
+  if (index < 0)\r
+  {\r
+    if (name)\r
+      return name;\r
+    wchar_t s[16];\r
+    ConvertUInt32ToString(propID, s);\r
+    return s;\r
+  }\r
+  const CPropertyIDNamePair &pair = kPropertyIDNamePairs[index];\r
+  return LangString(pair.ResourceID, pair.LangID);\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/PropertyName.h b/CPP/7zip/UI/FileManager/PropertyName.h
new file mode 100755 (executable)
index 0000000..9a590b4
--- /dev/null
@@ -0,0 +1,10 @@
+// PropertyName.h\r
+\r
+#ifndef __PROPERTYNAME_H\r
+#define __PROPERTYNAME_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+UString GetNameOfProperty(PROPID propID, const wchar_t *name);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/PropertyName.rc b/CPP/7zip/UI/FileManager/PropertyName.rc
new file mode 100755 (executable)
index 0000000..625b427
--- /dev/null
@@ -0,0 +1,60 @@
+#include "PropertyNameRes.h"\r
+\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r
+\r
+STRINGTABLE\r
+BEGIN\r
+  IDS_PROP_PATH       "Path"\r
+  IDS_PROP_NAME       "Name"\r
+  IDS_PROP_EXTENSION  "Extension"\r
+  IDS_PROP_IS_FOLDER  "Folder"\r
+  IDS_PROP_SIZE       "Size"\r
+  IDS_PROP_PACKED_SIZE "Packed Size"\r
+  IDS_PROP_ATTRIBUTES "Attributes"\r
+  IDS_PROP_CTIME "Created"\r
+  IDS_PROP_ATIME "Accessed"\r
+  IDS_PROP_MTIME "Modified"\r
+  IDS_PROP_SOLID      "Solid"\r
+  IDS_PROP_C0MMENTED  "Commented"\r
+  IDS_PROP_ENCRYPTED  "Encrypted"\r
+  IDS_PROP_DICTIONARY_SIZE "Dictionary Size"\r
+  IDS_PROP_SPLIT_BEFORE "Split Before"\r
+  IDS_PROP_SPLIT_AFTER "Split After"\r
+  IDS_PROP_CRC        "CRC"\r
+  IDS_PROP_FILE_TYPE  "Type"\r
+  IDS_PROP_ANTI       "Anti"\r
+  IDS_PROP_METHOD     "Method"\r
+  IDS_PROP_HOST_OS    "Host OS"\r
+  IDS_PROP_FILE_SYSTEM "File System"\r
+  IDS_PROP_USER "User"\r
+  IDS_PROP_GROUP "Group"\r
+  IDS_PROP_BLOCK "Block"\r
+  IDS_PROP_COMMENT "Comment"\r
+  IDS_PROP_POSITION "Position"\r
+  IDS_PROP_PREFIX "Path Prefix"\r
+  IDS_PROP_FOLDERS "Folders"\r
+  IDS_PROP_FILES "Files"\r
+  IDS_PROP_VERSION "Version"\r
+  IDS_PROP_VOLUME "Volume"\r
+  IDS_PROP_IS_VOLUME "Multivolume"\r
+  IDS_PROP_OFFSET "Offset"\r
+  IDS_PROP_LINKS "Links"\r
+  IDS_PROP_NUM_BLOCKS "Blocks"\r
+  IDS_PROP_NUM_VOLUMES "Volumes"\r
+\r
+  IDS_PROP_BIT64 "64-bit"\r
+  IDS_PROP_BIG_ENDIAN "Big-endian"\r
+  IDS_PROP_CPU "CPU"\r
+  IDS_PROP_PHY_SIZE "Physical Size"\r
+  IDS_PROP_HEADERS_SIZE "Headers Size"\r
+  IDS_PROP_CHECKSUM "Checksum"\r
+  IDS_PROP_CHARACTS "Characteristics"\r
+  IDS_PROP_VA "Virtual Address"\r
+  IDS_PROP_ID "ID"\r
+  IDS_PROP_SHORT_NAME "Short Name"\r
+  IDS_PROP_CREATOR_APP "Creator Application"\r
+  IDS_PROP_SECTOR_SIZE "Sector Size"\r
+  IDS_PROP_POSIX_ATTRIB "Mode"\r
+  IDS_PROP_LINK "Link"\r
+  IDS_PROP_ERROR "Error"\r
+END\r
diff --git a/CPP/7zip/UI/FileManager/PropertyNameRes.h b/CPP/7zip/UI/FileManager/PropertyNameRes.h
new file mode 100755 (executable)
index 0000000..7859657
--- /dev/null
@@ -0,0 +1,53 @@
+#define IDS_PROP_PATH                3\r
+#define IDS_PROP_NAME                4\r
+#define IDS_PROP_EXTENSION           5\r
+#define IDS_PROP_IS_FOLDER           6\r
+#define IDS_PROP_SIZE                7\r
+#define IDS_PROP_PACKED_SIZE         8\r
+#define IDS_PROP_ATTRIBUTES          9\r
+#define IDS_PROP_CTIME              10\r
+#define IDS_PROP_ATIME              11\r
+#define IDS_PROP_MTIME              12\r
+#define IDS_PROP_SOLID              13\r
+#define IDS_PROP_C0MMENTED          14\r
+#define IDS_PROP_ENCRYPTED          15\r
+#define IDS_PROP_DICTIONARY_SIZE    16\r
+#define IDS_PROP_SPLIT_BEFORE       17\r
+#define IDS_PROP_SPLIT_AFTER        18\r
+#define IDS_PROP_CRC                19\r
+#define IDS_PROP_FILE_TYPE          20\r
+#define IDS_PROP_ANTI               21\r
+#define IDS_PROP_METHOD             22\r
+#define IDS_PROP_HOST_OS            23\r
+#define IDS_PROP_FILE_SYSTEM        24\r
+#define IDS_PROP_USER               25\r
+#define IDS_PROP_GROUP              26\r
+#define IDS_PROP_BLOCK              27\r
+#define IDS_PROP_COMMENT            28\r
+#define IDS_PROP_POSITION           29\r
+#define IDS_PROP_PREFIX             30\r
+#define IDS_PROP_FOLDERS            31\r
+#define IDS_PROP_FILES              32\r
+#define IDS_PROP_VERSION            33\r
+#define IDS_PROP_VOLUME             34\r
+#define IDS_PROP_IS_VOLUME          35\r
+#define IDS_PROP_OFFSET             36\r
+#define IDS_PROP_LINKS              37\r
+#define IDS_PROP_NUM_BLOCKS         38\r
+#define IDS_PROP_NUM_VOLUMES        39\r
+\r
+#define IDS_PROP_BIT64              41\r
+#define IDS_PROP_BIG_ENDIAN         42\r
+#define IDS_PROP_CPU                43\r
+#define IDS_PROP_PHY_SIZE           44\r
+#define IDS_PROP_HEADERS_SIZE       45\r
+#define IDS_PROP_CHECKSUM           46\r
+#define IDS_PROP_CHARACTS           47\r
+#define IDS_PROP_VA                 48\r
+#define IDS_PROP_ID                 49\r
+#define IDS_PROP_SHORT_NAME         50\r
+#define IDS_PROP_CREATOR_APP        51\r
+#define IDS_PROP_SECTOR_SIZE        52\r
+#define IDS_PROP_POSIX_ATTRIB       53\r
+#define IDS_PROP_LINK               54\r
+#define IDS_PROP_ERROR              55\r
diff --git a/CPP/7zip/UI/FileManager/RegistryAssociations.cpp b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp
new file mode 100755 (executable)
index 0000000..68f949c
--- /dev/null
@@ -0,0 +1,312 @@
+// RegistryAssociations.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "RegistryAssociations.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+#include "Common/StringToInt.h"\r
+\r
+#include "Windows/Registry.h"\r
+#include "Windows/Synchronization.h"\r
+\r
+#include "StringUtils.h"\r
+\r
+using namespace NWindows;\r
+using namespace NRegistry;\r
+\r
+namespace NRegistryAssociations {\r
+  \r
+static NSynchronization::CCriticalSection g_CriticalSection;\r
+\r
+#define REG_PATH_FM TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") TEXT(STRING_PATH_SEPARATOR) TEXT("FM")\r
+\r
+/*\r
+\r
+static const TCHAR *kCUKeyPath = REG_PATH_FM;\r
+static const WCHAR *kExtPlugins = L"Plugins";\r
+static const TCHAR *kExtEnabled = TEXT("Enabled");\r
+\r
+#define kAssociations TEXT("Associations")\r
+#define kAssociationsPath REG_PATH_FM TEXT(STRING_PATH_SEPARATOR) kAssociations\r
+\r
+bool ReadInternalAssociation(const wchar_t *ext, CExtInfo &extInfo)\r
+{\r
+  NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\r
+  CKey key;\r
+  if (key.Open(HKEY_CURRENT_USER,\r
+      CSysString(kAssociationsPath TEXT(STRING_PATH_SEPARATOR)) +\r
+      GetSystemString(ext), KEY_READ) != ERROR_SUCCESS)\r
+    return false;\r
+  UString pluginsString;\r
+  key.QueryValue(kExtPlugins, pluginsString);\r
+  SplitString(pluginsString, extInfo.Plugins);\r
+  return true;\r
+}\r
+\r
+void ReadInternalAssociations(CObjectVector<CExtInfo> &items)\r
+{\r
+  items.Clear();\r
+  NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\r
+  CKey associationsKey;\r
+  if (associationsKey.Open(HKEY_CURRENT_USER, kAssociationsPath, KEY_READ) != ERROR_SUCCESS)\r
+    return;\r
+  CSysStringVector extNames;\r
+  associationsKey.EnumKeys(extNames);\r
+  for(int i = 0; i < extNames.Size(); i++)\r
+  {\r
+    const CSysString extName = extNames[i];\r
+    CExtInfo extInfo;\r
+    // extInfo.Enabled = false;\r
+    extInfo.Ext = GetUnicodeString(extName);\r
+    CKey key;\r
+    if (key.Open(associationsKey, extName, KEY_READ) != ERROR_SUCCESS)\r
+      return;\r
+    UString pluginsString;\r
+    key.QueryValue(kExtPlugins, pluginsString);\r
+    SplitString(pluginsString, extInfo.Plugins);\r
+    // if (key.QueryValue(kExtEnabled, extInfo.Enabled) != ERROR_SUCCESS)\r
+    //   extInfo.Enabled = false;\r
+    items.Add(extInfo);\r
+  }\r
+}\r
+\r
+void WriteInternalAssociations(const CObjectVector<CExtInfo> &items)\r
+{\r
+  NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\r
+  CKey mainKey;\r
+  mainKey.Create(HKEY_CURRENT_USER, kCUKeyPath);\r
+  mainKey.RecurseDeleteKey(kAssociations);\r
+  CKey associationsKey;\r
+  associationsKey.Create(mainKey, kAssociations);\r
+  for(int i = 0; i < items.Size(); i++)\r
+  {\r
+    const CExtInfo &extInfo = items[i];\r
+    CKey key;\r
+    key.Create(associationsKey, GetSystemString(extInfo.Ext));\r
+    key.SetValue(kExtPlugins, JoinStrings(extInfo.Plugins));\r
+    // key.SetValue(kExtEnabled, extInfo.Enabled);\r
+  }\r
+}\r
+*/\r
+\r
+///////////////////////////////////\r
+// External\r
+\r
+static const TCHAR *kShellNewKeyName = TEXT("ShellNew");\r
+static const TCHAR *kShellNewDataValueName = TEXT("Data");\r
+  \r
+static const TCHAR *kDefaultIconKeyName = TEXT("DefaultIcon");\r
+static const TCHAR *kShellKeyName = TEXT("shell");\r
+static const TCHAR *kOpenKeyName = TEXT("open");\r
+static const TCHAR *kCommandKeyName = TEXT("command");\r
+static const TCHAR *k7zipPrefix = TEXT("7-Zip.");\r
+\r
+static CSysString GetExtensionKeyName(const CSysString &extension)\r
+{\r
+  return CSysString(TEXT(".")) + extension;\r
+}\r
+\r
+static CSysString GetExtProgramKeyName(const CSysString &extension)\r
+{\r
+  return CSysString(k7zipPrefix) + extension;\r
+}\r
+\r
+static bool CheckShellExtensionInfo2(const CSysString &extension,\r
+    CSysString programKeyName, UString &iconPath, int &iconIndex)\r
+{\r
+  iconIndex = -1;\r
+  iconPath.Empty();\r
+  NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\r
+  CKey extKey;\r
+  if (extKey.Open(HKEY_CLASSES_ROOT, GetExtensionKeyName(extension), KEY_READ) != ERROR_SUCCESS)\r
+    return false;\r
+  if (extKey.QueryValue(NULL, programKeyName) != ERROR_SUCCESS)\r
+    return false;\r
+  UString s = GetUnicodeString(k7zipPrefix);\r
+  if (s.CompareNoCase(GetUnicodeString(programKeyName.Left(s.Length()))) != 0)\r
+    return false;\r
+  CKey iconKey;\r
+  if (extKey.Open(HKEY_CLASSES_ROOT, programKeyName + CSysString(TEXT(CHAR_PATH_SEPARATOR)) + kDefaultIconKeyName, KEY_READ) != ERROR_SUCCESS)\r
+    return false;\r
+  UString value;\r
+  if (extKey.QueryValue(NULL, value) == ERROR_SUCCESS)\r
+  {\r
+    int pos = value.ReverseFind(L',');\r
+    iconPath = value;\r
+    if (pos >= 0)\r
+    {\r
+      const wchar_t *end;\r
+      UInt64 index = ConvertStringToUInt64((const wchar_t *)value + pos + 1, &end);\r
+      if (*end == 0)\r
+      {\r
+        iconIndex = (int)index;\r
+        iconPath = value.Left(pos);\r
+      }\r
+    }\r
+  }\r
+  return true;\r
+}\r
+\r
+bool CheckShellExtensionInfo(const CSysString &extension, UString &iconPath, int &iconIndex)\r
+{\r
+  NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\r
+  CSysString programKeyName;\r
+  if (!CheckShellExtensionInfo2(extension, programKeyName, iconPath, iconIndex))\r
+    return false;\r
+  CKey extProgKey;\r
+  return (extProgKey.Open(HKEY_CLASSES_ROOT, programKeyName, KEY_READ) == ERROR_SUCCESS);\r
+}\r
+\r
+static void DeleteShellExtensionKey(const CSysString &extension)\r
+{\r
+  NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\r
+  CKey rootKey;\r
+  rootKey.Attach(HKEY_CLASSES_ROOT);\r
+  rootKey.RecurseDeleteKey(GetExtensionKeyName(extension));\r
+  rootKey.Detach();\r
+}\r
+\r
+static void DeleteShellExtensionProgramKey(const CSysString &extension)\r
+{\r
+  NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\r
+  CKey rootKey;\r
+  rootKey.Attach(HKEY_CLASSES_ROOT);\r
+  rootKey.RecurseDeleteKey(GetExtProgramKeyName(extension));\r
+  rootKey.Detach();\r
+}\r
+\r
+void DeleteShellExtensionInfo(const CSysString &extension)\r
+{\r
+  CSysString programKeyName;\r
+  UString iconPath;\r
+  int iconIndex;\r
+  if (CheckShellExtensionInfo2(extension, programKeyName, iconPath, iconIndex))\r
+    DeleteShellExtensionKey(extension);\r
+  DeleteShellExtensionProgramKey(extension);\r
+}\r
+\r
+void AddShellExtensionInfo(const CSysString &extension,\r
+    const UString &programTitle,\r
+    const UString &programOpenCommand,\r
+    const UString &iconPath, int iconIndex,\r
+    const void *shellNewData, int shellNewDataSize)\r
+{\r
+  DeleteShellExtensionKey(extension);\r
+  DeleteShellExtensionProgramKey(extension);\r
+  NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\r
+  CSysString programKeyName;\r
+  {\r
+    CSysString ext = extension;\r
+    if (iconIndex < 0)\r
+      ext = TEXT("*");\r
+    programKeyName = GetExtProgramKeyName(ext);\r
+  }\r
+  {\r
+    CKey extKey;\r
+    extKey.Create(HKEY_CLASSES_ROOT, GetExtensionKeyName(extension));\r
+    extKey.SetValue(NULL, programKeyName);\r
+    if (shellNewData != NULL)\r
+    {\r
+      CKey shellNewKey;\r
+      shellNewKey.Create(extKey, kShellNewKeyName);\r
+      shellNewKey.SetValue(kShellNewDataValueName, shellNewData, shellNewDataSize);\r
+    }\r
+  }\r
+  CKey programKey;\r
+  programKey.Create(HKEY_CLASSES_ROOT, programKeyName);\r
+  programKey.SetValue(NULL, programTitle);\r
+  {\r
+    CKey iconKey;\r
+    iconKey.Create(programKey, kDefaultIconKeyName);\r
+    UString iconPathFull = iconPath;\r
+    if (iconIndex < 0)\r
+      iconIndex = 0;\r
+    // if (iconIndex >= 0)\r
+    {\r
+      iconPathFull += L",";\r
+      wchar_t s[16];\r
+      ConvertUInt32ToString(iconIndex, s);\r
+      iconPathFull += s;\r
+    }\r
+    iconKey.SetValue(NULL, iconPathFull);\r
+  }\r
+\r
+  CKey shellKey;\r
+  shellKey.Create(programKey, kShellKeyName);\r
+  shellKey.SetValue(NULL, TEXT(""));\r
+\r
+  CKey openKey;\r
+  openKey.Create(shellKey, kOpenKeyName);\r
+  openKey.SetValue(NULL, TEXT(""));\r
+  \r
+  CKey commandKey;\r
+  commandKey.Create(openKey, kCommandKeyName);\r
+\r
+  commandKey.SetValue(NULL, programOpenCommand);\r
+}\r
+\r
+///////////////////////////\r
+// ContextMenu\r
+/*\r
+\r
+static const TCHAR *kContextMenuKeyName = TEXT("\\shellex\\ContextMenuHandlers\\7-Zip");\r
+static const TCHAR *kContextMenuHandlerCLASSIDValue =\r
+    TEXT("{23170F69-40C1-278A-1000-000100020000}");\r
+static const TCHAR *kRootKeyNameForFile = TEXT("*");\r
+static const TCHAR *kRootKeyNameForFolder = TEXT("Folder");\r
+\r
+static CSysString GetFullContextMenuKeyName(const CSysString &aKeyName)\r
+  { return (aKeyName + kContextMenuKeyName); }\r
+\r
+static bool CheckContextMenuHandlerCommon(const CSysString &aKeyName)\r
+{\r
+  NSynchronization::CCriticalSectionLock lock(&g_CriticalSection, true);\r
+  CKey aKey;\r
+  if (aKey.Open(HKEY_CLASSES_ROOT, GetFullContextMenuKeyName(aKeyName), KEY_READ)\r
+      != ERROR_SUCCESS)\r
+    return false;\r
+  CSysString aValue;\r
+  if (aKey.QueryValue(NULL, aValue) != ERROR_SUCCESS)\r
+    return false;\r
+  return (aValue.CompareNoCase(kContextMenuHandlerCLASSIDValue) == 0);\r
+}\r
+\r
+bool CheckContextMenuHandler()\r
+{\r
+  return CheckContextMenuHandlerCommon(kRootKeyNameForFile) &&\r
+    CheckContextMenuHandlerCommon(kRootKeyNameForFolder);\r
+}\r
+\r
+static void DeleteContextMenuHandlerCommon(const CSysString &aKeyName)\r
+{\r
+  CKey rootKey;\r
+  rootKey.Attach(HKEY_CLASSES_ROOT);\r
+  rootKey.RecurseDeleteKey(GetFullContextMenuKeyName(aKeyName));\r
+  rootKey.Detach();\r
+}\r
+\r
+void DeleteContextMenuHandler()\r
+{\r
+  DeleteContextMenuHandlerCommon(kRootKeyNameForFile);\r
+  DeleteContextMenuHandlerCommon(kRootKeyNameForFolder);\r
+}\r
+\r
+static void AddContextMenuHandlerCommon(const CSysString &aKeyName)\r
+{\r
+  DeleteContextMenuHandlerCommon(aKeyName);\r
+  NSynchronization::CCriticalSectionLock lock(&g_CriticalSection, true);\r
+  CKey aKey;\r
+  aKey.Create(HKEY_CLASSES_ROOT, GetFullContextMenuKeyName(aKeyName));\r
+  aKey.SetValue(NULL, kContextMenuHandlerCLASSIDValue);\r
+}\r
+\r
+void AddContextMenuHandler()\r
+{\r
+  AddContextMenuHandlerCommon(kRootKeyNameForFile);\r
+  AddContextMenuHandlerCommon(kRootKeyNameForFolder);\r
+}\r
+*/\r
+\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/RegistryAssociations.h b/CPP/7zip/UI/FileManager/RegistryAssociations.h
new file mode 100755 (executable)
index 0000000..1bdc909
--- /dev/null
@@ -0,0 +1,46 @@
+// RegistryAssociations.h\r
+\r
+#ifndef __REGISTRYASSOCIATIONS_H\r
+#define __REGISTRYASSOCIATIONS_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+namespace NRegistryAssociations {\r
+\r
+  /*\r
+  struct CExtInfo\r
+  {\r
+    UString Ext;\r
+    UStringVector Plugins;\r
+    // bool Enabled;\r
+  };\r
+  bool ReadInternalAssociation(const wchar_t *ext, CExtInfo &extInfo);\r
+  void ReadInternalAssociations(CObjectVector<CExtInfo> &items);\r
+  void WriteInternalAssociations(const CObjectVector<CExtInfo> &items);\r
+  */\r
+\r
+  bool CheckShellExtensionInfo(const CSysString &extension, UString &iconPath, int &iconIndex);\r
+\r
+  // void ReadCompressionInfo(NZipSettings::NCompression::CInfo &anInfo,\r
+  void DeleteShellExtensionInfo(const CSysString &extension);\r
+\r
+  void AddShellExtensionInfo(const CSysString &extension,\r
+      const UString &programTitle,\r
+      const UString &programOpenCommand,\r
+      const UString &iconPath, int iconIndex,\r
+      const void *shellNewData, int shellNewDataSize);\r
+\r
+\r
+  ///////////////////////////\r
+  // ContextMenu\r
+  /*\r
+  bool CheckContextMenuHandler();\r
+  void AddContextMenuHandler();\r
+  void DeleteContextMenuHandler();\r
+  */\r
+\r
+}\r
+\r
+// bool GetProgramDirPrefix(CSysString &aFolder);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/RegistryPlugins.cpp b/CPP/7zip/UI/FileManager/RegistryPlugins.cpp
new file mode 100755 (executable)
index 0000000..13bd678
--- /dev/null
@@ -0,0 +1,141 @@
+// RegistryPlugins.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/DLL.h"\r
+#include "Windows/PropVariant.h"\r
+#include "Windows/FileFind.h"\r
+\r
+#include "ProgramLocation.h"\r
+#include "RegistryPlugins.h"\r
+#include "IFolder.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+\r
+/*\r
+static const TCHAR *kLMBasePath = TEXT("Software\\7-Zip\\FM");\r
+\r
+static const TCHAR *kPluginsKeyName = TEXT("Plugins");\r
+static const TCHAR *kPluginsOpenClassIDValue = TEXT("CLSID");\r
+static const TCHAR *kPluginsOptionsClassIDValue = TEXT("Options");\r
+static const TCHAR *kPluginsTypeValue = TEXT("Type");\r
+\r
+static CSysString GetFileFolderPluginsKeyName()\r
+{\r
+  return CSysString(kLMBasePath) + CSysString(TEXT('\\')) +\r
+      CSysString(kPluginsKeyName);\r
+}\r
+\r
+*/\r
+\r
+typedef UINT32 (WINAPI * GetPluginPropertyFunc)(PROPID propID, PROPVARIANT *value);\r
+\r
+static bool ReadPluginInfo(CPluginInfo &pluginInfo, bool needCheckDll)\r
+{\r
+  if (needCheckDll)\r
+  {\r
+    NDLL::CLibrary lib;\r
+    if (!lib.LoadEx(pluginInfo.FilePath, LOAD_LIBRARY_AS_DATAFILE))\r
+      return false;\r
+  }\r
+  NDLL::CLibrary lib;\r
+  if (!lib.Load(pluginInfo.FilePath))\r
+    return false;\r
+  GetPluginPropertyFunc getPluginProperty = (GetPluginPropertyFunc)lib.GetProc("GetPluginProperty");\r
+  if (getPluginProperty == NULL)\r
+    return false;\r
+  \r
+  NCOM::CPropVariant prop;\r
+  if (getPluginProperty(NPlugin::kName, &prop) != S_OK)\r
+    return false;\r
+  if (prop.vt != VT_BSTR)\r
+    return false;\r
+  pluginInfo.Name = prop.bstrVal;\r
+  prop.Clear();\r
+  \r
+  if (getPluginProperty(NPlugin::kClassID, &prop) != S_OK)\r
+    return false;\r
+  if (prop.vt == VT_EMPTY)\r
+    pluginInfo.ClassIDDefined = false;\r
+  else if (prop.vt != VT_BSTR)\r
+    return false;\r
+  else\r
+  {\r
+    pluginInfo.ClassIDDefined = true;\r
+    pluginInfo.ClassID = *(const GUID *)prop.bstrVal;\r
+  }\r
+  prop.Clear();\r
+  \r
+  if (getPluginProperty(NPlugin::kOptionsClassID, &prop) != S_OK)\r
+    return false;\r
+  if (prop.vt == VT_EMPTY)\r
+    pluginInfo.OptionsClassIDDefined = false;\r
+  else if (prop.vt != VT_BSTR)\r
+    return false;\r
+  else\r
+  {\r
+    pluginInfo.OptionsClassIDDefined = true;\r
+    pluginInfo.OptionsClassID = *(const GUID *)prop.bstrVal;\r
+  }\r
+  prop.Clear();\r
+\r
+  if (getPluginProperty(NPlugin::kType, &prop) != S_OK)\r
+    return false;\r
+  if (prop.vt == VT_EMPTY)\r
+    pluginInfo.Type = kPluginTypeFF;\r
+  else if (prop.vt == VT_UI4)\r
+    pluginInfo.Type = (EPluginType)prop.ulVal;\r
+  else\r
+    return false;\r
+  return true;\r
+}\r
+\r
+UString GetProgramFolderPrefix();\r
+\r
+void ReadPluginInfoList(CObjectVector<CPluginInfo> &plugins)\r
+{\r
+  plugins.Clear();\r
+\r
+  UString baseFolderPrefix;\r
+  GetProgramFolderPath(baseFolderPrefix);\r
+  {\r
+    CPluginInfo pluginInfo;\r
+    pluginInfo.FilePath = baseFolderPrefix + L"7-zip.dll";\r
+    if (::ReadPluginInfo(pluginInfo, false))\r
+      plugins.Add(pluginInfo);\r
+  }\r
+  UString folderPath = baseFolderPrefix + L"Plugins" WSTRING_PATH_SEPARATOR;\r
+  NFind::CEnumeratorW enumerator(folderPath + L"*");\r
+  NFind::CFileInfoW fileInfo;\r
+  while (enumerator.Next(fileInfo))\r
+  {\r
+    if (fileInfo.IsDir())\r
+      continue;\r
+    CPluginInfo pluginInfo;\r
+    pluginInfo.FilePath = folderPath + fileInfo.Name;\r
+    if (::ReadPluginInfo(pluginInfo, true))\r
+      plugins.Add(pluginInfo);\r
+  }\r
+}\r
+\r
+void ReadFileFolderPluginInfoList(CObjectVector<CPluginInfo> &plugins)\r
+{\r
+  ReadPluginInfoList(plugins);\r
+  for (int i = 0; i < plugins.Size();)\r
+    if (plugins[i].Type != kPluginTypeFF)\r
+      plugins.Delete(i);\r
+    else\r
+      i++;\r
+  {\r
+    CPluginInfo p;\r
+    // p.FilePath.Empty();\r
+    p.Type = kPluginTypeFF;\r
+    p.Name = L"7-Zip";\r
+    // p.ClassID = CLSID_CAgentArchiveHandler;\r
+    p.ClassIDDefined = true;\r
+    // p.OptionsClassID;\r
+    p.OptionsClassIDDefined = false;\r
+    plugins.Add(p);\r
+  }\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/RegistryPlugins.h b/CPP/7zip/UI/FileManager/RegistryPlugins.h
new file mode 100755 (executable)
index 0000000..9af9682
--- /dev/null
@@ -0,0 +1,32 @@
+// RegistryPlugins.h\r
+\r
+#ifndef __REGISTRYPLUGINS_H\r
+#define __REGISTRYPLUGINS_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+enum EPluginType\r
+{\r
+  kPluginTypeFF = 0\r
+};\r
+\r
+struct CPluginInfo\r
+{\r
+  UString FilePath;\r
+  EPluginType Type;\r
+  UString Name;\r
+  CLSID ClassID;\r
+  CLSID OptionsClassID;\r
+  bool ClassIDDefined;\r
+  bool OptionsClassIDDefined;\r
+\r
+  // CSysString Extension;\r
+  // CSysString AddExtension;\r
+  // bool UpdateEnabled;\r
+  // bool KeepName;\r
+};\r
+\r
+void ReadPluginInfoList(CObjectVector<CPluginInfo> &plugins);\r
+void ReadFileFolderPluginInfoList(CObjectVector<CPluginInfo> &plugins);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/RegistryUtils.cpp b/CPP/7zip/UI/FileManager/RegistryUtils.cpp
new file mode 100755 (executable)
index 0000000..7c3aea9
--- /dev/null
@@ -0,0 +1,160 @@
+// RegistryUtils.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+\r
+#include "Windows/Registry.h"\r
+\r
+#include "RegistryUtils.h"\r
+\r
+using namespace NWindows;\r
+using namespace NRegistry;\r
+\r
+#define REG_PATH_7Z TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip")\r
+\r
+static const TCHAR *kCUBasePath = REG_PATH_7Z;\r
+static const TCHAR *kCU_FMPath = REG_PATH_7Z TEXT(STRING_PATH_SEPARATOR) TEXT("FM");\r
+// static const TCHAR *kLM_Path = REG_PATH_7Z TEXT(STRING_PATH_SEPARATOR) TEXT("FM");\r
+\r
+static const WCHAR *kLangValueName = L"Lang";\r
+static const WCHAR *kEditor = L"Editor";\r
+static const WCHAR *kDiff = L"Diff";\r
+static const TCHAR *kShowDots = TEXT("ShowDots");\r
+static const TCHAR *kShowRealFileIcons = TEXT("ShowRealFileIcons");\r
+static const TCHAR *kShowSystemMenu = TEXT("ShowSystemMenu");\r
+\r
+static const TCHAR *kFullRow = TEXT("FullRow");\r
+static const TCHAR *kShowGrid = TEXT("ShowGrid");\r
+static const TCHAR *kAlternativeSelection = TEXT("AlternativeSelection");\r
+// static const TCHAR *kLockMemoryAdd = TEXT("LockMemoryAdd");\r
+static const TCHAR *kLargePagesEnable = TEXT("LargePages");\r
+static const TCHAR *kSingleClick = TEXT("SingleClick");\r
+// static const TCHAR *kUnderline = TEXT("Underline");\r
+\r
+static const TCHAR *kFlatViewName = TEXT("FlatViewArc");\r
+\r
+static void SaveCuString(LPCTSTR keyPath, LPCWSTR valuePath, LPCWSTR value)\r
+{\r
+  CKey key;\r
+  key.Create(HKEY_CURRENT_USER, keyPath);\r
+  key.SetValue(valuePath, value);\r
+}\r
+\r
+static void ReadCuString(LPCTSTR keyPath, LPCWSTR valuePath, UString &res)\r
+{\r
+  res.Empty();\r
+  CKey key;\r
+  if (key.Open(HKEY_CURRENT_USER, keyPath, KEY_READ) == ERROR_SUCCESS)\r
+    key.QueryValue(valuePath, res);\r
+}\r
+\r
+void SaveRegLang(const UString &path) { SaveCuString(kCUBasePath, kLangValueName, path); }\r
+void ReadRegLang(UString &path) { ReadCuString(kCUBasePath, kLangValueName, path); }\r
+\r
+void SaveRegEditor(const UString &path) { SaveCuString(kCU_FMPath, kEditor, path); }\r
+void ReadRegEditor(UString &path) { ReadCuString(kCU_FMPath, kEditor, path); }\r
+\r
+void SaveRegDiff(const UString &path) { SaveCuString(kCU_FMPath, kDiff, path); }\r
+void ReadRegDiff(UString &path) { ReadCuString(kCU_FMPath, kDiff, path); }\r
+\r
+static void Save7ZipOption(const TCHAR *value, bool enabled)\r
+{\r
+  CKey key;\r
+  key.Create(HKEY_CURRENT_USER, kCUBasePath);\r
+  key.SetValue(value, enabled);\r
+}\r
+\r
+static void SaveOption(const TCHAR *value, bool enabled)\r
+{\r
+  CKey key;\r
+  key.Create(HKEY_CURRENT_USER, kCU_FMPath);\r
+  key.SetValue(value, enabled);\r
+}\r
+\r
+static bool Read7ZipOption(const TCHAR *value, bool defaultValue)\r
+{\r
+  CKey key;\r
+  if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) == ERROR_SUCCESS)\r
+  {\r
+    bool enabled;\r
+    if (key.QueryValue(value, enabled) == ERROR_SUCCESS)\r
+      return enabled;\r
+  }\r
+  return defaultValue;\r
+}\r
+\r
+static bool ReadOption(const TCHAR *value, bool defaultValue)\r
+{\r
+  CKey key;\r
+  if (key.Open(HKEY_CURRENT_USER, kCU_FMPath, KEY_READ) == ERROR_SUCCESS)\r
+  {\r
+    bool enabled;\r
+    if (key.QueryValue(value, enabled) == ERROR_SUCCESS)\r
+      return enabled;\r
+  }\r
+  return defaultValue;\r
+}\r
+\r
+/*\r
+static void SaveLmOption(const TCHAR *value, bool enabled)\r
+{\r
+  CKey key;\r
+  key.Create(HKEY_LOCAL_MACHINE, kLM_Path);\r
+  key.SetValue(value, enabled);\r
+}\r
+\r
+static bool ReadLmOption(const TCHAR *value, bool defaultValue)\r
+{\r
+  CKey key;\r
+  if (key.Open(HKEY_LOCAL_MACHINE, kLM_Path, KEY_READ) == ERROR_SUCCESS)\r
+  {\r
+    bool enabled;\r
+    if (key.QueryValue(value, enabled) == ERROR_SUCCESS)\r
+      return enabled;\r
+  }\r
+  return defaultValue;\r
+}\r
+*/\r
+\r
+void SaveShowDots(bool showDots) { SaveOption(kShowDots, showDots); }\r
+bool ReadShowDots() { return ReadOption(kShowDots, false); }\r
+\r
+void SaveShowRealFileIcons(bool show)  { SaveOption(kShowRealFileIcons, show); }\r
+bool ReadShowRealFileIcons() { return ReadOption(kShowRealFileIcons, false); }\r
+\r
+void SaveShowSystemMenu(bool show) { SaveOption(kShowSystemMenu, show); }\r
+bool ReadShowSystemMenu(){ return ReadOption(kShowSystemMenu, false); }\r
+\r
+void SaveFullRow(bool enable) { SaveOption(kFullRow, enable); }\r
+bool ReadFullRow() { return ReadOption(kFullRow, false); }\r
+\r
+void SaveShowGrid(bool enable) { SaveOption(kShowGrid, enable); }\r
+bool ReadShowGrid(){ return ReadOption(kShowGrid, false); }\r
+\r
+void SaveAlternativeSelection(bool enable) { SaveOption(kAlternativeSelection, enable); }\r
+bool ReadAlternativeSelection(){ return ReadOption(kAlternativeSelection, false); }\r
+\r
+void SaveSingleClick(bool enable) { SaveOption(kSingleClick, enable); }\r
+bool ReadSingleClick(){ return ReadOption(kSingleClick, false); }\r
+\r
+/*\r
+void SaveUnderline(bool enable) { SaveOption(kUnderline, enable); }\r
+bool ReadUnderline(){ return ReadOption(kUnderline, false); }\r
+*/\r
+\r
+// void SaveLockMemoryAdd(bool enable) { SaveLmOption(kLockMemoryAdd, enable); }\r
+// bool ReadLockMemoryAdd() { return ReadLmOption(kLockMemoryAdd, true); }\r
+\r
+void SaveLockMemoryEnable(bool enable) { Save7ZipOption(kLargePagesEnable, enable); }\r
+bool ReadLockMemoryEnable() { return Read7ZipOption(kLargePagesEnable, false); }\r
+\r
+static CSysString GetFlatViewName(UInt32 panelIndex)\r
+{\r
+  TCHAR panelString[16];\r
+  ConvertUInt32ToString(panelIndex, panelString);\r
+  return (CSysString)kFlatViewName + panelString;\r
+}\r
+\r
+void SaveFlatView(UInt32 panelIndex, bool enable) { SaveOption(GetFlatViewName(panelIndex), enable); }\r
+bool ReadFlatView(UInt32 panelIndex) { return ReadOption(GetFlatViewName(panelIndex), false); }\r
diff --git a/CPP/7zip/UI/FileManager/RegistryUtils.h b/CPP/7zip/UI/FileManager/RegistryUtils.h
new file mode 100755 (executable)
index 0000000..b636633
--- /dev/null
@@ -0,0 +1,53 @@
+// RegistryUtils.h\r
+\r
+#ifndef __REGISTRY_UTILS_H\r
+#define __REGISTRY_UTILS_H\r
+\r
+#include "Common/MyString.h"\r
+#include "Common/Types.h"\r
+\r
+void SaveRegLang(const UString &path);\r
+void ReadRegLang(UString &path);\r
+\r
+void SaveRegEditor(const UString &path);\r
+void ReadRegEditor(UString &path);\r
+\r
+void SaveRegDiff(const UString &path);\r
+void ReadRegDiff(UString &path);\r
+\r
+void SaveShowDots(bool showDots);\r
+bool ReadShowDots();\r
+\r
+void SaveShowRealFileIcons(bool show);\r
+bool ReadShowRealFileIcons();\r
+\r
+void SaveShowSystemMenu(bool showSystemMenu);\r
+bool ReadShowSystemMenu();\r
+\r
+void SaveFullRow(bool enable);\r
+bool ReadFullRow();\r
+\r
+void SaveShowGrid(bool enable);\r
+bool ReadShowGrid();\r
+\r
+void SaveAlternativeSelection(bool enable);\r
+bool ReadAlternativeSelection();\r
+\r
+// void SaveLockMemoryAdd(bool enable);\r
+// bool ReadLockMemoryAdd();\r
+\r
+bool ReadLockMemoryEnable();\r
+void SaveLockMemoryEnable(bool enable);\r
+\r
+void SaveSingleClick(bool enable);\r
+bool ReadSingleClick();\r
+\r
+/*\r
+void SaveUnderline(bool enable);\r
+bool ReadUnderline();\r
+*/\r
+\r
+void SaveFlatView(UInt32 panelIndex, bool enable);\r
+bool ReadFlatView(UInt32 panelIndex);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/RootFolder.cpp b/CPP/7zip/UI/FileManager/RootFolder.cpp
new file mode 100755 (executable)
index 0000000..2942214
--- /dev/null
@@ -0,0 +1,272 @@
+// RootFolder.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/DLL.h"\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../../PropID.h"\r
+\r
+#include "FSFolder.h"\r
+#include "LangUtils.h"\r
+#ifndef UNDER_CE\r
+#include "NetFolder.h"\r
+#include "FSDrives.h"\r
+#endif\r
+#include "RootFolder.h"\r
+#include "SysIconUtils.h"\r
+\r
+#include "resource.h"\r
+\r
+using namespace NWindows;\r
+\r
+static const STATPROPSTG kProps[] =\r
+{\r
+  { NULL, kpidName, VT_BSTR}\r
+};\r
+\r
+UString RootFolder_GetName_Computer(int &iconIndex)\r
+{\r
+  #ifdef UNDER_CE\r
+  GetRealIconIndex(L"\\", FILE_ATTRIBUTE_DIRECTORY, iconIndex);\r
+  #else\r
+  iconIndex = GetIconIndexForCSIDL(CSIDL_DRIVES);\r
+  #endif\r
+  return LangString(IDS_COMPUTER, 0x03020300);\r
+}\r
+\r
+UString RootFolder_GetName_Network(int &iconIndex)\r
+{\r
+  iconIndex = GetIconIndexForCSIDL(CSIDL_NETWORK);\r
+  return LangString(IDS_NETWORK, 0x03020301);\r
+}\r
+\r
+UString RootFolder_GetName_Documents(int &iconIndex)\r
+{\r
+  iconIndex = GetIconIndexForCSIDL(CSIDL_PERSONAL);\r
+  return LangString(IDS_DOCUMENTS, 0x03020302); ;\r
+}\r
+\r
+enum\r
+{\r
+  ROOT_INDEX_COMPUTER = 0\r
+  #ifndef UNDER_CE\r
+  , ROOT_INDEX_DOCUMENTS\r
+  , ROOT_INDEX_NETWORK\r
+  , ROOT_INDEX_VOLUMES\r
+  #endif\r
+};\r
+\r
+#ifndef UNDER_CE\r
+static const wchar_t *kVolPrefix = L"\\\\.";\r
+#endif\r
+\r
+void CRootFolder::Init()\r
+{\r
+  _names[ROOT_INDEX_COMPUTER] = RootFolder_GetName_Computer(_iconIndices[ROOT_INDEX_COMPUTER]);\r
+  #ifndef UNDER_CE\r
+  _names[ROOT_INDEX_DOCUMENTS] = RootFolder_GetName_Documents(_iconIndices[ROOT_INDEX_DOCUMENTS]);\r
+  _names[ROOT_INDEX_NETWORK] = RootFolder_GetName_Network(_iconIndices[ROOT_INDEX_NETWORK]);\r
+  _names[ROOT_INDEX_VOLUMES] = kVolPrefix;\r
+  _iconIndices[ROOT_INDEX_VOLUMES] = GetIconIndexForCSIDL(CSIDL_DRIVES);\r
+  #endif\r
+}\r
+\r
+STDMETHODIMP CRootFolder::LoadItems()\r
+{\r
+  Init();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CRootFolder::GetNumberOfItems(UInt32 *numItems)\r
+{\r
+  *numItems = kNumRootFolderItems;\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CRootFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value)\r
+{\r
+  NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidIsDir:  prop = true; break;\r
+    case kpidName:  prop = _names[itemIndex]; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+typedef BOOL (WINAPI *SHGetSpecialFolderPathWp)(HWND hwnd, LPWSTR pszPath, int csidl, BOOL fCreate);\r
+typedef BOOL (WINAPI *SHGetSpecialFolderPathAp)(HWND hwnd, LPSTR pszPath, int csidl, BOOL fCreate);\r
+\r
+UString GetMyDocsPath()\r
+{\r
+  UString us;\r
+  WCHAR s[MAX_PATH + 1];\r
+  SHGetSpecialFolderPathWp getW = (SHGetSpecialFolderPathWp)\r
+      #ifdef UNDER_CE\r
+      My_GetProcAddress(GetModuleHandle(TEXT("coredll.dll")), "SHGetSpecialFolderPath");\r
+      #else\r
+      My_GetProcAddress(GetModuleHandle(TEXT("shell32.dll")), "SHGetSpecialFolderPathW");\r
+      #endif\r
+  if (getW && getW(0, s, CSIDL_PERSONAL, FALSE))\r
+    us = s;\r
+  #ifndef _UNICODE\r
+  else\r
+  {\r
+    SHGetSpecialFolderPathAp getA = (SHGetSpecialFolderPathAp)\r
+        ::GetProcAddress(::GetModuleHandleA("shell32.dll"), "SHGetSpecialFolderPathA");\r
+    CHAR s2[MAX_PATH + 1];\r
+    if (getA && getA(0, s2, CSIDL_PERSONAL, FALSE))\r
+      us = GetUnicodeString(s2);\r
+  }\r
+  #endif\r
+  if (us.Length() > 0 && us[us.Length() - 1] != WCHAR_PATH_SEPARATOR)\r
+    us += WCHAR_PATH_SEPARATOR;\r
+  return us;\r
+}\r
+\r
+STDMETHODIMP CRootFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder)\r
+{\r
+  *resultFolder = NULL;\r
+  CMyComPtr<IFolderFolder> subFolder;\r
+  #ifdef UNDER_CE\r
+  if (index == ROOT_INDEX_COMPUTER)\r
+  {\r
+    NFsFolder::CFSFolder *fsFolder = new NFsFolder::CFSFolder;\r
+    subFolder = fsFolder;\r
+    fsFolder->InitToRoot();\r
+  }\r
+  #else\r
+  if (index == ROOT_INDEX_COMPUTER || index == ROOT_INDEX_VOLUMES)\r
+  {\r
+    CFSDrives *fsDrivesSpec = new CFSDrives;\r
+    subFolder = fsDrivesSpec;\r
+    fsDrivesSpec->Init(index == ROOT_INDEX_VOLUMES);\r
+  }\r
+  else if (index == ROOT_INDEX_NETWORK)\r
+  {\r
+    CNetFolder *netFolderSpec = new CNetFolder;\r
+    subFolder = netFolderSpec;\r
+    netFolderSpec->Init(0, 0, _names[ROOT_INDEX_NETWORK] + WCHAR_PATH_SEPARATOR);\r
+  }\r
+  else if (index == ROOT_INDEX_DOCUMENTS)\r
+  {\r
+    UString s = GetMyDocsPath();\r
+    if (!s.IsEmpty())\r
+    {\r
+      NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;\r
+      subFolder = fsFolderSpec;\r
+      RINOK(fsFolderSpec->Init(s, NULL));\r
+    }\r
+  }\r
+  #endif\r
+  else\r
+    return E_INVALIDARG;\r
+  *resultFolder = subFolder.Detach();\r
+  return S_OK;\r
+}\r
+\r
+static bool AreEqualNames(const UString &name1, const UString &name2)\r
+{\r
+  return (name1 == name2 || name1 == (name2 + UString(WCHAR_PATH_SEPARATOR)));\r
+}\r
+\r
+STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder)\r
+{\r
+  *resultFolder = 0;\r
+  UString name2 = name;\r
+  name2.Trim();\r
+  if (name2.IsEmpty())\r
+  {\r
+    CRootFolder *rootFolderSpec = new CRootFolder;\r
+    CMyComPtr<IFolderFolder> rootFolder = rootFolderSpec;\r
+    rootFolderSpec->Init();\r
+    *resultFolder = rootFolder.Detach();\r
+    return S_OK;\r
+  }\r
+  for (int i = 0; i < kNumRootFolderItems; i++)\r
+    if (AreEqualNames(name2, _names[i]))\r
+      return BindToFolder((UInt32)i, resultFolder);\r
+  #ifdef UNDER_CE\r
+  if (name2 == L"\\")\r
+    return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder);\r
+  #else\r
+  if (AreEqualNames(name2, L"My Documents") ||\r
+      AreEqualNames(name2, L"Documents"))\r
+    return BindToFolder((UInt32)ROOT_INDEX_DOCUMENTS, resultFolder);\r
+  #endif\r
+  if (AreEqualNames(name2, L"My Computer") ||\r
+      AreEqualNames(name2, L"Computer"))\r
+    return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder);\r
+  if (name2 == UString(WCHAR_PATH_SEPARATOR))\r
+  {\r
+    CMyComPtr<IFolderFolder> subFolder = this;\r
+    *resultFolder = subFolder.Detach();\r
+    return S_OK;\r
+  }\r
+\r
+  if (name2.Length () < 2)\r
+    return E_INVALIDARG;\r
+\r
+  CMyComPtr<IFolderFolder> subFolder;\r
+  \r
+  #ifndef UNDER_CE\r
+  if (name2.Left(4) == kVolPrefix)\r
+  {\r
+    CFSDrives *folderSpec = new CFSDrives;\r
+    subFolder = folderSpec;\r
+    folderSpec->Init(true);\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    if (name2[name2.Length () - 1] != WCHAR_PATH_SEPARATOR)\r
+      name2 += WCHAR_PATH_SEPARATOR;\r
+    NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;\r
+    subFolder = fsFolderSpec;\r
+    if (fsFolderSpec->Init(name2, 0) != S_OK)\r
+    {\r
+      #ifndef UNDER_CE\r
+      if (name2[0] == WCHAR_PATH_SEPARATOR)\r
+      {\r
+        CNetFolder *netFolderSpec = new CNetFolder;\r
+        subFolder = netFolderSpec;\r
+        netFolderSpec->Init(name2);\r
+      }\r
+      else\r
+      #endif\r
+        return E_INVALIDARG;\r
+    }\r
+  }\r
+  *resultFolder = subFolder.Detach();\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CRootFolder::BindToParentFolder(IFolderFolder **resultFolder)\r
+{\r
+  *resultFolder = 0;\r
+  return S_OK;\r
+}\r
+\r
+IMP_IFolderFolder_Props(CRootFolder)\r
+\r
+STDMETHODIMP CRootFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)\r
+{\r
+  NWindows::NCOM::CPropVariant prop;\r
+  switch(propID)\r
+  {\r
+    case kpidType: prop = L"RootFolder"; break;\r
+    case kpidPath: prop = L""; break;\r
+  }\r
+  prop.Detach(value);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CRootFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)\r
+{\r
+  *iconIndex = _iconIndices[index];\r
+  return S_OK;\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/RootFolder.h b/CPP/7zip/UI/FileManager/RootFolder.h
new file mode 100755 (executable)
index 0000000..9f75ac6
--- /dev/null
@@ -0,0 +1,33 @@
+// RootFolder.h\r
+\r
+#ifndef __ROOT_FOLDER_H\r
+#define __ROOT_FOLDER_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+#include "IFolder.h"\r
+\r
+const int kNumRootFolderItems =\r
+  #ifdef UNDER_CE\r
+  1\r
+  #else\r
+  4\r
+  #endif\r
+  ;\r
+\r
+class CRootFolder:\r
+  public IFolderFolder,\r
+  public IFolderGetSystemIconIndex,\r
+  public CMyUnknownImp\r
+{\r
+  UString _names[kNumRootFolderItems];\r
+  int _iconIndices[kNumRootFolderItems];\r
+\r
+public:\r
+  MY_UNKNOWN_IMP1(IFolderGetSystemIconIndex)\r
+  INTERFACE_FolderFolder(;)\r
+  STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex);\r
+  void Init();\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/SettingsPage.cpp b/CPP/7zip/UI/FileManager/SettingsPage.cpp
new file mode 100755 (executable)
index 0000000..29d7429
--- /dev/null
@@ -0,0 +1,117 @@
+// SettingsPage.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/StringConvert.h"\r
+\r
+#ifndef UNDER_CE\r
+#include "Windows/MemoryLock.h"\r
+#endif\r
+\r
+#include "HelpUtils.h"\r
+#include "LangUtils.h"\r
+#include "ProgramLocation.h"\r
+#include "RegistryUtils.h"\r
+#include "SettingsPage.h"\r
+\r
+#include "SettingsPageRes.h"\r
+\r
+using namespace NWindows;\r
+\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDC_SETTINGS_SHOW_DOTS, 0x03010401},\r
+  { IDC_SETTINGS_SHOW_REAL_FILE_ICONS, 0x03010402},\r
+  { IDC_SETTINGS_SHOW_SYSTEM_MENU, 0x03010410},\r
+  { IDC_SETTINGS_FULL_ROW, 0x03010420},\r
+  { IDC_SETTINGS_SHOW_GRID, 0x03010421},\r
+  { IDC_SETTINGS_SINGLE_CLICK, 0x03010422},\r
+  // { IDC_SETTINGS_UNDERLINE, 0x03010423}\r
+  { IDC_SETTINGS_ALTERNATIVE_SELECTION, 0x03010430},\r
+  { IDC_SETTINGS_LARGE_PAGES, 0x03010440}\r
+};\r
+\r
+static LPCWSTR kEditTopic = L"FM/options.htm#settings";\r
+\r
+extern bool IsLargePageSupported();\r
+\r
+bool CSettingsPage::OnInit()\r
+{\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+\r
+  CheckButton(IDC_SETTINGS_SHOW_DOTS, ReadShowDots());\r
+  CheckButton(IDC_SETTINGS_SHOW_SYSTEM_MENU, ReadShowSystemMenu());\r
+  CheckButton(IDC_SETTINGS_SHOW_REAL_FILE_ICONS, ReadShowRealFileIcons());\r
+\r
+  CheckButton(IDC_SETTINGS_FULL_ROW, ReadFullRow());\r
+  CheckButton(IDC_SETTINGS_SHOW_GRID, ReadShowGrid());\r
+  CheckButton(IDC_SETTINGS_ALTERNATIVE_SELECTION, ReadAlternativeSelection());\r
+  if (IsLargePageSupported())\r
+    CheckButton(IDC_SETTINGS_LARGE_PAGES, ReadLockMemoryEnable());\r
+  else\r
+    EnableItem(IDC_SETTINGS_LARGE_PAGES, false);\r
+  CheckButton(IDC_SETTINGS_SINGLE_CLICK, ReadSingleClick());\r
+  // CheckButton(IDC_SETTINGS_UNDERLINE, ReadUnderline());\r
+\r
+  // EnableSubItems();\r
+\r
+  return CPropertyPage::OnInit();\r
+}\r
+\r
+/*\r
+void CSettingsPage::EnableSubItems()\r
+{\r
+  EnableItem(IDC_SETTINGS_UNDERLINE, IsButtonCheckedBool(IDC_SETTINGS_SINGLE_CLICK));\r
+}\r
+*/\r
+\r
+LONG CSettingsPage::OnApply()\r
+{\r
+  SaveShowDots(IsButtonCheckedBool(IDC_SETTINGS_SHOW_DOTS));\r
+  SaveShowSystemMenu(IsButtonCheckedBool(IDC_SETTINGS_SHOW_SYSTEM_MENU));\r
+  SaveShowRealFileIcons(IsButtonCheckedBool(IDC_SETTINGS_SHOW_REAL_FILE_ICONS));\r
+\r
+  SaveFullRow(IsButtonCheckedBool(IDC_SETTINGS_FULL_ROW));\r
+  SaveShowGrid(IsButtonCheckedBool(IDC_SETTINGS_SHOW_GRID));\r
+  SaveAlternativeSelection(IsButtonCheckedBool(IDC_SETTINGS_ALTERNATIVE_SELECTION));\r
+  #ifndef UNDER_CE\r
+  if (IsLargePageSupported())\r
+  {\r
+    bool enable = IsButtonCheckedBool(IDC_SETTINGS_LARGE_PAGES);\r
+    NSecurity::EnableLockMemoryPrivilege(enable);\r
+    SaveLockMemoryEnable(enable);\r
+  }\r
+  #endif\r
+  \r
+  SaveSingleClick(IsButtonCheckedBool(IDC_SETTINGS_SINGLE_CLICK));\r
+  // SaveUnderline(IsButtonCheckedBool(IDC_SETTINGS_UNDERLINE));\r
+\r
+  return PSNRET_NOERROR;\r
+}\r
+\r
+void CSettingsPage::OnNotifyHelp()\r
+{\r
+  ShowHelpWindow(NULL, kEditTopic); // change it\r
+}\r
+\r
+bool CSettingsPage::OnButtonClicked(int buttonID, HWND buttonHWND)\r
+{\r
+  switch(buttonID)\r
+  {\r
+    case IDC_SETTINGS_SINGLE_CLICK:\r
+    /*\r
+      EnableSubItems();\r
+      break;\r
+    */\r
+    case IDC_SETTINGS_SHOW_DOTS:\r
+    case IDC_SETTINGS_SHOW_SYSTEM_MENU:\r
+    case IDC_SETTINGS_SHOW_REAL_FILE_ICONS:\r
+    case IDC_SETTINGS_FULL_ROW:\r
+    case IDC_SETTINGS_SHOW_GRID:\r
+    case IDC_SETTINGS_ALTERNATIVE_SELECTION:\r
+    case IDC_SETTINGS_LARGE_PAGES:\r
+      Changed();\r
+      return true;\r
+  }\r
+  return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/SettingsPage.h b/CPP/7zip/UI/FileManager/SettingsPage.h
new file mode 100755 (executable)
index 0000000..4d9d2fd
--- /dev/null
@@ -0,0 +1,19 @@
+// SettingsPage.h\r
\r
+#ifndef __SETTINGSPAGE_H\r
+#define __SETTINGSPAGE_H\r
+\r
+#include "Windows/Control/PropertyPage.h"\r
+#include "Windows/Control/Edit.h"\r
+\r
+class CSettingsPage: public NWindows::NControl::CPropertyPage\r
+{\r
+  // void EnableSubItems();\r
+  bool OnButtonClicked(int buttonID, HWND buttonHWND);\r
+public:\r
+  virtual bool OnInit();\r
+  virtual void OnNotifyHelp();\r
+  virtual LONG OnApply();\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/SettingsPage.rc b/CPP/7zip/UI/FileManager/SettingsPage.rc
new file mode 100755 (executable)
index 0000000..7516318
--- /dev/null
@@ -0,0 +1,22 @@
+#include "SettingsPageRes.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#define xc 200\r
+#define yc 120\r
+\r
+IDD_SETTINGS  MY_PAGE\r
+#include "SettingsPage2.rc"\r
+\r
+\r
+#ifdef UNDER_CE\r
+\r
+#undef m\r
+#undef xc\r
+\r
+#define m 4\r
+#define xc (SMALL_PAGE_SIZE_X + 8)\r
+\r
+IDD_SETTINGS_2  MY_PAGE\r
+#include "SettingsPage2.rc"\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/SettingsPage2.rc b/CPP/7zip/UI/FileManager/SettingsPage2.rc
new file mode 100755 (executable)
index 0000000..f7c0549
--- /dev/null
@@ -0,0 +1,24 @@
+CAPTION "Settings"\r
+BEGIN\r
+  CONTROL  "Show "".."" item", IDC_SETTINGS_SHOW_DOTS, MY_CHECKBOX,\r
+           m,  8, xc, 10\r
+  CONTROL  "Show real file &icons", IDC_SETTINGS_SHOW_REAL_FILE_ICONS, MY_CHECKBOX,\r
+           m, 22, xc, 10\r
+  CONTROL  "Show system &menu", IDC_SETTINGS_SHOW_SYSTEM_MENU, MY_CHECKBOX,\r
+           m, 36, xc, 10\r
+  CONTROL  "&Full row select", IDC_SETTINGS_FULL_ROW, MY_CHECKBOX,\r
+           m, 50, xc, 10\r
+  CONTROL  "Show &grid lines", IDC_SETTINGS_SHOW_GRID, MY_CHECKBOX,\r
+           m, 64, xc, 10\r
+  CONTROL  "&Single-click to open an item", IDC_SETTINGS_SINGLE_CLICK, MY_CHECKBOX,\r
+           m, 78, xc, 10\r
+  /*\r
+  CONTROL  "&Underline current name", IDC_SETTINGS_UNDERLINE, "Button", BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,\r
+           m + 12, 92, xc - 12, 10\r
+  */\r
+\r
+  CONTROL  "&Alternative selection mode", IDC_SETTINGS_ALTERNATIVE_SELECTION, MY_CHECKBOX,\r
+           m, 92, xc, 10\r
+  CONTROL  "Use &large memory pages", IDC_SETTINGS_LARGE_PAGES, MY_CHECKBOX,\r
+           m, 106, xc, 10\r
+END\r
diff --git a/CPP/7zip/UI/FileManager/SettingsPageRes.h b/CPP/7zip/UI/FileManager/SettingsPageRes.h
new file mode 100755 (executable)
index 0000000..4517165
--- /dev/null
@@ -0,0 +1,13 @@
+#define IDD_SETTINGS                    543\r
+#define IDD_SETTINGS_2                  643\r
+\r
+#define IDC_SETTINGS_SHOW_DOTS          1000\r
+#define IDC_SETTINGS_SHOW_REAL_FILE_ICONS 1001\r
+\r
+#define IDC_SETTINGS_SHOW_SYSTEM_MENU   1010\r
+#define IDC_SETTINGS_FULL_ROW           1011\r
+#define IDC_SETTINGS_SHOW_GRID          1013\r
+#define IDC_SETTINGS_SINGLE_CLICK       1014\r
+#define IDC_SETTINGS_UNDERLINE          1015\r
+#define IDC_SETTINGS_ALTERNATIVE_SELECTION 1016\r
+#define IDC_SETTINGS_LARGE_PAGES 1017\r
diff --git a/CPP/7zip/UI/FileManager/SplitDialog.cpp b/CPP/7zip/UI/FileManager/SplitDialog.cpp
new file mode 100755 (executable)
index 0000000..fd7f796
--- /dev/null
@@ -0,0 +1,116 @@
+// SplitDialog.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/FileName.h"\r
+\r
+#ifdef LANG\r
+#include "LangUtils.h"\r
+#endif\r
+\r
+#include "BrowseDialog.h"\r
+#include "CopyDialogRes.h"\r
+#include "SplitDialog.h"\r
+#include "SplitUtils.h"\r
+#include "resourceGui.h"\r
+\r
+using namespace NWindows;\r
+\r
+#ifdef LANG\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDC_STATIC_SPLIT_PATH, 0x03020501 },\r
+  { IDC_STATIC_SPLIT_VOLUME, 0x02000D40 },\r
+};\r
+#endif\r
+\r
+\r
+bool CSplitDialog::OnInit()\r
+{\r
+  #ifdef LANG\r
+  LangSetWindowText(HWND(*this), 0x03020500);\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+  #endif\r
+  _pathCombo.Attach(GetItem(IDC_COMBO_SPLIT_PATH));\r
+  _volumeCombo.Attach(GetItem(IDC_COMBO_SPLIT_VOLUME));\r
+  \r
+  if (!FilePath.IsEmpty())\r
+  {\r
+    UString title;\r
+    GetText(title);\r
+    title += L' ';\r
+    title += FilePath;\r
+    SetText(title);\r
+  }\r
+  _pathCombo.SetText(Path);\r
+  AddVolumeItems(_volumeCombo);\r
+  _volumeCombo.SetCurSel(0);\r
+  NormalizeSize();\r
+  return CModalDialog::OnInit();\r
+}\r
+\r
+bool CSplitDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)\r
+{\r
+  int mx, my;\r
+  GetMargins(8, mx, my);\r
+  int bx1, bx2, by;\r
+  GetItemSizes(IDCANCEL, bx1, by);\r
+  GetItemSizes(IDOK, bx2, by);\r
+  int yPos = ySize - my - by;\r
+  int xPos = xSize - mx - bx1;\r
+\r
+  InvalidateRect(NULL);\r
+\r
+  {\r
+    RECT rect;\r
+    GetClientRectOfItem(IDC_BUTTON_SPLIT_PATH, rect);\r
+    int bx = rect.right - rect.left;\r
+    MoveItem(IDC_BUTTON_SPLIT_PATH, xSize - mx - bx, rect.top, bx, rect.bottom - rect.top);\r
+    ChangeSubWindowSizeX(_pathCombo, xSize - mx - mx - bx - mx);\r
+  }\r
+\r
+  MoveItem(IDCANCEL, xPos, yPos, bx1, by);\r
+  MoveItem(IDOK, xPos - mx - bx2, yPos, bx2, by);\r
+\r
+  return false;\r
+}\r
+\r
+bool CSplitDialog::OnButtonClicked(int buttonID, HWND buttonHWND)\r
+{\r
+  switch(buttonID)\r
+  {\r
+    case IDC_BUTTON_SPLIT_PATH:\r
+      OnButtonSetPath();\r
+      return true;\r
+  }\r
+  return CModalDialog::OnButtonClicked(buttonID, buttonHWND);\r
+}\r
+\r
+void CSplitDialog::OnButtonSetPath()\r
+{\r
+  UString currentPath;\r
+  _pathCombo.GetText(currentPath);\r
+  // UString title = L"Specify a location for output folder";\r
+  UString title = LangStringSpec(IDS_SET_FOLDER, 0x03020209);\r
+\r
+  UString resultPath;\r
+  if (!MyBrowseForFolder(HWND(*this), title, currentPath, resultPath))\r
+    return;\r
+  NFile::NName::NormalizeDirPathPrefix(resultPath);\r
+  _pathCombo.SetCurSel(-1);\r
+  _pathCombo.SetText(resultPath);\r
+}\r
+\r
+void CSplitDialog::OnOK()\r
+{\r
+  _pathCombo.GetText(Path);\r
+  UString volumeString;\r
+  _volumeCombo.GetText(volumeString);\r
+  volumeString.Trim();\r
+  if (!ParseVolumeSizes(volumeString, VolumeSizes) || VolumeSizes.Size() == 0)\r
+  {\r
+    ::MessageBoxW(*this, LangString(IDS_INCORRECT_VOLUME_SIZE, 0x02000D41), L"7-Zip", 0);\r
+    return;\r
+  }\r
+  CModalDialog::OnOK();\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/SplitDialog.h b/CPP/7zip/UI/FileManager/SplitDialog.h
new file mode 100755 (executable)
index 0000000..6d4f820
--- /dev/null
@@ -0,0 +1,28 @@
+// SplitDialog.h\r
+\r
+#ifndef __SPLIT_DIALOG_H\r
+#define __SPLIT_DIALOG_H\r
+\r
+#include "Windows/Control/Dialog.h"\r
+#include "Windows/Control/ComboBox.h"\r
+\r
+#include "SplitDialogRes.h"\r
+\r
+class CSplitDialog: public NWindows::NControl::CModalDialog\r
+{\r
+  NWindows::NControl::CComboBox _pathCombo;\r
+  NWindows::NControl::CComboBox _volumeCombo;\r
+  virtual void OnOK();\r
+  virtual bool OnInit();\r
+  virtual bool OnSize(WPARAM wParam, int xSize, int ySize);\r
+  virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);\r
+  void OnButtonSetPath();\r
+public:\r
+  UString FilePath;\r
+  UString Path;\r
+  CRecordVector<UInt64> VolumeSizes;\r
+  INT_PTR Create(HWND parentWindow = 0)\r
+    { return CModalDialog::Create(IDD_DIALOG_SPLIT, parentWindow); }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/SplitDialog.rc b/CPP/7zip/UI/FileManager/SplitDialog.rc
new file mode 100755 (executable)
index 0000000..31dad22
--- /dev/null
@@ -0,0 +1,16 @@
+#include "SplitDialogRes.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#define xc 288\r
+#define yc 96\r
+\r
+IDD_DIALOG_SPLIT MY_RESIZE_DIALOG\r
+CAPTION "Split File"\r
+BEGIN\r
+  LTEXT       "&Split to:", IDC_STATIC_SPLIT_PATH, m, m, xc, 8\r
+  COMBOBOX    IDC_COMBO_SPLIT_PATH, m, 20, xc - bxsDots - m, 64, MY_COMBO_WITH_EDIT\r
+  PUSHBUTTON  "...", IDC_BUTTON_SPLIT_PATH, xs - m - bxsDots, 18, bxsDots, bys, WS_GROUP\r
+  LTEXT       "Split to &volumes,  bytes:", IDC_STATIC_SPLIT_VOLUME, m, 44, xc, 8\r
+  COMBOBOX    IDC_COMBO_SPLIT_VOLUME, m, 56, 96, 52, MY_COMBO_WITH_EDIT\r
+  OK_CANCEL\r
+END\r
diff --git a/CPP/7zip/UI/FileManager/SplitDialogRes.h b/CPP/7zip/UI/FileManager/SplitDialogRes.h
new file mode 100755 (executable)
index 0000000..a3e874d
--- /dev/null
@@ -0,0 +1,7 @@
+#define IDD_DIALOG_SPLIT                504\r
+#define IDC_STATIC_SPLIT_PATH           1000\r
+#define IDC_COMBO_SPLIT_PATH            1001\r
+#define IDC_BUTTON_SPLIT_PATH           1002\r
+#define IDC_STATIC_SPLIT_VOLUME         1010\r
+#define IDC_COMBO_SPLIT_VOLUME          1011\r
+\r
diff --git a/CPP/7zip/UI/FileManager/SplitUtils.cpp b/CPP/7zip/UI/FileManager/SplitUtils.cpp
new file mode 100755 (executable)
index 0000000..a51ff59
--- /dev/null
@@ -0,0 +1,86 @@
+// SplitUtils.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/StringToInt.h"\r
+\r
+#include "SplitUtils.h"\r
+#include "StringUtils.h"\r
+\r
+bool ParseVolumeSizes(const UString &s, CRecordVector<UInt64> &values)\r
+{\r
+  values.Clear();\r
+  UStringVector destStrings;\r
+  SplitString(s, destStrings);\r
+  bool prevIsNumber = false;\r
+  for (int i = 0; i < destStrings.Size(); i++)\r
+  {\r
+    UString subString = destStrings[i];\r
+    subString.MakeUpper();\r
+    if (subString.IsEmpty())\r
+      return false;\r
+    if (subString == L"-")\r
+      return true;\r
+    if (prevIsNumber)\r
+    {\r
+      wchar_t c = subString[0];\r
+      UInt64 &value = values.Back();\r
+      prevIsNumber = false;\r
+      switch(c)\r
+      {\r
+        case L'B':\r
+          continue;\r
+        case L'K':\r
+          value <<= 10;\r
+          continue;\r
+        case L'M':\r
+          value <<= 20;\r
+          continue;\r
+        case L'G':\r
+          value <<= 30;\r
+          continue;\r
+      }\r
+    }\r
+    const wchar_t *start = subString;\r
+    const wchar_t *end;\r
+    UInt64 value = ConvertStringToUInt64(start, &end);\r
+    if (start == end)\r
+      return false;\r
+    if (value == 0)\r
+      return false;\r
+    values.Add(value);\r
+    prevIsNumber = true;\r
+    UString rem = subString.Mid((int)(end - start));\r
+    if (!rem.IsEmpty())\r
+      destStrings.Insert(i + 1, rem);\r
+  }\r
+  return true;\r
+}\r
+\r
+void AddVolumeItems(NWindows::NControl::CComboBox &volumeCombo)\r
+{\r
+  volumeCombo.AddString(TEXT("10M"));\r
+  volumeCombo.AddString(TEXT("650M - CD"));\r
+  volumeCombo.AddString(TEXT("700M - CD"));\r
+  volumeCombo.AddString(TEXT("4480M - DVD"));\r
+  volumeCombo.AddString(TEXT("1457664 - 3.5\" floppy"));\r
+}\r
+\r
+UInt64 GetNumberOfVolumes(UInt64 size, CRecordVector<UInt64> &volSizes)\r
+{\r
+  if (size == 0 || volSizes.Size() == 0)\r
+    return 1;\r
+  UInt64 numVolumes = 0;\r
+  for (int i = 0; i < volSizes.Size(); i++)\r
+  {\r
+    UInt64 volSize = volSizes[i];\r
+    numVolumes++;\r
+    if (volSize >= size)\r
+      return numVolumes;\r
+    size -= volSize;\r
+  }\r
+  UInt64 volSize = volSizes.Back();\r
+  if (volSize == 0)\r
+    return (UInt64)(Int64)-1;\r
+  return numVolumes + (size - 1) / volSize + 1;\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/SplitUtils.h b/CPP/7zip/UI/FileManager/SplitUtils.h
new file mode 100755 (executable)
index 0000000..9fda0fd
--- /dev/null
@@ -0,0 +1,15 @@
+// SplitUtils.h\r
+\r
+#ifndef __SPLITUTILS_H\r
+#define __SPLITUTILS_H\r
+\r
+#include "Common/MyString.h"\r
+#include "Common/Types.h"\r
+#include "Windows/Control/ComboBox.h"\r
+\r
+bool ParseVolumeSizes(const UString &s, CRecordVector<UInt64> &values);\r
+void AddVolumeItems(NWindows::NControl::CComboBox &volumeCombo);\r
+\r
+UInt64 GetNumberOfVolumes(UInt64 size, CRecordVector<UInt64> &volSizes);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/StdAfx.cpp b/CPP/7zip/UI/FileManager/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..c6d3b1f
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/UI/FileManager/StdAfx.h b/CPP/7zip/UI/FileManager/StdAfx.h
new file mode 100755 (executable)
index 0000000..a9ae92e
--- /dev/null
@@ -0,0 +1,23 @@
+// stdafx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#define _WIN32_WINNT 0x0400\r
+\r
+// it's for Windows NT supporting (MENUITEMINFOW)\r
+#define WINVER 0x0400\r
+\r
+#include <windows.h>\r
+#include <stdio.h>\r
+#include <commctrl.h>\r
+#include <ShlObj.h>\r
+#include <limits.h>\r
+#include <tchar.h>\r
+#include <shlwapi.h>\r
+\r
+// #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers\r
+\r
+#include "Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/StringUtils.cpp b/CPP/7zip/UI/FileManager/StringUtils.cpp
new file mode 100755 (executable)
index 0000000..7c7de13
--- /dev/null
@@ -0,0 +1,68 @@
+// StringUtils.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "StringUtils.h"\r
+\r
+void SplitStringToTwoStrings(const UString &src, UString &dest1, UString &dest2)\r
+{\r
+  dest1.Empty();\r
+  dest2.Empty();\r
+  bool quoteMode = false;\r
+  int i;\r
+  for (i = 0; i < src.Length(); i++)\r
+  {\r
+    wchar_t c = src[i];\r
+    if (c == L'\"')\r
+      quoteMode = !quoteMode;\r
+    else if (c == L' ' && !quoteMode)\r
+    {\r
+      if (!quoteMode)\r
+      {\r
+        i++;\r
+        break;\r
+      }\r
+    }\r
+    else\r
+      dest1 += c;\r
+  }\r
+  dest2 = src.Mid(i);\r
+}\r
+\r
+void SplitString(const UString &srcString, UStringVector &destStrings)\r
+{\r
+  destStrings.Clear();\r
+  UString string;\r
+  int len = srcString.Length();\r
+  if (len == 0)\r
+    return;\r
+  for (int i = 0; i < len; i++)\r
+  {\r
+    wchar_t c = srcString[i];\r
+    if (c == L' ')\r
+    {\r
+      if (!string.IsEmpty())\r
+      {\r
+        destStrings.Add(string);\r
+        string.Empty();\r
+      }\r
+    }\r
+    else\r
+      string += c;\r
+  }\r
+  if (!string.IsEmpty())\r
+    destStrings.Add(string);\r
+}\r
+\r
+UString JoinStrings(const UStringVector &srcStrings)\r
+{\r
+  UString destString;\r
+  for (int i = 0; i < srcStrings.Size(); i++)\r
+  {\r
+    if (i != 0)\r
+      destString += L' ';\r
+    destString += srcStrings[i];\r
+  }\r
+  return destString;\r
+}\r
+\r
diff --git a/CPP/7zip/UI/FileManager/StringUtils.h b/CPP/7zip/UI/FileManager/StringUtils.h
new file mode 100755 (executable)
index 0000000..8857bff
--- /dev/null
@@ -0,0 +1,13 @@
+// StringUtils.h\r
+\r
+#ifndef __STRINGUTILS_H\r
+#define __STRINGUTILS_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+void SplitStringToTwoStrings(const UString &src, UString &dest1, UString &dest2);\r
+\r
+void SplitString(const UString &srcString, UStringVector &destStrings);\r
+UString JoinStrings(const UStringVector &srcStrings);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.cpp b/CPP/7zip/UI/FileManager/SysIconUtils.cpp
new file mode 100755 (executable)
index 0000000..35fe0de
--- /dev/null
@@ -0,0 +1,159 @@
+// SysIconUtils.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#ifndef _UNICODE\r
+#include "Common/StringConvert.h"\r
+#endif\r
+\r
+#include "SysIconUtils.h"\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+int GetIconIndexForCSIDL(int csidl)\r
+{\r
+  LPITEMIDLIST pidl = 0;\r
+  SHGetSpecialFolderLocation(NULL, csidl, &pidl);\r
+  if (pidl)\r
+  {\r
+    SHFILEINFO shellInfo;\r
+    SHGetFileInfo(LPCTSTR(pidl), FILE_ATTRIBUTE_NORMAL,\r
+      &shellInfo, sizeof(shellInfo),\r
+      SHGFI_PIDL | SHGFI_SYSICONINDEX);\r
+    IMalloc  *pMalloc;\r
+    SHGetMalloc(&pMalloc);\r
+    if(pMalloc)\r
+    {\r
+      pMalloc->Free(pidl);\r
+      pMalloc->Release();\r
+    }\r
+    return shellInfo.iIcon;\r
+  }\r
+  return 0;\r
+}\r
+\r
+DWORD_PTR GetRealIconIndex(LPCTSTR path, DWORD attrib, int &iconIndex)\r
+{\r
+  SHFILEINFO shellInfo;\r
+  DWORD_PTR res = ::SHGetFileInfo(path, FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,\r
+      sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);\r
+  iconIndex = shellInfo.iIcon;\r
+  return res;\r
+}\r
+\r
+\r
+#ifndef _UNICODE\r
+typedef int (WINAPI * SHGetFileInfoWP)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags);\r
+\r
+struct CSHGetFileInfoInit\r
+{\r
+  SHGetFileInfoWP shGetFileInfoW;\r
+  CSHGetFileInfoInit()\r
+  {\r
+    shGetFileInfoW = (SHGetFileInfoWP)\r
+    ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetFileInfoW");\r
+  }\r
+} g_SHGetFileInfoInit;\r
+#endif\r
+\r
+static DWORD_PTR MySHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags)\r
+{\r
+  #ifdef _UNICODE\r
+  return SHGetFileInfo(\r
+  #else\r
+  if (g_SHGetFileInfoInit.shGetFileInfoW == 0)\r
+    return 0;\r
+  return g_SHGetFileInfoInit.shGetFileInfoW(\r
+  #endif\r
+  pszPath, attrib, psfi, cbFileInfo, uFlags);\r
+}\r
+\r
+#ifndef _UNICODE\r
+// static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }\r
+DWORD_PTR GetRealIconIndex(LPCWSTR path, DWORD attrib, int &iconIndex)\r
+{\r
+  if(g_IsNT)\r
+  {\r
+    SHFILEINFOW shellInfo;\r
+    DWORD_PTR res = ::MySHGetFileInfoW(path, FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,\r
+      sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);\r
+    iconIndex = shellInfo.iIcon;\r
+    return res;\r
+  }\r
+  else\r
+    return GetRealIconIndex(UnicodeStringToMultiByte(path), attrib, iconIndex);\r
+}\r
+#endif\r
+\r
+DWORD_PTR GetRealIconIndex(const UString &fileName, DWORD attrib,\r
+    int &iconIndex, UString &typeName)\r
+{\r
+  #ifndef _UNICODE\r
+  if(!g_IsNT)\r
+  {\r
+    SHFILEINFO shellInfo;\r
+    shellInfo.szTypeName[0] = 0;\r
+    DWORD_PTR res = ::SHGetFileInfoA(GetSystemString(fileName), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,\r
+        sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);\r
+    typeName = GetUnicodeString(shellInfo.szTypeName);\r
+    iconIndex = shellInfo.iIcon;\r
+    return res;\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    SHFILEINFOW shellInfo;\r
+    shellInfo.szTypeName[0] = 0;\r
+    DWORD_PTR res = ::MySHGetFileInfoW(fileName, FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,\r
+        sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);\r
+    typeName = shellInfo.szTypeName;\r
+    iconIndex = shellInfo.iIcon;\r
+    return res;\r
+  }\r
+}\r
+\r
+int CExtToIconMap::GetIconIndex(DWORD attrib, const UString &fileName, UString &typeName)\r
+{\r
+  int dotPos = fileName.ReverseFind(L'.');\r
+  if ((attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 || dotPos < 0)\r
+  {\r
+    CAttribIconPair pair;\r
+    pair.Attrib = attrib;\r
+    int index = _attribMap.FindInSorted(pair);\r
+    if (index >= 0)\r
+    {\r
+      typeName = _attribMap[index].TypeName;\r
+      return _attribMap[index].IconIndex;\r
+    }\r
+    GetRealIconIndex(\r
+        #ifdef UNDER_CE\r
+        L"\\"\r
+        #endif\r
+        L"__File__"\r
+        , attrib, pair.IconIndex, pair.TypeName);\r
+    _attribMap.AddToSorted(pair);\r
+    typeName = pair.TypeName;\r
+    return pair.IconIndex;\r
+  }\r
+\r
+  CExtIconPair pair;\r
+  pair.Ext = fileName.Mid(dotPos + 1);\r
+  int index = _extMap.FindInSorted(pair);\r
+  if (index >= 0)\r
+  {\r
+    typeName = _extMap[index].TypeName;\r
+    return _extMap[index].IconIndex;\r
+  }\r
+  GetRealIconIndex(fileName.Mid(dotPos), attrib, pair.IconIndex, pair.TypeName);\r
+  _extMap.AddToSorted(pair);\r
+  typeName = pair.TypeName;\r
+  return pair.IconIndex;\r
+}\r
+\r
+int CExtToIconMap::GetIconIndex(DWORD attrib, const UString &fileName)\r
+{\r
+  UString typeName;\r
+  return GetIconIndex(attrib, fileName, typeName);\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.h b/CPP/7zip/UI/FileManager/SysIconUtils.h
new file mode 100755 (executable)
index 0000000..59fcad5
--- /dev/null
@@ -0,0 +1,57 @@
+// SysIconUtils.h\r
+\r
+#ifndef __SYS_ICON_UTILS_H\r
+#define __SYS_ICON_UTILS_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+struct CExtIconPair\r
+{\r
+  UString Ext;\r
+  int IconIndex;\r
+  UString TypeName;\r
+};\r
+\r
+struct CAttribIconPair\r
+{\r
+  DWORD Attrib;\r
+  int IconIndex;\r
+  UString TypeName;\r
+};\r
+\r
+inline bool operator==(const CExtIconPair &a1, const CExtIconPair &a2) { return a1.Ext == a2.Ext; }\r
+inline bool operator< (const CExtIconPair &a1, const CExtIconPair &a2) { return a1.Ext < a2.Ext; }\r
+\r
+inline bool operator==(const CAttribIconPair &a1, const CAttribIconPair &a2) { return a1.Attrib == a2.Attrib; }\r
+inline bool operator< (const CAttribIconPair &a1, const CAttribIconPair &a2) { return a1.Attrib < a2.Attrib; }\r
+\r
+class CExtToIconMap\r
+{\r
+  CObjectVector<CExtIconPair> _extMap;\r
+  CObjectVector<CAttribIconPair> _attribMap;\r
+public:\r
+  void Clear()\r
+  {\r
+    _extMap.Clear();\r
+    _attribMap.Clear();\r
+  }\r
+  int GetIconIndex(DWORD attrib, const UString &fileName, UString &typeName);\r
+  int GetIconIndex(DWORD attrib, const UString &fileName);\r
+};\r
+\r
+DWORD_PTR GetRealIconIndex(LPCTSTR path, DWORD attrib, int &iconIndex);\r
+#ifndef _UNICODE\r
+DWORD_PTR GetRealIconIndex(LPCWSTR path, DWORD attrib, int &iconIndex);\r
+#endif\r
+int GetIconIndexForCSIDL(int csidl);\r
+\r
+inline HIMAGELIST GetSysImageList(bool smallIcons)\r
+{\r
+  SHFILEINFO shellInfo;\r
+  return (HIMAGELIST)SHGetFileInfo(TEXT(""),\r
+      FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY,\r
+      &shellInfo, sizeof(shellInfo),\r
+      SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | (smallIcons ? SHGFI_SMALLICON : SHGFI_ICON));\r
+}\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/SystemPage.cpp b/CPP/7zip/UI/FileManager/SystemPage.cpp
new file mode 100755 (executable)
index 0000000..5b96869
--- /dev/null
@@ -0,0 +1,402 @@
+// SystemPage.cpp\r
+\r
+#include "StdAfx.h"\r
+#include "SystemPageRes.h"\r
+#include "SystemPage.h"\r
+\r
+#include "Common/StringConvert.h"\r
+#include "Common/MyCom.h"\r
+\r
+#include "Windows/Defs.h"\r
+#include "Windows/Control/ListView.h"\r
+#include "Windows/FileFind.h"\r
+\r
+#include "IFolder.h"\r
+#include "HelpUtils.h"\r
+#include "LangUtils.h"\r
+#include "PluginLoader.h"\r
+#include "ProgramLocation.h"\r
+#include "StringUtils.h"\r
+\r
+#include "PropertyNameRes.h"\r
+#include "../Agent/Agent.h"\r
+\r
+using namespace NRegistryAssociations;\r
+\r
+const int kRefreshpluginsListMessage  = WM_USER + 1;\r
+const int kUpdateDatabase = kRefreshpluginsListMessage  + 1;\r
+\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDC_SYSTEM_STATIC_ASSOCIATE,  0x03010302},\r
+  { IDC_SYSTEM_SELECT_ALL,        0x03000330}\r
+};\r
+\r
+static LPCWSTR kSystemTopic = L"FM/options.htm#system";\r
+\r
+\r
+bool CSystemPage::OnInit()\r
+{\r
+  _initMode = true;\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+\r
+  _listViewExt.Attach(GetItem(IDC_SYSTEM_LIST_ASSOCIATE));\r
+  _listViewPlugins.Attach(GetItem(IDC_SYSTEM_LIST_PLUGINS));\r
+\r
+  /*\r
+  CheckButton(IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU,\r
+      NRegistryAssociations::CheckContextMenuHandler());\r
+  */\r
+\r
+  UINT32 newFlags = LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT;\r
+  _listViewExt.SetExtendedListViewStyle(newFlags, newFlags);\r
+  _listViewPlugins.SetExtendedListViewStyle(newFlags, newFlags);\r
+\r
+  _listViewExt.InsertColumn(0, LangString(IDS_PROP_EXTENSION, 0x02000205), 40);\r
+  const UString s = LangString(IDS_PLUGIN, 0x03010310);\r
+  _listViewExt.InsertColumn(1, s, 40);\r
+\r
+  _listViewPlugins.InsertColumn(0, s, 40);\r
+\r
+  _extDatabase.Read();\r
+\r
+  for (int i = 0; i < _extDatabase.ExtBigItems.Size(); i++)\r
+  {\r
+    CExtInfoBig &extInfo = _extDatabase.ExtBigItems[i];\r
+\r
+    int itemIndex = _listViewExt.InsertItem(i, (LPCWSTR)extInfo.Ext);\r
+\r
+    UString iconPath;\r
+    int iconIndex;\r
+    extInfo.Associated = NRegistryAssociations::CheckShellExtensionInfo(GetSystemString(extInfo.Ext), iconPath, iconIndex);\r
+    if (extInfo.Associated && !NWindows::NFile::NFind::DoesFileExist(iconPath))\r
+      extInfo.Associated = false;\r
+    _listViewExt.SetCheckState(itemIndex, extInfo.Associated);\r
+\r
+    SetMainPluginText(itemIndex, i);\r
+  }\r
+  // _listViewExt.SortItems();\r
+  \r
+  if (_listViewExt.GetItemCount() > 0)\r
+    _listViewExt.SetItemState_FocusedSelected(0);\r
+  RefreshPluginsList(-1);\r
+  _initMode = false;\r
+\r
+  return CPropertyPage::OnInit();\r
+}\r
+\r
+void CSystemPage::SetMainPluginText(int itemIndex, int indexInDatabase)\r
+{\r
+  _listViewExt.SetSubItem(itemIndex, 1, _extDatabase.GetMainPluginNameForExtItem(indexInDatabase));\r
+}\r
+\r
+static UString GetProgramCommand()\r
+{\r
+  UString path = L"\"";\r
+  UString folder;\r
+  if (GetProgramFolderPath(folder))\r
+    path += folder;\r
+  path += L"7zFM.exe\" \"%1\"";\r
+  return path;\r
+}\r
+\r
+static UString GetIconPath(const UString &filePath,\r
+    const CLSID &clsID, const UString &extension, Int32 &iconIndex)\r
+{\r
+  CPluginLibrary library;\r
+  CMyComPtr<IFolderManager> folderManager;\r
+  CMyComPtr<IFolderFolder> folder;\r
+  if (filePath.IsEmpty())\r
+    folderManager = new CArchiveFolderManager;\r
+  else if (library.LoadAndCreateManager(filePath, clsID, &folderManager) != S_OK)\r
+    return UString();\r
+  CMyComBSTR extBSTR;\r
+  if (folderManager->GetExtensions(&extBSTR) != S_OK)\r
+    return UString();\r
+  const UString ext2 = (const wchar_t *)extBSTR;\r
+  UStringVector exts;\r
+  SplitString(ext2, exts);\r
+  for (int i = 0; i < exts.Size(); i++)\r
+  {\r
+    const UString &plugExt = exts[i];\r
+    if (extension.CompareNoCase((const wchar_t *)plugExt) == 0)\r
+    {\r
+      CMyComBSTR iconPathTemp;\r
+      if (folderManager->GetIconPath(plugExt, &iconPathTemp, &iconIndex) != S_OK)\r
+        break;\r
+      if (iconPathTemp != 0)\r
+        return (const wchar_t *)iconPathTemp;\r
+    }\r
+  }\r
+  return UString();\r
+}\r
+\r
+LONG CSystemPage::OnApply()\r
+{\r
+  UpdateDatabase();\r
+  _extDatabase.Save();\r
+  UString command = GetProgramCommand();\r
+  \r
+  for (int i = 0; i < _extDatabase.ExtBigItems.Size(); i++)\r
+  {\r
+    const CExtInfoBig &extInfo = _extDatabase.ExtBigItems[i];\r
+    if (extInfo.Associated)\r
+    {\r
+      UString title = extInfo.Ext + UString(L" Archive");\r
+      UString command = GetProgramCommand();\r
+      UString iconPath;\r
+      Int32 iconIndex = -1;\r
+      if (!extInfo.PluginsPairs.IsEmpty())\r
+      {\r
+        const CPluginInfo &plugin = _extDatabase.Plugins[extInfo.PluginsPairs[0].Index];\r
+        iconPath = GetIconPath(plugin.FilePath, plugin.ClassID, extInfo.Ext, iconIndex);\r
+      }\r
+      NRegistryAssociations::AddShellExtensionInfo(GetSystemString(extInfo.Ext),\r
+            title, command, iconPath, iconIndex, NULL, 0);\r
+    }\r
+    else\r
+      NRegistryAssociations::DeleteShellExtensionInfo(GetSystemString(extInfo.Ext));\r
+  }\r
+  /*\r
+  if (IsButtonCheckedBool(IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU))\r
+    NRegistryAssociations::AddContextMenuHandler();\r
+  else\r
+    NRegistryAssociations::DeleteContextMenuHandler();\r
+  */\r
+  #ifndef UNDER_CE\r
+  SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);\r
+  WasChanged = true;\r
+  #endif\r
+  return PSNRET_NOERROR;\r
+}\r
+\r
+void CSystemPage::OnNotifyHelp()\r
+{\r
+  ShowHelpWindow(NULL, kSystemTopic);\r
+}\r
+\r
+void CSystemPage::SelectAll()\r
+{\r
+  int count = _listViewExt.GetItemCount();\r
+  for (int i = 0; i < count; i++)\r
+    _listViewExt.SetCheckState(i, true);\r
+  UpdateDatabase();\r
+}\r
+\r
+bool CSystemPage::OnButtonClicked(int buttonID, HWND buttonHWND)\r
+{\r
+  switch(buttonID)\r
+  {\r
+    case IDC_SYSTEM_SELECT_ALL:\r
+    {\r
+      SelectAll();\r
+      Changed();\r
+      return true;\r
+    }\r
+  }\r
+  return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);\r
+}\r
+\r
+bool CSystemPage::OnNotify(UINT controlID, LPNMHDR lParam)\r
+{\r
+  if (lParam->hwndFrom == HWND(_listViewExt))\r
+  {\r
+    switch(lParam->code)\r
+    {\r
+      case (LVN_ITEMCHANGED):\r
+        return OnItemChanged((const NMLISTVIEW *)lParam);\r
+      case NM_RCLICK:\r
+      case NM_DBLCLK:\r
+      case LVN_KEYDOWN:\r
+      case NM_CLICK:\r
+      case LVN_BEGINRDRAG:\r
+        PostMessage(kRefreshpluginsListMessage, 0);\r
+        PostMessage(kUpdateDatabase, 0);\r
+        break;\r
+    }\r
+  }\r
+  else if (lParam->hwndFrom == HWND(_listViewPlugins))\r
+  {\r
+    switch(lParam->code)\r
+    {\r
+      case NM_RCLICK:\r
+      case NM_DBLCLK:\r
+      // case LVN_KEYDOWN:\r
+      case NM_CLICK:\r
+      case LVN_BEGINRDRAG:\r
+        PostMessage(kUpdateDatabase, 0);\r
+        break;\r
+\r
+      case (LVN_ITEMCHANGED):\r
+      {\r
+        OnItemChanged((const NMLISTVIEW *)lParam);\r
+        PostMessage(kUpdateDatabase, 0);\r
+        break;\r
+      }\r
+      case LVN_KEYDOWN:\r
+      {\r
+        OnPluginsKeyDown((LPNMLVKEYDOWN)lParam);\r
+        PostMessage(kUpdateDatabase, 0);\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  return CPropertyPage::OnNotify(controlID, lParam);\r
+}\r
+\r
+bool CSystemPage::OnPluginsKeyDown(LPNMLVKEYDOWN keyDownInfo)\r
+{\r
+  bool alt = (::GetKeyState(VK_MENU) & 0x8000) != 0;\r
+  // bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0;\r
+  switch(keyDownInfo->wVKey)\r
+  {\r
+    case VK_UP:\r
+    {\r
+      if (alt)\r
+        MovePlugin(true);\r
+      return true;\r
+    }\r
+    case VK_DOWN:\r
+    {\r
+      if (alt)\r
+        MovePlugin(false);\r
+      return true;\r
+    }\r
+  }\r
+  return false;\r
+}\r
+\r
+void CSystemPage::MovePlugin(bool upDirection)\r
+{\r
+  int selectedPlugin = _listViewPlugins.GetSelectionMark();\r
+  if (selectedPlugin < 0)\r
+    return;\r
+  int newIndex = selectedPlugin + (upDirection ? -1: 1);\r
+  if (newIndex < 0 || newIndex >= _listViewPlugins.GetItemCount())\r
+    return;\r
+  int selectedExtIndex = GetSelectedExtIndex();\r
+  if (selectedExtIndex < 0)\r
+    return;\r
+  CExtInfoBig &extInfo = _extDatabase.ExtBigItems[selectedExtIndex];\r
+  CPluginEnabledPair pluginPairTemp = extInfo.PluginsPairs[newIndex];\r
+  extInfo.PluginsPairs[newIndex] = extInfo.PluginsPairs[selectedPlugin];\r
+  extInfo.PluginsPairs[selectedPlugin] = pluginPairTemp;\r
+\r
+  SetMainPluginText(_listViewExt.GetSelectionMark(), selectedExtIndex);\r
+  RefreshPluginsList(newIndex);\r
+\r
+  Changed();\r
+}\r
+\r
+bool CSystemPage::OnItemChanged(const NMLISTVIEW *info)\r
+{\r
+  if (_initMode)\r
+    return true;\r
+  if ((info->uChanged & LVIF_STATE) != 0)\r
+  {\r
+    UINT oldState = info->uOldState & LVIS_STATEIMAGEMASK;\r
+    UINT newState = info->uNewState & LVIS_STATEIMAGEMASK;\r
+    if (oldState != newState)\r
+      Changed();\r
+  }\r
+  // PostMessage(kRefreshpluginsListMessage, 0);\r
+  // RefreshPluginsList();\r
+  return true;\r
+}\r
+\r
+bool CSystemPage::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+  switch(message)\r
+  {\r
+    case kRefreshpluginsListMessage:\r
+      RefreshPluginsList(-1);\r
+      return true;\r
+    case kUpdateDatabase:\r
+      UpdateDatabase();\r
+      return true;\r
+  }\r
+  return CPropertyPage::OnMessage(message, wParam, lParam);\r
+}\r
+\r
+void CSystemPage::UpdateDatabase()\r
+{\r
+  int i;\r
+  for (i = 0; i < _listViewExt.GetItemCount(); i++)\r
+  {\r
+    LPARAM param;\r
+    if (!_listViewExt.GetItemParam(i, param))\r
+      return;\r
+    CExtInfoBig &extInfo = _extDatabase.ExtBigItems[(int)param];\r
+    extInfo.Associated = _listViewExt.GetCheckState(i);\r
+  }\r
+\r
+  int selectedExtIndex = GetSelectedExtIndex();\r
+  if (selectedExtIndex < 0)\r
+    return;\r
+\r
+  CExtInfoBig &extInfo = _extDatabase.ExtBigItems[selectedExtIndex];\r
+  for (i = 0; i < _listViewPlugins.GetItemCount(); i++)\r
+  {\r
+    extInfo.PluginsPairs[i].Enabled = _listViewPlugins.GetCheckState(i);\r
+  }\r
+}\r
+\r
+\r
+\r
+int CSystemPage::GetSelectedExtIndex()\r
+{\r
+  int selectedIndex = _listViewExt.GetSelectionMark();\r
+  if (selectedIndex < 0)\r
+    return -1;\r
+  LPARAM param;\r
+  if (!_listViewExt.GetItemParam(selectedIndex, param))\r
+    return -1;\r
+  return (int)param;\r
+}\r
+\r
+\r
+void CSystemPage::RefreshPluginsList(int selectIndex)\r
+{\r
+  _listViewPlugins.DeleteAllItems();\r
+  int selectedExtIndex = GetSelectedExtIndex();\r
+  if (selectedExtIndex < 0)\r
+    return;\r
+  const CExtInfoBig &extInfo = _extDatabase.ExtBigItems[selectedExtIndex];\r
+\r
+  _initMode = true;\r
+  for (int i = 0; i < extInfo.PluginsPairs.Size(); i++)\r
+  {\r
+    CPluginEnabledPair pluginPair = extInfo.PluginsPairs[i];\r
+    int itemIndex = _listViewPlugins.InsertItem(i, _extDatabase.Plugins[pluginPair.Index].Name);\r
+    _listViewPlugins.SetCheckState(itemIndex, pluginPair.Enabled);\r
+  }\r
+  if (_listViewPlugins.GetItemCount() > 0)\r
+  {\r
+    if (selectIndex < 0)\r
+      selectIndex = 0;\r
+    _listViewPlugins.SetItemState_FocusedSelected(selectIndex);\r
+  }\r
+  _initMode = false;\r
+}\r
+\r
+\r
+\r
+/*\r
+static BYTE kZipShellNewData[] =\r
+  { 0x50-1, 0x4B, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0 };\r
+\r
+static BYTE kRarShellNewData[] =\r
+  { 0x52-1, 0x61, 0x72, 0x21, 0x1A, 7, 0, 0xCF, 0x90, 0x73, 0, 0, 0x0D, 0, 0, 0, 0, 0, 0, 0};\r
+\r
+class CSignatureMaker\r
+{\r
+public:\r
+  CSignatureMaker()\r
+  {\r
+    kZipShellNewData[0]++;\r
+    kRarShellNewData[0]++;\r
+  };\r
+};\r
+\r
+static CSignatureMaker g_SignatureMaker;\r
+*/\r
diff --git a/CPP/7zip/UI/FileManager/SystemPage.h b/CPP/7zip/UI/FileManager/SystemPage.h
new file mode 100755 (executable)
index 0000000..54e6e70
--- /dev/null
@@ -0,0 +1,41 @@
+// SystemPage.h\r
\r
+#ifndef __SYSTEM_PAGE_H\r
+#define __SYSTEM_PAGE_H\r
+\r
+#include "Windows/Control/PropertyPage.h"\r
+#include "Windows/Control/ListView.h"\r
+\r
+#include "FilePlugins.h"\r
+\r
+class CSystemPage: public NWindows::NControl::CPropertyPage\r
+{\r
+  bool _initMode;\r
+  CExtDatabase _extDatabase;\r
+\r
+  NWindows::NControl::CListView _listViewExt;\r
+  NWindows::NControl::CListView _listViewPlugins;\r
+\r
+  void SetMainPluginText(int itemIndex, int indexInDatabase);\r
+\r
+  int GetSelectedExtIndex();\r
+  void RefreshPluginsList(int selectIndex);\r
+  void MovePlugin(bool upDirection);\r
+  void UpdateDatabase();\r
+  void SelectAll();\r
+\r
+public:\r
+  bool WasChanged;\r
+  CSystemPage(): WasChanged(false) {}\r
+  virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);\r
+  virtual bool OnInit();\r
+  virtual void OnNotifyHelp();\r
+  virtual bool OnNotify(UINT controlID, LPNMHDR lParam);\r
+  virtual bool OnItemChanged(const NMLISTVIEW *info);\r
+\r
+  virtual LONG OnApply();\r
+  virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);\r
+  bool OnPluginsKeyDown(LPNMLVKEYDOWN keyDownInfo);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/SystemPage.rc b/CPP/7zip/UI/FileManager/SystemPage.rc
new file mode 100755 (executable)
index 0000000..a2e4062
--- /dev/null
@@ -0,0 +1,43 @@
+#include "SystemPageRes.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#define xc 200\r
+#define yc 200\r
+\r
+IDD_SYSTEM  MY_PAGE\r
+CAPTION "System"\r
+BEGIN\r
+  LTEXT      "Associate 7-Zip with:", IDC_SYSTEM_STATIC_ASSOCIATE, m, m, xc, 8\r
+  CONTROL    "List1", IDC_SYSTEM_LIST_ASSOCIATE, "SysListView32",\r
+             LVS_LIST | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP,\r
+             m, m + 12, xc, (yc - m - 12 - 1 - bys)\r
+  PUSHBUTTON  "Select all", IDC_SYSTEM_SELECT_ALL, m, (ys - m - bys), 90, bys\r
+END\r
+\r
+#ifdef UNDER_CE\r
+\r
+#undef m\r
+#undef xc\r
+#undef yc\r
+\r
+#define m 4\r
+#define xc (SMALL_PAGE_SIZE_X + 8)\r
+#define yc (128 + 8)\r
+\r
+IDD_SYSTEM_2  MY_PAGE\r
+CAPTION "System"\r
+BEGIN\r
+  LTEXT      "Associate 7-Zip with:", IDC_SYSTEM_STATIC_ASSOCIATE, m, m, xc, 8\r
+  CONTROL    "List1", IDC_SYSTEM_LIST_ASSOCIATE, "SysListView32",\r
+             LVS_LIST | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP,\r
+             m, m + 12, xc, (yc - m - 12 - 1 - bys - 8)\r
+  PUSHBUTTON  "Select all", IDC_SYSTEM_SELECT_ALL, m, (ys - m - bys - 8), 90, bys\r
+END\r
+\r
+#endif\r
+\r
+\r
+STRINGTABLE\r
+BEGIN\r
+  IDS_PLUGIN  "Plugin"\r
+END\r
diff --git a/CPP/7zip/UI/FileManager/SystemPageRes.h b/CPP/7zip/UI/FileManager/SystemPageRes.h
new file mode 100755 (executable)
index 0000000..c4667d3
--- /dev/null
@@ -0,0 +1,8 @@
+#define IDD_SYSTEM                      540\r
+#define IDD_SYSTEM_2                    640\r
+#define IDS_PLUGIN                      990\r
+// #define IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU 1010\r
+#define IDC_SYSTEM_STATIC_ASSOCIATE     1020\r
+#define IDC_SYSTEM_LIST_ASSOCIATE       1021\r
+#define IDC_SYSTEM_LIST_PLUGINS         1022\r
+#define IDC_SYSTEM_SELECT_ALL           1023\r
diff --git a/CPP/7zip/UI/FileManager/Test.bmp b/CPP/7zip/UI/FileManager/Test.bmp
new file mode 100755 (executable)
index 0000000..ef85ba2
Binary files /dev/null and b/CPP/7zip/UI/FileManager/Test.bmp differ
diff --git a/CPP/7zip/UI/FileManager/Test2.bmp b/CPP/7zip/UI/FileManager/Test2.bmp
new file mode 100755 (executable)
index 0000000..99b7dbf
Binary files /dev/null and b/CPP/7zip/UI/FileManager/Test2.bmp differ
diff --git a/CPP/7zip/UI/FileManager/TextPairs.cpp b/CPP/7zip/UI/FileManager/TextPairs.cpp
new file mode 100755 (executable)
index 0000000..f46bce7
--- /dev/null
@@ -0,0 +1,189 @@
+// TextPairs.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "TextPairs.h"\r
+\r
+static const wchar_t kNewLineChar = '\n';\r
+static const wchar_t kQuoteChar = '\"';\r
+\r
+static const wchar_t kBOM = (wchar_t)0xFEFF;\r
+\r
+static bool IsSeparatorChar(wchar_t c)\r
+{\r
+  return (c == ' ' || c == '\t');\r
+}\r
+\r
+static void RemoveCr(UString &s)\r
+{\r
+  s.Replace(L"\x0D", L"");\r
+}\r
+\r
+static UString GetIDString(const wchar_t *srcString, int &finishPos)\r
+{\r
+  UString result;\r
+  bool quotes = false;\r
+  for (finishPos = 0;;)\r
+  {\r
+    wchar_t c = srcString[finishPos];\r
+    if (c == 0)\r
+      break;\r
+    finishPos++;\r
+    bool isSeparatorChar = IsSeparatorChar(c);\r
+    if (c == kNewLineChar || (isSeparatorChar && !quotes)\r
+        || (c == kQuoteChar && quotes))\r
+      break;\r
+    else if (c == kQuoteChar)\r
+      quotes = true;\r
+    else\r
+      result += c;\r
+  }\r
+  result.Trim();\r
+  RemoveCr(result);\r
+  return result;\r
+}\r
+\r
+static UString GetValueString(const wchar_t *srcString, int &finishPos)\r
+{\r
+  UString result;\r
+  for (finishPos = 0;;)\r
+  {\r
+    wchar_t c = srcString[finishPos];\r
+    if (c == 0)\r
+      break;\r
+    finishPos++;\r
+    if (c == kNewLineChar)\r
+      break;\r
+    result += c;\r
+  }\r
+  result.Trim();\r
+  RemoveCr(result);\r
+  return result;\r
+}\r
+\r
+static bool GetTextPairs(const UString &srcString, CObjectVector<CTextPair> &pairs)\r
+{\r
+  pairs.Clear();\r
+  int pos = 0;\r
+  \r
+  if (srcString.Length() > 0)\r
+  {\r
+    if (srcString[0] == kBOM)\r
+      pos++;\r
+  }\r
+  while (pos < srcString.Length())\r
+  {\r
+    int finishPos;\r
+    UString id = GetIDString((const wchar_t *)srcString + pos, finishPos);\r
+    pos += finishPos;\r
+    if (id.IsEmpty())\r
+      continue;\r
+    UString value = GetValueString((const wchar_t *)srcString + pos, finishPos);\r
+    pos += finishPos;\r
+    if (!id.IsEmpty())\r
+    {\r
+      CTextPair pair;\r
+      pair.ID = id;\r
+      pair.Value = value;\r
+      pairs.Add(pair);\r
+    }\r
+  }\r
+  return true;\r
+}\r
+\r
+static int ComparePairIDs(const UString &s1, const UString &s2)\r
+  { return s1.CompareNoCase(s2); }\r
+static int ComparePairItems(const CTextPair &p1, const CTextPair &p2)\r
+  { return ComparePairIDs(p1.ID, p2.ID); }\r
+\r
+static int ComparePairItems(void *const *a1, void *const *a2, void * /* param */)\r
+  { return ComparePairItems(**(const CTextPair **)a1, **(const CTextPair **)a2); }\r
+\r
+void CPairsStorage::Sort() { Pairs.Sort(ComparePairItems, 0); }\r
+\r
+int CPairsStorage::FindID(const UString &id, int &insertPos)\r
+{\r
+  int left = 0, right = Pairs.Size();\r
+  while (left != right)\r
+  {\r
+    int mid = (left + right) / 2;\r
+    int compResult = ComparePairIDs(id, Pairs[mid].ID);\r
+    if (compResult == 0)\r
+      return mid;\r
+    if (compResult < 0)\r
+      right = mid;\r
+    else\r
+      left = mid + 1;\r
+  }\r
+  insertPos = left;\r
+  return -1;\r
+}\r
+\r
+int CPairsStorage::FindID(const UString &id)\r
+{\r
+  int pos;\r
+  return FindID(id, pos);\r
+}\r
+\r
+void CPairsStorage::AddPair(const CTextPair &pair)\r
+{\r
+  int insertPos;\r
+  int pos = FindID(pair.ID, insertPos);\r
+  if (pos >= 0)\r
+    Pairs[pos] = pair;\r
+  else\r
+    Pairs.Insert(insertPos, pair);\r
+}\r
+\r
+void CPairsStorage::DeletePair(const UString &id)\r
+{\r
+  int pos = FindID(id);\r
+  if (pos >= 0)\r
+    Pairs.Delete(pos);\r
+}\r
+\r
+bool CPairsStorage::GetValue(const UString &id, UString &value)\r
+{\r
+  value.Empty();\r
+  int pos = FindID(id);\r
+  if (pos < 0)\r
+    return false;\r
+  value = Pairs[pos].Value;\r
+  return true;\r
+}\r
+\r
+UString CPairsStorage::GetValue(const UString &id)\r
+{\r
+  int pos = FindID(id);\r
+  if (pos < 0)\r
+    return UString();\r
+  return Pairs[pos].Value;\r
+}\r
+\r
+bool CPairsStorage::ReadFromString(const UString &text)\r
+{\r
+  bool result = ::GetTextPairs(text, Pairs);\r
+  if (result)\r
+    Sort();\r
+  else\r
+    Pairs.Clear();\r
+  return result;\r
+}\r
+\r
+void CPairsStorage::SaveToString(UString &text)\r
+{\r
+  for (int i = 0; i < Pairs.Size(); i++)\r
+  {\r
+    const CTextPair &pair = Pairs[i];\r
+    bool multiWord = (pair.ID.Find(L' ') >= 0);\r
+    if (multiWord)\r
+      text += L'\"';\r
+    text += pair.ID;\r
+    if (multiWord)\r
+      text += L'\"';\r
+    text += L' ';\r
+    text += pair.Value;\r
+    text += L'\x0D';\r
+    text += L'\n';\r
+  }\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/TextPairs.h b/CPP/7zip/UI/FileManager/TextPairs.h
new file mode 100755 (executable)
index 0000000..2abe920
--- /dev/null
@@ -0,0 +1,31 @@
+// TextPairs.h\r
+\r
+#ifndef __FM_TEXT_PAIRS_H\r
+#define __FM_TEXT_PAIRS_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+struct CTextPair\r
+{\r
+  UString ID;\r
+  UString Value;\r
+};\r
+\r
+class CPairsStorage\r
+{\r
+  CObjectVector<CTextPair> Pairs;\r
+  int FindID(const UString &id, int &insertPos);\r
+  int FindID(const UString &id);\r
+  void Sort();\r
+public:\r
+  void Clear() { Pairs.Clear(); };\r
+  bool ReadFromString(const UString &text);\r
+  void SaveToString(UString &text);\r
+\r
+  bool GetValue(const UString &id, UString &value);\r
+  UString GetValue(const UString &id);\r
+  void AddPair(const CTextPair &pair);\r
+  void DeletePair(const UString &id);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/UpdateCallback100.cpp b/CPP/7zip/UI/FileManager/UpdateCallback100.cpp
new file mode 100755 (executable)
index 0000000..7526dd7
--- /dev/null
@@ -0,0 +1,90 @@
+// UpdateCallback100.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "PasswordDialog.h"\r
+#include "UpdateCallback100.h"\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::SetNumFiles(UInt64 numFiles)\r
+{\r
+  ProgressDialog->Sync.SetNumFilesTotal(numFiles);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::SetTotal(UInt64 size)\r
+{\r
+  ProgressDialog->Sync.SetProgress(size, 0);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::SetCompleted(const UInt64 *completeValue)\r
+{\r
+  RINOK(ProgressDialog->Sync.ProcessStopAndPause());\r
+  if (completeValue != NULL)\r
+    ProgressDialog->Sync.SetPos(*completeValue);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)\r
+{\r
+  ProgressDialog->Sync.SetRatioInfo(inSize, outSize);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::CompressOperation(const wchar_t *name)\r
+{\r
+  ProgressDialog->Sync.SetCurrentFileName(name);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::DeleteOperation(const wchar_t *name)\r
+{\r
+  ProgressDialog->Sync.SetCurrentFileName(name);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::OperationResult(Int32 /* operationResult */)\r
+{\r
+  ProgressDialog->Sync.SetNumFilesCur(++_numFiles);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::UpdateErrorMessage(const wchar_t *message)\r
+{\r
+  ProgressDialog->Sync.AddErrorMessage(message);\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)\r
+{\r
+  *password = NULL;\r
+  *passwordIsDefined = BoolToInt(_passwordIsDefined);\r
+  if (!_passwordIsDefined)\r
+    return S_OK;\r
+  return StringToBstr(_password, password);\r
+}\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */)\r
+{\r
+  return S_OK;\r
+}\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */)\r
+{\r
+  return ProgressDialog->Sync.ProcessStopAndPause();\r
+}\r
+\r
+STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password)\r
+{\r
+  *password = NULL;\r
+  if (!_passwordIsDefined)\r
+  {\r
+    CPasswordDialog dialog;\r
+    ProgressDialog->WaitCreating();\r
+    if (dialog.Create(*ProgressDialog) == IDCANCEL)\r
+      return E_ABORT;\r
+    _password = dialog.Password;\r
+    _passwordIsDefined = true;\r
+  }\r
+  return StringToBstr(_password, password);\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/UpdateCallback100.h b/CPP/7zip/UI/FileManager/UpdateCallback100.h
new file mode 100755 (executable)
index 0000000..00411d6
--- /dev/null
@@ -0,0 +1,54 @@
+// UpdateCallback100.h\r
+\r
+#ifndef __UPDATE_CALLBACK100_H\r
+#define __UPDATE_CALLBACK100_H\r
+\r
+#include "Common/MyCom.h"\r
+\r
+#include "../../IPassword.h"\r
+\r
+#include "../Agent/IFolderArchive.h"\r
+\r
+#include "ProgressDialog2.h"\r
+\r
+class CUpdateCallback100Imp:\r
+  public IFolderArchiveUpdateCallback,\r
+  public ICryptoGetTextPassword2,\r
+  public ICryptoGetTextPassword,\r
+  public IArchiveOpenCallback,\r
+  public ICompressProgressInfo,\r
+  public CMyUnknownImp\r
+{\r
+  bool _passwordIsDefined;\r
+  UString _password;\r
+  UInt64 _numFiles;\r
+public:\r
+  CProgressDialog *ProgressDialog;\r
+\r
+  CUpdateCallback100Imp(): ProgressDialog(0) {}\r
+\r
+  MY_UNKNOWN_IMP5(\r
+    IFolderArchiveUpdateCallback,\r
+    ICryptoGetTextPassword2,\r
+    ICryptoGetTextPassword,\r
+    IArchiveOpenCallback,\r
+    ICompressProgressInfo)\r
+\r
+  INTERFACE_IProgress(;)\r
+  INTERFACE_IArchiveOpenCallback(;)\r
+  INTERFACE_IFolderArchiveUpdateCallback(;)\r
+\r
+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);\r
+\r
+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);\r
+  STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);\r
+\r
+  void Init(bool passwordIsDefined, const UString &password)\r
+  {\r
+    _passwordIsDefined = passwordIsDefined;\r
+    _password = password;\r
+    _numFiles = 0;\r
+  }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/ViewSettings.cpp b/CPP/7zip/UI/FileManager/ViewSettings.cpp
new file mode 100755 (executable)
index 0000000..d7a1894
--- /dev/null
@@ -0,0 +1,390 @@
+// ViewSettings.h\r
+\r
+#include "StdAfx.h"\r
\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "ViewSettings.h"\r
+#include "Windows/Registry.h"\r
+#include "Windows/Synchronization.h"\r
+\r
+using namespace NWindows;\r
+using namespace NRegistry;\r
+\r
+#define REG_PATH_FM TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") TEXT(STRING_PATH_SEPARATOR) TEXT("FM")\r
+\r
+static const TCHAR *kCUBasePath = REG_PATH_FM;\r
+static const TCHAR *kCulumnsKeyName = REG_PATH_FM TEXT(STRING_PATH_SEPARATOR) TEXT("Columns");\r
+\r
+static const TCHAR *kPositionValueName = TEXT("Position");\r
+static const TCHAR *kPanelsInfoValueName = TEXT("Panels");\r
+static const TCHAR *kToolbars = TEXT("Toolbars");\r
+\r
+static const WCHAR *kPanelPathValueName = L"PanelPath";\r
+static const TCHAR *kListMode = TEXT("ListMode");\r
+static const TCHAR *kFolderHistoryValueName = TEXT("FolderHistory");\r
+static const TCHAR *kFastFoldersValueName = TEXT("FolderShortcuts");\r
+static const TCHAR *kCopyHistoryValueName = TEXT("CopyHistory");\r
+\r
+/*\r
+class CColumnInfoSpec\r
+{\r
+  UInt32 PropID;\r
+  Byte IsVisible;\r
+  UInt32 Width;\r
+};\r
+\r
+struct CColumnHeader\r
+{\r
+  UInt32 Version;\r
+  UInt32 SortID;\r
+  Byte Ascending;\r
+};\r
+*/\r
+\r
+static const UInt32 kColumnInfoSpecHeader = 12;\r
+static const UInt32 kColumnHeaderSize = 12;\r
+\r
+static const UInt32 kColumnInfoVersion = 1;\r
+\r
+static NSynchronization::CCriticalSection g_CS;\r
+\r
+class CTempOutBufferSpec\r
+{\r
+  CByteBuffer Buffer;\r
+  UInt32 Size;\r
+  UInt32 Pos;\r
+public:\r
+  operator const Byte *() const { return (const Byte *)Buffer; }\r
+  void Init(UInt32 dataSize)\r
+  {\r
+    Buffer.SetCapacity(dataSize);\r
+    Size = dataSize;\r
+    Pos = 0;\r
+  }\r
+  void WriteByte(Byte value)\r
+  {\r
+    if (Pos >= Size)\r
+      throw "overflow";\r
+    ((Byte *)Buffer)[Pos++] = value;\r
+  }\r
+  void WriteUInt32(UInt32 value)\r
+  {\r
+    for (int i = 0; i < 4; i++)\r
+    {\r
+      WriteByte((Byte)value);\r
+      value >>= 8;\r
+    }\r
+  }\r
+  void WriteBool(bool value)\r
+  {\r
+    WriteUInt32(value ? 1 : 0);\r
+  }\r
+};\r
+\r
+class CTempInBufferSpec\r
+{\r
+public:\r
+  Byte *Buffer;\r
+  UInt32 Size;\r
+  UInt32 Pos;\r
+  Byte ReadByte()\r
+  {\r
+    if (Pos >= Size)\r
+      throw "overflow";\r
+    return Buffer[Pos++];\r
+  }\r
+  UInt32 ReadUInt32()\r
+  {\r
+    UInt32 value = 0;\r
+    for (int i = 0; i < 4; i++)\r
+      value |= (((UInt32)ReadByte()) << (8 * i));\r
+    return value;\r
+  }\r
+  bool ReadBool()\r
+  {\r
+    return (ReadUInt32() != 0);\r
+  }\r
+};\r
+\r
+void SaveListViewInfo(const UString &id, const CListViewInfo &viewInfo)\r
+{\r
+  const CObjectVector<CColumnInfo> &columns = viewInfo.Columns;\r
+  CTempOutBufferSpec buffer;\r
+  UInt32 dataSize = kColumnHeaderSize + kColumnInfoSpecHeader * columns.Size();\r
+  buffer.Init(dataSize);\r
+\r
+  buffer.WriteUInt32(kColumnInfoVersion);\r
+  buffer.WriteUInt32(viewInfo.SortID);\r
+  buffer.WriteBool(viewInfo.Ascending);\r
+  for(int i = 0; i < columns.Size(); i++)\r
+  {\r
+    const CColumnInfo &column = columns[i];\r
+    buffer.WriteUInt32(column.PropID);\r
+    buffer.WriteBool(column.IsVisible);\r
+    buffer.WriteUInt32(column.Width);\r
+  }\r
+  {\r
+    NSynchronization::CCriticalSectionLock lock(g_CS);\r
+    CKey key;\r
+    key.Create(HKEY_CURRENT_USER, kCulumnsKeyName);\r
+    key.SetValue(GetSystemString(id), (const Byte *)buffer, dataSize);\r
+  }\r
+}\r
+\r
+void ReadListViewInfo(const UString &id, CListViewInfo &viewInfo)\r
+{\r
+  viewInfo.Clear();\r
+  CObjectVector<CColumnInfo> &columns = viewInfo.Columns;\r
+  CByteBuffer buffer;\r
+  UInt32 size;\r
+  {\r
+    NSynchronization::CCriticalSectionLock lock(g_CS);\r
+    CKey key;\r
+    if (key.Open(HKEY_CURRENT_USER, kCulumnsKeyName, KEY_READ) != ERROR_SUCCESS)\r
+      return;\r
+    if (key.QueryValue(GetSystemString(id), buffer, size) != ERROR_SUCCESS)\r
+      return;\r
+  }\r
+  if (size < kColumnHeaderSize)\r
+    return;\r
+  CTempInBufferSpec inBuffer;\r
+  inBuffer.Size = size;\r
+  inBuffer.Buffer = (Byte *)buffer;\r
+  inBuffer.Pos = 0;\r
+\r
+\r
+  UInt32 version = inBuffer.ReadUInt32();\r
+  if (version != kColumnInfoVersion)\r
+    return;\r
+  viewInfo.SortID = inBuffer.ReadUInt32();\r
+  viewInfo.Ascending = inBuffer.ReadBool();\r
+\r
+  size -= kColumnHeaderSize;\r
+  if (size % kColumnInfoSpecHeader != 0)\r
+    return;\r
+  int numItems = size / kColumnInfoSpecHeader;\r
+  columns.Reserve(numItems);\r
+  for(int i = 0; i < numItems; i++)\r
+  {\r
+    CColumnInfo columnInfo;\r
+    columnInfo.PropID = inBuffer.ReadUInt32();\r
+    columnInfo.IsVisible = inBuffer.ReadBool();\r
+    columnInfo.Width = inBuffer.ReadUInt32();\r
+    columns.Add(columnInfo);\r
+  }\r
+}\r
+\r
+static const UInt32 kWindowPositionHeaderSize = 5 * 4;\r
+static const UInt32 kPanelsInfoHeaderSize = 3 * 4;\r
+\r
+/*\r
+struct CWindowPosition\r
+{\r
+  RECT Rect;\r
+  UInt32 Maximized;\r
+};\r
+\r
+struct CPanelsInfo\r
+{\r
+  UInt32 NumPanels;\r
+  UInt32 CurrentPanel;\r
+  UInt32 SplitterPos;\r
+};\r
+*/\r
+\r
+void SaveWindowSize(const RECT &rect, bool maximized)\r
+{\r
+  CSysString keyName = kCUBasePath;\r
+  NSynchronization::CCriticalSectionLock lock(g_CS);\r
+  CKey key;\r
+  key.Create(HKEY_CURRENT_USER, keyName);\r
+  // CWindowPosition position;\r
+  CTempOutBufferSpec buffer;\r
+  buffer.Init(kWindowPositionHeaderSize);\r
+  buffer.WriteUInt32(rect.left);\r
+  buffer.WriteUInt32(rect.top);\r
+  buffer.WriteUInt32(rect.right);\r
+  buffer.WriteUInt32(rect.bottom);\r
+  buffer.WriteBool(maximized);\r
+  key.SetValue(kPositionValueName, (const Byte *)buffer, kWindowPositionHeaderSize);\r
+}\r
+\r
+bool ReadWindowSize(RECT &rect, bool &maximized)\r
+{\r
+  CSysString keyName = kCUBasePath;\r
+  NSynchronization::CCriticalSectionLock lock(g_CS);\r
+  CKey key;\r
+  if (key.Open(HKEY_CURRENT_USER, keyName, KEY_READ) != ERROR_SUCCESS)\r
+    return false;\r
+  CByteBuffer buffer;\r
+  UInt32 size;\r
+  if (key.QueryValue(kPositionValueName, buffer, size) != ERROR_SUCCESS)\r
+    return false;\r
+  if (size != kWindowPositionHeaderSize)\r
+    return false;\r
+  CTempInBufferSpec inBuffer;\r
+  inBuffer.Size = size;\r
+  inBuffer.Buffer = (Byte *)buffer;\r
+  inBuffer.Pos = 0;\r
+  rect.left = inBuffer.ReadUInt32();\r
+  rect.top = inBuffer.ReadUInt32();\r
+  rect.right = inBuffer.ReadUInt32();\r
+  rect.bottom = inBuffer.ReadUInt32();\r
+  maximized = inBuffer.ReadBool();\r
+  return true;\r
+}\r
+\r
+void SavePanelsInfo(UInt32 numPanels, UInt32 currentPanel, UInt32 splitterPos)\r
+{\r
+  CSysString keyName = kCUBasePath;\r
+  NSynchronization::CCriticalSectionLock lock(g_CS);\r
+  CKey key;\r
+  key.Create(HKEY_CURRENT_USER, keyName);\r
+\r
+  CTempOutBufferSpec buffer;\r
+  buffer.Init(kPanelsInfoHeaderSize);\r
+  buffer.WriteUInt32(numPanels);\r
+  buffer.WriteUInt32(currentPanel);\r
+  buffer.WriteUInt32(splitterPos);\r
+  key.SetValue(kPanelsInfoValueName, (const Byte *)buffer, kPanelsInfoHeaderSize);\r
+}\r
+\r
+bool ReadPanelsInfo(UInt32 &numPanels, UInt32 &currentPanel, UInt32 &splitterPos)\r
+{\r
+  CSysString keyName = kCUBasePath;\r
+  NSynchronization::CCriticalSectionLock lock(g_CS);\r
+  CKey key;\r
+  if (key.Open(HKEY_CURRENT_USER, keyName, KEY_READ) != ERROR_SUCCESS)\r
+    return false;\r
+  CByteBuffer buffer;\r
+  UInt32 size;\r
+  if (key.QueryValue(kPanelsInfoValueName, buffer, size) != ERROR_SUCCESS)\r
+    return false;\r
+  if (size != kPanelsInfoHeaderSize)\r
+    return false;\r
+  CTempInBufferSpec inBuffer;\r
+  inBuffer.Size = size;\r
+  inBuffer.Buffer = (Byte *)buffer;\r
+  inBuffer.Pos = 0;\r
+  numPanels = inBuffer.ReadUInt32();\r
+  currentPanel = inBuffer.ReadUInt32();\r
+  splitterPos = inBuffer.ReadUInt32();\r
+  return true;\r
+}\r
+\r
+void SaveToolbarsMask(UInt32 toolbarMask)\r
+{\r
+  CKey key;\r
+  key.Create(HKEY_CURRENT_USER, kCUBasePath);\r
+  key.SetValue(kToolbars, toolbarMask);\r
+}\r
+\r
+static const UInt32 kDefaultToolbarMask = ((UInt32)1 << 31) | 8 | 4 | 1;\r
+\r
+UInt32 ReadToolbarsMask()\r
+{\r
+  CKey key;\r
+  if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS)\r
+    return kDefaultToolbarMask;\r
+  UInt32 mask;\r
+  if (key.QueryValue(kToolbars, mask) != ERROR_SUCCESS)\r
+    return kDefaultToolbarMask;\r
+  return mask;\r
+}\r
+\r
+\r
+static UString GetPanelPathName(UInt32 panelIndex)\r
+{\r
+  WCHAR panelString[16];\r
+  ConvertUInt32ToString(panelIndex, panelString);\r
+  return UString(kPanelPathValueName) + panelString;\r
+}\r
+\r
+\r
+void SavePanelPath(UInt32 panel, const UString &path)\r
+{\r
+  NSynchronization::CCriticalSectionLock lock(g_CS);\r
+  CKey key;\r
+  key.Create(HKEY_CURRENT_USER, kCUBasePath);\r
+  key.SetValue(GetPanelPathName(panel), path);\r
+}\r
+\r
+bool ReadPanelPath(UInt32 panel, UString &path)\r
+{\r
+  NSynchronization::CCriticalSectionLock lock(g_CS);\r
+  CKey key;\r
+  if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS)\r
+    return false;\r
+  return (key.QueryValue(GetPanelPathName(panel), path) == ERROR_SUCCESS);\r
+}\r
+\r
+void SaveListMode(const CListMode &listMode)\r
+{\r
+  CKey key;\r
+  key.Create(HKEY_CURRENT_USER, kCUBasePath);\r
+  UInt32 t = 0;\r
+  for (int i = 0; i < 2; i++)\r
+    t |= ((listMode.Panels[i]) & 0xFF) << (i * 8);\r
+  key.SetValue(kListMode, t);\r
+}\r
+\r
+void ReadListMode(CListMode &listMode)\r
+{\r
+  CKey key;\r
+  listMode.Init();\r
+  if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS)\r
+    return;\r
+  UInt32 t;\r
+  if (key.QueryValue(kListMode, t) != ERROR_SUCCESS)\r
+    return;\r
+  for (int i = 0; i < 2; i++)\r
+  {\r
+    listMode.Panels[i] = (t & 0xFF);\r
+    t >>= 8;\r
+  }\r
+}\r
+\r
+\r
+static void SaveStringList(LPCTSTR valueName, const UStringVector &folders)\r
+{\r
+  NSynchronization::CCriticalSectionLock lock(g_CS);\r
+  CKey key;\r
+  key.Create(HKEY_CURRENT_USER, kCUBasePath);\r
+  key.SetValue_Strings(valueName, folders);\r
+}\r
+\r
+static void ReadStringList(LPCTSTR valueName, UStringVector &folders)\r
+{\r
+  folders.Clear();\r
+  NSynchronization::CCriticalSectionLock lock(g_CS);\r
+  CKey key;\r
+  if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) == ERROR_SUCCESS)\r
+    key.GetValue_Strings(valueName, folders);\r
+}\r
+\r
+void SaveFolderHistory(const UStringVector &folders)\r
+  { SaveStringList(kFolderHistoryValueName, folders); }\r
+void ReadFolderHistory(UStringVector &folders)\r
+  { ReadStringList(kFolderHistoryValueName, folders); }\r
+\r
+void SaveFastFolders(const UStringVector &folders)\r
+  { SaveStringList(kFastFoldersValueName, folders); }\r
+void ReadFastFolders(UStringVector &folders)\r
+  { ReadStringList(kFastFoldersValueName, folders); }\r
+\r
+void SaveCopyHistory(const UStringVector &folders)\r
+  { SaveStringList(kCopyHistoryValueName, folders); }\r
+void ReadCopyHistory(UStringVector &folders)\r
+  { ReadStringList(kCopyHistoryValueName, folders); }\r
+\r
+void AddUniqueStringToHeadOfList(UStringVector &list, const UString &s)\r
+{\r
+  for (int i = 0; i < list.Size();)\r
+    if (s.CompareNoCase(list[i]) == 0)\r
+      list.Delete(i);\r
+    else\r
+      i++;\r
+  list.Insert(0, s);\r
+}\r
diff --git a/CPP/7zip/UI/FileManager/ViewSettings.h b/CPP/7zip/UI/FileManager/ViewSettings.h
new file mode 100755 (executable)
index 0000000..6ba6902
--- /dev/null
@@ -0,0 +1,98 @@
+// ViewSettings.h\r
+\r
+#ifndef __VIEW_SETTINGS_H\r
+#define __VIEW_SETTINGS_H\r
+\r
+#include "Common/MyString.h"\r
+#include "Common/Types.h"\r
+\r
+struct CColumnInfo\r
+{\r
+  PROPID PropID;\r
+  bool IsVisible;\r
+  UInt32 Width;\r
+};\r
+\r
+inline bool operator==(const CColumnInfo &a1, const CColumnInfo &a2)\r
+{\r
+  return (a1.PropID == a2.PropID) &&\r
+    (a1.IsVisible == a2.IsVisible) && (a1.Width == a2.Width);\r
+}\r
+\r
+inline bool operator!=(const CColumnInfo &a1, const CColumnInfo &a2)\r
+{\r
+  return !(a1 == a2);\r
+}\r
+\r
+struct CListViewInfo\r
+{\r
+  CObjectVector<CColumnInfo> Columns;\r
+  PROPID SortID;\r
+  bool Ascending;\r
+\r
+  void Clear()\r
+  {\r
+    SortID = 0;\r
+    Ascending = true;\r
+    Columns.Clear();\r
+  }\r
+\r
+  int FindColumnWithID(PROPID propID) const\r
+  {\r
+    for (int i = 0; i < Columns.Size(); i++)\r
+      if (Columns[i].PropID == propID)\r
+        return i;\r
+    return -1;\r
+  }\r
+\r
+  bool IsEqual(const CListViewInfo &info) const\r
+  {\r
+    if (Columns.Size() != info.Columns.Size() ||\r
+        // SortIndex != info.SortIndex ||\r
+        SortID != info.SortID ||\r
+        Ascending != info.Ascending)\r
+      return false;\r
+    for (int i = 0; i < Columns.Size(); i++)\r
+      if (Columns[i] != info.Columns[i])\r
+        return false;\r
+    return true;\r
+  }\r
+};\r
+\r
+void SaveListViewInfo(const UString &id, const CListViewInfo &viewInfo);\r
+void ReadListViewInfo(const UString &id, CListViewInfo &viewInfo);\r
+\r
+void SaveWindowSize(const RECT &rect, bool maximized);\r
+bool ReadWindowSize(RECT &rect, bool &maximized);\r
+\r
+void SavePanelsInfo(UInt32 numPanels, UInt32 currentPanel, UInt32 splitterPos);\r
+bool ReadPanelsInfo(UInt32 &numPanels, UInt32 &currentPanel, UInt32 &splitterPos);\r
+\r
+void SaveToolbarsMask(UInt32 toolbarMask);\r
+UInt32 ReadToolbarsMask();\r
+\r
+void SavePanelPath(UInt32 panel, const UString &path);\r
+bool ReadPanelPath(UInt32 panel, UString &path);\r
+\r
+struct CListMode\r
+{\r
+  UInt32 Panels[2];\r
+  void Init() { Panels[0] = Panels[1] = 3; }\r
+  CListMode() { Init(); }\r
+};\r
+\r
+void SaveListMode(const CListMode &listMode);\r
+void ReadListMode(CListMode &listMode);\r
+\r
+void SaveFolderHistory(const UStringVector &folders);\r
+void ReadFolderHistory(UStringVector &folders);\r
+\r
+void SaveFastFolders(const UStringVector &folders);\r
+void ReadFastFolders(UStringVector &folders);\r
+\r
+void SaveCopyHistory(const UStringVector &folders);\r
+void ReadCopyHistory(UStringVector &folders);\r
+\r
+void AddUniqueStringToHeadOfList(UStringVector &list, const UString &s);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/FileManager/makefile b/CPP/7zip/UI/FileManager/makefile
new file mode 100755 (executable)
index 0000000..45e08a0
--- /dev/null
@@ -0,0 +1,223 @@
+PROG = 7zFM.exe\r
+CFLAGS = $(CFLAGS) -I ../../../ \\r
+  -DLANG \\r
+  -DNEW_FOLDER_INTERFACE \\r
+  -DEXTERNAL_CODECS \\r
+\r
+!IFDEF UNDER_CE\r
+LIBS = $(LIBS) ceshell.lib Commctrl.lib\r
+!ELSE\r
+LIBS = $(LIBS) comctl32.lib htmlhelp.lib comdlg32.lib Mpr.lib Gdi32.lib\r
+CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -DSUPPORT_DEVICE_FILE\r
+!ENDIF\r
+\r
+FM_OBJS = \\r
+  $O\App.obj \\r
+  $O\BrowseDialog.obj \\r
+  $O\ClassDefs.obj \\r
+  $O\EnumFormatEtc.obj \\r
+  $O\ExtractCallback.obj \\r
+  $O\FileFolderPluginOpen.obj \\r
+  $O\FilePlugins.obj \\r
+  $O\FM.obj \\r
+  $O\FoldersPage.obj \\r
+  $O\FormatUtils.obj \\r
+  $O\FSFolder.obj \\r
+  $O\FSFolderCopy.obj \\r
+  $O\HelpUtils.obj \\r
+  $O\LangUtils.obj \\r
+  $O\MenuPage.obj \\r
+  $O\MyLoadMenu.obj \\r
+  $O\OpenCallback.obj \\r
+  $O\OptionsDialog.obj \\r
+  $O\Panel.obj \\r
+  $O\PanelCopy.obj \\r
+  $O\PanelCrc.obj \\r
+  $O\PanelDrag.obj \\r
+  $O\PanelFolderChange.obj \\r
+  $O\PanelItemOpen.obj \\r
+  $O\PanelItems.obj \\r
+  $O\PanelKey.obj \\r
+  $O\PanelListNotify.obj \\r
+  $O\PanelMenu.obj \\r
+  $O\PanelOperations.obj \\r
+  $O\PanelSelect.obj \\r
+  $O\PanelSort.obj \\r
+  $O\PanelSplitFile.obj \\r
+  $O\ProgramLocation.obj \\r
+  $O\PropertyName.obj \\r
+  $O\RegistryAssociations.obj \\r
+  $O\RegistryPlugins.obj \\r
+  $O\RegistryUtils.obj \\r
+  $O\RootFolder.obj \\r
+  $O\SplitUtils.obj \\r
+  $O\StringUtils.obj \\r
+  $O\SysIconUtils.obj \\r
+  $O\TextPairs.obj \\r
+  $O\UpdateCallback100.obj \\r
+  $O\ViewSettings.obj \\r
+  $O\AboutDialog.obj \\r
+  $O\ComboDialog.obj \\r
+  $O\CopyDialog.obj \\r
+  $O\EditPage.obj \\r
+  $O\LangPage.obj \\r
+  $O\ListViewDialog.obj \\r
+  $O\MessagesDialog.obj \\r
+  $O\OverwriteDialog.obj \\r
+  $O\PasswordDialog.obj \\r
+  $O\ProgressDialog2.obj \\r
+  $O\SettingsPage.obj \\r
+  $O\SplitDialog.obj \\r
+  $O\SystemPage.obj \\r
+\r
+COMMON_OBJS = \\r
+  $O\CRC.obj \\r
+  $O\IntToString.obj \\r
+  $O\Lang.obj \\r
+  $O\MyString.obj \\r
+  $O\MyVector.obj \\r
+  $O\NewHandler.obj \\r
+  $O\Random.obj \\r
+  $O\StringConvert.obj \\r
+  $O\StringToInt.obj \\r
+  $O\TextConfig.obj \\r
+  $O\UTFConvert.obj \\r
+  $O\Wildcard.obj \\r
+\r
+WIN_OBJS = \\r
+  $O\Clipboard.obj \\r
+  $O\CommonDialog.obj \\r
+  $O\DLL.obj \\r
+  $O\Error.obj \\r
+  $O\FileDir.obj \\r
+  $O\FileFind.obj \\r
+  $O\FileIO.obj \\r
+  $O\FileName.obj \\r
+  $O\Memory.obj \\r
+  $O\MemoryLock.obj \\r
+  $O\Menu.obj \\r
+  $O\Process.obj \\r
+  $O\PropVariant.obj \\r
+  $O\PropVariantConversions.obj \\r
+  $O\Registry.obj \\r
+  $O\ResourceString.obj \\r
+  $O\Shell.obj \\r
+  $O\Synchronization.obj \\r
+  $O\Time.obj \\r
+  $O\Window.obj \\r
+\r
+!IFNDEF UNDER_CE\r
+\r
+FM_OBJS = $(FM_OBJS) \\r
+  $O\FSDrives.obj \\r
+  $O\NetFolder.obj \\r
+\r
+WIN_OBJS = $(WIN_OBJS) \\r
+  $O\FileSystem.obj \\r
+  $O\Net.obj \\r
+  $O\Security.obj \\r
+\r
+!ENDIF\r
+\r
+\r
+WIN_CTRL_OBJS = \\r
+  $O\ComboBox.obj \\r
+  $O\Dialog.obj \\r
+  $O\ListView.obj \\r
+  $O\PropertyPage.obj \\r
+  $O\Window2.obj \\r
+\r
+7ZIP_COMMON_OBJS = \\r
+  $O\FilePathAutoRename.obj \\r
+  $O\FileStreams.obj \\r
+  $O\ProgressUtils.obj \\r
+  $O\StreamObjects.obj \\r
+  $O\StreamUtils.obj \\r
+\r
+AR_COMMON_OBJS = \\r
+  $O\OutStreamWithCRC.obj \\r
+\r
+UI_COMMON_OBJS = \\r
+  $O\ArchiveExtractCallback.obj \\r
+  $O\ArchiveName.obj \\r
+  $O\ArchiveOpenCallback.obj \\r
+  $O\CompressCall.obj \\r
+  $O\DefaultName.obj \\r
+  $O\EnumDirItems.obj \\r
+  $O\ExtractingFilePath.obj \\r
+  $O\LoadCodecs.obj \\r
+  $O\OpenArchive.obj \\r
+  $O\PropIDUtils.obj \\r
+  $O\SortUtils.obj \\r
+  $O\UpdateAction.obj \\r
+  $O\UpdateCallback.obj \\r
+  $O\UpdatePair.obj \\r
+  $O\UpdateProduce.obj \\r
+  $O\WorkDir.obj \\r
+  $O\ZipRegistry.obj \\r
+\r
+EXPLORER_OBJS = \\r
+  $O\ContextMenu.obj \\r
+  $O\RegistryContextMenu.obj \\r
+\r
+AGENT_OBJS = \\r
+  $O\Agent.obj \\r
+  $O\AgentOut.obj \\r
+  $O\AgentProxy.obj \\r
+  $O\ArchiveFolder.obj \\r
+  $O\ArchiveFolderOpen.obj \\r
+  $O\ArchiveFolderOut.obj \\r
+  $O\UpdateCallbackAgent.obj \\r
+\r
+C_OBJS = \\r
+  $O\Alloc.obj \\r
+  $O\CpuArch.obj \\r
+  $O\Sha256.obj \\r
+  $O\Sort.obj \\r
+  $O\Threads.obj \\r
+\r
+!include "../../Crc.mak"\r
+\r
+OBJS = \\r
+  $O\StdAfx.obj \\r
+  $(FM_OBJS)\\r
+  $(COMMON_OBJS) \\r
+  $(WIN_OBJS) \\r
+  $(WIN_CTRL_OBJS) \\r
+  $(7ZIP_COMMON_OBJS) \\r
+  $(AR_COMMON_OBJS) \\r
+  $(UI_COMMON_OBJS) \\r
+  $(EXPLORER_OBJS) \\r
+  $(AGENT_OBJS) \\r
+  $O\CopyCoder.obj \\r
+  $(C_OBJS) \\r
+  $(ASM_OBJS) \\r
+  $O\resource.res \\r
+\r
+!include "../../../Build.mak"\r
+\r
+$(FM_OBJS): $(*B).cpp\r
+       $(COMPL)\r
+$(COMMON_OBJS): ../../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_OBJS): ../../../Windows/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp\r
+       $(COMPL)\r
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp\r
+       $(COMPL)\r
+$(UI_COMMON_OBJS): ../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(AGENT_OBJS): ../Agent/$(*B).cpp\r
+       $(COMPL)\r
+$(EXPLORER_OBJS): ../Explorer/$(*B).cpp\r
+       $(COMPL)\r
+\r
+$O\CopyCoder.obj: ../../Compress/$(*B).cpp\r
+       $(COMPL)\r
+$(C_OBJS): ../../../../C/$(*B).c\r
+       $(COMPL_O2)\r
+\r
+!include "../../Asm.mak"\r
diff --git a/CPP/7zip/UI/FileManager/resource.h b/CPP/7zip/UI/FileManager/resource.h
new file mode 100755 (executable)
index 0000000..61c6989
--- /dev/null
@@ -0,0 +1,163 @@
+#include "resourceGui.h"\r
+\r
+#define IDR_MENUBAR1                    103\r
+#define IDM_MENU                        103\r
+#define IDR_ACCELERATOR1                209\r
+#define IDM_FILE_OPEN                   210\r
+#define IDM_FILE_OPEN_INSIDE            211\r
+#define IDM_FILE_OPEN_OUTSIDE           212\r
+#define IDM_FILE_VIEW                   220\r
+#define IDM_FILE_EDIT                   221\r
+#define IDM_RENAME                      230\r
+#define IDM_COPY_TO                     231\r
+#define IDM_MOVE_TO                     232\r
+#define IDM_DELETE                      233\r
+#define IDM_FILE_SPLIT                  238\r
+#define IDM_FILE_COMBINE                239\r
+#define IDM_FILE_PROPERTIES             240\r
+#define IDM_FILE_COMMENT                241\r
+#define IDM_FILE_CRC                    242\r
+#define IDM_FILE_DIFF                   243\r
+#define IDM_CREATE_FOLDER               250\r
+#define IDM_CREATE_FILE                 251\r
+#define IDM_EDIT_CUT                    320\r
+#define IDM_EDIT_COPY                   321\r
+#define IDM_EDIT_PASTE                  322\r
+#define IDM_SELECT_ALL                  330\r
+#define IDM_DESELECT_ALL                331\r
+#define IDM_INVERT_SELECTION            332\r
+#define IDM_SELECT                      333\r
+#define IDM_DESELECT                    334\r
+#define IDM_SELECT_BY_TYPE              335\r
+#define IDM_DESELECT_BY_TYPE            336\r
+#define IDM_VIEW_LARGE_ICONS            410\r
+#define IDM_VIEW_SMALL_ICONS            411\r
+#define IDM_VIEW_LIST                   412\r
+#define IDM_VIEW_DETAILS                413\r
+#define IDM_VIEW_ARANGE_BY_NAME         420\r
+#define IDM_VIEW_ARANGE_BY_TYPE         421\r
+#define IDM_VIEW_ARANGE_BY_DATE         422\r
+#define IDM_VIEW_ARANGE_BY_SIZE         423\r
+#define IDM_VIEW_ARANGE_NO_SORT         424\r
+#define IDM_OPEN_ROOT_FOLDER            430\r
+#define IDM_OPEN_PARENT_FOLDER          431\r
+#define IDM_FOLDERS_HISTORY             432\r
+#define IDM_VIEW_REFRESH                440\r
+#define IDM_VIEW_FLAT_VIEW              449\r
+#define IDM_VIEW_TWO_PANELS             450\r
+#define IDM_VIEW_TOOLBARS               451\r
+#define IDM_VIEW_STANDARD_TOOLBAR       460\r
+#define IDM_VIEW_ARCHIVE_TOOLBAR        461\r
+#define IDM_VIEW_TOOLBARS_LARGE_BUTTONS 462\r
+#define IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT 463\r
+#define IDM_OPTIONS                     510\r
+#define IDM_BENCHMARK                   511\r
+#define IDM_HELP_CONTENTS               610\r
+#define IDM_ABOUT                       620\r
+#define IDS_BOOKMARK                    720\r
+#define IDB_ADD                         2002\r
+#define IDB_EXTRACT                     2003\r
+#define IDB_TEST                        2004\r
+#define IDB_COPY                        2010\r
+#define IDB_MOVE                        2011\r
+#define IDB_DELETE                      2012\r
+#define IDB_INFO                        2013\r
+#define IDB_ADD2                        2082\r
+#define IDB_EXTRACT2                    2083\r
+#define IDB_TEST2                       2084\r
+#define IDB_COPY2                       2090\r
+#define IDB_MOVE2                       2091\r
+#define IDB_DELETE2                     2092\r
+#define IDB_INFO2                       2093\r
+#define IDS_APP_TITLE                   2200\r
+#define IDS_COPY                        2201\r
+#define IDS_MOVE                        2202\r
+#define IDS_COPY_TO                     2203\r
+#define IDS_MOVE_TO                     2204\r
+#define IDS_COPYING                     2205\r
+#define IDS_MOVING                      2206\r
+#define IDS_CANNOT_COPY                 2207\r
+#define IDS_OPERATION_IS_NOT_SUPPORTED  2208\r
+\r
+#define IDS_CONFIRM_FILE_DELETE         2210\r
+#define IDS_CONFIRM_FOLDER_DELETE       2211\r
+#define IDS_CONFIRM_ITEMS_DELETE        2212\r
+#define IDS_WANT_TO_DELETE_FILE         2213\r
+#define IDS_WANT_TO_DELETE_FOLDER       2214\r
+#define IDS_WANT_TO_DELETE_ITEMS        2215\r
+#define IDS_DELETING                    2216\r
+#define IDS_ERROR_DELETING              2217\r
+#define IDS_ERROR_LONG_PATH_TO_RECYCLE  2218\r
+\r
+#define IDS_RENAMING                    2220\r
+#define IDS_ERROR_RENAMING              2221\r
+#define IDS_CONFIRM_FILE_COPY           2222\r
+#define IDS_WANT_TO_COPY_FILES          2223\r
+\r
+\r
+#define IDS_CREATE_FOLDER               2230\r
+#define IDS_CREATE_FOLDER_NAME          2231\r
+#define IDS_CREATE_FOLDER_DEFAULT_NAME  2232\r
+#define IDS_CREATE_FOLDER_ERROR         2233\r
+#define IDS_CREATE_FILE                 2240\r
+#define IDS_CREATE_FILE_NAME            2241\r
+#define IDS_CREATE_FOLDER_DEFAULT_FILE_NAME 2242\r
+#define IDS_CREATE_FILE_DEFAULT_NAME    2242\r
+#define IDS_CREATE_FILE_ERROR           2243\r
+#define IDS_SELECT                      2250\r
+#define IDS_DESELECT                    2251\r
+#define IDS_SELECT_MASK                 2252\r
+#define IDS_FOLDERS_HISTORY             2260\r
+#define IDS_N_SELECTED_ITEMS            2270\r
+\r
+#define IDS_TOO_MANY_ITEMS              2279\r
+#define IDS_WANT_UPDATE_MODIFIED_FILE   2280\r
+#define IDS_CANNOT_UPDATE_FILE          2281\r
+#define IDS_CANNOT_START_EDITOR         2282\r
+#define IDS_OPENNING                    2283\r
+#define IDS_VIRUS                       2284\r
+#define IDS_COMPUTER                    2300\r
+#define IDS_NETWORK                     2301\r
+#define IDS_DOCUMENTS                   2302\r
+#define IDS_ADD                         2400\r
+#define IDS_EXTRACT                     2401\r
+#define IDS_TEST                        2402\r
+#define IDS_BUTTON_COPY                 2420\r
+#define IDS_BUTTON_MOVE                 2421\r
+#define IDS_BUTTON_DELETE               2422\r
+#define IDS_BUTTON_INFO                 2423\r
+#define IDS_PROP_TOTAL_SIZE             3100\r
+#define IDS_PROP_FREE_SPACE             3101\r
+#define IDS_PROP_CLUSTER_SIZE           3102\r
+#define IDS_PROP_VOLUME_NAME            3103\r
+#define IDS_PROP_LOCAL_NAME             3200\r
+#define IDS_PROP_PROVIDER               3201\r
+#define IDS_OPTIONS                     4000\r
+#define IDS_COMMENT                     4001\r
+#define IDS_COMMENT2                    4002\r
+#define IDS_SYSTEM                      4010\r
+\r
+#define IDS_SPLITTING                   4020\r
+#define IDS_SPLIT_CONFIRM_TITLE         4021\r
+#define IDS_SPLIT_CONFIRM_MESSAGE       4022\r
+#define IDS_SPLIT_VOL_MUST_BE_SMALLER   4023\r
+\r
+#define IDS_COMBINE                     4030\r
+#define IDS_COMBINE_TO                  4031\r
+#define IDS_COMBINING                   4032\r
+#define IDS_COMBINE_SELECT_ONE_FILE     4033\r
+#define IDS_COMBINE_CANT_DETECT_SPLIT_FILE 4034\r
+#define IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART 4035\r
+\r
+#define IDS_CHECKSUM_CALCULATING        4040\r
+#define IDS_CHECKSUM_INFORMATION        4041\r
+#define IDS_CHECKSUM_CRC_DATA           4042\r
+#define IDS_CHECKSUM_CRC_DATA_NAMES     4043\r
+\r
+#define IDS_SCANNING                    4050\r
+#define IDS_PROPERTIES                  4060\r
+\r
+#define IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER  4301\r
+#define IDS_SELECT_ONE_FILE             4302\r
+#define IDS_SELECT_FILES                4303\r
+#define IDS_FILE_EXIST                  4304\r
diff --git a/CPP/7zip/UI/FileManager/resource.rc b/CPP/7zip/UI/FileManager/resource.rc
new file mode 100755 (executable)
index 0000000..71144a4
--- /dev/null
@@ -0,0 +1,248 @@
+#include "../../MyVersionInfo.rc"\r
+#include "../../GuiCommon.rc"\r
+#include "resource.h"\r
+\r
+MY_VERSION_INFO_APP("7-Zip File Manager", "7zFM")\r
+\r
+\r
+IDR_ACCELERATOR1 ACCELERATORS\r
+BEGIN\r
+  "N",     IDM_CREATE_FILE,      VIRTKEY, CONTROL, NOINVERT\r
+  VK_F1,   IDM_HELP_CONTENTS,    VIRTKEY, NOINVERT\r
+  VK_F12,  IDM_FOLDERS_HISTORY,  VIRTKEY, ALT, NOINVERT\r
+  VK_F7,   IDM_CREATE_FOLDER,    VIRTKEY, NOINVERT\r
+END\r
+\r
+\r
+IDM_MENU MENU\r
+BEGIN\r
+  POPUP "&File"\r
+  BEGIN\r
+    MENUITEM "&Open\tEnter",                IDM_FILE_OPEN\r
+    MENUITEM "Open &Inside\tCtrl+PgDn",     IDM_FILE_OPEN_INSIDE\r
+    MENUITEM "Open O&utside\tShift+Enter",  IDM_FILE_OPEN_OUTSIDE\r
+    MENUITEM "&Edit\tF4",                   IDM_FILE_EDIT\r
+    MENUITEM SEPARATOR\r
+    MENUITEM "Rena&me\tF2",                 IDM_RENAME\r
+    MENUITEM "&Copy To...\tF5",             IDM_COPY_TO\r
+    MENUITEM "&Move To...\tF6",             IDM_MOVE_TO\r
+    MENUITEM "&Delete\tDel",                IDM_DELETE\r
+    MENUITEM SEPARATOR\r
+    MENUITEM "&Split file...",              IDM_FILE_SPLIT\r
+    MENUITEM "Com&bine files...",           IDM_FILE_COMBINE\r
+    MENUITEM SEPARATOR\r
+    MENUITEM "P&roperties\tAlt+Enter",      IDM_FILE_PROPERTIES\r
+    MENUITEM "Comme&nt...\tCtrl+Z",         IDM_FILE_COMMENT\r
+    MENUITEM "Calculate checksum",          IDM_FILE_CRC\r
+    MENUITEM "Di&ff",                       IDM_FILE_DIFF\r
+    MENUITEM SEPARATOR\r
+    MENUITEM "Create Folder\tF7",           IDM_CREATE_FOLDER\r
+    MENUITEM "Create File\tCtrl+N",         IDM_CREATE_FILE\r
+    MENUITEM SEPARATOR\r
+    MENUITEM "E&xit\tAlt+F4",               IDCLOSE\r
+  END\r
+  POPUP "&Edit"\r
+  BEGIN\r
+    // MENUITEM "Cu&t\tCtrl+X",                IDM_EDIT_CUT, GRAYED\r
+    // MENUITEM "&Copy\tCtrl+C",               IDM_EDIT_COPY, GRAYED\r
+    // MENUITEM "&Paste\tCtrl+V",              IDM_EDIT_PASTE, GRAYED\r
+    // MENUITEM SEPARATOR\r
+    MENUITEM "Select &All\tShift+[Grey +]", IDM_SELECT_ALL\r
+    MENUITEM "Deselect All\tShift+[Grey -]", IDM_DESELECT_ALL\r
+    MENUITEM "&Invert Selection\tGrey *",   IDM_INVERT_SELECTION\r
+    MENUITEM "Select...\tGrey +",           IDM_SELECT\r
+    MENUITEM "Deselect...\tGrey -",         IDM_DESELECT\r
+    MENUITEM "Select by Type\tAlt+[Grey+]", IDM_SELECT_BY_TYPE\r
+    MENUITEM "Deselect by Type\tAlt+[Grey -]", IDM_DESELECT_BY_TYPE\r
+  END\r
+  POPUP "&View"\r
+  BEGIN\r
+    MENUITEM "Lar&ge Icons\tCtrl+1",        IDM_VIEW_LARGE_ICONS\r
+    MENUITEM "S&mall Icons\tCtrl+2",        IDM_VIEW_SMALL_ICONS\r
+    MENUITEM "&List\tCtrl+3",               IDM_VIEW_LIST\r
+    MENUITEM "&Details\tCtrl+4",            IDM_VIEW_DETAILS, CHECKED\r
+    MENUITEM SEPARATOR\r
+    MENUITEM "Name\tCtrl+F3",               IDM_VIEW_ARANGE_BY_NAME\r
+    MENUITEM "Type\tCtrl+F4",               IDM_VIEW_ARANGE_BY_TYPE\r
+    MENUITEM "Date\tCtrl+F5",               IDM_VIEW_ARANGE_BY_DATE\r
+    MENUITEM "Size\tCtrl+F6",               IDM_VIEW_ARANGE_BY_SIZE\r
+    MENUITEM "Unsorted\tCtrl+F7",           IDM_VIEW_ARANGE_NO_SORT\r
+    MENUITEM SEPARATOR\r
+    MENUITEM "Flat View",                   IDM_VIEW_FLAT_VIEW\r
+    MENUITEM "&2 Panels\tF9",               IDM_VIEW_TWO_PANELS\r
+    POPUP "Toolbars"\r
+    BEGIN\r
+      MENUITEM "Archive Toolbar",             IDM_VIEW_ARCHIVE_TOOLBAR\r
+      MENUITEM "Standard Toolbar",            IDM_VIEW_STANDARD_TOOLBAR\r
+      MENUITEM SEPARATOR\r
+      MENUITEM "Large Buttons",               IDM_VIEW_TOOLBARS_LARGE_BUTTONS\r
+      MENUITEM "Show Buttons Text",           IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT\r
+    END\r
+    MENUITEM "Open Root Folder\t\\",        IDM_OPEN_ROOT_FOLDER\r
+    MENUITEM "Up One Level\tBackspace",     IDM_OPEN_PARENT_FOLDER\r
+    MENUITEM "Folders History...\tAlt+F12", IDM_FOLDERS_HISTORY\r
+    MENUITEM "&Refresh\tCtrl+R",            IDM_VIEW_REFRESH\r
+  END\r
+  POPUP "F&avorites"\r
+  BEGIN\r
+    POPUP "&Add folder to Favorites as"\r
+    BEGIN\r
+        MENUITEM SEPARATOR\r
+    END\r
+    MENUITEM SEPARATOR\r
+  END\r
+  POPUP "&Tools"\r
+  BEGIN\r
+    MENUITEM "&Options...",                 IDM_OPTIONS\r
+    MENUITEM "&Benchmark",                  IDM_BENCHMARK\r
+  #ifndef UNDER_CE\r
+  END\r
+  POPUP "&Help"\r
+  BEGIN\r
+    MENUITEM "&Contents...\tF1",            IDM_HELP_CONTENTS\r
+  #endif\r
+    MENUITEM SEPARATOR\r
+  MENUITEM "&About 7-Zip...",             IDM_ABOUT\r
+  END\r
+END\r
+\r
+\r
+IDI_ICON  ICON  "../../UI/FileManager/FM.ico"\r
+\r
+#ifndef UNDER_CE\r
+1  24  MOVEABLE PURE   "../../UI/FileManager/7zFM.exe.manifest"\r
+#endif\r
+\r
+IDB_ADD        BITMAP  "../../UI/FileManager/Add.bmp"\r
+IDB_EXTRACT    BITMAP  "../../UI/FileManager/Extract.bmp"\r
+IDB_TEST       BITMAP  "../../UI/FileManager/Test.bmp"\r
+IDB_COPY       BITMAP  "../../UI/FileManager/Copy.bmp"\r
+IDB_MOVE       BITMAP  "../../UI/FileManager/Move.bmp"\r
+IDB_DELETE     BITMAP  "../../UI/FileManager/Delete.bmp"\r
+IDB_INFO       BITMAP  "../../UI/FileManager/Info.bmp"\r
+IDB_ADD2       BITMAP  "../../UI/FileManager/Add2.bmp"\r
+IDB_EXTRACT2   BITMAP  "../../UI/FileManager/Extract2.bmp"\r
+IDB_TEST2      BITMAP  "../../UI/FileManager/Test2.bmp"\r
+IDB_COPY2      BITMAP  "../../UI/FileManager/Copy2.bmp"\r
+IDB_MOVE2      BITMAP  "../../UI/FileManager/Move2.bmp"\r
+IDB_DELETE2    BITMAP  "../../UI/FileManager/Delete2.bmp"\r
+IDB_INFO2      BITMAP  "../../UI/FileManager/Info2.bmp"\r
+\r
+\r
+STRINGTABLE\r
+BEGIN\r
+  IDS_APP_TITLE           "7-Zip File Manager"\r
+  IDS_COPY                "Copy"\r
+  IDS_MOVE                "Move"\r
+  IDS_COPY_TO             "Copy to:"\r
+  IDS_MOVE_TO             "Move to:"\r
+  IDS_COPYING             "Copying..."\r
+  IDS_MOVING              "Moving..."\r
+  IDS_CANNOT_COPY         "You cannot move or copy items for such folders."\r
+  IDS_SPLITTING           "Splitting..."\r
+  IDS_SPLIT_CONFIRM_TITLE "Confirm Splitting"\r
+  IDS_SPLIT_CONFIRM_MESSAGE "Are you sure you want to split file into {0} volumes?"\r
+  IDS_SPLIT_VOL_MUST_BE_SMALLER "Volume size must be smaller than size of original file"\r
+\r
+  IDS_COMBINE             "Combine Files"\r
+  IDS_COMBINE_TO          "&Combine to:"\r
+  IDS_COMBINING           "Combining..."\r
+  IDS_COMBINE_SELECT_ONE_FILE "Select only first part of split file"\r
+  IDS_COMBINE_CANT_DETECT_SPLIT_FILE "Can not detect file as split file"\r
+  IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART "Can not find more than one part of split file"\r
+\r
+  IDS_CHECKSUM_CALCULATING "Checksum calculating..."\r
+  IDS_CHECKSUM_INFORMATION "Checksum information"\r
+  IDS_CHECKSUM_CRC_DATA     "CRC checksum for data:"\r
+  IDS_CHECKSUM_CRC_DATA_NAMES "CRC checksum for data and names:"\r
+\r
+  IDS_SCANNING "Scanning..."\r
+\r
+  IDS_PROPERTIES "Properties"\r
+\r
+  IDS_OPERATION_IS_NOT_SUPPORTED "Operation is not supported."\r
+  \r
+  IDS_CONFIRM_FILE_DELETE "Confirm File Delete"\r
+  IDS_CONFIRM_FOLDER_DELETE "Confirm Folder Delete"\r
+  IDS_CONFIRM_ITEMS_DELETE "Confirm Multiple File Delete"\r
+  IDS_WANT_TO_DELETE_FILE "Are you sure you want to delete '{0}'?"\r
+  IDS_WANT_TO_DELETE_FOLDER "Are you sure you want to delete the folder '{0}' and all its contents?"\r
+  IDS_WANT_TO_DELETE_ITEMS  "Are you sure you want to delete these {0} items?"\r
+  IDS_DELETING            "Deleting..."\r
+  IDS_ERROR_DELETING      "Error Deleting File or Folder"\r
+  IDS_ERROR_LONG_PATH_TO_RECYCLE  "The system cannot move a file with long path to the Recycle Bin"\r
+  IDS_RENAMING            "Renaming..."\r
+  IDS_ERROR_RENAMING      "Error Renaming File or Folder"\r
+  IDS_CONFIRM_FILE_COPY   "Confirm File Copy"\r
+  IDS_WANT_TO_COPY_FILES  "Are you sure you want to copy files to archive"\r
+  \r
+  IDS_CREATE_FOLDER       "Create Folder"\r
+  IDS_CREATE_FOLDER_NAME  "Folder name:"\r
+  IDS_CREATE_FOLDER_DEFAULT_NAME "New Folder"\r
+  IDS_CREATE_FOLDER_ERROR "Error Creating Folder"\r
+  IDS_CREATE_FILE         "Create File"\r
+  IDS_CREATE_FILE_NAME    "File Name:"\r
+  IDS_CREATE_FILE_DEFAULT_NAME "New File"\r
+  IDS_CREATE_FILE_ERROR   "Error Creating File"\r
+  IDS_SELECT              "Select"\r
+  IDS_DESELECT            "Deselect"\r
+  IDS_SELECT_MASK         "Mask:"\r
+  IDS_FOLDERS_HISTORY     "Folders History"\r
+  IDS_N_SELECTED_ITEMS    "{0} object(s) selected"\r
+\r
+  IDS_PROP_TOTAL_SIZE     "Total Size"\r
+  IDS_PROP_FREE_SPACE     "Free Space"\r
+  IDS_PROP_CLUSTER_SIZE   "Cluster Size"\r
+  IDS_PROP_VOLUME_NAME    "Label"\r
+  IDS_PROP_LOCAL_NAME     "Local Name"\r
+  IDS_PROP_PROVIDER       "Provider"\r
+  IDS_OPTIONS             "Options"\r
+  IDS_COMMENT             "Comment"\r
+  IDS_COMMENT2            "&Comment:"\r
+  IDS_SYSTEM              "System"\r
+  IDS_TOO_MANY_ITEMS      "Too many items"\r
+  IDS_WANT_UPDATE_MODIFIED_FILE "File '{0}' was modified.\nDo you want to update it in the archive?"\r
+  IDS_CANNOT_UPDATE_FILE  "Can not update file\n'{0}'"\r
+  IDS_CANNOT_START_EDITOR "Cannot start editor."\r
+  IDS_OPENNING            "Opening..."\r
+  IDS_VIRUS               "The file looks like a virus (the file name contains long spaces in name)."\r
+  IDS_ADD                 "Add"\r
+  IDS_EXTRACT             "Extract"\r
+  IDS_TEST                "Test"\r
+  IDS_BUTTON_COPY         "Copy"\r
+  IDS_BUTTON_MOVE         "Move"\r
+  IDS_BUTTON_DELETE       "Delete"\r
+  IDS_BUTTON_INFO         "Info"\r
+  IDS_BOOKMARK            "Bookmark"\r
+  IDS_COMPUTER            "Computer"\r
+  IDS_NETWORK             "Network"\r
+  IDS_DOCUMENTS           "Documents"\r
+\r
+  IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER "The operation cannot be called from a folder that has a long path."\r
+  IDS_SELECT_ONE_FILE  "You must select one file"\r
+  IDS_SELECT_FILES  "You must select one or more files"\r
+  IDS_FILE_EXIST  "File {0} is already exist"\r
+END\r
+\r
+\r
+#include "AboutDialog.rc"\r
+#include "BrowseDialog.rc"\r
+#include "ComboDialog.rc"\r
+#include "CopyDialog.rc"\r
+#include "EditPage.rc"\r
+#include "FoldersPage.rc"\r
+#include "LangPage.rc"\r
+#include "ListViewDialog.rc"\r
+#include "MenuPage.rc"\r
+#include "MessagesDialog.rc"\r
+#include "OverwriteDialog.rc"\r
+#include "PasswordDialog.rc"\r
+#include "PluginsPage.rc"\r
+#include "ProgressDialog2.rc"\r
+#include "PropertyName.rc"\r
+#include "SettingsPage.rc"\r
+#include "SplitDialog.rc"\r
+#include "SystemPage.rc"\r
+#include "../GUI/Extract.rc"\r
+#include "../Explorer/resource2.rc"\r
+#include "resourceGui.rc"\r
diff --git a/CPP/7zip/UI/FileManager/resourceGui.h b/CPP/7zip/UI/FileManager/resourceGui.h
new file mode 100755 (executable)
index 0000000..74124ab
--- /dev/null
@@ -0,0 +1,10 @@
+#define IDI_ICON  1\r
+\r
+#define IDS_INCORRECT_VOLUME_SIZE       95\r
+\r
+#define IDS_FILES_COLON                 2274\r
+#define IDS_FOLDERS_COLON               2275\r
+#define IDS_SIZE_COLON                  2276\r
+\r
+#define IDS_PROGRESS_TESTING            4100\r
+#define IDS_MESSAGE_NO_ERRORS           4200\r
diff --git a/CPP/7zip/UI/FileManager/resourceGui.rc b/CPP/7zip/UI/FileManager/resourceGui.rc
new file mode 100755 (executable)
index 0000000..227ec35
--- /dev/null
@@ -0,0 +1,13 @@
+#include "resourceGui.h"\r
+\r
+STRINGTABLE\r
+BEGIN\r
+    IDS_INCORRECT_VOLUME_SIZE "Incorrect volume size"\r
+\r
+    IDS_FILES_COLON         "Files:"\r
+    IDS_FOLDERS_COLON       "Folders:"\r
+    IDS_SIZE_COLON          "Size:"\r
+\r
+    IDS_PROGRESS_TESTING    "Testing"\r
+    IDS_MESSAGE_NO_ERRORS   "There are no errors"\r
+END\r
diff --git a/CPP/7zip/UI/GUI/7zG.exe.manifest b/CPP/7zip/UI/GUI/7zG.exe.manifest
new file mode 100755 (executable)
index 0000000..504328c
--- /dev/null
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="7-Zip.7-Zip.7zG" type="win32"/><description>7-Zip GUI.</description><dependency> <dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/></dependentAssembly></dependency></assembly>\r
diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp
new file mode 100755 (executable)
index 0000000..8d8e7ef
--- /dev/null
@@ -0,0 +1,581 @@
+// BenchmarkDialog.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/MyException.h"\r
+\r
+#include "Windows/Error.h"\r
+#include "Windows/System.h"\r
+#include "Windows/Thread.h"\r
+\r
+#include "../FileManager/HelpUtils.h"\r
+\r
+#include "BenchmarkDialog.h"\r
+\r
+using namespace NWindows;\r
+\r
+static LPCWSTR kHelpTopic = L"fm/benchmark.htm";\r
+\r
+static const UINT_PTR kTimerID = 4;\r
+static const UINT kTimerElapse = 1000;\r
+\r
+#ifdef LANG\r
+#include "../FileManager/LangUtils.h"\r
+#endif\r
+\r
+using namespace NWindows;\r
+\r
+UString HResultToMessage(HRESULT errorCode);\r
+\r
+#ifdef LANG\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDC_BENCHMARK_DICTIONARY, 0x02000D0C },\r
+  { IDC_BENCHMARK_MEMORY, 0x03080001 },\r
+  { IDC_BENCHMARK_NUM_THREADS, 0x02000D12 },\r
+  { IDC_BENCHMARK_SPEED_LABEL, 0x03080004 },\r
+  { IDC_BENCHMARK_RATING_LABEL, 0x03080005 },\r
+  { IDC_BENCHMARK_COMPRESSING, 0x03080002 },\r
+  { IDC_BENCHMARK_DECOMPRESSING, 0x03080003 },\r
+  { IDC_BENCHMARK_CURRENT, 0x03080007 },\r
+  { IDC_BENCHMARK_RESULTING, 0x03080008 },\r
+  { IDC_BENCHMARK_CURRENT2, 0x03080007 },\r
+  { IDC_BENCHMARK_RESULTING2, 0x03080008 },\r
+  { IDC_BENCHMARK_TOTAL_RATING, 0x03080006 },\r
+  { IDC_BENCHMARK_ELAPSED, 0x02000C01 },\r
+  { IDC_BENCHMARK_SIZE, 0x02000C03 },\r
+  { IDC_BENCHMARK_PASSES, 0x03080009 },\r
+  // { IDC_BENCHMARK_ERRORS, 0x0308000A },\r
+  { IDC_BENCHMARK_USAGE_LABEL, 0x0308000B },\r
+  { IDC_BENCHMARK_RPU_LABEL, 0x0308000C },\r
+  { IDC_BENCHMARK_COMBO_NUM_THREADS, 0x02000D12},\r
\r
+  { IDC_BUTTON_STOP, 0x02000714 },\r
+  { IDC_BUTTON_RESTART, 0x02000715 },\r
+  { IDHELP, 0x02000720 },\r
+  { IDCANCEL, 0x02000710 }\r
+};\r
+#endif\r
+\r
+const LPCTSTR kProcessingString = TEXT("...");\r
+const LPCTSTR kMB = TEXT(" MB");\r
+const LPCTSTR kMIPS =  TEXT(" MIPS");\r
+const LPCTSTR kKBs = TEXT(" KB/s");\r
+\r
+#ifdef UNDER_CE\r
+static const int kMinDicLogSize = 20;\r
+#else\r
+static const int kMinDicLogSize = 21;\r
+#endif\r
+static const UInt32 kMinDicSize = (1 << kMinDicLogSize);\r
+static const UInt32 kMaxDicSize =\r
+    #ifdef _WIN64\r
+    (1 << 30);\r
+    #else\r
+    (1 << 27);\r
+    #endif\r
+\r
+bool CBenchmarkDialog::OnInit()\r
+{\r
+  #ifdef LANG\r
+  LangSetWindowText(HWND(*this), 0x03080000);\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+  #endif\r
+\r
+  Sync.Init();\r
+\r
+\r
+  UInt32 numCPUs = NSystem::GetNumberOfProcessors();\r
+  if (numCPUs < 1)\r
+    numCPUs = 1;\r
+  numCPUs = MyMin(numCPUs, (UInt32)(1 << 8));\r
+\r
+  if (Sync.NumThreads == (UInt32)-1)\r
+  {\r
+    Sync.NumThreads = numCPUs;\r
+    if (Sync.NumThreads > 1)\r
+      Sync.NumThreads &= ~1;\r
+  }\r
+  m_NumThreads.Attach(GetItem(IDC_BENCHMARK_COMBO_NUM_THREADS));\r
+  int cur = 0;\r
+  for (UInt32 num = 1; num <= numCPUs * 2;)\r
+  {\r
+    TCHAR s[40];\r
+    ConvertUInt64ToString(num, s);\r
+    int index = (int)m_NumThreads.AddString(s);\r
+    m_NumThreads.SetItemData(index, num);\r
+    if (num <= Sync.NumThreads)\r
+      cur = index;\r
+    if (num > 1)\r
+      num++;\r
+    num++;\r
+  }\r
+  m_NumThreads.SetCurSel(cur);\r
+  Sync.NumThreads = GetNumberOfThreads();\r
+\r
+  m_Dictionary.Attach(GetItem(IDC_BENCHMARK_COMBO_DICTIONARY));\r
+  cur = 0;\r
+  UInt64 ramSize = NSystem::GetRamSize();\r
+  \r
+  #ifdef UNDER_CE\r
+  const UInt32 kNormalizedCeSize = (16 << 20);\r
+  if (ramSize > kNormalizedCeSize && ramSize < (33 << 20))\r
+    ramSize = kNormalizedCeSize;\r
+  #endif\r
+\r
+  if (Sync.DictionarySize == (UInt32)-1)\r
+  {\r
+    int dicSizeLog;\r
+    for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--)\r
+      if (GetBenchMemoryUsage(Sync.NumThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize)\r
+        break;\r
+    Sync.DictionarySize = (1 << dicSizeLog);\r
+  }\r
+  if (Sync.DictionarySize < kMinDicSize)\r
+    Sync.DictionarySize = kMinDicSize;\r
+  if (Sync.DictionarySize > kMaxDicSize)\r
+    Sync.DictionarySize = kMaxDicSize;\r
+\r
+  for (int i = kMinDicLogSize; i <= 30; i++)\r
+    for (int j = 0; j < 2; j++)\r
+    {\r
+      UInt32 dictionary = (1 << i) + (j << (i - 1));\r
+      if (dictionary > kMaxDicSize)\r
+        continue;\r
+      TCHAR s[40];\r
+      ConvertUInt64ToString((dictionary >> 20), s);\r
+      lstrcat(s, kMB);\r
+      int index = (int)m_Dictionary.AddString(s);\r
+      m_Dictionary.SetItemData(index, dictionary);\r
+      if (dictionary <= Sync.DictionarySize)\r
+        cur = index;\r
+    }\r
+  m_Dictionary.SetCurSel(cur);\r
+\r
+  OnChangeSettings();\r
+\r
+  Sync._startEvent.Set();\r
+  _timer = SetTimer(kTimerID, kTimerElapse);\r
+\r
+  NormalizePosition();\r
+  return CModalDialog::OnInit();\r
+}\r
+\r
+UInt32 CBenchmarkDialog::GetNumberOfThreads()\r
+{\r
+  return (UInt32)m_NumThreads.GetItemData(m_NumThreads.GetCurSel());\r
+}\r
+\r
+UInt32 CBenchmarkDialog::OnChangeDictionary()\r
+{\r
+  UInt32 dictionary = (UInt32)m_Dictionary.GetItemData(m_Dictionary.GetCurSel());\r
+  UInt64 memUsage = GetBenchMemoryUsage(GetNumberOfThreads(), dictionary);\r
+  memUsage = (memUsage + (1 << 20) - 1) >> 20;\r
+  TCHAR s[40];\r
+  ConvertUInt64ToString(memUsage, s);\r
+  lstrcat(s, kMB);\r
+  SetItemText(IDC_BENCHMARK_MEMORY_VALUE, s);\r
+  return dictionary;\r
+}\r
+\r
+static const UInt32 g_IDs[] =\r
+{\r
+  IDC_BENCHMARK_COMPRESSING_USAGE,\r
+  IDC_BENCHMARK_COMPRESSING_USAGE2,\r
+  IDC_BENCHMARK_COMPRESSING_SPEED,\r
+  IDC_BENCHMARK_COMPRESSING_SPEED2,\r
+  IDC_BENCHMARK_COMPRESSING_RATING,\r
+  IDC_BENCHMARK_COMPRESSING_RATING2,\r
+  IDC_BENCHMARK_COMPRESSING_RPU,\r
+  IDC_BENCHMARK_COMPRESSING_RPU2,\r
+  \r
+  IDC_BENCHMARK_DECOMPRESSING_SPEED,\r
+  IDC_BENCHMARK_DECOMPRESSING_SPEED2,\r
+  IDC_BENCHMARK_DECOMPRESSING_RATING,\r
+  IDC_BENCHMARK_DECOMPRESSING_RATING2,\r
+  IDC_BENCHMARK_DECOMPRESSING_USAGE,\r
+  IDC_BENCHMARK_DECOMPRESSING_USAGE2,\r
+  IDC_BENCHMARK_DECOMPRESSING_RPU,\r
+  IDC_BENCHMARK_DECOMPRESSING_RPU2,\r
+  \r
+  IDC_BENCHMARK_TOTAL_USAGE_VALUE,\r
+  IDC_BENCHMARK_TOTAL_RATING_VALUE,\r
+  IDC_BENCHMARK_TOTAL_RPU_VALUE\r
+};\r
+  \r
+void CBenchmarkDialog::OnChangeSettings()\r
+{\r
+  EnableItem(IDC_BUTTON_STOP, true);\r
+  UInt32 dictionary = OnChangeDictionary();\r
+  TCHAR s[40] = { TEXT('/'), TEXT(' '), 0 };\r
+  ConvertUInt64ToString(NSystem::GetNumberOfProcessors(), s + 2);\r
+  SetItemText(IDC_BENCHMARK_HARDWARE_THREADS, s);\r
+  for (int i = 0; i < sizeof(g_IDs) / sizeof(g_IDs[0]); i++)\r
+    SetItemText(g_IDs[i], kProcessingString);\r
+  _startTime = GetTickCount();\r
+  PrintTime();\r
+  NWindows::NSynchronization::CCriticalSectionLock lock(Sync.CS);\r
+  Sync.Init();\r
+  Sync.DictionarySize = dictionary;\r
+  Sync.Changed = true;\r
+  Sync.NumThreads = GetNumberOfThreads();\r
+}\r
+\r
+void CBenchmarkDialog::OnRestartButton()\r
+{\r
+  OnChangeSettings();\r
+}\r
+\r
+void CBenchmarkDialog::OnStopButton()\r
+{\r
+  EnableItem(IDC_BUTTON_STOP, false);\r
+  Sync.Pause();\r
+}\r
+\r
+void CBenchmarkDialog::OnHelp()\r
+{\r
+  ShowHelpWindow(NULL, kHelpTopic);\r
+}\r
+\r
+void CBenchmarkDialog::OnCancel()\r
+{\r
+  Sync.Stop();\r
+  KillTimer(_timer);\r
+  CModalDialog::OnCancel();\r
+}\r
+\r
+static void GetTimeString(UInt64 timeValue, TCHAR *s)\r
+{\r
+  wsprintf(s, TEXT("%02d:%02d:%02d"),\r
+      UInt32(timeValue / 3600),\r
+      UInt32((timeValue / 60) % 60),\r
+      UInt32(timeValue % 60));\r
+}\r
+\r
+void CBenchmarkDialog::PrintTime()\r
+{\r
+  UInt32 curTime = ::GetTickCount();\r
+  UInt32 elapsedTime = (curTime - _startTime);\r
+  UInt32 elapsedSec = elapsedTime / 1000;\r
+  if (elapsedSec != 0 && Sync.WasPaused())\r
+    return;\r
+  TCHAR s[40];\r
+  GetTimeString(elapsedSec, s);\r
+  SetItemText(IDC_BENCHMARK_ELAPSED_VALUE, s);\r
+}\r
+\r
+void CBenchmarkDialog::PrintRating(UInt64 rating, UINT controlID)\r
+{\r
+  TCHAR s[40];\r
+  ConvertUInt64ToString(rating / 1000000, s);\r
+  lstrcat(s, kMIPS);\r
+  SetItemText(controlID, s);\r
+}\r
+\r
+void CBenchmarkDialog::PrintUsage(UInt64 usage, UINT controlID)\r
+{\r
+  TCHAR s[40];\r
+  ConvertUInt64ToString((usage + 5000) / 10000, s);\r
+  lstrcat(s, TEXT("%"));\r
+  SetItemText(controlID, s);\r
+}\r
+\r
+void CBenchmarkDialog::PrintResults(\r
+    UInt32 dictionarySize,\r
+    const CBenchInfo2 &info,\r
+    UINT usageID, UINT speedID, UINT rpuID, UINT ratingID,\r
+    bool decompressMode)\r
+{\r
+  if (info.GlobalTime == 0)\r
+    return;\r
+\r
+  UInt64 size = info.UnpackSize;\r
+  TCHAR s[40];\r
+  {\r
+    UInt64 speed = size * info.GlobalFreq / info.GlobalTime;\r
+    ConvertUInt64ToString(speed / 1024, s);\r
+    lstrcat(s, kKBs);\r
+    SetItemText(speedID, s);\r
+  }\r
+  UInt64 rating;\r
+  if (decompressMode)\r
+    rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, size, info.PackSize, 1);\r
+  else\r
+    rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, size * info.NumIterations);\r
+\r
+  PrintRating(rating, ratingID);\r
+  PrintRating(GetRatingPerUsage(info, rating), rpuID);\r
+  PrintUsage(GetUsage(info), usageID);\r
+}\r
+\r
+bool CBenchmarkDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */)\r
+{\r
+  PrintTime();\r
+  NWindows::NSynchronization::CCriticalSectionLock lock(Sync.CS);\r
+\r
+  TCHAR s[40];\r
+  ConvertUInt64ToString((Sync.ProcessedSize >> 20), s);\r
+  lstrcat(s, kMB);\r
+  SetItemText(IDC_BENCHMARK_SIZE_VALUE, s);\r
+\r
+  ConvertUInt64ToString(Sync.NumPasses, s);\r
+  SetItemText(IDC_BENCHMARK_PASSES_VALUE, s);\r
+\r
+  /*\r
+  ConvertUInt64ToString(Sync.NumErrors, s);\r
+  SetItemText(IDC_BENCHMARK_ERRORS_VALUE, s);\r
+  */\r
+\r
+  {\r
+    UInt32 dicSizeTemp = (UInt32)MyMax(Sync.ProcessedSize, UInt64(1) << 20);\r
+    dicSizeTemp = MyMin(dicSizeTemp, Sync.DictionarySize),\r
+    PrintResults(dicSizeTemp,\r
+      Sync.CompressingInfoTemp,\r
+      IDC_BENCHMARK_COMPRESSING_USAGE,\r
+      IDC_BENCHMARK_COMPRESSING_SPEED,\r
+      IDC_BENCHMARK_COMPRESSING_RPU,\r
+      IDC_BENCHMARK_COMPRESSING_RATING);\r
+  }\r
+\r
+  {\r
+    PrintResults(\r
+      Sync.DictionarySize,\r
+      Sync.CompressingInfo,\r
+      IDC_BENCHMARK_COMPRESSING_USAGE2,\r
+      IDC_BENCHMARK_COMPRESSING_SPEED2,\r
+      IDC_BENCHMARK_COMPRESSING_RPU2,\r
+      IDC_BENCHMARK_COMPRESSING_RATING2);\r
+  }\r
+\r
+  {\r
+    PrintResults(\r
+      Sync.DictionarySize,\r
+      Sync.DecompressingInfoTemp,\r
+      IDC_BENCHMARK_DECOMPRESSING_USAGE,\r
+      IDC_BENCHMARK_DECOMPRESSING_SPEED,\r
+      IDC_BENCHMARK_DECOMPRESSING_RPU,\r
+      IDC_BENCHMARK_DECOMPRESSING_RATING,\r
+      true);\r
+  }\r
+  {\r
+    PrintResults(\r
+      Sync.DictionarySize,\r
+      Sync.DecompressingInfo,\r
+      IDC_BENCHMARK_DECOMPRESSING_USAGE2,\r
+      IDC_BENCHMARK_DECOMPRESSING_SPEED2,\r
+      IDC_BENCHMARK_DECOMPRESSING_RPU2,\r
+      IDC_BENCHMARK_DECOMPRESSING_RATING2,\r
+      true);\r
+    if (Sync.DecompressingInfo.GlobalTime > 0 &&\r
+        Sync.CompressingInfo.GlobalTime > 0)\r
+    {\r
+      UInt64 comprRating = GetCompressRating(Sync.DictionarySize,\r
+          Sync.CompressingInfo.GlobalTime, Sync.CompressingInfo.GlobalFreq, Sync.CompressingInfo.UnpackSize);\r
+      UInt64 decomprRating = GetDecompressRating(Sync.DecompressingInfo.GlobalTime,\r
+          Sync.DecompressingInfo.GlobalFreq, Sync.DecompressingInfo.UnpackSize,\r
+          Sync.DecompressingInfo.PackSize, 1);\r
+      PrintRating((comprRating + decomprRating) / 2, IDC_BENCHMARK_TOTAL_RATING_VALUE);\r
+      PrintRating((\r
+          GetRatingPerUsage(Sync.CompressingInfo, comprRating) +\r
+          GetRatingPerUsage(Sync.DecompressingInfo, decomprRating)) / 2, IDC_BENCHMARK_TOTAL_RPU_VALUE);\r
+      PrintUsage((GetUsage(Sync.CompressingInfo) + GetUsage(Sync.DecompressingInfo)) / 2, IDC_BENCHMARK_TOTAL_USAGE_VALUE);\r
+    }\r
+  }\r
+  return true;\r
+}\r
+\r
+bool CBenchmarkDialog::OnCommand(int code, int itemID, LPARAM lParam)\r
+{\r
+  if (code == CBN_SELCHANGE &&\r
+      (itemID == IDC_BENCHMARK_COMBO_DICTIONARY ||\r
+       itemID == IDC_BENCHMARK_COMBO_NUM_THREADS))\r
+  {\r
+    OnChangeSettings();\r
+    return true;\r
+  }\r
+  return CModalDialog::OnCommand(code, itemID, lParam);\r
+}\r
+\r
+bool CBenchmarkDialog::OnButtonClicked(int buttonID, HWND buttonHWND)\r
+{\r
+  switch(buttonID)\r
+  {\r
+    case IDC_BUTTON_RESTART:\r
+      OnRestartButton();\r
+      return true;\r
+    case IDC_BUTTON_STOP:\r
+      OnStopButton();\r
+      return true;\r
+  }\r
+  return CModalDialog::OnButtonClicked(buttonID, buttonHWND);\r
+}\r
+\r
+struct CThreadBenchmark\r
+{\r
+  CBenchmarkDialog *BenchmarkDialog;\r
+  UInt64 _startTime;\r
+  DECL_EXTERNAL_CODECS_VARS\r
+  // UInt32 dictionarySize;\r
+  // UInt32 numThreads;\r
+\r
+  HRESULT Process();\r
+  HRESULT Result;\r
+  static THREAD_FUNC_DECL MyThreadFunction(void *param)\r
+  {\r
+    ((CThreadBenchmark *)param)->Result = ((CThreadBenchmark *)param)->Process();\r
+    return 0;\r
+  }\r
+};\r
+\r
+struct CBenchCallback: public IBenchCallback\r
+{\r
+  UInt32 dictionarySize;\r
+  CProgressSyncInfo *Sync;\r
+  HRESULT SetEncodeResult(const CBenchInfo &info, bool final);\r
+  HRESULT SetDecodeResult(const CBenchInfo &info, bool final);\r
+};\r
+\r
+HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final)\r
+{\r
+  NSynchronization::CCriticalSectionLock lock(Sync->CS);\r
+  if (Sync->Changed || Sync->Paused || Sync->Stopped)\r
+    return E_ABORT;\r
+  Sync->ProcessedSize = info.UnpackSize;\r
+  if (final && Sync->CompressingInfo.GlobalTime == 0)\r
+  {\r
+    (CBenchInfo&)Sync->CompressingInfo = info;\r
+    if (Sync->CompressingInfo.GlobalTime == 0)\r
+      Sync->CompressingInfo.GlobalTime = 1;\r
+  }\r
+  else\r
+    (CBenchInfo&)Sync->CompressingInfoTemp = info;\r
+\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final)\r
+{\r
+  NSynchronization::CCriticalSectionLock lock(Sync->CS);\r
+  if (Sync->Changed || Sync->Paused || Sync->Stopped)\r
+    return E_ABORT;\r
+  CBenchInfo info2 = info;\r
+  if (info2.NumIterations == 0)\r
+    info2.NumIterations = 1;\r
+\r
+  info2.UnpackSize *= info2.NumIterations;\r
+  info2.PackSize *= info2.NumIterations;\r
+  info2.NumIterations = 1;\r
+\r
+  if (final && Sync->DecompressingInfo.GlobalTime == 0)\r
+  {\r
+    (CBenchInfo&)Sync->DecompressingInfo = info2;\r
+    if (Sync->DecompressingInfo.GlobalTime == 0)\r
+      Sync->DecompressingInfo.GlobalTime = 1;\r
+  }\r
+  else\r
+    (CBenchInfo&)Sync->DecompressingInfoTemp = info2;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CThreadBenchmark::Process()\r
+{\r
+  CProgressSyncInfo &sync = BenchmarkDialog->Sync;\r
+  sync.WaitCreating();\r
+  try\r
+  {\r
+    for (;;)\r
+    {\r
+      if (sync.WasStopped())\r
+        return 0;\r
+      if (sync.WasPaused())\r
+      {\r
+        Sleep(200);\r
+        continue;\r
+      }\r
+      UInt32 dictionarySize;\r
+      UInt32 numThreads;\r
+      {\r
+        NSynchronization::CCriticalSectionLock lock(sync.CS);\r
+        if (sync.Stopped || sync.Paused)\r
+          continue;\r
+        if (sync.Changed)\r
+          sync.Init();\r
+        dictionarySize = sync.DictionarySize;\r
+        numThreads = sync.NumThreads;\r
+      }\r
+      \r
+      CBenchCallback callback;\r
+      callback.dictionarySize = dictionarySize;\r
+      callback.Sync = &sync;\r
+      HRESULT result;\r
+      try\r
+      {\r
+        result = LzmaBench(\r
+          EXTERNAL_CODECS_VARS\r
+          numThreads, dictionarySize, &callback);\r
+      }\r
+      catch(...)\r
+      {\r
+        result = E_FAIL;\r
+      }\r
+\r
+      if (result != S_OK)\r
+      {\r
+        if (result != E_ABORT)\r
+        {\r
+          // sync.NumErrors++;\r
+          {\r
+            NSynchronization::CCriticalSectionLock lock(sync.CS);\r
+            sync.Pause();\r
+          }\r
+          UString message;\r
+          if (result == S_FALSE)\r
+            message = L"Decoding error";\r
+          else if (result == CLASS_E_CLASSNOTAVAILABLE)\r
+            message = L"Can't find 7z.dll";\r
+          else\r
+            message = HResultToMessage(result);\r
+          BenchmarkDialog->MessageBoxError(message);\r
+        }\r
+      }\r
+      else\r
+      {\r
+        NSynchronization::CCriticalSectionLock lock(sync.CS);\r
+        sync.NumPasses++;\r
+      }\r
+    }\r
+    // return S_OK;\r
+  }\r
+  catch(CSystemException &e)\r
+  {\r
+    BenchmarkDialog->MessageBoxError(HResultToMessage(e.ErrorCode));\r
+    return E_FAIL;\r
+  }\r
+  catch(...)\r
+  {\r
+    BenchmarkDialog->MessageBoxError(HResultToMessage(E_FAIL));\r
+    return E_FAIL;\r
+  }\r
+}\r
+\r
+HRESULT Benchmark(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    UInt32 numThreads, UInt32 dictionarySize, HWND hwndParent)\r
+{\r
+  CThreadBenchmark benchmarker;\r
+  #ifdef EXTERNAL_CODECS\r
+  benchmarker._codecsInfo = codecsInfo;\r
+  benchmarker._externalCodecs = *externalCodecs;\r
+  #endif\r
+\r
+  CBenchmarkDialog benchmarkDialog;\r
+  benchmarkDialog.Sync.DictionarySize = dictionarySize;\r
+  benchmarkDialog.Sync.NumThreads = numThreads;\r
+\r
+  benchmarker.BenchmarkDialog = &benchmarkDialog;\r
+  NWindows::CThread thread;\r
+  RINOK(thread.Create(CThreadBenchmark::MyThreadFunction, &benchmarker));\r
+  benchmarkDialog.Create(hwndParent);\r
+  return thread.Wait();\r
+}\r
diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.h b/CPP/7zip/UI/GUI/BenchmarkDialog.h
new file mode 100755 (executable)
index 0000000..6b0d4d2
--- /dev/null
@@ -0,0 +1,135 @@
+// BenchmarkDialog.h\r
+\r
+#ifndef __BENCHMARK_DIALOG_H\r
+#define __BENCHMARK_DIALOG_H\r
+\r
+#include "Windows/Synchronization.h"\r
+#include "Windows/Control/ComboBox.h"\r
+\r
+#include "../Common/Bench.h"\r
+\r
+#include "../FileManager/DialogSize.h"\r
+\r
+#include "BenchmarkDialogRes.h"\r
+\r
+struct CBenchInfo2 : public CBenchInfo\r
+{\r
+  void Init()  { GlobalTime = UserTime = 0; }\r
+};\r
+\r
+class CProgressSyncInfo\r
+{\r
+public:\r
+  bool Stopped;\r
+  bool Paused;\r
+  bool Changed;\r
+  UInt32 DictionarySize;\r
+  UInt32 NumThreads;\r
+  UInt64 NumPasses;\r
+  // UInt64 NumErrors;\r
+  NWindows::NSynchronization::CManualResetEvent _startEvent;\r
+  NWindows::NSynchronization::CCriticalSection CS;\r
+\r
+  CBenchInfo2 CompressingInfoTemp;\r
+  CBenchInfo2 CompressingInfo;\r
+  UInt64 ProcessedSize;\r
+\r
+  CBenchInfo2 DecompressingInfoTemp;\r
+  CBenchInfo2 DecompressingInfo;\r
+\r
+  CProgressSyncInfo()\r
+  {\r
+    if (_startEvent.Create() != S_OK)\r
+      throw 3986437;\r
+  }\r
+  void Init()\r
+  {\r
+    Changed = false;\r
+    Stopped = false;\r
+    Paused = false;\r
+    CompressingInfoTemp.Init();\r
+    CompressingInfo.Init();\r
+    ProcessedSize = 0;\r
+    \r
+    DecompressingInfoTemp.Init();\r
+    DecompressingInfo.Init();\r
+\r
+    NumPasses = 0;\r
+    // NumErrors = 0;\r
+  }\r
+  void Stop()\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(CS);\r
+    Stopped = true;\r
+  }\r
+  bool WasStopped()\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(CS);\r
+    return Stopped;\r
+  }\r
+  void Pause()\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(CS);\r
+    Paused = true;\r
+  }\r
+  void Start()\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(CS);\r
+    Paused = false;\r
+  }\r
+  bool WasPaused()\r
+  {\r
+    NWindows::NSynchronization::CCriticalSectionLock lock(CS);\r
+    return Paused;\r
+  }\r
+  void WaitCreating() { _startEvent.Lock(); }\r
+};\r
+\r
+class CBenchmarkDialog:\r
+  public NWindows::NControl::CModalDialog\r
+{\r
+  NWindows::NControl::CComboBox m_Dictionary;\r
+  NWindows::NControl::CComboBox m_NumThreads;\r
+  UINT_PTR _timer;\r
+  UINT32 _startTime;\r
+\r
+  bool OnTimer(WPARAM timerID, LPARAM callback);\r
+  virtual bool OnInit();\r
+  void OnRestartButton();\r
+  void OnStopButton();\r
+  void OnHelp();\r
+  virtual void OnCancel();\r
+  bool OnButtonClicked(int buttonID, HWND buttonHWND);\r
+  bool OnCommand(int code, int itemID, LPARAM lParam);\r
+\r
+  void PrintTime();\r
+  void PrintRating(UInt64 rating, UINT controlID);\r
+  void PrintUsage(UInt64 usage, UINT controlID);\r
+  void PrintResults(\r
+      UINT32 dictionarySize,\r
+      const CBenchInfo2 &info, UINT usageID, UINT speedID, UINT rpuID, UINT ratingID,\r
+      bool decompressMode = false);\r
+\r
+  UInt32 GetNumberOfThreads();\r
+  UInt32 OnChangeDictionary();\r
+  void OnChangeSettings();\r
+public:\r
+  CProgressSyncInfo Sync;\r
+\r
+  CBenchmarkDialog(): _timer(0) {}\r
+  INT_PTR Create(HWND wndParent = 0)\r
+  {\r
+    BIG_DIALOG_SIZE(332, 228);\r
+    return CModalDialog::Create(SIZED_DIALOG(IDD_DIALOG_BENCHMARK), wndParent);\r
+  }\r
+  void MessageBoxError(LPCWSTR message)\r
+  {\r
+    MessageBoxW(*this, message, L"7-Zip", MB_ICONERROR);\r
+  }\r
+};\r
+\r
+HRESULT Benchmark(\r
+    DECL_EXTERNAL_CODECS_LOC_VARS\r
+    UInt32 numThreads, UInt32 dictionarySize, HWND hwndParent = NULL);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.rc b/CPP/7zip/UI/GUI/BenchmarkDialog.rc
new file mode 100755 (executable)
index 0000000..da30fc3
--- /dev/null
@@ -0,0 +1,227 @@
+#include "BenchmarkDialogRes.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#define xc 332\r
+#define yc 228\r
+\r
+#undef g0xs\r
+#undef g1x\r
+#undef g1xs\r
+#undef g2xs\r
+#undef g3x\r
+#undef g3xs\r
+#undef g4x\r
+\r
+#define gs 160\r
+#define gSpace 24\r
+\r
+#define g0xs 90\r
+#define g1xs 44\r
+#define g1x  (m + g0xs)\r
+#define gc2x  (g1x + g1xs + m)\r
+#define gc2xs 80\r
+\r
+#define g4x (m + m)\r
+\r
+#define sRating 60\r
+#define sSpeed 60\r
+#define sUsage 60\r
+#define sRpu 60\r
+\r
+#define xRating (xs - m - m - sRating)\r
+#define xRpu (xRating - sRpu)\r
+#define xUsage (xRpu - sUsage)\r
+#define xSpeed (xUsage - sSpeed)\r
+\r
+#define sLabel (xUsage - g4x)\r
+#define sTotalRating (sUsage + sRpu + sRating + m + m)\r
+#define xTotalRating (xs - m - sTotalRating)\r
+\r
+#define g2xs 58\r
+#define g3xs 36\r
+#define g3x (m + g2xs)\r
+\r
+\r
+IDD_DIALOG_BENCHMARK DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE | WS_MINIMIZEBOX\r
+CAPTION "Benchmark"\r
+MY_FONT\r
+BEGIN\r
+  PUSHBUTTON  "&Restart", IDC_BUTTON_RESTART, bx1, m, bxs, bys\r
+  PUSHBUTTON  "&Stop",    IDC_BUTTON_STOP,    bx1, m + bys + 6, bxs, bys\r
+  \r
+  PUSHBUTTON  "&Help",    IDHELP,             bx2, by, bxs, bys\r
+  PUSHBUTTON  "Cancel",   IDCANCEL,           bx1, by, bxs, bys\r
+  \r
+  LTEXT     "&Dictionary size:", IDC_BENCHMARK_DICTIONARY, m, m + 1, g0xs, 8\r
+  COMBOBOX  IDC_BENCHMARK_COMBO_DICTIONARY, g1x, m, g1xs, 140, MY_COMBO\r
+  LTEXT     "Memory usage:", IDC_BENCHMARK_MEMORY, gc2x, m + 1, gc2xs, 8\r
+  LTEXT     "0 MB", IDC_BENCHMARK_MEMORY_VALUE, gc2x + gc2xs, m + 1, 40, 8\r
+\r
+  LTEXT     "&Number of CPU threads:", IDC_BENCHMARK_NUM_THREADS, m, 28, g0xs, 8\r
+  COMBOBOX  IDC_BENCHMARK_COMBO_NUM_THREADS, g1x, 27, g1xs, 140, MY_COMBO\r
+  LTEXT     "1", IDC_BENCHMARK_HARDWARE_THREADS, gc2x, 28, 40, 8\r
+\r
+  RTEXT     "CPU Usage", IDC_BENCHMARK_USAGE_LABEL,           xUsage,  54, sUsage,  8\r
+  RTEXT     "Speed", IDC_BENCHMARK_SPEED_LABEL,               xSpeed,  54, sSpeed,  8\r
+  RTEXT     "Rating / Usage", IDC_BENCHMARK_RPU_LABEL,          xRpu,  54, sRpu,    8\r
+  RTEXT     "Rating", IDC_BENCHMARK_RATING_LABEL,            xRating,  54, sRating, 8\r
+  \r
+  GROUPBOX  "Compressing", IDC_BENCHMARK_COMPRESSING,              m,  64, xc, 40\r
\r
+  LTEXT     "Current", IDC_BENCHMARK_CURRENT,                    g4x,  76, sLabel,  8\r
+  RTEXT     "100%", IDC_BENCHMARK_COMPRESSING_USAGE,          xUsage,  76, sUsage,  8\r
+  RTEXT     "100 KB/s", IDC_BENCHMARK_COMPRESSING_SPEED,      xSpeed,  76, sSpeed,  8\r
+  RTEXT     "0", IDC_BENCHMARK_COMPRESSING_RPU,                 xRpu,  76, sRpu,    8\r
+  RTEXT     "0", IDC_BENCHMARK_COMPRESSING_RATING,           xRating,  76, sRating, 8\r
+  \r
+  LTEXT     "Resulting", IDC_BENCHMARK_RESULTING,                g4x,  89, sLabel,  8\r
+  RTEXT     "100%", IDC_BENCHMARK_COMPRESSING_USAGE2,         xUsage,  89, sUsage,  8\r
+  RTEXT     "100 KB/s", IDC_BENCHMARK_COMPRESSING_SPEED2,     xSpeed,  89, sSpeed,  8\r
+  RTEXT     "0", IDC_BENCHMARK_COMPRESSING_RPU2,                xRpu,  89, sRpu,    8\r
+  RTEXT     "0", IDC_BENCHMARK_COMPRESSING_RATING2,          xRating,  89, sRating, 8\r
+  \r
+  GROUPBOX  "Decompressing", IDC_BENCHMARK_DECOMPRESSING,          m, 111, xc, 40\r
+\r
+  LTEXT     "Current", IDC_BENCHMARK_CURRENT2,                   g4x, 123,  sLabel, 8\r
+  RTEXT     "100%", IDC_BENCHMARK_DECOMPRESSING_USAGE,        xUsage, 123,  sUsage, 8\r
+  RTEXT     "100 KB/s", IDC_BENCHMARK_DECOMPRESSING_SPEED,    xSpeed, 123,  sSpeed, 8\r
+  RTEXT     "0", IDC_BENCHMARK_DECOMPRESSING_RPU,               xRpu, 123,    sRpu, 8\r
+  RTEXT     "0", IDC_BENCHMARK_DECOMPRESSING_RATING,         xRating, 123, sRating, 8\r
+  \r
+  LTEXT     "Resulting", IDC_BENCHMARK_RESULTING2,               g4x, 136,  sLabel, 8\r
+  RTEXT     "100%", IDC_BENCHMARK_DECOMPRESSING_USAGE2,       xUsage, 136,  sUsage, 8\r
+  RTEXT     "100 KB/s", IDC_BENCHMARK_DECOMPRESSING_SPEED2,   xSpeed, 136,  sSpeed, 8\r
+  RTEXT     "0", IDC_BENCHMARK_DECOMPRESSING_RPU2,              xRpu, 136,    sRpu, 8\r
+  RTEXT     "0", IDC_BENCHMARK_DECOMPRESSING_RATING2,        xRating, 136, sRating, 8\r
+  \r
+  GROUPBOX  "Total Rating", IDC_BENCHMARK_TOTAL_RATING, xTotalRating, 163, sTotalRating, 38\r
+  RTEXT     "0", IDC_BENCHMARK_TOTAL_USAGE_VALUE,             xUsage, 181,  sUsage, 8\r
+  RTEXT     "0", IDC_BENCHMARK_TOTAL_RPU_VALUE,                 xRpu, 181,    sRpu, 8\r
+  RTEXT     "0", IDC_BENCHMARK_TOTAL_RATING_VALUE,           xRating, 181, sRating, 8\r
+  \r
+  LTEXT     "Elapsed time:", IDC_BENCHMARK_ELAPSED,    m, 163, g2xs, 8\r
+  LTEXT     "Size:", IDC_BENCHMARK_SIZE,               m, 176, g2xs, 8\r
+  LTEXT     "Passes:", IDC_BENCHMARK_PASSES,           m, 189, g2xs, 8\r
+  RTEXT     "00:00:00", IDC_BENCHMARK_ELAPSED_VALUE, g3x, 163, g3xs, 8\r
+  RTEXT     "0", IDC_BENCHMARK_SIZE_VALUE,           g3x, 176, g3xs, 8\r
+  RTEXT     "0", IDC_BENCHMARK_PASSES_VALUE,         g3x, 189, g3xs, 8\r
+END\r
+\r
+#ifdef UNDER_CE\r
+\r
+#undef m\r
+#define m 4\r
+\r
+#undef xc\r
+#undef yc\r
+\r
+#define xc 154\r
+#define yc 160\r
+\r
+#undef g0xs\r
+#undef g1x\r
+#undef g1xs\r
+#undef g2xs\r
+#undef g3x\r
+#undef g3xs\r
+\r
+#undef bxs\r
+#undef bys\r
+\r
+#define bxs 60\r
+#define bys 14\r
+\r
+#undef gs\r
+#undef gSpace\r
+\r
+#define gs 160\r
+#define gSpace 24\r
+\r
+#define g0xs (xc - bxs)\r
+#define g1xs 44\r
+\r
+#undef g4x\r
+#define g4x (m)\r
+\r
+#undef xRpu\r
+#undef xUsage\r
+#undef xRating\r
+#undef xTotalRating\r
+\r
+#undef sRpu\r
+#undef sRating\r
+#undef sUsage\r
+#undef sLabel\r
+#undef sTotalRating\r
+\r
+#define sRating 40\r
+#define sUsage 24\r
+#define sRpu 40\r
+\r
+#define xRating (xs - m - sRating)\r
+#define xRpu (xRating - sRpu)\r
+#define xUsage (xRpu - sUsage)\r
+\r
+#define sLabel (xUsage - g4x)\r
+#define sTotalRating (sRpu + sRating)\r
+#define xTotalRating (xs - m - sTotalRating)\r
+\r
+#define g3xs 32\r
+#define g3x (xRpu - g3xs)\r
+#define g2xs (g3x - m)\r
+\r
+\r
+IDD_DIALOG_BENCHMARK_2 DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE | WS_MINIMIZEBOX\r
+CAPTION "Benchmark"\r
+MY_FONT\r
+BEGIN\r
+  PUSHBUTTON  "&Restart", IDC_BUTTON_RESTART, bx1, m, bxs, bys\r
+  PUSHBUTTON  "&Stop",    IDC_BUTTON_STOP,    bx1, m + bys + m, bxs, bys\r
+  PUSHBUTTON  "Cancel",   IDCANCEL,           bx1, m + bys + m + bys + m, bxs, bys\r
+  \r
+  LTEXT     "&Dictionary size:", IDC_BENCHMARK_DICTIONARY, m, m, g0xs, 8\r
+  COMBOBOX  IDC_BENCHMARK_COMBO_DICTIONARY, m, m + 11, g1xs, 140, MY_COMBO\r
+\r
+  LTEXT     "&Number of CPU threads:", IDC_BENCHMARK_NUM_THREADS, m, 31, g0xs, 8\r
+  COMBOBOX  IDC_BENCHMARK_COMBO_NUM_THREADS, m, 42, g1xs, 140, MY_COMBO\r
+\r
+  LTEXT     "0 MB", IDC_BENCHMARK_MEMORY_VALUE, m + g1xs + 8, m + 13, xc - bxs - g1xs - 8, 8\r
+  LTEXT     "1", IDC_BENCHMARK_HARDWARE_THREADS, m + g1xs + 8, 44, xc - bxs - g1xs - 8, 8\r
+  \r
+  LTEXT     "Current", IDC_BENCHMARK_CURRENT,                    g4x,  70, sLabel,  8\r
+  RTEXT     "100%", IDC_BENCHMARK_COMPRESSING_USAGE,          xUsage,  70, sUsage,  8\r
+  RTEXT     "0", IDC_BENCHMARK_COMPRESSING_RPU,                 xRpu,  70, sRpu,    8\r
+  RTEXT     "0", IDC_BENCHMARK_COMPRESSING_RATING,           xRating,  70, sRating, 8\r
+\r
+  LTEXT     "Resulting", IDC_BENCHMARK_RESULTING,                g4x,  80, sLabel,  8\r
+  RTEXT     "100%", IDC_BENCHMARK_COMPRESSING_USAGE2,         xUsage,  80, sUsage,  8\r
+  RTEXT     "0", IDC_BENCHMARK_COMPRESSING_RPU2,                xRpu,  80, sRpu,    8\r
+  RTEXT     "0", IDC_BENCHMARK_COMPRESSING_RATING2,          xRating,  80, sRating, 8\r
+\r
+  LTEXT     "Compressing", IDC_BENCHMARK_COMPRESSING,              m,  60, xc - bxs, 8\r
+  \r
+  LTEXT     "Current", IDC_BENCHMARK_CURRENT2,                   g4x, 104,  sLabel, 8\r
+  RTEXT     "100%", IDC_BENCHMARK_DECOMPRESSING_USAGE,        xUsage, 104,  sUsage, 8\r
+  RTEXT     "0", IDC_BENCHMARK_DECOMPRESSING_RPU,               xRpu, 104,  sRpu, 8\r
+  RTEXT     "0", IDC_BENCHMARK_DECOMPRESSING_RATING,         xRating, 104, sRating, 8\r
+  \r
+  LTEXT     "Resulting", IDC_BENCHMARK_RESULTING2,               g4x, 114,  sLabel, 8\r
+  RTEXT     "100%", IDC_BENCHMARK_DECOMPRESSING_USAGE2,       xUsage, 114,  sUsage, 8\r
+  RTEXT     "0", IDC_BENCHMARK_DECOMPRESSING_RPU2,              xRpu, 114,    sRpu, 8\r
+  RTEXT     "0", IDC_BENCHMARK_DECOMPRESSING_RATING2,        xRating, 114, sRating, 8\r
+  \r
+  LTEXT  "Decompressing", IDC_BENCHMARK_DECOMPRESSING,          m, 94, xc, 8\r
+\r
+  RTEXT     "0", IDC_BENCHMARK_TOTAL_RPU_VALUE,                 xRpu, 140,    sRpu, 8\r
+  RTEXT     "0", IDC_BENCHMARK_TOTAL_RATING_VALUE,           xRating, 140, sRating, 8\r
+  \r
+  LTEXT     "Elapsed time:", IDC_BENCHMARK_ELAPSED,    m, 130, g2xs, 8\r
+  LTEXT     "Size:", IDC_BENCHMARK_SIZE,               m, 140, g2xs, 8\r
+  LTEXT     "Passes:", IDC_BENCHMARK_PASSES,           m, 150, g2xs, 8\r
+\r
+  RTEXT     "00:00:00", IDC_BENCHMARK_ELAPSED_VALUE, g3x, 130, g3xs, 8\r
+  RTEXT     "0", IDC_BENCHMARK_SIZE_VALUE,           g3x, 140, g3xs, 8\r
+  RTEXT     "0", IDC_BENCHMARK_PASSES_VALUE,         g3x, 150, g3xs, 8\r
+END\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/GUI/BenchmarkDialogRes.h b/CPP/7zip/UI/GUI/BenchmarkDialogRes.h
new file mode 100755 (executable)
index 0000000..03bd6de
--- /dev/null
@@ -0,0 +1,55 @@
+#define IDD_DIALOG_BENCHMARK            550\r
+#define IDD_DIALOG_BENCHMARK_2          650\r
+#define IDC_BUTTON_STOP                 1001\r
+#define IDC_BUTTON_RESTART              1002\r
+#define IDC_BENCHMARK_DICTIONARY        1010\r
+#define IDC_BENCHMARK_COMBO_DICTIONARY  1011\r
+#define IDC_BENCHMARK_MEMORY            1012\r
+#define IDC_BENCHMARK_MEMORY_VALUE      1013\r
+#define IDC_BENCHMARK_NUM_THREADS       1014\r
+#define IDC_BENCHMARK_COMBO_NUM_THREADS 1015\r
+#define IDC_BENCHMARK_HARDWARE_THREADS  1016\r
+\r
+#define IDC_BENCHMARK_SPEED_LABEL       1020\r
+#define IDC_BENCHMARK_RATING_LABEL      1021\r
+#define IDC_BENCHMARK_COMPRESSING       1022\r
+#define IDC_BENCHMARK_DECOMPRESSING     1023\r
+#define IDC_BENCHMARK_CURRENT           1024\r
+#define IDC_BENCHMARK_RESULTING         1025\r
+#define IDC_BENCHMARK_CURRENT2          1026\r
+#define IDC_BENCHMARK_RESULTING2        1027\r
+#define IDC_BENCHMARK_USAGE_LABEL       1028\r
+#define IDC_BENCHMARK_RPU_LABEL         1029\r
+\r
+#define IDC_BENCHMARK_COMPRESSING_SPEED 1030\r
+#define IDC_BENCHMARK_COMPRESSING_SPEED2 1031\r
+#define IDC_BENCHMARK_COMPRESSING_RATING 1032\r
+#define IDC_BENCHMARK_COMPRESSING_RATING2 1033\r
+#define IDC_BENCHMARK_COMPRESSING_USAGE 1034\r
+#define IDC_BENCHMARK_COMPRESSING_USAGE2 1035\r
+#define IDC_BENCHMARK_COMPRESSING_RPU 1036\r
+#define IDC_BENCHMARK_COMPRESSING_RPU2 1037\r
+\r
+\r
+#define IDC_BENCHMARK_DECOMPRESSING_SPEED 1040\r
+#define IDC_BENCHMARK_DECOMPRESSING_SPEED2 1041\r
+#define IDC_BENCHMARK_DECOMPRESSING_RATING 1042\r
+#define IDC_BENCHMARK_DECOMPRESSING_RATING2 1043\r
+#define IDC_BENCHMARK_DECOMPRESSING_USAGE 1044\r
+#define IDC_BENCHMARK_DECOMPRESSING_USAGE2 1045\r
+#define IDC_BENCHMARK_DECOMPRESSING_RPU 1046\r
+#define IDC_BENCHMARK_DECOMPRESSING_RPU2 1047\r
+\r
+\r
+#define IDC_BENCHMARK_TOTAL_RATING      1050\r
+\r
+#define IDC_BENCHMARK_TOTAL_RATING_VALUE 1051\r
+#define IDC_BENCHMARK_TOTAL_RPU_VALUE 1052\r
+#define IDC_BENCHMARK_TOTAL_USAGE_VALUE 1053\r
+\r
+#define IDC_BENCHMARK_ELAPSED           1060\r
+#define IDC_BENCHMARK_ELAPSED_VALUE     1061\r
+#define IDC_BENCHMARK_SIZE              1062\r
+#define IDC_BENCHMARK_SIZE_VALUE        1063\r
+#define IDC_BENCHMARK_PASSES            1066\r
+#define IDC_BENCHMARK_PASSES_VALUE      1067\r
diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp
new file mode 100755 (executable)
index 0000000..9f3b065
--- /dev/null
@@ -0,0 +1,1496 @@
+// CompressDialog.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileName.h"\r
+#include "Windows/System.h"\r
+\r
+#include "../FileManager/BrowseDialog.h"\r
+#include "../FileManager/FormatUtils.h"\r
+#include "../FileManager/HelpUtils.h"\r
+#include "../FileManager/SplitUtils.h"\r
+\r
+#include "../Explorer/MyMessages.h"\r
+\r
+#include "../Common/ZipRegistry.h"\r
+\r
+#include "CompressDialog.h"\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+#ifdef LANG\r
+#include "../FileManager/LangUtils.h"\r
+#endif\r
+\r
+#include "CompressDialogRes.h"\r
+\r
+#define MY_SIZE_OF_ARRAY(x) (sizeof(x) / sizeof(x[0]))\r
+\r
+#ifdef LANG\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDC_STATIC_COMPRESS_ARCHIVE, 0x02000D01 },\r
+  { IDC_STATIC_COMPRESS_FORMAT, 0x02000D03 },\r
+  { IDC_STATIC_COMPRESS_LEVEL, 0x02000D0B },\r
+  { IDC_STATIC_COMPRESS_METHOD, 0x02000D04 },\r
+  { IDC_STATIC_COMPRESS_DICTIONARY, 0x02000D0C },\r
+  { IDC_STATIC_COMPRESS_ORDER, 0x02000D0D },\r
+  { IDC_STATIC_COMPRESS_MEMORY, 0x02000D0E },\r
+  { IDC_STATIC_COMPRESS_MEMORY_DE, 0x02000D0F },\r
+  { IDC_STATIC_COMPRESS_THREADS, 0x02000D12 },\r
+  { IDC_STATIC_COMPRESS_SOLID, 0x02000D13 },\r
+  { IDC_STATIC_COMPRESS_VOLUME, 0x02000D40 },\r
+  { IDC_STATIC_COMPRESS_PARAMETERS, 0x02000D06 },\r
+  \r
+  { IDC_STATIC_COMPRESS_UPDATE_MODE, 0x02000D02 },\r
+  { IDC_STATIC_COMPRESS_OPTIONS, 0x02000D07 },\r
+  { IDC_COMPRESS_SFX, 0x02000D08 },\r
+  { IDC_COMPRESS_SHARED, 0x02000D16 },\r
+  \r
+  { IDC_COMPRESS_ENCRYPTION, 0x02000D10 },\r
+  { IDC_STATIC_COMPRESS_PASSWORD1, 0x02000B01 },\r
+  { IDC_STATIC_COMPRESS_PASSWORD2, 0x02000B03 },\r
+  { IDC_COMPRESS_CHECK_SHOW_PASSWORD, 0x02000B02 },\r
+  { IDC_STATIC_COMPRESS_ENCRYPTION_METHOD, 0x02000D11 },\r
+  { IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, 0x02000D0A },\r
+\r
+  { IDOK, 0x02000702 },\r
+  { IDCANCEL, 0x02000710 },\r
+  { IDHELP, 0x02000720 }\r
+};\r
+#endif\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+using namespace NName;\r
+using namespace NDirectory;\r
+\r
+static const int kHistorySize = 20;\r
+\r
+static LPCWSTR kExeExt = L".exe";\r
+static LPCWSTR k7zFormat = L"7z";\r
+\r
+struct CLevelInfo\r
+{\r
+  UInt32 ResourceID;\r
+  UInt32 LangID;\r
+};\r
+\r
+enum ELevel\r
+{\r
+  kStore = 0,\r
+  kFastest = 1,\r
+  kFast = 3,\r
+  kNormal = 5,\r
+  kMaximum = 7,\r
+  kUltra = 9\r
+};\r
+\r
+static const CLevelInfo g_Levels[] =\r
+{\r
+  { IDS_METHOD_STORE, 0x02000D81 },\r
+  { IDS_METHOD_FASTEST, 0x02000D85 },\r
+  { 0, 0 },\r
+  { IDS_METHOD_FAST, 0x02000D84 },\r
+  { 0, 0 },\r
+  { IDS_METHOD_NORMAL, 0x02000D82 },\r
+  { 0, 0 },\r
+  { IDS_METHOD_MAXIMUM, 0x02000D83 },\r
+  { 0, 0 },\r
+  { IDS_METHOD_ULTRA, 0x02000D86 }\r
+};\r
+\r
+enum EMethodID\r
+{\r
+  kCopy,\r
+  kLZMA,\r
+  kLZMA2,\r
+  kPPMd,\r
+  kBZip2,\r
+  kDeflate,\r
+  kDeflate64,\r
+  kPPMdZip\r
+};\r
+\r
+static const LPCWSTR kMethodsNames[] =\r
+{\r
+  L"Copy",\r
+  L"LZMA",\r
+  L"LZMA2",\r
+  L"PPMd",\r
+  L"BZip2",\r
+  L"Deflate",\r
+  L"Deflate64",\r
+  L"PPMd"\r
+};\r
+\r
+static const EMethodID g_7zMethods[] =\r
+{\r
+  kLZMA,\r
+  kLZMA2,\r
+  kPPMd,\r
+  kBZip2\r
+};\r
+\r
+static const EMethodID g_7zSfxMethods[] =\r
+{\r
+  kCopy,\r
+  kLZMA,\r
+  kLZMA2,\r
+  kPPMd\r
+};\r
+\r
+static EMethodID g_ZipMethods[] =\r
+{\r
+  kDeflate,\r
+  kDeflate64,\r
+  kBZip2,\r
+  kLZMA,\r
+  kPPMdZip\r
+};\r
+\r
+static EMethodID g_GZipMethods[] =\r
+{\r
+  kDeflate\r
+};\r
+\r
+static EMethodID g_BZip2Methods[] =\r
+{\r
+  kBZip2\r
+};\r
+\r
+static EMethodID g_XzMethods[] =\r
+{\r
+  kLZMA2\r
+};\r
+\r
+struct CFormatInfo\r
+{\r
+  LPCWSTR Name;\r
+  UInt32 LevelsMask;\r
+  const EMethodID *MathodIDs;\r
+  int NumMethods;\r
+  bool Filter;\r
+  bool Solid;\r
+  bool MultiThread;\r
+  bool SFX;\r
+  bool Encrypt;\r
+  bool EncryptFileNames;\r
+};\r
+\r
+#define METHODS_PAIR(x) x, MY_SIZE_OF_ARRAY(x)\r
+\r
+static const CFormatInfo g_Formats[] =\r
+{\r
+  {\r
+    L"",\r
+    (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),\r
+    0, 0,\r
+    false, false, false, false, false, false\r
+  },\r
+  {\r
+    k7zFormat,\r
+    (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),\r
+    METHODS_PAIR(g_7zMethods),\r
+    true, true, true, true, true, true\r
+  },\r
+  {\r
+    L"Zip",\r
+    (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),\r
+    METHODS_PAIR(g_ZipMethods),\r
+    false, false, true, false, true, false\r
+  },\r
+  {\r
+    L"GZip",\r
+    (1 << 1) | (1 << 5) | (1 << 7) | (1 << 9),\r
+    METHODS_PAIR(g_GZipMethods),\r
+    false, false, false, false, false, false\r
+  },\r
+  {\r
+    L"BZip2",\r
+    (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),\r
+    METHODS_PAIR(g_BZip2Methods),\r
+    false, false, true, false, false, false\r
+  },\r
+  {\r
+    L"xz",\r
+    (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),\r
+    METHODS_PAIR(g_XzMethods),\r
+    false, false, true, false, false, false\r
+  },\r
+  {\r
+    L"Tar",\r
+    (1 << 0),\r
+    0, 0,\r
+    false, false, false, false, false, false\r
+  },\r
+  {\r
+    L"wim",\r
+    (1 << 0),\r
+    0, 0,\r
+    false, false, false, false, false, false\r
+  }\r
+};\r
+\r
+static bool IsMethodSupportedBySfx(int methodID)\r
+{\r
+  for (int i = 0; i < MY_SIZE_OF_ARRAY(g_7zSfxMethods); i++)\r
+    if (methodID == g_7zSfxMethods[i])\r
+      return true;\r
+  return false;\r
+}\r
+\r
+static UInt64 GetMaxRamSizeForProgram()\r
+{\r
+  UInt64 physSize = NSystem::GetRamSize();\r
+  const UInt64 kMinSysSize = (1 << 24);\r
+  if (physSize <= kMinSysSize)\r
+    physSize = 0;\r
+  else\r
+    physSize -= kMinSysSize;\r
+  const UInt64 kMinUseSize = (1 << 24);\r
+  if (physSize < kMinUseSize)\r
+    physSize = kMinUseSize;\r
+  return physSize;\r
+}\r
+\r
+bool CCompressDialog::OnInit()\r
+{\r
+  #ifdef LANG\r
+  LangSetWindowText(HWND(*this), 0x02000D00);\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, MY_SIZE_OF_ARRAY(kIDLangPairs) );\r
+  #endif\r
+  _password1Control.Attach(GetItem(IDC_COMPRESS_EDIT_PASSWORD1));\r
+  _password2Control.Attach(GetItem(IDC_COMPRESS_EDIT_PASSWORD2));\r
+  _password1Control.SetText(Info.Password);\r
+  _password2Control.SetText(Info.Password);\r
+  _encryptionMethod.Attach(GetItem(IDC_COMPRESS_COMBO_ENCRYPTION_METHOD));\r
+\r
+  m_ArchivePath.Attach(GetItem(IDC_COMPRESS_COMBO_ARCHIVE));\r
+  m_Format.Attach(GetItem(IDC_COMPRESS_COMBO_FORMAT));\r
+  m_Level.Attach(GetItem(IDC_COMPRESS_COMBO_LEVEL));\r
+  m_Method.Attach(GetItem(IDC_COMPRESS_COMBO_METHOD));\r
+  m_Dictionary.Attach(GetItem(IDC_COMPRESS_COMBO_DICTIONARY));\r
+  m_Order.Attach(GetItem(IDC_COMPRESS_COMBO_ORDER));\r
+  m_Solid.Attach(GetItem(IDC_COMPRESS_COMBO_SOLID));\r
+  m_NumThreads.Attach(GetItem(IDC_COMPRESS_COMBO_THREADS));\r
+  \r
+  m_UpdateMode.Attach(GetItem(IDC_COMPRESS_COMBO_UPDATE_MODE));\r
+  m_Volume.Attach(GetItem(IDC_COMPRESS_COMBO_VOLUME));\r
+  m_Params.Attach(GetItem(IDC_COMPRESS_EDIT_PARAMETERS));\r
+\r
+  AddVolumeItems(m_Volume);\r
+\r
+  m_RegistryInfo.Load();\r
+  CheckButton(IDC_COMPRESS_CHECK_SHOW_PASSWORD, m_RegistryInfo.ShowPassword);\r
+  CheckButton(IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, m_RegistryInfo.EncryptHeaders);\r
+\r
+  UpdatePasswordControl();\r
+\r
+  Info.FormatIndex = -1;\r
+  int i;\r
+  for (i = 0; i < ArcIndices.Size(); i++)\r
+  {\r
+    int arcIndex = ArcIndices[i];\r
+    const CArcInfoEx &ai = (*ArcFormats)[arcIndex];\r
+    int index = (int)m_Format.AddString(ai.Name);\r
+    m_Format.SetItemData(index, arcIndex);\r
+    if (ai.Name.CompareNoCase(m_RegistryInfo.ArcType) == 0 || i == 0)\r
+    {\r
+      m_Format.SetCurSel(index);\r
+      Info.FormatIndex = arcIndex;\r
+    }\r
+  }\r
+\r
+  SetArchiveName(Info.ArchiveName);\r
+  SetLevel();\r
+  SetParams();\r
+  \r
+  for (i = 0; i < m_RegistryInfo.ArcPaths.Size() && i < kHistorySize; i++)\r
+    m_ArchivePath.AddString(m_RegistryInfo.ArcPaths[i]);\r
+\r
+  m_UpdateMode.AddString(LangString(IDS_COMPRESS_UPDATE_MODE_ADD, 0x02000DA1));\r
+  m_UpdateMode.AddString(LangString(IDS_COMPRESS_UPDATE_MODE_UPDATE, 0x02000DA2));\r
+  m_UpdateMode.AddString(LangString(IDS_COMPRESS_UPDATE_MODE_FRESH, 0x02000DA3));\r
+  m_UpdateMode.AddString(LangString(IDS_COMPRESS_UPDATE_MODE_SYNCHRONIZE, 0x02000DA4));\r
+\r
+  m_UpdateMode.SetCurSel(0);\r
+\r
+  SetSolidBlockSize();\r
+  SetNumThreads();\r
+\r
+  TCHAR s[40] = { TEXT('/'), TEXT(' '), 0 };\r
+  ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2);\r
+  SetItemText(IDC_COMPRESS_HARDWARE_THREADS, s);\r
+\r
+  CheckButton(IDC_COMPRESS_SFX, Info.SFXMode);\r
+  CheckButton(IDC_COMPRESS_SHARED, Info.OpenShareForWrite);\r
+  \r
+  CheckControlsEnable();\r
+\r
+  OnButtonSFX();\r
+\r
+  SetEncryptionMethod();\r
+  SetMemoryUsage();\r
+\r
+  NormalizePosition();\r
+\r
+  return CModalDialog::OnInit();\r
+}\r
+\r
+namespace NCompressDialog\r
+{\r
+  bool CInfo::GetFullPathName(UString &result) const\r
+  {\r
+    #ifndef UNDER_CE\r
+    NDirectory::MySetCurrentDirectory(CurrentDirPrefix);\r
+    #endif\r
+    return MyGetFullPathName(ArchiveName, result);\r
+  }\r
+}\r
+\r
+void CCompressDialog::UpdatePasswordControl()\r
+{\r
+  bool showPassword = IsShowPasswordChecked();\r
+  TCHAR c = showPassword ? 0: TEXT('*');\r
+  _password1Control.SetPasswordChar(c);\r
+  _password2Control.SetPasswordChar(c);\r
+  UString password;\r
+  _password1Control.GetText(password);\r
+  _password1Control.SetText(password);\r
+  _password2Control.GetText(password);\r
+  _password2Control.SetText(password);\r
+\r
+  int cmdShow = showPassword ? SW_HIDE : SW_SHOW;\r
+  ShowItem(IDC_STATIC_COMPRESS_PASSWORD2, cmdShow);\r
+  _password2Control.Show(cmdShow);\r
+}\r
+\r
+bool CCompressDialog::OnButtonClicked(int buttonID, HWND buttonHWND)\r
+{\r
+  switch(buttonID)\r
+  {\r
+    case IDC_COMPRESS_BUTTON_SET_ARCHIVE:\r
+    {\r
+      OnButtonSetArchive();\r
+      return true;\r
+    }\r
+    case IDC_COMPRESS_SFX:\r
+    {\r
+      OnButtonSFX();\r
+      SetMemoryUsage();\r
+      return true;\r
+    }\r
+    case IDC_COMPRESS_CHECK_SHOW_PASSWORD:\r
+    {\r
+      UpdatePasswordControl();\r
+      return true;\r
+    }\r
+  }\r
+  return CModalDialog::OnButtonClicked(buttonID, buttonHWND);\r
+}\r
+\r
+void CCompressDialog::CheckSFXControlsEnable()\r
+{\r
+  const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];\r
+  bool enable = fi.SFX;\r
+  if (enable)\r
+  {\r
+    int methodID = GetMethodID();\r
+    enable = (methodID == -1 || IsMethodSupportedBySfx(methodID));\r
+  }\r
+  if (!enable)\r
+    CheckButton(IDC_COMPRESS_SFX, false);\r
+  EnableItem(IDC_COMPRESS_SFX, enable);\r
+}\r
+\r
+void CCompressDialog::CheckVolumeEnable()\r
+{\r
+  bool isSFX = IsSFX();\r
+  m_Volume.Enable(!isSFX);\r
+  if (isSFX)\r
+    m_Volume.SetText(TEXT(""));\r
+}\r
+\r
+void CCompressDialog::CheckControlsEnable()\r
+{\r
+  const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];\r
+  Info.SolidIsSpecified = fi.Solid;\r
+  bool multiThreadEnable = fi.MultiThread;\r
+  Info.MultiThreadIsAllowed = multiThreadEnable;\r
+  Info.EncryptHeadersIsAllowed = fi.EncryptFileNames;\r
+  \r
+  EnableItem(IDC_COMPRESS_COMBO_SOLID, fi.Solid);\r
+  EnableItem(IDC_COMPRESS_COMBO_THREADS, multiThreadEnable);\r
+  CheckSFXControlsEnable();\r
+  CheckVolumeEnable();\r
+\r
+  EnableItem(IDC_COMPRESS_ENCRYPTION, fi.Encrypt);\r
+\r
+  EnableItem(IDC_STATIC_COMPRESS_PASSWORD1, fi.Encrypt);\r
+  EnableItem(IDC_STATIC_COMPRESS_PASSWORD2, fi.Encrypt);\r
+  EnableItem(IDC_COMPRESS_EDIT_PASSWORD1, fi.Encrypt);\r
+  EnableItem(IDC_COMPRESS_EDIT_PASSWORD2, fi.Encrypt);\r
+  EnableItem(IDC_COMPRESS_CHECK_SHOW_PASSWORD, fi.Encrypt);\r
+\r
+  EnableItem(IDC_STATIC_COMPRESS_ENCRYPTION_METHOD, fi.Encrypt);\r
+  EnableItem(IDC_COMPRESS_COMBO_ENCRYPTION_METHOD, fi.Encrypt);\r
+  EnableItem(IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, fi.EncryptFileNames);\r
+\r
+  ShowItem(IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, fi.EncryptFileNames ? SW_SHOW : SW_HIDE);\r
+}\r
+\r
+bool CCompressDialog::IsSFX()\r
+{\r
+  CWindow sfxButton = GetItem(IDC_COMPRESS_SFX);\r
+  return sfxButton.IsEnabled() && IsButtonCheckedBool(IDC_COMPRESS_SFX);\r
+}\r
+\r
+void CCompressDialog::OnButtonSFX()\r
+{\r
+  SetMethod(GetMethodID());\r
+\r
+  UString fileName;\r
+  m_ArchivePath.GetText(fileName);\r
+  int dotPos = fileName.ReverseFind(L'.');\r
+  int slashPos = fileName.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+  if (dotPos < 0 || dotPos <= slashPos)\r
+    dotPos = -1;\r
+  if (IsSFX())\r
+  {\r
+    if (dotPos >= 0)\r
+      fileName = fileName.Left(dotPos);\r
+    fileName += kExeExt;\r
+    m_ArchivePath.SetText(fileName);\r
+  }\r
+  else\r
+  {\r
+    if (dotPos >= 0)\r
+    {\r
+      UString ext = fileName.Mid(dotPos);\r
+      if (ext.CompareNoCase(kExeExt) == 0)\r
+      {\r
+        fileName = fileName.Left(dotPos);\r
+        m_ArchivePath.SetText(fileName);\r
+      }\r
+    }\r
+    SetArchiveName2(false); // it's for OnInit\r
+  }\r
+\r
+  CheckVolumeEnable();\r
+}\r
+\r
+void CCompressDialog::OnButtonSetArchive()\r
+{\r
+  UString fileName;\r
+  m_ArchivePath.GetText(fileName);\r
+  fileName.Trim();\r
+  Info.ArchiveName = fileName;\r
+  UString fullFileName;\r
+  if (!Info.GetFullPathName(fullFileName))\r
+  {\r
+    fullFileName = Info.ArchiveName;\r
+    return;\r
+  }\r
+  UString title = LangString(IDS_COMPRESS_SET_ARCHIVE_DIALOG_TITLE, 0x02000D90);\r
+  UString s = LangString(IDS_OPEN_TYPE_ALL_FILES, 0x02000DB1);\r
+  s += L" (*.*)";\r
+  UString resPath;\r
+  if (!MyBrowseForFile(HWND(*this), title, fullFileName, s, resPath))\r
+    return;\r
+  m_ArchivePath.SetText(resPath);\r
+}\r
+\r
+// in ExtractDialog.cpp\r
+extern void AddUniqueString(UStringVector &strings, const UString &srcString);\r
+\r
+static bool IsAsciiString(const UString &s)\r
+{\r
+  for (int i = 0; i < s.Length(); i++)\r
+  {\r
+    wchar_t c = s[i];\r
+    if (c < 0x20 || c > 0x7F)\r
+      return false;\r
+  }\r
+  return true;\r
+}\r
+\r
+void CCompressDialog::OnOK()\r
+{\r
+  _password1Control.GetText(Info.Password);\r
+  if (IsZipFormat())\r
+  {\r
+    if (!IsAsciiString(Info.Password))\r
+    {\r
+      ShowErrorMessageHwndRes(*this, IDS_PASSWORD_USE_ASCII, 0x02000B11);\r
+      return;\r
+    }\r
+    UString method = GetEncryptionMethodSpec();\r
+    method.MakeUpper();\r
+    if (method.Find(L"AES") == 0)\r
+    {\r
+      if (Info.Password.Length() > 99)\r
+      {\r
+        ShowErrorMessageHwndRes(*this, IDS_PASSWORD_IS_TOO_LONG, 0x02000B12);\r
+        return;\r
+      }\r
+    }\r
+  }\r
+  if (!IsShowPasswordChecked())\r
+  {\r
+    UString password2;\r
+    _password2Control.GetText(password2);\r
+    if (password2 != Info.Password)\r
+    {\r
+      ShowErrorMessageHwndRes(*this, IDS_PASSWORD_PASSWORDS_DO_NOT_MATCH, 0x02000B10);\r
+      return;\r
+    }\r
+  }\r
+\r
+  SaveOptionsInMem();\r
+  UString s;\r
+  m_ArchivePath.GetText(s);\r
+  s.Trim();\r
+  m_RegistryInfo.ArcPaths.Clear();\r
+  AddUniqueString(m_RegistryInfo.ArcPaths, s);\r
+  Info.ArchiveName = s;\r
+  Info.UpdateMode = NCompressDialog::NUpdateMode::EEnum(m_UpdateMode.GetCurSel());\r
+\r
+  Info.Level = GetLevelSpec();\r
+  Info.Dictionary = GetDictionarySpec();\r
+  Info.Order = GetOrderSpec();\r
+  Info.OrderMode = GetOrderMode();\r
+  Info.NumThreads = GetNumThreadsSpec();\r
+\r
+  UInt32 solidLogSize = GetBlockSizeSpec();\r
+  Info.SolidBlockSize = 0;\r
+  if (solidLogSize > 0 && solidLogSize != (UInt32)-1)\r
+    Info.SolidBlockSize = (solidLogSize >= 64) ? (UInt64)(Int64)-1 : ((UInt64)1 << solidLogSize);\r
+\r
+  Info.Method = GetMethodSpec();\r
+  Info.EncryptionMethod = GetEncryptionMethodSpec();\r
+  Info.FormatIndex = GetFormatIndex();\r
+  Info.SFXMode = IsSFX();\r
+  Info.OpenShareForWrite = IsButtonCheckedBool(IDC_COMPRESS_SHARED);\r
+\r
+  m_RegistryInfo.EncryptHeaders = Info.EncryptHeaders = IsButtonCheckedBool(IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES);\r
+\r
+  m_Params.GetText(Info.Options);\r
+  UString volumeString;\r
+  m_Volume.GetText(volumeString);\r
+  volumeString.Trim();\r
+  Info.VolumeSizes.Clear();\r
+  if (!volumeString.IsEmpty())\r
+  {\r
+    if (!ParseVolumeSizes(volumeString, Info.VolumeSizes))\r
+    {\r
+      ShowErrorMessageHwndRes(*this, IDS_COMPRESS_INCORRECT_VOLUME_SIZE, 0x02000D41);\r
+      return;\r
+    }\r
+    if (!Info.VolumeSizes.IsEmpty())\r
+    {\r
+      const UInt64 volumeSize = Info.VolumeSizes.Back();\r
+      if (volumeSize < (100 << 10))\r
+      {\r
+        wchar_t s[32];\r
+        ConvertUInt64ToString(volumeSize, s);\r
+        if (::MessageBoxW(*this, MyFormatNew(IDS_COMPRESS_SPLIT_CONFIRM_MESSAGE, 0x02000D42, s),\r
+            L"7-Zip", MB_YESNOCANCEL | MB_ICONQUESTION) != IDYES)\r
+          return;\r
+      }\r
+    }\r
+  }\r
+\r
+  for (int i = 0; i < m_ArchivePath.GetCount(); i++)\r
+  {\r
+    UString sTemp;\r
+    m_ArchivePath.GetLBText(i, sTemp);\r
+    sTemp.Trim();\r
+    AddUniqueString(m_RegistryInfo.ArcPaths, sTemp);\r
+  }\r
+  if (m_RegistryInfo.ArcPaths.Size() > kHistorySize)\r
+    m_RegistryInfo.ArcPaths.DeleteBack();\r
+  \r
+  m_RegistryInfo.ArcType = (*ArcFormats)[Info.FormatIndex].Name;\r
+  m_RegistryInfo.ShowPassword = IsShowPasswordChecked();\r
+\r
+  m_RegistryInfo.Save();\r
+  \r
+  CModalDialog::OnOK();\r
+}\r
+\r
+static LPCWSTR kHelpTopic = L"fm/plugins/7-zip/add.htm";\r
+\r
+void CCompressDialog::OnHelp()\r
+{\r
+  ShowHelpWindow(NULL, kHelpTopic);\r
+}\r
+\r
+bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam)\r
+{\r
+  if (code == CBN_SELCHANGE)\r
+  {\r
+    switch(itemID)\r
+    {\r
+      case IDC_COMPRESS_COMBO_FORMAT:\r
+      {\r
+        bool isSFX = IsSFX();\r
+        SaveOptionsInMem();\r
+        SetLevel();\r
+        SetSolidBlockSize();\r
+        SetNumThreads();\r
+        SetParams();\r
+        CheckControlsEnable();\r
+        SetArchiveName2(isSFX);\r
+        SetEncryptionMethod();\r
+        SetMemoryUsage();\r
+        return true;\r
+      }\r
+      case IDC_COMPRESS_COMBO_LEVEL:\r
+      {\r
+        const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];\r
+        int index = FindRegistryFormatAlways(ai.Name);\r
+        NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];\r
+        fo.ResetForLevelChange();\r
+        SetMethod();\r
+        SetSolidBlockSize();\r
+        SetNumThreads();\r
+        CheckSFXNameChange();\r
+        SetMemoryUsage();\r
+        return true;\r
+      }\r
+      case IDC_COMPRESS_COMBO_METHOD:\r
+      {\r
+        SetDictionary();\r
+        SetOrder();\r
+        SetSolidBlockSize();\r
+        SetNumThreads();\r
+        CheckSFXNameChange();\r
+        SetMemoryUsage();\r
+        return true;\r
+      }\r
+      case IDC_COMPRESS_COMBO_DICTIONARY:\r
+      case IDC_COMPRESS_COMBO_ORDER:\r
+      {\r
+        SetSolidBlockSize();\r
+        SetMemoryUsage();\r
+        return true;\r
+      }\r
+      case IDC_COMPRESS_COMBO_THREADS:\r
+      {\r
+        SetMemoryUsage();\r
+        return true;\r
+      }\r
+    }\r
+  }\r
+  return CModalDialog::OnCommand(code, itemID, lParam);\r
+}\r
+\r
+void CCompressDialog::CheckSFXNameChange()\r
+{\r
+  bool isSFX = IsSFX();\r
+  CheckSFXControlsEnable();\r
+  if (isSFX != IsSFX())\r
+    SetArchiveName2(isSFX);\r
+}\r
+\r
+void CCompressDialog::SetArchiveName2(bool prevWasSFX)\r
+{\r
+  UString fileName;\r
+  m_ArchivePath.GetText(fileName);\r
+  const CArcInfoEx &prevArchiverInfo = (*ArcFormats)[m_PrevFormat];\r
+  if (prevArchiverInfo.KeepName || Info.KeepName)\r
+  {\r
+    UString prevExtension = prevArchiverInfo.GetMainExt();\r
+    if (prevWasSFX)\r
+      prevExtension = kExeExt;\r
+    else\r
+      prevExtension = UString('.') + prevExtension;\r
+    const int prevExtensionLen = prevExtension.Length();\r
+    if (fileName.Length() >= prevExtensionLen)\r
+      if (fileName.Right(prevExtensionLen).CompareNoCase(prevExtension) == 0)\r
+        fileName = fileName.Left(fileName.Length() - prevExtensionLen);\r
+  }\r
+  SetArchiveName(fileName);\r
+}\r
+\r
+// if type.KeepName then use OriginalFileName\r
+// else if !KeepName remove extension\r
+// add new extension\r
+\r
+void CCompressDialog::SetArchiveName(const UString &name)\r
+{\r
+  UString fileName = name;\r
+  Info.FormatIndex = GetFormatIndex();\r
+  const CArcInfoEx &ai = (*ArcFormats)[Info.FormatIndex];\r
+  m_PrevFormat = Info.FormatIndex;\r
+  if (ai.KeepName)\r
+  {\r
+    fileName = OriginalFileName;\r
+  }\r
+  else\r
+  {\r
+    if (!Info.KeepName)\r
+    {\r
+      int dotPos = fileName.ReverseFind('.');\r
+      int slashPos = MyMax(fileName.ReverseFind(WCHAR_PATH_SEPARATOR), fileName.ReverseFind('/'));\r
+      if (dotPos >= 0 && dotPos > slashPos + 1)\r
+        fileName = fileName.Left(dotPos);\r
+    }\r
+  }\r
+\r
+  if (IsSFX())\r
+    fileName += kExeExt;\r
+  else\r
+  {\r
+    fileName += L'.';\r
+    fileName += ai.GetMainExt();\r
+  }\r
+  m_ArchivePath.SetText(fileName);\r
+}\r
+\r
+int CCompressDialog::FindRegistryFormat(const UString &name)\r
+{\r
+  for (int i = 0; i < m_RegistryInfo.Formats.Size(); i++)\r
+  {\r
+    const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[i];\r
+    if (name.CompareNoCase(GetUnicodeString(fo.FormatID)) == 0)\r
+      return i;\r
+  }\r
+  return -1;\r
+}\r
+\r
+int CCompressDialog::FindRegistryFormatAlways(const UString &name)\r
+{\r
+  int index = FindRegistryFormat(name);\r
+  if (index < 0)\r
+  {\r
+    NCompression::CFormatOptions fo;\r
+    fo.FormatID = GetSystemString(name);\r
+    index = m_RegistryInfo.Formats.Add(fo);\r
+  }\r
+  return index;\r
+}\r
+\r
+int CCompressDialog::GetStaticFormatIndex()\r
+{\r
+  int formatIndex = GetFormatIndex();\r
+  const CArcInfoEx &ai = (*ArcFormats)[formatIndex];\r
+  for (int i = 0; i < MY_SIZE_OF_ARRAY(g_Formats); i++)\r
+    if (ai.Name.CompareNoCase(g_Formats[i].Name) == 0)\r
+      return i;\r
+  return 0; // -1;\r
+}\r
+\r
+void CCompressDialog::SetNearestSelectComboBox(NControl::CComboBox &comboBox, UInt32 value)\r
+{\r
+  for (int i = comboBox.GetCount() - 1; i >= 0; i--)\r
+    if ((UInt32)comboBox.GetItemData(i) <= value)\r
+    {\r
+      comboBox.SetCurSel(i);\r
+      return;\r
+    }\r
+  if (comboBox.GetCount() > 0)\r
+    comboBox.SetCurSel(0);\r
+}\r
+\r
+void CCompressDialog::SetLevel()\r
+{\r
+  m_Level.ResetContent();\r
+  const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];\r
+  const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];\r
+  int index = FindRegistryFormat(ai.Name);\r
+  UInt32 level = kNormal;\r
+  if (index >= 0)\r
+  {\r
+    const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];\r
+    if (fo.Level <= kUltra)\r
+      level = fo.Level;\r
+    else\r
+      level = kUltra;\r
+  }\r
+  int i;\r
+  for (i = 0; i <= kUltra; i++)\r
+  {\r
+    if ((fi.LevelsMask & (1 << i)) != 0)\r
+    {\r
+      const CLevelInfo &levelInfo = g_Levels[i];\r
+      int index = (int)m_Level.AddString(LangString(levelInfo.ResourceID, levelInfo.LangID));\r
+      m_Level.SetItemData(index, i);\r
+    }\r
+  }\r
+  SetNearestSelectComboBox(m_Level, level);\r
+  SetMethod();\r
+}\r
+\r
+void CCompressDialog::SetMethod(int keepMethodId)\r
+{\r
+  m_Method.ResetContent();\r
+  UInt32 level = GetLevel();\r
+  if (level == 0)\r
+  {\r
+    SetDictionary();\r
+    SetOrder();\r
+    return;\r
+  }\r
+  const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];\r
+  const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];\r
+  int index = FindRegistryFormat(ai.Name);\r
+  UString defaultMethod;\r
+  if (index >= 0)\r
+  {\r
+    const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];\r
+    defaultMethod = fo.Method;\r
+  }\r
+  bool isSfx = IsSFX();\r
+  bool weUseSameMethod = false;\r
+  for (int m = 0; m < fi.NumMethods; m++)\r
+  {\r
+    EMethodID methodID = fi.MathodIDs[m];\r
+    if (isSfx)\r
+      if (!IsMethodSupportedBySfx(methodID))\r
+        continue;\r
+    const LPCWSTR method = kMethodsNames[methodID];\r
+    int itemIndex = (int)m_Method.AddString(GetSystemString(method));\r
+    m_Method.SetItemData(itemIndex, methodID);\r
+    if (keepMethodId == methodID)\r
+    {\r
+      m_Method.SetCurSel(itemIndex);\r
+      weUseSameMethod = true;\r
+      continue;\r
+    }\r
+    if ((defaultMethod.CompareNoCase(method) == 0 || m == 0) && !weUseSameMethod)\r
+      m_Method.SetCurSel(itemIndex);\r
+  }\r
+  if (!weUseSameMethod)\r
+  {\r
+    SetDictionary();\r
+    SetOrder();\r
+  }\r
+}\r
+\r
+bool CCompressDialog::IsZipFormat()\r
+{\r
+  const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];\r
+  return (ai.Name.CompareNoCase(L"zip") == 0);\r
+}\r
+\r
+void CCompressDialog::SetEncryptionMethod()\r
+{\r
+  _encryptionMethod.ResetContent();\r
+  const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];\r
+  if (ai.Name.CompareNoCase(L"7z") == 0)\r
+  {\r
+    _encryptionMethod.AddString(TEXT("AES-256"));\r
+    _encryptionMethod.SetCurSel(0);\r
+  }\r
+  else if (ai.Name.CompareNoCase(L"zip") == 0)\r
+  {\r
+    int index = FindRegistryFormat(ai.Name);\r
+    UString encryptionMethod;\r
+    if (index >= 0)\r
+    {\r
+      const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];\r
+      encryptionMethod = fo.EncryptionMethod;\r
+    }\r
+    _encryptionMethod.AddString(TEXT("ZipCrypto"));\r
+    _encryptionMethod.AddString(TEXT("AES-256"));\r
+    _encryptionMethod.SetCurSel(encryptionMethod.Find(L"AES") == 0 ? 1 : 0);\r
+  }\r
+}\r
+\r
+int CCompressDialog::GetMethodID()\r
+{\r
+  if (m_Method.GetCount() <= 0)\r
+    return -1;\r
+  return (int)(UInt32)m_Method.GetItemData(m_Method.GetCurSel());\r
+}\r
+\r
+UString CCompressDialog::GetMethodSpec()\r
+{\r
+  if (m_Method.GetCount() <= 1)\r
+    return UString();\r
+  return kMethodsNames[GetMethodID()];\r
+}\r
+\r
+UString CCompressDialog::GetEncryptionMethodSpec()\r
+{\r
+  if (_encryptionMethod.GetCount() <= 1)\r
+    return UString();\r
+  if (_encryptionMethod.GetCurSel() <= 0)\r
+    return UString();\r
+  UString result;\r
+  _encryptionMethod.GetText(result);\r
+  result.Replace(L"-", L"");\r
+  return result;\r
+}\r
+\r
+int CCompressDialog::AddDictionarySize(UInt32 size, bool kilo, bool maga)\r
+{\r
+  UInt32 sizePrint = size;\r
+  if (kilo)\r
+    sizePrint >>= 10;\r
+  else if (maga)\r
+    sizePrint >>= 20;\r
+  TCHAR s[40];\r
+  ConvertUInt32ToString(sizePrint, s);\r
+  if (kilo)\r
+    lstrcat(s, TEXT(" K"));\r
+  else if (maga)\r
+    lstrcat(s, TEXT(" M"));\r
+  else\r
+    lstrcat(s, TEXT(" "));\r
+  lstrcat(s, TEXT("B"));\r
+  int index = (int)m_Dictionary.AddString(s);\r
+  m_Dictionary.SetItemData(index, size);\r
+  return index;\r
+}\r
+\r
+int CCompressDialog::AddDictionarySize(UInt32 size)\r
+{\r
+  if (size > 0)\r
+  {\r
+    if ((size & 0xFFFFF) == 0)\r
+      return AddDictionarySize(size, false, true);\r
+    if ((size & 0x3FF) == 0)\r
+      return AddDictionarySize(size, true, false);\r
+  }\r
+  return AddDictionarySize(size, false, false);\r
+}\r
+\r
+void CCompressDialog::SetDictionary()\r
+{\r
+  m_Dictionary.ResetContent();\r
+  const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];\r
+  int index = FindRegistryFormat(ai.Name);\r
+  UInt32 defaultDictionary = (UInt32)-1;\r
+  if (index >= 0)\r
+  {\r
+    const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];\r
+    if (fo.Method.CompareNoCase(GetMethodSpec()) == 0)\r
+      defaultDictionary = fo.Dictionary;\r
+  }\r
+  int methodID = GetMethodID();\r
+  UInt32 level = GetLevel2();\r
+  if (methodID < 0)\r
+    return;\r
+  const UInt64 maxRamSize = GetMaxRamSizeForProgram();\r
+  switch (methodID)\r
+  {\r
+    case kLZMA:\r
+    case kLZMA2:\r
+    {\r
+      static const UInt32 kMinDicSize = (1 << 16);\r
+      if (defaultDictionary == (UInt32)-1)\r
+      {\r
+        if (level >= 9)      defaultDictionary = (1 << 26);\r
+        else if (level >= 7) defaultDictionary = (1 << 25);\r
+        else if (level >= 5) defaultDictionary = (1 << 24);\r
+        else if (level >= 3) defaultDictionary = (1 << 20);\r
+        else                 defaultDictionary = (kMinDicSize);\r
+      }\r
+      int i;\r
+      AddDictionarySize(kMinDicSize);\r
+      m_Dictionary.SetCurSel(0);\r
+      for (i = 20; i <= 30; i++)\r
+        for (int j = 0; j < 2; j++)\r
+        {\r
+          if (i == 20 && j > 0)\r
+            continue;\r
+          UInt32 dictionary = (1 << i) + (j << (i - 1));\r
+          if (dictionary >\r
+          #ifdef _WIN64\r
+            (1 << 30)\r
+          #else\r
+            (1 << 26)\r
+          #endif\r
+            )\r
+            continue;\r
+          AddDictionarySize(dictionary);\r
+          UInt64 decomprSize;\r
+          UInt64 requiredComprSize = GetMemoryUsage(dictionary, decomprSize);\r
+          if (dictionary <= defaultDictionary && requiredComprSize <= maxRamSize)\r
+            m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1);\r
+        }\r
+\r
+      // SetNearestSelectComboBox(m_Dictionary, defaultDictionary);\r
+      break;\r
+    }\r
+    case kPPMd:\r
+    {\r
+      if (defaultDictionary == (UInt32)-1)\r
+      {\r
+        if (level >= 9)      defaultDictionary = (192 << 20);\r
+        else if (level >= 7) defaultDictionary = ( 64 << 20);\r
+        else if (level >= 5) defaultDictionary = ( 16 << 20);\r
+        else                 defaultDictionary = (  4 << 20);\r
+      }\r
+      int i;\r
+      for (i = 20; i < 31; i++)\r
+        for (int j = 0; j < 2; j++)\r
+        {\r
+          if (i == 20 && j > 0)\r
+            continue;\r
+          UInt32 dictionary = (1 << i) + (j << (i - 1));\r
+          if (dictionary >\r
+            #ifdef _WIN64\r
+              (1 << 30)\r
+            #else\r
+              (1 << 29)\r
+            #endif\r
+            )\r
+            continue;\r
+          AddDictionarySize(dictionary);\r
+          UInt64 decomprSize;\r
+          UInt64 requiredComprSize = GetMemoryUsage(dictionary, decomprSize);\r
+          if (dictionary <= defaultDictionary && requiredComprSize <= maxRamSize || m_Dictionary.GetCount() == 0)\r
+            m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1);\r
+        }\r
+      SetNearestSelectComboBox(m_Dictionary, defaultDictionary);\r
+      break;\r
+    }\r
+    case kDeflate:\r
+    {\r
+      AddDictionarySize(32 << 10);\r
+      m_Dictionary.SetCurSel(0);\r
+      break;\r
+    }\r
+    case kDeflate64:\r
+    {\r
+      AddDictionarySize(64 << 10);\r
+      m_Dictionary.SetCurSel(0);\r
+      break;\r
+    }\r
+    case kBZip2:\r
+    {\r
+      if (defaultDictionary == (UInt32)-1)\r
+      {\r
+        if (level >= 5)\r
+          defaultDictionary = (900 << 10);\r
+        else if (level >= 3)\r
+          defaultDictionary = (500 << 10);\r
+        else\r
+          defaultDictionary = (100 << 10);\r
+      }\r
+      for (int i = 1; i <= 9; i++)\r
+      {\r
+        UInt32 dictionary = (i * 100) << 10;\r
+        AddDictionarySize(dictionary);\r
+        if (dictionary <= defaultDictionary || m_Dictionary.GetCount() == 0)\r
+          m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1);\r
+      }\r
+      break;\r
+    }\r
+    case kPPMdZip:\r
+    {\r
+      if (defaultDictionary == (UInt32)-1)\r
+        defaultDictionary = (1 << (19 + (level > 8 ? 8 : level)));\r
+      for (int i = 20; i <= 28; i++)\r
+      {\r
+        UInt32 dictionary = (1 << i);\r
+        AddDictionarySize(dictionary);\r
+        UInt64 decomprSize;\r
+        UInt64 requiredComprSize = GetMemoryUsage(dictionary, decomprSize);\r
+        if (dictionary <= defaultDictionary && requiredComprSize <= maxRamSize || m_Dictionary.GetCount() == 0)\r
+          m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1);\r
+      }\r
+      SetNearestSelectComboBox(m_Dictionary, defaultDictionary);\r
+      break;\r
+    }\r
+  }\r
+}\r
+\r
+UInt32 CCompressDialog::GetComboValue(NWindows::NControl::CComboBox &c, int defMax)\r
+{\r
+  if (c.GetCount() <= defMax)\r
+    return (UInt32)-1;\r
+  return (UInt32)c.GetItemData(c.GetCurSel());\r
+}\r
+\r
+UInt32 CCompressDialog::GetLevel2()\r
+{\r
+  UInt32 level = GetLevel();\r
+  if (level == (UInt32)-1)\r
+    level = 5;\r
+  return level;\r
+}\r
+\r
+int CCompressDialog::AddOrder(UInt32 size)\r
+{\r
+  TCHAR s[40];\r
+  ConvertUInt32ToString(size, s);\r
+  int index = (int)m_Order.AddString(s);\r
+  m_Order.SetItemData(index, size);\r
+  return index;\r
+}\r
+\r
+void CCompressDialog::SetOrder()\r
+{\r
+  m_Order.ResetContent();\r
+  const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];\r
+  int index = FindRegistryFormat(ai.Name);\r
+  UInt32 defaultOrder = (UInt32)-1;\r
+  if (index >= 0)\r
+  {\r
+    const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];\r
+    if (fo.Method.CompareNoCase(GetMethodSpec()) == 0)\r
+      defaultOrder = fo.Order;\r
+  }\r
+  int methodID = GetMethodID();\r
+  UInt32 level = GetLevel2();\r
+  if (methodID < 0)\r
+    return;\r
+  switch (methodID)\r
+  {\r
+    case kLZMA:\r
+    case kLZMA2:\r
+    {\r
+      if (defaultOrder == (UInt32)-1)\r
+        defaultOrder = (level >= 7) ? 64 : 32;\r
+      for (int i = 3; i <= 8; i++)\r
+        for (int j = 0; j < 2; j++)\r
+        {\r
+          UInt32 order = (1 << i) + (j << (i - 1));\r
+          if (order <= 256)\r
+            AddOrder(order);\r
+        }\r
+      AddOrder(273);\r
+      SetNearestSelectComboBox(m_Order, defaultOrder);\r
+      break;\r
+    }\r
+    case kPPMd:\r
+    {\r
+      if (defaultOrder == (UInt32)-1)\r
+      {\r
+        if (level >= 9)\r
+          defaultOrder = 32;\r
+        else if (level >= 7)\r
+          defaultOrder = 16;\r
+        else if (level >= 5)\r
+          defaultOrder = 6;\r
+        else\r
+          defaultOrder = 4;\r
+      }\r
+      int i;\r
+      AddOrder(2);\r
+      AddOrder(3);\r
+      for (i = 2; i < 8; i++)\r
+        for (int j = 0; j < 4; j++)\r
+        {\r
+          UInt32 order = (1 << i) + (j << (i - 2));\r
+          if (order < 32)\r
+            AddOrder(order);\r
+        }\r
+      AddOrder(32);\r
+      SetNearestSelectComboBox(m_Order, defaultOrder);\r
+      break;\r
+    }\r
+    case kDeflate:\r
+    case kDeflate64:\r
+    {\r
+      if (defaultOrder == (UInt32)-1)\r
+      {\r
+        if (level >= 9)\r
+          defaultOrder = 128;\r
+        else if (level >= 7)\r
+          defaultOrder = 64;\r
+        else\r
+          defaultOrder = 32;\r
+      }\r
+      int i;\r
+      for (i = 3; i <= 8; i++)\r
+        for (int j = 0; j < 2; j++)\r
+        {\r
+          UInt32 order = (1 << i) + (j << (i - 1));\r
+          if (order <= 256)\r
+            AddOrder(order);\r
+        }\r
+      AddOrder(methodID == kDeflate64 ? 257 : 258);\r
+      SetNearestSelectComboBox(m_Order, defaultOrder);\r
+      break;\r
+    }\r
+    case kBZip2:\r
+    {\r
+      break;\r
+    }\r
+    case kPPMdZip:\r
+    {\r
+      if (defaultOrder == (UInt32)-1)\r
+        defaultOrder = level + 3;\r
+      for (int i = 2; i <= 16; i++)\r
+        AddOrder(i);\r
+      SetNearestSelectComboBox(m_Order, defaultOrder);\r
+      break;\r
+    }\r
+  }\r
+}\r
+\r
+bool CCompressDialog::GetOrderMode()\r
+{\r
+  switch (GetMethodID())\r
+  {\r
+    case kPPMd:\r
+      return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+static const UInt32 kNoSolidBlockSize = 0;\r
+static const UInt32 kSolidBlockSize = 64;\r
+\r
+void CCompressDialog::SetSolidBlockSize()\r
+{\r
+  m_Solid.ResetContent();\r
+  const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];\r
+  if (!fi.Solid)\r
+    return;\r
+\r
+  UInt32 level = GetLevel2();\r
+  if (level == 0)\r
+    return;\r
+\r
+  UInt32 dictionary = GetDictionarySpec();\r
+  if (dictionary == (UInt32)-1)\r
+    dictionary = 1;\r
+\r
+  UInt32 defaultBlockSize = (UInt32)-1;\r
+\r
+  const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];\r
+  int index = FindRegistryFormat(ai.Name);\r
+  if (index >= 0)\r
+  {\r
+    const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];\r
+    if (fo.Method.CompareNoCase(GetMethodSpec()) == 0)\r
+      defaultBlockSize = fo.BlockLogSize;\r
+  }\r
+\r
+  index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_NON_SOLID, 0x02000D14));\r
+  m_Solid.SetItemData(index, (UInt32)kNoSolidBlockSize);\r
+  m_Solid.SetCurSel(0);\r
+  bool needSet = defaultBlockSize == (UInt32)-1;\r
+  for (int i = 20; i <= 36; i++)\r
+  {\r
+    if (needSet && dictionary >= (((UInt64)1 << (i - 7))) && i <= 32)\r
+      defaultBlockSize = i;\r
+    TCHAR s[40];\r
+    ConvertUInt32ToString(1 << (i % 10), s);\r
+    if (i < 30) lstrcat(s, TEXT(" M"));\r
+    else        lstrcat(s, TEXT(" G"));\r
+    lstrcat(s, TEXT("B"));\r
+    int index = (int)m_Solid.AddString(s);\r
+    m_Solid.SetItemData(index, (UInt32)i);\r
+  }\r
+  index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_SOLID, 0x02000D15));\r
+  m_Solid.SetItemData(index, kSolidBlockSize);\r
+  if (defaultBlockSize == (UInt32)-1)\r
+    defaultBlockSize = kSolidBlockSize;\r
+  if (defaultBlockSize != kNoSolidBlockSize)\r
+    SetNearestSelectComboBox(m_Solid, defaultBlockSize);\r
+}\r
+\r
+void CCompressDialog::SetNumThreads()\r
+{\r
+  m_NumThreads.ResetContent();\r
+\r
+  const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];\r
+  if (!fi.MultiThread)\r
+    return;\r
+\r
+  UInt32 numHardwareThreads = NSystem::GetNumberOfProcessors();\r
+  UInt32 defaultValue = numHardwareThreads;\r
+\r
+  const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];\r
+  int index = FindRegistryFormat(ai.Name);\r
+  if (index >= 0)\r
+  {\r
+    const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];\r
+    if (fo.Method.CompareNoCase(GetMethodSpec()) == 0 && fo.NumThreads != (UInt32)-1)\r
+      defaultValue = fo.NumThreads;\r
+  }\r
+\r
+  UInt32 numAlgoThreadsMax = 1;\r
+  int methodID = GetMethodID();\r
+  switch (methodID)\r
+  {\r
+    case kLZMA: numAlgoThreadsMax = 2; break;\r
+    case kLZMA2: numAlgoThreadsMax = 32; break;\r
+    case kBZip2: numAlgoThreadsMax = 32; break;\r
+  }\r
+  if (IsZipFormat())\r
+    numAlgoThreadsMax = 128;\r
+  for (UInt32 i = 1; i <= numHardwareThreads * 2 && i <= numAlgoThreadsMax; i++)\r
+  {\r
+    TCHAR s[40];\r
+    ConvertUInt32ToString(i, s);\r
+    int index = (int)m_NumThreads.AddString(s);\r
+    m_NumThreads.SetItemData(index, (UInt32)i);\r
+  }\r
+  SetNearestSelectComboBox(m_NumThreads, defaultValue);\r
+}\r
+\r
+UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemory)\r
+{\r
+  decompressMemory = UInt64(Int64(-1));\r
+  UInt32 level = GetLevel2();\r
+  if (level == 0)\r
+  {\r
+    decompressMemory = (1 << 20);\r
+    return decompressMemory;\r
+  }\r
+  UInt64 size = 0;\r
+\r
+  const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];\r
+  if (fi.Filter && level >= 9)\r
+    size += (12 << 20) * 2 + (5 << 20);\r
+  UInt32 numThreads = GetNumThreads2();\r
+  if (IsZipFormat())\r
+  {\r
+    UInt32 numSubThreads = 1;\r
+    if (GetMethodID() == kLZMA && numThreads > 1 && level >= 5)\r
+      numSubThreads = 2;\r
+    UInt32 numMainThreads = numThreads / numSubThreads;\r
+    if (numMainThreads > 1)\r
+      size += (UInt64)numMainThreads << 25;\r
+  }\r
+  int methidId = GetMethodID();\r
+  switch (methidId)\r
+  {\r
+    case kLZMA:\r
+    case kLZMA2:\r
+    {\r
+      UInt32 hs = dictionary - 1;\r
+      hs |= (hs >> 1);\r
+      hs |= (hs >> 2);\r
+      hs |= (hs >> 4);\r
+      hs |= (hs >> 8);\r
+      hs >>= 1;\r
+      hs |= 0xFFFF;\r
+      if (hs > (1 << 24))\r
+        hs >>= 1;\r
+      hs++;\r
+      UInt64 size1 = (UInt64)hs * 4;\r
+      size1 += (UInt64)dictionary * 4;\r
+      if (level >= 5)\r
+        size1 += (UInt64)dictionary * 4;\r
+      size1 += (2 << 20);\r
+\r
+      UInt32 numThreads1 = 1;\r
+      if (numThreads > 1 && level >= 5)\r
+      {\r
+        size1 += (2 << 20) + (4 << 20);\r
+        numThreads1 = 2;\r
+      }\r
+      UInt32 numBlockThreads = numThreads / numThreads1;\r
+      if (methidId == kLZMA || numBlockThreads == 1)\r
+        size1 += (UInt64)dictionary * 3 / 2;\r
+      else\r
+      {\r
+        UInt64 chunkSize = (UInt64)dictionary << 2;\r
+        chunkSize = MyMax(chunkSize, (UInt64)(1 << 20));\r
+        chunkSize = MyMin(chunkSize, (UInt64)(1 << 28));\r
+        chunkSize = MyMax(chunkSize, (UInt64)dictionary);\r
+        size1 += chunkSize * 2;\r
+      }\r
+      size += size1 * numBlockThreads;\r
+\r
+      decompressMemory = dictionary + (2 << 20);\r
+      return size;\r
+    }\r
+    case kPPMd:\r
+    {\r
+      decompressMemory = dictionary + (2 << 20);\r
+      return size + decompressMemory;\r
+    }\r
+    case kDeflate:\r
+    case kDeflate64:\r
+    {\r
+      UInt32 order = GetOrder();\r
+      if (order == (UInt32)-1)\r
+        order = 32;\r
+      if (level >= 7)\r
+        size += (1 << 20);\r
+      size += 3 << 20;\r
+      decompressMemory = (2 << 20);\r
+      return size;\r
+    }\r
+    case kBZip2:\r
+    {\r
+      decompressMemory = (7 << 20);\r
+      UInt64 memForOneThread = (10 << 20);\r
+      return size + memForOneThread * numThreads;\r
+    }\r
+    case kPPMdZip:\r
+    {\r
+      decompressMemory = dictionary + (2 << 20);\r
+      return size + (UInt64)decompressMemory * numThreads;\r
+    }\r
+  }\r
+  return (UInt64)(Int64)-1;\r
+}\r
+\r
+UInt64 CCompressDialog::GetMemoryUsage(UInt64 &decompressMemory)\r
+{\r
+  return GetMemoryUsage(GetDictionary(), decompressMemory);\r
+}\r
+\r
+void CCompressDialog::PrintMemUsage(UINT res, UInt64 value)\r
+{\r
+  if (value == (UInt64)(Int64)-1)\r
+  {\r
+    SetItemText(res, TEXT("?"));\r
+    return;\r
+  }\r
+  value = (value + (1 << 20) - 1) >> 20;\r
+  TCHAR s[40];\r
+  ConvertUInt64ToString(value, s);\r
+  lstrcat(s, TEXT(" MB"));\r
+  SetItemText(res, s);\r
+}\r
+    \r
+void CCompressDialog::SetMemoryUsage()\r
+{\r
+  UInt64 decompressMem;\r
+  UInt64 memUsage = GetMemoryUsage(decompressMem);\r
+  PrintMemUsage(IDC_STATIC_COMPRESS_MEMORY_VALUE, memUsage);\r
+  PrintMemUsage(IDC_STATIC_COMPRESS_MEMORY_DE_VALUE, decompressMem);\r
+}\r
+\r
+void CCompressDialog::SetParams()\r
+{\r
+  const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];\r
+  m_Params.SetText(TEXT(""));\r
+  int index = FindRegistryFormat(ai.Name);\r
+  if (index >= 0)\r
+  {\r
+    const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];\r
+    m_Params.SetText(fo.Options);\r
+  }\r
+}\r
+\r
+void CCompressDialog::SaveOptionsInMem()\r
+{\r
+  const CArcInfoEx &ai = (*ArcFormats)[Info.FormatIndex];\r
+  int index = FindRegistryFormatAlways(ai.Name);\r
+  m_Params.GetText(Info.Options);\r
+  Info.Options.Trim();\r
+  NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];\r
+  fo.Options = Info.Options;\r
+  fo.Level = GetLevelSpec();\r
+  fo.Dictionary = GetDictionarySpec();\r
+  fo.Order = GetOrderSpec();\r
+  fo.Method = GetMethodSpec();\r
+  fo.EncryptionMethod = GetEncryptionMethodSpec();\r
+  fo.NumThreads = GetNumThreadsSpec();\r
+  fo.BlockLogSize = GetBlockSizeSpec();\r
+}\r
+\r
+int CCompressDialog::GetFormatIndex()\r
+{\r
+  return (int)m_Format.GetItemData(m_Format.GetCurSel());\r
+}\r
diff --git a/CPP/7zip/UI/GUI/CompressDialog.h b/CPP/7zip/UI/GUI/CompressDialog.h
new file mode 100755 (executable)
index 0000000..6213dfd
--- /dev/null
@@ -0,0 +1,189 @@
+// CompressDialog.h\r
+\r
+#ifndef __COMPRESS_DIALOG_H\r
+#define __COMPRESS_DIALOG_H\r
+\r
+#include "Windows/Control/ComboBox.h"\r
+#include "Windows/Control/Edit.h"\r
+\r
+#include "../Common/LoadCodecs.h"\r
+#include "../Common/ZipRegistry.h"\r
+\r
+#include "../FileManager/DialogSize.h"\r
+\r
+#include "CompressDialogRes.h"\r
+\r
+namespace NCompressDialog\r
+{\r
+  namespace NUpdateMode\r
+  {\r
+    enum EEnum\r
+    {\r
+      kAdd,\r
+      kUpdate,\r
+      kFresh,\r
+      kSynchronize\r
+    };\r
+  }\r
+  struct CInfo\r
+  {\r
+    NUpdateMode::EEnum UpdateMode;\r
+    bool SolidIsSpecified;\r
+    bool MultiThreadIsAllowed;\r
+    UInt64 SolidBlockSize;\r
+    UInt32 NumThreads;\r
+\r
+    CRecordVector<UInt64> VolumeSizes;\r
+\r
+    UInt32 Level;\r
+    UString Method;\r
+    UInt32 Dictionary;\r
+    bool OrderMode;\r
+    UInt32 Order;\r
+    UString Options;\r
+\r
+    UString EncryptionMethod;\r
+\r
+    bool SFXMode;\r
+    bool OpenShareForWrite;\r
+\r
+    \r
+    UString ArchiveName; // in: Relative for ; out: abs\r
+    UString CurrentDirPrefix;\r
+    bool KeepName;\r
+\r
+    bool GetFullPathName(UString &result) const;\r
+\r
+    int FormatIndex;\r
+\r
+    UString Password;\r
+    bool EncryptHeadersIsAllowed;\r
+    bool EncryptHeaders;\r
+\r
+    void Init()\r
+    {\r
+      Level = Dictionary = Order = UInt32(-1);\r
+      OrderMode = false;\r
+      Method.Empty();\r
+      Options.Empty();\r
+      EncryptionMethod.Empty();\r
+    }\r
+    CInfo()\r
+    {\r
+      Init();\r
+    }\r
+  };\r
+}\r
+\r
+class CCompressDialog: public NWindows::NControl::CModalDialog\r
+{\r
+  NWindows::NControl::CComboBox m_ArchivePath;\r
+  NWindows::NControl::CComboBox m_Format;\r
+  NWindows::NControl::CComboBox m_Level;\r
+  NWindows::NControl::CComboBox m_Method;\r
+  NWindows::NControl::CComboBox m_Dictionary;\r
+  NWindows::NControl::CComboBox m_Order;\r
+  NWindows::NControl::CComboBox m_Solid;\r
+  NWindows::NControl::CComboBox m_NumThreads;\r
+  NWindows::NControl::CComboBox m_UpdateMode;\r
+  NWindows::NControl::CComboBox m_Volume;\r
+  NWindows::NControl::CDialogChildControl m_Params;\r
+\r
+  NWindows::NControl::CEdit _password1Control;\r
+  NWindows::NControl::CEdit _password2Control;\r
+  NWindows::NControl::CComboBox _encryptionMethod;\r
+\r
+  NCompression::CInfo m_RegistryInfo;\r
+\r
+  int m_PrevFormat;\r
+  void SetArchiveName(const UString &name);\r
+  int FindRegistryFormat(const UString &name);\r
+  int FindRegistryFormatAlways(const UString &name);\r
+  \r
+  void CheckSFXNameChange();\r
+  void SetArchiveName2(bool prevWasSFX);\r
+  \r
+  int GetStaticFormatIndex();\r
+\r
+  void SetNearestSelectComboBox(NWindows::NControl::CComboBox &comboBox, UInt32 value);\r
+\r
+  void SetLevel();\r
+  \r
+  void SetMethod(int keepMethodId = -1);\r
+  int GetMethodID();\r
+  UString GetMethodSpec();\r
+  UString GetEncryptionMethodSpec();\r
+\r
+  bool IsZipFormat();\r
+\r
+  void SetEncryptionMethod();\r
+\r
+  int AddDictionarySize(UInt32 size, bool kilo, bool maga);\r
+  int AddDictionarySize(UInt32 size);\r
+  \r
+  void SetDictionary();\r
+\r
+  UInt32 GetComboValue(NWindows::NControl::CComboBox &c, int defMax = 0);\r
+\r
+  UInt32 GetLevel()  { return GetComboValue(m_Level); }\r
+  UInt32 GetLevelSpec()  { return GetComboValue(m_Level, 1); }\r
+  UInt32 GetLevel2();\r
+  UInt32 GetDictionary() { return GetComboValue(m_Dictionary); }\r
+  UInt32 GetDictionarySpec() { return GetComboValue(m_Dictionary, 1); }\r
+  UInt32 GetOrder() { return GetComboValue(m_Order); }\r
+  UInt32 GetOrderSpec() { return GetComboValue(m_Order, 1); }\r
+  UInt32 GetNumThreadsSpec() { return GetComboValue(m_NumThreads, 1); }\r
+  UInt32 GetNumThreads2() { UInt32 num = GetNumThreadsSpec(); if (num == UInt32(-1)) num = 1; return num; }\r
+  UInt32 GetBlockSizeSpec() { return GetComboValue(m_Solid, 1); }\r
+\r
+  int AddOrder(UInt32 size);\r
+  void SetOrder();\r
+  bool GetOrderMode();\r
+\r
+  void SetSolidBlockSize();\r
+  void SetNumThreads();\r
+\r
+  UInt64 GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemory);\r
+  UInt64 GetMemoryUsage(UInt64 &decompressMemory);\r
+  void PrintMemUsage(UINT res, UInt64 value);\r
+  void SetMemoryUsage();\r
+  void SetParams();\r
+  void SaveOptionsInMem();\r
+\r
+  void UpdatePasswordControl();\r
+  bool IsShowPasswordChecked() const\r
+    { return IsButtonChecked(IDC_COMPRESS_CHECK_SHOW_PASSWORD) == BST_CHECKED; }\r
+\r
+  int GetFormatIndex();\r
+public:\r
+  CObjectVector<CArcInfoEx> *ArcFormats;\r
+  CRecordVector<int> ArcIndices;\r
+\r
+  NCompressDialog::CInfo Info;\r
+  UString OriginalFileName; // for bzip2, gzip2\r
+\r
+  INT_PTR Create(HWND wndParent = 0)\r
+  {\r
+    BIG_DIALOG_SIZE(400, 304);\r
+    return CModalDialog::Create(SIZED_DIALOG(IDD_DIALOG_COMPRESS), wndParent);\r
+  }\r
+\r
+protected:\r
+\r
+  void CheckSFXControlsEnable();\r
+  void CheckVolumeEnable();\r
+  void CheckControlsEnable();\r
+\r
+  void OnButtonSetArchive();\r
+  bool IsSFX();\r
+  void OnButtonSFX();\r
+\r
+  virtual bool OnInit();\r
+  virtual bool OnCommand(int code, int itemID, LPARAM lParam);\r
+  virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);\r
+  virtual void OnOK();\r
+  virtual void OnHelp();\r
+\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/GUI/CompressDialog.rc b/CPP/7zip/UI/GUI/CompressDialog.rc
new file mode 100755 (executable)
index 0000000..0ca7b70
--- /dev/null
@@ -0,0 +1,187 @@
+#include "CompressDialogRes.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#define xc 400\r
+#define yc 304\r
+\r
+#undef gSize\r
+#undef gSpace\r
+#undef g0xs\r
+#undef g1x\r
+#undef g1xs\r
+#undef g2xs\r
+#undef g3x\r
+#undef g3xs\r
+#undef g4x\r
+#undef g4x2\r
+#undef g4xs\r
+#undef g4xs2\r
+\r
+#define gSize 192\r
+#define gSpace 24\r
+\r
+#define g1xs 88\r
+#define g0xs (gSize - g1xs)\r
+#define g1x  (m + g0xs)\r
+\r
+#define g3xs 40\r
+#define g2xs (gSize - g3xs)\r
+#define g3x  (m + g2xs)\r
+\r
+#define g4x (m + gSize + gSpace)\r
+#define g4x2 (g4x + m)\r
+#define g4xs (xc - gSize - gSpace)\r
+#define g4xs2 (g4xs - m - m)\r
+\r
+#define yOpt 72\r
+#define yPsw 128\r
+\r
+IDD_DIALOG_COMPRESS MY_DIALOG\r
+CAPTION "Add to Archive"\r
+BEGIN\r
+  LTEXT    "&Archive:", IDC_STATIC_COMPRESS_ARCHIVE, m, m, xc, 8\r
+  COMBOBOX  IDC_COMPRESS_COMBO_ARCHIVE, m, 18, xc - bxsDots - 12, 126, MY_COMBO_WITH_EDIT\r
+  PUSHBUTTON  "...", IDC_COMPRESS_BUTTON_SET_ARCHIVE, xs - m - bxsDots, 17, bxsDots, bys, WS_GROUP\r
+\r
+  LTEXT     "Archive &format:", IDC_STATIC_COMPRESS_FORMAT,     m,  41, g0xs, 8\r
+  COMBOBOX  IDC_COMPRESS_COMBO_FORMAT,     g1x, 39,  g1xs , 80, MY_COMBO | CBS_SORT\r
+  \r
+  LTEXT     "Compression &level:",IDC_STATIC_COMPRESS_LEVEL,    m,  62, g0xs, 8\r
+  COMBOBOX  IDC_COMPRESS_COMBO_LEVEL,      g1x, 60,  g1xs,  80, MY_COMBO\r
+  \r
+  LTEXT     "Compression &method:",IDC_STATIC_COMPRESS_METHOD,  m,  83, g0xs, 8\r
+  COMBOBOX  IDC_COMPRESS_COMBO_METHOD,     g1x, 81,  g1xs,  80, MY_COMBO\r
+\r
+  LTEXT     "&Dictionary size:",IDC_STATIC_COMPRESS_DICTIONARY, m, 104, g0xs, 8\r
+  COMBOBOX  IDC_COMPRESS_COMBO_DICTIONARY, g1x, 102, g1xs,  167, MY_COMBO\r
+\r
+  LTEXT     "&Word size:",IDC_STATIC_COMPRESS_ORDER,            m, 125, g0xs, 8\r
+  COMBOBOX  IDC_COMPRESS_COMBO_ORDER,      g1x, 123, g1xs,  141, MY_COMBO\r
+\r
+  LTEXT     "&Solid Block size:",IDC_STATIC_COMPRESS_SOLID,        m, 146, g0xs, 8\r
+  COMBOBOX  IDC_COMPRESS_COMBO_SOLID,      g1x, 144, g1xs,  140, MY_COMBO\r
+\r
+  LTEXT     "&Number of CPU threads:",IDC_STATIC_COMPRESS_THREADS, m, 167, g0xs, 8\r
+  COMBOBOX  IDC_COMPRESS_COMBO_THREADS,   g1x, 165, g1xs - 35,  140, MY_COMBO\r
+  RTEXT     "1", IDC_COMPRESS_HARDWARE_THREADS, g1x + g1xs - 35 + 10, 167, 25, 8\r
+\r
+  \r
+  LTEXT     "Memory usage for Compressing:", IDC_STATIC_COMPRESS_MEMORY,      m, 190, g2xs, 8\r
+  RTEXT     "0", IDC_STATIC_COMPRESS_MEMORY_VALUE,   g3x, 190, g3xs, 8\r
+  \r
+  LTEXT     "Memory usage for Decompressing:", IDC_STATIC_COMPRESS_MEMORY_DE, m, 206, g2xs, 8\r
+  RTEXT     "0",IDC_STATIC_COMPRESS_MEMORY_DE_VALUE, g3x, 206, g3xs, 8\r
+\r
+\r
+  LTEXT     "Split to &volumes, bytes:", IDC_STATIC_COMPRESS_VOLUME, m, 225, gSize, 8\r
+  COMBOBOX  IDC_COMPRESS_COMBO_VOLUME, m, 237, gSize, 73, MY_COMBO_WITH_EDIT\r
+\r
+  LTEXT     "&Parameters:",IDC_STATIC_COMPRESS_PARAMETERS, m, 260, xc, 8\r
+  EDITTEXT  IDC_COMPRESS_EDIT_PARAMETERS, m, 272, xc, 14, ES_AUTOHSCROLL\r
+\r
+  LTEXT     "&Update mode:",IDC_STATIC_COMPRESS_UPDATE_MODE, g4x, 39, g4xs, 8\r
+  COMBOBOX  IDC_COMPRESS_COMBO_UPDATE_MODE, g4x, 51, g4xs, 80, MY_COMBO\r
+\r
+  GROUPBOX  "Options",IDC_STATIC_COMPRESS_OPTIONS, g4x, yOpt, g4xs, 48\r
+  CONTROL   "Create SF&X archive",IDC_COMPRESS_SFX, MY_CHECKBOX,\r
+            g4x2, yOpt + 14, g4xs2, 10\r
+  CONTROL   "Compress shared files",IDC_COMPRESS_SHARED, MY_CHECKBOX,\r
+            g4x2, yOpt + 30, g4xs2, 10\r
+  \r
+  GROUPBOX  "Encryption",IDC_COMPRESS_ENCRYPTION, g4x, yPsw, g4xs, 127\r
+\r
+  LTEXT     "Enter password:",IDC_STATIC_COMPRESS_PASSWORD1, g4x2, yPsw + 14, g4xs2, 8\r
+  EDITTEXT  IDC_COMPRESS_EDIT_PASSWORD1, g4x2, yPsw + 26, g4xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL\r
+  LTEXT     "Reenter password:",IDC_STATIC_COMPRESS_PASSWORD2, g4x2, yPsw + 46, g4xs2, 8\r
+  EDITTEXT  IDC_COMPRESS_EDIT_PASSWORD2, g4x2, yPsw + 58, g4xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL\r
+\r
+  CONTROL   "Show Password",IDC_COMPRESS_CHECK_SHOW_PASSWORD,MY_CHECKBOX,\r
+            g4x2, yPsw + 79, g4xs2, 10\r
+\r
+  LTEXT     "&Encryption method:",IDC_STATIC_COMPRESS_ENCRYPTION_METHOD, g4x2, yPsw + 95, 100, 8\r
+  COMBOBOX  IDC_COMPRESS_COMBO_ENCRYPTION_METHOD, g4x2 + 100, yPsw + 93, g4xs2 - 100,  198, MY_COMBO\r
+\r
+  CONTROL   "Encrypt file &names", IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, MY_CHECKBOX,\r
+            g4x2, yPsw + 111, g4xs2, 10\r
+  \r
+  DEFPUSHBUTTON  "OK",         IDOK, bx3, by, bxs, bys, WS_GROUP\r
+  PUSHBUTTON     "Cancel", IDCANCEL, bx2, by, bxs, bys\r
+  PUSHBUTTON     "Help",     IDHELP, bx1, by, bxs, bys\r
+END\r
+\r
+\r
+#ifdef UNDER_CE\r
+\r
+#undef m\r
+#undef xc\r
+#undef yc\r
+\r
+#define m 4\r
+#define xc 152\r
+#define yc 160\r
+\r
+\r
+IDD_DIALOG_COMPRESS_2 MY_DIALOG\r
+CAPTION "Add to Archive"\r
+MY_FONT\r
+BEGIN\r
+  // LTEXT    "&Archive:", IDC_STATIC_COMPRESS_ARCHIVE, m, m + 1, 32, 8\r
+  COMBOBOX  IDC_COMPRESS_COMBO_ARCHIVE, m, m, xc - bxsDots - m, 126, MY_COMBO_WITH_EDIT\r
+  PUSHBUTTON  "...", IDC_COMPRESS_BUTTON_SET_ARCHIVE, xs - m - bxsDots, m, bxsDots, 12, WS_GROUP\r
+\r
+  COMBOBOX  IDC_COMPRESS_COMBO_FORMAT, m      , 22, 32, 80, MY_COMBO | CBS_SORT\r
+  COMBOBOX  IDC_COMPRESS_COMBO_LEVEL,  m +  36, 22, 68, 80, MY_COMBO\r
+  COMBOBOX  IDC_COMPRESS_COMBO_METHOD, m + 108, 22, 44, 80, MY_COMBO\r
+\r
+  COMBOBOX  IDC_COMPRESS_COMBO_DICTIONARY,    m, 40, 40, 80, MY_COMBO\r
+  COMBOBOX  IDC_COMPRESS_COMBO_ORDER,   m +  44, 40, 32, 80, MY_COMBO\r
+  COMBOBOX  IDC_COMPRESS_COMBO_SOLID,   m +  80, 40, 40, 80, MY_COMBO\r
+  COMBOBOX  IDC_COMPRESS_COMBO_THREADS, m + 124, 40, 28, 80, MY_COMBO\r
+\r
+  LTEXT     "Split to &volumes, bytes:", IDC_STATIC_COMPRESS_VOLUME, m, 60, 32, 8\r
+  COMBOBOX  IDC_COMPRESS_COMBO_VOLUME, m + 32, 58, 44, 73, MY_COMBO_WITH_EDIT\r
+  LTEXT     "&Parameters:",IDC_STATIC_COMPRESS_PARAMETERS, m + 80, 60, 48, 8\r
+  EDITTEXT  IDC_COMPRESS_EDIT_PARAMETERS, m + 128, 58, 24, 13, ES_AUTOHSCROLL\r
+\r
+  COMBOBOX  IDC_COMPRESS_COMBO_UPDATE_MODE, m, 76, 88, 80, MY_COMBO\r
+  CONTROL   "SF&X", IDC_COMPRESS_SFX, MY_CHECKBOX, m + 92, 77, 60, 10\r
+\r
+  CONTROL   "Compress shared files", IDC_COMPRESS_SHARED, MY_CHECKBOX, m, 94, xc, 10\r
+  \r
+  LTEXT     "Enter password:", IDC_STATIC_COMPRESS_PASSWORD1, m, 112, 60, 8\r
+  EDITTEXT  IDC_COMPRESS_EDIT_PASSWORD1, m + 60, 110, 44, 13, ES_PASSWORD | ES_AUTOHSCROLL\r
+  CONTROL   "Show Password", IDC_COMPRESS_CHECK_SHOW_PASSWORD, MY_CHECKBOX, m + 108, 112, 44, 10\r
+\r
+  COMBOBOX  IDC_COMPRESS_COMBO_ENCRYPTION_METHOD, m, 128, 48, 198, MY_COMBO\r
+  CONTROL   "Encrypt file &names", IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, MY_CHECKBOX, m + 52, 130, 100, 10\r
+  \r
+  OK_CANCEL\r
+END\r
+\r
+#endif\r
+\r
+STRINGTABLE\r
+BEGIN\r
+    IDS_METHOD_STORE        "Store"\r
+    IDS_METHOD_NORMAL       "Normal"\r
+    IDS_METHOD_MAXIMUM      "Maximum"\r
+    IDS_METHOD_FAST         "Fast"\r
+    IDS_METHOD_FASTEST      "Fastest"\r
+    IDS_METHOD_ULTRA        "Ultra"\r
+\r
+    IDS_COMPRESS_NON_SOLID "Non-solid"\r
+    IDS_COMPRESS_SOLID "Solid"\r
+\r
+    IDS_COMPRESS_UPDATE_MODE_ADD "Add and replace files"\r
+    IDS_COMPRESS_UPDATE_MODE_UPDATE "Update and add files"\r
+    IDS_COMPRESS_UPDATE_MODE_FRESH "Freshen existing files"\r
+    IDS_COMPRESS_UPDATE_MODE_SYNCHRONIZE "Synchronize files"\r
+    IDS_COMPRESS_SET_ARCHIVE_DIALOG_TITLE "Browse"\r
+    IDS_COMPRESS_SPLIT_CONFIRM_MESSAGE "Specified volume size: {0} bytes.\nAre you sure you want to split archive into such volumes?"\r
+\r
+    IDS_OPEN_TYPE_ALL_FILES "All Files"\r
+\r
+    IDS_PASSWORD_USE_ASCII  "Use only English letters, numbers and special characters (!, #, $, ...) for password."\r
+    IDS_PASSWORD_PASSWORDS_DO_NOT_MATCH  "Passwords do not match"\r
+    IDS_PASSWORD_IS_TOO_LONG "Password is too long"\r
+END\r
diff --git a/CPP/7zip/UI/GUI/CompressDialogRes.h b/CPP/7zip/UI/GUI/CompressDialogRes.h
new file mode 100755 (executable)
index 0000000..2127d4e
--- /dev/null
@@ -0,0 +1,81 @@
+#define IDD_DIALOG_COMPRESS             551\r
+#define IDD_DIALOG_COMPRESS_2           651\r
+#define IDC_STATIC_COMPRESS_MEMORY      1022\r
+#define IDC_STATIC_COMPRESS_MEMORY_DE   1023\r
+#define IDC_STATIC_COMPRESS_MEMORY_VALUE 1027\r
+#define IDC_STATIC_COMPRESS_MEMORY_DE_VALUE 1028\r
+#define IDC_COMPRESS_COMBO_ARCHIVE      1072\r
+#define IDC_COMPRESS_BUTTON_SET_ARCHIVE 1073\r
+#define IDC_COMPRESS_COMBO_LEVEL        1074\r
+#define IDC_COMPRESS_COMBO_UPDATE_MODE  1075\r
+#define IDC_COMPRESS_COMBO_FORMAT       1076\r
+#define IDC_COMPRESS_COMBO_VOLUME       1077\r
+#define IDC_COMPRESS_COMBO_METHOD       1078\r
+#define IDC_COMPRESS_COMBO_DICTIONARY   1079\r
+#define IDC_COMPRESS_COMBO_ORDER        1080\r
+\r
+#define IDC_COMPRESS_COMBO_SOLID        1081\r
+#define IDC_COMPRESS_COMBO_THREADS      1082\r
+#define IDC_COMPRESS_HARDWARE_THREADS   1083\r
+\r
+#define IDC_COMPRESS_SFX                1090\r
+#define IDC_COMPRESS_EDIT_PARAMETERS    1091\r
+\r
+// #define IDC_COMPRESS_SOLID              1092\r
+// #define IDC_COMPRESS_MULTI_THREAD       1093\r
+\r
+#define IDC_STATIC_COMPRESS_ARCHIVE     1097\r
+#define IDC_STATIC_COMPRESS_FORMAT      1098\r
+#define IDC_STATIC_COMPRESS_LEVEL       1099\r
+#define IDC_STATIC_COMPRESS_PARAMETERS  1100\r
+#define IDC_STATIC_COMPRESS_UPDATE_MODE 1101\r
+#define IDC_STATIC_COMPRESS_OPTIONS     1102\r
+#define IDC_STATIC_COMPRESS_VOLUME      1103\r
+#define IDC_STATIC_COMPRESS_METHOD      1104\r
+#define IDC_STATIC_COMPRESS_DICTIONARY  1105\r
+#define IDC_STATIC_COMPRESS_ORDER       1106\r
+\r
+#define IDC_STATIC_COMPRESS_SOLID       1107\r
+#define IDC_STATIC_COMPRESS_THREADS     1108\r
+\r
+#define IDC_COMPRESS_ENCRYPTION         1110\r
+#define IDC_STATIC_COMPRESS_PASSWORD1   1111\r
+#define IDC_COMPRESS_EDIT_PASSWORD1     1112\r
+#define IDC_STATIC_COMPRESS_PASSWORD2   1113\r
+#define IDC_COMPRESS_EDIT_PASSWORD2     1114\r
+#define IDC_COMPRESS_CHECK_SHOW_PASSWORD 1115\r
+\r
+#define IDC_STATIC_COMPRESS_ENCRYPTION_METHOD 1120\r
+#define IDC_COMPRESS_COMBO_ENCRYPTION_METHOD 1121\r
+\r
+#define IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES 1122\r
+\r
+#define IDC_COMPRESS_SHARED    1130\r
+\r
+\r
+#define IDS_OPEN_TYPE_ALL_FILES         80\r
+\r
+#define IDS_METHOD_STORE                81\r
+#define IDS_METHOD_NORMAL               82\r
+#define IDS_METHOD_MAXIMUM              83\r
+#define IDS_METHOD_FAST                 84\r
+#define IDS_METHOD_FASTEST              85\r
+#define IDS_METHOD_ULTRA                86\r
+\r
+#define IDS_COMPRESS_NON_SOLID 88\r
+#define IDS_COMPRESS_SOLID 89\r
+\r
+#define IDS_COMPRESS_UPDATE_MODE_ADD    90\r
+#define IDS_COMPRESS_UPDATE_MODE_UPDATE 91\r
+#define IDS_COMPRESS_UPDATE_MODE_FRESH  92\r
+#define IDS_COMPRESS_UPDATE_MODE_SYNCHRONIZE 93\r
+\r
+#define IDS_COMPRESS_SPLIT_CONFIRM_MESSAGE   94\r
+\r
+#define IDS_COMPRESS_SET_ARCHIVE_DIALOG_TITLE 96\r
+\r
+#define IDS_PASSWORD_USE_ASCII               110\r
+#define IDS_PASSWORD_PASSWORDS_DO_NOT_MATCH  111\r
+#define IDS_PASSWORD_IS_TOO_LONG             112\r
+\r
+#define IDS_COMPRESS_INCORRECT_VOLUME_SIZE   95\r
diff --git a/CPP/7zip/UI/GUI/Extract.rc b/CPP/7zip/UI/GUI/Extract.rc
new file mode 100755 (executable)
index 0000000..72ebe07
--- /dev/null
@@ -0,0 +1,33 @@
+#include "ExtractRes.h"\r
+\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r
+\r
+STRINGTABLE DISCARDABLE\r
+BEGIN\r
+  IDS_UPDATE_NOT_SUPPORTED "Update operations are not supported for this archive."\r
+  IDS_CANNOT_CREATE_FOLDER "Cannot create folder '{0}'"\r
+  IDS_OPEN_IS_NOT_SUPORTED_ARCHIVE "File is not supported archive."\r
+  IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC "CRC failed in '{0}'. File is broken."\r
+  IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR  "Data error in '{0}'. File is broken"\r
+  IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC_ENCRYPTED "CRC failed in encrypted file '{0}'. Wrong password?"\r
+  IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED  "Data error in encrypted file '{0}'. Wrong password?"\r
+  IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_UNSUPPORTED_METHOD  "Unsupported compression method for '{0}'."\r
+  IDS_EXTRACT_SET_FOLDER  "Specify a location for extracted files."\r
+  IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CANNOT_OPEN_FILE  "Can not open output file '{0}'."\r
+  IDS_PROGRESS_EXTRACTING "Extracting"\r
+  IDS_CANT_OPEN_ARCHIVE   "Can not open file '{0}' as archive"\r
+  IDS_CANT_OPEN_ENCRYPTED_ARCHIVE   "Can not open encrypted archive '{0}'. Wrong password?"\r
+  IDS_MEM_ERROR  "The system cannot allocate the required amount of memory"\r
+  IDS_UNKNOWN_ERROR  "Unknown Error"\r
+  IDS_UNSUPPORTED_ARCHIVE_TYPE  "Unsupported archive type"\r
+\r
+  IDC_EXTRACT_RADIO_FULL_PATHNAMES "Full pathnames"\r
+  IDC_EXTRACT_RADIO_CURRENT_PATHNAMES "Current pathnames"\r
+  IDC_EXTRACT_RADIO_NO_PATHNAMES "No pathnames"\r
+\r
+  IDC_EXTRACT_RADIO_ASK_BEFORE_OVERWRITE "Ask before overwrite"\r
+  IDC_EXTRACT_RADIO_OVERWRITE_WITHOUT_PROMPT "Overwrite without prompt"\r
+  IDC_EXTRACT_RADIO_SKIP_EXISTING_FILES "Skip existing files"\r
+  IDC_EXTRACT_RADIO_AUTO_RENAME "Auto rename"\r
+  IDC_EXTRACT_RADIO_AUTO_RENAME_EXISTING "Auto rename existing files"\r
+END\r
diff --git a/CPP/7zip/UI/GUI/ExtractDialog.cpp b/CPP/7zip/UI/GUI/ExtractDialog.cpp
new file mode 100755 (executable)
index 0000000..83b4582
--- /dev/null
@@ -0,0 +1,355 @@
+// ExtractDialog.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+// #include <HtmlHelp.h>\r
+\r
+#include "ExtractDialog.h"\r
+\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/FileName.h"\r
+#include "Windows/FileDir.h"\r
+#include "Windows/ResourceString.h"\r
+\r
+#ifndef NO_REGISTRY\r
+#include "../FileManager/HelpUtils.h"\r
+#endif\r
+\r
+#include "../Common/ZipRegistry.h"\r
+\r
+#include "../FileManager/BrowseDialog.h"\r
+#include "../FileManager/LangUtils.h"\r
+#include "../FileManager/resourceGui.h"\r
+\r
+#include "ExtractRes.h"\r
+#include "ExtractDialogRes.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+using namespace NName;\r
+\r
+extern HINSTANCE g_hInstance;\r
+\r
+static CIDLangPair kPathMode_Pairs[] =\r
+{\r
+  { IDC_EXTRACT_RADIO_FULL_PATHNAMES,    0x02000811 },\r
+  // { IDC_EXTRACT_RADIO_CURRENT_PATHNAMES, 0x02000812 },\r
+  { IDC_EXTRACT_RADIO_NO_PATHNAMES,      0x02000813 }\r
+};\r
+\r
+static CIDLangPair kOverwriteMode_Pairs[] =\r
+{\r
+  { IDC_EXTRACT_RADIO_ASK_BEFORE_OVERWRITE,     0x02000821 },\r
+  { IDC_EXTRACT_RADIO_OVERWRITE_WITHOUT_PROMPT, 0x02000822 },\r
+  { IDC_EXTRACT_RADIO_SKIP_EXISTING_FILES,      0x02000823 },\r
+  { IDC_EXTRACT_RADIO_AUTO_RENAME,              0x02000824 },\r
+  { IDC_EXTRACT_RADIO_AUTO_RENAME_EXISTING,     0x02000825 }\r
+};\r
+\r
+#ifndef _SFX\r
+\r
+static const\r
+  // NExtract::NPathMode::EEnum\r
+  int\r
+  kPathModeButtonsVals[] =\r
+{\r
+  NExtract::NPathMode::kFullPathnames,\r
+  // NExtract::NPathMode::kCurrentPathnames,\r
+  NExtract::NPathMode::kNoPathnames\r
+};\r
+\r
+static const int kOverwriteButtons[] =\r
+{\r
+  IDC_EXTRACT_RADIO_ASK_BEFORE_OVERWRITE,\r
+  IDC_EXTRACT_RADIO_OVERWRITE_WITHOUT_PROMPT,\r
+  IDC_EXTRACT_RADIO_SKIP_EXISTING_FILES,\r
+  IDC_EXTRACT_RADIO_AUTO_RENAME,\r
+  IDC_EXTRACT_RADIO_AUTO_RENAME_EXISTING,\r
+};\r
+\r
+static const\r
+  int\r
+  // NExtract::NOverwriteMode::EEnum\r
+  kOverwriteButtonsVals[] =\r
+{\r
+  NExtract::NOverwriteMode::kAskBefore,\r
+  NExtract::NOverwriteMode::kWithoutPrompt,\r
+  NExtract::NOverwriteMode::kSkipExisting,\r
+  NExtract::NOverwriteMode::kAutoRename,\r
+  NExtract::NOverwriteMode::kAutoRenameExisting\r
+};\r
+\r
+static const int kNumOverwriteButtons = sizeof(kOverwriteButtons) / sizeof(kOverwriteButtons[0]);\r
+\r
+/*\r
+static const int kFilesButtons[] =\r
+{\r
+  IDC_EXTRACT_RADIO_SELECTED_FILES,\r
+  IDC_EXTRACT_RADIO_ALL_FILES\r
+};\r
+static const int kNumFilesButtons = sizeof(kFilesButtons) / sizeof(kFilesButtons[0]);\r
+*/\r
+\r
+/*\r
+int CExtractDialog::GetFilesMode() const\r
+{\r
+  for (int i = 0; i < kNumFilesButtons; i++)\r
+    if (IsButtonCheckedBool(kFilesButtons[i]))\r
+      return i;\r
+  throw 0;\r
+}\r
+*/\r
+\r
+#endif\r
+\r
+#ifdef LANG\r
+static CIDLangPair kIDLangPairs[] =\r
+{\r
+  { IDC_STATIC_EXTRACT_EXTRACT_TO,      0x02000801 },\r
+  { IDC_EXTRACT_PATH_MODE,               0x02000810 },\r
+  { IDC_EXTRACT_OVERWRITE_MODE,          0x02000820 },\r
+  // { IDC_EXTRACT_FILES,                0x02000830 },\r
+  // { IDC_EXTRACT_RADIO_SELECTED_FILES, 0x02000831 },\r
+  // { IDC_EXTRACT_RADIO_ALL_FILES,      0x02000832 },\r
+  { IDC_EXTRACT_PASSWORD,        0x02000802 },\r
+  { IDC_EXTRACT_CHECK_SHOW_PASSWORD, 0x02000B02 },\r
+  { IDOK,     0x02000702 },\r
+  { IDCANCEL, 0x02000710 },\r
+  { IDHELP,   0x02000720 }\r
+\r
+};\r
+#endif\r
+\r
+// static const int kWildcardsButtonIndex = 2;\r
+\r
+#ifndef NO_REGISTRY\r
+static const int kHistorySize = 8;\r
+#endif\r
+\r
+#ifndef _SFX\r
+static void AddComboItems(NWindows::NControl::CComboBox &combo, const CIDLangPair *items, int numItems, const int *values, int curVal)\r
+{\r
+  int curSel = 0;\r
+  for (int i = 0; i < numItems; i++)\r
+  {\r
+    UString s = LangString(items[i].ControlID, items[i].LangID);\r
+    s.Replace(L"&", L"");\r
+    int index = (int)combo.AddString(s);\r
+    combo.SetItemData(index, i);\r
+    if (values[i] == curVal)\r
+      curSel = i;\r
+  }\r
+  combo.SetCurSel(curSel);\r
+}\r
+#endif\r
+\r
+bool CExtractDialog::OnInit()\r
+{\r
+  #ifdef LANG\r
+  LangSetWindowText(HWND(*this), 0x02000800);\r
+  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));\r
+  #endif\r
+  #ifndef _SFX\r
+  _passwordControl.Attach(GetItem(IDC_EXTRACT_EDIT_PASSWORD));\r
+  _passwordControl.SetText(Password);\r
+  _passwordControl.SetPasswordChar(TEXT('*'));\r
+  #endif\r
+\r
+  NExtract::CInfo info;\r
+\r
+  #ifdef NO_REGISTRY\r
+  PathMode = NExtract::NPathMode::kFullPathnames;\r
+  OverwriteMode = NExtract::NOverwriteMode::kAskBefore;\r
+  // info.Paths = NExtract::NPathMode::kFullPathnames;\r
+  #else\r
+  info.Load();\r
+  CheckButton(IDC_EXTRACT_CHECK_SHOW_PASSWORD, info.ShowPassword);\r
+  UpdatePasswordControl();\r
+  PathMode = info.PathMode;\r
+  OverwriteMode = info.OverwriteMode;\r
+  #endif\r
+\r
+  _path.Attach(GetItem(IDC_EXTRACT_COMBO_PATH));\r
+\r
+  _path.SetText(DirectoryPath);\r
+  \r
+  #ifndef NO_REGISTRY\r
+  for (int i = 0; i < info.Paths.Size() && i < kHistorySize; i++)\r
+    _path.AddString(info.Paths[i]);\r
+  #endif\r
+\r
+  /*\r
+  if (info.Paths.Size() > 0)\r
+    _path.SetCurSel(0);\r
+  else\r
+    _path.SetCurSel(-1);\r
+  */\r
+\r
+  #ifndef _SFX\r
+\r
+  _pathMode.Attach(GetItem(IDC_EXTRACT_COMBO_PATH_MODE));\r
+  AddComboItems(_pathMode, kPathMode_Pairs, sizeof(kPathMode_Pairs) / sizeof(kPathMode_Pairs[0]),\r
+      kPathModeButtonsVals, PathMode);\r
+\r
+  _overwriteMode.Attach(GetItem(IDC_EXTRACT_COMBO_OVERWRITE_MODE));\r
+  AddComboItems(_overwriteMode, kOverwriteMode_Pairs, sizeof(kOverwriteMode_Pairs) / sizeof(kOverwriteMode_Pairs[0]),\r
+      kOverwriteButtonsVals, OverwriteMode);\r
+\r
+  /*\r
+  CheckRadioButton(kFilesButtons[0], kFilesButtons[kNumFilesButtons - 1],\r
+      kFilesButtons[_filesMode]);\r
+  */\r
+\r
+  // CWindow selectedFilesWindow = GetItem(IDC_EXTRACT_RADIO_SELECTED_FILES);\r
+  // selectedFilesWindow.Enable(_enableSelectedFilesButton);\r
+\r
+\r
+  #endif\r
+\r
+  HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON));\r
+  SetIcon(ICON_BIG, icon);\r
\r
+  // CWindow filesWindow = GetItem(IDC_EXTRACT_RADIO_FILES);\r
+  // filesWindow.Enable(_enableFilesButton);\r
+\r
+  // UpdateWildCardState();\r
+  NormalizePosition();\r
+\r
+  return CModalDialog::OnInit();\r
+}\r
+\r
+#ifndef _SFX\r
+void CExtractDialog::UpdatePasswordControl()\r
+{\r
+  _passwordControl.SetPasswordChar((IsButtonChecked(\r
+    IDC_EXTRACT_CHECK_SHOW_PASSWORD) == BST_CHECKED) ? 0: TEXT('*'));\r
+  UString password;\r
+  _passwordControl.GetText(password);\r
+  _passwordControl.SetText(password);\r
+}\r
+#endif\r
+\r
+bool CExtractDialog::OnButtonClicked(int buttonID, HWND buttonHWND)\r
+{\r
+  /*\r
+  for (int i = 0; i < kNumFilesButtons; i++)\r
+    if (buttonID == kFilesButtons[i])\r
+    {\r
+      UpdateWildCardState();\r
+      return true;\r
+    }\r
+  */\r
+  switch(buttonID)\r
+  {\r
+    case IDC_EXTRACT_BUTTON_SET_PATH:\r
+      OnButtonSetPath();\r
+      return true;\r
+    #ifndef _SFX\r
+    case IDC_EXTRACT_CHECK_SHOW_PASSWORD:\r
+    {\r
+      UpdatePasswordControl();\r
+      return true;\r
+    }\r
+    #endif\r
+  }\r
+  return CModalDialog::OnButtonClicked(buttonID, buttonHWND);\r
+}\r
+\r
+void CExtractDialog::OnButtonSetPath()\r
+{\r
+  UString currentPath;\r
+  _path.GetText(currentPath);\r
+  UString title = LangStringSpec(IDS_EXTRACT_SET_FOLDER, 0x02000881);\r
+  UString resultPath;\r
+  if (!MyBrowseForFolder(HWND(*this), title, currentPath, resultPath))\r
+    return;\r
+  #ifndef NO_REGISTRY\r
+  _path.SetCurSel(-1);\r
+  #endif\r
+  _path.SetText(resultPath);\r
+}\r
+\r
+void AddUniqueString(UStringVector &list, const UString &s)\r
+{\r
+  for (int i = 0; i < list.Size(); i++)\r
+    if (s.CompareNoCase(list[i]) == 0)\r
+      return;\r
+  list.Add(s);\r
+}\r
+\r
+void CExtractDialog::OnOK()\r
+{\r
+  #ifndef _SFX\r
+  NExtract::NPathMode::EEnum pathMode2 = (NExtract::NPathMode::EEnum)kPathModeButtonsVals[_pathMode.GetItemData(_pathMode.GetCurSel())];\r
+  if (PathMode != NExtract::NPathMode::kCurrentPathnames ||\r
+      pathMode2 != NExtract::NPathMode::kFullPathnames)\r
+    PathMode = pathMode2;\r
+  OverwriteMode = (NExtract::NOverwriteMode::EEnum)kOverwriteButtonsVals[_overwriteMode.GetItemData(_overwriteMode.GetCurSel())];\r
+\r
+  // _filesMode = (NExtractionDialog::NFilesMode::EEnum)GetFilesMode();\r
+\r
+  _passwordControl.GetText(Password);\r
+  #endif\r
+\r
+  NExtract::CInfo info;\r
+  info.PathMode = PathMode;\r
+  info.OverwriteMode = OverwriteMode;\r
+  info.ShowPassword = (IsButtonCheckedBool(IDC_EXTRACT_CHECK_SHOW_PASSWORD));\r
+  \r
+  UString s;\r
+  \r
+  #ifdef NO_REGISTRY\r
+  \r
+  _path.GetText(s);\r
+  \r
+  #else\r
+\r
+  int currentItem = _path.GetCurSel();\r
+  if (currentItem == CB_ERR)\r
+  {\r
+    _path.GetText(s);\r
+    if (_path.GetCount() >= kHistorySize)\r
+      currentItem = _path.GetCount() - 1;\r
+  }\r
+  else\r
+    _path.GetLBText(currentItem, s);\r
+  \r
+  #endif\r
+\r
+  s.Trim();\r
+  #ifndef _SFX\r
+  AddUniqueString(info.Paths, s);\r
+  #endif\r
+  DirectoryPath = s;\r
+  #ifndef  NO_REGISTRY\r
+  for (int i = 0; i < _path.GetCount(); i++)\r
+    if (i != currentItem)\r
+    {\r
+      UString sTemp;\r
+      _path.GetLBText(i, sTemp);\r
+      sTemp.Trim();\r
+      AddUniqueString(info.Paths, sTemp);\r
+    }\r
+  info.Save();\r
+  #endif\r
+  CModalDialog::OnOK();\r
+}\r
+\r
+/*\r
+void CExtractDialog::UpdateWildCardState()\r
+{\r
+  // UpdateData(TRUE);\r
+  // m_Wildcards.EnableWindow(BoolToBOOL(m_Files == kWildcardsButtonIndex));\r
+}\r
+*/\r
+\r
+#ifndef  NO_REGISTRY\r
+static LPCWSTR kHelpTopic = L"fm/plugins/7-zip/extract.htm";\r
+void CExtractDialog::OnHelp()\r
+{\r
+  ShowHelpWindow(NULL, kHelpTopic);\r
+  CModalDialog::OnHelp();\r
+}\r
+#endif\r
+\r
diff --git a/CPP/7zip/UI/GUI/ExtractDialog.h b/CPP/7zip/UI/GUI/ExtractDialog.h
new file mode 100755 (executable)
index 0000000..37e24df
--- /dev/null
@@ -0,0 +1,83 @@
+// ExtractDialog.h\r
+\r
+#ifndef __EXTRACT_DIALOG_H\r
+#define __EXTRACT_DIALOG_H\r
+\r
+#include "ExtractDialogRes.h"\r
+\r
+#include "Windows/Control/Edit.h"\r
+#include "Windows/Control/ComboBox.h"\r
+\r
+#ifndef  NO_REGISTRY\r
+#include "../Common/ZipRegistry.h"\r
+#endif\r
+#include "../Common/ExtractMode.h"\r
+\r
+#include "../FileManager/DialogSize.h"\r
+\r
+namespace NExtractionDialog\r
+{\r
+  /*\r
+  namespace NFilesMode\r
+  {\r
+    enum EEnum\r
+    {\r
+      kSelected,\r
+      kAll,\r
+      kSpecified\r
+    };\r
+  }\r
+  */\r
+}\r
+\r
+class CExtractDialog: public NWindows::NControl::CModalDialog\r
+{\r
+  #ifdef NO_REGISTRY\r
+  NWindows::NControl::CDialogChildControl _path;\r
+  #else\r
+  NWindows::NControl::CComboBox _path;\r
+  #endif\r
+  \r
+  #ifndef _SFX\r
+  NWindows::NControl::CEdit _passwordControl;\r
+  NWindows::NControl::CComboBox _pathMode;\r
+  NWindows::NControl::CComboBox _overwriteMode;\r
+  #endif\r
+\r
+  #ifndef _SFX\r
+  // int GetFilesMode() const;\r
+  void UpdatePasswordControl();\r
+  #endif\r
+  \r
+  void OnButtonSetPath();\r
+\r
+  virtual bool OnInit();\r
+  virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);\r
+  virtual void OnOK();\r
+  #ifndef  NO_REGISTRY\r
+  virtual void OnHelp();\r
+  #endif\r
+public:\r
+  // bool _enableSelectedFilesButton;\r
+  // bool _enableFilesButton;\r
+  // NExtractionDialog::NFilesMode::EEnum FilesMode;\r
+\r
+  UString DirectoryPath;\r
+  #ifndef _SFX\r
+  UString Password;\r
+  #endif\r
+  NExtract::NPathMode::EEnum PathMode;\r
+  NExtract::NOverwriteMode::EEnum OverwriteMode;\r
+\r
+  INT_PTR Create(HWND aWndParent = 0)\r
+  {\r
+    #ifdef _SFX\r
+    BIG_DIALOG_SIZE(240, 64);\r
+    #else\r
+    BIG_DIALOG_SIZE(300, 160);\r
+    #endif\r
+    return CModalDialog::Create(SIZED_DIALOG(IDD_DIALOG_EXTRACT), aWndParent);\r
+  }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/GUI/ExtractDialog.rc b/CPP/7zip/UI/GUI/ExtractDialog.rc
new file mode 100755 (executable)
index 0000000..656b264
--- /dev/null
@@ -0,0 +1,83 @@
+#include "ExtractDialogRes.h"\r
+#include "../../GuiCommon.rc"\r
+\r
+#define xc 280\r
+#define yc 128\r
+\r
+#undef g1xs\r
+#undef g2x\r
+#undef g2x2\r
+#undef g2xs\r
+#undef g2xs2\r
+\r
+#define g1xs 128\r
+\r
+#define gSpace 24\r
+#define g2x (m + g1xs + gSpace)\r
+#define g2x2 (g2x + m)\r
+#define g2xs (xc - g1xs - gSpace)\r
+#define g2xs2 (g2xs - m - m)\r
+\r
+IDD_DIALOG_EXTRACT MY_DIALOG\r
+CAPTION "Extract"\r
+BEGIN\r
+  LTEXT      "E&xtract to:", IDC_STATIC_EXTRACT_EXTRACT_TO, m, m, xc, 8\r
+  COMBOBOX   IDC_EXTRACT_COMBO_PATH, m, m + 12, xc - bxsDots - 12, 100, MY_COMBO_WITH_EDIT\r
+  PUSHBUTTON "...", IDC_EXTRACT_BUTTON_SET_PATH, xs - m - bxsDots, m + 12 - 2, bxsDots, bys, WS_GROUP\r
+\r
+  LTEXT      "Path mode:", IDC_EXTRACT_PATH_MODE, m, m + 36, g1xs, 8\r
+  COMBOBOX   IDC_EXTRACT_COMBO_PATH_MODE, m, m + 48, g1xs, 140, MY_COMBO\r
+\r
+  LTEXT      "Overwrite mode:", IDC_EXTRACT_OVERWRITE_MODE, m, m + 68, g1xs, 8\r
+  COMBOBOX   IDC_EXTRACT_COMBO_OVERWRITE_MODE, m, m + 80, g1xs, 140, MY_COMBO\r
+\r
+  #ifdef UNDER_CE\r
+  LTEXT "Password", IDC_EXTRACT_PASSWORD, g2x, m + 36, g2xs, 8\r
+  #else\r
+  GROUPBOX "Password", IDC_EXTRACT_PASSWORD, g2x, m + 36, g2xs, 56\r
+  #endif\r
+  EDITTEXT IDC_EXTRACT_EDIT_PASSWORD, g2x2, m + 50, g2xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL\r
+  CONTROL "Show Password", IDC_EXTRACT_CHECK_SHOW_PASSWORD, MY_CHECKBOX, g2x2, m + 72, g2xs2, 10\r
+  \r
+  DEFPUSHBUTTON  "OK",         IDOK, bx3, by, bxs, bys, WS_GROUP\r
+  PUSHBUTTON     "Cancel", IDCANCEL, bx2, by, bxs, bys\r
+  PUSHBUTTON     "Help",     IDHELP, bx1, by, bxs, bys\r
+END\r
+\r
+\r
+#ifdef UNDER_CE\r
+\r
+#undef m\r
+#define m 4\r
+\r
+#undef xc\r
+#undef yc\r
+\r
+#define xc 152\r
+#define yc 128\r
+\r
+#undef g1xs\r
+\r
+#define g1xs 64\r
+\r
+IDD_DIALOG_EXTRACT_2 MY_DIALOG\r
+CAPTION "Extract"\r
+BEGIN\r
+  LTEXT    "E&xtract to:", IDC_STATIC_EXTRACT_EXTRACT_TO, m, m, xc - bxsDots - 8, 8\r
+  COMBOBOX   IDC_EXTRACT_COMBO_PATH, m, m + 12, xc - bxsDots - 8, 100, MY_COMBO_WITH_EDIT\r
+  PUSHBUTTON "...", IDC_EXTRACT_BUTTON_SET_PATH, xs - m - bxsDots, m + 12 - 3, bxsDots, bys, WS_GROUP\r
+\r
+  LTEXT     "Path mode:", IDC_EXTRACT_PATH_MODE, m, m + 36, g1xs, 8\r
+  COMBOBOX  IDC_EXTRACT_COMBO_PATH_MODE, m + g1xs, m + 36, xc - g1xs, 100, MY_COMBO\r
+\r
+  LTEXT     "Overwrite mode:", IDC_EXTRACT_OVERWRITE_MODE, m, m + 56, g1xs, 8\r
+  COMBOBOX  IDC_EXTRACT_COMBO_OVERWRITE_MODE, m + g1xs, m + 56, xc - g1xs, 100, MY_COMBO\r
+\r
+  LTEXT "Password", IDC_EXTRACT_PASSWORD, m, m + 76, g1xs, 8\r
+  EDITTEXT IDC_EXTRACT_EDIT_PASSWORD, m + g1xs, m + 76, xc - g1xs, 14, ES_PASSWORD | ES_AUTOHSCROLL\r
+  CONTROL  "Show Password", IDC_EXTRACT_CHECK_SHOW_PASSWORD, MY_CHECKBOX, m, m + 92, xc, 10\r
+  \r
+  OK_CANCEL\r
+END\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/GUI/ExtractDialogRes.h b/CPP/7zip/UI/GUI/ExtractDialogRes.h
new file mode 100755 (executable)
index 0000000..3039561
--- /dev/null
@@ -0,0 +1,19 @@
+#define IDD_DIALOG_EXTRACT              552\r
+#define IDD_DIALOG_EXTRACT_2            652\r
+\r
+#define IDC_STATIC_EXTRACT_EXTRACT_TO   1020\r
+#define IDC_EXTRACT_COMBO_PATH          1021\r
+#define IDC_EXTRACT_BUTTON_SET_PATH     1022\r
+\r
+#define IDC_EXTRACT_COMBO_PATH_MODE 1030\r
+#define IDC_EXTRACT_COMBO_OVERWRITE_MODE 1031\r
+\r
+#define IDC_EXTRACT_PATH_MODE           1040\r
+#define IDC_EXTRACT_OVERWRITE_MODE      1050\r
+\r
+#define IDC_EXTRACT_FILES               1060\r
+\r
+#define IDC_EXTRACT_PASSWORD            1100\r
+#define IDC_EXTRACT_EDIT_PASSWORD       1101\r
+#define IDC_EXTRACT_CHECK_SHOW_PASSWORD 1102\r
+\r
diff --git a/CPP/7zip/UI/GUI/ExtractGUI.cpp b/CPP/7zip/UI/GUI/ExtractGUI.cpp
new file mode 100755 (executable)
index 0000000..e9846cc
--- /dev/null
@@ -0,0 +1,205 @@
+// ExtractGUI.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/Error.h"\r
+#include "Windows/FileDir.h"\r
+#include "Windows/FileFind.h"\r
+#include "Windows/Thread.h"\r
+\r
+#include "../FileManager/ExtractCallback.h"\r
+#include "../FileManager/FormatUtils.h"\r
+#include "../FileManager/LangUtils.h"\r
+#include "../FileManager/resourceGui.h"\r
+\r
+#include "../Common/ArchiveExtractCallback.h"\r
+#include "../Common/PropIDUtils.h"\r
+\r
+#include "../Explorer/MyMessages.h"\r
+\r
+#include "resource2.h"\r
+#include "ExtractRes.h"\r
+\r
+#include "ExtractDialog.h"\r
+#include "ExtractGUI.h"\r
+\r
+using namespace NWindows;\r
+\r
+static const wchar_t *kIncorrectOutDir = L"Incorrect output directory path";\r
+\r
+#ifndef _SFX\r
+\r
+static void AddValuePair(UINT resourceID, UInt32 langID, UInt64 value, UString &s)\r
+{\r
+  wchar_t sz[32];\r
+  s += LangString(resourceID, langID);\r
+  s += L' ';\r
+  ConvertUInt64ToString(value, sz);\r
+  s += sz;\r
+  s += L'\n';\r
+}\r
+\r
+static void AddSizePair(UINT resourceID, UInt32 langID, UInt64 value, UString &s)\r
+{\r
+  wchar_t sz[32];\r
+  s += LangString(resourceID, langID);\r
+  s += L' ';\r
+  ConvertUInt64ToString(value, sz);\r
+  s += sz;\r
+  ConvertUInt64ToString(value >> 20, sz);\r
+  s += L" (";\r
+  s += sz;\r
+  s += L" MB)";\r
+  s += L'\n';\r
+}\r
+\r
+#endif\r
+\r
+class CThreadExtracting: public CProgressThreadVirt\r
+{\r
+  HRESULT ProcessVirt();\r
+public:\r
+  CCodecs *codecs;\r
+  CExtractCallbackImp *ExtractCallbackSpec;\r
+  CIntVector FormatIndices;\r
+\r
+  UStringVector *ArchivePaths;\r
+  UStringVector *ArchivePathsFull;\r
+  const NWildcard::CCensorNode *WildcardCensor;\r
+  const CExtractOptions *Options;\r
+  CMyComPtr<IExtractCallbackUI> ExtractCallback;\r
+  UString Title;\r
+};\r
+\r
+HRESULT CThreadExtracting::ProcessVirt()\r
+{\r
+  CDecompressStat Stat;\r
+  HRESULT res = DecompressArchives(codecs, FormatIndices, *ArchivePaths, *ArchivePathsFull,\r
+      *WildcardCensor, *Options, ExtractCallbackSpec, ExtractCallback, ErrorMessage, Stat);\r
+  #ifndef _SFX\r
+  if (Options->TestMode && ExtractCallbackSpec->IsOK())\r
+  {\r
+    UString s;\r
+    AddValuePair(IDS_ARCHIVES_COLON, 0x02000324, Stat.NumArchives, s);\r
+    AddValuePair(IDS_FOLDERS_COLON, 0x02000321, Stat.NumFolders, s);\r
+    AddValuePair(IDS_FILES_COLON, 0x02000320, Stat.NumFiles, s);\r
+    AddSizePair(IDS_SIZE_COLON, 0x02000322, Stat.UnpackSize, s);\r
+    AddSizePair(IDS_COMPRESSED_COLON, 0x02000323, Stat.PackSize, s);\r
+    \r
+    if (Options->CalcCrc)\r
+    {\r
+      wchar_t temp[16];\r
+      ConvertUInt32ToHex(Stat.CrcSum, temp);\r
+      s += L"CRC: ";\r
+      s += temp;\r
+      s += L'\n';\r
+    }\r
+    \r
+    s += L'\n';\r
+    s += LangString(IDS_MESSAGE_NO_ERRORS, 0x02000608);\r
+    \r
+    OkMessageTitle = Title;\r
+    OkMessage = s;\r
+  }\r
+  #endif\r
+  return res;\r
+}\r
+\r
+HRESULT ExtractGUI(\r
+    CCodecs *codecs,\r
+    const CIntVector &formatIndices,\r
+    UStringVector &archivePaths,\r
+    UStringVector &archivePathsFull,\r
+    const NWildcard::CCensorNode &wildcardCensor,\r
+    CExtractOptions &options,\r
+    bool showDialog,\r
+    bool &messageWasDisplayed,\r
+    CExtractCallbackImp *extractCallback,\r
+    HWND hwndParent)\r
+{\r
+  messageWasDisplayed = false;\r
+\r
+  CThreadExtracting extracter;\r
+  extracter.codecs = codecs;\r
+  extracter.FormatIndices = formatIndices;\r
+\r
+  if (!options.TestMode)\r
+  {\r
+    UString outputDir = options.OutputDir;\r
+    #ifndef UNDER_CE\r
+    if (outputDir.IsEmpty())\r
+      NFile::NDirectory::MyGetCurrentDirectory(outputDir);\r
+    #endif\r
+    if (showDialog)\r
+    {\r
+      CExtractDialog dialog;\r
+      if (!NFile::NDirectory::MyGetFullPathName(outputDir, dialog.DirectoryPath))\r
+      {\r
+        ShowErrorMessage(kIncorrectOutDir);\r
+        messageWasDisplayed = true;\r
+        return E_FAIL;\r
+      }\r
+      NFile::NName::NormalizeDirPathPrefix(dialog.DirectoryPath);\r
+\r
+      // dialog.OverwriteMode = options.OverwriteMode;\r
+      // dialog.PathMode = options.PathMode;\r
+\r
+      if (dialog.Create(hwndParent) != IDOK)\r
+        return E_ABORT;\r
+      outputDir = dialog.DirectoryPath;\r
+      options.OverwriteMode = dialog.OverwriteMode;\r
+      options.PathMode = dialog.PathMode;\r
+      #ifndef _SFX\r
+      extractCallback->Password = dialog.Password;\r
+      extractCallback->PasswordIsDefined = !dialog.Password.IsEmpty();\r
+      #endif\r
+    }\r
+    if (!NFile::NDirectory::MyGetFullPathName(outputDir, options.OutputDir))\r
+    {\r
+      ShowErrorMessage(kIncorrectOutDir);\r
+      messageWasDisplayed = true;\r
+      return E_FAIL;\r
+    }\r
+    NFile::NName::NormalizeDirPathPrefix(options.OutputDir);\r
+    \r
+    /*\r
+    if(!NFile::NDirectory::CreateComplexDirectory(options.OutputDir))\r
+    {\r
+      UString s = GetUnicodeString(NError::MyFormatMessage(GetLastError()));\r
+      UString s2 = MyFormatNew(IDS_CANNOT_CREATE_FOLDER,\r
+      #ifdef LANG\r
+      0x02000603,\r
+      #endif\r
+      options.OutputDir);\r
+      MyMessageBox(s2 + UString(L'\n') + s);\r
+      return E_FAIL;\r
+    }\r
+    */\r
+  }\r
+  \r
+  UString title = LangStringSpec(options.TestMode ? IDS_PROGRESS_TESTING : IDS_PROGRESS_EXTRACTING,\r
+      options.TestMode ? 0x02000F90: 0x02000890);\r
+\r
+  extracter.Title = title;\r
+  extracter.ExtractCallbackSpec = extractCallback;\r
+  extracter.ExtractCallbackSpec->ProgressDialog = &extracter.ProgressDialog;\r
+  extracter.ExtractCallback = extractCallback;\r
+  extracter.ExtractCallbackSpec->Init();\r
+\r
+  extracter.ProgressDialog.CompressingMode = false;\r
+\r
+  extracter.ArchivePaths = &archivePaths;\r
+  extracter.ArchivePathsFull = &archivePathsFull;\r
+  extracter.WildcardCensor = &wildcardCensor;\r
+  extracter.Options = &options;\r
+\r
+  extracter.ProgressDialog.IconID = IDI_ICON;\r
+\r
+  RINOK(extracter.Create(title, hwndParent));\r
+  messageWasDisplayed = extracter.ThreadFinishedOK &\r
+      extracter.ProgressDialog.MessagesDisplayed;\r
+  return extracter.Result;\r
+}\r
diff --git a/CPP/7zip/UI/GUI/ExtractGUI.h b/CPP/7zip/UI/GUI/ExtractGUI.h
new file mode 100755 (executable)
index 0000000..0c34cb0
--- /dev/null
@@ -0,0 +1,34 @@
+// GUI/ExtractGUI.h\r
+\r
+#ifndef __EXTRACT_GUI_H\r
+#define __EXTRACT_GUI_H\r
+\r
+#include "../Common/Extract.h"\r
+\r
+#include "../FileManager/ExtractCallback.h"\r
+\r
+/*\r
+  RESULT can be S_OK, even if there are errors!!!\r
+  if RESULT == S_OK, check extractCallback->IsOK() after ExtractGUI().\r
+\r
+  RESULT = E_ABORT - user break.\r
+  RESULT != E_ABORT:\r
+  {\r
+   messageWasDisplayed = true  - message was displayed already.\r
+   messageWasDisplayed = false - there was some internal error, so you must show error message.\r
+  }\r
+*/\r
+\r
+HRESULT ExtractGUI(\r
+    CCodecs *codecs,\r
+    const CIntVector &formatIndices,\r
+    UStringVector &archivePaths,\r
+    UStringVector &archivePathsFull,\r
+    const NWildcard::CCensorNode &wildcardCensor,\r
+    CExtractOptions &options,\r
+    bool showDialog,\r
+    bool &messageWasDisplayed,\r
+    CExtractCallbackImp *extractCallback,\r
+    HWND hwndParent = NULL);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/GUI/ExtractRes.h b/CPP/7zip/UI/GUI/ExtractRes.h
new file mode 100755 (executable)
index 0000000..3c287bb
--- /dev/null
@@ -0,0 +1,29 @@
+#define IDS_UPDATE_NOT_SUPPORTED 199\r
+#define IDS_CANNOT_CREATE_FOLDER  200\r
+#define IDS_OPEN_IS_NOT_SUPORTED_ARCHIVE  201\r
+\r
+#define IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC  202\r
+#define IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR  203\r
+#define IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_UNSUPPORTED_METHOD  204\r
+#define IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC_ENCRYPTED  205\r
+#define IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED  206\r
+\r
+#define IDS_EXTRACT_SET_FOLDER  207\r
+#define IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CANNOT_OPEN_FILE  208\r
+#define IDS_PROGRESS_EXTRACTING  209\r
+\r
+#define IDS_CANT_OPEN_ARCHIVE   103\r
+#define IDS_CANT_OPEN_ENCRYPTED_ARCHIVE 104\r
+#define IDS_MEM_ERROR 105\r
+#define IDS_UNKNOWN_ERROR 106\r
+#define IDS_UNSUPPORTED_ARCHIVE_TYPE 107\r
+\r
+#define IDC_EXTRACT_RADIO_FULL_PATHNAMES 1041\r
+#define IDC_EXTRACT_RADIO_CURRENT_PATHNAMES 1042\r
+#define IDC_EXTRACT_RADIO_NO_PATHNAMES 1043\r
+\r
+#define IDC_EXTRACT_RADIO_ASK_BEFORE_OVERWRITE 1051\r
+#define IDC_EXTRACT_RADIO_OVERWRITE_WITHOUT_PROMPT 1052\r
+#define IDC_EXTRACT_RADIO_SKIP_EXISTING_FILES 1053\r
+#define IDC_EXTRACT_RADIO_AUTO_RENAME 1056\r
+#define IDC_EXTRACT_RADIO_AUTO_RENAME_EXISTING 1057\r
diff --git a/CPP/7zip/UI/GUI/FM.ico b/CPP/7zip/UI/GUI/FM.ico
new file mode 100755 (executable)
index 0000000..3a0a34d
Binary files /dev/null and b/CPP/7zip/UI/GUI/FM.ico differ
diff --git a/CPP/7zip/UI/GUI/GUI.cpp b/CPP/7zip/UI/GUI/GUI.cpp
new file mode 100755 (executable)
index 0000000..ba59ddf
--- /dev/null
@@ -0,0 +1,283 @@
+// GUI.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/MyInitGuid.h"\r
+\r
+#include "../../../../C/Alloc.h"\r
+\r
+#include "Common/CommandLineParser.h"\r
+#include "Common/MyException.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/Error.h"\r
+#include "Windows/NtCheck.h"\r
+#ifdef _WIN32\r
+#include "Windows/MemoryLock.h"\r
+#endif\r
+\r
+#include "../Common/ArchiveCommandLine.h"\r
+#include "../Common/ExitCode.h"\r
+\r
+#include "../FileManager/StringUtils.h"\r
+\r
+#include "BenchmarkDialog.h"\r
+#include "ExtractGUI.h"\r
+#include "UpdateGUI.h"\r
+\r
+#include "ExtractRes.h"\r
+\r
+using namespace NWindows;\r
+\r
+HINSTANCE g_hInstance;\r
+#ifndef _UNICODE\r
+#endif\r
+\r
+#ifdef UNDER_CE\r
+bool g_LVN_ITEMACTIVATE_Support = true;\r
+#endif\r
+\r
+static void ErrorMessage(LPCWSTR message)\r
+{\r
+  MessageBoxW(NULL, message, L"7-Zip", MB_ICONERROR | MB_OK);\r
+}\r
+\r
+static void ErrorLangMessage(UINT resourceID, UInt32 langID)\r
+{\r
+  ErrorMessage(LangString(resourceID, langID));\r
+}\r
+\r
+static const char *kNoFormats = "7-Zip cannot find the code that works with archives.";\r
+\r
+static int ShowMemErrorMessage()\r
+{\r
+  ErrorLangMessage(IDS_MEM_ERROR, 0x0200060B);\r
+  return NExitCode::kMemoryError;\r
+}\r
+\r
+static int ShowSysErrorMessage(DWORD errorCode)\r
+{\r
+  if (errorCode == E_OUTOFMEMORY)\r
+    return ShowMemErrorMessage();\r
+  ErrorMessage(HResultToMessage(errorCode));\r
+  return NExitCode::kFatalError;\r
+}\r
+\r
+static int Main2()\r
+{\r
+  UStringVector commandStrings;\r
+  NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);\r
+\r
+  #ifndef UNDER_CE\r
+  if (commandStrings.Size() > 0)\r
+    commandStrings.Delete(0);\r
+  #endif\r
+  if (commandStrings.Size() == 0)\r
+  {\r
+    MessageBoxW(0, L"Specify command", L"7-Zip", 0);\r
+    return 0;\r
+  }\r
+\r
+  CArchiveCommandLineOptions options;\r
+  CArchiveCommandLineParser parser;\r
+\r
+  parser.Parse1(commandStrings, options);\r
+  parser.Parse2(options);\r
+\r
+  #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)\r
+  if (options.LargePages)\r
+    NSecurity::EnableLockMemoryPrivilege();\r
+  #endif\r
+\r
+  CCodecs *codecs = new CCodecs;\r
+  CMyComPtr<IUnknown> compressCodecsInfo = codecs;\r
+  HRESULT result = codecs->Load();\r
+  if (result != S_OK)\r
+    throw CSystemException(result);\r
+  \r
+  bool isExtractGroupCommand = options.Command.IsFromExtractGroup();\r
+  if (codecs->Formats.Size() == 0 &&\r
+        (isExtractGroupCommand ||\r
+        options.Command.IsFromUpdateGroup()))\r
+    throw kNoFormats;\r
+\r
+  CIntVector formatIndices;\r
+  if (!codecs->FindFormatForArchiveType(options.ArcType, formatIndices))\r
+  {\r
+    ErrorLangMessage(IDS_UNSUPPORTED_ARCHIVE_TYPE, 0x0200060D);\r
+    return NExitCode::kFatalError;\r
+  }\r
\r
+  if (options.Command.CommandType == NCommandType::kBenchmark)\r
+  {\r
+    HRESULT res;\r
+    #ifdef EXTERNAL_CODECS\r
+    CObjectVector<CCodecInfoEx> externalCodecs;\r
+    res = LoadExternalCodecs(codecs, externalCodecs);\r
+    if (res != S_OK)\r
+      throw CSystemException(res);\r
+    #endif\r
+    res = Benchmark(\r
+      #ifdef EXTERNAL_CODECS\r
+      codecs, &externalCodecs,\r
+      #endif\r
+      options.NumThreads, options.DictionarySize);\r
+    if (res != S_OK)\r
+      throw CSystemException(res);\r
+  }\r
+  else if (isExtractGroupCommand)\r
+  {\r
+    CExtractCallbackImp *ecs = new CExtractCallbackImp;\r
+    CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;\r
+\r
+    #ifndef _NO_CRYPTO\r
+    ecs->PasswordIsDefined = options.PasswordEnabled;\r
+    ecs->Password = options.Password;\r
+    #endif\r
+\r
+    ecs->Init();\r
+\r
+    CExtractOptions eo;\r
+    eo.StdOutMode = options.StdOutMode;\r
+    eo.OutputDir = options.OutputDir;\r
+    eo.YesToAll = options.YesToAll;\r
+    eo.OverwriteMode = options.OverwriteMode;\r
+    eo.PathMode = options.Command.GetPathMode();\r
+    eo.TestMode = options.Command.IsTestMode();\r
+    eo.CalcCrc = options.CalcCrc;\r
+    #if !defined(_7ZIP_ST) && !defined(_SFX)\r
+    eo.Properties = options.ExtractProperties;\r
+    #endif\r
+\r
+    bool messageWasDisplayed = false;\r
+    HRESULT result = ExtractGUI(codecs, formatIndices,\r
+          options.ArchivePathsSorted,\r
+          options.ArchivePathsFullSorted,\r
+          options.WildcardCensor.Pairs.Front().Head,\r
+          eo, options.ShowDialog, messageWasDisplayed, ecs);\r
+    if (result != S_OK)\r
+    {\r
+      if (result != E_ABORT && messageWasDisplayed)\r
+        return NExitCode::kFatalError;\r
+      throw CSystemException(result);\r
+    }\r
+    if (!ecs->IsOK())\r
+      return NExitCode::kFatalError;\r
+  }\r
+  else if (options.Command.IsFromUpdateGroup())\r
+  {\r
+    #ifndef _NO_CRYPTO\r
+    bool passwordIsDefined = options.PasswordEnabled && !options.Password.IsEmpty();\r
+    #endif\r
+\r
+    CUpdateCallbackGUI callback;\r
+    // callback.EnablePercents = options.EnablePercents;\r
+\r
+    #ifndef _NO_CRYPTO\r
+    callback.PasswordIsDefined = passwordIsDefined;\r
+    callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty();\r
+    callback.Password = options.Password;\r
+    #endif\r
+\r
+    // callback.StdOutMode = options.UpdateOptions.StdOutMode;\r
+    callback.Init();\r
+\r
+    if (!options.UpdateOptions.Init(codecs, formatIndices, options.ArchiveName))\r
+    {\r
+      ErrorLangMessage(IDS_UPDATE_NOT_SUPPORTED, 0x02000601);\r
+      return NExitCode::kFatalError;\r
+    }\r
+    bool messageWasDisplayed = false;\r
+    HRESULT result = UpdateGUI(\r
+        codecs,\r
+        options.WildcardCensor, options.UpdateOptions,\r
+        options.ShowDialog,\r
+        messageWasDisplayed, &callback);\r
+\r
+    if (result != S_OK)\r
+    {\r
+      if (result != E_ABORT && messageWasDisplayed)\r
+        return NExitCode::kFatalError;\r
+      throw CSystemException(result);\r
+    }\r
+    if (callback.FailedFiles.Size() > 0)\r
+    {\r
+      if (!messageWasDisplayed)\r
+        throw CSystemException(E_FAIL);\r
+      return NExitCode::kWarning;\r
+    }\r
+  }\r
+  else\r
+  {\r
+    throw "Unsupported command";\r
+  }\r
+  return 0;\r
+}\r
+\r
+#define NT_CHECK_FAIL_ACTION ErrorMessage(L"Unsupported Windows version"); return NExitCode::kFatalError;\r
+\r
+int APIENTRY WinMain(HINSTANCE  hInstance, HINSTANCE /* hPrevInstance */,\r
+  #ifdef UNDER_CE\r
+  LPWSTR\r
+  #else\r
+  LPSTR\r
+  #endif\r
+  /* lpCmdLine */, int /* nCmdShow */)\r
+{\r
+  g_hInstance = hInstance;\r
+  #ifdef _WIN32\r
+  NT_CHECK\r
+  SetLargePageSize();\r
+  #endif\r
+\r
+  InitCommonControls();\r
+\r
+  ReloadLang();\r
+\r
+  // setlocale(LC_COLLATE, ".ACP");\r
+  try\r
+  {\r
+    return Main2();\r
+  }\r
+  catch(const CNewException &)\r
+  {\r
+    return ShowMemErrorMessage();\r
+  }\r
+  catch(const CArchiveCommandLineException &e)\r
+  {\r
+    ErrorMessage(GetUnicodeString(e));\r
+    return NExitCode::kUserError;\r
+  }\r
+  catch(const CSystemException &systemError)\r
+  {\r
+    if (systemError.ErrorCode == E_ABORT)\r
+      return NExitCode::kUserBreak;\r
+    return ShowSysErrorMessage(systemError.ErrorCode);\r
+  }\r
+  catch(const UString &s)\r
+  {\r
+    ErrorMessage(s);\r
+    return NExitCode::kFatalError;\r
+  }\r
+  catch(const AString &s)\r
+  {\r
+    ErrorMessage(GetUnicodeString(s));\r
+    return NExitCode::kFatalError;\r
+  }\r
+  catch(const wchar_t *s)\r
+  {\r
+    ErrorMessage(s);\r
+    return NExitCode::kFatalError;\r
+  }\r
+  catch(const char *s)\r
+  {\r
+    ErrorMessage(GetUnicodeString(s));\r
+    return NExitCode::kFatalError;\r
+  }\r
+  catch(...)\r
+  {\r
+    ErrorLangMessage(IDS_UNKNOWN_ERROR, 0x0200060C);\r
+    return NExitCode::kFatalError;\r
+  }\r
+}\r
+\r
diff --git a/CPP/7zip/UI/GUI/GUI.dsp b/CPP/7zip/UI/GUI/GUI.dsp
new file mode 100755 (executable)
index 0000000..422b5d4
--- /dev/null
@@ -0,0 +1,1018 @@
+# Microsoft Developer Studio Project File - Name="GUI" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Application" 0x0101\r
+\r
+CFG=GUI - Win32 DebugU\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "GUI.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "GUI.mak" CFG="GUI - Win32 DebugU"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "GUI - Win32 Release" (based on "Win32 (x86) Application")\r
+!MESSAGE "GUI - Win32 Debug" (based on "Win32 (x86) Application")\r
+!MESSAGE "GUI - Win32 ReleaseU" (based on "Win32 (x86) Application")\r
+!MESSAGE "GUI - Win32 DebugU" (based on "Win32 (x86) Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+MTL=midl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "GUI - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c\r
+# 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\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-Zip\7zg.exe" /opt:NOWIN98\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "GUI - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c\r
+# 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\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x419 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-Zip\7zg.exe" /pdbtype:sept\r
+\r
+!ELSEIF  "$(CFG)" == "GUI - Win32 ReleaseU"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "ReleaseU"\r
+# PROP BASE Intermediate_Dir "ReleaseU"\r
+# PROP BASE Ignore_Export_Lib 0\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "ReleaseU"\r
+# PROP Intermediate_Dir "ReleaseU"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c\r
+# 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\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "NDEBUG"\r
+# ADD RSC /l 0x419 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\UTIL\7zg.exe"\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-Zip\7zgn.exe" /opt:NOWIN98\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "GUI - Win32 DebugU"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "DebugU"\r
+# PROP BASE Intermediate_Dir "DebugU"\r
+# PROP BASE Ignore_Export_Lib 0\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "DebugU"\r
+# PROP Intermediate_Dir "DebugU"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c\r
+# 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\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x419 /d "_DEBUG"\r
+# ADD RSC /l 0x419 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\UTIL\7zg.exe" /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-Zip\7zgn.exe" /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "GUI - Win32 Release"\r
+# Name "GUI - Win32 Debug"\r
+# Name "GUI - Win32 ReleaseU"\r
+# Name "GUI - Win32 DebugU"\r
+# Begin Group "Spec"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\7zG.exe.manifest\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\FM.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\resource.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\resource.rc\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.cpp\r
+# ADD CPP /Yc"stdafx.h"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\StdAfx.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "UI Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveCommandLine.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveCommandLine.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveExtractCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveExtractCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveOpenCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ArchiveOpenCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\Bench.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\Bench.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\DefaultName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\DefaultName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\DirItem.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\EnumDirItems.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\EnumDirItems.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ExitCode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\Extract.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\Extract.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ExtractingFilePath.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ExtractingFilePath.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ExtractMode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\HandlerLoader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\IFileExtractCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\LoadCodecs.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\LoadCodecs.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\OpenArchive.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\OpenArchive.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\Property.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\PropIDUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\PropIDUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\SetProperties.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\SetProperties.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\SortUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\SortUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\TempFiles.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\TempFiles.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\Update.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\Update.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateAction.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateAction.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdatePair.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdatePair.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateProduce.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\UpdateProduce.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\WorkDir.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\WorkDir.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ZipRegistry.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Common\ZipRegistry.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Explorer"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\Explorer\MyMessages.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\Explorer\MyMessages.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Dialogs"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\BenchmarkDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\BenchmarkDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\CompressDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\CompressDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ExtractDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ExtractDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\OverwriteDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\OverwriteDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\PasswordDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\PasswordDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\ProgressDialog2.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\ProgressDialog2.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "FM Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\ExtractCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\ExtractCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\FolderInterface.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\FormatUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\FormatUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\HelpUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\HelpUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\LangUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\LangUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\OpenCallback.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\OpenCallback.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\ProgramLocation.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\ProgramLocation.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\RegistryUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\RegistryUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\SplitUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\SplitUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\StringUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\FileManager\StringUtils.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Engine"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\ExtractGUI.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ExtractGUI.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\GUI.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\UpdateCallbackGUI.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\UpdateCallbackGUI.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\UpdateGUI.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\UpdateGUI.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "7-zip Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\CreateCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilePathAutoRename.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilePathAutoRename.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FileStreams.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\FilterCoder.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\ProgressUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Common\StreamUtils.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Compress"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyCoder.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Compress\CopyCoder.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "C"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.c\r
+\r
+!IF  "$(CFG)" == "GUI - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "GUI - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "GUI - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "GUI - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\7zCrcOpt.c\r
+\r
+!IF  "$(CFG)" == "GUI - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "GUI - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "GUI - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "GUI - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Alloc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.c\r
+\r
+!IF  "$(CFG)" == "GUI - Win32 Release"\r
+\r
+# ADD CPP /O2\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "GUI - Win32 Debug"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "GUI - Win32 ReleaseU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ELSEIF  "$(CFG)" == "GUI - Win32 DebugU"\r
+\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\CpuArch.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.c\r
+# SUBTRACT CPP /YX /Yc /Yu\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\..\C\Threads.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CommandLineParser.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CommandLineParser.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\CRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\IntToString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Lang.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Lang.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\ListFileUtils.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\ListFileUtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\MyVector.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\NewHandler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringToInt.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\StringToInt.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\TextConfig.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\TextConfig.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\UTFConvert.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\UTFConvert.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Common\Wildcard.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Windows"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Group "Control"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ComboBox.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ComboBox.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Dialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Dialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Edit.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ListView.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ListView.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\ProgressBar.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Control\Static.h\r
+# End Source File\r
+# End Group\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\COM.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\CommonDialog.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\CommonDialog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\DLL.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Error.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileDir.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileFind.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileIO.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileMapping.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\FileName.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\MemoryLock.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\MemoryLock.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariant.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantConversions.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\PropVariantConversions.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Registry.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Registry.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\ResourceString.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\ResourceString.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Shell.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Shell.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Synchronization.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\System.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\System.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Time.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Window.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\Windows\Window.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Archive Common"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.h\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/CPP/7zip/UI/GUI/GUI.dsw b/CPP/7zip/UI/GUI/GUI.dsw
new file mode 100755 (executable)
index 0000000..465622e
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "GUI"=.\GUI.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/CPP/7zip/UI/GUI/StdAfx.cpp b/CPP/7zip/UI/GUI/StdAfx.cpp
new file mode 100755 (executable)
index 0000000..c6d3b1f
--- /dev/null
@@ -0,0 +1,3 @@
+// StdAfx.cpp\r
+\r
+#include "StdAfx.h"\r
diff --git a/CPP/7zip/UI/GUI/StdAfx.h b/CPP/7zip/UI/GUI/StdAfx.h
new file mode 100755 (executable)
index 0000000..2dbbc04
--- /dev/null
@@ -0,0 +1,13 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include <windows.h>\r
+#include <commctrl.h>\r
+#include <shlobj.h>\r
+#include <stdio.h>\r
+\r
+#include "Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp b/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp
new file mode 100755 (executable)
index 0000000..25a3c4f
--- /dev/null
@@ -0,0 +1,228 @@
+// UpdateCallbackGUI.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/Error.h"\r
+#include "Windows/PropVariant.h"\r
+\r
+#include "../FileManager/PasswordDialog.h"\r
+\r
+#include "UpdateCallbackGUI.h"\r
+\r
+using namespace NWindows;\r
+\r
+CUpdateCallbackGUI::~CUpdateCallbackGUI() {}\r
+\r
+void CUpdateCallbackGUI::Init()\r
+{\r
+  FailedFiles.Clear();\r
+  NumFiles = 0;\r
+}\r
+\r
+void CUpdateCallbackGUI::AddErrorMessage(LPCWSTR message)\r
+{\r
+  ProgressDialog->Sync.AddErrorMessage(message);\r
+}\r
+\r
+void CUpdateCallbackGUI::AddErrorMessage(const wchar_t *name, DWORD systemError)\r
+{\r
+  AddErrorMessage(\r
+      UString(L"WARNING: ") +\r
+      NError::MyFormatMessageW(systemError) +\r
+      UString(L": ") +\r
+      UString(name));\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::OpenResult(const wchar_t *name, HRESULT result)\r
+{\r
+  if (result != S_OK)\r
+  {\r
+    AddErrorMessage (UString(L"Error: ") + name + UString(L" is not supported archive"));\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::StartScanning()\r
+{\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::CanNotFindError(const wchar_t *name, DWORD systemError)\r
+{\r
+  FailedFiles.Add(name);\r
+  AddErrorMessage(name, systemError);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::FinishScanning()\r
+{\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::StartArchive(const wchar_t *name, bool /* updating */)\r
+{\r
+  ProgressDialog->Sync.SetTitleFileName(name);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::FinishArchive()\r
+{\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::CheckBreak()\r
+{\r
+  return ProgressDialog->Sync.ProcessStopAndPause();\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::ScanProgress(UInt64 /* numFolders */, UInt64 numFiles, const wchar_t *path)\r
+{\r
+  ProgressDialog->Sync.SetCurrentFileName(path);\r
+  ProgressDialog->Sync.SetNumFilesTotal(numFiles);\r
+  return ProgressDialog->Sync.ProcessStopAndPause();\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::Finilize()\r
+{\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::SetNumFiles(UInt64 numFiles)\r
+{\r
+  ProgressDialog->Sync.SetNumFilesTotal(numFiles);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::SetTotal(UInt64 total)\r
+{\r
+  ProgressDialog->Sync.SetProgress(total, 0);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::SetCompleted(const UInt64 *completeValue)\r
+{\r
+  RINOK(CheckBreak());\r
+  if (completeValue != NULL)\r
+    ProgressDialog->Sync.SetPos(*completeValue);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)\r
+{\r
+  RINOK(CheckBreak());\r
+  ProgressDialog->Sync.SetRatioInfo(inSize, outSize);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::GetStream(const wchar_t *name, bool /* isAnti */)\r
+{\r
+  ProgressDialog->Sync.SetCurrentFileName(name);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::OpenFileError(const wchar_t *name, DWORD systemError)\r
+{\r
+  FailedFiles.Add(name);\r
+  // if (systemError == ERROR_SHARING_VIOLATION)\r
+  {\r
+    AddErrorMessage(name, systemError);\r
+    return S_FALSE;\r
+  }\r
+  // return systemError;\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::SetOperationResult(Int32 /* operationResult */)\r
+{\r
+  NumFiles++;\r
+  ProgressDialog->Sync.SetNumFilesCur(NumFiles);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)\r
+{\r
+  *password = NULL;\r
+  if (!PasswordIsDefined)\r
+  {\r
+    if (passwordIsDefined == 0 || AskPassword)\r
+    {\r
+      CPasswordDialog dialog;\r
+      ProgressDialog->WaitCreating();\r
+      if (dialog.Create(*ProgressDialog) == IDCANCEL)\r
+        return E_ABORT;\r
+      Password = dialog.Password;\r
+      PasswordIsDefined = true;\r
+    }\r
+  }\r
+  if (passwordIsDefined != 0)\r
+    *passwordIsDefined = BoolToInt(PasswordIsDefined);\r
+  return StringToBstr(Password, password);\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::CryptoGetTextPassword(BSTR *password)\r
+{\r
+  return CryptoGetTextPassword2(NULL, password);\r
+}\r
+\r
+/*\r
+It doesn't work, since main stream waits Dialog\r
+HRESULT CUpdateCallbackGUI::CloseProgress()\r
+{\r
+  ProgressDialog->MyClose();\r
+  return S_OK;\r
+}\r
+*/\r
+\r
+\r
+HRESULT CUpdateCallbackGUI::Open_CheckBreak()\r
+{\r
+  return ProgressDialog->Sync.ProcessStopAndPause();\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)\r
+{\r
+  // if (numFiles != NULL) ProgressDialog->Sync.SetNumFilesTotal(*numFiles);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)\r
+{\r
+  return ProgressDialog->Sync.ProcessStopAndPause();\r
+}\r
+\r
+#ifndef _NO_CRYPTO\r
+\r
+HRESULT CUpdateCallbackGUI::Open_CryptoGetTextPassword(BSTR *password)\r
+{\r
+  PasswordWasAsked = true;\r
+  return CryptoGetTextPassword2(NULL, password);\r
+}\r
+\r
+HRESULT CUpdateCallbackGUI::Open_GetPasswordIfAny(UString &password)\r
+{\r
+  if (PasswordIsDefined)\r
+    password = Password;\r
+  return S_OK;\r
+}\r
+\r
+bool CUpdateCallbackGUI::Open_WasPasswordAsked()\r
+{\r
+  return PasswordWasAsked;\r
+}\r
+\r
+void CUpdateCallbackGUI::Open_ClearPasswordWasAskedFlag()\r
+{\r
+  PasswordWasAsked = false;\r
+}\r
+\r
+/*\r
+HRESULT CUpdateCallbackGUI::ShowDeleteFile(const wchar_t *name)\r
+{\r
+  ProgressDialog->Sync.SetCurrentFileName(name);\r
+  return S_OK;\r
+}\r
+*/\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI.h b/CPP/7zip/UI/GUI/UpdateCallbackGUI.h
new file mode 100755 (executable)
index 0000000..ea243d6
--- /dev/null
@@ -0,0 +1,41 @@
+// UpdateCallbackGUI.h\r
+\r
+#ifndef __UPDATE_CALLBACK_GUI_H\r
+#define __UPDATE_CALLBACK_GUI_H\r
+\r
+#include "../Common/Update.h"\r
+#include "../Common/ArchiveOpenCallback.h"\r
+#include "../FileManager/ProgressDialog2.h"\r
+\r
+class CUpdateCallbackGUI:\r
+  public IOpenCallbackUI,\r
+  public IUpdateCallbackUI2\r
+{\r
+public:\r
+  bool PasswordIsDefined;\r
+  UString Password;\r
+  bool AskPassword;\r
+  bool PasswordWasAsked;\r
+  UInt64 NumFiles;\r
+\r
+  CUpdateCallbackGUI():\r
+      PasswordIsDefined(false),\r
+      PasswordWasAsked(false),\r
+      AskPassword(false)\r
+      {}\r
+  \r
+  ~CUpdateCallbackGUI();\r
+  void Init();\r
+\r
+  INTERFACE_IUpdateCallbackUI2(;)\r
+  INTERFACE_IOpenCallbackUI(;)\r
+\r
+  UStringVector FailedFiles;\r
+\r
+  CProgressDialog *ProgressDialog;\r
+\r
+  void AddErrorMessage(LPCWSTR message);\r
+  void AddErrorMessage(const wchar_t *name, DWORD systemError);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/GUI/UpdateGUI.cpp b/CPP/7zip/UI/GUI/UpdateGUI.cpp
new file mode 100755 (executable)
index 0000000..c0eb45a
--- /dev/null
@@ -0,0 +1,399 @@
+// UpdateGUI.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "UpdateGUI.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+#include "Common/StringToInt.h"\r
+\r
+#include "Windows/Error.h"\r
+#include "Windows/FileDir.h"\r
+#include "Windows/Thread.h"\r
+\r
+#include "../Common/WorkDir.h"\r
+\r
+#include "../Explorer/MyMessages.h"\r
+\r
+#include "../FileManager/LangUtils.h"\r
+#include "../FileManager/ProgramLocation.h"\r
+#include "../FileManager/StringUtils.h"\r
+#include "../FileManager/resourceGui.h"\r
+\r
+#include "CompressDialog.h"\r
+#include "UpdateGUI.h"\r
+\r
+#include "resource2.h"\r
+\r
+using namespace NWindows;\r
+using namespace NFile;\r
+\r
+static const wchar_t *kDefaultSfxModule = L"7z.sfx";\r
+static const wchar_t *kSFXExtension = L"exe";\r
+\r
+extern void AddMessageToString(UString &dest, const UString &src);\r
+\r
+UString HResultToMessage(HRESULT errorCode);\r
+\r
+class CThreadUpdating: public CProgressThreadVirt\r
+{\r
+  HRESULT ProcessVirt();\r
+public:\r
+  CCodecs *codecs;\r
+  CUpdateCallbackGUI *UpdateCallbackGUI;\r
+  const NWildcard::CCensor *WildcardCensor;\r
+  CUpdateOptions *Options;\r
+};\r
\r
+HRESULT CThreadUpdating::ProcessVirt()\r
+{\r
+  CUpdateErrorInfo ei;\r
+  HRESULT res = UpdateArchive(codecs, *WildcardCensor, *Options,\r
+     ei, UpdateCallbackGUI, UpdateCallbackGUI);\r
+  ErrorMessage = ei.Message;\r
+  ErrorPath1 = ei.FileName;\r
+  ErrorPath2 = ei.FileName2;\r
+  if (ei.SystemError != S_OK && ei.SystemError != E_FAIL && ei.SystemError != E_ABORT)\r
+    return ei.SystemError;\r
+  return res;\r
+}\r
+\r
+static void AddProp(CObjectVector<CProperty> &properties, const UString &name, const UString &value)\r
+{\r
+  CProperty prop;\r
+  prop.Name = name;\r
+  prop.Value = value;\r
+  properties.Add(prop);\r
+}\r
+\r
+static void AddProp(CObjectVector<CProperty> &properties, const UString &name, UInt32 value)\r
+{\r
+  wchar_t tmp[32];\r
+  ConvertUInt64ToString(value, tmp);\r
+  AddProp(properties, name, tmp);\r
+}\r
+\r
+static void AddProp(CObjectVector<CProperty> &properties, const UString &name, bool value)\r
+{\r
+  AddProp(properties, name, value ? UString(L"on"): UString(L"off"));\r
+}\r
+\r
+static bool IsThereMethodOverride(bool is7z, const UString &propertiesString)\r
+{\r
+  UStringVector strings;\r
+  SplitString(propertiesString, strings);\r
+  for (int i = 0; i < strings.Size(); i++)\r
+  {\r
+    const UString &s = strings[i];\r
+    if (is7z)\r
+    {\r
+      const wchar_t *end;\r
+      UInt64 n = ConvertStringToUInt64(s, &end);\r
+      if (n == 0 && *end == L'=')\r
+        return true;\r
+    }\r
+    else\r
+    {\r
+      if (s.Length() > 0)\r
+        if (s[0] == L'm' && s[1] == L'=')\r
+          return true;\r
+    }\r
+  }\r
+  return false;\r
+}\r
+\r
+static void ParseAndAddPropertires(CObjectVector<CProperty> &properties,\r
+    const UString &propertiesString)\r
+{\r
+  UStringVector strings;\r
+  SplitString(propertiesString, strings);\r
+  for (int i = 0; i < strings.Size(); i++)\r
+  {\r
+    const UString &s = strings[i];\r
+    CProperty property;\r
+    int index = s.Find(L'=');\r
+    if (index < 0)\r
+      property.Name = s;\r
+    else\r
+    {\r
+      property.Name = s.Left(index);\r
+      property.Value = s.Mid(index + 1);\r
+    }\r
+    properties.Add(property);\r
+  }\r
+}\r
+\r
+static UString GetNumInBytesString(UInt64 v)\r
+{\r
+  wchar_t s[32];\r
+  ConvertUInt64ToString(v, s);\r
+  size_t len = wcslen(s);\r
+  s[len++] = L'B';\r
+  s[len] = L'\0';\r
+  return s;\r
+}\r
+\r
+static void SetOutProperties(\r
+    CObjectVector<CProperty> &properties,\r
+    bool is7z,\r
+    UInt32 level,\r
+    bool setMethod,\r
+    const UString &method,\r
+    UInt32 dictionary,\r
+    bool orderMode,\r
+    UInt32 order,\r
+    bool solidIsSpecified, UInt64 solidBlockSize,\r
+    bool multiThreadIsAllowed, UInt32 numThreads,\r
+    const UString &encryptionMethod,\r
+    bool encryptHeadersIsAllowed, bool encryptHeaders,\r
+    bool /* sfxMode */)\r
+{\r
+  if (level != (UInt32)(Int32)-1)\r
+    AddProp(properties, L"x", (UInt32)level);\r
+  if (setMethod)\r
+  {\r
+    if (!method.IsEmpty())\r
+      AddProp(properties, is7z ? L"0": L"m", method);\r
+    if (dictionary != (UInt32)(Int32)-1)\r
+    {\r
+      UString name;\r
+      if (is7z)\r
+        name = L"0";\r
+      if (orderMode)\r
+        name += L"mem";\r
+      else\r
+        name += L"d";\r
+      AddProp(properties, name, GetNumInBytesString(dictionary));\r
+    }\r
+    if (order != (UInt32)(Int32)-1)\r
+    {\r
+      UString name;\r
+      if (is7z)\r
+        name = L"0";\r
+      if (orderMode)\r
+        name += L"o";\r
+      else\r
+        name += L"fb";\r
+      AddProp(properties, name, (UInt32)order);\r
+    }\r
+  }\r
+    \r
+  if (!encryptionMethod.IsEmpty())\r
+    AddProp(properties, L"em", encryptionMethod);\r
+\r
+  if (encryptHeadersIsAllowed)\r
+    AddProp(properties, L"he", encryptHeaders);\r
+  if (solidIsSpecified)\r
+    AddProp(properties, L"s", GetNumInBytesString(solidBlockSize));\r
+  if (multiThreadIsAllowed)\r
+    AddProp(properties, L"mt", numThreads);\r
+}\r
+\r
+static HRESULT ShowDialog(\r
+    CCodecs *codecs,\r
+    const NWildcard::CCensor &censor,\r
+    CUpdateOptions &options, CUpdateCallbackGUI *callback, HWND hwndParent)\r
+{\r
+  if (options.Commands.Size() != 1)\r
+    throw "It must be one command";\r
+  UString currentDirPrefix;\r
+  #ifndef UNDER_CE\r
+  {\r
+    if (!NDirectory::MyGetCurrentDirectory(currentDirPrefix))\r
+      return E_FAIL;\r
+    NName::NormalizeDirPathPrefix(currentDirPrefix);\r
+  }\r
+  #endif\r
+\r
+  bool oneFile = false;\r
+  NFind::CFileInfoW fileInfo;\r
+  UString name;\r
+  if (censor.Pairs.Size() > 0)\r
+  {\r
+    const NWildcard::CPair &pair = censor.Pairs[0];\r
+    if (pair.Head.IncludeItems.Size() > 0)\r
+    {\r
+      const NWildcard::CItem &item = pair.Head.IncludeItems[0];\r
+      if (item.ForFile)\r
+      {\r
+        name = pair.Prefix;\r
+        for (int i = 0; i < item.PathParts.Size(); i++)\r
+        {\r
+          if (i > 0)\r
+            name += WCHAR_PATH_SEPARATOR;\r
+          name += item.PathParts[i];\r
+        }\r
+        if (fileInfo.Find(name))\r
+        {\r
+          if (censor.Pairs.Size() == 1 && pair.Head.IncludeItems.Size() == 1)\r
+            oneFile = !fileInfo.IsDir();\r
+        }\r
+      }\r
+    }\r
+  }\r
+    \r
+  CCompressDialog dialog;\r
+  NCompressDialog::CInfo &di = dialog.Info;\r
+  dialog.ArcFormats = &codecs->Formats;\r
+  for (int i = 0; i < codecs->Formats.Size(); i++)\r
+  {\r
+    const CArcInfoEx &ai = codecs->Formats[i];\r
+    if (ai.Name.CompareNoCase(L"swfc") == 0)\r
+      if (!oneFile || name.Right(4).CompareNoCase(L".swf") != 0)\r
+        continue;\r
+    if (ai.UpdateEnabled && (oneFile || !ai.KeepName))\r
+      dialog.ArcIndices.Add(i);\r
+  }\r
+  if (dialog.ArcIndices.Size() == 0)\r
+  {\r
+    ShowErrorMessage(L"No Update Engines");\r
+    return E_FAIL;\r
+  }\r
+\r
+  // di.ArchiveName = options.ArchivePath.GetFinalPath();\r
+  di.ArchiveName = options.ArchivePath.GetPathWithoutExt();\r
+  dialog.OriginalFileName = options.ArchivePath.Prefix + fileInfo.Name;\r
+    \r
+  di.CurrentDirPrefix = currentDirPrefix;\r
+  di.SFXMode = options.SfxMode;\r
+  di.OpenShareForWrite = options.OpenShareForWrite;\r
+  \r
+  if (callback->PasswordIsDefined)\r
+    di.Password = callback->Password;\r
+    \r
+  di.KeepName = !oneFile;\r
+    \r
+  if (dialog.Create(hwndParent) != IDOK)\r
+    return E_ABORT;\r
+    \r
+  options.VolumesSizes = di.VolumeSizes;\r
+  /*\r
+  if (di.VolumeSizeIsDefined)\r
+  {\r
+    MyMessageBox(L"Splitting to volumes is not supported");\r
+    return E_FAIL;\r
+  }\r
+  */\r
+  \r
+  NUpdateArchive::CActionSet &actionSet = options.Commands.Front().ActionSet;\r
+  \r
+  switch(di.UpdateMode)\r
+  {\r
+    case NCompressDialog::NUpdateMode::kAdd:\r
+      actionSet = NUpdateArchive::kAddActionSet;\r
+      break;\r
+    case NCompressDialog::NUpdateMode::kUpdate:\r
+      actionSet = NUpdateArchive::kUpdateActionSet;\r
+      break;\r
+    case NCompressDialog::NUpdateMode::kFresh:\r
+      actionSet = NUpdateArchive::kFreshActionSet;\r
+      break;\r
+    case NCompressDialog::NUpdateMode::kSynchronize:\r
+      actionSet = NUpdateArchive::kSynchronizeActionSet;\r
+      break;\r
+    default:\r
+      throw 1091756;\r
+  }\r
+  const CArcInfoEx &archiverInfo = codecs->Formats[di.FormatIndex];\r
+  callback->PasswordIsDefined = (!di.Password.IsEmpty());\r
+  if (callback->PasswordIsDefined)\r
+    callback->Password = di.Password;\r
+\r
+  options.MethodMode.Properties.Clear();\r
+\r
+  bool is7z = archiverInfo.Name.CompareNoCase(L"7z") == 0;\r
+  bool methodOverride = IsThereMethodOverride(is7z, di.Options);\r
+\r
+  SetOutProperties(\r
+      options.MethodMode.Properties,\r
+      is7z,\r
+      di.Level,\r
+      !methodOverride,\r
+      di.Method,\r
+      di.Dictionary,\r
+      di.OrderMode, di.Order,\r
+      di.SolidIsSpecified, di.SolidBlockSize,\r
+      di.MultiThreadIsAllowed, di.NumThreads,\r
+      di.EncryptionMethod,\r
+      di.EncryptHeadersIsAllowed, di.EncryptHeaders,\r
+      di.SFXMode);\r
+  \r
+  options.OpenShareForWrite = di.OpenShareForWrite;\r
+  ParseAndAddPropertires(options.MethodMode.Properties, di.Options);\r
+\r
+  if (di.SFXMode)\r
+    options.SfxMode = true;\r
+  options.MethodMode.FormatIndex = di.FormatIndex;\r
+\r
+  options.ArchivePath.VolExtension = archiverInfo.GetMainExt();\r
+  if (di.SFXMode)\r
+    options.ArchivePath.BaseExtension = kSFXExtension;\r
+  else\r
+    options.ArchivePath.BaseExtension = options.ArchivePath.VolExtension;\r
+  options.ArchivePath.ParseFromPath(di.ArchiveName);\r
+\r
+  NWorkDir::CInfo workDirInfo;\r
+  workDirInfo.Load();\r
+  options.WorkingDir.Empty();\r
+  if (workDirInfo.Mode != NWorkDir::NMode::kCurrent)\r
+  {\r
+    UString fullPath;\r
+    NDirectory::MyGetFullPathName(di.ArchiveName, fullPath);\r
+    options.WorkingDir = GetWorkDir(workDirInfo, fullPath);\r
+    NDirectory::CreateComplexDirectory(options.WorkingDir);\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+HRESULT UpdateGUI(\r
+    CCodecs *codecs,\r
+    const NWildcard::CCensor &censor,\r
+    CUpdateOptions &options,\r
+    bool showDialog,\r
+    bool &messageWasDisplayed,\r
+    CUpdateCallbackGUI *callback,\r
+    HWND hwndParent)\r
+{\r
+  messageWasDisplayed = false;\r
+  if (showDialog)\r
+  {\r
+    RINOK(ShowDialog(codecs, censor, options, callback, hwndParent));\r
+  }\r
+  if (options.SfxMode && options.SfxModule.IsEmpty())\r
+  {\r
+    UString folder;\r
+    if (!GetProgramFolderPath(folder))\r
+      folder.Empty();\r
+    options.SfxModule = folder + kDefaultSfxModule;\r
+  }\r
+\r
+  CThreadUpdating tu;\r
+\r
+  tu.codecs = codecs;\r
+\r
+  tu.UpdateCallbackGUI = callback;\r
+  tu.UpdateCallbackGUI->ProgressDialog = &tu.ProgressDialog;\r
+  tu.UpdateCallbackGUI->Init();\r
+\r
+  UString title = LangString(IDS_PROGRESS_COMPRESSING, 0x02000DC0);\r
+\r
+  /*\r
+  if (hwndParent != 0)\r
+  {\r
+    tu.ProgressDialog.MainWindow = hwndParent;\r
+    // tu.ProgressDialog.MainTitle = fileName;\r
+    tu.ProgressDialog.MainAddTitle = title + L" ";\r
+  }\r
+  */\r
+\r
+  tu.WildcardCensor = &censor;\r
+  tu.Options = &options;\r
+  tu.ProgressDialog.IconID = IDI_ICON;\r
+\r
+  RINOK(tu.Create(title, hwndParent));\r
+\r
+  messageWasDisplayed = tu.ThreadFinishedOK &\r
+      tu.ProgressDialog.MessagesDisplayed;\r
+  return tu.Result;\r
+}\r
diff --git a/CPP/7zip/UI/GUI/UpdateGUI.h b/CPP/7zip/UI/GUI/UpdateGUI.h
new file mode 100755 (executable)
index 0000000..12e55a4
--- /dev/null
@@ -0,0 +1,31 @@
+// GUI/UpdateGUI.h\r
+\r
+#ifndef __UPDATE_GUI_H\r
+#define __UPDATE_GUI_H\r
+\r
+#include "../Common/Update.h"\r
+\r
+#include "UpdateCallbackGUI.h"\r
+\r
+/*\r
+  callback->FailedFiles contains names of files for that there were problems.\r
+  RESULT can be S_OK, even if there are such warnings!!!\r
+  \r
+  RESULT = E_ABORT - user break.\r
+  RESULT != E_ABORT:\r
+  {\r
+   messageWasDisplayed = true  - message was displayed already.\r
+   messageWasDisplayed = false - there was some internal error, so you must show error message.\r
+  }\r
+*/\r
+\r
+HRESULT UpdateGUI(\r
+    CCodecs *codecs,\r
+    const NWildcard::CCensor &censor,\r
+    CUpdateOptions &options,\r
+    bool showDialog,\r
+    bool &messageWasDisplayed,\r
+    CUpdateCallbackGUI *callback,\r
+    HWND hwndParent = NULL);\r
+\r
+#endif\r
diff --git a/CPP/7zip/UI/GUI/makefile b/CPP/7zip/UI/GUI/makefile
new file mode 100755 (executable)
index 0000000..bc3c083
--- /dev/null
@@ -0,0 +1,165 @@
+PROG = 7zG.exe\r
+CFLAGS = $(CFLAGS) -I ../../../  \\r
+  -DLANG \\r
+  -DEXTERNAL_CODECS \\r
+\r
+!IFDEF UNDER_CE\r
+LIBS = $(LIBS) ceshell.lib Commctrl.lib\r
+!ELSE\r
+LIBS = $(LIBS) comctl32.lib htmlhelp.lib comdlg32.lib\r
+CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -DSUPPORT_DEVICE_FILE -D_7ZIP_LARGE_PAGES\r
+!ENDIF\r
+\r
+GUI_OBJS = \\r
+  $O\BenchmarkDialog.obj \\r
+  $O\CompressDialog.obj \\r
+  $O\ExtractDialog.obj \\r
+  $O\ExtractGUI.obj \\r
+  $O\GUI.obj \\r
+  $O\UpdateCallbackGUI.obj \\r
+  $O\UpdateGUI.obj \\r
+\r
+COMMON_OBJS = \\r
+  $O\CommandLineParser.obj \\r
+  $O\CRC.obj \\r
+  $O\IntToString.obj \\r
+  $O\Lang.obj \\r
+  $O\ListFileUtils.obj \\r
+  $O\MyString.obj \\r
+  $O\MyVector.obj \\r
+  $O\NewHandler.obj \\r
+  $O\StringConvert.obj \\r
+  $O\StringToInt.obj \\r
+  $O\TextConfig.obj \\r
+  $O\UTFConvert.obj \\r
+  $O\Wildcard.obj \\r
+\r
+WIN_OBJS = \\r
+  $O\CommonDialog.obj \\r
+  $O\DLL.obj \\r
+  $O\Error.obj \\r
+  $O\FileDir.obj \\r
+  $O\FileFind.obj \\r
+  $O\FileIO.obj \\r
+  $O\FileName.obj \\r
+  $O\MemoryLock.obj \\r
+  $O\PropVariant.obj \\r
+  $O\PropVariantConversions.obj \\r
+  $O\Registry.obj \\r
+  $O\ResourceString.obj \\r
+  $O\Shell.obj \\r
+  $O\Synchronization.obj \\r
+  $O\System.obj \\r
+  $O\Time.obj \\r
+  $O\Window.obj \\r
+\r
+WIN_CTRL_OBJS = \\r
+  $O\ComboBox.obj \\r
+  $O\Dialog.obj \\r
+  $O\ListView.obj \\r
+\r
+7ZIP_COMMON_OBJS = \\r
+  $O\CreateCoder.obj \\r
+  $O\FilePathAutoRename.obj \\r
+  $O\FileStreams.obj \\r
+  $O\FilterCoder.obj \\r
+  $O\ProgressUtils.obj \\r
+  $O\StreamUtils.obj \\r
+\r
+UI_COMMON_OBJS = \\r
+  $O\ArchiveCommandLine.obj \\r
+  $O\ArchiveExtractCallback.obj \\r
+  $O\ArchiveOpenCallback.obj \\r
+  $O\Bench.obj \\r
+  $O\DefaultName.obj \\r
+  $O\EnumDirItems.obj \\r
+  $O\Extract.obj \\r
+  $O\ExtractingFilePath.obj \\r
+  $O\LoadCodecs.obj \\r
+  $O\OpenArchive.obj \\r
+  $O\PropIDUtils.obj \\r
+  $O\SetProperties.obj \\r
+  $O\SortUtils.obj \\r
+  $O\TempFiles.obj \\r
+  $O\Update.obj \\r
+  $O\UpdateAction.obj \\r
+  $O\UpdateCallback.obj \\r
+  $O\UpdatePair.obj \\r
+  $O\UpdateProduce.obj \\r
+  $O\WorkDir.obj \\r
+  $O\ZipRegistry.obj \\r
+\r
+AR_COMMON_OBJS = \\r
+  $O\OutStreamWithCRC.obj \\r
+\r
+FM_OBJS = \\r
+  $O\ExtractCallback.obj \\r
+  $O\FormatUtils.obj \\r
+  $O\HelpUtils.obj \\r
+  $O\LangUtils.obj \\r
+  $O\OpenCallback.obj \\r
+  $O\ProgramLocation.obj \\r
+  $O\RegistryUtils.obj \\r
+  $O\SplitUtils.obj \\r
+  $O\StringUtils.obj \\r
+  $O\OverwriteDialog.obj \\r
+  $O\PasswordDialog.obj \\r
+  $O\ProgressDialog2.obj \\r
+\r
+!IFDEF UNDER_CE\r
+FM_OBJS = $(FM_OBJS) \\r
+  $O\BrowseDialog.obj \\r
+  $O\SysIconUtils.obj \\r
+!ENDIF\r
+\r
+C_OBJS = \\r
+  $O\Alloc.obj \\r
+  $O\CpuArch.obj \\r
+  $O\Threads.obj \\r
+\r
+!include "../../Crc.mak"\r
+\r
+OBJS = \\r
+  $O\StdAfx.obj \\r
+  $(GUI_OBJS) \\r
+  $(COMMON_OBJS) \\r
+  $(WIN_OBJS) \\r
+  $(WIN_CTRL_OBJS) \\r
+  $(7ZIP_COMMON_OBJS) \\r
+  $(UI_COMMON_OBJS) \\r
+  $(AR_COMMON_OBJS) \\r
+  $(FM_OBJS)\\r
+  $O\MyMessages.obj \\r
+  $O\CopyCoder.obj \\r
+  $(LZMA_BENCH_OBJS) \\r
+  $(C_OBJS) \\r
+  $(ASM_OBJS) \\r
+  $O\resource.res\r
+\r
+!include "../../../Build.mak"\r
+\r
+$(GUI_OBJS): $(*B).cpp\r
+       $(COMPL)\r
+$(COMMON_OBJS): ../../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_OBJS): ../../../Windows/$(*B).cpp\r
+       $(COMPL)\r
+$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp\r
+       $(COMPL)\r
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(UI_COMMON_OBJS): ../Common/$(*B).cpp\r
+       $(COMPL)\r
+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp\r
+       $(COMPL)\r
+$(FM_OBJS): ../FileManager/$(*B).cpp\r
+       $(COMPL)\r
+$O\MyMessages.obj: ../Explorer/MyMessages.cpp\r
+       $(COMPL)\r
+\r
+$O\CopyCoder.obj: ../../Compress/$(*B).cpp\r
+       $(COMPL)\r
+$(C_OBJS): ../../../../C/$(*B).c\r
+       $(COMPL_O2)\r
+\r
+!include "../../Asm.mak"\r
diff --git a/CPP/7zip/UI/GUI/resource.rc b/CPP/7zip/UI/GUI/resource.rc
new file mode 100755 (executable)
index 0000000..966b1cf
--- /dev/null
@@ -0,0 +1,21 @@
+#include "../../MyVersionInfo.rc"\r
+#include <winnt.h>\r
+\r
+#include "resource2.rc"\r
+#include "../FileManager/resourceGui.rc"\r
+\r
+MY_VERSION_INFO_APP("7-Zip GUI", "7zg")\r
+\r
+IDI_ICON ICON "FM.ico"\r
+\r
+#ifndef UNDER_CE\r
+1 24 MOVEABLE PURE "7zG.exe.manifest"\r
+#endif\r
+\r
+#ifdef UNDER_CE\r
+#include "../FileManager/PropertyName.rc"\r
+#endif\r
+#include "../FileManager/OverwriteDialog.rc"\r
+#include "../FileManager/PasswordDialog.rc"\r
+#include "../FileManager/ProgressDialog2.rc"\r
+#include "Extract.rc"\r
diff --git a/CPP/7zip/UI/GUI/resource2.h b/CPP/7zip/UI/GUI/resource2.h
new file mode 100755 (executable)
index 0000000..b9330af
--- /dev/null
@@ -0,0 +1,3 @@
+#define IDS_COMPRESSED_COLON            2277\r
+#define IDS_ARCHIVES_COLON              2278\r
+#define IDS_PROGRESS_COMPRESSING        98\r
diff --git a/CPP/7zip/UI/GUI/resource2.rc b/CPP/7zip/UI/GUI/resource2.rc
new file mode 100755 (executable)
index 0000000..58b309b
--- /dev/null
@@ -0,0 +1,11 @@
+#include "ExtractDialog.rc"\r
+#include "CompressDialog.rc"\r
+#include "BenchmarkDialog.rc"\r
+#include "resource2.h"\r
+\r
+STRINGTABLE\r
+BEGIN\r
+    IDS_COMPRESSED_COLON    "Compressed size:"\r
+    IDS_ARCHIVES_COLON      "Archives:"\r
+    IDS_PROGRESS_COMPRESSING "Compressing"\r
+END\r
diff --git a/CPP/7zip/UI/makefile b/CPP/7zip/UI/makefile
new file mode 100755 (executable)
index 0000000..9d51814
--- /dev/null
@@ -0,0 +1,12 @@
+DIRS = \\r
+  Client7z\~ \\r
+  Console\~ \\r
+  Explorer\~ \\r
+  Far\~ \\r
+  FileManager\~ \\r
+  GUI\~ \\r
+\r
+all: $(DIRS)\r
+\r
+$(DIRS):\r
+!include "../SubBuild.mak"\r
diff --git a/CPP/7zip/makefile b/CPP/7zip/makefile
new file mode 100755 (executable)
index 0000000..422d2d2
--- /dev/null
@@ -0,0 +1,10 @@
+DIRS = \\r
+  UI\~ \\r
+  Bundles\~ \\r
+  \r
+all: $(DIRS)\r
+\r
+$(DIRS):\r
+       cd $(@D)\r
+       $(MAKE) -nologo\r
+       cd ..\r
diff --git a/CPP/Build.mak b/CPP/Build.mak
new file mode 100755 (executable)
index 0000000..81ac79d
--- /dev/null
@@ -0,0 +1,94 @@
+LIBS = $(LIBS) oleaut32.lib ole32.lib\r
+\r
+!IFDEF CPU\r
+!IFNDEF NO_BUFFEROVERFLOWU\r
+LIBS = $(LIBS) bufferoverflowU.lib\r
+!ENDIF\r
+!ENDIF\r
+\r
+\r
+!IFNDEF O\r
+!IFDEF CPU\r
+O=$(CPU)\r
+!ELSE\r
+O=O\r
+!ENDIF\r
+!ENDIF\r
+\r
+!IF "$(CPU)" == "AMD64"\r
+MY_ML = ml64 -Dx64\r
+!ELSEIF "$(CPU)" == "ARM"\r
+MY_ML = armasm\r
+!ELSE\r
+MY_ML = ml\r
+!ENDIF\r
+\r
+\r
+!IFDEF UNDER_CE\r
+RFLAGS = $(RFLAGS) -dUNDER_CE\r
+!IFDEF MY_CONSOLE\r
+LFLAGS = $(LFLAGS) /ENTRY:mainACRTStartup\r
+!ENDIF\r
+!ELSE\r
+!IFNDEF NEW_COMPILER\r
+LFLAGS = $(LFLAGS) -OPT:NOWIN98\r
+!ENDIF\r
+CFLAGS = $(CFLAGS) -Gr\r
+LIBS = $(LIBS) user32.lib advapi32.lib shell32.lib\r
+!ENDIF\r
+\r
+!IF "$(CPU)" == "ARM"\r
+COMPL_ASM = $(MY_ML) $** $O/$(*B).obj\r
+!ELSE\r
+COMPL_ASM = $(MY_ML) -c -Fo$O/ $**\r
+!ENDIF\r
+\r
+CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -WX -EHsc -Gy -GR-\r
+\r
+!IFDEF MY_STATIC_LINK\r
+!IFNDEF MY_SINGLE_THREAD\r
+CFLAGS = $(CFLAGS) -MT\r
+!ENDIF\r
+!ELSE\r
+CFLAGS = $(CFLAGS) -MD\r
+!ENDIF\r
+\r
+!IFDEF NEW_COMPILER\r
+CFLAGS = $(CFLAGS) -W4 -GS- -Zc:forScope\r
+!ELSE\r
+CFLAGS = $(CFLAGS) -W3\r
+!ENDIF\r
+\r
+CFLAGS_O1 = $(CFLAGS) -O1\r
+CFLAGS_O2 = $(CFLAGS) -O2\r
+\r
+LFLAGS = $(LFLAGS) -nologo -OPT:REF -OPT:ICF\r
+\r
+!IFDEF DEF_FILE\r
+LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE)\r
+!ENDIF\r
+\r
+PROGPATH = $O\$(PROG)\r
+\r
+COMPL_O1   = $(CC) $(CFLAGS_O1) $**\r
+COMPL_O2   = $(CC) $(CFLAGS_O2) $**\r
+COMPL_PCH  = $(CC) $(CFLAGS_O1) -Yc"StdAfx.h" -Fp$O/a.pch $**\r
+COMPL      = $(CC) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $**\r
+\r
+all: $(PROGPATH)\r
+\r
+clean:\r
+       -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch\r
+\r
+$O:\r
+       if not exist "$O" mkdir "$O"\r
+\r
+$(PROGPATH): $O $(OBJS) $(DEF_FILE)\r
+       link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS)\r
+\r
+!IFNDEF NO_DEFAULT_RES\r
+$O\resource.res: $(*B).rc\r
+       rc $(RFLAGS) -fo$@ $**\r
+!ENDIF\r
+$O\StdAfx.obj: $(*B).cpp\r
+       $(COMPL_PCH)\r
diff --git a/CPP/Common/AutoPtr.h b/CPP/Common/AutoPtr.h
new file mode 100755 (executable)
index 0000000..e53fb7f
--- /dev/null
@@ -0,0 +1,35 @@
+// Common/AutoPtr.h\r
+\r
+#ifndef __COMMON_AUTOPTR_H\r
+#define __COMMON_AUTOPTR_H\r
+\r
+template<class T> class CMyAutoPtr\r
+{\r
+  T *_p;\r
+public:\r
+  CMyAutoPtr(T *p = 0) : _p(p) {}\r
+  CMyAutoPtr(CMyAutoPtr<T>& p): _p(p.release()) {}\r
+  CMyAutoPtr<T>& operator=(CMyAutoPtr<T>& p)\r
+  {\r
+    reset(p.release());\r
+    return (*this);\r
+  }\r
+  ~CMyAutoPtr() { delete _p; }\r
+  T& operator*() const { return *_p; }\r
+  // T* operator->() const { return (&**this); }\r
+  T* get() const { return _p; }\r
+  T* release()\r
+  {\r
+    T *tmp = _p;\r
+    _p = 0;\r
+    return tmp;\r
+  }\r
+  void reset(T* p = 0)\r
+  {\r
+    if (p != _p)\r
+      delete _p;\r
+    _p = p;\r
+  }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/Common/Buffer.h b/CPP/Common/Buffer.h
new file mode 100755 (executable)
index 0000000..defe943
--- /dev/null
@@ -0,0 +1,77 @@
+// Common/Buffer.h\r
+\r
+#ifndef __COMMON_BUFFER_H\r
+#define __COMMON_BUFFER_H\r
+\r
+#include "Defs.h"\r
+\r
+template <class T> class CBuffer\r
+{\r
+protected:\r
+  size_t _capacity;\r
+  T *_items;\r
+public:\r
+  void Free()\r
+  {\r
+    delete []_items;\r
+    _items = 0;\r
+    _capacity = 0;\r
+  }\r
+  CBuffer(): _capacity(0), _items(0) {};\r
+  CBuffer(const CBuffer &buffer): _capacity(0), _items(0) { *this = buffer; }\r
+  CBuffer(size_t size): _items(0), _capacity(0) {  SetCapacity(size); }\r
+  virtual ~CBuffer() { delete []_items; }\r
+  operator T *() { return _items; };\r
+  operator const T *() const { return _items; };\r
+  size_t GetCapacity() const { return  _capacity; }\r
+  void SetCapacity(size_t newCapacity)\r
+  {\r
+    if (newCapacity == _capacity)\r
+      return;\r
+    T *newBuffer;\r
+    if (newCapacity > 0)\r
+    {\r
+      newBuffer = new T[newCapacity];\r
+      if (_capacity > 0)\r
+        memmove(newBuffer, _items, MyMin(_capacity, newCapacity) * sizeof(T));\r
+    }\r
+    else\r
+      newBuffer = 0;\r
+    delete []_items;\r
+    _items = newBuffer;\r
+    _capacity = newCapacity;\r
+  }\r
+  CBuffer& operator=(const CBuffer &buffer)\r
+  {\r
+    Free();\r
+    if (buffer._capacity > 0)\r
+    {\r
+      SetCapacity(buffer._capacity);\r
+      memmove(_items, buffer._items, buffer._capacity * sizeof(T));\r
+    }\r
+    return *this;\r
+  }\r
+};\r
+\r
+template <class T>\r
+bool operator==(const CBuffer<T>& b1, const CBuffer<T>& b2)\r
+{\r
+  if (b1.GetCapacity() != b2.GetCapacity())\r
+    return false;\r
+  for (size_t i = 0; i < b1.GetCapacity(); i++)\r
+    if (b1[i] != b2[i])\r
+      return false;\r
+  return true;\r
+}\r
+\r
+template <class T>\r
+bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2)\r
+{\r
+  return !(b1 == b2);\r
+}\r
+\r
+typedef CBuffer<char> CCharBuffer;\r
+typedef CBuffer<wchar_t> CWCharBuffer;\r
+typedef CBuffer<unsigned char> CByteBuffer;\r
+\r
+#endif\r
diff --git a/CPP/Common/CRC.cpp b/CPP/Common/CRC.cpp
new file mode 100755 (executable)
index 0000000..6ac52c4
--- /dev/null
@@ -0,0 +1,7 @@
+// Common/CRC.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../C/7zCrc.h"\r
+\r
+struct CCRCTableInit { CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit;\r
diff --git a/CPP/Common/C_FileIO.cpp b/CPP/Common/C_FileIO.cpp
new file mode 100755 (executable)
index 0000000..0e5647f
--- /dev/null
@@ -0,0 +1,88 @@
+// Common/C_FileIO.h\r
+\r
+#include "C_FileIO.h"\r
+\r
+#include <fcntl.h>\r
+#include <unistd.h>\r
+\r
+namespace NC {\r
+namespace NFile {\r
+namespace NIO {\r
+\r
+bool CFileBase::OpenBinary(const char *name, int flags)\r
+{\r
+  #ifdef O_BINARY\r
+  flags |= O_BINARY;\r
+  #endif\r
+  Close();\r
+  _handle = ::open(name, flags, 0666);\r
+  return _handle != -1;\r
+}\r
+\r
+bool CFileBase::Close()\r
+{\r
+  if (_handle == -1)\r
+    return true;\r
+  if (close(_handle) != 0)\r
+    return false;\r
+  _handle = -1;\r
+  return true;\r
+}\r
+\r
+bool CFileBase::GetLength(UInt64 &length) const\r
+{\r
+  off_t curPos = Seek(0, SEEK_CUR);\r
+  off_t lengthTemp = Seek(0, SEEK_END);\r
+  Seek(curPos, SEEK_SET);\r
+  length = (UInt64)lengthTemp;\r
+  return true;\r
+}\r
+\r
+off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const\r
+{\r
+  return ::lseek(_handle, distanceToMove, moveMethod);\r
+}\r
+\r
+/////////////////////////\r
+// CInFile\r
+\r
+bool CInFile::Open(const char *name)\r
+{\r
+  return CFileBase::OpenBinary(name, O_RDONLY);\r
+}\r
+\r
+bool CInFile::OpenShared(const char *name, bool)\r
+{\r
+  return Open(name);\r
+}\r
+\r
+ssize_t CInFile::Read(void *data, size_t size)\r
+{\r
+  return read(_handle, data, size);\r
+}\r
+\r
+/////////////////////////\r
+// COutFile\r
+\r
+bool COutFile::Create(const char *name, bool createAlways)\r
+{\r
+  if (createAlways)\r
+  {\r
+    Close();\r
+    _handle = ::creat(name, 0666);\r
+    return _handle != -1;\r
+  }\r
+  return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY);\r
+}\r
+\r
+bool COutFile::Open(const char *name, DWORD creationDisposition)\r
+{\r
+  return Create(name, false);\r
+}\r
+\r
+ssize_t COutFile::Write(const void *data, size_t size)\r
+{\r
+  return write(_handle, data, size);\r
+}\r
+\r
+}}}\r
diff --git a/CPP/Common/C_FileIO.h b/CPP/Common/C_FileIO.h
new file mode 100755 (executable)
index 0000000..3f8cbca
--- /dev/null
@@ -0,0 +1,47 @@
+// Common/C_FileIO.h\r
+\r
+#ifndef __COMMON_C_FILEIO_H\r
+#define __COMMON_C_FILEIO_H\r
+\r
+#include <stdio.h>\r
+#include <sys/types.h>\r
+\r
+#include "Types.h"\r
+#include "MyWindows.h"\r
+\r
+namespace NC {\r
+namespace NFile {\r
+namespace NIO {\r
+\r
+class CFileBase\r
+{\r
+protected:\r
+  int _handle;\r
+  bool OpenBinary(const char *name, int flags);\r
+public:\r
+  CFileBase(): _handle(-1) {};\r
+  ~CFileBase() { Close(); }\r
+  bool Close();\r
+  bool GetLength(UInt64 &length) const;\r
+  off_t Seek(off_t distanceToMove, int moveMethod) const;\r
+};\r
+\r
+class CInFile: public CFileBase\r
+{\r
+public:\r
+  bool Open(const char *name);\r
+  bool OpenShared(const char *name, bool shareForWrite);\r
+  ssize_t Read(void *data, size_t size);\r
+};\r
+\r
+class COutFile: public CFileBase\r
+{\r
+public:\r
+  bool Create(const char *name, bool createAlways);\r
+  bool Open(const char *name, DWORD creationDisposition);\r
+  ssize_t Write(const void *data, size_t size);\r
+};\r
+\r
+}}}\r
+\r
+#endif\r
diff --git a/CPP/Common/ComTry.h b/CPP/Common/ComTry.h
new file mode 100755 (executable)
index 0000000..b2b3029
--- /dev/null
@@ -0,0 +1,17 @@
+// ComTry.h\r
+\r
+#ifndef __COM_TRY_H\r
+#define __COM_TRY_H\r
+\r
+#include "MyWindows.h"\r
+// #include "Exception.h"\r
+// #include "NewHandler.h"\r
+\r
+#define COM_TRY_BEGIN try {\r
+#define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; }\r
+  \r
+  // catch(const CNewException &) { return E_OUTOFMEMORY; }\r
+  // catch(const CSystemException &e) { return e.ErrorCode; }\r
+  // catch(...) { return E_FAIL; }\r
+\r
+#endif\r
diff --git a/CPP/Common/CommandLineParser.cpp b/CPP/Common/CommandLineParser.cpp
new file mode 100755 (executable)
index 0000000..028f4f8
--- /dev/null
@@ -0,0 +1,229 @@
+// CommandLineParser.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "CommandLineParser.h"\r
+\r
+namespace NCommandLineParser {\r
+\r
+bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2)\r
+{\r
+  dest1.Empty();\r
+  dest2.Empty();\r
+  bool quoteMode = false;\r
+  int i;\r
+  for (i = 0; i < src.Length(); i++)\r
+  {\r
+    wchar_t c = src[i];\r
+    if (c == L' ' && !quoteMode)\r
+    {\r
+      dest2 = src.Mid(i + 1);\r
+      return i != 0;\r
+    }\r
+    if (c == L'\"')\r
+      quoteMode = !quoteMode;\r
+    else\r
+      dest1 += c;\r
+  }\r
+  return i != 0;\r
+}\r
+\r
+void SplitCommandLine(const UString &s, UStringVector &parts)\r
+{\r
+  UString sTemp = s;\r
+  sTemp.Trim();\r
+  parts.Clear();\r
+  for (;;)\r
+  {\r
+    UString s1, s2;\r
+    if (SplitCommandLine(sTemp, s1, s2))\r
+      parts.Add(s1);\r
+    if (s2.IsEmpty())\r
+      break;\r
+    sTemp = s2;\r
+  }\r
+}\r
+\r
+\r
+static const wchar_t kSwitchID1 = '-';\r
+// static const wchar_t kSwitchID2 = '/';\r
+\r
+static const wchar_t kSwitchMinus = '-';\r
+static const wchar_t *kStopSwitchParsing = L"--";\r
+\r
+static bool IsItSwitchChar(wchar_t c)\r
+{\r
+  return (c == kSwitchID1 /*|| c == kSwitchID2 */);\r
+}\r
+\r
+CParser::CParser(int numSwitches):\r
+  _numSwitches(numSwitches)\r
+{\r
+  _switches = new CSwitchResult[_numSwitches];\r
+}\r
+\r
+CParser::~CParser()\r
+{\r
+  delete []_switches;\r
+}\r
+\r
+void CParser::ParseStrings(const CSwitchForm *switchForms,\r
+  const UStringVector &commandStrings)\r
+{\r
+  int numCommandStrings = commandStrings.Size();\r
+  bool stopSwitch = false;\r
+  for (int i = 0; i < numCommandStrings; i++)\r
+  {\r
+    const UString &s = commandStrings[i];\r
+    if (stopSwitch)\r
+      NonSwitchStrings.Add(s);\r
+    else\r
+      if (s == kStopSwitchParsing)\r
+        stopSwitch = true;\r
+      else\r
+        if (!ParseString(s, switchForms))\r
+          NonSwitchStrings.Add(s);\r
+  }\r
+}\r
+\r
+// if string contains switch then function updates switch structures\r
+// out: (string is a switch)\r
+bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms)\r
+{\r
+  int len = s.Length();\r
+  if (len == 0)\r
+    return false;\r
+  int pos = 0;\r
+  if (!IsItSwitchChar(s[pos]))\r
+    return false;\r
+  while (pos < len)\r
+  {\r
+    if (IsItSwitchChar(s[pos]))\r
+      pos++;\r
+    const int kNoLen = -1;\r
+    int matchedSwitchIndex = 0; // GCC Warning\r
+    int maxLen = kNoLen;\r
+    for (int switchIndex = 0; switchIndex < _numSwitches; switchIndex++)\r
+    {\r
+      int switchLen = MyStringLen(switchForms[switchIndex].IDString);\r
+      if (switchLen <= maxLen || pos + switchLen > len)\r
+        continue;\r
+\r
+      UString temp = s + pos;\r
+      temp = temp.Left(switchLen);\r
+      if (temp.CompareNoCase(switchForms[switchIndex].IDString) == 0)\r
+      // if (_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0)\r
+      {\r
+        matchedSwitchIndex = switchIndex;\r
+        maxLen = switchLen;\r
+      }\r
+    }\r
+    if (maxLen == kNoLen)\r
+      throw "maxLen == kNoLen";\r
+    CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex];\r
+    const CSwitchForm &switchForm = switchForms[matchedSwitchIndex];\r
+    if ((!switchForm.Multi) && matchedSwitch.ThereIs)\r
+      throw "switch must be single";\r
+    matchedSwitch.ThereIs = true;\r
+    pos += maxLen;\r
+    int tailSize = len - pos;\r
+    NSwitchType::EEnum type = switchForm.Type;\r
+    switch(type)\r
+    {\r
+      case NSwitchType::kPostMinus:\r
+        {\r
+          if (tailSize == 0)\r
+            matchedSwitch.WithMinus = false;\r
+          else\r
+          {\r
+            matchedSwitch.WithMinus = (s[pos] == kSwitchMinus);\r
+            if (matchedSwitch.WithMinus)\r
+              pos++;\r
+          }\r
+          break;\r
+        }\r
+      case NSwitchType::kPostChar:\r
+        {\r
+          if (tailSize < switchForm.MinLen)\r
+            throw "switch is not full";\r
+          UString set = switchForm.PostCharSet;\r
+          const int kEmptyCharValue = -1;\r
+          if (tailSize == 0)\r
+            matchedSwitch.PostCharIndex = kEmptyCharValue;\r
+          else\r
+          {\r
+            int index = set.Find(s[pos]);\r
+            if (index < 0)\r
+              matchedSwitch.PostCharIndex =  kEmptyCharValue;\r
+            else\r
+            {\r
+              matchedSwitch.PostCharIndex = index;\r
+              pos++;\r
+            }\r
+          }\r
+          break;\r
+        }\r
+      case NSwitchType::kLimitedPostString:\r
+      case NSwitchType::kUnLimitedPostString:\r
+        {\r
+          int minLen = switchForm.MinLen;\r
+          if (tailSize < minLen)\r
+            throw "switch is not full";\r
+          if (type == NSwitchType::kUnLimitedPostString)\r
+          {\r
+            matchedSwitch.PostStrings.Add(s.Mid(pos));\r
+            return true;\r
+          }\r
+          int maxLen = switchForm.MaxLen;\r
+          UString stringSwitch = s.Mid(pos, minLen);\r
+          pos += minLen;\r
+          for (int i = minLen; i < maxLen && pos < len; i++, pos++)\r
+          {\r
+            wchar_t c = s[pos];\r
+            if (IsItSwitchChar(c))\r
+              break;\r
+            stringSwitch += c;\r
+          }\r
+          matchedSwitch.PostStrings.Add(stringSwitch);\r
+          break;\r
+        }\r
+      case NSwitchType::kSimple:\r
+          break;\r
+    }\r
+  }\r
+  return true;\r
+}\r
+\r
+const CSwitchResult& CParser::operator[](size_t index) const\r
+{\r
+  return _switches[index];\r
+}\r
+\r
+/////////////////////////////////\r
+// Command parsing procedures\r
+\r
+int ParseCommand(int numCommandForms, const CCommandForm *commandForms,\r
+    const UString &commandString, UString &postString)\r
+{\r
+  for (int i = 0; i < numCommandForms; i++)\r
+  {\r
+    const UString id = commandForms[i].IDString;\r
+    if (commandForms[i].PostStringMode)\r
+    {\r
+      if (commandString.Find(id) == 0)\r
+      {\r
+        postString = commandString.Mid(id.Length());\r
+        return i;\r
+      }\r
+    }\r
+    else\r
+      if (commandString == id)\r
+      {\r
+        postString.Empty();\r
+        return i;\r
+      }\r
+  }\r
+  return -1;\r
+}\r
+   \r
+}\r
diff --git a/CPP/Common/CommandLineParser.h b/CPP/Common/CommandLineParser.h
new file mode 100755 (executable)
index 0000000..ec079e3
--- /dev/null
@@ -0,0 +1,72 @@
+// Common/CommandLineParser.h\r
+\r
+#ifndef __COMMON_COMMAND_LINE_PARSER_H\r
+#define __COMMON_COMMAND_LINE_PARSER_H\r
+\r
+#include "MyString.h"\r
+\r
+namespace NCommandLineParser {\r
+\r
+bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2);\r
+void SplitCommandLine(const UString &s, UStringVector &parts);\r
+\r
+namespace NSwitchType {\r
+  enum EEnum\r
+  {\r
+    kSimple,\r
+    kPostMinus,\r
+    kLimitedPostString,\r
+    kUnLimitedPostString,\r
+    kPostChar\r
+  };\r
+}\r
+\r
+struct CSwitchForm\r
+{\r
+  const wchar_t *IDString;\r
+  NSwitchType::EEnum Type;\r
+  bool Multi;\r
+  int MinLen;\r
+  int MaxLen;\r
+  const wchar_t *PostCharSet;\r
+};\r
+\r
+struct CSwitchResult\r
+{\r
+  bool ThereIs;\r
+  bool WithMinus;\r
+  UStringVector PostStrings;\r
+  int PostCharIndex;\r
+  CSwitchResult(): ThereIs(false) {};\r
+};\r
+  \r
+class CParser\r
+{\r
+  int _numSwitches;\r
+  CSwitchResult *_switches;\r
+  bool ParseString(const UString &s, const CSwitchForm *switchForms);\r
+public:\r
+  UStringVector NonSwitchStrings;\r
+  CParser(int numSwitches);\r
+  ~CParser();\r
+  void ParseStrings(const CSwitchForm *switchForms,\r
+    const UStringVector &commandStrings);\r
+  const CSwitchResult& operator[](size_t index) const;\r
+};\r
+\r
+/////////////////////////////////\r
+// Command parsing procedures\r
+\r
+struct CCommandForm\r
+{\r
+  const wchar_t *IDString;\r
+  bool PostStringMode;\r
+};\r
+\r
+// Returns: Index of form and postString; -1, if there is no match\r
+int ParseCommand(int numCommandForms, const CCommandForm *commandForms,\r
+    const UString &commandString, UString &postString);\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/Common/Defs.h b/CPP/Common/Defs.h
new file mode 100755 (executable)
index 0000000..69b8ece
--- /dev/null
@@ -0,0 +1,20 @@
+// Common/Defs.h\r
+\r
+#ifndef __COMMON_DEFS_H\r
+#define __COMMON_DEFS_H\r
+\r
+template <class T> inline T MyMin(T a, T b)\r
+  {  return a < b ? a : b; }\r
+template <class T> inline T MyMax(T a, T b)\r
+  {  return a > b ? a : b; }\r
+\r
+template <class T> inline int MyCompare(T a, T b)\r
+  {  return a < b ? -1 : (a == b ? 0 : 1); }\r
+\r
+inline int BoolToInt(bool value)\r
+  { return (value ? 1: 0); }\r
+\r
+inline bool IntToBool(int value)\r
+  { return (value != 0); }\r
+\r
+#endif\r
diff --git a/CPP/Common/DynamicBuffer.h b/CPP/Common/DynamicBuffer.h
new file mode 100755 (executable)
index 0000000..2bd80ac
--- /dev/null
@@ -0,0 +1,50 @@
+// Common/DynamicBuffer.h\r
+\r
+#ifndef __COMMON_DYNAMIC_BUFFER_H\r
+#define __COMMON_DYNAMIC_BUFFER_H\r
+\r
+#include "Buffer.h"\r
+\r
+template <class T> class CDynamicBuffer: public CBuffer<T>\r
+{\r
+  void GrowLength(size_t size)\r
+  {\r
+    size_t delta;\r
+    if (this->_capacity > 64)\r
+      delta = this->_capacity / 4;\r
+    else if (this->_capacity > 8)\r
+      delta = 16;\r
+    else\r
+      delta = 4;\r
+    delta = MyMax(delta, size);\r
+    size_t newCap = this->_capacity + delta;\r
+    if (newCap < delta)\r
+      newCap = this->_capacity + size;\r
+    SetCapacity(newCap);\r
+  }\r
+public:\r
+  CDynamicBuffer(): CBuffer<T>() {};\r
+  CDynamicBuffer(const CDynamicBuffer &buffer): CBuffer<T>(buffer) {};\r
+  CDynamicBuffer(size_t size): CBuffer<T>(size) {};\r
+  CDynamicBuffer& operator=(const CDynamicBuffer &buffer)\r
+  {\r
+    this->Free();\r
+    if (buffer._capacity > 0)\r
+    {\r
+      SetCapacity(buffer._capacity);\r
+      memmove(this->_items, buffer._items, buffer._capacity * sizeof(T));\r
+    }\r
+    return *this;\r
+  }\r
+  void EnsureCapacity(size_t capacity)\r
+  {\r
+    if (this->_capacity < capacity)\r
+      GrowLength(capacity - this->_capacity);\r
+  }\r
+};\r
+\r
+typedef CDynamicBuffer<char> CCharDynamicBuffer;\r
+typedef CDynamicBuffer<wchar_t> CWCharDynamicBuffer;\r
+typedef CDynamicBuffer<unsigned char> CByteDynamicBuffer;\r
+\r
+#endif\r
diff --git a/CPP/Common/IntToString.cpp b/CPP/Common/IntToString.cpp
new file mode 100755 (executable)
index 0000000..312e9f0
--- /dev/null
@@ -0,0 +1,77 @@
+// Common/IntToString.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "IntToString.h"\r
+\r
+void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base)\r
+{\r
+  if (base < 2 || base > 36)\r
+  {\r
+    *s = '\0';\r
+    return;\r
+  }\r
+  char temp[72];\r
+  int pos = 0;\r
+  do\r
+  {\r
+    int delta = (int)(value % base);\r
+    temp[pos++] = (char)((delta < 10) ? ('0' + delta) : ('a' + (delta - 10)));\r
+    value /= base;\r
+  }\r
+  while (value != 0);\r
+  do\r
+    *s++ = temp[--pos];\r
+  while (pos > 0);\r
+  *s = '\0';\r
+}\r
+\r
+void ConvertUInt64ToString(UInt64 value, wchar_t *s)\r
+{\r
+  wchar_t temp[32];\r
+  int pos = 0;\r
+  do\r
+  {\r
+    temp[pos++] = (wchar_t)(L'0' + (int)(value % 10));\r
+    value /= 10;\r
+  }\r
+  while (value != 0);\r
+  do\r
+    *s++ = temp[--pos];\r
+  while (pos > 0);\r
+  *s = L'\0';\r
+}\r
+\r
+void ConvertUInt32ToString(UInt32 value, char *s) { ConvertUInt64ToString(value, s); }\r
+void ConvertUInt32ToString(UInt32 value, wchar_t *s) { ConvertUInt64ToString(value, s); }\r
+\r
+void ConvertInt64ToString(Int64 value, char *s)\r
+{\r
+  if (value < 0)\r
+  {\r
+    *s++ = '-';\r
+    value = -value;\r
+  }\r
+  ConvertUInt64ToString(value, s);\r
+}\r
+\r
+void ConvertInt64ToString(Int64 value, wchar_t *s)\r
+{\r
+  if (value < 0)\r
+  {\r
+    *s++ = L'-';\r
+    value = -value;\r
+  }\r
+  ConvertUInt64ToString(value, s);\r
+}\r
+\r
+void ConvertUInt32ToHexWithZeros(UInt32 value, char *s)\r
+{\r
+  for (int i = 0; i < 8; i++)\r
+  {\r
+    int t = value & 0xF;\r
+    value >>= 4;\r
+    s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));\r
+  }\r
+  s[8] = '\0';\r
+}\r
diff --git a/CPP/Common/IntToString.h b/CPP/Common/IntToString.h
new file mode 100755 (executable)
index 0000000..c57fd6a
--- /dev/null
@@ -0,0 +1,19 @@
+// Common/IntToString.h\r
+\r
+#ifndef __COMMON_INT_TO_STRING_H\r
+#define __COMMON_INT_TO_STRING_H\r
+\r
+#include <stddef.h>\r
+#include "Types.h"\r
+\r
+void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base = 10);\r
+void ConvertUInt64ToString(UInt64 value, wchar_t *s);\r
+void ConvertInt64ToString(Int64 value, char *s);\r
+void ConvertInt64ToString(Int64 value, wchar_t *s);\r
+\r
+void ConvertUInt32ToString(UInt32 value, char *s);\r
+void ConvertUInt32ToString(UInt32 value, wchar_t *s);\r
+\r
+void ConvertUInt32ToHexWithZeros(UInt32 value, char *s);\r
+\r
+#endif\r
diff --git a/CPP/Common/Lang.cpp b/CPP/Common/Lang.cpp
new file mode 100755 (executable)
index 0000000..161b30b
--- /dev/null
@@ -0,0 +1,130 @@
+// Common/Lang.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Lang.h"\r
+#include "TextConfig.h"\r
+\r
+#include "../Windows/FileIO.h"\r
+#include "UTFConvert.h"\r
+#include "Defs.h"\r
+\r
+static bool HexStringToNumber(const UString &s, UInt32 &value)\r
+{\r
+  value = 0;\r
+  if (s.IsEmpty())\r
+    return false;\r
+  for (int i = 0; i < s.Length(); i++)\r
+  {\r
+    wchar_t c = s[i];\r
+    int a;\r
+    if (c >= L'0' && c <= L'9')\r
+      a = c - L'0';\r
+    else if (c >= L'A' && c <= L'F')\r
+      a = 10 + c - L'A';\r
+    else if (c >= L'a' && c <= L'f')\r
+      a = 10 + c - L'a';\r
+    else\r
+      return false;\r
+    value *= 0x10;\r
+    value += a;\r
+  }\r
+  return true;\r
+}\r
+\r
+\r
+static bool WaitNextLine(const AString &s, int &pos)\r
+{\r
+  for (; pos < s.Length(); pos++)\r
+    if (s[pos] == 0x0A)\r
+      return true;\r
+  return false;\r
+}\r
+\r
+static int CompareLangItems(void *const *elem1, void *const *elem2, void *)\r
+{\r
+  const CLangPair &langPair1 = *(*((const CLangPair **)elem1));\r
+  const CLangPair &langPair2 = *(*((const CLangPair **)elem2));\r
+  return MyCompare(langPair1.Value, langPair2.Value);\r
+}\r
+\r
+bool CLang::Open(LPCWSTR fileName)\r
+{\r
+  _langPairs.Clear();\r
+  NWindows::NFile::NIO::CInFile file;\r
+  if (!file.Open(fileName))\r
+    return false;\r
+  UInt64 length;\r
+  if (!file.GetLength(length))\r
+    return false;\r
+  if (length > (1 << 20))\r
+    return false;\r
+  AString s;\r
+  char *p = s.GetBuffer((int)length + 1);\r
+  UInt32 processed;\r
+  if (!file.Read(p, (UInt32)length, processed))\r
+    return false;\r
+  p[(UInt32)length] = 0;\r
+  s.ReleaseBuffer();\r
+  file.Close();\r
+  int pos = 0;\r
+  if (s.Length() >= 3)\r
+  {\r
+    if (Byte(s[0]) == 0xEF && Byte(s[1]) == 0xBB && Byte(s[2]) == 0xBF)\r
+      pos += 3;\r
+  }\r
+\r
+  /////////////////////\r
+  // read header\r
+\r
+  AString stringID = ";!@Lang@!UTF-8!";\r
+  if (s.Mid(pos, stringID.Length()) != stringID)\r
+    return false;\r
+  pos += stringID.Length();\r
+  \r
+  if (!WaitNextLine(s, pos))\r
+    return false;\r
+\r
+  CObjectVector<CTextConfigPair> pairs;\r
+  if (!GetTextConfig(s.Mid(pos), pairs))\r
+    return false;\r
+\r
+  _langPairs.Reserve(_langPairs.Size());\r
+  for (int i = 0; i < pairs.Size(); i++)\r
+  {\r
+    CTextConfigPair textConfigPair = pairs[i];\r
+    CLangPair langPair;\r
+    if (!HexStringToNumber(textConfigPair.ID, langPair.Value))\r
+      return false;\r
+    langPair.String = textConfigPair.String;\r
+    _langPairs.Add(langPair);\r
+  }\r
+  _langPairs.Sort(CompareLangItems, NULL);\r
+  return true;\r
+}\r
+\r
+int CLang::FindItem(UInt32 value) const\r
+{\r
+  int left = 0, right = _langPairs.Size();\r
+  while (left != right)\r
+  {\r
+    UInt32 mid = (left + right) / 2;\r
+    UInt32 midValue = _langPairs[mid].Value;\r
+    if (value == midValue)\r
+      return mid;\r
+    if (value < midValue)\r
+      right = mid;\r
+    else\r
+      left = mid + 1;\r
+  }\r
+  return -1;\r
+}\r
+\r
+bool CLang::GetMessage(UInt32 value, UString &message) const\r
+{\r
+  int index =  FindItem(value);\r
+  if (index < 0)\r
+    return false;\r
+  message = _langPairs[index].String;\r
+  return true;\r
+}\r
diff --git a/CPP/Common/Lang.h b/CPP/Common/Lang.h
new file mode 100755 (executable)
index 0000000..ac595c6
--- /dev/null
@@ -0,0 +1,28 @@
+// Common/Lang.h\r
+\r
+#ifndef __COMMON_LANG_H\r
+#define __COMMON_LANG_H\r
+\r
+#include "MyVector.h"\r
+#include "MyString.h"\r
+#include "Types.h"\r
+\r
+struct CLangPair\r
+{\r
+  UInt32 Value;\r
+  UString String;\r
+};\r
+\r
+class CLang\r
+{\r
+  CObjectVector<CLangPair> _langPairs;\r
+public:\r
+  bool Open(LPCWSTR fileName);\r
+  void Clear() { _langPairs.Clear(); }\r
+  int FindItem(UInt32 value) const;\r
+  bool GetMessage(UInt32 value, UString &message) const;\r
+};\r
+\r
+#endif\r
+\r
+\r
diff --git a/CPP/Common/ListFileUtils.cpp b/CPP/Common/ListFileUtils.cpp
new file mode 100755 (executable)
index 0000000..ff61b02
--- /dev/null
@@ -0,0 +1,75 @@
+// Common/ListFileUtils.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "MyWindows.h"\r
+#include "../Windows/FileIO.h"\r
+\r
+#include "ListFileUtils.h"\r
+#include "StringConvert.h"\r
+#include "UTFConvert.h"\r
+\r
+static const char kQuoteChar     = '\"';\r
+static void RemoveQuote(UString &s)\r
+{\r
+  if (s.Length() >= 2)\r
+    if (s[0] == kQuoteChar && s[s.Length() - 1] == kQuoteChar)\r
+      s = s.Mid(1, s.Length() - 2);\r
+}\r
+\r
+bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &resultStrings, UINT codePage)\r
+{\r
+  NWindows::NFile::NIO::CInFile file;\r
+  if (!file.Open(fileName))\r
+    return false;\r
+  UInt64 length;\r
+  if (!file.GetLength(length))\r
+    return false;\r
+  if (length > ((UInt32)1 << 31))\r
+    return false;\r
+  AString s;\r
+  char *p = s.GetBuffer((int)length + 1);\r
+  UInt32 processed;\r
+  if (!file.Read(p, (UInt32)length, processed))\r
+    return false;\r
+  p[(UInt32)length] = 0;\r
+  s.ReleaseBuffer();\r
+  file.Close();\r
+\r
+  UString u;\r
+  #ifdef CP_UTF8\r
+  if (codePage == CP_UTF8)\r
+  {\r
+    if (!ConvertUTF8ToUnicode(s, u))\r
+      return false;\r
+  }\r
+  else\r
+  #endif\r
+    u = MultiByteToUnicodeString(s, codePage);\r
+  if (!u.IsEmpty())\r
+  {\r
+    if (u[0] == 0xFEFF)\r
+      u.Delete(0);\r
+  }\r
+\r
+  UString t;\r
+  for (int i = 0; i < u.Length(); i++)\r
+  {\r
+    wchar_t c = u[i];\r
+    if (c == L'\n' || c == 0xD)\r
+    {\r
+      t.Trim();\r
+      RemoveQuote(t);\r
+      if (!t.IsEmpty())\r
+        resultStrings.Add(t);\r
+      t.Empty();\r
+    }\r
+    else\r
+      t += c;\r
+  }\r
+  t.Trim();\r
+  RemoveQuote(t);\r
+  if (!t.IsEmpty())\r
+    resultStrings.Add(t);\r
+  return true;\r
+}\r
diff --git a/CPP/Common/ListFileUtils.h b/CPP/Common/ListFileUtils.h
new file mode 100755 (executable)
index 0000000..64f2199
--- /dev/null
@@ -0,0 +1,11 @@
+// Common/ListFileUtils.h\r
+\r
+#ifndef __COMMON_LISTFILEUTILS_H\r
+#define __COMMON_LISTFILEUTILS_H\r
+\r
+#include "MyString.h"\r
+#include "Types.h"\r
+\r
+bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP);\r
+\r
+#endif\r
diff --git a/CPP/Common/MyCom.h b/CPP/Common/MyCom.h
new file mode 100755 (executable)
index 0000000..d04fa4c
--- /dev/null
@@ -0,0 +1,225 @@
+// MyCom.h\r
+\r
+#ifndef __MYCOM_H\r
+#define __MYCOM_H\r
+\r
+#include "MyWindows.h"\r
+\r
+#ifndef RINOK\r
+#define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; }\r
+#endif\r
+\r
+template <class T>\r
+class CMyComPtr\r
+{\r
+  T* _p;\r
+public:\r
+  // typedef T _PtrClass;\r
+  CMyComPtr() { _p = NULL;}\r
+  CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); }\r
+  CMyComPtr(const CMyComPtr<T>& lp)\r
+  {\r
+    if ((_p = lp._p) != NULL)\r
+      _p->AddRef();\r
+  }\r
+  ~CMyComPtr() { if (_p) _p->Release(); }\r
+  void Release() { if (_p) { _p->Release(); _p = NULL; } }\r
+  operator T*() const {  return (T*)_p;  }\r
+  // T& operator*() const {  return *_p; }\r
+  T** operator&() { return &_p; }\r
+  T* operator->() const { return _p; }\r
+  T* operator=(T* p)\r
+  {\r
+    if (p != 0)\r
+      p->AddRef();\r
+    if (_p)\r
+      _p->Release();\r
+    _p = p;\r
+    return p;\r
+  }\r
+  T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); }\r
+  bool operator!() const { return (_p == NULL); }\r
+  // bool operator==(T* pT) const {  return _p == pT; }\r
+  // Compare two objects for equivalence\r
+  void Attach(T* p2)\r
+  {\r
+    Release();\r
+    _p = p2;\r
+  }\r
+  T* Detach()\r
+  {\r
+    T* pt = _p;\r
+    _p = NULL;\r
+    return pt;\r
+  }\r
+  #ifdef _WIN32\r
+  HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)\r
+  {\r
+    return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p);\r
+  }\r
+  #endif\r
+  /*\r
+  HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)\r
+  {\r
+    CLSID clsid;\r
+    HRESULT hr = CLSIDFromProgID(szProgID, &clsid);\r
+    ATLASSERT(_p == NULL);\r
+    if (SUCCEEDED(hr))\r
+      hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p);\r
+    return hr;\r
+  }\r
+  */\r
+  template <class Q>\r
+  HRESULT QueryInterface(REFGUID iid, Q** pp) const\r
+  {\r
+    return _p->QueryInterface(iid, (void**)pp);\r
+  }\r
+};\r
+\r
+//////////////////////////////////////////////////////////\r
+\r
+inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr)\r
+{\r
+  *bstr = ::SysAllocString(src);\r
+  return (*bstr != 0) ? S_OK : E_OUTOFMEMORY;\r
+}\r
+\r
+class CMyComBSTR\r
+{\r
+public:\r
+  BSTR m_str;\r
+  CMyComBSTR(): m_str(NULL) {}\r
+  CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); }\r
+  // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); }\r
+  // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize);  }\r
+  CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); }\r
+  /*\r
+  CMyComBSTR(REFGUID src)\r
+  {\r
+    LPOLESTR szGuid;\r
+    StringFromCLSID(src, &szGuid);\r
+    m_str = ::SysAllocString(szGuid);\r
+    CoTaskMemFree(szGuid);\r
+  }\r
+  */\r
+  ~CMyComBSTR() { ::SysFreeString(m_str); }\r
+  CMyComBSTR& operator=(const CMyComBSTR& src)\r
+  {\r
+    if (m_str != src.m_str)\r
+    {\r
+      if (m_str)\r
+        ::SysFreeString(m_str);\r
+      m_str = src.MyCopy();\r
+    }\r
+    return *this;\r
+  }\r
+  CMyComBSTR& operator=(LPCOLESTR src)\r
+  {\r
+    ::SysFreeString(m_str);\r
+    m_str = ::SysAllocString(src);\r
+    return *this;\r
+  }\r
+  unsigned int Length() const { return ::SysStringLen(m_str); }\r
+  operator BSTR() const { return m_str; }\r
+  BSTR* operator&() { return &m_str; }\r
+  BSTR MyCopy() const\r
+  {\r
+    int byteLen = ::SysStringByteLen(m_str);\r
+    BSTR res = ::SysAllocStringByteLen(NULL, byteLen);\r
+    memcpy(res, m_str, byteLen);\r
+    return res;\r
+  }\r
+  /*\r
+  void Attach(BSTR src) { m_str = src; }\r
+  BSTR Detach()\r
+  {\r
+    BSTR s = m_str;\r
+    m_str = NULL;\r
+    return s;\r
+  }\r
+  */\r
+  void Empty()\r
+  {\r
+    ::SysFreeString(m_str);\r
+    m_str = NULL;\r
+  }\r
+  bool operator!() const {  return (m_str == NULL); }\r
+};\r
+\r
+//////////////////////////////////////////////////////////\r
+\r
+class CMyUnknownImp\r
+{\r
+public:\r
+  ULONG __m_RefCount;\r
+  CMyUnknownImp(): __m_RefCount(0) {}\r
+};\r
+\r
+#define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \\r
+    (REFGUID iid, void **outObject) {\r
+\r
+#define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \\r
+    { *outObject = (void *)(i *)this; AddRef(); return S_OK; }\r
+\r
+#define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \\r
+    { *outObject = (void *)(IUnknown *)(i *)this; AddRef(); return S_OK; }\r
+\r
+#define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \\r
+    MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \\r
+    MY_QUERYINTERFACE_ENTRY(i)\r
+\r
+#define MY_QUERYINTERFACE_END return E_NOINTERFACE; }\r
+\r
+#define MY_ADDREF_RELEASE \\r
+STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \\r
+STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0)  \\r
+  return __m_RefCount; delete this; return 0; }\r
+\r
+#define MY_UNKNOWN_IMP_SPEC(i) \\r
+  MY_QUERYINTERFACE_BEGIN \\r
+  i \\r
+  MY_QUERYINTERFACE_END \\r
+  MY_ADDREF_RELEASE\r
+\r
+\r
+#define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \\r
+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \\r
+  MY_QUERYINTERFACE_END \\r
+  MY_ADDREF_RELEASE\r
+\r
+#define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \\r
+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \\r
+  MY_QUERYINTERFACE_ENTRY(i) \\r
+  )\r
+\r
+#define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \\r
+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \\r
+  MY_QUERYINTERFACE_ENTRY(i1) \\r
+  MY_QUERYINTERFACE_ENTRY(i2) \\r
+  )\r
+\r
+#define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \\r
+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \\r
+  MY_QUERYINTERFACE_ENTRY(i1) \\r
+  MY_QUERYINTERFACE_ENTRY(i2) \\r
+  MY_QUERYINTERFACE_ENTRY(i3) \\r
+  )\r
+\r
+#define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \\r
+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \\r
+  MY_QUERYINTERFACE_ENTRY(i1) \\r
+  MY_QUERYINTERFACE_ENTRY(i2) \\r
+  MY_QUERYINTERFACE_ENTRY(i3) \\r
+  MY_QUERYINTERFACE_ENTRY(i4) \\r
+  )\r
+\r
+#define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \\r
+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \\r
+  MY_QUERYINTERFACE_ENTRY(i1) \\r
+  MY_QUERYINTERFACE_ENTRY(i2) \\r
+  MY_QUERYINTERFACE_ENTRY(i3) \\r
+  MY_QUERYINTERFACE_ENTRY(i4) \\r
+  MY_QUERYINTERFACE_ENTRY(i5) \\r
+  )\r
+\r
+#endif\r
diff --git a/CPP/Common/MyException.h b/CPP/Common/MyException.h
new file mode 100755 (executable)
index 0000000..cd9fe69
--- /dev/null
@@ -0,0 +1,14 @@
+// Common/Exception.h\r
+\r
+#ifndef __COMMON_EXCEPTION_H\r
+#define __COMMON_EXCEPTION_H\r
+\r
+#include "MyWindows.h"\r
+\r
+struct CSystemException\r
+{\r
+  HRESULT ErrorCode;\r
+  CSystemException(HRESULT errorCode): ErrorCode(errorCode) {}\r
+};\r
+\r
+#endif\r
diff --git a/CPP/Common/MyGuidDef.h b/CPP/Common/MyGuidDef.h
new file mode 100755 (executable)
index 0000000..da73d0a
--- /dev/null
@@ -0,0 +1,54 @@
+// Common/MyGuidDef.h\r
+\r
+#ifndef GUID_DEFINED\r
+#define GUID_DEFINED\r
+\r
+#include "Types.h"\r
+\r
+typedef struct {\r
+  UInt32 Data1;\r
+  UInt16 Data2;\r
+  UInt16 Data3;\r
+  unsigned char Data4[8];\r
+} GUID;\r
+\r
+#ifdef __cplusplus\r
+#define REFGUID const GUID &\r
+#else\r
+#define REFGUID const GUID *\r
+#endif\r
+\r
+#define REFCLSID REFGUID\r
+#define REFIID REFGUID\r
+\r
+#ifdef __cplusplus\r
+inline int operator==(REFGUID g1, REFGUID g2)\r
+{\r
+  for (int i = 0; i < (int)sizeof(g1); i++)\r
+    if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i])\r
+      return 0;\r
+  return 1;\r
+}\r
+inline int operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); }\r
+#endif\r
+\r
+#ifdef __cplusplus\r
+  #define MY_EXTERN_C extern "C"\r
+#else\r
+  #define MY_EXTERN_C extern\r
+#endif\r
+\r
+#endif\r
+\r
+\r
+#ifdef DEFINE_GUID\r
+#undef DEFINE_GUID\r
+#endif\r
+\r
+#ifdef INITGUID\r
+  #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \\r
+    MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }\r
+#else\r
+  #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \\r
+    MY_EXTERN_C const GUID name\r
+#endif\r
diff --git a/CPP/Common/MyInitGuid.h b/CPP/Common/MyInitGuid.h
new file mode 100755 (executable)
index 0000000..98d1705
--- /dev/null
@@ -0,0 +1,22 @@
+// Common/MyInitGuid.h\r
+\r
+#ifndef __COMMON_MY_INITGUID_H\r
+#define __COMMON_MY_INITGUID_H\r
+\r
+#ifdef _WIN32\r
+#ifdef UNDER_CE\r
+#include <basetyps.h>\r
+#endif\r
+#include <initguid.h>\r
+#ifdef UNDER_CE\r
+DEFINE_GUID(IID_IUnknown,\r
+0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);\r
+#endif\r
+#else\r
+#define INITGUID\r
+#include "MyGuidDef.h"\r
+DEFINE_GUID(IID_IUnknown,\r
+0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);\r
+#endif\r
+\r
+#endif\r
diff --git a/CPP/Common/MyMap.cpp b/CPP/Common/MyMap.cpp
new file mode 100755 (executable)
index 0000000..a69c61a
--- /dev/null
@@ -0,0 +1,140 @@
+// MyMap.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "MyMap.h"\r
+\r
+static const unsigned kNumBitsMax = sizeof(UInt32) * 8;\r
+\r
+static UInt32 GetSubBits(UInt32 value, unsigned startPos, unsigned numBits)\r
+{\r
+  if (startPos == sizeof(value) * 8)\r
+    return 0;\r
+  value >>= startPos;\r
+  if (numBits == sizeof(value) * 8)\r
+    return value;\r
+  return value & (((UInt32)1 << numBits) - 1);\r
+}\r
+\r
+static inline unsigned GetSubBit(UInt32 v, unsigned n) { return (unsigned)(v >> n) & 1; }\r
+\r
+bool CMap32::Find(UInt32 key, UInt32 &valueRes) const\r
+{\r
+  valueRes = (UInt32)(Int32)-1;\r
+  if (Nodes.Size() == 0)\r
+    return false;\r
+  if (Nodes.Size() == 1)\r
+  {\r
+    const CNode &n = Nodes[0];\r
+    if (n.Len == kNumBitsMax)\r
+    {\r
+      valueRes = n.Values[0];\r
+      return (key == n.Key);\r
+    }\r
+  }\r
+\r
+  int cur = 0;\r
+  unsigned bitPos = kNumBitsMax;\r
+  for (;;)\r
+  {\r
+    const CNode &n = Nodes[cur];\r
+    bitPos -= n.Len;\r
+    if (GetSubBits(key, bitPos, n.Len) != GetSubBits(n.Key, bitPos, n.Len))\r
+      return false;\r
+    unsigned bit = GetSubBit(key, --bitPos);\r
+    if (n.IsLeaf[bit])\r
+    {\r
+      valueRes = n.Values[bit];\r
+      return (key == n.Keys[bit]);\r
+    }\r
+    cur = (int)n.Keys[bit];\r
+  }\r
+}\r
+\r
+bool CMap32::Set(UInt32 key, UInt32 value)\r
+{\r
+  if (Nodes.Size() == 0)\r
+  {\r
+    CNode n;\r
+    n.Key = n.Keys[0] = n.Keys[1] = key;\r
+    n.Values[0] = n.Values[1] = value;\r
+    n.IsLeaf[0] = n.IsLeaf[1] = 1;\r
+    n.Len = kNumBitsMax;\r
+    Nodes.Add(n);\r
+    return false;\r
+  }\r
+  if (Nodes.Size() == 1)\r
+  {\r
+    CNode &n = Nodes[0];\r
+    if (n.Len == kNumBitsMax)\r
+    {\r
+      if (key == n.Key)\r
+      {\r
+        n.Values[0] = n.Values[1] = value;\r
+        return true;\r
+      }\r
+      unsigned i = kNumBitsMax - 1;\r
+      for (;GetSubBit(key, i) == GetSubBit(n.Key, i); i--);\r
+      n.Len = (UInt16)(kNumBitsMax - (1 + i));\r
+      unsigned newBit = GetSubBit(key, i);\r
+      n.Values[newBit] = value;\r
+      n.Keys[newBit] = key;\r
+      return false;\r
+    }\r
+  }\r
+\r
+  int cur = 0;\r
+  unsigned bitPos = kNumBitsMax;\r
+  for (;;)\r
+  {\r
+    CNode &n = Nodes[cur];\r
+    bitPos -= n.Len;\r
+    if (GetSubBits(key, bitPos, n.Len) != GetSubBits(n.Key, bitPos, n.Len))\r
+    {\r
+      unsigned i = n.Len - 1;\r
+      for (; GetSubBit(key, bitPos + i) == GetSubBit(n.Key, bitPos + i); i--);\r
+      \r
+      CNode e2(n);\r
+      e2.Len = (UInt16)i;\r
+\r
+      n.Len = (UInt16)(n.Len - (1 + i));\r
+      unsigned newBit = GetSubBit(key, bitPos + i);\r
+      n.Values[newBit] = value;\r
+      n.IsLeaf[newBit] = 1;\r
+      n.IsLeaf[1 - newBit] = 0;\r
+      n.Keys[newBit] = key;\r
+      n.Keys[1 - newBit] = Nodes.Size();\r
+      Nodes.Add(e2);\r
+      return false;\r
+    }\r
+    unsigned bit = GetSubBit(key, --bitPos);\r
+\r
+    if (n.IsLeaf[bit])\r
+    {\r
+      if (key == n.Keys[bit])\r
+      {\r
+        n.Values[bit] = value;\r
+        return true;\r
+      }\r
+      unsigned i = bitPos - 1;\r
+      for (;GetSubBit(key, i) == GetSubBit(n.Keys[bit], i); i--);\r
+     \r
+      CNode e2;\r
+      \r
+      unsigned newBit = GetSubBit(key, i);\r
+      e2.Values[newBit] = value;\r
+      e2.Values[1 - newBit] = n.Values[bit];\r
+      e2.IsLeaf[newBit] = e2.IsLeaf[1 - newBit] = 1;\r
+      e2.Keys[newBit] = key;\r
+      e2.Keys[1 - newBit] = e2.Key = n.Keys[bit];\r
+      e2.Len = (UInt16)(bitPos - (1 + i));\r
+\r
+      n.IsLeaf[bit] = 0;\r
+      n.Keys[bit] = Nodes.Size();\r
+\r
+      Nodes.Add(e2);\r
+      return false;\r
+    }\r
+    cur = (int)n.Keys[bit];\r
+  }\r
+}\r
diff --git a/CPP/Common/MyMap.h b/CPP/Common/MyMap.h
new file mode 100755 (executable)
index 0000000..4545bce
--- /dev/null
@@ -0,0 +1,28 @@
+// MyMap.h\r
+\r
+#ifndef __COMMON_MYMAP_H\r
+#define __COMMON_MYMAP_H\r
+\r
+#include "MyVector.h"\r
+#include "Types.h"\r
+\r
+class CMap32\r
+{\r
+  struct CNode\r
+  {\r
+    UInt32 Key;\r
+    UInt32 Keys[2];\r
+    UInt32 Values[2];\r
+    UInt16 Len;\r
+    Byte IsLeaf[2];\r
+  };\r
+  CRecordVector<CNode> Nodes;\r
+\r
+public:\r
+\r
+  void Clear() { Nodes.Clear(); }\r
+  bool Find(UInt32 key, UInt32 &valueRes) const;\r
+  bool Set(UInt32 key, UInt32 value); // returns true, if there is such key already\r
+};\r
+\r
+#endif\r
diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp
new file mode 100755 (executable)
index 0000000..1a25c9e
--- /dev/null
@@ -0,0 +1,200 @@
+// Common/MyString.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#ifndef _WIN32\r
+#include <ctype.h>\r
+#endif\r
+\r
+#ifndef _UNICODE\r
+#include "StringConvert.h"\r
+#endif\r
+\r
+#include "MyString.h"\r
+\r
+\r
+#ifdef _WIN32\r
+\r
+#ifndef _UNICODE\r
+\r
+wchar_t MyCharUpper(wchar_t c)\r
+{\r
+  if (c == 0)\r
+    return 0;\r
+  wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c);\r
+  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)\r
+    return (wchar_t)(unsigned int)(UINT_PTR)res;\r
+  const int kBufferSize = 4;\r
+  char s[kBufferSize + 1];\r
+  int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0);\r
+  if (numChars == 0 || numChars > kBufferSize)\r
+    return c;\r
+  s[numChars] = 0;\r
+  ::CharUpperA(s);\r
+  ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);\r
+  return c;\r
+}\r
+\r
+wchar_t MyCharLower(wchar_t c)\r
+{\r
+  if (c == 0)\r
+    return 0;\r
+  wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c);\r
+  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)\r
+    return (wchar_t)(unsigned int)(UINT_PTR)res;\r
+  const int kBufferSize = 4;\r
+  char s[kBufferSize + 1];\r
+  int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0);\r
+  if (numChars == 0 || numChars > kBufferSize)\r
+    return c;\r
+  s[numChars] = 0;\r
+  ::CharLowerA(s);\r
+  ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);\r
+  return c;\r
+}\r
+\r
+wchar_t * MyStringUpper(wchar_t *s)\r
+{\r
+  if (s == 0)\r
+    return 0;\r
+  wchar_t *res = CharUpperW(s);\r
+  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)\r
+    return res;\r
+  AString a = UnicodeStringToMultiByte(s);\r
+  a.MakeUpper();\r
+  return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));\r
+}\r
+\r
+wchar_t * MyStringLower(wchar_t *s)\r
+{\r
+  if (s == 0)\r
+    return 0;\r
+  wchar_t *res = CharLowerW(s);\r
+  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)\r
+    return res;\r
+  AString a = UnicodeStringToMultiByte(s);\r
+  a.MakeLower();\r
+  return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));\r
+}\r
+\r
+#endif\r
+\r
+/*\r
+inline int ConvertCompareResult(int r) { return r - 2; }\r
+\r
+int MyStringCollate(const wchar_t *s1, const wchar_t *s2)\r
+{\r
+  int res = CompareStringW(\r
+        LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1);\r
+  #ifdef _UNICODE\r
+  return ConvertCompareResult(res);\r
+  #else\r
+  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)\r
+    return ConvertCompareResult(res);\r
+  return MyStringCollate(UnicodeStringToMultiByte(s1),\r
+        UnicodeStringToMultiByte(s2));\r
+  #endif\r
+}\r
+\r
+#ifndef UNDER_CE\r
+int MyStringCollate(const char *s1, const char *s2)\r
+{\r
+  return ConvertCompareResult(CompareStringA(\r
+    LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1));\r
+}\r
+\r
+int MyStringCollateNoCase(const char *s1, const char *s2)\r
+{\r
+  return ConvertCompareResult(CompareStringA(\r
+    LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1));\r
+}\r
+#endif\r
+\r
+int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2)\r
+{\r
+  int res = CompareStringW(\r
+        LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1);\r
+  #ifdef _UNICODE\r
+  return ConvertCompareResult(res);\r
+  #else\r
+  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)\r
+    return ConvertCompareResult(res);\r
+  return MyStringCollateNoCase(UnicodeStringToMultiByte(s1),\r
+      UnicodeStringToMultiByte(s2));\r
+  #endif\r
+}\r
+*/\r
+\r
+#else\r
+\r
+wchar_t MyCharUpper(wchar_t c)\r
+{\r
+  return toupper(c);\r
+}\r
+\r
+/*\r
+int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2)\r
+{\r
+  for (;;)\r
+  {\r
+    wchar_t c1 = *s1++;\r
+    wchar_t c2 = *s2++;\r
+    wchar_t u1 = MyCharUpper(c1);\r
+    wchar_t u2 = MyCharUpper(c2);\r
+\r
+    if (u1 < u2) return -1;\r
+    if (u1 > u2) return 1;\r
+    if (u1 == 0) return 0;\r
+  }\r
+}\r
+*/\r
+\r
+#endif\r
+\r
+int MyStringCompare(const char *s1, const char *s2)\r
+{\r
+  for (;;)\r
+  {\r
+    unsigned char c1 = (unsigned char)*s1++;\r
+    unsigned char c2 = (unsigned char)*s2++;\r
+    if (c1 < c2) return -1;\r
+    if (c1 > c2) return 1;\r
+    if (c1 == 0) return 0;\r
+  }\r
+}\r
+\r
+int MyStringCompare(const wchar_t *s1, const wchar_t *s2)\r
+{\r
+  for (;;)\r
+  {\r
+    wchar_t c1 = *s1++;\r
+    wchar_t c2 = *s2++;\r
+    if (c1 < c2) return -1;\r
+    if (c1 > c2) return 1;\r
+    if (c1 == 0) return 0;\r
+  }\r
+}\r
+\r
+int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2)\r
+{\r
+  for (;;)\r
+  {\r
+    wchar_t c1 = *s1++;\r
+    wchar_t c2 = *s2++;\r
+    if (c1 != c2)\r
+    {\r
+      wchar_t u1 = MyCharUpper(c1);\r
+      wchar_t u2 = MyCharUpper(c2);\r
+      if (u1 < u2) return -1;\r
+      if (u1 > u2) return 1;\r
+    }\r
+    if (c1 == 0) return 0;\r
+  }\r
+}\r
+\r
+/*\r
+int MyStringCompareNoCase(const char *s1, const char *s2)\r
+{\r
+  return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2));\r
+}\r
+*/\r
diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h
new file mode 100755 (executable)
index 0000000..ede2573
--- /dev/null
@@ -0,0 +1,625 @@
+// Common/String.h\r
+\r
+#ifndef __COMMON_STRING_H\r
+#define __COMMON_STRING_H\r
+\r
+#include <string.h>\r
+\r
+#include "MyVector.h"\r
+\r
+template <class T>\r
+inline int MyStringLen(const T *s)\r
+{\r
+  int i;\r
+  for (i = 0; s[i] != '\0'; i++);\r
+  return i;\r
+}\r
+\r
+template <class T>\r
+inline T * MyStringCopy(T *dest, const T *src)\r
+{\r
+  T *destStart = dest;\r
+  while ((*dest++ = *src++) != 0);\r
+  return destStart;\r
+}\r
+\r
+inline wchar_t* MyStringGetNextCharPointer(wchar_t *p)\r
+  { return (p + 1); }\r
+inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p)\r
+  { return (p + 1); }\r
+inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p)\r
+  { return (p - 1); }\r
+inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p)\r
+  { return (p - 1); }\r
+\r
+#ifdef _WIN32\r
+\r
+inline const char* MyStringGetNextCharPointer(const char *p)\r
+{\r
+  #ifdef UNDER_CE\r
+  return p + 1;\r
+  #else\r
+  return CharNextA(p);\r
+  #endif\r
+}\r
+\r
+inline const char* MyStringGetPrevCharPointer(const char *base, const char *p)\r
+  { return CharPrevA(base, p); }\r
+\r
+inline char MyCharUpper(char c)\r
+  { return (char)(unsigned int)(UINT_PTR)CharUpperA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); }\r
+#ifdef _UNICODE\r
+inline wchar_t MyCharUpper(wchar_t c)\r
+  { return (wchar_t)(unsigned int)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); }\r
+#else\r
+wchar_t MyCharUpper(wchar_t c);\r
+#endif\r
+\r
+#ifdef _UNICODE\r
+inline wchar_t MyCharLower(wchar_t c)\r
+  { return (wchar_t)(unsigned int)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); }\r
+#else\r
+wchar_t MyCharLower(wchar_t c);\r
+#endif\r
+\r
+inline char MyCharLower(char c)\r
+#ifdef UNDER_CE\r
+  { return (char)MyCharLower((wchar_t)c); }\r
+#else\r
+  { return (char)(unsigned int)(UINT_PTR)CharLowerA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); }\r
+#endif\r
+\r
+inline char * MyStringUpper(char *s) { return CharUpperA(s); }\r
+#ifdef _UNICODE\r
+inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); }\r
+#else\r
+wchar_t * MyStringUpper(wchar_t *s);\r
+#endif\r
+\r
+inline char * MyStringLower(char *s) { return CharLowerA(s); }\r
+#ifdef _UNICODE\r
+inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); }\r
+#else\r
+wchar_t * MyStringLower(wchar_t *s);\r
+#endif\r
+\r
+#else // Standard-C\r
+wchar_t MyCharUpper(wchar_t c);\r
+#endif\r
+\r
+//////////////////////////////////////\r
+// Compare\r
+\r
+/*\r
+#ifndef UNDER_CE\r
+int MyStringCollate(const char *s1, const char *s2);\r
+int MyStringCollateNoCase(const char *s1, const char *s2);\r
+#endif\r
+int MyStringCollate(const wchar_t *s1, const wchar_t *s2);\r
+int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2);\r
+*/\r
+\r
+int MyStringCompare(const char *s1, const char  *s2);\r
+int MyStringCompare(const wchar_t *s1, const wchar_t *s2);\r
+\r
+// int MyStringCompareNoCase(const char *s1, const char  *s2);\r
+int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2);\r
+\r
+template <class T>\r
+class CStringBase\r
+{\r
+  void TrimLeftWithCharSet(const CStringBase &charSet)\r
+  {\r
+    const T *p = _chars;\r
+    while (charSet.Find(*p) >= 0 && (*p != 0))\r
+      p = GetNextCharPointer(p);\r
+    Delete(0, (int)(p - _chars));\r
+  }\r
+  void TrimRightWithCharSet(const CStringBase &charSet)\r
+  {\r
+    const T *p = _chars;\r
+    const T *pLast = NULL;\r
+    while (*p != 0)\r
+    {\r
+      if (charSet.Find(*p) >= 0)\r
+      {\r
+        if (pLast == NULL)\r
+          pLast = p;\r
+      }\r
+      else\r
+        pLast = NULL;\r
+      p = GetNextCharPointer(p);\r
+    }\r
+    if (pLast != NULL)\r
+    {\r
+      int i = (int)(pLast - _chars);\r
+      Delete(i, _length - i);\r
+    }\r
+\r
+  }\r
+  void MoveItems(int destIndex, int srcIndex)\r
+  {\r
+    memmove(_chars + destIndex, _chars + srcIndex,\r
+        sizeof(T) * (_length - srcIndex + 1));\r
+  }\r
+  \r
+  void InsertSpace(int &index, int size)\r
+  {\r
+    CorrectIndex(index);\r
+    GrowLength(size);\r
+    MoveItems(index + size, index);\r
+  }\r
+\r
+  static const T *GetNextCharPointer(const T *p)\r
+    { return MyStringGetNextCharPointer(p); }\r
+  static const T *GetPrevCharPointer(const T *base, const T *p)\r
+    { return MyStringGetPrevCharPointer(base, p); }\r
+protected:\r
+  T *_chars;\r
+  int _length;\r
+  int _capacity;\r
+  \r
+  void SetCapacity(int newCapacity)\r
+  {\r
+    int realCapacity = newCapacity + 1;\r
+    if (realCapacity == _capacity)\r
+      return;\r
+    /*\r
+    const int kMaxStringSize = 0x20000000;\r
+    if (newCapacity > kMaxStringSize || newCapacity < _length)\r
+      throw 1052337;\r
+    */\r
+    T *newBuffer = new T[realCapacity];\r
+    if (_capacity > 0)\r
+    {\r
+      for (int i = 0; i < _length; i++)\r
+        newBuffer[i] = _chars[i];\r
+      delete []_chars;\r
+    }\r
+    _chars = newBuffer;\r
+    _chars[_length] = 0;\r
+    _capacity = realCapacity;\r
+  }\r
+\r
+  void GrowLength(int n)\r
+  {\r
+    int freeSize = _capacity - _length - 1;\r
+    if (n <= freeSize)\r
+      return;\r
+    int delta;\r
+    if (_capacity > 64)\r
+      delta = _capacity / 2;\r
+    else if (_capacity > 8)\r
+      delta = 16;\r
+    else\r
+      delta = 4;\r
+    if (freeSize + delta < n)\r
+      delta = n - freeSize;\r
+    SetCapacity(_capacity + delta);\r
+  }\r
+\r
+  void CorrectIndex(int &index) const\r
+  {\r
+    if (index > _length)\r
+      index = _length;\r
+  }\r
+\r
+public:\r
+  CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(3); }\r
+  CStringBase(T c):  _chars(0), _length(0), _capacity(0)\r
+  {\r
+    SetCapacity(1);\r
+    _chars[0] = c;\r
+    _chars[1] = 0;\r
+    _length = 1;\r
+  }\r
+  CStringBase(const T *chars): _chars(0), _length(0), _capacity(0)\r
+  {\r
+    int length = MyStringLen(chars);\r
+    SetCapacity(length);\r
+    MyStringCopy(_chars, chars); // can be optimized by memove()\r
+    _length = length;\r
+  }\r
+  CStringBase(const CStringBase &s):  _chars(0), _length(0), _capacity(0)\r
+  {\r
+    SetCapacity(s._length);\r
+    MyStringCopy(_chars, s._chars);\r
+    _length = s._length;\r
+  }\r
+  ~CStringBase() {  delete []_chars; }\r
+\r
+  operator const T*() const { return _chars;}\r
+\r
+  T Back() const { return _chars[_length - 1]; }\r
+\r
+  // The minimum size of the character buffer in characters.\r
+  // This value does not include space for a null terminator.\r
+  T* GetBuffer(int minBufLength)\r
+  {\r
+    if (minBufLength >= _capacity)\r
+      SetCapacity(minBufLength);\r
+    return _chars;\r
+  }\r
+  void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }\r
+  void ReleaseBuffer(int newLength)\r
+  {\r
+    /*\r
+    if (newLength >= _capacity)\r
+      throw 282217;\r
+    */\r
+    _chars[newLength] = 0;\r
+    _length = newLength;\r
+  }\r
+\r
+  CStringBase& operator=(T c)\r
+  {\r
+    Empty();\r
+    SetCapacity(1);\r
+    _chars[0] = c;\r
+    _chars[1] = 0;\r
+    _length = 1;\r
+    return *this;\r
+  }\r
+  CStringBase& operator=(const T *chars)\r
+  {\r
+    Empty();\r
+    int length = MyStringLen(chars);\r
+    SetCapacity(length);\r
+    MyStringCopy(_chars, chars);\r
+    _length = length;\r
+    return *this;\r
+  }\r
+  CStringBase& operator=(const CStringBase& s)\r
+  {\r
+    if (&s == this)\r
+      return *this;\r
+    Empty();\r
+    SetCapacity(s._length);\r
+    MyStringCopy(_chars, s._chars);\r
+    _length = s._length;\r
+    return *this;\r
+  }\r
+  \r
+  CStringBase& operator+=(T c)\r
+  {\r
+    GrowLength(1);\r
+    _chars[_length] = c;\r
+    _chars[++_length] = 0;\r
+    return *this;\r
+  }\r
+  CStringBase& operator+=(const T *s)\r
+  {\r
+    int len = MyStringLen(s);\r
+    GrowLength(len);\r
+    MyStringCopy(_chars + _length, s);\r
+    _length += len;\r
+    return *this;\r
+  }\r
+  CStringBase& operator+=(const CStringBase &s)\r
+  {\r
+    GrowLength(s._length);\r
+    MyStringCopy(_chars + _length, s._chars);\r
+    _length += s._length;\r
+    return *this;\r
+  }\r
+  void Empty()\r
+  {\r
+    _length = 0;\r
+    _chars[0] = 0;\r
+  }\r
+  int Length() const { return _length; }\r
+  bool IsEmpty() const { return (_length == 0); }\r
+\r
+  CStringBase Mid(int startIndex) const\r
+    { return Mid(startIndex, _length - startIndex); }\r
+  CStringBase Mid(int startIndex, int count) const\r
+  {\r
+    if (startIndex + count > _length)\r
+      count = _length - startIndex;\r
+    \r
+    if (startIndex == 0 && startIndex + count == _length)\r
+      return *this;\r
+    \r
+    CStringBase<T> result;\r
+    result.SetCapacity(count);\r
+    // MyStringNCopy(result._chars, _chars + startIndex, count);\r
+    for (int i = 0; i < count; i++)\r
+      result._chars[i] = _chars[startIndex + i];\r
+    result._chars[count] = 0;\r
+    result._length = count;\r
+    return result;\r
+  }\r
+  CStringBase Left(int count) const\r
+    { return Mid(0, count); }\r
+  CStringBase Right(int count) const\r
+  {\r
+    if (count > _length)\r
+      count = _length;\r
+    return Mid(_length - count, count);\r
+  }\r
+\r
+  void MakeUpper()\r
+    { MyStringUpper(_chars); }\r
+  void MakeLower()\r
+    { MyStringLower(_chars); }\r
+\r
+  int Compare(const CStringBase& s) const\r
+    { return MyStringCompare(_chars, s._chars); }\r
+\r
+  int Compare(const T *s) const\r
+    { return MyStringCompare(_chars, s); }\r
+\r
+  int CompareNoCase(const CStringBase& s) const\r
+    { return MyStringCompareNoCase(_chars, s._chars); }\r
+\r
+  int CompareNoCase(const T *s) const\r
+    { return MyStringCompareNoCase(_chars, s); }\r
+\r
+  /*\r
+  int Collate(const CStringBase& s) const\r
+    { return MyStringCollate(_chars, s._chars); }\r
+  int CollateNoCase(const CStringBase& s) const\r
+    { return MyStringCollateNoCase(_chars, s._chars); }\r
+  */\r
+\r
+  int Find(T c) const { return Find(c, 0); }\r
+  int Find(T c, int startIndex) const\r
+  {\r
+    const T *p = _chars + startIndex;\r
+    for (;;)\r
+    {\r
+      if (*p == c)\r
+        return (int)(p - _chars);\r
+      if (*p == 0)\r
+        return -1;\r
+      p = GetNextCharPointer(p);\r
+    }\r
+  }\r
+  int Find(const CStringBase &s) const { return Find(s, 0); }\r
+  int Find(const CStringBase &s, int startIndex) const\r
+  {\r
+    if (s.IsEmpty())\r
+      return startIndex;\r
+    for (; startIndex < _length; startIndex++)\r
+    {\r
+      int j;\r
+      for (j = 0; j < s._length && startIndex + j < _length; j++)\r
+        if (_chars[startIndex+j] != s._chars[j])\r
+          break;\r
+      if (j == s._length)\r
+        return startIndex;\r
+    }\r
+    return -1;\r
+  }\r
+  int ReverseFind(T c) const\r
+  {\r
+    if (_length == 0)\r
+      return -1;\r
+    const T *p = _chars + _length - 1;\r
+    for (;;)\r
+    {\r
+      if (*p == c)\r
+        return (int)(p - _chars);\r
+      if (p == _chars)\r
+        return -1;\r
+      p = GetPrevCharPointer(_chars, p);\r
+    }\r
+  }\r
+  int FindOneOf(const CStringBase &s) const\r
+  {\r
+    for (int i = 0; i < _length; i++)\r
+      if (s.Find(_chars[i]) >= 0)\r
+        return i;\r
+      return -1;\r
+  }\r
+\r
+  void TrimLeft(T c)\r
+  {\r
+    const T *p = _chars;\r
+    while (c == *p)\r
+      p = GetNextCharPointer(p);\r
+    Delete(0, p - _chars);\r
+  }\r
+  private:\r
+  CStringBase GetTrimDefaultCharSet()\r
+  {\r
+    CStringBase<T> charSet;\r
+    charSet += (T)' ';\r
+    charSet += (T)'\n';\r
+    charSet += (T)'\t';\r
+    return charSet;\r
+  }\r
+  public:\r
+\r
+  void TrimLeft()\r
+  {\r
+    TrimLeftWithCharSet(GetTrimDefaultCharSet());\r
+  }\r
+  void TrimRight()\r
+  {\r
+    TrimRightWithCharSet(GetTrimDefaultCharSet());\r
+  }\r
+  void TrimRight(T c)\r
+  {\r
+    const T *p = _chars;\r
+    const T *pLast = NULL;\r
+    while (*p != 0)\r
+    {\r
+      if (*p == c)\r
+      {\r
+        if (pLast == NULL)\r
+          pLast = p;\r
+      }\r
+      else\r
+        pLast = NULL;\r
+      p = GetNextCharPointer(p);\r
+    }\r
+    if (pLast != NULL)\r
+    {\r
+      int i = pLast - _chars;\r
+      Delete(i, _length - i);\r
+    }\r
+  }\r
+  void Trim()\r
+  {\r
+    TrimRight();\r
+    TrimLeft();\r
+  }\r
+\r
+  int Insert(int index, T c)\r
+  {\r
+    InsertSpace(index, 1);\r
+    _chars[index] = c;\r
+    _length++;\r
+    return _length;\r
+  }\r
+  int Insert(int index, const CStringBase &s)\r
+  {\r
+    CorrectIndex(index);\r
+    if (s.IsEmpty())\r
+      return _length;\r
+    int numInsertChars = s.Length();\r
+    InsertSpace(index, numInsertChars);\r
+    for (int i = 0; i < numInsertChars; i++)\r
+      _chars[index + i] = s[i];\r
+    _length += numInsertChars;\r
+    return _length;\r
+  }\r
+\r
+  // !!!!!!!!!!!!!!! test it if newChar = '\0'\r
+  int Replace(T oldChar, T newChar)\r
+  {\r
+    if (oldChar == newChar)\r
+      return 0;\r
+    int number  = 0;\r
+    int pos  = 0;\r
+    while (pos < Length())\r
+    {\r
+      pos = Find(oldChar, pos);\r
+      if (pos < 0)\r
+        break;\r
+      _chars[pos] = newChar;\r
+      pos++;\r
+      number++;\r
+    }\r
+    return number;\r
+  }\r
+  int Replace(const CStringBase &oldString, const CStringBase &newString)\r
+  {\r
+    if (oldString.IsEmpty())\r
+      return 0;\r
+    if (oldString == newString)\r
+      return 0;\r
+    int oldStringLength = oldString.Length();\r
+    int newStringLength = newString.Length();\r
+    int number  = 0;\r
+    int pos  = 0;\r
+    while (pos < _length)\r
+    {\r
+      pos = Find(oldString, pos);\r
+      if (pos < 0)\r
+        break;\r
+      Delete(pos, oldStringLength);\r
+      Insert(pos, newString);\r
+      pos += newStringLength;\r
+      number++;\r
+    }\r
+    return number;\r
+  }\r
+  int Delete(int index, int count = 1)\r
+  {\r
+    if (index + count > _length)\r
+      count = _length - index;\r
+    if (count > 0)\r
+    {\r
+      MoveItems(index, index + count);\r
+      _length -= count;\r
+    }\r
+    return _length;\r
+  }\r
+  void DeleteBack() { Delete(_length - 1); }\r
+};\r
+\r
+template <class T>\r
+CStringBase<T> operator+(const CStringBase<T>& s1, const CStringBase<T>& s2)\r
+{\r
+  CStringBase<T> result(s1);\r
+  result += s2;\r
+  return result;\r
+}\r
+\r
+template <class T>\r
+CStringBase<T> operator+(const CStringBase<T>& s, T c)\r
+{\r
+  CStringBase<T> result(s);\r
+  result += c;\r
+  return result;\r
+}\r
+\r
+template <class T>\r
+CStringBase<T> operator+(T c, const CStringBase<T>& s)\r
+{\r
+  CStringBase<T> result(c);\r
+  result += s;\r
+  return result;\r
+}\r
+\r
+template <class T>\r
+CStringBase<T> operator+(const CStringBase<T>& s, const T * chars)\r
+{\r
+  CStringBase<T> result(s);\r
+  result += chars;\r
+  return result;\r
+}\r
+\r
+template <class T>\r
+CStringBase<T> operator+(const T * chars, const CStringBase<T>& s)\r
+{\r
+  CStringBase<T> result(chars);\r
+  result += s;\r
+  return result;\r
+}\r
+\r
+template <class T>\r
+bool operator==(const CStringBase<T>& s1, const CStringBase<T>& s2)\r
+  { return (s1.Compare(s2) == 0); }\r
+\r
+template <class T>\r
+bool operator<(const CStringBase<T>& s1, const CStringBase<T>& s2)\r
+  { return (s1.Compare(s2) < 0); }\r
+\r
+template <class T>\r
+bool operator==(const T *s1, const CStringBase<T>& s2)\r
+  { return (s2.Compare(s1) == 0); }\r
+\r
+template <class T>\r
+bool operator==(const CStringBase<T>& s1, const T *s2)\r
+  { return (s1.Compare(s2) == 0); }\r
+\r
+template <class T>\r
+bool operator!=(const CStringBase<T>& s1, const CStringBase<T>& s2)\r
+  { return (s1.Compare(s2) != 0); }\r
+\r
+template <class T>\r
+bool operator!=(const T *s1, const CStringBase<T>& s2)\r
+  { return (s2.Compare(s1) != 0); }\r
+\r
+template <class T>\r
+bool operator!=(const CStringBase<T>& s1, const T *s2)\r
+  { return (s1.Compare(s2) != 0); }\r
+\r
+typedef CStringBase<char> AString;\r
+typedef CStringBase<wchar_t> UString;\r
+\r
+typedef CObjectVector<AString> AStringVector;\r
+typedef CObjectVector<UString> UStringVector;\r
+\r
+#ifdef _UNICODE\r
+  typedef UString CSysString;\r
+#else\r
+  typedef AString CSysString;\r
+#endif\r
+\r
+typedef CObjectVector<CSysString> CSysStringVector;\r
+\r
+#endif\r
diff --git a/CPP/Common/MyUnknown.h b/CPP/Common/MyUnknown.h
new file mode 100755 (executable)
index 0000000..7935124
--- /dev/null
@@ -0,0 +1,13 @@
+// MyUnknown.h\r
+\r
+#ifndef __MY_UNKNOWN_H\r
+#define __MY_UNKNOWN_H\r
+\r
+#ifdef _WIN32\r
+#include <basetyps.h>\r
+#include <unknwn.h>\r
+#else\r
+#include "MyWindows.h"\r
+#endif\r
+  \r
+#endif\r
diff --git a/CPP/Common/MyVector.cpp b/CPP/Common/MyVector.cpp
new file mode 100755 (executable)
index 0000000..054d0aa
--- /dev/null
@@ -0,0 +1,87 @@
+// Common/MyVector.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include <string.h>\r
+\r
+#include "MyVector.h"\r
+\r
+CBaseRecordVector::~CBaseRecordVector() { ClearAndFree(); }\r
+\r
+void CBaseRecordVector::ClearAndFree()\r
+{\r
+  Clear();\r
+  delete []((unsigned char *)_items);\r
+  _capacity = 0;\r
+  _size = 0;\r
+  _items = 0;\r
+}\r
+\r
+void CBaseRecordVector::Clear() { DeleteFrom(0); }\r
+void CBaseRecordVector::DeleteBack() { Delete(_size - 1); }\r
+void CBaseRecordVector::DeleteFrom(int index) { Delete(index, _size - index); }\r
+\r
+void CBaseRecordVector::ReserveOnePosition()\r
+{\r
+  if (_size != _capacity)\r
+    return;\r
+  unsigned delta = 1;\r
+  if (_capacity >= 64)\r
+    delta = (unsigned)_capacity / 4;\r
+  else if (_capacity >= 8)\r
+    delta = 8;\r
+  Reserve(_capacity + (int)delta);\r
+}\r
+\r
+void CBaseRecordVector::Reserve(int newCapacity)\r
+{\r
+  // if (newCapacity <= _capacity)\r
+  if (newCapacity == _capacity)\r
+    return;\r
+  if ((unsigned)newCapacity >= ((unsigned)1 << (sizeof(unsigned) * 8 - 1)))\r
+    throw 1052353;\r
+  size_t newSize = (size_t)(unsigned)newCapacity * _itemSize;\r
+  if (newSize / _itemSize != (size_t)(unsigned)newCapacity)\r
+    throw 1052354;\r
+  unsigned char *p = NULL;\r
+  if (newSize > 0)\r
+  {\r
+    p = new unsigned char[newSize];\r
+    if (p == 0)\r
+      throw 1052355;\r
+    int numRecordsToMove = (_size < newCapacity ? _size : newCapacity);\r
+    memcpy(p, _items, _itemSize * numRecordsToMove);\r
+  }\r
+  delete [](unsigned char *)_items;\r
+  _items = p;\r
+  _capacity = newCapacity;\r
+}\r
+\r
+void CBaseRecordVector::ReserveDown()\r
+{\r
+  Reserve(_size);\r
+}\r
+\r
+void CBaseRecordVector::MoveItems(int destIndex, int srcIndex)\r
+{\r
+  memmove(((unsigned char *)_items) + destIndex * _itemSize,\r
+    ((unsigned char  *)_items) + srcIndex * _itemSize,\r
+    _itemSize * (_size - srcIndex));\r
+}\r
+\r
+void CBaseRecordVector::InsertOneItem(int index)\r
+{\r
+  ReserveOnePosition();\r
+  MoveItems(index + 1, index);\r
+  _size++;\r
+}\r
+\r
+void CBaseRecordVector::Delete(int index, int num)\r
+{\r
+  TestIndexAndCorrectNum(index, num);\r
+  if (num > 0)\r
+  {\r
+    MoveItems(index, index + num);\r
+    _size -= num;\r
+  }\r
+}\r
diff --git a/CPP/Common/MyVector.h b/CPP/Common/MyVector.h
new file mode 100755 (executable)
index 0000000..24740dc
--- /dev/null
@@ -0,0 +1,266 @@
+// Common/Vector.h\r
+\r
+#ifndef __COMMON_VECTOR_H\r
+#define __COMMON_VECTOR_H\r
+\r
+#include "Defs.h"\r
+\r
+class CBaseRecordVector\r
+{\r
+  void MoveItems(int destIndex, int srcIndex);\r
+protected:\r
+  int _capacity;\r
+  int _size;\r
+  void *_items;\r
+  size_t _itemSize;\r
+  \r
+  void ReserveOnePosition();\r
+  void InsertOneItem(int index);\r
+  void TestIndexAndCorrectNum(int index, int &num) const\r
+    { if (index + num > _size) num = _size - index; }\r
+public:\r
+  CBaseRecordVector(size_t itemSize): _capacity(0), _size(0), _items(0), _itemSize(itemSize) {}\r
+  virtual ~CBaseRecordVector();\r
+  void ClearAndFree();\r
+  int Size() const { return _size; }\r
+  bool IsEmpty() const { return (_size == 0); }\r
+  void Reserve(int newCapacity);\r
+  void ReserveDown();\r
+  virtual void Delete(int index, int num = 1);\r
+  void Clear();\r
+  void DeleteFrom(int index);\r
+  void DeleteBack();\r
+};\r
+\r
+template <class T>\r
+class CRecordVector: public CBaseRecordVector\r
+{\r
+public:\r
+  CRecordVector(): CBaseRecordVector(sizeof(T)){};\r
+  CRecordVector(const CRecordVector &v): CBaseRecordVector(sizeof(T)) { *this = v; }\r
+  CRecordVector& operator=(const CRecordVector &v)\r
+  {\r
+    Clear();\r
+    return (*this += v);\r
+  }\r
+  CRecordVector& operator+=(const CRecordVector &v)\r
+  {\r
+    int size = v.Size();\r
+    Reserve(Size() + size);\r
+    for (int i = 0; i < size; i++)\r
+      Add(v[i]);\r
+    return *this;\r
+  }\r
+  int Add(T item)\r
+  {\r
+    ReserveOnePosition();\r
+    ((T *)_items)[_size] = item;\r
+    return _size++;\r
+  }\r
+  void Insert(int index, T item)\r
+  {\r
+    InsertOneItem(index);\r
+    ((T *)_items)[index] = item;\r
+  }\r
+  // T* GetPointer() const { return (T*)_items; }\r
+  // operator const T *() const { return _items; };\r
+  const T& operator[](int index) const { return ((T *)_items)[index]; }\r
+  T& operator[](int index) { return ((T *)_items)[index]; }\r
+  const T& Front() const { return operator[](0); }\r
+  T& Front() { return operator[](0); }\r
+  const T& Back() const { return operator[](_size - 1); }\r
+  T& Back() { return operator[](_size - 1); }\r
+\r
+  void Swap(int i, int j)\r
+  {\r
+    T temp = operator[](i);\r
+    operator[](i) = operator[](j);\r
+    operator[](j) = temp;\r
+  }\r
+\r
+  int FindInSorted(const T& item, int left, int right) const\r
+  {\r
+    while (left != right)\r
+    {\r
+      int mid = (left + right) / 2;\r
+      const T& midValue = (*this)[mid];\r
+      if (item == midValue)\r
+        return mid;\r
+      if (item < midValue)\r
+        right = mid;\r
+      else\r
+        left = mid + 1;\r
+    }\r
+    return -1;\r
+  }\r
+\r
+  int FindInSorted(const T& item) const\r
+  {\r
+    int left = 0, right = Size();\r
+    while (left != right)\r
+    {\r
+      int mid = (left + right) / 2;\r
+      const T& midValue = (*this)[mid];\r
+      if (item == midValue)\r
+        return mid;\r
+      if (item < midValue)\r
+        right = mid;\r
+      else\r
+        left = mid + 1;\r
+    }\r
+    return -1;\r
+  }\r
+\r
+  int AddToUniqueSorted(const T& item)\r
+  {\r
+    int left = 0, right = Size();\r
+    while (left != right)\r
+    {\r
+      int mid = (left + right) / 2;\r
+      const T& midValue = (*this)[mid];\r
+      if (item == midValue)\r
+        return mid;\r
+      if (item < midValue)\r
+        right = mid;\r
+      else\r
+        left = mid + 1;\r
+    }\r
+    Insert(right, item);\r
+    return right;\r
+  }\r
+\r
+  static void SortRefDown(T* p, int k, int size, int (*compare)(const T*, const T*, void *), void *param)\r
+  {\r
+    T temp = p[k];\r
+    for (;;)\r
+    {\r
+      int s = (k << 1);\r
+      if (s > size)\r
+        break;\r
+      if (s < size && compare(p + s + 1, p + s, param) > 0)\r
+        s++;\r
+      if (compare(&temp, p + s, param) >= 0)\r
+        break;\r
+      p[k] = p[s];\r
+      k = s;\r
+    }\r
+    p[k] = temp;\r
+  }\r
+\r
+  void Sort(int (*compare)(const T*, const T*, void *), void *param)\r
+  {\r
+    int size = _size;\r
+    if (size <= 1)\r
+      return;\r
+    T* p = (&Front()) - 1;\r
+    {\r
+      int i = size / 2;\r
+      do\r
+        SortRefDown(p, i, size, compare, param);\r
+      while (--i != 0);\r
+    }\r
+    do\r
+    {\r
+      T temp = p[size];\r
+      p[size--] = p[1];\r
+      p[1] = temp;\r
+      SortRefDown(p, 1, size, compare, param);\r
+    }\r
+    while (size > 1);\r
+  }\r
+};\r
+\r
+typedef CRecordVector<int> CIntVector;\r
+typedef CRecordVector<unsigned int> CUIntVector;\r
+typedef CRecordVector<bool> CBoolVector;\r
+typedef CRecordVector<unsigned char> CByteVector;\r
+typedef CRecordVector<void *> CPointerVector;\r
+\r
+template <class T>\r
+class CObjectVector: public CPointerVector\r
+{\r
+public:\r
+  CObjectVector() {};\r
+  ~CObjectVector() { Clear(); };\r
+  CObjectVector(const CObjectVector &v): CPointerVector() { *this = v; }\r
+  CObjectVector& operator=(const CObjectVector &v)\r
+  {\r
+    Clear();\r
+    return (*this += v);\r
+  }\r
+  CObjectVector& operator+=(const CObjectVector &v)\r
+  {\r
+    int size = v.Size();\r
+    Reserve(Size() + size);\r
+    for (int i = 0; i < size; i++)\r
+      Add(v[i]);\r
+    return *this;\r
+  }\r
+  const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); }\r
+  T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); }\r
+  T& Front() { return operator[](0); }\r
+  const T& Front() const { return operator[](0); }\r
+  T& Back() { return operator[](_size - 1); }\r
+  const T& Back() const { return operator[](_size - 1); }\r
+  int Add(const T& item) { return CPointerVector::Add(new T(item)); }\r
+  void Insert(int index, const T& item) { CPointerVector::Insert(index, new T(item)); }\r
+  virtual void Delete(int index, int num = 1)\r
+  {\r
+    TestIndexAndCorrectNum(index, num);\r
+    for (int i = 0; i < num; i++)\r
+      delete (T *)(((void **)_items)[index + i]);\r
+    CPointerVector::Delete(index, num);\r
+  }\r
+  int Find(const T& item) const\r
+  {\r
+    for (int i = 0; i < Size(); i++)\r
+      if (item == (*this)[i])\r
+        return i;\r
+    return -1;\r
+  }\r
+  int FindInSorted(const T& item) const\r
+  {\r
+    int left = 0, right = Size();\r
+    while (left != right)\r
+    {\r
+      int mid = (left + right) / 2;\r
+      const T& midValue = (*this)[mid];\r
+      if (item == midValue)\r
+        return mid;\r
+      if (item < midValue)\r
+        right = mid;\r
+      else\r
+        left = mid + 1;\r
+    }\r
+    return -1;\r
+  }\r
+  int AddToSorted(const T& item)\r
+  {\r
+    int left = 0, right = Size();\r
+    while (left != right)\r
+    {\r
+      int mid = (left + right) / 2;\r
+      const T& midValue = (*this)[mid];\r
+      if (item == midValue)\r
+      {\r
+        right = mid + 1;\r
+        break;\r
+      }\r
+      if (item < midValue)\r
+        right = mid;\r
+      else\r
+        left = mid + 1;\r
+    }\r
+    Insert(right, item);\r
+    return right;\r
+  }\r
+\r
+  void Sort(int (*compare)(void *const *, void *const *, void *), void *param)\r
+    { CPointerVector::Sort(compare, param); }\r
+\r
+  static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */)\r
+    { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); }\r
+  void Sort() { CPointerVector::Sort(CompareObjectItems, 0); }\r
+};\r
+\r
+#endif\r
diff --git a/CPP/Common/MyWindows.cpp b/CPP/Common/MyWindows.cpp
new file mode 100755 (executable)
index 0000000..9e246af
--- /dev/null
@@ -0,0 +1,109 @@
+// MyWindows.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#ifndef _WIN32\r
+\r
+#include "MyWindows.h"\r
+#include "Types.h"\r
+#include <malloc.h>\r
+\r
+static inline void *AllocateForBSTR(size_t cb) { return ::malloc(cb); }\r
+static inline void FreeForBSTR(void *pv) { ::free(pv);}\r
+\r
+static UINT MyStringLen(const wchar_t *s)\r
+{\r
+  UINT i;\r
+  for (i = 0; s[i] != '\0'; i++);\r
+  return i;\r
+}\r
+\r
+BSTR SysAllocStringByteLen(LPCSTR psz, UINT len)\r
+{\r
+  int realLen = len + sizeof(UINT) + sizeof(OLECHAR) + sizeof(OLECHAR);\r
+  void *p = AllocateForBSTR(realLen);\r
+  if (p == 0)\r
+    return 0;\r
+  *(UINT *)p = len;\r
+  BSTR bstr = (BSTR)((UINT *)p + 1);\r
+  memmove(bstr, psz, len);\r
+  Byte *pb = ((Byte *)bstr) + len;\r
+  for (int i = 0; i < sizeof(OLECHAR) * 2; i++)\r
+    pb[i] = 0;\r
+  return bstr;\r
+}\r
+\r
+BSTR SysAllocString(const OLECHAR *sz)\r
+{\r
+  if (sz == 0)\r
+    return 0;\r
+  UINT strLen = MyStringLen(sz);\r
+  UINT len = (strLen + 1) * sizeof(OLECHAR);\r
+  void *p = AllocateForBSTR(len + sizeof(UINT));\r
+  if (p == 0)\r
+    return 0;\r
+  *(UINT *)p = strLen;\r
+  BSTR bstr = (BSTR)((UINT *)p + 1);\r
+  memmove(bstr, sz, len);\r
+  return bstr;\r
+}\r
+\r
+void SysFreeString(BSTR bstr)\r
+{\r
+  if (bstr != 0)\r
+    FreeForBSTR((UINT *)bstr - 1);\r
+}\r
+\r
+UINT SysStringByteLen(BSTR bstr)\r
+{\r
+  if (bstr == 0)\r
+    return 0;\r
+  return *((UINT *)bstr - 1);\r
+}\r
+\r
+UINT SysStringLen(BSTR bstr)\r
+{\r
+  return SysStringByteLen(bstr) / sizeof(OLECHAR);\r
+}\r
+\r
+HRESULT VariantClear(VARIANTARG *prop)\r
+{\r
+  if (prop->vt == VT_BSTR)\r
+    SysFreeString(prop->bstrVal);\r
+  prop->vt = VT_EMPTY;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src)\r
+{\r
+  HRESULT res = ::VariantClear(dest);\r
+  if (res != S_OK)\r
+    return res;\r
+  if (src->vt == VT_BSTR)\r
+  {\r
+    dest->bstrVal = SysAllocStringByteLen((LPCSTR)src->bstrVal,\r
+        SysStringByteLen(src->bstrVal));\r
+    if (dest->bstrVal == 0)\r
+      return E_OUTOFMEMORY;\r
+    dest->vt = VT_BSTR;\r
+  }\r
+  else\r
+    *dest = *src;\r
+  return S_OK;\r
+}\r
+\r
+LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2)\r
+{\r
+  if (ft1->dwHighDateTime < ft2->dwHighDateTime) return -1;\r
+  if (ft1->dwHighDateTime > ft2->dwHighDateTime) return 1;\r
+  if (ft1->dwLowDateTime < ft2->dwLowDateTime) return -1;\r
+  if (ft1->dwLowDateTime > ft2->dwLowDateTime) return 1;\r
+  return 0;\r
+}\r
+\r
+DWORD GetLastError()\r
+{\r
+  return 0;\r
+}\r
+\r
+#endif\r
diff --git a/CPP/Common/MyWindows.h b/CPP/Common/MyWindows.h
new file mode 100755 (executable)
index 0000000..5cfded1
--- /dev/null
@@ -0,0 +1,204 @@
+// MyWindows.h\r
+\r
+#ifndef __MYWINDOWS_H\r
+#define __MYWINDOWS_H\r
+\r
+#ifdef _WIN32\r
+\r
+#include <windows.h>\r
+\r
+#else\r
+\r
+#include <stddef.h> // for wchar_t\r
+#include <string.h>\r
+\r
+#include "MyGuidDef.h"\r
+\r
+typedef char CHAR;\r
+typedef unsigned char UCHAR;\r
+\r
+#undef BYTE\r
+typedef unsigned char BYTE;\r
+\r
+typedef short SHORT;\r
+typedef unsigned short USHORT;\r
+\r
+#undef WORD\r
+typedef unsigned short WORD;\r
+typedef short VARIANT_BOOL;\r
+\r
+typedef int INT;\r
+typedef Int32 INT32;\r
+typedef unsigned int UINT;\r
+typedef UInt32 UINT32;\r
+typedef INT32 LONG;   // LONG, ULONG and DWORD must be 32-bit\r
+typedef UINT32 ULONG;\r
+\r
+#undef DWORD\r
+typedef UINT32 DWORD;\r
+\r
+typedef Int64 LONGLONG;\r
+typedef UInt64 ULONGLONG;\r
+\r
+typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER;\r
+typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER;\r
+\r
+typedef const CHAR *LPCSTR;\r
+typedef CHAR TCHAR;\r
+typedef const TCHAR *LPCTSTR;\r
+typedef wchar_t WCHAR;\r
+typedef WCHAR OLECHAR;\r
+typedef const WCHAR *LPCWSTR;\r
+typedef OLECHAR *BSTR;\r
+typedef const OLECHAR *LPCOLESTR;\r
+typedef OLECHAR *LPOLESTR;\r
+\r
+typedef struct _FILETIME\r
+{\r
+  DWORD dwLowDateTime;\r
+  DWORD dwHighDateTime;\r
+}FILETIME;\r
+\r
+#define HRESULT LONG\r
+#define FAILED(Status) ((HRESULT)(Status)<0)\r
+typedef ULONG PROPID;\r
+typedef LONG SCODE;\r
+\r
+#define S_OK    ((HRESULT)0x00000000L)\r
+#define S_FALSE ((HRESULT)0x00000001L)\r
+#define E_NOTIMPL ((HRESULT)0x80004001L)\r
+#define E_NOINTERFACE ((HRESULT)0x80004002L)\r
+#define E_ABORT ((HRESULT)0x80004004L)\r
+#define E_FAIL ((HRESULT)0x80004005L)\r
+#define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L)\r
+#define E_OUTOFMEMORY ((HRESULT)0x8007000EL)\r
+#define E_INVALIDARG ((HRESULT)0x80070057L)\r
+\r
+#ifdef _MSC_VER\r
+#define STDMETHODCALLTYPE __stdcall\r
+#else\r
+#define STDMETHODCALLTYPE\r
+#endif\r
+\r
+#define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f\r
+#define STDMETHOD(f) STDMETHOD_(HRESULT, f)\r
+#define STDMETHODIMP_(type) type STDMETHODCALLTYPE\r
+#define STDMETHODIMP STDMETHODIMP_(HRESULT)\r
+\r
+#define PURE = 0\r
+\r
+#define MIDL_INTERFACE(x) struct\r
+\r
+#ifdef __cplusplus\r
+\r
+DEFINE_GUID(IID_IUnknown,\r
+0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);\r
+struct IUnknown\r
+{\r
+  STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE;\r
+  STDMETHOD_(ULONG, AddRef)() PURE;\r
+  STDMETHOD_(ULONG, Release)() PURE;\r
+  #ifndef _WIN32\r
+  virtual ~IUnknown() {}\r
+  #endif\r
+};\r
+\r
+typedef IUnknown *LPUNKNOWN;\r
+\r
+#endif\r
+\r
+#define VARIANT_TRUE ((VARIANT_BOOL)-1)\r
+#define VARIANT_FALSE ((VARIANT_BOOL)0)\r
+\r
+enum VARENUM\r
+{\r
+  VT_EMPTY = 0,\r
+  VT_NULL = 1,\r
+  VT_I2 = 2,\r
+  VT_I4 = 3,\r
+  VT_R4 = 4,\r
+  VT_R8 = 5,\r
+  VT_CY = 6,\r
+  VT_DATE = 7,\r
+  VT_BSTR = 8,\r
+  VT_DISPATCH = 9,\r
+  VT_ERROR = 10,\r
+  VT_BOOL = 11,\r
+  VT_VARIANT = 12,\r
+  VT_UNKNOWN = 13,\r
+  VT_DECIMAL = 14,\r
+  VT_I1 = 16,\r
+  VT_UI1 = 17,\r
+  VT_UI2 = 18,\r
+  VT_UI4 = 19,\r
+  VT_I8 = 20,\r
+  VT_UI8 = 21,\r
+  VT_INT = 22,\r
+  VT_UINT = 23,\r
+  VT_VOID = 24,\r
+  VT_HRESULT = 25,\r
+  VT_FILETIME = 64\r
+};\r
+\r
+typedef unsigned short VARTYPE;\r
+typedef WORD PROPVAR_PAD1;\r
+typedef WORD PROPVAR_PAD2;\r
+typedef WORD PROPVAR_PAD3;\r
+\r
+#ifdef __cplusplus\r
+\r
+typedef struct tagPROPVARIANT\r
+{\r
+  VARTYPE vt;\r
+  PROPVAR_PAD1 wReserved1;\r
+  PROPVAR_PAD2 wReserved2;\r
+  PROPVAR_PAD3 wReserved3;\r
+  union\r
+  {\r
+    CHAR cVal;\r
+    UCHAR bVal;\r
+    SHORT iVal;\r
+    USHORT uiVal;\r
+    LONG lVal;\r
+    ULONG ulVal;\r
+    INT intVal;\r
+    UINT uintVal;\r
+    LARGE_INTEGER hVal;\r
+    ULARGE_INTEGER uhVal;\r
+    VARIANT_BOOL boolVal;\r
+    SCODE scode;\r
+    FILETIME filetime;\r
+    BSTR bstrVal;\r
+  };\r
+} PROPVARIANT;\r
+\r
+typedef PROPVARIANT tagVARIANT;\r
+typedef tagVARIANT VARIANT;\r
+typedef VARIANT VARIANTARG;\r
+\r
+MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop);\r
+MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src);\r
+\r
+#endif\r
+\r
+MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len);\r
+MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz);\r
+MY_EXTERN_C void SysFreeString(BSTR bstr);\r
+MY_EXTERN_C UINT SysStringByteLen(BSTR bstr);\r
+MY_EXTERN_C UINT SysStringLen(BSTR bstr);\r
+\r
+MY_EXTERN_C DWORD GetLastError();\r
+MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2);\r
+\r
+#define CP_ACP    0\r
+#define CP_OEMCP  1\r
+\r
+typedef enum tagSTREAM_SEEK\r
+{\r
+  STREAM_SEEK_SET = 0,\r
+  STREAM_SEEK_CUR = 1,\r
+  STREAM_SEEK_END = 2\r
+} STREAM_SEEK;\r
+\r
+#endif\r
+#endif\r
diff --git a/CPP/Common/MyXml.cpp b/CPP/Common/MyXml.cpp
new file mode 100755 (executable)
index 0000000..ce4c781
--- /dev/null
@@ -0,0 +1,209 @@
+// MyXml.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "MyXml.h"\r
+\r
+static bool IsValidChar(char c)\r
+{\r
+  return\r
+    c >= 'a' && c <= 'z' ||\r
+    c >= 'A' && c <= 'Z' ||\r
+    c >= '0' && c <= '9' ||\r
+    c == '-';\r
+}\r
+\r
+static bool IsSpaceChar(char c)\r
+{\r
+  return (c == ' ' || c == '\t' || c == 0x0D || c == 0x0A);\r
+}\r
+\r
+#define SKIP_SPACES(s, pos) while (IsSpaceChar(s[pos])) pos++;\r
+\r
+static bool ReadProperty(const AString &s, int &pos, CXmlProp &prop)\r
+{\r
+  prop.Name.Empty();\r
+  prop.Value.Empty();\r
+  for (; pos < s.Length(); pos++)\r
+  {\r
+    char c = s[pos];\r
+    if (!IsValidChar(c))\r
+      break;\r
+    prop.Name += c;\r
+  }\r
+  \r
+  if (prop.Name.IsEmpty())\r
+    return false;\r
+\r
+  SKIP_SPACES(s, pos);\r
+  if (s[pos++] != '=')\r
+    return false;\r
+\r
+  SKIP_SPACES(s, pos);\r
+  if (s[pos++] != '\"')\r
+    return false;\r
+  \r
+  while (pos < s.Length())\r
+  {\r
+    char c = s[pos++];\r
+    if (c == '\"')\r
+      return true;\r
+    prop.Value += c;\r
+  }\r
+  return false;\r
+}\r
+\r
+int CXmlItem::FindProperty(const AString &propName) const\r
+{\r
+  for (int i = 0; i < Props.Size(); i++)\r
+    if (Props[i].Name == propName)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+AString CXmlItem::GetPropertyValue(const AString &propName) const\r
+{\r
+  int index = FindProperty(propName);\r
+  if (index >= 0)\r
+    return Props[index].Value;\r
+  return AString();\r
+}\r
+\r
+bool CXmlItem::IsTagged(const AString &tag) const\r
+{\r
+  return (IsTag && Name == tag);\r
+}\r
+\r
+int CXmlItem::FindSubTag(const AString &tag) const\r
+{\r
+  for (int i = 0; i < SubItems.Size(); i++)\r
+    if (SubItems[i].IsTagged(tag))\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+AString CXmlItem::GetSubString() const\r
+{\r
+  if (SubItems.Size() == 1)\r
+  {\r
+    const CXmlItem &item = SubItems[0];\r
+    if (!item.IsTag)\r
+      return item.Name;\r
+  }\r
+  return AString();\r
+}\r
+\r
+AString CXmlItem::GetSubStringForTag(const AString &tag) const\r
+{\r
+  int index = FindSubTag(tag);\r
+  if (index >= 0)\r
+    return SubItems[index].GetSubString();\r
+  return AString();\r
+}\r
+\r
+bool CXmlItem::ParseItems(const AString &s, int &pos, int numAllowedLevels)\r
+{\r
+  if (numAllowedLevels == 0)\r
+    return false;\r
+  SubItems.Clear();\r
+  AString finishString = "</";\r
+  for (;;)\r
+  {\r
+    SKIP_SPACES(s, pos);\r
+\r
+    if (s.Mid(pos, finishString.Length()) == finishString)\r
+      return true;\r
+      \r
+    CXmlItem item;\r
+    if (!item.ParseItem(s, pos, numAllowedLevels - 1))\r
+      return false;\r
+    SubItems.Add(item);\r
+  }\r
+}\r
+\r
+bool CXmlItem::ParseItem(const AString &s, int &pos, int numAllowedLevels)\r
+{\r
+  SKIP_SPACES(s, pos);\r
+\r
+  int pos2 = s.Find('<', pos);\r
+  if (pos2 < 0)\r
+    return false;\r
+  if (pos2 != pos)\r
+  {\r
+    IsTag = false;\r
+    Name += s.Mid(pos, pos2 - pos);\r
+    pos = pos2;\r
+    return true;\r
+  }\r
+  IsTag = true;\r
+\r
+  pos++;\r
+  SKIP_SPACES(s, pos);\r
+\r
+  for (; pos < s.Length(); pos++)\r
+  {\r
+    char c = s[pos];\r
+    if (!IsValidChar(c))\r
+      break;\r
+    Name += c;\r
+  }\r
+  if (Name.IsEmpty() || pos == s.Length())\r
+    return false;\r
+\r
+  int posTemp = pos;\r
+  for (;;)\r
+  {\r
+    SKIP_SPACES(s, pos);\r
+    if (s[pos] == '/')\r
+    {\r
+      pos++;\r
+      // SKIP_SPACES(s, pos);\r
+      return (s[pos++] == '>');\r
+    }\r
+    if (s[pos] == '>')\r
+    {\r
+      if (!ParseItems(s, ++pos, numAllowedLevels))\r
+        return false;\r
+      AString finishString = AString("</") + Name + AString(">");\r
+      if (s.Mid(pos, finishString.Length()) != finishString)\r
+        return false;\r
+      pos += finishString.Length();\r
+      return true;\r
+    }\r
+    if (posTemp == pos)\r
+      return false;\r
+\r
+    CXmlProp prop;\r
+    if (!ReadProperty(s, pos, prop))\r
+      return false;\r
+    Props.Add(prop);\r
+    posTemp = pos;\r
+  }\r
+}\r
+\r
+static bool SkipHeader(const AString &s, int &pos, const AString &startString, const AString &endString)\r
+{\r
+  SKIP_SPACES(s, pos);\r
+  if (s.Mid(pos, startString.Length()) == startString)\r
+  {\r
+    pos = s.Find(endString, pos);\r
+    if (pos < 0)\r
+      return false;\r
+    pos += endString.Length();\r
+    SKIP_SPACES(s, pos);\r
+  }\r
+  return true;\r
+}\r
+\r
+bool CXml::Parse(const AString &s)\r
+{\r
+  int pos = 0;\r
+  if (!SkipHeader(s, pos, "<?xml", "?>"))\r
+    return false;\r
+  if (!SkipHeader(s, pos, "<!DOCTYPE", ">"))\r
+    return false;\r
+  if (!Root.ParseItem(s, pos, 1000))\r
+    return false;\r
+  SKIP_SPACES(s, pos);\r
+  return (pos == s.Length() && Root.IsTag);\r
+}\r
diff --git a/CPP/Common/MyXml.h b/CPP/Common/MyXml.h
new file mode 100755 (executable)
index 0000000..52e23d1
--- /dev/null
@@ -0,0 +1,40 @@
+// MyXml.h\r
+\r
+#ifndef __MYXML_H\r
+#define __MYXML_H\r
+\r
+#include "MyString.h"\r
+\r
+struct CXmlProp\r
+{\r
+  AString Name;\r
+  AString Value;\r
+};\r
+\r
+class CXmlItem\r
+{\r
+  bool ParseItems(const AString &s, int &pos, int numAllowedLevels);\r
+\r
+public:\r
+  AString Name;\r
+  bool IsTag;\r
+  CObjectVector<CXmlProp> Props;\r
+  CObjectVector<CXmlItem> SubItems;\r
+\r
+  bool ParseItem(const AString &s, int &pos, int numAllowedLevels);\r
+  \r
+  bool IsTagged(const AString &tag) const;\r
+  int FindProperty(const AString &propName) const;\r
+  AString GetPropertyValue(const AString &propName) const;\r
+  AString GetSubString() const;\r
+  int FindSubTag(const AString &tag) const;\r
+  AString GetSubStringForTag(const AString &tag) const;\r
+};\r
+\r
+struct CXml\r
+{\r
+  CXmlItem Root;\r
+  bool Parse(const AString &s);\r
+};\r
+\r
+#endif\r
diff --git a/CPP/Common/NewHandler.cpp b/CPP/Common/NewHandler.cpp
new file mode 100755 (executable)
index 0000000..611bbd8
--- /dev/null
@@ -0,0 +1,116 @@
+// NewHandler.cpp\r
\r
+#include "StdAfx.h"\r
+\r
+#include <stdlib.h>\r
+\r
+#include "NewHandler.h"\r
+\r
+// #define DEBUG_MEMORY_LEAK\r
+\r
+#ifndef DEBUG_MEMORY_LEAK\r
+\r
+#ifdef _WIN32\r
+void *\r
+#ifdef _MSC_VER\r
+__cdecl\r
+#endif\r
+operator new(size_t size)\r
+{\r
+  // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size);\r
+  void *p = ::malloc(size);\r
+  if (p == 0)\r
+    throw CNewException();\r
+  return p;\r
+}\r
+\r
+void\r
+#ifdef _MSC_VER\r
+__cdecl\r
+#endif\r
+operator delete(void *p) throw()\r
+{\r
+  /*\r
+  if (p == 0)\r
+    return;\r
+  ::HeapFree(::GetProcessHeap(), 0, p);\r
+  */\r
+  ::free(p);\r
+}\r
+#endif\r
+\r
+#else\r
+\r
+#pragma init_seg(lib)\r
+const int kDebugSize = 1000000;\r
+static void *a[kDebugSize];\r
+static int index = 0;\r
+\r
+static int numAllocs = 0;\r
+void * __cdecl operator new(size_t size)\r
+{\r
+  numAllocs++;\r
+  void *p = HeapAlloc(GetProcessHeap(), 0, size);\r
+  if (index == 40)\r
+  {\r
+    int t = 1;\r
+  }\r
+  if (index < kDebugSize)\r
+  {\r
+    a[index] = p;\r
+    index++;\r
+  }\r
+  if (p == 0)\r
+    throw CNewException();\r
+  printf("Alloc %6d, size = %8d\n", numAllocs, size);\r
+  return p;\r
+}\r
+\r
+class CC\r
+{\r
+public:\r
+  CC()\r
+  {\r
+    for (int i = 0; i < kDebugSize; i++)\r
+      a[i] = 0;\r
+  }\r
+  ~CC()\r
+  {\r
+    for (int i = 0; i < kDebugSize; i++)\r
+      if (a[i] != 0)\r
+        return;\r
+  }\r
+} g_CC;\r
+\r
+\r
+void __cdecl operator delete(void *p)\r
+{\r
+  if (p == 0)\r
+    return;\r
+  /*\r
+  for (int i = 0; i < index; i++)\r
+    if (a[i] == p)\r
+      a[i] = 0;\r
+  */\r
+  HeapFree(GetProcessHeap(), 0, p);\r
+  numAllocs--;\r
+  printf("Free %d\n", numAllocs);\r
+}\r
+\r
+#endif\r
+\r
+/*\r
+int MemErrorVC(size_t)\r
+{\r
+  throw CNewException();\r
+  // return 1;\r
+}\r
+CNewHandlerSetter::CNewHandlerSetter()\r
+{\r
+  // MemErrorOldVCFunction = _set_new_handler(MemErrorVC);\r
+}\r
+CNewHandlerSetter::~CNewHandlerSetter()\r
+{\r
+  // _set_new_handler(MemErrorOldVCFunction);\r
+}\r
+*/\r
diff --git a/CPP/Common/NewHandler.h b/CPP/Common/NewHandler.h
new file mode 100755 (executable)
index 0000000..6f710cd
--- /dev/null
@@ -0,0 +1,16 @@
+// Common/NewHandler.h\r
+\r
+#ifndef __COMMON_NEWHANDLER_H\r
+#define __COMMON_NEWHANDLER_H\r
+\r
+class CNewException {};\r
+\r
+#ifdef _WIN32\r
+void\r
+#ifdef _MSC_VER\r
+__cdecl\r
+#endif\r
+operator delete(void *p) throw();\r
+#endif\r
+\r
+#endif\r
diff --git a/CPP/Common/Random.cpp b/CPP/Common/Random.cpp
new file mode 100755 (executable)
index 0000000..ca0113f
--- /dev/null
@@ -0,0 +1,26 @@
+// Common/Random.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include <stdlib.h>\r
+\r
+#ifndef _WIN32\r
+#include <time.h>\r
+#endif\r
+\r
+#include "Random.h"\r
+\r
+void CRandom::Init(unsigned int seed) { srand(seed); }\r
+\r
+void CRandom::Init()\r
+{\r
+  Init((unsigned int)\r
+    #ifdef _WIN32\r
+    GetTickCount()\r
+    #else\r
+    time(NULL)\r
+    #endif\r
+    );\r
+}\r
+\r
+int CRandom::Generate() const { return rand(); }\r
diff --git a/CPP/Common/Random.h b/CPP/Common/Random.h
new file mode 100755 (executable)
index 0000000..f6fe5c4
--- /dev/null
@@ -0,0 +1,16 @@
+// Common/Random.h\r
+\r
+#ifndef __COMMON_RANDOM_H\r
+#define __COMMON_RANDOM_H\r
+\r
+class CRandom\r
+{\r
+public:\r
+  void Init();\r
+  void Init(unsigned int seed);\r
+  int Generate() const;\r
+};\r
+\r
+#endif\r
+\r
+\r
diff --git a/CPP/Common/StdAfx.h b/CPP/Common/StdAfx.h
new file mode 100755 (executable)
index 0000000..9b43572
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+// #include "MyWindows.h"\r
+#include "NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/Common/StdInStream.cpp b/CPP/Common/StdInStream.cpp
new file mode 100755 (executable)
index 0000000..442191e
--- /dev/null
@@ -0,0 +1,107 @@
+// Common/StdInStream.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include <tchar.h>\r
+\r
+#include "StdInStream.h"\r
+#include "StringConvert.h"\r
+#include "UTFConvert.h"\r
+\r
+#ifdef _MSC_VER\r
+// "was declared deprecated" disabling\r
+#pragma warning(disable : 4996 )\r
+#endif\r
+\r
+static const char kIllegalChar = '\0';\r
+static const char kNewLineChar = '\n';\r
+\r
+static const char *kEOFMessage = "Unexpected end of input stream";\r
+static const char *kReadErrorMessage  ="Error reading input stream";\r
+static const char *kIllegalCharMessage = "Illegal character in input stream";\r
+\r
+static LPCTSTR kFileOpenMode = TEXT("r");\r
+\r
+extern int g_CodePage;\r
+\r
+CStdInStream g_StdIn(stdin);\r
+\r
+bool CStdInStream::Open(LPCTSTR fileName)\r
+{\r
+  Close();\r
+  _stream = _tfopen(fileName, kFileOpenMode);\r
+  _streamIsOpen = (_stream != 0);\r
+  return _streamIsOpen;\r
+}\r
+\r
+bool CStdInStream::Close()\r
+{\r
+  if (!_streamIsOpen)\r
+    return true;\r
+  _streamIsOpen = (fclose(_stream) != 0);\r
+  return !_streamIsOpen;\r
+}\r
+\r
+CStdInStream::~CStdInStream()\r
+{\r
+  Close();\r
+}\r
+\r
+AString CStdInStream::ScanStringUntilNewLine(bool allowEOF)\r
+{\r
+  AString s;\r
+  for (;;)\r
+  {\r
+    int intChar = GetChar();\r
+    if (intChar == EOF)\r
+    {\r
+      if (allowEOF)\r
+        break;\r
+      throw kEOFMessage;\r
+    }\r
+    char c = char(intChar);\r
+    if (c == kIllegalChar)\r
+      throw kIllegalCharMessage;\r
+    if (c == kNewLineChar)\r
+      break;\r
+    s += c;\r
+  }\r
+  return s;\r
+}\r
+\r
+UString CStdInStream::ScanUStringUntilNewLine()\r
+{\r
+  AString s = ScanStringUntilNewLine(true);\r
+  int codePage = g_CodePage;\r
+  if (codePage == -1)\r
+    codePage = CP_OEMCP;\r
+  UString dest;\r
+  if (codePage == CP_UTF8)\r
+    ConvertUTF8ToUnicode(s, dest);\r
+  else\r
+    dest = MultiByteToUnicodeString(s, (UINT)codePage);\r
+  return dest;\r
+}\r
+\r
+void CStdInStream::ReadToString(AString &resultString)\r
+{\r
+  resultString.Empty();\r
+  int c;\r
+  while ((c = GetChar()) != EOF)\r
+    resultString += char(c);\r
+}\r
+\r
+bool CStdInStream::Eof()\r
+{\r
+  return (feof(_stream) != 0);\r
+}\r
+\r
+int CStdInStream::GetChar()\r
+{\r
+  int c = fgetc(_stream); // getc() doesn't work in BeOS?\r
+  if (c == EOF && !Eof())\r
+    throw kReadErrorMessage;\r
+  return c;\r
+}\r
+\r
+\r
diff --git a/CPP/Common/StdInStream.h b/CPP/Common/StdInStream.h
new file mode 100755 (executable)
index 0000000..67ef82b
--- /dev/null
@@ -0,0 +1,32 @@
+// Common/StdInStream.h\r
+\r
+#ifndef __COMMON_STDINSTREAM_H\r
+#define __COMMON_STDINSTREAM_H\r
+\r
+#include <stdio.h>\r
+\r
+#include "MyString.h"\r
+#include "Types.h"\r
+\r
+class CStdInStream\r
+{\r
+  bool _streamIsOpen;\r
+  FILE *_stream;\r
+public:\r
+  CStdInStream(): _streamIsOpen(false) {};\r
+  CStdInStream(FILE *stream): _streamIsOpen(false), _stream(stream) {};\r
+  ~CStdInStream();\r
+  bool Open(LPCTSTR fileName);\r
+  bool Close();\r
+\r
+  AString ScanStringUntilNewLine(bool allowEOF = false);\r
+  void ReadToString(AString &resultString);\r
+  UString ScanUStringUntilNewLine();\r
+\r
+  bool Eof();\r
+  int GetChar();\r
+};\r
+\r
+extern CStdInStream g_StdIn;\r
+\r
+#endif\r
diff --git a/CPP/Common/StdOutStream.cpp b/CPP/Common/StdOutStream.cpp
new file mode 100755 (executable)
index 0000000..f7ec2a6
--- /dev/null
@@ -0,0 +1,104 @@
+// Common/StdOutStream.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include <tchar.h>\r
+\r
+#include "IntToString.h"\r
+#include "StdOutStream.h"\r
+#include "StringConvert.h"\r
+#include "UTFConvert.h"\r
+\r
+#ifdef _MSC_VER\r
+// "was declared deprecated" disabling\r
+#pragma warning(disable : 4996 )\r
+#endif\r
+\r
+static const char kNewLineChar =  '\n';\r
+\r
+static const char *kFileOpenMode = "wt";\r
+\r
+extern int g_CodePage;\r
+\r
+CStdOutStream  g_StdOut(stdout);\r
+CStdOutStream  g_StdErr(stderr);\r
+\r
+bool CStdOutStream::Open(const char *fileName)\r
+{\r
+  Close();\r
+  _stream = fopen(fileName, kFileOpenMode);\r
+  _streamIsOpen = (_stream != 0);\r
+  return _streamIsOpen;\r
+}\r
+\r
+bool CStdOutStream::Close()\r
+{\r
+  if (!_streamIsOpen)\r
+    return true;\r
+  if (fclose(_stream) != 0)\r
+    return false;\r
+  _stream = 0;\r
+  _streamIsOpen = false;\r
+  return true;\r
+}\r
+\r
+bool CStdOutStream::Flush()\r
+{\r
+  return (fflush(_stream) == 0);\r
+}\r
+\r
+CStdOutStream::~CStdOutStream ()\r
+{\r
+  Close();\r
+}\r
+\r
+CStdOutStream & CStdOutStream::operator<<(CStdOutStream & (*aFunction)(CStdOutStream  &))\r
+{\r
+  (*aFunction)(*this);\r
+  return *this;\r
+}\r
+\r
+CStdOutStream & endl(CStdOutStream & outStream)\r
+{\r
+  return outStream << kNewLineChar;\r
+}\r
+\r
+CStdOutStream & CStdOutStream::operator<<(const char *s)\r
+{\r
+  fputs(s, _stream);\r
+  return *this;\r
+}\r
+\r
+CStdOutStream & CStdOutStream::operator<<(const wchar_t *s)\r
+{\r
+  int codePage = g_CodePage;\r
+  if (codePage == -1)\r
+    codePage = CP_OEMCP;\r
+  AString dest;\r
+  if (codePage == CP_UTF8)\r
+    ConvertUnicodeToUTF8(s, dest);\r
+  else\r
+    dest = UnicodeStringToMultiByte(s, (UINT)codePage);\r
+  *this << (const char *)dest;\r
+  return *this;\r
+}\r
+\r
+CStdOutStream & CStdOutStream::operator<<(char c)\r
+{\r
+  fputc(c, _stream);\r
+  return *this;\r
+}\r
+\r
+CStdOutStream & CStdOutStream::operator<<(int number)\r
+{\r
+  char textString[32];\r
+  ConvertInt64ToString(number, textString);\r
+  return operator<<(textString);\r
+}\r
+\r
+CStdOutStream & CStdOutStream::operator<<(UInt64 number)\r
+{\r
+  char textString[32];\r
+  ConvertUInt64ToString(number, textString);\r
+  return operator<<(textString);\r
+}\r
diff --git a/CPP/Common/StdOutStream.h b/CPP/Common/StdOutStream.h
new file mode 100755 (executable)
index 0000000..c2fcd9d
--- /dev/null
@@ -0,0 +1,35 @@
+// Common/StdOutStream.h\r
+\r
+#ifndef __COMMON_STDOUTSTREAM_H\r
+#define __COMMON_STDOUTSTREAM_H\r
+\r
+#include <stdio.h>\r
+\r
+#include "Types.h"\r
+\r
+class CStdOutStream\r
+{\r
+  bool _streamIsOpen;\r
+  FILE *_stream;\r
+public:\r
+  CStdOutStream (): _streamIsOpen(false), _stream(0) {};\r
+  CStdOutStream (FILE *stream): _streamIsOpen(false), _stream(stream) {};\r
+  ~CStdOutStream ();\r
+  operator FILE *() { return _stream; }\r
+  bool Open(const char *fileName);\r
+  bool Close();\r
+  bool Flush();\r
+  CStdOutStream & operator<<(CStdOutStream & (* aFunction)(CStdOutStream  &));\r
+  CStdOutStream & operator<<(const char *string);\r
+  CStdOutStream & operator<<(const wchar_t *string);\r
+  CStdOutStream & operator<<(char c);\r
+  CStdOutStream & operator<<(int number);\r
+  CStdOutStream & operator<<(UInt64 number);\r
+};\r
+\r
+CStdOutStream & endl(CStdOutStream & outStream);\r
+\r
+extern CStdOutStream g_StdOut;\r
+extern CStdOutStream g_StdErr;\r
+\r
+#endif\r
diff --git a/CPP/Common/StringConvert.cpp b/CPP/Common/StringConvert.cpp
new file mode 100755 (executable)
index 0000000..7f9999c
--- /dev/null
@@ -0,0 +1,97 @@
+// Common/StringConvert.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "StringConvert.h"\r
+\r
+#ifndef _WIN32\r
+#include <stdlib.h>\r
+#endif\r
+\r
+#ifdef _WIN32\r
+UString MultiByteToUnicodeString(const AString &srcString, UINT codePage)\r
+{\r
+  UString resultString;\r
+  if (!srcString.IsEmpty())\r
+  {\r
+    int numChars = MultiByteToWideChar(codePage, 0, srcString,\r
+      srcString.Length(), resultString.GetBuffer(srcString.Length()),\r
+      srcString.Length() + 1);\r
+    if (numChars == 0)\r
+      throw 282228;\r
+    resultString.ReleaseBuffer(numChars);\r
+  }\r
+  return resultString;\r
+}\r
+\r
+AString UnicodeStringToMultiByte(const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed)\r
+{\r
+  AString dest;\r
+  defaultCharWasUsed = false;\r
+  if (!s.IsEmpty())\r
+  {\r
+    int numRequiredBytes = s.Length() * 2;\r
+    BOOL defUsed;\r
+    int numChars = WideCharToMultiByte(codePage, 0, s, s.Length(),\r
+        dest.GetBuffer(numRequiredBytes), numRequiredBytes + 1,\r
+        &defaultChar, &defUsed);\r
+    defaultCharWasUsed = (defUsed != FALSE);\r
+    if (numChars == 0)\r
+      throw 282229;\r
+    dest.ReleaseBuffer(numChars);\r
+  }\r
+  return dest;\r
+}\r
+\r
+AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage)\r
+{\r
+  bool defaultCharWasUsed;\r
+  return UnicodeStringToMultiByte(srcString, codePage, '_', defaultCharWasUsed);\r
+}\r
+\r
+#ifndef UNDER_CE\r
+AString SystemStringToOemString(const CSysString &srcString)\r
+{\r
+  AString result;\r
+  CharToOem(srcString, result.GetBuffer(srcString.Length() * 2));\r
+  result.ReleaseBuffer();\r
+  return result;\r
+}\r
+#endif\r
+\r
+#else\r
+\r
+UString MultiByteToUnicodeString(const AString &srcString, UINT codePage)\r
+{\r
+  UString resultString;\r
+  for (int i = 0; i < srcString.Length(); i++)\r
+    resultString += wchar_t(srcString[i]);\r
+  /*\r
+  if (!srcString.IsEmpty())\r
+  {\r
+    int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1);\r
+    if (numChars < 0) throw "Your environment does not support UNICODE";\r
+    resultString.ReleaseBuffer(numChars);\r
+  }\r
+  */\r
+  return resultString;\r
+}\r
+\r
+AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage)\r
+{\r
+  AString resultString;\r
+  for (int i = 0; i < srcString.Length(); i++)\r
+    resultString += char(srcString[i]);\r
+  /*\r
+  if (!srcString.IsEmpty())\r
+  {\r
+    int numRequiredBytes = srcString.Length() * 6 + 1;\r
+    int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes);\r
+    if (numChars < 0) throw "Your environment does not support UNICODE";\r
+    resultString.ReleaseBuffer(numChars);\r
+  }\r
+  */\r
+  return resultString;\r
+}\r
+\r
+#endif\r
diff --git a/CPP/Common/StringConvert.h b/CPP/Common/StringConvert.h
new file mode 100755 (executable)
index 0000000..1c7a951
--- /dev/null
@@ -0,0 +1,73 @@
+// Common/StringConvert.h\r
+\r
+#ifndef __COMMON_STRING_CONVERT_H\r
+#define __COMMON_STRING_CONVERT_H\r
+\r
+#include "MyWindows.h"\r
+#include "MyString.h"\r
+#include "Types.h"\r
+\r
+UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP);\r
+AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage, char defaultChar, bool &defaultCharWasUsed);\r
+AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP);\r
+\r
+\r
+inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString)\r
+  { return unicodeString; }\r
+inline const UString& GetUnicodeString(const UString &unicodeString)\r
+  { return unicodeString; }\r
+inline UString GetUnicodeString(const AString &ansiString)\r
+  { return MultiByteToUnicodeString(ansiString); }\r
+inline UString GetUnicodeString(const AString &multiByteString, UINT codePage)\r
+  { return MultiByteToUnicodeString(multiByteString, codePage); }\r
+inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT)\r
+  { return unicodeString; }\r
+inline const UString& GetUnicodeString(const UString &unicodeString, UINT)\r
+  { return unicodeString; }\r
+\r
+inline const char* GetAnsiString(const char* ansiString)\r
+  { return ansiString; }\r
+inline const AString& GetAnsiString(const AString &ansiString)\r
+  { return ansiString; }\r
+inline AString GetAnsiString(const UString &unicodeString)\r
+  { return UnicodeStringToMultiByte(unicodeString); }\r
+\r
+inline const char* GetOemString(const char* oemString)\r
+  { return oemString; }\r
+inline const AString& GetOemString(const AString &oemString)\r
+  { return oemString; }\r
+inline AString GetOemString(const UString &unicodeString)\r
+  { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); }\r
+\r
+\r
+#ifdef _UNICODE\r
+  inline const wchar_t* GetSystemString(const wchar_t* unicodeString)\r
+    { return unicodeString;}\r
+  inline const UString& GetSystemString(const UString &unicodeString)\r
+    { return unicodeString;}\r
+  inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT /* codePage */)\r
+    { return unicodeString;}\r
+  inline const UString& GetSystemString(const UString &unicodeString, UINT /* codePage */)\r
+    { return unicodeString;}\r
+  inline UString GetSystemString(const AString &multiByteString, UINT codePage)\r
+    { return MultiByteToUnicodeString(multiByteString, codePage);}\r
+  inline UString GetSystemString(const AString &multiByteString)\r
+    { return MultiByteToUnicodeString(multiByteString);}\r
+#else\r
+  inline const char* GetSystemString(const char *ansiString)\r
+    { return ansiString; }\r
+  inline const AString& GetSystemString(const AString &multiByteString, UINT)\r
+    { return multiByteString; }\r
+  inline const char * GetSystemString(const char *multiByteString, UINT)\r
+    { return multiByteString; }\r
+  inline AString GetSystemString(const UString &unicodeString)\r
+    { return UnicodeStringToMultiByte(unicodeString); }\r
+  inline AString GetSystemString(const UString &unicodeString, UINT codePage)\r
+    { return UnicodeStringToMultiByte(unicodeString, codePage); }\r
+#endif\r
+\r
+#ifndef UNDER_CE\r
+AString SystemStringToOemString(const CSysString &srcString);\r
+#endif\r
+\r
+#endif\r
diff --git a/CPP/Common/StringToInt.cpp b/CPP/Common/StringToInt.cpp
new file mode 100755 (executable)
index 0000000..77ce7c5
--- /dev/null
@@ -0,0 +1,90 @@
+// Common/StringToInt.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "StringToInt.h"\r
+\r
+UInt64 ConvertStringToUInt64(const char *s, const char **end)\r
+{\r
+  UInt64 result = 0;\r
+  for (;;)\r
+  {\r
+    char c = *s;\r
+    if (c < '0' || c > '9')\r
+    {\r
+      if (end != NULL)\r
+        *end = s;\r
+      return result;\r
+    }\r
+    result *= 10;\r
+    result += (c - '0');\r
+    s++;\r
+  }\r
+}\r
+\r
+UInt64 ConvertOctStringToUInt64(const char *s, const char **end)\r
+{\r
+  UInt64 result = 0;\r
+  for (;;)\r
+  {\r
+    char c = *s;\r
+    if (c < '0' || c > '7')\r
+    {\r
+      if (end != NULL)\r
+        *end = s;\r
+      return result;\r
+    }\r
+    result <<= 3;\r
+    result += (c - '0');\r
+    s++;\r
+  }\r
+}\r
+\r
+UInt64 ConvertHexStringToUInt64(const char *s, const char **end)\r
+{\r
+  UInt64 result = 0;\r
+  for (;;)\r
+  {\r
+    char c = *s;\r
+    UInt32 v;\r
+    if (c >= '0' && c <= '9') v = (c - '0');\r
+    else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A');\r
+    else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a');\r
+    else\r
+    {\r
+      if (end != NULL)\r
+        *end = s;\r
+      return result;\r
+    }\r
+    result <<= 4;\r
+    result |= v;\r
+    s++;\r
+  }\r
+}\r
+\r
+\r
+UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end)\r
+{\r
+  UInt64 result = 0;\r
+  for (;;)\r
+  {\r
+    wchar_t c = *s;\r
+    if (c < '0' || c > '9')\r
+    {\r
+      if (end != NULL)\r
+        *end = s;\r
+      return result;\r
+    }\r
+    result *= 10;\r
+    result += (c - '0');\r
+    s++;\r
+  }\r
+}\r
+\r
+\r
+Int64 ConvertStringToInt64(const char *s, const char **end)\r
+{\r
+  if (*s == '-')\r
+    return -(Int64)ConvertStringToUInt64(s + 1, end);\r
+  return ConvertStringToUInt64(s, end);\r
+}\r
diff --git a/CPP/Common/StringToInt.h b/CPP/Common/StringToInt.h
new file mode 100755 (executable)
index 0000000..16a1a4f
--- /dev/null
@@ -0,0 +1,18 @@
+// Common/StringToInt.h\r
+\r
+#ifndef __COMMON_STRINGTOINT_H\r
+#define __COMMON_STRINGTOINT_H\r
+\r
+#include <string.h>\r
+#include "Types.h"\r
+\r
+UInt64 ConvertStringToUInt64(const char *s, const char **end);\r
+UInt64 ConvertOctStringToUInt64(const char *s, const char **end);\r
+UInt64 ConvertHexStringToUInt64(const char *s, const char **end);\r
+UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end);\r
+\r
+Int64 ConvertStringToInt64(const char *s, const char **end);\r
+\r
+#endif\r
+\r
+\r
diff --git a/CPP/Common/TextConfig.cpp b/CPP/Common/TextConfig.cpp
new file mode 100755 (executable)
index 0000000..16c2e7a
--- /dev/null
@@ -0,0 +1,138 @@
+// Common/TextConfig.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "TextConfig.h"\r
+\r
+#include "Defs.h"\r
+#include "UTFConvert.h"\r
+\r
+static bool IsDelimitChar(char c)\r
+{\r
+  return (c == ' ' || c == 0x0A || c == 0x0D ||\r
+      c == '\0' || c == '\t');\r
+}\r
+    \r
+static AString GetIDString(const char *string, int &finishPos)\r
+{\r
+  AString result;\r
+  for (finishPos = 0; ; finishPos++)\r
+  {\r
+    char c = string[finishPos];\r
+    if (IsDelimitChar(c) || c == '=')\r
+      break;\r
+    result += c;\r
+  }\r
+  return result;\r
+}\r
+\r
+static bool WaitNextLine(const AString &string, int &pos)\r
+{\r
+  for (;pos < string.Length(); pos++)\r
+    if (string[pos] == 0x0A)\r
+      return true;\r
+  return false;\r
+}\r
+\r
+static bool SkipSpaces(const AString &string, int &pos)\r
+{\r
+  for (;pos < string.Length(); pos++)\r
+  {\r
+    char c = string[pos];\r
+    if (!IsDelimitChar(c))\r
+    {\r
+      if (c != ';')\r
+        return true;\r
+      if (!WaitNextLine(string, pos))\r
+        return false;\r
+    }\r
+  }\r
+  return false;\r
+}\r
+\r
+bool GetTextConfig(const AString &string, CObjectVector<CTextConfigPair> &pairs)\r
+{\r
+  pairs.Clear();\r
+  int pos = 0;\r
+\r
+  /////////////////////\r
+  // read strings\r
+\r
+  for (;;)\r
+  {\r
+    if (!SkipSpaces(string, pos))\r
+      break;\r
+    CTextConfigPair pair;\r
+    int finishPos;\r
+    AString temp = GetIDString(((const char *)string) + pos, finishPos);\r
+    if (!ConvertUTF8ToUnicode(temp, pair.ID))\r
+      return false;\r
+    if (finishPos == 0)\r
+      return false;\r
+    pos += finishPos;\r
+    if (!SkipSpaces(string, pos))\r
+      return false;\r
+    if (string[pos] != '=')\r
+      return false;\r
+    pos++;\r
+    if (!SkipSpaces(string, pos))\r
+      return false;\r
+    if (string[pos] != '\"')\r
+      return false;\r
+    pos++;\r
+    AString message;\r
+    for (;;)\r
+    {\r
+      if (pos >= string.Length())\r
+        return false;\r
+      char c = string[pos++];\r
+      if (c == '\"')\r
+        break;\r
+      if (c == '\\')\r
+      {\r
+        char c = string[pos++];\r
+        switch(c)\r
+        {\r
+          case 'n':\r
+            message += '\n';\r
+            break;\r
+          case 't':\r
+            message += '\t';\r
+            break;\r
+          case '\\':\r
+            message += '\\';\r
+            break;\r
+          case '\"':\r
+            message += '\"';\r
+            break;\r
+          default:\r
+            message += '\\';\r
+            message += c;\r
+            break;\r
+        }\r
+      }\r
+      else\r
+        message += c;\r
+    }\r
+    if (!ConvertUTF8ToUnicode(message, pair.String))\r
+      return false;\r
+    pairs.Add(pair);\r
+  }\r
+  return true;\r
+}\r
+\r
+int FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const UString &id)\r
+{\r
+  for (int  i = 0; i < pairs.Size(); i++)\r
+    if (pairs[i].ID.Compare(id) == 0)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+UString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const UString &id)\r
+{\r
+  int index = FindTextConfigItem(pairs, id);\r
+  if (index < 0)\r
+    return UString();\r
+  return pairs[index].String;\r
+}\r
diff --git a/CPP/Common/TextConfig.h b/CPP/Common/TextConfig.h
new file mode 100755 (executable)
index 0000000..d61cf2f
--- /dev/null
@@ -0,0 +1,22 @@
+// Common/TextConfig.h\r
+\r
+#ifndef __COMMON_TEXTCONFIG_H\r
+#define __COMMON_TEXTCONFIG_H\r
+\r
+#include "MyVector.h"\r
+#include "MyString.h"\r
+\r
+struct CTextConfigPair\r
+{\r
+  UString ID;\r
+  UString String;\r
+};\r
+\r
+bool GetTextConfig(const AString &text, CObjectVector<CTextConfigPair> &pairs);\r
+\r
+int FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const UString &id);\r
+UString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const UString &id);\r
+\r
+#endif\r
+\r
+\r
diff --git a/CPP/Common/Types.h b/CPP/Common/Types.h
new file mode 100755 (executable)
index 0000000..fd00237
--- /dev/null
@@ -0,0 +1,11 @@
+// Common/Types.h\r
+\r
+#ifndef __COMMON_TYPES_H\r
+#define __COMMON_TYPES_H\r
+\r
+#include "../../C/Types.h"\r
+\r
+typedef int HRes;\r
+\r
+#endif\r
+\r
diff --git a/CPP/Common/UTFConvert.cpp b/CPP/Common/UTFConvert.cpp
new file mode 100755 (executable)
index 0000000..d3935b1
--- /dev/null
@@ -0,0 +1,145 @@
+// UTFConvert.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "UTFConvert.h"\r
+#include "Types.h"\r
+\r
+static const Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };\r
+\r
+static Bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, size_t srcLen)\r
+{\r
+  size_t destPos = 0, srcPos = 0;\r
+  for (;;)\r
+  {\r
+    Byte c;\r
+    int numAdds;\r
+    if (srcPos == srcLen)\r
+    {\r
+      *destLen = destPos;\r
+      return True;\r
+    }\r
+    c = (Byte)src[srcPos++];\r
+\r
+    if (c < 0x80)\r
+    {\r
+      if (dest)\r
+        dest[destPos] = (wchar_t)c;\r
+      destPos++;\r
+      continue;\r
+    }\r
+    if (c < 0xC0)\r
+      break;\r
+    for (numAdds = 1; numAdds < 5; numAdds++)\r
+      if (c < kUtf8Limits[numAdds])\r
+        break;\r
+    UInt32 value = (c - kUtf8Limits[numAdds - 1]);\r
+\r
+    do\r
+    {\r
+      Byte c2;\r
+      if (srcPos == srcLen)\r
+        break;\r
+      c2 = (Byte)src[srcPos++];\r
+      if (c2 < 0x80 || c2 >= 0xC0)\r
+        break;\r
+      value <<= 6;\r
+      value |= (c2 - 0x80);\r
+    }\r
+    while (--numAdds != 0);\r
+    \r
+    if (value < 0x10000)\r
+    {\r
+      if (dest)\r
+        dest[destPos] = (wchar_t)value;\r
+      destPos++;\r
+    }\r
+    else\r
+    {\r
+      value -= 0x10000;\r
+      if (value >= 0x100000)\r
+        break;\r
+      if (dest)\r
+      {\r
+        dest[destPos + 0] = (wchar_t)(0xD800 + (value >> 10));\r
+        dest[destPos + 1] = (wchar_t)(0xDC00 + (value & 0x3FF));\r
+      }\r
+      destPos += 2;\r
+    }\r
+  }\r
+  *destLen = destPos;\r
+  return False;\r
+}\r
+\r
+static Bool Utf16_To_Utf8(char *dest, size_t *destLen, const wchar_t *src, size_t srcLen)\r
+{\r
+  size_t destPos = 0, srcPos = 0;\r
+  for (;;)\r
+  {\r
+    unsigned numAdds;\r
+    UInt32 value;\r
+    if (srcPos == srcLen)\r
+    {\r
+      *destLen = destPos;\r
+      return True;\r
+    }\r
+    value = src[srcPos++];\r
+    if (value < 0x80)\r
+    {\r
+      if (dest)\r
+        dest[destPos] = (char)value;\r
+      destPos++;\r
+      continue;\r
+    }\r
+    if (value >= 0xD800 && value < 0xE000)\r
+    {\r
+      UInt32 c2;\r
+      if (value >= 0xDC00 || srcPos == srcLen)\r
+        break;\r
+      c2 = src[srcPos++];\r
+      if (c2 < 0xDC00 || c2 >= 0xE000)\r
+        break;\r
+      value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;\r
+    }\r
+    for (numAdds = 1; numAdds < 5; numAdds++)\r
+      if (value < (((UInt32)1) << (numAdds * 5 + 6)))\r
+        break;\r
+    if (dest)\r
+      dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));\r
+    destPos++;\r
+    do\r
+    {\r
+      numAdds--;\r
+      if (dest)\r
+        dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));\r
+      destPos++;\r
+    }\r
+    while (numAdds != 0);\r
+  }\r
+  *destLen = destPos;\r
+  return False;\r
+}\r
+\r
+bool ConvertUTF8ToUnicode(const AString &src, UString &dest)\r
+{\r
+  dest.Empty();\r
+  size_t destLen = 0;\r
+  Utf8_To_Utf16(NULL, &destLen, src, src.Length());\r
+  wchar_t *p = dest.GetBuffer((int)destLen);\r
+  Bool res = Utf8_To_Utf16(p, &destLen, src, src.Length());\r
+  p[destLen] = 0;\r
+  dest.ReleaseBuffer();\r
+  return res ? true : false;\r
+}\r
+\r
+bool ConvertUnicodeToUTF8(const UString &src, AString &dest)\r
+{\r
+  dest.Empty();\r
+  size_t destLen = 0;\r
+  Utf16_To_Utf8(NULL, &destLen, src, src.Length());\r
+  char *p = dest.GetBuffer((int)destLen);\r
+  Bool res = Utf16_To_Utf8(p, &destLen, src, src.Length());\r
+  p[destLen] = 0;\r
+  dest.ReleaseBuffer();\r
+  return res ? true : false;\r
+}\r
diff --git a/CPP/Common/UTFConvert.h b/CPP/Common/UTFConvert.h
new file mode 100755 (executable)
index 0000000..d553101
--- /dev/null
@@ -0,0 +1,11 @@
+// Common/UTFConvert.h\r
+\r
+#ifndef __COMMON_UTFCONVERT_H\r
+#define __COMMON_UTFCONVERT_H\r
+\r
+#include "MyString.h"\r
+\r
+bool ConvertUTF8ToUnicode(const AString &utfString, UString &resultString);\r
+bool ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString);\r
+\r
+#endif\r
diff --git a/CPP/Common/Wildcard.cpp b/CPP/Common/Wildcard.cpp
new file mode 100755 (executable)
index 0000000..024d7a5
--- /dev/null
@@ -0,0 +1,462 @@
+// Common/Wildcard.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../../C/Types.h"\r
+\r
+#include "Wildcard.h"\r
+\r
+bool g_CaseSensitive =\r
+  #ifdef _WIN32\r
+    false;\r
+  #else\r
+    true;\r
+  #endif\r
+\r
+static const wchar_t kAnyCharsChar = L'*';\r
+static const wchar_t kAnyCharChar = L'?';\r
+\r
+#ifdef _WIN32\r
+static const wchar_t kDirDelimiter1 = L'\\';\r
+#endif\r
+static const wchar_t kDirDelimiter2 = L'/';\r
+\r
+static const UString kWildCardCharSet = L"?*";\r
+\r
+static const UString kIllegalWildCardFileNameChars=\r
+  L"\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF"\r
+  L"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"\r
+  L"\"/:<>\\|";\r
+\r
+\r
+static inline bool IsCharDirLimiter(wchar_t c)\r
+{\r
+  return (\r
+    #ifdef _WIN32\r
+    c == kDirDelimiter1 ||\r
+    #endif\r
+    c == kDirDelimiter2);\r
+}\r
+\r
+int CompareFileNames(const UString &s1, const UString &s2)\r
+{\r
+  if (g_CaseSensitive)\r
+    return s1.Compare(s2);\r
+  return s1.CompareNoCase(s2);\r
+}\r
+\r
+// -----------------------------------------\r
+// this function compares name with mask\r
+// ? - any char\r
+// * - any char or empty\r
+\r
+static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name)\r
+{\r
+  for (;;)\r
+  {\r
+    wchar_t m = *mask;\r
+    wchar_t c = *name;\r
+    if (m == 0)\r
+      return (c == 0);\r
+    if (m == kAnyCharsChar)\r
+    {\r
+      if (EnhancedMaskTest(mask + 1, name))\r
+        return true;\r
+      if (c == 0)\r
+        return false;\r
+    }\r
+    else\r
+    {\r
+      if (m == kAnyCharChar)\r
+      {\r
+        if (c == 0)\r
+          return false;\r
+      }\r
+      else if (m != c)\r
+        if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c))\r
+          return false;\r
+      mask++;\r
+    }\r
+    name++;\r
+  }\r
+}\r
+\r
+// --------------------------------------------------\r
+// Splits path to strings\r
+\r
+void SplitPathToParts(const UString &path, UStringVector &pathParts)\r
+{\r
+  pathParts.Clear();\r
+  UString name;\r
+  int len = path.Length();\r
+  if (len == 0)\r
+    return;\r
+  for (int i = 0; i < len; i++)\r
+  {\r
+    wchar_t c = path[i];\r
+    if (IsCharDirLimiter(c))\r
+    {\r
+      pathParts.Add(name);\r
+      name.Empty();\r
+    }\r
+    else\r
+      name += c;\r
+  }\r
+  pathParts.Add(name);\r
+}\r
+\r
+void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name)\r
+{\r
+  int i;\r
+  for (i = path.Length() - 1; i >= 0; i--)\r
+    if (IsCharDirLimiter(path[i]))\r
+      break;\r
+  dirPrefix = path.Left(i + 1);\r
+  name = path.Mid(i + 1);\r
+}\r
+\r
+UString ExtractDirPrefixFromPath(const UString &path)\r
+{\r
+  int i;\r
+  for (i = path.Length() - 1; i >= 0; i--)\r
+    if (IsCharDirLimiter(path[i]))\r
+      break;\r
+  return path.Left(i + 1);\r
+}\r
+\r
+UString ExtractFileNameFromPath(const UString &path)\r
+{\r
+  int i;\r
+  for (i = path.Length() - 1; i >= 0; i--)\r
+    if (IsCharDirLimiter(path[i]))\r
+      break;\r
+  return path.Mid(i + 1);\r
+}\r
+\r
+\r
+bool CompareWildCardWithName(const UString &mask, const UString &name)\r
+{\r
+  return EnhancedMaskTest(mask, name);\r
+}\r
+\r
+bool DoesNameContainWildCard(const UString &path)\r
+{\r
+  return (path.FindOneOf(kWildCardCharSet) >= 0);\r
+}\r
+\r
+\r
+// ----------------------------------------------------------'\r
+// NWildcard\r
+\r
+namespace NWildcard {\r
+\r
+\r
+/*\r
+M = MaskParts.Size();\r
+N = TestNameParts.Size();\r
+\r
+                           File                          Dir\r
+ForFile     req   M<=N  [N-M, N)                          -\r
+         nonreq   M=N   [0, M)                            -\r
\r
+ForDir      req   M<N   [0, M) ... [N-M-1, N-1)  same as ForBoth-File\r
+         nonreq         [0, M)                   same as ForBoth-File\r
+\r
+ForBoth     req   m<=N  [0, M) ... [N-M, N)      same as ForBoth-File\r
+         nonreq         [0, M)                   same as ForBoth-File\r
+\r
+*/\r
+\r
+bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const\r
+{\r
+  if (!isFile && !ForDir)\r
+    return false;\r
+  int delta = (int)pathParts.Size() - (int)PathParts.Size();\r
+  if (delta < 0)\r
+    return false;\r
+  int start = 0;\r
+  int finish = 0;\r
+  if (isFile)\r
+  {\r
+    if (!ForDir && !Recursive && delta !=0)\r
+      return false;\r
+    if (!ForFile && delta == 0)\r
+      return false;\r
+    if (!ForDir && Recursive)\r
+      start = delta;\r
+  }\r
+  if (Recursive)\r
+  {\r
+    finish = delta;\r
+    if (isFile && !ForFile)\r
+      finish = delta - 1;\r
+  }\r
+  for (int d = start; d <= finish; d++)\r
+  {\r
+    int i;\r
+    for (i = 0; i < PathParts.Size(); i++)\r
+      if (!CompareWildCardWithName(PathParts[i], pathParts[i + d]))\r
+        break;\r
+    if (i == PathParts.Size())\r
+      return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+int CCensorNode::FindSubNode(const UString &name) const\r
+{\r
+  for (int i = 0; i < SubNodes.Size(); i++)\r
+    if (CompareFileNames(SubNodes[i].Name, name) == 0)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+void CCensorNode::AddItemSimple(bool include, CItem &item)\r
+{\r
+  if (include)\r
+    IncludeItems.Add(item);\r
+  else\r
+    ExcludeItems.Add(item);\r
+}\r
+\r
+void CCensorNode::AddItem(bool include, CItem &item)\r
+{\r
+  if (item.PathParts.Size() <= 1)\r
+  {\r
+    AddItemSimple(include, item);\r
+    return;\r
+  }\r
+  const UString &front = item.PathParts.Front();\r
+  if (DoesNameContainWildCard(front))\r
+  {\r
+    AddItemSimple(include, item);\r
+    return;\r
+  }\r
+  int index = FindSubNode(front);\r
+  if (index < 0)\r
+    index = SubNodes.Add(CCensorNode(front, this));\r
+  item.PathParts.Delete(0);\r
+  SubNodes[index].AddItem(include, item);\r
+}\r
+\r
+void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir)\r
+{\r
+  CItem item;\r
+  SplitPathToParts(path, item.PathParts);\r
+  item.Recursive = recursive;\r
+  item.ForFile = forFile;\r
+  item.ForDir = forDir;\r
+  AddItem(include, item);\r
+}\r
+\r
+bool CCensorNode::NeedCheckSubDirs() const\r
+{\r
+  for (int i = 0; i < IncludeItems.Size(); i++)\r
+  {\r
+    const CItem &item = IncludeItems[i];\r
+    if (item.Recursive || item.PathParts.Size() > 1)\r
+      return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+bool CCensorNode::AreThereIncludeItems() const\r
+{\r
+  if (IncludeItems.Size() > 0)\r
+    return true;\r
+  for (int i = 0; i < SubNodes.Size(); i++)\r
+    if (SubNodes[i].AreThereIncludeItems())\r
+      return true;\r
+  return false;\r
+}\r
+\r
+bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const\r
+{\r
+  const CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems;\r
+  for (int i = 0; i < items.Size(); i++)\r
+    if (items[i].CheckPath(pathParts, isFile))\r
+      return true;\r
+  return false;\r
+}\r
+\r
+bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include) const\r
+{\r
+  if (CheckPathCurrent(false, pathParts, isFile))\r
+  {\r
+    include = false;\r
+    return true;\r
+  }\r
+  include = true;\r
+  bool finded = CheckPathCurrent(true, pathParts, isFile);\r
+  if (pathParts.Size() == 1)\r
+    return finded;\r
+  int index = FindSubNode(pathParts.Front());\r
+  if (index >= 0)\r
+  {\r
+    UStringVector pathParts2 = pathParts;\r
+    pathParts2.Delete(0);\r
+    if (SubNodes[index].CheckPath(pathParts2, isFile, include))\r
+      return true;\r
+  }\r
+  return finded;\r
+}\r
+\r
+bool CCensorNode::CheckPath(const UString &path, bool isFile, bool &include) const\r
+{\r
+  UStringVector pathParts;\r
+  SplitPathToParts(path, pathParts);\r
+  return CheckPath(pathParts, isFile, include);\r
+}\r
+\r
+bool CCensorNode::CheckPath(const UString &path, bool isFile) const\r
+{\r
+  bool include;\r
+  if (CheckPath(path, isFile, include))\r
+    return include;\r
+  return false;\r
+}\r
+\r
+bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const\r
+{\r
+  if (CheckPathCurrent(include, pathParts, isFile))\r
+    return true;\r
+  if (Parent == 0)\r
+    return false;\r
+  pathParts.Insert(0, Name);\r
+  return Parent->CheckPathToRoot(include, pathParts, isFile);\r
+}\r
+\r
+/*\r
+bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const\r
+{\r
+  UStringVector pathParts;\r
+  SplitPathToParts(path, pathParts);\r
+  return CheckPathToRoot(include, pathParts, isFile);\r
+}\r
+*/\r
+\r
+void CCensorNode::AddItem2(bool include, const UString &path, bool recursive)\r
+{\r
+  if (path.IsEmpty())\r
+    return;\r
+  bool forFile = true;\r
+  bool forFolder = true;\r
+  UString path2 = path;\r
+  if (IsCharDirLimiter(path[path.Length() - 1]))\r
+  {\r
+    path2.Delete(path.Length() - 1);\r
+    forFile = false;\r
+  }\r
+  AddItem(include, path2, recursive, forFile, forFolder);\r
+}\r
+\r
+void CCensorNode::ExtendExclude(const CCensorNode &fromNodes)\r
+{\r
+  ExcludeItems += fromNodes.ExcludeItems;\r
+  for (int i = 0; i < fromNodes.SubNodes.Size(); i++)\r
+  {\r
+    const CCensorNode &node = fromNodes.SubNodes[i];\r
+    int subNodeIndex = FindSubNode(node.Name);\r
+    if (subNodeIndex < 0)\r
+      subNodeIndex = SubNodes.Add(CCensorNode(node.Name, this));\r
+    SubNodes[subNodeIndex].ExtendExclude(node);\r
+  }\r
+}\r
+\r
+int CCensor::FindPrefix(const UString &prefix) const\r
+{\r
+  for (int i = 0; i < Pairs.Size(); i++)\r
+    if (CompareFileNames(Pairs[i].Prefix, prefix) == 0)\r
+      return i;\r
+  return -1;\r
+}\r
+\r
+void CCensor::AddItem(bool include, const UString &path, bool recursive)\r
+{\r
+  UStringVector pathParts;\r
+  if (path.IsEmpty())\r
+    throw "Empty file path";\r
+  SplitPathToParts(path, pathParts);\r
+  bool forFile = true;\r
+  if (pathParts.Back().IsEmpty())\r
+  {\r
+    forFile = false;\r
+    pathParts.DeleteBack();\r
+  }\r
+  const UString &front = pathParts.Front();\r
+  bool isAbs = false;\r
+  if (front.IsEmpty())\r
+    isAbs = true;\r
+  else if (front.Length() == 2 && front[1] == L':')\r
+    isAbs = true;\r
+  else\r
+  {\r
+    for (int i = 0; i < pathParts.Size(); i++)\r
+    {\r
+      const UString &part = pathParts[i];\r
+      if (part == L".." || part == L".")\r
+      {\r
+        isAbs = true;\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  int numAbsParts = 0;\r
+  if (isAbs)\r
+    if (pathParts.Size() > 1)\r
+      numAbsParts = pathParts.Size() - 1;\r
+    else\r
+      numAbsParts = 1;\r
+  UString prefix;\r
+  for (int i = 0; i < numAbsParts; i++)\r
+  {\r
+    const UString &front = pathParts.Front();\r
+    if (DoesNameContainWildCard(front))\r
+      break;\r
+    prefix += front;\r
+    prefix += WCHAR_PATH_SEPARATOR;\r
+    pathParts.Delete(0);\r
+  }\r
+  int index = FindPrefix(prefix);\r
+  if (index < 0)\r
+    index = Pairs.Add(CPair(prefix));\r
+\r
+  CItem item;\r
+  item.PathParts = pathParts;\r
+  item.ForDir = true;\r
+  item.ForFile = forFile;\r
+  item.Recursive = recursive;\r
+  Pairs[index].Head.AddItem(include, item);\r
+}\r
+\r
+bool CCensor::CheckPath(const UString &path, bool isFile) const\r
+{\r
+  bool finded = false;\r
+  for (int i = 0; i < Pairs.Size(); i++)\r
+  {\r
+    bool include;\r
+    if (Pairs[i].Head.CheckPath(path, isFile, include))\r
+    {\r
+      if (!include)\r
+        return false;\r
+      finded = true;\r
+    }\r
+  }\r
+  return finded;\r
+}\r
+\r
+void CCensor::ExtendExclude()\r
+{\r
+  int i;\r
+  for (i = 0; i < Pairs.Size(); i++)\r
+    if (Pairs[i].Prefix.IsEmpty())\r
+      break;\r
+  if (i == Pairs.Size())\r
+    return;\r
+  int index = i;\r
+  for (i = 0; i < Pairs.Size(); i++)\r
+    if (index != i)\r
+      Pairs[i].Head.ExtendExclude(Pairs[index].Head);\r
+}\r
+\r
+}\r
diff --git a/CPP/Common/Wildcard.h b/CPP/Common/Wildcard.h
new file mode 100755 (executable)
index 0000000..e2a42c8
--- /dev/null
@@ -0,0 +1,80 @@
+// Common/Wildcard.h\r
+\r
+#ifndef __COMMON_WILDCARD_H\r
+#define __COMMON_WILDCARD_H\r
+\r
+#include "MyString.h"\r
+\r
+int CompareFileNames(const UString &s1, const UString &s2);\r
+\r
+void SplitPathToParts(const UString &path, UStringVector &pathParts);\r
+void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name);\r
+UString ExtractDirPrefixFromPath(const UString &path);\r
+UString ExtractFileNameFromPath(const UString &path);\r
+bool DoesNameContainWildCard(const UString &path);\r
+bool CompareWildCardWithName(const UString &mask, const UString &name);\r
+\r
+namespace NWildcard {\r
+\r
+struct CItem\r
+{\r
+  UStringVector PathParts;\r
+  bool Recursive;\r
+  bool ForFile;\r
+  bool ForDir;\r
+  bool CheckPath(const UStringVector &pathParts, bool isFile) const;\r
+};\r
+\r
+class CCensorNode\r
+{\r
+  CCensorNode *Parent;\r
+  bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const;\r
+  void AddItemSimple(bool include, CItem &item);\r
+  bool CheckPath(UStringVector &pathParts, bool isFile, bool &include) const;\r
+public:\r
+  CCensorNode(): Parent(0) { };\r
+  CCensorNode(const UString &name, CCensorNode *parent): Name(name), Parent(parent) { };\r
+  UString Name;\r
+  CObjectVector<CCensorNode> SubNodes;\r
+  CObjectVector<CItem> IncludeItems;\r
+  CObjectVector<CItem> ExcludeItems;\r
+\r
+  int FindSubNode(const UString &path) const;\r
+\r
+  void AddItem(bool include, CItem &item);\r
+  void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir);\r
+  void AddItem2(bool include, const UString &path, bool recursive);\r
+\r
+  bool NeedCheckSubDirs() const;\r
+  bool AreThereIncludeItems() const;\r
+\r
+  bool CheckPath(const UString &path, bool isFile, bool &include) const;\r
+  bool CheckPath(const UString &path, bool isFile) const;\r
+\r
+  bool CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const;\r
+  // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const;\r
+  void ExtendExclude(const CCensorNode &fromNodes);\r
+};\r
+\r
+struct CPair\r
+{\r
+  UString Prefix;\r
+  CCensorNode Head;\r
+  CPair(const UString &prefix): Prefix(prefix) { };\r
+};\r
+\r
+class CCensor\r
+{\r
+  int FindPrefix(const UString &prefix) const;\r
+public:\r
+  CObjectVector<CPair> Pairs;\r
+  bool AllAreRelative() const\r
+    { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); }\r
+  void AddItem(bool include, const UString &path, bool recursive);\r
+  bool CheckPath(const UString &path, bool isFile) const;\r
+  void ExtendExclude();\r
+};\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/Windows/COM.cpp b/CPP/Windows/COM.cpp
new file mode 100755 (executable)
index 0000000..78a1ac8
--- /dev/null
@@ -0,0 +1,37 @@
+// Windows/COM.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/COM.h"\r
+#include "Common/StringConvert.h"\r
+\r
+namespace NWindows {\r
+namespace NCOM {\r
+\r
+// CoInitialize (NULL); must be called!\r
+\r
+UString GUIDToStringW(REFGUID guid)\r
+{\r
+  UString string;\r
+  const int kStringSize = 48;\r
+  StringFromGUID2(guid, string.GetBuffer(kStringSize), kStringSize);\r
+  string.ReleaseBuffer();\r
+  return string;\r
+}\r
+\r
+AString GUIDToStringA(REFGUID guid)\r
+{\r
+  return UnicodeStringToMultiByte(GUIDToStringW(guid));\r
+}\r
+\r
+HRESULT StringToGUIDW(const wchar_t *string, GUID &classID)\r
+{\r
+  return CLSIDFromString((wchar_t *)string, &classID);\r
+}\r
+\r
+HRESULT StringToGUIDA(const char *string, GUID &classID)\r
+{\r
+  return StringToGUIDW(MultiByteToUnicodeString(string), classID);\r
+}\r
+\r
+}}\r
diff --git a/CPP/Windows/COM.h b/CPP/Windows/COM.h
new file mode 100755 (executable)
index 0000000..c963431
--- /dev/null
@@ -0,0 +1,69 @@
+// Windows/COM.h\r
+\r
+#ifndef __WINDOWS_COM_H\r
+#define __WINDOWS_COM_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+namespace NWindows {\r
+namespace NCOM {\r
+\r
+#ifdef _WIN32\r
+  \r
+class CComInitializer\r
+{\r
+public:\r
+  CComInitializer()\r
+  {\r
+    #ifdef UNDER_CE\r
+    CoInitializeEx(NULL, COINIT_MULTITHREADED);\r
+    #else\r
+    // it's single thread. Do we need multithread?\r
+    CoInitialize(NULL);\r
+    #endif\r
+  };\r
+  ~CComInitializer() { CoUninitialize(); };\r
+};\r
+\r
+class CStgMedium\r
+{\r
+  STGMEDIUM _object;\r
+public:\r
+  bool _mustBeReleased;\r
+  CStgMedium(): _mustBeReleased(false) {}\r
+  ~CStgMedium() { Free(); }\r
+  void Free()\r
+  {\r
+    if (_mustBeReleased)\r
+      ReleaseStgMedium(&_object);\r
+    _mustBeReleased = false;\r
+  }\r
+  const STGMEDIUM* operator->() const { return &_object;}\r
+  STGMEDIUM* operator->() { return &_object;}\r
+  STGMEDIUM* operator&() { return &_object; }\r
+};\r
+\r
+#endif\r
+\r
+//////////////////////////////////\r
+// GUID <--> String Conversions\r
+UString GUIDToStringW(REFGUID guid);\r
+AString GUIDToStringA(REFGUID guid);\r
+#ifdef UNICODE\r
+  #define GUIDToString GUIDToStringW\r
+#else\r
+  #define GUIDToString GUIDToStringA\r
+#endif\r
+\r
+HRESULT StringToGUIDW(const wchar_t *string, GUID &classID);\r
+HRESULT StringToGUIDA(const char *string, GUID &classID);\r
+#ifdef UNICODE\r
+  #define StringToGUID StringToGUIDW\r
+#else\r
+  #define StringToGUID StringToGUIDA\r
+#endif\r
+\r
+  \r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Clipboard.cpp b/CPP/Windows/Clipboard.cpp
new file mode 100755 (executable)
index 0000000..01cdeb3
--- /dev/null
@@ -0,0 +1,135 @@
+// Windows/Clipboard.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#ifdef UNDER_CE\r
+#include <winuserm.h>\r
+#endif\r
+\r
+#include "Windows/Clipboard.h"\r
+#include "Windows/Defs.h"\r
+#include "Windows/Memory.h"\r
+#include "Windows/Shell.h"\r
+#include "Windows/Memory.h"\r
+\r
+#include "Common/StringConvert.h"\r
+\r
+namespace NWindows {\r
+\r
+bool CClipboard::Open(HWND wndNewOwner)\r
+{\r
+  m_Open = BOOLToBool(::OpenClipboard(wndNewOwner));\r
+  return m_Open;\r
+}\r
+\r
+CClipboard::~CClipboard()\r
+{\r
+  Close();\r
+}\r
+\r
+bool CClipboard::Close()\r
+{\r
+  if (!m_Open)\r
+    return true;\r
+  m_Open = !BOOLToBool(CloseClipboard());\r
+  return !m_Open;\r
+}\r
+\r
+bool ClipboardIsFormatAvailableHDROP()\r
+{\r
+  return BOOLToBool(IsClipboardFormatAvailable(CF_HDROP));\r
+}\r
+\r
+/*\r
+bool ClipboardGetTextString(AString &s)\r
+{\r
+  s.Empty();\r
+  if (!IsClipboardFormatAvailable(CF_TEXT))\r
+    return false;\r
+  CClipboard clipboard;\r
+\r
+  if (!clipboard.Open(NULL))\r
+    return false;\r
+\r
+  HGLOBAL h = ::GetClipboardData(CF_TEXT);\r
+  if (h != NULL)\r
+  {\r
+    NMemory::CGlobalLock globalLock(h);\r
+    const char *p = (const char *)globalLock.GetPointer();\r
+    if (p != NULL)\r
+    {\r
+      s = p;\r
+      return true;\r
+    }\r
+  }\r
+  return false;\r
+}\r
+*/\r
+\r
+/*\r
+bool ClipboardGetFileNames(UStringVector &names)\r
+{\r
+  names.Clear();\r
+  if (!IsClipboardFormatAvailable(CF_HDROP))\r
+    return false;\r
+  CClipboard clipboard;\r
+\r
+  if (!clipboard.Open(NULL))\r
+    return false;\r
+\r
+  HGLOBAL h = ::GetClipboardData(CF_HDROP);\r
+  if (h != NULL)\r
+  {\r
+    NMemory::CGlobalLock globalLock(h);\r
+    void *p = (void *)globalLock.GetPointer();\r
+    if (p != NULL)\r
+    {\r
+      NShell::CDrop drop(false);\r
+      drop.Attach((HDROP)p);\r
+      drop.QueryFileNames(names);\r
+      return true;\r
+    }\r
+  }\r
+  return false;\r
+}\r
+*/\r
+\r
+static bool ClipboardSetData(UINT uFormat, const void *data, size_t size)\r
+{\r
+  NMemory::CGlobal global;\r
+  if (!global.Alloc(GMEM_DDESHARE | GMEM_MOVEABLE, size))\r
+    return false;\r
+  {\r
+    NMemory::CGlobalLock globalLock(global);\r
+    LPVOID p = globalLock.GetPointer();\r
+    if (p == NULL)\r
+      return false;\r
+    memcpy(p, data, size);\r
+  }\r
+  if (::SetClipboardData(uFormat, global) == NULL)\r
+    return false;\r
+  global.Detach();\r
+  return true;\r
+}\r
+\r
+bool ClipboardSetText(HWND owner, const UString &s)\r
+{\r
+  CClipboard clipboard;\r
+  if (!clipboard.Open(owner))\r
+    return false;\r
+  if (!::EmptyClipboard())\r
+    return false;\r
+\r
+  bool res;\r
+  res = ClipboardSetData(CF_UNICODETEXT, (const wchar_t *)s, (s.Length() + 1) * sizeof(wchar_t));\r
+  #ifndef _UNICODE\r
+  AString a;\r
+  a = UnicodeStringToMultiByte(s, CP_ACP);\r
+  res |=  ClipboardSetData(CF_TEXT, (const char *)a, (a.Length() + 1) * sizeof(char));\r
+  a = UnicodeStringToMultiByte(s, CP_OEMCP);\r
+  res |=  ClipboardSetData(CF_OEMTEXT, (const char *)a, (a.Length() + 1) * sizeof(char));\r
+  #endif\r
+  return res;\r
+}\r
\r
+}\r
diff --git a/CPP/Windows/Clipboard.h b/CPP/Windows/Clipboard.h
new file mode 100755 (executable)
index 0000000..c168412
--- /dev/null
@@ -0,0 +1,28 @@
+// Windows/Clipboard.h\r
+\r
+#ifndef __CLIPBOARD_H\r
+#define __CLIPBOARD_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+namespace NWindows {\r
+\r
+class CClipboard\r
+{\r
+  bool m_Open;\r
+public:\r
+  CClipboard(): m_Open(false) {};\r
+  ~CClipboard();\r
+  bool Open(HWND wndNewOwner);\r
+  bool Close();\r
+};\r
+\r
+bool ClipboardIsFormatAvailableHDROP();\r
+\r
+// bool ClipboardGetFileNames(UStringVector &names);\r
+// bool ClipboardGetTextString(AString &s);\r
+bool ClipboardSetText(HWND owner, const UString &s);\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/Windows/CommonDialog.cpp b/CPP/Windows/CommonDialog.cpp
new file mode 100755 (executable)
index 0000000..34f4a31
--- /dev/null
@@ -0,0 +1,184 @@
+// Windows/CommonDialog.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#ifdef UNDER_CE\r
+#include <commdlg.h>\r
+#endif\r
+\r
+#ifndef _UNICODE\r
+#include "Common/StringConvert.h"\r
+#endif\r
+#include "Common/MyCom.h"\r
+\r
+#include "Windows/Defs.h"\r
+\r
+#include "CommonDialog.h"\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+namespace NWindows{\r
+\r
+#ifndef _UNICODE\r
+class CDoubleZeroStringListA\r
+{\r
+  CRecordVector<int> m_Indexes;\r
+  AString m_String;\r
+public:\r
+  void Add(LPCSTR s);\r
+  void SetForBuffer(LPSTR buffer);\r
+};\r
+\r
+void CDoubleZeroStringListA::Add(LPCSTR s)\r
+{\r
+  m_String += s;\r
+  m_Indexes.Add(m_String.Length());\r
+  m_String += ' ';\r
+}\r
+\r
+void CDoubleZeroStringListA::SetForBuffer(LPSTR buffer)\r
+{\r
+  MyStringCopy(buffer, (const char *)m_String);\r
+  for (int i = 0; i < m_Indexes.Size(); i++)\r
+    buffer[m_Indexes[i]] = '\0';\r
+}\r
+#endif\r
+\r
+class CDoubleZeroStringListW\r
+{\r
+  CRecordVector<int> m_Indexes;\r
+  UString m_String;\r
+public:\r
+  void Add(LPCWSTR s);\r
+  void SetForBuffer(LPWSTR buffer);\r
+};\r
+\r
+void CDoubleZeroStringListW::Add(LPCWSTR s)\r
+{\r
+  m_String += s;\r
+  m_Indexes.Add(m_String.Length());\r
+  m_String += L' ';\r
+}\r
+\r
+void CDoubleZeroStringListW::SetForBuffer(LPWSTR buffer)\r
+{\r
+  MyStringCopy(buffer, (const wchar_t *)m_String);\r
+  for (int i = 0; i < m_Indexes.Size(); i++)\r
+    buffer[m_Indexes[i]] = L'\0';\r
+}\r
+\r
+#define MY_OFN_PROJECT 0x00400000\r
+#define MY_OFN_SHOW_ALL 0x01000000\r
+\r
+bool MyGetOpenFileName(HWND hwnd, LPCWSTR title, LPCWSTR fullFileName,\r
+    LPCWSTR s, UString &resPath\r
+    #ifdef UNDER_CE\r
+    , bool openFolder\r
+    #endif\r
+    )\r
+{\r
+  const int kBufferSize = MAX_PATH * 2;\r
+  #ifndef _UNICODE\r
+  if (!g_IsNT)\r
+  {\r
+    CHAR buffer[kBufferSize];\r
+    MyStringCopy(buffer, (const char *)GetSystemString(fullFileName));\r
+    OPENFILENAME info;\r
+    info.lStructSize = sizeof(info);\r
+    info.hwndOwner = hwnd;\r
+    info.hInstance = 0;\r
+    const int kFilterBufferSize = MAX_PATH;\r
+    CHAR filterBuffer[kFilterBufferSize];\r
+    CDoubleZeroStringListA doubleZeroStringList;\r
+    doubleZeroStringList.Add(GetSystemString(s));\r
+    doubleZeroStringList.Add("*.*");\r
+    doubleZeroStringList.SetForBuffer(filterBuffer);\r
+    info.lpstrFilter = filterBuffer;\r
+    \r
+    info.lpstrCustomFilter = NULL;\r
+    info.nMaxCustFilter = 0;\r
+    info.nFilterIndex = 0;\r
+    \r
+    info.lpstrFile = buffer;\r
+    info.nMaxFile = kBufferSize;\r
+    \r
+    info.lpstrFileTitle = NULL;\r
+    info.nMaxFileTitle = 0;\r
+    \r
+    info.lpstrInitialDir= NULL;\r
+\r
+    info.lpstrTitle = 0;\r
+    AString titleA;\r
+    if (title != 0)\r
+    {\r
+      titleA = GetSystemString(title);\r
+      info.lpstrTitle = titleA;\r
+    }\r
+    \r
+    info.Flags = OFN_EXPLORER | OFN_HIDEREADONLY;\r
+    info.nFileOffset = 0;\r
+    info.nFileExtension = 0;\r
+    info.lpstrDefExt = NULL;\r
+    \r
+    info.lCustData = 0;\r
+    info.lpfnHook = NULL;\r
+    info.lpTemplateName = NULL;\r
+    \r
+    bool res = BOOLToBool(::GetOpenFileNameA(&info));\r
+    resPath = GetUnicodeString(buffer);\r
+    return res;\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    WCHAR buffer[kBufferSize];\r
+    MyStringCopy(buffer, fullFileName);\r
+    OPENFILENAMEW info;\r
+    info.lStructSize = sizeof(info);\r
+    info.hwndOwner = hwnd;\r
+    info.hInstance = 0;\r
+    const int kFilterBufferSize = MAX_PATH;\r
+    WCHAR filterBuffer[kFilterBufferSize];\r
+    CDoubleZeroStringListW doubleZeroStringList;\r
+    doubleZeroStringList.Add(s);\r
+    doubleZeroStringList.Add(L"*.*");\r
+    doubleZeroStringList.SetForBuffer(filterBuffer);\r
+    info.lpstrFilter = filterBuffer;\r
+        \r
+    info.lpstrCustomFilter = NULL;\r
+    info.nMaxCustFilter = 0;\r
+    info.nFilterIndex = 0;\r
+    \r
+    info.lpstrFile = buffer;\r
+    info.nMaxFile = kBufferSize;\r
+    \r
+    info.lpstrFileTitle = NULL;\r
+    info.nMaxFileTitle = 0;\r
+    \r
+    info.lpstrInitialDir= NULL;\r
+       \r
+    info.lpstrTitle = title;\r
+    \r
+    info.Flags = OFN_EXPLORER | OFN_HIDEREADONLY\r
+        #ifdef UNDER_CE\r
+        | (openFolder ? (MY_OFN_PROJECT | MY_OFN_SHOW_ALL) : 0)\r
+        #endif\r
+    ;\r
+\r
+    info.nFileOffset = 0;\r
+    info.nFileExtension = 0;\r
+    info.lpstrDefExt = NULL;\r
+    \r
+    info.lCustData = 0;\r
+    info.lpfnHook = NULL;\r
+    info.lpTemplateName = NULL;\r
+    \r
+    bool res = BOOLToBool(::GetOpenFileNameW(&info));\r
+    resPath = buffer;\r
+    return res;\r
+  }\r
+}\r
+\r
+}\r
diff --git a/CPP/Windows/CommonDialog.h b/CPP/Windows/CommonDialog.h
new file mode 100755 (executable)
index 0000000..bf87180
--- /dev/null
@@ -0,0 +1,19 @@
+// Windows/CommonDialog.h\r
+\r
+#ifndef __WINDOWS_COMMON_DIALOG_H\r
+#define __WINDOWS_COMMON_DIALOG_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+namespace NWindows{\r
+\r
+bool MyGetOpenFileName(HWND hwnd, LPCWSTR title, LPCWSTR fullFileName,\r
+    LPCWSTR s, UString &resPath\r
+    #ifdef UNDER_CE\r
+    , bool openFolder = false\r
+    #endif\r
+);\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Console.cpp b/CPP/Windows/Console.cpp
new file mode 100755 (executable)
index 0000000..fb2830c
--- /dev/null
@@ -0,0 +1,10 @@
+// Windows/Console.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/Console.h"\r
+\r
+namespace NWindows{\r
+namespace NConsole{\r
+\r
+}}\r
diff --git a/CPP/Windows/Console.h b/CPP/Windows/Console.h
new file mode 100755 (executable)
index 0000000..9000471
--- /dev/null
@@ -0,0 +1,52 @@
+// Windows/Console.h\r
+\r
+#ifndef __WINDOWS_CONSOLE_H\r
+#define __WINDOWS_CONSOLE_H\r
+\r
+#include "Windows/Defs.h"\r
+\r
+namespace NWindows{\r
+namespace NConsole{\r
+\r
+class CBase\r
+{\r
+protected:\r
+  HANDLE m_Object;\r
+public:\r
+  void Attach(HANDLE aHandle) { m_Object = aHandle; };\r
+  bool GetMode(DWORD &aMode)\r
+    { return BOOLToBool(::GetConsoleMode(m_Object, &aMode)); }\r
+  bool SetMode(DWORD aMode)\r
+    { return BOOLToBool(::SetConsoleMode(m_Object, aMode)); }\r
+};\r
+\r
+class CIn: public CBase\r
+{\r
+public:\r
+  bool PeekEvents(PINPUT_RECORD anEvents, DWORD aNumEvents, DWORD &aNumEventsRead)\r
+    {  return BOOLToBool(::PeekConsoleInput(m_Object, anEvents, aNumEvents, &aNumEventsRead)); }\r
+  bool PeekEvent(INPUT_RECORD &anEvent, DWORD &aNumEventsRead)\r
+    {  return PeekEvents(&anEvent, 1, aNumEventsRead); }\r
+  bool ReadEvents(PINPUT_RECORD anEvents, DWORD aNumEvents, DWORD &aNumEventsRead)\r
+    {  return BOOLToBool(::ReadConsoleInput(m_Object, anEvents, aNumEvents, &aNumEventsRead)); }\r
+  bool ReadEvent(INPUT_RECORD &anEvent, DWORD &aNumEventsRead)\r
+    {  return ReadEvents(&anEvent, 1, aNumEventsRead); }\r
+  bool GetNumberOfEvents(DWORD &aNumberOfEvents)\r
+    {  return BOOLToBool(::GetNumberOfConsoleInputEvents(m_Object, &aNumberOfEvents)); }\r
+\r
+  bool WriteEvents(const INPUT_RECORD *anEvents, DWORD aNumEvents, DWORD &aNumEventsWritten)\r
+    {  return BOOLToBool(::WriteConsoleInput(m_Object, anEvents, aNumEvents, &aNumEventsWritten)); }\r
+  bool WriteEvent(const INPUT_RECORD &anEvent, DWORD &aNumEventsWritten)\r
+    {  return WriteEvents(&anEvent, 1, aNumEventsWritten); }\r
+  \r
+  bool Read(LPVOID aBuffer, DWORD aNumberOfCharsToRead, DWORD &aNumberOfCharsRead)\r
+    {  return BOOLToBool(::ReadConsole(m_Object, aBuffer, aNumberOfCharsToRead, &aNumberOfCharsRead, NULL)); }\r
+\r
+  bool Flush()\r
+    {  return BOOLToBool(::FlushConsoleInputBuffer(m_Object)); }\r
+\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Control/ComboBox.cpp b/CPP/Windows/Control/ComboBox.cpp
new file mode 100755 (executable)
index 0000000..62ff2a1
--- /dev/null
@@ -0,0 +1,58 @@
+// Windows/Control/ComboBox.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#ifndef _UNICODE\r
+#include "Common/StringConvert.h"\r
+#endif\r
+\r
+#include "Windows/Control/ComboBox.h"\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+namespace NWindows {\r
+namespace NControl {\r
+\r
+LRESULT CComboBox::GetLBText(int index, CSysString &s)\r
+{\r
+  s.Empty();\r
+  LRESULT len = GetLBTextLen(index);\r
+  if (len == CB_ERR)\r
+    return len;\r
+  len = GetLBText(index, s.GetBuffer((int)len + 1));\r
+  s.ReleaseBuffer();\r
+  return len;\r
+}\r
+\r
+#ifndef _UNICODE\r
+LRESULT CComboBox::AddString(LPCWSTR s)\r
+{\r
+  if (g_IsNT)\r
+    return SendMessageW(CB_ADDSTRING, 0, (LPARAM)s);\r
+  return AddString(GetSystemString(s));\r
+}\r
+\r
+LRESULT CComboBox::GetLBText(int index, UString &s)\r
+{\r
+  s.Empty();\r
+  if (g_IsNT)\r
+  {\r
+    LRESULT len = SendMessageW(CB_GETLBTEXTLEN, index, 0);\r
+    if (len == CB_ERR)\r
+      return len;\r
+    len = SendMessageW(CB_GETLBTEXT, index, (LPARAM)s.GetBuffer((int)len + 1));\r
+    s.ReleaseBuffer();\r
+    return len;\r
+  }\r
+  AString sa;\r
+  LRESULT len = GetLBText(index, sa);\r
+  if (len == CB_ERR)\r
+    return len;\r
+  s = GetUnicodeString(sa);\r
+  return s.Length();\r
+}\r
+#endif\r
+\r
+}}\r
diff --git a/CPP/Windows/Control/ComboBox.h b/CPP/Windows/Control/ComboBox.h
new file mode 100755 (executable)
index 0000000..10f769f
--- /dev/null
@@ -0,0 +1,61 @@
+// Windows/Control/ComboBox.h\r
+\r
+#ifndef __WINDOWS_CONTROL_COMBOBOX_H\r
+#define __WINDOWS_CONTROL_COMBOBOX_H\r
+\r
+#include <commctrl.h>\r
+\r
+#include "../Window.h"\r
+\r
+namespace NWindows {\r
+namespace NControl {\r
+\r
+class CComboBox: public CWindow\r
+{\r
+public:\r
+  void ResetContent() { SendMessage(CB_RESETCONTENT, 0, 0); }\r
+  LRESULT AddString(LPCTSTR s) { return SendMessage(CB_ADDSTRING, 0, (LPARAM)s); }\r
+  #ifndef _UNICODE\r
+  LRESULT AddString(LPCWSTR s);\r
+  #endif\r
+  LRESULT SetCurSel(int index) { return SendMessage(CB_SETCURSEL, index, 0); }\r
+  int GetCurSel() { return (int)SendMessage(CB_GETCURSEL, 0, 0); }\r
+  int GetCount() { return (int)SendMessage(CB_GETCOUNT, 0, 0); }\r
+  \r
+  LRESULT GetLBTextLen(int index) { return SendMessage(CB_GETLBTEXTLEN, index, 0); }\r
+  LRESULT GetLBText(int index, LPTSTR s) { return SendMessage(CB_GETLBTEXT, index, (LPARAM)s); }\r
+  LRESULT GetLBText(int index, CSysString &s);\r
+  #ifndef _UNICODE\r
+  LRESULT GetLBText(int index, UString &s);\r
+  #endif\r
+\r
+  LRESULT SetItemData(int index, LPARAM lParam) { return SendMessage(CB_SETITEMDATA, index, lParam); }\r
+  LRESULT GetItemData(int index) { return SendMessage(CB_GETITEMDATA, index, 0); }\r
+\r
+  void ShowDropDown(bool show = true) { SendMessage(CB_SHOWDROPDOWN, show ? TRUE : FALSE, 0);  }\r
+};\r
+\r
+#ifndef UNDER_CE\r
+\r
+class CComboBoxEx: public CComboBox\r
+{\r
+public:\r
+  bool SetUnicodeFormat(bool fUnicode) { return LRESULTToBool(SendMessage(CBEM_SETUNICODEFORMAT, BOOLToBool(fUnicode), 0)); }\r
+\r
+  LRESULT DeleteItem(int index) { return SendMessage(CBEM_DELETEITEM, index, 0); }\r
+  LRESULT InsertItem(COMBOBOXEXITEM *item) { return SendMessage(CBEM_INSERTITEM, 0, (LPARAM)item); }\r
+  #ifndef _UNICODE\r
+  LRESULT InsertItem(COMBOBOXEXITEMW *item) { return SendMessage(CBEM_INSERTITEMW, 0, (LPARAM)item); }\r
+  #endif\r
+\r
+  LRESULT SetItem(COMBOBOXEXITEM *item) { return SendMessage(CBEM_SETITEM, 0, (LPARAM)item); }\r
+  DWORD SetExtendedStyle(DWORD exMask, DWORD exStyle) { return (DWORD)SendMessage(CBEM_SETEXTENDEDSTYLE, exMask, exStyle); }\r
+  HWND GetEditControl() { return (HWND)SendMessage(CBEM_GETEDITCONTROL, 0, 0); }\r
+  HIMAGELIST SetImageList(HIMAGELIST imageList) { return (HIMAGELIST)SendMessage(CBEM_SETIMAGELIST, 0, (LPARAM)imageList); }\r
+};\r
+\r
+#endif\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Control/CommandBar.h b/CPP/Windows/Control/CommandBar.h
new file mode 100755 (executable)
index 0000000..218130a
--- /dev/null
@@ -0,0 +1,48 @@
+// Windows/Control/CommandBar.h\r
+  \r
+#ifndef __WINDOWS_CONTROL_COMMANDBAR_H\r
+#define __WINDOWS_CONTROL_COMMANDBAR_H\r
+\r
+#ifdef UNDER_CE\r
+\r
+#include "Windows/Window.h"\r
+\r
+namespace NWindows {\r
+namespace NControl {\r
+\r
+class CCommandBar: public NWindows::CWindow\r
+{\r
+public:\r
+  bool Create(HINSTANCE hInst, HWND hwndParent, int idCmdBar)\r
+  {\r
+    _window = ::CommandBar_Create(hInst, hwndParent, idCmdBar);\r
+    return (_window != NULL);\r
+  }\r
+  \r
+  // Macros\r
+  // void Destroy() { CommandBar_Destroy(_window); }\r
+  bool AddButtons(int iButton, UINT numButtons, LPTBBUTTON buttons) { return BOOLToBool(SendMessage(TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)buttons)); }\r
+  bool InsertButton(int iButton, LPTBBUTTON button) { return BOOLToBool(SendMessage(TB_INSERTBUTTON, (WPARAM)iButton, (LPARAM)button)); }\r
+  BOOL AddToolTips(UINT numToolTips, LPTSTR toolTips) { return BOOLToBool(SendMessage(TB_SETTOOLTIPS, (WPARAM)numToolTips, (LPARAM)toolTips)); }\r
+  void AutoSize() { SendMessage(TB_AUTOSIZE, 0, 0); }\r
+\r
+  bool AddAdornments(DWORD dwFlags) { return BOOLToBool(::CommandBar_AddAdornments(_window, dwFlags, 0)); }\r
+  int AddBitmap(HINSTANCE hInst, int idBitmap, int iNumImages, int iImageWidth, int iImageHeight) { return ::CommandBar_AddBitmap(_window, hInst, idBitmap, iNumImages, iImageWidth, iImageHeight); }\r
+  bool DrawMenuBar(WORD iButton) { return BOOLToBool(::CommandBar_DrawMenuBar(_window, iButton)); }\r
+  HMENU GetMenu(WORD iButton) { return ::CommandBar_GetMenu(_window, iButton); }\r
+  int Height() { return CommandBar_Height(_window); }\r
+  HWND InsertComboBox(HINSTANCE hInst, int iWidth, UINT dwStyle, WORD idComboBox, WORD iButton) { return ::CommandBar_InsertComboBox(_window, hInst, iWidth, dwStyle, idComboBox, iButton); }\r
+  bool InsertMenubar(HINSTANCE hInst, WORD idMenu, WORD iButton) { return BOOLToBool(::CommandBar_InsertMenubar(_window, hInst, idMenu, iButton)); }\r
+  bool InsertMenubarEx(HINSTANCE hInst, LPTSTR pszMenu, WORD iButton) { return BOOLToBool(::CommandBar_InsertMenubarEx(_window, hInst, pszMenu, iButton)); }\r
+  bool Show(bool cmdShow) { return BOOLToBool(::CommandBar_Show(_window, BoolToBOOL(cmdShow))); }\r
+  \r
+\r
+  // CE 4.0\r
+  void AlignAdornments() { CommandBar_AlignAdornments(_window); }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
+\r
+#endif\r
diff --git a/CPP/Windows/Control/Dialog.cpp b/CPP/Windows/Control/Dialog.cpp
new file mode 100755 (executable)
index 0000000..f0209f0
--- /dev/null
@@ -0,0 +1,201 @@
+// Windows/Control/Dialog.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#ifndef _UNICODE\r
+#include "Common/StringConvert.h"\r
+#endif\r
+#include "Windows/Control/Dialog.h"\r
+\r
+extern HINSTANCE g_hInstance;\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+namespace NWindows {\r
+namespace NControl {\r
+\r
+static INT_PTR APIENTRY DialogProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+  CWindow dialogTmp(dialogHWND);\r
+  if (message == WM_INITDIALOG)\r
+    dialogTmp.SetUserDataLongPtr(lParam);\r
+  CDialog *dialog = (CDialog *)(dialogTmp.GetUserDataLongPtr());\r
+  if (dialog == NULL)\r
+    return FALSE;\r
+  if (message == WM_INITDIALOG)\r
+    dialog->Attach(dialogHWND);\r
+\r
+  try { return BoolToBOOL(dialog->OnMessage(message, wParam, lParam)); }\r
+  catch(...) { return true; }\r
+}\r
+\r
+bool CDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+  switch (message)\r
+  {\r
+    case WM_INITDIALOG: return OnInit();\r
+    case WM_COMMAND: return OnCommand(wParam, lParam);\r
+    case WM_NOTIFY: return OnNotify((UINT)wParam, (LPNMHDR) lParam);\r
+    case WM_TIMER: return OnTimer(wParam, lParam);\r
+    case WM_SIZE: return OnSize(wParam, LOWORD(lParam), HIWORD(lParam));\r
+    case WM_HELP: OnHelp(); return true;\r
+    /*\r
+        OnHelp(\r
+          #ifdef UNDER_CE\r
+          (void *)\r
+          #else\r
+          (LPHELPINFO)\r
+          #endif\r
+          lParam);\r
+        return true;\r
+    */\r
+    default: return false;\r
+  }\r
+}\r
+\r
+bool CDialog::OnCommand(WPARAM wParam, LPARAM lParam)\r
+{\r
+  return OnCommand(HIWORD(wParam), LOWORD(wParam), lParam);\r
+}\r
+\r
+bool CDialog::OnCommand(int code, int itemID, LPARAM lParam)\r
+{\r
+  if (code == BN_CLICKED)\r
+    return OnButtonClicked(itemID, (HWND)lParam);\r
+  return false;\r
+}\r
+\r
+bool CDialog::OnButtonClicked(int buttonID, HWND /* buttonHWND */)\r
+{\r
+  switch(buttonID)\r
+  {\r
+    case IDOK: OnOK(); break;\r
+    case IDCANCEL: OnCancel(); break;\r
+    case IDHELP: OnHelp(); break;\r
+    default: return false;\r
+  }\r
+  return true;\r
+}\r
+\r
+static bool GetWorkAreaRect(RECT *rect)\r
+{\r
+  // use another function for multi-monitor.\r
+  return BOOLToBool(::SystemParametersInfo(SPI_GETWORKAREA, NULL, rect, NULL));\r
+}\r
+\r
+bool IsDialogSizeOK(int xSize, int ySize)\r
+{\r
+  // it returns for system font. Real font uses another values\r
+  LONG v = GetDialogBaseUnits();\r
+  int x = LOWORD(v);\r
+  int y = HIWORD(v);\r
+\r
+  RECT rect;\r
+  GetWorkAreaRect(&rect);\r
+  int wx = RECT_SIZE_X(rect);\r
+  int wy = RECT_SIZE_Y(rect);\r
+  return\r
+    xSize / 4 * x <= wx &&\r
+    ySize / 8 * y <= wy;\r
+}\r
+\r
+void CDialog::NormalizeSize(bool fullNormalize)\r
+{\r
+  RECT workRect;\r
+  GetWorkAreaRect(&workRect);\r
+  int xSize = RECT_SIZE_X(workRect);\r
+  int ySize = RECT_SIZE_Y(workRect);\r
+  RECT rect;\r
+  GetWindowRect(&rect);\r
+  int xSize2 = RECT_SIZE_X(rect);\r
+  int ySize2 = RECT_SIZE_Y(rect);\r
+  bool needMove = (xSize2 > xSize || ySize2 > ySize);\r
+  if (xSize2 > xSize || (needMove && fullNormalize))\r
+  {\r
+    rect.left = workRect.left;\r
+    rect.right = workRect.right;\r
+    xSize2 = xSize;\r
+  }\r
+  if (ySize2 > ySize || (needMove && fullNormalize))\r
+  {\r
+    rect.top = workRect.top;\r
+    rect.bottom = workRect.bottom;\r
+    ySize2 = ySize;\r
+  }\r
+  if (needMove)\r
+  {\r
+    if (fullNormalize)\r
+      Show(SW_SHOWMAXIMIZED);\r
+    else\r
+      Move(rect.left, rect.top, xSize2, ySize2, true);\r
+  }\r
+}\r
+\r
+void CDialog::NormalizePosition()\r
+{\r
+  RECT workRect, rect;\r
+  GetWorkAreaRect(&workRect);\r
+  GetWindowRect(&rect);\r
+  if (rect.bottom > workRect.bottom && rect.top > workRect.top)\r
+    Move(rect.left, workRect.top, RECT_SIZE_X(rect), RECT_SIZE_Y(rect), true);\r
+}\r
+\r
+bool CModelessDialog::Create(LPCTSTR templateName, HWND parentWindow)\r
+{\r
+  HWND aHWND = CreateDialogParam(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);\r
+  if (aHWND == 0)\r
+    return false;\r
+  Attach(aHWND);\r
+  return true;\r
+}\r
+\r
+INT_PTR CModalDialog::Create(LPCTSTR templateName, HWND parentWindow)\r
+{\r
+  return DialogBoxParam(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);\r
+}\r
+\r
+#ifndef _UNICODE\r
+\r
+bool CModelessDialog::Create(LPCWSTR templateName, HWND parentWindow)\r
+{\r
+  HWND aHWND;\r
+  if (g_IsNT)\r
+    aHWND = CreateDialogParamW(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);\r
+  else\r
+  {\r
+    AString name;\r
+    LPCSTR templateNameA;\r
+    if (IS_INTRESOURCE(templateName))\r
+      templateNameA = (LPCSTR)templateName;\r
+    else\r
+    {\r
+      name = GetSystemString(templateName);\r
+      templateNameA = name;\r
+    }\r
+    aHWND = CreateDialogParamA(g_hInstance, templateNameA, parentWindow, DialogProcedure, (LPARAM)this);\r
+  }\r
+  if (aHWND == 0)\r
+    return false;\r
+  Attach(aHWND);\r
+  return true;\r
+}\r
+\r
+INT_PTR CModalDialog::Create(LPCWSTR templateName, HWND parentWindow)\r
+{\r
+  if (g_IsNT)\r
+    return DialogBoxParamW(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);\r
+  AString name;\r
+  LPCSTR templateNameA;\r
+  if (IS_INTRESOURCE(templateName))\r
+    templateNameA = (LPCSTR)templateName;\r
+  else\r
+  {\r
+    name = GetSystemString(templateName);\r
+    templateNameA = name;\r
+  }\r
+  return DialogBoxParamA(g_hInstance, templateNameA, parentWindow, DialogProcedure, (LPARAM)this);\r
+}\r
+#endif\r
+\r
+}}\r
diff --git a/CPP/Windows/Control/Dialog.h b/CPP/Windows/Control/Dialog.h
new file mode 100755 (executable)
index 0000000..b4c5e4f
--- /dev/null
@@ -0,0 +1,205 @@
+// Windows/Control/Dialog.h\r
+\r
+#ifndef __WINDOWS_CONTROL_DIALOG_H\r
+#define __WINDOWS_CONTROL_DIALOG_H\r
+\r
+#include "Windows/Window.h"\r
+\r
+namespace NWindows {\r
+namespace NControl {\r
+\r
+class CDialog: public CWindow\r
+{\r
+public:\r
+  CDialog(HWND wndow = NULL): CWindow(wndow){};\r
+  virtual ~CDialog() {};\r
+\r
+  HWND GetItem(int itemID) const\r
+    { return GetDlgItem(_window, itemID); }\r
+\r
+  bool EnableItem(int itemID, bool enable) const\r
+    { return BOOLToBool(::EnableWindow(GetItem(itemID), BoolToBOOL(enable))); }\r
+\r
+  bool ShowItem(int itemID, int cmdShow) const\r
+    { return BOOLToBool(::ShowWindow(GetItem(itemID), cmdShow)); }\r
+\r
+  bool HideItem(int itemID) const { return ShowItem(itemID, SW_HIDE); }\r
+\r
+  bool SetItemText(int itemID, LPCTSTR s)\r
+    { return BOOLToBool(SetDlgItemText(_window, itemID, s)); }\r
+\r
+  #ifndef _UNICODE\r
+  bool SetItemText(int itemID, LPCWSTR s)\r
+  {\r
+    CWindow window(GetItem(itemID));\r
+    return window.SetText(s);\r
+  }\r
+  #endif\r
+\r
+  UINT GetItemText(int itemID, LPTSTR string, int maxCount)\r
+    { return GetDlgItemText(_window, itemID, string, maxCount); }\r
+  #ifndef _UNICODE\r
+  /*\r
+  bool GetItemText(int itemID, LPWSTR string, int maxCount)\r
+  {\r
+    CWindow window(GetItem(itemID));\r
+    return window.GetText(string, maxCount);\r
+  }\r
+  */\r
+  #endif\r
+\r
+  bool SetItemInt(int itemID, UINT value, bool isSigned)\r
+    { return BOOLToBool(SetDlgItemInt(_window, itemID, value, BoolToBOOL(isSigned))); }\r
+  bool GetItemInt(int itemID, bool isSigned, UINT &value)\r
+  {\r
+    BOOL result;\r
+    value = GetDlgItemInt(_window, itemID, &result, BoolToBOOL(isSigned));\r
+    return BOOLToBool(result);\r
+  }\r
+\r
+  HWND GetNextGroupItem(HWND control, bool previous)\r
+    { return GetNextDlgGroupItem(_window, control, BoolToBOOL(previous)); }\r
+  HWND GetNextTabItem(HWND control, bool previous)\r
+    { return GetNextDlgTabItem(_window, control, BoolToBOOL(previous)); }\r
+\r
+  bool MapRect(LPRECT rect)\r
+    { return BOOLToBool(MapDialogRect(_window, rect)); }\r
+\r
+  bool IsMessage(LPMSG message)\r
+    { return BOOLToBool(IsDialogMessage(_window, message)); }\r
+\r
+  LRESULT SendItemMessage(int itemID, UINT message, WPARAM wParam, LPARAM lParam)\r
+    { return SendDlgItemMessage(_window, itemID, message, wParam, lParam); }\r
+\r
+  bool CheckButton(int buttonID, UINT checkState)\r
+    { return BOOLToBool(CheckDlgButton(_window, buttonID, checkState)); }\r
+  bool CheckButton(int buttonID, bool checkState)\r
+    { return CheckButton(buttonID, UINT(checkState ? BST_CHECKED : BST_UNCHECKED)); }\r
+\r
+  UINT IsButtonChecked(int buttonID) const\r
+    { return IsDlgButtonChecked(_window, buttonID); }\r
+  bool IsButtonCheckedBool(int buttonID) const\r
+    { return (IsButtonChecked(buttonID) == BST_CHECKED); }\r
+\r
+  bool CheckRadioButton(int firstButtonID, int lastButtonID, int checkButtonID)\r
+    { return BOOLToBool(::CheckRadioButton(_window, firstButtonID, lastButtonID, checkButtonID)); }\r
+\r
+  virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);\r
+  virtual bool OnInit() { return true; }\r
+  virtual bool OnCommand(WPARAM wParam, LPARAM lParam);\r
+  virtual bool OnCommand(int code, int itemID, LPARAM lParam);\r
+  virtual bool OnSize(WPARAM /* wParam */, int /* xSize */, int /* ySize */) { return false; }\r
+\r
+  /*\r
+  #ifdef UNDER_CE\r
+  virtual void OnHelp(void *) { OnHelp(); };\r
+  #else\r
+  virtual void OnHelp(LPHELPINFO) { OnHelp(); };\r
+  #endif\r
+  */\r
+  virtual void OnHelp() {};\r
+\r
+  virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);\r
+  virtual void OnOK() {};\r
+  virtual void OnCancel() {};\r
+  virtual bool OnNotify(UINT /* controlID */, LPNMHDR /* lParam */) { return false; }\r
+  virtual bool OnTimer(WPARAM /* timerID */, LPARAM /* callback */) { return false; }\r
+\r
+  LONG_PTR SetMsgResult(LONG_PTR newLongPtr )\r
+    { return SetLongPtr(DWLP_MSGRESULT, newLongPtr); }\r
+  LONG_PTR GetMsgResult() const\r
+    { return GetLongPtr(DWLP_MSGRESULT); }\r
+\r
+\r
+  bool GetMargins(int margin, int &x, int &y)\r
+  {\r
+    RECT rect;\r
+    rect.left = 0;\r
+    rect.top = 0;\r
+    rect.right = margin;\r
+    rect.bottom = margin;\r
+    if (!MapRect(&rect))\r
+      return false;\r
+    x = rect.right - rect.left;\r
+    y = rect.bottom - rect.top;\r
+    return true;\r
+  }\r
+\r
+  int Units_To_Pixels_X(int units)\r
+  {\r
+    RECT rect;\r
+    rect.left = 0;\r
+    rect.top = 0;\r
+    rect.right = units;\r
+    rect.bottom = units;\r
+    if (!MapRect(&rect))\r
+      return units * 3 / 2;\r
+    return rect.right - rect.left;\r
+  }\r
+\r
+  bool GetItemSizes(int id, int &x, int &y)\r
+  {\r
+    RECT rect;\r
+    if (!::GetWindowRect(GetItem(id), &rect))\r
+      return false;\r
+    x = rect.right - rect.left;\r
+    y = rect.bottom - rect.top;\r
+    return true;\r
+  }\r
+\r
+  void GetClientRectOfItem(int id, RECT &rect)\r
+  {\r
+    ::GetWindowRect(GetItem(id), &rect);\r
+    ScreenToClient(&rect);\r
+  }\r
+\r
+  \r
+  bool MoveItem(int id, int x, int y, int width, int height, bool repaint = true)\r
+    { return BOOLToBool(::MoveWindow(GetItem(id), x, y, width, height, BoolToBOOL(repaint))); }\r
+\r
+  void NormalizeSize(bool fullNormalize = false);\r
+  void NormalizePosition();\r
+};\r
+\r
+class CModelessDialog: public CDialog\r
+{\r
+public:\r
+  bool Create(LPCTSTR templateName, HWND parentWindow);\r
+  bool Create(UINT resID, HWND parentWindow) { return Create(MAKEINTRESOURCEW(resID), parentWindow); }\r
+  #ifndef _UNICODE\r
+  bool Create(LPCWSTR templateName, HWND parentWindow);\r
+  #endif\r
+  virtual void OnOK() { Destroy(); }\r
+  virtual void OnCancel() { Destroy(); }\r
+};\r
+\r
+class CModalDialog: public CDialog\r
+{\r
+public:\r
+  INT_PTR Create(LPCTSTR templateName, HWND parentWindow);\r
+  INT_PTR Create(UINT resID, HWND parentWindow) { return Create(MAKEINTRESOURCEW(resID), parentWindow); }\r
+  #ifndef _UNICODE\r
+  INT_PTR Create(LPCWSTR templateName, HWND parentWindow);\r
+  #endif\r
+\r
+  bool End(INT_PTR result) { return BOOLToBool(::EndDialog(_window, result)); }\r
+  virtual void OnOK() { End(IDOK); }\r
+  virtual void OnCancel() { End(IDCANCEL); }\r
+};\r
+\r
+class CDialogChildControl: public NWindows::CWindow\r
+{\r
+  int m_ID;\r
+public:\r
+  void Init(const NWindows::NControl::CDialog &parentDialog, int id)\r
+  {\r
+    m_ID = id;\r
+    Attach(parentDialog.GetItem(id));\r
+  }\r
+};\r
+\r
+bool IsDialogSizeOK(int xSize, int ySize);\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Control/Edit.h b/CPP/Windows/Control/Edit.h
new file mode 100755 (executable)
index 0000000..fc12b8d
--- /dev/null
@@ -0,0 +1,19 @@
+// Windows/Control/Edit.h\r
+\r
+#ifndef __WINDOWS_CONTROL_EDIT_H\r
+#define __WINDOWS_CONTROL_EDIT_H\r
+\r
+#include "Windows/Window.h"\r
+\r
+namespace NWindows {\r
+namespace NControl {\r
+\r
+class CEdit: public CWindow\r
+{\r
+public:\r
+  void SetPasswordChar(WPARAM c) { SendMessage(EM_SETPASSWORDCHAR, c); }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Control/ImageList.cpp b/CPP/Windows/Control/ImageList.cpp
new file mode 100755 (executable)
index 0000000..8aa39c4
--- /dev/null
@@ -0,0 +1,11 @@
+// Windows/Control/ImageList.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/Control/ImageList.h"\r
+\r
+namespace NWindows {\r
+namespace NControl {\r
+\r
+}}\r
+\r
diff --git a/CPP/Windows/Control/ImageList.h b/CPP/Windows/Control/ImageList.h
new file mode 100755 (executable)
index 0000000..2ac528b
--- /dev/null
@@ -0,0 +1,85 @@
+// Windows/Control/ImageList.h\r
+\r
+#ifndef __WINDOWS_CONTROL_IMAGELIST_H\r
+#define __WINDOWS_CONTROL_IMAGELIST_H\r
+\r
+#include "Windows/Defs.h"\r
+\r
+namespace NWindows {\r
+namespace NControl {\r
+\r
+class CImageList\r
+{\r
+  HIMAGELIST m_Object;\r
+public:\r
+  operator HIMAGELIST() const {return m_Object; }\r
+  CImageList(): m_Object(NULL) {}\r
+  bool Attach(HIMAGELIST imageList)\r
+  {\r
+    if (imageList == NULL)\r
+      return false;\r
+    m_Object = imageList;\r
+    return true;\r
+  }\r
+\r
+  HIMAGELIST Detach()\r
+  {\r
+    HIMAGELIST imageList = m_Object;\r
+    m_Object = NULL;\r
+    return imageList;\r
+  }\r
+  \r
+  bool Create(int width, int height, UINT flags, int initialNumber, int grow)\r
+  {\r
+    HIMAGELIST a = ImageList_Create(width, height, flags,\r
+      initialNumber, grow);\r
+    if (a == NULL)\r
+      return false;\r
+    return Attach(a);\r
+  }\r
+  \r
+  bool Destroy() // DeleteImageList() in MFC\r
+  {\r
+    if (m_Object == NULL)\r
+      return false;\r
+    return BOOLToBool(ImageList_Destroy(Detach()));\r
+  }\r
+\r
+  ~CImageList()\r
+    { Destroy(); }\r
+\r
+  int GetImageCount() const\r
+    { return ImageList_GetImageCount(m_Object); }\r
+\r
+  bool GetImageInfo(int index, IMAGEINFO* imageInfo) const\r
+    { return BOOLToBool(ImageList_GetImageInfo(m_Object, index, imageInfo)); }\r
+\r
+  int Add(HBITMAP hbmImage, HBITMAP hbmMask = 0)\r
+    { return ImageList_Add(m_Object, hbmImage, hbmMask); }\r
+  int AddMasked(HBITMAP hbmImage, COLORREF mask)\r
+    { return ImageList_AddMasked(m_Object, hbmImage, mask); }\r
+  int AddIcon(HICON icon)\r
+    { return ImageList_AddIcon(m_Object, icon); }\r
+  int Replace(int index, HICON icon)\r
+    { return ImageList_ReplaceIcon(m_Object, index, icon); }\r
+\r
+  // If index is -1, the function removes all images.\r
+  bool Remove(int index)\r
+    { return BOOLToBool(ImageList_Remove(m_Object, index)); }\r
+  bool RemoveAll()\r
+    { return BOOLToBool(ImageList_RemoveAll(m_Object)); }\r
+\r
+  HICON ExtractIcon(int index)\r
+    { return ImageList_ExtractIcon(NULL, m_Object, index); }\r
+  HICON GetIcon(int index, UINT flags)\r
+    { return ImageList_GetIcon(m_Object, index, flags); }\r
+\r
+  bool GetIconSize(int &width, int &height) const\r
+    { return BOOLToBool(ImageList_GetIconSize(m_Object, &width, &height)); }\r
+  bool SetIconSize(int width, int height)\r
+    { return BOOLToBool(ImageList_SetIconSize(m_Object, width, height)); }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Control/ListView.cpp b/CPP/Windows/Control/ListView.cpp
new file mode 100755 (executable)
index 0000000..08af2b1
--- /dev/null
@@ -0,0 +1,96 @@
+// Windows/Control/ListView.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/Control/ListView.h"\r
+\r
+namespace NWindows {\r
+namespace NControl {\r
+\r
+bool CListView::CreateEx(DWORD exStyle, DWORD style,\r
+      int x, int y, int width, int height,\r
+      HWND parentWindow, HMENU idOrHMenu,\r
+      HINSTANCE instance, LPVOID createParam)\r
+{\r
+  return CWindow::CreateEx(exStyle, WC_LISTVIEW, TEXT(""), style, x, y, width,\r
+      height, parentWindow, idOrHMenu, instance, createParam);\r
+}\r
+\r
+bool CListView::GetItemParam(int index, LPARAM &param) const\r
+{\r
+  LVITEM item;\r
+  item.iItem = index;\r
+  item.iSubItem = 0;\r
+  item.mask = LVIF_PARAM;\r
+  bool aResult = GetItem(&item);\r
+  param = item.lParam;\r
+  return aResult;\r
+}\r
+\r
+int CListView::InsertColumn(int columnIndex, LPCTSTR text, int width)\r
+{\r
+  LVCOLUMN ci;\r
+  ci.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;\r
+  ci.pszText = (LPTSTR)text;\r
+  ci.iSubItem = columnIndex;\r
+  ci.cx = width;\r
+  return InsertColumn(columnIndex, &ci);\r
+}\r
+\r
+int CListView::InsertItem(int index, LPCTSTR text)\r
+{\r
+  LVITEM item;\r
+  item.mask = LVIF_TEXT | LVIF_PARAM;\r
+  item.iItem = index;\r
+  item.lParam = index;\r
+  item.pszText = (LPTSTR)text;\r
+  item.iSubItem = 0;\r
+  return InsertItem(&item);\r
+}\r
+\r
+int CListView::SetSubItem(int index, int subIndex, LPCTSTR text)\r
+{\r
+  LVITEM item;\r
+  item.mask = LVIF_TEXT;\r
+  item.iItem = index;\r
+  item.pszText = (LPTSTR)text;\r
+  item.iSubItem = subIndex;\r
+  return SetItem(&item);\r
+}\r
+\r
+#ifndef _UNICODE\r
+\r
+int CListView::InsertColumn(int columnIndex, LPCWSTR text, int width)\r
+{\r
+  LVCOLUMNW ci;\r
+  ci.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;\r
+  ci.pszText = (LPWSTR)text;\r
+  ci.iSubItem = columnIndex;\r
+  ci.cx = width;\r
+  return InsertColumn(columnIndex, &ci);\r
+}\r
+\r
+int CListView::InsertItem(int index, LPCWSTR text)\r
+{\r
+  LVITEMW item;\r
+  item.mask = LVIF_TEXT | LVIF_PARAM;\r
+  item.iItem = index;\r
+  item.lParam = index;\r
+  item.pszText = (LPWSTR)text;\r
+  item.iSubItem = 0;\r
+  return InsertItem(&item);\r
+}\r
+\r
+int CListView::SetSubItem(int index, int subIndex, LPCWSTR text)\r
+{\r
+  LVITEMW item;\r
+  item.mask = LVIF_TEXT;\r
+  item.iItem = index;\r
+  item.pszText = (LPWSTR)text;\r
+  item.iSubItem = subIndex;\r
+  return SetItem(&item);\r
+}\r
+\r
+#endif\r
+\r
+}}\r
diff --git a/CPP/Windows/Control/ListView.h b/CPP/Windows/Control/ListView.h
new file mode 100755 (executable)
index 0000000..fc0e7de
--- /dev/null
@@ -0,0 +1,109 @@
+// Windows/Control/ListView.h\r
+\r
+#ifndef __WINDOWS_CONTROL_LISTVIEW_H\r
+#define __WINDOWS_CONTROL_LISTVIEW_H\r
+\r
+#include "Windows/Window.h"\r
+\r
+#include <commctrl.h>\r
+\r
+namespace NWindows {\r
+namespace NControl {\r
+\r
+class CListView: public NWindows::CWindow\r
+{\r
+public:\r
+  bool CreateEx(DWORD exStyle, DWORD style,\r
+      int x, int y, int width, int height,\r
+      HWND parentWindow, HMENU idOrHMenu,\r
+      HINSTANCE instance, LPVOID createParam);\r
+\r
+  #ifndef UNDER_CE\r
+  bool SetUnicodeFormat(bool fUnicode) { return BOOLToBool(ListView_SetUnicodeFormat(_window, BOOLToBool(fUnicode))); }\r
+  #endif\r
\r
+  bool DeleteAllItems() { return BOOLToBool(ListView_DeleteAllItems(_window)); }\r
+  bool DeleteColumn(int columnIndex) { return BOOLToBool(ListView_DeleteColumn(_window, columnIndex)); }\r
+\r
+  int InsertColumn(int columnIndex, const LVCOLUMN *columnInfo) { return ListView_InsertColumn(_window, columnIndex, columnInfo); }\r
+  int InsertColumn(int columnIndex, LPCTSTR text, int width);\r
+  int InsertItem(const LVITEM* item) { return ListView_InsertItem(_window, item); }\r
+  int InsertItem(int index, LPCTSTR text);\r
+  bool SetItem(const LVITEM* item) { return BOOLToBool(ListView_SetItem(_window, item)); }\r
+  int SetSubItem(int index, int subIndex, LPCTSTR text);\r
+\r
+  #ifndef _UNICODE\r
+\r
+  int InsertColumn(int columnIndex, const LVCOLUMNW *columnInfo) { return (int)SendMessage(LVM_INSERTCOLUMNW, (WPARAM)columnIndex, (LPARAM)columnInfo); }\r
+  int InsertColumn(int columnIndex, LPCWSTR text, int width);\r
+  int InsertItem(const LV_ITEMW* item) { return (int)SendMessage(LVM_INSERTITEMW, 0, (LPARAM)item); }\r
+  int InsertItem(int index, LPCWSTR text);\r
+  bool SetItem(const LV_ITEMW* item) { return BOOLToBool((BOOL)SendMessage(LVM_SETITEMW, 0, (LPARAM)item)); }\r
+  int SetSubItem(int index, int subIndex, LPCWSTR text);\r
+\r
+  #endif\r
+\r
+  bool DeleteItem(int itemIndex) { return BOOLToBool(ListView_DeleteItem(_window, itemIndex)); }\r
+\r
+  UINT GetSelectedCount() const { return ListView_GetSelectedCount(_window); }\r
+  int GetItemCount() const { return ListView_GetItemCount(_window); }\r
+\r
+  INT GetSelectionMark() const { return ListView_GetSelectionMark(_window); }\r
+\r
+  void SetItemCount(int numItems) { ListView_SetItemCount(_window, numItems); }\r
+  void SetItemCountEx(int numItems, DWORD flags) {  ListView_SetItemCountEx(_window, numItems, flags); }\r
+\r
+  int GetNextItem(int startIndex, UINT flags) const { return ListView_GetNextItem(_window, startIndex, flags); }\r
+  int GetNextSelectedItem(int startIndex) const { return GetNextItem(startIndex, LVNI_SELECTED); }\r
+  int GetFocusedItem() const { return GetNextItem(-1, LVNI_FOCUSED); }\r
+  \r
+  bool GetItem(LVITEM* item) const { return BOOLToBool(ListView_GetItem(_window, item)); }\r
+  bool GetItemParam(int itemIndex, LPARAM &param) const;\r
+  void GetItemText(int itemIndex, int subItemIndex, LPTSTR text, int textSizeMax) const\r
+    { ListView_GetItemText(_window, itemIndex, subItemIndex, text, textSizeMax); }\r
+  bool SortItems(PFNLVCOMPARE compareFunction, LPARAM dataParam)\r
+    { return BOOLToBool(ListView_SortItems(_window, compareFunction, dataParam)); }\r
+\r
+  void SetItemState(int index, UINT state, UINT mask) { ListView_SetItemState(_window, index, state, mask); }\r
+  void SetItemState_FocusedSelected(int index) { SetItemState(index, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); }\r
+  UINT GetItemState(int index, UINT mask) const { return ListView_GetItemState(_window, index, mask); }\r
+\r
+  bool GetColumn(int columnIndex, LVCOLUMN* columnInfo) const\r
+    { return BOOLToBool(ListView_GetColumn(_window, columnIndex, columnInfo)); }\r
+\r
+  HIMAGELIST SetImageList(HIMAGELIST imageList, int imageListType)\r
+    { return ListView_SetImageList(_window, imageList, imageListType); }\r
+\r
+  // version 4.70: NT5 | (NT4 + ie3) | w98 | (w95 + ie3)\r
+  DWORD GetExtendedListViewStyle() { return ListView_GetExtendedListViewStyle(_window); }\r
+  void SetExtendedListViewStyle(DWORD exStyle) { ListView_SetExtendedListViewStyle(_window, exStyle); }\r
+  void SetExtendedListViewStyle(DWORD exMask, DWORD exStyle) { ListView_SetExtendedListViewStyleEx(_window, exMask, exStyle); }\r
+\r
+  void SetCheckState(UINT index, bool checkState) { ListView_SetCheckState(_window, index, BoolToBOOL(checkState)); }\r
+  bool GetCheckState(UINT index) { return BOOLToBool(ListView_GetCheckState(_window, index)); }\r
+\r
+  bool EnsureVisible(int index, bool partialOK) { return BOOLToBool(ListView_EnsureVisible(_window, index, BoolToBOOL(partialOK))); }\r
+\r
+  bool GetItemRect(int index, RECT *rect, int code) { return BOOLToBool(ListView_GetItemRect(_window, index, rect, code)); }\r
+\r
+  HWND GetEditControl() { return ListView_GetEditControl(_window) ; }\r
+  HWND EditLabel(int itemIndex) { return ListView_EditLabel(_window, itemIndex) ; }\r
+\r
+  bool RedrawItems(int firstIndex, int lastIndex) { return BOOLToBool(ListView_RedrawItems(_window, firstIndex, lastIndex)); }\r
+  bool RedrawAllItems()\r
+  {\r
+    if (GetItemCount() > 0)\r
+      return RedrawItems(0, GetItemCount() - 1);\r
+    return true;\r
+  }\r
+  bool RedrawItem(int index) { return RedrawItems(index, index); }\r
\r
+  int HitTest(LPLVHITTESTINFO info) { return ListView_HitTest(_window, info); }\r
+  COLORREF GetBkColor() { return ListView_GetBkColor(_window); }\r
+  bool SetColumnWidth(int iCol, int cx) { return BOOLToBool(ListView_SetColumnWidth(_window, iCol, cx)); }\r
+  bool SetColumnWidthAuto(int iCol) { return SetColumnWidth(iCol, LVSCW_AUTOSIZE); }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Control/ProgressBar.h b/CPP/Windows/Control/ProgressBar.h
new file mode 100755 (executable)
index 0000000..71dc912
--- /dev/null
@@ -0,0 +1,31 @@
+// Windows/Control/ProgressBar.h\r
+\r
+#ifndef __WINDOWS_CONTROL_PROGRESSBAR_H\r
+#define __WINDOWS_CONTROL_PROGRESSBAR_H\r
+\r
+#include "../Window.h"\r
+\r
+namespace NWindows {\r
+namespace NControl {\r
+\r
+class CProgressBar: public CWindow\r
+{\r
+public:\r
+  LRESULT SetPos(int pos) { return SendMessage(PBM_SETPOS, pos, 0); }\r
+  LRESULT DeltaPos(int increment) { return SendMessage(PBM_DELTAPOS, increment, 0); }\r
+  UINT GetPos() { return (UINT)SendMessage(PBM_GETPOS, 0, 0); }\r
+  LRESULT SetRange(unsigned short minValue, unsigned short maxValue) { return SendMessage(PBM_SETRANGE, 0, MAKELPARAM(minValue, maxValue)); }\r
+  DWORD SetRange32(int minValue, int maxValue) { return (DWORD)SendMessage(PBM_SETRANGE32, minValue, maxValue); }\r
+  int SetStep(int step) { return (int)SendMessage(PBM_SETSTEP, step, 0); }\r
+  LRESULT StepIt() { return SendMessage(PBM_STEPIT, 0, 0); }\r
+  INT GetRange(bool minValue, PPBRANGE range) { return (INT)SendMessage(PBM_GETRANGE, BoolToBOOL(minValue), (LPARAM)range); }\r
+  \r
+  #ifndef UNDER_CE\r
+  COLORREF SetBarColor(COLORREF color) { return (COLORREF)SendMessage(PBM_SETBARCOLOR, 0, color); }\r
+  COLORREF SetBackgroundColor(COLORREF color) { return (COLORREF)SendMessage(PBM_SETBKCOLOR, 0, color); }\r
+  #endif\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Control/PropertyPage.cpp b/CPP/Windows/Control/PropertyPage.cpp
new file mode 100755 (executable)
index 0000000..d95ed58
--- /dev/null
@@ -0,0 +1,162 @@
+// Windows/Control/PropertyPage.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/Control/PropertyPage.h"\r
+#ifndef _UNICODE\r
+#include "../../Common/StringConvert.h"\r
+#endif\r
+\r
+extern HINSTANCE g_hInstance;\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+namespace NWindows {\r
+namespace NControl {\r
+\r
+INT_PTR APIENTRY ProperyPageProcedure(HWND dialogHWND, UINT message,\r
+    WPARAM wParam, LPARAM lParam)\r
+{\r
+  CDialog tempDialog(dialogHWND);\r
+  if (message == WM_INITDIALOG)\r
+    tempDialog.SetUserDataLongPtr(((PROPSHEETPAGE *)lParam)->lParam);\r
+  CDialog *dialog = (CDialog *)(tempDialog.GetUserDataLongPtr());\r
+  if (message == WM_INITDIALOG)\r
+    dialog->Attach(dialogHWND);\r
+  switch (message)\r
+  {\r
+    case WM_INITDIALOG:\r
+      return dialog->OnInit();\r
+    case WM_COMMAND:\r
+      return dialog->OnCommand(wParam, lParam);\r
+    case WM_NOTIFY:\r
+      return dialog->OnNotify((UINT)wParam, (LPNMHDR) lParam);\r
+  }\r
+  if (dialog == NULL)\r
+    return false;\r
+  return dialog->OnMessage(message, wParam, lParam);\r
+}\r
+\r
+bool CPropertyPage::OnNotify(UINT /* controlID */, LPNMHDR lParam)\r
+{\r
+  switch(lParam->code)\r
+  {\r
+    case PSN_APPLY:\r
+      SetMsgResult(OnApply(LPPSHNOTIFY(lParam)));\r
+      break;\r
+    case PSN_KILLACTIVE:\r
+      SetMsgResult(BoolToBOOL(OnKillActive(LPPSHNOTIFY(lParam))));\r
+      break;\r
+    case PSN_SETACTIVE:\r
+      SetMsgResult(OnSetActive(LPPSHNOTIFY(lParam)));\r
+      break;\r
+    case PSN_RESET:\r
+      OnReset(LPPSHNOTIFY(lParam));\r
+      break;\r
+    case PSN_HELP:\r
+      OnNotifyHelp(LPPSHNOTIFY(lParam));\r
+      break;\r
+    default:\r
+      return false;\r
+  }\r
+  return true;\r
+}\r
+\r
+INT_PTR MyPropertySheet(const CObjectVector<CPageInfo> &pagesInfo, HWND hwndParent, const UString &title)\r
+{\r
+  #ifndef _UNICODE\r
+  AStringVector titles;\r
+  #endif\r
+  #ifndef _UNICODE\r
+  CRecordVector<PROPSHEETPAGEA> pagesA;\r
+  #endif\r
+  CRecordVector<PROPSHEETPAGEW> pagesW;\r
+\r
+  int i;\r
+  #ifndef _UNICODE\r
+  for (i = 0; i < pagesInfo.Size(); i++)\r
+    titles.Add(GetSystemString(pagesInfo[i].Title));\r
+  #endif\r
+\r
+  for (i = 0; i < pagesInfo.Size(); i++)\r
+  {\r
+    const CPageInfo &pageInfo = pagesInfo[i];\r
+    #ifndef _UNICODE\r
+    {\r
+      PROPSHEETPAGE page;\r
+      page.dwSize = sizeof(page);\r
+      page.dwFlags = PSP_HASHELP;\r
+      page.hInstance = g_hInstance;\r
+      page.pszTemplate = MAKEINTRESOURCE(pageInfo.ID);\r
+      page.pszIcon = NULL;\r
+      page.pfnDlgProc = NWindows::NControl::ProperyPageProcedure;\r
+      \r
+      if (titles[i].IsEmpty())\r
+        page.pszTitle = NULL;\r
+      else\r
+      {\r
+        page.dwFlags |= PSP_USETITLE;\r
+        page.pszTitle = titles[i];\r
+      }\r
+      page.lParam = (LPARAM)pageInfo.Page;\r
+      page.pfnCallback = NULL;\r
+      pagesA.Add(page);\r
+    }\r
+    #endif\r
+    {\r
+      PROPSHEETPAGEW page;\r
+      page.dwSize = sizeof(page);\r
+      page.dwFlags = PSP_HASHELP;\r
+      page.hInstance = g_hInstance;\r
+      page.pszTemplate = MAKEINTRESOURCEW(pageInfo.ID);\r
+      page.pszIcon = NULL;\r
+      page.pfnDlgProc = NWindows::NControl::ProperyPageProcedure;\r
+      \r
+      if (pageInfo.Title.IsEmpty())\r
+        page.pszTitle = NULL;\r
+      else\r
+      {\r
+        page.dwFlags |= PSP_USETITLE;\r
+        page.pszTitle = pageInfo.Title;\r
+      }\r
+      page.lParam = (LPARAM)pageInfo.Page;\r
+      page.pfnCallback = NULL;\r
+      pagesW.Add(page);\r
+    }\r
+  }\r
+\r
+  #ifndef _UNICODE\r
+  if (!g_IsNT)\r
+  {\r
+    PROPSHEETHEADER sheet;\r
+    sheet.dwSize = sizeof(sheet);\r
+    sheet.dwFlags = PSH_PROPSHEETPAGE;\r
+    sheet.hwndParent = hwndParent;\r
+    sheet.hInstance = g_hInstance;\r
+    AString titleA = GetSystemString(title);\r
+    sheet.pszCaption = titleA;\r
+    sheet.nPages = pagesInfo.Size();\r
+    sheet.nStartPage = 0;\r
+    sheet.ppsp = &pagesA.Front();\r
+    sheet.pfnCallback = NULL;\r
+    return ::PropertySheetA(&sheet);\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    PROPSHEETHEADERW sheet;\r
+    sheet.dwSize = sizeof(sheet);\r
+    sheet.dwFlags = PSH_PROPSHEETPAGE;\r
+    sheet.hwndParent = hwndParent;\r
+    sheet.hInstance = g_hInstance;\r
+    sheet.pszCaption = title;\r
+    sheet.nPages = pagesInfo.Size();\r
+    sheet.nStartPage = 0;\r
+    sheet.ppsp = &pagesW.Front();\r
+    sheet.pfnCallback = NULL;\r
+    return ::PropertySheetW(&sheet);\r
+  }\r
+}\r
+\r
+}}\r
diff --git a/CPP/Windows/Control/PropertyPage.h b/CPP/Windows/Control/PropertyPage.h
new file mode 100755 (executable)
index 0000000..4687ed9
--- /dev/null
@@ -0,0 +1,46 @@
+// Windows/Control/PropertyPage.h\r
+\r
+#ifndef __WINDOWS_CONTROL_PROPERTYPAGE_H\r
+#define __WINDOWS_CONTROL_PROPERTYPAGE_H\r
+\r
+#include "Dialog.h"\r
+\r
+namespace NWindows {\r
+namespace NControl {\r
+\r
+INT_PTR APIENTRY ProperyPageProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam);\r
+\r
+class CPropertyPage: public CDialog\r
+{\r
+public:\r
+  CPropertyPage(HWND window = NULL): CDialog(window){};\r
+  \r
+  void Changed() { PropSheet_Changed(GetParent(), (HWND)*this); }\r
+  void UnChanged() { PropSheet_UnChanged(GetParent(), (HWND)*this); }\r
+\r
+  virtual bool OnNotify(UINT controlID, LPNMHDR lParam);\r
+\r
+  virtual bool OnKillActive() { return false; } // false = OK\r
+  virtual bool OnKillActive(const PSHNOTIFY *) { return OnKillActive(); }\r
+  virtual LONG OnSetActive() { return false; } // false = OK\r
+  virtual LONG OnSetActive(const PSHNOTIFY *) { return OnSetActive(); }\r
+  virtual LONG OnApply() { return PSNRET_NOERROR; }\r
+  virtual LONG OnApply(const PSHNOTIFY *) { return OnApply(); }\r
+  virtual void OnNotifyHelp() {}\r
+  virtual void OnNotifyHelp(const PSHNOTIFY *) { OnNotifyHelp(); }\r
+  virtual void OnReset() {}\r
+  virtual void OnReset(const PSHNOTIFY *) { OnReset(); }\r
+};\r
+\r
+struct CPageInfo\r
+{\r
+  CPropertyPage *Page;\r
+  UString Title;\r
+  UINT ID;\r
+};\r
+\r
+INT_PTR MyPropertySheet(const CObjectVector<CPageInfo> &pagesInfo, HWND hwndParent, const UString &title);\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Control/ReBar.h b/CPP/Windows/Control/ReBar.h
new file mode 100755 (executable)
index 0000000..a8f14b8
--- /dev/null
@@ -0,0 +1,35 @@
+// Windows/Control/ReBar.h\r
+  \r
+#ifndef __WINDOWS_CONTROL_REBAR_H\r
+#define __WINDOWS_CONTROL_REBAR_H\r
+\r
+#include "Windows/Window.h"\r
+#include "Windows/Defs.h"\r
+\r
+namespace NWindows {\r
+namespace NControl {\r
+\r
+class CReBar: public NWindows::CWindow\r
+{\r
+public:\r
+  bool SetBarInfo(LPREBARINFO barInfo)\r
+    { return LRESULTToBool(SendMessage(RB_SETBARINFO, 0, (LPARAM)barInfo)); }\r
+  bool InsertBand(int index, LPREBARBANDINFO bandInfo)\r
+    { return LRESULTToBool(SendMessage(RB_INSERTBAND, index, (LPARAM)bandInfo)); }\r
+  bool SetBandInfo(int index, LPREBARBANDINFO bandInfo)\r
+    { return LRESULTToBool(SendMessage(RB_SETBANDINFO, index, (LPARAM)bandInfo)); }\r
+  void MaximizeBand(int index, bool ideal)\r
+    { SendMessage(RB_MAXIMIZEBAND, index, BoolToBOOL(ideal)); }\r
+  bool SizeToRect(LPRECT rect)\r
+    { return LRESULTToBool(SendMessage(RB_SIZETORECT, 0, (LPARAM)rect)); }\r
+  UINT GetHeight()\r
+    { return (UINT)SendMessage(RB_GETBARHEIGHT); }\r
+  UINT GetBandCount()\r
+    { return (UINT)SendMessage(RB_GETBANDCOUNT); }\r
+  bool DeleteBand(UINT index)\r
+    { return LRESULTToBool(SendMessage(RB_DELETEBAND, index)); }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Control/Static.h b/CPP/Windows/Control/Static.h
new file mode 100755 (executable)
index 0000000..355b9e8
--- /dev/null
@@ -0,0 +1,28 @@
+// Windows/Control/Static.h\r
+\r
+#ifndef __WINDOWS_CONTROL_STATIC_H\r
+#define __WINDOWS_CONTROL_STATIC_H\r
+\r
+#include "../Window.h"\r
+\r
+namespace NWindows {\r
+namespace NControl {\r
+\r
+class CStatic: public CWindow\r
+{\r
+public:\r
+  HANDLE SetImage(WPARAM imageType, HANDLE handle) { return (HANDLE)SendMessage(STM_SETIMAGE, imageType, (LPARAM)handle); }\r
+  HANDLE GetImage(WPARAM imageType) { return (HANDLE)SendMessage(STM_GETIMAGE, imageType, 0); }\r
+\r
+  #ifdef UNDER_CE\r
+  HICON SetIcon(HICON icon) { return (HICON)SetImage(IMAGE_ICON, icon); }\r
+  HICON GetIcon() { return (HICON)GetImage(IMAGE_ICON); }\r
+  #else\r
+  HICON SetIcon(HICON icon) { return (HICON)SendMessage(STM_SETICON, (WPARAM)icon, 0); }\r
+  HICON GetIcon() { return (HICON)SendMessage(STM_GETICON, 0, 0); }\r
+  #endif\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Control/StatusBar.h b/CPP/Windows/Control/StatusBar.h
new file mode 100755 (executable)
index 0000000..9c88d36
--- /dev/null
@@ -0,0 +1,43 @@
+// Windows/Control/StatusBar.h\r
+\r
+#ifndef __WINDOWS_CONTROL_STATUSBAR_H\r
+#define __WINDOWS_CONTROL_STATUSBAR_H\r
+\r
+#include "Windows/Window.h"\r
+#include "Windows/Defs.h"\r
+\r
+namespace NWindows {\r
+namespace NControl {\r
+\r
+class CStatusBar: public NWindows::CWindow\r
+{\r
+public:\r
+  bool Create(LONG style, LPCTSTR text, HWND hwndParent, UINT id)\r
+    { return (_window = ::CreateStatusWindow(style, text, hwndParent, id)) != 0; }\r
+  bool SetParts(int numParts, const int *edgePostions)\r
+    { return LRESULTToBool(SendMessage(SB_SETPARTS, numParts, (LPARAM)edgePostions)); }\r
+  bool SetText(LPCTSTR text)\r
+    { return CWindow::SetText(text); }\r
+\r
+  bool SetText(int index, LPCTSTR text, UINT type)\r
+    { return LRESULTToBool(SendMessage(SB_SETTEXT, index | type, (LPARAM)text)); }\r
+  bool SetText(int index, LPCTSTR text)\r
+    { return SetText(index, text, 0); }\r
+  void Simple(bool simple)\r
+    { SendMessage(SB_SIMPLE, BoolToBOOL(simple), 0); }\r
+\r
+  #ifndef _UNICODE\r
+  bool Create(LONG style, LPCWSTR text, HWND hwndParent, UINT id)\r
+    { return (_window = ::CreateStatusWindowW(style, text, hwndParent, id)) != 0; }\r
+  bool SetText(LPCWSTR text)\r
+    { return CWindow::SetText(text); }\r
+  bool SetText(int index, LPCWSTR text, UINT type)\r
+    { return LRESULTToBool(SendMessage(SB_SETTEXTW, index | type, (LPARAM)text)); }\r
+  bool SetText(int index, LPCWSTR text)\r
+    { return SetText(index, text, 0); }\r
+  #endif\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Control/StdAfx.h b/CPP/Windows/Control/StdAfx.h
new file mode 100755 (executable)
index 0000000..f56e92f
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../../Common/MyWindows.h"\r
+#include "../../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/Windows/Control/ToolBar.h b/CPP/Windows/Control/ToolBar.h
new file mode 100755 (executable)
index 0000000..3aefd9b
--- /dev/null
@@ -0,0 +1,43 @@
+// Windows/Control/ToolBar.h\r
+  \r
+#ifndef __WINDOWS_CONTROL_TOOLBAR_H\r
+#define __WINDOWS_CONTROL_TOOLBAR_H\r
+\r
+#include "Windows/Window.h"\r
+\r
+namespace NWindows {\r
+namespace NControl {\r
+\r
+class CToolBar: public NWindows::CWindow\r
+{\r
+public:\r
+  void AutoSize() { SendMessage(TB_AUTOSIZE, 0, 0); }\r
+  DWORD GetButtonSize() { return (DWORD)SendMessage(TB_GETBUTTONSIZE, 0, 0); }\r
+  \r
+  bool GetMaxSize(LPSIZE size)\r
+  #ifdef UNDER_CE\r
+  {\r
+    // maybe it must be fixed for more than 1 buttons\r
+    DWORD val = GetButtonSize();\r
+    size->cx = LOWORD(val);\r
+    size->cy = HIWORD(val);\r
+    return true;\r
+  }\r
+  #else\r
+  {\r
+    return LRESULTToBool(SendMessage(TB_GETMAXSIZE, 0, (LPARAM)size));\r
+  }\r
+  #endif\r
+\r
+  bool EnableButton(UINT buttonID, bool enable) { return LRESULTToBool(SendMessage(TB_ENABLEBUTTON, buttonID, MAKELONG(BoolToBOOL(enable), 0))); }\r
+  void ButtonStructSize() { SendMessage(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON)); }\r
+  HIMAGELIST SetImageList(UINT listIndex, HIMAGELIST imageList) { return HIMAGELIST(SendMessage(TB_SETIMAGELIST, listIndex, (LPARAM)imageList)); }\r
+  bool AddButton(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMessage(TB_ADDBUTTONS, numButtons, (LPARAM)buttons)); }\r
+  #ifndef _UNICODE\r
+  bool AddButtonW(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMessage(TB_ADDBUTTONSW, numButtons, (LPARAM)buttons)); }\r
+  #endif\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Control/Trackbar.h b/CPP/Windows/Control/Trackbar.h
new file mode 100755 (executable)
index 0000000..6f03a69
--- /dev/null
@@ -0,0 +1,28 @@
+// Windows/Control/Trackbar.h\r
+\r
+#ifndef __WINDOWS_CONTROL_TRACKBAR_H\r
+#define __WINDOWS_CONTROL_TRACKBAR_H\r
+\r
+#include "Windows/Window.h"\r
+#include "Windows/Defs.h"\r
+\r
+namespace NWindows {\r
+namespace NControl {\r
+\r
+class CTrackbar: public CWindow\r
+{\r
+public:\r
+  void SetRange(int minimum, int maximum, bool redraw = true)\r
+    { SendMessage(TBM_SETRANGE, BoolToBOOL(redraw), MAKELONG(minimum, maximum)); }\r
+  void SetPos(int pos, bool redraw = true)\r
+    { SendMessage(TBM_SETPOS, BoolToBOOL(redraw), pos); }\r
+  void SetTicFreq(int freq)\r
+    { SendMessage(TBM_SETTICFREQ, freq); }\r
+  \r
+  int GetPos()\r
+    { return (int)SendMessage(TBM_GETPOS); }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Control/Window2.cpp b/CPP/Windows/Control/Window2.cpp
new file mode 100755 (executable)
index 0000000..7f928b0
--- /dev/null
@@ -0,0 +1,209 @@
+// Windows/Control/Window2.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#ifndef _UNICODE\r
+#include "Common/StringConvert.h"\r
+#endif\r
+#include "Windows/Control/Window2.h"\r
+\r
+// extern HINSTANCE g_hInstance;\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+namespace NWindows {\r
+\r
+#ifndef _UNICODE\r
+ATOM MyRegisterClass(CONST WNDCLASSW *wndClass);\r
+#endif\r
+\r
+namespace NControl {\r
+\r
+#ifdef UNDER_CE\r
+#define MY_START_WM_CREATE WM_CREATE\r
+#else\r
+#define MY_START_WM_CREATE WM_NCCREATE\r
+#endif\r
+\r
+static LRESULT CALLBACK WindowProcedure(HWND aHWND, UINT message,\r
+    WPARAM wParam, LPARAM lParam)\r
+{\r
+  CWindow tempWindow(aHWND);\r
+  if (message == MY_START_WM_CREATE)\r
+    tempWindow.SetUserDataLongPtr(\r
+        LONG_PTR(((LPCREATESTRUCT)lParam)->lpCreateParams));\r
+  CWindow2 *window = (CWindow2*)(tempWindow.GetUserDataLongPtr());\r
+  if (window != NULL && message == MY_START_WM_CREATE)\r
+    window->Attach(aHWND);\r
+  if (window == 0)\r
+  {\r
+    #ifndef _UNICODE\r
+    if (g_IsNT)\r
+      return DefWindowProcW(aHWND, message, wParam, lParam);\r
+    else\r
+    #endif\r
+      return DefWindowProc(aHWND, message, wParam, lParam);\r
+  }\r
+  return window->OnMessage(message, wParam, lParam);\r
+}\r
+\r
+bool CWindow2::CreateEx(DWORD exStyle, LPCTSTR className,\r
+      LPCTSTR windowName, DWORD style,\r
+      int x, int y, int width, int height,\r
+      HWND parentWindow, HMENU idOrHMenu,\r
+      HINSTANCE instance)\r
+{\r
+  WNDCLASS windowClass;\r
+  if (!::GetClassInfo(instance, className, &windowClass))\r
+  {\r
+    // windowClass.style          = CS_HREDRAW | CS_VREDRAW;\r
+    windowClass.style          = 0;\r
+\r
+    windowClass.lpfnWndProc    = WindowProcedure;\r
+    windowClass.cbClsExtra     = NULL;\r
+    windowClass.cbWndExtra     = NULL;\r
+    windowClass.hInstance      = instance;\r
+    windowClass.hIcon          = NULL;\r
+    windowClass.hCursor        = LoadCursor(NULL, IDC_ARROW);\r
+    windowClass.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);\r
+    windowClass.lpszMenuName   = NULL;\r
+    windowClass.lpszClassName  = className;\r
+    if (::RegisterClass(&windowClass) == 0)\r
+      return false;\r
+  }\r
+  return CWindow::CreateEx(exStyle, className, windowName,\r
+      style, x, y, width, height, parentWindow,\r
+      idOrHMenu, instance, this);\r
+}\r
+\r
+#ifndef _UNICODE\r
+\r
+bool CWindow2::CreateEx(DWORD exStyle, LPCWSTR className,\r
+      LPCWSTR windowName, DWORD style,\r
+      int x, int y, int width, int height,\r
+      HWND parentWindow, HMENU idOrHMenu,\r
+      HINSTANCE instance)\r
+{\r
+  bool needRegister;\r
+  if (g_IsNT)\r
+  {\r
+    WNDCLASSW windowClass;\r
+    needRegister = ::GetClassInfoW(instance, className, &windowClass) == 0;\r
+  }\r
+  else\r
+  {\r
+    WNDCLASSA windowClassA;\r
+    AString classNameA;\r
+    LPCSTR classNameP;\r
+    if (IS_INTRESOURCE(className))\r
+      classNameP = (LPCSTR)className;\r
+    else\r
+    {\r
+      classNameA = GetSystemString(className);\r
+      classNameP = classNameA;\r
+    }\r
+    needRegister = ::GetClassInfoA(instance, classNameP, &windowClassA) == 0;\r
+  }\r
+  if (needRegister)\r
+  {\r
+    WNDCLASSW windowClass;\r
+    // windowClass.style          = CS_HREDRAW | CS_VREDRAW;\r
+    windowClass.style          = 0;\r
+    windowClass.lpfnWndProc    = WindowProcedure;\r
+    windowClass.cbClsExtra     = NULL;\r
+    windowClass.cbWndExtra     = NULL;\r
+    windowClass.hInstance      = instance;\r
+    windowClass.hIcon          = NULL;\r
+    windowClass.hCursor        = LoadCursor(NULL, IDC_ARROW);\r
+    windowClass.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);\r
+    windowClass.lpszMenuName   = NULL;\r
+    windowClass.lpszClassName  = className;\r
+    if (MyRegisterClass(&windowClass) == 0)\r
+      return false;\r
+  }\r
+  return CWindow::CreateEx(exStyle, className, windowName,\r
+      style, x, y, width, height, parentWindow,\r
+      idOrHMenu, instance, this);\r
+\r
+}\r
+#endif\r
+\r
+LRESULT CWindow2::DefProc(UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+  #ifndef _UNICODE\r
+  if (g_IsNT)\r
+    return DefWindowProcW(_window, message, wParam, lParam);\r
+  else\r
+  #endif\r
+    return DefWindowProc(_window, message, wParam, lParam);\r
+}\r
+\r
+LRESULT CWindow2::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+  LRESULT result;\r
+  switch (message)\r
+  {\r
+    case WM_CREATE:\r
+      if (!OnCreate((CREATESTRUCT *)lParam))\r
+        return -1;\r
+      break;\r
+    case WM_COMMAND:\r
+      if (OnCommand(wParam, lParam, result))\r
+        return result;\r
+      break;\r
+    case WM_NOTIFY:\r
+      if (OnNotify((UINT)wParam, (LPNMHDR) lParam, result))\r
+        return result;\r
+      break;\r
+    case WM_DESTROY:\r
+      OnDestroy();\r
+      break;\r
+    case WM_CLOSE:\r
+      OnClose();\r
+      return 0;\r
+    case WM_SIZE:\r
+      if (OnSize(wParam, LOWORD(lParam), HIWORD(lParam)))\r
+        return 0;\r
+  }\r
+  return DefProc(message, wParam, lParam);\r
+}\r
+\r
+bool CWindow2::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT &result)\r
+{\r
+  return OnCommand(HIWORD(wParam), LOWORD(wParam), lParam, result);\r
+}\r
+\r
+bool CWindow2::OnCommand(int /* code */, int /* itemID */, LPARAM /* lParam */, LRESULT & /* result */)\r
+{\r
+  return false;\r
+  // return DefProc(message, wParam, lParam);\r
+  /*\r
+  if (code == BN_CLICKED)\r
+    return OnButtonClicked(itemID, (HWND)lParam);\r
+  */\r
+}\r
+\r
+/*\r
+bool CDialog::OnButtonClicked(int buttonID, HWND buttonHWND)\r
+{\r
+  switch(aButtonID)\r
+  {\r
+    case IDOK:\r
+      OnOK();\r
+      break;\r
+    case IDCANCEL:\r
+      OnCancel();\r
+      break;\r
+    case IDHELP:\r
+      OnHelp();\r
+      break;\r
+    default:\r
+      return false;\r
+  }\r
+  return true;\r
+}\r
+\r
+*/\r
+\r
+}}\r
diff --git a/CPP/Windows/Control/Window2.h b/CPP/Windows/Control/Window2.h
new file mode 100755 (executable)
index 0000000..b0aca17
--- /dev/null
@@ -0,0 +1,58 @@
+// Windows/Control/Window2.h\r
+\r
+#ifndef __WINDOWS_CONTROL_WINDOW2_H\r
+#define __WINDOWS_CONTROL_WINDOW2_H\r
+\r
+#include "Windows/Window.h"\r
+\r
+namespace NWindows {\r
+namespace NControl {\r
+\r
+class CWindow2: public CWindow\r
+{\r
+  LRESULT DefProc(UINT message, WPARAM wParam, LPARAM lParam);\r
+public:\r
+  CWindow2(HWND newWindow = NULL): CWindow(newWindow){};\r
+  virtual ~CWindow2() {};\r
+\r
+\r
+  bool CreateEx(DWORD exStyle, LPCTSTR className,\r
+      LPCTSTR windowName, DWORD style,\r
+      int x, int y, int width, int height,\r
+      HWND parentWindow, HMENU idOrHMenu,\r
+      HINSTANCE instance);\r
+\r
+  #ifndef _UNICODE\r
+  bool CreateEx(DWORD exStyle, LPCWSTR className,\r
+      LPCWSTR windowName, DWORD style,\r
+      int x, int y, int width, int height,\r
+      HWND parentWindow, HMENU idOrHMenu,\r
+      HINSTANCE instance);\r
+  #endif\r
+\r
+  virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam);\r
+  virtual bool OnCreate(CREATESTRUCT * /* createStruct */) { return true; }\r
+  // virtual LRESULT OnCommand(WPARAM wParam, LPARAM lParam);\r
+  virtual bool OnCommand(WPARAM wParam, LPARAM lParam, LRESULT &result);\r
+  virtual bool OnCommand(int code, int itemID, LPARAM lParam, LRESULT &result);\r
+  virtual bool OnSize(WPARAM /* wParam */, int /* xSize */, int /* ySize */) { return false; }\r
+  virtual bool OnNotify(UINT /* controlID */, LPNMHDR /* lParam */, LRESULT & /* result */) { return false; }\r
+  virtual void OnDestroy() { PostQuitMessage(0); }\r
+  virtual void OnClose() { Destroy(); }\r
+  /*\r
+  virtual LRESULT  OnHelp(LPHELPINFO helpInfo) { OnHelp(); };\r
+  virtual LRESULT  OnHelp() {};\r
+  virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);\r
+  virtual void OnOK() {};\r
+  virtual void OnCancel() {};\r
+  */\r
+\r
+  LONG_PTR SetMsgResult(LONG_PTR newLongPtr )\r
+    { return SetLongPtr(DWLP_MSGRESULT, newLongPtr); }\r
+  LONG_PTR GetMsgResult() const\r
+    { return GetLongPtr(DWLP_MSGRESULT); }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/DLL.cpp b/CPP/Windows/DLL.cpp
new file mode 100755 (executable)
index 0000000..6aaedb0
--- /dev/null
@@ -0,0 +1,110 @@
+// Windows/DLL.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#ifndef _UNICODE\r
+#include "../Common/StringConvert.h"\r
+#endif\r
+\r
+#include "DLL.h"\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+namespace NWindows {\r
+namespace NDLL {\r
+\r
+bool CLibrary::Free()\r
+{\r
+  if (_module == 0)\r
+    return true;\r
+  // MessageBox(0, TEXT(""), TEXT("Free"), 0);\r
+  // Sleep(5000);\r
+  if (!::FreeLibrary(_module))\r
+    return false;\r
+  _module = 0;\r
+  return true;\r
+}\r
+\r
+bool CLibrary::LoadOperations(HMODULE newModule)\r
+{\r
+  if (newModule == NULL)\r
+    return false;\r
+  if (!Free())\r
+    return false;\r
+  _module = newModule;\r
+  return true;\r
+}\r
+\r
+bool CLibrary::LoadEx(LPCTSTR fileName, DWORD flags)\r
+{\r
+  // MessageBox(0, fileName, TEXT("LoadEx"), 0);\r
+  return LoadOperations(::LoadLibraryEx(fileName, NULL, flags));\r
+}\r
+\r
+bool CLibrary::Load(LPCTSTR fileName)\r
+{\r
+  // MessageBox(0, fileName, TEXT("Load"), 0);\r
+  // Sleep(5000);\r
+  // OutputDebugString(fileName);\r
+  // OutputDebugString(TEXT("\n"));\r
+  return LoadOperations(::LoadLibrary(fileName));\r
+}\r
+\r
+#ifndef _UNICODE\r
+static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }\r
+CSysString GetSysPath(LPCWSTR sysPath)\r
+  { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); }\r
+\r
+bool CLibrary::LoadEx(LPCWSTR fileName, DWORD flags)\r
+{\r
+  if (g_IsNT)\r
+    return LoadOperations(::LoadLibraryExW(fileName, NULL, flags));\r
+  return LoadEx(GetSysPath(fileName), flags);\r
+}\r
+bool CLibrary::Load(LPCWSTR fileName)\r
+{\r
+  if (g_IsNT)\r
+    return LoadOperations(::LoadLibraryW(fileName));\r
+  return Load(GetSysPath(fileName));\r
+}\r
+#endif\r
+\r
+bool MyGetModuleFileName(HMODULE hModule, CSysString &result)\r
+{\r
+  result.Empty();\r
+  TCHAR fullPath[MAX_PATH + 2];\r
+  DWORD size = ::GetModuleFileName(hModule, fullPath, MAX_PATH + 1);\r
+  if (size <= MAX_PATH && size != 0)\r
+  {\r
+    result = fullPath;\r
+    return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool MyGetModuleFileName(HMODULE hModule, UString &result)\r
+{\r
+  result.Empty();\r
+  if (g_IsNT)\r
+  {\r
+    wchar_t fullPath[MAX_PATH + 2];\r
+    DWORD size = ::GetModuleFileNameW(hModule, fullPath, MAX_PATH + 1);\r
+    if (size <= MAX_PATH && size != 0)\r
+    {\r
+      result = fullPath;\r
+      return true;\r
+    }\r
+    return false;\r
+  }\r
+  CSysString resultSys;\r
+  if (!MyGetModuleFileName(hModule, resultSys))\r
+    return false;\r
+  result = MultiByteToUnicodeString(resultSys, GetCurrentCodePage());\r
+  return true;\r
+}\r
+#endif\r
+\r
+}}\r
diff --git a/CPP/Windows/DLL.h b/CPP/Windows/DLL.h
new file mode 100755 (executable)
index 0000000..7d02887
--- /dev/null
@@ -0,0 +1,59 @@
+// Windows/DLL.h\r
+\r
+#ifndef __WINDOWS_DLL_H\r
+#define __WINDOWS_DLL_H\r
+\r
+#include "../Common/MyString.h"\r
+\r
+namespace NWindows {\r
+namespace NDLL {\r
+\r
+#ifdef UNDER_CE\r
+#define My_GetProcAddress(module, proceName) GetProcAddressA(module, proceName)\r
+#else\r
+#define My_GetProcAddress(module, proceName) ::GetProcAddress(module, proceName)\r
+#endif\r
\r
+class CLibrary\r
+{\r
+  bool LoadOperations(HMODULE newModule);\r
+protected:\r
+  HMODULE _module;\r
+public:\r
+  CLibrary(): _module(NULL) {};\r
+  ~CLibrary() { Free(); }\r
+\r
+  operator HMODULE() const { return _module; }\r
+  HMODULE* operator&() { return &_module; }\r
+  bool IsLoaded() const { return (_module != NULL); };\r
+\r
+  void Attach(HMODULE m)\r
+  {\r
+    Free();\r
+    _module = m;\r
+  }\r
+  HMODULE Detach()\r
+  {\r
+    HMODULE m = _module;\r
+    _module = NULL;\r
+    return m;\r
+  }\r
+\r
+  bool Free();\r
+  bool LoadEx(LPCTSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE);\r
+  bool Load(LPCTSTR fileName);\r
+  #ifndef _UNICODE\r
+  bool LoadEx(LPCWSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE);\r
+  bool Load(LPCWSTR fileName);\r
+  #endif\r
+  FARPROC GetProc(LPCSTR procName) const { return My_GetProcAddress(_module, procName); }\r
+};\r
+\r
+bool MyGetModuleFileName(HMODULE hModule, CSysString &result);\r
+#ifndef _UNICODE\r
+bool MyGetModuleFileName(HMODULE hModule, UString &result);\r
+#endif\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Defs.h b/CPP/Windows/Defs.h
new file mode 100755 (executable)
index 0000000..f3d692f
--- /dev/null
@@ -0,0 +1,17 @@
+// Windows/Defs.h\r
+\r
+#ifndef __WINDOWS_DEFS_H\r
+#define __WINDOWS_DEFS_H\r
+\r
+#include "../Common/MyWindows.h"\r
+\r
+#ifdef _WIN32\r
+inline bool LRESULTToBool(LRESULT v) { return (v != FALSE); }\r
+inline bool BOOLToBool(BOOL v) { return (v != FALSE); }\r
+inline BOOL BoolToBOOL(bool v) { return (v ? TRUE: FALSE); }\r
+#endif\r
+\r
+inline VARIANT_BOOL BoolToVARIANT_BOOL(bool v) { return (v ? VARIANT_TRUE: VARIANT_FALSE); }\r
+inline bool VARIANT_BOOLToBool(VARIANT_BOOL v) { return (v != VARIANT_FALSE); }\r
+\r
+#endif\r
diff --git a/CPP/Windows/Error.cpp b/CPP/Windows/Error.cpp
new file mode 100755 (executable)
index 0000000..fcba1e6
--- /dev/null
@@ -0,0 +1,50 @@
+// Windows/Error.h\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/Error.h"\r
+#ifndef _UNICODE\r
+#include "Common/StringConvert.h"\r
+#endif\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+namespace NWindows {\r
+namespace NError {\r
+\r
+bool MyFormatMessage(DWORD messageID, CSysString &message)\r
+{\r
+  LPVOID msgBuf;\r
+  if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |\r
+      FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,\r
+      NULL,messageID, 0, (LPTSTR) &msgBuf,0, NULL) == 0)\r
+    return false;\r
+  message = (LPCTSTR)msgBuf;\r
+  ::LocalFree(msgBuf);\r
+  return true;\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool MyFormatMessage(DWORD messageID, UString &message)\r
+{\r
+  if (g_IsNT)\r
+  {\r
+    LPVOID msgBuf;\r
+    if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |\r
+        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,\r
+        NULL, messageID, 0, (LPWSTR) &msgBuf, 0, NULL) == 0)\r
+      return false;\r
+    message = (LPCWSTR)msgBuf;\r
+    ::LocalFree(msgBuf);\r
+    return true;\r
+  }\r
+  CSysString messageSys;\r
+  bool result = MyFormatMessage(messageID, messageSys);\r
+  message = GetUnicodeString(messageSys);\r
+  return result;\r
+}\r
+#endif\r
+\r
+}}\r
diff --git a/CPP/Windows/Error.h b/CPP/Windows/Error.h
new file mode 100755 (executable)
index 0000000..d916e8e
--- /dev/null
@@ -0,0 +1,33 @@
+// Windows/Error.h\r
+\r
+#ifndef __WINDOWS_ERROR_H\r
+#define __WINDOWS_ERROR_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+namespace NWindows {\r
+namespace NError {\r
+\r
+bool MyFormatMessage(DWORD messageID, CSysString &message);\r
+inline CSysString MyFormatMessage(DWORD messageID)\r
+{\r
+  CSysString message;\r
+  MyFormatMessage(messageID, message);\r
+  return message;\r
+}\r
+#ifdef _UNICODE\r
+inline UString MyFormatMessageW(DWORD messageID)\r
+  { return MyFormatMessage(messageID); }\r
+#else\r
+bool MyFormatMessage(DWORD messageID, UString &message);\r
+inline UString MyFormatMessageW(DWORD messageID)\r
+{\r
+  UString message;\r
+  MyFormatMessage(messageID, message);\r
+  return message;\r
+}\r
+#endif\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp
new file mode 100755 (executable)
index 0000000..daec1d3
--- /dev/null
@@ -0,0 +1,909 @@
+// Windows/FileDir.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#ifndef _UNICODE\r
+#include "../Common/StringConvert.h"\r
+#endif\r
+\r
+#include "FileDir.h"\r
+#include "FileFind.h"\r
+#include "FileName.h"\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+namespace NWindows {\r
+namespace NFile {\r
+\r
+#if defined(WIN_LONG_PATH) && defined(_UNICODE)\r
+#define WIN_LONG_PATH2\r
+#endif\r
+\r
+// SetCurrentDirectory doesn't support \\?\ prefix\r
+\r
+#ifdef WIN_LONG_PATH\r
+bool GetLongPathBase(LPCWSTR fileName, UString &res);\r
+bool GetLongPath(LPCWSTR fileName, UString &res);\r
+#endif\r
+\r
+namespace NDirectory {\r
+\r
+#ifndef _UNICODE\r
+static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }\r
+static UString GetUnicodePath(const CSysString &sysPath)\r
+  { return MultiByteToUnicodeString(sysPath, GetCurrentCodePage()); }\r
+static CSysString GetSysPath(LPCWSTR sysPath)\r
+  { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); }\r
+#endif\r
+\r
+#ifndef UNDER_CE\r
+\r
+bool MyGetWindowsDirectory(CSysString &path)\r
+{\r
+  UINT needLength = ::GetWindowsDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);\r
+  path.ReleaseBuffer();\r
+  return (needLength > 0 && needLength <= MAX_PATH);\r
+}\r
+\r
+bool MyGetSystemDirectory(CSysString &path)\r
+{\r
+  UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);\r
+  path.ReleaseBuffer();\r
+  return (needLength > 0 && needLength <= MAX_PATH);\r
+}\r
+\r
+#endif\r
+\r
+#ifndef _UNICODE\r
+bool MyGetWindowsDirectory(UString &path)\r
+{\r
+  if (g_IsNT)\r
+  {\r
+    UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);\r
+    path.ReleaseBuffer();\r
+    return (needLength > 0 && needLength <= MAX_PATH);\r
+  }\r
+  CSysString sysPath;\r
+  if (!MyGetWindowsDirectory(sysPath))\r
+    return false;\r
+  path = GetUnicodePath(sysPath);\r
+  return true;\r
+}\r
+\r
+bool MyGetSystemDirectory(UString &path)\r
+{\r
+  if (g_IsNT)\r
+  {\r
+    UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);\r
+    path.ReleaseBuffer();\r
+    return (needLength > 0 && needLength <= MAX_PATH);\r
+  }\r
+  CSysString sysPath;\r
+  if (!MyGetSystemDirectory(sysPath))\r
+    return false;\r
+  path = GetUnicodePath(sysPath);\r
+  return true;\r
+}\r
+#endif\r
+\r
+bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)\r
+{\r
+  #ifndef _UNICODE\r
+  if (!g_IsNT)\r
+  {\r
+    ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);\r
+    return false;\r
+  }\r
+  #endif\r
+  HANDLE hDir = ::CreateFileW(fileName, GENERIC_WRITE,\r
+      FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+      NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);\r
+  #ifdef WIN_LONG_PATH\r
+  if (hDir == INVALID_HANDLE_VALUE)\r
+  {\r
+    UString longPath;\r
+    if (GetLongPath(fileName, longPath))\r
+      hDir = ::CreateFileW(longPath, GENERIC_WRITE,\r
+        FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+        NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);\r
+  }\r
+  #endif\r
+\r
+  bool res = false;\r
+  if (hDir != INVALID_HANDLE_VALUE)\r
+  {\r
+    res = BOOLToBool(::SetFileTime(hDir, cTime, aTime, mTime));\r
+    ::CloseHandle(hDir);\r
+  }\r
+  return res;\r
+}\r
+\r
+bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes)\r
+{\r
+  if (::SetFileAttributes(fileName, fileAttributes))\r
+    return true;\r
+  #ifdef WIN_LONG_PATH2\r
+  UString longPath;\r
+  if (GetLongPath(fileName, longPath))\r
+    return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes));\r
+  #endif\r
+  return false;\r
+}\r
+\r
+bool MyRemoveDirectory(LPCTSTR pathName)\r
+{\r
+  if (::RemoveDirectory(pathName))\r
+    return true;\r
+  #ifdef WIN_LONG_PATH2\r
+  UString longPath;\r
+  if (GetLongPath(pathName, longPath))\r
+    return BOOLToBool(::RemoveDirectoryW(longPath));\r
+  #endif\r
+  return false;\r
+}\r
+\r
+#ifdef WIN_LONG_PATH\r
+bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2)\r
+{\r
+  if (!GetLongPathBase(s1, d1) || !GetLongPathBase(s2, d2))\r
+    return false;\r
+  if (d1.IsEmpty() && d2.IsEmpty()) return false;\r
+  if (d1.IsEmpty()) d1 = s1;\r
+  if (d2.IsEmpty()) d2 = s2;\r
+  return true;\r
+}\r
+#endif\r
+\r
+bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName)\r
+{\r
+  if (::MoveFile(existFileName, newFileName))\r
+    return true;\r
+  #ifdef WIN_LONG_PATH2\r
+  UString d1, d2;\r
+  if (GetLongPaths(existFileName, newFileName, d1, d2))\r
+    return BOOLToBool(::MoveFileW(d1, d2));\r
+  #endif\r
+  return false;\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes)\r
+{\r
+  if (!g_IsNT)\r
+    return MySetFileAttributes(GetSysPath(fileName), fileAttributes);\r
+  if (::SetFileAttributesW(fileName, fileAttributes))\r
+    return true;\r
+  #ifdef WIN_LONG_PATH\r
+  UString longPath;\r
+  if (GetLongPath(fileName, longPath))\r
+    return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes));\r
+  #endif\r
+  return false;\r
+}\r
+\r
+\r
+bool MyRemoveDirectory(LPCWSTR pathName)\r
+{\r
+  if (!g_IsNT)\r
+    return MyRemoveDirectory(GetSysPath(pathName));\r
+  if (::RemoveDirectoryW(pathName))\r
+    return true;\r
+  #ifdef WIN_LONG_PATH\r
+  UString longPath;\r
+  if (GetLongPath(pathName, longPath))\r
+    return BOOLToBool(::RemoveDirectoryW(longPath));\r
+  #endif\r
+  return false;\r
+}\r
+\r
+bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName)\r
+{\r
+  if (!g_IsNT)\r
+    return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName));\r
+  if (::MoveFileW(existFileName, newFileName))\r
+    return true;\r
+  #ifdef WIN_LONG_PATH\r
+  UString d1, d2;\r
+  if (GetLongPaths(existFileName, newFileName, d1, d2))\r
+    return BOOLToBool(::MoveFileW(d1, d2));\r
+  #endif\r
+  return false;\r
+}\r
+#endif\r
+\r
+bool MyCreateDirectory(LPCTSTR pathName)\r
+{\r
+  if (::CreateDirectory(pathName, NULL))\r
+    return true;\r
+  #ifdef WIN_LONG_PATH2\r
+  if (::GetLastError() != ERROR_ALREADY_EXISTS)\r
+  {\r
+    UString longPath;\r
+    if (GetLongPath(pathName, longPath))\r
+      return BOOLToBool(::CreateDirectoryW(longPath, NULL));\r
+  }\r
+  #endif\r
+  return false;\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool MyCreateDirectory(LPCWSTR pathName)\r
+{\r
+  if (!g_IsNT)\r
+    return MyCreateDirectory(GetSysPath(pathName));\r
+  if (::CreateDirectoryW(pathName, NULL))\r
+    return true;\r
+  #ifdef WIN_LONG_PATH\r
+  if (::GetLastError() != ERROR_ALREADY_EXISTS)\r
+  {\r
+    UString longPath;\r
+    if (GetLongPath(pathName, longPath))\r
+      return BOOLToBool(::CreateDirectoryW(longPath, NULL));\r
+  }\r
+  #endif\r
+  return false;\r
+}\r
+#endif\r
+\r
+/*\r
+bool CreateComplexDirectory(LPCTSTR pathName)\r
+{\r
+  NName::CParsedPath path;\r
+  path.ParsePath(pathName);\r
+  CSysString fullPath = path.Prefix;\r
+  DWORD errorCode = ERROR_SUCCESS;\r
+  for (int i = 0; i < path.PathParts.Size(); i++)\r
+  {\r
+    const CSysString &string = path.PathParts[i];\r
+    if (string.IsEmpty())\r
+    {\r
+      if (i != path.PathParts.Size() - 1)\r
+        return false;\r
+      return true;\r
+    }\r
+    fullPath += path.PathParts[i];\r
+    if (!MyCreateDirectory(fullPath))\r
+    {\r
+      DWORD errorCode = GetLastError();\r
+      if (errorCode != ERROR_ALREADY_EXISTS)\r
+        return false;\r
+    }\r
+    fullPath += NName::kDirDelimiter;\r
+  }\r
+  return true;\r
+}\r
+*/\r
+\r
+bool CreateComplexDirectory(LPCTSTR _aPathName)\r
+{\r
+  CSysString pathName = _aPathName;\r
+  int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));\r
+  if (pos > 0 && pos == pathName.Length() - 1)\r
+  {\r
+    if (pathName.Length() == 3 && pathName[1] == ':')\r
+      return true; // Disk folder;\r
+    pathName.Delete(pos);\r
+  }\r
+  CSysString pathName2 = pathName;\r
+  pos = pathName.Length();\r
+  for (;;)\r
+  {\r
+    if (MyCreateDirectory(pathName))\r
+      break;\r
+    if (::GetLastError() == ERROR_ALREADY_EXISTS)\r
+    {\r
+      NFind::CFileInfo fileInfo;\r
+      if (!fileInfo.Find(pathName)) // For network folders\r
+        return true;\r
+      if (!fileInfo.IsDir())\r
+        return false;\r
+      break;\r
+    }\r
+    pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));\r
+    if (pos < 0 || pos == 0)\r
+      return false;\r
+    if (pathName[pos - 1] == ':')\r
+      return false;\r
+    pathName = pathName.Left(pos);\r
+  }\r
+  pathName = pathName2;\r
+  while (pos < pathName.Length())\r
+  {\r
+    pos = pathName.Find(TEXT(CHAR_PATH_SEPARATOR), pos + 1);\r
+    if (pos < 0)\r
+      pos = pathName.Length();\r
+    if (!MyCreateDirectory(pathName.Left(pos)))\r
+      return false;\r
+  }\r
+  return true;\r
+}\r
+\r
+#ifndef _UNICODE\r
+\r
+bool CreateComplexDirectory(LPCWSTR _aPathName)\r
+{\r
+  UString pathName = _aPathName;\r
+  int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+  if (pos > 0 && pos == pathName.Length() - 1)\r
+  {\r
+    if (pathName.Length() == 3 && pathName[1] == L':')\r
+      return true; // Disk folder;\r
+    pathName.Delete(pos);\r
+  }\r
+  UString pathName2 = pathName;\r
+  pos = pathName.Length();\r
+  for (;;)\r
+  {\r
+    if (MyCreateDirectory(pathName))\r
+      break;\r
+    if (::GetLastError() == ERROR_ALREADY_EXISTS)\r
+    {\r
+      NFind::CFileInfoW fileInfo;\r
+      if (!fileInfo.Find(pathName)) // For network folders\r
+        return true;\r
+      if (!fileInfo.IsDir())\r
+        return false;\r
+      break;\r
+    }\r
+    pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+    if (pos < 0 || pos == 0)\r
+      return false;\r
+    if (pathName[pos - 1] == L':')\r
+      return false;\r
+    pathName = pathName.Left(pos);\r
+  }\r
+  pathName = pathName2;\r
+  while (pos < pathName.Length())\r
+  {\r
+    pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1);\r
+    if (pos < 0)\r
+      pos = pathName.Length();\r
+    if (!MyCreateDirectory(pathName.Left(pos)))\r
+      return false;\r
+  }\r
+  return true;\r
+}\r
+\r
+#endif\r
+\r
+bool DeleteFileAlways(LPCTSTR name)\r
+{\r
+  if (!MySetFileAttributes(name, 0))\r
+    return false;\r
+  if (::DeleteFile(name))\r
+    return true;\r
+  #ifdef WIN_LONG_PATH2\r
+  UString longPath;\r
+  if (GetLongPath(name, longPath))\r
+    return BOOLToBool(::DeleteFileW(longPath));\r
+  #endif\r
+  return false;\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool DeleteFileAlways(LPCWSTR name)\r
+{\r
+  if (!g_IsNT)\r
+    return DeleteFileAlways(GetSysPath(name));\r
+  if (!MySetFileAttributes(name, 0))\r
+    return false;\r
+  if (::DeleteFileW(name))\r
+    return true;\r
+  #ifdef WIN_LONG_PATH\r
+  UString longPath;\r
+  if (GetLongPath(name, longPath))\r
+    return BOOLToBool(::DeleteFileW(longPath));\r
+  #endif\r
+  return false;\r
+}\r
+#endif\r
+\r
+static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo)\r
+{\r
+  if (fileInfo.IsDir())\r
+    return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name);\r
+  return DeleteFileAlways(pathPrefix + fileInfo.Name);\r
+}\r
+\r
+bool RemoveDirectoryWithSubItems(const CSysString &path)\r
+{\r
+  NFind::CFileInfo fileInfo;\r
+  CSysString pathPrefix = path + NName::kDirDelimiter;\r
+  {\r
+    NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard));\r
+    while (enumerator.Next(fileInfo))\r
+      if (!RemoveDirectorySubItems2(pathPrefix, fileInfo))\r
+        return false;\r
+  }\r
+  if (!MySetFileAttributes(path, 0))\r
+    return false;\r
+  return MyRemoveDirectory(path);\r
+}\r
+\r
+#ifndef _UNICODE\r
+static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo)\r
+{\r
+  if (fileInfo.IsDir())\r
+    return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name);\r
+  return DeleteFileAlways(pathPrefix + fileInfo.Name);\r
+}\r
+bool RemoveDirectoryWithSubItems(const UString &path)\r
+{\r
+  NFind::CFileInfoW fileInfo;\r
+  UString pathPrefix = path + UString(NName::kDirDelimiter);\r
+  {\r
+    NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard));\r
+    while (enumerator.Next(fileInfo))\r
+      if (!RemoveDirectorySubItems2(pathPrefix, fileInfo))\r
+        return false;\r
+  }\r
+  if (!MySetFileAttributes(path, 0))\r
+    return false;\r
+  return MyRemoveDirectory(path);\r
+}\r
+#endif\r
+\r
+bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName)\r
+{\r
+  int index;\r
+  if (!MyGetFullPathName(fileName, resultName, index))\r
+    return false;\r
+  resultName = resultName.Left(index);\r
+  return true;\r
+}\r
+\r
+bool GetOnlyName(LPCTSTR fileName, CSysString &resultName)\r
+{\r
+  int index;\r
+  if (!MyGetFullPathName(fileName, resultName, index))\r
+    return false;\r
+  resultName = resultName.Mid(index);\r
+  return true;\r
+}\r
+\r
+#ifdef UNDER_CE\r
+bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath)\r
+{\r
+  resultPath = fileName;\r
+  return true;\r
+}\r
+\r
+bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex)\r
+{\r
+  resultPath = fileName;\r
+  // change it\r
+  fileNamePartStartIndex = resultPath.ReverseFind(WCHAR_PATH_SEPARATOR);\r
+  fileNamePartStartIndex++;\r
+  return true;\r
+}\r
+\r
+#else\r
+\r
+bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath)\r
+{\r
+  DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);\r
+  shortPath.ReleaseBuffer();\r
+  return (needLength > 0 && needLength < MAX_PATH);\r
+}\r
+\r
+#ifdef WIN_LONG_PATH\r
+\r
+static UString GetLastPart(LPCWSTR path)\r
+{\r
+  int i = (int)wcslen(path);\r
+  for (; i > 0; i--)\r
+  {\r
+    WCHAR c = path[i - 1];\r
+    if (c == WCHAR_PATH_SEPARATOR || c == '/')\r
+      break;\r
+  }\r
+  return path + i;\r
+}\r
+\r
+static void AddTrailingDots(LPCWSTR oldPath, UString &newPath)\r
+{\r
+  int len = (int)wcslen(oldPath);\r
+  int i;\r
+  for (i = len; i > 0 && oldPath[i - 1] == '.'; i--);\r
+  if (i == 0 || i == len)\r
+    return;\r
+  UString oldName = GetLastPart(oldPath);\r
+  UString newName = GetLastPart(newPath);\r
+  int nonDotsLen = oldName.Length() - (len - i);\r
+  if (nonDotsLen == 0 || newName.CompareNoCase(oldName.Left(nonDotsLen)) != 0)\r
+    return;\r
+  for (; i != len; i++)\r
+    newPath += '.';\r
+}\r
+\r
+#endif\r
+\r
+bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex)\r
+{\r
+  resultPath.Empty();\r
+  LPTSTR fileNamePointer = 0;\r
+  LPTSTR buffer = resultPath.GetBuffer(MAX_PATH);\r
+  DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1, buffer, &fileNamePointer);\r
+  resultPath.ReleaseBuffer();\r
+  if (needLength == 0)\r
+    return false;\r
+  if (needLength >= MAX_PATH)\r
+  {\r
+    #ifdef WIN_LONG_PATH2\r
+    needLength++;\r
+    buffer = resultPath.GetBuffer(needLength + 1);\r
+    DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer);\r
+    resultPath.ReleaseBuffer();\r
+    if (needLength2 == 0 || needLength2 > needLength)\r
+    #endif\r
+      return false;\r
+  }\r
+  if (fileNamePointer == 0)\r
+    fileNamePartStartIndex = lstrlen(fileName);\r
+  else\r
+    fileNamePartStartIndex = (int)(fileNamePointer - buffer);\r
+  #ifdef _UNICODE\r
+  #ifdef WIN_LONG_PATH\r
+  AddTrailingDots(fileName, resultPath);\r
+  #endif\r
+  #endif\r
+  return true;\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex)\r
+{\r
+  resultPath.Empty();\r
+  if (g_IsNT)\r
+  {\r
+    LPWSTR fileNamePointer = 0;\r
+    LPWSTR buffer = resultPath.GetBuffer(MAX_PATH);\r
+    DWORD needLength = ::GetFullPathNameW(fileName, MAX_PATH + 1, buffer, &fileNamePointer);\r
+    resultPath.ReleaseBuffer();\r
+    if (needLength == 0)\r
+      return false;\r
+    if (needLength >= MAX_PATH)\r
+    {\r
+      #ifdef WIN_LONG_PATH\r
+      needLength++;\r
+      buffer = resultPath.GetBuffer(needLength + 1);\r
+      DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer);\r
+      resultPath.ReleaseBuffer();\r
+      if (needLength2 == 0 || needLength2 > needLength)\r
+      #endif\r
+        return false;\r
+    }\r
+    if (fileNamePointer == 0)\r
+      fileNamePartStartIndex = MyStringLen(fileName);\r
+    else\r
+      fileNamePartStartIndex = (int)(fileNamePointer - buffer);\r
+    #ifdef WIN_LONG_PATH\r
+    AddTrailingDots(fileName, resultPath);\r
+    #endif\r
+  }\r
+  else\r
+  {\r
+    CSysString sysPath;\r
+    if (!MyGetFullPathName(GetSysPath(fileName), sysPath, fileNamePartStartIndex))\r
+      return false;\r
+    UString resultPath1 = GetUnicodePath(sysPath.Left(fileNamePartStartIndex));\r
+    UString resultPath2 = GetUnicodePath(sysPath.Mid(fileNamePartStartIndex));\r
+    fileNamePartStartIndex = resultPath1.Length();\r
+    resultPath = resultPath1 + resultPath2;\r
+  }\r
+  return true;\r
+}\r
+#endif\r
+\r
+\r
+bool MyGetFullPathName(LPCTSTR fileName, CSysString &path)\r
+{\r
+  int index;\r
+  return MyGetFullPathName(fileName, path, index);\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool MyGetFullPathName(LPCWSTR fileName, UString &path)\r
+{\r
+  int index;\r
+  return MyGetFullPathName(fileName, path, index);\r
+}\r
+#endif\r
+\r
+#ifndef _UNICODE\r
+bool GetOnlyName(LPCWSTR fileName, UString &resultName)\r
+{\r
+  int index;\r
+  if (!MyGetFullPathName(fileName, resultName, index))\r
+    return false;\r
+  resultName = resultName.Mid(index);\r
+  return true;\r
+}\r
+#endif\r
+\r
+#ifndef _UNICODE\r
+bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName)\r
+{\r
+  int index;\r
+  if (!MyGetFullPathName(fileName, resultName, index))\r
+    return false;\r
+  resultName = resultName.Left(index);\r
+  return true;\r
+}\r
+#endif\r
+\r
+bool MyGetCurrentDirectory(CSysString &path)\r
+{\r
+  DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));\r
+  path.ReleaseBuffer();\r
+  return (needLength > 0 && needLength <= MAX_PATH);\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool MySetCurrentDirectory(LPCWSTR path)\r
+{\r
+  if (g_IsNT)\r
+    return BOOLToBool(::SetCurrentDirectoryW(path));\r
+  return MySetCurrentDirectory(GetSysPath(path));\r
+}\r
+bool MyGetCurrentDirectory(UString &path)\r
+{\r
+  if (g_IsNT)\r
+  {\r
+    DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));\r
+    path.ReleaseBuffer();\r
+    return (needLength > 0 && needLength <= MAX_PATH);\r
+  }\r
+  CSysString sysPath;\r
+  if (!MyGetCurrentDirectory(sysPath))\r
+    return false;\r
+  path = GetUnicodePath(sysPath);\r
+  return true;\r
+}\r
+#endif\r
+\r
+bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension,\r
+  CSysString &resultPath, UINT32 &filePart)\r
+{\r
+  LPTSTR filePartPointer;\r
+  DWORD value = ::SearchPath(path, fileName, extension,\r
+    MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer);\r
+  filePart = (UINT32)(filePartPointer - (LPCTSTR)resultPath);\r
+  resultPath.ReleaseBuffer();\r
+  return (value > 0 && value <= MAX_PATH);\r
+}\r
+#endif\r
+\r
+#ifndef _UNICODE\r
+bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension,\r
+  UString &resultPath, UINT32 &filePart)\r
+{\r
+  if (g_IsNT)\r
+  {\r
+    LPWSTR filePartPointer = 0;\r
+    DWORD value = ::SearchPathW(path, fileName, extension,\r
+        MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer);\r
+    filePart = (UINT32)(filePartPointer - (LPCWSTR)resultPath);\r
+    resultPath.ReleaseBuffer();\r
+    return (value > 0 && value <= MAX_PATH);\r
+  }\r
+  \r
+  CSysString sysPath;\r
+  if (!MySearchPath(\r
+      path != 0 ? (LPCTSTR)GetSysPath(path): 0,\r
+      fileName != 0 ? (LPCTSTR)GetSysPath(fileName): 0,\r
+      extension != 0 ? (LPCTSTR)GetSysPath(extension): 0,\r
+      sysPath, filePart))\r
+    return false;\r
+  UString resultPath1 = GetUnicodePath(sysPath.Left(filePart));\r
+  UString resultPath2 = GetUnicodePath(sysPath.Mid(filePart));\r
+  filePart = resultPath1.Length();\r
+  resultPath = resultPath1 + resultPath2;\r
+  return true;\r
+}\r
+#endif\r
+\r
+bool MyGetTempPath(CSysString &path)\r
+{\r
+  DWORD needLength = ::GetTempPath(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));\r
+  path.ReleaseBuffer();\r
+  return (needLength > 0 && needLength <= MAX_PATH);\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool MyGetTempPath(UString &path)\r
+{\r
+  path.Empty();\r
+  if (g_IsNT)\r
+  {\r
+    DWORD needLength = ::GetTempPathW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));\r
+    path.ReleaseBuffer();\r
+    return (needLength > 0 && needLength <= MAX_PATH);\r
+  }\r
+  CSysString sysPath;\r
+  if (!MyGetTempPath(sysPath))\r
+    return false;\r
+  path = GetUnicodePath(sysPath);\r
+  return true;\r
+}\r
+#endif\r
+\r
+UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &path)\r
+{\r
+  UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH + 1));\r
+  path.ReleaseBuffer();\r
+  return number;\r
+}\r
+\r
+#ifndef _UNICODE\r
+UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &path)\r
+{\r
+  if (g_IsNT)\r
+  {\r
+    UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH));\r
+    path.ReleaseBuffer();\r
+    return number;\r
+  }\r
+  CSysString sysPath;\r
+  UINT number = MyGetTempFileName(\r
+      dirPath ? (LPCTSTR)GetSysPath(dirPath): 0,\r
+      prefix ? (LPCTSTR)GetSysPath(prefix): 0,\r
+      sysPath);\r
+  path = GetUnicodePath(sysPath);\r
+  return number;\r
+}\r
+#endif\r
+\r
+UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath)\r
+{\r
+  Remove();\r
+  UINT number = MyGetTempFileName(dirPath, prefix, resultPath);\r
+  if (number != 0)\r
+  {\r
+    _fileName = resultPath;\r
+    _mustBeDeleted = true;\r
+  }\r
+  return number;\r
+}\r
+\r
+bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath)\r
+{\r
+  CSysString tempPath;\r
+  if (!MyGetTempPath(tempPath))\r
+    return false;\r
+  if (Create(tempPath, prefix, resultPath) != 0)\r
+    return true;\r
+  #ifdef UNDER_CE\r
+  return false;\r
+  #else\r
+  if (!MyGetWindowsDirectory(tempPath))\r
+    return false;\r
+  return (Create(tempPath, prefix, resultPath) != 0);\r
+  #endif\r
+}\r
+\r
+bool CTempFile::Remove()\r
+{\r
+  if (!_mustBeDeleted)\r
+    return true;\r
+  _mustBeDeleted = !DeleteFileAlways(_fileName);\r
+  return !_mustBeDeleted;\r
+}\r
+\r
+#ifndef _UNICODE\r
+\r
+UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath)\r
+{\r
+  Remove();\r
+  UINT number = MyGetTempFileName(dirPath, prefix, resultPath);\r
+  if (number != 0)\r
+  {\r
+    _fileName = resultPath;\r
+    _mustBeDeleted = true;\r
+  }\r
+  return number;\r
+}\r
+\r
+bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath)\r
+{\r
+  UString tempPath;\r
+  if (!MyGetTempPath(tempPath))\r
+    return false;\r
+  if (Create(tempPath, prefix, resultPath) != 0)\r
+    return true;\r
+  if (!MyGetWindowsDirectory(tempPath))\r
+    return false;\r
+  return (Create(tempPath, prefix, resultPath) != 0);\r
+}\r
+\r
+bool CTempFileW::Remove()\r
+{\r
+  if (!_mustBeDeleted)\r
+    return true;\r
+  _mustBeDeleted = !DeleteFileAlways(_fileName);\r
+  return !_mustBeDeleted;\r
+}\r
+\r
+#endif\r
+\r
+bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName)\r
+{\r
+  /*\r
+  CSysString prefix = tempPath + prefixChars;\r
+  CRandom random;\r
+  random.Init();\r
+  */\r
+  for (;;)\r
+  {\r
+    {\r
+      CTempFile tempFile;\r
+      if (!tempFile.Create(prefix, dirName))\r
+        return false;\r
+      if (!tempFile.Remove())\r
+        return false;\r
+    }\r
+    /*\r
+    UINT32 randomNumber = random.Generate();\r
+    TCHAR randomNumberString[32];\r
+    _stprintf(randomNumberString, _T("%04X"), randomNumber);\r
+    dirName = prefix + randomNumberString;\r
+    */\r
+    if (NFind::DoesFileOrDirExist(dirName))\r
+      continue;\r
+    if (MyCreateDirectory(dirName))\r
+      return true;\r
+    if (::GetLastError() != ERROR_ALREADY_EXISTS)\r
+      return false;\r
+  }\r
+}\r
+\r
+bool CTempDirectory::Create(LPCTSTR prefix)\r
+{\r
+  Remove();\r
+  return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir));\r
+}\r
+\r
+#ifndef _UNICODE\r
+\r
+bool CreateTempDirectory(LPCWSTR prefix, UString &dirName)\r
+{\r
+  /*\r
+  CSysString prefix = tempPath + prefixChars;\r
+  CRandom random;\r
+  random.Init();\r
+  */\r
+  for (;;)\r
+  {\r
+    {\r
+      CTempFileW tempFile;\r
+      if (!tempFile.Create(prefix, dirName))\r
+        return false;\r
+      if (!tempFile.Remove())\r
+        return false;\r
+    }\r
+    /*\r
+    UINT32 randomNumber = random.Generate();\r
+    TCHAR randomNumberString[32];\r
+    _stprintf(randomNumberString, _T("%04X"), randomNumber);\r
+    dirName = prefix + randomNumberString;\r
+    */\r
+    if (NFind::DoesFileOrDirExist(dirName))\r
+      continue;\r
+    if (MyCreateDirectory(dirName))\r
+      return true;\r
+    if (::GetLastError() != ERROR_ALREADY_EXISTS)\r
+      return false;\r
+  }\r
+}\r
+\r
+bool CTempDirectoryW::Create(LPCWSTR prefix)\r
+{\r
+  Remove();\r
+  return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir));\r
+}\r
+\r
+#endif\r
+\r
+}}}\r
diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h
new file mode 100755 (executable)
index 0000000..2c15071
--- /dev/null
@@ -0,0 +1,177 @@
+// Windows/FileDir.h\r
+\r
+#ifndef __WINDOWS_FILEDIR_H\r
+#define __WINDOWS_FILEDIR_H\r
+\r
+#include "../Common/MyString.h"\r
+#include "Defs.h"\r
+\r
+namespace NWindows {\r
+namespace NFile {\r
+namespace NDirectory {\r
+\r
+#ifdef WIN_LONG_PATH\r
+bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2);\r
+#endif\r
+\r
+bool MyGetWindowsDirectory(CSysString &path);\r
+bool MyGetSystemDirectory(CSysString &path);\r
+#ifndef _UNICODE\r
+bool MyGetWindowsDirectory(UString &path);\r
+bool MyGetSystemDirectory(UString &path);\r
+#endif\r
+\r
+bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime);\r
+\r
+bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes);\r
+bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName);\r
+bool MyRemoveDirectory(LPCTSTR pathName);\r
+bool MyCreateDirectory(LPCTSTR pathName);\r
+bool CreateComplexDirectory(LPCTSTR pathName);\r
+bool DeleteFileAlways(LPCTSTR name);\r
+bool RemoveDirectoryWithSubItems(const CSysString &path);\r
+\r
+#ifndef _UNICODE\r
+bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes);\r
+bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName);\r
+bool MyRemoveDirectory(LPCWSTR pathName);\r
+bool MyCreateDirectory(LPCWSTR pathName);\r
+bool CreateComplexDirectory(LPCWSTR pathName);\r
+bool DeleteFileAlways(LPCWSTR name);\r
+bool RemoveDirectoryWithSubItems(const UString &path);\r
+#endif\r
+\r
+bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName);\r
+bool GetOnlyName(LPCTSTR fileName, CSysString &resultName);\r
+#ifdef UNDER_CE\r
+bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath);\r
+bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex);\r
+#else\r
+bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath);\r
+\r
+bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex);\r
+bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath);\r
+#ifndef _UNICODE\r
+bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath,\r
+    int &fileNamePartStartIndex);\r
+bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath);\r
+bool GetOnlyName(LPCWSTR fileName, UString &resultName);\r
+bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName);\r
+#endif\r
+\r
+inline bool MySetCurrentDirectory(LPCTSTR path)\r
+  { return BOOLToBool(::SetCurrentDirectory(path)); }\r
+bool MyGetCurrentDirectory(CSysString &resultPath);\r
+#ifndef _UNICODE\r
+bool MySetCurrentDirectory(LPCWSTR path);\r
+bool MyGetCurrentDirectory(UString &resultPath);\r
+#endif\r
+\r
+bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart);\r
+#ifndef _UNICODE\r
+bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart);\r
+#endif\r
+\r
+inline bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath)\r
+{\r
+  UINT32 value;\r
+  return MySearchPath(path, fileName, extension, resultPath, value);\r
+}\r
+\r
+#ifndef _UNICODE\r
+inline bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath)\r
+{\r
+  UINT32 value;\r
+  return MySearchPath(path, fileName, extension, resultPath, value);\r
+}\r
+#endif\r
+\r
+#endif\r
+\r
+bool MyGetTempPath(CSysString &resultPath);\r
+#ifndef _UNICODE\r
+bool MyGetTempPath(UString &resultPath);\r
+#endif\r
+\r
+UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath);\r
+#ifndef _UNICODE\r
+UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath);\r
+#endif\r
+\r
+class CTempFile\r
+{\r
+  bool _mustBeDeleted;\r
+  CSysString _fileName;\r
+public:\r
+  CTempFile(): _mustBeDeleted(false) {}\r
+  ~CTempFile() { Remove(); }\r
+  void DisableDeleting() { _mustBeDeleted = false; }\r
+  UINT Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath);\r
+  bool Create(LPCTSTR prefix, CSysString &resultPath);\r
+  bool Remove();\r
+};\r
+\r
+#ifdef _UNICODE\r
+typedef CTempFile CTempFileW;\r
+#else\r
+class CTempFileW\r
+{\r
+  bool _mustBeDeleted;\r
+  UString _fileName;\r
+public:\r
+  CTempFileW(): _mustBeDeleted(false) {}\r
+  ~CTempFileW() { Remove(); }\r
+  void DisableDeleting() { _mustBeDeleted = false; }\r
+  UINT Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath);\r
+  bool Create(LPCWSTR prefix, UString &resultPath);\r
+  bool Remove();\r
+};\r
+#endif\r
+\r
+bool CreateTempDirectory(LPCTSTR prefixChars, CSysString &dirName);\r
+\r
+class CTempDirectory\r
+{\r
+  bool _mustBeDeleted;\r
+  CSysString _tempDir;\r
+public:\r
+  const CSysString &GetPath() const { return _tempDir; }\r
+  CTempDirectory(): _mustBeDeleted(false) {}\r
+  ~CTempDirectory() { Remove();  }\r
+  bool Create(LPCTSTR prefix) ;\r
+  bool Remove()\r
+  {\r
+    if (!_mustBeDeleted)\r
+      return true;\r
+    _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir);\r
+    return (!_mustBeDeleted);\r
+  }\r
+  void DisableDeleting() { _mustBeDeleted = false; }\r
+};\r
+\r
+#ifdef _UNICODE\r
+typedef CTempDirectory CTempDirectoryW;\r
+#else\r
+class CTempDirectoryW\r
+{\r
+  bool _mustBeDeleted;\r
+  UString _tempDir;\r
+public:\r
+  const UString &GetPath() const { return _tempDir; }\r
+  CTempDirectoryW(): _mustBeDeleted(false) {}\r
+  ~CTempDirectoryW() { Remove();  }\r
+  bool Create(LPCWSTR prefix) ;\r
+  bool Remove()\r
+  {\r
+    if (!_mustBeDeleted)\r
+      return true;\r
+    _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir);\r
+    return (!_mustBeDeleted);\r
+  }\r
+  void DisableDeleting() { _mustBeDeleted = false; }\r
+};\r
+#endif\r
+\r
+}}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp
new file mode 100755 (executable)
index 0000000..99fb706
--- /dev/null
@@ -0,0 +1,462 @@
+// Windows/FileFind.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "FileFind.h"\r
+#include "FileIO.h"\r
+#ifndef _UNICODE\r
+#include "../Common/StringConvert.h"\r
+#endif\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+namespace NWindows {\r
+namespace NFile {\r
+\r
+#ifdef SUPPORT_DEVICE_FILE\r
+bool IsDeviceName(LPCTSTR n);\r
+#ifndef _UNICODE\r
+bool IsDeviceName(LPCWSTR n);\r
+#endif\r
+#endif\r
+\r
+#if defined(WIN_LONG_PATH) && defined(_UNICODE)\r
+#define WIN_LONG_PATH2\r
+#endif\r
+\r
+bool GetLongPath(LPCWSTR fileName, UString &res);\r
+\r
+namespace NFind {\r
+\r
+static const TCHAR kDot = TEXT('.');\r
+\r
+bool CFileInfo::IsDots() const\r
+{\r
+  if (!IsDir() || Name.IsEmpty())\r
+    return false;\r
+  if (Name[0] != kDot)\r
+    return false;\r
+  return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2);\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool CFileInfoW::IsDots() const\r
+{\r
+  if (!IsDir() || Name.IsEmpty())\r
+    return false;\r
+  if (Name[0] != kDot)\r
+    return false;\r
+  return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2);\r
+}\r
+#endif\r
+\r
+#define WIN_FD_TO_MY_FI(fi, fd) \\r
+  fi.Attrib = fd.dwFileAttributes; \\r
+  fi.CTime = fd.ftCreationTime; \\r
+  fi.ATime = fd.ftLastAccessTime; \\r
+  fi.MTime = fd.ftLastWriteTime; \\r
+  fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; \\r
+  fi.IsDevice = false;\r
+\r
+  /*\r
+  #ifdef UNDER_CE\r
+  fi.ObjectID = fd.dwOID;\r
+  #else\r
+  fi.ReparseTag = fd.dwReserved0;\r
+  #endif\r
+  */\r
+\r
+static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi)\r
+{\r
+  WIN_FD_TO_MY_FI(fi, fd);\r
+  fi.Name = fd.cFileName;\r
+}\r
+\r
+#ifndef _UNICODE\r
+\r
+static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }\r
+\r
+static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfoW &fi)\r
+{\r
+  WIN_FD_TO_MY_FI(fi, fd);\r
+  fi.Name = fd.cFileName;\r
+}\r
+\r
+static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfoW &fi)\r
+{\r
+  WIN_FD_TO_MY_FI(fi, fd);\r
+  fi.Name = GetUnicodeString(fd.cFileName, GetCurrentCodePage());\r
+}\r
+#endif\r
+  \r
+////////////////////////////////\r
+// CFindFile\r
+\r
+bool CFindFile::Close()\r
+{\r
+  if (_handle == INVALID_HANDLE_VALUE)\r
+    return true;\r
+  if (!::FindClose(_handle))\r
+    return false;\r
+  _handle = INVALID_HANDLE_VALUE;\r
+  return true;\r
+}\r
+\r
+          \r
+bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fi)\r
+{\r
+  if (!Close())\r
+    return false;\r
+  WIN32_FIND_DATA fd;\r
+  _handle = ::FindFirstFile(wildcard, &fd);\r
+  #ifdef WIN_LONG_PATH2\r
+  if (_handle == INVALID_HANDLE_VALUE)\r
+  {\r
+    UString longPath;\r
+    if (GetLongPath(wildcard, longPath))\r
+      _handle = ::FindFirstFileW(longPath, &fd);\r
+  }\r
+  #endif\r
+  if (_handle == INVALID_HANDLE_VALUE)\r
+    return false;\r
+  ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi);\r
+  return true;\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fi)\r
+{\r
+  if (!Close())\r
+    return false;\r
+  if (g_IsNT)\r
+  {\r
+    WIN32_FIND_DATAW fd;\r
+    _handle = ::FindFirstFileW(wildcard, &fd);\r
+    #ifdef WIN_LONG_PATH\r
+    if (_handle == INVALID_HANDLE_VALUE)\r
+    {\r
+      UString longPath;\r
+      if (GetLongPath(wildcard, longPath))\r
+        _handle = ::FindFirstFileW(longPath, &fd);\r
+    }\r
+    #endif\r
+    if (_handle != INVALID_HANDLE_VALUE)\r
+      ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi);\r
+  }\r
+  else\r
+  {\r
+    WIN32_FIND_DATAA fd;\r
+    _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard,\r
+        GetCurrentCodePage()), &fd);\r
+    if (_handle != INVALID_HANDLE_VALUE)\r
+      ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi);\r
+  }\r
+  return (_handle != INVALID_HANDLE_VALUE);\r
+}\r
+#endif\r
+\r
+bool CFindFile::FindNext(CFileInfo &fi)\r
+{\r
+  WIN32_FIND_DATA fd;\r
+  bool result = BOOLToBool(::FindNextFile(_handle, &fd));\r
+  if (result)\r
+    ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi);\r
+  return result;\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool CFindFile::FindNext(CFileInfoW &fi)\r
+{\r
+  if (g_IsNT)\r
+  {\r
+    WIN32_FIND_DATAW fd;\r
+    if (!::FindNextFileW(_handle, &fd))\r
+      return false;\r
+    ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi);\r
+  }\r
+  else\r
+  {\r
+    WIN32_FIND_DATAA fd;\r
+    if (!::FindNextFileA(_handle, &fd))\r
+      return false;\r
+    ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi);\r
+  }\r
+  return true;\r
+}\r
+#endif\r
+\r
+#define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0;\r
+\r
+void CFileInfoBase::Clear()\r
+{\r
+  Size = 0;\r
+  MY_CLEAR_FILETIME(CTime);\r
+  MY_CLEAR_FILETIME(ATime);\r
+  MY_CLEAR_FILETIME(MTime);\r
+  Attrib = 0;\r
+}\r
+  \r
+bool CFileInfo::Find(LPCTSTR wildcard)\r
+{\r
+  #ifdef SUPPORT_DEVICE_FILE\r
+  if (IsDeviceName(wildcard))\r
+  {\r
+    Clear();\r
+    IsDevice = true;\r
+    NIO::CInFile inFile;\r
+    if (!inFile.Open(wildcard))\r
+      return false;\r
+    Name = wildcard + 4;\r
+    if (inFile.LengthDefined)\r
+      Size = inFile.Length;\r
+    return true;\r
+  }\r
+  #endif\r
+  CFindFile finder;\r
+  return finder.FindFirst(wildcard, *this);\r
+}\r
+\r
+\r
+#ifndef _UNICODE\r
+bool CFileInfoW::Find(LPCWSTR wildcard)\r
+{\r
+  #ifdef SUPPORT_DEVICE_FILE\r
+  if (IsDeviceName(wildcard))\r
+  {\r
+    Clear();\r
+    IsDevice = true;\r
+    NIO::CInFile inFile;\r
+    if (!inFile.Open(wildcard))\r
+      return false;\r
+    Name = wildcard + 4;\r
+    if (inFile.LengthDefined)\r
+      Size = inFile.Length;\r
+    return true;\r
+  }\r
+  #endif\r
+  CFindFile finder;\r
+  return finder.FindFirst(wildcard, *this);\r
+}\r
+#endif\r
+\r
+bool DoesFileExist(LPCTSTR name)\r
+{\r
+  CFileInfo fi;\r
+  return fi.Find(name) && !fi.IsDir();\r
+}\r
+\r
+bool DoesDirExist(LPCTSTR name)\r
+{\r
+  CFileInfo fi;\r
+  return fi.Find(name) && fi.IsDir();\r
+}\r
+\r
+bool DoesFileOrDirExist(LPCTSTR name)\r
+{\r
+  CFileInfo fi;\r
+  return fi.Find(name);\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool DoesFileExist(LPCWSTR name)\r
+{\r
+  CFileInfoW fi;\r
+  return fi.Find(name) && !fi.IsDir();\r
+}\r
+\r
+bool DoesDirExist(LPCWSTR name)\r
+{\r
+  CFileInfoW fi;\r
+  return fi.Find(name) && fi.IsDir();\r
+}\r
+bool DoesFileOrDirExist(LPCWSTR name)\r
+{\r
+  CFileInfoW fi;\r
+  return fi.Find(name);\r
+}\r
+#endif\r
+\r
+/////////////////////////////////////\r
+// CEnumerator\r
+\r
+bool CEnumerator::NextAny(CFileInfo &fi)\r
+{\r
+  if (_findFile.IsHandleAllocated())\r
+    return _findFile.FindNext(fi);\r
+  else\r
+    return _findFile.FindFirst(_wildcard, fi);\r
+}\r
+\r
+bool CEnumerator::Next(CFileInfo &fi)\r
+{\r
+  for (;;)\r
+  {\r
+    if (!NextAny(fi))\r
+      return false;\r
+    if (!fi.IsDots())\r
+      return true;\r
+  }\r
+}\r
+\r
+bool CEnumerator::Next(CFileInfo &fi, bool &found)\r
+{\r
+  if (Next(fi))\r
+  {\r
+    found = true;\r
+    return true;\r
+  }\r
+  found = false;\r
+  return (::GetLastError() == ERROR_NO_MORE_FILES);\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool CEnumeratorW::NextAny(CFileInfoW &fi)\r
+{\r
+  if (_findFile.IsHandleAllocated())\r
+    return _findFile.FindNext(fi);\r
+  else\r
+    return _findFile.FindFirst(_wildcard, fi);\r
+}\r
+\r
+bool CEnumeratorW::Next(CFileInfoW &fi)\r
+{\r
+  for (;;)\r
+  {\r
+    if (!NextAny(fi))\r
+      return false;\r
+    if (!fi.IsDots())\r
+      return true;\r
+  }\r
+}\r
+\r
+bool CEnumeratorW::Next(CFileInfoW &fi, bool &found)\r
+{\r
+  if (Next(fi))\r
+  {\r
+    found = true;\r
+    return true;\r
+  }\r
+  found = false;\r
+  return (::GetLastError() == ERROR_NO_MORE_FILES);\r
+}\r
+\r
+#endif\r
+\r
+////////////////////////////////\r
+// CFindChangeNotification\r
+// FindFirstChangeNotification can return 0. MSDN doesn't tell about it.\r
+\r
+bool CFindChangeNotification::Close()\r
+{\r
+  if (!IsHandleAllocated())\r
+    return true;\r
+  if (!::FindCloseChangeNotification(_handle))\r
+    return false;\r
+  _handle = INVALID_HANDLE_VALUE;\r
+  return true;\r
+}\r
+           \r
+HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter)\r
+{\r
+  _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter);\r
+  #ifdef WIN_LONG_PATH2\r
+  if (!IsHandleAllocated())\r
+  {\r
+    UString longPath;\r
+    if (GetLongPath(pathName, longPath))\r
+      _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);\r
+  }\r
+  #endif\r
+  return _handle;\r
+}\r
+\r
+#ifndef _UNICODE\r
+HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter)\r
+{\r
+  if (!g_IsNT)\r
+    return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter);\r
+  _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter);\r
+  #ifdef WIN_LONG_PATH\r
+  if (!IsHandleAllocated())\r
+  {\r
+    UString longPath;\r
+    if (GetLongPath(pathName, longPath))\r
+      _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);\r
+  }\r
+  #endif\r
+  return _handle;\r
+}\r
+#endif\r
+\r
+#ifndef UNDER_CE\r
+bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings)\r
+{\r
+  driveStrings.Clear();\r
+  UINT32 size = GetLogicalDriveStrings(0, NULL);\r
+  if (size == 0)\r
+    return false;\r
+  CSysString buffer;\r
+  UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size));\r
+  if (newSize == 0)\r
+    return false;\r
+  if (newSize > size)\r
+    return false;\r
+  CSysString string;\r
+  for (UINT32 i = 0; i < newSize; i++)\r
+  {\r
+    TCHAR c = buffer[i];\r
+    if (c == TEXT('\0'))\r
+    {\r
+      driveStrings.Add(string);\r
+      string.Empty();\r
+    }\r
+    else\r
+      string += c;\r
+  }\r
+  if (!string.IsEmpty())\r
+    return false;\r
+  return true;\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool MyGetLogicalDriveStrings(UStringVector &driveStrings)\r
+{\r
+  driveStrings.Clear();\r
+  if (g_IsNT)\r
+  {\r
+    UINT32 size = GetLogicalDriveStringsW(0, NULL);\r
+    if (size == 0)\r
+      return false;\r
+    UString buffer;\r
+    UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size));\r
+    if (newSize == 0)\r
+      return false;\r
+    if (newSize > size)\r
+      return false;\r
+    UString string;\r
+    for (UINT32 i = 0; i < newSize; i++)\r
+    {\r
+      WCHAR c = buffer[i];\r
+      if (c == L'\0')\r
+      {\r
+        driveStrings.Add(string);\r
+        string.Empty();\r
+      }\r
+      else\r
+        string += c;\r
+    }\r
+    return string.IsEmpty();\r
+  }\r
+  CSysStringVector driveStringsA;\r
+  bool res = MyGetLogicalDriveStrings(driveStringsA);\r
+  for (int i = 0; i < driveStringsA.Size(); i++)\r
+    driveStrings.Add(GetUnicodeString(driveStringsA[i]));\r
+  return res;\r
+}\r
+#endif\r
+\r
+#endif\r
+\r
+}}}\r
diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h
new file mode 100755 (executable)
index 0000000..5affd83
--- /dev/null
@@ -0,0 +1,161 @@
+// Windows/FileFind.h\r
+\r
+#ifndef __WINDOWS_FILEFIND_H\r
+#define __WINDOWS_FILEFIND_H\r
+\r
+#include "../Common/MyString.h"\r
+#include "../Common/Types.h"\r
+#include "Defs.h"\r
+#include "FileName.h"\r
+\r
+namespace NWindows {\r
+namespace NFile {\r
+namespace NFind {\r
+\r
+namespace NAttributes\r
+{\r
+  inline bool IsReadOnly(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_READONLY) != 0; }\r
+  inline bool IsHidden(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_HIDDEN) != 0; }\r
+  inline bool IsSystem(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_SYSTEM) != 0; }\r
+  inline bool IsDir(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; }\r
+  inline bool IsArchived(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ARCHIVE) != 0; }\r
+  inline bool IsCompressed(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_COMPRESSED) != 0; }\r
+  inline bool IsEncrypted(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ENCRYPTED) != 0; }\r
+}\r
+\r
+class CFileInfoBase\r
+{\r
+  bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); }\r
+protected:\r
+  void Clear();\r
+public:\r
+  UInt64 Size;\r
+  FILETIME CTime;\r
+  FILETIME ATime;\r
+  FILETIME MTime;\r
+  DWORD Attrib;\r
+  bool IsDevice;\r
+\r
+  /*\r
+  #ifdef UNDER_CE\r
+  DWORD ObjectID;\r
+  #else\r
+  UINT32 ReparseTag;\r
+  #endif\r
+  */\r
+\r
+  bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); }\r
+  bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); }\r
+  bool IsDir() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); }\r
+  bool IsEncrypted() const { return MatchesMask(FILE_ATTRIBUTE_ENCRYPTED); }\r
+  bool IsHidden() const { return MatchesMask(FILE_ATTRIBUTE_HIDDEN); }\r
+  bool IsNormal() const { return MatchesMask(FILE_ATTRIBUTE_NORMAL); }\r
+  bool IsOffline() const { return MatchesMask(FILE_ATTRIBUTE_OFFLINE); }\r
+  bool IsReadOnly() const { return MatchesMask(FILE_ATTRIBUTE_READONLY); }\r
+  bool HasReparsePoint() const { return MatchesMask(FILE_ATTRIBUTE_REPARSE_POINT); }\r
+  bool IsSparse() const { return MatchesMask(FILE_ATTRIBUTE_SPARSE_FILE); }\r
+  bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); }\r
+  bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); }\r
+};\r
+\r
+struct CFileInfo: public CFileInfoBase\r
+{\r
+  CSysString Name;\r
+\r
+  bool IsDots() const;\r
+  bool Find(LPCTSTR wildcard);\r
+};\r
+\r
+#ifdef _UNICODE\r
+typedef CFileInfo CFileInfoW;\r
+#else\r
+struct CFileInfoW: public CFileInfoBase\r
+{\r
+  UString Name;\r
+\r
+  bool IsDots() const;\r
+  bool Find(LPCWSTR wildcard);\r
+};\r
+#endif\r
+\r
+class CFindFile\r
+{\r
+  friend class CEnumerator;\r
+  HANDLE _handle;\r
+public:\r
+  bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; }\r
+  CFindFile(): _handle(INVALID_HANDLE_VALUE) {}\r
+  ~CFindFile() {  Close(); }\r
+  bool FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo);\r
+  bool FindNext(CFileInfo &fileInfo);\r
+  #ifndef _UNICODE\r
+  bool FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo);\r
+  bool FindNext(CFileInfoW &fileInfo);\r
+  #endif\r
+  bool Close();\r
+};\r
+\r
+bool DoesFileExist(LPCTSTR name);\r
+bool DoesDirExist(LPCTSTR name);\r
+bool DoesFileOrDirExist(LPCTSTR name);\r
+#ifndef _UNICODE\r
+bool DoesFileExist(LPCWSTR name);\r
+bool DoesDirExist(LPCWSTR name);\r
+bool DoesFileOrDirExist(LPCWSTR name);\r
+#endif\r
+\r
+class CEnumerator\r
+{\r
+  CFindFile _findFile;\r
+  CSysString _wildcard;\r
+  bool NextAny(CFileInfo &fileInfo);\r
+public:\r
+  CEnumerator(): _wildcard(NName::kAnyStringWildcard) {}\r
+  CEnumerator(const CSysString &wildcard): _wildcard(wildcard) {}\r
+  bool Next(CFileInfo &fileInfo);\r
+  bool Next(CFileInfo &fileInfo, bool &found);\r
+};\r
+\r
+#ifdef _UNICODE\r
+typedef CEnumerator CEnumeratorW;\r
+#else\r
+class CEnumeratorW\r
+{\r
+  CFindFile _findFile;\r
+  UString _wildcard;\r
+  bool NextAny(CFileInfoW &fileInfo);\r
+public:\r
+  CEnumeratorW(): _wildcard(NName::kAnyStringWildcard) {}\r
+  CEnumeratorW(const UString &wildcard): _wildcard(wildcard) {}\r
+  bool Next(CFileInfoW &fileInfo);\r
+  bool Next(CFileInfoW &fileInfo, bool &found);\r
+};\r
+#endif\r
+\r
+class CFindChangeNotification\r
+{\r
+  HANDLE _handle;\r
+public:\r
+  operator HANDLE () { return _handle; }\r
+  bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE && _handle != 0; }\r
+  CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {}\r
+  ~CFindChangeNotification() { Close(); }\r
+  bool Close();\r
+  HANDLE FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter);\r
+  #ifndef _UNICODE\r
+  HANDLE FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter);\r
+  #endif\r
+  bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); }\r
+};\r
+\r
+#ifndef UNDER_CE\r
+bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings);\r
+#ifndef _UNICODE\r
+bool MyGetLogicalDriveStrings(UStringVector &driveStrings);\r
+#endif\r
+#endif\r
+\r
+}}}\r
+\r
+#endif\r
+\r
diff --git a/CPP/Windows/FileIO.cpp b/CPP/Windows/FileIO.cpp
new file mode 100755 (executable)
index 0000000..a1a1bcc
--- /dev/null
@@ -0,0 +1,434 @@
+// Windows/FileIO.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "FileIO.h"\r
+\r
+#if defined(WIN_LONG_PATH) || defined(SUPPORT_DEVICE_FILE)\r
+#include "../Common/MyString.h"\r
+#endif\r
+#ifndef _UNICODE\r
+#include "../Common/StringConvert.h"\r
+#endif\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+namespace NWindows {\r
+namespace NFile {\r
+\r
+#ifdef SUPPORT_DEVICE_FILE\r
+bool IsDeviceName(LPCTSTR n)\r
+{\r
+  #ifdef UNDER_CE\r
+  int len = (int)MyStringLen(n);\r
+  if (len < 5 || len > 5 || memcmp(n, TEXT("DSK"), 3 * sizeof(TCHAR)) != 0)\r
+    return false;\r
+  if (n[4] != ':')\r
+    return false;\r
+  // for reading use SG_REQ sg; if (DeviceIoControl(dsk, IOCTL_DISK_READ));\r
+  #else\r
+  if (n[0] != '\\' || n[1] != '\\' || n[2] != '.' ||  n[3] != '\\')\r
+    return false;\r
+  int len = (int)MyStringLen(n);\r
+  if (len == 6 && n[5] == ':')\r
+    return true;\r
+  if (len < 18 || len > 22 || memcmp(n + 4, TEXT("PhysicalDrive"), 13 * sizeof(TCHAR)) != 0)\r
+    return false;\r
+  for (int i = 17; i < len; i++)\r
+    if (n[i] < '0' || n[i] > '9')\r
+      return false;\r
+  #endif\r
+  return true;\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool IsDeviceName(LPCWSTR n)\r
+{\r
+  if (n[0] != '\\' || n[1] != '\\' || n[2] != '.' ||  n[3] != '\\')\r
+    return false;\r
+  int len = (int)wcslen(n);\r
+  if (len == 6 && n[5] == ':')\r
+    return true;\r
+  if (len < 18 || len > 22 || wcsncmp(n + 4, L"PhysicalDrive", 13) != 0)\r
+    return false;\r
+  for (int i = 17; i < len; i++)\r
+    if (n[i] < '0' || n[i] > '9')\r
+      return false;\r
+  return true;\r
+}\r
+#endif\r
+#endif\r
+\r
+#if defined(WIN_LONG_PATH) && defined(_UNICODE)\r
+#define WIN_LONG_PATH2\r
+#endif\r
+\r
+#ifdef WIN_LONG_PATH\r
+bool GetLongPathBase(LPCWSTR s, UString &res)\r
+{\r
+  res.Empty();\r
+  int len = MyStringLen(s);\r
+  wchar_t c = s[0];\r
+  if (len < 1 || c == L'\\' || c == L'.' && (len == 1 || len == 2 && s[1] == L'.'))\r
+    return true;\r
+  UString curDir;\r
+  bool isAbs = false;\r
+  if (len > 3)\r
+    isAbs = (s[1] == L':' && s[2] == L'\\' && (c >= L'a' && c <= L'z' || c >= L'A' && c <= L'Z'));\r
+\r
+  if (!isAbs)\r
+    {\r
+      DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(MAX_PATH + 1));\r
+      curDir.ReleaseBuffer();\r
+      if (needLength == 0 || needLength > MAX_PATH)\r
+        return false;\r
+      if (curDir[curDir.Length() - 1] != L'\\')\r
+        curDir += L'\\';\r
+    }\r
+  res = UString(L"\\\\?\\") + curDir + s;\r
+  return true;\r
+}\r
+\r
+bool GetLongPath(LPCWSTR path, UString &longPath)\r
+{\r
+  if (GetLongPathBase(path, longPath))\r
+    return !longPath.IsEmpty();\r
+  return false;\r
+}\r
+#endif\r
+\r
+namespace NIO {\r
+\r
+CFileBase::~CFileBase() { Close(); }\r
+\r
+bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess,\r
+    DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)\r
+{\r
+  if (!Close())\r
+    return false;\r
+  _handle = ::CreateFile(fileName, desiredAccess, shareMode,\r
+      (LPSECURITY_ATTRIBUTES)NULL, creationDisposition,\r
+      flagsAndAttributes, (HANDLE)NULL);\r
+  #ifdef WIN_LONG_PATH2\r
+  if (_handle == INVALID_HANDLE_VALUE)\r
+  {\r
+    UString longPath;\r
+    if (GetLongPath(fileName, longPath))\r
+      _handle = ::CreateFileW(longPath, desiredAccess, shareMode,\r
+        (LPSECURITY_ATTRIBUTES)NULL, creationDisposition,\r
+        flagsAndAttributes, (HANDLE)NULL);\r
+  }\r
+  #endif\r
+  #ifdef SUPPORT_DEVICE_FILE\r
+  IsDeviceFile = false;\r
+  #endif\r
+  return (_handle != INVALID_HANDLE_VALUE);\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess,\r
+    DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)\r
+{\r
+  if (!g_IsNT)\r
+    return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP),\r
+      desiredAccess, shareMode, creationDisposition, flagsAndAttributes);\r
+  if (!Close())\r
+    return false;\r
+  _handle = ::CreateFileW(fileName, desiredAccess, shareMode,\r
+    (LPSECURITY_ATTRIBUTES)NULL, creationDisposition,\r
+    flagsAndAttributes, (HANDLE)NULL);\r
+  #ifdef WIN_LONG_PATH\r
+  if (_handle == INVALID_HANDLE_VALUE)\r
+  {\r
+    UString longPath;\r
+    if (GetLongPath(fileName, longPath))\r
+      _handle = ::CreateFileW(longPath, desiredAccess, shareMode,\r
+        (LPSECURITY_ATTRIBUTES)NULL, creationDisposition,\r
+        flagsAndAttributes, (HANDLE)NULL);\r
+  }\r
+  #endif\r
+  #ifdef SUPPORT_DEVICE_FILE\r
+  IsDeviceFile = false;\r
+  #endif\r
+  return (_handle != INVALID_HANDLE_VALUE);\r
+}\r
+#endif\r
+\r
+bool CFileBase::Close()\r
+{\r
+  if (_handle == INVALID_HANDLE_VALUE)\r
+    return true;\r
+  if (!::CloseHandle(_handle))\r
+    return false;\r
+  _handle = INVALID_HANDLE_VALUE;\r
+  return true;\r
+}\r
+\r
+bool CFileBase::GetPosition(UInt64 &position) const\r
+{\r
+  return Seek(0, FILE_CURRENT, position);\r
+}\r
+\r
+bool CFileBase::GetLength(UInt64 &length) const\r
+{\r
+  #ifdef SUPPORT_DEVICE_FILE\r
+  if (IsDeviceFile && LengthDefined)\r
+  {\r
+    length = Length;\r
+    return true;\r
+  }\r
+  #endif\r
+\r
+  DWORD sizeHigh;\r
+  DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh);\r
+  if (sizeLow == 0xFFFFFFFF)\r
+    if (::GetLastError() != NO_ERROR)\r
+      return false;\r
+  length = (((UInt64)sizeHigh) << 32) + sizeLow;\r
+  return true;\r
+}\r
+\r
+bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const\r
+{\r
+  #ifdef SUPPORT_DEVICE_FILE\r
+  if (IsDeviceFile && LengthDefined && moveMethod == FILE_END)\r
+  {\r
+    distanceToMove += Length;\r
+    moveMethod = FILE_BEGIN;\r
+  }\r
+  #endif\r
+\r
+  LARGE_INTEGER value;\r
+  value.QuadPart = distanceToMove;\r
+  value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod);\r
+  if (value.LowPart == 0xFFFFFFFF)\r
+    if (::GetLastError() != NO_ERROR)\r
+      return false;\r
+  newPosition = value.QuadPart;\r
+  return true;\r
+}\r
+\r
+bool CFileBase::Seek(UInt64 position, UInt64 &newPosition)\r
+{\r
+  return Seek(position, FILE_BEGIN, newPosition);\r
+}\r
+\r
+bool CFileBase::SeekToBegin()\r
+{\r
+  UInt64 newPosition;\r
+  return Seek(0, newPosition);\r
+}\r
+\r
+bool CFileBase::SeekToEnd(UInt64 &newPosition)\r
+{\r
+  return Seek(0, FILE_END, newPosition);\r
+}\r
+\r
+bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const\r
+{\r
+  BY_HANDLE_FILE_INFORMATION winFileInfo;\r
+  if (!::GetFileInformationByHandle(_handle, &winFileInfo))\r
+    return false;\r
+  fileInfo.Attrib = winFileInfo.dwFileAttributes;\r
+  fileInfo.CTime = winFileInfo.ftCreationTime;\r
+  fileInfo.ATime = winFileInfo.ftLastAccessTime;\r
+  fileInfo.MTime = winFileInfo.ftLastWriteTime;\r
+  fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes;\r
+  fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) +  winFileInfo.nFileSizeLow;\r
+  fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks;\r
+  fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow;\r
+  return true;\r
+}\r
+\r
+/////////////////////////\r
+// CInFile\r
+\r
+#ifdef SUPPORT_DEVICE_FILE\r
+void CInFile::GetDeviceLength()\r
+{\r
+  if (_handle != INVALID_HANDLE_VALUE && IsDeviceFile)\r
+  {\r
+    #ifdef UNDER_CE\r
+    LengthDefined = true;\r
+    Length = 128 << 20;\r
+\r
+    #else\r
+    PARTITION_INFORMATION partInfo;\r
+    LengthDefined = true;\r
+    Length = 0;\r
+\r
+    if (GetPartitionInfo(&partInfo))\r
+      Length = partInfo.PartitionLength.QuadPart;\r
+    else\r
+    {\r
+      DISK_GEOMETRY geom;\r
+      if (!GetGeometry(&geom))\r
+        if (!GetCdRomGeometry(&geom))\r
+          LengthDefined = false;\r
+      if (LengthDefined)\r
+        Length = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector;\r
+    }\r
+    // SeekToBegin();\r
+    #endif\r
+  }\r
+}\r
+\r
+// ((desiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE)) == 0 &&\r
+\r
+#define MY_DEVICE_EXTRA_CODE \\r
+  IsDeviceFile = IsDeviceName(fileName); \\r
+  GetDeviceLength();\r
+#else\r
+#define MY_DEVICE_EXTRA_CODE\r
+#endif\r
+\r
+bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)\r
+{\r
+  bool res = Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes);\r
+  MY_DEVICE_EXTRA_CODE\r
+  return res;\r
+}\r
+\r
+bool CInFile::OpenShared(LPCTSTR fileName, bool shareForWrite)\r
+{ return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); }\r
+\r
+bool CInFile::Open(LPCTSTR fileName)\r
+  { return OpenShared(fileName, false); }\r
+\r
+#ifndef _UNICODE\r
+bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)\r
+{\r
+  bool res = Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes);\r
+  MY_DEVICE_EXTRA_CODE\r
+  return res;\r
+}\r
+\r
+bool CInFile::OpenShared(LPCWSTR fileName, bool shareForWrite)\r
+{ return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); }\r
+\r
+bool CInFile::Open(LPCWSTR fileName)\r
+  { return OpenShared(fileName, false); }\r
+#endif\r
+\r
+// ReadFile and WriteFile functions in Windows have BUG:\r
+// If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)\r
+// from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES\r
+// (Insufficient system resources exist to complete the requested service).\r
+\r
+// Probably in some version of Windows there are problems with other sizes:\r
+// for 32 MB (maybe also for 16 MB).\r
+// And message can be "Network connection was lost"\r
+\r
+static UInt32 kChunkSizeMax = (1 << 22);\r
+\r
+bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize)\r
+{\r
+  DWORD processedLoc = 0;\r
+  bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL));\r
+  processedSize = (UInt32)processedLoc;\r
+  return res;\r
+}\r
+\r
+bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize)\r
+{\r
+  if (size > kChunkSizeMax)\r
+    size = kChunkSizeMax;\r
+  return Read1(data, size, processedSize);\r
+}\r
+\r
+bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize)\r
+{\r
+  processedSize = 0;\r
+  do\r
+  {\r
+    UInt32 processedLoc = 0;\r
+    bool res = ReadPart(data, size, processedLoc);\r
+    processedSize += processedLoc;\r
+    if (!res)\r
+      return false;\r
+    if (processedLoc == 0)\r
+      return true;\r
+    data = (void *)((unsigned char *)data + processedLoc);\r
+    size -= processedLoc;\r
+  }\r
+  while (size > 0);\r
+  return true;\r
+}\r
+\r
+/////////////////////////\r
+// COutFile\r
+\r
+bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)\r
+  { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); }\r
+\r
+static inline DWORD GetCreationDisposition(bool createAlways)\r
+  { return createAlways? CREATE_ALWAYS: CREATE_NEW; }\r
+\r
+bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition)\r
+  { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); }\r
+\r
+bool COutFile::Create(LPCTSTR fileName, bool createAlways)\r
+  { return Open(fileName, GetCreationDisposition(createAlways)); }\r
+\r
+#ifndef _UNICODE\r
+\r
+bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)\r
+  { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); }\r
+\r
+bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition)\r
+  { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); }\r
+\r
+bool COutFile::Create(LPCWSTR fileName, bool createAlways)\r
+  { return Open(fileName, GetCreationDisposition(createAlways)); }\r
+\r
+#endif\r
+\r
+bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)\r
+  { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); }\r
+\r
+bool COutFile::SetMTime(const FILETIME *mTime) {  return SetTime(NULL, NULL, mTime); }\r
+\r
+bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize)\r
+{\r
+  if (size > kChunkSizeMax)\r
+    size = kChunkSizeMax;\r
+  DWORD processedLoc = 0;\r
+  bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL));\r
+  processedSize = (UInt32)processedLoc;\r
+  return res;\r
+}\r
+\r
+bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize)\r
+{\r
+  processedSize = 0;\r
+  do\r
+  {\r
+    UInt32 processedLoc = 0;\r
+    bool res = WritePart(data, size, processedLoc);\r
+    processedSize += processedLoc;\r
+    if (!res)\r
+      return false;\r
+    if (processedLoc == 0)\r
+      return true;\r
+    data = (const void *)((const unsigned char *)data + processedLoc);\r
+    size -= processedLoc;\r
+  }\r
+  while (size > 0);\r
+  return true;\r
+}\r
+\r
+bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); }\r
+\r
+bool COutFile::SetLength(UInt64 length)\r
+{\r
+  UInt64 newPosition;\r
+  if (!Seek(length, newPosition))\r
+    return false;\r
+  if (newPosition != length)\r
+    return false;\r
+  return SetEndOfFile();\r
+}\r
+\r
+}}}\r
diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h
new file mode 100755 (executable)
index 0000000..6f14817
--- /dev/null
@@ -0,0 +1,136 @@
+// Windows/FileIO.h\r
+\r
+#ifndef __WINDOWS_FILEIO_H\r
+#define __WINDOWS_FILEIO_H\r
+\r
+#include "../Common/Types.h"\r
+\r
+#include "Defs.h"\r
+\r
+namespace NWindows {\r
+namespace NFile {\r
+namespace NIO {\r
+\r
+struct CByHandleFileInfo\r
+{\r
+  DWORD Attrib;\r
+  FILETIME CTime;\r
+  FILETIME ATime;\r
+  FILETIME MTime;\r
+  DWORD VolumeSerialNumber;\r
+  UInt64 Size;\r
+  DWORD NumberOfLinks;\r
+  UInt64 FileIndex;\r
+};\r
+\r
+class CFileBase\r
+{\r
+protected:\r
+  HANDLE _handle;\r
+  \r
+  bool Create(LPCTSTR fileName, DWORD desiredAccess,\r
+      DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);\r
+  #ifndef _UNICODE\r
+  bool Create(LPCWSTR fileName, DWORD desiredAccess,\r
+      DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);\r
+  #endif\r
+\r
+public:\r
+  #ifdef SUPPORT_DEVICE_FILE\r
+  bool IsDeviceFile;\r
+  bool LengthDefined;\r
+  UInt64 Length;\r
+  #endif\r
+\r
+  CFileBase(): _handle(INVALID_HANDLE_VALUE) {};\r
+  ~CFileBase();\r
+\r
+  bool Close();\r
+\r
+  bool GetPosition(UInt64 &position) const;\r
+  bool GetLength(UInt64 &length) const;\r
+\r
+  bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const;\r
+  bool Seek(UInt64 position, UInt64 &newPosition);\r
+  bool SeekToBegin();\r
+  bool SeekToEnd(UInt64 &newPosition);\r
+  \r
+  bool GetFileInformation(CByHandleFileInfo &fileInfo) const;\r
+};\r
+\r
+#define IOCTL_CDROM_BASE  FILE_DEVICE_CD_ROM\r
+#define IOCTL_CDROM_GET_DRIVE_GEOMETRY  CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS)\r
+#define IOCTL_CDROM_MEDIA_REMOVAL  CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS)\r
+\r
+class CInFile: public CFileBase\r
+{\r
+  #ifdef SUPPORT_DEVICE_FILE\r
+  bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, DWORD inSize,\r
+      LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped) const\r
+  {\r
+    return BOOLToBool(::DeviceIoControl(_handle, controlCode, inBuffer, inSize,\r
+        outBuffer, outSize, bytesReturned, overlapped));\r
+  }\r
+\r
+  bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer,\r
+      DWORD inSize, LPVOID outBuffer, DWORD outSize) const\r
+  {\r
+    DWORD ret;\r
+    return DeviceIoControl(controlCode, inBuffer, inSize, outBuffer, outSize, &ret, 0);\r
+  }\r
+\r
+  bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const\r
+    { return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize); }\r
+\r
+  #ifndef UNDER_CE\r
+  bool GetGeometry(DISK_GEOMETRY *res) const\r
+    { return DeviceIoControlOut(IOCTL_DISK_GET_DRIVE_GEOMETRY, res, sizeof(*res)); }\r
+\r
+  bool GetCdRomGeometry(DISK_GEOMETRY *res) const\r
+    { return DeviceIoControlOut(IOCTL_CDROM_GET_DRIVE_GEOMETRY, res, sizeof(*res)); }\r
+  \r
+  bool GetPartitionInfo(PARTITION_INFORMATION *res)\r
+    { return DeviceIoControlOut(IOCTL_DISK_GET_PARTITION_INFO, LPVOID(res), sizeof(*res)); }\r
+  #endif\r
+\r
+  void GetDeviceLength();\r
+  #endif\r
+\r
+public:\r
+  bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);\r
+  bool OpenShared(LPCTSTR fileName, bool shareForWrite);\r
+  bool Open(LPCTSTR fileName);\r
+  #ifndef _UNICODE\r
+  bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);\r
+  bool OpenShared(LPCWSTR fileName, bool shareForWrite);\r
+  bool Open(LPCWSTR fileName);\r
+  #endif\r
+  bool Read1(void *data, UInt32 size, UInt32 &processedSize);\r
+  bool ReadPart(void *data, UInt32 size, UInt32 &processedSize);\r
+  bool Read(void *data, UInt32 size, UInt32 &processedSize);\r
+};\r
+\r
+class COutFile: public CFileBase\r
+{\r
+public:\r
+  bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);\r
+  bool Open(LPCTSTR fileName, DWORD creationDisposition);\r
+  bool Create(LPCTSTR fileName, bool createAlways);\r
+\r
+  #ifndef _UNICODE\r
+  bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);\r
+  bool Open(LPCWSTR fileName, DWORD creationDisposition);\r
+  bool Create(LPCWSTR fileName, bool createAlways);\r
+  #endif\r
+\r
+  bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime);\r
+  bool SetMTime(const FILETIME *mTime);\r
+  bool WritePart(const void *data, UInt32 size, UInt32 &processedSize);\r
+  bool Write(const void *data, UInt32 size, UInt32 &processedSize);\r
+  bool SetEndOfFile();\r
+  bool SetLength(UInt64 length);\r
+};\r
+\r
+}}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/FileMapping.cpp b/CPP/Windows/FileMapping.cpp
new file mode 100755 (executable)
index 0000000..857e70d
--- /dev/null
@@ -0,0 +1,12 @@
+// Windows/FileMapping.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/FileMapping.h"\r
+\r
+namespace NWindows {\r
+namespace NFile {\r
+namespace NMapping {\r
+\r
+\r
+}}}\r
diff --git a/CPP/Windows/FileMapping.h b/CPP/Windows/FileMapping.h
new file mode 100755 (executable)
index 0000000..138a175
--- /dev/null
@@ -0,0 +1,62 @@
+// Windows/FileMapping.h\r
+\r
+#ifndef __WINDOWS_FILEMAPPING_H\r
+#define __WINDOWS_FILEMAPPING_H\r
+\r
+#include "Common/Types.h"\r
+\r
+#include "Handle.h"\r
+\r
+namespace NWindows {\r
+\r
+class CFileMapping: public CHandle\r
+{\r
+public:\r
+  WRes Create(DWORD protect, UInt64 maxSize, LPCTSTR name)\r
+  {\r
+    _handle = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, protect, (DWORD)(maxSize >> 32), (DWORD)maxSize, name);\r
+    return ::GetLastError();\r
+  }\r
+\r
+  WRes Open(DWORD desiredAccess, LPCTSTR name)\r
+  {\r
+    #ifdef UNDER_CE\r
+    WRes res = Create(PAGE_READONLY, 0, name);\r
+    if (res == ERROR_ALREADY_EXISTS)\r
+      return 0;\r
+    Close();\r
+    if (res == 0)\r
+      res = ERROR_FILE_NOT_FOUND;\r
+    return res;\r
+    #else\r
+    _handle = ::OpenFileMapping(desiredAccess, FALSE, name);\r
+    if (_handle != 0)\r
+      return 0;\r
+    return ::GetLastError();\r
+    #endif\r
+  }\r
+\r
+  LPVOID Map(DWORD desiredAccess, UInt64 fileOffset, SIZE_T numberOfBytesToMap)\r
+  {\r
+    return ::MapViewOfFile(_handle, desiredAccess, (DWORD)(fileOffset >> 32), (DWORD)fileOffset, numberOfBytesToMap);\r
+  }\r
+\r
+  #ifndef UNDER_CE\r
+  LPVOID Map(DWORD desiredAccess, UInt64 fileOffset, SIZE_T numberOfBytesToMap, LPVOID baseAddress)\r
+  {\r
+    return ::MapViewOfFileEx(_handle, desiredAccess, (DWORD)(fileOffset >> 32), (DWORD)fileOffset, numberOfBytesToMap, baseAddress);\r
+  }\r
+  #endif\r
+};\r
+\r
+class CFileUnmapper\r
+{\r
+  const void *_data;\r
+public:\r
+  CFileUnmapper(const void *data) : _data(data) {}\r
+  ~CFileUnmapper() { ::UnmapViewOfFile(_data); }\r
+};\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/Windows/FileName.cpp b/CPP/Windows/FileName.cpp
new file mode 100755 (executable)
index 0000000..4e55a53
--- /dev/null
@@ -0,0 +1,50 @@
+// Windows/FileName.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/FileName.h"\r
+#include "Common/Wildcard.h"\r
+\r
+namespace NWindows {\r
+namespace NFile {\r
+namespace NName {\r
+\r
+void NormalizeDirPathPrefix(CSysString &dirPath)\r
+{\r
+  if (dirPath.IsEmpty())\r
+    return;\r
+  if (dirPath.ReverseFind(kDirDelimiter) != dirPath.Length() - 1)\r
+    dirPath += kDirDelimiter;\r
+}\r
+\r
+#ifndef _UNICODE\r
+void NormalizeDirPathPrefix(UString &dirPath)\r
+{\r
+  if (dirPath.IsEmpty())\r
+    return;\r
+  if (dirPath.ReverseFind(wchar_t(kDirDelimiter)) != dirPath.Length() - 1)\r
+    dirPath += wchar_t(kDirDelimiter);\r
+}\r
+#endif\r
+\r
+const wchar_t kExtensionDelimiter = L'.';\r
+\r
+void SplitNameToPureNameAndExtension(const UString &fullName,\r
+    UString &pureName, UString &extensionDelimiter, UString &extension)\r
+{\r
+  int index = fullName.ReverseFind(kExtensionDelimiter);\r
+  if (index < 0)\r
+  {\r
+    pureName = fullName;\r
+    extensionDelimiter.Empty();\r
+    extension.Empty();\r
+  }\r
+  else\r
+  {\r
+    pureName = fullName.Left(index);\r
+    extensionDelimiter = kExtensionDelimiter;\r
+    extension = fullName.Mid(index + 1);\r
+  }\r
+}\r
+\r
+}}}\r
diff --git a/CPP/Windows/FileName.h b/CPP/Windows/FileName.h
new file mode 100755 (executable)
index 0000000..b980236
--- /dev/null
@@ -0,0 +1,27 @@
+// Windows/FileName.h\r
+\r
+#ifndef __WINDOWS_FILENAME_H\r
+#define __WINDOWS_FILENAME_H\r
+\r
+#include "../../C/Types.h"\r
+\r
+#include "../Common/MyString.h"\r
+\r
+namespace NWindows {\r
+namespace NFile {\r
+namespace NName {\r
+\r
+const TCHAR kDirDelimiter = CHAR_PATH_SEPARATOR;\r
+const TCHAR kAnyStringWildcard = '*';\r
+\r
+void NormalizeDirPathPrefix(CSysString &dirPath); // ensures that it ended with '\\'\r
+#ifndef _UNICODE\r
+void NormalizeDirPathPrefix(UString &dirPath); // ensures that it ended with '\\'\r
+#endif\r
+\r
+void SplitNameToPureNameAndExtension(const UString &fullName,\r
+    UString &pureName, UString &extensionDelimiter, UString &extension);\r
+\r
+}}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/FileSystem.cpp b/CPP/Windows/FileSystem.cpp
new file mode 100755 (executable)
index 0000000..5e2f324
--- /dev/null
@@ -0,0 +1,126 @@
+// Windows/FileSystem.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "FileSystem.h"\r
+#include "Defs.h"\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+namespace NWindows {\r
+namespace NFile {\r
+namespace NSystem {\r
+\r
+bool MyGetVolumeInformation(\r
+    LPCTSTR rootPathName,\r
+    CSysString &volumeName,\r
+    LPDWORD volumeSerialNumber,\r
+    LPDWORD maximumComponentLength,\r
+    LPDWORD fileSystemFlags,\r
+    CSysString &fileSystemName)\r
+{\r
+  bool result = BOOLToBool(GetVolumeInformation(\r
+      rootPathName,\r
+      volumeName.GetBuffer(MAX_PATH), MAX_PATH,\r
+      volumeSerialNumber,\r
+      maximumComponentLength,\r
+      fileSystemFlags,\r
+      fileSystemName.GetBuffer(MAX_PATH), MAX_PATH));\r
+  volumeName.ReleaseBuffer();\r
+  fileSystemName.ReleaseBuffer();\r
+  return result;\r
+}\r
+\r
+\r
+#ifndef _UNICODE\r
+bool MyGetVolumeInformation(\r
+    LPCWSTR rootPathName,\r
+    UString &volumeName,\r
+    LPDWORD volumeSerialNumber,\r
+    LPDWORD maximumComponentLength,\r
+    LPDWORD fileSystemFlags,\r
+    UString &fileSystemName)\r
+{\r
+  if (g_IsNT)\r
+  {\r
+    bool result = BOOLToBool(GetVolumeInformationW(\r
+      rootPathName,\r
+      volumeName.GetBuffer(MAX_PATH), MAX_PATH,\r
+      volumeSerialNumber,\r
+      maximumComponentLength,\r
+      fileSystemFlags,\r
+      fileSystemName.GetBuffer(MAX_PATH), MAX_PATH));\r
+    volumeName.ReleaseBuffer();\r
+    fileSystemName.ReleaseBuffer();\r
+    return result;\r
+  }\r
+  AString volumeNameA, fileSystemNameA;\r
+  bool result = MyGetVolumeInformation(GetSystemString(rootPathName), volumeNameA,\r
+      volumeSerialNumber, maximumComponentLength, fileSystemFlags,fileSystemNameA);\r
+  if (result)\r
+  {\r
+    volumeName = GetUnicodeString(volumeNameA);\r
+    fileSystemName = GetUnicodeString(fileSystemNameA);\r
+  }\r
+  return result;\r
+}\r
+#endif\r
+\r
+typedef BOOL (WINAPI * GetDiskFreeSpaceExPointer)(\r
+  LPCTSTR lpDirectoryName,                 // directory name\r
+  PULARGE_INTEGER lpFreeBytesAvailable,    // bytes available to caller\r
+  PULARGE_INTEGER lpTotalNumberOfBytes,    // bytes on disk\r
+  PULARGE_INTEGER lpTotalNumberOfFreeBytes // free bytes on disk\r
+);\r
+\r
+bool MyGetDiskFreeSpace(LPCTSTR rootPathName,\r
+    UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize)\r
+{\r
+  GetDiskFreeSpaceExPointer pGetDiskFreeSpaceEx =\r
+      (GetDiskFreeSpaceExPointer)GetProcAddress(\r
+      GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExA");\r
+\r
+  bool sizeIsDetected = false;\r
+  if (pGetDiskFreeSpaceEx)\r
+  {\r
+    ULARGE_INTEGER i64FreeBytesToCaller, totalSize2, freeSize2;\r
+    sizeIsDetected = BOOLToBool(pGetDiskFreeSpaceEx(rootPathName,\r
+                &i64FreeBytesToCaller,\r
+                &totalSize2,\r
+                &freeSize2));\r
+    totalSize = totalSize2.QuadPart;\r
+    freeSize = freeSize2.QuadPart;\r
+  }\r
+\r
+  DWORD numSectorsPerCluster;\r
+  DWORD bytesPerSector;\r
+  DWORD numberOfFreeClusters;\r
+  DWORD totalNumberOfClusters;\r
+\r
+  if (!::GetDiskFreeSpace(rootPathName,\r
+      &numSectorsPerCluster,\r
+      &bytesPerSector,\r
+      &numberOfFreeClusters,\r
+      &totalNumberOfClusters))\r
+    return false;\r
+\r
+  clusterSize = (UInt64)bytesPerSector * (UInt64)numSectorsPerCluster;\r
+  if (!sizeIsDetected)\r
+  {\r
+    totalSize =  clusterSize * (UInt64)totalNumberOfClusters;\r
+    freeSize =  clusterSize * (UInt64)numberOfFreeClusters;\r
+  }\r
+  return true;\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool MyGetDiskFreeSpace(LPCWSTR rootPathName,\r
+    UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize)\r
+{\r
+  return MyGetDiskFreeSpace(GetSystemString(rootPathName), clusterSize, totalSize, freeSize);\r
+}\r
+#endif\r
+\r
+}}}\r
diff --git a/CPP/Windows/FileSystem.h b/CPP/Windows/FileSystem.h
new file mode 100755 (executable)
index 0000000..dfce999
--- /dev/null
@@ -0,0 +1,51 @@
+// Windows/FileSystem.h\r
+\r
+#ifndef __WINDOWS_FILESYSTEM_H\r
+#define __WINDOWS_FILESYSTEM_H\r
+\r
+#include "../Common/MyString.h"\r
+#include "../Common/Types.h"\r
+\r
+#ifndef _UNICODE\r
+#include "../Common/StringConvert.h"\r
+#endif\r
+\r
+namespace NWindows {\r
+namespace NFile {\r
+namespace NSystem {\r
+\r
+bool MyGetVolumeInformation(\r
+    LPCTSTR rootPathName,\r
+    CSysString &volumeName,\r
+    LPDWORD volumeSerialNumber,\r
+    LPDWORD maximumComponentLength,\r
+    LPDWORD fileSystemFlags,\r
+    CSysString &fileSystemName);\r
+\r
+#ifndef _UNICODE\r
+bool MyGetVolumeInformation(\r
+    LPCWSTR rootPathName,\r
+    UString &volumeName,\r
+    LPDWORD volumeSerialNumber,\r
+    LPDWORD maximumComponentLength,\r
+    LPDWORD fileSystemFlags,\r
+    UString &fileSystemName);\r
+#endif\r
+\r
+inline UINT MyGetDriveType(LPCTSTR pathName) { return GetDriveType(pathName); }\r
+#ifndef _UNICODE\r
+inline UINT MyGetDriveType(LPCWSTR pathName) { return GetDriveType(GetSystemString(pathName)); }\r
+#endif\r
+\r
+bool MyGetDiskFreeSpace(LPCTSTR rootPathName,\r
+    UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);\r
+\r
+#ifndef _UNICODE\r
+bool MyGetDiskFreeSpace(LPCWSTR rootPathName,\r
+    UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);\r
+#endif\r
+\r
+}}}\r
+\r
+#endif\r
+\r
diff --git a/CPP/Windows/Handle.h b/CPP/Windows/Handle.h
new file mode 100755 (executable)
index 0000000..755eeb8
--- /dev/null
@@ -0,0 +1,37 @@
+// Windows/Handle.h\r
+\r
+#ifndef __WINDOWS_HANDLE_H\r
+#define __WINDOWS_HANDLE_H\r
+\r
+namespace NWindows {\r
+\r
+class CHandle\r
+{\r
+protected:\r
+  HANDLE _handle;\r
+public:\r
+  operator HANDLE() { return _handle; }\r
+  CHandle(): _handle(NULL) {}\r
+  ~CHandle() { Close(); }\r
+  bool IsCreated() const { return (_handle != NULL); }\r
+  bool Close()\r
+  {\r
+    if (_handle == NULL)\r
+      return true;\r
+    if (!::CloseHandle(_handle))\r
+      return false;\r
+    _handle = NULL;\r
+    return true;\r
+  }\r
+  void Attach(HANDLE handle) { _handle = handle; }\r
+  HANDLE Detach()\r
+  {\r
+    HANDLE handle = _handle;\r
+    _handle = NULL;\r
+    return handle;\r
+  }\r
+};\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Memory.cpp b/CPP/Windows/Memory.cpp
new file mode 100755 (executable)
index 0000000..fd50a59
--- /dev/null
@@ -0,0 +1,36 @@
+// Windows/Memory.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/Memory.h"\r
+\r
+namespace NWindows {\r
+namespace NMemory {\r
+\r
+bool CGlobal::Alloc(UINT flags, SIZE_T size)\r
+{\r
+  HGLOBAL newBlock = ::GlobalAlloc(flags, size);\r
+  if (newBlock == NULL)\r
+    return false;\r
+  m_MemoryHandle = newBlock;\r
+  return true;\r
+}\r
+\r
+bool CGlobal::Free()\r
+{\r
+  if (m_MemoryHandle == NULL)\r
+    return true;\r
+  m_MemoryHandle = ::GlobalFree(m_MemoryHandle);\r
+  return (m_MemoryHandle == NULL);\r
+}\r
+\r
+bool CGlobal::ReAlloc(SIZE_T size)\r
+{\r
+  HGLOBAL newBlock = ::GlobalReAlloc(m_MemoryHandle, size, GMEM_MOVEABLE);\r
+  if (newBlock == NULL)\r
+    return false;\r
+  m_MemoryHandle = newBlock;\r
+  return true;\r
+}\r
+\r
+}}\r
diff --git a/CPP/Windows/Memory.h b/CPP/Windows/Memory.h
new file mode 100755 (executable)
index 0000000..80b3049
--- /dev/null
@@ -0,0 +1,53 @@
+// Windows/Memory.h\r
+\r
+#ifndef __WINDOWS_MEMORY_H\r
+#define __WINDOWS_MEMORY_H\r
+\r
+namespace NWindows {\r
+namespace NMemory {\r
+\r
+class CGlobal\r
+{\r
+  HGLOBAL m_MemoryHandle;\r
+public:\r
+  CGlobal(): m_MemoryHandle(NULL){};\r
+  ~CGlobal() { Free(); }\r
+  operator HGLOBAL() const { return m_MemoryHandle; };\r
+  void Attach(HGLOBAL hGlobal)\r
+  {\r
+    Free();\r
+    m_MemoryHandle = hGlobal;\r
+  }\r
+  HGLOBAL Detach()\r
+  {\r
+    HGLOBAL h = m_MemoryHandle;\r
+    m_MemoryHandle = NULL;\r
+    return h;\r
+  }\r
+  bool Alloc(UINT flags, SIZE_T size);\r
+  bool Free();\r
+  LPVOID Lock() const { return GlobalLock(m_MemoryHandle); }\r
+  void Unlock() const { GlobalUnlock(m_MemoryHandle); }\r
+  bool ReAlloc(SIZE_T size);\r
+};\r
+\r
+class CGlobalLock\r
+{\r
+  HGLOBAL m_Global;\r
+  LPVOID m_Pointer;\r
+public:\r
+  LPVOID GetPointer() const { return m_Pointer; }\r
+  CGlobalLock(HGLOBAL hGlobal): m_Global(hGlobal)\r
+  {\r
+    m_Pointer = GlobalLock(hGlobal);\r
+  };\r
+  ~CGlobalLock()\r
+  {\r
+    if (m_Pointer != NULL)\r
+      GlobalUnlock(m_Global);\r
+  }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/MemoryLock.cpp b/CPP/Windows/MemoryLock.cpp
new file mode 100755 (executable)
index 0000000..9b2ffb8
--- /dev/null
@@ -0,0 +1,82 @@
+// Common/MemoryLock.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+namespace NWindows {\r
+namespace NSecurity {\r
+\r
+#ifndef UNDER_CE\r
+\r
+#ifndef _UNICODE\r
+typedef BOOL (WINAPI * OpenProcessTokenP)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle);\r
+typedef BOOL (WINAPI * LookupPrivilegeValueP)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID  lpLuid);\r
+typedef BOOL (WINAPI * AdjustTokenPrivilegesP)(HANDLE TokenHandle, BOOL DisableAllPrivileges,\r
+    PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState,PDWORD ReturnLength);\r
+#endif\r
+\r
+#ifdef _UNICODE\r
+bool EnableLockMemoryPrivilege(\r
+#else\r
+static bool EnableLockMemoryPrivilege2(HMODULE hModule,\r
+#endif\r
+bool enable)\r
+{\r
+  #ifndef _UNICODE\r
+  if (hModule == NULL)\r
+    return false;\r
+  OpenProcessTokenP openProcessToken = (OpenProcessTokenP)GetProcAddress(hModule, "OpenProcessToken");\r
+  LookupPrivilegeValueP lookupPrivilegeValue = (LookupPrivilegeValueP)GetProcAddress(hModule, "LookupPrivilegeValueA" );\r
+  AdjustTokenPrivilegesP adjustTokenPrivileges = (AdjustTokenPrivilegesP)GetProcAddress(hModule, "AdjustTokenPrivileges");\r
+  if (openProcessToken == NULL || adjustTokenPrivileges == NULL || lookupPrivilegeValue == NULL)\r
+    return false;\r
+  #endif\r
+\r
+  HANDLE token;\r
+  if (!\r
+    #ifdef _UNICODE\r
+    ::OpenProcessToken\r
+    #else\r
+    openProcessToken\r
+    #endif\r
+    (::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))\r
+    return false;\r
+  TOKEN_PRIVILEGES tp;\r
+  bool res = false;\r
+  if (\r
+    #ifdef _UNICODE\r
+    ::LookupPrivilegeValue\r
+    #else\r
+    lookupPrivilegeValue\r
+    #endif\r
+    (NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid)))\r
+  {\r
+    tp.PrivilegeCount = 1;\r
+    tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED: 0;\r
+    if (\r
+      #ifdef _UNICODE\r
+      ::AdjustTokenPrivileges\r
+      #else\r
+      adjustTokenPrivileges\r
+      #endif\r
+      (token, FALSE, &tp, 0, NULL, NULL))\r
+      res = (GetLastError() == ERROR_SUCCESS);\r
+  }\r
+  ::CloseHandle(token);\r
+  return res;\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool EnableLockMemoryPrivilege(bool enable)\r
+{\r
+  HMODULE hModule = LoadLibrary(TEXT("Advapi32.dll"));\r
+  if (hModule == NULL)\r
+    return false;\r
+  bool res = EnableLockMemoryPrivilege2(hModule, enable);\r
+  ::FreeLibrary(hModule);\r
+  return res;\r
+}\r
+#endif\r
+\r
+#endif\r
+\r
+}}\r
diff --git a/CPP/Windows/MemoryLock.h b/CPP/Windows/MemoryLock.h
new file mode 100755 (executable)
index 0000000..f2e574b
--- /dev/null
@@ -0,0 +1,15 @@
+// Windows/MemoryLock.h\r
+\r
+#ifndef __WINDOWS_MEMORYLOCK_H\r
+#define __WINDOWS_MEMORYLOCK_H\r
+\r
+namespace NWindows {\r
+namespace NSecurity {\r
+\r
+#ifndef UNDER_CE\r
+bool EnableLockMemoryPrivilege(bool enable = true);\r
+#endif\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Menu.cpp b/CPP/Windows/Menu.cpp
new file mode 100755 (executable)
index 0000000..aabfcf6
--- /dev/null
@@ -0,0 +1,191 @@
+// Windows/Menu.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#ifndef _UNICODE\r
+#include "Common/StringConvert.h"\r
+#endif\r
+#include "Windows/Menu.h"\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+namespace NWindows {\r
+\r
+static void ConvertItemToSysForm(const CMenuItem &item, MENUITEMINFOW &si)\r
+{\r
+  ZeroMemory(&si, sizeof(si));\r
+  si.cbSize = sizeof(si);\r
+  si.fMask = item.fMask;\r
+  si.fType = item.fType;\r
+  si.fState = item.fState;\r
+  si.wID = item.wID;\r
+  si.hSubMenu = item.hSubMenu;\r
+  si.hbmpChecked = item.hbmpChecked;\r
+  si.hbmpUnchecked = item.hbmpUnchecked;\r
+  si.dwItemData = item.dwItemData;\r
+}\r
+\r
+#ifndef _UNICODE\r
+static void ConvertItemToSysForm(const CMenuItem &item, MENUITEMINFOA &si)\r
+{\r
+  ZeroMemory(&si, sizeof(si));\r
+  si.cbSize = sizeof(si);\r
+  si.fMask = item.fMask;\r
+  si.fType = item.fType;\r
+  si.fState = item.fState;\r
+  si.wID = item.wID;\r
+  si.hSubMenu = item.hSubMenu;\r
+  si.hbmpChecked = item.hbmpChecked;\r
+  si.hbmpUnchecked = item.hbmpUnchecked;\r
+  si.dwItemData = item.dwItemData;\r
+}\r
+#endif\r
+\r
+static void ConvertItemToMyForm(const MENUITEMINFOW &si, CMenuItem &item)\r
+{\r
+  item.fMask = si.fMask;\r
+  item.fType = si.fType;\r
+  item.fState = si.fState;\r
+  item.wID = si.wID;\r
+  item.hSubMenu = si.hSubMenu;\r
+  item.hbmpChecked = si.hbmpChecked;\r
+  item.hbmpUnchecked = si.hbmpUnchecked;\r
+  item.dwItemData = si.dwItemData;\r
+}\r
+\r
+#ifndef _UNICODE\r
+static void ConvertItemToMyForm(const MENUITEMINFOA &si, CMenuItem &item)\r
+{\r
+  item.fMask = si.fMask;\r
+  item.fType = si.fType;\r
+  item.fState = si.fState;\r
+  item.wID = si.wID;\r
+  item.hSubMenu = si.hSubMenu;\r
+  item.hbmpChecked = si.hbmpChecked;\r
+  item.hbmpUnchecked = si.hbmpUnchecked;\r
+  item.dwItemData = si.dwItemData;\r
+}\r
+#endif\r
+\r
+bool CMenu::GetItem(UINT itemIndex, bool byPosition, CMenuItem &item)\r
+{\r
+  const UINT kMaxSize = 512;\r
+  #ifndef _UNICODE\r
+  if (!g_IsNT)\r
+  {\r
+    CHAR s[kMaxSize + 1];\r
+    MENUITEMINFOA si;\r
+    ConvertItemToSysForm(item, si);\r
+    if (item.IsString())\r
+    {\r
+      si.cch = kMaxSize;\r
+      si.dwTypeData = s;\r
+    }\r
+    if (GetItemInfo(itemIndex, byPosition, &si))\r
+    {\r
+      ConvertItemToMyForm(si, item);\r
+      if (item.IsString())\r
+        item.StringValue = GetUnicodeString(s);\r
+      return true;\r
+    }\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    wchar_t s[kMaxSize + 1];\r
+    MENUITEMINFOW si;\r
+    ConvertItemToSysForm(item, si);\r
+    if (item.IsString())\r
+    {\r
+      si.cch = kMaxSize;\r
+      si.dwTypeData = s;\r
+    }\r
+    if (GetItemInfo(itemIndex, byPosition, &si))\r
+    {\r
+      ConvertItemToMyForm(si, item);\r
+      if (item.IsString())\r
+        item.StringValue = s;\r
+      return true;\r
+    }\r
+  }\r
+  return false;\r
+}\r
+\r
+bool CMenu::SetItem(UINT itemIndex, bool byPosition, const CMenuItem &item)\r
+{\r
+  #ifndef _UNICODE\r
+  if (!g_IsNT)\r
+  {\r
+    MENUITEMINFOA si;\r
+    ConvertItemToSysForm(item, si);\r
+    AString s;\r
+    if (item.IsString())\r
+    {\r
+      s = GetSystemString(item.StringValue);\r
+      si.dwTypeData = (LPTSTR)(LPCTSTR)s;\r
+    }\r
+    return SetItemInfo(itemIndex, byPosition, &si);\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    MENUITEMINFOW si;\r
+    ConvertItemToSysForm(item, si);\r
+    if (item.IsString())\r
+      si.dwTypeData = (LPWSTR)(LPCWSTR)item.StringValue;\r
+    return SetItemInfo(itemIndex, byPosition, &si);\r
+  }\r
+}\r
+\r
+bool CMenu::InsertItem(UINT itemIndex, bool byPosition, const CMenuItem &item)\r
+{\r
+  #ifndef _UNICODE\r
+  if (!g_IsNT)\r
+  {\r
+    MENUITEMINFOA si;\r
+    ConvertItemToSysForm(item, si);\r
+    AString s;\r
+    if (item.IsString())\r
+    {\r
+      s = GetSystemString(item.StringValue);\r
+      si.dwTypeData = (LPTSTR)(LPCTSTR)s;\r
+    }\r
+    return InsertItem(itemIndex, byPosition, &si);\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    MENUITEMINFOW si;\r
+    ConvertItemToSysForm(item, si);\r
+    if (item.IsString())\r
+      si.dwTypeData = (LPWSTR)(LPCWSTR)item.StringValue;\r
+    #ifdef UNDER_CE\r
+    UINT flags = (item.fType & MFT_SEPARATOR) ? MF_SEPARATOR : MF_STRING;\r
+    UINT id = item.wID;\r
+    if ((item.fMask & MIIM_SUBMENU) != 0)\r
+    {\r
+      flags |= MF_POPUP;\r
+      id = (UINT)item.hSubMenu;\r
+    }\r
+    if (!Insert(itemIndex, flags | (byPosition ? MF_BYPOSITION : MF_BYCOMMAND), id, item.StringValue))\r
+      return false;\r
+    return SetItemInfo(itemIndex, byPosition, &si);\r
+    #else\r
+    return InsertItem(itemIndex, byPosition, &si);\r
+    #endif\r
+  }\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool CMenu::AppendItem(UINT flags, UINT_PTR newItemID, LPCWSTR newItem)\r
+{\r
+  if (g_IsNT)\r
+    return BOOLToBool(::AppendMenuW(_menu, flags, newItemID, newItem));\r
+  else\r
+    return AppendItem(flags, newItemID, GetSystemString(newItem));\r
+}\r
+#endif\r
+\r
+}\r
diff --git a/CPP/Windows/Menu.h b/CPP/Windows/Menu.h
new file mode 100755 (executable)
index 0000000..9aca0a2
--- /dev/null
@@ -0,0 +1,153 @@
+// Windows/Menu.h\r
+\r
+#ifndef __WINDOWS_MENU_H\r
+#define __WINDOWS_MENU_H\r
+\r
+#include "Common/MyString.h"\r
+#include "Windows/Defs.h"\r
+\r
+namespace NWindows {\r
+\r
+struct CMenuItem\r
+{\r
+  UString StringValue;\r
+  UINT fMask;\r
+  UINT fType;\r
+  UINT fState;\r
+  UINT wID;\r
+  HMENU hSubMenu;\r
+  HBITMAP hbmpChecked;\r
+  HBITMAP hbmpUnchecked;\r
+  ULONG_PTR dwItemData;\r
+  // LPTSTR dwTypeData;\r
+  // UINT cch;\r
+  // HBITMAP hbmpItem;\r
+  bool IsString() const // change it MIIM_STRING\r
+    { return ((fMask & MIIM_TYPE) != 0 && (fType == MFT_STRING)); }\r
+  bool IsSeparator() const { return (fType == MFT_SEPARATOR); }\r
+  CMenuItem(): fMask(0), fType(0), fState(0), wID(0), hSubMenu(0), hbmpChecked(0),\r
+    hbmpUnchecked(0), dwItemData(0) {}\r
+};\r
+\r
+class CMenu\r
+{\r
+  HMENU _menu;\r
+public:\r
+  CMenu(): _menu(NULL) {};\r
+  operator HMENU() const { return _menu; }\r
+  void Attach(HMENU menu) { _menu = menu; }\r
+  \r
+  HMENU Detach()\r
+  {\r
+    HMENU menu = _menu;\r
+    _menu = NULL;\r
+    return menu;\r
+  }\r
+  \r
+  bool Create()\r
+  {\r
+    _menu = ::CreateMenu();\r
+    return (_menu != NULL);\r
+  }\r
+\r
+  bool CreatePopup()\r
+  {\r
+    _menu = ::CreatePopupMenu();\r
+    return (_menu != NULL);\r
+  }\r
+  \r
+  bool Destroy()\r
+  {\r
+    if (_menu == NULL)\r
+      return false;\r
+    return BOOLToBool(::DestroyMenu(Detach()));\r
+  }\r
+  \r
+  int GetItemCount()\r
+  {\r
+    #ifdef UNDER_CE\r
+    for (int i = 0;; i++)\r
+    {\r
+      CMenuItem item;\r
+      item.fMask = MIIM_STATE;\r
+      if (!GetItem(i, true, item))\r
+        return i;\r
+    }\r
+    #else\r
+    return GetMenuItemCount(_menu);\r
+    #endif\r
+  }\r
+\r
+  HMENU GetSubMenu(int pos) { return ::GetSubMenu(_menu, pos); }\r
+  #ifndef UNDER_CE\r
+  bool GetItemString(UINT idItem, UINT flag, CSysString &result)\r
+  {\r
+    result.Empty();\r
+    int len = ::GetMenuString(_menu, idItem, 0, 0, flag);\r
+    len = ::GetMenuString(_menu, idItem, result.GetBuffer(len + 2), len + 1, flag);\r
+    result.ReleaseBuffer();\r
+    return (len != 0);\r
+  }\r
+  UINT GetItemID(int pos) { return ::GetMenuItemID(_menu, pos);   }\r
+  UINT GetItemState(UINT id, UINT flags) { return ::GetMenuState(_menu, id, flags);   }\r
+  #endif\r
+  \r
+  bool GetItemInfo(UINT itemIndex, bool byPosition, LPMENUITEMINFO itemInfo)\r
+    { return BOOLToBool(::GetMenuItemInfo(_menu, itemIndex, BoolToBOOL(byPosition), itemInfo)); }\r
+  bool SetItemInfo(UINT itemIndex, bool byPosition, LPMENUITEMINFO itemInfo)\r
+    { return BOOLToBool(::SetMenuItemInfo(_menu, itemIndex, BoolToBOOL(byPosition), itemInfo)); }\r
+\r
+  bool AppendItem(UINT flags, UINT_PTR newItemID, LPCTSTR newItem)\r
+    { return BOOLToBool(::AppendMenu(_menu, flags, newItemID, newItem)); }\r
+\r
+  bool Insert(UINT position, UINT flags, UINT_PTR idNewItem, LPCTSTR newItem)\r
+    { return BOOLToBool(::InsertMenu(_menu, position, flags, idNewItem, newItem)); }\r
+\r
+  #ifndef UNDER_CE\r
+  bool InsertItem(UINT itemIndex, bool byPosition, LPCMENUITEMINFO itemInfo)\r
+    { return BOOLToBool(::InsertMenuItem(_menu, itemIndex, BoolToBOOL(byPosition), itemInfo)); }\r
+  #endif\r
+\r
+  bool RemoveItem(UINT item, UINT flags) { return BOOLToBool(::RemoveMenu(_menu, item, flags)); }\r
+  void RemoveAllItemsFrom(UINT index) { while (RemoveItem(index, MF_BYPOSITION)); }\r
+  void RemoveAllItems() { RemoveAllItemsFrom(0); }\r
+\r
+  #ifndef _UNICODE\r
+  bool GetItemInfo(UINT itemIndex, bool byPosition, LPMENUITEMINFOW itemInfo)\r
+    { return BOOLToBool(::GetMenuItemInfoW(_menu, itemIndex, BoolToBOOL(byPosition), itemInfo)); }\r
+  bool InsertItem(UINT itemIndex, bool byPosition, LPMENUITEMINFOW itemInfo)\r
+    { return BOOLToBool(::InsertMenuItemW(_menu, itemIndex, BoolToBOOL(byPosition), itemInfo)); }\r
+  bool SetItemInfo(UINT itemIndex, bool byPosition, LPMENUITEMINFOW itemInfo)\r
+    { return BOOLToBool(::SetMenuItemInfoW(_menu, itemIndex, BoolToBOOL(byPosition), itemInfo)); }\r
+  bool AppendItem(UINT flags, UINT_PTR newItemID, LPCWSTR newItem);\r
+  #endif\r
+\r
+  bool GetItem(UINT itemIndex, bool byPosition, CMenuItem &item);\r
+  bool SetItem(UINT itemIndex, bool byPosition, const CMenuItem &item);\r
+  bool InsertItem(UINT itemIndex, bool byPosition, const CMenuItem &item);\r
+\r
+  int Track(UINT flags, int x, int y, HWND hWnd) { return ::TrackPopupMenuEx(_menu, flags, x, y, hWnd, NULL); }\r
+\r
+  bool CheckRadioItem(UINT idFirst, UINT idLast, UINT idCheck, UINT flags)\r
+    { return BOOLToBool(::CheckMenuRadioItem(_menu, idFirst, idLast, idCheck, flags)); }\r
+\r
+  DWORD CheckItem(UINT id, UINT uCheck) { return ::CheckMenuItem(_menu, id, uCheck); }\r
+  DWORD CheckItemByID(UINT id, bool check) { return CheckItem(id, MF_BYCOMMAND | (check ? MF_CHECKED : MF_UNCHECKED)); }\r
+\r
+  BOOL EnableItem(UINT uIDEnableItem, UINT uEnable) { return EnableMenuItem(_menu, uIDEnableItem, uEnable); }\r
+};\r
+\r
+class CMenuDestroyer\r
+{\r
+  CMenu *_menu;\r
+public:\r
+  CMenuDestroyer(CMenu &menu): _menu(&menu) {}\r
+  CMenuDestroyer(): _menu(0) {}\r
+  ~CMenuDestroyer() { if (_menu) _menu->Destroy(); }\r
+  void Attach(CMenu &menu) { _menu = &menu; }\r
+  void Disable() { _menu = 0; }\r
+};\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/Windows/NationalTime.cpp b/CPP/Windows/NationalTime.cpp
new file mode 100755 (executable)
index 0000000..bbb08d2
--- /dev/null
@@ -0,0 +1,37 @@
+// Windows/NationalTime.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/NationalTime.h"\r
+\r
+namespace NWindows {\r
+namespace NNational {\r
+namespace NTime {\r
+\r
+bool MyGetTimeFormat(LCID locale, DWORD flags, CONST SYSTEMTIME *time,\r
+    LPCTSTR format, CSysString &resultString)\r
+{\r
+  resultString.Empty();\r
+  int numChars = ::GetTimeFormat(locale, flags, time, format, NULL, 0);\r
+  if (numChars == 0)\r
+    return false;\r
+  numChars = ::GetTimeFormat(locale, flags, time, format,\r
+      resultString.GetBuffer(numChars), numChars + 1);\r
+  resultString.ReleaseBuffer();\r
+  return (numChars != 0);\r
+}\r
+\r
+bool MyGetDateFormat(LCID locale, DWORD flags, CONST SYSTEMTIME *time,\r
+    LPCTSTR format, CSysString &resultString)\r
+{\r
+  resultString.Empty();\r
+  int numChars = ::GetDateFormat(locale, flags, time, format, NULL, 0);\r
+  if (numChars == 0)\r
+    return false;\r
+  numChars = ::GetDateFormat(locale, flags, time, format,\r
+      resultString.GetBuffer(numChars), numChars + 1);\r
+  resultString.ReleaseBuffer();\r
+  return (numChars != 0);\r
+}\r
+\r
+}}}\r
diff --git a/CPP/Windows/NationalTime.h b/CPP/Windows/NationalTime.h
new file mode 100755 (executable)
index 0000000..d5419c7
--- /dev/null
@@ -0,0 +1,20 @@
+// Windows/NationalTime.h\r
+\r
+#ifndef __WINDOWS_NATIONALTIME_H\r
+#define __WINDOWS_NATIONALTIME_H\r
+\r
+#include "Common/String.h"\r
+\r
+namespace NWindows {\r
+namespace NNational {\r
+namespace NTime {\r
+\r
+bool MyGetTimeFormat(LCID locale, DWORD flags, CONST SYSTEMTIME *time,\r
+    LPCTSTR format, CSysString &resultString);\r
+\r
+bool MyGetDateFormat(LCID locale, DWORD flags, CONST SYSTEMTIME *time,\r
+    LPCTSTR format, CSysString &resultString);\r
+\r
+}}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Net.cpp b/CPP/Windows/Net.cpp
new file mode 100755 (executable)
index 0000000..01a68fb
--- /dev/null
@@ -0,0 +1,380 @@
+// Windows/Net.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#ifndef _UNICODE\r
+#include "Common/StringConvert.h"\r
+#endif\r
+\r
+#include "Windows/Net.h"\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+namespace NWindows {\r
+namespace NNet {\r
+\r
+DWORD CEnum::Open(DWORD scope, DWORD type, DWORD usage, LPNETRESOURCE netResource)\r
+{\r
+  Close();\r
+  DWORD result = ::WNetOpenEnum(scope, type, usage, netResource, &_handle);\r
+  _handleAllocated = (result == NO_ERROR);\r
+  return result;\r
+}\r
+\r
+#ifndef _UNICODE\r
+DWORD CEnum::Open(DWORD scope, DWORD type, DWORD usage, LPNETRESOURCEW netResource)\r
+{\r
+  Close();\r
+  DWORD result = ::WNetOpenEnumW(scope, type, usage, netResource, &_handle);\r
+  _handleAllocated = (result == NO_ERROR);\r
+  return result;\r
+}\r
+#endif\r
+\r
+static void SetComplexString(bool &defined, CSysString &destString, LPCTSTR srsString)\r
+{\r
+  defined = (srsString != 0);\r
+  if (defined)\r
+    destString = srsString;\r
+  else\r
+    destString.Empty();\r
+}\r
+\r
+static void ConvertNETRESOURCEToCResource(const NETRESOURCE &netResource, CResource &resource)\r
+{\r
+  resource.Scope = netResource.dwScope;\r
+  resource.Type = netResource.dwType;\r
+  resource.DisplayType = netResource.dwDisplayType;\r
+  resource.Usage = netResource.dwUsage;\r
+  SetComplexString(resource.LocalNameIsDefined, resource.LocalName, netResource.lpLocalName);\r
+  SetComplexString(resource.RemoteNameIsDefined, resource.RemoteName, netResource.lpRemoteName);\r
+  SetComplexString(resource.CommentIsDefined, resource.Comment, netResource.lpComment);\r
+  SetComplexString(resource.ProviderIsDefined, resource.Provider, netResource.lpProvider);\r
+}\r
+\r
+static void SetComplexString2(LPTSTR *destString, bool defined, const CSysString &srcString)\r
+{\r
+  if (defined)\r
+    *destString = (TCHAR *)(const TCHAR *)srcString;\r
+  else\r
+    *destString = 0;\r
+}\r
+\r
+static void ConvertCResourceToNETRESOURCE(const CResource &resource, NETRESOURCE &netResource)\r
+{\r
+  netResource.dwScope = resource.Scope;\r
+  netResource.dwType = resource.Type;\r
+  netResource.dwDisplayType = resource.DisplayType;\r
+  netResource.dwUsage = resource.Usage;\r
+  SetComplexString2(&netResource.lpLocalName, resource.LocalNameIsDefined, resource.LocalName);\r
+  SetComplexString2(&netResource.lpRemoteName, resource.RemoteNameIsDefined, resource.RemoteName);\r
+  SetComplexString2(&netResource.lpComment, resource.CommentIsDefined, resource.Comment);\r
+  SetComplexString2(&netResource.lpProvider, resource.ProviderIsDefined, resource.Provider);\r
+}\r
+\r
+#ifndef _UNICODE\r
+\r
+static void SetComplexString(bool &defined, UString &destString, LPCWSTR srsString)\r
+{\r
+  defined = (srsString != 0);\r
+  if (defined)\r
+    destString = srsString;\r
+  else\r
+    destString.Empty();\r
+}\r
+\r
+static void ConvertNETRESOURCEToCResource(const NETRESOURCEW &netResource, CResourceW &resource)\r
+{\r
+  resource.Scope = netResource.dwScope;\r
+  resource.Type = netResource.dwType;\r
+  resource.DisplayType = netResource.dwDisplayType;\r
+  resource.Usage = netResource.dwUsage;\r
+  SetComplexString(resource.LocalNameIsDefined, resource.LocalName, netResource.lpLocalName);\r
+  SetComplexString(resource.RemoteNameIsDefined, resource.RemoteName, netResource.lpRemoteName);\r
+  SetComplexString(resource.CommentIsDefined, resource.Comment, netResource.lpComment);\r
+  SetComplexString(resource.ProviderIsDefined, resource.Provider, netResource.lpProvider);\r
+}\r
+\r
+static void SetComplexString2(LPWSTR *destString, bool defined, const UString &srcString)\r
+{\r
+  if (defined)\r
+    *destString = (WCHAR *)(const WCHAR *)srcString;\r
+  else\r
+    *destString = 0;\r
+}\r
+\r
+static void ConvertCResourceToNETRESOURCE(const CResourceW &resource, NETRESOURCEW &netResource)\r
+{\r
+  netResource.dwScope = resource.Scope;\r
+  netResource.dwType = resource.Type;\r
+  netResource.dwDisplayType = resource.DisplayType;\r
+  netResource.dwUsage = resource.Usage;\r
+  SetComplexString2(&netResource.lpLocalName, resource.LocalNameIsDefined, resource.LocalName);\r
+  SetComplexString2(&netResource.lpRemoteName, resource.RemoteNameIsDefined, resource.RemoteName);\r
+  SetComplexString2(&netResource.lpComment, resource.CommentIsDefined, resource.Comment);\r
+  SetComplexString2(&netResource.lpProvider, resource.ProviderIsDefined, resource.Provider);\r
+}\r
+\r
+static void ConvertResourceWToResource(const CResourceW &resourceW, CResource &resource)\r
+{\r
+  *(CResourceBase *)&resource = *(CResourceBase *)&resourceW;\r
+  resource.LocalName = GetSystemString(resourceW.LocalName);\r
+  resource.RemoteName = GetSystemString(resourceW.RemoteName);\r
+  resource.Comment = GetSystemString(resourceW.Comment);\r
+  resource.Provider = GetSystemString(resourceW.Provider);\r
+}\r
+\r
+static void ConvertResourceToResourceW(const CResource &resource, CResourceW &resourceW)\r
+{\r
+  *(CResourceBase *)&resourceW = *(CResourceBase *)&resource;\r
+  resourceW.LocalName = GetUnicodeString(resource.LocalName);\r
+  resourceW.RemoteName = GetUnicodeString(resource.RemoteName);\r
+  resourceW.Comment = GetUnicodeString(resource.Comment);\r
+  resourceW.Provider = GetUnicodeString(resource.Provider);\r
+}\r
+#endif\r
+\r
+DWORD CEnum::Open(DWORD scope, DWORD type, DWORD usage, const CResource *resource)\r
+{\r
+  NETRESOURCE netResource;\r
+  LPNETRESOURCE pointer;\r
+  if (resource == 0)\r
+    pointer = 0;\r
+  else\r
+  {\r
+    ConvertCResourceToNETRESOURCE(*resource, netResource);\r
+    pointer = &netResource;\r
+  }\r
+  return Open(scope, type, usage, pointer);\r
+}\r
+\r
+#ifndef _UNICODE\r
+DWORD CEnum::Open(DWORD scope, DWORD type, DWORD usage, const CResourceW *resource)\r
+{\r
+  if (g_IsNT)\r
+  {\r
+    NETRESOURCEW netResource;\r
+    LPNETRESOURCEW pointer;\r
+    if (resource == 0)\r
+      pointer = 0;\r
+    else\r
+    {\r
+      ConvertCResourceToNETRESOURCE(*resource, netResource);\r
+      pointer = &netResource;\r
+    }\r
+    return Open(scope, type, usage, pointer);\r
+  }\r
+  CResource *pointer;\r
+  CResource resourceA;\r
+  if (resource == 0)\r
+    pointer = 0;\r
+  else\r
+  {\r
+    ConvertResourceWToResource(*resource, resourceA);\r
+    pointer = &resourceA;\r
+  }\r
+  return Open(scope, type, usage, pointer);\r
+}\r
+#endif\r
+\r
+DWORD CEnum::Close()\r
+{\r
+  if (!_handleAllocated)\r
+    return NO_ERROR;\r
+  DWORD result = ::WNetCloseEnum(_handle);\r
+  _handleAllocated = (result != NO_ERROR);\r
+  return result;\r
+}\r
+\r
+DWORD CEnum::Next(LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)\r
+{\r
+  return ::WNetEnumResource(_handle, lpcCount, lpBuffer, lpBufferSize);\r
+}\r
+\r
+#ifndef _UNICODE\r
+DWORD CEnum::NextW(LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)\r
+{\r
+  return ::WNetEnumResourceW(_handle, lpcCount, lpBuffer, lpBufferSize);\r
+}\r
+#endif\r
+\r
+DWORD CEnum::Next(CResource &resource)\r
+{\r
+  CByteBuffer byteBuffer;\r
+  const DWORD kBufferSize = 16384;\r
+  byteBuffer.SetCapacity(kBufferSize);\r
+  LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (BYTE *)(byteBuffer);\r
+  ZeroMemory(lpnrLocal, kBufferSize);\r
+  DWORD bufferSize = kBufferSize;\r
+  DWORD numEntries = 1;\r
+  DWORD result = Next(&numEntries, lpnrLocal, &bufferSize);\r
+  if (result != NO_ERROR)\r
+    return result;\r
+  if (numEntries != 1)\r
+    return (DWORD)E_FAIL;\r
+  ConvertNETRESOURCEToCResource(lpnrLocal[0], resource);\r
+  return result;\r
+}\r
+\r
+#ifndef _UNICODE\r
+DWORD CEnum::Next(CResourceW &resource)\r
+{\r
+  if (g_IsNT)\r
+  {\r
+    CByteBuffer byteBuffer;\r
+    const DWORD kBufferSize = 16384;\r
+    byteBuffer.SetCapacity(kBufferSize);\r
+    LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (BYTE *)(byteBuffer);\r
+    ZeroMemory(lpnrLocal, kBufferSize);\r
+    DWORD bufferSize = kBufferSize;\r
+    DWORD numEntries = 1;\r
+    DWORD result = NextW(&numEntries, lpnrLocal, &bufferSize);\r
+    if (result != NO_ERROR)\r
+      return result;\r
+    if (numEntries != 1)\r
+      return (DWORD)E_FAIL;\r
+    ConvertNETRESOURCEToCResource(lpnrLocal[0], resource);\r
+    return result;\r
+  }\r
+  CResource resourceA;\r
+  DWORD result = Next(resourceA);\r
+  ConvertResourceToResourceW(resourceA, resource);\r
+  return result;\r
+}\r
+#endif\r
+\r
+\r
+DWORD GetResourceParent(const CResource &resource, CResource &parentResource)\r
+{\r
+  CByteBuffer byteBuffer;\r
+  const DWORD kBufferSize = 16384;\r
+  byteBuffer.SetCapacity(kBufferSize);\r
+  LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (BYTE *)(byteBuffer);\r
+  ZeroMemory(lpnrLocal, kBufferSize);\r
+  DWORD bufferSize = kBufferSize;\r
+  NETRESOURCE netResource;\r
+  ConvertCResourceToNETRESOURCE(resource, netResource);\r
+  DWORD result = ::WNetGetResourceParent(&netResource, lpnrLocal, &bufferSize);\r
+  if (result != NO_ERROR)\r
+    return result;\r
+  ConvertNETRESOURCEToCResource(lpnrLocal[0], parentResource);\r
+  return result;\r
+}\r
+\r
+#ifndef _UNICODE\r
+DWORD GetResourceParent(const CResourceW &resource, CResourceW &parentResource)\r
+{\r
+  if (g_IsNT)\r
+  {\r
+    CByteBuffer byteBuffer;\r
+    const DWORD kBufferSize = 16384;\r
+    byteBuffer.SetCapacity(kBufferSize);\r
+    LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (BYTE *)(byteBuffer);\r
+    ZeroMemory(lpnrLocal, kBufferSize);\r
+    DWORD bufferSize = kBufferSize;\r
+    NETRESOURCEW netResource;\r
+    ConvertCResourceToNETRESOURCE(resource, netResource);\r
+    DWORD result = ::WNetGetResourceParentW(&netResource, lpnrLocal, &bufferSize);\r
+    if (result != NO_ERROR)\r
+      return result;\r
+    ConvertNETRESOURCEToCResource(lpnrLocal[0], parentResource);\r
+    return result;\r
+  }\r
+  CResource resourceA, parentResourceA;\r
+  ConvertResourceWToResource(resource, resourceA);\r
+  DWORD result = GetResourceParent(resourceA, parentResourceA);\r
+  ConvertResourceToResourceW(parentResourceA, parentResource);\r
+  return result;\r
+}\r
+#endif\r
+\r
+DWORD GetResourceInformation(const CResource &resource,\r
+    CResource &destResource, CSysString &systemPathPart)\r
+{\r
+  CByteBuffer byteBuffer;\r
+  const DWORD kBufferSize = 16384;\r
+  byteBuffer.SetCapacity(kBufferSize);\r
+  LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (BYTE *)(byteBuffer);\r
+  ZeroMemory(lpnrLocal, kBufferSize);\r
+  DWORD bufferSize = kBufferSize;\r
+  NETRESOURCE netResource;\r
+  ConvertCResourceToNETRESOURCE(resource, netResource);\r
+  LPTSTR lplpSystem;\r
+  DWORD result = ::WNetGetResourceInformation(&netResource,\r
+      lpnrLocal, &bufferSize, &lplpSystem);\r
+  if (result != NO_ERROR)\r
+    return result;\r
+  if (lplpSystem != 0)\r
+    systemPathPart = lplpSystem;\r
+  ConvertNETRESOURCEToCResource(lpnrLocal[0], destResource);\r
+  return result;\r
+}\r
+\r
+#ifndef _UNICODE\r
+DWORD GetResourceInformation(const CResourceW &resource,\r
+    CResourceW &destResource, UString &systemPathPart)\r
+{\r
+  if (g_IsNT)\r
+  {\r
+    CByteBuffer byteBuffer;\r
+    const DWORD kBufferSize = 16384;\r
+    byteBuffer.SetCapacity(kBufferSize);\r
+    LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (BYTE *)(byteBuffer);\r
+    ZeroMemory(lpnrLocal, kBufferSize);\r
+    DWORD bufferSize = kBufferSize;\r
+    NETRESOURCEW netResource;\r
+    ConvertCResourceToNETRESOURCE(resource, netResource);\r
+    LPWSTR lplpSystem;\r
+    DWORD result = ::WNetGetResourceInformationW(&netResource,\r
+      lpnrLocal, &bufferSize, &lplpSystem);\r
+    if (result != NO_ERROR)\r
+      return result;\r
+    if (lplpSystem != 0)\r
+      systemPathPart = lplpSystem;\r
+    ConvertNETRESOURCEToCResource(lpnrLocal[0], destResource);\r
+    return result;\r
+  }\r
+  CResource resourceA, destResourceA;\r
+  ConvertResourceWToResource(resource, resourceA);\r
+  AString systemPathPartA;\r
+  DWORD result = GetResourceInformation(resourceA, destResourceA, systemPathPartA);\r
+  ConvertResourceToResourceW(destResourceA, destResource);\r
+  systemPathPart = GetUnicodeString(systemPathPartA);\r
+  return result;\r
+}\r
+#endif\r
+\r
+DWORD AddConnection2(const CResource &resource,\r
+    LPCTSTR password, LPCTSTR userName, DWORD flags)\r
+{\r
+  NETRESOURCE netResource;\r
+  ConvertCResourceToNETRESOURCE(resource, netResource);\r
+  return ::WNetAddConnection2(&netResource,\r
+    password, userName, flags);\r
+}\r
+\r
+DWORD AddConnection2(const CResource &resource, LPCTSTR password, LPCTSTR userName, DWORD flags);\r
+\r
+#ifndef _UNICODE\r
+DWORD AddConnection2(const CResourceW &resource, LPCWSTR password, LPCWSTR userName, DWORD flags)\r
+{\r
+  if (g_IsNT)\r
+  {\r
+    NETRESOURCEW netResource;\r
+    ConvertCResourceToNETRESOURCE(resource, netResource);\r
+    return ::WNetAddConnection2W(&netResource,password, userName, flags);\r
+  }\r
+  CResource resourceA;\r
+  ConvertResourceWToResource(resource, resourceA);\r
+  CSysString passwordA = GetSystemString(password);\r
+  CSysString userNameA = GetSystemString(userName);\r
+  return AddConnection2(resourceA,\r
+    password ? (LPCTSTR)passwordA: 0,\r
+    userName ? (LPCTSTR)userNameA: 0,\r
+    flags);\r
+}\r
+#endif\r
+\r
+}}\r
diff --git a/CPP/Windows/Net.h b/CPP/Windows/Net.h
new file mode 100755 (executable)
index 0000000..5fae43d
--- /dev/null
@@ -0,0 +1,87 @@
+// Windows/Net.h\r
+\r
+#ifndef __WINDOWS_NET_H\r
+#define __WINDOWS_NET_H\r
+\r
+#include "Common/Buffer.h"\r
+#include "Common/MyString.h"\r
+\r
+namespace NWindows {\r
+namespace NNet {\r
+\r
+struct CResourceBase\r
+{\r
+  DWORD Scope;\r
+  DWORD Type;\r
+  DWORD DisplayType;\r
+  DWORD Usage;\r
+  bool LocalNameIsDefined;\r
+  bool RemoteNameIsDefined;\r
+  bool CommentIsDefined;\r
+  bool ProviderIsDefined;\r
+};\r
+\r
+struct CResource: public CResourceBase\r
+{\r
+  CSysString LocalName;\r
+  CSysString RemoteName;\r
+  CSysString Comment;\r
+  CSysString Provider;\r
+};\r
+\r
+#ifdef _UNICODE\r
+typedef CResource CResourceW;\r
+#else\r
+struct CResourceW: public CResourceBase\r
+{\r
+  UString LocalName;\r
+  UString RemoteName;\r
+  UString Comment;\r
+  UString Provider;\r
+};\r
+#endif\r
+\r
+class CEnum\r
+{\r
+  HANDLE _handle;\r
+  bool _handleAllocated;\r
+  DWORD Open(DWORD scope, DWORD type, DWORD usage, LPNETRESOURCE netResource);\r
+  DWORD Next(LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize);\r
+  #ifndef _UNICODE\r
+  DWORD Open(DWORD scope, DWORD type, DWORD usage, LPNETRESOURCEW netResource);\r
+  DWORD NextW(LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize);\r
+  #endif\r
+protected:\r
+  bool IsHandleAllocated() const { return _handleAllocated; }\r
+public:\r
+  CEnum(): _handleAllocated(false) {}\r
+  ~CEnum() {  Close(); }\r
+  DWORD Close();\r
+  DWORD Open(DWORD scope, DWORD type, DWORD usage, const CResource *resource);\r
+  DWORD Next(CResource &resource);\r
+  #ifndef _UNICODE\r
+  DWORD Open(DWORD scope, DWORD type, DWORD usage, const CResourceW *resource);\r
+  DWORD Next(CResourceW &resource);\r
+  #endif\r
+};\r
+\r
+DWORD GetResourceParent(const CResource &resource, CResource &parentResource);\r
+#ifndef _UNICODE\r
+DWORD GetResourceParent(const CResourceW &resource, CResourceW &parentResource);\r
+#endif\r
+\r
+DWORD GetResourceInformation(const CResource &resource,\r
+    CResource &destResource, CSysString &systemPathPart);\r
+#ifndef _UNICODE\r
+DWORD GetResourceInformation(const CResourceW &resource,\r
+    CResourceW &destResource, UString &systemPathPart);\r
+#endif\r
+\r
+DWORD AddConnection2(const CResource &resource, LPCTSTR password, LPCTSTR userName, DWORD flags);\r
+#ifndef _UNICODE\r
+DWORD AddConnection2(const CResourceW &resource, LPCWSTR password, LPCWSTR userName, DWORD flags);\r
+#endif\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/NtCheck.h b/CPP/Windows/NtCheck.h
new file mode 100755 (executable)
index 0000000..b8fa99b
--- /dev/null
@@ -0,0 +1,44 @@
+// Windows/NtCheck.h\r
+\r
+#ifndef __WINDOWS_NT_CHECK_H\r
+#define __WINDOWS_NT_CHECK_H\r
+\r
+#ifdef _WIN32\r
+\r
+#if !defined(_WIN64) && !defined(UNDER_CE)\r
+static inline bool IsItWindowsNT()\r
+{\r
+  OSVERSIONINFO vi;\r
+  vi.dwOSVersionInfoSize = sizeof(vi);\r
+  return (::GetVersionEx(&vi) && vi.dwPlatformId == VER_PLATFORM_WIN32_NT);\r
+}\r
+#endif\r
+\r
+#ifndef _UNICODE\r
+  #if defined(_WIN64) || defined(UNDER_CE)\r
+    bool g_IsNT = true;\r
+    #define SET_IS_NT\r
+  #else\r
+    bool g_IsNT = false;\r
+    #define SET_IS_NT g_IsNT = IsItWindowsNT();\r
+  #endif\r
+  #define NT_CHECK_ACTION\r
+  // #define NT_CHECK_ACTION { NT_CHECK_FAIL_ACTION }\r
+#else\r
+  #if !defined(_WIN64) && !defined(UNDER_CE)\r
+    #define NT_CHECK_ACTION if (!IsItWindowsNT()) { NT_CHECK_FAIL_ACTION }\r
+  #else\r
+    #define NT_CHECK_ACTION\r
+  #endif\r
+  #define SET_IS_NT\r
+#endif\r
+\r
+#define NT_CHECK  NT_CHECK_ACTION SET_IS_NT\r
+\r
+#else\r
+\r
+#define NT_CHECK\r
+\r
+#endif\r
+\r
+#endif\r
diff --git a/CPP/Windows/Process.cpp b/CPP/Windows/Process.cpp
new file mode 100755 (executable)
index 0000000..27972cd
--- /dev/null
@@ -0,0 +1,81 @@
+// Process.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../Common/StringConvert.h"\r
+\r
+#include "Process.h"\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+namespace NWindows {\r
+\r
+static UString GetQuotedString(const UString &s)\r
+{\r
+  return UString(L'\"') + s + UString(L'\"');\r
+}\r
+\r
+WRes CProcess::Create(LPCWSTR imageName, const UString &params, LPCWSTR curDir)\r
+{\r
+  Close();\r
+  const UString params2 =\r
+      #ifndef UNDER_CE\r
+      GetQuotedString(imageName) + L' ' +\r
+      #endif\r
+      params;\r
+  #ifdef UNDER_CE\r
+  curDir = 0;\r
+  #else\r
+  imageName = 0;\r
+  #endif\r
+  PROCESS_INFORMATION pi;\r
+  BOOL result;\r
+  #ifndef _UNICODE\r
+  if (!g_IsNT)\r
+  {\r
+    STARTUPINFOA si;\r
+    si.cb = sizeof(si);\r
+    si.lpReserved = 0;\r
+    si.lpDesktop = 0;\r
+    si.lpTitle = 0;\r
+    si.dwFlags = 0;\r
+    si.cbReserved2 = 0;\r
+    si.lpReserved2 = 0;\r
+    \r
+    CSysString curDirA;\r
+    if (curDir != 0)\r
+      curDirA = GetSystemString(curDir);\r
+    result = ::CreateProcessA(NULL, (LPSTR)(LPCSTR)GetSystemString(params2),\r
+        NULL, NULL, FALSE, 0, NULL, ((curDir != 0) ? (LPCSTR)curDirA: 0), &si, &pi);\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    STARTUPINFOW si;\r
+    si.cb = sizeof(si);\r
+    si.lpReserved = 0;\r
+    si.lpDesktop = 0;\r
+    si.lpTitle = 0;\r
+    si.dwFlags = 0;\r
+    si.cbReserved2 = 0;\r
+    si.lpReserved2 = 0;\r
+    \r
+    result = CreateProcessW(imageName, (LPWSTR)(LPCWSTR)params2,\r
+        NULL, NULL, FALSE, 0, NULL, (LPWSTR)curDir, &si, &pi);\r
+  }\r
+  if (result == 0)\r
+    return ::GetLastError();\r
+  ::CloseHandle(pi.hThread);\r
+  _handle = pi.hProcess;\r
+  return 0;\r
+}\r
+\r
+WRes MyCreateProcess(LPCWSTR imageName, const UString &params)\r
+{\r
+  CProcess process;\r
+  return process.Create(imageName, params, 0);\r
+}\r
+\r
+}\r
diff --git a/CPP/Windows/Process.h b/CPP/Windows/Process.h
new file mode 100755 (executable)
index 0000000..1b6b555
--- /dev/null
@@ -0,0 +1,100 @@
+// Windows/Process.h\r
+\r
+#ifndef __WINDOWS_PROCESS_H\r
+#define __WINDOWS_PROCESS_H\r
+\r
+#include <psapi.h>\r
+\r
+#include "../Common/MyString.h"\r
+\r
+#include "Defs.h"\r
+#include "Handle.h"\r
+\r
+namespace NWindows {\r
+\r
+class CProcess: public CHandle\r
+{\r
+public:\r
+  bool Open(DWORD desiredAccess, bool inheritHandle, DWORD processId)\r
+  {\r
+    _handle = ::OpenProcess(desiredAccess, inheritHandle, processId);\r
+    return (_handle != 0);\r
+  }\r
+\r
+  #ifndef UNDER_CE\r
+\r
+  bool GetExitCodeProcess(LPDWORD lpExitCode) { return BOOLToBool(::GetExitCodeProcess(_handle, lpExitCode)); }\r
+  bool Terminate(UINT exitCode) { return BOOLToBool(::TerminateProcess(_handle, exitCode)); }\r
+  #if(WINVER >= 0x0500)\r
+  DWORD GetGuiResources (DWORD uiFlags) { return ::GetGuiResources(_handle, uiFlags); }\r
+  #endif\r
+  bool SetPriorityClass(DWORD dwPriorityClass) { return BOOLToBool(::SetPriorityClass(_handle, dwPriorityClass)); }\r
+  DWORD GetPriorityClass() { return ::GetPriorityClass(_handle); }\r
+  bool GetIoCounters(PIO_COUNTERS lpIoCounters ) { return BOOLToBool(::GetProcessIoCounters(_handle, lpIoCounters )); }\r
+\r
+  bool GetTimes(LPFILETIME creationTime, LPFILETIME exitTime, LPFILETIME kernelTime, LPFILETIME userTime)\r
+    { return BOOLToBool(::GetProcessTimes(_handle, creationTime, exitTime, kernelTime, userTime)); }\r
+\r
+  DWORD WaitForInputIdle(DWORD milliseconds) { return ::WaitForInputIdle(_handle, milliseconds);  }\r
+\r
+  // Debug\r
+\r
+  bool ReadMemory(LPCVOID baseAddress, LPVOID buffer, SIZE_T size, SIZE_T* numberOfBytesRead)\r
+    { return BOOLToBool(::ReadProcessMemory(_handle, baseAddress, buffer, size, numberOfBytesRead));  }\r
+\r
+  bool WriteMemory(LPVOID baseAddress, LPCVOID buffer, SIZE_T size, SIZE_T* numberOfBytesWritten)\r
+    { return BOOLToBool(::WriteProcessMemory(_handle, baseAddress, buffer, size, numberOfBytesWritten)); }\r
+\r
+  bool FlushInstructionCache(LPCVOID baseAddress = 0, SIZE_T size = 0)\r
+    { return BOOLToBool(::FlushInstructionCache(_handle, baseAddress, size)); }\r
+\r
+  LPVOID VirtualAlloc(LPVOID address, SIZE_T size, DWORD allocationType, DWORD protect)\r
+    { return VirtualAllocEx(_handle, address, size, allocationType, protect);  }\r
+\r
+  bool VirtualFree(LPVOID address, SIZE_T size, DWORD freeType)\r
+    { return BOOLToBool(::VirtualFreeEx(_handle, address, size, freeType)); }\r
+\r
+  // Process Status API (PSAPI)\r
+\r
+  bool EmptyWorkingSet()\r
+    { return BOOLToBool(::EmptyWorkingSet(_handle)); }\r
+  bool EnumModules(HMODULE *hModules, DWORD arraySizeInBytes, LPDWORD receivedBytes)\r
+    { return BOOLToBool(::EnumProcessModules(_handle, hModules, arraySizeInBytes, receivedBytes)); }\r
+\r
+  DWORD MyGetModuleBaseName(HMODULE hModule, LPTSTR baseName, DWORD size)\r
+    { return ::GetModuleBaseName(_handle, hModule, baseName, size); }\r
+  bool MyGetModuleBaseName(HMODULE hModule, CSysString &name)\r
+  {\r
+    const int length = 1000;\r
+    DWORD resultLen = MyGetModuleBaseName(hModule, name.GetBuffer(length), length);\r
+    name.ReleaseBuffer();\r
+    return (resultLen != 0);\r
+  }\r
+\r
+  DWORD MyGetModuleFileNameEx(HMODULE hModule, LPTSTR baseName, DWORD size)\r
+    { return ::GetModuleFileNameEx(_handle, hModule, baseName, size); }\r
+  bool MyGetModuleFileNameEx(HMODULE hModule, CSysString &name)\r
+  {\r
+    const int length = MAX_PATH + 100;\r
+    DWORD resultLen = MyGetModuleFileNameEx(hModule, name.GetBuffer(length), length);\r
+    name.ReleaseBuffer();\r
+    return (resultLen != 0);\r
+  }\r
+\r
+  bool GetModuleInformation(HMODULE hModule, LPMODULEINFO moduleInfo)\r
+    { return BOOLToBool(::GetModuleInformation(_handle, hModule, moduleInfo, sizeof(MODULEINFO))); }\r
+  bool GetMemoryInfo(PPROCESS_MEMORY_COUNTERS memCounters)\r
+    { return BOOLToBool(::GetProcessMemoryInfo(_handle, memCounters, sizeof(PROCESS_MEMORY_COUNTERS))); }\r
+\r
+  #endif\r
+\r
+  WRes Create(LPCWSTR imageName, const UString &params, LPCWSTR curDir);\r
+\r
+  DWORD Wait() { return ::WaitForSingleObject(_handle, INFINITE); }\r
+};\r
+\r
+WRes MyCreateProcess(LPCWSTR imageName, const UString &params);\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/Windows/ProcessMessages.cpp b/CPP/Windows/ProcessMessages.cpp
new file mode 100755 (executable)
index 0000000..439d3fd
--- /dev/null
@@ -0,0 +1,22 @@
+// Windows/ProcessMessages.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "ProcessMessages.h"\r
+\r
+namespace NWindows {\r
+\r
+void ProcessMessages(HWND window)\r
+{\r
+  MSG msg;\r
+  while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )\r
+  {\r
+    if (window == (HWND) NULL || !IsDialogMessage(window, &msg))\r
+    {\r
+      TranslateMessage(&msg);\r
+      DispatchMessage(&msg);\r
+    }\r
+  }\r
+}\r
+\r
+}\r
diff --git a/CPP/Windows/ProcessMessages.h b/CPP/Windows/ProcessMessages.h
new file mode 100755 (executable)
index 0000000..082556a
--- /dev/null
@@ -0,0 +1,14 @@
+// Windows/ProcessMessages.h\r
+\r
+#ifndef __WINDOWS_PROCESSMESSAGES_H\r
+#define __WINDOWS_PROCESSMESSAGES_H\r
+\r
+namespace NWindows {\r
+\r
+void ProcessMessages(HWND window);\r
+\r
+}\r
+\r
+#endif\r
+\r
+\r
diff --git a/CPP/Windows/PropVariant.cpp b/CPP/Windows/PropVariant.cpp
new file mode 100755 (executable)
index 0000000..bcd85a5
--- /dev/null
@@ -0,0 +1,243 @@
+// Windows/PropVariant.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "PropVariant.h"\r
+\r
+#include "../Common/Defs.h"\r
+\r
+namespace NWindows {\r
+namespace NCOM {\r
+\r
+CPropVariant::CPropVariant(const PROPVARIANT &varSrc)\r
+{\r
+  vt = VT_EMPTY;\r
+  InternalCopy(&varSrc);\r
+}\r
+\r
+CPropVariant::CPropVariant(const CPropVariant &varSrc)\r
+{\r
+  vt = VT_EMPTY;\r
+  InternalCopy(&varSrc);\r
+}\r
+\r
+CPropVariant::CPropVariant(BSTR bstrSrc)\r
+{\r
+  vt = VT_EMPTY;\r
+  *this = bstrSrc;\r
+}\r
+\r
+CPropVariant::CPropVariant(LPCOLESTR lpszSrc)\r
+{\r
+  vt = VT_EMPTY;\r
+  *this = lpszSrc;\r
+}\r
+\r
+CPropVariant& CPropVariant::operator=(const CPropVariant &varSrc)\r
+{\r
+  InternalCopy(&varSrc);\r
+  return *this;\r
+}\r
+CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc)\r
+{\r
+  InternalCopy(&varSrc);\r
+  return *this;\r
+}\r
+\r
+CPropVariant& CPropVariant::operator=(BSTR bstrSrc)\r
+{\r
+  *this = (LPCOLESTR)bstrSrc;\r
+  return *this;\r
+}\r
+\r
+static const char *kMemException = "out of memory";\r
+\r
+CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc)\r
+{\r
+  InternalClear();\r
+  vt = VT_BSTR;\r
+  wReserved1 = 0;\r
+  bstrVal = ::SysAllocString(lpszSrc);\r
+  if (bstrVal == NULL && lpszSrc != NULL)\r
+  {\r
+    throw kMemException;\r
+    // vt = VT_ERROR;\r
+    // scode = E_OUTOFMEMORY;\r
+  }\r
+  return *this;\r
+}\r
+\r
+\r
+CPropVariant& CPropVariant::operator=(const char *s)\r
+{\r
+  InternalClear();\r
+  vt = VT_BSTR;\r
+  wReserved1 = 0;\r
+  UINT len = (UINT)strlen(s);\r
+  bstrVal = ::SysAllocStringByteLen(0, (UINT)len * sizeof(OLECHAR));\r
+  if (bstrVal == NULL)\r
+  {\r
+    throw kMemException;\r
+    // vt = VT_ERROR;\r
+    // scode = E_OUTOFMEMORY;\r
+  }\r
+  else\r
+  {\r
+    for (UINT i = 0; i <= len; i++)\r
+      bstrVal[i] = s[i];\r
+  }\r
+  return *this;\r
+}\r
+\r
+CPropVariant& CPropVariant::operator=(bool bSrc)\r
+{\r
+  if (vt != VT_BOOL)\r
+  {\r
+    InternalClear();\r
+    vt = VT_BOOL;\r
+  }\r
+  boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;\r
+  return *this;\r
+}\r
+\r
+#define SET_PROP_FUNC(type, id, dest) \\r
+  CPropVariant& CPropVariant::operator=(type value) \\r
+  { if (vt != id) { InternalClear(); vt = id; } \\r
+    dest = value; return *this; }\r
+\r
+SET_PROP_FUNC(Byte, VT_UI1, bVal)\r
+SET_PROP_FUNC(Int16, VT_I2, iVal)\r
+SET_PROP_FUNC(Int32, VT_I4, lVal)\r
+SET_PROP_FUNC(UInt32, VT_UI4, ulVal)\r
+SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart)\r
+SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime)\r
+\r
+static HRESULT MyPropVariantClear(PROPVARIANT *prop)\r
+{\r
+  switch(prop->vt)\r
+  {\r
+    case VT_UI1:\r
+    case VT_I1:\r
+    case VT_I2:\r
+    case VT_UI2:\r
+    case VT_BOOL:\r
+    case VT_I4:\r
+    case VT_UI4:\r
+    case VT_R4:\r
+    case VT_INT:\r
+    case VT_UINT:\r
+    case VT_ERROR:\r
+    case VT_FILETIME:\r
+    case VT_UI8:\r
+    case VT_R8:\r
+    case VT_CY:\r
+    case VT_DATE:\r
+      prop->vt = VT_EMPTY;\r
+      prop->wReserved1 = 0;\r
+      return S_OK;\r
+  }\r
+  return ::VariantClear((VARIANTARG *)prop);\r
+}\r
+\r
+HRESULT CPropVariant::Clear()\r
+{\r
+  return MyPropVariantClear(this);\r
+}\r
+\r
+HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc)\r
+{\r
+  ::VariantClear((tagVARIANT *)this);\r
+  switch(pSrc->vt)\r
+  {\r
+    case VT_UI1:\r
+    case VT_I1:\r
+    case VT_I2:\r
+    case VT_UI2:\r
+    case VT_BOOL:\r
+    case VT_I4:\r
+    case VT_UI4:\r
+    case VT_R4:\r
+    case VT_INT:\r
+    case VT_UINT:\r
+    case VT_ERROR:\r
+    case VT_FILETIME:\r
+    case VT_UI8:\r
+    case VT_R8:\r
+    case VT_CY:\r
+    case VT_DATE:\r
+      memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT));\r
+      return S_OK;\r
+  }\r
+  return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast<PROPVARIANT *>(pSrc));\r
+}\r
+\r
+\r
+HRESULT CPropVariant::Attach(PROPVARIANT *pSrc)\r
+{\r
+  HRESULT hr = Clear();\r
+  if (FAILED(hr))\r
+    return hr;\r
+  memcpy(this, pSrc, sizeof(PROPVARIANT));\r
+  pSrc->vt = VT_EMPTY;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CPropVariant::Detach(PROPVARIANT *pDest)\r
+{\r
+  HRESULT hr = MyPropVariantClear(pDest);\r
+  if (FAILED(hr))\r
+    return hr;\r
+  memcpy(pDest, this, sizeof(PROPVARIANT));\r
+  vt = VT_EMPTY;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT CPropVariant::InternalClear()\r
+{\r
+  HRESULT hr = Clear();\r
+  if (FAILED(hr))\r
+  {\r
+    vt = VT_ERROR;\r
+    scode = hr;\r
+  }\r
+  return hr;\r
+}\r
+\r
+void CPropVariant::InternalCopy(const PROPVARIANT *pSrc)\r
+{\r
+  HRESULT hr = Copy(pSrc);\r
+  if (FAILED(hr))\r
+  {\r
+    if (hr == E_OUTOFMEMORY)\r
+      throw kMemException;\r
+    vt = VT_ERROR;\r
+    scode = hr;\r
+  }\r
+}\r
+\r
+int CPropVariant::Compare(const CPropVariant &a)\r
+{\r
+  if (vt != a.vt)\r
+    return MyCompare(vt, a.vt);\r
+  switch (vt)\r
+  {\r
+    case VT_EMPTY: return 0;\r
+    // case VT_I1: return MyCompare(cVal, a.cVal);\r
+    case VT_UI1: return MyCompare(bVal, a.bVal);\r
+    case VT_I2: return MyCompare(iVal, a.iVal);\r
+    case VT_UI2: return MyCompare(uiVal, a.uiVal);\r
+    case VT_I4: return MyCompare(lVal, a.lVal);\r
+    case VT_UI4: return MyCompare(ulVal, a.ulVal);\r
+    // case VT_UINT: return MyCompare(uintVal, a.uintVal);\r
+    case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart);\r
+    case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart);\r
+    case VT_BOOL: return -MyCompare(boolVal, a.boolVal);\r
+    case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime);\r
+    case VT_BSTR:\r
+      return 0; // Not implemented\r
+      // return MyCompare(aPropVarint.cVal);\r
+    default: return 0;\r
+  }\r
+}\r
+\r
+}}\r
diff --git a/CPP/Windows/PropVariant.h b/CPP/Windows/PropVariant.h
new file mode 100755 (executable)
index 0000000..1605eec
--- /dev/null
@@ -0,0 +1,56 @@
+// Windows/PropVariant.h\r
+\r
+#ifndef __WINDOWS_PROPVARIANT_H\r
+#define __WINDOWS_PROPVARIANT_H\r
+\r
+#include "../Common/MyWindows.h"\r
+#include "../Common/Types.h"\r
+\r
+namespace NWindows {\r
+namespace NCOM {\r
+\r
+class CPropVariant : public tagPROPVARIANT\r
+{\r
+public:\r
+  CPropVariant() { vt = VT_EMPTY; wReserved1 = 0; }\r
+  ~CPropVariant() { Clear(); }\r
+  CPropVariant(const PROPVARIANT &varSrc);\r
+  CPropVariant(const CPropVariant &varSrc);\r
+  CPropVariant(BSTR bstrSrc);\r
+  CPropVariant(LPCOLESTR lpszSrc);\r
+  CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); };\r
+  CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; }\r
+  CPropVariant(Int16 value) { vt = VT_I2; wReserved1 = 0; iVal = value; }\r
+  CPropVariant(Int32 value) { vt = VT_I4; wReserved1 = 0; lVal = value; }\r
+  CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; }\r
+  CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal.QuadPart = value; }\r
+  CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; }\r
+\r
+  CPropVariant& operator=(const CPropVariant &varSrc);\r
+  CPropVariant& operator=(const PROPVARIANT &varSrc);\r
+  CPropVariant& operator=(BSTR bstrSrc);\r
+  CPropVariant& operator=(LPCOLESTR lpszSrc);\r
+  CPropVariant& operator=(const char *s);\r
+  CPropVariant& operator=(bool bSrc);\r
+  CPropVariant& operator=(Byte value);\r
+  CPropVariant& operator=(Int16 value);\r
+  CPropVariant& operator=(Int32 value);\r
+  CPropVariant& operator=(UInt32 value);\r
+  CPropVariant& operator=(Int64 value);\r
+  CPropVariant& operator=(UInt64 value);\r
+  CPropVariant& operator=(const FILETIME &value);\r
+\r
+  HRESULT Clear();\r
+  HRESULT Copy(const PROPVARIANT *pSrc);\r
+  HRESULT Attach(PROPVARIANT *pSrc);\r
+  HRESULT Detach(PROPVARIANT *pDest);\r
+\r
+  HRESULT InternalClear();\r
+  void InternalCopy(const PROPVARIANT *pSrc);\r
+\r
+  int Compare(const CPropVariant &a1);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/PropVariantConversions.cpp b/CPP/Windows/PropVariantConversions.cpp
new file mode 100755 (executable)
index 0000000..9d7c2a2
--- /dev/null
@@ -0,0 +1,105 @@
+// PropVariantConversions.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/IntToString.h"\r
+#include "Common/StringConvert.h"\r
+\r
+#include "Windows/Defs.h"\r
+\r
+#include "PropVariantConversions.h"\r
+\r
+static UString ConvertUInt64ToString(UInt64 value)\r
+{\r
+  wchar_t buffer[32];\r
+  ConvertUInt64ToString(value, buffer);\r
+  return buffer;\r
+}\r
+\r
+static UString ConvertInt64ToString(Int64 value)\r
+{\r
+  wchar_t buffer[32];\r
+  ConvertInt64ToString(value, buffer);\r
+  return buffer;\r
+}\r
+\r
+static char *UIntToStringSpec(char c, UInt32 value, char *s, int numPos)\r
+{\r
+  if (c != 0)\r
+    *s++ = c;\r
+  char temp[16];\r
+  int pos = 0;\r
+  do\r
+  {\r
+    temp[pos++] = (char)('0' + value % 10);\r
+    value /= 10;\r
+  }\r
+  while (value != 0);\r
+  int i;\r
+  for (i = 0; i < numPos - pos; i++)\r
+    *s++ = '0';\r
+  do\r
+    *s++ = temp[--pos];\r
+  while (pos > 0);\r
+  *s = '\0';\r
+  return s;\r
+}\r
+\r
+bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds)\r
+{\r
+  s[0] = '\0';\r
+  SYSTEMTIME st;\r
+  if (!BOOLToBool(FileTimeToSystemTime(&ft, &st)))\r
+    return false;\r
+  s = UIntToStringSpec(0, st.wYear, s, 4);\r
+  s = UIntToStringSpec('-', st.wMonth, s, 2);\r
+  s = UIntToStringSpec('-', st.wDay, s, 2);\r
+  if (includeTime)\r
+  {\r
+    s = UIntToStringSpec(' ', st.wHour, s, 2);\r
+    s = UIntToStringSpec(':', st.wMinute, s, 2);\r
+    if (includeSeconds)\r
+      UIntToStringSpec(':', st.wSecond, s, 2);\r
+  }\r
+  return true;\r
+}\r
+\r
+UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime, bool includeSeconds)\r
+{\r
+  char s[32];\r
+  ConvertFileTimeToString(ft, s, includeTime, includeSeconds);\r
+  return GetUnicodeString(s);\r
+}\r
\r
+\r
+UString ConvertPropVariantToString(const PROPVARIANT &prop)\r
+{\r
+  switch (prop.vt)\r
+  {\r
+    case VT_EMPTY: return UString();\r
+    case VT_BSTR: return prop.bstrVal;\r
+    case VT_UI1: return ConvertUInt64ToString(prop.bVal);\r
+    case VT_UI2: return ConvertUInt64ToString(prop.uiVal);\r
+    case VT_UI4: return ConvertUInt64ToString(prop.ulVal);\r
+    case VT_UI8: return ConvertUInt64ToString(prop.uhVal.QuadPart);\r
+    case VT_FILETIME: return ConvertFileTimeToString(prop.filetime, true, true);\r
+    // case VT_I1: return ConvertInt64ToString(prop.cVal);\r
+    case VT_I2: return ConvertInt64ToString(prop.iVal);\r
+    case VT_I4: return ConvertInt64ToString(prop.lVal);\r
+    case VT_I8: return ConvertInt64ToString(prop.hVal.QuadPart);\r
+    case VT_BOOL: return VARIANT_BOOLToBool(prop.boolVal) ? L"+" : L"-";\r
+    default: throw 150245;\r
+  }\r
+}\r
+\r
+UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &prop)\r
+{\r
+  switch (prop.vt)\r
+  {\r
+    case VT_UI1: return prop.bVal;\r
+    case VT_UI2: return prop.uiVal;\r
+    case VT_UI4: return prop.ulVal;\r
+    case VT_UI8: return (UInt64)prop.uhVal.QuadPart;\r
+    default: throw 151199;\r
+  }\r
+}\r
diff --git a/CPP/Windows/PropVariantConversions.h b/CPP/Windows/PropVariantConversions.h
new file mode 100755 (executable)
index 0000000..74139a4
--- /dev/null
@@ -0,0 +1,14 @@
+// Windows/PropVariantConversions.h\r
+\r
+#ifndef __PROP_VARIANT_CONVERSIONS_H\r
+#define __PROP_VARIANT_CONVERSIONS_H\r
+\r
+#include "Common/MyString.h"\r
+#include "Common/Types.h"\r
+\r
+bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true);\r
+UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime = true, bool includeSeconds = true);\r
+UString ConvertPropVariantToString(const PROPVARIANT &prop);\r
+UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &prop);\r
+\r
+#endif\r
diff --git a/CPP/Windows/PropVariantUtils.cpp b/CPP/Windows/PropVariantUtils.cpp
new file mode 100755 (executable)
index 0000000..a2ebd64
--- /dev/null
@@ -0,0 +1,78 @@
+// PropVariantUtils.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "PropVariantUtils.h"\r
+#include "Common/StringConvert.h"\r
+#include "Common/IntToString.h"\r
+\r
+using namespace NWindows;\r
+\r
+static AString GetHex(UInt32 v)\r
+{\r
+  char sz[32] = { '0', 'x' };\r
+  ConvertUInt64ToString(v, sz + 2, 16);\r
+  return sz;\r
+}\r
+\r
+void StringToProp(const AString &s, NCOM::CPropVariant &prop)\r
+{\r
+  prop = MultiByteToUnicodeString(s);\r
+}\r
+\r
+void PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NCOM::CPropVariant &prop)\r
+{\r
+  AString s;\r
+  for (unsigned i = 0; i < num; i++)\r
+  {\r
+    const CUInt32PCharPair &p = pairs[i];\r
+    if (p.Value == value)\r
+      s = p.Name;\r
+  }\r
+  if (s.IsEmpty())\r
+    s = GetHex(value);\r
+  StringToProp(s, prop);\r
+}\r
+\r
+AString TypeToString(const char *table[], unsigned num, UInt32 value)\r
+{\r
+  if (value < num)\r
+    return table[value];\r
+  return GetHex(value);\r
+}\r
+\r
+void TypeToProp(const char *table[], unsigned num, UInt32 value, NCOM::CPropVariant &prop)\r
+{\r
+  StringToProp(TypeToString(table, num, value), prop);\r
+}\r
+\r
+\r
+AString FlagsToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags)\r
+{\r
+  AString s;\r
+  for (unsigned i = 0; i < num; i++)\r
+  {\r
+    const CUInt32PCharPair &p = pairs[i];\r
+    UInt32 flag = (UInt32)1 << (unsigned)p.Value;\r
+    if ((flags & flag) != 0)\r
+    {\r
+      if (!s.IsEmpty())\r
+        s += ' ';\r
+      s += p.Name;\r
+    }\r
+    flags &= ~flag;\r
+  }\r
+  if (flags != 0)\r
+  {\r
+    if (!s.IsEmpty())\r
+      s += ' ';\r
+    s += GetHex(flags);\r
+  }\r
+  return s;\r
+}\r
+\r
+void FlagsToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags, NCOM::CPropVariant &prop)\r
+{\r
+  StringToProp(FlagsToString(pairs, num, flags), prop);\r
+}\r
+\r
diff --git a/CPP/Windows/PropVariantUtils.h b/CPP/Windows/PropVariantUtils.h
new file mode 100755 (executable)
index 0000000..88025c5
--- /dev/null
@@ -0,0 +1,28 @@
+// Windows/PropVariantUtils.h\r
+\r
+#ifndef __PROP_VARIANT_UTILS_H\r
+#define __PROP_VARIANT_UTILS_H\r
+\r
+#include "Common/MyString.h"\r
+#include "PropVariant.h"\r
+\r
+struct CUInt32PCharPair\r
+{\r
+  UInt32 Value;\r
+  const char *Name;\r
+};\r
+\r
+void StringToProp(const AString &s, NWindows::NCOM::CPropVariant &prop);\r
+void PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NWindows::NCOM::CPropVariant &prop);\r
+\r
+AString FlagsToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags);\r
+void FlagsToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags, NWindows::NCOM::CPropVariant &prop);\r
+\r
+AString TypeToString(const char *table[], unsigned num, UInt32 value);\r
+void TypeToProp(const char *table[], unsigned num, UInt32 value, NWindows::NCOM::CPropVariant &prop);\r
+\r
+#define PAIR_TO_PROP(pairs, value, prop) PairToProp(pairs, sizeof(pairs) / sizeof(pairs[0]), value, prop)\r
+#define FLAGS_TO_PROP(pairs, value, prop) FlagsToProp(pairs, sizeof(pairs) / sizeof(pairs[0]), value, prop)\r
+#define TYPE_TO_PROP(table, value, prop) TypeToProp(table, sizeof(table) / sizeof(table[0]), value, prop)\r
+\r
+#endif\r
diff --git a/CPP/Windows/Registry.cpp b/CPP/Windows/Registry.cpp
new file mode 100755 (executable)
index 0000000..3db00ea
--- /dev/null
@@ -0,0 +1,369 @@
+// Windows/Registry.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#ifndef _UNICODE\r
+#include "Common/StringConvert.h"\r
+#endif\r
+#include "Windows/Registry.h"\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+namespace NWindows {\r
+namespace NRegistry {\r
+\r
+#define MYASSERT(expr) // _ASSERTE(expr)\r
+\r
+LONG CKey::Create(HKEY parentKey, LPCTSTR keyName,\r
+    LPTSTR keyClass, DWORD options, REGSAM accessMask,\r
+    LPSECURITY_ATTRIBUTES securityAttributes, LPDWORD disposition)\r
+{\r
+  MYASSERT(parentKey != NULL);\r
+  DWORD dispositionReal;\r
+  HKEY key = NULL;\r
+  LONG res = RegCreateKeyEx(parentKey, keyName, 0, keyClass,\r
+      options, accessMask, securityAttributes, &key, &dispositionReal);\r
+  if (disposition != NULL)\r
+    *disposition = dispositionReal;\r
+  if (res == ERROR_SUCCESS)\r
+  {\r
+    res = Close();\r
+    _object = key;\r
+  }\r
+  return res;\r
+}\r
+\r
+LONG CKey::Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask)\r
+{\r
+  MYASSERT(parentKey != NULL);\r
+  HKEY key = NULL;\r
+  LONG res = RegOpenKeyEx(parentKey, keyName, 0, accessMask, &key);\r
+  if (res == ERROR_SUCCESS)\r
+  {\r
+    res = Close();\r
+    MYASSERT(res == ERROR_SUCCESS);\r
+    _object = key;\r
+  }\r
+  return res;\r
+}\r
+\r
+LONG CKey::Close()\r
+{\r
+  LONG res = ERROR_SUCCESS;\r
+  if (_object != NULL)\r
+  {\r
+    res = RegCloseKey(_object);\r
+    _object = NULL;\r
+  }\r
+  return res;\r
+}\r
+\r
+// win95, win98: deletes sunkey and all its subkeys\r
+// winNT to be deleted must not have subkeys\r
+LONG CKey::DeleteSubKey(LPCTSTR subKeyName)\r
+{\r
+  MYASSERT(_object != NULL);\r
+  return RegDeleteKey(_object, subKeyName);\r
+}\r
+\r
+LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName)\r
+{\r
+  CKey key;\r
+  LONG res = key.Open(_object, subKeyName, KEY_READ | KEY_WRITE);\r
+  if (res != ERROR_SUCCESS)\r
+    return res;\r
+  FILETIME fileTime;\r
+  const UInt32 kBufferSize = MAX_PATH + 1; // 256 in ATL\r
+  DWORD size = kBufferSize;\r
+  TCHAR buffer[kBufferSize];\r
+  while (RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime) == ERROR_SUCCESS)\r
+  {\r
+    res = key.RecurseDeleteKey(buffer);\r
+    if (res != ERROR_SUCCESS)\r
+      return res;\r
+    size = kBufferSize;\r
+  }\r
+  key.Close();\r
+  return DeleteSubKey(subKeyName);\r
+}\r
+\r
+\r
+/////////////////////////\r
+// Value Functions\r
+\r
+static inline UInt32 BoolToUINT32(bool value) {  return (value ? 1: 0); }\r
+static inline bool UINT32ToBool(UInt32 value) {  return (value != 0); }\r
+\r
+\r
+LONG CKey::DeleteValue(LPCTSTR name)\r
+{\r
+  MYASSERT(_object != NULL);\r
+  return ::RegDeleteValue(_object, name);\r
+}\r
+\r
+#ifndef _UNICODE\r
+LONG CKey::DeleteValue(LPCWSTR name)\r
+{\r
+  MYASSERT(_object != NULL);\r
+  if (g_IsNT)\r
+    return ::RegDeleteValueW(_object, name);\r
+  return DeleteValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name));\r
+}\r
+#endif\r
+\r
+LONG CKey::SetValue(LPCTSTR name, UInt32 value)\r
+{\r
+  MYASSERT(_object != NULL);\r
+  return RegSetValueEx(_object, name, NULL, REG_DWORD,\r
+      (BYTE * const)&value, sizeof(UInt32));\r
+}\r
+\r
+LONG CKey::SetValue(LPCTSTR name, bool value)\r
+{\r
+  return SetValue(name, BoolToUINT32(value));\r
+}\r
+\r
+LONG CKey::SetValue(LPCTSTR name, LPCTSTR value)\r
+{\r
+  MYASSERT(value != NULL);\r
+  MYASSERT(_object != NULL);\r
+  return RegSetValueEx(_object, name, NULL, REG_SZ,\r
+      (const BYTE * )value, (lstrlen(value) + 1) * sizeof(TCHAR));\r
+}\r
+\r
+/*\r
+LONG CKey::SetValue(LPCTSTR name, const CSysString &value)\r
+{\r
+  MYASSERT(value != NULL);\r
+  MYASSERT(_object != NULL);\r
+  return RegSetValueEx(_object, name, NULL, REG_SZ,\r
+      (const BYTE *)(const TCHAR *)value, (value.Length() + 1) * sizeof(TCHAR));\r
+}\r
+*/\r
+\r
+#ifndef _UNICODE\r
+\r
+LONG CKey::SetValue(LPCWSTR name, LPCWSTR value)\r
+{\r
+  MYASSERT(value != NULL);\r
+  MYASSERT(_object != NULL);\r
+  if (g_IsNT)\r
+    return RegSetValueExW(_object, name, NULL, REG_SZ,\r
+      (const BYTE * )value, (DWORD)((wcslen(value) + 1) * sizeof(wchar_t)));\r
+  return SetValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name),\r
+    value == 0 ? 0 : (LPCSTR)GetSystemString(value));\r
+}\r
+\r
+#endif\r
+\r
+\r
+LONG CKey::SetValue(LPCTSTR name, const void *value, UInt32 size)\r
+{\r
+  MYASSERT(value != NULL);\r
+  MYASSERT(_object != NULL);\r
+  return RegSetValueEx(_object, name, NULL, REG_BINARY,\r
+      (const BYTE *)value, size);\r
+}\r
+\r
+LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value)\r
+{\r
+  MYASSERT(value != NULL);\r
+  CKey key;\r
+  LONG res = key.Create(parentKey, keyName);\r
+  if (res == ERROR_SUCCESS)\r
+    res = key.SetValue(valueName, value);\r
+  return res;\r
+}\r
+\r
+LONG CKey::SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value)\r
+{\r
+  MYASSERT(value != NULL);\r
+  CKey key;\r
+  LONG res = key.Create(_object, keyName);\r
+  if (res == ERROR_SUCCESS)\r
+    res = key.SetValue(valueName, value);\r
+  return res;\r
+}\r
+\r
+LONG CKey::QueryValue(LPCTSTR name, UInt32 &value)\r
+{\r
+  DWORD type = NULL;\r
+  DWORD count = sizeof(DWORD);\r
+  LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type,\r
+    (LPBYTE)&value, &count);\r
+  MYASSERT((res!=ERROR_SUCCESS) || (type == REG_DWORD));\r
+  MYASSERT((res!=ERROR_SUCCESS) || (count == sizeof(UInt32)));\r
+  return res;\r
+}\r
+\r
+LONG CKey::QueryValue(LPCTSTR name, bool &value)\r
+{\r
+  UInt32 uintValue = BoolToUINT32(value);\r
+  LONG res = QueryValue(name, uintValue);\r
+  value = UINT32ToBool(uintValue);\r
+  return res;\r
+}\r
+\r
+LONG CKey::GetValue_IfOk(LPCTSTR name, UInt32 &value)\r
+{\r
+  UInt32 newVal;\r
+  LONG res = QueryValue(name, newVal);\r
+  if (res == ERROR_SUCCESS)\r
+    value = newVal;\r
+  return res;\r
+}\r
+\r
+LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value)\r
+{\r
+  bool newVal;\r
+  LONG res = QueryValue(name, newVal);\r
+  if (res == ERROR_SUCCESS)\r
+    value = newVal;\r
+  return res;\r
+}\r
+\r
+LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count)\r
+{\r
+  MYASSERT(count != NULL);\r
+  DWORD type = NULL;\r
+  LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count);\r
+  MYASSERT((res!=ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));\r
+  return res;\r
+}\r
+\r
+LONG CKey::QueryValue(LPCTSTR name, CSysString &value)\r
+{\r
+  value.Empty();\r
+  DWORD type = NULL;\r
+  UInt32 currentSize = 0;\r
+  LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&currentSize);\r
+  if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)\r
+    return res;\r
+  res = QueryValue(name, value.GetBuffer(currentSize), currentSize);\r
+  value.ReleaseBuffer();\r
+  return res;\r
+}\r
+\r
+#ifndef _UNICODE\r
+LONG CKey::QueryValue(LPCWSTR name, LPWSTR value, UInt32 &count)\r
+{\r
+  MYASSERT(count != NULL);\r
+  DWORD type = NULL;\r
+  LONG res = RegQueryValueExW(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count);\r
+  MYASSERT((res!=ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));\r
+  return res;\r
+}\r
+LONG CKey::QueryValue(LPCWSTR name, UString &value)\r
+{\r
+  value.Empty();\r
+  DWORD type = NULL;\r
+  UInt32 currentSize = 0;\r
+\r
+  LONG res;\r
+  if (g_IsNT)\r
+  {\r
+    res = RegQueryValueExW(_object, name, NULL, &type, NULL, (DWORD *)&currentSize);\r
+    if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)\r
+      return res;\r
+    res = QueryValue(name, value.GetBuffer(currentSize), currentSize);\r
+    value.ReleaseBuffer();\r
+  }\r
+  else\r
+  {\r
+    AString vTemp;\r
+    res = QueryValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), vTemp);\r
+    value = GetUnicodeString(vTemp);\r
+  }\r
+  return res;\r
+}\r
+#endif\r
+\r
+LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count)\r
+{\r
+  DWORD type = NULL;\r
+  LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count);\r
+  MYASSERT((res!=ERROR_SUCCESS) || (type == REG_BINARY));\r
+  return res;\r
+}\r
+\r
+\r
+LONG CKey::QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize)\r
+{\r
+  DWORD type = NULL;\r
+  dataSize = 0;\r
+  LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&dataSize);\r
+  if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)\r
+    return res;\r
+  value.SetCapacity(dataSize);\r
+  return QueryValue(name, (BYTE *)value, dataSize);\r
+}\r
+\r
+LONG CKey::EnumKeys(CSysStringVector &keyNames)\r
+{\r
+  keyNames.Clear();\r
+  CSysString keyName;\r
+  for (UInt32 index = 0; ; index++)\r
+  {\r
+    const UInt32 kBufferSize = MAX_PATH + 1; // 256 in ATL\r
+    FILETIME lastWriteTime;\r
+    UInt32 nameSize = kBufferSize;\r
+    LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuffer(kBufferSize),\r
+        (DWORD *)&nameSize, NULL, NULL, NULL, &lastWriteTime);\r
+    keyName.ReleaseBuffer();\r
+    if (result == ERROR_NO_MORE_ITEMS)\r
+      break;\r
+    if (result != ERROR_SUCCESS)\r
+      return result;\r
+    keyNames.Add(keyName);\r
+  }\r
+  return ERROR_SUCCESS;\r
+}\r
+\r
+LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings)\r
+{\r
+  UInt32 numChars = 0;\r
+  int i;\r
+  for (i = 0; i < strings.Size(); i++)\r
+    numChars += strings[i].Length() + 1;\r
+  CBuffer<wchar_t> buffer;\r
+  buffer.SetCapacity(numChars);\r
+  int pos = 0;\r
+  for (i = 0; i < strings.Size(); i++)\r
+  {\r
+    const UString &s = strings[i];\r
+    MyStringCopy((wchar_t *)buffer + pos, (const wchar_t *)s);\r
+    pos += s.Length() + 1;\r
+  }\r
+  return SetValue(valueName, buffer, numChars * sizeof(wchar_t));\r
+}\r
+\r
+LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings)\r
+{\r
+  strings.Clear();\r
+  CByteBuffer buffer;\r
+  UInt32 dataSize;\r
+  LONG res = QueryValue(valueName, buffer, dataSize);\r
+  if (res != ERROR_SUCCESS)\r
+    return res;\r
+  if (dataSize % sizeof(wchar_t) != 0)\r
+    return E_FAIL;\r
+  const wchar_t *data = (const wchar_t *)(const Byte  *)buffer;\r
+  int numChars = dataSize / sizeof(wchar_t);\r
+  UString s;\r
+  for (int i = 0; i < numChars; i++)\r
+  {\r
+    wchar_t c = data[i];\r
+    if (c == 0)\r
+    {\r
+      strings.Add(s);\r
+      s.Empty();\r
+    }\r
+    else\r
+      s += c;\r
+  }\r
+  return res;\r
+}\r
+\r
+}}\r
diff --git a/CPP/Windows/Registry.h b/CPP/Windows/Registry.h
new file mode 100755 (executable)
index 0000000..8f4ede3
--- /dev/null
@@ -0,0 +1,85 @@
+// Windows/Registry.h\r
+\r
+#ifndef __WINDOWS_REGISTRY_H\r
+#define __WINDOWS_REGISTRY_H\r
+\r
+#include "Common/Buffer.h"\r
+#include "Common/MyString.h"\r
+#include "Common/Types.h"\r
+\r
+namespace NWindows {\r
+namespace NRegistry {\r
+\r
+LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value);\r
+\r
+class CKey\r
+{\r
+  HKEY _object;\r
+public:\r
+  CKey(): _object(NULL) {}\r
+  ~CKey() { Close(); }\r
+\r
+  operator HKEY() const { return _object; }\r
+  void Attach(HKEY key) { _object = key; }\r
+  HKEY Detach()\r
+  {\r
+    HKEY key = _object;\r
+    _object = NULL;\r
+    return key;\r
+  }\r
+\r
+  LONG Create(HKEY parentKey, LPCTSTR keyName,\r
+      LPTSTR keyClass = REG_NONE, DWORD options = REG_OPTION_NON_VOLATILE,\r
+      REGSAM accessMask = KEY_ALL_ACCESS,\r
+      LPSECURITY_ATTRIBUTES securityAttributes = NULL,\r
+      LPDWORD disposition = NULL);\r
+  LONG Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask = KEY_ALL_ACCESS);\r
+\r
+  LONG Close();\r
+\r
+  LONG DeleteSubKey(LPCTSTR subKeyName);\r
+  LONG RecurseDeleteKey(LPCTSTR subKeyName);\r
+\r
+  LONG DeleteValue(LPCTSTR name);\r
+  #ifndef _UNICODE\r
+  LONG DeleteValue(LPCWSTR name);\r
+  #endif\r
+\r
+  LONG SetValue(LPCTSTR valueName, UInt32 value);\r
+  LONG SetValue(LPCTSTR valueName, bool value);\r
+  LONG SetValue(LPCTSTR valueName, LPCTSTR value);\r
+  // LONG SetValue(LPCTSTR valueName, const CSysString &value);\r
+  #ifndef _UNICODE\r
+  LONG SetValue(LPCWSTR name, LPCWSTR value);\r
+  // LONG SetValue(LPCWSTR name, const UString &value);\r
+  #endif\r
+\r
+  LONG SetValue(LPCTSTR name, const void *value, UInt32 size);\r
+\r
+  LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings);\r
+  LONG GetValue_Strings(LPCTSTR valueName, UStringVector &strings);\r
+\r
+  LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value);\r
+\r
+  LONG QueryValue(LPCTSTR name, UInt32 &value);\r
+  LONG QueryValue(LPCTSTR name, bool &value);\r
+  LONG QueryValue(LPCTSTR name, LPTSTR value, UInt32 &dataSize);\r
+  LONG QueryValue(LPCTSTR name, CSysString &value);\r
+\r
+  LONG GetValue_IfOk(LPCTSTR name, UInt32 &value);\r
+  LONG GetValue_IfOk(LPCTSTR name, bool &value);\r
+\r
+  #ifndef _UNICODE\r
+  LONG QueryValue(LPCWSTR name, LPWSTR value, UInt32 &dataSize);\r
+  LONG QueryValue(LPCWSTR name, UString &value);\r
+  #endif\r
+\r
+  LONG QueryValue(LPCTSTR name, void *value, UInt32 &dataSize);\r
+  LONG QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize);\r
+\r
+  LONG EnumKeys(CSysStringVector &keyNames);\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/ResourceString.cpp b/CPP/Windows/ResourceString.cpp
new file mode 100755 (executable)
index 0000000..83b7c23
--- /dev/null
@@ -0,0 +1,64 @@
+// Windows/ResourceString.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/ResourceString.h"\r
+#ifndef _UNICODE\r
+#include "Common/StringConvert.h"\r
+#endif\r
+\r
+extern HINSTANCE g_hInstance;\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+namespace NWindows {\r
+\r
+CSysString MyLoadString(HINSTANCE hInstance, UINT resourceID)\r
+{\r
+  CSysString s;\r
+  int size = 256;\r
+  int len;\r
+  do\r
+  {\r
+    size += 256;\r
+    len = ::LoadString(hInstance, resourceID, s.GetBuffer(size - 1), size);\r
+  }\r
+  while (size - len <= 1);\r
+  s.ReleaseBuffer();\r
+  return s;\r
+}\r
+\r
+CSysString MyLoadString(UINT resourceID)\r
+{\r
+  return MyLoadString(g_hInstance, resourceID);\r
+}\r
+\r
+#ifndef _UNICODE\r
+UString MyLoadStringW(HINSTANCE hInstance, UINT resourceID)\r
+{\r
+  if (g_IsNT)\r
+  {\r
+    UString s;\r
+    int size = 256;\r
+    int len;\r
+    do\r
+    {\r
+      size += 256;\r
+      len = ::LoadStringW(hInstance, resourceID, s.GetBuffer(size - 1), size);\r
+    }\r
+    while (size - len <= 1);\r
+    s.ReleaseBuffer();\r
+    return s;\r
+  }\r
+  return GetUnicodeString(MyLoadString(hInstance, resourceID));\r
+}\r
+\r
+UString MyLoadStringW(UINT resourceID)\r
+{\r
+  return MyLoadStringW(g_hInstance, resourceID);\r
+}\r
+\r
+#endif\r
+\r
+}\r
diff --git a/CPP/Windows/ResourceString.h b/CPP/Windows/ResourceString.h
new file mode 100755 (executable)
index 0000000..fd49286
--- /dev/null
@@ -0,0 +1,22 @@
+// Windows/ResourceString.h\r
+\r
+#ifndef __WINDOWS_RESOURCESTRING_H\r
+#define __WINDOWS_RESOURCESTRING_H\r
+\r
+#include "Common/MyString.h"\r
+\r
+namespace NWindows {\r
+\r
+CSysString MyLoadString(HINSTANCE hInstance, UINT resourceID);\r
+CSysString MyLoadString(UINT resourceID);\r
+#ifdef _UNICODE\r
+inline UString MyLoadStringW(HINSTANCE hInstance, UINT resourceID) { return MyLoadString(hInstance, resourceID); }\r
+inline UString MyLoadStringW(UINT resourceID) { return MyLoadString(resourceID); }\r
+#else\r
+UString MyLoadStringW(HINSTANCE hInstance, UINT resourceID);\r
+UString MyLoadStringW(UINT resourceID);\r
+#endif\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Security.cpp b/CPP/Windows/Security.cpp
new file mode 100755 (executable)
index 0000000..a762f07
--- /dev/null
@@ -0,0 +1,179 @@
+// Windows/Security.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Security.h"\r
+\r
+namespace NWindows {\r
+namespace NSecurity {\r
+\r
+/*\r
+bool MyLookupAccountSid(LPCTSTR systemName, PSID sid,\r
+  CSysString &accountName, CSysString &domainName, PSID_NAME_USE sidNameUse)\r
+{\r
+  DWORD accountNameSize = 0, domainNameSize = 0;\r
+\r
+  if (!::LookupAccountSid(systemName, sid,\r
+      accountName.GetBuffer(0), &accountNameSize,\r
+      domainName.GetBuffer(0), &domainNameSize, sidNameUse))\r
+  {\r
+    if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)\r
+      return false;\r
+  }\r
+  bool result = BOOLToBool(::LookupAccountSid(systemName, sid,\r
+      accountName.GetBuffer(accountNameSize), &accountNameSize,\r
+      domainName.GetBuffer(domainNameSize), &domainNameSize, sidNameUse));\r
+  accountName.ReleaseBuffer();\r
+  domainName.ReleaseBuffer();\r
+  return result;\r
+}\r
+*/\r
+  \r
+static void SetLsaString(LPWSTR src, PLSA_UNICODE_STRING dest)\r
+{\r
+  int len = (int)wcslen(src);\r
+  dest->Length = (USHORT)(len * sizeof(WCHAR));\r
+  dest->MaximumLength = (USHORT)((len + 1) * sizeof(WCHAR));\r
+  dest->Buffer = src;\r
+}\r
+\r
+/*\r
+static void MyLookupSids(CPolicy &policy, PSID ps)\r
+{\r
+  LSA_REFERENCED_DOMAIN_LIST *referencedDomains = NULL;\r
+  LSA_TRANSLATED_NAME *names = NULL;\r
+  NTSTATUS nts = policy.LookupSids(1, &ps, &referencedDomains, &names);\r
+  int res = LsaNtStatusToWinError(nts);\r
+  LsaFreeMemory(referencedDomains);\r
+  LsaFreeMemory(names);\r
+}\r
+*/\r
+\r
+#ifndef _UNICODE\r
+typedef BOOL (WINAPI * LookupAccountNameWP)(\r
+    LPCWSTR lpSystemName,\r
+    LPCWSTR lpAccountName,\r
+    PSID Sid,\r
+    LPDWORD cbSid,\r
+    LPWSTR ReferencedDomainName,\r
+    LPDWORD cchReferencedDomainName,\r
+    PSID_NAME_USE peUse\r
+    );\r
+#endif\r
+\r
+static PSID GetSid(LPWSTR accountName)\r
+{\r
+  #ifndef _UNICODE\r
+  HMODULE hModule = GetModuleHandle(TEXT("Advapi32.dll"));\r
+  if (hModule == NULL)\r
+    return NULL;\r
+  LookupAccountNameWP lookupAccountNameW = (LookupAccountNameWP)GetProcAddress(hModule, "LookupAccountNameW");\r
+  if (lookupAccountNameW == NULL)\r
+    return NULL;\r
+  #endif\r
+\r
+  DWORD sidLen = 0, domainLen = 0;\r
+  SID_NAME_USE sidNameUse;\r
+  if (!\r
+    #ifdef _UNICODE\r
+    ::LookupAccountNameW\r
+    #else\r
+    lookupAccountNameW\r
+    #endif\r
+    (NULL, accountName, NULL, &sidLen, NULL, &domainLen, &sidNameUse))\r
+  {\r
+    if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)\r
+    {\r
+      PSID pSid = ::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sidLen);\r
+      LPWSTR domainName = (LPWSTR)::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (domainLen + 1) * sizeof(WCHAR));\r
+      BOOL res =\r
+        #ifdef _UNICODE\r
+        ::LookupAccountNameW\r
+        #else\r
+        lookupAccountNameW\r
+        #endif\r
+        (NULL, accountName, pSid, &sidLen, domainName, &domainLen, &sidNameUse);\r
+      ::HeapFree(GetProcessHeap(), 0, domainName);\r
+      if (res)\r
+        return pSid;\r
+    }\r
+  }\r
+  return NULL;\r
+}\r
+\r
+#define MY__SE_LOCK_MEMORY_NAME L"SeLockMemoryPrivilege"\r
+\r
+bool AddLockMemoryPrivilege()\r
+{\r
+  CPolicy policy;\r
+  LSA_OBJECT_ATTRIBUTES attr;\r
+  attr.Length = sizeof(attr);\r
+  attr.RootDirectory = NULL;\r
+  attr.ObjectName  = NULL;\r
+  attr.Attributes = 0;\r
+  attr.SecurityDescriptor = NULL;\r
+  attr.SecurityQualityOfService  = NULL;\r
+  if (policy.Open(NULL, &attr,\r
+      // GENERIC_WRITE)\r
+      POLICY_ALL_ACCESS)\r
+      // STANDARD_RIGHTS_REQUIRED,\r
+      // GENERIC_READ | GENERIC_EXECUTE | POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES)\r
+      != 0)\r
+    return false;\r
+  LSA_UNICODE_STRING userRights;\r
+  wchar_t s[128] = MY__SE_LOCK_MEMORY_NAME;\r
+  SetLsaString(s, &userRights);\r
+  WCHAR userName[256 + 2];\r
+  DWORD size = 256;\r
+  if (!GetUserNameW(userName, &size))\r
+    return false;\r
+  PSID psid = GetSid(userName);\r
+  if (psid == NULL)\r
+    return false;\r
+  bool res = false;\r
+\r
+  /*\r
+  PLSA_UNICODE_STRING userRightsArray;\r
+  ULONG countOfRights;\r
+  NTSTATUS status = policy.EnumerateAccountRights(psid, &userRightsArray, &countOfRights);\r
+  if (status != 0)\r
+    return false;\r
+  bool finded = false;\r
+  for (ULONG i = 0; i < countOfRights; i++)\r
+  {\r
+    LSA_UNICODE_STRING &ur = userRightsArray[i];\r
+    if (ur.Length != s.Length() * sizeof(WCHAR))\r
+      continue;\r
+    if (wcsncmp(ur.Buffer, s, s.Length()) != 0)\r
+      continue;\r
+    finded = true;\r
+    res = true;\r
+    break;\r
+  }\r
+  if (!finded)\r
+  */\r
+  {\r
+    /*\r
+    LSA_ENUMERATION_INFORMATION *enums;\r
+    ULONG countReturned;\r
+    NTSTATUS status = policy.EnumerateAccountsWithUserRight(&userRights, &enums, &countReturned);\r
+    if (status == 0)\r
+    {\r
+      for (ULONG i = 0; i < countReturned; i++)\r
+        MyLookupSids(policy, enums[i].Sid);\r
+      if (enums)\r
+        ::LsaFreeMemory(enums);\r
+      res = true;\r
+    }\r
+    */\r
+    NTSTATUS status = policy.AddAccountRights(psid, &userRights);\r
+    if (status == 0)\r
+      res = true;\r
+    // ULONG res = LsaNtStatusToWinError(status);\r
+  }\r
+  HeapFree(GetProcessHeap(), 0, psid);\r
+  return res;\r
+}\r
+\r
+}}\r
+\r
diff --git a/CPP/Windows/Security.h b/CPP/Windows/Security.h
new file mode 100755 (executable)
index 0000000..8a88777
--- /dev/null
@@ -0,0 +1,167 @@
+// Windows/Security.h\r
+\r
+#ifndef __WINDOWS_SECURITY_H\r
+#define __WINDOWS_SECURITY_H\r
+\r
+#include <NTSecAPI.h>\r
+\r
+#include "Defs.h"\r
+\r
+namespace NWindows {\r
+namespace NSecurity {\r
+\r
+class CAccessToken\r
+{\r
+  HANDLE _handle;\r
+public:\r
+  CAccessToken(): _handle(NULL) {};\r
+  ~CAccessToken() { Close(); }\r
+  bool Close()\r
+  {\r
+    if (_handle == NULL)\r
+      return true;\r
+    bool res = BOOLToBool(::CloseHandle(_handle));\r
+    if (res)\r
+      _handle = NULL;\r
+    return res;\r
+  }\r
+\r
+  bool OpenProcessToken(HANDLE processHandle, DWORD desiredAccess)\r
+  {\r
+    Close();\r
+    return BOOLToBool(::OpenProcessToken(processHandle, desiredAccess, &_handle));\r
+  }\r
+\r
+  /*\r
+  bool OpenThreadToken(HANDLE threadHandle, DWORD desiredAccess, bool openAsSelf)\r
+  {\r
+    Close();\r
+    return BOOLToBool(::OpenTreadToken(threadHandle, desiredAccess, BoolToBOOL(anOpenAsSelf), &_handle));\r
+  }\r
+  */\r
+\r
+  bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState,\r
+      DWORD bufferLength, PTOKEN_PRIVILEGES previousState, PDWORD returnLength)\r
+    { return BOOLToBool(::AdjustTokenPrivileges(_handle, BoolToBOOL(disableAllPrivileges),\r
+      newState, bufferLength, previousState, returnLength)); }\r
+  \r
+  bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState)\r
+    { return AdjustPrivileges(disableAllPrivileges, newState, 0, NULL, NULL); }\r
+  \r
+  bool AdjustPrivileges(PTOKEN_PRIVILEGES newState)\r
+    { return AdjustPrivileges(false, newState); }\r
+\r
+};\r
+\r
+#ifndef _UNICODE\r
+typedef NTSTATUS (NTAPI *LsaOpenPolicyP)(PLSA_UNICODE_STRING SystemName,\r
+    PLSA_OBJECT_ATTRIBUTES ObjectAttributes, ACCESS_MASK DesiredAccess, PLSA_HANDLE PolicyHandle);\r
+typedef NTSTATUS (NTAPI *LsaCloseP)(LSA_HANDLE ObjectHandle);\r
+typedef NTSTATUS (NTAPI *LsaAddAccountRightsP)(LSA_HANDLE PolicyHandle,\r
+    PSID AccountSid, PLSA_UNICODE_STRING UserRights, ULONG CountOfRights );\r
+#define MY_STATUS_NOT_IMPLEMENTED           ((NTSTATUS)0xC0000002L)\r
+#endif\r
+\r
+struct CPolicy\r
+{\r
+protected:\r
+  LSA_HANDLE _handle;\r
+  #ifndef _UNICODE\r
+  HMODULE hModule;\r
+  #endif\r
+public:\r
+  operator LSA_HANDLE() const { return _handle; }\r
+  CPolicy(): _handle(NULL)\r
+  {\r
+    #ifndef _UNICODE\r
+    hModule = GetModuleHandle(TEXT("Advapi32.dll"));\r
+    #endif\r
+  };\r
+  ~CPolicy() { Close(); }\r
+\r
+  NTSTATUS Open(PLSA_UNICODE_STRING systemName, PLSA_OBJECT_ATTRIBUTES objectAttributes,\r
+      ACCESS_MASK desiredAccess)\r
+  {\r
+    #ifndef _UNICODE\r
+    if (hModule == NULL)\r
+      return MY_STATUS_NOT_IMPLEMENTED;\r
+    LsaOpenPolicyP lsaOpenPolicy = (LsaOpenPolicyP)GetProcAddress(hModule, "LsaOpenPolicy");\r
+    if (lsaOpenPolicy == NULL)\r
+      return MY_STATUS_NOT_IMPLEMENTED;\r
+    #endif\r
+\r
+    Close();\r
+    return\r
+      #ifdef _UNICODE\r
+      ::LsaOpenPolicy\r
+      #else\r
+      lsaOpenPolicy\r
+      #endif\r
+      (systemName, objectAttributes, desiredAccess, &_handle);\r
+  }\r
+  \r
+  NTSTATUS Close()\r
+  {\r
+    if (_handle == NULL)\r
+      return 0;\r
+\r
+    #ifndef _UNICODE\r
+    if (hModule == NULL)\r
+      return MY_STATUS_NOT_IMPLEMENTED;\r
+    LsaCloseP lsaClose = (LsaCloseP)GetProcAddress(hModule, "LsaClose");\r
+    if (lsaClose == NULL)\r
+      return MY_STATUS_NOT_IMPLEMENTED;\r
+    #endif\r
+\r
+    NTSTATUS res =\r
+      #ifdef _UNICODE\r
+      ::LsaClose\r
+      #else\r
+      lsaClose\r
+      #endif\r
+      (_handle);\r
+    _handle = NULL;\r
+    return res;\r
+  }\r
+  \r
+  NTSTATUS EnumerateAccountsWithUserRight(PLSA_UNICODE_STRING userRights,\r
+      PLSA_ENUMERATION_INFORMATION *enumerationBuffer, PULONG countReturned)\r
+    { return LsaEnumerateAccountsWithUserRight(_handle, userRights, (void **)enumerationBuffer, countReturned); }\r
+\r
+  NTSTATUS EnumerateAccountRights(PSID sid, PLSA_UNICODE_STRING* userRights, PULONG countOfRights)\r
+    { return ::LsaEnumerateAccountRights(_handle, sid, userRights, countOfRights); }\r
+\r
+  NTSTATUS LookupSids(ULONG count, PSID* sids,\r
+      PLSA_REFERENCED_DOMAIN_LIST* referencedDomains, PLSA_TRANSLATED_NAME* names)\r
+    { return LsaLookupSids(_handle, count, sids, referencedDomains, names); }\r
+\r
+  NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights, ULONG countOfRights)\r
+  {\r
+    #ifndef _UNICODE\r
+    if (hModule == NULL)\r
+      return MY_STATUS_NOT_IMPLEMENTED;\r
+    LsaAddAccountRightsP lsaAddAccountRights = (LsaAddAccountRightsP)GetProcAddress(hModule, "LsaAddAccountRights");\r
+    if (lsaAddAccountRights == NULL)\r
+      return MY_STATUS_NOT_IMPLEMENTED;\r
+    #endif\r
+\r
+    return\r
+      #ifdef _UNICODE\r
+      ::LsaAddAccountRights\r
+      #else\r
+      lsaAddAccountRights\r
+      #endif\r
+      (_handle, accountSid, userRights, countOfRights);\r
+  }\r
+  NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights)\r
+    { return AddAccountRights(accountSid, userRights, 1); }\r
+\r
+  NTSTATUS RemoveAccountRights(PSID accountSid, bool allRights, PLSA_UNICODE_STRING userRights, ULONG countOfRights)\r
+    { return LsaRemoveAccountRights(_handle, accountSid, (BOOLEAN)(allRights ? TRUE : FALSE), userRights, countOfRights); }\r
+};\r
+\r
+bool AddLockMemoryPrivilege();\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Shell.cpp b/CPP/Windows/Shell.cpp
new file mode 100755 (executable)
index 0000000..89b2e7e
--- /dev/null
@@ -0,0 +1,335 @@
+// Windows/Shell.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Common/MyCom.h"\r
+#ifndef _UNICODE\r
+#include "Common/StringConvert.h"\r
+#endif\r
+\r
+#include "Windows/COM.h"\r
+#include "Windows/Shell.h"\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+namespace NWindows {\r
+namespace NShell {\r
+\r
+#ifndef UNDER_CE\r
+\r
+// SHGetMalloc is unsupported in Windows Mobile?\r
+\r
+void CItemIDList::Free()\r
+{\r
+  if (m_Object == NULL)\r
+    return;\r
+  CMyComPtr<IMalloc> shellMalloc;\r
+  if (::SHGetMalloc(&shellMalloc) != NOERROR)\r
+    throw 41099;\r
+  shellMalloc->Free(m_Object);\r
+  m_Object = NULL;\r
+}\r
+\r
+/*\r
+CItemIDList::(LPCITEMIDLIST itemIDList): m_Object(NULL)\r
+  {  *this = itemIDList; }\r
+CItemIDList::(const CItemIDList& itemIDList): m_Object(NULL)\r
+  {  *this = itemIDList; }\r
+\r
+CItemIDList& CItemIDList::operator=(LPCITEMIDLIST object)\r
+{\r
+  Free();\r
+  if (object != 0)\r
+  {\r
+    UINT32 size = GetSize(object);\r
+    m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size);\r
+    if (m_Object != NULL)\r
+      MoveMemory(m_Object, object, size);\r
+  }\r
+  return *this;\r
+}\r
+\r
+CItemIDList& CItemIDList::operator=(const CItemIDList &object)\r
+{\r
+  Free();\r
+  if (object.m_Object != NULL)\r
+  {\r
+    UINT32 size = GetSize(object.m_Object);\r
+    m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size);\r
+    if (m_Object != NULL)\r
+      MoveMemory(m_Object, object.m_Object, size);\r
+  }\r
+  return *this;\r
+}\r
+*/\r
+\r
+/////////////////////////////\r
+// CDrop\r
+\r
+void CDrop::Attach(HDROP object)\r
+{\r
+  Free();\r
+  m_Object = object;\r
+  m_Assigned = true;\r
+}\r
+\r
+void CDrop::Free()\r
+{\r
+  if (m_MustBeFinished && m_Assigned)\r
+    Finish();\r
+  m_Assigned = false;\r
+}\r
+\r
+UINT CDrop::QueryCountOfFiles()\r
+{\r
+  return QueryFile(0xFFFFFFFF, (LPTSTR)NULL, 0);\r
+}\r
+\r
+UString CDrop::QueryFileName(UINT fileIndex)\r
+{\r
+  UString fileName;\r
+  #ifndef _UNICODE\r
+  if (!g_IsNT)\r
+  {\r
+    AString fileNameA;\r
+    UINT bufferSize = QueryFile(fileIndex, (LPTSTR)NULL, 0);\r
+    QueryFile(fileIndex, fileNameA.GetBuffer(bufferSize + 2), bufferSize + 1);\r
+    fileNameA.ReleaseBuffer();\r
+    fileName = GetUnicodeString(fileNameA);\r
+  }\r
+  else\r
+  #endif\r
+  {\r
+    UINT bufferSize = QueryFile(fileIndex, (LPWSTR)NULL, 0);\r
+    QueryFile(fileIndex, fileName.GetBuffer(bufferSize + 2), bufferSize + 1);\r
+    fileName.ReleaseBuffer();\r
+  }\r
+  return fileName;\r
+}\r
+\r
+void CDrop::QueryFileNames(UStringVector &fileNames)\r
+{\r
+  fileNames.Clear();\r
+  UINT numFiles = QueryCountOfFiles();\r
+  fileNames.Reserve(numFiles);\r
+  for (UINT i = 0; i < numFiles; i++)\r
+    fileNames.Add(QueryFileName(i));\r
+}\r
+\r
+\r
+bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path)\r
+{\r
+  bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuffer(MAX_PATH * 2)));\r
+  path.ReleaseBuffer();\r
+  return result;\r
+}\r
+\r
+#endif\r
+\r
+#ifdef UNDER_CE\r
+\r
+bool BrowseForFolder(LPBROWSEINFO, CSysString)\r
+{\r
+  return false;\r
+}\r
+\r
+bool BrowseForFolder(HWND, LPCTSTR, UINT, LPCTSTR, CSysString &)\r
+{\r
+  return false;\r
+}\r
+\r
+bool BrowseForFolder(HWND owner, LPCTSTR title,\r
+    LPCTSTR initialFolder, CSysString &resultPath)\r
+{\r
+  /*\r
+  // SHBrowseForFolder doesn't work before CE 6.0 ?\r
+  if (GetProcAddress(LoadLibrary(L"ceshell.dll", L"SHBrowseForFolder") == 0)\r
+    MessageBoxW(0, L"no", L"", 0);\r
+  else\r
+    MessageBoxW(0, L"yes", L"", 0);\r
+  */\r
+  /*\r
+  UString s = L"all files";\r
+  s += L" (*.*)";\r
+  return MyGetOpenFileName(owner, title, initialFolder, s, resultPath, true);\r
+  */\r
+  return false;\r
+}\r
+\r
+#else\r
+\r
+bool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath)\r
+{\r
+  NWindows::NCOM::CComInitializer comInitializer;\r
+  LPITEMIDLIST itemIDList = ::SHBrowseForFolder(browseInfo);\r
+  if (itemIDList == NULL)\r
+    return false;\r
+  CItemIDList itemIDListHolder;\r
+  itemIDListHolder.Attach(itemIDList);\r
+  return GetPathFromIDList(itemIDList, resultPath);\r
+}\r
+\r
+\r
+int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)\r
+{\r
+  #ifndef UNDER_CE\r
+  switch(uMsg)\r
+  {\r
+    case BFFM_INITIALIZED:\r
+    {\r
+      SendMessage(hwnd, BFFM_SETSELECTION, TRUE, data);\r
+      break;\r
+    }\r
+    /*\r
+    case BFFM_SELCHANGED:\r
+    {\r
+      TCHAR dir[MAX_PATH];\r
+      if (::SHGetPathFromIDList((LPITEMIDLIST) lp , dir))\r
+        SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)dir);\r
+      else\r
+        SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)TEXT(""));\r
+      break;\r
+    }\r
+    */\r
+    default:\r
+      break;\r
+  }\r
+  #endif\r
+  return 0;\r
+}\r
+\r
+\r
+bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags,\r
+    LPCTSTR initialFolder, CSysString &resultPath)\r
+{\r
+  CSysString displayName;\r
+  BROWSEINFO browseInfo;\r
+  browseInfo.hwndOwner = owner;\r
+  browseInfo.pidlRoot = NULL;\r
+\r
+  // there are Unicode/astring problems in WinCE SDK!!!\r
+  #ifdef UNDER_CE\r
+  browseInfo.pszDisplayName = (LPSTR)displayName.GetBuffer(MAX_PATH);\r
+  browseInfo.lpszTitle = (LPCSTR)title;\r
+  #else\r
+  browseInfo.pszDisplayName = displayName.GetBuffer(MAX_PATH);\r
+  browseInfo.lpszTitle = title;\r
+  #endif\r
+  browseInfo.ulFlags = ulFlags;\r
+  browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc : NULL;\r
+  browseInfo.lParam = (LPARAM)initialFolder;\r
+  return BrowseForFolder(&browseInfo, resultPath);\r
+}\r
+\r
+bool BrowseForFolder(HWND owner, LPCTSTR title,\r
+    LPCTSTR initialFolder, CSysString &resultPath)\r
+{\r
+  return BrowseForFolder(owner, title,\r
+      #ifndef UNDER_CE\r
+      BIF_NEWDIALOGSTYLE |\r
+      #endif\r
+      BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT, initialFolder, resultPath);\r
+  // BIF_STATUSTEXT; BIF_USENEWUI   (Version 5.0)\r
+}\r
+\r
+#ifndef _UNICODE\r
+\r
+typedef BOOL (WINAPI * SHGetPathFromIDListWP)(LPCITEMIDLIST pidl, LPWSTR pszPath);\r
+\r
+bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path)\r
+{\r
+  path.Empty();\r
+  SHGetPathFromIDListWP shGetPathFromIDListW = (SHGetPathFromIDListWP)\r
+    ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListW");\r
+  if (shGetPathFromIDListW == 0)\r
+    return false;\r
+  bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuffer(MAX_PATH * 2)));\r
+  path.ReleaseBuffer();\r
+  return result;\r
+}\r
+\r
+typedef LPITEMIDLIST (WINAPI * SHBrowseForFolderWP)(LPBROWSEINFOW lpbi);\r
+\r
+bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath)\r
+{\r
+  NWindows::NCOM::CComInitializer comInitializer;\r
+  SHBrowseForFolderWP shBrowseForFolderW = (SHBrowseForFolderWP)\r
+    ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHBrowseForFolderW");\r
+  if (shBrowseForFolderW == 0)\r
+    return false;\r
+  LPITEMIDLIST itemIDList = shBrowseForFolderW(browseInfo);\r
+  if (itemIDList == NULL)\r
+    return false;\r
+  CItemIDList itemIDListHolder;\r
+  itemIDListHolder.Attach(itemIDList);\r
+  return GetPathFromIDList(itemIDList, resultPath);\r
+}\r
+\r
+\r
+int CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)\r
+{\r
+  switch(uMsg)\r
+  {\r
+    case BFFM_INITIALIZED:\r
+    {\r
+      SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, data);\r
+      break;\r
+    }\r
+    /*\r
+    case BFFM_SELCHANGED:\r
+    {\r
+      wchar_t dir[MAX_PATH * 2];\r
+\r
+      if (shGetPathFromIDListW((LPITEMIDLIST)lp , dir))\r
+        SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)dir);\r
+      else\r
+        SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)L"");\r
+      break;\r
+    }\r
+    */\r
+    default:\r
+      break;\r
+  }\r
+  return 0;\r
+}\r
+\r
+\r
+static bool BrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags,\r
+    LPCWSTR initialFolder, UString &resultPath)\r
+{\r
+  UString displayName;\r
+  BROWSEINFOW browseInfo;\r
+  browseInfo.hwndOwner = owner;\r
+  browseInfo.pidlRoot = NULL;\r
+  browseInfo.pszDisplayName = displayName.GetBuffer(MAX_PATH);\r
+  browseInfo.lpszTitle = title;\r
+  browseInfo.ulFlags = ulFlags;\r
+  browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc2 : NULL;\r
+  browseInfo.lParam = (LPARAM)initialFolder;\r
+  return BrowseForFolder(&browseInfo, resultPath);\r
+}\r
+\r
+bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath)\r
+{\r
+  if (g_IsNT)\r
+    return BrowseForFolder(owner, title,\r
+      BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS\r
+      //  | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified.\r
+      , initialFolder, resultPath);\r
+  // BIF_STATUSTEXT; BIF_USENEWUI   (Version 5.0)\r
+  CSysString s;\r
+  bool res = BrowseForFolder(owner, GetSystemString(title),\r
+      BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS\r
+      // | BIF_STATUSTEXT  // This flag is not supported when BIF_NEWDIALOGSTYLE is specified.\r
+      , GetSystemString(initialFolder), s);\r
+  resultPath = GetUnicodeString(s);\r
+  return res;\r
+}\r
+\r
+#endif\r
+\r
+#endif\r
+\r
+}}\r
diff --git a/CPP/Windows/Shell.h b/CPP/Windows/Shell.h
new file mode 100755 (executable)
index 0000000..d8849cd
--- /dev/null
@@ -0,0 +1,93 @@
+// Windows/Shell.h\r
+\r
+#ifndef __WINDOWS_SHELL_H\r
+#define __WINDOWS_SHELL_H\r
+\r
+#include <windows.h>\r
+#include <shlobj.h>\r
+\r
+#include "Common/MyString.h"\r
+#include "Windows/Defs.h"\r
+\r
+namespace NWindows{\r
+namespace NShell{\r
+\r
+/////////////////////////\r
+// CItemIDList\r
+#ifndef UNDER_CE\r
+\r
+class CItemIDList\r
+{\r
+  LPITEMIDLIST m_Object;\r
+public:\r
+  CItemIDList(): m_Object(NULL) {}\r
+  // CItemIDList(LPCITEMIDLIST itemIDList);\r
+  // CItemIDList(const CItemIDList& itemIDList);\r
+  ~CItemIDList() { Free(); }\r
+  void Free();\r
+  void Attach(LPITEMIDLIST object)\r
+  {\r
+    Free();\r
+    m_Object = object;\r
+  }\r
+  LPITEMIDLIST Detach()\r
+  {\r
+    LPITEMIDLIST object = m_Object;\r
+    m_Object = NULL;\r
+    return object;\r
+  }\r
+  operator LPITEMIDLIST() { return m_Object;}\r
+  operator LPCITEMIDLIST() const { return m_Object;}\r
+  LPITEMIDLIST* operator&() { return &m_Object; }\r
+  LPITEMIDLIST operator->() { return m_Object; }\r
+\r
+  // CItemIDList& operator=(LPCITEMIDLIST object);\r
+  // CItemIDList& operator=(const CItemIDList &object);\r
+};\r
+\r
+/////////////////////////////\r
+// CDrop\r
+\r
+class CDrop\r
+{\r
+  HDROP m_Object;\r
+  bool m_MustBeFinished;\r
+  bool m_Assigned;\r
+  void Free();\r
+public:\r
+  CDrop(bool mustBeFinished) : m_MustBeFinished(mustBeFinished), m_Assigned(false) {}\r
+  ~CDrop() { Free(); }\r
+\r
+  void Attach(HDROP object);\r
+  operator HDROP() { return m_Object;}\r
+  bool QueryPoint(LPPOINT point)\r
+    { return BOOLToBool(::DragQueryPoint(m_Object, point)); }\r
+  void Finish() {  ::DragFinish(m_Object); }\r
+  UINT QueryFile(UINT fileIndex, LPTSTR fileName, UINT fileNameSize)\r
+    { return ::DragQueryFile(m_Object, fileIndex, fileName, fileNameSize); }\r
+  #ifndef _UNICODE\r
+  UINT QueryFile(UINT fileIndex, LPWSTR fileName, UINT fileNameSize)\r
+    { return ::DragQueryFileW(m_Object, fileIndex, fileName, fileNameSize); }\r
+  #endif\r
+  UINT QueryCountOfFiles();\r
+  UString QueryFileName(UINT fileIndex);\r
+  void QueryFileNames(UStringVector &fileNames);\r
+};\r
+\r
+#endif\r
+\r
+/////////////////////////////\r
+// Functions\r
+\r
+bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path);\r
+bool BrowseForFolder(LPBROWSEINFO lpbi, CSysString &resultPath);\r
+bool BrowseForFolder(HWND owner, LPCTSTR title, LPCTSTR initialFolder, CSysString &resultPath);\r
+\r
+#ifndef _UNICODE\r
+bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path);\r
+bool BrowseForFolder(LPBROWSEINFO lpbi, UString &resultPath);\r
+bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath);\r
+#endif\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/StdAfx.h b/CPP/Windows/StdAfx.h
new file mode 100755 (executable)
index 0000000..5308d63
--- /dev/null
@@ -0,0 +1,9 @@
+// StdAfx.h\r
+\r
+#ifndef __STDAFX_H\r
+#define __STDAFX_H\r
+\r
+#include "../Common/MyWindows.h"\r
+#include "../Common/NewHandler.h"\r
+\r
+#endif\r
diff --git a/CPP/Windows/Synchronization.cpp b/CPP/Windows/Synchronization.cpp
new file mode 100755 (executable)
index 0000000..01f1ad9
--- /dev/null
@@ -0,0 +1,10 @@
+// Windows/Synchronization.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Synchronization.h"\r
+\r
+namespace NWindows {\r
+namespace NSynchronization {\r
+\r
+}}\r
diff --git a/CPP/Windows/Synchronization.h b/CPP/Windows/Synchronization.h
new file mode 100755 (executable)
index 0000000..786da00
--- /dev/null
@@ -0,0 +1,164 @@
+// Windows/Synchronization.h\r
+\r
+#ifndef __WINDOWS_SYNCHRONIZATION_H\r
+#define __WINDOWS_SYNCHRONIZATION_H\r
+\r
+#include "../../C/Threads.h"\r
+\r
+#include "Defs.h"\r
+\r
+#ifdef _WIN32\r
+#include "Handle.h"\r
+#endif\r
+\r
+namespace NWindows {\r
+namespace NSynchronization {\r
+\r
+class CBaseEvent\r
+{\r
+protected:\r
+  ::CEvent _object;\r
+public:\r
+  bool IsCreated() { return Event_IsCreated(&_object) != 0; }\r
+  operator HANDLE() { return _object; }\r
+  CBaseEvent() { Event_Construct(&_object); }\r
+  ~CBaseEvent() { Close(); }\r
+  WRes Close() { return Event_Close(&_object); }\r
+  #ifdef _WIN32\r
+  WRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL)\r
+  {\r
+    _object = ::CreateEvent(sa, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name);\r
+    if (name == NULL && _object != 0)\r
+      return 0;\r
+    return ::GetLastError();\r
+  }\r
+  WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name)\r
+  {\r
+    _object = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name);\r
+    if (_object != 0)\r
+      return 0;\r
+    return ::GetLastError();\r
+  }\r
+  #endif\r
+\r
+  WRes Set() { return Event_Set(&_object); }\r
+  // bool Pulse() { return BOOLToBool(::PulseEvent(_handle)); }\r
+  WRes Reset() { return Event_Reset(&_object); }\r
+  WRes Lock() { return Event_Wait(&_object); }\r
+};\r
+\r
+class CManualResetEvent: public CBaseEvent\r
+{\r
+public:\r
+  WRes Create(bool initiallyOwn = false)\r
+  {\r
+    return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0);\r
+  }\r
+  WRes CreateIfNotCreated()\r
+  {\r
+    if (IsCreated())\r
+      return 0;\r
+    return ManualResetEvent_CreateNotSignaled(&_object);\r
+  }\r
+  #ifdef _WIN32\r
+  WRes CreateWithName(bool initiallyOwn, LPCTSTR name)\r
+  {\r
+    return CBaseEvent::Create(true, initiallyOwn, name);\r
+  }\r
+  #endif\r
+};\r
+\r
+class CAutoResetEvent: public CBaseEvent\r
+{\r
+public:\r
+  WRes Create()\r
+  {\r
+    return AutoResetEvent_CreateNotSignaled(&_object);\r
+  }\r
+  WRes CreateIfNotCreated()\r
+  {\r
+    if (IsCreated())\r
+      return 0;\r
+    return AutoResetEvent_CreateNotSignaled(&_object);\r
+  }\r
+};\r
+\r
+#ifdef _WIN32\r
+class CObject: public CHandle\r
+{\r
+public:\r
+  WRes Lock(DWORD timeoutInterval = INFINITE)\r
+    { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); }\r
+};\r
+class CMutex: public CObject\r
+{\r
+public:\r
+  WRes Create(bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL)\r
+  {\r
+    _handle = ::CreateMutex(sa, BoolToBOOL(initiallyOwn), name);\r
+    if (name == NULL && _handle != 0)\r
+      return 0;\r
+    return ::GetLastError();\r
+  }\r
+  #ifndef UNDER_CE\r
+  WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name)\r
+  {\r
+    _handle = ::OpenMutex(desiredAccess, BoolToBOOL(inheritHandle), name);\r
+    if (_handle != 0)\r
+      return 0;\r
+    return ::GetLastError();\r
+  }\r
+  #endif\r
+  WRes Release()\r
+  {\r
+    return ::ReleaseMutex(_handle) ? 0 : ::GetLastError();\r
+  }\r
+};\r
+class CMutexLock\r
+{\r
+  CMutex *_object;\r
+public:\r
+  CMutexLock(CMutex &object): _object(&object) { _object->Lock(); }\r
+  ~CMutexLock() { _object->Release(); }\r
+};\r
+#endif\r
+\r
+class CSemaphore\r
+{\r
+  ::CSemaphore _object;\r
+public:\r
+  CSemaphore() { Semaphore_Construct(&_object); }\r
+  ~CSemaphore() { Close(); }\r
+  WRes Close() {  return Semaphore_Close(&_object); }\r
+  operator HANDLE() { return _object; }\r
+  WRes Create(UInt32 initiallyCount, UInt32 maxCount)\r
+  {\r
+    return Semaphore_Create(&_object, initiallyCount, maxCount);\r
+  }\r
+  WRes Release() { return Semaphore_Release1(&_object); }\r
+  WRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); }\r
+  WRes Lock() { return Semaphore_Wait(&_object); }\r
+};\r
+\r
+class CCriticalSection\r
+{\r
+  ::CCriticalSection _object;\r
+public:\r
+  CCriticalSection() { CriticalSection_Init(&_object); }\r
+  ~CCriticalSection() { CriticalSection_Delete(&_object); }\r
+  void Enter() { CriticalSection_Enter(&_object); }\r
+  void Leave() { CriticalSection_Leave(&_object); }\r
+};\r
+\r
+class CCriticalSectionLock\r
+{\r
+  CCriticalSection *_object;\r
+  void Unlock()  { _object->Leave(); }\r
+public:\r
+  CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); }\r
+  ~CCriticalSectionLock() { Unlock(); }\r
+};\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp
new file mode 100755 (executable)
index 0000000..545ea0e
--- /dev/null
@@ -0,0 +1,72 @@
+// Windows/System.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "../Common/Defs.h"\r
+\r
+#include "System.h"\r
+\r
+namespace NWindows {\r
+namespace NSystem {\r
+\r
+UInt32 GetNumberOfProcessors()\r
+{\r
+  SYSTEM_INFO systemInfo;\r
+  GetSystemInfo(&systemInfo);\r
+  return (UInt32)systemInfo.dwNumberOfProcessors;\r
+}\r
+\r
+#ifndef UNDER_CE\r
+\r
+#if !defined(_WIN64) && defined(__GNUC__)\r
+\r
+typedef struct _MY_MEMORYSTATUSEX {\r
+  DWORD dwLength;\r
+  DWORD dwMemoryLoad;\r
+  DWORDLONG ullTotalPhys;\r
+  DWORDLONG ullAvailPhys;\r
+  DWORDLONG ullTotalPageFile;\r
+  DWORDLONG ullAvailPageFile;\r
+  DWORDLONG ullTotalVirtual;\r
+  DWORDLONG ullAvailVirtual;\r
+  DWORDLONG ullAvailExtendedVirtual;\r
+} MY_MEMORYSTATUSEX, *MY_LPMEMORYSTATUSEX;\r
+\r
+#else\r
+\r
+#define MY_MEMORYSTATUSEX MEMORYSTATUSEX\r
+#define MY_LPMEMORYSTATUSEX LPMEMORYSTATUSEX\r
+\r
+#endif\r
+\r
+typedef BOOL (WINAPI *GlobalMemoryStatusExP)(MY_LPMEMORYSTATUSEX lpBuffer);\r
+\r
+#endif\r
+\r
+UInt64 GetRamSize()\r
+{\r
+  #ifndef UNDER_CE\r
+  MY_MEMORYSTATUSEX stat;\r
+  stat.dwLength = sizeof(stat);\r
+  #endif\r
+  #ifdef _WIN64\r
+  if (!::GlobalMemoryStatusEx(&stat))\r
+    return 0;\r
+  return MyMin(stat.ullTotalVirtual, stat.ullTotalPhys);\r
+  #else\r
+  #ifndef UNDER_CE\r
+  GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP)\r
+      ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GlobalMemoryStatusEx");\r
+  if (globalMemoryStatusEx != 0 && globalMemoryStatusEx(&stat))\r
+    return MyMin(stat.ullTotalVirtual, stat.ullTotalPhys);\r
+  #endif\r
+  {\r
+    MEMORYSTATUS stat;\r
+    stat.dwLength = sizeof(stat);\r
+    ::GlobalMemoryStatus(&stat);\r
+    return MyMin(stat.dwTotalVirtual, stat.dwTotalPhys);\r
+  }\r
+  #endif\r
+}\r
+\r
+}}\r
diff --git a/CPP/Windows/System.h b/CPP/Windows/System.h
new file mode 100755 (executable)
index 0000000..49a4fe7
--- /dev/null
@@ -0,0 +1,16 @@
+// Windows/System.h\r
+\r
+#ifndef __WINDOWS_SYSTEM_H\r
+#define __WINDOWS_SYSTEM_H\r
+\r
+#include "../Common/Types.h"\r
+\r
+namespace NWindows {\r
+namespace NSystem {\r
+\r
+UInt32 GetNumberOfProcessors();\r
+UInt64 GetRamSize();\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Thread.h b/CPP/Windows/Thread.h
new file mode 100755 (executable)
index 0000000..1b5863c
--- /dev/null
@@ -0,0 +1,38 @@
+// Windows/Thread.h\r
+\r
+#ifndef __WINDOWS_THREAD_H\r
+#define __WINDOWS_THREAD_H\r
+\r
+#include "../../C/Threads.h"\r
+\r
+#include "Defs.h"\r
+\r
+namespace NWindows {\r
+\r
+class CThread\r
+{\r
+  ::CThread thread;\r
+public:\r
+  CThread() { Thread_Construct(&thread); }\r
+  ~CThread() { Close(); }\r
+  bool IsCreated() { return Thread_WasCreated(&thread) != 0; }\r
+  WRes Close()  { return Thread_Close(&thread); }\r
+  WRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter)\r
+    { return Thread_Create(&thread, startAddress, parameter); }\r
+  WRes Wait() { return Thread_Wait(&thread); }\r
+  \r
+  #ifdef _WIN32\r
+  operator HANDLE() { return thread; }\r
+  void Attach(HANDLE handle) { thread = handle; }\r
+  HANDLE Detach() { HANDLE h = thread; thread = NULL; return h; }\r
+  DWORD Resume() { return ::ResumeThread(thread); }\r
+  DWORD Suspend() { return ::SuspendThread(thread); }\r
+  bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread, exitCode)); }\r
+  int GetPriority() { return ::GetThreadPriority(thread); }\r
+  bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread, priority)); }\r
+  #endif\r
+};\r
+\r
+}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Time.cpp b/CPP/Windows/Time.cpp
new file mode 100755 (executable)
index 0000000..0504cdf
--- /dev/null
@@ -0,0 +1,170 @@
+// Windows/Time.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#include "Windows/Defs.h"\r
+\r
+#include "Time.h"\r
+\r
+namespace NWindows {\r
+namespace NTime {\r
+\r
+static const UInt32 kNumTimeQuantumsInSecond = 10000000;\r
+static const UInt32 kFileTimeStartYear = 1601;\r
+static const UInt32 kDosTimeStartYear = 1980;\r
+static const UInt32 kUnixTimeStartYear = 1970;\r
+static const UInt64 kUnixTimeStartValue = ((UInt64)kNumTimeQuantumsInSecond) *\r
+    60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear));\r
+\r
+bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft)\r
+{\r
+  #if defined(_WIN32) && !defined(UNDER_CE)\r
+  return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft));\r
+  #else\r
+  ft.dwLowDateTime = 0;\r
+  ft.dwHighDateTime = 0;\r
+  UInt64 res;\r
+  if (!GetSecondsSince1601(kDosTimeStartYear + (dosTime >> 25), (dosTime >> 21) & 0xF, (dosTime >> 16) & 0x1F,\r
+      (dosTime >> 11) & 0x1F, (dosTime >> 5) & 0x3F, (dosTime & 0x1F) * 2, res))\r
+    return false;\r
+  res *= kNumTimeQuantumsInSecond;\r
+  ft.dwLowDateTime = (UInt32)res;\r
+  ft.dwHighDateTime = (UInt32)(res >> 32);\r
+  return true;\r
+  #endif\r
+}\r
+\r
+static const UInt32 kHighDosTime = 0xFF9FBF7D;\r
+static const UInt32 kLowDosTime = 0x210000;\r
+\r
+#define PERIOD_4 (4 * 365 + 1)\r
+#define PERIOD_100 (PERIOD_4 * 25 - 1)\r
+#define PERIOD_400 (PERIOD_100 * 4 + 1)\r
+\r
+bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime)\r
+{\r
+  #if defined(_WIN32) && !defined(UNDER_CE)\r
+\r
+  WORD datePart, timePart;\r
+  if (!::FileTimeToDosDateTime(&ft, &datePart, &timePart))\r
+  {\r
+    dosTime = (ft.dwHighDateTime >= 0x01C00000) ? kHighDosTime : kLowDosTime;\r
+    return false;\r
+  }\r
+  dosTime = (((UInt32)datePart) << 16) + timePart;\r
+\r
+  #else\r
+\r
+  unsigned year, mon, day, hour, min, sec;\r
+  UInt64 v64 = ft.dwLowDateTime | ((UInt64)ft.dwHighDateTime << 32);\r
+  Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\r
+  unsigned temp;\r
+  UInt32 v;\r
+  v64 += (kNumTimeQuantumsInSecond * 2 - 1);\r
+  v64 /= kNumTimeQuantumsInSecond;\r
+  sec = (unsigned)(v64 % 60);\r
+  v64 /= 60;\r
+  min = (unsigned)(v64 % 60);\r
+  v64 /= 60;\r
+  hour = (unsigned)(v64 % 24);\r
+  v64 /= 24;\r
+\r
+  v = (UInt32)v64;\r
+\r
+  year = (unsigned)(kFileTimeStartYear + v / PERIOD_400 * 400);\r
+  v %= PERIOD_400;\r
+\r
+  temp = (unsigned)(v / PERIOD_100);\r
+  if (temp == 4)\r
+    temp = 3;\r
+  year += temp * 100;\r
+  v -= temp * PERIOD_100;\r
+\r
+  temp = v / PERIOD_4;\r
+  if (temp == 25)\r
+    temp = 24;\r
+  year += temp * 4;\r
+  v -= temp * PERIOD_4;\r
+\r
+  temp = v / 365;\r
+  if (temp == 4)\r
+    temp = 3;\r
+  year += temp;\r
+  v -= temp * 365;\r
+\r
+  if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))\r
+    ms[1] = 29;\r
+  for (mon = 1; mon <= 12; mon++)\r
+  {\r
+    unsigned s = ms[mon - 1];\r
+    if (v < s)\r
+      break;\r
+    v -= s;\r
+  }\r
+  day = (unsigned)v + 1;\r
+\r
+  dosTime = kLowDosTime;\r
+  if (year < kDosTimeStartYear)\r
+    return false;\r
+  year -= kDosTimeStartYear;\r
+  dosTime = kHighDosTime;\r
+  if (year >= 128)\r
+    return false;\r
+  dosTime = (year << 25) | (mon << 21) | (day << 16) | (hour << 11) | (min << 5) | (sec >> 1);\r
+  #endif\r
+  return true;\r
+}\r
+\r
+void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft)\r
+{\r
+  UInt64 v = kUnixTimeStartValue + ((UInt64)unixTime) * kNumTimeQuantumsInSecond;\r
+  ft.dwLowDateTime = (DWORD)v;\r
+  ft.dwHighDateTime = (DWORD)(v >> 32);\r
+}\r
+\r
+bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime)\r
+{\r
+  UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;\r
+  if (winTime < kUnixTimeStartValue)\r
+  {\r
+    unixTime = 0;\r
+    return false;\r
+  }\r
+  winTime = (winTime - kUnixTimeStartValue) / kNumTimeQuantumsInSecond;\r
+  if (winTime > 0xFFFFFFFF)\r
+  {\r
+    unixTime = 0xFFFFFFFF;\r
+    return false;\r
+  }\r
+  unixTime = (UInt32)winTime;\r
+  return true;\r
+}\r
+\r
+bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day,\r
+  unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds)\r
+{\r
+  resSeconds = 0;\r
+  if (year < kFileTimeStartYear || year >= 10000 || month < 1 || month > 12 ||\r
+      day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59)\r
+    return false;\r
+  UInt32 numYears = year - kFileTimeStartYear;\r
+  UInt32 numDays = numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400;\r
+  Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\r
+  if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))\r
+    ms[1] = 29;\r
+  month--;\r
+  for (unsigned i = 0; i < month; i++)\r
+    numDays += ms[i];\r
+  numDays += day - 1;\r
+  resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec;\r
+  return true;\r
+}\r
+\r
+void GetCurUtcFileTime(FILETIME &ft)\r
+{\r
+  SYSTEMTIME st;\r
+  GetSystemTime(&st);\r
+  SystemTimeToFileTime(&st, &ft);\r
+}\r
+\r
+}}\r
diff --git a/CPP/Windows/Time.h b/CPP/Windows/Time.h
new file mode 100755 (executable)
index 0000000..7ecb204
--- /dev/null
@@ -0,0 +1,21 @@
+// Windows/Time.h\r
+\r
+#ifndef __WINDOWS_TIME_H\r
+#define __WINDOWS_TIME_H\r
+\r
+#include "Common/Types.h"\r
+\r
+namespace NWindows {\r
+namespace NTime {\r
+\r
+bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime);\r
+bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime);\r
+void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime);\r
+bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime);\r
+bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day,\r
+  unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds);\r
+void GetCurUtcFileTime(FILETIME &ft);\r
+\r
+}}\r
+\r
+#endif\r
diff --git a/CPP/Windows/Window.cpp b/CPP/Windows/Window.cpp
new file mode 100755 (executable)
index 0000000..b283686
--- /dev/null
@@ -0,0 +1,169 @@
+// Windows/Window.cpp\r
+\r
+#include "StdAfx.h"\r
+\r
+#ifndef _UNICODE\r
+#include "Common/StringConvert.h"\r
+#endif\r
+#include "Windows/Window.h"\r
+\r
+#ifndef _UNICODE\r
+extern bool g_IsNT;\r
+#endif\r
+\r
+namespace NWindows {\r
+\r
+#ifndef _UNICODE\r
+ATOM MyRegisterClass(CONST WNDCLASSW *wndClass)\r
+{\r
+  if (g_IsNT)\r
+    return RegisterClassW(wndClass);\r
+  WNDCLASSA wndClassA;\r
+  wndClassA.style = wndClass->style;\r
+  wndClassA.lpfnWndProc = wndClass->lpfnWndProc;\r
+  wndClassA.cbClsExtra = wndClass->cbClsExtra;\r
+  wndClassA.cbWndExtra = wndClass->cbWndExtra;\r
+  wndClassA.hInstance = wndClass->hInstance;\r
+  wndClassA.hIcon = wndClass->hIcon;\r
+  wndClassA.hCursor = wndClass->hCursor;\r
+  wndClassA.hbrBackground = wndClass->hbrBackground;\r
+  AString menuName;\r
+  AString className;\r
+  if (IS_INTRESOURCE(wndClass->lpszMenuName))\r
+    wndClassA.lpszMenuName = (LPCSTR)wndClass->lpszMenuName;\r
+  else\r
+  {\r
+    menuName = GetSystemString(wndClass->lpszMenuName);\r
+    wndClassA.lpszMenuName = menuName;\r
+  }\r
+  if (IS_INTRESOURCE(wndClass->lpszClassName))\r
+    wndClassA.lpszClassName = (LPCSTR)wndClass->lpszClassName;\r
+  else\r
+  {\r
+    className = GetSystemString(wndClass->lpszClassName);\r
+    wndClassA.lpszClassName = className;\r
+  }\r
+  return RegisterClassA(&wndClassA);\r
+}\r
+\r
+bool CWindow::Create(LPCWSTR className,\r
+      LPCWSTR windowName, DWORD style,\r
+      int x, int y, int width, int height,\r
+      HWND parentWindow, HMENU idOrHMenu,\r
+      HINSTANCE instance, LPVOID createParam)\r
+{\r
+  if (g_IsNT)\r
+  {\r
+    _window = ::CreateWindowW(className, windowName,\r
+        style, x, y, width, height, parentWindow,\r
+        idOrHMenu, instance, createParam);\r
+     return (_window != NULL);\r
+  }\r
+  return Create(GetSystemString(className), GetSystemString(windowName),\r
+        style, x, y, width, height, parentWindow,\r
+        idOrHMenu, instance, createParam);\r
+}\r
+\r
+bool CWindow::CreateEx(DWORD exStyle, LPCWSTR className,\r
+      LPCWSTR windowName, DWORD style,\r
+      int x, int y, int width, int height,\r
+      HWND parentWindow, HMENU idOrHMenu,\r
+      HINSTANCE instance, LPVOID createParam)\r
+{\r
+  if (g_IsNT)\r
+  {\r
+    _window = ::CreateWindowExW(exStyle, className, windowName,\r
+      style, x, y, width, height, parentWindow,\r
+      idOrHMenu, instance, createParam);\r
+     return (_window != NULL);\r
+  }\r
+  AString classNameA;\r
+  LPCSTR classNameP;\r
+  if (IS_INTRESOURCE(className))\r
+    classNameP = (LPCSTR)className;\r
+  else\r
+  {\r
+    classNameA = GetSystemString(className);\r
+    classNameP = classNameA;\r
+  }\r
+  AString windowNameA;\r
+  LPCSTR windowNameP;\r
+  if (IS_INTRESOURCE(windowName))\r
+    windowNameP = (LPCSTR)windowName;\r
+  else\r
+  {\r
+    windowNameA = GetSystemString(windowName);\r
+    windowNameP = windowNameA;\r
+  }\r
+  return CreateEx(exStyle, classNameP, windowNameP,\r
+      style, x, y, width, height, parentWindow,\r
+      idOrHMenu, instance, createParam);\r
+}\r
+\r
+#endif\r
+\r
+#ifndef _UNICODE\r
+bool MySetWindowText(HWND wnd, LPCWSTR s)\r
+{\r
+  if (g_IsNT)\r
+    return BOOLToBool(::SetWindowTextW(wnd, s));\r
+  return BOOLToBool(::SetWindowTextA(wnd, UnicodeStringToMultiByte(s)));\r
+}\r
+#endif\r
+\r
+bool CWindow::GetText(CSysString &s)\r
+{\r
+  s.Empty();\r
+  int length = GetTextLength();\r
+  if (length == 0)\r
+    return (::GetLastError() == ERROR_SUCCESS);\r
+  length = GetText(s.GetBuffer(length), length + 1);\r
+  s.ReleaseBuffer();\r
+  if (length == 0)\r
+    return (::GetLastError() != ERROR_SUCCESS);\r
+  return true;\r
+}\r
+\r
+#ifndef _UNICODE\r
+bool CWindow::GetText(UString &s)\r
+{\r
+  if (g_IsNT)\r
+  {\r
+    s.Empty();\r
+    int length = GetWindowTextLengthW(_window);\r
+    if (length == 0)\r
+      return (::GetLastError() == ERROR_SUCCESS);\r
+    length = GetWindowTextW(_window, s.GetBuffer(length), length + 1);\r
+    s.ReleaseBuffer();\r
+    if (length == 0)\r
+      return (::GetLastError() == ERROR_SUCCESS);\r
+    return true;\r
+  }\r
+  CSysString sysString;\r
+  bool result = GetText(sysString);\r
+  s = GetUnicodeString(sysString);\r
+  return result;\r
+}\r
+#endif\r
+\r
\r
+/*\r
+bool CWindow::ModifyStyleBase(int styleOffset,\r
+  DWORD remove, DWORD add, UINT flags)\r
+{\r
+  DWORD style = GetWindowLong(styleOffset);\r
+  DWORD newStyle = (style & ~remove) | add;\r
+  if (style == newStyle)\r
+    return false; // it is not good\r
+\r
+  SetWindowLong(styleOffset, newStyle);\r
+  if (flags != 0)\r
+  {\r
+    ::SetWindowPos(_window, NULL, 0, 0, 0, 0,\r
+      SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | flags);\r
+  }\r
+  return TRUE;\r
+}\r
+*/\r
+\r
+}\r
diff --git a/CPP/Windows/Window.h b/CPP/Windows/Window.h
new file mode 100755 (executable)
index 0000000..aeb8dd9
--- /dev/null
@@ -0,0 +1,261 @@
+// Windows/Window.h\r
+\r
+#ifndef __WINDOWS_WINDOW_H\r
+#define __WINDOWS_WINDOW_H\r
+\r
+#include "Defs.h"\r
+#include "Common/MyString.h"\r
+\r
+namespace NWindows {\r
+\r
+inline ATOM MyRegisterClass(CONST WNDCLASS *wndClass)\r
+  { return ::RegisterClass(wndClass); }\r
+\r
+#ifndef _UNICODE\r
+ATOM MyRegisterClass(CONST WNDCLASSW *wndClass);\r
+#endif\r
+\r
+#ifdef _UNICODE\r
+inline bool MySetWindowText(HWND wnd, LPCWSTR s) { return BOOLToBool(::SetWindowText(wnd, s)); }\r
+#else\r
+bool MySetWindowText(HWND wnd, LPCWSTR s);\r
+#endif\r
+\r
+\r
+#ifdef UNDER_CE\r
+#define GWLP_USERDATA GWL_USERDATA\r
+#define GWLP_WNDPROC GWL_WNDPROC\r
+#define BTNS_BUTTON TBSTYLE_BUTTON\r
+#define WC_COMBOBOXW L"ComboBox"\r
+#define DWLP_MSGRESULT DWL_MSGRESULT\r
+#endif\r
+\r
+class CWindow\r
+{\r
+private:\r
+   // bool ModifyStyleBase(int styleOffset, DWORD remove, DWORD add, UINT flags);\r
+protected:\r
+  HWND _window;\r
+public:\r
+  CWindow(HWND newWindow = NULL): _window(newWindow){};\r
+  CWindow& operator=(HWND newWindow)\r
+  {\r
+    _window = newWindow;\r
+    return *this;\r
+  }\r
+  operator HWND() const { return _window; }\r
+  void Attach(HWND newWindow) { _window = newWindow; }\r
+  HWND Detach()\r
+  {\r
+    HWND window = _window;\r
+    _window = NULL;\r
+    return window;\r
+  }\r
+\r
+  bool Foreground() { return BOOLToBool(::SetForegroundWindow(_window)); }\r
+  \r
+  HWND GetParent() const { return ::GetParent(_window); }\r
+  bool GetWindowRect(LPRECT rect) const { return BOOLToBool(::GetWindowRect(_window,rect)); }\r
+  #ifndef UNDER_CE\r
+  bool IsZoomed() const { return BOOLToBool(::IsZoomed(_window)); }\r
+  #endif\r
+  bool ClientToScreen(LPPOINT point) const { return BOOLToBool(::ClientToScreen(_window, point)); }\r
+  bool ScreenToClient(LPPOINT point) const { return BOOLToBool(::ScreenToClient(_window, point)); }\r
+\r
+  bool CreateEx(DWORD exStyle, LPCTSTR className,\r
+      LPCTSTR windowName, DWORD style,\r
+      int x, int y, int width, int height,\r
+      HWND parentWindow, HMENU idOrHMenu,\r
+      HINSTANCE instance, LPVOID createParam)\r
+  {\r
+    _window = ::CreateWindowEx(exStyle, className, windowName,\r
+      style, x, y, width, height, parentWindow,\r
+      idOrHMenu, instance, createParam);\r
+    return (_window != NULL);\r
+  }\r
+\r
+  bool Create(LPCTSTR className,\r
+      LPCTSTR windowName, DWORD style,\r
+      int x, int y, int width, int height,\r
+      HWND parentWindow, HMENU idOrHMenu,\r
+      HINSTANCE instance, LPVOID createParam)\r
+  {\r
+    _window = ::CreateWindow(className, windowName,\r
+      style, x, y, width, height, parentWindow,\r
+      idOrHMenu, instance, createParam);\r
+    return (_window != NULL);\r
+  }\r
+\r
+  #ifndef _UNICODE\r
+  bool Create(LPCWSTR className,\r
+      LPCWSTR windowName, DWORD style,\r
+      int x, int y, int width, int height,\r
+      HWND parentWindow, HMENU idOrHMenu,\r
+      HINSTANCE instance, LPVOID createParam);\r
+  bool CreateEx(DWORD exStyle, LPCWSTR className,\r
+      LPCWSTR windowName, DWORD style,\r
+      int x, int y, int width, int height,\r
+      HWND parentWindow, HMENU idOrHMenu,\r
+      HINSTANCE instance, LPVOID createParam);\r
+  #endif\r
+\r
+\r
+  bool Destroy()\r
+  {\r
+    if (_window == NULL)\r
+      return true;\r
+    bool result = BOOLToBool(::DestroyWindow(_window));\r
+    if (result)\r
+      _window = NULL;\r
+    return result;\r
+  }\r
+  bool IsWindow() {  return BOOLToBool(::IsWindow(_window)); }\r
+  bool Move(int x, int y, int width, int height, bool repaint = true)\r
+    { return BOOLToBool(::MoveWindow(_window, x, y, width, height, BoolToBOOL(repaint))); }\r
+\r
+  bool ChangeSubWindowSizeX(HWND hwnd, int xSize)\r
+  {\r
+    RECT rect;\r
+    ::GetWindowRect(hwnd, &rect);\r
+    POINT p1;\r
+    p1.x = rect.left;\r
+    p1.y = rect.top;\r
+    ScreenToClient(&p1);\r
+    return BOOLToBool(::MoveWindow(hwnd, p1.x, p1.y, xSize, rect.bottom - rect.top, TRUE));\r
+  }\r
+\r
+  void ScreenToClient(RECT *rect)\r
+  {\r
+    POINT p1, p2;\r
+    p1.x = rect->left;\r
+    p1.y = rect->top;\r
+    p2.x = rect->right;\r
+    p2.y = rect->bottom;\r
+    ScreenToClient(&p1);\r
+    ScreenToClient(&p2);\r
+\r
+    rect->left = p1.x;\r
+    rect->top = p1.y;\r
+    rect->right = p2.x;\r
+    rect->bottom = p2.y;\r
+  }\r
+\r
+  bool GetClientRect(LPRECT rect) { return BOOLToBool(::GetClientRect(_window, rect)); }\r
+  bool Show(int cmdShow) { return BOOLToBool(::ShowWindow(_window, cmdShow)); }\r
+  #ifndef UNDER_CE\r
+  bool SetPlacement(CONST WINDOWPLACEMENT *placement) { return BOOLToBool(::SetWindowPlacement(_window, placement)); }\r
+  bool GetPlacement(WINDOWPLACEMENT *placement) { return BOOLToBool(::GetWindowPlacement(_window, placement)); }\r
+  #endif\r
+  bool Update() { return BOOLToBool(::UpdateWindow(_window)); }\r
+  bool InvalidateRect(LPCRECT rect, bool backgroundErase = true)\r
+    { return BOOLToBool(::InvalidateRect(_window, rect, BoolToBOOL(backgroundErase))); }\r
+  void SetRedraw(bool redraw = true) { SendMessage(WM_SETREDRAW, BoolToBOOL(redraw), 0); }\r
+\r
+  LONG_PTR SetStyle(LONG_PTR style) { return SetLongPtr(GWL_STYLE, style); }\r
+  LONG_PTR GetStyle() const { return GetLongPtr(GWL_STYLE); }\r
+  // bool MyIsMaximized() const { return ((GetStyle() & WS_MAXIMIZE) != 0); }\r
+\r
+  LONG_PTR SetLong(int index, LONG newLongPtr) { return ::SetWindowLong(_window, index, newLongPtr); }\r
+  LONG_PTR GetLong(int index) const { return ::GetWindowLong(_window, index); }\r
+  LONG_PTR SetUserDataLong(LONG newLongPtr) { return SetLong(GWLP_USERDATA, newLongPtr); }\r
+  LONG_PTR GetUserDataLong() const { return GetLong(GWLP_USERDATA); }\r
+\r
+\r
+  #ifdef UNDER_CE\r
+\r
+  LONG_PTR SetLongPtr(int index, LONG_PTR newLongPtr) { return SetLong(index, newLongPtr); }\r
+  LONG_PTR GetLongPtr(int index) const { return GetLong(index); }\r
+\r
+  LONG_PTR SetUserDataLongPtr(LONG_PTR newLongPtr) { return SetUserDataLong(newLongPtr); }\r
+  LONG_PTR GetUserDataLongPtr() const { return GetUserDataLong(); }\r
+  \r
+  #else\r
+  \r
+  LONG_PTR SetLongPtr(int index, LONG_PTR newLongPtr)\r
+    { return ::SetWindowLongPtr(_window, index,\r
+          #ifndef _WIN64\r
+          (LONG)\r
+          #endif\r
+          newLongPtr); }\r
+  #ifndef _UNICODE\r
+  LONG_PTR SetLongPtrW(int index, LONG_PTR newLongPtr)\r
+    { return ::SetWindowLongPtrW(_window, index,\r
+          #ifndef _WIN64\r
+          (LONG)\r
+          #endif\r
+          newLongPtr); }\r
+  #endif\r
+\r
+  LONG_PTR GetLongPtr(int index) const { return ::GetWindowLongPtr(_window, index); }\r
+  LONG_PTR SetUserDataLongPtr(LONG_PTR newLongPtr) { return SetLongPtr(GWLP_USERDATA, newLongPtr); }\r
+  LONG_PTR GetUserDataLongPtr() const { return GetLongPtr(GWLP_USERDATA); }\r
+  \r
+  #endif\r
+  \r
+  /*\r
+  bool ModifyStyle(HWND hWnd, DWORD remove, DWORD add, UINT flags = 0)\r
+    {  return ModifyStyleBase(GWL_STYLE, remove, add, flags); }\r
+  bool ModifyStyleEx(HWND hWnd, DWORD remove, DWORD add, UINT flags = 0)\r
+    { return ModifyStyleBase(GWL_EXSTYLE, remove, add, flags); }\r
+  */\r
\r
+  HWND SetFocus() { return ::SetFocus(_window); }\r
+\r
+  LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)\r
+    { return ::SendMessage(_window, message, wParam, lParam) ;}\r
+  #ifndef _UNICODE\r
+  LRESULT SendMessageW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)\r
+    { return ::SendMessageW(_window, message, wParam, lParam) ;}\r
+  #endif\r
+\r
+  bool PostMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)\r
+    {  return BOOLToBool(::PostMessage(_window, message, wParam, lParam)) ;}\r
+  #ifndef _UNICODE\r
+  LRESULT PostMessageW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)\r
+    { return ::PostMessageW(_window, message, wParam, lParam) ;}\r
+  #endif\r
+\r
+  bool SetText(LPCTSTR s) { return BOOLToBool(::SetWindowText(_window, s)); }\r
+  #ifndef _UNICODE\r
+  bool CWindow::SetText(LPCWSTR s) { return MySetWindowText(_window, s); }\r
+  #endif\r
+\r
+  int GetTextLength() const\r
+    { return GetWindowTextLength(_window); }\r
+  UINT GetText(LPTSTR string, int maxCount) const\r
+    { return GetWindowText(_window, string, maxCount); }\r
+  bool GetText(CSysString &s);\r
+  #ifndef _UNICODE\r
+  /*\r
+  UINT GetText(LPWSTR string, int maxCount) const\r
+    { return GetWindowTextW(_window, string, maxCount); }\r
+  */\r
+  bool GetText(UString &s);\r
+  #endif\r
+\r
+  bool Enable(bool enable)\r
+    { return BOOLToBool(::EnableWindow(_window, BoolToBOOL(enable))); }\r
+  \r
+  bool IsEnabled()\r
+    { return BOOLToBool(::IsWindowEnabled(_window)); }\r
+  \r
+  #ifndef UNDER_CE\r
+  HMENU GetSystemMenu(bool revert)\r
+    { return ::GetSystemMenu(_window, BoolToBOOL(revert)); }\r
+  #endif\r
+\r
+  UINT_PTR SetTimer(UINT_PTR idEvent, UINT elapse, TIMERPROC timerFunc = 0)\r
+    { return ::SetTimer(_window, idEvent, elapse, timerFunc); }\r
+  bool KillTimer(UINT_PTR idEvent)\r
+    {return BOOLToBool(::KillTimer(_window, idEvent)); }\r
+\r
+  HICON SetIcon(WPARAM sizeType, HICON icon) { return (HICON)SendMessage(WM_SETICON, sizeType, (LPARAM)icon); }\r
+};\r
+\r
+#define RECT_SIZE_X(r) ((r).right - (r).left)\r
+#define RECT_SIZE_Y(r) ((r).bottom - (r).top)\r
+\r
+}\r
+\r
+#endif\r
+\r
diff --git a/DOC/7zC.txt b/DOC/7zC.txt
new file mode 100755 (executable)
index 0000000..4ff6325
--- /dev/null
@@ -0,0 +1,194 @@
+7z ANSI-C Decoder 4.62\r
+----------------------\r
+\r
+7z ANSI-C provides 7z/LZMA decoding.\r
+7z ANSI-C version is simplified version ported from C++ code.\r
+\r
+LZMA is default and general compression method of 7z format\r
+in 7-Zip compression program (www.7-zip.org). LZMA provides high \r
+compression ratio and very fast decompression.\r
+\r
+\r
+LICENSE\r
+-------\r
+\r
+7z ANSI-C Decoder is part of the LZMA SDK.\r
+LZMA SDK is written and placed in the public domain by Igor Pavlov.\r
+\r
+Files\r
+---------------------\r
+\r
+7zDecode.*   - Low level 7z decoding\r
+7zExtract.*  - High level 7z decoding\r
+7zHeader.*   - .7z format constants\r
+7zIn.*       - .7z archive opening\r
+7zItem.*     - .7z structures\r
+7zMain.c     - Test application\r
+\r
+\r
+How To Use\r
+----------\r
+\r
+You must download 7-Zip program from www.7-zip.org.\r
+\r
+You can create .7z archive with 7z.exe or 7za.exe:\r
+\r
+  7za.exe a archive.7z *.htm -r -mx -m0fb=255\r
+\r
+If you have big number of files in archive, and you need fast extracting, \r
+you can use partly-solid archives:\r
+  \r
+  7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K\r
+\r
+In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only \r
+512KB for extracting one file from such archive.\r
+\r
+\r
+Limitations of current version of 7z ANSI-C Decoder\r
+---------------------------------------------------\r
+\r
+ - It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive.\r
+ - It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters.\r
+ - It converts original UTF-16 Unicode file names to UTF-8 Unicode file names.\r
\r
+These limitations will be fixed in future versions.\r
+\r
+\r
+Using 7z ANSI-C Decoder Test application:\r
+-----------------------------------------\r
+\r
+Usage: 7zDec <command> <archive_name>\r
+\r
+<Command>:\r
+  e: Extract files from archive\r
+  l: List contents of archive\r
+  t: Test integrity of archive\r
+\r
+Example: \r
+\r
+  7zDec l archive.7z\r
+\r
+lists contents of archive.7z\r
+\r
+  7zDec e archive.7z\r
+\r
+extracts files from archive.7z to current folder.\r
+\r
+\r
+How to use .7z Decoder\r
+----------------------\r
+\r
+Memory allocation\r
+~~~~~~~~~~~~~~~~~\r
+\r
+7z Decoder uses two memory pools:\r
+1) Temporary pool\r
+2) Main pool\r
+Such scheme can allow you to avoid fragmentation of allocated blocks.\r
+\r
+\r
+Steps for using 7z decoder\r
+--------------------------\r
+\r
+Use code at 7zMain.c as example.\r
+\r
+1) Declare variables:\r
+  inStream                 /* implements ILookInStream interface */\r
+  CSzArEx db;              /* 7z archive database structure */\r
+  ISzAlloc allocImp;       /* memory functions for main pool */\r
+  ISzAlloc allocTempImp;   /* memory functions for temporary pool */\r
+\r
+2) call CrcGenerateTable(); function to initialize CRC structures.\r
+\r
+3) call SzArEx_Init(&db); function to initialize db structures.\r
+\r
+4) call SzArEx_Open(&db, inStream, &allocMain, &allocTemp) to open archive\r
+\r
+This function opens archive "inStream" and reads headers to "db".\r
+All items in "db" will be allocated with "allocMain" functions.\r
+SzArEx_Open function allocates and frees temporary structures by "allocTemp" functions.\r
+\r
+5) List items or Extract items\r
+\r
+  Listing code:\r
+  ~~~~~~~~~~~~~\r
+    {\r
+      UInt32 i;\r
+      for (i = 0; i < db.db.NumFiles; i++)\r
+      {\r
+        CFileItem *f = db.db.Files + i;\r
+        printf("%10d  %s\n", (int)f->Size, f->Name);\r
+      }\r
+    }\r
+\r
+  Extracting code:\r
+  ~~~~~~~~~~~~~~~~\r
+\r
+  SZ_RESULT SzAr_Extract(\r
+    CArchiveDatabaseEx *db,\r
+    ILookInStream *inStream, \r
+    UInt32 fileIndex,         /* index of file */\r
+    UInt32 *blockIndex,       /* index of solid block */\r
+    Byte **outBuffer,         /* pointer to pointer to output buffer (allocated with allocMain) */\r
+    size_t *outBufferSize,    /* buffer size for output buffer */\r
+    size_t *offset,           /* offset of stream for required file in *outBuffer */\r
+    size_t *outSizeProcessed, /* size of file in *outBuffer */\r
+    ISzAlloc *allocMain,\r
+    ISzAlloc *allocTemp);\r
+\r
+  If you need to decompress more than one file, you can send these values from previous call:\r
+    blockIndex, \r
+    outBuffer, \r
+    outBufferSize,\r
+  You can consider "outBuffer" as cache of solid block. If your archive is solid, \r
+  it will increase decompression speed.\r
+\r
+  After decompressing you must free "outBuffer":\r
+  allocImp.Free(outBuffer);\r
+\r
+6) call SzArEx_Free(&db, allocImp.Free) to free allocated items in "db".\r
+\r
+\r
+\r
+\r
+Memory requirements for .7z decoding \r
+------------------------------------\r
+\r
+Memory usage for Archive opening:\r
+  - Temporary pool:\r
+     - Memory for uncompressed .7z headers\r
+     - some other temporary blocks\r
+  - Main pool:\r
+     - Memory for database: \r
+       Estimated size of one file structures in solid archive:\r
+         - Size (4 or 8 Bytes)\r
+         - CRC32 (4 bytes)\r
+         - LastWriteTime (8 bytes)\r
+         - Some file information (4 bytes)\r
+         - File Name (variable length) + pointer + allocation structures\r
+\r
+Memory usage for archive Decompressing:\r
+  - Temporary pool:\r
+     - Memory for LZMA decompressing structures\r
+  - Main pool:\r
+     - Memory for decompressed solid block\r
+     - Memory for temprorary buffers, if BCJ2 fileter is used. Usually these \r
+       temprorary buffers can be about 15% of solid block size. \r
+  \r
+\r
+7z Decoder doesn't allocate memory for compressed blocks. \r
+Instead of this, you must allocate buffer with desired \r
+size before calling 7z Decoder. Use 7zMain.c as example.\r
+\r
+\r
+Defines\r
+-------\r
+\r
+_SZ_ALLOC_DEBUG   - define it if you want to debug alloc/free operations to stderr.\r
+\r
+\r
+---\r
+\r
+http://www.7-zip.org\r
+http://www.7-zip.org/sdk.html\r
+http://www.7-zip.org/support.html\r
diff --git a/DOC/7zFormat.txt b/DOC/7zFormat.txt
new file mode 100755 (executable)
index 0000000..6b8678f
--- /dev/null
@@ -0,0 +1,469 @@
+7z Format description (4.59)\r
+----------------------------\r
+\r
+This file contains description of 7z archive format. \r
+7z archive can contain files compressed with any method.\r
+See "Methods.txt" for description for defined compressing methods.\r
+\r
+\r
+Format structure Overview\r
+-------------------------\r
+\r
+Some fields can be optional.\r
+\r
+Archive structure\r
+~~~~~~~~~~~~~~~~~  \r
+SignatureHeader\r
+[PackedStreams]\r
+[PackedStreamsForHeaders]\r
+[\r
+  Header \r
+  or \r
+  {\r
+    Packed Header\r
+    HeaderInfo\r
+  }\r
+]\r
+\r
+\r
+\r
+Header structure\r
+~~~~~~~~~~~~~~~~  \r
+{\r
+  ArchiveProperties\r
+  AdditionalStreams\r
+  {\r
+    PackInfo\r
+    {\r
+      PackPos\r
+      NumPackStreams\r
+      Sizes[NumPackStreams]\r
+      CRCs[NumPackStreams]\r
+    }\r
+    CodersInfo\r
+    {\r
+      NumFolders\r
+      Folders[NumFolders]\r
+      {\r
+        NumCoders\r
+        CodersInfo[NumCoders]\r
+        {\r
+          ID\r
+          NumInStreams;\r
+          NumOutStreams;\r
+          PropertiesSize\r
+          Properties[PropertiesSize]\r
+        }\r
+        NumBindPairs\r
+        BindPairsInfo[NumBindPairs]\r
+        {\r
+          InIndex;\r
+          OutIndex;\r
+        }\r
+        PackedIndices\r
+      }\r
+      UnPackSize[Folders][Folders.NumOutstreams]\r
+      CRCs[NumFolders]\r
+    }\r
+    SubStreamsInfo\r
+    {\r
+      NumUnPackStreamsInFolders[NumFolders];\r
+      UnPackSizes[]\r
+      CRCs[]\r
+    }\r
+  }\r
+  MainStreamsInfo\r
+  {\r
+    (Same as in AdditionalStreams)\r
+  }\r
+  FilesInfo\r
+  {\r
+    NumFiles\r
+    Properties[]\r
+    {\r
+      ID\r
+      Size\r
+      Data\r
+    }\r
+  }\r
+}\r
+\r
+HeaderInfo structure\r
+~~~~~~~~~~~~~~~~~~~~\r
+{\r
+  (Same as in AdditionalStreams)\r
+}\r
+\r
+\r
+\r
+Notes about Notation and encoding\r
+---------------------------------\r
+\r
+7z uses little endian encoding.\r
+\r
+7z archive format has optional headers that are marked as\r
+[]\r
+Header\r
+[]\r
+\r
+REAL_UINT64 means real UINT64.\r
+\r
+UINT64 means real UINT64 encoded with the following scheme:\r
+\r
+  Size of encoding sequence depends from first byte:\r
+  First_Byte  Extra_Bytes        Value\r
+  (binary)   \r
+  0xxxxxxx               : ( xxxxxxx           )\r
+  10xxxxxx    BYTE y[1]  : (  xxxxxx << (8 * 1)) + y\r
+  110xxxxx    BYTE y[2]  : (   xxxxx << (8 * 2)) + y\r
+  ...\r
+  1111110x    BYTE y[6]  : (       x << (8 * 6)) + y\r
+  11111110    BYTE y[7]  :                         y\r
+  11111111    BYTE y[8]  :                         y\r
+\r
+\r
+\r
+Property IDs\r
+------------\r
+\r
+0x00 = kEnd\r
+\r
+0x01 = kHeader\r
+\r
+0x02 = kArchiveProperties\r
+    \r
+0x03 = kAdditionalStreamsInfo\r
+0x04 = kMainStreamsInfo\r
+0x05 = kFilesInfo\r
+    \r
+0x06 = kPackInfo\r
+0x07 = kUnPackInfo\r
+0x08 = kSubStreamsInfo\r
+\r
+0x09 = kSize\r
+0x0A = kCRC\r
+\r
+0x0B = kFolder\r
+\r
+0x0C = kCodersUnPackSize\r
+0x0D = kNumUnPackStream\r
+\r
+0x0E = kEmptyStream\r
+0x0F = kEmptyFile\r
+0x10 = kAnti\r
+\r
+0x11 = kName\r
+0x12 = kCTime\r
+0x13 = kATime\r
+0x14 = kMTime\r
+0x15 = kWinAttributes\r
+0x16 = kComment\r
+\r
+0x17 = kEncodedHeader\r
+\r
+0x18 = kStartPos\r
+0x19 = kDummy\r
+\r
+\r
+7z format headers\r
+-----------------\r
+\r
+SignatureHeader\r
+~~~~~~~~~~~~~~~\r
+  BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};\r
+\r
+  ArchiveVersion\r
+  {\r
+    BYTE Major;   // now = 0\r
+    BYTE Minor;   // now = 2\r
+  };\r
+\r
+  UINT32 StartHeaderCRC;\r
+\r
+  StartHeader\r
+  {\r
+    REAL_UINT64 NextHeaderOffset\r
+    REAL_UINT64 NextHeaderSize\r
+    UINT32 NextHeaderCRC\r
+  }\r
+\r
+\r
+...........................\r
+\r
+\r
+ArchiveProperties\r
+~~~~~~~~~~~~~~~~~\r
+BYTE NID::kArchiveProperties (0x02)\r
+for (;;)\r
+{\r
+  BYTE PropertyType;\r
+  if (aType == 0)\r
+    break;\r
+  UINT64 PropertySize;\r
+  BYTE PropertyData[PropertySize];\r
+}\r
+\r
+\r
+Digests (NumStreams)\r
+~~~~~~~~~~~~~~~~~~~~~\r
+  BYTE AllAreDefined\r
+  if (AllAreDefined == 0)\r
+  {\r
+    for(NumStreams)\r
+      BIT Defined\r
+  }\r
+  UINT32 CRCs[NumDefined]\r
+\r
+\r
+PackInfo\r
+~~~~~~~~~~~~\r
+  BYTE NID::kPackInfo  (0x06)\r
+  UINT64 PackPos\r
+  UINT64 NumPackStreams\r
+\r
+  []\r
+  BYTE NID::kSize    (0x09)\r
+  UINT64 PackSizes[NumPackStreams]\r
+  []\r
+\r
+  []\r
+  BYTE NID::kCRC      (0x0A)\r
+  PackStreamDigests[NumPackStreams]\r
+  []\r
+\r
+  BYTE NID::kEnd\r
+\r
+\r
+Folder\r
+~~~~~~\r
+  UINT64 NumCoders;\r
+  for (NumCoders)\r
+  {\r
+    BYTE \r
+    {\r
+      0:3 CodecIdSize\r
+      4:  Is Complex Coder\r
+      5:  There Are Attributes\r
+      6:  Reserved\r
+      7:  There are more alternative methods. (Not used anymore, must be 0).\r
+    } \r
+    BYTE CodecId[CodecIdSize]\r
+    if (Is Complex Coder)\r
+    {\r
+      UINT64 NumInStreams;\r
+      UINT64 NumOutStreams;\r
+    }\r
+    if (There Are Attributes)\r
+    {\r
+      UINT64 PropertiesSize\r
+      BYTE Properties[PropertiesSize]\r
+    }\r
+  }\r
+    \r
+  NumBindPairs = NumOutStreamsTotal - 1;\r
+\r
+  for (NumBindPairs)\r
+  {\r
+    UINT64 InIndex;\r
+    UINT64 OutIndex;\r
+  }\r
+\r
+  NumPackedStreams = NumInStreamsTotal - NumBindPairs;\r
+  if (NumPackedStreams > 1)\r
+    for(NumPackedStreams)\r
+    {\r
+      UINT64 Index;\r
+    };\r
+\r
+\r
+\r
+\r
+Coders Info\r
+~~~~~~~~~~~\r
+\r
+  BYTE NID::kUnPackInfo  (0x07)\r
+\r
+\r
+  BYTE NID::kFolder  (0x0B)\r
+  UINT64 NumFolders\r
+  BYTE External\r
+  switch(External)\r
+  {\r
+    case 0:\r
+      Folders[NumFolders]\r
+    case 1:\r
+      UINT64 DataStreamIndex\r
+  }\r
+\r
+\r
+  BYTE ID::kCodersUnPackSize  (0x0C)\r
+  for(Folders)\r
+    for(Folder.NumOutStreams)\r
+     UINT64 UnPackSize;\r
+\r
+\r
+  []\r
+  BYTE NID::kCRC   (0x0A)\r
+  UnPackDigests[NumFolders]\r
+  []\r
+\r
+  \r
+\r
+  BYTE NID::kEnd\r
+\r
+\r
+\r
+SubStreams Info\r
+~~~~~~~~~~~~~~\r
+  BYTE NID::kSubStreamsInfo; (0x08)\r
+\r
+  []\r
+  BYTE NID::kNumUnPackStream; (0x0D)\r
+  UINT64 NumUnPackStreamsInFolders[NumFolders];\r
+  []\r
+\r
+\r
+  []\r
+  BYTE NID::kSize  (0x09)\r
+  UINT64 UnPackSizes[]\r
+  []\r
+\r
+\r
+  []\r
+  BYTE NID::kCRC  (0x0A)\r
+  Digests[Number of streams with unknown CRC]\r
+  []\r
+\r
+  \r
+  BYTE NID::kEnd\r
+\r
+\r
+Streams Info\r
+~~~~~~~~~~~~\r
+\r
+  []\r
+  PackInfo\r
+  []\r
+\r
+\r
+  []\r
+  CodersInfo\r
+  []\r
+\r
+\r
+  []\r
+  SubStreamsInfo\r
+  []\r
+\r
+  BYTE NID::kEnd\r
+\r
+\r
+FilesInfo\r
+~~~~~~~~~\r
+  BYTE NID::kFilesInfo;  (0x05)\r
+  UINT64 NumFiles\r
+\r
+  for (;;)\r
+  {\r
+    BYTE PropertyType;\r
+    if (aType == 0)\r
+      break;\r
+\r
+    UINT64 Size;\r
+\r
+    switch(PropertyType)\r
+    {\r
+      kEmptyStream:   (0x0E)\r
+        for(NumFiles)\r
+          BIT IsEmptyStream\r
+\r
+      kEmptyFile:     (0x0F)\r
+        for(EmptyStreams)\r
+          BIT IsEmptyFile\r
+\r
+      kAnti:          (0x10)\r
+        for(EmptyStreams)\r
+          BIT IsAntiFile\r
+      \r
+      case kCTime: (0x12)\r
+      case kATime: (0x13)\r
+      case kMTime: (0x14)\r
+        BYTE AllAreDefined\r
+        if (AllAreDefined == 0)\r
+        {\r
+          for(NumFiles)\r
+            BIT TimeDefined\r
+        }\r
+        BYTE External;\r
+        if(External != 0)\r
+          UINT64 DataIndex\r
+        []\r
+        for(Definded Items)\r
+          UINT64 Time\r
+        []\r
+      \r
+      kNames:     (0x11)\r
+        BYTE External;\r
+        if(External != 0)\r
+          UINT64 DataIndex\r
+        []\r
+        for(Files)\r
+        {\r
+          wchar_t Names[NameSize];\r
+          wchar_t 0;\r
+        }\r
+        []\r
+\r
+      kAttributes:  (0x15)\r
+        BYTE AllAreDefined\r
+        if (AllAreDefined == 0)\r
+        {\r
+          for(NumFiles)\r
+            BIT AttributesAreDefined\r
+        }\r
+        BYTE External;\r
+        if(External != 0)\r
+          UINT64 DataIndex\r
+        []\r
+        for(Definded Attributes)\r
+          UINT32 Attributes\r
+        []\r
+    }\r
+  }\r
+\r
+\r
+Header\r
+~~~~~~\r
+  BYTE NID::kHeader (0x01)\r
+\r
+  []\r
+  ArchiveProperties\r
+  []\r
+\r
+  []\r
+  BYTE NID::kAdditionalStreamsInfo; (0x03)\r
+  StreamsInfo\r
+  []\r
+\r
+  []\r
+  BYTE NID::kMainStreamsInfo;    (0x04)\r
+  StreamsInfo\r
+  []\r
+\r
+  []\r
+  FilesInfo\r
+  []\r
+\r
+  BYTE NID::kEnd\r
+\r
+\r
+HeaderInfo\r
+~~~~~~~~~~\r
+  []\r
+  BYTE NID::kEncodedHeader; (0x17)\r
+  StreamsInfo for Encoded Header\r
+  []\r
+\r
+\r
+---\r
+End of document\r
diff --git a/DOC/7zip.hhp b/DOC/7zip.hhp
new file mode 100755 (executable)
index 0000000..84667f5
--- /dev/null
@@ -0,0 +1,70 @@
+[OPTIONS]\r
+Compatibility=1.1 or later\r
+Compiled file=7-zip.chm\r
+Contents file=7zip.hhc\r
+Default topic=start.htm\r
+Display compile progress=No\r
+Full-text search=Yes\r
+Index file=7zip.hhk\r
+Language=0x409 English (United States)\r
+\r
+\r
+[FILES]\r
+start.htm\r
+general\thanks.htm\r
+general\faq.htm\r
+general\formats.htm\r
+general\index.htm\r
+general\license.htm\r
+general\performance.htm\r
+general\7z.htm\r
+cmdline\index.htm\r
+cmdline\syntax.htm\r
+cmdline\exit_codes.htm\r
+cmdline\commands\update.htm\r
+cmdline\commands\delete.htm\r
+cmdline\commands\extract.htm\r
+cmdline\commands\extract_full.htm\r
+cmdline\commands\index.htm\r
+cmdline\commands\list.htm\r
+cmdline\commands\test.htm\r
+cmdline\commands\add.htm\r
+cmdline\commands\bench.htm\r
+cmdline\switches\index.htm\r
+cmdline\switches\yes.htm\r
+cmdline\switches\include.htm\r
+cmdline\switches\method.htm\r
+cmdline\switches\ar_include.htm\r
+cmdline\switches\ar_exclude.htm\r
+cmdline\switches\ar_no.htm\r
+cmdline\switches\scc.htm\r
+cmdline\switches\charset.htm\r
+cmdline\switches\email.htm\r
+cmdline\switches\list_tech.htm\r
+cmdline\switches\large_pages.htm\r
+cmdline\switches\output_dir.htm\r
+cmdline\switches\overwrite.htm\r
+cmdline\switches\password.htm\r
+cmdline\switches\recurse.htm\r
+cmdline\switches\sfx.htm\r
+cmdline\switches\shared.htm\r
+cmdline\switches\ssc.htm\r
+cmdline\switches\stdin.htm\r
+cmdline\switches\stdout.htm\r
+cmdline\switches\stop_switch.htm\r
+cmdline\switches\type.htm\r
+cmdline\switches\update.htm\r
+cmdline\switches\working_dir.htm\r
+cmdline\switches\exclude.htm\r
+fm\options.htm\r
+fm\benchmark.htm\r
+fm\index.htm\r
+fm\menu.htm\r
+fm\about.htm\r
+fm\plugins\index.htm\r
+fm\plugins\7-zip\extract.htm\r
+fm\plugins\7-zip\index.htm\r
+fm\plugins\7-zip\add.htm\r
+\r
+[INFOTYPES]\r
+\r
diff --git a/DOC/7zip.inf b/DOC/7zip.inf
new file mode 100755 (executable)
index 0000000..b5758ff
--- /dev/null
@@ -0,0 +1,55 @@
+[CODE]\r
+\r
+[Version]\r
+Signature = "$Windows NT$"\r
+Provider = "7-zip.org"\r
+CESignature = "$Windows CE$"\r
+\r
+[CEStrings]\r
+AppName = "7-Zip"\r
+InstallDir = %CE1%\%AppName%\r
+\r
+[Strings]\r
+AppVer = "9.20"\r
+AppDate = "2010-11-18"\r
+\r
+[CEDevice]\r
+; ProcessorType = 2577 ; ARM\r
+VersionMin = 3.0\r
+BuildMin = 0.0\r
+VersionMax = 1000.0\r
+BuildMax = 0xE0000000\r
+\r
+[DefaultInstall]\r
+CopyFiles = CopyFilesSection,CopyFilesSection.Lang\r
+AddReg = RegSettings\r
+CEShortcuts = Shortcuts\r
+\r
+[SourceDisksNames]\r
+1 = ,"Common files",,"."\r
+2 = ,"Lang files",,"Lang"\r
+\r
+[SourceDisksFiles]\r
+7zFM.exe = 1\r
+7z.sfx = 1\r
+7zS2.sfx = 1\r
+ru.txt = 2\r
+\r
+[DestinationDirs]\r
+DefaultDestDir = ,%InstallDir%\r
+CopyFilesSection = ,%InstallDir%\r
+CopyFilesSection.Lang = ,"%InstallDir%\Lang"\r
+Shortcuts = ,%CE11%\r
+\r
+[CopyFilesSection]\r
+7zFM.exe\r
+7z.sfx\r
+7zS2.sfx\r
+\r
+[CopyFilesSection.Lang]\r
+ru.txt\r
+\r
+[RegSettings]\r
+\r
+[Shortcuts]\r
+7-Zip,0,7zFM.exe\r
diff --git a/DOC/7zip.nsi b/DOC/7zip.nsi
new file mode 100755 (executable)
index 0000000..6ff701d
--- /dev/null
@@ -0,0 +1,535 @@
+;--------------------------------\r
+;Defines\r
+\r
+!define VERSION_MAJOR 9\r
+!define VERSION_MINOR 20\r
+!define VERSION_POSTFIX_FULL ""\r
+!ifdef WIN64\r
+!ifdef IA64\r
+!define VERSION_SYS_POSTFIX_FULL " for Windows IA-64"\r
+!else\r
+!define VERSION_SYS_POSTFIX_FULL " for Windows x64"\r
+!endif\r
+!else\r
+!define VERSION_SYS_POSTFIX_FULL ""\r
+!endif\r
+!define NAME_FULL "7-Zip ${VERSION_MAJOR}.${VERSION_MINOR}${VERSION_POSTFIX_FULL}${VERSION_SYS_POSTFIX_FULL}"\r
+!define VERSION_POSTFIX ""\r
+!ifdef WIN64\r
+!ifdef IA64\r
+!define VERSION_SYS_POSTFIX "-ia64"\r
+!else\r
+!define VERSION_SYS_POSTFIX "-x64"\r
+!endif\r
+!else\r
+!define VERSION_SYS_POSTFIX ""\r
+!endif\r
+\r
+\r
+\r
+!define FM_LINK "7-Zip File Manager.lnk"\r
+!define HELP_LINK "7-Zip Help.lnk"\r
+\r
+!define CLSID_CONTEXT_MENU {23170F69-40C1-278A-1000-000100020000}\r
+\r
+#!define NO_COMPRESSION\r
+\r
+  !include "Library.nsh"\r
+  !include "MUI.nsh"\r
+\r
+;--------------------------------\r
+;Configuration\r
+\r
+  ;General\r
+  Name "${NAME_FULL}"\r
+  BrandingText "www.7-zip.org"\r
+  OutFile "..\7z${VERSION_MAJOR}${VERSION_MINOR}${VERSION_POSTFIX}${VERSION_SYS_POSTFIX}.exe"\r
+\r
+  ;Folder selection page\r
+  InstallDir "$PROGRAMFILES\7-Zip"\r
+  \r
+  ;Get install folder from registry if available\r
+  InstallDirRegKey HKLM "Software\7-Zip" "Path"\r
+\r
+  ;Compressor\r
+!ifndef NO_COMPRESSION\r
+  SetCompressor /solid lzma\r
+  ; SetCompressorFilter 1\r
+!ifdef IA64\r
+  SetCompressorDictSize 8\r
+!else\r
+  SetCompressorDictSize 4\r
+!endif\r
+!else\r
+  SetCompress off\r
+!endif\r
+\r
+\r
+;--------------------------------\r
+;Variables\r
+\r
+;--------------------------------\r
+;Interface Settings\r
+\r
+  !define MUI_ABORTWARNING\r
+\r
+;--------------------------------\r
+;Pages\r
+\r
+  #!insertmacro MUI_PAGE_LICENSE "License.txt"\r
+  !insertmacro MUI_PAGE_DIRECTORY\r
+  !insertmacro MUI_PAGE_INSTFILES\r
+  !insertmacro MUI_PAGE_FINISH\r
+  \r
+  !insertmacro MUI_UNPAGE_CONFIRM\r
+  !insertmacro MUI_UNPAGE_INSTFILES\r
+  !insertmacro MUI_UNPAGE_FINISH\r
+  \r
+;--------------------------------\r
+;Languages\r
\r
+  !insertmacro MUI_LANGUAGE "English"\r
+\r
+;--------------------------------\r
+;Reserve Files\r
+  \r
+  ;These files should be inserted before other files in the data block\r
+  ;Keep these lines before any File command\r
+  ;Only for solid compression (by default, solid compression is enabled for BZIP2 and LZMA)\r
+  \r
+  !insertmacro MUI_RESERVEFILE_LANGDLL\r
+\r
+;--------------------------------\r
+;Installer Sections\r
+\r
+Section\r
+  !ifndef WIN64\r
+  DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\App Paths\7zFMn.exe"\r
+  !endif\r
+\r
+  # delete old unwanted files\r
+  Delete $INSTDIR\7zFMn.exe\r
+  Delete $INSTDIR\7zgn.exe\r
+  Delete $INSTDIR\7zn.exe\r
+  Delete $INSTDIR\7zan.exe\r
+  Delete $INSTDIR\7zC.sfx\r
+  Delete $INSTDIR\7-zipn.dll\r
+  Delete $INSTDIR\7zipDoc.txt\r
+  Delete $INSTDIR\file_id.diz\r
+\r
+  Delete $INSTDIR\Codecs\7zAES.dll\r
+  Delete $INSTDIR\Codecs\AES.dll\r
+  Delete $INSTDIR\Codecs\Branch.dll\r
+  Delete $INSTDIR\Codecs\BZip2.dll\r
+  Delete $INSTDIR\Codecs\Copy.dll\r
+  Delete $INSTDIR\Codecs\Deflate.dll\r
+  Delete $INSTDIR\Codecs\Implode.dll\r
+  Delete $INSTDIR\Codecs\LZMA.dll\r
+  Delete $INSTDIR\Codecs\PPMD.dll\r
+  Delete $INSTDIR\Codecs\Rar29.dll\r
+  Delete $INSTDIR\Codecs\Swap.dll\r
+\r
+  RMDir $INSTDIR\Codecs\r
+\r
+  Delete $INSTDIR\Formats\7z.dll\r
+  Delete $INSTDIR\Formats\arj.dll\r
+  Delete $INSTDIR\Formats\bz2.dll\r
+  Delete $INSTDIR\Formats\cab.dll\r
+  Delete $INSTDIR\Formats\chm.dll\r
+  Delete $INSTDIR\Formats\cpio.dll\r
+  Delete $INSTDIR\Formats\deb.dll\r
+  Delete $INSTDIR\Formats\gz.dll\r
+  Delete $INSTDIR\Formats\iso.dll\r
+  Delete $INSTDIR\Formats\lzh.dll\r
+  Delete $INSTDIR\Formats\nsis.dll\r
+  Delete $INSTDIR\Formats\rar.dll\r
+  Delete $INSTDIR\Formats\rpm.dll\r
+  Delete $INSTDIR\Formats\split.dll\r
+  Delete $INSTDIR\Formats\tar.dll\r
+  Delete $INSTDIR\Formats\z.dll\r
+  Delete $INSTDIR\Formats\zip.dll\r
+\r
+  RMDir $INSTDIR\Formats\r
+\r
+  Delete $INSTDIR\Lang\no.txt\r
+\r
+  # install files\r
+  SetOutPath "$INSTDIR"\r
+\r
+  File descript.ion\r
+  File History.txt\r
+  File License.txt\r
+  File readme.txt\r
+\r
+  # File 7-zip.dll\r
+  # File 7-zipn.dll\r
+  File 7zFM.exe\r
+  File 7z.exe\r
+  !ifdef WIN64\r
+  File 7za.exe\r
+  !endif\r
+  File 7zg.exe\r
+\r
+  File 7z.sfx\r
+  File 7zCon.sfx\r
+\r
+  File 7-zip.chm\r
+\r
+  File 7z.dll\r
+\r
+  SetOutPath $INSTDIR\Lang\r
+\r
+  File en.ttt\r
+  File af.txt\r
+  File ar.txt\r
+  File ast.txt\r
+  File az.txt\r
+  File ba.txt\r
+  File be.txt\r
+  File bg.txt\r
+  File bn.txt\r
+  File br.txt\r
+  File ca.txt\r
+  File cs.txt\r
+  File cy.txt\r
+  File da.txt\r
+  File de.txt\r
+  File el.txt\r
+  File eo.txt\r
+  File es.txt\r
+  File et.txt\r
+  File eu.txt\r
+  File ext.txt\r
+  File fa.txt\r
+  File fi.txt\r
+  File fr.txt\r
+  File fur.txt\r
+  File fy.txt\r
+  File gl.txt\r
+  File gu.txt\r
+  File he.txt\r
+  File hi.txt\r
+  File hr.txt\r
+  File hu.txt\r
+  File hy.txt\r
+  File id.txt\r
+  File io.txt\r
+  File is.txt\r
+  File it.txt\r
+  File ja.txt\r
+  File ka.txt\r
+  File kk.txt\r
+  File ko.txt\r
+  File ku.txt\r
+  File ku-ckb.txt\r
+  File lt.txt\r
+  File lv.txt\r
+  File mk.txt\r
+  File mn.txt\r
+  File mr.txt\r
+  File ms.txt\r
+  File ne.txt\r
+  File nl.txt\r
+  File nb.txt\r
+  File nn.txt\r
+  File pa-in.txt\r
+  File pl.txt\r
+  File ps.txt\r
+  File pt.txt\r
+  File pt-br.txt\r
+  File ro.txt\r
+  File ru.txt\r
+  File sa.txt\r
+  File si.txt\r
+  File sk.txt\r
+  File sl.txt\r
+  File sq.txt\r
+  File sr-spc.txt\r
+  File sr-spl.txt\r
+  File sv.txt\r
+  File ta.txt\r
+  File th.txt\r
+  File tr.txt\r
+  File tt.txt\r
+  File ug.txt\r
+  File uk.txt\r
+  File uz.txt\r
+  File va.txt\r
+  File vi.txt\r
+  File zh-cn.txt\r
+  File zh-tw.txt\r
+\r
+  SetOutPath $INSTDIR\r
+\r
+  # delete "current user" menu items\r
+\r
+  Delete "$SMPROGRAMS\7-Zip\${FM_LINK}"\r
+  Delete "$SMPROGRAMS\7-Zip\${HELP_LINK}"\r
+  RMDir  "$SMPROGRAMS\7-Zip"\r
+\r
+  # set "all users" mode\r
+\r
+  SetShellVarContext all\r
+\r
+  !insertmacro InstallLib DLL NOTSHARED REBOOT_NOTPROTECTED 7-zip.dll $INSTDIR\7-zip.dll $INSTDIR\r
+\r
+  ClearErrors\r
+\r
+  # create start menu icons\r
+  SetOutPath $INSTDIR # working directory\r
+  CreateDirectory $SMPROGRAMS\7-Zip\r
+\r
+  CreateShortcut "$SMPROGRAMS\7-Zip\${FM_LINK}" $INSTDIR\7zFM.exe\r
+  CreateShortcut "$SMPROGRAMS\7-Zip\${HELP_LINK}" $INSTDIR\7-zip.chm\r
+\r
+  IfErrors 0 noScErrors\r
+\r
+  SetShellVarContext current\r
+\r
+  CreateDirectory $SMPROGRAMS\7-Zip\r
+  CreateShortcut "$SMPROGRAMS\7-Zip\${FM_LINK}" $INSTDIR\7zFM.exe\r
+  CreateShortcut "$SMPROGRAMS\7-Zip\${HELP_LINK}" $INSTDIR\7-zip.chm\r
+\r
+  noScErrors:\r
+\r
+  # store install folder\r
+  WriteRegStr HKLM "Software\7-Zip" "Path" $INSTDIR\r
+  WriteRegStr HKCU "Software\7-Zip" "Path" $INSTDIR\r
+\r
+  # write reg entries\r
+  WriteRegStr HKCR "CLSID\${CLSID_CONTEXT_MENU}" "" "7-Zip Shell Extension"\r
+  WriteRegStr HKCR "CLSID\${CLSID_CONTEXT_MENU}\InprocServer32" "" "$INSTDIR\7-zip.dll"\r
+  WriteRegStr HKCR "CLSID\${CLSID_CONTEXT_MENU}\InprocServer32" "ThreadingModel" "Apartment"\r
+\r
+\r
+  WriteRegStr HKCR "*\shellex\ContextMenuHandlers\7-Zip" "" "${CLSID_CONTEXT_MENU}"\r
+  WriteRegStr HKCR "Directory\shellex\ContextMenuHandlers\7-Zip" "" "${CLSID_CONTEXT_MENU}"\r
+;  WriteRegStr HKCR "Folder\shellex\ContextMenuHandlers\7-Zip" "" "${CLSID_CONTEXT_MENU}"\r
+\r
+  WriteRegStr HKCR "Directory\shellex\DragDropHandlers\7-Zip" "" "${CLSID_CONTEXT_MENU}"\r
+  WriteRegStr HKCR "Drive\shellex\DragDropHandlers\7-Zip" "" "${CLSID_CONTEXT_MENU}"\r
+\r
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved" "${CLSID_CONTEXT_MENU}" "7-Zip Shell Extension"\r
+  \r
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\App Paths\7zFM.exe" "" "$INSTDIR\7zFM.exe"\r
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\App Paths\7zFM.exe" "Path" "$INSTDIR"\r
+\r
+  # create uninstaller\r
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip" "DisplayName" "${NAME_FULL}"\r
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip" "UninstallString" '"$INSTDIR\Uninstall.exe"'\r
+  WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip" "NoModify" 1\r
+  WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip" "NoRepair" 1\r
+  WriteUninstaller $INSTDIR\Uninstall.exe\r
+\r
+  DeleteRegValue HKCR "CLSID\${CLSID_CONTEXT_MENU}\InprocServer32" "InprocServer32"\r
+\r
+  !ifdef WIN64\r
+  ExecWait 'regsvr32 /s "$INSTDIR\7-zip.dll"'\r
+  !endif\r
+\r
+SectionEnd\r
\r
+\r
+;--------------------------------\r
+;Installer Functions\r
+\r
+/*\r
+Function .onInit\r
+\r
+  !insertmacro MUI_LANGDLL_DISPLAY\r
+\r
+FunctionEnd\r
+*/\r
+\r
+;--------------------------------\r
+;Uninstaller Section\r
+\r
+Section "Uninstall"\r
+\r
+  ExecWait 'regsvr32 /u /s "$INSTDIR\7-zip.dll"'\r
+\r
+  # delete files\r
+\r
+  Delete $INSTDIR\descript.ion\r
+  Delete $INSTDIR\History.txt\r
+  Delete $INSTDIR\License.txt\r
+  Delete $INSTDIR\copying.txt\r
+  Delete $INSTDIR\readme.txt\r
+  Delete $INSTDIR\7zip_pad.xml\r
+\r
+  Delete /REBOOTOK $INSTDIR\7-zip.dll\r
+  Delete $INSTDIR\7zFM.exe\r
+  Delete $INSTDIR\7z.exe\r
+  !ifdef WIN64\r
+  Delete $INSTDIR\7za.exe\r
+  !endif\r
+  Delete $INSTDIR\7zg.exe\r
+\r
+  Delete $INSTDIR\7z.sfx\r
+  Delete $INSTDIR\7zCon.sfx\r
+  Delete $INSTDIR\7zC.sfx\r
+\r
+  Delete $INSTDIR\7-zip.chm\r
+\r
+  Delete $INSTDIR\7z.dll\r
+\r
+  Delete $INSTDIR\Lang\en.ttt\r
+  Delete $INSTDIR\Lang\af.txt\r
+  Delete $INSTDIR\Lang\ar.txt\r
+  Delete $INSTDIR\Lang\ast.txt\r
+  Delete $INSTDIR\Lang\az.txt\r
+  Delete $INSTDIR\Lang\ba.txt\r
+  Delete $INSTDIR\Lang\be.txt\r
+  Delete $INSTDIR\Lang\bg.txt\r
+  Delete $INSTDIR\Lang\bn.txt\r
+  Delete $INSTDIR\Lang\br.txt\r
+  Delete $INSTDIR\Lang\ca.txt\r
+  Delete $INSTDIR\Lang\cs.txt\r
+  Delete $INSTDIR\Lang\cy.txt\r
+  Delete $INSTDIR\Lang\da.txt\r
+  Delete $INSTDIR\Lang\de.txt\r
+  Delete $INSTDIR\Lang\el.txt\r
+  Delete $INSTDIR\Lang\eo.txt\r
+  Delete $INSTDIR\Lang\es.txt\r
+  Delete $INSTDIR\Lang\et.txt\r
+  Delete $INSTDIR\Lang\eu.txt\r
+  Delete $INSTDIR\Lang\ext.txt\r
+  Delete $INSTDIR\Lang\fa.txt\r
+  Delete $INSTDIR\Lang\fi.txt\r
+  Delete $INSTDIR\Lang\fr.txt\r
+  Delete $INSTDIR\Lang\fur.txt\r
+  Delete $INSTDIR\Lang\fy.txt\r
+  Delete $INSTDIR\Lang\gl.txt\r
+  Delete $INSTDIR\Lang\gu.txt\r
+  Delete $INSTDIR\Lang\he.txt\r
+  Delete $INSTDIR\Lang\hi.txt\r
+  Delete $INSTDIR\Lang\hr.txt\r
+  Delete $INSTDIR\Lang\hu.txt\r
+  Delete $INSTDIR\Lang\hy.txt\r
+  Delete $INSTDIR\Lang\id.txt\r
+  Delete $INSTDIR\Lang\io.txt\r
+  Delete $INSTDIR\Lang\is.txt\r
+  Delete $INSTDIR\Lang\it.txt\r
+  Delete $INSTDIR\Lang\ja.txt\r
+  Delete $INSTDIR\Lang\ka.txt\r
+  Delete $INSTDIR\Lang\kk.txt\r
+  Delete $INSTDIR\Lang\ko.txt\r
+  Delete $INSTDIR\Lang\ku.txt\r
+  Delete $INSTDIR\Lang\ku-ckb.txt\r
+  Delete $INSTDIR\Lang\lt.txt\r
+  Delete $INSTDIR\Lang\lv.txt\r
+  Delete $INSTDIR\Lang\mk.txt\r
+  Delete $INSTDIR\Lang\mn.txt\r
+  Delete $INSTDIR\Lang\mr.txt\r
+  Delete $INSTDIR\Lang\ms.txt\r
+  Delete $INSTDIR\Lang\ne.txt\r
+  Delete $INSTDIR\Lang\nl.txt\r
+  Delete $INSTDIR\Lang\nb.txt\r
+  Delete $INSTDIR\Lang\nn.txt\r
+  Delete $INSTDIR\Lang\pa-in.txt\r
+  Delete $INSTDIR\Lang\pl.txt\r
+  Delete $INSTDIR\Lang\ps.txt\r
+  Delete $INSTDIR\Lang\pt.txt\r
+  Delete $INSTDIR\Lang\pt-br.txt\r
+  Delete $INSTDIR\Lang\ro.txt\r
+  Delete $INSTDIR\Lang\ru.txt\r
+  Delete $INSTDIR\Lang\sa.txt\r
+  Delete $INSTDIR\Lang\si.txt\r
+  Delete $INSTDIR\Lang\sk.txt\r
+  Delete $INSTDIR\Lang\sl.txt\r
+  Delete $INSTDIR\Lang\sq.txt\r
+  Delete $INSTDIR\Lang\sr.txt\r
+  Delete $INSTDIR\Lang\sr-spc.txt\r
+  Delete $INSTDIR\Lang\sr-spl.txt\r
+  Delete $INSTDIR\Lang\sv.txt\r
+  Delete $INSTDIR\Lang\ta.txt\r
+  Delete $INSTDIR\Lang\th.txt\r
+  Delete $INSTDIR\Lang\tr.txt\r
+  Delete $INSTDIR\Lang\tt.txt\r
+  Delete $INSTDIR\Lang\ug.txt\r
+  Delete $INSTDIR\Lang\uk.txt\r
+  Delete $INSTDIR\Lang\uz.txt\r
+  Delete $INSTDIR\Lang\va.txt\r
+  Delete $INSTDIR\Lang\vi.txt\r
+  Delete $INSTDIR\Lang\vr.txt\r
+  Delete $INSTDIR\Lang\zh-cn.txt\r
+  Delete $INSTDIR\Lang\zh-tw.txt\r
+\r
+  RMDir $INSTDIR\Lang\r
+\r
+  Delete $INSTDIR\Uninstall.exe\r
+\r
+  RMDir $INSTDIR\r
+\r
+  # delete start menu entires\r
+\r
+  SetShellVarContext all\r
+\r
+  # ClearErrors\r
+\r
+  Delete "$SMPROGRAMS\7-Zip\${FM_LINK}"\r
+  Delete "$SMPROGRAMS\7-Zip\${HELP_LINK}"\r
+  RMDir  "$SMPROGRAMS\7-Zip"\r
+\r
+  # IfErrors 0 noScErrors\r
+\r
+  SetShellVarContext current\r
+\r
+  Delete "$SMPROGRAMS\7-Zip\${FM_LINK}"\r
+  Delete "$SMPROGRAMS\7-Zip\${HELP_LINK}"\r
+  RMDir  "$SMPROGRAMS\7-Zip"\r
+\r
+  # noScErrors:\r
+\r
+\r
+  # delete registry entries\r
+\r
+  DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip"\r
+  DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\App Paths\7zFM.exe"\r
+\r
+  DeleteRegKey HKLM "Software\7-Zip"\r
+  DeleteRegKey HKCU "Software\7-Zip"\r
+\r
+  DeleteRegKey HKCR "CLSID\${CLSID_CONTEXT_MENU}"\r
+\r
+  DeleteRegKey HKCR "*\shellex\ContextMenuHandlers\7-Zip"\r
+  DeleteRegKey HKCR "Directory\shellex\ContextMenuHandlers\7-Zip"\r
+  DeleteRegKey HKCR "Folder\shellex\ContextMenuHandlers\7-Zip"\r
+\r
+  DeleteRegKey HKCR "Directory\shellex\DragDropHandlers\7-Zip"\r
+  DeleteRegKey HKCR "Folder\shellex\DragDropHandlers\7-Zip"\r
+\r
+  DeleteRegValue HKLM "Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved" "${CLSID_CONTEXT_MENU}"\r
+\r
+  DeleteRegKey HKCR "7-Zip.001"\r
+  DeleteRegKey HKCR "7-Zip.7z"\r
+  DeleteRegKey HKCR "7-Zip.arj"\r
+  DeleteRegKey HKCR "7-Zip.bz2"\r
+  DeleteRegKey HKCR "7-Zip.bzip2"\r
+  DeleteRegKey HKCR "7-Zip.tbz"\r
+  DeleteRegKey HKCR "7-Zip.tbz2"\r
+  DeleteRegKey HKCR "7-Zip.cab"\r
+  DeleteRegKey HKCR "7-Zip.cpio"\r
+  DeleteRegKey HKCR "7-Zip.deb"\r
+  DeleteRegKey HKCR "7-Zip.dmg"\r
+  DeleteRegKey HKCR "7-Zip.gz"\r
+  DeleteRegKey HKCR "7-Zip.gzip"\r
+  DeleteRegKey HKCR "7-Zip.hfs"\r
+  DeleteRegKey HKCR "7-Zip.iso"\r
+  DeleteRegKey HKCR "7-Zip.lha"\r
+  DeleteRegKey HKCR "7-Zip.lzh"\r
+  DeleteRegKey HKCR "7-Zip.lzma"\r
+  DeleteRegKey HKCR "7-Zip.rar"\r
+  DeleteRegKey HKCR "7-Zip.rpm"\r
+  DeleteRegKey HKCR "7-Zip.split"\r
+  DeleteRegKey HKCR "7-Zip.swm"\r
+  DeleteRegKey HKCR "7-Zip.tar"\r
+  DeleteRegKey HKCR "7-Zip.taz"\r
+  DeleteRegKey HKCR "7-Zip.tgz"\r
+  DeleteRegKey HKCR "7-Zip.tpz"\r
+  DeleteRegKey HKCR "7-Zip.wim"\r
+  DeleteRegKey HKCR "7-Zip.xar"\r
+  DeleteRegKey HKCR "7-Zip.z"\r
+  DeleteRegKey HKCR "7-Zip.zip"\r
+\r
+SectionEnd\r
diff --git a/DOC/7zip.wxs b/DOC/7zip.wxs
new file mode 100755 (executable)
index 0000000..1d3d0a9
--- /dev/null
@@ -0,0 +1,353 @@
+<?xml version="1.0"?>\r
+\r
+<?define VerMajor = "9" ?>\r
+<?define VerMinor = "20" ?>\r
+<?define VerBuild = "00" ?>\r
+<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>\r
+<?define MmHex = "0$(var.VerMajor)$(var.VerMinor)" ?>\r
+<?define MmmmVer = "$(var.MmVer).$(var.VerBuild).0" ?>\r
+<?define UpgradeMinVer = "4.38" ?>\r
+\r
+<?define ProductName = "7-Zip" ?>\r
+\r
+<?ifndef MyCPU?>\r
+  <?define MyCPU = "Intel" ?>\r
+<?endif?>\r
+\r
+<?if $(var.MyCPU) = "x64" ?>\r
+  <?define CpuId = "2" ?>\r
+  <?define PFilesFolder = "ProgramFiles64Folder" ?>\r
+  <?define Platforms = "x64" ?>\r
+  <?define CpuPostfix = " (x64 edition)" ?>\r
+  <?define Is64 = "yes" ?>\r
+<?elseif $(var.MyCPU) = "ia64" ?>\r
+  <?define CpuId = "3" ?>\r
+  <?define PFilesFolder = "ProgramFiles64Folder" ?>\r
+  <?define Platforms = "Intel64" ?>\r
+  <?define CpuPostfix = " (ia64 edition)" ?>\r
+  <?define Is64 = "yes" ?>\r
+<?else ?>\r
+  <?define CpuId = "1" ?>\r
+  <?define PFilesFolder = "ProgramFilesFolder" ?>\r
+  <?define Platforms = "Intel" ?>\r
+  <?define CpuPostfix = "" ?>\r
+  <?define Is64 = "no" ?>\r
+<?endif ?>\r
+\r
+\r
+<?define ShellExtId = "{23170F69-40C1-278A-1000-000100020000}" ?>\r
+\r
+<?define BaseId = "23170F69-40C1-270$(var.CpuId)" ?>\r
+<?define BaseIdVer = "$(var.BaseId)-$(var.MmHex)-$(var.VerBuild)00" ?>\r
+<?define ProductId   = "$(var.BaseIdVer)01000000" ?>\r
+<?define PackageId   = "$(var.BaseIdVer)02000000" ?>\r
+<?define CompId      = "$(var.BaseIdVer)030000" ?>\r
+<?define UpgradeCode = "$(var.BaseId)-0000-000004000000" ?>\r
+\r
+<?define CompFm       = "$(var.CompId)01" ?>\r
+<?define CompShellExt = "$(var.CompId)02" ?>\r
+<?define CompCmdLine  = "$(var.CompId)03" ?>\r
+<?define CompCmdLineA = "$(var.CompId)04" ?>\r
+<?define CompGui      = "$(var.CompId)05" ?>\r
+<?define CompGuiSfx   = "$(var.CompId)06" ?>\r
+<?define CompConSfx   = "$(var.CompId)07" ?>\r
+<?define CompHelp     = "$(var.CompId)08" ?>\r
+<?define CompDocs     = "$(var.CompId)09" ?>\r
+<?define CompFormats  = "$(var.CompId)10" ?>\r
+<?define CompCodecs   = "$(var.CompId)11" ?>\r
+<?define CompLang     = "$(var.CompId)12" ?>\r
+<?define CompInstallRegCU         = "$(var.CompId)80" ?>\r
+<?define CompInstallRegLM         = "$(var.CompId)81" ?>\r
+<?define CompInstallRegWild       = "$(var.CompId)82" ?>\r
+<?define CompInstallRegDirectory  = "$(var.CompId)83" ?>\r
+<?define CompInstallRegDirDD      = "$(var.CompId)84" ?>\r
+<?define CompInstallRegDriveDD    = "$(var.CompId)85" ?>\r
+<?define CompInstallRegApproved   = "$(var.CompId)86" ?>\r
+<?define CompInstallRegAppPath    = "$(var.CompId)87" ?>\r
+\r
+\r
+<?define Manufacturer = "Igor Pavlov" ?>\r
+<?define HomePage = "http://www.7-zip.org/" ?>\r
+<?define AboutURL = "$(var.HomePage)" ?>\r
+<?define UpdatesURL = "$(var.HomePage)download.html" ?>\r
+<?define SupportURL = "$(var.HomePage)support.html" ?>\r
+\r
+<Wix xmlns="http://schemas.microsoft.com/wix/2003/01/wi">\r
+  <Product\r
+      Id="$(var.ProductId)"\r
+      UpgradeCode="$(var.UpgradeCode)"\r
+      Name="$(var.ProductName) $(var.MmVer)$(var.CpuPostfix)"\r
+      Language="1033"\r
+      Version="$(var.MmmmVer)"\r
+      Manufacturer="$(var.Manufacturer)">\r
+   \r
+    <Package\r
+        Id="$(var.PackageId)"\r
+        Description="$(var.ProductName)$(var.CpuPostfix) Package"\r
+        Comments="$(var.ProductName)$(var.CpuPostfix) Package"\r
+        Manufacturer="$(var.Manufacturer)"\r
+        InstallerVersion="200"\r
+        Compressed="yes"\r
+        Platforms="$(var.Platforms)"\r
+        />\r
+\r
+    <!-- Major upgrade -->\r
+    <Upgrade Id="$(var.UpgradeCode)">\r
+      <UpgradeVersion Minimum="$(var.UpgradeMinVer)" IncludeMinimum="yes"\r
+           Maximum="$(var.MmmmVer)" IncludeMaximum="no" Property="OLDERVERSIONBEINGUPGRADED" />\r
+    </Upgrade>\r
+\r
+    <Media Id="1" Cabinet="product.cab" EmbedCab="yes" CompressionLevel="high" />\r
+\r
+    <Property Id="INSTALLDIR">\r
+      <RegistrySearch Id="My7zipPath" Type="raw" Root="HKCU" Key="Software\7-Zip" Name="Path" />\r
+    </Property>\r
+\r
+    <Property Id="ALLUSERS">2</Property>\r
+\r
+\r
+    <Property Id="ARPURLINFOABOUT" Value="$(var.AboutURL)" />\r
+    <Property Id="ARPHELPLINK" Value="$(var.SupportURL)" />\r
+    <Property Id="ARPURLUPDATEINFO" Value="$(var.UpdatesURL)" />\r
+\r
+\r
+    <Directory Id="TARGETDIR" Name="SourceDir">\r
+      <Directory Id="$(var.PFilesFolder)" Name="Files">\r
+        <Directory Id="INSTALLDIR" Name="7-Zip">\r
+\r
+          <Component Id="InstallRegCU" Guid="$(var.CompInstallRegCU)" DiskId="1" Win64="$(var.Is64)">\r
+            <Registry Id="MyInstallRegCU" Root="HKCU" Key="Software\7-Zip" Name="Path"\r
+               Action="write" Type="string" Value="[INSTALLDIR]" />\r
+          </Component>\r
+          <Component Id="InstallRegLM" Guid="$(var.CompInstallRegLM)" DiskId="1" Win64="$(var.Is64)">\r
+            <Condition>Privileged</Condition>\r
+            <Registry Id="MyInstallRegLM" Root="HKLM" Key="Software\7-Zip" Name="Path"\r
+               Action="write" Type="string" Value="[INSTALLDIR]" />\r
+          </Component>\r
+          \r
+\r
+          <Component Id="InstallRegWild" Guid="$(var.CompInstallRegWild)" DiskId="1" Win64="$(var.Is64)">\r
+            <Registry Id="MyInstallRegWild" Action="write" Type="string"\r
+               Root="HKCR" Key="*\shellex\ContextMenuHandlers\7-Zip"\r
+               Value="$(var.ShellExtId)" />\r
+          </Component>\r
+\r
+          <Component Id="InstallRegDirectory" Guid="$(var.CompInstallRegDirectory)" DiskId="1" Win64="$(var.Is64)">\r
+            <Registry Id="MyInstallRegDirectory" Action="write" Type="string"\r
+               Root="HKCR" Key="Directory\shellex\ContextMenuHandlers\7-Zip"\r
+               Value="$(var.ShellExtId)" />\r
+          </Component>\r
+\r
+          <Component Id="InstallRegDirDD" Guid="$(var.CompInstallRegDirDD)" DiskId="1" Win64="$(var.Is64)">\r
+            <Registry Id="MyInstallRegDirDD" Action="write" Type="string"\r
+               Root="HKCR" Key="Directory\shellex\DragDropHandlers\7-Zip"\r
+               Value="$(var.ShellExtId)" />\r
+          </Component>\r
+\r
+          <Component Id="InstallRegDriveDD" Guid="$(var.CompInstallRegDriveDD)" DiskId="1" Win64="$(var.Is64)">\r
+            <Registry Id="MyInstallRegDriveDD" Action="write" Type="string"\r
+               Root="HKCR" Key="Drive\shellex\DragDropHandlers\7-Zip"\r
+               Value="$(var.ShellExtId)" />\r
+          </Component>\r
+\r
+          <Component Id="InstallRegApproved" Guid="$(var.CompInstallRegApproved)" DiskId="1" Win64="$(var.Is64)">\r
+            <Condition>Privileged</Condition>\r
+            <Registry Id="MyInstallRegApproved" Action="write" Type="string"\r
+               Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved"\r
+               Name="$(var.ShellExtId)" Value="7-Zip Shell Extension" />\r
+          </Component>\r
+\r
+\r
+          <Component Id="InstallRegAppPath" Guid="$(var.CompInstallRegAppPath)" DiskId="1" Win64="$(var.Is64)">\r
+            <Condition>Privileged</Condition>\r
+            <Registry Id="MyInstallRegAppPath" Action="write" Type="string"\r
+               Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\App Paths\7zFM.exe"\r
+               Value="[INSTALLDIR]7zFM.exe" />\r
+            <Registry Id="MyInstallRegAppPath2" Action="write" Type="string"\r
+               Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\App Paths\7zFM.exe" Name="Path"\r
+               Value="[INSTALLDIR]" />\r
+          </Component>\r
+\r
+          <Component Id="Fm" Guid="$(var.CompFm)" DiskId="1" Win64="$(var.Is64)">\r
+            <File Id="_7zFM.exe" Name="7zFM.exe">\r
+              <Shortcut Id="startmenuFmShortcut" Directory="PMenu" Name="7zipFM" LongName="7-Zip File Manager" />\r
+            </File>\r
+          </Component>\r
+\r
+          <Component Id="ShellExt" Guid="$(var.CompShellExt)" DiskId="1" Win64="$(var.Is64)">\r
+            <File Id="_7zip.dll" Name="7-zip.dll" />\r
+            <Registry Id="shellReg0" Action="write" Type="string" Root="HKCR"\r
+               Key="CLSID\$(var.ShellExtId)\InprocServer32"\r
+               Value="[INSTALLDIR]7-zip.dll" />\r
+            <Registry Id="shellReg1" Action="write" Type="string" Root="HKCR"\r
+               Key="CLSID\$(var.ShellExtId)\InprocServer32"\r
+               Name="ThreadingModel"\r
+               Value="Apartment" />\r
+          </Component>\r
+\r
+          <Component Id="CmdLine" Guid="$(var.CompCmdLine)" DiskId="1" Win64="$(var.Is64)">\r
+            <File Id="_7z.exe" Name="7z.exe" />\r
+          </Component>\r
+\r
+          <Component Id="Gui" Guid="$(var.CompGui)" DiskId="1" Win64="$(var.Is64)">\r
+            <File Id="_7zG.exe" Name="7zG.exe" />\r
+          </Component>\r
+\r
+          <Component Id="Formats" Guid="$(var.CompFormats)" DiskId="1" Win64="$(var.Is64)">\r
+              <File Id="_7z.dll" Name="7z.dll" />\r
+          </Component>\r
+\r
+          <Component Id="GuiSfx" Guid="$(var.CompGuiSfx)" DiskId="1" Win64="$(var.Is64)">\r
+            <File Id="_7z.sfx" Name="7z.sfx" />\r
+          </Component>\r
+\r
+          <Component Id="ConSfx" Guid="$(var.CompConSfx)" DiskId="1" Win64="$(var.Is64)">\r
+            <File Id="_7zCon.sfx" Name="7zCon.sfx" />\r
+          </Component>\r
+\r
+          <Component Id="Docs" Guid="$(var.CompDocs)" DiskId="1" Win64="$(var.Is64)">\r
+            <File Id="descript.ion" Name="descript.ion" />\r
+            <File Id="History.txt" Name="History.txt" />\r
+            <File Id="License.txt" Name="License.txt" />\r
+            <File Id="readme.txt" Name="readme.txt" />\r
+          </Component>\r
+\r
+\r
+          <Component Id="Help" Guid="$(var.CompHelp)">\r
+            <File Id="_7zip.chm" Name="7-zip.chm" DiskId="1" >\r
+              <Shortcut Id="startmenuHelpShortcut" Directory="PMenu" Name="7zipHelp" LongName="7-Zip Help" />\r
+            </File>\r
+          </Component>\r
+\r
+          <Directory Id="MyLang" Name="Lang">\r
+            <Component Id="Lang" Guid="$(var.CompLang)" DiskId="1" Win64="$(var.Is64)">\r
+              <File Id="en.ttt" Name="en.ttt" />\r
+              <File Id="af.txt" Name="af.txt" />\r
+              <File Id="ar.txt" Name="ar.txt" />\r
+              <File Id="ast.txt" Name="ast.txt" />\r
+              <File Id="az.txt" Name="az.txt" />\r
+              <File Id="ba.txt" Name="ba.txt" />\r
+              <File Id="be.txt" Name="be.txt" />\r
+              <File Id="bg.txt" Name="bg.txt" />\r
+              <File Id="bn.txt" Name="bn.txt" />\r
+              <File Id="br.txt" Name="br.txt" />\r
+              <File Id="ca.txt" Name="ca.txt" />\r
+              <File Id="cs.txt" Name="cs.txt" />\r
+              <File Id="cy.txt" Name="cy.txt" />\r
+              <File Id="da.txt" Name="da.txt" />\r
+              <File Id="de.txt" Name="de.txt" />\r
+              <File Id="el.txt" Name="el.txt" />\r
+              <File Id="eo.txt" Name="eo.txt" />\r
+              <File Id="es.txt" Name="es.txt" />\r
+              <File Id="et.txt" Name="et.txt" />\r
+              <File Id="eu.txt" Name="eu.txt" />\r
+              <File Id="ext.txt" Name="ext.txt" />\r
+              <File Id="fa.txt" Name="fa.txt" />\r
+              <File Id="fi.txt" Name="fi.txt" />\r
+              <File Id="fr.txt" Name="fr.txt" />\r
+              <File Id="fur.txt" Name="fur.txt" />\r
+              <File Id="fy.txt" Name="fy.txt" />\r
+              <File Id="gl.txt" Name="gl.txt" />\r
+              <File Id="gu.txt" Name="gu.txt" />\r
+              <File Id="he.txt" Name="he.txt" />\r
+              <File Id="hi.txt" Name="hi.txt" />\r
+              <File Id="hr.txt" Name="hr.txt" />\r
+              <File Id="hu.txt" Name="hu.txt" />\r
+              <File Id="hy.txt" Name="hy.txt" />\r
+              <File Id="id.txt" Name="id.txt" />\r
+              <File Id="io.txt" Name="io.txt" />\r
+              <File Id="is.txt" Name="is.txt" />\r
+              <File Id="it.txt" Name="it.txt" />\r
+              <File Id="ja.txt" Name="ja.txt" />\r
+              <File Id="ka.txt" Name="ka.txt" />\r
+              <File Id="kk.txt" Name="kk.txt" />\r
+              <File Id="ko.txt" Name="ko.txt" />\r
+              <File Id="ku.txt" Name="ku.txt" />\r
+              <File Id="ku_ckb.txt" Name="ku-ckb.txt" />\r
+              <File Id="lt.txt" Name="lt.txt" />\r
+              <File Id="lv.txt" Name="lv.txt" />\r
+              <File Id="mk.txt" Name="mk.txt" />\r
+              <File Id="mn.txt" Name="mn.txt" />\r
+              <File Id="mr.txt" Name="mr.txt" />\r
+              <File Id="ms.txt" Name="ms.txt" />\r
+              <File Id="ne.txt" Name="ne.txt" />\r
+              <File Id="nl.txt" Name="nl.txt" />\r
+              <File Id="nb.txt" Name="nb.txt" />\r
+              <File Id="nn.txt" Name="nn.txt" />\r
+              <File Id="pa_in.txt" Name="pa-in.txt" />\r
+              <File Id="pl.txt" Name="pl.txt" />\r
+              <File Id="ps.txt" Name="ps.txt" />\r
+              <File Id="pt.txt" Name="pt.txt" />\r
+              <File Id="pt_br.txt" Name="pt-br.txt" />\r
+              <File Id="ro.txt" Name="ro.txt" />\r
+              <File Id="ru.txt" Name="ru.txt" />\r
+              <File Id="sa.txt" Name="sa.txt" />\r
+              <File Id="si.txt" Name="si.txt" />\r
+              <File Id="sk.txt" Name="sk.txt" />\r
+              <File Id="sl.txt" Name="sl.txt" />\r
+              <File Id="sq.txt" Name="sq.txt" />\r
+              <File Id="sr_spl.txt" Name="sr-spl.txt" />\r
+              <File Id="sr_spc.txt" Name="sr-spc.txt" />\r
+              <File Id="sv.txt" Name="sv.txt" />\r
+              <File Id="ta.txt" Name="ta.txt" />\r
+              <File Id="th.txt" Name="th.txt" />\r
+              <File Id="tr.txt" Name="tr.txt" />\r
+              <File Id="tt.txt" Name="tt.txt" />\r
+              <File Id="ug.txt" Name="ug.txt" />\r
+              <File Id="uk.txt" Name="uk.txt" />\r
+              <File Id="uz.txt" Name="uz.txt" />\r
+              <File Id="va.txt" Name="va.txt" />\r
+              <File Id="vi.txt" Name="vi.txt" />\r
+              <File Id="zh_cn.txt" Name="zh-cn.txt" />\r
+              <File Id="zh_tw.txt" Name="zh-tw.txt" />\r
+            </Component>\r
+          </Directory>\r
+\r
+\r
+        </Directory>\r
+      </Directory>\r
+\r
+      <Directory Id="ProgramMenuFolder" Name="PMenu" LongName="Programs">\r
+        <Directory Id="PMenu" Name="7zip" LongName="7-Zip" />\r
+      </Directory>\r
+    </Directory>\r
+\r
+    <Feature Id="Complete" Title="7-Zip" Description="The complete package."\r
+         Display="expand" Level="1" ConfigurableDirectory="INSTALLDIR"\r
+         Absent="disallow" AllowAdvertise="no" >\r
+      <Feature Id="Program" Title="Program files" Description="Program files." Level="1"\r
+         Absent="disallow" AllowAdvertise="no">\r
+        <ComponentRef Id="Fm" />\r
+        <ComponentRef Id="ShellExt" />\r
+        <ComponentRef Id="CmdLine" />\r
+        <ComponentRef Id="Gui" />\r
+        <ComponentRef Id="GuiSfx" />\r
+        <ComponentRef Id="ConSfx" />\r
+        <ComponentRef Id="Formats" />\r
+        <ComponentRef Id="Docs" />\r
+        <ComponentRef Id="Help" />\r
+        <ComponentRef Id="InstallRegCU" />\r
+        <ComponentRef Id="InstallRegLM" />\r
+        <ComponentRef Id="InstallRegWild" />\r
+        <ComponentRef Id="InstallRegDirectory" />\r
+        <ComponentRef Id="InstallRegDirDD" />\r
+        <ComponentRef Id="InstallRegDriveDD" />\r
+        <ComponentRef Id="InstallRegApproved" />\r
+        <ComponentRef Id="InstallRegAppPath" />\r
+\r
+      </Feature>\r
+      <Feature Id="LanguageFiles" Title="Localization files" Description="Localization files for 71 languages."\r
+          Level="1" AllowAdvertise="no">\r
+        <ComponentRef Id="Lang" />\r
+      </Feature>\r
+    </Feature>\r
+\r
+    <UIRef Id="WixUI" />\r
+\r
+    <!-- Install Sequences -->\r
+    <InstallExecuteSequence>\r
+      <RemoveExistingProducts After="InstallValidate" />\r
+    </InstallExecuteSequence>\r
+\r
+  </Product>\r
+</Wix>\r
diff --git a/DOC/License.txt b/DOC/License.txt
new file mode 100755 (executable)
index 0000000..0b7b3d2
--- /dev/null
@@ -0,0 +1,52 @@
+  7-Zip source code\r
+  ~~~~~~~~~~~~~~~~~\r
+  License for use and distribution\r
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+\r
+  7-Zip Copyright (C) 1999-2010 Igor Pavlov.\r
+\r
+  Licenses for files are:\r
+\r
+    1) CPP/7zip/Compress/Rar* files:  GNU LGPL + unRAR restriction\r
+    2) All other files:  GNU LGPL\r
+\r
+  The GNU LGPL + unRAR restriction means that you must follow both \r
+  GNU LGPL rules and unRAR restriction rules.\r
+\r
+\r
+  GNU LGPL information\r
+  --------------------\r
+\r
+    This library is free software; you can redistribute it and/or\r
+    modify it under the terms of the GNU Lesser General Public\r
+    License as published by the Free Software Foundation; either\r
+    version 2.1 of the License, or (at your option) any later version.\r
+\r
+    This library is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+    Lesser General Public License for more details.\r
+\r
+    You should have received a copy of the GNU Lesser General Public\r
+    License along with this library; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+\r
+\r
+  unRAR restriction\r
+  -----------------\r
+\r
+    The decompression engine for RAR archives was developed using source \r
+    code of unRAR program.\r
+    All copyrights to original unRAR code are owned by Alexander Roshal.\r
+\r
+    The license for original unRAR code has the following restriction:\r
+\r
+    The unRAR sources cannot be used to re-create the RAR compression algorithm, \r
+    which is proprietary. Distribution of modified unRAR sources in separate form \r
+    or as a part of other software is permitted, provided that it is clearly\r
+    stated in the documentation and source comments that the code may\r
+    not be used to develop a RAR (WinRAR) compatible archiver.\r
+\r
+\r
+  --\r
+  Igor Pavlov\r
diff --git a/DOC/Methods.txt b/DOC/Methods.txt
new file mode 100755 (executable)
index 0000000..4c3ec68
--- /dev/null
@@ -0,0 +1,152 @@
+7-Zip method IDs (9.18)\r
+-----------------------\r
+\r
+Each compression or crypto method in 7z has unique binary value (ID).\r
+The length of ID in bytes is arbitrary but it can not exceed 63 bits (8 bytes).\r
+\r
+If you want to add some new ID, you have two ways:\r
+1) Write request for allocating IDs to 7-zip developers.\r
+2) Generate 8-bytes ID:\r
+\r
+    3F ZZ ZZ ZZ ZZ ZZ MM MM \r
+\r
+    3F              - Prefix for random IDs (1 byte)\r
+    ZZ ZZ ZZ ZZ ZZ  - Developer ID (5 bytes). Use real random bytes. \r
+                      \r
+    MM MM           - Method ID (2 bytes)\r
+\r
+    You can notify 7-Zip developers about your Developer ID / Method ID.\r
+\r
+    Note: Use new ID only if old codec can not decode data encoded with new version.\r
+\r
+\r
+List of defined IDs\r
+-------------------\r
+      \r
+00 - Copy\r
+\r
+03 - Delta\r
+04 - x86 (BCJ)\r
+05 - PPC (Big Endian)\r
+06 - IA64\r
+07 - ARM (little endian)\r
+08 - ARM Thumb (little endian)\r
+09 - SPARC\r
+21 - LZMA2\r
+          \r
+02.. - Common\r
+   03 Swap\r
+      - 2 Swap2\r
+      - 4 Swap4\r
+\r
+03.. - 7z\r
+   01 - LZMA\r
+      01 - Version\r
+  \r
+   03 - Branch\r
+      01 - x86\r
+         03  - BCJ\r
+         1B  - BCJ2\r
+      02 - PPC\r
+         05 - PPC (Big Endian)\r
+      03 - Alpha\r
+         01 - Alpha\r
+      04 - IA64\r
+         01 - IA64\r
+      05 - ARM\r
+         01 - ARM\r
+      06 - M68\r
+         05 - M68 (Big Endian)\r
+      07 - ARM Thumb\r
+         01 - ARMT\r
+      08 - SPARC\r
+         05 - SPARC\r
+\r
+   04 - PPMD\r
+      01 - Version\r
+\r
+   7F -\r
+      01 - experimental methods.\r
+\r
+\r
+04.. - Misc\r
+   00 - Reserved\r
+   01 - Zip\r
+      00 - Copy (not used). Use {00} instead\r
+      01 - Shrink\r
+      06 - Implode\r
+      08 - Deflate\r
+      09 - Deflate64\r
+      10 - Imploding\r
+      12 - BZip2 (not used). Use {04 02 02} instead\r
+      14 - LZMA\r
+      60 - Jpeg\r
+      61 - WavPack\r
+      62 - PPMd\r
+      63 - wzAES\r
+   02 - BZip\r
+      02 - BZip2\r
+   03 - Rar\r
+      01 - Rar15\r
+      02 - Rar20\r
+      03 - Rar29\r
+   04 - Arj\r
+      01 - Arj (1,2,3)\r
+      02 - Arj 4\r
+   05 - Z\r
+   06 - Lzh\r
+   07 - Reserved for 7z\r
+   08 - Cab\r
+   09 - NSIS\r
+      01 - DeflateNSIS\r
+      02 - BZip2NSIS\r
+\r
+\r
+06.. - Crypto \r
+   00 - \r
+   01 - AES\r
+      0x - AES-128\r
+      4x - AES-192\r
+      8x - AES-256\r
+      Cx - AES\r
+\r
+      x0 - ECB\r
+      x1 - CBC\r
+      x2 - CFB\r
+      x3 - OFB\r
+\r
+   07 - Reserved\r
+   0F - Reserved\r
+\r
+   F0 - Misc Ciphers (Real Ciphers without hashing algo)\r
+\r
+   F1 - Misc Ciphers (Combine)\r
+      01 - Zip\r
+         01 - Main Zip crypto algo\r
+      03 - RAR\r
+         02 - \r
+         03 - Rar29 AES-128 + (modified SHA-1)\r
+      07 - 7z\r
+         01 - AES-256 + SHA-256\r
+\r
+07.. - Hash (subject to change)\r
+   00 - \r
+   01 - CRC\r
+   02 - SHA-1\r
+   03 - SHA-256\r
+   04 - SHA-384\r
+   05 - SHA-512\r
+\r
+   F0 - Misc Hash\r
+\r
+   F1 - Misc\r
+      03 - RAR\r
+         03 - Rar29 Password Hashing (modified SHA1)\r
+      07 - 7z \r
+         01 - SHA-256 Password Hashing\r
+    \r
+   \r
+\r
+\r
+---\r
+End of document\r
diff --git a/DOC/copying.txt b/DOC/copying.txt
new file mode 100755 (executable)
index 0000000..f3926a6
--- /dev/null
@@ -0,0 +1,504 @@
+      GNU LESSER GENERAL PUBLIC LICENSE\r
+           Version 2.1, February 1999\r
+\r
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.\r
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ Everyone is permitted to copy and distribute verbatim copies\r
+ of this license document, but changing it is not allowed.\r
+\r
+[This is the first released version of the Lesser GPL.  It also counts\r
+ as the successor of the GNU Library Public License, version 2, hence\r
+ the version number 2.1.]\r
+\r
+          Preamble\r
+\r
+  The licenses for most software are designed to take away your\r
+freedom to share and change it.  By contrast, the GNU General Public\r
+Licenses are intended to guarantee your freedom to share and change\r
+free software--to make sure the software is free for all its users.\r
+\r
+  This license, the Lesser General Public License, applies to some\r
+specially designated software packages--typically libraries--of the\r
+Free Software Foundation and other authors who decide to use it.  You\r
+can use it too, but we suggest you first think carefully about whether\r
+this license or the ordinary General Public License is the better\r
+strategy to use in any particular case, based on the explanations below.\r
+\r
+  When we speak of free software, we are referring to freedom of use,\r
+not price.  Our General Public Licenses are designed to make sure that\r
+you have the freedom to distribute copies of free software (and charge\r
+for this service if you wish); that you receive source code or can get\r
+it if you want it; that you can change the software and use pieces of\r
+it in new free programs; and that you are informed that you can do\r
+these things.\r
+\r
+  To protect your rights, we need to make restrictions that forbid\r
+distributors to deny you these rights or to ask you to surrender these\r
+rights.  These restrictions translate to certain responsibilities for\r
+you if you distribute copies of the library or if you modify it.\r
+\r
+  For example, if you distribute copies of the library, whether gratis\r
+or for a fee, you must give the recipients all the rights that we gave\r
+you.  You must make sure that they, too, receive or can get the source\r
+code.  If you link other code with the library, you must provide\r
+complete object files to the recipients, so that they can relink them\r
+with the library after making changes to the library and recompiling\r
+it.  And you must show them these terms so they know their rights.\r
+\r
+  We protect your rights with a two-step method: (1) we copyright the\r
+library, and (2) we offer you this license, which gives you legal\r
+permission to copy, distribute and/or modify the library.\r
+\r
+  To protect each distributor, we want to make it very clear that\r
+there is no warranty for the free library.  Also, if the library is\r
+modified by someone else and passed on, the recipients should know\r
+that what they have is not the original version, so that the original\r
+author's reputation will not be affected by problems that might be\r
+introduced by others.\r
+\f\r
+  Finally, software patents pose a constant threat to the existence of\r
+any free program.  We wish to make sure that a company cannot\r
+effectively restrict the users of a free program by obtaining a\r
+restrictive license from a patent holder.  Therefore, we insist that\r
+any patent license obtained for a version of the library must be\r
+consistent with the full freedom of use specified in this license.\r
+\r
+  Most GNU software, including some libraries, is covered by the\r
+ordinary GNU General Public License.  This license, the GNU Lesser\r
+General Public License, applies to certain designated libraries, and\r
+is quite different from the ordinary General Public License.  We use\r
+this license for certain libraries in order to permit linking those\r
+libraries into non-free programs.\r
+\r
+  When a program is linked with a library, whether statically or using\r
+a shared library, the combination of the two is legally speaking a\r
+combined work, a derivative of the original library.  The ordinary\r
+General Public License therefore permits such linking only if the\r
+entire combination fits its criteria of freedom.  The Lesser General\r
+Public License permits more lax criteria for linking other code with\r
+the library.\r
+\r
+  We call this license the "Lesser" General Public License because it\r
+does Less to protect the user's freedom than the ordinary General\r
+Public License.  It also provides other free software developers Less\r
+of an advantage over competing non-free programs.  These disadvantages\r
+are the reason we use the ordinary General Public License for many\r
+libraries.  However, the Lesser license provides advantages in certain\r
+special circumstances.\r
+\r
+  For example, on rare occasions, there may be a special need to\r
+encourage the widest possible use of a certain library, so that it becomes\r
+a de-facto standard.  To achieve this, non-free programs must be\r
+allowed to use the library.  A more frequent case is that a free\r
+library does the same job as widely used non-free libraries.  In this\r
+case, there is little to gain by limiting the free library to free\r
+software only, so we use the Lesser General Public License.\r
+\r
+  In other cases, permission to use a particular library in non-free\r
+programs enables a greater number of people to use a large body of\r
+free software.  For example, permission to use the GNU C Library in\r
+non-free programs enables many more people to use the whole GNU\r
+operating system, as well as its variant, the GNU/Linux operating\r
+system.\r
+\r
+  Although the Lesser General Public License is Less protective of the\r
+users' freedom, it does ensure that the user of a program that is\r
+linked with the Library has the freedom and the wherewithal to run\r
+that program using a modified version of the Library.\r
+\r
+  The precise terms and conditions for copying, distribution and\r
+modification follow.  Pay close attention to the difference between a\r
+"work based on the library" and a "work that uses the library".  The\r
+former contains code derived from the library, whereas the latter must\r
+be combined with the library in order to run.\r
+\f\r
+      GNU LESSER GENERAL PUBLIC LICENSE\r
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\r
+\r
+  0. This License Agreement applies to any software library or other\r
+program which contains a notice placed by the copyright holder or\r
+other authorized party saying it may be distributed under the terms of\r
+this Lesser General Public License (also called "this License").\r
+Each licensee is addressed as "you".\r
+\r
+  A "library" means a collection of software functions and/or data\r
+prepared so as to be conveniently linked with application programs\r
+(which use some of those functions and data) to form executables.\r
+\r
+  The "Library", below, refers to any such software library or work\r
+which has been distributed under these terms.  A "work based on the\r
+Library" means either the Library or any derivative work under\r
+copyright law: that is to say, a work containing the Library or a\r
+portion of it, either verbatim or with modifications and/or translated\r
+straightforwardly into another language.  (Hereinafter, translation is\r
+included without limitation in the term "modification".)\r
+\r
+  "Source code" for a work means the preferred form of the work for\r
+making modifications to it.  For a library, complete source code means\r
+all the source code for all modules it contains, plus any associated\r
+interface definition files, plus the scripts used to control compilation\r
+and installation of the library.\r
+\r
+  Activities other than copying, distribution and modification are not\r
+covered by this License; they are outside its scope.  The act of\r
+running a program using the Library is not restricted, and output from\r
+such a program is covered only if its contents constitute a work based\r
+on the Library (independent of the use of the Library in a tool for\r
+writing it).  Whether that is true depends on what the Library does\r
+and what the program that uses the Library does.\r
+  \r
+  1. You may copy and distribute verbatim copies of the Library's\r
+complete source code as you receive it, in any medium, provided that\r
+you conspicuously and appropriately publish on each copy an\r
+appropriate copyright notice and disclaimer of warranty; keep intact\r
+all the notices that refer to this License and to the absence of any\r
+warranty; and distribute a copy of this License along with the\r
+Library.\r
+\r
+  You may charge a fee for the physical act of transferring a copy,\r
+and you may at your option offer warranty protection in exchange for a\r
+fee.\r
+\f\r
+  2. You may modify your copy or copies of the Library or any portion\r
+of it, thus forming a work based on the Library, and copy and\r
+distribute such modifications or work under the terms of Section 1\r
+above, provided that you also meet all of these conditions:\r
+\r
+    a) The modified work must itself be a software library.\r
+\r
+    b) You must cause the files modified to carry prominent notices\r
+    stating that you changed the files and the date of any change.\r
+\r
+    c) You must cause the whole of the work to be licensed at no\r
+    charge to all third parties under the terms of this License.\r
+\r
+    d) If a facility in the modified Library refers to a function or a\r
+    table of data to be supplied by an application program that uses\r
+    the facility, other than as an argument passed when the facility\r
+    is invoked, then you must make a good faith effort to ensure that,\r
+    in the event an application does not supply such function or\r
+    table, the facility still operates, and performs whatever part of\r
+    its purpose remains meaningful.\r
+\r
+    (For example, a function in a library to compute square roots has\r
+    a purpose that is entirely well-defined independent of the\r
+    application.  Therefore, Subsection 2d requires that any\r
+    application-supplied function or table used by this function must\r
+    be optional: if the application does not supply it, the square\r
+    root function must still compute square roots.)\r
+\r
+These requirements apply to the modified work as a whole.  If\r
+identifiable sections of that work are not derived from the Library,\r
+and can be reasonably considered independent and separate works in\r
+themselves, then this License, and its terms, do not apply to those\r
+sections when you distribute them as separate works.  But when you\r
+distribute the same sections as part of a whole which is a work based\r
+on the Library, the distribution of the whole must be on the terms of\r
+this License, whose permissions for other licensees extend to the\r
+entire whole, and thus to each and every part regardless of who wrote\r
+it.\r
+\r
+Thus, it is not the intent of this section to claim rights or contest\r
+your rights to work written entirely by you; rather, the intent is to\r
+exercise the right to control the distribution of derivative or\r
+collective works based on the Library.\r
+\r
+In addition, mere aggregation of another work not based on the Library\r
+with the Library (or with a work based on the Library) on a volume of\r
+a storage or distribution medium does not bring the other work under\r
+the scope of this License.\r
+\r
+  3. You may opt to apply the terms of the ordinary GNU General Public\r
+License instead of this License to a given copy of the Library.  To do\r
+this, you must alter all the notices that refer to this License, so\r
+that they refer to the ordinary GNU General Public License, version 2,\r
+instead of to this License.  (If a newer version than version 2 of the\r
+ordinary GNU General Public License has appeared, then you can specify\r
+that version instead if you wish.)  Do not make any other change in\r
+these notices.\r
+\f\r
+  Once this change is made in a given copy, it is irreversible for\r
+that copy, so the ordinary GNU General Public License applies to all\r
+subsequent copies and derivative works made from that copy.\r
+\r
+  This option is useful when you wish to copy part of the code of\r
+the Library into a program that is not a library.\r
+\r
+  4. You may copy and distribute the Library (or a portion or\r
+derivative of it, under Section 2) in object code or executable form\r
+under the terms of Sections 1 and 2 above provided that you accompany\r
+it with the complete corresponding machine-readable source code, which\r
+must be distributed under the terms of Sections 1 and 2 above on a\r
+medium customarily used for software interchange.\r
+\r
+  If distribution of object code is made by offering access to copy\r
+from a designated place, then offering equivalent access to copy the\r
+source code from the same place satisfies the requirement to\r
+distribute the source code, even though third parties are not\r
+compelled to copy the source along with the object code.\r
+\r
+  5. A program that contains no derivative of any portion of the\r
+Library, but is designed to work with the Library by being compiled or\r
+linked with it, is called a "work that uses the Library".  Such a\r
+work, in isolation, is not a derivative work of the Library, and\r
+therefore falls outside the scope of this License.\r
+\r
+  However, linking a "work that uses the Library" with the Library\r
+creates an executable that is a derivative of the Library (because it\r
+contains portions of the Library), rather than a "work that uses the\r
+library".  The executable is therefore covered by this License.\r
+Section 6 states terms for distribution of such executables.\r
+\r
+  When a "work that uses the Library" uses material from a header file\r
+that is part of the Library, the object code for the work may be a\r
+derivative work of the Library even though the source code is not.\r
+Whether this is true is especially significant if the work can be\r
+linked without the Library, or if the work is itself a library.  The\r
+threshold for this to be true is not precisely defined by law.\r
+\r
+  If such an object file uses only numerical parameters, data\r
+structure layouts and accessors, and small macros and small inline\r
+functions (ten lines or less in length), then the use of the object\r
+file is unrestricted, regardless of whether it is legally a derivative\r
+work.  (Executables containing this object code plus portions of the\r
+Library will still fall under Section 6.)\r
+\r
+  Otherwise, if the work is a derivative of the Library, you may\r
+distribute the object code for the work under the terms of Section 6.\r
+Any executables containing that work also fall under Section 6,\r
+whether or not they are linked directly with the Library itself.\r
+\f\r
+  6. As an exception to the Sections above, you may also combine or\r
+link a "work that uses the Library" with the Library to produce a\r
+work containing portions of the Library, and distribute that work\r
+under terms of your choice, provided that the terms permit\r
+modification of the work for the customer's own use and reverse\r
+engineering for debugging such modifications.\r
+\r
+  You must give prominent notice with each copy of the work that the\r
+Library is used in it and that the Library and its use are covered by\r
+this License.  You must supply a copy of this License.  If the work\r
+during execution displays copyright notices, you must include the\r
+copyright notice for the Library among them, as well as a reference\r
+directing the user to the copy of this License.  Also, you must do one\r
+of these things:\r
+\r
+    a) Accompany the work with the complete corresponding\r
+    machine-readable source code for the Library including whatever\r
+    changes were used in the work (which must be distributed under\r
+    Sections 1 and 2 above); and, if the work is an executable linked\r
+    with the Library, with the complete machine-readable "work that\r
+    uses the Library", as object code and/or source code, so that the\r
+    user can modify the Library and then relink to produce a modified\r
+    executable containing the modified Library.  (It is understood\r
+    that the user who changes the contents of definitions files in the\r
+    Library will not necessarily be able to recompile the application\r
+    to use the modified definitions.)\r
+\r
+    b) Use a suitable shared library mechanism for linking with the\r
+    Library.  A suitable mechanism is one that (1) uses at run time a\r
+    copy of the library already present on the user's computer system,\r
+    rather than copying library functions into the executable, and (2)\r
+    will operate properly with a modified version of the library, if\r
+    the user installs one, as long as the modified version is\r
+    interface-compatible with the version that the work was made with.\r
+\r
+    c) Accompany the work with a written offer, valid for at\r
+    least three years, to give the same user the materials\r
+    specified in Subsection 6a, above, for a charge no more\r
+    than the cost of performing this distribution.\r
+\r
+    d) If distribution of the work is made by offering access to copy\r
+    from a designated place, offer equivalent access to copy the above\r
+    specified materials from the same place.\r
+\r
+    e) Verify that the user has already received a copy of these\r
+    materials or that you have already sent this user a copy.\r
+\r
+  For an executable, the required form of the "work that uses the\r
+Library" must include any data and utility programs needed for\r
+reproducing the executable from it.  However, as a special exception,\r
+the materials to be distributed need not include anything that is\r
+normally distributed (in either source or binary form) with the major\r
+components (compiler, kernel, and so on) of the operating system on\r
+which the executable runs, unless that component itself accompanies\r
+the executable.\r
+\r
+  It may happen that this requirement contradicts the license\r
+restrictions of other proprietary libraries that do not normally\r
+accompany the operating system.  Such a contradiction means you cannot\r
+use both them and the Library together in an executable that you\r
+distribute.\r
+\f\r
+  7. You may place library facilities that are a work based on the\r
+Library side-by-side in a single library together with other library\r
+facilities not covered by this License, and distribute such a combined\r
+library, provided that the separate distribution of the work based on\r
+the Library and of the other library facilities is otherwise\r
+permitted, and provided that you do these two things:\r
+\r
+    a) Accompany the combined library with a copy of the same work\r
+    based on the Library, uncombined with any other library\r
+    facilities.  This must be distributed under the terms of the\r
+    Sections above.\r
+\r
+    b) Give prominent notice with the combined library of the fact\r
+    that part of it is a work based on the Library, and explaining\r
+    where to find the accompanying uncombined form of the same work.\r
+\r
+  8. You may not copy, modify, sublicense, link with, or distribute\r
+the Library except as expressly provided under this License.  Any\r
+attempt otherwise to copy, modify, sublicense, link with, or\r
+distribute the Library is void, and will automatically terminate your\r
+rights under this License.  However, parties who have received copies,\r
+or rights, from you under this License will not have their licenses\r
+terminated so long as such parties remain in full compliance.\r
+\r
+  9. You are not required to accept this License, since you have not\r
+signed it.  However, nothing else grants you permission to modify or\r
+distribute the Library or its derivative works.  These actions are\r
+prohibited by law if you do not accept this License.  Therefore, by\r
+modifying or distributing the Library (or any work based on the\r
+Library), you indicate your acceptance of this License to do so, and\r
+all its terms and conditions for copying, distributing or modifying\r
+the Library or works based on it.\r
+\r
+  10. Each time you redistribute the Library (or any work based on the\r
+Library), the recipient automatically receives a license from the\r
+original licensor to copy, distribute, link with or modify the Library\r
+subject to these terms and conditions.  You may not impose any further\r
+restrictions on the recipients' exercise of the rights granted herein.\r
+You are not responsible for enforcing compliance by third parties with\r
+this License.\r
+\f\r
+  11. If, as a consequence of a court judgment or allegation of patent\r
+infringement or for any other reason (not limited to patent issues),\r
+conditions are imposed on you (whether by court order, agreement or\r
+otherwise) that contradict the conditions of this License, they do not\r
+excuse you from the conditions of this License.  If you cannot\r
+distribute so as to satisfy simultaneously your obligations under this\r
+License and any other pertinent obligations, then as a consequence you\r
+may not distribute the Library at all.  For example, if a patent\r
+license would not permit royalty-free redistribution of the Library by\r
+all those who receive copies directly or indirectly through you, then\r
+the only way you could satisfy both it and this License would be to\r
+refrain entirely from distribution of the Library.\r
+\r
+If any portion of this section is held invalid or unenforceable under any\r
+particular circumstance, the balance of the section is intended to apply,\r
+and the section as a whole is intended to apply in other circumstances.\r
+\r
+It is not the purpose of this section to induce you to infringe any\r
+patents or other property right claims or to contest validity of any\r
+such claims; this section has the sole purpose of protecting the\r
+integrity of the free software distribution system which is\r
+implemented by public license practices.  Many people have made\r
+generous contributions to the wide range of software distributed\r
+through that system in reliance on consistent application of that\r
+system; it is up to the author/donor to decide if he or she is willing\r
+to distribute software through any other system and a licensee cannot\r
+impose that choice.\r
+\r
+This section is intended to make thoroughly clear what is believed to\r
+be a consequence of the rest of this License.\r
+\r
+  12. If the distribution and/or use of the Library is restricted in\r
+certain countries either by patents or by copyrighted interfaces, the\r
+original copyright holder who places the Library under this License may add\r
+an explicit geographical distribution limitation excluding those countries,\r
+so that distribution is permitted only in or among countries not thus\r
+excluded.  In such case, this License incorporates the limitation as if\r
+written in the body of this License.\r
+\r
+  13. The Free Software Foundation may publish revised and/or new\r
+versions of the Lesser General Public License from time to time.\r
+Such new versions will be similar in spirit to the present version,\r
+but may differ in detail to address new problems or concerns.\r
+\r
+Each version is given a distinguishing version number.  If the Library\r
+specifies a version number of this License which applies to it and\r
+"any later version", you have the option of following the terms and\r
+conditions either of that version or of any later version published by\r
+the Free Software Foundation.  If the Library does not specify a\r
+license version number, you may choose any version ever published by\r
+the Free Software Foundation.\r
+\f\r
+  14. If you wish to incorporate parts of the Library into other free\r
+programs whose distribution conditions are incompatible with these,\r
+write to the author to ask for permission.  For software which is\r
+copyrighted by the Free Software Foundation, write to the Free\r
+Software Foundation; we sometimes make exceptions for this.  Our\r
+decision will be guided by the two goals of preserving the free status\r
+of all derivatives of our free software and of promoting the sharing\r
+and reuse of software generally.\r
+\r
+          NO WARRANTY\r
+\r
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO\r
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.\r
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR\r
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY\r
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE\r
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE\r
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME\r
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\r
+\r
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN\r
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY\r
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU\r
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR\r
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE\r
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING\r
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A\r
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF\r
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+DAMAGES.\r
+\r
+         END OF TERMS AND CONDITIONS\r
+\f\r
+           How to Apply These Terms to Your New Libraries\r
+\r
+  If you develop a new library, and you want it to be of the greatest\r
+possible use to the public, we recommend making it free software that\r
+everyone can redistribute and change.  You can do so by permitting\r
+redistribution under these terms (or, alternatively, under the terms of the\r
+ordinary General Public License).\r
+\r
+  To apply these terms, attach the following notices to the library.  It is\r
+safest to attach them to the start of each source file to most effectively\r
+convey the exclusion of warranty; and each file should have at least the\r
+"copyright" line and a pointer to where the full notice is found.\r
+\r
+    <one line to give the library's name and a brief idea of what it does.>\r
+    Copyright (C) <year>  <name of author>\r
+\r
+    This library is free software; you can redistribute it and/or\r
+    modify it under the terms of the GNU Lesser General Public\r
+    License as published by the Free Software Foundation; either\r
+    version 2.1 of the License, or (at your option) any later version.\r
+\r
+    This library is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+    Lesser General Public License for more details.\r
+\r
+    You should have received a copy of the GNU Lesser General Public\r
+    License along with this library; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+\r
+Also add information on how to contact you by electronic and paper mail.\r
+\r
+You should also get your employer (if you work as a programmer) or your\r
+school, if any, to sign a "copyright disclaimer" for the library, if\r
+necessary.  Here is a sample; alter the names:\r
+\r
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the\r
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.\r
+\r
+  <signature of Ty Coon>, 1 April 1990\r
+  Ty Coon, President of Vice\r
+\r
+That's all there is to it!\r
+\r
+\r
diff --git a/DOC/history.txt b/DOC/history.txt
new file mode 100755 (executable)
index 0000000..a3ece98
--- /dev/null
@@ -0,0 +1,456 @@
+Sources history of the 7-Zip\r
+----------------------------\r
+\r
+9.18           2010-11-02\r
+-------------------------      \r
+- New small SFX module for installers (C/Util/SfxSetup).\r
+\r
+\r
+9.17           2010-10-04\r
+-------------------------\r
+- IStream.h::IOutStream::\r
+    STDMETHOD(SetSize)(Int64 newSize) PURE;\r
+  was changed to\r
+    STDMETHOD(SetSize)(UInt64 newSize) PURE;\r
+\r
+\r
+9.09           2009-12-12\r
+-------------------------\r
+- The bug was fixed:\r
+   Utf16_To_Utf8 funstions in UTFConvert.cpp and 7zMain.c\r
+   incorrectly converted surrogate characters (the code >= 0x10000) to UTF-8.\r
+\r
+\r
+9.05           2009-07-05\r
+-------------------------\r
+- FileMapping.h::CFileMapping now returns WRes\r
+\r
+\r
+9.04           2009-05-30\r
+-------------------------\r
+- ICoder.h: NCoderPropID::EEnum values were changed\r
+\r
+\r
+9.02           2009-04-23\r
+-------------------------\r
+- Bug was fixed: if swap2 filter was requests at compression,\r
+  7-zip used swap4 filter instead (but id was swap2), so archives were incorrect.\r
+  \r
+4.61           2008-11-23\r
+-------------------------\r
+- Bug in ver. 4.58+ was fixed:\r
+   7-Zip didn't use any -m* switch after -mtc, -mcl or -mcu for .zip archives. \r
+- Bug in .CAB code was fixed. 7-Zip didn't show some empty files,\r
+  if .CAB archive contains more than one empty file.\r
+   \r
+\r
+4.59           2008-07-27\r
+-------------------------\r
+- Bug was fixed:\r
+   LZMA Encoder in fast compression mode could access memory outside of \r
+   allocated range in some rare cases.\r
+   \r
+\r
+4.59 alpha     2008-05-30\r
+-------------------------\r
+- BUGS was fixed: \r
+    7zOut.cpp: 7-Zip incorrectly wrote size of property records in some cases.\r
+    7zIn.cpp:  7-Zip incorrectly work with archive, containg archive properties.\r
+\r
+4.58 alpha 9   2008-04-29\r
+-------------------------\r
+- BUG was fixed: 7-Zip showed incorrect timestamps in ISO files.\r
+\r
+\r
+4.58 alpha 8   2008-04-15\r
+-------------------------\r
+- BUG in 4.58 alpha 5/6/7 was fixed:\r
+    LZMA encoder worked incorrectly, if lp != 0.\r
+- Unicode (UTF-8) support for filenames in .ZIP archives. Now there are 3 modes:\r
+    1) Default mode: 7-Zip uses UTF-8, if the local code page doesn't contain required symbols.\r
+    2) -mcu switch:  7-Zip uses UTF-8, if there are non-ASCII symbols.\r
+    3) -mcl switch:  7-Zip uses local code page.\r
+- Now it's possible to use -mSW- and -mSW+ switches instead of -mSW=off and -mSW=on  \r
+\r
+\r
+4.58 alpha 7   2008-04-08\r
+-------------------------\r
+- BUG was fixed: BZip2Encoder and BZip2Decoder used CEvent objects without \r
+  creating, when BZip2 code was called with one thread (with -mmt1 switch or with \r
+  default switches on single thread CPU).\r
+- .lzma support.\r
+- RPM and NSIS support was improved.\r
+- LZMA now stores only (2 << n) or (3 << n) dictionary size value to LZMA properties.\r
+\r
+\r
+4.58 alpha 6   2008-03-27\r
+-------------------------\r
+- NTFS time extra in ZIP.\r
+- New item property - kpidTimeType - VT_UI4 (0 - NTFS, 1 - Unix, 2 - DOS).\r
+- Static CRC table is not required now for Lzma Encoder (in Lz MatchFinder).\r
+\r
+\r
+4.58 alpha 5   2008-03-19\r
+-------------------------\r
+- Creation time (-mtc switch) for .7z archives\r
+- LZMA encoder was converted to ANSI-C\r
+\r
+\r
+4.58 alpha 3   2008-02-25\r
+-------------------------\r
+- Speed optimizations for LZMA decoding. Now it uses C code instead of C++.\r
+- 7-Zip now has 128 MB dictionary limit for 32-bit version:\r
+  It's for speed optimization: kNumLogBits = 9 + sizeof(size_t) / 2;\r
+- TAR: 'D' link flag support.\r
+- 7-Zip now can unpack multivolume RAR archives created with \r
+  "old style volume names" scheme (-vn switch) and names *.001, *.002, ...\r
+- Fixed bugs:\r
+  - 7-Zip FM could not copy / move files to root network folders like \\COMPNAME\FOLDERNAME\\r
+    In case of move it removed original files.\r
+  - SFX-WIN: if there are errors, it still could return 0.\r
+  - ZIP (.XPS file) isZip64 && thisDiskNumber16 == 0xFFFF.\r
+  - ZIP name updating:\r
+      If zip file contains extra field and you try to change properties of files,\r
+      7-zip tries to delete all extra fileds (except for WzAES).\r
+      And that code could hang.\r
+  -  7-Zip GUI didn't suggest BZip2 dictionary size used in previous run.\r
+  -  If creation time stamp was included in .RAR archive, 7-zip used creation time stamp \r
+     as modification time stamp.\r
+\r
+4.58 alpha 2   2007-12-31\r
+-------------------------\r
+- Small changes in Deflate and LZMA compression.\r
+- Some speed optimizations.\r
+\r
+\r
+4.57\r
+----\r
+- Bug was fixed:\r
+  Anti item is created for wrong file:\r
+  http://sourceforge.net/forum/forum.php?thread_id=1880366&forum_id=45798\r
+\r
+\r
+4.52 beta      2007-07-32\r
+-------------------------\r
+- 7-Zip could not decompress some cab files\r
+- "." dir creating at FAT was fixed / long names\r
+\r
+\r
+4.50 beta      2007-07-24\r
+-------------------------\r
+- 7-Zip now replaces unsupported filenames (like "nul", "com1") during extracting.\r
+- New switch for command line version:\r
+    -ssc[-] enables/disables case-sensitive mode.\r
+- 7z.exe l shows archive comment for zip archives\r
+- Some bugs were fixed: long paths names shorter than 4.\r
+- Speed optimizations for AES encryption.\r
+\r
+\r
+\r
+4.56 beta      2007-09-13\r
+-------------------------\r
+- some fixes in LZ encoder (LZMA and Deflate) code.\r
+ size_t was replaces to ptrdiff_t.\r
+ size_t version worked incorrectly with some compilers.\r
+\r
\r
+4.46 beta      2007-05-25\r
+-------------------------\r
+- CPP Synchronization objects now return HRes (error code) instead of bool.\r
+\r
+\r
+4.45 beta      2007-04-16\r
+-------------------------\r
+- 7-Zip now uses C version of CRC, so you must call CrcGenerateTable at \r
+  stratup code, or you must add CPP/Common/CRC.cpp to your project.\r
+- Method ID in .7z now is 63-bit integer (UInt64).\r
+- Open error messages\r
+- unRar 1.5 fixed\r
+- unShrink fixed\r
+- BUG of 4.43 beta and 4.44 beta was fixed.\r
+  7-Zip compressing to .zip in multi-threading mode didn't work in some cases.\r
+\r
+\r
+4.44 beta      2007-01-20\r
+-------------------------\r
+\r
+- Bug was fixed: LZMAEncoder.cpp::CEncoder::GetOptimumFast\r
+  it was:\r
+    data++\r
+  fixed version:\r
+    data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1;\r
+  It could lead to very small cpmpression ratio decreasing when block needs move.\r
+\r
+\r
+4.30 beta      2005-11-18\r
+-------------------------\r
+- Security.h::AddLockMemoryPrivilege       - installs "Large pages" feature\r
+- MemoryLock.h::EnableLockMemoryPrivilege  - enables "Large pages" feature\r
+- Alloc.h::SetLargePageSize                - sets optimal LargePageSize size\r
+\r
+\r
+4.27           2005-09-21\r
+-------------------------\r
+- Some GUIDs/interfaces were changed.\r
+ IStream.h:\r
+   ISequentialInStream::Read now works as old ReadPart\r
+   ISequentialOutStream::Write now works as old WritePart\r
+\r
+\r
+4.26 beta      2005-08-05\r
+-------------------------\r
+-  MyAlloc(0)/BigAlloc(0) now return 0\r
+\r
+\r
+4.25 beta      2005-07-31\r
+-------------------------\r
+-  More 64-bit compatibilty\r
+\r
+\r
+4.24 beta      2005-07-06\r
+-------------------------\r
+-  Common\NewHandler.h: using throw() for code size optimization.\r
+\r
+\r
+4.23           2005-06-29\r
+-------------------------\r
+-  Bug was fixed: memory leak in Cab decoder.\r
+\r
+\r
+4.19 beta      2005-05-21\r
+-------------------------\r
+-  BZip2 code was rewritten. Now 7-Zip doesn't use original BZip2 code.\r
+  Old (original) version was moved to folder 7zip/Compress/BZip2Original/\r
+\r
+\r
+4.14 beta      2005-01-11\r
+-------------------------\r
+-  STL using was reduced\r
+-  7za now supports Split(001) archves\r
+\r
+\r
+4.10 beta      2004-10-21\r
+-------------------------\r
+-  Codecs now use new interface: ICompressSetDecoderProperties2\r
+\r
+\r
+4.07 beta      2004-10-03\r
+-------------------------\r
+-  some interfaces were changed slightly to support \r
+  -stdin -stdout mode.\r
+-  FilterCoder for simple filters\r
+-  Wildcard censor class was changed.\r
+-  Bug was fixed: when encrypted stream was multiple 16,\r
+  it used additional 16 empty bytes.\r
+\r
+\r
+3.11           2003-10-06\r
+-------------------------\r
+  File functions support unicode strings even\r
+  on Windows 95/98/ME.\r
+\r
+\r
+3.08.02        2003-09-20\r
+-------------------------\r
+  More compatible with GCC.\r
+\r
+\r
+3.08.02 beta   2003-08-20\r
+-------------------------\r
+  Extracting bug in 7zExtract.cpp was fixed.\r
\r
+\r
+3.08 beta      2003-08-19\r
+-------------------------\r
+  Big source code reconstruction.\r
\r
+\r
+2.30 Beta 32   2003-05-15\r
+-------------------------\r
+  Small changes in Deflate decoder.\r
\r
+\r
+2.30 Beta 31   2003-04-29\r
+-------------------------\r
+  Common/NewHandler.cpp\r
+    HeapAlloc in (included to beta 30) was changed to malloc.\r
+    HeapAlloc worked slower in Win95/98/Me.\r
\r
+\r
+2.30 Beta 30   2003-04-21\r
+-------------------------\r
+  new file: Common/String.cpp\r
+  Common/NewHandler.*  were changed\r
+\r
+\r
+2.30 Beta 29   2003-04-07\r
+-------------------------\r
+  Small changes in LZMA code.\r
+\r
+\r
+2.30 Beta 28   2003-02-16\r
+-------------------------\r
+  Processing anti-files was corrected.\r
+\r
+\r
+2.30 Beta 27   2003-01-24\r
+-------------------------\r
+  Project/Archiver/Format/Common/ArchiveInterface.h:\r
+    new IArchiveOpenVolumeCallback interface.\r
+\r
+\r
+2.30 Beta 26   2003-01-12\r
+-------------------------\r
+  SDK/Interface/PropID.h:\r
+    kpidComment now is kpidCommented\r
+\r
+\r
+2.30 Beta 25   2003-01-02\r
+-------------------------\r
+  Main archive interfaces were changed.\r
+\r
+\r
+2.30 Beta 24   2002-11-01\r
+-------------------------\r
+  SDK/Windows/Synchronization.h \r
+  SDK/Windows/Synchronization.cpp\r
+    - some changes.\r
+\r
+\r
+2.30 Beta 23   2002-09-07\r
+-------------------------\r
+  Project/FileManager folder was added.\r
+  Notation of some source files was changed.\r
+\r
+\r
+2.30 Beta 22   2002-08-28\r
+-------------------------\r
+  Project/FileManager folder was added.\r
+  Notation of some source files was changed.\r
+\r
+\r
+\r
+2.30 Beta 21   2002-07-08\r
+-------------------------\r
+  Project/Compress/LZ/MatchFinder/BinTree/BinTree.h\r
+  Project/Compress/LZ/MatchFinder/BinTree/BinTreeMain.h\r
+  Project/Compress/LZ/MatchFinder/BinTree/HC.h\r
+  Project/Compress/LZ/MatchFinder/BinTree/HCMain.h\r
+    - RAM requirements for LZMA (7z) compression were reduced.\r
+\r
+\r
+2.30 Beta 20   2002-07-01\r
+-------------------------\r
+- SDK/Stream/WindowOut.h \r
+    now it uses only required memory (dictionary size).\r
+- Project/Archiver/Resource \r
+    contains common resurces\r
+\r
+\r
+2.30 Beta 19   2002-04-11\r
+-------------------------\r
+- SDK/Archive/Rar/Handler.cpp\r
+    supporting RAR29\r
+\r
+2.30 Beta 18   2002-03-25\r
+-------------------------\r
+- SDK/Archive/Cab/MSZipDecoder.cpp\r
+  SDK/Archive/Cab/LZXDecoder.cpp:\r
+    bug with corrupted archives was fixed\r
+- Project/Compress/LZ/MatchFinder/BinTree/BinTree.h \r
+- Project/Compress/LZ/MatchFinder/BinTree/BinTreeMain.h \r
+    some speed optimization (using prefetching)\r
+\r
+\r
+2.30 Beta 17   2002-03-03\r
+-------------------------\r
+- ARJ suppport.\r
+\r
+\r
+2.30 Beta 16   2002-02-24\r
+-------------------------\r
+- Project/Compress/LZ/LZMA/Decoder.cpp:\r
+    Bug was fixed: LZMA could not extract more than 4 GB.\r
+- RPM and CPIO formats.\r
+- Project/Compress/LZ/LZMA/Encoder.*\r
+  Project/Archiver/Format/7z/OutHandler.cpp \r
+    New fast compression mode for LZMA: -m0a=0.\r
+- New match finders for LZMA: bt4b, hc3, hc4.\r
+\r
+\r
+2.30 Beta 15   2002-02-17\r
+-------------------------\r
+- Compression ratio in LZMA was slightly improved:\r
+    Project/Compress/LZ/LZMA/Encoder.*\r
+    Project/Archiver/Format/7z/OutHandler.cpp \r
+\r
+\r
+2.30 Beta 14   2002-02-10\r
+-------------------------\r
+- Supporting multithreading for LZMA:\r
+    Project/Compress/LZ/MatchFinder/MT \r
+- Common/String.h:\r
+    CStringBase::Replace function was fixed.\r
+\r
+\r
+2.30 Beta 13   2002-01-27\r
+-------------------------\r
+- Compress/LZ/MatchFinder/BinTree3.h: \r
+   method\r
+- Compress/LZ/MatchFinder/BinTreemain.h: \r
+    - one VirtualAlloc array was splitted to \r
+      the for 3 arrays.\r
+    - Hash-functions were changed.\r
+\r
+\r
+\r
+2.30 Beta 12   2002-01-16\r
+-------------------------\r
+- Compress/LZ/MatchFinder/BinTreemain.h: \r
+  Compress/LZ/MatchFinder/Patricia.h: \r
+  Compress/PPM/PPMd/SubAlloc.h: \r
+    Beta 11 bugs were fixed:\r
+      - VirtualFree was used incorrectly\r
+      - checking WIN32 instead _WINDOWS.\r
+  Compress/LZ/MatchFinder/Patricia.h: \r
+    Beta 11 bug with deleting m_Hash2Descendants was fixed.\r
+\r
+\r
+2.30 Beta 11   2002-01-15\r
+-------------------------\r
+- Compress/LZ/MatchFinder/BinTreemain.h: \r
+  Compress/LZ/MatchFinder/Patricia.h: \r
+  Compress/PPM/PPMd/SubAlloc.h: \r
+    using VirtualAlloc for memory allocating\r
+- Exlorer/ContextMenu.cpp: \r
+    Testing supporting.\r
+    CreateProcess instead WinExec\r
+- Format/Common/IArchiveHandler.h:\r
+  Exlorer/ProxyHandler.cpp:\r
+  FAR/Plugin.cpp:\r
+    New properties names: Method, HostOS.\r
+- Exlorer/OverwriteDialog.cpp:\r
+  FAR/OverwriteDialog.cpp:\r
+  Windows/PropVariantConversions.h\r
+    Using National time format was eliminated.\r
+\r
+\r
+\r
+2.30 Beta 10   2002-01-11\r
+-------------------------\r
+- Exlorer/ContextMenu.cpp: bug with context menu on \r
+  Windows NT4 in Unicode version was fixed.\r
+- Format/7z/UpdateArchiveEngine.cpp: bug was fixed - \r
+  Updating in Beta 8 and 9 didn't work.\r
+- Exlorer/CCompressDialog.cpp: history growing bug was fixed.\r
+\r
+\r
+2.30 Beta 9    2002-01-08\r
+-------------------------\r
+- SDK/Common/Vector.h: sopporting sorted object vectors .\r
+- Lang features.\r
+- Two new match finders: pat3h and pat4h.\r
+- SDK/Archive/Zip/InEngine.cpp: bug was fixed.\r
+- SDK/Windows/FileDir.cpp: function CreateComplexDirectory\r
+  was changed.\r
+\r
diff --git a/DOC/lzma.txt b/DOC/lzma.txt
new file mode 100755 (executable)
index 0000000..579f2cc
--- /dev/null
@@ -0,0 +1,598 @@
+LZMA SDK 9.20\r
+-------------\r
+\r
+LZMA SDK provides the documentation, samples, header files, libraries, \r
+and tools you need to develop applications that use LZMA compression.\r
+\r
+LZMA is default and general compression method of 7z format\r
+in 7-Zip compression program (www.7-zip.org). LZMA provides high \r
+compression ratio and very fast decompression.\r
+\r
+LZMA is an improved version of famous LZ77 compression algorithm. \r
+It was improved in way of maximum increasing of compression ratio,\r
+keeping high decompression speed and low memory requirements for \r
+decompressing.\r
+\r
+\r
+\r
+LICENSE\r
+-------\r
+\r
+LZMA SDK is written and placed in the public domain by Igor Pavlov.\r
+\r
+Some code in LZMA SDK is based on public domain code from another developers:\r
+  1) PPMd var.H (2001): Dmitry Shkarin\r
+  2) SHA-256: Wei Dai (Crypto++ library)\r
+\r
+\r
+LZMA SDK Contents\r
+-----------------\r
+\r
+LZMA SDK includes:\r
+\r
+  - ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing\r
+  - Compiled file->file LZMA compressing/decompressing program for Windows system\r
+\r
+\r
+UNIX/Linux version \r
+------------------\r
+To compile C++ version of file->file LZMA encoding, go to directory\r
+CPP/7zip/Bundles/LzmaCon\r
+and call make to recompile it:\r
+  make -f makefile.gcc clean all\r
+\r
+In some UNIX/Linux versions you must compile LZMA with static libraries.\r
+To compile with static libraries, you can use \r
+LIB = -lm -static\r
+\r
+\r
+Files\r
+---------------------\r
+lzma.txt     - LZMA SDK description (this file)\r
+7zFormat.txt - 7z Format description\r
+7zC.txt      - 7z ANSI-C Decoder description\r
+methods.txt  - Compression method IDs for .7z\r
+lzma.exe     - Compiled file->file LZMA encoder/decoder for Windows\r
+7zr.exe      - 7-Zip with 7z/lzma/xz support.\r
+history.txt  - history of the LZMA SDK\r
+\r
+\r
+Source code structure\r
+---------------------\r
+\r
+C/  - C files\r
+        7zCrc*.*   - CRC code\r
+        Alloc.*    - Memory allocation functions\r
+        Bra*.*     - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code\r
+        LzFind.*   - Match finder for LZ (LZMA) encoders \r
+        LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding\r
+        LzHash.h   - Additional file for LZ match finder\r
+        LzmaDec.*  - LZMA decoding\r
+        LzmaEnc.*  - LZMA encoding\r
+        LzmaLib.*  - LZMA Library for DLL calling\r
+        Types.h    - Basic types for another .c files\r
+        Threads.*  - The code for multithreading.\r
+\r
+    LzmaLib  - LZMA Library (.DLL for Windows)\r
+    \r
+    LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder).\r
+\r
+    Archive - files related to archiving\r
+      7z     - 7z ANSI-C Decoder\r
+\r
+CPP/ -- CPP files\r
+\r
+  Common  - common files for C++ projects\r
+  Windows - common files for Windows related code\r
+\r
+  7zip    - files related to 7-Zip Project\r
+\r
+    Common   - common files for 7-Zip\r
+\r
+    Compress - files related to compression/decompression\r
+\r
+    Archive - files related to archiving\r
+\r
+      Common   - common files for archive handling\r
+      7z       - 7z C++ Encoder/Decoder\r
+\r
+    Bundles    - Modules that are bundles of other modules\r
+  \r
+      Alone7z           - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2\r
+      LzmaCon           - lzma.exe: LZMA compression/decompression\r
+      Format7zR         - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2\r
+      Format7zExtractR  - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2.\r
+\r
+    UI        - User Interface files\r
+         \r
+      Client7z - Test application for 7za.dll,  7zr.dll, 7zxr.dll\r
+      Common   - Common UI files\r
+      Console  - Code for console archiver\r
+\r
+\r
+\r
+CS/ - C# files\r
+  7zip\r
+    Common   - some common files for 7-Zip\r
+    Compress - files related to compression/decompression\r
+      LZ     - files related to LZ (Lempel-Ziv) compression algorithm\r
+      LZMA         - LZMA compression/decompression\r
+      LzmaAlone    - file->file LZMA compression/decompression\r
+      RangeCoder   - Range Coder (special code of compression/decompression)\r
+\r
+Java/  - Java files\r
+  SevenZip\r
+    Compression    - files related to compression/decompression\r
+      LZ           - files related to LZ (Lempel-Ziv) compression algorithm\r
+      LZMA         - LZMA compression/decompression\r
+      RangeCoder   - Range Coder (special code of compression/decompression)\r
+\r
+\r
+C/C++ source code of LZMA SDK is part of 7-Zip project.\r
+7-Zip source code can be downloaded from 7-Zip's SourceForge page:\r
+\r
+  http://sourceforge.net/projects/sevenzip/\r
+\r
+\r
+\r
+LZMA features\r
+-------------\r
+  - Variable dictionary size (up to 1 GB)\r
+  - Estimated compressing speed: about 2 MB/s on 2 GHz CPU\r
+  - Estimated decompressing speed: \r
+      - 20-30 MB/s on 2 GHz Core 2 or AMD Athlon 64\r
+      - 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC\r
+  - Small memory requirements for decompressing (16 KB + DictionarySize)\r
+  - Small code size for decompressing: 5-8 KB\r
+\r
+LZMA decoder uses only integer operations and can be \r
+implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions).\r
+\r
+Some critical operations that affect the speed of LZMA decompression:\r
+  1) 32*16 bit integer multiply\r
+  2) Misspredicted branches (penalty mostly depends from pipeline length)\r
+  3) 32-bit shift and arithmetic operations\r
+\r
+The speed of LZMA decompressing mostly depends from CPU speed.\r
+Memory speed has no big meaning. But if your CPU has small data cache, \r
+overall weight of memory speed will slightly increase.\r
+\r
+\r
+How To Use\r
+----------\r
+\r
+Using LZMA encoder/decoder executable\r
+--------------------------------------\r
+\r
+Usage:  LZMA <e|d> inputFile outputFile [<switches>...]\r
+\r
+  e: encode file\r
+\r
+  d: decode file\r
+\r
+  b: Benchmark. There are two tests: compressing and decompressing \r
+     with LZMA method. Benchmark shows rating in MIPS (million \r
+     instructions per second). Rating value is calculated from \r
+     measured speed and it is normalized with Intel's Core 2 results.\r
+     Also Benchmark checks possible hardware errors (RAM \r
+     errors in most cases). Benchmark uses these settings:\r
+     (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter. \r
+     Also you can change the number of iterations. Example for 30 iterations:\r
+       LZMA b 30\r
+     Default number of iterations is 10.\r
+\r
+<Switches>\r
+  \r
+\r
+  -a{N}:  set compression mode 0 = fast, 1 = normal\r
+          default: 1 (normal)\r
+\r
+  d{N}:   Sets Dictionary size - [0, 30], default: 23 (8MB)\r
+          The maximum value for dictionary size is 1 GB = 2^30 bytes.\r
+          Dictionary size is calculated as DictionarySize = 2^N bytes. \r
+          For decompressing file compressed by LZMA method with dictionary \r
+          size D = 2^N you need about D bytes of memory (RAM).\r
+\r
+  -fb{N}: set number of fast bytes - [5, 273], default: 128\r
+          Usually big number gives a little bit better compression ratio \r
+          and slower compression process.\r
+\r
+  -lc{N}: set number of literal context bits - [0, 8], default: 3\r
+          Sometimes lc=4 gives gain for big files.\r
+\r
+  -lp{N}: set number of literal pos bits - [0, 4], default: 0\r
+          lp switch is intended for periodical data when period is \r
+          equal 2^N. For example, for 32-bit (4 bytes) \r
+          periodical data you can use lp=2. Often it's better to set lc0, \r
+          if you change lp switch.\r
+\r
+  -pb{N}: set number of pos bits - [0, 4], default: 2\r
+          pb switch is intended for periodical data \r
+          when period is equal 2^N.\r
+\r
+  -mf{MF_ID}: set Match Finder. Default: bt4. \r
+              Algorithms from hc* group doesn't provide good compression \r
+              ratio, but they often works pretty fast in combination with \r
+              fast mode (-a0).\r
+\r
+              Memory requirements depend from dictionary size \r
+              (parameter "d" in table below). \r
+\r
+               MF_ID     Memory                   Description\r
+\r
+                bt2    d *  9.5 + 4MB  Binary Tree with 2 bytes hashing.\r
+                bt3    d * 11.5 + 4MB  Binary Tree with 3 bytes hashing.\r
+                bt4    d * 11.5 + 4MB  Binary Tree with 4 bytes hashing.\r
+                hc4    d *  7.5 + 4MB  Hash Chain with 4 bytes hashing.\r
+\r
+  -eos:   write End Of Stream marker. By default LZMA doesn't write \r
+          eos marker, since LZMA decoder knows uncompressed size \r
+          stored in .lzma file header.\r
+\r
+  -si:    Read data from stdin (it will write End Of Stream marker).\r
+  -so:    Write data to stdout\r
+\r
+\r
+Examples:\r
+\r
+1) LZMA e file.bin file.lzma -d16 -lc0 \r
+\r
+compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K)  \r
+and 0 literal context bits. -lc0 allows to reduce memory requirements \r
+for decompression.\r
+\r
+\r
+2) LZMA e file.bin file.lzma -lc0 -lp2\r
+\r
+compresses file.bin to file.lzma with settings suitable \r
+for 32-bit periodical data (for example, ARM or MIPS code).\r
+\r
+3) LZMA d file.lzma file.bin\r
+\r
+decompresses file.lzma to file.bin.\r
+\r
+\r
+Compression ratio hints\r
+-----------------------\r
+\r
+Recommendations\r
+---------------\r
+\r
+To increase the compression ratio for LZMA compressing it's desirable \r
+to have aligned data (if it's possible) and also it's desirable to locate\r
+data in such order, where code is grouped in one place and data is \r
+grouped in other place (it's better than such mixing: code, data, code,\r
+data, ...).\r
+\r
+\r
+Filters\r
+-------\r
+You can increase the compression ratio for some data types, using\r
+special filters before compressing. For example, it's possible to \r
+increase the compression ratio on 5-10% for code for those CPU ISAs: \r
+x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC.\r
+\r
+You can find C source code of such filters in C/Bra*.* files\r
+\r
+You can check the compression ratio gain of these filters with such \r
+7-Zip commands (example for ARM code):\r
+No filter:\r
+  7z a a1.7z a.bin -m0=lzma\r
+\r
+With filter for little-endian ARM code:\r
+  7z a a2.7z a.bin -m0=arm -m1=lzma        \r
+\r
+It works in such manner:\r
+Compressing    = Filter_encoding + LZMA_encoding\r
+Decompressing  = LZMA_decoding + Filter_decoding\r
+\r
+Compressing and decompressing speed of such filters is very high,\r
+so it will not increase decompressing time too much.\r
+Moreover, it reduces decompression time for LZMA_decoding, \r
+since compression ratio with filtering is higher.\r
+\r
+These filters convert CALL (calling procedure) instructions \r
+from relative offsets to absolute addresses, so such data becomes more \r
+compressible.\r
+\r
+For some ISAs (for example, for MIPS) it's impossible to get gain from such filter.\r
+\r
+\r
+LZMA compressed file format\r
+---------------------------\r
+Offset Size Description\r
+  0     1   Special LZMA properties (lc,lp, pb in encoded form)\r
+  1     4   Dictionary size (little endian)\r
+  5     8   Uncompressed size (little endian). -1 means unknown size\r
+ 13         Compressed data\r
+\r
+\r
+ANSI-C LZMA Decoder\r
+~~~~~~~~~~~~~~~~~~~\r
+\r
+Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58.\r
+If you want to use old interfaces you can download previous version of LZMA SDK\r
+from sourceforge.net site.\r
+\r
+To use ANSI-C LZMA Decoder you need the following files:\r
+1) LzmaDec.h + LzmaDec.c + Types.h\r
+LzmaUtil/LzmaUtil.c is example application that uses these files.\r
+\r
+\r
+Memory requirements for LZMA decoding\r
+-------------------------------------\r
+\r
+Stack usage of LZMA decoding function for local variables is not \r
+larger than 200-400 bytes.\r
+\r
+LZMA Decoder uses dictionary buffer and internal state structure.\r
+Internal state structure consumes\r
+  state_size = (4 + (1.5 << (lc + lp))) KB\r
+by default (lc=3, lp=0), state_size = 16 KB.\r
+\r
+\r
+How To decompress data\r
+----------------------\r
+\r
+LZMA Decoder (ANSI-C version) now supports 2 interfaces:\r
+1) Single-call Decompressing\r
+2) Multi-call State Decompressing (zlib-like interface)\r
+\r
+You must use external allocator:\r
+Example:\r
+void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); }\r
+void SzFree(void *p, void *address) { p = p; free(address); }\r
+ISzAlloc alloc = { SzAlloc, SzFree };\r
+\r
+You can use p = p; operator to disable compiler warnings.\r
+\r
+\r
+Single-call Decompressing\r
+-------------------------\r
+When to use: RAM->RAM decompressing\r
+Compile files: LzmaDec.h + LzmaDec.c + Types.h\r
+Compile defines: no defines\r
+Memory Requirements:\r
+  - Input buffer: compressed size\r
+  - Output buffer: uncompressed size\r
+  - LZMA Internal Structures: state_size (16 KB for default settings) \r
+\r
+Interface:\r
+  int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\r
+      const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, \r
+      ELzmaStatus *status, ISzAlloc *alloc);\r
+  In: \r
+    dest     - output data\r
+    destLen  - output data size\r
+    src      - input data\r
+    srcLen   - input data size\r
+    propData - LZMA properties  (5 bytes)\r
+    propSize - size of propData buffer (5 bytes)\r
+    finishMode - It has meaning only if the decoding reaches output limit (*destLen).\r
+         LZMA_FINISH_ANY - Decode just destLen bytes.\r
+         LZMA_FINISH_END - Stream must be finished after (*destLen).\r
+                           You can use LZMA_FINISH_END, when you know that \r
+                           current output buffer covers last bytes of stream. \r
+    alloc    - Memory allocator.\r
+\r
+  Out: \r
+    destLen  - processed output size \r
+    srcLen   - processed input size \r
+\r
+  Output:\r
+    SZ_OK\r
+      status:\r
+        LZMA_STATUS_FINISHED_WITH_MARK\r
+        LZMA_STATUS_NOT_FINISHED \r
+        LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK\r
+    SZ_ERROR_DATA - Data error\r
+    SZ_ERROR_MEM  - Memory allocation error\r
+    SZ_ERROR_UNSUPPORTED - Unsupported properties\r
+    SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).\r
+\r
+  If LZMA decoder sees end_marker before reaching output limit, it returns OK result,\r
+  and output value of destLen will be less than output buffer size limit.\r
+\r
+  You can use multiple checks to test data integrity after full decompression:\r
+    1) Check Result and "status" variable.\r
+    2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.\r
+    3) Check that output(srcLen) = compressedSize, if you know real compressedSize. \r
+       You must use correct finish mode in that case. */ \r
+\r
+\r
+Multi-call State Decompressing (zlib-like interface)\r
+----------------------------------------------------\r
+\r
+When to use: file->file decompressing \r
+Compile files: LzmaDec.h + LzmaDec.c + Types.h\r
+\r
+Memory Requirements:\r
+ - Buffer for input stream: any size (for example, 16 KB)\r
+ - Buffer for output stream: any size (for example, 16 KB)\r
+ - LZMA Internal Structures: state_size (16 KB for default settings) \r
+ - LZMA dictionary (dictionary size is encoded in LZMA properties header)\r
+\r
+1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header:\r
+   unsigned char header[LZMA_PROPS_SIZE + 8];\r
+   ReadFile(inFile, header, sizeof(header)\r
+\r
+2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties\r
+\r
+  CLzmaDec state;\r
+  LzmaDec_Constr(&state);\r
+  res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc);\r
+  if (res != SZ_OK)\r
+    return res;\r
+\r
+3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop\r
+\r
+  LzmaDec_Init(&state);\r
+  for (;;)\r
+  {\r
+    ... \r
+    int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, \r
+        const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode);\r
+    ...\r
+  }\r
+\r
+\r
+4) Free all allocated structures\r
+  LzmaDec_Free(&state, &g_Alloc);\r
+\r
+For full code example, look at C/LzmaUtil/LzmaUtil.c code.\r
+\r
+\r
+How To compress data\r
+--------------------\r
+\r
+Compile files: LzmaEnc.h + LzmaEnc.c + Types.h +\r
+LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + LzHash.h\r
+\r
+Memory Requirements:\r
+  - (dictSize * 11.5 + 6 MB) + state_size\r
+\r
+Lzma Encoder can use two memory allocators:\r
+1) alloc - for small arrays.\r
+2) allocBig - for big arrays.\r
+\r
+For example, you can use Large RAM Pages (2 MB) in allocBig allocator for \r
+better compression speed. Note that Windows has bad implementation for \r
+Large RAM Pages. \r
+It's OK to use same allocator for alloc and allocBig.\r
+\r
+\r
+Single-call Compression with callbacks\r
+--------------------------------------\r
+\r
+Check C/LzmaUtil/LzmaUtil.c as example, \r
+\r
+When to use: file->file decompressing \r
+\r
+1) you must implement callback structures for interfaces:\r
+ISeqInStream\r
+ISeqOutStream\r
+ICompressProgress\r
+ISzAlloc\r
+\r
+static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }\r
+static void SzFree(void *p, void *address) {  p = p; MyFree(address); }\r
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };\r
+\r
+  CFileSeqInStream inStream;\r
+  CFileSeqOutStream outStream;\r
+\r
+  inStream.funcTable.Read = MyRead;\r
+  inStream.file = inFile;\r
+  outStream.funcTable.Write = MyWrite;\r
+  outStream.file = outFile;\r
+\r
+\r
+2) Create CLzmaEncHandle object;\r
+\r
+  CLzmaEncHandle enc;\r
+\r
+  enc = LzmaEnc_Create(&g_Alloc);\r
+  if (enc == 0)\r
+    return SZ_ERROR_MEM;\r
+\r
+\r
+3) initialize CLzmaEncProps properties;\r
+\r
+  LzmaEncProps_Init(&props);\r
+\r
+  Then you can change some properties in that structure.\r
+\r
+4) Send LZMA properties to LZMA Encoder\r
+\r
+  res = LzmaEnc_SetProps(enc, &props);\r
+\r
+5) Write encoded properties to header\r
+\r
+    Byte header[LZMA_PROPS_SIZE + 8];\r
+    size_t headerSize = LZMA_PROPS_SIZE;\r
+    UInt64 fileSize;\r
+    int i;\r
+\r
+    res = LzmaEnc_WriteProperties(enc, header, &headerSize);\r
+    fileSize = MyGetFileLength(inFile);\r
+    for (i = 0; i < 8; i++)\r
+      header[headerSize++] = (Byte)(fileSize >> (8 * i));\r
+    MyWriteFileAndCheck(outFile, header, headerSize)\r
+\r
+6) Call encoding function:\r
+      res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable, \r
+        NULL, &g_Alloc, &g_Alloc);\r
+\r
+7) Destroy LZMA Encoder Object\r
+  LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);\r
+\r
+\r
+If callback function return some error code, LzmaEnc_Encode also returns that code\r
+or it can return the code like SZ_ERROR_READ, SZ_ERROR_WRITE or SZ_ERROR_PROGRESS.\r
+\r
+\r
+Single-call RAM->RAM Compression\r
+--------------------------------\r
+\r
+Single-call RAM->RAM Compression is similar to Compression with callbacks,\r
+but you provide pointers to buffers instead of pointers to stream callbacks:\r
+\r
+HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,\r
+    CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, \r
+    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);\r
+\r
+Return code:\r
+  SZ_OK               - OK\r
+  SZ_ERROR_MEM        - Memory allocation error \r
+  SZ_ERROR_PARAM      - Incorrect paramater\r
+  SZ_ERROR_OUTPUT_EOF - output buffer overflow\r
+  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)\r
+\r
+\r
+\r
+Defines\r
+-------\r
+\r
+_LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code.\r
+\r
+_LZMA_PROB32   - It can increase the speed on some 32-bit CPUs, but memory usage for \r
+                 some structures will be doubled in that case.\r
+\r
+_LZMA_UINT32_IS_ULONG  - Define it if int is 16-bit on your compiler and long is 32-bit.\r
+\r
+_LZMA_NO_SYSTEM_SIZE_T  - Define it if you don't want to use size_t type.\r
+\r
+\r
+_7ZIP_PPMD_SUPPPORT - Define it if you don't want to support PPMD method in AMSI-C .7z decoder.\r
+\r
+\r
+C++ LZMA Encoder/Decoder \r
+~~~~~~~~~~~~~~~~~~~~~~~~\r
+C++ LZMA code use COM-like interfaces. So if you want to use it, \r
+you can study basics of COM/OLE.\r
+C++ LZMA code is just wrapper over ANSI-C code.\r
+\r
+\r
+C++ Notes\r
+~~~~~~~~~~~~~~~~~~~~~~~~\r
+If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling),\r
+you must check that you correctly work with "new" operator.\r
+7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator.\r
+So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator:\r
+operator new(size_t size)\r
+{\r
+  void *p = ::malloc(size);\r
+  if (p == 0)\r
+    throw CNewException();\r
+  return p;\r
+}\r
+If you use MSCV that throws exception for "new" operator, you can compile without \r
+"NewHandler.cpp". So standard exception will be used. Actually some code of \r
+7-Zip catches any exception in internal code and converts it to HRESULT code.\r
+So you don't need to catch CNewException, if you call COM interfaces of 7-Zip.\r
+\r
+---\r
+\r
+http://www.7-zip.org\r
+http://www.7-zip.org/sdk.html\r
+http://www.7-zip.org/support.html\r
diff --git a/DOC/readme.txt b/DOC/readme.txt
new file mode 100755 (executable)
index 0000000..14731ee
--- /dev/null
@@ -0,0 +1,181 @@
+7-Zip 9.20 Sources\r
+------------------\r
+\r
+7-Zip is a file archiver for Windows. \r
+\r
+7-Zip Copyright (C) 1999-2010 Igor Pavlov.\r
+\r
+\r
+License Info\r
+------------\r
+\r
+7-Zip is free software distributed under the GNU LGPL \r
+(except for unRar code).\r
+read License.txt for more infomation about license.\r
+\r
+Notes about unRAR license:\r
+\r
+Please check main restriction from unRar license:\r
+\r
+   2. The unRAR sources may be used in any software to handle RAR\r
+      archives without limitations free of charge, but cannot be used\r
+      to re-create the RAR compression algorithm, which is proprietary.\r
+      Distribution of modified unRAR sources in separate form or as a\r
+      part of other software is permitted, provided that it is clearly\r
+      stated in the documentation and source comments that the code may\r
+      not be used to develop a RAR (WinRAR) compatible archiver.\r
+\r
+In brief it means:\r
+1) You can compile and use compiled files under GNU LGPL rules, since \r
+   unRAR license almost has no restrictions for compiled files.\r
+   You can link these compiled files to LGPL programs.\r
+2) You can fix bugs in source code and use compiled fixed version.\r
+3) You can not use unRAR sources to re-create the RAR compression algorithm.\r
+\r
+\r
+LZMA SDK\r
+--------\r
+\r
+Also this package contains files from LZMA SDK\r
+you can download LZMA SDK from this page:\r
+http://www.7-zip.org/sdk.html\r
+read about addtional licenses for LZMA SDK in file\r
+DOC/lzma.txt\r
+\r
+\r
+How to compile\r
+--------------\r
+To compile sources you need Visual C++ 6.0.\r
+For compiling some files you also need \r
+new Platform SDK from Microsoft' Site:\r
+http://www.microsoft.com/msdownload/platformsdk/sdkupdate/psdk-full.htm\r
+or\r
+http://www.microsoft.com/msdownload/platformsdk/sdkupdate/XPSP2FULLInstall.htm\r
+or\r
+http://www.microsoft.com/msdownload/platformsdk/sdkupdate/\r
+\r
+If you use MSVC6, specify SDK directories at top of directories lists:\r
+Tools / Options / Directories\r
+  - Include files\r
+  - Library files\r
+\r
+\r
+To compile 7-Zip for AMD64 and IA64 you need:\r
+  Windows Server 2003 SP1 Platform SDK from microsoft.com\r
+\r
+Also you need Microsoft Macro Assembler:\r
+  - ml.exe for x86 \r
+  - ml64.exe for AMD64\r
+You can use ml.exe from Windows SDK for Windows Vista or some other version.\r
+\r
+\r
+Compiling under Unix/Linux\r
+--------------------------\r
+Check this site for Posix/Linux version:\r
+http://sourceforge.net/projects/p7zip/\r
+\r
+\r
+Notes:\r
+------\r
+7-Zip consists of COM modules (DLL files).\r
+But 7-Zip doesn't use standard COM interfaces for creating objects.\r
+Look at\r
+7zip\UI\Client7z folder for example of using DLL files of 7-Zip. \r
+Some DLL files can use other DLL files from 7-Zip.\r
+If you don't like it, you must use standalone version of DLL.\r
+To compile standalone version of DLL you must include all used parts\r
+to project and define some defs. \r
+For example, 7zip\Bundles\Format7z is a standalone version  of 7z.dll \r
+that works with 7z format. So you can use such DLL in your project \r
+without additional DLL files.\r
+\r
+\r
+Description of 7-Zip sources package\r
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+\r
+DOC                Documentation\r
+---\r
+  7zFormat.txt   - 7z format description\r
+  copying.txt    - GNU LGPL license\r
+  unRarLicense.txt - License for unRAR part of source code\r
+  history.txt    - Sources history\r
+  Methods.txt    - Compression method IDs\r
+  readme.txt     - Readme file\r
+  lzma.txt       - LZMA SDK description\r
+  7zip.nsi       - installer script for NSIS\r
+\r
+\r
+C   - Source code in C\r
+CPP - Source code in CPP\r
+\r
+Common            Common modules\r
+Windows           Win32 wrappers\r
+\r
+7zip\r
+-------\r
+  Common          Common modules for 7-zip\r
+\r
+  Archive         7-Zip Archive Format Plugins \r
+  --------\r
+    Common\r
+    7z\r
+    Arj\r
+    BZip2\r
+    Cab\r
+    Cpio\r
+    GZip\r
+    Rar\r
+    Rpm            \r
+    Split\r
+    Tar\r
+    Zip\r
+\r
+  Bundle          Modules that are bundles of other modules\r
+  ------\r
+    Alone         7za.exe: Standalone version of 7z\r
+    Alone7z       7zr.exe: Standalone version of 7z that supports only 7z/LZMA/BCJ/BCJ2\r
+    SFXCon        7zCon.sfx: Console 7z SFX module\r
+    SFXWin        7z.sfx: Windows 7z SFX module\r
+    SFXSetup      7zS.sfx: Windows 7z SFX module for Installers\r
+    Format7z            7za.dll:  .7z support\r
+    Format7zExtract     7zxa.dll: .7z support, extracting only\r
+    Format7zR           7zr.dll:  .7z support, LZMA/BCJ* only\r
+    Format7zExtractR    7zxr.dll: .7z support, LZMA/BCJ* only, extracting only\r
+    Format7zF           7z.dll:   all formats\r
+\r
+  UI\r
+  --\r
+    Agent         Intermediary modules for FAR plugin and Explorer plugin\r
+    Console       7z.exe Console version\r
+    Explorer      Explorer plugin\r
+    Resource      Resources\r
+    Far           FAR plugin  \r
+    Client7z      Test application for 7za.dll \r
+\r
+  Compress\r
+  --------\r
+    BZip2        BZip2 compressor\r
+    Branch       Branch converter\r
+    ByteSwap     Byte Swap converter\r
+    Copy         Copy coder\r
+    Deflate       \r
+    Implode\r
+    Arj\r
+    LZMA\r
+    PPMd          Dmitry Shkarin's PPMdH with small changes.\r
+    LZ            Lempel - Ziv\r
+\r
+  Crypto          Crypto modules\r
+  ------\r
+    7zAES         Cipher for 7z\r
+    AES           AES Cipher\r
+    Rar20         Cipher for Rar 2.0\r
+    RarAES        Cipher for Rar 3.0\r
+    Zip           Cipher for Zip\r
+\r
+  FileManager       File Manager\r
+\r
+\r
+---\r
+Igor Pavlov\r
+http://www.7-zip.org\r
diff --git a/DOC/unRarLicense.txt b/DOC/unRarLicense.txt
new file mode 100755 (executable)
index 0000000..5f78b72
--- /dev/null
@@ -0,0 +1,41 @@
+ ******    *****   ******   unRAR - free utility for RAR archives
+ **   **  **   **  **   **  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ******   *******  ******    License for use and distribution of
+ **   **  **   **  **   **   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ **   **  **   **  **   **         FREE portable version
+                                   ~~~~~~~~~~~~~~~~~~~~~
+
+      The source code of unRAR utility is freeware. This means:
+
+   1. All copyrights to RAR and the utility unRAR are exclusively
+      owned by the author - Alexander Roshal.
+
+   2. The unRAR sources may be used in any software to handle RAR
+      archives without limitations free of charge, but cannot be used
+      to re-create the RAR compression algorithm, which is proprietary.
+      Distribution of modified unRAR sources in separate form or as a
+      part of other software is permitted, provided that it is clearly
+      stated in the documentation and source comments that the code may
+      not be used to develop a RAR (WinRAR) compatible archiver.
+
+   3. The unRAR utility may be freely distributed. No person or company 
+      may charge a fee for the distribution of unRAR without written
+      permission from the copyright holder.
+
+   4. THE RAR ARCHIVER AND THE UNRAR UTILITY ARE DISTRIBUTED "AS IS".
+      NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED.  YOU USE AT 
+      YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS, 
+      DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING
+      OR MISUSING THIS SOFTWARE.
+
+   5. Installing and using the unRAR utility signifies acceptance of
+      these terms and conditions of the license.
+
+   6. If you don't agree with terms of the license you must remove
+      unRAR files from your storage devices and cease to use the
+      utility.
+
+      Thank you for your interest in RAR and unRAR.
+
+
+                                            Alexander L. Roshal
\ No newline at end of file