diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2021-07-23 01:00:14 +0300 |
---|---|---|
committer | Kornel <kornel@geekhood.net> | 2021-07-23 01:00:14 +0300 |
commit | 585698650f7257d2cefa6a3a2a49d5bbe84fd9b2 (patch) | |
tree | 8900be42e892a440bbd1063804b0557288c2f97f /CPP | |
parent | 4a960640a340a848a2d2c27f19b339c2c3d3f734 (diff) |
21.0221.02
Diffstat (limited to 'CPP')
515 files changed, 21830 insertions, 6849 deletions
diff --git a/CPP/7zip/7zip_gcc.mak b/CPP/7zip/7zip_gcc.mak new file mode 100644 index 00000000..122686ff --- /dev/null +++ b/CPP/7zip/7zip_gcc.mak @@ -0,0 +1,1183 @@ +# USE_CLANG=1 +# USE_ASM = 1 +# IS_X64 = 1 +# MY_ARCH = + + +MY_ARCH_2 = $(MY_ARCH) + +MY_ASM = jwasm +MY_ASM = asmc + +PROGPATH = $(O)/$(PROG) + + +ifneq ($(CC), xlc) +CFLAGS_WARN_WALL = -Wall -Werror -Wextra +endif + +# for object file +CFLAGS_BASE_LIST = -c +# CFLAGS_BASE_LIST = -S +CFLAGS_BASE = -O2 $(CFLAGS_BASE_LIST) $(CFLAGS_WARN_WALL) $(CFLAGS_WARN) \ + -DNDEBUG -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \ + -fPIC + + +ifdef SystemDrive +IS_MINGW = 1 +endif + +ifdef IS_MINGW +LDFLAGS_STATIC_2 = -static +else +ifndef DEF_FILE +ifndef IS_NOT_STANDALONE +ifndef MY_DYNAMIC_LINK +ifneq ($(CC), clang) +LDFLAGS_STATIC_2 = +# -static +# -static-libstdc++ -static-libgcc +endif +endif +endif +endif +endif + +LDFLAGS_STATIC = -DNDEBUG $(LDFLAGS_STATIC_2) + +ifndef O + ifdef IS_MINGW + O=_o + else + O=_o + endif +endif + + +ifdef DEF_FILE + + +ifdef IS_MINGW +SHARED_EXT=.dll +LDFLAGS = -shared -DEF $(DEF_FILE) $(LDFLAGS_STATIC) +else +SHARED_EXT=.so +LDFLAGS = -shared -fPIC $(LDFLAGS_STATIC) +CC_SHARED=-fPIC +endif + + +else + +LDFLAGS = $(LDFLAGS_STATIC) +# -s is not required for clang, do we need it for GGC ??? +# -s + +#-static -static-libgcc -static-libstdc++ + +ifdef IS_MINGW +SHARED_EXT=.exe +else +SHARED_EXT= +endif + +endif + + +PROGPATH = $(O)/$(PROG)$(SHARED_EXT) + + +ifdef IS_MINGW + +RM = del +MY_MKDIR=mkdir +LIB2 = -loleaut32 -luuid -ladvapi32 -lUser32 + +CXXFLAGS_EXTRA = -DUNICODE -D_UNICODE +# -Wno-delete-non-virtual-dtor + +DEL_OBJ_EXE = -$(RM) $(O)\*.o $(O)\$(PROG).exe $(O)\$(PROG).dll + +else + +RM = rm -f +MY_MKDIR=mkdir -p +# CFLAGS_BASE := $(CFLAGS_BASE) -D_7ZIP_ST +# CXXFLAGS_EXTRA = -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE + +# LOCAL_LIBS=-lpthread +# LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl +LIB2 = -lpthread -ldl + + + +DEL_OBJ_EXE = -$(RM) $(PROGPATH) $(OBJS) + +endif + + + +CFLAGS = $(MY_ARCH_2) $(LOCAL_FLAGS) $(CFLAGS_BASE2) $(CFLAGS_BASE) $(CC_SHARED) -o $@ + + +ifdef IS_MINGW +AFLAGS_ABI = -coff -DABI_CDECL +AFLAGS = $(AFLAGS_ABI) -Fo$(O)/$(basename $(<F)).o +else +ifdef IS_X64 +AFLAGS_ABI = -elf64 -DABI_LINUX +else +AFLAGS_ABI = -elf -DABI_LINUX -DABI_CDECL +# -DABI_CDECL +# -DABI_LINUX +# -DABI_CDECL +endif +AFLAGS = $(AFLAGS_ABI) -Fo$(O)/ +endif + +ifdef USE_ASM +CONSOLE_ASM_FLAGS=-D_7ZIP_ASM +else +CONSOLE_ASM_FLAGS= +endif + +CXX_WARN_FLAGS = +#-Wno-invalid-offsetof +#-Wno-reorder + +CXXFLAGS = $(MY_ARCH_2) $(LOCAL_FLAGS) $(CXXFLAGS_BASE2) $(CFLAGS_BASE) $(CXXFLAGS_EXTRA) $(CC_SHARED) -o $@ $(CXX_WARN_FLAGS) + +all: $(O) $(PROGPATH) + +$(O): + $(MY_MKDIR) $(O) + +$(PROGPATH): $(OBJS) + $(CXX) -o $(PROGPATH) -s $(MY_ARCH_2) $(LDFLAGS) $(LD_arch) $(OBJS) $(MY_LIBS) $(LIB2) + +# -s strips debug sections from executable in GCC + + + + +ifndef NO_DEFAULT_RES +$O/resource.o: resource.rc + windres.exe $(RFLAGS) resource.rc $O/resource.o +endif + +$O/LzmaAlone.o: LzmaAlone.cpp + $(CXX) $(CXXFLAGS) $< + + +$O/CommandLineParser.o: ../../../Common/CommandLineParser.cpp + $(CXX) $(CXXFLAGS) $< +$O/CRC.o: ../../../Common/CRC.cpp + $(CXX) $(CXXFLAGS) $< + +$O/CrcReg.o: ../../../Common/CrcReg.cpp + $(CXX) $(CXXFLAGS) $< + +$O/DynLimBuf.o: ../../../Common/DynLimBuf.cpp + $(CXX) $(CXXFLAGS) $< +$O/IntToString.o: ../../../Common/IntToString.cpp + $(CXX) $(CXXFLAGS) $< +$O/Lang.o: ../../../Common/Lang.cpp + $(CXX) $(CXXFLAGS) $< +$O/ListFileUtils.o: ../../../Common/ListFileUtils.cpp + $(CXX) $(CXXFLAGS) $< +$O/MyMap.o: ../../../Common/MyMap.cpp + $(CXX) $(CXXFLAGS) $< +$O/MyString.o: ../../../Common/MyString.cpp + $(CXX) $(CXXFLAGS) $< +$O/MyVector.o: ../../../Common/MyVector.cpp + $(CXX) $(CXXFLAGS) $< +$O/MyWindows.o: ../../../Common/MyWindows.cpp + $(CXX) $(CXXFLAGS) $< +$O/MyWindows2.o: ../../../Common/MyWindows2.cpp + $(CXX) $(CXXFLAGS) $< +$O/MyXml.o: ../../../Common/MyXml.cpp + $(CXX) $(CXXFLAGS) $< +$O/NewHandler.o: ../../../Common/NewHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/Random.o: ../../../Common/Random.cpp + $(CXX) $(CXXFLAGS) $< +$O/Sha1Prepare.o: ../../../Common/Sha1Prepare.cpp + $(CXX) $(CXXFLAGS) $< +$O/Sha1Reg.o: ../../../Common/Sha1Reg.cpp + $(CXX) $(CXXFLAGS) $< +$O/Sha256Prepare.o: ../../../Common/Sha256Prepare.cpp + $(CXX) $(CXXFLAGS) $< +$O/Sha256Reg.o: ../../../Common/Sha256Reg.cpp + $(CXX) $(CXXFLAGS) $< +$O/StdInStream.o: ../../../Common/StdInStream.cpp + $(CXX) $(CXXFLAGS) $< +$O/StdOutStream.o: ../../../Common/StdOutStream.cpp + $(CXX) $(CXXFLAGS) $< +$O/StringConvert.o: ../../../Common/StringConvert.cpp + $(CXX) $(CXXFLAGS) $< +$O/StringToInt.o: ../../../Common/StringToInt.cpp + $(CXX) $(CXXFLAGS) $< +$O/TextConfig.o: ../../../Common/TextConfig.cpp + $(CXX) $(CXXFLAGS) $< +$O/UTFConvert.o: ../../../Common/UTFConvert.cpp + $(CXX) $(CXXFLAGS) $< +$O/Wildcard.o: ../../../Common/Wildcard.cpp + $(CXX) $(CXXFLAGS) $< +$O/XzCrc64Init.o: ../../../Common/XzCrc64Init.cpp + $(CXX) $(CXXFLAGS) $< +$O/XzCrc64Reg.o: ../../../Common/XzCrc64Reg.cpp + $(CXX) $(CXXFLAGS) $< + + + +$O/Clipboard.o: ../../../Windows/Clipboard.cpp + $(CXX) $(CXXFLAGS) $< +$O/COM.o: ../../../Windows/COM.cpp + $(CXX) $(CXXFLAGS) $< +$O/CommonDialog.o: ../../../Windows/CommonDialog.cpp + $(CXX) $(CXXFLAGS) $< +$O/Console.o: ../../../Windows/Console.cpp + $(CXX) $(CXXFLAGS) $< +$O/DLL.o: ../../../Windows/DLL.cpp + $(CXX) $(CXXFLAGS) $< +$O/ErrorMsg.o: ../../../Windows/ErrorMsg.cpp + $(CXX) $(CXXFLAGS) $< +$O/FileDir.o: ../../../Windows/FileDir.cpp + $(CXX) $(CXXFLAGS) $< +$O/FileFind.o: ../../../Windows/FileFind.cpp + $(CXX) $(CXXFLAGS) $< + +$O/FileIO.o: ../../../Windows/FileIO.cpp + $(CXX) $(CXXFLAGS) $< + +$O/FileLink.o: ../../../Windows/FileLink.cpp + $(CXX) $(CXXFLAGS) $< +$O/FileMapping.o: ../../../Windows/FileMapping.cpp + $(CXX) $(CXXFLAGS) $< +$O/FileName.o: ../../../Windows/FileName.cpp + $(CXX) $(CXXFLAGS) $< +$O/FileSystem.o: ../../../Windows/FileSystem.cpp + $(CXX) $(CXXFLAGS) $< +$O/MemoryGlobal.o: ../../../Windows/MemoryGlobal.cpp + $(CXX) $(CXXFLAGS) $< +$O/MemoryLock.o: ../../../Windows/MemoryLock.cpp + $(CXX) $(CXXFLAGS) $< +$O/Menu.o: ../../../Windows/Menu.cpp + $(CXX) $(CXXFLAGS) $< +$O/NationalTime.o: ../../../Windows/NationalTime.cpp + $(CXX) $(CXXFLAGS) $< +$O/Net.o: ../../../Windows/Net.cpp + $(CXX) $(CXXFLAGS) $< +$O/ProcessMessages.o: ../../../Windows/ProcessMessages.cpp + $(CXX) $(CXXFLAGS) $< +$O/ProcessUtils.o: ../../../Windows/ProcessUtils.cpp + $(CXX) $(CXXFLAGS) $< +$O/PropVariant.o: ../../../Windows/PropVariant.cpp + $(CXX) $(CXXFLAGS) $< +$O/PropVariantConv.o: ../../../Windows/PropVariantConv.cpp + $(CXX) $(CXXFLAGS) $< +$O/PropVariantUtils.o: ../../../Windows/PropVariantUtils.cpp + $(CXX) $(CXXFLAGS) $< +$O/Registry.o: ../../../Windows/Registry.cpp + $(CXX) $(CXXFLAGS) $< +$O/ResourceString.o: ../../../Windows/ResourceString.cpp + $(CXX) $(CXXFLAGS) $< +$O/SecurityUtils.o: ../../../Windows/SecurityUtils.cpp + $(CXX) $(CXXFLAGS) $< +$O/Shell.o: ../../../Windows/Shell.cpp + $(CXX) $(CXXFLAGS) $< +$O/Synchronization.o: ../../../Windows/Synchronization.cpp + $(CXX) $(CXXFLAGS) $< +$O/System.o: ../../../Windows/System.cpp + $(CXX) $(CXXFLAGS) $< +$O/SystemInfo.o: ../../../Windows/SystemInfo.cpp + $(CXX) $(CXXFLAGS) $< +$O/TimeUtils.o: ../../../Windows/TimeUtils.cpp + $(CXX) $(CXXFLAGS) $< +$O/Window.o: ../../../Windows/Window.cpp + $(CXX) $(CXXFLAGS) $< + + + +$O/ComboBox.o: ../../../Windows/Control/ComboBox.cpp + $(CXX) $(CXXFLAGS) $< +$O/Dialog.o: ../../../Windows/Control/Dialog.cpp + $(CXX) $(CXXFLAGS) $< +$O/ImageList.o: ../../../Windows/Control/ImageList.cpp + $(CXX) $(CXXFLAGS) $< +$O/ListView.o: ../../../Windows/Control/ListView.cpp + $(CXX) $(CXXFLAGS) $< +$O/PropertyPage.o: ../../../Windows/Control/PropertyPage.cpp + $(CXX) $(CXXFLAGS) $< +$O/Window2.o: ../../../Windows/Control/Window2.cpp + $(CXX) $(CXXFLAGS) $< + + +$O/CreateCoder.o: ../../Common/CreateCoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/CWrappers.o: ../../Common/CWrappers.cpp + $(CXX) $(CXXFLAGS) $< +$O/FilePathAutoRename.o: ../../Common/FilePathAutoRename.cpp + $(CXX) $(CXXFLAGS) $< +$O/FileStreams.o: ../../Common/FileStreams.cpp + $(CXX) $(CXXFLAGS) $< +$O/FilterCoder.o: ../../Common/FilterCoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/InBuffer.o: ../../Common/InBuffer.cpp + $(CXX) $(CXXFLAGS) $< +$O/InOutTempBuffer.o: ../../Common/InOutTempBuffer.cpp + $(CXX) $(CXXFLAGS) $< +$O/LimitedStreams.o: ../../Common/LimitedStreams.cpp + $(CXX) $(CXXFLAGS) $< +$O/LockedStream.o: ../../Common/LockedStream.cpp + $(CXX) $(CXXFLAGS) $< +$O/MemBlocks.o: ../../Common/MemBlocks.cpp + $(CXX) $(CXXFLAGS) $< +$O/MethodId.o: ../../Common/MethodId.cpp + $(CXX) $(CXXFLAGS) $< +$O/MethodProps.o: ../../Common/MethodProps.cpp + $(CXX) $(CXXFLAGS) $< +$O/OffsetStream.o: ../../Common/OffsetStream.cpp + $(CXX) $(CXXFLAGS) $< +$O/OutBuffer.o: ../../Common/OutBuffer.cpp + $(CXX) $(CXXFLAGS) $< +$O/OutMemStream.o: ../../Common/OutMemStream.cpp + $(CXX) $(CXXFLAGS) $< +$O/ProgressMt.o: ../../Common/ProgressMt.cpp + $(CXX) $(CXXFLAGS) $< +$O/ProgressUtils.o: ../../Common/ProgressUtils.cpp + $(CXX) $(CXXFLAGS) $< +$O/PropId.o: ../../Common/PropId.cpp + $(CXX) $(CXXFLAGS) $< +$O/StreamBinder.o: ../../Common/StreamBinder.cpp + $(CXX) $(CXXFLAGS) $< +$O/StreamObjects.o: ../../Common/StreamObjects.cpp + $(CXX) $(CXXFLAGS) $< +$O/StreamUtils.o: ../../Common/StreamUtils.cpp + $(CXX) $(CXXFLAGS) $< +$O/UniqBlocks.o: ../../Common/UniqBlocks.cpp + $(CXX) $(CXXFLAGS) $< +$O/VirtThread.o: ../../Common/VirtThread.cpp + $(CXX) $(CXXFLAGS) $< + + +$O/ApmHandler.o: ../../Archive/ApmHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/ArchiveExports.o: ../../Archive/ArchiveExports.cpp + $(CXX) $(CXXFLAGS) $< +$O/ArHandler.o: ../../Archive/ArHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/ArjHandler.o: ../../Archive/ArjHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/Base64Handler.o: ../../Archive/Base64Handler.cpp + $(CXX) $(CXXFLAGS) $< +$O/Bz2Handler.o: ../../Archive/Bz2Handler.cpp + $(CXX) $(CXXFLAGS) $< +$O/ComHandler.o: ../../Archive/ComHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/CpioHandler.o: ../../Archive/CpioHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/CramfsHandler.o: ../../Archive/CramfsHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/DeflateProps.o: ../../Archive/DeflateProps.cpp + $(CXX) $(CXXFLAGS) $< +$O/DllExports.o: ../../Archive/DllExports.cpp + $(CXX) $(CXXFLAGS) $< +$O/DllExports2.o: ../../Archive/DllExports2.cpp + $(CXX) $(CXXFLAGS) $< +$O/DmgHandler.o: ../../Archive/DmgHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/ElfHandler.o: ../../Archive/ElfHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/ExtHandler.o: ../../Archive/ExtHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/FatHandler.o: ../../Archive/FatHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/FlvHandler.o: ../../Archive/FlvHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/GptHandler.o: ../../Archive/GptHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/GzHandler.o: ../../Archive/GzHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/HandlerCont.o: ../../Archive/HandlerCont.cpp + $(CXX) $(CXXFLAGS) $< +$O/HfsHandler.o: ../../Archive/HfsHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/IhexHandler.o: ../../Archive/IhexHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/LzhHandler.o: ../../Archive/LzhHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/LzmaHandler.o: ../../Archive/LzmaHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/MachoHandler.o: ../../Archive/MachoHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/MbrHandler.o: ../../Archive/MbrHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/MslzHandler.o: ../../Archive/MslzHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/MubHandler.o: ../../Archive/MubHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/NtfsHandler.o: ../../Archive/NtfsHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/PeHandler.o: ../../Archive/PeHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/PpmdHandler.o: ../../Archive/PpmdHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/QcowHandler.o: ../../Archive/QcowHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/RpmHandler.o: ../../Archive/RpmHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/SplitHandler.o: ../../Archive/SplitHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/SquashfsHandler.o: ../../Archive/SquashfsHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/SwfHandler.o: ../../Archive/SwfHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/UefiHandler.o: ../../Archive/UefiHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/VdiHandler.o: ../../Archive/VdiHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/VhdHandler.o: ../../Archive/VhdHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/VmdkHandler.o: ../../Archive/VmdkHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/XarHandler.o: ../../Archive/XarHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/XzHandler.o: ../../Archive/XzHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/ZHandler.o: ../../Archive/ZHandler.cpp + $(CXX) $(CXXFLAGS) $< + + +$O/7zCompressionMode.o: ../../Archive/7z/7zCompressionMode.cpp + $(CXX) $(CXXFLAGS) $< +$O/7zDecode.o: ../../Archive/7z/7zDecode.cpp + $(CXX) $(CXXFLAGS) $< +$O/7zEncode.o: ../../Archive/7z/7zEncode.cpp + $(CXX) $(CXXFLAGS) $< +$O/7zExtract.o: ../../Archive/7z/7zExtract.cpp + $(CXX) $(CXXFLAGS) $< +$O/7zFolderInStream.o: ../../Archive/7z/7zFolderInStream.cpp + $(CXX) $(CXXFLAGS) $< +$O/7zHandler.o: ../../Archive/7z/7zHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/7zHandlerOut.o: ../../Archive/7z/7zHandlerOut.cpp + $(CXX) $(CXXFLAGS) $< +$O/7zHeader.o: ../../Archive/7z/7zHeader.cpp + $(CXX) $(CXXFLAGS) $< +$O/7zIn.o: ../../Archive/7z/7zIn.cpp + $(CXX) $(CXXFLAGS) $< +$O/7zOut.o: ../../Archive/7z/7zOut.cpp + $(CXX) $(CXXFLAGS) $< +$O/7zProperties.o: ../../Archive/7z/7zProperties.cpp + $(CXX) $(CXXFLAGS) $< +$O/7zRegister.o: ../../Archive/7z/7zRegister.cpp + $(CXX) $(CXXFLAGS) $< +$O/7zSpecStream.o: ../../Archive/7z/7zSpecStream.cpp + $(CXX) $(CXXFLAGS) $< +$O/7zUpdate.o: ../../Archive/7z/7zUpdate.cpp + $(CXX) $(CXXFLAGS) $< + + +$O/CabBlockInStream.o: ../../Archive/Cab/CabBlockInStream.cpp + $(CXX) $(CXXFLAGS) $< +$O/CabHandler.o: ../../Archive/Cab/CabHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/CabHeader.o: ../../Archive/Cab/CabHeader.cpp + $(CXX) $(CXXFLAGS) $< +$O/CabIn.o: ../../Archive/Cab/CabIn.cpp + $(CXX) $(CXXFLAGS) $< +$O/CabRegister.o: ../../Archive/Cab/CabRegister.cpp + $(CXX) $(CXXFLAGS) $< + + +$O/ChmHandler.o: ../../Archive/Chm/ChmHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/ChmIn.o: ../../Archive/Chm/ChmIn.cpp + $(CXX) $(CXXFLAGS) $< + +$O/IsoHandler.o: ../../Archive/Iso/IsoHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/IsoHeader.o: ../../Archive/Iso/IsoHeader.cpp + $(CXX) $(CXXFLAGS) $< +$O/IsoIn.o: ../../Archive/Iso/IsoIn.cpp + $(CXX) $(CXXFLAGS) $< +$O/IsoRegister.o: ../../Archive/Iso/IsoRegister.cpp + $(CXX) $(CXXFLAGS) $< + +$O/NsisDecode.o: ../../Archive/Nsis/NsisDecode.cpp + $(CXX) $(CXXFLAGS) $< +$O/NsisHandler.o: ../../Archive/Nsis/NsisHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/NsisIn.o: ../../Archive/Nsis/NsisIn.cpp + $(CXX) $(CXXFLAGS) $< +$O/NsisRegister.o: ../../Archive/Nsis/NsisRegister.cpp + $(CXX) $(CXXFLAGS) $< + +$O/Rar5Handler.o: ../../Archive/Rar/Rar5Handler.cpp + $(CXX) $(CXXFLAGS) $< +$O/RarHandler.o: ../../Archive/Rar/RarHandler.cpp + $(CXX) $(CXXFLAGS) $< + +$O/TarHandler.o: ../../Archive/Tar/TarHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/TarHandlerOut.o: ../../Archive/Tar/TarHandlerOut.cpp + $(CXX) $(CXXFLAGS) $< +$O/TarHeader.o: ../../Archive/Tar/TarHeader.cpp + $(CXX) $(CXXFLAGS) $< +$O/TarIn.o: ../../Archive/Tar/TarIn.cpp + $(CXX) $(CXXFLAGS) $< +$O/TarOut.o: ../../Archive/Tar/TarOut.cpp + $(CXX) $(CXXFLAGS) $< +$O/TarRegister.o: ../../Archive/Tar/TarRegister.cpp + $(CXX) $(CXXFLAGS) $< +$O/TarUpdate.o: ../../Archive/Tar/TarUpdate.cpp + $(CXX) $(CXXFLAGS) $< + +$O/UdfHandler.o: ../../Archive/Udf/UdfHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/UdfIn.o: ../../Archive/Udf/UdfIn.cpp + $(CXX) $(CXXFLAGS) $< + + +$O/WimHandler.o: ../../Archive/Wim/WimHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/WimHandlerOut.o: ../../Archive/Wim/WimHandlerOut.cpp + $(CXX) $(CXXFLAGS) $< +$O/WimIn.o: ../../Archive/Wim/WimIn.cpp + $(CXX) $(CXXFLAGS) $< +$O/WimRegister.o: ../../Archive/Wim/WimRegister.cpp + $(CXX) $(CXXFLAGS) $< + + +$O/ZipAddCommon.o: ../../Archive/Zip/ZipAddCommon.cpp + $(CXX) $(CXXFLAGS) $< +$O/ZipHandler.o: ../../Archive/Zip/ZipHandler.cpp + $(CXX) $(CXXFLAGS) $< +$O/ZipHandlerOut.o: ../../Archive/Zip/ZipHandlerOut.cpp + $(CXX) $(CXXFLAGS) $< +$O/ZipIn.o: ../../Archive/Zip/ZipIn.cpp + $(CXX) $(CXXFLAGS) $< +$O/ZipItem.o: ../../Archive/Zip/ZipItem.cpp + $(CXX) $(CXXFLAGS) $< +$O/ZipOut.o: ../../Archive/Zip/ZipOut.cpp + $(CXX) $(CXXFLAGS) $< +$O/ZipUpdate.o: ../../Archive/Zip/ZipUpdate.cpp + $(CXX) $(CXXFLAGS) $< +$O/ZipRegister.o: ../../Archive/Zip/ZipRegister.cpp + $(CXX) $(CXXFLAGS) $< + + +$O/Bcj2Coder.o: ../../Compress/Bcj2Coder.cpp + $(CXX) $(CXXFLAGS) $< +$O/Bcj2Register.o: ../../Compress/Bcj2Register.cpp + $(CXX) $(CXXFLAGS) $< +$O/BcjCoder.o: ../../Compress/BcjCoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/BcjRegister.o: ../../Compress/BcjRegister.cpp + $(CXX) $(CXXFLAGS) $< +$O/BitlDecoder.o: ../../Compress/BitlDecoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/BranchMisc.o: ../../Compress/BranchMisc.cpp + $(CXX) $(CXXFLAGS) $< +$O/BranchRegister.o: ../../Compress/BranchRegister.cpp + $(CXX) $(CXXFLAGS) $< +$O/ByteSwap.o: ../../Compress/ByteSwap.cpp + $(CXX) $(CXXFLAGS) $< +$O/BZip2Crc.o: ../../Compress/BZip2Crc.cpp + $(CXX) $(CXXFLAGS) $< +$O/BZip2Decoder.o: ../../Compress/BZip2Decoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/BZip2Encoder.o: ../../Compress/BZip2Encoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/BZip2Register.o: ../../Compress/BZip2Register.cpp + $(CXX) $(CXXFLAGS) $< +$O/CodecExports.o: ../../Compress/CodecExports.cpp + $(CXX) $(CXXFLAGS) $< +$O/CopyCoder.o: ../../Compress/CopyCoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/CopyRegister.o: ../../Compress/CopyRegister.cpp + $(CXX) $(CXXFLAGS) $< +$O/Deflate64Register.o: ../../Compress/Deflate64Register.cpp + $(CXX) $(CXXFLAGS) $< +$O/DeflateDecoder.o: ../../Compress/DeflateDecoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/DeflateEncoder.o: ../../Compress/DeflateEncoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/DeflateRegister.o: ../../Compress/DeflateRegister.cpp + $(CXX) $(CXXFLAGS) $< +$O/DeltaFilter.o: ../../Compress/DeltaFilter.cpp + $(CXX) $(CXXFLAGS) $< +$O/DllExports2Compress.o: ../../Compress/DllExports2Compress.cpp + $(CXX) $(CXXFLAGS) $< +$O/DllExportsCompress.o: ../../Compress/DllExportsCompress.cpp + $(CXX) $(CXXFLAGS) $< +$O/ImplodeDecoder.o: ../../Compress/ImplodeDecoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/ImplodeHuffmanDecoder.o: ../../Compress/ImplodeHuffmanDecoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/LzfseDecoder.o: ../../Compress/LzfseDecoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/LzhDecoder.o: ../../Compress/LzhDecoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/Lzma2Decoder.o: ../../Compress/Lzma2Decoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/Lzma2Encoder.o: ../../Compress/Lzma2Encoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/Lzma2Register.o: ../../Compress/Lzma2Register.cpp + $(CXX) $(CXXFLAGS) $< +$O/LzmaDecoder.o: ../../Compress/LzmaDecoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/LzmaEncoder.o: ../../Compress/LzmaEncoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/LzmaRegister.o: ../../Compress/LzmaRegister.cpp + $(CXX) $(CXXFLAGS) $< +$O/LzmsDecoder.o: ../../Compress/LzmsDecoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/LzOutWindow.o: ../../Compress/LzOutWindow.cpp + $(CXX) $(CXXFLAGS) $< +$O/LzxDecoder.o: ../../Compress/LzxDecoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/PpmdDecoder.o: ../../Compress/PpmdDecoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/PpmdEncoder.o: ../../Compress/PpmdEncoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/PpmdRegister.o: ../../Compress/PpmdRegister.cpp + $(CXX) $(CXXFLAGS) $< +$O/PpmdZip.o: ../../Compress/PpmdZip.cpp + $(CXX) $(CXXFLAGS) $< +$O/QuantumDecoder.o: ../../Compress/QuantumDecoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/Rar1Decoder.o: ../../Compress/Rar1Decoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/Rar2Decoder.o: ../../Compress/Rar2Decoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/Rar3Decoder.o: ../../Compress/Rar3Decoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/Rar3Vm.o: ../../Compress/Rar3Vm.cpp + $(CXX) $(CXXFLAGS) $< +$O/Rar5Decoder.o: ../../Compress/Rar5Decoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/RarCodecsRegister.o: ../../Compress/RarCodecsRegister.cpp + $(CXX) $(CXXFLAGS) $< +$O/ShrinkDecoder.o: ../../Compress/ShrinkDecoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/XpressDecoder.o: ../../Compress/XpressDecoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/XzDecoder.o: ../../Compress/XzDecoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/XzEncoder.o: ../../Compress/XzEncoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/ZDecoder.o: ../../Compress/ZDecoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/ZlibDecoder.o: ../../Compress/ZlibDecoder.cpp + $(CXX) $(CXXFLAGS) $< +$O/ZlibEncoder.o: ../../Compress/ZlibEncoder.cpp + $(CXX) $(CXXFLAGS) $< + + +$O/7zAes.o: ../../Crypto/7zAes.cpp + $(CXX) $(CXXFLAGS) $< +$O/7zAesRegister.o: ../../Crypto/7zAesRegister.cpp + $(CXX) $(CXXFLAGS) $< +$O/HmacSha1.o: ../../Crypto/HmacSha1.cpp + $(CXX) $(CXXFLAGS) $< +$O/HmacSha256.o: ../../Crypto/HmacSha256.cpp + $(CXX) $(CXXFLAGS) $< +$O/MyAes.o: ../../Crypto/MyAes.cpp + $(CXX) $(CXXFLAGS) $< +$O/MyAesReg.o: ../../Crypto/MyAesReg.cpp + $(CXX) $(CXXFLAGS) $< +$O/Pbkdf2HmacSha1.o: ../../Crypto/Pbkdf2HmacSha1.cpp + $(CXX) $(CXXFLAGS) $< +$O/RandGen.o: ../../Crypto/RandGen.cpp + $(CXX) $(CXXFLAGS) $< +$O/Rar20Crypto.o: ../../Crypto/Rar20Crypto.cpp + $(CXX) $(CXXFLAGS) $< +$O/Rar5Aes.o: ../../Crypto/Rar5Aes.cpp + $(CXX) $(CXXFLAGS) $< +$O/RarAes.o: ../../Crypto/RarAes.cpp + $(CXX) $(CXXFLAGS) $< +$O/WzAes.o: ../../Crypto/WzAes.cpp + $(CXX) $(CXXFLAGS) $< +$O/ZipCrypto.o: ../../Crypto/ZipCrypto.cpp + $(CXX) $(CXXFLAGS) $< +$O/ZipStrong.o: ../../Crypto/ZipStrong.cpp + $(CXX) $(CXXFLAGS) $< + + + +$O/CoderMixer2.o: ../../Archive/Common/CoderMixer2.cpp + $(CXX) $(CXXFLAGS) $< +$O/DummyOutStream.o: ../../Archive/Common/DummyOutStream.cpp + $(CXX) $(CXXFLAGS) $< +$O/FindSignature.o: ../../Archive/Common/FindSignature.cpp + $(CXX) $(CXXFLAGS) $< +$O/HandlerOut.o: ../../Archive/Common/HandlerOut.cpp + $(CXX) $(CXXFLAGS) $< +$O/InStreamWithCRC.o: ../../Archive/Common/InStreamWithCRC.cpp + $(CXX) $(CXXFLAGS) $< +$O/ItemNameUtils.o: ../../Archive/Common/ItemNameUtils.cpp + $(CXX) $(CXXFLAGS) $< +$O/MultiStream.o: ../../Archive/Common/MultiStream.cpp + $(CXX) $(CXXFLAGS) $< +$O/OutStreamWithCRC.o: ../../Archive/Common/OutStreamWithCRC.cpp + $(CXX) $(CXXFLAGS) $< +$O/OutStreamWithSha1.o: ../../Archive/Common/OutStreamWithSha1.cpp + $(CXX) $(CXXFLAGS) $< +$O/ParseProperties.o: ../../Archive/Common/ParseProperties.cpp + $(CXX) $(CXXFLAGS) $< + + + + +$O/ArchiveCommandLine.o: ../../UI/Common/ArchiveCommandLine.cpp + $(CXX) $(CXXFLAGS) $< +$O/ArchiveExtractCallback.o: ../../UI/Common/ArchiveExtractCallback.cpp + $(CXX) $(CXXFLAGS) $< +$O/ArchiveName.o: ../../UI/Common/ArchiveName.cpp + $(CXX) $(CXXFLAGS) $< +$O/ArchiveOpenCallback.o: ../../UI/Common/ArchiveOpenCallback.cpp + $(CXX) $(CXXFLAGS) $< +$O/Bench.o: ../../UI/Common/Bench.cpp + $(CXX) $(CXXFLAGS) $< +$O/CompressCall.o: ../../UI/Common/CompressCall.cpp + $(CXX) $(CXXFLAGS) $< +$O/CompressCall2.o: ../../UI/Common/CompressCall2.cpp + $(CXX) $(CXXFLAGS) $< +$O/DefaultName.o: ../../UI/Common/DefaultName.cpp + $(CXX) $(CXXFLAGS) $< +$O/EnumDirItems.o: ../../UI/Common/EnumDirItems.cpp + $(CXX) $(CXXFLAGS) $< +$O/Extract.o: ../../UI/Common/Extract.cpp + $(CXX) $(CXXFLAGS) $< +$O/ExtractingFilePath.o: ../../UI/Common/ExtractingFilePath.cpp + $(CXX) $(CXXFLAGS) $< +$O/HashCalc.o: ../../UI/Common/HashCalc.cpp + $(CXX) $(CXXFLAGS) $< +$O/LoadCodecs.o: ../../UI/Common/LoadCodecs.cpp + $(CXX) $(CXXFLAGS) $< +$O/OpenArchive.o: ../../UI/Common/OpenArchive.cpp + $(CXX) $(CXXFLAGS) $< +$O/PropIDUtils.o: ../../UI/Common/PropIDUtils.cpp + $(CXX) $(CXXFLAGS) $< +$O/SetProperties.o: ../../UI/Common/SetProperties.cpp + $(CXX) $(CXXFLAGS) $< +$O/SortUtils.o: ../../UI/Common/SortUtils.cpp + $(CXX) $(CXXFLAGS) $< +$O/TempFiles.o: ../../UI/Common/TempFiles.cpp + $(CXX) $(CXXFLAGS) $< +$O/Update.o: ../../UI/Common/Update.cpp + $(CXX) $(CXXFLAGS) $< +$O/UpdateAction.o: ../../UI/Common/UpdateAction.cpp + $(CXX) $(CXXFLAGS) $< +$O/UpdateCallback.o: ../../UI/Common/UpdateCallback.cpp + $(CXX) $(CXXFLAGS) $< +$O/UpdatePair.o: ../../UI/Common/UpdatePair.cpp + $(CXX) $(CXXFLAGS) $< +$O/UpdateProduce.o: ../../UI/Common/UpdateProduce.cpp + $(CXX) $(CXXFLAGS) $< +$O/WorkDir.o: ../../UI/Common/WorkDir.cpp + $(CXX) $(CXXFLAGS) $< +$O/ZipRegistry.o: ../../UI/Common/ZipRegistry.cpp + $(CXX) $(CXXFLAGS) $< + + +$O/Agent.o: ../../UI/Agent/Agent.cpp + $(CXX) $(CXXFLAGS) $< +$O/AgentOut.o: ../../UI/Agent/AgentOut.cpp + $(CXX) $(CXXFLAGS) $< +$O/AgentProxy.o: ../../UI/Agent/AgentProxy.cpp + $(CXX) $(CXXFLAGS) $< +$O/ArchiveFolder.o: ../../UI/Agent/ArchiveFolder.cpp + $(CXX) $(CXXFLAGS) $< +$O/ArchiveFolderOpen.o: ../../UI/Agent/ArchiveFolderOpen.cpp + $(CXX) $(CXXFLAGS) $< +$O/ArchiveFolderOut.o: ../../UI/Agent/ArchiveFolderOut.cpp + $(CXX) $(CXXFLAGS) $< +$O/UpdateCallbackAgent.o: ../../UI/Agent/UpdateCallbackAgent.cpp + $(CXX) $(CXXFLAGS) $< + + +$O/Client7z.o: ../../UI/Client7z/Client7z.cpp + $(CXX) $(CXXFLAGS) $< + + +$O/BenchCon.o: ../../UI/Console/BenchCon.cpp + $(CXX) $(CXXFLAGS) $< +$O/ConsoleClose.o: ../../UI/Console/ConsoleClose.cpp + $(CXX) $(CXXFLAGS) $< +$O/ExtractCallbackConsole.o: ../../UI/Console/ExtractCallbackConsole.cpp + $(CXX) $(CXXFLAGS) $< +$O/HashCon.o: ../../UI/Console/HashCon.cpp + $(CXX) $(CXXFLAGS) $< +$O/List.o: ../../UI/Console/List.cpp + $(CXX) $(CXXFLAGS) $< +$O/Main.o: ../../UI/Console/Main.cpp ../../../../C/7zVersion.h + $(CXX) $(CXXFLAGS) $(CONSOLE_VARIANT_FLAGS) $(CONSOLE_ASM_FLAGS) $< +$O/MainAr.o: ../../UI/Console/MainAr.cpp + $(CXX) $(CXXFLAGS) $< +$O/OpenCallbackConsole.o: ../../UI/Console/OpenCallbackConsole.cpp + $(CXX) $(CXXFLAGS) $< +$O/PercentPrinter.o: ../../UI/Console/PercentPrinter.cpp + $(CXX) $(CXXFLAGS) $< +$O/UpdateCallbackConsole.o: ../../UI/Console/UpdateCallbackConsole.cpp + $(CXX) $(CXXFLAGS) $< +$O/UserInputUtils.o: ../../UI/Console/UserInputUtils.cpp + $(CXX) $(CXXFLAGS) $< + +$O/BenchmarkDialog.o: ../../UI/GUI/BenchmarkDialog.cpp + $(CXX) $(CXXFLAGS) $< +$O/CompressDialog.o: ../../UI/GUI/CompressDialog.cpp + $(CXX) $(CXXFLAGS) $< +$O/ExtractDialog.o: ../../UI/GUI/ExtractDialog.cpp + $(CXX) $(CXXFLAGS) $< +$O/ExtractGUI.o: ../../UI/GUI/ExtractGUI.cpp + $(CXX) $(CXXFLAGS) $< +$O/GUI.o: ../../UI/GUI/GUI.cpp + $(CXX) $(CXXFLAGS) $< +$O/HashGUI.o: ../../UI/GUI/HashGUI.cpp + $(CXX) $(CXXFLAGS) $< +$O/UpdateCallbackGUI.o: ../../UI/GUI/UpdateCallbackGUI.cpp + $(CXX) $(CXXFLAGS) $< +$O/UpdateCallbackGUI2.o: ../../UI/GUI/UpdateCallbackGUI2.cpp + $(CXX) $(CXXFLAGS) $< +$O/UpdateGUI.o: ../../UI/GUI/UpdateGUI.cpp + $(CXX) $(CXXFLAGS) $< + +$O/MyMessages.o: ../../UI/Explorer/MyMessages.cpp + $(CXX) $(CXXFLAGS) $< +$O/ContextMenu.o: ../../UI/Explorer/ContextMenu.cpp + $(CXX) $(CXXFLAGS) $< +$O/DllExportsExplorer.o: ../../UI/Explorer/DllExportsExplorer.cpp + $(CXX) $(CXXFLAGS) $< +$O/RegistryContextMenu.o: ../../UI/Explorer/RegistryContextMenu.cpp + $(CXX) $(CXXFLAGS) $< + + + +$O/AboutDialog.o: ../../UI/FileManager/AboutDialog.cpp + $(CXX) $(CXXFLAGS) $< +$O/AltStreamsFolder.o: ../../UI/FileManager/AltStreamsFolder.cpp + $(CXX) $(CXXFLAGS) $< +$O/App.o: ../../UI/FileManager/App.cpp + $(CXX) $(CXXFLAGS) $< +$O/BrowseDialog.o: ../../UI/FileManager/BrowseDialog.cpp + $(CXX) $(CXXFLAGS) $< +$O/ClassDefs.o: ../../UI/FileManager/ClassDefs.cpp + $(CXX) $(CXXFLAGS) $< +$O/ComboDialog.o: ../../UI/FileManager/ComboDialog.cpp + $(CXX) $(CXXFLAGS) $< +$O/CopyDialog.o: ../../UI/FileManager/CopyDialog.cpp + $(CXX) $(CXXFLAGS) $< +$O/EditDialog.o: ../../UI/FileManager/EditDialog.cpp + $(CXX) $(CXXFLAGS) $< +$O/EditPage.o: ../../UI/FileManager/EditPage.cpp + $(CXX) $(CXXFLAGS) $< +$O/EnumFormatEtc.o: ../../UI/FileManager/EnumFormatEtc.cpp + $(CXX) $(CXXFLAGS) $< +$O/ExtractCallback.o: ../../UI/FileManager/ExtractCallback.cpp + $(CXX) $(CXXFLAGS) $< +$O/FileFolderPluginOpen.o: ../../UI/FileManager/FileFolderPluginOpen.cpp + $(CXX) $(CXXFLAGS) $< +$O/FilePlugins.o: ../../UI/FileManager/FilePlugins.cpp + $(CXX) $(CXXFLAGS) $< +$O/FM.o: ../../UI/FileManager/FM.cpp + $(CXX) $(CXXFLAGS) $< +$O/FoldersPage.o: ../../UI/FileManager/FoldersPage.cpp + $(CXX) $(CXXFLAGS) $< +$O/FormatUtils.o: ../../UI/FileManager/FormatUtils.cpp + $(CXX) $(CXXFLAGS) $< +$O/FSDrives.o: ../../UI/FileManager/FSDrives.cpp + $(CXX) $(CXXFLAGS) $< +$O/FSFolder.o: ../../UI/FileManager/FSFolder.cpp + $(CXX) $(CXXFLAGS) $< +$O/FSFolderCopy.o: ../../UI/FileManager/FSFolderCopy.cpp + $(CXX) $(CXXFLAGS) $< +$O/HelpUtils.o: ../../UI/FileManager/HelpUtils.cpp + $(CXX) $(CXXFLAGS) $< +$O/LangPage.o: ../../UI/FileManager/LangPage.cpp + $(CXX) $(CXXFLAGS) $< +$O/LangUtils.o: ../../UI/FileManager/LangUtils.cpp + $(CXX) $(CXXFLAGS) $< +$O/LinkDialog.o: ../../UI/FileManager/LinkDialog.cpp + $(CXX) $(CXXFLAGS) $< +$O/ListViewDialog.o: ../../UI/FileManager/ListViewDialog.cpp + $(CXX) $(CXXFLAGS) $< +$O/MenuPage.o: ../../UI/FileManager/MenuPage.cpp + $(CXX) $(CXXFLAGS) $< +$O/MessagesDialog.o: ../../UI/FileManager/MessagesDialog.cpp + $(CXX) $(CXXFLAGS) $< +$O/MyLoadMenu.o: ../../UI/FileManager/MyLoadMenu.cpp + $(CXX) $(CXXFLAGS) $< +$O/NetFolder.o: ../../UI/FileManager/NetFolder.cpp + $(CXX) $(CXXFLAGS) $< +$O/OpenCallback.o: ../../UI/FileManager/OpenCallback.cpp + $(CXX) $(CXXFLAGS) $< +$O/OptionsDialog.o: ../../UI/FileManager/OptionsDialog.cpp + $(CXX) $(CXXFLAGS) $< +$O/OverwriteDialog.o: ../../UI/FileManager/OverwriteDialog.cpp + $(CXX) $(CXXFLAGS) $< +$O/Panel.o: ../../UI/FileManager/Panel.cpp + $(CXX) $(CXXFLAGS) $< +$O/PanelCopy.o: ../../UI/FileManager/PanelCopy.cpp + $(CXX) $(CXXFLAGS) $< +$O/PanelCrc.o: ../../UI/FileManager/PanelCrc.cpp + $(CXX) $(CXXFLAGS) $< +$O/PanelDrag.o: ../../UI/FileManager/PanelDrag.cpp + $(CXX) $(CXXFLAGS) $< +$O/PanelFolderChange.o: ../../UI/FileManager/PanelFolderChange.cpp + $(CXX) $(CXXFLAGS) $< +$O/PanelItemOpen.o: ../../UI/FileManager/PanelItemOpen.cpp + $(CXX) $(CXXFLAGS) $< +$O/PanelItems.o: ../../UI/FileManager/PanelItems.cpp + $(CXX) $(CXXFLAGS) $< +$O/PanelKey.o: ../../UI/FileManager/PanelKey.cpp + $(CXX) $(CXXFLAGS) $< +$O/PanelListNotify.o: ../../UI/FileManager/PanelListNotify.cpp + $(CXX) $(CXXFLAGS) $< +$O/PanelMenu.o: ../../UI/FileManager/PanelMenu.cpp + $(CXX) $(CXXFLAGS) $< +$O/PanelOperations.o: ../../UI/FileManager/PanelOperations.cpp + $(CXX) $(CXXFLAGS) $< +$O/PanelSelect.o: ../../UI/FileManager/PanelSelect.cpp + $(CXX) $(CXXFLAGS) $< +$O/PanelSort.o: ../../UI/FileManager/PanelSort.cpp + $(CXX) $(CXXFLAGS) $< +$O/PanelSplitFile.o: ../../UI/FileManager/PanelSplitFile.cpp + $(CXX) $(CXXFLAGS) $< +$O/PasswordDialog.o: ../../UI/FileManager/PasswordDialog.cpp + $(CXX) $(CXXFLAGS) $< +$O/ProgramLocation.o: ../../UI/FileManager/ProgramLocation.cpp + $(CXX) $(CXXFLAGS) $< +$O/ProgressDialog.o: ../../UI/FileManager/ProgressDialog.cpp + $(CXX) $(CXXFLAGS) $< +$O/ProgressDialog2.o: ../../UI/FileManager/ProgressDialog2.cpp + $(CXX) $(CXXFLAGS) $< +$O/PropertyName.o: ../../UI/FileManager/PropertyName.cpp + $(CXX) $(CXXFLAGS) $< +$O/RegistryAssociations.o: ../../UI/FileManager/RegistryAssociations.cpp + $(CXX) $(CXXFLAGS) $< +$O/RegistryPlugins.o: ../../UI/FileManager/RegistryPlugins.cpp + $(CXX) $(CXXFLAGS) $< +$O/RegistryUtils.o: ../../UI/FileManager/RegistryUtils.cpp + $(CXX) $(CXXFLAGS) $< +$O/RootFolder.o: ../../UI/FileManager/RootFolder.cpp + $(CXX) $(CXXFLAGS) $< +$O/SettingsPage.o: ../../UI/FileManager/SettingsPage.cpp + $(CXX) $(CXXFLAGS) $< +$O/SplitDialog.o: ../../UI/FileManager/SplitDialog.cpp + $(CXX) $(CXXFLAGS) $< +$O/SplitUtils.o: ../../UI/FileManager/SplitUtils.cpp + $(CXX) $(CXXFLAGS) $< +$O/StringUtils.o: ../../UI/FileManager/StringUtils.cpp + $(CXX) $(CXXFLAGS) $< +$O/SysIconUtils.o: ../../UI/FileManager/SysIconUtils.cpp + $(CXX) $(CXXFLAGS) $< +$O/SystemPage.o: ../../UI/FileManager/SystemPage.cpp + $(CXX) $(CXXFLAGS) $< +$O/TextPairs.o: ../../UI/FileManager/TextPairs.cpp + $(CXX) $(CXXFLAGS) $< +$O/UpdateCallback100.o: ../../UI/FileManager/UpdateCallback100.cpp + $(CXX) $(CXXFLAGS) $< +$O/ViewSettings.o: ../../UI/FileManager/ViewSettings.cpp + $(CXX) $(CXXFLAGS) $< + +$O/SfxCon.o: ../../Bundles/SFXCon/SfxCon.cpp + $(CXX) $(CXXFLAGS) $< + +$O/$(FILE_IO).o: ../../../$(FILE_IO_2).cpp + $(CXX) $(CXXFLAGS) $< + + + + + + +$O/7zAlloc.o: ../../../../C/7zAlloc.c + $(CC) $(CFLAGS) $< +$O/7zArcIn.o: ../../../../C/7zArcIn.c + $(CC) $(CFLAGS) $< +$O/7zBuf.o: ../../../../C/7zBuf.c + $(CC) $(CFLAGS) $< +$O/7zBuf2.o: ../../../../C/7zBuf2.c + $(CC) $(CFLAGS) $< +$O/7zCrc.o: ../../../../C/7zCrc.c + $(CC) $(CFLAGS) $< +$O/7zDec.o: ../../../../C/7zDec.c + $(CC) $(CFLAGS) $< +$O/7zFile.o: ../../../../C/7zFile.c + $(CC) $(CFLAGS) $< +$O/7zStream.o: ../../../../C/7zStream.c + $(CC) $(CFLAGS) $< +$O/Aes.o: ../../../../C/Aes.c + $(CC) $(CFLAGS) $< +$O/Alloc.o: ../../../../C/Alloc.c + $(CC) $(CFLAGS) $< +$O/Bcj2.o: ../../../../C/Bcj2.c + $(CC) $(CFLAGS) $< +$O/Bcj2Enc.o: ../../../../C/Bcj2Enc.c + $(CC) $(CFLAGS) $< +$O/Blake2s.o: ../../../../C/Blake2s.c + $(CC) $(CFLAGS) $< +$O/Bra.o: ../../../../C/Bra.c + $(CC) $(CFLAGS) $< +$O/Bra86.o: ../../../../C/Bra86.c + $(CC) $(CFLAGS) $< +$O/BraIA64.o: ../../../../C/BraIA64.c + $(CC) $(CFLAGS) $< +$O/BwtSort.o: ../../../../C/BwtSort.c + $(CC) $(CFLAGS) $< + +$O/CpuArch.o: ../../../../C/CpuArch.c + $(CC) $(CFLAGS) $< +$O/Delta.o: ../../../../C/Delta.c + $(CC) $(CFLAGS) $< +$O/DllSecur.o: ../../../../C/DllSecur.c + $(CC) $(CFLAGS) $< +$O/HuffEnc.o: ../../../../C/HuffEnc.c + $(CC) $(CFLAGS) $< +$O/LzFind.o: ../../../../C/LzFind.c + $(CC) $(CFLAGS) $< + +# ifdef MT_FILES +$O/LzFindMt.o: ../../../../C/LzFindMt.c + $(CC) $(CFLAGS) $< + +$O/Threads.o: ../../../../C/Threads.c + $(CC) $(CFLAGS) $< +# endif + +$O/LzmaEnc.o: ../../../../C/LzmaEnc.c + $(CC) $(CFLAGS) $< +$O/Lzma86Dec.o: ../../../../C/Lzma86Dec.c + $(CC) $(CFLAGS) $< +$O/Lzma86Enc.o: ../../../../C/Lzma86Enc.c + $(CC) $(CFLAGS) $< +$O/Lzma2Dec.o: ../../../../C/Lzma2Dec.c + $(CC) $(CFLAGS) $< +$O/Lzma2DecMt.o: ../../../../C/Lzma2DecMt.c + $(CC) $(CFLAGS) $< +$O/Lzma2Enc.o: ../../../../C/Lzma2Enc.c + $(CC) $(CFLAGS) $< +$O/LzmaLib.o: ../../../../C/LzmaLib.c + $(CC) $(CFLAGS) $< +$O/MtCoder.o: ../../../../C/MtCoder.c + $(CC) $(CFLAGS) $< +$O/MtDec.o: ../../../../C/MtDec.c + $(CC) $(CFLAGS) $< +$O/Ppmd7.o: ../../../../C/Ppmd7.c + $(CC) $(CFLAGS) $< +$O/Ppmd7aDec.o: ../../../../C/Ppmd7aDec.c + $(CC) $(CFLAGS) $< +$O/Ppmd7Dec.o: ../../../../C/Ppmd7Dec.c + $(CC) $(CFLAGS) $< +$O/Ppmd7Enc.o: ../../../../C/Ppmd7Enc.c + $(CC) $(CFLAGS) $< +$O/Ppmd8.o: ../../../../C/Ppmd8.c + $(CC) $(CFLAGS) $< +$O/Ppmd8Dec.o: ../../../../C/Ppmd8Dec.c + $(CC) $(CFLAGS) $< +$O/Ppmd8Enc.o: ../../../../C/Ppmd8Enc.c + $(CC) $(CFLAGS) $< +$O/Sha1.o: ../../../../C/Sha1.c + $(CC) $(CFLAGS) $< +$O/Sha256.o: ../../../../C/Sha256.c + $(CC) $(CFLAGS) $< +$O/Sort.o: ../../../../C/Sort.c + $(CC) $(CFLAGS) $< +$O/Xz.o: ../../../../C/Xz.c + $(CC) $(CFLAGS) $< +$O/XzCrc64.o: ../../../../C/XzCrc64.c + $(CC) $(CFLAGS) $< + +ifdef USE_ASM +ifdef IS_X64 +USE_X86_ASM=1 +else +ifdef IS_X86 +USE_X86_ASM=1 +endif +endif +endif + +ifdef USE_X86_ASM +$O/7zCrcOpt.o: ../../../../Asm/x86/7zCrcOpt.asm + $(MY_ASM) $(AFLAGS) $< +$O/XzCrc64Opt.o: ../../../../Asm/x86/XzCrc64Opt.asm + $(MY_ASM) $(AFLAGS) $< +$O/AesOpt.o: ../../../../Asm/x86/AesOpt.asm + $(MY_ASM) $(AFLAGS) $< +$O/Sha1Opt.o: ../../../../Asm/x86/Sha1Opt.asm + $(MY_ASM) $(AFLAGS) $< +$O/Sha256Opt.o: ../../../../Asm/x86/Sha256Opt.asm + $(MY_ASM) $(AFLAGS) $< +else +$O/7zCrcOpt.o: ../../../../C/7zCrcOpt.c + $(CC) $(CFLAGS) $< +$O/XzCrc64Opt.o: ../../../../C/XzCrc64Opt.c + $(CC) $(CFLAGS) $< +$O/Sha1Opt.o: ../../../../C/Sha1Opt.c + $(CC) $(CFLAGS) $< +$O/Sha256Opt.o: ../../../../C/Sha256Opt.c + $(CC) $(CFLAGS) $< +$O/AesOpt.o: ../../../../C/AesOpt.c + $(CC) $(CFLAGS) $< +endif + + +ifdef USE_LZMA_DEC_ASM + +ifdef IS_X64 +$O/LzmaDecOpt.o: ../../../../Asm/x86/LzmaDecOpt.asm + $(MY_ASM) $(AFLAGS) $< +endif + +ifdef IS_ARM64 +$O/LzmaDecOpt.o: ../../../../Asm/arm64/LzmaDecOpt.S ../../../../Asm/arm64/7zAsm.S + $(CC) $(CFLAGS) $< +endif + +$O/LzmaDec.o: ../../../../C/LzmaDec.c + $(CC) $(CFLAGS) -D_LZMA_DEC_OPT $< + +else + +$O/LzmaDec.o: ../../../../C/LzmaDec.c + $(CC) $(CFLAGS) $< + +endif + + + +$O/XzDec.o: ../../../../C/XzDec.c + $(CC) $(CFLAGS) $< +$O/XzEnc.o: ../../../../C/XzEnc.c + $(CC) $(CFLAGS) $< +$O/XzIn.o: ../../../../C/XzIn.c + $(CC) $(CFLAGS) $< + + +$O/7zMain.o: ../../../../C/Util/7z/7zMain.c + $(CC) $(CFLAGS) $< +$O/LzmaUtil.o: ../../../../C/Util/Lzma/LzmaUtil.c + $(CC) $(CFLAGS) $< + +ifneq ($(CC), xlc) +SHOW_PREDEF=-dM +else +SHOW_PREDEF= -qshowmacros=pre +endif + +predef_cc: + $(CC) $(CFLAGS) -E $(SHOW_PREDEF) ../../../../C/CpuArch.c > predef_cc_log +# $(CC) $(CFLAGS) -E -dM - < /dev/null +predef_cxx: + $(CXX) $(CFLAGS) -E $(SHOW_PREDEF) ../../../Common/CrcReg.cpp > predef_cxx_log + +predef: predef_cc predef_cxx + + +clean: + -$(DEL_OBJ_EXE) diff --git a/CPP/7zip/Aes.mak b/CPP/7zip/Aes.mak index 20f1a72f..7d8da2d8 100644 --- a/CPP/7zip/Aes.mak +++ b/CPP/7zip/Aes.mak @@ -1,7 +1,10 @@ C_OBJS = $(C_OBJS) \ $O\Aes.obj -!IF "$(PLATFORM)" != "ia64" && "$(PLATFORM)" != "mips" && "$(PLATFORM)" != "arm" && "$(PLATFORM)" != "arm64" +!IF defined(USE_C_AES) || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "arm64" +C_OBJS = $(C_OBJS) \ + $O\AesOpt.obj +!ELSEIF "$(PLATFORM)" != "ia64" && "$(PLATFORM)" != "mips" && "$(PLATFORM)" != "arm" && "$(PLATFORM)" != "arm64" ASM_OBJS = $(ASM_OBJS) \ $O\AesOpt.obj !ENDIF diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h index 608293d6..44c90226 100644 --- a/CPP/7zip/Archive/7z/7zCompressionMode.h +++ b/CPP/7zip/Archive/7z/7zCompressionMode.h @@ -57,18 +57,20 @@ struct CCompressionMethodMode #endif bool PasswordIsDefined; - UString Password; + UString Password; // _Wipe bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); } CCompressionMethodMode(): - DefaultMethod_was_Inserted(false), - Filter_was_Inserted(false), - PasswordIsDefined(false) + DefaultMethod_was_Inserted(false) + , Filter_was_Inserted(false) #ifndef _7ZIP_ST , NumThreads(1) , MultiThreadMixer(true) #endif + , PasswordIsDefined(false) {} + + ~CCompressionMethodMode() { Password.Wipe_and_Empty(); } }; }} diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp index 9df531e0..c27c8fbc 100644 --- a/CPP/7zip/Archive/7z/7zDecode.cpp +++ b/CPP/7zip/Archive/7z/7zDecode.cpp @@ -158,7 +158,7 @@ STDMETHODIMP CLockedSequentialInStreamMT::Read(void *data, UInt32 size, UInt32 * if (_pos != _glob->Pos) { - RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL)); + RINOK(_glob->Stream->Seek((Int64)_pos, STREAM_SEEK_SET, NULL)); _glob->Pos = _pos; } @@ -200,7 +200,7 @@ STDMETHODIMP CLockedSequentialInStreamST::Read(void *data, UInt32 size, UInt32 * { if (_pos != _glob->Pos) { - RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL)); + RINOK(_glob->Stream->Seek((Int64)_pos, STREAM_SEEK_SET, NULL)); _glob->Pos = _pos; } @@ -276,6 +276,7 @@ HRESULT CDecoder::Decode( if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev)) { + _bindInfoPrev_Defined = false; _mixerRef.Release(); #ifdef USE_MIXER_MT @@ -348,7 +349,7 @@ HRESULT CDecoder::Decode( _bindInfoPrev_Defined = true; } - _mixer->ReInit(); + RINOK(_mixer->ReInit2()); UInt32 packStreamIndex = 0; UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex]; @@ -396,10 +397,10 @@ HRESULT CDecoder::Decode( if (setDecoderProperties) { const CByteBuffer &props = coderInfo.Props; - size_t size = props.Size(); - if (size > 0xFFFFFFFF) + const UInt32 size32 = (UInt32)props.Size(); + if (props.Size() != size32) return E_NOTIMPL; - HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size); + HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, size32); if (res == E_INVALIDARG) res = E_NOTIMPL; RINOK(res); @@ -415,17 +416,17 @@ HRESULT CDecoder::Decode( isEncrypted = true; if (!getTextPassword) return E_NOTIMPL; - CMyComBSTR passwordBSTR; + CMyComBSTR_Wipe passwordBSTR; RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR)); passwordIsDefined = true; - password.Empty(); + password.Wipe_and_Empty(); size_t len = 0; if (passwordBSTR) { password = passwordBSTR; len = password.Len(); } - CByteBuffer buffer(len * 2); + CByteBuffer_Wipe buffer(len * 2); for (size_t k = 0; k < len; k++) { wchar_t c = passwordBSTR[k]; @@ -444,7 +445,7 @@ HRESULT CDecoder::Decode( if (setFinishMode) { finishMode = fullUnpack; - RINOK(setFinishMode->SetFinishMode(BoolToInt(finishMode))); + RINOK(setFinishMode->SetFinishMode(BoolToUInt(finishMode))); } } @@ -487,36 +488,49 @@ HRESULT CDecoder::Decode( CLockedInStream *lockedInStreamSpec = new CLockedInStream; CMyComPtr<IUnknown> lockedInStream = lockedInStreamSpec; - bool needMtLock = false; + #ifdef USE_MIXER_MT + #ifdef USE_MIXER_ST + bool needMtLock = _useMixerMT; + #endif + #endif if (folderInfo.PackStreams.Size() > 1) { // lockedInStream.Pos = (UInt64)(Int64)-1; // RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &lockedInStream.Pos)); - RINOK(inStream->Seek(startPos + packPositions[0], STREAM_SEEK_SET, &lockedInStreamSpec->Pos)); + RINOK(inStream->Seek((Int64)(startPos + packPositions[0]), STREAM_SEEK_SET, &lockedInStreamSpec->Pos)); lockedInStreamSpec->Stream = inStream; + #ifdef USE_MIXER_MT #ifdef USE_MIXER_ST - if (_mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex)) - #endif + /* + For ST-mixer mode: + If parallel input stream reading from pack streams is possible, + we must use MT-lock for packed streams. + Internal decoders in 7-Zip will not read pack streams in parallel in ST-mixer mode. + So we force to needMtLock mode only if there is unknown (external) decoder. + */ + if (!needMtLock && _mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex)) needMtLock = true; + #endif + #endif } for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++) { CMyComPtr<ISequentialInStream> packStream; - UInt64 packPos = startPos + packPositions[j]; + const UInt64 packPos = startPos + packPositions[j]; if (folderInfo.PackStreams.Size() == 1) { - RINOK(inStream->Seek(packPos, STREAM_SEEK_SET, NULL)); + RINOK(inStream->Seek((Int64)packPos, STREAM_SEEK_SET, NULL)); packStream = inStream; } else { #ifdef USE_MIXER_MT #ifdef USE_MIXER_ST - if (_useMixerMT || needMtLock) + if (needMtLock) #endif { CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT; @@ -542,7 +556,7 @@ HRESULT CDecoder::Decode( streamSpec->Init(packPositions[j + 1] - packPositions[j]); } - unsigned num = inStreams.Size(); + const unsigned num = inStreams.Size(); CObjArray<ISequentialInStream *> inStreamPointers(num); for (i = 0; i < num; i++) inStreamPointers[i] = inStreams[i]; diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp index 7d8270f9..49963241 100644 --- a/CPP/7zip/Archive/7z/7zEncode.cpp +++ b/CPP/7zip/Archive/7z/7zEncode.cpp @@ -158,7 +158,7 @@ HRESULT CEncoder::CreateMixerCoder( { RINOK(CreateCoder_Index( EXTERNAL_CODECS_LOC_VARS - methodFull.CodecIndex, true, cod)); + (unsigned)methodFull.CodecIndex, true, cod)); } else { @@ -215,7 +215,7 @@ HRESULT CEncoder::CreateMixerCoder( if (cryptoSetPassword) { const unsigned sizeInBytes = _options.Password.Len() * 2; - CByteBuffer buffer(sizeInBytes); + CByteBuffer_Wipe buffer(sizeInBytes); for (unsigned i = 0; i < _options.Password.Len(); i++) { wchar_t c = _options.Password[i]; @@ -249,11 +249,12 @@ public: STDMETHODIMP CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed) { - if (!_buf->Write(data, size)) + HRESULT res = _buf->Write_HRESULT(data, size); + if (res != S_OK) { if (processed) *processed = 0; - return E_FAIL; + return res; } if (processed) *processed = size; @@ -309,7 +310,7 @@ HRESULT CEncoder::Encode( RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)); } - _mixer->ReInit(); + RINOK(_mixer->ReInit2()); CMtEncMultiProgress *mtProgressSpec = NULL; CMyComPtr<ICompressProgressInfo> mtProgress; @@ -478,7 +479,7 @@ HRESULT CEncoder::Encode( unpackSize = streamSize; } else - streamSize = _mixer->GetBondStreamSize(bond); + streamSize = _mixer->GetBondStreamSize((unsigned)bond); coderUnpackSizes.Add(streamSize); } @@ -609,13 +610,13 @@ HRESULT CEncoder::EncoderConstr() int bond = _bindInfo.FindBond_for_PackStream(outIndex); if (bond >= 0) { - ci = _bindInfo.Bonds[bond].UnpackIndex; + ci = _bindInfo.Bonds[(unsigned)bond].UnpackIndex; continue; } int si = _bindInfo.FindStream_in_PackStreams(outIndex); if (si >= 0) - _bindInfo.PackStreams.MoveToFront(si); + _bindInfo.PackStreams.MoveToFront((unsigned)si); break; } } diff --git a/CPP/7zip/Archive/7z/7zEncode.h b/CPP/7zip/Archive/7z/7zEncode.h index f1a9b5ad..6ea7f276 100644 --- a/CPP/7zip/Archive/7z/7zEncode.h +++ b/CPP/7zip/Archive/7z/7zEncode.h @@ -41,7 +41,7 @@ public: STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; -class CEncoder +class CEncoder MY_UNCOPYABLE { #ifdef USE_MIXER_ST NCoderMixer2::CMixerST *_mixerST; diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp index 9ffe2fdc..95eba9af 100644 --- a/CPP/7zip/Archive/7z/7zExtract.cpp +++ b/CPP/7zip/Archive/7z/7zExtract.cpp @@ -217,6 +217,10 @@ HRESULT CFolderOutStream::FlushCorrupted(Int32 callbackOperationResult) STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec) { + // for GCC + // CFolderOutStream *folderOutStream = new CFolderOutStream; + // CMyComPtr<ISequentialOutStream> outStream(folderOutStream); + COM_TRY_BEGIN CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; @@ -350,7 +354,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, #ifndef _NO_CRYPTO bool isEncrypted = false; bool passwordIsDefined = false; - UString password; + UString_Wipe password; #endif @@ -411,7 +415,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)); // continue; - return E_FAIL; + // return E_FAIL; + throw; } } diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp index bbb892e7..9e344c34 100644 --- a/CPP/7zip/Archive/7z/7zHandler.cpp +++ b/CPP/7zip/Archive/7z/7zHandler.cpp @@ -107,34 +107,62 @@ static void ConvertMethodIdToString(AString &res, UInt64 id) res += s + len - ConvertMethodIdToString_Back(s + len, id); } -static unsigned GetStringForSizeValue(char *s, UInt32 val) + +static char *GetStringForSizeValue(char *s, UInt32 val) { unsigned i; for (i = 0; i <= 31; i++) if (((UInt32)1 << i) == val) { - if (i < 10) + if (i >= 10) { - s[0] = (char)('0' + i); - s[1] = 0; - return 1; + *s++= (char)('0' + i / 10); + i %= 10; } - if (i < 20) { s[0] = '1'; s[1] = (char)('0' + i - 10); } - else if (i < 30) { s[0] = '2'; s[1] = (char)('0' + i - 20); } - else { s[0] = '3'; s[1] = (char)('0' + i - 30); } - s[2] = 0; - return 2; + *s++ = (char)('0' + i); + *s = 0; + return s; } + char c = 'b'; if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; } else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; } - ::ConvertUInt32ToString(val, s); - unsigned pos = MyStringLen(s); - s[pos++] = c; - s[pos] = 0; - return pos; + s = ConvertUInt32ToString(val, s); + *s++ = c; + *s = 0; + return s; } + +static void GetLzma2String(char *s, unsigned d) +{ + if (d > 40) + { + *s = 0; + return; + // s = MyStpCpy(s, "unsup"); + } + else if ((d & 1) == 0) + d = (d >> 1) + 12; + else + { + // s = GetStringForSizeValue(s, (UInt32)3 << ((d >> 1) + 11)); + d = (d >> 1) + 1; + char c = 'k'; + if (d >= 10) + { + c = 'm'; + d -= 10; + } + s = ConvertUInt32ToString((UInt32)3 << d, s); + *s++ = c; + *s = 0; + return; + } + ConvertUInt32ToString(d, s); +} + + /* static inline void AddHexToString(UString &res, Byte value) { @@ -147,8 +175,7 @@ static char *AddProp32(char *s, const char *name, UInt32 v) { *s++ = ':'; s = MyStpCpy(s, name); - ::ConvertUInt32ToString(v, s); - return s + MyStringLen(s); + return ConvertUInt32ToString(v, s); } void CHandler::AddMethodName(AString &s, UInt64 id) @@ -184,10 +211,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) if (id == k_LZMA2) { s += "LZMA2:"; - if ((pm.Lzma2Prop & 1) == 0) - ConvertUInt32ToString((pm.Lzma2Prop >> 1) + 12, temp); - else - GetStringForSizeValue(temp, 3 << ((pm.Lzma2Prop >> 1) + 11)); + GetLzma2String(temp, pm.Lzma2Prop); s += temp; } else if (id == k_LZMA) @@ -244,14 +268,13 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) break; } } - prop.Detach(value); - return S_OK; + return prop.Detach(value); #ifndef _SFX COM_TRY_END #endif } -static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, int index) +static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, unsigned index) { UInt64 value; if (v.GetItem(index, value)) @@ -416,7 +439,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const if (propsSize == 5) { UInt32 dicSize = GetUi32((const Byte *)props + 1); - char *dest = s + GetStringForSizeValue(s, dicSize); + char *dest = GetStringForSizeValue(s, dicSize); UInt32 d = props[0]; if (d != 0x5D) { @@ -434,24 +457,16 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const { name = "LZMA2"; if (propsSize == 1) - { - Byte d = props[0]; - if ((d & 1) == 0) - ConvertUInt32ToString((UInt32)((d >> 1) + 12), s); - else - GetStringForSizeValue(s, 3 << ((d >> 1) + 11)); - } + GetLzma2String(s, props[0]); } else if (id == k_PPMD) { name = "PPMD"; if (propsSize == 5) { - Byte order = *props; char *dest = s; *dest++ = 'o'; - ConvertUInt32ToString(order, dest); - dest += MyStringLen(dest); + dest = ConvertUInt32ToString(*props, dest); dest = MyStpCpy(dest, ":mem"); GetStringForSizeValue(dest, GetUi32(props + 1)); } @@ -534,7 +549,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { - PropVariant_Clear(value); + RINOK(PropVariant_Clear(value)); // COM_TRY_BEGIN // NCOM::CPropVariant prop; @@ -637,7 +652,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val #endif } - // prop.Detach(value); + // return prop.Detach(value); return S_OK; // COM_TRY_END } @@ -708,7 +723,7 @@ STDMETHODIMP CHandler::Close() #ifndef _NO_CRYPTO _isEncrypted = false; _passwordIsDefined = false; - _password.Empty(); + _password.Wipe_and_Empty(); #endif return S_OK; COM_TRY_END diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h index 99942eb0..cad1ae61 100644 --- a/CPP/7zip/Archive/7z/7zHandler.h +++ b/CPP/7zip/Archive/7z/7zHandler.h @@ -129,6 +129,10 @@ public: DECL_ISetCompressCodecsInfo CHandler(); + ~CHandler() + { + Close(); + } private: CMyComPtr<IInStream> _inStream; @@ -137,7 +141,7 @@ private: #ifndef _NO_CRYPTO bool _isEncrypted; bool _passwordIsDefined; - UString _password; + UString _password; // _Wipe #endif #ifdef EXTRACT_ONLY diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp index b6be06a8..b549d94a 100644 --- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp +++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp @@ -111,7 +111,7 @@ HRESULT CHandler::SetMainMethod( } const UInt64 kSolidBytes_Min = (1 << 24); - const UInt64 kSolidBytes_Max = ((UInt64)1 << 32) - 1; + const UInt64 kSolidBytes_Max = ((UInt64)1 << 32); bool needSolid = false; @@ -140,26 +140,52 @@ HRESULT CHandler::SetMainMethod( case k_LZMA2: dicSize = oneMethodInfo.Get_Lzma_DicSize(); break; case k_PPMD: dicSize = oneMethodInfo.Get_Ppmd_MemSize(); break; case k_Deflate: dicSize = (UInt32)1 << 15; break; + case k_Deflate64: dicSize = (UInt32)1 << 16; break; case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break; default: continue; } - - _numSolidBytes = (UInt64)dicSize << 7; - if (_numSolidBytes < kSolidBytes_Min) _numSolidBytes = kSolidBytes_Min; - if (_numSolidBytes > kSolidBytes_Max) _numSolidBytes = kSolidBytes_Max; + + if (methodFull.Id == k_LZMA2) + { + // he we calculate default chunk Size for LZMA2 as defined in LZMA2 encoder code + UInt64 cs = (UInt64)dicSize << 2; + const UInt32 kMinSize = (UInt32)1 << 20; + const UInt32 kMaxSize = (UInt32)1 << 28; + if (cs < kMinSize) cs = kMinSize; + if (cs > kMaxSize) cs = kMaxSize; + if (cs < dicSize) cs = dicSize; + cs += (kMinSize - 1); + cs &= ~(UInt64)(kMinSize - 1); + // we want to use at least 64 chunks (threads) per one solid block. + _numSolidBytes = cs << 6; + const UInt64 kSolidBytes_Lzma2_Max = ((UInt64)1 << 34); + if (_numSolidBytes > kSolidBytes_Lzma2_Max) + _numSolidBytes = kSolidBytes_Lzma2_Max; + } + else + { + _numSolidBytes = (UInt64)dicSize << 7; + if (_numSolidBytes > kSolidBytes_Max) + _numSolidBytes = kSolidBytes_Max; + } + + if (_numSolidBytes < kSolidBytes_Min) + _numSolidBytes = kSolidBytes_Min; _numSolidBytesDefined = true; } if (!_numSolidBytesDefined) + { if (needSolid) _numSolidBytes = kSolidBytes_Max; else _numSolidBytes = 0; + } _numSolidBytesDefined = true; return S_OK; } -static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, PROPID propID, UInt64 &ft, bool &ftDefined) +static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, unsigned index, PROPID propID, UInt64 &ft, bool &ftDefined) { // ft = 0; // ftDefined = false; @@ -289,8 +315,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt bool need_CTime = (Write_CTime.Def && Write_CTime.Val); bool need_ATime = (Write_ATime.Def && Write_ATime.Val); - bool need_MTime = (Write_MTime.Def && Write_MTime.Val || !Write_MTime.Def); - bool need_Attrib = (Write_Attrib.Def && Write_Attrib.Val || !Write_Attrib.Def); + bool need_MTime = (Write_MTime.Def ? Write_MTime.Val : true); + bool need_Attrib = (Write_Attrib.Def ? Write_Attrib.Val : true); if (db && !db->Files.IsEmpty()) { @@ -313,7 +339,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt CUpdateItem ui; ui.NewProps = IntToBool(newProps); ui.NewData = IntToBool(newData); - ui.IndexInArchive = indexInArchive; + ui.IndexInArchive = (int)indexInArchive; ui.IndexInClient = i; ui.IsAnti = false; ui.Size = 0; @@ -322,23 +348,23 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt // bool isAltStream = false; if (ui.IndexInArchive != -1) { - if (db == 0 || (unsigned)ui.IndexInArchive >= db->Files.Size()) + if (!db || (unsigned)ui.IndexInArchive >= db->Files.Size()) return E_INVALIDARG; - const CFileItem &fi = db->Files[ui.IndexInArchive]; + const CFileItem &fi = db->Files[(unsigned)ui.IndexInArchive]; if (!ui.NewProps) { - _db.GetPath(ui.IndexInArchive, name); + _db.GetPath((unsigned)ui.IndexInArchive, name); } ui.IsDir = fi.IsDir; ui.Size = fi.Size; // isAltStream = fi.IsAltStream; - ui.IsAnti = db->IsItemAnti(ui.IndexInArchive); + ui.IsAnti = db->IsItemAnti((unsigned)ui.IndexInArchive); if (!ui.NewProps) { - ui.CTimeDefined = db->CTime.GetItem(ui.IndexInArchive, ui.CTime); - ui.ATimeDefined = db->ATime.GetItem(ui.IndexInArchive, ui.ATime); - ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime); + ui.CTimeDefined = db->CTime.GetItem((unsigned)ui.IndexInArchive, ui.CTime); + ui.ATimeDefined = db->ATime.GetItem((unsigned)ui.IndexInArchive, ui.ATime); + ui.MTimeDefined = db->MTime.GetItem((unsigned)ui.IndexInArchive, ui.MTime); } } @@ -570,10 +596,10 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt updateCallback->QueryInterface(IID_ICryptoGetTextPassword2, (void **)&getPassword2); methodMode.PasswordIsDefined = false; - methodMode.Password.Empty(); + methodMode.Password.Wipe_and_Empty(); if (getPassword2) { - CMyComBSTR password; + CMyComBSTR_Wipe password; Int32 passwordIsDefined; RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password)); methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); @@ -751,7 +777,7 @@ HRESULT COutHandler::SetSolidFromString(const UString &s) _solidExtension = true; continue; } - i += (int)(end - start); + i += (unsigned)(end - start); if (i == s2.Len()) return E_INVALIDARG; wchar_t c = s2[i++]; @@ -829,7 +855,7 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val } UInt32 number; - int index = ParseStringToUInt32(name, number); + unsigned index = ParseStringToUInt32(name, number); // UString realName = name.Ptr(index); if (index == 0) { diff --git a/CPP/7zip/Archive/7z/7zHeader.h b/CPP/7zip/Archive/7z/7zHeader.h index d7f0ae36..e1bbc0aa 100644 --- a/CPP/7zip/Archive/7z/7zHeader.h +++ b/CPP/7zip/Archive/7z/7zHeader.h @@ -108,8 +108,9 @@ const UInt32 k_SWAP4 = 0x20304; const UInt32 k_LZMA = 0x30101; const UInt32 k_PPMD = 0x30401; -const UInt32 k_Deflate = 0x40108; -const UInt32 k_BZip2 = 0x40202; +const UInt32 k_Deflate = 0x40108; +const UInt32 k_Deflate64 = 0x40109; +const UInt32 k_BZip2 = 0x40202; const UInt32 k_BCJ = 0x3030103; const UInt32 k_BCJ2 = 0x303011B; diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp index ab5b5de4..7134595c 100644 --- a/CPP/7zip/Archive/7z/7zIn.cpp +++ b/CPP/7zip/Archive/7z/7zIn.cpp @@ -11,6 +11,8 @@ #include "../../../../C/7zCrc.h" #include "../../../../C/CpuArch.h" +// #include "../../../Common/UTFConvert.h" + #include "../../Common/StreamObjects.h" #include "../../Common/StreamUtils.h" @@ -32,6 +34,7 @@ using namespace NCOM; namespace NArchive { namespace N7z { +unsigned BoolVector_CountSum(const CBoolVector &v); unsigned BoolVector_CountSum(const CBoolVector &v) { unsigned sum = 0; @@ -59,9 +62,13 @@ static void BoolVector_Fill_False(CBoolVector &v, unsigned size) class CInArchiveException {}; class CUnsupportedFeatureException: public CInArchiveException {}; +MY_ATTR_NORETURN static void ThrowException() { throw CInArchiveException(); } +MY_ATTR_NORETURN static inline void ThrowEndOfData() { ThrowException(); } +MY_ATTR_NORETURN static inline void ThrowUnsupported() { throw CUnsupportedFeatureException(); } +MY_ATTR_NORETURN static inline void ThrowIncorrect() { ThrowException(); } class CStreamSwitch @@ -328,7 +335,7 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search { memcpy(_header, p, kHeaderSize); _arhiveBeginStreamPosition += offset + pos; - return stream->Seek(_arhiveBeginStreamPosition + kHeaderSize, STREAM_SEEK_SET, NULL); + return stream->Seek((Int64)(_arhiveBeginStreamPosition + kHeaderSize), STREAM_SEEK_SET, NULL); } } @@ -344,7 +351,7 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) Close(); RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition)) RINOK(stream->Seek(0, STREAM_SEEK_END, &_fileEndPosition)) - RINOK(stream->Seek(_arhiveBeginStreamPosition, STREAM_SEEK_SET, NULL)) + RINOK(stream->Seek((Int64)_arhiveBeginStreamPosition, STREAM_SEEK_SET, NULL)) RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)); _stream = stream; return S_OK; @@ -478,7 +485,7 @@ void CDatabase::GetPath(unsigned index, UString &path) const #if defined(_WIN32) && defined(MY_CPU_LE) - wmemcpy(s, (const wchar_t *)p, size); + wmemcpy(s, (const wchar_t *)(const void *)p, size); #else @@ -506,10 +513,27 @@ HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw() if (size >= (1 << 14)) return S_OK; - RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size - 1)); + // (size) includes null terminator + + /* + #if WCHAR_MAX > 0xffff + + const Byte *p = ((const Byte *)NamesBuf + offset * 2); + size = Utf16LE__Get_Num_WCHARs(p, size - 1); + // (size) doesn't include null terminator + RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size)); wchar_t *s = path->bstrVal; + wchar_t *sEnd = Utf16LE__To_WCHARs_Sep(p, size, s); + *sEnd = 0; + if (s + size != sEnd) return E_FAIL; + #else + */ + + RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size - 1)); + wchar_t *s = path->bstrVal; const Byte *p = ((const Byte *)NamesBuf + offset * 2); + // Utf16LE__To_WCHARs_Sep(p, size, s); for (size_t i = 0; i < size; i++) { @@ -518,10 +542,14 @@ HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw() #if WCHAR_PATH_SEPARATOR != L'/' if (c == L'/') c = WCHAR_PATH_SEPARATOR; + else if (c == L'\\') + c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme #endif *s++ = c; } + // #endif + return S_OK; /* @@ -673,7 +701,7 @@ void CInArchive::ReadUnpackInfo( { UInt32 indexOfMainStream = 0; UInt32 numPackStreams = 0; - folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr; + folders.FoCodersDataOffset[fo] = (size_t)(_inByteBack->GetPtr() - startBufPtr); CNum numInStreams = 0; CNum numCoders = inByte->ReadNum(); @@ -794,10 +822,10 @@ void CInArchive::ReadUnpackInfo( folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream; } - size_t dataSize = _inByteBack->GetPtr() - startBufPtr; + const size_t dataSize = (size_t)(_inByteBack->GetPtr() - startBufPtr); folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; folders.FoStartPackStreamIndex[fo] = packStreamIndex; - folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr; + folders.FoCodersDataOffset[fo] = (size_t)(_inByteBack->GetPtr() - startBufPtr); folders.CodersData.CopyFrom(startBufPtr, dataSize); // if (folders.NumPackStreams != packStreamIndex) ThrowUnsupported(); @@ -962,6 +990,8 @@ void CInArchive::ReadSubStreamsInfo( } } + + void CInArchive::ReadStreamsInfo( const CObjectVector<CByteBuffer> *dataVector, UInt64 &dataOffset, @@ -974,7 +1004,11 @@ void CInArchive::ReadStreamsInfo( if (type == NID::kPackInfo) { dataOffset = ReadNumber(); + if (dataOffset > _rangeLimit) + ThrowIncorrect(); ReadPackInfo(folders); + if (folders.PackPositions[folders.NumPackStreams] > _rangeLimit - dataOffset) + ThrowIncorrect(); type = ReadID(); } @@ -1029,7 +1063,7 @@ void CInArchive::ReadBoolVector(unsigned numItems, CBoolVector &v) mask = 0x80; } p[i] = ((b & mask) != 0); - mask >>= 1; + mask = (Byte)(mask >> 1); } } @@ -1090,8 +1124,8 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( for (CNum i = 0; i < folders.NumFolders; i++) { CByteBuffer &data = dataVector.AddNew(); - UInt64 unpackSize64 = folders.GetFolderUnpackSize(i); - size_t unpackSize = (size_t)unpackSize64; + const UInt64 unpackSize64 = folders.GetFolderUnpackSize(i); + const size_t unpackSize = (size_t)unpackSize64; if (unpackSize != unpackSize64) ThrowUnsupported(); data.Alloc(unpackSize); @@ -1106,7 +1140,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS _stream, baseOffset + dataOffset, folders, i, - NULL, // *unpackSize + NULL, // &unpackSize64 outStream, NULL, // *compressProgress @@ -1127,6 +1161,9 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( if (dataAfterEnd_Error) ThereIsHeaderError = true; + if (unpackSize != outStreamSpec->GetPos()) + ThrowIncorrect(); + if (folders.FolderCRCs.ValidAndDefined(i)) if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i]) ThrowIncorrect(); @@ -1226,8 +1263,8 @@ HRESULT CInArchive::ReadHeader( unsigned i; for (i = 0; i < numFiles; i++) { - size_t curRem = (rem - pos) / 2; - const UInt16 *buf = (const UInt16 *)(db.NamesBuf + pos); + const size_t curRem = (rem - pos) / 2; + const UInt16 *buf = (const UInt16 *)(const void *)(db.NamesBuf + pos); size_t j; for (j = 0; j < curRem && buf[j] != 0; j++); if (j == curRem) @@ -1519,13 +1556,13 @@ HRESULT CInArchive::ReadDatabase2( const unsigned kCheckSize = 512; Byte buf[kCheckSize]; RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize)); - UInt64 rem = fileSize - cur; + const UInt64 rem = fileSize - cur; unsigned checkSize = kCheckSize; if (rem < kCheckSize) checkSize = (unsigned)(rem); if (checkSize < 3) return S_FALSE; - RINOK(_stream->Seek(fileSize - checkSize, STREAM_SEEK_SET, NULL)); + RINOK(_stream->Seek((Int64)(fileSize - checkSize), STREAM_SEEK_SET, NULL)); RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize)); if (buf[checkSize - 1] != 0) @@ -1534,8 +1571,8 @@ HRESULT CInArchive::ReadDatabase2( unsigned i; for (i = checkSize - 2;; i--) { - if (buf[i] == NID::kEncodedHeader && buf[i + 1] == NID::kPackInfo || - buf[i] == NID::kHeader && buf[i + 1] == NID::kMainStreamsInfo) + if ((buf[i] == NID::kEncodedHeader && buf[i + 1] == NID::kPackInfo) || + (buf[i] == NID::kHeader && buf[i + 1] == NID::kMainStreamsInfo)) break; if (i == 0) return S_FALSE; @@ -1543,7 +1580,7 @@ HRESULT CInArchive::ReadDatabase2( nextHeaderSize = checkSize - i; nextHeaderOffset = rem - nextHeaderSize; nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); - RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); + RINOK(_stream->Seek((Int64)cur, STREAM_SEEK_SET, NULL)); db.StartHeaderWasRecovered = true; } else @@ -1560,25 +1597,32 @@ HRESULT CInArchive::ReadDatabase2( if ((Int64)nextHeaderOffset < 0 || nextHeaderSize > ((UInt64)1 << 62)) return S_FALSE; + + HeadersSize = kHeaderSize; + if (nextHeaderSize == 0) { if (nextHeaderOffset != 0) return S_FALSE; db.IsArc = true; + db.HeadersSize = HeadersSize; return S_OK; } if (!db.StartHeaderWasRecovered) db.IsArc = true; - HeadersSize += kHeaderSize + nextHeaderSize; + HeadersSize += nextHeaderSize; + // db.EndHeaderOffset = nextHeaderOffset; + _rangeLimit = nextHeaderOffset; + db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; if (_fileEndPosition - db.ArcInfo.StartPositionAfterHeader < nextHeaderOffset + nextHeaderSize) { db.UnexpectedEnd = true; return S_FALSE; } - RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); + RINOK(_stream->Seek((Int64)nextHeaderOffset, STREAM_SEEK_CUR, NULL)); size_t nextHeaderSize_t = (size_t)nextHeaderSize; if (nextHeaderSize_t != nextHeaderSize) diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h index 6a61d314..ffa1e4bc 100644 --- a/CPP/7zip/Archive/7z/7zIn.h +++ b/CPP/7zip/Archive/7z/7zIn.h @@ -174,13 +174,14 @@ struct CDatabase: public CFolders HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw(); }; + struct CInArchiveInfo { CArchiveVersion Version; - UInt64 StartPosition; - UInt64 StartPositionAfterHeader; - UInt64 DataStartPosition; - UInt64 DataStartPosition2; + UInt64 StartPosition; // in stream + UInt64 StartPositionAfterHeader; // in stream + UInt64 DataStartPosition; // in stream + UInt64 DataStartPosition2; // in stream. it's for headers CRecordVector<UInt64> FileInfoPopIDs; void Clear() @@ -193,6 +194,7 @@ struct CInArchiveInfo } }; + struct CDbEx: public CDatabase { CInArchiveInfo ArcInfo; @@ -202,6 +204,7 @@ struct CDbEx: public CDatabase UInt64 HeadersSize; UInt64 PhySize; + // UInt64 EndHeaderOffset; // relative to position after StartHeader (32 bytes) /* CRecordVector<size_t> SecureOffsets; @@ -255,6 +258,7 @@ struct CDbEx: public CDatabase HeadersSize = 0; PhySize = 0; + // EndHeaderOffset = 0; } bool CanUpdate() const @@ -349,6 +353,8 @@ class CInArchive UInt64 _arhiveBeginStreamPosition; UInt64 _fileEndPosition; + UInt64 _rangeLimit; // relative to position after StartHeader (32 bytes) + Byte _header[kHeaderSize]; UInt64 HeadersSize; diff --git a/CPP/7zip/Archive/7z/7zItem.h b/CPP/7zip/Archive/7z/7zItem.h index ee4aed3f..0f9fdada 100644 --- a/CPP/7zip/Archive/7z/7zItem.h +++ b/CPP/7zip/Archive/7z/7zItem.h @@ -50,7 +50,7 @@ public: { FOR_VECTOR(i, PackStreams) if (PackStreams[i] == packStream) - return i; + return (int)i; return -1; } @@ -58,7 +58,7 @@ public: { FOR_VECTOR(i, Bonds) if (Bonds[i].PackIndex == packStream) - return i; + return (int)i; return -1; } diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp index aa977292..2786bf28 100644 --- a/CPP/7zip/Archive/7z/7zOut.cpp +++ b/CPP/7zip/Archive/7z/7zOut.cpp @@ -5,6 +5,7 @@ #include "../../../../C/7zCrc.h" #include "../../../Common/AutoPtr.h" +// #include "../../../Common/UTFConvert.h" #include "../../Common/StreamObjects.h" @@ -196,7 +197,7 @@ void COutArchive::WriteNumber(UInt64 value) break; } firstByte |= mask; - mask >>= 1; + mask = (Byte)(mask >> 1); } WriteByte(firstByte); for (; i > 0; i--) @@ -206,9 +207,9 @@ void COutArchive::WriteNumber(UInt64 value) } } -static UInt32 GetBigNumberSize(UInt64 value) +static unsigned GetBigNumberSize(UInt64 value) { - int i; + unsigned i; for (i = 1; i < 9; i++) if (value < (((UInt64)1 << (i * 7)))) break; @@ -264,18 +265,18 @@ void COutArchive::WriteFolder(const CFolder &folder) for (idSize = 1; idSize < sizeof(id); idSize++) if ((id >> (8 * idSize)) == 0) break; - idSize &= 0xF; + // idSize &= 0xF; // idSize is smaller than 16 already Byte temp[16]; for (unsigned t = idSize; t != 0; t--, id >>= 8) temp[t] = (Byte)(id & 0xFF); - Byte b = (Byte)(idSize); - bool isComplex = !coder.IsSimpleCoder(); + unsigned b = idSize; + const bool isComplex = !coder.IsSimpleCoder(); b |= (isComplex ? 0x10 : 0); - size_t propsSize = coder.Props.Size(); + const size_t propsSize = coder.Props.Size(); b |= ((propsSize != 0) ? 0x20 : 0); - temp[0] = b; + temp[0] = (Byte)b; WriteBytes(temp, idSize + 1); if (isComplex) { @@ -309,7 +310,7 @@ void COutArchive::WriteBoolVector(const CBoolVector &boolVector) { if (boolVector[i]) b |= mask; - mask >>= 1; + mask = (Byte)(mask >> 1); if (mask == 0) { WriteByte(b); @@ -476,7 +477,7 @@ void COutArchive::WriteAlignedBools(const CBoolVector &v, unsigned numDefined, B { const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v); const UInt64 dataSize = ((UInt64)numDefined << itemSizeShifts) + bvSize + 2; - SkipToAligned(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSizeShifts); + SkipToAligned(3 + bvSize + GetBigNumberSize(dataSize), itemSizeShifts); WriteByte(type); WriteNumber(dataSize); @@ -545,7 +546,39 @@ void COutArchive::WriteHeader( WriteByte(NID::kHeader); - // Archive Properties + /* + { + // It's example for per archive properies writing + + WriteByte(NID::kArchiveProperties); + + // you must use random 40-bit number that will identify you + // then you can use same kDeveloperID for any properties and methods + const UInt64 kDeveloperID = 0x123456789A; // change that value to real random 40-bit number + + #define GENERATE_7Z_ID(developerID, subID) (((UInt64)0x3F << 56) | ((UInt64)developerID << 16) | subID) + + { + const UInt64 kSubID = 0x1; // you can use small number for subID + const UInt64 kID = GENERATE_7Z_ID(kDeveloperID, kSubID); + WriteNumber(kID); + const unsigned kPropsSize = 3; // it's example size + WriteNumber(kPropsSize); + for (unsigned i = 0; i < kPropsSize; i++) + WriteByte((Byte)(i & 0xFF)); + } + { + const UInt64 kSubID = 0x2; // you can use small number for subID + const UInt64 kID = GENERATE_7Z_ID(kDeveloperID, kSubID); + WriteNumber(kID); + const unsigned kPropsSize = 5; // it's example size + WriteNumber(kPropsSize); + for (unsigned i = 0; i < kPropsSize; i++) + WriteByte((Byte)(i + 16)); + } + WriteByte(NID::kEnd); + } + */ if (db.Folders.Size() > 0) { @@ -637,7 +670,15 @@ void COutArchive::WriteHeader( const UString &name = db.Names[i]; if (!name.IsEmpty()) numDefined++; - namesDataSize += (name.Len() + 1) * 2; + const size_t numUtfChars = + /* + #if WCHAR_MAX > 0xffff + Get_Num_Utf16_chars_from_wchar_string(name.Ptr()); + #else + */ + name.Len(); + // #endif + namesDataSize += (numUtfChars + 1) * 2; } if (numDefined > 0) @@ -654,6 +695,25 @@ void COutArchive::WriteHeader( for (unsigned t = 0; t <= name.Len(); t++) { wchar_t c = name[t]; + + /* + #if WCHAR_MAX > 0xffff + if (c >= 0x10000) + { + c -= 0x10000; + if (c < (1 << 20)) + { + unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF); + WriteByte((Byte)c0); + WriteByte((Byte)(c0 >> 8)); + c = 0xdc00 + (c & 0x3FF); + } + else + c = '_'; // we change character unsupported by UTF16 + } + #endif + */ + WriteByte((Byte)c); WriteByte((Byte)(c >> 8)); } @@ -855,7 +915,7 @@ HRESULT COutArchive::WriteDatabase( h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = headerOffset; - RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL)); + RINOK(Stream->Seek((Int64)_prefixHeaderPos, STREAM_SEEK_SET, NULL)); return WriteStartHeader(h); } } diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp index 6705fc00..b641d93f 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp @@ -55,8 +55,8 @@ struct CFilterMode #define PE_SIG 0x00004550 #define PE_OptHeader_Magic_32 0x10B #define PE_OptHeader_Magic_64 0x20B -#define PE_SectHeaderSize 40 -#define PE_SECT_EXECUTE 0x20000000 +// #define PE_SectHeaderSize 40 +// #define PE_SECT_EXECUTE 0x20000000 static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode) { @@ -254,10 +254,12 @@ static BoolInt Parse_WAV(const Byte *buf, size_t size, CFilterMode *filterMode) if (subChunkSize < 0x10 || subChunkSize > 0x12 || GetUi16(buf + 0x14) != 1) return False; - unsigned numChannels = GetUi16(buf + 0x16); - unsigned bitsPerSample = GetUi16(buf + 0x22); - - if ((bitsPerSample & 0x7) != 0 || bitsPerSample >= 256 || numChannels >= 256) + const unsigned numChannels = GetUi16(buf + 0x16); + const unsigned bitsPerSample = GetUi16(buf + 0x22); + if ((bitsPerSample & 0x7) != 0) + return False; + const UInt32 delta = (UInt32)numChannels * (bitsPerSample >> 3); + if (delta == 0 || delta > 256) return False; pos = 0x14 + subChunkSize; @@ -271,9 +273,6 @@ static BoolInt Parse_WAV(const Byte *buf, size_t size, CFilterMode *filterMode) subChunkSize = GetUi32(buf + pos + 4); if (GetUi32(buf + pos) == WAV_SUBCHUNK_data) { - unsigned delta = numChannels * (bitsPerSample >> 3); - if (delta >= 256) - return False; filterMode->Id = k_Delta; filterMode->Delta = delta; return True; @@ -418,7 +417,7 @@ static unsigned Get_FilterGroup_for_Folder( static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, UInt64 position, UInt64 size, ICompressProgressInfo *progress) { - RINOK(inStream->Seek(position, STREAM_SEEK_SET, 0)); + RINOK(inStream->Seek((Int64)position, STREAM_SEEK_SET, 0)); CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec); streamSpec->SetStream(inStream); @@ -642,13 +641,13 @@ struct CRefItem if (sortByType) { int slashPos = ui.Name.ReverseFind_PathSepar(); - NamePos = slashPos + 1; + NamePos = (unsigned)(slashPos + 1); int dotPos = ui.Name.ReverseFind_Dot(); if (dotPos <= slashPos) ExtensionPos = ui.Name.Len(); else { - ExtensionPos = dotPos + 1; + ExtensionPos = (unsigned)(dotPos + 1); if (ExtensionPos != ui.Name.Len()) { AString s; @@ -836,7 +835,7 @@ HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMo { const wchar_t *ext; if (dotPos > slashPos) - ext = ui.Name.Ptr(dotPos + 1); + ext = ui.Name.Ptr((unsigned)(dotPos + 1)); else ext = ui.Name.RightPtr(0); @@ -1071,12 +1070,12 @@ static HRESULT MakeExeMethod(CCompressionMethodMode &mode, if (alignBits != 0) { if (alignBits > 2 || filterMode.Id == k_Delta) - nextMethod.AddProp32(NCoderPropID::kPosStateBits, alignBits); + nextMethod.AddProp32(NCoderPropID::kPosStateBits, (unsigned)alignBits); unsigned lc = 0; if (alignBits < 3) - lc = 3 - alignBits; + lc = (unsigned)(3 - alignBits); nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc); - nextMethod.AddProp32(NCoderPropID::kLitPosBits, alignBits); + nextMethod.AddProp32(NCoderPropID::kLitPosBits, (unsigned)alignBits); } } } @@ -1453,7 +1452,7 @@ public: UInt64 StartPos; const CFolders *Folders; - int FolderIndex; + unsigned FolderIndex; // bool send_UnpackSize; // UInt64 UnpackSize; @@ -1609,7 +1608,10 @@ HRESULT Update( CRecordVector<CFilterMode2> filters; CObjectVector<CSolidGroup> groups; + + #ifndef _7ZIP_ST bool thereAreRepacks = false; + #endif bool useFilters = options.UseFilters; if (useFilters) @@ -1636,7 +1638,7 @@ HRESULT Update( { int index = updateItems[i].IndexInArchive; if (index != -1) - fileIndexToUpdateIndexMap[(unsigned)index] = i; + fileIndexToUpdateIndexMap[(unsigned)index] = (int)i; } for (i = 0; i < db->NumFolders; i++) @@ -1656,7 +1658,7 @@ HRESULT Update( { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fi]; - if (updateIndex >= 0 && !updateItems[updateIndex].NewData) + if (updateIndex >= 0 && !updateItems[(unsigned)updateIndex].NewData) { numCopyItems++; repackSize += file.Size; @@ -1688,7 +1690,9 @@ HRESULT Update( complexity += db->GetFolderFullPackSize(i); else { + #ifndef _7ZIP_ST thereAreRepacks = true; + #endif complexity += repackSize; if (inSizeForReduce2 < repackSize) inSizeForReduce2 = repackSize; @@ -1727,10 +1731,12 @@ HRESULT Update( #ifndef _7ZIP_ST CStreamBinder sb; + /* if (options.MultiThreadMixer) { RINOK(sb.CreateEvents()); } + */ #endif @@ -1742,7 +1748,9 @@ HRESULT Update( #ifdef EXTERNAL_CODECS threadDecoder.__externalCodecs = __externalCodecs; #endif - RINOK(threadDecoder.Create()); + WRes wres = threadDecoder.Create(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); } #endif @@ -1887,7 +1895,7 @@ HRESULT Update( if (ui.HasStream()) continue; } - else if (ui.IndexInArchive != -1 && db->Files[ui.IndexInArchive].HasStream) + else if (ui.IndexInArchive != -1 && db->Files[(unsigned)ui.IndexInArchive].HasStream) continue; /* if (ui.TreeFolderIndex >= 0) @@ -1912,8 +1920,8 @@ HRESULT Update( } else { - GetFile(*db, ui.IndexInArchive, file, file2); - db->GetPath(ui.IndexInArchive, name); + GetFile(*db, (unsigned)ui.IndexInArchive, file, file2); + db->GetPath((unsigned)ui.IndexInArchive, name); } /* @@ -2065,7 +2073,7 @@ HRESULT Update( { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fi]; - if (updateIndex >= 0 && !updateItems[updateIndex].NewData) + if (updateIndex >= 0 && !updateItems[(unsigned)updateIndex].NewData) needExtract = true; // decodeSize += file.Size; } @@ -2099,8 +2107,8 @@ HRESULT Update( { repackBase = threadDecoder.FosSpec; CMyComPtr<ISequentialOutStream> sbOutStream; - sb.CreateStreams(&sbInStream, &sbOutStream); - sb.ReInit(); + sb.CreateStreams2(sbInStream, sbOutStream); + RINOK(sb.Create_ReInit()); threadDecoder.FosSpec->_stream = sbOutStream; @@ -2171,7 +2179,9 @@ HRESULT Update( #ifndef _7ZIP_ST if (options.MultiThreadMixer) { - threadDecoder.Start(); + WRes wres = threadDecoder.Start(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); } #endif } @@ -2197,7 +2207,11 @@ HRESULT Update( inStreamSizeCount.Release(); sbInStream.Release(); - threadDecoder.WaitExecuteFinish(); + { + WRes wres = threadDecoder.WaitExecuteFinish(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + } HRESULT decodeRes = threadDecoder.Result; // if (res == k_My_HRESULT_CRC_ERROR) @@ -2259,7 +2273,7 @@ HRESULT Update( int updateIndex = fileIndexToUpdateIndexMap[fi]; if (updateIndex >= 0) { - const CUpdateItem &ui = updateItems[updateIndex]; + const CUpdateItem &ui = updateItems[(unsigned)updateIndex]; if (ui.NewData) continue; @@ -2347,7 +2361,7 @@ HRESULT Update( { int slashPos = ui.Name.ReverseFind_PathSepar(); int dotPos = ui.Name.ReverseFind_Dot(); - const wchar_t *ext = ui.Name.Ptr(dotPos <= slashPos ? ui.Name.Len() : dotPos + 1); + const wchar_t *ext = ui.Name.Ptr(dotPos <= slashPos ? ui.Name.Len() : (unsigned)(dotPos + 1)); if (numSubFiles == 0) prevExtension = ext; else if (!StringsAreEqualNoCase(ext, prevExtension)) @@ -2403,8 +2417,8 @@ HRESULT Update( } else { - GetFile(*db, ui.IndexInArchive, file, file2); - db->GetPath(ui.IndexInArchive, name); + GetFile(*db, (unsigned)ui.IndexInArchive, file, file2); + db->GetPath((unsigned)ui.IndexInArchive, name); } if (file2.IsAnti || file.IsDir) return E_FAIL; diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h index a7abf779..7c0f78a8 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.h +++ b/CPP/7zip/Archive/7z/7zUpdate.h @@ -31,7 +31,7 @@ struct CTreeFolder struct CUpdateItem { int IndexInArchive; - int IndexInClient; + unsigned IndexInClient; UInt64 CTime; UInt64 ATime; diff --git a/CPP/7zip/Archive/ApmHandler.cpp b/CPP/7zip/Archive/ApmHandler.cpp index 4d3f2728..73e5fcb6 100644 --- a/CPP/7zip/Archive/ApmHandler.cpp +++ b/CPP/7zip/Archive/ApmHandler.cpp @@ -240,7 +240,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) mainIndex = -1; break; } - mainIndex = i; + mainIndex = (int)i; } } if (mainIndex >= 0) diff --git a/CPP/7zip/Archive/ArHandler.cpp b/CPP/7zip/Archive/ArHandler.cpp index 09a62201..0bea8b4e 100644 --- a/CPP/7zip/Archive/ArHandler.cpp +++ b/CPP/7zip/Archive/ArHandler.cpp @@ -618,13 +618,15 @@ STDMETHODIMP CHandler::Open(IInStream *stream, _items.DeleteFrontal(1); for (unsigned i = 0; i < _items.Size(); i++) if (_items[i].Name.IsPrefixedBy("data.tar.")) + { if (_mainSubfile < 0) - _mainSubfile = i; + _mainSubfile = (int)i; else { _mainSubfile = -1; break; } + } } else { @@ -845,7 +847,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) } REGISTER_ARC_I( - "Ar", "ar a deb lib", 0, 0xEC, + "Ar", "ar a deb udeb lib", 0, 0xEC, kSignature, 0, 0, diff --git a/CPP/7zip/Archive/ArchiveExports.cpp b/CPP/7zip/Archive/ArchiveExports.cpp index 28e9946d..6549b3d2 100644 --- a/CPP/7zip/Archive/ArchiveExports.cpp +++ b/CPP/7zip/Archive/ArchiveExports.cpp @@ -46,7 +46,7 @@ static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) return SetPropStrFromBin((const char *)&guid, sizeof(guid), value); } -int FindFormatCalssId(const GUID *clsid) +static int FindFormatCalssId(const GUID *clsid) { GUID cls = *clsid; CLS_ARC_ID_ITEM(cls) = 0; @@ -59,6 +59,7 @@ int FindFormatCalssId(const GUID *clsid) return -1; } +STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject) { COM_TRY_BEGIN @@ -89,6 +90,7 @@ STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject) return S_OK; } +STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value); STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN @@ -130,17 +132,20 @@ STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value COM_TRY_END } +STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value); STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) { return GetHandlerProperty2(g_DefaultArcIndex, propID, value); } +STDAPI GetNumberOfFormats(UINT32 *numFormats); STDAPI GetNumberOfFormats(UINT32 *numFormats) { *numFormats = g_NumArcs; return S_OK; } +STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc); STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc) { *isArc = NULL; diff --git a/CPP/7zip/Archive/ArjHandler.cpp b/CPP/7zip/Archive/ArjHandler.cpp index fb9e3e7a..0e353dca 100644 --- a/CPP/7zip/Archive/ArjHandler.cpp +++ b/CPP/7zip/Archive/ArjHandler.cpp @@ -235,13 +235,13 @@ namespace NFileType namespace NFlags { const Byte kGarbled = 1 << 0; - const Byte kAnsiPage = 1 << 1; // or (OLD_SECURED_FLAG) obsolete + // const Byte kAnsiPage = 1 << 1; // or (OLD_SECURED_FLAG) obsolete const Byte kVolume = 1 << 2; const Byte kExtFile = 1 << 3; - const Byte kPathSym = 1 << 4; - const Byte kBackup = 1 << 5; // obsolete - const Byte kSecured = 1 << 6; - const Byte kDualName = 1 << 7; + // const Byte kPathSym = 1 << 4; + // const Byte kBackup = 1 << 5; // obsolete + // const Byte kSecured = 1 << 6; + // const Byte kDualName = 1 << 7; } namespace NHostOS @@ -375,6 +375,32 @@ HRESULT CArcHeader::Parse(const Byte *p, unsigned size) return S_OK; } + +struct CExtendedInfo +{ + UInt64 Size; + bool CrcError; + + void Clear() + { + Size = 0; + CrcError = false; + } + void ParseToPropVar(NCOM::CPropVariant &prop) const + { + if (Size != 0) + { + AString s; + s += "Extended:"; + s.Add_UInt32((UInt32)Size); + if (CrcError) + s += ":CRC_ERROR"; + prop = s; + } + } +}; + + struct CItem { AString Name; @@ -399,6 +425,8 @@ struct CItem // Byte LastChapter; UInt64 DataPosition; + + CExtendedInfo ExtendedInfo; bool IsEncrypted() const { return (Flags & NFlags::kGarbled) != 0; } bool IsDir() const { return (FileType == NFileType::kDirectory); } @@ -462,7 +490,7 @@ enum EErrorType { k_ErrorType_OK, k_ErrorType_Corrupted, - k_ErrorType_UnexpectedEnd, + k_ErrorType_UnexpectedEnd }; class CArc @@ -476,19 +504,22 @@ public: UInt64 NumFiles; CArcHeader Header; + CExtendedInfo ExtendedInfo; + HRESULT Open(); HRESULT GetNextItem(CItem &item, bool &filled); void Close() { IsArc = false; Error = k_ErrorType_OK; + ExtendedInfo.Clear(); } private: - UInt32 _blockSize; - Byte _block[kBlockSizeMax + 4]; + unsigned _blockSize; + CByteBuffer _block; - HRESULT ReadBlock(bool &filled, bool readSignature); - HRESULT SkipExtendedHeaders(); + HRESULT ReadBlock(bool &filled, CExtendedInfo *extendedInfo); + HRESULT SkipExtendedHeaders(CExtendedInfo &extendedInfo); HRESULT Read(void *data, size_t *size); }; @@ -503,14 +534,14 @@ HRESULT CArc::Read(void *data, size_t *size) { size_t _processed_ = (_size_); RINOK(Read(_dest_, &_processed_)); \ if (_processed_ != (_size_)) { Error = k_ErrorType_UnexpectedEnd; return S_OK; } } -HRESULT CArc::ReadBlock(bool &filled, bool readSignature) +HRESULT CArc::ReadBlock(bool &filled, CExtendedInfo *extendedInfo) { Error = k_ErrorType_OK; filled = false; Byte buf[4]; - unsigned signSize = readSignature ? 2 : 0; + const unsigned signSize = extendedInfo ? 0 : 2; READ_STREAM(buf, signSize + 2) - if (readSignature) + if (!extendedInfo) if (buf[0] != kSig0 || buf[1] != kSig1) { Error = k_ErrorType_Corrupted; @@ -519,28 +550,48 @@ HRESULT CArc::ReadBlock(bool &filled, bool readSignature) _blockSize = Get16(buf + signSize); if (_blockSize == 0) // end of archive return S_OK; - if (_blockSize < kBlockSizeMin || - _blockSize > kBlockSizeMax) + + if (!extendedInfo) + if (_blockSize < kBlockSizeMin || _blockSize > kBlockSizeMax) + { + Error = k_ErrorType_Corrupted; + return S_OK; + } + + const size_t readSize = _blockSize + 4; + if (readSize > _block.Size()) { - Error = k_ErrorType_Corrupted; - return S_OK; + // extended data size is limited by (64 KB) + // _blockSize is less than 64 KB + const size_t upSize = (_blockSize > kBlockSizeMax ? (1 << 16) : kBlockSizeMax); + _block.Alloc(upSize + 4); } - READ_STREAM(_block, _blockSize + 4); + + if (extendedInfo) + extendedInfo->Size += _blockSize; + + READ_STREAM(_block, readSize); if (Get32(_block + _blockSize) != CrcCalc(_block, _blockSize)) { - Error = k_ErrorType_Corrupted; - return S_OK; + if (extendedInfo) + extendedInfo->CrcError = true; + else + { + Error = k_ErrorType_Corrupted; + return S_OK; + } } filled = true; return S_OK; } -HRESULT CArc::SkipExtendedHeaders() +HRESULT CArc::SkipExtendedHeaders(CExtendedInfo &extendedInfo) { + extendedInfo.Clear(); for (UInt32 i = 0;; i++) { bool filled; - RINOK(ReadBlock(filled, false)); + RINOK(ReadBlock(filled, &extendedInfo)); if (!filled) return S_OK; if (Callback && (i & 0xFF) == 0) @@ -551,17 +602,17 @@ HRESULT CArc::SkipExtendedHeaders() HRESULT CArc::Open() { bool filled; - RINOK(ReadBlock(filled, true)); + RINOK(ReadBlock(filled, NULL)); // (extendedInfo = NULL) if (!filled) return S_FALSE; RINOK(Header.Parse(_block, _blockSize)); IsArc = true; - return SkipExtendedHeaders(); + return SkipExtendedHeaders(ExtendedInfo); } HRESULT CArc::GetNextItem(CItem &item, bool &filled) { - RINOK(ReadBlock(filled, true)); + RINOK(ReadBlock(filled, NULL)); // (extendedInfo = NULL) if (!filled) return S_OK; filled = false; @@ -576,7 +627,7 @@ HRESULT CArc::GetNextItem(CItem &item, bool &filled) extraData = GetUi32(_block + pos); */ - RINOK(SkipExtendedHeaders()); + RINOK(SkipExtendedHeaders(item.ExtendedInfo)); filled = true; return S_OK; } @@ -603,7 +654,8 @@ static const Byte kArcProps[] = kpidCTime, kpidMTime, kpidHostOS, - kpidComment + kpidComment, + kpidCharacts }; static const Byte kProps[] = @@ -619,7 +671,8 @@ static const Byte kProps[] = kpidCRC, kpidMethod, kpidHostOS, - kpidComment + kpidComment, + kpidCharacts }; IMP_IInArchive_Props @@ -671,10 +724,14 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { case k_ErrorType_UnexpectedEnd: v |= kpv_ErrorFlags_UnexpectedEnd; break; case k_ErrorType_Corrupted: v |= kpv_ErrorFlags_HeadersError; break; + case k_ErrorType_OK: + default: + break; } prop = v; break; } + case kpidCharacts: _arc.ExtendedInfo.ParseToPropVar(prop); break; } prop.Detach(value); return S_OK; @@ -706,6 +763,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidHostOS: SetHostOS(item.HostOS, prop); break; case kpidMTime: SetTime(item.MTime, prop); break; case kpidComment: SetUnicodeString(item.Comment, prop); break; + case kpidCharacts: item.ExtendedInfo.ParseToPropVar(prop); break; } prop.Detach(value); return S_OK; diff --git a/CPP/7zip/Archive/Base64Handler.cpp b/CPP/7zip/Archive/Base64Handler.cpp new file mode 100644 index 00000000..63b4552e --- /dev/null +++ b/CPP/7zip/Archive/Base64Handler.cpp @@ -0,0 +1,511 @@ +// Base64Handler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "../../Common/ComTry.h" +#include "../../Common/MyBuffer.h" +#include "../../Common/IntToString.h" +#include "../../Common/MyVector.h" + +#include "../../Windows/PropVariant.h" + +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" +#include "../Common/InBuffer.h" + +/* +spaces: + 9(TAB),10(LF),13(CR),32(SPACE) + Non-breaking space: + 0xa0 : Unicode, Windows code pages 1250-1258 + 0xff (unused): DOS code pages + +end of stream markers: '=' (0x3d): + "=" , if numBytes (% 3 == 2) + "==" , if numBytes (% 3 == 1) +*/ + + +static const Byte k_Base64Table[256] = +{ + 66,77,77,77,77,77,77,77,77,65,65,77,77,65,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 65,77,77,77,77,77,77,77,77,77,77,62,77,77,77,63, + 52,53,54,55,56,57,58,59,60,61,77,77,77,64,77,77, + 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, + 15,16,17,18,19,20,21,22,23,24,25,77,77,77,77,77, + 77,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, + 41,42,43,44,45,46,47,48,49,50,51,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 65,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77 +}; + +static const unsigned k_Code_Equals = 64; +static const unsigned k_Code_Space = 65; +static const unsigned k_Code_Zero = 66; + +API_FUNC_static_IsArc IsArc_Base64(const Byte *p, size_t size) +{ + size_t num = 0; + size_t firstSpace = 0; + + for (;;) + { + if (size == 0) + return k_IsArc_Res_NEED_MORE; + UInt32 c = k_Base64Table[(Byte)(*p++)]; + size--; + if (c < 64) + { + num++; + continue; + } + + if (c == k_Code_Space) + { + if (p[-1] == ' ' && firstSpace == 0) + firstSpace = num; + continue; + } + + if (c != k_Code_Equals) + return k_IsArc_Res_NO; + break; + } + + { + // we try to redece false positive detection here. + // we don't expect space character in starting base64 line + const unsigned kNumExpectedNonSpaceSyms = 20; + if (firstSpace != 0 && firstSpace < num && firstSpace < kNumExpectedNonSpaceSyms) + return k_IsArc_Res_NO; + } + + num &= 3; + + if (num <= 1) + return k_IsArc_Res_NO; + if (num != 3) + { + if (size == 0) + return k_IsArc_Res_NEED_MORE; + UInt32 c = k_Base64Table[(Byte)(*p++)]; + size--; + if (c != k_Code_Equals) + return k_IsArc_Res_NO; + } + + for (;;) + { + if (size == 0) + return k_IsArc_Res_YES; + UInt32 c = k_Base64Table[(Byte)(*p++)]; + size--; + if (c == k_Code_Space) + continue; + return k_IsArc_Res_NO; + } +} +} + + +enum EBase64Res +{ + k_Base64_RES_MaybeFinished, + k_Base64_RES_Finished, + k_Base64_RES_NeedMoreInput, + k_Base64_RES_UnexpectedChar +}; + + +static EBase64Res Base64ToBin(Byte *p, size_t size, const Byte **srcEnd, Byte **destEnd) +{ + Byte *dest = p; + UInt32 val = 1; + EBase64Res res = k_Base64_RES_NeedMoreInput; + + for (;;) + { + if (size == 0) + { + if (val == 1) + res = k_Base64_RES_MaybeFinished; + break; + } + UInt32 c = k_Base64Table[(Byte)(*p++)]; + size--; + if (c < 64) + { + val = (val << 6) | c; + if ((val & ((UInt32)1 << 24)) == 0) + continue; + dest[0] = (Byte)(val >> 16); + dest[1] = (Byte)(val >> 8); + dest[2] = (Byte)(val); + dest += 3; + val = 1; + continue; + } + + if (c == k_Code_Space) + continue; + + if (c == k_Code_Equals) + { + if (val >= (1 << 12)) + { + if (val & (1 << 18)) + { + res = k_Base64_RES_Finished; + break; + } + if (size == 0) + break; + c = k_Base64Table[(Byte)(*p++)]; + size--; + if (c == k_Code_Equals) + { + res = k_Base64_RES_Finished; + break; + } + } + } + + p--; + res = k_Base64_RES_UnexpectedChar; + break; + } + + if (val >= ((UInt32)1 << 12)) + { + if (val & (1 << 18)) + { + *dest++ = (Byte)(val >> 10); + val <<= 2; + } + *dest++ = (Byte)(val >> 4); + } + + *srcEnd = p; + *destEnd = dest; + return res; +} + + +static const Byte *Base64_SkipSpaces(const Byte *p, size_t size) +{ + for (;;) + { + if (size == 0) + return p; + UInt32 c = k_Base64Table[(Byte)(*p++)]; + size--; + if (c == k_Code_Space) + continue; + return p - 1; + } +} + + +// the following function is used by DmgHandler.cpp + +Byte *Base64ToBin(Byte *dest, const char *src); +Byte *Base64ToBin(Byte *dest, const char *src) +{ + UInt32 val = 1; + + for (;;) + { + UInt32 c = k_Base64Table[(Byte)(*src++)]; + + if (c < 64) + { + val = (val << 6) | c; + if ((val & ((UInt32)1 << 24)) == 0) + continue; + dest[0] = (Byte)(val >> 16); + dest[1] = (Byte)(val >> 8); + dest[2] = (Byte)(val); + dest += 3; + val = 1; + continue; + } + + if (c == k_Code_Space) + continue; + + if (c == k_Code_Equals) + break; + + if (c == k_Code_Zero && val == 1) // end of string + return dest; + + return NULL; + } + + if (val < (1 << 12)) + return NULL; + + if (val & (1 << 18)) + { + *dest++ = (Byte)(val >> 10); + val <<= 2; + } + else if (k_Base64Table[(Byte)(*src++)] != k_Code_Equals) + return NULL; + *dest++ = (Byte)(val >> 4); + + for (;;) + { + Byte c = k_Base64Table[(Byte)(*src++)]; + if (c == k_Code_Space) + continue; + if (c == k_Code_Zero) + return dest; + return NULL; + } +} + + +namespace NArchive { +namespace NBase64 { + +class CHandler: + public IInArchive, + public CMyUnknownImp +{ + bool _isArc; + UInt64 _phySize; + size_t _size; + EBase64Res _sres; + CByteBuffer _data; +public: + MY_UNKNOWN_IMP1(IInArchive) + INTERFACE_IInArchive(;) +}; + +static const Byte kProps[] = +{ + kpidSize, + kpidPackSize, +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant prop; + switch (propID) + { + case kpidPhySize: if (_phySize != 0) prop = _phySize; break; + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; + if (_sres == k_Base64_RES_NeedMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; + if (v != 0) + prop = v; + break; + } + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + // COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch (propID) + { + case kpidSize: prop = (UInt64)_size; break; + case kpidPackSize: prop = _phySize; break; + } + prop.Detach(value); + return S_OK; + // COM_TRY_END +} + + +static HRESULT ReadStream_OpenProgress(ISequentialInStream *stream, void *data, size_t size, IArchiveOpenCallback *openCallback) throw() +{ + UInt64 bytes = 0; + while (size != 0) + { + const UInt32 kBlockSize = ((UInt32)1 << 24); + UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize; + UInt32 processedSizeLoc; + RINOK(stream->Read(data, curSize, &processedSizeLoc)); + if (processedSizeLoc == 0) + return E_FAIL; + data = (void *)((Byte *)data + processedSizeLoc); + size -= processedSizeLoc; + bytes += processedSizeLoc; + const UInt64 files = 1; + RINOK(openCallback->SetCompleted(&files, &bytes)); + } + return S_OK; +} + + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openCallback) +{ + COM_TRY_BEGIN + { + Close(); + { + const unsigned kStartSize = 1 << 12; + _data.Alloc(kStartSize); + size_t size = kStartSize; + RINOK(ReadStream(stream, _data, &size)); + UInt32 isArcRes = IsArc_Base64(_data, size); + if (isArcRes == k_IsArc_Res_NO) + return S_FALSE; + } + _isArc = true; + + UInt64 packSize64; + RINOK(stream->Seek(0, STREAM_SEEK_END, &packSize64)); + + if (packSize64 == 0) + return S_FALSE; + + size_t curSize = 1 << 16; + if (curSize > packSize64) + curSize = (size_t)packSize64; + const unsigned kLogStep = 4; + + for (;;) + { + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + + _data.Alloc(curSize); + RINOK(ReadStream_OpenProgress(stream, _data, curSize, openCallback)); + + const Byte *srcEnd; + Byte *dest; + _sres = Base64ToBin(_data, curSize, &srcEnd, &dest); + _size = dest - _data; + size_t mainSize = srcEnd - _data; + _phySize = mainSize; + if (_sres == k_Base64_RES_UnexpectedChar) + break; + if (curSize != mainSize) + { + const Byte *end2 = Base64_SkipSpaces(srcEnd, curSize - mainSize); + if ((size_t)(end2 - _data) != curSize) + break; + _phySize = curSize; + } + + if (curSize == packSize64) + break; + + UInt64 curSize64 = packSize64; + if (curSize < (packSize64 >> kLogStep)) + curSize64 = (UInt64)curSize << kLogStep; + curSize = (size_t)curSize64; + if (curSize != curSize64) + return E_OUTOFMEMORY; + } + if (_size == 0) + return S_FALSE; + return S_OK; + } + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _phySize = 0; + _size = 0; + _isArc = false; + _sres = k_Base64_RES_MaybeFinished; + _data.Free(); + return S_OK; +} + + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)(Int32)-1); + if (allFilesMode) + numItems = 1; + if (numItems == 0) + return S_OK; + if (numItems != 1 || *indices != 0) + return E_INVALIDARG; + + RINOK(extractCallback->SetTotal(_size)); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + + { + lps->InSize = lps->OutSize = 0; + RINOK(lps->SetCur()); + + CMyComPtr<ISequentialOutStream> realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + + RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); + + if (!testMode && !realOutStream) + return S_OK; + + extractCallback->PrepareOperation(askMode); + + if (realOutStream) + { + RINOK(WriteStream(realOutStream, (const Byte *)_data, _size)); + realOutStream.Release(); + } + + Int32 opRes = NExtract::NOperationResult::kOK; + + if (_sres != k_Base64_RES_Finished) + { + if (_sres == k_Base64_RES_NeedMoreInput) + opRes = NExtract::NOperationResult::kUnexpectedEnd; + else if (_sres == k_Base64_RES_UnexpectedChar) + opRes = NExtract::NOperationResult::kDataError; + } + + RINOK(extractCallback->SetOperationResult(opRes)); + } + + lps->InSize = _phySize; + lps->OutSize = _size; + return lps->SetCur(); + + COM_TRY_END +} + +REGISTER_ARC_I_NO_SIG( + "Base64", "b64", 0, 0xC5, + 0, + NArcInfoFlags::kKeepName | NArcInfoFlags::kStartOpen | NArcInfoFlags::kByExtOnlyOpen, + IsArc_Base64) + +}} diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp index 4395ae1a..9f50d3aa 100644 --- a/CPP/7zip/Archive/Cab/CabHandler.cpp +++ b/CPP/7zip/Archive/Cab/CabHandler.cpp @@ -309,11 +309,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidMethod: { - UInt32 realFolderIndex = item.GetFolderIndex(db.Folders.Size()); - const CFolder &folder = db.Folders[realFolderIndex]; - char s[kMethodNameBufSize];; - SetMethodName(s, folder.GetMethod(), folder.MethodMinor); - prop = s; + const int realFolderIndex = item.GetFolderIndex(db.Folders.Size()); + if (realFolderIndex >= 0) + { + const CFolder &folder = db.Folders[(unsigned)realFolderIndex]; + char s[kMethodNameBufSize];; + SetMethodName(s, folder.GetMethod(), folder.MethodMinor); + prop = s; + } break; } @@ -341,7 +344,8 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, CInArchive archive; CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; - callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback); + if (callback) + callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback); CMyComPtr<IInStream> nextStream = inStream; bool prevChecked = false; @@ -420,7 +424,10 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, } } - RINOK(callback->SetCompleted(&numItems, NULL)); + if (callback) + { + RINOK(callback->SetCompleted(&numItems, NULL)); + } nextStream = NULL; @@ -1007,7 +1014,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, continue; } - unsigned startIndex2 = m_Database.FolderStartFileIndex[folderIndex]; + const unsigned startIndex2 = m_Database.FolderStartFileIndex[(unsigned)folderIndex]; unsigned startIndex = startIndex2; extractStatuses.Clear(); for (; startIndex < index; startIndex++) @@ -1037,8 +1044,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CFolderOutStream *cabFolderOutStream = new CFolderOutStream; CMyComPtr<ISequentialOutStream> outStream(cabFolderOutStream); - unsigned folderIndex2 = item.GetFolderIndex(db.Folders.Size()); - const CFolder &folder = db.Folders[folderIndex2]; + const int folderIndex2 = item.GetFolderIndex(db.Folders.Size()); + if (folderIndex2 < 0) + return E_FAIL; + const CFolder &folder = db.Folders[(unsigned)folderIndex2]; cabFolderOutStream->Init(&m_Database, &extractStatuses, startIndex2, curUnpack, extractCallback, testMode); @@ -1107,12 +1116,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } const CDatabaseEx &db2 = m_Database.Volumes[volIndex]; - const CFolder &folder2 = db2.Folders[locFolderIndex]; + if (locFolderIndex < 0) + return E_FAIL; + const CFolder &folder2 = db2.Folders[(unsigned)locFolderIndex]; if (bl == 0) { cabBlockInStreamSpec->ReservedSize = db2.ArcInfo.GetDataBlockReserveSize(); - RINOK(db2.Stream->Seek(db2.StartPosition + folder2.DataStart, STREAM_SEEK_SET, NULL)); + RINOK(db2.Stream->Seek((Int64)(db2.StartPosition + folder2.DataStart), STREAM_SEEK_SET, NULL)); } if (bl == folder2.NumDataBlocks) @@ -1242,7 +1253,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (res != S_OK || cabFolderOutStream->NeedMoreWrite()) { - RINOK(cabFolderOutStream->FlushCorrupted(folderIndex2)); + RINOK(cabFolderOutStream->FlushCorrupted((unsigned)folderIndex2)); } totalUnPacked += curUnpack; diff --git a/CPP/7zip/Archive/Cab/CabIn.cpp b/CPP/7zip/Archive/Cab/CabIn.cpp index ca0052bf..e11ce9d0 100644 --- a/CPP/7zip/Archive/Cab/CabIn.cpp +++ b/CPP/7zip/Archive/Cab/CabIn.cpp @@ -114,8 +114,8 @@ HRESULT CSignatureFinder::Find() Byte b = Signature[0]; for (;;) { - if (*p == b) break; p++; - if (*p == b) break; p++; + if (*p == b) { break; } p++; + if (*p == b) { break; } p++; } Pos = (UInt32)(p - Buf); if (End - Pos < _HeaderSize) @@ -311,7 +311,7 @@ HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit) { // printf("\n!!! Seek Error !!!!\n"); // fflush(stdout); - RINOK(db.Stream->Seek(db.StartPosition + ai.FileHeadersOffset, STREAM_SEEK_SET, NULL)); + RINOK(db.Stream->Seek((Int64)(db.StartPosition + ai.FileHeadersOffset), STREAM_SEEK_SET, NULL)); limitedStreamSpec->Init(ai.Size - ai.FileHeadersOffset); _inBuffer.Init(); } diff --git a/CPP/7zip/Archive/Cab/CabIn.h b/CPP/7zip/Archive/Cab/CabIn.h index a1fc6bdc..39586d12 100644 --- a/CPP/7zip/Archive/Cab/CabIn.h +++ b/CPP/7zip/Archive/Cab/CabIn.h @@ -100,7 +100,7 @@ struct CDatabase int GetNumberOfNewFolders() const { - int res = Folders.Size(); + int res = (int)Folders.Size(); if (IsTherePrevFolder()) res--; return res; diff --git a/CPP/7zip/Archive/Cab/CabItem.h b/CPP/7zip/Archive/Cab/CabItem.h index 9b513202..9a912d5e 100644 --- a/CPP/7zip/Archive/Cab/CabItem.h +++ b/CPP/7zip/Archive/Cab/CabItem.h @@ -56,8 +56,8 @@ struct CItem if (ContinuedFromPrev()) return 0; if (ContinuedToNext()) - return numFolders - 1; - return FolderIndex; + return (int)numFolders - 1; + return (int)FolderIndex; } }; diff --git a/CPP/7zip/Archive/Chm/ChmHandler.cpp b/CPP/7zip/Archive/Chm/ChmHandler.cpp index 7ffdafe0..03e7ddd2 100644 --- a/CPP/7zip/Archive/Chm/ChmHandler.cpp +++ b/CPP/7zip/Archive/Chm/ChmHandler.cpp @@ -145,10 +145,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidMethod: { if (!item.IsDir()) + { if (item.Section == 0) prop = "Copy"; else if (item.Section < m_Database.Sections.Size()) prop = m_Database.Sections[(unsigned)item.Section].GetMethodName(); + } break; } case kpidBlock: diff --git a/CPP/7zip/Archive/Chm/ChmIn.cpp b/CPP/7zip/Archive/Chm/ChmIn.cpp index 7e3f155b..f4916b68 100644 --- a/CPP/7zip/Archive/Chm/ChmIn.cpp +++ b/CPP/7zip/Archive/Chm/ChmIn.cpp @@ -13,7 +13,6 @@ #include "ChmIn.h" -#define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) #define Get64(p) GetUi64(p) @@ -117,7 +116,7 @@ UString CSectionInfo::GetMethodName() const if (!IsLzx()) { UString temp; - if (ConvertUTF8ToUnicode(Name, temp)) + ConvertUTF8ToUnicode(Name, temp); s += temp; s += ": "; } diff --git a/CPP/7zip/Archive/ComHandler.cpp b/CPP/7zip/Archive/ComHandler.cpp index d2dc6c5f..a1f643b7 100644 --- a/CPP/7zip/Archive/ComHandler.cpp +++ b/CPP/7zip/Archive/ComHandler.cpp @@ -36,7 +36,7 @@ enum EType k_Type_Msp, k_Type_Doc, k_Type_Ppt, - k_Type_Xls, + k_Type_Xls }; static const char * const kExtensions[] = @@ -51,10 +51,10 @@ static const char * const kExtensions[] = namespace NFatID { - static const UInt32 kFree = 0xFFFFFFFF; + // static const UInt32 kFree = 0xFFFFFFFF; static const UInt32 kEndOfChain = 0xFFFFFFFE; - static const UInt32 kFatSector = 0xFFFFFFFD; - static const UInt32 kMatSector = 0xFFFFFFFC; + // static const UInt32 kFatSector = 0xFFFFFFFD; + // static const UInt32 kMatSector = 0xFFFFFFFC; static const UInt32 kMaxValue = 0xFFFFFFFA; } @@ -62,9 +62,9 @@ namespace NItemType { static const Byte kEmpty = 0; static const Byte kStorage = 1; - static const Byte kStream = 2; - static const Byte kLockBytes = 3; - static const Byte kProperty = 4; + // static const Byte kStream = 2; + // static const Byte kLockBytes = 3; + // static const Byte kProperty = 4; static const Byte kRootStorage = 5; } @@ -298,7 +298,7 @@ static bool CompoundMsiNameToFileName(const UString &name, UString &res) for (unsigned i = 0; i < name.Len(); i++) { wchar_t c = name[i]; - if (c < k_Msi_StartUnicodeChar || c > k_Msi_StartUnicodeChar + k_Msi_UnicodeRange) + if (c < (wchar_t)k_Msi_StartUnicodeChar || c > (wchar_t)(k_Msi_StartUnicodeChar + k_Msi_UnicodeRange)) return false; /* if (i == 0) @@ -578,11 +578,10 @@ HRESULT CDatabase::Open(IInStream *inStream) { // bool isThereExt = (msiName.Find(L'.') >= 0); bool isMsiSpec = (msiName[0] == k_Msi_SpecChar); - if (msiName.Len() >= 4 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(4), ".cab") - || !isMsiSpec && msiName.Len() >= 3 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(3), "exe") - // || !isMsiSpec && !isThereExt + if ((msiName.Len() >= 4 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(4), ".cab")) + || (!isMsiSpec && msiName.Len() >= 3 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(3), "exe")) + // || (!isMsiSpec && !isThereExt) ) - { numCabs++; MainSubfile = i; diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp index c7002121..c8b67bd4 100644 --- a/CPP/7zip/Archive/Common/CoderMixer2.cpp +++ b/CPP/7zip/Archive/Common/CoderMixer2.cpp @@ -137,7 +137,7 @@ bool CBondsChecks::CheckCoder(unsigned coderIndex) return false; _coderUsed[coderIndex] = true; - UInt32 start = BindInfo->Coder_to_Stream[coderIndex]; + const UInt32 start = BindInfo->Coder_to_Stream[coderIndex]; for (unsigned i = 0; i < coder.NumStreams; i++) { @@ -146,10 +146,10 @@ bool CBondsChecks::CheckCoder(unsigned coderIndex) if (BindInfo->IsStream_in_PackStreams(ind)) continue; - int bond = BindInfo->FindBond_for_PackStream(ind); + const int bond = BindInfo->FindBond_for_PackStream(ind); if (bond < 0) return false; - if (!CheckCoder(BindInfo->Bonds[bond].UnpackIndex)) + if (!CheckCoder(BindInfo->Bonds[(unsigned)bond].UnpackIndex)) return false; } @@ -246,15 +246,15 @@ bool CMixer::Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex) if (coderIndex == _bi.UnpackCoder) return true; - int bond = _bi.FindBond_for_UnpackStream(coderIndex); + const int bond = _bi.FindBond_for_UnpackStream(coderIndex); if (bond < 0) throw 20150213; /* UInt32 coderIndex, coderStreamIndex; - _bi.GetCoder_for_Stream(_bi.Bonds[bond].PackIndex, coderIndex, coderStreamIndex); + _bi.GetCoder_for_Stream(_bi.Bonds[(unsigned)bond].PackIndex, coderIndex, coderStreamIndex); */ - UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[bond].PackIndex]; + const UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[(unsigned)bond].PackIndex]; if (!IsFilter_Vector[nextCoder]) return false; @@ -267,11 +267,11 @@ bool CMixer::Is_PackSize_Correct_for_Stream(UInt32 streamIndex) if (_bi.IsStream_in_PackStreams(streamIndex)) return true; - int bond = _bi.FindBond_for_PackStream(streamIndex); + const int bond = _bi.FindBond_for_PackStream(streamIndex); if (bond < 0) throw 20150213; - UInt32 nextCoder = _bi.Bonds[bond].UnpackIndex; + const UInt32 nextCoder = _bi.Bonds[(unsigned)bond].UnpackIndex; if (!IsFilter_Vector[nextCoder]) return false; @@ -281,8 +281,8 @@ bool CMixer::Is_PackSize_Correct_for_Stream(UInt32 streamIndex) bool CMixer::Is_PackSize_Correct_for_Coder(UInt32 coderIndex) { - UInt32 startIndex = _bi.Coder_to_Stream[coderIndex]; - UInt32 numStreams = _bi.Coders[coderIndex].NumStreams; + const UInt32 startIndex = _bi.Coder_to_Stream[coderIndex]; + const UInt32 numStreams = _bi.Coders[coderIndex].NumStreams; for (UInt32 i = 0; i < numStreams; i++) if (!Is_PackSize_Correct_for_Stream(startIndex + i)) return false; @@ -293,19 +293,19 @@ bool CMixer::IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex) { if (IsExternal_Vector[coderIndex]) return true; - UInt32 startIndex = _bi.Coder_to_Stream[coderIndex]; - UInt32 numStreams = _bi.Coders[coderIndex].NumStreams; + const UInt32 startIndex = _bi.Coder_to_Stream[coderIndex]; + const UInt32 numStreams = _bi.Coders[coderIndex].NumStreams; for (UInt32 i = 0; i < numStreams; i++) { - UInt32 si = startIndex + i; + const UInt32 si = startIndex + i; if (_bi.IsStream_in_PackStreams(si)) continue; - int bond = _bi.FindBond_for_PackStream(si); + const int bond = _bi.FindBond_for_PackStream(si); if (bond < 0) throw 20150213; - if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[bond].UnpackIndex)) + if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[(unsigned)bond].UnpackIndex)) return true; } return false; @@ -360,7 +360,7 @@ CCoder &CMixerST::GetCoder(unsigned index) return _coders[index]; } -void CMixerST::ReInit() {} +HRESULT CMixerST::ReInit2() { return S_OK; } HRESULT CMixerST::GetInStream2( ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ @@ -444,18 +444,18 @@ HRESULT CMixerST::GetInStream( } } - int bond = FindBond_for_Stream( + const int bond = FindBond_for_Stream( true, // forInputStream inStreamIndex); if (bond < 0) return E_INVALIDARG; RINOK(GetInStream2(inStreams, /* inSizes, */ - _bi.Bonds[bond].Get_OutIndex(EncodeMode), &seqInStream)); + _bi.Bonds[(unsigned)bond].Get_OutIndex(EncodeMode), &seqInStream)); while (_binderStreams.Size() <= (unsigned)bond) _binderStreams.AddNew(); - CStBinderStream &bs = _binderStreams[bond]; + CStBinderStream &bs = _binderStreams[(unsigned)bond]; if (bs.StreamRef || bs.InStreamSpec) return E_NOTIMPL; @@ -498,13 +498,13 @@ HRESULT CMixerST::GetOutStream( } } - int bond = FindBond_for_Stream( + const int bond = FindBond_for_Stream( false, // forInputStream outStreamIndex); if (bond < 0) return E_INVALIDARG; - UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode); + UInt32 inStreamIndex = _bi.Bonds[(unsigned)bond].Get_InIndex(EncodeMode); UInt32 coderIndex = inStreamIndex; UInt32 coderStreamIndex = 0; @@ -560,7 +560,7 @@ HRESULT CMixerST::GetOutStream( while (_binderStreams.Size() <= (unsigned)bond) _binderStreams.AddNew(); - CStBinderStream &bs = _binderStreams[bond]; + CStBinderStream &bs = _binderStreams[(unsigned)bond]; if (bs.StreamRef || bs.OutStreamSpec) return E_NOTIMPL; @@ -610,13 +610,13 @@ HRESULT CMixerST::FinishStream(UInt32 streamIndex) return S_OK; } - int bond = FindBond_for_Stream( + const int bond = FindBond_for_Stream( false, // forInputStream streamIndex); if (bond < 0) return E_INVALIDARG; - UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode); + UInt32 inStreamIndex = _bi.Bonds[(unsigned)bond].Get_InIndex(EncodeMode); UInt32 coderIndex = inStreamIndex; UInt32 coderStreamIndex = 0; @@ -654,7 +654,7 @@ void CMixerST::SelectMainCoder(bool useFirst) unsigned ci = _bi.UnpackCoder; int firstNonFilter = -1; - int firstAllowed = ci; + unsigned firstAllowed = ci; for (;;) { @@ -674,7 +674,7 @@ void CMixerST::SelectMainCoder(bool useFirst) UInt32 st = _bi.Coder_to_Stream[ci]; if (_bi.IsStream_in_PackStreams(st)) break; - int bond = _bi.FindBond_for_PackStream(st); + const int bond = _bi.FindBond_for_PackStream(st); if (bond < 0) throw 20150213; @@ -682,15 +682,15 @@ void CMixerST::SelectMainCoder(bool useFirst) break; if (firstNonFilter == -1 && !IsFilter_Vector[ci]) - firstNonFilter = ci; + firstNonFilter = (int)ci; - ci = _bi.Bonds[bond].UnpackIndex; + ci = _bi.Bonds[(unsigned)bond].UnpackIndex; } if (useFirst) ci = firstAllowed; else if (firstNonFilter >= 0) - ci = firstNonFilter; + ci = (unsigned)firstNonFilter; MainCoderIndex = ci; } @@ -919,7 +919,8 @@ HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo) _streamBinders.Clear(); FOR_VECTOR (i, _bi.Bonds) { - RINOK(_streamBinders.AddNew().CreateEvents()); + // RINOK(_streamBinders.AddNew().CreateEvents()); + _streamBinders.AddNew(); } return S_OK; } @@ -941,10 +942,13 @@ CCoder &CMixerMT::GetCoder(unsigned index) return _coders[index]; } -void CMixerMT::ReInit() +HRESULT CMixerMT::ReInit2() { FOR_VECTOR (i, _streamBinders) - _streamBinders[i].ReInit(); + { + RINOK(_streamBinders[i].Create_ReInit()); + } + return S_OK; } void CMixerMT::SelectMainCoder(bool useFirst) @@ -962,10 +966,10 @@ void CMixerMT::SelectMainCoder(bool useFirst) UInt32 st = _bi.Coder_to_Stream[ci]; if (_bi.IsStream_in_PackStreams(st)) break; - int bond = _bi.FindBond_for_PackStream(st); + const int bond = _bi.FindBond_for_PackStream(st); if (bond < 0) throw 20150213; - ci = _bi.Bonds[bond].UnpackIndex; + ci = _bi.Bonds[(unsigned)bond].UnpackIndex; } MainCoderIndex = ci; @@ -1012,9 +1016,9 @@ HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStr outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0; } - _streamBinders[i].CreateStreams( - &_coders[inCoderIndex].InStreams[inCoderStreamIndex], - &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]); + _streamBinders[i].CreateStreams2( + _coders[inCoderIndex].InStreams[inCoderStreamIndex], + _coders[outCoderIndex].OutStreams[outCoderStreamIndex]); CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize; _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize); @@ -1072,18 +1076,31 @@ HRESULT CMixerMT::Code( for (i = 0; i < _coders.Size(); i++) if (i != MainCoderIndex) { - RINOK(_coders[i].Create()); + const WRes wres = _coders[i].Create(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); } for (i = 0; i < _coders.Size(); i++) if (i != MainCoderIndex) - _coders[i].Start(); + { + const WRes wres = _coders[i].Start(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + } _coders[MainCoderIndex].Code(progress); + WRes wres = 0; for (i = 0; i < _coders.Size(); i++) if (i != MainCoderIndex) - _coders[i].WaitExecuteFinish(); + { + WRes wres2 = _coders[i].WaitExecuteFinish(); + if (wres == 0) + wres = wres2; + } + if (wres != 0) + return HRESULT_FROM_WIN32(wres); RINOK(ReturnIfError(E_ABORT)); RINOK(ReturnIfError(E_OUTOFMEMORY)); diff --git a/CPP/7zip/Archive/Common/CoderMixer2.h b/CPP/7zip/Archive/Common/CoderMixer2.h index 798411ab..f099ac3e 100644 --- a/CPP/7zip/Archive/Common/CoderMixer2.h +++ b/CPP/7zip/Archive/Common/CoderMixer2.h @@ -107,7 +107,7 @@ struct CBindInfo { FOR_VECTOR (i, Bonds) if (Bonds[i].PackIndex == packStream) - return i; + return (int)i; return -1; } @@ -115,7 +115,7 @@ struct CBindInfo { FOR_VECTOR (i, Bonds) if (Bonds[i].UnpackIndex == unpackStream) - return i; + return (int)i; return -1; } @@ -144,7 +144,7 @@ struct CBindInfo { FOR_VECTOR(i, PackStreams) if (PackStreams[i] == streamIndex) - return i; + return (int)i; return -1; } @@ -251,6 +251,7 @@ public: // , InternalPackSizeError(false) {} + virtual ~CMixer() {}; /* Sequence of calling: @@ -279,7 +280,7 @@ public: virtual void AddCoder(const CCreatedCoder &cod) = 0; virtual CCoder &GetCoder(unsigned index) = 0; virtual void SelectMainCoder(bool useFirst) = 0; - virtual void ReInit() = 0; + virtual HRESULT ReInit2() = 0; virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) = 0; virtual HRESULT Code( ISequentialInStream * const *inStreams, @@ -322,6 +323,8 @@ class CMixerST: public CMixer, public CMyUnknownImp { + CLASS_NO_COPY(CMixerST) + HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ UInt32 outStreamIndex, ISequentialInStream **inStreamRes); HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ @@ -345,7 +348,7 @@ public: virtual void AddCoder(const CCreatedCoder &cod); virtual CCoder &GetCoder(unsigned index); virtual void SelectMainCoder(bool useFirst); - virtual void ReInit(); + virtual HRESULT ReInit2(); virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); } virtual HRESULT Code( @@ -402,7 +405,7 @@ public: }; CCoderMT(): EncodeMode(false) {} - ~CCoderMT() { CVirtThread::WaitThreadFinish(); } + virtual ~CCoderMT() { CVirtThread::WaitThreadFinish(); } void Code(ICompressProgressInfo *progress); }; @@ -413,11 +416,14 @@ class CMixerMT: public CMixer, public CMyUnknownImp { + CLASS_NO_COPY(CMixerMT) + CObjectVector<CStreamBinder> _streamBinders; HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams); HRESULT ReturnIfError(HRESULT code); + // virtual ~CMixerMT() {}; public: CObjectVector<CCoderMT> _coders; @@ -427,7 +433,7 @@ public: virtual void AddCoder(const CCreatedCoder &cod); virtual CCoder &GetCoder(unsigned index); virtual void SelectMainCoder(bool useFirst); - virtual void ReInit(); + virtual HRESULT ReInit2(); virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); } virtual HRESULT Code( diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp index 77a35c74..972a766a 100644 --- a/CPP/7zip/Archive/Common/HandlerOut.cpp +++ b/CPP/7zip/Archive/Common/HandlerOut.cpp @@ -179,8 +179,8 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN } if (number > 64) return E_FAIL; - for (int j = _methods.Size(); j <= (int)number; j++) - _methods.Add(COneMethodInfo()); + for (unsigned j = _methods.Size(); j <= number; j++) + _methods.AddNew(); return _methods[number].ParseMethodFromPROPVARIANT(realName, value); } diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/CPP/7zip/Archive/Common/ItemNameUtils.cpp index d5093a24..905a863d 100644 --- a/CPP/7zip/Archive/Common/ItemNameUtils.cpp +++ b/CPP/7zip/Archive/Common/ItemNameUtils.cpp @@ -8,7 +8,10 @@ namespace NArchive { namespace NItemName { static const wchar_t kOsPathSepar = WCHAR_PATH_SEPARATOR; + +#if WCHAR_PATH_SEPARATOR != L'/' static const wchar_t kUnixPathSepar = L'/'; +#endif void ReplaceSlashes_OsToUnix #if WCHAR_PATH_SEPARATOR != L'/' @@ -44,17 +47,35 @@ UString GetOsPath_Remove_TailSlash(const UString &name) } -void ReplaceToOsSlashes_Remove_TailSlash(UString &name) -{ - if (!name.IsEmpty()) - { +void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool #if WCHAR_PATH_SEPARATOR != L'/' - name.Replace(kUnixPathSepar, kOsPathSepar); + useBackslashReplacement #endif - - if (name.Back() == kOsPathSepar) - name.DeleteBack(); + ) +{ + if (name.IsEmpty()) + return; + + #if WCHAR_PATH_SEPARATOR != L'/' + { + // name.Replace(kUnixPathSepar, kOsPathSepar); + const unsigned len = name.Len(); + for (unsigned i = 0; i < len; i++) + { + wchar_t c = name[i]; + if (c == L'/') + c = WCHAR_PATH_SEPARATOR; + else if (useBackslashReplacement && c == L'\\') + c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme + else + continue; + name.ReplaceOneCharAtPos(i, c); + } } + #endif + + if (name.Back() == kOsPathSepar) + name.DeleteBack(); } @@ -66,12 +87,15 @@ bool HasTailSlash(const AString &name, UINT { if (name.IsEmpty()) return false; - char c = + char c; #if defined(_WIN32) && !defined(UNDER_CE) - *CharPrevExA((WORD)codePage, name, name.Ptr(name.Len()), 0); - #else - name.Back(); + if (codePage != CP_UTF8) + c = *CharPrevExA((WORD)codePage, name, name.Ptr(name.Len()), 0); + else #endif + { + c = name.Back(); + } return (c == '/'); } diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.h b/CPP/7zip/Archive/Common/ItemNameUtils.h index 31150864..6a4d6c71 100644 --- a/CPP/7zip/Archive/Common/ItemNameUtils.h +++ b/CPP/7zip/Archive/Common/ItemNameUtils.h @@ -13,7 +13,7 @@ void ReplaceSlashes_OsToUnix(UString &name); UString GetOsPath(const UString &name); UString GetOsPath_Remove_TailSlash(const UString &name); -void ReplaceToOsSlashes_Remove_TailSlash(UString &name); +void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool useBackslashReplacement = false); bool HasTailSlash(const AString &name, UINT codePage); diff --git a/CPP/7zip/Archive/Common/MultiStream.cpp b/CPP/7zip/Archive/Common/MultiStream.cpp index 1de74afe..162fc928 100644 --- a/CPP/7zip/Archive/Common/MultiStream.cpp +++ b/CPP/7zip/Archive/Common/MultiStream.cpp @@ -36,7 +36,7 @@ STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) UInt64 localPos = _pos - s.GlobalOffset; if (localPos != s.LocalPos) { - RINOK(s.Stream->Seek(localPos, STREAM_SEEK_SET, &s.LocalPos)); + RINOK(s.Stream->Seek((Int64)localPos, STREAM_SEEK_SET, &s.LocalPos)); } UInt64 rem = s.Size - localPos; if (size > rem) @@ -60,9 +60,9 @@ STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosi } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _pos = offset; + _pos = (UInt64)offset; if (newPosition) - *newPosition = offset; + *newPosition = (UInt64)offset; return S_OK; } diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp index 77252938..ac26edf7 100644 --- a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp +++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp @@ -10,7 +10,7 @@ STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *pr if (_stream) result = _stream->Write(data, size, &size); if (_calculate) - Sha1_Update(&_sha, (const Byte *)data, size); + Sha1_Update(Sha(), (const Byte *)data, size); _size += size; if (processedSize) *processedSize = size; diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.h b/CPP/7zip/Archive/Common/OutStreamWithSha1.h index 41a84cd6..5a7bfef3 100644 --- a/CPP/7zip/Archive/Common/OutStreamWithSha1.h +++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.h @@ -5,6 +5,7 @@ #include "../../../../C/Sha1.h" +#include "../../../Common/MyBuffer2.h" #include "../../../Common/MyCom.h" #include "../../IStream.h" @@ -15,10 +16,16 @@ class COutStreamWithSha1: { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; - CSha1 _sha; + // CSha1 _sha; bool _calculate; + CAlignedBuffer _sha; + + CSha1 *Sha() { return (CSha1 *)(void *)(Byte *)_sha; } public: MY_UNKNOWN_IMP + + COutStreamWithSha1(): _sha(sizeof(CSha1)) {} + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } @@ -26,11 +33,11 @@ public: { _size = 0; _calculate = calculate; - Sha1_Init(&_sha); + Sha1_Init(Sha()); } - void InitSha1() { Sha1_Init(&_sha); } + void InitSha1() { Sha1_Init(Sha()); } UInt64 GetSize() const { return _size; } - void Final(Byte *digest) { Sha1_Final(&_sha, digest); } + void Final(Byte *digest) { Sha1_Final(Sha(), digest); } }; #endif diff --git a/CPP/7zip/Archive/CpioHandler.cpp b/CPP/7zip/Archive/CpioHandler.cpp index b8fb530f..ffdab16c 100644 --- a/CPP/7zip/Archive/CpioHandler.cpp +++ b/CPP/7zip/Archive/CpioHandler.cpp @@ -131,7 +131,7 @@ enum EErrorType { k_ErrorType_OK, k_ErrorType_Corrupted, - k_ErrorType_UnexpectedEnd, + k_ErrorType_UnexpectedEnd }; struct CInArchive @@ -218,7 +218,7 @@ API_FUNC_static_IsArc IsArc_Cpio(const Byte *p, size_t size) { if (size < k_OctRecord_Size) return k_IsArc_Res_NEED_MORE; - for (int i = 6; i < k_OctRecord_Size; i++) + for (unsigned i = 6; i < k_OctRecord_Size; i++) { char c = p[i]; if (c < '0' || c > '7') @@ -231,7 +231,7 @@ API_FUNC_static_IsArc IsArc_Cpio(const Byte *p, size_t size) { if (size < k_HexRecord_Size) return k_IsArc_Res_NEED_MORE; - for (int i = 6; i < k_HexRecord_Size; i++) + for (unsigned i = 6; i < k_HexRecord_Size; i++) { char c = p[i]; if ((c < '0' || c > '9') && @@ -268,7 +268,9 @@ API_FUNC_static_IsArc IsArc_Cpio(const Byte *p, size_t size) if (nameSize > (1 << 8)) return k_IsArc_Res_NO; } - if (numLinks == 0 || numLinks >= (1 << 10)) + // 20.03: some cpio files have (numLinks == 0). + // if (numLinks == 0) return k_IsArc_Res_NO; + if (numLinks >= (1 << 10)) return k_IsArc_Res_NO; if (nameSize == 0 || nameSize > kNameSizeMax) return k_IsArc_Res_NO; @@ -462,6 +464,9 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { case k_ErrorType_UnexpectedEnd: v |= kpv_ErrorFlags_UnexpectedEnd; break; case k_ErrorType_Corrupted: v |= kpv_ErrorFlags_HeadersError; break; + case k_ErrorType_OK: + default: + break; } prop = v; break; @@ -565,23 +570,30 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb { // Read tailing zeros. // Most of cpio files use 512-bytes aligned zeros - UInt64 pos = arc.Processed; - const UInt32 kTailSize_MAX = 1 << 9; + // rare case: 4K/8K aligment is possible also + const unsigned kTailSize_MAX = 1 << 9; Byte buf[kTailSize_MAX]; - UInt32 rem = (kTailSize_MAX - (UInt32)pos) & (kTailSize_MAX - 1); - if (rem != 0) + unsigned pos = (unsigned)arc.Processed & (kTailSize_MAX - 1); + if (pos != 0) // use this check to support 512 bytes alignment only + for (;;) { - rem++; // we need to see that it's end of file + unsigned rem = kTailSize_MAX - pos; size_t processed = rem; - RINOK(ReadStream(stream, buf, &processed)); - if (processed < rem) - { - unsigned i; - for (i = 0; i < processed && buf[i] == 0; i++); - if (i == processed) - _phySize += processed; - } + RINOK(ReadStream(stream, buf + pos, &processed)); + if (processed != rem) + break; + + for (; pos < kTailSize_MAX && buf[pos] == 0; pos++) + {} + if (pos != kTailSize_MAX) + break; + _phySize += processed; + pos = 0; + + // use break to support 512 bytes alignment zero tail + // don't use break to support 512*n bytes alignment zero tail + break; } } @@ -622,7 +634,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val UString res; bool needConvert = true; #ifdef _WIN32 - if (ConvertUTF8ToUnicode(item.Name, res)) + // if ( + ConvertUTF8ToUnicode(item.Name, res); + // ) needConvert = false; #endif if (needConvert) diff --git a/CPP/7zip/Archive/DllExports2.cpp b/CPP/7zip/Archive/DllExports2.cpp index 10889e75..967a7cbf 100644 --- a/CPP/7zip/Archive/DllExports2.cpp +++ b/CPP/7zip/Archive/DllExports2.cpp @@ -22,11 +22,24 @@ #include "IArchive.h" -HINSTANCE g_hInstance; +#ifdef _WIN32 + +#if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) #define NT_CHECK_FAIL_ACTION return FALSE; +#endif + +HINSTANCE g_hInstance; + +extern "C" +BOOL WINAPI DllMain( + #ifdef UNDER_CE + HANDLE + #else + HINSTANCE + #endif + hInstance, DWORD dwReason, LPVOID /*lpReserved*/); -#ifdef _WIN32 extern "C" BOOL WINAPI DllMain( #ifdef UNDER_CE @@ -50,7 +63,22 @@ BOOL WINAPI DllMain( */ return TRUE; } -#endif + +#else // _WIN32 + +#include "../../Common/StringConvert.h" +// #include <stdio.h> + +// STDAPI LibStartup(); +static __attribute__((constructor)) void Init_ForceToUTF8(); +static __attribute__((constructor)) void Init_ForceToUTF8() +{ + g_ForceToUTF8 = IsNativeUTF8(); + // printf("\nDLLExports2.cpp::Init_ForceToUTF8 =%d\n", g_ForceToUTF8 ? 1 : 0); +} + +#endif // _WIN32 + DEFINE_GUID(CLSID_CArchiveHandler, k_7zip_GUID_Data1, @@ -62,6 +90,7 @@ STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateHasher(const GUID *clsid, IHasher **hasher); STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject); +STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) { // COM_TRY_BEGIN @@ -76,16 +105,20 @@ STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) // COM_TRY_END } +STDAPI SetLargePageMode(); STDAPI SetLargePageMode() { #if defined(_7ZIP_LARGE_PAGES) + #ifdef _WIN32 SetLargePageSize(); #endif + #endif return S_OK; } extern bool g_CaseSensitive; +STDAPI SetCaseSensitive(Int32 caseSensitive); STDAPI SetCaseSensitive(Int32 caseSensitive) { g_CaseSensitive = (caseSensitive != 0); @@ -96,6 +129,7 @@ STDAPI SetCaseSensitive(Int32 caseSensitive) CExternalCodecs g_ExternalCodecs; +STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo); STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo) { COM_TRY_BEGIN @@ -114,6 +148,7 @@ STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo) #else +STDAPI SetCodecs(ICompressCodecsInfo *); STDAPI SetCodecs(ICompressCodecsInfo *) { return S_OK; diff --git a/CPP/7zip/Archive/DmgHandler.cpp b/CPP/7zip/Archive/DmgHandler.cpp index d9fe6016..a08dcac1 100644 --- a/CPP/7zip/Archive/DmgHandler.cpp +++ b/CPP/7zip/Archive/DmgHandler.cpp @@ -33,99 +33,22 @@ #define Get32(p) GetBe32(p) #define Get64(p) GetBe64(p) -static const Byte k_Base64Table[256] = -{ - 66,77,77,77,77,77,77,77,77,65,65,77,77,65,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 65,77,77,77,77,77,77,77,77,77,77,62,77,77,77,63, - 52,53,54,55,56,57,58,59,60,61,77,77,77,64,77,77, - 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, - 15,16,17,18,19,20,21,22,23,24,25,77,77,77,77,77, - 77,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, - 41,42,43,44,45,46,47,48,49,50,51,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77 -}; - -static Byte *Base64ToBin(Byte *dest, const char *src) -{ - UInt32 val = 1; - - for (;;) - { - UInt32 c = k_Base64Table[(Byte)(*src++)]; - - if (c < 64) - { - val = (val << 6) | c; - if ((val & ((UInt32)1 << 24)) == 0) - continue; - dest[0] = (Byte)(val >> 16); - dest[1] = (Byte)(val >> 8); - dest[2] = (Byte)(val); - dest += 3; - val = 1; - continue; - } - - if (c == 65) // space - continue; - - if (c == 64) // '=' - break; - - if (c == 66 && val == 1) // end of string - return dest; - - return NULL; - } - - if (val < (1 << 12)) - return NULL; - - if (val & (1 << 18)) - { - *dest++ = (Byte)(val >> 10); - *dest++ = (Byte)(val >> 2); - } - else if (k_Base64Table[(Byte)(*src++)] != 64) // '=' - return NULL; - else - *dest++ = (Byte)(val >> 4); - - for (;;) - { - Byte c = k_Base64Table[(Byte)(*src++)]; - if (c == 65) // space - continue; - if (c == 66) // end of string - return dest; - return NULL; - } -} - +Byte *Base64ToBin(Byte *dest, const char *src); namespace NArchive { namespace NDmg { -enum -{ - METHOD_ZERO_0 = 0, - METHOD_COPY = 1, - METHOD_ZERO_2 = 2, // without file CRC calculation - METHOD_ADC = 0x80000004, - METHOD_ZLIB = 0x80000005, - METHOD_BZIP2 = 0x80000006, - METHOD_LZFSE = 0x80000007, - METHOD_COMMENT = 0x7FFFFFFE, // is used to comment "+beg" and "+end" in extra field. - METHOD_END = 0xFFFFFFFF -}; + +static const UInt32 METHOD_ZERO_0 = 0; +static const UInt32 METHOD_COPY = 1; +static const UInt32 METHOD_ZERO_2 = 2; // without file CRC calculation +static const UInt32 METHOD_ADC = 0x80000004; +static const UInt32 METHOD_ZLIB = 0x80000005; +static const UInt32 METHOD_BZIP2 = 0x80000006; +static const UInt32 METHOD_LZFSE = 0x80000007; +static const UInt32 METHOD_COMMENT = 0x7FFFFFFE; // is used to comment "+beg" and "+end" in extra field. +static const UInt32 METHOD_END = 0xFFFFFFFF; + struct CBlock { @@ -266,7 +189,7 @@ void CMethods::GetString(AString &res) const for (i = 0; i < Types.Size(); i++) { - UInt32 type = Types[i]; + const UInt32 type = Types[i]; if (type == METHOD_COMMENT || type == METHOD_END) continue; char buf[16]; @@ -407,6 +330,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidWarning: if (_masterCrcError) prop = "Master CRC error"; + break; case kpidWarningFlags: { @@ -727,7 +651,8 @@ HRESULT CHandler::Open2(IInStream *stream) if (xmlPair2.Len > len) xmlPair2.Len = len; CByteBuffer buf2; - if (ReadData(stream, xmlPair2, buf2) != S_OK + if (xmlPair2.Len < len + || ReadData(stream, xmlPair2, buf2) != S_OK || memcmp(buf2, sz, len) != 0) { // if absolute offset is not OK, probably it's archive with offset @@ -1054,7 +979,9 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } +#ifdef DMG_SHOW_RAW #define RAW_PREFIX "raw" STRING_PATH_SEPARATOR +#endif STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { @@ -1608,7 +1535,7 @@ public: }; -unsigned FindBlock(const CRecordVector<CBlock> &blocks, UInt64 pos) +static unsigned FindBlock(const CRecordVector<CBlock> &blocks, UInt64 pos) { unsigned left = 0, right = blocks.Size(); for (;;) @@ -1762,8 +1689,8 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) } const CBlock &block = File->Blocks[_latestBlock]; - UInt64 offset = _virtPos - block.UnpPos; - UInt64 rem = block.UnpSize - offset; + const UInt64 offset = _virtPos - block.UnpPos; + const UInt64 rem = block.UnpSize - offset; if (size > rem) size = (UInt32)rem; @@ -1777,7 +1704,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) else if (block.IsZeroMethod()) memset(data, 0, size); else if (size != 0) - memcpy(data, _chunks[_latestChunk].Buf + offset, size); + memcpy(data, _chunks[_latestChunk].Buf + (size_t)offset, size); _virtPos += size; if (processedSize) diff --git a/CPP/7zip/Archive/ElfHandler.cpp b/CPP/7zip/Archive/ElfHandler.cpp index c5ce279e..efcde95d 100644 --- a/CPP/7zip/Archive/ElfHandler.cpp +++ b/CPP/7zip/Archive/ElfHandler.cpp @@ -226,6 +226,7 @@ void CSegment::Parse(const Byte *p, bool mode64, bool be) // Section types +/* #define SHT_NULL 0 #define SHT_PROGBITS 1 #define SHT_SYMTAB 2 @@ -234,7 +235,9 @@ void CSegment::Parse(const Byte *p, bool mode64, bool be) #define SHT_HASH 5 #define SHT_DYNAMIC 6 #define SHT_NOTE 7 +*/ #define SHT_NOBITS 8 +/* #define SHT_REL 9 #define SHT_SHLIB 10 #define SHT_DYNSYM 11 @@ -245,7 +248,7 @@ void CSegment::Parse(const Byte *p, bool mode64, bool be) #define SHT_PREINIT_ARRAY 16 #define SHT_GROUP 17 #define SHT_SYMTAB_SHNDX 18 - +*/ static const CUInt32PCharPair g_SectTypes[] = { @@ -633,11 +636,11 @@ static const CUInt32PCharPair g_MIPS_Flags[] = }; -#define ET_NONE 0 +// #define ET_NONE 0 #define ET_REL 1 -#define ET_EXEC 2 +// #define ET_EXEC 2 #define ET_DYN 3 -#define ET_CORE 4 +// #define ET_CORE 4 static const char * const g_Types[] = { diff --git a/CPP/7zip/Archive/ExtHandler.cpp b/CPP/7zip/Archive/ExtHandler.cpp index db65fbea..e9808aac 100644 --- a/CPP/7zip/Archive/ExtHandler.cpp +++ b/CPP/7zip/Archive/ExtHandler.cpp @@ -99,6 +99,8 @@ static UInt32 Crc16Calc(Byte const *data, size_t size) #define EXT4_GOOD_OLD_INODE_SIZE 128 +#define EXT_NODE_SIZE_MIN 128 + // inodes numbers @@ -436,9 +438,9 @@ bool CHeader::Parse(const Byte *p) LE_16 (0x58, InodeSize); if (FirstInode < k_INODE_GOOD_OLD_FIRST) return false; - if (InodeSize > (UInt32)1 << BlockBits) - return false; - if (GetLog(InodeSize) < 0) + if (InodeSize > ((UInt32)1 << BlockBits) + || InodeSize < EXT_NODE_SIZE_MIN + || GetLog(InodeSize) < 0) return false; } @@ -603,7 +605,7 @@ struct CExtent if (Len > (UInt32)0x8000) { IsInited = false; - Len -= (UInt32)0x8000; + Len = (UInt16)(Len - (UInt32)0x8000); } LE_32 (0x08, PhyStart); UInt16 hi; @@ -628,8 +630,8 @@ struct CNode int DirIndex; // in _dirs[] UInt16 Mode; - UInt16 Uid; - UInt16 Gid; + UInt32 Uid; // fixed 21.02 + UInt32 Gid; // fixed 21.02 // UInt16 Checksum; UInt64 FileSize; @@ -730,6 +732,8 @@ bool CNode::Parse(const Byte *p, const CHeader &_h) if (_h.InodeSize > 128) { + // InodeSize is power of 2, so the following check is not required: + // if (_h.InodeSize < 128 + 2) return false; UInt16 extra_isize; LE_16 (0x80, extra_isize); if (128 + extra_isize > _h.InodeSize) @@ -842,7 +846,7 @@ class CHandler: } - const int GetParentAux(const CItem &item) const + int GetParentAux(const CItem &item) const { if (item.Node < _h.FirstInode && _auxSysIndex >= 0) return _auxSysIndex; @@ -931,7 +935,7 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned iNodeDir) return S_FALSE; if (_isUTF) - _isUTF = CheckUTF8(item.Name); + _isUTF = CheckUTF8_AString(item.Name); if (iNode == 0) { @@ -1201,7 +1205,7 @@ HRESULT CHandler::Open2(IInStream *inStream) UInt32 numNodes = _h.InodesPerGroup; if (numNodes > _h.NumInodes) numNodes = _h.NumInodes; - size_t nodesDataSize = (size_t)numNodes * _h.InodeSize; + const size_t nodesDataSize = (size_t)numNodes * _h.InodeSize; if (nodesDataSize / _h.InodeSize != numNodes) return S_FALSE; @@ -1213,7 +1217,7 @@ HRESULT CHandler::Open2(IInStream *inStream) return S_FALSE; } - UInt32 numReserveInodes = _h.NumInodes - _h.NumFreeInodes + 1; + const UInt32 numReserveInodes = _h.NumInodes - _h.NumFreeInodes + 1; // numReserveInodes = _h.NumInodes + 1; if (numReserveInodes != 0) { @@ -1348,7 +1352,8 @@ HRESULT CHandler::Open2(IInStream *inStream) RINOK(CheckProgress()); } - if (_nodes[_refs[k_INODE_ROOT]].ParentNode != k_INODE_ROOT) + int ref = _refs[k_INODE_ROOT]; + if (ref < 0 || _nodes[ref].ParentNode != k_INODE_ROOT) return S_FALSE; } diff --git a/CPP/7zip/Archive/FatHandler.cpp b/CPP/7zip/Archive/FatHandler.cpp index bf6053e0..1cbc8508 100644 --- a/CPP/7zip/Archive/FatHandler.cpp +++ b/CPP/7zip/Archive/FatHandler.cpp @@ -682,7 +682,7 @@ HRESULT CDatabase::Open() RINOK(ReadStream_FALSE(InStream, byteBuf, readSize)); NumCurUsedBytes += readSize; - const UInt32 *src = (const UInt32 *)(const Byte *)byteBuf; + const UInt32 *src = (const UInt32 *)(const void *)(const Byte *)byteBuf; UInt32 *dest = Fat + i; if (numFreeClustersDefined) for (UInt32 j = 0; j < size; j++) diff --git a/CPP/7zip/Archive/FlvHandler.cpp b/CPP/7zip/Archive/FlvHandler.cpp index 1f52f60b..97a7c268 100644 --- a/CPP/7zip/Archive/FlvHandler.cpp +++ b/CPP/7zip/Archive/FlvHandler.cpp @@ -23,14 +23,14 @@ ((UInt32)((const Byte *)(p))[1] << 8) | \ ((const Byte *)(p))[2] ) -#define Get16(p) GetBe16(p) +// #define Get16(p) GetBe16(p) #define Get24(p) GetBe24(p) #define Get32(p) GetBe32(p) namespace NArchive { namespace NFlv { -static const UInt32 kFileSizeMax = (UInt32)1 << 30; +// static const UInt32 kFileSizeMax = (UInt32)1 << 30; static const UInt32 kNumChunksMax = (UInt32)1 << 23; static const UInt32 kTagHeaderSize = 11; diff --git a/CPP/7zip/Archive/GptHandler.cpp b/CPP/7zip/Archive/GptHandler.cpp index a86ad37c..7b3d23bb 100644 --- a/CPP/7zip/Archive/GptHandler.cpp +++ b/CPP/7zip/Archive/GptHandler.cpp @@ -333,16 +333,25 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { case kpidPath: { + // Windows BDP partitions can have identical names. + // So we add the partition number at front UString s; - for (unsigned i = 0; i < kNameLen; i++) + s.Add_UInt32(index); { - wchar_t c = (wchar_t)Get16(item.Name + i * 2); - if (c == 0) - break; - s += c; + UString s2; + for (unsigned i = 0; i < kNameLen; i++) + { + wchar_t c = (wchar_t)Get16(item.Name + i * 2); + if (c == 0) + break; + s2 += c; + } + if (!s2.IsEmpty()) + { + s += '.'; + s += s2; + } } - if (s.IsEmpty()) - s.Add_UInt32(index); { s += '.'; const char *ext = NULL; diff --git a/CPP/7zip/Archive/GzHandler.cpp b/CPP/7zip/Archive/GzHandler.cpp index 130f8b35..0054840d 100644 --- a/CPP/7zip/Archive/GzHandler.cpp +++ b/CPP/7zip/Archive/GzHandler.cpp @@ -45,7 +45,7 @@ namespace NGz { namespace NFlags { - const Byte kIsText = 1 << 0; + // const Byte kIsText = 1 << 0; const Byte kCrc = 1 << 1; const Byte kExtra = 1 << 2; const Byte kName = 1 << 3; @@ -234,7 +234,8 @@ static UInt32 Is_Deflate(const Byte *p, size_t size) return k_IsArc_Res_NO; if (size < 4) return k_IsArc_Res_NEED_MORE; - if (GetUi16(p) != (UInt16)~GetUi16(p + 2)) + UInt16 r = (UInt16)~GetUi16(p + 2); + if (GetUi16(p) != r) return k_IsArc_Res_NO; } else if (type == 2) @@ -248,8 +249,8 @@ static UInt32 Is_Deflate(const Byte *p, size_t size) return k_IsArc_Res_YES; } -static unsigned kNameMaxLen = 1 << 12; -static unsigned kCommentMaxLen = 1 << 16; +static const unsigned kNameMaxLen = 1 << 12; +static const unsigned kCommentMaxLen = 1 << 16; API_FUNC_static_IsArc IsArc_Gz(const Byte *p, size_t size) { @@ -962,7 +963,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt UString name = prop.bstrVal; int slashPos = name.ReverseFind_PathSepar(); if (slashPos >= 0) - name.DeleteFrontal(slashPos + 1); + name.DeleteFrontal((unsigned)(slashPos + 1)); newItem.Name = UnicodeStringToMultiByte(name, CP_ACP); if (!newItem.Name.IsEmpty()) newItem.Flags |= NFlags::kName; @@ -1019,7 +1020,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt newItem.WriteHeader(outStream); offset += _headerSize; } - RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); + RINOK(_stream->Seek((Int64)offset, STREAM_SEEK_SET, NULL)); return NCompress::CopyStream(_stream, outStream, progress); diff --git a/CPP/7zip/Archive/HandlerCont.cpp b/CPP/7zip/Archive/HandlerCont.cpp index c2d5c70c..22a8c4a9 100644 --- a/CPP/7zip/Archive/HandlerCont.cpp +++ b/CPP/7zip/Archive/HandlerCont.cpp @@ -269,7 +269,7 @@ HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 for (;;) { UInt32 size = 0; - HRESULT(stream->Read(buf, kBufSize, &size)); + RINOK(stream->Read(buf, kBufSize, &size)); if (size == 0) return S_OK; for (UInt32 i = 0; i < size; i++) diff --git a/CPP/7zip/Archive/HfsHandler.cpp b/CPP/7zip/Archive/HfsHandler.cpp index ca1d7bda..57313280 100644 --- a/CPP/7zip/Archive/HfsHandler.cpp +++ b/CPP/7zip/Archive/HfsHandler.cpp @@ -275,7 +275,7 @@ struct CItem CItem(): UseAttr(false), UseInlineData(false) {} bool IsDir() const { return Type == RECORD_TYPE_FOLDER; } - const CFork &GetFork(bool isResource) const { return (CFork & )*(isResource ? &ResourceFork: &DataFork ); } + const CFork &GetFork(bool isResource) const { return (const CFork & )*(isResource ? &ResourceFork: &DataFork ); } }; struct CAttr @@ -320,12 +320,14 @@ public: UInt64 SpecOffset; UInt64 PhySize; UInt64 PhySize2; + UInt64 ArcFileSize; void Clear() { SpecOffset = 0; PhySize = 0; PhySize2 = 0; + ArcFileSize = 0; HeadersError = false; ThereAreAltStreams = false; // CaseSensetive = false; @@ -440,7 +442,10 @@ HRESULT CDatabase::ReadFile(const CFork &fork, CByteBuffer &buf, IInStream *inSt { if (fork.NumBlocks >= Header.NumBlocks) return S_FALSE; - size_t totalSize = (size_t)fork.NumBlocks << Header.BlockSizeLog; + if ((ArcFileSize >> Header.BlockSizeLog) + 1 < fork.NumBlocks) + return S_FALSE; + + const size_t totalSize = (size_t)fork.NumBlocks << Header.BlockSizeLog; if ((totalSize >> Header.BlockSizeLog) != fork.NumBlocks) return S_FALSE; buf.Alloc(totalSize); @@ -473,20 +478,36 @@ struct CNodeDescriptor // Byte Height; unsigned NumRecords; - bool CheckNumRecords(unsigned nodeSizeLog) - { - return (kNodeDescriptor_Size + ((UInt32)NumRecords + 1) * 2 <= ((UInt32)1 << nodeSizeLog)); - } - void Parse(const Byte *p); + bool Parse(const Byte *p, unsigned nodeSizeLog); }; -void CNodeDescriptor::Parse(const Byte *p) + +bool CNodeDescriptor::Parse(const Byte *p, unsigned nodeSizeLog) { fLink = Get32(p); // bLink = Get32(p + 4); Kind = p[8]; // Height = p[9]; NumRecords = Get16(p + 10); + + const size_t nodeSize = (size_t)1 << nodeSizeLog; + if (kNodeDescriptor_Size + ((UInt32)NumRecords + 1) * 2 > nodeSize) + return false; + const size_t limit = nodeSize - ((UInt32)NumRecords + 1) * 2; + + p += nodeSize - 2; + + for (unsigned i = 0; i < NumRecords; i++) + { + const UInt32 offs = Get16(p); + p -= 2; + const UInt32 offsNext = Get16(p); + if (offs < kNodeDescriptor_Size + || offs >= offsNext + || offsNext > limit) + return false; + } + return true; } struct CHeaderRec @@ -576,7 +597,7 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec if (node == 0) return S_OK; - CByteBuffer usedBuf(hr.TotalNodes); + CByteArr usedBuf(hr.TotalNodes); memset(usedBuf, 0, hr.TotalNodes); while (node != 0) @@ -585,10 +606,9 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec return S_FALSE; usedBuf[node] = 1; - size_t nodeOffset = (size_t)node << hr.NodeSizeLog; + const size_t nodeOffset = (size_t)node << hr.NodeSizeLog; CNodeDescriptor desc; - desc.Parse(p + nodeOffset); - if (!desc.CheckNumRecords(hr.NodeSizeLog)) + if (!desc.Parse(p + nodeOffset, hr.NodeSizeLog)) return S_FALSE; if (desc.Kind != kNodeType_Leaf) return S_FALSE; @@ -597,18 +617,16 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec for (unsigned i = 0; i < desc.NumRecords; i++) { - const UInt32 nodeSize = (UInt32)1 << hr.NodeSizeLog; - const UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2); - const UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2); - if (offs > nodeSize || offsNext > nodeSize) - return S_FALSE; - UInt32 recSize = offsNext - offs; + const UInt32 nodeSize = (1 << hr.NodeSizeLog); + const Byte *r = p + nodeOffset + nodeSize - i * 2; + const UInt32 offs = Get16(r - 2); + UInt32 recSize = Get16(r - 4) - offs; const unsigned kKeyLen = 10; if (recSize != 2 + kKeyLen + kNumFixedExtents * 8) return S_FALSE; - const Byte *r = p + nodeOffset + offs; + r = p + nodeOffset + offs; if (Get16(r) != kKeyLen) return S_FALSE; @@ -717,7 +735,7 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe if (node == 0) return S_OK; - CByteBuffer usedBuf(hr.TotalNodes); + CByteArr usedBuf(hr.TotalNodes); memset(usedBuf, 0, hr.TotalNodes); CFork resFork; @@ -728,10 +746,9 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe return S_FALSE; usedBuf[node] = 1; - size_t nodeOffset = (size_t)node << hr.NodeSizeLog; + const size_t nodeOffset = (size_t)node << hr.NodeSizeLog; CNodeDescriptor desc; - desc.Parse(p + nodeOffset); - if (!desc.CheckNumRecords(hr.NodeSizeLog)) + if (!desc.Parse(p + nodeOffset, hr.NodeSizeLog)) return S_FALSE; if (desc.Kind != kNodeType_Leaf) return S_FALSE; @@ -739,19 +756,14 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe for (unsigned i = 0; i < desc.NumRecords; i++) { const UInt32 nodeSize = (1 << hr.NodeSizeLog); - const UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2); - const UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2); - UInt32 recSize = offsNext - offs; - if (offs >= nodeSize - || offsNext > nodeSize - || offsNext < offs) - return S_FALSE; - + const Byte *r = p + nodeOffset + nodeSize - i * 2; + const UInt32 offs = Get16(r - 2); + UInt32 recSize = Get16(r - 4) - offs; const unsigned kHeadSize = 14; if (recSize < kHeadSize) return S_FALSE; - const Byte *r = p + nodeOffset + offs; + r = p + nodeOffset + offs; UInt32 keyLen = Get16(r); // UInt16 pad = Get16(r + 2); @@ -805,7 +817,7 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe if (progress && (i & 0xFFF) == 0) { - UInt64 numFiles = 0; + const UInt64 numFiles = 0; RINOK(progress->SetCompleted(&numFiles, NULL)); } } @@ -873,13 +885,6 @@ bool CDatabase::Parse_decmpgfs(const CAttr &attr, CItem &item, bool &skip) HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents> *overflowExtentsArray, IInStream *inStream, IArchiveOpenCallback *progress) { - unsigned reserveSize = (unsigned)(Header.NumFolders + 1 + Header.NumFiles); - Items.ClearAndReserve(reserveSize); - Refs.ClearAndReserve(reserveSize); - - CRecordVector<CIdIndexPair> IdToIndexMap; - IdToIndexMap.ClearAndReserve(reserveSize); - CByteBuffer buf; RINOK(ReadFile(fork, buf, inStream)); const Byte *p = (const Byte *)buf; @@ -888,10 +893,24 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents // nodeDesc.Parse(p); CHeaderRec hr; RINOK(hr.Parse2(buf)); - + + CRecordVector<CIdIndexPair> IdToIndexMap; + + const unsigned reserveSize = (unsigned)(Header.NumFolders + 1 + Header.NumFiles); + + const unsigned kBasicRecSize = 0x58; + const unsigned kMinRecSize = kBasicRecSize + 10; + + if ((UInt64)reserveSize * kMinRecSize < buf.Size()) + { + Items.ClearAndReserve(reserveSize); + Refs.ClearAndReserve(reserveSize); + IdToIndexMap.ClearAndReserve(reserveSize); + } + // CaseSensetive = (Header.IsHfsX() && hr.KeyCompareType == 0xBC); - CByteBuffer usedBuf(hr.TotalNodes); + CByteArr usedBuf(hr.TotalNodes); memset(usedBuf, 0, hr.TotalNodes); CFork resFork; @@ -908,8 +927,7 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents const size_t nodeOffset = (size_t)node << hr.NodeSizeLog; CNodeDescriptor desc; - desc.Parse(p + nodeOffset); - if (!desc.CheckNumRecords(hr.NodeSizeLog)) + if (!desc.Parse(p + nodeOffset, hr.NodeSizeLog)) return S_FALSE; if (desc.Kind != kNodeType_Leaf) return S_FALSE; @@ -917,16 +935,13 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents for (unsigned i = 0; i < desc.NumRecords; i++) { const UInt32 nodeSize = (1 << hr.NodeSizeLog); - const UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2); - const UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2); - UInt32 recSize = offsNext - offs; - if (offs >= nodeSize - || offsNext > nodeSize - || offsNext < offs - || recSize < 6) + const Byte *r = p + nodeOffset + nodeSize - i * 2; + const UInt32 offs = Get16(r - 2); + UInt32 recSize = Get16(r - 4) - offs; + if (recSize < 6) return S_FALSE; - const Byte *r = p + nodeOffset + offs; + r = p + nodeOffset + offs; UInt32 keyLen = Get16(r); UInt32 parentID = Get32(r + 2); if (keyLen < 6 || (keyLen & 1) != 0 || keyLen + 2 > recSize) @@ -952,7 +967,6 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents type != RECORD_TYPE_FILE) continue; - const unsigned kBasicRecSize = 0x58; if (recSize < kBasicRecSize) return S_FALSE; @@ -1042,7 +1056,7 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents } if (progress && (Items.Size() & 0xFFF) == 0) { - UInt64 numItems = Items.Size(); + const UInt64 numItems = Items.Size(); RINOK(progress->SetCompleted(&numItems, NULL)); } } @@ -1286,9 +1300,12 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress) if (h.NumFolders > ((UInt32)1 << 29) || h.NumFiles > ((UInt32)1 << 30)) return S_FALSE; + + RINOK(inStream->Seek(0, STREAM_SEEK_END, &ArcFileSize)); + if (progress) { - UInt64 numFiles = (UInt64)h.NumFiles + h.NumFolders + 1; + const UInt64 numFiles = (UInt64)h.NumFiles + h.NumFolders + 1; RINOK(progress->SetTotal(&numFiles, NULL)); } @@ -1313,13 +1330,6 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress) h.VolID = Get64(p + 0x68); */ - /* - UInt64 endPos; - RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); - if ((endPos >> h.BlockSizeLog) < h.NumBlocks) - return S_FALSE; - */ - ResFileName = kResFileName; CFork extentsFork, catalogFork, attrFork; @@ -1499,7 +1509,7 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data else s = &Items[ref.ItemIndex].Name; *data = (const wchar_t *)(*s); - *dataSize = (s->Len() + 1) * sizeof(wchar_t); + *dataSize = (s->Len() + 1) * (UInt32)sizeof(wchar_t); *propType = PROP_DATA_TYPE_wchar_t_PTR_Z_LE; return S_OK; } @@ -1700,7 +1710,7 @@ HRESULT CHandler::ExtractZlibFile( } outPos += blockSize; - UInt64 progressPos = progressStart + outPos; + const UInt64 progressPos = progressStart + outPos; RINOK(extractCallback->SetCompleted(&progressPos)); } @@ -1884,7 +1894,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } pos += cur; extentRem -= cur; - UInt64 processed = currentTotalSize + pos; + const UInt64 processed = currentTotalSize + pos; RINOK(extractCallback->SetCompleted(&processed)); } } diff --git a/CPP/7zip/Archive/IArchive.h b/CPP/7zip/Archive/IArchive.h index 7d7256c9..8290c735 100644 --- a/CPP/7zip/Archive/IArchive.h +++ b/CPP/7zip/Archive/IArchive.h @@ -10,6 +10,30 @@ #define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x) #define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x) +/* +How the function in 7-Zip returns object for output parameter via pointer + +1) The caller sets the value of variable before function call: + PROPVARIANT : vt = VT_EMPTY + BSTR : NULL + IUnknown* and derived interfaces : NULL + another scalar types : any non-initialized value is allowed + +2) The callee in current 7-Zip code now can free input object for output parameter: + PROPVARIANT : the callee calls VariantClear(propvaiant_ptr) for input + value stored in variable + another types : the callee ignores stored value. + +3) The callee writes new value to variable for output parameter and + returns execution to caller. + +4) The caller must free or release object returned by the callee: + PROPVARIANT : VariantClear(&propvaiant) + BSTR : SysFreeString(bstr) + IUnknown* and derived interfaces : if (ptr) ptr->Relase() +*/ + + namespace NFileTimeType { enum EEnum @@ -34,6 +58,7 @@ namespace NArcInfoFlags const UInt32 kPreArc = 1 << 9; // such archive can be stored before real archive (like SFX stub) const UInt32 kSymLinks = 1 << 10; // the handler supports symbolic links const UInt32 kHardLinks = 1 << 11; // the handler supports hard links + const UInt32 kByExtOnlyOpen = 1 << 12; // call handler only if file extension matches } namespace NArchive @@ -106,7 +131,7 @@ namespace NArchive enum { kOK = 0 - , // kError + // , kError }; } } @@ -137,13 +162,13 @@ IArchiveExtractCallback::GetStream() Int32 askExtractMode (Extract::NAskMode) if (askMode != NExtract::NAskMode::kExtract) { - then the callee can not real stream: (*inStream == NULL) + then the callee doesn't write data to stream: (*outStream == NULL) } Out: - (*inStream == NULL) - for directories - (*inStream == NULL) - if link (hard link or symbolic link) was created - if (*inStream == NULL && askMode == NExtract::NAskMode::kExtract) + (*outStream == NULL) - for directories + (*outStream == NULL) - if link (hard link or symbolic link) was created + if (*outStream == NULL && askMode == NExtract::NAskMode::kExtract) { then the caller must skip extracting of that file. } diff --git a/CPP/7zip/Archive/IhexHandler.cpp b/CPP/7zip/Archive/IhexHandler.cpp index 00ff80a7..05453ee6 100644 --- a/CPP/7zip/Archive/IhexHandler.cpp +++ b/CPP/7zip/Archive/IhexHandler.cpp @@ -121,9 +121,9 @@ static int Parse(const Byte *p) #define kType_Data 0 #define kType_Eof 1 #define kType_Seg 2 -#define kType_CsIp 3 +// #define kType_CsIp 3 #define kType_High 4 -#define kType_Ip32 5 +// #define kType_Ip32 5 #define kType_MAX 5 diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp index 2230cd23..87f4aa3b 100644 --- a/CPP/7zip/Archive/Iso/IsoHandler.cpp +++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp @@ -3,6 +3,7 @@ #include "StdAfx.h" #include "../../../Common/ComTry.h" +#include "../../../Common/MyLinux.h" #include "../../../Common/StringConvert.h" #include "../../../Windows/PropVariant.h" @@ -221,16 +222,15 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidSymLink: if (_archive.IsSusp) { - UString s; UInt32 mode; if (item.GetPx(_archive.SuspSkipSize, k_Px_Mode, mode)) { - if (((mode >> 12) & 0xF) == 10) + if (MY_LIN_S_ISLNK(mode)) { AString s8; if (item.GetSymLink(_archive.SuspSkipSize, s8)) { - s = MultiByteToUnicodeString(s8, CP_OEMCP); + UString s = MultiByteToUnicodeString(s8, CP_OEMCP); prop = s; } } diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp index b0bfb164..211b3eea 100644 --- a/CPP/7zip/Archive/Iso/IsoIn.cpp +++ b/CPP/7zip/Archive/Iso/IsoIn.cpp @@ -299,10 +299,12 @@ void CInArchive::ReadVolumeDescriptor(CVolumeDescriptor &d) static const Byte kSig_CD001[5] = { 'C', 'D', '0', '0', '1' }; +/* static const Byte kSig_NSR02[5] = { 'N', 'S', 'R', '0', '2' }; static const Byte kSig_NSR03[5] = { 'N', 'S', 'R', '0', '3' }; static const Byte kSig_BEA01[5] = { 'B', 'E', 'A', '0', '1' }; static const Byte kSig_TEA01[5] = { 'T', 'E', 'A', '0', '1' }; +*/ static inline bool CheckSignature(const Byte *sig, const Byte *data) { diff --git a/CPP/7zip/Archive/Iso/IsoItem.h b/CPP/7zip/Archive/Iso/IsoItem.h index 5ae13a60..a42ae039 100644 --- a/CPP/7zip/Archive/Iso/IsoItem.h +++ b/CPP/7zip/Archive/Iso/IsoItem.h @@ -149,7 +149,7 @@ struct CDirRecord } - const bool GetSymLink(int skipSize, AString &link) const + bool GetSymLink(int skipSize, AString &link) const { link.Empty(); const Byte *p = NULL; @@ -208,7 +208,7 @@ struct CDirRecord return true; } - static const bool GetLe32Be32(const Byte *p, UInt32 &dest) + static bool GetLe32Be32(const Byte *p, UInt32 &dest) { UInt32 v1 = GetUi32(p); UInt32 v2 = GetBe32(p + 4); @@ -221,7 +221,7 @@ struct CDirRecord } - const bool GetPx(int skipSize, unsigned pxType, UInt32 &val) const + bool GetPx(int skipSize, unsigned pxType, UInt32 &val) const { val = 0; const Byte *p = NULL; @@ -237,7 +237,7 @@ struct CDirRecord } /* - const bool GetTf(int skipSize, unsigned pxType, CRecordingDateTime &t) const + bool GetTf(int skipSize, unsigned pxType, CRecordingDateTime &t) const { const Byte *p = NULL; unsigned len = 0; diff --git a/CPP/7zip/Archive/LzhHandler.cpp b/CPP/7zip/Archive/LzhHandler.cpp index 53d69db7..e1984d28 100644 --- a/CPP/7zip/Archive/LzhHandler.cpp +++ b/CPP/7zip/Archive/LzhHandler.cpp @@ -41,6 +41,7 @@ static UInt16 g_LzhCrc16Table[256]; #define CRC16_UPDATE_BYTE(crc, b) (g_LzhCrc16Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) +UInt32 LzhCrc16Update(UInt32 crc, const void *data, size_t size); UInt32 LzhCrc16Update(UInt32 crc, const void *data, size_t size) { const Byte *p = (const Byte *)data; @@ -83,13 +84,7 @@ struct CExtension AString GetString() const { AString s; - for (size_t i = 0; i < Data.Size(); i++) - { - char c = (char)Data[i]; - if (c == 0) - break; - s += c; - } + s.SetFrom_CalcLen((const char *)(const Byte *)Data, (unsigned)Data.Size()); return s; } }; @@ -184,11 +179,13 @@ struct CItem return i; return -1; } + bool GetUnixTime(UInt32 &value) const { value = 0; int index = FindExt(kExtIdUnixTime); - if (index < 0) + if (index < 0 + || Extensions[index].Data.Size() < 4) { if (Level == 2) { @@ -220,13 +217,14 @@ struct CItem AString GetName() const { - AString dirName (GetDirName()); + AString s (GetDirName()); const char kDirSeparator = '\\'; // check kDirSeparator in Linux - dirName.Replace((char)(unsigned char)0xFF, kDirSeparator); - if (!dirName.IsEmpty() && dirName.Back() != kDirSeparator) - dirName += kDirSeparator; - return dirName + GetFileName(); + s.Replace((char)(unsigned char)0xFF, kDirSeparator); + if (!s.IsEmpty() && s.Back() != kDirSeparator) + s += kDirSeparator; + s += GetFileName(); + return s; } }; @@ -332,7 +330,7 @@ static HRESULT GetNextItem(ISequentialInStream *stream, bool &filled, CItem &ite return S_FALSE; CExtension ext; RINOK(ReadStream_FALSE(stream, &ext.Type, 1)) - nextSize -= 3; + nextSize = (UInt16)(nextSize - 3); ext.Data.Alloc(nextSize); RINOK(ReadStream_FALSE(stream, (Byte *)ext.Data, nextSize)) item.Extensions.Add(ext); diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp index 9eac3ca1..ba547c83 100644 --- a/CPP/7zip/Archive/LzmaHandler.cpp +++ b/CPP/7zip/Archive/LzmaHandler.cpp @@ -242,29 +242,25 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) } -static void DictSizeToString(UInt32 val, char *s) +static char * DictSizeToString(UInt32 val, char *s) { for (unsigned i = 0; i <= 31; i++) if (((UInt32)1 << i) == val) - { - ::ConvertUInt32ToString(i, s); - return; - } + return ::ConvertUInt32ToString(i, s); char c = 'b'; if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; } else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; } - ::ConvertUInt32ToString(val, s); - s += MyStringLen(s); + s = ::ConvertUInt32ToString(val, s); *s++ = c; *s = 0; + return s; } static char *AddProp32(char *s, const char *name, UInt32 v) { *s++ = ':'; s = MyStpCpy(s, name); - ::ConvertUInt32ToString(v, s); - return s + MyStringLen(s); + return ::ConvertUInt32ToString(v, s); } void CHandler::GetMethod(NCOM::CPropVariant &prop) @@ -277,8 +273,7 @@ void CHandler::GetMethod(NCOM::CPropVariant &prop) if (_header.FilterID != 0) s = MyStpCpy(s, "BCJ "); s = MyStpCpy(s, "LZMA:"); - DictSizeToString(_header.GetDicSize(), s); - s += strlen(s); + s = DictSizeToString(_header.GetDicSize(), s); UInt32 d = _header.GetProp(); // if (d != 0x5D) @@ -315,10 +310,10 @@ API_FUNC_static_IsArc IsArc_Lzma(const Byte *p, size_t size) return k_IsArc_Res_NEED_MORE; if (p[0] >= 5 * 5 * 9) return k_IsArc_Res_NO; - UInt64 unpackSize = GetUi64(p + 1 + 4); + const UInt64 unpackSize = GetUi64(p + 1 + 4); if (unpackSize != (UInt64)(Int64)-1) { - if (size >= ((UInt64)1 << 56)) + if (unpackSize >= ((UInt64)1 << 56)) return k_IsArc_Res_NO; } if (unpackSize != 0) diff --git a/CPP/7zip/Archive/MachoHandler.cpp b/CPP/7zip/Archive/MachoHandler.cpp index 1f65574d..bc8ba223 100644 --- a/CPP/7zip/Archive/MachoHandler.cpp +++ b/CPP/7zip/Archive/MachoHandler.cpp @@ -35,11 +35,11 @@ namespace NMacho { #define CPU_SUBTYPE_I386_ALL 3 -#define CPU_TYPE_PPC64 (CPU_ARCH_ABI64 | CPU_TYPE_PPC) +// #define CPU_TYPE_PPC64 (CPU_ARCH_ABI64 | CPU_TYPE_PPC) #define CPU_TYPE_AMD64 (CPU_ARCH_ABI64 | CPU_TYPE_386) #define CPU_TYPE_ARM64 (CPU_ARCH_ABI64 | CPU_TYPE_ARM) -#define CPU_SUBTYPE_LIB64 (1 << 31) +#define CPU_SUBTYPE_LIB64 ((UInt32)1 << 31) #define CPU_SUBTYPE_POWERPC_970 100 diff --git a/CPP/7zip/Archive/MbrHandler.cpp b/CPP/7zip/Archive/MbrHandler.cpp index 14a1224c..026696f3 100644 --- a/CPP/7zip/Archive/MbrHandler.cpp +++ b/CPP/7zip/Archive/MbrHandler.cpp @@ -51,10 +51,10 @@ struct CChs bool Check() const { return GetSector() > 0; } }; -#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } // Chs in some MBRs contains only low bits of "Cyl number". So we disable check. /* +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } static int CompareChs(const CChs &c1, const CChs &c2) { RINOZ(MyCompare(c1.GetCyl(), c2.GetCyl())); diff --git a/CPP/7zip/Archive/MubHandler.cpp b/CPP/7zip/Archive/MubHandler.cpp index 6d054356..c790265d 100644 --- a/CPP/7zip/Archive/MubHandler.cpp +++ b/CPP/7zip/Archive/MubHandler.cpp @@ -33,7 +33,7 @@ namespace NMub { #define MACH_CPU_TYPE_AMD64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_386) #define MACH_CPU_TYPE_ARM64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_ARM) -#define MACH_CPU_SUBTYPE_LIB64 (1 << 31) +#define MACH_CPU_SUBTYPE_LIB64 ((UInt32)1 << 31) #define MACH_CPU_SUBTYPE_I386_ALL 3 @@ -124,14 +124,15 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } if (ext) strcpy(temp, ext); - if (item.SubType != 0 && ( - item.Type != MACH_CPU_TYPE_386 && - item.Type != MACH_CPU_TYPE_AMD64 || - (item.SubType & ~(UInt32)MACH_CPU_SUBTYPE_LIB64) != MACH_CPU_SUBTYPE_I386_ALL)) + if (item.SubType != 0) + if ((item.Type != MACH_CPU_TYPE_386 && + item.Type != MACH_CPU_TYPE_AMD64) + || (item.SubType & ~(UInt32)MACH_CPU_SUBTYPE_LIB64) != MACH_CPU_SUBTYPE_I386_ALL + ) { unsigned pos = MyStringLen(temp); temp[pos++] = '-'; - ConvertUInt32ToString(item.SubType, temp + pos); + ConvertUInt32ToString(item.SubType, temp + pos); } return PropVarEm_Set_Str(value, temp); } diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.cpp b/CPP/7zip/Archive/Nsis/NsisHandler.cpp index 095105fe..aa0a9175 100644 --- a/CPP/7zip/Archive/Nsis/NsisHandler.cpp +++ b/CPP/7zip/Archive/Nsis/NsisHandler.cpp @@ -50,6 +50,7 @@ static const Byte kArcProps[] = { kpidMethod, kpidSolid, + kpidBit64, kpidHeadersSize, kpidEmbeddedStubSize, kpidSubType @@ -134,6 +135,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) break; } + case kpidBit64: if (_archive.Is64Bit) prop = true; break; case kpidMethod: prop = _methodString; break; case kpidSolid: prop = _archive.IsSolid; break; case kpidOffset: prop = _archive.StartOffset; break; diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp index f4f9ab04..3c1a0f17 100644 --- a/CPP/7zip/Archive/Nsis/NsisIn.cpp +++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp @@ -155,7 +155,7 @@ enum kNumCmds }; -static const unsigned kNumAdditionalParkCmds = 3; + struct CCommandInfo { @@ -506,18 +506,20 @@ void CInArchive::AddLicense(UInt32 param, Int32 langID) #endif -#define kVar_CMDLINE 20 +// #define kVar_CMDLINE 20 #define kVar_INSTDIR 21 #define kVar_OUTDIR 22 #define kVar_EXEDIR 23 -#define kVar_LANGUAGE 24 +// #define kVar_LANGUAGE 24 #define kVar_TEMP 25 #define kVar_PLUGINSDIR 26 #define kVar_EXEPATH 27 // NSIS 2.26+ -#define kVar_EXEFILE 28 // NSIS 2.26+ +// #define kVar_EXEFILE 28 // NSIS 2.26+ #define kVar_HWNDPARENT_225 27 +#ifdef NSIS_SCRIPT #define kVar_HWNDPARENT 29 +#endif // #define kVar__CLICK 30 #define kVar_Spec_OUTDIR_225 29 // NSIS 2.04 - 2.25 @@ -606,9 +608,9 @@ void CInArchive::AddParam_UInt(UInt32 value) #define NS_CODE_SKIP 252 #define NS_CODE_VAR 253 #define NS_CODE_SHELL 254 -#define NS_CODE_LANG 255 +// #define NS_CODE_LANG 255 -#define NS_3_CODE_LANG 1 +// #define NS_3_CODE_LANG 1 #define NS_3_CODE_SHELL 2 #define NS_3_CODE_VAR 3 #define NS_3_CODE_SKIP 4 @@ -1364,7 +1366,7 @@ void CInArchive::ReadString2(AString &s, UInt32 pos) #ifdef NSIS_SCRIPT -#define DEL_DIR 1 +// #define DEL_DIR 1 #define DEL_RECURSE 2 #define DEL_REBOOT 4 // #define DEL_SIMPLE 8 @@ -1445,9 +1447,11 @@ static void FlagsToString2(CDynLimBuf &s, const char * const *table, unsigned nu static bool DoesNeedQuotes(const char *s) { - char c = s[0]; - if (c == 0 || c == '#' || c == ';' || (c == '/' && s[1] == '*')) - return true; + { + char c = s[0]; + if (c == 0 || c == '#' || c == ';' || (c == '/' && s[1] == '*')) + return true; + } for (;;) { char c = *s++; @@ -1737,12 +1741,12 @@ void CNsis_CtlColors::Parse(const Byte *p) // Win32 constants #define MY__TRANSPARENT 1 -#define MY__OPAQUE 2 +// #define MY__OPAQUE 2 -#define MY__GENERIC_READ (1 << 31) -#define MY__GENERIC_WRITE (1 << 30) -#define MY__GENERIC_EXECUTE (1 << 29) -#define MY__GENERIC_ALL (1 << 28) +#define MY__GENERIC_READ ((UInt32)1 << 31) +#define MY__GENERIC_WRITE ((UInt32)1 << 30) +#define MY__GENERIC_EXECUTE ((UInt32)1 << 29) +#define MY__GENERIC_ALL ((UInt32)1 << 28) #define MY__CREATE_NEW 1 #define MY__CREATE_ALWAYS 2 @@ -2068,9 +2072,11 @@ void CSection::Parse(const Byte *p) #define SF_BOLD (1 << 3) #define SF_RO (1 << 4) #define SF_EXPAND (1 << 5) +/* #define SF_PSELECTED (1 << 6) #define SF_TOGGLED (1 << 7) #define SF_NAMECHG (1 << 8) +*/ bool CInArchive::PrintSectionBegin(const CSection §, unsigned index) { @@ -2115,7 +2121,7 @@ bool CInArchive::PrintSectionBegin(const CSection §, unsigned index) Script += ' '; else */ - SmallSpaceComment(); + SmallSpaceComment(); Script += "Section_"; Add_UInt(index); @@ -2290,14 +2296,15 @@ bool CInArchive::CompareCommands(const Byte *rawCmds, const Byte *sequence, size return true; } -#endif static const UInt32 kSectionSize_base = 6 * 4; -static const UInt32 kSectionSize_8bit = kSectionSize_base + 1024; -static const UInt32 kSectionSize_16bit = kSectionSize_base + 1024 * 2; -static const UInt32 kSectionSize_16bit_Big = kSectionSize_base + 8196 * 2; +// static const UInt32 kSectionSize_8bit = kSectionSize_base + 1024; +// static const UInt32 kSectionSize_16bit = kSectionSize_base + 1024 * 2; +// static const UInt32 kSectionSize_16bit_Big = kSectionSize_base + 8196 * 2; // 8196 is default string length in NSIS-Unicode since 2.37.3 +#endif + static void AddString(AString &dest, const char *src) { @@ -2330,8 +2337,13 @@ AString CInArchive::GetFormatDescription() const if (IsUnicode) AddString(s, "Unicode"); + + if (Is64Bit) + AddString(s, "64-bit"); + if (LogCmdIsEnabled) AddString(s, "log"); + if (BadCmd >= 0) { AddString(s, "BadCmd="); @@ -2342,9 +2354,11 @@ AString CInArchive::GetFormatDescription() const #ifdef NSIS_SCRIPT +static const unsigned kNumAdditionalParkCmds = 3; + unsigned CInArchive::GetNumSupportedCommands() const { - unsigned numCmds = IsPark() ? kNumCmds : kNumCmds - kNumAdditionalParkCmds; + unsigned numCmds = IsPark() ? (unsigned)kNumCmds : (unsigned)(kNumCmds) - kNumAdditionalParkCmds; if (!LogCmdIsEnabled) numCmds--; if (!IsUnicode) @@ -2792,26 +2806,20 @@ bool CInArchive::IsAbsolutePathVar(UInt32 strPos) const return false; } -#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z') +#define IS_LETTER_CHAR(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) // We use same check as in NSIS decoder -bool IsDrivePath(const wchar_t *s) { return IS_LETTER_CHAR(s[0]) && s[1] == ':' /* && s[2] == '\\' */ ; } -bool IsDrivePath(const char *s) { return IS_LETTER_CHAR(s[0]) && s[1] == ':' /* && s[2] == '\\' */ ; } +static bool IsDrivePath(const wchar_t *s) { return IS_LETTER_CHAR(s[0]) && s[1] == ':' /* && s[2] == '\\' */ ; } +static bool IsDrivePath(const char *s) { return IS_LETTER_CHAR(s[0]) && s[1] == ':' /* && s[2] == '\\' */ ; } static bool IsAbsolutePath(const wchar_t *s) { - return - s[0] == WCHAR_PATH_SEPARATOR && - s[1] == WCHAR_PATH_SEPARATOR || - IsDrivePath(s); + return (s[0] == WCHAR_PATH_SEPARATOR && s[1] == WCHAR_PATH_SEPARATOR) || IsDrivePath(s); } static bool IsAbsolutePath(const char *s) { - return - s[0] == CHAR_PATH_SEPARATOR && - s[1] == CHAR_PATH_SEPARATOR || - IsDrivePath(s); + return (s[0] == CHAR_PATH_SEPARATOR && s[1] == CHAR_PATH_SEPARATOR) || IsDrivePath(s); } void CInArchive::SetItemName(CItem &item, UInt32 strPos) @@ -3748,8 +3756,8 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) for (UInt32 j = i - 1; j >= kkk + 3; j--) { - const Byte *pCmd = p + kCmdSize * (j - kkk); - AddParam(GET_CMD_PARAM(pCmd, 0)); + const Byte *pCmd2 = p + kCmdSize * (j - kkk); + AddParam(GET_CMD_PARAM(pCmd2, 0)); } NewLine(); Tab(true); @@ -3850,13 +3858,13 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) { case k_ExecFlags_AutoClose: case k_ExecFlags_RebootFlag: - if (v < 2) s2 = (v == 0) ? "false" : "true"; break; + if (v < 2) { s2 = (v == 0) ? "false" : "true"; } break; case k_ExecFlags_ShellVarContext: - if (v < 2) s2 = (v == 0) ? "current" : "all"; break; + if (v < 2) { s2 = (v == 0) ? "current" : "all"; } break; case k_ExecFlags_Silent: - if (v < 2) s2 = (v == 0) ? "normal" : "silent"; break; + if (v < 2) { s2 = (v == 0) ? "normal" : "silent"; } break; case k_ExecFlags_RegView: - if (v == 0) s2 = "32"; + if (v == 0) s2 = "32"; else if (v == 256) s2 = "64"; break; case k_ExecFlags_DetailsPrint: @@ -3864,6 +3872,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) else if (v == 2) s2 = "textonly"; else if (v == 4) s2 = "listonly"; else if (v == 6) s2 = "none"; + break; } if (s2) { @@ -4400,7 +4409,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) s += 'F'; Add_UInt(key - kMy_VK_F1 + 1); } - else if (key >= 'A' && key <= 'Z' || key >= '0' && key <= '9') + else if ((key >= 'A' && key <= 'Z') || (key >= '0' && key <= '9')) s += (char)key; else { @@ -4687,6 +4696,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) s += "Text"; AddParam(params[1]); } + break; } case EW_SECTIONSET: @@ -4829,9 +4839,6 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) } else { - if (curSectionIndex == 49) - curSectionIndex = curSectionIndex; - if (PrintSectionBegin(sect, curSectionIndex)) curSectionIndex++; else @@ -4846,8 +4853,8 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) static int CompareItems(void *const *p1, void *const *p2, void *param) { - const CItem &i1 = **(CItem **)p1; - const CItem &i2 = **(CItem **)p2; + const CItem &i1 = **(const CItem *const *)p1; + const CItem &i2 = **(const CItem *const *)p2; RINOZ(MyCompare(i1.Pos, i2.Pos)); const CInArchive *inArchive = (const CInArchive *)param; if (inArchive->IsUnicode) @@ -4970,14 +4977,15 @@ HRESULT CInArchive::SortItems() return S_OK; } +#ifdef NSIS_SCRIPT // Flags for common_header.flags -#define CH_FLAGS_DETAILS_SHOWDETAILS 1 -#define CH_FLAGS_DETAILS_NEVERSHOW 2 +// #define CH_FLAGS_DETAILS_SHOWDETAILS 1 +// #define CH_FLAGS_DETAILS_NEVERSHOW 2 #define CH_FLAGS_PROGRESS_COLORED 4 #define CH_FLAGS_SILENT 8 #define CH_FLAGS_SILENT_LOG 16 #define CH_FLAGS_AUTO_CLOSE 32 -#define CH_FLAGS_DIR_NO_SHOW 64 // unused now +// #define CH_FLAGS_DIR_NO_SHOW 64 // unused now #define CH_FLAGS_NO_ROOT_DIR 128 #define CH_FLAGS_COMP_ONLY_ON_CUSTOM 256 #define CH_FLAGS_NO_CUSTOM 512 @@ -4989,29 +4997,59 @@ static const char * const k_PostStrings[] = , "uninstcmd" // NSIS 2.25+, used by uninstaller: , "wininit" // NSIS 2.25+, used by move file on reboot }; +#endif + + +void CBlockHeader::Parse(const Byte *p, unsigned bhoSize) +{ + if (bhoSize == 12) + { + // UInt64 a = GetUi64(p); + if (GetUi32(p + 4) != 0) + throw 1; + } + Offset = GetUi32(p); + Num = GetUi32(p + bhoSize - 4); +} + +#define PARSE_BH(k, bh) bh.Parse (p1 + 4 + bhoSize * k, bhoSize) + HRESULT CInArchive::Parse() { // UInt32 offset = ReadUInt32(); // ???? offset == FirstHeader.HeaderSize - const Byte *p = _data; + const Byte * const p1 = _data; + + if (_size < 4 + 12 * 8) + Is64Bit = false; + else + { + Is64Bit = true; + // here we test high 32-bit of possible UInt64 CBlockHeader::Offset field + for (int k = 0; k < 8; k++) + if (GetUi32(p1 + 4 + 12 * k + 4) != 0) + Is64Bit = false; + } - if (_size < 4 + 8 * 8) + const unsigned bhoSize = Is64Bit ? 12 : 8; + if (_size < 4 + bhoSize * 8) return S_FALSE; CBlockHeader bhEntries, bhStrings, bhLangTables; - bhEntries.Parse(p + 4 + 8 * 2); - bhStrings.Parse(p + 4 + 8 * 3); - bhLangTables.Parse(p + 4 + 8 * 4); + + PARSE_BH (2, bhEntries); + PARSE_BH (3, bhStrings); + PARSE_BH (4, bhLangTables); #ifdef NSIS_SCRIPT CBlockHeader bhFont; - bhPages.Parse(p + 4 + 8 * 0); - bhSections.Parse(p + 4 + 8 * 1); - bhCtlColors.Parse(p + 4 + 8 * 5); - bhFont.Parse(p + 4 + 8 * 6); - bhData.Parse(p + 4 + 8 * 7); + PARSE_BH (0, bhPages); + PARSE_BH (1, bhSections); + PARSE_BH (5, bhCtlColors); + PARSE_BH (6, bhFont); + PARSE_BH (7, bhData); #endif @@ -5084,6 +5122,7 @@ HRESULT CInArchive::Parse() case NMethodType::kDeflate: m = "zlib"; break; case NMethodType::kBZip2: m = "bzip2"; break; case NMethodType::kLZMA: m = "lzma"; break; + default: break; } Script += "SetCompressor"; if (IsSolid) @@ -5167,7 +5206,7 @@ HRESULT CInArchive::Parse() memset(strUsed, 0, NumStringChars); { - UInt32 ehFlags = Get32(p); + UInt32 ehFlags = Get32(p1); UInt32 showDetails = ehFlags & 3;// CH_FLAGS_DETAILS_SHOWDETAILS & CH_FLAGS_DETAILS_NEVERSHOW; if (showDetails >= 1 && showDetails <= 2) { @@ -5208,11 +5247,16 @@ HRESULT CInArchive::Parse() } } - unsigned paramsOffset = 4 + 8 * 8; - if (bhPages.Offset == 276) - paramsOffset -= 8; + unsigned paramsOffset; + { + unsigned numBhs = 8; + // probably its for old NSIS? + if (bhoSize == 8 && bhPages.Offset == 276) + numBhs = 7; + paramsOffset = 4 + bhoSize * numBhs; + } - const Byte *p2 = p + paramsOffset; + const Byte *p2 = p1 + paramsOffset; { UInt32 rootKey = Get32(p2); // (rootKey = -1) in uninstaller by default (the bug in NSIS) @@ -5261,7 +5305,8 @@ HRESULT CInArchive::Parse() } UInt32 license_bg = Get32(p2 + 36); - if (license_bg != (UInt32)(Int32)-1 && license_bg != -15) // COLOR_BTNFACE + if (license_bg != (UInt32)(Int32)-1 && + license_bg != (UInt32)(Int32)-15) // COLOR_BTNFACE { Script += "LicenseBkColor"; if ((Int32)license_bg == -5) // COLOR_WINDOW @@ -5275,13 +5320,19 @@ HRESULT CInArchive::Parse() AddLF(); } - UInt32 langtable_size = Get32(p2 + 32); if (bhLangTables.Num > 0) { + const UInt32 langtable_size = Get32(p2 + 32); + if (langtable_size == (UInt32)(Int32)-1) return E_NOTIMPL; // maybe it's old NSIS archive() - UInt32 numStrings = (langtable_size - 10) / 4; + if (langtable_size < 10) + return S_FALSE; + if (bhLangTables.Num > (_size - bhLangTables.Offset) / langtable_size) + return S_FALSE; + + const UInt32 numStrings = (langtable_size - 10) / 4; _numLangStrings = numStrings; AddLF(); Separator(); @@ -5289,12 +5340,12 @@ HRESULT CInArchive::Parse() PrintNumComment("LANG STRINGS", numStrings); AddLF(); - if (licenseLangIndex >= 0) + if (licenseLangIndex >= 0 && (unsigned)licenseLangIndex < numStrings) { for (UInt32 i = 0; i < bhLangTables.Num; i++) { - const Byte *p = _data + bhLangTables.Offset + langtable_size * i; - LANGID langID = Get16(p); + const Byte * const p = _data + bhLangTables.Offset + langtable_size * i; + const UInt16 langID = Get16(p); UInt32 val = Get32(p + 10 + (UInt32)licenseLangIndex * 4); if (val != 0) { @@ -5309,33 +5360,24 @@ HRESULT CInArchive::Parse() AddLF(); } - UInt32 brandingText = 0; - UInt32 caption = 0; - UInt32 name = 0; + UInt32 names[3] = { 0 }; + UInt32 i; for (i = 0; i < bhLangTables.Num; i++) { - const Byte *p = _data + bhLangTables.Offset + langtable_size * i; - LANGID langID = Get16(p); + const Byte * const p = _data + bhLangTables.Offset + langtable_size * i; + const UInt16 langID = Get16(p); if (i == 0 || langID == 1033) _mainLang = p + 10; + for (unsigned k = 0; k < ARRAY_SIZE(names) && k < numStrings; k++) { - UInt32 v = Get32(p + 10 + 0 * 4); - if (v != 0 && (langID == 1033 || brandingText == 0)) - brandingText = v; - } - { - UInt32 v = Get32(p + 10 + 1 * 4); - if (v != 0 && (langID == 1033 || caption == 0)) - caption = v; - } - { - UInt32 v = Get32(p + 10 + 2 * 4); - if (v != 0 && (langID == 1033 || name == 0)) - name = v; + UInt32 v = Get32(p + 10 + k * 4); + if (v != 0 && (langID == 1033 || names[k] == 0)) + names[k] = v; } } - + + const UInt32 name = names[2]; if (name != 0) { Script += "Name"; @@ -5346,6 +5388,7 @@ HRESULT CInArchive::Parse() } /* + const UInt32 caption = names[1]; if (caption != 0) { Script += "Caption"; @@ -5354,6 +5397,7 @@ HRESULT CInArchive::Parse() } */ + const UInt32 brandingText = names[0]; if (brandingText != 0) { Script += "BrandingText"; @@ -5365,8 +5409,8 @@ HRESULT CInArchive::Parse() for (i = 0; i < bhLangTables.Num; i++) { - const Byte *p = _data + bhLangTables.Offset + langtable_size * i; - LANGID langID = Get16(p); + const Byte * const p = _data + bhLangTables.Offset + langtable_size * i; + const UInt16 langID = Get16(p); AddLF(); AddCommentAndString("LANG:"); @@ -5641,10 +5685,12 @@ HRESULT CInArchive::Open2(const Byte *sig, size_t size) if (Get32((const Byte *)buf) != FirstHeader.HeaderSize) return S_FALSE; } - size_t processedSize = FirstHeader.HeaderSize; - RINOK(Decoder.Read(_data, &processedSize)); - if (processedSize != FirstHeader.HeaderSize) - return S_FALSE; + { + size_t processedSize = FirstHeader.HeaderSize; + RINOK(Decoder.Read(_data, &processedSize)); + if (processedSize != FirstHeader.HeaderSize) + return S_FALSE; + } #ifdef NSIS_SCRIPT if (IsSolid) @@ -5824,14 +5870,25 @@ HRESULT CInArchive::Open(IInStream *inStream, const UInt64 *maxCheckStartPositio DataStreamOffset = pos + kStartHeaderSize; FirstHeader.Flags = Get32(buf); if ((FirstHeader.Flags & (~kFlagsMask)) != 0) + { + // return E_NOTIMPL; return S_FALSE; + } IsInstaller = (FirstHeader.Flags & NFlags::kUninstall) == 0; FirstHeader.HeaderSize = Get32(buf + kSignatureSize + 4); FirstHeader.ArcSize = Get32(buf + kSignatureSize + 8); if (FirstHeader.ArcSize <= kStartHeaderSize) return S_FALSE; - + + /* + if ((FirstHeader.Flags & NFlags::k_BI_ExternalFileSupport) != 0) + { + UInt32 datablock_low = Get32(buf + kSignatureSize + 12); + UInt32 datablock_high = Get32(buf + kSignatureSize + 16); + } + */ + RINOK(inStream->Seek(0, STREAM_SEEK_END, &_fileSize)); IsArc = true; @@ -5872,7 +5929,8 @@ UString CInArchive::ConvertToUnicode(const AString &s) const if (IsUnicode) { UString res; - if (ConvertUTF8ToUnicode(s, res)) + // if ( + ConvertUTF8ToUnicode(s, res); return res; } return MultiByteToUnicodeString(s); @@ -5886,6 +5944,7 @@ void CInArchive::Clear2() IsNsis200 = false; LogCmdIsEnabled = false; BadCmd = -1; + Is64Bit = false; #ifdef NSIS_SCRIPT Name.Empty(); diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h index 028e4a5d..5c88188d 100644 --- a/CPP/7zip/Archive/Nsis/NsisIn.h +++ b/CPP/7zip/Archive/Nsis/NsisIn.h @@ -34,6 +34,11 @@ namespace NFlags const UInt32 kSilent = 2; const UInt32 kNoCrc = 4; const UInt32 kForceCrc = 8; + // NSISBI fork flags: + const UInt32 k_BI_LongOffset = 16; + const UInt32 k_BI_ExternalFileSupport = 32; + const UInt32 k_BI_ExternalFile = 64; + const UInt32 k_BI_IsStubInstaller = 128; } struct CFirstHeader @@ -58,11 +63,7 @@ struct CBlockHeader UInt32 Offset; UInt32 Num; - void Parse(const Byte *p) - { - Offset = GetUi32(p); - Num = GetUi32(p + 4); - } + void Parse(const Byte *p, unsigned bhoSize); }; struct CItem @@ -159,6 +160,7 @@ public: CByteBuffer _data; CObjectVector<CItem> Items; bool IsUnicode; + bool Is64Bit; private: UInt32 _stringsPos; // relative to _data UInt32 NumStringChars; @@ -170,7 +172,6 @@ private: ENsisType NsisType; bool IsNsis200; // NSIS 2.03 and before bool IsNsis225; // NSIS 2.25 and before - bool LogCmdIsEnabled; int BadCmd; // -1: no bad command; in another cases lowest bad command id diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp index 21372033..daa01fef 100644 --- a/CPP/7zip/Archive/NtfsHandler.cpp +++ b/CPP/7zip/Archive/NtfsHandler.cpp @@ -208,7 +208,7 @@ enum Posix name can be after or before Win32 name */ -static const Byte kFileNameType_Posix = 0; // for hard links +// static const Byte kFileNameType_Posix = 0; // for hard links static const Byte kFileNameType_Win32 = 1; // after Dos name static const Byte kFileNameType_Dos = 2; // short name static const Byte kFileNameType_Win32Dos = 3; // short and full name are same @@ -386,8 +386,8 @@ struct CAttr static int CompareAttr(void *const *elem1, void *const *elem2, void *) { - const CAttr &a1 = *(*((const CAttr **)elem1)); - const CAttr &a2 = *(*((const CAttr **)elem2)); + const CAttr &a1 = *(*((const CAttr *const *)elem1)); + const CAttr &a2 = *(*((const CAttr *const *)elem2)); RINOZ(MyCompare(a1.Type, a2.Type)); if (a1.Name.IsEmpty()) { @@ -717,12 +717,16 @@ static size_t Lznt1Dec(Byte *dest, size_t outBufLim, size_t destLen, const Byte UInt32 dist = (v >> (16 - numDistBits)); if (dist >= sbOffset) return 0; - Int32 offs = -1 - dist; - Byte *p = dest + destSize; - for (UInt32 t = 0; t < len; t++) - p[t] = p[t + offs]; + const size_t offs = 1 + dist; + Byte *p = dest + destSize - offs; destSize += len; sbOffset += len; + const Byte *lim = p + len; + p[offs] = *p; ++p; + p[offs] = *p; ++p; + do + p[offs] = *p; + while (++p != lim); } } } @@ -1094,7 +1098,7 @@ struct CMftRec void CMftRec::ParseDataNames() { DataRefs.Clear(); - DataAttrs.Sort(CompareAttr, 0); + DataAttrs.Sort(CompareAttr, NULL); for (unsigned i = 0; i < DataAttrs.Size();) { @@ -2188,7 +2192,7 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data *data = (const wchar_t *)EmptyString; else *data = s->GetRawPtr(); - *dataSize = (s->Len() + 1) * sizeof(wchar_t); + *dataSize = (s->Len() + 1) * (UInt32)sizeof(wchar_t); *propType = PROP_DATA_TYPE_wchar_t_PTR_Z_LE; #endif return S_OK; diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp index 675293ba..ee265571 100644 --- a/CPP/7zip/Archive/PeHandler.cpp +++ b/CPP/7zip/Archive/PeHandler.cpp @@ -363,8 +363,8 @@ struct CSection CSection(): IsRealSect(false), IsDebug(false), IsAdditionalSection(false) {} - const UInt32 GetSizeExtract() const { return PSize; } - const UInt32 GetSizeMin() const { return MyMin(PSize, VSize); } + UInt32 GetSizeExtract() const { return PSize; } + UInt32 GetSizeMin() const { return MyMin(PSize, VSize); } void UpdateTotalSize(UInt32 &totalSize) const { @@ -768,15 +768,15 @@ class CHandler: bool _oneLang; UString _resourcesPrefix; CUsedBitmap _usedRes; - bool _parseResources; + // bool _parseResources; bool _checksumError; bool IsOpt() const { return _header.OptHeaderSize != 0; } COptHeader _optHeader; - bool _allowTail; bool _coffMode; + bool _allowTail; HRESULT LoadDebugSections(IInStream *stream, bool &thereIsSection); HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); @@ -2005,10 +2005,12 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi const UInt32 mask = ((UInt32)1 << numBits) - 1; const size_t end = (size_t)((sect.VSize + mask) & (UInt32)~mask); if (end > sect.VSize) + { if (end <= sect.PSize) fileSize = end; else fileSize = sect.PSize; + } } } @@ -2459,7 +2461,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) return S_FALSE; } - _parseResources = true; + bool _parseResources = true; // _parseResources = false; UInt64 mainSize = 0, mainSize2 = 0; @@ -2467,11 +2469,11 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) for (i = 0; i < _sections.Size(); i++) { const CSection § = _sections[i]; - CMixItem mixItem; - mixItem.SectionIndex = i; if (IsOpt()) - if (_parseResources && sect.Name == ".rsrc" && _items.IsEmpty()) + if (_parseResources && sect.Name == ".rsrc") { + // 20.01: we try to parse only first copy of .rsrc section. + _parseResources = false; const unsigned numMixItems = _mixItems.Size(); HRESULT res = OpenResources(i, stream, callback); if (res == S_OK) @@ -2483,6 +2485,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) const CResItem &item = _items[j]; if (item.Enabled) { + CMixItem mixItem; + mixItem.SectionIndex = i; mixItem.ResourceIndex = j; if (item.IsRcDataOrUnknown()) { @@ -2531,6 +2535,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) _mixItems.DeleteFrom(numMixItems); CloseResources(); } + if (sect.IsAdditionalSection) { if (sect.PSize >= mainSize) @@ -2542,6 +2547,9 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) else if (sect.PSize >= mainSize2) mainSize2 = sect.PSize; } + + CMixItem mixItem; + mixItem.SectionIndex = i; _mixItems.Add(mixItem); } @@ -3017,7 +3025,7 @@ static const Byte kProps[] = enum { - kpidSubSystem = kpidUserDefined, + kpidSubSystem = kpidUserDefined // , kpidImageBase }; diff --git a/CPP/7zip/Archive/PpmdHandler.cpp b/CPP/7zip/Archive/PpmdHandler.cpp index c80400bc..05a07e53 100644 --- a/CPP/7zip/Archive/PpmdHandler.cpp +++ b/CPP/7zip/Archive/PpmdHandler.cpp @@ -1,5 +1,5 @@ /* PpmdHandler.cpp -- PPMd format handler -2015-11-30 : Igor Pavlov : Public domain +2020 : Igor Pavlov : Public domain This code is based on: PPMd var.H (2001) / var.I (2002): Dmitry Shkarin : Public domain Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ @@ -59,7 +59,7 @@ struct CItem unsigned Restor; HRESULT ReadHeader(ISequentialInStream *s, UInt32 &headerSize); - bool IsSupported() const { return Ver == 7 || (Ver == 8 && Restor <= 1); } + bool IsSupported() const { return Ver == 7 || (Ver == 8 && Restor < PPMD8_RESTORE_METHOD_UNSUPPPORTED); } }; HRESULT CItem::ReadHeader(ISequentialInStream *s, UInt32 &headerSize) @@ -218,91 +218,11 @@ STDMETHODIMP CHandler::Close() return S_OK; } -static const UInt32 kTopValue = (1 << 24); -static const UInt32 kBot = (1 << 15); -struct CRangeDecoder -{ - IPpmd7_RangeDec vt; - UInt32 Range; - UInt32 Code; - UInt32 Low; - CByteInBufWrap *Stream; - -public: - bool Init() - { - Code = 0; - Low = 0; - Range = 0xFFFFFFFF; - for (int i = 0; i < 4; i++) - Code = (Code << 8) | Stream->ReadByte(); - return Code < 0xFFFFFFFF; - } - - void Normalize() - { - while ((Low ^ (Low + Range)) < kTopValue || - Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1)) - { - Code = (Code << 8) | Stream->ReadByte(); - Range <<= 8; - Low <<= 8; - } - } - - CRangeDecoder(); -}; - - -extern "C" { - -#define GET_RangeDecoder CRangeDecoder *p = CONTAINER_FROM_VTBL(pp, CRangeDecoder, vt); - -static UInt32 Range_GetThreshold(const IPpmd7_RangeDec *pp, UInt32 total) -{ - GET_RangeDecoder - return p->Code / (p->Range /= total); -} - -static void Range_Decode(const IPpmd7_RangeDec *pp, UInt32 start, UInt32 size) -{ - GET_RangeDecoder - start *= p->Range; - p->Low += start; - p->Code -= start; - p->Range *= size; - p->Normalize(); -} - -static UInt32 Range_DecodeBit(const IPpmd7_RangeDec *pp, UInt32 size0) -{ - GET_RangeDecoder - if (p->Code / (p->Range >>= 14) < size0) - { - Range_Decode(&p->vt, 0, size0); - return 0; - } - else - { - Range_Decode(&p->vt, size0, (1 << 14) - size0); - return 1; - } -} - -} - -CRangeDecoder::CRangeDecoder() -{ - vt.GetThreshold = Range_GetThreshold; - vt.Decode = Range_Decode; - vt.DecodeBit = Range_DecodeBit; -} struct CPpmdCpp { unsigned Ver; - CRangeDecoder _rc; CPpmd7 _ppmd7; CPpmd8 _ppmd8; @@ -339,20 +259,20 @@ struct CPpmdCpp { if (Ver == 7) { - _rc.Stream = inStream; - return _rc.Init(); + _ppmd7.rc.dec.Stream = &inStream->vt; + return (Ppmd7a_RangeDec_Init(&_ppmd7.rc.dec) != 0); } else { _ppmd8.Stream.In = &inStream->vt; - return Ppmd8_RangeDec_Init(&_ppmd8) != 0; + return Ppmd8_Init_RangeDec(&_ppmd8) != 0; } } bool IsFinishedOK() { if (Ver == 7) - return Ppmd7z_RangeDec_IsFinishedOK(&_rc); + return Ppmd7z_RangeDec_IsFinishedOK(&_ppmd7.rc.dec); return Ppmd8_RangeDec_IsFinishedOK(&_ppmd8); } }; @@ -416,14 +336,15 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, size_t i; int sym = 0; + Byte *buf = outBuf.Buf; if (ppmd.Ver == 7) { for (i = 0; i < kBufSize; i++) { - sym = Ppmd7_DecodeSymbol(&ppmd._ppmd7, &ppmd._rc.vt); + sym = Ppmd7a_DecodeSymbol(&ppmd._ppmd7); if (inBuf.Extra || sym < 0) break; - outBuf.Buf[i] = (Byte)sym; + buf[i] = (Byte)sym; } } else @@ -433,7 +354,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, sym = Ppmd8_DecodeSymbol(&ppmd._ppmd8); if (inBuf.Extra || sym < 0) break; - outBuf.Buf[i] = (Byte)sym; + buf[i] = (Byte)sym; } } diff --git a/CPP/7zip/Archive/QcowHandler.cpp b/CPP/7zip/Archive/QcowHandler.cpp index 065f59b3..200ec62d 100644 --- a/CPP/7zip/Archive/QcowHandler.cpp +++ b/CPP/7zip/Archive/QcowHandler.cpp @@ -8,6 +8,7 @@ #include "../../Common/ComTry.h" #include "../../Common/IntToString.h" +#include "../../Common/MyBuffer2.h" #include "../../Windows/PropVariant.h" @@ -31,13 +32,21 @@ namespace NQcow { static const Byte k_Signature[] = SIGNATURE; +/* +VA to PA maps: + high bits (L1) : : in L1 Table : the reference to L1 Table + mid bits (L2) : _numMidBits : in L2 Table : the reference to cluster + low bits : _clusterBits +*/ + class CHandler: public CHandlerImg { unsigned _clusterBits; unsigned _numMidBits; UInt64 _compressedFlag; - CObjectVector<CByteBuffer> _tables; + CObjArray2<UInt32> _dir; + CAlignedBuffer _table; UInt64 _cacheCluster; CByteBuffer _cache; CByteBuffer _cacheCompressed; @@ -63,7 +72,7 @@ class CHandler: public CHandlerImg UInt32 _version; UInt32 _cryptMethod; - HRESULT Seek(UInt64 offset) + HRESULT Seek2(UInt64 offset) { _posInArc = offset; return Stream->Seek(offset, STREAM_SEEK_SET, NULL); @@ -72,7 +81,7 @@ class CHandler: public CHandlerImg HRESULT InitAndSeek() { _virtPos = 0; - return Seek(0); + return Seek2(0); } HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback); @@ -85,10 +94,15 @@ public: }; +static const UInt32 kEmptyDirItem = (UInt32)0 - 1; + STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) *processedSize = 0; + + // printf("\nRead _virtPos = %6d size = %6d\n", (UInt32)_virtPos, size); + if (_virtPos >= _size) return S_OK; { @@ -101,9 +115,9 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) for (;;) { - UInt64 cluster = _virtPos >> _clusterBits; - size_t clusterSize = (size_t)1 << _clusterBits; - size_t lowBits = (size_t)_virtPos & (clusterSize - 1); + const UInt64 cluster = _virtPos >> _clusterBits; + const size_t clusterSize = (size_t)1 << _clusterBits; + const size_t lowBits = (size_t)_virtPos & (clusterSize - 1); { size_t rem = clusterSize - lowBits; if (size > rem) @@ -113,21 +127,19 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) if (cluster == _cacheCluster) { memcpy(data, _cache + lowBits, size); - _virtPos += size; - if (processedSize) - *processedSize = size; - return S_OK; + break; } - UInt64 high = cluster >> _numMidBits; + const UInt64 high = cluster >> _numMidBits; - if (high < _tables.Size()) + if (high < _dir.Size()) { - const CByteBuffer &buffer = _tables[(unsigned)high]; + const UInt32 tabl = _dir[(unsigned)high]; - if (buffer.Size() != 0) + if (tabl != kEmptyDirItem) { - size_t midBits = (size_t)cluster & (((size_t)1 << _numMidBits) - 1); + const Byte *buffer = _table + ((size_t)tabl << (_numMidBits + 3)); + const size_t midBits = (size_t)cluster & (((size_t)1 << _numMidBits) - 1); const Byte *p = (const Byte *)buffer + (midBits << 3); UInt64 v = Get64(p); @@ -137,19 +149,32 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) { if (_version <= 1) return E_FAIL; - unsigned numOffsetBits = (62 - (_clusterBits - 8)); - UInt64 offset = v & (((UInt64)1 << 62) - 1); + + /* + the example of table record for 12-bit clusters (4KB uncompressed). + 2 bits : isCompressed status + 4 bits : num_sectors_minus1; packSize = (num_sectors_minus1 + 1) * 512; + it uses one additional bit over unpacked cluster_bits + 49 bits : offset of 512-sector + 9 bits : offset in 512-sector + */ + + const unsigned numOffsetBits = (62 - (_clusterBits - 9 + 1)); + const UInt64 offset = v & (((UInt64)1 << 62) - 1); const size_t dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9; - offset &= ((UInt64)1 << numOffsetBits) - 1; - UInt64 sectorOffset = offset >> 9 << 9; - UInt64 offset2inCache = sectorOffset - _comprPos; + UInt64 sectorOffset = offset & (((UInt64)1 << numOffsetBits) - (1 << 9)); + const UInt64 offset2inCache = sectorOffset - _comprPos; + // _comprPos is aligned for 512-bytes + // we try to use previous _cacheCompressed that contains compressed data + // that was read for previous unpacking + if (sectorOffset >= _comprPos && offset2inCache < _comprSize) { if (offset2inCache != 0) { _comprSize -= (size_t)offset2inCache; - memmove(_cacheCompressed, _cacheCompressed + offset2inCache, _comprSize); + memmove(_cacheCompressed, _cacheCompressed + (size_t)offset2inCache, _comprSize); _comprPos = sectorOffset; } sectorOffset += _comprSize; @@ -160,25 +185,27 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) _comprSize = 0; } - // printf("\nDeflate"); - if (sectorOffset != _posInArc) + if (dataSize > _comprSize) { - // printf("\nDeflate %12I64x %12I64x\n", sectorOffset, sectorOffset - _posInArc); - RINOK(Seek(sectorOffset)); + if (sectorOffset != _posInArc) + { + // printf("\nDeflate-Seek %12I64x %12I64x\n", sectorOffset, sectorOffset - _posInArc); + RINOK(Seek2(sectorOffset)); + } + if (_cacheCompressed.Size() < dataSize) + return E_FAIL; + const size_t dataSize3 = dataSize - _comprSize; + size_t dataSize2 = dataSize3; + // printf("\n\n=======\nReadStream = %6d _comprPos = %6d \n", (UInt32)dataSize2, (UInt32)_comprPos); + RINOK(ReadStream(Stream, _cacheCompressed + _comprSize, &dataSize2)); + _posInArc += dataSize2; + if (dataSize2 != dataSize3) + return E_FAIL; + _comprSize += dataSize2; } - if (_cacheCompressed.Size() < dataSize) - return E_FAIL; - size_t dataSize3 = dataSize - _comprSize; - size_t dataSize2 = dataSize3; - RINOK(ReadStream(Stream, _cacheCompressed + _comprSize, &dataSize2)); - _posInArc += dataSize2; - if (dataSize2 != dataSize3) - return E_FAIL; - _comprSize += dataSize2; - const size_t kSectorMask = (1 << 9) - 1; - size_t offsetInSector = ((size_t)offset & kSectorMask); + const size_t offsetInSector = ((size_t)offset & kSectorMask); _bufInStreamSpec->Init(_cacheCompressed + offsetInSector, dataSize - offsetInSector); _cacheCluster = (UInt64)(Int64)-1; @@ -187,7 +214,7 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) _bufOutStreamSpec->Init(_cache, clusterSize); // Do we need to use smaller block than clusterSize for last cluster? - UInt64 blockSize64 = clusterSize; + const UInt64 blockSize64 = clusterSize; HRESULT res = _deflateDecoderSpec->Code(_bufInStream, _bufOutStream, NULL, &blockSize64, NULL); /* @@ -206,10 +233,7 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) continue; /* memcpy(data, _cache + lowBits, size); - _virtPos += size; - if (processedSize) - *processedSize = size; - return S_OK; + break; */ } @@ -221,7 +245,7 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) if (v != _posInArc) { // printf("\n%12I64x\n", v - _posInArc); - RINOK(Seek(v)); + RINOK(Seek2(v)); } HRESULT res = Stream->Read(data, size, &size); _posInArc += size; @@ -235,11 +259,13 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) } memset(data, 0, size); - _virtPos += size; - if (processedSize) - *processedSize = size; - return S_OK; + break; } + + _virtPos += size; + if (processedSize) + *processedSize = size; + return S_OK; } @@ -347,8 +373,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) const UInt64 backOffset = Get64(buf + 8); // UInt32 backSize = Get32(buf + 0x10); - UInt64 l1Offset = 0; - UInt32 l1Size = 0; + UInt64 l1Offset; + UInt32 l1Size; if (_version == 1) { @@ -364,8 +390,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) l1Offset = Get64(buf + 0x28); if (l1Offset < 0x30) return S_FALSE; - unsigned numBits2 = (_clusterBits + _numMidBits); - UInt64 l1Size64 = (_size + (((UInt64)1 << numBits2) - 1)) >> numBits2; + const unsigned numBits2 = (_clusterBits + _numMidBits); + const UInt64 l1Size64 = (_size + (((UInt64)1 << numBits2) - 1)) >> numBits2; if (l1Size64 > ((UInt32)1 << 31)) return S_FALSE; l1Size = (UInt32)l1Size64; @@ -381,8 +407,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) l1Size = Get32(buf + 0x24); l1Offset = Get64(buf + 0x28); // must be aligned for cluster - UInt64 refOffset = Get64(buf + 0x30); // must be aligned for cluster - UInt32 refClusters = Get32(buf + 0x38); + const UInt64 refOffset = Get64(buf + 0x30); // must be aligned for cluster + const UInt32 refClusters = Get32(buf + 0x38); // UInt32 numSnapshots = Get32(buf + 0x3C); // UInt64 snapshotsOffset = Get64(buf + 0x40); // must be aligned for cluster @@ -393,14 +419,14 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) if (refClusters != 0) { - size_t numBytes = refClusters << _clusterBits; + const size_t numBytes = refClusters << _clusterBits; /* CByteBuffer refs; refs.Alloc(numBytes); RINOK(stream->Seek(refOffset, STREAM_SEEK_SET, NULL)); RINOK(ReadStream_FALSE(stream, refs, numBytes)); */ - UInt64 end = refOffset + numBytes; + const UInt64 end = refOffset + numBytes; if (_phySize < end) _phySize = end; /* @@ -426,7 +452,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) CByteBuffer table; { - size_t t1SizeBytes = (size_t)l1Size << 3; + const size_t t1SizeBytes = (size_t)l1Size << 3; if ((t1SizeBytes >> 3) != l1Size) return S_FALSE; table.Alloc(t1SizeBytes); @@ -442,41 +468,72 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) } } - if (openCallback) + _compressedFlag = (_version <= 1) ? ((UInt64)1 << 63) : ((UInt64)1 << 62); + const UInt64 offsetMask = _compressedFlag - 1; + + UInt32 numTables = 0; + UInt32 i; + + for (i = 0; i < l1Size; i++) { - UInt64 totalBytes = (UInt64)l1Size << (_numMidBits + 3); - RINOK(openCallback->SetTotal(NULL, &totalBytes)); + const UInt64 v = Get64((const Byte *)table + (size_t)i * 8) & offsetMask; + if (v != 0) + numTables++; } - _compressedFlag = (_version <= 1) ? ((UInt64)1 << 63) : ((UInt64)1 << 62); - const UInt64 offsetMask = _compressedFlag - 1; + if (numTables != 0) + { + const size_t size = (size_t)numTables << (_numMidBits + 3); + if (size >> (_numMidBits + 3) != numTables) + return E_OUTOFMEMORY; + _table.Alloc(size); + if (!_table.IsAllocated()) + return E_OUTOFMEMORY; + } + + _dir.SetSize(l1Size); - for (UInt32 i = 0; i < l1Size; i++) + UInt32 curTable = 0; + + if (openCallback) { - if (openCallback) - { - UInt64 numBytes = (UInt64)i << (_numMidBits + 3); - RINOK(openCallback->SetCompleted(NULL, &numBytes)); - } + const UInt64 totalBytes = (UInt64)numTables << (_numMidBits + 3); + RINOK(openCallback->SetTotal(NULL, &totalBytes)); + } - CByteBuffer &buf2 = _tables.AddNew(); - + for (i = 0; i < l1Size; i++) + { + Byte *buf2; + const size_t midSize = (size_t)1 << (_numMidBits + 3); + { - UInt64 v = Get64((const Byte *)table + (size_t)i * 8); - v &= offsetMask; + const UInt64 v = Get64((const Byte *)table + (size_t)i * 8) & offsetMask; if (v == 0) + { + _dir[i] = kEmptyDirItem; continue; + } + + _dir[i] = curTable; + const size_t tableOffset = ((size_t)curTable << (_numMidBits + 3)); + buf2 = (Byte *)_table + tableOffset; + curTable++; + + if (openCallback && (tableOffset & 0xFFFFF) == 0) + { + const UInt64 numBytes = tableOffset; + RINOK(openCallback->SetCompleted(NULL, &numBytes)); + } - buf2.Alloc((size_t)1 << (_numMidBits + 3)); RINOK(stream->Seek(v, STREAM_SEEK_SET, NULL)); - RINOK(ReadStream_FALSE(stream, buf2, clusterSize)); + RINOK(ReadStream_FALSE(stream, buf2, midSize)); - const UInt64 end = v + clusterSize; + const UInt64 end = v + midSize; if (_phySize < end) _phySize = end; } - for (size_t k = 0; k < clusterSize; k += 8) + for (size_t k = 0; k < midSize; k += 8) { const UInt64 v = Get64((const Byte *)buf2 + (size_t)k); if (v == 0) @@ -519,12 +576,15 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) } } - UInt64 end = offset + dataSize; + const UInt64 end = offset + dataSize; if (_phySize < end) _phySize = end; } } + if (curTable != numTables) + return E_FAIL; + if (_cryptMethod != 0) _unsupported = true; @@ -538,7 +598,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) STDMETHODIMP CHandler::Close() { - _tables.Clear(); + _table.Free(); + _dir.Free(); _phySize = 0; _size = 0; @@ -588,7 +649,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea _deflateDecoderSpec->Set_NeedFinishInput(true); } - size_t clusterSize = (size_t)1 << _clusterBits; + const size_t clusterSize = (size_t)1 << _clusterBits; _cache.AllocAtLeast(clusterSize); _cacheCompressed.AllocAtLeast(clusterSize * 2); } diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.cpp b/CPP/7zip/Archive/Rar/Rar5Handler.cpp index 320771d5..bb8a2edb 100644 --- a/CPP/7zip/Archive/Rar/Rar5Handler.cpp +++ b/CPP/7zip/Archive/Rar/Rar5Handler.cpp @@ -124,19 +124,13 @@ static unsigned ReadVarInt(const Byte *p, size_t maxSize, UInt64 *val) bool CLinkInfo::Parse(const Byte *p, unsigned size) { const Byte *pStart = p; - unsigned num = ReadVarInt(p, size, &Type); - if (num == 0) return false; p += num; size -= num; - - num = ReadVarInt(p, size, &Flags); - if (num == 0) return false; p += num; size -= num; - + unsigned num; UInt64 len; - num = ReadVarInt(p, size, &len); - if (num == 0) return false; p += num; size -= num; - + num = ReadVarInt(p, size, &Type); if (num == 0) { return false; } p += num; size -= num; + num = ReadVarInt(p, size, &Flags); if (num == 0) { return false; } p += num; size -= num; + num = ReadVarInt(p, size, &len); if (num == 0) { return false; } p += num; size -= num; if (size != len) return false; - NameLen = (unsigned)len; NameOffset = (unsigned)(p - pStart); return true; @@ -319,10 +313,10 @@ bool CCryptoInfo::Parse(const Byte *p, size_t size) Cnt = 0; unsigned num = ReadVarInt(p, size, &Algo); - if (num == 0) return false; p += num; size -= num; + if (num == 0) { return false; } p += num; size -= num; num = ReadVarInt(p, size, &Flags); - if (num == 0) return false; p += num; size -= num; + if (num == 0) { return false; } p += num; size -= num; if (size > 0) Cnt = p[0]; @@ -344,10 +338,10 @@ bool CItem::FindExtra_Version(UInt64 &version) const UInt64 flags; unsigned num = ReadVarInt(p, size, &flags); - if (num == 0) return false; p += num; size -= num; + if (num == 0) { return false; } p += num; size -= num; num = ReadVarInt(p, size, &version); - if (num == 0) return false; p += num; size -= num; + if (num == 0) { return false; } p += num; size -= num; return size == 0; } @@ -406,8 +400,8 @@ void CItem::Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) s.SetFrom_CalcLen((const char *)(Extra + link.NameOffset), link.NameLen); UString unicode; - if (ConvertUTF8ToUnicode(s, unicode)) - prop = NItemName::GetOsPath(unicode); + ConvertUTF8ToUnicode(s, unicode); + prop = NItemName::GetOsPath(unicode); } bool CItem::GetAltStreamName(AString &name) const @@ -596,11 +590,12 @@ public: static HRESULT MySetPassword(ICryptoGetTextPassword *getTextPassword, NCrypto::NRar5::CDecoder *cryptoDecoderSpec) { - CMyComBSTR password; + CMyComBSTR_Wipe password; RINOK(getTextPassword->CryptoGetTextPassword(&password)); - AString utf8; + AString_Wipe utf8; const unsigned kPasswordLen_MAX = 127; - UString unicode = (LPCOLESTR)password; + UString_Wipe unicode; + unicode.SetFromBstr(password); if (unicode.Len() > kPasswordLen_MAX) unicode.DeleteFrom(kPasswordLen_MAX); ConvertUnicodeToUTF8(unicode, utf8); @@ -1153,7 +1148,7 @@ HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSiz } else { - res = res; + // res = res; } if (isCryptoMode) @@ -1434,8 +1429,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) AString s; s.SetFrom_CalcLen((const char *)(const Byte *)cmt, (unsigned)cmt.Size()); UString unicode; - if (ConvertUTF8ToUnicode(s, unicode)) - prop = unicode; + ConvertUTF8ToUnicode(s, unicode); + prop = unicode; } } break; @@ -1686,13 +1681,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val if (name[0] != ':') s += ':'; s += name; - if (!ConvertUTF8ToUnicode(s, unicodeName)) - break; + ConvertUTF8ToUnicode(s, unicodeName); } else { - if (!ConvertUTF8ToUnicode(item.Name, unicodeName)) - break; + ConvertUTF8ToUnicode(item.Name, unicodeName); + if (item.Version_Defined) { char temp[32]; @@ -1752,8 +1746,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { name.DeleteFrontal(1); UString unicodeName; - if (ConvertUTF8ToUnicode(name, unicodeName)) - prop = unicodeName; + ConvertUTF8ToUnicode(name, unicodeName); + prop = unicodeName; } } break; diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp index dd78e312..7491c50b 100644 --- a/CPP/7zip/Archive/Rar/RarHandler.cpp +++ b/CPP/7zip/Archive/Rar/RarHandler.cpp @@ -466,7 +466,7 @@ bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item) for (unsigned i = 0; i < sizeof(item.Salt); i++) item.Salt[i] = p[i]; p += sizeof(item.Salt); - size -= sizeof(item.Salt); + size -= (unsigned)sizeof(item.Salt); } // some rar archives have HasExtTime flag without field. @@ -526,31 +526,36 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass } // m_RarAESSpec->SetRar350Mode(ArcInfo.IsEncryptOld()); - // Salt - const UInt32 kSaltSize = 8; - Byte salt[kSaltSize]; - if (!ReadBytesAndTestSize(salt, kSaltSize)) - return S_FALSE; - m_Position += kSaltSize; - RINOK(m_RarAESSpec->SetDecoderProperties2(salt, kSaltSize)) - // Password - CMyComBSTR password; - RINOK(getTextPassword->CryptoGetTextPassword(&password)) - unsigned len = 0; - if (password) - len = MyStringLen(password); - if (len > kPasswordLen_MAX) - len = kPasswordLen_MAX; - - CByteArr buffer(len * 2); - for (unsigned i = 0; i < len; i++) { - wchar_t c = password[i]; - ((Byte *)buffer)[i * 2] = (Byte)c; - ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); + // Salt + const UInt32 kSaltSize = 8; + Byte salt[kSaltSize]; + if (!ReadBytesAndTestSize(salt, kSaltSize)) + return S_FALSE; + m_Position += kSaltSize; + RINOK(m_RarAESSpec->SetDecoderProperties2(salt, kSaltSize)) } - m_RarAESSpec->SetPassword((const Byte *)buffer, len * 2); + { + // Password + CMyComBSTR_Wipe password; + RINOK(getTextPassword->CryptoGetTextPassword(&password)) + unsigned len = 0; + if (password) + len = MyStringLen(password); + if (len > kPasswordLen_MAX) + len = kPasswordLen_MAX; + + CByteBuffer_Wipe buffer(len * 2); + for (unsigned i = 0; i < len; i++) + { + wchar_t c = password[i]; + ((Byte *)buffer)[i * 2] = (Byte)c; + ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); + } + + m_RarAESSpec->SetPassword((const Byte *)buffer, len * 2); + } const UInt32 kDecryptedBufferSize = (1 << 12); if (m_DecryptedDataAligned.Size() == 0) @@ -1621,7 +1626,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, // if (getTextPassword) { - CMyComBSTR password; + CMyComBSTR_Wipe password; RINOK(getTextPassword->CryptoGetTextPassword(&password)); if (item.UnPackVersion >= 29) @@ -1631,7 +1636,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, len = MyStringLen(password); if (len > kPasswordLen_MAX) len = kPasswordLen_MAX; - CByteArr buffer(len * 2); + CByteBuffer_Wipe buffer(len * 2); for (unsigned k = 0; k < len; k++) { wchar_t c = password[k]; @@ -1642,13 +1647,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } else { - AString oemPassword; + AString_Wipe oemPassword; if (password) { - UString unicode = (LPCOLESTR)password; + UString_Wipe unicode; + unicode.SetFromBstr(password); if (unicode.Len() > kPasswordLen_MAX) unicode.DeleteFrom(kPasswordLen_MAX); - oemPassword = UnicodeStringToMultiByte(unicode, CP_OEMCP); + UnicodeStringToMultiByte2(oemPassword, unicode, CP_OEMCP); } rar20CryptoDecoderSpec->SetPassword((const Byte *)(const char *)oemPassword, oemPassword.Len()); } diff --git a/CPP/7zip/Archive/Rar/RarHandler.h b/CPP/7zip/Archive/Rar/RarHandler.h index e444bd77..a62b60cd 100644 --- a/CPP/7zip/Archive/Rar/RarHandler.h +++ b/CPP/7zip/Archive/Rar/RarHandler.h @@ -26,7 +26,7 @@ struct CInArcInfo UInt32 DataCRC; bool EndOfArchive_was_Read; - CInArcInfo(): EndFlags(0), EndOfArchive_was_Read(false), VolNumber(0) {} + CInArcInfo(): EndFlags(0), VolNumber(0), EndOfArchive_was_Read(false) {} UInt64 GetPhySize() const { return EndPos - StartPos; } diff --git a/CPP/7zip/Archive/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp index f4a10b1d..6705aee0 100644 --- a/CPP/7zip/Archive/SplitHandler.cpp +++ b/CPP/7zip/Archive/SplitHandler.cpp @@ -142,8 +142,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) } int dotPos = name.ReverseFind_Dot(); - const UString prefix = name.Left(dotPos + 1); - const UString ext = name.Ptr(dotPos + 1); + const UString prefix = name.Left((unsigned)(dotPos + 1)); + const UString ext = name.Ptr((unsigned)(dotPos + 1)); UString ext2 = ext; ext2.MakeLower_Ascii(); diff --git a/CPP/7zip/Archive/SquashfsHandler.cpp b/CPP/7zip/Archive/SquashfsHandler.cpp index 89de660f..74bc8fb8 100644 --- a/CPP/7zip/Archive/SquashfsHandler.cpp +++ b/CPP/7zip/Archive/SquashfsHandler.cpp @@ -41,9 +41,9 @@ static const unsigned kNumDirLevelsMax = (1 << 10); #define Get64(p) (be ? GetBe64(p) : GetUi64(p)) */ -UInt16 Get16b(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); } -UInt32 Get32b(const Byte *p, bool be) { return be ? GetBe32(p) : GetUi32(p); } -UInt64 Get64b(const Byte *p, bool be) { return be ? GetBe64(p) : GetUi64(p); } +static UInt16 Get16b(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); } +static UInt32 Get32b(const Byte *p, bool be) { return be ? GetBe32(p) : GetUi32(p); } +static UInt64 Get64b(const Byte *p, bool be) { return be ? GetBe64(p) : GetUi64(p); } #define Get16(p) Get16b(p, be) #define Get32(p) Get32b(p, be) @@ -121,6 +121,10 @@ static const char * const k_Flags[] = , "ALWAYS_FRAGMENTS" , "DUPLICATES_REMOVED" , "EXPORTABLE" + , "UNCOMPRESSED_XATTRS" + , "NO_XATTRS" + , "COMPRESSOR_OPTIONS" + , "UNCOMPRESSED_IDS" }; static const UInt32 kNotCompressedBit16 = (1 << 15); @@ -129,10 +133,10 @@ static const UInt32 kNotCompressedBit32 = (1 << 24); #define GET_COMPRESSED_BLOCK_SIZE(size) ((size) & ~kNotCompressedBit32) #define IS_COMPRESSED_BLOCK(size) (((size) & kNotCompressedBit32) == 0) -static const UInt32 kHeaderSize1 = 0x33; -static const UInt32 kHeaderSize2 = 0x3F; +// static const UInt32 kHeaderSize1 = 0x33; +// static const UInt32 kHeaderSize2 = 0x3F; static const UInt32 kHeaderSize3 = 0x77; -static const UInt32 kHeaderSize4 = 0x60; +// static const UInt32 kHeaderSize4 = 0x60; struct CHeader { @@ -1243,7 +1247,8 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool &status, &g_Alloc); if (res != 0) return SResToHRESULT(res); - if (status != LZMA_STATUS_FINISHED_WITH_MARK) + if (status != LZMA_STATUS_FINISHED_WITH_MARK + && status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) return S_FALSE; } else @@ -1310,7 +1315,7 @@ HRESULT CHandler::ReadData(CData &data, UInt64 start, UInt64 end) { if (end < start || end - start >= ((UInt64)1 << 32)) return S_FALSE; - UInt32 size = (UInt32)(end - start); + const UInt32 size = (UInt32)(end - start); RINOK(_stream->Seek(start, STREAM_SEEK_SET, NULL)); _dynOutStreamSpec->Init(); UInt32 packPos = 0; @@ -1322,8 +1327,11 @@ HRESULT CHandler::ReadData(CData &data, UInt64 start, UInt64 end) return S_FALSE; UInt32 packSize = size - packPos; RINOK(ReadMetadataBlock(packSize)); - if (_dynOutStreamSpec->GetSize() >= ((UInt64)1 << 32)) - return S_FALSE; + { + const size_t tSize = _dynOutStreamSpec->GetSize(); + if (tSize != (UInt32)tSize) + return S_FALSE; + } packPos += packSize; } data.UnpackPos.Add((UInt32)_dynOutStreamSpec->GetSize()); @@ -1487,7 +1495,7 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned if (_openCodePage == CP_UTF8) { tempString.SetFrom_CalcLen((const char *)p, size); - if (!CheckUTF8(tempString)) + if (!CheckUTF8_AString(tempString)) _openCodePage = CP_OEMCP; } @@ -1608,11 +1616,14 @@ HRESULT CHandler::Open2(IInStream *inStream) { UInt32 pos = 0; UInt32 totalSize = (UInt32)_inodesData.Data.Size(); + const unsigned kMinNodeParseSize = 4; + if (_h.NumInodes > totalSize / kMinNodeParseSize) + return S_FALSE; _nodesPos.ClearAndReserve(_h.NumInodes); _nodes.ClearAndReserve(_h.NumInodes); // we use _blockToNode for binary search seed optimizations _blockToNode.ClearAndReserve(_inodesData.GetNumBlocks() + 1); - int curBlock = 0; + unsigned curBlock = 0; for (UInt32 i = 0; i < _h.NumInodes; i++) { CNode n; @@ -2090,9 +2101,9 @@ HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) bool compressed; if (blockIndex < _blockCompressed.Size()) { - compressed = _blockCompressed[(int)blockIndex]; - blockOffset = _blockOffsets[(int)blockIndex]; - packBlockSize = (UInt32)(_blockOffsets[(int)blockIndex + 1] - blockOffset); + compressed = _blockCompressed[(unsigned)blockIndex]; + blockOffset = _blockOffsets[(unsigned)blockIndex]; + packBlockSize = (UInt32)(_blockOffsets[(unsigned)blockIndex + 1] - blockOffset); blockOffset += node.StartBlock; } else @@ -2126,14 +2137,16 @@ HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) bool outBufWasWritten; UInt32 outBufWasWrittenSize; HRESULT res = Decompress(_outStream, _cachedBlock, &outBufWasWritten, &outBufWasWrittenSize, packBlockSize, _h.BlockSize); + RINOK(res); if (outBufWasWritten) _cachedUnpackBlockSize = outBufWasWrittenSize; else _cachedUnpackBlockSize = (UInt32)_outStreamSpec->GetPos(); - RINOK(res); } else { + if (packBlockSize > _h.BlockSize) + return S_FALSE; RINOK(ReadStream_FALSE(_limitedInStream, _cachedBlock, packBlockSize)); _cachedUnpackBlockSize = packBlockSize; } diff --git a/CPP/7zip/Archive/SwfHandler.cpp b/CPP/7zip/Archive/SwfHandler.cpp index ebb6acfd..9666c69d 100644 --- a/CPP/7zip/Archive/SwfHandler.cpp +++ b/CPP/7zip/Archive/SwfHandler.cpp @@ -776,21 +776,21 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb static UInt16 Read16(CInBuffer &stream) { - UInt16 res = 0; - for (int i = 0; i < 2; i++) + UInt32 res = 0; + for (unsigned i = 0; i < 2; i++) { Byte b; if (!stream.ReadByte(b)) throw 1; - res |= (UInt16)b << (i * 8); + res |= (UInt32)b << (i * 8); } - return res; + return (UInt16)res; } static UInt32 Read32(CInBuffer &stream) { UInt32 res = 0; - for (int i = 0; i < 4; i++) + for (unsigned i = 0; i < 4; i++) { Byte b; if (!stream.ReadByte(b)) @@ -826,7 +826,7 @@ UInt32 CBitReader::ReadBits(unsigned numBits) res <<= numBits; NumBits -= numBits; res |= (Val >> NumBits); - Val &= (1 << NumBits) - 1; + Val = (Byte)(Val & (((unsigned)1 << NumBits) - 1)); break; } else diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp index 72fbf74e..bc00e3fc 100644 --- a/CPP/7zip/Archive/Tar/TarHandler.cpp +++ b/CPP/7zip/Archive/Tar/TarHandler.cpp @@ -24,7 +24,9 @@ using namespace NWindows; namespace NArchive { namespace NTar { -static const UINT k_DefaultCodePage = CP_OEMCP; // it uses it if UTF8 check in names shows error +// 21.02: we use UTF8 code page by default, even if some files show error +// before 21.02 : CP_OEMCP; +// static const UINT k_DefaultCodePage = CP_UTF8; static const Byte kProps[] = @@ -39,13 +41,15 @@ static const Byte kProps[] = kpidGroup, kpidSymLink, kpidHardLink, + kpidCharacts // kpidLinkType }; static const Byte kArcProps[] = { kpidHeadersSize, - kpidCodePage + kpidCodePage, + kpidCharacts }; IMP_IInArchive_Props @@ -67,8 +71,12 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { case k_ErrorType_UnexpectedEnd: flags = kpv_ErrorFlags_UnexpectedEnd; break; case k_ErrorType_Corrupted: flags = kpv_ErrorFlags_HeadersError; break; + // case k_ErrorType_OK: break; + // case k_ErrorType_Warning: break; + default: break; } - prop = flags; + if (flags != 0) + prop = flags; break; } @@ -96,6 +104,13 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) prop = name; break; } + + case kpidCharacts: + { + AString s = _encodingCharacts.GetCharactsString(); + prop = s; + break; + } } prop.Detach(value); return S_OK; @@ -119,12 +134,64 @@ HRESULT CHandler::ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx & */ if (item.IsPaxExtendedHeader()) _thereIsPaxExtendedHeader = true; + if (item.IsThereWarning()) + _warning = true; } _phySize += item.HeaderSize; _headersSize += item.HeaderSize; return S_OK; } + +void CEncodingCharacts::Check(const AString &s) +{ + IsAscii = s.IsAscii(); + if (!IsAscii) + { + /* + { + Oem_Checked = true; + UString u; + MultiByteToUnicodeString2(u, s, CP_OEMCP); + Oem_Ok = (u.Find((wchar_t)0xfffd) <= 0); + } + Utf_Checked = true; + */ + UtfCheck.Check_AString(s); + } +} + + +AString CEncodingCharacts::GetCharactsString() const +{ + AString s; + if (IsAscii) + { + s += "ASCII"; + } + /* + if (Oem_Checked) + { + s.Add_Space_if_NotEmpty(); + s += (Oem_Ok ? "oem-ok" : "oem-error"); + } + if (Utf_Checked) + */ + else + { + s.Add_Space_if_NotEmpty(); + s += (UtfCheck.IsOK() ? "UTF8" : "UTF8-ERROR"); // "UTF8-error" + { + AString s2; + UtfCheck.PrintStatus(s2); + s.Add_Space_if_NotEmpty(); + s += s2; + } + } + return s; +} + + HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) { UInt64 endPos = 0; @@ -135,12 +202,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) _phySizeDefined = true; - bool utf8_OK = true; - if (!_forceCodePage) - { - if (!utf8_OK) - _curCodePage = k_DefaultCodePage; - } + // bool utf8_OK = true; for (;;) { @@ -151,8 +213,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) break; _isArc = true; - _items.Add(item); + /* if (!_forceCodePage) { if (utf8_OK) utf8_OK = CheckUTF8(item.Name, item.NameCouldBeReduced); @@ -160,8 +222,14 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) if (utf8_OK) utf8_OK = CheckUTF8(item.User); if (utf8_OK) utf8_OK = CheckUTF8(item.Group); } - - RINOK(stream->Seek(item.GetPackSizeAligned(), STREAM_SEEK_CUR, &_phySize)); + */ + + item.EncodingCharacts.Check(item.Name); + _encodingCharacts.Update(item.EncodingCharacts); + + _items.Add(item); + + RINOK(stream->Seek((Int64)item.GetPackSizeAligned(), STREAM_SEEK_CUR, &_phySize)); if (_phySize > endPos) { _error = k_ErrorType_UnexpectedEnd; @@ -188,11 +256,13 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) } } + /* if (!_forceCodePage) { if (!utf8_OK) _curCodePage = k_DefaultCodePage; } + */ _openCodePage = _curCodePage; if (_items.Size() == 0) @@ -255,6 +325,7 @@ STDMETHODIMP CHandler::Close() _latestIsRead = false; // _isSparse = false; _thereIsPaxExtendedHeader = false; + _encodingCharacts.Clear(); _items.Clear(); _seqStream.Release(); _stream.Release(); @@ -315,7 +386,8 @@ void CHandler::TarStringToUnicode(const AString &s, NWindows::NCOM::CPropVariant else MultiByteToUnicodeString2(dest, s, _curCodePage); if (toOs) - NItemName::ReplaceToOsSlashes_Remove_TailSlash(dest); + NItemName::ReplaceToOsSlashes_Remove_TailSlash(dest, + true); // useBackslashReplacement prop = dest; } @@ -358,6 +430,17 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidSymLink: if (item->LinkFlag == NFileHeader::NLinkFlag::kSymLink && !item->LinkName.IsEmpty()) TarStringToUnicode(item->LinkName, prop); break; case kpidHardLink: if (item->LinkFlag == NFileHeader::NLinkFlag::kHardLink && !item->LinkName.IsEmpty()) TarStringToUnicode(item->LinkName, prop); break; // case kpidLinkType: prop = (int)item->LinkFlag; break; + case kpidCharacts: + { + AString s = item->EncodingCharacts.GetCharactsString(); + if (item->IsThereWarning()) + { + s.Add_Space_if_NotEmpty(); + s += "HEADER_ERROR"; + } + prop = s; + break; + } } prop.Detach(value); return S_OK; @@ -407,7 +490,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 askMode = testMode ? NExtract::NAskMode::kTest : NExtract::NAskMode::kExtract; - Int32 index = allFilesMode ? i : indices[i]; + const UInt32 index = allFilesMode ? i : indices[i]; const CItemEx *item; if (seqMode) { @@ -475,7 +558,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, { if (!seqMode) { - RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL)); + RINOK(_stream->Seek((Int64)item->GetDataPosition(), STREAM_SEEK_SET, NULL)); } streamSpec->Init(item->GetPackSizeAligned()); RINOK(copyCoder->Code(inStream2, outStream, NULL, NULL, progress)); @@ -566,7 +649,7 @@ STDMETHODIMP CSparseStream::Read(void *data, UInt32 size, UInt32 *processedSize) UInt64 phyPos = PhyOffsets[left] + relat; if (_needStartSeek || _phyPos != phyPos) { - RINOK(Handler->_stream->Seek(item.GetDataPosition() + phyPos, STREAM_SEEK_SET, NULL)); + RINOK(Handler->_stream->Seek((Int64)(item.GetDataPosition() + phyPos), STREAM_SEEK_SET, NULL)); _needStartSeek = false; _phyPos = phyPos; } @@ -604,7 +687,7 @@ STDMETHODIMP CSparseStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPos } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _virtPos = offset; + _virtPos = (UInt64)offset; if (newPosition) *newPosition = _virtPos; return S_OK; @@ -650,7 +733,6 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) void CHandler::Init() { _forceCodePage = false; - // _codePage = CP_OEMCP; _curCodePage = _specifiedCodePage = CP_UTF8; // CP_OEMCP; _thereIsPaxExtendedHeader = false; } diff --git a/CPP/7zip/Archive/Tar/TarHandler.h b/CPP/7zip/Archive/Tar/TarHandler.h index eb9c049e..4834c2a7 100644 --- a/CPP/7zip/Archive/Tar/TarHandler.h +++ b/CPP/7zip/Archive/Tar/TarHandler.h @@ -48,6 +48,8 @@ private: UInt32 _curCodePage; UInt32 _openCodePage; + CEncodingCharacts _encodingCharacts; + NCompress::CCopyCoder *copyCoderSpec; CMyComPtr<ICompressCoder> copyCoder; diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp index 41934339..7a7a2cba 100644 --- a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp +++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp @@ -25,8 +25,8 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) return S_OK; } -HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, - AString &res, UINT codePage, bool convertSlash = false) +HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res, + UINT codePage, unsigned utfFlags, bool convertSlash) { NCOM::CPropVariant prop; RINOK(callback->GetProperty(index, propId, &prop)); @@ -39,7 +39,7 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro if (codePage == CP_UTF8) { - ConvertUnicodeToUTF8(s, res); + ConvertUnicodeToUTF8_Flags(s, res, utfFlags); // if (!ConvertUnicodeToUTF8(s, res)) // return E_INVALIDARG; } else @@ -56,8 +56,8 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro static int CompareUpdateItems(void *const *p1, void *const *p2, void *) { - const CUpdateItem &u1 = *(*((const CUpdateItem **)p1)); - const CUpdateItem &u2 = *(*((const CUpdateItem **)p2)); + const CUpdateItem &u1 = *(*((const CUpdateItem *const *)p1)); + const CUpdateItem &u2 = *(*((const CUpdateItem *const *)p2)); if (!u1.NewProps) { if (u2.NewProps) @@ -78,8 +78,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if ((_stream && (_error != k_ErrorType_OK || _warning /* || _isSparse */)) || _seqStream) return E_NOTIMPL; CObjectVector<CUpdateItem> updateItems; - UINT codePage = (_forceCodePage ? _specifiedCodePage : _openCodePage); - + const UINT codePage = (_forceCodePage ? _specifiedCodePage : _openCodePage); + const unsigned utfFlags = g_Unicode_To_UTF8_Flags; + /* + // for debug only: + unsigned utfFlags = 0; + utfFlags |= UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE; + utfFlags |= UTF_FLAG__TO_UTF8__SURROGATE_ERROR; + */ + for (UInt32 i = 0; i < numItems; i++) { CUpdateItem ui; @@ -94,7 +101,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt ui.NewProps = IntToBool(newProps); ui.NewData = IntToBool(newData); - ui.IndexInArc = indexInArc; + ui.IndexInArc = (int)indexInArc; ui.IndexInClient = i; if (IntToBool(newProps)) @@ -138,11 +145,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt ui.MTime = NTime::FileTimeToUnixTime64(prop.filetime); } - RINOK(GetPropString(callback, i, kpidPath, ui.Name, codePage, true)); + RINOK(GetPropString(callback, i, kpidPath, ui.Name, codePage, utfFlags, true)); if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/') ui.Name += '/'; - RINOK(GetPropString(callback, i, kpidUser, ui.User, codePage)); - RINOK(GetPropString(callback, i, kpidGroup, ui.Group, codePage)); + RINOK(GetPropString(callback, i, kpidUser, ui.User, codePage, utfFlags, false)); + RINOK(GetPropString(callback, i, kpidGroup, ui.Group, codePage, utfFlags, false)); } if (IntToBool(newData)) @@ -168,7 +175,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt updateItems.Sort(CompareUpdateItems, NULL); } - return UpdateArchive(_stream, outStream, _items, updateItems, codePage, callback); + return UpdateArchive(_stream, outStream, _items, updateItems, codePage, utfFlags, callback); COM_TRY_END } diff --git a/CPP/7zip/Archive/Tar/TarHeader.h b/CPP/7zip/Archive/Tar/TarHeader.h index 47971b58..249368f6 100644 --- a/CPP/7zip/Archive/Tar/TarHeader.h +++ b/CPP/7zip/Archive/Tar/TarHeader.h @@ -58,6 +58,7 @@ namespace NFileHeader const char kGnu_LongLink = 'K'; const char kGnu_LongName = 'L'; const char kSparse = 'S'; + const char kLabel = 'V'; const char kDumpDir = 'D'; /* GNUTYPE_DUMPDIR. data: list of files created by the --incremental (-G) option Each file name is preceded by either diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp index 32761658..0099e6f7 100644 --- a/CPP/7zip/Archive/Tar/TarIn.cpp +++ b/CPP/7zip/Archive/Tar/TarIn.cpp @@ -81,14 +81,14 @@ static void ReadString(const char *s, unsigned size, AString &result) static bool ParseInt64(const char *p, Int64 &val) { UInt32 h = GetBe32(p); - val = GetBe64(p + 4); + val = (Int64)GetBe64(p + 4); if (h == (UInt32)1 << 31) return ((val >> 63) & 1) == 0; if (h == (UInt32)(Int32)-1) return ((val >> 63) & 1) != 0; UInt64 uv; bool res = OctalToNumber(p, 12, uv); - val = uv; + val = (Int64)uv; return res; } @@ -112,7 +112,9 @@ static bool ParseSize(const char *p, UInt64 &val) val = GetBe64(p + 4); return ((val >> 63) & 1) == 0; } - return OctalToNumber(p, 12, val); + return OctalToNumber(p, 12, val, + true // 20.03: allow empty size for 'V' Label entry + ); } #define CHECK(x) { if (!(x)) return k_IsArc_Res_NO; } @@ -201,8 +203,8 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE // we allow empty Mode value for LongName prefix items RIF(OctalToNumber32(p, 8, item.Mode, true)); p += 8; - if (!OctalToNumber32(p, 8, item.UID)) item.UID = 0; p += 8; - if (!OctalToNumber32(p, 8, item.GID)) item.GID = 0; p += 8; + if (!OctalToNumber32(p, 8, item.UID)) { item.UID = 0; } p += 8; + if (!OctalToNumber32(p, 8, item.GID)) { item.GID = 0; } p += 8; RIF(ParseSize(p, item.PackSize)); item.Size = item.PackSize; @@ -245,6 +247,15 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE item.PackSize = 0; item.Size = 0; } + + if (item.LinkFlag == NFileHeader::NLinkFlag::kDirectory) + { + // GNU tar ignores Size field, if LinkFlag is kDirectory + // 21.02 : we set PackSize = 0 to be more compatible with GNU tar + item.PackSize = 0; + // item.Size = 0; + } + /* TAR standard requires sum of unsigned byte values. But some TAR programs use sum of signed byte values. @@ -269,7 +280,7 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE if (item.LinkFlag == NFileHeader::NLinkFlag::kSparse) { - Byte isExtended = buf[482]; + Byte isExtended = (Byte)buf[482]; if (isExtended != 0 && isExtended != 1) return S_OK; RIF(ParseSize(buf + 483, item.Size)); @@ -309,7 +320,7 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE } item.HeaderSize += NFileHeader::kRecordSize; - isExtended = buf[21 * 24]; + isExtended = (Byte)buf[21 * 24]; if (isExtended != 0 && isExtended != 1) return S_OK; for (unsigned i = 0; i < 21; i++) @@ -442,9 +453,16 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErro case 'x': case 'X': { - // pax Extended Header - if (item.Name.IsPrefixedBy("PaxHeader/") - || item.Name.Find("PaxHeaders.4467/") >= 0) + const char *s = item.Name.Ptr(); + if (IsString1PrefixedByString2(s, "./")) + s += 2; + if (IsString1PrefixedByString2(s, "./")) + s += 2; + if ( IsString1PrefixedByString2(s, "PaxHeader/") + || IsString1PrefixedByString2(s, "PaxHeaders.X/") + || IsString1PrefixedByString2(s, "PaxHeaders.4467/") + || StringsAreEqual_Ascii(s, "@PaxHeader") + ) { RINOK(ReadDataToString(stream, item, pax, error)); if (error != k_ErrorType_OK) diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h index bc3b4084..8c34b841 100644 --- a/CPP/7zip/Archive/Tar/TarItem.h +++ b/CPP/7zip/Archive/Tar/TarItem.h @@ -4,6 +4,7 @@ #define __ARCHIVE_TAR_ITEM_H #include "../../../Common/MyLinux.h" +#include "../../../Common/UTFConvert.h" #include "../Common/ItemNameUtils.h" @@ -108,8 +109,52 @@ struct CItem } UInt64 GetPackSizeAligned() const { return (PackSize + 0x1FF) & (~((UInt64)0x1FF)); } + + bool IsThereWarning() const + { + // that Header Warning is possible if (Size != 0) for dir item + return (PackSize < Size) && (LinkFlag == NFileHeader::NLinkFlag::kDirectory); + } }; + + +struct CEncodingCharacts +{ + bool IsAscii; + // bool Oem_Checked; + // bool Oem_Ok; + // bool Utf_Checked; + CUtf8Check UtfCheck; + + void Clear() + { + IsAscii = true; + // Oem_Checked = false; + // Oem_Ok = false; + // Utf_Checked = false; + UtfCheck.Clear(); + } + + void Update(const CEncodingCharacts &ec) + { + if (!ec.IsAscii) + IsAscii = false; + + // if (ec.Utf_Checked) + { + UtfCheck.Update(ec.UtfCheck); + // Utf_Checked = true; + } + } + + CEncodingCharacts() { Clear(); } + void Check(const AString &s); + AString GetCharactsString() const; +}; + + + struct CItemEx: public CItem { UInt64 HeaderPos; @@ -117,6 +162,8 @@ struct CItemEx: public CItem bool NameCouldBeReduced; bool LinkNameCouldBeReduced; + CEncodingCharacts EncodingCharacts; + UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; } UInt64 GetFullSize() const { return HeaderSize + PackSize; } }; diff --git a/CPP/7zip/Archive/Tar/TarOut.cpp b/CPP/7zip/Archive/Tar/TarOut.cpp index 51081e8b..e2da3238 100644 --- a/CPP/7zip/Archive/Tar/TarOut.cpp +++ b/CPP/7zip/Archive/Tar/TarOut.cpp @@ -62,7 +62,7 @@ static void WriteOctal_12_Signed(char *s, Int64 val) { if (val >= 0) { - WriteOctal_12(s, val); + WriteOctal_12(s, (UInt64)val); return; } s[0] = s[1] = s[2] = s[3] = (char)(Byte)0xFF; diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp index 0cdb30d1..c7598f8d 100644 --- a/CPP/7zip/Archive/Tar/TarUpdate.cpp +++ b/CPP/7zip/Archive/Tar/TarUpdate.cpp @@ -15,13 +15,10 @@ namespace NArchive { namespace NTar { -HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, - AString &res, UINT codePage, bool convertSlash = false); - HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, const CObjectVector<NArchive::NTar::CItemEx> &inputItems, const CObjectVector<CUpdateItem> &updateItems, - UINT codePage, + UINT codePage, unsigned utfFlags, IArchiveUpdateCallback *updateCallback) { COutArchive outArchive; @@ -43,7 +40,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, if (ui.NewData) complexity += ui.Size; else - complexity += inputItems[ui.IndexInArc].GetFullSize(); + complexity += inputItems[(unsigned)ui.IndexInArc].GetFullSize(); } RINOK(updateCallback->SetTotal(complexity)); @@ -95,12 +92,12 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, memcpy(item.Magic, NFileHeader::NMagic::kUsTar_00, 8); } else - item = inputItems[ui.IndexInArc]; + item = inputItems[(unsigned)ui.IndexInArc]; AString symLink; if (ui.NewData || ui.NewProps) { - RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidSymLink, symLink, codePage, true)); + RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidSymLink, symLink, codePage, utfFlags, true)); if (!symLink.IsEmpty()) { item.LinkFlag = NFileHeader::NLinkFlag::kSymLink; @@ -159,7 +156,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, { AString hardLink; - RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidHardLink, hardLink, codePage, true)); + RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidHardLink, hardLink, codePage, utfFlags, true)); if (!hardLink.IsEmpty()) { item.LinkFlag = NFileHeader::NLinkFlag::kHardLink; @@ -189,7 +186,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, outArchive.Pos = fileHeaderStartPos; item.PackSize = copyCoderSpec->TotalSize; RINOK(outArchive.WriteHeader(item)); - RINOK(outSeekStream->Seek(item.PackSize, STREAM_SEEK_CUR, NULL)); + RINOK(outSeekStream->Seek((Int64)item.PackSize, STREAM_SEEK_CUR, NULL)); outArchive.Pos += item.PackSize; } RINOK(outArchive.FillDataResidual(item.PackSize)); @@ -201,7 +198,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, } else { - const CItemEx &existItem = inputItems[ui.IndexInArc]; + const CItemEx &existItem = inputItems[(unsigned)ui.IndexInArc]; UInt64 size; if (ui.NewProps) @@ -231,12 +228,12 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, item.GID = existItem.GID; RINOK(outArchive.WriteHeader(item)); - RINOK(inStream->Seek(existItem.GetDataPosition(), STREAM_SEEK_SET, NULL)); + RINOK(inStream->Seek((Int64)existItem.GetDataPosition(), STREAM_SEEK_SET, NULL)); size = existItem.PackSize; } else { - RINOK(inStream->Seek(existItem.HeaderPos, STREAM_SEEK_SET, NULL)); + RINOK(inStream->Seek((Int64)existItem.HeaderPos, STREAM_SEEK_SET, NULL)); size = existItem.GetFullSize(); } diff --git a/CPP/7zip/Archive/Tar/TarUpdate.h b/CPP/7zip/Archive/Tar/TarUpdate.h index b758635f..1e3d0217 100644 --- a/CPP/7zip/Archive/Tar/TarUpdate.h +++ b/CPP/7zip/Archive/Tar/TarUpdate.h @@ -13,7 +13,7 @@ namespace NTar { struct CUpdateItem { int IndexInArc; - int IndexInClient; + unsigned IndexInClient; UInt64 Size; Int64 MTime; UInt32 Mode; @@ -30,9 +30,12 @@ struct CUpdateItem HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, const CObjectVector<CItemEx> &inputItems, const CObjectVector<CUpdateItem> &updateItems, - UINT codePage, + UINT codePage, unsigned utfFlags, IArchiveUpdateCallback *updateCallback); +HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res, + UINT codePage, unsigned utfFlags, bool convertSlash); + }} #endif diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp index cfe6c5ad..520ceeea 100644 --- a/CPP/7zip/Archive/Udf/UdfIn.cpp +++ b/CPP/7zip/Archive/Udf/UdfIn.cpp @@ -39,13 +39,13 @@ static const UInt64 kFileNameLengthTotalMax = (UInt64)1 << 33; static const UInt64 kInlineExtentsSizeMax = (UInt64)1 << 33; #define CRC16_INIT_VAL 0 -#define CRC16_GET_DIGEST(crc) (crc) +// #define CRC16_GET_DIGEST(crc) (crc) #define CRC16_UPDATE_BYTE(crc, b) ((UInt16)(g_Crc16Table[(((crc) >> 8) ^ (b)) & 0xFF] ^ ((crc) << 8))) #define kCrc16Poly 0x1021 static UInt16 g_Crc16Table[256]; -void MY_FAST_CALL Crc16GenerateTable(void) +static void MY_FAST_CALL Crc16GenerateTable(void) { UInt32 i; for (i = 0; i < 256; i++) @@ -57,7 +57,7 @@ void MY_FAST_CALL Crc16GenerateTable(void) } } -UInt32 MY_FAST_CALL Crc16_Update(UInt32 v, const void *data, size_t size) +static UInt32 MY_FAST_CALL Crc16_Update(UInt32 v, const void *data, size_t size) { const Byte *p = (const Byte *)data; for (; size > 0 ; size--, p++) @@ -65,7 +65,7 @@ UInt32 MY_FAST_CALL Crc16_Update(UInt32 v, const void *data, size_t size) return v; } -UInt32 MY_FAST_CALL Crc16Calc(const void *data, size_t size) +static UInt32 MY_FAST_CALL Crc16Calc(const void *data, size_t size) { return Crc16_Update(CRC16_INIT_VAL, data, size); } diff --git a/CPP/7zip/Archive/Udf/UdfIn.h b/CPP/7zip/Archive/Udf/UdfIn.h index f7379401..c26f6099 100644 --- a/CPP/7zip/Archive/Udf/UdfIn.h +++ b/CPP/7zip/Archive/Udf/UdfIn.h @@ -351,7 +351,7 @@ class CInArchive UInt64 _processedProgressBytes; UInt64 _fileNameLengthTotal; - int _numRefs; + unsigned _numRefs; UInt32 _numExtents; UInt64 _inlineExtentsSize; bool CheckExtent(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len) const; diff --git a/CPP/7zip/Archive/UefiHandler.cpp b/CPP/7zip/Archive/UefiHandler.cpp index 5892d568..67fe795a 100644 --- a/CPP/7zip/Archive/UefiHandler.cpp +++ b/CPP/7zip/Archive/UefiHandler.cpp @@ -52,7 +52,7 @@ static const Byte k_IntelMeSignature[] = 0x5A, 0xA5, 0xF0, 0x0F }; -bool IsIntelMe(const Byte *p) +static bool IsIntelMe(const Byte *p) { return memcmp(p, k_IntelMeSignature, sizeof(k_IntelMeSignature)) == 0; } @@ -318,19 +318,19 @@ static const CUInt32PCharPair g_FFS_FILE_ATTRIBUTES[] = // SECTION_TYPE -#define SECTION_ALL 0x00 +// #define SECTION_ALL 0x00 #define SECTION_COMPRESSION 0x01 #define SECTION_GUID_DEFINED 0x02 // Leaf section Type values -#define SECTION_PE32 0x10 -#define SECTION_PIC 0x11 -#define SECTION_TE 0x12 +// #define SECTION_PE32 0x10 +// #define SECTION_PIC 0x11 +// #define SECTION_TE 0x12 #define SECTION_DXE_DEPEX 0x13 #define SECTION_VERSION 0x14 #define SECTION_USER_INTERFACE 0x15 -#define SECTION_COMPATIBILITY16 0x16 +// #define SECTION_COMPATIBILITY16 0x16 #define SECTION_FIRMWARE_VOLUME_IMAGE 0x17 #define SECTION_FREEFORM_SUBTYPE_GUID 0x18 #define SECTION_RAW 0x19 @@ -471,7 +471,7 @@ public: bool Parse(const Byte *p) { - int i; + unsigned i; for (i = 0; i < kFileHeaderSize; i++) if (p[i] != 0xFF) break; @@ -719,11 +719,11 @@ class CHandler: HRESULT ParseIntelMe(int bufIndex, UInt32 posBase, UInt32 exactSize, UInt32 limitSize, - int parent, int method, int level); + int parent, int method, unsigned level); HRESULT ParseVolume(int bufIndex, UInt32 posBase, UInt32 exactSize, UInt32 limitSize, - int parent, int method, int level); + int parent, int method, unsigned level); HRESULT OpenCapsule(IInStream *stream); HRESULT OpenFv(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback); @@ -857,13 +857,13 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) } #ifdef SHOW_DEBUG_INFO -static void PrintLevel(int level) +static void PrintLevel(unsigned level) { PRF(printf("\n")); - for (int i = 0; i < level; i++) + for (unsigned i = 0; i < level; i++) PRF(printf(" ")); } -static void MyPrint(UInt32 posBase, UInt32 size, int level, const char *name) +static void MyPrint(UInt32 posBase, UInt32 size, unsigned level, const char *name) { PrintLevel(level); PRF(printf("%s, pos = %6x, size = %6x", name, posBase, size)); @@ -1312,7 +1312,7 @@ bool CVolFfsHeader::Parse(const Byte *p) HRESULT CHandler::ParseVolume( int bufIndex, UInt32 posBase, UInt32 exactSize, UInt32 limitSize, - int parent, int method, int level) + int parent, int method, unsigned level) { if (level > kLevelMax) return S_FALSE; @@ -1333,7 +1333,7 @@ HRESULT CHandler::ParseVolume( if (!Is_FF_Stream(p + kFfsGuidOffset, 16)) item.SetGuid(p + kFfsGuidOffset); // if (item.Name.IsEmpty()) - item.Name += "[VOL]"; + item.Name += "[VOL]"; AddItem(item); return S_OK; } @@ -1512,7 +1512,7 @@ static const char * const kRegionName[] = HRESULT CHandler::ParseIntelMe( int bufIndex, UInt32 posBase, UInt32 exactSize, UInt32 limitSize, - int parent, int method, int level) + int parent, int method, unsigned level) { UNUSED_VAR(limitSize) level++; diff --git a/CPP/7zip/Archive/VdiHandler.cpp b/CPP/7zip/Archive/VdiHandler.cpp index b8ef35bb..66cf39cd 100644 --- a/CPP/7zip/Archive/VdiHandler.cpp +++ b/CPP/7zip/Archive/VdiHandler.cpp @@ -18,7 +18,6 @@ #include "HandlerCont.h" -#define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) #define Get64(p) GetUi64(p) @@ -87,7 +86,7 @@ class CHandler: public CHandlerImg Byte Guids[kNumGuids][16]; - HRESULT Seek(UInt64 offset) + HRESULT Seek2(UInt64 offset) { _posInArc = offset; return Stream->Seek(offset, STREAM_SEEK_SET, NULL); @@ -96,7 +95,7 @@ class CHandler: public CHandlerImg HRESULT InitAndSeek() { _virtPos = 0; - return Seek(0); + return Seek2(0); } HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback); @@ -143,7 +142,7 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) offset += lowBits; if (offset != _posInArc) { - RINOK(Seek(offset)); + RINOK(Seek2(offset)); } HRESULT res = Stream->Read(data, size, &size); _posInArc += size; diff --git a/CPP/7zip/Archive/VhdHandler.cpp b/CPP/7zip/Archive/VhdHandler.cpp index d79ae907..c70d667e 100644 --- a/CPP/7zip/Archive/VhdHandler.cpp +++ b/CPP/7zip/Archive/VhdHandler.cpp @@ -248,7 +248,7 @@ class CHandler: public CHandlerImg } void Reset_PosInArc() { _posInArc = (UInt64)0 - 1; } - HRESULT Seek(UInt64 offset); + HRESULT Seek2(UInt64 offset); HRESULT InitAndSeek(); HRESULT ReadPhy(UInt64 offset, void *data, UInt32 size); @@ -316,7 +316,7 @@ public: STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; -HRESULT CHandler::Seek(UInt64 offset) { return Stream->Seek(_startOffset + offset, STREAM_SEEK_SET, NULL); } +HRESULT CHandler::Seek2(UInt64 offset) { return Stream->Seek(_startOffset + offset, STREAM_SEEK_SET, NULL); } HRESULT CHandler::InitAndSeek() { @@ -327,7 +327,7 @@ HRESULT CHandler::InitAndSeek() _virtPos = _posInArc = 0; BitMapTag = kUnusedBlock; BitMap.Alloc(Dyn.NumBitMapSectors() << kSectorSize_Log); - return Seek(0); + return Seek2(0); } HRESULT CHandler::ReadPhy(UInt64 offset, void *data, UInt32 size) @@ -337,7 +337,7 @@ HRESULT CHandler::ReadPhy(UInt64 offset, void *data, UInt32 size) if (offset != _posInArc) { _posInArc = offset; - RINOK(Seek(offset)); + RINOK(Seek2(offset)); } HRESULT res = ReadStream_FALSE(Stream, data, size); if (res == S_OK) diff --git a/CPP/7zip/Archive/VmdkHandler.cpp b/CPP/7zip/Archive/VmdkHandler.cpp index 942bd792..096bd103 100644 --- a/CPP/7zip/Archive/VmdkHandler.cpp +++ b/CPP/7zip/Archive/VmdkHandler.cpp @@ -41,7 +41,7 @@ namespace NVmdk { static const Byte k_Signature[] = SIGNATURE; static const UInt32 k_Flags_NL = (UInt32)1 << 0; -static const UInt32 k_Flags_RGD = (UInt32)1 << 1; +// static const UInt32 k_Flags_RGD = (UInt32)1 << 1; static const UInt32 k_Flags_ZeroGrain = (UInt32)1 << 2; static const UInt32 k_Flags_Compressed = (UInt32)1 << 16; static const UInt32 k_Flags_Marker = (UInt32)1 << 17; @@ -855,11 +855,13 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) } case kpidId: + { if (desc && !desc->CID.IsEmpty()) { prop = desc->CID; - break; } + break; + } case kpidName: { diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp index 927a0b38..2553c175 100644 --- a/CPP/7zip/Archive/Wim/WimHandler.cpp +++ b/CPP/7zip/Archive/Wim/WimHandler.cpp @@ -350,7 +350,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) COM_TRY_END } -void GetFileTime(const Byte *p, NCOM::CPropVariant &prop) +static void GetFileTime(const Byte *p, NCOM::CPropVariant &prop) { prop.vt = VT_FILETIME; prop.filetime.dwLowDateTime = Get32(p); diff --git a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp index 18740c70..6b4497fe 100644 --- a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp +++ b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp @@ -4,6 +4,7 @@ #include "../../../Common/ComTry.h" #include "../../../Common/IntToString.h" +#include "../../../Common/MyBuffer2.h" #include "../../../Common/StringToInt.h" #include "../../../Common/UTFConvert.h" #include "../../../Common/Wildcard.h" @@ -93,9 +94,15 @@ struct CMetaItem CByteBuffer Reparse; unsigned GetNumAltStreams() const { return AltStreams.Size() - NumSkipAltStreams; } - CMetaItem(): UpdateIndex(-1), HashIndex(-1), SecurityId(-1), - FileID(0), VolID(0), - Skip(false), NumSkipAltStreams(0) {} + CMetaItem(): + UpdateIndex(-1) + , HashIndex(-1) + , FileID(0) + , VolID(0) + , SecurityId(-1) + , Skip(false) + , NumSkipAltStreams(0) + {} }; @@ -320,20 +327,23 @@ class CInStreamWithSha1: { CMyComPtr<ISequentialInStream> _stream; UInt64 _size; - NCrypto::NSha1::CContext _sha; + // NCrypto::NSha1::CContext _sha; + CAlignedBuffer _sha; + CSha1 *Sha() { return (CSha1 *)(void *)(Byte *)_sha; } public: MY_UNKNOWN_IMP1(IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + CInStreamWithSha1(): _sha(sizeof(CSha1)) {} void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init() { _size = 0; - _sha.Init(); + Sha1_Init(Sha()); } void ReleaseStream() { _stream.Release(); } UInt64 GetSize() const { return _size; } - void Final(Byte *digest) { _sha.Final(digest); } + void Final(Byte *digest) { Sha1_Final(Sha(), digest); } }; STDMETHODIMP CInStreamWithSha1::Read(void *data, UInt32 size, UInt32 *processedSize) @@ -341,7 +351,7 @@ STDMETHODIMP CInStreamWithSha1::Read(void *data, UInt32 size, UInt32 *processedS UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; - _sha.Update((const Byte *)data, realProcessedSize); + Sha1_Update(Sha(), (const Byte *)data, realProcessedSize); if (processedSize) *processedSize = realProcessedSize; return result; @@ -427,9 +437,9 @@ static size_t WriteItem(const CStreamInfo *streams, const CMetaItem &item, Byte Set16(p + 0x64, (UInt16)fileNameLen); unsigned i; for (i = 0; i * 2 < fileNameLen; i++) - Set16(p + kDirRecordSize + i * 2, item.Name[i]); + Set16(p + kDirRecordSize + i * 2, (UInt16)item.Name[i]); for (i = 0; i * 2 < shortNameLen; i++) - Set16(p + kDirRecordSize + fileNameLen2 + i * 2, item.ShortName[i]); + Set16(p + kDirRecordSize + fileNameLen2 + i * 2, (UInt16)item.ShortName[i]); if (item.GetNumAltStreams() == 0) { @@ -468,7 +478,7 @@ static size_t WriteItem(const CStreamInfo *streams, const CMetaItem &item, Byte memcpy(p + 0x10, streams[ss.HashIndex].Hash, kHashSize); Set16(p + 0x24, (UInt16)fileNameLen); for (i = 0; i * 2 < fileNameLen; i++) - Set16(p + 0x26 + i * 2, ss.Name[i]); + Set16(p + 0x26 + i * 2, (UInt16)ss.Name[i]); totalLen += curLen; p += curLen; } @@ -690,7 +700,7 @@ static void AddTrees(CObjectVector<CDir> &trees, CObjectVector<CMetaItem> &metaI } -#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z') +#define IS_LETTER_CHAR(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) @@ -1024,7 +1034,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu imageIndex = (int)val - 1; if (imageIndex < (int)isChangedImage.Size()) - if (!isChangedImage[imageIndex]) + if (!isChangedImage[imageIndex]) return E_FAIL; AddTrees(trees, db.MetaItems, ri, imageIndex); @@ -1079,7 +1089,27 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu fileName.Empty(); } else + { + /* + #if WCHAR_MAX > 0xffff + if (c >= 0x10000) + { + c -= 0x10000; + + if (c < (1 << 20)) + { + wchar_t c0 = 0xd800 + ((c >> 10) & 0x3FF); + fileName += c0; + c = 0xdc00 + (c & 0x3FF); + } + else + c = '_'; // we change character unsupported by UTF16 + } + #endif + */ + fileName += c; + } } if (isAltStream) @@ -1838,7 +1868,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu if (_xmls.Size() == 1) { const CWimXml &_oldXml = _xmls[0]; - if ((int)i < _oldXml.Images.Size()) + if (i < _oldXml.Images.Size()) { // int ttt = _oldXml.Images[i].ItemIndexInXml; item = _oldXml.Xml.Root.SubItems[_oldXml.Images[i].ItemIndexInXml]; @@ -1880,7 +1910,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu CByteArr xmlBuf(xmlSize); Set16((Byte *)xmlBuf, 0xFEFF); for (i = 0; i < (unsigned)utf16.Len(); i++) - Set16((Byte *)xmlBuf + 2 + i * 2, utf16[i]); + Set16((Byte *)xmlBuf + 2 + i * 2, (UInt16)utf16[i]); RINOK(WriteStream(outStream, (const Byte *)xmlBuf, xmlSize)); } diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp index 3c712084..fef6b34f 100644 --- a/CPP/7zip/Archive/Wim/WimIn.cpp +++ b/CPP/7zip/Archive/Wim/WimIn.cpp @@ -302,12 +302,12 @@ HRESULT CUnpacker::Unpack2( UInt64 packDataSize; size_t numChunks; { - UInt64 numChunks64 = (unpackSize + (((UInt32)1 << chunkSizeBits) - 1)) >> chunkSizeBits; - UInt64 sizesBufSize64 = (numChunks64 - 1) << entrySizeShifts; + const UInt64 numChunks64 = (unpackSize + (((UInt32)1 << chunkSizeBits) - 1)) >> chunkSizeBits; + const UInt64 sizesBufSize64 = (numChunks64 - 1) << entrySizeShifts; if (sizesBufSize64 > resource.PackSize) return S_FALSE; packDataSize = resource.PackSize - sizesBufSize64; - size_t sizesBufSize = (size_t)sizesBufSize64; + const size_t sizesBufSize = (size_t)sizesBufSize64; if (sizesBufSize != sizesBufSize64) return E_OUTOFMEMORY; sizesBuf.AllocAtLeast(sizesBufSize); @@ -639,10 +639,10 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent) p += dirRecordSize; { - if (*(const UInt16 *)(p + fileNameLen) != 0) + if (*(const UInt16 *)(const void *)(p + fileNameLen) != 0) return S_FALSE; for (UInt32 j = 0; j < fileNameLen; j += 2) - if (*(const UInt16 *)(p + j) == 0) + if (*(const UInt16 *)(const void *)(p + j) == 0) return S_FALSE; } @@ -652,10 +652,10 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent) { // empty shortName has no ZERO at the end ? const Byte *p2 = p + fileNameLen2; - if (*(const UInt16 *)(p2 + shortNameLen) != 0) + if (*(const UInt16 *)(const void *)(p2 + shortNameLen) != 0) return S_FALSE; for (UInt32 j = 0; j < shortNameLen; j += 2) - if (*(const UInt16 *)(p2 + j) == 0) + if (*(const UInt16 *)(const void *)(p2 + j) == 0) return S_FALSE; } @@ -703,10 +703,10 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent) { const Byte *p3 = p2 + extraOffset + 2; - if (*(const UInt16 *)(p3 + fileNameLen111) != 0) + if (*(const UInt16 *)(const void *)(p3 + fileNameLen111) != 0) return S_FALSE; for (UInt32 j = 0; j < fileNameLen111; j += 2) - if (*(const UInt16 *)(p3 + j) == 0) + if (*(const UInt16 *)(const void *)(p3 + j) == 0) return S_FALSE; // PRF(printf("\n %S", p3)); @@ -1790,7 +1790,8 @@ void CImageInfo::Parse(const CXmlItem &item) { CTimeDefined = ParseTime(item, CTime, "CREATIONTIME"); MTimeDefined = ParseTime(item, MTime, "LASTMODIFICATIONTIME"); - NameDefined = ConvertUTF8ToUnicode(item.GetSubStringForTag("NAME"), Name); + NameDefined = true; + ConvertUTF8ToUnicode(item.GetSubStringForTag("NAME"), Name); ParseNumber64(item.GetSubStringForTag("DIRCOUNT"), DirCount); ParseNumber64(item.GetSubStringForTag("FILECOUNT"), FileCount); diff --git a/CPP/7zip/Archive/XarHandler.cpp b/CPP/7zip/Archive/XarHandler.cpp index f20b1eb9..35dd607a 100644 --- a/CPP/7zip/Archive/XarHandler.cpp +++ b/CPP/7zip/Archive/XarHandler.cpp @@ -82,11 +82,13 @@ struct CFile int Parent; - CFile(): IsDir(false), HasData(false), ModeDefined(false), Sha1IsDefined(false), - /* packSha1IsDefined(false), */ - Parent(-1), + CFile(): Size(0), PackSize(0), Offset(0), - CTime(0), MTime(0), ATime(0), Mode(0) {} + CTime(0), MTime(0), ATime(0), Mode(0), + IsDir(false), HasData(false), ModeDefined(false), Sha1IsDefined(false), + /* packSha1IsDefined(false), */ + Parent(-1) + {} bool IsCopyMethod() const { @@ -435,8 +437,8 @@ static void Utf8StringToProp(const AString &s, NCOM::CPropVariant &prop) if (!s.IsEmpty()) { UString us; - if (ConvertUTF8ToUnicode(s, us)) - prop = us; + ConvertUTF8ToUnicode(s, us); + prop = us; } } diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp index 801619fb..2803f6a8 100644 --- a/CPP/7zip/Archive/XzHandler.cpp +++ b/CPP/7zip/Archive/XzHandler.cpp @@ -61,20 +61,29 @@ class CHandler: public CCommonMethodProps #endif { - CXzStatInfo _stat; - SRes MainDecodeSRes; + CXzStatInfo _stat; // it's stat from backward parsing + CXzStatInfo _stat2; // it's data from forward parsing, if the decoder was called + SRes _stat2_decode_SRes; + bool _stat_defined; + bool _stat2_defined; + + const CXzStatInfo *GetStat() const + { + if (_stat_defined) return &_stat; + if (_stat2_defined) return &_stat2; + return NULL; + } bool _isArc; bool _needSeekToStart; - bool _phySize_Defined; bool _firstBlockWasRead; AString _methodsString; + #ifndef EXTRACT_ONLY UInt32 _filterId; - UInt64 _numSolidBytes; void InitXz() @@ -85,6 +94,7 @@ class CHandler: #endif + void Init() { #ifndef EXTRACT_ONLY @@ -109,18 +119,24 @@ class CHandler: #endif decoder._memUsage = _memUsage; - MainDecodeSRes = SZ_OK; - - RINOK(decoder.Decode(seqInStream, outStream, + HRESULT hres = decoder.Decode(seqInStream, outStream, NULL, // *outSizeLimit true, // finishStream - progress)); + progress); - _stat = decoder.Stat; - MainDecodeSRes = decoder.MainDecodeSRes; + if (decoder.MainDecodeSRes_wasUsed + && decoder.MainDecodeSRes != SZ_ERROR_MEM + && decoder.MainDecodeSRes != SZ_ERROR_UNSUPPORTED) + { + // if (!_stat2_defined) + { + _stat2_decode_SRes = decoder.MainDecodeSRes; + _stat2 = decoder.Stat; + _stat2_defined = true; + } + } - _phySize_Defined = true; - return S_OK; + return hres; } public: @@ -143,8 +159,8 @@ public: INTERFACE_IOutArchive(;) #endif - size_t _blocksArraySize; CBlockInfo *_blocks; + size_t _blocksArraySize; UInt64 _maxBlocksSize; CMyComPtr<IInStream> _stream; CMyComPtr<ISequentialInStream> _seqStream; @@ -156,7 +172,7 @@ public: HRESULT SeekToPackPos(UInt64 pos) { - return _stream->Seek(pos, STREAM_SEEK_SET, NULL); + return _stream->Seek((Int64)pos, STREAM_SEEK_SET, NULL); } }; @@ -325,13 +341,16 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; + + const CXzStatInfo *stat = GetStat(); + switch (propID) { - case kpidPhySize: if (_phySize_Defined) prop = _stat.InSize; break; - case kpidNumStreams: if (_stat.NumStreams_Defined) prop = _stat.NumStreams; break; - case kpidNumBlocks: if (_stat.NumBlocks_Defined) prop = _stat.NumBlocks; break; - case kpidUnpackSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break; - case kpidClusterSize: if (_stat.NumBlocks_Defined && _stat.NumBlocks > 1) prop = _maxBlocksSize; break; + case kpidPhySize: if (stat) prop = stat->InSize; break; + case kpidNumStreams: if (stat && stat->NumStreams_Defined) prop = stat->NumStreams; break; + case kpidNumBlocks: if (stat && stat->NumBlocks_Defined) prop = stat->NumBlocks; break; + case kpidUnpackSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break; + case kpidClusterSize: if (_stat_defined && _stat.NumBlocks_Defined && stat->NumBlocks > 1) prop = _maxBlocksSize; break; case kpidCharacts: if (_firstBlockWasRead) { @@ -350,14 +369,14 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidErrorFlags: { UInt32 v = 0; - SRes sres = MainDecodeSRes; // _stat.DecodeRes2; // - if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; - if (/*_stat.UnexpectedEnd */ sres == SZ_ERROR_INPUT_EOF) v |= kpv_ErrorFlags_UnexpectedEnd; - if (_stat.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; - if (/* _stat.HeadersError */ sres == SZ_ERROR_ARCHIVE) v |= kpv_ErrorFlags_HeadersError; - if (/* _stat.Unsupported */ sres == SZ_ERROR_UNSUPPORTED) v |= kpv_ErrorFlags_UnsupportedMethod; - if (/* _stat.DataError */ sres == SZ_ERROR_DATA) v |= kpv_ErrorFlags_DataError; - if (/* _stat.CrcError */ sres == SZ_ERROR_CRC) v |= kpv_ErrorFlags_CrcError; + SRes sres = _stat2_decode_SRes; + if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; + if (sres == SZ_ERROR_INPUT_EOF) v |= kpv_ErrorFlags_UnexpectedEnd; + if (_stat2_defined && _stat2.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; + if (sres == SZ_ERROR_ARCHIVE) v |= kpv_ErrorFlags_HeadersError; + if (sres == SZ_ERROR_UNSUPPORTED) v |= kpv_ErrorFlags_UnsupportedMethod; + if (sres == SZ_ERROR_DATA) v |= kpv_ErrorFlags_DataError; + if (sres == SZ_ERROR_CRC) v |= kpv_ErrorFlags_CrcError; if (v != 0) prop = v; break; @@ -384,11 +403,12 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN + const CXzStatInfo *stat = GetStat(); NCOM::CPropVariant prop; switch (propID) { - case kpidSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break; - case kpidPackSize: if (_phySize_Defined) prop = _stat.InSize; break; + case kpidSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break; + case kpidPackSize: if (stat) prop = stat->InSize; break; case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; } prop.Detach(value); @@ -402,7 +422,9 @@ struct COpenCallbackWrap ICompressProgress vt; IArchiveOpenCallback *OpenCallback; HRESULT Res; - COpenCallbackWrap(IArchiveOpenCallback *progress); + + // new clang shows "non-POD" warning for offsetof(), if we use constructor instead of Init() + void Init(IArchiveOpenCallback *progress); }; static SRes OpenCallbackProgress(const ICompressProgress *pp, UInt64 inSize, UInt64 /* outSize */) @@ -413,7 +435,7 @@ static SRes OpenCallbackProgress(const ICompressProgress *pp, UInt64 inSize, UIn return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS); } -COpenCallbackWrap::COpenCallbackWrap(IArchiveOpenCallback *callback) +void COpenCallbackWrap::Init(IArchiveOpenCallback *callback) { vt.Progress = OpenCallbackProgress; OpenCallback = callback; @@ -482,7 +504,11 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal CSeqInStreamWrap inStreamWrap; inStreamWrap.Init(inStream); + SRes res = Xz_ReadHeader(&st, &inStreamWrap.vt); + + if (inStreamWrap.Res != S_OK) + return inStreamWrap.Res; if (res != SZ_OK) return SRes_to_Open_HRESULT(res); @@ -490,8 +516,27 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal CXzBlock block; BoolInt isIndex; UInt32 headerSizeRes; + SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.vt, &isIndex, &headerSizeRes); - if (res2 == SZ_OK && !isIndex) + + if (inStreamWrap.Res != S_OK) + return inStreamWrap.Res; + + if (res2 != SZ_OK) + { + if (res2 == SZ_ERROR_INPUT_EOF) + { + _stat2_decode_SRes = res2; + _stream = inStream; + _seqStream = inStream; + _isArc = true; + return S_OK; + } + + if (res2 == SZ_ERROR_ARCHIVE) + return S_FALSE; + } + else if (!isIndex) { _firstBlockWasRead = true; _firstBlock = block; @@ -526,7 +571,8 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal lookStream.realStream = &inStreamImp.vt; LookToRead2_Init(&lookStream); - COpenCallbackWrap openWrap(callback); + COpenCallbackWrap openWrap; + openWrap.Init(callback); CXzsCPP xzs; Int64 startPosition; @@ -539,7 +585,7 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal */ if (res == SZ_OK && startPosition == 0) { - _phySize_Defined = true; + _stat_defined = true; _stat.OutSize = Xzs_GetUnpackSize(&xzs.p); _stat.UnpackSize_Defined = true; @@ -615,6 +661,7 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal } RINOK(SRes_to_Open_HRESULT(res)); + _stream = inStream; _seqStream = inStream; _isArc = true; @@ -645,12 +692,15 @@ STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) STDMETHODIMP CHandler::Close() { XzStatInfo_Clear(&_stat); + XzStatInfo_Clear(&_stat2); + _stat_defined = false; + _stat2_defined = false; + _stat2_decode_SRes = SZ_OK; _isArc = false; _needSeekToStart = false; - _phySize_Defined = false; _firstBlockWasRead = false; - + _methodsString.Empty(); _stream.Release(); _seqStream.Release(); @@ -660,8 +710,6 @@ STDMETHODIMP CHandler::Close() _blocksArraySize = 0; _maxBlocksSize = 0; - MainDecodeSRes = SZ_OK; - return S_OK; } @@ -729,7 +777,7 @@ CInStream::~CInStream() } -size_t FindBlock(const CBlockInfo *blocks, size_t numBlocks, UInt64 pos) +static size_t FindBlock(const CBlockInfo *blocks, size_t numBlocks, UInt64 pos) { size_t left = 0, right = numBlocks; for (;;) @@ -900,9 +948,9 @@ STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPositio } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _virtPos = offset; + _virtPos = (UInt64)offset; if (newPosition) - *newPosition = offset; + *newPosition = (UInt64)offset; return S_OK; } @@ -951,7 +999,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) static Int32 Get_Extract_OperationResult(const NCompress::NXz::CDecoder &decoder) { Int32 opRes; - SRes sres = decoder.MainDecodeSRes; // decoder.Stat.DecodeRes2; + SRes sres = decoder.MainDecodeSRes; if (sres == SZ_ERROR_NO_ARCHIVE) // (!IsArc) opRes = NExtract::NOperationResult::kIsNotArc; else if (sres == SZ_ERROR_INPUT_EOF) // (UnexpectedEnd) @@ -985,8 +1033,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; - if (_phySize_Defined) - extractCallback->SetTotal(_stat.InSize); + const CXzStatInfo *stat = GetStat(); + + if (stat) + extractCallback->SetTotal(stat->InSize); UInt64 currentTotalPacked = 0; RINOK(extractCallback->SetCompleted(¤tTotalPacked)); @@ -1106,7 +1156,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt */ #ifndef _7ZIP_ST - xzProps.numTotalThreads = _numThreads; + xzProps.numTotalThreads = (int)_numThreads; #endif xzProps.blockSize = _numSolidBytes; @@ -1161,7 +1211,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); - return encoderSpec->Code(fileInStream, outStream, NULL, NULL, progress); + RINOK(encoderSpec->Code(fileInStream, outStream, NULL, NULL, progress)); + + return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); } if (indexInArchive != 0) @@ -1176,8 +1228,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (_stream) { - if (_phySize_Defined) - RINOK(updateCallback->SetTotal(_stat.InSize)); + const CXzStatInfo *stat = GetStat(); + if (stat) + RINOK(updateCallback->SetTotal(stat->InSize)); RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); } diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp index 1ee7e22f..2bb57d5c 100644 --- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp @@ -88,14 +88,18 @@ STDMETHODIMP CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStr } -CAddCommon::CAddCommon(const CCompressionMethodMode &options): - _options(options), +CAddCommon::CAddCommon(): _copyCoderSpec(NULL), + _isLzmaEos(false), _cryptoStreamSpec(NULL), - _buf(NULL), - _isLzmaEos(false) + _buf(NULL) {} +void CAddCommon::SetOptions(const CCompressionMethodMode &options) +{ + _options = options; +} + CAddCommon::~CAddCommon() { MidFree(_buf); @@ -230,6 +234,11 @@ HRESULT CAddCommon::Compress( unsigned numTestMethods = _options.MethodSequence.Size(); bool descriptorMode = outSeqMode; + + // ZipCrypto without descriptor requires additional reading pass for + // inStream to calculate CRC for password check field. + // The descriptor allows to use ZipCrypto check field without CRC (InfoZip's modification). + if (!outSeqMode) if (inSeqMode && _options.PasswordIsDefined && !_options.IsAesMode) descriptorMode = true; @@ -262,6 +271,15 @@ HRESULT CAddCommon::Compress( RINOK(outStream->SetSize(0)); RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL)); } + + method = _options.MethodSequence[i]; + if (method == NCompressionMethod::kStore && descriptorMode) + { + // we still can create descriptor_mode archives with "Store" method, but they are not good for 100% + return E_NOTIMPL; + } + + bool needCode = true; if (_options.PasswordIsDefined) { @@ -314,23 +332,25 @@ HRESULT CAddCommon::Compress( RINOK(_filterSpec->WriteHeader_Check16(outStream, (UInt16)check)); } - RINOK(_cryptoStreamSpec->SetOutStream(outStream)); - RINOK(_cryptoStreamSpec->InitEncoder()); - outStreamReleaser.FilterCoder = _cryptoStreamSpec; + if (method == NCompressionMethod::kStore) + { + needCode = false; + RINOK(_cryptoStreamSpec->Code(inCrcStream, outStream, NULL, NULL, progress)); + } + else + { + RINOK(_cryptoStreamSpec->SetOutStream(outStream)); + RINOK(_cryptoStreamSpec->InitEncoder()); + outStreamReleaser.FilterCoder = _cryptoStreamSpec; + } } - method = _options.MethodSequence[i]; - - switch (method) + if (needCode) { + switch (method) + { case NCompressionMethod::kStore: { - if (descriptorMode) - { - // we still can create descriptor_mode archives with "Store" method, but they are not good for 100% - return E_NOTIMPL; - } - if (!_copyCoderSpec) { _copyCoderSpec = new NCompress::CCopyCoder; @@ -438,15 +458,21 @@ HRESULT CAddCommon::Compress( } } + try { RINOK(_compressEncoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress)); + } catch (...) { return E_FAIL; } break; } + } // switch end + + if (_options.PasswordIsDefined) + { + RINOK(_cryptoStreamSpec->OutStreamFinish()); + } } if (_options.PasswordIsDefined) { - RINOK(_cryptoStreamSpec->OutStreamFinish()); - if (_options.IsAesMode) { RINOK(_filterAesSpec->WriteFooter(outStream)); diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.h b/CPP/7zip/Archive/Zip/ZipAddCommon.h index ff3251db..0aa44adf 100644 --- a/CPP/7zip/Archive/Zip/ZipAddCommon.h +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.h @@ -28,9 +28,15 @@ struct CCompressingResult Byte ExtractVersion; bool DescriptorMode; bool LzmaEos; + + CCompressingResult() + { + // for GCC: + UnpackSize = 0; + } }; -class CAddCommon +class CAddCommon MY_UNCOPYABLE { CCompressionMethodMode _options; NCompress::CCopyCoder *_copyCoderSpec; @@ -50,7 +56,9 @@ class CAddCommon HRESULT CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC); public: - CAddCommon(const CCompressionMethodMode &options); + // CAddCommon(const CCompressionMethodMode &options); + CAddCommon(); + void SetOptions(const CCompressionMethodMode &options); ~CAddCommon(); HRESULT Set_Pre_CompressionResult(bool inSeqMode, bool outSeqMode, UInt64 unpackSize, diff --git a/CPP/7zip/Archive/Zip/ZipCompressionMode.h b/CPP/7zip/Archive/Zip/ZipCompressionMode.h index 1125f6ed..842991c4 100644 --- a/CPP/7zip/Archive/Zip/ZipCompressionMode.h +++ b/CPP/7zip/Archive/Zip/ZipCompressionMode.h @@ -35,7 +35,7 @@ struct CCompressionMethodMode: public CBaseProps { CRecordVector<Byte> MethodSequence; bool PasswordIsDefined; - AString Password; + AString Password; // _Wipe UInt64 _dataSizeReduce; bool _dataSizeReduceDefined; @@ -47,6 +47,8 @@ struct CCompressionMethodMode: public CBaseProps _dataSizeReduceDefined = false; _dataSizeReduce = 0; } + + ~CCompressionMethodMode() { Password.Wipe_and_Empty(); } }; }} diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp index a4794f51..72a77cb7 100644 --- a/CPP/7zip/Archive/Zip/ZipHandler.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp @@ -18,6 +18,17 @@ #include "../../Common/StreamUtils.h" #include "../../Compress/CopyCoder.h" + +#ifdef EXTERNAL_CODECS +#ifndef SUPPORT_LZFSE +#define SUPPORT_LZFSE +#endif +#endif + +#ifdef SUPPORT_LZFSE +#include "../../Compress/LzfseDecoder.h" +#endif + #include "../../Compress/LzmaDecoder.h" #include "../../Compress/ImplodeDecoder.h" #include "../../Compress/PpmdZip.h" @@ -81,16 +92,24 @@ const char * const kMethodNames1[kNumMethodNames1] = , "BZip2" , NULL , "LZMA" + , NULL + , NULL + , NULL + , NULL + , NULL + , "zstd-pk" }; const char * const kMethodNames2[kNumMethodNames2] = { - "xz" + "zstd-wz" + , "MP3" + , "xz" , "Jpeg" , "WavPack" , "PPMd" - , "WzAES" + , "LZFSE" // , "WzAES" }; #define kMethod_AES "AES" @@ -240,6 +259,12 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) if (m_Archive.IsZip64) s.Add_OptSpaced("Zip64"); + if (m_Archive.IsCdUnsorted) + s.Add_OptSpaced("Unsorted_CD"); + + if (m_Archive.IsApk) + s.Add_OptSpaced("apk"); + if (m_Archive.ExtraMinorError) s.Add_OptSpaced("Minor_Extra_ERROR"); @@ -312,9 +337,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) // case kpidIsAltStream: prop = true; break; } - prop.Detach(value); + return prop.Detach(value); COM_TRY_END - return S_OK; } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) @@ -336,7 +360,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { UString res; item.GetUnicodeString(res, item.Name, false, _forceCodePage, _specifiedCodePage); - NItemName::ReplaceToOsSlashes_Remove_TailSlash(res); + NItemName::ReplaceToOsSlashes_Remove_TailSlash(res, + item.Is_MadeBy_Unix() // useBackslashReplacement + ); /* if (item.ParentOfAltStream >= 0) { @@ -359,7 +385,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidIsDir: prop = item.IsDir(); break; case kpidSize: { - if (item.FromCentral || !item.FromLocal || !item.HasDescriptor() || item.DescriptorWasRead) + if (!item.IsBadDescriptor()) prop = item.Size; break; } @@ -467,23 +493,27 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidMethod: { - unsigned id = item.Method; AString m; - - if (item.IsEncrypted()) + bool isWzAes = false; + unsigned id = item.Method; + + if (id == NFileHeader::NCompressionMethod::kWzAES) { - if (id == NFileHeader::NCompressionMethod::kWzAES) + CWzAesExtra aesField; + if (extra.GetWzAes(aesField)) { m += kMethod_AES; - CWzAesExtra aesField; - if (extra.GetWzAes(aesField)) - { - m += '-'; - m.Add_UInt32(((unsigned)aesField.Strength + 1) * 64); - id = aesField.Method; - } + m += '-'; + m.Add_UInt32(((unsigned)aesField.Strength + 1) * 64); + id = aesField.Method; + isWzAes = true; } - else if (item.IsStrongEncrypted()) + } + + if (item.IsEncrypted()) + if (!isWzAes) + { + if (item.IsStrongEncrypted()) { CStrongCryptoExtra f; f.AlgId = 0; @@ -506,8 +536,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } else m += kMethod_ZipCrypto; - m += ' '; } + + m.Add_Space_if_NotEmpty(); { const char *s = NULL; @@ -516,7 +547,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val else { int id2 = (int)id - (int)kMethodNames2Start; - if (id2 >= 0 && id2 < kNumMethodNames2) + if (id2 >= 0 && (unsigned)id2 < kNumMethodNames2) s = kMethodNames2[id2]; } if (s) @@ -532,7 +563,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { if (level & 1) m += ":eos"; - level &= ~1; + level &= ~(unsigned)1; } else if (id == NFileHeader::NCompressionMethod::kDeflate) { @@ -576,7 +607,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } UInt32 flags = item.Flags; - flags &= ~(6); // we don't need compression related bits here. + flags &= ~(unsigned)6; // we don't need compression related bits here. if (flags != 0) { @@ -589,7 +620,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } } - if (!item.FromCentral && item.FromLocal && item.HasDescriptor() && !item.DescriptorWasRead) + if (item.IsBadDescriptor()) s.Add_OptSpaced("Descriptor_ERROR"); if (!s.IsEmpty()) @@ -634,8 +665,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val */ } - prop.Detach(value); - return S_OK; + return prop.Detach(value); COM_TRY_END } @@ -860,11 +890,14 @@ public: }; -static HRESULT SkipStreamData(ISequentialInStream *stream, bool &thereAreData) +static HRESULT SkipStreamData(ISequentialInStream *stream, + ICompressProgressInfo *progress, UInt64 packSize, UInt64 unpackSize, + bool &thereAreData) { thereAreData = false; const size_t kBufSize = 1 << 12; Byte buf[kBufSize]; + UInt64 prev = packSize; for (;;) { size_t size = kBufSize; @@ -872,10 +905,80 @@ static HRESULT SkipStreamData(ISequentialInStream *stream, bool &thereAreData) if (size == 0) return S_OK; thereAreData = true; + packSize += size; + if ((packSize - prev) >= (1 << 22)) + { + prev = packSize; + RINOK(progress->SetRatioInfo(&packSize, &unpackSize)); + } } } + +class COutStreamWithPadPKCS7: + public ISequentialOutStream, + public CMyUnknownImp +{ + CMyComPtr<ISequentialOutStream> _stream; + UInt64 _size; + UInt64 _padPos; + UInt32 _padSize; + bool _padFailure; +public: + MY_UNKNOWN_IMP + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void ReleaseStream() { _stream.Release(); } + + // padSize == 0 means (no_pad Mode) + void Init(UInt64 padPos, UInt32 padSize) + { + _padPos = padPos; + _padSize = padSize; + _size = 0; + _padFailure = false; + } + UInt64 GetSize() const { return _size; } + bool WasPadFailure() const { return _padFailure; } +}; + + +STDMETHODIMP COutStreamWithPadPKCS7::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 written = 0; + HRESULT result = S_OK; + if (_size < _padPos) + { + const UInt64 rem = _padPos - _size; + UInt32 num = size; + if (num > rem) + num = (UInt32)rem; + result = _stream->Write(data, num, &written); + _size += written; + if (processedSize) + *processedSize = written; + if (_size != _padPos || result != S_OK) + return result; + size -= written; + data = ((const Byte *)data) + written; + } + _size += size; + written += size; + if (processedSize) + *processedSize = written; + if (_padSize != 0) + for (; size != 0; size--) + { + if (*(const Byte *)data != _padSize) + _padFailure = true; + data = ((const Byte *)data) + 1; + } + return result; +} + + + HRESULT CZipDecoder::Decode( DECL_EXTERNAL_CODECS_LOC_VARS CInArchive &archive, const CItemEx &item, @@ -895,9 +998,32 @@ HRESULT CZipDecoder::Decode( bool needCRC = true; bool wzAesMode = false; bool pkAesMode = false; + + bool badDescriptor = item.IsBadDescriptor(); + if (badDescriptor) + needCRC = false; + unsigned id = item.Method; + CWzAesExtra aesField; + // LZFSE and WinZip's AES use same id - kWzAES. + + if (id == NFileHeader::NCompressionMethod::kWzAES) + { + if (item.GetMainExtra().GetWzAes(aesField)) + { + if (!item.IsEncrypted()) + { + res = NExtract::NOperationResult::kUnsupportedMethod; + return S_OK; + } + wzAesMode = true; + needCRC = aesField.NeedCrc(); + } + } + + if (!wzAesMode) if (item.IsEncrypted()) { if (item.IsStrongEncrypted()) @@ -910,14 +1036,6 @@ HRESULT CZipDecoder::Decode( } pkAesMode = true; } - else if (id == NFileHeader::NCompressionMethod::kWzAES) - { - CWzAesExtra aesField; - if (!item.GetMainExtra().GetWzAes(aesField)) - return S_OK; - wzAesMode = true; - needCRC = aesField.NeedCrc(); - } } COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; @@ -957,9 +1075,6 @@ HRESULT CZipDecoder::Decode( { if (wzAesMode) { - CWzAesExtra aesField; - if (!item.GetMainExtra().GetWzAes(aesField)) - return S_OK; id = aesField.Method; if (!_wzAesDecoder) { @@ -1002,12 +1117,12 @@ HRESULT CZipDecoder::Decode( if (getTextPassword) { - CMyComBSTR password; + CMyComBSTR_Wipe password; RINOK(getTextPassword->CryptoGetTextPassword(&password)); - AString charPassword; + AString_Wipe charPassword; if (password) { - UnicodeStringToMultiByte2(charPassword, (const wchar_t *)password, CP_ACP); + UnicodeStringToMultiByte2(charPassword, (LPCOLESTR)password, CP_ACP); /* if (wzAesMode || pkAesMode) { @@ -1063,6 +1178,10 @@ HRESULT CZipDecoder::Decode( mi.Coder = new NCompress::NXz::CComDecoder; else if (id == NFileHeader::NCompressionMethod::kPPMd) mi.Coder = new NCompress::NPpmdZip::CDecoder(true); + #ifdef SUPPORT_LZFSE + else if (id == NFileHeader::NCompressionMethod::kWzAES) + mi.Coder = new NCompress::NLzfse::CDecoder; + #endif else { CMethodId szMethodID; @@ -1089,7 +1208,8 @@ HRESULT CZipDecoder::Decode( m = methodItems.Add(mi); } - ICompressCoder *coder = methodItems[m].Coder; + const CMethodItem &mi = methodItems[m]; + ICompressCoder *coder = mi.Coder; #ifndef _7ZIP_ST @@ -1123,14 +1243,22 @@ HRESULT CZipDecoder::Decode( } - CMyComPtr<ISequentialInStream> inStreamNew; - bool isFullStreamExpected = (!item.HasDescriptor() || item.PackSize != 0); bool needReminderCheck = false; bool dataAfterEnd = false; bool truncatedError = false; bool lzmaEosError = false; + bool headersError = false; + bool padError = false; + bool readFromFilter = false; + + const bool useUnpackLimit = (id == NFileHeader::NCompressionMethod::kStore + || !item.HasDescriptor() + || item.Size >= ((UInt64)1 << 32) + || item.LocalExtra.IsZip64 + || item.CentralExtra.IsZip64 + ); { HRESULT result = S_OK; @@ -1198,23 +1326,7 @@ HRESULT CZipDecoder::Decode( } } } - - if (result == S_OK) - { - inStreamReleaser.FilterCoder = filterStreamSpec; - RINOK(filterStreamSpec->SetInStream(inStream)); - - /* IFilter::Init() does nothing in all zip crypto filters. - So we can call any Initialize function in CFilterCoder. */ - - RINOK(filterStreamSpec->Init_NoSubFilterInit()); - // RINOK(filterStreamSpec->SetOutStreamSize(NULL)); - - inStreamNew = filterStream; - } } - else - inStreamNew = inStream; if (result == S_OK) { @@ -1222,26 +1334,84 @@ HRESULT CZipDecoder::Decode( coder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode); if (setFinishMode) { - RINOK(setFinishMode->SetFinishMode(BoolToInt(true))); + RINOK(setFinishMode->SetFinishMode(BoolToUInt(true))); } const UInt64 coderPackSize = limitedStreamSpec->GetRem(); - bool useUnpackLimit = (id == 0 - || !item.HasDescriptor() - || item.Size >= ((UInt64)1 << 32) - || item.LocalExtra.IsZip64 - || item.CentralExtra.IsZip64 - ); + if (id == NFileHeader::NCompressionMethod::kStore && item.IsEncrypted()) + { + readFromFilter = false; + + COutStreamWithPadPKCS7 *padStreamSpec = NULL; + CMyComPtr<ISequentialOutStream> padStream; + UInt32 padSize = 0; + + if (pkAesMode) + { + padStreamSpec = new COutStreamWithPadPKCS7; + padStream = padStreamSpec; + padSize = _pkAesDecoderSpec->GetPadSize((UInt32)item.Size); + padStreamSpec->SetStream(outStream); + padStreamSpec->Init(item.Size, padSize); + } + + // Here we decode minimal required size, including padding + const UInt64 expectedSize = item.Size + padSize; + UInt64 size = coderPackSize; + if (item.Size > coderPackSize) + headersError = true; + else if (expectedSize != coderPackSize) + { + headersError = true; + if (coderPackSize > expectedSize) + size = expectedSize; + } - result = coder->Code(inStreamNew, outStream, - isFullStreamExpected ? &coderPackSize : NULL, - // NULL, - useUnpackLimit ? &item.Size : NULL, - compressProgress); + result = filterStreamSpec->Code(inStream, padStream ? + (ISequentialOutStream *)padStream : + (ISequentialOutStream *)outStream, + NULL, &size, compressProgress); - if (result == S_OK) + if (outStreamSpec->GetSize() != item.Size) + truncatedError = true; + + if (pkAesMode) + { + if (padStreamSpec->GetSize() != size) + truncatedError = true; + if (padStreamSpec->WasPadFailure()) + padError = true; + } + } + else { + if (item.IsEncrypted()) + { + readFromFilter = true; + inStreamReleaser.FilterCoder = filterStreamSpec; + RINOK(filterStreamSpec->SetInStream(inStream)); + + /* IFilter::Init() does nothing in all zip crypto filters. + So we can call any Initialize function in CFilterCoder. */ + + RINOK(filterStreamSpec->Init_NoSubFilterInit()); + // RINOK(filterStreamSpec->SetOutStreamSize(NULL)); + } + + try { + result = coder->Code(readFromFilter ? + (ISequentialInStream *)filterStream : + (ISequentialInStream *)inStream, + outStream, + isFullStreamExpected ? &coderPackSize : NULL, + // NULL, + useUnpackLimit ? &item.Size : NULL, + compressProgress); + } catch (...) { return E_FAIL; } + + if (result == S_OK) + { CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize; coder->QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize); if (getInStreamProcessedSize && setFinishMode) @@ -1259,7 +1429,32 @@ HRESULT CZipDecoder::Decode( { if (processed + padSize < coderPackSize) dataAfterEnd = true; - // also here we can check PKCS7 padding data from reminder (it can be inside stream buffer in coder). + else + { + // here we can PKCS7 padding data from reminder (it can be inside stream buffer in coder). + CMyComPtr<ICompressReadUnusedFromInBuf> readInStream; + coder->QueryInterface(IID_ICompressReadUnusedFromInBuf, (void **)&readInStream); + if (readInStream) + { + // change pad size, it we support another block size in ZipStron + // here we request more to detect error with data after end. + const UInt32 kBufSize = NCrypto::NZipStrong::kAesPadAllign + 16; + Byte buf[kBufSize]; + UInt32 processedSize; + RINOK(readInStream->ReadUnusedFromInBuf(buf, kBufSize, &processedSize)); + if (processedSize > padSize) + dataAfterEnd = true; + else + { + if (ReadStream_FALSE(filterStream, buf + processedSize, padSize - processedSize) != S_OK) + padError = true; + else + for (unsigned i = 0; i < padSize; i++) + if (buf[i] != padSize) + padError = true; + } + } + } } } else @@ -1270,11 +1465,15 @@ HRESULT CZipDecoder::Decode( dataAfterEnd = true; } else if (processed > coderPackSize) + { + // that case is additional check, that can show the bugs in code (coder) truncatedError = true; + } needReminderCheck = isFullStreamExpected; } } } + } } if (result == S_OK && id == NFileHeader::NCompressionMethod::kLZMA) @@ -1298,19 +1497,33 @@ HRESULT CZipDecoder::Decode( bool authOk = true; if (needCRC) crcOK = (outStreamSpec->GetCRC() == item.Crc); + + if (useUnpackLimit) + if (outStreamSpec->GetSize() != item.Size) + truncatedError = true; if (wzAesMode) { + const UInt64 unpackSize = outStreamSpec->GetSize(); + const UInt64 packSize = limitedStreamSpec->GetSize(); bool thereAreData = false; - if (SkipStreamData(inStreamNew, thereAreData) != S_OK) + // read to the end from filter or from packed stream + if (SkipStreamData(readFromFilter ? + (ISequentialInStream *)filterStream : + (ISequentialInStream *)inStream, + compressProgress, packSize, unpackSize, thereAreData) != S_OK) authOk = false; - if (needReminderCheck && thereAreData) dataAfterEnd = true; - - limitedStreamSpec->Init(NCrypto::NWzAes::kMacSize); - if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK) - authOk = false; + + if (limitedStreamSpec->GetRem() != 0) + truncatedError = true; + else + { + limitedStreamSpec->Init(NCrypto::NWzAes::kMacSize); + if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK) + authOk = false; + } } res = NExtract::NOperationResult::kCRCError; @@ -1321,10 +1534,16 @@ HRESULT CZipDecoder::Decode( if (dataAfterEnd) res = NExtract::NOperationResult::kDataAfterEnd; + else if (padError) + res = NExtract::NOperationResult::kCRCError; else if (truncatedError) res = NExtract::NOperationResult::kUnexpectedEnd; + else if (headersError) + res = NExtract::NOperationResult::kHeadersError; else if (lzmaEosError) res = NExtract::NOperationResult::kHeadersError; + else if (badDescriptor) + res = NExtract::NOperationResult::kUnexpectedEnd; // CheckDescriptor() supports only data descriptor with signature and // it doesn't support "old" pkzip's data descriptor without signature. diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h index bee57c00..3043e41c 100644 --- a/CPP/7zip/Archive/Zip/ZipHandler.h +++ b/CPP/7zip/Archive/Zip/ZipHandler.h @@ -15,8 +15,8 @@ namespace NArchive { namespace NZip { -const unsigned kNumMethodNames1 = NFileHeader::NCompressionMethod::kLZMA + 1; -const unsigned kMethodNames2Start = NFileHeader::NCompressionMethod::kXz; +const unsigned kNumMethodNames1 = NFileHeader::NCompressionMethod::kZstdPk + 1; +const unsigned kMethodNames2Start = NFileHeader::NCompressionMethod::kZstdWz; const unsigned kNumMethodNames2 = NFileHeader::NCompressionMethod::kWzAES + 1 - kMethodNames2Start; extern const char * const kMethodNames1[kNumMethodNames1]; diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp index c21b5605..a9b3eae5 100644 --- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp @@ -53,7 +53,7 @@ static int FindZipMethod(const char *s, const char * const *names, unsigned num) { const char *name = names[i]; if (name && StringsAreEqualNoCase_Ascii(s, name)) - return i; + return (int)i; } return -1; } @@ -65,7 +65,7 @@ static int FindZipMethod(const char *s) return k; k = FindZipMethod(s, kMethodNames2, kNumMethodNames2); if (k >= 0) - return kMethodNames2Start + k; + return (int)kMethodNames2Start + k; return -1; } @@ -75,7 +75,7 @@ static int FindZipMethod(const char *s) catch(const CSystemException &e) { return e.ErrorCode; } \ catch(...) { return E_OUTOFMEMORY; } -static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propID, FILETIME &filetime) +static HRESULT GetTime(IArchiveUpdateCallback *callback, unsigned index, PROPID propID, FILETIME &filetime) { filetime.dwHighDateTime = filetime.dwLowDateTime = 0; NCOM::CPropVariant prop; @@ -106,6 +106,10 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt UInt64 largestSize = 0; bool largestSizeDefined = false; + #ifdef _WIN32 + const UINT oemCP = GetOEMCP(); + #endif + UString name; CUpdateItem ui; @@ -125,7 +129,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt ui.NewProps = IntToBool(newProps); ui.NewData = IntToBool(newData); - ui.IndexInArc = indexInArc; + ui.IndexInArc = (int)indexInArc; ui.IndexInClient = i; bool existInArchive = (indexInArc != (UInt32)(Int32)-1); @@ -240,10 +244,25 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (needSlash) name += kSlash; - UINT codePage = _forceCodePage ? _specifiedCodePage : CP_OEMCP; - + const UINT codePage = _forceCodePage ? _specifiedCodePage : CP_OEMCP; bool tryUtf8 = true; - if ((m_ForceLocal || !m_ForceUtf8) && codePage != CP_UTF8) + + /* + Windows 10 allows users to set UTF-8 in Region Settings via option: + "Beta: Use Unicode UTF-8 for worldwide language support" + In that case Windows uses CP_UTF8 when we use CP_OEMCP. + 21.02 fixed: + we set UTF-8 mark for non-latin files for such UTF-8 mode in Windows. + we write additional Info-Zip Utf-8 FileName Extra for non-latin names/ + */ + + if ((codePage != CP_UTF8) && + #ifdef _WIN32 + (m_ForceLocal || !m_ForceUtf8) && (oemCP != CP_UTF8) + #else + (m_ForceLocal && !m_ForceUtf8) + #endif + ) { bool defaultCharWasUsed; ui.Name = UnicodeStringToMultiByte(name, codePage, '_', defaultCharWasUsed); @@ -251,13 +270,26 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt MultiByteToUnicodeString(ui.Name, codePage) != name)); } + const bool isNonLatin = !name.IsAscii(); + if (tryUtf8) { - ui.IsUtf8 = !name.IsAscii(); + ui.IsUtf8 = isNonLatin; ConvertUnicodeToUTF8(name, ui.Name); + + #ifndef _WIN32 + if (ui.IsUtf8 && !CheckUTF8_AString(ui.Name)) + { + // if it's non-Windows and there are non-UTF8 characters we clear UTF8-flag + ui.IsUtf8 = false; + } + #endif } + else if (isNonLatin) + Convert_Unicode_To_UTF8_Buf(name, ui.Name_Utf); - if (ui.Name.Len() >= (1 << 16)) + if (ui.Name.Len() >= (1 << 16) + || ui.Name_Utf.Size() >= (1 << 16) - 128) return E_INVALIDARG; { @@ -337,10 +369,10 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt options._dataSizeReduceDefined = largestSizeDefined; options.PasswordIsDefined = false; - options.Password.Empty(); + options.Password.Wipe_and_Empty(); if (getTextPassword) { - CMyComBSTR password; + CMyComBSTR_Wipe password; Int32 passwordIsDefined; RINOK(getTextPassword->CryptoGetTextPassword2(&passwordIsDefined, &password)); options.PasswordIsDefined = IntToBool(passwordIsDefined); @@ -352,7 +384,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (!IsSimpleAsciiString(password)) return E_INVALIDARG; if (password) - options.Password = UnicodeStringToMultiByte((LPCOLESTR)password, CP_OEMCP); + UnicodeStringToMultiByte2(options.Password, (LPCOLESTR)password, CP_OEMCP); if (options.IsAesMode) { if (options.Password.Len() > NCrypto::NWzAes::kPasswordSizeMax) @@ -496,7 +528,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR UInt32 id = prop.ulVal; if (id > 0xFF) return E_INVALIDARG; - m_MainMethod = id; + m_MainMethod = (int)id; } else { @@ -518,7 +550,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR const char *end; UInt32 id = ConvertStringToUInt32(methodName, &end); if (*end == 0 && id <= 0xFF) - m_MainMethod = id; + m_MainMethod = (int)id; else if (methodName.IsEqualTo_Ascii_NoCase("Copy")) // it's alias for "Store" m_MainMethod = 0; } diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h index 5e6f00e4..c5c7166e 100644 --- a/CPP/7zip/Archive/Zip/ZipHeader.h +++ b/CPP/7zip/Archive/Zip/ZipHeader.h @@ -56,7 +56,10 @@ namespace NFileHeader kTerse = 18, kLz77 = 19, + kZstdPk = 20, + kZstdWz = 93, + kMP3 = 94, kXz = 95, kJpeg = 96, kWavPack = 97, @@ -90,7 +93,10 @@ namespace NFileHeader kUnixExtra = 0x5855, kIzUnicodeComment = 0x6375, kIzUnicodeName = 0x7075, - kWzAES = 0x9901 + kUnix2Extra = 0x7855, + kUnix3Extra = 0x7875, + kWzAES = 0x9901, + kApkAlign = 0xD935 }; } diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index 509753c2..880ff218 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -152,6 +152,9 @@ void CInArchive::Close() IsArc = false; IsZip64 = false; + IsApk = false; + IsCdUnsorted = false; + HeadersError = false; HeadersWarning = false; ExtraMinorError = false; @@ -169,7 +172,7 @@ void CInArchive::Close() IsMultiVol = false; UseDisk_in_SingleVol = false; EcdVolIndex = 0; - + ArcInfo.Clear(); ClearRefs(); @@ -181,7 +184,7 @@ HRESULT CInArchive::Seek_SavePos(UInt64 offset) { // InitBuf(); // if (!Stream) return S_FALSE; - return Stream->Seek(offset, STREAM_SEEK_SET, &_streamPos); + return Stream->Seek((Int64)offset, STREAM_SEEK_SET, &_streamPos); } HRESULT CInArchive::SeekToVol(int volIndex, UInt64 offset) @@ -193,9 +196,9 @@ HRESULT CInArchive::SeekToVol(int volIndex, UInt64 offset) { if ((unsigned)volIndex >= Vols.Streams.Size()) return S_FALSE; - if (!Vols.Streams[volIndex].Stream) + if (!Vols.Streams[(unsigned)volIndex].Stream) return S_FALSE; - Stream = Vols.Streams[volIndex].Stream; + Stream = Vols.Streams[(unsigned)volIndex].Stream; } else if (volIndex == -2) { @@ -277,11 +280,11 @@ HRESULT CInArchive::ReadFromCache(Byte *data, unsigned size, unsigned &processed } else { - UInt32 cur = 0; - result = Stream->Read(data, size, &cur); + size_t cur = size; + result = ReadStream(Stream, data, &cur); data += cur; - size -= cur; - processed += cur; + size -= (unsigned)cur; + processed += (unsigned)cur; _streamPos += cur; _cnt += cur; if (cur != 0) @@ -299,7 +302,7 @@ HRESULT CInArchive::ReadFromCache(Byte *data, unsigned size, unsigned &processed || (unsigned)Vols.StreamIndex + 1 >= Vols.Streams.Size()) break; - const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex + 1]; + const CVols::CSubStreamInfo &s = Vols.Streams[(unsigned)Vols.StreamIndex + 1]; if (!s.Stream) break; result = s.SeekToStart(); @@ -316,6 +319,16 @@ HRESULT CInArchive::ReadFromCache(Byte *data, unsigned size, unsigned &processed } +HRESULT CInArchive::ReadFromCache_FALSE(Byte *data, unsigned size) +{ + unsigned processed; + HRESULT res = ReadFromCache(data, size, processed); + if (res == S_OK && size != processed) + return S_FALSE; + return res; +} + + static bool CheckDosTime(UInt32 dosTime) { if (dosTime == 0) @@ -412,8 +425,12 @@ API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size) const unsigned nameSize = Get16(p + 22); unsigned extraSize = Get16(p + 24); const UInt32 extraOffset = kLocalHeaderSize + (UInt32)nameSize; + + /* + // 21.02: fixed. we don't use the following check if (extraOffset + extraSize > (1 << 16)) return k_IsArc_Res_NO; + */ p -= 4; @@ -498,12 +515,9 @@ static const Byte *FindPK(const Byte *p, const Byte *limit) { for (;;) { - Byte b0 = p[0]; - if (p >= limit) - return p; - p++; - if (b0 == 0x50) - break; + Byte b0; + b0 = p[0]; if (p >= limit) return p; p++; if (b0 == 0x50) break; + b0 = p[0]; if (p >= limit) return p; p++; if (b0 == 0x50) break; } if (p[0] == 0x4B) return p - 1; @@ -540,10 +554,7 @@ HRESULT CInArchive::FindMarker(const UInt64 *searchLimit) if (searchLimit && *searchLimit == 0) { Byte startBuf[kMarkerSize]; - unsigned processed; - RINOK(ReadFromCache(startBuf, kMarkerSize, processed)); - if (processed != kMarkerSize) - return S_FALSE; + RINOK(ReadFromCache_FALSE(startBuf, kMarkerSize)); UInt32 marker = Get32(startBuf); _signature = marker; @@ -551,9 +562,7 @@ HRESULT CInArchive::FindMarker(const UInt64 *searchLimit) if ( marker == NSignature::kNoSpan || marker == NSignature::kSpan) { - RINOK(ReadFromCache(startBuf, kMarkerSize, processed)); - if (processed != kMarkerSize) - return S_FALSE; + RINOK(ReadFromCache_FALSE(startBuf, kMarkerSize)); _signature = Get32(startBuf); } @@ -605,7 +614,7 @@ HRESULT CInArchive::FindMarker(const UInt64 *searchLimit) SkipLookahed(avail); - const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex + 1]; + const CVols::CSubStreamInfo &s = Vols.Streams[(unsigned)Vols.StreamIndex + 1]; if (!s.Stream) break; @@ -645,14 +654,14 @@ HRESULT CInArchive::FindMarker(const UInt64 *searchLimit) p = FindPK(p, limit); if (p >= limit) break; - const size_t rem = pStart + avail - p; + const size_t rem = (size_t)(pStart + avail - p); UInt32 res = IsArc_Zip_2(p, rem, isFinished); if (res != k_IsArc_Res_NO) { if (rem < kMarkerSize) return S_FALSE; _signature = Get32(p); - SkipLookahed(p - pStart); + SkipLookahed((size_t)(p - pStart)); ArcInfo.MarkerVolIndex = Vols.StreamIndex; ArcInfo.MarkerPos = GetVirtStreamPos(); ArcInfo.MarkerPos2 = ArcInfo.MarkerPos; @@ -674,7 +683,7 @@ HRESULT CInArchive::FindMarker(const UInt64 *searchLimit) if (!IsMultiVol && isFinished) break; - SkipLookahed(p - pStart); + SkipLookahed((size_t)(p - pStart)); if (Callback && (_cnt - progressPrev) >= ((UInt32)1 << 23)) { @@ -728,7 +737,7 @@ HRESULT CInArchive::IncreaseRealPosition(UInt64 offset, bool &isFinished) if (!IsMultiVol) { _cnt += offset; - return Stream->Seek(offset, STREAM_SEEK_CUR, &_streamPos); + return Stream->Seek((Int64)offset, STREAM_SEEK_CUR, &_streamPos); } for (;;) @@ -744,7 +753,7 @@ HRESULT CInArchive::IncreaseRealPosition(UInt64 offset, bool &isFinished) return S_OK; } { - const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex]; + const CVols::CSubStreamInfo &s = Vols.Streams[(unsigned)Vols.StreamIndex]; if (!s.Stream) { isFinished = true; @@ -756,7 +765,7 @@ HRESULT CInArchive::IncreaseRealPosition(UInt64 offset, bool &isFinished) if ((UInt64)offset <= rem) { _cnt += offset; - return Stream->Seek(offset, STREAM_SEEK_CUR, &_streamPos); + return Stream->Seek((Int64)offset, STREAM_SEEK_CUR, &_streamPos); } RINOK(Seek_SavePos(s.Size)); offset -= rem; @@ -771,7 +780,7 @@ HRESULT CInArchive::IncreaseRealPosition(UInt64 offset, bool &isFinished) isFinished = true; return S_OK; } - const CVols::CSubStreamInfo &s2 = Vols.Streams[Vols.StreamIndex]; + const CVols::CSubStreamInfo &s2 = Vols.Streams[(unsigned)Vols.StreamIndex]; if (!s2.Stream) { isFinished = true; @@ -834,7 +843,7 @@ HRESULT CInArchive::LookAhead(size_t minRequired) || (unsigned)Vols.StreamIndex + 1 >= Vols.Streams.Size()) return S_OK; - const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex + 1]; + const CVols::CSubStreamInfo &s = Vols.Streams[(unsigned)Vols.StreamIndex + 1]; if (!s.Stream) return S_OK; @@ -979,7 +988,7 @@ bool CInArchive::ReadFileName(unsigned size, AString &s) #define ZIP64_IS_16_MAX(n) ((n) == 0xFFFF) -bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extra, +bool CInArchive::ReadExtra(const CLocalItem &item, unsigned extraSize, CExtraBlock &extra, UInt64 &unpackSize, UInt64 &packSize, UInt64 &localOffset, UInt32 &disk) { extra.Clear(); @@ -1010,16 +1019,16 @@ bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extra, bool isOK = true; if (ZIP64_IS_32_MAX(unpackSize)) - if (size < 8) isOK = false; else { size -= 8; unpackSize = ReadUInt64(); } + { if (size < 8) isOK = false; else { size -= 8; unpackSize = ReadUInt64(); }} if (isOK && ZIP64_IS_32_MAX(packSize)) - if (size < 8) isOK = false; else { size -= 8; packSize = ReadUInt64(); } + { if (size < 8) isOK = false; else { size -= 8; packSize = ReadUInt64(); }} if (isOK && ZIP64_IS_32_MAX(localOffset)) - if (size < 8) isOK = false; else { size -= 8; localOffset = ReadUInt64(); } + { if (size < 8) isOK = false; else { size -= 8; localOffset = ReadUInt64(); }} if (isOK && ZIP64_IS_16_MAX(disk)) - if (size < 4) isOK = false; else { size -= 4; disk = ReadUInt32(); } + { if (size < 4) isOK = false; else { size -= 4; disk = ReadUInt32(); }} if (!isOK || size != 0) { @@ -1033,6 +1042,11 @@ bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extra, { ReadBuffer(subBlock.Data, size); extra.SubBlocks.Add(subBlock); + if (subBlock.ID == NFileHeader::NExtraID::kIzUnicodeName) + { + if (!subBlock.CheckIzUnicode(item.Name)) + extra.Error = true; + } } } @@ -1054,7 +1068,7 @@ bool CInArchive::ReadLocalItem(CItemEx &item) { item.Disk = 0; if (IsMultiVol && Vols.StreamIndex >= 0) - item.Disk = Vols.StreamIndex; + item.Disk = (UInt32)Vols.StreamIndex; const unsigned kPureHeaderSize = kLocalHeaderSize - 4; Byte p[kPureHeaderSize]; SafeRead(p, kPureHeaderSize); @@ -1088,7 +1102,7 @@ bool CInArchive::ReadLocalItem(CItemEx &item) { UInt64 localOffset = 0; UInt32 disk = 0; - if (!ReadExtra(extraSize, item.LocalExtra, item.Size, item.PackSize, localOffset, disk)) + if (!ReadExtra(item, extraSize, item.LocalExtra, item.Size, item.PackSize, localOffset, disk)) { /* Most of archives are OK for Extra. But there are some rare cases that have error. And if error in first item, it can't open archive. @@ -1111,33 +1125,39 @@ bool CInArchive::ReadLocalItem(CItemEx &item) HeadersWarning = true; } - return item.LocalFullHeaderSize <= ((UInt32)1 << 16); + // return item.LocalFullHeaderSize <= ((UInt32)1 << 16); + return true; } -static bool FlagsAreSame(const CItem &i1, const CItem &i2) +static bool FlagsAreSame(const CItem &i1, const CItem &i2_cd) { - if (i1.Method != i2.Method) + if (i1.Method != i2_cd.Method) return false; - if (i1.Flags == i2.Flags) + + UInt32 mask = i1.Flags ^ i2_cd.Flags; + if (mask == 0) return true; - UInt32 mask = 0xFFFF; switch (i1.Method) { case NFileHeader::NCompressionMethod::kDeflate: - mask = 0x7FF9; + mask &= 0x7FF9; break; default: if (i1.Method <= NFileHeader::NCompressionMethod::kImplode) - mask = 0x7FFF; + mask &= 0x7FFF; } // we can ignore utf8 flag, if name is ascii - if ((i1.Flags ^ i2.Flags) & NFileHeader::NFlags::kUtf8) - if (i1.Name.IsAscii() && i2.Name.IsAscii()) + if (mask & NFileHeader::NFlags::kUtf8) + if (i1.Name.IsAscii() && i2_cd.Name.IsAscii()) mask &= ~NFileHeader::NFlags::kUtf8; + + // some bad archive in rare case can use descriptor without descriptor flag in Central Dir + // if (i1.HasDescriptor()) + mask &= ~NFileHeader::NFlags::kDescriptorUsedMask; - return ((i1.Flags & mask) == (i2.Flags & mask)); + return (mask == 0); } @@ -1167,13 +1187,13 @@ static bool AreEqualPaths_IgnoreSlashes(const char *s1, const char *s2) static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem) { - if (!FlagsAreSame(cdItem, localItem)) + if (!FlagsAreSame(localItem, cdItem)) return false; if (!localItem.HasDescriptor()) { if (cdItem.PackSize != localItem.PackSize || cdItem.Size != localItem.Size - || cdItem.Crc != localItem.Crc && cdItem.Crc != 0) // some program writes 0 to crc field in central directory + || (cdItem.Crc != localItem.Crc && cdItem.Crc != 0)) // some program writes 0 to crc field in central directory return false; } /* pkzip 2.50 creates incorrect archives. It uses @@ -1235,7 +1255,7 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail, bool return S_FALSE; } Stream = Vols.Streams[item.Disk].Stream; - Vols.StreamIndex = item.Disk; + Vols.StreamIndex = (int)item.Disk; if (!Stream) { isAvail = false; @@ -1251,7 +1271,7 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail, bool } Stream = StreamRef; - offset += ArcInfo.Base; + offset = (UInt64)((Int64)offset + ArcInfo.Base); if (ArcInfo.Base < 0 && (Int64)offset < 0) { isAvail = false; @@ -1281,6 +1301,11 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail, bool item.Crc = localItem.Crc; headersError = true; } + if ((item.Flags ^ localItem.Flags) & NFileHeader::NFlags::kDescriptorUsedMask) + { + item.Flags = (UInt16)(item.Flags ^ NFileHeader::NFlags::kDescriptorUsedMask); + headersError = true; + } item.FromLocal = true; } catch(...) { return S_FALSE; } @@ -1351,8 +1376,11 @@ HRESULT CInArchive::FindDescriptor(CItemEx &item, unsigned numFiles) { // we write to packSize all these available bytes. // later it's simpler to work with such value than with 0 - if (item.PackSize == 0) + // if (item.PackSize == 0) item.PackSize = packedSize + avail; + if (item.Method == 0) + item.Size = item.PackSize; + SkipLookahed(avail); return S_OK; } @@ -1384,7 +1412,7 @@ HRESULT CInArchive::FindDescriptor(CItemEx &item, unsigned numFiles) && sig != NSignature::kCentralFileHeader) continue; - const UInt64 packSizeCur = packedSize + (p - pStart); + const UInt64 packSizeCur = packedSize + (size_t)(p - pStart); if (descriptorSize4 == kDataDescriptorSize64 + kNextSignatureSize) // if (item.LocalExtra.IsZip64) { const UInt64 descriptorPackSize = Get64(p + 8); @@ -1406,14 +1434,14 @@ HRESULT CInArchive::FindDescriptor(CItemEx &item, unsigned numFiles) item.DescriptorWasRead = true; item.Crc = Get32(p + 4); - const size_t skip = (p - pStart) + descriptorSize4 - kNextSignatureSize; + const size_t skip = (size_t)(p - pStart) + descriptorSize4 - kNextSignatureSize; SkipLookahed(skip); return S_OK; } - const size_t skip = (p - pStart); + const size_t skip = (size_t)(p - pStart); SkipLookahed(skip); packedSize += skip; @@ -1529,7 +1557,7 @@ HRESULT CInArchive::ReadCdItem(CItemEx &item) ReadFileName(nameSize, item.Name); if (extraSize > 0) - ReadExtra(extraSize, item.CentralExtra, item.Size, item.PackSize, item.LocalHeaderPos, item.Disk); + ReadExtra(item, extraSize, item.CentralExtra, item.Size, item.PackSize, item.LocalHeaderPos, item.Disk); // May be these strings must be deleted /* @@ -1549,11 +1577,7 @@ HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo) Byte buf[kEcd64_FullSize]; RINOK(SeekToVol(Vols.StreamIndex, offset)); - unsigned processed = 0; - ReadFromCache(buf, kEcd64_FullSize, processed); - - if (processed != kEcd64_FullSize) - return S_FALSE; + RINOK(ReadFromCache_FALSE(buf, kEcd64_FullSize)); if (Get32(buf) != NSignature::kEcd64) return S_FALSE; @@ -1636,8 +1660,12 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode) { CLocator locator; locator.Parse(buf + locatorIndex + 4); - if ((cdInfo.ThisDisk == locator.NumDisks - 1 || ZIP64_IS_16_MAX(cdInfo.ThisDisk)) - && locator.Ecd64Disk < locator.NumDisks) + UInt32 numDisks = locator.NumDisks; + // we ignore the error, where some zip creators use (NumDisks == 0) + if (numDisks == 0) + numDisks = 1; + if ((cdInfo.ThisDisk == numDisks - 1 || ZIP64_IS_16_MAX(cdInfo.ThisDisk)) + && locator.Ecd64Disk < numDisks) { if (locator.Ecd64Disk != cdInfo.ThisDisk && !ZIP64_IS_16_MAX(cdInfo.ThisDisk)) return E_NOTIMPL; @@ -1657,7 +1685,7 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode) if (mainEcd64Size == kEcd64_MainSize) { cdInfo.ParseEcd64e(ecd64 + 12); - ArcInfo.Base = absEcd64 - locator.Ecd64Offset; + ArcInfo.Base = (Int64)(absEcd64 - locator.Ecd64Offset); // ArcInfo.BaseVolIndex = cdInfo.ThisDisk; return S_OK; } @@ -1685,7 +1713,7 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode) { if (TryEcd64(ArcInfo.MarkerPos + locator.Ecd64Offset, cdInfo) == S_OK) { - ArcInfo.Base = ArcInfo.MarkerPos; + ArcInfo.Base = (Int64)ArcInfo.MarkerPos; // ArcInfo.BaseVolIndex = cdInfo.ThisDisk; return S_OK; } @@ -1719,7 +1747,7 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode) } else */ - ArcInfo.Base = absEcdPos - cdEnd; + ArcInfo.Base = (Int64)(absEcdPos - cdEnd); } return S_OK; } @@ -1730,11 +1758,12 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode) HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdInfo, UInt64 cdOffset, UInt64 cdSize) { items.Clear(); + IsCdUnsorted = false; // _startLocalFromCd_Disk = (UInt32)(Int32)-1; // _startLocalFromCd_Offset = (UInt64)(Int64)-1; - RINOK(SeekToVol(IsMultiVol ? cdInfo.CdDisk : -1, cdOffset)); + RINOK(SeekToVol(IsMultiVol ? (int)cdInfo.CdDisk : -1, cdOffset)); _inBufMode = true; _cnt = 0; @@ -1767,6 +1796,15 @@ HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdIn } */ + if (items.Size() > 0 && !IsCdUnsorted) + { + const CItemEx &prev = items.Back(); + if (cdItem.Disk < prev.Disk + || (cdItem.Disk == prev.Disk && + cdItem.LocalHeaderPos < prev.LocalHeaderPos)) + IsCdUnsorted = true; + } + items.Add(cdItem); } if (Callback && (items.Size() & 0xFFF) == 0) @@ -1793,6 +1831,22 @@ HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdIn } +/* +static int CompareCdItems(void *const *elem1, void *const *elem2, void *) +{ + const CItemEx *i1 = *(const CItemEx **)elem1; + const CItemEx *i2 = *(const CItemEx **)elem2; + + if (i1->Disk < i2->Disk) return -1; + if (i1->Disk > i2->Disk) return 1; + if (i1->LocalHeaderPos < i2->LocalHeaderPos) return -1; + if (i1->LocalHeaderPos > i2->LocalHeaderPos) return 1; + if (i1 < i2) return -1; + if (i1 > i2) return 1; + return 0; +} +*/ + HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 &cdOffset, UInt64 &cdSize) { bool checkOffsetMode = true; @@ -1801,7 +1855,7 @@ HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 { if (Vols.EndVolIndex == -1) return S_FALSE; - Stream = Vols.Streams[Vols.EndVolIndex].Stream; + Stream = Vols.Streams[(unsigned)Vols.EndVolIndex].Stream; if (!Vols.StartIsZip) checkOffsetMode = false; } @@ -1827,7 +1881,7 @@ HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 return S_FALSE; } - const UInt64 base = (IsMultiVol ? 0 : ArcInfo.Base); + const UInt64 base = (IsMultiVol ? 0 : (UInt64)ArcInfo.Base); res = TryReadCd(items, cdInfo, base + cdOffset, cdSize); if (res == S_FALSE && !IsMultiVol && base != ArcInfo.MarkerPos) @@ -1835,9 +1889,11 @@ HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 // do we need that additional attempt to read cd? res = TryReadCd(items, cdInfo, ArcInfo.MarkerPos + cdOffset, cdSize); if (res == S_OK) - ArcInfo.Base = ArcInfo.MarkerPos; + ArcInfo.Base = (Int64)ArcInfo.MarkerPos; } + // Some rare case files are unsorted + // items.Sort(CompareCdItems, NULL); return res; } @@ -1849,14 +1905,14 @@ static int FindItem(const CObjectVector<CItemEx> &items, const CItemEx &item) { if (left >= right) return -1; - unsigned index = (left + right) / 2; + const unsigned index = (left + right) / 2; const CItemEx &item2 = items[index]; if (item.Disk < item2.Disk) right = index; else if (item.Disk > item2.Disk) left = index + 1; else if (item.LocalHeaderPos == item2.LocalHeaderPos) - return index; + return (int)index; else if (item.LocalHeaderPos < item2.LocalHeaderPos) right = index; else @@ -1921,7 +1977,7 @@ HRESULT CInArchive::ReadLocals(CObjectVector<CItemEx> &items) item.LocalHeaderPos = GetVirtStreamPos() - 4; if (!IsMultiVol) - item.LocalHeaderPos -= ArcInfo.Base; + item.LocalHeaderPos = (UInt64)((Int64)item.LocalHeaderPos - ArcInfo.Base); try { @@ -1950,7 +2006,7 @@ HRESULT CInArchive::ReadLocals(CObjectVector<CItemEx> &items) } catch (CUnexpectEnd &) { - if (items.IsEmpty() || items.Size() == 1 && IsStrangeItem(items[0])) + if (items.IsEmpty() || (items.Size() == 1 && IsStrangeItem(items[0]))) return S_FALSE; throw; } @@ -1986,11 +2042,11 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback) name = prop.bstrVal; } - int dotPos = name.ReverseFind_Dot(); + const int dotPos = name.ReverseFind_Dot(); if (dotPos < 0) return S_OK; - const UString ext = name.Ptr(dotPos + 1); - name.DeleteFrom(dotPos + 1); + const UString ext = name.Ptr((unsigned)(dotPos + 1)); + name.DeleteFrom((unsigned)(dotPos + 1)); StartVolIndex = (Int32)(-1); @@ -2047,7 +2103,7 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback) UInt32 volNum = ConvertStringToUInt32(ext.Ptr(1), &end); if (*end != 0 || volNum < 1 || volNum > ((UInt32)1 << 30)) return S_OK; - StartVolIndex = volNum - 1; + StartVolIndex = (Int32)(volNum - 1); BaseName = name; StartIsZ = true; } @@ -2147,7 +2203,7 @@ HRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback, UInt64 pos; RINOK(stream->Seek(0, STREAM_SEEK_CUR, &pos)); RINOK(stream->Seek(0, STREAM_SEEK_END, &size)); - RINOK(stream->Seek(pos, STREAM_SEEK_SET, NULL)); + RINOK(stream->Seek((Int64)pos, STREAM_SEEK_SET, NULL)); while (i >= Vols.Streams.Size()) Vols.Streams.AddNew(); @@ -2161,7 +2217,7 @@ HRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback, if ((int)i == zipDisk) { - Vols.EndVolIndex = Vols.Streams.Size() - 1; + Vols.EndVolIndex = (int)(Vols.Streams.Size() - 1); break; } } @@ -2211,7 +2267,7 @@ HRESULT CInArchive::ReadVols() CCdInfo &ecd = Vols.ecd; if (res == S_OK) { - zipDisk = ecd.ThisDisk; + zipDisk = (int)ecd.ThisDisk; Vols.ecd_wasRead = true; // if is not multivol or bad multivol, we return to main single stream code @@ -2220,9 +2276,9 @@ HRESULT CInArchive::ReadVols() || ecd.ThisDisk < ecd.CdDisk) return S_OK; - cdDisk = ecd.CdDisk; + cdDisk = (int)ecd.CdDisk; if (Vols.StartVolIndex < 0) - Vols.StartVolIndex = ecd.ThisDisk; + Vols.StartVolIndex = (Int32)ecd.ThisDisk; else if ((UInt32)Vols.StartVolIndex >= ecd.ThisDisk) return S_OK; @@ -2232,7 +2288,7 @@ HRESULT CInArchive::ReadVols() if (cdDisk != zipDisk) { // get volumes required for cd. - RINOK(ReadVols2(volCallback, cdDisk, zipDisk, zipDisk, 0, numMissingVols)); + RINOK(ReadVols2(volCallback, (unsigned)cdDisk, zipDisk, zipDisk, 0, numMissingVols)); if (numMissingVols != 0) { // cdOK = false; @@ -2269,10 +2325,10 @@ HRESULT CInArchive::ReadVols() if (Vols.StartVolIndex > (1 << 20)) return S_OK; if ((unsigned)Vols.StartVolIndex >= Vols.Streams.Size() - || !Vols.Streams[Vols.StartVolIndex].Stream) + || !Vols.Streams[(unsigned)Vols.StartVolIndex].Stream) { // we get volumes starting from StartVolIndex, if they we not requested before know the volume index (if FindCd() was ok) - RINOK(ReadVols2(volCallback, Vols.StartVolIndex, zipDisk, zipDisk, 0, numMissingVols)); + RINOK(ReadVols2(volCallback, (unsigned)Vols.StartVolIndex, zipDisk, zipDisk, 0, numMissingVols)); } } @@ -2285,7 +2341,7 @@ HRESULT CInArchive::ReadVols() if (zipDisk >= 0) { // we create item in Streams for ZipStream, if we know the volume index (if FindCd() was ok) - RINOK(ReadVols2(volCallback, zipDisk, zipDisk + 1, zipDisk, 0, numMissingVols)); + RINOK(ReadVols2(volCallback, (unsigned)zipDisk, zipDisk + 1, zipDisk, 0, numMissingVols)); } } @@ -2331,7 +2387,7 @@ HRESULT CVols::Read(void *data, UInt32 size, UInt32 *processedSize) return S_OK; if ((unsigned)StreamIndex >= Streams.Size()) return S_OK; - const CVols::CSubStreamInfo &s = Streams[StreamIndex]; + const CVols::CSubStreamInfo &s = Streams[(unsigned)StreamIndex]; if (!s.Stream) return S_FALSE; if (NeedSeek) @@ -2473,7 +2529,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) if (!ecd.IsEmptyArc()) return S_FALSE; - ArcInfo.Base = ArcInfo.MarkerPos; + ArcInfo.Base = (Int64)ArcInfo.MarkerPos; IsArc = true; // check it: we need more tests? RINOK(SeekToVol(ArcInfo.MarkerVolIndex, ArcInfo.MarkerPos2)); @@ -2514,16 +2570,44 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) res = S_FALSE; else { - firstItem.LocalHeaderPos = ArcInfo.MarkerPos2 - ArcInfo.Base; - int index = FindItem(items, firstItem); + firstItem.LocalHeaderPos = (UInt64)((Int64)ArcInfo.MarkerPos2 - ArcInfo.Base); + int index = -1; + + UInt32 min_Disk = (UInt32)(Int32)-1; + UInt64 min_LocalHeaderPos = (UInt64)(Int64)-1; + + if (!IsCdUnsorted) + index = FindItem(items, firstItem); + else + { + FOR_VECTOR (i, items) + { + const CItemEx &cdItem = items[i]; + if (cdItem.Disk == firstItem.Disk + && (cdItem.LocalHeaderPos == firstItem.LocalHeaderPos)) + index = (int)i; + + if (i == 0 + || cdItem.Disk < min_Disk + || (cdItem.Disk == min_Disk && cdItem.LocalHeaderPos < min_LocalHeaderPos)) + { + min_Disk = cdItem.Disk; + min_LocalHeaderPos = cdItem.LocalHeaderPos; + } + } + } + if (index == -1) res = S_FALSE; - else if (!AreItemsEqual(firstItem, items[index])) + else if (!AreItemsEqual(firstItem, items[(unsigned)index])) res = S_FALSE; else { ArcInfo.CdWasRead = true; - ArcInfo.FirstItemRelatOffset = items[0].LocalHeaderPos; + if (IsCdUnsorted) + ArcInfo.FirstItemRelatOffset = min_LocalHeaderPos; + else + ArcInfo.FirstItemRelatOffset = items[0].LocalHeaderPos; // ArcInfo.FirstItemRelatOffset = _startLocalFromCd_Offset; } @@ -2588,7 +2672,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) The (Base) can be corrected later after ECD reading. But sfx volume with stub and (No)Span-marker in (!IsMultiVol) mode will have incorrect (Base) here. */ - ArcInfo.Base = ArcInfo.MarkerPos2; + ArcInfo.Base = (Int64)ArcInfo.MarkerPos2; } RINOK(SeekToVol(ArcInfo.MarkerVolIndex, ArcInfo.MarkerPos2)); @@ -2607,15 +2691,42 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) // GetVirtStreamPos() - 4 if (items.IsEmpty()) return S_FALSE; - NoCentralDir = true; - HeadersError = true; - return S_OK; + + bool isError = true; + + const UInt32 apkSize = _signature; + const unsigned kApkFooterSize = 16 + 8; + if (apkSize >= kApkFooterSize && apkSize <= (1 << 20)) + { + if (ReadUInt32() == 0) + { + CByteBuffer apk; + apk.Alloc(apkSize); + SafeRead(apk, apkSize); + ReadSignature(); + const Byte *footer = apk + apkSize - kApkFooterSize; + if (_signature == NSignature::kCentralFileHeader) + if (GetUi64(footer) == apkSize) + if (memcmp(footer + 8, "APK Sig Block 42", 16) == 0) + { + isError = false; + IsApk = true; + } + } + } + + if (isError) + { + NoCentralDir = true; + HeadersError = true; + return S_OK; + } } _inBufMode = true; cdAbsOffset = GetVirtStreamPos() - 4; - cdDisk = Vols.StreamIndex; + cdDisk = (UInt32)Vols.StreamIndex; #ifdef ZIP_SELF_CHECK if (!IsMultiVol && _cnt != GetVirtStreamPos() - ArcInfo.MarkerPos2) @@ -2656,7 +2767,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) needSetBase = true; numCdItems = cdItems.Size(); - cdRelatOffset = cdAbsOffset - ArcInfo.Base; + cdRelatOffset = (UInt64)((Int64)cdAbsOffset - ArcInfo.Base); if (!cdItems.IsEmpty()) { @@ -2712,6 +2823,8 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) Byte buf[kBufSize]; SafeRead(buf, kBufSize); locator.Parse(buf); + // we ignore the error, where some zip creators use (NumDisks == 0) + // if (locator.NumDisks == 0) HeadersWarning = true; } ReadSignature(); @@ -2764,12 +2877,12 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) if (IsMultiVol) { - if (cdDisk != (int)cdInfo.CdDisk) + if (cdDisk != cdInfo.CdDisk) HeadersError = true; } else if (needSetBase && cdOK) { - const UInt64 oldBase = ArcInfo.Base; + const UInt64 oldBase = (UInt64)ArcInfo.Base; // localsWereRead == true // ArcInfo.Base == ArcInfo.MarkerPos2 // cdRelatOffset == (cdAbsOffset - ArcInfo.Base) @@ -2778,13 +2891,13 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) { if (ecd64Disk == Vols.StartVolIndex) { - const Int64 newBase = (Int64)ecd64AbsOffset - locator.Ecd64Offset; + const Int64 newBase = (Int64)ecd64AbsOffset - (Int64)locator.Ecd64Offset; if (newBase <= (Int64)ecd64AbsOffset) { if (!localsWereRead || newBase <= (Int64)ArcInfo.MarkerPos2) { ArcInfo.Base = newBase; - cdRelatOffset = cdAbsOffset - newBase; + cdRelatOffset = (UInt64)((Int64)cdAbsOffset - newBase); } else cdOK = false; @@ -2795,7 +2908,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) { if ((int)cdDisk == Vols.StartVolIndex) { - const Int64 newBase = (Int64)cdAbsOffset - cdInfo.Offset; + const Int64 newBase = (Int64)cdAbsOffset - (Int64)cdInfo.Offset; if (newBase <= (Int64)cdAbsOffset) { if (!localsWereRead || newBase <= (Int64)ArcInfo.MarkerPos2) @@ -2828,7 +2941,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) if (localsWereRead) { - const UInt64 delta = oldBase - ArcInfo.Base; + const UInt64 delta = (UInt64)((Int64)oldBase - ArcInfo.Base); if (delta != 0) { FOR_VECTOR (i, items) @@ -2864,7 +2977,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) if (isZip64) { - if (cdInfo.ThisDisk == 0 && ecd64AbsOffset != ArcInfo.Base + locator.Ecd64Offset + if ((cdInfo.ThisDisk == 0 && ecd64AbsOffset != (UInt64)(ArcInfo.Base + (Int64)locator.Ecd64Offset)) // || cdInfo.NumEntries_in_ThisDisk != numCdItems || cdInfo.NumEntries != numCdItems || cdInfo.Size != cdSize @@ -2902,10 +3015,10 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) { if ((unsigned)nextLocalIndex < items.Size()) { - CItemEx &item = items[nextLocalIndex]; + CItemEx &item = items[(unsigned)nextLocalIndex]; if (item.Disk == cdItem.Disk && (item.LocalHeaderPos == cdItem.LocalHeaderPos - || Overflow32bit && (UInt32)item.LocalHeaderPos == cdItem.LocalHeaderPos)) + || (Overflow32bit && (UInt32)item.LocalHeaderPos == cdItem.LocalHeaderPos))) index = nextLocalIndex++; else nextLocalIndex = -1; @@ -2924,7 +3037,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) continue; } - CItemEx &item = items[index]; + CItemEx &item = items[(unsigned)index]; if (item.Name != cdItem.Name // || item.Name.Len() != cdItem.Name.Len() || item.PackSize != cdItem.PackSize @@ -2965,7 +3078,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) if (isZip64) { if (cdInfo.NumEntries != items.Size() - || ecd.NumEntries != items.Size() && ecd.NumEntries != 0xFFFF) + || (ecd.NumEntries != items.Size() && ecd.NumEntries != 0xFFFF)) HeadersError = true; } else @@ -3069,7 +3182,9 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit, else { // printf("\nOpen offset = %u\n", (unsigned)startPos); - if (IsMultiVol && (unsigned)Vols.StartParsingVol < Vols.Streams.Size() && Vols.Streams[Vols.StartParsingVol].Stream) + if (IsMultiVol + && (unsigned)Vols.StartParsingVol < Vols.Streams.Size() + && Vols.Streams[(unsigned)Vols.StartParsingVol].Stream) { RINOK(SeekToVol(Vols.StartParsingVol, Vols.StreamIndex == Vols.StartVolIndex ? startPos : 0)); } @@ -3117,7 +3232,7 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit, { if ((unsigned)Vols.StartVolIndex < Vols.Streams.Size()) { - Stream = Vols.Streams[Vols.StartVolIndex].Stream; + Stream = Vols.Streams[(unsigned)Vols.StartVolIndex].Stream; if (Stream) { RINOK(Seek_SavePos(curPos)); @@ -3173,7 +3288,7 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit, { ArcInfo.FinishPos = ArcInfo.FileEndPos; if ((unsigned)Vols.StreamIndex < Vols.Streams.Size()) - if (GetVirtStreamPos() < Vols.Streams[Vols.StreamIndex].Size) + if (GetVirtStreamPos() < Vols.Streams[(unsigned)Vols.StreamIndex].Size) ArcInfo.ThereIsTail = true; } else @@ -3204,8 +3319,8 @@ HRESULT CInArchive::GetItemStream(const CItemEx &item, bool seekPackData, CMyCom { if (UseDisk_in_SingleVol && item.Disk != EcdVolIndex) return S_OK; - pos += ArcInfo.Base; - RINOK(StreamRef->Seek(pos, STREAM_SEEK_SET, NULL)); + pos = (UInt64)((Int64)pos + ArcInfo.Base); + RINOK(StreamRef->Seek((Int64)pos, STREAM_SEEK_SET, NULL)); stream = StreamRef; return S_OK; } @@ -3216,10 +3331,10 @@ HRESULT CInArchive::GetItemStream(const CItemEx &item, bool seekPackData, CMyCom IInStream *str2 = Vols.Streams[item.Disk].Stream; if (!str2) return S_OK; - RINOK(str2->Seek(pos, STREAM_SEEK_SET, NULL)); + RINOK(str2->Seek((Int64)pos, STREAM_SEEK_SET, NULL)); Vols.NeedSeek = false; - Vols.StreamIndex = item.Disk; + Vols.StreamIndex = (int)item.Disk; CVolStream *volsStreamSpec = new CVolStream; volsStreamSpec->Vols = &Vols; diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h index f46f1f07..31e524b6 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.h +++ b/CPP/7zip/Archive/Zip/ZipIn.h @@ -32,6 +32,11 @@ public: { return LocalFullHeaderSize + GetPackSizeWithDescriptor(); } UInt64 GetDataPosition() const { return LocalHeaderPos + LocalFullHeaderSize; } + + bool IsBadDescriptor() const + { + return !FromCentral && FromLocal && HasDescriptor() && !DescriptorWasRead; + } }; @@ -282,6 +287,7 @@ class CInArchive HRESULT SeekToVol(int volIndex, UInt64 offset); HRESULT ReadFromCache(Byte *data, unsigned size, unsigned &processed); + HRESULT ReadFromCache_FALSE(Byte *data, unsigned size); HRESULT ReadVols2(IArchiveOpenVolumeCallback *volCallback, unsigned start, int lastDisk, int zipDisk, unsigned numMissingVolsMax, unsigned &numMissingVols); @@ -305,7 +311,7 @@ class CInArchive bool ReadFileName(unsigned nameSize, AString &dest); - bool ReadExtra(unsigned extraSize, CExtraBlock &extra, + bool ReadExtra(const CLocalItem &item, unsigned extraSize, CExtraBlock &extra, UInt64 &unpackSize, UInt64 &packSize, UInt64 &localOffset, UInt32 &disk); bool ReadLocalItem(CItemEx &item); HRESULT FindDescriptor(CItemEx &item, unsigned numFiles); @@ -325,6 +331,9 @@ public: bool IsArc; bool IsZip64; + + bool IsApk; + bool IsCdUnsorted; bool HeadersError; bool HeadersWarning; @@ -345,14 +354,19 @@ public: CVols Vols; - CInArchive(): Stream(NULL), StartStream(NULL), Callback(NULL), IsArcOpen(false) {} + CInArchive(): + IsArcOpen(false), + Stream(NULL), + StartStream(NULL), + Callback(NULL) + {} UInt64 GetPhySize() const { if (IsMultiVol) return ArcInfo.FinishPos; else - return ArcInfo.FinishPos - ArcInfo.Base; + return (UInt64)((Int64)ArcInfo.FinishPos - ArcInfo.Base); } UInt64 GetOffset() const @@ -360,7 +374,7 @@ public: if (IsMultiVol) return 0; else - return ArcInfo.Base; + return (UInt64)ArcInfo.Base; } @@ -393,7 +407,7 @@ public: return ArcInfo.FirstItemRelatOffset; if (IsMultiVol) return 0; - return ArcInfo.MarkerPos2 - ArcInfo.Base; + return (UInt64)((Int64)ArcInfo.MarkerPos2 - ArcInfo.Base); } @@ -412,7 +426,9 @@ public: || ArcInfo.Base < 0 || (Int64)ArcInfo.MarkerPos2 < ArcInfo.Base || ArcInfo.ThereIsTail - || GetEmbeddedStubSize() != 0) + || GetEmbeddedStubSize() != 0 + || IsApk + || IsCdUnsorted) return false; // 7-zip probably can update archives with embedded stubs. diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp index 5cff1735..38921dce 100644 --- a/CPP/7zip/Archive/Zip/ZipItem.cpp +++ b/CPP/7zip/Archive/Zip/ZipItem.cpp @@ -33,9 +33,12 @@ static const CUInt32PCharPair g_ExtraTypes[] = { NExtraID::kStrongEncrypt, "StrongCrypto" }, { NExtraID::kUnixTime, "UT" }, { NExtraID::kUnixExtra, "UX" }, + { NExtraID::kUnix2Extra, "Ux" }, + { NExtraID::kUnix3Extra, "ux" }, { NExtraID::kIzUnicodeComment, "uc" }, { NExtraID::kIzUnicodeName, "up" }, - { NExtraID::kWzAES, "WzAES" } + { NExtraID::kWzAES, "WzAES" }, + { NExtraID::kApkAlign, "ApkAlign" } }; void CExtraSubBlock::PrintInfo(AString &s) const @@ -46,6 +49,22 @@ void CExtraSubBlock::PrintInfo(AString &s) const if (pair.Value == ID) { s += pair.Name; + /* + if (ID == NExtraID::kApkAlign && Data.Size() >= 2) + { + char sz[32]; + sz[0] = ':'; + ConvertUInt32ToHex(GetUi16(Data), sz + 1); + s += sz; + for (unsigned j = 2; j < Data.Size(); j++) + { + char sz[32]; + sz[0] = '-'; + ConvertUInt32ToHex(Data[j], sz + 1); + s += sz; + } + } + */ return; } } @@ -209,6 +228,7 @@ bool CLocalItem::IsDir() const bool CItem::IsDir() const { + // FIXME: we can check InfoZip UTF-8 name at first. if (NItemName::HasTailSlash(Name, GetCodePage())) return true; @@ -315,10 +335,30 @@ bool CItem::GetPosixAttrib(UInt32 &attrib) const return false; } + +bool CExtraSubBlock::CheckIzUnicode(const AString &s) const +{ + size_t size = Data.Size(); + if (size < 1 + 4) + return false; + const Byte *p = (const Byte *)Data; + if (p[0] > 1) + return false; + if (CrcCalc(s, s.Len()) != GetUi32(p + 1)) + return false; + size -= 5; + p += 5; + for (size_t i = 0; i < size; i++) + if (p[i] == 0) + return false; + return Check_UTF8_Buf((const char *)(const void *)p, size, false); +} + + void CItem::GetUnicodeString(UString &res, const AString &s, bool isComment, bool useSpecifiedCodePage, UINT codePage) const { bool isUtf8 = IsUtf8(); - bool ignore_Utf8_Errors = true; + // bool ignore_Utf8_Errors = true; if (!isUtf8) { @@ -333,10 +373,14 @@ void CItem::GetUnicodeString(UString &res, const AString &s, bool isComment, boo const CExtraSubBlock &sb = subBlocks[i]; if (sb.ID == id) { - AString utf; - if (sb.ExtractIzUnicode(CrcCalc(s, s.Len()), utf)) - if (ConvertUTF8ToUnicode(utf, res)) + if (sb.CheckIzUnicode(s)) + { + // const unsigned kIzUnicodeHeaderSize = 5; + if (Convert_UTF8_Buf_To_Unicode( + (const char *)(const void *)(const Byte *)sb.Data + 5, + sb.Data.Size() - 5, res)) return; + } break; } } @@ -351,15 +395,21 @@ void CItem::GetUnicodeString(UString &res, const AString &s, bool isComment, boo We try to get name as UTF-8. Do we need to do it in POSIX version also? */ isUtf8 = true; - ignore_Utf8_Errors = false; + + /* 21.02: we want to ignore UTF-8 errors to support file paths that are mixed + of UTF-8 and non-UTF-8 characters. */ + // ignore_Utf8_Errors = false; + // ignore_Utf8_Errors = true; } #endif } if (isUtf8) - if (ConvertUTF8ToUnicode(s, res) || ignore_Utf8_Errors) - return; + { + ConvertUTF8ToUnicode(s, res); + return; + } MultiByteToUnicodeString2(res, s, useSpecifiedCodePage ? codePage : GetCodePage()); } diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h index e5769711..6ee87658 100644 --- a/CPP/7zip/Archive/Zip/ZipItem.h +++ b/CPP/7zip/Archive/Zip/ZipItem.h @@ -33,23 +33,8 @@ struct CExtraSubBlock bool ExtractNtfsTime(unsigned index, FILETIME &ft) const; bool ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const; bool ExtractUnixExtraTime(unsigned index, UInt32 &res) const; - - bool ExtractIzUnicode(UInt32 crc, AString &name) const - { - unsigned size = (unsigned)Data.Size(); - if (size < 1 + 4) - return false; - const Byte *p = (const Byte *)Data; - if (p[0] > 1) - return false; - if (crc != GetUi32(p + 1)) - return false; - size -= 5; - name.SetFrom_CalcLen((const char *)p + 5, size); - if (size != name.Len()) - return false; - return CheckUTF8(name, false); - } + + bool CheckIzUnicode(const AString &s) const; void PrintInfo(AString &s) const; }; @@ -202,8 +187,14 @@ struct CExtraBlock for (unsigned i = SubBlocks.Size(); i != 0;) { i--; - if (SubBlocks[i].ID != NFileHeader::NExtraID::kWzAES) - SubBlocks.Delete(i); + switch (SubBlocks[i].ID) + { + case NFileHeader::NExtraID::kStrongEncrypt: + case NFileHeader::NExtraID::kWzAES: + break; + default: + SubBlocks.Delete(i); + } } } }; @@ -266,9 +257,9 @@ private: void SetFlag(unsigned bitMask, bool enable) { if (enable) - Flags |= bitMask; + Flags = (UInt16)(Flags | bitMask); else - Flags &= ~bitMask; + Flags = (UInt16)(Flags & ~bitMask); } public: @@ -279,7 +270,12 @@ public: // void SetFlag_AltStream(bool isAltStream) { SetFlag(NFileHeader::NFlags::kAltStream, isAltStream); } void SetDescriptorMode(bool useDescriptor) { SetFlag(NFileHeader::NFlags::kDescriptorUsedMask, useDescriptor); } - UINT GetCodePage() const { return CP_OEMCP; } + UINT GetCodePage() const + { + if (IsUtf8()) + return CP_UTF8; + return CP_OEMCP; + } }; @@ -330,10 +326,19 @@ public: } return (Crc != 0 || !IsDir()); } + + bool Is_MadeBy_Unix() const + { + if (!FromCentral) + return false; + return (MadeByVersion.HostOS == NFileHeader::NHostOS::kUnix); + } UINT GetCodePage() const { // 18.06: now we use HostOS only from Central::MadeByVersion + if (IsUtf8()) + return CP_UTF8; if (!FromCentral) return CP_OEMCP; Byte hostOS = MadeByVersion.HostOS; diff --git a/CPP/7zip/Archive/Zip/ZipOut.cpp b/CPP/7zip/Archive/Zip/ZipOut.cpp index 945bd020..efed0a41 100644 --- a/CPP/7zip/Archive/Zip/ZipOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipOut.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../../C/7zCrc.h" + #include "../../Common/OffsetStream.h" #include "ZipOut.h" @@ -23,7 +25,7 @@ HRESULT COutArchive::Create(IOutStream *outStream) void COutArchive::SeekToCurPos() { - HRESULT res = m_Stream->Seek(m_Base + m_CurPos, STREAM_SEEK_SET, NULL); + HRESULT res = m_Stream->Seek((Int64)(m_Base + m_CurPos), STREAM_SEEK_SET, NULL); if (res != S_OK) throw CSystemException(res); } @@ -97,6 +99,17 @@ void COutArchive::WriteCommonItemInfo(const CLocalItem &item, bool isZip64) #define WRITE_32_VAL_SPEC(__v, __isZip64) Write32((__isZip64) ? 0xFFFFFFFF : (UInt32)(__v)); +void COutArchive::WriteUtfName(const CItemOut &item) +{ + if (item.Name_Utf.Size() == 0) + return; + Write16(NFileHeader::NExtraID::kIzUnicodeName); + Write16((UInt16)(5 + item.Name_Utf.Size())); + Write8(1); // (1 = version) of that extra field + Write32(CrcCalc(item.Name.Ptr(), item.Name.Len())); + WriteBytes(item.Name_Utf, (UInt16)item.Name_Utf.Size()); +} + void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck) { m_LocalHeaderPos = m_CurPos; @@ -109,7 +122,10 @@ void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck) if (needCheck && m_IsZip64) isZip64 = true; - const UInt32 localExtraSize = (UInt32)((isZip64 ? (4 + 8 + 8): 0) + item.LocalExtra.GetSize()); + const UInt32 localExtraSize = (UInt32)( + (isZip64 ? (4 + 8 + 8): 0) + + item.Get_UtfName_ExtraSize() + + item.LocalExtra.GetSize()); if ((UInt16)localExtraSize != localExtraSize) throw CSystemException(E_FAIL); if (needCheck && m_ExtraSize != localExtraSize) @@ -152,6 +168,8 @@ void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck) Write64(packSize); } + WriteUtfName(item); + WriteExtra(item.LocalExtra); // Why don't we write NTFS timestamps to local header? @@ -230,14 +248,19 @@ void COutArchive::WriteCentralHeader(const CItemOut &item) Write16((UInt16)item.Name.Len()); - UInt16 zip64ExtraSize = (UInt16)((isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0)); + const UInt16 zip64ExtraSize = (UInt16)((isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0)); const UInt16 kNtfsExtraSize = 4 + 2 + 2 + (3 * 8); - const UInt16 centralExtraSize = (UInt16)( - (isZip64 ? 4 + zip64ExtraSize : 0) + - (item.NtfsTimeIsDefined ? 4 + kNtfsExtraSize : 0) + - item.CentralExtra.GetSize()); + const size_t centralExtraSize = + (isZip64 ? 4 + zip64ExtraSize : 0) + + (item.NtfsTimeIsDefined ? 4 + kNtfsExtraSize : 0) + + item.Get_UtfName_ExtraSize() + + item.CentralExtra.GetSize(); + + const UInt16 centralExtraSize16 = (UInt16)centralExtraSize; + if (centralExtraSize16 != centralExtraSize) + throw CSystemException(E_FAIL); - Write16(centralExtraSize); // test it; + Write16(centralExtraSize16); const UInt16 commentSize = (UInt16)item.Comment.Size(); @@ -271,6 +294,8 @@ void COutArchive::WriteCentralHeader(const CItemOut &item) WriteNtfsTime(item.Ntfs_ATime); WriteNtfsTime(item.Ntfs_CTime); } + + WriteUtfName(item); WriteExtra(item.CentralExtra); if (commentSize != 0) diff --git a/CPP/7zip/Archive/Zip/ZipOut.h b/CPP/7zip/Archive/Zip/ZipOut.h index 0a0ac0c8..3546411c 100644 --- a/CPP/7zip/Archive/Zip/ZipOut.h +++ b/CPP/7zip/Archive/Zip/ZipOut.h @@ -21,6 +21,16 @@ public: bool NtfsTimeIsDefined; // It's possible that NtfsTime is not defined, but there is NtfsTime in Extra. + + CByteBuffer Name_Utf; // for Info-Zip (kIzUnicodeName) Extra + + size_t Get_UtfName_ExtraSize() const + { + const size_t size = Name_Utf.Size(); + if (size == 0) + return 0; + return 4 + 5 + size; + } CItemOut(): NtfsTimeIsDefined(false) {} }; @@ -52,6 +62,7 @@ class COutArchive Write32(ft.dwHighDateTime); } + void WriteUtfName(const CItemOut &item); void WriteExtra(const CExtraBlock &extra); void WriteCommonItemInfo(const CLocalItem &item, bool isZip64); void WriteCentralHeader(const CItemOut &item); diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp index e65c2b8b..4468c7c5 100644 --- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp @@ -62,6 +62,21 @@ static void AddAesExtra(CItem &item, Byte aesKeyMode, UInt16 method) } +static void Copy_From_UpdateItem_To_ItemOut(const CUpdateItem &ui, CItemOut &item) +{ + item.Name = ui.Name; + item.Name_Utf = ui.Name_Utf; + item.Comment = ui.Comment; + item.SetUtf8(ui.IsUtf8); + // item.SetFlag_AltStream(ui.IsAltStream); + // item.ExternalAttrib = ui.Attrib; + item.Time = ui.Time; + item.Ntfs_MTime = ui.Ntfs_MTime; + item.Ntfs_ATime = ui.Ntfs_ATime; + item.Ntfs_CTime = ui.Ntfs_CTime; + item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined; +} + static void SetFileHeader( const CCompressionMethodMode &options, const CUpdateItem &ui, @@ -69,22 +84,15 @@ static void SetFileHeader( CItemOut &item) { item.Size = ui.Size; - bool isDir = ui.IsDir; + const bool isDir = ui.IsDir; item.ClearFlags(); if (ui.NewProps) { - item.Name = ui.Name; - item.Comment = ui.Comment; - item.SetUtf8(ui.IsUtf8); + Copy_From_UpdateItem_To_ItemOut(ui, item); // item.SetFlag_AltStream(ui.IsAltStream); item.ExternalAttrib = ui.Attrib; - item.Time = ui.Time; - item.Ntfs_MTime = ui.Ntfs_MTime; - item.Ntfs_ATime = ui.Ntfs_ATime; - item.Ntfs_CTime = ui.Ntfs_CTime; - item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined; } /* else @@ -148,6 +156,35 @@ static void SetItemInfoFromCompressingResult(const CCompressingResult &compressi #ifndef _7ZIP_ST +struct CMtSem +{ + NWindows::NSynchronization::CSemaphore Semaphore; + NWindows::NSynchronization::CCriticalSection CS; + CIntVector Indexes; + int Head; + + void ReleaseItem(unsigned index) + { + { + CCriticalSectionLock lock(CS); + Indexes[index] = Head; + Head = (int)index; + } + Semaphore.Release(); + } + + int GetFreeItem() + { + int i; + { + CCriticalSectionLock lock(CS); + i = Head; + Head = Indexes[(unsigned)i]; + } + return i; + } +}; + static THREAD_FUNC_DECL CoderThread(void *threadCoderInfo); struct CThreadInfo @@ -156,7 +193,9 @@ struct CThreadInfo NWindows::CThread Thread; NWindows::NSynchronization::CAutoResetEvent CompressEvent; - NWindows::NSynchronization::CAutoResetEvent CompressionCompletedEvent; + CMtSem *MtSem; + unsigned ThreadIndex; + bool ExitThread; CMtCompressProgress *ProgressSpec; @@ -177,34 +216,43 @@ struct CThreadInfo UInt32 FileTime; UInt64 ExpectedDataSize; - CThreadInfo(const CCompressionMethodMode &options): + CThreadInfo(): ExitThread(false), - ProgressSpec(0), - OutStreamSpec(0), - Coder(options), + ProgressSpec(NULL), + OutStreamSpec(NULL), InSeqMode(false), OutSeqMode(false), FileTime(0), ExpectedDataSize((UInt64)(Int64)-1) {} + + void SetOptions(const CCompressionMethodMode &options) + { + Coder.SetOptions(options); + } HRESULT CreateEvents() { - RINOK(CompressEvent.CreateIfNotCreated()); - return CompressionCompletedEvent.CreateIfNotCreated(); + WRes wres = CompressEvent.CreateIfNotCreated_Reset(); + return HRESULT_FROM_WIN32(wres); + } + + HRESULT CreateThread() + { + WRes wres = Thread.Create(CoderThread, this); + return HRESULT_FROM_WIN32(wres); } - HRes CreateThread() { return Thread.Create(CoderThread, this); } void WaitAndCode(); - void StopWaitClose() + + void StopWait_Close() { ExitThread = true; - if (OutStreamSpec != 0) + if (OutStreamSpec) OutStreamSpec->StopWriting(E_ABORT); if (CompressEvent.IsCreated()) CompressEvent.Set(); - Thread.Wait(); - Thread.Close(); + Thread.Wait_Close(); } }; @@ -215,7 +263,7 @@ void CThreadInfo::WaitAndCode() CompressEvent.Lock(); if (ExitThread) return; - + Result = Coder.Compress( EXTERNAL_CODECS_LOC_VARS InStream, OutStream, @@ -224,7 +272,8 @@ void CThreadInfo::WaitAndCode() if (Result == S_OK && Progress) Result = Progress->SetRatioInfo(&CompressingResult.UnpackSize, &CompressingResult.PackSize); - CompressionCompletedEvent.Set(); + + MtSem->ReleaseItem(ThreadIndex); } } @@ -241,7 +290,7 @@ public: ~CThreads() { FOR_VECTOR (i, Threads) - Threads[i].StopWaitClose(); + Threads[i].StopWait_Close(); } }; @@ -253,7 +302,8 @@ struct CMemBlocks2: public CMemLockBlocks bool Finished; CCompressingResult CompressingResult; - CMemBlocks2(): Skip(false), InSeqMode(false), PreDescriptorMode(false), Finished(false) {} + CMemBlocks2(): Skip(false), InSeqMode(false), PreDescriptorMode(false), Finished(false), + CompressingResult() {} }; class CMemRefs @@ -359,7 +409,6 @@ STDMETHODIMP CMtProgressMixer::SetRatioInfo(const UInt64 *inSize, const UInt64 * #endif - static HRESULT UpdateItemOldData( COutArchive &archive, CInArchive *inArchive, @@ -385,21 +434,11 @@ static HRESULT UpdateItemOldData( if (item.HasDescriptor()) return E_NOTIMPL; - // use old name size. - // we keep ExternalAttrib and some another properties from old archive // item.ExternalAttrib = ui.Attrib; - // if we don't change Comment, we keep Comment from OldProperties - item.Comment = ui.Comment; - item.Name = ui.Name; - item.SetUtf8(ui.IsUtf8); + Copy_From_UpdateItem_To_ItemOut(ui, item); // item.SetFlag_AltStream(ui.IsAltStream); - item.Time = ui.Time; - item.Ntfs_MTime = ui.Ntfs_MTime; - item.Ntfs_ATime = ui.Ntfs_ATime; - item.Ntfs_CTime = ui.Ntfs_CTime; - item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined; item.CentralExtra.RemoveUnknownSubBlocks(); item.LocalExtra.RemoveUnknownSubBlocks(); @@ -452,16 +491,16 @@ static void UpdatePropsFromStream(CUpdateItem &item, ISequentialInStream *fileIn FILETIME cTime, aTime, mTime; UInt64 size; - // UInt32 attrib; - if (getProps->GetProps(&size, &cTime, &aTime, &mTime, NULL) != S_OK) + UInt32 attrib; + if (getProps->GetProps(&size, &cTime, &aTime, &mTime, &attrib) != S_OK) return; if (size != item.Size && size != (UInt64)(Int64)-1) { - Int64 newComplexity = totalComplexity + ((Int64)size - (Int64)item.Size); + const Int64 newComplexity = (Int64)totalComplexity + ((Int64)size - (Int64)item.Size); if (newComplexity > 0) { - totalComplexity = newComplexity; + totalComplexity = (UInt64)newComplexity; updateCallback->SetTotal(totalComplexity); } item.Size = size; @@ -481,7 +520,7 @@ static void UpdatePropsFromStream(CUpdateItem &item, ISequentialInStream *fileIn if (!IsZero_FILETIME(cTime)) item.Ntfs_CTime = cTime; if (!IsZero_FILETIME(aTime)) item.Ntfs_ATime = aTime; - // item.Attrib = attrib; + item.Attrib = attrib; } @@ -501,7 +540,8 @@ static HRESULT Update2St( CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); - CAddCommon compressor(*options); + CAddCommon compressor; + compressor.SetOptions(*options); CObjectVector<CItemOut> items; UInt64 unpackSizeTotal = 0, packSizeTotal = 0; @@ -519,7 +559,7 @@ static HRESULT Update2St( { // Note: for (ui.NewProps && !ui.NewData) it copies Props from old archive, // But we will rewrite all important properties later. But we can keep some properties like Comment - itemEx = inputItems[ui.IndexInArc]; + itemEx = inputItems[(unsigned)ui.IndexInArc]; if (inArchive->ReadLocalItemAfterCdItemFull(itemEx) != S_OK) return E_NOTIMPL; (CItem &)item = itemEx; @@ -659,7 +699,7 @@ static HRESULT Update2( } else { - CItemEx inputItem = inputItems[ui.IndexInArc]; + CItemEx inputItem = inputItems[(unsigned)ui.IndexInArc]; if (inArchive->ReadLocalItemAfterCdItemFull(inputItem) != S_OK) return E_NOTIMPL; complexity += inputItem.GetLocalFullSize(); @@ -686,7 +726,8 @@ static HRESULT Update2( options2._methods.AddNew(); } - CAddCommon compressor(options2); + CAddCommon compressor; + compressor.SetOptions(options2); complexity = 0; @@ -715,15 +756,24 @@ static HRESULT Update2( UInt32 numThreads = options._numThreads; - const UInt32 kNumMaxThreads = 64; - if (numThreads > kNumMaxThreads) - numThreads = kNumMaxThreads; - if (numThreads > MAXIMUM_WAIT_OBJECTS) // is 64 in Windows (is it 64 in all versions?) + { + const UInt32 kNumMaxThreads = + #ifdef _WIN32 + 64; // _WIN32 supports only 64 threads in one group. So no need for more threads here + #else + 128; + #endif + if (numThreads > kNumMaxThreads) + numThreads = kNumMaxThreads; + } + /* + if (numThreads > MAXIMUM_WAIT_OBJECTS) // is 64 in Windows numThreads = MAXIMUM_WAIT_OBJECTS; + */ if (numThreads < 1) numThreads = 1; - const size_t kMemPerThread = (1 << 25); + const size_t kMemPerThread = (size_t)1 << 25; const size_t kBlockSize = 1 << 16; bool mtMode = (numThreads > 1); @@ -731,6 +781,8 @@ static HRESULT Update2( if (numFilesToCompress <= 1) mtMode = false; + // mtMode = true; // debug: to test mtMode + if (!mtMode) { FOR_VECTOR (mi, options2._methods) @@ -788,7 +840,7 @@ static HRESULT Update2( if (t > numThreads) t = numThreads; oneMethodMain->AddProp_NumThreads(t); - numXzThreads = t; + numXzThreads = (int)t; } numThreads /= (unsigned)numXzThreads; } @@ -830,8 +882,16 @@ static HRESULT Update2( CMemBlockManagerMt memManager(kBlockSize); CMemRefs refs(&memManager); + CMtSem mtSem; CThreads threads; - CRecordVector<HANDLE> compressingCompletedEvents; + mtSem.Head = -1; + mtSem.Indexes.ClearAndSetSize(numThreads); + { + WRes wres = mtSem.Semaphore.Create(0, numThreads); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + } + CUIntVector threadIndices; // list threads in order of updateItems { @@ -840,26 +900,32 @@ static HRESULT Update2( refs.Refs.Add(CMemBlocks2()); for (i = 0; i < numThreads; i++) - threads.Threads.Add(CThreadInfo(options2)); + { + threads.Threads.AddNew(); + // mtSem.Indexes[i] = -1; // actually we don't use these values + } for (i = 0; i < numThreads; i++) { CThreadInfo &threadInfo = threads.Threads[i]; + threadInfo.SetOptions(options2); ; #ifdef EXTERNAL_CODECS threadInfo.__externalCodecs = __externalCodecs; #endif RINOK(threadInfo.CreateEvents()); threadInfo.OutStreamSpec = new COutMemStream(&memManager); - RINOK(threadInfo.OutStreamSpec->CreateEvents()); + RINOK(threadInfo.OutStreamSpec->CreateEvents(SYNC_WFMO(&memManager.Synchro))); threadInfo.OutStream = threadInfo.OutStreamSpec; threadInfo.IsFree = true; threadInfo.ProgressSpec = new CMtCompressProgress(); threadInfo.Progress = threadInfo.ProgressSpec; - threadInfo.ProgressSpec->Init(&mtCompressProgressMixer, (int)i); + threadInfo.ProgressSpec->Init(&mtCompressProgressMixer, i); threadInfo.InSeqMode = false; threadInfo.OutSeqMode = false; threadInfo.FileTime = 0; threadInfo.ExpectedDataSize = (UInt64)(Int64)-1; + threadInfo.ThreadIndex = i; + threadInfo.MtSem = &mtSem; RINOK(threadInfo.CreateThread()); } } @@ -890,7 +956,7 @@ static HRESULT Update2( } else { - itemEx = inputItems[ui.IndexInArc]; + itemEx = inputItems[(unsigned)ui.IndexInArc]; if (inArchive->ReadLocalItemAfterCdItemFull(itemEx) != S_OK) return E_NOTIMPL; (CItem &)item = itemEx; @@ -958,10 +1024,9 @@ static HRESULT Update2( threadInfo.OutSeqMode = outSeqMode; threadInfo.FileTime = ui.Time; // FileTime is used for ZipCrypto only in seqMode threadInfo.ExpectedDataSize = ui.Size; - + threadInfo.CompressEvent.Set(); - compressingCompletedEvents.Add(threadInfo.CompressionCompletedEvent); threadIndices.Add(k); } } @@ -982,7 +1047,7 @@ static HRESULT Update2( if (!ui.NewProps || !ui.NewData) { - itemEx = inputItems[ui.IndexInArc]; + itemEx = inputItems[(unsigned)ui.IndexInArc]; if (inArchive->ReadLocalItemAfterCdItemFull(itemEx) != S_OK) return E_NOTIMPL; (CItem &)item = itemEx; @@ -1004,7 +1069,7 @@ static HRESULT Update2( if (memRef.Finished) { if (lastRealStreamItemIndex < (int)itemIndex) - lastRealStreamItemIndex = itemIndex; + lastRealStreamItemIndex = (int)itemIndex; SetFileHeader(options, ui, memRef.CompressingResult.DescriptorMode, item); @@ -1030,7 +1095,7 @@ static HRESULT Update2( { // LocalHeader was not written for current itemIndex still - lastRealStreamItemIndex = itemIndex; + lastRealStreamItemIndex = (int)itemIndex; // thread was started before for that item already, and memRef.SeqMode was set @@ -1060,24 +1125,30 @@ static HRESULT Update2( } } - DWORD result = ::WaitForMultipleObjects(compressingCompletedEvents.Size(), - &compressingCompletedEvents.Front(), FALSE, INFINITE); - if (result == WAIT_FAILED) - { - DWORD lastError = GetLastError(); - return lastError != 0 ? lastError : E_FAIL; - } - - unsigned t = (unsigned)(result - WAIT_OBJECT_0); - if (t >= compressingCompletedEvents.Size()) + WRes wres = mtSem.Semaphore.Lock(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + + int ti = mtSem.GetFreeItem(); + if (ti < 0) return E_FAIL; - CThreadInfo &threadInfo = threads.Threads[threadIndices[t]]; + CThreadInfo &threadInfo = threads.Threads[(unsigned)ti]; threadInfo.InStream.Release(); threadInfo.IsFree = true; RINOK(threadInfo.Result); + + unsigned t = 0; + + for (;;) + { + if (t == threadIndices.Size()) + return E_FAIL; + if (threadIndices[t] == (unsigned)ti) + break; + t++; + } threadIndices.Delete(t); - compressingCompletedEvents.Delete(t); if (t == 0) { @@ -1187,7 +1258,7 @@ HRESULT CCacheOutStream::Init(ISequentialOutStream *seqStream, IOutStream *strea { RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &_virtPos)); RINOK(_stream->Seek(0, STREAM_SEEK_END, &_virtSize)); - RINOK(_stream->Seek(_virtPos, STREAM_SEEK_SET, &_virtPos)); + RINOK(_stream->Seek((Int64)_virtPos, STREAM_SEEK_SET, &_virtPos)); } _phyPos = _virtPos; _phySize = _virtSize; @@ -1204,7 +1275,7 @@ HRESULT CCacheOutStream::MyWrite(size_t size) { if (!_stream) return E_FAIL; - RINOK(_stream->Seek(_cachedPos, STREAM_SEEK_SET, &_phyPos)); + RINOK(_stream->Seek((Int64)_cachedPos, STREAM_SEEK_SET, &_phyPos)); } size_t pos = (size_t)_cachedPos & kCacheMask; size_t curSize = MyMin(kCacheSize - pos, _cachedSize); @@ -1233,7 +1304,7 @@ CCacheOutStream::~CCacheOutStream() if (_virtSize != _phySize) _stream->SetSize(_virtSize); if (_virtPos != _phyPos) - _stream->Seek(_virtPos, STREAM_SEEK_SET, NULL); + _stream->Seek((Int64)_virtPos, STREAM_SEEK_SET, NULL); } ::MidFree(_cache); } @@ -1332,9 +1403,9 @@ STDMETHODIMP CCacheOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newP } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _virtPos = offset; + _virtPos = (UInt64)offset; if (newPosition) - *newPosition = offset; + *newPosition = (UInt64)offset; return S_OK; } @@ -1391,7 +1462,7 @@ HRESULT Update( { IInStream *baseStream = inArchive->GetBaseStream(); RINOK(baseStream->Seek(0, STREAM_SEEK_SET, NULL)); - RINOK(NCompress::CopyStream_ExactSize(baseStream, seqOutStream, inArchive->ArcInfo.Base, NULL)); + RINOK(NCompress::CopyStream_ExactSize(baseStream, seqOutStream, (UInt64)inArchive->ArcInfo.Base, NULL)); } } @@ -1412,7 +1483,7 @@ HRESULT Update( { IInStream *baseStream = inArchive->GetBaseStream(); RINOK(baseStream->Seek(inArchive->ArcInfo.Base, STREAM_SEEK_SET, NULL)); - UInt64 embStubSize = inArchive->ArcInfo.MarkerPos2 - inArchive->ArcInfo.Base; + const UInt64 embStubSize = (UInt64)((Int64)inArchive->ArcInfo.MarkerPos2 - inArchive->ArcInfo.Base); RINOK(NCompress::CopyStream_ExactSize(baseStream, outStream, embStubSize, NULL)); outArchive.MoveCurPos(embStubSize); } diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.h b/CPP/7zip/Archive/Zip/ZipUpdate.h index 8785ae60..95e72a47 100644 --- a/CPP/7zip/Archive/Zip/ZipUpdate.h +++ b/CPP/7zip/Archive/Zip/ZipUpdate.h @@ -34,11 +34,12 @@ struct CUpdateItem bool IsUtf8; // bool IsAltStream; int IndexInArc; - int IndexInClient; + unsigned IndexInClient; UInt32 Attrib; UInt32 Time; UInt64 Size; AString Name; + CByteBuffer Name_Utf; // for Info-Zip (kIzUnicodeName) Extra CByteBuffer Comment; // bool Commented; // CUpdateRange CommentRange; @@ -54,6 +55,7 @@ struct CUpdateItem // IsAltStream = false; Size = 0; Name.Empty(); + Name_Utf.Free(); Comment.Free(); } diff --git a/CPP/7zip/Bundles/Alone/Alone.dsp b/CPP/7zip/Bundles/Alone/Alone.dsp index 96a0f054..145cf2ca 100644 --- a/CPP/7zip/Bundles/Alone/Alone.dsp +++ b/CPP/7zip/Bundles/Alone/Alone.dsp @@ -44,7 +44,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /Gz /MT /W4 /WX /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gz /MT /W4 /WX /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe @@ -69,7 +69,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MDd /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # SUBTRACT CPP /WX # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" @@ -95,7 +95,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /Yu"StdAfx.h" /FD /c -# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe @@ -122,7 +122,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe @@ -350,10 +350,18 @@ SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\Sha1Prepare.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\Sha1Reg.cpp # End Source File # Begin Source File +SOURCE=..\..\..\Common\Sha256Prepare.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\Sha256Reg.cpp # End Source File # Begin Source File @@ -390,10 +398,6 @@ SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File -SOURCE=..\..\..\Common\Types.h -# End Source File -# Begin Source File - SOURCE=..\..\..\Common\UTFConvert.cpp # End Source File # Begin Source File @@ -526,6 +530,14 @@ SOURCE=..\..\..\Windows\PropVariantUtils.h # End Source File # Begin Source File +SOURCE=..\..\..\Windows\Registry.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Registry.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File @@ -542,6 +554,14 @@ SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File +SOURCE=..\..\..\Windows\SystemInfo.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\SystemInfo.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Windows\Thread.h # End Source File # Begin Source File @@ -999,14 +1019,6 @@ SOURCE=..\..\Compress\LzmaRegister.cpp # PROP Default_Filter "" # Begin Source File -SOURCE=..\..\Compress\PpmdContext.h -# End Source File -# Begin Source File - -SOURCE=..\..\Compress\PpmdDecode.h -# End Source File -# Begin Source File - SOURCE=..\..\Compress\PpmdDecoder.cpp !IF "$(CFG)" == "Alone - Win32 Release" @@ -1032,10 +1044,6 @@ SOURCE=..\..\Compress\PpmdDecoder.h # End Source File # Begin Source File -SOURCE=..\..\Compress\PpmdEncode.h -# End Source File -# Begin Source File - SOURCE=..\..\Compress\PpmdEncoder.cpp !IF "$(CFG)" == "Alone - Win32 Release" @@ -1065,14 +1073,6 @@ SOURCE=..\..\Compress\PpmdRegister.cpp # End Source File # Begin Source File -SOURCE=..\..\Compress\PpmdSubAlloc.h -# End Source File -# Begin Source File - -SOURCE=..\..\Compress\PpmdType.h -# End Source File -# Begin Source File - SOURCE=..\..\Compress\PpmdZip.cpp # End Source File # Begin Source File @@ -1457,10 +1457,6 @@ SOURCE=..\..\Archive\Zip\ZipItem.h # End Source File # Begin Source File -SOURCE=..\..\Archive\Zip\ZipItemEx.h -# End Source File -# Begin Source File - SOURCE=..\..\Archive\Zip\ZipOut.cpp # End Source File # Begin Source File @@ -2223,6 +2219,10 @@ SOURCE=..\..\..\..\C\7zStream.c # End Source File # Begin Source File +SOURCE=..\..\..\..\C\7zTypes.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Aes.c !IF "$(CFG)" == "Alone - Win32 Release" @@ -2981,6 +2981,11 @@ SOURCE=..\..\..\..\C\Sha1.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Sha1Opt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Sha256.c !IF "$(CFG)" == "Alone - Win32 Release" @@ -3009,6 +3014,11 @@ SOURCE=..\..\..\..\C\Sha256.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Sha256Opt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Sort.c !IF "$(CFG)" == "Alone - Win32 Release" @@ -3063,10 +3073,6 @@ SOURCE=..\..\..\..\C\Threads.c SOURCE=..\..\..\..\C\Threads.h # End Source File -# Begin Source File - -SOURCE=..\..\..\..\C\Types.h -# End Source File # End Group # End Target # End Project diff --git a/CPP/7zip/Bundles/Alone/makefile b/CPP/7zip/Bundles/Alone/makefile index 27bdbb94..0fce341b 100644 --- a/CPP/7zip/Bundles/Alone/makefile +++ b/CPP/7zip/Bundles/Alone/makefile @@ -1,4 +1,6 @@ PROG = 7za.exe +# USE_C_AES = 1 +# USE_C_SHA = 1 COMMON_OBJS = \ $O\CommandLineParser.obj \ @@ -33,8 +35,10 @@ WIN_OBJS = \ $O\PropVariant.obj \ $O\PropVariantConv.obj \ $O\PropVariantUtils.obj \ + $O\Registry.obj \ $O\Synchronization.obj \ $O\System.obj \ + $O\SystemInfo.obj \ $O\TimeUtils.obj \ 7ZIP_COMMON_OBJS = \ @@ -133,7 +137,7 @@ COMPRESS_OBJS = \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ - $O\BZip2CRC.obj \ + $O\BZip2Crc.obj \ $O\BZip2Decoder.obj \ $O\BZip2Encoder.obj \ $O\BZip2Register.obj \ @@ -201,8 +205,6 @@ C_OBJS = \ $O\Ppmd8.obj \ $O\Ppmd8Dec.obj \ $O\Ppmd8Enc.obj \ - $O\Sha1.obj \ - $O\Sha256.obj \ $O\Sort.obj \ $O\Threads.obj \ $O\Xz.obj \ @@ -216,5 +218,7 @@ C_OBJS = \ !include "../../Crc.mak" !include "../../Crc64.mak" !include "../../LzmaDec.mak" +!include "../../Sha1.mak" +!include "../../Sha256.mak" !include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/Alone/makefile.gcc b/CPP/7zip/Bundles/Alone/makefile.gcc new file mode 100644 index 00000000..e63fc332 --- /dev/null +++ b/CPP/7zip/Bundles/Alone/makefile.gcc @@ -0,0 +1,334 @@ +PROG = 7za + + + +# IS_X64 = 1 +# USE_ASM = 1 +# ST_MODE = 1 + +include ../../LzmaDec_gcc.mak + + +LOCAL_FLAGS_ST = +MT_OBJS = + + +ifdef ST_MODE + +LOCAL_FLAGS_ST = -D_7ZIP_ST + +ifdef SystemDrive +MT_OBJS = \ + $O/Threads.o \ + +endif + +else + +MT_OBJS = \ + $O/LzFindMt.o \ + $O/StreamBinder.o \ + $O/Synchronization.o \ + $O/VirtThread.o \ + $O/MemBlocks.o \ + $O/OutMemStream.o \ + $O/ProgressMt.o \ + $O/Threads.o \ + +endif + + + +LOCAL_FLAGS_SYS = + +ifdef SystemDrive + +LOCAL_FLAGS_SYS = \ + -D_7ZIP_LARGE_PAGES \ + -DWIN_LONG_PATH \ + -DSUPPORT_DEVICE_FILE \ + +SYS_OBJS = \ + $O/FileSystem.o \ + $O/Registry.o \ + $O/MemoryLock.o \ + $O/DLL.o \ + $O/DllSecur.o \ + $O/resource.o \ + +else + +SYS_OBJS = \ + $O/MyWindows.o \ + +endif + +LOCAL_FLAGS = \ + $(LOCAL_FLAGS_ST) \ + $(LOCAL_FLAGS_SYS) \ + + + +CONSOLE_OBJS = \ + $O/BenchCon.o \ + $O/ConsoleClose.o \ + $O/ExtractCallbackConsole.o \ + $O/HashCon.o \ + $O/List.o \ + $O/Main.o \ + $O/MainAr.o \ + $O/OpenCallbackConsole.o \ + $O/PercentPrinter.o \ + $O/UpdateCallbackConsole.o \ + $O/UserInputUtils.o \ + +UI_COMMON_OBJS = \ + $O/ArchiveCommandLine.o \ + $O/ArchiveExtractCallback.o \ + $O/ArchiveOpenCallback.o \ + $O/Bench.o \ + $O/DefaultName.o \ + $O/EnumDirItems.o \ + $O/Extract.o \ + $O/ExtractingFilePath.o \ + $O/HashCalc.o \ + $O/LoadCodecs.o \ + $O/OpenArchive.o \ + $O/PropIDUtils.o \ + $O/SetProperties.o \ + $O/SortUtils.o \ + $O/TempFiles.o \ + $O/Update.o \ + $O/UpdateAction.o \ + $O/UpdateCallback.o \ + $O/UpdatePair.o \ + $O/UpdateProduce.o \ + +COMMON_OBJS = \ + $O/CommandLineParser.o \ + $O/CRC.o \ + $O/CrcReg.o \ + $O/IntToString.o \ + $O/ListFileUtils.o \ + $O/MyString.o \ + $O/NewHandler.o \ + $O/StdInStream.o \ + $O/StdOutStream.o \ + $O/Sha1Prepare.o \ + $O/Sha1Reg.o \ + $O/Sha256Prepare.o \ + $O/Sha256Reg.o \ + $O/StringConvert.o \ + $O/StringToInt.o \ + $O/UTFConvert.o \ + $O/MyVector.o \ + $O/Wildcard.o \ + $O/XzCrc64Init.o \ + $O/XzCrc64Reg.o \ + + +WIN_OBJS = \ + $O/ErrorMsg.o \ + $O/FileDir.o \ + $O/FileFind.o \ + $O/FileIO.o \ + $O/FileLink.o \ + $O/FileName.o \ + $O/PropVariant.o \ + $O/PropVariantConv.o \ + $O/PropVariantUtils.o \ + $O/System.o \ + $O/SystemInfo.o \ + $O/TimeUtils.o \ + + +7ZIP_COMMON_OBJS = \ + $O/CreateCoder.o \ + $O/CWrappers.o \ + $O/FilePathAutoRename.o \ + $O/FileStreams.o \ + $O/InBuffer.o \ + $O/InOutTempBuffer.o \ + $O/FilterCoder.o \ + $O/LimitedStreams.o \ + $O/MethodId.o \ + $O/MethodProps.o \ + $O/OffsetStream.o \ + $O/OutBuffer.o \ + $O/ProgressUtils.o \ + $O/PropId.o \ + $O/StreamObjects.o \ + $O/StreamUtils.o \ + $O/UniqBlocks.o \ + +AR_OBJS = \ + $O/Bz2Handler.o \ + $O/GzHandler.o \ + $O/LzmaHandler.o \ + $O/SplitHandler.o \ + $O/XzHandler.o \ + +AR_COMMON_OBJS = \ + $O/CoderMixer2.o \ + $O/DummyOutStream.o \ + $O/HandlerOut.o \ + $O/InStreamWithCRC.o \ + $O/ItemNameUtils.o \ + $O/MultiStream.o \ + $O/OutStreamWithCRC.o \ + $O/ParseProperties.o \ + +7Z_OBJS = \ + $O/7zCompressionMode.o \ + $O/7zDecode.o \ + $O/7zEncode.o \ + $O/7zExtract.o \ + $O/7zFolderInStream.o \ + $O/7zHandler.o \ + $O/7zHandlerOut.o \ + $O/7zHeader.o \ + $O/7zIn.o \ + $O/7zOut.o \ + $O/7zProperties.o \ + $O/7zRegister.o \ + $O/7zSpecStream.o \ + $O/7zUpdate.o \ + +CAB_OBJS = \ + $O/CabBlockInStream.o \ + $O/CabHandler.o \ + $O/CabHeader.o \ + $O/CabIn.o \ + $O/CabRegister.o \ + +TAR_OBJS = \ + $O/TarHandler.o \ + $O/TarHandlerOut.o \ + $O/TarHeader.o \ + $O/TarIn.o \ + $O/TarOut.o \ + $O/TarUpdate.o \ + $O/TarRegister.o \ + +ZIP_OBJS = \ + $O/ZipAddCommon.o \ + $O/ZipHandler.o \ + $O/ZipHandlerOut.o \ + $O/ZipIn.o \ + $O/ZipItem.o \ + $O/ZipOut.o \ + $O/ZipUpdate.o \ + $O/ZipRegister.o \ + +COMPRESS_OBJS = \ + $O/Bcj2Coder.o \ + $O/Bcj2Register.o \ + $O/BcjCoder.o \ + $O/BcjRegister.o \ + $O/BitlDecoder.o \ + $O/BranchMisc.o \ + $O/BranchRegister.o \ + $O/ByteSwap.o \ + $O/BZip2Crc.o \ + $O/BZip2Decoder.o \ + $O/BZip2Encoder.o \ + $O/BZip2Register.o \ + $O/CopyCoder.o \ + $O/CopyRegister.o \ + $O/Deflate64Register.o \ + $O/DeflateDecoder.o \ + $O/DeflateEncoder.o \ + $O/DeflateRegister.o \ + $O/DeltaFilter.o \ + $O/ImplodeDecoder.o \ + $O/Lzma2Decoder.o \ + $O/Lzma2Encoder.o \ + $O/Lzma2Register.o \ + $O/LzmaDecoder.o \ + $O/LzmaEncoder.o \ + $O/LzmaRegister.o \ + $O/LzOutWindow.o \ + $O/LzxDecoder.o \ + $O/PpmdDecoder.o \ + $O/PpmdEncoder.o \ + $O/PpmdRegister.o \ + $O/PpmdZip.o \ + $O/QuantumDecoder.o \ + $O/ShrinkDecoder.o \ + $O/XzDecoder.o \ + $O/XzEncoder.o \ + +CRYPTO_OBJS = \ + $O/7zAes.o \ + $O/7zAesRegister.o \ + $O/HmacSha1.o \ + $O/MyAes.o \ + $O/MyAesReg.o \ + $O/Pbkdf2HmacSha1.o \ + $O/RandGen.o \ + $O/WzAes.o \ + $O/ZipCrypto.o \ + $O/ZipStrong.o \ + +C_OBJS = \ + $O/7zStream.o \ + $O/Alloc.o \ + $O/Bcj2.o \ + $O/Bcj2Enc.o \ + $O/Bra.o \ + $O/Bra86.o \ + $O/BraIA64.o \ + $O/BwtSort.o \ + $O/CpuArch.o \ + $O/Delta.o \ + $O/HuffEnc.o \ + $O/LzFind.o \ + $O/Lzma2Dec.o \ + $O/Lzma2DecMt.o \ + $O/Lzma2Enc.o \ + $O/LzmaDec.o \ + $O/LzmaEnc.o \ + $O/MtCoder.o \ + $O/MtDec.o \ + $O/Ppmd7.o \ + $O/Ppmd7Dec.o \ + $O/Ppmd7Enc.o \ + $O/Ppmd8.o \ + $O/Ppmd8Dec.o \ + $O/Ppmd8Enc.o \ + $O/Sort.o \ + $O/Xz.o \ + $O/XzDec.o \ + $O/XzEnc.o \ + $O/XzIn.o \ + $O/XzCrc64.o \ + $O/XzCrc64Opt.o \ + $O/7zCrc.o \ + $O/7zCrcOpt.o \ + $O/Aes.o \ + $O/AesOpt.o \ + $O/Sha256.o \ + $O/Sha256Opt.o \ + $O/Sha1.o \ + $O/Sha1Opt.o \ + +OBJS = \ + $(LZMA_DEC_OPT_OBJS) \ + $(C_OBJS) \ + $(MT_OBJS) \ + $(SYS_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(COMPRESS_OBJS) \ + $(CRYPTO_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(AR_OBJS) \ + $(AR_COMMON_OBJS) \ + $(7Z_OBJS) \ + $(CAB_OBJS) \ + $(TAR_OBJS) \ + $(ZIP_OBJS) \ + $(UI_COMMON_OBJS) \ + $(CONSOLE_OBJS) \ + +include ../../7zip_gcc.mak diff --git a/CPP/7zip/Bundles/Alone2/StdAfx.cpp b/CPP/7zip/Bundles/Alone2/StdAfx.cpp new file mode 100644 index 00000000..d0feea85 --- /dev/null +++ b/CPP/7zip/Bundles/Alone2/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Bundles/Alone2/StdAfx.h b/CPP/7zip/Bundles/Alone2/StdAfx.h new file mode 100644 index 00000000..2854ff3e --- /dev/null +++ b/CPP/7zip/Bundles/Alone2/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/Common.h" + +#endif diff --git a/CPP/7zip/Bundles/Alone2/makefile b/CPP/7zip/Bundles/Alone2/makefile new file mode 100644 index 00000000..56de5b2e --- /dev/null +++ b/CPP/7zip/Bundles/Alone2/makefile @@ -0,0 +1,29 @@ +PROG = 7zz.exe +# USE_C_AES = 1 +# USE_C_SHA = 1 +CFLAGS = $(CFLAGS) -DPROG_VARIANT_Z + +!include "../Format7zF/Arc.mak" +!include "../../UI/Console/Console.mak" + +COMMON_OBJS = $(COMMON_OBJS) \ + $O\CommandLineParser.obj \ + $O\ListFileUtils.obj \ + $O\StdInStream.obj \ + $O\StdOutStream.obj \ + +WIN_OBJS = $(WIN_OBJS) \ + $O\DLL.obj \ + $O\ErrorMsg.obj \ + $O\FileLink.obj \ + $O\FileSystem.obj \ + $O\MemoryLock.obj \ + $O\PropVariantConv.obj \ + $O\Registry.obj \ + $O\SystemInfo.obj \ + +7ZIP_COMMON_OBJS = $(7ZIP_COMMON_OBJS) \ + $O\FilePathAutoRename.obj \ + $O\FileStreams.obj \ + +!include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/Alone2/makefile.gcc b/CPP/7zip/Bundles/Alone2/makefile.gcc new file mode 100644 index 00000000..1e7e17f1 --- /dev/null +++ b/CPP/7zip/Bundles/Alone2/makefile.gcc @@ -0,0 +1,100 @@ +PROG = 7zz + +# IS_X64 = 1 +# USE_ASM = 1 +# ST_MODE = 1 + +CONSOLE_VARIANT_FLAGS=-DPROG_VARIANT_Z + +include ../Format7zF/Arc_gcc.mak + +ifdef SystemDrive + +LOCAL_FLAGS_SYS = \ + -D_7ZIP_LARGE_PAGES \ + -DWIN_LONG_PATH \ + -DSUPPORT_DEVICE_FILE \ + +SYS_OBJS = \ + $O/FileSystem.o \ + $O/Registry.o \ + $O/MemoryLock.o \ + $O/DLL.o \ + $O/DllSecur.o \ + $O/resource.o \ + +else + +SYS_OBJS = \ + $O/MyWindows.o \ + +endif + + +LOCAL_FLAGS = \ + $(LOCAL_FLAGS_SYS) \ + $(LOCAL_FLAGS_ST) \ + + +UI_COMMON_OBJS = \ + $O/ArchiveCommandLine.o \ + $O/ArchiveExtractCallback.o \ + $O/ArchiveOpenCallback.o \ + $O/Bench.o \ + $O/DefaultName.o \ + $O/EnumDirItems.o \ + $O/Extract.o \ + $O/ExtractingFilePath.o \ + $O/HashCalc.o \ + $O/LoadCodecs.o \ + $O/OpenArchive.o \ + $O/PropIDUtils.o \ + $O/SetProperties.o \ + $O/SortUtils.o \ + $O/TempFiles.o \ + $O/Update.o \ + $O/UpdateAction.o \ + $O/UpdateCallback.o \ + $O/UpdatePair.o \ + $O/UpdateProduce.o \ + + +CONSOLE_OBJS = \ + $O/BenchCon.o \ + $O/ConsoleClose.o \ + $O/ExtractCallbackConsole.o \ + $O/HashCon.o \ + $O/List.o \ + $O/Main.o \ + $O/MainAr.o \ + $O/OpenCallbackConsole.o \ + $O/PercentPrinter.o \ + $O/UpdateCallbackConsole.o \ + $O/UserInputUtils.o \ + +COMMON_OBJS_2 = \ + $O/CommandLineParser.o \ + $O/ListFileUtils.o \ + $O/StdInStream.o \ + $O/StdOutStream.o \ + +WIN_OBJS_2 = \ + $O/ErrorMsg.o \ + $O/FileLink.o \ + $O/PropVariantConv.o \ + $O/SystemInfo.o \ + +7ZIP_COMMON_OBJS_2 = \ + $O/FilePathAutoRename.o \ + $O/FileStreams.o \ + +OBJS = \ + $(ARC_OBJS) \ + $(SYS_OBJS) \ + $(COMMON_OBJS_2) \ + $(WIN_OBJS_2) \ + $(7ZIP_COMMON_OBJS_2) \ + $(UI_COMMON_OBJS) \ + $(CONSOLE_OBJS) \ + +include ../../7zip_gcc.mak diff --git a/CPP/7zip/Bundles/Alone2/resource.rc b/CPP/7zip/Bundles/Alone2/resource.rc new file mode 100644 index 00000000..af24c175 --- /dev/null +++ b/CPP/7zip/Bundles/Alone2/resource.rc @@ -0,0 +1,7 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_APP("7-Zip Standalone 2 Console", "7zz") + +#ifndef UNDER_CE +1 24 MOVEABLE PURE "../../UI/Console/Console.manifest" +#endif diff --git a/CPP/7zip/Bundles/Alone7z/Alone.dsp b/CPP/7zip/Bundles/Alone7z/Alone.dsp index bb7ca4c9..a46526bf 100644 --- a/CPP/7zip/Bundles/Alone7z/Alone.dsp +++ b/CPP/7zip/Bundles/Alone7z/Alone.dsp @@ -44,7 +44,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /Gr /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /FAc /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gr /MT /W4 /WX /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /FAc /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe @@ -69,7 +69,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /Gr /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gr /MDd /W4 /WX /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe @@ -342,6 +342,14 @@ SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\MyWindows.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyWindows.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File @@ -350,6 +358,10 @@ SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\Sha256Prepare.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\Sha256Reg.cpp # End Source File # Begin Source File @@ -518,6 +530,14 @@ SOURCE=..\..\..\Windows\PropVariantConv.h # End Source File # Begin Source File +SOURCE=..\..\..\Windows\Registry.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Registry.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File @@ -534,6 +554,14 @@ SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File +SOURCE=..\..\..\Windows\SystemInfo.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\SystemInfo.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Windows\Thread.h # End Source File # Begin Source File @@ -1233,34 +1261,6 @@ SOURCE=..\..\PropID.h # PROP Default_Filter "" # Begin Source File -SOURCE=..\..\..\..\C\Sha256.c - -!IF "$(CFG)" == "Alone - Win32 Release" - -# ADD CPP /O2 -# SUBTRACT CPP /YX /Yc /Yu - -!ELSEIF "$(CFG)" == "Alone - Win32 Debug" - -# SUBTRACT CPP /YX /Yc /Yu - -!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" - -# SUBTRACT CPP /YX /Yc /Yu - -!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" - -# SUBTRACT CPP /YX /Yc /Yu - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=..\..\..\..\C\Sha256.h -# End Source File -# Begin Source File - SOURCE=..\..\..\..\C\Xz.c !IF "$(CFG)" == "Alone - Win32 Release" @@ -1457,6 +1457,10 @@ SOURCE=..\..\..\..\C\7zStream.c # End Source File # Begin Source File +SOURCE=..\..\..\..\C\7zTypes.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Aes.c !IF "$(CFG)" == "Alone - Win32 Release" @@ -1862,6 +1866,39 @@ SOURCE=..\..\..\..\C\MtDec.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Sha256.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sha256.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sha256Opt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File @@ -1899,6 +1936,10 @@ SOURCE=..\..\Crypto\MyAes.h # End Source File # Begin Source File +SOURCE=..\..\Crypto\MyAesReg.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Crypto\RandGen.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/Bundles/Alone7z/makefile b/CPP/7zip/Bundles/Alone7z/makefile index 10be3cfb..803277ab 100644 --- a/CPP/7zip/Bundles/Alone7z/makefile +++ b/CPP/7zip/Bundles/Alone7z/makefile @@ -1,6 +1,8 @@ PROG = 7zr.exe -CFLAGS = $(CFLAGS) \ - -DPROG_VARIANT_R \ + +# USE_C_AES = 1 + +CFLAGS = $(CFLAGS) -DPROG_VARIANT_R COMMON_OBJS = \ $O\CommandLineParser.obj \ @@ -33,8 +35,10 @@ WIN_OBJS = \ $O\MemoryLock.obj \ $O\PropVariant.obj \ $O\PropVariantConv.obj \ + $O\Registry.obj \ $O\Synchronization.obj \ $O\System.obj \ + $O\SystemInfo.obj \ $O\TimeUtils.obj \ 7ZIP_COMMON_OBJS = \ @@ -136,7 +140,6 @@ C_OBJS = \ $O\LzmaEnc.obj \ $O\MtCoder.obj \ $O\MtDec.obj \ - $O\Sha256.obj \ $O\Sort.obj \ $O\Threads.obj \ $O\Xz.obj \ @@ -150,5 +153,6 @@ C_OBJS = \ !include "../../Crc.mak" !include "../../Crc64.mak" !include "../../LzmaDec.mak" +!include "../../Sha256.mak" !include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/Alone7z/makefile.gcc b/CPP/7zip/Bundles/Alone7z/makefile.gcc new file mode 100644 index 00000000..b1f69734 --- /dev/null +++ b/CPP/7zip/Bundles/Alone7z/makefile.gcc @@ -0,0 +1,266 @@ +PROG = 7zr + +CONSOLE_VARIANT_FLAGS=-DPROG_VARIANT_R + +# IS_X64 = 1 +# USE_ASM = 1 +# ST_MODE = 1 + +include ../../LzmaDec_gcc.mak + + +LOCAL_FLAGS_ST = +MT_OBJS = + + +ifdef ST_MODE + +LOCAL_FLAGS_ST = -D_7ZIP_ST + +ifdef SystemDrive +MT_OBJS = \ + $O/Threads.o \ + +endif + +else + +MT_OBJS = \ + $O/LzFindMt.o \ + $O/StreamBinder.o \ + $O/Synchronization.o \ + $O/VirtThread.o \ + $O/Threads.o \ + + + +endif + + + +LOCAL_FLAGS_SYS = + +ifdef SystemDrive + +LOCAL_FLAGS_SYS = \ + -D_7ZIP_LARGE_PAGES \ + -DWIN_LONG_PATH \ + -DSUPPORT_DEVICE_FILE \ + +SYS_OBJS = \ + $O/FileSystem.o \ + $O/Registry.o \ + $O/MemoryLock.o \ + $O/DLL.o \ + $O/DllSecur.o \ + $O/resource.o \ + +else + +SYS_OBJS = \ + $O/MyWindows.o \ + +endif + +LOCAL_FLAGS = \ + $(LOCAL_FLAGS_ST) \ + $(LOCAL_FLAGS_SYS) \ + +# -D_LZMA_PROB32 + + +CONSOLE_OBJS = \ + $O/BenchCon.o \ + $O/ConsoleClose.o \ + $O/ExtractCallbackConsole.o \ + $O/HashCon.o \ + $O/List.o \ + $O/Main.o \ + $O/MainAr.o \ + $O/OpenCallbackConsole.o \ + $O/PercentPrinter.o \ + $O/UpdateCallbackConsole.o \ + $O/UserInputUtils.o \ + +UI_COMMON_OBJS = \ + $O/ArchiveCommandLine.o \ + $O/ArchiveExtractCallback.o \ + $O/ArchiveOpenCallback.o \ + $O/Bench.o \ + $O/DefaultName.o \ + $O/EnumDirItems.o \ + $O/Extract.o \ + $O/ExtractingFilePath.o \ + $O/HashCalc.o \ + $O/LoadCodecs.o \ + $O/OpenArchive.o \ + $O/PropIDUtils.o \ + $O/SetProperties.o \ + $O/SortUtils.o \ + $O/TempFiles.o \ + $O/Update.o \ + $O/UpdateAction.o \ + $O/UpdateCallback.o \ + $O/UpdatePair.o \ + $O/UpdateProduce.o \ + +COMMON_OBJS = \ + $O/CommandLineParser.o \ + $O/CRC.o \ + $O/CrcReg.o \ + $O/IntToString.o \ + $O/ListFileUtils.o \ + $O/MyString.o \ + $O/MyVector.o \ + $O/NewHandler.o \ + $O/Sha256Prepare.o \ + $O/Sha256Reg.o \ + $O/StringConvert.o \ + $O/StringToInt.o \ + $O/StdInStream.o \ + $O/StdOutStream.o \ + $O/UTFConvert.o \ + $O/Wildcard.o \ + $O/XzCrc64Init.o \ + $O/XzCrc64Reg.o \ + +WIN_OBJS = \ + $O/ErrorMsg.o \ + $O/FileDir.o \ + $O/FileFind.o \ + $O/FileIO.o \ + $O/FileLink.o \ + $O/FileName.o \ + $O/PropVariant.o \ + $O/PropVariantConv.o \ + $O/System.o \ + $O/SystemInfo.o \ + $O/TimeUtils.o \ + +7ZIP_COMMON_OBJS = \ + $O/CreateCoder.o \ + $O/CWrappers.o \ + $O/FilePathAutoRename.o \ + $O/FileStreams.o \ + $O/InBuffer.o \ + $O/InOutTempBuffer.o \ + $O/FilterCoder.o \ + $O/LimitedStreams.o \ + $O/MethodId.o \ + $O/MethodProps.o \ + $O/OffsetStream.o \ + $O/OutBuffer.o \ + $O/ProgressUtils.o \ + $O/PropId.o \ + $O/StreamObjects.o \ + $O/StreamUtils.o \ + $O/UniqBlocks.o \ + +AR_OBJS = \ + $O/LzmaHandler.o \ + $O/SplitHandler.o \ + $O/XzHandler.o \ + +AR_COMMON_OBJS = \ + $O/CoderMixer2.o \ + $O/DummyOutStream.o \ + $O/HandlerOut.o \ + $O/InStreamWithCRC.o \ + $O/ItemNameUtils.o \ + $O/MultiStream.o \ + $O/OutStreamWithCRC.o \ + $O/ParseProperties.o \ + +7Z_OBJS = \ + $O/7zCompressionMode.o \ + $O/7zDecode.o \ + $O/7zEncode.o \ + $O/7zExtract.o \ + $O/7zFolderInStream.o \ + $O/7zHandler.o \ + $O/7zHandlerOut.o \ + $O/7zHeader.o \ + $O/7zIn.o \ + $O/7zOut.o \ + $O/7zProperties.o \ + $O/7zRegister.o \ + $O/7zSpecStream.o \ + $O/7zUpdate.o \ + +COMPRESS_OBJS = \ + $O/Bcj2Coder.o \ + $O/Bcj2Register.o \ + $O/BcjCoder.o \ + $O/BcjRegister.o \ + $O/BranchMisc.o \ + $O/BranchRegister.o \ + $O/ByteSwap.o \ + $O/CopyCoder.o \ + $O/CopyRegister.o \ + $O/DeltaFilter.o \ + $O/Lzma2Decoder.o \ + $O/Lzma2Encoder.o \ + $O/Lzma2Register.o \ + $O/LzmaDecoder.o \ + $O/LzmaEncoder.o \ + $O/LzmaRegister.o \ + $O/XzDecoder.o \ + $O/XzEncoder.o \ + +CRYPTO_OBJS = \ + $O/7zAes.o \ + $O/7zAesRegister.o \ + $O/MyAes.o \ + $O/MyAesReg.o \ + $O/RandGen.o \ + +C_OBJS = \ + $O/7zStream.o \ + $O/Alloc.o \ + $O/Bcj2.o \ + $O/Bcj2Enc.o \ + $O/Bra.o \ + $O/Bra86.o \ + $O/BraIA64.o \ + $O/CpuArch.o \ + $O/Delta.o \ + $O/LzFind.o \ + $O/Lzma2Dec.o \ + $O/Lzma2DecMt.o \ + $O/Lzma2Enc.o \ + $O/LzmaDec.o \ + $O/LzmaEnc.o \ + $O/MtCoder.o \ + $O/MtDec.o \ + $O/Sha256.o \ + $O/Sha256Opt.o \ + $O/Sort.o \ + $O/Xz.o \ + $O/XzDec.o \ + $O/XzEnc.o \ + $O/XzIn.o \ + $O/XzCrc64.o \ + $O/XzCrc64Opt.o \ + $O/7zCrc.o \ + $O/7zCrcOpt.o \ + $O/Aes.o \ + $O/AesOpt.o \ + + +OBJS = \ + $(LZMA_DEC_OPT_OBJS) \ + $(C_OBJS) \ + $(MT_OBJS) \ + $(SYS_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(COMPRESS_OBJS) \ + $(CRYPTO_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(AR_OBJS) \ + $(AR_COMMON_OBJS) \ + $(7Z_OBJS) \ + $(UI_COMMON_OBJS) \ + $(CONSOLE_OBJS) \ + +include ../../7zip_gcc.mak diff --git a/CPP/7zip/Bundles/Fm/FM.dsp b/CPP/7zip/Bundles/Fm/FM.dsp index 03fbb50e..cccf1be5 100644 --- a/CPP/7zip/Bundles/Fm/FM.dsp +++ b/CPP/7zip/Bundles/Fm/FM.dsp @@ -55,7 +55,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /opt:NOWIN98 +# 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:\Util\7zFM.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "FM - Win32 Debug" @@ -82,7 +82,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Util\7zFM.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "FM - Win32 ReleaseU" @@ -109,7 +109,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /opt:NOWIN98 +# 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:\Util\7zFM.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "FM - Win32 DebugU" @@ -137,7 +137,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /pdbtype:sept +# 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:\Util\7zFM.exe" /pdbtype:sept !ENDIF @@ -579,6 +579,10 @@ SOURCE=..\..\UI\FileManager\PanelSort.cpp SOURCE=..\..\UI\FileManager\PanelSplitFile.cpp # End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\VerCtrl.cpp +# End Source File # End Group # Begin Group "Dialog" @@ -1103,6 +1107,11 @@ SOURCE=..\..\..\..\C\Sha256.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Sha256Opt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Sort.c # SUBTRACT CPP /YX /Yc /Yu # End Source File @@ -1405,6 +1414,14 @@ SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File +SOURCE=..\..\..\Windows\SystemInfo.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\SystemInfo.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Windows\Thread.h # End Source File # Begin Source File @@ -1537,7 +1554,7 @@ SOURCE=..\..\..\Common\Random.h # End Source File # Begin Source File -SOURCE=..\..\..\Common\Sha256Reg.cpp +SOURCE=..\..\..\Common\Sha256Prepare.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/Bundles/Fm/StdAfx.h b/CPP/7zip/Bundles/Fm/StdAfx.h index d2301e48..15fd136e 100644 --- a/CPP/7zip/Bundles/Fm/StdAfx.h +++ b/CPP/7zip/Bundles/Fm/StdAfx.h @@ -9,8 +9,8 @@ #include "../../../Common/Common.h" -#include <commctrl.h> +#include <CommCtrl.h> #include <ShlObj.h> -#include <shlwapi.h> +#include <Shlwapi.h> #endif diff --git a/CPP/7zip/Bundles/Fm/makefile b/CPP/7zip/Bundles/Fm/makefile index 8da34edb..2c80ca1d 100644 --- a/CPP/7zip/Bundles/Fm/makefile +++ b/CPP/7zip/Bundles/Fm/makefile @@ -23,6 +23,7 @@ WIN_OBJS = $(WIN_OBJS) \ $O\PropVariantConv.obj \ $O\Registry.obj \ $O\ResourceString.obj \ + $O\SystemInfo.obj \ $O\Shell.obj \ $O\Window.obj \ diff --git a/CPP/7zip/Bundles/Fm/resource.rc b/CPP/7zip/Bundles/Fm/resource.rc index dd2058a1..6c329588 100644 --- a/CPP/7zip/Bundles/Fm/resource.rc +++ b/CPP/7zip/Bundles/Fm/resource.rc @@ -3,5 +3,5 @@ STRINGTABLE BEGIN - 100 "7z zip rar 001 cab iso xz txz lzma tar cpio bz2 bzip2 tbz2 tbz gz gzip tgz tpz z taz lzh lha rpm deb arj vhd wim swm fat ntfs dmg hfs xar squashfs" + 100 "7z zip rar 001 cab iso xz txz lzma tar cpio bz2 bzip2 tbz2 tbz gz gzip tgz tpz z taz lzh lha rpm deb arj vhd wim swm esd fat ntfs dmg hfs xar squashfs" END diff --git a/CPP/7zip/Bundles/Format7z/makefile b/CPP/7zip/Bundles/Format7z/makefile index 1233d4fc..ca66599a 100644 --- a/CPP/7zip/Bundles/Format7z/makefile +++ b/CPP/7zip/Bundles/Format7z/makefile @@ -132,12 +132,12 @@ C_OBJS = \ $O\Ppmd7.obj \ $O\Ppmd7Dec.obj \ $O\Ppmd7Enc.obj \ - $O\Sha256.obj \ $O\Sort.obj \ $O\Threads.obj \ !include "../../Aes.mak" !include "../../Crc.mak" !include "../../LzmaDec.mak" +!include "../../Sha256.mak" !include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/Format7zExtract/makefile b/CPP/7zip/Bundles/Format7zExtract/makefile index e22faf36..9b4831a9 100644 --- a/CPP/7zip/Bundles/Format7zExtract/makefile +++ b/CPP/7zip/Bundles/Format7zExtract/makefile @@ -104,11 +104,11 @@ C_OBJS = \ $O\MtDec.obj \ $O\Ppmd7.obj \ $O\Ppmd7Dec.obj \ - $O\Sha256.obj \ $O\Threads.obj \ !include "../../Aes.mak" !include "../../Crc.mak" !include "../../LzmaDec.mak" +!include "../../Sha256.mak" !include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/Format7zF/Arc.mak b/CPP/7zip/Bundles/Format7zF/Arc.mak index fd24d5a8..fedce5e0 100644 --- a/CPP/7zip/Bundles/Format7zF/Arc.mak +++ b/CPP/7zip/Bundles/Format7zF/Arc.mak @@ -55,6 +55,7 @@ AR_OBJS = \ $O\ApmHandler.obj \ $O\ArHandler.obj \ $O\ArjHandler.obj \ + $O\Base64Handler.obj \ $O\Bz2Handler.obj \ $O\ComHandler.obj \ $O\CpioHandler.obj \ @@ -271,12 +272,11 @@ C_OBJS = \ $O\MtDec.obj \ $O\Ppmd7.obj \ $O\Ppmd7Dec.obj \ + $O\Ppmd7aDec.obj \ $O\Ppmd7Enc.obj \ $O\Ppmd8.obj \ $O\Ppmd8Dec.obj \ $O\Ppmd8Enc.obj \ - $O\Sha1.obj \ - $O\Sha256.obj \ $O\Sort.obj \ $O\Threads.obj \ $O\Xz.obj \ @@ -288,3 +288,5 @@ C_OBJS = \ !include "../../Crc.mak" !include "../../Crc64.mak" !include "../../LzmaDec.mak" +!include "../../Sha1.mak" +!include "../../Sha256.mak" diff --git a/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak b/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak new file mode 100644 index 00000000..c3dbf349 --- /dev/null +++ b/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak @@ -0,0 +1,345 @@ +include ../../LzmaDec_gcc.mak + +LOCAL_FLAGS_ST = +MT_OBJS = + + +ifdef ST_MODE + +LOCAL_FLAGS_ST = -D_7ZIP_ST + +ifdef SystemDrive +MT_OBJS = \ + $O/Threads.o \ + +endif + +else + +MT_OBJS = \ + $O/LzFindMt.o \ + $O/StreamBinder.o \ + $O/Synchronization.o \ + $O/VirtThread.o \ + $O/MemBlocks.o \ + $O/OutMemStream.o \ + $O/ProgressMt.o \ + $O/Threads.o \ + +endif + + + +COMMON_OBJS = \ + $O/CRC.o \ + $O/CrcReg.o \ + $O/DynLimBuf.o \ + $O/IntToString.o \ + $O/MyMap.o \ + $O/MyString.o \ + $O/MyVector.o \ + $O/MyXml.o \ + $O/NewHandler.o \ + $O/Sha1Prepare.o \ + $O/Sha1Reg.o \ + $O/Sha256Prepare.o \ + $O/Sha256Reg.o \ + $O/StringConvert.o \ + $O/StringToInt.o \ + $O/UTFConvert.o \ + $O/Wildcard.o \ + $O/XzCrc64Init.o \ + $O/XzCrc64Reg.o \ + +WIN_OBJS = \ + $O/FileDir.o \ + $O/FileFind.o \ + $O/FileIO.o \ + $O/FileName.o \ + $O/PropVariant.o \ + $O/PropVariantUtils.o \ + $O/System.o \ + $O/TimeUtils.o \ + +7ZIP_COMMON_OBJS = \ + $O/CreateCoder.o \ + $O/CWrappers.o \ + $O/InBuffer.o \ + $O/InOutTempBuffer.o \ + $O/FilterCoder.o \ + $O/LimitedStreams.o \ + $O/LockedStream.o \ + $O/MethodId.o \ + $O/MethodProps.o \ + $O/OffsetStream.o \ + $O/OutBuffer.o \ + $O/ProgressUtils.o \ + $O/PropId.o \ + $O/StreamObjects.o \ + $O/StreamUtils.o \ + $O/UniqBlocks.o \ + +AR_OBJS = \ + $O/ApmHandler.o \ + $O/ArHandler.o \ + $O/ArjHandler.o \ + $O/Base64Handler.o \ + $O/Bz2Handler.o \ + $O/ComHandler.o \ + $O/CpioHandler.o \ + $O/CramfsHandler.o \ + $O/DeflateProps.o \ + $O/DmgHandler.o \ + $O/ElfHandler.o \ + $O/ExtHandler.o \ + $O/FatHandler.o \ + $O/FlvHandler.o \ + $O/GzHandler.o \ + $O/GptHandler.o \ + $O/HandlerCont.o \ + $O/HfsHandler.o \ + $O/IhexHandler.o \ + $O/LzhHandler.o \ + $O/LzmaHandler.o \ + $O/MachoHandler.o \ + $O/MbrHandler.o \ + $O/MslzHandler.o \ + $O/MubHandler.o \ + $O/NtfsHandler.o \ + $O/PeHandler.o \ + $O/PpmdHandler.o \ + $O/QcowHandler.o \ + $O/RpmHandler.o \ + $O/SplitHandler.o \ + $O/SquashfsHandler.o \ + $O/SwfHandler.o \ + $O/UefiHandler.o \ + $O/VdiHandler.o \ + $O/VhdHandler.o \ + $O/VmdkHandler.o \ + $O/XarHandler.o \ + $O/XzHandler.o \ + $O/ZHandler.o \ + +AR_COMMON_OBJS = \ + $O/CoderMixer2.o \ + $O/DummyOutStream.o \ + $O/FindSignature.o \ + $O/InStreamWithCRC.o \ + $O/ItemNameUtils.o \ + $O/MultiStream.o \ + $O/OutStreamWithCRC.o \ + $O/OutStreamWithSha1.o \ + $O/HandlerOut.o \ + $O/ParseProperties.o \ + + +7Z_OBJS = \ + $O/7zCompressionMode.o \ + $O/7zDecode.o \ + $O/7zEncode.o \ + $O/7zExtract.o \ + $O/7zFolderInStream.o \ + $O/7zHandler.o \ + $O/7zHandlerOut.o \ + $O/7zHeader.o \ + $O/7zIn.o \ + $O/7zOut.o \ + $O/7zProperties.o \ + $O/7zSpecStream.o \ + $O/7zUpdate.o \ + $O/7zRegister.o \ + +CAB_OBJS = \ + $O/CabBlockInStream.o \ + $O/CabHandler.o \ + $O/CabHeader.o \ + $O/CabIn.o \ + $O/CabRegister.o \ + +CHM_OBJS = \ + $O/ChmHandler.o \ + $O/ChmIn.o \ + +ISO_OBJS = \ + $O/IsoHandler.o \ + $O/IsoHeader.o \ + $O/IsoIn.o \ + $O/IsoRegister.o \ + +NSIS_OBJS = \ + $O/NsisDecode.o \ + $O/NsisHandler.o \ + $O/NsisIn.o \ + $O/NsisRegister.o \ + +RAR_OBJS = \ + $O/RarHandler.o \ + $O/Rar5Handler.o \ + +TAR_OBJS = \ + $O/TarHandler.o \ + $O/TarHandlerOut.o \ + $O/TarHeader.o \ + $O/TarIn.o \ + $O/TarOut.o \ + $O/TarUpdate.o \ + $O/TarRegister.o \ + +UDF_OBJS = \ + $O/UdfHandler.o \ + $O/UdfIn.o \ + +WIM_OBJS = \ + $O/WimHandler.o \ + $O/WimHandlerOut.o \ + $O/WimIn.o \ + $O/WimRegister.o \ + +ZIP_OBJS = \ + $O/ZipAddCommon.o \ + $O/ZipHandler.o \ + $O/ZipHandlerOut.o \ + $O/ZipIn.o \ + $O/ZipItem.o \ + $O/ZipOut.o \ + $O/ZipUpdate.o \ + $O/ZipRegister.o \ + +COMPRESS_OBJS = \ + $O/Bcj2Coder.o \ + $O/Bcj2Register.o \ + $O/BcjCoder.o \ + $O/BcjRegister.o \ + $O/BitlDecoder.o \ + $O/BranchMisc.o \ + $O/BranchRegister.o \ + $O/ByteSwap.o \ + $O/BZip2Crc.o \ + $O/BZip2Decoder.o \ + $O/BZip2Encoder.o \ + $O/BZip2Register.o \ + $O/CopyCoder.o \ + $O/CopyRegister.o \ + $O/Deflate64Register.o \ + $O/DeflateDecoder.o \ + $O/DeflateEncoder.o \ + $O/DeflateRegister.o \ + $O/DeltaFilter.o \ + $O/ImplodeDecoder.o \ + $O/LzfseDecoder.o \ + $O/LzhDecoder.o \ + $O/Lzma2Decoder.o \ + $O/Lzma2Encoder.o \ + $O/Lzma2Register.o \ + $O/LzmaDecoder.o \ + $O/LzmaEncoder.o \ + $O/LzmaRegister.o \ + $O/LzmsDecoder.o \ + $O/LzOutWindow.o \ + $O/LzxDecoder.o \ + $O/PpmdDecoder.o \ + $O/PpmdEncoder.o \ + $O/PpmdRegister.o \ + $O/PpmdZip.o \ + $O/QuantumDecoder.o \ + $O/Rar1Decoder.o \ + $O/Rar2Decoder.o \ + $O/Rar3Decoder.o \ + $O/Rar3Vm.o \ + $O/Rar5Decoder.o \ + $O/RarCodecsRegister.o \ + $O/ShrinkDecoder.o \ + $O/XpressDecoder.o \ + $O/XzDecoder.o \ + $O/XzEncoder.o \ + $O/ZlibDecoder.o \ + $O/ZlibEncoder.o \ + $O/ZDecoder.o \ + + +CRYPTO_OBJS = \ + $O/7zAes.o \ + $O/7zAesRegister.o \ + $O/HmacSha1.o \ + $O/HmacSha256.o \ + $O/MyAes.o \ + $O/MyAesReg.o \ + $O/Pbkdf2HmacSha1.o \ + $O/RandGen.o \ + $O/Rar20Crypto.o \ + $O/Rar5Aes.o \ + $O/RarAes.o \ + $O/WzAes.o \ + $O/ZipCrypto.o \ + $O/ZipStrong.o \ + + +C_OBJS = \ + $O/7zBuf2.o \ + $O/7zStream.o \ + $O/Alloc.o \ + $O/Bcj2.o \ + $O/Bcj2Enc.o \ + $O/Blake2s.o \ + $O/Bra.o \ + $O/Bra86.o \ + $O/BraIA64.o \ + $O/BwtSort.o \ + $O/CpuArch.o \ + $O/Delta.o \ + $O/HuffEnc.o \ + $O/LzFind.o \ + $O/Lzma2Dec.o \ + $O/Lzma2DecMt.o \ + $O/Lzma2Enc.o \ + $O/LzmaDec.o \ + $O/LzmaEnc.o \ + $O/MtCoder.o \ + $O/MtDec.o \ + $O/Ppmd7.o \ + $O/Ppmd7Dec.o \ + $O/Ppmd7aDec.o \ + $O/Ppmd7Enc.o \ + $O/Ppmd8.o \ + $O/Ppmd8Dec.o \ + $O/Ppmd8Enc.o \ + $O/Sort.o \ + $O/Xz.o \ + $O/XzDec.o \ + $O/XzEnc.o \ + $O/XzIn.o \ + $O/XzCrc64.o \ + $O/XzCrc64Opt.o \ + $O/7zCrc.o \ + $O/7zCrcOpt.o \ + $O/Aes.o \ + $O/AesOpt.o \ + $O/Sha256.o \ + $O/Sha256Opt.o \ + $O/Sha1.o \ + $O/Sha1Opt.o \ + +ARC_OBJS = \ + $(LZMA_DEC_OPT_OBJS) \ + $(C_OBJS) \ + $(MT_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(AR_OBJS) \ + $(AR_COMMON_OBJS) \ + $(7Z_OBJS) \ + $(CAB_OBJS) \ + $(CHM_OBJS) \ + $(COM_OBJS) \ + $(ISO_OBJS) \ + $(NSIS_OBJS) \ + $(RAR_OBJS) \ + $(TAR_OBJS) \ + $(UDF_OBJS) \ + $(WIM_OBJS) \ + $(ZIP_OBJS) \ + $(COMPRESS_OBJS) \ + $(CRYPTO_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp index 3e202fe7..67883ebc 100644 --- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp +++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp @@ -53,7 +53,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-Zip\7z.dll" /opt:NOWIN98 +# 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\7z.dll" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none /debug !ELSEIF "$(CFG)" == "7z - Win32 Debug" @@ -80,7 +80,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-Zip\7z.dll" /pdbtype:sept /ignore:4033 +# 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\7z.dll" /pdbtype:sept /ignore:4033 # SUBTRACT LINK32 /pdb:none !ENDIF @@ -347,10 +347,18 @@ SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\Sha1Prepare.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\Sha1Reg.cpp # End Source File # Begin Source File +SOURCE=..\..\..\Common\Sha256Prepare.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\Sha256Reg.cpp # End Source File # Begin Source File @@ -1060,6 +1068,16 @@ SOURCE=..\..\Compress\ZDecoder.h # Begin Source File SOURCE=..\..\Crypto\7zAes.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + # End Source File # Begin Source File @@ -1068,6 +1086,16 @@ SOURCE=..\..\Crypto\7zAes.h # Begin Source File SOURCE=..\..\Crypto\7zAesRegister.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + # End Source File # Begin Source File @@ -1090,6 +1118,16 @@ SOURCE=..\..\Crypto\HmacSha1.h # Begin Source File SOURCE=..\..\Crypto\HmacSha256.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + # End Source File # Begin Source File @@ -1098,6 +1136,16 @@ SOURCE=..\..\Crypto\HmacSha256.h # Begin Source File SOURCE=..\..\Crypto\MyAes.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + # End Source File # Begin Source File @@ -1106,6 +1154,16 @@ SOURCE=..\..\Crypto\MyAes.h # Begin Source File SOURCE=..\..\Crypto\MyAesReg.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + # End Source File # Begin Source File @@ -1164,6 +1222,16 @@ SOURCE=..\..\Crypto\Rar20Crypto.h # Begin Source File SOURCE=..\..\Crypto\Rar5Aes.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + # End Source File # Begin Source File @@ -1172,6 +1240,16 @@ SOURCE=..\..\Crypto\Rar5Aes.h # Begin Source File SOURCE=..\..\Crypto\RarAes.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + # End Source File # Begin Source File @@ -1184,6 +1262,16 @@ SOURCE=..\..\Crypto\Sha1Cls.h # Begin Source File SOURCE=..\..\Crypto\WzAes.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + # End Source File # Begin Source File @@ -1938,6 +2026,22 @@ SOURCE=..\..\..\..\C\Ppmd7.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Ppmd7aDec.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Ppmd7Dec.c !IF "$(CFG)" == "7z - Win32 Release" @@ -2651,6 +2755,10 @@ SOURCE=..\..\Archive\ArjHandler.cpp # End Source File # Begin Source File +SOURCE=..\..\Archive\Base64Handler.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Archive\Bz2Handler.cpp # End Source File # Begin Source File @@ -3003,6 +3111,68 @@ InputName=AesOpt !ENDIF # End Source File +# Begin Source File + +SOURCE=..\..\..\..\Asm\x86\Sha1Opt.asm + +!IF "$(CFG)" == "7z - Win32 Release" + +# Begin Custom Build +OutDir=.\Release +InputPath=..\..\..\..\Asm\x86\Sha1Opt.asm +InputName=Sha1Opt + +"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml.exe -c -Fo$(OutDir)\$(InputName).obj $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# Begin Custom Build +OutDir=.\Debug +InputPath=..\..\..\..\Asm\x86\Sha1Opt.asm +InputName=Sha1Opt + +"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml.exe -c -omf -Fo$(OutDir)\$(InputName).obj $(InputPath) + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\Asm\x86\Sha256Opt.asm + +!IF "$(CFG)" == "7z - Win32 Release" + +# Begin Custom Build +OutDir=.\Release +InputPath=..\..\..\..\Asm\x86\Sha256Opt.asm +InputName=Sha256Opt + +"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml.exe -c -Fo$(OutDir)\$(InputName).obj $(InputPath) + +# End Custom Build + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# Begin Custom Build +OutDir=.\Debug +InputPath=..\..\..\..\Asm\x86\Sha256Opt.asm +InputName=Sha256Opt + +"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + ml.exe -c -omf -Fo$(OutDir)\$(InputName).obj $(InputPath) + +# End Custom Build + +!ENDIF + +# End Source File # End Group # End Target # End Project diff --git a/CPP/7zip/Bundles/Format7zF/makefile.gcc b/CPP/7zip/Bundles/Format7zF/makefile.gcc new file mode 100644 index 00000000..1953dd55 --- /dev/null +++ b/CPP/7zip/Bundles/Format7zF/makefile.gcc @@ -0,0 +1,45 @@ +PROG = 7z +DEF_FILE = ../../Archive/Archive2.def + +# IS_X64 = 1 +# USE_ASM = 1 +# ST_MODE = 1 + +include Arc_gcc.mak + +ifdef SystemDrive + +LOCAL_FLAGS_WIN = \ + -D_7ZIP_LARGE_PAGES \ + $(LOCAL_FLAGS_ST) \ + +SYS_OBJS = \ + $O/resource.o \ + +else + +SYS_OBJS = \ + $O/MyWindows.o \ + +endif + +LOCAL_FLAGS = \ + -DEXTERNAL_CODECS \ + $(LOCAL_FLAGS_WIN) \ + $(LOCAL_FLAGS_ST) \ + + +COMPRESS_OBJS_2 = \ + $O/CodecExports.o \ + +AR_OBJS_2 = \ + $O/ArchiveExports.o \ + $O/DllExports2.o \ + +OBJS = \ + $(ARC_OBJS) \ + $(AR_OBJS_2) \ + $(COMPRESS_OBJS_2) \ + $(SYS_OBJS) \ + +include ../../7zip_gcc.mak diff --git a/CPP/7zip/Bundles/Format7zF/resource.rc b/CPP/7zip/Bundles/Format7zF/resource.rc index 705814f5..5330a415 100644 --- a/CPP/7zip/Bundles/Format7zF/resource.rc +++ b/CPP/7zip/Bundles/Format7zF/resource.rc @@ -33,5 +33,5 @@ MY_VERSION_INFO_DLL("7z Plugin" , "7z") STRINGTABLE BEGIN - 100 "7z:0 zip:1 rar:3 001:9 cab:7 iso:8 xz:23 txz:23 lzma:16 tar:13 cpio:12 bz2:2 bzip2:2 tbz2:2 tbz:2 gz:14 gzip:14 tgz:14 tpz:14 z:5 taz:5 lzh:6 lha:6 rpm:10 deb:11 arj:4 vhd:20 wim:15 swm:15 fat:21 ntfs:22 dmg:17 hfs:18 xar:19 squashfs:24" + 100 "7z:0 zip:1 rar:3 001:9 cab:7 iso:8 xz:23 txz:23 lzma:16 tar:13 cpio:12 bz2:2 bzip2:2 tbz2:2 tbz:2 gz:14 gzip:14 tgz:14 tpz:14 z:5 taz:5 lzh:6 lha:6 rpm:10 deb:11 arj:4 vhd:20 wim:15 swm:15 esd:15 fat:21 ntfs:22 dmg:17 hfs:18 xar:19 squashfs:24" END diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp index 62d3a84c..a08d9c09 100644 --- a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp +++ b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp @@ -2,7 +2,7 @@ #include "StdAfx.h" -#include <stdio.h> +// #include <stdio.h> #include "../../../../C/CpuArch.h" @@ -71,7 +71,7 @@ static const char * const kHelpString = " -so : write data to stdout\n"; -static const char * const kCantAllocate = "Can not allocate memory"; +static const char * const kCantAllocate = "Cannot allocate memory"; static const char * const kReadError = "Read error"; static const char * const kWriteError = "Write error"; @@ -99,24 +99,32 @@ enum Enum }; } +#define SWFRM_3(t, mu, mi) t, mu, mi, NULL + +#define SWFRM_1(t) SWFRM_3(t, false, 0) +#define SWFRM_SIMPLE SWFRM_1(NSwitchType::kSimple) +#define SWFRM_STRING SWFRM_1(NSwitchType::kString) + +#define SWFRM_STRING_SINGL(mi) SWFRM_3(NSwitchType::kString, false, mi) + static const CSwitchForm kSwitchForms[] = { - { "?", NSwitchType::kSimple, false }, - { "H", NSwitchType::kSimple, false }, - { "MM", NSwitchType::kString, false, 1 }, - { "X", NSwitchType::kString, false, 1 }, - { "A", NSwitchType::kString, false, 1 }, - { "D", NSwitchType::kString, false, 1 }, - { "FB", NSwitchType::kString, false, 1 }, - { "MC", NSwitchType::kString, false, 1 }, - { "LC", NSwitchType::kString, false, 1 }, - { "LP", NSwitchType::kString, false, 1 }, - { "PB", NSwitchType::kString, false, 1 }, - { "MF", NSwitchType::kString, false, 1 }, - { "MT", NSwitchType::kString, false, 0 }, - { "EOS", NSwitchType::kSimple, false }, - { "SI", NSwitchType::kSimple, false }, - { "SO", NSwitchType::kSimple, false }, + { "?", SWFRM_SIMPLE }, + { "H", SWFRM_SIMPLE }, + { "MM", SWFRM_STRING_SINGL(1) }, + { "X", SWFRM_STRING_SINGL(1) }, + { "A", SWFRM_STRING_SINGL(1) }, + { "D", SWFRM_STRING_SINGL(1) }, + { "FB", SWFRM_STRING_SINGL(1) }, + { "MC", SWFRM_STRING_SINGL(1) }, + { "LC", SWFRM_STRING_SINGL(1) }, + { "LP", SWFRM_STRING_SINGL(1) }, + { "PB", SWFRM_STRING_SINGL(1) }, + { "MF", SWFRM_STRING_SINGL(1) }, + { "MT", SWFRM_STRING }, + { "EOS", SWFRM_SIMPLE }, + { "SI", SWFRM_SIMPLE }, + { "SO", SWFRM_SIMPLE }, { "F86", NSwitchType::kChar, false, 0, "+" } }; @@ -264,6 +272,7 @@ STDMETHODIMP CProgressPrint::SetRatioInfo(const UInt64 *inSize, const UInt64 *ou } +MY_ATTR_NORETURN static void IncorrectCommand() { throw "Incorrect command"; @@ -314,7 +323,9 @@ static int Error_HRESULT(const char *s, HRESULT res) return 1; } +#if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) #define NT_CHECK_FAIL_ACTION PrintError("Unsupported Windows version"); return 1; +#endif static void AddProp(CObjectVector<CProperty> &props2, const char *name, const wchar_t *val) { @@ -474,7 +485,7 @@ static int main2(int numArgs, const char *args[]) inStream = inStreamSpec; if (!inStreamSpec->Open(us2fs(inputName))) { - PrintError2("can not open input file", inputName); + PrintError2("Cannot open input file", inputName); return 1; } } @@ -494,7 +505,7 @@ static int main2(int numArgs, const char *args[]) outStream = outStreamSpec; if (!outStreamSpec->Create(us2fs(outputName), true)) { - PrintError2("can not open output file", outputName); + PrintError2("Cannot open output file", outputName); return 1; } } @@ -505,7 +516,7 @@ static int main2(int numArgs, const char *args[]) if (inStreamSpec) { if (!inStreamSpec->File.GetLength(fileSize)) - throw "Can not get file length"; + throw "Cannot get file length"; fileSizeDefined = true; if (!stdOutMode) Print_Size("Input size: ", fileSize); @@ -532,7 +543,7 @@ static int main2(int numArgs, const char *args[]) You can use xz format instead, if you want to use filters */ if (parser[NKey::kEOS].ThereIs || stdInMode) - throw "Can not use stdin in this mode"; + throw "Cannot use stdin in this mode"; size_t inSize = (size_t)fileSize; @@ -549,7 +560,7 @@ static int main2(int numArgs, const char *args[]) } if (ReadStream_FAIL(inStream, inBuffer, inSize) != S_OK) - throw "Can not read"; + throw "Cannot read"; Byte *outBuffer = NULL; size_t outSize; diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp index f8267a11..907b23e0 100644 --- a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp +++ b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp @@ -140,6 +140,14 @@ SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File +SOURCE=..\..\..\Windows\Registry.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Registry.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File @@ -156,6 +164,14 @@ SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File +SOURCE=..\..\..\Windows\SystemInfo.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\SystemInfo.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Windows\Thread.h # End Source File # End Group diff --git a/CPP/7zip/Bundles/LzmaCon/makefile b/CPP/7zip/Bundles/LzmaCon/makefile index 000ca446..e87becc4 100644 --- a/CPP/7zip/Bundles/LzmaCon/makefile +++ b/CPP/7zip/Bundles/LzmaCon/makefile @@ -15,23 +15,24 @@ COMMON_OBJS = \ $O\CrcReg.obj \ $O\IntToString.obj \ $O\MyString.obj \ + $O\MyVector.obj \ $O\NewHandler.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ - $O\MyVector.obj WIN_OBJS = \ $O\FileIO.obj \ $O\PropVariant.obj \ - $O\System.obj + $O\Registry.obj \ + $O\System.obj \ + $O\SystemInfo.obj \ 7ZIP_COMMON_OBJS = \ - $O\CWrappers.obj \ $O\CreateCoder.obj \ + $O\CWrappers.obj \ $O\FileStreams.obj \ $O\FilterCoder.obj \ $O\MethodProps.obj \ - $O\OutBuffer.obj \ $O\StreamUtils.obj \ UI_COMMON_OBJS = \ diff --git a/CPP/7zip/Bundles/LzmaCon/makefile.gcc b/CPP/7zip/Bundles/LzmaCon/makefile.gcc index 97fe4508..f9ccfce4 100644 --- a/CPP/7zip/Bundles/LzmaCon/makefile.gcc +++ b/CPP/7zip/Bundles/LzmaCon/makefile.gcc @@ -1,195 +1,113 @@ PROG = lzma -CXX = g++ -O2 -# -Wall -Werror -Wno-delete-non-virtual-dtor -CXX_C = gcc -O2 -Wall -Werror -ifdef SystemDrive -IS_MINGW = 1 -endif +# IS_X64 = 1 +# USE_ASM = 1 +# ST_MODE = 1 + +include ../../LzmaDec_gcc.mak -ifdef IS_MINGW +LOCAL_FLAGS_ST = +MT_OBJS = -RM = del -CFLAGS = -c -LIB2 = -loleaut32 -luuid -LDFLAGS = -s -FILE_IO =FileIO -FILE_IO_2 =Windows/$(FILE_IO) +ifdef ST_MODE -MT_FILES = \ - LzFindMt.o \ - Threads.o \ +LOCAL_FLAGS_ST = -D_7ZIP_ST else -RM = rm -f -CFLAGS = -c -D_7ZIP_ST +MT_OBJS = \ + $O/LzFindMt.o \ + $O/Synchronization.o \ + $O/Threads.o \ -FILE_IO =C_FileIO -FILE_IO_2 =Common/$(FILE_IO) endif -OBJS = \ - $(MT_FILES) \ - $(FILE_IO).o \ - LzmaAlone.o \ - Bench.o \ - BenchCon.o \ - ConsoleClose.o \ - LzmaDecoder.o \ - LzmaEncoder.o \ - LzmaRegister.o \ - CreateCoder.o \ - CWrappers.o \ - FileStreams.o \ - FilterCoder.o \ - MethodProps.o \ - StreamUtils.o \ - CommandLineParser.o \ - CRC.o \ - CrcReg.o \ - IntToString.o \ - MyString.o \ - MyVector.o \ - MyWindows.o \ - StringConvert.o \ - StringToInt.o \ - PropVariant.o \ - System.o \ - 7zCrc.o \ - 7zCrcOpt.o \ - Alloc.o \ - Bra86.o \ - CpuArch.o \ - LzFind.o \ - LzmaDec.o \ - LzmaEnc.o \ - Lzma86Dec.o \ - Lzma86Enc.o \ - - -all: $(PROG) - -$(PROG): $(OBJS) - $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB2) - -LzmaAlone.o: LzmaAlone.cpp - $(CXX) $(CFLAGS) LzmaAlone.cpp - -Bench.o: ../../UI/Common/Bench.cpp - $(CXX) $(CFLAGS) ../../UI/Common/Bench.cpp - -BenchCon.o: ../../UI/Console/BenchCon.cpp - $(CXX) $(CFLAGS) ../../UI/Console/BenchCon.cpp - -ConsoleClose.o: ../../UI/Console/ConsoleClose.cpp - $(CXX) $(CFLAGS) ../../UI/Console/ConsoleClose.cpp - -LzmaDecoder.o: ../../Compress/LzmaDecoder.cpp - $(CXX) $(CFLAGS) ../../Compress/LzmaDecoder.cpp - -LzmaEncoder.o: ../../Compress/LzmaEncoder.cpp - $(CXX) $(CFLAGS) ../../Compress/LzmaEncoder.cpp - -LzmaRegister.o: ../../Compress/LzmaRegister.cpp - $(CXX) $(CFLAGS) ../../Compress/LzmaRegister.cpp - -CreateCoder.o: ../../Common/CreateCoder.cpp - $(CXX) $(CFLAGS) ../../Common/CreateCoder.cpp - -CWrappers.o: ../../Common/CWrappers.cpp - $(CXX) $(CFLAGS) ../../Common/CWrappers.cpp - -FileStreams.o: ../../Common/FileStreams.cpp - $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp - -FilterCoder.o: ../../Common/FilterCoder.cpp - $(CXX) $(CFLAGS) ../../Common/FilterCoder.cpp - -MethodProps.o: ../../Common/MethodProps.cpp - $(CXX) $(CFLAGS) ../../Common/MethodProps.cpp - -StreamUtils.o: ../../Common/StreamUtils.cpp - $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp - -$(FILE_IO).o: ../../../$(FILE_IO_2).cpp - $(CXX) $(CFLAGS) ../../../$(FILE_IO_2).cpp +LOCAL_FLAGS_SYS = -CommandLineParser.o: ../../../Common/CommandLineParser.cpp - $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp - -CRC.o: ../../../Common/CRC.cpp - $(CXX) $(CFLAGS) ../../../Common/CRC.cpp - -CrcReg.o: ../../../Common/CrcReg.cpp - $(CXX) $(CFLAGS) ../../../Common/CrcReg.cpp - -IntToString.o: ../../../Common/IntToString.cpp - $(CXX) $(CFLAGS) ../../../Common/IntToString.cpp - -MyString.o: ../../../Common/MyString.cpp - $(CXX) $(CFLAGS) ../../../Common/MyString.cpp - -MyVector.o: ../../../Common/MyVector.cpp - $(CXX) $(CFLAGS) ../../../Common/MyVector.cpp - -MyWindows.o: ../../../Common/MyWindows.cpp - $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp - -StringConvert.o: ../../../Common/StringConvert.cpp - $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp - -StringToInt.o: ../../../Common/StringToInt.cpp - $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp - -PropVariant.o: ../../../Windows/PropVariant.cpp - $(CXX) $(CFLAGS) ../../../Windows/PropVariant.cpp - -System.o: ../../../Windows/System.cpp - $(CXX) $(CFLAGS) ../../../Windows/System.cpp - -7zCrc.o: ../../../../C/7zCrc.c - $(CXX_C) $(CFLAGS) ../../../../C/7zCrc.c - -7zCrcOpt.o: ../../../../C/7zCrcOpt.c - $(CXX_C) $(CFLAGS) ../../../../C/7zCrcOpt.c - -Alloc.o: ../../../../C/Alloc.c - $(CXX_C) $(CFLAGS) ../../../../C/Alloc.c - -Bra86.o: ../../../../C/Bra86.c - $(CXX_C) $(CFLAGS) ../../../../C/Bra86.c +ifdef SystemDrive -CpuArch.o: ../../../../C/CpuArch.c - $(CXX_C) $(CFLAGS) ../../../../C/CpuArch.c +SYS_OBJS = \ + $O/Registry.o \ + $O/resource.o \ -LzFind.o: ../../../../C/LzFind.c - $(CXX_C) $(CFLAGS) ../../../../C/LzFind.c +else -ifdef MT_FILES -LzFindMt.o: ../../../../C/LzFindMt.c - $(CXX_C) $(CFLAGS) ../../../../C/LzFindMt.c +SYS_OBJS = \ + $O/FileDir.o \ + $O/FileFind.o \ + $O/FileName.o \ + $O/MyWindows.o \ + $O/TimeUtils.o \ -Threads.o: ../../../../C/Threads.c - $(CXX_C) $(CFLAGS) ../../../../C/Threads.c endif -LzmaDec.o: ../../../../C/LzmaDec.c - $(CXX_C) $(CFLAGS) ../../../../C/LzmaDec.c - -LzmaEnc.o: ../../../../C/LzmaEnc.c - $(CXX_C) $(CFLAGS) ../../../../C/LzmaEnc.c - -Lzma86Dec.o: ../../../../C/Lzma86Dec.c - $(CXX_C) $(CFLAGS) ../../../../C/Lzma86Dec.c +LOCAL_FLAGS = \ + $(LOCAL_FLAGS_ST) \ + + +COMMON_OBJS = \ + $O/CommandLineParser.o \ + $O/CRC.o \ + $O/CrcReg.o \ + $O/IntToString.o \ + $O/MyString.o \ + $O/MyVector.o \ + $O/NewHandler.o \ + $O/StringConvert.o \ + $O/StringToInt.o \ + $O/UTFConvert.o \ + +WIN_OBJS = \ + $O/FileIO.o \ + $O/PropVariant.o \ + $O/System.o \ + $O/SystemInfo.o \ + +COMPRESS_OBJS = \ + $O/LzmaDecoder.o \ + $O/LzmaEncoder.o \ + $O/LzmaRegister.o \ + +CONSOLE_OBJS = \ + $O/BenchCon.o \ + $O/ConsoleClose.o \ + +7ZIP_COMMON_OBJS = \ + $O/CreateCoder.o \ + $O/CWrappers.o \ + $O/FileStreams.o \ + $O/FilterCoder.o \ + $O/MethodProps.o \ + $O/StreamUtils.o \ + +C_OBJS = \ + $O/7zCrc.o \ + $O/7zCrcOpt.o \ + $O/Alloc.o \ + $O/Bra86.o \ + $O/CpuArch.o \ + $O/LzFind.o \ + $O/LzmaDec.o \ + $O/LzmaEnc.o \ + $O/Lzma86Dec.o \ + $O/Lzma86Enc.o \ -Lzma86Enc.o: ../../../../C/Lzma86Enc.c - $(CXX_C) $(CFLAGS) ../../../../C/Lzma86Enc.c - -clean: - -$(RM) $(PROG) $(OBJS) +OBJS = \ + $(LZMA_DEC_OPT_OBJS) \ + $(C_OBJS) \ + $(MT_OBJS) \ + $(SYS_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(COMPRESS_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(CONSOLE_OBJS) \ + $O/LzmaAlone.o \ + $O/Bench.o \ + +include ../../7zip_gcc.mak diff --git a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp index 0f032d81..87e27c4f 100644 --- a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp +++ b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp @@ -481,6 +481,10 @@ SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\Sha256Prepare.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\StdInStream.cpp # End Source File # Begin Source File @@ -888,6 +892,11 @@ SOURCE=..\..\..\..\C\Sha256.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Sha256Opt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File diff --git a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp index 3209a01c..b149889b 100644 --- a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp +++ b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp @@ -13,8 +13,10 @@ #ifdef _WIN32 #include "../../../Windows/DLL.h" -#include "../../../Windows/FileDir.h" +#else +#include "../../../Common/StringConvert.h" #endif +#include "../../../Windows/FileDir.h" #include "../../../Windows/FileName.h" #include "../../UI/Common/ExitCode.h" @@ -82,14 +84,20 @@ static const char kImmediateNameID = '!'; static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be */ + +#define SWFRM_3(t, mu, mi) t, mu, mi, NULL +#define SWFRM_1(t) SWFRM_3(t, false, 0) +#define SWFRM_SIMPLE SWFRM_1(NSwitchType::kSimple) +#define SWFRM_STRING_SINGL(mi) SWFRM_3(NSwitchType::kString, false, mi) + static const CSwitchForm kSwitchForms[kNumSwitches] = { - { "?", NSwitchType::kSimple }, - { "H", NSwitchType::kSimple }, - { "BD", NSwitchType::kSimple }, - { "Y", NSwitchType::kSimple }, - { "P", NSwitchType::kString, false, 1 }, - { "O", NSwitchType::kString, false, 1 }, + { "?", SWFRM_SIMPLE }, + { "H", SWFRM_SIMPLE }, + { "BD", SWFRM_SIMPLE }, + { "Y", SWFRM_SIMPLE }, + { "P", SWFRM_STRING_SINGL(1) }, + { "O", SWFRM_STRING_SINGL(1) }, }; static const int kNumCommandForms = 3; @@ -103,7 +111,6 @@ static const NRecursedType::EEnum kCommandRecursedDefault[kNumCommandForms] = // static const bool kAddRecursedDefault = false; static const char * const kUniversalWildcard = "*"; -static const int kCommandIndex = 0; static const char * const kHelpString = "\nUsage: 7zSFX [<command>] [<switches>...] [<file_name>...]\n" @@ -152,7 +159,7 @@ struct CArchiveCommand NRecursedType::EEnum DefaultRecursedType() const; }; -bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) +static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) { UString s = commandString; s.MakeLower_Ascii(); @@ -172,17 +179,19 @@ NRecursedType::EEnum CArchiveCommand::DefaultRecursedType() const return kCommandRecursedDefault[CommandType]; } -void PrintHelp(void) +static void PrintHelp(void) { g_StdOut << kHelpString; } +MY_ATTR_NORETURN static void ShowMessageAndThrowException(const char *message, NExitCode::EEnum code) { g_StdOut << message << endl; throw code; } +MY_ATTR_NORETURN static void PrintHelpAndExit() // yyy { PrintHelp(); @@ -218,7 +227,7 @@ static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor, return true; } -void AddCommandLineWildcardToCensor(NWildcard::CCensor &wildcardCensor, +static void AddCommandLineWildcardToCensor(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum type) { if (!AddNameToCensor(wildcardCensor, name, include, type)) @@ -227,7 +236,7 @@ void AddCommandLineWildcardToCensor(NWildcard::CCensor &wildcardCensor, #ifndef _WIN32 -static void GetArguments(int numArgs, const char *args[], UStringVector &parts) +static void GetArguments(int numArgs, char *args[], UStringVector &parts) { parts.Clear(); for (int i = 0; i < numArgs; i++) @@ -238,9 +247,15 @@ static void GetArguments(int numArgs, const char *args[], UStringVector &parts) } #endif + int Main2( #ifndef _WIN32 - int numArgs, const char *args[] + int numArgs, char *args[] + #endif +); +int Main2( + #ifndef _WIN32 + int numArgs, char *args[] #endif ) { @@ -253,6 +268,10 @@ int Main2( SetFileApisToOEM(); #endif + #ifdef ENV_HAVE_LOCALE + MY_SetLocale(); + #endif + g_StdOut << kCopyrightString; UStringVector commandStrings; @@ -277,7 +296,10 @@ int Main2( #else - UString arcPath = commandStrings.Front(); + if (commandStrings.IsEmpty()) + return NExitCode::kFatalError; + + const FString arcPath = us2fs(commandStrings.Front()); #endif @@ -356,7 +378,7 @@ int Main2( if (passwordEnabled) password = parser[NKey::kPassword].PostStrings[0]; - if (!NFind::DoesFileExist(arcPath)) + if (!NFind::DoesFileExist_FollowLink(arcPath)) throw kCantFindSFX; FString outputDir; diff --git a/CPP/7zip/Bundles/SFXCon/makefile b/CPP/7zip/Bundles/SFXCon/makefile index 077dbc0a..633bd775 100644 --- a/CPP/7zip/Bundles/SFXCon/makefile +++ b/CPP/7zip/Bundles/SFXCon/makefile @@ -29,8 +29,8 @@ COMMON_OBJS = \ $O\StdInStream.obj \ $O\StdOutStream.obj \ $O\StringConvert.obj \ - $O\Wildcard.obj \ $O\UTFConvert.obj \ + $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ @@ -64,9 +64,9 @@ UI_COMMON_OBJS = \ $O\ArchiveExtractCallback.obj \ $O\ArchiveOpenCallback.obj \ $O\DefaultName.obj \ - $O\LoadCodecs.obj \ $O\Extract.obj \ $O\ExtractingFilePath.obj \ + $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ @@ -79,7 +79,6 @@ AR_COMMON_OBJS = \ $O\MultiStream.obj \ $O\OutStreamWithCRC.obj \ - 7Z_OBJS = \ $O\7zDecode.obj \ $O\7zExtract.obj \ @@ -124,11 +123,11 @@ C_OBJS = \ $O\MtDec.obj \ $O\Ppmd7.obj \ $O\Ppmd7Dec.obj \ - $O\Sha256.obj \ $O\Threads.obj \ !include "../../Aes.mak" !include "../../Crc.mak" !include "../../LzmaDec.mak" +!include "../../Sha256.mak" !include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/SFXCon/makefile.gcc b/CPP/7zip/Bundles/SFXCon/makefile.gcc new file mode 100644 index 00000000..889ec1f9 --- /dev/null +++ b/CPP/7zip/Bundles/SFXCon/makefile.gcc @@ -0,0 +1,204 @@ +PROG = 7zCon + +# IS_X64 = 1 +# USE_ASM = 1 +# ST_MODE = 1 + +include ../../LzmaDec_gcc.mak + + +LOCAL_FLAGS_ST = +MT_OBJS = + + +ifdef ST_MODE + +LOCAL_FLAGS_ST = -D_7ZIP_ST + +ifdef SystemDrive +MT_OBJS = \ + $O/Threads.o \ + +endif + +else + +MT_OBJS = \ + $O/StreamBinder.o \ + $O/Synchronization.o \ + $O/VirtThread.o \ + $O/Threads.o \ + +endif + + + +LOCAL_FLAGS_SYS = + +ifdef SystemDrive + +LOCAL_FLAGS_SYS = \ + +SYS_OBJS = \ + $O/DLL.o \ + $O/DllSecur.o \ + $O/resource.o \ + +else + +SYS_OBJS = \ + $O/MyWindows.o \ + +endif + +LOCAL_FLAGS = \ + $(LOCAL_FLAGS_ST) \ + $(LOCAL_FLAGS_SYS) \ + -DEXTRACT_ONLY \ + -DNO_READ_FROM_CODER \ + -D_SFX \ + + +CURRENT_OBJS = \ + $O/SfxCon.o \ + +CONSOLE_OBJS = \ + $O/ConsoleClose.o \ + $O/ExtractCallbackConsole.o \ + $O/List.o \ + $O/MainAr.o \ + $O/OpenCallbackConsole.o \ + $O/PercentPrinter.o \ + $O/UserInputUtils.o \ + +COMMON_OBJS = \ + $O/CommandLineParser.o \ + $O/CRC.o \ + $O/IntToString.o \ + $O/MyString.o \ + $O/MyVector.o \ + $O/NewHandler.o \ + $O/Sha256Prepare.o \ + $O/StdInStream.o \ + $O/StdOutStream.o \ + $O/StringConvert.o \ + $O/UTFConvert.o \ + $O/Wildcard.o \ + +WIN_OBJS = \ + \ + $O/ErrorMsg.o \ + $O/FileDir.o \ + $O/FileFind.o \ + $O/FileIO.o \ + $O/FileName.o \ + $O/PropVariant.o \ + $O/PropVariantConv.o \ + \ + $O/System.o \ + $O/TimeUtils.o \ + +7ZIP_COMMON_OBJS = \ + $O/CreateCoder.o \ + $O/CWrappers.o \ + $O/FilePathAutoRename.o \ + $O/FileStreams.o \ + $O/InBuffer.o \ + $O/FilterCoder.o \ + $O/LimitedStreams.o \ + $O/OutBuffer.o \ + $O/ProgressUtils.o \ + $O/PropId.o \ + \ + $O/StreamObjects.o \ + $O/StreamUtils.o \ + \ + +UI_COMMON_OBJS = \ + $O/ArchiveExtractCallback.o \ + $O/ArchiveOpenCallback.o \ + $O/DefaultName.o \ + $O/Extract.o \ + $O/ExtractingFilePath.o \ + $O/LoadCodecs.o \ + $O/OpenArchive.o \ + $O/PropIDUtils.o \ + +AR_OBJS = \ + $O/SplitHandler.o \ + +AR_COMMON_OBJS = \ + $O/CoderMixer2.o \ + $O/ItemNameUtils.o \ + $O/MultiStream.o \ + $O/OutStreamWithCRC.o \ + +7Z_OBJS = \ + $O/7zDecode.o \ + $O/7zExtract.o \ + $O/7zHandler.o \ + $O/7zIn.o \ + $O/7zRegister.o \ + +COMPRESS_OBJS = \ + $O/Bcj2Coder.o \ + $O/Bcj2Register.o \ + $O/BcjCoder.o \ + $O/BcjRegister.o \ + $O/BranchMisc.o \ + $O/BranchRegister.o \ + $O/CopyCoder.o \ + $O/CopyRegister.o \ + $O/DeltaFilter.o \ + $O/Lzma2Decoder.o \ + $O/Lzma2Register.o \ + $O/LzmaDecoder.o \ + $O/LzmaRegister.o \ + $O/PpmdDecoder.o \ + $O/PpmdRegister.o \ + +CRYPTO_OBJS = \ + $O/7zAes.o \ + $O/7zAesRegister.o \ + $O/MyAes.o \ + +C_OBJS = \ + $O/Alloc.o \ + $O/Bcj2.o \ + $O/Bra.o \ + $O/Bra86.o \ + $O/BraIA64.o \ + $O/CpuArch.o \ + $O/Delta.o \ + \ + $O/Lzma2Dec.o \ + $O/Lzma2DecMt.o \ + $O/LzmaDec.o \ + $O/MtDec.o \ + $O/Ppmd7.o \ + $O/Ppmd7Dec.o \ + $O/Sha256.o \ + $O/Sha256Opt.o \ + $O/7zCrc.o \ + $O/7zCrcOpt.o \ + $O/Aes.o \ + $O/AesOpt.o \ + +OBJS = \ + $(LZMA_DEC_OPT_OBJS) \ + $(C_OBJS) \ + $(MT_OBJS) \ + $(SYS_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(COMPRESS_OBJS) \ + $(CRYPTO_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(AR_OBJS) \ + $(AR_COMMON_OBJS) \ + $(7Z_OBJS) \ + $(UI_COMMON_OBJS) \ + $(CONSOLE_OBJS) \ + $(CURRENT_OBJS) \ + +include ../../7zip_gcc.mak diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp index 00e3ba53..8eaeabe7 100644 --- a/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp +++ b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp @@ -15,8 +15,8 @@ using namespace NWindows; using namespace NFile; using namespace NDir; -static LPCSTR const kCantDeleteFile = "Can not delete output file"; -static LPCSTR const kCantOpenFile = "Can not open output file"; +static LPCSTR const kCantDeleteFile = "Cannot delete output file"; +static LPCSTR const kCantOpenFile = "Cannot open output file"; static LPCSTR const kUnsupportedMethod = "Unsupported Method"; void CExtractCallbackImp::Init(IInArchive *archiveHandler, diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp index e510e5c8..71b65c62 100644 --- a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp +++ b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp @@ -18,8 +18,8 @@ using namespace NWindows; using namespace NFile; using namespace NDir; -static LPCSTR const kCantFindArchive = "Can not find archive file"; -static LPCSTR const kCantOpenArchive = "Can not open the file as archive"; +static LPCSTR const kCantFindArchive = "Cannot find archive file"; +static LPCSTR const kCantOpenArchive = "Cannot open the file as archive"; struct CThreadExtracting { diff --git a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp index 0c302332..86b4f0fb 100644 --- a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp +++ b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp @@ -44,32 +44,32 @@ static bool ReadDataString(CFSTR fileName, LPCSTR startID, NIO::CInFile inFile; if (!inFile.Open(fileName)) return false; - const int kBufferSize = (1 << 12); + const size_t kBufferSize = (1 << 12); Byte buffer[kBufferSize]; - int signatureStartSize = MyStringLen(startID); - int signatureEndSize = MyStringLen(endID); + const unsigned signatureStartSize = MyStringLen(startID); + const unsigned signatureEndSize = MyStringLen(endID); - UInt32 numBytesPrev = 0; + size_t numBytesPrev = 0; bool writeMode = false; UInt64 posTotal = 0; for (;;) { if (posTotal > (1 << 20)) return (stringResult.IsEmpty()); - UInt32 numReadBytes = kBufferSize - numBytesPrev; - UInt32 processedSize; - if (!inFile.Read(buffer + numBytesPrev, numReadBytes, processedSize)) + const size_t numReadBytes = kBufferSize - numBytesPrev; + size_t processedSize; + if (!inFile.ReadFull(buffer + numBytesPrev, numReadBytes, processedSize)) return false; if (processedSize == 0) return true; - UInt32 numBytesInBuffer = numBytesPrev + processedSize; + const size_t numBytesInBuffer = numBytesPrev + processedSize; UInt32 pos = 0; for (;;) { if (writeMode) { - if (pos > numBytesInBuffer - signatureEndSize) + if (pos + signatureEndSize > numBytesInBuffer) break; if (memcmp(buffer + pos, endID, signatureEndSize) == 0) return true; @@ -81,7 +81,7 @@ static bool ReadDataString(CFSTR fileName, LPCSTR startID, } else { - if (pos > numBytesInBuffer - signatureStartSize) + if (pos + signatureStartSize > numBytesInBuffer) break; if (memcmp(buffer + pos, startID, signatureStartSize) == 0) { @@ -111,7 +111,9 @@ struct CInstallIDInit } g_CInstallIDInit; +#if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) #define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return 1; +#endif static void ShowErrorMessageSpec(const UString &name) { @@ -207,7 +209,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, if (!tempDir.Create(kTempDirPrefix)) { if (!assumeYes) - ShowErrorMessage(L"Can not create temp folder archive"); + ShowErrorMessage(L"Cannot create temp folder archive"); return 1; } @@ -217,7 +219,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, HRESULT result = codecs->Load(); if (result != S_OK) { - ShowErrorMessage(L"Can not load codecs"); + ShowErrorMessage(L"Cannot load codecs"); return 1; } } @@ -292,7 +294,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, if (result <= 32) { if (!assumeYes) - ShowErrorMessage(L"Can not open file"); + ShowErrorMessage(L"Cannot open file"); return 1; } hProcess = execInfo.hProcess; @@ -303,10 +305,10 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, if (appLaunched.IsEmpty()) { appLaunched = L"setup.exe"; - if (!NFind::DoesFileExist(us2fs(appLaunched))) + if (!NFind::DoesFileExist_FollowLink(us2fs(appLaunched))) { if (!assumeYes) - ShowErrorMessage(L"Can not find setup.exe"); + ShowErrorMessage(L"Cannot find setup.exe"); return 1; } } diff --git a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp index 14492ca1..c80736de 100644 --- a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp +++ b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp @@ -701,6 +701,10 @@ SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\Sha256Prepare.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File @@ -960,6 +964,11 @@ SOURCE=..\..\..\..\C\Sha256.c # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Sha256Opt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File diff --git a/CPP/7zip/Bundles/SFXWin/SfxWin.cpp b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp index 3c77356e..2f809322 100644 --- a/CPP/7zip/Bundles/SFXWin/SfxWin.cpp +++ b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp @@ -67,12 +67,12 @@ bool g_LVN_ITEMACTIVATE_Support = true; static const wchar_t * const kUnknownExceptionMessage = L"ERROR: Unknown Error!"; -void ErrorMessageForHRESULT(HRESULT res) +static void ErrorMessageForHRESULT(HRESULT res) { ShowErrorMessage(HResultToMessage(res)); } -int APIENTRY WinMain2() +static int APIENTRY WinMain2() { // OleInitialize is required for ProgressBar in TaskBar. #ifndef UNDER_CE @@ -206,7 +206,9 @@ int APIENTRY WinMain2() return NExitCode::kFatalError; } +#if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) #define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return NExitCode::kFatalError; +#endif int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, #ifdef UNDER_CE diff --git a/CPP/7zip/Bundles/SFXWin/makefile b/CPP/7zip/Bundles/SFXWin/makefile index b3b4546f..57d922fb 100644 --- a/CPP/7zip/Bundles/SFXWin/makefile +++ b/CPP/7zip/Bundles/SFXWin/makefile @@ -143,11 +143,11 @@ C_OBJS = \ $O\MtDec.obj \ $O\Ppmd7.obj \ $O\Ppmd7Dec.obj \ - $O\Sha256.obj \ $O\Threads.obj \ !include "../../Aes.mak" !include "../../Crc.mak" !include "../../LzmaDec.mak" +!include "../../Sha256.mak" !include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/makefile b/CPP/7zip/Bundles/makefile index e3b4b88f..0651da54 100644 --- a/CPP/7zip/Bundles/makefile +++ b/CPP/7zip/Bundles/makefile @@ -1,5 +1,6 @@ DIRS = \ Alone\~ \ + Alone2\~ \ Alone7z\~ \ Fm\~ \ Format7z\~ \ diff --git a/CPP/7zip/Common/CWrappers.cpp b/CPP/7zip/Common/CWrappers.cpp index d6b04206..ee4c36a2 100644 --- a/CPP/7zip/Common/CWrappers.cpp +++ b/CPP/7zip/Common/CWrappers.cpp @@ -1,4 +1,4 @@ -// CWrappers.h +// CWrappers.c #include "StdAfx.h" @@ -158,27 +158,27 @@ void CSeekInStreamWrap::Init(IInStream *stream) throw() void CByteInBufWrap::Free() throw() { ::MidFree(Buf); - Buf = 0; + Buf = NULL; } bool CByteInBufWrap::Alloc(UInt32 size) throw() { - if (Buf == 0 || size != Size) + if (!Buf || size != Size) { Free(); Lim = Cur = Buf = (Byte *)::MidAlloc((size_t)size); Size = size; } - return (Buf != 0); + return (Buf != NULL); } Byte CByteInBufWrap::ReadByteFromNewBlock() throw() { - if (Res == S_OK) + if (!Extra && Res == S_OK) { UInt32 avail; - Processed += (Cur - Buf); Res = Stream->Read(Buf, Size, &avail); + Processed += (size_t)(Cur - Buf); Cur = Buf; Lim = Buf + avail; if (avail != 0) @@ -196,41 +196,88 @@ static Byte Wrap_ReadByte(const IByteIn *pp) throw() return p->ReadByteFromNewBlock(); } -CByteInBufWrap::CByteInBufWrap(): Buf(0) +CByteInBufWrap::CByteInBufWrap(): Buf(NULL) { vt.Read = Wrap_ReadByte; } + +/* ---------- CByteOutBufWrap ---------- */ + +/* +void CLookToSequentialWrap::Free() throw() +{ + ::MidFree(BufBase); + BufBase = NULL; +} + +bool CLookToSequentialWrap::Alloc(UInt32 size) throw() +{ + if (!BufBase || size != Size) + { + Free(); + BufBase = (Byte *)::MidAlloc((size_t)size); + Size = size; + } + return (BufBase != NULL); +} +*/ + +/* +EXTERN_C_BEGIN + +void CLookToSequentialWrap_Look(ILookInSeqStream *pp) +{ + CLookToSequentialWrap *p = (CLookToSequentialWrap *)pp->Obj; + + if (p->Extra || p->Res != S_OK) + return; + { + UInt32 avail; + p->Res = p->Stream->Read(p->BufBase, p->Size, &avail); + p->Processed += avail; + pp->Buf = p->BufBase; + pp->Limit = pp->Buf + avail; + if (avail == 0) + p->Extra = true; + } +} + +EXTERN_C_END +*/ + + /* ---------- CByteOutBufWrap ---------- */ void CByteOutBufWrap::Free() throw() { ::MidFree(Buf); - Buf = 0; + Buf = NULL; } bool CByteOutBufWrap::Alloc(size_t size) throw() { - if (Buf == 0 || size != Size) + if (!Buf || size != Size) { Free(); Buf = (Byte *)::MidAlloc(size); Size = size; } - return (Buf != 0); + return (Buf != NULL); } HRESULT CByteOutBufWrap::Flush() throw() { if (Res == S_OK) { - size_t size = (Cur - Buf); + const size_t size = (size_t)(Cur - Buf); Res = WriteStream(Stream, Buf, size); if (Res == S_OK) Processed += size; - Cur = Buf; + // else throw 11; } + Cur = Buf; // reset pointer for later Wrap_WriteByte() return Res; } @@ -244,7 +291,57 @@ static void Wrap_WriteByte(const IByteOut *pp, Byte b) throw() p->Flush(); } -CByteOutBufWrap::CByteOutBufWrap() throw(): Buf(0) +CByteOutBufWrap::CByteOutBufWrap() throw(): Buf(NULL), Size(0) { vt.Write = Wrap_WriteByte; } + + +/* ---------- CLookOutWrap ---------- */ + +/* +void CLookOutWrap::Free() throw() +{ + ::MidFree(Buf); + Buf = NULL; +} + +bool CLookOutWrap::Alloc(size_t size) throw() +{ + if (!Buf || size != Size) + { + Free(); + Buf = (Byte *)::MidAlloc(size); + Size = size; + } + return (Buf != NULL); +} + +static size_t LookOutWrap_GetOutBuf(const ILookOutStream *pp, void **buf) throw() +{ + CLookOutWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CLookOutWrap, vt); + *buf = p->Buf; + return p->Size; +} + +static size_t LookOutWrap_Write(const ILookOutStream *pp, size_t size) throw() +{ + CLookOutWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CLookOutWrap, vt); + if (p->Res == S_OK && size != 0) + { + p->Res = WriteStream(p->Stream, p->Buf, size); + if (p->Res == S_OK) + { + p->Processed += size; + return size; + } + } + return 0; +} + +CLookOutWrap::CLookOutWrap() throw(): Buf(NULL), Size(0) +{ + vt.GetOutBuf = LookOutWrap_GetOutBuf; + vt.Write = LookOutWrap_Write; +} +*/ diff --git a/CPP/7zip/Common/CWrappers.h b/CPP/7zip/Common/CWrappers.h index e5c890d8..e7196a5c 100644 --- a/CPP/7zip/Common/CWrappers.h +++ b/CPP/7zip/Common/CWrappers.h @@ -74,7 +74,7 @@ struct CByteInBufWrap Extra = false; Res = S_OK; } - UInt64 GetProcessed() const { return Processed + (Cur - Buf); } + UInt64 GetProcessed() const { return Processed + (size_t)(Cur - Buf); } Byte ReadByteFromNewBlock() throw(); Byte ReadByte() { @@ -85,6 +85,45 @@ struct CByteInBufWrap }; +/* +struct CLookToSequentialWrap +{ + Byte *BufBase; + UInt32 Size; + ISequentialInStream *Stream; + UInt64 Processed; + bool Extra; + HRESULT Res; + + CLookToSequentialWrap(): BufBase(NULL) {} + ~CLookToSequentialWrap() { Free(); } + void Free() throw(); + bool Alloc(UInt32 size) throw(); + void Init() + { + // Lim = Cur = Buf; + Processed = 0; + Extra = false; + Res = S_OK; + } + // UInt64 GetProcessed() const { return Processed + (Cur - Buf); } + + Byte ReadByteFromNewBlock() throw(); + Byte ReadByte() + { + if (Cur != Lim) + return *Cur++; + return ReadByteFromNewBlock(); + } +}; + +EXTERN_C_BEGIN +// void CLookToSequentialWrap_Look(ILookInSeqStream *pp); +EXTERN_C_END +*/ + + + struct CByteOutBufWrap { IByteOut vt; @@ -107,7 +146,7 @@ struct CByteOutBufWrap Processed = 0; Res = S_OK; } - UInt64 GetProcessed() const { return Processed + (Cur - Buf); } + UInt64 GetProcessed() const { return Processed + (size_t)(Cur - Buf); } HRESULT Flush() throw(); void WriteByte(Byte b) { @@ -117,4 +156,27 @@ struct CByteOutBufWrap } }; + +/* +struct CLookOutWrap +{ + ILookOutStream vt; + Byte *Buf; + size_t Size; + ISequentialOutStream *Stream; + UInt64 Processed; + HRESULT Res; + + CLookOutWrap() throw(); + ~CLookOutWrap() { Free(); } + void Free() throw(); + bool Alloc(size_t size) throw(); + void Init() + { + Processed = 0; + Res = S_OK; + } +}; +*/ + #endif diff --git a/CPP/7zip/Common/CreateCoder.cpp b/CPP/7zip/Common/CreateCoder.cpp index bf525dc8..e62bb0b4 100644 --- a/CPP/7zip/Common/CreateCoder.cpp +++ b/CPP/7zip/Common/CreateCoder.cpp @@ -11,19 +11,23 @@ #include "RegisterCodec.h" static const unsigned kNumCodecsMax = 64; +extern +unsigned g_NumCodecs; unsigned g_NumCodecs = 0; +extern +const CCodecInfo *g_Codecs[]; const CCodecInfo *g_Codecs[kNumCodecsMax]; // We use g_ExternalCodecs in other stages. -/* #ifdef EXTERNAL_CODECS +/* extern CExternalCodecs g_ExternalCodecs; #define CHECK_GLOBAL_CODECS \ if (!__externalCodecs || !__externalCodecs->IsSet()) __externalCodecs = &g_ExternalCodecs; -#endif */ - #define CHECK_GLOBAL_CODECS +#endif + void RegisterCodec(const CCodecInfo *codecInfo) throw() { @@ -32,7 +36,11 @@ void RegisterCodec(const CCodecInfo *codecInfo) throw() } static const unsigned kNumHashersMax = 16; +extern +unsigned g_NumHashers; unsigned g_NumHashers = 0; +extern +const CHasherInfo *g_Hashers[]; const CHasherInfo *g_Hashers[kNumHashersMax]; void RegisterHasher(const CHasherInfo *hashInfo) throw() @@ -164,7 +172,7 @@ int FindMethod_Index( { methodId = codec.Id; numStreams = codec.NumStreams; - return i; + return (int)i; } } @@ -181,7 +189,7 @@ int FindMethod_Index( { methodId = codec.Id; numStreams = codec.NumStreams; - return g_NumCodecs + i; + return (int)(g_NumCodecs + i); } } @@ -200,7 +208,7 @@ static int FindMethod_Index( { const CCodecInfo &codec = *g_Codecs[i]; if (codec.Id == methodId && (encode ? codec.CreateEncoder : codec.CreateDecoder)) - return i; + return (int)i; } #ifdef EXTERNAL_CODECS @@ -212,7 +220,7 @@ static int FindMethod_Index( { const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; if (codec.Id == methodId && (encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned)) - return g_NumCodecs + i; + return (int)(g_NumCodecs + i); } #endif @@ -441,7 +449,7 @@ HRESULT CreateCoder_Id( int index = FindMethod_Index(EXTERNAL_CODECS_LOC_VARS methodId, encode); if (index < 0) return S_OK; - return CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS index, encode, filter, cod); + return CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS (unsigned)index, encode, filter, cod); } diff --git a/CPP/7zip/Common/FilePathAutoRename.cpp b/CPP/7zip/Common/FilePathAutoRename.cpp index 0904e696..1ebfd72b 100644 --- a/CPP/7zip/Common/FilePathAutoRename.cpp +++ b/CPP/7zip/Common/FilePathAutoRename.cpp @@ -26,8 +26,8 @@ bool AutoRenamePath(FString &path) FString extension; if (dotPos > slashPos + 1) { - name.DeleteFrom(dotPos); - extension = path.Ptr(dotPos); + name.DeleteFrom((unsigned)dotPos); + extension = path.Ptr((unsigned)dotPos); } name += '_'; diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp index f3a322fc..466f46e9 100644 --- a/CPP/7zip/Common/FileStreams.cpp +++ b/CPP/7zip/Common/FileStreams.cpp @@ -6,6 +6,7 @@ #include <fcntl.h> #include <unistd.h> #include <errno.h> +#include "../../Windows/FileFind.h" #endif #ifdef SUPPORT_DEVICE_FILE @@ -15,22 +16,26 @@ #include "FileStreams.h" -static inline HRESULT ConvertBoolToHRESULT(bool result) +static inline HRESULT GetLastError_HRESULT() { - #ifdef _WIN32 - if (result) - return S_OK; DWORD lastError = ::GetLastError(); if (lastError == 0) return E_FAIL; return HRESULT_FROM_WIN32(lastError); - #else - return result ? S_OK: E_FAIL; - #endif +} + +static inline HRESULT ConvertBoolToHRESULT(bool result) +{ + if (result) + return S_OK; + return GetLastError_HRESULT(); } +#ifdef SUPPORT_DEVICE_FILE static const UInt32 kClusterSize = 1 << 18; +#endif + CInFileStream::CInFileStream(): #ifdef SUPPORT_DEVICE_FILE VirtPos(0), @@ -111,7 +116,7 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) if (alignedPos != PhyPos) { UInt64 realNewPosition; - bool result = File.Seek(alignedPos, FILE_BEGIN, realNewPosition); + bool result = File.Seek((Int64)alignedPos, FILE_BEGIN, realNewPosition); if (!result) return ConvertBoolToHRESULT(result); PhyPos = realNewPosition; @@ -140,7 +145,7 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) if (VirtPos != PhyPos) { UInt64 realNewPosition; - bool result = File.Seek(VirtPos, FILE_BEGIN, realNewPosition); + bool result = File.Seek((Int64)VirtPos, FILE_BEGIN, realNewPosition); if (!result) return ConvertBoolToHRESULT(result); PhyPos = VirtPos = realNewPosition; @@ -149,7 +154,7 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) #endif UInt32 realProcessedSize; - bool result = File.ReadPart(data, size, realProcessedSize); + const bool result = File.ReadPart(data, size, realProcessedSize); if (processedSize) *processedSize = realProcessedSize; @@ -161,33 +166,27 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) if (result) return S_OK; + #else // USE_WIN_FILE + + if (processedSize) + *processedSize = 0; + const ssize_t res = File.read_part(data, (size_t)size); + if (res != -1) { - DWORD error = ::GetLastError(); + if (processedSize) + *processedSize = (UInt32)res; + return S_OK; + } + #endif // USE_WIN_FILE + { + const DWORD error = ::GetLastError(); if (Callback) return Callback->InFileStream_On_Error(CallbackRef, error); if (error == 0) return E_FAIL; - return HRESULT_FROM_WIN32(error); } - - #else - - if (processedSize) - *processedSize = 0; - ssize_t res = File.Read(data, (size_t)size); - if (res == -1) - { - if (Callback) - return Callback->InFileStream_On_Error(CallbackRef, E_FAIL); - return E_FAIL; - } - if (processedSize) - *processedSize = (UInt32)res; - return S_OK; - - #endif } #ifdef UNDER_CE @@ -228,7 +227,7 @@ STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSi } while (res < 0 && (errno == EINTR)); if (res == -1) - return E_FAIL; + return GetLastError_HRESULT(); if (processedSize) *processedSize = (UInt32)res; return S_OK; @@ -257,9 +256,9 @@ STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPos } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - VirtPos = offset; + VirtPos = (UInt64)offset; if (newPosition) - *newPosition = offset; + *newPosition = (UInt64)offset; return S_OK; } #endif @@ -277,9 +276,9 @@ STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPos #else - off_t res = File.Seek((off_t)offset, seekOrigin); + off_t res = File.seek((off_t)offset, (int)seekOrigin); if (res == -1) - return E_FAIL; + return GetLastError_HRESULT(); if (newPosition) *newPosition = (UInt64)res; return S_OK; @@ -306,7 +305,7 @@ STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aT if (attrib) *attrib = info.dwFileAttributes; return S_OK; } - return GetLastError(); + return GetLastError_HRESULT(); } STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) @@ -325,7 +324,71 @@ STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) props->MTime = info.ftLastWriteTime; return S_OK; } - return GetLastError(); + return GetLastError_HRESULT(); +} + +#elif !defined(_WIN32) + +STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) +{ + struct stat st; + if (File.my_fstat(&st) != 0) + return GetLastError_HRESULT(); + + if (size) *size = (UInt64)st.st_size; + #ifdef __APPLE__ + if (cTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctimespec, *cTime); + if (aTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atimespec, *aTime); + if (mTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtimespec, *mTime); + #else + if (cTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctim, *cTime); + if (aTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atim, *aTime); + if (mTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtim, *mTime); + #endif + if (attrib) *attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); + + return S_OK; +} + +// #include <stdio.h> + +STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) +{ + struct stat st; + if (File.my_fstat(&st) != 0) + return GetLastError_HRESULT(); + + props->Size = (UInt64)st.st_size; + /* + dev_t stat::st_dev: + GCC:Linux long unsigned int : __dev_t + Mac: int + */ + props->VolID = (UInt64)(Int64)st.st_dev; + props->FileID_Low = st.st_ino; + props->FileID_High = 0; + props->NumLinks = (UInt32)st.st_nlink; // we reduce to UInt32 from (nlink_t) that is (unsigned long) + props->Attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); + + #ifdef __APPLE__ + NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctimespec, props->CTime); + NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atimespec, props->ATime); + NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtimespec, props->MTime); + #else + NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctim, props->CTime); + NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atim, props->ATime); + NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtim, props->MTime); + #endif + + /* + printf("\nGetProps2() NumLinks=%d = st_dev=%d st_ino = %d\n" + , (unsigned)(props->NumLinks) + , (unsigned)(st.st_dev) + , (unsigned)(st.st_ino) + ); + */ + + return S_OK; } #endif @@ -343,7 +406,7 @@ STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *proces #ifdef USE_WIN_FILE UInt32 realProcessedSize; - bool result = File.Write(data, size, realProcessedSize); + const bool result = File.Write(data, size, realProcessedSize); ProcessedSize += realProcessedSize; if (processedSize) *processedSize = realProcessedSize; @@ -353,12 +416,13 @@ STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *proces if (processedSize) *processedSize = 0; - ssize_t res = File.Write(data, (size_t)size); - if (res == -1) - return E_FAIL; + size_t realProcessedSize; + const ssize_t res = File.write_full(data, (size_t)size, realProcessedSize); + ProcessedSize += realProcessedSize; if (processedSize) - *processedSize = (UInt32)res; - ProcessedSize += res; + *processedSize = (UInt32)realProcessedSize; + if (res == -1) + return GetLastError_HRESULT(); return S_OK; #endif @@ -379,9 +443,9 @@ STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo #else - off_t res = File.Seek((off_t)offset, seekOrigin); + off_t res = File.seek((off_t)offset, (int)seekOrigin); if (res == -1) - return E_FAIL; + return GetLastError_HRESULT(); if (newPosition) *newPosition = (UInt64)res; return S_OK; @@ -403,8 +467,11 @@ STDMETHODIMP COutFileStream::SetSize(UInt64 newSize) #else - return E_FAIL; - + // SetLength() uses ftruncate() that doesn't change file offset + if (!File.SetLength(newSize)) + return GetLastError_HRESULT(); + return S_OK; + #endif } @@ -462,7 +529,7 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro while (res < 0 && (errno == EINTR)); if (res == -1) - return E_FAIL; + return GetLastError_HRESULT(); _size += (size_t)res; if (processedSize) diff --git a/CPP/7zip/Common/FileStreams.h b/CPP/7zip/Common/FileStreams.h index ef2986fd..fe9f4c19 100644 --- a/CPP/7zip/Common/FileStreams.h +++ b/CPP/7zip/Common/FileStreams.h @@ -7,42 +7,30 @@ #define USE_WIN_FILE #endif +#include "../../Common/MyCom.h" #include "../../Common/MyString.h" -#ifdef USE_WIN_FILE #include "../../Windows/FileIO.h" -#else -#include "../../Common/C_FileIO.h" -#endif - -#include "../../Common/MyCom.h" #include "../IStream.h" -#ifdef _WIN32 -typedef UINT_PTR My_UINT_PTR; -#else -typedef UINT My_UINT_PTR; -#endif - struct IInFileStream_Callback { - virtual HRESULT InFileStream_On_Error(My_UINT_PTR val, DWORD error) = 0; - virtual void InFileStream_On_Destroy(My_UINT_PTR val) = 0; + virtual HRESULT InFileStream_On_Error(UINT_PTR val, DWORD error) = 0; + virtual void InFileStream_On_Destroy(UINT_PTR val) = 0; }; class CInFileStream: public IInStream, public IStreamGetSize, - #ifdef USE_WIN_FILE public IStreamGetProps, public IStreamGetProps2, - #endif public CMyUnknownImp { public: - #ifdef USE_WIN_FILE NWindows::NFile::NIO::CInFile File; + + #ifdef USE_WIN_FILE #ifdef SUPPORT_DEVICE_FILE UInt64 VirtPos; @@ -52,14 +40,12 @@ public: UInt32 BufSize; #endif - #else - NC::NFile::NIO::CInFile File; #endif bool SupportHardLinks; IInFileStream_Callback *Callback; - My_UINT_PTR CallbackRef; + UINT_PTR CallbackRef; virtual ~CInFileStream(); @@ -77,10 +63,8 @@ public: MY_QUERYINTERFACE_BEGIN2(IInStream) MY_QUERYINTERFACE_ENTRY(IStreamGetSize) - #ifdef USE_WIN_FILE MY_QUERYINTERFACE_ENTRY(IStreamGetProps) MY_QUERYINTERFACE_ENTRY(IStreamGetProps2) - #endif MY_QUERYINTERFACE_END MY_ADDREF_RELEASE @@ -88,10 +72,8 @@ public: STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(GetSize)(UInt64 *size); - #ifdef USE_WIN_FILE STDMETHOD(GetProps)(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib); STDMETHOD(GetProps2)(CStreamFileProps *props); - #endif }; class CStdInFileStream: @@ -110,11 +92,8 @@ class COutFileStream: public CMyUnknownImp { public: - #ifdef USE_WIN_FILE NWindows::NFile::NIO::COutFile File; - #else - NC::NFile::NIO::COutFile File; - #endif + virtual ~COutFileStream() {} bool Create(CFSTR fileName, bool createAlways) { @@ -131,14 +110,11 @@ public: UInt64 ProcessedSize; - #ifdef USE_WIN_FILE bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { return File.SetTime(cTime, aTime, mTime); } bool SetMTime(const FILETIME *mTime) { return File.SetMTime(mTime); } - #endif - MY_UNKNOWN_IMP1(IOutStream) @@ -146,6 +122,15 @@ public: STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(UInt64 newSize); + bool SeekToBegin_bool() + { + #ifdef USE_WIN_FILE + return File.SeekToBegin(); + #else + return File.seekToBegin() == 0; + #endif + } + HRESULT GetSize(UInt64 *size); }; diff --git a/CPP/7zip/Common/FilterCoder.cpp b/CPP/7zip/Common/FilterCoder.cpp index f4c00273..fb99f610 100644 --- a/CPP/7zip/Common/FilterCoder.cpp +++ b/CPP/7zip/Common/FilterCoder.cpp @@ -86,47 +86,47 @@ STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStr { RINOK(Init_and_Alloc()); + UInt64 prev = 0; UInt64 nowPos64 = 0; bool inputFinished = false; UInt32 pos = 0; while (!outSize || nowPos64 < *outSize) { - UInt32 endPos = pos; - if (!inputFinished) { size_t processedSize = _bufSize - pos; RINOK(ReadStream(inStream, _buf + pos, &processedSize)); - endPos = pos + (UInt32)processedSize; - inputFinished = (endPos != _bufSize); + pos += (UInt32)processedSize; + inputFinished = (pos != _bufSize); } - pos = Filter->Filter(_buf, endPos); + if (pos == 0) + return S_OK; + + UInt32 filtered = Filter->Filter(_buf, pos); - if (pos > endPos) + if (filtered > pos) { // AES - if (!inputFinished || pos > _bufSize) + if (!inputFinished || filtered > _bufSize) return E_FAIL; if (!_encodeMode) return S_FALSE; + Byte *buf = _buf; do - _buf[endPos] = 0; - while (++endPos != pos); + buf[pos] = 0; + while (++pos != filtered); - if (pos != Filter->Filter(_buf, pos)) + if (filtered != Filter->Filter(buf, filtered)) return E_FAIL; } - if (endPos == 0) - return S_OK; - - UInt32 size = (pos != 0 ? pos : endPos); + UInt32 size = (filtered != 0 ? filtered : pos); if (outSize) { - UInt64 remSize = *outSize - nowPos64; + const UInt64 remSize = *outSize - nowPos64; if (size > remSize) size = (UInt32)remSize; } @@ -134,16 +134,17 @@ STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStr RINOK(WriteStream(outStream, _buf, size)); nowPos64 += size; - if (pos == 0) + if (filtered == 0) return S_OK; + pos -= filtered; + for (UInt32 i = 0; i < pos; i++) + _buf[i] = _buf[filtered++]; - if (progress) + if (progress && (nowPos64 - prev) >= (1 << 22)) + { + prev = nowPos64; RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64)); - - UInt32 i = 0; - while (pos < endPos) - _buf[i++] = _buf[pos++]; - pos = i; + } } return S_OK; diff --git a/CPP/7zip/Common/InBuffer.cpp b/CPP/7zip/Common/InBuffer.cpp index d1bc9b9a..6f6eecad 100644 --- a/CPP/7zip/Common/InBuffer.cpp +++ b/CPP/7zip/Common/InBuffer.cpp @@ -56,7 +56,7 @@ bool CInBufferBase::ReadBlock() #endif if (_wasFinished) return false; - _processedSize += (_buf - _bufBase); + _processedSize += (size_t)(_buf - _bufBase); _buf = _bufBase; _bufLim = _bufBase; UInt32 processed; @@ -100,7 +100,7 @@ size_t CInBufferBase::ReadBytes(Byte *buf, size_t size) size_t num = 0; for (;;) { - const size_t rem = _bufLim - _buf; + const size_t rem = (size_t)(_bufLim - _buf); if (size <= rem) { if (size != 0) @@ -148,7 +148,7 @@ size_t CInBufferBase::Skip(size_t size) size_t processed = 0; for (;;) { - size_t rem = (_bufLim - _buf); + const size_t rem = (size_t)(_bufLim - _buf); if (rem >= size) { _buf += size; diff --git a/CPP/7zip/Common/InBuffer.h b/CPP/7zip/Common/InBuffer.h index 4b9c2c32..fa063949 100644 --- a/CPP/7zip/Common/InBuffer.h +++ b/CPP/7zip/Common/InBuffer.h @@ -38,8 +38,16 @@ public: CInBufferBase() throw(); - UInt64 GetStreamSize() const { return _processedSize + (_buf - _bufBase); } - UInt64 GetProcessedSize() const { return _processedSize + NumExtraBytes + (_buf - _bufBase); } + // the size of portion of data in real stream that was already read from this object + // it doesn't include unused data in buffer + // it doesn't include virtual Extra bytes after the end of real stream data + UInt64 GetStreamSize() const { return _processedSize + (size_t)(_buf - _bufBase); } + + // the size of virtual data that was read from this object + // it doesn't include unused data in buffers + // it includes any virtual Extra bytes after the end of real data + UInt64 GetProcessedSize() const { return _processedSize + NumExtraBytes + (size_t)(_buf - _bufBase); } + bool WasFinished() const { return _wasFinished; } void SetStream(ISequentialInStream *stream) { _stream = stream; } @@ -68,6 +76,15 @@ public: b = *_buf++; return true; } + + MY_FORCE_INLINE + bool ReadByte_FromBuf(Byte &b) + { + if (_buf >= _bufLim) + return false; + b = *_buf++; + return true; + } MY_FORCE_INLINE Byte ReadByte() diff --git a/CPP/7zip/Common/InOutTempBuffer.cpp b/CPP/7zip/Common/InOutTempBuffer.cpp index 7523f3a3..cae6b803 100644 --- a/CPP/7zip/Common/InOutTempBuffer.cpp +++ b/CPP/7zip/Common/InOutTempBuffer.cpp @@ -2,13 +2,13 @@ #include "StdAfx.h" -#include "../../../C/7zCrc.h" - -#include "../../Common/Defs.h" - #include "InOutTempBuffer.h" #include "StreamUtils.h" +#ifdef USE_InOutTempBuffer_FILE + +#include "../../../C/7zCrc.h" + using namespace NWindows; using namespace NFile; using namespace NDir; @@ -16,50 +16,58 @@ using namespace NDir; static const size_t kTempBufSize = (1 << 20); #define kTempFilePrefixString FTEXT("7zt") +CInOutTempBuffer::~CInOutTempBuffer() +{ + delete []_buf; +} +#endif -CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { } +CInOutTempBuffer::CInOutTempBuffer() + #ifdef USE_InOutTempBuffer_FILE + : _buf(NULL) + #endif +{ } void CInOutTempBuffer::Create() { + #ifdef USE_InOutTempBuffer_FILE if (!_buf) _buf = new Byte[kTempBufSize]; -} - -CInOutTempBuffer::~CInOutTempBuffer() -{ - delete []_buf; + #endif } void CInOutTempBuffer::InitWriting() { + #ifdef USE_InOutTempBuffer_FILE _bufPos = 0; + _crc = CRC_INIT_VAL; _tempFileCreated = false; + #endif _size = 0; - _crc = CRC_INIT_VAL; } -bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size) + +#ifdef USE_InOutTempBuffer_FILE + +static inline HRESULT Get_HRESULT_LastError() { - if (size == 0) - return true; - if (!_tempFileCreated) - { - if (!_tempFile.CreateRandomInTempFolder(kTempFilePrefixString, &_outFile)) - return false; - _tempFileCreated = true; - } - UInt32 processed; - if (!_outFile.Write(data, size, processed)) - return false; - _crc = CrcUpdate(_crc, data, processed); - _size += processed; - return (processed == size); + #ifdef _WIN32 + DWORD lastError = ::GetLastError(); + if (lastError != 0) + return HRESULT_FROM_WIN32(lastError); + #endif + return E_FAIL; } -bool CInOutTempBuffer::Write(const void *data, UInt32 size) +#endif + + +HRESULT CInOutTempBuffer::Write_HRESULT(const void *data, UInt32 size) { + #ifdef USE_InOutTempBuffer_FILE + if (size == 0) - return true; + return S_OK; size_t cur = kTempBufSize - _bufPos; if (cur != 0) { @@ -72,11 +80,42 @@ bool CInOutTempBuffer::Write(const void *data, UInt32 size) size -= (UInt32)cur; data = ((const Byte *)data) + cur; } - return WriteToFile(data, size); + + if (size == 0) + return S_OK; + + if (!_tempFileCreated) + { + if (!_tempFile.CreateRandomInTempFolder(kTempFilePrefixString, &_outFile)) + return Get_HRESULT_LastError(); + _tempFileCreated = true; + } + UInt32 processed; + if (!_outFile.Write(data, size, processed)) + return Get_HRESULT_LastError(); + _crc = CrcUpdate(_crc, data, processed); + _size += processed; + return (processed == size) ? S_OK : E_FAIL; + + #else + + const size_t newSize = _size + size; + if (newSize < _size) + return E_OUTOFMEMORY; + if (!_dynBuffer.EnsureCapacity(newSize)) + return E_OUTOFMEMORY; + memcpy(((Byte *)_dynBuffer) + _size, data, size); + _size = newSize; + return S_OK; + + #endif } + HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) { + #ifdef USE_InOutTempBuffer_FILE + if (!_outFile.Close()) return E_FAIL; @@ -107,8 +146,13 @@ HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) size += processed; } } - return (_crc == crc && size == _size) ? S_OK : E_FAIL; + + #else + + return WriteStream(stream, (const Byte *)_dynBuffer, _size); + + #endif } /* diff --git a/CPP/7zip/Common/InOutTempBuffer.h b/CPP/7zip/Common/InOutTempBuffer.h index 204a105f..755935ea 100644 --- a/CPP/7zip/Common/InOutTempBuffer.h +++ b/CPP/7zip/Common/InOutTempBuffer.h @@ -3,30 +3,48 @@ #ifndef __IN_OUT_TEMP_BUFFER_H #define __IN_OUT_TEMP_BUFFER_H -#include "../../Common/MyCom.h" +#ifdef _WIN32 +// #define USE_InOutTempBuffer_FILE +#endif + +#ifdef USE_InOutTempBuffer_FILE #include "../../Windows/FileDir.h" +#else +#include "StreamObjects.h" +#endif #include "../IStream.h" class CInOutTempBuffer { + #ifdef USE_InOutTempBuffer_FILE + NWindows::NFile::NDir::CTempFile _tempFile; NWindows::NFile::NIO::COutFile _outFile; + bool _tempFileCreated; Byte *_buf; size_t _bufPos; UInt64 _size; UInt32 _crc; - bool _tempFileCreated; - bool WriteToFile(const void *data, UInt32 size); + #else + + CByteDynBuffer _dynBuffer; + size_t _size; + + #endif + + CLASS_NO_COPY(CInOutTempBuffer); public: CInOutTempBuffer(); - ~CInOutTempBuffer(); void Create(); - void InitWriting(); - bool Write(const void *data, UInt32 size); + #ifdef USE_InOutTempBuffer_FILE + ~CInOutTempBuffer(); + #endif + void InitWriting(); + HRESULT Write_HRESULT(const void *data, UInt32 size); HRESULT WriteToStream(ISequentialOutStream *stream); UInt64 GetDataSize() const { return _size; } }; diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp index 8e032561..add6636b 100644 --- a/CPP/7zip/Common/LimitedStreams.cpp +++ b/CPP/7zip/Common/LimitedStreams.cpp @@ -67,7 +67,7 @@ STDMETHODIMP CLimitedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *new } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _virtPos = offset; + _virtPos = (UInt64)offset; if (newPosition) *newPosition = _virtPos; return S_OK; @@ -115,7 +115,7 @@ STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSi _curRem = blockSize - offsetInBlock; - for (int i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++) + for (unsigned i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++) _curRem += (UInt32)1 << BlockSizeLog; } @@ -143,9 +143,9 @@ STDMETHODIMP CClusterInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *new return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; if (_virtPos != (UInt64)offset) _curRem = 0; - _virtPos = offset; + _virtPos = (UInt64)offset; if (newPosition) - *newPosition = offset; + *newPosition = (UInt64)offset; return S_OK; } @@ -203,7 +203,7 @@ STDMETHODIMP CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _virtPos = offset; + _virtPos = (UInt64)offset; if (newPosition) *newPosition = _virtPos; return S_OK; @@ -268,10 +268,10 @@ STDMETHODIMP CTailInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPos } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _virtPos = offset; + _virtPos = (UInt64)offset; if (newPosition) *newPosition = _virtPos; - return Stream->Seek(Offset + _virtPos, STREAM_SEEK_SET, NULL); + return Stream->Seek((Int64)(Offset + _virtPos), STREAM_SEEK_SET, NULL); } STDMETHODIMP CLimitedCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize) @@ -325,7 +325,7 @@ STDMETHODIMP CLimitedCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt6 } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _virtPos = offset; + _virtPos = (UInt64)offset; if (newPosition) *newPosition = _virtPos; return S_OK; @@ -354,10 +354,10 @@ STDMETHODIMP CTailOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _virtPos = offset; + _virtPos = (UInt64)offset; if (newPosition) *newPosition = _virtPos; - return Stream->Seek(Offset + _virtPos, STREAM_SEEK_SET, NULL); + return Stream->Seek((Int64)(Offset + _virtPos), STREAM_SEEK_SET, NULL); } STDMETHODIMP CTailOutStream::SetSize(UInt64 newSize) diff --git a/CPP/7zip/Common/LimitedStreams.h b/CPP/7zip/Common/LimitedStreams.h index fb1ac3cd..ade29937 100644 --- a/CPP/7zip/Common/LimitedStreams.h +++ b/CPP/7zip/Common/LimitedStreams.h @@ -44,7 +44,7 @@ class CLimitedInStream: UInt64 _size; UInt64 _startOffset; - HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } + HRESULT SeekToPhys() { return _stream->Seek((Int64)_physPos, STREAM_SEEK_SET, NULL); } public: void SetStream(IInStream *stream) { _stream = stream; } HRESULT InitAndSeek(UInt64 startOffset, UInt64 size) @@ -80,7 +80,7 @@ public: CRecordVector<UInt32> Vector; UInt64 StartOffset; - HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } + HRESULT SeekToPhys() { return Stream->Seek((Int64)_physPos, STREAM_SEEK_SET, NULL); } HRESULT InitAndSeek() { @@ -115,7 +115,7 @@ class CExtentsStream: UInt64 _virtPos; bool _needStartSeek; - HRESULT SeekToPhys() { return Stream->Seek(_phyPos, STREAM_SEEK_SET, NULL); } + HRESULT SeekToPhys() { return Stream->Seek((Int64)_phyPos, STREAM_SEEK_SET, NULL); } public: CMyComPtr<IInStream> Stream; @@ -177,7 +177,7 @@ public: STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); - HRESULT SeekToStart() { return Stream->Seek(Offset, STREAM_SEEK_SET, NULL); } + HRESULT SeekToStart() { return Stream->Seek((Int64)Offset, STREAM_SEEK_SET, NULL); } }; class CLimitedCachedInStream: @@ -195,7 +195,7 @@ class CLimitedCachedInStream: size_t _cachePhyPos; - HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } + HRESULT SeekToPhys() { return _stream->Seek((Int64)_physPos, STREAM_SEEK_SET, NULL); } public: CByteBuffer Buffer; diff --git a/CPP/7zip/Common/MemBlocks.cpp b/CPP/7zip/Common/MemBlocks.cpp index 5aba046b..f351abbd 100644 --- a/CPP/7zip/Common/MemBlocks.cpp +++ b/CPP/7zip/Common/MemBlocks.cpp @@ -7,21 +7,26 @@ #include "MemBlocks.h" #include "StreamUtils.h" -bool CMemBlockManager::AllocateSpace(size_t numBlocks) +bool CMemBlockManager::AllocateSpace_bool(size_t numBlocks) { FreeSpace(); - if (_blockSize < sizeof(void *) || numBlocks < 1) + if (numBlocks == 0) + { + return true; + // return false; + } + if (_blockSize < sizeof(void *)) return false; - size_t totalSize = numBlocks * _blockSize; + const size_t totalSize = numBlocks * _blockSize; if (totalSize / _blockSize != numBlocks) return false; _data = ::MidAlloc(totalSize); - if (_data == 0) + if (!_data) return false; Byte *p = (Byte *)_data; for (size_t i = 0; i + 1 < numBlocks; i++, p += _blockSize) - *(Byte **)p = (p + _blockSize); - *(Byte **)p = 0; + *(Byte **)(void *)p = (p + _blockSize); + *(Byte **)(void *)p = NULL; _headFree = _data; return true; } @@ -35,41 +40,64 @@ void CMemBlockManager::FreeSpace() void *CMemBlockManager::AllocateBlock() { - if (_headFree == 0) - return 0; void *p = _headFree; - _headFree = *(void **)_headFree; + if (p) + _headFree = *(void **)p; return p; } void CMemBlockManager::FreeBlock(void *p) { - if (p == 0) + if (!p) return; *(void **)p = _headFree; _headFree = p; } +// #include <stdio.h> + HRes CMemBlockManagerMt::AllocateSpace(size_t numBlocks, size_t numNoLockBlocks) { if (numNoLockBlocks > numBlocks) return E_INVALIDARG; - if (!CMemBlockManager::AllocateSpace(numBlocks)) + const size_t numLockBlocks = numBlocks - numNoLockBlocks; + UInt32 maxCount = (UInt32)numLockBlocks; + if (maxCount != numLockBlocks) + return E_OUTOFMEMORY; + if (!CMemBlockManager::AllocateSpace_bool(numBlocks)) return E_OUTOFMEMORY; - size_t numLockBlocks = numBlocks - numNoLockBlocks; Semaphore.Close(); - return Semaphore.Create((LONG)numLockBlocks, (LONG)numLockBlocks); + // we need (maxCount = 1), if we want to create non-use empty Semaphore + if (maxCount == 0) + maxCount = 1; + + // printf("\n Synchro.Create() \n"); + WRes wres; + #ifndef _WIN32 + wres = Synchro.Create(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + wres = Semaphore.Create(&Synchro, (UInt32)numLockBlocks, maxCount); + #else + wres = Semaphore.Create((UInt32)numLockBlocks, maxCount); + #endif + + return HRESULT_FROM_WIN32(wres); } + HRes CMemBlockManagerMt::AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks) { + // desiredNumberOfBlocks = 0; // for debug if (numNoLockBlocks > desiredNumberOfBlocks) return E_INVALIDARG; for (;;) { - if (AllocateSpace(desiredNumberOfBlocks, numNoLockBlocks) == 0) - return 0; + // if (desiredNumberOfBlocks == 0) return E_OUTOFMEMORY; + HRes hres = AllocateSpace(desiredNumberOfBlocks, numNoLockBlocks); + if (hres != E_OUTOFMEMORY) + return hres; if (desiredNumberOfBlocks == numNoLockBlocks) return E_OUTOFMEMORY; desiredNumberOfBlocks = numNoLockBlocks + ((desiredNumberOfBlocks - numNoLockBlocks) >> 1); @@ -91,7 +119,7 @@ void *CMemBlockManagerMt::AllocateBlock() void CMemBlockManagerMt::FreeBlock(void *p, bool lockMode) { - if (p == 0) + if (!p) return; { NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); @@ -101,6 +129,8 @@ void CMemBlockManagerMt::FreeBlock(void *p, bool lockMode) Semaphore.Release(); } + + void CMemBlocks::Free(CMemBlockManagerMt *manager) { while (Blocks.Size() > 0) @@ -122,9 +152,9 @@ HRESULT CMemBlocks::WriteToStream(size_t blockSize, ISequentialOutStream *outStr UInt64 totalSize = TotalSize; for (unsigned blockIndex = 0; totalSize > 0; blockIndex++) { - UInt32 curSize = (UInt32)blockSize; - if (totalSize < curSize) - curSize = (UInt32)totalSize; + size_t curSize = blockSize; + if (curSize > totalSize) + curSize = (size_t)totalSize; if (blockIndex >= Blocks.Size()) return E_FAIL; RINOK(WriteStream(outStream, Blocks[blockIndex], curSize)); @@ -134,10 +164,10 @@ HRESULT CMemBlocks::WriteToStream(size_t blockSize, ISequentialOutStream *outStr } -void CMemLockBlocks::FreeBlock(int index, CMemBlockManagerMt *memManager) +void CMemLockBlocks::FreeBlock(unsigned index, CMemBlockManagerMt *memManager) { memManager->FreeBlock(Blocks[index], LockMode); - Blocks[index] = 0; + Blocks[index] = NULL; } void CMemLockBlocks::Free(CMemBlockManagerMt *memManager) @@ -150,6 +180,7 @@ void CMemLockBlocks::Free(CMemBlockManagerMt *memManager) TotalSize = 0; } +/* HRes CMemLockBlocks::SwitchToNoLockMode(CMemBlockManagerMt *memManager) { if (LockMode) @@ -162,13 +193,14 @@ HRes CMemLockBlocks::SwitchToNoLockMode(CMemBlockManagerMt *memManager) } return 0; } +*/ void CMemLockBlocks::Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager) { blocks.Free(memManager); blocks.LockMode = LockMode; UInt64 totalSize = 0; - size_t blockSize = memManager->GetBlockSize(); + const size_t blockSize = memManager->GetBlockSize(); FOR_VECTOR (i, Blocks) { if (totalSize < TotalSize) diff --git a/CPP/7zip/Common/MemBlocks.h b/CPP/7zip/Common/MemBlocks.h index ec56c14d..3c9cefdb 100644 --- a/CPP/7zip/Common/MemBlocks.h +++ b/CPP/7zip/Common/MemBlocks.h @@ -15,10 +15,10 @@ class CMemBlockManager size_t _blockSize; void *_headFree; public: - CMemBlockManager(size_t blockSize = (1 << 20)): _data(0), _blockSize(blockSize), _headFree(0) {} + CMemBlockManager(size_t blockSize = (1 << 20)): _data(NULL), _blockSize(blockSize), _headFree(NULL) {} ~CMemBlockManager() { FreeSpace(); } - bool AllocateSpace(size_t numBlocks); + bool AllocateSpace_bool(size_t numBlocks); void FreeSpace(); size_t GetBlockSize() const { return _blockSize; } void *AllocateBlock(); @@ -30,17 +30,18 @@ class CMemBlockManagerMt: public CMemBlockManager { NWindows::NSynchronization::CCriticalSection _criticalSection; public: - NWindows::NSynchronization::CSemaphore Semaphore; + SYNC_OBJ_DECL(Synchro); + NWindows::NSynchronization::CSemaphore_WFMO Semaphore; CMemBlockManagerMt(size_t blockSize = (1 << 20)): CMemBlockManager(blockSize) {} ~CMemBlockManagerMt() { FreeSpace(); } - HRes AllocateSpace(size_t numBlocks, size_t numNoLockBlocks = 0); + HRes AllocateSpace(size_t numBlocks, size_t numNoLockBlocks); HRes AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks = 0); void FreeSpace(); void *AllocateBlock(); void FreeBlock(void *p, bool lockMode = true); - HRes ReleaseLockedBlocks(int number) { return Semaphore.Release(number); } + // WRes ReleaseLockedBlocks_WRes(unsigned number) { return Semaphore.Release(number); } }; @@ -63,8 +64,8 @@ struct CMemLockBlocks: public CMemBlocks CMemLockBlocks(): LockMode(true) {}; void Free(CMemBlockManagerMt *memManager); - void FreeBlock(int index, CMemBlockManagerMt *memManager); - HRes SwitchToNoLockMode(CMemBlockManagerMt *memManager); + void FreeBlock(unsigned index, CMemBlockManagerMt *memManager); + // HRes SwitchToNoLockMode(CMemBlockManagerMt *memManager); void Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager); }; diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp index 8a6ebcaf..bea51db3 100644 --- a/CPP/7zip/Common/MethodProps.cpp +++ b/CPP/7zip/Common/MethodProps.cpp @@ -184,10 +184,12 @@ class CCoderProps unsigned _numProps; unsigned _numPropsMax; public: - CCoderProps(unsigned numPropsMax) + CCoderProps(unsigned numPropsMax): + _propIDs(NULL), + _props(NULL), + _numProps(0), + _numPropsMax(numPropsMax) { - _numPropsMax = numPropsMax; - _numProps = 0; _propIDs = new PROPID[numPropsMax]; _props = new NCOM::CPropVariant[numPropsMax]; } @@ -214,7 +216,15 @@ void CCoderProps::AddProp(const CProp &prop) HRESULT CProps::SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const { - CCoderProps coderProps(Props.Size() + (dataSizeReduce ? 1 : 0)); + return SetCoderProps_DSReduce_Aff(scp, dataSizeReduce, NULL); +} + +HRESULT CProps::SetCoderProps_DSReduce_Aff( + ICompressSetCoderProperties *scp, + const UInt64 *dataSizeReduce, + const UInt64 *affinity) const +{ + CCoderProps coderProps(Props.Size() + (dataSizeReduce ? 1 : 0) + (affinity ? 1 : 0) ); FOR_VECTOR (i, Props) coderProps.AddProp(Props[i]); if (dataSizeReduce) @@ -224,27 +234,34 @@ HRESULT CProps::SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *da prop.Value = *dataSizeReduce; coderProps.AddProp(prop); } + if (affinity) + { + CProp prop; + prop.Id = NCoderPropID::kAffinity; + prop.Value = *affinity; + coderProps.AddProp(prop); + } return coderProps.SetProps(scp); } int CMethodProps::FindProp(PROPID id) const { - for (int i = Props.Size() - 1; i >= 0; i--) - if (Props[i].Id == id) + for (int i = (int)Props.Size() - 1; i >= 0; i--) + if (Props[(unsigned)i].Id == id) return i; return -1; } -int CMethodProps::GetLevel() const +unsigned CMethodProps::GetLevel() const { int i = FindProp(NCoderPropID::kLevel); if (i < 0) return 5; - if (Props[i].Value.vt != VT_UI4) + if (Props[(unsigned)i].Value.vt != VT_UI4) return 9; - UInt32 level = Props[i].Value.ulVal; - return level > 9 ? 9 : (int)level; + UInt32 level = Props[(unsigned)i].Value.ulVal; + return level > 9 ? 9 : (unsigned)level; } struct CNameToPropID @@ -286,7 +303,7 @@ static int FindPropIdExact(const UString &name) { for (unsigned i = 0; i < ARRAY_SIZE(g_NameToPropID); i++) if (StringsAreEqualNoCase_Ascii(name, g_NameToPropID[i].Name)) - return i; + return (int)i; return -1; } @@ -346,8 +363,8 @@ static void SplitParam(const UString ¶m, UString &name, UString &value) int eqPos = param.Find(L'='); if (eqPos >= 0) { - name.SetFrom(param, eqPos); - value = param.Ptr(eqPos + 1); + name.SetFrom(param, (unsigned)eqPos); + value = param.Ptr((unsigned)(eqPos + 1)); return; } unsigned i; @@ -382,7 +399,7 @@ HRESULT CMethodProps::SetParam(const UString &name, const UString &value) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index]; CProp prop; - prop.Id = index; + prop.Id = (unsigned)index; if (IsLogSizeProp(prop.Id)) { @@ -463,7 +480,7 @@ HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index]; CProp prop; - prop.Id = index; + prop.Id = (unsigned)index; if (IsLogSizeProp(prop.Id)) { @@ -485,14 +502,14 @@ HRESULT COneMethodInfo::ParseMethodFromString(const UString &s) { UString temp = s; if (splitPos >= 0) - temp.DeleteFrom(splitPos); + temp.DeleteFrom((unsigned)splitPos); if (!temp.IsAscii()) return E_INVALIDARG; MethodName.SetFromWStr_if_Ascii(temp); } if (splitPos < 0) return S_OK; - PropsString = s.Ptr(splitPos + 1); + PropsString = s.Ptr((unsigned)(splitPos + 1)); return ParseParamsFromString(PropsString); } diff --git a/CPP/7zip/Common/MethodProps.h b/CPP/7zip/Common/MethodProps.h index 39580881..e0519b16 100644 --- a/CPP/7zip/Common/MethodProps.h +++ b/CPP/7zip/Common/MethodProps.h @@ -53,20 +53,21 @@ struct CProps prop.Value = s; } - HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const; + HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce = NULL) const; + HRESULT SetCoderProps_DSReduce_Aff(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce, const UInt64 *affinity) const; }; class CMethodProps: public CProps { HRESULT SetParam(const UString &name, const UString &value); public: - int GetLevel() const; + unsigned GetLevel() const; int Get_NumThreads() const { int i = FindProp(NCoderPropID::kNumThreads); if (i >= 0) - if (Props[i].Value.vt == VT_UI4) - return (int)Props[i].Value.ulVal; + if (Props[(unsigned)i].Value.vt == VT_UI4) + return (int)Props[(unsigned)i].Value.ulVal; return -1; } @@ -75,9 +76,9 @@ public: res = 0; int i = FindProp(NCoderPropID::kDictionarySize); if (i >= 0) - if (Props[i].Value.vt == VT_UI4) + if (Props[(unsigned)i].Value.vt == VT_UI4) { - res = Props[i].Value.ulVal; + res = Props[(unsigned)i].Value.ulVal; return true; } return false; @@ -89,8 +90,8 @@ public: { int i = FindProp(NCoderPropID::kAlgorithm); if (i >= 0) - if (Props[i].Value.vt == VT_UI4) - return Props[i].Value.ulVal; + if (Props[(unsigned)i].Value.vt == VT_UI4) + return Props[(unsigned)i].Value.ulVal; return GetLevel() >= 5 ? 1 : 0; } @@ -98,10 +99,14 @@ public: { int i = FindProp(NCoderPropID::kDictionarySize); if (i >= 0) - if (Props[i].Value.vt == VT_UI4) - return Props[i].Value.ulVal; - int level = GetLevel(); - return level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)); + if (Props[(unsigned)i].Value.vt == VT_UI4) + return Props[(unsigned)i].Value.ulVal; + unsigned level = GetLevel(); + return + ( level <= 3 ? (1 << (level * 2 + 16)) : + ( level <= 6 ? (1 << (level + 19)) : + ( level <= 7 ? (1 << 25) : (1 << 26) + ))); } bool Get_Lzma_Eos() const @@ -109,7 +114,7 @@ public: int i = FindProp(NCoderPropID::kEndMarker); if (i >= 0) { - const NWindows::NCOM::CPropVariant &val = Props[i].Value; + const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_BOOL) return VARIANT_BOOLToBool(val.boolVal); } @@ -150,7 +155,7 @@ public: int i = FindProp(id); if (i >= 0) { - const NWindows::NCOM::CPropVariant &val = Props[i].Value; + const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_UI4) { return val.ulVal; } if (val.vt == VT_UI8) { return val.uhVal.QuadPart; } } @@ -191,8 +196,8 @@ public: fixedNumber = true; if (numThreads < 1) return 1; const unsigned kNumBZip2ThreadsMax = 64; - if (numThreads > kNumBZip2ThreadsMax) return kNumBZip2ThreadsMax; - return numThreads; + if ((unsigned)numThreads > kNumBZip2ThreadsMax) return kNumBZip2ThreadsMax; + return (unsigned)numThreads; } return 1; } @@ -201,16 +206,16 @@ public: { int i = FindProp(NCoderPropID::kDictionarySize); if (i >= 0) - if (Props[i].Value.vt == VT_UI4) + if (Props[(unsigned)i].Value.vt == VT_UI4) { - UInt32 blockSize = Props[i].Value.ulVal; + UInt32 blockSize = Props[(unsigned)i].Value.ulVal; const UInt32 kDicSizeMin = 100000; const UInt32 kDicSizeMax = 900000; if (blockSize < kDicSizeMin) blockSize = kDicSizeMin; if (blockSize > kDicSizeMax) blockSize = kDicSizeMax; return blockSize; } - int level = GetLevel(); + unsigned level = GetLevel(); return 100000 * (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1)); } @@ -218,10 +223,10 @@ public: { int i = FindProp(NCoderPropID::kUsedMemorySize); if (i >= 0) - if (Props[i].Value.vt == VT_UI4) - return Props[i].Value.ulVal; - int level = GetLevel(); - return level >= 9 ? (192 << 20) : ((UInt32)1 << (level + 19)); + if (Props[(unsigned)i].Value.vt == VT_UI4) + return Props[(unsigned)i].Value.ulVal; + unsigned level = GetLevel(); + return ((UInt32)1 << (level + 19)); } void AddProp_Level(UInt32 level) diff --git a/CPP/7zip/Common/OffsetStream.cpp b/CPP/7zip/Common/OffsetStream.cpp index 368d39b6..b3e710f9 100644 --- a/CPP/7zip/Common/OffsetStream.cpp +++ b/CPP/7zip/Common/OffsetStream.cpp @@ -10,7 +10,7 @@ HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset) { _offset = offset; _stream = stream; - return _stream->Seek(offset, STREAM_SEEK_SET, NULL); + return _stream->Seek((Int64)offset, STREAM_SEEK_SET, NULL); } STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) diff --git a/CPP/7zip/Common/OutMemStream.cpp b/CPP/7zip/Common/OutMemStream.cpp index 768c2d45..241589d2 100644 --- a/CPP/7zip/Common/OutMemStream.cpp +++ b/CPP/7zip/Common/OutMemStream.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +// #include <stdio.h> + #include "OutMemStream.h" void COutMemStream::Free() @@ -34,11 +36,12 @@ HRESULT COutMemStream::WriteToRealStream() return S_OK; } + STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (_realStreamMode) return OutSeqStream->Write(data, size, processedSize); - if (processedSize != 0) + if (processedSize) *processedSize = 0; while (size != 0) { @@ -49,7 +52,7 @@ STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *process if (size < curSize) curSize = size; memcpy(p, data, curSize); - if (processedSize != 0) + if (processedSize) *processedSize += (UInt32)curSize; data = (const void *)((const Byte *)data + curSize); size -= (UInt32)curSize; @@ -65,8 +68,14 @@ STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *process } continue; } - HANDLE events[3] = { StopWritingEvent, WriteToRealStreamEvent, /* NoLockEvent, */ _memManager->Semaphore }; - DWORD waitResult = ::WaitForMultipleObjects((Blocks.LockMode ? 3 : 2), events, FALSE, INFINITE); + + const NWindows::NSynchronization::CHandle_WFMO events[3] = + { StopWritingEvent, WriteToRealStreamEvent, /* NoLockEvent, */ _memManager->Semaphore }; + const DWORD waitResult = NWindows::NSynchronization::WaitForMultiObj_Any_Infinite( + ((Blocks.LockMode /* && _memManager->Semaphore.IsCreated() */) ? 3 : 2), events); + + // printf("\n 1- outMemStream %d\n", waitResult - WAIT_OBJECT_0); + switch (waitResult) { case (WAIT_OBJECT_0 + 0): @@ -77,27 +86,34 @@ STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *process RINOK(WriteToRealStream()); UInt32 processedSize2; HRESULT res = OutSeqStream->Write(data, size, &processedSize2); - if (processedSize != 0) + if (processedSize) *processedSize += processedSize2; return res; } - /* case (WAIT_OBJECT_0 + 2): { // it has bug: no write. + /* if (!Blocks.SwitchToNoLockMode(_memManager)) return E_FAIL; + */ break; } - */ - case (WAIT_OBJECT_0 + 2): - break; default: + { + if (waitResult == WAIT_FAILED) + { + DWORD res = ::GetLastError(); + if (res != 0) + return HRESULT_FROM_WIN32(res); + } return E_FAIL; + } } - Blocks.Blocks.Add(_memManager->AllocateBlock()); - if (Blocks.Blocks.Back() == 0) + void *p = _memManager->AllocateBlock(); + if (!p) return E_FAIL; + Blocks.Blocks.Add(p); } return S_OK; } diff --git a/CPP/7zip/Common/OutMemStream.h b/CPP/7zip/Common/OutMemStream.h index 0a892c52..873742ed 100644 --- a/CPP/7zip/Common/OutMemStream.h +++ b/CPP/7zip/Common/OutMemStream.h @@ -17,8 +17,8 @@ class COutMemStream: bool _realStreamMode; bool _unlockEventWasSent; - NWindows::NSynchronization::CAutoResetEvent StopWritingEvent; - NWindows::NSynchronization::CAutoResetEvent WriteToRealStreamEvent; + NWindows::NSynchronization::CAutoResetEvent_WFMO StopWritingEvent; + NWindows::NSynchronization::CAutoResetEvent_WFMO WriteToRealStreamEvent; // NWindows::NSynchronization::CAutoResetEvent NoLockEvent; HRESULT StopWriteResult; @@ -31,10 +31,13 @@ class COutMemStream: public: - HRes CreateEvents() + + HRes CreateEvents(SYNC_PARAM_DECL(synchro)) { - RINOK(StopWritingEvent.CreateIfNotCreated()); - return WriteToRealStreamEvent.CreateIfNotCreated(); + WRes wres = StopWritingEvent.CreateIfNotCreated_Reset(SYNC_WFMO(synchro)); + if (wres == 0) + wres = WriteToRealStreamEvent.CreateIfNotCreated_Reset(SYNC_WFMO(synchro)); + return HRESULT_FROM_WIN32(wres); } void SetOutStream(IOutStream *outStream) @@ -55,7 +58,16 @@ public: OutSeqStream.Release(); } - COutMemStream(CMemBlockManagerMt *memManager): _memManager(memManager) { } + COutMemStream(CMemBlockManagerMt *memManager): + _memManager(memManager) + { + /* + #ifndef _WIN32 + StopWritingEvent._sync = + WriteToRealStreamEvent._sync = &memManager->Synchro; + #endif + */ + } ~COutMemStream() { Free(); } void Free(); diff --git a/CPP/7zip/Common/ProgressMt.cpp b/CPP/7zip/Common/ProgressMt.cpp index 319bd241..c2714a27 100644 --- a/CPP/7zip/Common/ProgressMt.cpp +++ b/CPP/7zip/Common/ProgressMt.cpp @@ -4,12 +4,12 @@ #include "ProgressMt.h" -void CMtCompressProgressMixer::Init(int numItems, ICompressProgressInfo *progress) +void CMtCompressProgressMixer::Init(unsigned numItems, ICompressProgressInfo *progress) { NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection); InSizes.Clear(); OutSizes.Clear(); - for (int i = 0; i < numItems; i++) + for (unsigned i = 0; i < numItems; i++) { InSizes.Add(0); OutSizes.Add(0); @@ -19,23 +19,23 @@ void CMtCompressProgressMixer::Init(int numItems, ICompressProgressInfo *progres _progress = progress; } -void CMtCompressProgressMixer::Reinit(int index) +void CMtCompressProgressMixer::Reinit(unsigned index) { NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection); InSizes[index] = 0; OutSizes[index] = 0; } -HRESULT CMtCompressProgressMixer::SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize) +HRESULT CMtCompressProgressMixer::SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize) { NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection); - if (inSize != 0) + if (inSize) { UInt64 diff = *inSize - InSizes[index]; InSizes[index] = *inSize; TotalInSize += diff; } - if (outSize != 0) + if (outSize) { UInt64 diff = *outSize - OutSizes[index]; OutSizes[index] = *outSize; diff --git a/CPP/7zip/Common/ProgressMt.h b/CPP/7zip/Common/ProgressMt.h index 26079d4e..32da976b 100644 --- a/CPP/7zip/Common/ProgressMt.h +++ b/CPP/7zip/Common/ProgressMt.h @@ -19,9 +19,9 @@ class CMtCompressProgressMixer UInt64 TotalOutSize; public: NWindows::NSynchronization::CCriticalSection CriticalSection; - void Init(int numItems, ICompressProgressInfo *progress); - void Reinit(int index); - HRESULT SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize); + void Init(unsigned numItems, ICompressProgressInfo *progress); + void Reinit(unsigned index); + HRESULT SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize); }; class CMtCompressProgress: @@ -29,9 +29,9 @@ class CMtCompressProgress: public CMyUnknownImp { CMtCompressProgressMixer *_progress; - int _index; + unsigned _index; public: - void Init(CMtCompressProgressMixer *progress, int index) + void Init(CMtCompressProgressMixer *progress, unsigned index) { _progress = progress; _index = index; diff --git a/CPP/7zip/Common/RegisterCodec.h b/CPP/7zip/Common/RegisterCodec.h index 7ddb7604..a942da7a 100644 --- a/CPP/7zip/Common/RegisterCodec.h +++ b/CPP/7zip/Common/RegisterCodec.h @@ -26,11 +26,11 @@ void RegisterCodec(const CCodecInfo *codecInfo) throw(); #define REGISTER_CODEC_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressCoder) #define REGISTER_CODEC_NAME(x) CRegisterCodec ## x -#define REGISTER_CODEC_VAR static const CCodecInfo g_CodecInfo = +#define REGISTER_CODEC_VAR(x) static const CCodecInfo g_CodecInfo_ ## x = #define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \ - REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \ - static REGISTER_CODEC_NAME(x) g_RegisterCodec; + REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo_ ## x); }}; \ + static REGISTER_CODEC_NAME(x) g_RegisterCodec_ ## x; #define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x @@ -43,7 +43,7 @@ void RegisterCodec(const CCodecInfo *codecInfo) throw(); #define REGISTER_CODEC_2(x, crDec, crEnc, id, name) \ - REGISTER_CODEC_VAR \ + REGISTER_CODEC_VAR(x) \ { crDec, crEnc, id, name, 1, false }; \ REGISTER_CODEC(x) @@ -67,19 +67,19 @@ void RegisterCodec(const CCodecInfo *codecInfo) throw(); { crDec, crEnc, id, name, 1, true } #define REGISTER_FILTER(x, crDec, crEnc, id, name) \ - REGISTER_CODEC_VAR \ + REGISTER_CODEC_VAR(x) \ REGISTER_FILTER_ITEM(crDec, crEnc, id, name); \ REGISTER_CODEC(x) #ifdef EXTRACT_ONLY #define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \ - REGISTER_FILTER_CREATE(CreateDec, clsDec) \ - REGISTER_FILTER(x, CreateDec, NULL, id, name) + REGISTER_FILTER_CREATE(x ## _CreateDec, clsDec) \ + REGISTER_FILTER(x, x ## _CreateDec, NULL, id, name) #else #define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \ - REGISTER_FILTER_CREATE(CreateDec, clsDec) \ - REGISTER_FILTER_CREATE(CreateEnc, clsEnc) \ - REGISTER_FILTER(x, CreateDec, CreateEnc, id, name) + REGISTER_FILTER_CREATE(x ## _CreateDec, clsDec) \ + REGISTER_FILTER_CREATE(x ## _CreateEnc, clsEnc) \ + REGISTER_FILTER(x, x ## _CreateDec, x ## _CreateEnc, id, name) #endif diff --git a/CPP/7zip/Common/StreamBinder.cpp b/CPP/7zip/Common/StreamBinder.cpp index 435440c6..fbf2a0de 100644 --- a/CPP/7zip/Common/StreamBinder.cpp +++ b/CPP/7zip/Common/StreamBinder.cpp @@ -14,7 +14,7 @@ class CBinderInStream: public: MY_UNKNOWN_IMP1(ISequentialInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - ~CBinderInStream() { _binder->CloseRead(); } + ~CBinderInStream() { _binder->CloseRead_CallOnce(); } CBinderInStream(CStreamBinder *binder): _binder(binder) {} }; @@ -37,19 +37,24 @@ STDMETHODIMP CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *proc { return _binder->Write(data, size, processedSize); } - -WRes CStreamBinder::CreateEvents() +static HRESULT Event__Create_or_Reset(NWindows::NSynchronization::CAutoResetEvent &event) { - RINOK(_canWrite_Event.Create()); - RINOK(_canRead_Event.Create()); - return _readingWasClosed_Event.Create(); + WRes wres; + if (event.IsCreated()) + wres = event.Reset(); + else + wres = event.Create(); + return HRESULT_FROM_WIN32(wres); } -void CStreamBinder::ReInit() +HRESULT CStreamBinder::Create_ReInit() { - _canWrite_Event.Reset(); - _canRead_Event.Reset(); - _readingWasClosed_Event.Reset(); + RINOK(Event__Create_or_Reset(_canRead_Event)); + // RINOK(Event__Create_or_Reset(_canWrite_Event)); + + _canWrite_Semaphore.Close(); + // we need at least 3 items of maxCount: 1 for normal unlock in Read(), 2 items for unlock in CloseRead_CallOnce() + _canWrite_Semaphore.Create(0, 3); // _readingWasClosed = false; _readingWasClosed2 = false; @@ -59,27 +64,14 @@ void CStreamBinder::ReInit() _buf = NULL; ProcessedSize = 0; // WritingWasCut = false; + return S_OK; } -void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream) +void CStreamBinder::CreateStreams2(CMyComPtr<ISequentialInStream> &inStream, CMyComPtr<ISequentialOutStream> &outStream) { - // _readingWasClosed = false; - _readingWasClosed2 = false; - - _waitWrite = true; - _bufSize = 0; - _buf = NULL; - ProcessedSize = 0; - // WritingWasCut = false; - - CBinderInStream *inStreamSpec = new CBinderInStream(this); - CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); - *inStream = inStreamLoc.Detach(); - - CBinderOutStream *outStreamSpec = new CBinderOutStream(this); - CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec); - *outStream = outStreamLoc.Detach(); + inStream = new CBinderInStream(this); + outStream = new CBinderOutStream(this); } // (_canRead_Event && _bufSize == 0) means that stream is finished. @@ -92,7 +84,9 @@ HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { if (_waitWrite) { - RINOK(_canRead_Event.Lock()); + WRes wres = _canRead_Event.Lock(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); _waitWrite = false; } if (size > _bufSize) @@ -105,17 +99,25 @@ HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) if (processedSize) *processedSize = size; _bufSize -= size; + + /* + if (_bufSize == 0), then we have read whole buffer + we have two ways here: + - if we check (_bufSize == 0) here, we unlock Write only after full data Reading - it reduces the number of syncs + - if we don't check (_bufSize == 0) here, we unlock Write after partial data Reading + */ if (_bufSize == 0) { _waitWrite = true; - _canRead_Event.Reset(); - _canWrite_Event.Set(); + // _canWrite_Event.Set(); + _canWrite_Semaphore.Release(); } } } return S_OK; } + HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) @@ -135,20 +137,20 @@ HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSiz _readingWasClosed2 = true; */ - HANDLE events[2] = { _canWrite_Event, _readingWasClosed_Event }; - DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); - if (waitResult >= WAIT_OBJECT_0 + 2) - return E_FAIL; + _canWrite_Semaphore.Lock(); + // _bufSize : is remain size that was not read size -= _bufSize; + + // size : is size of data that was read if (size != 0) { + // if some data was read, then we report that size and return if (processedSize) *processedSize = size; return S_OK; } - // if (waitResult == WAIT_OBJECT_0 + 1) - _readingWasClosed2 = true; + _readingWasClosed2 = true; } // WritingWasCut = true; diff --git a/CPP/7zip/Common/StreamBinder.h b/CPP/7zip/Common/StreamBinder.h index 12088a94..16c872fb 100644 --- a/CPP/7zip/Common/StreamBinder.h +++ b/CPP/7zip/Common/StreamBinder.h @@ -8,45 +8,63 @@ #include "../IStream.h" /* -We don't use probably UNSAFE version: -reader thread: +We can use one from two code versions here: with Event or with Semaphore to unlock Writer thread +The difference for cases where Reading must be closed before Writing closing + +1) Event Version: _canWrite_Event + We call _canWrite_Event.Set() without waiting _canRead_Event in CloseRead() function. + The writer thread can get (_readingWasClosed) status in one from two iterations. + It's ambiguity of processing flow. But probably it's SAFE to use, if Event functions provide memory barriers. + reader thread: _canWrite_Event.Set(); - _readingWasClosed = true + _readingWasClosed = true; _canWrite_Event.Set(); -writer thread: + writer thread: _canWrite_Event.Wait() if (_readingWasClosed) -Can second call of _canWrite_Event.Set() be executed without memory barrier, if event is already set? + +2) Semaphore Version: _canWrite_Semaphore + writer thread always will detect closing of reading in latest iteration after all data processing iterations */ class CStreamBinder { - NWindows::NSynchronization::CAutoResetEvent _canWrite_Event; - NWindows::NSynchronization::CManualResetEvent _canRead_Event; - NWindows::NSynchronization::CManualResetEvent _readingWasClosed_Event; + NWindows::NSynchronization::CAutoResetEvent _canRead_Event; + // NWindows::NSynchronization::CAutoResetEvent _canWrite_Event; + NWindows::NSynchronization::CSemaphore _canWrite_Semaphore; - // bool _readingWasClosed; - bool _readingWasClosed2; + // bool _readingWasClosed; // set it in reader thread and check it in write thread + bool _readingWasClosed2; // use it in writer thread // bool WritingWasCut; - bool _waitWrite; + bool _waitWrite; // use it in reader thread UInt32 _bufSize; const void *_buf; public: - UInt64 ProcessedSize; + UInt64 ProcessedSize; // the size that was read by reader thread - WRes CreateEvents(); - void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream); + void CreateStreams2(CMyComPtr<ISequentialInStream> &inStream, CMyComPtr<ISequentialOutStream> &outStream); - void ReInit(); + HRESULT Create_ReInit(); HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize); - void CloseRead() + void CloseRead_CallOnce() { - _readingWasClosed_Event.Set(); - // _readingWasClosed = true; - // _canWrite_Event.Set(); + // call it only once: for example, in destructor + + /* + _readingWasClosed = true; + _canWrite_Event.Set(); + */ + + /* + We must relase Semaphore only once !!! + we must release at least 2 items of Semaphore: + one item to unlock partial Write(), if Read() have read some items + then additional item to stop writing (_bufSize will be 0) + */ + _canWrite_Semaphore.Release(2); } void CloseWrite() diff --git a/CPP/7zip/Common/StreamObjects.cpp b/CPP/7zip/Common/StreamObjects.cpp index 8136716d..2d941df6 100644 --- a/CPP/7zip/Common/StreamObjects.cpp +++ b/CPP/7zip/Common/StreamObjects.cpp @@ -37,9 +37,9 @@ STDMETHODIMP CBufferInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newP } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _pos = offset; + _pos = (UInt64)offset; if (newPosition) - *newPosition = offset; + *newPosition = (UInt64)offset; return S_OK; } @@ -72,9 +72,9 @@ STDMETHODIMP CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosi } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _pos = offset; + _pos = (UInt64)offset; if (newPosition) - *newPosition = offset; + *newPosition = (UInt64)offset; return S_OK; } @@ -108,14 +108,10 @@ bool CByteDynBuffer::EnsureCapacity(size_t cap) throw() { if (cap <= _capacity) return true; - size_t delta; - if (_capacity > 64) - delta = _capacity / 4; - else if (_capacity > 8) - delta = 16; - else - delta = 4; - cap = MyMax(_capacity + delta, cap); + size_t delta = _capacity / 4; + size_t cap2 = _capacity + delta; + if (cap < cap2) + cap = cap2; Byte *buf = (Byte *)realloc(_buf, cap); if (!buf) return false; @@ -185,9 +181,9 @@ static const UInt64 kEmptyTag = (UInt64)(Int64)-1; void CCachedInStream::Free() throw() { MyFree(_tags); - _tags = 0; + _tags = NULL; MidFree(_data); - _data = 0; + _data = NULL; } bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw() @@ -196,19 +192,19 @@ bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw( if (sizeLog >= sizeof(size_t) * 8) return false; size_t dataSize = (size_t)1 << sizeLog; - if (_data == 0 || dataSize != _dataSize) + if (!_data || dataSize != _dataSize) { MidFree(_data); _data = (Byte *)MidAlloc(dataSize); - if (_data == 0) + if (!_data) return false; _dataSize = dataSize; } - if (_tags == 0 || numBlocksLog != _numBlocksLog) + if (!_tags || numBlocksLog != _numBlocksLog) { MyFree(_tags); _tags = (UInt64 *)MyAlloc(sizeof(UInt64) << numBlocksLog); - if (_tags == 0) + if (!_tags) return false; _numBlocksLog = numBlocksLog; } @@ -242,21 +238,32 @@ STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSiz while (size != 0) { - UInt64 cacheTag = _pos >> _blockSizeLog; - size_t cacheIndex = (size_t)cacheTag & (((size_t)1 << _numBlocksLog) - 1); + const UInt64 cacheTag = _pos >> _blockSizeLog; + const size_t cacheIndex = (size_t)cacheTag & (((size_t)1 << _numBlocksLog) - 1); Byte *p = _data + (cacheIndex << _blockSizeLog); + if (_tags[cacheIndex] != cacheTag) { + _tags[cacheIndex] = kEmptyTag; UInt64 remInBlock = _size - (cacheTag << _blockSizeLog); size_t blockSize = (size_t)1 << _blockSizeLog; if (blockSize > remInBlock) blockSize = (size_t)remInBlock; + RINOK(ReadBlock(cacheTag, p, blockSize)); + _tags[cacheIndex] = cacheTag; } - size_t offset = (size_t)_pos & (((size_t)1 << _blockSizeLog) - 1); - UInt32 cur = (UInt32)MyMin(((size_t)1 << _blockSizeLog) - offset, (size_t)size); + + const size_t kBlockSize = (size_t)1 << _blockSizeLog; + const size_t offset = (size_t)_pos & (kBlockSize - 1); + UInt32 cur = size; + const size_t rem = kBlockSize - offset; + if (cur > rem) + cur = (UInt32)rem; + memcpy(data, p + offset, cur); + if (processedSize) *processedSize += cur; data = (void *)((const Byte *)data + cur); @@ -266,6 +273,7 @@ STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSiz return S_OK; } + STDMETHODIMP CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { @@ -278,8 +286,8 @@ STDMETHODIMP CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newP } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _pos = offset; + _pos = (UInt64)offset; if (newPosition) - *newPosition = offset; + *newPosition = (UInt64)offset; return S_OK; } diff --git a/CPP/7zip/Common/StreamObjects.h b/CPP/7zip/Common/StreamObjects.h index e20e9bd8..a8fb229c 100644 --- a/CPP/7zip/Common/StreamObjects.h +++ b/CPP/7zip/Common/StreamObjects.h @@ -24,6 +24,7 @@ public: STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; + struct CReferenceBuf: public IUnknown, public CMyUnknownImp @@ -32,6 +33,7 @@ struct CReferenceBuf: MY_UNKNOWN_IMP }; + class CBufInStream: public IInStream, public CMyUnknownImp @@ -41,7 +43,7 @@ class CBufInStream: size_t _size; CMyComPtr<IUnknown> _ref; public: - void Init(const Byte *data, size_t size, IUnknown *ref = 0) + void Init(const Byte *data, size_t size, IUnknown *ref = NULL) { _data = data; _size = size; @@ -55,17 +57,20 @@ public: STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; + void Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream); void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream); inline void Create_BufInStream_WithNewBuffer(const CByteBuffer &buf, ISequentialInStream **stream) { Create_BufInStream_WithNewBuffer(buf, buf.Size(), stream); } + class CByteDynBuffer { size_t _capacity; Byte *_buf; + CLASS_NO_COPY(CByteDynBuffer); public: - CByteDynBuffer(): _capacity(0), _buf(0) {}; + CByteDynBuffer(): _capacity(0), _buf(NULL) {}; // there is no copy constructor. So don't copy this object. ~CByteDynBuffer() { Free(); } void Free() throw(); @@ -75,6 +80,7 @@ public: bool EnsureCapacity(size_t capacity) throw(); }; + class CDynBufSeqOutStream: public ISequentialOutStream, public CMyUnknownImp @@ -94,6 +100,7 @@ public: STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; + class CBufPtrSeqOutStream: public ISequentialOutStream, public CMyUnknownImp @@ -114,6 +121,7 @@ public: STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; + class CSequentialOutStreamSizeCount: public ISequentialOutStream, public CMyUnknownImp @@ -129,6 +137,7 @@ public: STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; + class CCachedInStream: public IInStream, public CMyUnknownImp @@ -143,7 +152,7 @@ class CCachedInStream: protected: virtual HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) = 0; public: - CCachedInStream(): _tags(0), _data(0) {} + CCachedInStream(): _tags(NULL), _data(NULL) {} virtual ~CCachedInStream() { Free(); } // the destructor must be virtual (release calls it) !!! void Free() throw(); bool Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw(); diff --git a/CPP/7zip/Common/UniqBlocks.h b/CPP/7zip/Common/UniqBlocks.h index a376024e..d6cd3728 100644 --- a/CPP/7zip/Common/UniqBlocks.h +++ b/CPP/7zip/Common/UniqBlocks.h @@ -19,7 +19,7 @@ struct CUniqBlocks bool IsOnlyEmpty() const { - return (Bufs.Size() == 0 || Bufs.Size() == 1 && Bufs[0].Size() == 0); + return (Bufs.Size() == 0 || (Bufs.Size() == 1 && Bufs[0].Size() == 0)); } }; diff --git a/CPP/7zip/Common/VirtThread.cpp b/CPP/7zip/Common/VirtThread.cpp index 77e3c1ac..bf24bb1c 100644 --- a/CPP/7zip/Common/VirtThread.cpp +++ b/CPP/7zip/Common/VirtThread.cpp @@ -19,20 +19,20 @@ static THREAD_FUNC_DECL CoderThread(void *p) WRes CVirtThread::Create() { - RINOK(StartEvent.CreateIfNotCreated()); - RINOK(FinishedEvent.CreateIfNotCreated()); - StartEvent.Reset(); - FinishedEvent.Reset(); + RINOK_WRes(StartEvent.CreateIfNotCreated_Reset()); + RINOK_WRes(FinishedEvent.CreateIfNotCreated_Reset()); + // StartEvent.Reset(); + // FinishedEvent.Reset(); Exit = false; if (Thread.IsCreated()) return S_OK; return Thread.Create(CoderThread, this); } -void CVirtThread::Start() +WRes CVirtThread::Start() { Exit = false; - StartEvent.Set(); + return StartEvent.Set(); } void CVirtThread::WaitThreadFinish() @@ -42,7 +42,6 @@ void CVirtThread::WaitThreadFinish() StartEvent.Set(); if (Thread.IsCreated()) { - Thread.Wait(); - Thread.Close(); + Thread.Wait_Close(); } } diff --git a/CPP/7zip/Common/VirtThread.h b/CPP/7zip/Common/VirtThread.h index ebee158c..b4d8a5a9 100644 --- a/CPP/7zip/Common/VirtThread.h +++ b/CPP/7zip/Common/VirtThread.h @@ -16,9 +16,9 @@ struct CVirtThread ~CVirtThread() { WaitThreadFinish(); } void WaitThreadFinish(); // call it in destructor of child class ! WRes Create(); - void Start(); + WRes Start(); virtual void Execute() = 0; - void WaitExecuteFinish() { FinishedEvent.Lock(); } + WRes WaitExecuteFinish() { return FinishedEvent.Lock(); } }; #endif diff --git a/CPP/7zip/Compress/BZip2Const.h b/CPP/7zip/Compress/BZip2Const.h index 0efecba3..7927d018 100644 --- a/CPP/7zip/Compress/BZip2Const.h +++ b/CPP/7zip/Compress/BZip2Const.h @@ -55,10 +55,15 @@ The number of selectors stored in bzip2 block: (numSelectors <= 18001) - must work with any decoder. (numSelectors == 18002) - works with bzip2 1.0.6 decoder and all derived decoders. (numSelectors > 18002) - 7-Zip decoder doesn't support it. - bzip2 1.0.6 decoder can overflow selector[18002] arrays. But there are another + lbzip2 2.5: encoder can write up to (18001 + 7) selectors. + + 7-Zip before 19.03: decoder doesn't support it. + 7-Zip 19.03: decoder allows 8 additional selector records for lbzip2 compatibility. + + bzip2 1.0.6: decoder can overflow selector[18002] arrays. But there are another arrays after selector arrays. So the compiled code works. - lbzip2 2.5 encoder can write up to (18001 + 7) selectors. + bzip2 1.0.7: decoder doesn't support it. + bzip2 1.0.8: decoder allows additional selector records for lbzip2 compatibility. */ }} diff --git a/CPP/7zip/Compress/BZip2Crc.cpp b/CPP/7zip/Compress/BZip2Crc.cpp index bf8e540f..9639c7b7 100644 --- a/CPP/7zip/Compress/BZip2Crc.cpp +++ b/CPP/7zip/Compress/BZip2Crc.cpp @@ -19,6 +19,7 @@ void CBZip2Crc::InitTable() } } +static class CBZip2CrcTableInit { public: diff --git a/CPP/7zip/Compress/BZip2Decoder.cpp b/CPP/7zip/Compress/BZip2Decoder.cpp index b414d088..c09c160e 100644 --- a/CPP/7zip/Compress/BZip2Decoder.cpp +++ b/CPP/7zip/Compress/BZip2Decoder.cpp @@ -20,7 +20,6 @@ #define PRIN(s) #define PRIN_VAL(s, val) -#define PRIN_MT(s) PRIN(" " s) #include "../../../C/Alloc.h" @@ -183,10 +182,10 @@ SRes CBase::ReadStreamSignature2() unsigned b; READ_BITS_8(b, 8); - if ( state2 == 0 && b != kArSig0 - || state2 == 1 && b != kArSig1 - || state2 == 2 && b != kArSig2 - || state2 == 3 && (b <= kArSig3 || b > kArSig3 + kBlockSizeMultMax)) + if ( (state2 == 0 && b != kArSig0) + || (state2 == 1 && b != kArSig1) + || (state2 == 2 && b != kArSig2) + || (state2 == 3 && (b <= kArSig3 || b > kArSig3 + kBlockSizeMultMax))) return SZ_ERROR_DATA; state2++; @@ -342,7 +341,11 @@ SRes CBase::ReadBlock2() state2 = 0x543210; state3 = 0; state4 = 0; - if (numSelectors == 0 || numSelectors > kNumSelectorsMax) + // lbzip2 can write small number of additional selectors, + // 20.01: we allow big number of selectors here like bzip2-1.0.8 + if (numSelectors == 0 + // || numSelectors > kNumSelectorsMax_Decoder + ) return SZ_ERROR_DATA; } @@ -365,10 +368,19 @@ SRes CBase::ReadBlock2() UInt32 mask = ((UInt32)1 << ((state4 + 1) * kMtfBits)) - 1; state4 = 0; state2 = ((state2 << kMtfBits) & mask) | (state2 & ~mask) | tmp; - selectors[state3] = (Byte)tmp; + // 20.01: here we keep compatibility with bzip2-1.0.8 decoder: + if (state3 < kNumSelectorsMax) + selectors[state3] = (Byte)tmp; } while (++state3 < numSelectors); + // we allowed additional dummy selector records filled above to support lbzip2's archives. + // but we still don't allow to use these additional dummy selectors in the code bellow + // bzip2 1.0.8 decoder also has similar restriction. + + if (numSelectors > kNumSelectorsMax) + numSelectors = kNumSelectorsMax; + state = STATE_LEVELS; state2 = 0; state3 = 0; @@ -412,14 +424,15 @@ SRes CBase::ReadBlock2() state5 = 0; } + // 19.03: we use Build() instead of BuildFull() to support lbzip2 archives // lbzip2 2.5 can produce dummy tree, where lens[i] = kMaxHuffmanLen // BuildFull() returns error for such tree - /* for (unsigned i = state4; i < kMaxAlphaSize; i++) lens[i] = 0; if (!huffs[state2].Build(lens)) - */ + /* if (!huffs[state2].BuildFull(lens, state4)) + */ return SZ_ERROR_DATA; state3 = 0; } @@ -476,10 +489,11 @@ SRes CBase::ReadBlock2() val = VAL >> (32 - kMaxHuffmanLen); unsigned len; for (len = kNumTableBits + 1; val >= huff->_limits[len]; len++); - /* + + // 19.03: we use that check to support partial trees created Build() for lbzip2 archives if (len > kNumBitsMax) return SZ_ERROR_DATA; // that check is required, if NHuffman::Build() was used instead of BuildFull() - */ + if (_numBits < len) { SAVE_LOCAL @@ -769,7 +783,7 @@ Byte * CSpecState::Decode(Byte *data, size_t size) throw() continue; } - reps = b; + reps = (int)b; while (reps) { reps--; @@ -802,7 +816,7 @@ Byte * CSpecState::Decode(Byte *data, size_t size) throw() _randToGo--; } - reps = b; + reps = (int)b; } _tPos = tPos; @@ -857,7 +871,7 @@ HRESULT CDecoder::DecodeBlock(const CBlockProps &props) } TICKS_START - const size_t processed = block.Decode(data, size) - data; + const size_t processed = (size_t)(block.Decode(data, size) - data); TICKS_UPDATE(2) _outPosTotal += processed; @@ -879,11 +893,12 @@ HRESULT CDecoder::DecodeBlock(const CBlockProps &props) CDecoder::CDecoder(): - _inBuf(NULL), _outBuf(NULL), - _counters(NULL), FinishMode(false), - _outSizeDefined(false) + _outSizeDefined(false), + _counters(NULL), + _inBuf(NULL), + _inProcessed(0) { #ifndef _7ZIP_ST MtMode = false; @@ -909,9 +924,8 @@ CDecoder::~CDecoder() ScoutEvent.Set(); PRIN("\nThread.Wait()()"); - Thread.Wait(); + Thread.Wait_Close(); PRIN("\n after Thread.Wait()()"); - Thread.Close(); // if (ScoutRes != S_OK) throw ScoutRes; } @@ -929,7 +943,7 @@ HRESULT CDecoder::ReadInput() if (Base._buf != Base._lim || _inputFinished || _inputRes != S_OK) return _inputRes; - _inProcessed += (Base._buf - _inBuf); + _inProcessed += (size_t)(Base._buf - _inBuf); Base._buf = _inBuf; Base._lim = _inBuf; UInt32 size = 0; @@ -1138,7 +1152,11 @@ HRESULT CDecoder::DecodeStreams(ICompressProgressInfo *progress) if (useMt) { PRIN("DecoderEvent.Lock()"); - RINOK(DecoderEvent.Lock()); + { + WRes wres = DecoderEvent.Lock(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + } NeedWaitScout = false; PRIN("-- DecoderEvent.Lock()"); props = _block.Props; @@ -1186,7 +1204,11 @@ HRESULT CDecoder::DecodeStreams(ICompressProgressInfo *progress) */ PRIN("ScoutEvent.Set()"); - RINOK(ScoutEvent.Set()); + { + WRes wres = ScoutEvent.Set(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + } NeedWaitScout = true; } #endif @@ -1219,14 +1241,17 @@ bool CDecoder::CreateInputBufer() _inBuf = (Byte *)MidAlloc(kInBufSize); if (!_inBuf) return false; + Base._buf = _inBuf; + Base._lim = _inBuf; } if (!_counters) { - _counters = (UInt32 *)::BigAlloc((256 + kBlockSizeMax) * sizeof(UInt32) + const size_t size = (256 + kBlockSizeMax) * sizeof(UInt32) #ifdef BZIP2_BYTE_MODE + kBlockSizeMax #endif - + 256); + + 256; + _counters = (UInt32 *)::BigAlloc(size); if (!_counters) return false; Base.Counters = _counters; @@ -1266,14 +1291,19 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream } */ - InitOutSize(outSize); - _inputFinished = false; _inputRes = S_OK; _writeRes = S_OK; try { + InitOutSize(outSize); + + // we can request data from InputBuffer after Code(). + // so we init InputBuffer before any function return. + + InitInputBuffer(); + if (!CreateInputBufer()) return E_OUTOFMEMORY; @@ -1286,7 +1316,7 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream Base.InStream = inStream; - InitInputBuffer(); + // InitInputBuffer(); _outStream = outStream; _outWritten = 0; @@ -1323,23 +1353,43 @@ STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode) STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { - *value = GetInputProcessedSize(); + *value = GetInStreamSize(); + return S_OK; +} + + +STDMETHODIMP CDecoder::ReadUnusedFromInBuf(void *data, UInt32 size, UInt32 *processedSize) +{ + Base.AlignToByte(); + UInt32 i; + for (i = 0; i < size; i++) + { + int b; + Base.ReadByte(b); + if (b < 0) + break; + ((Byte *)data)[i] = (Byte)b; + } + if (processedSize) + *processedSize = i; return S_OK; } #ifndef _7ZIP_ST -#define RINOK_THREAD(x) { WRes __result_ = (x); if (__result_ != 0) return __result_; } +#define PRIN_MT(s) PRIN(" " s) + +// #define RINOK_THREAD(x) { WRes __result_ = (x); if (__result_ != 0) return __result_; } static THREAD_FUNC_DECL RunScout2(void *p) { ((CDecoder *)p)->RunScout(); return 0; } HRESULT CDecoder::CreateThread() { - RINOK_THREAD(DecoderEvent.CreateIfNotCreated()); - RINOK_THREAD(ScoutEvent.CreateIfNotCreated()); - RINOK_THREAD(Thread.Create(RunScout2, this)); - return S_OK; + WRes wres = DecoderEvent.CreateIfNotCreated_Reset(); + if (wres == 0) { wres = ScoutEvent.CreateIfNotCreated_Reset(); + if (wres == 0) { wres = Thread.Create(RunScout2, this); }} + return HRESULT_FROM_WIN32(wres); } void CDecoder::RunScout() @@ -1512,10 +1562,12 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { InitOutSize(outSize); + InitInputBuffer(); + if (!CreateInputBufer()) return E_OUTOFMEMORY; - InitInputBuffer(); + // InitInputBuffer(); StartNewStream(); diff --git a/CPP/7zip/Compress/BZip2Decoder.h b/CPP/7zip/Compress/BZip2Decoder.h index 68aa7094..8fe4ef1b 100644 --- a/CPP/7zip/Compress/BZip2Decoder.h +++ b/CPP/7zip/Compress/BZip2Decoder.h @@ -73,9 +73,19 @@ struct CBitDecoder */ SRes ReadByte(int &b); + + CBitDecoder(): + _buf(NULL), + _lim(NULL) + { + InitBitDecoder(); + } }; +// 19.03: we allow additional 8 selectors to support files created by lbzip2. +const UInt32 kNumSelectorsMax_Decoder = kNumSelectorsMax + 8; + struct CBase: public CBitDecoder { unsigned numInUse; @@ -100,7 +110,7 @@ struct CBase: public CBitDecoder private: CMtf8Decoder mtf; - Byte selectors[kNumSelectorsMax]; + Byte selectors[kNumSelectorsMax_Decoder]; CHuffmanDecoder huffs[kNumTablesMax]; Byte lens[kMaxAlphaSize]; @@ -188,6 +198,7 @@ class CDecoder : public ICompressCoder, public ICompressSetFinishMode, public ICompressGetInStreamProcessedSize, + public ICompressReadUnusedFromInBuf, #ifndef NO_READ_FROM_CODER public ICompressSetInStream, @@ -293,6 +304,8 @@ public: void InitInputBuffer() { + // We use InitInputBuffer() before stream init. + // So don't read from stream here _inProcessed = 0; Base._buf = _inBuf; Base._lim = _inBuf; @@ -302,7 +315,12 @@ public: UInt64 GetInputProcessedSize() const { // for NSIS case : we need also look the number of bits in bitDecoder - return _inProcessed + (Base._buf - _inBuf); + return _inProcessed + (size_t)(Base._buf - _inBuf); + } + + UInt64 GetInStreamSize() const + { + return _inProcessed + (size_t)(Base._buf - _inBuf) - (Base._numBits >> 3); } UInt64 GetOutProcessedSize() const { return _outWritten + _outPos; } @@ -324,6 +342,7 @@ public: MY_QUERYINTERFACE_BEGIN2(ICompressCoder) MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode) MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize) + MY_QUERYINTERFACE_ENTRY(ICompressReadUnusedFromInBuf) #ifndef NO_READ_FROM_CODER MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) @@ -344,6 +363,7 @@ public: STDMETHOD(SetFinishMode)(UInt32 finishMode); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); + STDMETHOD(ReadUnusedFromInBuf)(void *data, UInt32 size, UInt32 *processedSize); UInt64 GetNumStreams() const { return Base.NumStreams; } UInt64 GetNumBlocks() const { return Base.NumBlocks; } diff --git a/CPP/7zip/Compress/BZip2Encoder.cpp b/CPP/7zip/Compress/BZip2Encoder.cpp index c9f9c664..25c3f045 100644 --- a/CPP/7zip/Compress/BZip2Encoder.cpp +++ b/CPP/7zip/Compress/BZip2Encoder.cpp @@ -20,17 +20,17 @@ static const unsigned kNumHuffPasses = 4; bool CThreadInfo::Alloc() { - if (m_BlockSorterIndex == 0) + if (!m_BlockSorterIndex) { m_BlockSorterIndex = (UInt32 *)::BigAlloc(BLOCK_SORT_BUF_SIZE(kBlockSizeMax) * sizeof(UInt32)); - if (m_BlockSorterIndex == 0) + if (!m_BlockSorterIndex) return false; } - if (m_Block == 0) + if (!m_Block) { m_Block = (Byte *)::MidAlloc(kBlockSizeMax * 5 + kBlockSizeMax / 10 + (20 << 10)); - if (m_Block == 0) + if (!m_Block) return false; m_MtfArray = m_Block + kBlockSizeMax; m_TempArray = m_MtfArray + kBlockSizeMax * 2 + 2; @@ -41,9 +41,9 @@ bool CThreadInfo::Alloc() void CThreadInfo::Free() { ::BigFree(m_BlockSorterIndex); - m_BlockSorterIndex = 0; + m_BlockSorterIndex = NULL; ::MidFree(m_Block); - m_Block = 0; + m_Block = NULL; } #ifndef _7ZIP_ST @@ -53,15 +53,19 @@ static THREAD_FUNC_DECL MFThread(void *threadCoderInfo) return ((CThreadInfo *)threadCoderInfo)->ThreadFunc(); } -#define RINOK_THREAD(x) { WRes __result_ = (x); if (__result_ != 0) return __result_; } - HRESULT CThreadInfo::Create() { - RINOK_THREAD(StreamWasFinishedEvent.Create()); - RINOK_THREAD(WaitingWasStartedEvent.Create()); - RINOK_THREAD(CanWriteEvent.Create()); - RINOK_THREAD(Thread.Create(MFThread, this)); - return S_OK; + WRes wres = StreamWasFinishedEvent.Create(); + if (wres == 0) { wres = WaitingWasStartedEvent.Create(); + if (wres == 0) { wres = CanWriteEvent.Create(); + if (wres == 0) + { + if (Encoder->_props.Affinity != 0) + wres = Thread.Create_With_Affinity(MFThread, this, (CAffinityMask)Encoder->_props.Affinity); + else + wres = Thread.Create(MFThread, this); + }}} + return HRESULT_FROM_WIN32(wres); } void CThreadInfo::FinishStream(bool needLeave) @@ -74,7 +78,7 @@ void CThreadInfo::FinishStream(bool needLeave) WaitingWasStartedEvent.Set(); } -DWORD CThreadInfo::ThreadFunc() +THREAD_FUNC_RET_TYPE CThreadInfo::ThreadFunc() { for (;;) { @@ -133,7 +137,7 @@ void CEncProps::Normalize(int level) if (NumPasses > kNumPassesMax) NumPasses = kNumPassesMax; if (BlockSizeMult == (UInt32)(Int32)-1) - BlockSizeMult = (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1)); + BlockSizeMult = (level >= 5 ? 9 : (level >= 1 ? (unsigned)level * 2 - 1: 1)); if (BlockSizeMult < kBlockSizeMultMin) BlockSizeMult = kBlockSizeMultMin; if (BlockSizeMult > kBlockSizeMultMax) BlockSizeMult = kBlockSizeMultMax; } @@ -143,7 +147,7 @@ CEncoder::CEncoder() _props.Normalize(-1); #ifndef _7ZIP_ST - ThreadsInfo = 0; + ThreadsInfo = NULL; m_NumThreadsPrev = 0; NumThreads = 1; #endif @@ -157,9 +161,14 @@ CEncoder::~CEncoder() HRESULT CEncoder::Create() { - RINOK_THREAD(CanProcessEvent.CreateIfNotCreated()); - RINOK_THREAD(CanStartWaitingEvent.CreateIfNotCreated()); - if (ThreadsInfo != 0 && m_NumThreadsPrev == NumThreads) + { + WRes wres = CanProcessEvent.CreateIfNotCreated_Reset(); + if (wres == 0) { wres = CanStartWaitingEvent.CreateIfNotCreated_Reset(); } + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + } + + if (ThreadsInfo && m_NumThreadsPrev == NumThreads) return S_OK; try { @@ -167,7 +176,7 @@ HRESULT CEncoder::Create() MtMode = (NumThreads > 1); m_NumThreadsPrev = NumThreads; ThreadsInfo = new CThreadInfo[NumThreads]; - if (ThreadsInfo == 0) + if (!ThreadsInfo) return E_OUTOFMEMORY; } catch(...) { return E_OUTOFMEMORY; } @@ -199,11 +208,11 @@ void CEncoder::Free() { CThreadInfo &ti = ThreadsInfo[t]; if (MtMode) - ti.Thread.Wait(); + ti.Thread.Wait_Close(); ti.Free(); } delete []ThreadsInfo; - ThreadsInfo = 0; + ThreadsInfo = NULL; } #endif @@ -745,9 +754,11 @@ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * CThreadInfo &ti = ThreadsInfo[t]; if (MtMode) { - RINOK(ti.StreamWasFinishedEvent.Reset()); - RINOK(ti.WaitingWasStartedEvent.Reset()); - RINOK(ti.CanWriteEvent.Reset()); + WRes wres = ti.StreamWasFinishedEvent.Reset(); + if (wres == 0) { wres = ti.WaitingWasStartedEvent.Reset(); + if (wres == 0) { wres = ti.CanWriteEvent.Reset(); }} + if (wres != 0) + return HRESULT_FROM_WIN32(wres); } #else CThreadInfo &ti = ThreadsInfo; @@ -854,6 +865,16 @@ HRESULT CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *c { const PROPVARIANT &prop = coderProps[i]; PROPID propID = propIDs[i]; + + if (propID == NCoderPropID::kAffinity) + { + if (prop.vt == VT_UI8) + props.Affinity = prop.uhVal.QuadPart; + else + return E_INVALIDARG; + continue; + } + if (propID >= NCoderPropID::kReduceSize) continue; if (prop.vt != VT_UI4) @@ -863,7 +884,7 @@ HRESULT CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *c { case NCoderPropID::kNumPasses: props.NumPasses = v; break; case NCoderPropID::kDictionarySize: props.BlockSizeMult = v / kBlockSizeStep; break; - case NCoderPropID::kLevel: level = v; break; + case NCoderPropID::kLevel: level = (int)v; break; case NCoderPropID::kNumThreads: { #ifndef _7ZIP_ST diff --git a/CPP/7zip/Compress/BZip2Encoder.h b/CPP/7zip/Compress/BZip2Encoder.h index 05d6fa16..5e63a730 100644 --- a/CPP/7zip/Compress/BZip2Encoder.h +++ b/CPP/7zip/Compress/BZip2Encoder.h @@ -53,7 +53,7 @@ public: unsigned numNewBits = MyMin(numBits, _bitPos); numBits -= numNewBits; - _curByte <<= numNewBits; + _curByte = (Byte)(_curByte << numNewBits); UInt32 newBits = value >> numBits; _curByte |= Byte(newBits); value -= (newBits << numBits); @@ -134,10 +134,10 @@ public: Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. HRESULT Create(); void FinishStream(bool needLeave); - DWORD ThreadFunc(); + THREAD_FUNC_RET_TYPE ThreadFunc(); #endif - CThreadInfo(): m_BlockSorterIndex(0), m_Block(0) {} + CThreadInfo(): m_Block(NULL), m_BlockSorterIndex(NULL) {} ~CThreadInfo() { Free(); } bool Alloc(); void Free(); @@ -149,11 +149,13 @@ struct CEncProps { UInt32 BlockSizeMult; UInt32 NumPasses; + UInt64 Affinity; CEncProps() { BlockSizeMult = (UInt32)(Int32)-1; NumPasses = (UInt32)(Int32)-1; + Affinity = 0; } void Normalize(int level); bool DoOptimizeNumTables() const { return NumPasses > 1; } diff --git a/CPP/7zip/Compress/Bcj2Coder.cpp b/CPP/7zip/Compress/Bcj2Coder.cpp index 4906e78c..561fd08b 100644 --- a/CPP/7zip/Compress/Bcj2Coder.cpp +++ b/CPP/7zip/Compress/Bcj2Coder.cpp @@ -234,14 +234,14 @@ HRESULT CEncoder::CodeReal(ISequentialInStream * const *inStreams, const UInt64 Bcj2Enc_Encode(&enc); - currentInPos = totalStreamRead - numBytes_in_ReadBuf + (enc.src - _bufs[BCJ2_NUM_STREAMS]) - enc.tempPos; + currentInPos = totalStreamRead - numBytes_in_ReadBuf + (size_t)(enc.src - _bufs[BCJ2_NUM_STREAMS]) - enc.tempPos; if (Bcj2Enc_IsFinished(&enc)) break; if (enc.state < BCJ2_NUM_STREAMS) { - size_t curSize = enc.bufs[enc.state] - _bufs[enc.state]; + const size_t curSize = (size_t)(enc.bufs[enc.state] - _bufs[enc.state]); // printf("Write stream = %2d %6d\n", enc.state, curSize); RINOK(WriteStream(outStreams[enc.state], _bufs[enc.state], curSize)); if (enc.state == BCJ2_STREAM_RC) @@ -286,7 +286,7 @@ HRESULT CEncoder::CodeReal(ISequentialInStream * const *inStreams, const UInt64 if (progress && currentInPos - prevProgress >= (1 << 20)) { - UInt64 outSize2 = currentInPos + outSizeRc + enc.bufs[BCJ2_STREAM_RC] - enc.bufs[BCJ2_STREAM_RC]; + const UInt64 outSize2 = currentInPos + outSizeRc + (size_t)(enc.bufs[BCJ2_STREAM_RC] - enc.bufs[BCJ2_STREAM_RC]); prevProgress = currentInPos; // printf("progress %8d, %8d\n", (int)inSize2, (int)outSize2); RINOK(progress->SetRatioInfo(¤tInPos, &outSize2)); @@ -295,7 +295,7 @@ HRESULT CEncoder::CodeReal(ISequentialInStream * const *inStreams, const UInt64 for (int i = 0; i < BCJ2_NUM_STREAMS; i++) { - RINOK(WriteStream(outStreams[i], _bufs[i], enc.bufs[i] - _bufs[i])); + RINOK(WriteStream(outStreams[i], _bufs[i], (size_t)(enc.bufs[i] - _bufs[i]))); } // if (currentInPos != subStreamStartPos + subStreamSize) return E_FAIL; @@ -440,7 +440,7 @@ HRESULT CDecoder::Code(ISequentialInStream * const *inStreams, const UInt64 * co } else // if (dec.state <= BCJ2_STATE_ORIG) { - size_t curSize = dec.dest - _bufs[BCJ2_NUM_STREAMS]; + const size_t curSize = (size_t)(dec.dest - _bufs[BCJ2_NUM_STREAMS]); if (curSize != 0) { outSizeProcessed += curSize; @@ -463,17 +463,17 @@ HRESULT CDecoder::Code(ISequentialInStream * const *inStreams, const UInt64 * co if (progress) { - const UInt64 outSize2 = outSizeProcessed + (dec.dest - _bufs[BCJ2_NUM_STREAMS]); + const UInt64 outSize2 = outSizeProcessed + (size_t)(dec.dest - _bufs[BCJ2_NUM_STREAMS]); if (outSize2 - prevProgress >= (1 << 22)) { - const UInt64 inSize2 = outSize2 + _inStreamsProcessed[BCJ2_STREAM_RC] - (dec.lims[BCJ2_STREAM_RC] - dec.bufs[BCJ2_STREAM_RC]); + const UInt64 inSize2 = outSize2 + _inStreamsProcessed[BCJ2_STREAM_RC] - (size_t)(dec.lims[BCJ2_STREAM_RC] - dec.bufs[BCJ2_STREAM_RC]); RINOK(progress->SetRatioInfo(&inSize2, &outSize2)); prevProgress = outSize2; } } } - size_t curSize = dec.dest - _bufs[BCJ2_NUM_STREAMS]; + const size_t curSize = (size_t)(dec.dest - _bufs[BCJ2_NUM_STREAMS]); if (curSize != 0) { outSizeProcessed += curSize; @@ -498,7 +498,7 @@ HRESULT CDecoder::Code(ISequentialInStream * const *inStreams, const UInt64 * co { for (int i = 0; i < BCJ2_NUM_STREAMS; i++) { - size_t rem = dec.lims[i] - dec.bufs[i] + _extraReadSizes[i]; + const size_t rem = (size_t)(dec.lims[i] - dec.bufs[i]) + _extraReadSizes[i]; /* if (rem != 0) return S_FALSE; @@ -658,7 +658,7 @@ STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) STDMETHODIMP CDecoder::GetInStreamProcessedSize2(UInt32 streamIndex, UInt64 *value) { - const size_t rem = dec.lims[streamIndex] - dec.bufs[streamIndex] + _extraReadSizes[streamIndex]; + const size_t rem = (size_t)(dec.lims[streamIndex] - dec.bufs[streamIndex]) + _extraReadSizes[streamIndex]; *value = _inStreamsProcessed[streamIndex] - rem; return S_OK; } diff --git a/CPP/7zip/Compress/Bcj2Register.cpp b/CPP/7zip/Compress/Bcj2Register.cpp index 7a48f91c..2868f1c9 100644 --- a/CPP/7zip/Compress/Bcj2Register.cpp +++ b/CPP/7zip/Compress/Bcj2Register.cpp @@ -16,7 +16,7 @@ REGISTER_CODEC_CREATE_2(CreateCodecOut, CEncoder(), ICompressCoder2) #define CreateCodecOut NULL #endif -REGISTER_CODEC_VAR +REGISTER_CODEC_VAR(BCJ2) { CreateCodec, CreateCodecOut, 0x303011B, "BCJ2", 4, false }; REGISTER_CODEC(BCJ2) diff --git a/CPP/7zip/Compress/BitlDecoder.cpp b/CPP/7zip/Compress/BitlDecoder.cpp index 516b0932..876e6497 100644 --- a/CPP/7zip/Compress/BitlDecoder.cpp +++ b/CPP/7zip/Compress/BitlDecoder.cpp @@ -8,6 +8,7 @@ namespace NBitl { Byte kInvertTable[256]; +static struct CInverterTableInitializer { CInverterTableInitializer() diff --git a/CPP/7zip/Compress/BitlDecoder.h b/CPP/7zip/Compress/BitlDecoder.h index f3b8248f..e85942cf 100644 --- a/CPP/7zip/Compress/BitlDecoder.h +++ b/CPP/7zip/Compress/BitlDecoder.h @@ -38,7 +38,18 @@ public: _value = 0; } - UInt64 GetStreamSize() const { return _stream.GetStreamSize(); } + // the size of portion data in real stream that was already read from this object. + // it doesn't include unused data in BitStream object buffer (up to 4 bytes) + // it doesn't include unused data in TInByte buffers + // it doesn't include virtual Extra bytes after the end of real stream data + UInt64 GetStreamSize() const + { + return ExtraBitsWereRead() ? + _stream.GetStreamSize(): + GetProcessedSize(); + } + + // the size of virtual data that was read from this object. UInt64 GetProcessedSize() const { return _stream.GetProcessedSize() - ((kNumBigValueBits - _bitPos) >> 3); } bool ThereAreDataInBitsBuffer() const { return this->_bitPos != kNumBigValueBits; } @@ -139,6 +150,17 @@ public: MovePos(8); return b; } + + // call it only if the object is aligned for byte. + MY_FORCE_INLINE + bool ReadAlignedByte_FromBuf(Byte &b) + { + if (this->_bitPos == kNumBigValueBits) + return this->_stream.ReadByte_FromBuf(b); + b = (Byte)(_normalValue & 0xFF); + MovePos(8); + return true; + } }; } diff --git a/CPP/7zip/Compress/BitlEncoder.h b/CPP/7zip/Compress/BitlEncoder.h index 22b83545..9a4612fc 100644 --- a/CPP/7zip/Compress/BitlEncoder.h +++ b/CPP/7zip/Compress/BitlEncoder.h @@ -39,7 +39,7 @@ public: { if (numBits < _bitPos) { - _curByte |= (value & ((1 << numBits) - 1)) << (8 - _bitPos); + _curByte |= (Byte)((value & ((1 << numBits) - 1)) << (8 - _bitPos)); _bitPos -= numBits; return; } diff --git a/CPP/7zip/Compress/BitmEncoder.h b/CPP/7zip/Compress/BitmEncoder.h index 05079ace..4499c79d 100644 --- a/CPP/7zip/Compress/BitmEncoder.h +++ b/CPP/7zip/Compress/BitmEncoder.h @@ -33,7 +33,7 @@ public: { if (numBits < _bitPos) { - _curByte |= ((Byte)value << (_bitPos -= numBits)); + _curByte = (Byte)(_curByte | (value << (_bitPos -= numBits))); return; } numBits -= _bitPos; diff --git a/CPP/7zip/Compress/CodecExports.cpp b/CPP/7zip/Compress/CodecExports.cpp index 99085040..2aea7b33 100644 --- a/CPP/7zip/Compress/CodecExports.cpp +++ b/CPP/7zip/Compress/CodecExports.cpp @@ -82,6 +82,14 @@ static HRESULT FindCodecClassId(const GUID *clsid, bool isCoder2, bool isFilter, return S_OK; } +/* +#ifdef __GNUC__ +#ifndef __clang__ +#pragma GCC diagnostic ignored "-Wduplicated-branches" +#endif +#endif +*/ + static HRESULT CreateCoderMain(unsigned index, bool encode, void **coder) { COM_TRY_BEGIN @@ -97,12 +105,15 @@ static HRESULT CreateCoderMain(unsigned index, bool encode, void **coder) if (c) { IUnknown *unk; + unk = (IUnknown *)c; + /* if (codec.IsFilter) unk = (IUnknown *)(ICompressFilter *)c; else if (codec.NumStreams != 1) unk = (IUnknown *)(ICompressCoder2 *)c; else unk = (IUnknown *)(ICompressCoder *)c; + */ unk->AddRef(); *coder = c; } @@ -136,16 +147,22 @@ static HRESULT CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **o return CreateCoderMain(index, encode, outObject); } + +STDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject); STDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject) { return CreateCoder2(false, index, iid, outObject); } + +STDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject); STDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject) { return CreateCoder2(true, index, iid, outObject); } + +STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject) { *outObject = NULL; @@ -175,6 +192,8 @@ STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject) return CreateCoderMain(codecIndex, encode, outObject); } + +STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) { ::VariantClear((VARIANTARG *)value); @@ -238,6 +257,8 @@ STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) return S_OK; } + +STDAPI GetNumberOfMethods(UINT32 *numCodecs); STDAPI GetNumberOfMethods(UINT32 *numCodecs) { *numCodecs = g_NumCodecs; @@ -270,6 +291,7 @@ static HRESULT CreateHasher2(UInt32 index, IHasher **hasher) COM_TRY_END } +STDAPI CreateHasher(const GUID *clsid, IHasher **outObject); STDAPI CreateHasher(const GUID *clsid, IHasher **outObject) { COM_TRY_BEGIN @@ -281,6 +303,7 @@ STDAPI CreateHasher(const GUID *clsid, IHasher **outObject) COM_TRY_END } +STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) { ::VariantClear((VARIANTARG *)value); @@ -318,6 +341,7 @@ public: STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher); }; +STDAPI GetHashers(IHashers **hashers); STDAPI GetHashers(IHashers **hashers) { COM_TRY_BEGIN diff --git a/CPP/7zip/Compress/DeflateDecoder.cpp b/CPP/7zip/Compress/DeflateDecoder.cpp index fceef857..e34c2c0c 100644 --- a/CPP/7zip/Compress/DeflateDecoder.cpp +++ b/CPP/7zip/Compress/DeflateDecoder.cpp @@ -9,8 +9,8 @@ namespace NDeflate { namespace NDecoder { CCoder::CCoder(bool deflate64Mode): - _deflate64Mode(deflate64Mode), _deflateNSIS(false), + _deflate64Mode(deflate64Mode), _keepHistory(false), _needFinishInput(false), _needInitInStream(true), @@ -408,9 +408,25 @@ STDMETHODIMP CCoder::SetFinishMode(UInt32 finishMode) STDMETHODIMP CCoder::GetInStreamProcessedSize(UInt64 *value) { - if (!value) - return E_INVALIDARG; - *value = m_InBitStream.GetProcessedSize(); + *value = m_InBitStream.GetStreamSize(); + return S_OK; +} + + +STDMETHODIMP CCoder::ReadUnusedFromInBuf(void *data, UInt32 size, UInt32 *processedSize) +{ + AlignToByte(); + UInt32 i = 0; + if (!m_InBitStream.ExtraBitsWereRead()) + { + for (i = 0; i < size; i++) + { + if (!m_InBitStream.ReadAlignedByte_FromBuf(((Byte *)data)[i])) + break; + } + } + if (processedSize) + *processedSize = i; return S_OK; } diff --git a/CPP/7zip/Compress/DeflateDecoder.h b/CPP/7zip/Compress/DeflateDecoder.h index 0a724247..141184ef 100644 --- a/CPP/7zip/Compress/DeflateDecoder.h +++ b/CPP/7zip/Compress/DeflateDecoder.h @@ -25,6 +25,7 @@ class CCoder: public ICompressCoder, public ICompressSetFinishMode, public ICompressGetInStreamProcessedSize, + public ICompressReadUnusedFromInBuf, #ifndef NO_READ_FROM_CODER public ICompressSetInStream, public ICompressSetOutStreamSize, @@ -103,6 +104,7 @@ public: MY_QUERYINTERFACE_BEGIN2(ICompressCoder) MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode) MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize) + MY_QUERYINTERFACE_ENTRY(ICompressReadUnusedFromInBuf) #ifndef NO_READ_FROM_CODER MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) @@ -119,6 +121,7 @@ public: STDMETHOD(SetFinishMode)(UInt32 finishMode); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); + STDMETHOD(ReadUnusedFromInBuf)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); @@ -141,7 +144,10 @@ public: } bool InputEofError() const { return m_InBitStream.ExtraBitsWereRead(); } + // size of used real data from input stream UInt64 GetStreamSize() const { return m_InBitStream.GetStreamSize(); } + + // size of virtual input stream processed UInt64 GetInputProcessedSize() const { return m_InBitStream.GetProcessedSize(); } }; diff --git a/CPP/7zip/Compress/DeflateEncoder.cpp b/CPP/7zip/Compress/DeflateEncoder.cpp index 233edb5f..fb24c6b0 100644 --- a/CPP/7zip/Compress/DeflateEncoder.cpp +++ b/CPP/7zip/Compress/DeflateEncoder.cpp @@ -36,7 +36,7 @@ static const UInt32 kMatchArrayLimit = kMatchArraySize - kMatchMaxLen * 4 * size static const UInt32 kBlockUncompressedSizeThreshold = kMaxUncompressedBlockSize - kMatchMaxLen - kNumOpts; -static const unsigned kMaxCodeBitLength = 11; +// static const unsigned kMaxCodeBitLength = 11; static const unsigned kMaxLevelBitLength = 7; static const Byte kNoLiteralStatPrice = 11; @@ -89,7 +89,7 @@ void CEncProps::Normalize() if (algo < 0) algo = (level < 5 ? 0 : 1); if (fb < 0) fb = (level < 7 ? 32 : (level < 9 ? 64 : 128)); if (btMode < 0) btMode = (algo == 0 ? 0 : 1); - if (mc == 0) mc = (16 + (fb >> 1)); + if (mc == 0) mc = (16 + ((unsigned)fb >> 1)); if (numPasses == (UInt32)(Int32)-1) numPasses = (level < 7 ? 1 : (level < 9 ? 3 : 10)); } @@ -100,7 +100,7 @@ void CCoder::SetProps(const CEncProps *props2) m_MatchFinderCycles = props.mc; { - unsigned fb = props.fb; + unsigned fb = (unsigned)props.fb; if (fb < kMatchMinLen) fb = kMatchMinLen; if (fb > m_MatchMaxLen) @@ -125,12 +125,12 @@ void CCoder::SetProps(const CEncProps *props2) } CCoder::CCoder(bool deflate64Mode): - m_Deflate64Mode(deflate64Mode), - m_OnePosMatchesMemory(0), - m_DistanceMemory(0), + m_Values(NULL), + m_OnePosMatchesMemory(NULL), + m_DistanceMemory(NULL), m_Created(false), - m_Values(0), - m_Tables(0) + m_Deflate64Mode(deflate64Mode), + m_Tables(NULL) { m_MatchMaxLen = deflate64Mode ? kMatchMaxLen64 : kMatchMaxLen32; m_NumLenCombinations = deflate64Mode ? kNumLenSymbols64 : kNumLenSymbols32; @@ -213,10 +213,10 @@ HRESULT CCoder::BaseSetEncoderProperties2(const PROPID *propIDs, const PROPVARIA switch (propID) { case NCoderPropID::kNumPasses: props.numPasses = v; break; - case NCoderPropID::kNumFastBytes: props.fb = v; break; + case NCoderPropID::kNumFastBytes: props.fb = (int)v; break; case NCoderPropID::kMatchFinderCycles: props.mc = v; break; - case NCoderPropID::kAlgorithm: props.algo = v; break; - case NCoderPropID::kLevel: props.Level = v; break; + case NCoderPropID::kAlgorithm: props.algo = (int)v; break; + case NCoderPropID::kLevel: props.Level = (int)v; break; case NCoderPropID::kNumThreads: break; default: return E_INVALIDARG; } @@ -595,7 +595,7 @@ NO_INLINE void CCoder::MakeTables(unsigned maxHuffLen) Huffman_Generate(distFreqs, distCodes, m_NewLevels.distLevels, kDistTableSize64, maxHuffLen); } -NO_INLINE UInt32 Huffman_GetPrice(const UInt32 *freqs, const Byte *lens, UInt32 num) +static NO_INLINE UInt32 Huffman_GetPrice(const UInt32 *freqs, const Byte *lens, UInt32 num) { UInt32 price = 0; UInt32 i; @@ -604,7 +604,7 @@ NO_INLINE UInt32 Huffman_GetPrice(const UInt32 *freqs, const Byte *lens, UInt32 return price; } -NO_INLINE UInt32 Huffman_GetPrice_Spec(const UInt32 *freqs, const Byte *lens, UInt32 num, const Byte *extraBits, UInt32 extraBase) +static NO_INLINE UInt32 Huffman_GetPrice_Spec(const UInt32 *freqs, const Byte *lens, UInt32 num, const Byte *extraBits, UInt32 extraBase) { return Huffman_GetPrice(freqs, lens, num) + Huffman_GetPrice(freqs + extraBase, extraBits, num - extraBase); @@ -629,8 +629,9 @@ NO_INLINE void CCoder::TryBlock() { if (m_OptimumCurrentIndex == m_OptimumEndIndex) { - if (m_Pos >= kMatchArrayLimit || BlockSizeRes >= blockSize || !m_SecondPass && - ((Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) == 0) || m_ValueIndex >= m_ValueBlockSize)) + if (m_Pos >= kMatchArrayLimit + || BlockSizeRes >= blockSize + || (!m_SecondPass && ((Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) == 0) || m_ValueIndex >= m_ValueBlockSize))) break; } UInt32 pos; @@ -688,7 +689,7 @@ NO_INLINE void CCoder::SetPrices(const CLevels &levels) } } -NO_INLINE void Huffman_ReverseBits(UInt32 *codes, const Byte *lens, UInt32 num) +static NO_INLINE void Huffman_ReverseBits(UInt32 *codes, const Byte *lens, UInt32 num) { for (UInt32 i = 0; i < num; i++) { diff --git a/CPP/7zip/Compress/DllExportsCompress.cpp b/CPP/7zip/Compress/DllExportsCompress.cpp index c58d2d5e..24749d27 100644 --- a/CPP/7zip/Compress/DllExportsCompress.cpp +++ b/CPP/7zip/Compress/DllExportsCompress.cpp @@ -27,6 +27,16 @@ void RegisterHasher(const CHasherInfo *hashInfo) throw() } #ifdef _WIN32 + +extern "C" +BOOL WINAPI DllMain( + #ifdef UNDER_CE + HANDLE + #else + HINSTANCE + #endif + , DWORD /* dwReason */, LPVOID /*lpReserved*/); + extern "C" BOOL WINAPI DllMain( #ifdef UNDER_CE @@ -42,6 +52,7 @@ BOOL WINAPI DllMain( STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); +STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) { return CreateCoder(clsid, iid, outObject); diff --git a/CPP/7zip/Compress/ImplodeDecoder.cpp b/CPP/7zip/Compress/ImplodeDecoder.cpp index 736c832e..97a3cdf7 100644 --- a/CPP/7zip/Compress/ImplodeDecoder.cpp +++ b/CPP/7zip/Compress/ImplodeDecoder.cpp @@ -83,8 +83,8 @@ static const UInt32 kHistorySize = (1 << kNumDistDirectBitsBig) * kDistTableSize CCoder::CCoder(): - _fullStreamMode(false), - _flags(0) + _flags(0), + _fullStreamMode(false) {} diff --git a/CPP/7zip/Compress/Lzma2Encoder.cpp b/CPP/7zip/Compress/Lzma2Encoder.cpp index caecbc09..6a5d6797 100644 --- a/CPP/7zip/Compress/Lzma2Encoder.cpp +++ b/CPP/7zip/Compress/Lzma2Encoder.cpp @@ -34,6 +34,7 @@ CEncoder::~CEncoder() } +HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props); HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props) { switch (propID) @@ -49,7 +50,10 @@ HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzm break; } case NCoderPropID::kNumThreads: - if (prop.vt != VT_UI4) return E_INVALIDARG; lzma2Props.numTotalThreads = (int)(prop.ulVal); break; + if (prop.vt != VT_UI4) + return E_INVALIDARG; + lzma2Props.numTotalThreads = (int)(prop.ulVal); + break; default: RINOK(NLzma::SetLzmaProp(propID, prop, lzma2Props.lzmaProps)); } diff --git a/CPP/7zip/Compress/LzmaDecoder.cpp b/CPP/7zip/Compress/LzmaDecoder.cpp index 83c24f1c..a25d36d1 100644 --- a/CPP/7zip/Compress/LzmaDecoder.cpp +++ b/CPP/7zip/Compress/LzmaDecoder.cpp @@ -153,7 +153,7 @@ HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream * SizeT inProcessed = _inLim - _inPos; ELzmaStatus status; - + SRes res = LzmaDec_DecodeToDic(&_state, dicPos + size, _inBuf + _inPos, &inProcessed, finishMode, &status); _lzmaStatus = status; @@ -183,7 +183,10 @@ HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream * if (needStop) { if (res != 0) + { + // return SResToHRESULT(res); return S_FALSE; + } if (status == LZMA_STATUS_FINISHED_WITH_MARK) { diff --git a/CPP/7zip/Compress/LzmaEncoder.cpp b/CPP/7zip/Compress/LzmaEncoder.cpp index e47f776b..5a6c6831 100644 --- a/CPP/7zip/Compress/LzmaEncoder.cpp +++ b/CPP/7zip/Compress/LzmaEncoder.cpp @@ -9,6 +9,20 @@ #include "LzmaEncoder.h" +#include "../../Common/IntToString.h" +#include "../../Windows/TimeUtils.h" + +// #define LOG_LZMA_THREADS + +#ifdef LOG_LZMA_THREADS +#include <stdio.h> + +EXTERN_C_BEGIN +void LzmaEnc_GetLzThreads(CLzmaEncHandle pp, HANDLE lz_threads[2]); +EXTERN_C_END + +#endif + namespace NCompress { namespace NLzma { @@ -26,46 +40,48 @@ CEncoder::~CEncoder() LzmaEnc_Destroy(_encoder, &g_AlignedAlloc, &g_BigAlloc); } -static inline wchar_t GetUpperChar(wchar_t c) +static inline wchar_t GetLowCharFast(wchar_t c) { - if (c >= 'a' && c <= 'z') - c -= 0x20; - return c; + return c |= 0x20; } static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes) { - wchar_t c = GetUpperChar(*s++); - if (c == L'H') + wchar_t c = GetLowCharFast(*s++); + if (c == 'h') { - if (GetUpperChar(*s++) != L'C') + if (GetLowCharFast(*s++) != 'c') return 0; - int numHashBytesLoc = (int)(*s++ - L'0'); - if (numHashBytesLoc < 4 || numHashBytesLoc > 4) + int num = (int)(*s++ - L'0'); + if (num < 4 || num > 5) return 0; if (*s != 0) return 0; *btMode = 0; - *numHashBytes = numHashBytesLoc; + *numHashBytes = num; return 1; } - if (c != L'B') - return 0; - if (GetUpperChar(*s++) != L'T') - return 0; - int numHashBytesLoc = (int)(*s++ - L'0'); - if (numHashBytesLoc < 2 || numHashBytesLoc > 4) - return 0; - if (*s != 0) + if (c != 'b') return 0; - *btMode = 1; - *numHashBytes = numHashBytesLoc; - return 1; + { + if (GetLowCharFast(*s++) != 't') + return 0; + int num = (int)(*s++ - L'0'); + if (num < 2 || num > 5) + return 0; + if (*s != 0) + return 0; + *btMode = 1; + *numHashBytes = num; + return 1; + } } -#define SET_PROP_32(_id_, _dest_) case NCoderPropID::_id_: ep._dest_ = v; break; +#define SET_PROP_32(_id_, _dest_) case NCoderPropID::_id_: ep._dest_ = (int)v; break; +#define SET_PROP_32U(_id_, _dest_) case NCoderPropID::_id_: ep._dest_ = v; break; +HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep); HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep) { if (propID == NCoderPropID::kMatchFinder) @@ -74,7 +90,16 @@ HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep) return E_INVALIDARG; return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG; } - + + if (propID == NCoderPropID::kAffinity) + { + if (prop.vt == VT_UI8) + ep.affinity = prop.uhVal.QuadPart; + else + return E_INVALIDARG; + return S_OK; + } + if (propID > NCoderPropID::kReduceSize) return S_OK; @@ -95,9 +120,9 @@ HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep) case NCoderPropID::kDefaultProp: if (v > 31) return E_INVALIDARG; ep.dictSize = (UInt32)1 << (unsigned)v; break; SET_PROP_32(kLevel, level) SET_PROP_32(kNumFastBytes, fb) - SET_PROP_32(kMatchFinderCycles, mc) + SET_PROP_32U(kMatchFinderCycles, mc) SET_PROP_32(kAlgorithm, algo) - SET_PROP_32(kDictionarySize, dictSize) + SET_PROP_32U(kDictionarySize, dictSize) SET_PROP_32(kPosStateBits, pb) SET_PROP_32(kLitPosBits, lp) SET_PROP_32(kLitContextBits, lc) @@ -120,7 +145,10 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, switch (propID) { case NCoderPropID::kEndMarker: - if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal != VARIANT_FALSE); break; + if (prop.vt != VT_BOOL) + return E_INVALIDARG; + props.writeEndMark = (prop.boolVal != VARIANT_FALSE); + break; default: RINOK(SetLzmaProp(propID, prop, props)); } @@ -156,6 +184,92 @@ STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) #define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \ if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes; + + +#ifdef LOG_LZMA_THREADS + +static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } + +static void PrintNum(UInt64 val, unsigned numDigits, char c = ' ') +{ + char temp[64]; + char *p = temp + 32; + ConvertUInt64ToString(val, p); + unsigned len = (unsigned)strlen(p); + for (; len < numDigits; len++) + *--p = c; + printf("%s", p); +} + +static void PrintTime(const char *s, UInt64 val, UInt64 total) +{ + printf(" %s :", s); + const UInt32 kFreq = 10000000; + UInt64 sec = val / kFreq; + PrintNum(sec, 6); + printf(" ."); + UInt32 ms = (UInt32)(val - (sec * kFreq)) / (kFreq / 1000); + PrintNum(ms, 3, '0'); + + while (val > ((UInt64)1 << 56)) + { + val >>= 1; + total >>= 1; + } + + UInt64 percent = 0; + if (total != 0) + percent = val * 100 / total; + printf(" ="); + PrintNum(percent, 4); + printf("%%"); +} + + +struct CBaseStat +{ + UInt64 kernelTime, userTime; + + BOOL Get(HANDLE thread, const CBaseStat *prevStat) + { + FILETIME creationTimeFT, exitTimeFT, kernelTimeFT, userTimeFT; + BOOL res = GetThreadTimes(thread + , &creationTimeFT, &exitTimeFT, &kernelTimeFT, &userTimeFT); + if (res) + { + kernelTime = GetTime64(kernelTimeFT); + userTime = GetTime64(userTimeFT); + if (prevStat) + { + kernelTime -= prevStat->kernelTime; + userTime -= prevStat->userTime; + } + } + return res; + } +}; + + +static void PrintStat(HANDLE thread, UInt64 totalTime, const CBaseStat *prevStat) +{ + CBaseStat newStat; + if (!newStat.Get(thread, prevStat)) + return; + + PrintTime("K", newStat.kernelTime, totalTime); + + const UInt64 processTime = newStat.kernelTime + newStat.userTime; + + PrintTime("U", newStat.userTime, totalTime); + PrintTime("S", processTime, totalTime); + printf("\n"); + // PrintTime("G ", totalTime, totalTime); +} + +#endif + + + STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) { @@ -167,6 +281,18 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream outWrap.Init(outStream); progressWrap.Init(progress); + #ifdef LOG_LZMA_THREADS + + FILETIME startTimeFT; + NWindows::NTime::GetCurUtcFileTime(startTimeFT); + UInt64 totalTime = GetTime64(startTimeFT); + CBaseStat oldStat; + if (!oldStat.Get(GetCurrentThread(), NULL)) + return E_FAIL; + + #endif + + SRes res = LzmaEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt, progress ? &progressWrap.vt : NULL, &g_AlignedAlloc, &g_BigAlloc); @@ -175,7 +301,23 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ) RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE) RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS) + + + #ifdef LOG_LZMA_THREADS + NWindows::NTime::GetCurUtcFileTime(startTimeFT); + totalTime = GetTime64(startTimeFT) - totalTime; + HANDLE lz_threads[2]; + LzmaEnc_GetLzThreads(_encoder, lz_threads); + printf("\n"); + printf("Main: "); PrintStat(GetCurrentThread(), totalTime, &oldStat); + printf("Hash: "); PrintStat(lz_threads[0], totalTime, NULL); + printf("BinT: "); PrintStat(lz_threads[1], totalTime, NULL); + // PrintTime("Total: ", totalTime, totalTime); + printf("\n"); + + #endif + return SResToHRESULT(res); } diff --git a/CPP/7zip/Compress/LzmsDecoder.cpp b/CPP/7zip/Compress/LzmsDecoder.cpp index 5189ce16..e27afa3c 100644 --- a/CPP/7zip/Compress/LzmsDecoder.cpp +++ b/CPP/7zip/Compress/LzmsDecoder.cpp @@ -123,7 +123,7 @@ static void x86_Filter(Byte *data, UInt32 size, Int32 *history) for (;;) { - const Byte *p = data + (UInt32)i; + Byte *p = data + (UInt32)i; for (;;) { @@ -198,7 +198,7 @@ static void x86_Filter(Byte *data, UInt32 size, Int32 *history) Int32 *target; { - const Byte *p2 = p + codeLen; + Byte *p2 = p + codeLen; UInt32 n = GetUi32(p2); if (i - last_x86_pos <= maxTransOffset) { @@ -208,7 +208,7 @@ static void x86_Filter(Byte *data, UInt32 size, Int32 *history) target = history + (((UInt32)i + n) & 0xFFFF); } - i += codeLen + sizeof(UInt32) - 1; + i += (Int32)(codeLen + sizeof(UInt32) - 1); if (i - *target <= k_x86_WindowSize) last_x86_pos = i; @@ -220,7 +220,7 @@ static void x86_Filter(Byte *data, UInt32 size, Int32 *history) -static const int kLenIdNeedInit = -2; +// static const int kLenIdNeedInit = -2; CDecoder::CDecoder(): _x86_history(NULL) @@ -232,7 +232,7 @@ CDecoder::~CDecoder() ::MidFree(_x86_history); } -#define RIF(x) { if (!(x)) return false; } +// #define RIF(x) { if (!(x)) return false; } #define LIMIT_CHECK if (_bs._buf < _rc.cur) return S_FALSE; // #define LIMIT_CHECK @@ -539,8 +539,8 @@ HRESULT CDecoder::CodeReal(const Byte *in, size_t inSize, Byte *_win, size_t out _rc.Normalize(); if (_rc.code != 0) return S_FALSE; - if (_rc.cur > _bs._buf || - _rc.cur == _bs._buf && _bs._bitPos != 0) + if (_rc.cur > _bs._buf + || (_rc.cur == _bs._buf && _bs._bitPos != 0)) return S_FALSE; /* diff --git a/CPP/7zip/Compress/LzmsDecoder.h b/CPP/7zip/Compress/LzmsDecoder.h index 510d3389..f0909a1e 100644 --- a/CPP/7zip/Compress/LzmsDecoder.h +++ b/CPP/7zip/Compress/LzmsDecoder.h @@ -263,7 +263,7 @@ public: ~CDecoder(); HRESULT Code(const Byte *in, size_t inSize, Byte *out, size_t outSize); - const size_t GetUnpackSize() const { return _pos; } + size_t GetUnpackSize() const { return _pos; } }; }} diff --git a/CPP/7zip/Compress/LzxDecoder.cpp b/CPP/7zip/Compress/LzxDecoder.cpp index a7bba903..e59cd400 100644 --- a/CPP/7zip/Compress/LzxDecoder.cpp +++ b/CPP/7zip/Compress/LzxDecoder.cpp @@ -32,7 +32,7 @@ static void x86_Filter(Byte *data, UInt32 size, UInt32 processedSize, UInt32 tra for (UInt32 i = 0;;) { - const Byte *p = data + i; + Byte *p = data + i; for (;;) { if (*p++ == 0xE8) break; @@ -46,13 +46,13 @@ static void x86_Filter(Byte *data, UInt32 size, UInt32 processedSize, UInt32 tra if (i > size) break; { - Int32 v = GetUi32(p); + Int32 v = (Int32)GetUi32(p); Int32 pos = (Int32)((Int32)1 - (Int32)(processedSize + i)); i += 4; if (v >= pos && v < (Int32)translationSize) { - v += (v >= 0 ? pos : translationSize); - SetUi32(p, v); + v += (v >= 0 ? pos : (Int32)translationSize); + SetUi32(p, (UInt32)v); } } } @@ -63,15 +63,15 @@ static void x86_Filter(Byte *data, UInt32 size, UInt32 processedSize, UInt32 tra CDecoder::CDecoder(bool wimMode): _win(NULL), - _keepHistory(false), _skipByte(false), + _unpackBlockSize(0), + KeepHistoryForNext(true), + NeedAlloc(true), + _keepHistory(false), _wimMode(wimMode), _numDictBits(15), - _unpackBlockSize(0), _x86_buf(NULL), _x86_translationSize(0), - KeepHistoryForNext(true), - NeedAlloc(true), _unpackedData(NULL) { } diff --git a/CPP/7zip/Compress/LzxDecoder.h b/CPP/7zip/Compress/LzxDecoder.h index a5c6f12c..4d70b272 100644 --- a/CPP/7zip/Compress/LzxDecoder.h +++ b/CPP/7zip/Compress/LzxDecoder.h @@ -30,7 +30,7 @@ public: _extraSize = 0; } - size_t GetRem() const { return _bufLim + 1 - _buf; } + size_t GetRem() const { return (size_t)(_bufLim + 1 - _buf); } bool WasExtraReadError_Fast() const { return _extraSize > 4; } bool WasFinishedOK() const @@ -238,7 +238,7 @@ public: bool WasBlockFinished() const { return _unpackBlockSize == 0; } const Byte *GetUnpackData() const { return _unpackedData; } - const UInt32 GetUnpackSize() const { return _pos - _writePos; } + UInt32 GetUnpackSize() const { return _pos - _writePos; } }; }} diff --git a/CPP/7zip/Compress/PpmdDecoder.cpp b/CPP/7zip/Compress/PpmdDecoder.cpp index ed0e9e29..7f54ec3b 100644 --- a/CPP/7zip/Compress/PpmdDecoder.cpp +++ b/CPP/7zip/Compress/PpmdDecoder.cpp @@ -1,5 +1,5 @@ // PpmdDecoder.cpp -// 2009-03-11 : Igor Pavlov : Public domain +// 2020-07-03 : Igor Pavlov : Public domain #include "StdAfx.h" @@ -13,13 +13,13 @@ namespace NCompress { namespace NPpmd { -static const UInt32 kBufSize = (1 << 20); +static const UInt32 kBufSize = (1 << 16); enum { kStatus_NeedInit, kStatus_Normal, - kStatus_Finished, + kStatus_Finished_With_Mark, kStatus_Error }; @@ -35,7 +35,8 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size) return E_INVALIDARG; _order = props[0]; UInt32 memSize = GetUi32(props + 1); - if (_order < PPMD7_MIN_ORDER || + if ( + // _order < PPMD7_MIN_ORDER || _order > PPMD7_MAX_ORDER || memSize < PPMD7_MIN_MEM_SIZE || memSize > PPMD7_MAX_MEM_SIZE) @@ -47,23 +48,36 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size) return S_OK; } +#define _rangeDec _ppmd.rc.dec + +#define CHECK_EXTRA_ERROR \ + if (_inStream.Extra) { \ + _status = kStatus_Error; \ + return (_res = (_inStream.Res != SZ_OK ? _inStream.Res: S_FALSE)); } + + HRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size) { + if (_res != S_OK) + return _res; + switch (_status) { - case kStatus_Finished: return S_OK; + case kStatus_Finished_With_Mark: return S_OK; case kStatus_Error: return S_FALSE; case kStatus_NeedInit: _inStream.Init(); if (!Ppmd7z_RangeDec_Init(&_rangeDec)) { _status = kStatus_Error; - return S_FALSE; + return (_res = S_FALSE); } + CHECK_EXTRA_ERROR _status = kStatus_Normal; Ppmd7_Init(&_ppmd, _order); break; } + if (_outSizeDefined) { const UInt64 rem = _outSize - _processedSize; @@ -71,29 +85,54 @@ HRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size) size = (UInt32)rem; } - UInt32 i; int sym = 0; - for (i = 0; i != size; i++) { - sym = Ppmd7_DecodeSymbol(&_ppmd, &_rangeDec.vt); - if (_inStream.Extra || sym < 0) - break; - memStream[i] = (Byte)sym; + Byte *buf = memStream; + const Byte *lim = buf + size; + for (; buf != lim; buf++) + { + sym = Ppmd7z_DecodeSymbol(&_ppmd); + if (_inStream.Extra || sym < 0) + break; + *buf = (Byte)sym; + } + /* + buf = Ppmd7z_DecodeSymbols(&_ppmd, buf, lim); + sym = _ppmd.LastSymbol; + */ + _processedSize += (size_t)(buf - memStream); } - _processedSize += i; - if (_inStream.Extra) + CHECK_EXTRA_ERROR + + if (sym >= 0) + { + if (!FinishStream + || !_outSizeDefined + || _outSize != _processedSize + || _rangeDec.Code == 0) + return S_OK; + /* + // We can decode additional End Marker here: + sym = Ppmd7z_DecodeSymbol(&_ppmd); + CHECK_EXTRA_ERROR + */ + } + + if (sym != PPMD7_SYM_END || _rangeDec.Code != 0) { _status = kStatus_Error; - return _inStream.Res; + return (_res = S_FALSE); } - if (sym < 0) - _status = (sym < -1) ? kStatus_Error : kStatus_Finished; + + _status = kStatus_Finished_With_Mark; return S_OK; } + + STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { if (!_outBuf) { @@ -112,18 +151,23 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream size_t processed = (size_t)(_processedSize - startPos); RINOK(WriteStream(outStream, _outBuf, processed)); RINOK(res); - if (_status == kStatus_Finished) + if (_status == kStatus_Finished_With_Mark) break; if (progress) { - UInt64 inSize = _inStream.GetProcessed(); - RINOK(progress->SetRatioInfo(&inSize, &_processedSize)); + const UInt64 inProcessed = _inStream.GetProcessed(); + RINOK(progress->SetRatioInfo(&inProcessed, &_processedSize)); } } while (!_outSizeDefined || _processedSize < _outSize); + + if (FinishStream && inSize && *inSize != _inStream.GetProcessed()) + return S_FALSE; + return S_OK; } + STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { _outSizeDefined = (outSize != NULL); @@ -131,9 +175,15 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) _outSize = *outSize; _processedSize = 0; _status = kStatus_NeedInit; + _res = SZ_OK; return S_OK; } +STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode) +{ + FinishStream = (finishMode != 0); + return S_OK; +} STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { diff --git a/CPP/7zip/Compress/PpmdDecoder.h b/CPP/7zip/Compress/PpmdDecoder.h index 2b6213c0..f1a8ee21 100644 --- a/CPP/7zip/Compress/PpmdDecoder.h +++ b/CPP/7zip/Compress/PpmdDecoder.h @@ -1,5 +1,5 @@ // PpmdDecoder.h -// 2009-03-11 : Igor Pavlov : Public domain +// 2020-07-03 : Igor Pavlov : Public domain #ifndef __COMPRESS_PPMD_DECODER_H #define __COMPRESS_PPMD_DECODER_H @@ -8,16 +8,17 @@ #include "../../Common/MyCom.h" -#include "../Common/CWrappers.h" - #include "../ICoder.h" +#include "../Common/CWrappers.h" + namespace NCompress { namespace NPpmd { class CDecoder : public ICompressCoder, public ICompressSetDecoderProperties2, + public ICompressSetFinishMode, public ICompressGetInStreamProcessedSize, #ifndef NO_READ_FROM_CODER public ICompressSetInStream, @@ -27,12 +28,13 @@ class CDecoder : public CMyUnknownImp { Byte *_outBuf; - CPpmd7z_RangeDec _rangeDec; CByteInBufWrap _inStream; CPpmd7 _ppmd; Byte _order; + bool FinishStream; bool _outSizeDefined; + HRESULT _res; int _status; UInt64 _outSize; UInt64 _processedSize; @@ -47,7 +49,7 @@ public: MY_QUERYINTERFACE_BEGIN2(ICompressCoder) MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2) - // MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode) + MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode) MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize) #ifndef NO_READ_FROM_CODER MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) @@ -61,6 +63,7 @@ public: STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + STDMETHOD(SetFinishMode)(UInt32 finishMode); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); @@ -71,11 +74,13 @@ public: STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); #endif - CDecoder(): _outBuf(NULL), _outSizeDefined(false) + CDecoder(): + _outBuf(NULL), + FinishStream(false), + _outSizeDefined(false) { - Ppmd7z_RangeDec_CreateVTable(&_rangeDec); - _rangeDec.Stream = &_inStream.vt; Ppmd7_Construct(&_ppmd); + _ppmd.rc.dec.Stream = &_inStream.vt; } ~CDecoder(); diff --git a/CPP/7zip/Compress/PpmdEncoder.cpp b/CPP/7zip/Compress/PpmdEncoder.cpp index 34e6d361..e2754772 100644 --- a/CPP/7zip/Compress/PpmdEncoder.cpp +++ b/CPP/7zip/Compress/PpmdEncoder.cpp @@ -3,7 +3,6 @@ #include "StdAfx.h" #include "../../../C/Alloc.h" -#include "../../../C/CpuArch.h" #include "../Common/StreamUtils.h" @@ -21,7 +20,7 @@ void CEncProps::Normalize(int level) if (level < 0) level = 5; if (level > 9) level = 9; if (MemSize == (UInt32)(Int32)-1) - MemSize = level >= 9 ? ((UInt32)192 << 20) : ((UInt32)1 << (level + 19)); + MemSize = (UInt32)1 << (level + 19); const unsigned kMult = 16; if (MemSize / kMult > ReduceSize) { @@ -43,8 +42,8 @@ CEncoder::CEncoder(): _inBuf(NULL) { _props.Normalize(-1); - _rangeEnc.Stream = &_outStream.vt; Ppmd7_Construct(&_ppmd); + _ppmd.rc.enc.Stream = &_outStream.vt; } CEncoder::~CEncoder() @@ -120,8 +119,8 @@ HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outS _outStream.Stream = outStream; _outStream.Init(); - Ppmd7z_RangeEnc_Init(&_rangeEnc); - Ppmd7_Init(&_ppmd, _props.Order); + Ppmd7z_Init_RangeEnc(&_ppmd); + Ppmd7_Init(&_ppmd, (unsigned)_props.Order); UInt64 processed = 0; for (;;) @@ -131,19 +130,27 @@ HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outS if (size == 0) { // We don't write EndMark in PPMD-7z. - // Ppmd7_EncodeSymbol(&_ppmd, &_rangeEnc, -1); - Ppmd7z_RangeEnc_FlushData(&_rangeEnc); + // Ppmd7z_EncodeSymbol(&_ppmd, -1); + Ppmd7z_Flush_RangeEnc(&_ppmd); return _outStream.Flush(); } - for (UInt32 i = 0; i < size; i++) + const Byte *buf = _inBuf; + const Byte *lim = buf + size; + /* + for (; buf < lim; buf++) { - Ppmd7_EncodeSymbol(&_ppmd, &_rangeEnc, _inBuf[i]); + Ppmd7z_EncodeSymbol(&_ppmd, *buf); RINOK(_outStream.Res); } + */ + + Ppmd7z_EncodeSymbols(&_ppmd, buf, lim); + RINOK(_outStream.Res); + processed += size; if (progress) { - UInt64 outSize = _outStream.GetProcessed(); + const UInt64 outSize = _outStream.GetProcessed(); RINOK(progress->SetRatioInfo(&processed, &outSize)); } } diff --git a/CPP/7zip/Compress/PpmdEncoder.h b/CPP/7zip/Compress/PpmdEncoder.h index 671a5353..0104663f 100644 --- a/CPP/7zip/Compress/PpmdEncoder.h +++ b/CPP/7zip/Compress/PpmdEncoder.h @@ -37,7 +37,6 @@ class CEncoder : { Byte *_inBuf; CByteOutBufWrap _outStream; - CPpmd7z_RangeEnc _rangeEnc; CPpmd7 _ppmd; CEncProps _props; public: diff --git a/CPP/7zip/Compress/PpmdZip.cpp b/CPP/7zip/Compress/PpmdZip.cpp index d9ce218a..434e143b 100644 --- a/CPP/7zip/Compress/PpmdZip.cpp +++ b/CPP/7zip/Compress/PpmdZip.cpp @@ -15,8 +15,8 @@ namespace NPpmdZip { CDecoder::CDecoder(bool fullFileMode): _fullFileMode(fullFileMode) { - _ppmd.Stream.In = &_inStream.vt; Ppmd8_Construct(&_ppmd); + _ppmd.Stream.In = &_inStream.vt; } CDecoder::~CDecoder() @@ -27,6 +27,8 @@ CDecoder::~CDecoder() STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { + // try { + if (!_outStream.Alloc()) return E_OUTOFMEMORY; if (!_inStream.Alloc(1 << 20)) @@ -43,9 +45,9 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream return S_FALSE; UInt32 val = GetUi16(buf); - UInt32 order = (val & 0xF) + 1; + unsigned order = (val & 0xF) + 1; UInt32 mem = ((val >> 4) & 0xFF) + 1; - UInt32 restor = (val >> 12); + unsigned restor = (val >> 12); if (order < 2 || restor > 2) return S_FALSE; @@ -57,7 +59,7 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream if (!Ppmd8_Alloc(&_ppmd, mem << 20, &g_BigAlloc)) return E_OUTOFMEMORY; - if (!Ppmd8_RangeDec_Init(&_ppmd)) + if (!Ppmd8_Init_RangeDec(&_ppmd)) return S_FALSE; Ppmd8_Init(&_ppmd, order, restor); } @@ -79,21 +81,23 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream } } - Byte *data = _outStream.Buf; - size_t i = 0; - int sym = 0; + int sym; + Byte *buf = _outStream.Buf; + const Byte *lim = buf + size; + do { sym = Ppmd8_DecodeSymbol(&_ppmd); if (_inStream.Extra || sym < 0) break; - data[i] = (Byte)sym; + *buf++ = (Byte)sym; } - while (++i != size); + while (buf != lim); - processedSize += i; + size_t cur = (size_t)(buf - _outStream.Buf); + processedSize += cur; - RINOK(WriteStream(outStream, _outStream.Buf, i)); + RINOK(WriteStream(outStream, _outStream.Buf, cur)); RINOK(_inStream.Res); if (_inStream.Extra) @@ -133,6 +137,8 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream } return S_OK; + + // } catch (...) { return E_FAIL; } } @@ -158,21 +164,14 @@ void CEncProps::Normalize(int level) if (level == 0) level = 1; if (level > 9) level = 9; if (MemSizeMB == (UInt32)(Int32)-1) - MemSizeMB = (1 << ((level > 8 ? 8 : level) - 1)); + MemSizeMB = 1 << (level - 1); const unsigned kMult = 16; - if ((MemSizeMB << 20) / kMult > ReduceSize) - { - for (UInt32 m = (1 << 20); m <= (1 << 28); m <<= 1) + for (UInt32 m = 1; m < MemSizeMB; m <<= 1) + if (ReduceSize <= (m << 20) / kMult) { - if (ReduceSize <= m / kMult) - { - m >>= 20; - if (MemSizeMB > m) - MemSizeMB = m; - break; - } + MemSizeMB = m; + break; } - } if (Order == -1) Order = 3 + level; if (Restor == -1) Restor = level < 7 ? @@ -197,6 +196,7 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIA continue; if (propID == NCoderPropID::kReduceSize) { + props.ReduceSize = (UInt32)(Int32)-1; if (prop.vt == VT_UI8 && prop.uhVal.QuadPart < (UInt32)(Int32)-1) props.ReduceSize = (UInt32)prop.uhVal.QuadPart; continue; @@ -219,9 +219,9 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIA case NCoderPropID::kNumThreads: break; case NCoderPropID::kLevel: level = (int)v; break; case NCoderPropID::kAlgorithm: - if (v > 1) + if (v >= PPMD8_RESTORE_METHOD_UNSUPPPORTED) return E_INVALIDARG; - props.Restor = v; + props.Restor = (int)v; break; default: return E_INVALIDARG; } @@ -251,12 +251,14 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream _outStream.Stream = outStream; _outStream.Init(); - Ppmd8_RangeEnc_Init(&_ppmd); - Ppmd8_Init(&_ppmd, _props.Order, _props.Restor); + Ppmd8_Init_RangeEnc(&_ppmd); + Ppmd8_Init(&_ppmd, (unsigned)_props.Order, (unsigned)_props.Restor); - UInt32 val = (UInt32)((_props.Order - 1) + ((_props.MemSizeMB - 1) << 4) + (_props.Restor << 12)); - _outStream.WriteByte((Byte)(val & 0xFF)); - _outStream.WriteByte((Byte)(val >> 8)); + { + UInt32 val = (UInt32)(((unsigned)_props.Order - 1) + ((_props.MemSizeMB - 1) << 4) + ((unsigned)_props.Restor << 12)); + _outStream.WriteByte((Byte)(val & 0xFF)); + _outStream.WriteByte((Byte)(val >> 8)); + } RINOK(_outStream.Res); UInt64 processed = 0; @@ -267,15 +269,23 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream if (size == 0) { Ppmd8_EncodeSymbol(&_ppmd, -1); - Ppmd8_RangeEnc_FlushData(&_ppmd); + Ppmd8_Flush_RangeEnc(&_ppmd); return _outStream.Flush(); } - for (UInt32 i = 0; i < size; i++) + + processed += size; + const Byte *buf = _inStream.Buf; + const Byte *lim = buf + size; + do { - Ppmd8_EncodeSymbol(&_ppmd, _inStream.Buf[i]); - RINOK(_outStream.Res); + Ppmd8_EncodeSymbol(&_ppmd, *buf); + if (_outStream.Res != S_OK) + break; } - processed += size; + while (++buf != lim); + + RINOK(_outStream.Res); + if (progress) { const UInt64 outProccessed = _outStream.GetProcessed(); @@ -284,4 +294,7 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream } } + + + }} diff --git a/CPP/7zip/Compress/PpmdZip.h b/CPP/7zip/Compress/PpmdZip.h index b8c7aae0..9d1fc4bd 100644 --- a/CPP/7zip/Compress/PpmdZip.h +++ b/CPP/7zip/Compress/PpmdZip.h @@ -8,10 +8,10 @@ #include "../../Common/MyCom.h" -#include "../Common/CWrappers.h" - #include "../ICoder.h" +#include "../Common/CWrappers.h" + namespace NCompress { namespace NPpmdZip { @@ -21,7 +21,7 @@ struct CBuf { Byte *Buf; - CBuf(): Buf(0) {} + CBuf(): Buf(NULL) {} ~CBuf() { ::MidFree(Buf); } bool Alloc() { @@ -52,7 +52,7 @@ public: STDMETHOD(SetFinishMode)(UInt32 finishMode); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); - CDecoder(bool fullFileMode); + CDecoder(bool fullFileMode = true); ~CDecoder(); }; diff --git a/CPP/7zip/Compress/QuantumDecoder.cpp b/CPP/7zip/Compress/QuantumDecoder.cpp index 64e35bf2..8c650581 100644 --- a/CPP/7zip/Compress/QuantumDecoder.cpp +++ b/CPP/7zip/Compress/QuantumDecoder.cpp @@ -41,7 +41,7 @@ unsigned CModelDecoder::Decode(CRangeDecoder *rc) unsigned res = Vals[--i]; do - Freqs[i] += kUpdateStep; + Freqs[i] = (UInt16)(Freqs[i] + kUpdateStep); while (i--); if (Freqs[0] > kFreqSumMax) @@ -72,7 +72,7 @@ unsigned CModelDecoder::Decode(CRangeDecoder *rc) i = NumItems - 1; do { - Freqs[i] >>= 1; + Freqs[i] = (UInt16)(Freqs[i] >> 1); if (Freqs[i] <= Freqs[(size_t)i + 1]) Freqs[i] = (UInt16)(Freqs[(size_t)i + 1] + 1); } diff --git a/CPP/7zip/Compress/Rar1Decoder.cpp b/CPP/7zip/Compress/Rar1Decoder.cpp index 6b55705b..510bbd17 100644 --- a/CPP/7zip/Compress/Rar1Decoder.cpp +++ b/CPP/7zip/Compress/Rar1Decoder.cpp @@ -239,6 +239,7 @@ HRESULT CDecoder::LongLZ() oldAvr3 = AvrLn3; if (len != 1 && len != 4) + { if (len == 0 && dist <= MaxDist3) { AvrLn3++; @@ -246,6 +247,7 @@ HRESULT CDecoder::LongLZ() } else if (AvrLn3 > 0) AvrLn3--; + } len += 3; @@ -254,7 +256,7 @@ HRESULT CDecoder::LongLZ() if (dist <= 256) len += 8; - if (oldAvr3 > 0xb0 || AvrPlc >= 0x2a00 && oldAvr2 < 0x40) + if (oldAvr3 > 0xb0 || (AvrPlc >= 0x2a00 && oldAvr2 < 0x40)) MaxDist3 = 0x7f00; else MaxDist3 = 0x2001; @@ -412,7 +414,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * { // InitStructures - for (int i = 0; i < kNumRepDists; i++) + for (unsigned i = 0; i < kNumRepDists; i++) m_RepDists[i] = 0; m_RepDistPtr = 0; LastLength = 0; diff --git a/CPP/7zip/Compress/Rar2Decoder.cpp b/CPP/7zip/Compress/Rar2Decoder.cpp index fe458c85..b1c8c2d4 100644 --- a/CPP/7zip/Compress/Rar2Decoder.cpp +++ b/CPP/7zip/Compress/Rar2Decoder.cpp @@ -4,6 +4,8 @@ #include "StdAfx.h" +#include <stdlib.h> + #include "Rar2Decoder.h" namespace NCompress { @@ -77,7 +79,7 @@ Byte CFilter::Decode(int &channelDelta, Byte deltaByte) static const UInt32 kHistorySize = 1 << 20; -static const UInt32 kWindowReservSize = (1 << 22) + 256; +// static const UInt32 kWindowReservSize = (1 << 22) + 256; CDecoder::CDecoder(): _isSolid(false), @@ -209,6 +211,7 @@ bool CDecoder::ReadLastTables() // + 2 works for: return 0xFF; in CInBuffer::ReadByte. if (m_InBitStream.GetProcessedSize() + 7 <= m_PackSize) // test it: probably incorrect; // if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: probably incorrect; + { if (m_AudioMode) { UInt32 symbol = m_MMDecoders[m_MmFilter.CurrentChannel].Decode(&m_InBitStream); @@ -225,6 +228,7 @@ bool CDecoder::ReadLastTables() if (sym >= kMainTableSize) return false; } + } return true; } diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp index 4456ba63..2271dcc8 100644 --- a/CPP/7zip/Compress/Rar3Decoder.cpp +++ b/CPP/7zip/Compress/Rar3Decoder.cpp @@ -19,20 +19,14 @@ static const UInt32 kNumAlignReps = 15; static const UInt32 kSymbolReadTable = 256; static const UInt32 kSymbolRep = 259; -static const UInt32 kSymbolLen2 = kSymbolRep + kNumReps; - -static const Byte kLenStart [kLenTableSize] = {0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224}; -static const Byte kLenDirectBits[kLenTableSize] = {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5}; static const Byte kDistDirectBits[kDistTableSize] = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15, 16,16,16,16,16,16,16,16,16,16,16,16,16,16, 18,18,18,18,18,18,18,18,18,18,18,18}; -static const Byte kLevelDirectBits[kLevelTableSize] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; - -static const Byte kLen2DistStarts[kNumLen2Symbols]={0,4,8,16,32,64,128,192}; -static const Byte kLen2DistDirectBits[kNumLen2Symbols]={2,2,3, 4, 5, 6, 6, 6}; +static const Byte kLen2DistStarts[kNumLen2Symbols] = {0,4,8,16,32,64,128,192}; +static const Byte kLen2DistDirectBits[kNumLen2Symbols] = {2,2,3, 4, 5, 6, 6, 6}; static const UInt32 kDistLimit3 = 0x2000 - 2; static const UInt32 kDistLimit4 = 0x40000 - 2; @@ -44,47 +38,20 @@ static const UInt32 kVmCodeSizeMax = 1 << 16; extern "C" { -#define GET_RangeDecoder CRangeDecoder *p = CONTAINER_FROM_VTBL_CLS(pp, CRangeDecoder, vt); - -static UInt32 Range_GetThreshold(const IPpmd7_RangeDec *pp, UInt32 total) +static Byte Wrap_ReadByte(const IByteIn *pp) throw() { - GET_RangeDecoder; - return p->Code / (p->Range /= total); + CByteIn *p = CONTAINER_FROM_VTBL_CLS(pp, CByteIn, IByteIn_obj); + return p->BitDecoder.Stream.ReadByte(); } -static void Range_Decode(const IPpmd7_RangeDec *pp, UInt32 start, UInt32 size) +static Byte Wrap_ReadBits8(const IByteIn *pp) throw() { - GET_RangeDecoder; - start *= p->Range; - p->Low += start; - p->Code -= start; - p->Range *= size; - p->Normalize(); + CByteIn *p = CONTAINER_FROM_VTBL_CLS(pp, CByteIn, IByteIn_obj); + return (Byte)p->BitDecoder.ReadByteFromAligned(); } -static UInt32 Range_DecodeBit(const IPpmd7_RangeDec *pp, UInt32 size0) -{ - GET_RangeDecoder; - if (p->Code / (p->Range >>= 14) < size0) - { - Range_Decode(&p->vt, 0, size0); - return 0; - } - else - { - Range_Decode(&p->vt, size0, (1 << 14) - size0); - return 1; - } } -} - -CRangeDecoder::CRangeDecoder() throw() -{ - vt.GetThreshold = Range_GetThreshold; - vt.Decode = Range_Decode; - vt.DecodeBit = Range_DecodeBit; -} CDecoder::CDecoder(): _window(0), @@ -98,6 +65,13 @@ CDecoder::CDecoder(): _solidAllowed(false) { Ppmd7_Construct(&_ppmd); + + UInt32 start = 0; + for (UInt32 i = 0; i < kDistTableSize; i++) + { + kDistStart[i] = start; + start += ((UInt32)1 << kDistDirectBits[i]); + } } CDecoder::~CDecoder() @@ -360,32 +334,37 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize) bool CDecoder::ReadVmCodeLZ() { UInt32 firstByte = ReadBits(8); - UInt32 length = (firstByte & 7) + 1; - if (length == 7) - length = ReadBits(8) + 7; - else if (length == 8) - length = ReadBits(16); - if (length > kVmDataSizeMax) + UInt32 len = (firstByte & 7) + 1; + if (len == 7) + len = ReadBits(8) + 7; + else if (len == 8) + len = ReadBits(16); + if (len > kVmDataSizeMax) return false; - for (UInt32 i = 0; i < length; i++) + for (UInt32 i = 0; i < len; i++) _vmData[i] = (Byte)ReadBits(8); - return AddVmCode(firstByte, length); + return AddVmCode(firstByte, len); } + +// int CDecoder::DecodePpmSymbol() { return Ppmd7a_DecodeSymbol(&_ppmd); } +#define DecodePpmSymbol() Ppmd7a_DecodeSymbol(&_ppmd) + + bool CDecoder::ReadVmCodePPM() { int firstByte = DecodePpmSymbol(); if (firstByte < 0) return false; - UInt32 length = (firstByte & 7) + 1; - if (length == 7) + UInt32 len = (firstByte & 7) + 1; + if (len == 7) { int b1 = DecodePpmSymbol(); if (b1 < 0) return false; - length = b1 + 7; + len = b1 + 7; } - else if (length == 8) + else if (len == 8) { int b1 = DecodePpmSymbol(); if (b1 < 0) @@ -393,20 +372,20 @@ bool CDecoder::ReadVmCodePPM() int b2 = DecodePpmSymbol(); if (b2 < 0) return false; - length = b1 * 256 + b2; + len = b1 * 256 + b2; } - if (length > kVmDataSizeMax) + if (len > kVmDataSizeMax) return false; if (InputEofError_Fast()) return false; - for (UInt32 i = 0; i < length; i++) + for (UInt32 i = 0; i < len; i++) { int b = DecodePpmSymbol(); if (b < 0) return false; _vmData[i] = (Byte)b; } - return AddVmCode(firstByte, length); + return AddVmCode(firstByte, len); } #define RIF(x) { if (!(x)) return S_FALSE; } @@ -422,19 +401,22 @@ HRESULT CDecoder::InitPPM() bool reset = ((maxOrder & 0x20) != 0); UInt32 maxMB = 0; if (reset) - maxMB = (Byte)ReadBits(8); + maxMB = (Byte)Wrap_ReadBits8(&m_InBitStream.IByteIn_obj); else { if (PpmError || !Ppmd7_WasAllocated(&_ppmd)) return S_FALSE; } if (maxOrder & 0x40) - PpmEscChar = (Byte)ReadBits(8); - m_InBitStream.InitRangeCoder(); - /* - if (m_InBitStream.m_BitPos != 0) - return S_FALSE; - */ + PpmEscChar = (Byte)Wrap_ReadBits8(&m_InBitStream.IByteIn_obj); + + _ppmd.rc.dec.Stream = &m_InBitStream.IByteIn_obj; + m_InBitStream.IByteIn_obj.Read = Wrap_ReadBits8; + + Ppmd7a_RangeDec_Init(&_ppmd.rc.dec); + + m_InBitStream.IByteIn_obj.Read = Wrap_ReadByte; + if (reset) { PpmError = true; @@ -454,7 +436,6 @@ HRESULT CDecoder::InitPPM() return S_OK; } -int CDecoder::DecodePpmSymbol() { return Ppmd7_DecodeSymbol(&_ppmd, &m_InBitStream.vt); } HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing) { @@ -503,8 +484,8 @@ HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing) } if (nextCh == 4 || nextCh == 5) { - UInt32 distance = 0; - UInt32 length = 4; + UInt32 dist = 0; + UInt32 len = 4; if (nextCh == 4) { for (int i = 0; i < 3; i++) @@ -515,10 +496,10 @@ HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing) PpmError = true; return S_FALSE; } - distance = (distance << 8) + (Byte)c2; + dist = (dist << 8) + (Byte)c2; } - distance++; - length += 28; + dist++; + len += 28; } int c2 = DecodePpmSymbol(); if (c2 < 0) @@ -526,11 +507,11 @@ HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing) PpmError = true; return S_FALSE; } - length += c2; - if (distance >= _lzSize) + len += c2; + if (dist >= _lzSize) return S_FALSE; - CopyBlock(distance, length); - num -= (Int32)length; + CopyBlock(dist, len); + num -= (Int32)len; continue; } } @@ -571,8 +552,8 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing) for (i = 0; i < kLevelTableSize; i++) { - UInt32 length = ReadBits(4); - if (length == 15) + UInt32 len = ReadBits(4); + if (len == 15) { UInt32 zeroCount = ReadBits(4); if (zeroCount != 0) @@ -584,7 +565,7 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing) continue; } } - levelLevels[i] = (Byte)length; + levelLevels[i] = (Byte)len; } RIF(m_LevelDecoder.Build(levelLevels)); @@ -674,22 +655,6 @@ HRESULT CDecoder::ReadEndOfBlock(bool &keepDecompressing) return ReadTables(keepDecompressing); } -UInt32 kDistStart[kDistTableSize]; - -class CDistInit -{ -public: - CDistInit() { Init(); } - void Init() - { - UInt32 start = 0; - for (UInt32 i = 0; i < kDistTableSize; i++) - { - kDistStart[i] = start; - start += (1 << kDistDirectBits[i]); - } - } -} g_DistInit; HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) { @@ -697,7 +662,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) UInt32 rep1 = _reps[1]; UInt32 rep2 = _reps[2]; UInt32 rep3 = _reps[3]; - UInt32 length = _lastLength; + UInt32 len = _lastLength; for (;;) { if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos) @@ -732,35 +697,40 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) } else if (sym == 258) { - if (length == 0) + if (len == 0) return S_FALSE; } else if (sym < kSymbolRep + 4) { if (sym != kSymbolRep) { - UInt32 distance; + UInt32 dist; if (sym == kSymbolRep + 1) - distance = rep1; + dist = rep1; else { if (sym == kSymbolRep + 2) - distance = rep2; + dist = rep2; else { - distance = rep3; + dist = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; - rep0 = distance; + rep0 = dist; } const UInt32 sym2 = m_LenDecoder.Decode(&m_InBitStream.BitDecoder); if (sym2 >= kLenTableSize) return S_FALSE; - length = 2 + kLenStart[sym2] + m_InBitStream.BitDecoder.ReadBits(kLenDirectBits[sym2]); + len = 2 + sym2; + if (sym2 >= 8) + { + unsigned num = (sym2 >> 2) - 1; + len = 2 + ((4 + (sym2 & 3)) << num) + m_InBitStream.BitDecoder.ReadBits_upto8(num); + } } else { @@ -770,13 +740,18 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) if (sym < 271) { sym -= 263; - rep0 = kLen2DistStarts[sym] + m_InBitStream.BitDecoder.ReadBits(kLen2DistDirectBits[sym]); - length = 2; + rep0 = kLen2DistStarts[sym] + m_InBitStream.BitDecoder.ReadBits_upto8(kLen2DistDirectBits[sym]); + len = 2; } else if (sym < 299) { sym -= 271; - length = kNormalMatchMinLen + (UInt32)kLenStart[sym] + m_InBitStream.BitDecoder.ReadBits(kLenDirectBits[sym]); + len = kNormalMatchMinLen + sym; + if (sym >= 8) + { + unsigned num = (sym >> 2) - 1; + len = kNormalMatchMinLen + ((4 + (sym & 3)) << num) + m_InBitStream.BitDecoder.ReadBits_upto8(num); + } const UInt32 sym2 = m_DistDecoder.Decode(&m_InBitStream.BitDecoder); if (sym2 >= kDistTableSize) return S_FALSE; @@ -809,21 +784,21 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) } } else - rep0 += m_InBitStream.BitDecoder.ReadBits(numBits); - length += ((kDistLimit4 - rep0) >> 31) + ((kDistLimit3 - rep0) >> 31); + rep0 += m_InBitStream.BitDecoder.ReadBits_upto8(numBits); + len += ((UInt32)(kDistLimit4 - rep0) >> 31) + ((UInt32)(kDistLimit3 - rep0) >> 31); } else return S_FALSE; } if (rep0 >= _lzSize) return S_FALSE; - CopyBlock(rep0, length); + CopyBlock(rep0, len); } _reps[0] = rep0; _reps[1] = rep1; _reps[2] = rep2; _reps[3] = rep3; - _lastLength = length; + _lastLength = len; return S_OK; } @@ -839,7 +814,7 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) _lzSize = 0; _winPos = 0; _wrPtr = 0; - for (int i = 0; i < kNumReps; i++) + for (unsigned i = 0; i < kNumReps; i++) _reps[i] = 0; _lastLength = 0; memset(m_LastLevels, 0, kTablesSizesSum); diff --git a/CPP/7zip/Compress/Rar3Decoder.h b/CPP/7zip/Compress/Rar3Decoder.h index 3d319ded..fdecc55f 100644 --- a/CPP/7zip/Compress/Rar3Decoder.h +++ b/CPP/7zip/Compress/Rar3Decoder.h @@ -95,44 +95,40 @@ public: MovePos(numBits); return res; } -}; - -const UInt32 kTopValue = (1 << 24); -const UInt32 kBot = (1 << 15); - -struct CRangeDecoder -{ - IPpmd7_RangeDec vt; - UInt32 Range; - UInt32 Code; - UInt32 Low; - CBitDecoder BitDecoder; - SRes Res; -public: - void InitRangeCoder() + UInt32 ReadBits_upto8(unsigned numBits) { - Code = 0; - Low = 0; - Range = 0xFFFFFFFF; - for (int i = 0; i < 4; i++) - Code = (Code << 8) | BitDecoder.ReadBits(8); + if (_bitPos < numBits) + { + _bitPos += 8; + _value = (_value << 8) | Stream.ReadByte(); + } + _bitPos -= numBits; + UInt32 res = _value >> _bitPos; + _value = _value & ((1 << _bitPos) - 1); + return res; } - void Normalize() + Byte ReadByteFromAligned() { - while ((Low ^ (Low + Range)) < kTopValue || - Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1)) - { - Code = (Code << 8) | BitDecoder.Stream.ReadByte(); - Range <<= 8; - Low <<= 8; - } + if (_bitPos == 0) + return Stream.ReadByte(); + unsigned bitsPos = _bitPos - 8; + Byte b = (Byte)(_value >> bitsPos); + _value = _value & ((1 << bitsPos) - 1); + _bitPos = bitsPos; + return b; } +}; + - CRangeDecoder() throw(); +struct CByteIn +{ + IByteIn IByteIn_obj; + CBitDecoder BitDecoder; }; + struct CFilter: public NVm::CProgram { CRecordVector<Byte> GlobalData; @@ -165,7 +161,7 @@ class CDecoder: public ICompressSetDecoderProperties2, public CMyUnknownImp { - CRangeDecoder m_InBitStream; + CByteIn m_InBitStream; Byte *_window; UInt32 _winPos; UInt32 _wrPtr; @@ -174,6 +170,7 @@ class CDecoder: UInt64 _writtenFileSize; // if it's > _unpackSize, then _unpackSize only written ISequentialOutStream *_outStream; NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder; + UInt32 kDistStart[kDistTableSize]; NHuffman::CDecoder<kNumHuffmanBits, kDistTableSize> m_DistDecoder; NHuffman::CDecoder<kNumHuffmanBits, kAlignTableSize> m_AlignDecoder; NHuffman::CDecoder<kNumHuffmanBits, kLenTableSize> m_LenDecoder; @@ -223,7 +220,7 @@ class CDecoder: UInt32 ReadBits(unsigned numBits); HRESULT InitPPM(); - int DecodePpmSymbol(); + // int DecodePpmSymbol(); HRESULT DecodePPM(Int32 num, bool &keepDecompressing); HRESULT ReadTables(bool &keepDecompressing); @@ -245,10 +242,10 @@ public: STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); - void CopyBlock(UInt32 distance, UInt32 len) + void CopyBlock(UInt32 dist, UInt32 len) { _lzSize += len; - UInt32 pos = (_winPos - distance - 1) & kWindowMask; + UInt32 pos = (_winPos - dist - 1) & kWindowMask; Byte *window = _window; UInt32 winPos = _winPos; if (kWindowSize - winPos > len && kWindowSize - pos > len) @@ -273,12 +270,11 @@ public: void PutByte(Byte b) { - _window[_winPos] = b; - _winPos = (_winPos + 1) & kWindowMask; + UInt32 wp = _winPos; + _window[wp] = b; + _winPos = (wp + 1) & kWindowMask; _lzSize++; } - - }; }} diff --git a/CPP/7zip/Compress/Rar3Vm.cpp b/CPP/7zip/Compress/Rar3Vm.cpp index 61cf657c..6accd08c 100644 --- a/CPP/7zip/Compress/Rar3Vm.cpp +++ b/CPP/7zip/Compress/Rar3Vm.cpp @@ -34,7 +34,7 @@ UInt32 CMemBitDecoder::ReadBits(unsigned numBits) if (numBits <= avail) { _bitPos += numBits; - return res | (b >> (avail - numBits)) & ((1 << numBits) - 1); + return res | ((b >> (avail - numBits)) & ((1 << numBits) - 1)); } numBits -= avail; res |= (UInt32)(b & ((1 << avail) - 1)) << numBits; diff --git a/CPP/7zip/Compress/Rar5Decoder.cpp b/CPP/7zip/Compress/Rar5Decoder.cpp index d7c68e21..caabb316 100644 --- a/CPP/7zip/Compress/Rar5Decoder.cpp +++ b/CPP/7zip/Compress/Rar5Decoder.cpp @@ -64,16 +64,16 @@ enum FilterType static const size_t kWriteStep = (size_t)1 << 22; CDecoder::CDecoder(): + _isSolid(false), + _solidAllowed(false), + _wasInit(false), + _dictSizeLog(0), _window(NULL), _winPos(0), - _winSizeAllocated(0), _lzSize(0), _lzEnd(0), _writtenFileSize(0), - _dictSizeLog(0), - _isSolid(false), - _solidAllowed(false), - _wasInit(false), + _winSizeAllocated(0), _inputBuf(NULL) { } diff --git a/CPP/7zip/Compress/ShrinkDecoder.cpp b/CPP/7zip/Compress/ShrinkDecoder.cpp index 41f0e352..22f3844c 100644 --- a/CPP/7zip/Compress/ShrinkDecoder.cpp +++ b/CPP/7zip/Compress/ShrinkDecoder.cpp @@ -160,7 +160,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * } } - lastSym = sym; + lastSym = (int)sym; unsigned cur = sym; unsigned i = 0; diff --git a/CPP/7zip/Compress/XpressDecoder.cpp b/CPP/7zip/Compress/XpressDecoder.cpp index 864c6f8f..a8bbd008 100644 --- a/CPP/7zip/Compress/XpressDecoder.cpp +++ b/CPP/7zip/Compress/XpressDecoder.cpp @@ -7,6 +7,7 @@ #include "../../../C/CpuArch.h" #include "HuffmanDecoder.h" +#include "XpressDecoder.h" namespace NCompress { namespace NXpress { diff --git a/CPP/7zip/Compress/XzDecoder.cpp b/CPP/7zip/Compress/XzDecoder.cpp index 7a974311..0371173c 100644 --- a/CPP/7zip/Compress/XzDecoder.cpp +++ b/CPP/7zip/Compress/XzDecoder.cpp @@ -34,7 +34,7 @@ static HRESULT SResToHRESULT_Code(SRes res) throw() HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *progress) { - MainDecodeSRes = S_OK; + MainDecodeSRes = SZ_OK; MainDecodeSRes_wasUsed = false; XzStatInfo_Clear(&Stat); @@ -95,7 +95,7 @@ HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS) RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ) - // return E_OUTOFMEMORY; + // return E_OUTOFMEMORY; // for debug check MainDecodeSRes_wasUsed = true; diff --git a/CPP/7zip/Compress/XzDecoder.h b/CPP/7zip/Compress/XzDecoder.h index b65b46b8..7ad81f49 100644 --- a/CPP/7zip/Compress/XzDecoder.h +++ b/CPP/7zip/Compress/XzDecoder.h @@ -38,8 +38,9 @@ struct CDecoder XzDecMt_Destroy(xz); } - /* Decode() can return ERROR code only if there is progress or stream error. - Decode() returns S_OK in case of xz decoding error, but DecodeRes and CStatInfo contain error information */ + /* Decode() can return S_OK, if there is data after good xz streams, and that data is not new xz stream. + check also (Stat.DataAfterEnd) flag */ + HRESULT Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *compressProgress); }; diff --git a/CPP/7zip/Compress/XzEncoder.cpp b/CPP/7zip/Compress/XzEncoder.cpp index 7dd4d860..d6f42caf 100644 --- a/CPP/7zip/Compress/XzEncoder.cpp +++ b/CPP/7zip/Compress/XzEncoder.cpp @@ -159,7 +159,7 @@ HRESULT CEncoder::SetCoderProp(PROPID propID, const PROPVARIANT &prop) int filterId = FilterIdFromName(prop.bstrVal); if (filterId < 0 /* || filterId == XZ_ID_LZMA2 */) return E_INVALIDARG; - id32 = filterId; + id32 = (unsigned)filterId; } } diff --git a/CPP/7zip/Compress/ZlibDecoder.cpp b/CPP/7zip/Compress/ZlibDecoder.cpp index 8f3a63cb..2356c7c5 100644 --- a/CPP/7zip/Compress/ZlibDecoder.cpp +++ b/CPP/7zip/Compress/ZlibDecoder.cpp @@ -15,6 +15,7 @@ namespace NZlib { #define ADLER_MOD 65521 #define ADLER_LOOP_MAX 5550 +UInt32 Adler32_Update(UInt32 adler, const Byte *buf, size_t size); UInt32 Adler32_Update(UInt32 adler, const Byte *buf, size_t size) { UInt32 a = adler & 0xFFFF; diff --git a/CPP/7zip/Crypto/7zAes.cpp b/CPP/7zip/Crypto/7zAes.cpp index 2ed69bad..7f34e910 100644 --- a/CPP/7zip/Crypto/7zAes.cpp +++ b/CPP/7zip/Crypto/7zAes.cpp @@ -2,9 +2,11 @@ #include "StdAfx.h" +#include "../../../C/CpuArch.h" #include "../../../C/Sha256.h" #include "../../Common/ComTry.h" +#include "../../Common/MyBuffer2.h" #ifndef _7ZIP_ST #include "../../Windows/Synchronization.h" @@ -48,31 +50,65 @@ void CKeyInfo::CalcKey() } else { - size_t bufSize = 8 + SaltSize + Password.Size(); - CObjArray<Byte> buf(bufSize); + const unsigned kUnrPow = 6; + const UInt32 numUnroll = (UInt32)1 << (NumCyclesPower <= kUnrPow ? (unsigned)NumCyclesPower : kUnrPow); + + const size_t bufSize = 8 + SaltSize + Password.Size(); + const size_t unrollSize = bufSize * numUnroll; + + // MY_ALIGN (16) + // CSha256 sha; + CAlignedBuffer sha(sizeof(CSha256) + unrollSize + bufSize * 2); + Byte *buf = sha + sizeof(CSha256); + memcpy(buf, Salt, SaltSize); memcpy(buf + SaltSize, Password, Password.Size()); + memset(buf + bufSize - 8, 0, 8); - CSha256 sha; - Sha256_Init(&sha); - - Byte *ctr = buf + SaltSize + Password.Size(); - - for (unsigned i = 0; i < 8; i++) - ctr[i] = 0; + Sha256_Init((CSha256 *)(void *)(Byte *)sha); + { + { + Byte *dest = buf; + for (UInt32 i = 1; i < numUnroll; i++) + { + dest += bufSize; + memcpy(dest, buf, bufSize); + } + } + + const UInt32 numRounds = (UInt32)1 << NumCyclesPower; + UInt32 r = 0; + do + { + Byte *dest = buf + bufSize - 8; + UInt32 i = r; + r += numUnroll; + do + { + SetUi32(dest, i); i++; dest += bufSize; + // SetUi32(dest, i); i++; dest += bufSize; + } + while (i < r); + Sha256_Update((CSha256 *)(void *)(Byte *)sha, buf, unrollSize); + } + while (r < numRounds); + } + /* UInt64 numRounds = (UInt64)1 << NumCyclesPower; do { - Sha256_Update(&sha, buf, bufSize); + Sha256_Update((CSha256 *)(Byte *)sha, buf, bufSize); for (unsigned i = 0; i < 8; i++) if (++(ctr[i]) != 0) break; } while (--numRounds != 0); + */ - Sha256_Final(&sha, Key); + Sha256_Final((CSha256 *)(void *)(Byte *)sha, Key); + memset(sha, 0, sha.Size()); } } @@ -250,6 +286,7 @@ STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size) { COM_TRY_BEGIN + _key.Password.Wipe(); _key.Password.CopyFrom(data, (size_t)size); return S_OK; diff --git a/CPP/7zip/Crypto/7zAes.h b/CPP/7zip/Crypto/7zAes.h index 84e07ac9..a67ac0b6 100644 --- a/CPP/7zip/Crypto/7zAes.h +++ b/CPP/7zip/Crypto/7zAes.h @@ -37,6 +37,17 @@ public: for (unsigned i = 0; i < sizeof(Salt); i++) Salt[i] = 0; } + + void Wipe() + { + Password.Wipe(); + NumCyclesPower = 0; + SaltSize = 0; + MY_memset_0_ARRAY(Salt); + MY_memset_0_ARRAY(Key); + } + + ~CKeyInfo() { Wipe(); } }; class CKeyInfoCache diff --git a/CPP/7zip/Crypto/7zAesRegister.cpp b/CPP/7zip/Crypto/7zAesRegister.cpp index f9d59699..35605f43 100644 --- a/CPP/7zip/Crypto/7zAesRegister.cpp +++ b/CPP/7zip/Crypto/7zAesRegister.cpp @@ -9,9 +9,9 @@ namespace NCrypto { namespace N7z { -REGISTER_FILTER_E(7zAES, - CDecoder(), - CEncoder(), +REGISTER_FILTER_E(_7zAES, + CDecoder, + CEncoder, 0x6F10701, "7zAES") }} diff --git a/CPP/7zip/Crypto/HmacSha1.cpp b/CPP/7zip/Crypto/HmacSha1.cpp index 359b65bc..d085bb05 100644 --- a/CPP/7zip/Crypto/HmacSha1.cpp +++ b/CPP/7zip/Crypto/HmacSha1.cpp @@ -11,110 +11,82 @@ namespace NSha1 { void CHmac::SetKey(const Byte *key, size_t keySize) { - Byte keyTemp[kBlockSize]; + MY_ALIGN (16) + UInt32 temp[SHA1_NUM_BLOCK_WORDS]; size_t i; - for (i = 0; i < kBlockSize; i++) - keyTemp[i] = 0; + for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++) + temp[i] = 0; if (keySize > kBlockSize) { _sha.Init(); _sha.Update(key, keySize); - _sha.Final(keyTemp); + _sha.Final((Byte *)temp); } else - for (i = 0; i < keySize; i++) - keyTemp[i] = key[i]; + memcpy(temp, key, keySize); - for (i = 0; i < kBlockSize; i++) - keyTemp[i] ^= 0x36; + for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++) + temp[i] ^= 0x36363636; _sha.Init(); - _sha.Update(keyTemp, kBlockSize); + _sha.Update((const Byte *)temp, kBlockSize); - for (i = 0; i < kBlockSize; i++) - keyTemp[i] ^= 0x36 ^ 0x5C; + for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++) + temp[i] ^= 0x36363636 ^ 0x5C5C5C5C; _sha2.Init(); - _sha2.Update(keyTemp, kBlockSize); + _sha2.Update((const Byte *)temp, kBlockSize); } -void CHmac::Final(Byte *mac, size_t macSize) + +void CHmac::Final(Byte *mac) { - Byte digest[kDigestSize]; - _sha.Final(digest); - _sha2.Update(digest, kDigestSize); - _sha2.Final(digest); - for (size_t i = 0; i < macSize; i++) - mac[i] = digest[i]; + _sha.Final(mac); + _sha2.Update(mac, kDigestSize); + _sha2.Final(mac); } -void CHmac32::SetKey(const Byte *key, size_t keySize) +void CHmac::GetLoopXorDigest1(void *mac, UInt32 numIteration) { - UInt32 keyTemp[kNumBlockWords]; - size_t i; - - for (i = 0; i < kNumBlockWords; i++) - keyTemp[i] = 0; - - if (keySize > kBlockSize) - { - CContext sha; - sha.Init(); - sha.Update(key, keySize); - Byte digest[kDigestSize]; - sha.Final(digest); - - for (i = 0 ; i < kNumDigestWords; i++) - keyTemp[i] = GetBe32(digest + i * 4 + 0); - } - else - for (i = 0; i < keySize; i++) - keyTemp[i / 4] |= (key[i] << (24 - 8 * (i & 3))); - - for (i = 0; i < kNumBlockWords; i++) - keyTemp[i] ^= 0x36363636; - - _sha.Init(); - _sha.Update(keyTemp, kNumBlockWords); + MY_ALIGN (16) UInt32 block [SHA1_NUM_BLOCK_WORDS]; + MY_ALIGN (16) UInt32 block2[SHA1_NUM_BLOCK_WORDS]; + MY_ALIGN (16) UInt32 mac2 [SHA1_NUM_BLOCK_WORDS]; - for (i = 0; i < kNumBlockWords; i++) - keyTemp[i] ^= 0x36363636 ^ 0x5C5C5C5C; - - _sha2.Init(); - _sha2.Update(keyTemp, kNumBlockWords); -} + _sha. PrepareBlock((Byte *)block, SHA1_DIGEST_SIZE); + _sha2.PrepareBlock((Byte *)block2, SHA1_DIGEST_SIZE); -void CHmac32::Final(UInt32 *mac, size_t macSize) -{ - UInt32 digest[kNumDigestWords]; - _sha.Final(digest); - _sha2.Update(digest, kNumDigestWords); - _sha2.Final(digest); - for (size_t i = 0; i < macSize; i++) - mac[i] = digest[i]; -} + block[0] = ((const UInt32 *)mac)[0]; + block[1] = ((const UInt32 *)mac)[1]; + block[2] = ((const UInt32 *)mac)[2]; + block[3] = ((const UInt32 *)mac)[3]; + block[4] = ((const UInt32 *)mac)[4]; -void CHmac32::GetLoopXorDigest(UInt32 *mac, UInt32 numIteration) -{ - UInt32 block[kNumBlockWords]; - UInt32 block2[kNumBlockWords]; - - _sha.PrepareBlock(block, kNumDigestWords); - _sha2.PrepareBlock(block2, kNumDigestWords); + mac2[0] = block[0]; + mac2[1] = block[1]; + mac2[2] = block[2]; + mac2[3] = block[3]; + mac2[4] = block[4]; - for (unsigned s = 0; s < kNumDigestWords; s++) - block[s] = mac[s]; - for (UInt32 i = 0; i < numIteration; i++) { - _sha.GetBlockDigest(block, block2); - _sha2.GetBlockDigest(block2, block); - for (unsigned s = 0; s < kNumDigestWords; s++) - mac[s] ^= block[s]; + _sha. GetBlockDigest((const Byte *)block, (Byte *)block2); + _sha2.GetBlockDigest((const Byte *)block2, (Byte *)block); + + mac2[0] ^= block[0]; + mac2[1] ^= block[1]; + mac2[2] ^= block[2]; + mac2[3] ^= block[3]; + mac2[4] ^= block[4]; } + + ((UInt32 *)mac)[0] = mac2[0]; + ((UInt32 *)mac)[1] = mac2[1]; + ((UInt32 *)mac)[2] = mac2[2]; + ((UInt32 *)mac)[3] = mac2[3]; + ((UInt32 *)mac)[4] = mac2[4]; } }} diff --git a/CPP/7zip/Crypto/HmacSha1.h b/CPP/7zip/Crypto/HmacSha1.h index 6ba015e8..d4b21b36 100644 --- a/CPP/7zip/Crypto/HmacSha1.h +++ b/CPP/7zip/Crypto/HmacSha1.h @@ -9,7 +9,7 @@ namespace NCrypto { namespace NSha1 { -// Use: SetKey(key, keySize); for () Update(data, size); Final(mac, macSize); +// Use: SetKey(key, keySize); for () Update(data, size); FinalFull(mac); class CHmac { @@ -18,20 +18,12 @@ class CHmac public: void SetKey(const Byte *key, size_t keySize); void Update(const Byte *data, size_t dataSize) { _sha.Update(data, dataSize); } - void Final(Byte *mac, size_t macSize = kDigestSize); -}; - -class CHmac32 -{ - CContext32 _sha; - CContext32 _sha2; -public: - void SetKey(const Byte *key, size_t keySize); - void Update(const UInt32 *data, size_t dataSize) { _sha.Update(data, dataSize); } - void Final(UInt32 *mac, size_t macSize = kNumDigestWords); - // It'sa for hmac function. in,out: mac[kNumDigestWords]. - void GetLoopXorDigest(UInt32 *mac, UInt32 numIteration); + // Final() : mac is recommended to be aligned for 4 bytes + // GetLoopXorDigest1() : mac is required to be aligned for 4 bytes + // The caller can use: UInt32 mac[NSha1::kNumDigestWords] and typecast to (Byte *) and (void *); + void Final(Byte *mac); + void GetLoopXorDigest1(void *mac, UInt32 numIteration); }; }} diff --git a/CPP/7zip/Crypto/HmacSha256.cpp b/CPP/7zip/Crypto/HmacSha256.cpp index 2e1efb48..cec5e752 100644 --- a/CPP/7zip/Crypto/HmacSha256.cpp +++ b/CPP/7zip/Crypto/HmacSha256.cpp @@ -9,39 +9,38 @@ namespace NCrypto { namespace NSha256 { -static const unsigned kBlockSize = 64; - void CHmac::SetKey(const Byte *key, size_t keySize) { - Byte temp[kBlockSize]; + MY_ALIGN (16) + UInt32 temp[SHA256_NUM_BLOCK_WORDS]; size_t i; - for (i = 0; i < kBlockSize; i++) + for (i = 0; i < SHA256_NUM_BLOCK_WORDS; i++) temp[i] = 0; if (keySize > kBlockSize) { Sha256_Init(&_sha); Sha256_Update(&_sha, key, keySize); - Sha256_Final(&_sha, temp); + Sha256_Final(&_sha, (Byte *)temp); } else - for (i = 0; i < keySize; i++) - temp[i] = key[i]; + memcpy(temp, key, keySize); - for (i = 0; i < kBlockSize; i++) - temp[i] ^= 0x36; + for (i = 0; i < SHA256_NUM_BLOCK_WORDS; i++) + temp[i] ^= 0x36363636; Sha256_Init(&_sha); - Sha256_Update(&_sha, temp, kBlockSize); + Sha256_Update(&_sha, (const Byte *)temp, kBlockSize); - for (i = 0; i < kBlockSize; i++) - temp[i] ^= 0x36 ^ 0x5C; + for (i = 0; i < SHA256_NUM_BLOCK_WORDS; i++) + temp[i] ^= 0x36363636 ^ 0x5C5C5C5C; Sha256_Init(&_sha2); - Sha256_Update(&_sha2, temp, kBlockSize); + Sha256_Update(&_sha2, (const Byte *)temp, kBlockSize); } + void CHmac::Final(Byte *mac) { Sha256_Final(&_sha, mac); @@ -49,14 +48,4 @@ void CHmac::Final(Byte *mac) Sha256_Final(&_sha2, mac); } -/* -void CHmac::Final(Byte *mac, size_t macSize) -{ - Byte digest[SHA256_DIGEST_SIZE]; - Final(digest); - for (size_t i = 0; i < macSize; i++) - mac[i] = digest[i]; -} -*/ - }} diff --git a/CPP/7zip/Crypto/HmacSha256.h b/CPP/7zip/Crypto/HmacSha256.h index 233424a0..d709f43d 100644 --- a/CPP/7zip/Crypto/HmacSha256.h +++ b/CPP/7zip/Crypto/HmacSha256.h @@ -9,6 +9,7 @@ namespace NCrypto { namespace NSha256 { +const unsigned kBlockSize = SHA256_BLOCK_SIZE; const unsigned kDigestSize = SHA256_DIGEST_SIZE; class CHmac @@ -19,7 +20,6 @@ public: void SetKey(const Byte *key, size_t keySize); void Update(const Byte *data, size_t dataSize) { Sha256_Update(&_sha, data, dataSize); } void Final(Byte *mac); - // void Final(Byte *mac, size_t macSize); }; }} diff --git a/CPP/7zip/Crypto/MyAes.cpp b/CPP/7zip/Crypto/MyAes.cpp index 52eaab7a..5cb7f463 100644 --- a/CPP/7zip/Crypto/MyAes.cpp +++ b/CPP/7zip/Crypto/MyAes.cpp @@ -10,91 +10,179 @@ namespace NCrypto { static struct CAesTabInit { CAesTabInit() { AesGenTables();} } g_AesTabInit; -CAesCbcCoder::CAesCbcCoder(bool encodeMode, unsigned keySize): +CAesCoder::CAesCoder(bool encodeMode, unsigned keySize, bool ctrMode): _keySize(keySize), _keyIsSet(false), - _encodeMode(encodeMode) + _encodeMode(encodeMode), + _ctrMode(ctrMode), + _aes(AES_NUM_IVMRK_WORDS * 4 + AES_BLOCK_SIZE * 2) { - _offset = ((0 - (unsigned)(ptrdiff_t)_aes) & 0xF) / sizeof(UInt32); + // _offset = ((0 - (unsigned)(ptrdiff_t)_aes) & 0xF) / sizeof(UInt32); memset(_iv, 0, AES_BLOCK_SIZE); + /* + // we can use the following code to test 32-bit overflow case for AES-CTR + for (unsigned i = 0; i < 16; i++) _iv[i] = (Byte)(i + 1); + _iv[0] = 0xFE; _iv[1] = _iv[2] = _iv[3] = 0xFF; + */ SetFunctions(0); } -STDMETHODIMP CAesCbcCoder::Init() +STDMETHODIMP CAesCoder::Init() { - AesCbc_Init(_aes + _offset, _iv); - return _keyIsSet ? S_OK : E_FAIL; + AesCbc_Init(Aes(), _iv); + return _keyIsSet ? S_OK : E_NOTIMPL; // E_FAIL } -STDMETHODIMP_(UInt32) CAesCbcCoder::Filter(Byte *data, UInt32 size) +STDMETHODIMP_(UInt32) CAesCoder::Filter(Byte *data, UInt32 size) { if (!_keyIsSet) return 0; if (size == 0) return 0; if (size < AES_BLOCK_SIZE) + { + #ifndef _SFX + if (_ctrMode) + { + // use that code only for last block !!! + Byte *ctr = (Byte *)(Aes() + AES_NUM_IVMRK_WORDS); + memset(ctr, 0, AES_BLOCK_SIZE); + memcpy(ctr, data, size); + _codeFunc(Aes(), ctr, 1); + memcpy(data, ctr, size); + return size; + } + #endif return AES_BLOCK_SIZE; + } size >>= 4; - _codeFunc(_aes + _offset, data, size); + _codeFunc(Aes(), data, size); return size << 4; } -STDMETHODIMP CAesCbcCoder::SetKey(const Byte *data, UInt32 size) +STDMETHODIMP CAesCoder::SetKey(const Byte *data, UInt32 size) { if ((size & 0x7) != 0 || size < 16 || size > 32) return E_INVALIDARG; if (_keySize != 0 && size != _keySize) return E_INVALIDARG; - AES_SET_KEY_FUNC setKeyFunc = _encodeMode ? Aes_SetKey_Enc : Aes_SetKey_Dec; - setKeyFunc(_aes + _offset + 4, data, size); + AES_SET_KEY_FUNC setKeyFunc = (_ctrMode | _encodeMode) ? Aes_SetKey_Enc : Aes_SetKey_Dec; + setKeyFunc(Aes() + 4, data, size); _keyIsSet = true; return S_OK; } -STDMETHODIMP CAesCbcCoder::SetInitVector(const Byte *data, UInt32 size) +STDMETHODIMP CAesCoder::SetInitVector(const Byte *data, UInt32 size) { if (size != AES_BLOCK_SIZE) return E_INVALIDARG; memcpy(_iv, data, size); - CAesCbcCoder::Init(); // don't call virtual function here !!! + CAesCoder::Init(); // don't call virtual function here !!! return S_OK; } -EXTERN_C_BEGIN +#ifndef _SFX -void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks); -void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks); -void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks); +#ifdef MY_CPU_X86_OR_AMD64 + #define USE_HW_AES +#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) + #if defined(__clang__) + #if (__clang_major__ >= 8) // fix that check + #define USE_HW_AES + #endif + #elif defined(__GNUC__) + #if (__GNUC__ >= 6) // fix that check + #define USE_HW_AES + #endif + #elif defined(_MSC_VER) + #if _MSC_VER >= 1910 + #define USE_HW_AES + #endif + #endif +#endif -void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks); -void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks); -void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks); +#endif -EXTERN_C_END -bool CAesCbcCoder::SetFunctions(UInt32 algo) +bool CAesCoder::SetFunctions(UInt32 + #ifndef _SFX + algo + #endif + ) { - _codeFunc = _encodeMode ? - g_AesCbc_Encode : - g_AesCbc_Decode; + _codeFunc = g_AesCbc_Decode; + + #ifdef _SFX + + return true; + + #else + + if (_ctrMode) + _codeFunc = g_AesCtr_Code; + else if (_encodeMode) + _codeFunc = g_AesCbc_Encode; + + if (algo < 1) + return true; + if (algo == 1) { - _codeFunc = _encodeMode ? - AesCbc_Encode: - AesCbc_Decode; + _codeFunc = AesCbc_Decode; + + #ifndef _SFX + if (_ctrMode) + _codeFunc = AesCtr_Code; + else if (_encodeMode) + _codeFunc = AesCbc_Encode; + #endif + return true; } - if (algo == 2) + + #ifdef USE_HW_AES + // if (CPU_IsSupported_AES()) { - #ifdef MY_CPU_X86_OR_AMD64 - if (g_AesCbc_Encode != AesCbc_Encode_Intel) + if (algo == 2) + if (g_Aes_SupportedFunctions_Flags & k_Aes_SupportedFunctions_HW) + { + _codeFunc = AesCbc_Decode_HW; + #ifndef _SFX + if (_ctrMode) + _codeFunc = AesCtr_Code_HW; + else if (_encodeMode) + _codeFunc = AesCbc_Encode_HW; + #endif + return true; + } + + #if defined(MY_CPU_X86_OR_AMD64) + if (algo == 3) + if (g_Aes_SupportedFunctions_Flags & k_Aes_SupportedFunctions_HW_256) + { + _codeFunc = AesCbc_Decode_HW_256; + #ifndef _SFX + if (_ctrMode) + _codeFunc = AesCtr_Code_HW_256; + else if (_encodeMode) + _codeFunc = AesCbc_Encode_HW; + #endif + return true; + } #endif - return false; } - return true; + #endif + + return false; + + #endif } -STDMETHODIMP CAesCbcCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) + +#ifndef _SFX + +STDMETHODIMP CAesCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) { + UInt32 algo = 0; for (UInt32 i = 0; i < numProps; i++) { const PROPVARIANT &prop = coderProps[i]; @@ -102,11 +190,16 @@ STDMETHODIMP CAesCbcCoder::SetCoderProperties(const PROPID *propIDs, const PROPV { if (prop.vt != VT_UI4) return E_INVALIDARG; - if (!SetFunctions(prop.ulVal)) + if (prop.ulVal > 3) return E_NOTIMPL; + algo = prop.ulVal; } } + if (!SetFunctions(algo)) + return E_NOTIMPL; return S_OK; } +#endif + } diff --git a/CPP/7zip/Crypto/MyAes.h b/CPP/7zip/Crypto/MyAes.h index 182411db..a60042be 100644 --- a/CPP/7zip/Crypto/MyAes.h +++ b/CPP/7zip/Crypto/MyAes.h @@ -5,51 +5,73 @@ #include "../../../C/Aes.h" +#include "../../Common/MyBuffer2.h" #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCrypto { -class CAesCbcCoder: +class CAesCoder: public ICompressFilter, public ICryptoProperties, + #ifndef _SFX public ICompressSetCoderProperties, + #endif public CMyUnknownImp { AES_CODE_FUNC _codeFunc; - unsigned _offset; + // unsigned _offset; unsigned _keySize; bool _keyIsSet; bool _encodeMode; - UInt32 _aes[AES_NUM_IVMRK_WORDS + 3]; + bool _ctrMode; + + // UInt32 _aes[AES_NUM_IVMRK_WORDS + 3]; + CAlignedBuffer _aes; + Byte _iv[AES_BLOCK_SIZE]; + // UInt32 *Aes() { return _aes + _offset; } + UInt32 *Aes() { return (UInt32 *)(void *)(Byte *)_aes; } + bool SetFunctions(UInt32 algo); public: - CAesCbcCoder(bool encodeMode, unsigned keySize); + CAesCoder(bool encodeMode, unsigned keySize, bool ctrMode); - virtual ~CAesCbcCoder() {}; // we need virtual destructor for derived classes + virtual ~CAesCoder() {}; // we need virtual destructor for derived classes - MY_UNKNOWN_IMP3(ICompressFilter, ICryptoProperties, ICompressSetCoderProperties) + MY_QUERYINTERFACE_BEGIN2(ICompressFilter) + MY_QUERYINTERFACE_ENTRY(ICryptoProperties) + #ifndef _SFX + MY_QUERYINTERFACE_ENTRY(ICompressSetCoderProperties) + #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE INTERFACE_ICompressFilter(;) + + void SetKeySize(unsigned size) { _keySize = size; } STDMETHOD(SetKey)(const Byte *data, UInt32 size); STDMETHOD(SetInitVector)(const Byte *data, UInt32 size); + #ifndef _SFX STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + #endif }; -struct CAesCbcEncoder: public CAesCbcCoder +#ifndef _SFX +struct CAesCbcEncoder: public CAesCoder { - CAesCbcEncoder(unsigned keySize = 0): CAesCbcCoder(true, keySize) {} + CAesCbcEncoder(unsigned keySize = 0): CAesCoder(true, keySize, false) {} }; +#endif -struct CAesCbcDecoder: public CAesCbcCoder +struct CAesCbcDecoder: public CAesCoder { - CAesCbcDecoder(unsigned keySize = 0): CAesCbcCoder(false, keySize) {} + CAesCbcDecoder(unsigned keySize = 0): CAesCoder(false, keySize, false) {} }; } diff --git a/CPP/7zip/Crypto/MyAesReg.cpp b/CPP/7zip/Crypto/MyAesReg.cpp index 28006835..86bd2547 100644 --- a/CPP/7zip/Crypto/MyAesReg.cpp +++ b/CPP/7zip/Crypto/MyAesReg.cpp @@ -8,9 +8,23 @@ namespace NCrypto { -REGISTER_FILTER_E(AES256CBC, - CAesCbcDecoder(32), - CAesCbcEncoder(32), - 0x6F00181, "AES256CBC") +#ifndef _SFX + +#define REGISTER_AES_2(name, nameString, keySize, isCtr) \ + REGISTER_FILTER_E(name, \ + CAesCoder(false, keySize, isCtr), \ + CAesCoder(true , keySize, isCtr), \ + 0x6F00100 | ((keySize - 16) * 8) | (isCtr ? 4 : 1), \ + nameString) \ + +#define REGISTER_AES(name, nameString, isCtr) \ + /* REGISTER_AES_2(AES128 ## name, "AES128" nameString, 16, isCtr) */ \ + /* REGISTER_AES_2(AES192 ## name, "AES192" nameString, 24, isCtr) */ \ + REGISTER_AES_2(AES256 ## name, "AES256" nameString, 32, isCtr) \ + +REGISTER_AES(CBC, "CBC", false) +// REGISTER_AES(CTR, "CTR", true) + +#endif } diff --git a/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp b/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp index a7fcb728..6b504ee9 100644 --- a/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp +++ b/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp @@ -5,6 +5,7 @@ #include "../../../C/CpuArch.h" #include "HmacSha1.h" +#include "Pbkdf2HmacSha1.h" namespace NCrypto { namespace NSha1 { @@ -14,81 +15,29 @@ void Pbkdf2Hmac(const Byte *pwd, size_t pwdSize, UInt32 numIterations, Byte *key, size_t keySize) { + MY_ALIGN (16) CHmac baseCtx; baseCtx.SetKey(pwd, pwdSize); for (UInt32 i = 1; keySize != 0; i++) { - CHmac ctx = baseCtx; + MY_ALIGN (16) + CHmac ctx; + ctx = baseCtx; ctx.Update(salt, saltSize); - Byte u[kDigestSize]; - SetBe32(u, i); - - ctx.Update(u, 4); - ctx.Final(u, kDigestSize); - - const unsigned curSize = (keySize < kDigestSize) ? (unsigned)keySize : kDigestSize; - unsigned s; - for (s = 0; s < curSize; s++) - key[s] = u[s]; - - for (UInt32 j = numIterations; j > 1; j--) - { - ctx = baseCtx; - ctx.Update(u, kDigestSize); - ctx.Final(u, kDigestSize); - for (s = 0; s < curSize; s++) - key[s] ^= u[s]; - } - - key += curSize; - keySize -= curSize; - } -} - -void Pbkdf2Hmac32(const Byte *pwd, size_t pwdSize, - const UInt32 *salt, size_t saltSize, - UInt32 numIterations, - UInt32 *key, size_t keySize) -{ - CHmac32 baseCtx; - baseCtx.SetKey(pwd, pwdSize); - - for (UInt32 i = 1; keySize != 0; i++) - { - CHmac32 ctx = baseCtx; - ctx.Update(salt, saltSize); - + MY_ALIGN (16) UInt32 u[kNumDigestWords]; - u[0] = i; + SetBe32(u, i); - ctx.Update(u, 1); - ctx.Final(u, kNumDigestWords); + ctx.Update((const Byte *)u, 4); + ctx.Final((Byte *)u); - // Speed-optimized code start ctx = baseCtx; - ctx.GetLoopXorDigest(u, numIterations - 1); - // Speed-optimized code end - - const unsigned curSize = (keySize < kNumDigestWords) ? (unsigned)keySize : kNumDigestWords; - unsigned s; - for (s = 0; s < curSize; s++) - key[s] = u[s]; - - /* - // Default code start - for (UInt32 j = numIterations; j > 1; j--) - { - ctx = baseCtx; - ctx.Update(u, kNumDigestWords); - ctx.Final(u, kNumDigestWords); - for (s = 0; s < curSize; s++) - key[s] ^= u[s]; - } - // Default code end - */ + ctx.GetLoopXorDigest1((void *)u, numIterations - 1); + const unsigned curSize = (keySize < kDigestSize) ? (unsigned)keySize : kDigestSize;; + memcpy(key, (const Byte *)u, curSize); key += curSize; keySize -= curSize; } diff --git a/CPP/7zip/Crypto/Pbkdf2HmacSha1.h b/CPP/7zip/Crypto/Pbkdf2HmacSha1.h index 6560b8d1..e9462e47 100644 --- a/CPP/7zip/Crypto/Pbkdf2HmacSha1.h +++ b/CPP/7zip/Crypto/Pbkdf2HmacSha1.h @@ -14,9 +14,6 @@ namespace NSha1 { void Pbkdf2Hmac(const Byte *pwd, size_t pwdSize, const Byte *salt, size_t saltSize, UInt32 numIterations, Byte *key, size_t keySize); -void Pbkdf2Hmac32(const Byte *pwd, size_t pwdSize, const UInt32 *salt, size_t saltSize, - UInt32 numIterations, UInt32 *key, size_t keySize); - }} #endif diff --git a/CPP/7zip/Crypto/RandGen.cpp b/CPP/7zip/Crypto/RandGen.cpp index f98878f5..65633fd8 100644 --- a/CPP/7zip/Crypto/RandGen.cpp +++ b/CPP/7zip/Crypto/RandGen.cpp @@ -19,7 +19,7 @@ #ifdef USE_STATIC_RtlGenRandom -#include <ntsecapi.h> +// #include <NTSecAPI.h> EXTERN_C_BEGIN #ifndef RtlGenRandom @@ -59,6 +59,7 @@ EXTERN_C_END void CRandomGenerator::Init() { + MY_ALIGN (16) CSha256 hash; Sha256_Init(&hash); @@ -68,6 +69,7 @@ void CRandomGenerator::Init() #ifndef UNDER_CE const unsigned kNumIterations_Small = 100; const unsigned kBufSize = 32; + MY_ALIGN (16) Byte buf[kBufSize]; #endif @@ -98,7 +100,7 @@ void CRandomGenerator::Init() if (hModule) { // SystemFunction036() is real name of RtlGenRandom() function - Func_RtlGenRandom my_RtlGenRandom = (Func_RtlGenRandom)GetProcAddress(hModule, "SystemFunction036"); + Func_RtlGenRandom my_RtlGenRandom = (Func_RtlGenRandom)(void *)GetProcAddress(hModule, "SystemFunction036"); if (my_RtlGenRandom) { if (my_RtlGenRandom(buf, kBufSize)) @@ -126,11 +128,11 @@ void CRandomGenerator::Init() { do { - int n = read(f, buf, numBytes); + ssize_t n = read(f, buf, numBytes); if (n <= 0) break; - Sha256_Update(&hash, buf, n); - numBytes -= n; + Sha256_Update(&hash, buf, (size_t)n); + numBytes -= (unsigned)n; } while (numBytes); close(f); @@ -211,6 +213,7 @@ void CRandomGenerator::Generate(Byte *data, unsigned size) Init(); while (size != 0) { + MY_ALIGN (16) CSha256 hash; Sha256_Init(&hash); @@ -221,6 +224,7 @@ void CRandomGenerator::Generate(Byte *data, unsigned size) UInt32 salt = 0xF672ABD1; HASH_UPD(salt); Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE); + MY_ALIGN (16) Byte buff[SHA256_DIGEST_SIZE]; Sha256_Final(&hash, buff); for (unsigned i = 0; i < SHA256_DIGEST_SIZE && size != 0; i++, size--) diff --git a/CPP/7zip/Crypto/Rar20Crypto.cpp b/CPP/7zip/Crypto/Rar20Crypto.cpp index 878dfc5c..2bbaa931 100644 --- a/CPP/7zip/Crypto/Rar20Crypto.cpp +++ b/CPP/7zip/Crypto/Rar20Crypto.cpp @@ -54,7 +54,7 @@ void CData::SetPassword(const Byte *data, unsigned size) Keys[3] = 0xA4E7F123L; Byte psw[128]; - memset(psw, 0, sizeof(psw)); + MY_memset_0_ARRAY(psw); if (size != 0) { if (size >= sizeof(psw)) diff --git a/CPP/7zip/Crypto/Rar20Crypto.h b/CPP/7zip/Crypto/Rar20Crypto.h index 6d1d0f5d..596619ce 100644 --- a/CPP/7zip/Crypto/Rar20Crypto.h +++ b/CPP/7zip/Crypto/Rar20Crypto.h @@ -28,6 +28,13 @@ class CData void UpdateKeys(const Byte *data); void CryptBlock(Byte *buf, bool encrypt); public: + ~CData() { Wipe(); } + void Wipe() + { + MY_memset_0_ARRAY(SubstTable); + MY_memset_0_ARRAY(Keys); + } + void EncryptBlock(Byte *buf) { CryptBlock(buf, true); } void DecryptBlock(Byte *buf) { CryptBlock(buf, false); } void SetPassword(const Byte *password, unsigned passwordLen); diff --git a/CPP/7zip/Crypto/Rar5Aes.cpp b/CPP/7zip/Crypto/Rar5Aes.cpp index 005fa6bc..5834bbb7 100644 --- a/CPP/7zip/Crypto/Rar5Aes.cpp +++ b/CPP/7zip/Crypto/Rar5Aes.cpp @@ -9,6 +9,7 @@ #endif #include "Rar5Aes.h" +#include "HmacSha256.h" namespace NCrypto { namespace NRar5 { @@ -122,6 +123,7 @@ void CDecoder::SetPassword(const Byte *data, size_t size) if (size != _password.Size() || memcmp(data, _password, size) != 0) { _needCalc = true; + _password.Wipe(); _password.CopyFrom(data, size); } } @@ -132,28 +134,31 @@ STDMETHODIMP CDecoder::Init() CalcKey_and_CheckPassword(); RINOK(SetKey(_key, kAesKeySize)); RINOK(SetInitVector(_iv, AES_BLOCK_SIZE)); - return CAesCbcCoder::Init(); + return CAesCoder::Init(); } UInt32 CDecoder::Hmac_Convert_Crc32(UInt32 crc) const { + MY_ALIGN (16) NSha256::CHmac ctx; ctx.SetKey(_hashKey, NSha256::kDigestSize); - Byte v[4]; - SetUi32(v, crc); - ctx.Update(v, 4); - Byte h[NSha256::kDigestSize]; - ctx.Final(h); + UInt32 v; + SetUi32(&v, crc); + ctx.Update((const Byte *)&v, 4); + MY_ALIGN (16) + UInt32 h[SHA256_NUM_DIGEST_WORDS]; + ctx.Final((Byte *)h); crc = 0; - for (unsigned i = 0; i < NSha256::kDigestSize; i++) - crc ^= (UInt32)h[i] << ((i & 3) * 8); + for (unsigned i = 0; i < SHA256_NUM_DIGEST_WORDS; i++) + crc ^= (UInt32)GetUi32(h + i); return crc; }; void CDecoder::Hmac_Convert_32Bytes(Byte *data) const { + MY_ALIGN (16) NSha256::CHmac ctx; ctx.SetKey(_hashKey, NSha256::kDigestSize); ctx.Update(data, NSha256::kDigestSize); @@ -190,13 +195,16 @@ bool CDecoder::CalcKey_and_CheckPassword() { // Pbkdf HMAC-SHA-256 + MY_ALIGN (16) NSha256::CHmac baseCtx; baseCtx.SetKey(_password, _password.Size()); NSha256::CHmac ctx = baseCtx; ctx.Update(_salt, sizeof(_salt)); + MY_ALIGN (16) Byte u[NSha256::kDigestSize]; + MY_ALIGN (16) Byte key[NSha256::kDigestSize]; u[0] = 0; diff --git a/CPP/7zip/Crypto/Rar5Aes.h b/CPP/7zip/Crypto/Rar5Aes.h index c69b24e4..e779c17b 100644 --- a/CPP/7zip/Crypto/Rar5Aes.h +++ b/CPP/7zip/Crypto/Rar5Aes.h @@ -3,11 +3,10 @@ #ifndef __CRYPTO_RAR5_AES_H #define __CRYPTO_RAR5_AES_H -#include "../../../C/Aes.h" +#include "../../../C/Sha256.h" #include "../../Common/MyBuffer.h" -#include "HmacSha256.h" #include "MyAes.h" namespace NCrypto { @@ -50,6 +49,17 @@ struct CKey } CKey(); + + void Wipe() + { + _password.Wipe(); + MY_memset_0_ARRAY(_salt); + MY_memset_0_ARRAY(_key); + MY_memset_0_ARRAY(_check_Calced); + MY_memset_0_ARRAY(_hashKey); + } + + ~CKey() { Wipe(); } }; diff --git a/CPP/7zip/Crypto/RarAes.cpp b/CPP/7zip/Crypto/RarAes.cpp index 98e9f62d..aa9444cf 100644 --- a/CPP/7zip/Crypto/RarAes.cpp +++ b/CPP/7zip/Crypto/RarAes.cpp @@ -2,6 +2,9 @@ #include "StdAfx.h" +#include "../../../C/CpuArch.h" +#include "../../../C/RotateDefs.h" + #include "RarAes.h" #include "Sha1Cls.h" @@ -71,6 +74,7 @@ void CDecoder::SetPassword(const Byte *data, unsigned size) } if (!_needCalc && !same) _needCalc = true; + _password.Wipe(); _password.CopyFrom(data, (size_t)size); } @@ -79,9 +83,44 @@ STDMETHODIMP CDecoder::Init() CalcKey(); RINOK(SetKey(_key, kAesKeySize)); RINOK(SetInitVector(_iv, AES_BLOCK_SIZE)); - return CAesCbcCoder::Init(); + return CAesCoder::Init(); } + +// if (password_size_in_bytes + SaltSize > 64), +// the original rar code updates password_with_salt buffer +// with some generated data from SHA1 code. + +// #define RAR_SHA1_REDUCE + +#ifdef RAR_SHA1_REDUCE + #define kNumW 16 + #define WW(i) W[(i)&15] +#else + #define kNumW 80 + #define WW(i) W[i] +#endif + +static void UpdatePswDataSha1(Byte *data) +{ + UInt32 W[kNumW]; + size_t i; + + for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++) + W[i] = GetBe32(data + i * 4); + + for (i = 16; i < 80; i++) + { + WW(i) = rotlFixed(WW((i)-3) ^ WW((i)-8) ^ WW((i)-14) ^ WW((i)-16), 1); + } + + for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++) + { + SetUi32(data + i * 4, W[kNumW - SHA1_NUM_BLOCK_WORDS + i]); + } +} + + void CDecoder::CalcKey() { if (!_needCalc) @@ -102,20 +141,42 @@ void CDecoder::CalcKey() rawSize += kSaltSize; } + MY_ALIGN (16) NSha1::CContext sha; sha.Init(); + MY_ALIGN (16) Byte digest[NSha1::kDigestSize]; // rar reverts hash for sha. const UInt32 kNumRounds = ((UInt32)1 << 18); + UInt32 pos = 0; UInt32 i; for (i = 0; i < kNumRounds; i++) { - sha.UpdateRar(buf, rawSize /* , _rar350Mode */); + sha.Update(buf, rawSize); + // if (_rar350Mode) + { + const UInt32 kBlockSize = 64; + const UInt32 endPos = (pos + (UInt32)rawSize) & ~(kBlockSize - 1); + if (endPos > pos + kBlockSize) + { + UInt32 curPos = pos & ~(kBlockSize - 1); + curPos += kBlockSize; + do + { + UpdatePswDataSha1(buf + (curPos - pos)); + curPos += kBlockSize; + } + while (curPos != endPos); + } + } + pos += (UInt32)rawSize; Byte pswNum[3] = { (Byte)i, (Byte)(i >> 8), (Byte)(i >> 16) }; - sha.UpdateRar(pswNum, 3 /* , _rar350Mode */); + sha.Update(pswNum, 3); + pos += 3; if (i % (kNumRounds / 16) == 0) { + MY_ALIGN (16) NSha1::CContext shaTemp = sha; shaTemp.Final(digest); _iv[i / (kNumRounds / 16)] = (Byte)digest[4 * 4 + 3]; diff --git a/CPP/7zip/Crypto/RarAes.h b/CPP/7zip/Crypto/RarAes.h index 645da1af..2bb68667 100644 --- a/CPP/7zip/Crypto/RarAes.h +++ b/CPP/7zip/Crypto/RarAes.h @@ -44,6 +44,15 @@ public: HRESULT SetDecoderProperties2(const Byte *data, UInt32 size); CDecoder(); + + ~CDecoder() { Wipe(); } + void Wipe() + { + _password.Wipe(); + MY_memset_0_ARRAY(_salt); + MY_memset_0_ARRAY(_key); + MY_memset_0_ARRAY(_iv); + } // void SetRar350Mode(bool rar350Mode) { _rar350Mode = rar350Mode; } }; diff --git a/CPP/7zip/Crypto/Sha1Cls.h b/CPP/7zip/Crypto/Sha1Cls.h index 71acbdec..34616782 100644 --- a/CPP/7zip/Crypto/Sha1Cls.h +++ b/CPP/7zip/Crypto/Sha1Cls.h @@ -1,7 +1,7 @@ -// Crypto/Sha1.h +// Crypto/Sha1Cls.h -#ifndef __CRYPTO_SHA1_H -#define __CRYPTO_SHA1_H +#ifndef __CRYPTO_SHA1_CLS_H +#define __CRYPTO_SHA1_CLS_H #include "../../../C/Sha1.h" @@ -14,35 +14,21 @@ const unsigned kNumDigestWords = SHA1_NUM_DIGEST_WORDS; const unsigned kBlockSize = SHA1_BLOCK_SIZE; const unsigned kDigestSize = SHA1_DIGEST_SIZE; -class CContextBase +class CContext { -protected: CSha1 _s; public: void Init() throw() { Sha1_Init(&_s); } - void GetBlockDigest(const UInt32 *blockData, UInt32 *destDigest) throw() { Sha1_GetBlockDigest(&_s, blockData, destDigest); } -}; - -class CContext: public CContextBase -{ -public: void Update(const Byte *data, size_t size) throw() { Sha1_Update(&_s, data, size); } - void UpdateRar(Byte *data, size_t size /* , bool rar350Mode */) throw() { Sha1_Update_Rar(&_s, data, size /* , rar350Mode ? 1 : 0 */); } void Final(Byte *digest) throw() { Sha1_Final(&_s, digest); } -}; - -class CContext32: public CContextBase -{ -public: - void Update(const UInt32 *data, size_t size) throw() { Sha1_32_Update(&_s, data, size); } - void Final(UInt32 *digest) throw() { Sha1_32_Final(&_s, digest); } - - /* PrepareBlock can be used only when size <= 13. size in Words - _buffer must be empty (_count & 0xF) == 0) */ - void PrepareBlock(UInt32 *block, unsigned size) const throw() + void PrepareBlock(Byte *block, unsigned size) const throw() + { + Sha1_PrepareBlock(&_s, block, size); + } + void GetBlockDigest(const Byte *blockData, Byte *destDigest) const throw() { - Sha1_32_PrepareBlock(&_s, block, size); + Sha1_GetBlockDigest(&_s, blockData, destDigest); } }; diff --git a/CPP/7zip/Crypto/WzAes.cpp b/CPP/7zip/Crypto/WzAes.cpp index d415ab84..b422b501 100644 --- a/CPP/7zip/Crypto/WzAes.cpp +++ b/CPP/7zip/Crypto/WzAes.cpp @@ -16,9 +16,6 @@ Note: you must include MyAes.cpp to project to initialize AES tables #include "RandGen.h" #include "WzAes.h" -// define it if you don't want to use speed-optimized version of NSha1::Pbkdf2Hmac -// #define _NO_WZAES_OPTIMIZATIONS - namespace NCrypto { namespace NWzAes { @@ -30,6 +27,7 @@ STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size) { if (size > kPasswordSizeMax) return E_INVALIDARG; + _key.Password.Wipe(); _key.Password.CopyFrom(data, (size_t)size); return S_OK; } @@ -40,52 +38,25 @@ void CBaseCoder::Init2() Byte dk[dkSizeMax32 * 4]; const unsigned keySize = _key.GetKeySize(); - const unsigned dkSize = 2 * keySize + kPwdVerifSize; + const unsigned dkSize = 2 * keySize + ((kPwdVerifSize + 3) & ~(unsigned)3); // for (unsigned ii = 0; ii < 1000; ii++) { - #ifdef _NO_WZAES_OPTIMIZATIONS - NSha1::Pbkdf2Hmac( _key.Password, _key.Password.Size(), _key.Salt, _key.GetSaltSize(), kNumKeyGenIterations, dk, dkSize); - - #else - - UInt32 dk32[dkSizeMax32]; - const unsigned dkSize32 = (dkSize + 3) / 4; - UInt32 salt[kSaltSizeMax / 4]; - unsigned numSaltWords = _key.GetNumSaltWords(); - - for (unsigned i = 0; i < numSaltWords; i++) - { - const Byte *src = _key.Salt + i * 4; - salt[i] = GetBe32(src); - } - - NSha1::Pbkdf2Hmac32( - _key.Password, _key.Password.Size(), - salt, numSaltWords, - kNumKeyGenIterations, - dk32, dkSize32); - - /* - for (unsigned j = 0; j < dkSize; j++) - dk[j] = (Byte)(dk32[j / 4] >> (24 - 8 * (j & 3))); - */ - for (unsigned j = 0; j < dkSize32; j++) - SetBe32(dk + j * 4, dk32[j]); - - #endif } - _hmac.SetKey(dk + keySize, keySize); + Hmac()->SetKey(dk + keySize, keySize); memcpy(_key.PwdVerifComputed, dk + 2 * keySize, kPwdVerifSize); - Aes_SetKey_Enc(_aes.aes + _aes.offset + 8, dk, keySize); - AesCtr2_Init(&_aes); + // Aes_SetKey_Enc(_aes.Aes() + 8, dk, keySize); + // AesCtr2_Init(&_aes); + _aesCoderSpec->SetKeySize(keySize); + if (_aesCoderSpec->SetKey(dk, keySize) != S_OK) throw 2; + if (_aesCoderSpec->Init() != S_OK) throw 3; } STDMETHODIMP CBaseCoder::Init() @@ -104,8 +75,9 @@ HRESULT CEncoder::WriteHeader(ISequentialOutStream *outStream) HRESULT CEncoder::WriteFooter(ISequentialOutStream *outStream) { - Byte mac[kMacSize]; - _hmac.Final(mac, kMacSize); + MY_ALIGN (16) + UInt32 mac[NSha1::kNumDigestWords]; + Hmac()->Final((Byte *)mac); return WriteStream(outStream, mac, kMacSize); } @@ -150,34 +122,41 @@ bool CDecoder::Init_and_CheckPassword() HRESULT CDecoder::CheckMac(ISequentialInStream *inStream, bool &isOK) { isOK = false; + MY_ALIGN (16) Byte mac1[kMacSize]; RINOK(ReadStream_FAIL(inStream, mac1, kMacSize)); - Byte mac2[kMacSize]; - _hmac.Final(mac2, kMacSize); - isOK = CompareArrays(mac1, mac2, kMacSize); + MY_ALIGN (16) + UInt32 mac2[NSha1::kNumDigestWords]; + Hmac()->Final((Byte *)mac2); + isOK = CompareArrays(mac1, (const Byte *)mac2, kMacSize); return S_OK; } -CAesCtr2::CAesCtr2() +/* + +CAesCtr2::CAesCtr2(): + aes((4 + AES_NUM_IVMRK_WORDS) * 4) { - offset = ((0 - (unsigned)(ptrdiff_t)aes) & 0xF) / sizeof(UInt32); + // offset = ((0 - (unsigned)(ptrdiff_t)aes) & 0xF) / sizeof(UInt32); + // first 16 bytes are buffer for last block data. + // so the ivAES is aligned for (Align + 16). } void AesCtr2_Init(CAesCtr2 *p) { - UInt32 *ctr = p->aes + p->offset + 4; + UInt32 *ctr = p->Aes() + 4; unsigned i; for (i = 0; i < 4; i++) ctr[i] = 0; p->pos = AES_BLOCK_SIZE; } -/* (size != 16 * N) is allowed only for last call */ +// (size != 16 * N) is allowed only for last call void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size) { unsigned pos = p->pos; - UInt32 *buf32 = p->aes + p->offset; + UInt32 *buf32 = p->Aes(); if (size == 0) return; @@ -188,6 +167,8 @@ void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size) *data++ ^= buf[pos++]; while (--size != 0 && pos != AES_BLOCK_SIZE); } + + // (size == 0 || pos == AES_BLOCK_SIZE) if (size >= 16) { @@ -196,8 +177,10 @@ void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size) size2 <<= 4; data += size2; size -= size2; - pos = AES_BLOCK_SIZE; + // (pos == AES_BLOCK_SIZE) } + + // (size < 16) if (size != 0) { @@ -215,20 +198,26 @@ void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size) p->pos = pos; } +*/ /* (size != 16 * N) is allowed only for last Filter() call */ STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size) { - AesCtr2_Code(&_aes, data, size); - _hmac.Update(data, size); + // AesCtr2_Code(&_aes, data, size); + size = _aesCoder->Filter(data, size); + Hmac()->Update(data, size); return size; } STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size) { - _hmac.Update(data, size); - AesCtr2_Code(&_aes, data, size); + if (size >= 16) + size &= ~(UInt32)15; + + Hmac()->Update(data, size); + // AesCtr2_Code(&_aes, data, size); + size = _aesCoder->Filter(data, size); return size; } diff --git a/CPP/7zip/Crypto/WzAes.h b/CPP/7zip/Crypto/WzAes.h index 3b22bc16..fa6221c5 100644 --- a/CPP/7zip/Crypto/WzAes.h +++ b/CPP/7zip/Crypto/WzAes.h @@ -12,15 +12,12 @@ specified in "A Password Based File Encryption Utility": #ifndef __CRYPTO_WZ_AES_H #define __CRYPTO_WZ_AES_H -#include "../../../C/Aes.h" - #include "../../Common/MyBuffer.h" -#include "../../Common/MyCom.h" -#include "../ICoder.h" #include "../IPassword.h" #include "HmacSha1.h" +#include "MyAes.h" namespace NCrypto { namespace NWzAes { @@ -64,18 +61,33 @@ struct CKeyInfo unsigned GetNumSaltWords() const { return (KeySizeMode + 1); } CKeyInfo(): KeySizeMode(kKeySizeMode_AES256) {} + + void Wipe() + { + Password.Wipe(); + MY_memset_0_ARRAY(Salt); + MY_memset_0_ARRAY(PwdVerifComputed); + } + + ~CKeyInfo() { Wipe(); } }; +/* struct CAesCtr2 { unsigned pos; - unsigned offset; - UInt32 aes[4 + AES_NUM_IVMRK_WORDS + 3]; + CAlignedBuffer aes; + UInt32 *Aes() { return (UInt32 *)(Byte *)aes; } + + // unsigned offset; + // UInt32 aes[4 + AES_NUM_IVMRK_WORDS + 3]; + // UInt32 *Aes() { return aes + offset; } CAesCtr2(); }; void AesCtr2_Init(CAesCtr2 *p); void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size); +*/ class CBaseCoder: public ICompressFilter, @@ -84,8 +96,21 @@ class CBaseCoder: { protected: CKeyInfo _key; - NSha1::CHmac _hmac; - CAesCtr2 _aes; + + // NSha1::CHmac _hmac; + // NSha1::CHmac *Hmac() { return &_hmac; } + CAlignedBuffer _hmacBuf; + NSha1::CHmac *Hmac() { return (NSha1::CHmac *)(void *)(Byte *)_hmacBuf; } + + // CAesCtr2 _aes; + CAesCoder *_aesCoderSpec; + CMyComPtr<ICompressFilter> _aesCoder; + CBaseCoder(): + _hmacBuf(sizeof(NSha1::CHmac)) + { + _aesCoderSpec = new CAesCoder(true, 32, true); + _aesCoder = _aesCoderSpec; + } void Init2(); public: diff --git a/CPP/7zip/Crypto/ZipCrypto.h b/CPP/7zip/Crypto/ZipCrypto.h index acc0b031..d2fe4c4f 100644 --- a/CPP/7zip/Crypto/ZipCrypto.h +++ b/CPP/7zip/Crypto/ZipCrypto.h @@ -51,7 +51,12 @@ public: STDMETHOD(Init)(); STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); - virtual ~CCipher() {} + virtual ~CCipher() + { + Key0 = KeyMem0 = + Key1 = KeyMem1 = + Key2 = KeyMem2 = 0; + } }; class CEncoder: public CCipher diff --git a/CPP/7zip/Crypto/ZipStrong.cpp b/CPP/7zip/Crypto/ZipStrong.cpp index 22a905cb..895ce949 100644 --- a/CPP/7zip/Crypto/ZipStrong.cpp +++ b/CPP/7zip/Crypto/ZipStrong.cpp @@ -26,10 +26,12 @@ static const UInt16 kAES128 = 0x660E; static void DeriveKey2(const Byte *digest, Byte c, Byte *dest) { + MY_ALIGN (16) Byte buf[64]; memset(buf, c, 64); for (unsigned i = 0; i < NSha1::kDigestSize; i++) buf[i] ^= digest[i]; + MY_ALIGN (16) NSha1::CContext sha; sha.Init(); sha.Update(buf, 64); @@ -38,8 +40,10 @@ static void DeriveKey2(const Byte *digest, Byte c, Byte *dest) static void DeriveKey(NSha1::CContext &sha, Byte *key) { + MY_ALIGN (16) Byte digest[NSha1::kDigestSize]; sha.Final(digest); + MY_ALIGN (16) Byte temp[NSha1::kDigestSize * 2]; DeriveKey2(digest, 0x36, temp); DeriveKey2(digest, 0x5C, temp + NSha1::kDigestSize); @@ -48,6 +52,7 @@ static void DeriveKey(NSha1::CContext &sha, Byte *key) void CKeyInfo::SetPassword(const Byte *data, UInt32 size) { + MY_ALIGN (16) NSha1::CContext sha; sha.Init(); sha.Update(data, size); @@ -103,21 +108,21 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK) if (_remSize < 16) return E_NOTIMPL; Byte *p = _bufAligned; - UInt16 format = GetUi16(p); + const unsigned format = GetUi16(p); if (format != 3) return E_NOTIMPL; - UInt16 algId = GetUi16(p + 2); + unsigned algId = GetUi16(p + 2); if (algId < kAES128) return E_NOTIMPL; algId -= kAES128; if (algId > 2) return E_NOTIMPL; - UInt16 bitLen = GetUi16(p + 4); - UInt16 flags = GetUi16(p + 6); + const unsigned bitLen = GetUi16(p + 4); + const unsigned flags = GetUi16(p + 6); if (algId * 64 + 128 != bitLen) return E_NOTIMPL; _key.KeySize = 16 + algId * 8; - bool cert = ((flags & 2) != 0); + const bool cert = ((flags & 2) != 0); if ((flags & 0x4000) != 0) { @@ -198,7 +203,7 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK) UInt32 validSize = GetUi16(p2); p2 += 2; - const size_t validOffset = p2 - p; + const size_t validOffset = (size_t)(p2 - p); if ((validSize & 0xF) != 0 || validOffset + validSize != _remSize) return E_NOTIMPL; @@ -214,7 +219,9 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK) return S_OK; // passwOK = false; } + MY_ALIGN (16) Byte fileKey[32]; + MY_ALIGN (16) NSha1::CContext sha; sha.Init(); sha.Update(_iv, _ivSize); diff --git a/CPP/7zip/Crypto/ZipStrong.h b/CPP/7zip/Crypto/ZipStrong.h index 03a0f2c7..2b58a5cb 100644 --- a/CPP/7zip/Crypto/ZipStrong.h +++ b/CPP/7zip/Crypto/ZipStrong.h @@ -27,6 +27,12 @@ struct CKeyInfo UInt32 KeySize; void SetPassword(const Byte *data, UInt32 size); + + ~CKeyInfo() { Wipe(); } + void Wipe() + { + MY_memset_0_ARRAY(MasterKey); + } }; class CBaseCoder: @@ -58,6 +64,12 @@ public: // Change it, if is not AES return kAesPadAllign - (packSize32 & (kAesPadAllign - 1)); } + + ~CDecoder() { Wipe(); } + void Wipe() + { + MY_memset_0_ARRAY(_iv); + } }; }} diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt index c9da7ed7..f28afcd1 100644 --- a/CPP/7zip/Guid.txt +++ b/CPP/7zip/Guid.txt @@ -50,6 +50,7 @@ 26 ICompressSetFinishMode 27 ICompressGetInStreamProcessedSize2 28 ICompressSetMemLimit + 29 ICompressReadUnusedFromInBuf 30 ICompressGetSubStreamSize 31 ICompressSetInStream @@ -166,6 +167,7 @@ Handler GUIDs: 0C xz 0D ppmd + C5 Base64 C6 COFF C7 Ext C8 VMDK diff --git a/CPP/7zip/ICoder.h b/CPP/7zip/ICoder.h index 677d8cfb..314d33d4 100644 --- a/CPP/7zip/ICoder.h +++ b/CPP/7zip/ICoder.h @@ -131,7 +131,8 @@ namespace NCoderPropID kBlockSize2, // VT_UI4 or VT_UI8 kCheckSize, // VT_UI4 : size of digest in bytes kFilter, // VT_BSTR - kMemUse // VT_UI8 + kMemUse, // VT_UI8 + kAffinity // VT_UI8 }; } @@ -198,6 +199,22 @@ CODER_INTERFACE(ICompressSetMemLimit, 0x28) }; +/* + ICompressReadUnusedFromInBuf is supported by ICoder object + call ReadUnusedFromInBuf() after ICoder::Code(inStream, ...). + ICoder::Code(inStream, ...) decodes data, and the ICoder object is allowed + to read from inStream to internal buffers more data than minimal data required for decoding. + So we can call ReadUnusedFromInBuf() from same ICoder object to read unused input + data from the internal buffer. + in ReadUnusedFromInBuf(): the Coder is not allowed to use (ISequentialInStream *inStream) object, that was sent to ICoder::Code(). +*/ + +CODER_INTERFACE(ICompressReadUnusedFromInBuf, 0x29) +{ + STDMETHOD(ReadUnusedFromInBuf)(void *data, UInt32 size, UInt32 *processedSize) PURE; +}; + + CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) { @@ -284,8 +301,24 @@ CODER_INTERFACE(ICompressSetInStreamSize2, 0x39) /* ICompressFilter - Filter() converts as most as possible bytes + Filter() converts as most as possible bytes required for fast processing. + Some filters have (smallest_fast_block). + For example, (smallest_fast_block == 16) for AES CBC/CTR filters. + If data stream is not finished, caller must call Filter() for larger block: + where (size >= smallest_fast_block). + if (size >= smallest_fast_block) + { + The filter can leave some bytes at the end of data without conversion: + if there are data alignment reasons or speed reasons. + The caller must read additional data from stream and call Filter() again. + } + If data stream was finished, caller can call Filter() for (size < smallest_fast_block) + + data : must be aligned for at least 16 bytes for some filters (AES) + returns: (outSize): + if (outSize == 0) : Filter have not converted anything. + So the caller can stop processing, if data stream was finished. if (outSize <= size) : Filter have converted outSize bytes if (outSize > size) : Filter have not converted anything. and it needs at least outSize bytes to convert one block diff --git a/CPP/7zip/IPassword.h b/CPP/7zip/IPassword.h index 7ea45537..4ccc9ac7 100644 --- a/CPP/7zip/IPassword.h +++ b/CPP/7zip/IPassword.h @@ -10,11 +10,41 @@ #define PASSWORD_INTERFACE(i, x) DECL_INTERFACE(i, 5, x) +/* +How to use output parameter (BSTR *password): + +in: The caller is required to set BSTR value as NULL (no string). + The callee (in 7-Zip code) ignores the input value stored in BSTR variable, + +out: The callee rewrites BSTR variable (*password) with new allocated string pointer. + The caller must free BSTR string with function SysFreeString(); +*/ + PASSWORD_INTERFACE(ICryptoGetTextPassword, 0x10) { STDMETHOD(CryptoGetTextPassword)(BSTR *password) PURE; }; + +/* +CryptoGetTextPassword2() +in: + The caller is required to set BSTR value as NULL (no string). + The caller is not required to set (*passwordIsDefined) value. + +out: + Return code: != S_OK : error code + Return code: S_OK : success + + if (*passwordIsDefined == 1), the variable (*password) contains password string + + if (*passwordIsDefined == 0), the password is not defined, + but the callee still could set (*password) to some allocated string, for example, as empty string. + + The caller must free BSTR string with function SysFreeString() +*/ + + PASSWORD_INTERFACE(ICryptoGetTextPassword2, 0x11) { STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password) PURE; diff --git a/CPP/7zip/IStream.h b/CPP/7zip/IStream.h index 9a0bcbf3..48c67c1a 100644 --- a/CPP/7zip/IStream.h +++ b/CPP/7zip/IStream.h @@ -62,12 +62,21 @@ STREAM_INTERFACE(ISequentialOutStream, 0x02) */ }; +#ifdef _WIN32 + #ifdef __HRESULT_FROM_WIN32 #define HRESULT_WIN32_ERROR_NEGATIVE_SEEK __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK) #else #define HRESULT_WIN32_ERROR_NEGATIVE_SEEK HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK) #endif +#else + +#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK MY__E_ERROR_NEGATIVE_SEEK + +#endif + + /* Seek() Function If you seek before the beginning of the stream, Seek() function returns error code: Recommended error code is __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK). diff --git a/CPP/7zip/LzmaDec.mak b/CPP/7zip/LzmaDec.mak index 8d7f6f98..bed4700a 100644 --- a/CPP/7zip/LzmaDec.mak +++ b/CPP/7zip/LzmaDec.mak @@ -1,5 +1,7 @@ !IF "$(PLATFORM)" == "x64" +!IFNDEF NO_ASM CFLAGS_C_SPEC = -D_LZMA_DEC_OPT ASM_OBJS = $(ASM_OBJS) \ $O\LzmaDecOpt.obj !ENDIF +!ENDIF diff --git a/CPP/7zip/LzmaDec_gcc.mak b/CPP/7zip/LzmaDec_gcc.mak new file mode 100644 index 00000000..51924f50 --- /dev/null +++ b/CPP/7zip/LzmaDec_gcc.mak @@ -0,0 +1,14 @@ +ifdef USE_ASM +ifdef IS_X64 +USE_LZMA_DEC_ASM=1 +endif +ifdef IS_ARM64 +USE_LZMA_DEC_ASM=1 +endif +endif + +ifdef USE_LZMA_DEC_ASM + +LZMA_DEC_OPT_OBJS= $O/LzmaDecOpt.o + +endif diff --git a/CPP/7zip/Sha1.mak b/CPP/7zip/Sha1.mak new file mode 100644 index 00000000..1b5f605f --- /dev/null +++ b/CPP/7zip/Sha1.mak @@ -0,0 +1,13 @@ +COMMON_OBJS = $(COMMON_OBJS) \ + $O\Sha1Prepare.obj + +C_OBJS = $(C_OBJS) \ + $O\Sha1.obj + +!IF defined(USE_C_SHA) || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "arm64" +C_OBJS = $(C_OBJS) \ + $O\Sha1Opt.obj +!ELSEIF "$(PLATFORM)" != "ia64" && "$(PLATFORM)" != "mips" && "$(PLATFORM)" != "arm" && "$(PLATFORM)" != "arm64" +ASM_OBJS = $(ASM_OBJS) \ + $O\Sha1Opt.obj +!ENDIF diff --git a/CPP/7zip/Sha256.mak b/CPP/7zip/Sha256.mak new file mode 100644 index 00000000..0bdbcb60 --- /dev/null +++ b/CPP/7zip/Sha256.mak @@ -0,0 +1,13 @@ +COMMON_OBJS = $(COMMON_OBJS) \ + $O\Sha256Prepare.obj + +C_OBJS = $(C_OBJS) \ + $O\Sha256.obj + +!IF defined(USE_C_SHA) || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "arm64" +C_OBJS = $(C_OBJS) \ + $O\Sha256Opt.obj +!ELSEIF "$(PLATFORM)" != "ia64" && "$(PLATFORM)" != "mips" && "$(PLATFORM)" != "arm" && "$(PLATFORM)" != "arm64" +ASM_OBJS = $(ASM_OBJS) \ + $O\Sha256Opt.obj +!ENDIF diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp index 1c2e3397..76b243f2 100644 --- a/CPP/7zip/UI/Agent/Agent.cpp +++ b/CPP/7zip/UI/Agent/Agent.cpp @@ -27,8 +27,10 @@ CCodecs *g_CodecsObj; #ifdef EXTERNAL_CODECS CExternalCodecs g_ExternalCodecs; - CCodecs::CReleaser g_CodecsReleaser; + static CCodecs::CReleaser g_CodecsReleaser; #else + extern + CMyComPtr<IUnknown> g_CodecsRef; CMyComPtr<IUnknown> g_CodecsRef; #endif @@ -1245,7 +1247,7 @@ STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) // case kpidName: prop = dir.Name; break; // case kpidPath: prop = _proxy2->GetFullPathPrefix(_proxyDirIndex); break; case kpidType: prop = UString("7-Zip.") + _agentSpec->ArchiveType; break; - case kpidCRC: if (dir.CrcIsDefined) prop = dir.Crc; break; + case kpidCRC: if (dir.CrcIsDefined) { prop = dir.Crc; } break; } } @@ -1533,8 +1535,8 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, CAgent::CAgent(): _proxy(NULL), _proxy2(NULL), - _isDeviceFile(false), - _updatePathPrefix_is_AltFolder(false) + _updatePathPrefix_is_AltFolder(false), + _isDeviceFile(false) { } @@ -1611,24 +1613,30 @@ STDMETHODIMP CAgent::Open( options.filePath = _archiveFilePath; options.callback = openArchiveCallback; - RINOK(_archiveLink.Open(options)); + HRESULT res = _archiveLink.Open(options); - CArc &arc = _archiveLink.Arcs.Back(); - if (!inStream) + if (!_archiveLink.Arcs.IsEmpty()) { - arc.MTimeDefined = !fi.IsDevice; - arc.MTime = fi.MTime; + CArc &arc = _archiveLink.Arcs.Back(); + if (!inStream) + { + arc.MTimeDefined = !fi.IsDevice; + arc.MTime = fi.MTime; + } + + ArchiveType = GetTypeOfArc(arc); + if (archiveType) + { + RINOK(StringToBstr(ArchiveType, archiveType)); + } } - ArchiveType = GetTypeOfArc(arc); - if (archiveType) - { - RINOK(StringToBstr(ArchiveType, archiveType)); - } - return S_OK; + return res; + COM_TRY_END } + STDMETHODIMP CAgent::ReOpen(IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN @@ -1717,7 +1725,10 @@ HRESULT CAgent::ReadItems() STDMETHODIMP CAgent::BindToRootFolder(IFolderFolder **resultFolder) { COM_TRY_BEGIN - RINOK(ReadItems()); + if (!_archiveLink.Arcs.IsEmpty()) + { + RINOK(ReadItems()); + } CAgentFolder *folderSpec = new CAgentFolder; CMyComPtr<IFolderFolder> rootFolder = folderSpec; folderSpec->Init(_proxy, _proxy2, k_Proxy_RootDirIndex, /* NULL, */ this); @@ -1813,6 +1824,20 @@ STDMETHODIMP CAgent::GetArcProp(UInt32 level, PROPID propID, PROPVARIANT *value) if (_archiveLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) prop = g_CodecsObj->Formats[_archiveLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name; break; + case kpidErrorFlags: + { + UInt32 flags = _archiveLink.NonOpen_ErrorInfo.GetErrorFlags(); + if (flags != 0) + prop = flags; + break; + } + case kpidWarningFlags: + { + UInt32 flags = _archiveLink.NonOpen_ErrorInfo.GetWarningFlags(); + if (flags != 0) + prop = flags; + break; + } } } else @@ -1822,7 +1847,10 @@ STDMETHODIMP CAgent::GetArcProp(UInt32 level, PROPID propID, PROPVARIANT *value) { case kpidType: prop = GetTypeOfArc(arc); break; case kpidPath: prop = arc.Path; break; - case kpidErrorType: if (arc.ErrorInfo.ErrorFormatIndex >= 0) prop = g_CodecsObj->Formats[arc.ErrorInfo.ErrorFormatIndex].Name; break; + case kpidErrorType: + if (arc.ErrorInfo.ErrorFormatIndex >= 0) + prop = g_CodecsObj->Formats[arc.ErrorInfo.ErrorFormatIndex].Name; + break; case kpidErrorFlags: { UInt32 flags = arc.ErrorInfo.GetErrorFlags(); diff --git a/CPP/7zip/UI/Agent/Agent.h b/CPP/7zip/UI/Agent/Agent.h index f7d7b5e4..498e7d0c 100644 --- a/CPP/7zip/UI/Agent/Agent.h +++ b/CPP/7zip/UI/Agent/Agent.h @@ -292,7 +292,7 @@ public: s2 += "Warning: The archive is open with offset"; else { - s2 += "Can not open the file as ["; + s2 += "Cannot open the file as ["; s2 += g_CodecsObj->GetFormatNamePtr(arc.ErrorInfo.ErrorFormatIndex); s2 += "] archive"; } diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp index 40876d76..8dfb63a2 100644 --- a/CPP/7zip/UI/Agent/AgentOut.cpp +++ b/CPP/7zip/UI/Agent/AgentOut.cpp @@ -166,7 +166,7 @@ struct CDirItemsCallback_AgentOut: public IDirItemsCallback IFolderArchiveUpdateCallback *FolderArchiveUpdateCallback; HRESULT ErrorCode; - CDirItemsCallback_AgentOut(): ErrorCode(S_OK), FolderArchiveUpdateCallback(NULL) {} + CDirItemsCallback_AgentOut(): FolderArchiveUpdateCallback(NULL), ErrorCode(S_OK) {} HRESULT ScanError(const FString &name, DWORD systemError) { diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp index 7f550f75..f0acd20b 100644 --- a/CPP/7zip/UI/Agent/AgentProxy.cpp +++ b/CPP/7zip/UI/Agent/AgentProxy.cpp @@ -51,6 +51,18 @@ int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name) const return FindSubDir(dirIndex, name, insertPos); } +static const wchar_t *AllocStringAndCopy(const wchar_t *s, size_t len) +{ + wchar_t *p = new wchar_t[len + 1]; + MyStringCopy(p, s); + return p; +} + +static const wchar_t *AllocStringAndCopy(const UString &s) +{ + return AllocStringAndCopy(s, s.Len()); +} + unsigned CProxyArc::AddDir(unsigned dirIndex, int arcIndex, const UString &name) { unsigned insertPos; @@ -70,8 +82,7 @@ unsigned CProxyArc::AddDir(unsigned dirIndex, int arcIndex, const UString &name) CProxyDir &item = Dirs.AddNew(); item.NameLen = name.Len(); - item.Name = new wchar_t[item.NameLen + 1]; - MyStringCopy((wchar_t *)item.Name, name); + item.Name = AllocStringAndCopy(name); item.ArcIndex = arcIndex; item.ParentDir = dirIndex; @@ -248,6 +259,10 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) unsigned len = 0; bool isPtrName = false; + #if WCHAR_PATH_SEPARATOR != L'/' + wchar_t replaceFromChar = 0; + #endif + #if defined(MY_CPU_LE) && defined(_WIN32) // it works only if (sizeof(wchar_t) == 2) if (arc.GetRawProps) @@ -263,6 +278,9 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) len = size / 2 - 1; s = (const wchar_t *)p; isPtrName = true; + #if WCHAR_PATH_SEPARATOR != L'/' + replaceFromChar = L'\\'; + #endif } } if (!s) @@ -309,9 +327,17 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) for (unsigned j = 0; j < len; j++) { - wchar_t c = s[j]; + const wchar_t c = s[j]; if (c == WCHAR_PATH_SEPARATOR || c == L'/') { + #if WCHAR_PATH_SEPARATOR != L'/' + if (c == replaceFromChar) + { + // s.ReplaceOneCharAtPos(j, WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT); + continue; + } + #endif + const unsigned kLevelLimit = 1 << 10; if (numLevels <= kLevelLimit) { @@ -351,9 +377,8 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) f.Name = s; else { - f.Name = new wchar_t[f.NameLen + 1]; + f.Name = AllocStringAndCopy(s, f.NameLen); f.NeedDeleteName = true; - MyStringCopy((wchar_t *)f.Name, s); } if (isDir) @@ -382,15 +407,15 @@ void CProxyArc2::GetDirPathParts(int dirIndex, UStringVector &pathParts, bool &i isAltStreamDir = false; - if (dirIndex == k_Proxy2_RootDirIndex) + if (dirIndex == (int)k_Proxy2_RootDirIndex) return; - if (dirIndex == k_Proxy2_AltRootDirIndex) + if (dirIndex == (int)k_Proxy2_AltRootDirIndex) { isAltStreamDir = true; return; } - while (dirIndex >= k_Proxy2_NumRootDirs) + while (dirIndex >= (int)k_Proxy2_NumRootDirs) { const CProxyDir2 &dir = Dirs[dirIndex]; const CProxyFile2 &file = Files[dir.ArcIndex]; @@ -608,9 +633,8 @@ HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress) tempAString = (const char *)p; ConvertUTF8ToUnicode(tempAString, tempUString); file.NameLen = tempUString.Len(); - file.Name = new wchar_t[file.NameLen + 1]; + file.Name = AllocStringAndCopy(tempUString); file.NeedDeleteName = true; - wmemcpy((wchar_t *)file.Name, tempUString.Ptr(), file.NameLen + 1); } else { @@ -624,9 +648,8 @@ HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress) else return E_FAIL; file.NameLen = MyStringLen(s); - file.Name = new wchar_t[file.NameLen + 1]; + file.Name = AllocStringAndCopy(s, file.NameLen); file.NeedDeleteName = true; - wmemcpy((wchar_t *)file.Name, s, file.NameLen + 1); } UInt32 parent = (UInt32)(Int32)-1; diff --git a/CPP/7zip/UI/Agent/AgentProxy.h b/CPP/7zip/UI/Agent/AgentProxy.h index 49012676..f2cb3d7a 100644 --- a/CPP/7zip/UI/Agent/AgentProxy.h +++ b/CPP/7zip/UI/Agent/AgentProxy.h @@ -12,7 +12,7 @@ struct CProxyFile bool NeedDeleteName; CProxyFile(): Name(NULL), NameLen(0), NeedDeleteName(false) {} - ~CProxyFile() { if (NeedDeleteName) delete [](wchar_t *)Name; } + ~CProxyFile() { if (NeedDeleteName) delete [](wchar_t *)(void *)Name; } // delete [](wchar_t *)Name; }; const unsigned k_Proxy_RootDirIndex = 0; @@ -35,7 +35,7 @@ struct CProxyDir bool CrcIsDefined; CProxyDir(): Name(NULL), NameLen(0), ParentDir(-1) {}; - ~CProxyDir() { delete [](wchar_t *)Name; } + ~CProxyDir() { delete [](wchar_t *)(void *)Name; } void Clear(); bool IsLeaf() const { return ArcIndex >= 0; } @@ -93,7 +93,7 @@ struct CProxyFile2 ~CProxyFile2() { if (NeedDeleteName) - delete [](wchar_t *)Name; + delete [](wchar_t *)(void *)Name; } }; diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp index 62d5b1f8..55457f45 100644 --- a/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp @@ -31,8 +31,21 @@ STDMETHODIMP CArchiveFolderManager::OpenFolderFile(IInStream *inStream, } CAgent *agent = new CAgent(); CMyComPtr<IInFolderArchive> archive = agent; - RINOK(agent->Open(inStream, filePath, arcFormat, NULL, openArchiveCallback)); - return agent->BindToRootFolder(resultFolder); + + HRESULT res = agent->Open(inStream, filePath, arcFormat, NULL, openArchiveCallback); + + if (res != S_OK) + { + if (res != S_FALSE) + return res; + /* 20.01: we create folder even for Non-Open cases, if there is NonOpen_ErrorInfo information. + So we can get error information from that IFolderFolder later. */ + if (!agent->_archiveLink.NonOpen_ErrorInfo.IsThereErrorOrWarning()) + return res; + } + + RINOK(agent->BindToRootFolder(resultFolder)); + return res; } /* diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp index ecbfe58b..ba52f4e7 100644 --- a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp @@ -27,30 +27,41 @@ void CAgentFolder::GetPathParts(UStringVector &pathParts, bool &isAltStreamFolde _proxy->GetDirPathParts(_proxyDirIndex, pathParts); } -static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path) +static bool Delete_EmptyFolder_And_EmptySubFolders(const FString &path) { - NFind::CFileInfo fileInfo; - FString pathPrefix = path; - pathPrefix.Add_PathSepar(); { - NFind::CEnumerator enumerator; - enumerator.SetDirPrefix(pathPrefix); - while (enumerator.Next(fileInfo)) + const FString pathPrefix = path + FCHAR_PATH_SEPARATOR; + CObjectVector<FString> names; { - if (fileInfo.IsDir()) - if (!DeleteEmptyFolderAndEmptySubFolders(pathPrefix + fileInfo.Name)) + NFind::CDirEntry fileInfo; + NFind::CEnumerator enumerator; + enumerator.SetDirPrefix(pathPrefix); + for (;;) + { + bool found; + if (!enumerator.Next(fileInfo, found)) return false; + if (!found) + break; + if (fileInfo.IsDir()) + names.Add(fileInfo.Name); + } + } + bool res = true; + FOR_VECTOR (i, names) + { + if (!Delete_EmptyFolder_And_EmptySubFolders(pathPrefix + names[i])) + res = false; } + if (!res) + return false; } - /* - // we don't need clear readonly for folders + // we clear read-only attrib to remove read-only dir if (!SetFileAttrib(path, 0)) return false; - */ return RemoveDir(path); } - HRESULT CAgentFolder::CommonUpdateOperation( AGENT_OP operation, bool moveMode, @@ -123,7 +134,7 @@ HRESULT CAgentFolder::CommonUpdateOperation( case AGENT_OP_Uni: { Byte actionSetByte[NUpdateArchive::NPairState::kNumValues]; - for (int i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) + for (unsigned i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) actionSetByte[i] = (Byte)actionSet->StateActions[i]; result = _agentSpec->DoOperation2( moveMode ? &requestedPaths : NULL, @@ -162,7 +173,7 @@ HRESULT CAgentFolder::CommonUpdateOperation( { const FString &fs = requestedPaths[i]; if (NFind::DoesDirExist(fs)) - DeleteEmptyFolderAndEmptySubFolders(fs); + Delete_EmptyFolder_And_EmptySubFolders(fs); } } } diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp index 4ebfb2dc..0c69bdc0 100644 --- a/CPP/7zip/UI/Client7z/Client7z.cpp +++ b/CPP/7zip/UI/Client7z/Client7z.cpp @@ -28,10 +28,12 @@ #include "../../../../C/7zVersion.h" #ifdef _WIN32 +extern +HINSTANCE g_hInstance; HINSTANCE g_hInstance = 0; #endif -// Tou can find the list of all GUIDs in Guid.txt file. +// You can find the list of all GUIDs in Guid.txt file. // use another CLSIDs, if you want to support other formats (zip, rar, ...). // {23170F69-40C1-278A-1000-000110070000} @@ -47,7 +49,11 @@ using namespace NWindows; using namespace NFile; using namespace NDir; +#ifdef _WIN32 #define kDllName "7z.dll" +#else +#define kDllName "7z.so" +#endif static const char * const kCopyrightString = "\n" @@ -383,7 +389,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, { if (!DeleteFileAlways(fullProcessedPath)) { - PrintError("Can not delete output file", fullProcessedPath); + PrintError("Cannot delete output file", fullProcessedPath); return E_ABORT; } } @@ -392,7 +398,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS)) { - PrintError("Can not open output file", fullProcessedPath); + PrintError("Cannot open output file", fullProcessedPath); return E_ABORT; } _outFileStream = outStreamLoc; @@ -556,7 +562,11 @@ public: FStringVector FailedFiles; CRecordVector<HRESULT> FailedCodes; - CArchiveUpdateCallback(): PasswordIsDefined(false), AskPassword(false), DirItems(0) {}; + CArchiveUpdateCallback(): + DirItems(NULL), + PasswordIsDefined(false), + AskPassword(false) + {} ~CArchiveUpdateCallback() { Finilize(); } HRESULT Finilize(); @@ -726,12 +736,18 @@ STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDef // Main function +#if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) #define NT_CHECK_FAIL_ACTION PrintError("Unsupported Windows version"); return 1; +#endif int MY_CDECL main(int numArgs, const char *args[]) { NT_CHECK + #ifdef ENV_HAVE_LOCALE + MY_SetLocale(); + #endif + PrintStringLn(kCopyrightString); if (numArgs < 2) @@ -740,55 +756,96 @@ int MY_CDECL main(int numArgs, const char *args[]) return 0; } - if (numArgs < 3) + FString dllPrefix; + + #ifdef _WIN32 + dllPrefix = NDLL::GetModuleDirPrefix(); + #else { - PrintError(kIncorrectCommand); - return 1; + AString s (args[0]); + int sep = s.ReverseFind_PathSepar(); + s.DeleteFrom(sep + 1); + dllPrefix = s; } + #endif - NDLL::CLibrary lib; - if (!lib.Load(NDLL::GetModuleDirPrefix() + FTEXT(kDllName))) + if (!lib.Load(dllPrefix + FTEXT(kDllName))) { - PrintError("Can not load 7-zip library"); + PrintError("Cannot load 7-zip library"); return 1; } Func_CreateObject createObjectFunc = (Func_CreateObject)lib.GetProc("CreateObject"); if (!createObjectFunc) { - PrintError("Can not get CreateObject"); + PrintError("Cannot get CreateObject"); return 1; } - char c; + char c = 0; + UString password; + bool passwordIsDefined = false; + CObjectVector<FString> params; + + for (int curCmd = 1; curCmd < numArgs; curCmd++) { - AString command (args[1]); - if (command.Len() != 1) + AString a(args[curCmd]); + + if (!a.IsEmpty()) + { + if (a[0] == '-') + { + if (!passwordIsDefined && a[1] == 'p') + { + password = GetUnicodeString(a.Ptr(2)); + passwordIsDefined = true; + continue; + } + } + else + { + if (c) + { + params.Add(CmdStringToFString(a)); + continue; + } + if (a.Len() == 1) + { + c = (char)MyCharLower_Ascii(a[0]); + continue; + } + } + } { PrintError(kIncorrectCommand); return 1; } - c = (char)MyCharLower_Ascii(command[0]); } - FString archiveName = CmdStringToFString(args[2]); + if (!c || params.Size() < 1) + { + PrintError(kIncorrectCommand); + return 1; + } + + const FString &archiveName = params[0]; if (c == 'a') { // create archive command - if (numArgs < 4) + if (params.Size() < 2) { PrintError(kIncorrectCommand); return 1; } CObjectVector<CDirItem> dirItems; { - int i; - for (i = 3; i < numArgs; i++) + unsigned i; + for (i = 1; i < params.Size(); i++) { CDirItem di; - FString name = CmdStringToFString(args[i]); + const FString &name = params[i]; NFind::CFileInfo fi; if (!fi.Find(name)) @@ -819,15 +876,15 @@ int MY_CDECL main(int numArgs, const char *args[]) CMyComPtr<IOutArchive> outArchive; if (createObjectFunc(&CLSID_Format, &IID_IOutArchive, (void **)&outArchive) != S_OK) { - PrintError("Can not get class object"); + PrintError("Cannot get class object"); return 1; } CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec); updateCallbackSpec->Init(&dirItems); - // updateCallbackSpec->PasswordIsDefined = true; - // updateCallbackSpec->Password = L"1"; + updateCallbackSpec->PasswordIsDefined = passwordIsDefined; + updateCallbackSpec->Password = password; /* { @@ -874,7 +931,7 @@ int MY_CDECL main(int numArgs, const char *args[]) } else { - if (numArgs != 3) + if (params.Size() != 1) { PrintError(kIncorrectCommand); return 1; @@ -895,7 +952,7 @@ int MY_CDECL main(int numArgs, const char *args[]) CMyComPtr<IInArchive> archive; if (createObjectFunc(&CLSID_Format, &IID_IInArchive, (void **)&archive) != S_OK) { - PrintError("Can not get class object"); + PrintError("Cannot get class object"); return 1; } @@ -904,21 +961,20 @@ int MY_CDECL main(int numArgs, const char *args[]) if (!fileSpec->Open(archiveName)) { - PrintError("Can not open archive file", archiveName); + PrintError("Cannot open archive file", archiveName); return 1; } { CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback; CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec); - openCallbackSpec->PasswordIsDefined = false; - // openCallbackSpec->PasswordIsDefined = true; - // openCallbackSpec->Password = L"1"; + openCallbackSpec->PasswordIsDefined = passwordIsDefined; + openCallbackSpec->Password = password; const UInt64 scanSize = 1 << 23; if (archive->Open(file, &scanSize, openCallback) != S_OK) { - PrintError("Can not open file as archive", archiveName); + PrintError("Cannot open file as archive", archiveName); return 1; } } @@ -957,9 +1013,8 @@ int MY_CDECL main(int numArgs, const char *args[]) CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec); extractCallbackSpec->Init(archive, FString()); // second parameter is output folder path - extractCallbackSpec->PasswordIsDefined = false; - // extractCallbackSpec->PasswordIsDefined = true; - // extractCallbackSpec->Password = "1"; + extractCallbackSpec->PasswordIsDefined = passwordIsDefined; + extractCallbackSpec->Password = password; /* const wchar_t *names[] = diff --git a/CPP/7zip/UI/Client7z/makefile b/CPP/7zip/UI/Client7z/makefile index 99a6d494..988701ef 100644 --- a/CPP/7zip/UI/Client7z/makefile +++ b/CPP/7zip/UI/Client7z/makefile @@ -8,9 +8,9 @@ COMMON_OBJS = \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ + $O\MyVector.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ - $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ diff --git a/CPP/7zip/UI/Client7z/makefile.gcc b/CPP/7zip/UI/Client7z/makefile.gcc new file mode 100644 index 00000000..b65095bf --- /dev/null +++ b/CPP/7zip/UI/Client7z/makefile.gcc @@ -0,0 +1,59 @@ +PROG = 7zcl +IS_NOT_STANDALONE = 1 + +# IS_X64 = 1 + + + +ifdef SystemDrive + +SYS_OBJS = \ + $O/resource.o \ + +else + +SYS_OBJS = \ + $O/MyWindows.o \ + $O/TimeUtils.o \ + +endif + + +LOCAL_FLAGS = \ + + +CURRENT_OBJS = \ + $O/Client7z.o \ + +COMMON_OBJS = \ + $O/IntToString.o \ + $O/MyString.o \ + $O/MyVector.o \ + $O/NewHandler.o \ + $O/StringConvert.o \ + $O/StringToInt.o \ + $O/UTFConvert.o \ + $O/Wildcard.o \ + +WIN_OBJS = \ + $O/DLL.o \ + $O/FileDir.o \ + $O/FileFind.o \ + $O/FileIO.o \ + $O/FileName.o \ + $O/PropVariant.o \ + $O/PropVariantConv.o \ + +7ZIP_COMMON_OBJS = \ + $O/FileStreams.o \ + + +OBJS = \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(SYS_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(CURRENT_OBJS) \ + + +include ../../7zip_gcc.mak diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp index 0e2a4700..ef7eb1a7 100644 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp @@ -19,6 +19,7 @@ #include "../../../../C/Alloc.h" #endif +#include "../../../Common/IntToString.h" #include "../../../Common/ListFileUtils.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" @@ -26,6 +27,7 @@ #include "../../../Windows/ErrorMsg.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileName.h" +#include "../../../Windows/System.h" #ifdef _WIN32 #include "../../../Windows/FileMapping.h" #include "../../../Windows/MemoryLock.h" @@ -41,22 +43,37 @@ extern bool g_CaseSensitive; extern bool g_PathTrailReplaceMode; #ifdef _7ZIP_LARGE_PAGES +extern +bool g_LargePagesMode; bool g_LargePagesMode = false; #endif +/* +#ifdef ENV_HAVE_LSTAT +EXTERN_C_BEGIN +extern int global_use_lstat; +EXTERN_C_END +#endif +*/ + #ifdef UNDER_CE #define MY_IS_TERMINAL(x) false; #else -#if _MSC_VER >= 1400 -#define MY_isatty_fileno(x) _isatty(_fileno(x)) -#else -#define MY_isatty_fileno(x) isatty(fileno(x)) -#endif - -#define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0); +// #define MY_isatty_fileno(x) (isatty(fileno(x))) +// #define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0); +static inline bool MY_IS_TERMINAL(FILE *x) +{ + return ( + #if defined(_MSC_VER) && (_MSC_VER >= 1400) + _isatty(_fileno(x)) + #else + isatty(fileno(x)) + #endif + != 0); +} #endif @@ -74,8 +91,6 @@ static bool StringToUInt32(const wchar_t *s, UInt32 &v) } -int g_CodePage = -1; - namespace NKey { enum Enum { @@ -127,6 +142,7 @@ enum Enum kConsoleCharSet, kTechMode, + kPreserveATime, kShareForWrite, kStopAfterOpenError, kCaseSensitive, @@ -137,6 +153,7 @@ enum Enum kFullPathMode, kHardLinks, + kSymLinks_AllowDangerous, kSymLinks, kNtSecurity, @@ -164,7 +181,7 @@ static const char * const k_ArcNameMode_PostCharSet = "sea"; static const char * const k_Stream_PostCharSet = "012"; -static inline const EArcNameMode ParseArcNameMode(int postCharIndex) +static inline EArcNameMode ParseArcNameMode(int postCharIndex) { switch (postCharIndex) { @@ -182,12 +199,15 @@ namespace NRecursedPostCharIndex { }; } -static const char kImmediateNameID = '!'; -static const char kMapNameID = '#'; -static const char kFileListID = '@'; +// static const char +#define kImmediateNameID '!' +#ifdef _WIN32 +#define kMapNameID '#' +#endif +#define kFileListID '@' -static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be -static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be +static const Byte kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be +static const Byte kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be static const char * const kOverwritePostCharSet = "asut"; @@ -199,80 +219,95 @@ static const NExtract::NOverwriteMode::EEnum k_OverwriteModes[] = NExtract::NOverwriteMode::kRenameExisting }; + + +#define SWFRM_3(t, mu, mi) t, mu, mi, NULL + +#define SWFRM_1(t) SWFRM_3(t, false, 0) +#define SWFRM_SIMPLE SWFRM_1(NSwitchType::kSimple) +#define SWFRM_MINUS SWFRM_1(NSwitchType::kMinus) +#define SWFRM_STRING SWFRM_1(NSwitchType::kString) + +#define SWFRM_STRING_SINGL(mi) SWFRM_3(NSwitchType::kString, false, mi) +#define SWFRM_STRING_MULT(mi) SWFRM_3(NSwitchType::kString, true, mi) + + static const CSwitchForm kSwitchForms[] = { - { "?" }, - { "h" }, - { "-help" }, + { "?", SWFRM_SIMPLE }, + { "h", SWFRM_SIMPLE }, + { "-help", SWFRM_SIMPLE }, - { "ba" }, - { "bd" }, - { "bt" }, - { "bb", NSwitchType::kString, false, 0 }, + { "ba", SWFRM_SIMPLE }, + { "bd", SWFRM_SIMPLE }, + { "bt", SWFRM_SIMPLE }, + { "bb", SWFRM_STRING_SINGL(0) }, { "bso", NSwitchType::kChar, false, 1, k_Stream_PostCharSet }, { "bse", NSwitchType::kChar, false, 1, k_Stream_PostCharSet }, { "bsp", NSwitchType::kChar, false, 1, k_Stream_PostCharSet }, - { "y" }, + { "y", SWFRM_SIMPLE }, - { "ad" }, + { "ad", SWFRM_SIMPLE }, { "ao", NSwitchType::kChar, false, 1, kOverwritePostCharSet}, - { "t", NSwitchType::kString, false, 1 }, - { "stx", NSwitchType::kString, true, 1 }, + { "t", SWFRM_STRING_SINGL(1) }, + { "stx", SWFRM_STRING_MULT(1) }, - { "m", NSwitchType::kString, true, 1 }, - { "o", NSwitchType::kString, false, 1 }, - { "w", NSwitchType::kString }, - - { "i", NSwitchType::kString, true, kSomeCludePostStringMinSize}, - { "x", NSwitchType::kString, true, kSomeCludePostStringMinSize}, - { "ai", NSwitchType::kString, true, kSomeCludePostStringMinSize}, - { "ax", NSwitchType::kString, true, kSomeCludePostStringMinSize}, - { "an" }, + { "m", SWFRM_STRING_MULT(1) }, + { "o", SWFRM_STRING_SINGL(1) }, + { "w", SWFRM_STRING }, + + { "i", SWFRM_STRING_MULT(kSomeCludePostStringMinSize) }, + { "x", SWFRM_STRING_MULT(kSomeCludePostStringMinSize) }, + { "ai", SWFRM_STRING_MULT(kSomeCludePostStringMinSize) }, + { "ax", SWFRM_STRING_MULT(kSomeCludePostStringMinSize) }, + { "an", SWFRM_SIMPLE }, - { "u", NSwitchType::kString, true, 1}, - { "v", NSwitchType::kString, true, 1}, + { "u", SWFRM_STRING_MULT(1) }, + { "v", SWFRM_STRING_MULT(1) }, { "r", NSwitchType::kChar, false, 0, kRecursedPostCharSet }, - { "stm", NSwitchType::kString }, - { "sfx", NSwitchType::kString }, - { "seml", NSwitchType::kString, false, 0}, - { "scrc", NSwitchType::kString, true, 0 }, + { "stm", SWFRM_STRING }, + { "sfx", SWFRM_STRING }, + { "seml", SWFRM_STRING_SINGL(0) }, + { "scrc", SWFRM_STRING_MULT(0) }, - { "si", NSwitchType::kString }, - { "so" }, - - { "slp", NSwitchType::kString }, - { "scs", NSwitchType::kString }, - { "scc", NSwitchType::kString }, - { "slt" }, - - { "ssw" }, - { "sse" }, - { "ssc", NSwitchType::kMinus }, + { "si", SWFRM_STRING }, + { "so", SWFRM_SIMPLE }, + + { "slp", SWFRM_STRING }, + { "scs", SWFRM_STRING }, + { "scc", SWFRM_STRING }, + { "slt", SWFRM_SIMPLE }, + + { "ssp", SWFRM_SIMPLE }, + { "ssw", SWFRM_SIMPLE }, + { "sse", SWFRM_SIMPLE }, + { "ssc", SWFRM_MINUS }, { "sa", NSwitchType::kChar, false, 1, k_ArcNameMode_PostCharSet }, - { "spd" }, - { "spe", NSwitchType::kMinus }, - { "spf", NSwitchType::kString, false, 0 }, + { "spd", SWFRM_SIMPLE }, + { "spe", SWFRM_MINUS }, + { "spf", SWFRM_STRING_SINGL(0) }, - { "snh", NSwitchType::kMinus }, - { "snl", NSwitchType::kMinus }, - { "sni" }, + { "snh", SWFRM_MINUS }, + { "snld", SWFRM_MINUS }, + { "snl", SWFRM_MINUS }, + { "sni", SWFRM_SIMPLE }, - { "sns", NSwitchType::kMinus }, - { "snr" }, - { "snc" }, + { "sns", SWFRM_MINUS }, + { "snr", SWFRM_SIMPLE }, + { "snc", SWFRM_SIMPLE }, - { "snt", NSwitchType::kMinus }, + { "snt", SWFRM_MINUS }, - { "sdel" }, - { "stl" } + { "sdel", SWFRM_SIMPLE }, + { "stl", SWFRM_SIMPLE } #ifndef _NO_CRYPTO - , { "p", NSwitchType::kString } + , { "p", SWFRM_STRING } #endif }; @@ -281,7 +316,7 @@ static const unsigned kMinNonSwitchWords = 1; static const unsigned kCommandIndex = 0; // static const char * const kUserErrorMessage = "Incorrect command line"; -static const char * const kCannotFindListFile = "Cannot find listfile"; +// static const char * const kCannotFindListFile = "Cannot find listfile"; static const char * const kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch."; static const char * const kTerminalOutError = "I won't write compressed data to a terminal"; static const char * const kSameTerminalError = "I won't write data and program's messages to same stream"; @@ -295,8 +330,9 @@ bool CArcCommand::IsFromExtractGroup() const case NCommandType::kExtract: case NCommandType::kExtractFull: return true; + default: + return false; } - return false; } NExtract::NPathMode::EEnum CArcCommand::GetPathMode() const @@ -306,8 +342,9 @@ NExtract::NPathMode::EEnum CArcCommand::GetPathMode() const case NCommandType::kTest: case NCommandType::kExtractFull: return NExtract::NPathMode::kFullPaths; + default: + return NExtract::NPathMode::kNoPaths; } - return NExtract::NPathMode::kNoPaths; } bool CArcCommand::IsFromUpdateGroup() const @@ -319,8 +356,9 @@ bool CArcCommand::IsFromUpdateGroup() const case NCommandType::kDelete: case NCommandType::kRename: return true; + default: + return false; } - return false; } static NRecursedType::EEnum GetRecursedTypeFromIndex(int index) @@ -376,6 +414,8 @@ static void AddNameToCensor(NWildcard::CCensor &censor, case NRecursedType::kRecursed: recursed = true; break; + default: + break; } censor.AddPreItem(include, name, recursed, wildcardMatching); } @@ -408,11 +448,13 @@ static void AddRenamePair(CObjectVector<CRenamePair> *renamePairs, static void AddToCensorFromListFile( CObjectVector<CRenamePair> *renamePairs, NWildcard::CCensor &censor, - LPCWSTR fileName, bool include, NRecursedType::EEnum type, bool wildcardMatching, Int32 codePage) + LPCWSTR fileName, bool include, NRecursedType::EEnum type, bool wildcardMatching, UInt32 codePage) { UStringVector names; - if (!NFind::DoesFileExist(us2fs(fileName))) + /* + if (!NFind::DoesFileExist_FollowLink(us2fs(fileName))) throw CArcCmdLineException(kCannotFindListFile, fileName); + */ DWORD lastError = 0; if (!ReadNamesFromListFile2(us2fs(fileName), names, codePage, lastError)) { @@ -449,7 +491,7 @@ static void AddToCensorFromNonSwitchesStrings( int stopSwitchIndex, NRecursedType::EEnum type, bool wildcardMatching, - bool thereAreSwitchIncludes, Int32 codePage) + bool thereAreSwitchIncludes, UInt32 codePage) { if ((renamePairs || nonSwitchStrings.Size() == startIndex) && !thereAreSwitchIncludes) AddNameToCensor(censor, UString(kUniversalWildcard), true, type, @@ -459,7 +501,7 @@ static void AddToCensorFromNonSwitchesStrings( int oldIndex = -1; if (stopSwitchIndex < 0) - stopSwitchIndex = nonSwitchStrings.Size(); + stopSwitchIndex = (int)nonSwitchStrings.Size(); for (unsigned i = startIndex; i < nonSwitchStrings.Size(); i++) { @@ -471,11 +513,11 @@ static void AddToCensorFromNonSwitchesStrings( else if (renamePairs) { if (oldIndex == -1) - oldIndex = i; + oldIndex = (int)i; else { // NRecursedType::EEnum type is used for global wildcard (-i! switches) - AddRenamePair(renamePairs, nonSwitchStrings[oldIndex], s, NRecursedType::kNonRecursed, wildcardMatching); + AddRenamePair(renamePairs, nonSwitchStrings[(unsigned)oldIndex], s, NRecursedType::kNonRecursed, wildcardMatching); // AddRenamePair(renamePairs, nonSwitchStrings[oldIndex], s, type); oldIndex = -1; } @@ -486,7 +528,7 @@ static void AddToCensorFromNonSwitchesStrings( if (oldIndex != -1) { - throw CArcCmdLineException("There is no second file name for rename pair:", nonSwitchStrings[oldIndex]); + throw CArcCmdLineException("There is no second file name for rename pair:", nonSwitchStrings[(unsigned)oldIndex]); } } @@ -517,23 +559,23 @@ static const char *ParseMapWithPaths( int pos = s.Find(L':'); if (pos < 0) return k_IncorrectMapCommand; - int pos2 = s.Find(L':', pos + 1); + int pos2 = s.Find(L':', (unsigned)(pos + 1)); if (pos2 < 0) return k_IncorrectMapCommand; - CEventSetEnd eventSetEnd((const wchar_t *)s + ((unsigned)pos2 + 1)); - s.DeleteFrom(pos2); + CEventSetEnd eventSetEnd((const wchar_t *)s + (unsigned)(pos2 + 1)); + s.DeleteFrom((unsigned)pos2); UInt32 size; - if (!StringToUInt32(s.Ptr(pos + 1), size) + if (!StringToUInt32(s.Ptr((unsigned)(pos + 1)), size) || size < sizeof(wchar_t) || size > ((UInt32)1 << 31) || size % sizeof(wchar_t) != 0) return "Unsupported Map data size"; - s.DeleteFrom(pos); + s.DeleteFrom((unsigned)pos); CFileMapping map; if (map.Open(FILE_MAP_READ, GetSystemString(s)) != 0) - return "Can not open mapping"; + return "Cannot open mapping"; LPVOID data = map.Map(FILE_MAP_READ, 0, size); if (!data) return "MapViewOfFile error"; @@ -569,7 +611,7 @@ static void AddSwitchWildcardsToCensor( const UStringVector &strings, bool include, NRecursedType::EEnum commonRecursedType, bool wildcardMatching, - Int32 codePage) + UInt32 codePage) { const char *errorMessage = NULL; unsigned i; @@ -667,9 +709,9 @@ static bool ParseUpdateCommandString2(const UString &command, if (i >= command.Len()) return false; c = command[i]; - if (c < '0' || c >= '0' + kNumUpdatePairActions) + if (c < '0' || c >= (wchar_t)('0' + kNumUpdatePairActions)) return false; - unsigned actionPos = c - '0'; + unsigned actionPos = (unsigned)(c - '0'); actionSet.StateActions[(unsigned)statePos] = (NUpdateArchive::NPairAction::EEnum)(actionPos); if (kUpdatePairStateNotSupportedActions[(unsigned)statePos] == (int)actionPos) return false; @@ -791,8 +833,8 @@ static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &pr int index = prop.Name.Find(L'='); if (index >= 0) { - prop.Value = prop.Name.Ptr(index + 1); - prop.Name.DeleteFrom(index); + prop.Value = prop.Name.Ptr((unsigned)(index + 1)); + prop.Name.DeleteFrom((unsigned)index); } properties.Add(prop); } @@ -803,13 +845,24 @@ static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &pr static inline void SetStreamMode(const CSwitchResult &sw, unsigned &res) { if (sw.ThereIs) - res = sw.PostCharIndex; + res = (unsigned)sw.PostCharIndex; } +#if defined(_WIN32) && !defined(UNDER_CE) +static void PrintHex(UString &s, UInt64 v) +{ + char temp[32]; + ConvertUInt64ToHex(v, temp); + s += temp; +} +#endif + + void CArcCmdLineParser::Parse1(const UStringVector &commandStrings, CArcCmdLineOptions &options) { + Parse1Log.Empty(); if (!parser.ParseStrings(kSwitchForms, ARRAY_SIZE(kSwitchForms), commandStrings)) throw CArcCmdLineException(parser.ErrorMessage, parser.ErrorLine); @@ -879,14 +932,16 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings, #ifdef _7ZIP_LARGE_PAGES if (slp > - #ifndef UNDER_CE + #if defined(_WIN32) && !defined(UNDER_CE) (unsigned)NSecurity::Get_LargePages_RiskLevel() #else 0 #endif ) { + #ifdef _WIN32 // change it ! SetLargePageSize(); + #endif // note: this process also can inherit that Privilege from parent process g_LargePagesMode = #if defined(_WIN32) && !defined(UNDER_CE) @@ -906,32 +961,83 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings, const UString &s = parser[NKey::kAffinity].PostStrings[0]; if (!s.IsEmpty()) { - UInt32 v = 0; AString a; a.SetFromWStr_if_Ascii(s); - if (!a.IsEmpty()) + Parse1Log += "Set process affinity mask: "; + + #ifdef _WIN32 + + UInt64 v = 0; { const char *end; - v = ConvertHexStringToUInt32(a, &end); + v = ConvertHexStringToUInt64(a, &end); if (*end != 0) a.Empty(); } if (a.IsEmpty()) throw CArcCmdLineException("Unsupported switch postfix -stm", s); + + { + #ifndef _WIN64 + if (v >= ((UInt64)1 << 32)) + throw CArcCmdLineException("unsupported value -stm", s); + #endif + { + PrintHex(Parse1Log, v); + if (!SetProcessAffinityMask(GetCurrentProcess(), (DWORD_PTR)v)) + { + DWORD lastError = GetLastError(); + Parse1Log += " : ERROR : "; + Parse1Log += NError::MyFormatMessage(lastError); + } + } + } - #ifdef _WIN32 - SetProcessAffinityMask(GetCurrentProcess(), v); - #endif + #else // _WIN32 + + { + Parse1Log += a; + NSystem::CProcessAffinity aff; + aff.CpuZero(); + for (unsigned i = 0; i < a.Len(); i++) + { + char c = a[i]; + unsigned v; + if (c >= '0' && c <= '9') v = (unsigned)(c - '0'); + else if (c >= 'A' && c <= 'F') v = 10 + (unsigned)(c - 'A'); + else if (c >= 'a' && c <= 'f') v = 10 + (unsigned)(c - 'a'); + else + throw CArcCmdLineException("Unsupported switch postfix -stm", s); + for (unsigned k = 0; k < 4; k++) + { + const unsigned cpu = (a.Len() - 1 - i) * 4 + k; + if (v & ((unsigned)1 << k)) + aff.CpuSet(cpu); + } + } + + if (!aff.SetProcAffinity()) + { + DWORD lastError = GetLastError(); + Parse1Log += " : ERROR : "; + Parse1Log += NError::MyFormatMessage(lastError); + } + } + #endif // _WIN32 + + Parse1Log.Add_LF(); } } #endif } + + struct CCodePagePair { const char *Name; - Int32 CodePage; + UInt32 CodePage; }; static const unsigned kNumByteOnlyCodePages = 3; @@ -964,7 +1070,7 @@ static Int32 FindCharset(const NCommandLineParser::CParser &parser, unsigned key throw CArcCmdLineException("Unsupported charset:", name); const CCodePagePair &pair = g_CodePagePairs[i]; if (name.IsEqualTo(pair.Name)) - return pair.CodePage; + return (Int32)pair.CodePage; } } @@ -1023,8 +1129,9 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) if (parser[NKey::kDisableWildcardParsing].ThereIs) wildcardMatching = false; - g_CodePage = FindCharset(parser, NKey::kConsoleCharSet, true, -1); - Int32 codePage = FindCharset(parser, NKey::kListfileCharSet, false, CP_UTF8); + options.ConsoleCodePage = FindCharset(parser, NKey::kConsoleCharSet, true, -1); + + UInt32 codePage = (UInt32)FindCharset(parser, NKey::kListfileCharSet, false, CP_UTF8); bool thereAreSwitchIncludes = false; @@ -1097,6 +1204,30 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) SetBoolPair(parser, NKey::kHardLinks, options.HardLinks); SetBoolPair(parser, NKey::kSymLinks, options.SymLinks); + CBoolPair symLinks_AllowDangerous; + SetBoolPair(parser, NKey::kSymLinks_AllowDangerous, symLinks_AllowDangerous); + + + /* + bool supportSymLink = options.SymLinks.Val; + + if (!options.SymLinks.Def) + { + if (isExtractOrList) + supportSymLink = true; + else + supportSymLink = false; + } + + #ifdef ENV_HAVE_LSTAT + if (supportSymLink) + global_use_lstat = 1; + else + global_use_lstat = 0; + #endif + */ + + if (isExtractOrList) { CExtractOptionsBase &eo = options.ExtractOptions; @@ -1117,6 +1248,8 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) if (!options.SymLinks.Def) nt.SymLinks.Val = true; + nt.SymLinks_AllowDangerous = symLinks_AllowDangerous; + nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs; nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs; } @@ -1174,6 +1307,9 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) if (parser[NKey::kOutputDir].ThereIs) { eo.OutputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]); + #ifdef _WIN32 + NFile::NName::NormalizeDirSeparators(eo.OutputDir); + #endif NFile::NName::NormalizeDirPathPrefix(eo.OutputDir); } @@ -1213,6 +1349,8 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) updateOptions.MethodMode.Properties = options.Properties; + if (parser[NKey::kPreserveATime].ThereIs) + updateOptions.PreserveATime = true; if (parser[NKey::kShareForWrite].ThereIs) updateOptions.OpenShareForWrite = true; if (parser[NKey::kStopAfterOpenError].ThereIs) @@ -1270,7 +1408,7 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) if (curCommandIndex < numNonSwitchStrings) { if (!StringToUInt32(nonSwitchStrings[curCommandIndex], options.NumIterations)) - throw CArcCmdLineException("Incorrect Number of benmchmark iterations", nonSwitchStrings[curCommandIndex]); + throw CArcCmdLineException("Incorrect number of benchmark iterations", nonSwitchStrings[curCommandIndex]); curCommandIndex++; } } @@ -1282,10 +1420,13 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) CHashOptions &hashOptions = options.HashOptions; hashOptions.PathMode = censorPathMode; hashOptions.Methods = options.HashMethods; + if (parser[NKey::kPreserveATime].ThereIs) + hashOptions.PreserveATime = true; if (parser[NKey::kShareForWrite].ThereIs) hashOptions.OpenShareForWrite = true; hashOptions.StdInMode = options.StdInMode; hashOptions.AltStreamsMode = options.AltStreams.Val; + hashOptions.SymLinks = options.SymLinks; } else if (options.Command.CommandType == NCommandType::kInfo) { @@ -1293,3 +1434,45 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) else throw 20150919; } + + + +#ifndef _WIN32 + +static AString g_ModuleDirPrefix; + +void Set_ModuleDirPrefix_From_ProgArg0(const char *s); +void Set_ModuleDirPrefix_From_ProgArg0(const char *s) +{ + AString a (s); + int sep = a.ReverseFind_PathSepar(); + a.DeleteFrom((unsigned)(sep + 1)); + g_ModuleDirPrefix = a; +} + +namespace NWindows { +namespace NDLL { + +FString GetModuleDirPrefix(); +FString GetModuleDirPrefix() +{ + FString s; + + s = g_ModuleDirPrefix; + if (s.IsEmpty()) + s = FTEXT(".") FSTRING_PATH_SEPARATOR; + return s; + /* + setenv("_7ZIP_HOME_DIR", "/test/", 0); + const char *home = getenv("_7ZIP_HOME_DIR"); + if (home) + s = home; + else + s = FTEXT(".") FSTRING_PATH_SEPARATOR; + return s; + */ +} + +}} + +#endif // ! _WIN32 diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.h b/CPP/7zip/UI/Common/ArchiveCommandLine.h index 9ed0825f..150541e6 100644 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.h +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.h @@ -63,6 +63,11 @@ struct CArcCmdLineOptions bool YesToAll; bool ShowDialog; + bool TechMode; + bool ShowTime; + + int ConsoleCodePage; + NWildcard::CCensor Censor; CArcCommand Command; @@ -73,9 +78,6 @@ struct CArcCmdLineOptions UString Password; #endif - bool TechMode; - bool ShowTime; - UStringVector HashMethods; bool AppendName; @@ -109,13 +111,27 @@ struct CArcCmdLineOptions UInt32 NumIterations; CArcCmdLineOptions(): + HelpMode(false), // LargePages(false), CaseSensitiveChange(false), CaseSensitive(false), + IsInTerminal(false), + IsStdOutTerminal(false), + IsStdErrTerminal(false), + StdInMode(false), StdOutMode(false), + EnableHeaders(false), + + YesToAll(false), + ShowDialog(false), + TechMode(false), + ShowTime(false), + + ConsoleCodePage(-1), + Number_for_Out(k_OutStream_stdout), Number_for_Errors(k_OutStream_stderr), Number_for_Percents(k_OutStream_stdout), @@ -129,6 +145,7 @@ class CArcCmdLineParser { NCommandLineParser::CParser parser; public: + UString Parse1Log; void Parse1(const UStringVector &commandStrings, CArcCmdLineOptions &options); void Parse2(CArcCmdLineOptions &options); }; diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp index de2f2e00..40e43d2a 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp @@ -15,6 +15,7 @@ #include "../../../Common/ComTry.h" #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" +#include "../../../Common/UTFConvert.h" #include "../../../Common/Wildcard.h" #include "../../../Windows/ErrorMsg.h" @@ -30,7 +31,7 @@ #endif #include "../../Common/FilePathAutoRename.h" -// #include "../../Common/StreamUtils.h" +#include "../../Common/StreamUtils.h" #include "../Common/ExtractingFilePath.h" #include "../Common/PropIDUtils.h" @@ -41,15 +42,16 @@ using namespace NWindows; using namespace NFile; using namespace NDir; -static const char * const kCantAutoRename = "Can not create file with auto name"; -static const char * const kCantRenameFile = "Can not rename existing file"; -static const char * const kCantDeleteOutputFile = "Can not delete output file"; -static const char * const kCantDeleteOutputDir = "Can not delete output folder"; -static const char * const kCantCreateHardLink = "Can not create hard link"; -static const char * const kCantCreateSymLink = "Can not create symbolic link"; -static const char * const kCantOpenOutFile = "Can not open output file"; -static const char * const kCantSetFileLen = "Can not set length for output file"; - +static const char * const kCantAutoRename = "Cannot create file with auto name"; +static const char * const kCantRenameFile = "Cannot rename existing file"; +static const char * const kCantDeleteOutputFile = "Cannot delete output file"; +static const char * const kCantDeleteOutputDir = "Cannot delete output folder"; +static const char * const kCantOpenOutFile = "Cannot open output file"; +static const char * const kCantSetFileLen = "Cannot set length for output file"; +#ifdef SUPPORT_LINKS +static const char * const kCantCreateHardLink = "Cannot create hard link"; +static const char * const kCantCreateSymLink = "Cannot create symbolic link"; +#endif #ifndef _SFX @@ -66,9 +68,11 @@ STDMETHODIMP COutStreamWithHash::Write(const void *data, UInt32 size, UInt32 *pr return result; } -#endif +#endif // _SFX + #ifdef _USE_SECURITY_CODE +bool InitLocalPrivileges(); bool InitLocalPrivileges() { NSecurity::CAccessToken token; @@ -87,7 +91,8 @@ bool InitLocalPrivileges() return false; return (GetLastError() == ERROR_SUCCESS); } -#endif +#endif // _USE_SECURITY_CODE + #ifdef SUPPORT_LINKS @@ -158,7 +163,7 @@ HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *r hardIDs.Sort2(); { - // wee keep only items that have 2 or more items + // we keep only items that have 2 or more items unsigned k = 0; unsigned numSame = 1; for (unsigned i = 1; i < hardIDs.Size(); i++) @@ -179,7 +184,8 @@ HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *r return S_OK; } -#endif +#endif // SUPPORT_LINKS + CArchiveExtractCallback::CArchiveExtractCallback(): _arc(NULL), @@ -196,6 +202,7 @@ CArchiveExtractCallback::CArchiveExtractCallback(): #endif } + void CArchiveExtractCallback::Init( const CExtractNtOptions &ntOptions, const NWildcard::CCensorNode *wildcardCensor, @@ -208,6 +215,7 @@ void CArchiveExtractCallback::Init( { ClearExtractedDirsInfo(); _outFileStream.Release(); + _bufPtrSeqOutStream.Release(); #ifdef SUPPORT_LINKS _hardLinks.Clear(); @@ -274,6 +282,7 @@ void CArchiveExtractCallback::Init( } } + STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size) { COM_TRY_BEGIN @@ -285,6 +294,7 @@ STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size) COM_TRY_END } + static void NormalizeVals(UInt64 &v1, UInt64 &v2) { const UInt64 kMax = (UInt64)1 << 31; @@ -295,6 +305,7 @@ static void NormalizeVals(UInt64 &v1, UInt64 &v2) } } + static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal) { NormalizeVals(packTotal, unpTotal); @@ -304,6 +315,7 @@ static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal) return unpCur * packTotal / unpTotal; } + STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue) { COM_TRY_BEGIN @@ -324,6 +336,7 @@ STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue) COM_TRY_END } + STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { COM_TRY_BEGIN @@ -331,6 +344,7 @@ STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const U COM_TRY_END } + void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath) { bool isAbsPath = false; @@ -369,6 +383,7 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat } } + HRESULT CArchiveExtractCallback::GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined) { filetimeIsDefined = false; @@ -417,9 +432,14 @@ HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *mes return _extractCallback2->MessageError(s); } -HRESULT CArchiveExtractCallback::SendMessageError2(const char *message, const FString &path1, const FString &path2) +HRESULT CArchiveExtractCallback::SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2) { UString s (message); + if (errorCode != 0) + { + s += " : "; + s += NError::MyFormatMessage(errorCode); + } AddPathToMessage(s, path1); AddPathToMessage(s, path2); return _extractCallback2->MessageError(s); @@ -442,7 +462,7 @@ STDMETHODIMP CGetProp::GetProp(PROPID propID, PROPVARIANT *value) return Arc->Archive->GetProperty(IndexInArc, propID, value); } -#endif +#endif // _SFX #ifdef SUPPORT_LINKS @@ -455,22 +475,32 @@ static UString GetDirPrefixOf(const UString &src) if (IsPathSepar(s.Back())) s.DeleteBack(); int pos = s.ReverseFind_PathSepar(); - s.DeleteFrom(pos + 1); + s.DeleteFrom((unsigned)(pos + 1)); } return s; } -#endif +#endif // SUPPORT_LINKS +struct CLinkLevelsInfo +{ + bool IsAbsolute; + int LowLevel; + int FinalLevel; -bool IsSafePath(const UString &path) + void Parse(const UString &path); +}; + +void CLinkLevelsInfo::Parse(const UString &path) { - if (NName::IsAbsolutePath(path)) - return false; + IsAbsolute = NName::IsAbsolutePath(path); + + LowLevel = 0; + FinalLevel = 0; UStringVector parts; SplitPathToParts(path, parts); - unsigned level = 0; + int level = 0; FOR_VECTOR (i, parts) { @@ -478,29 +508,42 @@ bool IsSafePath(const UString &path) if (s.IsEmpty()) { if (i == 0) - return false; + IsAbsolute = true; continue; } if (s == L".") continue; if (s == L"..") { - if (level == 0) - return false; level--; + if (LowLevel > level) + LowLevel = level; } else level++; } - return level > 0; + FinalLevel = level; +} + + +bool IsSafePath(const UString &path); +bool IsSafePath(const UString &path) +{ + CLinkLevelsInfo levelsInfo; + levelsInfo.Parse(path); + return !levelsInfo.IsAbsolute + && levelsInfo.LowLevel >= 0 + && levelsInfo.FinalLevel > 0; } +bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include); bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include) { bool found = false; - + + // CheckPathVect() doesn't check path to Parent nodes if (node.CheckPathVect(item.PathParts, !item.MainIsDir, include)) { if (!include) @@ -535,11 +578,12 @@ bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcIte return true; } - #endif + #endif // SUPPORT_ALT_STREAMS return found; } + bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item) { bool include; @@ -548,6 +592,7 @@ bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem return false; } + static FString MakePath_from_2_Parts(const FString &prefix, const FString &path) { FString s (prefix); @@ -563,9 +608,10 @@ static FString MakePath_from_2_Parts(const FString &prefix, const FString &path) } -/* + #ifdef SUPPORT_LINKS +/* struct CTempMidBuffer { void *Buf; @@ -601,90 +647,23 @@ HRESULT CArchiveExtractCallback::MyCopyFile(ISequentialOutStream *outStream) RINOK(WriteStream(outStream, buf.Buf, num)); } } - -#endif */ -STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) +HRESULT CArchiveExtractCallback::ReadLink() { - COM_TRY_BEGIN - - *outStream = NULL; - - #ifndef _SFX - if (_hashStream) - _hashStreamSpec->ReleaseStream(); - _hashStreamWasUsed = false; - #endif - - _outFileStream.Release(); - - _encrypted = false; - _position = 0; - _isSplit = false; - - _curSize = 0; - _curSizeDefined = false; - _fileLengthWasSet = false; - _index = index; - - _diskFilePath.Empty(); - - // _fi.Clear(); - - #ifdef SUPPORT_LINKS - // _CopyFile_Path.Empty(); - linkPath.Empty(); - #endif - IInArchive *archive = _arc->Archive; - - #ifndef _SFX - _item._use_baseParentFolder_mode = _use_baseParentFolder_mode; - if (_use_baseParentFolder_mode) - { - _item._baseParentFolder = _baseParentFolder; - if (_pathMode == NExtract::NPathMode::kFullPaths || - _pathMode == NExtract::NPathMode::kAbsPaths) - _item._baseParentFolder = -1; - } - #endif - - #ifdef SUPPORT_ALT_STREAMS - _item.WriteToAltStreamIfColon = _ntOptions.WriteToAltStreamIfColon; - #endif - - RINOK(_arc->GetItem(index, _item)); - - { - NCOM::CPropVariant prop; - RINOK(archive->GetProperty(index, kpidPosition, &prop)); - if (prop.vt != VT_EMPTY) - { - if (prop.vt != VT_UI8) - return E_FAIL; - _position = prop.uhVal.QuadPart; - _isSplit = true; - } - } - - #ifdef SUPPORT_LINKS - - // bool isCopyLink = false; - bool isHardLink = false; - bool isJunction = false; - bool isRelative = false; + const UInt32 index = _index; { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidHardLink, &prop)); if (prop.vt == VT_BSTR) { - isHardLink = true; - // isCopyLink = false; - isRelative = false; // RAR5, TAR: hard links are from root folder of archive - linkPath.SetFromBstr(prop.bstrVal); + _link.isHardLink = true; + // _link.isCopyLink = false; + _link.isRelative = false; // RAR5, TAR: hard links are from root folder of archive + _link.linkPath.SetFromBstr(prop.bstrVal); } else if (prop.vt != VT_EMPTY) return E_FAIL; @@ -696,10 +675,10 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre RINOK(archive->GetProperty(index, kpidCopyLink, &prop)); if (prop.vt == VT_BSTR) { - isHardLink = false; - isCopyLink = true; - isRelative = false; // RAR5: copy links are from root folder of archive - linkPath.SetFromBstr(prop.bstrVal); + _link.isHardLink = false; + _link.isCopyLink = true; + _link.isRelative = false; // RAR5: copy links are from root folder of archive + _link.linkPath.SetFromBstr(prop.bstrVal); } else if (prop.vt != VT_EMPTY) return E_FAIL; @@ -711,19 +690,19 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre RINOK(archive->GetProperty(index, kpidSymLink, &prop)); if (prop.vt == VT_BSTR) { - isHardLink = false; - // isCopyLink = false; - isRelative = true; // RAR5, TAR: symbolic links can be relative - linkPath.SetFromBstr(prop.bstrVal); + _link.isHardLink = false; + // _link.isCopyLink = false; + _link.isRelative = true; // RAR5, TAR: symbolic links can be relative + _link.linkPath.SetFromBstr(prop.bstrVal); } else if (prop.vt != VT_EMPTY) return E_FAIL; } + NtReparse_Data = NULL; + NtReparse_Size = 0; - bool isOkReparse = false; - - if (linkPath.IsEmpty() && _arc->GetRawProps) + if (_link.linkPath.IsEmpty() && _arc->GetRawProps) { const void *data; UInt32 dataSize; @@ -731,56 +710,75 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre _arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType); + // if (dataSize == 1234567) // for debug: unpacking without reparse if (dataSize != 0) { if (propType != NPropDataType::kRaw) return E_FAIL; - UString s; + + #ifdef _WIN32 + + NtReparse_Data = data; + NtReparse_Size = dataSize; + CReparseAttr reparse; - DWORD errorCode = 0; - isOkReparse = reparse.Parse((const Byte *)data, dataSize, errorCode); + bool isOkReparse = reparse.Parse((const Byte *)data, dataSize); if (isOkReparse) { - isHardLink = false; - // isCopyLink = false; - linkPath = reparse.GetPath(); - isJunction = reparse.IsMountPoint(); - isRelative = reparse.IsRelative(); + _link.isHardLink = false; + // _link.isCopyLink = false; + _link.linkPath = reparse.GetPath(); + _link.isJunction = reparse.IsMountPoint(); + + if (reparse.IsSymLink_WSL()) + { + _link.isWSL = true; + _link.isRelative = reparse.IsRelative_WSL(); + } + else + _link.isRelative = reparse.IsRelative_Win(); + #ifndef _WIN32 - linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); + _link.linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); #endif } + #endif } } - if (!linkPath.IsEmpty()) + if (_link.linkPath.IsEmpty()) + return S_OK; + { #ifdef _WIN32 - linkPath.Replace(L'/', WCHAR_PATH_SEPARATOR); + _link.linkPath.Replace(L'/', WCHAR_PATH_SEPARATOR); #endif // rar5 uses "\??\" prefix for absolute links - if (linkPath.IsPrefixedBy(WSTRING_PATH_SEPARATOR L"??" WSTRING_PATH_SEPARATOR)) + if (_link.linkPath.IsPrefixedBy(WSTRING_PATH_SEPARATOR L"??" WSTRING_PATH_SEPARATOR)) { - isRelative = false; - linkPath.DeleteFrontal(4); + _link.isRelative = false; + _link.linkPath.DeleteFrontal(4); } for (;;) // while (NName::IsAbsolutePath(linkPath)) { - unsigned n = NName::GetRootPrefixSize(linkPath); + unsigned n = NName::GetRootPrefixSize(_link.linkPath); if (n == 0) break; - isRelative = false; - linkPath.DeleteFrontal(n); + _link.isRelative = false; + _link.linkPath.DeleteFrontal(n); } } - if (!linkPath.IsEmpty() && !isRelative && _removePathParts.Size() != 0) + if (_link.linkPath.IsEmpty()) + return S_OK; + + if (!_link.isRelative && _removePathParts.Size() != 0) { UStringVector pathParts; - SplitPathToParts(linkPath, pathParts); + SplitPathToParts(_link.linkPath, pathParts); bool badPrefix = false; FOR_VECTOR (i, _removePathParts) { @@ -792,22 +790,597 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre } if (!badPrefix) pathParts.DeleteFrontal(_removePathParts.Size()); - linkPath = MakePathFromParts(pathParts); + _link.linkPath = MakePathFromParts(pathParts); + } + + /* + if (!_link.linkPath.IsEmpty()) + { + printf("\n_link %s to -> %s\n", GetOemString(_item.Path).Ptr(), GetOemString(_link.linkPath).Ptr()); + } + */ + + return S_OK; +} + +#endif // SUPPORT_LINKS + + + +HRESULT CArchiveExtractCallback::Read_fi_Props() +{ + IInArchive *archive = _arc->Archive; + const UInt32 index = _index; + + _fi.AttribDefined = false; + + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidPosixAttrib, &prop)); + if (prop.vt == VT_UI4) + { + _fi.SetFromPosixAttrib(prop.ulVal); + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; } + + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidAttrib, &prop)); + if (prop.vt == VT_UI4) + { + _fi.Attrib = prop.ulVal; + _fi.AttribDefined = true; + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; + } + + RINOK(GetTime(index, kpidCTime, _fi.CTime, _fi.CTimeDefined)); + RINOK(GetTime(index, kpidATime, _fi.ATime, _fi.ATimeDefined)); + RINOK(GetTime(index, kpidMTime, _fi.MTime, _fi.MTimeDefined)); + return S_OK; +} + + +void CArchiveExtractCallback::CorrectPathParts() +{ + UStringVector &pathParts = _item.PathParts; + + #ifdef SUPPORT_ALT_STREAMS + if (!_item.IsAltStream + || !pathParts.IsEmpty() + || !(_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt)) #endif + Correct_FsPath(_pathMode == NExtract::NPathMode::kAbsPaths, _keepAndReplaceEmptyDirPrefixes, pathParts, _item.MainIsDir); - RINOK(Archive_GetItemBoolProp(archive, index, kpidEncrypted, _encrypted)); + #ifdef SUPPORT_ALT_STREAMS + + if (_item.IsAltStream) + { + UString s (_item.AltStreamName); + Correct_AltStream_Name(s); + bool needColon = true; + + if (pathParts.IsEmpty()) + { + pathParts.AddNew(); + if (_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt) + needColon = false; + } + #ifdef _WIN32 + else if (_pathMode == NExtract::NPathMode::kAbsPaths && + NWildcard::GetNumPrefixParts_if_DrivePath(pathParts) == pathParts.Size()) + pathParts.AddNew(); + #endif + + UString &name = pathParts.Back(); + if (needColon) + name += (char)(_ntOptions.ReplaceColonForAltStream ? '_' : ':'); + name += s; + } + + #endif // SUPPORT_ALT_STREAMS +} + - RINOK(GetUnpackSize()); + +void CArchiveExtractCallback::CreateFolders() +{ + UStringVector &pathParts = _item.PathParts; + + if (!_item.IsDir) + { + if (!pathParts.IsEmpty()) + pathParts.DeleteBack(); + } + + if (pathParts.IsEmpty()) + return; + + FString fullPathNew; + CreateComplexDirectory(pathParts, fullPathNew); + + if (!_item.IsDir) + return; + + CDirPathTime &pt = _extractedFolders.AddNew(); + + pt.CTime = _fi.CTime; + pt.CTimeDefined = (WriteCTime && _fi.CTimeDefined); + + pt.ATime = _fi.ATime; + pt.ATimeDefined = (WriteATime && _fi.ATimeDefined); + + pt.MTimeDefined = false; + + if (WriteMTime) + { + if (_fi.MTimeDefined) + { + pt.MTime = _fi.MTime; + pt.MTimeDefined = true; + } + else if (_arc->MTimeDefined) + { + pt.MTime = _arc->MTime; + pt.MTimeDefined = true; + } + } + + pt.Path = fullPathNew; + pt.SetDirTime(); +} + + + +/* + CheckExistFile(fullProcessedPath) + it can change: fullProcessedPath, _isRenamed, _overwriteMode + (needExit = true) means that we must exit GetStream() even for S_OK result. +*/ + +HRESULT CArchiveExtractCallback::CheckExistFile(FString &fullProcessedPath, bool &needExit) +{ + needExit = true; // it was set already before + + NFind::CFileInfo fileInfo; + + if (fileInfo.Find(fullProcessedPath)) + { + if (_overwriteMode == NExtract::NOverwriteMode::kSkip) + return S_OK; + + if (_overwriteMode == NExtract::NOverwriteMode::kAsk) + { + int slashPos = fullProcessedPath.ReverseFind_PathSepar(); + FString realFullProcessedPath (fullProcessedPath.Left((unsigned)(slashPos + 1)) + fileInfo.Name); + + /* (fileInfo) can be symbolic link. + we can show final file properties here. */ + + Int32 overwriteResult; + RINOK(_extractCallback2->AskOverwrite( + fs2us(realFullProcessedPath), &fileInfo.MTime, &fileInfo.Size, _item.Path, + _fi.MTimeDefined ? &_fi.MTime : NULL, + _curSizeDefined ? &_curSize : NULL, + &overwriteResult)) + + switch (overwriteResult) + { + case NOverwriteAnswer::kCancel: + return E_ABORT; + case NOverwriteAnswer::kNo: + return S_OK; + case NOverwriteAnswer::kNoToAll: + _overwriteMode = NExtract::NOverwriteMode::kSkip; + return S_OK; + + case NOverwriteAnswer::kYes: + break; + case NOverwriteAnswer::kYesToAll: + _overwriteMode = NExtract::NOverwriteMode::kOverwrite; + break; + case NOverwriteAnswer::kAutoRename: + _overwriteMode = NExtract::NOverwriteMode::kRename; + break; + default: + return E_FAIL; + } + } // NExtract::NOverwriteMode::kAsk + + if (_overwriteMode == NExtract::NOverwriteMode::kRename) + { + if (!AutoRenamePath(fullProcessedPath)) + { + RINOK(SendMessageError(kCantAutoRename, fullProcessedPath)); + return E_FAIL; + } + _isRenamed = true; + } + else if (_overwriteMode == NExtract::NOverwriteMode::kRenameExisting) + { + FString existPath (fullProcessedPath); + if (!AutoRenamePath(existPath)) + { + RINOK(SendMessageError(kCantAutoRename, fullProcessedPath)); + return E_FAIL; + } + // MyMoveFile can rename folders. So it's OK to use it for folders too + if (!MyMoveFile(fullProcessedPath, existPath)) + { + HRESULT errorCode = GetLastError_noZero_HRESULT(); + RINOK(SendMessageError2(errorCode, kCantRenameFile, existPath, fullProcessedPath)); + return E_FAIL; + } + } + else // not Rename* + { + if (fileInfo.IsDir()) + { + // do we need to delete all files in folder? + if (!RemoveDir(fullProcessedPath)) + { + RINOK(SendMessageError_with_LastError(kCantDeleteOutputDir, fullProcessedPath)); + return S_OK; + } + } + else // fileInfo is not Dir + { + if (NFind::DoesFileExist_Raw(fullProcessedPath)) + if (!DeleteFileAlways(fullProcessedPath)) + if (GetLastError() != ERROR_FILE_NOT_FOUND) // check it in linux + { + RINOK(SendMessageError_with_LastError(kCantDeleteOutputFile, fullProcessedPath)); + return S_OK; + // return E_FAIL; + } + } // fileInfo is not Dir + } // not Rename* + } + else // not Find(fullProcessedPath) + { + #if defined(_WIN32) && !defined(UNDER_CE) + // we need to clear READ-ONLY of parent before creating alt stream + int colonPos = NName::FindAltStreamColon(fullProcessedPath); + if (colonPos >= 0 && fullProcessedPath[(unsigned)colonPos + 1] != 0) + { + FString parentFsPath (fullProcessedPath); + parentFsPath.DeleteFrom((unsigned)colonPos); + NFind::CFileInfo parentFi; + if (parentFi.Find(parentFsPath)) + { + if (parentFi.IsReadOnly()) + SetFileAttrib(parentFsPath, parentFi.Attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY); + } + } + #endif // defined(_WIN32) && !defined(UNDER_CE) + } + + needExit = false; + return S_OK; +} + + + + + + +HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit) +{ + needExit = true; + + RINOK(Read_fi_Props()); + + #ifdef SUPPORT_LINKS + IInArchive *archive = _arc->Archive; + #endif + + const UStringVector &pathParts = _item.PathParts; + const UInt32 index = _index; + + bool isAnti = false; + RINOK(_arc->IsItemAnti(index, isAnti)); + + CorrectPathParts(); + + UString processedPath (MakePathFromParts(pathParts)); + + if (!isAnti) + CreateFolders(); + + FString fullProcessedPath (us2fs(processedPath)); + if (_pathMode != NExtract::NPathMode::kAbsPaths + || !NName::IsAbsolutePath(processedPath)) + { + fullProcessedPath = MakePath_from_2_Parts(_dirPathPrefix, fullProcessedPath); + } #ifdef SUPPORT_ALT_STREAMS + if (_item.IsAltStream && _item.ParentIndex != (UInt32)(Int32)-1) + { + int renIndex = _renamedFiles.FindInSorted(CIndexToPathPair(_item.ParentIndex)); + if (renIndex >= 0) + { + const CIndexToPathPair &pair = _renamedFiles[(unsigned)renIndex]; + fullProcessedPath = pair.Path; + fullProcessedPath += ':'; + UString s (_item.AltStreamName); + Correct_AltStream_Name(s); + fullProcessedPath += us2fs(s); + } + } + #endif // SUPPORT_ALT_STREAMS + + if (_item.IsDir) + { + _diskFilePath = fullProcessedPath; + if (isAnti) + RemoveDir(_diskFilePath); + #ifdef SUPPORT_LINKS + if (_link.linkPath.IsEmpty()) + #endif + return S_OK; + } + else if (!_isSplit) + { + RINOK(CheckExistFile(fullProcessedPath, needExit)); + if (needExit) + return S_OK; + needExit = true; + } - if (!_ntOptions.AltStreams.Val && _item.IsAltStream) + _diskFilePath = fullProcessedPath; + + + if (isAnti) + { + needExit = false; return S_OK; + } + + // not anti + + #ifdef SUPPORT_LINKS + + if (!_link.linkPath.IsEmpty()) + { + #ifndef UNDER_CE + { + bool linkWasSet = false; + RINOK(SetFromLinkPath(fullProcessedPath, _link, linkWasSet)); + } + #endif // UNDER_CE + + // if (_CopyFile_Path.IsEmpty()) + { + needExit = false; + return S_OK; + } + } + + if (!_hardLinks.IDs.IsEmpty() && !_item.IsAltStream) + { + CHardLinkNode h; + bool defined; + RINOK(Archive_Get_HardLinkNode(archive, index, h, defined)); + if (defined) + { + int linkIndex = _hardLinks.IDs.FindInSorted2(h); + if (linkIndex >= 0) + { + FString &hl = _hardLinks.Links[(unsigned)linkIndex]; + if (hl.IsEmpty()) + hl = fullProcessedPath; + else + { + if (!MyCreateHardLink(fullProcessedPath, hl)) + { + HRESULT errorCode = GetLastError_noZero_HRESULT(); + RINOK(SendMessageError2(errorCode, kCantCreateHardLink, fullProcessedPath, hl)); + return S_OK; + } + + needExit = false; + return S_OK; + } + } + } + } + + #endif // SUPPORT_LINKS + + + // ---------- CREATE WRITE FILE ----- + + _outFileStreamSpec = new COutFileStream; + CMyComPtr<ISequentialOutStream> outFileStream_Loc(_outFileStreamSpec); + + if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS)) + { + // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) + { + RINOK(SendMessageError_with_LastError(kCantOpenOutFile, fullProcessedPath)); + return S_OK; + } + } + + _fileWasExtracted = true; + + if (_curSizeDefined && _curSize > 0 && _curSize < (1 << 12)) + { + if (_fi.IsLinuxSymLink()) + { + _is_SymLink_in_Data = true; + _is_SymLink_in_Data_Linux = true; + } + else if (_fi.IsReparse()) + { + _is_SymLink_in_Data = true; + _is_SymLink_in_Data_Linux = false; + } + } + if (_is_SymLink_in_Data) + { + _outMemBuf.Alloc((size_t)_curSize); + _bufPtrSeqOutStream_Spec = new CBufPtrSeqOutStream; + _bufPtrSeqOutStream = _bufPtrSeqOutStream_Spec; + _bufPtrSeqOutStream_Spec->Init(_outMemBuf, _outMemBuf.Size()); + outStreamLoc = _bufPtrSeqOutStream; + } + else // not reprase + { + if (_ntOptions.PreAllocateOutFile && !_isSplit && _curSizeDefined && _curSize > (1 << 12)) + { + // UInt64 ticks = GetCpuTicks(); + _fileLength_that_WasSet = _curSize; + bool res = _outFileStreamSpec->File.SetLength(_curSize); + _fileLengthWasSet = res; + + // ticks = GetCpuTicks() - ticks; + // printf("\nticks = %10d\n", (unsigned)ticks); + if (!res) + { + RINOK(SendMessageError_with_LastError(kCantSetFileLen, fullProcessedPath)); + } + + /* + _outFileStreamSpec->File.Close(); + ticks = GetCpuTicks() - ticks; + printf("\nticks = %10d\n", (unsigned)ticks); + return S_FALSE; + */ + + /* + File.SetLength() on FAT (xp64): is fast, but then File.Close() can be slow, + if we don't write any data. + File.SetLength() for remote share file (exFAT) can be slow in some cases, + and the Windows can return "network error" after 1 minute, + while remote file still can grow. + We need some way to detect such bad cases and disable PreAllocateOutFile mode. + */ + + res = _outFileStreamSpec->SeekToBegin_bool(); + if (!res) + { + RINOK(SendMessageError_with_LastError("Cannot seek to begin of file", fullProcessedPath)); + } + } // PreAllocateOutFile + + #ifdef SUPPORT_ALT_STREAMS + if (_isRenamed && !_item.IsAltStream) + { + CIndexToPathPair pair(index, fullProcessedPath); + unsigned oldSize = _renamedFiles.Size(); + unsigned insertIndex = _renamedFiles.AddToUniqueSorted(pair); + if (oldSize == _renamedFiles.Size()) + _renamedFiles[insertIndex].Path = fullProcessedPath; + } + #endif // SUPPORT_ALT_STREAMS + + if (_isSplit) + { + RINOK(_outFileStreamSpec->Seek((Int64)_position, STREAM_SEEK_SET, NULL)); + } + outStreamLoc = outFileStream_Loc; + } // if not reprase + + _outFileStream = outFileStream_Loc; + + needExit = false; + return S_OK; +} + + + + + +STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) +{ + COM_TRY_BEGIN + + *outStream = NULL; + + #ifndef _SFX + if (_hashStream) + _hashStreamSpec->ReleaseStream(); + _hashStreamWasUsed = false; #endif + _outFileStream.Release(); + _bufPtrSeqOutStream.Release(); + + _encrypted = false; + _position = 0; + _isSplit = false; + + _curSize = 0; + _curSizeDefined = false; + _fileLengthWasSet = false; + _fileLength_that_WasSet = 0; + _index = index; + + _diskFilePath.Empty(); + + _isRenamed = false; + // _fi.Clear(); + _is_SymLink_in_Data = false; + _is_SymLink_in_Data_Linux = false; + + _fileWasExtracted = false; + + #ifdef SUPPORT_LINKS + // _CopyFile_Path.Empty(); + _link.Clear(); + #endif + + IInArchive *archive = _arc->Archive; + + #ifndef _SFX + _item._use_baseParentFolder_mode = _use_baseParentFolder_mode; + if (_use_baseParentFolder_mode) + { + _item._baseParentFolder = (int)_baseParentFolder; + if (_pathMode == NExtract::NPathMode::kFullPaths || + _pathMode == NExtract::NPathMode::kAbsPaths) + _item._baseParentFolder = -1; + } + #endif // _SFX + + #ifdef SUPPORT_ALT_STREAMS + _item.WriteToAltStreamIfColon = _ntOptions.WriteToAltStreamIfColon; + #endif + + RINOK(_arc->GetItem(index, _item)); + + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidPosition, &prop)); + if (prop.vt != VT_EMPTY) + { + if (prop.vt != VT_UI8) + return E_FAIL; + _position = prop.uhVal.QuadPart; + _isSplit = true; + } + } + + #ifdef SUPPORT_LINKS + RINOK(ReadLink()); + #endif // SUPPORT_LINKS + + + RINOK(Archive_GetItemBoolProp(archive, index, kpidEncrypted, _encrypted)); + + RINOK(GetUnpackSize()); + + #ifdef SUPPORT_ALT_STREAMS + if (!_ntOptions.AltStreams.Val && _item.IsAltStream) + return S_OK; + #endif // SUPPORT_ALT_STREAMS UStringVector &pathParts = _item.PathParts; @@ -836,7 +1409,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre } } else - #endif + #endif // _SFX { if (pathParts.IsEmpty()) { @@ -924,11 +1497,14 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre case NExtract::NPathMode::kAbsPaths: break; */ + default: + break; } pathParts.DeleteFrontal(numRemovePathParts); } + #ifndef _SFX if (ExtractToStreamCallback) @@ -954,480 +1530,25 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre return ExtractToStreamCallback->GetStream7(name, BoolToInt(_item.IsDir), outStream, askExtractMode, GetProp); } - #endif + #endif // _SFX + CMyComPtr<ISequentialOutStream> outStreamLoc; -if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) -{ - if (_stdOutMode) + if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) { - outStreamLoc = new CStdOutFileStream; - } - else - { - { - NCOM::CPropVariant prop; - RINOK(archive->GetProperty(index, kpidAttrib, &prop)); - if (prop.vt == VT_UI4) - { - _fi.Attrib = prop.ulVal; - _fi.AttribDefined = true; - } - else if (prop.vt == VT_EMPTY) - _fi.AttribDefined = false; - else - return E_FAIL; - } - - RINOK(GetTime(index, kpidCTime, _fi.CTime, _fi.CTimeDefined)); - RINOK(GetTime(index, kpidATime, _fi.ATime, _fi.ATimeDefined)); - RINOK(GetTime(index, kpidMTime, _fi.MTime, _fi.MTimeDefined)); - - bool isAnti = false; - RINOK(_arc->IsItemAnti(index, isAnti)); - - #ifdef SUPPORT_ALT_STREAMS - if (!_item.IsAltStream - || !pathParts.IsEmpty() - || !(_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt)) - #endif - Correct_FsPath(_pathMode == NExtract::NPathMode::kAbsPaths, _keepAndReplaceEmptyDirPrefixes, pathParts, _item.MainIsDir); - - #ifdef SUPPORT_ALT_STREAMS - - if (_item.IsAltStream) - { - UString s (_item.AltStreamName); - Correct_AltStream_Name(s); - bool needColon = true; - - if (pathParts.IsEmpty()) - { - pathParts.AddNew(); - if (_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt) - needColon = false; - } - else if (_pathMode == NExtract::NPathMode::kAbsPaths && - NWildcard::GetNumPrefixParts_if_DrivePath(pathParts) == pathParts.Size()) - pathParts.AddNew(); - - UString &name = pathParts.Back(); - if (needColon) - name += (char)(_ntOptions.ReplaceColonForAltStream ? '_' : ':'); - name += s; - } - - #endif - - UString processedPath (MakePathFromParts(pathParts)); - - if (!isAnti) - { - if (!_item.IsDir) - { - if (!pathParts.IsEmpty()) - pathParts.DeleteBack(); - } - - if (!pathParts.IsEmpty()) - { - FString fullPathNew; - CreateComplexDirectory(pathParts, fullPathNew); - - if (_item.IsDir) - { - CDirPathTime &pt = _extractedFolders.AddNew(); - - pt.CTime = _fi.CTime; - pt.CTimeDefined = (WriteCTime && _fi.CTimeDefined); - - pt.ATime = _fi.ATime; - pt.ATimeDefined = (WriteATime && _fi.ATimeDefined); - - pt.MTimeDefined = false; - - if (WriteMTime) - { - if (_fi.MTimeDefined) - { - pt.MTime = _fi.MTime; - pt.MTimeDefined = true; - } - else if (_arc->MTimeDefined) - { - pt.MTime = _arc->MTime; - pt.MTimeDefined = true; - } - } - - pt.Path = fullPathNew; - - pt.SetDirTime(); - } - } - } - - - FString fullProcessedPath (us2fs(processedPath)); - if (_pathMode != NExtract::NPathMode::kAbsPaths - || !NName::IsAbsolutePath(processedPath)) - { - fullProcessedPath = MakePath_from_2_Parts(_dirPathPrefix, fullProcessedPath); - } - - #ifdef SUPPORT_ALT_STREAMS - - if (_item.IsAltStream && _item.ParentIndex != (UInt32)(Int32)-1) - { - int renIndex = _renamedFiles.FindInSorted(CIndexToPathPair(_item.ParentIndex)); - if (renIndex >= 0) - { - const CIndexToPathPair &pair = _renamedFiles[renIndex]; - fullProcessedPath = pair.Path; - fullProcessedPath += ':'; - UString s (_item.AltStreamName); - Correct_AltStream_Name(s); - fullProcessedPath += us2fs(s); - } - } - - #endif - - bool isRenamed = false; - - if (_item.IsDir) + if (_stdOutMode) + outStreamLoc = new CStdOutFileStream; + else { - _diskFilePath = fullProcessedPath; - if (isAnti) - RemoveDir(_diskFilePath); - #ifdef SUPPORT_LINKS - if (linkPath.IsEmpty()) - #endif + bool needExit = true; + RINOK(GetExtractStream(outStreamLoc, needExit)); + if (needExit) return S_OK; } - else if (!_isSplit) - { - - // ----- Is file (not split) ----- - NFind::CFileInfo fileInfo; - if (fileInfo.Find(fullProcessedPath)) - { - switch (_overwriteMode) - { - case NExtract::NOverwriteMode::kSkip: - return S_OK; - case NExtract::NOverwriteMode::kAsk: - { - int slashPos = fullProcessedPath.ReverseFind_PathSepar(); - FString realFullProcessedPath (fullProcessedPath.Left(slashPos + 1) + fileInfo.Name); - - Int32 overwriteResult; - RINOK(_extractCallback2->AskOverwrite( - fs2us(realFullProcessedPath), &fileInfo.MTime, &fileInfo.Size, _item.Path, - _fi.MTimeDefined ? &_fi.MTime : NULL, - _curSizeDefined ? &_curSize : NULL, - &overwriteResult)) - - switch (overwriteResult) - { - case NOverwriteAnswer::kCancel: return E_ABORT; - case NOverwriteAnswer::kNo: return S_OK; - case NOverwriteAnswer::kNoToAll: _overwriteMode = NExtract::NOverwriteMode::kSkip; return S_OK; - case NOverwriteAnswer::kYes: break; - case NOverwriteAnswer::kYesToAll: _overwriteMode = NExtract::NOverwriteMode::kOverwrite; break; - case NOverwriteAnswer::kAutoRename: _overwriteMode = NExtract::NOverwriteMode::kRename; break; - default: - return E_FAIL; - } - } - } - if (_overwriteMode == NExtract::NOverwriteMode::kRename) - { - if (!AutoRenamePath(fullProcessedPath)) - { - RINOK(SendMessageError(kCantAutoRename, fullProcessedPath)); - return E_FAIL; - } - isRenamed = true; - } - else if (_overwriteMode == NExtract::NOverwriteMode::kRenameExisting) - { - FString existPath (fullProcessedPath); - if (!AutoRenamePath(existPath)) - { - RINOK(SendMessageError(kCantAutoRename, fullProcessedPath)); - return E_FAIL; - } - // MyMoveFile can raname folders. So it's OK to use it for folders too - if (!MyMoveFile(fullProcessedPath, existPath)) - { - RINOK(SendMessageError2(kCantRenameFile, existPath, fullProcessedPath)); - return E_FAIL; - } - } - else - { - if (fileInfo.IsDir()) - { - // do we need to delete all files in folder? - if (!RemoveDir(fullProcessedPath)) - { - RINOK(SendMessageError_with_LastError(kCantDeleteOutputDir, fullProcessedPath)); - return S_OK; - } - } - else - { - bool needDelete = true; - if (needDelete) - { - if (NFind::DoesFileExist(fullProcessedPath)) - if (!DeleteFileAlways(fullProcessedPath)) - if (GetLastError() != ERROR_FILE_NOT_FOUND) - { - RINOK(SendMessageError_with_LastError(kCantDeleteOutputFile, fullProcessedPath)); - return S_OK; - // return E_FAIL; - } - } - } - } - } - else // not Find(fullProcessedPath) - { - // we need to clear READ-ONLY of parent before creating alt stream - #if defined(_WIN32) && !defined(UNDER_CE) - int colonPos = NName::FindAltStreamColon(fullProcessedPath); - if (colonPos >= 0 && fullProcessedPath[(unsigned)colonPos + 1] != 0) - { - FString parentFsPath (fullProcessedPath); - parentFsPath.DeleteFrom(colonPos); - NFind::CFileInfo parentFi; - if (parentFi.Find(parentFsPath)) - { - if (parentFi.IsReadOnly()) - SetFileAttrib(parentFsPath, parentFi.Attrib & ~FILE_ATTRIBUTE_READONLY); - } - } - #endif - } - // ----- END of code for Is file (not split) ----- - - } - _diskFilePath = fullProcessedPath; - - - if (!isAnti) - { - #ifdef SUPPORT_LINKS - - if (!linkPath.IsEmpty()) - { - #ifndef UNDER_CE - - UString relatPath; - if (isRelative) - relatPath = GetDirPrefixOf(_item.Path); - relatPath += linkPath; - - if (!IsSafePath(relatPath)) - { - RINOK(SendMessageError("Dangerous link path was ignored", us2fs(relatPath))); - } - else - { - FString existPath; - if (isHardLink /* || isCopyLink */ || !isRelative) - { - if (!NName::GetFullPath(_dirPathPrefix_Full, us2fs(relatPath), existPath)) - { - RINOK(SendMessageError("Incorrect path", us2fs(relatPath))); - } - } - else - { - existPath = us2fs(linkPath); - } - - if (!existPath.IsEmpty()) - { - if (isHardLink /* || isCopyLink */) - { - // if (isHardLink) - { - if (!MyCreateHardLink(fullProcessedPath, existPath)) - { - RINOK(SendMessageError2(kCantCreateHardLink, fullProcessedPath, existPath)); - // return S_OK; - } - } - /* - else - { - NFind::CFileInfo fi; - if (!fi.Find(existPath)) - { - RINOK(SendMessageError2("Can not find the file for copying", existPath, fullProcessedPath)); - } - else - { - if (_curSizeDefined && _curSize == fi.Size) - _CopyFile_Path = existPath; - else - { - RINOK(SendMessageError2("File size collision for file copying", existPath, fullProcessedPath)); - } - - // RINOK(MyCopyFile(existPath, fullProcessedPath)); - } - } - */ - } - else if (_ntOptions.SymLinks.Val) - { - // bool isSymLink = true; // = false for junction - if (_item.IsDir && !isRelative) - { - // if it's before Vista we use Junction Point - // isJunction = true; - // convertToAbs = true; - } - - CByteBuffer data; - if (FillLinkData(data, fs2us(existPath), !isJunction)) - { - CReparseAttr attr; - DWORD errorCode = 0; - if (!attr.Parse(data, data.Size(), errorCode)) - { - RINOK(SendMessageError("Internal error for symbolic link file", us2fs(_item.Path))); - // return E_FAIL; - } - else - if (!NFile::NIO::SetReparseData(fullProcessedPath, _item.IsDir, data, (DWORD)data.Size())) - { - RINOK(SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath)); - } - } - } - } - } - - #endif - } - - if (linkPath.IsEmpty() /* || !_CopyFile_Path.IsEmpty() */) - #endif // SUPPORT_LINKS - { - bool needWriteFile = true; - - #ifdef SUPPORT_LINKS - if (!_hardLinks.IDs.IsEmpty() && !_item.IsAltStream) - { - CHardLinkNode h; - bool defined; - RINOK(Archive_Get_HardLinkNode(archive, index, h, defined)); - if (defined) - { - { - int linkIndex = _hardLinks.IDs.FindInSorted2(h); - if (linkIndex >= 0) - { - FString &hl = _hardLinks.Links[linkIndex]; - if (hl.IsEmpty()) - hl = fullProcessedPath; - else - { - if (!MyCreateHardLink(fullProcessedPath, hl)) - { - RINOK(SendMessageError2(kCantCreateHardLink, fullProcessedPath, hl)); - return S_OK; - } - needWriteFile = false; - } - } - } - } - } - #endif - - if (needWriteFile) - { - _outFileStreamSpec = new COutFileStream; - CMyComPtr<ISequentialOutStream> outStreamLoc2(_outFileStreamSpec); - if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS)) - { - // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) - { - RINOK(SendMessageError_with_LastError(kCantOpenOutFile, fullProcessedPath)); - return S_OK; - } - } - - if (_ntOptions.PreAllocateOutFile && !_isSplit && _curSizeDefined && _curSize > (1 << 12)) - { - // UInt64 ticks = GetCpuTicks(); - bool res = _outFileStreamSpec->File.SetLength(_curSize); - _fileLengthWasSet = res; - - // ticks = GetCpuTicks() - ticks; - // printf("\nticks = %10d\n", (unsigned)ticks); - if (!res) - { - RINOK(SendMessageError_with_LastError(kCantSetFileLen, fullProcessedPath)); - } - - /* - _outFileStreamSpec->File.Close(); - ticks = GetCpuTicks() - ticks; - printf("\nticks = %10d\n", (unsigned)ticks); - return S_FALSE; - */ - - /* - File.SetLength() on FAT (xp64): is fast, but then File.Close() can be slow, - if we don't write any data. - File.SetLength() for remote share file (exFAT) can be slow in some cases, - and the Windows can return "network error" after 1 minute, - while remote file still can grow. - We need some way to detect such bad cases and disable PreAllocateOutFile mode. - */ - - res = _outFileStreamSpec->File.SeekToBegin(); - if (!res) - { - RINOK(SendMessageError_with_LastError("Can not seek to begin of file", fullProcessedPath)); - } - } - - #ifdef SUPPORT_ALT_STREAMS - if (isRenamed && !_item.IsAltStream) - { - CIndexToPathPair pair(index, fullProcessedPath); - unsigned oldSize = _renamedFiles.Size(); - unsigned insertIndex = _renamedFiles.AddToUniqueSorted(pair); - if (oldSize == _renamedFiles.Size()) - _renamedFiles[insertIndex].Path = fullProcessedPath; - } - #endif - - if (_isSplit) - { - RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL)); - } - - _outFileStream = outStreamLoc2; - } - } - } - - outStreamLoc = _outFileStream; } -} #ifndef _SFX - if (_hashStream) { if (askExtractMode == NArchive::NExtract::NAskMode::kExtract || @@ -1439,28 +1560,22 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) _hashStreamWasUsed = true; } } + #endif // _SFX - #endif - - if (outStreamLoc) { /* #ifdef SUPPORT_LINKS - if (!_CopyFile_Path.IsEmpty()) { RINOK(PrepareOperation(askExtractMode)); RINOK(MyCopyFile(outStreamLoc)); return SetOperationResult(NArchive::NExtract::NOperationResult::kOK); } - - if (isCopyLink && _testMode) + if (_link.isCopyLink && _testMode) return S_OK; - #endif */ - *outStream = outStreamLoc.Detach(); } @@ -1470,6 +1585,15 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) } + + + + + + + + + STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { COM_TRY_BEGIN @@ -1498,33 +1622,352 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) } + + + HRESULT CArchiveExtractCallback::CloseFile() { if (!_outFileStream) return S_OK; HRESULT hres = S_OK; - _outFileStreamSpec->SetTime( - (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL, - (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL, - (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL)); const UInt64 processedSize = _outFileStreamSpec->ProcessedSize; - if (_fileLengthWasSet && _curSize > processedSize) + if (_fileLengthWasSet && _fileLength_that_WasSet > processedSize) { bool res = _outFileStreamSpec->File.SetLength(processedSize); _fileLengthWasSet = res; if (!res) - hres = SendMessageError_with_LastError(kCantSetFileLen, us2fs(_item.Path)); + { + HRESULT hres2 = SendMessageError_with_LastError(kCantSetFileLen, us2fs(_item.Path)); + if (hres == S_OK) + hres = hres2; + } } + _curSize = processedSize; _curSizeDefined = true; + + // #ifdef _WIN32 + _outFileStreamSpec->SetTime( + (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL, + (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL, + (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL)); + // #endif + RINOK(_outFileStreamSpec->Close()); _outFileStream.Release(); return hres; } +#ifdef SUPPORT_LINKS + + +HRESULT CArchiveExtractCallback::SetFromLinkPath( + const FString &fullProcessedPath, + const CLinkInfo &linkInfo, + bool &linkWasSet) +{ + linkWasSet = false; + if (!_ntOptions.SymLinks.Val && !linkInfo.isHardLink) + return S_OK; + + UString relatPath; + + /* if (linkInfo.isRelative) + linkInfo.linkPath is final link path that must be stored to file link field + else + linkInfo.linkPath is path from root of archive. So we must add _dirPathPrefix_Full before linkPath. + */ + + if (linkInfo.isRelative) + relatPath = GetDirPrefixOf(_item.Path); + relatPath += linkInfo.linkPath; + + if (!IsSafePath(relatPath)) + { + return SendMessageError2( + 0, // errorCode + "Dangerous link path was ignored", + us2fs(_item.Path), + us2fs(linkInfo.linkPath)); // us2fs(relatPath) + } + + FString existPath; + if (linkInfo.isHardLink /* || linkInfo.IsCopyLink */ || !linkInfo.isRelative) + { + if (!NName::GetFullPath(_dirPathPrefix_Full, us2fs(relatPath), existPath)) + { + RINOK(SendMessageError("Incorrect path", us2fs(relatPath))); + } + } + else + { + existPath = us2fs(linkInfo.linkPath); + // printf("\nlinkPath = : %s\n", GetOemString(linkInfo.linkPath).Ptr()); + } + + if (existPath.IsEmpty()) + return SendMessageError("Empty link", fullProcessedPath); + + if (linkInfo.isHardLink /* || linkInfo.IsCopyLink */) + { + // if (linkInfo.isHardLink) + { + if (!MyCreateHardLink(fullProcessedPath, existPath)) + { + HRESULT errorCode = GetLastError_noZero_HRESULT(); + RINOK(SendMessageError2(errorCode, kCantCreateHardLink, fullProcessedPath, existPath)); + } + linkWasSet = true; + return S_OK; + } + /* + // IsCopyLink + { + NFind::CFileInfo fi; + if (!fi.Find(existPath)) + { + RINOK(SendMessageError2("Cannot find the file for copying", existPath, fullProcessedPath)); + } + else + { + if (_curSizeDefined && _curSize == fi.Size) + _CopyFile_Path = existPath; + else + { + RINOK(SendMessageError2("File size collision for file copying", existPath, fullProcessedPath)); + } + // RINOK(MyCopyFile(existPath, fullProcessedPath)); + } + } + */ + } + + // is Symbolic link + + /* + if (_item.IsDir && !isRelative) + { + // Windows before Vista doesn't support symbolic links. + // we could convert such symbolic links to Junction Points + // isJunction = true; + // convertToAbs = true; + } + */ + + if (!_ntOptions.SymLinks_AllowDangerous.Val) + { + #ifdef _WIN32 + if (_item.IsDir) + #endif + if (linkInfo.isRelative) + { + CLinkLevelsInfo levelsInfo; + levelsInfo.Parse(linkInfo.linkPath); + if (levelsInfo.FinalLevel < 1 || levelsInfo.IsAbsolute) + { + return SendMessageError2( + 0, // errorCode + "Dangerous symbolic link path was ignored", + us2fs(_item.Path), + us2fs(linkInfo.linkPath)); + } + } + } + + + #ifdef _WIN32 + + CByteBuffer data; + // printf("\nFillLinkData(): %s\n", GetOemString(existPath).Ptr()); + if (!FillLinkData(data, fs2us(existPath), !linkInfo.isJunction, linkInfo.isWSL)) + return SendMessageError("Cannot fill link data", us2fs(_item.Path)); + + /* + if (NtReparse_Size != data.Size() || memcmp(NtReparse_Data, data, data.Size()) != 0) + { + SendMessageError("reconstructed Reparse is different", fs2us(existPath)); + } + */ + + CReparseAttr attr; + if (!attr.Parse(data, data.Size())) + { + RINOK(SendMessageError("Internal error for symbolic link file", us2fs(_item.Path))); + return S_OK; + } + if (!NFile::NIO::SetReparseData(fullProcessedPath, _item.IsDir, data, (DWORD)data.Size())) + { + RINOK(SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath)); + return S_OK; + } + linkWasSet = true; + + return S_OK; + + + #else // ! _WIN32 + + if (!NFile::NIO::SetSymLink(fullProcessedPath, existPath)) + { + RINOK(SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath)); + return S_OK; + } + linkWasSet = true; + + return S_OK; + + #endif // ! _WIN32 +} + + +bool CLinkInfo::Parse(const Byte *data, size_t dataSize, bool isLinuxData) +{ + // this->isLinux = isLinuxData; + + if (isLinuxData) + { + isJunction = false; + isHardLink = false; + AString utf; + if (dataSize >= (1 << 12)) + return false; + utf.SetFrom_CalcLen((const char *)data, (unsigned)dataSize); + UString u; + if (!ConvertUTF8ToUnicode(utf, u)) + return false; + linkPath = u; + + // in linux symbolic data: we expect that linux separator '/' is used + // if windows link was created, then we also must use linux separator + if (u.IsEmpty()) + return false; + wchar_t c = u[0]; + isRelative = !IS_PATH_SEPAR(c); + return true; + } + + CReparseAttr reparse; + if (!reparse.Parse(data, dataSize)) + return false; + isHardLink = false; + // isCopyLink = false; + linkPath = reparse.GetPath(); + isJunction = reparse.IsMountPoint(); + + if (reparse.IsSymLink_WSL()) + { + isWSL = true; + isRelative = reparse.IsRelative_WSL(); + } + else + isRelative = reparse.IsRelative_Win(); + + // FIXME !!! + #ifndef _WIN32 + linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); + #endif + + return true; +} + +#endif // SUPPORT_LINKS + + +HRESULT CArchiveExtractCallback::CloseReparseAndFile() +{ + HRESULT res = S_OK; + + #ifdef SUPPORT_LINKS + + size_t reparseSize = 0; + bool repraseMode = false; + bool needSetReparse = false; + CLinkInfo linkInfo; + + if (_bufPtrSeqOutStream) + { + repraseMode = true; + reparseSize = _bufPtrSeqOutStream_Spec->GetPos(); + if (_curSizeDefined && reparseSize == _outMemBuf.Size()) + { + /* + CReparseAttr reparse; + DWORD errorCode = 0; + needSetReparse = reparse.Parse(_outMemBuf, reparseSize, errorCode); + if (needSetReparse) + { + UString linkPath = reparse.GetPath(); + #ifndef _WIN32 + linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); + #endif + } + */ + needSetReparse = linkInfo.Parse(_outMemBuf, reparseSize, _is_SymLink_in_Data_Linux); + if (!needSetReparse) + res = SendMessageError_with_LastError("Incorrect reparse stream", us2fs(_item.Path)); + } + else + { + res = SendMessageError_with_LastError("Unknown reparse stream", us2fs(_item.Path)); + } + if (!needSetReparse && _outFileStream) + { + HRESULT res2 = WriteStream(_outFileStream, _outMemBuf, reparseSize); + if (res == S_OK) + res = res2; + } + _bufPtrSeqOutStream.Release(); + } + + #endif // SUPPORT_LINKS + + + HRESULT res2 = CloseFile(); + + if (res == S_OK) + res = res2; + + RINOK(res); + + #ifdef SUPPORT_LINKS + if (repraseMode) + { + _curSize = reparseSize; + _curSizeDefined = true; + + #ifdef SUPPORT_LINKS + if (needSetReparse) + { + // in Linux : we must delete empty file before symbolic link creation + // in Windows : we can create symbolic link even without file deleting + if (!DeleteFileAlways(_diskFilePath)) + { + RINOK(SendMessageError_with_LastError("can't delete file", _diskFilePath)); + } + { + bool linkWasSet = false; + RINOK(SetFromLinkPath(_diskFilePath, linkInfo, linkWasSet)); + if (!linkWasSet) + _fileWasExtracted = false; + } + /* + if (!NFile::NIO::SetReparseData(_diskFilePath, _item.IsDir, )) + { + res = SendMessageError_with_LastError(kCantCreateSymLink, _diskFilePath); + } + */ + } + #endif + } + #endif + return res; +} + + + STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes) { COM_TRY_BEGIN @@ -1551,9 +1994,9 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes) _hashStreamWasUsed = false; } - #endif + #endif // _SFX - RINOK(CloseFile()); + RINOK(CloseReparseAndFile()); #ifdef _USE_SECURITY_CODE if (!_stdOutMode && _extractMode && _ntOptions.NtSecurity.Val && _arc->GetRawProps) @@ -1571,11 +2014,11 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes) SECURITY_INFORMATION securInfo = DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION; if (_saclEnabled) securInfo |= SACL_SECURITY_INFORMATION; - ::SetFileSecurityW(fs2us(_diskFilePath), securInfo, (PSECURITY_DESCRIPTOR)(void *)data); + ::SetFileSecurityW(fs2us(_diskFilePath), securInfo, (PSECURITY_DESCRIPTOR)(void *)(const Byte *)(data)); } } } - #endif + #endif // _USE_SECURITY_CODE if (!_curSizeDefined) GetUnpackSize(); @@ -1599,8 +2042,16 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes) else NumFiles++; + if (_fileWasExtracted) if (!_stdOutMode && _extractMode && _fi.AttribDefined) - SetFileAttrib_PosixHighDetect(_diskFilePath, _fi.Attrib); + { + bool res = SetFileAttrib_PosixHighDetect(_diskFilePath, _fi.Attrib); + if (!res) + { + // do we need error message here in Windows and in posix? + SendMessageError_with_LastError("Cannot set file attribute", _diskFilePath); + } + } RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted))); @@ -1609,6 +2060,8 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes) COM_TRY_END } + + STDMETHODIMP CArchiveExtractCallback::ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes) { if (_folderArchiveExtractCallback2) @@ -1666,7 +2119,7 @@ void CDirPathSortPair::SetNumSlashes(const FChar *s) } -bool CDirPathTime::SetDirTime() +bool CDirPathTime::SetDirTime() const { return NDir::SetDirTime(Path, CTimeDefined ? &CTime : NULL, @@ -1693,20 +2146,44 @@ HRESULT CArchiveExtractCallback::SetDirsTimes() pairs.Sort2(); + HRESULT res = S_OK; + for (i = 0; i < pairs.Size(); i++) { - _extractedFolders[pairs[i].Index].SetDirTime(); - // if (!) return GetLastError(); + const CDirPathTime &dpt = _extractedFolders[pairs[i].Index]; + if (!dpt.SetDirTime()) + { + // result = E_FAIL; + // do we need error message here in Windows and in posix? + // SendMessageError_with_LastError("Cannot set directory time", dpt.Path); + } } + /* + #ifndef _WIN32 + for (i = 0; i < _delayedSymLinks.Size(); i++) + { + const CDelayedSymLink &link = _delayedSymLinks[i]; + if (!link.Create()) + { + if (res == S_OK) + res = GetLastError_noZero_HRESULT(); + // res = E_FAIL; + // do we need error message here in Windows and in posix? + SendMessageError_with_LastError("Cannot create Symbolic Link", link._source); + } + } + #endif // _WIN32 + */ + ClearExtractedDirsInfo(); - return S_OK; + return res; } HRESULT CArchiveExtractCallback::CloseArc() { - HRESULT res = CloseFile(); + HRESULT res = CloseReparseAndFile(); HRESULT res2 = SetDirsTimes(); if (res == S_OK) res = res2; diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h index dd5c98c0..25eb6444 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h @@ -4,12 +4,14 @@ #define __ARCHIVE_EXTRACT_CALLBACK_H #include "../../../Common/MyCom.h" +#include "../../../Common/MyLinux.h" #include "../../../Common/Wildcard.h" #include "../../IPassword.h" #include "../../Common/FileStreams.h" #include "../../Common/ProgressUtils.h" +#include "../../Common/StreamObjects.h" #include "../../Archive/IArchive.h" @@ -52,6 +54,7 @@ struct CExtractNtOptions { CBoolPair NtSecurity; CBoolPair SymLinks; + CBoolPair SymLinks_AllowDangerous; CBoolPair HardLinks; CBoolPair AltStreams; bool ReplaceColonForAltStream; @@ -64,9 +67,10 @@ struct CExtractNtOptions WriteToAltStreamIfColon(false) { SymLinks.Val = true; + SymLinks_AllowDangerous.Val = false; HardLinks.Val = true; AltStreams.Val = true; - + PreAllocateOutFile = #ifdef _WIN32 true; @@ -165,9 +169,35 @@ struct CDirPathTime FString Path; - bool SetDirTime(); + bool SetDirTime() const; +}; + + +#ifdef SUPPORT_LINKS + +struct CLinkInfo +{ + // bool isCopyLink; + bool isHardLink; + bool isJunction; + bool isRelative; + bool isWSL; + UString linkPath; + + void Clear() + { + // IsCopyLink = false; + isHardLink = false; + isJunction = false; + isRelative = false; + isWSL = false; + linkPath.Empty(); + } + + bool Parse(const Byte *data, size_t dataSize, bool isLinuxData); }; +#endif // SUPPORT_LINKS class CArchiveExtractCallback: @@ -225,15 +255,53 @@ class CArchiveExtractCallback: bool ATimeDefined; bool MTimeDefined; bool AttribDefined; + + bool IsReparse() const + { + return (AttribDefined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0); + } + + bool IsLinuxSymLink() const + { + return (AttribDefined && MY_LIN_S_ISLNK(Attrib >> 16)); + } + + void SetFromPosixAttrib(UInt32 a) + { + // here we set only part of combined attribute required by SetFileAttrib() call + #ifdef _WIN32 + // Windows sets FILE_ATTRIBUTE_NORMAL, if we try to set 0 as attribute. + Attrib = MY_LIN_S_ISDIR(a) ? + FILE_ATTRIBUTE_DIRECTORY : + FILE_ATTRIBUTE_ARCHIVE; + if ((a & 0222) == 0) // (& S_IWUSR) in p7zip + Attrib |= FILE_ATTRIBUTE_READONLY; + #else + Attrib = (a << 16) | FILE_ATTRIBUTE_UNIX_EXTENSION; + #endif + AttribDefined = true; + } } _fi; + bool _is_SymLink_in_Data; + bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX + + bool _fileWasExtracted; + UInt32 _index; UInt64 _curSize; bool _curSizeDefined; bool _fileLengthWasSet; + UInt64 _fileLength_that_WasSet; + COutFileStream *_outFileStreamSpec; CMyComPtr<ISequentialOutStream> _outFileStream; + CByteBuffer _outMemBuf; + CBufPtrSeqOutStream *_bufPtrSeqOutStream_Spec; + CMyComPtr<ISequentialOutStream> _bufPtrSeqOutStream; + + #ifndef _SFX COutStreamWithHash *_hashStreamSpec; @@ -261,6 +329,10 @@ class CArchiveExtractCallback: bool _progressTotal_Defined; CObjectVector<CDirPathTime> _extractedFolders; + + #ifndef _WIN32 + // CObjectVector<NWindows::NFile::NDir::CDelayedSymLink> _delayedSymLinks; + #endif #if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX) bool _saclEnabled; @@ -272,7 +344,7 @@ class CArchiveExtractCallback: HRESULT SendMessageError(const char *message, const FString &path); HRESULT SendMessageError_with_LastError(const char *message, const FString &path); - HRESULT SendMessageError2(const char *message, const FString &path1, const FString &path2); + HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2); public: @@ -335,10 +407,12 @@ public: private: CHardLinks _hardLinks; - UString linkPath; + CLinkInfo _link; // FString _CopyFile_Path; // HRESULT MyCopyFile(ISequentialOutStream *outStream); + HRESULT Link(const FString &fullProcessedPath); + HRESULT ReadLink(); public: // call PrepareHardLinks() after Init() @@ -367,10 +441,33 @@ private: void ClearExtractedDirsInfo() { _extractedFolders.Clear(); + #ifndef _WIN32 + // _delayedSymLinks.Clear(); + #endif } + HRESULT Read_fi_Props(); + void CorrectPathParts(); + void CreateFolders(); + + bool _isRenamed; + HRESULT CheckExistFile(FString &fullProcessedPath, bool &needExit); + HRESULT GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit); + HRESULT CloseFile(); + HRESULT CloseReparseAndFile(); + HRESULT CloseReparseAndFile2(); HRESULT SetDirsTimes(); + + const void *NtReparse_Data; + UInt32 NtReparse_Size; + + #ifdef SUPPORT_LINKS + HRESULT SetFromLinkPath( + const FString &fullProcessedPath, + const CLinkInfo &linkInfo, + bool &linkWasSet); + #endif }; diff --git a/CPP/7zip/UI/Common/ArchiveName.cpp b/CPP/7zip/UI/Common/ArchiveName.cpp index 9048edce..1baf3e1e 100644 --- a/CPP/7zip/UI/Common/ArchiveName.cpp +++ b/CPP/7zip/UI/Common/ArchiveName.cpp @@ -21,7 +21,7 @@ static UString CreateArchiveName(const NFind::CFileInfo &fi, bool keepName) int dotPos = resultName.ReverseFind_Dot(); if (dotPos > 0) { - FString archiveName2 = resultName.Left(dotPos); + FString archiveName2 = resultName.Left((unsigned)dotPos); if (archiveName2.ReverseFind_Dot() < 0) resultName = archiveName2; } @@ -64,7 +64,7 @@ static FString CreateArchiveName2(const FString &path, bool fromPrev, bool keepN int dotPos = resultName.ReverseFind_Dot(); if (dotPos > 0) { - FString name2 = resultName.Left(dotPos); + FString name2 = resultName.Left((unsigned)dotPos); if (name2.ReverseFind_Dot() < 0) resultName = name2; } diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp index 4d9d9e14..d3e0d3ce 100644 --- a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp @@ -63,7 +63,7 @@ STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value) struct CInFileStreamVol: public CInFileStream { - int FileNameIndex; + unsigned FileNameIndex; COpenCallbackImp *OpenCallbackImp; CMyComPtr<IArchiveOpenCallback> OpenCallbackRef; @@ -116,7 +116,7 @@ STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStre FString fullPath; if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name2), fullPath)) return S_FALSE; - if (!_fileInfo.Find(fullPath)) + if (!_fileInfo.Find_FollowLink(fullPath)) return S_FALSE; if (_fileInfo.IsDir()) return S_FALSE; @@ -124,10 +124,7 @@ STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStre CMyComPtr<IInStream> inStreamTemp = inFile; if (!inFile->Open(fullPath)) { - DWORD lastError = ::GetLastError(); - if (lastError == 0) - return E_FAIL; - return HRESULT_FROM_WIN32(lastError); + return GetLastError_noZero_HRESULT(); } FileSizes.Add(_fileInfo.Size); diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/CPP/7zip/UI/Common/ArchiveOpenCallback.h index e9575f56..46b26768 100644 --- a/CPP/7zip/UI/Common/ArchiveOpenCallback.h +++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.h @@ -6,6 +6,7 @@ #include "../../../Common/MyCom.h" #include "../../../Windows/FileFind.h" +#include "../../../Windows/FileIO.h" #ifndef _NO_CRYPTO #include "../../IPassword.h" @@ -88,24 +89,28 @@ public: CMyComPtr<IArchiveOpenCallback> ReOpenCallback; // UInt64 TotalSize; - COpenCallbackImp(): Callback(NULL), _subArchiveMode(false) {} + COpenCallbackImp(): _subArchiveMode(false), Callback(NULL) {} - void Init(const FString &folderPrefix, const FString &fileName) + HRESULT Init2(const FString &folderPrefix, const FString &fileName) { - _folderPrefix = folderPrefix; - if (!_fileInfo.Find(_folderPrefix + fileName)) - throw 20121118; FileNames.Clear(); FileNames_WasUsed.Clear(); FileSizes.Clear(); _subArchiveMode = false; // TotalSize = 0; PasswordWasAsked = false; + _folderPrefix = folderPrefix; + if (!_fileInfo.Find_FollowLink(_folderPrefix + fileName)) + { + // throw 20121118; + return GetLastError_noZero_HRESULT(); + } + return S_OK; } bool SetSecondFileInfo(CFSTR newName) { - return _fileInfo.Find(newName) && !_fileInfo.IsDir(); + return _fileInfo.Find_FollowLink(newName) && !_fileInfo.IsDir(); } }; diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp index f849a877..4e957331 100644 --- a/CPP/7zip/UI/Common/Bench.cpp +++ b/CPP/7zip/UI/Common/Bench.cpp @@ -2,19 +2,24 @@ #include "StdAfx.h" -#include <stdio.h> +#include "../../../../C/CpuArch.h" + +// #include <stdio.h> #ifndef _WIN32 + #define USE_POSIX_TIME #define USE_POSIX_TIME2 -#endif +#endif // _WIN32 #ifdef USE_POSIX_TIME #include <time.h> +#include <unistd.h> #ifdef USE_POSIX_TIME2 #include <sys/time.h> +#include <sys/times.h> #endif -#endif +#endif // USE_POSIX_TIME #ifdef _WIN32 #define USE_ALLOCA @@ -29,21 +34,16 @@ #endif #include "../../../../C/7zCrc.h" -#include "../../../../C/CpuArch.h" +#include "../../../../C/RotateDefs.h" #ifndef _7ZIP_ST #include "../../../Windows/Synchronization.h" #include "../../../Windows/Thread.h" #endif -#if defined(_WIN32) || defined(UNIX_USE_WIN_FILE) -#define USE_WIN_FILE -#endif - -#ifdef USE_WIN_FILE #include "../../../Windows/FileIO.h" -#endif - +#include "../../../Windows/FileFind.h" +#include "../../../Windows/SystemInfo.h" #include "../../../Common/IntToString.h" #include "../../../Common/MyBuffer2.h" @@ -57,7 +57,9 @@ using namespace NWindows; +#ifndef _7ZIP_ST static const UInt32 k_LZMA = 0x030101; +#endif static const UInt64 kComplexInCommands = (UInt64)1 << #ifdef UNDER_CE @@ -66,9 +68,9 @@ static const UInt64 kComplexInCommands = (UInt64)1 << 34; #endif -static const UInt32 kComplexInSeconds = 4; +static const UInt32 kComplexInMs = 4000; -static void SetComplexCommands(UInt32 complexInSeconds, +static void SetComplexCommandsMs(UInt32 complexInMs, bool isSpecifiedFreq, UInt64 cpuFreq, UInt64 &complexInCommands) { complexInCommands = kComplexInCommands; @@ -78,15 +80,15 @@ static void SetComplexCommands(UInt32 complexInSeconds, cpuFreq = kMinFreq; if (cpuFreq < kMaxFreq || isSpecifiedFreq) { - if (complexInSeconds != 0) - complexInCommands = complexInSeconds * cpuFreq; + if (complexInMs != 0) + complexInCommands = complexInMs * cpuFreq / 1000; else complexInCommands = cpuFreq >> 2; } } static const unsigned kNumHashDictBits = 17; -static const UInt32 kFilterUnpackSize = (48 << 10); +static const UInt32 kFilterUnpackSize = (47 << 10); // + 5; // for test static const unsigned kOldLzmaDictBits = 30; @@ -97,8 +99,8 @@ static const UInt32 kMaxLzmaPropSize = 5; #define ALLOC_WITH_HRESULT(_buffer_, _size_) \ - (_buffer_)->Alloc(_size_); \ - if (!(_buffer_)->IsAllocated()) return E_OUTOFMEMORY; + { (_buffer_)->Alloc(_size_); \ + if (!(_buffer_)->IsAllocated()) return E_OUTOFMEMORY; } class CBaseRandomGenerator @@ -109,6 +111,7 @@ class CBaseRandomGenerator public: CBaseRandomGenerator(UInt32 salt = 0): Salt(salt) { Init(); } void Init() { A1 = 362436069; A2 = 521288629;} + MY_FORCE_INLINE UInt32 GetRnd() { return Salt ^ @@ -120,6 +123,26 @@ public: }; +MY_NO_INLINE +static void RandGen(Byte *buf, size_t size) +{ + CBaseRandomGenerator RG; + const size_t size4 = size & ~((size_t)3); + size_t i; + for (i = 0; i < size4; i += 4) + { + const UInt32 v = RG.GetRnd(); + SetUi32(buf + i, v); + } + UInt32 v = RG.GetRnd(); + for (; i < size; i++) + { + buf[i] = (Byte)v; + v >>= 8; + } +} + + class CBenchRandomGenerator: public CAlignedBuffer { static UInt32 GetVal(UInt32 &res, unsigned numBits) @@ -218,6 +241,7 @@ class CBenchmarkInStream: const Byte *Data; size_t Pos; size_t Size; + public: MY_UNKNOWN_IMP void Init(const Byte *data, size_t size) @@ -226,19 +250,22 @@ public: Size = size; Pos = 0; } + bool WasFinished() const { return Pos == Size; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { - size_t remain = Size - Pos; - UInt32 kMaxBlockSize = (1 << 20); + const UInt32 kMaxBlockSize = (1 << 20); if (size > kMaxBlockSize) size = kMaxBlockSize; + const size_t remain = Size - Pos; if (size > remain) size = (UInt32)remain; - for (UInt32 i = 0; i < size; i++) - ((Byte *)data)[i] = Data[Pos + i]; + + if (size != 0) + memcpy(data, Data + Pos, size); + Pos += size; if (processedSize) *processedSize = size; @@ -267,6 +294,16 @@ public: Pos = 0; } + void InitCrc() + { + Crc = CRC_INIT_VAL; + } + + void Calc(const void *data, size_t size) + { + Crc = CrcUpdate(Crc, data, size); + } + // void Print() { printf("\n%8d %8d\n", (unsigned)BufferSize, (unsigned)Pos); } MY_UNKNOWN_IMP @@ -283,7 +320,7 @@ STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *p if (RealCopy) memcpy(((Byte *)*this) + Pos, data, curSize); if (CalcCrc) - Crc = CrcUpdate(Crc, data, curSize); + Calc(data, curSize); Pos += curSize; } if (processedSize) @@ -296,6 +333,7 @@ STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *p return S_OK; } + class CCrcOutStream: public ISequentialOutStream, public CMyUnknownImp @@ -303,39 +341,46 @@ class CCrcOutStream: public: bool CalcCrc; UInt32 Crc; + UInt64 Pos; + MY_UNKNOWN_IMP CCrcOutStream(): CalcCrc(true) {}; - void Init() { Crc = CRC_INIT_VAL; } + void Init() { Crc = CRC_INIT_VAL; Pos = 0; } + void Calc(const void *data, size_t size) + { + Crc = CrcUpdate(Crc, data, size); + } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (CalcCrc) - Crc = CrcUpdate(Crc, data, size); + Calc(data, size); + Pos += size; if (processedSize) *processedSize = size; return S_OK; } +// #include "../../../../C/My_sys_time.h" + static UInt64 GetTimeCount() { #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 timeval v; if (gettimeofday(&v, 0) == 0) - return (UInt64)(v.tv_sec) * 1000000 + v.tv_usec; + return (UInt64)(v.tv_sec) * 1000000 + (UInt64)v.tv_usec; return (UInt64)time(NULL) * 1000000; #else return time(NULL); #endif #else - /* LARGE_INTEGER value; if (::QueryPerformanceCounter(&value)) - return value.QuadPart; - */ + return (UInt64)value.QuadPart; return GetTickCount(); #endif } @@ -349,15 +394,14 @@ static UInt64 GetFreq() return 1; #endif #else - /* LARGE_INTEGER value; if (::QueryPerformanceFrequency(&value)) - return value.QuadPart; - */ + return (UInt64)value.QuadPart; return 1000; #endif } + #ifdef USE_POSIX_TIME struct CUserTime @@ -367,50 +411,98 @@ struct CUserTime void Init() { - Prev = clock(); + // Prev = clock(); + Sum = 0; + Prev = 0; + Update(); Sum = 0; } - UInt64 GetUserTime() + void Update() { + tms t; + /* clock_t res = */ times(&t); + clock_t newVal = t.tms_utime + t.tms_stime; + Sum += (UInt64)(newVal - Prev); + Prev = newVal; + + /* clock_t v = clock(); - Sum += v - Prev; - Prev = v; + if (v != -1) + { + Sum += v - Prev; + Prev = v; + } + */ + } + UInt64 GetUserTime() + { + Update(); return Sum; } }; #else -static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } -UInt64 GetWinUserTime() -{ - FILETIME creationTime, exitTime, kernelTime, userTime; - if ( - #ifdef UNDER_CE - ::GetThreadTimes(::GetCurrentThread() - #else - ::GetProcessTimes(::GetCurrentProcess() - #endif - , &creationTime, &exitTime, &kernelTime, &userTime) != 0) - return GetTime64(userTime) + GetTime64(kernelTime); - return (UInt64)GetTickCount() * 10000; -} struct CUserTime { - UInt64 StartTime; + bool UseTick; + DWORD Prev_Tick; + UInt64 Prev; + UInt64 Sum; - void Init() { StartTime = GetWinUserTime(); } - UInt64 GetUserTime() { return GetWinUserTime() - StartTime; } + void Init() + { + UseTick = false; + Prev_Tick = 0; + Prev = 0; + Sum = 0; + Update(); + Sum = 0; + } + UInt64 GetUserTime() + { + Update(); + return Sum; + } + void Update(); }; +static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } + +void CUserTime::Update() +{ + DWORD new_Tick = GetTickCount(); + FILETIME creationTime, exitTime, kernelTime, userTime; + if (!UseTick && + #ifdef UNDER_CE + ::GetThreadTimes(::GetCurrentThread() + #else + ::GetProcessTimes(::GetCurrentProcess() + #endif + , &creationTime, &exitTime, &kernelTime, &userTime)) + { + UInt64 newVal = GetTime64(userTime) + GetTime64(kernelTime); + Sum += newVal - Prev; + Prev = newVal; + } + else + { + UseTick = true; + Sum += (UInt64)(new_Tick - (DWORD)Prev_Tick) * 10000; + } + Prev_Tick = new_Tick; +} + + #endif static UInt64 GetUserFreq() { #ifdef USE_POSIX_TIME - return CLOCKS_PER_SEC; + // return CLOCKS_PER_SEC; + return (UInt64)sysconf(_SC_CLK_TCK); #else return 10000000; #endif @@ -551,7 +643,10 @@ UInt64 CBenchInfo::GetRatingPerUsage(UInt64 rating) const if (globalFreq == 0) globalFreq = 1; if (userTime == 0) - userTime = 1; + { + return 0; + // userTime = 1; + } return userFreq * globalTime / globalFreq * rating / userTime; } @@ -577,11 +672,20 @@ struct CBenchProps UInt32 DecComplexCompr; UInt32 DecComplexUnc; - CBenchProps(): LzmaRatingMode(false) {} + unsigned KeySize; + + CBenchProps(): + LzmaRatingMode(false), + KeySize(0) + {} + void SetLzmaCompexity(); UInt64 GeComprCommands(UInt64 unpackSize) { + const UInt32 kMinSize = 100; + if (unpackSize < kMinSize) + unpackSize = kMinSize; return unpackSize * EncComplex; } @@ -637,9 +741,133 @@ UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt } +#ifndef _7ZIP_ST + +#define NUM_CPU_LEVELS_MAX 3 + +struct CAffinityMode +{ + unsigned NumBundleThreads; + unsigned NumLevels; + unsigned NumCoreThreads; + unsigned NumCores; + // unsigned DivideNum; + UInt32 Sizes[NUM_CPU_LEVELS_MAX]; + + void SetLevels(unsigned numCores, unsigned numCoreThreads); + DWORD_PTR GetAffinityMask(UInt32 bundleIndex, CCpuSet *cpuSet) const; + bool NeedAffinity() const { return NumBundleThreads != 0; } + + WRes CreateThread_WithAffinity(NWindows::CThread &thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter, UInt32 bundleIndex) const + { + if (NeedAffinity()) + { + CCpuSet cpuSet; + GetAffinityMask(bundleIndex, &cpuSet); + return thread.Create_With_CpuSet(startAddress, parameter, &cpuSet); + } + return thread.Create(startAddress, parameter); + } + + CAffinityMode(): + NumBundleThreads(0), + NumLevels(0), + NumCoreThreads(1) + // DivideNum(1) + {} +}; + +void CAffinityMode::SetLevels(unsigned numCores, unsigned numCoreThreads) +{ + NumCores = numCores; + NumCoreThreads = numCoreThreads; + NumLevels = 0; + if (numCoreThreads == 0 || numCores == 0 || numCores % numCoreThreads != 0) + return; + UInt32 c = numCores / numCoreThreads; + UInt32 c2 = 1; + while ((c & 1) == 0) + { + c >>= 1; + c2 <<= 1; + } + if (c2 != 1) + Sizes[NumLevels++] = c2; + if (c != 1) + Sizes[NumLevels++] = c; + if (numCoreThreads != 1) + Sizes[NumLevels++] = numCoreThreads; + if (NumLevels == 0) + Sizes[NumLevels++] = 1; + + /* + printf("\n Cores:"); + for (unsigned i = 0; i < NumLevels; i++) + { + printf(" %d", Sizes[i]); + } + printf("\n"); + */ +} + + +DWORD_PTR CAffinityMode::GetAffinityMask(UInt32 bundleIndex, CCpuSet *cpuSet) const +{ + CpuSet_Zero(cpuSet); + + if (NumLevels == 0) + return 0; + + // printf("\n%2d", bundleIndex); + + /* + UInt32 low = 0; + if (DivideNum != 1) + { + low = bundleIndex % DivideNum; + bundleIndex /= DivideNum; + } + */ + + UInt32 numGroups = NumCores / NumBundleThreads; + UInt32 m = bundleIndex % numGroups; + UInt32 v = 0; + for (unsigned i = 0; i < NumLevels; i++) + { + UInt32 size = Sizes[i]; + while ((size & 1) == 0) + { + v *= 2; + v |= (m & 1); + m >>= 1; + size >>= 1; + } + v *= size; + v += m % size; + m /= size; + } + + // UInt32 nb = NumBundleThreads / DivideNum; + UInt32 nb = NumBundleThreads; + + DWORD_PTR mask = ((DWORD_PTR)1 << nb) - 1; + // v += low; + mask <<= v; + + // printf(" %2d %8x \n ", v, (unsigned)mask); + #ifdef _WIN32 + *cpuSet = mask; + #else + { + for (unsigned k = 0; k < nb; k++) + CpuSet_Set(cpuSet, v + k); + } + #endif + + return mask; +} -#ifndef _7ZIP_ST struct CBenchSyncCommon { bool ExitMode; @@ -647,9 +875,11 @@ struct CBenchSyncCommon CBenchSyncCommon(): ExitMode(false) {} }; + #endif + struct CEncoderInfo; struct CEncoderInfo @@ -659,6 +889,9 @@ struct CEncoderInfo NSynchronization::CManualResetEvent ReadyEvent; UInt32 NumDecoderSubThreads; CBenchSyncCommon *Common; + UInt32 EncoderIndex; + UInt32 NumEncoderInternalThreads; + CAffinityMode AffinityMode; #endif CMyComPtr<ICompressCoder> _encoder; @@ -673,9 +906,18 @@ struct CEncoderInfo size_t AllocaSize; #endif + unsigned KeySize; Byte _key[32]; Byte _iv[16]; + + HRESULT Set_Key_and_IV(ICryptoProperties *cp) + { + RINOK(cp->SetKey(_key, KeySize)); + return cp->SetInitVector(_iv, sizeof(_iv)); + } + Byte _psw[16]; + bool CheckCrc_Enc; bool CheckCrc_Dec; @@ -726,10 +968,15 @@ struct CEncoderInfo Common(NULL), #endif Salt(0), - fileData(NULL), + KeySize(0), CheckCrc_Enc(true), CheckCrc_Dec(true), - outStreamSpec(NULL), callback(NULL), printCallback(NULL), propStreamSpec(NULL) {} + outStreamSpec(NULL), + callback(NULL), + printCallback(NULL), + fileData(NULL), + propStreamSpec(NULL) + {} #ifndef _7ZIP_ST @@ -775,7 +1022,8 @@ struct CEncoderInfo if (!ReadyEvent.IsCreated()) res = ReadyEvent.Create(); if (res == 0) - res = thread[0].Create(EncodeThreadFunction, this); + res = AffinityMode.CreateThread_WithAffinity(thread[0], EncodeThreadFunction, this, + EncoderIndex); return HRESULT_FROM_WIN32(res); } @@ -794,7 +1042,13 @@ struct CEncoderInfo #endif decoder.CallbackMode = callbackMode; - return thread[index].Create(DecodeThreadFunction, &decoder); + + WRes res = AffinityMode.CreateThread_WithAffinity(thread[index], DecodeThreadFunction, &decoder, + // EncoderIndex * NumEncoderInternalThreads + index + EncoderIndex + ); + + return HRESULT_FROM_WIN32(res); } #endif @@ -864,8 +1118,23 @@ HRESULT CEncoderInfo::Generate() coder.QueryInterface(IID_ICompressSetCoderProperties, &scp); if (scp) { - UInt64 reduceSize = kBufferSize; - RINOK(method.SetCoderProps(scp, &reduceSize)); + const UInt64 reduceSize = kBufferSize; + + /* in posix new thread uses same affinity as parent thread, + so we don't need to send affinity to coder in posix */ + UInt64 affMask; + #if !defined(_7ZIP_ST) && defined(_WIN32) + { + CCpuSet cpuSet; + affMask = AffinityMode.GetAffinityMask(EncoderIndex, &cpuSet); + } + #else + affMask = 0; + #endif + // affMask <<= 3; // debug line: to test no affinity in coder; + // affMask = 0; + + RINOK(method.SetCoderProps_DSReduce_Aff(scp, &reduceSize, (affMask != 0 ? &affMask : NULL))); } else { @@ -971,52 +1240,100 @@ HRESULT CEncoderInfo::Encode() coder.QueryInterface(IID_ICryptoProperties, &cp); CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr<ISequentialInStream> inStream = inStreamSpec; - UInt64 prev = 0; - - UInt32 crcPrev = 0; if (cp) { - RINOK(cp->SetKey(_key, sizeof(_key))); - RINOK(cp->SetInitVector(_iv, sizeof(_iv))); + RINOK(Set_Key_and_IV(cp)); } - for (UInt64 i = 0; i < NumIterations; i++) + compressedSize = 0; + if (_encoderFilter) + compressedSize = kBufferSize; + + // CBenchmarkOutStream *outStreamSpec = this->outStreamSpec; + UInt64 prev = 0; + const UInt32 mask = (CheckCrc_Enc ? 0 : 0xFFF); + bool useCrc = (mask < NumIterations); + bool crcPrev_defined = false; + UInt32 crcPrev = 0; + UInt64 i = NumIterations; + // printCallback->NewLine(); + + while (i != 0) { - if (printCallback && bi.UnpackSize - prev > (1 << 20)) + i--; + if (printCallback && bi.UnpackSize - prev >= (1 << 24)) { RINOK(printCallback->CheckBreak()); prev = bi.UnpackSize; } + + /* + CBenchInfo info; + progressInfoSpec[0]->SetStartTime(); + */ - bool isLast = (i == NumIterations - 1); - bool calcCrc = ((isLast || (i & 0x7F) == 0 || CheckCrc_Enc) && NumIterations != 1); - outStreamSpec->Init(isLast, calcCrc); - + bool calcCrc = false; + if (useCrc) + calcCrc = (((UInt32)i & mask) == 0); + if (_encoderFilter) { - memcpy((Byte *)rgCopy, uncompressedDataPtr, kBufferSize); + // if (needRealData) + memcpy((Byte *)*outStreamSpec, uncompressedDataPtr, kBufferSize); _encoderFilter->Init(); - My_FilterBench(_encoderFilter, (Byte *)rgCopy, kBufferSize); - RINOK(WriteStream(outStream, (const Byte *)rgCopy, kBufferSize)); + My_FilterBench(_encoderFilter, (Byte *)*outStreamSpec, kBufferSize); + if (calcCrc) + { + outStreamSpec->InitCrc(); + outStreamSpec->Calc((Byte *)*outStreamSpec, kBufferSize); + } } else { + outStreamSpec->Init(true, calcCrc); // write real data for speed consistency at any number of iterations inStreamSpec->Init(uncompressedDataPtr, kBufferSize); RINOK(_encoder->Code(inStream, outStream, NULL, NULL, progressInfo[0])); + if (!inStreamSpec->WasFinished()) + return E_FAIL; + if (compressedSize != outStreamSpec->Pos) + { + if (compressedSize != 0) + return E_FAIL; + compressedSize = outStreamSpec->Pos; + } } // outStreamSpec->Print(); - UInt32 crcNew = CRC_GET_DIGEST(outStreamSpec->Crc); - if (i == 0) - crcPrev = crcNew; - else if (calcCrc && crcPrev != crcNew) - return E_FAIL; + if (calcCrc) + { + const UInt32 crc2 = CRC_GET_DIGEST(outStreamSpec->Crc); + if (crcPrev_defined && crcPrev != crc2) + return E_FAIL; + crcPrev = crc2; + crcPrev_defined = true; + } - compressedSize = outStreamSpec->Pos; bi.UnpackSize += kBufferSize; bi.PackSize += compressedSize; + + /* + { + progressInfoSpec[0]->SetFinishTime(info); + info.UnpackSize = 0; + info.PackSize = 0; + info.NumIterations = 1; + + info.UnpackSize = kBufferSize; + info.PackSize = compressedSize; + // printf("\n%7d\n", encoder.compressedSize); + + RINOK(callback->SetEncodeResult(info, true)); + printCallback->NewLine(); + } + */ + } _encoder.Release(); @@ -1067,7 +1384,7 @@ HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) coder.QueryInterface(IID_ICompressSetCoderProperties, &scp); if (scp) { - UInt64 reduceSize = _uncompressedDataSize; + const UInt64 reduceSize = _uncompressedDataSize; RINOK(_method.SetCoderProps(scp, &reduceSize)); } @@ -1092,40 +1409,84 @@ HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) if (cp) { - RINOK(cp->SetKey(_key, sizeof(_key))); - RINOK(cp->SetInitVector(_iv, sizeof(_iv))); + RINOK(Set_Key_and_IV(cp)); } - for (UInt64 i = 0; i < NumIterations; i++) + CMyComPtr<ICompressSetFinishMode> setFinishMode; + + if (_decoderFilter) { - if (printCallback && pi->BenchInfo.UnpackSize - prev > (1 << 20)) + if (compressedSize > rgCopy.Size()) + return E_FAIL; + } + else + { + decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode); + } + + const UInt64 numIterations = this->NumIterations; + const UInt32 mask = (CheckCrc_Dec ? 0 : 0xFFF); + + for (UInt64 i = 0; i < numIterations; i++) + { + if (printCallback && pi->BenchInfo.UnpackSize - prev >= (1 << 24)) { RINOK(printCallback->CheckBreak()); prev = pi->BenchInfo.UnpackSize; } - inStreamSpec->Init((const Byte *)*outStreamSpec, compressedSize); + const UInt64 outSize = kBufferSize; + bool calcCrc = false; + if (((UInt32)i & mask) == 0) + calcCrc = true; crcOutStreamSpec->Init(); - UInt64 outSize = kBufferSize; - crcOutStreamSpec->CalcCrc = ((i & 0x7F) == 0 || CheckCrc_Dec); - if (_decoderFilter) { - if (compressedSize > rgCopy.Size()) - return E_FAIL; + if (calcCrc) // for pure filter speed test without multi-iteration consistency + // if (needRealData) memcpy((Byte *)rgCopy, (const Byte *)*outStreamSpec, compressedSize); _decoderFilter->Init(); My_FilterBench(_decoderFilter, (Byte *)rgCopy, compressedSize); - RINOK(WriteStream(crcOutStream, (const Byte *)rgCopy, compressedSize)); + if (calcCrc) + crcOutStreamSpec->Calc((const Byte *)rgCopy, compressedSize); } else { + crcOutStreamSpec->CalcCrc = calcCrc; + inStreamSpec->Init((const Byte *)*outStreamSpec, compressedSize); + + if (setFinishMode) + { + RINOK(setFinishMode->SetFinishMode(BoolToUInt(true))); + } + RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex])); + + if (setFinishMode) + { + if (!inStreamSpec->WasFinished()) + return S_FALSE; + + CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize; + decoder.QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize); + + if (getInStreamProcessedSize) + { + UInt64 processed; + RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&processed)); + if (processed != compressedSize) + return S_FALSE; + } + } + + if (crcOutStreamSpec->Pos != outSize) + return S_FALSE; } - if (crcOutStreamSpec->CalcCrc && CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc) + if (calcCrc && CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc) return S_FALSE; + pi->BenchInfo.UnpackSize += kBufferSize; pi->BenchInfo.PackSize += compressedSize; } @@ -1191,10 +1552,8 @@ WRes CBenchThreadsFlusher::StartAndWait(bool exitMode) NWindows::CThread &t = EncodersSpec->encoders[i].thread[0]; if (t.IsCreated()) { - WRes res2 = t.Wait(); - if (res2 == 0) - res2 = t.Close(); - if (res == S_OK) + WRes res2 = t.Wait_Close(); + if (res == 0) res = res2; } } @@ -1202,23 +1561,29 @@ WRes CBenchThreadsFlusher::StartAndWait(bool exitMode) return res; } -#endif +#endif // _7ZIP_ST + + + +static void SetPseudoRand(Byte *data, size_t size, UInt32 startValue) +{ + for (size_t i = 0; i < size; i++) + { + data[i] = (Byte)startValue; + startValue++; + } +} static HRESULT MethodBench( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 complexInCommands, - bool - #ifndef _7ZIP_ST - oldLzmaBenchMode - #endif - , - UInt32 - #ifndef _7ZIP_ST - numThreads - #endif - , + #ifndef _7ZIP_ST + bool oldLzmaBenchMode, + UInt32 numThreads, + const CAffinityMode *affinityMode, + #endif const COneMethodInfo &method2, size_t uncompressedDataSize, const Byte *fileData, @@ -1231,7 +1596,7 @@ static HRESULT MethodBench( COneMethodInfo method = method2; UInt64 methodId; UInt32 numStreams; - int codecIndex = FindMethod_Index( + const int codecIndex = FindMethod_Index( EXTERNAL_CODECS_LOC_VARS method.MethodName, true, methodId, numStreams); @@ -1246,19 +1611,21 @@ static HRESULT MethodBench( #ifndef _7ZIP_ST numEncoderThreads = numThreads; - if (oldLzmaBenchMode && methodId == k_LZMA) + if (oldLzmaBenchMode) + if (methodId == k_LZMA) { if (numThreads == 1 && method.Get_NumThreads() < 0) method.AddProp_NumThreads(1); const UInt32 numLzmaThreads = method.Get_Lzma_NumThreads(); if (numThreads > 1 && numLzmaThreads > 1) { - numEncoderThreads = numThreads / 2; + numEncoderThreads = (numThreads + 1) / 2; // 20.03 numSubDecoderThreads = 2; } } - bool mtEncMode = (numEncoderThreads > 1); + bool mtEncMode = (numEncoderThreads > 1) || affinityMode->NeedAffinity(); + #endif CBenchEncoders encodersSpec(numEncoderThreads); @@ -1272,20 +1639,38 @@ static HRESULT MethodBench( encoder.callback = (i == 0) ? callback : 0; encoder.printCallback = printCallback; + #ifndef _7ZIP_ST + encoder.EncoderIndex = i; + encoder.NumEncoderInternalThreads = numSubDecoderThreads; + encoder.AffinityMode = *affinityMode; + + /* + if (numSubDecoderThreads > 1) + if (encoder.AffinityMode.NeedAffinity() + && encoder.AffinityMode.NumBundleThreads == 1) + { + // if old LZMA benchmark uses two threads in coder, we increase (NumBundleThreads) for old LZMA benchmark uses two threads instead of one + if (encoder.AffinityMode.NumBundleThreads * 2 <= encoder.AffinityMode.NumCores) + encoder.AffinityMode.NumBundleThreads *= 2; + } + */ + + #endif + { CCreatedCoder cod; - RINOK(CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS codecIndex, true, encoder._encoderFilter, cod)); + RINOK(CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS (unsigned)codecIndex, true, encoder._encoderFilter, cod)); encoder._encoder = cod.Coder; if (!encoder._encoder && !encoder._encoderFilter) return E_NOTIMPL; } - encoder.CheckCrc_Enc = (benchProps->EncComplex) > 30 ; - encoder.CheckCrc_Dec = (benchProps->DecComplexCompr + benchProps->DecComplexUnc) > 30 ; + encoder.CheckCrc_Enc = (benchProps->EncComplex) > 30; + encoder.CheckCrc_Dec = (benchProps->DecComplexCompr + benchProps->DecComplexUnc) > 30; - memset(encoder._iv, 0, sizeof(encoder._iv)); - memset(encoder._key, 0, sizeof(encoder._key)); - memset(encoder._psw, 0, sizeof(encoder._psw)); + SetPseudoRand(encoder._iv, sizeof(encoder._iv), 17); + SetPseudoRand(encoder._key, sizeof(encoder._key), 51); + SetPseudoRand(encoder._psw, sizeof(encoder._psw), 123); for (UInt32 j = 0; j < numSubDecoderThreads; j++) { @@ -1334,11 +1719,14 @@ static HRESULT MethodBench( { CEncoderInfo &encoder = encoders[i]; encoder.NumIterations = GetNumIterations(benchProps->GeComprCommands(uncompressedDataSize), complexInCommands); + // encoder.NumIterations = 3; encoder.Salt = g_CrcTable[i & 0xFF]; encoder.Salt ^= (g_CrcTable[(i >> 8) & 0xFF] << 3); // (g_CrcTable[0] == 0), and (encoder.Salt == 0) for first thread // printf(" %8x", encoder.Salt); + encoder.KeySize = benchProps->KeySize; + for (int j = 0; j < 2; j++) { CBenchProgressInfo *spec = new CBenchProgressInfo; @@ -1424,12 +1812,24 @@ static HRESULT MethodBench( status.Res = S_OK; status.EncodeMode = false; - UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads; + const UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads; + #ifndef _7ZIP_ST + const bool mtDecoderMode = (numDecoderThreads > 1) || affinityMode->NeedAffinity(); + #endif for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; + /* + #ifndef _7ZIP_ST + // encoder.affinityMode = *affinityMode; + if (encoder.NumEncoderInternalThreads != 1) + encoder.AffinityMode.DivideNum = encoder.NumEncoderInternalThreads; + #endif + */ + + if (i == 0) { encoder.NumIterations = GetNumIterations(benchProps->GeDecomprCommands(encoder.compressedSize, encoder.kBufferSize), complexInCommands); @@ -1444,9 +1844,9 @@ static HRESULT MethodBench( #ifndef _7ZIP_ST { int numSubThreads = method.Get_NumThreads(); - encoder.NumDecoderSubThreads = (numSubThreads <= 0) ? 1 : numSubThreads; + encoder.NumDecoderSubThreads = (numSubThreads <= 0) ? 1 : (unsigned)numSubThreads; } - if (numDecoderThreads > 1) + if (mtDecoderMode) { for (UInt32 j = 0; j < numSubDecoderThreads; j++) { @@ -1466,25 +1866,36 @@ static HRESULT MethodBench( } #ifndef _7ZIP_ST - HRESULT res = S_OK; - if (numDecoderThreads > 1) + if (mtDecoderMode) + { + WRes wres = 0; + HRESULT res = S_OK; for (i = 0; i < numEncoderThreads; i++) for (UInt32 j = 0; j < numSubDecoderThreads; j++) { CEncoderInfo &encoder = encoders[i]; - encoder.thread[j].Wait(); - if (encoder.Results[j] != S_OK) - res = encoder.Results[j]; + WRes wres2 = encoder.thread[j]. + // Wait(); // later we can get thread times from thread in UNDER_CE + Wait_Close(); + if (wres == 0 && wres2 != 0) + wres = wres2; + HRESULT res2 = encoder.Results[j]; + if (res == 0 && res2 != 0) + res = res2; } - RINOK(res); - #endif - + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + RINOK(res); + } + #endif // _7ZIP_ST + RINOK(status.Res); encoders[0].progressInfoSpec[0]->SetFinishTime(info); - + + /* #ifndef _7ZIP_ST #ifdef UNDER_CE - if (numDecoderThreads > 1) + if (mtDecoderMode) for (i = 0; i < numEncoderThreads; i++) for (UInt32 j = 0; j < numSubDecoderThreads; j++) { @@ -1494,6 +1905,7 @@ static HRESULT MethodBench( } #endif #endif + */ info.UnpackSize = 0; info.PackSize = 0; @@ -1541,37 +1953,112 @@ UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary, bool totalBench GetLZMAUsage(lzmaMt, dictionary) + (2 << 20)) * numBigThreads; } -static HRESULT CrcBig(const void *data, UInt32 size, UInt64 numIterations, + + +// ---------- CRC and HASH ---------- + +struct CCrcInfo_Base +{ + CAlignedBuffer Buffer; + const Byte *Data; + size_t Size; + bool CreateLocalBuf; + UInt32 CheckSum_Res; + + CCrcInfo_Base(): CreateLocalBuf(true), CheckSum_Res(0) {} + + HRESULT Generate(const Byte *data, size_t size); + HRESULT CrcProcess(UInt64 numIterations, + const UInt32 *checkSum, IHasher *hf, + IBenchPrintCallback *callback); +}; + + +HRESULT CCrcInfo_Base::Generate(const Byte *data, size_t size) +{ + Size = size; + Data = data; + if (!data || CreateLocalBuf) + { + ALLOC_WITH_HRESULT(&Buffer, size) + Data = Buffer; + } + if (!data) + RandGen(Buffer, size); + else if (CreateLocalBuf && size != 0) + memcpy(Buffer, data, size); + return S_OK; +} + + +HRESULT CCrcInfo_Base::CrcProcess(UInt64 numIterations, const UInt32 *checkSum, IHasher *hf, IBenchPrintCallback *callback) { + MY_ALIGN(16) Byte hash[64]; - UInt64 i; - for (i = 0; i < sizeof(hash); i++) - hash[i] = 0; - for (i = 0; i < numIterations; i++) + memset(hash, 0, sizeof(hash)); + + CheckSum_Res = 0; + + const UInt32 hashSize = hf->GetDigestSize(); + if (hashSize > sizeof(hash)) + return S_FALSE; + + const Byte *buf = Data; + const size_t size = Size; + UInt32 checkSum_Prev = 0; + + UInt64 prev = 0; + UInt64 cur = 0; + + for (UInt64 i = 0; i < numIterations; i++) { - if (callback && (i & 0xFF) == 0) + hf->Init(); + size_t pos = 0; + do { - RINOK(callback->CheckBreak()); + const size_t rem = size - pos; + const UInt32 kStep = ((UInt32)1 << 31); + const UInt32 curSize = (rem < kStep) ? (UInt32)rem : kStep; + hf->Update(buf + pos, curSize); + pos += curSize; } - hf->Init(); - hf->Update(data, size); + while (pos != size); + hf->Final(hash); - UInt32 hashSize = hf->GetDigestSize(); - if (hashSize > sizeof(hash)) - return S_FALSE; UInt32 sum = 0; for (UInt32 j = 0; j < hashSize; j += 4) - sum ^= GetUi32(hash + j); - if (checkSum && sum != *checkSum) { - return S_FALSE; + sum = rotlFixed(sum, 11); + sum += GetUi32(hash + j); + } + if (checkSum) + { + if (sum != *checkSum) + return S_FALSE; + } + else + { + checkSum_Prev = sum; + checkSum = &checkSum_Prev; + } + if (callback) + { + cur += size; + if (cur - prev >= ((UInt32)1 << 30)) + { + prev = cur; + RINOK(callback->CheckBreak()); + } } } + CheckSum_Res = checkSum_Prev; return S_OK; } +extern +UInt32 g_BenchCpuFreqTemp; // we need non-static variavble to disable compiler optimization UInt32 g_BenchCpuFreqTemp = 1; #define YY1 sum += val; sum ^= val; @@ -1596,22 +2083,27 @@ EXTERN_C_END #ifndef _7ZIP_ST -struct CFreqInfo +struct CBaseThreadInfo { NWindows::CThread Thread; IBenchPrintCallback *Callback; HRESULT CallbackRes; - UInt32 ValRes; - UInt32 Size; - UInt64 NumIterations; - void Wait() + WRes Wait_If_Created() { - Thread.Wait(); - Thread.Close(); + if (!Thread.IsCreated()) + return 0; + return Thread.Wait_Close(); } }; +struct CFreqInfo: public CBaseThreadInfo +{ + UInt32 ValRes; + UInt32 Size; + UInt64 NumIterations; +}; + static THREAD_FUNC_DECL FreqThreadFunction(void *param) { CFreqInfo *p = (CFreqInfo *)param; @@ -1634,12 +2126,20 @@ struct CFreqThreads UInt32 NumThreads; CFreqThreads(): Items(NULL), NumThreads(0) {} - void WaitAll() + + WRes WaitAll() { + WRes wres = 0; for (UInt32 i = 0; i < NumThreads; i++) - Items[i].Wait(); + { + WRes wres2 = Items[i].Wait_If_Created(); + if (wres == 0 && wres2 != 0) + wres = wres2; + } NumThreads = 0; + return wres; } + ~CFreqThreads() { WaitAll(); @@ -1647,30 +2147,95 @@ struct CFreqThreads } }; -struct CCrcInfo -{ - NWindows::CThread Thread; - IBenchPrintCallback *Callback; - HRESULT CallbackRes; +static THREAD_FUNC_DECL CrcThreadFunction(void *param); + +struct CCrcInfo: public CBaseThreadInfo +{ const Byte *Data; - UInt32 Size; + size_t Size; UInt64 NumIterations; bool CheckSumDefined; UInt32 CheckSum; CMyComPtr<IHasher> Hasher; HRESULT Res; + UInt32 CheckSum_Res; + + #ifndef _7ZIP_ST + NSynchronization::CManualResetEvent ReadyEvent; + UInt32 ThreadIndex; + CBenchSyncCommon *Common; + CAffinityMode AffinityMode; + #endif + + // we want to call CCrcInfo_Base::Buffer.Free() in main thread. + // so we uses non-local CCrcInfo_Base. + CCrcInfo_Base crcib; + + HRESULT CreateThread() + { + WRes res = 0; + if (!ReadyEvent.IsCreated()) + res = ReadyEvent.Create(); + if (res == 0) + res = AffinityMode.CreateThread_WithAffinity(Thread, CrcThreadFunction, this, + ThreadIndex); + return HRESULT_FROM_WIN32(res); + } #ifdef USE_ALLOCA size_t AllocaSize; #endif - void Wait() + void Process(); + + CCrcInfo(): Res(E_FAIL) {} +}; + +static const bool k_Crc_CreateLocalBuf_For_File = true; // for total BW test +// static const bool k_Crc_CreateLocalBuf_For_File = false; // for shared memory read test + +void CCrcInfo::Process() +{ + crcib.CreateLocalBuf = k_Crc_CreateLocalBuf_For_File; + // we can use additional Generate() passes to reduce some time effects for new page allocation + // for (unsigned y = 0; y < 10; y++) + Res = crcib.Generate(Data, Size); + + // if (Common) { - Thread.Wait(); - Thread.Close(); + WRes wres = ReadyEvent.Set(); + if (wres != 0) + { + if (Res == 0) + Res = HRESULT_FROM_WIN32(wres); + return; + } + if (Res != 0) + return; + + wres = Common->StartEvent.Lock(); + + if (wres != 0) + { + Res = HRESULT_FROM_WIN32(wres); + return; + } + if (Common->ExitMode) + return; } -}; + + Res = crcib.CrcProcess(NumIterations, + CheckSumDefined ? &CheckSum : NULL, Hasher, + Callback); + CheckSum_Res = crcib.CheckSum_Res; + /* + We don't want to include the time of slow CCrcInfo_Base::Buffer.Free() + to time of benchmark. So we don't free Buffer here + */ + // crcib.Buffer.Free(); +} + static THREAD_FUNC_DECL CrcThreadFunction(void *param) { @@ -1679,34 +2244,52 @@ static THREAD_FUNC_DECL CrcThreadFunction(void *param) #ifdef USE_ALLOCA alloca(p->AllocaSize); #endif - - p->Res = CrcBig(p->Data, p->Size, p->NumIterations, - p->CheckSumDefined ? &p->CheckSum : NULL, p->Hasher, - p->Callback); + p->Process(); return 0; } + struct CCrcThreads { CCrcInfo *Items; - UInt32 NumThreads; + unsigned NumThreads; + CBenchSyncCommon Common; + bool NeedClose; + + CCrcThreads(): Items(NULL), NumThreads(0), NeedClose(false) {} + + WRes StartAndWait(bool exitMode = false); - CCrcThreads(): Items(NULL), NumThreads(0) {} - void WaitAll() - { - for (UInt32 i = 0; i < NumThreads; i++) - Items[i].Wait(); - NumThreads = 0; - } ~CCrcThreads() { - WaitAll(); + StartAndWait(true); delete []Items; } }; + +WRes CCrcThreads::StartAndWait(bool exitMode) +{ + if (!NeedClose) + return 0; + + Common.ExitMode = exitMode; + WRes wres = Common.StartEvent.Set(); + + for (unsigned i = 0; i < NumThreads; i++) + { + WRes wres2 = Items[i].Wait_If_Created(); + if (wres == 0 && wres2 != 0) + wres = wres2; + } + NumThreads = 0; + NeedClose = false; + return wres; +} + #endif + static UInt32 CrcCalc1(const Byte *buf, size_t size) { UInt32 crc = CRC_INIT_VAL;; @@ -1715,19 +2298,15 @@ static UInt32 CrcCalc1(const Byte *buf, size_t size) return CRC_GET_DIGEST(crc); } -static void RandGen(Byte *buf, size_t size, CBaseRandomGenerator &RG) -{ - for (size_t i = 0; i < size; i++) - buf[i] = (Byte)RG.GetRnd(); -} - +/* static UInt32 RandGenCrc(Byte *buf, size_t size, CBaseRandomGenerator &RG) { RandGen(buf, size, RG); return CrcCalc1(buf, size); } +*/ -bool CrcInternalTest() +static bool CrcInternalTest() { CAlignedBuffer buffer; const size_t kBufferSize0 = (1 << 8); @@ -1743,8 +2322,7 @@ bool CrcInternalTest() UInt32 crc1 = CrcCalc1(buf, kBufferSize0); if (crc1 != 0x29058C73) return false; - CBaseRandomGenerator RG; - RandGen(buf + kBufferSize0, kBufferSize1, RG); + RandGen(buf + kBufferSize0, kBufferSize1); for (i = 0; i < kBufferSize0 + kBufferSize1 - kCheckSize; i++) for (unsigned j = 0; j < kCheckSize; j++) if (CrcCalc1(buf + i, j) != CrcCalc(buf + i, j)) @@ -1760,11 +2338,25 @@ struct CBenchMethod UInt32 DecComplexCompr; UInt32 DecComplexUnc; const char *Name; + // unsigned KeySize; }; +// #define USE_SW_CMPLX + +#ifdef USE_SW_CMPLX +#define CMPLX(x) ((x) * 1000) +#else +#define CMPLX(x) (x) +#endif + static const CBenchMethod g_Bench[] = { - { 40, 17, 357, 145, 20, "LZMA:x1" }, + // { 40, 17, 357, 145, 20, "LZMA:x1" }, + // { 20, 18, 360, 145, 20, "LZMA2:x1:mt2" }, + + { 20, 18, 360, 145, 20, "LZMA:x1" }, + { 20, 22, 600, 145, 20, "LZMA:x3" }, + { 80, 24, 1220, 145, 20, "LZMA:x5:mt1" }, { 80, 24, 1220, 145, 20, "LZMA:x5:mt2" }, @@ -1778,14 +2370,42 @@ static const CBenchMethod g_Bench[] = { 10, 19, 815, 122, 122, "BZip2:x5:mt2" }, { 10, 19, 2530, 122, 122, "BZip2:x7" }, + // { 10, 18, 1010, 0, 1150, "PPMDZip:x1" }, { 10, 18, 1010, 0, 1150, "PPMD:x1" }, + // { 10, 22, 1655, 0, 1830, "PPMDZip:x5" }, { 10, 22, 1655, 0, 1830, "PPMD:x5" }, - { 2, 0, 6, 0, 6, "Delta:4" }, + // { 2, 0, 3, 0, 4, "Delta:1" }, + // { 2, 0, 3, 0, 4, "Delta:2" }, + // { 2, 0, 3, 0, 4, "Delta:3" }, + { 2, 0, 3, 0, 4, "Delta:4" }, + // { 2, 0, 3, 0, 4, "Delta:8" }, + // { 2, 0, 3, 0, 4, "Delta:32" }, + { 2, 0, 4, 0, 4, "BCJ" }, + // { 10, 0, 18, 0, 18, "AES128CBC:1" }, + // { 10, 0, 21, 0, 21, "AES192CBC:1" }, { 10, 0, 24, 0, 24, "AES256CBC:1" }, - { 2, 0, 8, 0, 2, "AES256CBC:2" } + + // { 10, 0, 18, 0, 18, "AES128CTR:1" }, + // { 10, 0, 21, 0, 21, "AES192CTR:1" }, + // { 10, 0, 24, 0, 24, "AES256CTR:1" }, + // { 2, 0, CMPLX(6), 0, CMPLX(1), "AES128CBC:2" }, + // { 2, 0, CMPLX(7), 0, CMPLX(1), "AES192CBC:2" }, + { 2, 0, CMPLX(8), 0, CMPLX(1), "AES256CBC:2" }, + + // { 2, 0, CMPLX(1), 0, CMPLX(1), "AES128CTR:2" }, + // { 2, 0, CMPLX(1), 0, CMPLX(1), "AES192CTR:2" }, + // { 2, 0, CMPLX(1), 0, CMPLX(1), "AES256CTR:2" }, + + // { 1, 0, CMPLX(6), 0, CMPLX(1), "AES128CBC:3" }, + // { 1, 0, CMPLX(7), 0, CMPLX(1), "AES192CBC:3" }, + { 1, 0, CMPLX(8), 0, CMPLX(1), "AES256CBC:3" } + + // { 1, 0, CMPLX(1), 0, CMPLX(1), "AES128CTR:3" }, + // { 1, 0, CMPLX(1), 0, CMPLX(1), "AES192CTR:3" }, + // { 1, 0, CMPLX(1), 0, CMPLX(1), "AES256CTR:3" }, }; struct CBenchHash @@ -1796,15 +2416,25 @@ struct CBenchHash const char *Name; }; +// #define ARM_CRC_MUL 100 +#define ARM_CRC_MUL 1 + static const CBenchHash g_Hash[] = { - { 1, 1820, 0x8F8FEDAB, "CRC32:1" }, - { 10, 558, 0x8F8FEDAB, "CRC32:4" }, - { 10, 339, 0x8F8FEDAB, "CRC32:8" }, - { 10, 512, 0xDF1C17CC, "CRC64" }, - { 10, 5100, 0x2D79FF2E, "SHA256" }, - { 10, 2340, 0x4C25132B, "SHA1" }, - { 2, 5500, 0xE084E913, "BLAKE2sp" } + { 1, 1820, 0x21e207bb, "CRC32:1" }, + { 10, 558, 0x21e207bb, "CRC32:4" }, + { 10, 339, 0x21e207bb, "CRC32:8" } , + { 2, 128 *ARM_CRC_MUL, 0x21e207bb, "CRC32:32" }, + { 2, 64 *ARM_CRC_MUL, 0x21e207bb, "CRC32:64" }, + { 10, 512, 0x41b901d1, "CRC64" }, + + { 10, 5100, 0x7913ba03, "SHA256:1" }, + { 2, CMPLX((32 * 4 + 1) * 4 + 4), 0x7913ba03, "SHA256:2" }, + + { 10, 2340, 0xff769021, "SHA1:1" }, + { 2, CMPLX((20 * 6 + 1) * 4 + 4), 0xff769021, "SHA1:2" }, + + { 2, 5500, 0x85189d02, "BLAKE2sp" } }; struct CTotalBenchRes @@ -1842,9 +2472,11 @@ static void PrintNumber(IBenchPrintCallback &f, UInt64 value, unsigned size) unsigned len = (unsigned)strlen(s + startPos); if (size > len) { - startPos -= (size - len); - if (startPos < 0) + size -= len; + if (startPos < size) startPos = 0; + else + startPos -= size; } f.Print(s + startPos); } @@ -1870,7 +2502,10 @@ static void PrintRating(IBenchPrintCallback &f, UInt64 rating, unsigned size) static void PrintPercents(IBenchPrintCallback &f, UInt64 val, UInt64 divider, unsigned size) { - PrintNumber(f, (val * 100 + divider / 2) / divider, size); + UInt64 v = 0; + if (divider != 0) + v = (val * 100 + divider / 2) / divider; + PrintNumber(f, v, size); } static void PrintChars(IBenchPrintCallback &f, char c, unsigned size) @@ -1886,9 +2521,14 @@ static void PrintSpaces(IBenchPrintCallback &f, unsigned size) PrintChars(f, ' ', size); } +static void PrintUsage(IBenchPrintCallback &f, UInt64 usage, unsigned size) +{ + PrintNumber(f, (usage + 5000) / 10000, size); +} + static void PrintResults(IBenchPrintCallback &f, UInt64 usage, UInt64 rpu, UInt64 rating, bool showFreq, UInt64 cpuFreq) { - PrintNumber(f, (usage + 5000) / 10000, kFieldSize_Usage); + PrintUsage(f, usage, kFieldSize_Usage); PrintRating(f, rpu, kFieldSize_RU); PrintRating(f, rating, kFieldSize_Rating); if (showFreq) @@ -1898,8 +2538,10 @@ static void PrintResults(IBenchPrintCallback &f, UInt64 usage, UInt64 rpu, UInt6 else { UInt64 ddd = cpuFreq * usage / 100; + /* if (ddd == 0) ddd = 1; + */ PrintPercents(f, (rating * 10000), ddd, kFieldSize_EU); PrintPercents(f, rating, cpuFreq, kFieldSize_Effec); } @@ -1958,58 +2600,57 @@ AString GetProcessThreadsInfo(const NSystem::CProcessAffinity &ti) { AString s; // s.Add_UInt32(ti.numProcessThreads); - if (ti.processAffinityMask != ti.systemAffinityMask) + unsigned numSysThreads = ti.GetNumSystemThreads(); + if (ti.GetNumProcessThreads() != numSysThreads) { // if (ti.numProcessThreads != ti.numSysThreads) { s += " / "; - s.Add_UInt32(ti.GetNumSystemThreads()); + s.Add_UInt32(numSysThreads); } s += " : "; + #ifdef _WIN32 PrintHex(s, ti.processAffinityMask); s += " / "; PrintHex(s, ti.systemAffinityMask); + #else + unsigned i = (numSysThreads + 3) & ~(unsigned)3; + if (i == 0) + i = 4; + for (; i >= 4; ) + { + i -= 4; + unsigned val = 0; + for (unsigned k = 0; k < 4; k++) + { + const unsigned bit = (ti.IsCpuSet(i + k) ? 1 : 0); + val += (bit << k); + } + PrintHex(s, val); + } + #endif } return s; } -static void PrintSize(AString &s, UInt64 v) -{ - char c = 0; - if ((v & 0x3FF) == 0) { v >>= 10; c = 'K'; - if ((v & 0x3FF) == 0) { v >>= 10; c = 'M'; - if ((v & 0x3FF) == 0) { v >>= 10; c = 'G'; - if ((v & 0x3FF) == 0) { v >>= 10; c = 'T'; - }}}} - else - { - PrintHex(s, v); - return; - } - char temp[32]; - ConvertUInt64ToString(v, temp); - s += temp; - if (c) - s += c; -} - - #ifdef _7ZIP_LARGE_PAGES +#ifdef _WIN32 extern bool g_LargePagesMode; - extern "C" { extern SIZE_T g_LargePageSize; } +#endif void Add_LargePages_String(AString &s) { + #ifdef _WIN32 if (g_LargePagesMode || g_LargePageSize != 0) { s += " (LP-"; - PrintSize(s, g_LargePageSize); + PrintSize_KMGT_Or_Hex(s, g_LargePageSize); #ifdef MY_CPU_X86_OR_AMD64 if (CPU_IsSupported_PageGB()) s += "-1G"; @@ -2018,6 +2659,9 @@ void Add_LargePages_String(AString &s) s += "-NA"; s += ")"; } + #else + s += ""; + #endif } #endif @@ -2140,26 +2784,29 @@ void CBenchCallbackToPrint::NewLine() _file->NewLine(); } -void PrintLeft(IBenchPrintCallback &f, const char *s, unsigned size) +static void PrintLeft(IBenchPrintCallback &f, const char *s, unsigned size) { f.Print(s); - int numSpaces = size - MyStringLen(s); + int numSpaces = (int)size - (int)MyStringLen(s); if (numSpaces > 0) - PrintSpaces(f, numSpaces); + PrintSpaces(f, (unsigned)numSpaces); } -void PrintRight(IBenchPrintCallback &f, const char *s, unsigned size) +static void PrintRight(IBenchPrintCallback &f, const char *s, unsigned size) { - int numSpaces = size - MyStringLen(s); + int numSpaces = (int)size - (int)MyStringLen(s); if (numSpaces > 0) - PrintSpaces(f, numSpaces); + PrintSpaces(f, (unsigned)numSpaces); f.Print(s); } static HRESULT TotalBench( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 complexInCommands, + #ifndef _7ZIP_ST UInt32 numThreads, + const CAffinityMode *affinityMode, + #endif bool forceUnpackSize, size_t unpackSize, const Byte *fileData, @@ -2169,6 +2816,12 @@ static HRESULT TotalBench( { const CBenchMethod &bench = g_Bench[i]; PrintLeft(*callback->_file, bench.Name, kFieldSize_Name); + { + unsigned keySize = 32; + if (IsString1PrefixedByString2(bench.Name, "AES128")) keySize = 16; + else if (IsString1PrefixedByString2(bench.Name, "AES192")) keySize = 24; + callback->BenchProps.KeySize = keySize; + } callback->BenchProps.DecComplexUnc = bench.DecComplexUnc; callback->BenchProps.DecComplexCompr = bench.DecComplexCompr; callback->BenchProps.EncComplex = bench.EncComplex; @@ -2188,7 +2841,10 @@ static HRESULT TotalBench( HRESULT res = MethodBench( EXTERNAL_CODECS_LOC_VARS complexInCommands, - false, numThreads, method, + #ifndef _7ZIP_ST + false, numThreads, affinityMode, + #endif + method, unpackSize2, fileData, bench.DictBits, printCallback, callback, &callback->BenchProps); @@ -2211,20 +2867,38 @@ static HRESULT TotalBench( } -static HRESULT FreqBench( - UInt64 complexInCommands, - UInt32 numThreads, - IBenchPrintCallback *_file, - bool showFreq, - UInt64 specifiedFreq, - UInt64 &cpuFreq, - UInt32 &res) +struct CFreqBench +{ + // in: + UInt64 complexInCommands; + UInt32 numThreads; + bool showFreq; + UInt64 specifiedFreq; + + // out: + UInt64 cpuFreq; + UInt32 res; + + CFreqBench() + {} + + HRESULT FreqBench(IBenchPrintCallback *_file + #ifndef _7ZIP_ST + , const CAffinityMode *affinityMode + #endif + ); +}; + + +HRESULT CFreqBench::FreqBench(IBenchPrintCallback *_file + #ifndef _7ZIP_ST + , const CAffinityMode *affinityMode + #endif + ) { res = 0; cpuFreq = 0; - UInt32 bufferSize = 1 << 20; - UInt32 complexity = kNumFreqCommands; if (numThreads == 0) numThreads = 1; @@ -2232,17 +2906,26 @@ static HRESULT FreqBench( numThreads = 1; #endif - UInt32 bsize = (bufferSize == 0 ? 1 : bufferSize); - UInt64 numIterations = complexInCommands / complexity / bsize; - if (numIterations == 0) + const UInt32 complexity = kNumFreqCommands; + UInt64 numIterations = complexInCommands / complexity; + UInt32 numIterations2 = 1 << 30; + if (numIterations > numIterations2) + numIterations /= numIterations2; + else + { + numIterations2 = (UInt32)numIterations; numIterations = 1; + } CBenchInfoCalc progressInfoSpec; #ifndef _7ZIP_ST - CFreqThreads threads; - if (numThreads > 1) + + bool mtMode = (numThreads > 1) || affinityMode->NeedAffinity(); + + if (mtMode) { + CFreqThreads threads; threads.Items = new CFreqInfo[numThreads]; UInt32 i; for (i = 0; i < numThreads; i++) @@ -2251,16 +2934,22 @@ static HRESULT FreqBench( info.Callback = _file; info.CallbackRes = S_OK; info.NumIterations = numIterations; - info.Size = bufferSize; + info.Size = numIterations2; } progressInfoSpec.SetStartTime(); for (i = 0; i < numThreads; i++) { + // Sleep(10); CFreqInfo &info = threads.Items[i]; - RINOK(info.Thread.Create(FreqThreadFunction, &info)); - threads.NumThreads++; + WRes wres = affinityMode->CreateThread_WithAffinity(info.Thread, FreqThreadFunction, &info, i); + if (info.Thread.IsCreated()) + threads.NumThreads++; + if (wres != 0) + return HRESULT_FROM_WIN32(wres); } - threads.WaitAll(); + WRes wres = threads.WaitAll(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); for (i = 0; i < numThreads; i++) { RINOK(threads.Items[i].CallbackRes); @@ -2273,11 +2962,20 @@ static HRESULT FreqBench( UInt32 sum = g_BenchCpuFreqTemp; for (UInt64 k = numIterations; k > 0; k--) { - RINOK(_file->CheckBreak()); - sum = CountCpuFreq(sum, bufferSize, g_BenchCpuFreqTemp); + sum = CountCpuFreq(sum, numIterations2, g_BenchCpuFreqTemp); + if (_file) + { + RINOK(_file->CheckBreak()); + } } res += sum; } + + if (res == 0x12345678) + if (_file) + { + RINOK(_file->CheckBreak()); + } CBenchInfo info; progressInfoSpec.SetFinishTime(info); @@ -2289,7 +2987,7 @@ static HRESULT FreqBench( if (_file) { { - UInt64 numCommands = (UInt64)numIterations * bufferSize * numThreads * complexity; + UInt64 numCommands = (UInt64)numIterations * numIterations2 * numThreads * complexity; UInt64 rating = info.GetSpeed(numCommands); cpuFreq = rating / numThreads; PrintResults(_file, info, @@ -2308,12 +3006,21 @@ static HRESULT FreqBench( static HRESULT CrcBench( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 complexInCommands, - UInt32 numThreads, UInt32 bufferSize, + UInt32 numThreads, + const size_t bufferSize, + const Byte *fileData, + UInt64 &speed, + UInt64 &usage, + UInt32 complexity, unsigned benchWeight, const UInt32 *checkSum, const COneMethodInfo &method, IBenchPrintCallback *_file, + #ifndef _7ZIP_ST + const CAffinityMode *affinityMode, + #endif + bool showRating, CTotalBenchRes *encodeRes, bool showFreq, UInt64 cpuFreq) { @@ -2332,80 +3039,112 @@ static HRESULT CrcBench( methodName, hashID)) return E_NOTIMPL; + /* + // if will generate random data in each thread, instead of global data CAlignedBuffer buffer; - size_t totalSize = (size_t)bufferSize * numThreads; - if (totalSize / numThreads != bufferSize) - return E_OUTOFMEMORY; - ALLOC_WITH_HRESULT(&buffer, totalSize) + if (!fileData) + { + ALLOC_WITH_HRESULT(&buffer, bufferSize) + RandGen(buffer, bufferSize); + fileData = buffer; + } + */ - Byte *buf = (Byte *)buffer; - CBaseRandomGenerator RG; - UInt32 bsize = (bufferSize == 0 ? 1 : bufferSize); + const size_t bsize = (bufferSize == 0 ? 1 : bufferSize); UInt64 numIterations = complexInCommands * 256 / complexity / bsize; if (numIterations == 0) numIterations = 1; CBenchInfoCalc progressInfoSpec; + CBenchInfo info; #ifndef _7ZIP_ST - CCrcThreads threads; - if (numThreads > 1) + bool mtEncMode = (numThreads > 1) || affinityMode->NeedAffinity(); + + if (mtEncMode) { + CCrcThreads threads; threads.Items = new CCrcInfo[numThreads]; - + { + WRes wres = threads.Common.StartEvent.Create(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + threads.NeedClose = true; + } + UInt32 i; for (i = 0; i < numThreads; i++) { - CCrcInfo &info = threads.Items[i]; + CCrcInfo &ci = threads.Items[i]; AString name; - RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, info.Hasher)); - if (!info.Hasher) + RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, ci.Hasher)); + if (!ci.Hasher) return E_NOTIMPL; CMyComPtr<ICompressSetCoderProperties> scp; - info.Hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp); + ci.Hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp); if (scp) { - UInt64 reduceSize = 1; - RINOK(method.SetCoderProps(scp, &reduceSize)); + RINOK(method.SetCoderProps(scp)); } - Byte *data = buf + (size_t)bufferSize * i; - info.Callback = _file; - info.Data = data; - info.NumIterations = numIterations; - info.Size = bufferSize; - /* info.Crc = */ RandGenCrc(data, bufferSize, RG); - info.CheckSumDefined = false; + ci.Callback = _file; + ci.Data = fileData; + ci.NumIterations = numIterations; + ci.Size = bufferSize; + ci.CheckSumDefined = false; if (checkSum) { - info.CheckSum = *checkSum; - info.CheckSumDefined = (checkSum && (i == 0)); + ci.CheckSum = *checkSum; + ci.CheckSumDefined = true; } #ifdef USE_ALLOCA - info.AllocaSize = (i * 16 * 21) & 0x7FF; + ci.AllocaSize = (i * 16 * 21) & 0x7FF; #endif } - progressInfoSpec.SetStartTime(); + for (i = 0; i < numThreads; i++) + { + CCrcInfo &ci = threads.Items[i]; + ci.ThreadIndex = i; + ci.Common = &threads.Common; + ci.AffinityMode = *affinityMode; + HRESULT hres = ci.CreateThread(); + if (ci.Thread.IsCreated()) + threads.NumThreads++; + if (hres != 0) + return hres; + } for (i = 0; i < numThreads; i++) { - CCrcInfo &info = threads.Items[i]; - RINOK(info.Thread.Create(CrcThreadFunction, &info)); - threads.NumThreads++; + CCrcInfo &ci = threads.Items[i]; + WRes wres = ci.ReadyEvent.Lock(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + RINOK(ci.Res); } - threads.WaitAll(); + + progressInfoSpec.SetStartTime(); + + WRes wres = threads.StartAndWait(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + + progressInfoSpec.SetFinishTime(info); + for (i = 0; i < numThreads; i++) { RINOK(threads.Items[i].Res); + if (i != 0) + if (threads.Items[i].CheckSum_Res != + threads.Items[i - 1].CheckSum_Res) + return S_FALSE; } } else #endif { - /* UInt32 crc = */ RandGenCrc(buf, bufferSize, RG); - progressInfoSpec.SetStartTime(); CMyComPtr<IHasher> hasher; AString name; RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, hasher)); @@ -2415,14 +3154,16 @@ static HRESULT CrcBench( hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp); if (scp) { - UInt64 reduceSize = 1; - RINOK(method.SetCoderProps(scp, &reduceSize)); + RINOK(method.SetCoderProps(scp)); } - RINOK(CrcBig(buf, bufferSize, numIterations, checkSum, hasher, _file)); + CCrcInfo_Base crcib; + crcib.CreateLocalBuf = false; + RINOK(crcib.Generate(fileData, bufferSize)); + progressInfoSpec.SetStartTime(); + RINOK(crcib.CrcProcess(numIterations, checkSum, hasher, _file)); + progressInfoSpec.SetFinishTime(info); } - CBenchInfo info; - progressInfoSpec.SetFinishTime(info); UInt64 unpSize = numIterations * bufferSize; UInt64 unpSizeThreads = unpSize * numThreads; @@ -2432,9 +3173,13 @@ static HRESULT CrcBench( if (_file) { + if (showRating) { - UInt64 numCommands = unpSizeThreads * complexity / 256; - UInt64 rating = info.GetSpeed(numCommands); + UInt64 unpSizeThreads2 = unpSizeThreads; + if (unpSizeThreads2 == 0) + unpSizeThreads2 = numIterations * 1 * numThreads; + const UInt64 numCommands = unpSizeThreads2 * complexity / 256; + const UInt64 rating = info.GetSpeed(numCommands); PrintResults(_file, info, benchWeight, rating, showFreq, cpuFreq, encodeRes); @@ -2443,15 +3188,23 @@ static HRESULT CrcBench( } speed = info.GetSpeed(unpSizeThreads); + usage = info.GetUsage(); return S_OK; } + + static HRESULT TotalBench_Hash( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 complexInCommands, - UInt32 numThreads, UInt32 bufSize, + UInt32 numThreads, + size_t bufSize, + const Byte *fileData, IBenchPrintCallback *printCallback, CBenchCallbackToPrint *callback, + #ifndef _7ZIP_ST + const CAffinityMode *affinityMode, + #endif CTotalBenchRes *encodeRes, bool showFreq, UInt64 cpuFreq) { @@ -2468,15 +3221,22 @@ static HRESULT TotalBench_Hash( propVariant = bench.Name; RINOK(method.ParseMethodFromPROPVARIANT(UString(), propVariant)); - UInt64 speed; + UInt64 speed, usage; + HRESULT res = CrcBench( EXTERNAL_CODECS_LOC_VARS complexInCommands, - numThreads, bufSize, - speed, + numThreads, bufSize, fileData, + speed, usage, bench.Complex, bench.Weight, - &bench.CheckSum, method, - printCallback, encodeRes, showFreq, cpuFreq); + (!fileData && bufSize == (1 << kNumHashDictBits)) ? &bench.CheckSum : NULL, + method, + printCallback, + #ifndef _7ZIP_ST + affinityMode, + #endif + true, // showRating + encodeRes, showFreq, cpuFreq); if (res == E_NOTIMPL) { // callback->Print(" ---"); @@ -2509,14 +3269,6 @@ static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop) prop = result; } -static UInt32 GetNumThreadsNext(unsigned i, UInt32 numThreads) -{ - if (i < 2) - return i + 1; - i -= 1; - UInt32 num = (UInt32)(2 + (i & 1)) << (i >> 1); - return (num <= numThreads) ? num : numThreads; -} static bool AreSameMethodNames(const char *fullName, const char *shortName) { @@ -2524,357 +3276,13 @@ static bool AreSameMethodNames(const char *fullName, const char *shortName) } -#ifdef MY_CPU_X86_OR_AMD64 -static void PrintCpuChars(AString &s, UInt32 v) -{ - for (int j = 0; j < 4; j++) - { - Byte b = (Byte)(v & 0xFF); - v >>= 8; - if (b == 0) - break; - s += (char)b; - } -} -static void x86cpuid_to_String(const Cx86cpuid &c, AString &s) +static void Print_Usage_and_Threads(IBenchPrintCallback &f, UInt64 usage, UInt32 threads) { - s.Empty(); - - UInt32 maxFunc2 = 0; - UInt32 t[3]; - - MyCPUID(0x80000000, &maxFunc2, &t[0], &t[1], &t[2]); - - bool fullNameIsAvail = (maxFunc2 >= 0x80000004); - - if (!fullNameIsAvail) - { - for (int i = 0; i < 3; i++) - PrintCpuChars(s, c.vendor[i]); - } - else - { - for (int i = 0; i < 3; i++) - { - UInt32 d[4] = { 0 }; - MyCPUID(0x80000002 + i, &d[0], &d[1], &d[2], &d[3]); - for (int j = 0; j < 4; j++) - PrintCpuChars(s, d[j]); - } - } - - s.Add_Space_if_NotEmpty(); - { - char temp[32]; - ConvertUInt32ToHex(c.ver, temp); - s += '('; - s += temp; - s += ')'; - } + PrintRequirements(f, "usage:", true, usage, "Benchmark threads: ", threads); } -#endif - - - -static const char * const k_PROCESSOR_ARCHITECTURE[] = -{ - "x86" // "INTEL" - , "MIPS" - , "ALPHA" - , "PPC" - , "SHX" - , "ARM" - , "IA64" - , "ALPHA64" - , "MSIL" - , "x64" // "AMD64" - , "IA32_ON_WIN64" - , "NEUTRAL" - , "ARM64" - , "ARM32_ON_WIN64" -}; - -#define MY__PROCESSOR_ARCHITECTURE_INTEL 0 -#define MY__PROCESSOR_ARCHITECTURE_AMD64 9 - - -#define MY__PROCESSOR_INTEL_PENTIUM 586 -#define MY__PROCESSOR_AMD_X8664 8664 - -/* -static const CUInt32PCharPair k_PROCESSOR[] = -{ - { 2200, "IA64" }, - { 8664, "x64" } -}; - -#define PROCESSOR_INTEL_386 386 -#define PROCESSOR_INTEL_486 486 -#define PROCESSOR_INTEL_PENTIUM 586 -#define PROCESSOR_INTEL_860 860 -#define PROCESSOR_INTEL_IA64 2200 -#define PROCESSOR_AMD_X8664 8664 -#define PROCESSOR_MIPS_R2000 2000 -#define PROCESSOR_MIPS_R3000 3000 -#define PROCESSOR_MIPS_R4000 4000 -#define PROCESSOR_ALPHA_21064 21064 -#define PROCESSOR_PPC_601 601 -#define PROCESSOR_PPC_603 603 -#define PROCESSOR_PPC_604 604 -#define PROCESSOR_PPC_620 620 -#define PROCESSOR_HITACHI_SH3 10003 -#define PROCESSOR_HITACHI_SH3E 10004 -#define PROCESSOR_HITACHI_SH4 10005 -#define PROCESSOR_MOTOROLA_821 821 -#define PROCESSOR_SHx_SH3 103 -#define PROCESSOR_SHx_SH4 104 -#define PROCESSOR_STRONGARM 2577 // 0xA11 -#define PROCESSOR_ARM720 1824 // 0x720 -#define PROCESSOR_ARM820 2080 // 0x820 -#define PROCESSOR_ARM920 2336 // 0x920 -#define PROCESSOR_ARM_7TDMI 70001 -#define PROCESSOR_OPTIL 18767 // 0x494f -*/ - -#ifdef _WIN32 - -static const char * const k_PF[] = -{ - "FP_ERRATA" - , "FP_EMU" - , "CMPXCHG" - , "MMX" - , "PPC_MOVEMEM_64BIT" - , "ALPHA_BYTE" - , "SSE" - , "3DNOW" - , "RDTSC" - , "PAE" - , "SSE2" - , "SSE_DAZ" - , "NX" - , "SSE3" - , "CMPXCHG16B" - , "CMP8XCHG16" - , "CHANNELS" - , "XSAVE" - , "ARM_VFP_32" - , "ARM_NEON" - , "L2AT" - , "VIRT_FIRMWARE" - , "RDWRFSGSBASE" - , "FASTFAIL" - , "ARM_DIVIDE" - , "ARM_64BIT_LOADSTORE_ATOMIC" - , "ARM_EXTERNAL_CACHE" - , "ARM_FMAC" - , "RDRAND" - , "ARM_V8" - , "ARM_V8_CRYPTO" - , "ARM_V8_CRC32" - , "RDTSCP" -}; - -#endif - - - - -static void PrintPage(AString &s, UInt32 v) -{ - if ((v & 0x3FF) == 0) - { - s.Add_UInt32(v >> 10); - s += "K"; - } - else - s.Add_UInt32(v >> 10); -} - -static AString TypeToString2(const char * const table[], unsigned num, UInt32 value) -{ - char sz[16]; - const char *p = NULL; - if (value < num) - p = table[value]; - if (!p) - { - ConvertUInt32ToString(value, sz); - p = sz; - } - return (AString)p; -} - -#ifdef _WIN32 - -static void SysInfo_To_String(AString &s, const SYSTEM_INFO &si) -{ - s += TypeToString2(k_PROCESSOR_ARCHITECTURE, ARRAY_SIZE(k_PROCESSOR_ARCHITECTURE), si.wProcessorArchitecture); - - if (!( si.wProcessorArchitecture == MY__PROCESSOR_ARCHITECTURE_INTEL && si.dwProcessorType == MY__PROCESSOR_INTEL_PENTIUM - || si.wProcessorArchitecture == MY__PROCESSOR_ARCHITECTURE_AMD64 && si.dwProcessorType == MY__PROCESSOR_AMD_X8664)) - { - s += " "; - // s += TypePairToString(k_PROCESSOR, ARRAY_SIZE(k_PROCESSOR), si.dwProcessorType); - s.Add_UInt32(si.dwProcessorType); - } - s += " "; - PrintHex(s, si.wProcessorLevel); - s += "."; - PrintHex(s, si.wProcessorRevision); - if ((UInt64)si.dwActiveProcessorMask + 1 != ((UInt64)1 << si.dwNumberOfProcessors)) - if ((UInt64)si.dwActiveProcessorMask + 1 != 0 || si.dwNumberOfProcessors != sizeof(UInt64) * 8) - { - s += " act:"; - PrintHex(s, si.dwActiveProcessorMask); - } - s += " cpus:"; - s.Add_UInt32(si.dwNumberOfProcessors); - if (si.dwPageSize != 1 << 12) - { - s += " page:"; - PrintPage(s, si.dwPageSize); - } - if (si.dwAllocationGranularity != 1 << 16) - { - s += " gran:"; - PrintPage(s, si.dwAllocationGranularity); - } - s += " "; - - DWORD_PTR minAdd = (DWORD_PTR)si.lpMinimumApplicationAddress; - UInt64 maxSize = (UInt64)(DWORD_PTR)si.lpMaximumApplicationAddress + 1; - const UInt32 kReserveSize = ((UInt32)1 << 16); - if (minAdd != kReserveSize) - { - PrintSize(s, minAdd); - s += "-"; - } - else - { - if ((maxSize & (kReserveSize - 1)) == 0) - maxSize += kReserveSize; - } - PrintSize(s, maxSize); -} - -#ifndef _WIN64 -typedef VOID (WINAPI *Func_GetNativeSystemInfo)(LPSYSTEM_INFO lpSystemInfo); -#endif - -#endif - -void GetSysInfo(AString &s1, AString &s2) -{ - s1.Empty(); - s2.Empty(); - - #ifdef _WIN32 - SYSTEM_INFO si; - GetSystemInfo(&si); - { - SysInfo_To_String(s1, si); - // s += " : "; - } - - #if !defined(_WIN64) && !defined(UNDER_CE) - Func_GetNativeSystemInfo fn_GetNativeSystemInfo = (Func_GetNativeSystemInfo)GetProcAddress( - GetModuleHandleA("kernel32.dll"), "GetNativeSystemInfo"); - if (fn_GetNativeSystemInfo) - { - SYSTEM_INFO si2; - fn_GetNativeSystemInfo(&si2); - // if (memcmp(&si, &si2, sizeof(si)) != 0) - { - // s += " - "; - SysInfo_To_String(s2, si2); - } - } - #endif - #endif -} - - -void GetCpuName(AString &s) -{ - s.Empty(); - - #ifdef MY_CPU_X86_OR_AMD64 - { - Cx86cpuid cpuid; - if (x86cpuid_CheckAndRead(&cpuid)) - { - AString s2; - x86cpuid_to_String(cpuid, s2); - s += s2; - } - else - { - #ifdef MY_CPU_AMD64 - s += "x64"; - #else - s += "x86"; - #endif - } - } - #else - - #ifdef MY_CPU_LE - s += "LE"; - #elif defined(MY_CPU_BE) - s += "BE"; - #endif - - #endif - - #ifdef _7ZIP_LARGE_PAGES - Add_LargePages_String(s); - #endif -} - - -void GetCpuFeatures(AString &s) -{ - s.Empty(); - - #ifdef _WIN32 - const unsigned kNumFeatures_Extra = 32; // we check also for unknown features - const unsigned kNumFeatures = ARRAY_SIZE(k_PF) + kNumFeatures_Extra; - for (unsigned i = 0; i < kNumFeatures; i++) - { - if (IsProcessorFeaturePresent(i)) - { - s.Add_Space_if_NotEmpty(); - s += TypeToString2(k_PF, ARRAY_SIZE(k_PF), i); - } - } - #endif -} - - -#ifdef _WIN32 -#ifndef UNDER_CE - -typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *); - -static BOOL My_RtlGetVersion(OSVERSIONINFOEXW *vi) -{ - HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll"); - if (!ntdll) - return FALSE; - Func_RtlGetVersion func = (Func_RtlGetVersion)GetProcAddress(ntdll, "RtlGetVersion"); - if (!func) - return FALSE; - func(vi); - return TRUE; -} - -#endif -#endif - HRESULT Bench( DECL_EXTERNAL_CODECS_LOC_VARS @@ -2896,22 +3304,41 @@ HRESULT Bench( #ifndef _7ZIP_ST - if (threadsInfo.Get() && threadsInfo.processAffinityMask != 0) + if (threadsInfo.Get() && threadsInfo.GetNumProcessThreads() != 0) numCPUs = threadsInfo.GetNumProcessThreads(); else numCPUs = NSystem::GetNumberOfProcessors(); #endif + + // numCPUs = 24; + /* + { + DWORD_PTR mask = (1 << 0); + DWORD_PTR old = SetThreadAffinityMask(GetCurrentThread(), mask); + old = old; + DWORD_PTR old2 = SetThreadAffinityMask(GetCurrentThread(), mask); + old2 = old2; + return 0; + } + */ bool ramSize_Defined = NSystem::GetRamSize(ramSize); UInt32 numThreadsSpecified = numCPUs; - - UInt32 testTime = kComplexInSeconds; - + bool needSetComplexity = false; + UInt32 testTimeMs = kComplexInMs; + UInt32 startDicLog = 22; + bool startDicLog_Defined = false; UInt64 specifiedFreq = 0; - bool multiThreadTests = false; + UInt64 complexInCommands = kComplexInCommands; + UInt32 numThreads_Start = 1; + + #ifndef _7ZIP_ST + CAffinityMode affinityMode; + #endif + COneMethodInfo method; @@ -2919,6 +3346,25 @@ HRESULT Bench( { unsigned i; + + if (printCallback) + { + for (i = 0; i < props.Size(); i++) + { + const CProperty &property = props[i]; + printCallback->Print(" "); + printCallback->Print(GetAnsiString(property.Name)); + if (!property.Value.IsEmpty()) + { + printCallback->Print("="); + printCallback->Print(GetAnsiString(property.Value)); + } + } + if (!props.IsEmpty()) + printCallback->NewLine(); + } + + for (i = 0; i < props.Size(); i++) { const CProperty &property = props[i]; @@ -2930,34 +3376,35 @@ HRESULT Bench( if (property.Value.IsEmpty()) return E_INVALIDARG; - #ifdef USE_WIN_FILE - NFile::NIO::CInFile file; if (!file.Open(us2fs(property.Value))) - return E_INVALIDARG; - UInt64 len; - if (!file.GetLength(len)) - return E_FAIL; - if (len >= ((UInt32)1 << 31) || len == 0) - return E_INVALIDARG; - ALLOC_WITH_HRESULT(&fileDataBuffer, (size_t)len); - UInt32 processedSize; - file.Read((Byte *)fileDataBuffer, (UInt32)len, processedSize); - if (processedSize != len) - return E_FAIL; - if (printCallback) + return GetLastError_noZero_HRESULT(); + size_t len; { - printCallback->Print("file size ="); - PrintNumber(*printCallback, len, 0); - printCallback->NewLine(); + UInt64 len64; + if (!file.GetLength(len64)) + return GetLastError_noZero_HRESULT(); + if (printCallback) + { + printCallback->Print("file size ="); + PrintNumber(*printCallback, len64, 0); + printCallback->NewLine(); + } + len = (size_t)len64; + if (len != len64) + return E_INVALIDARG; } - continue; - #else - - return E_NOTIMPL; + ALLOC_WITH_HRESULT(&fileDataBuffer, len); - #endif + { + size_t processed; + if (!file.ReadFull((Byte *)fileDataBuffer, len, processed)) + return GetLastError_noZero_HRESULT(); + if (processed != len) + return E_FAIL; + } + continue; } NCOM::CPropVariant propVariant; @@ -2966,10 +3413,56 @@ HRESULT Bench( if (name.IsEqualTo("time")) { - RINOK(ParsePropToUInt32(UString(), propVariant, testTime)); + RINOK(ParsePropToUInt32(UString(), propVariant, testTimeMs)); + needSetComplexity = true; + testTimeMs *= 1000; continue; } - + + if (name.IsEqualTo("timems")) + { + RINOK(ParsePropToUInt32(UString(), propVariant, testTimeMs)); + needSetComplexity = true; + continue; + } + + if (name.IsEqualTo("tic")) + { + UInt32 v; + RINOK(ParsePropToUInt32(UString(), propVariant, v)); + if (v >= 64) + return E_INVALIDARG; + complexInCommands = (UInt64)1 << v; + continue; + } + + if (name.IsEqualTo("ds")) + { + RINOK(ParsePropToUInt32(UString(), propVariant, startDicLog)); + startDicLog_Defined = true; + continue; + } + + if (name.IsEqualTo("mts")) + { + RINOK(ParsePropToUInt32(UString(), propVariant, numThreads_Start)); + continue; + } + + if (name.IsEqualTo("af")) + { + UInt32 bundle; + RINOK(ParsePropToUInt32(UString(), propVariant, bundle)); + if (bundle > 0 && bundle < numCPUs) + { + #ifndef _7ZIP_ST + affinityMode.SetLevels(numCPUs, 2); + affinityMode.NumBundleThreads = bundle; + #endif + } + continue; + } + if (name.IsEqualTo("freq")) { UInt32 freq32 = 0; @@ -2992,7 +3485,9 @@ HRESULT Bench( { UString s = name.Ptr(2); if (s.IsEqualTo("*") - || s.IsEmpty() && propVariant.vt == VT_BSTR && StringsAreEqual_Ascii(propVariant.bstrVal, "*")) + || (s.IsEmpty() + && propVariant.vt == VT_BSTR + && StringsAreEqual_Ascii(propVariant.bstrVal, "*"))) { multiThreadTests = true; continue; @@ -3009,62 +3504,10 @@ HRESULT Bench( if (printCallback) { - #ifdef _WIN32 - #ifndef UNDER_CE - { - AString s; - // OSVERSIONINFO vi; - OSVERSIONINFOEXW vi; - vi.dwOSVersionInfoSize = sizeof(vi); - // if (::GetVersionEx(&vi)) - if (My_RtlGetVersion(&vi)) - { - s += "Windows"; - if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT) - s.Add_UInt32(vi.dwPlatformId); - s += " "; s.Add_UInt32(vi.dwMajorVersion); - s += "."; s.Add_UInt32(vi.dwMinorVersion); - s += " "; s.Add_UInt32(vi.dwBuildNumber); - // s += " "; s += GetAnsiString(vi.szCSDVersion); - } - printCallback->Print(s); - printCallback->NewLine(); - } - #endif - #endif - - { - AString s1, s2; - GetSysInfo(s1, s2); - if (!s1.IsEmpty() || !s2.IsEmpty()) - { - printCallback->Print(s1); - if (s1 != s2 && !s2.IsEmpty()) - { - printCallback->Print(" - "); - printCallback->Print(s2); - } - printCallback->NewLine(); - } - } - { - AString s; - GetCpuFeatures(s); - if (!s.IsEmpty()) - { - printCallback->Print(s); - printCallback->NewLine(); - } - } - { - AString s; - GetCpuName(s); - if (!s.IsEmpty()) - { - printCallback->Print(s); - printCallback->NewLine(); - } - } + AString s; + GetSystemInfoText(s); + printCallback->Print(s); + printCallback->NewLine(); } if (printCallback) @@ -3072,8 +3515,6 @@ HRESULT Bench( printCallback->Print("CPU Freq:"); } - UInt64 complexInCommands = kComplexInCommands; - if (printCallback /* || freqCallback */) { UInt64 numMilCommands = 1 << 6; @@ -3098,7 +3539,9 @@ HRESULT Bench( start = realDelta; if (start == 0) start = 1; - UInt64 freq = GetFreq(); + if (start > (UInt64)1 << 61) + start = 1; + const UInt64 freq = GetFreq(); // mips is constant in some compilers const UInt64 mipsVal = numMilCommands * freq / start; if (printCallback) @@ -3118,12 +3561,25 @@ HRESULT Bench( freqCallback->AddCpuFreq(mipsVal); */ - if (jj >= 3) + if (jj >= 1) { - SetComplexCommands(testTime, false, mipsVal * 1000000, complexInCommands); - if (jj >= 8 || start >= freq) + bool needStop = (numMilCommands >= (1 << + #ifdef _DEBUG + 7 + #else + 11 + #endif + )); + if (start >= freq * 16) + { + printCallback->Print(" (Cmplx)"); + needSetComplexity = true; + needStop = true; + } + if (needSetComplexity) + SetComplexCommandsMs(testTimeMs, false, mipsVal * 1000000, complexInCommands); + if (needStop) break; - // break; // change it numMilCommands <<= 1; } } @@ -3156,7 +3612,10 @@ HRESULT Bench( return MethodBench( EXTERNAL_CODECS_LOC_VARS complexInCommands, + #ifndef _7ZIP_ST true, numThreadsSpecified, + &affinityMode, + #endif method, uncompressedDataSize, (const Byte *)fileDataBuffer, kOldLzmaDictBits, printCallback, benchCallback, &benchProps); @@ -3173,9 +3632,17 @@ HRESULT Bench( if (!printCallback) return S_FALSE; IBenchPrintCallback &f = *printCallback; - if (!dictIsDefined) - dict = (1 << 24); + UInt64 dict64 = dict; + if (!dictIsDefined) + dict64 = (1 << 27); + if (fileDataBuffer.IsAllocated()) + { + if (!dictIsDefined) + dict64 = fileDataBuffer.Size(); + else if (dict64 > fileDataBuffer.Size()) + dict64 = fileDataBuffer.Size(); + } // methhodName.RemoveChar(L'-'); UInt32 complexity = 10000; @@ -3190,87 +3657,172 @@ HRESULT Bench( int propPos = benchMethod.Find(':'); if (propPos >= 0) { - benchProps = benchMethod.Ptr(propPos + 1); - benchMethod.DeleteFrom(propPos); + benchProps = benchMethod.Ptr((unsigned)(propPos + 1)); + benchMethod.DeleteFrom((unsigned)propPos); } if (AreSameMethodNames(benchMethod, methodName)) { - if (benchProps.IsEmpty() - || benchMethod.IsEqualTo_Ascii_NoCase("crc32") && benchProps == "8" && method.PropsString.IsEmpty() - || method.PropsString.IsPrefixedBy_Ascii_NoCase(benchProps)) + bool isMainMathed = method.PropsString.IsEmpty(); + if (isMainMathed) + isMainMathed = !checkSum + || (benchMethod.IsEqualTo_Ascii_NoCase("crc32") && benchProps.IsEqualTo_Ascii_NoCase("8")); + const bool sameProps = method.PropsString.IsEqualTo_Ascii_NoCase(benchProps); + if (sameProps || isMainMathed) { complexity = h.Complex; checkSum = &h.CheckSum; - if (method.PropsString.IsEqualTo_Ascii_NoCase(benchProps)) + if (sameProps) break; } } } - if (i == ARRAY_SIZE(g_Hash)) + if (!checkSum) return E_NOTIMPL; } + { + UInt64 usage = 1 << 20; + UInt64 bufSize = dict64; + if (fileDataBuffer.IsAllocated()) + { + usage += fileDataBuffer.Size(); + if (bufSize > fileDataBuffer.Size()) + bufSize = fileDataBuffer.Size(); + if (numThreadsSpecified != 1) + usage += bufSize * numThreadsSpecified * (k_Crc_CreateLocalBuf_For_File ? 1 : 0); + } + else + usage += numThreadsSpecified * bufSize; + Print_Usage_and_Threads(f, usage, numThreadsSpecified); + } + f.NewLine(); - f.Print("Size"); - const unsigned kFieldSize_CrcSpeed = 6; - unsigned numThreadsTests = 0; - for (;;) - { - UInt32 t = GetNumThreadsNext(numThreadsTests, numThreadsSpecified); - PrintNumber(f, t, kFieldSize_CrcSpeed); - numThreadsTests++; - if (t >= numThreadsSpecified) - break; + + const unsigned kFieldSize_CrcSpeed = 7; + CUIntVector numThreadsVector; + { + unsigned nt = numThreads_Start; + for (;;) + { + if (nt > numThreadsSpecified) + break; + numThreadsVector.Add(nt); + unsigned next = nt * 2; + UInt32 ntHalf= numThreadsSpecified / 2; + if (ntHalf > nt && ntHalf < next) + numThreadsVector.Add(ntHalf); + if (numThreadsSpecified > nt && numThreadsSpecified < next) + numThreadsVector.Add(numThreadsSpecified); + nt = next; + } + { + f.NewLine(); + f.Print("THRD"); + FOR_VECTOR (ti, numThreadsVector) + { + PrintNumber(f, numThreadsVector[ti], 1 + kFieldSize_Usage + kFieldSize_CrcSpeed); + } + } + { + f.NewLine(); + f.Print(" "); + FOR_VECTOR (ti, numThreadsVector) + { + PrintRight(f, "Usage", kFieldSize_Usage + 1); + PrintRight(f, "BW", kFieldSize_CrcSpeed + 1); + } + } + { + f.NewLine(); + f.Print("Size"); + FOR_VECTOR (ti, numThreadsVector) + { + PrintRight(f, "%", kFieldSize_Usage + 1); + PrintRight(f, "MB/s", kFieldSize_CrcSpeed + 1); + } + } } + f.NewLine(); f.NewLine(); - CTempValues speedTotals(numThreadsTests); + + CTempValues speedTotals(numThreadsVector.Size()); + CTempValues usageTotals(numThreadsVector.Size()); { - for (unsigned ti = 0; ti < numThreadsTests; ti++) + FOR_VECTOR (ti, numThreadsVector) + { speedTotals.Values[ti] = 0; + usageTotals.Values[ti] = 0; + } } UInt64 numSteps = 0; + for (UInt32 i = 0; i < numIterations; i++) { - for (unsigned pow = 10; pow < 32; pow++) + unsigned pow = 10; // kNumHashDictBits + if (startDicLog_Defined) + pow = startDicLog; + for (;; pow++) { - UInt32 bufSize = (UInt32)1 << pow; - if (bufSize > dict) - break; + const UInt64 bufSize = (UInt64)1 << pow; char s[16]; ConvertUInt32ToString(pow, s); unsigned pos = MyStringLen(s); s[pos++] = ':'; s[pos++] = ' '; s[pos] = 0; - f.Print(s); + PrintRight(f, s, 4); + + size_t dataSize = fileDataBuffer.Size(); + if (dataSize > bufSize || !fileDataBuffer.IsAllocated()) + dataSize = (size_t)bufSize; - for (unsigned ti = 0; ti < numThreadsTests; ti++) + FOR_VECTOR (ti, numThreadsVector) { RINOK(f.CheckBreak()); - UInt32 t = GetNumThreadsNext(ti, numThreadsSpecified); + const UInt32 t = numThreadsVector[ti]; UInt64 speed = 0; - RINOK(CrcBench(EXTERNAL_CODECS_LOC_VARS complexInCommands, - t, bufSize, speed, + UInt64 usage = 0; + + HRESULT res = CrcBench(EXTERNAL_CODECS_LOC_VARS complexInCommands, + t, + dataSize, (const Byte *)fileDataBuffer, + speed, usage, complexity, 1, // benchWeight, - (pow == kNumHashDictBits) ? checkSum : NULL, method, NULL, NULL, false, 0)); - PrintNumber(f, (speed >> 20), kFieldSize_CrcSpeed); + (pow == kNumHashDictBits && !fileDataBuffer.IsAllocated()) ? checkSum : NULL, + method, + &f, + #ifndef _7ZIP_ST + &affinityMode, + #endif + false, // showRating + NULL, false, 0); + + RINOK(res); + + PrintUsage(f, usage, kFieldSize_Usage); + PrintNumber(f, speed / 1000000, kFieldSize_CrcSpeed); speedTotals.Values[ti] += speed; + usageTotals.Values[ti] += usage; } + f.NewLine(); numSteps++; + if (dataSize >= dict64) + break; } } if (numSteps != 0) { f.NewLine(); f.Print("Avg:"); - for (unsigned ti = 0; ti < numThreadsTests; ti++) + for (unsigned ti = 0; ti < numThreadsVector.Size(); ti++) { - PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), kFieldSize_CrcSpeed); + PrintUsage(f, usageTotals.Values[ti] / numSteps, kFieldSize_Usage); + PrintNumber(f, speedTotals.Values[ti] / numSteps / 1000000, kFieldSize_CrcSpeed); } f.NewLine(); } @@ -3352,7 +3904,7 @@ HRESULT Bench( } } - PrintRequirements(f, "usage:", true, GetBenchMemoryUsage(numThreads, dict, totalBenchMode), "Benchmark threads: ", numThreads); + Print_Usage_and_Threads(f, GetBenchMemoryUsage(numThreads, dict, totalBenchMode), numThreads); f.NewLine(); f.NewLine(); @@ -3443,60 +3995,114 @@ HRESULT Bench( { if (i != 0) printCallback->NewLine(); - HRESULT res; const unsigned kNumCpuTests = 3; for (unsigned freqTest = 0; freqTest < kNumCpuTests; freqTest++) { PrintLeft(f, "CPU", kFieldSize_Name); - UInt32 resVal; - RINOK(FreqBench(complexInCommands, numThreads, printCallback, - (freqTest == kNumCpuTests - 1 || specifiedFreq != 0), // showFreq - specifiedFreq, - cpuFreq, resVal)); + + // UInt32 resVal; + + CFreqBench fb; + fb.complexInCommands = complexInCommands; + fb.numThreads = numThreads; + // showFreq; + fb.showFreq = (freqTest == kNumCpuTests - 1 || specifiedFreq != 0); + fb.specifiedFreq = specifiedFreq; + + HRESULT res = fb.FreqBench(printCallback + #ifndef _7ZIP_ST + , &affinityMode + #endif + ); + RINOK(res); + + cpuFreq = fb.cpuFreq; callback.NewLine(); if (specifiedFreq != 0) cpuFreq = specifiedFreq; + if (testTimeMs >= 1000) if (freqTest == kNumCpuTests - 1) - SetComplexCommands(testTime, specifiedFreq != 0, cpuFreq, complexInCommands); + { + // SetComplexCommandsMs(testTimeMs, specifiedFreq != 0, cpuFreq, complexInCommands); + } } callback.NewLine(); + // return S_OK; // change it + callback.SetFreq(true, cpuFreq); if (!onlyHashBench) { - res = TotalBench(EXTERNAL_CODECS_LOC_VARS - complexInCommands, numThreads, + size_t dataSize = dict; + if (fileDataBuffer.IsAllocated()) + { + dataSize = fileDataBuffer.Size(); + if (dictIsDefined && dataSize > dict) + dataSize = dict; + } + + HRESULT res = TotalBench(EXTERNAL_CODECS_LOC_VARS + complexInCommands, + #ifndef _7ZIP_ST + numThreads, + &affinityMode, + #endif dictIsDefined || fileDataBuffer.IsAllocated(), // forceUnpackSize - fileDataBuffer.IsAllocated() ? fileDataBuffer.Size() : dict, + dataSize, (const Byte *)fileDataBuffer, printCallback, &callback); RINOK(res); } - res = TotalBench_Hash(EXTERNAL_CODECS_LOC_VARS complexInCommands, numThreads, - 1 << kNumHashDictBits, printCallback, &callback, &callback.EncodeRes, true, cpuFreq); - RINOK(res); + { + size_t dataSize = (size_t)1 << kNumHashDictBits; + if (dictIsDefined) + dataSize = dict; + if (fileDataBuffer.IsAllocated()) + { + dataSize = fileDataBuffer.Size(); + if (dictIsDefined && dataSize > dict) + dataSize = dict; + } + + HRESULT res = TotalBench_Hash(EXTERNAL_CODECS_LOC_VARS complexInCommands, numThreads, + dataSize, (const Byte *)fileDataBuffer, + printCallback, &callback, + #ifndef _7ZIP_ST + &affinityMode, + #endif + &callback.EncodeRes, true, cpuFreq); + RINOK(res); + } callback.NewLine(); { PrintLeft(f, "CPU", kFieldSize_Name); - UInt32 resVal; - UInt64 cpuFreqLastTemp = cpuFreq; - RINOK(FreqBench(complexInCommands, numThreads, printCallback, - specifiedFreq != 0, // showFreq - specifiedFreq, - cpuFreqLastTemp, resVal)); + + CFreqBench fb; + fb.complexInCommands = complexInCommands; + fb.numThreads = numThreads; + // showFreq; + fb.showFreq = (specifiedFreq != 0); + fb.specifiedFreq = specifiedFreq; + + HRESULT res = fb.FreqBench(printCallback + #ifndef _7ZIP_ST + , &affinityMode + #endif + ); + RINOK(res); callback.NewLine(); } } } else { - bool needSetComplexity = true; + needSetComplexity = true; if (!methodName.IsEqualTo_Ascii_NoCase("LZMA")) { unsigned i; @@ -3508,14 +4114,14 @@ HRESULT Bench( int propPos = benchMethod.Find(':'); if (propPos >= 0) { - benchProps = benchMethod.Ptr(propPos + 1); - benchMethod.DeleteFrom(propPos); + benchProps = benchMethod.Ptr((unsigned)(propPos + 1)); + benchMethod.DeleteFrom((unsigned)propPos); } if (AreSameMethodNames(benchMethod, methodName)) { if (benchProps.IsEmpty() - || benchProps == "x5" && method.PropsString.IsEmpty() + || (benchProps == "x5" && method.PropsString.IsEmpty()) || method.PropsString.IsPrefixedBy_Ascii_NoCase(benchProps)) { callback.BenchProps.EncComplex = h.EncComplex; @@ -3532,10 +4138,12 @@ HRESULT Bench( if (needSetComplexity) callback.BenchProps.SetLzmaCompexity(); + if (startDicLog < kBenchMinDicLogSize) + startDicLog = kBenchMinDicLogSize; + for (unsigned i = 0; i < numIterations; i++) { - const unsigned kStartDicLog = 22; - unsigned pow = (dict < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog; + unsigned pow = (dict < ((UInt32)1 << startDicLog)) ? kBenchMinDicLogSize : (unsigned)startDicLog; if (!multiDict) pow = 31; while (((UInt32)1 << pow) > dict && pow > 0) @@ -3576,7 +4184,10 @@ HRESULT Bench( HRESULT res = MethodBench( EXTERNAL_CODECS_LOC_VARS complexInCommands, + #ifndef _7ZIP_ST true, numThreads, + &affinityMode, + #endif method2, uncompressedDataSize, (const Byte *)fileDataBuffer, kOldLzmaDictBits, printCallback, &callback, &callback.BenchProps); diff --git a/CPP/7zip/UI/Common/Bench.h b/CPP/7zip/UI/Common/Bench.h index 18a40a84..02f443e3 100644 --- a/CPP/7zip/UI/Common/Bench.h +++ b/CPP/7zip/UI/Common/Bench.h @@ -66,7 +66,7 @@ AString GetProcessThreadsInfo(const NWindows::NSystem::CProcessAffinity &ti); void GetSysInfo(AString &s1, AString &s2); void GetCpuName(AString &s); -void GetCpuFeatures(AString &s); +void AddCpuFeatures(AString &s); #ifdef _7ZIP_LARGE_PAGES void Add_LargePages_String(AString &s); diff --git a/CPP/7zip/UI/Common/CompressCall.cpp b/CPP/7zip/UI/Common/CompressCall.cpp index 42cb0d23..72a61685 100644 --- a/CPP/7zip/UI/Common/CompressCall.cpp +++ b/CPP/7zip/UI/Common/CompressCall.cpp @@ -76,11 +76,12 @@ static HRESULT Call7zGui(const UString ¶ms, imageName += k7zGui; CProcess process; - WRes res = process.Create(imageName, params, NULL); // curDir); - if (res != 0) + const WRes wres = process.Create(imageName, params, NULL); // curDir); + if (wres != 0) { - ErrorMessageHRESULT(res, imageName); - return res; + HRESULT hres = HRESULT_FROM_WIN32(wres); + ErrorMessageHRESULT(hres, imageName); + return hres; } if (waitFinish) process.Wait(); @@ -130,12 +131,11 @@ static HRESULT CreateMap(const UStringVector &names, for (;;) { random.GenerateName(mappingName, "7zMap"); - - WRes res = fileMapping.Create(PAGE_READWRITE, totalSize, GetSystemString(mappingName)); - if (fileMapping.IsCreated() && res == 0) + const WRes wres = fileMapping.Create(PAGE_READWRITE, totalSize, GetSystemString(mappingName)); + if (fileMapping.IsCreated() && wres == 0) break; - if (res != ERROR_ALREADY_EXISTS) - return res; + if (wres != ERROR_ALREADY_EXISTS) + return HRESULT_FROM_WIN32(wres); fileMapping.Close(); } @@ -143,11 +143,11 @@ static HRESULT CreateMap(const UStringVector &names, for (;;) { random.GenerateName(eventName, "7zEvent"); - WRes res = event.CreateWithName(false, GetSystemString(eventName)); - if (event.IsCreated() && res == 0) + const WRes wres = event.CreateWithName(false, GetSystemString(eventName)); + if (event.IsCreated() && wres == 0) break; - if (res != ERROR_ALREADY_EXISTS) - return res; + if (wres != ERROR_ALREADY_EXISTS) + return HRESULT_FROM_WIN32(wres); event.Close(); } diff --git a/CPP/7zip/UI/Common/CompressCall2.cpp b/CPP/7zip/UI/Common/CompressCall2.cpp index 5bad774b..cbb5dcc9 100644 --- a/CPP/7zip/UI/Common/CompressCall2.cpp +++ b/CPP/7zip/UI/Common/CompressCall2.cpp @@ -6,6 +6,8 @@ #include "../../UI/Common/EnumDirItems.h" +#include "../../UI/FileManager/LangUtils.h" + #include "../../UI/GUI/BenchmarkDialog.h" #include "../../UI/GUI/ExtractGUI.h" #include "../../UI/GUI/UpdateGUI.h" diff --git a/CPP/7zip/UI/Common/DefaultName.cpp b/CPP/7zip/UI/Common/DefaultName.cpp index 02f611c3..8c34ffc7 100644 --- a/CPP/7zip/UI/Common/DefaultName.cpp +++ b/CPP/7zip/UI/Common/DefaultName.cpp @@ -20,7 +20,7 @@ static UString GetDefaultName3(const UString &fileName, int dotPos = fileName.ReverseFind_Dot(); if (dotPos > 0) - return fileName.Left(dotPos) + addSubExtension; + return fileName.Left((unsigned)dotPos) + addSubExtension; if (addSubExtension.IsEmpty()) return fileName + L'~'; diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h index 83937103..337cd1a7 100644 --- a/CPP/7zip/UI/Common/DirItem.h +++ b/CPP/7zip/UI/Common/DirItem.h @@ -3,6 +3,10 @@ #ifndef __DIR_ITEM_H #define __DIR_ITEM_H +#ifdef _WIN32 +#include "../../../Common/MyLinux.h" +#endif + #include "../../../Common/MyString.h" #include "../../../Windows/FileFind.h" @@ -84,13 +88,18 @@ struct CDirItem FILETIME MTime; UString Name; - #if defined(_WIN32) && !defined(UNDER_CE) - // UString ShortName; + #ifndef UNDER_CE CByteBuffer ReparseData; - CByteBuffer ReparseData2; // fixed (reduced) absolute links + #ifdef _WIN32 + // UString ShortName; + CByteBuffer ReparseData2; // fixed (reduced) absolute links for WIM format bool AreReparseData() const { return ReparseData.Size() != 0 || ReparseData2.Size() != 0; } - #endif + #else + bool AreReparseData() const { return ReparseData.Size() != 0; } + #endif // _WIN32 + + #endif // !UNDER_CE UInt32 Attrib; int PhyParent; @@ -100,9 +109,23 @@ struct CDirItem bool IsAltStream; CDirItem(): PhyParent(-1), LogParent(-1), SecureIndex(-1), IsAltStream(false) {} - bool IsDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } + + bool IsDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; } + bool IsReadOnly() const { return (Attrib & FILE_ATTRIBUTE_READONLY) != 0; } + bool Has_Attrib_ReparsePoint() const { return (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0; } + + #ifdef _WIN32 + UInt32 GetPosixAttrib() const + { + UInt32 v = IsDir() ? MY_LIN_S_IFDIR : MY_LIN_S_IFREG; + v |= (IsReadOnly() ? 0555 : 0777); + return v; + } + #endif }; + + class CDirItems { UStringVector Prefixes; @@ -117,17 +140,15 @@ public: CObjectVector<CDirItem> Items; bool SymLinks; - bool ScanAltStreams; CDirItemsStat Stat; - #ifndef UNDER_CE + #if !defined(UNDER_CE) HRESULT SetLinkInfo(CDirItem &dirItem, const NWindows::NFile::NFind::CFileInfo &fi, const FString &phyPrefix); #endif - #if defined(_WIN32) && !defined(UNDER_CE) CUniqBlocks SecureBlocks; @@ -136,6 +157,7 @@ public: bool ReadSecure; HRESULT AddSecurityItem(const FString &path, int &secureIndex); + HRESULT FillFixedReparse(); #endif @@ -157,6 +179,9 @@ public: unsigned AddPrefix(int phyParent, int logParent, const UString &prefix); void DeleteLastPrefix(); + + // HRESULT EnumerateOneDir(const FString &phyPrefix, CObjectVector<NWindows::NFile::NFind::CDirEntry> &files); + HRESULT EnumerateOneDir(const FString &phyPrefix, CObjectVector<NWindows::NFile::NFind::CFileInfo> &files); HRESULT EnumerateItems2( const FString &phyPrefix, @@ -164,13 +189,10 @@ public: const FStringVector &filePaths, FStringVector *requestedPaths); - #if defined(_WIN32) && !defined(UNDER_CE) - void FillFixedReparse(); - #endif - void ReserveDown(); }; + struct CArcItem { UInt64 Size; diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp index 088f0777..7a2dd008 100644 --- a/CPP/7zip/UI/Common/EnumDirItems.cpp +++ b/CPP/7zip/UI/Common/EnumDirItems.cpp @@ -3,6 +3,7 @@ #include "StdAfx.h" #include <wchar.h> +// #include <stdio.h> #include "../../../Common/Wildcard.h" @@ -55,8 +56,13 @@ void CDirItems::AddDirFileInfo(int phyParent, int logParent, int secureIndex, } } +// (DWORD)E_FAIL +#define DI_DEFAULT_ERROR ERROR_INVALID_FUNCTION + HRESULT CDirItems::AddError(const FString &path, DWORD errorCode) { + if (errorCode == 0) + errorCode = DI_DEFAULT_ERROR; Stat.NumErrors++; if (Callback) return Callback->ScanError(path, errorCode); @@ -83,17 +89,17 @@ UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const U unsigned len = name.Len(); int i; - for (i = index; i >= 0; i = parents[i]) - len += Prefixes[i].Len(); + for (i = index; i >= 0; i = parents[(unsigned)i]) + len += Prefixes[(unsigned)i].Len(); wchar_t *p = path.GetBuf_SetEnd(len) + len; p -= name.Len(); wmemcpy(p, (const wchar_t *)name, name.Len()); - for (i = index; i >= 0; i = parents[i]) + for (i = index; i >= 0; i = parents[(unsigned)i]) { - const UString &s = Prefixes[i]; + const UString &s = Prefixes[(unsigned)i]; p -= s.Len(); wmemcpy(p, (const wchar_t *)s, s.Len()); } @@ -150,6 +156,7 @@ CDirItems::CDirItems(): #endif } + #ifdef _USE_SECURITY_CODE HRESULT CDirItems::AddSecurityItem(const FString &path, int &secureIndex) @@ -166,7 +173,7 @@ HRESULT CDirItems::AddSecurityItem(const FString &path, int &secureIndex) DWORD errorCode = 0; DWORD secureSize; - BOOL res = ::GetFileSecurityW(fs2us(path), securInfo, (PSECURITY_DESCRIPTOR)(Byte *)TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize); + BOOL res = ::GetFileSecurityW(fs2us(path), securInfo, (PSECURITY_DESCRIPTOR)(void *)(Byte *)TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize); if (res) { @@ -185,7 +192,7 @@ HRESULT CDirItems::AddSecurityItem(const FString &path, int &secureIndex) else { TempSecureBuf.Alloc(secureSize); - res = ::GetFileSecurityW(fs2us(path), securInfo, (PSECURITY_DESCRIPTOR)(Byte *)TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize); + res = ::GetFileSecurityW(fs2us(path), securInfo, (PSECURITY_DESCRIPTOR)(void *)(Byte *)TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize); if (res) { if (secureSize != TempSecureBuf.Size()) @@ -199,33 +206,117 @@ HRESULT CDirItems::AddSecurityItem(const FString &path, int &secureIndex) if (res) { - secureIndex = SecureBlocks.AddUniq(TempSecureBuf, secureSize); + secureIndex = (int)SecureBlocks.AddUniq(TempSecureBuf, secureSize); return S_OK; } - if (errorCode == 0) - errorCode = ERROR_INVALID_FUNCTION; return AddError(path, errorCode); } -#endif +#endif // _USE_SECURITY_CODE -HRESULT CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phyPrefix) -{ - RINOK(ScanProgress(phyPrefix)); +HRESULT CDirItems::EnumerateOneDir(const FString &phyPrefix, CObjectVector<NFind::CFileInfo> &files) +{ NFind::CEnumerator enumerator; + // printf("\n enumerator.SetDirPrefix(phyPrefix) \n"); + enumerator.SetDirPrefix(phyPrefix); + + #ifdef _WIN32 + + NFind::CFileInfo fi; + for (unsigned ttt = 0; ; ttt++) { - NFind::CFileInfo fi; bool found; if (!enumerator.Next(fi, found)) + return AddError(phyPrefix); + if (!found) + return S_OK; + files.Add(fi); + if (Callback && (ttt & kScanProgressStepMask) == kScanProgressStepMask) + { + RINOK(ScanProgress(phyPrefix)); + } + } + + #else // _WIN32 + + // enumerator.SolveLinks = !SymLinks; + + CObjectVector<NFind::CDirEntry> entries; + + for (unsigned ttt = 0; ; ttt++) + { + bool found; + NFind::CDirEntry de; + if (!enumerator.Next(de, found)) { return AddError(phyPrefix); } if (!found) - return S_OK; + break; + entries.Add(de); + } + + FOR_VECTOR(i, entries) + { + const NFind::CDirEntry &de = entries[i]; + NFind::CFileInfo fi; + if (!enumerator.Fill_FileInfo(de, fi, !SymLinks)) + // if (!fi.Find_AfterEnumerator(path)) + { + const FString path = phyPrefix + de.Name; + { + RINOK(AddError(path)); + continue; + } + } + + files.Add(fi); + + if (Callback && (i & kScanProgressStepMask) == kScanProgressStepMask) + { + RINOK(ScanProgress(phyPrefix)); + } + } + + return S_OK; + + #endif // _WIN32 +} + + + + +HRESULT CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phyPrefix) +{ + RINOK(ScanProgress(phyPrefix)); + + CObjectVector<NFind::CFileInfo> files; + RINOK(EnumerateOneDir(phyPrefix, files)); + + FOR_VECTOR (i, files) + { + #ifdef _WIN32 + const NFind::CFileInfo &fi = files[i]; + #else + const NFind::CFileInfo &fi = files[i]; + /* + NFind::CFileInfo fi; + { + const NFind::CDirEntry &di = files[i]; + const FString path = phyPrefix + di.Name; + if (!fi.Find_AfterEnumerator(path)) + { + RINOK(AddError(path)); + continue; + } + fi.Name = di.Name; + } + */ + #endif int secureIndex = -1; #ifdef _USE_SECURITY_CODE @@ -237,7 +328,7 @@ HRESULT CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phy AddDirFileInfo(phyParent, logParent, secureIndex, fi); - if (Callback && (ttt & kScanProgressStepMask) == kScanProgressStepMask) + if (Callback && (i & kScanProgressStepMask) == kScanProgressStepMask) { RINOK(ScanProgress(phyPrefix)); } @@ -246,26 +337,45 @@ HRESULT CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phy { const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; unsigned parent = AddPrefix(phyParent, logParent, fs2us(name2)); - RINOK(EnumerateDir(parent, parent, phyPrefix + name2)); + RINOK(EnumerateDir((int)parent, (int)parent, phyPrefix + name2)); } } + return S_OK; } + +/* +EnumerateItems2() + const FStringVector &filePaths - are path without tail slashes. + All dir prefixes of filePaths will be not stores in logical paths +fix it: we can scan AltStream also. +*/ + +#ifdef _WIN32 +// #define FOLLOW_LINK_PARAM +// #define FOLLOW_LINK_PARAM2 +#define FOLLOW_LINK_PARAM , (!SymLinks) +#define FOLLOW_LINK_PARAM2 , (!dirItems.SymLinks) +#else +#define FOLLOW_LINK_PARAM , (!SymLinks) +#define FOLLOW_LINK_PARAM2 , (!dirItems.SymLinks) +#endif + HRESULT CDirItems::EnumerateItems2( const FString &phyPrefix, const UString &logPrefix, const FStringVector &filePaths, FStringVector *requestedPaths) { - int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, fs2us(phyPrefix)); - int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix); + const int phyParent = phyPrefix.IsEmpty() ? -1 : (int)AddPrefix(-1, -1, fs2us(phyPrefix)); + const int logParent = logPrefix.IsEmpty() ? -1 : (int)AddPrefix(-1, -1, logPrefix); FOR_VECTOR (i, filePaths) { const FString &filePath = filePaths[i]; NFind::CFileInfo fi; const FString phyPath = phyPrefix + filePath; - if (!fi.Find(phyPath)) + if (!fi.Find(phyPath FOLLOW_LINK_PARAM)) { RINOK(AddError(phyPath)); continue; @@ -273,13 +383,13 @@ HRESULT CDirItems::EnumerateItems2( if (requestedPaths) requestedPaths->Add(phyPath); - int delimiter = filePath.ReverseFind_PathSepar(); + const int delimiter = filePath.ReverseFind_PathSepar(); FString phyPrefixCur; int phyParentCur = phyParent; if (delimiter >= 0) { - phyPrefixCur.SetFrom(filePath, delimiter + 1); - phyParentCur = AddPrefix(phyParent, logParent, fs2us(phyPrefixCur)); + phyPrefixCur.SetFrom(filePath, (unsigned)(delimiter + 1)); + phyParentCur = (int)AddPrefix(phyParent, logParent, fs2us(phyPrefixCur)); } int secureIndex = -1; @@ -296,7 +406,7 @@ HRESULT CDirItems::EnumerateItems2( { const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; unsigned parent = AddPrefix(phyParentCur, logParent, fs2us(name2)); - RINOK(EnumerateDir(parent, parent, phyPrefix + phyPrefixCur + name2)); + RINOK(EnumerateDir((int)parent, (int)parent, phyPrefix + phyPrefixCur + name2)); } } @@ -307,34 +417,46 @@ HRESULT CDirItems::EnumerateItems2( - - static HRESULT EnumerateDirItems( const NWildcard::CCensorNode &curNode, - int phyParent, int logParent, const FString &phyPrefix, - const UStringVector &addArchivePrefix, + const int phyParent, const int logParent, + const FString &phyPrefix, + const UStringVector &addParts, // additional parts from curNode CDirItems &dirItems, bool enterToSubFolders); + +/* EnumerateDirItems_Spec() + adds new Dir item prefix, and enumerates dir items, + then it can remove that Dir item prefix, if there are no items in that dir. +*/ + + +/* + EnumerateDirItems_Spec() + it's similar to EnumerateDirItems, but phyPrefix doesn't include (curFolderName) +*/ + static HRESULT EnumerateDirItems_Spec( const NWildcard::CCensorNode &curNode, - int phyParent, int logParent, const FString &curFolderName, - const FString &phyPrefix, - const UStringVector &addArchivePrefix, + const int phyParent, const int logParent, const FString &curFolderName, + const FString &phyPrefix, // without (curFolderName) + const UStringVector &addParts, // (curNode + addParts) includes (curFolderName) CDirItems &dirItems, bool enterToSubFolders) { const FString name2 = curFolderName + FCHAR_PATH_SEPARATOR; - unsigned parent = dirItems.AddPrefix(phyParent, logParent, fs2us(name2)); - unsigned numItems = dirItems.Items.Size(); + const unsigned parent = dirItems.AddPrefix(phyParent, logParent, fs2us(name2)); + const unsigned numItems = dirItems.Items.Size(); HRESULT res = EnumerateDirItems( - curNode, parent, parent, phyPrefix + name2, - addArchivePrefix, dirItems, enterToSubFolders); + curNode, (int)parent, (int)parent, phyPrefix + name2, + addParts, dirItems, enterToSubFolders); if (numItems == dirItems.Items.Size()) dirItems.DeleteLastPrefix(); return res; } + #ifndef UNDER_CE #ifdef _WIN32 @@ -342,98 +464,107 @@ static HRESULT EnumerateDirItems_Spec( static HRESULT EnumerateAltStreams( const NFind::CFileInfo &fi, const NWildcard::CCensorNode &curNode, - int phyParent, int logParent, const FString &fullPath, - const UStringVector &addArchivePrefix, // prefix from curNode - bool addAllItems, + const int phyParent, const int logParent, + const FString &phyPath, // with (fi.Name), without tail slash for folders + const UStringVector &addParts, // with (fi.Name), prefix parts from curNode + bool addAllSubStreams, CDirItems &dirItems) { - NFind::CStreamEnumerator enumerator(fullPath); + NFind::CStreamEnumerator enumerator(phyPath); for (;;) { NFind::CStreamInfo si; bool found; if (!enumerator.Next(si, found)) { - return dirItems.AddError(fullPath + FTEXT(":*")); // , (DWORD)E_FAIL + return dirItems.AddError(phyPath + FTEXT(":*")); // , (DWORD)E_FAIL } if (!found) return S_OK; if (si.IsMainStream()) continue; - UStringVector addArchivePrefixNew = addArchivePrefix; - UString reducedName = si.GetReducedName(); - addArchivePrefixNew.Back() += reducedName; - if (curNode.CheckPathToRoot(false, addArchivePrefixNew, true)) + UStringVector parts = addParts; + const UString reducedName = si.GetReducedName(); + parts.Back() += reducedName; + if (curNode.CheckPathToRoot(false, parts, true)) continue; - if (!addAllItems) - if (!curNode.CheckPathToRoot(true, addArchivePrefixNew, true)) + if (!addAllSubStreams) + if (!curNode.CheckPathToRoot(true, parts, true)) continue; NFind::CFileInfo fi2 = fi; fi2.Name += us2fs(reducedName); fi2.Size = si.Size; - fi2.Attrib &= ~FILE_ATTRIBUTE_DIRECTORY; + fi2.Attrib &= ~(DWORD)(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT); fi2.IsAltStream = true; dirItems.AddDirFileInfo(phyParent, logParent, -1, fi2); } } -#endif +#endif // _WIN32 + + +/* We get Reparse data and parse it. + If there is Reparse error, we free dirItem.Reparse data. + Do we need to work with empty reparse data? +*/ HRESULT CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi, const FString &phyPrefix) { - if (!SymLinks || !fi.HasReparsePoint()) + if (!SymLinks) return S_OK; + + #ifdef _WIN32 + if (!fi.HasReparsePoint() || fi.IsAltStream) + #else // _WIN32 + if (!fi.IsPosixLink()) + #endif // _WIN32 + return S_OK; + const FString path = phyPrefix + fi.Name; CByteBuffer &buf = dirItem.ReparseData; - DWORD res = 0; if (NIO::GetReparseData(path, buf)) { - CReparseAttr attr; - if (attr.Parse(buf, buf.Size(), res)) - return S_OK; - // we ignore unknown reparse points - if (res != ERROR_INVALID_REPARSE_DATA) - res = 0; - } - else - { - res = ::GetLastError(); - if (res == 0) - res = ERROR_INVALID_FUNCTION; + // if (dirItem.ReparseData.Size() != 0) + Stat.FilesSize -= fi.Size; + return S_OK; } + DWORD res = ::GetLastError(); buf.Free(); - if (res == 0) - return S_OK; return AddError(path, res); } -#endif +#endif // UNDER_CE + + static HRESULT EnumerateForItem( - NFind::CFileInfo &fi, + const NFind::CFileInfo &fi, const NWildcard::CCensorNode &curNode, - int phyParent, int logParent, const FString &phyPrefix, - const UStringVector &addArchivePrefix, // prefix from curNode + const int phyParent, const int logParent, const FString &phyPrefix, + const UStringVector &addParts, // additional parts from curNode, without (fi.Name) CDirItems &dirItems, bool enterToSubFolders) { const UString name = fs2us(fi.Name); - bool enterToSubFolders2 = enterToSubFolders; - UStringVector addArchivePrefixNew = addArchivePrefix; - addArchivePrefixNew.Add(name); - { - UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); - if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir())) - return S_OK; - } - int dirItemIndex = -1; + UStringVector newParts = addParts; + newParts.Add(name); + // check the path in exclude rules + if (curNode.CheckPathToRoot(false, newParts, !fi.IsDir())) + return S_OK; + + #if !defined(UNDER_CE) + int dirItemIndex = -1; + #if defined(_WIN32) bool addAllSubStreams = false; + #endif // _WIN32 + #endif // !defined(UNDER_CE) - if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir())) + // check the path in inlcude rules + if (curNode.CheckPathToRoot(true, newParts, !fi.IsDir())) { int secureIndex = -1; #ifdef _USE_SECURITY_CODE @@ -443,58 +574,96 @@ static HRESULT EnumerateForItem( } #endif - dirItemIndex = dirItems.Items.Size(); + #if !defined(UNDER_CE) + dirItemIndex = (int)dirItems.Items.Size(); + #if defined(_WIN32) + // we will not check include rules for substreams. + addAllSubStreams = true; + #endif // _WIN32 + #endif // !defined(UNDER_CE) + dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi); if (fi.IsDir()) - enterToSubFolders2 = true; - - addAllSubStreams = true; + enterToSubFolders = true; } - #ifndef UNDER_CE - if (dirItems.ScanAltStreams) - { - RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent, - phyPrefix + fi.Name, - addArchivePrefixNew, - addAllSubStreams, - dirItems)); - } + #if !defined(UNDER_CE) + + // we don't scan AltStreams for link files if (dirItemIndex >= 0) { - CDirItem &dirItem = dirItems.Items[dirItemIndex]; + CDirItem &dirItem = dirItems.Items[(unsigned)dirItemIndex]; RINOK(dirItems.SetLinkInfo(dirItem, fi, phyPrefix)); if (dirItem.ReparseData.Size() != 0) return S_OK; } - #endif + #if defined(_WIN32) + if (dirItems.ScanAltStreams) + { + RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent, + phyPrefix + fi.Name, // with (fi.Name) + newParts, // with (fi.Name) + addAllSubStreams, + dirItems)); + } + #endif + + #endif // !defined(UNDER_CE) + + + #ifndef _WIN32 + if (!fi.IsPosixLink()) // posix link can follow to dir + #endif if (!fi.IsDir()) return S_OK; - - const NWildcard::CCensorNode *nextNode = 0; - if (addArchivePrefix.IsEmpty()) + + const NWildcard::CCensorNode *nextNode = NULL; + + if (addParts.IsEmpty()) { int index = curNode.FindSubNode(name); if (index >= 0) - nextNode = &curNode.SubNodes[index]; + { + nextNode = &curNode.SubNodes[(unsigned)index]; + newParts.Clear(); + } } - if (!enterToSubFolders2 && nextNode == 0) - return S_OK; - - addArchivePrefixNew = addArchivePrefix; - if (nextNode == 0) + + if (!nextNode) { + if (!enterToSubFolders) + return S_OK; + + #ifndef _WIN32 + if (fi.IsPosixLink()) + { + // here we can try to resolve posix link + // if the link to dir, then can we follow it + return S_OK; // we don't follow posix link + } + #endif + + if (dirItems.SymLinks && fi.HasReparsePoint()) + { + /* 20.03: in SymLinks mode: we don't enter to directory that + has reparse point and has no CCensorNode + NOTE: (curNode and parent nodes) still can have wildcard rules + to include some items of target directory (of reparse point), + but we ignore these rules here. + */ + return S_OK; + } nextNode = &curNode; - addArchivePrefixNew.Add(name); } return EnumerateDirItems_Spec( - *nextNode, phyParent, logParent, fi.Name, phyPrefix, - addArchivePrefixNew, + *nextNode, phyParent, logParent, fi.Name, + phyPrefix, // without (fi.Name) + newParts, // relative to (*nextNode). (*nextNode + newParts) includes (fi.Name) dirItems, - enterToSubFolders2); + enterToSubFolders); } @@ -513,10 +682,13 @@ static bool CanUseFsDirect(const NWildcard::CCensorNode &curNode) /* Windows doesn't support file name with wildcard But if another system supports file name with wildcard, - and wildcard mode is disabled, we can ignore wildcard in name */ + and wildcard mode is disabled, we can ignore wildcard in name + */ /* + #ifndef _WIN32 if (!item.WildcardParsing) continue; + #endif */ if (DoesNameContainWildcard(name)) return false; @@ -532,26 +704,33 @@ static bool IsVirtualFsFolder(const FString &prefix, const UString &name) UString s = fs2us(prefix); s += name; s.Add_PathSepar(); + // it returns (true) for non real FS folder path like - "\\SERVER\" return IsPathSepar(s[0]) && GetRootPrefixSize(s) == 0; } #endif + + static HRESULT EnumerateDirItems( const NWildcard::CCensorNode &curNode, - int phyParent, int logParent, const FString &phyPrefix, - const UStringVector &addArchivePrefix, // prefix from curNode + const int phyParent, const int logParent, const FString &phyPrefix, + const UStringVector &addParts, // prefix from curNode including CDirItems &dirItems, bool enterToSubFolders) { if (!enterToSubFolders) + { + /* if there are IncludeItems censor rules that affect items in subdirs, + then we will enter to all subfolders */ if (curNode.NeedCheckSubDirs()) enterToSubFolders = true; + } RINOK(dirItems.ScanProgress(phyPrefix)); // try direct_names case at first - if (addArchivePrefix.IsEmpty() && !enterToSubFolders) + if (addParts.IsEmpty() && !enterToSubFolders) { if (CanUseFsDirect(curNode)) { @@ -616,16 +795,16 @@ static HRESULT EnumerateDirItems( } else #endif - if (!fi.Find(fullPath)) + if (!fi.Find(fullPath FOLLOW_LINK_PARAM2)) { RINOK(dirItems.AddError(fullPath)); continue; } - bool isDir = fi.IsDir(); - if (isDir && !item.ForDir || !isDir && !item.ForFile) + const bool isDir = fi.IsDir(); + if ((isDir && !item.ForDir) || (!isDir && !item.ForFile)) { - RINOK(dirItems.AddError(fullPath, (DWORD)E_FAIL)); + RINOK(dirItems.AddError(fullPath, DI_DEFAULT_ERROR)); continue; } { @@ -645,55 +824,74 @@ static HRESULT EnumerateDirItems( dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi); - #ifndef UNDER_CE + // we don't scan AltStreams for link files + + #if !defined(UNDER_CE) { CDirItem &dirItem = dirItems.Items.Back(); RINOK(dirItems.SetLinkInfo(dirItem, fi, phyPrefix)); if (dirItem.ReparseData.Size() != 0) - { - if (fi.IsAltStream) - dirItems.Stat.AltStreamsSize -= fi.Size; - else - dirItems.Stat.FilesSize -= fi.Size; continue; - } } - #endif - - - #ifndef UNDER_CE + + #if defined(_WIN32) if (needAltStreams && dirItems.ScanAltStreams) { UStringVector pathParts; pathParts.Add(fs2us(fi.Name)); RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent, - fullPath, pathParts, + fullPath, // including (name) + pathParts, // including (fi.Name) true, /* addAllSubStreams */ dirItems)); } - #endif + #endif // defined(_WIN32) + #endif // !defined(UNDER_CE) + + + #ifndef _WIN32 + if (!fi.IsPosixLink()) // posix link can follow to dir + #endif if (!isDir) continue; - - UStringVector addArchivePrefixNew; - const NWildcard::CCensorNode *nextNode = 0; + + UStringVector newParts; + const NWildcard::CCensorNode *nextNode = NULL; int index = curNode.FindSubNode(name); if (index >= 0) { - for (int t = needEnterVector.Size(); t <= index; t++) + for (int t = (int)needEnterVector.Size(); t <= index; t++) needEnterVector.Add(true); - needEnterVector[index] = false; - nextNode = &curNode.SubNodes[index]; + needEnterVector[(unsigned)index] = false; + nextNode = &curNode.SubNodes[(unsigned)index]; } else { + #ifndef _WIN32 + if (fi.IsPosixLink()) + { + // here we can try to resolve posix link + // if the link to dir, then can we follow it + continue; // we don't follow posix link + } + #endif + + if (dirItems.SymLinks) + { + if (fi.HasReparsePoint()) + { + /* 20.03: in SymLinks mode: we don't enter to directory that + has reparse point and has no CCensorNode */ + continue; + } + } nextNode = &curNode; - addArchivePrefixNew.Add(name); // don't change it to fi.Name. It's for shortnames support + newParts.Add(name); // don't change it to fi.Name. It's for shortnames support } RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix, - addArchivePrefixNew, dirItems, true)); + newParts, dirItems, true)); } for (i = 0; i < curNode.SubNodes.Size(); i++) @@ -718,7 +916,7 @@ static HRESULT EnumerateDirItems( } // we don't want to call fi.Find() for root folder or virtual folder - if (phyPrefix.IsEmpty() && nextNode.Name.IsEmpty() + if ((phyPrefix.IsEmpty() && nextNode.Name.IsEmpty()) #if defined(_WIN32) && !defined(UNDER_CE) || IsVirtualFsFolder(phyPrefix, nextNode.Name) #endif @@ -729,7 +927,7 @@ static HRESULT EnumerateDirItems( } else { - if (!fi.Find(fullPath)) + if (!fi.Find(fullPath FOLLOW_LINK_PARAM2)) { if (!nextNode.AreThereIncludeItems()) continue; @@ -739,7 +937,7 @@ static HRESULT EnumerateDirItems( if (!fi.IsDir()) { - RINOK(dirItems.AddError(fullPath, (DWORD)E_FAIL)); + RINOK(dirItems.AddError(fullPath, DI_DEFAULT_ERROR)); continue; } } @@ -791,7 +989,7 @@ static HRESULT EnumerateDirItems( fi.Name = driveName; RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix, - addArchivePrefix, dirItems, enterToSubFolders)); + addParts, dirItems, enterToSubFolders)); } return S_OK; } @@ -800,43 +998,81 @@ static HRESULT EnumerateDirItems( #endif #endif - NFind::CEnumerator enumerator; - enumerator.SetDirPrefix(phyPrefix); - for (unsigned ttt = 0; ; ttt++) + CObjectVector<NFind::CFileInfo> files; + + // for (int y = 0; y < 1; y++) { - NFind::CFileInfo fi; - bool found; - if (!enumerator.Next(fi, found)) + // files.Clear(); + RINOK(dirItems.EnumerateOneDir(phyPrefix, files)); + /* + FOR_VECTOR (i, files) + { + #ifdef _WIN32 + // const NFind::CFileInfo &fi = files[i]; + #else + NFind::CFileInfo &fi = files[i]; { - RINOK(dirItems.AddError(phyPrefix)); - break; + const NFind::CFileInfo &di = files[i]; + const FString path = phyPrefix + di.Name; + if (!fi.Find_AfterEnumerator(path)) + { + RINOK(dirItems.AddError(path)); + continue; + } + fi.Name = di.Name; } - if (!found) - break; + #endif - if (dirItems.Callback && (ttt & kScanProgressStepMask) == kScanProgressStepMask) + } + */ + } + + FOR_VECTOR (i, files) + { + #ifdef _WIN32 + const NFind::CFileInfo &fi = files[i]; + #else + const NFind::CFileInfo &fi = files[i]; + /* + NFind::CFileInfo fi; { - RINOK(dirItems.ScanProgress(phyPrefix)); + const NFind::CDirEntry &di = files[i]; + const FString path = phyPrefix + di.Name; + if (!fi.Find_AfterEnumerator(path)) + { + RINOK(dirItems.AddError(path)); + continue; + } + fi.Name = di.Name; } + */ + #endif RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix, - addArchivePrefix, dirItems, enterToSubFolders)); + addParts, dirItems, enterToSubFolders)); + if (dirItems.Callback && (i & kScanProgressStepMask) == kScanProgressStepMask) + { + RINOK(dirItems.ScanProgress(phyPrefix)); + } } return S_OK; } + + + HRESULT EnumerateItems( const NWildcard::CCensor &censor, const NWildcard::ECensorPathMode pathMode, - const UString &addPathPrefix, + const UString &addPathPrefix, // prefix that will be added to Logical Path CDirItems &dirItems) { FOR_VECTOR (i, censor.Pairs) { const NWildcard::CPair &pair = censor.Pairs[i]; - int phyParent = pair.Prefix.IsEmpty() ? -1 : dirItems.AddPrefix(-1, -1, pair.Prefix); + const int phyParent = pair.Prefix.IsEmpty() ? -1 : (int)dirItems.AddPrefix(-1, -1, pair.Prefix); int logParent = -1; if (pathMode == NWildcard::k_AbsPath) @@ -844,7 +1080,7 @@ HRESULT EnumerateItems( else { if (!addPathPrefix.IsEmpty()) - logParent = dirItems.AddPrefix(-1, -1, addPathPrefix); + logParent = (int)dirItems.AddPrefix(-1, -1, addPathPrefix); } RINOK(EnumerateDirItems(pair.Head, phyParent, logParent, us2fs(pair.Prefix), UStringVector(), @@ -855,34 +1091,103 @@ HRESULT EnumerateItems( dirItems.ReserveDown(); #if defined(_WIN32) && !defined(UNDER_CE) - dirItems.FillFixedReparse(); + RINOK(dirItems.FillFixedReparse()); #endif return S_OK; } + + #if defined(_WIN32) && !defined(UNDER_CE) -void CDirItems::FillFixedReparse() +HRESULT CDirItems::FillFixedReparse() { - /* imagex/WIM reduces absolute pathes in links (raparse data), - if we archive non root folder. We do same thing here */ - - if (!SymLinks) - return; - FOR_VECTOR(i, Items) { CDirItem &item = Items[i]; + + if (!SymLinks) + { + // continue; // for debug + if (!item.Has_Attrib_ReparsePoint()) + continue; + + // if (item.IsDir()) continue; + + const FString phyPath = GetPhyPath(i); + + NFind::CFileInfo fi; + if (fi.Fill_From_ByHandleFileInfo(phyPath)) // item.IsDir() + { + item.Size = fi.Size; + item.CTime = fi.CTime; + item.ATime = fi.ATime; + item.MTime = fi.MTime; + item.Attrib = fi.Attrib; + continue; + } + + /* + // we request properties of target file instead of properies of symbolic link + // here we also can manually parse unsupported links (like WSL links) + NIO::CInFile inFile; + if (inFile.Open(phyPath)) + { + BY_HANDLE_FILE_INFORMATION info; + if (inFile.GetFileInformation(&info)) + { + // Stat.FilesSize doesn't contain item.Size already + // Stat.FilesSize -= item.Size; + item.Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; + Stat.FilesSize += item.Size; + item.CTime = info.ftCreationTime; + item.ATime = info.ftLastAccessTime; + item.MTime = info.ftLastWriteTime; + item.Attrib = info.dwFileAttributes; + continue; + } + } + */ + + RINOK(AddError(phyPath)); + continue; + } + + // (SymLinks == true) here + if (item.ReparseData.Size() == 0) continue; + + // if (item.Size == 0) + { + // 20.03: we use Reparse Data instead of real data + item.Size = item.ReparseData.Size(); + } CReparseAttr attr; - DWORD errorCode = 0; - if (!attr.Parse(item.ReparseData, item.ReparseData.Size(), errorCode)) + if (!attr.Parse(item.ReparseData, item.ReparseData.Size())) + { + const FString phyPath = GetPhyPath(i); + AddError(phyPath, attr.ErrorCode); continue; - if (attr.IsRelative()) + } + + /* imagex/WIM reduces absolute paths in links (raparse data), + if we archive non root folder. We do same thing here */ + + bool isWSL = false; + if (attr.IsSymLink_WSL()) + { + // isWSL = true; + // we don't change WSL symlinks continue; + } + else + { + if (attr.IsRelative_Win()) + continue; + } const UString &link = attr.GetPath(); if (!IsDrivePath(link)) @@ -892,7 +1197,7 @@ void CDirItems::FillFixedReparse() FString fullPathF; if (!NDir::MyGetFullPathName(GetPhyPath(i), fullPathF)) continue; - UString fullPath = fs2us(fullPathF); + const UString fullPath = fs2us(fullPathF); const UString logPath = GetLogPath(i); if (logPath.Len() >= fullPath.Len()) continue; @@ -903,7 +1208,7 @@ void CDirItems::FillFixedReparse() if (!IsPathSepar(prefix.Back())) continue; - unsigned rootPrefixSize = GetRootPrefixSize(prefix); + const unsigned rootPrefixSize = GetRootPrefixSize(prefix); if (rootPrefixSize == 0) continue; if (rootPrefixSize == prefix.Len()) @@ -919,10 +1224,12 @@ void CDirItems::FillFixedReparse() newLink += link.Ptr(prefix.Len()); CByteBuffer data; - if (!FillLinkData(data, newLink, attr.IsSymLink())) + bool isSymLink = !attr.IsMountPoint(); + if (!FillLinkData(data, newLink, isSymLink, isWSL)) continue; item.ReparseData2 = data; } + return S_OK; } #endif diff --git a/CPP/7zip/UI/Common/EnumDirItems.h b/CPP/7zip/UI/Common/EnumDirItems.h index 6490bd50..9b17c600 100644 --- a/CPP/7zip/UI/Common/EnumDirItems.h +++ b/CPP/7zip/UI/Common/EnumDirItems.h @@ -5,12 +5,8 @@ #include "../../../Common/Wildcard.h" -#include "../../../Windows/FileFind.h" - #include "DirItem.h" -void AddDirFileInfo(int phyParent, int logParent, int secureIndex, - const NWindows::NFile::NFind::CFileInfo &fi, CObjectVector<CDirItem> &dirItems); HRESULT EnumerateItems( const NWildcard::CCensor &censor, diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp index c49daa1d..18bd1037 100644 --- a/CPP/7zip/UI/Common/Extract.cpp +++ b/CPP/7zip/UI/Common/Extract.cpp @@ -7,6 +7,7 @@ #include "../../../Common/StringConvert.h" #include "../../../Windows/FileDir.h" +#include "../../../Windows/ErrorMsg.h" #include "../../../Windows/PropVariant.h" #include "../../../Windows/PropVariantConv.h" @@ -19,6 +20,19 @@ using namespace NWindows; using namespace NFile; using namespace NDir; + +static void SetErrorMessage(const char *message, + const FString &path, HRESULT errorCode, + UString &s) +{ + s = message; + s += " : "; + s += NError::MyFormatMessage(errorCode); + s += " : "; + s += fs2us(path); +} + + static HRESULT DecompressArchive( CCodecs *codecs, const CArchiveLink &arcLink, @@ -47,7 +61,7 @@ static HRESULT DecompressArchive( // So it extracts different archives to one folder. // We will use top level archive name const CArc &arc0 = arcLink.Arcs[0]; - if (StringsAreEqualNoCase_Ascii(codecs->Formats[arc0.FormatIndex].Name, "pe")) + if (arc0.FormatIndex >= 0 && StringsAreEqualNoCase_Ascii(codecs->Formats[(unsigned)arc0.FormatIndex].Name, "pe")) replaceName = arc0.DefaultName; } @@ -164,11 +178,8 @@ static HRESULT DecompressArchive( */ else if (!CreateComplexDir(outDir)) { - HRESULT res = ::GetLastError(); - if (res == S_OK) - res = E_FAIL; - errorMessage = "Can not create output directory: "; - errorMessage += fs2us(outDir); + const HRESULT res = GetLastError_noZero_HRESULT(); + SetErrorMessage("Cannot create output directory", outDir, res, errorMessage); return res; } @@ -221,6 +232,7 @@ static HRESULT DecompressArchive( Sorted list for file paths was sorted with case insensitive compare function. But FindInSorted function did binary search via case sensitive compare function */ +int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &name); int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &name) { unsigned left = 0, right = fileName.Size(); @@ -230,7 +242,7 @@ int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &n const UString &midValue = fileName[mid]; int compare = CompareFileNames(name, midValue); if (compare == 0) - return mid; + return (int)mid; if (compare < 0) right = mid; else @@ -239,6 +251,8 @@ int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &n return -1; } + + HRESULT Extract( CCodecs *codecs, const CObjectVector<COpenType> &types, @@ -268,11 +282,19 @@ HRESULT Extract( fi.Size = 0; if (!options.StdInMode) { - const FString &arcPath = us2fs(arcPaths[i]); - if (!fi.Find(arcPath)) - throw "there is no such archive"; + const FString arcPath = us2fs(arcPaths[i]); + if (!fi.Find_FollowLink(arcPath)) + { + const HRESULT errorCode = GetLastError_noZero_HRESULT(); + SetErrorMessage("Cannot find archive file", arcPath, errorCode, errorMessage); + return errorCode; + } if (fi.IsDir()) - throw "can't decompress folder"; + { + HRESULT errorCode = E_FAIL; + SetErrorMessage("The item is a directory", arcPath, errorCode, errorMessage); + return errorCode; + } } arcSizes.Add(fi.Size); totalPackSize += fi.Size; @@ -314,8 +336,12 @@ HRESULT Extract( } else { - if (!fi.Find(us2fs(arcPath)) || fi.IsDir()) - throw "there is no such archive"; + if (!fi.Find_FollowLink(us2fs(arcPath)) || fi.IsDir()) + { + const HRESULT errorCode = GetLastError_noZero_HRESULT(); + SetErrorMessage("Cannot find archive file", us2fs(arcPath), errorCode, errorMessage); + return errorCode; + } } /* @@ -379,12 +405,7 @@ HRESULT Extract( { thereAreNotOpenArcs = true; if (!options.StdInMode) - { - NFind::CFileInfo fi2; - if (fi2.Find(us2fs(arcPath))) - if (!fi2.IsDir()) - totalPackProcessed += fi2.Size; - } + totalPackProcessed += fi.Size; continue; } @@ -397,7 +418,7 @@ HRESULT Extract( // numArcs = arcPaths.Size(); if (arcLink.VolumePaths.Size() != 0) { - Int64 correctionSize = arcLink.VolumesSize; + Int64 correctionSize = (Int64)arcLink.VolumesSize; FOR_VECTOR (v, arcLink.VolumePaths) { int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]); @@ -415,7 +436,7 @@ HRESULT Extract( Int64 newPackSize = (Int64)totalPackSize + correctionSize; if (newPackSize < 0) newPackSize = 0; - totalPackSize = newPackSize; + totalPackSize = (UInt64)newPackSize; RINOK(extractCallback->SetTotal(totalPackSize)); } } diff --git a/CPP/7zip/UI/Common/Extract.h b/CPP/7zip/UI/Common/Extract.h index 03ac74b2..bfabe195 100644 --- a/CPP/7zip/UI/Common/Extract.h +++ b/CPP/7zip/UI/Common/Extract.h @@ -53,10 +53,10 @@ struct CExtractOptions: public CExtractOptionsBase #endif CExtractOptions(): - TestMode(false), StdInMode(false), StdOutMode(false), - YesToAll(false) + YesToAll(false), + TestMode(false) {} }; diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp index 535530e4..21a306d2 100644 --- a/CPP/7zip/UI/Common/ExtractingFilePath.cpp +++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp @@ -8,6 +8,8 @@ #include "ExtractingFilePath.h" +extern +bool g_PathTrailReplaceMode; bool g_PathTrailReplaceMode = #ifdef _WIN32 true @@ -17,6 +19,7 @@ bool g_PathTrailReplaceMode = ; +#ifdef _WIN32 static void ReplaceIncorrectChars(UString &s) { { @@ -31,7 +34,10 @@ static void ReplaceIncorrectChars(UString &s) || #endif c == WCHAR_PATH_SEPARATOR) - s.ReplaceOneCharAtPos(i, '_'); + s.ReplaceOneCharAtPos(i, + '_' // default + // (wchar_t)(0xf000 + c) // 21.02 debug: WSL encoding for unsupported characters + ); } } @@ -72,8 +78,7 @@ static void ReplaceIncorrectChars(UString &s) } } } - -#ifdef _WIN32 +#endif /* WinXP-64 doesn't support ':', '\\' and '/' symbols in name of alt stream. But colon in postfix ":$DATA" is allowed. @@ -98,6 +103,8 @@ void Correct_AltStream_Name(UString &s) s = '_'; } +#ifdef _WIN32 + static const unsigned g_ReservedWithNum_Index = 4; static const char * const g_ReservedNames[] = @@ -149,7 +156,7 @@ static void Correct_PathPart(UString &s) if (s.IsEmpty()) return; - if (s[0] == '.' && (s[1] == 0 || s[1] == '.' && s[2] == 0)) + if (s[0] == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) s.Empty(); #ifdef _WIN32 else diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.h b/CPP/7zip/UI/Common/ExtractingFilePath.h index 81cb8267..8f8f9f1b 100644 --- a/CPP/7zip/UI/Common/ExtractingFilePath.h +++ b/CPP/7zip/UI/Common/ExtractingFilePath.h @@ -5,9 +5,9 @@ #include "../../../Common/MyString.h" -#ifdef _WIN32 +// #ifdef _WIN32 void Correct_AltStream_Name(UString &s); -#endif +// #endif // replaces unsuported characters, and replaces "." , ".." and "" to "[]" UString Get_Correct_FsFile_Name(const UString &name); diff --git a/CPP/7zip/UI/Common/HashCalc.cpp b/CPP/7zip/UI/Common/HashCalc.cpp index c340ac7f..c87be443 100644 --- a/CPP/7zip/UI/Common/HashCalc.cpp +++ b/CPP/7zip/UI/Common/HashCalc.cpp @@ -8,6 +8,7 @@ #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" +#include "../../Common/StreamObjects.h" #include "EnumDirItems.h" #include "HashCalc.h" @@ -211,6 +212,8 @@ HRESULT HashCalc( else { RINOK(callback->StartScanning()); + + dirItems.SymLinks = options.SymLinks.Val; dirItems.ScanAltStreams = options.AltStreamsMode; HRESULT res = EnumerateItems(censor, @@ -258,31 +261,47 @@ HRESULT HashCalc( UString path; bool isDir = false; bool isAltStream = false; + if (options.StdInMode) { inStream = new CStdInFileStream; } else { - CInFileStream *inStreamSpec = new CInFileStream; - inStream = inStreamSpec; - const CDirItem &dirItem = dirItems.Items[i]; - isDir = dirItem.IsDir(); - isAltStream = dirItem.IsAltStream; path = dirItems.GetLogPath(i); - if (!isDir) + const CDirItem &di = dirItems.Items[i]; + isAltStream = di.IsAltStream; + + #ifndef UNDER_CE + // if (di.AreReparseData()) + if (di.ReparseData.Size() != 0) { - FString phyPath = dirItems.GetPhyPath(i); - if (!inStreamSpec->OpenShared(phyPath, options.OpenShareForWrite)) + CBufInStream *inStreamSpec = new CBufInStream(); + inStream = inStreamSpec; + inStreamSpec->Init(di.ReparseData, di.ReparseData.Size()); + } + else + #endif + { + CInFileStream *inStreamSpec = new CInFileStream; + inStreamSpec->File.PreserveATime = options.PreserveATime; + inStream = inStreamSpec; + isDir = di.IsDir(); + if (!isDir) { - HRESULT res = callback->OpenFileError(phyPath, ::GetLastError()); - hb.NumErrors++; - if (res != S_FALSE) - return res; - continue; + const FString phyPath = dirItems.GetPhyPath(i); + if (!inStreamSpec->OpenShared(phyPath, options.OpenShareForWrite)) + { + HRESULT res = callback->OpenFileError(phyPath, ::GetLastError()); + hb.NumErrors++; + if (res != S_FALSE) + return res; + continue; + } } } } + RINOK(callback->GetStream(path, isDir)); UInt64 fileSize = 0; diff --git a/CPP/7zip/UI/Common/HashCalc.h b/CPP/7zip/UI/Common/HashCalc.h index db5b39aa..b6d320b5 100644 --- a/CPP/7zip/UI/Common/HashCalc.h +++ b/CPP/7zip/UI/Common/HashCalc.h @@ -62,6 +62,8 @@ struct CHashBundle: public IHashCalc NumDirs = NumFiles = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0; } + virtual ~CHashBundle() {}; + void InitForNewFile(); void Update(const void *data, UInt32 size); void SetSize(UInt64 size); @@ -90,12 +92,20 @@ struct IHashCallbackUI: public IDirItemsCallback struct CHashOptions { UStringVector Methods; + bool PreserveATime; bool OpenShareForWrite; bool StdInMode; bool AltStreamsMode; + CBoolPair SymLinks; + NWildcard::ECensorPathMode PathMode; - CHashOptions(): StdInMode(false), OpenShareForWrite(false), AltStreamsMode(false), PathMode(NWildcard::k_RelatPath) {}; + CHashOptions(): + PreserveATime(false), + OpenShareForWrite(false), + StdInMode(false), + AltStreamsMode(false), + PathMode(NWildcard::k_RelatPath) {}; }; HRESULT HashCalc( diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp index f1334613..b94720c5 100644 --- a/CPP/7zip/UI/Common/LoadCodecs.cpp +++ b/CPP/7zip/UI/Common/LoadCodecs.cpp @@ -39,6 +39,8 @@ EXPORT_CODECS #include "../../../Common/StringToInt.h" #include "../../../Common/StringConvert.h" +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/FileIO.h" #include "../../../Windows/PropVariant.h" #include "LoadCodecs.h" @@ -82,11 +84,11 @@ using namespace NFile; static CFSTR const kMainDll = - // #ifdef _WIN32 + #ifdef _WIN32 FTEXT("7z.dll"); - // #else - // FTEXT("7z.so"); - // #endif + #else + FTEXT("7z.so"); + #endif #ifdef _WIN32 @@ -110,7 +112,7 @@ static bool ReadPathFromRegistry(HKEY baseKey, LPCWSTR value, FString &path) { path = us2fs(pathU); NName::NormalizeDirPathPrefix(path); - return NFind::DoesFileExist(path + kMainDll); + return NFind::DoesFileExist_Raw(path + kMainDll); } } return false; @@ -163,7 +165,7 @@ int CArcInfoEx::FindExtension(const UString &ext) const { FOR_VECTOR (i, Exts) if (ext.IsEqualTo_NoCase(Exts[i].Ext)) - return i; + return (int)i; return -1; } @@ -206,15 +208,18 @@ static bool ParseSignatures(const Byte *data, unsigned size, CObjectVector<CByte #endif // _SFX +// #include <stdio.h> + #ifdef EXTERNAL_CODECS static FString GetBaseFolderPrefixFromRegistry() { FString moduleFolderPrefix = NDLL::GetModuleDirPrefix(); + #ifdef _WIN32 - if (!NFind::DoesFileExist(moduleFolderPrefix + kMainDll) && - !NFind::DoesDirExist(moduleFolderPrefix + kCodecsFolderName) && - !NFind::DoesDirExist(moduleFolderPrefix + kFormatsFolderName)) + if ( !NFind::DoesFileOrDirExist(moduleFolderPrefix + kMainDll) + && !NFind::DoesFileOrDirExist(moduleFolderPrefix + kCodecsFolderName) + && !NFind::DoesFileOrDirExist(moduleFolderPrefix + kFormatsFolderName)) { FString path; if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPath2Value, path)) return path; @@ -223,6 +228,8 @@ static FString GetBaseFolderPrefixFromRegistry() if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPathValue, path)) return path; } #endif + + // printf("\nmoduleFolderPrefix = %s\n", (const char *)GetAnsiString(moduleFolderPrefix)); return moduleFolderPrefix; } @@ -238,25 +245,29 @@ static HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 in if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID)) return E_FAIL; isAssigned = true; - clsId = *(const GUID *)prop.bstrVal; + clsId = *(const GUID *)(const void *)prop.bstrVal; } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } +#define MY_GET_FUNC(dest, type, func) *(void **)(&dest) = (func); +// #define MY_GET_FUNC(dest, type, func) dest = (type)(func); + HRESULT CCodecs::LoadCodecs() { CCodecLib &lib = Libs.Back(); - lib.CreateDecoder = (Func_CreateDecoder)lib.Lib.GetProc("CreateDecoder"); - lib.CreateEncoder = (Func_CreateEncoder)lib.Lib.GetProc("CreateEncoder"); - lib.GetMethodProperty = (Func_GetMethodProperty)lib.Lib.GetProc("GetMethodProperty"); + MY_GET_FUNC (lib.CreateDecoder, Func_CreateDecoder, lib.Lib.GetProc("CreateDecoder")); + MY_GET_FUNC (lib.CreateEncoder, Func_CreateEncoder, lib.Lib.GetProc("CreateEncoder")); + MY_GET_FUNC (lib.GetMethodProperty, Func_GetMethodProperty, lib.Lib.GetProc("GetMethodProperty")); if (lib.GetMethodProperty) { UInt32 numMethods = 1; - Func_GetNumberOfMethods getNumberOfMethods = (Func_GetNumberOfMethods)lib.Lib.GetProc("GetNumberOfMethods"); + Func_GetNumberOfMethods getNumberOfMethods; + MY_GET_FUNC (getNumberOfMethods, Func_GetNumberOfMethods, lib.Lib.GetProc("GetNumberOfMethods")); if (getNumberOfMethods) { RINOK(getNumberOfMethods(&numMethods)); @@ -272,7 +283,8 @@ HRESULT CCodecs::LoadCodecs() } } - Func_GetHashers getHashers = (Func_GetHashers)lib.Lib.GetProc("GetHashers"); + Func_GetHashers getHashers; + MY_GET_FUNC (getHashers, Func_GetHashers, lib.Lib.GetProc("GetHashers")); if (getHashers) { RINOK(getHashers(&lib.ComHashers)); @@ -381,14 +393,17 @@ HRESULT CCodecs::LoadFormats() const NDLL::CLibrary &lib = Libs.Back().Lib; Func_GetHandlerProperty getProp = NULL; - Func_GetHandlerProperty2 getProp2 = (Func_GetHandlerProperty2)lib.GetProc("GetHandlerProperty2"); - Func_GetIsArc getIsArc = (Func_GetIsArc)lib.GetProc("GetIsArc"); + Func_GetHandlerProperty2 getProp2; + MY_GET_FUNC (getProp2, Func_GetHandlerProperty2, lib.GetProc("GetHandlerProperty2")); + Func_GetIsArc getIsArc; + MY_GET_FUNC (getIsArc, Func_GetIsArc, lib.GetProc("GetIsArc")); UInt32 numFormats = 1; if (getProp2) { - Func_GetNumberOfFormats getNumberOfFormats = (Func_GetNumberOfFormats)lib.GetProc("GetNumberOfFormats"); + Func_GetNumberOfFormats getNumberOfFormats; + MY_GET_FUNC (getNumberOfFormats, Func_GetNumberOfFormats, lib.GetProc("GetNumberOfFormats")); if (getNumberOfFormats) { RINOK(getNumberOfFormats(&numFormats)); @@ -396,7 +411,7 @@ HRESULT CCodecs::LoadFormats() } else { - getProp = (Func_GetHandlerProperty)lib.GetProc("GetHandlerProperty"); + MY_GET_FUNC (getProp, Func_GetHandlerProperty, lib.GetProc("GetHandlerProperty")); if (!getProp) return S_OK; } @@ -404,7 +419,7 @@ HRESULT CCodecs::LoadFormats() for (UInt32 i = 0; i < numFormats; i++) { CArcInfoEx item; - item.LibIndex = Libs.Size() - 1; + item.LibIndex = (int)(Libs.Size() - 1); item.FormatIndex = i; RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kName, item.Name)); @@ -417,7 +432,7 @@ HRESULT CCodecs::LoadFormats() continue; if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID)) return E_FAIL; - item.ClassID = *(const GUID *)prop.bstrVal; + item.ClassID = *(const GUID *)(const void *)prop.bstrVal; prop.Clear(); } @@ -473,23 +488,53 @@ extern "C" } #endif + +void CCodecs::AddLastError(const FString &path) +{ + HRESULT res = GetLastError_noZero_HRESULT(); + CCodecError &error = Errors.AddNew(); + error.Path = path; + error.ErrorCode = res; +} + HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loadedOK) { if (loadedOK) *loadedOK = false; + // needCheckDll = 1; + + #ifdef _WIN32 if (needCheckDll) { NDLL::CLibrary lib; if (!lib.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE)) + { + /* if is not win32 + // %1 is not a valid Win32 application. + // #define ERROR_BAD_EXE_FORMAT 193L + */ + // return GetLastError_noZero_HRESULT(); + DWORD lastError = GetLastError(); + if (lastError != ERROR_BAD_EXE_FORMAT) + { + CCodecError &error = Errors.AddNew(); + error.Path = dllPath; + error.Message = "cannot load file as datafile library"; + error.ErrorCode = HRESULT_FROM_WIN32(lastError); + } return S_OK; + } } + #else + UNUSED_VAR(needCheckDll) + #endif Libs.AddNew(); CCodecLib &lib = Libs.Back(); lib.Path = dllPath; bool used = false; - HRESULT res = S_OK; + // HRESULT res = S_OK; if (lib.Lib.Load(dllPath)) { @@ -499,10 +544,28 @@ HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loaded lib.LoadIcons(); #endif + /* + { + Func_LibStartup _LibStartup; + MY_GET_FUNC (_LibStartup, Func_LibStartup, lib.Lib.GetProc("LibStartup")); + if (_LibStartup) + { + HRESULT res = _LibStartup(); + if (res != 0) + { + CCodecError &error = Errors.AddNew(); + error.Path = dllPath; + error.ErrorCode = res; + } + } + } + */ + #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0) { - Func_SetLargePageMode setLargePageMode = (Func_SetLargePageMode)lib.Lib.GetProc("SetLargePageMode"); + Func_SetLargePageMode setLargePageMode; + MY_GET_FUNC (setLargePageMode, Func_SetLargePageMode, lib.Lib.GetProc("SetLargePageMode")); if (setLargePageMode) setLargePageMode(); } @@ -510,16 +573,18 @@ HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loaded if (CaseSensitiveChange) { - Func_SetCaseSensitive setCaseSensitive = (Func_SetCaseSensitive)lib.Lib.GetProc("SetCaseSensitive"); + Func_SetCaseSensitive setCaseSensitive; + MY_GET_FUNC (setCaseSensitive, Func_SetCaseSensitive, lib.Lib.GetProc("SetCaseSensitive")); if (setCaseSensitive) setCaseSensitive(CaseSensitive ? 1 : 0); } - lib.CreateObject = (Func_CreateObject)lib.Lib.GetProc("CreateObject"); + MY_GET_FUNC (lib.CreateObject, Func_CreateObject, lib.Lib.GetProc("CreateObject")); { unsigned startSize = Codecs.Size() + Hashers.Size(); - res = LoadCodecs(); - used = (startSize != Codecs.Size() + Hashers.Size()); + HRESULT res = LoadCodecs(); + if (startSize != Codecs.Size() + Hashers.Size()) + used = true; if (res == S_OK && lib.CreateObject) { startSize = Formats.Size(); @@ -527,22 +592,61 @@ HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loaded if (startSize != Formats.Size()) used = true; } + if (res != S_OK) + { + CCodecError &error = Errors.AddNew(); + error.Path = dllPath; + error.ErrorCode = res; + } } + // plugins can use non-7-zip dlls, so we silently ignore non7zip DLLs + /* + if (!used) + { + CCodecError &error = Errors.AddNew(); + error.Path = dllPath; + error.Message = "no 7-Zip code"; + } + */ + } + else + { + AddLastError(dllPath); } if (!used) Libs.DeleteBack(); - return res; + return S_OK; } -HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPrefix) +HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPath) { + if (!NFile::NFind::DoesDirExist_FollowLink(folderPath)) + // if (!NFile::NFind::DoesDirExist(folderPath)) + { + // AddLastError(folderPath); + return S_OK; + } + + FString folderPrefix = folderPath; + folderPrefix.Add_PathSepar(); + NFile::NFind::CEnumerator enumerator; enumerator.SetDirPrefix(folderPrefix); - NFile::NFind::CFileInfo fi; - while (enumerator.Next(fi)) + NFile::NFind::CDirEntry fi; + for (;;) { + bool found; + if (!enumerator.Next(fi, found)) + { + // it can be wrong Symbolic link to folder here + AddLastError(folderPath); + break; + // return GetLastError_noZero_HRESULT(); + } + if (!found) + break; if (fi.IsDir()) continue; RINOK(LoadDll(folderPrefix + fi.Name, true)); @@ -585,6 +689,7 @@ HRESULT CCodecs::Load() Formats.Clear(); #ifdef EXTERNAL_CODECS + Errors.Clear(); MainDll_ErrorPath.Empty(); Codecs.Clear(); Hashers.Clear(); @@ -627,6 +732,8 @@ HRESULT CCodecs::Load() Formats.Add(item); } + // printf("\nLoad codecs \n"); + #ifdef EXTERNAL_CODECS const FString baseFolder = GetBaseFolderPrefixFromRegistry(); { @@ -635,8 +742,8 @@ HRESULT CCodecs::Load() if (!loadedOK) MainDll_ErrorPath = kMainDll; } - RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName FSTRING_PATH_SEPARATOR)); - RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName FSTRING_PATH_SEPARATOR)); + RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName)); + RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName)); NeedSetLibCodecs = true; @@ -659,7 +766,7 @@ HRESULT CCodecs::Load() FOR_VECTOR(i, Libs) { CCodecLib &lib = Libs[i]; - lib.SetCodecs = (Func_SetCodecs)lib.Lib.GetProc("SetCodecs"); + MY_GET_FUNC (lib.SetCodecs, Func_SetCodecs, lib.Lib.GetProc("SetCodecs")); if (lib.SetCodecs) { RINOK(lib.SetCodecs(this)); @@ -679,7 +786,7 @@ int CCodecs::FindFormatForArchiveName(const UString &arcPath) const int dotPos = arcPath.ReverseFind_Dot(); if (dotPos <= arcPath.ReverseFind_PathSepar()) return -1; - const UString ext = arcPath.Ptr(dotPos + 1); + const UString ext = arcPath.Ptr((unsigned)(dotPos + 1)); if (ext.IsEmpty()) return -1; if (ext.IsEqualTo_Ascii_NoCase("exe")) @@ -692,7 +799,7 @@ int CCodecs::FindFormatForArchiveName(const UString &arcPath) const continue; */ if (arc.FindExtension(ext) >= 0) - return i; + return (int)i; } return -1; } @@ -703,7 +810,7 @@ int CCodecs::FindFormatForExtension(const UString &ext) const return -1; FOR_VECTOR (i, Formats) if (Formats[i].FindExtension(ext) >= 0) - return i; + return (int)i; return -1; } @@ -711,7 +818,7 @@ int CCodecs::FindFormatForArchiveType(const UString &arcType) const { FOR_VECTOR (i, Formats) if (Formats[i].Name.IsEqualTo_NoCase(arcType)) - return i; + return (int)i; return -1; } @@ -722,8 +829,8 @@ bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &forma { int pos2 = arcType.Find(L'.', pos); if (pos2 < 0) - pos2 = arcType.Len(); - const UString name = arcType.Mid(pos, pos2 - pos); + pos2 = (int)arcType.Len(); + const UString name = arcType.Mid(pos, (unsigned)pos2 - pos); if (name.IsEmpty()) return false; int index = FindFormatForArchiveType(name); @@ -733,7 +840,7 @@ bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &forma return false; } formatIndices.Add(index); - pos = pos2 + 1; + pos = (unsigned)pos2 + 1; } return true; } @@ -756,19 +863,19 @@ void CCodecIcons::LoadIcons(HMODULE m) CIconPair iconPair; iconPair.IconIndex = -1; if (pos < 0) - pos = s.Len(); + pos = (int)s.Len(); else { - UString num = s.Ptr(pos + 1); + const UString num = s.Ptr((unsigned)pos + 1); if (!num.IsEmpty()) { const wchar_t *end; - iconPair.IconIndex = ConvertStringToUInt32(num, &end); + iconPair.IconIndex = (int)ConvertStringToUInt32(num, &end); if (*end != 0) continue; } } - iconPair.Ext = s.Left(pos); + iconPair.Ext = s.Left((unsigned)pos); IconPairs.Add(iconPair); } } @@ -946,7 +1053,7 @@ int CCodecs::GetCodec_LibIndex(UInt32 index) const #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; - return ci.LibIndex; + return (int)ci.LibIndex; #else return -1; #endif @@ -961,7 +1068,7 @@ int CCodecs::GetHasherLibIndex(UInt32 index) #ifdef EXTERNAL_CODECS const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; - return ci.LibIndex; + return (int)ci.LibIndex; #else return -1; #endif @@ -1014,7 +1121,8 @@ bool CCodecs::GetCodec_EncoderIsAssigned(UInt32 index) const UInt32 CCodecs::GetCodec_NumStreams(UInt32 index) { NCOM::CPropVariant prop; - RINOK(GetProperty(index, NMethodPropID::kPackStreams, &prop)); + if (GetProperty(index, NMethodPropID::kPackStreams, &prop) != S_OK) + return 0; if (prop.vt == VT_UI4) return (UInt32)prop.ulVal; if (prop.vt == VT_EMPTY) @@ -1065,10 +1173,33 @@ AString CCodecs::GetHasherName(UInt32 index) UInt32 CCodecs::GetHasherDigestSize(UInt32 index) { NCOM::CPropVariant prop; - RINOK(GetHasherProp(index, NMethodPropID::kDigestSize, &prop)); + if (GetHasherProp(index, NMethodPropID::kDigestSize, &prop) != S_OK) + return 0; if (prop.vt != VT_UI4) return 0; return prop.ulVal; } +void CCodecs::GetCodecsErrorMessage(UString &s) +{ + s.Empty(); + FOR_VECTOR (i, Errors) + { + const CCodecError &ce = Errors[i]; + s += "Codec Load Error: "; + s += fs2us(ce.Path); + if (ce.ErrorCode != 0) + { + s += " : "; + s += NWindows::NError::MyFormatMessage(ce.ErrorCode); + } + if (!ce.Message.IsEmpty()) + { + s += " : "; + s += ce.Message; + } + s.Add_LF(); + } +} + #endif // EXTERNAL_CODECS diff --git a/CPP/7zip/UI/Common/LoadCodecs.h b/CPP/7zip/UI/Common/LoadCodecs.h index ac9eeac7..660ddee4 100644 --- a/CPP/7zip/UI/Common/LoadCodecs.h +++ b/CPP/7zip/UI/Common/LoadCodecs.h @@ -132,7 +132,8 @@ struct CArcInfoEx bool Flags_BackwardOpen() const { return (Flags & NArcInfoFlags::kBackwardOpen) != 0; } bool Flags_PreArc() const { return (Flags & NArcInfoFlags::kPreArc) != 0; } bool Flags_PureStartOpen() const { return (Flags & NArcInfoFlags::kPureStartOpen) != 0; } - + bool Flags_ByExtOnlyOpen() const { return (Flags & NArcInfoFlags::kByExtOnlyOpen) != 0; } + UString GetMainExt() const { if (Exts.IsEmpty()) @@ -227,6 +228,13 @@ struct CCodecLib #endif +struct CCodecError +{ + FString Path; + HRESULT ErrorCode; + AString Message; + CCodecError(): ErrorCode(0) {} +}; class CCodecs: #ifdef EXTERNAL_CODECS @@ -243,7 +251,9 @@ public: CObjectVector<CCodecLib> Libs; FString MainDll_ErrorPath; - + CObjectVector<CCodecError> Errors; + + void AddLastError(const FString &path); void CloseLibs(); class CReleaser @@ -272,7 +282,7 @@ public: HRESULT CreateArchiveHandler(const CArcInfoEx &ai, bool outHandler, void **archive) const { - return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive); + return Libs[(unsigned)ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive); } #endif @@ -306,11 +316,11 @@ public: const wchar_t *GetFormatNamePtr(int formatIndex) const { - return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[formatIndex].Name; + return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[(unsigned)formatIndex].Name; } HRESULT Load(); - + #ifndef _SFX int FindFormatForArchiveName(const UString &arcPath) const; int FindFormatForExtension(const UString &ext) const; @@ -352,6 +362,8 @@ public: AString GetHasherName(UInt32 index); UInt32 GetHasherDigestSize(UInt32 index); + void GetCodecsErrorMessage(UString &s); + #endif HRESULT CreateInArchive(unsigned formatIndex, CMyComPtr<IInArchive> &archive) const @@ -399,7 +411,7 @@ public: if (!arc.UpdateEnabled) continue; if (arc.Name.IsEqualTo_NoCase(name)) - return i; + return (int)i; } return -1; } diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp index 419c29ee..7bec9d53 100644 --- a/CPP/7zip/UI/Common/OpenArchive.cpp +++ b/CPP/7zip/UI/Common/OpenArchive.cpp @@ -14,6 +14,7 @@ #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" +#include "../../../Common/UTFConvert.h" #include "../../../Common/Wildcard.h" #include "../../../Windows/FileDir.h" @@ -32,11 +33,13 @@ #include "SetProperties.h" #endif +#ifndef _SFX #ifdef SHOW_DEBUG_INFO #define PRF(x) x #else #define PRF(x) #endif +#endif // increase it, if you need to support larger SFX stubs static const UInt64 kMaxCheckStartPosition = 1 << 23; @@ -64,7 +67,7 @@ Open: - open FAIL: Try to open with all other types from offset 0 only. If some open type is OK and physical archive size is uequal or larger - than file size, then return that archive with warning that can not be open as [extension type]. + than file size, then return that archive with warning that cannot be open as [extension type]. If extension was EXE, it will try to open as unknown_extension case - file has unknown extension (like a.hhh) It tries to open via parser code. @@ -141,14 +144,14 @@ struct CParseItem bool LenIsUnknown; CParseItem(): - LenIsUnknown(false), + // OkSize(0), FileTime_Defined(false), UnpackSize_Defined(false), - NumSubFiles_Defined(false), NumSubDirs_Defined(false), + NumSubFiles_Defined(false), IsSelfExe(false), - IsNotArcType(false) - // OkSize(0) + IsNotArcType(false), + LenIsUnknown(false) {} /* @@ -214,15 +217,17 @@ int CHandler::FindInsertPos(const CParseItem &item) const left = mid + 1; else if (item.Size < midItem.Size) right = mid; + /* else if (item.Size > midItem.Size) left = mid + 1; + */ else { left = mid + 1; // return -1; } } - return left; + return (int)left; } void CHandler::AddUnknownItem(UInt64 next) @@ -260,7 +265,7 @@ void CHandler::AddItem(const CParseItem &item) int pos = FindInsertPos(item); if (pos >= 0) { - _items.Insert(pos, item); + _items.Insert((unsigned)pos, item); UInt64 next = item.Offset + item.Size; if (_maxEndOffset < next) _maxEndOffset = next; @@ -401,7 +406,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 askMode = testMode ? NExtract::NAskMode::kTest : NExtract::NAskMode::kExtract; - Int32 index = allFilesMode ? i : indices[i]; + UInt32 index = allFilesMode ? i : indices[i]; const CParseItem &item = _items[index]; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); @@ -417,7 +422,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, outStreamSpec->Init(skipMode ? 0 : unpackSize, true); Int32 opRes = NExtract::NOperationResult::kOK; - RINOK(_stream->Seek(item.Offset, STREAM_SEEK_SET, NULL)); + RINOK(_stream->Seek((Int64)item.Offset, STREAM_SEEK_SET, NULL)); streamSpec->Init(unpackSize); RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); @@ -496,13 +501,14 @@ static HRESULT Archive_GetArcProp_UInt(IInArchive *arc, PROPID propid, UInt64 &r RINOK(arc->GetArchiveProperty(propid, &prop)); switch (prop.vt) { - case VT_UI4: result = prop.ulVal; defined = true; break; - case VT_I4: result = (Int64)prop.lVal; defined = true; break; - case VT_UI8: result = (UInt64)prop.uhVal.QuadPart; defined = true; break; - case VT_I8: result = (UInt64)prop.hVal.QuadPart; defined = true; break; - case VT_EMPTY: break; + case VT_UI4: result = prop.ulVal; break; + case VT_I4: result = (UInt64)(Int64)prop.lVal; break; + case VT_UI8: result = (UInt64)prop.uhVal.QuadPart; break; + case VT_I8: result = (UInt64)prop.hVal.QuadPart; break; + case VT_EMPTY: return S_OK; default: return E_FAIL; } + defined = true; return S_OK; } @@ -513,13 +519,14 @@ static HRESULT Archive_GetArcProp_Int(IInArchive *arc, PROPID propid, Int64 &res RINOK(arc->GetArchiveProperty(propid, &prop)); switch (prop.vt) { - case VT_UI4: result = prop.ulVal; defined = true; break; - case VT_I4: result = prop.lVal; defined = true; break; - case VT_UI8: result = (Int64)prop.uhVal.QuadPart; defined = true; break; - case VT_I8: result = (Int64)prop.hVal.QuadPart; defined = true; break; - case VT_EMPTY: break; + case VT_UI4: result = prop.ulVal; break; + case VT_I4: result = prop.lVal; break; + case VT_UI8: result = (Int64)prop.uhVal.QuadPart; break; + case VT_I8: result = (Int64)prop.hVal.QuadPart; break; + case VT_EMPTY: return S_OK; default: return E_FAIL; } + defined = true; return S_OK; } @@ -607,6 +614,8 @@ HRESULT CArc::GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &pa #endif + + HRESULT CArc::GetItemPath(UInt32 index, UString &result) const { #ifdef MY_CPU_LE @@ -621,19 +630,42 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const propType == NPropDataType::kUtf16z) { unsigned len = size / 2 - 1; + // (len) doesn't include null terminator + + /* + #if WCHAR_MAX > 0xffff + len = (unsigned)Utf16LE__Get_Num_WCHARs(p, len); + + wchar_t *s = result.GetBuf(len); + wchar_t *sEnd = Utf16LE__To_WCHARs_Sep(p, len, s); + if (s + len != sEnd) return E_FAIL; + *sEnd = 0; + + #else + */ + wchar_t *s = result.GetBuf(len); for (unsigned i = 0; i < len; i++) { wchar_t c = GetUi16(p); p = (const void *)((const Byte *)p + 2); + #if WCHAR_PATH_SEPARATOR != L'/' if (c == L'/') c = WCHAR_PATH_SEPARATOR; + else if (c == L'\\') + c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme #endif + *s++ = c; } *s = 0; + + // #endif + result.ReleaseBuf_SetLen(len); + + Convert_UnicodeEsc16_To_UnicodeEscHigh(result); if (len != 0) return S_OK; } @@ -721,6 +753,8 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const if (result.IsEmpty()) return GetDefaultItemPath(index, result); + + Convert_UnicodeEsc16_To_UnicodeEscHigh(result); return S_OK; } @@ -772,7 +806,7 @@ int FindAltStreamColon_in_Path(const wchar_t *path) if (c == ':') { if (colonPos < 0) - colonPos = i; + colonPos = (int)i; continue; } if (c == WCHAR_PATH_SEPARATOR) @@ -865,8 +899,8 @@ HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const int colon = FindAltStreamColon_in_Path(item.Path); if (colon >= 0) { - item.MainPath.DeleteFrom(colon); - item.AltStreamName = item.Path.Ptr(colon + 1); + item.MainPath.DeleteFrom((unsigned)colon); + item.AltStreamName = item.Path.Ptr((unsigned)(colon + 1)); item.MainIsDir = (colon == 0 || IsPathSepar(item.Path[(unsigned)colon - 1])); item.IsAltStream = true; } @@ -877,7 +911,7 @@ HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const #ifndef _SFX if (item._use_baseParentFolder_mode) { - RINOK(GetItemPathToParent(mainIndex, item._baseParentFolder, item.PathParts)); + RINOK(GetItemPathToParent(mainIndex, (unsigned)item._baseParentFolder, item.PathParts)); #ifdef SUPPORT_ALT_STREAMS if ((item.WriteToAltStreamIfColon || needFindAltStream) && !item.PathParts.IsEmpty()) @@ -888,10 +922,10 @@ HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const colon = FindAltStreamColon_in_Path(s); if (colon >= 0) { - item.AltStreamName = s.Ptr(colon + 1); + item.AltStreamName = s.Ptr((unsigned)(colon + 1)); item.MainIsDir = (colon == 0 || IsPathSepar(s[(unsigned)colon - 1])); item.IsAltStream = true; - s.DeleteFrom(colon); + s.DeleteFrom((unsigned)colon); } } if (colon == 0) @@ -1007,9 +1041,9 @@ static void MakeCheckOrder(CCodecs *codecs, FOR_VECTOR (k, sigs) { const CByteBuffer &sig = sigs[k]; - if (sig.Size() == 0 && dataSize == 0 || - sig.Size() != 0 && sig.Size() <= dataSize && - TestSignature(data, sig, sig.Size())) + if ((sig.Size() == 0 && dataSize == 0) + || (sig.Size() != 0 && sig.Size() <= dataSize + && TestSignature(data, sig, sig.Size()))) { orderIndices2.Add(index); orderIndices[i] = -1; @@ -1019,8 +1053,6 @@ static void MakeCheckOrder(CCodecs *codecs, } } -#endif - #ifdef UNDER_CE static const unsigned kNumHashBytes = 1; #define HASH_VAL(buf) ((buf)[0]) @@ -1030,9 +1062,6 @@ static void MakeCheckOrder(CCodecs *codecs, #define HASH_VAL(buf) GetUi16(buf) #endif - -#ifndef _SFX - static bool IsExeExt(const UString &ext) { return ext.IsEqualTo_Ascii_NoCase("exe"); @@ -1243,11 +1272,11 @@ HRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openR bool offsetDefined; RINOK(Archive_GetArcProp_Int(archive, kpidOffset, Offset, offsetDefined)); - Int64 globalOffset = startPos + Offset; - AvailPhySize = FileSize - globalOffset; + Int64 globalOffset = (Int64)startPos + Offset; + AvailPhySize = (UInt64)((Int64)FileSize - globalOffset); if (PhySizeDefined) { - UInt64 endPos = globalOffset + PhySize; + UInt64 endPos = (UInt64)(globalOffset + (Int64)PhySize); if (endPos < FileSize) { AvailPhySize = PhySize; @@ -1263,11 +1292,12 @@ HRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openR } /* -static PrintNumber(const char *s, int n) +static void PrintNumber(const char *s, int n) { char temp[100]; sprintf(temp, "%s %d", s, n); - OutputDebugStringA(temp); + // OutputDebugStringA(temp); + printf(temp); } */ @@ -1286,7 +1316,7 @@ HRESULT CArc::PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyCom { const CArcInfoEx &ai = op.codecs->Formats[formatIndex]; if (ai.LibIndex >= 0 ? - !op.codecs->Libs[ai.LibIndex].SetCodecs : + !op.codecs->Libs[(unsigned)ai.LibIndex].SetCodecs : !op.codecs->Libs.IsEmpty()) { CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; @@ -1437,7 +1467,7 @@ HRESULT CArc::CheckZerosTail(const COpenOptions &op, UInt64 offset) { if (!op.stream) return S_OK; - RINOK(op.stream->Seek(offset, STREAM_SEEK_SET, NULL)); + RINOK(op.stream->Seek((Int64)offset, STREAM_SEEK_SET, NULL)); const UInt32 kBufSize = 1 << 11; Byte buf[kBufSize]; @@ -1463,6 +1493,8 @@ HRESULT CArc::CheckZerosTail(const COpenOptions &op, UInt64 offset) } } + + #ifndef _SFX class CExtractCallback_To_OpenCallback: @@ -1510,7 +1542,7 @@ STDMETHODIMP CExtractCallback_To_OpenCallback::SetRatioInfo(const UInt64 *inSize STDMETHODIMP CExtractCallback_To_OpenCallback::GetStream(UInt32 /* index */, ISequentialOutStream **outStream, Int32 /* askExtractMode */) { - *outStream = 0; + *outStream = NULL; return S_OK; } @@ -1524,6 +1556,7 @@ STDMETHODIMP CExtractCallback_To_OpenCallback::SetOperationResult(Int32 /* opera return S_OK; } + static HRESULT OpenArchiveSpec(IInArchive *archive, bool needPhySize, IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback, @@ -1547,22 +1580,32 @@ static HRESULT OpenArchiveSpec(IInArchive *archive, bool needPhySize, if (phySize_Defined) return S_OK; - bool phySizeCantBeDetected = false;; + bool phySizeCantBeDetected = false; RINOK(Archive_GetArcBoolProp(archive, kpidPhySizeCantBeDetected, phySizeCantBeDetected)); if (!phySizeCantBeDetected) { - RINOK(archive->Extract(0, (UInt32)(Int32)-1, BoolToInt(true), extractCallback)); + PRF(printf("\n-- !phySize_Defined after Open, call archive->Extract()")); + // It's for bzip2/gz and some xz archives, where Open operation doesn't know phySize. + // But the Handler will know phySize after full archive testing. + RINOK(archive->Extract(NULL, (UInt32)(Int32)-1, BoolToInt(true), extractCallback)); + PRF(printf("\n-- OK")); } } return S_OK; } + + static int FindFormatForArchiveType(CCodecs *codecs, CIntVector orderIndices, const char *name) { FOR_VECTOR (i, orderIndices) - if (StringsAreEqualNoCase_Ascii(codecs->Formats[orderIndices[i]].Name, name)) - return i; + { + int oi = orderIndices[i]; + if (oi >= 0) + if (StringsAreEqualNoCase_Ascii(codecs->Formats[(unsigned)oi].Name, name)) + return (int)i; + } return -1; } @@ -1590,7 +1633,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) { int dotPos = fileName.ReverseFind_Dot(); if (dotPos >= 0) - extension = fileName.Ptr(dotPos + 1); + extension = fileName.Ptr((unsigned)(dotPos + 1)); } CIntVector orderIndices; @@ -1615,13 +1658,18 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) bool isUnknownExt = false; #endif + #ifndef _SFX bool isForced = false; + #endif + unsigned numMainTypes = 0; int formatIndex = op.openType.FormatIndex; if (formatIndex >= 0) { + #ifndef _SFX isForced = true; + #endif orderIndices.Add(formatIndex); numMainTypes = 1; isMainFormatArr[(unsigned)formatIndex] = true; @@ -1658,10 +1706,12 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) isNumber = true; } if (isNumber) + { if (c == 'z' || c == 'Z') isZip = true; else isRar = true; + } } #endif @@ -1673,7 +1723,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) if (IgnoreSplit || !op.openType.CanReturnArc) if (ai.IsSplit()) continue; - if (op.excludedFormats->FindInSorted(i) >= 0) + if (op.excludedFormats->FindInSorted((int)i) >= 0) continue; #ifndef _SFX @@ -1683,17 +1733,17 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) if (ai.FindExtension(extension) >= 0 #ifndef _SFX - || isZip && StringsAreEqualNoCase_Ascii(ai.Name, "zip") - || isRar && StringsAreEqualNoCase_Ascii(ai.Name, "rar") + || (isZip && StringsAreEqualNoCase_Ascii(ai.Name, "zip")) + || (isRar && StringsAreEqualNoCase_Ascii(ai.Name, "rar")) #endif ) { // PrintNumber("orderIndices.Insert", i); - orderIndices.Insert(numFinded++, i); + orderIndices.Insert(numFinded++, (int)i); isMainFormatArr[i] = true; } else - orderIndices.Add(i); + orderIndices.Add((int)i); } } @@ -1739,8 +1789,8 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) const Byte kRarHeader[] = { 0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 }; if (TestSignature(buf, kRarHeader, 7) && buf[9] == 0x73 && (buf[10] & 1) != 0) { - orderIndices2.Add(orderIndices[i]); - orderIndices[i] = -1; + orderIndices2.Add(orderIndices[(unsigned)i]); + orderIndices[(unsigned)i] = -1; if (i >= (int)numFinded) numFinded++; } @@ -1785,10 +1835,10 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) int iUdf = FindFormatForArchiveType(op.codecs, orderIndices, "udf"); if (iUdf > iIso && iIso >= 0) { - int isoIndex = orderIndices[iIso]; - int udfIndex = orderIndices[iUdf]; - orderIndices[iUdf] = isoIndex; - orderIndices[iIso] = udfIndex; + int isoIndex = orderIndices[(unsigned)iIso]; + int udfIndex = orderIndices[(unsigned)iUdf]; + orderIndices[(unsigned)iUdf] = isoIndex; + orderIndices[(unsigned)iIso] = udfIndex; } } @@ -1842,12 +1892,14 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) for (unsigned i = 0; i < numCheckTypes; i++) { FormatIndex = orderIndices[i]; + + // orderIndices[] item cannot be negative here bool exactOnly = false; #ifndef _SFX - const CArcInfoEx &ai = op.codecs->Formats[FormatIndex]; + const CArcInfoEx &ai = op.codecs->Formats[(unsigned)FormatIndex]; // OutputDebugStringW(ai.Name); if (i >= numMainTypes) { @@ -1871,7 +1923,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) CMyComPtr<IInArchive> archive; - RINOK(PrepareToOpen(op, FormatIndex, archive)); + RINOK(PrepareToOpen(op, (unsigned)FormatIndex, archive)); if (!archive) continue; @@ -1948,7 +2000,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) bool thereIsTail = ErrorInfo.ThereIsTail; if (thereIsTail && mode.ZerosTailIsAllowed) { - RINOK(CheckZerosTail(op, Offset + PhySize)); + RINOK(CheckZerosTail(op, (UInt64)(Offset + (Int64)PhySize))); if (ErrorInfo.IgnoreTail) thereIsTail = false; } @@ -2063,16 +2115,22 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) for (i = 0; i < orderIndices.Size(); i++) { - unsigned form = orderIndices[i]; + // orderIndices[] item cannot be negative here + unsigned form = (unsigned)orderIndices[i]; if (skipFrontalFormat[form]) continue; + const CArcInfoEx &ai = op.codecs->Formats[form]; + if (ai.IsSplit()) { - splitIndex = form; + splitIndex = (int)form; continue; } + if (ai.Flags_ByExtOnlyOpen()) + continue; + if (ai.IsArcFunc) { UInt32 isArcRes = ai.IsArcFunc(byteBuffer, processedSize); @@ -2118,12 +2176,12 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) } if (splitIndex >= 0) - sortedFormats.Insert(0, splitIndex); + sortedFormats.Insert(0, (unsigned)splitIndex); for (i = 0; i < sortedFormats.Size(); i++) { - FormatIndex = sortedFormats[i]; - const CArcInfoEx &ai = op.codecs->Formats[FormatIndex]; + FormatIndex = (int)sortedFormats[i]; + const CArcInfoEx &ai = op.codecs->Formats[(unsigned)FormatIndex]; if (op.callback) RINOK(op.callback->SetTotal(NULL, &fileSize)); @@ -2131,7 +2189,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); CMyComPtr<IInArchive> archive; - RINOK(PrepareToOpen(op, FormatIndex, archive)); + RINOK(PrepareToOpen(op, (unsigned)FormatIndex, archive)); if (!archive) continue; @@ -2144,7 +2202,10 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) result = archive->Open(op.stream, &searchLimit, op.callback); else */ - result = OpenArchiveSpec(archive, !mode.CanReturnArc, op.stream, &searchLimit, op.callback, extractCallback_To_OpenCallback); + // if (!CanReturnArc), it's ParserMode, and we need phy size + result = OpenArchiveSpec(archive, + !mode.CanReturnArc, // needPhySize + op.stream, &searchLimit, op.callback, extractCallback_To_OpenCallback); } if (result == S_FALSE) @@ -2166,7 +2227,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) } NArchive::NParser::CParseItem pi; - pi.Offset = Offset; + pi.Offset = (UInt64)Offset; pi.Size = AvailPhySize; // bool needScan = false; @@ -2203,7 +2264,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) { if (mode.ZerosTailIsAllowed) { - RINOK(CheckZerosTail(op, Offset + PhySize)); + RINOK(CheckZerosTail(op, (UInt64)(Offset + (Int64)PhySize))); if (ErrorInfo.IgnoreTail) openCur = true; } @@ -2299,6 +2360,8 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) if (index < 0) continue; const CArcInfoEx &ai = op.codecs->Formats[(unsigned)index]; + if (ai.Flags_ByExtOnlyOpen()) + continue; bool isDifficult = false; // if (ai.Version < 0x91F) // we don't use parser with old DLL (before 9.31) if (!ai.NewInterface) @@ -2329,7 +2392,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) } if (isDifficult) { - difficultFormats.Add(index); + difficultFormats.Add((unsigned)index); difficultBools[(unsigned)index] = true; } } @@ -2398,7 +2461,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) size_t processedSize = kBufSize - bytesInBuf; // printf("\nRead ask = %d", (unsigned)processedSize); UInt64 seekPos = bufPhyPos + bytesInBuf; - RINOK(op.stream->Seek(bufPhyPos + bytesInBuf, STREAM_SEEK_SET, NULL)); + RINOK(op.stream->Seek((Int64)(bufPhyPos + bytesInBuf), STREAM_SEEK_SET, NULL)); RINOK(ReadStream(op.stream, byteBuffer + bytesInBuf, &processedSize)); // printf(" processed = %d", (unsigned)processedSize); if (processedSize == 0) @@ -2471,7 +2534,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) } } - size_t availSize = bytesInBuf - (size_t)posInBuf; + const size_t availSize = bytesInBuf - (size_t)posInBuf; if (availSize < kNumHashBytes) break; size_t scanSize = availSize - @@ -2502,7 +2565,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) if (!needCheckStartOpen) { for (; buf < bufLimit && hash[HASH_VAL(buf)] == 0xFF; buf++); - ppp = buf - (byteBuffer + (size_t)posInBuf); + ppp = (size_t)(buf - (byteBuffer + (size_t)posInBuf)); pos += ppp; if (buf == bufLimit) continue; @@ -2599,13 +2662,9 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) // printf("\nIsArc OK: %S", (const wchar_t *)ai.Name); } - /* - if (pos == 67109888) - pos = pos; - */ PRF(printf("\npos = %9I64d : %S", pos, (const wchar_t *)ai.Name)); - bool isMainFormat = isMainFormatArr[index]; + const bool isMainFormat = isMainFormatArr[index]; const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt); CMyComPtr<IInArchive> archive; @@ -2615,14 +2674,14 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) // OutputDebugStringW(ai.Name); - UInt64 rem = fileSize - startArcPos; + const UInt64 rem = fileSize - startArcPos; UInt64 arcStreamOffset = 0; if (ai.Flags_UseGlobalOffset()) { limitedStreamSpec->InitAndSeek(0, fileSize); - limitedStream->Seek(startArcPos, STREAM_SEEK_SET, NULL); + limitedStream->Seek((Int64)startArcPos, STREAM_SEEK_SET, NULL); } else { @@ -2642,20 +2701,23 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) extractCallback_To_OpenCallback_Spec->Files = 0; extractCallback_To_OpenCallback_Spec->Offset = startArcPos; - HRESULT result = OpenArchiveSpec(archive, true, limitedStream, &maxCheckStartPosition, + HRESULT result = OpenArchiveSpec(archive, + true, // needPhySize + limitedStream, &maxCheckStartPosition, useOffsetCallback ? (IArchiveOpenCallback *)openCallback_Offset : (IArchiveOpenCallback *)op.callback, extractCallback_To_OpenCallback); RINOK(ReadBasicProps(archive, ai.Flags_UseGlobalOffset() ? 0 : startArcPos, result)); bool isOpen = false; + if (result == S_FALSE) { if (!mode.CanReturnParser) { if (formatIndex < 0 && ErrorInfo.IsArc_After_NonOpen()) { - ErrorInfo.ErrorFormatIndex = index; + ErrorInfo.ErrorFormatIndex = (int)index; NonOpen_ErrorInfo = ErrorInfo; // if archive was detected, we don't need additional open attempts return S_FALSE; @@ -2667,6 +2729,12 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) } else { + if (PhySizeDefined && PhySize == 0) + { + PRF(printf(" phySizeDefined && PhySize == 0 ")); + // we skip that epmty archive case with unusual unexpected (PhySize == 0) from Code function. + continue; + } isOpen = true; RINOK(result); PRF(printf(" OK ")); @@ -2680,9 +2748,10 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) pi.Offset = startArcPos; if (ai.Flags_UseGlobalOffset()) - pi.Offset = Offset; + pi.Offset = (UInt64)Offset; else if (Offset != 0) return E_FAIL; + UInt64 arcRem = FileSize - pi.Offset; UInt64 phySize = arcRem; bool phySizeDefined = PhySizeDefined; @@ -2714,7 +2783,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) if (isOpen && !phySizeDefined) { - // it's for Z format + // it's for Z format, or bzip2,gz,xz with phySize that was not detected pi.LenIsUnknown = true; needScan = true; phySize = arcRem; @@ -2786,7 +2855,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) bool thereIsTail = ErrorInfo.ThereIsTail; if (thereIsTail && mode.ZerosTailIsAllowed) { - RINOK(CheckZerosTail(op, arcStreamOffset + Offset + PhySize)); + RINOK(CheckZerosTail(op, (UInt64)((Int64)arcStreamOffset + Offset + (Int64)PhySize))); if (ErrorInfo.IgnoreTail) thereIsTail = false; } @@ -2794,10 +2863,12 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) if (pi.Offset != 0) { if (!pi.IsNotArcType) + { if (thereIsTail) openCur = specFlags.CanReturnMid; else openCur = specFlags.CanReturnTail; + } } else { @@ -2805,11 +2876,11 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) openCur = true; else openCur = specFlags.CanReturnFrontal; - if (formatIndex >= -2) openCur = true; } + if (formatIndex < 0 && pi.IsSelfExe /* && mode.SkipSfxStub */) openCur = false; @@ -2836,7 +2907,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) { InStream = op.stream; Archive = archive; - FormatIndex = index; + FormatIndex = (int)index; ArcStreamOffset = arcStreamOffset; return S_OK; } @@ -2850,7 +2921,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) } */ - pi.FormatIndex = index; + pi.FormatIndex = (int)index; // printf("\nAdd offset = %d", (int)pi.Offset); handlerSpec->AddItem(pi); @@ -2905,6 +2976,9 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) return S_OK; } + + + HRESULT CArc::OpenStream(const COpenOptions &op) { RINOK(OpenStream2(op)); @@ -2929,13 +3003,13 @@ HRESULT CArc::OpenStream(const COpenOptions &op) { int dotPos = fileName.ReverseFind_Dot(); if (dotPos >= 0) - extension = fileName.Ptr(dotPos + 1); + extension = fileName.Ptr((unsigned)(dotPos + 1)); } DefaultName.Empty(); if (FormatIndex >= 0) { - const CArcInfoEx &ai = op.codecs->Formats[FormatIndex]; + const CArcInfoEx &ai = op.codecs->Formats[(unsigned)FormatIndex]; if (ai.Exts.Size() == 0) DefaultName = GetDefaultName2(fileName, UString(), UString()); else @@ -2943,7 +3017,7 @@ HRESULT CArc::OpenStream(const COpenOptions &op) int subExtIndex = ai.FindExtension(extension); if (subExtIndex < 0) subExtIndex = 0; - const CArcExtInfo &extInfo = ai.Exts[subExtIndex]; + const CArcExtInfo &extInfo = ai.Exts[(unsigned)subExtIndex]; DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt); } } @@ -2981,9 +3055,7 @@ HRESULT CArc::OpenStreamOrFile(COpenOptions &op) fileStream = fileStreamSpec; Path = filePath; if (!fileStreamSpec->Open(us2fs(Path))) - { - return GetLastError(); - } + return GetLastError_noZero_HRESULT(); op.stream = fileStream; #ifdef _SFX IgnoreSplit = true; @@ -3288,7 +3360,7 @@ HRESULT CArchiveLink::Open2(COpenOptions &op, IOpenCallbackUI *callbackUI) if (!op.stream && !op.stdInMode) { NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), prefix, name); - openCallbackSpec->Init(prefix, name); + RINOK(openCallbackSpec->Init2(prefix, name)); } else { @@ -3340,7 +3412,7 @@ HRESULT CArc::ReOpen(const COpenOptions &op) CTailInStream *tailStreamSpec = new CTailInStream; stream2 = tailStreamSpec; tailStreamSpec->Stream = op.stream; - tailStreamSpec->Offset = globalOffset; + tailStreamSpec->Offset = (UInt64)globalOffset; tailStreamSpec->Init(); RINOK(tailStreamSpec->SeekToStart()); } @@ -3352,8 +3424,8 @@ HRESULT CArc::ReOpen(const COpenOptions &op) if (res == S_OK) { - RINOK(ReadBasicProps(Archive, globalOffset, res)); - ArcStreamOffset = globalOffset; + RINOK(ReadBasicProps(Archive, (UInt64)globalOffset, res)); + ArcStreamOffset = (UInt64)globalOffset; if (ArcStreamOffset != 0) InStream = op.stream; } @@ -3393,14 +3465,14 @@ HRESULT CArchiveLink::ReOpen(COpenOptions &op) { FString dirPrefix, fileName; NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), dirPrefix, fileName); - openCallbackSpec->Init(dirPrefix, fileName); + RINOK(openCallbackSpec->Init2(dirPrefix, fileName)); } CInFileStream *fileStreamSpec = new CInFileStream; CMyComPtr<IInStream> stream(fileStreamSpec); if (!fileStreamSpec->Open(us2fs(op.filePath))) - return GetLastError(); + return GetLastError_noZero_HRESULT(); op.stream = stream; CArc &arc = Arcs[0]; @@ -3415,6 +3487,7 @@ HRESULT CArchiveLink::ReOpen(COpenOptions &op) #ifndef _SFX +bool ParseComplexSize(const wchar_t *s, UInt64 &result); bool ParseComplexSize(const wchar_t *s, UInt64 &result) { result = 0; @@ -3472,7 +3545,7 @@ static bool ParseTypeParams(const UString &s, COpenType &type) return false; } -bool ParseType(CCodecs &codecs, const UString &s, COpenType &type) +static bool ParseType(CCodecs &codecs, const UString &s, COpenType &type) { int pos2 = s.Find(L':'); @@ -3481,11 +3554,11 @@ bool ParseType(CCodecs &codecs, const UString &s, COpenType &type) if (pos2 < 0) { name = s; - pos2 = s.Len(); + pos2 = (int)s.Len(); } else { - name = s.Left(pos2); + name = s.Left((unsigned)pos2); pos2++; } @@ -3514,17 +3587,17 @@ bool ParseType(CCodecs &codecs, const UString &s, COpenType &type) } - for (unsigned i = pos2; i < s.Len();) + for (unsigned i = (unsigned)pos2; i < s.Len();) { int next = s.Find(L':', i); if (next < 0) - next = s.Len(); - const UString name = s.Mid(i, next - i); + next = (int)s.Len(); + const UString name = s.Mid(i, (unsigned)next - i); if (name.IsEmpty()) return false; if (!ParseTypeParams(name, type)) return false; - i = next + 1; + i = (unsigned)next + 1; } return true; @@ -3537,15 +3610,15 @@ bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> { int pos2 = s.Find(L'.', pos); if (pos2 < 0) - pos2 = s.Len(); - UString name = s.Mid(pos, pos2 - pos); + pos2 = (int)s.Len(); + UString name = s.Mid(pos, (unsigned)pos2 - pos); if (name.IsEmpty()) return false; COpenType type; if (!ParseType(codecs, name, type)) return false; types.Add(type); - pos = pos2 + 1; + pos = (unsigned)pos2 + 1; } return true; } diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h index 6eb0d395..ebeb91d1 100644 --- a/CPP/7zip/UI/Common/OpenArchive.h +++ b/CPP/7zip/UI/Common/OpenArchive.h @@ -88,9 +88,9 @@ struct COpenType COpenType(): FormatIndex(-1), Recursive(true), - EachPos(false), CanReturnArc(true), CanReturnParser(false), + EachPos(false), // SkipSfxStub(true), // ExeAsUnknown(true), ZerosTailIsAllowed(false), @@ -121,7 +121,7 @@ struct COpenOptions IInStream *stream; ISequentialInStream *seqStream; IArchiveOpenCallback *callback; - COpenCallbackImp *callbackSpec; + COpenCallbackImp *callbackSpec; // it's used for SFX only OPEN_PROPS_DECL // bool openOnlySpecifiedByExtension, @@ -286,7 +286,7 @@ public: UString filePath; UString DefaultName; int FormatIndex; // - 1 means Parser. - int SubfileIndex; + UInt32 SubfileIndex; // (UInt32)(Int32)-1; means no subfile FILETIME MTime; bool MTimeDefined; @@ -302,7 +302,7 @@ public: UInt64 GetEstmatedPhySize() const { return PhySizeDefined ? PhySize : FileSize; } UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler - Int64 GetGlobalOffset() const { return ArcStreamOffset + Offset; } // it's global offset of archive + Int64 GetGlobalOffset() const { return (Int64)ArcStreamOffset + Offset; } // it's global offset of archive // AString ErrorFlagsText; @@ -397,6 +397,13 @@ struct CArchiveLink IArchiveGetRawProps *GetArchiveGetRawProps() const { return Arcs.Back().GetRawProps; } IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; } + /* + Open() opens archive and COpenOptions::callback + Open2() uses COpenCallbackImp that implements Volumes and password callback + Open3() calls Open2() and callbackUI->Open_Finished(); + Open_Strict() returns S_FALSE also in case, if there is non-open expected nested archive. + */ + HRESULT Open(COpenOptions &options); HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI); HRESULT Open3(COpenOptions &options, IOpenCallbackUI *callbackUI); diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp index 7702e222..30efd53b 100644 --- a/CPP/7zip/UI/Common/PropIDUtils.cpp +++ b/CPP/7zip/UI/Common/PropIDUtils.cpp @@ -14,8 +14,10 @@ #include "PropIDUtils.h" +#ifndef _SFX #define Get16(x) GetUi16(x) #define Get32(x) GetUi32(x) +#endif using namespace NWindows; @@ -63,9 +65,9 @@ static void ConvertPosixAttribToString(char *s, UInt32 a) throw() s[8 - i] = MY_ATTR_CHAR(a, i + 1, 'w'); s[9 - i] = MY_ATTR_CHAR(a, i + 0, 'x'); } - if ((a & 0x800) != 0) s[3] = ((a & (1 << 6)) ? 's' : 'S'); - if ((a & 0x400) != 0) s[6] = ((a & (1 << 3)) ? 's' : 'S'); - if ((a & 0x200) != 0) s[9] = ((a & (1 << 0)) ? 't' : 'T'); + if ((a & 0x800) != 0) s[3] = ((a & (1 << 6)) ? 's' : 'S'); // S_ISUID + if ((a & 0x400) != 0) s[6] = ((a & (1 << 3)) ? 's' : 'S'); // S_ISGID + if ((a & 0x200) != 0) s[9] = ((a & (1 << 0)) ? 't' : 'T'); // S_ISVTX s[10] = 0; a &= ~(UInt32)0xFFFF; @@ -213,13 +215,13 @@ void ConvertPropertyToString2(UString &dest, const PROPVARIANT &prop, PROPID pro dest = temp; } +#ifndef _SFX + static inline unsigned GetHex(unsigned v) { return (v < 10) ? ('0' + v) : ('A' + (v - 10)); } -#ifndef _SFX - static inline void AddHexToString(AString &res, unsigned v) { res += (char)GetHex(v >> 4); @@ -272,7 +274,7 @@ static int FindPairIndex(const CSecID2Name * pairs, unsigned num, UInt32 id) { for (unsigned i = 0; i < num; i++) if (pairs[i].n == id) - return i; + return (int)i; return -1; } @@ -479,11 +481,16 @@ static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName */ } +/* #define MY_SE_OWNER_DEFAULTED (0x0001) #define MY_SE_GROUP_DEFAULTED (0x0002) +*/ #define MY_SE_DACL_PRESENT (0x0004) +/* #define MY_SE_DACL_DEFAULTED (0x0008) +*/ #define MY_SE_SACL_PRESENT (0x0010) +/* #define MY_SE_SACL_DEFAULTED (0x0020) #define MY_SE_DACL_AUTO_INHERIT_REQ (0x0100) #define MY_SE_SACL_AUTO_INHERIT_REQ (0x0200) @@ -493,6 +500,7 @@ static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName #define MY_SE_SACL_PROTECTED (0x2000) #define MY_SE_RM_CONTROL_VALID (0x4000) #define MY_SE_SELF_RELATIVE (0x8000) +*/ void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s) { @@ -590,25 +598,45 @@ static const CSecID2Name k_ReparseTags[] = { 0x80000014, "NFS" }, { 0x80000015, "FILE_PLACEHOLDER" }, { 0x80000016, "DFM" }, - { 0x80000017, "WOF" } + { 0x80000017, "WOF" }, + { 0x80000018, "WCI" }, + { 0x8000001B, "APPEXECLINK" }, + { 0xA000001D, "LX_SYMLINK" }, + { 0x80000023, "AF_UNIX" }, + { 0x80000024, "LX_FIFO" }, + { 0x80000025, "LX_CHR" }, + { 0x80000026, "LX_BLK" } }; bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s) { s.Empty(); NFile::CReparseAttr attr; - DWORD errorCode = 0; - if (attr.Parse(data, size, errorCode)) + + if (attr.Parse(data, size)) { - if (!attr.IsSymLink()) - s += "Junction: "; - s += attr.GetPath(); - if (!attr.IsOkNamePair()) + if (attr.IsSymLink_WSL()) { - s += " : "; - s += attr.PrintName; + s += "WSL: "; + s += attr.GetPath(); + } + else + { + if (!attr.IsSymLink_Win()) + s += "Junction: "; + s += attr.GetPath(); + if (s.IsEmpty()) + s += "Link: "; + if (!attr.IsOkNamePair()) + { + s += " : "; + s += attr.PrintName; + } } + if (attr.MinorError) + s += " : MINOR_ERROR"; return true; + // s += " "; // for debug } if (size < 8) @@ -651,7 +679,7 @@ bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s) for (UInt32 i = 0; i < len; i++) { - if (i >= 8) + if (i >= 16) { s += "..."; break; diff --git a/CPP/7zip/UI/Common/SetProperties.cpp b/CPP/7zip/UI/Common/SetProperties.cpp index c3de5d5a..4b3037af 100644 --- a/CPP/7zip/UI/Common/SetProperties.cpp +++ b/CPP/7zip/UI/Common/SetProperties.cpp @@ -27,6 +27,21 @@ static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop) prop = result; } + +struct CPropPropetiesVector +{ + CPropVariant *values; + CPropPropetiesVector(unsigned num) + { + values = new CPropVariant[num]; + } + ~CPropPropetiesVector() + { + delete []values; + } +}; + + HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties) { if (properties.IsEmpty()) @@ -37,8 +52,7 @@ HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &propert return S_OK; UStringVector realNames; - CPropVariant *values = new CPropVariant[properties.Size()]; - try + CPropPropetiesVector values(properties.Size()); { unsigned i; for (i = 0; i < properties.Size(); i++) @@ -62,19 +76,12 @@ HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &propert else ParseNumberString(property.Value, propVariant); realNames.Add(name); - values[i] = propVariant; + values.values[i] = propVariant; } CRecordVector<const wchar_t *> names; for (i = 0; i < realNames.Size(); i++) names.Add((const wchar_t *)realNames[i]); - RINOK(setProperties->SetProperties(&names.Front(), values, names.Size())); - } - catch(...) - { - delete []values; - throw; + return setProperties->SetProperties(&names.Front(), values.values, names.Size()); } - delete []values; - return S_OK; } diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp index 8c7ae45f..fc922a70 100644 --- a/CPP/7zip/UI/Common/Update.cpp +++ b/CPP/7zip/UI/Common/Update.cpp @@ -32,7 +32,7 @@ static const char * const kUpdateIsNotSupoorted = "update operations are not supported for this archive"; -static const char * const kUpdateIsNotSupoorted_MultiVol = +static const char * const kUpdateIsNotSupported_MultiVol = "Updating for multivolume archives is not implemented"; using namespace NWindows; @@ -41,8 +41,9 @@ using namespace NFile; using namespace NDir; using namespace NName; +#ifdef _WIN32 static CFSTR const kTempFolderPrefix = FTEXT("7zE"); - +#endif void CUpdateErrorInfo::SetFromLastError(const char *message) { @@ -57,26 +58,12 @@ HRESULT CUpdateErrorInfo::SetFromLastError(const char *message, const FString &f return Get_HRESULT_Error(); } -static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path) +HRESULT CUpdateErrorInfo::SetFromError_DWORD(const char *message, const FString &fileName, DWORD error) { - NFind::CFileInfo fileInfo; - FString pathPrefix = path + FCHAR_PATH_SEPARATOR; - { - NFind::CEnumerator enumerator; - enumerator.SetDirPrefix(pathPrefix); - while (enumerator.Next(fileInfo)) - { - if (fileInfo.IsDir()) - if (!DeleteEmptyFolderAndEmptySubFolders(pathPrefix + fileInfo.Name)) - return false; - } - } - /* - // we don't need clear read-only for folders - if (!MySetFileAttributes(path, 0)) - return false; - */ - return RemoveDir(path); + Message = message; + FileNames.Add(fileName); + SystemError = error; + return Get_HRESULT_Error(); } @@ -175,7 +162,7 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr altStream.StreamSpec = new COutFileStream; altStream.Stream = altStream.StreamSpec; if (!altStream.StreamSpec->Create(name, false)) - return ::GetLastError(); + return GetLastError_noZero_HRESULT(); { // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS); TempFiles->Paths.Add(name); @@ -204,14 +191,14 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr { // CMyComPtr<IOutStream> outStream; // RINOK(altStream.Stream.QueryInterface(IID_IOutStream, &outStream)); - RINOK(altStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); + RINOK(altStream.Stream->Seek((Int64)_offsetPos, STREAM_SEEK_SET, NULL)); altStream.Pos = _offsetPos; } UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - altStream.Pos); UInt32 realProcessed; RINOK(altStream.Stream->Write(data, curSize, &realProcessed)); - data = (void *)((Byte *)data + realProcessed); + data = (const void *)((const Byte *)data + realProcessed); size -= realProcessed; altStream.Pos += realProcessed; _offsetPos += realProcessed; @@ -240,9 +227,9 @@ STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *n return STG_E_INVALIDFUNCTION; switch (seekOrigin) { - case STREAM_SEEK_SET: _absPos = offset; break; - case STREAM_SEEK_CUR: _absPos += offset; break; - case STREAM_SEEK_END: _absPos = _length + offset; break; + case STREAM_SEEK_SET: _absPos = (UInt64)offset; break; + case STREAM_SEEK_CUR: _absPos = (UInt64)((Int64)_absPos + offset); break; + case STREAM_SEEK_END: _absPos = (UInt64)((Int64)_length + offset); break; } _offsetPos = _absPos; if (newPosition) @@ -298,11 +285,11 @@ void CArchivePath::ParseFromPath(const UString &path, EArcNameMode mode) Name.DeleteBack(); else { - const UString ext = Name.Ptr(dotPos + 1); + const UString ext = Name.Ptr((unsigned)(dotPos + 1)); if (BaseExtension.IsEqualTo_NoCase(ext)) { BaseExtension = ext; - Name.DeleteFrom(dotPos); + Name.DeleteFrom((unsigned)dotPos); return; } } @@ -392,7 +379,7 @@ bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath) } else { - const CArcInfoEx &arcInfo = codecs->Formats[formatIndex]; + const CArcInfoEx &arcInfo = codecs->Formats[(unsigned)formatIndex]; if (!arcInfo.UpdateEnabled) return false; typeExt = arcInfo.GetMainExt(); @@ -417,8 +404,8 @@ bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath) struct CUpdateProduceCallbackImp: public IUpdateProduceCallback { const CObjectVector<CArcItem> *_arcItems; - IUpdateCallbackUI *_callback; CDirItemsStat *_stat; + IUpdateCallbackUI *_callback; CUpdateProduceCallbackImp( const CObjectVector<CArcItem> *a, @@ -541,7 +528,7 @@ static HRESULT Compress( } else { - RINOK(codecs->CreateOutArchive(formatIndex, outArchive)); + RINOK(codecs->CreateOutArchive((unsigned)formatIndex, outArchive)); #ifdef EXTERNAL_CODECS { @@ -576,7 +563,7 @@ static HRESULT Compress( } { - const CArcInfoEx &arcInfo = codecs->Formats[formatIndex]; + const CArcInfoEx &arcInfo = codecs->Formats[(unsigned)formatIndex]; if (options.AltStreams.Val && !arcInfo.Flags_AltStreams()) return E_NOTIMPL; if (options.NtSecurity.Val && !arcInfo.Flags_NtSecure()) @@ -614,7 +601,7 @@ static HRESULT Compress( int colonPos = FindAltStreamColon_in_Path(ai.Name); if (colonPos >= 0) { - UString mainName = ai.Name.Left(colonPos); + UString mainName = ai.Name.Left((unsigned)colonPos); /* actually we must improve that code to support cases with folder renaming like: rn arc dir1\ dir2\ @@ -623,7 +610,7 @@ static HRESULT Compress( { needRename = true; dest += ':'; - dest += ai.Name.Ptr(colonPos + 1); + dest += ai.Name.Ptr((unsigned)(colonPos + 1)); break; } } @@ -638,7 +625,7 @@ static HRESULT Compress( { up2.NewProps = true; RINOK(arc->IsItemAnti(i, up2.IsAnti)); - up2.NewNameIndex = newNames.Add(dest); + up2.NewNameIndex = (int)newNames.Add(dest); } updatePairs2.Add(up2); } @@ -664,7 +651,7 @@ static HRESULT Compress( if (up.ExistOnDisk()) { CDirItemsStat2 &stat = stat2.NewData; - const CDirItem &di = dirItems.Items[up.DirIndex]; + const CDirItem &di = dirItems.Items[(unsigned)up.DirIndex]; if (di.IsDir()) { if (up.IsAnti) @@ -697,7 +684,7 @@ static HRESULT Compress( else if (up.ArcIndex >= 0) { CDirItemsStat2 &stat = *(up.NewData ? &stat2.NewData : &stat2.OldData); - const CArcItem &ai = arcItems[up.ArcIndex]; + const CArcItem &ai = arcItems[(unsigned)up.ArcIndex]; if (ai.IsDir) { if (up.IsAnti) @@ -733,6 +720,7 @@ static HRESULT Compress( CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec); + updateCallbackSpec->PreserveATime = options.PreserveATime; updateCallbackSpec->ShareForWrite = options.OpenShareForWrite; updateCallbackSpec->StopAfterOpenError = options.StopAfterOpenError; updateCallbackSpec->StdInMode = options.StdInMode; @@ -922,9 +910,9 @@ static HRESULT Compress( CUpdatePair2 &pair2 = updatePairs2[i]; const FILETIME *ft2 = NULL; if (pair2.NewProps && pair2.DirIndex >= 0) - ft2 = &dirItems.Items[pair2.DirIndex].MTime; + ft2 = &dirItems.Items[(unsigned)pair2.DirIndex].MTime; else if (pair2.UseArcProps && pair2.ArcIndex >= 0) - ft2 = &arcItems[pair2.ArcIndex].MTime; + ft2 = &arcItems[(unsigned)pair2.ArcIndex].MTime; if (ft2) { if (::CompareFileTime(&ft, ft2) < 0) @@ -936,7 +924,7 @@ static HRESULT Compress( if (outStreamSpec) outStreamSpec->SetMTime(&ft); else if (volStreamSpec) - volStreamSpec->SetMTime(&ft);; + volStreamSpec->SetMTime(&ft); } } @@ -1041,7 +1029,7 @@ static HRESULT EnumerateInArchiveItems( #if defined(_WIN32) && !defined(UNDER_CE) -#include <mapi.h> +#include <MAPI.h> #endif @@ -1074,7 +1062,7 @@ HRESULT UpdateArchive( if (options.Commands.Size() != 1) return E_NOTIMPL; const CActionSet &as = options.Commands[0].ActionSet; - for (int i = 2; i < NPairState::kNumValues; i++) + for (unsigned i = 2; i < NPairState::kNumValues; i++) if (as.StateActions[i] != NPairAction::kCompress) return E_NOTIMPL; } @@ -1103,7 +1091,7 @@ HRESULT UpdateArchive( if (options.SfxModule.Find(FCHAR_PATH_SEPARATOR) < 0) { const FString fullName = NDLL::GetModuleDirPrefix() + options.SfxModule; - if (NFind::DoesFileExist(fullName)) + if (NFind::DoesFileExist_FollowLink(fullName)) { options.SfxModule = fullName; found = true; @@ -1111,7 +1099,7 @@ HRESULT UpdateArchive( } if (!found) { - if (!NFind::DoesFileExist(options.SfxModule)) + if (!NFind::DoesFileExist_FollowLink(options.SfxModule)) return errorInfo.SetFromLastError("cannot find specified SFX module", options.SfxModule); } } @@ -1143,7 +1131,7 @@ HRESULT UpdateArchive( else { NFind::CFileInfo fi; - if (!fi.Find(us2fs(arcPath))) + if (!fi.Find_FollowLink(us2fs(arcPath))) { if (renameMode) throw "can't find archive";; @@ -1156,24 +1144,35 @@ HRESULT UpdateArchive( else { if (fi.IsDir()) - throw "there is no such archive"; + return errorInfo.SetFromError_DWORD("There is a folder with the name of archive", + us2fs(arcPath), + #ifdef _WIN32 + ERROR_ACCESS_DENIED + #else + EISDIR + #endif + ); if (fi.IsDevice) return E_NOTIMPL; if (!options.StdOutMode && options.UpdateArchiveItself) if (fi.IsReadOnly()) { - errorInfo.SystemError = ERROR_ACCESS_DENIED; - errorInfo.Message = "The file is read-only"; - errorInfo.FileNames.Add(us2fs(arcPath)); - return errorInfo.Get_HRESULT_Error(); + return errorInfo.SetFromError_DWORD("The file is read-only", + us2fs(arcPath), + #ifdef _WIN32 + ERROR_ACCESS_DENIED + #else + EACCES + #endif + ); } if (options.VolumesSizes.Size() > 0) { errorInfo.FileNames.Add(us2fs(arcPath)); - errorInfo.SystemError = (DWORD)E_NOTIMPL; - errorInfo.Message = kUpdateIsNotSupoorted_MultiVol; + // errorInfo.SystemError = (DWORD)E_NOTIMPL; + errorInfo.Message = kUpdateIsNotSupported_MultiVol; return E_NOTIMPL; } CObjectVector<COpenType> types2; @@ -1211,8 +1210,8 @@ HRESULT UpdateArchive( if (arcLink.VolumePaths.Size() > 1) { - errorInfo.SystemError = (DWORD)E_NOTIMPL; - errorInfo.Message = kUpdateIsNotSupoorted_MultiVol; + // errorInfo.SystemError = (DWORD)E_NOTIMPL; + errorInfo.Message = kUpdateIsNotSupported_MultiVol; return E_NOTIMPL; } @@ -1222,7 +1221,7 @@ HRESULT UpdateArchive( if (arc.ErrorInfo.ThereIsTail) { - errorInfo.SystemError = (DWORD)E_NOTIMPL; + // errorInfo.SystemError = (DWORD)E_NOTIMPL; errorInfo.Message = "There is some data block after the end of the archive"; return E_NOTIMPL; } @@ -1292,7 +1291,7 @@ HRESULT UpdateArchive( HRESULT res = EnumerateItems(censor, options.PathMode, - options.AddPathPrefix, + UString(), // options.AddPathPrefix, dirItems); if (res != S_OK) @@ -1332,8 +1331,6 @@ HRESULT UpdateArchive( dirItems.AddSecurityItem(prefix, secureIndex); #endif parentDirItem.SecureIndex = secureIndex; - - parentDirItem_Ptr = &parentDirItem; } } } @@ -1565,7 +1562,7 @@ HRESULT UpdateArchive( } */ - LPMAPISENDMAIL sendMail = (LPMAPISENDMAIL)mapiLib.GetProc("MAPISendMail"); + LPMAPISENDMAIL sendMail = (LPMAPISENDMAIL)(void *)mapiLib.GetProc("MAPISendMail"); if (sendMail == 0) { errorInfo.SetFromLastError("7-Zip cannot find MAPISendMail function"); @@ -1610,8 +1607,8 @@ HRESULT UpdateArchive( MapiFileDesc &f = files[i]; memset(&f, 0, sizeof(f)); f.nPosition = 0xFFFFFFFF; - f.lpszPathName = (char *)(const char *)paths[i]; - f.lpszFileName = (char *)(const char *)names[i]; + f.lpszPathName = paths[i].Ptr_non_const(); + f.lpszFileName = names[i].Ptr_non_const(); } { @@ -1626,7 +1623,7 @@ HRESULT UpdateArchive( { memset(&rec, 0, sizeof(rec)); rec.ulRecipClass = MAPI_TO; - rec.lpszAddress = (char *)(const char *)addr; + rec.lpszAddress = addr.Ptr_non_const(); m.nRecipCount = 1; m.lpRecips = &rec; } @@ -1660,8 +1657,12 @@ HRESULT UpdateArchive( if (processedItems[i] != 0 || dirItem.Size == 0) { NFind::CFileInfo fileInfo; + /* here we compare Raw FileInfo that can be link with actual file info that was processed. + we can fix it. */ if (fileInfo.Find(phyPath)) { + // FIXME: here we can check Find_FollowLink() also; + // maybe we must exclude also files with archive name: "a a.7z * -sdel" if (fileInfo.Size == dirItem.Size && CompareFileTime(&fileInfo.MTime, &dirItem.MTime) == 0 diff --git a/CPP/7zip/UI/Common/Update.h b/CPP/7zip/UI/Common/Update.h index dc9ff5d3..06d13877 100644 --- a/CPP/7zip/UI/Common/Update.h +++ b/CPP/7zip/UI/Common/Update.h @@ -18,7 +18,7 @@ enum EArcNameMode { k_ArcNameMode_Smart, k_ArcNameMode_Exact, - k_ArcNameMode_Add, + k_ArcNameMode_Add }; struct CArchivePath @@ -91,6 +91,7 @@ struct CUpdateOptions bool SfxMode; FString SfxModule; + bool PreserveATime; bool OpenShareForWrite; bool StopAfterOpenError; @@ -104,7 +105,7 @@ struct CUpdateOptions FString WorkingDir; NWildcard::ECensorPathMode PathMode; - UString AddPathPrefix; + // UString AddPathPrefix; CBoolPair NtSecurity; CBoolPair AltStreams; @@ -122,20 +123,26 @@ struct CUpdateOptions CUpdateOptions(): UpdateArchiveItself(true), + ArcNameMode(k_ArcNameMode_Smart), + SfxMode(false), + + PreserveATime(false), + OpenShareForWrite(false), + StopAfterOpenError(false), + StdInMode(false), StdOutMode(false), + EMailMode(false), EMailRemoveAfter(false), - OpenShareForWrite(false), - StopAfterOpenError(false), - ArcNameMode(k_ArcNameMode_Smart), + PathMode(NWildcard::k_RelatPath), DeleteAfterCompressing(false), SetArcMTime(false) - {}; + {}; void SetActionCommand_Add() { @@ -150,7 +157,7 @@ struct CUpdateOptions struct CUpdateErrorInfo { - DWORD SystemError; + DWORD SystemError; // it's DWORD (WRes) only; AString Message; FStringVector FileNames; @@ -158,6 +165,7 @@ struct CUpdateErrorInfo HRESULT Get_HRESULT_Error() const { return SystemError == 0 ? E_FAIL : HRESULT_FROM_WIN32(SystemError); } void SetFromLastError(const char *message); HRESULT SetFromLastError(const char *message, const FString &fileName); + HRESULT SetFromError_DWORD(const char *message, const FString &fileName, DWORD error); CUpdateErrorInfo(): SystemError(0) {}; }; diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp index fd46dda8..69cde093 100644 --- a/CPP/7zip/UI/Common/UpdateCallback.cpp +++ b/CPP/7zip/UI/Common/UpdateCallback.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +// #include <stdio.h> + #ifndef _7ZIP_ST #include "../../../Windows/Synchronization.h" #endif @@ -10,6 +12,7 @@ #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #include "../../../Common/Wildcard.h" +#include "../../../Common/UTFConvert.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileName.h" @@ -54,6 +57,7 @@ CArchiveUpdateCallback::CArchiveUpdateCallback(): CommentIndex(-1), Comment(NULL), + PreserveATime(false), ShareForWrite(false), StopAfterOpenError(false), StdInMode(false), @@ -124,7 +128,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index, { *indexInArchive = (UInt32)(Int32)-1; if (up.ExistInArchive()) - *indexInArchive = (ArcItems == 0) ? up.ArcIndex : (*ArcItems)[up.ArcIndex].IndexInServer; + *indexInArchive = ArcItems ? (*ArcItems)[(unsigned)up.ArcIndex].IndexInServer : (UInt32)(Int32)up.ArcIndex; } return S_OK; COM_TRY_END @@ -188,7 +192,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetRootRawProp(PROPID { if (ParentDirItem->SecureIndex < 0) return S_OK; - const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[ParentDirItem->SecureIndex]; + const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[(unsigned)ParentDirItem->SecureIndex]; *data = buf; *dataSize = (UInt32)buf.Size(); *propType = NPropDataType::kRaw; @@ -220,7 +224,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetRawProp(UInt32 index, PROPID propID, con const CUpdatePair2 &up = (*UpdatePairs)[index]; if (up.UseArcProps && up.ExistInArchive() && Arc->GetRawProps) return Arc->GetRawProps->GetRawProp( - ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex, + ArcItems ? (*ArcItems)[(unsigned)up.ArcIndex].IndexInServer : (UInt32)(Int32)up.ArcIndex, propID, data, dataSize, propType); { /* @@ -230,8 +234,8 @@ STDMETHODIMP CArchiveUpdateCallback::GetRawProp(UInt32 index, PROPID propID, con if (up.IsAnti) return S_OK; - #ifndef UNDER_CE - const CDirItem &di = DirItems->Items[up.DirIndex]; + #if defined(_WIN32) && !defined(UNDER_CE) + const CDirItem &di = DirItems->Items[(unsigned)up.DirIndex]; #endif #ifdef _USE_SECURITY_CODE @@ -241,18 +245,19 @@ STDMETHODIMP CArchiveUpdateCallback::GetRawProp(UInt32 index, PROPID propID, con return S_OK; if (di.SecureIndex < 0) return S_OK; - const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[di.SecureIndex]; + const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[(unsigned)di.SecureIndex]; *data = buf; *dataSize = (UInt32)buf.Size(); *propType = NPropDataType::kRaw; } else #endif + if (propID == kpidNtReparse) { - // propID == kpidNtReparse if (!StoreSymLinks) return S_OK; - #ifndef UNDER_CE + #if defined(_WIN32) && !defined(UNDER_CE) + // we use ReparseData2 instead of ReparseData for WIM format const CByteBuffer *buf = &di.ReparseData2; if (buf->Size() == 0) buf = &di.ReparseData; @@ -272,7 +277,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetRawProp(UInt32 index, PROPID propID, con return S_OK; } -#ifndef UNDER_CE +#if defined(_WIN32) && !defined(UNDER_CE) static UString GetRelativePath(const UString &to, const UString &from) { @@ -340,22 +345,25 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR prop.Detach(value); return S_OK; } + + #if !defined(UNDER_CE) + if (up.DirIndex >= 0) { - #ifndef UNDER_CE - const CDirItem &di = DirItems->Items[up.DirIndex]; + const CDirItem &di = DirItems->Items[(unsigned)up.DirIndex]; + + #ifdef _WIN32 // if (di.IsDir()) { CReparseAttr attr; - DWORD errorCode = 0; - if (attr.Parse(di.ReparseData, di.ReparseData.Size(), errorCode)) + if (attr.Parse(di.ReparseData, di.ReparseData.Size())) { UString simpleName = attr.GetPath(); - if (attr.IsRelative()) + if (!attr.IsSymLink_WSL() && attr.IsRelative_Win()) prop = simpleName; else { - const FString phyPath = DirItems->GetPhyPath(up.DirIndex); + const FString phyPath = DirItems->GetPhyPath((unsigned)up.DirIndex); FString fullPath; if (NDir::MyGetFullPathName(phyPath, fullPath)) { @@ -366,8 +374,26 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR return S_OK; } } - #endif + + #else // _WIN32 + + if (di.ReparseData.Size() != 0) + { + AString utf; + utf.SetFrom_CalcLen((const char *)(const Byte *)di.ReparseData, (unsigned)di.ReparseData.Size()); + + UString us; + if (ConvertUTF8ToUnicode(utf, us)) + { + prop = us; + prop.Detach(value); + return S_OK; + } + } + + #endif // _WIN32 } + #endif // !defined(UNDER_CE) } else if (propID == kpidHardLink) { @@ -375,7 +401,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR { const CKeyKeyValPair &pair = _map[_hardIndex_To]; const CUpdatePair2 &up2 = (*UpdatePairs)[pair.Value]; - prop = DirItems->GetLogPath(up2.DirIndex); + prop = DirItems->GetLogPath((unsigned)up2.DirIndex); prop.Detach(value); return S_OK; } @@ -399,7 +425,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR } } else if (propID == kpidPath && up.NewNameIndex >= 0) - prop = (*NewNames)[up.NewNameIndex]; + prop = (*NewNames)[(unsigned)up.NewNameIndex]; else if (propID == kpidComment && CommentIndex >= 0 && (unsigned)CommentIndex == index @@ -411,13 +437,13 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR } else if ((up.UseArcProps || (KeepOriginalItemNames && (propID == kpidPath || propID == kpidIsAltStream))) && up.ExistInArchive() && Archive) - return Archive->GetProperty(ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex, propID, value); + return Archive->GetProperty(ArcItems ? (*ArcItems)[(unsigned)up.ArcIndex].IndexInServer : (UInt32)(Int32)up.ArcIndex, propID, value); else if (up.ExistOnDisk()) { - const CDirItem &di = DirItems->Items[up.DirIndex]; + const CDirItem &di = DirItems->Items[(unsigned)up.DirIndex]; switch (propID) { - case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break; + case kpidPath: prop = DirItems->GetLogPath((unsigned)up.DirIndex); break; case kpidIsDir: prop = di.IsDir(); break; case kpidSize: prop = di.IsDir() ? (UInt64)0 : di.Size; break; case kpidAttrib: prop = di.Attrib; break; @@ -428,6 +454,16 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR #if defined(_WIN32) && !defined(UNDER_CE) // case kpidShortName: prop = di.ShortName; break; #endif + case kpidPosixAttrib: + { + #ifdef _WIN32 + prop = di.GetPosixAttrib(); + #else + if (di.Attrib & FILE_ATTRIBUTE_UNIX_EXTENSION) + prop = (UInt32)(di.Attrib >> 16); + #endif + break; + } } } prop.Detach(value); @@ -456,9 +492,9 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStrea { UString name; if (up.ArcIndex >= 0) - name = (*ArcItems)[up.ArcIndex].Name; + name = (*ArcItems)[(unsigned)up.ArcIndex].Name; else if (up.DirIndex >= 0) - name = DirItems->GetLogPath(up.DirIndex); + name = DirItems->GetLogPath((unsigned)up.DirIndex); RINOK(Callback->GetStream(name, isDir, true, mode)); /* 9.33: fixed. Handlers expect real stream object for files, even for anti-file. @@ -474,7 +510,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStrea return S_OK; } - RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), isDir, false, mode)); + RINOK(Callback->GetStream(DirItems->GetLogPath((unsigned)up.DirIndex), isDir, false, mode)); if (isDir) return S_OK; @@ -491,27 +527,42 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStrea } else { + #if !defined(UNDER_CE) + const CDirItem &di = DirItems->Items[(unsigned)up.DirIndex]; + if (di.AreReparseData()) + { + /* + // we still need DeviceIoControlOut() instead of Read + if (!inStreamSpec->File.OpenReparse(path)) + { + return Callback->OpenFileError(path, ::GetLastError()); + } + */ + // 20.03: we use Reparse Data instead of real data + + CBufInStream *inStreamSpec = new CBufInStream(); + CMyComPtr<ISequentialInStream> inStreamLoc = inStreamSpec; + inStreamSpec->Init(di.ReparseData, di.ReparseData.Size()); + *inStream = inStreamLoc.Detach(); + return S_OK; + } + #endif // !defined(UNDER_CE) + CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); inStreamSpec->SupportHardLinks = StoreHardLinks; - inStreamSpec->Callback = this; - inStreamSpec->CallbackRef = index; + inStreamSpec->File.PreserveATime = PreserveATime; - const FString path = DirItems->GetPhyPath(up.DirIndex); + const FString path = DirItems->GetPhyPath((unsigned)up.DirIndex); _openFiles_Indexes.Add(index); _openFiles_Paths.Add(path); - #if defined(_WIN32) && !defined(UNDER_CE) - if (DirItems->Items[up.DirIndex].AreReparseData()) - { - if (!inStreamSpec->File.OpenReparse(path)) - { - return Callback->OpenFileError(path, ::GetLastError()); - } - } - else - #endif + /* 21.02 : we set Callback/CallbackRef after _openFiles_Indexes adding + for correct working if exception was raised in GetPhyPath */ + inStreamSpec->Callback = this; + inStreamSpec->CallbackRef = index; + if (!inStreamSpec->OpenShared(path, ShareForWrite)) { DWORD error = ::GetLastError(); @@ -522,6 +573,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStrea return hres; } + // #if defined(USE_WIN_FILE) || !defined(_WIN32) if (StoreHardLinks) { CStreamFileProps props; @@ -546,6 +598,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStrea } } } + // #endif if (ProcessedItemsStatuses) { @@ -592,8 +645,8 @@ STDMETHODIMP CArchiveUpdateCallback::ReportOperation(UInt32 indexType, UInt32 in const CUpdatePair2 &up = (*UpdatePairs)[index]; if (up.ExistOnDisk()) { - name = DirItems->GetLogPath(up.DirIndex); - isDir = DirItems->Items[up.DirIndex].IsDir(); + name = DirItems->GetLogPath((unsigned)up.DirIndex); + isDir = DirItems->Items[(unsigned)up.DirIndex].IsDir(); } } return Callback->ReportUpdateOpeartion(op, name.IsEmpty() ? NULL : name.Ptr(), isDir); @@ -716,7 +769,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOu COutFileStream *streamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> streamLoc(streamSpec); if (!streamSpec->Create(fileName, false)) - return ::GetLastError(); + return GetLastError_noZero_HRESULT(); *volumeStream = streamLoc.Detach(); return S_OK; COM_TRY_END @@ -738,7 +791,10 @@ STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword(BSTR *password) HRESULT CArchiveUpdateCallback::InFileStream_On_Error(UINT_PTR val, DWORD error) { - if (error == ERROR_LOCK_VIOLATION) + #ifdef _WIN32 // FIX IT !!! + // why did we check only for ERROR_LOCK_VIOLATION ? + // if (error == ERROR_LOCK_VIOLATION) + #endif { MT_LOCK UInt32 index = (UInt32)val; @@ -756,6 +812,7 @@ HRESULT CArchiveUpdateCallback::InFileStream_On_Error(UINT_PTR val, DWORD error) void CArchiveUpdateCallback::InFileStream_On_Destroy(UINT_PTR val) { + { MT_LOCK UInt32 index = (UInt32)val; FOR_VECTOR(i, _openFiles_Indexes) @@ -767,5 +824,11 @@ void CArchiveUpdateCallback::InFileStream_On_Destroy(UINT_PTR val) return; } } - throw 20141125; + } + /* 21.02 : this function can be called in destructor. + And destructor can be called after some exception. + If we don't want to throw exception in desctructors or after another exceptions, + we must disable the code below that raises new exception. + */ + // throw 20141125; } diff --git a/CPP/7zip/UI/Common/UpdateCallback.h b/CPP/7zip/UI/Common/UpdateCallback.h index 9e6925f6..3fe0a647 100644 --- a/CPP/7zip/UI/Common/UpdateCallback.h +++ b/CPP/7zip/UI/Common/UpdateCallback.h @@ -135,6 +135,7 @@ public: int CommentIndex; const UString *Comment; + bool PreserveATime; bool ShareForWrite; bool StopAfterOpenError; bool StdInMode; @@ -152,9 +153,9 @@ public: bool IsDir(const CUpdatePair2 &up) const { if (up.DirIndex >= 0) - return DirItems->Items[up.DirIndex].IsDir(); + return DirItems->Items[(unsigned)up.DirIndex].IsDir(); else if (up.ArcIndex >= 0) - return (*ArcItems)[up.ArcIndex].IsDir; + return (*ArcItems)[(unsigned)up.ArcIndex].IsDir; return false; } }; diff --git a/CPP/7zip/UI/Common/UpdatePair.cpp b/CPP/7zip/UI/Common/UpdatePair.cpp index 82876c1d..31d73f94 100644 --- a/CPP/7zip/UI/Common/UpdatePair.cpp +++ b/CPP/7zip/UI/Common/UpdatePair.cpp @@ -42,7 +42,9 @@ static const char * const k_Duplicate_inArc_Message = "Duplicate filename in arc static const char * const k_Duplicate_inDir_Message = "Duplicate filename on disk:"; static const char * const k_NotCensoredCollision_Message = "Internal file name collision (file on disk, file in archive):"; -static void ThrowError(const char *message, const UString &s1, const UString &s2) +MY_ATTR_NORETURN +static +void ThrowError(const char *message, const UString &s1, const UString &s2) { UString m (message); m.Add_LF(); m += s1; @@ -144,18 +146,18 @@ void GetUpdatePairInfoList( if (dirIndex < numDirItems) { - dirIndex2 = dirIndices[dirIndex]; - di = &dirItems.Items[dirIndex2]; + dirIndex2 = (int)dirIndices[dirIndex]; + di = &dirItems.Items[(unsigned)dirIndex2]; } if (arcIndex < numArcItems) { - arcIndex2 = arcIndices[arcIndex]; - ai = &arcItems[arcIndex2]; + arcIndex2 = (int)arcIndices[arcIndex]; + ai = &arcItems[(unsigned)arcIndex2]; compareResult = 1; if (dirIndex < numDirItems) { - compareResult = CompareFileNames(dirNames[dirIndex2], ai->Name); + compareResult = CompareFileNames(dirNames[(unsigned)dirIndex2], ai->Name); if (compareResult == 0) { if (di->IsDir() != ai->IsDir) @@ -166,7 +168,7 @@ void GetUpdatePairInfoList( if (compareResult < 0) { - name = &dirNames[dirIndex2]; + name = &dirNames[(unsigned)dirIndex2]; pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirIndex = dirIndex2; dirIndex++; @@ -184,9 +186,9 @@ void GetUpdatePairInfoList( { int dupl = duplicatedArcItem[arcIndex]; if (dupl != 0) - ThrowError(k_Duplicate_inArc_Message, ai->Name, arcItems[arcIndices[arcIndex + dupl]].Name); + ThrowError(k_Duplicate_inArc_Message, ai->Name, arcItems[arcIndices[(unsigned)((int)arcIndex + dupl)]].Name); - name = &dirNames[dirIndex2]; + name = &dirNames[(unsigned)dirIndex2]; if (!ai->Censored) ThrowError(k_NotCensoredCollision_Message, *name, ai->Name); @@ -222,7 +224,7 @@ void GetUpdatePairInfoList( } else { - prevHostFile = updatePairs.Size(); + prevHostFile = (int)updatePairs.Size(); prevHostName = name; } diff --git a/CPP/7zip/UI/Common/UpdateProduce.cpp b/CPP/7zip/UI/Common/UpdateProduce.cpp index d5052f13..fa4bd69c 100644 --- a/CPP/7zip/UI/Common/UpdateProduce.cpp +++ b/CPP/7zip/UI/Common/UpdateProduce.cpp @@ -28,7 +28,7 @@ void UpdateProduce( { case NPairAction::kIgnore: if (pair.ArcIndex >= 0 && callback) - callback->ShowDeleteFile(pair.ArcIndex); + callback->ShowDeleteFile((unsigned)pair.ArcIndex); continue; case NPairAction::kCopy: @@ -43,7 +43,7 @@ void UpdateProduce( 1) no such alt stream in Disk 2) there is Host file in disk */ - if (updatePairs[pair.HostIndex].DirIndex >= 0) + if (updatePairs[(unsigned)pair.HostIndex].DirIndex >= 0) continue; } } diff --git a/CPP/7zip/UI/Common/UpdateProduce.h b/CPP/7zip/UI/Common/UpdateProduce.h index 64c58cc5..595370fe 100644 --- a/CPP/7zip/UI/Common/UpdateProduce.h +++ b/CPP/7zip/UI/Common/UpdateProduce.h @@ -18,12 +18,12 @@ struct CUpdatePair2 bool IsMainRenameItem; - void SetAs_NoChangeArcItem(int arcIndex) + void SetAs_NoChangeArcItem(unsigned arcIndex) // int { NewData = NewProps = false; UseArcProps = true; IsAnti = false; - ArcIndex = arcIndex; + ArcIndex = (int)arcIndex; } bool ExistOnDisk() const { return DirIndex != -1; } diff --git a/CPP/7zip/UI/Common/WorkDir.cpp b/CPP/7zip/UI/Common/WorkDir.cpp index 284eaa16..1307ceeb 100644 --- a/CPP/7zip/UI/Common/WorkDir.cpp +++ b/CPP/7zip/UI/Common/WorkDir.cpp @@ -5,6 +5,7 @@ #include "../../../Common/StringConvert.h" #include "../../../Common/Wildcard.h" +#include "../../../Windows/FileFind.h" #include "../../../Windows/FileName.h" #include "WorkDir.h" @@ -39,13 +40,13 @@ FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FStr #endif int pos = path.ReverseFind_PathSepar() + 1; - fileName = path.Ptr(pos); + fileName = path.Ptr((unsigned)pos); switch (mode) { case NWorkDir::NMode::kCurrent: { - return path.Left(pos); + return path.Left((unsigned)pos); } case NWorkDir::NMode::kSpecified: { @@ -75,8 +76,7 @@ HRESULT CWorkDirTempFile::CreateTempFile(const FString &originalPath) OutStream = _outStreamSpec; if (!_tempFile.Create(workDir + namePart, &_outStreamSpec->File)) { - DWORD error = GetLastError(); - return error ? error : E_FAIL; + return GetLastError_noZero_HRESULT(); } _originalPath = originalPath; return S_OK; @@ -87,8 +87,7 @@ HRESULT CWorkDirTempFile::MoveToOriginal(bool deleteOriginal) OutStream.Release(); if (!_tempFile.MoveTo(_originalPath, deleteOriginal)) { - DWORD error = GetLastError(); - return error ? error : E_FAIL; + return GetLastError_noZero_HRESULT(); } return S_OK; } diff --git a/CPP/7zip/UI/Console/Console.dsp b/CPP/7zip/UI/Console/Console.dsp index 34918e38..53ec5525 100644 --- a/CPP/7zip/UI/Console/Console.dsp +++ b/CPP/7zip/UI/Console/Console.dsp @@ -357,6 +357,14 @@ SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File +SOURCE=..\..\..\Windows\SystemInfo.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\SystemInfo.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Windows\Thread.h # End Source File # Begin Source File diff --git a/CPP/7zip/UI/Console/ConsoleClose.cpp b/CPP/7zip/UI/Console/ConsoleClose.cpp index 703f8213..9e4c040d 100644 --- a/CPP/7zip/UI/Console/ConsoleClose.cpp +++ b/CPP/7zip/UI/Console/ConsoleClose.cpp @@ -4,8 +4,13 @@ #include "ConsoleClose.h" -#if !defined(UNDER_CE) && defined(_WIN32) +#ifndef UNDER_CE + +#ifdef _WIN32 #include "../../../Common/MyWindows.h" +#else +#include <stdlib.h> +#include <signal.h> #endif namespace NConsoleClose { @@ -13,7 +18,8 @@ namespace NConsoleClose { unsigned g_BreakCounter = 0; static const unsigned kBreakAbortThreshold = 2; -#if !defined(UNDER_CE) && defined(_WIN32) +#ifdef _WIN32 + static BOOL WINAPI HandlerRoutine(DWORD ctrlType) { if (ctrlType == CTRL_LOGOFF_EVENT) @@ -37,33 +43,58 @@ static BOOL WINAPI HandlerRoutine(DWORD ctrlType) return FALSE; */ } -#endif - -/* -void CheckCtrlBreak() -{ - if (TestBreakSignal()) - throw CCtrlBreakException(); -} -*/ CCtrlHandlerSetter::CCtrlHandlerSetter() { - #if !defined(UNDER_CE) && defined(_WIN32) if (!SetConsoleCtrlHandler(HandlerRoutine, TRUE)) throw "SetConsoleCtrlHandler fails"; - #endif } CCtrlHandlerSetter::~CCtrlHandlerSetter() { - #if !defined(UNDER_CE) && defined(_WIN32) if (!SetConsoleCtrlHandler(HandlerRoutine, FALSE)) { // warning for throw in destructor. // throw "SetConsoleCtrlHandler fails"; } - #endif } +#else // _WIN32 + +static void HandlerRoutine(int) +{ + g_BreakCounter++; + if (g_BreakCounter < kBreakAbortThreshold) + return; + exit(EXIT_FAILURE); +} + +CCtrlHandlerSetter::CCtrlHandlerSetter() +{ + memo_sig_int = signal(SIGINT, HandlerRoutine); // CTRL-C + if (memo_sig_int == SIG_ERR) + throw "SetConsoleCtrlHandler fails (SIGINT)"; + memo_sig_term = signal(SIGTERM, HandlerRoutine); // for kill -15 (before "kill -9") + if (memo_sig_term == SIG_ERR) + throw "SetConsoleCtrlHandler fails (SIGTERM)"; +} + +CCtrlHandlerSetter::~CCtrlHandlerSetter() +{ + signal(SIGINT, memo_sig_int); // CTRL-C + signal(SIGTERM, memo_sig_term); // kill {pid} +} + +#endif // _WIN32 + +/* +void CheckCtrlBreak() +{ + if (TestBreakSignal()) + throw CCtrlBreakException(); +} +*/ + } + +#endif diff --git a/CPP/7zip/UI/Console/ConsoleClose.h b/CPP/7zip/UI/Console/ConsoleClose.h index 11c1631c..9c9e035c 100644 --- a/CPP/7zip/UI/Console/ConsoleClose.h +++ b/CPP/7zip/UI/Console/ConsoleClose.h @@ -5,28 +5,34 @@ namespace NConsoleClose { +class CCtrlBreakException {}; + +#ifdef UNDER_CE + +inline bool TestBreakSignal() { return false; } +struct CCtrlHandlerSetter {}; + +#else + extern unsigned g_BreakCounter; inline bool TestBreakSignal() { - #ifdef UNDER_CE - return false; - #else return (g_BreakCounter != 0); - #endif } class CCtrlHandlerSetter { + #ifndef _WIN32 + void (*memo_sig_int)(int); + void (*memo_sig_term)(int); + #endif public: CCtrlHandlerSetter(); virtual ~CCtrlHandlerSetter(); }; -class CCtrlBreakException -{}; - -// void CheckCtrlBreak(); +#endif } diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp index 21c2f071..23eab615 100644 --- a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp +++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp @@ -69,6 +69,7 @@ HRESULT CExtractScanConsole::ScanError(const FString &path, DWORD systemError) } +void Print_UInt64_and_String(AString &s, UInt64 val, const char *name); void Print_UInt64_and_String(AString &s, UInt64 val, const char *name) { char temp[32]; @@ -78,6 +79,7 @@ void Print_UInt64_and_String(AString &s, UInt64 val, const char *name) s += name; } +void PrintSize_bytes_Smart(AString &s, UInt64 val); void PrintSize_bytes_Smart(AString &s, UInt64 val) { Print_UInt64_and_String(s, val, "bytes"); @@ -96,7 +98,7 @@ void PrintSize_bytes_Smart(AString &s, UInt64 val) s += ')'; } -void PrintSize_bytes_Smart_comma(AString &s, UInt64 val) +static void PrintSize_bytes_Smart_comma(AString &s, UInt64 val) { if (val == (UInt64)(Int64)-1) return; @@ -106,6 +108,7 @@ void PrintSize_bytes_Smart_comma(AString &s, UInt64 val) +void Print_DirItemsStat(AString &s, const CDirItemsStat &st); void Print_DirItemsStat(AString &s, const CDirItemsStat &st) { if (st.NumDirs != 0) @@ -124,6 +127,7 @@ void Print_DirItemsStat(AString &s, const CDirItemsStat &st) } +void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st); void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st) { Print_DirItemsStat(s, (CDirItemsStat &)st); @@ -184,9 +188,9 @@ static const char * const kTestString = "T"; static const char * const kExtractString = "-"; static const char * const kSkipString = "."; -// static const char * const kCantAutoRename = "can not create file with auto name\n"; -// static const char * const kCantRenameFile = "can not rename existing file\n"; -// static const char * const kCantDeleteOutputFile = "can not delete output file "; +// static const char * const kCantAutoRename = "cannot create file with auto name\n"; +// static const char * const kCantRenameFile = "cannot rename existing file\n"; +// static const char * const kCantDeleteOutputFile = "cannot delete output file "; static const char * const kMemoryExceptionMessage = "Can't allocate required memory!"; @@ -394,6 +398,7 @@ STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message) return CheckBreak2(); } +void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest); void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest) { dest.Empty(); @@ -436,7 +441,7 @@ void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest) else { dest += "Error #"; - dest.Add_UInt32(opRes); + dest.Add_UInt32((UInt32)opRes); } } @@ -566,6 +571,7 @@ static AString GetOpenArcErrorMessage(UInt32 errorFlags) return s; } +void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags); void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags) { if (errorFlags == 0) @@ -573,7 +579,7 @@ void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags) so << s << endl << GetOpenArcErrorMessage(errorFlags) << endl; } -void Add_Messsage_Pre_ArcType(UString &s, const char *pre, const wchar_t *arcType) +static void Add_Messsage_Pre_ArcType(UString &s, const char *pre, const wchar_t *arcType) { s.Add_LF(); s += pre; @@ -582,6 +588,7 @@ void Add_Messsage_Pre_ArcType(UString &s, const char *pre, const wchar_t *arcTyp s += "] archive"; } +void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc); void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc) { const CArcErrorInfo &er = arc.ErrorInfo; @@ -596,7 +603,7 @@ void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, c } else { - Add_Messsage_Pre_ArcType(s, "Can not open the file", codecs->GetFormatNamePtr(er.ErrorFormatIndex)); + Add_Messsage_Pre_ArcType(s, "Cannot open the file", codecs->GetFormatNamePtr(er.ErrorFormatIndex)); Add_Messsage_Pre_ArcType(s, "The file is open", codecs->GetFormatNamePtr(arc.FormatIndex)); } @@ -806,7 +813,9 @@ HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result) else { NumArcsWithError++; - if (result == E_ABORT || result == ERROR_DISK_FULL) + if (result == E_ABORT + || result == HRESULT_FROM_WIN32(ERROR_DISK_FULL) + ) return result; if (_se) diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.h b/CPP/7zip/UI/Console/ExtractCallbackConsole.h index dc659521..5ac1d0b0 100644 --- a/CPP/7zip/UI/Console/ExtractCallbackConsole.h +++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.h @@ -32,6 +32,9 @@ class CExtractScanConsole: public IDirItemsCallback } public: + + virtual ~CExtractScanConsole() {} + void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream) { _so = outStream; diff --git a/CPP/7zip/UI/Console/HashCon.cpp b/CPP/7zip/UI/Console/HashCon.cpp index 762b21bb..a70f5f8a 100644 --- a/CPP/7zip/UI/Console/HashCon.cpp +++ b/CPP/7zip/UI/Console/HashCon.cpp @@ -222,7 +222,8 @@ void CHashCallbackConsole::PrintResultLine(UInt64 fileSize, s[0] = 0; if (showHash) AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize); - SetSpacesAndNul(s + strlen(s), (int)GetColumnWidth(h.DigestSize) - (int)strlen(s)); + const unsigned pos = (unsigned)strlen(s); + SetSpacesAndNul(s + pos, GetColumnWidth(h.DigestSize) - pos); if (i != 0) _s.Add_Space(); _s += s; @@ -235,20 +236,15 @@ void CHashCallbackConsole::PrintResultLine(UInt64 fileSize, char s[kSizeField_Len + 32]; char *p = s; + SetSpacesAndNul(s, kSizeField_Len); if (showHash) { p = s + kSizeField_Len; ConvertUInt64ToString(fileSize, p); - int numSpaces = kSizeField_Len - (int)strlen(p); + int numSpaces = (int)kSizeField_Len - (int)strlen(p); if (numSpaces > 0) - { p -= (unsigned)numSpaces; - for (unsigned i = 0; i < (unsigned)numSpaces; i++) - p[i] = ' '; - } } - else - SetSpacesAndNul(s, kSizeField_Len); _s += p; } diff --git a/CPP/7zip/UI/Console/HashCon.h b/CPP/7zip/UI/Console/HashCon.h index 5b30b69a..0731bd18 100644 --- a/CPP/7zip/UI/Console/HashCon.h +++ b/CPP/7zip/UI/Console/HashCon.h @@ -38,7 +38,7 @@ public: PrintName(true) {} - ~CHashCallbackConsole() { } + virtual ~CHashCallbackConsole() {} INTERFACE_IHashCallbackUI(;) }; diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp index 416ef2c9..d6cb9825 100644 --- a/CPP/7zip/UI/Console/List.cpp +++ b/CPP/7zip/UI/Console/List.cpp @@ -351,7 +351,7 @@ struct CListStat2 AltStreams.Update(st.AltStreams); NumDirs += st.NumDirs; } - const UInt64 GetNumStreams() const { return MainFiles.NumFiles + AltStreams.NumFiles; } + UInt64 GetNumStreams() const { return MainFiles.NumFiles + AltStreams.NumFiles; } CListStat &GetStat(bool altStreamsMode) { return altStreamsMode ? AltStreams : MainFiles; } }; @@ -751,7 +751,7 @@ void CFieldPrinter::PrintSum(const CListStat2 &stat2) PrintSum(stat2.MainFiles, stat2.NumDirs, kString_Files); if (stat2.AltStreams.NumFiles != 0) { - PrintSum(stat2.AltStreams, 0, kString_AltStreams);; + PrintSum(stat2.AltStreams, 0, kString_AltStreams); CListStat st = stat2.MainFiles; st.Update(stat2.AltStreams); PrintSum(st, 0, kString_Streams); @@ -905,7 +905,7 @@ static HRESULT PrintArcProp(CStdOutStream &so, IInArchive *archive, PROPID propI static void PrintArcTypeError(CStdOutStream &so, const UString &type, bool isWarning) { so << "Open " << (isWarning ? "WARNING" : "ERROR") - << ": Can not open the file as [" + << ": Cannot open the file as [" << type << "] archive" << endl; @@ -926,6 +926,7 @@ static void ErrorInfo_Print(CStdOutStream &so, const CArcErrorInfo &er) PrintPropPair(so, "WARNING", er.WarningMessage, true); } +HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink) { FOR_VECTOR (r, arcLink.Arcs) @@ -990,11 +991,12 @@ HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const return S_OK; } +HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink) { #ifndef _NO_CRYPTO if (arcLink.PasswordWasAsked) - so << "Can not open encrypted archive. Wrong password?"; + so << "Cannot open encrypted archive. Wrong password?"; else #endif { @@ -1002,10 +1004,10 @@ HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const { so.NormalizePrint_UString(arcLink.NonOpen_ArcPath); so << endl; - PrintArcTypeError(so, codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false); + PrintArcTypeError(so, codecs->Formats[(unsigned)arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false); } else - so << "Can not open the file as archive"; + so << "Cannot open the file as archive"; } so << endl; @@ -1065,12 +1067,12 @@ HRESULT ListArchives(CCodecs *codecs, if (!stdInMode) { NFile::NFind::CFileInfo fi; - if (!fi.Find(us2fs(arcPath))) + if (!fi.Find_FollowLink(us2fs(arcPath))) { DWORD errorCode = GetLastError(); if (errorCode == 0) errorCode = ERROR_FILE_NOT_FOUND; - lastError = HRESULT_FROM_WIN32(lastError);; + lastError = HRESULT_FROM_WIN32(errorCode); g_StdOut.Flush(); if (g_ErrStream) { @@ -1279,7 +1281,7 @@ HRESULT ListArchives(CCodecs *codecs, } else { - SplitPathToParts(fp.FilePath, pathParts);; + SplitPathToParts(fp.FilePath, pathParts); bool include; if (!wildcardCensor.CheckPathVect(pathParts, !fp.IsDir, include)) continue; @@ -1331,7 +1333,7 @@ HRESULT ListArchives(CCodecs *codecs, { g_StdOut << "----------\n"; PrintPropPair(g_StdOut, "Path", arcLink.NonOpen_ArcPath, false); - PrintArcTypeError(g_StdOut, codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false); + PrintArcTypeError(g_StdOut, codecs->Formats[(unsigned)arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false); } } diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp index 333223bd..8c24aaff 100644 --- a/CPP/7zip/UI/Console/Main.cpp +++ b/CPP/7zip/UI/Console/Main.cpp @@ -6,6 +6,11 @@ #ifdef _WIN32 #include <Psapi.h> +#else +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/times.h> #endif #include "../../../../C/CpuArch.h" @@ -15,12 +20,13 @@ #include "../../../Common/CommandLineParser.h" #include "../../../Common/IntToString.h" #include "../../../Common/MyException.h" +#include "../../../Common/StdInStream.h" +#include "../../../Common/StdOutStream.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" #include "../../../Common/UTFConvert.h" #include "../../../Windows/ErrorMsg.h" - #include "../../../Windows/TimeUtils.h" #include "../Common/ArchiveCommandLine.h" @@ -37,12 +43,11 @@ #include "BenchCon.h" #include "ConsoleClose.h" #include "ExtractCallbackConsole.h" +#include "HashCon.h" #include "List.h" #include "OpenCallbackConsole.h" #include "UpdateCallbackConsole.h" -#include "HashCon.h" - #ifdef PROG_VARIANT_R #include "../../../../C/7zVersion.h" #else @@ -66,27 +71,30 @@ extern const CCodecInfo *g_Codecs[]; extern unsigned g_NumHashers; extern const CHasherInfo *g_Hashers[]; -static const char * const kCopyrightString = "\n7-Zip" - #ifndef EXTERNAL_CODECS - #ifdef PROG_VARIANT_R - " (r)" - #else - " (a)" - #endif - #endif +#if defined(PROG_VARIANT_Z) + #define PROG_POSTFIX "z" + #define PROG_POSTFIX_2 " (z)" +#elif defined(PROG_VARIANT_R) + #define PROG_POSTFIX "r" + #define PROG_POSTFIX_2 " (r)" +#elif !defined(EXTERNAL_CODECS) + #define PROG_POSTFIX "a" + #define PROG_POSTFIX_2 " (a)" +#else + #define PROG_POSTFIX "" + #define PROG_POSTFIX_2 "" +#endif + + +static const char * const kCopyrightString = "\n7-Zip" + PROG_POSTFIX_2 " " MY_VERSION_CPU - " : " MY_COPYRIGHT_DATE "\n\n"; + " : " MY_COPYRIGHT_DATE "\n"; static const char * const kHelpString = "Usage: 7z" -#ifndef EXTERNAL_CODECS -#ifdef PROG_VARIANT_R - "r" -#else - "a" -#endif -#endif + PROG_POSTFIX " <command> [<switches>...] <archive_name> [<file_names>...] [@listfile]\n" "\n" "<Commands>\n" @@ -141,6 +149,7 @@ static const char * const kHelpString = " -spf : use fully qualified file paths\n" " -ssc[-] : set sensitive case mode\n" " -sse : stop archive creating, if it can't open some input file\n" + " -ssp : do not change Last Access Time of source files while archiving\n" " -ssw : compress shared files\n" " -stl : set archive timestamp from the most recently modified file\n" " -stm{HexMask} : set CPU thread affinity mask (hexadecimal number)\n" @@ -163,6 +172,7 @@ static const char * const kUnsupportedArcTypeMessage = "Unsupported archive type #define kDefaultSfxModule "7zCon.sfx" +MY_ATTR_NORETURN static void ShowMessageAndThrowException(LPCSTR message, NExitCode::EEnum code) { if (g_ErrStream) @@ -170,15 +180,109 @@ static void ShowMessageAndThrowException(LPCSTR message, NExitCode::EEnum code) throw code; } -#ifndef _WIN32 -static void GetArguments(int numArgs, const char *args[], UStringVector &parts) + +#ifdef _WIN32 +#define ShowProgInfo(so) +#else +static void ShowProgInfo(CStdOutStream *so) { - parts.Clear(); - for (int i = 0; i < numArgs; i++) + if (!so) + return; + + *so + + /* + #ifdef __DATE__ + << " " << __DATE__ + #endif + #ifdef __TIME__ + << " " << __TIME__ + #endif + */ + + #ifdef __VERSION__ + << " compiler: " << __VERSION__ + #endif + + #ifdef __GNUC__ + << " GCC " << __GNUC__ << "." << __GNUC_MINOR__ << "." << __GNUC_PATCHLEVEL__ + #endif + + #ifdef __clang__ + << " CLANG " << __clang_major__ << "." << __clang_minor__ + #endif + + #ifdef __xlC__ + << " XLC " << (__xlC__ >> 8) << "." << (__xlC__ & 0xFF) + #ifdef __xlC_ver__ + << "." << (__xlC_ver__ >> 8) << "." << (__xlC_ver__ & 0xFF) + #endif + #endif + + #ifdef _MSC_VER + << " MSC " << _MSC_VER + #endif + + #ifdef __ARM_FEATURE_CRC32 + << " CRC32" + #endif + + << " " << (unsigned)(sizeof(void *)) * 8 << "-bit" + + #ifdef __ILP32__ + << " ILP32" + #endif + + #ifdef __ARM_ARCH + << " arm_v:" << __ARM_ARCH + #ifdef __ARM_ARCH_ISA_THUMB + << " thumb:" << __ARM_ARCH_ISA_THUMB + #endif + #endif + + + #ifdef ENV_HAVE_LOCALE + << " locale=" << GetLocale() + #endif + #ifndef _WIN32 + << " UTF8=" << (IsNativeUTF8() ? "+" : "-") + << " use-UTF8=" << (g_ForceToUTF8 ? "+" : "-") + << " wchar_t=" << (unsigned)(sizeof(wchar_t)) * 8 << "-bit" + << " Files=" << (unsigned)(sizeof(off_t)) * 8 << "-bit" + #endif + ; + { - UString s = MultiByteToUnicodeString(args[i]); - parts.Add(s); + const UInt32 numCpus = NWindows::NSystem::GetNumberOfProcessors(); + *so << " Threads:" << numCpus; } + + { + AString s; + GetCpuName(s); + s.Trim(); + *so << ", " << s; + } + + #ifdef _7ZIP_ASM + *so << ",ASM"; + #endif + + #if (defined MY_CPU_X86_OR_AMD64 || defined(MY_CPU_ARM_OR_ARM64)) + if (CPU_IsSupported_AES()) *so << ",AES"; + #endif + + #ifdef MY_CPU_ARM_OR_ARM64 + if (CPU_IsSupported_CRC32()) *so << ",CRC32"; + #if defined(_WIN32) + if (CPU_IsSupported_CRYPTO()) *so << ",CRYPTO"; + #else + if (CPU_IsSupported_SHA1()) *so << ",SHA1"; + if (CPU_IsSupported_SHA2()) *so << ",SHA2"; + #endif + #endif + + *so << endl; } #endif @@ -188,6 +292,8 @@ static void ShowCopyrightAndHelp(CStdOutStream *so, bool needHelp) return; *so << kCopyrightString; // *so << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << endl; + ShowProgInfo(so); + *so << endl; if (needHelp) *so << kHelpString; } @@ -211,7 +317,7 @@ static void PrintUInt32(CStdOutStream &so, UInt32 val, unsigned size) static void PrintLibIndex(CStdOutStream &so, int libIndex) { if (libIndex >= 0) - PrintUInt32(so, libIndex, 2); + PrintUInt32(so, (UInt32)libIndex, 2); else so << " "; so << ' '; @@ -329,7 +435,6 @@ static void ThrowException_if_Error(HRESULT res) throw CSystemException(res); } - static void PrintNum(UInt64 val, unsigned numDigits, char c = ' ') { char temp[64]; @@ -341,6 +446,8 @@ static void PrintNum(UInt64 val, unsigned numDigits, char c = ' ') *g_StdStream << p; } +#ifdef _WIN32 + static void PrintTime(const char *s, UInt64 val, UInt64 total) { *g_StdStream << endl << s << " Time ="; @@ -427,19 +534,19 @@ static void PrintStat() HMODULE kern = ::GetModuleHandleW(L"kernel32.dll"); Func_GetProcessMemoryInfo my_GetProcessMemoryInfo = (Func_GetProcessMemoryInfo) - ::GetProcAddress(kern, "K32GetProcessMemoryInfo"); + (void *)::GetProcAddress(kern, "K32GetProcessMemoryInfo"); if (!my_GetProcessMemoryInfo) { HMODULE lib = LoadLibraryW(L"Psapi.dll"); if (lib) - my_GetProcessMemoryInfo = (Func_GetProcessMemoryInfo)::GetProcAddress(lib, "GetProcessMemoryInfo"); + my_GetProcessMemoryInfo = (Func_GetProcessMemoryInfo)(void *)::GetProcAddress(lib, "GetProcessMemoryInfo"); } if (my_GetProcessMemoryInfo) memDefined = my_GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m)); // FreeLibrary(lib); Func_QueryProcessCycleTime my_QueryProcessCycleTime = (Func_QueryProcessCycleTime) - ::GetProcAddress(kern, "QueryProcessCycleTime"); + (void *)::GetProcAddress(kern, "QueryProcessCycleTime"); if (my_QueryProcessCycleTime) cycleDefined = my_QueryProcessCycleTime(GetCurrentProcess(), &cycleTime); } @@ -455,18 +562,32 @@ static void PrintStat() PrintTime("Kernel ", kernelTime, totalTime); + const UInt64 processTime = kernelTime + userTime; + #ifndef UNDER_CE if (cycleDefined) { - *g_StdStream << " "; - PrintNum(cycleTime / 1000000, 22); + *g_StdStream << " Cnt:"; + PrintNum(cycleTime / 1000000, 15); *g_StdStream << " MCycles"; } #endif PrintTime("User ", userTime, totalTime); + + #ifndef UNDER_CE + if (cycleDefined) + { + *g_StdStream << " Freq (cnt/ptime):"; + UInt64 us = processTime / 10; + if (us == 0) + us = 1; + PrintNum(cycleTime / us, 6); + *g_StdStream << " MHz"; + } + #endif - PrintTime("Process", kernelTime + userTime, totalTime); + PrintTime("Process", processTime, totalTime); #ifndef UNDER_CE if (memDefined) PrintMemUsage("Virtual ", m.PeakPagefileUsage); #endif @@ -475,10 +596,96 @@ static void PrintStat() #ifndef UNDER_CE if (memDefined) PrintMemUsage("Physical", m.PeakWorkingSetSize); #endif +} + + +#else // ! _WIN32 + +static UInt64 Get_timeofday_us() +{ + struct timeval now; + if (gettimeofday(&now, 0 ) == 0) + return (UInt64)now.tv_sec * 1000000 + (UInt64)now.tv_usec; + return 0; +} + +static void PrintTime(const char *s, UInt64 val, UInt64 total_us, UInt64 kFreq) +{ + *g_StdStream << endl << s << " Time ="; + + { + UInt64 sec, ms; + + if (kFreq == 0) + { + sec = val / 1000000; + ms = val % 1000000 / 1000; + } + else + { + sec = val / kFreq; + ms = (UInt32)((val - (sec * kFreq)) * 1000 / kFreq); + } + + PrintNum(sec, 6); + *g_StdStream << '.'; + PrintNum(ms, 3, '0'); + } + if (total_us == 0) + return; + + UInt64 percent = 0; + if (kFreq == 0) + percent = val * 100 / total_us; + else + { + const UInt64 kMaxVal = (UInt64)(Int64)-1; + UInt32 m = 100000000; + for (;;) + { + if (m == 0 || kFreq == 0) + break; + if (kMaxVal / m > val && + kMaxVal / kFreq > total_us) + break; + if (val > m) + val >>= 1; + else + m >>= 1; + if (kFreq > total_us) + kFreq >>= 1; + else + total_us >>= 1; + } + const UInt64 total = kFreq * total_us; + if (total != 0) + percent = val * m / total; + } + *g_StdStream << " ="; + PrintNum(percent, 5); + *g_StdStream << '%'; +} + +static void PrintStat(UInt64 startTime) +{ + tms t; + /* clock_t res = */ times(&t); + const UInt64 totalTime = Get_timeofday_us() - startTime; + const UInt64 kFreq = (UInt64)sysconf(_SC_CLK_TCK); + PrintTime("Kernel ", (UInt64)t.tms_stime, totalTime, kFreq); + PrintTime("User ", (UInt64)t.tms_utime, totalTime, kFreq); + PrintTime("Process", (UInt64)t.tms_utime + (UInt64)t.tms_stime, totalTime, kFreq); + PrintTime("Global ", totalTime, totalTime, 0); *g_StdStream << endl; } +#endif // ! _WIN32 + + + + + static void PrintHexId(CStdOutStream &so, UInt64 id) { char s[32]; @@ -486,23 +693,62 @@ static void PrintHexId(CStdOutStream &so, UInt64 id) PrintStringRight(so, s, 8); } +#ifndef _WIN32 +void Set_ModuleDirPrefix_From_ProgArg0(const char *s); +#endif int Main2( #ifndef _WIN32 int numArgs, char *args[] #endif +); +int Main2( + #ifndef _WIN32 + int numArgs, char *args[] + #endif ) { + #if defined(MY_CPU_SIZEOF_POINTER) + { unsigned k = sizeof(void *); if (k != MY_CPU_SIZEOF_POINTER) throw "incorrect MY_CPU_PTR_SIZE"; } + #endif + #if defined(_WIN32) && !defined(UNDER_CE) SetFileApisToOEM(); #endif + #ifdef ENV_HAVE_LOCALE + // printf("\nBefore SetLocale() : %s\n", IsNativeUtf8() ? "NATIVE UTF-8" : "IS NOT NATIVE UTF-8"); + MY_SetLocale(); + // printf("\nAfter SetLocale() : %s\n", IsNativeUtf8() ? "NATIVE UTF-8" : "IS NOT NATIVE UTF-8"); + #endif + + #ifndef _WIN32 + UInt64 startTime = Get_timeofday_us(); + #endif + UStringVector commandStrings; #ifdef _WIN32 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); #else - GetArguments(numArgs, args, commandStrings); + { + if (numArgs > 0) + Set_ModuleDirPrefix_From_ProgArg0(args[0]); + + for (int i = 0; i < numArgs; i++) + { + AString a (args[i]); + /* + printf("\n%d %s :", i, a.Ptr()); + for (unsigned k = 0; k < a.Len(); k++) + printf(" %2x", (unsigned)(Byte)a[k]); + */ + const UString s = MultiByteToUnicodeString(a); + commandStrings.Add(s); + } + // printf("\n"); + } + #endif #ifndef UNDER_CE @@ -542,10 +788,53 @@ int Main2( } if (options.EnableHeaders) + { ShowCopyrightAndHelp(g_StdStream, false); + if (!parser.Parse1Log.IsEmpty()) + *g_StdStream << parser.Parse1Log; + } parser.Parse2(options); + { + int cp = options.ConsoleCodePage; + + int stdout_cp = cp; + int stderr_cp = cp; + int stdin_cp = cp; + + /* + // these cases are complicated. + // maybe we must use CRT functions instead of console WIN32. + // different Windows/CRT versions also can work different ways. + // so the following code was not enabled: + if (cp == -1) + { + // we set CodePage only if stream is attached to terminal + // maybe we should set CodePage even if is not terminal? + #ifdef _WIN32 + { + UINT ccp = GetConsoleOutputCP(); + if (ccp != 0) + { + if (options.IsStdOutTerminal) stdout_cp = ccp; + if (options.IsStdErrTerminal) stderr_cp = ccp; + } + } + if (options.IsInTerminal) + { + UINT ccp = GetConsoleCP(); + if (ccp != 0) stdin_cp = ccp; + } + #endif + } + */ + + if (stdout_cp != -1) g_StdOut.CodePage = stdout_cp; + if (stderr_cp != -1) g_StdErr.CodePage = stderr_cp; + if (stdin_cp != -1) g_StdIn.CodePage = stdin_cp; + } + unsigned percentsNameLevel = 1; if (options.LogLevel == 0 || options.Number_for_Percents != options.Number_for_Out) percentsNameLevel = 2; @@ -559,13 +848,13 @@ int Main2( #if !defined(UNDER_CE) CONSOLE_SCREEN_BUFFER_INFO consoleInfo; if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo)) - consoleWidth = consoleInfo.dwSize.X; + consoleWidth = (unsigned)consoleInfo.dwSize.X; #endif #else struct winsize w; - if (ioctl(0, TIOCGWINSZ, &w) == ) + if (ioctl(0, TIOCGWINSZ, &w) == 0) consoleWidth = w.ws_col; #endif @@ -577,6 +866,19 @@ int Main2( codecs->CaseSensitive = options.CaseSensitive; ThrowException_if_Error(codecs->Load()); + #ifdef EXTERNAL_CODECS + { + UString s; + codecs->GetCodecsErrorMessage(s); + if (!s.IsEmpty()) + { + CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut); + so << endl << s << endl; + } + } + #endif + + bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); if (codecs->Formats.Size() == 0 && @@ -640,14 +942,14 @@ int Main2( so << endl << "Libs:" << endl; for (i = 0; i < codecs->Libs.Size(); i++) { - PrintLibIndex(so, i); + PrintLibIndex(so, (int)i); so << ' ' << codecs->Libs[i].Path << endl; } #endif so << endl << "Formats:" << endl; - const char * const kArcFlags = "KSNFMGOPBELH"; + const char * const kArcFlags = "KSNFMGOPBELHX"; const unsigned kNumArcFlags = (unsigned)strlen(kArcFlags); for (i = 0; i < codecs->Formats.Size(); i++) @@ -804,6 +1106,7 @@ int Main2( options.Properties, options.NumIterations, (FILE *)so); if (hresultMain == S_FALSE) { + so << endl; if (g_ErrStream) *g_ErrStream << "\nDecoding ERROR\n"; retCode = NExitCode::kFatalError; @@ -863,7 +1166,7 @@ int Main2( } } - if (hresultMain == S_OK) + if (hresultMain == S_OK) { if (isExtractGroupCommand) { CExtractCallbackConsole *ecs = new CExtractCallbackConsole; @@ -992,7 +1295,7 @@ int Main2( if (isError) retCode = NExitCode::kFatalError; - if (so) + if (so) { if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0) { // if (ecs->NumArchives > 1) @@ -1023,8 +1326,9 @@ int Main2( PrintHashStat(*so, hb); } } + } // if (so) } - else + else // if_(!isExtractGroupCommand) { UInt64 numErrors = 0; UInt64 numWarnings = 0; @@ -1060,7 +1364,8 @@ int Main2( g_StdOut << endl << "Errors: " << numErrors << endl; retCode = NExitCode::kFatalError; } - } + } // if_(isExtractGroupCommand) + } // if_(hresultMain == S_OK) } else if (options.Command.IsFromUpdateGroup()) { @@ -1146,7 +1451,11 @@ int Main2( ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError); if (options.ShowTime && g_StdStream) - PrintStat(); + PrintStat( + #ifndef _WIN32 + startTime + #endif + ); ThrowException_if_Error(hresultMain); diff --git a/CPP/7zip/UI/Console/MainAr.cpp b/CPP/7zip/UI/Console/MainAr.cpp index 87bf57e8..0e45312c 100644 --- a/CPP/7zip/UI/Console/MainAr.cpp +++ b/CPP/7zip/UI/Console/MainAr.cpp @@ -19,7 +19,11 @@ using namespace NWindows; +extern +CStdOutStream *g_StdStream; CStdOutStream *g_StdStream = NULL; +extern +CStdOutStream *g_ErrStream; CStdOutStream *g_ErrStream = NULL; extern int Main2( @@ -48,7 +52,9 @@ static void PrintError(const char *message) *g_ErrStream << "\n\n" << message << endl; } +#if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) #define NT_CHECK_FAIL_ACTION *g_StdStream << "Unsupported Windows version"; return NExitCode::kFatalError; +#endif int MY_CDECL main ( diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.h b/CPP/7zip/UI/Console/OpenCallbackConsole.h index 64c1dad3..075d3741 100644 --- a/CPP/7zip/UI/Console/OpenCallbackConsole.h +++ b/CPP/7zip/UI/Console/OpenCallbackConsole.h @@ -46,6 +46,8 @@ public: #endif {} + + virtual ~COpenCallbackConsole() {} void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream) { diff --git a/CPP/7zip/UI/Console/PercentPrinter.cpp b/CPP/7zip/UI/Console/PercentPrinter.cpp index b2426878..4341fd9f 100644 --- a/CPP/7zip/UI/Console/PercentPrinter.cpp +++ b/CPP/7zip/UI/Console/PercentPrinter.cpp @@ -143,7 +143,7 @@ void CPercentPrinter::Print() _tempU = FileName; _so->Normalize_UString(_tempU); - StdOut_Convert_UString_to_AString(_tempU, _temp); + _so->Convert_UString_to_AString(_tempU, _temp); if (_s.Len() + _temp.Len() > MaxLen) { unsigned len = FileName.Len(); @@ -157,7 +157,7 @@ void CPercentPrinter::Print() _tempU.Delete(len / 2, _tempU.Len() - len); _tempU.Insert(len / 2, L" . "); _so->Normalize_UString(_tempU); - StdOut_Convert_UString_to_AString(_tempU, _temp); + _so->Convert_UString_to_AString(_tempU, _temp); if (_s.Len() + _temp.Len() <= MaxLen) break; } diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp index cd232fff..24056072 100644 --- a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp +++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp @@ -209,6 +209,7 @@ HRESULT CCallbackConsoleBase::OpenFileError_Base(const FString &path, DWORD syst { MT_LOCK FailedFiles.AddError(path, systemError); + NumNonOpenFiles++; /* if (systemError == ERROR_SHARING_VIOLATION) { @@ -282,6 +283,12 @@ HRESULT CUpdateCallbackConsole::StartOpenArchive(const wchar_t *name) HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating) { + if (NeedPercents()) + _percent.ClosePrint(true); + + _percent.ClearCurState(); + NumNonOpenFiles = 0; + if (_so) { *_so << (updating ? kUpdatingArchiveMessage : kCreatingArchiveMessage); @@ -302,7 +309,7 @@ HRESULT CUpdateCallbackConsole::FinishArchive(const CFinishArchiveStat &st) { AString s; // Print_UInt64_and_String(s, _percent.Files == 1 ? "file" : "files", _percent.Files); - PrintPropPair(s, "Files read from disk", _percent.Files); + PrintPropPair(s, "Files read from disk", _percent.Files - NumNonOpenFiles); s.Add_LF(); s += "Archive size: "; PrintSize_bytes_Smart(s, st.OutArcFileSize); diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.h b/CPP/7zip/UI/Console/UpdateCallbackConsole.h index ba8614eb..5c205aad 100644 --- a/CPP/7zip/UI/Console/UpdateCallbackConsole.h +++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.h @@ -56,7 +56,8 @@ public: StdOutMode(false), NeedFlush(false), PercentsNameLevel(1), - LogLevel(0) + LogLevel(0), + NumNonOpenFiles(0) {} void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; } @@ -82,9 +83,9 @@ public: _percent.ClosePrint(false); } - CErrorPathCodes FailedFiles; CErrorPathCodes ScanErrors; + UInt64 NumNonOpenFiles; HRESULT PrintProgress(const wchar_t *name, const char *command, bool showInLog); @@ -95,21 +96,23 @@ class CUpdateCallbackConsole: public IUpdateCallbackUI2, public CCallbackConsole // void PrintPropPair(const char *name, const wchar_t *val); public: + bool DeleteMessageWasShown; + #ifndef _NO_CRYPTO bool PasswordIsDefined; UString Password; bool AskPassword; #endif - bool DeleteMessageWasShown; - - CUpdateCallbackConsole() - : DeleteMessageWasShown(false) + CUpdateCallbackConsole(): + DeleteMessageWasShown(false) #ifndef _NO_CRYPTO , PasswordIsDefined(false) , AskPassword(false) #endif {} + + virtual ~CUpdateCallbackConsole() {} /* void Init(CStdOutStream *outStream) diff --git a/CPP/7zip/UI/Console/UserInputUtils.cpp b/CPP/7zip/UI/Console/UserInputUtils.cpp index 0e2d7ac1..93f60eb2 100644 --- a/CPP/7zip/UI/Console/UserInputUtils.cpp +++ b/CPP/7zip/UI/Console/UserInputUtils.cpp @@ -78,7 +78,7 @@ static bool GetPassword(CStdOutStream *outStream, UString &psw) DWORD mode = 0; if (console != INVALID_HANDLE_VALUE && console != 0) if (GetConsoleMode(console, &mode)) - wasChanged = (SetConsoleMode(console, mode & ~ENABLE_ECHO_INPUT) != 0); + wasChanged = (SetConsoleMode(console, mode & ~(DWORD)ENABLE_ECHO_INPUT) != 0); bool res = g_StdIn.ScanUStringUntilNewLine(psw); if (wasChanged) SetConsoleMode(console, mode); diff --git a/CPP/7zip/UI/Console/makefile b/CPP/7zip/UI/Console/makefile index 541b7681..ada782b0 100644 --- a/CPP/7zip/UI/Console/makefile +++ b/CPP/7zip/UI/Console/makefile @@ -31,6 +31,7 @@ WIN_OBJS = \ $O\PropVariantConv.obj \ $O\Registry.obj \ $O\System.obj \ + $O\SystemInfo.obj \ $O\TimeUtils.obj \ 7ZIP_COMMON_OBJS = \ diff --git a/CPP/7zip/UI/Console/makefile.gcc b/CPP/7zip/UI/Console/makefile.gcc new file mode 100644 index 00000000..e0d996c1 --- /dev/null +++ b/CPP/7zip/UI/Console/makefile.gcc @@ -0,0 +1,171 @@ +PROG = 7z +IS_NOT_STANDALONE = 1 + +# IS_X64 = 1 +# USE_ASM = 1 +# ST_MODE = 1 + + +LOCAL_FLAGS_ST = +MT_OBJS = + +ifdef ST_MODE + +LOCAL_FLAGS_ST = -D_7ZIP_ST + +ifdef SystemDrive +MT_OBJS = \ + $O/Threads.o \ + +endif + +else + +MT_OBJS = \ + $O/Synchronization.o \ + $O/Threads.o \ + +endif + + + +LOCAL_FLAGS_WIN= + +ifdef SystemDrive + +LOCAL_FLAGS_WIN = \ + -D_7ZIP_LARGE_PAGES \ + -DWIN_LONG_PATH \ + -DSUPPORT_DEVICE_FILE \ + +SYS_OBJS = \ + $O/FileSystem.o \ + $O/Registry.o \ + $O/MemoryLock.o \ + $O/DllSecur.o \ + $O/resource.o \ + +else + +SYS_OBJS = \ + $O/MyWindows.o \ + +endif + + + +LOCAL_FLAGS = \ + $(LOCAL_FLAGS_WIN) \ + $(LOCAL_FLAGS_ST) \ + -DEXTERNAL_CODECS \ + + + +CONSOLE_OBJS = \ + $O/BenchCon.o \ + $O/ConsoleClose.o \ + $O/ExtractCallbackConsole.o \ + $O/HashCon.o \ + $O/List.o \ + $O/Main.o \ + $O/MainAr.o \ + $O/OpenCallbackConsole.o \ + $O/PercentPrinter.o \ + $O/UpdateCallbackConsole.o \ + $O/UserInputUtils.o \ + +UI_COMMON_OBJS = \ + $O/ArchiveCommandLine.o \ + $O/ArchiveExtractCallback.o \ + $O/ArchiveOpenCallback.o \ + $O/Bench.o \ + $O/DefaultName.o \ + $O/EnumDirItems.o \ + $O/Extract.o \ + $O/ExtractingFilePath.o \ + $O/HashCalc.o \ + $O/LoadCodecs.o \ + $O/OpenArchive.o \ + $O/PropIDUtils.o \ + $O/SetProperties.o \ + $O/SortUtils.o \ + $O/TempFiles.o \ + $O/Update.o \ + $O/UpdateAction.o \ + $O/UpdateCallback.o \ + $O/UpdatePair.o \ + $O/UpdateProduce.o \ + +COMMON_OBJS = \ + $O/CommandLineParser.o \ + $O/CRC.o \ + $O/CrcReg.o \ + $O/IntToString.o \ + $O/ListFileUtils.o \ + $O/NewHandler.o \ + $O/StdInStream.o \ + $O/StdOutStream.o \ + $O/MyString.o \ + $O/StringConvert.o \ + $O/StringToInt.o \ + $O/UTFConvert.o \ + $O/MyVector.o \ + $O/Wildcard.o \ + +WIN_OBJS = \ + $O/DLL.o \ + $O/ErrorMsg.o \ + $O/FileDir.o \ + $O/FileFind.o \ + $O/FileIO.o \ + $O/FileLink.o \ + $O/FileName.o \ + $O/PropVariant.o \ + $O/PropVariantConv.o \ + $O/System.o \ + $O/SystemInfo.o \ + $O/TimeUtils.o \ + +7ZIP_COMMON_OBJS = \ + $O/CreateCoder.o \ + $O/CWrappers.o \ + $O/FilePathAutoRename.o \ + $O/FileStreams.o \ + $O/InBuffer.o \ + $O/InOutTempBuffer.o \ + $O/FilterCoder.o \ + $O/LimitedStreams.o \ + $O/MethodId.o \ + $O/MethodProps.o \ + $O/OffsetStream.o \ + $O/OutBuffer.o \ + $O/ProgressUtils.o \ + $O/PropId.o \ + $O/StreamObjects.o \ + $O/StreamUtils.o \ + $O/UniqBlocks.o \ + +COMPRESS_OBJS = \ + $O/CopyCoder.o \ + +C_OBJS = \ + $O/Alloc.o \ + $O/CpuArch.o \ + $O/Sort.o \ + $O/7zCrc.o \ + $O/7zCrcOpt.o \ + + +OBJS = \ + $(C_OBJS) \ + $(MT_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(SYS_OBJS) \ + $(COMPRESS_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(UI_COMMON_OBJS) \ + $(CONSOLE_OBJS) \ + + +include ../../7zip_gcc.mak diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp index a99ca81d..0334942a 100644 --- a/CPP/7zip/UI/Explorer/ContextMenu.cpp +++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp @@ -2,6 +2,7 @@ #include "StdAfx.h" +#include "../../../Common/ComTry.h" #include "../../../Common/StringConvert.h" #include "../../../Windows/COM.h" @@ -31,6 +32,12 @@ #include "resource.h" +// #define SHOW_DEBUG_CTX_MENU + +#ifdef SHOW_DEBUG_CTX_MENU +#include <stdio.h> +#endif + using namespace NWindows; using namespace NFile; using namespace NDir; @@ -63,8 +70,8 @@ CZipContextMenu::~CZipContextMenu() HRESULT CZipContextMenu::GetFileNames(LPDATAOBJECT dataObject, UStringVector &fileNames) { fileNames.Clear(); - if (dataObject == NULL) - return E_FAIL; + if (!dataObject) + return E_INVALIDARG; #ifndef UNDER_CE @@ -146,76 +153,24 @@ struct CContextMenuCommand UINT ResourceID; }; +#define CMD_REC(cns, verb, ids) { NContextMenuFlags::cns, CZipContextMenu::cns, verb, ids } + static const CContextMenuCommand g_Commands[] = { - { - NContextMenuFlags::kOpen, - CZipContextMenu::kOpen, - "Open", - IDS_CONTEXT_OPEN - }, - { - NContextMenuFlags::kExtract, - CZipContextMenu::kExtract, - "Extract", - IDS_CONTEXT_EXTRACT - }, - { - NContextMenuFlags::kExtractHere, - CZipContextMenu::kExtractHere, - "ExtractHere", - IDS_CONTEXT_EXTRACT_HERE - }, - { - NContextMenuFlags::kExtractTo, - CZipContextMenu::kExtractTo, - "ExtractTo", - IDS_CONTEXT_EXTRACT_TO - }, - { - NContextMenuFlags::kTest, - CZipContextMenu::kTest, - "Test", - IDS_CONTEXT_TEST - }, - { - NContextMenuFlags::kCompress, - CZipContextMenu::kCompress, - "Compress", - IDS_CONTEXT_COMPRESS - }, - { - NContextMenuFlags::kCompressEmail, - CZipContextMenu::kCompressEmail, - "CompressEmail", - IDS_CONTEXT_COMPRESS_EMAIL - }, - { - NContextMenuFlags::kCompressTo7z, - CZipContextMenu::kCompressTo7z, - "CompressTo7z", - IDS_CONTEXT_COMPRESS_TO - }, - { - NContextMenuFlags::kCompressTo7zEmail, - CZipContextMenu::kCompressTo7zEmail, - "CompressTo7zEmail", - IDS_CONTEXT_COMPRESS_TO_EMAIL - }, - { - NContextMenuFlags::kCompressToZip, - CZipContextMenu::kCompressToZip, - "CompressToZip", - IDS_CONTEXT_COMPRESS_TO - }, - { - NContextMenuFlags::kCompressToZipEmail, - CZipContextMenu::kCompressToZipEmail, - "CompressToZipEmail", - IDS_CONTEXT_COMPRESS_TO_EMAIL - } + CMD_REC( kOpen, "Open", IDS_CONTEXT_OPEN), + CMD_REC( kExtract, "Extract", IDS_CONTEXT_EXTRACT), + CMD_REC( kExtractHere, "ExtractHere", IDS_CONTEXT_EXTRACT_HERE), + CMD_REC( kExtractTo, "ExtractTo", IDS_CONTEXT_EXTRACT_TO), + CMD_REC( kTest, "Test", IDS_CONTEXT_TEST), + CMD_REC( kCompress, "Compress", IDS_CONTEXT_COMPRESS), + CMD_REC( kCompressEmail, "CompressEmail", IDS_CONTEXT_COMPRESS_EMAIL), + CMD_REC( kCompressTo7z, "CompressTo7z", IDS_CONTEXT_COMPRESS_TO), + CMD_REC( kCompressTo7zEmail, "CompressTo7zEmail", IDS_CONTEXT_COMPRESS_TO_EMAIL), + CMD_REC( kCompressToZip, "CompressToZip", IDS_CONTEXT_COMPRESS_TO), + CMD_REC( kCompressToZipEmail, "CompressToZipEmail", IDS_CONTEXT_COMPRESS_TO_EMAIL) }; + struct CHashCommand { CZipContextMenu::ECommandInternalID CommandInternalID; @@ -232,6 +187,7 @@ static const CHashCommand g_HashCommands[] = { CZipContextMenu::kHash_All, "*", "*" } }; + static int FindCommand(CZipContextMenu::ECommandInternalID &id) { for (unsigned i = 0; i < ARRAY_SIZE(g_Commands); i++) @@ -240,22 +196,31 @@ static int FindCommand(CZipContextMenu::ECommandInternalID &id) return -1; } -bool CZipContextMenu::FillCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &commandMapItem) + +void CZipContextMenu::FillCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &cmi) { mainString.Empty(); int i = FindCommand(id); if (i < 0) - return false; - const CContextMenuCommand &command = g_Commands[i]; - commandMapItem.CommandInternalID = command.CommandInternalID; - commandMapItem.Verb = kMainVerb; - commandMapItem.Verb += command.Verb; - // LangString(command.ResourceHelpID, command.LangID + 1, commandMapItem.HelpString); + throw 201908; + const CContextMenuCommand &command = g_Commands[(unsigned)i]; + cmi.CommandInternalID = command.CommandInternalID; + cmi.Verb = kMainVerb; + cmi.Verb += command.Verb; + // cmi.HelpString = cmi.Verb; LangString(command.ResourceID, mainString); - return true; + // return true; } -static bool MyInsertMenu(CMenu &menu, int pos, UINT id, const UString &s, HBITMAP bitmap) + +void CZipContextMenu::AddCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &cmi) +{ + FillCommand(id, mainString, cmi); + _commandMap.Add(cmi); +} + + +static void MyInsertMenu(CMenu &menu, int pos, UINT id, const UString &s, HBITMAP bitmap) { CMenuItem mi; mi.fType = MFT_STRING; @@ -266,12 +231,40 @@ static bool MyInsertMenu(CMenu &menu, int pos, UINT id, const UString &s, HBITMA mi.StringValue = s; mi.hbmpUnchecked = bitmap; // mi.hbmpChecked = bitmap; // do we need hbmpChecked ??? - return menu.InsertItem(pos, true, mi); + if (!menu.InsertItem(pos, true, mi)) + throw 20190816; // SetMenuItemBitmaps also works // ::SetMenuItemBitmaps(menu, pos, MF_BYPOSITION, bitmap, NULL); } + +static void MyAddSubMenu( + CObjectVector<CZipContextMenu::CCommandMapItem> &_commandMap, + const char *verb, + CMenu &menu, int pos, UINT id, const UString &s, HMENU hSubMenu, HBITMAP bitmap) +{ + CZipContextMenu::CCommandMapItem cmi; + cmi.CommandInternalID = CZipContextMenu::kCommandNULL; + cmi.Verb = verb; + // cmi.HelpString = verb; + _commandMap.Add(cmi); + + CMenuItem mi; + mi.fType = MFT_STRING; + mi.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID; + if (bitmap) + mi.fMask |= MIIM_CHECKMARKS; + mi.wID = id; + mi.hSubMenu = hSubMenu; + mi.hbmpUnchecked = bitmap; + + mi.StringValue = s; + if (!menu.InsertItem(pos, true, mi)) + throw 20190817; +} + + static const char * const kArcExts[] = { "7z" @@ -289,6 +282,7 @@ static bool IsItArcExt(const UString &ext) return false; } +UString GetSubFolderNameForExtract(const UString &arcName); UString GetSubFolderNameForExtract(const UString &arcName) { int dotPos = arcName.ReverseFind_Dot(); @@ -302,11 +296,11 @@ UString GetSubFolderNameForExtract(const UString &arcName) if (dotPos > 0) { const UString ext2 = res.Ptr(dotPos + 1); - if (ext.IsEqualTo_Ascii_NoCase("001") && IsItArcExt(ext2) - || ext.IsEqualTo_Ascii_NoCase("rar") && + if ((ext.IsEqualTo_Ascii_NoCase("001") && IsItArcExt(ext2)) + || (ext.IsEqualTo_Ascii_NoCase("rar") && ( ext2.IsEqualTo_Ascii_NoCase("part001") || ext2.IsEqualTo_Ascii_NoCase("part01") - || ext2.IsEqualTo_Ascii_NoCase("part1"))) + || ext2.IsEqualTo_Ascii_NoCase("part1")))) res.DeleteFrom(dotPos); res.TrimRight(); } @@ -415,17 +409,44 @@ static bool DoNeedExtract(const FString &name) // we must use diferent Verbs for Popup subMenu. void CZipContextMenu::AddMapItem_ForSubMenu(const char *verb) { - CCommandMapItem commandMapItem; - commandMapItem.CommandInternalID = kCommandNULL; - commandMapItem.Verb = verb; - _commandMap.Add(commandMapItem); + CCommandMapItem cmi; + cmi.CommandInternalID = kCommandNULL; + cmi.Verb = verb; + // cmi.HelpString = verb; + _commandMap.Add(cmi); +} + + +static HRESULT RETURN_WIN32_LastError_AS_HRESULT() +{ + DWORD lastError = ::GetLastError(); + if (lastError == 0) + return E_FAIL; + return HRESULT_FROM_WIN32(lastError); } +/* + we add CCommandMapItem to _commandMap for each new Mene ID. + so then we use _commandMap[offset]. + That way we can execute commands that have menu item. + Another non-implemented way: + We can return the number off all possible commnad in QueryContextMenu(). + so the caller could call InvokeCommand() via string verb aven + without using menu items. +*/ + + + STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT commandIDFirst, UINT commandIDLast, UINT flags) { - // OutputDebugStringA("QueryContextMenu"); + COM_TRY_BEGIN + try { + + #ifdef SHOW_DEBUG_CTX_MENU + { char s[256]; sprintf(s, "QueryContextMenu: index=%d first=%d last=%d flags=%x _files=%d", + indexMenu, commandIDFirst, commandIDLast, flags, _fileNames.Size()); OutputDebugStringA(s); } /* for (UInt32 i = 0; i < _fileNames.Size(); i++) @@ -433,15 +454,29 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, OutputDebugStringW(_fileNames[i]); } */ + #endif LoadLangOneTime(); + if (_fileNames.Size() == 0) - return E_FAIL; + { + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0); + // return E_INVALIDARG; + } + + if (commandIDFirst > commandIDLast) + return E_INVALIDARG; + + UINT currentCommandID = commandIDFirst; - if ((flags & 0x000F) != CMF_NORMAL && - (flags & CMF_VERBSONLY) == 0 && - (flags & CMF_EXPLORE) == 0) - return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID); + + if ((flags & 0x000F) != CMF_NORMAL + && (flags & CMF_VERBSONLY) == 0 + && (flags & CMF_EXPLORE) == 0) + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID - commandIDFirst); + // return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID); + // 19.01 : we changed from (currentCommandID) to (currentCommandID - commandIDFirst) + // why it was so before? _commandMap.Clear(); @@ -462,7 +497,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (ci.Cascaded.Val) { if (!popupMenu.CreatePopup()) - return E_FAIL; + return RETURN_WIN32_LastError_AS_HRESULT(); menuDestroyer.Attach(popupMenu); /* 9.31: we commented the following code. Probably we don't need. @@ -508,7 +543,10 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, #endif { if (!fi0.Find(us2fs(fileName))) - return E_FAIL; + { + throw 20190820; + // return RETURN_WIN32_LastError_AS_HRESULT(); + } GetOnlyDirPrefix(us2fs(fileName), folderPrefix); } } @@ -523,10 +561,9 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, bool thereIsMainOpenItem = ((contextMenuFlags & NContextMenuFlags::kOpen) != 0); if (thereIsMainOpenItem) { - CCommandMapItem commandMapItem; - FillCommand(kOpen, mainString, commandMapItem); + CCommandMapItem cmi; + AddCommand(kOpen, mainString, cmi); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); - _commandMap.Add(commandMapItem); } if ((contextMenuFlags & NContextMenuFlags::kOpenAs) != 0 // && (!thereIsMainOpenItem || !FindExt(kNoOpenAsExtensions, fi0.Name)) @@ -535,37 +572,26 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, CMenu subMenu; if (subMenu.CreatePopup()) { - CMenuItem mi; - mi.fType = MFT_STRING; - mi.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID; - if (bitmap) - mi.fMask |= MIIM_CHECKMARKS; - mi.wID = currentCommandID++; - mi.hSubMenu = subMenu; - mi.hbmpUnchecked = bitmap; - - LangString(IDS_CONTEXT_OPEN, mi.StringValue); - popupMenu.InsertItem(subIndex++, true, mi); - AddMapItem_ForSubMenu(kOpenCascadedVerb); + MyAddSubMenu(_commandMap, kOpenCascadedVerb, popupMenu, subIndex++, currentCommandID++, LangString(IDS_CONTEXT_OPEN), subMenu, bitmap); UINT subIndex2 = 0; for (unsigned i = (thereIsMainOpenItem ? 1 : 0); i < ARRAY_SIZE(kOpenTypes); i++) { - CCommandMapItem commandMapItem; + CCommandMapItem cmi; if (i == 0) - FillCommand(kOpen, mainString, commandMapItem); + FillCommand(kOpen, mainString, cmi); else { mainString = kOpenTypes[i]; - commandMapItem.CommandInternalID = kOpen; - commandMapItem.Verb = kMainVerb; - commandMapItem.Verb += ".Open."; - commandMapItem.Verb += mainString; - commandMapItem.HelpString = mainString; - commandMapItem.ArcType = mainString; + cmi.CommandInternalID = kOpen; + cmi.Verb = kMainVerb; + cmi.Verb += ".Open."; + cmi.Verb += mainString; + // cmi.HelpString = cmi.Verb; + cmi.ArcType = mainString; } + _commandMap.Add(cmi); MyInsertMenu(subMenu, subIndex2++, currentCommandID++, mainString, bitmap); - _commandMap.Add(commandMapItem); } subMenu.Detach(); @@ -584,7 +610,10 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, { NFind::CFileInfo fi; if (!fi.Find(us2fs(_fileNames[i]))) - return E_FAIL; + { + throw 20190821; + // return RETURN_WIN32_LastError_AS_HRESULT(); + } if (!fi.IsDir() && DoNeedExtract(fi.Name)) { needExtract = true; @@ -610,43 +639,39 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if ((contextMenuFlags & NContextMenuFlags::kExtract) != 0) { // Extract - CCommandMapItem commandMapItem; - FillCommand(kExtract, mainString, commandMapItem); - commandMapItem.Folder = baseFolder + specFolder; + CCommandMapItem cmi; + cmi.Folder = baseFolder + specFolder; + AddCommand(kExtract, mainString, cmi); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); - _commandMap.Add(commandMapItem); } if ((contextMenuFlags & NContextMenuFlags::kExtractHere) != 0) { // Extract Here - CCommandMapItem commandMapItem; - FillCommand(kExtractHere, mainString, commandMapItem); - commandMapItem.Folder = baseFolder; + CCommandMapItem cmi; + cmi.Folder = baseFolder; + AddCommand(kExtractHere, mainString, cmi); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); - _commandMap.Add(commandMapItem); } if ((contextMenuFlags & NContextMenuFlags::kExtractTo) != 0) { // Extract To - CCommandMapItem commandMapItem; + CCommandMapItem cmi; UString s; - FillCommand(kExtractTo, s, commandMapItem); - commandMapItem.Folder = baseFolder + specFolder; + cmi.Folder = baseFolder + specFolder; + AddCommand(kExtractTo, s, cmi); MyFormatNew_ReducedName(s, specFolder); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); - _commandMap.Add(commandMapItem); } } if ((contextMenuFlags & NContextMenuFlags::kTest) != 0) { // Test - CCommandMapItem commandMapItem; - FillCommand(kTest, mainString, commandMapItem); + CCommandMapItem cmi; + AddCommand(kTest, mainString, cmi); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); - _commandMap.Add(commandMapItem); } } @@ -660,26 +685,24 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, // Compress if ((contextMenuFlags & NContextMenuFlags::kCompress) != 0) { - CCommandMapItem commandMapItem; + CCommandMapItem cmi; if (_dropMode) - commandMapItem.Folder = _dropPath; + cmi.Folder = _dropPath; else - commandMapItem.Folder = fs2us(folderPrefix); - commandMapItem.ArcName = arcName; - FillCommand(kCompress, mainString, commandMapItem); + cmi.Folder = fs2us(folderPrefix); + cmi.ArcName = arcName; + AddCommand(kCompress, mainString, cmi); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); - _commandMap.Add(commandMapItem); } #ifdef EMAIL_SUPPORT // CompressEmail if ((contextMenuFlags & NContextMenuFlags::kCompressEmail) != 0 && !_dropMode) { - CCommandMapItem commandMapItem; - commandMapItem.ArcName = arcName; - FillCommand(kCompressEmail, mainString, commandMapItem); + CCommandMapItem cmi; + cmi.ArcName = arcName; + AddCommand(kCompressEmail, mainString, cmi); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); - _commandMap.Add(commandMapItem); } #endif @@ -687,32 +710,30 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (contextMenuFlags & NContextMenuFlags::kCompressTo7z && !arcName7z.IsEqualTo_NoCase(fs2us(fi0.Name))) { - CCommandMapItem commandMapItem; + CCommandMapItem cmi; UString s; - FillCommand(kCompressTo7z, s, commandMapItem); if (_dropMode) - commandMapItem.Folder = _dropPath; + cmi.Folder = _dropPath; else - commandMapItem.Folder = fs2us(folderPrefix); - commandMapItem.ArcName = arcName7z; - commandMapItem.ArcType = "7z"; + cmi.Folder = fs2us(folderPrefix); + cmi.ArcName = arcName7z; + cmi.ArcType = "7z"; + AddCommand(kCompressTo7z, s, cmi); MyFormatNew_ReducedName(s, arcName7z); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); - _commandMap.Add(commandMapItem); } #ifdef EMAIL_SUPPORT // CompressTo7zEmail if ((contextMenuFlags & NContextMenuFlags::kCompressTo7zEmail) != 0 && !_dropMode) { - CCommandMapItem commandMapItem; + CCommandMapItem cmi; UString s; - FillCommand(kCompressTo7zEmail, s, commandMapItem); - commandMapItem.ArcName = arcName7z; - commandMapItem.ArcType = "7z"; + cmi.ArcName = arcName7z; + cmi.ArcType = "7z"; + AddCommand(kCompressTo7zEmail, s, cmi); MyFormatNew_ReducedName(s, arcName7z); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); - _commandMap.Add(commandMapItem); } #endif @@ -720,32 +741,30 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (contextMenuFlags & NContextMenuFlags::kCompressToZip && !arcNameZip.IsEqualTo_NoCase(fs2us(fi0.Name))) { - CCommandMapItem commandMapItem; + CCommandMapItem cmi; UString s; - FillCommand(kCompressToZip, s, commandMapItem); if (_dropMode) - commandMapItem.Folder = _dropPath; + cmi.Folder = _dropPath; else - commandMapItem.Folder = fs2us(folderPrefix); - commandMapItem.ArcName = arcNameZip; - commandMapItem.ArcType = "zip"; + cmi.Folder = fs2us(folderPrefix); + cmi.ArcName = arcNameZip; + cmi.ArcType = "zip"; + AddCommand(kCompressToZip, s, cmi); MyFormatNew_ReducedName(s, arcNameZip); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); - _commandMap.Add(commandMapItem); } #ifdef EMAIL_SUPPORT // CompressToZipEmail if ((contextMenuFlags & NContextMenuFlags::kCompressToZipEmail) != 0 && !_dropMode) { - CCommandMapItem commandMapItem; + CCommandMapItem cmi; UString s; - FillCommand(kCompressToZipEmail, s, commandMapItem); - commandMapItem.ArcName = arcNameZip; - commandMapItem.ArcType = "zip"; + cmi.ArcName = arcNameZip; + cmi.ArcType = "zip"; + AddCommand(kCompressToZipEmail, s, cmi); MyFormatNew_ReducedName(s, arcNameZip); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); - _commandMap.Add(commandMapItem); } #endif } @@ -757,22 +776,10 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (ci.Cascaded.Val) { - CMenuItem mi; - mi.fType = MFT_STRING; - mi.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID; - if (bitmap) - mi.fMask |= MIIM_CHECKMARKS; - mi.wID = currentCommandID++; - mi.hSubMenu = popupMenu.Detach(); - mi.StringValue = "7-Zip"; // LangString(IDS_CONTEXT_POPUP_CAPTION); - mi.hbmpUnchecked = bitmap; - CMenu menu; menu.Attach(hMenu); menuDestroyer.Disable(); - menu.InsertItem(indexMenu++, true, mi); - - AddMapItem_ForSubMenu(kMainVerb); + MyAddSubMenu(_commandMap, kMainVerb, menu, indexMenu++, currentCommandID++, (UString)"7-Zip", popupMenu.Detach(), bitmap); } else { @@ -783,7 +790,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (!_isMenuForFM && ((contextMenuFlags & NContextMenuFlags::kCRC) != 0 - && currentCommandID + 6 <= commandIDLast)) + && currentCommandID + 1 < commandIDLast)) { CMenu subMenu; // CMenuDestroyer menuDestroyer_CRC; @@ -793,40 +800,58 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (subMenu.CreatePopup()) { // menuDestroyer_CRC.Attach(subMenu); - CMenuItem mi; - mi.fType = MFT_STRING; - mi.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID; - if (bitmap) - mi.fMask |= MIIM_CHECKMARKS; - mi.wID = currentCommandID++; - mi.hSubMenu = subMenu; - mi.StringValue = "CRC SHA"; - mi.hbmpUnchecked = bitmap; CMenu menu; menu.Attach(hMenu); // menuDestroyer_CRC.Disable(); - menu.InsertItem(indexMenu++, true, mi); - - AddMapItem_ForSubMenu(kCheckSumCascadedVerb); + MyAddSubMenu(_commandMap, kCheckSumCascadedVerb, menu, indexMenu++, currentCommandID++, (UString)"CRC SHA", subMenu, bitmap); for (unsigned i = 0; i < ARRAY_SIZE(g_HashCommands); i++) { + if (currentCommandID >= commandIDLast) + break; const CHashCommand &hc = g_HashCommands[i]; - CCommandMapItem commandMapItem; - commandMapItem.CommandInternalID = hc.CommandInternalID; - commandMapItem.Verb = kCheckSumCascadedVerb; - commandMapItem.Verb += hc.MethodName; - // commandMapItem.HelpString = hc.Name; + CCommandMapItem cmi; + cmi.CommandInternalID = hc.CommandInternalID; + cmi.Verb = kCheckSumCascadedVerb; + cmi.Verb += '.'; + cmi.Verb += hc.MethodName; + // cmi.HelpString = cmi.Verb; + _commandMap.Add(cmi); MyInsertMenu(subMenu, subIndex_CRC++, currentCommandID++, (UString)hc.UserName, bitmap); - _commandMap.Add(commandMapItem); } subMenu.Detach(); } } + #ifdef SHOW_DEBUG_CTX_MENU + { char s[256]; sprintf(s, "Commands=%d currentCommandID - commandIDFirst = %d", + _commandMap.Size(), currentCommandID - commandIDFirst); OutputDebugStringA(s); } + #endif + + if (_commandMap.Size() != currentCommandID - commandIDFirst) + throw 20190818; return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID - commandIDFirst); + + } + catch(...) + { + /* we added some menu items already : num_added_menu_items, + So we MUST return (number_of_defined_ids), where (number_of_defined_ids >= num_added_menu_items) + This will prevent incorrect menu working, when same IDs can be + assigned in multiple menu items from different subhandlers. + And we must add items to _commandMap before adding to menu. + */ + #ifdef SHOW_DEBUG_CTX_MENU + { char s[256]; sprintf(s, "catch() exception: Commands=%d", + _commandMap.Size()); OutputDebugStringA(s); } + #endif + // if (_commandMap.Size() != 0) + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, _commandMap.Size()); + // throw; + } + COM_TRY_END } @@ -843,35 +868,122 @@ static UString Get7zFmPath() return fs2us(NWindows::NDLL::GetModuleDirPrefix()) + L"7zFM.exe"; } + +#ifdef UNDER_CE + #define MY__IS_INTRESOURCE(_r) ((((ULONG_PTR)(_r)) >> 16) == 0) +#else + #define MY__IS_INTRESOURCE(_r) IS_INTRESOURCE(_r) +#endif + + +#ifdef SHOW_DEBUG_CTX_MENU +static void PrintStringA(const char *name, LPCSTR ptr) +{ + AString m; + m += name; + m += ": "; + char s[32]; + sprintf(s, "%p", ptr); + m += s; + if (!MY__IS_INTRESOURCE(ptr)) + { + m += ": \""; + m += ptr; + m += "\""; + } + OutputDebugStringA(m); +} + +#if !defined(UNDER_CE) +static void PrintStringW(const char *name, LPCWSTR ptr) +{ + UString m; + m += name; + m += ": "; + char s[32]; + sprintf(s, "%p", ptr); + m += s; + if (!MY__IS_INTRESOURCE(ptr)) + { + m += ": \""; + m += ptr; + m += "\""; + } + OutputDebugStringW(m); +} +#endif +#endif + + STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo) { - // ::OutputDebugStringA("1"); - int commandOffset; + COM_TRY_BEGIN + + #ifdef SHOW_DEBUG_CTX_MENU + + { char s[1280]; sprintf(s, + #ifdef _WIN64 + "64" + #else + "32" + #endif + ": InvokeCommand: cbSize=%d flags=%x " + , commandInfo->cbSize, commandInfo->fMask); OutputDebugStringA(s); } + + PrintStringA("Verb", commandInfo->lpVerb); + PrintStringA("Parameters", commandInfo->lpParameters); + PrintStringA("Directory", commandInfo->lpDirectory); + #endif + + int commandOffset = -1; - // It's fix for bug: crashing in XP. See example in MSDN: "Creating Context Menu Handlers". + // xp64 / Win10 : explorer.exe sends 0 in lpVerbW + // MSDN: if (IS_INTRESOURCE(lpVerbW)), we must use LOWORD(lpVerb) as sommand offset - #if !defined(UNDER_CE) && defined(_MSC_VER) + // FIXME: MINGW doesn't define CMINVOKECOMMANDINFOEX + #if !defined(UNDER_CE) /* && defined(_MSC_VER) */ + bool unicodeVerb = false; if (commandInfo->cbSize == sizeof(CMINVOKECOMMANDINFOEX) && (commandInfo->fMask & CMIC_MASK_UNICODE) != 0) { LPCMINVOKECOMMANDINFOEX commandInfoEx = (LPCMINVOKECOMMANDINFOEX)commandInfo; - if (HIWORD(commandInfoEx->lpVerbW) == 0) - commandOffset = LOWORD(commandInfo->lpVerb); - else + if (!MY__IS_INTRESOURCE(commandInfoEx->lpVerbW)) + { + unicodeVerb = true; commandOffset = FindVerb(commandInfoEx->lpVerbW); + } + + #ifdef SHOW_DEBUG_CTX_MENU + PrintStringW("VerbW", commandInfoEx->lpVerbW); + PrintStringW("ParametersW", commandInfoEx->lpParametersW); + PrintStringW("DirectoryW", commandInfoEx->lpDirectoryW); + PrintStringW("TitleW", commandInfoEx->lpTitleW); + PrintStringA("Title", commandInfoEx->lpTitle); + #endif } - else + if (!unicodeVerb) #endif - if (HIWORD(commandInfo->lpVerb) == 0) + { + #ifdef SHOW_DEBUG_CTX_MENU + OutputDebugStringA("use non-UNICODE verb"); + #endif + // if (HIWORD(commandInfo->lpVerb) == 0) + if (MY__IS_INTRESOURCE(commandInfo->lpVerb)) commandOffset = LOWORD(commandInfo->lpVerb); else commandOffset = FindVerb(GetUnicodeString(commandInfo->lpVerb)); + } + + #ifdef SHOW_DEBUG_CTX_MENU + { char s[128]; sprintf(s, "commandOffset=%d", + commandOffset); OutputDebugStringA(s); } + #endif if (commandOffset < 0 || (unsigned)commandOffset >= _commandMap.Size()) - return E_FAIL; + return E_INVALIDARG; - const CCommandMapItem commandMapItem = _commandMap[commandOffset]; - ECommandInternalID cmdID = commandMapItem.CommandInternalID; + const CCommandMapItem &cmi = _commandMap[(unsigned)commandOffset]; + ECommandInternalID cmdID = cmi.CommandInternalID; try { @@ -881,10 +993,10 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo) { UString params; params = GetQuotedString(_fileNames[0]); - if (!commandMapItem.ArcType.IsEmpty()) + if (!cmi.ArcType.IsEmpty()) { params += " -t"; - params += commandMapItem.ArcType; + params += cmi.ArcType; } MyCreateProcess(Get7zFmPath(), params); break; @@ -893,7 +1005,7 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo) case kExtractHere: case kExtractTo: { - ExtractArchives(_fileNames, commandMapItem.Folder, + ExtractArchives(_fileNames, cmi.Folder, (cmdID == kExtract), // showDialog (cmdID == kExtractTo) && _elimDup.Val // elimDup ); @@ -919,8 +1031,8 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo) (cmdID == kCompress) || (cmdID == kCompressEmail); bool addExtension = (cmdID == kCompress || cmdID == kCompressEmail); - CompressFiles(commandMapItem.Folder, - commandMapItem.ArcName, commandMapItem.ArcType, + CompressFiles(cmi.Folder, + cmi.ArcName, cmi.ArcType, addExtension, _fileNames, email, showDialog, false); break; @@ -943,6 +1055,8 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo) } break; } + case kCommandNULL: + break; } } catch(...) @@ -950,66 +1064,75 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo) ::MessageBoxW(0, L"Error", L"7-Zip", MB_ICONERROR); } return S_OK; + COM_TRY_END } -static void MyCopyString(void *dest, const wchar_t *src, bool writeInUnicode) + + +static void MyCopyString(void *dest, const UString &src, bool writeInUnicode, UINT size) { + if (size != 0) + size--; if (writeInUnicode) { - MyStringCopy((wchar_t *)dest, src); + UString s = src; + s.DeleteFrom(size); + MyStringCopy((wchar_t *)dest, s); } else - MyStringCopy((char *)dest, (const char *)GetAnsiString(src)); + { + AString s = GetAnsiString(src); + s.DeleteFrom(size); + MyStringCopy((char *)dest, s); + } } + STDMETHODIMP CZipContextMenu::GetCommandString(UINT_PTR commandOffset, UINT uType, - UINT * /* pwReserved */ , LPSTR pszName, UINT /* cchMax */) + UINT * /* pwReserved */ , LPSTR pszName, UINT cchMax) { - int cmdOffset = (int)commandOffset; - switch (uType) + COM_TRY_BEGIN + + const int cmdOffset = (int)commandOffset; + + #ifdef SHOW_DEBUG_CTX_MENU + { char s[256]; sprintf(s, "GetCommandString: cmdOffset=%d uType=%d cchMax = %d", + cmdOffset, uType, cchMax); OutputDebugStringA(s); } + #endif + + if (uType == GCS_VALIDATEA || uType == GCS_VALIDATEW) { - #ifdef UNDER_CE - case GCS_VALIDATE: - #else - case GCS_VALIDATEA: - case GCS_VALIDATEW: - #endif - if (cmdOffset < 0 || (unsigned)cmdOffset >= _commandMap.Size()) - return S_FALSE; - else - return S_OK; + if (cmdOffset < 0 || (unsigned)cmdOffset >= _commandMap.Size()) + return S_FALSE; + else + return S_OK; } + if (cmdOffset < 0 || (unsigned)cmdOffset >= _commandMap.Size()) - return E_FAIL; - #ifdef UNDER_CE - if (uType == GCS_HELPTEXT) - #else + { + #ifdef SHOW_DEBUG_CTX_MENU + OutputDebugStringA("---------------- cmdOffset: E_INVALIDARG"); + #endif + return E_INVALIDARG; + } + + const CCommandMapItem &cmi = _commandMap[(unsigned)cmdOffset]; + if (uType == GCS_HELPTEXTA || uType == GCS_HELPTEXTW) - #endif { - MyCopyString(pszName, _commandMap[cmdOffset].HelpString, - #ifdef UNDER_CE - true - #else - uType == GCS_HELPTEXTW - #endif - ); - return NO_ERROR; + // we can return "Verb" here for debug purposes. + // HelpString; + MyCopyString(pszName, cmi.Verb, uType == GCS_HELPTEXTW, cchMax); + return S_OK; } - #ifdef UNDER_CE - if (uType == GCS_VERB) - #else + if (uType == GCS_VERBA || uType == GCS_VERBW) - #endif { - MyCopyString(pszName, _commandMap[cmdOffset].Verb, - #ifdef UNDER_CE - true - #else - uType == GCS_VERBW - #endif - ); - return NO_ERROR; + MyCopyString(pszName, cmi.Verb, uType == GCS_VERBW, cchMax); + return S_OK; } - return E_FAIL; + + return E_INVALIDARG; + + COM_TRY_END } diff --git a/CPP/7zip/UI/Explorer/ContextMenu.h b/CPP/7zip/UI/Explorer/ContextMenu.h index 3a0eacc8..dddb9fd1 100644 --- a/CPP/7zip/UI/Explorer/ContextMenu.h +++ b/CPP/7zip/UI/Explorer/ContextMenu.h @@ -54,18 +54,18 @@ public: CZipContextMenu(); ~CZipContextMenu(); -private: - struct CCommandMapItem { ECommandInternalID CommandInternalID; UString Verb; - UString HelpString; + // UString HelpString; UString Folder; UString ArcName; UString ArcType; }; +private: + bool _isMenuForFM; UStringVector _fileNames; bool _dropMode; @@ -78,7 +78,8 @@ private: HRESULT GetFileNames(LPDATAOBJECT dataObject, UStringVector &fileNames); int FindVerb(const UString &verb); - bool FillCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &commandMapItem); + void FillCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &cmi); + void AddCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &cmi); void AddMapItem_ForSubMenu(const char *ver); }; diff --git a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp index c38d7257..cb4da016 100644 --- a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp +++ b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp @@ -39,9 +39,16 @@ DEFINE_GUID(CLSID_CZipContextMenu, using namespace NWindows; +extern +HINSTANCE g_hInstance; HINSTANCE g_hInstance = 0; + +extern +HWND g_HWND; HWND g_HWND = 0; +extern +LONG g_DllRefCount; LONG g_DllRefCount = 0; // Reference count of this DLL. @@ -91,7 +98,18 @@ STDMETHODIMP CShellExtClassFactory::LockServer(BOOL /* fLock */) } +#if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) #define NT_CHECK_FAIL_ACTION return FALSE; +#endif + +extern "C" +BOOL WINAPI DllMain( + #ifdef UNDER_CE + HANDLE hInstance + #else + HINSTANCE hInstance + #endif + , DWORD dwReason, LPVOID); extern "C" BOOL WINAPI DllMain( diff --git a/CPP/7zip/UI/Explorer/MyMessages.cpp b/CPP/7zip/UI/Explorer/MyMessages.cpp index 70c2a460..c912504c 100644 --- a/CPP/7zip/UI/Explorer/MyMessages.cpp +++ b/CPP/7zip/UI/Explorer/MyMessages.cpp @@ -26,7 +26,7 @@ void ShowErrorMessageRes(UINT resID) ShowErrorMessageHwndRes(0, resID); } -void ShowErrorMessageDWORD(HWND window, DWORD errorCode) +static void ShowErrorMessageDWORD(HWND window, DWORD errorCode) { ShowErrorMessage(window, NError::MyFormatMessage(errorCode)); } diff --git a/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp b/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp index c9d7910f..9f6e44c8 100644 --- a/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp +++ b/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp @@ -59,14 +59,16 @@ static const bool k_shellex_Statuses[2][4] = #else */ -typedef WINADVAPI LONG (APIENTRY *Func_RegDeleteKeyExW)(HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired, DWORD Reserved); +typedef +// WINADVAPI +LONG (APIENTRY *Func_RegDeleteKeyExW)(HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired, DWORD Reserved); static Func_RegDeleteKeyExW func_RegDeleteKeyExW; static void Init_RegDeleteKeyExW() { if (!func_RegDeleteKeyExW) func_RegDeleteKeyExW = (Func_RegDeleteKeyExW) - GetProcAddress(GetModuleHandleW(L"advapi32.dll"), "RegDeleteKeyExW"); + (void *)GetProcAddress(GetModuleHandleW(L"advapi32.dll"), "RegDeleteKeyExW"); } #define INIT_REG_WOW if (wow != 0) Init_RegDeleteKeyExW(); @@ -80,12 +82,12 @@ static LONG MyRegistry_DeleteKey(HKEY parentKey, LPCTSTR name, UInt32 wow) /* #ifdef _WIN64 - return RegDeleteKeyExW + return RegDeleteKeyExW #else */ - if (!func_RegDeleteKeyExW) - return E_NOTIMPL; - return func_RegDeleteKeyExW + if (!func_RegDeleteKeyExW) + return E_NOTIMPL; + return func_RegDeleteKeyExW // #endif (parentKey, GetUnicodeString(name), wow, 0); } diff --git a/CPP/7zip/UI/Explorer/StdAfx.cpp b/CPP/7zip/UI/Explorer/StdAfx.cpp index 2550270c..d0feea85 100644 --- a/CPP/7zip/UI/Explorer/StdAfx.cpp +++ b/CPP/7zip/UI/Explorer/StdAfx.cpp @@ -1,3 +1,3 @@ // StdAfx.cpp -#include "stdafx.h" +#include "StdAfx.h" diff --git a/CPP/7zip/UI/Far/ExtractEngine.cpp b/CPP/7zip/UI/Far/ExtractEngine.cpp index 3567c048..e6fe2d01 100644 --- a/CPP/7zip/UI/Far/ExtractEngine.cpp +++ b/CPP/7zip/UI/Far/ExtractEngine.cpp @@ -167,6 +167,7 @@ STDMETHODIMP CExtractCallbackImp::MessageError(const wchar_t *message) return CheckBreak2(); } +void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &s); void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &s) { s.Empty(); diff --git a/CPP/7zip/UI/Far/Far.cpp b/CPP/7zip/UI/Far/Far.cpp index 5d92bc40..a9e47916 100644 --- a/CPP/7zip/UI/Far/Far.cpp +++ b/CPP/7zip/UI/Far/Far.cpp @@ -3,6 +3,10 @@ #include "StdAfx.h" +#ifdef __clang__ + #pragma clang diagnostic ignored "-Wmissing-prototypes" +#endif + #include "../../../Common/MyWindows.h" #include "../../../Common/MyInitGuid.h" @@ -39,7 +43,9 @@ const char *g_PluginName_for_Error = "7-Zip"; } +#if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) #define NT_CHECK_FAIL_ACTION return FALSE; +#endif BOOL WINAPI DllMain( #ifdef UNDER_CE diff --git a/CPP/7zip/UI/Far/Far.dsp b/CPP/7zip/UI/Far/Far.dsp index 2433b252..b32ae6fa 100644 --- a/CPP/7zip/UI/Far/Far.dsp +++ b/CPP/7zip/UI/Far/Far.dsp @@ -53,7 +53,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\Far\Plugins\7-Zip\7-ZipFar.dll" /opt:NOWIN98 +# 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:\Progs\Far\Plugins\7-Zip\7-ZipFar.dll" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Far - Win32 Debug" @@ -80,7 +80,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\Far\Plugins\7-Zip\7-ZipFar.dll" /pdbtype:sept +# 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:\Progs\Far\Plugins\7-Zip\7-ZipFar.dll" /pdbtype:sept !ENDIF diff --git a/CPP/7zip/UI/Far/OverwriteDialogFar.cpp b/CPP/7zip/UI/Far/OverwriteDialogFar.cpp index 1171453e..b8fc565f 100644 --- a/CPP/7zip/UI/Far/OverwriteDialogFar.cpp +++ b/CPP/7zip/UI/Far/OverwriteDialogFar.cpp @@ -26,7 +26,7 @@ struct CFileInfoStrings AString Time; }; -void SetFileInfoStrings(const CFileInfo &fileInfo, +static void SetFileInfoStrings(const CFileInfo &fileInfo, CFileInfoStrings &fileInfoStrings) { char buffer[256]; diff --git a/CPP/7zip/UI/Far/Plugin.cpp b/CPP/7zip/UI/Far/Plugin.cpp index 72f81ac9..92b62369 100644 --- a/CPP/7zip/UI/Far/Plugin.cpp +++ b/CPP/7zip/UI/Far/Plugin.cpp @@ -197,10 +197,12 @@ void CPlugin::EnterToDirectory(const UString &dirName) s = ".."; _folder->BindToFolder(s, &newFolder); if (!newFolder) + { if (dirName.IsEmpty()) return; else throw 40325; + } _folder = newFolder; } @@ -457,7 +459,7 @@ static AString PropToString2(const NCOM::CPropVariant &prop, PROPID propID) return s; } -static void AddPropertyString(InfoPanelLine *lines, int &numItems, PROPID propID, const wchar_t *name, +static void AddPropertyString(InfoPanelLine *lines, unsigned &numItems, PROPID propID, const wchar_t *name, const NCOM::CPropVariant &prop) { if (prop.vt != VT_EMPTY) @@ -472,7 +474,7 @@ static void AddPropertyString(InfoPanelLine *lines, int &numItems, PROPID propID } } -static void InsertSeparator(InfoPanelLine *lines, int &numItems) +static void InsertSeparator(InfoPanelLine *lines, unsigned &numItems) { if (numItems < kNumInfoLinesMax) { @@ -528,7 +530,7 @@ void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info) MyStringCopy(m_InfoLines[1].Text, g_StartupInfo.GetMsgString(NMessageID::kArchiveType)); MyStringCopy(m_InfoLines[1].Data, (const char *)UnicodeStringToMultiByte(_archiveTypeName, CP_OEMCP)); - int numItems = 2; + unsigned numItems = 2; { CMyComPtr<IFolderProperties> folderProperties; diff --git a/CPP/7zip/UI/Far/PluginDelete.cpp b/CPP/7zip/UI/Far/PluginDelete.cpp index 95584341..0d19c6e7 100644 --- a/CPP/7zip/UI/Far/PluginDelete.cpp +++ b/CPP/7zip/UI/Far/PluginDelete.cpp @@ -4,6 +4,9 @@ #include <stdio.h> +#include "../../../Common/StringConvert.h" +#include "FarUtils.h" + #include "Messages.h" #include "Plugin.h" #include "UpdateCallbackFar.h" @@ -28,16 +31,37 @@ int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode) g_StartupInfo.GetMsgString(NMessageID::kDeleteDelete), g_StartupInfo.GetMsgString(NMessageID::kDeleteCancel) }; - char msg[1024]; + + // char msg[1024]; + AString str1; + if (numItems == 1) { - sprintf(msg, g_StartupInfo.GetMsgString(NMessageID::kDeleteFile), panelItems[0].FindData.cFileName); - msgItems[1] = msg; + str1 = g_StartupInfo.GetMsgString(NMessageID::kDeleteFile); + AString name (panelItems[0].FindData.cFileName); + const unsigned kSizeLimit = 48; + if (name.Len() > kSizeLimit) + { + UString s = MultiByteToUnicodeString(name, CP_OEMCP); + ReduceString(s, kSizeLimit); + name = UnicodeStringToMultiByte(s, CP_OEMCP); + } + str1.Replace(AString ("%.40s"), name); + msgItems[1] = str1; + // sprintf(msg, g_StartupInfo.GetMsgString(NMessageID::kDeleteFile), panelItems[0].FindData.cFileName); + // msgItems[2] = msg; } else if (numItems > 1) { - sprintf(msg, g_StartupInfo.GetMsgString(NMessageID::kDeleteNumberOfFiles), numItems); - msgItems[1] = msg; + str1 = g_StartupInfo.GetMsgString(NMessageID::kDeleteNumberOfFiles); + { + AString n; + n.Add_UInt32(numItems); + str1.Replace(AString ("%d"), n); + } + msgItems[1] = str1; + // sprintf(msg, g_StartupInfo.GetMsgString(NMessageID::kDeleteNumberOfFiles), numItems); + // msgItems[1] = msg; } if (g_StartupInfo.ShowMessage(FMSG_WARNING, NULL, msgItems, ARRAY_SIZE(msgItems), 2) != 0) return (FALSE); diff --git a/CPP/7zip/UI/Far/PluginWrite.cpp b/CPP/7zip/UI/Far/PluginWrite.cpp index ec0f119b..bf1d13df 100644 --- a/CPP/7zip/UI/Far/PluginWrite.cpp +++ b/CPP/7zip/UI/Far/PluginWrite.cpp @@ -89,7 +89,7 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles( } */ - if (numItems == 0) + if (numItems <= 0) return NFileOperationReturnCode::kError; if (_agent->IsThereReadOnlyArc()) @@ -104,14 +104,18 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles( NCompression::CInfo compressionInfo; compressionInfo.Load(); - int methodIndex = 0; - int i; - for (i = ARRAY_SIZE(g_MethodMap) - 1; i >= 0; i--) + unsigned methodIndex = 0; + + unsigned i; + for (i = ARRAY_SIZE(g_MethodMap); i != 0;) + { + i--; if (compressionInfo.Level >= g_MethodMap[i]) { methodIndex = i; break; } + } const int kMethodRadioIndex = 2; const int kModeRadioIndex = kMethodRadioIndex + 7; @@ -200,10 +204,10 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles( UStringVector fileNames; fileNames.ClearAndReserve(numItems); - for (i = 0; i < numItems; i++) + for (i = 0; i < (unsigned)numItems; i++) fileNames.AddInReserved(MultiByteToUnicodeString(panelItems[i].FindData.cFileName, CP_OEMCP)); CObjArray<const wchar_t *> fileNamePointers(numItems); - for (i = 0; i < numItems; i++) + for (i = 0; i < (unsigned)numItems; i++) fileNamePointers[i] = fileNames[i]; CMyComPtr<IOutFolderArchive> outArchive; @@ -459,29 +463,36 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) const int kMethodRadioIndex = kArchiveNameIndex + 2; const int kModeRadioIndex = kMethodRadioIndex + 7; - - char updateAddToArchiveString[512]; + // char updateAddToArchiveString[512]; + AString str1; { const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex]; const AString s (UnicodeStringToMultiByte(arcInfo.Name, CP_OEMCP)); + str1 = g_StartupInfo.GetMsgString(NMessageID::kUpdateAddToArchive); + str1.Replace(AString ("%s"), s); + /* sprintf(updateAddToArchiveString, g_StartupInfo.GetMsgString(NMessageID::kUpdateAddToArchive), (const char *)s); + */ } - int methodIndex = 0; - int i; - for (i = ARRAY_SIZE(g_MethodMap) - 1; i >= 0; i--) + unsigned methodIndex = 0; + unsigned i; + for (i = ARRAY_SIZE(g_MethodMap); i != 0;) + { + i--; if (compressionInfo.Level >= g_MethodMap[i]) { methodIndex = i; break; } + } const struct CInitDialogItem initItems[]= { { DI_DOUBLEBOX, 3, 1, 72, kYSize - 2, false, false, 0, false, NMessageID::kUpdateTitle, NULL, NULL }, - { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, -1, updateAddToArchiveString, NULL }, + { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, -1, str1, NULL }, { DI_EDIT, 5, 3, 70, 3, true, false, DIF_HISTORY, false, -1, archiveNameA, kArchiveHistoryKeyName}, // { DI_EDIT, 5, 3, 70, 3, true, false, 0, false, -1, arcName, NULL}, diff --git a/CPP/7zip/UI/Far/makefile b/CPP/7zip/UI/Far/makefile index 621c8d9e..14be13d6 100644 --- a/CPP/7zip/UI/Far/makefile +++ b/CPP/7zip/UI/Far/makefile @@ -20,7 +20,6 @@ CURRENT_OBJS = \ $O\PluginWrite.obj \ $O\ProgressBox.obj \ $O\UpdateCallbackFar.obj \ - $O\UTFConvert.obj \ COMMON_OBJS = \ $O\IntToString.obj \ @@ -29,6 +28,7 @@ COMMON_OBJS = \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ + $O\UTFConvert.obj \ $O\Wildcard.obj \ WIN_OBJS = \ diff --git a/CPP/7zip/UI/FileManager/AboutDialog.cpp b/CPP/7zip/UI/FileManager/AboutDialog.cpp index a644474b..b3455cf5 100644 --- a/CPP/7zip/UI/FileManager/AboutDialog.cpp +++ b/CPP/7zip/UI/FileManager/AboutDialog.cpp @@ -6,6 +6,8 @@ #include "../../MyVersion.h" +#include "../Common/LoadCodecs.h" + #include "AboutDialog.h" #include "PropertyNameRes.h" @@ -23,8 +25,20 @@ static const UInt32 kLangIDs[] = #define LLL_(quote) L##quote #define LLL(quote) LLL_(quote) +extern CCodecs *g_CodecsObj; + bool CAboutDialog::OnInit() { + #ifdef EXTERNAL_CODECS + if (g_CodecsObj) + { + UString s; + g_CodecsObj->GetCodecsErrorMessage(s); + if (!s.IsEmpty()) + MessageBoxW(GetParent(), s, L"7-Zip", MB_ICONERROR); + } + #endif + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); SetItemText(IDT_ABOUT_VERSION, UString("7-Zip " MY_VERSION_CPU)); SetItemText(IDT_ABOUT_DATE, LLL(MY_DATE)); diff --git a/CPP/7zip/UI/FileManager/AboutDialog.rc b/CPP/7zip/UI/FileManager/AboutDialog.rc index 6953c141..b235df0b 100644 --- a/CPP/7zip/UI/FileManager/AboutDialog.rc +++ b/CPP/7zip/UI/FileManager/AboutDialog.rc @@ -18,7 +18,7 @@ CAPTION "About 7-Zip" { DEFPUSHBUTTON "OK", IDOK, bx1, by, bxs, bys PUSHBUTTON "www.7-zip.org", IDB_ABOUT_HOMEPAGE, bx2, by, bxs, bys - ICON IDI_LOGO, -1, m, m, 32, 32, SS_REALSIZEIMAGE, + ICON IDI_LOGO, -1, m, m, 32, 32, SS_REALSIZEIMAGE LTEXT "", IDT_ABOUT_VERSION, m, 54, xc, 8 LTEXT "", IDT_ABOUT_DATE, m, 67, xc, 8 LTEXT MY_COPYRIGHT, -1, m, 80, xc, 8 diff --git a/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp b/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp index 7069e1aa..e1c99d3c 100644 --- a/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp +++ b/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp @@ -86,7 +86,7 @@ HRESULT CAltStreamsFolder::Init(const FString &path /* , IFolderFolder *parentFo { CFileInfo fi; if (!fi.Find(_pathBaseFile)) - return GetLastError(); + return GetLastError_noZero_HRESULT(); } unsigned prefixSize = GetFsParentPrefixSize(_pathBaseFile); @@ -612,7 +612,7 @@ static HRESULT CopyStream( FString destPath = destPathSpec; if (CompareFileNames(destPath, srcPath) == 0) { - RINOK(SendMessageError(callback, "can not copy file onto itself", destPath)); + RINOK(SendMessageError(callback, "Cannot copy file onto itself", destPath)); return E_ABORT; } @@ -716,7 +716,7 @@ STDMETHODIMP CAltStreamsFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UI if (destPath.IsEmpty() /* && !ExtractToStreamCallback */) return E_INVALIDARG; - bool isAltDest = NName::IsAltPathPrefix(destPath);; + bool isAltDest = NName::IsAltPathPrefix(destPath); bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back())); if (isDirectPath) @@ -764,7 +764,7 @@ STDMETHODIMP CAltStreamsFolder::CopyFrom(Int32 /* moveMode */, const wchar_t * / if (CompareFileNames(fromFolderPath, fs2us(_pathPrefix)) == 0) { - RINOK(SendMessageError(callback, "can not copy file onto itself", _pathPrefix)); + RINOK(SendMessageError(callback, "Cannot copy file onto itself", _pathPrefix)); return E_ABORT; } diff --git a/CPP/7zip/UI/FileManager/App.cpp b/CPP/7zip/UI/FileManager/App.cpp index 4c1ea548..512acc53 100644 --- a/CPP/7zip/UI/FileManager/App.cpp +++ b/CPP/7zip/UI/FileManager/App.cpp @@ -117,7 +117,7 @@ void CApp::SetListSettings() HRESULT CApp::CreateOnePanel(int panelIndex, const UString &mainPath, const UString &arcFormat, bool needOpenArc, - bool &archiveIsOpened, bool &encrypted) + COpenResult &openRes) { if (Panels[panelIndex].PanelCreated) return S_OK; @@ -138,7 +138,7 @@ HRESULT CApp::CreateOnePanel(int panelIndex, const UString &mainPath, const UStr return Panels[panelIndex].Create(_window, _window, id, path, arcFormat, &m_PanelCallbackImp[panelIndex], &AppState, needOpenArc, - archiveIsOpened, encrypted); + openRes); } @@ -282,7 +282,7 @@ void CApp::SaveToolbarChanges() } -HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool needOpenArc, bool &archiveIsOpened, bool &encrypted) +HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool needOpenArc, COpenResult &openRes) { _window.Attach(hwnd); @@ -334,21 +334,19 @@ HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcForma { if (NumPanels == 1) Panels[panelIndex]._xSize = xSizes[0] + xSizes[1]; - bool archiveIsOpened2 = false; - bool encrypted2 = false; + + COpenResult openRes2; UString path; if (isMainPanel) path = mainPath; RINOK(CreateOnePanel(panelIndex, path, arcFormat, isMainPanel && needOpenArc, - archiveIsOpened2, encrypted2)); + *(isMainPanel ? &openRes : &openRes2))); if (isMainPanel) { - archiveIsOpened = archiveIsOpened2; - encrypted = encrypted2; - if (needOpenArc && !archiveIsOpened2) + if (needOpenArc && !openRes.ArchiveIsOpened) return S_OK; } } @@ -365,10 +363,10 @@ HRESULT CApp::SwitchOnOffOnePanel() if (NumPanels == 1) { NumPanels++; - bool archiveIsOpened, encrypted; + COpenResult openRes; RINOK(CreateOnePanel(1 - LastFocusedPanel, UString(), UString(), false, // needOpenArc - archiveIsOpened, encrypted)); + openRes)); Panels[1 - LastFocusedPanel].Enable(true); Panels[1 - LastFocusedPanel].Show(SW_SHOWNORMAL); } @@ -414,13 +412,13 @@ void CApp::Release() // reduces path to part that exists on disk (or root prefix of path) // output path is normalized (with WCHAR_PATH_SEPARATOR) -static void ReducePathToRealFileSystemPath(UString &path) +static void Reduce_Path_To_RealFileSystemPath(UString &path) { unsigned prefixSize = GetRootPrefixSize(path); while (!path.IsEmpty()) { - if (NFind::DoesDirExist(us2fs(path))) + if (NFind::DoesDirExist_FollowLink(us2fs(path))) { NName::NormalizeDirPathPrefix(path); break; @@ -431,10 +429,10 @@ static void ReducePathToRealFileSystemPath(UString &path) path.Empty(); break; } - path.DeleteFrom(pos + 1); + path.DeleteFrom((unsigned)(pos + 1)); if ((unsigned)pos + 1 == prefixSize) break; - path.DeleteFrom(pos); + path.DeleteFrom((unsigned)pos); } } @@ -443,7 +441,7 @@ static void ReducePathToRealFileSystemPath(UString &path) static bool CheckFolderPath(const UString &path) { UString pathReduced = path; - ReducePathToRealFileSystemPath(pathReduced); + Reduce_Path_To_RealFileSystemPath(pathReduced); return (pathReduced == path); } */ @@ -463,6 +461,7 @@ static void AddValuePair1(UString &s, UINT resourceID, UInt64 size) s.Add_LF(); } +void AddValuePair2(UString &s, UINT resourceID, UInt64 num, UInt64 size); void AddValuePair2(UString &s, UINT resourceID, UInt64 num, UInt64 size) { if (num == 0) @@ -601,7 +600,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) return; destPath = destPanel.GetFsPath(); if (NumPanels == 1) - ReducePathToRealFileSystemPath(destPath); + Reduce_Path_To_RealFileSystemPath(destPath); } } @@ -660,7 +659,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) { if (NumPanels == 1 || CompareFileNames(destPath, srcPanel.GetFsPath()) == 0) { - srcPanel.MessageBox_Error(L"Can not copy files onto itself"); + srcPanel.MessageBox_Error(L"Cannot copy files onto itself"); return; } @@ -882,9 +881,11 @@ void CApp::OnSetSubFolder(int srcPanelIndex) return; if (!newFolder) { - const UString parentPrefix = srcPanel.GetParentDirPrefix(); - bool archiveIsOpened, encrypted; - destPanel.BindToPath(parentPrefix, UString(), archiveIsOpened, encrypted); + { + const UString parentPrefix = srcPanel.GetParentDirPrefix(); + COpenResult openRes; + destPanel.BindToPath(parentPrefix, UString(), openRes); + } destPanel.RefreshListCtrl(); return; } @@ -936,7 +937,7 @@ void CApp::OnNotify(int /* ctrlID */, LPNMHDR pnmh) g_ToolTipBuffer.Empty(); SetButtonText((int)info->hdr.idFrom, g_ToolTipBuffer); g_ToolTipBufferSys = GetSystemString(g_ToolTipBuffer); - info->lpszText = (LPTSTR)(LPCTSTR)g_ToolTipBufferSys; + info->lpszText = g_ToolTipBufferSys.Ptr_non_const(); return; } #ifndef _UNICODE @@ -946,7 +947,7 @@ void CApp::OnNotify(int /* ctrlID */, LPNMHDR pnmh) info->hinst = 0; g_ToolTipBuffer.Empty(); SetButtonText((int)info->hdr.idFrom, g_ToolTipBuffer); - info->lpszText = (LPWSTR)(LPCWSTR)g_ToolTipBuffer; + info->lpszText = g_ToolTipBuffer.Ptr_non_const(); return; } #endif @@ -971,7 +972,7 @@ void CApp::RefreshTitlePanel(unsigned panelIndex, bool always) RefreshTitle(always); } -void AddUniqueStringToHead(UStringVector &list, const UString &s) +static void AddUniqueStringToHead(UStringVector &list, const UString &s) { for (unsigned i = 0; i < list.Size();) if (s.IsEqualTo_NoCase(list[i])) diff --git a/CPP/7zip/UI/FileManager/App.h b/CPP/7zip/UI/FileManager/App.h index fa8eeaa7..21b160dc 100644 --- a/CPP/7zip/UI/FileManager/App.h +++ b/CPP/7zip/UI/FileManager/App.h @@ -89,22 +89,24 @@ public: STDMETHOD(Drop)(IDataObject * dataObject, DWORD keyState, POINTL pt, DWORD *effect); CDropTarget(): - TargetPanelIndex(-1), - SrcPanelIndex(-1), - m_IsAppTarget(false), - m_Panel(0), - App(0), - m_PanelDropIsAllowed(false), - m_DropIsAllowed(false), m_SelectionIndex(-1), + m_DropIsAllowed(false), + m_PanelDropIsAllowed(false), m_SubFolderIndex(-1), - m_SetPathIsOK(false) {} + m_Panel(NULL), + m_IsAppTarget(false), + m_SetPathIsOK(false), + App(NULL), + SrcPanelIndex(-1), + TargetPanelIndex(-1) + {} CApp *App; int SrcPanelIndex; // index of D&D source_panel int TargetPanelIndex; // what panel to use as target_panel of Application }; + class CApp { public: @@ -173,8 +175,8 @@ public: void OnSetSameFolder(int srcPanelIndex); void OnSetSubFolder(int srcPanelIndex); - HRESULT CreateOnePanel(int panelIndex, const UString &mainPath, const UString &arcFormat, bool needOpenArc, bool &archiveIsOpened, bool &encrypted); - HRESULT Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool needOpenArc, bool &archiveIsOpened, bool &encrypted); + HRESULT CreateOnePanel(int panelIndex, const UString &mainPath, const UString &arcFormat, bool needOpenArc, COpenResult &openRes); + HRESULT Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool needOpenArc, COpenResult &openRes); void Read(); void Save(); void Release(); @@ -196,7 +198,12 @@ public: void Delete(bool toRecycleBin) { GetFocusedPanel().DeleteItems(toRecycleBin); } HRESULT CalculateCrc2(const UString &methodName); void CalculateCrc(const char *methodName); + + void DiffFiles(const UString &path1, const UString &path2); void DiffFiles(); + + void VerCtrl(unsigned id); + void Split(); void Combine(); void Properties() { GetFocusedPanel().Properties(); } diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp index d8f9ebe8..6d2b6b55 100644 --- a/CPP/7zip/UI/FileManager/BrowseDialog.cpp +++ b/CPP/7zip/UI/FileManager/BrowseDialog.cpp @@ -4,7 +4,7 @@ #include "../../../Common/MyWindows.h" -#include <commctrl.h> +#include <CommCtrl.h> #ifndef UNDER_CE #include "../../../Windows/CommonDialog.h" @@ -139,7 +139,7 @@ public: UStringVector Filters; UString FilterDescription; - CBrowseDialog(): FolderMode(false), _showDots(false), ShowAllFiles(true) {} + CBrowseDialog(): _showDots(false), FolderMode(false), ShowAllFiles(true) {} void SetFilter(const UString &s); INT_PTR Create(HWND parent = 0) { return CModalDialog::Create(IDD_BROWSE, parent); } int CompareItems(LPARAM lParam1, LPARAM lParam2); @@ -235,7 +235,7 @@ bool CBrowseDialog::OnInit() column.fmt = LVCFMT_RIGHT; column.cx = 100; const UString s = LangString(IDS_PROP_SIZE); - column.pszText = (wchar_t *)(const wchar_t *)s; + column.pszText = s.Ptr_non_const(); _list.InsertColumn(2, &column); } @@ -476,7 +476,7 @@ bool CBrowseDialog::GetParentPath(const UString &path, UString &parentPrefix, US return false; int pos = s.ReverseFind_PathSepar(); parentPrefix.SetFrom(s, pos + 1); - name = s.Ptr(pos + 1); + name = s.Ptr((unsigned)(pos + 1)); return true; } @@ -604,7 +604,7 @@ HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selected int subItem = 0; item.iSubItem = subItem++; item.lParam = kParentIndex; - item.pszText = (wchar_t *)(const wchar_t *)itemName; + item.pszText = itemName.Ptr_non_const(); item.iImage = _extToIconMap.GetIconIndex(FILE_ATTRIBUTE_DIRECTORY, DirPrefix); if (item.iImage < 0) item.iImage = 0; @@ -626,7 +626,7 @@ HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selected int subItem = 0; item.iSubItem = subItem++; item.lParam = i; - item.pszText = (wchar_t *)(const wchar_t *)name; + item.pszText = name.Ptr_non_const(); const UString fullPath = DirPrefix + name; #ifndef UNDER_CE @@ -953,7 +953,7 @@ bool CorrectFsPath(const UString &relBase, const UString &path2, UString &result if (path.Back() == WCHAR_PATH_SEPARATOR) { path.DeleteBack(); - result.Insert(0, WCHAR_PATH_SEPARATOR);; + result.Insert(0, WCHAR_PATH_SEPARATOR); } int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR) + 1; UString cur = path.Ptr(pos); diff --git a/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp b/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp index cba9aa21..389aa3e8 100644 --- a/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp +++ b/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp @@ -58,7 +58,7 @@ CEnumFormatEtc::~CEnumFormatEtc() for (ULONG i = 0; i < m_NumFormats; i++) if (m_Formats[i].ptd) CoTaskMemFree(m_Formats[i].ptd); - delete[]m_Formats; + delete []m_Formats; } } diff --git a/CPP/7zip/UI/FileManager/EnumFormatEtc.h b/CPP/7zip/UI/FileManager/EnumFormatEtc.h index 6c476f1a..93a53cb3 100644 --- a/CPP/7zip/UI/FileManager/EnumFormatEtc.h +++ b/CPP/7zip/UI/FileManager/EnumFormatEtc.h @@ -3,7 +3,7 @@ #ifndef __ENUMFORMATETC_H #define __ENUMFORMATETC_H -#include <windows.h> +#include "../../../Common/MyWindows.h" HRESULT CreateEnumFormatEtc(UINT numFormats, const FORMATETC *formats, IEnumFORMATETC **enumFormat); diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/CPP/7zip/UI/FileManager/ExtractCallback.cpp index 1bc96ae3..0e285f04 100644 --- a/CPP/7zip/UI/FileManager/ExtractCallback.cpp +++ b/CPP/7zip/UI/FileManager/ExtractCallback.cpp @@ -262,6 +262,7 @@ STDMETHODIMP CExtractCallbackImp::ShowMessage(const wchar_t *s) #endif +void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s); void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s) { s.Empty(); @@ -449,6 +450,7 @@ static void AddNewLineString(UString &s, const UString &m) s.Add_LF(); } +UString GetOpenArcErrorMessage(UInt32 errorFlags); UString GetOpenArcErrorMessage(UInt32 errorFlags) { UString s; @@ -523,6 +525,7 @@ static UString GetBracedType(const wchar_t *type) return s; } +void OpenResult_GUI(UString &s, const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result); void OpenResult_GUI(UString &s, const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) { FOR_VECTOR (level, arcLink.Arcs) @@ -632,7 +635,9 @@ HRESULT CExtractCallbackImp::ExtractResult(HRESULT result) if (result == S_OK) return result; NumArchiveErrors++; - if (result == E_ABORT || result == ERROR_DISK_FULL) + if (result == E_ABORT + || result == HRESULT_FROM_WIN32(ERROR_DISK_FULL) + ) return result; Add_ArchiveName_Error(); @@ -702,7 +707,7 @@ STDMETHODIMP CExtractCallbackImp::AskWrite( { if (!destFileInfo.IsDir()) { - RINOK(MessageError("can not replace file with folder with same name", destPathSys)); + RINOK(MessageError("Cannot replace file with folder with same name", destPathSys)); return E_ABORT; } *writeAnswer = BoolToInt(false); @@ -711,7 +716,7 @@ STDMETHODIMP CExtractCallbackImp::AskWrite( if (destFileInfo.IsDir()) { - RINOK(MessageError("can not replace folder with file with same name", destPathSys)); + RINOK(MessageError("Cannot replace folder with file with same name", destPathSys)); *writeAnswer = BoolToInt(false); return S_OK; } @@ -725,7 +730,7 @@ STDMETHODIMP CExtractCallbackImp::AskWrite( Int32 overwriteResult; UString destPathSpec = destPath; int slashPos = destPathSpec.ReverseFind_PathSepar(); - destPathSpec.DeleteFrom(slashPos + 1); + destPathSpec.DeleteFrom((unsigned)(slashPos + 1)); destPathSpec += fs2us(destFileInfo.Name); RINOK(AskOverwrite( @@ -746,25 +751,28 @@ STDMETHODIMP CExtractCallbackImp::AskWrite( default: return E_FAIL; } + break; } + default: + break; } if (OverwriteMode == NExtract::NOverwriteMode::kRename) { if (!AutoRenamePath(destPathSys)) { - RINOK(MessageError("can not create name for file", destPathSys)); + RINOK(MessageError("Cannot create name for file", destPathSys)); return E_ABORT; } destPathResultTemp = fs2us(destPathSys); } else { - if (NFind::DoesFileExist(destPathSys)) + if (NFind::DoesFileExist_Raw(destPathSys)) if (!NDir::DeleteFileAlways(destPathSys)) if (GetLastError() != ERROR_FILE_NOT_FOUND) { - RINOK(MessageError("can not delete output file", destPathSys)); + RINOK(MessageError("Cannot delete output file", destPathSys)); return E_ABORT; } } @@ -950,9 +958,8 @@ STDMETHODIMP CExtractCallbackImp::SetOperationResult7(Int32 opRes, Int32 encrypt } -static const size_t k_SizeT_MAX = (size_t)((size_t)0 - 1); -static const UInt32 kBlockSize = ((UInt32)1 << 31); +// static const UInt32 kBlockSize = ((UInt32)1 << 31); STDMETHODIMP CVirtFileSystem::Write(const void *data, UInt32 size, UInt32 *processedSize) { @@ -977,8 +984,9 @@ STDMETHODIMP CVirtFileSystem::Write(const void *data, UInt32 size, UInt32 *proce if (b < a) b = a; useMem = false; - if (b <= k_SizeT_MAX && b <= MaxTotalAllocSize) - useMem = file.Data.ReAlloc_KeepData((size_t)b, (size_t)file.Size); + const size_t b_sizet = (size_t)b; + if (b == b_sizet && b <= MaxTotalAllocSize) + useMem = file.Data.ReAlloc_KeepData(b_sizet, (size_t)file.Size); } if (useMem) { diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.h b/CPP/7zip/UI/FileManager/ExtractCallback.h index 6cd8d0aa..297492eb 100644 --- a/CPP/7zip/UI/FileManager/ExtractCallback.h +++ b/CPP/7zip/UI/FileManager/ExtractCallback.h @@ -289,21 +289,19 @@ public: bool MultiArcMode; CExtractCallbackImp(): + #ifndef _SFX + _hashCalc(NULL), + #endif + ProcessAltStreams(true), + StreamMode(false), + OverwriteMode(NExtract::NOverwriteMode::kAsk), #ifndef _NO_CRYPTO PasswordIsDefined(false), PasswordWasAsked(false), #endif - OverwriteMode(NExtract::NOverwriteMode::kAsk), - StreamMode(false), - ProcessAltStreams(true), - _totalFilesDefined(false), _totalBytesDefined(false), MultiArcMode(false) - - #ifndef _SFX - , _hashCalc(NULL) - #endif {} ~CExtractCallbackImp(); diff --git a/CPP/7zip/UI/FileManager/FM.cpp b/CPP/7zip/UI/FileManager/FM.cpp index 3e7f104d..812eff67 100644 --- a/CPP/7zip/UI/FileManager/FM.cpp +++ b/CPP/7zip/UI/FileManager/FM.cpp @@ -4,7 +4,7 @@ #include "../../../Common/MyWindows.h" -#include <shlwapi.h> +#include <Shlwapi.h> #include "../../../../C/Alloc.h" #ifdef _WIN32 @@ -40,19 +40,24 @@ using namespace NWindows; using namespace NFile; using namespace NFind; -#define MAX_LOADSTRING 100 - -#define MENU_HEIGHT 26 +// #define MAX_LOADSTRING 100 +extern +bool g_RAM_Size_Defined; bool g_RAM_Size_Defined; -bool g_LargePagesMode = false; -bool g_OpenArchive = false; + +static bool g_LargePagesMode = false; +// static bool g_OpenArchive = false; static bool g_Maximized = false; +extern +UInt64 g_RAM_Size; UInt64 g_RAM_Size; #ifdef _WIN32 +extern +HINSTANCE g_hInstance; HINSTANCE g_hInstance; #endif @@ -66,6 +71,8 @@ void FreeGlobalCodecs(); #ifndef UNDER_CE +extern +DWORD g_ComCtl32Version; DWORD g_ComCtl32Version; static DWORD GetDllVersion(LPCTSTR dllName) @@ -74,7 +81,7 @@ static DWORD GetDllVersion(LPCTSTR dllName) HINSTANCE hinstDll = LoadLibrary(dllName); if (hinstDll) { - DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion"); + DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)(void *)GetProcAddress(hinstDll, "DllGetVersion"); if (pDllGetVersion) { DLLVERSIONINFO dvi; @@ -93,19 +100,19 @@ static DWORD GetDllVersion(LPCTSTR dllName) bool g_IsSmallScreen = false; +extern +bool g_LVN_ITEMACTIVATE_Support; bool g_LVN_ITEMACTIVATE_Support = true; // LVN_ITEMACTIVATE replaces both NM_DBLCLK & NM_RETURN // Windows 2000 // NT/98 + IE 3 (g_ComCtl32Version >= 4.70) -const int kNumDefaultPanels = 1; - -const int kSplitterWidth = 4; -int kSplitterRateMax = 1 << 16; -int kPanelSizeMin = 120; +static const int kNumDefaultPanels = 1; +static const int kSplitterWidth = 4; +static const int kSplitterRateMax = 1 << 16; +static const int kPanelSizeMin = 120; -// bool OnMenuCommand(HWND hWnd, int id); class CSplitterPos { @@ -343,7 +350,7 @@ typedef BOOL (WINAPI *Func_IsWow64Process)(HANDLE, PBOOL); static void Set_Wow64() { g_Is_Wow64 = false; - Func_IsWow64Process fnIsWow64Process = (Func_IsWow64Process)GetProcAddress( + Func_IsWow64Process fnIsWow64Process = (Func_IsWow64Process)(void *)GetProcAddress( GetModuleHandleA("kernel32.dll"), "IsWow64Process"); if (fnIsWow64Process) { @@ -356,6 +363,7 @@ static void Set_Wow64() #endif +bool IsLargePageSupported(); bool IsLargePageSupported() { #ifdef _WIN64 @@ -383,7 +391,7 @@ static void SetMemoryLock() if (!IsLargePageSupported()) return; // if (ReadLockMemoryAdd()) - NSecurity::AddLockMemoryPrivilege(); + NSecurity::AddLockMemoryPrivilege(); if (ReadLockMemoryEnable()) if (NSecurity::Get_LargePages_RiskLevel() == 0) @@ -393,6 +401,8 @@ static void SetMemoryLock() } } +extern +bool g_SymLink_Supported; bool g_SymLink_Supported = false; static void Set_SymLink_Supported() @@ -443,7 +453,9 @@ static void ErrorMessage(const char *s) } +#if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) #define NT_CHECK_FAIL_ACTION ErrorMessage("Unsupported Windows version"); return 1; +#endif static int WINAPI WinMain2(int nCmdShow) { @@ -756,12 +768,12 @@ static void ExecuteCommand(UINT commandID) LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - int wmId, wmEvent; switch (message) { case WM_COMMAND: - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); + { + unsigned wmId = LOWORD(wParam); + unsigned wmEvent = HIWORD(wParam); if ((HWND) lParam != NULL && wmEvent != 0) break; if (wmId >= kMenuCmdID_Toolbar_Start && wmId < kMenuCmdID_Toolbar_End) @@ -772,6 +784,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) if (OnMenuCommand(hWnd, wmId)) return 0; break; + } case WM_INITMENUPOPUP: OnMenuActivating(hWnd, HMENU(wParam), LOWORD(lParam)); break; @@ -837,9 +850,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) g_App.CreateDragTarget(); - bool archiveIsOpened; - bool encrypted; - bool needOpenFile = false; + COpenResult openRes; + bool needOpenArc = false; UString fullPath = g_MainPath; if (!fullPath.IsEmpty() /* && g_OpenArchive */) @@ -850,29 +862,34 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) if (NFile::NName::GetFullPath(us2fs(fullPath), fullPathF)) fullPath = fs2us(fullPathF); } - if (NFile::NFind::DoesFileExist(us2fs(fullPath))) - needOpenFile = true; + if (NFile::NFind::DoesFileExist_FollowLink(us2fs(fullPath))) + needOpenArc = true; } HRESULT res = g_App.Create(hWnd, fullPath, g_ArcFormat, xSizes, - needOpenFile, - archiveIsOpened, encrypted); + needOpenArc, + openRes); if (res == E_ABORT) return -1; - if (needOpenFile && !archiveIsOpened || res != S_OK) + if ((needOpenArc && !openRes.ArchiveIsOpened) || res != S_OK) { UString m ("Error"); if (res == S_FALSE || res == S_OK) { - m = MyFormatNew(encrypted ? + m = MyFormatNew(openRes.Encrypted ? IDS_CANT_OPEN_ENCRYPTED_ARCHIVE : IDS_CANT_OPEN_ARCHIVE, fullPath); } else if (res != S_OK) m = HResultToMessage(res); + if (!openRes.ErrorMessage.IsEmpty()) + { + m.Add_LF(); + m += openRes.ErrorMessage; + } ErrorMessage(m); return -1; } @@ -954,7 +971,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) g_Panel[1]._listView.MoveWindow(xSize - xWidth, 0, xWidth, ySize); */ return 0; - break; + // break; } case WM_SETFOCUS: diff --git a/CPP/7zip/UI/FileManager/FM.dsp b/CPP/7zip/UI/FileManager/FM.dsp index 69d285cb..d87beff5 100644 --- a/CPP/7zip/UI/FileManager/FM.dsp +++ b/CPP/7zip/UI/FileManager/FM.dsp @@ -55,7 +55,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /opt:NOWIN98 +# 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:\Util\7zFM.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "FM - Win32 Debug" @@ -82,7 +82,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Util\7zFM.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "FM - Win32 ReleaseU" @@ -109,7 +109,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /opt:NOWIN98 +# 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:\Util\7zFM.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "FM - Win32 DebugU" @@ -137,7 +137,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7zFM.exe" /pdbtype:sept +# 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:\Util\7zFM.exe" /pdbtype:sept !ENDIF @@ -393,6 +393,10 @@ SOURCE=.\PanelSort.cpp SOURCE=.\PanelSplitFile.cpp # End Source File +# Begin Source File + +SOURCE=.\VerCtrl.cpp +# End Source File # End Group # Begin Group "Dialog" diff --git a/CPP/7zip/UI/FileManager/FM.mak b/CPP/7zip/UI/FileManager/FM.mak index 654da627..8b3d97af 100644 --- a/CPP/7zip/UI/FileManager/FM.mak +++ b/CPP/7zip/UI/FileManager/FM.mak @@ -7,8 +7,8 @@ LIBS = $(LIBS) ceshell.lib Commctrl.lib !ELSE LIBS = $(LIBS) comctl32.lib htmlhelp.lib comdlg32.lib Mpr.lib Gdi32.lib CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -DSUPPORT_DEVICE_FILE -LFLAGS = $(LFLAGS) /DELAYLOAD:mpr.dll -LIBS = $(LIBS) delayimp.lib +LFLAGS = $(LFLAGS) /DELAYLOAD:mpr.dll +LIBS = $(LIBS) delayimp.lib !ENDIF FM_OBJS = \ @@ -70,6 +70,7 @@ FM_OBJS = \ $O\SettingsPage.obj \ $O\SplitDialog.obj \ $O\SystemPage.obj \ + $O\VerCtrl.obj \ !IFNDEF UNDER_CE diff --git a/CPP/7zip/UI/FileManager/FSFolder.cpp b/CPP/7zip/UI/FileManager/FSFolder.cpp index 9e720214..d82ddc27 100644 --- a/CPP/7zip/UI/FileManager/FSFolder.cpp +++ b/CPP/7zip/UI/FileManager/FSFolder.cpp @@ -115,15 +115,15 @@ HRESULT CFsFolderStat::Enumerate() const unsigned len = Path.Len(); CEnumerator enumerator; enumerator.SetDirPrefix(Path); - CFileInfo fi; + CDirEntry fi; while (enumerator.Next(fi)) { if (fi.IsDir()) { + NumFolders++; Path.DeleteFrom(len); Path += fi.Name; RINOK(Enumerate()); - NumFolders++; } else { @@ -136,6 +136,7 @@ HRESULT CFsFolderStat::Enumerate() #ifndef UNDER_CE +bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size); bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size) { DWORD highPart; @@ -171,7 +172,7 @@ bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size) HRESULT CFSFolder::LoadSubItems(int dirItem, const FString &relPrefix) { - unsigned startIndex = Folders.Size(); + const unsigned startIndex = Folders.Size(); { CEnumerator enumerator; enumerator.SetDirPrefix(_path + relPrefix); @@ -261,7 +262,7 @@ HRESULT CFSFolder::LoadSubItems(int dirItem, const FString &relPrefix) if (!_flatMode) return S_OK; - unsigned endIndex = Folders.Size(); + const unsigned endIndex = Folders.Size(); for (unsigned i = startIndex; i < endIndex; i++) LoadSubItems(i, Folders[i]); return S_OK; @@ -293,8 +294,9 @@ bool CFSFolder::LoadComments() return false; AString s; char *p = s.GetBuf((unsigned)(size_t)len); - UInt32 processedSize; - file.Read(p, (UInt32)len, processedSize); + size_t processedSize; + if (!file.ReadFull(p, (unsigned)(size_t)len, processedSize)) + return false; s.ReleaseBuf_CalcLen((unsigned)(size_t)len); if (processedSize != len) return false; @@ -506,7 +508,7 @@ STDMETHODIMP CFSFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va { int pos = comment.Find((wchar_t)4); if (pos >= 0) - comment.DeleteFrom(pos); + comment.DeleteFrom((unsigned)pos); prop = comment; } break; @@ -784,7 +786,7 @@ STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder) return E_FAIL; FString parentPath = _path.Left(pos); pos = parentPath.ReverseFind_PathSepar(); - parentPath.DeleteFrom(pos + 1); + parentPath.DeleteFrom((unsigned)(pos + 1)); if (NName::IsDrivePath_SuperAllowed(parentPath)) { diff --git a/CPP/7zip/UI/FileManager/FSFolder.h b/CPP/7zip/UI/FileManager/FSFolder.h index a7d78993..fac1ef97 100644 --- a/CPP/7zip/UI/FileManager/FSFolder.h +++ b/CPP/7zip/UI/FileManager/FSFolder.h @@ -203,7 +203,7 @@ struct CCopyStateIO int ErrorFileIndex; UString ErrorMessage; - CCopyStateIO(): DeleteSrcFile(false), TotalSize(0), StartPos(0) {} + CCopyStateIO(): TotalSize(0), StartPos(0), DeleteSrcFile(false) {} HRESULT MyCopyFile(CFSTR inPath, CFSTR outPath, DWORD attrib = INVALID_FILE_ATTRIBUTES); }; diff --git a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp index 7f95b1d2..9b78ba0a 100644 --- a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp +++ b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp @@ -4,7 +4,7 @@ #include "../../../Common/MyWindows.h" -#include <Winbase.h> +#include <WinBase.h> #include "../../../Common/Defs.h" #include "../../../Common/StringConvert.h" @@ -397,8 +397,8 @@ static HRESULT CopyFile_Ask( { RINOK(SendMessageError(state.Callback, state.MoveMode ? - "can not move file onto itself" : - "can not copy file onto itself" + "Cannot move file onto itself" : + "Cannot copy file onto itself" , destPath)); return E_ABORT; } @@ -497,8 +497,8 @@ static HRESULT CopyFolder( { RINOK(SendMessageError(state.Callback, state.MoveMode ? - "can not copy folder onto itself" : - "can not move folder onto itself" + "Cannot copy folder onto itself" : + "Cannot move folder onto itself" , destPath)); return E_ABORT; } @@ -513,7 +513,7 @@ static HRESULT CopyFolder( if (!CreateComplexDir(destPath)) { - RINOK(SendMessageError(state.Callback, "can not create folder", destPath)); + RINOK(SendMessageError(state.Callback, "Cannot create folder", destPath)); return E_ABORT; } @@ -547,7 +547,7 @@ static HRESULT CopyFolder( { if (!RemoveDir(srcPath)) { - RINOK(SendMessageError(state.Callback, "can not remove folder", srcPath)); + RINOK(SendMessageError(state.Callback, "Cannot remove folder", srcPath)); return E_ABORT; } } @@ -566,7 +566,7 @@ STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num if (destPath.IsEmpty()) return E_INVALIDARG; - bool isAltDest = NName::IsAltPathPrefix(destPath);; + bool isAltDest = NName::IsAltPathPrefix(destPath); bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back())); if (isDirectPath) diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp index 4e964628..a7873fe5 100644 --- a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp +++ b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp @@ -8,10 +8,14 @@ #include "../../../Windows/Thread.h" #include "../Agent/Agent.h" +#include "../GUI/ExtractRes.h" +#include "FileFolderPluginOpen.h" +#include "FormatUtils.h" #include "LangUtils.h" #include "OpenCallback.h" #include "PluginLoader.h" +#include "PropertyName.h" #include "RegistryPlugins.h" using namespace NWindows; @@ -69,18 +73,165 @@ static void SplitNameToPureNameAndExtension(const FString &fullName, { pureName.SetFrom(fullName, index); extensionDelimiter = '.'; - extension = fullName.Ptr(index + 1); + extension = fullName.Ptr((unsigned)index + 1); } } -HRESULT OpenFileFolderPlugin( - IInStream *inStream, - const FString &path, - const UString &arcFormat, - HMODULE *module, - IFolderFolder **resultFolder, - HWND parentWindow, - bool &encrypted, UString &password) + +struct CArcLevelInfo +{ + UString Error; + UString Path; + UString Type; + UString ErrorType; + UString ErrorFlags; +}; + + +struct CArcLevelsInfo +{ + CObjectVector<CArcLevelInfo> Levels; // LastLevel Is NON-OPEN +}; + + +UString GetOpenArcErrorMessage(UInt32 errorFlags); + + +static void GetFolderLevels(CMyComPtr<IFolderFolder> &folder, CArcLevelsInfo &levels) +{ + levels.Levels.Clear(); + + CMyComPtr<IGetFolderArcProps> getFolderArcProps; + folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps); + + if (!getFolderArcProps) + return; + CMyComPtr<IFolderArcProps> arcProps; + getFolderArcProps->GetFolderArcProps(&arcProps); + if (!arcProps) + return; + + UInt32 numLevels; + if (arcProps->GetArcNumLevels(&numLevels) != S_OK) + numLevels = 0; + + for (UInt32 level = 0; level <= numLevels; level++) + { + const PROPID propIDs[] = { kpidError, kpidPath, kpidType, kpidErrorType }; + + CArcLevelInfo lev; + + for (Int32 i = 0; i < 4; i++) + { + CMyComBSTR name; + NCOM::CPropVariant prop; + if (arcProps->GetArcProp(level, propIDs[i], &prop) != S_OK) + continue; + if (prop.vt != VT_EMPTY) + { + UString *s = NULL; + switch (propIDs[i]) + { + case kpidError: s = &lev.Error; break; + case kpidPath: s = &lev.Path; break; + case kpidType: s = &lev.Type; break; + case kpidErrorType: s = &lev.ErrorType; break; + } + *s = (prop.vt == VT_BSTR) ? prop.bstrVal : L"?"; + } + } + + { + NCOM::CPropVariant prop; + if (arcProps->GetArcProp(level, kpidErrorFlags, &prop) == S_OK) + { + UInt32 flags = GetOpenArcErrorFlags(prop); + if (flags != 0) + lev.ErrorFlags = GetOpenArcErrorMessage(flags); + } + } + + levels.Levels.Add(lev); + } +} + +static UString GetBracedType(const wchar_t *type) +{ + UString s ('['); + s += type; + s += ']'; + return s; +} + +static void GetFolderError(CMyComPtr<IFolderFolder> &folder, UString &open_Errors, UString &nonOpen_Errors) +{ + CArcLevelsInfo levs; + GetFolderLevels(folder, levs); + open_Errors.Empty(); + nonOpen_Errors.Empty(); + + FOR_VECTOR (i, levs.Levels) + { + bool isNonOpenLevel = (i == 0); + const CArcLevelInfo &lev = levs.Levels[levs.Levels.Size() - 1 - i]; + + UString m; + + if (!lev.ErrorType.IsEmpty()) + { + m = MyFormatNew(IDS_CANT_OPEN_AS_TYPE, GetBracedType(lev.ErrorType)); + if (!isNonOpenLevel) + { + m.Add_LF(); + m += MyFormatNew(IDS_IS_OPEN_AS_TYPE, GetBracedType(lev.Type)); + } + } + + if (!lev.Error.IsEmpty()) + { + if (!m.IsEmpty()) + m.Add_LF(); + m += GetBracedType(lev.Type); + m += " : "; + m += GetNameOfProperty(kpidError, L"Error"); + m += " : "; + m += lev.Error; + } + + if (!lev.ErrorFlags.IsEmpty()) + { + if (!m.IsEmpty()) + m.Add_LF(); + m += GetNameOfProperty(kpidErrorFlags, L"Errors"); + m += ": "; + m += lev.ErrorFlags; + } + + if (!m.IsEmpty()) + { + if (isNonOpenLevel) + { + UString &s = nonOpen_Errors; + s += lev.Path; + s.Add_LF(); + s += m; + } + else + { + UString &s = open_Errors; + if (!s.IsEmpty()) + s += "--------------------\n"; + s += lev.Path; + s.Add_LF(); + s += m; + } + } + } +} + + +HRESULT CFfpOpen::OpenFileFolderPlugin(IInStream *inStream, + const FString &path, const UString &arcFormat, HWND parentWindow) { CObjectVector<CPluginInfo> plugins; ReadFileFolderPluginInfoList(plugins); @@ -92,8 +243,8 @@ HRESULT OpenFileFolderPlugin( FString fileName; if (slashPos >= 0) { - dirPrefix.SetFrom(path, slashPos + 1); - fileName = path.Ptr(slashPos + 1); + dirPrefix.SetFrom(path, (unsigned)(slashPos + 1)); + fileName = path.Ptr((unsigned)(slashPos + 1)); } else fileName = path; @@ -120,6 +271,8 @@ HRESULT OpenFileFolderPlugin( } */ + ErrorMessage.Empty(); + FOR_VECTOR (i, plugins) { const CPluginInfo &plugin = plugins[i]; @@ -136,24 +289,29 @@ HRESULT OpenFileFolderPlugin( t.OpenCallbackSpec = new COpenArchiveCallback; t.OpenCallback = t.OpenCallbackSpec; - t.OpenCallbackSpec->PasswordIsDefined = encrypted; - t.OpenCallbackSpec->Password = password; + t.OpenCallbackSpec->PasswordIsDefined = Encrypted; + t.OpenCallbackSpec->Password = Password; t.OpenCallbackSpec->ParentWindow = parentWindow; if (inStream) t.OpenCallbackSpec->SetSubArchiveName(fs2us(fileName)); else - t.OpenCallbackSpec->LoadFileInfo(dirPrefix, fileName); + { + RINOK(t.OpenCallbackSpec->LoadFileInfo2(dirPrefix, fileName)); + } t.InStream = inStream; t.Path = fs2us(path); t.ArcFormat = arcFormat; - UString progressTitle = LangString(IDS_OPENNING); - t.OpenCallbackSpec->ProgressDialog.MainWindow = parentWindow; - t.OpenCallbackSpec->ProgressDialog.MainTitle = "7-Zip"; // LangString(IDS_APP_TITLE); - t.OpenCallbackSpec->ProgressDialog.MainAddTitle = progressTitle + L' '; - t.OpenCallbackSpec->ProgressDialog.WaitMode = true; + const UString progressTitle = LangString(IDS_OPENNING); + { + CProgressDialog &pd = t.OpenCallbackSpec->ProgressDialog; + pd.MainWindow = parentWindow; + pd.MainTitle = "7-Zip"; // LangString(IDS_APP_TITLE); + pd.MainAddTitle = progressTitle + L' '; + pd.WaitMode = true; + } { NWindows::CThread thread; @@ -161,23 +319,39 @@ HRESULT OpenFileFolderPlugin( t.OpenCallbackSpec->StartProgressDialog(progressTitle, thread); } - if (t.Result == E_ABORT) + if (t.Result != S_FALSE && t.Result != S_OK) return t.Result; - encrypted = t.OpenCallbackSpec->PasswordIsDefined; - if (t.Result == S_OK) + if (t.Folder) { - // if (openCallbackSpec->PasswordWasAsked) + UString open_Errors, nonOpen_Errors; + GetFolderError(t.Folder, open_Errors, nonOpen_Errors); + if (!nonOpen_Errors.IsEmpty()) { - password = t.OpenCallbackSpec->Password; + ErrorMessage = nonOpen_Errors; + // if (t.Result != S_OK) return t.Result; + /* if there are good open leves, and non0open level, + we could force error as critical error and return error here + but it's better to allow to open such rachives */ + // return S_FALSE; } - *module = library.Detach(); - *resultFolder = t.Folder.Detach(); - return S_OK; + } + + // if (openCallbackSpec->PasswordWasAsked) + { + Encrypted = t.OpenCallbackSpec->PasswordIsDefined; + Password = t.OpenCallbackSpec->Password; + } + + if (t.Result == S_OK) + { + Library.Attach(library.Detach()); + // Folder.Attach(t.Folder.Detach()); + Folder = t.Folder; } - if (t.Result != S_FALSE) - return t.Result; + return t.Result; } + return S_FALSE; } diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h index 593880e9..a1f2f104 100644 --- a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h +++ b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h @@ -3,7 +3,25 @@ #ifndef __FILE_FOLDER_PLUGIN_OPEN_H #define __FILE_FOLDER_PLUGIN_OPEN_H -HRESULT OpenFileFolderPlugin(IInStream *inStream, const FString &path, const UString &arcFormat, - HMODULE *module, IFolderFolder **resultFolder, HWND parentWindow, bool &encrypted, UString &password); +#include "../../../Windows/DLL.h" + +struct CFfpOpen +{ + CLASS_NO_COPY(CFfpOpen) +public: + // out: + bool Encrypted; + UString Password; + + NWindows::NDLL::CLibrary Library; + CMyComPtr<IFolderFolder> Folder; + UString ErrorMessage; + + CFfpOpen(): Encrypted (false) {} + + HRESULT OpenFileFolderPlugin(IInStream *inStream, + const FString &path, const UString &arcFormat, HWND parentWindow); +}; + #endif diff --git a/CPP/7zip/UI/FileManager/HelpUtils.cpp b/CPP/7zip/UI/FileManager/HelpUtils.cpp index c0f57990..2db95014 100644 --- a/CPP/7zip/UI/FileManager/HelpUtils.cpp +++ b/CPP/7zip/UI/FileManager/HelpUtils.cpp @@ -4,7 +4,7 @@ #include "HelpUtils.h" -#if defined(UNDER_CE) || !defined(_WIN32) +#if defined(UNDER_CE) || !defined(_WIN32) /* || !defined(_MSC_VER) */ void ShowHelpWindow(LPCSTR) { diff --git a/CPP/7zip/UI/FileManager/LangUtils.cpp b/CPP/7zip/UI/FileManager/LangUtils.cpp index bcaa5f1e..83d5aa70 100644 --- a/CPP/7zip/UI/FileManager/LangUtils.cpp +++ b/CPP/7zip/UI/FileManager/LangUtils.cpp @@ -23,6 +23,7 @@ static CLang g_Lang; static bool g_Loaded = false; static NSynchronization::CCriticalSection g_CriticalSection; +bool LangOpen(CLang &lang, CFSTR fileName); bool LangOpen(CLang &lang, CFSTR fileName) { return lang.Open(fileName, "7-Zip"); @@ -145,7 +146,7 @@ static const char * const kLangs = "it.ja.ko.nl.no.=nb.=nn.pl.pt.-br.rm.ro.ru.sr.=hr.-spl.-spc.sk.sq.sv.th.tr." "ur.id.uk.be.sl.et.lv.lt.tg.fa.vi.hy.az.eu.hsb.mk." "st.ts.tn.ve.xh.zu.af.ka.fo.hi.mt.se.ga.yi.ms.kk." - "ky.sw.tk.uz.tt.bn.pa.-in.gu.or.ta.te.kn.ml.as.mr.sa." + "ky.sw.tk.uz.-latn.-cyrl.tt.bn.pa.-in.gu.or.ta.te.kn.ml.as.mr.sa." "mn.=mn.=mng.bo.cy.kh.lo.my.gl.kok..sd.syr.si..iu.am.tzm." "ks.ne.fy.ps.tl.dv..ff.ha..yo.qu.st.ba.lb.kl." "ig.kr.om.ti.gn..la.so.ii..arn..moh..br.." diff --git a/CPP/7zip/UI/FileManager/LinkDialog.cpp b/CPP/7zip/UI/FileManager/LinkDialog.cpp index ddef365c..07f1f061 100644 --- a/CPP/7zip/UI/FileManager/LinkDialog.cpp +++ b/CPP/7zip/UI/FileManager/LinkDialog.cpp @@ -36,46 +36,50 @@ static const UInt32 kLangIDs[] = IDR_LINK_TYPE_HARD, IDR_LINK_TYPE_SYM_FILE, IDR_LINK_TYPE_SYM_DIR, - IDR_LINK_TYPE_JUNCTION + IDR_LINK_TYPE_JUNCTION, + IDR_LINK_TYPE_WSL }; #endif -static bool GetSymLink(CFSTR path, CReparseAttr &attr) -{ - NIO::CInFile file; - if (!file.Open(path, - FILE_SHARE_READ, - OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS)) - return false; - const unsigned kBufSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE; - CByteArr buf(kBufSize); - DWORD returnedSize; - if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize)) +static bool GetSymLink(CFSTR path, CReparseAttr &attr, UString &errorMessage) +{ + CByteBuffer buf; + if (!NIO::GetReparseData(path, buf, NULL)) return false; - DWORD errorCode = 0; - if (!attr.Parse(buf, returnedSize, errorCode)) + if (!attr.Parse(buf, buf.Size())) + { + SetLastError(attr.ErrorCode); return false; + } CByteBuffer data2; - if (!FillLinkData(data2, attr.GetPath(), attr.IsSymLink())) + if (!FillLinkData(data2, attr.GetPath(), + !attr.IsMountPoint(), attr.IsSymLink_WSL())) + { + errorMessage = "Cannot reproduce reparse point"; return false; + } - if (data2.Size() != returnedSize || - memcmp(data2, buf, returnedSize) != 0) + if (data2.Size() != buf.Size() || + memcmp(data2, buf, buf.Size()) != 0) + { + errorMessage = "mismatch for reproduced reparse point"; return false; + } return true; } + static const int k_LinkType_Buttons[] = { IDR_LINK_TYPE_HARD, IDR_LINK_TYPE_SYM_FILE, IDR_LINK_TYPE_SYM_DIR, - IDR_LINK_TYPE_JUNCTION + IDR_LINK_TYPE_JUNCTION, + IDR_LINK_TYPE_WSL }; void CLinkDialog::Set_LinkType_Radio(int idb) @@ -104,16 +108,33 @@ bool CLinkDialog::OnInit() if (fi.HasReparsePoint()) { CReparseAttr attr; - bool res = GetSymLink(us2fs(FilePath), attr); + UString error; + bool res = GetSymLink(us2fs(FilePath), attr, error); + if (!res && error.IsEmpty()) + { + DWORD lastError = GetLastError(); + if (lastError != 0) + error = NError::MyFormatMessage(lastError); + } - UString s = attr.PrintName; + UString s = attr.GetPath(); + if (!attr.IsSymLink_WSL()) if (!attr.IsOkNamePair()) { s += " : "; - s += attr.SubsName; + s += attr.PrintName; } + if (!res) + { s.Insert(0, L"ERROR: "); + if (!error.IsEmpty()) + { + s += " : "; + s += error; + } + } + SetItemText(IDT_LINK_PATH_TO_CUR, s); @@ -121,11 +142,13 @@ bool CLinkDialog::OnInit() _pathFromCombo.SetText(FilePath); _pathToCombo.SetText(destPath); - if (res) + // if (res) { if (attr.IsMountPoint()) linkType = IDR_LINK_TYPE_JUNCTION; - if (attr.IsSymLink()) + else if (attr.IsSymLink_WSL()) + linkType = IDR_LINK_TYPE_WSL; + else if (attr.IsSymLink_Win()) { linkType = fi.IsDir() ? @@ -140,6 +163,7 @@ bool CLinkDialog::OnInit() } else { + // no ReparsePoint _pathFromCombo.SetText(AnotherPath); _pathToCombo.SetText(FilePath); if (fi.IsDir()) @@ -258,15 +282,18 @@ void CLinkDialog::OnButton_Link() } NFind::CFileInfo info1, info2; - bool finded1 = info1.Find(us2fs(from)); - bool finded2 = info2.Find(us2fs(to)); + const bool finded1 = info1.Find(us2fs(from)); + const bool finded2 = info2.Find(us2fs(to)); - bool isDirLink = ( + const bool isDirLink = ( idb == IDR_LINK_TYPE_SYM_DIR || idb == IDR_LINK_TYPE_JUNCTION); - if (finded1 && info1.IsDir() != isDirLink || - finded2 && info2.IsDir() != isDirLink) + const bool isWSL = (idb == IDR_LINK_TYPE_WSL); + + if (!isWSL) + if ((finded1 && info1.IsDir() != isDirLink) || + (finded2 && info2.IsDir() != isDirLink)) { ShowError(L"Incorrect link type"); return; @@ -282,25 +309,41 @@ void CLinkDialog::OnButton_Link() } else { - bool isSymLink = (idb != IDR_LINK_TYPE_JUNCTION); + if (finded1 && !info1.IsDir() && !info1.HasReparsePoint() && info1.Size != 0) + { + UString s ("WARNING: reparse point will hide the data of existing file"); + s.Add_LF(); + s += from; + ShowError(s); + return; + } + + const bool isSymLink = (idb != IDR_LINK_TYPE_JUNCTION); CByteBuffer data; - if (!FillLinkData(data, to, isSymLink)) + if (!FillLinkData(data, to, isSymLink, isWSL)) { ShowError(L"Incorrect link"); return; } CReparseAttr attr; - DWORD errorCode = 0; - if (!attr.Parse(data, data.Size(), errorCode)) + if (!attr.Parse(data, data.Size())) { ShowError(L"Internal conversion error"); return; } - - - if (!NIO::SetReparseData(us2fs(from), isDirLink, data, (DWORD)data.Size())) + + bool res; + if (to.IsEmpty()) + { + // res = NIO::SetReparseData(us2fs(from), isDirLink, NULL, 0); + res = NIO::DeleteReparseData(us2fs(from)); + } + else + res = NIO::SetReparseData(us2fs(from), isDirLink, data, (DWORD)data.Size()); + + if (!res) { ShowLastErrorMessage(); return; @@ -350,5 +393,7 @@ void CApp::Link() if (dlg.Create(srcPanel.GetParent()) != IDOK) return; + // fix it: we should refresh panel with changed link + RefreshTitleAlways(); } diff --git a/CPP/7zip/UI/FileManager/LinkDialog.rc b/CPP/7zip/UI/FileManager/LinkDialog.rc index 3d481d4d..a9e220ba 100644 --- a/CPP/7zip/UI/FileManager/LinkDialog.rc +++ b/CPP/7zip/UI/FileManager/LinkDialog.rc @@ -2,7 +2,7 @@ #include "../../GuiCommon.rc" #define xc 288 -#define yc 200 +#define yc 214 #undef xRadioSize #define xRadioSize xc - m - 2 @@ -20,7 +20,7 @@ BEGIN LTEXT "", IDT_LINK_PATH_TO_CUR, m, 78, xc, 8 - GROUPBOX "Link Type", IDG_LINK_TYPE, m, 104, xc, 76 + GROUPBOX "Link Type", IDG_LINK_TYPE, m, 104, xc, 90 CONTROL "Hard Link", IDR_LINK_TYPE_HARD, "Button", BS_AUTORADIOBUTTON | WS_GROUP, m + m, 120, xRadioSize, 10 @@ -30,6 +30,8 @@ BEGIN m + m, 148, xRadioSize, 10 CONTROL "Directory Junction", IDR_LINK_TYPE_JUNCTION, "Button", BS_AUTORADIOBUTTON, m + m, 162, xRadioSize, 10 + CONTROL "WSL", IDR_LINK_TYPE_WSL, "Button", BS_AUTORADIOBUTTON, + m + m, 176, xRadioSize, 10 DEFPUSHBUTTON "Link", IDB_LINK_LINK, bx2, by, bxs, bys PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys diff --git a/CPP/7zip/UI/FileManager/LinkDialogRes.h b/CPP/7zip/UI/FileManager/LinkDialogRes.h index 47b89192..3f7b3f23 100644 --- a/CPP/7zip/UI/FileManager/LinkDialogRes.h +++ b/CPP/7zip/UI/FileManager/LinkDialogRes.h @@ -10,6 +10,7 @@ #define IDR_LINK_TYPE_SYM_FILE 7712 #define IDR_LINK_TYPE_SYM_DIR 7713 #define IDR_LINK_TYPE_JUNCTION 7714 +#define IDR_LINK_TYPE_WSL 7715 #define IDC_LINK_PATH_FROM 100 diff --git a/CPP/7zip/UI/FileManager/MenuPage.cpp b/CPP/7zip/UI/FileManager/MenuPage.cpp index 4067ad75..ac3a7b14 100644 --- a/CPP/7zip/UI/FileManager/MenuPage.cpp +++ b/CPP/7zip/UI/FileManager/MenuPage.cpp @@ -152,7 +152,7 @@ bool CMenuPage::OnInit() ); - if (!NFile::NFind::DoesFileExist(path)) + if (!NFile::NFind::DoesFileExist_Raw(path)) { path.Empty(); EnableItem(dll.ctrl, false); diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp index 50104950..a133a291 100644 --- a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp +++ b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp @@ -124,7 +124,7 @@ static void MyChangeMenu(HMENU menuLoc, int level, int menuIndex) CMenu menu; menu.Attach(menuLoc); - for (int i = 0;; i++) + for (unsigned i = 0;; i++) { CMenuItem item; item.fMask = Get_fMask_for_String() | MIIM_SUBMENU | MIIM_ID; @@ -214,7 +214,7 @@ static void MyChangeMenu(HMENU menuLoc, int level, int menuIndex) static CMenu g_FileMenu; -struct CFileMenuDestroyer +static struct CFileMenuDestroyer { ~CFileMenuDestroyer() { if ((HMENU)g_FileMenu != 0) g_FileMenu.Destroy(); } } g_FileMenuDestroyer; @@ -461,6 +461,22 @@ void OnMenuUnActivating(HWND hWnd, HMENU hMenu, int id) } */ +static const unsigned g_Zvc_IDs[] = +{ + IDM_VER_EDIT, + IDM_VER_COMMIT, + IDM_VER_REVERT, + IDM_VER_DIFF +}; + +static const char * const g_Zvc_Strings[] = +{ + "Ver Edit (&1)" + , "Ver Commit" + , "Ver Revert" + , "Ver Diff (&0)" +}; + void CFileMenu::Load(HMENU hMenu, unsigned startPos) { CMenu destMenu; @@ -468,7 +484,7 @@ void CFileMenu::Load(HMENU hMenu, unsigned startPos) UString diffPath; ReadRegDiff(diffPath); - + unsigned numRealItems = startPos; for (unsigned i = 0;; i++) @@ -544,11 +560,47 @@ void CFileMenu::Load(HMENU hMenu, unsigned startPos) numRealItems = startPos; } } + + UString vercPath; + if (!diffPath.IsEmpty() && isFsFolder && allAreFiles && numItems == 1) + ReadReg_VerCtrlPath(vercPath); + + if (!vercPath.IsEmpty()) + { + NFile::NFind::CFileInfo fi; + if (fi.Find(FilePath) && fi.Size < ((UInt32)1 << 31) && !fi.IsDir()) + { + for (unsigned k = 0; k < ARRAY_SIZE(g_Zvc_IDs); k++) + { + const unsigned id = g_Zvc_IDs[k]; + if (fi.IsReadOnly()) + { + if (id == IDM_VER_COMMIT || + id == IDM_VER_REVERT || + id == IDM_VER_DIFF) + continue; + } + else + { + if (id == IDM_VER_EDIT) + continue; + } + + CMenuItem item; + UString s (g_Zvc_Strings[k]); + if (destMenu.AppendItem(MF_STRING, id, s)) + { + startPos++; + numRealItems = startPos; + } + } + } + } destMenu.RemoveAllItemsFrom(numRealItems); } -bool ExecuteFileCommand(int id) +bool ExecuteFileCommand(unsigned id) { if (id >= kMenuCmdID_Plugin_Start) { @@ -582,6 +634,13 @@ bool ExecuteFileCommand(int id) case IDM_SHA256: g_App.CalculateCrc("SHA256"); break; case IDM_DIFF: g_App.DiffFiles(); break; + + case IDM_VER_EDIT: + case IDM_VER_COMMIT: + case IDM_VER_REVERT: + case IDM_VER_DIFF: + g_App.VerCtrl(id); break; + case IDM_SPLIT: g_App.Split(); break; case IDM_COMBINE: g_App.Combine(); break; case IDM_PROPERTIES: g_App.Properties(); break; @@ -604,7 +663,7 @@ static void MyBenchmark(bool totalMode) Benchmark(totalMode); } -bool OnMenuCommand(HWND hWnd, int id) +bool OnMenuCommand(HWND hWnd, unsigned id) { if (ExecuteFileCommand(id)) return true; diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.h b/CPP/7zip/UI/FileManager/MyLoadMenu.h index 02569e52..0a38a732 100644 --- a/CPP/7zip/UI/FileManager/MyLoadMenu.h +++ b/CPP/7zip/UI/FileManager/MyLoadMenu.h @@ -7,7 +7,7 @@ void OnMenuActivating(HWND hWnd, HMENU hMenu, int position); // void OnMenuUnActivating(HWND hWnd, HMENU hMenu, int id); // void OnMenuUnActivating(HWND hWnd); -bool OnMenuCommand(HWND hWnd, int id); +bool OnMenuCommand(HWND hWnd, unsigned id); void MyLoadMenu(); struct CFileMenu @@ -19,6 +19,8 @@ struct CFileMenu bool isAltStreamsSupported; int numItems; + UString FilePath; + CFileMenu(): programMenu(false), readOnly(false), @@ -31,6 +33,6 @@ struct CFileMenu void Load(HMENU hMenu, unsigned startPos); }; -bool ExecuteFileCommand(int id); +bool ExecuteFileCommand(unsigned id); #endif diff --git a/CPP/7zip/UI/FileManager/OpenCallback.cpp b/CPP/7zip/UI/FileManager/OpenCallback.cpp index bf7abfb7..ddec3877 100644 --- a/CPP/7zip/UI/FileManager/OpenCallback.cpp +++ b/CPP/7zip/UI/FileManager/OpenCallback.cpp @@ -92,7 +92,7 @@ STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **in FString fullPath; if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name), fullPath)) return S_FALSE; - if (!_fileInfo.Find(fullPath)) + if (!_fileInfo.Find_FollowLink(fullPath)) return S_FALSE; if (_fileInfo.IsDir()) return S_FALSE; diff --git a/CPP/7zip/UI/FileManager/OpenCallback.h b/CPP/7zip/UI/FileManager/OpenCallback.h index c952d7b0..9aa5d43c 100644 --- a/CPP/7zip/UI/FileManager/OpenCallback.h +++ b/CPP/7zip/UI/FileManager/OpenCallback.h @@ -74,12 +74,17 @@ public: _subArchiveMode = false; } */ - void LoadFileInfo(const FString &folderPrefix, const FString &fileName) + + HRESULT LoadFileInfo2(const FString &folderPrefix, const FString &fileName) { _folderPrefix = folderPrefix; - if (!_fileInfo.Find(_folderPrefix + fileName)) - throw 1; + if (!_fileInfo.Find_FollowLink(_folderPrefix + fileName)) + { + return GetLastError_noZero_HRESULT(); + } + return S_OK; } + void ShowMessage(const UInt64 *completed); INT_PTR StartProgressDialog(const UString &title, NWindows::CThread &thread) diff --git a/CPP/7zip/UI/FileManager/OptionsDialog.cpp b/CPP/7zip/UI/FileManager/OptionsDialog.cpp index 66e6f3c4..c42e0f87 100644 --- a/CPP/7zip/UI/FileManager/OptionsDialog.cpp +++ b/CPP/7zip/UI/FileManager/OptionsDialog.cpp @@ -28,6 +28,7 @@ using namespace NWindows; +void OptionsDialog(HWND hwndOwner, HINSTANCE hInstance); void OptionsDialog(HWND hwndOwner, HINSTANCE /* hInstance */) { CSystemPage systemPage; diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp index 1c029132..b455b14a 100644 --- a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp +++ b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp @@ -57,8 +57,8 @@ void COverwriteDialog::SetFileInfoControl(int textID, int iconID, const UString &fileName = fileInfo.Name; int slashPos = fileName.ReverseFind_PathSepar(); - UString s1 = fileName.Left(slashPos + 1); - UString s2 = fileName.Ptr(slashPos + 1); + UString s1 = fileName.Left((unsigned)(slashPos + 1)); + UString s2 = fileName.Ptr((unsigned)(slashPos + 1)); ReduceString(s1); ReduceString(s2); @@ -103,6 +103,22 @@ bool COverwriteDialog::OnInit() SetFileInfoControl(IDT_OVERWRITE_OLD_FILE_SIZE_TIME, IDI_OVERWRITE_OLD_FILE, OldFileInfo); SetFileInfoControl(IDT_OVERWRITE_NEW_FILE_SIZE_TIME, IDI_OVERWRITE_NEW_FILE, NewFileInfo); NormalizePosition(); + + if (!ShowExtraButtons) + { + HideItem(IDB_YES_TO_ALL); + HideItem(IDB_NO_TO_ALL); + HideItem(IDB_AUTO_RENAME); + } + + if (DefaultButton_is_NO) + { + PostMsg(DM_SETDEFID, IDNO); + HWND h = GetItem(IDNO); + PostMsg(WM_NEXTDLGCTL, (WPARAM)h, TRUE); + // ::SetFocus(h); + } + return CModalDialog::OnInit(); } diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.h b/CPP/7zip/UI/FileManager/OverwriteDialog.h index da7fa55f..24e56cac 100644 --- a/CPP/7zip/UI/FileManager/OverwriteDialog.h +++ b/CPP/7zip/UI/FileManager/OverwriteDialog.h @@ -20,7 +20,7 @@ namespace NOverwriteDialog void SetTime(const FILETIME *t) { - if (t == 0) + if (!t) TimeIsDefined = false; else { @@ -28,15 +28,19 @@ namespace NOverwriteDialog Time = *t; } } + + void SetSize(UInt64 size) + { + SizeIsDefined = true; + Size = size; + } + void SetSize(const UInt64 *size) { - if (size == 0) + if (!size) SizeIsDefined = false; else - { - SizeIsDefined = true; - Size = *size; - } + SetSize(*size); } }; } @@ -51,6 +55,12 @@ class COverwriteDialog: public NWindows::NControl::CModalDialog void ReduceString(UString &s); public: + bool ShowExtraButtons; + bool DefaultButton_is_NO; + + + COverwriteDialog(): ShowExtraButtons(true), DefaultButton_is_NO(false) {} + INT_PTR Create(HWND parent = 0) { BIG_DIALOG_SIZE(280, 200); diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp index afb5649a..6702fa9c 100644 --- a/CPP/7zip/UI/FileManager/Panel.cpp +++ b/CPP/7zip/UI/FileManager/Panel.cpp @@ -2,7 +2,7 @@ #include "StdAfx.h" -#include <Windowsx.h> +#include <WindowsX.h> // #include <stdio.h> #include "../../../Common/IntToString.h" @@ -62,7 +62,7 @@ CPanel::~CPanel() CloseOpenFolders(); } -HWND CPanel::GetParent() +HWND CPanel::GetParent() const { HWND h = CWindow2::GetParent(); return (h == 0) ? _mainWindow : h; @@ -76,7 +76,7 @@ HRESULT CPanel::Create(HWND mainWindow, HWND parentWindow, UINT id, const UString &arcFormat, CPanelCallback *panelCallback, CAppState *appState, bool needOpenArc, - bool &archiveIsOpened, bool &encrypted) + COpenResult &openRes) { _mainWindow = mainWindow; _processTimer = true; @@ -100,9 +100,9 @@ HRESULT CPanel::Create(HWND mainWindow, HWND parentWindow, UINT id, cfp = fs2us(cfpF); } - RINOK(BindToPath(cfp, arcFormat, archiveIsOpened, encrypted)); + RINOK(BindToPath(cfp, arcFormat, openRes)); - if (needOpenArc && !archiveIsOpened) + if (needOpenArc && !openRes.ArchiveIsOpened) return S_OK; if (!CreateEx(0, kClassName, 0, WS_CHILD | WS_VISIBLE, @@ -114,8 +114,11 @@ HRESULT CPanel::Create(HWND mainWindow, HWND parentWindow, UINT id, return S_OK; } +// extern UInt32 g_NumMessages; + LRESULT CPanel::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) { + // g_NumMessages++; switch (message) { case kShiftSelectMessage: @@ -309,7 +312,7 @@ LRESULT CMyComboBoxEdit::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) bool shift = IsKeyDown(VK_SHIFT); if (!alt && !ctrl && !shift) { - g_App.SwitchOnOffOnePanel();; + g_App.SwitchOnOffOnePanel(); return 0; } break; @@ -340,7 +343,7 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */) _ascending = true; _lastFocusedIsList = true; - DWORD style = WS_CHILD | WS_VISIBLE; // | WS_BORDER ; // | LVS_SHAREIMAGELISTS; // | LVS_SHOWSELALWAYS;; + DWORD style = WS_CHILD | WS_VISIBLE; // | WS_BORDER ; // | LVS_SHAREIMAGELISTS; // | LVS_SHOWSELALWAYS; style |= LVS_SHAREIMAGELISTS; // style |= LVS_AUTOARRANGE; @@ -396,7 +399,7 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */) TBBUTTON tbb [ ] = { // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0}, - {VIEW_PARENTFOLDER, kParentFolderID, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0}, + {VIEW_PARENTFOLDER, kParentFolderID, TBSTATE_ENABLED, BTNS_BUTTON, { 0, 0 }, 0, 0 }, // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0}, // {VIEW_NEWFOLDER, kCreateFolderID, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0}, }; @@ -667,9 +670,14 @@ bool CPanel::OnNotify(UINT /* controlID */, LPNMHDR header, LRESULT &result) return OnNotifyReBar(header, result); else if (header->hwndFrom == _listView) return OnNotifyList(header, result); - else if (::GetParent(header->hwndFrom) == _listView && - header->code == NM_RCLICK) - return OnRightClick((MY_NMLISTVIEW_NMITEMACTIVATE *)header, result); + else if (::GetParent(header->hwndFrom) == _listView) + { + // NMHDR:code is UINT + // NM_RCLICK is unsigned in windows sdk + // NM_RCLICK is int in MinGW + if (header->code == (UINT)NM_RCLICK) + return OnRightClick((MY_NMLISTVIEW_NMITEMACTIVATE *)header, result); + } return false; } @@ -903,8 +911,8 @@ static UString GetSubFolderNameForExtract2(const UString &arcPath) UString name = arcPath; if (slashPos >= 0) { - s = arcPath.Left(slashPos + 1); - name = arcPath.Ptr(slashPos + 1); + s = arcPath.Left((unsigned)(slashPos + 1)); + name = arcPath.Ptr((unsigned)(slashPos + 1)); } s += GetSubFolderNameForExtract(name); return s; @@ -967,7 +975,8 @@ static void AddValuePair(UINT resourceID, UInt64 value, UString &s) s += sz; s.Add_LF(); } -*/ + +// now we don't need CThreadTest, since now we call CopyTo for "test command class CThreadTest: public CProgressThreadVirt { @@ -979,9 +988,6 @@ public: CMyComPtr<IArchiveFolder> ArchiveFolder; }; -// actually now we don't need CThreadTest, since now we call CopyTo for "test command - -/* HRESULT CThreadTest::ProcessVirt() { RINOK(ArchiveFolder->Extract(&Indices[0], Indices.Size(), @@ -1005,9 +1011,7 @@ HRESULT CThreadTest::ProcessVirt() } return S_OK; } -*/ -/* static void AddSizePair(UInt32 langID, UInt64 value, UString &s) { char sz[32]; diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h index 03882344..f39d94e2 100644 --- a/CPP/7zip/UI/FileManager/Panel.h +++ b/CPP/7zip/UI/FileManager/Panel.h @@ -48,6 +48,7 @@ const int kParentFolderID = 100; const int kParentIndex = -1; +const UInt32 kParentIndex_UInt32 = (UInt32)(Int32)kParentIndex; #if !defined(_WIN32) || defined(UNDER_CE) #define ROOT_FS_FOLDER L"\\" @@ -225,7 +226,7 @@ struct CSelectedState UString FocusedName; UStringVector SelectedNames; - CSelectedState(): FocusedItem(-1), FocusedName_Defined(false), SelectFocused(true) {} + CSelectedState(): FocusedItem(-1), SelectFocused(true), FocusedName_Defined(false) {} }; #ifdef UNDER_CE @@ -263,6 +264,23 @@ struct CCopyToOptions }; + +struct COpenResult +{ + // bool needOpenArc; + // out: + bool ArchiveIsOpened; + bool Encrypted; + UString ErrorMessage; + + COpenResult(): + // needOpenArc(false), + ArchiveIsOpened(false), Encrypted(false) {} +}; + + + + class CPanel: public NWindows::NControl::CWindow2 { CExtToIconMap _extToIconMap; @@ -403,7 +421,7 @@ public: } } - HWND GetParent(); + HWND GetParent() const; UInt32 GetRealIndex(const LVITEMW &item) const { @@ -483,7 +501,7 @@ public: // PanelFolderChange.cpp void SetToRootFolder(); - HRESULT BindToPath(const UString &fullPath, const UString &arcFormat, bool &archiveIsOpened, bool &encrypted); // can be prefix + HRESULT BindToPath(const UString &fullPath, const UString &arcFormat, COpenResult &openRes); // can be prefix HRESULT BindToPathAndRefresh(const UString &path); void OpenDrivesFolder(); @@ -507,7 +525,8 @@ public: CPanelCallback *panelCallback, CAppState *appState, bool needOpenArc, - bool &archiveIsOpened, bool &encrypted); + COpenResult &openRes); + void SetFocusToList(); void SetFocusToLastRememberedItem(); @@ -515,32 +534,35 @@ public: void SaveListViewInfo(); CPanel() : - // _virtualMode(flase), + _thereAre_ListView_Items(false), _exStyle(0), _showDots(false), _showRealFileIcons(false), - _needSaveInfo(false), - _startGroupSelect(0), - _selectionIsDefined(false), + // _virtualMode(flase), + _enableItemChangeNotify(true), + _mySelectMode(false), + _timestampLevel(kTimestampPrintLevel_MIN), + + _thereAreDeletedItems(false), + _markDeletedItems(true), + PanelCreated(false), + _ListViewMode(3), + _xSize(300), + _flatMode(false), _flatModeForDisk(false), _flatModeForArc(false), - PanelCreated(false), - _thereAre_ListView_Items(false), // _showNtfsStrems_Mode(false), // _showNtfsStrems_ModeForDisk(false), // _showNtfsStrems_ModeForArc(false), - _xSize(300), - _mySelectMode(false), - _thereAreDeletedItems(false), - _markDeletedItems(true), - _enableItemChangeNotify(true), _dontShowMode(false), - _timestampLevel(kTimestampPrintLevel_MIN) + _needSaveInfo(false), + _startGroupSelect(0), + _selectionIsDefined(false) {} void SetExtendedStyle() @@ -590,8 +612,8 @@ public: CMyComPtr<IContextMenu> &systemContextMenu, bool programMenu); void CreateFileMenu(HMENU menu); - bool InvokePluginCommand(int id); - bool InvokePluginCommand(int id, IContextMenu *sevenZipContextMenu, + bool InvokePluginCommand(unsigned id); + bool InvokePluginCommand(unsigned id, IContextMenu *sevenZipContextMenu, IContextMenu *systemContextMenu); void InvokeSystemCommand(const char *command); @@ -737,9 +759,6 @@ public: } }; - // bool _passwordIsDefined; - // UString _password; - void InvalidateList() { _listView.InvalidateRect(NULL, true); } HRESULT RefreshListCtrl(); @@ -773,17 +792,21 @@ public: const CTempFileInfo &tempFileInfo, const UString &virtualFilePath, const UString &arcFormat, - bool &encrypted); + COpenResult &openRes); HRESULT OpenAsArc_Msg(IInStream *inStream, const CTempFileInfo &tempFileInfo, const UString &virtualFilePath, - const UString &arcFormat, - bool &encrypted, - bool showErrorMessage); + const UString &arcFormat + // , bool showErrorMessage + ); - HRESULT OpenAsArc_Name(const UString &relPath, const UString &arcFormat, bool &encrypted, bool showErrorMessage); - HRESULT OpenAsArc_Index(int index, const wchar_t *type /* = NULL */, bool showErrorMessage); + HRESULT OpenAsArc_Name(const UString &relPath, const UString &arcFormat + // , bool showErrorMessage + ); + HRESULT OpenAsArc_Index(int index, const wchar_t *type /* = NULL */ + // , bool showErrorMessage + ); void OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bool editMode, bool useEditor, const wchar_t *type = NULL); diff --git a/CPP/7zip/UI/FileManager/PanelCopy.cpp b/CPP/7zip/UI/FileManager/PanelCopy.cpp index c3416cc7..e1bd0117 100644 --- a/CPP/7zip/UI/FileManager/PanelCopy.cpp +++ b/CPP/7zip/UI/FileManager/PanelCopy.cpp @@ -31,14 +31,14 @@ public: CHashBundle Hash; // UString FirstFilePath; - HRESULT Result; + // HRESULT Result2; void ShowFinalResults(HWND hwnd); CPanelCopyThread(): - Result(E_FAIL), ResultsWereShown(false), NeedShowRes(false) + // , Result2(E_FAIL) {} }; @@ -68,6 +68,8 @@ HRESULT CPanelCopyThread::ProcessVirt() } */ + HRESULT result2; + if (options->testMode) { CMyComPtr<IArchiveFolder> archiveFolder; @@ -79,21 +81,21 @@ HRESULT CPanelCopyThread::ProcessVirt() NExtract::NPathMode::EEnum pathMode = NExtract::NPathMode::kCurPaths; // NExtract::NPathMode::kFullPathnames; - Result = archiveFolder->Extract(&Indices.Front(), Indices.Size(), + result2 = archiveFolder->Extract(&Indices.Front(), Indices.Size(), BoolToInt(options->includeAltStreams), BoolToInt(options->replaceAltStreamChars), pathMode, NExtract::NOverwriteMode::kAsk, options->folder, BoolToInt(true), extractCallback2); } else - Result = FolderOperations->CopyTo( + result2 = FolderOperations->CopyTo( BoolToInt(options->moveMode), &Indices.Front(), Indices.Size(), BoolToInt(options->includeAltStreams), BoolToInt(options->replaceAltStreamChars), options->folder, ExtractCallback); - if (Result == S_OK && !ExtractCallbackSpec->ThereAreMessageErrors) + if (result2 == S_OK && !ExtractCallbackSpec->ThereAreMessageErrors) { if (!options->hashMethods.IsEmpty()) NeedShowRes = true; @@ -104,7 +106,7 @@ HRESULT CPanelCopyThread::ProcessVirt() } } - return Result; + return result2; } @@ -232,6 +234,8 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind if (messages) *messages = extracter.Sync.Messages; + + // res = extracter.Result2; res = extracter.Result; if (res == S_OK && extracter.ExtractCallbackSpec->IsOK()) @@ -327,9 +331,11 @@ HRESULT CPanel::CopyFrom(bool moveMode, const UString &folderPrefix, const UStri for (i = 0; i < updater.FileNames.Size(); i++) updater.FileNamePointers.AddInReserved(updater.FileNames[i]); - NWindows::CThread thread; - RINOK(thread.Create(CThreadUpdate::MyThreadFunction, &updater)); - updater.ProgressDialog.Create(title, thread, GetParent()); + { + NWindows::CThread thread; + RINOK(thread.Create(CThreadUpdate::MyThreadFunction, &updater)); + updater.ProgressDialog.Create(title, thread, GetParent()); + } if (messages) *messages = updater.ProgressDialog.Sync.Messages; diff --git a/CPP/7zip/UI/FileManager/PanelCrc.cpp b/CPP/7zip/UI/FileManager/PanelCrc.cpp index 1cfbfe5d..6c49e897 100644 --- a/CPP/7zip/UI/FileManager/PanelCrc.cpp +++ b/CPP/7zip/UI/FileManager/PanelCrc.cpp @@ -383,7 +383,7 @@ HRESULT CApp::CalculateCrc2(const UString &methodName) { int pos = basePrefix2.ReverseFind_PathSepar(); if (pos >= 0) - basePrefix2.DeleteFrom(pos + 1); + basePrefix2.DeleteFrom((unsigned)(pos + 1)); } t.Enumerator.BasePrefix = us2fs(basePrefix); diff --git a/CPP/7zip/UI/FileManager/PanelDrag.cpp b/CPP/7zip/UI/FileManager/PanelDrag.cpp index 6a781e22..af8799ca 100644 --- a/CPP/7zip/UI/FileManager/PanelDrag.cpp +++ b/CPP/7zip/UI/FileManager/PanelDrag.cpp @@ -190,7 +190,7 @@ public: HRESULT Result; UStringVector Messages; - CDropSource(): NeedPostCopy(false), Panel(0), Result(S_OK), m_Effect(DROPEFFECT_NONE) {} + CDropSource(): m_Effect(DROPEFFECT_NONE), Panel(NULL), NeedPostCopy(false), Result(S_OK) {} }; STDMETHODIMP CDropSource::QueryContinueDrag(BOOL escapePressed, DWORD keyState) @@ -300,7 +300,7 @@ static bool CopyNamesToHGlobal(NMemory::CGlobal &hgDrop, const UStringVector &na dropFiles->pt.y = 0; dropFiles->pFiles = sizeof(DROPFILES); dropFiles->fWide = TRUE; - WCHAR *p = (WCHAR *)((BYTE *)dropFiles + sizeof(DROPFILES)); + WCHAR *p = (WCHAR *) (void *) ((BYTE *)dropFiles + sizeof(DROPFILES)); for (i = 0; i < names.Size(); i++) { const UString &s = names[i]; diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp index 38b83124..b91195f4 100644 --- a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp +++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp @@ -73,15 +73,15 @@ static bool DoesNameContainWildcard_SkipRoot(const UString &path) return DoesNameContainWildcard(path.Ptr(NName::GetRootPrefixSize(path))); } -HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bool &archiveIsOpened, bool &encrypted) +HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, COpenResult &openRes) { UString path = fullPath; #ifdef _WIN32 path.Replace(L'/', WCHAR_PATH_SEPARATOR); #endif - archiveIsOpened = false; - encrypted = false; + openRes.ArchiveIsOpened = false; + openRes.Encrypted = false; CDisableTimerProcessing disableTimerProcessing(*this); CDisableNotify disableNotify(*this); @@ -169,7 +169,7 @@ HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bo pos++; #endif - sysPath.DeleteFrom(pos); + sysPath.DeleteFrom((unsigned)pos); } } @@ -218,7 +218,7 @@ HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bo tfi.RelPath = fs2us(fileName); tfi.FolderPath = dirPrefix; tfi.FilePath = us2fs(sysPath); - res = OpenAsArc(NULL, tfi, sysPath, arcFormat, encrypted); + res = OpenAsArc(NULL, tfi, sysPath, arcFormat, openRes); } if (res == S_FALSE) @@ -226,7 +226,7 @@ HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bo else { RINOK(res); - archiveIsOpened = true; + openRes.ArchiveIsOpened = true; _parentFolders.Back().ParentFolderPath = fs2us(dirPrefix); path.DeleteFrontal(sysPath.Len()); if (!path.IsEmpty() && IS_PATH_SEPAR(path[0])) @@ -252,7 +252,7 @@ HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bo unsigned skipLen = s.Len(); if (slashPos >= 0) { - s.DeleteFrom(slashPos); + s.DeleteFrom((unsigned)slashPos); skipLen = slashPos + 1; } @@ -266,7 +266,7 @@ HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bo if (pos >= 0) { UString baseName = s; - baseName.DeleteFrom(pos); + baseName.DeleteFrom((unsigned)pos); if (_folderAltStreams->BindToAltStreams(baseName, &newFolder) == S_OK && newFolder) curPos += pos + 1; } @@ -286,7 +286,7 @@ HRESULT CPanel::BindToPathAndRefresh(const UString &path) { CDisableTimerProcessing disableTimerProcessing(*this); CDisableNotify disableNotify(*this); - bool archiveIsOpened, encrypted; + COpenResult openRes; UString s = path; #ifdef _WIN32 @@ -297,7 +297,7 @@ HRESULT CPanel::BindToPathAndRefresh(const UString &path) } #endif - HRESULT res = BindToPath(s, UString(), archiveIsOpened, encrypted); + HRESULT res = BindToPath(s, UString(), openRes); RefreshListCtrl(); return res; } @@ -484,7 +484,7 @@ void CPanel::AddComboBoxItem(const UString &name, int iconIndex, int indent, boo item.mask |= (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE); item.iItem = -1; item.iIndent = indent; - item.pszText = (LPWSTR)(LPCWSTR)name; + item.pszText = name.Ptr_non_const(); _headerComboBox.InsertItem(&item); #endif @@ -559,7 +559,6 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result) case CBN_SELENDOK: { - code = code; int index = _headerComboBox.GetCurSel(); if (index >= 0) { @@ -664,7 +663,7 @@ UString CPanel::GetParentDirPrefix() const { int pos = s.ReverseFind_PathSepar(); if (pos >= 0) - s.DeleteFrom(pos + 1); + s.DeleteFrom((unsigned)(pos + 1)); } } } @@ -700,7 +699,7 @@ void CPanel::OpenParentFolder() if (pos >= 0) { parentFolderPrefix = focusedName; - parentFolderPrefix.DeleteFrom(pos + 1); + parentFolderPrefix.DeleteFrom((unsigned)(pos + 1)); focusedName.DeleteFrontal(pos + 1); } } @@ -734,9 +733,8 @@ void CPanel::OpenParentFolder() if (needSetFolder) { { - bool archiveIsOpened; - bool encrypted; - BindToPath(parentFolderPrefix, UString(), archiveIsOpened, encrypted); + COpenResult openRes; + BindToPath(parentFolderPrefix, UString(), openRes); } } } @@ -822,7 +820,12 @@ void CPanel::OpenFolder(int index) return; } CMyComPtr<IFolderFolder> newFolder; - _folder->BindToFolder(index, &newFolder); + HRESULT res = _folder->BindToFolder(index, &newFolder); + if (res != 0) + { + MessageBox_Error_HRESULT(res); + return; + } if (!newFolder) return; SetNewFolder(newFolder); diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp index 89f49bf6..68fe7b02 100644 --- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp +++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp @@ -4,7 +4,7 @@ #include "../../../Common/MyWindows.h" -#include <tlhelp32.h> +#include <TlHelp32.h> #include "../../../Common/IntToString.h" @@ -222,14 +222,14 @@ static void My_GetProcessFileName(HANDLE hProcess, UString &path) const char *func_name = "GetProcessImageFileNameW"; Func_GetProcessImageFileNameW my_func = (Func_GetProcessImageFileNameW) - ::GetProcAddress(::GetModuleHandleA("kernel32.dll"), func_name); + (void *)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), func_name); if (!my_func) { if (!g_Psapi_dll_module) g_Psapi_dll_module = LoadLibraryW(L"Psapi.dll"); if (g_Psapi_dll_module) - my_func = (Func_GetProcessImageFileNameW)::GetProcAddress(g_Psapi_dll_module, func_name); + my_func = (Func_GetProcessImageFileNameW)(void *)::GetProcAddress(g_Psapi_dll_module, func_name); } if (my_func) @@ -319,7 +319,7 @@ public: { #ifndef UNDER_CE - Func_GetProcessId func = (Func_GetProcessId)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "GetProcessId"); + Func_GetProcessId func = (Func_GetProcessId)(void *)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "GetProcessId"); if (func) { DWORD id = func(h); @@ -349,7 +349,7 @@ public: GetSnapshot(sps); const int separ = Path.ReverseFind_PathSepar(); - const UString mainName = Path.Ptr(separ + 1); + const UString mainName = Path.Ptr((unsigned)(separ + 1)); if (mainName.IsEmpty()) needFindProcessByPath = false; @@ -444,14 +444,16 @@ public: } }; +void GetFolderError(CMyComPtr<IFolderFolder> &folder, UString &s); + HRESULT CPanel::OpenAsArc(IInStream *inStream, const CTempFileInfo &tempFileInfo, const UString &virtualFilePath, const UString &arcFormat, - bool &encrypted) + COpenResult &openRes) { - encrypted = false; + openRes.Encrypted = false; CFolderLink folderLink; (CTempFileInfo &)folderLink = tempFileInfo; @@ -468,21 +470,18 @@ HRESULT CPanel::OpenAsArc(IInStream *inStream, folderLink.VirtualPath = virtualFilePath; - CMyComPtr<IFolderFolder> newFolder; - - // _passwordIsDefined = false; - // _password.Empty(); + CFfpOpen ffp; + HRESULT res = ffp.OpenFileFolderPlugin(inStream, + folderLink.FilePath.IsEmpty() ? us2fs(virtualFilePath) : folderLink.FilePath, + arcFormat, GetParent()); - NDLL::CLibrary library; + openRes.Encrypted = ffp.Encrypted; + openRes.ErrorMessage = ffp.ErrorMessage; - UString password; - RINOK(OpenFileFolderPlugin(inStream, - folderLink.FilePath.IsEmpty() ? us2fs(virtualFilePath) : folderLink.FilePath, - arcFormat, - &library, &newFolder, GetParent(), encrypted, password)); + RINOK(res); - folderLink.Password = password; - folderLink.UsePassword = encrypted; + folderLink.Password = ffp.Password; + folderLink.UsePassword = ffp.Encrypted; if (_folder) folderLink.ParentFolderPath = GetFolderPath(_folder); @@ -497,75 +496,24 @@ HRESULT CPanel::OpenAsArc(IInStream *inStream, ReleaseFolder(); _library.Free(); - SetNewFolder(newFolder); - _library.Attach(library.Detach()); + SetNewFolder(ffp.Folder); + _library.Attach(ffp.Library.Detach()); _flatMode = _flatModeForArc; - CMyComPtr<IGetFolderArcProps> getFolderArcProps; - _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps); _thereAreDeletedItems = false; - if (getFolderArcProps) - { - CMyComPtr<IFolderArcProps> arcProps; - getFolderArcProps->GetFolderArcProps(&arcProps); - if (arcProps) - { - /* - UString s; - UInt32 numLevels; - if (arcProps->GetArcNumLevels(&numLevels) != S_OK) - numLevels = 0; - for (UInt32 level2 = 0; level2 <= numLevels; level2++) - { - UInt32 level = numLevels - level2; - PROPID propIDs[] = { kpidError, kpidPath, kpidType, kpidErrorType } ; - UString values[4]; - for (Int32 i = 0; i < 4; i++) - { - CMyComBSTR name; - NCOM::CPropVariant prop; - if (arcProps->GetArcProp(level, propIDs[i], &prop) != S_OK) - continue; - if (prop.vt != VT_EMPTY) - values[i] = (prop.vt == VT_BSTR) ? prop.bstrVal : L"?"; - } - UString s2; - if (!values[3].IsEmpty()) - { - s2 = "Can not open the file as [" + values[3] + "] archive"; - if (level2 != 0) - s2 += "\nThe file is open as [" + values[2] + "] archive"; - } - if (!values[0].IsEmpty()) - { - if (!s2.IsEmpty()) - s2.Add_LF(); - s2 += "["; - s2 += values[2]; - s2 += "] Error: "; - s2 += values[0]; - } - if (!s2.IsEmpty()) - { - if (!s.IsEmpty()) - s += "--------------------\n"; - s += values[1]; - s.Add_LF(); - s += s2; - } - } - */ - /* - if (!s.IsEmpty()) - MessageBox_Warning(s); - else - */ - // after MessageBox_Warning it throws exception in nested archives in Debug Mode. why ?. - // MessageBox_Warning(L"test error"); - } - } + if (!openRes.ErrorMessage.IsEmpty()) + MessageBox_Error(openRes.ErrorMessage); + /* + UString s; + GetFolderError(_folder, s); + if (!s.IsEmpty()) + MessageBox_Error(s); + */ + // we don't show error here by some reasons: + // after MessageBox_Warning it throws exception in nested archives in Debug Mode. why ?. + // MessageBox_Warning(L"test error"); return S_OK; } @@ -574,25 +522,28 @@ HRESULT CPanel::OpenAsArc(IInStream *inStream, HRESULT CPanel::OpenAsArc_Msg(IInStream *inStream, const CTempFileInfo &tempFileInfo, const UString &virtualFilePath, - const UString &arcFormat, - bool &encrypted, - bool showErrorMessage) + const UString &arcFormat + // , bool &encrypted + // , bool showErrorMessage + ) { - HRESULT res = OpenAsArc(inStream, tempFileInfo, virtualFilePath, arcFormat, encrypted); + COpenResult opRes; + + HRESULT res = OpenAsArc(inStream, tempFileInfo, virtualFilePath, arcFormat, opRes); if (res == S_OK) return res; if (res == E_ABORT) return res; - if (showErrorMessage) - if (encrypted || res != S_FALSE) // 17.01 : we show message also for (res != S_FALSE) + // if (showErrorMessage) + if (opRes.Encrypted || res != S_FALSE) // 17.01 : we show message also for (res != S_FALSE) { UString message; if (res == S_FALSE) { message = MyFormatNew( - encrypted ? + opRes.Encrypted ? IDS_CANT_OPEN_ENCRYPTED_ARCHIVE : IDS_CANT_OPEN_ARCHIVE, virtualFilePath); @@ -606,23 +557,28 @@ HRESULT CPanel::OpenAsArc_Msg(IInStream *inStream, } -HRESULT CPanel::OpenAsArc_Name(const UString &relPath, const UString &arcFormat, bool &encrypted, bool showErrorMessage) +HRESULT CPanel::OpenAsArc_Name(const UString &relPath, const UString &arcFormat + // , bool &encrypted, + // , bool showErrorMessage + ) { CTempFileInfo tfi; tfi.RelPath = relPath; tfi.FolderPath = us2fs(GetFsPath()); const UString fullPath = GetFsPath() + relPath; tfi.FilePath = us2fs(fullPath); - return OpenAsArc_Msg(NULL, tfi, fullPath, arcFormat, encrypted, showErrorMessage); + return OpenAsArc_Msg(NULL, tfi, fullPath, arcFormat /* , encrypted, showErrorMessage */); } -HRESULT CPanel::OpenAsArc_Index(int index, const wchar_t *type, bool showErrorMessage) +HRESULT CPanel::OpenAsArc_Index(int index, const wchar_t *type + // , bool showErrorMessage + ) { CDisableTimerProcessing disableTimerProcessing1(*this); CDisableNotify disableNotify(*this); - bool encrypted; - HRESULT res = OpenAsArc_Name(GetItemRelPath2(index), type ? type : L"", encrypted, showErrorMessage); + + HRESULT res = OpenAsArc_Name(GetItemRelPath2(index), type ? type : L"" /* , encrypted, showErrorMessage */); if (res != S_OK) { RefreshTitle(true); // in case of error we must refresh changed title of 7zFM @@ -677,16 +633,24 @@ static const char * const kStartExtensions = " msi doc dot xls ppt pps wps wpt wks xlr wdb vsd pub" " docx docm dotx dotm xlsx xlsm xltx xltm xlsb xps" - " xlam pptx pptm potx potm ppam ppsx ppsm xsn" + " xlam pptx pptm potx potm ppam ppsx ppsm vsdx xsn" " mpp" " msg" " dwf" " flv swf" + " epub" " odt ods" " wb3" " pdf" + " ps" + " txt" + " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml" + " h hpp hxx c cpp cxx m mm go swift" + " awk sed hta js json php php3 php4 php5 phptml pl pm py pyo rb tcl ts vbs" + " asm" + " mak clw csproj vcproj sln dsp dsw" " "; static bool FindExt(const char *p, const UString &name) @@ -724,6 +688,7 @@ static bool DoItemAlwaysStart(const UString &name) UString GetQuotedString(const UString &s); +void SplitCmdLineSmart(const UString &cmd, UString &prg, UString ¶ms); void SplitCmdLineSmart(const UString &cmd, UString &prg, UString ¶ms) { params.Empty(); @@ -734,11 +699,11 @@ void SplitCmdLineSmart(const UString &cmd, UString &prg, UString ¶ms) int pos = prg.Find(L'"', 1); if (pos >= 0) { - if ((unsigned)pos + 1 == prg.Len() || prg[pos + 1] == ' ') + if ((unsigned)(pos + 1) == prg.Len() || prg[pos + 1] == ' ') { - params = prg.Ptr(pos + 1); + params = prg.Ptr((unsigned)(pos + 1)); params.Trim(); - prg.DeleteFrom(pos); + prg.DeleteFrom((unsigned)pos); prg.DeleteFrontal(1); } } @@ -841,6 +806,11 @@ void CApp::DiffFiles() else return; + DiffFiles(path1, path2); +} + +void CApp::DiffFiles(const UString &path1, const UString &path2) +{ UString command; ReadRegDiff(command); if (command.IsEmpty()) @@ -894,7 +864,7 @@ static HRESULT StartApplication(const UString &dir, const UString &path, HWND wi execInfo.nShow = SW_SHOWNORMAL; execInfo.hProcess = 0; ShellExecuteExWP shellExecuteExW = (ShellExecuteExWP) - ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "ShellExecuteExW"); + (void *)::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "ShellExecuteExW"); if (!shellExecuteExW) return 0; shellExecuteExW(&execInfo); @@ -985,7 +955,7 @@ void CPanel::OpenFolderExternal(int index) int pos = prefix.ReverseFind_PathSepar(); if (pos < 0) return; - prefix.DeleteFrom(pos + 1); + prefix.DeleteFrom((unsigned)(pos + 1)); path = prefix; } else @@ -1102,7 +1072,9 @@ void CPanel::OpenItem(int index, bool tryInternal, bool tryExternal, const wchar if (tryInternal) if (!tryExternal || !DoItemAlwaysStart(name)) { - HRESULT res = OpenAsArc_Index(index, type, true); + HRESULT res = OpenAsArc_Index(index, type + // , true + ); disableNotify.Restore(); // we must restore to allow text notification update InvalidateList(); if (res == S_OK || res == E_ABORT) @@ -1299,7 +1271,7 @@ static THREAD_FUNC_DECL MyThreadFunction(void *param) { handles.Add(g_ExitEventLauncher._exitEvent); - DWORD waitResult = ::WaitForMultipleObjects(handles.Size(), &handles.Front(), FALSE, INFINITE); + DWORD waitResult = WaitForMultiObj_Any_Infinite(handles.Size(), &handles.Front()); waitResult -= WAIT_OBJECT_0; @@ -1451,8 +1423,8 @@ static void ReadZoneFile(CFSTR fileName, CByteBuffer &buf) if (fileSize == 0 || fileSize >= ((UInt32)1 << 20)) return; buf.Alloc((size_t)fileSize); - UInt32 processed; - if (file.Read(buf, (UInt32)fileSize, processed) && processed == fileSize) + size_t processed; + if (file.ReadFull(buf, (size_t)fileSize, processed) && processed == fileSize) return; buf.Free(); } @@ -1644,8 +1616,9 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo subSeqStream.QueryInterface(IID_IInStream, &subStream); if (subStream) { - bool encrypted; - HRESULT res = OpenAsArc_Msg(subStream, tempFileInfo, fullVirtPath, type ? type : L"", encrypted, true); + HRESULT res = OpenAsArc_Msg(subStream, tempFileInfo, fullVirtPath, type ? type : L"" + // , true // showErrorMessage + ); if (res == S_OK) { tempDirectory.DisableDeleting(); @@ -1757,9 +1730,12 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo CBufInStream *bufInStreamSpec = new CBufInStream; CMyComPtr<IInStream> bufInStream = bufInStreamSpec; bufInStreamSpec->Init(file.Data, streamSize, virtFileSystem); - bool encrypted; - HRESULT res = OpenAsArc_Msg(bufInStream, tempFileInfo, fullVirtPath, type ? type : L"", encrypted, true); + HRESULT res = OpenAsArc_Msg(bufInStream, tempFileInfo, fullVirtPath, type ? type : L"" + // , encrypted + // , true // showErrorMessage + ); + if (res == S_OK) { tempDirectory.DisableDeleting(); @@ -1782,7 +1758,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo #if defined(_WIN32) && !defined(UNDER_CE) if (zoneBuf.Size() != 0) { - if (NFind::DoesFileExist(tempFilePath)) + if (NFind::DoesFileExist_Raw(tempFilePath)) { WriteZoneFile(tempFilePath + k_ZoneId_StreamName, zoneBuf); } @@ -1792,8 +1768,10 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo if (tryAsArchive) { - bool encrypted; - HRESULT res = OpenAsArc_Msg(NULL, tempFileInfo, fullVirtPath, type ? type : L"", encrypted, true); + HRESULT res = OpenAsArc_Msg(NULL, tempFileInfo, fullVirtPath, type ? type : L"" + // , encrypted + // , true // showErrorMessage + ); if (res == S_OK) { tempDirectory.DisableDeleting(); diff --git a/CPP/7zip/UI/FileManager/PanelItems.cpp b/CPP/7zip/UI/FileManager/PanelItems.cpp index 178df7c7..33e44588 100644 --- a/CPP/7zip/UI/FileManager/PanelItems.cpp +++ b/CPP/7zip/UI/FileManager/PanelItems.cpp @@ -87,7 +87,7 @@ static int GetColumnAlign(PROPID propID, VARTYPE varType) static int ItemProperty_Compare_NameFirst(void *const *a1, void *const *a2, void * /* param */) { - return (*(*((const CPropColumn **)a1))).Compare_NameFirst(*(*((const CPropColumn **)a2))); + return (*(*((const CPropColumn *const *)a1))).Compare_NameFirst(*(*((const CPropColumn *const *)a2))); } HRESULT CPanel::InitColumns() @@ -154,6 +154,21 @@ HRESULT CPanel::InitColumns() prop.IsRawProp = false; _columns.Add(prop); } + + /* + { + // debug column + CPropColumn prop; + prop.Type = VT_BSTR; + prop.ID = 2000; + prop.Name = "Debug"; + prop.Order = -1; + prop.IsVisible = true; + prop.Width = 300; + prop.IsRawProp = false; + _columns.Add(prop); + } + */ } if (_folderRawProps) @@ -174,7 +189,7 @@ HRESULT CPanel::InitColumns() prop.Name = GetNameOfProperty(propID, name); prop.Order = -1; prop.IsVisible = GetColumnVisible(propID, isFsFolder); - prop.Width = GetColumnWidth(propID, VT_BSTR);; + prop.Width = GetColumnWidth(propID, VT_BSTR); prop.IsRawProp = true; _columns.Add(prop); } @@ -250,7 +265,7 @@ HRESULT CPanel::InitColumns() /* There are restrictions in ListView control: 1) main column (kpidName) must have (LV_COLUMNW::iSubItem = 0) So we need special sorting for columns. - 2) when we add new column, LV_COLUMNW::iOrder can not be larger than already inserted columns) + 2) when we add new column, LV_COLUMNW::iOrder cannot be larger than already inserted columns) So we set column order after all columns are added. */ newColumns.Sort(ItemProperty_Compare_NameFirst, NULL); @@ -435,11 +450,27 @@ void CPanel::SetFocusedSelectedItem(int index, bool select) #endif + +/* + +extern UInt32 g_NumGroups; +extern DWORD g_start_tick; +extern DWORD g_prev_tick; +extern DWORD g_Num_SetItemText; +extern UInt32 g_NumMessages; +*/ + HRESULT CPanel::RefreshListCtrl(const CSelectedState &state) { if (!_folder) return S_OK; + /* + g_start_tick = GetTickCount(); + g_Num_SetItemText = 0; + g_NumMessages = 0; + */ + _dontShowMode = false; LoadFullPathAndShow(); // OutputDebugStringA("=======\n"); @@ -545,6 +576,8 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state) Print_OnNotify("===== Before Load"); + // #define USE_EMBED_ITEM + if (showDots) { UString itemName (".."); @@ -555,8 +588,11 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state) int subItem = 0; item.iSubItem = subItem++; item.lParam = kParentIndex; - // item.pszText = const_cast<wchar_t *>((const wchar_t *)itemName); + #ifdef USE_EMBED_ITEM + item.pszText = const_cast<wchar_t *>((const wchar_t *)itemName); + #else item.pszText = LPSTR_TEXTCALLBACKW; + #endif UInt32 attrib = FILE_ATTRIBUTE_DIRECTORY; item.iImage = _extToIconMap.GetIconIndex(attrib, itemName); if (item.iImage < 0) @@ -591,10 +627,8 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state) if (state.FocusedName_Defined || !state.SelectedNames.IsEmpty()) { relPath.Empty(); - // relPath += GetItemPrefix(i); - // change it (_flatMode) - if (i != kParentIndex && _flatMode) + if (_flatMode) { const wchar_t *prefix = NULL; if (_folderGetItemName) @@ -672,8 +706,11 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state) else */ { - // item.pszText = const_cast<wchar_t *>((const wchar_t *)name); + #ifdef USE_EMBED_ITEM + item.pszText = const_cast<wchar_t *>((const wchar_t *)name); + #else item.pszText = LPSTR_TEXTCALLBACKW; + #endif /* LPSTR_TEXTCALLBACKW works, but in some cases there are problems, since we block notify handler. LPSTR_TEXTCALLBACKW can be 2-3 times faster for loading in this loop. */ diff --git a/CPP/7zip/UI/FileManager/PanelKey.cpp b/CPP/7zip/UI/FileManager/PanelKey.cpp index 5603251f..3ab478eb 100644 --- a/CPP/7zip/UI/FileManager/PanelKey.cpp +++ b/CPP/7zip/UI/FileManager/PanelKey.cpp @@ -29,7 +29,7 @@ static const CVKeyPropIDPair g_VKeyPropIDPairs[] = static int FindVKeyPropIDPair(WORD vKey) { - for (int i = 0; i < ARRAY_SIZE(g_VKeyPropIDPairs); i++) + for (unsigned i = 0; i < ARRAY_SIZE(g_VKeyPropIDPairs); i++) if (g_VKeyPropIDPairs[i].VKey == vKey) return i; return -1; diff --git a/CPP/7zip/UI/FileManager/PanelListNotify.cpp b/CPP/7zip/UI/FileManager/PanelListNotify.cpp index 9061e585..12f471b3 100644 --- a/CPP/7zip/UI/FileManager/PanelListNotify.cpp +++ b/CPP/7zip/UI/FileManager/PanelListNotify.cpp @@ -84,6 +84,7 @@ static void ConvertSizeToString(UInt64 val, wchar_t *s) throw() *s = 0; } +UString ConvertSizeToString(UInt64 value); UString ConvertSizeToString(UInt64 value) { wchar_t s[32]; @@ -110,6 +111,7 @@ static void HexToString(char *dest, const Byte *data, UInt32 size) } */ +bool IsSizeProp(UINT propID) throw(); bool IsSizeProp(UINT propID) throw() { switch (propID) @@ -141,12 +143,39 @@ bool IsSizeProp(UINT propID) throw() return false; } + + +/* +#include <stdio.h> + +UInt64 GetCpuTicks() +{ + #ifdef _WIN64 + return __rdtsc(); + #else + UInt32 lowVal, highVal; + __asm RDTSC; + __asm mov lowVal, EAX; + __asm mov highVal, EDX; + return ((UInt64)highVal << 32) | lowVal; + #endif +} + +UInt32 g_NumGroups; +UInt64 g_start_tick; +UInt64 g_prev_tick; +DWORD g_Num_SetItemText; +UInt32 g_NumMessages; +*/ + LRESULT CPanel::SetItemText(LVITEMW &item) { if (_dontShowMode) return 0; UInt32 realIndex = GetRealIndex(item); + // g_Num_SetItemText++; + /* if ((item.mask & LVIF_IMAGE) != 0) { @@ -190,7 +219,7 @@ LRESULT CPanel::SetItemText(LVITEMW &item) const CPropColumn &property = _visibleColumns[item.iSubItem]; PROPID propID = property.ID; - if (realIndex == kParentIndex) + if (realIndex == kParentIndex_UInt32) { if (propID == kpidName) { @@ -204,7 +233,52 @@ LRESULT CPanel::SetItemText(LVITEMW &item) return 0; } - + /* + // List-view in report-view in Windows 10 is slow (50+ ms) for page change. + // that code shows the time of page reload for items + // if you know how to improve the speed of list view refresh, notify 7-Zip developer + + // if (propID == 2000) + // if (propID == kpidName) + { + // debug column; + // DWORD dw = GetCpuTicks(); + UInt64 dw = GetCpuTicks(); + UInt64 deltaLast = dw - g_prev_tick; + #define conv_ticks(t) ((unsigned)((t) / 100000)) + if (deltaLast > 1000u * 1000 * 1000) + { + UInt64 deltaFull = g_prev_tick - g_start_tick; + char s[128]; + sprintf(s, "%d", conv_ticks(deltaFull)); + OutputDebugStringA(s); + g_start_tick = dw; + g_NumGroups++; + } + g_prev_tick = dw; + UString u; + char s[128]; + UInt64 deltaFull = dw - g_start_tick; + // for (int i = 0; i < 100000; i++) + sprintf(s, "%d %d %d-%d ", g_NumMessages, g_Num_SetItemText, g_NumGroups, conv_ticks(deltaFull)); + // sprintf(s, "%d-%d ", g_NumGroups, conv_ticks(deltaFull)); + u = s; + lstrcpyW(text, u.Ptr()); + text += u.Len(); + + // dw = GetCpuTicks(); + // deltaFull = dw - g_prev_tick; + // sprintf(s, "-%d ", conv_ticks(deltaFull)); + // u = s; + // lstrcpyW(text, u.Ptr()); + // text += u.Len(); + + if (propID != kpidName) + return 0; + } + */ + + if (property.IsRawProp) { const void *data; @@ -525,9 +599,15 @@ bool CPanel::OnNotifyList(LPNMHDR header, LRESULT &result) //is the sub-item information being requested? if ((dispInfo->item.mask & LVIF_TEXT) != 0 || - (dispInfo->item.mask & LVIF_IMAGE) != 0) + (dispInfo->item.mask & LVIF_IMAGE) != 0) SetItemText(dispInfo->item); - return false; + { + // 20.03: + result = 0; + return true; + // old 7-Zip: + // return false; + } } case LVN_KEYDOWN: { diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp index 11c6d7c1..7a88f8f2 100644 --- a/CPP/7zip/UI/FileManager/PanelMenu.cpp +++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp @@ -25,6 +25,8 @@ using namespace NWindows; +extern +LONG g_DllRefCount; LONG g_DllRefCount = 0; static const UINT kSevenZipStartMenuID = kMenuCmdID_Plugin_Start; @@ -99,18 +101,25 @@ static void AddPropertyString(PROPID propID, const wchar_t *nameBSTR, if (flags != 0) val = GetOpenArcErrorMessage(flags); } + if (val.IsEmpty()) - if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && IsSizeProp(propID)) { - UInt64 v = 0; - ConvertPropVariantToUInt64(prop, v); - val = ConvertSizeToString(v); + if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && IsSizeProp(propID)) + { + UInt64 v = 0; + ConvertPropVariantToUInt64(prop, v); + val = ConvertSizeToString(v); + } + else + ConvertPropertyToString2(val, prop, propID); } - else - ConvertPropertyToString2(val, prop, propID); if (!val.IsEmpty()) { + if (propID == kpidErrorType) + { + AddPropertyPair(L"Open WARNING:", L"Cannot open the file as expected archive type", dialog); + } AddPropertyPair(GetNameOfProperty(propID, nameBSTR), val, dialog); } } @@ -247,7 +256,7 @@ void CPanel::Properties() { numDirs++; numDirs += GetItem_UInt64Prop(index, kpidNumSubDirs); - numFiles += GetItem_UInt64Prop(index, kpidNumSubFiles);; + numFiles += GetItem_UInt64Prop(index, kpidNumSubFiles); } else numFiles++; @@ -343,7 +352,7 @@ void CPanel::Properties() } } - if (level2 != numLevels - 1) + if (level2 < numLevels - 1) { UInt32 level = numLevels - 1 - level2; UInt32 numProps; @@ -365,6 +374,28 @@ void CPanel::Properties() } } } + + { + // we ERROR message for NonOpen level + bool needSep = true; + const int kNumSpecProps = ARRAY_SIZE(kSpecProps); + for (Int32 i = -(int)kNumSpecProps; i < 0; i++) + { + CMyComBSTR name; + PROPID propID = kSpecProps[i + kNumSpecProps]; + NCOM::CPropVariant prop; + if (getProps->GetArcProp(numLevels, propID, &prop) != S_OK) + continue; + if (needSep) + { + AddSeparator(message); + AddSeparator(message); + needSep = false; + } + AddPropertyString(propID, name, prop, message); + } + } + } } @@ -460,7 +491,7 @@ HRESULT CPanel::CreateShellContextMenu( // if (folderPath.IsEmpty()), then ParseDisplayName returns pidls of "My Computer" RINOK(desktopFolder->ParseDisplayName( - GetParent(), NULL, (wchar_t *)(const wchar_t *)folderPath, + GetParent(), NULL, folderPath.Ptr_non_const(), &eaten, &pidls.parent, NULL)); /* @@ -516,14 +547,14 @@ HRESULT CPanel::CreateShellContextMenu( LPITEMIDLIST pidl; const UString fileName = GetItemRelPath2(operatedIndices[i]); RINOK(parentFolder->ParseDisplayName(GetParent(), 0, - (wchar_t *)(const wchar_t *)fileName, &eaten, &pidl, 0)); + fileName.Ptr_non_const(), &eaten, &pidl, 0)); pidls.items.AddInReserved(pidl); } // Get IContextMenu for items RINOK(parentFolder->GetUIObjectOf(GetParent(), pidls.items.Size(), - (LPCITEMIDLIST *)&pidls.items.Front(), IID_IContextMenu, 0, (void**)&systemContextMenu)); + (LPCITEMIDLIST *)(void *)&pidls.items.Front(), IID_IContextMenu, 0, (void**)&systemContextMenu)); if (!systemContextMenu) { @@ -533,6 +564,99 @@ HRESULT CPanel::CreateShellContextMenu( return S_OK; } +// #define SHOW_DEBUG_FM_CTX_MENU + +#ifdef SHOW_DEBUG_FM_CTX_MENU + +#include <stdio.h> + +// #include Common/IntToString.h" + +static void PrintHex(UString &s, UInt32 v) +{ + char sz[32]; + ConvertUInt32ToHex(v, sz); + s += sz; +} + +static void PrintContextStr(UString &s, IContextMenu *ctxm, unsigned i, unsigned id, const char *name) +{ + s += " | "; + name = name; + // s += name; + // s += ": "; + + UString s1; + { + char buf[256]; + buf[0] = 0; + HRESULT res = ctxm->GetCommandString(i, id, + NULL, buf, ARRAY_SIZE(buf) - 1); + if (res != S_OK) + { + PrintHex(s1, res); + s1.Add_Space(); + } + s1 += GetUnicodeString(buf); + } + + UString s2; + { + wchar_t buf2[256]; + buf2[0] = 0; + HRESULT res = ctxm->GetCommandString(i, id | GCS_UNICODE, + NULL, (char *)buf2, ARRAY_SIZE(buf2) - 1); + if (res != S_OK) + { + PrintHex(s2, res); + s2.Add_Space(); + } + s2 += buf2; + } + + s += s1; + if (s2.Compare(s1) != 0) + { + s += " Unicode: "; + s += s2; + } +} + + +static void PrintAllContextItems(IContextMenu *ctxm, unsigned num) +{ + for (unsigned i = 0; i < num; i++) + { + UString s; + s.Add_UInt32(i); + s += ": "; + + /* + UString valid; + { + char name[256]; + HRESULT res = ctxm->GetCommandString(i, GCS_VALIDATEA, + NULL, name, ARRAY_SIZE(name) - 1); + + if (res == S_OK) + { + // valid = "valid"; + } + else if (res == S_FALSE) + valid = "non-valid"; + else + PrintHex(valid, res); + } + s += valid; + */ + + PrintContextStr(s, ctxm, i, GCS_VALIDATEA, "valid"); + PrintContextStr(s, ctxm, i, GCS_VERBA, "v"); + PrintContextStr(s, ctxm, i, GCS_HELPTEXTA, "h"); + OutputDebugStringW(s); + } +} +#endif void CPanel::CreateSystemMenu(HMENU menuSpec, const CRecordVector<UInt32> &operatedIndices, @@ -542,14 +666,16 @@ void CPanel::CreateSystemMenu(HMENU menuSpec, CreateShellContextMenu(operatedIndices, systemContextMenu); - if (systemContextMenu == 0) + if (!systemContextMenu) return; + /* // Set up a CMINVOKECOMMANDINFO structure. CMINVOKECOMMANDINFO ci; ZeroMemory(&ci, sizeof(ci)); ci.cbSize = sizeof(CMINVOKECOMMANDINFO); ci.hwnd = GetParent(); + */ /* if (Sender == GoBtn) @@ -578,7 +704,7 @@ void CPanel::CreateSystemMenu(HMENU menuSpec, { // HMENU hMenu = CreatePopupMenu(); CMenu popupMenu; - // CMenuDestroyer menuDestroyer(popupMenu); + CMenuDestroyer menuDestroyer(popupMenu); if (!popupMenu.CreatePopup()) throw 210503; @@ -592,17 +718,21 @@ void CPanel::CreateSystemMenu(HMENU menuSpec, // commented out but you can uncommnent this // line to show the extended context menu. // Flags |= 0x00000080; - systemContextMenu->QueryContextMenu(hMenu, 0, kSystemStartMenuID, 0x7FFF, Flags); - + HRESULT res = systemContextMenu->QueryContextMenu(hMenu, 0, kSystemStartMenuID, 0x7FFF, Flags); + if (SUCCEEDED(res)) { + #ifdef SHOW_DEBUG_FM_CTX_MENU + PrintAllContextItems(systemContextMenu, (unsigned)res); + #endif + CMenu menu; menu.Attach(menuSpec); CMenuItem menuItem; menuItem.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID; menuItem.fType = MFT_STRING; menuItem.hSubMenu = popupMenu.Detach(); - // menuDestroyer.Disable(); + menuDestroyer.Disable(); LangString(IDS_SYSTEM, menuItem.StringValue); menu.InsertItem(0, true, menuItem); } @@ -648,8 +778,6 @@ void CPanel::CreateSevenZipMenu(HMENU menuSpec, // CMenuDestroyer menuDestroyer(menu); // menu.CreatePopup(); - bool sevenZipMenuCreated = false; - CZipContextMenu *contextMenuSpec = new CZipContextMenu; CMyComPtr<IContextMenu> contextMenu = contextMenuSpec; // if (contextMenu.CoCreateInstance(CLSID_CZipContextMenu, IID_IContextMenu) == S_OK) @@ -674,9 +802,24 @@ void CPanel::CreateSevenZipMenu(HMENU menuSpec, { HRESULT res = contextMenu->QueryContextMenu(menu, 0, kSevenZipStartMenuID, kSystemStartMenuID - 1, 0); - sevenZipMenuCreated = (HRESULT_SEVERITY(res) == SEVERITY_SUCCESS); + bool sevenZipMenuCreated = SUCCEEDED(res); if (sevenZipMenuCreated) - sevenZipContextMenu = contextMenu; + { + // if (res != 0) + { + // some "non-good" implementation of QueryContextMenu() could add some items to menu, but it return 0. + // so we still allow these items + sevenZipContextMenu = contextMenu; + #ifdef SHOW_DEBUG_FM_CTX_MENU + PrintAllContextItems(contextMenu, (unsigned)res); + #endif + } + } + else + { + // MessageBox_Error_HRESULT_Caption(res, L"QueryContextMenu"); + } + // int code = HRESULT_CODE(res); // int nextItemID = code; } @@ -795,6 +938,9 @@ void CPanel::CreateFileMenu(HMENU menuSpec, fm.isAltStreamsSupported = false; + if (fm.numItems == 1) + fm.FilePath = GetItemFullPath(operatedIndices[0]); + if (_folderAltStreams) { if (operatedIndices.Size() <= 1) @@ -818,7 +964,7 @@ void CPanel::CreateFileMenu(HMENU menuSpec, fm.Load(menu, menu.GetItemCount()); } -bool CPanel::InvokePluginCommand(int id) +bool CPanel::InvokePluginCommand(unsigned id) { return InvokePluginCommand(id, _sevenZipContextMenu, _systemContextMenu); } @@ -827,15 +973,15 @@ bool CPanel::InvokePluginCommand(int id) #define use_CMINVOKECOMMANDINFOEX #endif -bool CPanel::InvokePluginCommand(int id, +bool CPanel::InvokePluginCommand(unsigned id, IContextMenu *sevenZipContextMenu, IContextMenu *systemContextMenu) { UInt32 offset; bool isSystemMenu = (id >= kSystemStartMenuID); if (isSystemMenu) - offset = id - kSystemStartMenuID; + offset = id - kSystemStartMenuID; else - offset = id - kSevenZipStartMenuID; + offset = id - kSevenZipStartMenuID; #ifdef use_CMINVOKECOMMANDINFOEX CMINVOKECOMMANDINFOEX @@ -856,16 +1002,29 @@ bool CPanel::InvokePluginCommand(int id, commandInfo.hwnd = GetParent(); commandInfo.lpVerb = (LPCSTR)(MAKEINTRESOURCE(offset)); commandInfo.lpParameters = NULL; - const CSysString currentFolderSys (GetSystemString(_currentFolderPrefix)); - commandInfo.lpDirectory = (LPCSTR)(LPCTSTR)(currentFolderSys); + // 19.01: fixed CSysString to AString + // MSDN suggest to send NULL: lpDirectory: This member is always NULL for menu items inserted by a Shell extension. + const AString currentFolderA (GetAnsiString(_currentFolderPrefix)); + commandInfo.lpDirectory = (LPCSTR)(currentFolderA); commandInfo.nShow = SW_SHOW; #ifdef use_CMINVOKECOMMANDINFOEX commandInfo.lpParametersW = NULL; commandInfo.lpTitle = ""; - commandInfo.lpVerbW = (LPCWSTR)(MAKEINTRESOURCEW(offset)); - UString currentFolderUnicode = _currentFolderPrefix; + + /* + system ContextMenu handler supports ContextMenu subhandlers. + so InvokeCommand() converts (command_offset) from global number to subhandler number. + XP-64 / win10: + system ContextMenu converts (command_offset) in lpVerb only, + and it keeps lpVerbW unchanged. + also explorer.exe sends 0 in lpVerbW. + We try to keep compatibility with Windows Explorer here. + */ + commandInfo.lpVerbW = NULL; + + const UString currentFolderUnicode = _currentFolderPrefix; commandInfo.lpDirectoryW = currentFolderUnicode; commandInfo.lpTitleW = L""; // commandInfo.ptInvoke.x = xPos; @@ -885,6 +1044,8 @@ bool CPanel::InvokePluginCommand(int id, KillSelection(); return true; } + else + MessageBox_Error_HRESULT_Caption(result, L"InvokeCommand"); return false; } @@ -947,22 +1108,22 @@ bool CPanel::OnContextMenu(HANDLE windowHandle, int xPos, int yPos) CMyComPtr<IContextMenu> systemContextMenu; CreateFileMenu(menu, sevenZipContextMenu, systemContextMenu, false); - int result = menu.Track(TPM_LEFTALIGN + unsigned id = menu.Track(TPM_LEFTALIGN #ifndef UNDER_CE | TPM_RIGHTBUTTON #endif | TPM_RETURNCMD | TPM_NONOTIFY, xPos, yPos, _listView); - if (result == 0) + if (id == 0) return true; - if (result >= kMenuCmdID_Plugin_Start) + if (id >= kMenuCmdID_Plugin_Start) { - InvokePluginCommand(result, sevenZipContextMenu, systemContextMenu); + InvokePluginCommand(id, sevenZipContextMenu, systemContextMenu); return true; } - if (ExecuteFileCommand(result)) + if (ExecuteFileCommand(id)) return true; return true; } diff --git a/CPP/7zip/UI/FileManager/PanelOperations.cpp b/CPP/7zip/UI/FileManager/PanelOperations.cpp index 00bda1a9..d3e2e978 100644 --- a/CPP/7zip/UI/FileManager/PanelOperations.cpp +++ b/CPP/7zip/UI/FileManager/PanelOperations.cpp @@ -48,9 +48,7 @@ public: CMyComPtr<IProgress> UpdateCallback; CUpdateCallback100Imp *UpdateCallbackSpec; - HRESULT Result; - - CThreadFolderOperations(EFolderOpType opType): OpType(opType), Result(E_FAIL) {} + CThreadFolderOperations(EFolderOpType opType): OpType(opType) {} HRESULT DoOperation(CPanel &panel, const UString &progressTitle, const UString &titleError); }; @@ -60,18 +58,14 @@ HRESULT CThreadFolderOperations::ProcessVirt() switch (OpType) { case FOLDER_TYPE_CREATE_FOLDER: - Result = FolderOperations->CreateFolder(Name, UpdateCallback); - break; + return FolderOperations->CreateFolder(Name, UpdateCallback); case FOLDER_TYPE_DELETE: - Result = FolderOperations->Delete(&Indices.Front(), Indices.Size(), UpdateCallback); - break; + return FolderOperations->Delete(&Indices.Front(), Indices.Size(), UpdateCallback); case FOLDER_TYPE_RENAME: - Result = FolderOperations->Rename(Index, Name, UpdateCallback); - break; + return FolderOperations->Rename(Index, Name, UpdateCallback); default: - Result = E_FAIL; + return E_FAIL; } - return Result; } @@ -83,7 +77,6 @@ HRESULT CThreadFolderOperations::DoOperation(CPanel &panel, const UString &progr WaitMode = true; Sync.FinalMessage.ErrorMessage.Title = titleError; - Result = S_OK; UpdateCallbackSpec->Init(); @@ -94,7 +87,6 @@ HRESULT CThreadFolderOperations::DoOperation(CPanel &panel, const UString &progr UpdateCallbackSpec->Password = fl.Password; } - MainWindow = panel._mainWindow; // panel.GetParent() MainTitle = "7-Zip"; // LangString(IDS_APP_TITLE); MainAddTitle = progressTitle + L' '; @@ -274,9 +266,9 @@ BOOL CPanel::OnBeginLabelEdit(LV_DISPINFOW * lpnmh) return FALSE; } -bool IsCorrectFsName(const UString &name) +static bool IsCorrectFsName(const UString &name) { - const UString lastPart = name.Ptr(name.ReverseFind_PathSepar() + 1); + const UString lastPart = name.Ptr((unsigned)(name.ReverseFind_PathSepar() + 1)); return lastPart != L"." && lastPart != L".."; @@ -410,7 +402,7 @@ void CPanel::CreateFolder() { int pos = newName.Find(WCHAR_PATH_SEPARATOR); if (pos >= 0) - newName.DeleteFrom(pos); + newName.DeleteFrom((unsigned)(pos)); if (!_mySelectMode) state.SelectedNames.Clear(); state.FocusedName = newName; @@ -461,7 +453,7 @@ void CPanel::CreateFile() } int pos = newName.Find(WCHAR_PATH_SEPARATOR); if (pos >= 0) - newName.DeleteFrom(pos); + newName.DeleteFrom((unsigned)pos); if (!_mySelectMode) state.SelectedNames.Clear(); state.FocusedName = newName; diff --git a/CPP/7zip/UI/FileManager/PanelSelect.cpp b/CPP/7zip/UI/FileManager/PanelSelect.cpp index 8cfb23f4..eab9e1ab 100644 --- a/CPP/7zip/UI/FileManager/PanelSelect.cpp +++ b/CPP/7zip/UI/FileManager/PanelSelect.cpp @@ -193,7 +193,7 @@ void CPanel::SelectByType(bool selectMode) else { UString mask ('*'); - mask += name.Ptr(pos); + mask += name.Ptr((unsigned)pos); FOR_VECTOR (i, _selectedStatusVector) if (IsItem_Folder(i) == isItemFolder && DoesWildcardMatchName(mask, GetItemName(i))) _selectedStatusVector[i] = selectMode; @@ -241,6 +241,9 @@ void CPanel::InvertSelection() void CPanel::KillSelection() { SelectAll(false); + // ver 20.01: now we don't like that focused will be selected item. + // So the following code was disabled: + /* if (!_mySelectMode) { int focused = _listView.GetFocusedItem(); @@ -254,6 +257,7 @@ void CPanel::KillSelection() _listView.SetItemState_Selected(focused); } } + */ } void CPanel::OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate) diff --git a/CPP/7zip/UI/FileManager/PanelSort.cpp b/CPP/7zip/UI/FileManager/PanelSort.cpp index 4adfc39f..d26acb70 100644 --- a/CPP/7zip/UI/FileManager/PanelSort.cpp +++ b/CPP/7zip/UI/FileManager/PanelSort.cpp @@ -95,7 +95,7 @@ void CPanel::SetSortRawStatus() } -int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) +static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) { if (lpData == 0) return 0; @@ -182,7 +182,7 @@ int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) return prop1.Compare(prop2); } - +int CALLBACK CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData); int CALLBACK CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) { if (lpData == 0) return 0; diff --git a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp index 7c633323..00a0d801 100644 --- a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp +++ b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp @@ -274,7 +274,7 @@ void CApp::Split() NFind::CFileInfo fileInfo; if (!fileInfo.Find(us2fs(srcPath + itemName))) { - srcPanel.MessageBox_Error(L"Can not find file"); + srcPanel.MessageBox_Error(L"Cannot find file"); return; } if (fileInfo.Size <= splitDialog.VolumeSizes.Front()) diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.h b/CPP/7zip/UI/FileManager/ProgressDialog.h index 0f41b57a..35c182a8 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog.h +++ b/CPP/7zip/UI/FileManager/ProgressDialog.h @@ -137,7 +137,7 @@ public: { _title = title; INT_PTR res = CModalDialog::Create(IDD_PROGRESS, wndParent); - thread.Wait(); + thread.Wait_Close(); return res; } diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp index 28e3eae7..8e2d7c75 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp @@ -536,10 +536,10 @@ bool CProgressDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) labelSize = gSize - valueSize; yPos = my; - for (int i = 0; i < ARRAY_SIZE(kIDs); i += 2) + for (unsigned i = 0; i < ARRAY_SIZE(kIDs); i += 2) { int x = mx; - const int kNumColumn1Items = 5 * 2; + const unsigned kNumColumn1Items = 5 * 2; if (i >= kNumColumn1Items) { if (i == kNumColumn1Items) @@ -583,6 +583,7 @@ void CProgressDialog::SetProgressPos(UInt64 pos) #define UINT_TO_STR_2(val) { s[0] = (wchar_t)('0' + (val) / 10); s[1] = (wchar_t)('0' + (val) % 10); s += 2; } +void GetTimeString(UInt64 timeValue, wchar_t *s); void GetTimeString(UInt64 timeValue, wchar_t *s) { UInt64 hours = timeValue / 3600; @@ -892,8 +893,8 @@ void CProgressDialog::UpdateStatInfo(bool showAll) int slashPos = _filePath.ReverseFind_PathSepar(); if (slashPos >= 0) { - s1.SetFrom(_filePath, slashPos + 1); - s2 = _filePath.Ptr(slashPos + 1); + s1.SetFrom(_filePath, (unsigned)(slashPos + 1)); + s2 = _filePath.Ptr((unsigned)(slashPos + 1)); } else s2 = _filePath; @@ -942,7 +943,7 @@ INT_PTR CProgressDialog::Create(const UString &title, NWindows::CThread &thread, CWaitCursor waitCursor; HANDLE h[] = { thread, _createDialogEvent }; - WRes res2 = WaitForMultipleObjects(ARRAY_SIZE(h), h, FALSE, kCreateDelay); + DWORD res2 = WaitForMultipleObjects(ARRAY_SIZE(h), h, FALSE, kCreateDelay); if (res2 == WAIT_OBJECT_0 && !Sync.ThereIsMessage()) return 0; } @@ -954,9 +955,8 @@ INT_PTR CProgressDialog::Create(const UString &title, NWindows::CThread &thread, { _wasCreated = true; _dialogCreatedEvent.Set(); - res = res; } - thread.Wait(); + thread.Wait_Close(); if (!MessagesDisplayed) MessageBoxW(wndParent, L"Progress Error", L"7-Zip", MB_ICONERROR); return res; diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.h b/CPP/7zip/UI/FileManager/ProgressDialog2.h index 6c4213ac..fc032cd9 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog2.h +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.h @@ -321,7 +321,7 @@ CProgressThreadVirt::Create() CProgressThreadVirt::Process() { { - ProcessVirt(); // virtual function that must implement real work + Result = ProcessVirt(); // virtual function that must implement real work } if (exceptions) or FinalMessage.ErrorMessage.Message { diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2a.rc b/CPP/7zip/UI/FileManager/ProgressDialog2a.rc index e9713930..c183af82 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog2a.rc +++ b/CPP/7zip/UI/FileManager/ProgressDialog2a.rc @@ -44,7 +44,7 @@ DIALOG_ID DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT CAPTION "Progress" { DEFPUSHBUTTON "&Background", IDB_PROGRESS_BACKGROUND, bx3, by, bxs, bys - PUSHBUTTON "&Pause", IDB_PAUSE bx2, by, bxs, bys + PUSHBUTTON "&Pause", IDB_PAUSE, bx2, by, bxs, bys PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys LTEXT "Elapsed time:", IDT_PROGRESS_ELAPSED, m, y0, x0s, 8 diff --git a/CPP/7zip/UI/FileManager/RegistryPlugins.cpp b/CPP/7zip/UI/FileManager/RegistryPlugins.cpp index a0753ca6..76a5787c 100644 --- a/CPP/7zip/UI/FileManager/RegistryPlugins.cpp +++ b/CPP/7zip/UI/FileManager/RegistryPlugins.cpp @@ -62,7 +62,7 @@ static bool ReadPluginInfo(CPluginInfo &pluginInfo, bool needCheckDll) else { pluginInfo.ClassIDDefined = true; - pluginInfo.ClassID = *(const GUID *)prop.bstrVal; + pluginInfo.ClassID = *(const GUID *)(const void *)prop.bstrVal; } prop.Clear(); @@ -75,7 +75,7 @@ static bool ReadPluginInfo(CPluginInfo &pluginInfo, bool needCheckDll) else { pluginInfo.OptionsClassIDDefined = true; - pluginInfo.OptionsClassID = *(const GUID *)prop.bstrVal; + pluginInfo.OptionsClassID = *(const GUID *)(const void *)prop.bstrVal; } prop.Clear(); diff --git a/CPP/7zip/UI/FileManager/RegistryUtils.cpp b/CPP/7zip/UI/FileManager/RegistryUtils.cpp index 91b69a21..a2fc2011 100644 --- a/CPP/7zip/UI/FileManager/RegistryUtils.cpp +++ b/CPP/7zip/UI/FileManager/RegistryUtils.cpp @@ -22,6 +22,7 @@ static LPCWSTR const kLangValueName = L"Lang"; static LPCWSTR const kViewer = L"Viewer"; static LPCWSTR const kEditor = L"Editor"; static LPCWSTR const kDiff = L"Diff"; +static LPCWSTR const kVerCtrlPath = L"7vc"; static LPCTSTR const kShowDots = TEXT("ShowDots"); static LPCTSTR const kShowRealFileIcons = TEXT("ShowRealFileIcons"); @@ -63,6 +64,8 @@ void ReadRegEditor(bool useEditor, UString &path) { ReadCuString(kCU_FMPath, use void SaveRegDiff(const UString &path) { SaveCuString(kCU_FMPath, kDiff, path); } void ReadRegDiff(UString &path) { ReadCuString(kCU_FMPath, kDiff, path); } +void ReadReg_VerCtrlPath(UString &path) { ReadCuString(kCU_FMPath, kVerCtrlPath, path); } + static void Save7ZipOption(LPCTSTR value, bool enabled) { CKey key; diff --git a/CPP/7zip/UI/FileManager/RegistryUtils.h b/CPP/7zip/UI/FileManager/RegistryUtils.h index b731778b..b85d670f 100644 --- a/CPP/7zip/UI/FileManager/RegistryUtils.h +++ b/CPP/7zip/UI/FileManager/RegistryUtils.h @@ -15,6 +15,8 @@ void ReadRegEditor(bool useEditor, UString &path); void SaveRegDiff(const UString &path); void ReadRegDiff(UString &path); +void ReadReg_VerCtrlPath(UString &path); + struct CFmSettings { bool ShowDots; diff --git a/CPP/7zip/UI/FileManager/RootFolder.cpp b/CPP/7zip/UI/FileManager/RootFolder.cpp index 643f1066..84844c7d 100644 --- a/CPP/7zip/UI/FileManager/RootFolder.cpp +++ b/CPP/7zip/UI/FileManager/RootFolder.cpp @@ -46,6 +46,7 @@ static const Byte kProps[] = kpidName }; +UString RootFolder_GetName_Computer(int &iconIndex); UString RootFolder_GetName_Computer(int &iconIndex) { #ifdef USE_WIN_PATHS @@ -56,12 +57,14 @@ UString RootFolder_GetName_Computer(int &iconIndex) return LangString(IDS_COMPUTER); } +UString RootFolder_GetName_Network(int &iconIndex); UString RootFolder_GetName_Network(int &iconIndex) { iconIndex = GetIconIndexForCSIDL(CSIDL_NETWORK); return LangString(IDS_NETWORK); } +UString RootFolder_GetName_Documents(int &iconIndex); UString RootFolder_GetName_Documents(int &iconIndex) { iconIndex = GetIconIndexForCSIDL(CSIDL_PERSONAL); @@ -120,7 +123,7 @@ STDMETHODIMP CRootFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIA typedef BOOL (WINAPI *SHGetSpecialFolderPathWp)(HWND hwnd, LPWSTR pszPath, int csidl, BOOL fCreate); typedef BOOL (WINAPI *SHGetSpecialFolderPathAp)(HWND hwnd, LPSTR pszPath, int csidl, BOOL fCreate); -UString GetMyDocsPath() +static UString GetMyDocsPath() { UString us; WCHAR s[MAX_PATH + 1]; @@ -136,7 +139,7 @@ UString GetMyDocsPath() else { SHGetSpecialFolderPathAp getA = (SHGetSpecialFolderPathAp) - ::GetProcAddress(::GetModuleHandleA("shell32.dll"), "SHGetSpecialFolderPathA"); + (void *)::GetProcAddress(::GetModuleHandleA("shell32.dll"), "SHGetSpecialFolderPathA"); CHAR s2[MAX_PATH + 1]; if (getA && getA(0, s2, CSIDL_PERSONAL, FALSE)) us = GetUnicodeString(s2); diff --git a/CPP/7zip/UI/FileManager/StdAfx.h b/CPP/7zip/UI/FileManager/StdAfx.h index e6d96041..0e6d4461 100644 --- a/CPP/7zip/UI/FileManager/StdAfx.h +++ b/CPP/7zip/UI/FileManager/StdAfx.h @@ -14,8 +14,8 @@ // #include "../../../Common/MyWindows.h" -// #include <commctrl.h> +// #include <CommCtrl.h> // #include <ShlObj.h> -// #include <shlwapi.h> +// #include <Shlwapi.h> #endif diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.cpp b/CPP/7zip/UI/FileManager/SysIconUtils.cpp index c8ea8b95..b756dfcf 100644 --- a/CPP/7zip/UI/FileManager/SysIconUtils.cpp +++ b/CPP/7zip/UI/FileManager/SysIconUtils.cpp @@ -23,7 +23,7 @@ int GetIconIndexForCSIDL(int csidl) if (pidl) { SHFILEINFO shellInfo; - SHGetFileInfo(LPCTSTR(pidl), FILE_ATTRIBUTE_NORMAL, + SHGetFileInfo((LPCTSTR)(const void *)(pidl), FILE_ATTRIBUTE_NORMAL, &shellInfo, sizeof(shellInfo), SHGFI_PIDL | SHGFI_SYSICONINDEX); IMalloc *pMalloc; @@ -41,7 +41,7 @@ int GetIconIndexForCSIDL(int csidl) #ifndef _UNICODE typedef int (WINAPI * SHGetFileInfoWP)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags); -struct CSHGetFileInfoInit +static struct CSHGetFileInfoInit { SHGetFileInfoWP shGetFileInfoW; CSHGetFileInfoInit() diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.h b/CPP/7zip/UI/FileManager/SysIconUtils.h index f1b27fa1..fde16e46 100644 --- a/CPP/7zip/UI/FileManager/SysIconUtils.h +++ b/CPP/7zip/UI/FileManager/SysIconUtils.h @@ -5,7 +5,7 @@ #include "../../../Common/MyWindows.h" -#include <commctrl.h> +#include <CommCtrl.h> #include "../../../Common/MyString.h" diff --git a/CPP/7zip/UI/FileManager/SystemPage.cpp b/CPP/7zip/UI/FileManager/SystemPage.cpp index 819443ee..a95999f2 100644 --- a/CPP/7zip/UI/FileManager/SystemPage.cpp +++ b/CPP/7zip/UI/FileManager/SystemPage.cpp @@ -34,13 +34,16 @@ static const UInt32 kLangIDs[] = CSysString CModifiedExtInfo::GetString() const { + const char *s; if (State == kExtState_7Zip) - return TEXT("7-Zip"); - if (State == kExtState_Clear) - return TEXT(""); - if (Other7Zip) - return TEXT("[7-Zip]"); - return ProgramKey; + s = "7-Zip"; + else if (State == kExtState_Clear) + s = ""; + else if (Other7Zip) + s = "[7-Zip]"; + else + return ProgramKey; + return CSysString (s); }; @@ -197,14 +200,14 @@ bool CSystemPage::OnInit() ci.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM; ci.cx = 128; ci.fmt = LVCFMT_CENTER; - ci.pszText = (WCHAR *)(const WCHAR *)s; + ci.pszText = s.Ptr_non_const(); ci.iSubItem = 1; _listView.InsertColumn(1, &ci); #if NUM_EXT_GROUPS > 1 { LangString(IDS_SYSTEM_ALL_USERS, s); - ci.pszText = (WCHAR *)(const WCHAR *)s; + ci.pszText = s.Ptr_non_const(); ci.iSubItem = 2; _listView.InsertColumn(2, &ci); } @@ -225,7 +228,7 @@ bool CSystemPage::OnInit() // ListView always uses internal iImage that is 0 by default? // so we always use LVIF_IMAGE. item.iImage = -1; - item.pszText = (wchar_t *)(const wchar_t *)(LPCWSTR)extInfo.Ext; + item.pszText = extInfo.Ext.Ptr_non_const(); CAssoc assoc; const CPluginToIcon &plug = extInfo.Plugins[0]; diff --git a/CPP/7zip/UI/FileManager/SystemPage.h b/CPP/7zip/UI/FileManager/SystemPage.h index 761a49ac..765214cf 100644 --- a/CPP/7zip/UI/FileManager/SystemPage.h +++ b/CPP/7zip/UI/FileManager/SystemPage.h @@ -90,7 +90,7 @@ class CSystemPage: public NWindows::NControl::CPropertyPage bool _needSave; - const HKEY GetHKey(unsigned + HKEY GetHKey(unsigned #if NUM_EXT_GROUPS != 1 group #endif diff --git a/CPP/7zip/UI/FileManager/TextPairs.cpp b/CPP/7zip/UI/FileManager/TextPairs.cpp index d4002b45..6a989fcc 100644 --- a/CPP/7zip/UI/FileManager/TextPairs.cpp +++ b/CPP/7zip/UI/FileManager/TextPairs.cpp @@ -98,7 +98,7 @@ static int ComparePairItems(const CTextPair &p1, const CTextPair &p2) { return ComparePairIDs(p1.ID, p2.ID); } static int ComparePairItems(void *const *a1, void *const *a2, void * /* param */) - { return ComparePairItems(**(const CTextPair **)a1, **(const CTextPair **)a2); } + { return ComparePairItems(**(const CTextPair *const *)a1, **(const CTextPair *const *)a2); } void CPairsStorage::Sort() { Pairs.Sort(ComparePairItems, 0); } diff --git a/CPP/7zip/UI/FileManager/VerCtrl.cpp b/CPP/7zip/UI/FileManager/VerCtrl.cpp new file mode 100644 index 00000000..efed8468 --- /dev/null +++ b/CPP/7zip/UI/FileManager/VerCtrl.cpp @@ -0,0 +1,367 @@ +// VerCtrl.cpp + +#include "StdAfx.h" + +#include "../../../Common/StringToInt.h" + +#include "../../../Windows/FileName.h" +#include "../../../Windows/FileFind.h" + +#include "App.h" +#include "RegistryUtils.h" +#include "OverwriteDialog.h" + +#include "resource.h" + +using namespace NWindows; +using namespace NFile; +using namespace NFind; +using namespace NDir; + +static UString ConvertPath_to_Ctrl(const UString &path) +{ + UString s = path; + s.Replace(L':', L'_'); + return s; +} + +struct CFileDataInfo +{ + CByteBuffer Data; + BY_HANDLE_FILE_INFORMATION Info; + bool IsOpen; + + CFileDataInfo(): IsOpen (false) {} + UInt64 GetSize() const { return (((UInt64)Info.nFileSizeHigh) << 32) + Info.nFileSizeLow; } + bool Read(const UString &path); +}; + + +bool CFileDataInfo::Read(const UString &path) +{ + IsOpen = false; + NIO::CInFile file; + if (!file.Open(path)) + return false; + if (!file.GetFileInformation(&Info)) + return false; + + const UInt64 size = GetSize(); + const size_t size2 = (size_t)size; + if (size2 != size || size2 > (1 << 28)) + { + SetLastError(1); + return false; + } + + Data.Alloc(size2); + + size_t processedSize; + if (!file.ReadFull(Data, size2, processedSize)) + return false; + if (processedSize != size2) + { + SetLastError(1); + return false; + } + IsOpen = true; + return true; +} + + +static bool CreateComplexDir_for_File(const UString &path) +{ + FString resDirPrefix; + FString resFileName; + if (!GetFullPathAndSplit(path, resDirPrefix, resFileName)) + return false; + return CreateComplexDir(resDirPrefix); +} + + +static bool ParseNumberString(const FString &s, UInt32 &number) +{ + const wchar_t *end; + UInt64 result = ConvertStringToUInt64(s, &end); + if (*end != 0 || s.IsEmpty() || result > (UInt32)0x7FFFFFFF) + return false; + number = (UInt32)result; + return true; +} + + +static void WriteFile(const FString &path, bool createAlways, const CFileDataInfo &fdi, const CPanel &panel) +{ + NIO::COutFile outFile; + if (!outFile.Create(path, createAlways)) // (createAlways = false) means CREATE_NEW + { + panel.MessageBox_LastError(); + return; + } + UInt32 processedSize; + if (!outFile.Write(fdi.Data, (UInt32)fdi.Data.Size(), processedSize)) + { + panel.MessageBox_LastError(); + return; + } + if (processedSize != fdi.Data.Size()) + { + panel.MessageBox_Error(L"Write error"); + return; + } + if (!outFile.SetTime( + &fdi.Info.ftCreationTime, + &fdi.Info.ftLastAccessTime, + &fdi.Info.ftLastWriteTime)) + { + panel.MessageBox_LastError(); + return; + } + + if (!SetFileAttrib(path, fdi.Info.dwFileAttributes)) + { + panel.MessageBox_LastError(); + return; + } +} + + +void CApp::VerCtrl(unsigned id) +{ + const CPanel &panel = GetFocusedPanel(); + + if (!panel.Is_IO_FS_Folder()) + { + panel.MessageBox_Error_UnsupportOperation(); + return; + } + + CRecordVector<UInt32> indices; + panel.GetSelectedItemsIndices(indices); + + if (indices.Size() != 1) + { + // panel.MessageBox_Error_UnsupportOperation(); + return; + } + + const UString path = panel.GetItemFullPath(indices[0]); + + UString vercPath; + ReadReg_VerCtrlPath(vercPath); + if (vercPath.IsEmpty()) + return; + NName::NormalizeDirPathPrefix(vercPath); + + FString dirPrefix; + FString fileName; + if (!GetFullPathAndSplit(path, dirPrefix, fileName)) + { + panel.MessageBox_LastError(); + return; + } + + const UString dirPrefix2 = vercPath + ConvertPath_to_Ctrl(dirPrefix); + const UString path2 = dirPrefix2 + fileName; + + bool sameTime = false; + bool sameData = false; + bool areIdentical = false; + + CFileDataInfo fdi, fdi2; + if (!fdi.Read(path)) + { + panel.MessageBox_LastError(); + return; + } + + if (fdi2.Read(path2)) + { + sameData = (fdi.Data == fdi2.Data); + sameTime = (CompareFileTime(&fdi.Info.ftLastWriteTime, &fdi2.Info.ftLastWriteTime) == 0); + areIdentical = (sameData && sameTime); + } + + const bool isReadOnly = NAttributes::IsReadOnly(fdi.Info.dwFileAttributes); + + if (id == IDM_VER_EDIT) + { + if (!isReadOnly) + { + panel.MessageBox_Error(L"File is not read-only"); + return; + } + + if (!areIdentical) + { + if (fdi2.IsOpen) + { + NFind::CEnumerator enumerator; + FString d2 = dirPrefix2; + d2 += "_7vc"; + d2.Add_PathSepar(); + d2 += fileName; + d2.Add_PathSepar(); + enumerator.SetDirPrefix(d2); + NFind::CDirEntry fi; + Int32 maxVal = -1; + while (enumerator.Next(fi)) + { + UInt32 val; + if (!ParseNumberString(fi.Name, val)) + continue; + if ((Int32)val > maxVal) + maxVal = val; + } + + UInt32 next = (UInt32)maxVal + 1; + if (maxVal < 0) + { + next = 1; + if (!::CreateComplexDir_for_File(path2)) + { + panel.MessageBox_LastError(); + return; + } + } + + // we rename old file2 to some name; + FString path_num = d2; + { + AString t; + t.Add_UInt32((UInt32)next); + while (t.Len() < 3) + t.InsertAtFront('0'); + path_num += t; + } + + if (maxVal < 0) + { + if (!::CreateComplexDir_for_File(path_num)) + { + panel.MessageBox_LastError(); + return; + } + } + + if (!NDir::MyMoveFile(path2, path_num)) + { + panel.MessageBox_LastError(); + return; + } + } + else + { + if (!::CreateComplexDir_for_File(path2)) + { + panel.MessageBox_LastError(); + return; + } + } + /* + if (!::CopyFile(fs2fas(path), fs2fas(path2), TRUE)) + { + panel.MessageBox_LastError(); + return; + } + */ + WriteFile(path2, + false, // (createAlways = false) means CREATE_NEW + fdi, panel); + } + + if (!SetFileAttrib(path, fdi.Info.dwFileAttributes & ~(DWORD)FILE_ATTRIBUTE_READONLY)) + { + panel.MessageBox_LastError(); + return; + } + + return; + } + + if (isReadOnly) + { + panel.MessageBox_Error(L"File is read-only"); + return; + } + + if (id == IDM_VER_COMMIT) + { + if (sameData) + { + if (!sameTime) + { + panel.MessageBox_Error( + L"Same data, but different timestamps.\n" + L"Use `Revert` to recover timestamp."); + return; + } + } + if (!SetFileAttrib(path, fdi.Info.dwFileAttributes | FILE_ATTRIBUTE_READONLY)) + { + panel.MessageBox_LastError(); + return; + } + return; + } + + if (id == IDM_VER_REVERT) + { + if (!fdi2.IsOpen) + { + panel.MessageBox_Error(L"No file to revert"); + return; + } + if (!sameData || !sameTime) + { + if (!sameData) + { + /* + UString m; + m = "Are you sure you want to revert file ?"; + m.Add_LF(); + m += path; + if (::MessageBoxW(panel.GetParent(), m, L"Version Control: File Revert", MB_OKCANCEL | MB_ICONQUESTION) != IDOK) + return; + */ + COverwriteDialog dialog; + + dialog.OldFileInfo.SetTime(&fdi.Info.ftLastWriteTime); + dialog.OldFileInfo.SetSize(fdi.GetSize()); + dialog.OldFileInfo.Name = path; + + dialog.NewFileInfo.SetTime(&fdi2.Info.ftLastWriteTime); + dialog.NewFileInfo.SetSize(fdi2.GetSize()); + dialog.NewFileInfo.Name = path2; + + dialog.ShowExtraButtons = false; + dialog.DefaultButton_is_NO = true; + + INT_PTR writeAnswer = dialog.Create(panel.GetParent()); + + if (writeAnswer != IDYES) + return; + } + + WriteFile(path, + true, // (createAlways = true) means CREATE_ALWAYS + fdi2, panel); + } + else + { + if (!SetFileAttrib(path, fdi2.Info.dwFileAttributes | FILE_ATTRIBUTE_READONLY)) + { + panel.MessageBox_LastError(); + return; + } + } + return; + } + + // if (id == IDM_VER_DIFF) + { + if (!fdi2.IsOpen) + return; + DiffFiles(path2, path); + } +} diff --git a/CPP/7zip/UI/FileManager/ViewSettings.cpp b/CPP/7zip/UI/FileManager/ViewSettings.cpp index af61efcd..0f87711f 100644 --- a/CPP/7zip/UI/FileManager/ViewSettings.cpp +++ b/CPP/7zip/UI/FileManager/ViewSettings.cpp @@ -193,14 +193,14 @@ void CWindowInfo::Read(bool &windowPosDefined, bool &panelInfoDefined) } -void SaveUi32Val(const TCHAR *name, UInt32 value) +static void SaveUi32Val(const TCHAR *name, UInt32 value) { CKey key; key.Create(HKEY_CURRENT_USER, kCUBasePath); key.SetValue(name, value); } -bool ReadUi32Val(const TCHAR *name, UInt32 &value) +static bool ReadUi32Val(const TCHAR *name, UInt32 &value) { CKey key; if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS) diff --git a/CPP/7zip/UI/FileManager/resource.h b/CPP/7zip/UI/FileManager/resource.h index bb0d7752..98cb4fd4 100644 --- a/CPP/7zip/UI/FileManager/resource.h +++ b/CPP/7zip/UI/FileManager/resource.h @@ -47,6 +47,11 @@ #define IDM_LINK 558 #define IDM_ALT_STREAMS 559 +#define IDM_VER_EDIT 580 +#define IDM_VER_COMMIT 581 +#define IDM_VER_REVERT 582 +#define IDM_VER_DIFF 583 + #define IDM_OPEN_INSIDE_ONE 590 #define IDM_OPEN_INSIDE_PARSER 591 diff --git a/CPP/7zip/UI/FileManager/resource.rc b/CPP/7zip/UI/FileManager/resource.rc index 6d259eb0..fc2c8408 100644 --- a/CPP/7zip/UI/FileManager/resource.rc +++ b/CPP/7zip/UI/FileManager/resource.rc @@ -167,7 +167,7 @@ BEGIN IDS_FILE_EXIST "File {0} is already exist" IDS_WANT_UPDATE_MODIFIED_FILE "File '{0}' was modified.\nDo you want to update it in the archive?" - IDS_CANNOT_UPDATE_FILE "Can not update file\n'{0}'" + IDS_CANNOT_UPDATE_FILE "Cannot update file\n'{0}'" IDS_CANNOT_START_EDITOR "Cannot start editor." IDS_VIRUS "The file looks like a virus (the file name contains long spaces in name)." IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER "The operation cannot be called from a folder that has a long path." @@ -238,8 +238,8 @@ BEGIN IDS_COMBINE_TO "&Combine to:" IDS_COMBINING "Combining..." IDS_COMBINE_SELECT_ONE_FILE "Select only first part of split file" - IDS_COMBINE_CANT_DETECT_SPLIT_FILE "Can not detect file as split file" - IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART "Can not find more than one part of split file" + IDS_COMBINE_CANT_DETECT_SPLIT_FILE "Cannot detect file as split file" + IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART "Cannot find more than one part of split file" END diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp index e6dc57ba..94dfab4c 100644 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp @@ -164,14 +164,12 @@ bool CBenchmarkDialog::OnInit() s = s2; SetItemText(IDT_BENCH_CPU, s); } - /* { AString s2; - GetCpuFeatures(s2); + AddCpuFeatures(s2); s = s2; SetItemText(IDT_BENCH_CPU_FEATURE, s); } - */ s = "7-Zip " MY_VERSION_CPU; SetItemText(IDT_BENCH_VER, s); @@ -384,7 +382,7 @@ void CBenchmarkDialog::OnChangeSettings() EnableItem(IDB_STOP, true); UInt32 dict = OnChangeDictionary(); - for (int i = 0; i < ARRAY_SIZE(g_IDs); i++) + for (unsigned i = 0; i < ARRAY_SIZE(g_IDs); i++) SetItemText(g_IDs[i], kProcessingString); _startTime = GetTickCount(); PrintTime(); @@ -517,7 +515,7 @@ bool CBenchmarkDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */) { UInt32 dicSizeTemp = (UInt32)MyMax(Sync.ProcessedSize, UInt64(1) << 20); - dicSizeTemp = MyMin(dicSizeTemp, Sync.DictionarySize), + dicSizeTemp = MyMin(dicSizeTemp, Sync.DictionarySize); PrintResults(dicSizeTemp, Sync.CompressingInfoTemp, IDT_BENCH_COMPRESS_USAGE1, @@ -932,8 +930,10 @@ HRESULT Benchmark( benchmarker.BenchmarkDialog = &bd; - NWindows::CThread thread; - RINOK(thread.Create(CThreadBenchmark::MyThreadFunction, &benchmarker)); - bd.Create(hwndParent); - return thread.Wait(); + { + NWindows::CThread thread; + RINOK(thread.Create(CThreadBenchmark::MyThreadFunction, &benchmarker)); + bd.Create(hwndParent); + return thread.Wait_Close(); + } } diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.rc b/CPP/7zip/UI/GUI/BenchmarkDialog.rc index f1d37cab..a8455a0f 100644 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.rc +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.rc @@ -117,9 +117,9 @@ BEGIN RTEXT "", IDT_BENCH_CPU, m, 202, xc, 8 - RTEXT "", IDT_BENCH_VER, m + xc - 80, 216, 80, 8 + RTEXT "", IDT_BENCH_VER, m + xc - 100, 216, 100, 8 - LTEXT "", IDT_BENCH_CPU_FEATURE, m, 212, xc - 80, 26 + LTEXT "", IDT_BENCH_CPU_FEATURE, m, 228, xc - 100, 8 LTEXT "", IDT_BENCH_SYS1, m, 238, xc - 140, 8 LTEXT "", IDT_BENCH_SYS2, m, 248, xc - 140, 8 diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp index cbb2dda0..9f2cb146 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.cpp +++ b/CPP/7zip/UI/GUI/CompressDialog.cpp @@ -248,7 +248,7 @@ static const CFormatInfo g_Formats[] = static bool IsMethodSupportedBySfx(int methodID) { - for (int i = 0; i < ARRAY_SIZE(g_7zSfxMethods); i++) + for (unsigned i = 0; i < ARRAY_SIZE(g_7zSfxMethods); i++) if (methodID == g_7zSfxMethods[i]) return true; return false; @@ -336,6 +336,7 @@ bool CCompressDialog::OnInit() _password1Control.SetText(Info.Password); _password2Control.SetText(Info.Password); _encryptionMethod.Attach(GetItem(IDC_COMPRESS_ENCRYPTION_METHOD)); + _default_encryptionMethod_Index = -1; m_ArchivePath.Attach(GetItem(IDC_COMPRESS_ARCHIVE)); m_Format.Attach(GetItem(IDC_COMPRESS_FORMAT)); @@ -1150,11 +1151,13 @@ bool CCompressDialog::IsXzFormat() void CCompressDialog::SetEncryptionMethod() { _encryptionMethod.ResetContent(); + _default_encryptionMethod_Index = -1; const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; if (ai.Name.IsEqualTo_Ascii_NoCase("7z")) { ComboBox_AddStringAscii(_encryptionMethod, "AES-256"); _encryptionMethod.SetCurSel(0); + _default_encryptionMethod_Index = 0; } else if (ai.Name.IsEqualTo_Ascii_NoCase("zip")) { @@ -1165,9 +1168,15 @@ void CCompressDialog::SetEncryptionMethod() const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; encryptionMethod = fo.EncryptionMethod; } - ComboBox_AddStringAscii(_encryptionMethod, "ZipCrypto"); + int sel = 0; + // if (ZipCryptoIsAllowed) + { + ComboBox_AddStringAscii(_encryptionMethod, "ZipCrypto"); + sel = (encryptionMethod.IsPrefixedBy_Ascii_NoCase("aes") ? 1 : 0); + _default_encryptionMethod_Index = 0; + } ComboBox_AddStringAscii(_encryptionMethod, "AES-256"); - _encryptionMethod.SetCurSel(encryptionMethod.IsPrefixedBy_Ascii_NoCase("aes") ? 1 : 0); + _encryptionMethod.SetCurSel(sel); } } @@ -1189,8 +1198,8 @@ UString CCompressDialog::GetMethodSpec() UString CCompressDialog::GetEncryptionMethodSpec() { UString s; - if (_encryptionMethod.GetCount() > 1 - && _encryptionMethod.GetCurSel() > 0) + if (_encryptionMethod.GetCount() > 0 + && _encryptionMethod.GetCurSel() != _default_encryptionMethod_Index) { _encryptionMethod.GetText(s); s.RemoveChar(L'-'); @@ -1242,18 +1251,17 @@ void CCompressDialog::SetDictionary() case kLZMA: case kLZMA2: { - static const UInt32 kMinDicSize = (1 << 16); if (defaultDict == (UInt32)(Int32)-1) { - if (level >= 9) defaultDict = (1 << 26); - else if (level >= 7) defaultDict = (1 << 25); - else if (level >= 5) defaultDict = (1 << 24); - else if (level >= 3) defaultDict = (1 << 20); - else defaultDict = (kMinDicSize); + defaultDict = + ( level <= 3 ? (1 << (level * 2 + 16)) : + ( level <= 6 ? (1 << (level + 19)) : + ( level <= 7 ? (1 << 25) : (1 << 26) + ))); } - - AddDictionarySize(kMinDicSize); - m_Dictionary.SetCurSel(0); + AddDictionarySize(1 << 16); + AddDictionarySize(1 << 18); + m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1); for (unsigned i = 20; i <= 31; i++) for (unsigned j = 0; j < 2; j++) @@ -1286,10 +1294,7 @@ void CCompressDialog::SetDictionary() { if (defaultDict == (UInt32)(Int32)-1) { - if (level >= 9) defaultDict = (192 << 20); - else if (level >= 7) defaultDict = ( 64 << 20); - else if (level >= 5) defaultDict = ( 16 << 20); - else defaultDict = ( 4 << 20); + defaultDict = (UInt32)1 << (level + 19); } for (unsigned i = 20; i < 31; i++) @@ -1355,7 +1360,7 @@ void CCompressDialog::SetDictionary() case kPPMdZip: { if (defaultDict == (UInt32)(Int32)-1) - defaultDict = (1 << (19 + (level > 8 ? 8 : level))); + defaultDict = (UInt32)1 << (level + 19); for (unsigned i = 20; i <= 28; i++) { @@ -1512,6 +1517,21 @@ bool CCompressDialog::GetOrderMode() } +static UInt64 Get_Lzma2_ChunkSize(UInt32 dict) +{ + // we use same default chunk sizes as defined in 7z encoder and lzma2 encoder + UInt64 cs = (UInt64)dict << 2; + const UInt32 kMinSize = (UInt32)1 << 20; + const UInt32 kMaxSize = (UInt32)1 << 28; + if (cs < kMinSize) cs = kMinSize; + if (cs > kMaxSize) cs = kMaxSize; + if (cs < dict) cs = dict; + cs += (kMinSize - 1); + cs &= ~(UInt64)(kMinSize - 1); + return cs; +} + + void CCompressDialog::SetSolidBlockSize(bool useDictionary) { m_Solid.ResetContent(); @@ -1556,24 +1576,26 @@ void CCompressDialog::SetSolidBlockSize(bool useDictionary) m_Solid.SetCurSel(0); } - UInt64 blockSize; + const UInt64 cs = Get_Lzma2_ChunkSize(dict); + + // Solid Block Size + UInt64 blockSize = cs; // for xz if (is7z) { - blockSize = (UInt64)dict << 7; + // we use same default block sizes as defined in 7z encoder + UInt64 kMaxSize = (UInt64)1 << 32; + if (GetMethodID() == kLZMA2) + { + blockSize = cs << 6; + kMaxSize = (UInt64)1 << 34; + } + else + blockSize = (UInt64)dict << 7; + const UInt32 kMinSize = (UInt32)1 << 24; - const UInt64 kMaxSize = (UInt64)1 << 32; - if (blockSize < kMinSize) blockSize = kMinSize; - if (blockSize > kMaxSize) blockSize = kMaxSize; - } - else - { - blockSize = (UInt64)dict << 2; - const UInt32 kMinSize = (UInt32)1 << 20; - const UInt32 kMaxSize = (UInt32)1 << 28; if (blockSize < kMinSize) blockSize = kMinSize; if (blockSize > kMaxSize) blockSize = kMaxSize; - if (blockSize < dict) blockSize = dict; } for (unsigned i = 20; i <= 36; i++) @@ -1616,6 +1638,8 @@ void CCompressDialog::SetNumThreads() return; UInt32 numHardwareThreads = NSystem::GetNumberOfProcessors(); + // numHardwareThreads = 64; + UInt32 defaultValue = numHardwareThreads; { @@ -1634,7 +1658,7 @@ void CCompressDialog::SetNumThreads() switch (methodID) { case kLZMA: numAlgoThreadsMax = 2; break; - case kLZMA2: numAlgoThreadsMax = 32; break; + case kLZMA2: numAlgoThreadsMax = 256; break; case kBZip2: numAlgoThreadsMax = 32; break; } if (IsZipFormat()) @@ -1688,9 +1712,12 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt32 dict, UInt64 &decompressMemory) hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; - hs |= 0xFFFF; - if (hs > (1 << 24)) + if (hs >= (1 << 24)) hs >>= 1; + hs |= (1 << 16) - 1; + // if (numHashBytes >= 5) + if (level < 5) + hs |= (256 << 10) - 1; hs++; UInt64 size1 = (UInt64)hs * 4; size1 += (UInt64)dict * 4; @@ -1711,10 +1738,7 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt32 dict, UInt64 &decompressMemory) if (methidId != kLZMA && numBlockThreads != 1) { - chunkSize = (UInt64)dict << 2; - chunkSize = MyMax(chunkSize, (UInt64)(1 << 20)); - chunkSize = MyMin(chunkSize, (UInt64)(1 << 28)); - chunkSize = MyMax(chunkSize, (UInt64)dict); + chunkSize = Get_Lzma2_ChunkSize(dict); if (IsXzFormat()) { @@ -1795,10 +1819,19 @@ void CCompressDialog::PrintMemUsage(UINT res, UInt64 value) SetItemText(res, TEXT("?")); return; } - value = (value + (1 << 20) - 1) >> 20; TCHAR s[40]; - ConvertUInt64ToString(value, s); - lstrcat(s, TEXT(" MB")); + if (value <= ((UInt64)16 << 30)) + { + value = (value + (1 << 20) - 1) >> 20; + ConvertUInt64ToString(value, s); + lstrcat(s, TEXT(" MB")); + } + else + { + value = (value + (1 << 30) - 1) >> 30; + ConvertUInt64ToString(value, s); + lstrcat(s, TEXT(" GB")); + } SetItemText(res, s); } diff --git a/CPP/7zip/UI/GUI/CompressDialog.h b/CPP/7zip/UI/GUI/CompressDialog.h index 41466147..6658de5c 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.h +++ b/CPP/7zip/UI/GUI/CompressDialog.h @@ -108,6 +108,7 @@ class CCompressDialog: public NWindows::NControl::CModalDialog NWindows::NControl::CEdit _password1Control; NWindows::NControl::CEdit _password2Control; NWindows::NControl::CComboBox _encryptionMethod; + int _default_encryptionMethod_Index; NCompression::CInfo m_RegistryInfo; diff --git a/CPP/7zip/UI/GUI/Extract.rc b/CPP/7zip/UI/GUI/Extract.rc index f75b2e6f..36bfb009 100644 --- a/CPP/7zip/UI/GUI/Extract.rc +++ b/CPP/7zip/UI/GUI/Extract.rc @@ -7,11 +7,11 @@ BEGIN IDS_MEM_ERROR "The system cannot allocate the required amount of memory" IDS_CANNOT_CREATE_FOLDER "Cannot create folder '{0}'" IDS_UPDATE_NOT_SUPPORTED "Update operations are not supported for this archive." - IDS_CANT_OPEN_ARCHIVE "Can not open file '{0}' as archive" - IDS_CANT_OPEN_ENCRYPTED_ARCHIVE "Can not open encrypted archive '{0}'. Wrong password?" + IDS_CANT_OPEN_ARCHIVE "Cannot open file '{0}' as archive" + IDS_CANT_OPEN_ENCRYPTED_ARCHIVE "Cannot open encrypted archive '{0}'. Wrong password?" IDS_UNSUPPORTED_ARCHIVE_TYPE "Unsupported archive type" - IDS_CANT_OPEN_AS_TYPE "Can not open the file as {0} archive" + IDS_CANT_OPEN_AS_TYPE "Cannot open the file as {0} archive" IDS_IS_OPEN_AS_TYPE "The file is open as {0} archive" IDS_IS_OPEN_WITH_OFFSET "The archive is open with offset" @@ -45,7 +45,7 @@ BEGIN IDS_EXTRACT_MSG_DATA_ERROR "Data error" IDS_EXTRACT_MSG_CRC_ERROR "CRC failed" IDS_EXTRACT_MSG_UNAVAILABLE_DATA "Unavailable data" - IDS_EXTRACT_MSG_UEXPECTED_END "Unexpected end of data"; + IDS_EXTRACT_MSG_UEXPECTED_END "Unexpected end of data" IDS_EXTRACT_MSG_DATA_AFTER_END "There are some data after the end of the payload data" IDS_EXTRACT_MSG_IS_NOT_ARC "Is not archive" IDS_EXTRACT_MSG_HEADERS_ERROR "Headers Error" diff --git a/CPP/7zip/UI/GUI/ExtractDialog.cpp b/CPP/7zip/UI/GUI/ExtractDialog.cpp index b36a4943..5132084d 100644 --- a/CPP/7zip/UI/GUI/ExtractDialog.cpp +++ b/CPP/7zip/UI/GUI/ExtractDialog.cpp @@ -28,6 +28,8 @@ using namespace NName; extern HINSTANCE g_hInstance; +#ifndef _SFX + static const UInt32 kPathMode_IDs[] = { IDS_EXTRACT_PATHS_FULL, @@ -44,8 +46,6 @@ static const UInt32 kOverwriteMode_IDs[] = IDS_EXTRACT_OVERWRITE_RENAME_EXISTING }; -#ifndef _SFX - static const // NExtract::NPathMode::EEnum int @@ -94,6 +94,7 @@ static const unsigned kHistorySize = 16; #ifndef _SFX // it's used in CompressDialog also +void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned numItems, const int *values, int curVal); void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned numItems, const int *values, int curVal) { int curSel = 0; @@ -110,6 +111,7 @@ void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned n } // it's used in CompressDialog also +bool GetBoolsVal(const CBoolPair &b1, const CBoolPair &b2); bool GetBoolsVal(const CBoolPair &b1, const CBoolPair &b2) { if (b1.Def) return b1.Val; @@ -286,6 +288,7 @@ void CExtractDialog::OnButtonSetPath() _path.SetText(resultPath); } +void AddUniqueString(UStringVector &list, const UString &s); void AddUniqueString(UStringVector &list, const UString &s) { FOR_VECTOR (i, list) @@ -357,7 +360,7 @@ void CExtractDialog::OnOK() if (currentItem == CB_ERR) { _path.GetText(s); - if (_path.GetCount() >= kHistorySize) + if (_path.GetCount() >= (int)kHistorySize) currentItem = _path.GetCount() - 1; } else diff --git a/CPP/7zip/UI/GUI/GUI.cpp b/CPP/7zip/UI/GUI/GUI.cpp index 2674ec98..f5676d85 100644 --- a/CPP/7zip/UI/GUI/GUI.cpp +++ b/CPP/7zip/UI/GUI/GUI.cpp @@ -8,7 +8,7 @@ #include "../../../Common/MyWindows.h" -#include <shlwapi.h> +#include <Shlwapi.h> #include "../../../Common/MyInitGuid.h" @@ -34,10 +34,14 @@ using namespace NWindows; +extern +HINSTANCE g_hInstance; HINSTANCE g_hInstance; #ifndef UNDER_CE +extern +DWORD g_ComCtl32Version; DWORD g_ComCtl32Version; static DWORD GetDllVersion(LPCTSTR dllName) @@ -46,7 +50,7 @@ static DWORD GetDllVersion(LPCTSTR dllName) HINSTANCE hinstDll = LoadLibrary(dllName); if (hinstDll) { - DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion"); + DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)(void *)GetProcAddress(hinstDll, "DllGetVersion"); if (pDllGetVersion) { DLLVERSIONINFO dvi; @@ -63,6 +67,8 @@ static DWORD GetDllVersion(LPCTSTR dllName) #endif +extern +bool g_LVN_ITEMACTIVATE_Support; bool g_LVN_ITEMACTIVATE_Support = true; static void ErrorMessage(LPCWSTR message) @@ -90,7 +96,7 @@ static int ShowMemErrorMessage() static int ShowSysErrorMessage(DWORD errorCode) { - if (errorCode == E_OUTOFMEMORY) + if ((HRESULT)errorCode == E_OUTOFMEMORY) return ShowMemErrorMessage(); ErrorMessage(HResultToMessage(errorCode)); return NExitCode::kFatalError; @@ -128,7 +134,17 @@ static int Main2() codecs->CaseSensitiveChange = options.CaseSensitiveChange; codecs->CaseSensitive = options.CaseSensitive; ThrowException_if_Error(codecs->Load()); - + + #ifdef EXTERNAL_CODECS + { + UString s; + codecs->GetCodecsErrorMessage(s); + if (!s.IsEmpty()) + MessageBoxW(0, s, L"7-Zip", MB_ICONERROR); + } + #endif + + bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); if (codecs->Formats.Size() == 0 && @@ -343,7 +359,9 @@ static int Main2() return 0; } +#if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) #define NT_CHECK_FAIL_ACTION ErrorMessage("Unsupported Windows version"); return NExitCode::kFatalError; +#endif int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, #ifdef UNDER_CE diff --git a/CPP/7zip/UI/GUI/GUI.dsp b/CPP/7zip/UI/GUI/GUI.dsp index b70e2848..41c1e04d 100644 --- a/CPP/7zip/UI/GUI/GUI.dsp +++ b/CPP/7zip/UI/GUI/GUI.dsp @@ -55,7 +55,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-Zip\7zg.exe" /opt:NOWIN98 +# 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:\Util\7zg.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "GUI - Win32 Debug" @@ -82,7 +82,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-Zip\7zg.exe" /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Util\7zg.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "GUI - Win32 ReleaseU" @@ -109,7 +109,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\UTIL\7zg.exe" -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-Zip\7zgn.exe" /opt:NOWIN98 +# 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:\Util\7zg.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "GUI - Win32 DebugU" @@ -137,7 +137,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\UTIL\7zg.exe" /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-Zip\7zgn.exe" /pdbtype:sept +# 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:\Util\7zg.exe" /pdbtype:sept !ENDIF @@ -1156,6 +1156,14 @@ SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File +SOURCE=..\..\..\Windows\SystemInfo.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\SystemInfo.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Windows\TimeUtils.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/UI/GUI/StdAfx.h b/CPP/7zip/UI/GUI/StdAfx.h index 64290769..1918c8c4 100644 --- a/CPP/7zip/UI/GUI/StdAfx.h +++ b/CPP/7zip/UI/GUI/StdAfx.h @@ -11,9 +11,9 @@ // #include "../../../Common/MyWindows.h" -// #include <commctrl.h> +// #include <CommCtrl.h> // #include <ShlObj.h> -// #include <shlwapi.h> +// #include <Shlwapi.h> // #define printf(x) NO_PRINTF_(x) // #define sprintf(x) NO_SPRINTF_(x) diff --git a/CPP/7zip/UI/GUI/UpdateGUI.cpp b/CPP/7zip/UI/GUI/UpdateGUI.cpp index 2e738d3a..af07e550 100644 --- a/CPP/7zip/UI/GUI/UpdateGUI.cpp +++ b/CPP/7zip/UI/GUI/UpdateGUI.cpp @@ -56,9 +56,9 @@ HRESULT CThreadUpdating::ProcessVirt() ei, UpdateCallbackGUI, UpdateCallbackGUI, needSetPath); FinalMessage.ErrorMessage.Message = ei.Message.Ptr(); ErrorPaths = ei.FileNames; - if (ei.SystemError != S_OK && ei.SystemError != E_FAIL && ei.SystemError != E_ABORT) - return ei.SystemError; - return res; + if (res != S_OK) + return res; + return HRESULT_FROM_WIN32(ei.SystemError); } static void AddProp(CObjectVector<CProperty> &properties, const char *name, const UString &value) diff --git a/CPP/7zip/UI/GUI/makefile b/CPP/7zip/UI/GUI/makefile index f8416022..255c4f24 100644 --- a/CPP/7zip/UI/GUI/makefile +++ b/CPP/7zip/UI/GUI/makefile @@ -55,6 +55,7 @@ WIN_OBJS = \ $O\Shell.obj \ $O\Synchronization.obj \ $O\System.obj \ + $O\SystemInfo.obj \ $O\TimeUtils.obj \ $O\Window.obj \ diff --git a/CPP/7zip/cmpl_clang.mak b/CPP/7zip/cmpl_clang.mak new file mode 100644 index 00000000..e62e1e62 --- /dev/null +++ b/CPP/7zip/cmpl_clang.mak @@ -0,0 +1,3 @@ +include ../../var_clang.mak +include ../../warn_clang.mak +include makefile.gcc diff --git a/CPP/7zip/cmpl_clang_arm64.mak b/CPP/7zip/cmpl_clang_arm64.mak new file mode 100644 index 00000000..3f6b02bf --- /dev/null +++ b/CPP/7zip/cmpl_clang_arm64.mak @@ -0,0 +1,3 @@ +include ../../var_clang_arm64.mak +include ../../warn_clang.mak +include makefile.gcc diff --git a/CPP/7zip/cmpl_clang_x64.mak b/CPP/7zip/cmpl_clang_x64.mak new file mode 100644 index 00000000..b61e2af6 --- /dev/null +++ b/CPP/7zip/cmpl_clang_x64.mak @@ -0,0 +1,3 @@ +include ../../var_clang_x64.mak +include ../../warn_clang.mak +include makefile.gcc diff --git a/CPP/7zip/cmpl_clang_x86.mak b/CPP/7zip/cmpl_clang_x86.mak new file mode 100644 index 00000000..0e5cb76c --- /dev/null +++ b/CPP/7zip/cmpl_clang_x86.mak @@ -0,0 +1,3 @@ +include ../../var_clang_x86.mak +include ../../warn_clang.mak +include makefile.gcc diff --git a/CPP/7zip/cmpl_gcc.mak b/CPP/7zip/cmpl_gcc.mak new file mode 100644 index 00000000..7a1aef2e --- /dev/null +++ b/CPP/7zip/cmpl_gcc.mak @@ -0,0 +1,3 @@ +include ../../var_gcc.mak +include ../../warn_gcc.mak +include makefile.gcc diff --git a/CPP/7zip/cmpl_gcc_arm64.mak b/CPP/7zip/cmpl_gcc_arm64.mak new file mode 100644 index 00000000..53a85844 --- /dev/null +++ b/CPP/7zip/cmpl_gcc_arm64.mak @@ -0,0 +1,3 @@ +include ../../var_gcc_arm64.mak +include ../../warn_gcc.mak +include makefile.gcc diff --git a/CPP/7zip/cmpl_gcc_x64.mak b/CPP/7zip/cmpl_gcc_x64.mak new file mode 100644 index 00000000..500c30e4 --- /dev/null +++ b/CPP/7zip/cmpl_gcc_x64.mak @@ -0,0 +1,3 @@ +include ../../var_gcc_x64.mak +include ../../warn_gcc.mak +include makefile.gcc diff --git a/CPP/7zip/cmpl_gcc_x86.mak b/CPP/7zip/cmpl_gcc_x86.mak new file mode 100644 index 00000000..e7687070 --- /dev/null +++ b/CPP/7zip/cmpl_gcc_x86.mak @@ -0,0 +1,3 @@ +include ../../var_gcc_x86.mak +include ../../warn_gcc.mak +include makefile.gcc diff --git a/CPP/7zip/cmpl_mac_arm64.mak b/CPP/7zip/cmpl_mac_arm64.mak new file mode 100644 index 00000000..941028e9 --- /dev/null +++ b/CPP/7zip/cmpl_mac_arm64.mak @@ -0,0 +1,3 @@ +include ../../var_mac_arm64.mak +include ../../warn_clang_mac.mak +include makefile.gcc diff --git a/CPP/7zip/cmpl_mac_x64.mak b/CPP/7zip/cmpl_mac_x64.mak new file mode 100644 index 00000000..d3aa0396 --- /dev/null +++ b/CPP/7zip/cmpl_mac_x64.mak @@ -0,0 +1,3 @@ +include ../../var_mac_x64.mak +include ../../warn_clang_mac.mak +include makefile.gcc diff --git a/CPP/7zip/var_clang.mak b/CPP/7zip/var_clang.mak new file mode 100644 index 00000000..a6df26e7 --- /dev/null +++ b/CPP/7zip/var_clang.mak @@ -0,0 +1,11 @@ +PLATFORM= +O=b/c +IS_X64= +IS_X86= +IS_ARM64= +CROSS_COMPILE= +MY_ARCH= +USE_ASM= +CC=$(CROSS_COMPILE)clang +CXX=$(CROSS_COMPILE)clang++ +USE_CLANG=1 diff --git a/CPP/7zip/var_clang_arm64.mak b/CPP/7zip/var_clang_arm64.mak new file mode 100644 index 00000000..4b354096 --- /dev/null +++ b/CPP/7zip/var_clang_arm64.mak @@ -0,0 +1,11 @@ +PLATFORM=arm64 +O=b/c_$(PLATFORM) +IS_X64= +IS_X86= +IS_ARM64=1 +CROSS_COMPILE= +MY_ARCH= +USE_ASM=1 +CC=$(CROSS_COMPILE)clang +CXX=$(CROSS_COMPILE)clang++ +USE_CLANG=1 diff --git a/CPP/7zip/var_clang_x64.mak b/CPP/7zip/var_clang_x64.mak new file mode 100644 index 00000000..fefed51c --- /dev/null +++ b/CPP/7zip/var_clang_x64.mak @@ -0,0 +1,12 @@ +PLATFORM=x64 +O=b/c_$(PLATFORM) +IS_X64=1 +IS_X86= +IS_ARM64= +CROSS_COMPILE= +MY_ARCH= +USE_ASM=1 +CC=$(CROSS_COMPILE)clang +CXX=$(CROSS_COMPILE)clang++ +USE_CLANG=1 + diff --git a/CPP/7zip/var_clang_x86.mak b/CPP/7zip/var_clang_x86.mak new file mode 100644 index 00000000..5f3c2d9c --- /dev/null +++ b/CPP/7zip/var_clang_x86.mak @@ -0,0 +1,12 @@ +PLATFORM=x86 +O=b/c_$(PLATFORM) +IS_X64= +IS_X86=1 +IS_ARM64= +CROSS_COMPILE= +MY_ARCH=-m32 +USE_ASM=1 +CC=$(CROSS_COMPILE)clang +CXX=$(CROSS_COMPILE)clang++ +USE_CLANG=1 + diff --git a/CPP/7zip/var_gcc.mak b/CPP/7zip/var_gcc.mak new file mode 100644 index 00000000..664491cf --- /dev/null +++ b/CPP/7zip/var_gcc.mak @@ -0,0 +1,12 @@ +PLATFORM= +O=b/g +IS_X64= +IS_X86= +IS_ARM64= +CROSS_COMPILE= +MY_ARCH= +USE_ASM= +CC=$(CROSS_COMPILE)gcc +CXX=$(CROSS_COMPILE)g++ + +# -march=armv8-a+crc+crypto diff --git a/CPP/7zip/var_gcc_arm64.mak b/CPP/7zip/var_gcc_arm64.mak new file mode 100644 index 00000000..4bbb687d --- /dev/null +++ b/CPP/7zip/var_gcc_arm64.mak @@ -0,0 +1,12 @@ +PLATFORM=arm64 +O=b/g_$(PLATFORM) +IS_X64= +IS_X86= +IS_ARM64=1 +CROSS_COMPILE= +MY_ARCH=-mtune=cortex-a53 +USE_ASM=1 +CC=$(CROSS_COMPILE)gcc +CXX=$(CROSS_COMPILE)g++ + +# -march=armv8-a+crc+crypto diff --git a/CPP/7zip/var_gcc_x64.mak b/CPP/7zip/var_gcc_x64.mak new file mode 100644 index 00000000..1acf604f --- /dev/null +++ b/CPP/7zip/var_gcc_x64.mak @@ -0,0 +1,10 @@ +PLATFORM=x64 +O=b/g_$(PLATFORM) +IS_X64=1 +IS_X86= +IS_ARM64= +CROSS_COMPILE= +MY_ARCH= +USE_ASM=1 +CC=$(CROSS_COMPILE)gcc +CXX=$(CROSS_COMPILE)g++ diff --git a/CPP/7zip/var_gcc_x86.mak b/CPP/7zip/var_gcc_x86.mak new file mode 100644 index 00000000..288bf94b --- /dev/null +++ b/CPP/7zip/var_gcc_x86.mak @@ -0,0 +1,11 @@ +PLATFORM=x86 +O=b/g_$(PLATFORM) +IS_X64= +IS_X86=1 +IS_ARM64= +CROSS_COMPILE= +MY_ARCH=-m32 +USE_ASM=1 +CC=$(CROSS_COMPILE)gcc +CXX=$(CROSS_COMPILE)g++ + diff --git a/CPP/7zip/var_mac_arm64.mak b/CPP/7zip/var_mac_arm64.mak new file mode 100644 index 00000000..adf5fa1d --- /dev/null +++ b/CPP/7zip/var_mac_arm64.mak @@ -0,0 +1,11 @@ +PLATFORM=arm64 +O=b/m_$(PLATFORM) +IS_X64= +IS_X86= +IS_ARM64=1 +CROSS_COMPILE= +MY_ARCH=-arch arm64 +USE_ASM=1 +CC=$(CROSS_COMPILE)clang +CXX=$(CROSS_COMPILE)clang++ +USE_CLANG=1 diff --git a/CPP/7zip/var_mac_x64.mak b/CPP/7zip/var_mac_x64.mak new file mode 100644 index 00000000..13d7aa7f --- /dev/null +++ b/CPP/7zip/var_mac_x64.mak @@ -0,0 +1,11 @@ +PLATFORM=x64 +O=b/m_$(PLATFORM) +IS_X64=1 +IS_X86= +IS_ARM64= +CROSS_COMPILE= +MY_ARCH=-arch x86_64 +USE_ASM= +CC=$(CROSS_COMPILE)clang +CXX=$(CROSS_COMPILE)clang++ +USE_CLANG=1 diff --git a/CPP/7zip/warn_clang.mak b/CPP/7zip/warn_clang.mak new file mode 100644 index 00000000..ed4f908f --- /dev/null +++ b/CPP/7zip/warn_clang.mak @@ -0,0 +1,37 @@ +CFLAGS_WARN_CLANG_3_8_UNIQ = \ + -Wno-reserved-id-macro \ + -Wno-old-style-cast \ + -Wno-c++11-long-long \ + -Wno-unused-macros \ + +CFLAGS_WARN_CLANG_3_8 = \ + $(CFLAGS_WARN_CLANG_3_8_UNIQ) \ + -Weverything \ + -Wno-extra-semi \ + -Wno-sign-conversion \ + -Wno-language-extension-token \ + -Wno-global-constructors \ + -Wno-non-virtual-dtor \ + -Wno-switch-enum \ + -Wno-covered-switch-default \ + -Wno-cast-qual \ + -Wno-padded \ + -Wno-exit-time-destructors \ + -Wno-weak-vtables \ + +CFLAGS_WARN_CLANG_12= $(CFLAGS_WARN_CLANG_3_8) \ + -Wno-extra-semi-stmt \ + -Wno-zero-as-null-pointer-constant \ + -Wno-deprecated-dynamic-exception-spec \ + -Wno-c++98-compat-pedantic \ + -Wno-atomic-implicit-seq-cst \ + -Wconversion \ + -Wno-sign-conversion \ + +CFLAGS_WARN_1 = \ + -Wno-deprecated-copy-dtor \ + + + + +CFLAGS_WARN = $(CFLAGS_WARN_CLANG_12) $(CFLAGS_WARN_1) diff --git a/CPP/7zip/warn_clang_mac.mak b/CPP/7zip/warn_clang_mac.mak new file mode 100644 index 00000000..41044a2c --- /dev/null +++ b/CPP/7zip/warn_clang_mac.mak @@ -0,0 +1,37 @@ +CFLAGS_WARN_CLANG_3_8_UNIQ = \ + -Wno-reserved-id-macro \ + -Wno-old-style-cast \ + -Wno-c++11-long-long \ + -Wno-unused-macros \ + +CFLAGS_WARN_CLANG_3_8 = \ + $(CFLAGS_WARN_CLANG_3_8_UNIQ) \ + -Weverything \ + -Wno-extra-semi \ + -Wno-sign-conversion \ + -Wno-language-extension-token \ + -Wno-global-constructors \ + -Wno-non-virtual-dtor \ + -Wno-switch-enum \ + -Wno-covered-switch-default \ + -Wno-cast-qual \ + -Wno-padded \ + -Wno-exit-time-destructors \ + -Wno-weak-vtables \ + +CFLAGS_WARN_CLANG_12= $(CFLAGS_WARN_CLANG_3_8) \ + -Wno-extra-semi-stmt \ + -Wno-zero-as-null-pointer-constant \ + -Wno-deprecated-dynamic-exception-spec \ + -Wno-c++98-compat-pedantic \ + -Wno-atomic-implicit-seq-cst \ + -Wconversion \ + -Wno-sign-conversion \ + +CFLAGS_WARN_MAC = \ + -Wno-poison-system-directories \ + -Wno-c++11-long-long \ + -Wno-atomic-implicit-seq-cst \ + + +CFLAGS_WARN = $(CFLAGS_WARN_CLANG_12) $(CFLAGS_WARN_MAC) diff --git a/CPP/7zip/warn_gcc.mak b/CPP/7zip/warn_gcc.mak new file mode 100644 index 00000000..5fb747dc --- /dev/null +++ b/CPP/7zip/warn_gcc.mak @@ -0,0 +1,53 @@ +CFLAGS_WARN_GCC_4_5 = \ + +CFLAGS_WARN_GCC_6 = \ + -Waddress \ + -Waggressive-loop-optimizations \ + -Wattributes \ + -Wbool-compare \ + -Wcast-align \ + -Wcomment \ + -Wdiv-by-zero \ + -Wduplicated-cond \ + -Wformat-contains-nul \ + -Winit-self \ + -Wint-to-pointer-cast \ + -Wunused \ + -Wunused-macros \ + +# -Wno-strict-aliasing + +CFLAGS_WARN_GCC_9 = \ + -Waddress \ + -Waddress-of-packed-member \ + -Waggressive-loop-optimizations \ + -Wattributes \ + -Wbool-compare \ + -Wbool-operation \ + -Wcast-align \ + -Wcast-align=strict \ + -Wcomment \ + -Wdangling-else \ + -Wdiv-by-zero \ + -Wduplicated-branches \ + -Wduplicated-cond \ + -Wformat-contains-nul \ + -Wimplicit-fallthrough=5 \ + -Winit-self \ + -Wint-in-bool-context \ + -Wint-to-pointer-cast \ + -Wunused \ + -Wunused-macros \ + -Wconversion \ + +# -Wno-sign-conversion \ + +CFLAGS_WARN_GCC_PPMD_UNALIGNED = \ + -Wno-strict-aliasing \ + + +CFLAGS_WARN = $(CFLAGS_WARN_GCC_9) \ + +# $(CFLAGS_WARN_GCC_PPMD_UNALIGNED) + +
\ No newline at end of file diff --git a/CPP/Build.mak b/CPP/Build.mak index f53286b1..1ef676e0 100644 --- a/CPP/Build.mak +++ b/CPP/Build.mak @@ -12,17 +12,23 @@ O=o !ENDIF !ENDIF +!IF "$(CC)" != "clang-cl" # CFLAGS = $(CFLAGS) -FAsc -Fa$O/asm/ +!ENDIF !IF "$(PLATFORM)" == "x64" -MY_ML = ml64 -Dx64 -WX +MY_ML = ml64 -WX +#-Dx64 !ELSEIF "$(PLATFORM)" == "arm" MY_ML = armasm -WX !ELSE MY_ML = ml -WX +# -DABI_CDECL !ENDIF +# MY_ML = "$(MY_ML) -Fl$O\asm\ + !IFDEF UNDER_CE RFLAGS = $(RFLAGS) -dUNDER_CE @@ -47,6 +53,34 @@ COMPL_ASM = $(MY_ML) -c -Fo$O/ $** CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -W4 -WX -EHsc -Gy -GR- -GF +!IF "$(CC)" == "clang-cl" + +CFLAGS = $(CFLAGS) \ + -Werror \ + -Wextra \ + -Wall \ + -Weverything \ + -Wno-extra-semi-stmt \ + -Wno-extra-semi \ + -Wno-zero-as-null-pointer-constant \ + -Wno-sign-conversion \ + -Wno-old-style-cast \ + -Wno-reserved-id-macro \ + -Wno-deprecated-dynamic-exception-spec \ + -Wno-language-extension-token \ + -Wno-global-constructors \ + -Wno-non-virtual-dtor \ + -Wno-deprecated-copy-dtor \ + -Wno-exit-time-destructors \ + -Wno-switch-enum \ + -Wno-covered-switch-default \ + -Wno-nonportable-system-include-path \ + -Wno-c++98-compat-pedantic \ + -Wno-cast-qual \ + -Wc++11-extensions \ + +!ENDIF + !IFDEF MY_DYNAMIC_LINK CFLAGS = $(CFLAGS) -MD !ELSE @@ -55,10 +89,15 @@ CFLAGS = $(CFLAGS) -MT !ENDIF !ENDIF + +CFLAGS = $(CFLAGS_COMMON) $(CFLAGS) + !IFNDEF OLD_COMPILER CFLAGS = $(CFLAGS) -GS- -Zc:forScope -Zc:wchar_t !IFNDEF UNDER_CE -CFLAGS = $(CFLAGS) -MP2 +!IF "$(CC)" != "clang-cl" +CFLAGS = $(CFLAGS) -MP4 +!ENDIF !IFNDEF PLATFORM # CFLAGS = $(CFLAGS) -arch:IA32 !ENDIF @@ -134,6 +173,11 @@ CCOMPL_USE = $(CC) $(CFLAGS_C_ALL) -Yu"Precomp.h" -Fp$O/a.pch $** CCOMPL = $(CC) $(CFLAGS_C_ALL) $** CCOMPLB = $(CC) $(CFLAGS_C_ALL) $< +!IF "$(CC)" == "clang-cl" +COMPL = $(COMPL) -FI StdAfx.h +COMPLB = $(COMPLB) -FI StdAfx.h +CCOMPL_USE = $(CCOMPL_USE) -FI Precomp.h +!ENDIF all: $(PROGPATH) diff --git a/CPP/Common/CRC.cpp b/CPP/Common/CRC.cpp index 9a9f81fb..c6b7d5e4 100644 --- a/CPP/Common/CRC.cpp +++ b/CPP/Common/CRC.cpp @@ -4,4 +4,4 @@ #include "../../C/7zCrc.h" -struct CCRCTableInit { CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit; +static struct CCRCTableInit { CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit; diff --git a/CPP/Common/C_FileIO.cpp b/CPP/Common/C_FileIO.cpp index 7c629390..4bd3fadc 100644 --- a/CPP/Common/C_FileIO.cpp +++ b/CPP/Common/C_FileIO.cpp @@ -1,92 +1,3 @@ // Common/C_FileIO.cpp -#include "C_FileIO.h" - -#include <fcntl.h> -#ifdef _WIN32 -#include <io.h> -#else -#include <unistd.h> -#endif - -namespace NC { -namespace NFile { -namespace NIO { - -bool CFileBase::OpenBinary(const char *name, int flags) -{ - #ifdef O_BINARY - flags |= O_BINARY; - #endif - Close(); - _handle = ::open(name, flags, 0666); - return _handle != -1; -} - -bool CFileBase::Close() -{ - if (_handle == -1) - return true; - if (close(_handle) != 0) - return false; - _handle = -1; - return true; -} - -bool CFileBase::GetLength(UInt64 &length) const -{ - off_t curPos = Seek(0, SEEK_CUR); - off_t lengthTemp = Seek(0, SEEK_END); - Seek(curPos, SEEK_SET); - length = (UInt64)lengthTemp; - return true; -} - -off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const -{ - return ::lseek(_handle, distanceToMove, moveMethod); -} - -///////////////////////// -// CInFile - -bool CInFile::Open(const char *name) -{ - return CFileBase::OpenBinary(name, O_RDONLY); -} - -bool CInFile::OpenShared(const char *name, bool) -{ - return Open(name); -} - -ssize_t CInFile::Read(void *data, size_t size) -{ - return read(_handle, data, size); -} - -///////////////////////// -// COutFile - -bool COutFile::Create(const char *name, bool createAlways) -{ - if (createAlways) - { - Close(); - _handle = ::creat(name, 0666); - return _handle != -1; - } - return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY); -} - -bool COutFile::Open(const char *name, DWORD creationDisposition) -{ - return Create(name, false); -} - -ssize_t COutFile::Write(const void *data, size_t size) -{ - return write(_handle, data, size); -} - -}}} +#include "StdAfx.h" diff --git a/CPP/Common/C_FileIO.h b/CPP/Common/C_FileIO.h index ff4ec162..6818558b 100644 --- a/CPP/Common/C_FileIO.h +++ b/CPP/Common/C_FileIO.h @@ -3,51 +3,4 @@ #ifndef __COMMON_C_FILEIO_H #define __COMMON_C_FILEIO_H -#include <stdio.h> -#include <sys/types.h> - -#include "MyTypes.h" -#include "MyWindows.h" - -#ifdef _WIN32 -#ifdef _MSC_VER -typedef size_t ssize_t; -#endif -#endif - -namespace NC { -namespace NFile { -namespace NIO { - -class CFileBase -{ -protected: - int _handle; - bool OpenBinary(const char *name, int flags); -public: - CFileBase(): _handle(-1) {}; - ~CFileBase() { Close(); } - bool Close(); - bool GetLength(UInt64 &length) const; - off_t Seek(off_t distanceToMove, int moveMethod) const; -}; - -class CInFile: public CFileBase -{ -public: - bool Open(const char *name); - bool OpenShared(const char *name, bool shareForWrite); - ssize_t Read(void *data, size_t size); -}; - -class COutFile: public CFileBase -{ -public: - bool Create(const char *name, bool createAlways); - bool Open(const char *name, DWORD creationDisposition); - ssize_t Write(const void *data, size_t size); -}; - -}}} - #endif diff --git a/CPP/Common/CommandLineParser.cpp b/CPP/Common/CommandLineParser.cpp index 145f3435..465e0fde 100644 --- a/CPP/Common/CommandLineParser.cpp +++ b/CPP/Common/CommandLineParser.cpp @@ -84,7 +84,7 @@ bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms, unsi if (IsString1PrefixedByString2_NoCase_Ascii((const wchar_t *)s + pos, key)) { switchIndex = i; - maxLen = switchLen; + maxLen = (int)switchLen; } } @@ -94,7 +94,7 @@ bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms, unsi return false; } - pos += maxLen; + pos += (unsigned)maxLen; CSwitchResult &sw = _switches[switchIndex]; const CSwitchForm &form = switchForms[switchIndex]; @@ -107,7 +107,7 @@ bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms, unsi sw.ThereIs = true; - int rem = s.Len() - pos; + const unsigned rem = s.Len() - pos; if (rem < form.MinLen) { ErrorMessage = "Too short switch:"; @@ -178,7 +178,7 @@ bool CParser::ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, { if (s.IsEqualTo(kStopSwitchParsing)) { - StopSwitchIndex = NonSwitchStrings.Size(); + StopSwitchIndex = (int)NonSwitchStrings.Size(); continue; } if (!s.IsEmpty() && IsItSwitchChar(s[0])) diff --git a/CPP/Common/CommandLineParser.h b/CPP/Common/CommandLineParser.h index 1dbdd4ea..fbd4fa58 100644 --- a/CPP/Common/CommandLineParser.h +++ b/CPP/Common/CommandLineParser.h @@ -38,7 +38,7 @@ struct CSwitchResult int PostCharIndex; UStringVector PostStrings; - CSwitchResult(): ThereIs(false) {}; + CSwitchResult(): ThereIs(false) {} }; class CParser diff --git a/CPP/Common/Common.h b/CPP/Common/Common.h index 5430a92d..8dac613c 100644 --- a/CPP/Common/Common.h +++ b/CPP/Common/Common.h @@ -40,4 +40,18 @@ you can change this h file or h files included in this file. #define MY_ARRAY_NEW(p, T, size) p = new T[size]; #endif +#if (defined(__GNUC__) && (__GNUC__ >= 8)) + #define MY_ATTR_NORETURN __attribute__((noreturn)) +#elif (defined(__clang__) && (__clang_major__ >= 3)) + #if __has_feature(cxx_attributes) + #define MY_ATTR_NORETURN [[noreturn]] + #else + #define MY_ATTR_NORETURN __attribute__ ((noreturn)) + #endif +#elif (defined(_MSC_VER) && (_MSC_VER >= 1900)) + #define MY_ATTR_NORETURN [[noreturn]] +#else + #define MY_ATTR_NORETURN +#endif + #endif diff --git a/CPP/Common/CrcReg.cpp b/CPP/Common/CrcReg.cpp index 4b662f52..fdbba77b 100644 --- a/CPP/Common/CrcReg.cpp +++ b/CPP/Common/CrcReg.cpp @@ -16,8 +16,10 @@ typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table); extern CRC_FUNC g_CrcUpdate; -extern CRC_FUNC g_CrcUpdateT8; extern CRC_FUNC g_CrcUpdateT4; +extern CRC_FUNC g_CrcUpdateT8; +extern CRC_FUNC g_CrcUpdateT0_32; +extern CRC_FUNC g_CrcUpdateT0_64; EXTERN_C_END @@ -41,25 +43,20 @@ public: bool CCrcHasher::SetFunctions(UInt32 tSize) { - _updateFunc = g_CrcUpdate; + CRC_FUNC f = NULL; + if (tSize == 0) f = g_CrcUpdate; + else if (tSize == 1) f = CrcUpdateT1; + else if (tSize == 4) f = g_CrcUpdateT4; + else if (tSize == 8) f = g_CrcUpdateT8; + else if (tSize == 32) f = g_CrcUpdateT0_32; + else if (tSize == 64) f = g_CrcUpdateT0_64; - if (tSize == 1) - _updateFunc = CrcUpdateT1; - else if (tSize == 4) + if (!f) { - if (g_CrcUpdateT4) - _updateFunc = g_CrcUpdateT4; - else - return false; + _updateFunc = g_CrcUpdate; + return false; } - else if (tSize == 8) - { - if (g_CrcUpdateT8) - _updateFunc = g_CrcUpdateT8; - else - return false; - } - + _updateFunc = f; return true; } diff --git a/CPP/Common/Defs.h b/CPP/Common/Defs.h index 1fbd78bd..9adb88cf 100644 --- a/CPP/Common/Defs.h +++ b/CPP/Common/Defs.h @@ -10,6 +10,7 @@ template <class T> inline int MyCompare(T a, T b) { return a == b ? 0 : (a < b ? -1 : 1); } inline int BoolToInt(bool v) { return (v ? 1 : 0); } +inline unsigned BoolToUInt(bool v) { return (v ? (unsigned)1 : (unsigned)0); } inline bool IntToBool(int v) { return (v != 0); } #endif diff --git a/CPP/Common/DynLimBuf.cpp b/CPP/Common/DynLimBuf.cpp index 1d1d99dc..79141040 100644 --- a/CPP/Common/DynLimBuf.cpp +++ b/CPP/Common/DynLimBuf.cpp @@ -51,7 +51,7 @@ CDynLimBuf & CDynLimBuf::operator+=(char c) throw() _chars = newBuf; _size = n; } - _chars[_pos++] = c; + _chars[_pos++] = (Byte)c; return *this; } diff --git a/CPP/Common/DynamicBuffer.h b/CPP/Common/DynamicBuffer.h index 44e3df7f..f6f6b157 100644 --- a/CPP/Common/DynamicBuffer.h +++ b/CPP/Common/DynamicBuffer.h @@ -54,7 +54,7 @@ public: memcpy(GetCurPtrAndGrow(size), data, size * sizeof(T)); } - const size_t GetPos() const { return _pos; } + size_t GetPos() const { return _pos; } // void Empty() { _pos = 0; } }; diff --git a/CPP/Common/IntToString.cpp b/CPP/Common/IntToString.cpp index 05b1c148..c87643c8 100644 --- a/CPP/Common/IntToString.cpp +++ b/CPP/Common/IntToString.cpp @@ -10,20 +10,20 @@ unsigned char temp[tempSize]; unsigned i = 0; \ while (val >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(val % 10)); val /= 10; } \ *s++ = (charType)('0' + (unsigned)val); \ - while (i != 0) { i--; *s++ = temp[i]; } \ - *s = 0; + while (i != 0) { i--; *s++ = (charType)temp[i]; } \ + *s = 0; \ + return s; -void ConvertUInt32ToString(UInt32 val, char *s) throw() +char * ConvertUInt32ToString(UInt32 val, char *s) throw() { CONVERT_INT_TO_STR(char, 16); } -void ConvertUInt64ToString(UInt64 val, char *s) throw() +char * ConvertUInt64ToString(UInt64 val, char *s) throw() { if (val <= (UInt32)0xFFFFFFFF) { - ConvertUInt32ToString((UInt32)val, s); - return; + return ConvertUInt32ToString((UInt32)val, s); } CONVERT_INT_TO_STR(char, 24); } @@ -119,17 +119,16 @@ void ConvertUInt32ToHex8Digits(UInt32 val, wchar_t *s) } */ -void ConvertUInt32ToString(UInt32 val, wchar_t *s) throw() +wchar_t * ConvertUInt32ToString(UInt32 val, wchar_t *s) throw() { CONVERT_INT_TO_STR(wchar_t, 16); } -void ConvertUInt64ToString(UInt64 val, wchar_t *s) throw() +wchar_t * ConvertUInt64ToString(UInt64 val, wchar_t *s) throw() { if (val <= (UInt32)0xFFFFFFFF) { - ConvertUInt32ToString((UInt32)val, s); - return; + return ConvertUInt32ToString((UInt32)val, s); } CONVERT_INT_TO_STR(wchar_t, 24); } @@ -141,7 +140,7 @@ void ConvertInt64ToString(Int64 val, char *s) throw() *s++ = '-'; val = -val; } - ConvertUInt64ToString(val, s); + ConvertUInt64ToString((UInt64)val, s); } void ConvertInt64ToString(Int64 val, wchar_t *s) throw() @@ -151,7 +150,7 @@ void ConvertInt64ToString(Int64 val, wchar_t *s) throw() *s++ = L'-'; val = -val; } - ConvertUInt64ToString(val, s); + ConvertUInt64ToString((UInt64)val, s); } diff --git a/CPP/Common/IntToString.h b/CPP/Common/IntToString.h index d4110d1d..d0a96ef1 100644 --- a/CPP/Common/IntToString.h +++ b/CPP/Common/IntToString.h @@ -5,11 +5,13 @@ #include "MyTypes.h" -void ConvertUInt32ToString(UInt32 value, char *s) throw(); -void ConvertUInt64ToString(UInt64 value, char *s) throw(); +// return: the pointer to the "terminating" null character after written characters -void ConvertUInt32ToString(UInt32 value, wchar_t *s) throw(); -void ConvertUInt64ToString(UInt64 value, wchar_t *s) throw(); +char * ConvertUInt32ToString(UInt32 value, char *s) throw(); +char * ConvertUInt64ToString(UInt64 value, char *s) throw(); + +wchar_t * ConvertUInt32ToString(UInt32 value, wchar_t *s) throw(); +wchar_t * ConvertUInt64ToString(UInt64 value, wchar_t *s) throw(); void ConvertUInt64ToOct(UInt64 value, char *s) throw(); diff --git a/CPP/Common/Lang.cpp b/CPP/Common/Lang.cpp index e959ba48..35d37525 100644 --- a/CPP/Common/Lang.cpp +++ b/CPP/Common/Lang.cpp @@ -31,7 +31,7 @@ bool CLang::OpenFromString(const AString &s2) for (const char *p = kLangSignature;; i++) { - Byte c = *p++; + Byte c = (Byte)(*p++); if (c == 0) break; if (s[i] != c) @@ -122,10 +122,10 @@ bool CLang::Open(CFSTR fileName, const char *id) return false; AString s; - unsigned len = (unsigned)length; + const unsigned len = (unsigned)length; char *p = s.GetBuf(len); - UInt32 processed; - if (!file.Read(p, len, processed)) + size_t processed; + if (!file.ReadFull(p, len, processed)) return false; file.Close(); if (len != processed) @@ -159,5 +159,5 @@ const wchar_t *CLang::Get(UInt32 id) const throw() int index = _ids.FindInSorted(id); if (index < 0) return NULL; - return _text + (size_t)_offsets[index]; + return _text + (size_t)_offsets[(unsigned)index]; } diff --git a/CPP/Common/ListFileUtils.cpp b/CPP/Common/ListFileUtils.cpp index edd37eb1..b361b378 100644 --- a/CPP/Common/ListFileUtils.cpp +++ b/CPP/Common/ListFileUtils.cpp @@ -4,14 +4,19 @@ #include "../../C/CpuArch.h" -#include "../Windows/FileIO.h" - #include "ListFileUtils.h" #include "MyBuffer.h" #include "StringConvert.h" #include "UTFConvert.h" -static const char kQuoteChar = '\"'; +#include "../Windows/FileIO.h" + +#define CSysInFile NWindows::NFile::NIO::CInFile +#define MY_GET_LAST_ERROR ::GetLastError() + + +#define kQuoteChar '\"' + static void AddName(UStringVector &strings, UString &s) { @@ -25,19 +30,37 @@ static void AddName(UStringVector &strings, UString &s) strings.Add(s); } + +static bool My_File_Read(CSysInFile &file, void *data, size_t size, DWORD &lastError) +{ + size_t processed; + if (!file.ReadFull(data, size, processed)) + { + lastError = MY_GET_LAST_ERROR; + return false; + } + if (processed != size) + { + lastError = 1; // error: size of listfile was changed + return false; + } + return true; +} + + bool ReadNamesFromListFile2(CFSTR fileName, UStringVector &strings, UINT codePage, DWORD &lastError) { lastError = 0; - NWindows::NFile::NIO::CInFile file; + CSysInFile file; if (!file.Open(fileName)) { - lastError = ::GetLastError(); + lastError = MY_GET_LAST_ERROR; return false; } UInt64 fileSize; if (!file.GetLength(fileSize)) { - lastError = ::GetLastError(); + lastError = MY_GET_LAST_ERROR; return false; } if (fileSize >= ((UInt32)1 << 31) - 32) @@ -48,16 +71,12 @@ bool ReadNamesFromListFile2(CFSTR fileName, UStringVector &strings, UINT codePag if ((fileSize & 1) != 0) return false; CByteArr buf((size_t)fileSize); - UInt32 processed; - if (!file.Read(buf, (UInt32)fileSize, processed)) - { - lastError = ::GetLastError(); - return false; - } - if (processed != fileSize) + + if (!My_File_Read(file, buf, (size_t)fileSize, lastError)) return false; + file.Close(); - unsigned num = (unsigned)fileSize / 2; + const unsigned num = (unsigned)fileSize / 2; wchar_t *p = u.GetBuf(num); if (codePage == MY__CP_UTF16) for (unsigned i = 0; i < num; i++) @@ -82,22 +101,21 @@ bool ReadNamesFromListFile2(CFSTR fileName, UStringVector &strings, UINT codePag { AString s; char *p = s.GetBuf((unsigned)fileSize); - UInt32 processed; - if (!file.Read(p, (UInt32)fileSize, processed)) - { - lastError = ::GetLastError(); - return false; - } - if (processed != fileSize) + + if (!My_File_Read(file, p, (size_t)fileSize, lastError)) return false; + file.Close(); - s.ReleaseBuf_CalcLen((unsigned)processed); - if (s.Len() != processed) + s.ReleaseBuf_CalcLen((unsigned)fileSize); + if (s.Len() != fileSize) return false; // #ifdef CP_UTF8 if (codePage == CP_UTF8) { + // we must check UTF8 here, if convert function doesn't check + if (!CheckUTF8_AString(s)) + return false; if (!ConvertUTF8ToUnicode(s, u)) return false; } diff --git a/CPP/Common/MyBuffer.h b/CPP/Common/MyBuffer.h index 5d4e3475..18ab6fa4 100644 --- a/CPP/Common/MyBuffer.h +++ b/CPP/Common/MyBuffer.h @@ -4,6 +4,7 @@ #define __COMMON_MY_BUFFER_H #include "Defs.h" +#include "MyTypes.h" /* 7-Zip now uses CBuffer only as CByteBuffer. So there is no need to use MY_ARRAY_NEW macro in CBuffer code. */ @@ -91,6 +92,12 @@ public: _size = newSize; } + void Wipe() + { + if (_size != 0) + memset(_items, 0, _size * sizeof(T)); + } + CBuffer& operator=(const CBuffer &buffer) { if (&buffer != this) @@ -127,6 +134,17 @@ bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2) typedef CBuffer<unsigned char> CByteBuffer; +class CByteBuffer_Wipe: public CByteBuffer +{ + CLASS_NO_COPY(CByteBuffer_Wipe) +public: + // CByteBuffer_Wipe(): CBuffer<unsigned char>() {} + CByteBuffer_Wipe(size_t size): CBuffer<unsigned char>(size) {} + ~CByteBuffer_Wipe() { Wipe(); } +}; + + + template <class T> class CObjArray { protected: diff --git a/CPP/Common/MyBuffer2.h b/CPP/Common/MyBuffer2.h index d61a72ef..de5ebbdd 100644 --- a/CPP/Common/MyBuffer2.h +++ b/CPP/Common/MyBuffer2.h @@ -57,6 +57,15 @@ public: ISzAlloc_Free(&g_AlignedAlloc, _data); } + CAlignedBuffer(size_t size): _size(0) + { + _data = NULL; + _data = (Byte *)ISzAlloc_Alloc(&g_AlignedAlloc, size); + if (!_data) + throw 1; + _size = size; + } + void Free() { ISzAlloc_Free(&g_AlignedAlloc, _data); diff --git a/CPP/Common/MyCom.h b/CPP/Common/MyCom.h index 031921d3..524f6efb 100644 --- a/CPP/Common/MyCom.h +++ b/CPP/Common/MyCom.h @@ -4,6 +4,7 @@ #define __MY_COM_H #include "MyWindows.h" +#include "MyTypes.h" #ifndef RINOK #define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; } @@ -81,7 +82,7 @@ inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr) class CMyComBSTR { BSTR m_str; - + CLASS_NO_COPY(CMyComBSTR) public: CMyComBSTR(): m_str(NULL) {} ~CMyComBSTR() { ::SysFreeString(m_str); } @@ -89,13 +90,23 @@ public: operator LPCOLESTR() const { return m_str; } // operator bool() const { return m_str != NULL; } // bool operator!() const { return m_str == NULL; } + + void Wipe_and_Free() + { + if (m_str) + { + memset(m_str, 0, ::SysStringLen(m_str) * sizeof(*m_str)); + Empty(); + } + } + private: // operator BSTR() const { return m_str; } CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); } // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } - CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } + // CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } /* CMyComBSTR(REFGUID src) @@ -107,6 +118,7 @@ private: } */ + /* CMyComBSTR& operator=(const CMyComBSTR& src) { if (m_str != src.m_str) @@ -117,6 +129,7 @@ private: } return *this; } + */ CMyComBSTR& operator=(LPCOLESTR src) { @@ -158,6 +171,15 @@ private: }; +class CMyComBSTR_Wipe: public CMyComBSTR +{ + CLASS_NO_COPY(CMyComBSTR_Wipe) +public: + CMyComBSTR_Wipe(): CMyComBSTR() {} + ~CMyComBSTR_Wipe() { Wipe_and_Free(); } +}; + + /* If CMyUnknownImp doesn't use virtual destructor, the code size is smaller. @@ -168,17 +190,24 @@ private: virtual ~class_1(); In that case, class_1::Release() calls correct destructor of class_2. - Also you can use virtual ~CMyUnknownImp(), if you want to disable warning + We use virtual ~CMyUnknownImp() to disable warning "class has virtual functions, but destructor is not virtual". + + also we can use virtual ~IUnknown() {} in MyWindows.h */ class CMyUnknownImp { + CLASS_NO_COPY(CMyUnknownImp) public: ULONG __m_RefCount; CMyUnknownImp(): __m_RefCount(0) {} - // virtual + #ifdef _WIN32 + #if defined(__GNUC__) || defined(__clang__) + virtual // to disable GCC/CLANG varnings + #endif + #endif ~CMyUnknownImp() {} }; diff --git a/CPP/Common/MyGuidDef.h b/CPP/Common/MyGuidDef.h index 68745870..38aad6e6 100644 --- a/CPP/Common/MyGuidDef.h +++ b/CPP/Common/MyGuidDef.h @@ -18,6 +18,9 @@ typedef struct { #define REFGUID const GUID * #endif +// typedef GUID IID; +typedef GUID CLSID; + #define REFCLSID REFGUID #define REFIID REFGUID diff --git a/CPP/Common/MyInitGuid.h b/CPP/Common/MyInitGuid.h index 279fba5d..04d77e21 100644 --- a/CPP/Common/MyInitGuid.h +++ b/CPP/Common/MyInitGuid.h @@ -19,13 +19,17 @@ Also we need IID_IUnknown that is initialized in some file for linking: Other: we define IID_IUnknown in this file */ +#ifdef __clang__ + #pragma clang diagnostic ignored "-Wmissing-variable-declarations" +#endif + #ifdef _WIN32 #ifdef UNDER_CE #include <basetyps.h> #endif -#include <initguid.h> +#include <InitGuid.h> #ifdef UNDER_CE DEFINE_GUID(IID_IUnknown, diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp index e2ec8a68..821c9b37 100644 --- a/CPP/Common/MyString.cpp +++ b/CPP/Common/MyString.cpp @@ -237,11 +237,25 @@ bool UString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw() } } +bool StringsAreEqual_Ascii(const char *u, const char *a) throw() +{ + for (;;) + { + char c = *a; + if (c != *u) + return false; + if (c == 0) + return true; + a++; + u++; + } +} + bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw() { for (;;) { - unsigned char c = *a; + unsigned char c = (unsigned char)*a; if (c != *u) return false; if (c == 0) @@ -632,9 +646,8 @@ AString &AString::operator+=(const AString &s) void AString::Add_UInt32(UInt32 v) { - char sz[16]; - ConvertUInt32ToString(v, sz); - (*this) += sz; + Grow(10); + _len = (unsigned)(ConvertUInt32ToString(v, _chars + _len) - _chars); } void AString::SetFrom(const char *s, unsigned len) // no check @@ -835,7 +848,7 @@ void AString::Replace(char oldChar, char newChar) throw() char *chars = _chars; while ((unsigned)pos < _len) { - pos = Find(oldChar, pos); + pos = Find(oldChar, (unsigned)pos); if (pos < 0) break; chars[(unsigned)pos] = newChar; @@ -857,11 +870,11 @@ void AString::Replace(const AString &oldString, const AString &newString) int pos = 0; while ((unsigned)pos < _len) { - pos = Find(oldString, pos); + pos = Find(oldString, (unsigned)pos); if (pos < 0) break; - Delete(pos, oldLen); - Insert(pos, newString); + Delete((unsigned)pos, oldLen); + Insert((unsigned)pos, newString); pos += newLen; // number++; } @@ -1150,9 +1163,31 @@ void UString::SetFrom(const wchar_t *s, unsigned len) // no check _len = len; } -void UString::SetFromBstr(BSTR s) +void UString::SetFromBstr(LPCOLESTR s) { - unsigned len = ::SysStringLen(s); + unsigned len = ::SysStringLen((BSTR)(void *)(s)); + + /* + #if WCHAR_MAX > 0xffff + size_t num_wchars = 0; + for (size_t i = 0; i < len;) + { + wchar_t c = s[i++]; + if (c >= 0xd800 && c < 0xdc00 && i + 1 != len) + { + wchar_t c2 = s[i]; + if (c2 >= 0xdc00 && c2 < 0x10000) + { + c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); + i++; + } + } + num_wchars++; + } + len = num_wchars; + #endif + */ + if (len > _limit) { wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); @@ -1161,8 +1196,33 @@ void UString::SetFromBstr(BSTR s) _limit = len; } _len = len; + + /* + #if WCHAR_MAX > 0xffff + + wchar_t *chars = _chars; + for (size_t i = 0; i <= len; i++) + { + wchar_t c = *s++; + if (c >= 0xd800 && c < 0xdc00 && i + 1 != len) + { + wchar_t c2 = *s; + if (c2 >= 0xdc00 && c2 < 0x10000) + { + s++; + c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); + } + } + chars[i] = c; + } + + #else + */ + // if (s) wmemcpy(_chars, s, len + 1); + + // #endif } UString &UString::operator=(const char *s) @@ -1229,9 +1289,8 @@ UString &UString::operator+=(const char *s) void UString::Add_UInt32(UInt32 v) { - char sz[16]; - ConvertUInt32ToString(v, sz); - (*this) += sz; + Grow(10); + _len = (unsigned)(ConvertUInt32ToString(v, _chars + _len) - _chars); } @@ -1341,7 +1400,7 @@ void UString::InsertAtFront(wchar_t c) } /* -void UString::Insert(unsigned index, wchar_t c) +void UString::Insert_wchar_t(unsigned index, wchar_t c) { InsertSpace(index, 1); _chars[index] = c; @@ -1409,7 +1468,7 @@ void UString::Replace(wchar_t oldChar, wchar_t newChar) throw() wchar_t *chars = _chars; while ((unsigned)pos < _len) { - pos = Find(oldChar, pos); + pos = Find(oldChar, (unsigned)pos); if (pos < 0) break; chars[(unsigned)pos] = newChar; @@ -1431,11 +1490,11 @@ void UString::Replace(const UString &oldString, const UString &newString) int pos = 0; while ((unsigned)pos < _len) { - pos = Find(oldString, pos); + pos = Find(oldString, (unsigned)pos); if (pos < 0) break; - Delete(pos, oldLen); - Insert(pos, newString); + Delete((unsigned)pos, oldLen); + Insert((unsigned)pos, newString); pos += newLen; // number++; } @@ -1609,6 +1668,8 @@ int MyStringCompareNoCase(const char *s1, const char *s2) } */ +#if !defined(USE_UNICODE_FSTRING) || !defined(_UNICODE) + static inline UINT GetCurrentCodePage() { #if defined(UNDER_CE) || !defined(_WIN32) @@ -1618,6 +1679,8 @@ static inline UINT GetCurrentCodePage() #endif } +#endif + #ifdef USE_UNICODE_FSTRING #ifndef _UNICODE @@ -1637,9 +1700,9 @@ FString fas2fs(const AString &s) return MultiByteToUnicodeString(s, GetCurrentCodePage()); } -#endif +#endif // _UNICODE -#else +#else // USE_UNICODE_FSTRING UString fs2us(const FChar *s) { @@ -1656,4 +1719,4 @@ FString us2fs(const wchar_t *s) return UnicodeStringToMultiByte(s, GetCurrentCodePage()); } -#endif +#endif // USE_UNICODE_FSTRING diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h index 40de52cd..c242d923 100644 --- a/CPP/Common/MyString.h +++ b/CPP/Common/MyString.h @@ -159,7 +159,7 @@ inline wchar_t MyCharUpper(wchar_t c) throw() return (wchar_t)MyCharUpper_WIN(c); #endif #else - return (wchar_t)towupper(c); + return (wchar_t)towupper((wint_t)c); #endif } @@ -207,6 +207,7 @@ int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw(); // ---------- ASCII ---------- // char values in ASCII strings must be less then 128 +bool StringsAreEqual_Ascii(const char *u, const char *a) throw(); bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw(); bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw(); bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw(); @@ -231,7 +232,7 @@ bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw(); cls &operator=(const t *); \ cls &operator+=(t); \ cls &operator+=(const t *); \ - FORBID_STRING_OPS_2(cls, t); \ + FORBID_STRING_OPS_2(cls, t) \ /* cls &operator+(t); \ @@ -266,7 +267,7 @@ class AString AString(const AString &s, char c); // it's for String + char AString(const char *s1, unsigned num1, const char *s2, unsigned num2); - friend AString operator+(const AString &s, char c) { return AString(s, c); } ; + friend AString operator+(const AString &s, char c) { return AString(s, c); } // friend AString operator+(char c, const AString &s); // is not supported friend AString operator+(const AString &s1, const AString &s2); @@ -300,6 +301,7 @@ public: void Empty() { _len = 0; _chars[0] = 0; } operator const char *() const { return _chars; } + char *Ptr_non_const() const { return _chars; } const char *Ptr() const { return _chars; } const char *Ptr(unsigned pos) const { return _chars + pos; } const char *RightPtr(unsigned num) const { return _chars + _len - num; } @@ -438,8 +440,30 @@ public: _chars[index] = 0; } } + + void Wipe_and_Empty() + { + if (_chars) + { + memset(_chars, 0, (_limit + 1) * sizeof(*_chars)); + _len = 0; + } + } +}; + + +class AString_Wipe: public AString +{ + CLASS_NO_COPY(AString_Wipe) +public: + AString_Wipe(): AString() {} + // AString_Wipe(const AString &s): AString(s) {} + // AString_Wipe &operator=(const AString &s) { AString::operator=(s); return *this; } + // AString_Wipe &operator=(const char *s) { AString::operator=(s); return *this; } + ~AString_Wipe() { Wipe_and_Empty(); } }; + bool operator<(const AString &s1, const AString &s2); bool operator>(const AString &s1, const AString &s2); @@ -500,7 +524,7 @@ class UString UString(const UString &s, wchar_t c); // it's for String + char UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2); - friend UString operator+(const UString &s, wchar_t c) { return UString(s, c); } ; + friend UString operator+(const UString &s, wchar_t c) { return UString(s, c); } // friend UString operator+(wchar_t c, const UString &s); // is not supported friend UString operator+(const UString &s1, const UString &s2); @@ -539,6 +563,7 @@ public: void Empty() { _len = 0; _chars[0] = 0; } operator const wchar_t *() const { return _chars; } + wchar_t *Ptr_non_const() const { return _chars; } const wchar_t *Ptr() const { return _chars; } const wchar_t *Ptr(unsigned pos) const { return _chars + pos; } const wchar_t *RightPtr(unsigned num) const { return _chars + _len - num; } @@ -578,7 +603,7 @@ public: UString &operator=(const wchar_t *s); UString &operator=(const UString &s); void SetFrom(const wchar_t *s, unsigned len); // no check - void SetFromBstr(BSTR s); + void SetFromBstr(LPCOLESTR s); UString &operator=(const char *s); UString &operator=(const AString &s) { return operator=(s.Ptr()); } @@ -659,7 +684,7 @@ public: } void InsertAtFront(wchar_t c); - // void Insert(unsigned index, wchar_t c); + // void Insert_wchar_t(unsigned index, wchar_t c); void Insert(unsigned index, const wchar_t *s); void Insert(unsigned index, const UString &s); @@ -680,8 +705,30 @@ public: _chars[index] = 0; } } + + void Wipe_and_Empty() + { + if (_chars) + { + memset(_chars, 0, (_limit + 1) * sizeof(*_chars)); + _len = 0; + } + } +}; + + +class UString_Wipe: public UString +{ + CLASS_NO_COPY(UString_Wipe) +public: + UString_Wipe(): UString() {} + // UString_Wipe(const UString &s): UString(s) {} + // UString_Wipe &operator=(const UString &s) { UString::operator=(s); return *this; } + // UString_Wipe &operator=(const wchar_t *s) { UString::operator=(s); return *this; } + ~UString_Wipe() { Wipe_and_Empty(); } }; + bool operator<(const UString &s1, const UString &s2); bool operator>(const UString &s1, const UString &s2); @@ -866,3 +913,20 @@ typedef const FChar *CFSTR; typedef CObjectVector<FString> FStringVector; #endif + + + +#if defined(_WIN32) + // #include <wchar.h> + // WCHAR_MAX is defined as ((wchar_t)-1) + #define _WCHART_IS_16BIT 1 +#elif (defined(WCHAR_MAX) && (WCHAR_MAX <= 0xffff)) \ + || (defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ == 2)) + #define _WCHART_IS_16BIT 1 +#endif + +#if WCHAR_PATH_SEPARATOR == L'\\' +// WSL scheme +#define WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT ((wchar_t)((unsigned)(0xF000) + (unsigned)'\\')) +// #define WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT '_' +#endif diff --git a/CPP/Common/MyTypes.h b/CPP/Common/MyTypes.h index 75806f37..2b1acce2 100644 --- a/CPP/Common/MyTypes.h +++ b/CPP/Common/MyTypes.h @@ -32,4 +32,15 @@ struct CBoolPair cls(const cls &); \ cls &operator=(const cls &); +class CUncopyable +{ +protected: + CUncopyable() {} // allow constructor + // ~CUncopyable() {} +CLASS_NO_COPY(CUncopyable) +}; + +#define MY_UNCOPYABLE :private CUncopyable +// #define MY_UNCOPYABLE + #endif diff --git a/CPP/Common/MyVector.h b/CPP/Common/MyVector.h index 61dabbd1..c8512342 100644 --- a/CPP/Common/MyVector.h +++ b/CPP/Common/MyVector.h @@ -35,7 +35,7 @@ class CRecordVector public: - CRecordVector(): _items(0), _size(0), _capacity(0) {} + CRecordVector(): _items(NULL), _size(0), _capacity(0) {} CRecordVector(const CRecordVector &v): _items(0), _size(0), _capacity(0) { @@ -257,7 +257,7 @@ public: unsigned mid = (left + right) / 2; const T midVal = (*this)[mid]; if (item == midVal) - return mid; + return (int)mid; if (item < midVal) right = mid; else @@ -274,7 +274,7 @@ public: const T& midVal = (*this)[mid]; int comp = item.Compare(midVal); if (comp == 0) - return mid; + return (int)mid; if (comp < 0) right = mid; else @@ -428,7 +428,7 @@ public: // void Reserve(unsigned newCapacity) { _v.Reserve(newCapacity); } void ClearAndReserve(unsigned newCapacity) { Clear(); _v.ClearAndReserve(newCapacity); } - CObjectVector() {}; + CObjectVector() {} CObjectVector(const CObjectVector &v) { unsigned size = v.Size(); @@ -568,7 +568,7 @@ public: const T& midVal = (*this)[mid]; int comp = item.Compare(midVal); if (comp == 0) - return mid; + return (int)mid; if (comp < 0) right = mid; else @@ -624,9 +624,9 @@ public: { _v.Sort(compare, param); } static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */) - { return (*(*((const T **)a1))).Compare(*(*((const T **)a2))); } + { return (*(*((const T *const *)a1))).Compare(*(*((const T *const *)a2))); } - void Sort() { _v.Sort(CompareObjectItems, 0); } + void Sort() { _v.Sort(CompareObjectItems, NULL); } }; #define FOR_VECTOR(_i_, _v_) for (unsigned _i_ = 0; _i_ < (_v_).Size(); _i_++) diff --git a/CPP/Common/MyWindows.cpp b/CPP/Common/MyWindows.cpp index 463c77c4..88f312fb 100644 --- a/CPP/Common/MyWindows.cpp +++ b/CPP/Common/MyWindows.cpp @@ -5,6 +5,10 @@ #ifndef _WIN32 #include <stdlib.h> +#include <time.h> +#ifdef __GNUC__ +#include <sys/time.h> +#endif #include "MyWindows.h" @@ -38,11 +42,11 @@ BSTR SysAllocStringByteLen(LPCSTR s, UINT len) /* Original SysAllocStringByteLen in Win32 maybe fills only unaligned null OLECHAR at the end. We provide also aligned null OLECHAR at the end. */ - if (len >= (k_BstrSize_Max - sizeof(OLECHAR) - sizeof(OLECHAR) - sizeof(CBstrSizeType))) + if (len >= (k_BstrSize_Max - (UINT)sizeof(OLECHAR) - (UINT)sizeof(OLECHAR) - (UINT)sizeof(CBstrSizeType))) return NULL; - UINT size = (len + sizeof(OLECHAR) + sizeof(OLECHAR) - 1) & ~(sizeof(OLECHAR) - 1); - void *p = AllocateForBSTR(size + sizeof(CBstrSizeType)); + UINT size = (len + (UINT)sizeof(OLECHAR) + (UINT)sizeof(OLECHAR) - 1) & ~((UINT)sizeof(OLECHAR) - 1); + void *p = AllocateForBSTR(size + (UINT)sizeof(CBstrSizeType)); if (!p) return NULL; *(CBstrSizeType *)p = (CBstrSizeType)len; @@ -56,11 +60,11 @@ BSTR SysAllocStringByteLen(LPCSTR s, UINT len) BSTR SysAllocStringLen(const OLECHAR *s, UINT len) { - if (len >= (k_BstrSize_Max - sizeof(OLECHAR) - sizeof(CBstrSizeType)) / sizeof(OLECHAR)) + if (len >= (k_BstrSize_Max - (UINT)sizeof(OLECHAR) - (UINT)sizeof(CBstrSizeType)) / (UINT)sizeof(OLECHAR)) return NULL; - UINT size = len * sizeof(OLECHAR); - void *p = AllocateForBSTR(size + sizeof(CBstrSizeType) + sizeof(OLECHAR)); + UINT size = len * (UINT)sizeof(OLECHAR); + void *p = AllocateForBSTR(size + (UINT)sizeof(CBstrSizeType) + (UINT)sizeof(OLECHAR)); if (!p) return NULL; *(CBstrSizeType *)p = (CBstrSizeType)size; @@ -98,7 +102,7 @@ UINT SysStringLen(BSTR bstr) { if (!bstr) return 0; - return *((CBstrSizeType *)bstr - 1) / sizeof(OLECHAR); + return *((CBstrSizeType *)bstr - 1) / (UINT)sizeof(OLECHAR); } @@ -139,7 +143,150 @@ LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2) DWORD GetLastError() { - return 0; + return (DWORD)errno; +} + +void SetLastError(DWORD dw) +{ + errno = (int)dw; +} + + +static LONG TIME_GetBias() +{ + time_t utc = time(NULL); + struct tm *ptm = localtime(&utc); + int localdaylight = ptm->tm_isdst; /* daylight for local timezone */ + ptm = gmtime(&utc); + ptm->tm_isdst = localdaylight; /* use local daylight, not that of Greenwich */ + LONG bias = (int)(mktime(ptm)-utc); + return bias; +} + +#define TICKS_PER_SEC 10000000 +/* +#define SECS_PER_DAY (24 * 60 * 60) +#define SECS_1601_TO_1970 ((369 * 365 + 89) * (UInt64)SECS_PER_DAY) +#define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKS_PER_SEC) +*/ + +#define GET_TIME_64(pft) ((pft)->dwLowDateTime | ((UInt64)(pft)->dwHighDateTime << 32)) + +#define SET_FILETIME(ft, v64) \ + (ft)->dwLowDateTime = (DWORD)v64; \ + (ft)->dwHighDateTime = (DWORD)(v64 >> 32); + + +BOOL WINAPI FileTimeToLocalFileTime(const FILETIME *fileTime, FILETIME *localFileTime) +{ + UInt64 v = GET_TIME_64(fileTime); + v = (UInt64)((Int64)v - (Int64)TIME_GetBias() * TICKS_PER_SEC); + SET_FILETIME(localFileTime, v); + return TRUE; +} + +BOOL WINAPI LocalFileTimeToFileTime(const FILETIME *localFileTime, FILETIME *fileTime) +{ + UInt64 v = GET_TIME_64(localFileTime); + v = (UInt64)((Int64)v + (Int64)TIME_GetBias() * TICKS_PER_SEC); + SET_FILETIME(fileTime, v); + return TRUE; +} + +/* +VOID WINAPI GetSystemTimeAsFileTime(FILETIME *ft) +{ + UInt64 t = 0; + timeval tv; + if (gettimeofday(&tv, NULL) == 0) + { + t = tv.tv_sec * (UInt64)TICKS_PER_SEC + TICKS_1601_TO_1970; + t += tv.tv_usec * 10; + } + SET_FILETIME(ft, t); +} +*/ + +DWORD WINAPI GetTickCount(VOID) +{ + #ifndef _WIN32 + // gettimeofday() doesn't work in some MINGWs by unknown reason + timeval tv; + if (gettimeofday(&tv, NULL) == 0) + { + // tv_sec and tv_usec are (long) + return (DWORD)((UInt64)(Int64)tv.tv_sec * (UInt64)1000 + (UInt64)(Int64)tv.tv_usec / 1000); + } + #endif + return (DWORD)time(NULL) * 1000; +} + + +#define PERIOD_4 (4 * 365 + 1) +#define PERIOD_100 (PERIOD_4 * 25 - 1) +#define PERIOD_400 (PERIOD_100 * 4 + 1) + +BOOL WINAPI FileTimeToSystemTime(const FILETIME *ft, SYSTEMTIME *st) +{ + UInt32 v; + UInt64 v64 = GET_TIME_64(ft); + v64 /= 10000; + st->wMilliseconds = (WORD)(v64 % 1000); v64 /= 1000; + st->wSecond = (WORD)(v64 % 60); v64 /= 60; + st->wMinute = (WORD)(v64 % 60); v64 /= 60; + v = (UInt32)v64; + st->wHour = (WORD)(v % 24); v /= 24; + + // 1601-01-01 was Monday + st->wDayOfWeek = (WORD)((v + 1) % 7); + + UInt32 leaps, year, day, mon; + leaps = (3 * ((4 * v + (365 - 31 - 28) * 4 + 3) / PERIOD_400) + 3) / 4; + v += 28188 + leaps; + // leaps - the number of exceptions from PERIOD_4 rules starting from 1600-03-01 + // (1959 / 64) - converts day from 03-01 to month + year = (20 * v - 2442) / (5 * PERIOD_4); + day = v - (year * PERIOD_4) / 4; + mon = (64 * day) / 1959; + st->wDay = (WORD)(day - (1959 * mon) / 64); + mon -= 1; + year += 1524; + if (mon > 12) + { + mon -= 12; + year++; + } + st->wMonth = (WORD)mon; + st->wYear = (WORD)year; + + /* + unsigned year, mon; + unsigned char ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + unsigned t; + + year = (WORD)(1601 + v / PERIOD_400 * 400); + v %= PERIOD_400; + + t = v / PERIOD_100; if (t == 4) t = 3; year += t * 100; v -= t * PERIOD_100; + t = v / PERIOD_4; if (t == 25) t = 24; year += t * 4; v -= t * PERIOD_4; + t = v / 365; if (t == 4) t = 3; year += t; v -= t * 365; + + st->wYear = (WORD)year; + + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) + ms[1] = 29; + for (mon = 0;; mon++) + { + unsigned d = ms[mon]; + if (v < d) + break; + v -= d; + } + st->wDay = (WORD)(v + 1); + st->wMonth = (WORD)(mon + 1); + */ + + return TRUE; } #endif diff --git a/CPP/Common/MyWindows.h b/CPP/Common/MyWindows.h index db3f35d8..0664a5e0 100644 --- a/CPP/Common/MyWindows.h +++ b/CPP/Common/MyWindows.h @@ -5,14 +5,14 @@ #ifdef _WIN32 -#include <windows.h> +#include <Windows.h> #ifdef UNDER_CE #undef VARIANT_TRUE #define VARIANT_TRUE ((VARIANT_BOOL)-1) #endif -#else +#else // _WIN32 #include <stddef.h> // for wchar_t #include <string.h> @@ -20,7 +20,9 @@ #include "MyGuidDef.h" +// WINAPI is __stdcall in Windows-MSVC in windef.h #define WINAPI +#define EXTERN_C MY_EXTERN_C typedef char CHAR; typedef unsigned char UCHAR; @@ -35,17 +37,12 @@ typedef unsigned short USHORT; typedef unsigned short WORD; typedef short VARIANT_BOOL; -typedef int INT; -typedef Int32 INT32; -typedef unsigned int UINT; -typedef UInt32 UINT32; -typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit -typedef UINT32 ULONG; - -#undef DWORD -typedef UINT32 DWORD; +#define LOWORD(l) ((WORD)((DWORD_PTR)(l) & 0xffff)) +#define HIWORD(l) ((WORD)((DWORD_PTR)(l) >> 16)) -typedef long BOOL; +// MS uses long for BOOL, but long is 32-bit in MS. So we use int. +// typedef long BOOL; +typedef int BOOL; #ifndef FALSE #define FALSE 0 @@ -53,7 +50,7 @@ typedef long BOOL; #endif // typedef size_t ULONG_PTR; -typedef size_t DWORD_PTR; +// typedef size_t DWORD_PTR; // typedef uintptr_t UINT_PTR; // typedef ptrdiff_t UINT_PTR; @@ -80,28 +77,33 @@ typedef struct _FILETIME } FILETIME; #define HRESULT LONG -#define FAILED(Status) ((HRESULT)(Status)<0) +#define SUCCEEDED(hr) ((HRESULT)(hr) >= 0) +#define FAILED(hr) ((HRESULT)(hr) < 0) typedef ULONG PROPID; typedef LONG SCODE; -#define ERROR_NEGATIVE_SEEK 131L #define S_OK ((HRESULT)0x00000000L) #define S_FALSE ((HRESULT)0x00000001L) -#define E_NOTIMPL ((HRESULT)0x80004001L) +#define E_NOTIMPL ((HRESULT)0x80004001L) #define E_NOINTERFACE ((HRESULT)0x80004002L) -#define E_ABORT ((HRESULT)0x80004004L) -#define E_FAIL ((HRESULT)0x80004005L) -#define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) -#define E_OUTOFMEMORY ((HRESULT)0x8007000EL) -#define E_INVALIDARG ((HRESULT)0x80070057L) +#define E_ABORT ((HRESULT)0x80004004L) +#define E_FAIL ((HRESULT)0x80004005L) +#define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) +#define CLASS_E_CLASSNOTAVAILABLE ((HRESULT)0x80040111L) + #ifdef _MSC_VER #define STDMETHODCALLTYPE __stdcall +#define STDAPICALLTYPE __stdcall #else +// do we need __export here? #define STDMETHODCALLTYPE +#define STDAPICALLTYPE #endif +#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE + #define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f #define STDMETHOD(f) STDMETHOD_(HRESULT, f) #define STDMETHODIMP_(type) type STDMETHODCALLTYPE @@ -120,9 +122,8 @@ struct IUnknown STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE; STDMETHOD_(ULONG, AddRef)() PURE; STDMETHOD_(ULONG, Release)() PURE; - #ifndef _WIN32 virtual ~IUnknown() {} - #endif + // We use virtual ~IUnknown() here for binary compatibility with 7z.so from p7zip }; typedef IUnknown *LPUNKNOWN; @@ -214,8 +215,14 @@ MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); MY_EXTERN_C UINT SysStringLen(BSTR bstr); MY_EXTERN_C DWORD GetLastError(); +MY_EXTERN_C void SetLastError(DWORD dwCode); MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); +MY_EXTERN_C DWORD GetCurrentThreadId(); +MY_EXTERN_C DWORD GetCurrentProcessId(); + +#define MAX_PATH 1024 + #define CP_ACP 0 #define CP_OEMCP 1 #define CP_UTF8 65001 @@ -227,5 +234,35 @@ typedef enum tagSTREAM_SEEK STREAM_SEEK_END = 2 } STREAM_SEEK; -#endif + + +typedef struct _SYSTEMTIME +{ + WORD wYear; + WORD wMonth; + WORD wDayOfWeek; + WORD wDay; + WORD wHour; + WORD wMinute; + WORD wSecond; + WORD wMilliseconds; +} SYSTEMTIME; + +BOOL WINAPI FileTimeToLocalFileTime(const FILETIME *fileTime, FILETIME *localFileTime); +BOOL WINAPI LocalFileTimeToFileTime(const FILETIME *localFileTime, FILETIME *fileTime); +BOOL WINAPI FileTimeToSystemTime(const FILETIME *fileTime, SYSTEMTIME *systemTime); +// VOID WINAPI GetSystemTimeAsFileTime(FILETIME *systemTimeAsFileTime); + +DWORD GetTickCount(); + + +#define CREATE_NEW 1 +#define CREATE_ALWAYS 2 +#define OPEN_EXISTING 3 +#define OPEN_ALWAYS 4 +#define TRUNCATE_EXISTING 5 + + +#endif // _WIN32 + #endif diff --git a/CPP/Common/MyXml.cpp b/CPP/Common/MyXml.cpp index f34a745e..e0145188 100644 --- a/CPP/Common/MyXml.cpp +++ b/CPP/Common/MyXml.cpp @@ -7,9 +7,9 @@ static bool IsValidChar(char c) { return - c >= 'a' && c <= 'z' || - c >= 'A' && c <= 'Z' || - c >= '0' && c <= '9' || + (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || c == '-'; } @@ -24,7 +24,7 @@ int CXmlItem::FindProp(const char *propName) const throw() { FOR_VECTOR (i, Props) if (Props[i].Name == propName) - return i; + return (int)i; return -1; } @@ -32,7 +32,7 @@ AString CXmlItem::GetPropVal(const char *propName) const { int index = FindProp(propName); if (index >= 0) - return Props[index].Value; + return Props[(unsigned)index].Value; return AString(); } @@ -45,7 +45,7 @@ int CXmlItem::FindSubTag(const char *tag) const throw() { FOR_VECTOR (i, SubItems) if (SubItems[i].IsTagged(tag)) - return i; + return (int)i; return -1; } @@ -75,7 +75,7 @@ AString CXmlItem::GetSubStringForTag(const char *tag) const { int index = FindSubTag(tag); if (index >= 0) - return SubItems[index].GetSubString(); + return SubItems[(unsigned)index].GetSubString(); return AString(); } diff --git a/CPP/Common/Sha1Prepare.cpp b/CPP/Common/Sha1Prepare.cpp new file mode 100644 index 00000000..2652f009 --- /dev/null +++ b/CPP/Common/Sha1Prepare.cpp @@ -0,0 +1,7 @@ +// Sha1Prepare.cpp + +#include "StdAfx.h" + +#include "../../C/Sha1.h" + +static struct CSha1Prepare { CSha1Prepare() { Sha1Prepare(); } } g_Sha1Prepare; diff --git a/CPP/Common/Sha1Reg.cpp b/CPP/Common/Sha1Reg.cpp index 1400c989..0cb2baf7 100644 --- a/CPP/Common/Sha1Reg.cpp +++ b/CPP/Common/Sha1Reg.cpp @@ -4,37 +4,67 @@ #include "../../C/Sha1.h" +#include "../Common/MyBuffer2.h" #include "../Common/MyCom.h" #include "../7zip/Common/RegisterCodec.h" class CSha1Hasher: public IHasher, + public ICompressSetCoderProperties, public CMyUnknownImp { - CSha1 _sha; + CAlignedBuffer _buf; Byte mtDummy[1 << 7]; + CSha1 *Sha() { return (CSha1 *)(void *)(Byte *)_buf; } public: - CSha1Hasher() { Sha1_Init(&_sha); } + CSha1Hasher(): + _buf(sizeof(CSha1)) + { + Sha1_SetFunction(Sha(), 0); + Sha1_InitState(Sha()); + } - MY_UNKNOWN_IMP1(IHasher) + MY_UNKNOWN_IMP2(IHasher, ICompressSetCoderProperties) INTERFACE_IHasher(;) + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); }; STDMETHODIMP_(void) CSha1Hasher::Init() throw() { - Sha1_Init(&_sha); + Sha1_InitState(Sha()); } STDMETHODIMP_(void) CSha1Hasher::Update(const void *data, UInt32 size) throw() { - Sha1_Update(&_sha, (const Byte *)data, size); + Sha1_Update(Sha(), (const Byte *)data, size); } STDMETHODIMP_(void) CSha1Hasher::Final(Byte *digest) throw() { - Sha1_Final(&_sha, digest); + Sha1_Final(Sha(), digest); +} + + +STDMETHODIMP CSha1Hasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) +{ + unsigned algo = 0; + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = coderProps[i]; + if (propIDs[i] == NCoderPropID::kDefaultProp) + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + if (prop.ulVal > 2) + return E_NOTIMPL; + algo = (unsigned)prop.ulVal; + } + } + if (!Sha1_SetFunction(Sha(), algo)) + return E_NOTIMPL; + return S_OK; } REGISTER_HASHER(CSha1Hasher, 0x201, "SHA1", SHA1_DIGEST_SIZE) diff --git a/CPP/Common/Sha256Prepare.cpp b/CPP/Common/Sha256Prepare.cpp new file mode 100644 index 00000000..1ec242b5 --- /dev/null +++ b/CPP/Common/Sha256Prepare.cpp @@ -0,0 +1,7 @@ +// Sha256Prepare.cpp + +#include "StdAfx.h" + +#include "../../C/Sha256.h" + +static struct CSha256Prepare { CSha256Prepare() { Sha256Prepare(); } } g_Sha256Prepare; diff --git a/CPP/Common/Sha256Reg.cpp b/CPP/Common/Sha256Reg.cpp index 66941699..5f3a35b0 100644 --- a/CPP/Common/Sha256Reg.cpp +++ b/CPP/Common/Sha256Reg.cpp @@ -4,37 +4,67 @@ #include "../../C/Sha256.h" +#include "../Common/MyBuffer2.h" #include "../Common/MyCom.h" #include "../7zip/Common/RegisterCodec.h" class CSha256Hasher: public IHasher, + public ICompressSetCoderProperties, public CMyUnknownImp { - CSha256 _sha; + CAlignedBuffer _buf; Byte mtDummy[1 << 7]; + CSha256 *Sha() { return (CSha256 *)(void *)(Byte *)_buf; } public: - CSha256Hasher() { Sha256_Init(&_sha); } + CSha256Hasher(): + _buf(sizeof(CSha256)) + { + Sha256_SetFunction(Sha(), 0); + Sha256_InitState(Sha()); + } - MY_UNKNOWN_IMP1(IHasher) + MY_UNKNOWN_IMP2(IHasher, ICompressSetCoderProperties) INTERFACE_IHasher(;) + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); }; STDMETHODIMP_(void) CSha256Hasher::Init() throw() { - Sha256_Init(&_sha); + Sha256_InitState(Sha()); } STDMETHODIMP_(void) CSha256Hasher::Update(const void *data, UInt32 size) throw() { - Sha256_Update(&_sha, (const Byte *)data, size); + Sha256_Update(Sha(), (const Byte *)data, size); } STDMETHODIMP_(void) CSha256Hasher::Final(Byte *digest) throw() { - Sha256_Final(&_sha, digest); + Sha256_Final(Sha(), digest); +} + + +STDMETHODIMP CSha256Hasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) +{ + unsigned algo = 0; + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = coderProps[i]; + if (propIDs[i] == NCoderPropID::kDefaultProp) + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + if (prop.ulVal > 2) + return E_NOTIMPL; + algo = (unsigned)prop.ulVal; + } + } + if (!Sha256_SetFunction(Sha(), algo)) + return E_NOTIMPL; + return S_OK; } REGISTER_HASHER(CSha256Hasher, 0xA, "SHA256", SHA256_DIGEST_SIZE) diff --git a/CPP/Common/StdInStream.cpp b/CPP/Common/StdInStream.cpp index 422a96e5..abad34b6 100644 --- a/CPP/Common/StdInStream.cpp +++ b/CPP/Common/StdInStream.cpp @@ -2,7 +2,9 @@ #include "StdAfx.h" +#ifdef _WIN32 #include <tchar.h> +#endif #include "StdInStream.h" #include "StringConvert.h" @@ -14,14 +16,18 @@ #define kFileOpenMode TEXT("r") -extern int g_CodePage; - CStdInStream g_StdIn(stdin); bool CStdInStream::Open(LPCTSTR fileName) throw() { Close(); - _stream = _tfopen(fileName, kFileOpenMode); + _stream = + #ifdef _WIN32 + _tfopen + #else + fopen + #endif + (fileName, kFileOpenMode); _streamIsOpen = (_stream != 0); return _streamIsOpen; } @@ -56,7 +62,7 @@ bool CStdInStream::ScanUStringUntilNewLine(UString &dest) dest.Empty(); AString s; bool res = ScanAStringUntilNewLine(s); - int codePage = g_CodePage; + int codePage = CodePage; if (codePage == -1) codePage = CP_OEMCP; if (codePage == CP_UTF8) diff --git a/CPP/Common/StdInStream.h b/CPP/Common/StdInStream.h index 698ebec1..71578eb4 100644 --- a/CPP/Common/StdInStream.h +++ b/CPP/Common/StdInStream.h @@ -13,8 +13,14 @@ class CStdInStream FILE *_stream; bool _streamIsOpen; public: - CStdInStream(): _stream(0), _streamIsOpen(false) {}; - CStdInStream(FILE *stream): _stream(stream), _streamIsOpen(false) {}; + int CodePage; + + CStdInStream(FILE *stream = NULL): + _stream(stream), + _streamIsOpen(false), + CodePage(-1) + {}; + ~CStdInStream() { Close(); } bool Open(LPCTSTR fileName) throw(); diff --git a/CPP/Common/StdOutStream.cpp b/CPP/Common/StdOutStream.cpp index 8236072d..40799e22 100644 --- a/CPP/Common/StdOutStream.cpp +++ b/CPP/Common/StdOutStream.cpp @@ -2,7 +2,9 @@ #include "StdAfx.h" +#ifdef _WIN32 #include <tchar.h> +#endif #include "IntToString.h" #include "StdOutStream.h" @@ -11,8 +13,6 @@ #define kFileOpenMode "wt" -extern int g_CodePage; - CStdOutStream g_StdOut(stdout); CStdOutStream g_StdErr(stderr); @@ -47,32 +47,27 @@ CStdOutStream & endl(CStdOutStream & outStream) throw() CStdOutStream & CStdOutStream::operator<<(const wchar_t *s) { - int codePage = g_CodePage; - if (codePage == -1) - codePage = CP_OEMCP; - AString dest; - if (codePage == CP_UTF8) - ConvertUnicodeToUTF8(s, dest); - else - UnicodeStringToMultiByte2(dest, s, (UINT)codePage); - return operator<<((const char *)dest); + AString temp; + UString s2(s); + PrintUString(s2, temp); + return *this; } -void StdOut_Convert_UString_to_AString(const UString &s, AString &temp) +void CStdOutStream::PrintUString(const UString &s, AString &temp) { - int codePage = g_CodePage; + Convert_UString_to_AString(s, temp); + *this << (const char *)temp; +} + +void CStdOutStream::Convert_UString_to_AString(const UString &src, AString &dest) +{ + int codePage = CodePage; if (codePage == -1) codePage = CP_OEMCP; if (codePage == CP_UTF8) - ConvertUnicodeToUTF8(s, temp); + ConvertUnicodeToUTF8(src, dest); else - UnicodeStringToMultiByte2(temp, s, (UINT)codePage); -} - -void CStdOutStream::PrintUString(const UString &s, AString &temp) -{ - StdOut_Convert_UString_to_AString(s, temp); - *this << (const char *)temp; + UnicodeStringToMultiByte2(dest, src, (UINT)codePage); } diff --git a/CPP/Common/StdOutStream.h b/CPP/Common/StdOutStream.h index 2e637e8f..93f1dfa4 100644 --- a/CPP/Common/StdOutStream.h +++ b/CPP/Common/StdOutStream.h @@ -14,9 +14,15 @@ class CStdOutStream bool _streamIsOpen; public: bool IsTerminalMode; + int CodePage; + + CStdOutStream(FILE *stream = 0): + _stream(stream), + _streamIsOpen(false), + IsTerminalMode(false), + CodePage(-1) + {}; - CStdOutStream(): _stream(0), _streamIsOpen(false), IsTerminalMode(false) {}; - CStdOutStream(FILE *stream): _stream(stream), _streamIsOpen(false) {}; ~CStdOutStream() { Close(); } // void AttachStdStream(FILE *stream) { _stream = stream; _streamIsOpen = false; } @@ -52,6 +58,7 @@ public: CStdOutStream & operator<<(const wchar_t *s); void PrintUString(const UString &s, AString &temp); + void Convert_UString_to_AString(const UString &src, AString &dest); void Normalize_UString__LF_Allowed(UString &s); void Normalize_UString(UString &s); @@ -66,6 +73,4 @@ CStdOutStream & endl(CStdOutStream & outStream) throw(); extern CStdOutStream g_StdOut; extern CStdOutStream g_StdErr; -void StdOut_Convert_UString_to_AString(const UString &s, AString &temp); - #endif diff --git a/CPP/Common/StringConvert.cpp b/CPP/Common/StringConvert.cpp index 2a73d688..c0bde0fa 100644 --- a/CPP/Common/StringConvert.cpp +++ b/CPP/Common/StringConvert.cpp @@ -5,9 +5,18 @@ #include "StringConvert.h" #ifndef _WIN32 +// #include <stdio.h> #include <stdlib.h> #endif +#if !defined(_WIN32) || defined(ENV_HAVE_LOCALE) +#include "UTFConvert.h" +#endif + +#ifdef ENV_HAVE_LOCALE +#include <locale.h> +#endif + static const char k_DefultChar = '_'; #ifdef _WIN32 @@ -71,7 +80,7 @@ void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage) d[i] = 0; dest.ReleaseBuf_SetLen(i); */ - unsigned len = MultiByteToWideChar(codePage, 0, src, src.Len(), NULL, 0); + unsigned len = (unsigned)MultiByteToWideChar(codePage, 0, src, (int)src.Len(), NULL, 0); if (len == 0) { if (GetLastError() != 0) @@ -79,7 +88,7 @@ void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage) } else { - len = MultiByteToWideChar(codePage, 0, src, src.Len(), dest.GetBuf(len), len); + len = (unsigned)MultiByteToWideChar(codePage, 0, src, (int)src.Len(), dest.GetBuf(len), (int)len); if (len == 0) throw 282228; dest.ReleaseBuf_SetEnd(len); @@ -175,7 +184,7 @@ static void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT co } */ - unsigned len = WideCharToMultiByte(codePage, 0, src, src.Len(), NULL, 0, NULL, NULL); + unsigned len = (unsigned)WideCharToMultiByte(codePage, 0, src, (int)src.Len(), NULL, 0, NULL, NULL); if (len == 0) { if (GetLastError() != 0) @@ -186,8 +195,8 @@ static void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT co BOOL defUsed = FALSE; bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7); // defaultChar = defaultChar; - len = WideCharToMultiByte(codePage, 0, src, src.Len(), - dest.GetBuf(len), len, + len = (unsigned)WideCharToMultiByte(codePage, 0, src, (int)src.Len(), + dest.GetBuf(len), (int)len, (isUtf ? NULL : &defaultChar), (isUtf ? NULL : &defUsed) ); @@ -213,23 +222,137 @@ AString SystemStringToOemString(const CSysString &src) #endif */ -#else +#else // _WIN32 + +// #include <stdio.h> +/* + if (wchar_t is 32-bit (#if WCHAR_MAX > 0xffff), + and utf-8 string contains big unicode character > 0xffff), + then we still use 16-bit surrogate pair in UString. + It simplifies another code where utf-16 encoding is used. + So we use surrogate-conversion code only in is file. +*/ + +/* + mbstowcs() returns error if there is error in utf-8 stream, + mbstowcs() returns error if there is single surrogates point (d800-dfff) in utf-8 stream +*/ -void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT /* codePage */) +/* +static void MultiByteToUnicodeString2_Native(UString &dest, const AString &src) { dest.Empty(); if (src.IsEmpty()) return; - size_t limit = ((size_t)src.Len() + 1) * 2; + const size_t limit = ((size_t)src.Len() + 1) * 2; wchar_t *d = dest.GetBuf((unsigned)limit); - size_t len = mbstowcs(d, src, limit); + const size_t len = mbstowcs(d, src, limit); if (len != (size_t)-1) { dest.ReleaseBuf_SetEnd((unsigned)len); return; } + dest.ReleaseBuf_SetEnd(0); +} +*/ + +bool g_ForceToUTF8 = true; // false; + +void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage) +{ + dest.Empty(); + if (src.IsEmpty()) + return; + + if (codePage == CP_UTF8 || g_ForceToUTF8) + { + ConvertUTF8ToUnicode(src, dest); + return; + } + + const size_t limit = ((size_t)src.Len() + 1) * 2; + wchar_t *d = dest.GetBuf((unsigned)limit); + const size_t len = mbstowcs(d, src, limit); + if (len != (size_t)-1) + { + dest.ReleaseBuf_SetEnd((unsigned)len); + + #if WCHAR_MAX > 0xffff + d = dest.GetBuf(); + for (size_t i = 0;; i++) + { + // wchar_t c = dest[i]; + wchar_t c = d[i]; + if (c == 0) + break; + if (c >= 0x10000 && c < 0x110000) + { + /* + c -= 0x10000; + unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF); + dest.ReplaceOneCharAtPos(i, c0); + i++; + c = 0xdc00 + (c & 0x3FF); + dest.Insert_wchar_t(i, c); + */ + UString temp = d + i; + + for (size_t t = 0;; t++) + { + wchar_t w = temp[t]; + if (w == 0) + break; + if (i == limit) + break; // unexpected error + if (w >= 0x10000 && w < 0x110000) + { + if (i + 1 == limit) + break; // unexpected error + w -= 0x10000; + d[i++] = (unsigned)0xd800 + (((unsigned)w >> 10) & 0x3FF); + w = 0xdc00 + (w & 0x3FF); + } + d[i++] = w; + } + dest.ReleaseBuf_SetEnd((unsigned)i); + } + } + + #endif + + /* + printf("\nMultiByteToUnicodeString2 (%d) %s\n", (int)src.Len(), src.Ptr()); + printf("char: "); + for (unsigned i = 0; i < src.Len(); i++) + printf (" %02x", (int)(Byte)src[i]); + printf("\n"); + printf("\n-> (%d) %ls\n", (int)dest.Len(), dest.Ptr()); + printf("wchar_t: "); + for (unsigned i = 0; i < dest.Len(); i++) + { + printf (" %02x", (int)dest[i]); + } + printf("\n"); + */ + + return; + } + + /* if there is mbstowcs() error, we have two ways: + + 1) change 0x80+ characters to some character: '_' + in that case we lose data, but we have correct UString() + and that scheme can show errors to user in early stages, + when file converted back to mbs() cannot be found + + 2) transfer bad characters in some UTF-16 range. + it can be non-original Unicode character. + but later we still can restore original character. + */ + + // printf("\nmbstowcs ERROR !!!!!! s=%s\n", src.Ptr()); { unsigned i; const char *s = (const char *)src; @@ -238,6 +361,8 @@ void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT /* codePa Byte c = (Byte)s[i]; if (c == 0) break; + // we can use ascii compatibilty character '_' + // if (c > 0x7F) c = '_'; // we replace "bad: character d[i++] = (wchar_t)c; } d[i] = 0; @@ -245,43 +370,131 @@ void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT /* codePa } } -static void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT /* codePage */, char defaultChar, bool &defaultCharWasUsed) +static void UnicodeStringToMultiByte2_Native(AString &dest, const UString &src) { dest.Empty(); - defaultCharWasUsed = false; if (src.IsEmpty()) return; - size_t limit = ((size_t)src.Len() + 1) * 6; + const size_t limit = ((size_t)src.Len() + 1) * 6; char *d = dest.GetBuf((unsigned)limit); - size_t len = wcstombs(d, src, limit); + + const size_t len = wcstombs(d, src, limit); + if (len != (size_t)-1) { dest.ReleaseBuf_SetEnd((unsigned)len); return; } + dest.ReleaseBuf_SetEnd(0); +} + + +static void UnicodeStringToMultiByte2(AString &dest, const UString &src2, UINT codePage, char defaultChar, bool &defaultCharWasUsed) +{ + // if (codePage == 1234567) // for debug purposes + if (codePage == CP_UTF8 || g_ForceToUTF8) + { + defaultCharWasUsed = false; + ConvertUnicodeToUTF8(src2, dest); + return; + } + + UString src = src2; + #if WCHAR_MAX > 0xffff + { + src.Empty(); + for (unsigned i = 0; i < src2.Len();) + { + wchar_t c = src2[i]; + if (c >= 0xd800 && c < 0xdc00 && i + 1 != src2.Len()) + { + const wchar_t c2 = src2[i + 1]; + if (c2 >= 0xdc00 && c2 < 0x10000) + { + // printf("\nSurragate [%d]: %4x %4x -> ", i, (int)c, (int)c2); + c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); + // printf("%4x\n", (int)c); + i++; + } + } + src += c; + i++; + } + } + #endif + + dest.Empty(); + defaultCharWasUsed = false; + if (src.IsEmpty()) + return; + + const size_t len = wcstombs(NULL, src, 0); + + if (len != (size_t)-1) + { + const unsigned limit = ((unsigned)len); + if (limit == len) + { + char *d = dest.GetBuf(limit); + + /* + { + printf("\nwcstombs; len = %d %ls \n", (int)src.Len(), src.Ptr()); + for (unsigned i = 0; i < src.Len(); i++) + printf (" %02x", (int)src[i]); + printf("\n"); + printf("\ndest Limit = %d \n", limit); + } + */ + + const size_t len2 = wcstombs(d, src, len + 1); + + if (len2 != (size_t)-1 && len2 <= limit) + { + /* + printf("\nOK : destLen = %d : %s\n", (int)len, dest.Ptr()); + for (unsigned i = 0; i < len2; i++) + printf(" %02x", (int)(Byte)dest[i]); + printf("\n"); + */ + dest.ReleaseBuf_SetEnd((unsigned)len2); + return; + } + } + } { const wchar_t *s = (const wchar_t *)src; + char *d = dest.GetBuf(src.Len()); + unsigned i; for (i = 0;;) { wchar_t c = s[i]; if (c == 0) break; - if (c >= 0x100) + if (c >= + 0x100 + // 0x80 + ) { c = defaultChar; defaultCharWasUsed = true; } + d[i++] = (char)c; } d[i] = 0; dest.ReleaseBuf_SetLen(i); + /* + printf("\nUnicodeStringToMultiByte2; len = %d \n", (int)src.Len()); + printf("ERROR: %s\n", dest.Ptr()); + */ } } -#endif +#endif // _WIN32 UString MultiByteToUnicodeString(const AString &src, UINT codePage) @@ -317,3 +530,228 @@ AString UnicodeStringToMultiByte(const UString &src, UINT codePage) UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed); return dest; } + + + + + +#ifdef _WIN32 +#define U_to_A(a, b, c) UnicodeStringToMultiByte2 +// #define A_to_U(a, b, c) MultiByteToUnicodeString2 +#else +// void MultiByteToUnicodeString2_Native(UString &dest, const AString &src); +#define U_to_A(a, b, c) UnicodeStringToMultiByte2_Native(a, b) +// #define A_to_U(a, b, c) MultiByteToUnicodeString2_Native(a, b) +#endif + +#if !defined(_WIN32) || defined(ENV_HAVE_LOCALE) + +bool IsNativeUTF8() +{ + UString u; + AString a, a2; + // for (unsigned c = 0x80; c < (UInt32)0x10000; c += (c >> 9) + 1) + for (unsigned c = 0x80; c < (UInt32)0xD000; c += (c >> 2) + 1) + { + u.Empty(); + u += (wchar_t)c; + /* + if (Unicode_Is_There_Utf16SurrogateError(u)) + continue; + #ifndef _WIN32 + if (Unicode_Is_There_BmpEscape(u)) + continue; + #endif + */ + ConvertUnicodeToUTF8(u, a); + U_to_A(a2, u, CP_OEMCP); + if (a != a2) + return false; + } + return true; +} + +#endif + + +#ifdef ENV_HAVE_LOCALE + +const char *GetLocale(void) +{ + #ifdef ENV_HAVE_LOCALE + // printf("\n\nsetlocale(LC_CTYPE, NULL) : return : "); + const char *s = setlocale(LC_CTYPE, NULL); + if (!s) + { + // printf("[NULL]\n"); + s = "C"; + } + else + { + // ubuntu returns "C" after program start + // printf("\"%s\"\n", s); + } + return s; + #elif defined(LOCALE_IS_UTF8) + return "utf8"; + #else + return "C"; + #endif +} + +#ifdef _WIN32 + static void Set_ForceToUTF8(bool) {} +#else + static void Set_ForceToUTF8(bool val) { g_ForceToUTF8 = val; } +#endif + +static bool Is_Default_Basic_Locale(const char *locale) +{ + const AString a (locale); + if (a.IsEqualTo_Ascii_NoCase("") + || a.IsEqualTo_Ascii_NoCase("C") + || a.IsEqualTo_Ascii_NoCase("POSIX")) + return true; + return false; +} + +static bool Is_Default_Basic_Locale() +{ + return Is_Default_Basic_Locale(GetLocale()); +} + + +void MY_SetLocale() +{ + #ifdef ENV_HAVE_LOCALE + /* + { + const char *s = GetLocale(); + printf("\nGetLocale() : returned : \"%s\"\n", s); + } + */ + + unsigned start = 0; + // unsigned lim = 0; + unsigned lim = 3; + + /* + #define MY_SET_LOCALE_FLAGS__FROM_ENV 1 + #define MY_SET_LOCALE_FLAGS__TRY_UTF8 2 + + unsigned flags = + MY_SET_LOCALE_FLAGS__FROM_ENV | + MY_SET_LOCALE_FLAGS__TRY_UTF8 + + if (flags != 0) + { + if (flags & MY_SET_LOCALE_FLAGS__FROM_ENV) + lim = (flags & MY_SET_LOCALE_FLAGS__TRY_UTF8) ? 3 : 1; + else + { + start = 1; + lim = 2; + } + } + */ + + for (unsigned i = start; i < lim; i++) + { + /* + man7: "If locale is an empty string, "", each part of the locale that + should be modified is set according to the environment variables. + for glibc: glibc, first from the user's environment variables: + 1) the environment variable LC_ALL, + 2) environment variable with the same name as the category (see the + 3) the environment variable LANG + The locale "C" or "POSIX" is a portable locale; it exists on all conforming systems. + + for WIN32 : MSDN : + Sets the locale to the default, which is the user-default + ANSI code page obtained from the operating system. + The locale name is set to the value returned by GetUserDefaultLocaleName. + The code page is set to the value returned by GetACP + */ + const char *newLocale = ""; + + #ifdef __APPLE__ + + /* look also CFLocale + there is no C.UTF-8 in macos + macos has UTF-8 locale only with some language like en_US.UTF-8 + what is best way to set UTF-8 locale in macos? */ + if (i == 1) + newLocale = "en_US.UTF-8"; + + /* file open with non-utf8 sequencies return + #define EILSEQ 92 // "Illegal byte sequence" + */ +#else + // newLocale = "C"; + if (i == 1) + { + newLocale = "C.UTF-8"; // main UTF-8 locale in ubuntu + // newLocale = ".utf8"; // supported in new Windows 10 build 17134 (April 2018 Update), the Universal C Runtime + // newLocale = "en_US.utf8"; // supported by ubuntu ? + // newLocale = "en_US.UTF-8"; + /* setlocale() in ubuntu allows locales with minor chracter changes in strings + "en_US.UTF-8" / "en_US.utf8" */ + } + +#endif + + // printf("\nsetlocale(LC_ALL, \"%s\") : returned: ", newLocale); + + // const char *s = + setlocale(LC_ALL, newLocale); + + /* + if (!s) + printf("NULL: can't set locale"); + else + printf("\"%s\"\n", s); + */ + + // request curent locale of program + const char *locale = GetLocale(); + if (locale) + { + AString a (locale); + a.MakeLower_Ascii(); + // if (a.Find("utf") >= 0) + { + if (IsNativeUTF8()) + { + Set_ForceToUTF8(true); + return; + } + } + if (!Is_Default_Basic_Locale(locale)) + { + // if there is some non-default and non-utf locale, we want to use it + break; // comment it for debug + } + } + } + + if (IsNativeUTF8()) + { + Set_ForceToUTF8(true); + return; + } + + if (Is_Default_Basic_Locale()) + { + Set_ForceToUTF8(true); + return; + } + + Set_ForceToUTF8(false); + + #elif defined(LOCALE_IS_UTF8) + // assume LC_CTYPE="utf8" + #else + // assume LC_CTYPE="C" + #endif +} +#endif diff --git a/CPP/Common/StringConvert.h b/CPP/Common/StringConvert.h index 25fe503f..865c0254 100644 --- a/CPP/Common/StringConvert.h +++ b/CPP/Common/StringConvert.h @@ -85,4 +85,26 @@ inline AString GetOemString(const UString &u) AString SystemStringToOemString(const CSysString &src); #endif + +#ifdef _WIN32 +/* we don't need locale functions in Windows + but we can define ENV_HAVE_LOCALE here for debug purposes */ +// #define ENV_HAVE_LOCALE +#else +#define ENV_HAVE_LOCALE +#endif + +#ifdef ENV_HAVE_LOCALE +void MY_SetLocale(); +const char *GetLocale(void); +#endif + +#if !defined(_WIN32) || defined(ENV_HAVE_LOCALE) +bool IsNativeUTF8(); +#endif + +#ifndef _WIN32 +extern bool g_ForceToUTF8; +#endif + #endif diff --git a/CPP/Common/StringToInt.cpp b/CPP/Common/StringToInt.cpp index dfa5cc3b..839867a4 100644 --- a/CPP/Common/StringToInt.cpp +++ b/CPP/Common/StringToInt.cpp @@ -17,7 +17,7 @@ static const UInt64 k_UInt64_max = UINT64_CONST(0xFFFFFFFFFFFFFFFF); if (c < '0' || c > '9') { if (end) *end = s; return res; } \ if (res > (k_ ## uintType ## _max) / 10) return 0; \ res *= 10; \ - unsigned v = (c - '0'); \ + unsigned v = (unsigned)(c - '0'); \ if (res > (k_ ## uintType ## _max) - v) return 0; \ res += v; }} diff --git a/CPP/Common/UTFConvert.cpp b/CPP/Common/UTFConvert.cpp index b772164a..ac069dba 100644 --- a/CPP/Common/UTFConvert.cpp +++ b/CPP/Common/UTFConvert.cpp @@ -2,11 +2,17 @@ #include "StdAfx.h" +// #include <stdio.h> + #include "MyTypes.h" #include "UTFConvert.h" -#ifdef _WIN32 -#define _WCHART_IS_16BIT 1 + +#ifndef _WCHART_IS_16BIT +#ifndef __APPLE__ + // we define it if the system supports files with non-utf8 symbols: + #define _UTF8_RAW_NON_UTF8_SUPPORTED +#endif #endif /* @@ -18,78 +24,332 @@ 1 : 0xC0 : 11 : 2 : 0xE0 : 16 : Basic Multilingual Plane 3 : 0xF0 : 21 : Unicode space - 3 : 0xF8 : 26 : - 5 : 0xFC : 31 : UCS-4 + 4 : 0xF8 : 26 : + 5 : 0xFC : 31 : UCS-4 : wcstombs() in ubuntu is limited to that value 6 : 0xFE : 36 : We can use it, if we want to encode any 32-bit value 7 : 0xFF : */ #define _UTF8_START(n) (0x100 - (1 << (7 - (n)))) -#define _UTF8_HEAD_PARSE2(n) if (c < _UTF8_START((n) + 1)) { numBytes = (n); c -= _UTF8_START(n); } +#define _UTF8_HEAD_PARSE2(n) \ + if (c < _UTF8_START((n) + 1)) \ + { numBytes = (n); val -= _UTF8_START(n); } + +#ifndef _WCHART_IS_16BIT + +/* + if (wchar_t is 32-bit), we can support large points in long UTF-8 sequence, + when we convert wchar_t strings to UTF-8: + (_UTF8_NUM_TAIL_BYTES_MAX == 3) : (21-bits points) - Unicode + (_UTF8_NUM_TAIL_BYTES_MAX == 5) : (31-bits points) - UCS-4 + (_UTF8_NUM_TAIL_BYTES_MAX == 6) : (36-bit hack) +*/ + +#define _UTF8_NUM_TAIL_BYTES_MAX 5 +#endif +/* #define _UTF8_HEAD_PARSE \ + UInt32 val = c; \ _UTF8_HEAD_PARSE2(1) \ else _UTF8_HEAD_PARSE2(2) \ else _UTF8_HEAD_PARSE2(3) \ else _UTF8_HEAD_PARSE2(4) \ else _UTF8_HEAD_PARSE2(5) \ + #if _UTF8_NUM_TAIL_BYTES_MAX >= 6 + else _UTF8_HEAD_PARSE2(6) + #endif +*/ + +#define _UTF8_HEAD_PARSE_MAX_3_BYTES \ + UInt32 val = c; \ + _UTF8_HEAD_PARSE2(1) \ + else _UTF8_HEAD_PARSE2(2) \ + else { numBytes = 3; val -= _UTF8_START(3); } + + +#define _UTF8_RANGE(n) (((UInt32)1) << ((n) * 5 + 6)) + + +#define START_POINT_FOR_SURROGATE 0x10000 + + +/* we use 128 bytes block in 16-bit BMP-PLANE to encode non-UTF-8 Escapes + Also we can use additional HIGH-PLANE (we use 21-bit points above 0x1f0000) + to simplify internal intermediate conversion in Linux: + RAW-UTF-8 <-> internal wchar_t utf-16 strings <-> RAW-UTF-UTF-8 +*/ + + +#if defined(_WCHART_IS_16BIT) + +#define UTF_ESCAPE_PLANE 0 + +#else + +/* +we can place 128 ESCAPE chars to + ef 80 - ee be 80 (3-bytes utf-8) : similar to WSL + ef ff - ee bf bf + +1f ef 80 - f7 be be 80 (4-bytes utf-8) : last 4-bytes utf-8 plane (out of Unicode) +1f ef ff - f7 be bf bf (4-bytes utf-8) : last 4-bytes utf-8 plane (out of Unicode) +*/ + +// #define UTF_ESCAPE_PLANE_HIGH (0x1f << 16) +// #define UTF_ESCAPE_PLANE UTF_ESCAPE_PLANE_HIGH +#define UTF_ESCAPE_PLANE 0 + +/* + if (UTF_FLAG__FROM_UTF8__USE_ESCAPE is set) + { + if (UTF_ESCAPE_PLANE is UTF_ESCAPE_PLANE_HIGH) + { + we can restore any 8-bit Escape from ESCAPE-PLANE-21 plane. + But ESCAPE-PLANE-21 point cannot be stored to utf-16 (7z archive) + So we still need a way to extract 8-bit Escapes and BMP-Escapes-8 + from same BMP-Escapes-16 stored in 7z. + And if we want to restore any 8-bit from 7z archive, + we still must use UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT for (utf-8 -> utf-16) + Also we need additional Conversions to tranform from utf-16 to utf-16-With-Escapes-21 + } + else (UTF_ESCAPE_PLANE == 0) + { + we must convert original 3-bytes utf-8 BMP-Escape point to sequence + of 3 BMP-Escape-16 points with UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT + so we can extract original RAW-UTF-8 from UTFD-16 later. + } + } +*/ + +#endif + + + +#define UTF_ESCAPE_BASE 0xef00 + + +#ifdef UTF_ESCAPE_BASE +#define IS_ESCAPE_POINT(v, plane) (((v) & (UInt32)0xffffff80) == (plane) + UTF_ESCAPE_BASE + 0x80) +#endif + +#define IS_SURROGATE_POINT(v) (((v) & (UInt32)0xfffff800) == 0xd800) +#define IS_LOW_SURROGATE_POINT(v) (((v) & (UInt32)0xfffffC00) == 0xdc00) + + +#define _ERROR_UTF8_CHECK \ + { NonUtf = true; continue; } + +void CUtf8Check::Check_Buf(const char *src, size_t size) throw() +{ + Clear(); + // Byte maxByte = 0; + + for (;;) + { + if (size == 0) + break; + + const Byte c = (Byte)(*src++); + size--; + + if (c == 0) + { + ZeroChar = true; + continue; + } + + /* + if (c > maxByte) + maxByte = c; + */ + + if (c < 0x80) + continue; + + if (c < 0xc0 + 2)// it's limit for 0x140000 unicode codes : win32 compatibility + _ERROR_UTF8_CHECK + + unsigned numBytes; - // else _UTF8_HEAD_PARSE2(6) + UInt32 val = c; + _UTF8_HEAD_PARSE2(1) + else _UTF8_HEAD_PARSE2(2) + else _UTF8_HEAD_PARSE2(4) + else _UTF8_HEAD_PARSE2(5) + else + { + _ERROR_UTF8_CHECK + } + unsigned pos = 0; + do + { + if (pos == size) + break; + unsigned c2 = (Byte)src[pos]; + c2 -= 0x80; + if (c2 >= 0x40) + break; + val <<= 6; + val |= c2; + if (pos == 0) + if (val < (((unsigned)1 << 7) >> numBytes)) + break; + pos++; + } + while (--numBytes); + + if (numBytes != 0) + { + if (pos == size) + Truncated = true; + else + _ERROR_UTF8_CHECK + } + + #ifdef UTF_ESCAPE_BASE + if (IS_ESCAPE_POINT(val, 0)) + Escape = true; + #endif + + if (MaxHighPoint < val) + MaxHighPoint = val; + + if (IS_SURROGATE_POINT(val)) + SingleSurrogate = true; + + src += pos; + size -= pos; + } + + // MaxByte = maxByte; +} + +bool Check_UTF8_Buf(const char *src, size_t size, bool allowReduced) throw() +{ + CUtf8Check check; + check.Check_Buf(src, size); + return check.IsOK(allowReduced); +} + +/* +bool CheckUTF8_chars(const char *src, bool allowReduced) throw() +{ + CUtf8Check check; + check.CheckBuf(src, strlen(src)); + return check.IsOK(allowReduced); +} +*/ + +bool CheckUTF8_AString(const AString &s) throw() +{ + CUtf8Check check; + check.Check_AString(s); + return check.IsOK(); +} + + +/* bool CheckUTF8(const char *src, bool allowReduced) throw() { + // return Check_UTF8_Buf(src, strlen(src), allowReduced); + for (;;) { - Byte c = *src++; + const Byte c = (Byte)(*src++); if (c == 0) return true; if (c < 0x80) continue; - if (c < 0xC0) // (c < 0xC0 + 2) // if we support only optimal encoding chars + if (c < 0xC0 + 2 || c >= 0xf5) return false; unsigned numBytes; _UTF8_HEAD_PARSE else return false; - - UInt32 val = c; + unsigned pos = 0; + do { - Byte c2 = *src++; + Byte c2 = (Byte)(*src++); if (c2 < 0x80 || c2 >= 0xC0) return allowReduced && c2 == 0; val <<= 6; val |= (c2 - 0x80); + pos++; } while (--numBytes); - + + if (val < _UTF8_RANGE(pos - 1)) + return false; + if (val >= 0x110000) return false; } } +*/ + +// in case of UTF-8 error we have two ways: +// 21.01- : old : 0xfffd: REPLACEMENT CHARACTER : old version +// 21.02+ : new : 0xef00 + (c) : similar to WSL scheme for low symbols + +#define UTF_REPLACEMENT_CHAR 0xfffd + +#define UTF_ESCAPE(c) \ + ((flags & UTF_FLAG__FROM_UTF8__USE_ESCAPE) ? \ + UTF_ESCAPE_PLANE + UTF_ESCAPE_BASE + (c) : UTF_REPLACEMENT_CHAR) + +/* +#define _HARD_ERROR_UTF8 + { if (dest) dest[destPos] = (wchar_t)UTF_ESCAPE(c); \ + destPos++; ok = false; continue; } +*/ + +// we ignore utf errors, and don't change (ok) variable! + #define _ERROR_UTF8 \ - { if (dest) dest[destPos] = (wchar_t)0xFFFD; destPos++; ok = false; continue; } + { if (dest) dest[destPos] = (wchar_t)UTF_ESCAPE(c); \ + destPos++; continue; } -static bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, const char *srcLim) throw() +// we store UTF-16 in wchar_t strings. So we use surrogates for big unicode points: + +// for debug puposes only we can store UTF-32 in wchar_t: +// #define START_POINT_FOR_SURROGATE ((UInt32)0 - 1) + + +/* + WIN32 MultiByteToWideChar(CP_UTF8) emits 0xfffd point, if utf-8 error was found. + Ant it can emit single 0xfffd from 2 src bytes. + It doesn't emit single 0xfffd from 3-4 src bytes. + We can + 1) emit Escape point for each incorrect byte. So we can data recover later + 2) emit 0xfffd for each incorrect byte. + That scheme is similar to Escape scheme, but we emit 0xfffd + instead of each Escape point. + 3) emit single 0xfffd from 1-2 incorrect bytes, as WIN32 MultiByteToWideChar scheme +*/ + +static bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, const char *srcLim, unsigned flags) throw() { size_t destPos = 0; bool ok = true; for (;;) { - Byte c; if (src == srcLim) { *destLen = destPos; return ok; } - c = *src++; + + const Byte c = (Byte)(*src++); if (c < 0x80) { @@ -98,68 +358,127 @@ static bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, const destPos++; continue; } - if (c < 0xC0) + + if (c < 0xc0 + 2 + || c >= 0xf5) // it's limit for 0x140000 unicode codes : win32 compatibility + { _ERROR_UTF8 + } unsigned numBytes; - _UTF8_HEAD_PARSE - else - _ERROR_UTF8 - - UInt32 val = c; + _UTF8_HEAD_PARSE_MAX_3_BYTES + + unsigned pos = 0; do { - Byte c2; - if (src == srcLim) + if (src + pos == srcLim) break; - c2 = *src; - if (c2 < 0x80 || c2 >= 0xC0) + unsigned c2 = (Byte)src[pos]; + c2 -= 0x80; + if (c2 >= 0x40) break; - src++; val <<= 6; - val |= (c2 - 0x80); + val |= c2; + pos++; + if (pos == 1) + { + if (val < (((unsigned)1 << 7) >> numBytes)) + break; + if (numBytes == 2) + { + if (flags & UTF_FLAG__FROM_UTF8__SURROGATE_ERROR) + if ((val & (0xF800 >> 6)) == (0xd800 >> 6)) + break; + } + else if (numBytes == 3 && val >= (0x110000 >> 12)) + break; + } } while (--numBytes); if (numBytes != 0) + { + if ((flags & UTF_FLAG__FROM_UTF8__USE_ESCAPE) == 0) + { + // the following code to emit the 0xfffd chars as win32 Utf8 function. + // disable the folling line, if you need 0xfffd for each incorrect byte as in Escape mode + src += pos; + } + _ERROR_UTF8 + } + + /* + if (val < _UTF8_RANGE(pos - 1)) _ERROR_UTF8 + */ + + #ifdef UTF_ESCAPE_BASE + + if ((flags & UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT) + && IS_ESCAPE_POINT(val, 0)) + { + // We will emit 3 utf16-Escape-16-21 points from one Escape-16 point (3 bytes) + _ERROR_UTF8 + } + + #endif - if (val < 0x10000) + /* + We don't expect virtual Escape-21 points in UTF-8 stream. + And we don't check for Escape-21. + So utf8-Escape-21 will be converted to another 3 utf16-Escape-21 points. + Maybe we could convert virtual utf8-Escape-21 to one utf16-Escape-21 point in some cases? + */ + + if (val < START_POINT_FOR_SURROGATE) { + /* + if ((flags & UTF_FLAG__FROM_UTF8__SURROGATE_ERROR) + && IS_SURROGATE_POINT(val)) + { + // We will emit 3 utf16-Escape-16-21 points from one Surrogate-16 point (3 bytes) + _ERROR_UTF8 + } + */ if (dest) dest[destPos] = (wchar_t)val; destPos++; } else { - val -= 0x10000; - if (val >= 0x100000) + /* + if (val >= 0x110000) + { + // We will emit utf16-Escape-16-21 point from each source byte _ERROR_UTF8 + } + */ if (dest) { - dest[destPos + 0] = (wchar_t)(0xD800 + (val >> 10)); - dest[destPos + 1] = (wchar_t)(0xDC00 + (val & 0x3FF)); + dest[destPos + 0] = (wchar_t)(0xd800 - (0x10000 >> 10) + (val >> 10)); + dest[destPos + 1] = (wchar_t)(0xdc00 + (val & 0x3ff)); } destPos += 2; } + src += pos; } } -#define _UTF8_RANGE(n) (((UInt32)1) << ((n) * 5 + 6)) + #define _UTF8_HEAD(n, val) ((char)(_UTF8_START(n) + (val >> (6 * (n))))) #define _UTF8_CHAR(n, val) ((char)(0x80 + (((val) >> (6 * (n))) & 0x3F))) -static size_t Utf16_To_Utf8_Calc(const wchar_t *src, const wchar_t *srcLim) +static size_t Utf16_To_Utf8_Calc(const wchar_t *src, const wchar_t *srcLim, unsigned flags) { - size_t size = srcLim - src; + size_t size = (size_t)(srcLim - src); for (;;) { if (src == srcLim) return size; - UInt32 val = *src++; + UInt32 val = (UInt32)(*src++); if (val < 0x80) continue; @@ -170,15 +489,32 @@ static size_t Utf16_To_Utf8_Calc(const wchar_t *src, const wchar_t *srcLim) continue; } - if (val >= 0xD800 && val < 0xDC00 && src != srcLim) + #ifdef UTF_ESCAPE_BASE + + #if UTF_ESCAPE_PLANE != 0 + if (flags & UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE) + if (IS_ESCAPE_POINT(val, UTF_ESCAPE_PLANE)) + continue; + #endif + + if (flags & UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE) + if (IS_ESCAPE_POINT(val, 0)) + continue; + + #endif + + if (IS_SURROGATE_POINT(val)) { - UInt32 c2 = *src; - if (c2 >= 0xDC00 && c2 < 0xE000) + // it's hack to UTF-8 encoding + + if (val < 0xdc00 && src != srcLim) { - src++; - size += 2; - continue; + const UInt32 c2 = (UInt32)*src; + if (c2 >= 0xdc00 && c2 < 0xe000) + src++; } + size += 2; + continue; } #ifdef _WCHART_IS_16BIT @@ -191,20 +527,26 @@ static size_t Utf16_To_Utf8_Calc(const wchar_t *src, const wchar_t *srcLim) else if (val < _UTF8_RANGE(3)) size += 3; else if (val < _UTF8_RANGE(4)) size += 4; else if (val < _UTF8_RANGE(5)) size += 5; - else size += 6; + else + #if _UTF8_NUM_TAIL_BYTES_MAX >= 6 + size += 6; + #else + size += 3; + #endif #endif } } -static char *Utf16_To_Utf8(char *dest, const wchar_t *src, const wchar_t *srcLim) + +static char *Utf16_To_Utf8(char *dest, const wchar_t *src, const wchar_t *srcLim, unsigned flags) { for (;;) { if (src == srcLim) return dest; - UInt32 val = *src++; + UInt32 val = (UInt32)*src++; if (val < 0x80) { @@ -220,22 +562,57 @@ static char *Utf16_To_Utf8(char *dest, const wchar_t *src, const wchar_t *srcLim continue; } - if (val >= 0xD800 && val < 0xDC00 && src != srcLim) - { - UInt32 c2 = *src; - if (c2 >= 0xDC00 && c2 < 0xE000) + #ifdef UTF_ESCAPE_BASE + + #if UTF_ESCAPE_PLANE != 0 + /* + if (wchar_t is 32-bit) + && (UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE is set) + && (point is virtual escape plane) + we extract 8-bit byte from virtual HIGH-ESCAPE PLANE. + */ + if (flags & UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE) + if (IS_ESCAPE_POINT(val, UTF_ESCAPE_PLANE)) { - src++; - val = (((val - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000; - dest[0] = _UTF8_HEAD(3, val); - dest[1] = _UTF8_CHAR(2, val); - dest[2] = _UTF8_CHAR(1, val); - dest[3] = _UTF8_CHAR(0, val); - dest += 4; + *dest++ = (char)(val); + continue; + } + #endif // UTF_ESCAPE_PLANE != 0 + + /* if (UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE is defined) + we extract 8-bit byte from BMP-ESCAPE PLANE. */ + + if (flags & UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE) + if (IS_ESCAPE_POINT(val, 0)) + { + *dest++ = (char)(val); continue; } - } + #endif // UTF_ESCAPE_BASE + + if (IS_SURROGATE_POINT(val)) + { + // it's hack to UTF-8 encoding + if (val < 0xdc00 && src != srcLim) + { + const UInt32 c2 = (UInt32)*src; + if (IS_LOW_SURROGATE_POINT(c2)) + { + src++; + val = (((val - 0xd800) << 10) | (c2 - 0xdc00)) + 0x10000; + dest[0] = _UTF8_HEAD(3, val); + dest[1] = _UTF8_CHAR(2, val); + dest[2] = _UTF8_CHAR(1, val); + dest[3] = _UTF8_CHAR(0, val); + dest += 4; + continue; + } + } + if (flags & UTF_FLAG__TO_UTF8__SURROGATE_ERROR) + val = UTF_REPLACEMENT_CHAR; // WIN32 function does it + } + #ifndef _WCHART_IS_16BIT if (val < _UTF8_RANGE(2)) #endif @@ -249,14 +626,25 @@ static char *Utf16_To_Utf8(char *dest, const wchar_t *src, const wchar_t *srcLim #ifndef _WCHART_IS_16BIT - UInt32 b; + // we don't expect this case. so we can throw exception + // throw 20210407; + + char b; unsigned numBits; if (val < _UTF8_RANGE(3)) { numBits = 6 * 3; b = _UTF8_HEAD(3, val); } else if (val < _UTF8_RANGE(4)) { numBits = 6 * 4; b = _UTF8_HEAD(4, val); } else if (val < _UTF8_RANGE(5)) { numBits = 6 * 5; b = _UTF8_HEAD(5, val); } - else { numBits = 6 * 6; b = _UTF8_START(6); } - - *dest++ = (Byte)b; + #if _UTF8_NUM_TAIL_BYTES_MAX >= 6 + else { numBits = 6 * 6; b = (char)_UTF8_START(6); } + #else + else + { + val = UTF_REPLACEMENT_CHAR; + { numBits = 6 * 3; b = _UTF8_HEAD(3, val); } + } + #endif + + *dest++ = b; do { @@ -269,20 +657,207 @@ static char *Utf16_To_Utf8(char *dest, const wchar_t *src, const wchar_t *srcLim } } -bool ConvertUTF8ToUnicode(const AString &src, UString &dest) +bool Convert_UTF8_Buf_To_Unicode(const char *src, size_t srcSize, UString &dest, unsigned flags) { dest.Empty(); size_t destLen = 0; - Utf8_To_Utf16(NULL, &destLen, src, src.Ptr(src.Len())); - bool res = Utf8_To_Utf16(dest.GetBuf((unsigned)destLen), &destLen, src, src.Ptr(src.Len())); + Utf8_To_Utf16(NULL, &destLen, src, src + srcSize, flags); + bool res = Utf8_To_Utf16(dest.GetBuf((unsigned)destLen), &destLen, src, src + srcSize, flags); dest.ReleaseBuf_SetEnd((unsigned)destLen); return res; } -void ConvertUnicodeToUTF8(const UString &src, AString &dest) +bool ConvertUTF8ToUnicode_Flags(const AString &src, UString &dest, unsigned flags) +{ + return Convert_UTF8_Buf_To_Unicode(src, src.Len(), dest, flags); +} + + +static +unsigned g_UTF8_To_Unicode_Flags = + UTF_FLAG__FROM_UTF8__USE_ESCAPE + #ifndef _WCHART_IS_16BIT + | UTF_FLAG__FROM_UTF8__SURROGATE_ERROR + #ifdef _UTF8_RAW_NON_UTF8_SUPPORTED + | UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT + #endif + #endif + ; + + +/* +bool ConvertUTF8ToUnicode_boolRes(const AString &src, UString &dest) +{ + return ConvertUTF8ToUnicode_Flags(src, dest, g_UTF8_To_Unicode_Flags); +} +*/ + +bool ConvertUTF8ToUnicode(const AString &src, UString &dest) { + return ConvertUTF8ToUnicode_Flags(src, dest, g_UTF8_To_Unicode_Flags); +} + +void Print_UString(const UString &a); + +void ConvertUnicodeToUTF8_Flags(const UString &src, AString &dest, unsigned flags) +{ + /* + if (src.Len()== 24) + throw "202104"; + */ dest.Empty(); - size_t destLen = Utf16_To_Utf8_Calc(src, src.Ptr(src.Len())); - Utf16_To_Utf8(dest.GetBuf((unsigned)destLen), src, src.Ptr(src.Len())); + const size_t destLen = Utf16_To_Utf8_Calc(src, src.Ptr(src.Len()), flags); + char *destStart = dest.GetBuf((unsigned)destLen); + const char *destEnd = Utf16_To_Utf8(destStart, src, src.Ptr(src.Len()), flags); dest.ReleaseBuf_SetEnd((unsigned)destLen); + // printf("\nlen = %d\n", src.Len()); + if (destLen != (size_t)(destEnd - destStart)) + { + /* + // dest.ReleaseBuf_SetEnd((unsigned)(destEnd - destStart)); + printf("\nlen = %d\n", (unsigned)destLen); + printf("\n(destEnd - destStart) = %d\n", (unsigned)(destEnd - destStart)); + printf("\n"); + // Print_UString(src); + printf("\n"); + // printf("\nlen = %d\n", destLen); + */ + throw 20210406; + } +} + + + +unsigned g_Unicode_To_UTF8_Flags = + // UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE + 0 + #ifndef _WIN32 + #ifdef _UTF8_RAW_NON_UTF8_SUPPORTED + | UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE + #else + | UTF_FLAG__TO_UTF8__SURROGATE_ERROR; + #endif + #endif + ; + +void ConvertUnicodeToUTF8(const UString &src, AString &dest) +{ + ConvertUnicodeToUTF8_Flags(src, dest, g_Unicode_To_UTF8_Flags); +} + +void Convert_Unicode_To_UTF8_Buf(const UString &src, CByteBuffer &dest) +{ + const unsigned flags = g_Unicode_To_UTF8_Flags; + dest.Free(); + const size_t destLen = Utf16_To_Utf8_Calc(src, src.Ptr(src.Len()), flags); + dest.Alloc(destLen); + const char *destEnd = Utf16_To_Utf8((char *)(void *)(Byte *)dest, src, src.Ptr(src.Len()), flags); + if (destLen != (size_t)(destEnd - (char *)(void *)(Byte *)dest)) + throw 202104; } + +/* + +#ifndef _WIN32 +void Convert_UTF16_To_UTF32(const UString &src, UString &dest) +{ + dest.Empty(); + for (size_t i = 0; i < src.Len();) + { + wchar_t c = src[i++]; + if (c >= 0xd800 && c < 0xdc00 && i < src.Len()) + { + const wchar_t c2 = src[i]; + if (c2 >= 0xdc00 && c2 < 0x10000) + { + // printf("\nSurragate [%d]: %4x %4x -> ", i, (int)c, (int)c2); + c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); + // printf("%4x\n", (int)c); + i++; + } + } + dest += c; + } +} + +void Convert_UTF32_To_UTF16(const UString &src, UString &dest) +{ + dest.Empty(); + for (size_t i = 0; i < src.Len();) + { + wchar_t w = src[i++]; + if (w >= 0x10000 && w < 0x110000) + { + w -= 0x10000; + dest += (wchar_t)((unsigned)0xd800 + (((unsigned)w >> 10) & 0x3ff)); + w = 0xdc00 + (w & 0x3ff); + } + dest += w; + } +} + +bool UTF32_IsThere_BigPoint(const UString &src) +{ + for (size_t i = 0; i < src.Len();) + { + const UInt32 c = (UInt32)src[i++]; + if (c >= 0x110000) + return true; + } + return false; +} + +bool Unicode_IsThere_BmpEscape(const UString &src) +{ + for (size_t i = 0; i < src.Len();) + { + const UInt32 c = (UInt32)src[i++]; + if (IS_ESCAPE_POINT(c, 0)) + return true; + } + return false; +} + + +#endif + +bool Unicode_IsThere_Utf16SurrogateError(const UString &src) +{ + for (size_t i = 0; i < src.Len();) + { + const UInt32 val = (UInt32)src[i++]; + if (IS_SURROGATE_POINT(val)) + { + // it's hack to UTF-8 encoding + if (val >= 0xdc00 || i == src.Len()) + return true; + const UInt32 c2 = (UInt32)*src; + if (!IS_LOW_SURROGATE_POINT(c2)) + return true; + } + } + return false; +} +*/ + +#ifndef _WCHART_IS_16BIT + +void Convert_UnicodeEsc16_To_UnicodeEscHigh +#if UTF_ESCAPE_PLANE == 0 + (UString &) {} +#else + (UString &s) +{ + const unsigned len = s.Len(); + for (unsigned i = 0; i < len; i++) + { + wchar_t c = s[i]; + if (IS_ESCAPE_POINT(c, 0)) + { + c += UTF_ESCAPE_PLANE; + s.ReplaceOneCharAtPos(i, c); + } + } +} +#endif +#endif diff --git a/CPP/Common/UTFConvert.h b/CPP/Common/UTFConvert.h index 827f3dcf..37c4975a 100644 --- a/CPP/Common/UTFConvert.h +++ b/CPP/Common/UTFConvert.h @@ -3,10 +3,382 @@ #ifndef __COMMON_UTF_CONVERT_H #define __COMMON_UTF_CONVERT_H +#include "MyBuffer.h" #include "MyString.h" -bool CheckUTF8(const char *src, bool allowReduced = false) throw(); -bool ConvertUTF8ToUnicode(const AString &utfString, UString &resultString); -void ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString); +struct CUtf8Check +{ + // Byte MaxByte; // in original src stream + bool NonUtf; + bool ZeroChar; + bool SingleSurrogate; + bool Escape; + bool Truncated; + UInt32 MaxHighPoint; // only for points >= 0x80 + + CUtf8Check() { Clear(); } + + void Clear() + { + // MaxByte = 0; + NonUtf = false; + ZeroChar = false; + SingleSurrogate = false; + Escape = false; + Truncated = false; + MaxHighPoint = 0; + } + + void Update(const CUtf8Check &c) + { + if (c.NonUtf) NonUtf = true; + if (c.ZeroChar) ZeroChar = true; + if (c.SingleSurrogate) SingleSurrogate = true; + if (c.Escape) Escape = true; + if (c.Truncated) Truncated = true; + if (MaxHighPoint < c.MaxHighPoint) MaxHighPoint = c.MaxHighPoint; + } + + void PrintStatus(AString &s) const + { + s.Empty(); + + // s.Add_OptSpaced("MaxByte="); + // s.Add_UInt32(MaxByte); + + if (NonUtf) s.Add_OptSpaced("non-UTF8"); + if (ZeroChar) s.Add_OptSpaced("ZeroChar"); + if (SingleSurrogate) s.Add_OptSpaced("SingleSurrogate"); + if (Escape) s.Add_OptSpaced("Escape"); + if (Truncated) s.Add_OptSpaced("Truncated"); + + if (MaxHighPoint != 0) + { + s.Add_OptSpaced("MaxUnicode="); + s.Add_UInt32(MaxHighPoint); + } + } + + + bool IsOK(bool allowReduced = false) const + { + if (NonUtf || SingleSurrogate || ZeroChar) + return false; + if (MaxHighPoint >= 0x110000) + return false; + if (Truncated && !allowReduced) + return false; + return true; + } + + // it checks full buffer as specified in (size) and it doesn't stop on zero char + void Check_Buf(const char *src, size_t size) throw(); + + void Check_AString(const AString &s) throw() + { + Check_Buf(s.Ptr(), s.Len()); + } +}; + +/* +if (allowReduced == false) - all UTF-8 character sequences must be finished. +if (allowReduced == true) - it allows truncated last character-Utf8-sequence +*/ + +bool Check_UTF8_Buf(const char *src, size_t size, bool allowReduced) throw(); +bool CheckUTF8_AString(const AString &s) throw(); + +#define UTF_FLAG__FROM_UTF8__SURROGATE_ERROR (1 << 0) +#define UTF_FLAG__FROM_UTF8__USE_ESCAPE (1 << 1) +#define UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT (1 << 2) + +/* +UTF_FLAG__FROM_UTF8__SURROGATE_ERROR + + if (flag is NOT set) + { + it processes SINGLE-SURROGATE-8 as valid Unicode point. + it converts SINGLE-SURROGATE-8 to SINGLE-SURROGATE-16 + Note: some sequencies of two SINGLE-SURROGATE-8 points + will generate correct SURROGATE-16-PAIR, and + that SURROGATE-16-PAIR later will be converted to correct + UTF8-SURROGATE-21 point. So we don't restore original + STR-8 sequence in that case. + } + + if (flag is set) + { + if (UTF_FLAG__FROM_UTF8__USE_ESCAPE is defined) + it generates ESCAPE for SINGLE-SURROGATE-8, + if (UTF_FLAG__FROM_UTF8__USE_ESCAPE is not defined) + it generates U+fffd for SINGLE-SURROGATE-8, + } + + +UTF_FLAG__FROM_UTF8__USE_ESCAPE + + if (flag is NOT set) + it generates (U+fffd) code for non-UTF-8 (invalid) characters + + if (flag is set) + { + It generates (ESCAPE) codes for NON-UTF-8 (invalid) characters. + And later we can restore original UTF-8-RAW characters from (ESCAPE-16-21) codes. + } + +UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT + + if (flag is NOT set) + { + it process ESCAPE-8 points as another Unicode points. + In Linux: ESCAPE-16 will mean two different ESCAPE-8 seqences, + so we need HIGH-ESCAPE-PLANE-21 to restore UTF-8-RAW -> UTF-16 -> UTF-8-RAW + } + + if (flag is set) + { + it generates ESCAPE-16-21 for ESCAPE-8 points + so we can restore UTF-8-RAW -> UTF-16 -> UTF-8-RAW without HIGH-ESCAPE-PLANE-21. + } + + +Main USE CASES with UTF-8 <-> UTF-16 conversions: + + WIN32: UTF-16-RAW -> UTF-8 (Archive) -> UTF-16-RAW + { + set UTF_FLAG__FROM_UTF8__USE_ESCAPE + Do NOT set UTF_FLAG__FROM_UTF8__SURROGATE_ERROR + Do NOT set UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT + + So we restore original SINGLE-SURROGATE-16 from single SINGLE-SURROGATE-8. + } + + Linux: UTF-8-RAW -> UTF-16 (Intermediate / Archive) -> UTF-8-RAW + { + we want restore original UTF-8-RAW sequence later from that ESCAPE-16. + Set the flags: + UTF_FLAG__FROM_UTF8__SURROGATE_ERROR + UTF_FLAG__FROM_UTF8__USE_ESCAPE + UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT + } + + MacOS: UTF-8-RAW -> UTF-16 (Intermediate / Archive) -> UTF-8-RAW + { + we want to restore correct UTF-8 without any BMP processing: + Set the flags: + UTF_FLAG__FROM_UTF8__SURROGATE_ERROR + UTF_FLAG__FROM_UTF8__USE_ESCAPE + } + +*/ + +// zero char is not allowed in (src) buf +bool Convert_UTF8_Buf_To_Unicode(const char *src, size_t srcSize, UString &dest, unsigned flags = 0); + +bool ConvertUTF8ToUnicode_Flags(const AString &src, UString &dest, unsigned flags = 0); +bool ConvertUTF8ToUnicode(const AString &src, UString &dest); + +#define UTF_FLAG__TO_UTF8__SURROGATE_ERROR (1 << 8) +#define UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE (1 << 9) +// #define UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE (1 << 10) + +/* +UTF_FLAG__TO_UTF8__SURROGATE_ERROR + + if (flag is NOT set) + { + we extract SINGLE-SURROGATE as normal UTF-8 + + In Windows : for UTF-16-RAW <-> UTF-8 (archive) <-> UTF-16-RAW in . + + In Linux : + use-case-1: UTF-8 -> UTF-16 -> UTF-8 doesn't generate UTF-16 SINGLE-SURROGATE, + if (UTF_FLAG__FROM_UTF8__SURROGATE_ERROR) is used. + use-case 2: UTF-16-7z (with SINGLE-SURROGATE from Windows) -> UTF-8 (Linux) + will generate SINGLE-SURROGATE-UTF-8 here. + } + + if (flag is set) + { + we generate UTF_REPLACEMENT_CHAR (0xfffd) for SINGLE_SURROGATE + it can be used for compatibility mode with WIN32 UTF function + or if we want UTF-8 stream without any errors + } + + +UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE + + if (flag is NOT set) it doesn't extract raw 8-bit symbol from Escape-Plane-16 + if (flag is set) it extracts raw 8-bit symbol from Escape-Plane-16 + + in Linux we need some way to extract NON-UTF8 RAW 8-bits from BMP (UTF-16 7z archive): + if (we use High-Escape-Plane), we can transfer BMP escapes to High-Escape-Plane. + if (we don't use High-Escape-Plane), we must use UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE. + + +UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE + // that flag affects the code only if (wchar_t is 32-bit) + // that mode with high-escape can be disabled now in UTFConvert.cpp + if (flag is NOT set) + it doesn't extract raw 8-bit symbol from High-Escape-Plane + if (flag is set) + it extracts raw 8-bit symbol from High-Escape-Plane + +Main use cases: + +WIN32 : UTF-16-RAW -> UTF-8 (archive) -> UTF-16-RAW + { + Do NOT set UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE. + Do NOT set UTF_FLAG__TO_UTF8__SURROGATE_ERROR. + So we restore original UTF-16-RAW. + } + +Linix : UTF-8 with Escapes -> UTF-16 (7z archive) -> UTF-8 with Escapes + set UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE to extract non-UTF from 7z archive + set UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE for intermediate UTF-16. + Note: high esacape mode can be ignored now in UTFConvert.cpp + +macOS: + the system doesn't support incorrect UTF-8 in file names. + set UTF_FLAG__TO_UTF8__SURROGATE_ERROR +*/ + +extern unsigned g_Unicode_To_UTF8_Flags; + +void ConvertUnicodeToUTF8_Flags(const UString &src, AString &dest, unsigned flags = 0); +void ConvertUnicodeToUTF8(const UString &src, AString &dest); + +void Convert_Unicode_To_UTF8_Buf(const UString &src, CByteBuffer &dest); + +/* +#ifndef _WIN32 +void Convert_UTF16_To_UTF32(const UString &src, UString &dest); +void Convert_UTF32_To_UTF16(const UString &src, UString &dest); +bool UTF32_IsThere_BigPoint(const UString &src); +bool Unicode_IsThere_BmpEscape(const UString &src); +#endif + +bool Unicode_IsThere_Utf16SurrogateError(const UString &src); +*/ + +#ifdef _WCHART_IS_16BIT +#define Convert_UnicodeEsc16_To_UnicodeEscHigh(s) +#else +void Convert_UnicodeEsc16_To_UnicodeEscHigh(UString &s); +#endif + +/* +// #include "../../C/CpuArch.h" + +// ---------- Utf16 Little endian functions ---------- + +// We store 16-bit surrogates even in 32-bit WCHARs in Linux. +// So now we don't use the following code: + +#if WCHAR_MAX > 0xffff + +// void *p : pointer to src bytes stream +// size_t len : num Utf16 characters : it can include or not include NULL character + +inline size_t Utf16LE__Get_Num_WCHARs(const void *p, size_t len) +{ + #if WCHAR_MAX > 0xffff + size_t num_wchars = 0; + for (size_t i = 0; i < len; i++) + { + wchar_t c = GetUi16(p); + p = (const void *)((const Byte *)p + 2); + if (c >= 0xd800 && c < 0xdc00 && i + 1 != len) + { + wchar_t c2 = GetUi16(p); + if (c2 >= 0xdc00 && c2 < 0xe000) + { + c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); + p = (const void *)((const Byte *)p + 2); + i++; + } + } + num_wchars++; + } + return num_wchars; + #else + UNUSED_VAR(p) + return len; + #endif +} + +// #include <stdio.h> + +inline wchar_t *Utf16LE__To_WCHARs_Sep(const void *p, size_t len, wchar_t *dest) +{ + for (size_t i = 0; i < len; i++) + { + wchar_t c = GetUi16(p); + p = (const void *)((const Byte *)p + 2); + + #if WCHAR_PATH_SEPARATOR != L'/' + if (c == L'/') + c = WCHAR_PATH_SEPARATOR; + #endif + + #if WCHAR_MAX > 0xffff + + if (c >= 0xd800 && c < 0xdc00 && i + 1 != len) + { + wchar_t c2 = GetUi16(p); + if (c2 >= 0xdc00 && c2 < 0xe000) + { + // printf("\nSurragate : %4x %4x -> ", (int)c, (int)c2); + c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); + p = (const void *)((const Byte *)p + 2); + i++; + // printf("%4x\n", (int)c); + } + } + + #endif + + *dest++ = c; + } + return dest; +} + + +inline size_t Get_Num_Utf16_chars_from_wchar_string(const wchar_t *p) +{ + size_t num = 0; + for (;;) + { + wchar_t c = *p++; + if (c == 0) + return num; + num += ((c >= 0x10000 && c < 0x110000) ? 2 : 1); + } + return num; +} + +inline Byte *wchars_to_Utf16LE(const wchar_t *p, Byte *dest) +{ + for (;;) + { + wchar_t c = *p++; + if (c == 0) + return dest; + if (c >= 0x10000 && c < 0x110000) + { + SetUi16(dest , (UInt16)(0xd800 + ((c >> 10) & 0x3FF))); + SetUi16(dest + 2, (UInt16)(0xdc00 + ( c & 0x3FF))); + dest += 4; + } + else + { + SetUi16(dest, c); + dest += 2; + } + } +} + +#endif +*/ #endif diff --git a/CPP/Common/Wildcard.cpp b/CPP/Common/Wildcard.cpp index a7199170..e2040120 100644 --- a/CPP/Common/Wildcard.cpp +++ b/CPP/Common/Wildcard.cpp @@ -4,9 +4,17 @@ #include "Wildcard.h" +extern +bool g_CaseSensitive; bool g_CaseSensitive = #ifdef _WIN32 false; + #elif defined (__APPLE__) + #ifdef TARGET_OS_IPHONE + true; + #else + false; + #endif #else true; #endif @@ -19,8 +27,16 @@ bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2) return IsString1PrefixedByString2_NoCase(s1, s2); } +// #include <stdio.h> + int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW { + /* + printf("\nCompareFileNames"); + printf("\n S1: %ls", s1); + printf("\n S2: %ls", s2); + printf("\n"); + */ if (g_CaseSensitive) return MyStringCompare(s1, s2); return MyStringCompareNoCase(s1, s2); @@ -131,7 +147,7 @@ UString ExtractDirPrefixFromPath(const UString &path) UString ExtractFileNameFromPath(const UString &path) { - return UString(path.Ptr(path.ReverseFind_PathSepar() + 1)); + return UString(path.Ptr((unsigned)(path.ReverseFind_PathSepar() + 1))); } @@ -229,12 +245,12 @@ bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const { if (WildcardMatching) { - if (!DoesWildcardMatchName(PathParts[i], pathParts[i + d])) + if (!DoesWildcardMatchName(PathParts[i], pathParts[i + (unsigned)d])) break; } else { - if (CompareFileNames(PathParts[i], pathParts[i + d]) != 0) + if (CompareFileNames(PathParts[i], pathParts[i + (unsigned)d]) != 0) break; } } @@ -258,16 +274,14 @@ int CCensorNode::FindSubNode(const UString &name) const { FOR_VECTOR (i, SubNodes) if (CompareFileNames(SubNodes[i].Name, name) == 0) - return i; + return (int)i; return -1; } void CCensorNode::AddItemSimple(bool include, CItem &item) { - if (include) - IncludeItems.Add(item); - else - ExcludeItems.Add(item); + CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems; + items.Add(item); } void CCensorNode::AddItem(bool include, CItem &item, int ignoreWildcardIndex) @@ -282,6 +296,7 @@ void CCensorNode::AddItem(bool include, CItem &item, int ignoreWildcardIndex) AddItemSimple(include, item); return; } + const UString &front = item.PathParts.Front(); // WIN32 doesn't support wildcards in file names @@ -292,11 +307,9 @@ void CCensorNode::AddItem(bool include, CItem &item, int ignoreWildcardIndex) AddItemSimple(include, item); return; } - int index = FindSubNode(front); - if (index < 0) - index = SubNodes.Add(CCensorNode(front, this)); + CCensorNode &subNode = Find_SubNode_Or_Add_New(front); item.PathParts.Delete(0); - SubNodes[index].AddItem(include, item, ignoreWildcardIndex - 1); + subNode.AddItem(include, item, ignoreWildcardIndex - 1); } void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir, bool wildcardMatching) @@ -347,18 +360,19 @@ bool CCensorNode::CheckPathVect(const UStringVector &pathParts, bool isFile, boo include = false; return true; } - include = true; - bool finded = CheckPathCurrent(true, pathParts, isFile); - if (pathParts.Size() <= 1) - return finded; - int index = FindSubNode(pathParts.Front()); - if (index >= 0) + if (pathParts.Size() > 1) { - UStringVector pathParts2 = pathParts; - pathParts2.Delete(0); - if (SubNodes[index].CheckPathVect(pathParts2, isFile, include)) - return true; + int index = FindSubNode(pathParts.Front()); + if (index >= 0) + { + UStringVector pathParts2 = pathParts; + pathParts2.Delete(0); + if (SubNodes[(unsigned)index].CheckPathVect(pathParts2, isFile, include)) + return true; + } } + bool finded = CheckPathCurrent(true, pathParts, isFile); + include = finded; // if (!finded), then (true) is allowed also return finded; } @@ -394,14 +408,26 @@ bool CCensorNode::CheckPath(bool isAltStream, const UString &path, bool isFile) } */ -bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const +bool CCensorNode::CheckPathToRoot_Change(bool include, UStringVector &pathParts, bool isFile) const { if (CheckPathCurrent(include, pathParts, isFile)) return true; - if (Parent == 0) + if (!Parent) return false; pathParts.Insert(0, Name); - return Parent->CheckPathToRoot(include, pathParts, isFile); + return Parent->CheckPathToRoot_Change(include, pathParts, isFile); +} + +bool CCensorNode::CheckPathToRoot(bool include, const UStringVector &pathParts, bool isFile) const +{ + if (CheckPathCurrent(include, pathParts, isFile)) + return true; + if (!Parent) + return false; + UStringVector pathParts2; + pathParts2.Add(Name); + pathParts2 += pathParts; + return Parent->CheckPathToRoot_Change(include, pathParts2, isFile); } /* @@ -434,18 +460,15 @@ void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) FOR_VECTOR (i, fromNodes.SubNodes) { const CCensorNode &node = fromNodes.SubNodes[i]; - int subNodeIndex = FindSubNode(node.Name); - if (subNodeIndex < 0) - subNodeIndex = SubNodes.Add(CCensorNode(node.Name, this)); - SubNodes[subNodeIndex].ExtendExclude(node); + Find_SubNode_Or_Add_New(node.Name).ExtendExclude(node); } } -int CCensor::FindPrefix(const UString &prefix) const +int CCensor::FindPairForPrefix(const UString &prefix) const { FOR_VECTOR (i, Pairs) if (CompareFileNames(Pairs[i].Prefix, prefix) == 0) - return i; + return (int)i; return -1; } @@ -454,7 +477,11 @@ int CCensor::FindPrefix(const UString &prefix) const bool IsDriveColonName(const wchar_t *s) { wchar_t c = s[0]; - return c != 0 && s[1] == ':' && s[2] == 0 && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'); + return c != 0 + && s[1] == ':' + && s[2] == 0 + && ((c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z')); } unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts) @@ -571,14 +598,16 @@ void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &pat { const UString &part = pathParts[i]; if (part == L".." || part == L".") - dotsIndex = i; + dotsIndex = (int)i; } if (dotsIndex >= 0) + { if (dotsIndex == (int)pathParts.Size() - 1) numSkipParts = pathParts.Size(); else numSkipParts = pathParts.Size() - 1; + } } for (unsigned i = 0; i < numSkipParts; i++) @@ -596,13 +625,16 @@ void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &pat } } - int index = FindPrefix(prefix); + int index = FindPairForPrefix(prefix); if (index < 0) - index = Pairs.Add(CPair(prefix)); + { + index = (int)Pairs.Size(); + Pairs.AddNew().Prefix = prefix; + } if (pathMode != k_AbsPath) { - if (pathParts.IsEmpty() || pathParts.Size() == 1 && pathParts[0].IsEmpty()) + if (pathParts.IsEmpty() || (pathParts.Size() == 1 && pathParts[0].IsEmpty())) { // we create universal item, if we skip all parts as prefix (like \ or L:\ ) pathParts.Clear(); @@ -619,7 +651,7 @@ void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &pat item.ForFile = forFile; item.Recursive = recursive; item.WildcardMatching = wildcardMatching; - Pairs[index].Head.AddItem(include, item, ignoreWildcardIndex); + Pairs[(unsigned)index].Head.AddItem(include, item, ignoreWildcardIndex); } /* diff --git a/CPP/Common/Wildcard.h b/CPP/Common/Wildcard.h index 93f53c0f..32b1521f 100644 --- a/CPP/Common/Wildcard.h +++ b/CPP/Common/Wildcard.h @@ -51,23 +51,34 @@ struct CItem bool CheckPath(const UStringVector &pathParts, bool isFile) const; }; -class CCensorNode + +class CCensorNode MY_UNCOPYABLE { CCensorNode *Parent; bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const; void AddItemSimple(bool include, CItem &item); public: - bool CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const; - - CCensorNode(): Parent(0) { }; - CCensorNode(const UString &name, CCensorNode *parent): Name(name), Parent(parent) { }; + CCensorNode(): Parent(NULL) { }; + CCensorNode(const UString &name, CCensorNode *parent): Parent(parent), Name(name) { }; UString Name; // WIN32 doesn't support wildcards in file names CObjectVector<CCensorNode> SubNodes; CObjectVector<CItem> IncludeItems; CObjectVector<CItem> ExcludeItems; + CCensorNode &Find_SubNode_Or_Add_New(const UString &name) + { + int i = FindSubNode(name); + if (i >= 0) + return SubNodes[(unsigned)i]; + // return SubNodes.Add(CCensorNode(name, this)); + CCensorNode &node = SubNodes.AddNew(); + node.Parent = this; + node.Name = name; + return node; + } + bool AreAllAllowed() const; int FindSubNode(const UString &path) const; @@ -76,25 +87,41 @@ public: void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir, bool wildcardMatching); void AddItem2(bool include, const UString &path, bool recursive, bool wildcardMatching); + // NeedCheckSubDirs() returns true, if there are IncludeItems rules that affect items in subdirs bool NeedCheckSubDirs() const; bool AreThereIncludeItems() const; + /* + CheckPathVect() doesn't check path in Parent CCensorNode + so use CheckPathVect() for root CCensorNode + OUT: + returns (true) && (include = false) - file in exlude list + returns (true) && (include = true) - file in include list and is not in exlude list + returns (false) - file is not in (include/exlude) list + */ + bool CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const; + // bool CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const; // bool CheckPath(bool isAltStream, const UString &path, bool isFile) const; - bool CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const; + // CheckPathToRoot_Change() changes pathParts !!! + bool CheckPathToRoot_Change(bool include, UStringVector &pathParts, bool isFile) const; + bool CheckPathToRoot(bool include, const UStringVector &pathParts, bool isFile) const; + // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const; void ExtendExclude(const CCensorNode &fromNodes); }; -struct CPair + +struct CPair MY_UNCOPYABLE { UString Prefix; CCensorNode Head; - CPair(const UString &prefix): Prefix(prefix) { }; + // CPair(const UString &prefix): Prefix(prefix) { }; }; + enum ECensorPathMode { k_RelatPath, // absolute prefix as Prefix, remain path in Tree @@ -102,6 +129,7 @@ enum ECensorPathMode k_AbsPath // full path in Tree }; + struct CCensorPath { UString Path; @@ -116,9 +144,10 @@ struct CCensorPath {} }; -class CCensor + +class CCensor MY_UNCOPYABLE { - int FindPrefix(const UString &prefix) const; + int FindPairForPrefix(const UString &prefix) const; public: CObjectVector<CPair> Pairs; @@ -143,7 +172,6 @@ public: } }; - } #endif diff --git a/CPP/Windows/CommonDialog.cpp b/CPP/Windows/CommonDialog.cpp index 8f4f56d3..eaaecada 100644 --- a/CPP/Windows/CommonDialog.cpp +++ b/CPP/Windows/CommonDialog.cpp @@ -67,8 +67,11 @@ bool CDoubleZeroStringListW::Add(LPCWSTR s) throw() return true; } + +#ifdef UNDER_CE #define MY__OFN_PROJECT 0x00400000 #define MY__OFN_SHOW_ALL 0x01000000 +#endif /* if (lpstrFilter == NULL && nFilterIndex == 0) MSDN : "the system doesn't show any files", @@ -91,14 +94,34 @@ So we use size of old version of structure. */ #if defined(UNDER_CE) || defined(_WIN64) || (_WIN32_WINNT < 0x0500) // || !defined(WINVER) + #ifndef _UNICODE #define my_compatib_OPENFILENAMEA_size sizeof(OPENFILENAMEA) + #endif #define my_compatib_OPENFILENAMEW_size sizeof(OPENFILENAMEW) #else + + // MinGW doesn't support some required macros. So we define them here: + #ifndef CDSIZEOF_STRUCT + #define CDSIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member)) + #endif + #ifndef _UNICODE + #ifndef OPENFILENAME_SIZE_VERSION_400A + #define OPENFILENAME_SIZE_VERSION_400A CDSIZEOF_STRUCT(OPENFILENAMEA,lpTemplateName) + #endif + #endif + #ifndef OPENFILENAME_SIZE_VERSION_400W + #define OPENFILENAME_SIZE_VERSION_400W CDSIZEOF_STRUCT(OPENFILENAMEW,lpTemplateName) + #endif + + #ifndef _UNICODE #define my_compatib_OPENFILENAMEA_size OPENFILENAME_SIZE_VERSION_400A + #endif #define my_compatib_OPENFILENAMEW_size OPENFILENAME_SIZE_VERSION_400W #endif +#ifndef _UNICODE #define CONV_U_To_A(dest, src, temp) AString temp; if (src) { temp = GetSystemString(src); dest = temp; } +#endif bool MyGetOpenFileName(HWND hwnd, LPCWSTR title, LPCWSTR initialDir, diff --git a/CPP/Windows/Control/ComboBox.cpp b/CPP/Windows/Control/ComboBox.cpp index febc61ef..f6ed8d34 100644 --- a/CPP/Windows/Control/ComboBox.cpp +++ b/CPP/Windows/Control/ComboBox.cpp @@ -43,10 +43,10 @@ LRESULT CComboBox::GetLBText(int index, UString &s) s.Empty(); if (g_IsNT) { - LRESULT len = SendMsgW(CB_GETLBTEXTLEN, index, 0); + LRESULT len = SendMsgW(CB_GETLBTEXTLEN, MY__int_TO_WPARAM(index), 0); if (len == CB_ERR) return len; - LRESULT len2 = SendMsgW(CB_GETLBTEXT, index, (LPARAM)s.GetBuf((unsigned)len)); + LRESULT len2 = SendMsgW(CB_GETLBTEXT, MY__int_TO_WPARAM(index), (LPARAM)s.GetBuf((unsigned)len)); if (len2 == CB_ERR) return len; if (len > len2) diff --git a/CPP/Windows/Control/ComboBox.h b/CPP/Windows/Control/ComboBox.h index 1d5a4821..f08b1f7c 100644 --- a/CPP/Windows/Control/ComboBox.h +++ b/CPP/Windows/Control/ComboBox.h @@ -5,13 +5,15 @@ #include "../../Common/MyWindows.h" -#include <commctrl.h> +#include <CommCtrl.h> #include "../Window.h" namespace NWindows { namespace NControl { +#define MY__int_TO_WPARAM(i) ((WPARAM)(INT_PTR)(i)) + class CComboBox: public CWindow { public: @@ -20,19 +22,25 @@ public: #ifndef _UNICODE LRESULT AddString(LPCWSTR s); #endif - LRESULT SetCurSel(int index) { return SendMsg(CB_SETCURSEL, index, 0); } + + /* If this parameter is -1, any current selection in the list is removed and the edit control is cleared.*/ + LRESULT SetCurSel(int index) { return SendMsg(CB_SETCURSEL, MY__int_TO_WPARAM(index), 0); } + + /* If no item is selected, it returns CB_ERR (-1) */ int GetCurSel() { return (int)SendMsg(CB_GETCURSEL, 0, 0); } + + /* If an error occurs, it is CB_ERR (-1) */ int GetCount() { return (int)SendMsg(CB_GETCOUNT, 0, 0); } - LRESULT GetLBTextLen(int index) { return SendMsg(CB_GETLBTEXTLEN, index, 0); } - LRESULT GetLBText(int index, LPTSTR s) { return SendMsg(CB_GETLBTEXT, index, (LPARAM)s); } + LRESULT GetLBTextLen(int index) { return SendMsg(CB_GETLBTEXTLEN, MY__int_TO_WPARAM(index), 0); } + LRESULT GetLBText(int index, LPTSTR s) { return SendMsg(CB_GETLBTEXT, MY__int_TO_WPARAM(index), (LPARAM)s); } LRESULT GetLBText(int index, CSysString &s); #ifndef _UNICODE LRESULT GetLBText(int index, UString &s); #endif - LRESULT SetItemData(int index, LPARAM lParam) { return SendMsg(CB_SETITEMDATA, index, lParam); } - LRESULT GetItemData(int index) { return SendMsg(CB_GETITEMDATA, index, 0); } + LRESULT SetItemData(int index, LPARAM lParam) { return SendMsg(CB_SETITEMDATA, MY__int_TO_WPARAM(index), lParam); } + LRESULT GetItemData(int index) { return SendMsg(CB_GETITEMDATA, MY__int_TO_WPARAM(index), 0); } LRESULT GetItemData_of_CurSel() { return GetItemData(GetCurSel()); } @@ -46,7 +54,11 @@ class CComboBoxEx: public CComboBox public: bool SetUnicodeFormat(bool fUnicode) { return LRESULTToBool(SendMsg(CBEM_SETUNICODEFORMAT, BOOLToBool(fUnicode), 0)); } - LRESULT DeleteItem(int index) { return SendMsg(CBEM_DELETEITEM, index, 0); } + /* Returns: + an INT value that represents the number of items remaining in the control. + If (index) is invalid, the message returns CB_ERR. */ + LRESULT DeleteItem(int index) { return SendMsg(CBEM_DELETEITEM, MY__int_TO_WPARAM(index), 0); } + LRESULT InsertItem(COMBOBOXEXITEM *item) { return SendMsg(CBEM_INSERTITEM, 0, (LPARAM)item); } #ifndef _UNICODE LRESULT InsertItem(COMBOBOXEXITEMW *item) { return SendMsg(CBEM_INSERTITEMW, 0, (LPARAM)item); } diff --git a/CPP/Windows/Control/ImageList.h b/CPP/Windows/Control/ImageList.h index 0d9c9313..19feb117 100644 --- a/CPP/Windows/Control/ImageList.h +++ b/CPP/Windows/Control/ImageList.h @@ -3,7 +3,7 @@ #ifndef __WINDOWS_CONTROL_IMAGE_LIST_H #define __WINDOWS_CONTROL_IMAGE_LIST_H -#include <commctrl.h> +#include <CommCtrl.h> #include "../Defs.h" diff --git a/CPP/Windows/Control/ListView.cpp b/CPP/Windows/Control/ListView.cpp index 6d916591..16cfd396 100644 --- a/CPP/Windows/Control/ListView.cpp +++ b/CPP/Windows/Control/ListView.cpp @@ -35,7 +35,7 @@ int CListView::InsertColumn(int columnIndex, LPCTSTR text, int width) { LVCOLUMN ci; ci.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; - ci.pszText = (LPTSTR)text; + ci.pszText = (LPTSTR)(void *)text; ci.iSubItem = columnIndex; ci.cx = width; return InsertColumn(columnIndex, &ci); @@ -47,7 +47,7 @@ int CListView::InsertItem(int index, LPCTSTR text) item.mask = LVIF_TEXT | LVIF_PARAM; item.iItem = index; item.lParam = index; - item.pszText = (LPTSTR)text; + item.pszText = (LPTSTR)(void *)text; item.iSubItem = 0; return InsertItem(&item); } @@ -57,7 +57,7 @@ int CListView::SetSubItem(int index, int subIndex, LPCTSTR text) LVITEM item; item.mask = LVIF_TEXT; item.iItem = index; - item.pszText = (LPTSTR)text; + item.pszText = (LPTSTR)(void *)text; item.iSubItem = subIndex; return SetItem(&item); } @@ -68,7 +68,7 @@ int CListView::InsertColumn(int columnIndex, LPCWSTR text, int width) { LVCOLUMNW ci; ci.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; - ci.pszText = (LPWSTR)text; + ci.pszText = (LPWSTR)(void *)text; ci.iSubItem = columnIndex; ci.cx = width; return InsertColumn(columnIndex, &ci); @@ -80,7 +80,7 @@ int CListView::InsertItem(int index, LPCWSTR text) item.mask = LVIF_TEXT | LVIF_PARAM; item.iItem = index; item.lParam = index; - item.pszText = (LPWSTR)text; + item.pszText = (LPWSTR)(void *)text; item.iSubItem = 0; return InsertItem(&item); } @@ -90,7 +90,7 @@ int CListView::SetSubItem(int index, int subIndex, LPCWSTR text) LVITEMW item; item.mask = LVIF_TEXT; item.iItem = index; - item.pszText = (LPWSTR)text; + item.pszText = (LPWSTR)(void *)text; item.iSubItem = subIndex; return SetItem(&item); } diff --git a/CPP/Windows/Control/ListView.h b/CPP/Windows/Control/ListView.h index 9a3abe70..a13b1041 100644 --- a/CPP/Windows/Control/ListView.h +++ b/CPP/Windows/Control/ListView.h @@ -5,7 +5,7 @@ #include "../../Common/MyWindows.h" -#include <commctrl.h> +#include <CommCtrl.h> #include "../Window.h" @@ -32,7 +32,8 @@ public: int InsertColumn(int columnIndex, const LVCOLUMN *columnInfo) { return ListView_InsertColumn(_window, columnIndex, columnInfo); } int InsertColumn(int columnIndex, LPCTSTR text, int width); - bool SetColumnOrderArray(int count, const int *columns) { return BOOLToBool(ListView_SetColumnOrderArray(_window, count, columns)); } + bool SetColumnOrderArray(int count, const int *columns) + { return BOOLToBool(ListView_SetColumnOrderArray(_window, count, (int *)(void *)columns)); } /* int GetNumColumns() diff --git a/CPP/Windows/Control/ProgressBar.h b/CPP/Windows/Control/ProgressBar.h index 38ebcb61..03743067 100644 --- a/CPP/Windows/Control/ProgressBar.h +++ b/CPP/Windows/Control/ProgressBar.h @@ -5,7 +5,7 @@ #include "../../Common/MyWindows.h" -#include <commctrl.h> +#include <CommCtrl.h> #include "../Window.h" diff --git a/CPP/Windows/Control/PropertyPage.h b/CPP/Windows/Control/PropertyPage.h index 4c4ddad9..b68fd8fe 100644 --- a/CPP/Windows/Control/PropertyPage.h +++ b/CPP/Windows/Control/PropertyPage.h @@ -5,7 +5,7 @@ #include "../../Common/MyWindows.h" -#include <prsht.h> +#include <PrSht.h> #include "Dialog.h" diff --git a/CPP/Windows/DLL.cpp b/CPP/Windows/DLL.cpp index d7f38375..cf5d01a3 100644 --- a/CPP/Windows/DLL.cpp +++ b/CPP/Windows/DLL.cpp @@ -4,6 +4,8 @@ #include "DLL.h" +#ifdef _WIN32 + #ifndef _UNICODE extern bool g_IsNT; #endif @@ -97,7 +99,7 @@ FString GetModuleDirPrefix() { int pos = s.ReverseFind_PathSepar(); if (pos >= 0) - s.DeleteFrom(pos + 1); + s.DeleteFrom((unsigned)(pos + 1)); } if (s.IsEmpty()) s = "." STRING_PATH_SEPARATOR; @@ -107,3 +109,83 @@ FString GetModuleDirPrefix() #endif }} + +#else + +#include <dlfcn.h> +#include <stdlib.h> + +namespace NWindows { +namespace NDLL { + +bool CLibrary::Free() throw() +{ + if (_module == NULL) + return true; + int ret = dlclose(_module); + if (ret != 0) + return false; + _module = NULL; + return true; +} + +static +// FARPROC +void * +local_GetProcAddress(HMODULE module, LPCSTR procName) +{ + void *ptr = NULL; + if (module) + { + ptr = dlsym(module, procName); + } + return ptr; +} + +bool CLibrary::Load(CFSTR path) throw() +{ + if (!Free()) + return false; + + int options = 0; + + #ifdef RTLD_LOCAL + options |= RTLD_LOCAL; + #endif + + #ifdef RTLD_NOW + options |= RTLD_NOW; + #endif + + #ifdef RTLD_GROUP + #if ! (defined(hpux) || defined(__hpux)) + options |= RTLD_GROUP; // mainly for solaris but not for HPUX + #endif + #endif + + void *handler = dlopen(path, options); + + if (handler) + { + // here we can transfer some settings to DLL + } + else + { + } + + _module = handler; + + return (_module != NULL); +} + +// FARPROC +void * CLibrary::GetProc(LPCSTR procName) const +{ + // return My_GetProcAddress(_module, procName); + return local_GetProcAddress(_module, procName); + // return NULL; +} + +}} + +#endif diff --git a/CPP/Windows/DLL.h b/CPP/Windows/DLL.h index 984a1d33..0c093eed 100644 --- a/CPP/Windows/DLL.h +++ b/CPP/Windows/DLL.h @@ -8,10 +8,12 @@ namespace NWindows { namespace NDLL { +#ifdef _WIN32 + #ifdef UNDER_CE -#define My_GetProcAddress(module, procName) ::GetProcAddressA(module, procName) +#define My_GetProcAddress(module, procName) (void *)::GetProcAddressA(module, procName) #else -#define My_GetProcAddress(module, procName) ::GetProcAddress(module, procName) +#define My_GetProcAddress(module, procName) (void *)::GetProcAddress(module, procName) #endif /* Win32: Don't call CLibrary::Free() and FreeLibrary() from another @@ -46,9 +48,33 @@ public: bool Free() throw(); bool LoadEx(CFSTR path, DWORD flags = LOAD_LIBRARY_AS_DATAFILE) throw(); bool Load(CFSTR path) throw(); - FARPROC GetProc(LPCSTR procName) const { return My_GetProcAddress(_module, procName); } + // FARPROC + void *GetProc(LPCSTR procName) const { return My_GetProcAddress(_module, procName); } }; +#else + +typedef void * HMODULE; +// typedef int (*FARPROC)(); +// typedef void *FARPROC; + +class CLibrary +{ + HMODULE _module; + + // CLASS_NO_COPY(CLibrary); +public: + CLibrary(): _module(NULL) {}; + ~CLibrary() { Free(); } + + bool Free() throw(); + bool Load(CFSTR path) throw(); + // FARPROC + void *GetProc(LPCSTR procName) const; // { return My_GetProcAddress(_module, procName); } +}; + +#endif + bool MyGetModuleFileName(FString &path); FString GetModuleDirPrefix(); diff --git a/CPP/Windows/Defs.h b/CPP/Windows/Defs.h index 281c40c3..1d96078d 100644 --- a/CPP/Windows/Defs.h +++ b/CPP/Windows/Defs.h @@ -7,10 +7,11 @@ #ifdef _WIN32 inline bool LRESULTToBool(LRESULT v) { return (v != FALSE); } -inline bool BOOLToBool(BOOL v) { return (v != FALSE); } inline BOOL BoolToBOOL(bool v) { return (v ? TRUE: FALSE); } #endif +inline bool BOOLToBool(BOOL v) { return (v != FALSE); } + inline VARIANT_BOOL BoolToVARIANT_BOOL(bool v) { return (v ? VARIANT_TRUE: VARIANT_FALSE); } inline bool VARIANT_BOOLToBool(VARIANT_BOOL v) { return (v != VARIANT_FALSE); } diff --git a/CPP/Windows/ErrorMsg.cpp b/CPP/Windows/ErrorMsg.cpp index b86c0b39..bfa21e50 100644 --- a/CPP/Windows/ErrorMsg.cpp +++ b/CPP/Windows/ErrorMsg.cpp @@ -2,21 +2,25 @@ #include "StdAfx.h" -#ifndef _UNICODE +#if !defined(_UNICODE) || !defined(_WIN32) #include "../Common/StringConvert.h" #endif #include "ErrorMsg.h" -#ifndef _UNICODE +#ifdef _WIN32 +#if !defined(_UNICODE) extern bool g_IsNT; #endif +#endif namespace NWindows { namespace NError { static bool MyFormatMessage(DWORD errorCode, UString &message) { + #ifdef _WIN32 + LPVOID msgBuf; #ifndef _UNICODE if (!g_IsNT) @@ -38,8 +42,63 @@ static bool MyFormatMessage(DWORD errorCode, UString &message) } ::LocalFree(msgBuf); return true; + + #else // _WIN32 + + AString m; + + const char *s = NULL; + + switch ((Int32)errorCode) + { + // case ERROR_NO_MORE_FILES : s = "No more files"; break; + // case ERROR_DIRECTORY : s = "Error Directory"; break; + case E_NOTIMPL : s = "E_NOTIMPL : Not implemented"; break; + case E_NOINTERFACE : s = "E_NOINTERFACE : No such interface supported"; break; + case E_ABORT : s = "E_ABORT : Operation aborted"; break; + case E_FAIL : s = "E_FAIL : Unspecified error"; break; + + case STG_E_INVALIDFUNCTION : s = "STG_E_INVALIDFUNCTION"; break; + case CLASS_E_CLASSNOTAVAILABLE : s = "CLASS_E_CLASSNOTAVAILABLE"; break; + + case E_OUTOFMEMORY : s = "E_OUTOFMEMORY : Can't allocate required memory"; break; + case E_INVALIDARG : s = "E_INVALIDARG : One or more arguments are invalid"; break; + + // case MY__E_ERROR_NEGATIVE_SEEK : s = "MY__E_ERROR_NEGATIVE_SEEK"; break; + default: + break; + } + + /* strerror() for unknow errors still shows message "Unknown error -12345678") + So we must trasfer error codes before strerror() */ + if (!s) + { + if ((errorCode & 0xFFFF0000) == (UInt32)((MY__FACILITY__WRes << 16) | 0x80000000)) + errorCode &= 0xFFFF; + else if ((errorCode & ((UInt32)1 << 31))) + return false; // we will show hex error later for that case + + s = strerror((int)errorCode); + + // if (!s) + { + m += "errno="; + m.Add_UInt32(errorCode); + if (s) + m += " : "; + } + } + + if (s) + m += s; + + MultiByteToUnicodeString2(message, m); + return true; + + #endif } + UString MyFormatMessage(DWORD errorCode) { UString m; diff --git a/CPP/Windows/ErrorMsg.h b/CPP/Windows/ErrorMsg.h index 0957c696..01204eb9 100644 --- a/CPP/Windows/ErrorMsg.h +++ b/CPP/Windows/ErrorMsg.h @@ -9,6 +9,7 @@ namespace NWindows { namespace NError { UString MyFormatMessage(DWORD errorCode); +inline UString MyFormatMessage(HRESULT errorCode) { return MyFormatMessage((DWORD)errorCode); } }} diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp index 62b11c10..c06e7f37 100644 --- a/CPP/Windows/FileDir.cpp +++ b/CPP/Windows/FileDir.cpp @@ -2,8 +2,21 @@ #include "StdAfx.h" -#ifndef _UNICODE + +#ifndef _WIN32 +#include <stdio.h> +#include <errno.h> +#include <limits.h> +#include <unistd.h> +#include <time.h> +#include <utime.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> + #include "../Common/StringConvert.h" +#include "../Common/C_FileIO.h" +#include "TimeUtils.h" #endif #include "FileDir.h" @@ -22,6 +35,8 @@ namespace NWindows { namespace NFile { namespace NDir { +#ifdef _WIN32 + #ifndef UNDER_CE bool GetWindowsDir(FString &path) @@ -67,7 +82,8 @@ bool GetSystemDir(FString &path) } return (needLength > 0 && needLength <= MAX_PATH); } -#endif +#endif // UNDER_CE + bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { @@ -102,6 +118,8 @@ bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const return res; } + + bool SetFileAttrib(CFSTR path, DWORD attrib) { #ifndef _UNICODE @@ -131,8 +149,10 @@ bool SetFileAttrib(CFSTR path, DWORD attrib) bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) { + #ifdef _WIN32 if ((attrib & 0xF0000000) != 0) attrib &= 0x3FFF; + #endif return SetFileAttrib(path, attrib); } @@ -163,6 +183,7 @@ bool RemoveDir(CFSTR path) return false; } + bool MyMoveFile(CFSTR oldFile, CFSTR newFile) { #ifndef _UNICODE @@ -175,8 +196,10 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile) #endif { IF_USE_MAIN_PATH_2(oldFile, newFile) + { if (::MoveFileW(fs2us(oldFile), fs2us(newFile))) return true; + } #ifdef WIN_LONG_PATH if (USE_SUPER_PATH_2) { @@ -190,7 +213,6 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile) } #ifndef UNDER_CE - EXTERN_C_BEGIN typedef BOOL (WINAPI *Func_CreateHardLinkW)( LPCWSTR lpFileName, @@ -198,6 +220,7 @@ typedef BOOL (WINAPI *Func_CreateHardLinkW)( LPSECURITY_ATTRIBUTES lpSecurityAttributes ); EXTERN_C_END +#endif // UNDER_CE bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName) { @@ -215,12 +238,14 @@ bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName) #endif { Func_CreateHardLinkW my_CreateHardLinkW = (Func_CreateHardLinkW) - ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW"); + (void *)::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW"); if (!my_CreateHardLinkW) return false; IF_USE_MAIN_PATH_2(newFileName, existFileName) + { if (my_CreateHardLinkW(fs2us(newFileName), fs2us(existFileName), NULL)) return true; + } #ifdef WIN_LONG_PATH if (USE_SUPER_PATH_2) { @@ -233,7 +258,6 @@ bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName) return false; } -#endif /* WinXP-64 CreateDir(): @@ -333,6 +357,10 @@ static bool CreateDir2(CFSTR path) return fi.IsDir(); } +#endif // _WIN32 + +static bool CreateDir2(CFSTR path); + bool CreateComplexDir(CFSTR _path) { #ifdef _WIN32 @@ -348,11 +376,21 @@ bool CreateComplexDir(CFSTR _path) if (IsDriveRootPath_SuperAllowed(_path)) return false; - unsigned prefixSize = GetRootPrefixSize(_path); + const unsigned prefixSize = GetRootPrefixSize(_path); - #endif + #endif // UNDER_CE + + #else // _WIN32 + + // Posix + NFind::CFileInfo fi; + if (fi.Find(_path)) + { + if (fi.IsDir()) + return true; + } - #endif + #endif // _WIN32 FString path (_path); @@ -365,7 +403,7 @@ bool CreateComplexDir(CFSTR _path) } const FString path2 (path); - pos = path.Len(); + pos = (int)path.Len(); for (;;) { @@ -384,17 +422,17 @@ bool CreateComplexDir(CFSTR _path) return false; #endif - path.DeleteFrom(pos); + path.DeleteFrom((unsigned)pos); } while (pos < (int)path2.Len()) { - int pos2 = NName::FindSepar(path2.Ptr(pos + 1)); + int pos2 = NName::FindSepar(path2.Ptr((unsigned)pos + 1)); if (pos2 < 0) - pos = path2.Len(); + pos = (int)path2.Len(); else pos += 1 + pos2; - path.SetFrom(path2, pos); + path.SetFrom(path2, (unsigned)pos); if (!CreateDir(path)) return false; } @@ -402,6 +440,9 @@ bool CreateComplexDir(CFSTR _path) return true; } + +#ifdef _WIN32 + bool DeleteFileAlways(CFSTR path) { /* If alt stream, we also need to clear READ-ONLY attribute of main file before delete. @@ -412,7 +453,7 @@ bool DeleteFileAlways(CFSTR path) && (attrib & FILE_ATTRIBUTE_DIRECTORY) == 0 && (attrib & FILE_ATTRIBUTE_READONLY) != 0) { - if (!SetFileAttrib(path, attrib & ~FILE_ATTRIBUTE_READONLY)) + if (!SetFileAttrib(path, attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY)) return false; } } @@ -443,6 +484,8 @@ bool DeleteFileAlways(CFSTR path) return false; } + + bool RemoveDirWithSubItems(const FString &path) { bool needRemoveSubItems = true; @@ -466,7 +509,9 @@ bool RemoveDirWithSubItems(const FString &path) const unsigned prefixSize = s.Len(); NFind::CEnumerator enumerator; enumerator.SetDirPrefix(s); - NFind::CFileInfo fi; + NFind::CDirEntry fi; + bool isError = false; + DWORD lastError = 0; while (enumerator.Next(fi)) { s.DeleteFrom(prefixSize); @@ -474,18 +519,32 @@ bool RemoveDirWithSubItems(const FString &path) if (fi.IsDir()) { if (!RemoveDirWithSubItems(s)) - return false; + { + lastError = GetLastError(); + isError = true; + } } else if (!DeleteFileAlways(s)) - return false; + { + lastError = GetLastError(); + isError = false; + } + } + if (isError) + { + SetLastError(lastError); + return false; } } + // we clear read-only attrib to remove read-only dir if (!SetFileAttrib(path, 0)) return false; return RemoveDir(path); } +#endif // _WIN32 + #ifdef UNDER_CE bool MyGetFullPathName(CFSTR path, FString &resFullPath) @@ -501,6 +560,8 @@ bool MyGetFullPathName(CFSTR path, FString &resFullPath) return GetFullPath(path, resFullPath); } +#ifdef _WIN32 + bool SetCurrentDir(CFSTR path) { // SetCurrentDirectory doesn't support \\?\ prefix @@ -516,9 +577,11 @@ bool SetCurrentDir(CFSTR path) } } + bool GetCurrentDir(FString &path) { path.Empty(); + DWORD needLength; #ifndef _UNICODE if (!g_IsNT) @@ -539,7 +602,9 @@ bool GetCurrentDir(FString &path) return (needLength > 0 && needLength <= MAX_PATH); } -#endif +#endif // _WIN32 +#endif // UNDER_CE + bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName) { @@ -547,8 +612,9 @@ bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName if (!res) resDirPrefix = path; int pos = resDirPrefix.ReverseFind_PathSepar(); - resFileName = resDirPrefix.Ptr(pos + 1); - resDirPrefix.DeleteFrom(pos + 1); + pos++; + resFileName = resDirPrefix.Ptr((unsigned)pos); + resDirPrefix.DeleteFrom((unsigned)pos); return res; } @@ -560,6 +626,7 @@ bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix) bool MyGetTempPath(FString &path) { + #ifdef _WIN32 path.Empty(); DWORD needLength; #ifndef _UNICODE @@ -579,11 +646,27 @@ bool MyGetTempPath(FString &path) path = us2fs(s); } return (needLength > 0 && needLength <= MAX_PATH); + + #else + + // FIXME: improve that code + path = "/tmp/"; + if (!NFind::DoesDirExist_FollowLink(path)) + path = "./"; + return true; + #endif } + static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COutFile *outFile) { - UInt32 d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId(); + UInt32 d = + #ifdef _WIN32 + (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId(); + #else + (UInt32)(time(NULL) << 12) ^ ((UInt32)getppid() << 14) ^ (UInt32)(getpid()); + #endif + for (unsigned i = 0; i < 100; i++) { path = prefix; @@ -670,7 +753,7 @@ bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) // DWORD attrib = 0; if (deleteDestBefore) { - if (NFind::DoesFileExist(name)) + if (NFind::DoesFileExist_Raw(name)) { // attrib = NFind::GetFileAttrib(name); if (!DeleteFileAlways(name)) @@ -690,6 +773,7 @@ bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) */ } +#ifdef _WIN32 bool CTempDir::Create(CFSTR prefix) { if (!Remove()) @@ -710,5 +794,285 @@ bool CTempDir::Remove() _mustBeDeleted = !RemoveDirWithSubItems(_path); return !_mustBeDeleted; } +#endif + + + +#ifndef _WIN32 + +bool RemoveDir(CFSTR path) +{ + return (rmdir(path) == 0); +} + + +static BOOL My__CopyFile(CFSTR oldFile, CFSTR newFile) +{ + NWindows::NFile::NIO::COutFile outFile; + if (!outFile.Create(newFile, false)) + return FALSE; + + NWindows::NFile::NIO::CInFile inFile; + if (!inFile.Open(oldFile)) + return FALSE; + + char buf[1 << 14]; + + for (;;) + { + const ssize_t num = inFile.read_part(buf, sizeof(buf)); + if (num == 0) + return TRUE; + if (num < 0) + return FALSE; + size_t processed; + const ssize_t num2 = outFile.write_full(buf, (size_t)num, processed); + if (num2 != num || processed != (size_t)num) + return FALSE; + } +} + + +bool MyMoveFile(CFSTR oldFile, CFSTR newFile) +{ + int res = rename(oldFile, newFile); + if (res == 0) + return true; + if (errno != EXDEV) // (oldFile and newFile are not on the same mounted filesystem) + return false; + + if (My__CopyFile(oldFile, newFile) == FALSE) + return false; + + struct stat info_file; + res = stat(oldFile, &info_file); + if (res != 0) + return false; + + /* + ret = chmod(dst,info_file.st_mode & g_umask.mask); + */ + return (unlink(oldFile) == 0); +} + + +bool CreateDir(CFSTR path) +{ + return (mkdir(path, 0777) == 0); // change it +} + +static bool CreateDir2(CFSTR path) +{ + return (mkdir(path, 0777) == 0); // change it +} + + +bool DeleteFileAlways(CFSTR path) +{ + return (remove(path) == 0); +} + +bool SetCurrentDir(CFSTR path) +{ + return (chdir(path) == 0); +} + + +bool GetCurrentDir(FString &path) +{ + path.Empty(); + + #define MY__PATH_MAX PATH_MAX + // #define MY__PATH_MAX 1024 + + char s[MY__PATH_MAX + 1]; + char *res = getcwd(s, MY__PATH_MAX); + if (!res) + { + // if (errno != ERANGE) + return false; + } + path = fas2fs(s); + return true; +} + + +static void FILETME_To_timespec(const FILETIME *ft, timespec &ts) +{ + if (ft) + { + const Int64 sec = NTime::FileTimeToUnixTime64(*ft); + // time_t is long + const time_t sec2 = (time_t)sec; + if (sec2 == sec) + { + ts.tv_sec = sec2; + const UInt64 winTime = (((UInt64)ft->dwHighDateTime) << 32) + ft->dwLowDateTime; + ts.tv_nsec = (long)((winTime % 10000000) * 100); + return; + } + } + // else + { + ts.tv_sec = 0; + // ts.tv_nsec = UTIME_NOW; // set to the current time + ts.tv_nsec = UTIME_OMIT; // keep old timesptamp + } +} + + + + +bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) +{ + // need testing + /* + struct utimbuf buf; + struct stat st; + UNUSED_VAR(cTime) + + printf("\nstat = %s\n", path); + int ret = stat(path, &st); + + if (ret == 0) + { + buf.actime = st.st_atime; + buf.modtime = st.st_mtime; + } + else + { + time_t cur_time = time(0); + buf.actime = cur_time; + buf.modtime = cur_time; + } + + if (aTime) + { + UInt32 ut; + if (NTime::FileTimeToUnixTime(*aTime, ut)) + buf.actime = ut; + } + + if (mTime) + { + UInt32 ut; + if (NTime::FileTimeToUnixTime(*mTime, ut)) + buf.modtime = ut; + } + + return utime(path, &buf) == 0; + */ + + // if (!aTime && !mTime) return true; + + struct timespec times[2]; + UNUSED_VAR(cTime) + + FILETME_To_timespec(aTime, times[0]); + FILETME_To_timespec(mTime, times[1]); + + const int flags = 0; // follow link + // = AT_SYMLINK_NOFOLLOW; // don't follow link + return utimensat(AT_FDCWD, path, times, flags) == 0; +} + + + +struct C_umask +{ + mode_t mask; + + C_umask() + { + /* by security reasons we restrict attributes according + with process's file mode creation mask (umask) */ + const mode_t um = umask(0); // octal :0022 is expected + mask = 0777 & (~um); // octal: 0755 is expected + umask(um); // restore the umask + // printf("\n umask = 0%03o mask = 0%03o\n", um, mask); + + // mask = 0777; // debug we can disable the restriction: + } +}; + +static C_umask g_umask; + +// #define PRF(x) x; +#define PRF(x) + +#define TRACE_SetFileAttrib(msg) \ + PRF(printf("\nSetFileAttrib(%s, %x) : %s\n", (const char *)path, attrib, msg)); + +#define TRACE_chmod(s, mode) \ + PRF(printf("\n chmod(%s, %o)\n", (const char *)path, (unsigned)(mode))); + + +bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) +{ + TRACE_SetFileAttrib(""); + + struct stat st; + + bool use_lstat = true; + if (use_lstat) + { + if (lstat(path, &st) != 0) + { + TRACE_SetFileAttrib("bad lstat()"); + return false; + } + } + else + { + if (stat(path, &st) != 0) + { + TRACE_SetFileAttrib("bad stat()"); + return false; + } + } + + if (attrib & FILE_ATTRIBUTE_UNIX_EXTENSION) + { + st.st_mode = attrib >> 16; + if (S_ISDIR(st.st_mode)) + { + // user/7z must be able to create files in this directory + st.st_mode |= (S_IRUSR | S_IWUSR | S_IXUSR); + } + else if (!S_ISREG(st.st_mode)) + return true; + } + else if (S_ISLNK(st.st_mode)) + { + // change it + SetLastError(ENOSYS); + return false; + } + else + { + // Only Windows Attributes + if (S_ISDIR(st.st_mode) + || (attrib & FILE_ATTRIBUTE_READONLY) == 0) + return true; + st.st_mode &= ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); // octal: ~0222; // disable write permissions + } + + TRACE_chmod(path, (st.st_mode) & g_umask.mask); + int res = chmod(path, (st.st_mode) & g_umask.mask); + + // TRACE_SetFileAttrib("OK") + return (res == 0); +} + + +bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName) +{ + PRF(printf("\nhard link() %s -> %s\n", newFileName, existFileName)); + return (link(existFileName, newFileName) == 0); +} + +#endif // !_WIN32 + +// #endif }}} diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h index 154ed973..6d6ddeaf 100644 --- a/CPP/Windows/FileDir.h +++ b/CPP/Windows/FileDir.h @@ -17,6 +17,8 @@ bool GetSystemDir(FString &path); bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); +#ifdef _WIN32 + bool SetFileAttrib(CFSTR path, DWORD attrib); /* @@ -26,6 +28,8 @@ bool SetFileAttrib(CFSTR path, DWORD attrib); bits that are related to current system only. */ +#endif + bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib); @@ -61,7 +65,7 @@ bool GetCurrentDir(FString &resultPath); bool MyGetTempPath(FString &resultPath); -class CTempFile +class CTempFile MY_UNCOPYABLE { bool _mustBeDeleted; FString _path; @@ -76,7 +80,9 @@ public: bool MoveTo(CFSTR name, bool deleteDestBefore); }; -class CTempDir + +#ifdef _WIN32 +class CTempDir MY_UNCOPYABLE { bool _mustBeDeleted; FString _path; @@ -88,9 +94,11 @@ public: bool Create(CFSTR namePrefix) ; bool Remove(); }; +#endif + #if !defined(UNDER_CE) -class CCurrentDirRestorer +class CCurrentDirRestorer MY_UNCOPYABLE { FString _path; public: diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp index b9692b81..8ef0f7b6 100644 --- a/CPP/Windows/FileFind.cpp +++ b/CPP/Windows/FileFind.cpp @@ -2,8 +2,11 @@ #include "StdAfx.h" -#ifndef _UNICODE -#include "../Common/StringConvert.h" +// #include <stdio.h> + +#ifndef _WIN32 +#include <fcntl.h> /* Definition of AT_* constants */ +#include "TimeUtils.h" #endif #include "FileFind.h" @@ -34,27 +37,51 @@ typedef struct WCHAR cStreamName[MAX_PATH + 36]; } MY_WIN32_FIND_STREAM_DATA, *MY_PWIN32_FIND_STREAM_DATA; -typedef WINBASEAPI HANDLE (WINAPI *FindFirstStreamW_Ptr)(LPCWSTR fileName, MY_STREAM_INFO_LEVELS infoLevel, +typedef HANDLE (WINAPI *FindFirstStreamW_Ptr)(LPCWSTR fileName, MY_STREAM_INFO_LEVELS infoLevel, LPVOID findStreamData, DWORD flags); -typedef WINBASEAPI BOOL (APIENTRY *FindNextStreamW_Ptr)(HANDLE findStream, LPVOID findStreamData); +typedef BOOL (APIENTRY *FindNextStreamW_Ptr)(HANDLE findStream, LPVOID findStreamData); EXTERN_C_END -#endif +#endif // defined(_WIN32) && !defined(UNDER_CE) + namespace NWindows { namespace NFile { + +#ifdef _WIN32 #ifdef SUPPORT_DEVICE_FILE namespace NSystem { bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); } #endif +#endif namespace NFind { +#define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0; + +void CFileInfoBase::ClearBase() throw() +{ + Size = 0; + MY_CLEAR_FILETIME(CTime); + MY_CLEAR_FILETIME(ATime); + MY_CLEAR_FILETIME(MTime); + Attrib = 0; + // ReparseTag = 0; + IsAltStream = false; + IsDevice = false; + + #ifndef _WIN32 + ino = 0; + nlink = 0; + mode = 0; + #endif +} + bool CFileInfo::IsDots() const throw() { if (!IsDir() || Name.IsEmpty()) @@ -64,12 +91,17 @@ bool CFileInfo::IsDots() const throw() return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == '.'); } + +#ifdef _WIN32 + + #define WIN_FD_TO_MY_FI(fi, fd) \ fi.Attrib = fd.dwFileAttributes; \ fi.CTime = fd.ftCreationTime; \ fi.ATime = fd.ftLastAccessTime; \ fi.MTime = fd.ftLastWriteTime; \ fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; \ + /* fi.ReparseTag = fd.dwReserved0; */ \ fi.IsAltStream = false; \ fi.IsDevice = false; @@ -91,7 +123,6 @@ static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATAW &fd, CFil } #ifndef _UNICODE - static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) { WIN_FD_TO_MY_FI(fi, fd); @@ -143,7 +174,8 @@ WinXP-64 FindFirstFile(): \\Server\Share_RootDrive - ERROR_INVALID_NAME \\Server\Share_RootDrive\ - ERROR_INVALID_NAME - c:\* - ERROR_FILE_NOT_FOUND, if thare are no item in that folder + e:\* - ERROR_FILE_NOT_FOUND, if there are no items in that root folder + w:\* - ERROR_PATH_NOT_FOUND, if there is no such drive w: */ bool CFindFile::FindFirst(CFSTR path, CFileInfo &fi) @@ -210,12 +242,13 @@ bool CFindFile::FindNext(CFileInfo &fi) static FindFirstStreamW_Ptr g_FindFirstStreamW; static FindNextStreamW_Ptr g_FindNextStreamW; -struct CFindStreamLoader +static struct CFindStreamLoader { CFindStreamLoader() { - g_FindFirstStreamW = (FindFirstStreamW_Ptr)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "FindFirstStreamW"); - g_FindNextStreamW = (FindNextStreamW_Ptr)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "FindNextStreamW"); + HMODULE hm = ::GetModuleHandleA("kernel32.dll"); + g_FindFirstStreamW = (FindFirstStreamW_Ptr)(void *)::GetProcAddress(hm, "FindFirstStreamW"); + g_FindNextStreamW = (FindNextStreamW_Ptr)(void *)::GetProcAddress(hm, "FindNextStreamW"); } } g_FindStreamLoader; @@ -245,7 +278,7 @@ UString CStreamInfo::GetReducedName2() const static void Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(const MY_WIN32_FIND_STREAM_DATA &sd, CStreamInfo &si) { - si.Size = sd.StreamSize.QuadPart; + si.Size = (UInt64)sd.StreamSize.QuadPart; si.Name = sd.cStreamName; } @@ -336,19 +369,6 @@ bool CStreamEnumerator::Next(CStreamInfo &si, bool &found) #endif -#define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0; - -void CFileInfoBase::ClearBase() throw() -{ - Size = 0; - MY_CLEAR_FILETIME(CTime); - MY_CLEAR_FILETIME(ATime); - MY_CLEAR_FILETIME(MTime); - Attrib = 0; - IsAltStream = false; - IsDevice = false; -} - /* WinXP-64 GetFileAttributes(): If the function fails, it returns INVALID_FILE_ATTRIBUTES and use GetLastError() to get error code @@ -416,7 +436,7 @@ also we support paths that are not supported by FindFirstFile: c::stream - Name = c::stream */ -bool CFileInfo::Find(CFSTR path) +bool CFileInfo::Find(CFSTR path, bool followLink) { #ifdef SUPPORT_DEVICE_FILE if (IsDevicePath(path)) @@ -454,7 +474,7 @@ bool CFileInfo::Find(CFSTR path) { UString streamName = fs2us(path + (unsigned)colonPos); FString filePath (path); - filePath.DeleteFrom(colonPos); + filePath.DeleteFrom((unsigned)colonPos); /* we allow both cases: name:stream name:stream:$DATA @@ -467,7 +487,7 @@ bool CFileInfo::Find(CFSTR path) bool isOk = true; if (IsDrivePath2(filePath) && - (colonPos == 2 || colonPos == 3 && filePath[2] == '\\')) + (colonPos == 2 || (colonPos == 3 && filePath[2] == '\\'))) { // FindFirstFile doesn't work for "c:\" and for "c:" (if current dir is ROOT) ClearBase(); @@ -476,11 +496,11 @@ bool CFileInfo::Find(CFSTR path) Name = filePath; } else - isOk = Find(filePath); + isOk = Find(filePath, followLink); // check it (followLink) if (isOk) { - Attrib &= ~(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT); + Attrib &= ~(DWORD)(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT); Size = 0; CStreamEnumerator enumerator(filePath); for (;;) @@ -536,11 +556,15 @@ bool CFileInfo::Find(CFSTR path) ClearBase(); Attrib = attrib; Name = path + rootSize; - Name.DeleteFrom(2); // we don't need backslash (C:) + Name.DeleteFrom(2); + if (!Fill_From_ByHandleFileInfo(path)) + { + } return true; } } else if (IS_PATH_SEPAR(path[0])) + { if (path[1] == 0) { DWORD attrib = GetFileAttrib(path); @@ -559,10 +583,15 @@ bool CFileInfo::Find(CFSTR path) { if (NName::FindSepar(path + prefixSize) < 0) { + if (Fill_From_ByHandleFileInfo(path)) + { + Name = path + prefixSize; + return true; + } + FString s (path); s.Add_PathSepar(); s += '*'; // CHAR_ANY_MASK - bool isOK = false; if (finder.FindFirst(s, *this)) { @@ -577,7 +606,7 @@ bool CFileInfo::Find(CFSTR path) } { DWORD attrib = GetFileAttrib(path); - if (isOK || attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0) + if (isOK || (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)) { ClearBase(); if (attrib != INVALID_FILE_ATTRIBUTES) @@ -592,23 +621,105 @@ bool CFileInfo::Find(CFSTR path) } } } + } } #endif - return finder.FindFirst(path, *this); + bool res = finder.FindFirst(path, *this); + if (!followLink + || !res + || !HasReparsePoint()) + return res; + + // return FollowReparse(path, IsDir()); + return Fill_From_ByHandleFileInfo(path); +} + +bool CFileInfo::Fill_From_ByHandleFileInfo(CFSTR path) +{ + BY_HANDLE_FILE_INFORMATION info; + if (!NIO::CFileBase::GetFileInformation(path, &info)) + return false; + { + Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; + CTime = info.ftCreationTime; + ATime = info.ftLastAccessTime; + MTime = info.ftLastWriteTime; + Attrib = info.dwFileAttributes; + return true; + } } +/* +bool CFileInfo::FollowReparse(CFSTR path, bool isDir) +{ + if (isDir) + { + FString prefix = path; + prefix.Add_PathSepar(); + + // "folder/." refers to folder itself. So we can't use that path + // we must use enumerator and search "." item + CEnumerator enumerator; + enumerator.SetDirPrefix(prefix); + for (;;) + { + CFileInfo fi; + if (!enumerator.NextAny(fi)) + break; + if (fi.Name.IsEqualTo_Ascii_NoCase(".")) + { + // we can copy preperies; + CTime = fi.CTime; + ATime = fi.ATime; + MTime = fi.MTime; + Attrib = fi.Attrib; + Size = fi.Size; + return true; + } + break; + } + // LastError(lastError); + return false; + } + + { + NIO::CInFile inFile; + if (inFile.Open(path)) + { + BY_HANDLE_FILE_INFORMATION info; + if (inFile.GetFileInformation(&info)) + { + ClearBase(); + Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; + CTime = info.ftCreationTime; + ATime = info.ftLastAccessTime; + MTime = info.ftLastWriteTime; + Attrib = info.dwFileAttributes; + return true; + } + } + return false; + } +} +*/ -bool DoesFileExist(CFSTR name) +bool DoesFileExist_Raw(CFSTR name) { CFileInfo fi; return fi.Find(name) && !fi.IsDir(); } -bool DoesDirExist(CFSTR name) +bool DoesFileExist_FollowLink(CFSTR name) +{ + CFileInfo fi; + return fi.Find_FollowLink(name) && !fi.IsDir(); +} + +bool DoesDirExist(CFSTR name, bool followLink) { CFileInfo fi; - return fi.Find(name) && fi.IsDir(); + return fi.Find(name, followLink) && fi.IsDir(); } bool DoesFileOrDirExist(CFSTR name) @@ -645,15 +756,46 @@ bool CEnumerator::Next(CFileInfo &fi) bool CEnumerator::Next(CFileInfo &fi, bool &found) { + /* + for (;;) + { + if (!NextAny(fi)) + break; + if (!fi.IsDots()) + { + found = true; + return true; + } + } + */ + if (Next(fi)) { found = true; return true; } + found = false; - return (::GetLastError() == ERROR_NO_MORE_FILES); + DWORD lastError = ::GetLastError(); + if (_findFile.IsHandleAllocated()) + return (lastError == ERROR_NO_MORE_FILES); + // we support the case for empty root folder: FindFirstFile("c:\\*") returns ERROR_FILE_NOT_FOUND + if (lastError == ERROR_FILE_NOT_FOUND) + return true; + if (lastError == ERROR_ACCESS_DENIED) + { + // here we show inaccessible root system folder as empty folder to eliminate redundant user warnings + const char *s = "System Volume Information" STRING_PATH_SEPARATOR "*"; + const int len = (int)strlen(s); + const int delta = (int)_wildcard.Len() - len; + if (delta == 0 || (delta > 0 && IS_PATH_SEPAR(_wildcard[(unsigned)delta - 1]))) + if (StringsAreEqual_Ascii(_wildcard.Ptr((unsigned)delta), s)) + return true; + } + return false; } + //////////////////////////////// // CFindChangeNotification // FindFirstChangeNotification can return 0. MSDN doesn't tell about it. @@ -744,6 +886,331 @@ bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings) } } -#endif +#endif // UNDER_CE + + + +#else // _WIN32 + +// ---------- POSIX ---------- + +static int MY__lstat(CFSTR path, struct stat *st, bool followLink) +{ + memset(st, 0, sizeof(*st)); + int res; + // #ifdef ENV_HAVE_LSTAT + if (/* global_use_lstat && */ !followLink) + { + // printf("\nlstat\n"); + res = lstat(path, st); + } + else + // #endif + { + // printf("\nstat\n"); + res = stat(path, st); + } + /* + printf("\nres = %d\n", res); + printf("\n st_dev = %lld \n", (long long)(st->st_dev)); + printf("\n st_ino = %lld \n", (long long)(st->st_ino)); + printf("\n st_mode = %lld \n", (long long)(st->st_mode)); + printf("\n st_nlink = %lld \n", (long long)(st->st_nlink)); + printf("\n st_uid = %lld \n", (long long)(st->st_uid)); + printf("\n st_gid = %lld \n", (long long)(st->st_gid)); + printf("\n st_size = %lld \n", (long long)(st->st_size)); + printf("\n st_blksize = %lld \n", (long long)(st->st_blksize)); + printf("\n st_blocks = %lld \n", (long long)(st->st_blocks)); + */ + + return res; +} + + +static const char *Get_Name_from_Path(CFSTR path) throw() +{ + size_t len = strlen(path); + if (len == 0) + return path; + const char *p = path + len - 1; + { + if (p == path) + return path; + p--; + } + for (;;) + { + char c = *p; + if (IS_PATH_SEPAR(c)) + return p + 1; + if (p == path) + return path; + p--; + } +} + + +void timespec_To_FILETIME(const MY_ST_TIMESPEC &ts, FILETIME &ft) +{ + UInt64 v = NTime::UnixTime64ToFileTime64(ts.tv_sec) + ((UInt64)ts.tv_nsec / 100); + ft.dwLowDateTime = (DWORD)v; + ft.dwHighDateTime = (DWORD)(v >> 32); +} + +UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode) +{ + UInt32 attrib = S_ISDIR(mode) ? + FILE_ATTRIBUTE_DIRECTORY : + FILE_ATTRIBUTE_ARCHIVE; + if ((mode & 0222) == 0) // S_IWUSR in p7zip + attrib |= FILE_ATTRIBUTE_READONLY; + return attrib | FILE_ATTRIBUTE_UNIX_EXTENSION | ((mode & 0xFFFF) << 16); +} + +/* +UInt32 Get_WinAttrib_From_stat(const struct stat &st) +{ + UInt32 attrib = S_ISDIR(st.st_mode) ? + FILE_ATTRIBUTE_DIRECTORY : + FILE_ATTRIBUTE_ARCHIVE; + + if ((st.st_mode & 0222) == 0) // check it !!! + attrib |= FILE_ATTRIBUTE_READONLY; + + attrib |= FILE_ATTRIBUTE_UNIX_EXTENSION + ((st.st_mode & 0xFFFF) << 16); + return attrib; +} +*/ + +void CFileInfo::SetFrom_stat(const struct stat &st) +{ + IsDevice = false; + + if (S_ISDIR(st.st_mode)) + { + Size = 0; + } + else + { + Size = (UInt64)st.st_size; // for a symbolic link, size = size of filename + } + + Attrib = Get_WinAttribPosix_From_PosixMode(st.st_mode); + + // NTime::UnixTimeToFileTime(st.st_ctime, CTime); + // NTime::UnixTimeToFileTime(st.st_mtime, MTime); + // NTime::UnixTimeToFileTime(st.st_atime, ATime); + #ifdef __APPLE__ + timespec_To_FILETIME(st.st_ctimespec, CTime); + timespec_To_FILETIME(st.st_mtimespec, MTime); + timespec_To_FILETIME(st.st_atimespec, ATime); + #else + timespec_To_FILETIME(st.st_ctim, CTime); + timespec_To_FILETIME(st.st_mtim, MTime); + timespec_To_FILETIME(st.st_atim, ATime); + #endif + + dev = st.st_dev; + ino = st.st_ino; + nlink = st.st_nlink; + mode = st.st_mode; +} + +bool CFileInfo::Find_DontFill_Name(CFSTR path, bool followLink) +{ + struct stat st; + if (MY__lstat(path, &st, followLink) != 0) + return false; + SetFrom_stat(st); + return true; +} + + +bool CFileInfo::Find(CFSTR path, bool followLink) +{ + // printf("\nCEnumerator::Find() name = %s\n", path); + if (!Find_DontFill_Name(path, followLink)) + return false; + + // printf("\nOK\n"); + + Name = Get_Name_from_Path(path); + if (!Name.IsEmpty()) + { + char c = Name.Back(); + if (IS_PATH_SEPAR(c)) + Name.DeleteBack(); + } + return true; +} + + +bool DoesFileExist_Raw(CFSTR name) +{ + // FIXME for symbolic links. + struct stat st; + if (MY__lstat(name, &st, false) != 0) + return false; + return !S_ISDIR(st.st_mode); +} + +bool DoesFileExist_FollowLink(CFSTR name) +{ + // FIXME for symbolic links. + struct stat st; + if (MY__lstat(name, &st, true) != 0) + return false; + return !S_ISDIR(st.st_mode); +} + +bool DoesDirExist(CFSTR name, bool followLink) +{ + struct stat st; + if (MY__lstat(name, &st, followLink) != 0) + return false; + return S_ISDIR(st.st_mode); +} + +bool DoesFileOrDirExist(CFSTR name) +{ + struct stat st; + if (MY__lstat(name, &st, false) != 0) + return false; + return true; +} + + +CEnumerator::~CEnumerator() +{ + if (_dir) + closedir(_dir); +} + +void CEnumerator::SetDirPrefix(const FString &dirPrefix) +{ + _wildcard = dirPrefix; +} + +bool CDirEntry::IsDots() const throw() +{ + if ( + #if !defined(_AIX) + !IsDir() || + #endif + Name.IsEmpty()) + return false; + if (Name[0] != '.') + return false; + return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == '.'); +} + + +bool CEnumerator::NextAny(CDirEntry &fi, bool &found) +{ + found = false; + + if (!_dir) + { + const char *w = "./"; + if (!_wildcard.IsEmpty()) + w = _wildcard.Ptr(); + _dir = ::opendir((const char *)w); + if (_dir == NULL) + return false; + } + + // To distinguish end of stream from an error, we must set errno to zero before readdir() + errno = 0; + + struct dirent *de = readdir(_dir); + if (!de) + { + if (errno == 0) + return true; // it's end of stream, and we report it with (found = false) + // it's real error + return false; + } + + fi.iNode = de->d_ino; + + #if !defined(_AIX) + fi.Type = de->d_type; + #endif + + /* + if (de->d_type == DT_DIR) + fi.Attrib = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_UNIX_EXTENSION | ((UInt32)(S_IFDIR) << 16); + else if (de->d_type < 16) + fi.Attrib = FILE_ATTRIBUTE_UNIX_EXTENSION | ((UInt32)(de->d_type) << (16 + 12)); + */ + fi.Name = de->d_name; + + /* + printf("\nCEnumerator::NextAny; len = %d %s \n", (int)fi.Name.Len(), fi.Name.Ptr()); + for (unsigned i = 0; i < fi.Name.Len(); i++) + printf (" %02x", (unsigned)(Byte)de->d_name[i]); + printf("\n"); + */ + + found = true; + return true; +} + + +bool CEnumerator::Next(CDirEntry &fi, bool &found) +{ + // printf("\nCEnumerator::Next()\n"); + // PrintName("Next", ""); + for (;;) + { + if (!NextAny(fi, found)) + return false; + if (!found) + return true; + if (!fi.IsDots()) + { + /* + if (!NeedFullStat) + return true; + // we silently skip error file here - it can be wrong link item + if (fi.Find_DontFill_Name(path)) + return true; + */ + return true; + } + } +} + +/* +bool CEnumerator::Next(CDirEntry &fileInfo, bool &found) +{ + bool found; + if (!Next(fi, found)) + return false; + return found; +} +*/ + +bool CEnumerator::Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) +{ + // printf("\nCEnumerator::Fill_FileInfo()\n"); + struct stat st; + // probably it's OK to use fstatat() even if it changes file position dirfd(_dir) + int res = fstatat(dirfd(_dir), de.Name, &st, followLink ? 0 : AT_SYMLINK_NOFOLLOW); + // if fstatat() is not supported, we can use stat() / lstat() + + /* + const FString path = _wildcard + s; + int res = MY__lstat(path, &st, followLink); + */ + + if (res != 0) + return false; + fileInfo.SetFrom_stat(st); + fileInfo.Name = de.Name; + return true; +} + +#endif // _WIN32 }}} diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h index bfb29206..009e84e7 100644 --- a/CPP/Windows/FileFind.h +++ b/CPP/Windows/FileFind.h @@ -3,13 +3,36 @@ #ifndef __WINDOWS_FILE_FIND_H #define __WINDOWS_FILE_FIND_H +#ifndef _WIN32 +#include <sys/stat.h> +#include <sys/types.h> +#include <dirent.h> +#endif + #include "../Common/MyString.h" +#include "../Common/MyWindows.h" #include "Defs.h" namespace NWindows { namespace NFile { namespace NFind { +// bool DoesFileExist(CFSTR name, bool followLink); +bool DoesFileExist_Raw(CFSTR name); +bool DoesFileExist_FollowLink(CFSTR name); +bool DoesDirExist(CFSTR name, bool followLink); + +inline bool DoesDirExist(CFSTR name) + { return DoesDirExist(name, false); } +inline bool DoesDirExist_FollowLink(CFSTR name) + { return DoesDirExist(name, true); } + +// it's always _Raw +bool DoesFileOrDirExist(CFSTR name); + +DWORD GetFileAttrib(CFSTR path); + + namespace NAttributes { inline bool IsReadOnly(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_READONLY) != 0; } @@ -33,6 +56,7 @@ public: bool IsAltStream; bool IsDevice; + #ifdef _WIN32 /* #ifdef UNDER_CE DWORD ObjectID; @@ -40,11 +64,24 @@ public: UINT32 ReparseTag; #endif */ + #else + dev_t dev; + ino_t ino; + nlink_t nlink; + mode_t mode; + // bool Use_lstat; + #endif CFileInfoBase() { ClearBase(); } void ClearBase() throw(); - - void SetAsDir() { Attrib = FILE_ATTRIBUTE_DIRECTORY; } + + void SetAsDir() + { + Attrib = FILE_ATTRIBUTE_DIRECTORY; + #ifndef _WIN32 + Attrib |= (FILE_ATTRIBUTE_UNIX_EXTENSION + (S_IFDIR << 16)); + #endif + } bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } @@ -58,6 +95,14 @@ public: bool IsSparse() const { return MatchesMask(FILE_ATTRIBUTE_SPARSE_FILE); } bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); } bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); } + + #ifndef _WIN32 + bool IsPosixLink() const + { + const UInt32 mod = Attrib >> 16; + return S_ISLNK(mod); + } + #endif }; struct CFileInfo: public CFileInfoBase @@ -68,10 +113,22 @@ struct CFileInfo: public CFileInfoBase #endif bool IsDots() const throw(); - bool Find(CFSTR path); + bool Find(CFSTR path, bool followLink = false); + bool Find_FollowLink(CFSTR path) { return Find(path, true); } + + #ifdef _WIN32 + bool Fill_From_ByHandleFileInfo(CFSTR path); + // bool FollowReparse(CFSTR path, bool isDir); + #else + bool Find_DontFill_Name(CFSTR path, bool followLink = false); + void SetFrom_stat(const struct stat &st); + #endif }; -class CFindFileBase + +#ifdef _WIN32 + +class CFindFileBase MY_UNCOPYABLE { protected: HANDLE _handle; @@ -108,26 +165,21 @@ public: bool FindNext(CStreamInfo &streamInfo); }; -class CStreamEnumerator +class CStreamEnumerator MY_UNCOPYABLE { CFindStream _find; FString _filePath; - bool NextAny(CFileInfo &fileInfo); + bool NextAny(CFileInfo &fileInfo, bool &found); public: CStreamEnumerator(const FString &filePath): _filePath(filePath) {} bool Next(CStreamInfo &streamInfo, bool &found); }; -#endif +#endif // defined(_WIN32) && !defined(UNDER_CE) -bool DoesFileExist(CFSTR name); -bool DoesDirExist(CFSTR name); -bool DoesFileOrDirExist(CFSTR name); - -DWORD GetFileAttrib(CFSTR path); -class CEnumerator +class CEnumerator MY_UNCOPYABLE { CFindFile _findFile; FString _wildcard; @@ -139,7 +191,8 @@ public: bool Next(CFileInfo &fileInfo, bool &found); }; -class CFindChangeNotification + +class CFindChangeNotification MY_UNCOPYABLE { HANDLE _handle; public: @@ -156,6 +209,71 @@ public: bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings); #endif +typedef CFileInfo CDirEntry; + + +#else // WIN32 + + +struct CDirEntry +{ + ino_t iNode; + #if !defined(_AIX) + Byte Type; + #endif + FString Name; + + #if !defined(_AIX) + bool IsDir() const + { + // DT_DIR is + return Type == DT_DIR; + } + #endif + + bool IsDots() const throw(); +}; + +class CEnumerator MY_UNCOPYABLE +{ + DIR *_dir; + FString _wildcard; + + bool NextAny(CDirEntry &fileInfo, bool &found); +public: + CEnumerator(): _dir(NULL) {} + ~CEnumerator(); + void SetDirPrefix(const FString &dirPrefix); + + bool Next(CDirEntry &fileInfo, bool &found); + bool Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink); +}; + +/* +inline UInt32 Get_WinAttrib_From_PosixMode(UInt32 mode) +{ + UInt32 attrib = S_ISDIR(mode) ? + FILE_ATTRIBUTE_DIRECTORY : + FILE_ATTRIBUTE_ARCHIVE; + if ((st.st_mode & 0222) == 0) // check it !!! + attrib |= FILE_ATTRIBUTE_READONLY; + return attrib; +} +*/ + +UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode); + +// UInt32 Get_WinAttrib_From_stat(const struct stat &st); +#if defined(_AIX) + #define MY_ST_TIMESPEC st_timespec +#else + #define MY_ST_TIMESPEC timespec +#endif + +void timespec_To_FILETIME(const MY_ST_TIMESPEC &ts, FILETIME &ft); + +#endif // WIN32 + }}} #endif diff --git a/CPP/Windows/FileIO.cpp b/CPP/Windows/FileIO.cpp index 56e6ca45..b6f2f26e 100644 --- a/CPP/Windows/FileIO.cpp +++ b/CPP/Windows/FileIO.cpp @@ -6,9 +6,21 @@ #include "../../C/Alloc.h" #endif +// #include <stdio.h> + #include "FileIO.h" #include "FileName.h" +HRESULT GetLastError_noZero_HRESULT() +{ + DWORD res = ::GetLastError(); + if (res == 0) + return E_FAIL; + return HRESULT_FROM_WIN32(res); +} + +#ifdef _WIN32 + #ifndef _UNICODE extern bool g_IsNT; #endif @@ -78,6 +90,42 @@ bool CFileBase::Create(CFSTR path, DWORD desiredAccess, } #endif } + + /* + #ifndef UNDER_CE + #ifndef _SFX + if (_handle == INVALID_HANDLE_VALUE) + { + // it's debug hack to open symbolic links in Windows XP and WSL links in Windows 10 + DWORD lastError = GetLastError(); + if (lastError == ERROR_CANT_ACCESS_FILE) + { + CByteBuffer buf; + if (NIO::GetReparseData(path, buf, NULL)) + { + CReparseAttr attr; + if (attr.Parse(buf, buf.Size())) + { + FString dirPrefix, fileName; + if (NDir::GetFullPathAndSplit(path, dirPrefix, fileName)) + { + FString fullPath; + if (GetFullPath(dirPrefix, us2fs(attr.GetPath()), fullPath)) + { + // FIX IT: recursion levels must be restricted + return Create(fullPath, desiredAccess, + shareMode, creationDisposition, flagsAndAttributes); + } + } + } + } + SetLastError(lastError); + } + } + #endif + #endif + */ + return (_handle != INVALID_HANDLE_VALUE); } @@ -136,7 +184,7 @@ bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) const throw() { - return Seek(position, FILE_BEGIN, newPosition); + return Seek((Int64)position, FILE_BEGIN, newPosition); } bool CFileBase::SeekToBegin() const throw() @@ -258,7 +306,7 @@ void CInFile::CalcDeviceSize(CFSTR s) if (GetPartitionInfo(&partInfo)) { - Size = partInfo.PartitionLength.QuadPart; + Size = (UInt64)partInfo.PartitionLength.QuadPart; SizeDefined = true; needCorrectSize = false; if ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\' && (s)[5] == ':' && (s)[6] == 0) @@ -277,7 +325,7 @@ void CInFile::CalcDeviceSize(CFSTR s) my_DISK_GEOMETRY_EX geomEx; SizeDefined = GetGeometryEx(&geomEx); if (SizeDefined) - Size = geomEx.DiskSize.QuadPart; + Size = (UInt64)geomEx.DiskSize.QuadPart; else { DISK_GEOMETRY geom; @@ -285,7 +333,7 @@ void CInFile::CalcDeviceSize(CFSTR s) if (!SizeDefined) SizeDefined = GetCdRomGeometry(&geom); if (SizeDefined) - Size = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector; + Size = (UInt64)geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector; } } @@ -310,7 +358,24 @@ void CInFile::CalcDeviceSize(CFSTR s) bool CInFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { - bool res = Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); + DWORD desiredAccess = GENERIC_READ; + + #ifdef _WIN32 + if (PreserveATime) + desiredAccess |= FILE_WRITE_ATTRIBUTES; + #endif + + bool res = Create(fileName, desiredAccess, shareMode, creationDisposition, flagsAndAttributes); + + #ifdef _WIN32 + if (res && PreserveATime) + { + FILETIME ft; + ft.dwHighDateTime = ft.dwLowDateTime = 0xFFFFFFFF; + ::SetFileTime(_handle, NULL, &ft, NULL); + } + #endif + MY_DEVICE_EXTRA_CODE return res; } @@ -330,7 +395,7 @@ bool CInFile::Open(CFSTR fileName) // for 32 MB (maybe also for 16 MB). // And message can be "Network connection was lost" -static UInt32 kChunkSizeMax = (1 << 22); +static const UInt32 kChunkSizeMax = (1 << 22); bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) throw() { @@ -366,6 +431,26 @@ bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) throw() return true; } +bool CInFile::ReadFull(void *data, size_t size, size_t &processedSize) throw() +{ + processedSize = 0; + do + { + UInt32 processedLoc = 0; + const UInt32 sizeLoc = (size > kChunkSizeMax ? (UInt32)kChunkSizeMax : (UInt32)size); + const bool res = Read1(data, sizeLoc, processedLoc); + processedSize += processedLoc; + if (!res) + return false; + if (processedLoc == 0) + return true; + data = (void *)((unsigned char *)data + processedLoc); + size -= processedLoc; + } + while (size > 0); + return true; +} + // ---------- COutFile --------- static inline DWORD GetCreationDisposition(bool createAlways) @@ -430,3 +515,216 @@ bool COutFile::SetLength(UInt64 length) throw() } }}} + +#else // _WIN32 + + +// POSIX + +#include <fcntl.h> +#include <unistd.h> + +namespace NWindows { +namespace NFile { + +namespace NDir { +bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); +} + +namespace NIO { + +bool CFileBase::OpenBinary(const char *name, int flags) +{ + #ifdef O_BINARY + flags |= O_BINARY; + #endif + + Close(); + _handle = ::open(name, flags, 0666); + return _handle != -1; +} + +bool CFileBase::Close() +{ + if (_handle == -1) + return true; + if (close(_handle) != 0) + return false; + _handle = -1; + return true; +} + +bool CFileBase::GetLength(UInt64 &length) const +{ + const off_t curPos = seek(0, SEEK_CUR); + if (curPos == -1) + return false; + const off_t lengthTemp = seek(0, SEEK_END); + seek(curPos, SEEK_SET); + length = (UInt64)lengthTemp; + return (lengthTemp != -1); +} + +off_t CFileBase::seek(off_t distanceToMove, int moveMethod) const +{ + // printf("\nCFileBase::seek() moveMethod = %d, distanceToMove = %lld", moveMethod, (long long)distanceToMove); + // off_t res = ::lseek(_handle, distanceToMove, moveMethod); + return ::lseek(_handle, distanceToMove, moveMethod); + // printf(" res = %lld", (long long)res); + // return res; +} + +off_t CFileBase::seekToBegin() const throw() +{ + return seek(0, SEEK_SET); +} + +/* +bool CFileBase::SeekToBegin() const throw() +{ + return (::seek(0, SEEK_SET) != -1); +} +*/ + + +///////////////////////// +// CInFile + +bool CInFile::Open(const char *name) +{ + return CFileBase::OpenBinary(name, O_RDONLY); +} + +bool CInFile::OpenShared(const char *name, bool) +{ + return Open(name); +} + +/* +On Linux (32-bit and 64-bit): +read(), write() (and similar system calls) will transfer at most +0x7ffff000 = (2GiB - 4 KiB) bytes, returning the number of bytes actually transferred. +*/ + +static const size_t kChunkSizeMax = ((size_t)1 << 22); + +ssize_t CInFile::read_part(void *data, size_t size) throw() +{ + if (size > kChunkSizeMax) + size = kChunkSizeMax; + return ::read(_handle, data, size); +} + +bool CInFile::ReadFull(void *data, size_t size, size_t &processed) throw() +{ + processed = 0; + do + { + const ssize_t res = read_part(data, size); + if (res < 0) + return false; + if (res == 0) + break; + data = (void *)((unsigned char *)data + (size_t)res); + size -= (size_t)res; + processed += (size_t)res; + } + while (size > 0); + return true; +} + + +///////////////////////// +// COutFile + +bool COutFile::Create(const char *name, bool createAlways) +{ + Path = name; // change it : set it only if open is success. + if (createAlways) + { + Close(); + _handle = ::creat(name, 0666); + return _handle != -1; + } + return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY); +} + +bool COutFile::Open(const char *name, DWORD creationDisposition) +{ + UNUSED_VAR(creationDisposition) // FIXME + return Create(name, false); +} + +ssize_t COutFile::write_part(const void *data, size_t size) throw() +{ + if (size > kChunkSizeMax) + size = kChunkSizeMax; + return ::write(_handle, data, size); +} + +ssize_t COutFile::write_full(const void *data, size_t size, size_t &processed) throw() +{ + processed = 0; + do + { + const ssize_t res = write_part(data, size); + if (res < 0) + return res; + if (res == 0) + break; + data = (const void *)((const unsigned char *)data + (size_t)res); + size -= (size_t)res; + processed += (size_t)res; + } + while (size > 0); + return (ssize_t)processed; +} + +bool COutFile::SetLength(UInt64 length) throw() +{ + const off_t len2 = (off_t)length; + if ((Int64)length != len2) + { + SetLastError(EFBIG); + return false; + } + int iret = ftruncate(_handle, len2); + return (iret == 0); +} + +bool COutFile::Close() +{ + bool res = CFileBase::Close(); + if (!res) + return res; + if (CTime_defined || ATime_defined || MTime_defined) + { + /* bool res2 = */ NWindows::NFile::NDir::SetDirTime(Path, + CTime_defined ? &CTime : NULL, + ATime_defined ? &ATime : NULL, + MTime_defined ? &MTime : NULL); + } + return res; +} + +bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw() +{ + // On some OS (cygwin, MacOSX ...), you must close the file before updating times + // return true; + + if (cTime) { CTime = *cTime; CTime_defined = true; } else CTime_defined = false; + if (aTime) { ATime = *aTime; ATime_defined = true; } else ATime_defined = false; + if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false; + return true; +} + +bool COutFile::SetMTime(const FILETIME *mTime) throw() +{ + if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false; + return true; +} + +}}} + + +#endif diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h index 5ca5448b..276e595e 100644 --- a/CPP/Windows/FileIO.h +++ b/CPP/Windows/FileIO.h @@ -5,8 +5,26 @@ #include "../Common/MyWindows.h" +#define _my_IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) +#define _my_IO_REPARSE_TAG_SYMLINK (0xA000000CL) +#define _my_IO_REPARSE_TAG_LX_SYMLINK (0xA000001DL) + +#define _my_SYMLINK_FLAG_RELATIVE 1 + +// what the meaning of that FLAG or field (2)? +#define _my_LX_SYMLINK_FLAG 2 + +#ifdef _WIN32 + #if defined(_WIN32) && !defined(UNDER_CE) -#include <winioctl.h> +#include <WinIoCtl.h> +#endif + +#else + +#include <sys/types.h> +#include <sys/stat.h> + #endif #include "../Common/MyString.h" @@ -14,19 +32,17 @@ #include "Defs.h" -#define _my_IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) -#define _my_IO_REPARSE_TAG_SYMLINK (0xA000000CL) - -#define _my_SYMLINK_FLAG_RELATIVE 1 +HRESULT GetLastError_noZero_HRESULT(); -#define my_FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER -#define my_FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) // REPARSE_DATA_BUFFER +#define my_FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER +#define my_FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) // REPARSE_DATA_BUFFER +#define my_FSCTL_DELETE_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 43, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER namespace NWindows { namespace NFile { #if defined(_WIN32) && !defined(UNDER_CE) -bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink); +bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool isWSL); #endif struct CReparseShortInfo @@ -44,28 +60,50 @@ struct CReparseAttr UString SubsName; UString PrintName; + AString WslName; + + bool HeaderError; + bool TagIsUnknown; + bool MinorError; + DWORD ErrorCode; + CReparseAttr(): Tag(0), Flags(0) {} // Parse() - // returns true and (errorCode = 0), if (correct MOUNT_POINT or SYMLINK) - // returns false and (errorCode = ERROR_REPARSE_TAG_MISMATCH), if not (MOUNT_POINT or SYMLINK) - bool Parse(const Byte *p, size_t size, DWORD &errorCode); + // returns (true) and (ErrorCode = 0), if (it'a correct known link) + // returns (false) and (ErrorCode = ERROR_REPARSE_TAG_INVALID), if unknown tag + bool Parse(const Byte *p, size_t size); + + bool IsMountPoint() const { return Tag == _my_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction + bool IsSymLink_Win() const { return Tag == _my_IO_REPARSE_TAG_SYMLINK; } + bool IsSymLink_WSL() const { return Tag == _my_IO_REPARSE_TAG_LX_SYMLINK; } + + bool IsRelative_Win() const { return Flags == _my_SYMLINK_FLAG_RELATIVE; } + + bool IsRelative_WSL() const + { + if (WslName.IsEmpty()) + return true; + char c = WslName[0]; + return !IS_PATH_SEPAR(c); + } - bool IsMountPoint() const { return Tag == _my_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction - bool IsSymLink() const { return Tag == _my_IO_REPARSE_TAG_SYMLINK; } - bool IsRelative() const { return Flags == _my_SYMLINK_FLAG_RELATIVE; } // bool IsVolume() const; bool IsOkNamePair() const; UString GetPath() const; }; + +#ifdef _WIN32 + namespace NIO { bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo = NULL); bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size); +bool DeleteReparseData(CFSTR path); -class CFileBase +class CFileBase MY_UNCOPYABLE { protected: HANDLE _handle; @@ -94,13 +132,14 @@ public: } public: + bool PreserveATime; #ifdef SUPPORT_DEVICE_FILE bool IsDeviceFile; bool SizeDefined; UInt64 Size; // it can be larger than real available size #endif - CFileBase(): _handle(INVALID_HANDLE_VALUE) {}; + CFileBase(): _handle(INVALID_HANDLE_VALUE), PreserveATime(false) {}; ~CFileBase() { Close(); } bool Close() throw(); @@ -118,6 +157,7 @@ public: static bool GetFileInformation(CFSTR path, BY_HANDLE_FILE_INFORMATION *info) { + // probably it can work for complex paths: unsupported by another things NIO::CFileBase file; if (!file.Create(path, 0, FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS)) return false; @@ -189,6 +229,7 @@ public: bool Read1(void *data, UInt32 size, UInt32 &processedSize) throw(); bool ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw(); bool Read(void *data, UInt32 size, UInt32 &processedSize) throw(); + bool ReadFull(void *data, size_t size, size_t &processedSize) throw(); }; class COutFile: public CFileBase @@ -207,6 +248,83 @@ public: bool SetLength(UInt64 length) throw(); }; -}}} +} + + +#else // _WIN32 + +namespace NIO { + +bool GetReparseData(CFSTR path, CByteBuffer &reparseData); +// bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size); + +// parameters are in reverse order of symlink() function !!! +bool SetSymLink(CFSTR from, CFSTR to); +bool SetSymLink_UString(CFSTR from, const UString &to); + + +class CFileBase +{ +protected: + int _handle; + + bool OpenBinary(const char *name, int flags); +public: + bool PreserveATime; + + CFileBase(): _handle(-1), PreserveATime(false) {}; + ~CFileBase() { Close(); } + bool Close(); + bool GetLength(UInt64 &length) const; + off_t seek(off_t distanceToMove, int moveMethod) const; + off_t seekToBegin() const throw(); + // bool SeekToBegin() throw(); + int my_fstat(struct stat *st) const { return fstat(_handle, st); } +}; + +class CInFile: public CFileBase +{ +public: + bool Open(const char *name); + bool OpenShared(const char *name, bool shareForWrite); + ssize_t read_part(void *data, size_t size) throw(); + // ssize_t read_full(void *data, size_t size, size_t &processed); + bool ReadFull(void *data, size_t size, size_t &processedSize) throw(); +}; + +class COutFile: public CFileBase +{ + bool CTime_defined; + bool ATime_defined; + bool MTime_defined; + + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; + + AString Path; + ssize_t write_part(const void *data, size_t size) throw(); +public: + COutFile(): + CTime_defined(false), + ATime_defined(false), + MTime_defined(false) + {} + + bool Close(); + bool Create(const char *name, bool createAlways); + bool Open(const char *name, DWORD creationDisposition); + ssize_t write_full(const void *data, size_t size, size_t &processed) throw(); + bool SetLength(UInt64 length) throw(); + bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw(); + bool SetMTime(const FILETIME *mTime) throw(); +}; + +} + +#endif // _WIN32 + +}} + #endif diff --git a/CPP/Windows/FileLink.cpp b/CPP/Windows/FileLink.cpp index 3e2f6431..8ce634fd 100644 --- a/CPP/Windows/FileLink.cpp +++ b/CPP/Windows/FileLink.cpp @@ -4,10 +4,17 @@ #include "../../C/CpuArch.h" +#ifndef _WIN32 +#include <unistd.h> +#endif + #ifdef SUPPORT_DEVICE_FILE #include "../../C/Alloc.h" #endif +#include "../Common/UTFConvert.h" +#include "../Common/StringConvert.h" + #include "FileDir.h" #include "FileFind.h" #include "FileIO.h" @@ -55,6 +62,12 @@ using namespace NName; */ /* +Win10 WSL2: +admin rights + sudo: it creates normal windows symbolic link. +in another cases : it creates IO_REPARSE_TAG_LX_SYMLINK repare point. +*/ + +/* static const UInt32 kReparseFlags_Alias = (1 << 29); static const UInt32 kReparseFlags_HighLatency = (1 << 30); static const UInt32 kReparseFlags_Microsoft = ((UInt32)1 << 31); @@ -71,13 +84,10 @@ static const UInt32 kReparseFlags_Microsoft = ((UInt32)1 << 31); #define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) -#define Set16(p, v) SetUi16(p, v) -#define Set32(p, v) SetUi32(p, v) - static const wchar_t * const k_LinkPrefix = L"\\??\\"; static const unsigned k_LinkPrefix_Size = 4; -static const bool IsLinkPrefix(const wchar_t *s) +static bool IsLinkPrefix(const wchar_t *s) { return IsString1PrefixedByString2(s, k_LinkPrefix); } @@ -90,7 +100,12 @@ static const bool IsVolumeName(const wchar_t *s) } */ -void WriteString(Byte *dest, const wchar_t *path) +#if defined(_WIN32) && !defined(UNDER_CE) + +#define Set16(p, v) SetUi16(p, v) +#define Set32(p, v) SetUi32(p, v) + +static void WriteString(Byte *dest, const wchar_t *path) { for (;;) { @@ -102,14 +117,32 @@ void WriteString(Byte *dest, const wchar_t *path) } } -#if defined(_WIN32) && !defined(UNDER_CE) - -bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink) +bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool isWSL) { bool isAbs = IsAbsolutePath(path); if (!isAbs && !isSymLink) return false; + if (isWSL) + { + // unsupported characters probably use Replacement Character UTF-16 0xFFFD + AString utf; + ConvertUnicodeToUTF8(path, utf); + const size_t size = 4 + utf.Len(); + if (size != (UInt16)size) + return false; + dest.Alloc(8 + size); + Byte *p = dest; + Set32(p, _my_IO_REPARSE_TAG_LX_SYMLINK); + Set16(p + 4, (UInt16)(size)); + Set16(p + 6, 0); + Set32(p + 8, _my_LX_SYMLINK_FLAG); + memcpy(p + 12, utf.Ptr(), utf.Len()); + return true; + } + + // usual symbolic LINK (NOT WSL) + bool needPrintName = true; if (IsSuperPath(path)) @@ -121,12 +154,12 @@ bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink) const unsigned add_Prefix_Len = isAbs ? k_LinkPrefix_Size : 0; - unsigned len2 = MyStringLen(path) * 2; - const unsigned len1 = len2 + add_Prefix_Len * 2; + size_t len2 = (size_t)MyStringLen(path) * 2; + const size_t len1 = len2 + add_Prefix_Len * 2; if (!needPrintName) len2 = 0; - unsigned totalNamesSize = (len1 + len2); + size_t totalNamesSize = (len1 + len2); /* some WIM imagex software uses old scheme for symbolic links. so we can old scheme for byte to byte compatibility */ @@ -138,6 +171,8 @@ bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink) totalNamesSize += 2 * 2; const size_t size = 8 + 8 + (isSymLink ? 4 : 0) + totalNamesSize; + if (size != (UInt16)size) + return false; dest.Alloc(size); memset(dest, 0, size); const UInt32 tag = isSymLink ? @@ -152,9 +187,9 @@ bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink) unsigned subOffs = 0; unsigned printOffs = 0; if (newOrderScheme) - subOffs = len2; + subOffs = (unsigned)len2; else - printOffs = len1 + 2; + printOffs = (unsigned)len1 + 2; Set16(p + 0, (UInt16)subOffs); Set16(p + 2, (UInt16)len1); @@ -177,7 +212,8 @@ bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink) return true; } -#endif +#endif // defined(_WIN32) && !defined(UNDER_CE) + static void GetString(const Byte *p, unsigned len, UString &res) { @@ -194,35 +230,69 @@ static void GetString(const Byte *p, unsigned len, UString &res) res.ReleaseBuf_SetLen(i); } -bool CReparseAttr::Parse(const Byte *p, size_t size, DWORD &errorCode) +bool CReparseAttr::Parse(const Byte *p, size_t size) { - errorCode = ERROR_INVALID_REPARSE_DATA; + ErrorCode = (DWORD)ERROR_INVALID_REPARSE_DATA; + HeaderError = true; + TagIsUnknown = true; + MinorError = false; + if (size < 8) return false; Tag = Get32(p); UInt32 len = Get16(p + 4); - if (len + 8 > size) + if (len + 8 != size) + // if (len + 8 > size) return false; /* if ((type & kReparseFlags_Alias) == 0 || (type & kReparseFlags_Microsoft) == 0 || (type & 0xFFFF) != 3) */ - if (Tag != _my_IO_REPARSE_TAG_MOUNT_POINT && - Tag != _my_IO_REPARSE_TAG_SYMLINK) + + if (Get16(p + 6) != 0) // padding + return false; + + HeaderError = false; + + if ( Tag != _my_IO_REPARSE_TAG_MOUNT_POINT + && Tag != _my_IO_REPARSE_TAG_SYMLINK + && Tag != _my_IO_REPARSE_TAG_LX_SYMLINK) { - errorCode = ERROR_REPARSE_TAG_MISMATCH; // ERROR_REPARSE_TAG_INVALID + // for unsupported reparse points + ErrorCode = (DWORD)ERROR_REPARSE_TAG_INVALID; // ERROR_REPARSE_TAG_MISMATCH + // errorCode = ERROR_REPARSE_TAG_MISMATCH; // ERROR_REPARSE_TAG_INVALID return false; } - if (Get16(p + 6) != 0) // padding - return false; - + TagIsUnknown = false; + p += 8; size -= 8; - if (len != size) // do we need that check? - return false; + if (Tag == _my_IO_REPARSE_TAG_LX_SYMLINK) + { + if (len < 4) + return false; + Flags = Get32(p); // maybe it's not Flags + if (Flags != _my_LX_SYMLINK_FLAG) + return false; + len -= 4; + p += 4; + char *s = WslName.GetBuf(len); + unsigned i; + for (i = 0; i < len; i++) + { + char c = (char)p[i]; + s[i] = c; + if (c == 0) + break; + } + WslName.ReleaseBuf_SetEnd(i); + MinorError = (i != len); + ErrorCode = 0; + return true; + } if (len < 8) return false; @@ -250,10 +320,11 @@ bool CReparseAttr::Parse(const Byte *p, size_t size, DWORD &errorCode) GetString(p + subOffs, subLen >> 1, SubsName); GetString(p + printOffs, printLen >> 1, PrintName); - errorCode = 0; + ErrorCode = 0; return true; } + bool CReparseShortInfo::Parse(const Byte *p, size_t size) { const Byte *start = p; @@ -336,26 +407,34 @@ bool CReparseAttr::IsVolume() const UString CReparseAttr::GetPath() const { + if (IsSymLink_WSL()) + { + UString u; + // if (CheckUTF8(attr.WslName) + if (!ConvertUTF8ToUnicode(WslName, u)) + MultiByteToUnicodeString2(u, WslName); + return u; + } + UString s (SubsName); if (IsLinkPrefix(s)) { - s.ReplaceOneCharAtPos(1, '\\'); + s.ReplaceOneCharAtPos(1, '\\'); // we normalize prefix from "\??\" to "\\?\" if (IsDrivePath(s.Ptr(k_LinkPrefix_Size))) s.DeleteFrontal(k_LinkPrefix_Size); } return s; } - #ifdef SUPPORT_DEVICE_FILE namespace NSystem { bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); } -#endif +#endif // SUPPORT_DEVICE_FILE -#ifndef UNDER_CE +#if defined(_WIN32) && !defined(UNDER_CE) namespace NIO { @@ -388,11 +467,26 @@ static bool CreatePrefixDirOfFile(CFSTR path) if (pos == 2 && path2[1] == L':') return true; // we don't create Disk folder; #endif - path2.DeleteFrom(pos); + path2.DeleteFrom((unsigned)pos); return NDir::CreateComplexDir(path2); } -// If there is Reprase data already, it still writes new Reparse data + +static bool OutIoReparseData(DWORD controlCode, CFSTR path, void *data, DWORD size) +{ + COutFile file; + if (!file.Open(path, + FILE_SHARE_WRITE, + OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS)) + return false; + + DWORD returnedSize; + return file.DeviceIoControl(controlCode, data, size, NULL, 0, &returnedSize); +} + + +// If there is Reparse data already, it still writes new Reparse data bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size) { NFile::NFind::CFileInfo fi; @@ -420,21 +514,100 @@ bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size) } } - COutFile file; - if (!file.Open(path, - FILE_SHARE_WRITE, - OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS)) + return OutIoReparseData(my_FSCTL_SET_REPARSE_POINT, path, (void *)(const Byte *)(data), size); +} + + +bool DeleteReparseData(CFSTR path) +{ + CByteBuffer reparseData; + if (!GetReparseData(path, reparseData, NULL)) return false; + /* MSDN: The tag specified in the ReparseTag member of this structure + must match the tag of the reparse point to be deleted, + and the ReparseDataLength member must be zero */ + #define my_REPARSE_DATA_BUFFER_HEADER_SIZE 8 + if (reparseData.Size() < my_REPARSE_DATA_BUFFER_HEADER_SIZE) + { + SetLastError(ERROR_INVALID_REPARSE_DATA); + return false; + } + BYTE buf[my_REPARSE_DATA_BUFFER_HEADER_SIZE]; + memset(buf, 0, sizeof(buf)); + memcpy(buf, reparseData, 4); // tag + return OutIoReparseData(my_FSCTL_DELETE_REPARSE_POINT, path, buf, sizeof(buf)); +} - DWORD returnedSize; - if (!file.DeviceIoControl(my_FSCTL_SET_REPARSE_POINT, (void *)data, size, NULL, 0, &returnedSize)) +} + +#endif // defined(_WIN32) && !defined(UNDER_CE) + + +#ifndef _WIN32 + +namespace NIO { + +bool GetReparseData(CFSTR path, CByteBuffer &reparseData) +{ + reparseData.Free(); + + #define MAX_PATHNAME_LEN 1024 + char buf[MAX_PATHNAME_LEN + 2]; + const size_t request = sizeof(buf) - 1; + + // printf("\nreadlink() path = %s \n", path); + const ssize_t size = readlink(path, buf, request); + // there is no tail zero + + if (size < 0) return false; + if ((size_t)size >= request) + { + SetLastError(EINVAL); // check it: ENAMETOOLONG + return false; + } + + // printf("\nreadlink() res = %s size = %d \n", buf, (int)size); + reparseData.CopyFrom((const Byte *)buf, (size_t)size); return true; } + +/* +// If there is Reparse data already, it still writes new Reparse data +bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size) +{ + // AString s; + // s.SetFrom_CalcLen(data, size); + // return (symlink(s, path) == 0); + UNUSED_VAR(path) + UNUSED_VAR(isDir) + UNUSED_VAR(data) + UNUSED_VAR(size) + SetLastError(ENOSYS); + return false; } +*/ -#endif +bool SetSymLink(CFSTR from, CFSTR to) +{ + // printf("\nsymlink() %s -> %s\n", from, to); + int ir; + // ir = unlink(path); + // if (ir == 0) + ir = symlink(to, from); + return (ir == 0); +} + +bool SetSymLink_UString(CFSTR from, const UString &to) +{ + AString utf; + ConvertUnicodeToUTF8(to, utf); + return SetSymLink(from, utf); +} + +} + +#endif // !_WIN32 }} diff --git a/CPP/Windows/FileName.cpp b/CPP/Windows/FileName.cpp index 2d0b50d5..4ee94575 100644 --- a/CPP/Windows/FileName.cpp +++ b/CPP/Windows/FileName.cpp @@ -2,6 +2,12 @@ #include "StdAfx.h" +#ifndef _WIN32 +#include <limits.h> +#include <unistd.h> +#include "../Common/StringConvert.h" +#endif + #include "FileName.h" #ifndef _UNICODE @@ -58,7 +64,18 @@ void NormalizeDirPathPrefix(UString &dirPath) dirPath.Add_PathSepar(); } -#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z') +#ifdef _WIN32 +void NormalizeDirSeparators(FString &s) +{ + const unsigned len = s.Len(); + for (unsigned i = 0; i < len; i++) + if (s[i] == '/') + s.ReplaceOneCharAtPos(i, FCHAR_PATH_SEPARATOR); +} +#endif + + +#define IS_LETTER_CHAR(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); } @@ -88,7 +105,9 @@ bool IsAltPathPrefix(CFSTR s) throw() #if defined(_WIN32) && !defined(UNDER_CE) const char * const kSuperPathPrefix = "\\\\?\\"; +#ifdef WIN_LONG_PATH static const char * const kSuperUncPrefix = "\\\\?\\UNC\\"; +#endif #define IS_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '.' && IS_SEPAR((s)[3])) #define IS_SUPER_PREFIX(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '?' && IS_SEPAR((s)[3])) @@ -160,7 +179,7 @@ unsigned GetNetworkServerPrefixSize(CFSTR s) throw() int pos = FindSepar(s + prefixSize); if (pos < 0) return 0; - return prefixSize + pos + 1; + return prefixSize + (unsigned)(pos + 1); } bool IsNetworkShareRootPath(CFSTR s) throw() @@ -224,7 +243,7 @@ int FindAltStreamColon(CFSTR path) throw() if (c == ':') { if (colonPos < 0) - colonPos = i; + colonPos = (int)i; continue; } if (IS_SEPAR(c)) @@ -292,7 +311,7 @@ static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw() int pos2 = FindSepar(s + (unsigned)pos + 1); if (pos2 < 0) return 0; - return pos + pos2 + 2; + return (unsigned)(pos + pos2 + 2); } static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) throw() @@ -318,7 +337,7 @@ static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw() int pos = FindSepar(s + kSuperPathPrefixSize); if (pos < 0) return 0; - return kSuperPathPrefixSize + pos + 1; + return kSuperPathPrefixSize + (unsigned)(pos + 1); } unsigned GetRootPrefixSize(const wchar_t *s) throw() @@ -332,12 +351,13 @@ unsigned GetRootPrefixSize(const wchar_t *s) throw() #else // _WIN32 -bool IsAbsolutePath(const wchar_t *s) { return IS_SEPAR(s[0]); } +bool IsAbsolutePath(const wchar_t *s) throw() { return IS_SEPAR(s[0]); } #ifndef USE_UNICODE_FSTRING -unsigned GetRootPrefixSize(CFSTR s) { return IS_SEPAR(s[0]) ? 1 : 0; } +unsigned GetRootPrefixSize(CFSTR s) throw(); +unsigned GetRootPrefixSize(CFSTR s) throw() { return IS_SEPAR(s[0]) ? 1 : 0; } #endif -unsigned GetRootPrefixSize(const wchar_t *s) { return IS_SEPAR(s[0]) ? 1 : 0; } +unsigned GetRootPrefixSize(const wchar_t *s) throw() { return IS_SEPAR(s[0]) ? 1 : 0; } #endif // _WIN32 @@ -347,6 +367,9 @@ unsigned GetRootPrefixSize(const wchar_t *s) { return IS_SEPAR(s[0]) ? 1 : 0; } static bool GetCurDir(UString &path) { path.Empty(); + + #ifdef _WIN32 + DWORD needLength; #ifndef _UNICODE if (!g_IsNT) @@ -365,6 +388,23 @@ static bool GetCurDir(UString &path) path = s; } return (needLength > 0 && needLength <= MAX_PATH); + + #else + + #define MY__PATH_MAX PATH_MAX + // #define MY__PATH_MAX 1024 + + char s[MY__PATH_MAX + 1]; + char *res = getcwd(s, MY__PATH_MAX); + if (!res) + { + // if (errno != ERANGE) + return false; + } + path = GetUnicodeString(s); + return true; + + #endif } static bool ResolveDotsFolders(UString &s) @@ -388,7 +428,7 @@ static bool ResolveDotsFolders(UString &s) { if (i == 0) return false; - int k = i - 2; + int k = (int)i - 2; i += 2; for (;; k--) @@ -407,8 +447,8 @@ static bool ResolveDotsFolders(UString &s) if (k >= 0) { - num = i - k; - i = k; + num = i - (unsigned)k; + i = (unsigned)k; } else { @@ -528,6 +568,7 @@ int GetUseSuperPathType(CFSTR s) throw() } + /* returns false in two cases: - if GetCurDir was used, and GetCurDir returned error. @@ -538,7 +579,6 @@ int GetUseSuperPathType(CFSTR s) throw() for absolute paths, returns true, res is Super path. */ - static bool GetSuperPathBase(CFSTR s, UString &res) { res.Empty(); @@ -702,6 +742,8 @@ bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew) return false; superPath = fs2us(path); } + + NormalizeDirSeparators(superPath); return true; } return false; @@ -712,6 +754,10 @@ bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew) if (!GetSuperPathBase(s1, d1) || !GetSuperPathBase(s2, d2)) return false; + + NormalizeDirSeparators(d1); + NormalizeDirSeparators(d2); + if (d1.IsEmpty() && d2.IsEmpty() && onlyIfNew) return false; if (d1.IsEmpty()) d1 = fs2us(s1); diff --git a/CPP/Windows/FileName.h b/CPP/Windows/FileName.h index 2c9c56db..de8bd134 100644 --- a/CPP/Windows/FileName.h +++ b/CPP/Windows/FileName.h @@ -17,6 +17,10 @@ int FindSepar(const FChar *s) throw(); void NormalizeDirPathPrefix(FString &dirPath); // ensures that it ended with '\\', if dirPath is not epmty void NormalizeDirPathPrefix(UString &dirPath); +#ifdef _WIN32 +void NormalizeDirSeparators(FString &s); +#endif + bool IsDrivePath(const wchar_t *s) throw(); // first 3 chars are drive chars like "a:\\" bool IsAltPathPrefix(CFSTR s) throw(); /* name: */ diff --git a/CPP/Windows/FileSystem.cpp b/CPP/Windows/FileSystem.cpp index 6c1f48a2..62594532 100644 --- a/CPP/Windows/FileSystem.cpp +++ b/CPP/Windows/FileSystem.cpp @@ -19,6 +19,8 @@ namespace NWindows { namespace NFile { namespace NSystem { +#ifdef _WIN32 + bool MyGetVolumeInformation( CFSTR rootPath, UString &volumeName, @@ -90,7 +92,7 @@ bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, #ifndef _UNICODE if (!g_IsNT) { - GetDiskFreeSpaceExA_Pointer pGetDiskFreeSpaceEx = (GetDiskFreeSpaceExA_Pointer)GetProcAddress( + GetDiskFreeSpaceExA_Pointer pGetDiskFreeSpaceEx = (GetDiskFreeSpaceExA_Pointer)(void *)GetProcAddress( GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExA"); if (pGetDiskFreeSpaceEx) { @@ -105,7 +107,7 @@ bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, else #endif { - GetDiskFreeSpaceExW_Pointer pGetDiskFreeSpaceEx = (GetDiskFreeSpaceExW_Pointer)GetProcAddress( + GetDiskFreeSpaceExW_Pointer pGetDiskFreeSpaceEx = (GetDiskFreeSpaceExW_Pointer)(void *)GetProcAddress( GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExW"); if (pGetDiskFreeSpaceEx) { @@ -126,6 +128,8 @@ bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, return true; } +#endif + }}} #endif diff --git a/CPP/Windows/FileSystem.h b/CPP/Windows/FileSystem.h index 9076ea13..9b49a025 100644 --- a/CPP/Windows/FileSystem.h +++ b/CPP/Windows/FileSystem.h @@ -10,6 +10,8 @@ namespace NWindows { namespace NFile { namespace NSystem { +#ifdef _WIN32 + bool MyGetVolumeInformation( CFSTR rootPath , UString &volumeName, @@ -22,6 +24,8 @@ UINT MyGetDriveType(CFSTR pathName); bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); +#endif + }}} #endif diff --git a/CPP/Windows/Handle.h b/CPP/Windows/Handle.h index bb7cb705..5878c830 100644 --- a/CPP/Windows/Handle.h +++ b/CPP/Windows/Handle.h @@ -3,9 +3,11 @@ #ifndef __WINDOWS_HANDLE_H #define __WINDOWS_HANDLE_H +#include "../Common/MyTypes.h" + namespace NWindows { -class CHandle +class CHandle MY_UNCOPYABLE { protected: HANDLE _handle; diff --git a/CPP/Windows/MemoryLock.cpp b/CPP/Windows/MemoryLock.cpp index f9d08a6e..fdfbeb9d 100644 --- a/CPP/Windows/MemoryLock.cpp +++ b/CPP/Windows/MemoryLock.cpp @@ -75,11 +75,11 @@ typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *); /* We suppose that Window 10 works incorrectly with "Large Pages" at: - - Windows 10 1703 (15063) - - Windows 10 1709 (16299) - - - Windows 10 1809 (17763) on some CPUs that have no 1 GB page support. - We need more information about that new BUG in Windows. + - Windows 10 1703 (15063) : incorrect allocating after VirtualFree() + - Windows 10 1709 (16299) : incorrect allocating after VirtualFree() + - Windows 10 1809 (17763) : the failures for blocks of 1 GiB and larger, + if CPU doesn't support 1 GB pages. + Windows 10 1903 (18362) probably works correctly. */ unsigned Get_LargePages_RiskLevel() @@ -88,7 +88,7 @@ unsigned Get_LargePages_RiskLevel() HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll"); if (!ntdll) return 0; - Func_RtlGetVersion func = (Func_RtlGetVersion)GetProcAddress(ntdll, "RtlGetVersion"); + Func_RtlGetVersion func = (Func_RtlGetVersion)(void *)GetProcAddress(ntdll, "RtlGetVersion"); if (!func) return 0; func(&vi); @@ -100,7 +100,7 @@ unsigned Get_LargePages_RiskLevel() return 1; #ifdef MY_CPU_X86_OR_AMD64 - if (!CPU_IsSupported_PageGB()) + if (vi.dwBuildNumber < 18362 && !CPU_IsSupported_PageGB()) return 1; #endif diff --git a/CPP/Windows/Menu.cpp b/CPP/Windows/Menu.cpp index 3834881a..3ad69530 100644 --- a/CPP/Windows/Menu.cpp +++ b/CPP/Windows/Menu.cpp @@ -26,11 +26,15 @@ will not work at NT 4.0, if cbSize is set as sizeof(MENUITEMINFO*). So we use size of old version of structure. */ #if defined(UNDER_CE) || defined(_WIN64) || (WINVER < 0x0500) + #ifndef _UNICODE #define my_compatib_MENUITEMINFOA_size sizeof(MENUITEMINFOA) + #endif #define my_compatib_MENUITEMINFOW_size sizeof(MENUITEMINFOW) #else #define MY_STRUCT_SIZE_BEFORE(structname, member) ((UINT)(UINT_PTR)((LPBYTE)(&((structname*)0)->member) - (LPBYTE)(structname*)0)) + #ifndef _UNICODE #define my_compatib_MENUITEMINFOA_size MY_STRUCT_SIZE_BEFORE(MENUITEMINFOA, hbmpItem) + #endif #define my_compatib_MENUITEMINFOW_size MY_STRUCT_SIZE_BEFORE(MENUITEMINFOW, hbmpItem) #endif @@ -145,7 +149,7 @@ bool CMenu::SetItem(UINT itemIndex, bool byPosition, const CMenuItem &item) if (item.IsString()) { s = GetSystemString(item.StringValue); - si.dwTypeData = (LPTSTR)(LPCTSTR)s; + si.dwTypeData = s.Ptr_non_const(); } return SetItemInfo(itemIndex, byPosition, &si); } @@ -155,7 +159,7 @@ bool CMenu::SetItem(UINT itemIndex, bool byPosition, const CMenuItem &item) MENUITEMINFOW si; ConvertItemToSysForm(item, si); if (item.IsString()) - si.dwTypeData = (LPWSTR)(LPCWSTR)item.StringValue; + si.dwTypeData = item.StringValue.Ptr_non_const(); return SetItemInfo(itemIndex, byPosition, &si); } } @@ -171,7 +175,7 @@ bool CMenu::InsertItem(UINT itemIndex, bool byPosition, const CMenuItem &item) if (item.IsString()) { s = GetSystemString(item.StringValue); - si.dwTypeData = (LPTSTR)(LPCTSTR)s; + si.dwTypeData = s.Ptr_non_const(); } return InsertItem(itemIndex, byPosition, &si); } @@ -181,7 +185,7 @@ bool CMenu::InsertItem(UINT itemIndex, bool byPosition, const CMenuItem &item) MENUITEMINFOW si; ConvertItemToSysForm(item, si); if (item.IsString()) - si.dwTypeData = (LPWSTR)(LPCWSTR)item.StringValue; + si.dwTypeData = item.StringValue.Ptr_non_const(); #ifdef UNDER_CE UINT flags = (item.fType & MFT_SEPARATOR) ? MF_SEPARATOR : MF_STRING; UINT id = item.wID; diff --git a/CPP/Windows/Net.cpp b/CPP/Windows/Net.cpp index 14d06d6e..2a3952a1 100644 --- a/CPP/Windows/Net.cpp +++ b/CPP/Windows/Net.cpp @@ -35,11 +35,11 @@ DWORD CEnum::Open(DWORD scope, DWORD type, DWORD usage, LPNETRESOURCEW netResour } #endif -static void SetComplexString(bool &defined, CSysString &destString, LPCTSTR srsString) +static void SetComplexString(bool &defined, CSysString &destString, LPCTSTR srcString) { - defined = (srsString != 0); + defined = (srcString != 0); if (defined) - destString = srsString; + destString = srcString; else destString.Empty(); } @@ -59,9 +59,9 @@ static void ConvertNETRESOURCEToCResource(const NETRESOURCE &netResource, CResou static void SetComplexString2(LPTSTR *destString, bool defined, const CSysString &srcString) { if (defined) - *destString = (TCHAR *)(const TCHAR *)srcString; + *destString = srcString.Ptr_non_const(); else - *destString = 0; + *destString = NULL; } static void ConvertCResourceToNETRESOURCE(const CResource &resource, NETRESOURCE &netResource) @@ -78,11 +78,11 @@ static void ConvertCResourceToNETRESOURCE(const CResource &resource, NETRESOURCE #ifndef _UNICODE -static void SetComplexString(bool &defined, UString &destString, LPCWSTR srsString) +static void SetComplexString(bool &defined, UString &destString, LPCWSTR src) { - defined = (srsString != 0); + defined = (src != NULL); if (defined) - destString = srsString; + destString = src; else destString.Empty(); } @@ -102,9 +102,9 @@ static void ConvertNETRESOURCEToCResource(const NETRESOURCEW &netResource, CReso static void SetComplexString2(LPWSTR *destString, bool defined, const UString &srcString) { if (defined) - *destString = (WCHAR *)(const WCHAR *)srcString; + *destString = srcString.Ptr_non_const(); else - *destString = 0; + *destString = NULL; } static void ConvertCResourceToNETRESOURCE(const CResourceW &resource, NETRESOURCEW &netResource) @@ -141,10 +141,8 @@ static void ConvertResourceToResourceW(const CResource &resource, CResourceW &re DWORD CEnum::Open(DWORD scope, DWORD type, DWORD usage, const CResource *resource) { NETRESOURCE netResource; - LPNETRESOURCE pointer; - if (resource == 0) - pointer = 0; - else + LPNETRESOURCE pointer = NULL; + if (resource) { ConvertCResourceToNETRESOURCE(*resource, netResource); pointer = &netResource; @@ -158,21 +156,17 @@ DWORD CEnum::Open(DWORD scope, DWORD type, DWORD usage, const CResourceW *resour if (g_IsNT) { NETRESOURCEW netResource; - LPNETRESOURCEW pointer; - if (resource == 0) - pointer = 0; - else + LPNETRESOURCEW pointer = NULL; + if (resource) { ConvertCResourceToNETRESOURCE(*resource, netResource); pointer = &netResource; } return Open(scope, type, usage, pointer); } - CResource *pointer; CResource resourceA; - if (resource == 0) - pointer = 0; - else + CResource *pointer = NULL; + if (resource) { ConvertResourceWToResource(*resource, resourceA); pointer = &resourceA; @@ -206,7 +200,7 @@ DWORD CEnum::Next(CResource &resource) { const DWORD kBufferSize = 16384; CByteArr byteBuffer(kBufferSize); - LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (BYTE *)(byteBuffer); + LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (void *) (BYTE *)(byteBuffer); ZeroMemory(lpnrLocal, kBufferSize); DWORD bufferSize = kBufferSize; DWORD numEntries = 1; @@ -226,7 +220,7 @@ DWORD CEnum::Next(CResourceW &resource) { const DWORD kBufferSize = 16384; CByteArr byteBuffer(kBufferSize); - LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (BYTE *)(byteBuffer); + LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (void *) (BYTE *)(byteBuffer); ZeroMemory(lpnrLocal, kBufferSize); DWORD bufferSize = kBufferSize; DWORD numEntries = 1; @@ -250,7 +244,7 @@ DWORD GetResourceParent(const CResource &resource, CResource &parentResource) { const DWORD kBufferSize = 16384; CByteArr byteBuffer(kBufferSize); - LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (BYTE *)(byteBuffer); + LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (void *) (BYTE *)(byteBuffer); ZeroMemory(lpnrLocal, kBufferSize); DWORD bufferSize = kBufferSize; NETRESOURCE netResource; @@ -269,7 +263,7 @@ DWORD GetResourceParent(const CResourceW &resource, CResourceW &parentResource) { const DWORD kBufferSize = 16384; CByteArr byteBuffer(kBufferSize); - LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (BYTE *)(byteBuffer); + LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (void *) (BYTE *)(byteBuffer); ZeroMemory(lpnrLocal, kBufferSize); DWORD bufferSize = kBufferSize; NETRESOURCEW netResource; @@ -293,7 +287,7 @@ DWORD GetResourceInformation(const CResource &resource, { const DWORD kBufferSize = 16384; CByteArr byteBuffer(kBufferSize); - LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (BYTE *)(byteBuffer); + LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (void *) (BYTE *)(byteBuffer); ZeroMemory(lpnrLocal, kBufferSize); DWORD bufferSize = kBufferSize; NETRESOURCE netResource; @@ -317,7 +311,7 @@ DWORD GetResourceInformation(const CResourceW &resource, { const DWORD kBufferSize = 16384; CByteArr byteBuffer(kBufferSize); - LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (BYTE *)(byteBuffer); + LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (void *) (BYTE *)(byteBuffer); ZeroMemory(lpnrLocal, kBufferSize); DWORD bufferSize = kBufferSize; NETRESOURCEW netResource; diff --git a/CPP/Windows/NtCheck.h b/CPP/Windows/NtCheck.h index a1b89ef2..0af32911 100644 --- a/CPP/Windows/NtCheck.h +++ b/CPP/Windows/NtCheck.h @@ -17,6 +17,8 @@ static inline bool IsItWindowsNT() #endif #ifndef _UNICODE + extern + bool g_IsNT; #if defined(_WIN64) || defined(UNDER_CE) bool g_IsNT = true; #define SET_IS_NT diff --git a/CPP/Windows/ProcessUtils.cpp b/CPP/Windows/ProcessUtils.cpp index f7878d51..9bf05383 100644 --- a/CPP/Windows/ProcessUtils.cpp +++ b/CPP/Windows/ProcessUtils.cpp @@ -24,6 +24,21 @@ static UString GetQuotedString(const UString &s) WRes CProcess::Create(LPCWSTR imageName, const UString ¶ms, LPCWSTR curDir) { + /* + OutputDebugStringW(L"CProcess::Create"); + OutputDebugStringW(imageName); + if (params) + { + OutputDebugStringW(L"params:"); + OutputDebugStringW(params); + } + if (curDir) + { + OutputDebugStringW(L"cur dir:"); + OutputDebugStringW(curDir); + } + */ + Close(); const UString params2 = #ifndef UNDER_CE @@ -52,7 +67,8 @@ WRes CProcess::Create(LPCWSTR imageName, const UString ¶ms, LPCWSTR curDir) CSysString curDirA; if (curDir != 0) curDirA = GetSystemString(curDir); - result = ::CreateProcessA(NULL, (LPSTR)(LPCSTR)GetSystemString(params2), + const AString s = GetSystemString(params2); + result = ::CreateProcessA(NULL, s.Ptr_non_const(), NULL, NULL, FALSE, 0, NULL, ((curDir != 0) ? (LPCSTR)curDirA: 0), &si, &pi); } else @@ -67,8 +83,8 @@ WRes CProcess::Create(LPCWSTR imageName, const UString ¶ms, LPCWSTR curDir) si.cbReserved2 = 0; si.lpReserved2 = 0; - result = CreateProcessW(imageName, (LPWSTR)(LPCWSTR)params2, - NULL, NULL, FALSE, 0, NULL, (LPWSTR)curDir, &si, &pi); + result = CreateProcessW(imageName, params2.Ptr_non_const(), + NULL, NULL, FALSE, 0, NULL, curDir, &si, &pi); } if (result == 0) return ::GetLastError(); diff --git a/CPP/Windows/ProcessUtils.h b/CPP/Windows/ProcessUtils.h index a50bb5fc..e46f9ab2 100644 --- a/CPP/Windows/ProcessUtils.h +++ b/CPP/Windows/ProcessUtils.h @@ -3,7 +3,7 @@ #ifndef __WINDOWS_PROCESS_UTILS_H #define __WINDOWS_PROCESS_UTILS_H -#include <psapi.h> +#include <Psapi.h> #include "../Common/MyString.h" diff --git a/CPP/Windows/PropVariant.cpp b/CPP/Windows/PropVariant.cpp index c4ad3acb..8cc89a3a 100644 --- a/CPP/Windows/PropVariant.cpp +++ b/CPP/Windows/PropVariant.cpp @@ -278,7 +278,8 @@ HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw() HRESULT hr = Clear(); if (FAILED(hr)) return hr; - memcpy(this, pSrc, sizeof(PROPVARIANT)); + // memcpy((PROPVARIANT *)this, pSrc, sizeof(PROPVARIANT)); + *(PROPVARIANT *)this = *pSrc; pSrc->vt = VT_EMPTY; return S_OK; } @@ -291,7 +292,8 @@ HRESULT CPropVariant::Detach(PROPVARIANT *pDest) throw() if (FAILED(hr)) return hr; } - memcpy(pDest, this, sizeof(PROPVARIANT)); + // memcpy(pDest, this, sizeof(PROPVARIANT)); + *pDest = *(PROPVARIANT *)this; vt = VT_EMPTY; return S_OK; } diff --git a/CPP/Windows/PropVariantConv.cpp b/CPP/Windows/PropVariantConv.cpp index 65aa9f7e..b58d37e6 100644 --- a/CPP/Windows/PropVariantConv.cpp +++ b/CPP/Windows/PropVariantConv.cpp @@ -1,4 +1,4 @@ -// PropVariantConvert.cpp +// PropVariantConv.cpp #include "StdAfx.h" @@ -86,7 +86,7 @@ bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *dest, int level) th bool res = ConvertUtcFileTimeToString(ft, s, level); for (unsigned i = 0;; i++) { - unsigned char c = s[i]; + Byte c = (Byte)s[i]; dest[i] = c; if (c == 0) break; diff --git a/CPP/Windows/PropVariantUtils.cpp b/CPP/Windows/PropVariantUtils.cpp index fab556a5..6daee839 100644 --- a/CPP/Windows/PropVariantUtils.cpp +++ b/CPP/Windows/PropVariantUtils.cpp @@ -128,7 +128,7 @@ void FlagsToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags, NCOM } -AString Flags64ToString(const CUInt32PCharPair *pairs, unsigned num, UInt64 flags) +static AString Flags64ToString(const CUInt32PCharPair *pairs, unsigned num, UInt64 flags) { AString s; for (unsigned i = 0; i < num; i++) diff --git a/CPP/Windows/Registry.cpp b/CPP/Windows/Registry.cpp index a2893131..2c4643bc 100644 --- a/CPP/Windows/Registry.cpp +++ b/CPP/Windows/Registry.cpp @@ -119,7 +119,7 @@ LONG CKey::SetValue(LPCTSTR name, UInt32 value) throw() { MYASSERT(_object != NULL); return RegSetValueEx(_object, name, 0, REG_DWORD, - (BYTE * const)&value, sizeof(UInt32)); + (const BYTE *)&value, sizeof(UInt32)); } LONG CKey::SetValue(LPCTSTR name, bool value) throw() @@ -132,7 +132,7 @@ LONG CKey::SetValue(LPCTSTR name, LPCTSTR value) throw() MYASSERT(value != NULL); MYASSERT(_object != NULL); return RegSetValueEx(_object, name, 0, REG_SZ, - (const BYTE * )value, (lstrlen(value) + 1) * sizeof(TCHAR)); + (const BYTE *)value, ((DWORD)lstrlen(value) + 1) * sizeof(TCHAR)); } /* @@ -193,7 +193,7 @@ LONG CKey::QueryValue(LPCTSTR name, UInt32 &value) throw() { DWORD type = 0; DWORD count = sizeof(DWORD); - LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, + LONG res = RegQueryValueEx(_object, name, NULL, &type, (LPBYTE)&value, &count); MYASSERT((res != ERROR_SUCCESS) || (type == REG_DWORD)); MYASSERT((res != ERROR_SUCCESS) || (count == sizeof(UInt32))); @@ -219,7 +219,7 @@ LONG CKey::GetValue_IfOk(LPCTSTR name, UInt32 &value) throw() LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value) throw() { - bool newVal; + bool newVal = false; LONG res = QueryValue(name, newVal); if (res == ERROR_SUCCESS) value = newVal; @@ -229,7 +229,7 @@ LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value) throw() LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count) throw() { DWORD type = 0; - LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count); + LONG res = RegQueryValueEx(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count); MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); return res; } @@ -239,7 +239,7 @@ LONG CKey::QueryValue(LPCTSTR name, CSysString &value) value.Empty(); DWORD type = 0; UInt32 curSize = 0; - LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&curSize); + LONG res = RegQueryValueEx(_object, name, NULL, &type, NULL, (DWORD *)&curSize); if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) return res; UInt32 curSize2 = curSize; @@ -296,7 +296,7 @@ LONG CKey::QueryValue(LPCWSTR name, UString &value) LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count) throw() { DWORD type = 0; - LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count); + LONG res = RegQueryValueEx(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count); MYASSERT((res != ERROR_SUCCESS) || (type == REG_BINARY)); return res; } @@ -306,7 +306,7 @@ LONG CKey::QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize) { DWORD type = 0; dataSize = 0; - LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&dataSize); + LONG res = RegQueryValueEx(_object, name, NULL, &type, NULL, (DWORD *)&dataSize); if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) return res; value.Alloc(dataSize); @@ -369,7 +369,7 @@ LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings) if (dataSize % sizeof(wchar_t) != 0) return E_FAIL; - const wchar_t *data = (const wchar_t *)(const Byte *)buffer; + const wchar_t *data = (const wchar_t *)(const void *)(const Byte *)buffer; size_t numChars = dataSize / sizeof(wchar_t); size_t prev = 0; UString s; diff --git a/CPP/Windows/ResourceString.cpp b/CPP/Windows/ResourceString.cpp index cc8b964a..ae8182ed 100644 --- a/CPP/Windows/ResourceString.cpp +++ b/CPP/Windows/ResourceString.cpp @@ -25,10 +25,10 @@ static CSysString MyLoadStringA(HINSTANCE hInstance, UINT resourceID) do { size <<= 1; - len = ::LoadString(hInstance, resourceID, s.GetBuf(size - 1), size); + len = ::LoadString(hInstance, resourceID, s.GetBuf((unsigned)size - 1), size); } while (size - len <= 1); - s.ReleaseBuf_CalcLen(len); + s.ReleaseBuf_CalcLen((unsigned)len); return s; } @@ -43,10 +43,10 @@ static void MyLoadString2(HINSTANCE hInstance, UINT resourceID, UString &s) do { size <<= 1; - len = ::LoadStringW(hInstance, resourceID, s.GetBuf(size - 1), size); + len = ::LoadStringW(hInstance, resourceID, s.GetBuf((unsigned)size - 1), size); } while (size - len <= 1); - s.ReleaseBuf_CalcLen(len); + s.ReleaseBuf_CalcLen((unsigned)len); } // NT4 doesn't support LoadStringW(,,, 0) to get pointer to resource string. So we don't use it. diff --git a/CPP/Windows/SecurityUtils.cpp b/CPP/Windows/SecurityUtils.cpp index 67a9d7fd..640c90dc 100644 --- a/CPP/Windows/SecurityUtils.cpp +++ b/CPP/Windows/SecurityUtils.cpp @@ -34,7 +34,7 @@ bool MyLookupAccountSid(LPCTSTR systemName, PSID sid, static void SetLsaString(LPWSTR src, PLSA_UNICODE_STRING dest) { - int len = (int)wcslen(src); + size_t len = (size_t)wcslen(src); dest->Length = (USHORT)(len * sizeof(WCHAR)); dest->MaximumLength = (USHORT)((len + 1) * sizeof(WCHAR)); dest->Buffer = src; diff --git a/CPP/Windows/Shell.cpp b/CPP/Windows/Shell.cpp index b424e67c..d0f9032c 100644 --- a/CPP/Windows/Shell.cpp +++ b/CPP/Windows/Shell.cpp @@ -192,7 +192,7 @@ bool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath) } -int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data) +static int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data) { #ifndef UNDER_CE switch (uMsg) @@ -221,7 +221,7 @@ int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM da } -bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags, +static bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags, LPCTSTR initialFolder, CSysString &resultPath) { CSysString displayName; @@ -275,7 +275,7 @@ bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path) typedef LPITEMIDLIST (WINAPI * SHBrowseForFolderWP)(LPBROWSEINFOW lpbi); -bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath) +static bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath) { NWindows::NCOM::CComInitializer comInitializer; SHBrowseForFolderWP shBrowseForFolderW = (SHBrowseForFolderWP) @@ -290,7 +290,7 @@ bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath) return GetPathFromIDList(itemIDList, resultPath); } - +static int CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data) { switch (uMsg) diff --git a/CPP/Windows/Shell.h b/CPP/Windows/Shell.h index 4bff18cf..de91d3f1 100644 --- a/CPP/Windows/Shell.h +++ b/CPP/Windows/Shell.h @@ -3,8 +3,8 @@ #ifndef __WINDOWS_SHELL_H #define __WINDOWS_SHELL_H -#include <windows.h> -#include <shlobj.h> +#include "../Common/MyWindows.h" +#include <ShlObj.h> #include "../Common/MyString.h" diff --git a/CPP/Windows/Synchronization.cpp b/CPP/Windows/Synchronization.cpp index 5f86d1eb..fbf919dc 100644 --- a/CPP/Windows/Synchronization.cpp +++ b/CPP/Windows/Synchronization.cpp @@ -2,9 +2,62 @@ #include "StdAfx.h" +#ifndef _WIN32 + #include "Synchronization.h" namespace NWindows { namespace NSynchronization { +/* +#define INFINITE 0xFFFFFFFF +#define MAXIMUM_WAIT_OBJECTS 64 +#define STATUS_ABANDONED_WAIT_0 ((NTSTATUS)0x00000080L) +#define WAIT_ABANDONED ((STATUS_ABANDONED_WAIT_0 ) + 0 ) +#define WAIT_ABANDONED_0 ((STATUS_ABANDONED_WAIT_0 ) + 0 ) +// WINAPI +DWORD WaitForMultipleObjects(DWORD count, const HANDLE *handles, BOOL wait_all, DWORD timeout); +*/ + +DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles) +{ + if (count < 1) + { + // abort(); + SetLastError(EINVAL); + return WAIT_FAILED; + } + + CSynchro *synchro = handles[0]->_sync; + synchro->Enter(); + + // #ifdef DEBUG_SYNCHRO + for (DWORD i = 1; i < count; i++) + { + if (synchro != handles[i]->_sync) + { + // abort(); + synchro->Leave(); + SetLastError(EINVAL); + return WAIT_FAILED; + } + } + // #endif + + for (;;) + { + for (DWORD i = 0; i < count; i++) + { + if (handles[i]->IsSignaledAndUpdate()) + { + synchro->Leave(); + return WAIT_OBJECT_0 + i; + } + } + synchro->WaitCond(); + } +} + }} + +#endif diff --git a/CPP/Windows/Synchronization.h b/CPP/Windows/Synchronization.h index dc695f6f..98ea0b69 100644 --- a/CPP/Windows/Synchronization.h +++ b/CPP/Windows/Synchronization.h @@ -5,6 +5,8 @@ #include "../../C/Threads.h" +#include "../Common/MyTypes.h" + #include "Defs.h" #ifdef _WIN32 @@ -14,17 +16,19 @@ namespace NWindows { namespace NSynchronization { -class CBaseEvent +class CBaseEvent MY_UNCOPYABLE { protected: ::CEvent _object; public: bool IsCreated() { return Event_IsCreated(&_object) != 0; } - operator HANDLE() { return _object; } + CBaseEvent() { Event_Construct(&_object); } ~CBaseEvent() { Close(); } WRes Close() { return Event_Close(&_object); } + #ifdef _WIN32 + operator HANDLE() { return _object; } WRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL) { _object = ::CreateEvent(sa, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name); @@ -54,10 +58,10 @@ public: { return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0); } - WRes CreateIfNotCreated() + WRes CreateIfNotCreated_Reset() { if (IsCreated()) - return 0; + return Reset(); return ManualResetEvent_CreateNotSignaled(&_object); } #ifdef _WIN32 @@ -75,21 +79,25 @@ public: { return AutoResetEvent_CreateNotSignaled(&_object); } - WRes CreateIfNotCreated() + WRes CreateIfNotCreated_Reset() { if (IsCreated()) - return 0; + return Reset(); return AutoResetEvent_CreateNotSignaled(&_object); } }; + +/* #ifdef _WIN32 + class CObject: public CHandle { public: WRes Lock(DWORD timeoutInterval = INFINITE) { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); } }; + class CMutex: public CObject { public: @@ -114,33 +122,43 @@ public: return ::ReleaseMutex(_handle) ? 0 : ::GetLastError(); } }; -class CMutexLock + +class CMutexLock MY_UNCOPYABLE { CMutex *_object; public: CMutexLock(CMutex &object): _object(&object) { _object->Lock(); } ~CMutexLock() { _object->Release(); } }; -#endif -class CSemaphore +#endif // _WIN32 +*/ + + +class CSemaphore MY_UNCOPYABLE { ::CSemaphore _object; public: CSemaphore() { Semaphore_Construct(&_object); } ~CSemaphore() { Close(); } - WRes Close() { return Semaphore_Close(&_object); } + WRes Close() { return Semaphore_Close(&_object); } + + #ifdef _WIN32 operator HANDLE() { return _object; } - WRes Create(UInt32 initiallyCount, UInt32 maxCount) + #endif + + // bool IsCreated() const { return Semaphore_IsCreated(&_object) != 0; } + + WRes Create(UInt32 initCount, UInt32 maxCount) { - return Semaphore_Create(&_object, initiallyCount, maxCount); + return Semaphore_Create(&_object, initCount, maxCount); } WRes Release() { return Semaphore_Release1(&_object); } WRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); } WRes Lock() { return Semaphore_Wait(&_object); } }; -class CCriticalSection +class CCriticalSection MY_UNCOPYABLE { ::CCriticalSection _object; public: @@ -150,7 +168,7 @@ public: void Leave() { CriticalSection_Leave(&_object); } }; -class CCriticalSectionLock +class CCriticalSectionLock MY_UNCOPYABLE { CCriticalSection *_object; void Unlock() { _object->Leave(); } @@ -159,6 +177,213 @@ public: ~CCriticalSectionLock() { Unlock(); } }; + +#ifdef _WIN32 + +typedef HANDLE CHandle_WFMO; +typedef CSemaphore CSemaphore_WFMO; +typedef CAutoResetEvent CAutoResetEvent_WFMO; +typedef CManualResetEvent CManualResetEvent_WFMO; + +inline DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles) +{ + return ::WaitForMultipleObjects(count, handles, FALSE, INFINITE); +} + +#define SYNC_OBJ_DECL(obj) +#define SYNC_WFMO(x) +#define SYNC_PARAM(x) +#define SYNC_PARAM_DECL(x) + +#else // _WIN32 + +// POSIX sync objects for WaitForMultipleObjects + +#define SYNC_WFMO(x) x +#define SYNC_PARAM(x) x, +#define SYNC_PARAM_DECL(x) NWindows::NSynchronization::CSynchro *x +#define SYNC_OBJ_DECL(x) NWindows::NSynchronization::CSynchro x; + +class CSynchro MY_UNCOPYABLE +{ + pthread_mutex_t _mutex; + pthread_cond_t _cond; + bool _isValid; + +public: + CSynchro() { _isValid = false; } + ~CSynchro() + { + if (_isValid) + { + ::pthread_mutex_destroy(&_mutex); + ::pthread_cond_destroy(&_cond); + } + _isValid = false; + } + WRes Create() + { + RINOK(::pthread_mutex_init(&_mutex, 0)); + WRes ret = ::pthread_cond_init(&_cond, 0); + _isValid = 1; + return ret; + } + WRes Enter() + { + return ::pthread_mutex_lock(&_mutex); + } + WRes Leave() + { + return ::pthread_mutex_unlock(&_mutex); + } + WRes WaitCond() + { + return ::pthread_cond_wait(&_cond, &_mutex); + } + WRes LeaveAndSignal() + { + WRes res1 = ::pthread_cond_broadcast(&_cond); + WRes res2 = ::pthread_mutex_unlock(&_mutex); + return (res2 ? res2 : res1); + } +}; + + +struct CBaseHandle_WFMO; +typedef NWindows::NSynchronization::CBaseHandle_WFMO *CHandle_WFMO; + +// these constants are from Windows +#define WAIT_OBJECT_0 0 +#define WAIT_FAILED ((DWORD)0xFFFFFFFF) + +DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles); + + +struct CBaseHandle_WFMO MY_UNCOPYABLE +{ + CSynchro *_sync; + + CBaseHandle_WFMO(): _sync(NULL) {} + + operator CHandle_WFMO() { return this; } + virtual bool IsSignaledAndUpdate() = 0; +}; + + +class CBaseEvent_WFMO : public CBaseHandle_WFMO +{ + bool _manual_reset; + bool _state; + +public: + + // bool IsCreated() { return (this->_sync != NULL); } + // CBaseEvent_WFMO() { ; } + ~CBaseEvent_WFMO() { Close(); } + + WRes Close() { this->_sync = NULL; return 0; } + + WRes Create( + CSynchro *sync, + bool manualReset, bool initiallyOwn) + { + this->_sync = sync; + this->_manual_reset = manualReset; + this->_state = initiallyOwn; + return 0; + } + + WRes Set() + { + RINOK(this->_sync->Enter()); + this->_state = true; + return this->_sync->LeaveAndSignal(); + } + + WRes Reset() + { + RINOK(this->_sync->Enter()); + this->_state = false; + return this->_sync->Leave(); + } + + virtual bool IsSignaledAndUpdate() + { + if (this->_state == false) + return false; + if (this->_manual_reset == false) + this->_state = false; + return true; + } +}; + + +class CManualResetEvent_WFMO: public CBaseEvent_WFMO +{ +public: + WRes Create(CSynchro *sync, bool initiallyOwn = false) { return CBaseEvent_WFMO::Create(sync, true, initiallyOwn); } +}; + + +class CAutoResetEvent_WFMO: public CBaseEvent_WFMO +{ +public: + WRes Create(CSynchro *sync) { return CBaseEvent_WFMO::Create(sync, false, false); } + WRes CreateIfNotCreated_Reset(CSynchro *sync) + { + return Create(sync); + } +}; + + +class CSemaphore_WFMO : public CBaseHandle_WFMO +{ + UInt32 _count; + UInt32 _maxCount; + +public: + CSemaphore_WFMO() : _count(0), _maxCount(0) {} + + WRes Close() { this->_sync = NULL; return 0; } + + WRes Create(CSynchro *sync, UInt32 initCount, UInt32 maxCount) + { + if (initCount > maxCount || maxCount < 1) + return EINVAL; + this->_sync = sync; + this->_count = initCount; + this->_maxCount = maxCount; + return 0; + } + + WRes Release(UInt32 releaseCount = 1) + { + if (releaseCount < 1) + return EINVAL; + + RINOK(this->_sync->Enter()); + UInt32 newCount = this->_count + releaseCount; + if (newCount > this->_maxCount) + { + RINOK(this->_sync->Leave()); + return ERROR_TOO_MANY_POSTS; // EINVAL + } + this->_count = newCount; + + return this->_sync->LeaveAndSignal(); + } + + virtual bool IsSignaledAndUpdate() + { + if (this->_count == 0) + return false; + this->_count--; + return true; + } +}; + +#endif // _WIN32 + }} #endif diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp index cc33169a..099407ec 100644 --- a/CPP/Windows/System.cpp +++ b/CPP/Windows/System.cpp @@ -2,15 +2,27 @@ #include "StdAfx.h" -#include "../Common/MyWindows.h" +#ifndef _WIN32 +#include <unistd.h> +#ifdef __APPLE__ +#include <sys/sysctl.h> +#else +#include <sys/sysinfo.h> +#endif +#endif #include "../Common/Defs.h" +// #include "../Common/MyWindows.h" + +// #include "../../C/CpuArch.h" #include "System.h" namespace NWindows { namespace NSystem { +#ifdef _WIN32 + UInt32 CountAffinity(DWORD_PTR mask) { UInt32 num = 0; @@ -19,8 +31,6 @@ UInt32 CountAffinity(DWORD_PTR mask) return num; } -#ifdef _WIN32 - BOOL CProcessAffinity::Get() { #ifndef UNDER_CE @@ -52,9 +62,45 @@ UInt32 GetNumberOfProcessors() #else + +BOOL CProcessAffinity::Get() +{ + numSysThreads = GetNumberOfProcessors(); + + /* + numSysThreads = 8; + for (unsigned i = 0; i < numSysThreads; i++) + CpuSet_Set(&cpu_set, i); + return TRUE; + */ + + #ifdef _7ZIP_AFFINITY_SUPPORTED + + // numSysThreads = sysconf(_SC_NPROCESSORS_ONLN); // The number of processors currently online + if (sched_getaffinity(0, sizeof(cpu_set), &cpu_set) != 0) + return FALSE; + return TRUE; + + #else + + // cpu_set = ((CCpuSet)1 << (numSysThreads)) - 1; + return TRUE; + // errno = ENOSYS; + // return FALSE; + + #endif +} + UInt32 GetNumberOfProcessors() { + #ifndef _7ZIP_ST + long n = sysconf(_SC_NPROCESSORS_CONF); // The number of processors configured + if (n < 1) + n = 1; + return (UInt32)n; + #else return 1; + #endif } #endif @@ -87,17 +133,13 @@ typedef struct _MY_MEMORYSTATUSEX { typedef BOOL (WINAPI *GlobalMemoryStatusExP)(MY_LPMEMORYSTATUSEX lpBuffer); -#endif - -#endif - +#endif // !UNDER_CE + bool GetRamSize(UInt64 &size) { size = (UInt64)(sizeof(size_t)) << 29; - #ifdef _WIN32 - #ifndef UNDER_CE MY_MEMORYSTATUSEX stat; stat.dwLength = sizeof(stat); @@ -114,7 +156,7 @@ bool GetRamSize(UInt64 &size) #ifndef UNDER_CE GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP) - ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GlobalMemoryStatusEx"); + (void *)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "GlobalMemoryStatusEx"); if (globalMemoryStatusEx && globalMemoryStatusEx(&stat)) { size = MyMin(stat.ullTotalVirtual, stat.ullTotalPhys); @@ -129,14 +171,61 @@ bool GetRamSize(UInt64 &size) size = MyMin(stat2.dwTotalVirtual, stat2.dwTotalPhys); return true; } - #endif +} + +#else + +// POSIX +// #include <stdio.h> + +bool GetRamSize(UInt64 &size) +{ + size = (UInt64)(sizeof(size_t)) << 29; + + #ifdef __APPLE__ + + #ifdef HW_MEMSIZE + uint64_t val = 0; // support 2Gb+ RAM + int mib[2] = { CTL_HW, HW_MEMSIZE }; + #elif defined(HW_PHYSMEM64) + uint64_t val = 0; // support 2Gb+ RAM + int mib[2] = { CTL_HW, HW_PHYSMEM64 }; + #else + unsigned int val = 0; // For old system + int mib[2] = { CTL_HW, HW_PHYSMEM }; + #endif // HW_MEMSIZE + size_t size_sys = sizeof(val); + + sysctl(mib, 2, &val, &size_sys, NULL, 0); + if (val) + size = val; + + #elif defined(_AIX) + + // fixme #else - return false; + struct sysinfo info; + if (::sysinfo(&info) != 0) + return false; + size = (UInt64)info.mem_unit * info.totalram; + const UInt64 kLimit = (UInt64)1 << (sizeof(size_t) * 8 - 1); + if (size > kLimit) + size = kLimit; + + /* + printf("\n mem_unit = %lld", (UInt64)info.mem_unit); + printf("\n totalram = %lld", (UInt64)info.totalram); + printf("\n freeram = %lld", (UInt64)info.freeram); + */ #endif + + return true; } +#endif + }} diff --git a/CPP/Windows/System.h b/CPP/Windows/System.h index 519e0444..23cb0dab 100644 --- a/CPP/Windows/System.h +++ b/CPP/Windows/System.h @@ -3,11 +3,19 @@ #ifndef __WINDOWS_SYSTEM_H #define __WINDOWS_SYSTEM_H +#ifndef _WIN32 +// #include <sched.h> +#include "../../C/Threads.h" +#endif + #include "../Common/MyTypes.h" namespace NWindows { namespace NSystem { + +#ifdef _WIN32 + UInt32 CountAffinity(DWORD_PTR mask); struct CProcessAffinity @@ -25,12 +33,93 @@ struct CProcessAffinity systemAffinityMask = 1; } + void CpuZero() + { + processAffinityMask = 0; + } + + void CpuSet(unsigned cpuIndex) + { + processAffinityMask |= ((DWORD_PTR)1 << cpuIndex); + } + UInt32 GetNumProcessThreads() const { return CountAffinity(processAffinityMask); } UInt32 GetNumSystemThreads() const { return CountAffinity(systemAffinityMask); } BOOL Get(); + + BOOL SetProcAffinity() const + { + return SetProcessAffinityMask(GetCurrentProcess(), processAffinityMask); + } +}; + + +#else // WIN32 + +struct CProcessAffinity +{ + UInt32 numSysThreads; + + UInt32 GetNumSystemThreads() const { return (UInt32)numSysThreads; } + BOOL Get(); + + #ifdef _7ZIP_AFFINITY_SUPPORTED + + CCpuSet cpu_set; + + void InitST() + { + numSysThreads = 1; + CpuSet_Zero(&cpu_set); + CpuSet_Set(&cpu_set, 0); + } + + UInt32 GetNumProcessThreads() const { return (UInt32)CPU_COUNT(&cpu_set); } + void CpuZero() { CpuSet_Zero(&cpu_set); } + void CpuSet(unsigned cpuIndex) { CpuSet_Set(&cpu_set, cpuIndex); } + int IsCpuSet(unsigned cpuIndex) const { return CpuSet_IsSet(&cpu_set, cpuIndex); } + // void CpuClr(int cpuIndex) { CPU_CLR(cpuIndex, &cpu_set); } + + BOOL SetProcAffinity() const + { + return sched_setaffinity(0, sizeof(cpu_set), &cpu_set) == 0; + } + + #else + + void InitST() + { + numSysThreads = 1; + } + + UInt32 GetNumProcessThreads() const + { + return numSysThreads; + /* + UInt32 num = 0; + for (unsigned i = 0; i < sizeof(cpu_set) * 8; i++) + num += (UInt32)((cpu_set >> i) & 1); + return num; + */ + } + + void CpuZero() { } + void CpuSet(unsigned cpuIndex) { UNUSED_VAR(cpuIndex); } + int IsCpuSet(unsigned cpuIndex) const { return (cpuIndex < numSysThreads) ? 1 : 0; } + + BOOL SetProcAffinity() const + { + errno = ENOSYS; + return FALSE; + } + + #endif }; +#endif + + UInt32 GetNumberOfProcessors(); bool GetRamSize(UInt64 &size); // returns false, if unknown ram size diff --git a/CPP/Windows/SystemInfo.cpp b/CPP/Windows/SystemInfo.cpp new file mode 100644 index 00000000..55403efc --- /dev/null +++ b/CPP/Windows/SystemInfo.cpp @@ -0,0 +1,716 @@ +// Windows/SystemInfo.cpp + +#include "StdAfx.h" + +#include "../../C/CpuArch.h" + +#include "../Common/IntToString.h" + +#ifdef _WIN32 + +#include "Registry.h" + +#else + +#include <sys/utsname.h> +#ifdef __APPLE__ +#include <sys/sysctl.h> +#elif !defined(_AIX) + + +#include <sys/auxv.h> + +#ifdef MY_CPU_ARM_OR_ARM64 +#include <asm/hwcap.h> +#endif +#endif + +#endif + +#include "SystemInfo.h" +#include "System.h" + +using namespace NWindows; + +#ifndef __APPLE__ +static void PrintHex(AString &s, UInt64 v) +{ + char temp[32]; + ConvertUInt64ToHex(v, temp); + s += temp; +} +#endif + +#ifdef MY_CPU_X86_OR_AMD64 + +static void PrintCpuChars(AString &s, UInt32 v) +{ + for (int j = 0; j < 4; j++) + { + Byte b = (Byte)(v & 0xFF); + v >>= 8; + if (b == 0) + break; + s += (char)b; + } +} + + +static void x86cpuid_to_String(const Cx86cpuid &c, AString &s) +{ + s.Empty(); + + UInt32 maxFunc2 = 0; + UInt32 t[3]; + + MyCPUID(0x80000000, &maxFunc2, &t[0], &t[1], &t[2]); + + bool fullNameIsAvail = (maxFunc2 >= 0x80000004); + + if (fullNameIsAvail) + { + for (unsigned i = 0; i < 3; i++) + { + UInt32 d[4] = { 0 }; + MyCPUID(0x80000002 + i, &d[0], &d[1], &d[2], &d[3]); + for (unsigned j = 0; j < 4; j++) + PrintCpuChars(s, d[j]); + } + } + + s.Trim(); + + if (s.IsEmpty()) + { + for (int i = 0; i < 3; i++) + PrintCpuChars(s, c.vendor[i]); + s.Trim(); + } + + s.Add_Space_if_NotEmpty(); + { + char temp[32]; + ConvertUInt32ToHex(c.ver, temp); + s += '('; + s += temp; + s += ')'; + } +} + +/* +static void x86cpuid_all_to_String(AString &s) +{ + Cx86cpuid p; + if (!x86cpuid_CheckAndRead(&p)) + return; + s += "x86cpuid maxFunc = "; + s.Add_UInt32(p.maxFunc); + for (unsigned j = 0; j <= p.maxFunc; j++) + { + s.Add_LF(); + // s.Add_UInt32(j); // align + { + char temp[32]; + ConvertUInt32ToString(j, temp); + unsigned len = (unsigned)strlen(temp); + while (len < 8) + { + len++; + s.Add_Space(); + } + s += temp; + } + + s += ":"; + UInt32 d[4] = { 0 }; + MyCPUID(j, &d[0], &d[1], &d[2], &d[3]); + for (unsigned i = 0; i < 4; i++) + { + char temp[32]; + ConvertUInt32ToHex8Digits(d[i], temp); + s += " "; + s += temp; + } + } +} +*/ + +#endif + + + +#ifdef _WIN32 + +static const char * const k_PROCESSOR_ARCHITECTURE[] = +{ + "x86" // "INTEL" + , "MIPS" + , "ALPHA" + , "PPC" + , "SHX" + , "ARM" + , "IA64" + , "ALPHA64" + , "MSIL" + , "x64" // "AMD64" + , "IA32_ON_WIN64" + , "NEUTRAL" + , "ARM64" + , "ARM32_ON_WIN64" +}; + +#define MY__PROCESSOR_ARCHITECTURE_INTEL 0 +#define MY__PROCESSOR_ARCHITECTURE_AMD64 9 + + +#define MY__PROCESSOR_INTEL_PENTIUM 586 +#define MY__PROCESSOR_AMD_X8664 8664 + +/* +static const CUInt32PCharPair k_PROCESSOR[] = +{ + { 2200, "IA64" }, + { 8664, "x64" } +}; + +#define PROCESSOR_INTEL_386 386 +#define PROCESSOR_INTEL_486 486 +#define PROCESSOR_INTEL_PENTIUM 586 +#define PROCESSOR_INTEL_860 860 +#define PROCESSOR_INTEL_IA64 2200 +#define PROCESSOR_AMD_X8664 8664 +#define PROCESSOR_MIPS_R2000 2000 +#define PROCESSOR_MIPS_R3000 3000 +#define PROCESSOR_MIPS_R4000 4000 +#define PROCESSOR_ALPHA_21064 21064 +#define PROCESSOR_PPC_601 601 +#define PROCESSOR_PPC_603 603 +#define PROCESSOR_PPC_604 604 +#define PROCESSOR_PPC_620 620 +#define PROCESSOR_HITACHI_SH3 10003 +#define PROCESSOR_HITACHI_SH3E 10004 +#define PROCESSOR_HITACHI_SH4 10005 +#define PROCESSOR_MOTOROLA_821 821 +#define PROCESSOR_SHx_SH3 103 +#define PROCESSOR_SHx_SH4 104 +#define PROCESSOR_STRONGARM 2577 // 0xA11 +#define PROCESSOR_ARM720 1824 // 0x720 +#define PROCESSOR_ARM820 2080 // 0x820 +#define PROCESSOR_ARM920 2336 // 0x920 +#define PROCESSOR_ARM_7TDMI 70001 +#define PROCESSOR_OPTIL 18767 // 0x494f +*/ + + +/* +static const char * const k_PF[] = +{ + "FP_ERRATA" + , "FP_EMU" + , "CMPXCHG" + , "MMX" + , "PPC_MOVEMEM_64BIT" + , "ALPHA_BYTE" + , "SSE" + , "3DNOW" + , "RDTSC" + , "PAE" + , "SSE2" + , "SSE_DAZ" + , "NX" + , "SSE3" + , "CMPXCHG16B" + , "CMP8XCHG16" + , "CHANNELS" + , "XSAVE" + , "ARM_VFP_32" + , "ARM_NEON" + , "L2AT" + , "VIRT_FIRMWARE" + , "RDWRFSGSBASE" + , "FASTFAIL" + , "ARM_DIVIDE" + , "ARM_64BIT_LOADSTORE_ATOMIC" + , "ARM_EXTERNAL_CACHE" + , "ARM_FMAC" + , "RDRAND" + , "ARM_V8" + , "ARM_V8_CRYPTO" + , "ARM_V8_CRC32" + , "RDTSCP" + , "RDPID" + , "ARM_V81_ATOMIC" + , "MONITORX" +}; +*/ + +#endif + + +#ifdef _WIN32 + +static void PrintPage(AString &s, UInt32 v) +{ + if ((v & 0x3FF) == 0) + { + s.Add_UInt32(v >> 10); + s += "K"; + } + else + s.Add_UInt32(v >> 10); +} + +static AString TypeToString2(const char * const table[], unsigned num, UInt32 value) +{ + char sz[16]; + const char *p = NULL; + if (value < num) + p = table[value]; + if (!p) + { + ConvertUInt32ToString(value, sz); + p = sz; + } + return (AString)p; +} + +// #if defined(_7ZIP_LARGE_PAGES) || defined(_WIN32) +// #ifdef _WIN32 +void PrintSize_KMGT_Or_Hex(AString &s, UInt64 v) +{ + char c = 0; + if ((v & 0x3FF) == 0) { v >>= 10; c = 'K'; + if ((v & 0x3FF) == 0) { v >>= 10; c = 'M'; + if ((v & 0x3FF) == 0) { v >>= 10; c = 'G'; + if ((v & 0x3FF) == 0) { v >>= 10; c = 'T'; + }}}} + else + { + PrintHex(s, v); + return; + } + char temp[32]; + ConvertUInt64ToString(v, temp); + s += temp; + if (c) + s += c; +} +// #endif +// #endif + +static void SysInfo_To_String(AString &s, const SYSTEM_INFO &si) +{ + s += TypeToString2(k_PROCESSOR_ARCHITECTURE, ARRAY_SIZE(k_PROCESSOR_ARCHITECTURE), si.wProcessorArchitecture); + + if (!( (si.wProcessorArchitecture == MY__PROCESSOR_ARCHITECTURE_INTEL && si.dwProcessorType == MY__PROCESSOR_INTEL_PENTIUM) + || (si.wProcessorArchitecture == MY__PROCESSOR_ARCHITECTURE_AMD64 && si.dwProcessorType == MY__PROCESSOR_AMD_X8664))) + { + s += " "; + // s += TypePairToString(k_PROCESSOR, ARRAY_SIZE(k_PROCESSOR), si.dwProcessorType); + s.Add_UInt32(si.dwProcessorType); + } + s += " "; + PrintHex(s, si.wProcessorLevel); + s += "."; + PrintHex(s, si.wProcessorRevision); + if ((UInt64)si.dwActiveProcessorMask + 1 != ((UInt64)1 << si.dwNumberOfProcessors)) + if ((UInt64)si.dwActiveProcessorMask + 1 != 0 || si.dwNumberOfProcessors != sizeof(UInt64) * 8) + { + s += " act:"; + PrintHex(s, si.dwActiveProcessorMask); + } + s += " cpus:"; + s.Add_UInt32(si.dwNumberOfProcessors); + if (si.dwPageSize != 1 << 12) + { + s += " page:"; + PrintPage(s, si.dwPageSize); + } + if (si.dwAllocationGranularity != 1 << 16) + { + s += " gran:"; + PrintPage(s, si.dwAllocationGranularity); + } + s += " "; + + DWORD_PTR minAdd = (DWORD_PTR)si.lpMinimumApplicationAddress; + UInt64 maxSize = (UInt64)(DWORD_PTR)si.lpMaximumApplicationAddress + 1; + const UInt32 kReserveSize = ((UInt32)1 << 16); + if (minAdd != kReserveSize) + { + PrintSize_KMGT_Or_Hex(s, minAdd); + s += "-"; + } + else + { + if ((maxSize & (kReserveSize - 1)) == 0) + maxSize += kReserveSize; + } + PrintSize_KMGT_Or_Hex(s, maxSize); +} + +#ifndef _WIN64 +EXTERN_C_BEGIN +typedef VOID (WINAPI *Func_GetNativeSystemInfo)(LPSYSTEM_INFO lpSystemInfo); +EXTERN_C_END +#endif + +#endif + +#ifdef __APPLE__ +#ifndef MY_CPU_X86_OR_AMD64 +static void Add_sysctlbyname_to_String(const char *name, AString &s) +{ + size_t bufSize = 256; + char buf[256]; + if (My_sysctlbyname_Get(name, &buf, &bufSize) == 0) + s += buf; +} +#endif +#endif + +void GetSysInfo(AString &s1, AString &s2); +void GetSysInfo(AString &s1, AString &s2) +{ + s1.Empty(); + s2.Empty(); + + #ifdef _WIN32 + SYSTEM_INFO si; + GetSystemInfo(&si); + { + SysInfo_To_String(s1, si); + // s += " : "; + } + + #if !defined(_WIN64) && !defined(UNDER_CE) + Func_GetNativeSystemInfo fn_GetNativeSystemInfo = (Func_GetNativeSystemInfo)(void *)GetProcAddress( + GetModuleHandleA("kernel32.dll"), "GetNativeSystemInfo"); + if (fn_GetNativeSystemInfo) + { + SYSTEM_INFO si2; + fn_GetNativeSystemInfo(&si2); + // if (memcmp(&si, &si2, sizeof(si)) != 0) + { + // s += " - "; + SysInfo_To_String(s2, si2); + } + } + #endif + #endif +} + + +void GetCpuName(AString &s); +void GetCpuName(AString &s) +{ + s.Empty(); + + #ifdef MY_CPU_X86_OR_AMD64 + { + Cx86cpuid cpuid; + if (x86cpuid_CheckAndRead(&cpuid)) + { + AString s2; + x86cpuid_to_String(cpuid, s2); + s += s2; + } + else + { + #ifdef MY_CPU_AMD64 + s += "x64"; + #else + s += "x86"; + #endif + } + } + #elif defined(__APPLE__) + { + Add_sysctlbyname_to_String("machdep.cpu.brand_string", s); + } + #endif + + + if (s.IsEmpty()) + { + #ifdef MY_CPU_LE + s += "LE"; + #elif defined(MY_CPU_BE) + s += "BE"; + #endif + } + + #ifdef __APPLE__ + { + AString s2; + UInt32 v = 0; + if (My_sysctlbyname_Get_UInt32("machdep.cpu.core_count", &v) == 0) + { + s2.Add_UInt32(v); + s2 += 'C'; + } + if (My_sysctlbyname_Get_UInt32("machdep.cpu.thread_count", &v) == 0) + { + s2.Add_UInt32(v); + s2 += 'T'; + } + if (!s2.IsEmpty()) + { + s.Add_Space_if_NotEmpty(); + s += s2; + } + } + #endif + + + #ifdef _WIN32 + { + NRegistry::CKey key; + if (key.Open(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), KEY_READ) == ERROR_SUCCESS) + { + LONG res[2]; + CByteBuffer bufs[2]; + { + for (int i = 0; i < 2; i++) + { + UInt32 size = 0; + res[i] = key.QueryValue(i == 0 ? + TEXT("Previous Update Revision") : + TEXT("Update Revision"), bufs[i], size); + if (res[i] == ERROR_SUCCESS) + if (size != bufs[i].Size()) + res[i] = ERROR_SUCCESS + 1; + } + } + if (res[0] == ERROR_SUCCESS || res[1] == ERROR_SUCCESS) + { + s.Add_OptSpaced("("); + for (int i = 0; i < 2; i++) + { + if (i == 1) + s += "->"; + if (res[i] != ERROR_SUCCESS) + continue; + const CByteBuffer &buf = bufs[i]; + if (buf.Size() == 8) + { + UInt32 high = GetUi32(buf); + if (high != 0) + { + PrintHex(s, high); + s += "."; + } + PrintHex(s, GetUi32(buf + 4)); + } + } + s += ")"; + } + } + } + #endif + + + #ifdef _7ZIP_LARGE_PAGES + Add_LargePages_String(s); + #endif +} + +void AddCpuFeatures(AString &s); +void AddCpuFeatures(AString &s) +{ + #ifdef _WIN32 + // const unsigned kNumFeatures_Extra = 32; // we check also for unknown features + // const unsigned kNumFeatures = ARRAY_SIZE(k_PF) + kNumFeatures_Extra; + const unsigned kNumFeatures = 64; + UInt64 flags = 0; + for (unsigned i = 0; i < kNumFeatures; i++) + { + if (IsProcessorFeaturePresent(i)) + { + flags += (UInt64)1 << i; + // s.Add_Space_if_NotEmpty(); + // s += TypeToString2(k_PF, ARRAY_SIZE(k_PF), i); + } + } + s.Add_Space_if_NotEmpty(); + s += "f:"; + PrintHex(s, flags); + + #else // _WIN32 + + #ifdef __APPLE__ + { + UInt32 v = 0; + if (My_sysctlbyname_Get_UInt32("hw.pagesize", &v) == 0) + { + s += "PageSize:"; + s.Add_UInt32(v >> 10); + s += "KB"; + } + } + + #elif !defined(_AIX) + + s.Add_Space_if_NotEmpty(); + s += "hwcap:"; + { + unsigned long h = getauxval(AT_HWCAP); + PrintHex(s, h); + #ifdef MY_CPU_ARM64 + if (h & HWCAP_CRC32) s += ":CRC32"; + if (h & HWCAP_SHA1) s += ":SHA1"; + if (h & HWCAP_SHA2) s += ":SHA2"; + if (h & HWCAP_AES) s += ":AES"; + #endif + } + + { + unsigned long h = getauxval(AT_HWCAP2); + #ifndef MY_CPU_ARM + if (h != 0) + #endif + { + s += " hwcap2:"; + PrintHex(s, h); + #ifdef MY_CPU_ARM + if (h & HWCAP2_CRC32) s += ":CRC32"; + if (h & HWCAP2_SHA1) s += ":SHA1"; + if (h & HWCAP2_SHA2) s += ":SHA2"; + if (h & HWCAP2_AES) s += ":AES"; + #endif + } + } + + #endif + #endif // _WIN32 +} + + +#ifdef _WIN32 +#ifndef UNDER_CE + +EXTERN_C_BEGIN +typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *); +EXTERN_C_END + +static BOOL My_RtlGetVersion(OSVERSIONINFOEXW *vi) +{ + HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll"); + if (!ntdll) + return FALSE; + Func_RtlGetVersion func = (Func_RtlGetVersion)(void *)GetProcAddress(ntdll, "RtlGetVersion"); + if (!func) + return FALSE; + func(vi); + return TRUE; +} + +#endif +#endif + + +void GetSystemInfoText(AString &sRes) +{ + { + { + AString s; + #ifdef _WIN32 + #ifndef UNDER_CE + // OSVERSIONINFO vi; + OSVERSIONINFOEXW vi; + vi.dwOSVersionInfoSize = sizeof(vi); + // if (::GetVersionEx(&vi)) + if (My_RtlGetVersion(&vi)) + { + s += "Windows"; + if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT) + s.Add_UInt32(vi.dwPlatformId); + s += " "; s.Add_UInt32(vi.dwMajorVersion); + s += "."; s.Add_UInt32(vi.dwMinorVersion); + s += " "; s.Add_UInt32(vi.dwBuildNumber); + + if (vi.wServicePackMajor != 0 || vi.wServicePackMinor != 0) + { + s += " SP:"; s.Add_UInt32(vi.wServicePackMajor); + s += "."; s.Add_UInt32(vi.wServicePackMinor); + } + s += " Suite:"; PrintHex(s, vi.wSuiteMask); + s += " Type:"; s.Add_UInt32(vi.wProductType); + // s += " "; s += GetOemString(vi.szCSDVersion); + } + { + s += " OEMCP:"; + s.Add_UInt32(GetOEMCP()); + s += " ACP:"; + s.Add_UInt32(GetACP()); + } + #endif + #else // _WIN32 + + if (!s.IsEmpty()) + s.Add_LF(); + struct utsname un; + if (uname(&un) == 0) + { + s += un.sysname; + // s += " : "; s += un.nodename; // we don't want to show name of computer + s += " : "; s += un.release; + s += " : "; s += un.version; + s += " : "; s += un.machine; + + #ifdef __APPLE__ + // Add_sysctlbyname_to_String("kern.version", s); + // it's same as "utsname.version" + #endif + } + #endif // _WIN32 + + sRes += s; + sRes.Add_LF(); + } + + { + AString s, s1, s2; + GetSysInfo(s1, s2); + if (!s1.IsEmpty() || !s2.IsEmpty()) + { + s = s1; + if (s1 != s2 && !s2.IsEmpty()) + { + s += " - "; + s += s2; + } + } + { + AddCpuFeatures(s); + if (!s.IsEmpty()) + { + sRes += s; + sRes.Add_LF(); + } + } + } + { + AString s; + GetCpuName(s); + if (!s.IsEmpty()) + { + sRes += s; + sRes.Add_LF(); + } + } + /* + #ifdef MY_CPU_X86_OR_AMD64 + { + AString s; + x86cpuid_all_to_String(s); + if (!s.IsEmpty()) + { + printCallback->Print(s); + printCallback->NewLine(); + } + } + #endif + */ + } +} diff --git a/CPP/Windows/SystemInfo.h b/CPP/Windows/SystemInfo.h new file mode 100644 index 00000000..856bb2ba --- /dev/null +++ b/CPP/Windows/SystemInfo.h @@ -0,0 +1,12 @@ +// Windows/SystemInfo.h + +#ifndef __WINDOWS_SYSTEM_INFO_H +#define __WINDOWS_SYSTEM_INFO_H + +#include "../Common/MyString.h" + +void GetSystemInfoText(AString &s); +void PrintSize_KMGT_Or_Hex(AString &s, UInt64 v); +void Add_LargePages_String(AString &s); + +#endif diff --git a/CPP/Windows/Thread.h b/CPP/Windows/Thread.h index 16a509d4..c9571469 100644 --- a/CPP/Windows/Thread.h +++ b/CPP/Windows/Thread.h @@ -9,7 +9,7 @@ namespace NWindows { -class CThread +class CThread MY_UNCOPYABLE { ::CThread thread; public: @@ -17,9 +17,15 @@ public: ~CThread() { Close(); } bool IsCreated() { return Thread_WasCreated(&thread) != 0; } WRes Close() { return Thread_Close(&thread); } - WRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) - { return Thread_Create(&thread, startAddress, parameter); } - WRes Wait() { return Thread_Wait(&thread); } + // WRes Wait() { return Thread_Wait(&thread); } + WRes Wait_Close() { return Thread_Wait_Close(&thread); } + + WRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID param) + { return Thread_Create(&thread, startAddress, param); } + WRes Create_With_Affinity(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID param, CAffinityMask affinity) + { return Thread_Create_With_Affinity(&thread, startAddress, param, affinity); } + WRes Create_With_CpuSet(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID param, const CCpuSet *cpuSet) + { return Thread_Create_With_CpuSet(&thread, startAddress, param, cpuSet); } #ifdef _WIN32 operator HANDLE() { return thread; } diff --git a/CPP/Windows/TimeUtils.cpp b/CPP/Windows/TimeUtils.cpp index d288f121..1f1335f9 100644 --- a/CPP/Windows/TimeUtils.cpp +++ b/CPP/Windows/TimeUtils.cpp @@ -2,6 +2,10 @@ #include "StdAfx.h" +#ifndef _WIN32 +#include <sys/time.h> +#endif + #include "Defs.h" #include "TimeUtils.h" @@ -10,7 +14,9 @@ namespace NTime { static const UInt32 kNumTimeQuantumsInSecond = 10000000; static const UInt32 kFileTimeStartYear = 1601; +#if !defined(_WIN32) || defined(UNDER_CE) static const UInt32 kDosTimeStartYear = 1980; +#endif static const UInt32 kUnixTimeStartYear = 1970; static const UInt64 kUnixTimeOffset = (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); @@ -37,10 +43,6 @@ bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) throw() static const UInt32 kHighDosTime = 0xFF9FBF7D; static const UInt32 kLowDosTime = 0x210000; -#define PERIOD_4 (4 * 365 + 1) -#define PERIOD_100 (PERIOD_4 * 25 - 1) -#define PERIOD_400 (PERIOD_100 * 4 + 1) - bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) throw() { #if defined(_WIN32) && !defined(UNDER_CE) @@ -55,6 +57,10 @@ bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) throw() #else +#define PERIOD_4 (4 * 365 + 1) +#define PERIOD_100 (PERIOD_4 * 25 - 1) +#define PERIOD_400 (PERIOD_100 * 4 + 1) + unsigned year, mon, day, hour, min, sec; UInt64 v64 = ft.dwLowDateTime | ((UInt64)ft.dwHighDateTime << 32); Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; @@ -129,7 +135,7 @@ void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft) throw() UInt64 UnixTime64ToFileTime64(Int64 unixTime) throw() { - return (UInt64)(kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond; + return (UInt64)((Int64)kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond; } bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &ft) throw() @@ -200,6 +206,7 @@ void GetCurUtcFileTime(FILETIME &ft) throw() { // Both variants provide same low resolution on WinXP: about 15 ms. // But GetSystemTimeAsFileTime is much faster. + #ifdef _WIN32 #ifdef UNDER_CE SYSTEMTIME st; @@ -208,6 +215,20 @@ void GetCurUtcFileTime(FILETIME &ft) throw() #else GetSystemTimeAsFileTime(&ft); #endif + + #else + + UInt64 v = 0; + struct timeval now; + if (gettimeofday(&now, 0 ) == 0) + { + v = ((UInt64)now.tv_sec + kUnixTimeOffset) * + kNumTimeQuantumsInSecond + (UInt64)now.tv_usec * 10; + } + ft.dwLowDateTime = (DWORD)v; + ft.dwHighDateTime = (DWORD)(v >> 32); + + #endif } }} diff --git a/CPP/Windows/Window.cpp b/CPP/Windows/Window.cpp index 36585022..32af4aab 100644 --- a/CPP/Windows/Window.cpp +++ b/CPP/Windows/Window.cpp @@ -114,12 +114,12 @@ bool MySetWindowText(HWND wnd, LPCWSTR s) bool CWindow::GetText(CSysString &s) { s.Empty(); - int len = GetTextLength(); + unsigned len = (unsigned)GetTextLength(); if (len == 0) return (::GetLastError() == ERROR_SUCCESS); TCHAR *p = s.GetBuf(len); { - int len2 = GetText(p, len + 1); + unsigned len2 = (unsigned)GetText(p, (int)(len + 1)); if (len > len2) len = len2; } @@ -135,12 +135,12 @@ bool CWindow::GetText(UString &s) if (g_IsNT) { s.Empty(); - int len = GetWindowTextLengthW(_window); + unsigned len = (unsigned)GetWindowTextLengthW(_window); if (len == 0) return (::GetLastError() == ERROR_SUCCESS); wchar_t *p = s.GetBuf(len); { - int len2 = GetWindowTextW(_window, p, len + 1); + unsigned len2 = (unsigned)GetWindowTextW(_window, p, (int)(len + 1)); if (len > len2) len = len2; } diff --git a/CPP/Windows/Window.h b/CPP/Windows/Window.h index 3bda6795..83726c7a 100644 --- a/CPP/Windows/Window.h +++ b/CPP/Windows/Window.h @@ -171,7 +171,7 @@ public: bool Update() { return BOOLToBool(::UpdateWindow(_window)); } bool InvalidateRect(LPCRECT rect, bool backgroundErase = true) { return BOOLToBool(::InvalidateRect(_window, rect, BoolToBOOL(backgroundErase))); } - void SetRedraw(bool redraw = true) { SendMsg(WM_SETREDRAW, BoolToBOOL(redraw), 0); } + void SetRedraw(bool redraw = true) { SendMsg(WM_SETREDRAW, (WPARAM)BoolToBOOL(redraw), 0); } LONG_PTR SetStyle(LONG_PTR style) { return SetLongPtr(GWL_STYLE, style); } LONG_PTR GetStyle() const { return GetLongPtr(GWL_STYLE); } @@ -244,7 +244,7 @@ public: int GetTextLength() const { return GetWindowTextLength(_window); } - UINT GetText(LPTSTR string, int maxCount) const + int GetText(LPTSTR string, int maxCount) const { return GetWindowText(_window, string, maxCount); } bool GetText(CSysString &s); #ifndef _UNICODE |