chore: initial commit (extracted from Launchers monorepo)

Plugin: ns7zip v2.0.0
Architectures: x86-ansi, x86-unicode, amd64-unicode
License: LGPL-2.1-or-later
This commit is contained in:
Simone
2026-04-29 14:07:51 +02:00
commit d074cc7c07
3848 changed files with 1076682 additions and 0 deletions
+638
View File
@@ -0,0 +1,638 @@
# Microsoft Developer Studio Project File - Name="7z" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=7z - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "7z.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "7z.mak" CFG="7z - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "7z - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "7z - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "7z - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 1
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /YX /FD /c
# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "Z7_EXTERNAL_CODECS" /Yu"StdAfx.h" /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Util\Formats\7z.dll" /opt:NOWIN98
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 1
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "Z7_EXTERNAL_CODECS" /Yu"StdAfx.h" /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Util\Formats\7z.dll" /pdbtype:sept
!ENDIF
# Begin Target
# Name "7z - Win32 Release"
# Name "7z - Win32 Debug"
# Begin Group "Spec"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\Archive.def
# End Source File
# Begin Source File
SOURCE=..\ArchiveExports.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\CodecExports.cpp
# End Source File
# Begin Source File
SOURCE=..\DllExports2.cpp
# End Source File
# Begin Source File
SOURCE=.\resource.rc
# End Source File
# Begin Source File
SOURCE=.\StdAfx.cpp
# ADD CPP /Yc"StdAfx.h"
# End Source File
# Begin Source File
SOURCE=.\StdAfx.h
# End Source File
# End Group
# Begin Group "Engine"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\7zCompressionMode.cpp
# End Source File
# Begin Source File
SOURCE=.\7zCompressionMode.h
# End Source File
# Begin Source File
SOURCE=.\7zDecode.cpp
# End Source File
# Begin Source File
SOURCE=.\7zDecode.h
# End Source File
# Begin Source File
SOURCE=.\7zEncode.cpp
# End Source File
# Begin Source File
SOURCE=.\7zEncode.h
# End Source File
# Begin Source File
SOURCE=.\7zExtract.cpp
# End Source File
# Begin Source File
SOURCE=.\7zFolderInStream.cpp
# End Source File
# Begin Source File
SOURCE=.\7zFolderInStream.h
# End Source File
# Begin Source File
SOURCE=.\7zHandler.cpp
# End Source File
# Begin Source File
SOURCE=.\7zHandler.h
# End Source File
# Begin Source File
SOURCE=.\7zHandlerOut.cpp
# End Source File
# Begin Source File
SOURCE=.\7zHeader.cpp
# End Source File
# Begin Source File
SOURCE=.\7zHeader.h
# End Source File
# Begin Source File
SOURCE=.\7zIn.cpp
# End Source File
# Begin Source File
SOURCE=.\7zIn.h
# End Source File
# Begin Source File
SOURCE=.\7zItem.h
# End Source File
# Begin Source File
SOURCE=.\7zOut.cpp
# End Source File
# Begin Source File
SOURCE=.\7zOut.h
# End Source File
# Begin Source File
SOURCE=.\7zProperties.cpp
# End Source File
# Begin Source File
SOURCE=.\7zProperties.h
# End Source File
# Begin Source File
SOURCE=.\7zRegister.cpp
# End Source File
# Begin Source File
SOURCE=.\7zSpecStream.cpp
# End Source File
# Begin Source File
SOURCE=.\7zSpecStream.h
# End Source File
# Begin Source File
SOURCE=.\7zUpdate.cpp
# End Source File
# Begin Source File
SOURCE=.\7zUpdate.h
# End Source File
# End Group
# Begin Group "Interface"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\IArchive.h
# End Source File
# Begin Source File
SOURCE=..\..\ICoder.h
# End Source File
# Begin Source File
SOURCE=..\..\IMyUnknown.h
# End Source File
# Begin Source File
SOURCE=..\..\IPassword.h
# End Source File
# Begin Source File
SOURCE=..\..\IProgress.h
# End Source File
# Begin Source File
SOURCE=..\..\IStream.h
# End Source File
# Begin Source File
SOURCE=..\..\PropID.h
# End Source File
# End Group
# Begin Group "Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\Common\Buffer.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\CRC.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\DynamicBuffer.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\IntToString.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\IntToString.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\MyString.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\MyString.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\MyVector.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\MyVector.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\NewHandler.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\NewHandler.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\StringConvert.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\StringConvert.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\StringToInt.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\StringToInt.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Wildcard.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Wildcard.h
# End Source File
# End Group
# Begin Group "Archive Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\Common\CoderMixer2.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\CoderMixer2.h
# End Source File
# Begin Source File
SOURCE=..\Common\HandlerOut.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\HandlerOut.h
# End Source File
# Begin Source File
SOURCE=..\Common\InStreamWithCRC.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\InStreamWithCRC.h
# End Source File
# Begin Source File
SOURCE=..\Common\ItemNameUtils.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\ItemNameUtils.h
# End Source File
# Begin Source File
SOURCE=..\Common\MultiStream.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\MultiStream.h
# End Source File
# Begin Source File
SOURCE=..\Common\OutStreamWithCRC.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\OutStreamWithCRC.h
# End Source File
# Begin Source File
SOURCE=..\Common\ParseProperties.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\ParseProperties.h
# End Source File
# End Group
# Begin Group "7-Zip Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\Common\CreateCoder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\CreateCoder.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\FilterCoder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\FilterCoder.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\InOutTempBuffer.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\InOutTempBuffer.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\LimitedStreams.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\LimitedStreams.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\LockedStream.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\LockedStream.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\MethodId.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\MethodId.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\MethodProps.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\MethodProps.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\OutBuffer.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\OutBuffer.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\ProgressUtils.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\ProgressUtils.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\PropId.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\RegisterArc.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\RegisterCodec.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamBinder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamBinder.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamObjects.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamObjects.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamUtils.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamUtils.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\VirtThread.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\VirtThread.h
# End Source File
# End Group
# Begin Group "Windows"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\Windows\FileDir.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileDir.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileFind.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileFind.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileIO.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileIO.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileName.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileName.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Handle.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\PropVariant.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\PropVariant.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Synchronization.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Synchronization.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\System.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\System.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Thread.h
# End Source File
# End Group
# Begin Group "Compress"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\Compress\CopyCoder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\CopyCoder.h
# End Source File
# End Group
# Begin Group "C"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\..\C\7zCrc.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\7zCrc.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\7zCrcOpt.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Alloc.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Alloc.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\CpuArch.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Threads.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Threads.h
# End Source File
# End Group
# End Target
# End Project
+29
View File
@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "7z"=".\7z.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################
@@ -0,0 +1,3 @@
// CompressionMethod.cpp
#include "StdAfx.h"
@@ -0,0 +1,92 @@
// 7zCompressionMode.h
#ifndef ZIP7_INC_7Z_COMPRESSION_MODE_H
#define ZIP7_INC_7Z_COMPRESSION_MODE_H
#include "../../Common/MethodId.h"
#include "../../Common/MethodProps.h"
namespace NArchive {
namespace N7z {
struct CMethodFull: public CMethodProps
{
CMethodId Id;
UInt32 NumStreams;
int CodecIndex;
UInt32 NumThreads;
bool Set_NumThreads;
CMethodFull(): CodecIndex(-1), NumThreads(1), Set_NumThreads(false) {}
bool IsSimpleCoder() const { return NumStreams == 1; }
};
struct CBond2
{
UInt32 OutCoder;
UInt32 OutStream;
UInt32 InCoder;
};
struct CCompressionMethodMode
{
/*
if (Bonds.Empty()), then default bonds must be created
if (Filter_was_Inserted)
{
Methods[0] is filter method
Bonds don't contain bonds for filter (these bonds must be created)
}
*/
CObjectVector<CMethodFull> Methods;
CRecordVector<CBond2> Bonds;
bool IsThereBond_to_Coder(unsigned coderIndex) const
{
FOR_VECTOR(i, Bonds)
if (Bonds[i].InCoder == coderIndex)
return true;
return false;
}
bool DefaultMethod_was_Inserted;
bool Filter_was_Inserted;
bool PasswordIsDefined;
bool MemoryUsageLimit_WasSet;
#ifndef Z7_ST
bool NumThreads_WasForced;
bool MultiThreadMixer;
UInt32 NumThreads;
UInt32 NumThreadGroups;
#endif
UString Password; // _Wipe
UInt64 MemoryUsageLimit;
bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }
CCompressionMethodMode():
DefaultMethod_was_Inserted(false)
, Filter_was_Inserted(false)
, PasswordIsDefined(false)
, MemoryUsageLimit_WasSet(false)
#ifndef Z7_ST
, NumThreads_WasForced(false)
, MultiThreadMixer(true)
, NumThreads(1)
, NumThreadGroups(0)
#endif
, MemoryUsageLimit((UInt64)1 << 30)
{}
#ifdef Z7_CPP_IS_SUPPORTED_default
CCompressionMethodMode(const CCompressionMethodMode &) = default;
CCompressionMethodMode& operator =(const CCompressionMethodMode &) = default;
#endif
~CCompressionMethodMode() { Password.Wipe_and_Empty(); }
};
}}
#endif
@@ -0,0 +1,599 @@
// 7zDecode.cpp
#include "StdAfx.h"
#include "../../Common/LimitedStreams.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamObjects.h"
#include "../../Common/StreamUtils.h"
#include "7zDecode.h"
namespace NArchive {
namespace N7z {
Z7_CLASS_IMP_COM_1(
CDecProgress
, ICompressProgressInfo
)
CMyComPtr<ICompressProgressInfo> _progress;
public:
CDecProgress(ICompressProgressInfo *progress): _progress(progress) {}
};
Z7_COM7F_IMF(CDecProgress::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 *outSize))
{
return _progress->SetRatioInfo(NULL, outSize);
}
static void Convert_FolderInfo_to_BindInfo(const CFolderEx &folder, CBindInfoEx &bi)
{
bi.Clear();
bi.Bonds.ClearAndSetSize(folder.Bonds.Size());
unsigned i;
for (i = 0; i < folder.Bonds.Size(); i++)
{
NCoderMixer2::CBond &bond = bi.Bonds[i];
const N7z::CBond &folderBond = folder.Bonds[i];
bond.PackIndex = folderBond.PackIndex;
bond.UnpackIndex = folderBond.UnpackIndex;
}
bi.Coders.ClearAndSetSize(folder.Coders.Size());
bi.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());
for (i = 0; i < folder.Coders.Size(); i++)
{
const CCoderInfo &coderInfo = folder.Coders[i];
bi.Coders[i].NumStreams = coderInfo.NumStreams;
bi.CoderMethodIDs[i] = coderInfo.MethodID;
}
/*
if (!bi.SetUnpackCoder())
throw 1112;
*/
bi.UnpackCoder = folder.UnpackCoder;
bi.PackStreams.ClearAndSetSize(folder.PackStreams.Size());
for (i = 0; i < folder.PackStreams.Size(); i++)
bi.PackStreams[i] = folder.PackStreams[i];
}
static inline bool AreCodersEqual(
const NCoderMixer2::CCoderStreamsInfo &a1,
const NCoderMixer2::CCoderStreamsInfo &a2)
{
return (a1.NumStreams == a2.NumStreams);
}
static inline bool AreBondsEqual(
const NCoderMixer2::CBond &a1,
const NCoderMixer2::CBond &a2)
{
return
(a1.PackIndex == a2.PackIndex) &&
(a1.UnpackIndex == a2.UnpackIndex);
}
static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
{
if (a1.Coders.Size() != a2.Coders.Size())
return false;
unsigned i;
for (i = 0; i < a1.Coders.Size(); i++)
if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
return false;
if (a1.Bonds.Size() != a2.Bonds.Size())
return false;
for (i = 0; i < a1.Bonds.Size(); i++)
if (!AreBondsEqual(a1.Bonds[i], a2.Bonds[i]))
return false;
for (i = 0; i < a1.CoderMethodIDs.Size(); i++)
if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])
return false;
if (a1.PackStreams.Size() != a2.PackStreams.Size())
return false;
for (i = 0; i < a1.PackStreams.Size(); i++)
if (a1.PackStreams[i] != a2.PackStreams[i])
return false;
/*
if (a1.UnpackCoder != a2.UnpackCoder)
return false;
*/
return true;
}
CDecoder::CDecoder(bool useMixerMT):
_bindInfoPrev_Defined(false)
{
#if defined(USE_MIXER_ST) && defined(USE_MIXER_MT)
_useMixerMT = useMixerMT;
#else
UNUSED_VAR(useMixerMT)
#endif
}
Z7_CLASS_IMP_COM_0(
CLockedInStream
)
public:
CMyComPtr<IInStream> Stream;
UInt64 Pos;
#ifdef USE_MIXER_MT
NWindows::NSynchronization::CCriticalSection CriticalSection;
#endif
};
#ifdef USE_MIXER_MT
Z7_CLASS_IMP_COM_1(
CLockedSequentialInStreamMT
, ISequentialInStream
)
CLockedInStream *_glob;
UInt64 _pos;
CMyComPtr<IUnknown> _globRef;
public:
void Init(CLockedInStream *lockedInStream, UInt64 startPos)
{
_globRef = lockedInStream;
_glob = lockedInStream;
_pos = startPos;
}
};
Z7_COM7F_IMF(CLockedSequentialInStreamMT::Read(void *data, UInt32 size, UInt32 *processedSize))
{
NWindows::NSynchronization::CCriticalSectionLock lock(_glob->CriticalSection);
if (_pos != _glob->Pos)
{
RINOK(InStream_SeekSet(_glob->Stream, _pos))
_glob->Pos = _pos;
}
UInt32 realProcessedSize = 0;
const HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
_pos += realProcessedSize;
_glob->Pos = _pos;
if (processedSize)
*processedSize = realProcessedSize;
return res;
}
#endif
#ifdef USE_MIXER_ST
Z7_CLASS_IMP_COM_1(
CLockedSequentialInStreamST
, ISequentialInStream
)
CLockedInStream *_glob;
UInt64 _pos;
CMyComPtr<IUnknown> _globRef;
public:
void Init(CLockedInStream *lockedInStream, UInt64 startPos)
{
_globRef = lockedInStream;
_glob = lockedInStream;
_pos = startPos;
}
};
Z7_COM7F_IMF(CLockedSequentialInStreamST::Read(void *data, UInt32 size, UInt32 *processedSize))
{
if (_pos != _glob->Pos)
{
RINOK(InStream_SeekSet(_glob->Stream, _pos))
_glob->Pos = _pos;
}
UInt32 realProcessedSize = 0;
const HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
_pos += realProcessedSize;
_glob->Pos = _pos;
if (processedSize)
*processedSize = realProcessedSize;
return res;
}
#endif
HRESULT CDecoder::Decode(
DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream,
UInt64 startPos,
const CFolders &folders, unsigned folderIndex,
const UInt64 *unpackSize
, ISequentialOutStream *outStream
, ICompressProgressInfo *compressProgress
, ISequentialInStream **
#ifdef USE_MIXER_ST
inStreamMainRes
#endif
, bool &dataAfterEnd_Error
Z7_7Z_DECODER_CRYPRO_VARS_DECL
#if !defined(Z7_ST)
, bool mtMode, UInt32 numThreads, UInt64 memUsage
#endif
)
{
dataAfterEnd_Error = false;
const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]];
CFolderEx folderInfo;
folders.ParseFolderEx(folderIndex, folderInfo);
if (!folderInfo.IsDecodingSupported())
return E_NOTIMPL;
CBindInfoEx bindInfo;
Convert_FolderInfo_to_BindInfo(folderInfo, bindInfo);
if (!bindInfo.CalcMapsAndCheck())
return E_NOTIMPL;
UInt64 folderUnpackSize = folders.GetFolderUnpackSize(folderIndex);
bool fullUnpack = true;
if (unpackSize)
{
if (*unpackSize > folderUnpackSize)
return E_FAIL;
fullUnpack = (*unpackSize == folderUnpackSize);
}
/*
We don't need to init isEncrypted and passwordIsDefined
We must upgrade them only
#ifndef Z7_NO_CRYPTO
isEncrypted = false;
passwordIsDefined = false;
#endif
*/
if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev))
{
_bindInfoPrev_Defined = false;
_mixerRef.Release();
#ifdef USE_MIXER_MT
#ifdef USE_MIXER_ST
if (_useMixerMT)
#endif
{
_mixerMT = new NCoderMixer2::CMixerMT(false);
_mixerRef = _mixerMT;
_mixer = _mixerMT;
}
#ifdef USE_MIXER_ST
else
#endif
#endif
{
#ifdef USE_MIXER_ST
_mixerST = new NCoderMixer2::CMixerST(false);
_mixerRef = _mixerST;
_mixer = _mixerST;
#endif
}
RINOK(_mixer->SetBindInfo(bindInfo))
FOR_VECTOR(i, folderInfo.Coders)
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
#ifndef Z7_SFX
// we don't support RAR codecs here
if ((coderInfo.MethodID >> 8) == 0x403)
return E_NOTIMPL;
#endif
CCreatedCoder cod;
RINOK(CreateCoder_Id(
EXTERNAL_CODECS_LOC_VARS
coderInfo.MethodID, false, cod))
if (coderInfo.IsSimpleCoder())
{
if (!cod.Coder)
return E_NOTIMPL;
// CMethodId m = coderInfo.MethodID;
// isFilter = (IsFilterMethod(m) || m == k_AES);
}
else
{
if (!cod.Coder2 || cod.NumStreams != coderInfo.NumStreams)
return E_NOTIMPL;
}
_mixer->AddCoder(cod);
// now there is no codec that uses another external codec
/*
#ifdef Z7_EXTERNAL_CODECS
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
if (setCompressCodecsInfo)
{
// we must use g_ExternalCodecs also
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs));
}
#endif
*/
}
_bindInfoPrev = bindInfo;
_bindInfoPrev_Defined = true;
}
RINOK(_mixer->ReInit2())
UInt32 packStreamIndex = 0;
UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex];
unsigned i;
#if !defined(Z7_ST)
bool mt_wasUsed = false;
#endif
for (i = 0; i < folderInfo.Coders.Size(); i++)
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
IUnknown *decoder = _mixer->GetCoder(i).GetUnknown();
// now there is no codec that uses another external codec
/*
#ifdef Z7_EXTERNAL_CODECS
{
Z7_DECL_CMyComPtr_QI_FROM(ISetCompressCodecsInfo,
setCompressCodecsInfo, decoder)
if (setCompressCodecsInfo)
{
// we must use g_ExternalCodecs also
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs))
}
}
#endif
*/
#if !defined(Z7_ST)
if (!mt_wasUsed)
{
if (mtMode)
{
Z7_DECL_CMyComPtr_QI_FROM(ICompressSetCoderMt,
setCoderMt, decoder)
if (setCoderMt)
{
mt_wasUsed = true;
RINOK(setCoderMt->SetNumberOfThreads(numThreads))
}
}
// if (memUsage != 0)
{
Z7_DECL_CMyComPtr_QI_FROM(ICompressSetMemLimit,
setMemLimit, decoder)
if (setMemLimit)
{
mt_wasUsed = true;
RINOK(setMemLimit->SetMemLimit(memUsage))
}
}
}
#endif
{
Z7_DECL_CMyComPtr_QI_FROM(
ICompressSetDecoderProperties2,
setDecoderProperties, decoder)
const CByteBuffer &props = coderInfo.Props;
const UInt32 size32 = (UInt32)props.Size();
if (props.Size() != size32)
return E_NOTIMPL;
if (setDecoderProperties)
{
HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, size32);
if (res == E_INVALIDARG)
res = E_NOTIMPL;
RINOK(res)
}
else if (size32 != 0)
{
// v23: we fail, if decoder doesn't support properties
return E_NOTIMPL;
}
}
#ifndef Z7_NO_CRYPTO
{
Z7_DECL_CMyComPtr_QI_FROM(
ICryptoSetPassword,
cryptoSetPassword, decoder)
if (cryptoSetPassword)
{
isEncrypted = true;
if (!getTextPassword)
return E_NOTIMPL;
CMyComBSTR_Wipe passwordBSTR;
RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR))
passwordIsDefined = true;
password.Wipe_and_Empty();
size_t len = 0;
if (passwordBSTR)
{
password = passwordBSTR;
len = password.Len();
}
CByteBuffer_Wipe buffer(len * 2);
const LPCOLESTR psw = passwordBSTR;
for (size_t k = 0; k < len; k++)
{
const wchar_t c = psw[k];
((Byte *)buffer)[k * 2] = (Byte)c;
((Byte *)buffer)[k * 2 + 1] = (Byte)(c >> 8);
}
RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size()))
}
}
#endif
bool finishMode = false;
{
Z7_DECL_CMyComPtr_QI_FROM(
ICompressSetFinishMode,
setFinishMode, decoder)
if (setFinishMode)
{
finishMode = fullUnpack;
RINOK(setFinishMode->SetFinishMode(BoolToUInt(finishMode)))
}
}
UInt32 numStreams = (UInt32)coderInfo.NumStreams;
CObjArray<UInt64> packSizes(numStreams);
CObjArray<const UInt64 *> packSizesPointers(numStreams);
for (UInt32 j = 0; j < numStreams; j++, packStreamIndex++)
{
int bond = folderInfo.FindBond_for_PackStream(packStreamIndex);
if (bond >= 0)
packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + folderInfo.Bonds[(unsigned)bond].UnpackIndex];
else
{
int index = folderInfo.Find_in_PackStreams(packStreamIndex);
if (index < 0)
return E_NOTIMPL;
packSizes[j] = packPositions[(unsigned)index + 1] - packPositions[(unsigned)index];
packSizesPointers[j] = &packSizes[j];
}
}
const UInt64 *unpackSizesPointer =
(unpackSize && i == bindInfo.UnpackCoder) ?
unpackSize :
&folders.CoderUnpackSizes[unpackStreamIndexStart + i];
_mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers, finishMode);
}
if (outStream)
{
_mixer->SelectMainCoder(!fullUnpack);
}
CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
CMyComPtr2_Create<IUnknown, CLockedInStream> lockedInStream;
#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_GetPos(inStream, lockedInStream.Pos))
RINOK(inStream->Seek((Int64)(startPos + packPositions[0]), STREAM_SEEK_SET, &lockedInStream->Pos))
lockedInStream->Stream = inStream;
#ifdef USE_MIXER_MT
#ifdef USE_MIXER_ST
/*
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;
const UInt64 packPos = startPos + packPositions[j];
if (folderInfo.PackStreams.Size() == 1)
{
RINOK(InStream_SeekSet(inStream, packPos))
packStream = inStream;
}
else
{
#ifdef USE_MIXER_MT
#ifdef USE_MIXER_ST
if (needMtLock)
#endif
{
CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT;
packStream = lockedStreamImpSpec;
lockedStreamImpSpec->Init(lockedInStream.ClsPtr(), packPos);
}
#ifdef USE_MIXER_ST
else
#endif
#endif
{
#ifdef USE_MIXER_ST
CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST;
packStream = lockedStreamImpSpec;
lockedStreamImpSpec->Init(lockedInStream.ClsPtr(), packPos);
#endif
}
}
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
inStreams.AddNew() = streamSpec;
streamSpec->SetStream(packStream);
streamSpec->Init(packPositions[j + 1] - packPositions[j]);
}
const unsigned num = inStreams.Size();
CObjArray<ISequentialInStream *> inStreamPointers(num);
for (i = 0; i < num; i++)
inStreamPointers[i] = inStreams[i];
if (outStream)
{
CMyComPtr<ICompressProgressInfo> progress2;
if (compressProgress && !_mixer->Is_PackSize_Correct_for_Coder(_mixer->MainCoderIndex))
progress2 = new CDecProgress(compressProgress);
ISequentialOutStream *outStreamPointer = outStream;
return _mixer->Code(inStreamPointers, &outStreamPointer,
progress2 ? (ICompressProgressInfo *)progress2 : compressProgress,
dataAfterEnd_Error);
}
#ifdef USE_MIXER_ST
return _mixerST->GetMainUnpackStream(inStreamPointers, inStreamMainRes);
#else
return E_FAIL;
#endif
}
}}
@@ -0,0 +1,73 @@
// 7zDecode.h
#ifndef ZIP7_INC_7Z_DECODE_H
#define ZIP7_INC_7Z_DECODE_H
#include "../Common/CoderMixer2.h"
#include "7zIn.h"
namespace NArchive {
namespace N7z {
struct CBindInfoEx: public NCoderMixer2::CBindInfo
{
CRecordVector<CMethodId> CoderMethodIDs;
void Clear()
{
CBindInfo::Clear();
CoderMethodIDs.Clear();
}
};
class CDecoder
{
bool _bindInfoPrev_Defined;
#ifdef USE_MIXER_ST
#ifdef USE_MIXER_MT
bool _useMixerMT;
#endif
#endif
CBindInfoEx _bindInfoPrev;
#ifdef USE_MIXER_ST
NCoderMixer2::CMixerST *_mixerST;
#endif
#ifdef USE_MIXER_MT
NCoderMixer2::CMixerMT *_mixerMT;
#endif
NCoderMixer2::CMixer *_mixer;
CMyComPtr<IUnknown> _mixerRef;
public:
CDecoder(bool useMixerMT);
HRESULT Decode(
DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream,
UInt64 startPos,
const CFolders &folders, unsigned folderIndex,
const UInt64 *unpackSize // if (!unpackSize), then full folder is required
// if (unpackSize), then only *unpackSize bytes from folder are required
, ISequentialOutStream *outStream
, ICompressProgressInfo *compressProgress
, ISequentialInStream **inStreamMainRes
, bool &dataAfterEnd_Error
Z7_7Z_DECODER_CRYPRO_VARS_DECL
#if !defined(Z7_ST)
, bool mtMode, UInt32 numThreads, UInt64 memUsage
#endif
);
};
}}
#endif
@@ -0,0 +1,721 @@
// 7zEncode.cpp
#include "StdAfx.h"
#include "../../../Common/ComTry.h"
#include "../../Common/CreateCoder.h"
#include "../../Common/FilterCoder.h"
#include "../../Common/LimitedStreams.h"
#include "../../Common/InOutTempBuffer.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamObjects.h"
#include "7zEncode.h"
#include "7zSpecStream.h"
namespace NArchive {
namespace N7z {
void CEncoder::InitBindConv()
{
unsigned numIn = _bindInfo.Coders.Size();
SrcIn_to_DestOut.ClearAndSetSize(numIn);
DestOut_to_SrcIn.ClearAndSetSize(numIn);
unsigned numOut = _bindInfo.GetNum_Bonds_and_PackStreams();
SrcOut_to_DestIn.ClearAndSetSize(numOut);
// _DestIn_to_SrcOut.ClearAndSetSize(numOut);
UInt32 destIn = 0;
UInt32 destOut = 0;
for (unsigned i = _bindInfo.Coders.Size(); i != 0;)
{
i--;
const NCoderMixer2::CCoderStreamsInfo &coder = _bindInfo.Coders[i];
numIn--;
numOut -= coder.NumStreams;
SrcIn_to_DestOut[numIn] = destOut;
DestOut_to_SrcIn[destOut] = numIn;
destOut++;
for (UInt32 j = 0; j < coder.NumStreams; j++, destIn++)
{
UInt32 index = numOut + j;
SrcOut_to_DestIn[index] = destIn;
// _DestIn_to_SrcOut[destIn] = index;
}
}
}
void CEncoder::SetFolder(CFolder &folder)
{
folder.Bonds.SetSize(_bindInfo.Bonds.Size());
unsigned i;
for (i = 0; i < _bindInfo.Bonds.Size(); i++)
{
CBond &fb = folder.Bonds[i];
const NCoderMixer2::CBond &mixerBond = _bindInfo.Bonds[_bindInfo.Bonds.Size() - 1 - i];
fb.PackIndex = SrcOut_to_DestIn[mixerBond.PackIndex];
fb.UnpackIndex = SrcIn_to_DestOut[mixerBond.UnpackIndex];
}
folder.Coders.SetSize(_bindInfo.Coders.Size());
for (i = 0; i < _bindInfo.Coders.Size(); i++)
{
CCoderInfo &coderInfo = folder.Coders[i];
const NCoderMixer2::CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[_bindInfo.Coders.Size() - 1 - i];
coderInfo.NumStreams = coderStreamsInfo.NumStreams;
coderInfo.MethodID = _decompressionMethods[i];
// we don't free coderInfo.Props here. So coderInfo.Props can be non-empty.
}
folder.PackStreams.SetSize(_bindInfo.PackStreams.Size());
for (i = 0; i < _bindInfo.PackStreams.Size(); i++)
folder.PackStreams[i] = SrcOut_to_DestIn[_bindInfo.PackStreams[i]];
}
static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder)
{
Z7_DECL_CMyComPtr_QI_FROM(
ICompressSetCoderProperties,
setCoderProperties, coder)
if (setCoderProperties)
return props.SetCoderProps(setCoderProperties, dataSizeReduce);
return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK;
}
void CMtEncMultiProgress::Init(ICompressProgressInfo *progress)
{
_progress = progress;
OutSize = 0;
}
Z7_COM7F_IMF(CMtEncMultiProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */))
{
UInt64 outSize2;
{
#ifndef Z7_ST
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
#endif
outSize2 = OutSize;
}
if (_progress)
return _progress->SetRatioInfo(inSize, &outSize2);
return S_OK;
}
HRESULT CEncoder::CreateMixerCoder(
DECL_EXTERNAL_CODECS_LOC_VARS
const UInt64 *inSizeForReduce)
{
#ifdef USE_MIXER_MT
#ifdef USE_MIXER_ST
if (_options.MultiThreadMixer)
#endif
{
_mixerMT = new NCoderMixer2::CMixerMT(true);
_mixerRef = _mixerMT;
_mixer = _mixerMT;
}
#ifdef USE_MIXER_ST
else
#endif
#endif
{
#ifdef USE_MIXER_ST
_mixerST = new NCoderMixer2::CMixerST(true);
_mixerRef = _mixerST;
_mixer = _mixerST;
#endif
}
RINOK(_mixer->SetBindInfo(_bindInfo))
FOR_VECTOR (m, _options.Methods)
{
const CMethodFull &methodFull = _options.Methods[m];
CCreatedCoder cod;
if (methodFull.CodecIndex >= 0)
{
RINOK(CreateCoder_Index(
EXTERNAL_CODECS_LOC_VARS
(unsigned)methodFull.CodecIndex, true, cod))
}
else
{
RINOK(CreateCoder_Id(
EXTERNAL_CODECS_LOC_VARS
methodFull.Id, true, cod))
}
if (!cod.Coder && !cod.Coder2)
{
return E_NOTIMPL; // unsupported method, if encoder
// return E_FAIL;
}
if (cod.NumStreams != methodFull.NumStreams)
return E_FAIL;
CMyComPtr<IUnknown> encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2;
#ifndef Z7_ST
if (methodFull.Set_NumThreads)
{
CMyComPtr<ICompressSetCoderMt> setCoderMt;
encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
if (setCoderMt)
{
RINOK(setCoderMt->SetNumberOfThreads(
/* _options.NumThreads */
methodFull.NumThreads
))
}
}
#endif
RINOK(SetCoderProps2(methodFull, inSizeForReduce, encoderCommon))
/*
CMyComPtr<ICryptoResetSalt> resetSalt;
encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt);
if (resetSalt)
{
resetSalt->ResetSalt();
}
*/
// now there is no codec that uses another external codec
/*
#ifdef Z7_EXTERNAL_CODECS
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
if (setCompressCodecsInfo)
{
// we must use g_ExternalCodecs also
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs));
}
#endif
*/
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
if (cryptoSetPassword)
{
const unsigned sizeInBytes = _options.Password.Len() * 2;
CByteBuffer_Wipe buffer(sizeInBytes);
for (unsigned i = 0; i < _options.Password.Len(); i++)
{
wchar_t c = _options.Password[i];
((Byte *)buffer)[i * 2] = (Byte)c;
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
}
RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)sizeInBytes))
}
_mixer->AddCoder(cod);
}
return S_OK;
}
Z7_CLASS_IMP_COM_1(
CSequentialOutTempBufferImp2
, ISequentialOutStream
)
public:
CInOutTempBuffer TempBuffer;
CMtEncMultiProgress *_mtProgressSpec;
CSequentialOutTempBufferImp2(): _mtProgressSpec(NULL) {}
};
Z7_COM7F_IMF(CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed))
{
COM_TRY_BEGIN
if (processed)
*processed = 0;
RINOK(TempBuffer.Write_HRESULT(data, size))
if (processed)
*processed = size;
if (_mtProgressSpec)
_mtProgressSpec->AddOutSize(size);
return S_OK;
COM_TRY_END
}
Z7_CLASS_IMP_COM_1(
CSequentialOutMtNotify
, ISequentialOutStream
)
public:
CMyComPtr<ISequentialOutStream> _stream;
CMtEncMultiProgress *_mtProgressSpec;
CSequentialOutMtNotify(): _mtProgressSpec(NULL) {}
};
Z7_COM7F_IMF(CSequentialOutMtNotify::Write(const void *data, UInt32 size, UInt32 *processed))
{
UInt32 realProcessed = 0;
HRESULT res = _stream->Write(data, size, &realProcessed);
if (processed)
*processed = realProcessed;
if (_mtProgressSpec)
_mtProgressSpec->AddOutSize(size);
return res;
}
static HRESULT FillProps_from_Coder(IUnknown *coder, CByteBuffer &props)
{
Z7_DECL_CMyComPtr_QI_FROM(
ICompressWriteCoderProperties,
writeCoderProperties, coder)
if (writeCoderProperties)
{
CMyComPtr2_Create<ISequentialOutStream, CDynBufSeqOutStream> outStreamSpec;
outStreamSpec->Init();
RINOK(writeCoderProperties->WriteCoderProperties(outStreamSpec))
outStreamSpec->CopyToBuffer(props);
}
else
props.Free();
return S_OK;
}
HRESULT CEncoder::Encode1(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream,
// const UInt64 *inStreamSize,
const UInt64 *inSizeForReduce,
UInt64 expectedDataSize,
CFolder &folderItem,
// CRecordVector<UInt64> &coderUnpackSizes,
// UInt64 &unpackSize,
ISequentialOutStream *outStream,
CRecordVector<UInt64> &packSizes,
ICompressProgressInfo *compressProgress)
{
RINOK(EncoderConstr())
if (!_mixerRef)
{
RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce))
}
RINOK(_mixer->ReInit2())
CMyComPtr2<ICompressProgressInfo, CMtEncMultiProgress> mtProgress;
CMyComPtr2<ISequentialOutStream, CSequentialOutMtNotify> mtOutStreamNotify;
CRecordVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs;
CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
unsigned i;
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
{
CSequentialOutTempBufferImp2 *tempBufferSpec = new CSequentialOutTempBufferImp2();
CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
tempBufferSpecs.Add(tempBufferSpec);
tempBuffers.Add(tempBuffer);
}
const unsigned numMethods = _bindInfo.Coders.Size();
for (i = 0; i < numMethods; i++)
_mixer->SetCoderInfo(i, NULL, NULL, false);
/* inStreamSize can be used by BCJ2 to set optimal range of conversion.
But current BCJ2 encoder uses also another way to check exact size of current file.
So inStreamSize is not required. */
/*
if (inStreamSize)
_mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL);
*/
/*
CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;
CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
*/
CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL;
CMyComPtr<ISequentialOutStream> outStreamSizeCount;
// inStreamSizeCountSpec->Init(inStream);
// ISequentialInStream *inStreamPointer = inStreamSizeCount;
ISequentialInStream *inStreamPointer = inStream;
CRecordVector<ISequentialOutStream *> outStreamPointers;
SetFolder(folderItem);
for (i = 0; i < numMethods; i++)
{
IUnknown *coder = _mixer->GetCoder(i).GetUnknown();
/*
{
CEncoder *sfEncoder = NULL;
Z7_DECL_CMyComPtr_QI_FROM(
IGetSfEncoderInternal,
sf, coder)
if (sf)
{
RINOK(sf->GetSfEncoder(&sfEncoder));
if (!sfEncoder)
return E_FAIL;
}
}
*/
/*
#ifdef Z7_EXTERNAL_CODECS
{
Z7_DECL_CMyComPtr_QI_FROM(
ISetCompressCodecsInfo,
setCompressCodecsInfo, coder)
if (setCompressCodecsInfo)
{
// we must use g_ExternalCodecs also
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs))
}
}
#endif
*/
{
Z7_DECL_CMyComPtr_QI_FROM(
ICryptoResetInitVector,
resetInitVector, coder)
if (resetInitVector)
{
RINOK(resetInitVector->ResetInitVector())
}
}
{
Z7_DECL_CMyComPtr_QI_FROM(
ICompressSetCoderPropertiesOpt,
optProps, coder)
if (optProps)
{
const PROPID propID = NCoderPropID::kExpectedDataSize;
NWindows::NCOM::CPropVariant prop = (UInt64)expectedDataSize;
RINOK(optProps->SetCoderPropertiesOpt(&propID, &prop, 1))
}
}
// we must write properties from coder after ResetInitVector()
RINOK(FillProps_from_Coder(coder, folderItem.Coders[numMethods - 1 - i].Props))
}
_mixer->SelectMainCoder(false);
const UInt32 mainCoder = _mixer->MainCoderIndex;
bool useMtProgress = false;
if (!_mixer->Is_PackSize_Correct_for_Coder(mainCoder))
{
#ifdef Z7_ST
if (!_mixer->IsThere_ExternalCoder_in_PackTree(mainCoder))
#endif
useMtProgress = true;
}
if (useMtProgress)
{
mtProgress.SetFromCls(new CMtEncMultiProgress);
mtProgress->Init(compressProgress);
mtOutStreamNotify.SetFromCls(new CSequentialOutMtNotify);
mtOutStreamNotify->_stream = outStream;
mtOutStreamNotify->_mtProgressSpec = mtProgress.ClsPtr();
FOR_VECTOR (t, tempBufferSpecs)
{
tempBufferSpecs[t]->_mtProgressSpec = mtProgress.ClsPtr();
}
}
if (_bindInfo.PackStreams.Size() != 0)
{
outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
outStreamSizeCount = outStreamSizeCountSpec;
outStreamSizeCountSpec->SetStream(mtOutStreamNotify.IsDefined() ?
mtOutStreamNotify.Interface() : outStream);
outStreamSizeCountSpec->Init();
outStreamPointers.Add(outStreamSizeCount);
}
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
outStreamPointers.Add(tempBuffers[i - 1]);
bool dataAfterEnd_Error;
RINOK(_mixer->Code(
&inStreamPointer,
outStreamPointers.ConstData(),
mtProgress.IsDefined() ? mtProgress.Interface() :
compressProgress, dataAfterEnd_Error))
if (_bindInfo.PackStreams.Size() != 0)
packSizes.Add(outStreamSizeCountSpec->GetSize());
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
{
CInOutTempBuffer &iotb = tempBufferSpecs[i - 1]->TempBuffer;
RINOK(iotb.WriteToStream(outStream))
packSizes.Add(iotb.GetDataSize());
}
/* Code() in some future codec can change properties.
v23: so we fill properties again after Code() */
for (i = 0; i < numMethods; i++)
{
IUnknown *coder = _mixer->GetCoder(i).GetUnknown();
RINOK(FillProps_from_Coder(coder, folderItem.Coders[numMethods - 1 - i].Props))
}
return S_OK;
}
void CEncoder::Encode_Post(
UInt64 unpackSize,
CRecordVector<UInt64> &coderUnpackSizes)
{
// unpackSize = 0;
for (unsigned i = 0; i < _bindInfo.Coders.Size(); i++)
{
const int bond = _bindInfo.FindBond_for_UnpackStream(DestOut_to_SrcIn[i]);
UInt64 streamSize;
if (bond < 0)
{
// streamSize = inStreamSizeCountSpec->GetSize();
// unpackSize = streamSize;
streamSize = unpackSize;
}
else
streamSize = _mixer->GetBondStreamSize((unsigned)bond);
coderUnpackSizes.Add(streamSize);
}
}
CEncoder::CEncoder(const CCompressionMethodMode &options):
_constructed(false)
{
if (options.IsEmpty())
throw 1;
_options = options;
#ifdef USE_MIXER_ST
_mixerST = NULL;
#endif
#ifdef USE_MIXER_MT
_mixerMT = NULL;
#endif
_mixer = NULL;
}
HRESULT CEncoder::EncoderConstr()
{
if (_constructed)
return S_OK;
if (_options.Methods.IsEmpty())
{
// it has only password method;
if (!_options.PasswordIsDefined)
throw 1;
if (!_options.Bonds.IsEmpty())
throw 1;
CMethodFull method;
method.Id = k_AES;
method.NumStreams = 1;
_options.Methods.Add(method);
NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
coderStreamsInfo.NumStreams = 1;
_bindInfo.Coders.Add(coderStreamsInfo);
_bindInfo.PackStreams.Add(0);
_bindInfo.UnpackCoder = 0;
}
else
{
UInt32 numOutStreams = 0;
unsigned i;
for (i = 0; i < _options.Methods.Size(); i++)
{
const CMethodFull &methodFull = _options.Methods[i];
NCoderMixer2::CCoderStreamsInfo cod;
cod.NumStreams = methodFull.NumStreams;
if (_options.Bonds.IsEmpty())
{
// if there are no bonds in options, we create bonds via first streams of coders
if (i != _options.Methods.Size() - 1)
{
NCoderMixer2::CBond bond;
bond.PackIndex = numOutStreams;
bond.UnpackIndex = i + 1; // it's next coder
_bindInfo.Bonds.Add(bond);
}
else if (cod.NumStreams != 0)
_bindInfo.PackStreams.Insert(0, numOutStreams);
for (UInt32 j = 1; j < cod.NumStreams; j++)
_bindInfo.PackStreams.Add(numOutStreams + j);
}
numOutStreams += cod.NumStreams;
_bindInfo.Coders.Add(cod);
}
if (!_options.Bonds.IsEmpty())
{
for (i = 0; i < _options.Bonds.Size(); i++)
{
NCoderMixer2::CBond mixerBond;
const CBond2 &bond = _options.Bonds[i];
if (bond.InCoder >= _bindInfo.Coders.Size()
|| bond.OutCoder >= _bindInfo.Coders.Size()
|| bond.OutStream >= _bindInfo.Coders[bond.OutCoder].NumStreams)
return E_INVALIDARG;
mixerBond.PackIndex = _bindInfo.GetStream_for_Coder(bond.OutCoder) + bond.OutStream;
mixerBond.UnpackIndex = bond.InCoder;
_bindInfo.Bonds.Add(mixerBond);
}
for (i = 0; i < numOutStreams; i++)
if (_bindInfo.FindBond_for_PackStream(i) == -1)
_bindInfo.PackStreams.Add(i);
}
if (!_bindInfo.SetUnpackCoder())
return E_INVALIDARG;
if (!_bindInfo.CalcMapsAndCheck())
return E_INVALIDARG;
if (_bindInfo.PackStreams.Size() != 1)
{
/* main_PackStream is pack stream of main path of coders tree.
We find main_PackStream, and place to start of list of out streams.
It allows to use more optimal memory usage for temp buffers,
if main_PackStream is largest stream. */
UInt32 ci = _bindInfo.UnpackCoder;
for (;;)
{
if (_bindInfo.Coders[ci].NumStreams == 0)
break;
const UInt32 outIndex = _bindInfo.Coder_to_Stream[ci];
const int bond = _bindInfo.FindBond_for_PackStream(outIndex);
if (bond >= 0)
{
ci = _bindInfo.Bonds[(unsigned)bond].UnpackIndex;
continue;
}
const int si = _bindInfo.FindStream_in_PackStreams(outIndex);
if (si >= 0)
_bindInfo.PackStreams.MoveToFront((unsigned)si);
break;
}
}
if (_options.PasswordIsDefined)
{
unsigned numCryptoStreams = _bindInfo.PackStreams.Size();
unsigned numInStreams = _bindInfo.Coders.Size();
for (i = 0; i < numCryptoStreams; i++)
{
NCoderMixer2::CBond bond;
bond.UnpackIndex = numInStreams + i;
bond.PackIndex = _bindInfo.PackStreams[i];
_bindInfo.Bonds.Add(bond);
}
_bindInfo.PackStreams.Clear();
/*
if (numCryptoStreams == 0)
numCryptoStreams = 1;
*/
for (i = 0; i < numCryptoStreams; i++)
{
CMethodFull method;
method.NumStreams = 1;
method.Id = k_AES;
_options.Methods.Add(method);
NCoderMixer2::CCoderStreamsInfo cod;
cod.NumStreams = 1;
_bindInfo.Coders.Add(cod);
_bindInfo.PackStreams.Add(numOutStreams++);
}
}
}
for (unsigned i = _options.Methods.Size(); i != 0;)
_decompressionMethods.Add(_options.Methods[--i].Id);
if (_bindInfo.Coders.Size() > 16)
return E_INVALIDARG;
if (_bindInfo.GetNum_Bonds_and_PackStreams() > 16)
return E_INVALIDARG;
if (!_bindInfo.CalcMapsAndCheck())
return E_INVALIDARG;
InitBindConv();
_constructed = true;
return S_OK;
}
CEncoder::~CEncoder() {}
}}
@@ -0,0 +1,95 @@
// 7zEncode.h
#ifndef ZIP7_INC_7Z_ENCODE_H
#define ZIP7_INC_7Z_ENCODE_H
#include "7zCompressionMode.h"
#include "../Common/CoderMixer2.h"
#include "7zItem.h"
namespace NArchive {
namespace N7z {
Z7_CLASS_IMP_COM_1(
CMtEncMultiProgress,
ICompressProgressInfo
)
CMyComPtr<ICompressProgressInfo> _progress;
#ifndef Z7_ST
NWindows::NSynchronization::CCriticalSection CriticalSection;
#endif
public:
UInt64 OutSize;
CMtEncMultiProgress(): OutSize(0) {}
void Init(ICompressProgressInfo *progress);
void AddOutSize(UInt64 addOutSize)
{
#ifndef Z7_ST
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
#endif
OutSize += addOutSize;
}
};
class CEncoder Z7_final MY_UNCOPYABLE
{
#ifdef USE_MIXER_ST
NCoderMixer2::CMixerST *_mixerST;
#endif
#ifdef USE_MIXER_MT
NCoderMixer2::CMixerMT *_mixerMT;
#endif
NCoderMixer2::CMixer *_mixer;
CMyComPtr<IUnknown> _mixerRef;
CCompressionMethodMode _options;
NCoderMixer2::CBindInfo _bindInfo;
CRecordVector<CMethodId> _decompressionMethods;
CRecordVector<UInt32> SrcIn_to_DestOut;
CRecordVector<UInt32> SrcOut_to_DestIn;
// CRecordVector<UInt32> DestIn_to_SrcOut;
CRecordVector<UInt32> DestOut_to_SrcIn;
void InitBindConv();
void SetFolder(CFolder &folder);
HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS
const UInt64 *inSizeForReduce);
bool _constructed;
public:
CEncoder(const CCompressionMethodMode &options);
~CEncoder();
HRESULT EncoderConstr();
HRESULT Encode1(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream,
// const UInt64 *inStreamSize,
const UInt64 *inSizeForReduce,
UInt64 expectedDataSize,
CFolder &folderItem,
// CRecordVector<UInt64> &coderUnpackSizes,
// UInt64 &unpackSize,
ISequentialOutStream *outStream,
CRecordVector<UInt64> &packSizes,
ICompressProgressInfo *compressProgress);
void Encode_Post(
UInt64 unpackSize,
CRecordVector<UInt64> &coderUnpackSizes);
};
}}
#endif
@@ -0,0 +1,444 @@
// 7zExtract.cpp
#include "StdAfx.h"
#include "../../../../C/7zCrc.h"
#include "../../../Common/ComTry.h"
#include "../../Common/ProgressUtils.h"
#include "7zDecode.h"
#include "7zHandler.h"
// EXTERN_g_ExternalCodecs
namespace NArchive {
namespace N7z {
Z7_CLASS_IMP_COM_1(
CFolderOutStream
, ISequentialOutStream
/* , ICompressGetSubStreamSize */
)
CMyComPtr<ISequentialOutStream> _stream;
public:
bool TestMode;
bool CheckCrc;
private:
bool _fileIsOpen;
bool _calcCrc;
UInt32 _crc;
UInt64 _rem;
const UInt32 *_indexes;
// unsigned _startIndex;
unsigned _numFiles;
unsigned _fileIndex;
HRESULT OpenFile(bool isCorrupted = false);
HRESULT CloseFile_and_SetResult(Int32 res);
HRESULT CloseFile();
HRESULT ProcessEmptyFiles();
public:
const CDbEx *_db;
CMyComPtr<IArchiveExtractCallback> ExtractCallback;
bool ExtraWriteWasCut;
CFolderOutStream():
TestMode(false),
CheckCrc(true)
{}
HRESULT Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles);
HRESULT FlushCorrupted(Int32 callbackOperationResult);
bool WasWritingFinished() const { return _numFiles == 0; }
};
HRESULT CFolderOutStream::Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles)
{
// _startIndex = startIndex;
_fileIndex = startIndex;
_indexes = indexes;
_numFiles = numFiles;
_fileIsOpen = false;
ExtraWriteWasCut = false;
return ProcessEmptyFiles();
}
HRESULT CFolderOutStream::OpenFile(bool isCorrupted)
{
const CFileItem &fi = _db->Files[_fileIndex];
const UInt32 nextFileIndex = (_indexes ? *_indexes : _fileIndex);
Int32 askMode = (_fileIndex == nextFileIndex) ? TestMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract :
NExtract::NAskMode::kSkip;
if (isCorrupted
&& askMode == NExtract::NAskMode::kExtract
&& !_db->IsItemAnti(_fileIndex)
&& !fi.IsDir)
askMode = NExtract::NAskMode::kTest;
CMyComPtr<ISequentialOutStream> realOutStream;
RINOK(ExtractCallback->GetStream(_fileIndex, &realOutStream, askMode))
_stream = realOutStream;
_crc = CRC_INIT_VAL;
_calcCrc = (CheckCrc && fi.CrcDefined && !fi.IsDir);
_fileIsOpen = true;
_rem = fi.Size;
if (askMode == NExtract::NAskMode::kExtract
&& !realOutStream
&& !_db->IsItemAnti(_fileIndex)
&& !fi.IsDir)
askMode = NExtract::NAskMode::kSkip;
return ExtractCallback->PrepareOperation(askMode);
}
HRESULT CFolderOutStream::CloseFile_and_SetResult(Int32 res)
{
_stream.Release();
_fileIsOpen = false;
if (!_indexes)
_numFiles--;
else if (*_indexes == _fileIndex)
{
_indexes++;
_numFiles--;
}
_fileIndex++;
return ExtractCallback->SetOperationResult(res);
}
HRESULT CFolderOutStream::CloseFile()
{
const CFileItem &fi = _db->Files[_fileIndex];
return CloseFile_and_SetResult((!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc)) ?
NExtract::NOperationResult::kOK :
NExtract::NOperationResult::kCRCError);
}
HRESULT CFolderOutStream::ProcessEmptyFiles()
{
while (_numFiles != 0 && _db->Files[_fileIndex].Size == 0)
{
RINOK(OpenFile())
RINOK(CloseFile())
}
return S_OK;
}
Z7_COM7F_IMF(CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
{
if (processedSize)
*processedSize = 0;
while (size != 0)
{
if (_fileIsOpen)
{
UInt32 cur = (size < _rem ? size : (UInt32)_rem);
if (_calcCrc)
{
const UInt32 k_Step = (UInt32)1 << 20;
if (cur > k_Step)
cur = k_Step;
}
HRESULT result = S_OK;
if (_stream)
result = _stream->Write(data, cur, &cur);
if (_calcCrc)
_crc = CrcUpdate(_crc, data, cur);
if (processedSize)
*processedSize += cur;
data = (const Byte *)data + cur;
size -= cur;
_rem -= cur;
if (_rem == 0)
{
RINOK(CloseFile())
RINOK(ProcessEmptyFiles())
}
RINOK(result)
if (cur == 0)
break;
continue;
}
RINOK(ProcessEmptyFiles())
if (_numFiles == 0)
{
// we support partial extracting
/*
if (processedSize)
*processedSize += size;
break;
*/
ExtraWriteWasCut = true;
// return S_FALSE;
return k_My_HRESULT_WritingWasCut;
}
RINOK(OpenFile())
}
return S_OK;
}
HRESULT CFolderOutStream::FlushCorrupted(Int32 callbackOperationResult)
{
while (_numFiles != 0)
{
if (_fileIsOpen)
{
RINOK(CloseFile_and_SetResult(callbackOperationResult))
}
else
{
RINOK(OpenFile(true))
}
}
return S_OK;
}
/*
Z7_COM7F_IMF(CFolderOutStream::GetSubStreamSize(UInt64 subStream, UInt64 *value))
{
*value = 0;
// const unsigned numFiles_Original = _numFiles + _fileIndex - _startIndex;
const unsigned numFiles_Original = _numFiles;
if (subStream >= numFiles_Original)
return S_FALSE; // E_FAIL;
*value = _db->Files[_startIndex + (unsigned)subStream].Size;
return S_OK;
}
*/
Z7_COM7F_IMF(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;
UInt64 importantTotalUnpacked = 0;
// numItems = (UInt32)(Int32)-1;
const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
if (allFilesMode)
numItems = _db.Files.Size();
if (numItems == 0)
return S_OK;
{
CNum prevFolder = kNumNoIndex;
UInt32 nextFile = 0;
UInt32 i;
for (i = 0; i < numItems; i++)
{
const UInt32 fileIndex = allFilesMode ? i : indices[i];
const CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];
if (folderIndex == kNumNoIndex)
continue;
if (folderIndex != prevFolder || fileIndex < nextFile)
nextFile = _db.FolderStartFileIndex[folderIndex];
for (CNum index = nextFile; index <= fileIndex; index++)
importantTotalUnpacked += _db.Files[index].Size;
nextFile = fileIndex + 1;
prevFolder = folderIndex;
}
}
RINOK(extractCallback->SetTotal(importantTotalUnpacked))
CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
lps->Init(extractCallback, false);
CDecoder decoder(
#if !defined(USE_MIXER_MT)
false
#elif !defined(USE_MIXER_ST)
true
#elif !defined(Z7_7Z_SET_PROPERTIES)
#ifdef Z7_ST
false
#else
true
#endif
#else
_useMultiThreadMixer
#endif
);
UInt64 curPacked, curUnpacked;
CMyComPtr<IArchiveExtractCallbackMessage2> callbackMessage;
extractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage2, &callbackMessage);
CFolderOutStream *folderOutStream = new CFolderOutStream;
CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
folderOutStream->_db = &_db;
folderOutStream->ExtractCallback = extractCallback;
folderOutStream->TestMode = (testModeSpec != 0);
folderOutStream->CheckCrc = (_crcSize != 0);
for (UInt32 i = 0;; lps->OutSize += curUnpacked, lps->InSize += curPacked)
{
RINOK(lps->SetCur())
if (i >= numItems)
break;
curUnpacked = 0;
curPacked = 0;
UInt32 fileIndex = allFilesMode ? i : indices[i];
const CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];
UInt32 numSolidFiles = 1;
if (folderIndex != kNumNoIndex)
{
curPacked = _db.GetFolderFullPackSize(folderIndex);
UInt32 nextFile = fileIndex + 1;
fileIndex = _db.FolderStartFileIndex[folderIndex];
UInt32 k;
for (k = i + 1; k < numItems; k++)
{
const UInt32 fileIndex2 = allFilesMode ? k : indices[k];
if (_db.FileIndexToFolderIndexMap[fileIndex2] != folderIndex
|| fileIndex2 < nextFile)
break;
nextFile = fileIndex2 + 1;
}
numSolidFiles = k - i;
for (k = fileIndex; k < nextFile; k++)
curUnpacked += _db.Files[k].Size;
}
{
const HRESULT result = folderOutStream->Init(fileIndex,
allFilesMode ? NULL : indices + i,
numSolidFiles);
i += numSolidFiles;
RINOK(result)
}
if (folderOutStream->WasWritingFinished())
{
// for debug: to test zero size stream unpacking
// if (folderIndex == kNumNoIndex) // enable this check for debug
continue;
}
if (folderIndex == kNumNoIndex)
return E_FAIL;
#ifndef Z7_NO_CRYPTO
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
if (extractCallback)
extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
#endif
try
{
#ifndef Z7_NO_CRYPTO
bool isEncrypted = false;
bool passwordIsDefined = false;
UString_Wipe password;
#endif
bool dataAfterEnd_Error = false;
const HRESULT result = decoder.Decode(
EXTERNAL_CODECS_VARS
_inStream,
_db.ArcInfo.DataStartPosition,
_db, folderIndex,
&curUnpacked,
outStream,
lps,
NULL // *inStreamMainRes
, dataAfterEnd_Error
Z7_7Z_DECODER_CRYPRO_VARS
#if !defined(Z7_ST)
, true, _numThreads, _memUsage_Decompress
#endif
);
if (result == S_FALSE || result == E_NOTIMPL || dataAfterEnd_Error)
{
const bool wasFinished = folderOutStream->WasWritingFinished();
int resOp = NExtract::NOperationResult::kDataError;
if (result != S_FALSE)
{
if (result == E_NOTIMPL)
resOp = NExtract::NOperationResult::kUnsupportedMethod;
else if (wasFinished && dataAfterEnd_Error)
resOp = NExtract::NOperationResult::kDataAfterEnd;
}
RINOK(folderOutStream->FlushCorrupted(resOp))
if (wasFinished)
{
// we don't show error, if it's after required files
if (/* !folderOutStream->ExtraWriteWasCut && */ callbackMessage)
{
RINOK(callbackMessage->ReportExtractResult(NEventIndexType::kBlockIndex, folderIndex, resOp))
}
}
continue;
}
if (result != S_OK)
return result;
RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError))
continue;
}
catch(...)
{
RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError))
// continue;
// return E_FAIL;
throw;
}
}
return S_OK;
COM_TRY_END
}
}}
@@ -0,0 +1,264 @@
// 7zFolderInStream.cpp
#include "StdAfx.h"
#include "../../../Windows/TimeUtils.h"
#include "7zFolderInStream.h"
namespace NArchive {
namespace N7z {
void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,
const UInt32 *indexes, unsigned numFiles)
{
_updateCallback = updateCallback;
_indexes = indexes;
_numFiles = numFiles;
_totalSize_for_Coder = 0;
ClearFileInfo();
Processed.ClearAndReserve(numFiles);
Sizes.ClearAndReserve(numFiles);
CRCs.ClearAndReserve(numFiles);
TimesDefined.ClearAndReserve(numFiles);
MTimes.ClearAndReserve(Need_MTime ? numFiles : (unsigned)0);
CTimes.ClearAndReserve(Need_CTime ? numFiles : (unsigned)0);
ATimes.ClearAndReserve(Need_ATime ? numFiles : (unsigned)0);
Attribs.ClearAndReserve(Need_Attrib ? numFiles : (unsigned)0);
// FolderCrc = CRC_INIT_VAL;
_stream.Release();
}
void CFolderInStream::ClearFileInfo()
{
_pos = 0;
_crc = CRC_INIT_VAL;
_size_Defined = false;
_times_Defined = false;
_size = 0;
FILETIME_Clear(_mTime);
FILETIME_Clear(_cTime);
FILETIME_Clear(_aTime);
_attrib = 0;
}
HRESULT CFolderInStream::OpenStream()
{
while (Processed.Size() < _numFiles)
{
CMyComPtr<ISequentialInStream> stream;
const HRESULT result = _updateCallback->GetStream(_indexes[Processed.Size()], &stream);
if (result != S_OK && result != S_FALSE)
return result;
_stream = stream;
if (stream)
{
{
CMyComPtr<IStreamGetProps> getProps;
stream.QueryInterface(IID_IStreamGetProps, (void **)&getProps);
if (getProps)
{
// access could be changed in first myx pass
if (getProps->GetProps(&_size,
Need_CTime ? &_cTime : NULL,
Need_ATime ? &_aTime : NULL,
Need_MTime ? &_mTime : NULL,
Need_Attrib ? &_attrib : NULL)
== S_OK)
{
_size_Defined = true;
_times_Defined = true;
}
return S_OK;
}
}
{
CMyComPtr<IStreamGetSize> streamGetSize;
stream.QueryInterface(IID_IStreamGetSize, &streamGetSize);
if (streamGetSize)
{
if (streamGetSize->GetSize(&_size) == S_OK)
_size_Defined = true;
}
return S_OK;
}
}
RINOK(AddFileInfo(result == S_OK))
}
return S_OK;
}
static void AddFt(CRecordVector<UInt64> &vec, const FILETIME &ft)
{
vec.AddInReserved(FILETIME_To_UInt64(ft));
}
/*
HRESULT ReportItemProps(IArchiveUpdateCallbackArcProp *reportArcProp,
UInt32 index, UInt64 size, const UInt32 *crc)
{
PROPVARIANT prop;
prop.vt = VT_EMPTY;
prop.wReserved1 = 0;
NWindows::NCOM::PropVarEm_Set_UInt64(&prop, size);
RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidSize, &prop));
if (crc)
{
NWindows::NCOM::PropVarEm_Set_UInt32(&prop, *crc);
RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidCRC, &prop));
}
return reportArcProp->ReportFinished(NEventIndexType::kOutArcIndex, index, NUpdate::NOperationResult::kOK);
}
*/
HRESULT CFolderInStream::AddFileInfo(bool isProcessed)
{
// const UInt32 index = _indexes[Processed.Size()];
Processed.AddInReserved(isProcessed);
Sizes.AddInReserved(_pos);
CRCs.AddInReserved(CRC_GET_DIGEST(_crc));
if (Need_Attrib) Attribs.AddInReserved(_attrib);
TimesDefined.AddInReserved(_times_Defined);
if (Need_MTime) AddFt(MTimes, _mTime);
if (Need_CTime) AddFt(CTimes, _cTime);
if (Need_ATime) AddFt(ATimes, _aTime);
ClearFileInfo();
/*
if (isProcessed && _reportArcProp)
RINOK(ReportItemProps(_reportArcProp, index, _pos, &crc))
*/
return _updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
}
Z7_COM7F_IMF(CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
{
if (processedSize)
*processedSize = 0;
while (size != 0)
{
if (_stream)
{
/*
if (_pos == 0)
{
const UInt32 align = (UInt32)1 << AlignLog;
const UInt32 offset = (UInt32)_totalSize_for_Coder & (align - 1);
if (offset != 0)
{
UInt32 cur = align - offset;
if (cur > size)
cur = size;
memset(data, 0, cur);
data = (Byte *)data + cur;
size -= cur;
// _pos += cur; // for debug
_totalSize_for_Coder += cur;
if (processedSize)
*processedSize += cur;
continue;
}
}
*/
UInt32 cur = size;
const UInt32 kMax = (UInt32)1 << 20;
if (cur > kMax)
cur = kMax;
RINOK(_stream->Read(data, cur, &cur))
if (cur != 0)
{
// if (Need_Crc)
_crc = CrcUpdate(_crc, data, cur);
/*
if (FolderCrc)
FolderCrc = CrcUpdate(FolderCrc, data, cur);
*/
_pos += cur;
_totalSize_for_Coder += cur;
if (processedSize)
*processedSize = cur; // use +=cur, if continue is possible in loop
return S_OK;
}
_stream.Release();
RINOK(AddFileInfo(true))
}
if (Processed.Size() >= _numFiles)
break;
RINOK(OpenStream())
}
return S_OK;
}
Z7_COM7F_IMF(CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value))
{
*value = 0;
if (subStream > Sizes.Size())
return S_FALSE; // E_FAIL;
const unsigned index = (unsigned)subStream;
if (index < Sizes.Size())
{
*value = Sizes[index];
return S_OK;
}
if (!_size_Defined)
{
*value = _pos;
return S_FALSE;
}
*value = (_pos > _size ? _pos : _size);
return S_OK;
}
/*
HRESULT CFolderInStream::CloseCrcStream()
{
if (!_crcStream)
return S_OK;
if (!_crcStream_Spec->WasFinished())
return E_FAIL;
_crc = _crcStream_Spec->GetCRC() ^ CRC_INIT_VAL; // change it
const UInt64 size = _crcStream_Spec->GetSize();
_pos = size;
_totalSize_for_Coder += size;
_crcStream.Release();
// _crcStream->ReleaseStream();
_stream.Release();
return AddFileInfo(true);
}
Z7_COM7F_IMF(CFolderInStream::GetNextInSubStream(UInt64 *streamIndexRes, ISequentialInStream **stream)
{
RINOK(CloseCrcStream())
*stream = NULL;
*streamIndexRes = Processed.Size();
if (Processed.Size() >= _numFiles)
return S_OK;
RINOK(OpenStream());
if (!_stream)
return S_OK;
if (!_crcStream)
{
_crcStream_Spec = new CSequentialInStreamWithCRC;
_crcStream = _crcStream_Spec;
}
_crcStream_Spec->Init();
_crcStream_Spec->SetStream(_stream);
*stream = _crcStream;
_crcStream->AddRef();
return S_OK;
}
*/
}}
@@ -0,0 +1,101 @@
// 7zFolderInStream.h
#ifndef ZIP7_INC_7Z_FOLDER_IN_STREAM_H
#define ZIP7_INC_7Z_FOLDER_IN_STREAM_H
#include "../../../../C/7zCrc.h"
#include "../../../Common/MyCom.h"
#include "../../../Common/MyVector.h"
// #include "../Common/InStreamWithCRC.h"
#include "../../ICoder.h"
#include "../IArchive.h"
namespace NArchive {
namespace N7z {
Z7_CLASS_IMP_COM_2(
CFolderInStream
, ISequentialInStream
, ICompressGetSubStreamSize
)
/*
Z7_COM7F_IMP(GetNextStream(UInt64 *streamIndex))
Z7_IFACE_COM7_IMP(ICompressInSubStreams)
*/
CMyComPtr<ISequentialInStream> _stream;
UInt64 _totalSize_for_Coder;
UInt64 _pos;
UInt32 _crc;
bool _size_Defined;
bool _times_Defined;
UInt64 _size;
FILETIME _mTime;
FILETIME _cTime;
FILETIME _aTime;
UInt32 _attrib;
unsigned _numFiles;
const UInt32 *_indexes;
CMyComPtr<IArchiveUpdateCallback> _updateCallback;
void ClearFileInfo();
HRESULT OpenStream();
HRESULT AddFileInfo(bool isProcessed);
// HRESULT CloseCrcStream();
public:
bool Need_MTime;
bool Need_CTime;
bool Need_ATime;
bool Need_Attrib;
// bool Need_Crc;
// bool Need_FolderCrc;
// unsigned AlignLog;
CRecordVector<bool> Processed;
CRecordVector<UInt64> Sizes;
CRecordVector<UInt32> CRCs;
CRecordVector<UInt32> Attribs;
CRecordVector<bool> TimesDefined;
CRecordVector<UInt64> MTimes;
CRecordVector<UInt64> CTimes;
CRecordVector<UInt64> ATimes;
// UInt32 FolderCrc;
// UInt32 GetFolderCrc() const { return CRC_GET_DIGEST(FolderCrc); }
// CSequentialInStreamWithCRC *_crcStream_Spec;
// CMyComPtr<ISequentialInStream> _crcStream;
// CMyComPtr<IArchiveUpdateCallbackArcProp> _reportArcProp;
void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles);
bool WasFinished() const { return Processed.Size() == _numFiles; }
UInt64 Get_TotalSize_for_Coder() const { return _totalSize_for_Coder; }
/*
UInt64 GetFullSize() const
{
UInt64 size = 0;
FOR_VECTOR (i, Sizes)
size += Sizes[i];
return size;
}
*/
CFolderInStream():
Need_MTime(false),
Need_CTime(false),
Need_ATime(false),
Need_Attrib(false)
// , Need_Crc(true)
// , Need_FolderCrc(false)
// , AlignLog(0)
{}
};
}}
#endif
@@ -0,0 +1,795 @@
// 7zHandler.cpp
#include "StdAfx.h"
#include "../../../../C/CpuArch.h"
#include "../../../Common/ComTry.h"
#include "../../../Common/IntToString.h"
#ifndef Z7_7Z_SET_PROPERTIES
#include "../../../Windows/System.h"
#endif
#include "../Common/ItemNameUtils.h"
#include "7zHandler.h"
#include "7zProperties.h"
#ifdef Z7_7Z_SET_PROPERTIES
#ifdef Z7_EXTRACT_ONLY
#include "../Common/ParseProperties.h"
#endif
#endif
using namespace NWindows;
using namespace NCOM;
namespace NArchive {
namespace N7z {
CHandler::CHandler()
{
#ifndef Z7_NO_CRYPTO
_isEncrypted = false;
_passwordIsDefined = false;
#endif
#ifdef Z7_EXTRACT_ONLY
_crcSize = 4;
#ifdef Z7_7Z_SET_PROPERTIES
_useMultiThreadMixer = true;
#endif
#endif
}
Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
{
*numItems = _db.Files.Size();
return S_OK;
}
#ifdef Z7_SFX
IMP_IInArchive_ArcProps_NO_Table
Z7_COM7F_IMF(CHandler::GetNumberOfProperties(UInt32 *numProps))
{
*numProps = 0;
return S_OK;
}
Z7_COM7F_IMF(CHandler::GetPropertyInfo(UInt32 /* index */,
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */))
{
return E_NOTIMPL;
}
#else
static const Byte kArcProps[] =
{
kpidHeadersSize,
kpidMethod,
kpidSolid,
kpidNumBlocks
// , kpidIsTree
};
IMP_IInArchive_ArcProps
static inline char GetHex(unsigned value)
{
return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
}
static unsigned ConvertMethodIdToString_Back(char *s, UInt64 id)
{
int len = 0;
do
{
s[--len] = GetHex((unsigned)id & 0xF); id >>= 4;
s[--len] = GetHex((unsigned)id & 0xF); id >>= 4;
}
while (id != 0);
return (unsigned)-len;
}
static void ConvertMethodIdToString(AString &res, UInt64 id)
{
const unsigned kLen = 32;
char s[kLen];
unsigned len = kLen - 1;
s[len] = 0;
res += s + len - ConvertMethodIdToString_Back(s + len, id);
}
static char *GetStringForSizeValue(char *s, UInt32 val)
{
for (unsigned i = 0; i < 32; i++)
if (((UInt32)1 << i) == val)
{
if (i >= 10)
{
*s++= (char)('0' + i / 10);
i %= 10;
}
*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'; }
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)
{
res += GetHex((Byte)(value >> 4));
res += GetHex((Byte)(value & 0xF));
}
*/
static char *AddProp32(char *s, const char *name, UInt32 v)
{
*s++ = ':';
s = MyStpCpy(s, name);
return ConvertUInt32ToString(v, s);
}
void CHandler::AddMethodName(AString &s, UInt64 id)
{
AString name;
FindMethod(EXTERNAL_CODECS_VARS id, name);
if (name.IsEmpty())
ConvertMethodIdToString(s, id);
else
s += name;
}
#endif
Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
{
#ifndef Z7_SFX
COM_TRY_BEGIN
#endif
NCOM::CPropVariant prop;
switch (propID)
{
#ifndef Z7_SFX
case kpidMethod:
{
AString s;
const CParsedMethods &pm = _db.ParsedMethods;
FOR_VECTOR (i, pm.IDs)
{
UInt64 id = pm.IDs[i];
s.Add_Space_if_NotEmpty();
char temp[16];
if (id == k_LZMA2)
{
s += "LZMA2:";
GetLzma2String(temp, pm.Lzma2Prop);
s += temp;
}
else if (id == k_LZMA)
{
s += "LZMA:";
GetStringForSizeValue(temp, pm.LzmaDic);
s += temp;
}
/*
else if (id == k_ZSTD)
{
s += "ZSTD";
}
*/
else
AddMethodName(s, id);
}
prop = s;
break;
}
case kpidSolid: prop = _db.IsSolid(); break;
case kpidNumBlocks: prop = (UInt32)_db.NumFolders; break;
case kpidHeadersSize: prop = _db.HeadersSize; break;
case kpidPhySize: prop = _db.PhySize; break;
case kpidOffset: if (_db.ArcInfo.StartPosition != 0) prop = _db.ArcInfo.StartPosition; break;
/*
case kpidIsTree: if (_db.IsTree) prop = true; break;
case kpidIsAltStream: if (_db.ThereAreAltStreams) prop = true; break;
case kpidIsAux: if (_db.IsTree) prop = true; break;
*/
// case kpidError: if (_db.ThereIsHeaderError) prop = "Header error"; break;
#endif
case kpidWarningFlags:
{
UInt32 v = 0;
if (_db.StartHeaderWasRecovered) v |= kpv_ErrorFlags_HeadersError;
if (_db.UnsupportedFeatureWarning) v |= kpv_ErrorFlags_UnsupportedFeature;
if (v != 0)
prop = v;
break;
}
case kpidErrorFlags:
{
UInt32 v = 0;
if (!_db.IsArc) v |= kpv_ErrorFlags_IsNotArc;
if (_db.ThereIsHeaderError) v |= kpv_ErrorFlags_HeadersError;
if (_db.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;
// if (_db.UnsupportedVersion) v |= kpv_ErrorFlags_Unsupported;
if (_db.UnsupportedFeatureError) v |= kpv_ErrorFlags_UnsupportedFeature;
prop = v;
break;
}
case kpidReadOnly:
{
if (!_db.CanUpdate())
prop = true;
break;
}
default: break;
}
return prop.Detach(value);
#ifndef Z7_SFX
COM_TRY_END
#endif
}
static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, unsigned index)
{
UInt64 value;
if (v.GetItem(index, value))
PropVarEm_Set_FileTime64_Prec(prop, value, k_PropVar_TimePrec_100ns);
}
bool CHandler::IsFolderEncrypted(CNum folderIndex) const
{
if (folderIndex == kNumNoIndex)
return false;
const size_t startPos = _db.FoCodersDataOffset[folderIndex];
const Byte *p = _db.CodersData.ConstData() + startPos;
const size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
CInByte2 inByte;
inByte.Init(p, size);
CNum numCoders = inByte.ReadNum();
for (; numCoders != 0; numCoders--)
{
const Byte mainByte = inByte.ReadByte();
const unsigned idSize = (mainByte & 0xF);
const Byte *longID = inByte.GetPtr();
UInt64 id64 = 0;
for (unsigned j = 0; j < idSize; j++)
id64 = ((id64 << 8) | longID[j]);
inByte.SkipDataNoCheck(idSize);
if (id64 == k_AES)
return true;
if ((mainByte & 0x20) != 0)
inByte.SkipDataNoCheck(inByte.ReadNum());
}
return false;
}
Z7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps))
{
*numProps = 0;
return S_OK;
}
Z7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID))
{
*name = NULL;
*propID = kpidNtSecure;
return S_OK;
}
Z7_COM7F_IMF(CHandler::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType))
{
/*
const CFileItem &file = _db.Files[index];
*parentType = (file.IsAltStream ? NParentType::kAltStream : NParentType::kDir);
*parent = (UInt32)(Int32)file.Parent;
*/
*parentType = NParentType::kDir;
*parent = (UInt32)(Int32)-1;
return S_OK;
}
Z7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType))
{
*data = NULL;
*dataSize = 0;
*propType = 0;
if (/* _db.IsTree && propID == kpidName ||
!_db.IsTree && */ propID == kpidPath)
{
if (_db.NameOffsets && _db.NamesBuf)
{
const size_t offset = _db.NameOffsets[index];
const size_t size = (_db.NameOffsets[index + 1] - offset) * 2;
if (size < ((UInt32)1 << 31))
{
*data = (const void *)(_db.NamesBuf.ConstData() + offset * 2);
*dataSize = (UInt32)size;
*propType = NPropDataType::kUtf16z;
}
}
return S_OK;
}
/*
if (propID == kpidNtSecure)
{
if (index < (UInt32)_db.SecureIDs.Size())
{
int id = _db.SecureIDs[index];
size_t offs = _db.SecureOffsets[id];
size_t size = _db.SecureOffsets[id + 1] - offs;
if (size >= 0)
{
*data = _db.SecureBuf + offs;
*dataSize = (UInt32)size;
*propType = NPropDataType::kRaw;
}
}
}
*/
return S_OK;
}
#ifndef Z7_SFX
HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
{
PropVariant_Clear(prop);
if (folderIndex == kNumNoIndex)
return S_OK;
// for (int ttt = 0; ttt < 1; ttt++) {
const unsigned kTempSize = 256;
char temp[kTempSize];
unsigned pos = kTempSize;
temp[--pos] = 0;
const size_t startPos = _db.FoCodersDataOffset[folderIndex];
const Byte *p = _db.CodersData.ConstData() + startPos;
const size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
CInByte2 inByte;
inByte.Init(p, size);
// numCoders == 0 ???
CNum numCoders = inByte.ReadNum();
bool needSpace = false;
for (; numCoders != 0; numCoders--, needSpace = true)
{
if (pos < 32) // max size of property
break;
const Byte mainByte = inByte.ReadByte();
UInt64 id64 = 0;
const unsigned idSize = (mainByte & 0xF);
const Byte *longID = inByte.GetPtr();
for (unsigned j = 0; j < idSize; j++)
id64 = ((id64 << 8) | longID[j]);
inByte.SkipDataNoCheck(idSize);
if ((mainByte & 0x10) != 0)
{
inByte.ReadNum(); // NumInStreams
inByte.ReadNum(); // NumOutStreams
}
CNum propsSize = 0;
const Byte *props = NULL;
if ((mainByte & 0x20) != 0)
{
propsSize = inByte.ReadNum();
props = inByte.GetPtr();
inByte.SkipDataNoCheck(propsSize);
}
const char *name = NULL;
char s[32];
s[0] = 0;
if (id64 <= (UInt32)0xFFFFFFFF)
{
const UInt32 id = (UInt32)id64;
if (id == k_LZMA)
{
name = "LZMA";
if (propsSize == 5)
{
const UInt32 dicSize = GetUi32((const Byte *)props + 1);
char *dest = GetStringForSizeValue(s, dicSize);
UInt32 d = props[0];
if (d != 0x5D)
{
const UInt32 lc = d % 9;
d /= 9;
const UInt32 pb = d / 5;
const UInt32 lp = d % 5;
if (lc != 3) dest = AddProp32(dest, "lc", lc);
if (lp != 0) dest = AddProp32(dest, "lp", lp);
if (pb != 2) dest = AddProp32(dest, "pb", pb);
}
}
}
else if (id == k_LZMA2)
{
name = "LZMA2";
if (propsSize == 1)
GetLzma2String(s, props[0]);
}
else if (id == k_PPMD)
{
name = "PPMD";
if (propsSize == 5)
{
char *dest = s;
*dest++ = 'o';
dest = ConvertUInt32ToString(*props, dest);
dest = MyStpCpy(dest, ":mem");
GetStringForSizeValue(dest, GetUi32(props + 1));
}
}
else if (id == k_Delta)
{
name = "Delta";
if (propsSize == 1)
ConvertUInt32ToString((UInt32)props[0] + 1, s);
}
else if (id == k_ARM64 || id == k_RISCV)
{
name = id == k_ARM64 ? "ARM64" : "RISCV";
if (propsSize == 4)
ConvertUInt32ToString(GetUi32(props), s);
/*
else if (propsSize != 0)
MyStringCopy(s, "unsupported");
*/
}
else if (id == k_BCJ2) name = "BCJ2";
else if (id == k_BCJ) name = "BCJ";
else if (id == k_AES)
{
name = "7zAES";
if (propsSize >= 1)
{
const Byte firstByte = props[0];
const UInt32 numCyclesPower = firstByte & 0x3F;
ConvertUInt32ToString(numCyclesPower, s);
}
}
}
if (name)
{
const unsigned nameLen = MyStringLen(name);
const unsigned propsLen = MyStringLen(s);
unsigned totalLen = nameLen + propsLen;
if (propsLen != 0)
totalLen++;
if (needSpace)
totalLen++;
if (totalLen + 5 >= pos)
break;
pos -= totalLen;
MyStringCopy(temp + pos, name);
if (propsLen != 0)
{
char *dest = temp + pos + nameLen;
*dest++ = ':';
MyStringCopy(dest, s);
}
if (needSpace)
temp[pos + totalLen - 1] = ' ';
}
else
{
AString methodName;
FindMethod(EXTERNAL_CODECS_VARS id64, methodName);
if (needSpace)
temp[--pos] = ' ';
if (methodName.IsEmpty())
pos -= ConvertMethodIdToString_Back(temp + pos, id64);
else
{
const unsigned len = methodName.Len();
if (len + 5 > pos)
break;
pos -= len;
for (unsigned i = 0; i < len; i++)
temp[pos + i] = methodName[i];
}
}
}
if (numCoders != 0 && pos >= 4)
{
temp[--pos] = ' ';
temp[--pos] = '.';
temp[--pos] = '.';
temp[--pos] = '.';
}
return PropVarEm_Set_Str(prop, temp + pos);
// }
}
#endif
Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
{
RINOK(PropVariant_Clear(value))
// COM_TRY_BEGIN
// NCOM::CPropVariant prop;
/*
const CRef2 &ref2 = _refs[index];
if (ref2.Refs.IsEmpty())
return E_FAIL;
const CRef &ref = ref2.Refs.Front();
*/
const CFileItem &item = _db.Files[index];
const UInt32 index2 = index;
switch (propID)
{
case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break;
case kpidSize:
{
PropVarEm_Set_UInt64(value, item.Size);
// prop = ref2.Size;
break;
}
case kpidPackSize:
{
// prop = ref2.PackSize;
{
const CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
if (folderIndex != kNumNoIndex)
{
if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2)
PropVarEm_Set_UInt64(value, _db.GetFolderFullPackSize(folderIndex));
/*
else
PropVarEm_Set_UInt64(value, 0);
*/
}
else
PropVarEm_Set_UInt64(value, 0);
}
break;
}
// case kpidIsAux: prop = _db.IsItemAux(index2); break;
case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) PropVarEm_Set_UInt64(value, v); break; }
case kpidCTime: SetFileTimeProp_From_UInt64Def(value, _db.CTime, index2); break;
case kpidATime: SetFileTimeProp_From_UInt64Def(value, _db.ATime, index2); break;
case kpidMTime: SetFileTimeProp_From_UInt64Def(value, _db.MTime, index2); break;
case kpidAttrib: if (_db.Attrib.ValidAndDefined(index2)) PropVarEm_Set_UInt32(value, _db.Attrib.Vals[index2]); break;
case kpidCRC: if (item.CrcDefined) PropVarEm_Set_UInt32(value, item.Crc); break;
case kpidEncrypted: PropVarEm_Set_Bool(value, IsFolderEncrypted(_db.FileIndexToFolderIndexMap[index2])); break;
case kpidIsAnti: PropVarEm_Set_Bool(value, _db.IsItemAnti(index2)); break;
/*
case kpidIsAltStream: prop = item.IsAltStream; break;
case kpidNtSecure:
{
int id = _db.SecureIDs[index];
size_t offs = _db.SecureOffsets[id];
size_t size = _db.SecureOffsets[id + 1] - offs;
if (size >= 0)
{
prop.SetBlob(_db.SecureBuf + offs, (ULONG)size);
}
break;
}
*/
case kpidPath: return _db.GetPath_Prop(index, value);
#ifndef Z7_SFX
case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value);
case kpidBlock:
{
const CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
if (folderIndex != kNumNoIndex)
PropVarEm_Set_UInt32(value, (UInt32)folderIndex);
}
break;
#ifdef Z7_7Z_SHOW_PACK_STREAMS_SIZES
case kpidPackedSize0:
case kpidPackedSize1:
case kpidPackedSize2:
case kpidPackedSize3:
case kpidPackedSize4:
{
const CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
if (folderIndex != kNumNoIndex)
{
if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
_db.FoStartPackStreamIndex[folderIndex + 1] -
_db.FoStartPackStreamIndex[folderIndex] > (propID - kpidPackedSize0))
{
PropVarEm_Set_UInt64(value, _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0));
}
}
else
PropVarEm_Set_UInt64(value, 0);
}
break;
#endif
#endif
default: break;
}
// return prop.Detach(value);
return S_OK;
// COM_TRY_END
}
Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
const UInt64 *maxCheckStartPosition,
IArchiveOpenCallback *openArchiveCallback))
{
COM_TRY_BEGIN
Close();
#ifndef Z7_SFX
_fileInfoPopIDs.Clear();
#endif
try
{
CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;
#ifndef Z7_NO_CRYPTO
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
if (openArchiveCallback)
openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
#endif
CInArchive archive(
#ifdef Z7_7Z_SET_PROPERTIES
_useMultiThreadMixer
#else
true
#endif
);
_db.IsArc = false;
RINOK(archive.Open(stream, maxCheckStartPosition))
_db.IsArc = true;
HRESULT result = archive.ReadDatabase(
EXTERNAL_CODECS_VARS
_db
#ifndef Z7_NO_CRYPTO
, getTextPassword, _isEncrypted, _passwordIsDefined, _password
#endif
);
RINOK(result)
_inStream = stream;
}
catch(...)
{
Close();
// return E_INVALIDARG;
// return S_FALSE;
// we must return out_of_memory here
return E_OUTOFMEMORY;
}
// _inStream = stream;
#ifndef Z7_SFX
FillPopIDs();
#endif
return S_OK;
COM_TRY_END
}
Z7_COM7F_IMF(CHandler::Close())
{
COM_TRY_BEGIN
_inStream.Release();
_db.Clear();
#ifndef Z7_NO_CRYPTO
_isEncrypted = false;
_passwordIsDefined = false;
_password.Wipe_and_Empty();
#endif
return S_OK;
COM_TRY_END
}
#ifdef Z7_7Z_SET_PROPERTIES
#ifdef Z7_EXTRACT_ONLY
Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))
{
COM_TRY_BEGIN
InitCommon();
_useMultiThreadMixer = true;
for (UInt32 i = 0; i < numProps; i++)
{
UString name = names[i];
name.MakeLower_Ascii();
if (name.IsEmpty())
return E_INVALIDARG;
const PROPVARIANT &value = values[i];
UInt32 number;
const unsigned index = ParseStringToUInt32(name, number);
if (index == 0)
{
if (name.IsEqualTo("mtf"))
{
RINOK(PROPVARIANT_to_bool(value, _useMultiThreadMixer))
continue;
}
{
HRESULT hres;
if (SetCommonProperty(name, value, hres))
{
RINOK(hres)
continue;
}
}
return E_INVALIDARG;
}
}
return S_OK;
COM_TRY_END
}
#endif
#endif
IMPL_ISetCompressCodecsInfo
}}
@@ -0,0 +1,178 @@
// 7z/Handler.h
#ifndef ZIP7_7Z_HANDLER_H
#define ZIP7_7Z_HANDLER_H
#include "../../ICoder.h"
#include "../IArchive.h"
#include "../../Common/CreateCoder.h"
#ifndef Z7_7Z_SET_PROPERTIES
#ifdef Z7_EXTRACT_ONLY
#if !defined(Z7_ST) && !defined(Z7_SFX)
#define Z7_7Z_SET_PROPERTIES
#endif
#else
#define Z7_7Z_SET_PROPERTIES
#endif
#endif
// #ifdef Z7_7Z_SET_PROPERTIES
#include "../Common/HandlerOut.h"
// #endif
#include "7zCompressionMode.h"
#include "7zIn.h"
namespace NArchive {
namespace N7z {
#ifndef Z7_EXTRACT_ONLY
class COutHandler: public CMultiMethodProps
{
HRESULT SetSolidFromString(const UString &s);
HRESULT SetSolidFromPROPVARIANT(const PROPVARIANT &value);
public:
UInt64 _numSolidFiles;
UInt64 _numSolidBytes;
bool _numSolidBytesDefined;
bool _solidExtension;
bool _useTypeSorting;
bool _compressHeaders;
bool _encryptHeadersSpecified;
bool _encryptHeaders;
// bool _useParents; 9.26
CHandlerTimeOptions TimeOptions;
CBoolPair Write_Attrib;
bool _useMultiThreadMixer;
bool _removeSfxBlock;
// bool _volumeMode;
UInt32 _decoderCompatibilityVersion;
CUIntVector _enabledFilters;
CUIntVector _disabledFilters;
void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }
void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); }
void InitSolid()
{
InitSolidFiles();
InitSolidSize();
_solidExtension = false;
_numSolidBytesDefined = false;
}
void InitProps7z();
void InitProps();
COutHandler() { InitProps7z(); }
HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
};
#endif
class CHandler Z7_final:
public IInArchive,
public IArchiveGetRawProps,
#ifdef Z7_7Z_SET_PROPERTIES
public ISetProperties,
#endif
#ifndef Z7_EXTRACT_ONLY
public IOutArchive,
#endif
Z7_PUBLIC_ISetCompressCodecsInfo_IFEC
public CMyUnknownImp,
#ifndef Z7_EXTRACT_ONLY
public COutHandler
#else
public CCommonMethodProps
#endif
{
Z7_COM_QI_BEGIN2(IInArchive)
Z7_COM_QI_ENTRY(IArchiveGetRawProps)
#ifdef Z7_7Z_SET_PROPERTIES
Z7_COM_QI_ENTRY(ISetProperties)
#endif
#ifndef Z7_EXTRACT_ONLY
Z7_COM_QI_ENTRY(IOutArchive)
#endif
Z7_COM_QI_ENTRY_ISetCompressCodecsInfo_IFEC
Z7_COM_QI_END
Z7_COM_ADDREF_RELEASE
Z7_IFACE_COM7_IMP(IInArchive)
Z7_IFACE_COM7_IMP(IArchiveGetRawProps)
#ifdef Z7_7Z_SET_PROPERTIES
Z7_IFACE_COM7_IMP(ISetProperties)
#endif
#ifndef Z7_EXTRACT_ONLY
Z7_IFACE_COM7_IMP(IOutArchive)
#endif
DECL_ISetCompressCodecsInfo
private:
CMyComPtr<IInStream> _inStream;
NArchive::N7z::CDbEx _db;
#ifndef Z7_NO_CRYPTO
bool _isEncrypted;
bool _passwordIsDefined;
UString _password; // _Wipe
#endif
#ifdef Z7_EXTRACT_ONLY
#ifdef Z7_7Z_SET_PROPERTIES
bool _useMultiThreadMixer;
#endif
UInt32 _crcSize;
#else
CRecordVector<CBond2> _bonds;
HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m);
HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod);
HRESULT SetMainMethod(CCompressionMethodMode &method);
#endif
bool IsFolderEncrypted(CNum folderIndex) const;
#ifndef Z7_SFX
CRecordVector<UInt64> _fileInfoPopIDs;
void FillPopIDs();
void AddMethodName(AString &s, UInt64 id);
HRESULT SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const;
#endif
DECL_EXTERNAL_CODECS_VARS
public:
CHandler();
~CHandler()
{
Close();
}
};
}}
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,19 @@
// 7zHeader.cpp
#include "StdAfx.h"
#include "7zHeader.h"
namespace NArchive {
namespace N7z {
Byte kSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
#ifdef Z7_7Z_VOL
Byte kFinishSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C + 1};
#endif
// We can change signature. So file doesn't contain correct signature.
// struct SignatureInitializer { SignatureInitializer() { kSignature[0]--; } };
// static SignatureInitializer g_SignatureInitializer;
}}
@@ -0,0 +1,156 @@
// 7z/7zHeader.h
#ifndef ZIP7_INC_7Z_HEADER_H
#define ZIP7_INC_7Z_HEADER_H
#include "../../../Common/MyTypes.h"
namespace NArchive {
namespace N7z {
const unsigned kSignatureSize = 6;
extern Byte kSignature[kSignatureSize];
// #define Z7_7Z_VOL
// 7z-MultiVolume is not finished yet.
// It can work already, but I still do not like some
// things of that new multivolume format.
// So please keep it commented.
#ifdef Z7_7Z_VOL
extern Byte kFinishSignature[kSignatureSize];
#endif
struct CArchiveVersion
{
Byte Major;
Byte Minor;
};
const Byte kMajorVersion = 0;
struct CStartHeader
{
UInt64 NextHeaderOffset;
UInt64 NextHeaderSize;
UInt32 NextHeaderCRC;
};
const UInt32 kStartHeaderSize = 20;
#ifdef Z7_7Z_VOL
struct CFinishHeader: public CStartHeader
{
UInt64 ArchiveStartOffset; // data offset from end if that struct
UInt64 AdditionalStartBlockSize; // start signature & start header size
};
const UInt32 kFinishHeaderSize = kStartHeaderSize + 16;
#endif
namespace NID
{
enum EEnum
{
kEnd,
kHeader,
kArchiveProperties,
kAdditionalStreamsInfo,
kMainStreamsInfo,
kFilesInfo,
kPackInfo,
kUnpackInfo,
kSubStreamsInfo,
kSize,
kCRC,
kFolder,
kCodersUnpackSize,
kNumUnpackStream,
kEmptyStream,
kEmptyFile,
kAnti,
kName,
kCTime,
kATime,
kMTime,
kWinAttrib,
kComment,
kEncodedHeader,
kStartPos,
kDummy
// kNtSecure,
// kParent,
// kIsAux
};
}
const UInt32 k_Copy = 0;
const UInt32 k_Delta = 3;
const UInt32 k_ARM64 = 0xa;
const UInt32 k_RISCV = 0xb;
const UInt32 k_LZMA2 = 0x21;
const UInt32 k_SWAP2 = 0x20302;
const UInt32 k_SWAP4 = 0x20304;
const UInt32 k_LZMA = 0x30101;
const UInt32 k_PPMD = 0x30401;
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;
const UInt32 k_PPC = 0x3030205;
const UInt32 k_IA64 = 0x3030401;
const UInt32 k_ARM = 0x3030501;
const UInt32 k_ARMT = 0x3030701;
const UInt32 k_SPARC = 0x3030805;
const UInt32 k_AES = 0x6F10701;
// const UInt32 k_ZSTD = 0x4015D; // winzip zstd
// 0x4F71101, 7z-zstd
inline bool IsFilterMethod(UInt64 m)
{
if (m > (UInt32)0xFFFFFFFF)
return false;
switch ((UInt32)m)
{
case k_Delta:
case k_ARM64:
case k_RISCV:
case k_BCJ:
case k_BCJ2:
case k_PPC:
case k_IA64:
case k_ARM:
case k_ARMT:
case k_SPARC:
case k_SWAP2:
case k_SWAP4:
return true;
default: break;
}
return false;
}
}}
#endif
File diff suppressed because it is too large Load Diff
+454
View File
@@ -0,0 +1,454 @@
// 7zIn.h
#ifndef ZIP7_INC_7Z_IN_H
#define ZIP7_INC_7Z_IN_H
#include "../../../Common/MyCom.h"
#include "../../../Windows/PropVariant.h"
#include "../../IPassword.h"
#include "../../IStream.h"
#include "../../Common/CreateCoder.h"
#include "../../Common/InBuffer.h"
#include "7zItem.h"
namespace NArchive {
namespace N7z {
/*
We don't need to init isEncrypted and passwordIsDefined
We must upgrade them only */
#ifdef Z7_NO_CRYPTO
#define Z7_7Z_DECODER_CRYPRO_VARS_DECL
#define Z7_7Z_DECODER_CRYPRO_VARS
#else
#define Z7_7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined, UString &password
#define Z7_7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined, password
#endif
struct CParsedMethods
{
Byte Lzma2Prop;
UInt32 LzmaDic;
CRecordVector<UInt64> IDs;
CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {}
};
struct CFolderEx: public CFolder
{
unsigned UnpackCoder;
};
struct CFolders
{
CNum NumPackStreams;
CNum NumFolders;
CObjArray<UInt64> PackPositions; // NumPackStreams + 1
// CUInt32DefVector PackCRCs; // we don't use PackCRCs now
CUInt32DefVector FolderCRCs; // NumFolders
CObjArray<CNum> NumUnpackStreamsVector; // NumFolders
CObjArray<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders
CObjArray<CNum> FoToCoderUnpackSizes; // NumFolders + 1
CObjArray<CNum> FoStartPackStreamIndex; // NumFolders + 1
CObjArray<Byte> FoToMainUnpackSizeIndex; // NumFolders
CObjArray<size_t> FoCodersDataOffset; // NumFolders + 1
CByteBuffer CodersData;
CParsedMethods ParsedMethods;
void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const;
void ParseFolderEx(unsigned folderIndex, CFolderEx &folder) const
{
ParseFolderInfo(folderIndex, folder);
folder.UnpackCoder = FoToMainUnpackSizeIndex[folderIndex];
}
unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const
{
return (unsigned)(FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]);
}
UInt64 GetFolderUnpackSize(unsigned folderIndex) const
{
return CoderUnpackSizes[FoToCoderUnpackSizes[folderIndex] + FoToMainUnpackSizeIndex[folderIndex]];
}
UInt64 GetStreamPackSize(unsigned index) const
{
return PackPositions[index + 1] - PackPositions[index];
}
CFolders(): NumPackStreams(0), NumFolders(0) {}
void Clear()
{
NumPackStreams = 0;
PackPositions.Free();
// PackCRCs.Clear();
NumFolders = 0;
FolderCRCs.Clear();
NumUnpackStreamsVector.Free();
CoderUnpackSizes.Free();
FoToCoderUnpackSizes.Free();
FoStartPackStreamIndex.Free();
FoToMainUnpackSizeIndex.Free();
FoCodersDataOffset.Free();
CodersData.Free();
}
};
struct CDatabase: public CFolders
{
CRecordVector<CFileItem> Files;
CUInt64DefVector CTime;
CUInt64DefVector ATime;
CUInt64DefVector MTime;
CUInt64DefVector StartPos;
CUInt32DefVector Attrib;
CBoolVector IsAnti;
/*
CBoolVector IsAux;
CByteBuffer SecureBuf;
CRecordVector<UInt32> SecureIDs;
*/
CByteBuffer NamesBuf;
CObjArray<size_t> NameOffsets; // numFiles + 1, offsets of utf-16 symbols
/*
void ClearSecure()
{
SecureBuf.Free();
SecureIDs.Clear();
}
*/
void Clear()
{
CFolders::Clear();
// ClearSecure();
NamesBuf.Free();
NameOffsets.Free();
Files.Clear();
CTime.Clear();
ATime.Clear();
MTime.Clear();
StartPos.Clear();
Attrib.Clear();
IsAnti.Clear();
// IsAux.Clear();
}
bool IsSolid() const
{
for (CNum i = 0; i < NumFolders; i++)
if (NumUnpackStreamsVector[i] > 1)
return true;
return false;
}
bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }
// bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); }
/*
const void* GetName(unsigned index) const
{
if (!NameOffsets || !NamesBuf)
return NULL;
return (void *)((const Byte *)NamesBuf + NameOffsets[index] * 2);
};
*/
void GetPath(unsigned index, UString &path) const;
HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw();
};
struct CInArchiveInfo
{
CArchiveVersion Version;
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()
{
StartPosition = 0;
StartPositionAfterHeader = 0;
DataStartPosition = 0;
DataStartPosition2 = 0;
FileInfoPopIDs.Clear();
}
};
struct CDbEx: public CDatabase
{
CInArchiveInfo ArcInfo;
CObjArray<CNum> FolderStartFileIndex;
CObjArray<CNum> FileIndexToFolderIndexMap;
UInt64 HeadersSize;
UInt64 PhySize;
// UInt64 EndHeaderOffset; // relative to position after StartHeader (32 bytes)
/*
CRecordVector<size_t> SecureOffsets;
bool IsTree;
bool ThereAreAltStreams;
*/
bool IsArc;
bool PhySizeWasConfirmed;
bool ThereIsHeaderError;
bool UnexpectedEnd;
// bool UnsupportedVersion;
bool StartHeaderWasRecovered;
bool UnsupportedFeatureWarning;
bool UnsupportedFeatureError;
/*
void ClearSecureEx()
{
ClearSecure();
SecureOffsets.Clear();
}
*/
void Clear()
{
IsArc = false;
PhySizeWasConfirmed = false;
ThereIsHeaderError = false;
UnexpectedEnd = false;
// UnsupportedVersion = false;
StartHeaderWasRecovered = false;
UnsupportedFeatureError = false;
UnsupportedFeatureWarning = false;
/*
IsTree = false;
ThereAreAltStreams = false;
*/
CDatabase::Clear();
// SecureOffsets.Clear();
ArcInfo.Clear();
FolderStartFileIndex.Free();
FileIndexToFolderIndexMap.Free();
HeadersSize = 0;
PhySize = 0;
// EndHeaderOffset = 0;
}
bool CanUpdate() const
{
if (ThereIsHeaderError
|| UnexpectedEnd
|| StartHeaderWasRecovered
|| UnsupportedFeatureError)
return false;
return true;
}
void FillLinks();
UInt64 GetFolderStreamPos(size_t folderIndex, size_t indexInFolder) const
{
return ArcInfo.DataStartPosition + PackPositions.ConstData()
[FoStartPackStreamIndex.ConstData()[folderIndex] + indexInFolder];
}
UInt64 GetFolderFullPackSize(size_t folderIndex) const
{
return
PackPositions[FoStartPackStreamIndex.ConstData()[folderIndex + 1]] -
PackPositions[FoStartPackStreamIndex.ConstData()[folderIndex]];
}
UInt64 GetFolderPackStreamSize(size_t folderIndex, size_t streamIndex) const
{
const size_t i = FoStartPackStreamIndex.ConstData()[folderIndex] + streamIndex;
return PackPositions.ConstData()[i + 1] -
PackPositions.ConstData()[i];
}
/*
UInt64 GetFilePackSize(size_t fileIndex) const
{
const CNum folderIndex = FileIndexToFolderIndexMap[fileIndex];
if (folderIndex != kNumNoIndex)
if (FolderStartFileIndex[folderIndex] == fileIndex)
return GetFolderFullPackSize(folderIndex);
return 0;
}
*/
};
const unsigned kNumBufLevelsMax = 4;
struct CInByte2
{
const Byte *_buffer;
public:
size_t _size;
size_t _pos;
size_t GetRem() const { return _size - _pos; }
const Byte *GetPtr() const { return _buffer + _pos; }
void Init(const Byte *buffer, size_t size)
{
_buffer = buffer;
_size = size;
_pos = 0;
}
Byte ReadByte();
void ReadBytes(Byte *data, size_t size);
void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; }
void SkipData(UInt64 size);
void SkipData();
void SkipRem() { _pos = _size; }
UInt64 ReadNumber();
CNum ReadNum();
UInt32 ReadUInt32();
UInt64 ReadUInt64();
void ParseFolder(CFolder &folder);
};
class CStreamSwitch;
const UInt32 kHeaderSize = 32;
class CInArchive
{
friend class CStreamSwitch;
CMyComPtr<IInStream> _stream;
unsigned _numInByteBufs;
CInByte2 _inByteVector[kNumBufLevelsMax];
CInByte2 *_inByteBack;
bool ThereIsHeaderError;
UInt64 _arhiveBeginStreamPosition;
UInt64 _fileEndPosition;
UInt64 _rangeLimit; // relative to position after StartHeader (32 bytes)
Byte _header[kHeaderSize];
UInt64 HeadersSize;
bool _useMixerMT;
void AddByteStream(const Byte *buffer, size_t size);
void DeleteByteStream(bool needUpdatePos)
{
_numInByteBufs--;
if (_numInByteBufs > 0)
{
_inByteBack = &_inByteVector[_numInByteBufs - 1];
if (needUpdatePos)
_inByteBack->_pos += _inByteVector[_numInByteBufs]._pos;
}
}
HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
Byte ReadByte() { return _inByteBack->ReadByte(); }
UInt64 ReadNumber() { return _inByteBack->ReadNumber(); }
CNum ReadNum() { return _inByteBack->ReadNum(); }
UInt64 ReadID() { return _inByteBack->ReadNumber(); }
UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }
UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }
void SkipData(UInt64 size) { _inByteBack->SkipData(size); }
void SkipData() { _inByteBack->SkipData(); }
void WaitId(UInt64 id);
void Read_UInt32_Vector(CUInt32DefVector &v);
void ReadArchiveProperties(CInArchiveInfo &archiveInfo);
void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs);
void ReadPackInfo(CFolders &f);
void ReadUnpackInfo(
const CObjectVector<CByteBuffer> *dataVector,
CFolders &folders);
void ReadSubStreamsInfo(
CFolders &folders,
CRecordVector<UInt64> &unpackSizes,
CUInt32DefVector &digests);
void ReadStreamsInfo(
const CObjectVector<CByteBuffer> *dataVector,
UInt64 &dataOffset,
CFolders &folders,
CRecordVector<UInt64> &unpackSizes,
CUInt32DefVector &digests);
void ReadBoolVector(unsigned numItems, CBoolVector &v);
void ReadBoolVector2(unsigned numItems, CBoolVector &v);
void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,
CUInt64DefVector &v, unsigned numItems);
HRESULT ReadAndDecodePackedStreams(
DECL_EXTERNAL_CODECS_LOC_VARS
UInt64 baseOffset, UInt64 &dataOffset,
CObjectVector<CByteBuffer> &dataVector
Z7_7Z_DECODER_CRYPRO_VARS_DECL
);
HRESULT ReadHeader(
DECL_EXTERNAL_CODECS_LOC_VARS
CDbEx &db
Z7_7Z_DECODER_CRYPRO_VARS_DECL
);
HRESULT ReadDatabase2(
DECL_EXTERNAL_CODECS_LOC_VARS
CDbEx &db
Z7_7Z_DECODER_CRYPRO_VARS_DECL
);
public:
CInArchive(bool useMixerMT):
_numInByteBufs(0),
_useMixerMT(useMixerMT)
{}
HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
void Close();
HRESULT ReadDatabase(
DECL_EXTERNAL_CODECS_LOC_VARS
CDbEx &db
Z7_7Z_DECODER_CRYPRO_VARS_DECL
);
};
}}
#endif
+207
View File
@@ -0,0 +1,207 @@
// 7zItem.h
#ifndef ZIP7_INC_7Z_ITEM_H
#define ZIP7_INC_7Z_ITEM_H
#include "../../../Common/MyBuffer.h"
#include "../../../Common/MyString.h"
#include "../../Common/MethodId.h"
#include "7zHeader.h"
namespace NArchive {
namespace N7z {
typedef UInt32 CNum;
const CNum kNumMax = 0x7FFFFFFF;
const CNum kNumNoIndex = 0xFFFFFFFF;
struct CCoderInfo
{
CMethodId MethodID;
CByteBuffer Props;
UInt32 NumStreams;
bool IsSimpleCoder() const { return NumStreams == 1; }
};
struct CBond
{
UInt32 PackIndex;
UInt32 UnpackIndex;
};
struct CFolder
{
Z7_CLASS_NO_COPY(CFolder)
public:
CObjArray2<CCoderInfo> Coders;
CObjArray2<CBond> Bonds;
CObjArray2<UInt32> PackStreams;
CFolder() {}
bool IsDecodingSupported() const { return Coders.Size() <= 32; }
int Find_in_PackStreams(UInt32 packStream) const
{
FOR_VECTOR(i, PackStreams)
if (PackStreams[i] == packStream)
return (int)i;
return -1;
}
int FindBond_for_PackStream(UInt32 packStream) const
{
FOR_VECTOR(i, Bonds)
if (Bonds[i].PackIndex == packStream)
return (int)i;
return -1;
}
/*
int FindBond_for_UnpackStream(UInt32 unpackStream) const
{
FOR_VECTOR(i, Bonds)
if (Bonds[i].UnpackIndex == unpackStream)
return i;
return -1;
}
int FindOutCoder() const
{
for (int i = (int)Coders.Size() - 1; i >= 0; i--)
if (FindBond_for_UnpackStream(i) < 0)
return i;
return -1;
}
*/
bool IsEncrypted() const
{
FOR_VECTOR(i, Coders)
if (Coders[i].MethodID == k_AES)
return true;
return false;
}
};
struct CUInt32DefVector
{
CBoolVector Defs;
CRecordVector<UInt32> Vals;
void ClearAndSetSize(unsigned newSize)
{
Defs.ClearAndSetSize(newSize);
Vals.ClearAndSetSize(newSize);
}
void Clear()
{
Defs.Clear();
Vals.Clear();
}
void ReserveDown()
{
Defs.ReserveDown();
Vals.ReserveDown();
}
bool GetItem(unsigned index, UInt32 &value) const
{
if (index < Defs.Size() && Defs[index])
{
value = Vals[index];
return true;
}
value = 0;
return false;
}
bool ValidAndDefined(unsigned i) const { return i < Defs.Size() && Defs[i]; }
bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; }
void SetItem(unsigned index, bool defined, UInt32 value);
void if_NonEmpty_FillResidue_with_false(unsigned numItems)
{
if (Defs.Size() != 0 && Defs.Size() < numItems)
SetItem(numItems - 1, false, 0);
}
};
struct CUInt64DefVector
{
CBoolVector Defs;
CRecordVector<UInt64> Vals;
void Clear()
{
Defs.Clear();
Vals.Clear();
}
void ReserveDown()
{
Defs.ReserveDown();
Vals.ReserveDown();
}
bool GetItem(unsigned index, UInt64 &value) const
{
if (index < Defs.Size() && Defs[index])
{
value = Vals[index];
return true;
}
value = 0;
return false;
}
bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; }
void SetItem(unsigned index, bool defined, UInt64 value);
};
struct CFileItem
{
UInt64 Size;
UInt32 Crc;
/*
int Parent;
bool IsAltStream;
*/
bool HasStream; // Test it !!! it means that there is
// stream in some folder. It can be empty stream
bool IsDir;
bool CrcDefined;
/*
void Clear()
{
HasStream = true;
IsDir = false;
CrcDefined = false;
}
CFileItem():
// Parent(-1),
// IsAltStream(false),
HasStream(true),
IsDir(false),
CrcDefined(false),
{}
*/
};
}}
#endif
File diff suppressed because it is too large Load Diff
+346
View File
@@ -0,0 +1,346 @@
// 7zOut.h
#ifndef ZIP7_INC_7Z_OUT_H
#define ZIP7_INC_7Z_OUT_H
#include "7zCompressionMode.h"
#include "7zEncode.h"
#include "7zHeader.h"
#include "7zItem.h"
#include "../../Common/OutBuffer.h"
#include "../../Common/StreamUtils.h"
namespace NArchive {
namespace N7z {
const unsigned k_StartHeadersRewriteSize = 32;
class CWriteBufferLoc
{
Byte *_data;
Byte *_dataLim;
Byte *_dataBase;
public:
// CWriteBufferLoc(): _data(NULL), _dataLim(NULL), _dataBase(NULL) {}
void Init(Byte *data, size_t size)
{
_data = data;
_dataBase = data;
_dataLim = data + size;
}
Byte *GetDest_and_Update(size_t size)
{
Byte *dest = _data;
if (size > (size_t)(_dataLim - dest))
throw 1;
_data = dest + size;
return dest;
}
void WriteBytes(const void *data, size_t size)
{
if (size == 0)
return;
Byte *dest = GetDest_and_Update(size);
memcpy(dest, data, size);
}
void WriteByte(Byte b)
{
Byte *dest = _data;
if (dest == _dataLim)
throw 1;
*dest++ = b;
_data = dest;
}
size_t GetPos() const { return (size_t)(_data - _dataBase); }
};
struct CHeaderOptions
{
bool CompressMainHeader;
/*
bool WriteCTime;
bool WriteATime;
bool WriteMTime;
*/
CHeaderOptions():
CompressMainHeader(true)
/*
, WriteCTime(false)
, WriteATime(false)
, WriteMTime(true)
*/
{}
};
struct CFileItem2
{
UInt64 CTime;
UInt64 ATime;
UInt64 MTime;
UInt64 StartPos;
UInt32 Attrib;
bool CTimeDefined;
bool ATimeDefined;
bool MTimeDefined;
bool StartPosDefined;
bool AttribDefined;
bool IsAnti;
// bool IsAux;
/*
void Init()
{
CTimeDefined = false;
ATimeDefined = false;
MTimeDefined = false;
StartPosDefined = false;
AttribDefined = false;
IsAnti = false;
// IsAux = false;
}
*/
};
struct COutFolders
{
CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only.
CRecordVector<CNum> NumUnpackStreamsVector;
CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders
void OutFoldersClear()
{
FolderUnpackCRCs.Clear();
NumUnpackStreamsVector.Clear();
CoderUnpackSizes.Clear();
}
void OutFoldersReserveDown()
{
FolderUnpackCRCs.ReserveDown();
NumUnpackStreamsVector.ReserveDown();
CoderUnpackSizes.ReserveDown();
}
};
struct CArchiveDatabaseOut: public COutFolders
{
CRecordVector<UInt64> PackSizes;
CUInt32DefVector PackCRCs;
CObjectVector<CFolder> Folders;
CRecordVector<CFileItem> Files;
UStringVector Names;
CUInt64DefVector CTime;
CUInt64DefVector ATime;
CUInt64DefVector MTime;
CUInt64DefVector StartPos;
CUInt32DefVector Attrib;
CBoolVector IsAnti;
/*
CBoolVector IsAux;
CByteBuffer SecureBuf;
CRecordVector<UInt32> SecureSizes;
CRecordVector<UInt32> SecureIDs;
void ClearSecure()
{
SecureBuf.Free();
SecureSizes.Clear();
SecureIDs.Clear();
}
*/
void Clear()
{
OutFoldersClear();
PackSizes.Clear();
PackCRCs.Clear();
Folders.Clear();
Files.Clear();
Names.Clear();
CTime.Clear();
ATime.Clear();
MTime.Clear();
StartPos.Clear();
Attrib.Clear();
IsAnti.Clear();
/*
IsAux.Clear();
ClearSecure();
*/
}
void ReserveDown()
{
OutFoldersReserveDown();
PackSizes.ReserveDown();
PackCRCs.ReserveDown();
Folders.ReserveDown();
Files.ReserveDown();
Names.ReserveDown();
CTime.ReserveDown();
ATime.ReserveDown();
MTime.ReserveDown();
StartPos.ReserveDown();
Attrib.ReserveDown();
IsAnti.ReserveDown();
/*
IsAux.ReserveDown();
*/
}
bool IsEmpty() const
{
return (
PackSizes.IsEmpty() &&
NumUnpackStreamsVector.IsEmpty() &&
Folders.IsEmpty() &&
Files.IsEmpty());
}
bool CheckNumFiles() const
{
unsigned size = Files.Size();
return (
CTime.CheckSize(size)
&& ATime.CheckSize(size)
&& MTime.CheckSize(size)
&& StartPos.CheckSize(size)
&& Attrib.CheckSize(size)
&& (size == IsAnti.Size() || IsAnti.Size() == 0));
}
bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }
// bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); }
void SetItem_Anti(unsigned index, bool isAnti)
{
while (index >= IsAnti.Size())
IsAnti.Add(false);
IsAnti[index] = isAnti;
}
/*
void SetItem_Aux(unsigned index, bool isAux)
{
while (index >= IsAux.Size())
IsAux.Add(false);
IsAux[index] = isAux;
}
*/
void AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name);
};
class COutArchive
{
HRESULT WriteDirect(const void *data, UInt32 size) { return WriteStream(SeqStream, data, size); }
UInt64 GetPos() const;
void WriteBytes(const void *data, size_t size);
void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.Size()); }
void WriteByte(Byte b);
void WriteByte_ToStream(Byte b)
{
_outByte.WriteByte(b);
// _crc = CRC_UPDATE_BYTE(_crc, b);
}
// void WriteUInt32(UInt32 value);
// void WriteUInt64(UInt64 value);
void WriteNumber(UInt64 value);
void WriteID(UInt64 value) { WriteNumber(value); }
void WriteFolder(const CFolder &folder);
HRESULT WriteFileHeader(const CFileItem &itemInfo);
void Write_BoolVector(const CBoolVector &boolVector);
void Write_BoolVector_numDefined(const CBoolVector &boolVector, unsigned numDefined);
void WritePropBoolVector(Byte id, const CBoolVector &boolVector);
void WriteHashDigests(const CUInt32DefVector &digests);
void WritePackInfo(
UInt64 dataOffset,
const CRecordVector<UInt64> &packSizes,
const CUInt32DefVector &packCRCs);
void WriteUnpackInfo(
const CObjectVector<CFolder> &folders,
const COutFolders &outFolders);
void WriteSubStreamsInfo(
const CObjectVector<CFolder> &folders,
const COutFolders &outFolders,
const CRecordVector<UInt64> &unpackSizes,
const CUInt32DefVector &digests);
void SkipToAligned(unsigned pos, unsigned alignShifts);
void WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts);
void Write_UInt32DefVector_numDefined(const CUInt32DefVector &v, unsigned numDefined);
void Write_UInt64DefVector_type(const CUInt64DefVector &v, Byte type);
HRESULT EncodeStream(
DECL_EXTERNAL_CODECS_LOC_VARS
CEncoder &encoder, const CByteBuffer &data,
CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders);
void WriteHeader(
const CArchiveDatabaseOut &db,
// const CHeaderOptions &headerOptions,
UInt64 &headerOffset);
bool _countMode;
bool _writeToStream;
bool _useAlign;
#ifdef Z7_7Z_VOL
bool _endMarker;
#endif
// UInt32 _crc;
size_t _countSize;
CWriteBufferLoc _outByte2;
COutBuffer _outByte;
UInt64 _signatureHeaderPos;
CMyComPtr<IOutStream> Stream;
#ifdef Z7_7Z_VOL
HRESULT WriteFinishSignature();
HRESULT WriteFinishHeader(const CFinishHeader &h);
#endif
HRESULT WriteStartHeader(const CStartHeader &h);
public:
CMyComPtr<ISequentialOutStream> SeqStream;
// COutArchive();
HRESULT Create_and_WriteStartPrefix(ISequentialOutStream *stream /* , bool endMarker */);
void Close();
HRESULT WriteDatabase(
DECL_EXTERNAL_CODECS_LOC_VARS
const CArchiveDatabaseOut &db,
const CCompressionMethodMode *options,
const CHeaderOptions &headerOptions);
#ifdef Z7_7Z_VOL
static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false);
static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false);
#endif
};
}}
#endif
@@ -0,0 +1,182 @@
// 7zProperties.cpp
#include "StdAfx.h"
#include "7zHandler.h"
#include "7zProperties.h"
namespace NArchive {
namespace N7z {
struct CPropMap
{
Byte FilePropID;
// CStatProp StatProp;
VARTYPE vt;
UInt32 StatPropID;
};
// #define STAT_PROP(name, id, vt) { name, id, vt }
#define STAT_PROP(name, id, vt) vt, id
#define STAT_PROP2(id, vt) STAT_PROP(NULL, id, vt)
#define k_7z_id_Encrypted 97
#define k_7z_id_Method 98
#define k_7z_id_Block 99
static const CPropMap kPropMap[] =
{
{ NID::kName, STAT_PROP2(kpidPath, VT_BSTR) },
{ NID::kSize, STAT_PROP2(kpidSize, VT_UI8) },
{ NID::kPackInfo, STAT_PROP2(kpidPackSize, VT_UI8) },
#ifdef Z7_7Z_SHOW_PACK_STREAMS_SIZES
#define k_7z_id_PackedSize0 100
{ k_7z_id_PackedSize0 + 0, STAT_PROP("Pack0", kpidPackedSize0, VT_UI8) },
{ k_7z_id_PackedSize0 + 1, STAT_PROP("Pack1", kpidPackedSize1, VT_UI8) },
{ k_7z_id_PackedSize0 + 2, STAT_PROP("Pack2", kpidPackedSize2, VT_UI8) },
{ k_7z_id_PackedSize0 + 3, STAT_PROP("Pack3", kpidPackedSize3, VT_UI8) },
{ k_7z_id_PackedSize0 + 4, STAT_PROP("Pack4", kpidPackedSize4, VT_UI8) },
#endif
{ NID::kCTime, STAT_PROP2(kpidCTime, VT_FILETIME) },
{ NID::kMTime, STAT_PROP2(kpidMTime, VT_FILETIME) },
{ NID::kATime, STAT_PROP2(kpidATime, VT_FILETIME) },
{ NID::kWinAttrib, STAT_PROP2(kpidAttrib, VT_UI4) },
{ NID::kStartPos, STAT_PROP2(kpidPosition, VT_UI8) },
{ NID::kCRC, STAT_PROP2(kpidCRC, VT_UI4) },
// { NID::kIsAux, STAT_PROP2(kpidIsAux, VT_BOOL) },
{ NID::kAnti, STAT_PROP2(kpidIsAnti, VT_BOOL) }
#ifndef Z7_SFX
, { k_7z_id_Encrypted, STAT_PROP2(kpidEncrypted, VT_BOOL) }
, { k_7z_id_Method, STAT_PROP2(kpidMethod, VT_BSTR) }
, { k_7z_id_Block, STAT_PROP2(kpidBlock, VT_UI4) }
#endif
};
static void CopyOneItem(CRecordVector<UInt64> &src,
CRecordVector<UInt64> &dest, const UInt32 item)
{
FOR_VECTOR (i, src)
if (src[i] == item)
{
dest.Add(item);
src.Delete(i);
return;
}
}
static void RemoveOneItem(CRecordVector<UInt64> &src, const UInt32 item)
{
FOR_VECTOR (i, src)
if (src[i] == item)
{
src.Delete(i);
return;
}
}
static void InsertToHead(CRecordVector<UInt64> &dest, const UInt32 item)
{
FOR_VECTOR (i, dest)
if (dest[i] == item)
{
dest.Delete(i);
break;
}
dest.Insert(0, item);
}
#define COPY_ONE_ITEM(id) CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::id);
void CHandler::FillPopIDs()
{
_fileInfoPopIDs.Clear();
#ifdef Z7_7Z_VOL
if (_volumes.Size() < 1)
return;
const CVolume &volume = _volumes.Front();
const CArchiveDatabaseEx &_db = volume.Database;
#endif
CRecordVector<UInt64> fileInfoPopIDs = _db.ArcInfo.FileInfoPopIDs;
RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream);
RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile);
/*
RemoveOneItem(fileInfoPopIDs, NID::kParent);
RemoveOneItem(fileInfoPopIDs, NID::kNtSecure);
*/
COPY_ONE_ITEM(kName)
COPY_ONE_ITEM(kAnti)
COPY_ONE_ITEM(kSize)
COPY_ONE_ITEM(kPackInfo)
COPY_ONE_ITEM(kCTime)
COPY_ONE_ITEM(kMTime)
COPY_ONE_ITEM(kATime)
COPY_ONE_ITEM(kWinAttrib)
COPY_ONE_ITEM(kCRC)
COPY_ONE_ITEM(kComment)
_fileInfoPopIDs += fileInfoPopIDs;
#ifndef Z7_SFX
_fileInfoPopIDs.Add(k_7z_id_Encrypted);
_fileInfoPopIDs.Add(k_7z_id_Method);
_fileInfoPopIDs.Add(k_7z_id_Block);
#endif
#ifdef Z7_7Z_SHOW_PACK_STREAMS_SIZES
for (unsigned i = 0; i < 5; i++)
_fileInfoPopIDs.Add(k_7z_id_PackedSize0 + i);
#endif
#ifndef Z7_SFX
InsertToHead(_fileInfoPopIDs, NID::kMTime);
InsertToHead(_fileInfoPopIDs, NID::kPackInfo);
InsertToHead(_fileInfoPopIDs, NID::kSize);
InsertToHead(_fileInfoPopIDs, NID::kName);
#endif
}
Z7_COM7F_IMF(CHandler::GetNumberOfProperties(UInt32 *numProps))
{
*numProps = _fileInfoPopIDs.Size();
return S_OK;
}
Z7_COM7F_IMF(CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType))
{
if (index >= _fileInfoPopIDs.Size())
return E_INVALIDARG;
const UInt64 id = _fileInfoPopIDs[index];
for (unsigned i = 0; i < Z7_ARRAY_SIZE(kPropMap); i++)
{
const CPropMap &pr = kPropMap[i];
if (pr.FilePropID == id)
{
*propID = pr.StatPropID;
*varType = pr.vt;
/*
const CStatProp &st = pr.StatProp;
*propID = st.PropID;
*varType = st.vt;
*/
/*
if (st.lpwstrName)
*name = ::SysAllocString(st.lpwstrName);
else
*/
*name = NULL;
return S_OK;
}
}
return E_INVALIDARG;
}
}}
@@ -0,0 +1,26 @@
// 7zProperties.h
#ifndef ZIP7_INC_7Z_PROPERTIES_H
#define ZIP7_INC_7Z_PROPERTIES_H
#include "../../PropID.h"
namespace NArchive {
namespace N7z {
// #define Z7_7Z_SHOW_PACK_STREAMS_SIZES // for debug
#ifdef Z7_7Z_SHOW_PACK_STREAMS_SIZES
enum
{
kpidPackedSize0 = kpidUserDefined,
kpidPackedSize1,
kpidPackedSize2,
kpidPackedSize3,
kpidPackedSize4
};
#endif
}}
#endif
@@ -0,0 +1,27 @@
// 7zRegister.cpp
#include "StdAfx.h"
#include "../../Common/RegisterArc.h"
#include "7zHandler.h"
namespace NArchive {
namespace N7z {
static Byte k_Signature_Dec[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C};
REGISTER_ARC_IO_DECREMENT_SIG(
"7z", "7z", NULL, 7,
k_Signature_Dec,
0,
NArcInfoFlags::kFindSignature
| NArcInfoFlags::kCTime
| NArcInfoFlags::kATime
| NArcInfoFlags::kMTime
| NArcInfoFlags::kMTime_Default
, TIME_PREC_TO_ARC_FLAGS_MASK(NFileTimeType::kWindows)
| TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT(NFileTimeType::kWindows)
, NULL)
}}
@@ -0,0 +1,31 @@
// 7zSpecStream.cpp
#include "StdAfx.h"
#include "7zSpecStream.h"
/*
Z7_COM7F_IMF(CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 *processedSize))
{
UInt32 realProcessedSize;
const HRESULT result = _stream->Read(data, size, &realProcessedSize);
_size += realProcessedSize;
if (processedSize)
*processedSize = realProcessedSize;
return result;
}
Z7_COM7F_IMF(CSequentialInStreamSizeCount2::GetSubStreamSize(UInt64 subStream, UInt64 *value))
{
if (!_getSubStreamSize)
return E_NOTIMPL;
return _getSubStreamSize->GetSubStreamSize(subStream, value);
}
Z7_COM7F_IMF(CSequentialInStreamSizeCount2::GetNextInSubStream(UInt64 *streamIndexRes, ISequentialInStream **stream))
{
if (!_compressGetSubStreamSize)
return E_NOTIMPL;
return _compressGetSubStreamSize->GetNextInSubStream(streamIndexRes, stream);
}
*/
@@ -0,0 +1,49 @@
// 7zSpecStream.h
#ifndef ZIP7_INC_7Z_SPEC_STREAM_H
#define ZIP7_INC_7Z_SPEC_STREAM_H
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
/*
#define Z7_COM_QI_ENTRY_AG_2(i, sub0, sub) else if (iid == IID_ ## i) \
{ if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \
{ i *ti = this; *outObject = ti; } }
class CSequentialInStreamSizeCount2 Z7_final:
public ISequentialInStream,
public ICompressGetSubStreamSize,
public ICompressInSubStreams,
public CMyUnknownImp
{
Z7_COM_QI_BEGIN2(ISequentialInStream)
Z7_COM_QI_ENTRY(ICompressGetSubStreamSize)
Z7_COM_QI_ENTRY_AG_2(ISequentialInStream, _stream, _compressGetSubStreamSize)
Z7_COM_QI_END
Z7_COM_ADDREF_RELEASE
Z7_IFACE_COM7_IMP(ISequentialInStream)
Z7_IFACE_COM7_IMP(ICompressGetSubStreamSize)
Z7_IFACE_COM7_IMP(ICompressInSubStreams)
CMyComPtr<ISequentialInStream> _stream;
CMyComPtr<ICompressGetSubStreamSize> _getSubStreamSize;
CMyComPtr<ICompressInSubStreams> _compressGetSubStreamSize;
UInt64 _size;
public:
void Init(ISequentialInStream *stream)
{
_size = 0;
_getSubStreamSize.Release();
_compressGetSubStreamSize.Release();
_stream = stream;
_stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);
_stream.QueryInterface(IID_ICompressInSubStreams, &_compressGetSubStreamSize);
}
UInt64 GetSize() const { return _size; }
};
*/
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,167 @@
// 7zUpdate.h
#ifndef ZIP7_INC_7Z_UPDATE_H
#define ZIP7_INC_7Z_UPDATE_H
#include "../IArchive.h"
// #include "../../Common/UniqBlocks.h"
#include "7zCompressionMode.h"
#include "7zIn.h"
namespace NArchive {
namespace N7z {
/*
struct CTreeFolder
{
UString Name;
int Parent;
CIntVector SubFolders;
int UpdateItemIndex;
int SortIndex;
int SortIndexEnd;
CTreeFolder(): UpdateItemIndex(-1) {}
};
*/
struct CUpdateItem
{
int IndexInArchive;
unsigned IndexInClient;
UInt64 CTime;
UInt64 ATime;
UInt64 MTime;
UInt64 Size;
UString Name;
/*
bool IsAltStream;
int ParentFolderIndex;
int TreeFolderIndex;
*/
// that code is not used in 9.26
// int ParentSortIndex;
// int ParentSortIndexEnd;
UInt32 Attrib;
bool NewData;
bool NewProps;
bool IsAnti;
bool IsDir;
bool AttribDefined;
bool CTimeDefined;
bool ATimeDefined;
bool MTimeDefined;
// bool ATime_WasReadByAnalysis;
// int SecureIndex; // 0 means (no_security)
bool HasStream() const { return !IsDir && !IsAnti && Size != 0; }
// bool HasStream() const { return !IsDir && !IsAnti /* && Size != 0 */; } // for test purposes
CUpdateItem():
// ParentSortIndex(-1),
// IsAltStream(false),
IsAnti(false),
IsDir(false),
AttribDefined(false),
CTimeDefined(false),
ATimeDefined(false),
MTimeDefined(false)
// , ATime_WasReadByAnalysis(false)
// SecureIndex(0)
{}
void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); }
// unsigned GetExtensionPos() const;
// UString GetExtension() const;
};
struct CUpdateOptions
{
const CCompressionMethodMode *Method;
const CCompressionMethodMode *HeaderMethod;
bool UseFilters; // use additional filters for some files
bool MaxFilter; // use BCJ2 filter instead of BCJ
int AnalysisLevel;
UInt64 NumSolidFiles;
UInt64 NumSolidBytes;
bool SolidExtension;
bool UseTypeSorting;
bool RemoveSfxBlock;
bool MultiThreadMixer;
bool Need_CTime;
bool Need_ATime;
bool Need_MTime;
bool Need_Attrib;
// bool Need_Crc;
CHeaderOptions HeaderOptions;
CUIntVector DisabledFilterIDs;
void Add_DisabledFilter_for_id(UInt32 id,
const CUIntVector &enabledFilters)
{
if (enabledFilters.FindInSorted(id) < 0)
DisabledFilterIDs.AddToUniqueSorted(id);
}
void SetFilterSupporting_ver_enabled_disabled(
UInt32 compatVer,
const CUIntVector &enabledFilters,
const CUIntVector &disabledFilters)
{
DisabledFilterIDs = disabledFilters;
if (compatVer < 2300) Add_DisabledFilter_for_id(k_ARM64, enabledFilters);
if (compatVer < 2402) Add_DisabledFilter_for_id(k_RISCV, enabledFilters);
}
CUpdateOptions():
Method(NULL),
HeaderMethod(NULL),
UseFilters(false),
MaxFilter(false),
AnalysisLevel(-1),
NumSolidFiles((UInt64)(Int64)(-1)),
NumSolidBytes((UInt64)(Int64)(-1)),
SolidExtension(false),
UseTypeSorting(true),
RemoveSfxBlock(false),
MultiThreadMixer(true),
Need_CTime(false),
Need_ATime(false),
Need_MTime(false),
Need_Attrib(false)
// , Need_Crc(true)
{
DisabledFilterIDs.Add(k_RISCV);
}
};
HRESULT Update(
DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream,
const CDbEx *db,
CObjectVector<CUpdateItem> &updateItems,
// const CObjectVector<CTreeFolder> &treeFolders, // treeFolders[0] is root
// const CUniqBlocks &secureBlocks,
ISequentialOutStream *seqOutStream,
IArchiveUpdateCallback *updateCallback,
const CUpdateOptions &options);
}}
#endif
@@ -0,0 +1,3 @@
// StdAfx.cpp
#include "StdAfx.h"
@@ -0,0 +1,11 @@
// StdAfx.h
#ifndef ZIP7_INC_STDAFX_H
#define ZIP7_INC_STDAFX_H
#if defined(_MSC_VER) && _MSC_VER >= 1800
#pragma warning(disable : 4464) // relative include path contains '..'
#endif
#include "../../../Common/Common.h"
#endif
@@ -0,0 +1,81 @@
PROG = 7z.dll
DEF_FILE = ../Archive.def
CFLAGS = $(CFLAGS) \
-DZ7_EXTERNAL_CODECS \
AR_OBJS = \
$O\ArchiveExports.obj \
$O\DllExports2.obj \
7Z_OBJS = \
$O\7zCompressionMode.obj \
$O\7zDecode.obj \
$O\7zEncode.obj \
$O\7zExtract.obj \
$O\7zFolderInStream.obj \
$O\7zHandler.obj \
$O\7zHandlerOut.obj \
$O\7zHeader.obj \
$O\7zIn.obj \
$O\7zOut.obj \
$O\7zProperties.obj \
$O\7zSpecStream.obj \
$O\7zUpdate.obj \
$O\7zRegister.obj \
COMMON_OBJS = \
$O\CRC.obj \
$O\IntToString.obj \
$O\NewHandler.obj \
$O\MyString.obj \
$O\StringConvert.obj \
$O\StringToInt.obj \
$O\MyVector.obj \
$O\Wildcard.obj \
WIN_OBJS = \
$O\FileDir.obj \
$O\FileFind.obj \
$O\FileIO.obj \
$O\FileName.obj \
$O\PropVariant.obj \
$O\Synchronization.obj \
$O\System.obj \
7ZIP_COMMON_OBJS = \
$O\CreateCoder.obj \
$O\InOutTempBuffer.obj \
$O\FilterCoder.obj \
$O\LimitedStreams.obj \
$O\LockedStream.obj \
$O\MethodId.obj \
$O\MethodProps.obj \
$O\OutBuffer.obj \
$O\ProgressUtils.obj \
$O\PropId.obj \
$O\StreamBinder.obj \
$O\StreamObjects.obj \
$O\StreamUtils.obj \
$O\VirtThread.obj \
COMPRESS_OBJS = \
$O\CopyCoder.obj \
$O\CodecExports.obj \
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
$O\HandlerOut.obj \
$O\InStreamWithCRC.obj \
$O\ItemNameUtils.obj \
$O\MultiStream.obj \
$O\OutStreamWithCRC.obj \
$O\ParseProperties.obj \
C_OBJS = \
$O\Alloc.obj \
$O\CpuArch.obj \
$O\Threads.obj \
!include "../../Crc.mak"
!include "../../7zip.mak"
@@ -0,0 +1,11 @@
#include "../../MyVersionInfo.rc"
MY_VERSION_INFO_DLL("7z Plugin", "7z")
0 ICON "../Icons/7z.ico"
STRINGTABLE
BEGIN
100 "7z:0"
END