Move placement of lzma.

This commit is contained in:
2023-09-24 02:41:01 +01:00
parent fb79a7ddf6
commit 7cc2d1c72e
687 changed files with 2 additions and 2 deletions

240
3rdparty/lzma/CPP/7zip/7zip.mak vendored Normal file
View File

@@ -0,0 +1,240 @@
OBJS = \
$O\StdAfx.obj \
$(CURRENT_OBJS) \
$(COMMON_OBJS) \
$(WIN_OBJS) \
$(WIN_CTRL_OBJS) \
$(7ZIP_COMMON_OBJS) \
$(AR_OBJS) \
$(AR_COMMON_OBJS) \
$(UI_COMMON_OBJS) \
$(AGENT_OBJS) \
$(CONSOLE_OBJS) \
$(EXPLORER_OBJS) \
$(FM_OBJS) \
$(GUI_OBJS) \
$(7Z_OBJS) \
$(CAB_OBJS) \
$(CHM_OBJS) \
$(COM_OBJS) \
$(ISO_OBJS) \
$(NSIS_OBJS) \
$(RAR_OBJS) \
$(TAR_OBJS) \
$(UDF_OBJS) \
$(WIM_OBJS) \
$(ZIP_OBJS) \
$(COMPRESS_OBJS) \
$(CRYPTO_OBJS) \
$(C_OBJS) \
$(ASM_OBJS) \
$O\resource.res \
!include "../../../Build.mak"
# MAK_SINGLE_FILE = 1
!IFDEF MAK_SINGLE_FILE
!IFDEF CURRENT_OBJS
$(CURRENT_OBJS): ./$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF COMMON_OBJS
$(COMMON_OBJS): ../../../Common/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF WIN_OBJS
$(WIN_OBJS): ../../../Windows/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF WIN_CTRL_OBJS
$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF 7ZIP_COMMON_OBJS
$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF AR_OBJS
$(AR_OBJS): ../../Archive/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF AR_COMMON_OBJS
$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF 7Z_OBJS
$(7Z_OBJS): ../../Archive/7z/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF CAB_OBJS
$(CAB_OBJS): ../../Archive/Cab/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF CHM_OBJS
$(CHM_OBJS): ../../Archive/Chm/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF COM_OBJS
$(COM_OBJS): ../../Archive/Com/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF ISO_OBJS
$(ISO_OBJS): ../../Archive/Iso/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF NSIS_OBJS
$(NSIS_OBJS): ../../Archive/Nsis/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF RAR_OBJS
$(RAR_OBJS): ../../Archive/Rar/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF TAR_OBJS
$(TAR_OBJS): ../../Archive/Tar/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF UDF_OBJS
$(UDF_OBJS): ../../Archive/Udf/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF WIM_OBJS
$(WIM_OBJS): ../../Archive/Wim/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF ZIP_OBJS
$(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF COMPRESS_OBJS
$(COMPRESS_OBJS): ../../Compress/$(*B).cpp
$(COMPL_O2)
!ENDIF
!IFDEF CRYPTO_OBJS
$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp
$(COMPL_O2)
!ENDIF
!IFDEF UI_COMMON_OBJS
$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF AGENT_OBJS
$(AGENT_OBJS): ../../UI/Agent/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF CONSOLE_OBJS
$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF EXPLORER_OBJS
$(EXPLORER_OBJS): ../../UI/Explorer/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF FM_OBJS
$(FM_OBJS): ../../UI/FileManager/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF GUI_OBJS
$(GUI_OBJS): ../../UI/GUI/$(*B).cpp
$(COMPL)
!ENDIF
!IFDEF C_OBJS
$(C_OBJS): ../../../../C/$(*B).c
$(COMPL_O2)
!ENDIF
!ELSE
{.}.cpp{$O}.obj::
$(COMPLB)
{../../../Common}.cpp{$O}.obj::
$(COMPLB)
{../../../Windows}.cpp{$O}.obj::
$(COMPLB)
{../../../Windows/Control}.cpp{$O}.obj::
$(COMPLB)
{../../Common}.cpp{$O}.obj::
$(COMPLB)
{../../UI/Common}.cpp{$O}.obj::
$(COMPLB)
{../../UI/Agent}.cpp{$O}.obj::
$(COMPLB)
{../../UI/Console}.cpp{$O}.obj::
$(COMPLB)
{../../UI/Explorer}.cpp{$O}.obj::
$(COMPLB)
{../../UI/FileManager}.cpp{$O}.obj::
$(COMPLB)
{../../UI/GUI}.cpp{$O}.obj::
$(COMPLB)
{../../Archive}.cpp{$O}.obj::
$(COMPLB)
{../../Archive/Common}.cpp{$O}.obj::
$(COMPLB)
{../../Archive/7z}.cpp{$O}.obj::
$(COMPLB)
{../../Archive/Cab}.cpp{$O}.obj::
$(COMPLB)
{../../Archive/Chm}.cpp{$O}.obj::
$(COMPLB)
{../../Archive/Com}.cpp{$O}.obj::
$(COMPLB)
{../../Archive/Iso}.cpp{$O}.obj::
$(COMPLB)
{../../Archive/Nsis}.cpp{$O}.obj::
$(COMPLB)
{../../Archive/Rar}.cpp{$O}.obj::
$(COMPLB)
{../../Archive/Tar}.cpp{$O}.obj::
$(COMPLB)
{../../Archive/Udf}.cpp{$O}.obj::
$(COMPLB)
{../../Archive/Wim}.cpp{$O}.obj::
$(COMPLB)
{../../Archive/Zip}.cpp{$O}.obj::
$(COMPLB)
{../../Compress}.cpp{$O}.obj::
$(COMPLB_O2)
{../../Crypto}.cpp{$O}.obj::
$(COMPLB_O2)
{../../../../C}.c{$O}.obj::
$(CCOMPLB)
!ENDIF
!include "Asm.mak"

1195
3rdparty/lzma/CPP/7zip/7zip_gcc.mak vendored Normal file

File diff suppressed because it is too large Load Diff

10
3rdparty/lzma/CPP/7zip/Aes.mak vendored Normal file
View File

@@ -0,0 +1,10 @@
C_OBJS = $(C_OBJS) \
$O\Aes.obj
!IF defined(USE_C_AES) || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "arm64"
C_OBJS = $(C_OBJS) \
$O\AesOpt.obj
!ELSEIF "$(PLATFORM)" != "ia64" && "$(PLATFORM)" != "mips" && "$(PLATFORM)" != "arm" && "$(PLATFORM)" != "arm64"
ASM_OBJS = $(ASM_OBJS) \
$O\AesOpt.obj
!ENDIF

View File

@@ -0,0 +1,3 @@
// CompressionMethod.cpp
#include "StdAfx.h"

View File

@@ -0,0 +1,78 @@
// 7zCompressionMode.h
#ifndef __7Z_COMPRESSION_MODE_H
#define __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;
CMethodFull(): CodecIndex(-1) {}
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;
#ifndef _7ZIP_ST
UInt32 NumThreads;
bool MultiThreadMixer;
#endif
bool PasswordIsDefined;
UString Password; // _Wipe
bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }
CCompressionMethodMode():
DefaultMethod_was_Inserted(false)
, Filter_was_Inserted(false)
#ifndef _7ZIP_ST
, NumThreads(1)
, MultiThreadMixer(true)
#endif
, PasswordIsDefined(false)
{}
~CCompressionMethodMode() { Password.Wipe_and_Empty(); }
};
}}
#endif

View File

@@ -0,0 +1,583 @@
// 7zDecode.cpp
#include "StdAfx.h"
#include "../../Common/LimitedStreams.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamObjects.h"
#include "7zDecode.h"
namespace NArchive {
namespace N7z {
class CDecProgress:
public ICompressProgressInfo,
public CMyUnknownImp
{
CMyComPtr<ICompressProgressInfo> _progress;
public:
CDecProgress(ICompressProgressInfo *progress): _progress(progress) {}
MY_UNKNOWN_IMP1(ICompressProgressInfo)
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
};
STDMETHODIMP 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),
_useMixerMT(useMixerMT)
{}
struct CLockedInStream:
public IUnknown,
public CMyUnknownImp
{
CMyComPtr<IInStream> Stream;
UInt64 Pos;
MY_UNKNOWN_IMP
#ifdef USE_MIXER_MT
NWindows::NSynchronization::CCriticalSection CriticalSection;
#endif
};
#ifdef USE_MIXER_MT
class CLockedSequentialInStreamMT:
public ISequentialInStream,
public CMyUnknownImp
{
CLockedInStream *_glob;
UInt64 _pos;
CMyComPtr<IUnknown> _globRef;
public:
void Init(CLockedInStream *lockedInStream, UInt64 startPos)
{
_globRef = lockedInStream;
_glob = lockedInStream;
_pos = startPos;
}
MY_UNKNOWN_IMP1(ISequentialInStream)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
};
STDMETHODIMP CLockedSequentialInStreamMT::Read(void *data, UInt32 size, UInt32 *processedSize)
{
NWindows::NSynchronization::CCriticalSectionLock lock(_glob->CriticalSection);
if (_pos != _glob->Pos)
{
RINOK(_glob->Stream->Seek((Int64)_pos, STREAM_SEEK_SET, NULL));
_glob->Pos = _pos;
}
UInt32 realProcessedSize = 0;
HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
_pos += realProcessedSize;
_glob->Pos = _pos;
if (processedSize)
*processedSize = realProcessedSize;
return res;
}
#endif
#ifdef USE_MIXER_ST
class CLockedSequentialInStreamST:
public ISequentialInStream,
public CMyUnknownImp
{
CLockedInStream *_glob;
UInt64 _pos;
CMyComPtr<IUnknown> _globRef;
public:
void Init(CLockedInStream *lockedInStream, UInt64 startPos)
{
_globRef = lockedInStream;
_glob = lockedInStream;
_pos = startPos;
}
MY_UNKNOWN_IMP1(ISequentialInStream)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
};
STDMETHODIMP CLockedSequentialInStreamST::Read(void *data, UInt32 size, UInt32 *processedSize)
{
if (_pos != _glob->Pos)
{
RINOK(_glob->Stream->Seek((Int64)_pos, STREAM_SEEK_SET, NULL));
_glob->Pos = _pos;
}
UInt32 realProcessedSize = 0;
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
_7Z_DECODER_CRYPRO_VARS_DECL
#if !defined(_7ZIP_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 _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 _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 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(_7ZIP_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();
#if !defined(_7ZIP_ST)
if (!mt_wasUsed)
{
if (mtMode)
{
CMyComPtr<ICompressSetCoderMt> setCoderMt;
decoder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);
if (setCoderMt)
{
mt_wasUsed = true;
RINOK(setCoderMt->SetNumberOfThreads(numThreads));
}
}
// if (memUsage != 0)
{
CMyComPtr<ICompressSetMemLimit> setMemLimit;
decoder->QueryInterface(IID_ICompressSetMemLimit, (void **)&setMemLimit);
if (setMemLimit)
{
mt_wasUsed = true;
RINOK(setMemLimit->SetMemLimit(memUsage));
}
}
}
#endif
{
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
decoder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);
if (setDecoderProperties)
{
const CByteBuffer &props = coderInfo.Props;
const UInt32 size32 = (UInt32)props.Size();
if (props.Size() != size32)
return E_NOTIMPL;
HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, size32);
if (res == E_INVALIDARG)
res = E_NOTIMPL;
RINOK(res);
}
}
#ifndef _NO_CRYPTO
{
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
decoder->QueryInterface(IID_ICryptoSetPassword, (void **)&cryptoSetPassword);
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);
for (size_t k = 0; k < len; k++)
{
wchar_t c = passwordBSTR[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;
{
CMyComPtr<ICompressSetFinishMode> setFinishMode;
decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode);
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;
CLockedInStream *lockedInStreamSpec = new CLockedInStream;
CMyComPtr<IUnknown> lockedInStream = lockedInStreamSpec;
#ifdef USE_MIXER_MT
#ifdef USE_MIXER_ST
bool needMtLock = _useMixerMT;
#endif
#endif
if (folderInfo.PackStreams.Size() > 1)
{
// lockedInStream.Pos = (UInt64)(Int64)-1;
// RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &lockedInStream.Pos));
RINOK(inStream->Seek((Int64)(startPos + packPositions[0]), STREAM_SEEK_SET, &lockedInStreamSpec->Pos));
lockedInStreamSpec->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->Seek((Int64)packPos, STREAM_SEEK_SET, NULL));
packStream = inStream;
}
else
{
#ifdef USE_MIXER_MT
#ifdef USE_MIXER_ST
if (needMtLock)
#endif
{
CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT;
packStream = lockedStreamImpSpec;
lockedStreamImpSpec->Init(lockedInStreamSpec, packPos);
}
#ifdef USE_MIXER_ST
else
#endif
#endif
{
#ifdef USE_MIXER_ST
CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST;
packStream = lockedStreamImpSpec;
lockedStreamImpSpec->Init(lockedInStreamSpec, 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
}
}}

View File

@@ -0,0 +1,70 @@
// 7zDecode.h
#ifndef __7Z_DECODE_H
#define __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;
CBindInfoEx _bindInfoPrev;
bool _useMixerMT;
#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
_7Z_DECODER_CRYPRO_VARS_DECL
#if !defined(_7ZIP_ST)
, bool mtMode, UInt32 numThreads, UInt64 memUsage
#endif
);
};
}}
#endif

View File

@@ -0,0 +1,679 @@
// 7zEncode.cpp
#include "StdAfx.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)
{
CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties);
if (setCoderProperties)
return props.SetCoderProps(setCoderProperties, dataSizeReduce);
return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK;
}
void CMtEncMultiProgress::Init(ICompressProgressInfo *progress)
{
_progress = progress;
OutSize = 0;
}
STDMETHODIMP CMtEncMultiProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)
{
UInt64 outSize2;
{
#ifndef _7ZIP_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.NumStreams != methodFull.NumStreams)
return E_FAIL;
if (!cod.Coder && !cod.Coder2)
return E_FAIL;
CMyComPtr<IUnknown> encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2;
#ifndef _7ZIP_ST
{
CMyComPtr<ICompressSetCoderMt> setCoderMt;
encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
if (setCoderMt)
{
RINOK(setCoderMt->SetNumberOfThreads(_options.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 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;
}
class CSequentialOutTempBufferImp2:
public ISequentialOutStream,
public CMyUnknownImp
{
CInOutTempBuffer *_buf;
public:
CMtEncMultiProgress *_mtProgresSpec;
CSequentialOutTempBufferImp2(): _buf(0), _mtProgresSpec(NULL) {}
void Init(CInOutTempBuffer *buffer) { _buf = buffer; }
MY_UNKNOWN_IMP1(ISequentialOutStream)
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
};
STDMETHODIMP CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed)
{
HRESULT res = _buf->Write_HRESULT(data, size);
if (res != S_OK)
{
if (processed)
*processed = 0;
return res;
}
if (processed)
*processed = size;
if (_mtProgresSpec)
_mtProgresSpec->AddOutSize(size);
return S_OK;
}
class CSequentialOutMtNotify:
public ISequentialOutStream,
public CMyUnknownImp
{
public:
CMyComPtr<ISequentialOutStream> _stream;
CMtEncMultiProgress *_mtProgresSpec;
CSequentialOutMtNotify(): _mtProgresSpec(NULL) {}
MY_UNKNOWN_IMP1(ISequentialOutStream)
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
};
STDMETHODIMP CSequentialOutMtNotify::Write(const void *data, UInt32 size, UInt32 *processed)
{
UInt32 realProcessed = 0;
HRESULT res = _stream->Write(data, size, &realProcessed);
if (processed)
*processed = realProcessed;
if (_mtProgresSpec)
_mtProgresSpec->AddOutSize(size);
return res;
}
HRESULT CEncoder::Encode(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream,
// const UInt64 *inStreamSize,
const UInt64 *inSizeForReduce,
CFolder &folderItem,
CRecordVector<UInt64> &coderUnpackSizes,
UInt64 &unpackSize,
ISequentialOutStream *outStream,
CRecordVector<UInt64> &packSizes,
ICompressProgressInfo *compressProgress)
{
RINOK(EncoderConstr());
if (!_mixerRef)
{
RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));
}
RINOK(_mixer->ReInit2());
CMtEncMultiProgress *mtProgressSpec = NULL;
CMyComPtr<ICompressProgressInfo> mtProgress;
CSequentialOutMtNotify *mtOutStreamNotifySpec = NULL;
CMyComPtr<ISequentialOutStream> mtOutStreamNotify;
CObjectVector<CInOutTempBuffer> inOutTempBuffers;
CObjectVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs;
CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
unsigned numMethods = _bindInfo.Coders.Size();
unsigned i;
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
{
CInOutTempBuffer &iotb = inOutTempBuffers.AddNew();
iotb.Create();
iotb.InitWriting();
}
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
{
CSequentialOutTempBufferImp2 *tempBufferSpec = new CSequentialOutTempBufferImp2;
CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
tempBufferSpec->Init(&inOutTempBuffers[i - 1]);
tempBuffers.Add(tempBuffer);
tempBufferSpecs.Add(tempBufferSpec);
}
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;
CRecordVector<ISequentialOutStream *> outStreamPointers;
SetFolder(folderItem);
for (i = 0; i < numMethods; i++)
{
IUnknown *coder = _mixer->GetCoder(i).GetUnknown();
CMyComPtr<ICryptoResetInitVector> resetInitVector;
coder->QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
if (resetInitVector)
{
resetInitVector->ResetInitVector();
}
{
CMyComPtr<ICompressSetCoderPropertiesOpt> optProps;
coder->QueryInterface(IID_ICompressSetCoderPropertiesOpt, (void **)&optProps);
if (optProps)
{
PROPID propID = NCoderPropID::kExpectedDataSize;
NWindows::NCOM::CPropVariant prop = (UInt64)unpackSize;
RINOK(optProps->SetCoderPropertiesOpt(&propID, &prop, 1));
}
}
CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
CByteBuffer &props = folderItem.Coders[numMethods - 1 - i].Props;
if (writeCoderProperties)
{
CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;
CMyComPtr<ISequentialOutStream> dynOutStream(outStreamSpec);
outStreamSpec->Init();
RINOK(writeCoderProperties->WriteCoderProperties(dynOutStream));
outStreamSpec->CopyToBuffer(props);
}
else
props.Free();
}
_mixer->SelectMainCoder(false);
UInt32 mainCoder = _mixer->MainCoderIndex;
bool useMtProgress = false;
if (!_mixer->Is_PackSize_Correct_for_Coder(mainCoder))
{
#ifdef _7ZIP_ST
if (!_mixer->IsThere_ExternalCoder_in_PackTree(mainCoder))
#endif
useMtProgress = true;
}
if (useMtProgress)
{
mtProgressSpec = new CMtEncMultiProgress;
mtProgress = mtProgressSpec;
mtProgressSpec->Init(compressProgress);
mtOutStreamNotifySpec = new CSequentialOutMtNotify;
mtOutStreamNotify = mtOutStreamNotifySpec;
mtOutStreamNotifySpec->_stream = outStream;
mtOutStreamNotifySpec->_mtProgresSpec = mtProgressSpec;
FOR_VECTOR(t, tempBufferSpecs)
{
tempBufferSpecs[t]->_mtProgresSpec = mtProgressSpec;
}
}
if (_bindInfo.PackStreams.Size() != 0)
{
outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
outStreamSizeCount = outStreamSizeCountSpec;
outStreamSizeCountSpec->SetStream(mtOutStreamNotify ? (ISequentialOutStream *)mtOutStreamNotify : 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.Front(),
mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress, dataAfterEnd_Error));
if (_bindInfo.PackStreams.Size() != 0)
packSizes.Add(outStreamSizeCountSpec->GetSize());
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
{
CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];
RINOK(inOutTempBuffer.WriteToStream(outStream));
packSizes.Add(inOutTempBuffer.GetDataSize());
}
unpackSize = 0;
for (i = 0; i < _bindInfo.Coders.Size(); i++)
{
int bond = _bindInfo.FindBond_for_UnpackStream(_DestOut_to_SrcIn[i]);
UInt64 streamSize;
if (bond < 0)
{
streamSize = inStreamSizeCountSpec->GetSize();
unpackSize = streamSize;
}
else
streamSize = _mixer->GetBondStreamSize((unsigned)bond);
coderUnpackSizes.Add(streamSize);
}
return S_OK;
}
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;
UInt32 outIndex = _bindInfo.Coder_to_Stream[ci];
int bond = _bindInfo.FindBond_for_PackStream(outIndex);
if (bond >= 0)
{
ci = _bindInfo.Bonds[(unsigned)bond].UnpackIndex;
continue;
}
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() {}
}}

View File

@@ -0,0 +1,92 @@
// 7zEncode.h
#ifndef __7Z_ENCODE_H
#define __7Z_ENCODE_H
#include "7zCompressionMode.h"
#include "../Common/CoderMixer2.h"
#include "7zItem.h"
namespace NArchive {
namespace N7z {
class CMtEncMultiProgress:
public ICompressProgressInfo,
public CMyUnknownImp
{
CMyComPtr<ICompressProgressInfo> _progress;
#ifndef _7ZIP_ST
NWindows::NSynchronization::CCriticalSection CriticalSection;
#endif
public:
UInt64 OutSize;
CMtEncMultiProgress(): OutSize(0) {}
void Init(ICompressProgressInfo *progress);
void AddOutSize(UInt64 addOutSize)
{
#ifndef _7ZIP_ST
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
#endif
OutSize += addOutSize;
}
MY_UNKNOWN_IMP1(ICompressProgressInfo)
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
};
class CEncoder 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 Encode(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream,
// const UInt64 *inStreamSize,
const UInt64 *inSizeForReduce,
CFolder &folderItem,
CRecordVector<UInt64> &coderUnpackSizes,
UInt64 &unpackSize,
ISequentialOutStream *outStream,
CRecordVector<UInt64> &packSizes,
ICompressProgressInfo *compressProgress);
};
}}
#endif

View File

@@ -0,0 +1,428 @@
// 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 {
class CFolderOutStream:
public ISequentialOutStream,
public CMyUnknownImp
{
CMyComPtr<ISequentialOutStream> _stream;
public:
bool TestMode;
bool CheckCrc;
private:
bool _fileIsOpen;
bool _calcCrc;
UInt32 _crc;
UInt64 _rem;
const UInt32 *_indexes;
unsigned _numFiles;
unsigned _fileIndex;
HRESULT OpenFile(bool isCorrupted = false);
HRESULT CloseFile_and_SetResult(Int32 res);
HRESULT CloseFile();
HRESULT ProcessEmptyFiles();
public:
MY_UNKNOWN_IMP1(ISequentialOutStream)
const CDbEx *_db;
CMyComPtr<IArchiveExtractCallback> ExtractCallback;
bool ExtraWriteWasCut;
CFolderOutStream():
TestMode(false),
CheckCrc(true)
{}
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
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)
{
_fileIndex = startIndex;
_indexes = indexes;
_numFiles = numFiles;
_fileIsOpen = false;
ExtraWriteWasCut = false;
return ProcessEmptyFiles();
}
HRESULT CFolderOutStream::OpenFile(bool isCorrupted)
{
const CFileItem &fi = _db->Files[_fileIndex];
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;
}
STDMETHODIMP 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;
}
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec)
{
// for GCC
// CFolderOutStream *folderOutStream = new CFolderOutStream;
// CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
COM_TRY_BEGIN
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
UInt64 importantTotalUnpacked = 0;
// numItems = (UInt32)(Int32)-1;
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++)
{
UInt32 fileIndex = allFilesMode ? i : indices[i];
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));
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false);
CDecoder decoder(
#if !defined(USE_MIXER_MT)
false
#elif !defined(USE_MIXER_ST)
true
#elif !defined(__7Z_SET_PROPERTIES)
#ifdef _7ZIP_ST
false
#else
true
#endif
#else
_useMultiThreadMixer
#endif
);
UInt64 curPacked, curUnpacked;
CMyComPtr<IArchiveExtractCallbackMessage> callbackMessage;
extractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage, &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];
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++)
{
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;
}
{
HRESULT result = folderOutStream->Init(fileIndex,
allFilesMode ? NULL : indices + i,
numSolidFiles);
i += numSolidFiles;
RINOK(result);
}
// to test solid block with zero unpacked size we disable that code
if (folderOutStream->WasWritingFinished())
continue;
#ifndef _NO_CRYPTO
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
if (extractCallback)
extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
#endif
try
{
#ifndef _NO_CRYPTO
bool isEncrypted = false;
bool passwordIsDefined = false;
UString_Wipe password;
#endif
bool dataAfterEnd_Error = false;
HRESULT result = decoder.Decode(
EXTERNAL_CODECS_VARS
_inStream,
_db.ArcInfo.DataStartPosition,
_db, folderIndex,
&curUnpacked,
outStream,
progress,
NULL // *inStreamMainRes
, dataAfterEnd_Error
_7Z_DECODER_CRYPRO_VARS
#if !defined(_7ZIP_ST)
, true, _numThreads, _memUsage
#endif
);
if (result == S_FALSE || result == E_NOTIMPL || dataAfterEnd_Error)
{
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
}
}}

View File

@@ -0,0 +1,139 @@
// 7zFolderInStream.cpp
#include "StdAfx.h"
#include "7zFolderInStream.h"
namespace NArchive {
namespace N7z {
void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,
const UInt32 *indexes, unsigned numFiles)
{
_updateCallback = updateCallback;
_indexes = indexes;
_numFiles = numFiles;
_index = 0;
Processed.ClearAndReserve(numFiles);
CRCs.ClearAndReserve(numFiles);
Sizes.ClearAndReserve(numFiles);
_pos = 0;
_crc = CRC_INIT_VAL;
_size_Defined = false;
_size = 0;
_stream.Release();
}
HRESULT CFolderInStream::OpenStream()
{
_pos = 0;
_crc = CRC_INIT_VAL;
_size_Defined = false;
_size = 0;
while (_index < _numFiles)
{
CMyComPtr<ISequentialInStream> stream;
HRESULT result = _updateCallback->GetStream(_indexes[_index], &stream);
if (result != S_OK)
{
if (result != S_FALSE)
return result;
}
_stream = stream;
if (stream)
{
CMyComPtr<IStreamGetSize> streamGetSize;
stream.QueryInterface(IID_IStreamGetSize, &streamGetSize);
if (streamGetSize)
{
if (streamGetSize->GetSize(&_size) == S_OK)
_size_Defined = true;
}
return S_OK;
}
_index++;
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
AddFileInfo(result == S_OK);
}
return S_OK;
}
void CFolderInStream::AddFileInfo(bool isProcessed)
{
Processed.Add(isProcessed);
Sizes.Add(_pos);
CRCs.Add(CRC_GET_DIGEST(_crc));
}
STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
if (processedSize)
*processedSize = 0;
while (size != 0)
{
if (_stream)
{
UInt32 cur = size;
const UInt32 kMax = (UInt32)1 << 20;
if (cur > kMax)
cur = kMax;
RINOK(_stream->Read(data, cur, &cur));
if (cur != 0)
{
_crc = CrcUpdate(_crc, data, cur);
_pos += cur;
if (processedSize)
*processedSize = cur;
return S_OK;
}
_stream.Release();
_index++;
AddFileInfo(true);
_pos = 0;
_crc = CRC_INIT_VAL;
_size_Defined = false;
_size = 0;
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
}
if (_index >= _numFiles)
break;
RINOK(OpenStream());
}
return S_OK;
}
STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
{
*value = 0;
if (subStream > Sizes.Size())
return S_FALSE; // E_FAIL;
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;
}
}}

View File

@@ -0,0 +1,61 @@
// 7zFolderInStream.h
#ifndef __7Z_FOLDER_IN_STREAM_H
#define __7Z_FOLDER_IN_STREAM_H
#include "../../../../C/7zCrc.h"
#include "../../../Common/MyCom.h"
#include "../../../Common/MyVector.h"
#include "../../ICoder.h"
#include "../IArchive.h"
namespace NArchive {
namespace N7z {
class CFolderInStream:
public ISequentialInStream,
public ICompressGetSubStreamSize,
public CMyUnknownImp
{
CMyComPtr<ISequentialInStream> _stream;
UInt64 _pos;
UInt32 _crc;
bool _size_Defined;
UInt64 _size;
const UInt32 *_indexes;
unsigned _numFiles;
unsigned _index;
CMyComPtr<IArchiveUpdateCallback> _updateCallback;
HRESULT OpenStream();
void AddFileInfo(bool isProcessed);
public:
CRecordVector<bool> Processed;
CRecordVector<UInt32> CRCs;
CRecordVector<UInt64> Sizes;
MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles);
bool WasFinished() const { return _index == _numFiles; }
UInt64 GetFullSize() const
{
UInt64 size = 0;
FOR_VECTOR (i, Sizes)
size += Sizes[i];
return size;
}
};
}}
#endif

View File

@@ -0,0 +1,778 @@
// 7zHandler.cpp
#include "StdAfx.h"
#include "../../../../C/CpuArch.h"
#include "../../../Common/ComTry.h"
#include "../../../Common/IntToString.h"
#ifndef __7Z_SET_PROPERTIES
#include "../../../Windows/System.h"
#endif
#include "../Common/ItemNameUtils.h"
#include "7zHandler.h"
#include "7zProperties.h"
#ifdef __7Z_SET_PROPERTIES
#ifdef EXTRACT_ONLY
#include "../Common/ParseProperties.h"
#endif
#endif
using namespace NWindows;
using namespace NCOM;
namespace NArchive {
namespace N7z {
CHandler::CHandler()
{
#ifndef _NO_CRYPTO
_isEncrypted = false;
_passwordIsDefined = false;
#endif
#ifdef EXTRACT_ONLY
_crcSize = 4;
#ifdef __7Z_SET_PROPERTIES
_useMultiThreadMixer = true;
#endif
#endif
}
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
*numItems = _db.Files.Size();
return S_OK;
}
#ifdef _SFX
IMP_IInArchive_ArcProps_NO_Table
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps)
{
*numProps = 0;
return S_OK;
}
STDMETHODIMP 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)
{
unsigned i;
for (i = 0; i <= 31; 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
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
#ifndef _SFX
COM_TRY_BEGIN
#endif
NCOM::CPropVariant prop;
switch (propID)
{
#ifndef _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
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;
}
}
return prop.Detach(value);
#ifndef _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(prop, value);
}
bool CHandler::IsFolderEncrypted(CNum folderIndex) const
{
if (folderIndex == kNumNoIndex)
return false;
size_t startPos = _db.FoCodersDataOffset[folderIndex];
const Byte *p = _db.CodersData + startPos;
size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
CInByte2 inByte;
inByte.Init(p, size);
CNum numCoders = inByte.ReadNum();
for (; numCoders != 0; numCoders--)
{
Byte mainByte = inByte.ReadByte();
unsigned idSize = (mainByte & 0xF);
const Byte *longID = inByte.GetPtr();
UInt64 id64 = 0;
for (unsigned j = 0; j < idSize; j++)
id64 = ((id64 << 8) | longID[j]);
inByte.SkipDataNoCheck(idSize);
if (id64 == k_AES)
return true;
if ((mainByte & 0x20) != 0)
inByte.SkipDataNoCheck(inByte.ReadNum());
}
return false;
}
STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps)
{
*numProps = 0;
return S_OK;
}
STDMETHODIMP CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID)
{
*name = NULL;
*propID = kpidNtSecure;
return S_OK;
}
STDMETHODIMP 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;
}
STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)
{
*data = NULL;
*dataSize = 0;
*propType = 0;
if (/* _db.IsTree && propID == kpidName ||
!_db.IsTree && */ propID == kpidPath)
{
if (_db.NameOffsets && _db.NamesBuf)
{
size_t offset = _db.NameOffsets[index];
size_t size = (_db.NameOffsets[index + 1] - offset) * 2;
if (size < ((UInt32)1 << 31))
{
*data = (const void *)(_db.NamesBuf + 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 _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;
size_t startPos = _db.FoCodersDataOffset[folderIndex];
const Byte *p = _db.CodersData + startPos;
size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
CInByte2 inByte;
inByte.Init(p, size);
// numCoders == 0 ???
CNum numCoders = inByte.ReadNum();
bool needSpace = false;
for (; numCoders != 0; numCoders--, needSpace = true)
{
if (pos < 32) // max size of property
break;
Byte mainByte = inByte.ReadByte();
unsigned idSize = (mainByte & 0xF);
const Byte *longID = inByte.GetPtr();
UInt64 id64 = 0;
for (unsigned j = 0; j < idSize; j++)
id64 = ((id64 << 8) | longID[j]);
inByte.SkipDataNoCheck(idSize);
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)
{
UInt32 id = (UInt32)id64;
if (id == k_LZMA)
{
name = "LZMA";
if (propsSize == 5)
{
UInt32 dicSize = GetUi32((const Byte *)props + 1);
char *dest = GetStringForSizeValue(s, dicSize);
UInt32 d = props[0];
if (d != 0x5D)
{
UInt32 lc = d % 9;
d /= 9;
UInt32 pb = d / 5;
UInt32 lp = d % 5;
if (lc != 3) dest = AddProp32(dest, "lc", lc);
if (lp != 0) dest = AddProp32(dest, "lp", lp);
if (pb != 2) dest = AddProp32(dest, "pb", pb);
}
}
}
else if (id == k_LZMA2)
{
name = "LZMA2";
if (propsSize == 1)
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_BCJ2) name = "BCJ2";
else if (id == k_BCJ) name = "BCJ";
else if (id == k_AES)
{
name = "7zAES";
if (propsSize >= 1)
{
Byte firstByte = props[0];
UInt32 numCyclesPower = firstByte & 0x3F;
ConvertUInt32ToString(numCyclesPower, s);
}
}
}
if (name)
{
unsigned nameLen = MyStringLen(name);
unsigned propsLen = MyStringLen(s);
unsigned totalLen = nameLen + propsLen;
if (propsLen != 0)
totalLen++;
if (needSpace)
totalLen++;
if (totalLen + 5 >= pos)
break;
pos -= totalLen;
MyStringCopy(temp + pos, name);
if (propsLen != 0)
{
char *dest = temp + pos + nameLen;
*dest++ = ':';
MyStringCopy(dest, s);
}
if (needSpace)
temp[pos + totalLen - 1] = ' ';
}
else
{
AString methodName;
FindMethod(EXTERNAL_CODECS_VARS id64, methodName);
if (needSpace)
temp[--pos] = ' ';
if (methodName.IsEmpty())
pos -= ConvertMethodIdToString_Back(temp + pos, id64);
else
{
unsigned len = methodName.Len();
if (len + 5 > pos)
break;
pos -= len;
for (unsigned i = 0; i < len; i++)
temp[pos + i] = methodName[i];
}
}
}
if (numCoders != 0 && pos >= 4)
{
temp[--pos] = ' ';
temp[--pos] = '.';
temp[--pos] = '.';
temp[--pos] = '.';
}
return PropVarEm_Set_Str(prop, temp + pos);
// }
}
#endif
STDMETHODIMP 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;
{
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 _SFX
case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value);
case kpidBlock:
{
CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
if (folderIndex != kNumNoIndex)
PropVarEm_Set_UInt32(value, (UInt32)folderIndex);
}
break;
/*
case kpidPackedSize0:
case kpidPackedSize1:
case kpidPackedSize2:
case kpidPackedSize3:
case kpidPackedSize4:
{
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
}
// return prop.Detach(value);
return S_OK;
// COM_TRY_END
}
STDMETHODIMP CHandler::Open(IInStream *stream,
const UInt64 *maxCheckStartPosition,
IArchiveOpenCallback *openArchiveCallback)
{
COM_TRY_BEGIN
Close();
#ifndef _SFX
_fileInfoPopIDs.Clear();
#endif
try
{
CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;
#ifndef _NO_CRYPTO
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
if (openArchiveCallback)
openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
#endif
CInArchive archive(
#ifdef __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 _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 _SFX
FillPopIDs();
#endif
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::Close()
{
COM_TRY_BEGIN
_inStream.Release();
_db.Clear();
#ifndef _NO_CRYPTO
_isEncrypted = false;
_passwordIsDefined = false;
_password.Wipe_and_Empty();
#endif
return S_OK;
COM_TRY_END
}
#ifdef __7Z_SET_PROPERTIES
#ifdef EXTRACT_ONLY
STDMETHODIMP 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;
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
}}

View File

@@ -0,0 +1,185 @@
// 7z/Handler.h
#ifndef __7Z_HANDLER_H
#define __7Z_HANDLER_H
#include "../../ICoder.h"
#include "../IArchive.h"
#include "../../Common/CreateCoder.h"
#ifndef __7Z_SET_PROPERTIES
#ifdef EXTRACT_ONLY
#if !defined(_7ZIP_ST) && !defined(_SFX)
#define __7Z_SET_PROPERTIES
#endif
#else
#define __7Z_SET_PROPERTIES
#endif
#endif
// #ifdef __7Z_SET_PROPERTIES
#include "../Common/HandlerOut.h"
// #endif
#include "7zCompressionMode.h"
#include "7zIn.h"
namespace NArchive {
namespace N7z {
#ifndef 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
CBoolPair Write_CTime;
CBoolPair Write_ATime;
CBoolPair Write_MTime;
CBoolPair Write_Attrib;
bool _useMultiThreadMixer;
bool _removeSfxBlock;
// bool _volumeMode;
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:
public IInArchive,
public IArchiveGetRawProps,
#ifdef __7Z_SET_PROPERTIES
public ISetProperties,
#endif
#ifndef EXTRACT_ONLY
public IOutArchive,
#endif
PUBLIC_ISetCompressCodecsInfo
public CMyUnknownImp,
#ifndef EXTRACT_ONLY
public COutHandler
#else
public CCommonMethodProps
#endif
{
public:
MY_QUERYINTERFACE_BEGIN2(IInArchive)
MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
#ifdef __7Z_SET_PROPERTIES
MY_QUERYINTERFACE_ENTRY(ISetProperties)
#endif
#ifndef EXTRACT_ONLY
MY_QUERYINTERFACE_ENTRY(IOutArchive)
#endif
QUERY_ENTRY_ISetCompressCodecsInfo
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
INTERFACE_IInArchive(;)
INTERFACE_IArchiveGetRawProps(;)
#ifdef __7Z_SET_PROPERTIES
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
#endif
#ifndef EXTRACT_ONLY
INTERFACE_IOutArchive(;)
#endif
DECL_ISetCompressCodecsInfo
CHandler();
~CHandler()
{
Close();
}
private:
CMyComPtr<IInStream> _inStream;
NArchive::N7z::CDbEx _db;
#ifndef _NO_CRYPTO
bool _isEncrypted;
bool _passwordIsDefined;
UString _password; // _Wipe
#endif
#ifdef EXTRACT_ONLY
#ifdef __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
#ifndef _7ZIP_ST
, UInt32 numThreads
#endif
);
#endif
bool IsFolderEncrypted(CNum folderIndex) const;
#ifndef _SFX
CRecordVector<UInt64> _fileInfoPopIDs;
void FillPopIDs();
void AddMethodName(AString &s, UInt64 id);
HRESULT SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const;
#endif
DECL_EXTERNAL_CODECS_VARS
};
}}
#endif

View File

@@ -0,0 +1,968 @@
// 7zHandlerOut.cpp
#include "StdAfx.h"
#include "../../../Common/ComTry.h"
#include "../../../Common/StringToInt.h"
#include "../../../Common/Wildcard.h"
#include "../Common/ItemNameUtils.h"
#include "../Common/ParseProperties.h"
#include "7zHandler.h"
#include "7zOut.h"
#include "7zUpdate.h"
#ifndef EXTRACT_ONLY
using namespace NWindows;
namespace NArchive {
namespace N7z {
#define k_LZMA_Name "LZMA"
#define kDefaultMethodName "LZMA2"
#define k_Copy_Name "Copy"
#define k_MatchFinder_ForHeaders "BT2"
static const UInt32 k_NumFastBytes_ForHeaders = 273;
static const UInt32 k_Level_ForHeaders = 5;
static const UInt32 k_Dictionary_ForHeaders =
#ifdef UNDER_CE
1 << 18;
#else
1 << 20;
#endif
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
{
*type = NFileTimeType::kWindows;
return S_OK;
}
HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m)
{
dest.CodecIndex = FindMethod_Index(
EXTERNAL_CODECS_VARS
m.MethodName, true,
dest.Id, dest.NumStreams);
if (dest.CodecIndex < 0)
return E_INVALIDARG;
(CProps &)dest = (CProps &)m;
return S_OK;
}
HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod)
{
if (!_compressHeaders)
return S_OK;
COneMethodInfo m;
m.MethodName = k_LZMA_Name;
m.AddProp_Ascii(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders);
m.AddProp_Level(k_Level_ForHeaders);
m.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders);
m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders);
m.AddProp_NumThreads(1);
CMethodFull &methodFull = headerMethod.Methods.AddNew();
return PropsMethod_To_FullMethod(methodFull, m);
}
HRESULT CHandler::SetMainMethod(
CCompressionMethodMode &methodMode
#ifndef _7ZIP_ST
, UInt32 numThreads
#endif
)
{
methodMode.Bonds = _bonds;
CObjectVector<COneMethodInfo> methods = _methods;
{
FOR_VECTOR (i, methods)
{
AString &methodName = methods[i].MethodName;
if (methodName.IsEmpty())
methodName = kDefaultMethodName;
}
if (methods.IsEmpty())
{
COneMethodInfo &m = methods.AddNew();
m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName);
methodMode.DefaultMethod_was_Inserted = true;
}
}
if (!_filterMethod.MethodName.IsEmpty())
{
// if (methodMode.Bonds.IsEmpty())
{
FOR_VECTOR (k, methodMode.Bonds)
{
CBond2 &bond = methodMode.Bonds[k];
bond.InCoder++;
bond.OutCoder++;
}
methods.Insert(0, _filterMethod);
methodMode.Filter_was_Inserted = true;
}
}
const UInt64 kSolidBytes_Min = (1 << 24);
const UInt64 kSolidBytes_Max = ((UInt64)1 << 32);
bool needSolid = false;
FOR_VECTOR (i, methods)
{
COneMethodInfo &oneMethodInfo = methods[i];
SetGlobalLevelTo(oneMethodInfo);
#ifndef _7ZIP_ST
CMultiMethodProps::SetMethodThreadsTo(oneMethodInfo, numThreads);
#endif
CMethodFull &methodFull = methodMode.Methods.AddNew();
RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo));
if (methodFull.Id != k_Copy)
needSolid = true;
if (_numSolidBytesDefined)
continue;
UInt64 dicSize;
switch (methodFull.Id)
{
case k_LZMA:
case k_LZMA2: dicSize = oneMethodInfo.Get_Lzma_DicSize(); break;
case k_PPMD: dicSize = oneMethodInfo.Get_Ppmd_MemSize(); break;
case k_Deflate: dicSize = (UInt32)1 << 15; break;
case k_Deflate64: dicSize = (UInt32)1 << 16; break;
case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break;
default: continue;
}
if (methodFull.Id == k_LZMA2)
{
// he we calculate default chunk Size for LZMA2 as defined in LZMA2 encoder code
UInt64 cs = (UInt64)dicSize << 2;
const UInt32 kMinSize = (UInt32)1 << 20;
const UInt32 kMaxSize = (UInt32)1 << 28;
if (cs < kMinSize) cs = kMinSize;
if (cs > kMaxSize) cs = kMaxSize;
if (cs < dicSize) cs = dicSize;
cs += (kMinSize - 1);
cs &= ~(UInt64)(kMinSize - 1);
// we want to use at least 64 chunks (threads) per one solid block.
_numSolidBytes = cs << 6;
const UInt64 kSolidBytes_Lzma2_Max = ((UInt64)1 << 34);
if (_numSolidBytes > kSolidBytes_Lzma2_Max)
_numSolidBytes = kSolidBytes_Lzma2_Max;
}
else
{
_numSolidBytes = (UInt64)dicSize << 7;
if (_numSolidBytes > kSolidBytes_Max)
_numSolidBytes = kSolidBytes_Max;
}
if (_numSolidBytes < kSolidBytes_Min)
_numSolidBytes = kSolidBytes_Min;
_numSolidBytesDefined = true;
}
if (!_numSolidBytesDefined)
{
if (needSolid)
_numSolidBytes = kSolidBytes_Max;
else
_numSolidBytes = 0;
}
_numSolidBytesDefined = true;
return S_OK;
}
static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, unsigned index, PROPID propID, UInt64 &ft, bool &ftDefined)
{
// ft = 0;
// ftDefined = false;
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(index, propID, &prop));
if (prop.vt == VT_FILETIME)
{
ft = prop.filetime.dwLowDateTime | ((UInt64)prop.filetime.dwHighDateTime << 32);
ftDefined = true;
}
else if (prop.vt != VT_EMPTY)
return E_INVALIDARG;
else
{
ft = 0;
ftDefined = false;
}
return S_OK;
}
/*
#ifdef _WIN32
static const wchar_t kDirDelimiter1 = L'\\';
#endif
static const wchar_t kDirDelimiter2 = L'/';
static inline bool IsCharDirLimiter(wchar_t c)
{
return (
#ifdef _WIN32
c == kDirDelimiter1 ||
#endif
c == kDirDelimiter2);
}
static int FillSortIndex(CObjectVector<CTreeFolder> &treeFolders, int cur, int curSortIndex)
{
CTreeFolder &tf = treeFolders[cur];
tf.SortIndex = curSortIndex++;
for (int i = 0; i < tf.SubFolders.Size(); i++)
curSortIndex = FillSortIndex(treeFolders, tf.SubFolders[i], curSortIndex);
tf.SortIndexEnd = curSortIndex;
return curSortIndex;
}
static int FindSubFolder(const CObjectVector<CTreeFolder> &treeFolders, int cur, const UString &name, int &insertPos)
{
const CIntVector &subFolders = treeFolders[cur].SubFolders;
int left = 0, right = subFolders.Size();
insertPos = -1;
for (;;)
{
if (left == right)
{
insertPos = left;
return -1;
}
int mid = (left + right) / 2;
int midFolder = subFolders[mid];
int compare = CompareFileNames(name, treeFolders[midFolder].Name);
if (compare == 0)
return midFolder;
if (compare < 0)
right = mid;
else
left = mid + 1;
}
}
static int AddFolder(CObjectVector<CTreeFolder> &treeFolders, int cur, const UString &name)
{
int insertPos;
int folderIndex = FindSubFolder(treeFolders, cur, name, insertPos);
if (folderIndex < 0)
{
folderIndex = treeFolders.Size();
CTreeFolder &newFolder = treeFolders.AddNew();
newFolder.Parent = cur;
newFolder.Name = name;
treeFolders[cur].SubFolders.Insert(insertPos, folderIndex);
}
// else if (treeFolders[folderIndex].IsAltStreamFolder != isAltStreamFolder) throw 1123234234;
return folderIndex;
}
*/
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *updateCallback)
{
COM_TRY_BEGIN
const CDbEx *db = 0;
#ifdef _7Z_VOL
if (_volumes.Size() > 1)
return E_FAIL;
const CVolume *volume = 0;
if (_volumes.Size() == 1)
{
volume = &_volumes.Front();
db = &volume->Database;
}
#else
if (_inStream != 0)
db = &_db;
#endif
if (db && !db->CanUpdate())
return E_NOTIMPL;
/*
CMyComPtr<IArchiveGetRawProps> getRawProps;
updateCallback->QueryInterface(IID_IArchiveGetRawProps, (void **)&getRawProps);
CUniqBlocks secureBlocks;
secureBlocks.AddUniq(NULL, 0);
CObjectVector<CTreeFolder> treeFolders;
{
CTreeFolder folder;
folder.Parent = -1;
treeFolders.Add(folder);
}
*/
CObjectVector<CUpdateItem> updateItems;
bool need_CTime = (Write_CTime.Def && Write_CTime.Val);
bool need_ATime = (Write_ATime.Def && Write_ATime.Val);
bool need_MTime = (Write_MTime.Def ? Write_MTime.Val : true);
bool need_Attrib = (Write_Attrib.Def ? Write_Attrib.Val : true);
if (db && !db->Files.IsEmpty())
{
if (!Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty();
if (!Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty();
if (!Write_MTime.Def) need_MTime = !db->MTime.Defs.IsEmpty();
if (!Write_Attrib.Def) need_Attrib = !db->Attrib.Defs.IsEmpty();
}
// UString s;
UString name;
for (UInt32 i = 0; i < numItems; i++)
{
Int32 newData, newProps;
UInt32 indexInArchive;
if (!updateCallback)
return E_FAIL;
RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
CUpdateItem ui;
ui.NewProps = IntToBool(newProps);
ui.NewData = IntToBool(newData);
ui.IndexInArchive = (int)indexInArchive;
ui.IndexInClient = i;
ui.IsAnti = false;
ui.Size = 0;
name.Empty();
// bool isAltStream = false;
if (ui.IndexInArchive != -1)
{
if (!db || (unsigned)ui.IndexInArchive >= db->Files.Size())
return E_INVALIDARG;
const CFileItem &fi = db->Files[(unsigned)ui.IndexInArchive];
if (!ui.NewProps)
{
_db.GetPath((unsigned)ui.IndexInArchive, name);
}
ui.IsDir = fi.IsDir;
ui.Size = fi.Size;
// isAltStream = fi.IsAltStream;
ui.IsAnti = db->IsItemAnti((unsigned)ui.IndexInArchive);
if (!ui.NewProps)
{
ui.CTimeDefined = db->CTime.GetItem((unsigned)ui.IndexInArchive, ui.CTime);
ui.ATimeDefined = db->ATime.GetItem((unsigned)ui.IndexInArchive, ui.ATime);
ui.MTimeDefined = db->MTime.GetItem((unsigned)ui.IndexInArchive, ui.MTime);
}
}
if (ui.NewProps)
{
bool folderStatusIsDefined;
if (need_Attrib)
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(i, kpidAttrib, &prop));
if (prop.vt == VT_EMPTY)
ui.AttribDefined = false;
else if (prop.vt != VT_UI4)
return E_INVALIDARG;
else
{
ui.Attrib = prop.ulVal;
ui.AttribDefined = true;
}
}
// we need MTime to sort files.
if (need_CTime) RINOK(GetTime(updateCallback, i, kpidCTime, ui.CTime, ui.CTimeDefined));
if (need_ATime) RINOK(GetTime(updateCallback, i, kpidATime, ui.ATime, ui.ATimeDefined));
if (need_MTime) RINOK(GetTime(updateCallback, i, kpidMTime, ui.MTime, ui.MTimeDefined));
/*
if (getRawProps)
{
const void *data;
UInt32 dataSize;
UInt32 propType;
getRawProps->GetRawProp(i, kpidNtSecure, &data, &dataSize, &propType);
if (dataSize != 0 && propType != NPropDataType::kRaw)
return E_FAIL;
ui.SecureIndex = secureBlocks.AddUniq((const Byte *)data, dataSize);
}
*/
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(i, kpidPath, &prop));
if (prop.vt == VT_EMPTY)
{
}
else if (prop.vt != VT_BSTR)
return E_INVALIDARG;
else
{
name = prop.bstrVal;
NItemName::ReplaceSlashes_OsToUnix(name);
}
}
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(i, kpidIsDir, &prop));
if (prop.vt == VT_EMPTY)
folderStatusIsDefined = false;
else if (prop.vt != VT_BOOL)
return E_INVALIDARG;
else
{
ui.IsDir = (prop.boolVal != VARIANT_FALSE);
folderStatusIsDefined = true;
}
}
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(i, kpidIsAnti, &prop));
if (prop.vt == VT_EMPTY)
ui.IsAnti = false;
else if (prop.vt != VT_BOOL)
return E_INVALIDARG;
else
ui.IsAnti = (prop.boolVal != VARIANT_FALSE);
}
/*
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(i, kpidIsAltStream, &prop));
if (prop.vt == VT_EMPTY)
isAltStream = false;
else if (prop.vt != VT_BOOL)
return E_INVALIDARG;
else
isAltStream = (prop.boolVal != VARIANT_FALSE);
}
*/
if (ui.IsAnti)
{
ui.AttribDefined = false;
ui.CTimeDefined = false;
ui.ATimeDefined = false;
ui.MTimeDefined = false;
ui.Size = 0;
}
if (!folderStatusIsDefined && ui.AttribDefined)
ui.SetDirStatusFromAttrib();
}
else
{
/*
if (_db.SecureIDs.IsEmpty())
ui.SecureIndex = secureBlocks.AddUniq(NULL, 0);
else
{
int id = _db.SecureIDs[ui.IndexInArchive];
size_t offs = _db.SecureOffsets[id];
size_t size = _db.SecureOffsets[id + 1] - offs;
ui.SecureIndex = secureBlocks.AddUniq(_db.SecureBuf + offs, size);
}
*/
}
/*
{
int folderIndex = 0;
if (_useParents)
{
int j;
s.Empty();
for (j = 0; j < name.Len(); j++)
{
wchar_t c = name[j];
if (IsCharDirLimiter(c))
{
folderIndex = AddFolder(treeFolders, folderIndex, s);
s.Empty();
continue;
}
s += c;
}
if (isAltStream)
{
int colonPos = s.Find(':');
if (colonPos < 0)
{
// isAltStream = false;
return E_INVALIDARG;
}
UString mainName = s.Left(colonPos);
int newFolderIndex = AddFolder(treeFolders, folderIndex, mainName);
if (treeFolders[newFolderIndex].UpdateItemIndex < 0)
{
for (int j = updateItems.Size() - 1; j >= 0; j--)
{
CUpdateItem &ui2 = updateItems[j];
if (ui2.ParentFolderIndex == folderIndex
&& ui2.Name == mainName)
{
ui2.TreeFolderIndex = newFolderIndex;
treeFolders[newFolderIndex].UpdateItemIndex = j;
}
}
}
folderIndex = newFolderIndex;
s.Delete(0, colonPos + 1);
}
ui.Name = s;
}
else
ui.Name = name;
ui.IsAltStream = isAltStream;
ui.ParentFolderIndex = folderIndex;
ui.TreeFolderIndex = -1;
if (ui.IsDir && !s.IsEmpty())
{
ui.TreeFolderIndex = AddFolder(treeFolders, folderIndex, s);
treeFolders[ui.TreeFolderIndex].UpdateItemIndex = updateItems.Size();
}
}
*/
ui.Name = name;
if (ui.NewData)
{
ui.Size = 0;
if (!ui.IsDir)
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(i, kpidSize, &prop));
if (prop.vt != VT_UI8)
return E_INVALIDARG;
ui.Size = (UInt64)prop.uhVal.QuadPart;
if (ui.Size != 0 && ui.IsAnti)
return E_INVALIDARG;
}
}
updateItems.Add(ui);
}
/*
FillSortIndex(treeFolders, 0, 0);
for (i = 0; i < (UInt32)updateItems.Size(); i++)
{
CUpdateItem &ui = updateItems[i];
ui.ParentSortIndex = treeFolders[ui.ParentFolderIndex].SortIndex;
ui.ParentSortIndexEnd = treeFolders[ui.ParentFolderIndex].SortIndexEnd;
}
*/
CCompressionMethodMode methodMode, headerMethod;
HRESULT res = SetMainMethod(methodMode
#ifndef _7ZIP_ST
, _numThreads
#endif
);
RINOK(res);
RINOK(SetHeaderMethod(headerMethod));
#ifndef _7ZIP_ST
methodMode.NumThreads = _numThreads;
methodMode.MultiThreadMixer = _useMultiThreadMixer;
headerMethod.NumThreads = 1;
headerMethod.MultiThreadMixer = _useMultiThreadMixer;
#endif
CMyComPtr<ICryptoGetTextPassword2> getPassword2;
updateCallback->QueryInterface(IID_ICryptoGetTextPassword2, (void **)&getPassword2);
methodMode.PasswordIsDefined = false;
methodMode.Password.Wipe_and_Empty();
if (getPassword2)
{
CMyComBSTR_Wipe password;
Int32 passwordIsDefined;
RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password));
methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
if (methodMode.PasswordIsDefined && password)
methodMode.Password = password;
}
bool compressMainHeader = _compressHeaders; // check it
bool encryptHeaders = false;
#ifndef _NO_CRYPTO
if (!methodMode.PasswordIsDefined && _passwordIsDefined)
{
// if header is compressed, we use that password for updated archive
methodMode.PasswordIsDefined = true;
methodMode.Password = _password;
}
#endif
if (methodMode.PasswordIsDefined)
{
if (_encryptHeadersSpecified)
encryptHeaders = _encryptHeaders;
#ifndef _NO_CRYPTO
else
encryptHeaders = _passwordIsDefined;
#endif
compressMainHeader = true;
if (encryptHeaders)
{
headerMethod.PasswordIsDefined = methodMode.PasswordIsDefined;
headerMethod.Password = methodMode.Password;
}
}
if (numItems < 2)
compressMainHeader = false;
int level = GetLevel();
CUpdateOptions options;
options.Method = &methodMode;
options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : NULL;
options.UseFilters = (level != 0 && _autoFilter && !methodMode.Filter_was_Inserted);
options.MaxFilter = (level >= 8);
options.AnalysisLevel = GetAnalysisLevel();
options.HeaderOptions.CompressMainHeader = compressMainHeader;
/*
options.HeaderOptions.WriteCTime = Write_CTime;
options.HeaderOptions.WriteATime = Write_ATime;
options.HeaderOptions.WriteMTime = Write_MTime;
options.HeaderOptions.WriteAttrib = Write_Attrib;
*/
options.NumSolidFiles = _numSolidFiles;
options.NumSolidBytes = _numSolidBytes;
options.SolidExtension = _solidExtension;
options.UseTypeSorting = _useTypeSorting;
options.RemoveSfxBlock = _removeSfxBlock;
// options.VolumeMode = _volumeMode;
options.MultiThreadMixer = _useMultiThreadMixer;
COutArchive archive;
CArchiveDatabaseOut newDatabase;
CMyComPtr<ICryptoGetTextPassword> getPassword;
updateCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getPassword);
/*
if (secureBlocks.Sorted.Size() > 1)
{
secureBlocks.GetReverseMap();
for (int i = 0; i < updateItems.Size(); i++)
{
int &secureIndex = updateItems[i].SecureIndex;
secureIndex = secureBlocks.BufIndexToSortedIndex[secureIndex];
}
}
*/
res = Update(
EXTERNAL_CODECS_VARS
#ifdef _7Z_VOL
volume ? volume->Stream: 0,
volume ? db : 0,
#else
_inStream,
db,
#endif
updateItems,
// treeFolders,
// secureBlocks,
archive, newDatabase, outStream, updateCallback, options
#ifndef _NO_CRYPTO
, getPassword
#endif
);
RINOK(res);
updateItems.ClearAndFree();
return archive.WriteDatabase(EXTERNAL_CODECS_VARS
newDatabase, options.HeaderMethod, options.HeaderOptions);
COM_TRY_END
}
static HRESULT ParseBond(UString &srcString, UInt32 &coder, UInt32 &stream)
{
stream = 0;
{
unsigned index = ParseStringToUInt32(srcString, coder);
if (index == 0)
return E_INVALIDARG;
srcString.DeleteFrontal(index);
}
if (srcString[0] == 's')
{
srcString.Delete(0);
unsigned index = ParseStringToUInt32(srcString, stream);
if (index == 0)
return E_INVALIDARG;
srcString.DeleteFrontal(index);
}
return S_OK;
}
void COutHandler::InitProps7z()
{
_removeSfxBlock = false;
_compressHeaders = true;
_encryptHeadersSpecified = false;
_encryptHeaders = false;
// _useParents = false;
Write_CTime.Init();
Write_ATime.Init();
Write_MTime.Init();
Write_Attrib.Init();
_useMultiThreadMixer = true;
// _volumeMode = false;
InitSolid();
_useTypeSorting = false;
}
void COutHandler::InitProps()
{
CMultiMethodProps::Init();
InitProps7z();
}
HRESULT COutHandler::SetSolidFromString(const UString &s)
{
UString s2 = s;
s2.MakeLower_Ascii();
for (unsigned i = 0; i < s2.Len();)
{
const wchar_t *start = ((const wchar_t *)s2) + i;
const wchar_t *end;
UInt64 v = ConvertStringToUInt64(start, &end);
if (start == end)
{
if (s2[i++] != 'e')
return E_INVALIDARG;
_solidExtension = true;
continue;
}
i += (unsigned)(end - start);
if (i == s2.Len())
return E_INVALIDARG;
wchar_t c = s2[i++];
if (c == 'f')
{
if (v < 1)
v = 1;
_numSolidFiles = v;
}
else
{
unsigned numBits;
switch (c)
{
case 'b': numBits = 0; break;
case 'k': numBits = 10; break;
case 'm': numBits = 20; break;
case 'g': numBits = 30; break;
case 't': numBits = 40; break;
default: return E_INVALIDARG;
}
_numSolidBytes = (v << numBits);
_numSolidBytesDefined = true;
/*
if (_numSolidBytes == 0)
_numSolidFiles = 1;
*/
}
}
return S_OK;
}
HRESULT COutHandler::SetSolidFromPROPVARIANT(const PROPVARIANT &value)
{
bool isSolid;
switch (value.vt)
{
case VT_EMPTY: isSolid = true; break;
case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break;
case VT_BSTR:
if (StringToBool(value.bstrVal, isSolid))
break;
return SetSolidFromString(value.bstrVal);
default: return E_INVALIDARG;
}
if (isSolid)
InitSolid();
else
_numSolidFiles = 1;
return S_OK;
}
static HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest)
{
RINOK(PROPVARIANT_to_bool(prop, dest.Val));
dest.Def = true;
return S_OK;
}
HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
{
UString name = nameSpec;
name.MakeLower_Ascii();
if (name.IsEmpty())
return E_INVALIDARG;
if (name[0] == L's')
{
name.Delete(0);
if (name.IsEmpty())
return SetSolidFromPROPVARIANT(value);
if (value.vt != VT_EMPTY)
return E_INVALIDARG;
return SetSolidFromString(name);
}
UInt32 number;
unsigned index = ParseStringToUInt32(name, number);
// UString realName = name.Ptr(index);
if (index == 0)
{
if (name.IsEqualTo("rsfx")) return PROPVARIANT_to_bool(value, _removeSfxBlock);
if (name.IsEqualTo("hc")) return PROPVARIANT_to_bool(value, _compressHeaders);
// if (name.IsEqualToNoCase(L"HS")) return PROPVARIANT_to_bool(value, _useParents);
if (name.IsEqualTo("hcf"))
{
bool compressHeadersFull = true;
RINOK(PROPVARIANT_to_bool(value, compressHeadersFull));
return compressHeadersFull ? S_OK: E_INVALIDARG;
}
if (name.IsEqualTo("he"))
{
RINOK(PROPVARIANT_to_bool(value, _encryptHeaders));
_encryptHeadersSpecified = true;
return S_OK;
}
if (name.IsEqualTo("tc")) return PROPVARIANT_to_BoolPair(value, Write_CTime);
if (name.IsEqualTo("ta")) return PROPVARIANT_to_BoolPair(value, Write_ATime);
if (name.IsEqualTo("tm")) return PROPVARIANT_to_BoolPair(value, Write_MTime);
if (name.IsEqualTo("tr")) return PROPVARIANT_to_BoolPair(value, Write_Attrib);
if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer);
if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting);
// if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode);
}
return CMultiMethodProps::SetProperty(name, value);
}
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
COM_TRY_BEGIN
_bonds.Clear();
InitProps();
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];
if (name[0] == 'b')
{
if (value.vt != VT_EMPTY)
return E_INVALIDARG;
name.Delete(0);
CBond2 bond;
RINOK(ParseBond(name, bond.OutCoder, bond.OutStream));
if (name[0] != ':')
return E_INVALIDARG;
name.Delete(0);
UInt32 inStream = 0;
RINOK(ParseBond(name, bond.InCoder, inStream));
if (inStream != 0)
return E_INVALIDARG;
if (!name.IsEmpty())
return E_INVALIDARG;
_bonds.Add(bond);
continue;
}
RINOK(SetProperty(name, value));
}
unsigned numEmptyMethods = GetNumEmptyMethods();
if (numEmptyMethods > 0)
{
unsigned k;
for (k = 0; k < _bonds.Size(); k++)
{
const CBond2 &bond = _bonds[k];
if (bond.InCoder < (UInt32)numEmptyMethods ||
bond.OutCoder < (UInt32)numEmptyMethods)
return E_INVALIDARG;
}
for (k = 0; k < _bonds.Size(); k++)
{
CBond2 &bond = _bonds[k];
bond.InCoder -= (UInt32)numEmptyMethods;
bond.OutCoder -= (UInt32)numEmptyMethods;
}
_methods.DeleteFrontal(numEmptyMethods);
}
FOR_VECTOR (k, _bonds)
{
const CBond2 &bond = _bonds[k];
if (bond.InCoder >= (UInt32)_methods.Size() ||
bond.OutCoder >= (UInt32)_methods.Size())
return E_INVALIDARG;
}
return S_OK;
COM_TRY_END
}
}}
#endif

View File

@@ -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 _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;
}}

View File

@@ -0,0 +1,149 @@
// 7z/7zHeader.h
#ifndef __7Z_HEADER_H
#define __7Z_HEADER_H
#include "../../../Common/MyTypes.h"
namespace NArchive {
namespace N7z {
const unsigned kSignatureSize = 6;
extern Byte kSignature[kSignatureSize];
// #define _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 _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 _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_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;
static inline bool IsFilterMethod(UInt64 m)
{
if (m > (UInt64)0xFFFFFFFF)
return false;
switch ((UInt32)m)
{
case k_Delta:
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;
}
return false;
}
}}
#endif

1710
3rdparty/lzma/CPP/7zip/Archive/7z/7zIn.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

451
3rdparty/lzma/CPP/7zip/Archive/7z/7zIn.h vendored Normal file
View File

@@ -0,0 +1,451 @@
// 7zIn.h
#ifndef __7Z_IN_H
#define __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 _NO_CRYPTO
#define _7Z_DECODER_CRYPRO_VARS_DECL
#define _7Z_DECODER_CRYPRO_VARS
#else
#define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined, UString &password
#define _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(CNum folderIndex, unsigned indexInFolder) const
{
return ArcInfo.DataStartPosition +
PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder];
}
UInt64 GetFolderFullPackSize(CNum folderIndex) const
{
return
PackPositions[FoStartPackStreamIndex[folderIndex + 1]] -
PackPositions[FoStartPackStreamIndex[folderIndex]];
}
UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const
{
size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex;
return PackPositions[i + 1] - PackPositions[i];
}
UInt64 GetFilePackSize(CNum fileIndex) 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
_7Z_DECODER_CRYPRO_VARS_DECL
);
HRESULT ReadHeader(
DECL_EXTERNAL_CODECS_LOC_VARS
CDbEx &db
_7Z_DECODER_CRYPRO_VARS_DECL
);
HRESULT ReadDatabase2(
DECL_EXTERNAL_CODECS_LOC_VARS
CDbEx &db
_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
_7Z_DECODER_CRYPRO_VARS_DECL
);
};
}}
#endif

View File

@@ -0,0 +1,202 @@
// 7zItem.h
#ifndef __7Z_ITEM_H
#define __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
{
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);
};
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

View File

@@ -0,0 +1,961 @@
// 7zOut.cpp
#include "StdAfx.h"
#include "../../../../C/7zCrc.h"
#include "../../../Common/AutoPtr.h"
// #include "../../../Common/UTFConvert.h"
#include "../../Common/StreamObjects.h"
#include "7zOut.h"
namespace NArchive {
namespace N7z {
HRESULT COutArchive::WriteSignature()
{
Byte buf[8];
memcpy(buf, kSignature, kSignatureSize);
buf[kSignatureSize] = kMajorVersion;
buf[kSignatureSize + 1] = 4;
return WriteDirect(buf, 8);
}
#ifdef _7Z_VOL
HRESULT COutArchive::WriteFinishSignature()
{
RINOK(WriteDirect(kFinishSignature, kSignatureSize));
CArchiveVersion av;
av.Major = kMajorVersion;
av.Minor = 2;
RINOK(WriteDirectByte(av.Major));
return WriteDirectByte(av.Minor);
}
#endif
static void SetUInt32(Byte *p, UInt32 d)
{
for (int i = 0; i < 4; i++, d >>= 8)
p[i] = (Byte)d;
}
static void SetUInt64(Byte *p, UInt64 d)
{
for (int i = 0; i < 8; i++, d >>= 8)
p[i] = (Byte)d;
}
HRESULT COutArchive::WriteStartHeader(const CStartHeader &h)
{
Byte buf[24];
SetUInt64(buf + 4, h.NextHeaderOffset);
SetUInt64(buf + 12, h.NextHeaderSize);
SetUInt32(buf + 20, h.NextHeaderCRC);
SetUInt32(buf, CrcCalc(buf + 4, 20));
return WriteDirect(buf, 24);
}
#ifdef _7Z_VOL
HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h)
{
CCRC crc;
crc.UpdateUInt64(h.NextHeaderOffset);
crc.UpdateUInt64(h.NextHeaderSize);
crc.UpdateUInt32(h.NextHeaderCRC);
crc.UpdateUInt64(h.ArchiveStartOffset);
crc.UpdateUInt64(h.AdditionalStartBlockSize);
RINOK(WriteDirectUInt32(crc.GetDigest()));
RINOK(WriteDirectUInt64(h.NextHeaderOffset));
RINOK(WriteDirectUInt64(h.NextHeaderSize));
RINOK(WriteDirectUInt32(h.NextHeaderCRC));
RINOK(WriteDirectUInt64(h.ArchiveStartOffset));
return WriteDirectUInt64(h.AdditionalStartBlockSize);
}
#endif
HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker)
{
Close();
#ifdef _7Z_VOL
// endMarker = false;
_endMarker = endMarker;
#endif
SeqStream = stream;
if (!endMarker)
{
SeqStream.QueryInterface(IID_IOutStream, &Stream);
if (!Stream)
{
return E_NOTIMPL;
// endMarker = true;
}
}
#ifdef _7Z_VOL
if (endMarker)
{
/*
CStartHeader sh;
sh.NextHeaderOffset = (UInt32)(Int32)-1;
sh.NextHeaderSize = (UInt32)(Int32)-1;
sh.NextHeaderCRC = 0;
WriteStartHeader(sh);
*/
}
else
#endif
{
if (!Stream)
return E_FAIL;
RINOK(WriteSignature());
RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos));
}
return S_OK;
}
void COutArchive::Close()
{
SeqStream.Release();
Stream.Release();
}
HRESULT COutArchive::SkipPrefixArchiveHeader()
{
#ifdef _7Z_VOL
if (_endMarker)
return S_OK;
#endif
Byte buf[24];
memset(buf, 0, 24);
return WriteDirect(buf, 24);
}
UInt64 COutArchive::GetPos() const
{
if (_countMode)
return _countSize;
if (_writeToStream)
return _outByte.GetProcessedSize();
return _outByte2.GetPos();
}
void COutArchive::WriteBytes(const void *data, size_t size)
{
if (_countMode)
_countSize += size;
else if (_writeToStream)
{
_outByte.WriteBytes(data, size);
_crc = CrcUpdate(_crc, data, size);
}
else
_outByte2.WriteBytes(data, size);
}
void COutArchive::WriteByte(Byte b)
{
if (_countMode)
_countSize++;
else if (_writeToStream)
{
_outByte.WriteByte(b);
_crc = CRC_UPDATE_BYTE(_crc, b);
}
else
_outByte2.WriteByte(b);
}
void COutArchive::WriteUInt32(UInt32 value)
{
for (int i = 0; i < 4; i++)
{
WriteByte((Byte)value);
value >>= 8;
}
}
void COutArchive::WriteUInt64(UInt64 value)
{
for (int i = 0; i < 8; i++)
{
WriteByte((Byte)value);
value >>= 8;
}
}
void COutArchive::WriteNumber(UInt64 value)
{
Byte firstByte = 0;
Byte mask = 0x80;
int i;
for (i = 0; i < 8; i++)
{
if (value < ((UInt64(1) << ( 7 * (i + 1)))))
{
firstByte |= Byte(value >> (8 * i));
break;
}
firstByte |= mask;
mask = (Byte)(mask >> 1);
}
WriteByte(firstByte);
for (; i > 0; i--)
{
WriteByte((Byte)value);
value >>= 8;
}
}
static unsigned GetBigNumberSize(UInt64 value)
{
unsigned i;
for (i = 1; i < 9; i++)
if (value < (((UInt64)1 << (i * 7))))
break;
return i;
}
#ifdef _7Z_VOL
UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props)
{
UInt32 result = GetBigNumberSize(dataSize) * 2 + 41;
if (nameLength != 0)
{
nameLength = (nameLength + 1) * 2;
result += nameLength + GetBigNumberSize(nameLength) + 2;
}
if (props)
{
result += 20;
}
if (result >= 128)
result++;
result += kSignatureSize + 2 + kFinishHeaderSize;
return result;
}
UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props)
{
UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props);
int testSize;
if (volSize > headersSizeBase)
testSize = volSize - headersSizeBase;
else
testSize = 1;
UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props);
UInt64 pureSize = 1;
if (volSize > headersSize)
pureSize = volSize - headersSize;
return pureSize;
}
#endif
void COutArchive::WriteFolder(const CFolder &folder)
{
WriteNumber(folder.Coders.Size());
unsigned i;
for (i = 0; i < folder.Coders.Size(); i++)
{
const CCoderInfo &coder = folder.Coders[i];
{
UInt64 id = coder.MethodID;
unsigned idSize;
for (idSize = 1; idSize < sizeof(id); idSize++)
if ((id >> (8 * idSize)) == 0)
break;
// idSize &= 0xF; // idSize is smaller than 16 already
Byte temp[16];
for (unsigned t = idSize; t != 0; t--, id >>= 8)
temp[t] = (Byte)(id & 0xFF);
unsigned b = idSize;
const bool isComplex = !coder.IsSimpleCoder();
b |= (isComplex ? 0x10 : 0);
const size_t propsSize = coder.Props.Size();
b |= ((propsSize != 0) ? 0x20 : 0);
temp[0] = (Byte)b;
WriteBytes(temp, idSize + 1);
if (isComplex)
{
WriteNumber(coder.NumStreams);
WriteNumber(1); // NumOutStreams;
}
if (propsSize == 0)
continue;
WriteNumber(propsSize);
WriteBytes(coder.Props, propsSize);
}
}
for (i = 0; i < folder.Bonds.Size(); i++)
{
const CBond &bond = folder.Bonds[i];
WriteNumber(bond.PackIndex);
WriteNumber(bond.UnpackIndex);
}
if (folder.PackStreams.Size() > 1)
for (i = 0; i < folder.PackStreams.Size(); i++)
WriteNumber(folder.PackStreams[i]);
}
void COutArchive::WriteBoolVector(const CBoolVector &boolVector)
{
Byte b = 0;
Byte mask = 0x80;
FOR_VECTOR (i, boolVector)
{
if (boolVector[i])
b |= mask;
mask = (Byte)(mask >> 1);
if (mask == 0)
{
WriteByte(b);
mask = 0x80;
b = 0;
}
}
if (mask != 0x80)
WriteByte(b);
}
static inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; }
void COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector)
{
WriteByte(id);
WriteNumber(Bv_GetSizeInBytes(boolVector));
WriteBoolVector(boolVector);
}
unsigned BoolVector_CountSum(const CBoolVector &v);
void COutArchive::WriteHashDigests(const CUInt32DefVector &digests)
{
const unsigned numDefined = BoolVector_CountSum(digests.Defs);
if (numDefined == 0)
return;
WriteByte(NID::kCRC);
if (numDefined == digests.Defs.Size())
WriteByte(1);
else
{
WriteByte(0);
WriteBoolVector(digests.Defs);
}
for (unsigned i = 0; i < digests.Defs.Size(); i++)
if (digests.Defs[i])
WriteUInt32(digests.Vals[i]);
}
void COutArchive::WritePackInfo(
UInt64 dataOffset,
const CRecordVector<UInt64> &packSizes,
const CUInt32DefVector &packCRCs)
{
if (packSizes.IsEmpty())
return;
WriteByte(NID::kPackInfo);
WriteNumber(dataOffset);
WriteNumber(packSizes.Size());
WriteByte(NID::kSize);
FOR_VECTOR (i, packSizes)
WriteNumber(packSizes[i]);
WriteHashDigests(packCRCs);
WriteByte(NID::kEnd);
}
void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders, const COutFolders &outFolders)
{
if (folders.IsEmpty())
return;
WriteByte(NID::kUnpackInfo);
WriteByte(NID::kFolder);
WriteNumber(folders.Size());
{
WriteByte(0);
FOR_VECTOR (i, folders)
WriteFolder(folders[i]);
}
WriteByte(NID::kCodersUnpackSize);
FOR_VECTOR (i, outFolders.CoderUnpackSizes)
WriteNumber(outFolders.CoderUnpackSizes[i]);
WriteHashDigests(outFolders.FolderUnpackCRCs);
WriteByte(NID::kEnd);
}
void COutArchive::WriteSubStreamsInfo(const CObjectVector<CFolder> &folders,
const COutFolders &outFolders,
const CRecordVector<UInt64> &unpackSizes,
const CUInt32DefVector &digests)
{
const CRecordVector<CNum> &numUnpackStreamsInFolders = outFolders.NumUnpackStreamsVector;
WriteByte(NID::kSubStreamsInfo);
unsigned i;
for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
if (numUnpackStreamsInFolders[i] != 1)
{
WriteByte(NID::kNumUnpackStream);
for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
WriteNumber(numUnpackStreamsInFolders[i]);
break;
}
for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
if (numUnpackStreamsInFolders[i] > 1)
{
WriteByte(NID::kSize);
CNum index = 0;
for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
{
CNum num = numUnpackStreamsInFolders[i];
for (CNum j = 0; j < num; j++)
{
if (j + 1 != num)
WriteNumber(unpackSizes[index]);
index++;
}
}
break;
}
CUInt32DefVector digests2;
unsigned digestIndex = 0;
for (i = 0; i < folders.Size(); i++)
{
unsigned numSubStreams = (unsigned)numUnpackStreamsInFolders[i];
if (numSubStreams == 1 && outFolders.FolderUnpackCRCs.ValidAndDefined(i))
digestIndex++;
else
for (unsigned j = 0; j < numSubStreams; j++, digestIndex++)
{
digests2.Defs.Add(digests.Defs[digestIndex]);
digests2.Vals.Add(digests.Vals[digestIndex]);
}
}
WriteHashDigests(digests2);
WriteByte(NID::kEnd);
}
// 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field.
void COutArchive::SkipToAligned(unsigned pos, unsigned alignShifts)
{
if (!_useAlign)
return;
const unsigned alignSize = (unsigned)1 << alignShifts;
pos += (unsigned)GetPos();
pos &= (alignSize - 1);
if (pos == 0)
return;
unsigned skip = alignSize - pos;
if (skip < 2)
skip += alignSize;
skip -= 2;
WriteByte(NID::kDummy);
WriteByte((Byte)skip);
for (unsigned i = 0; i < skip; i++)
WriteByte(0);
}
void COutArchive::WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts)
{
const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v);
const UInt64 dataSize = ((UInt64)numDefined << itemSizeShifts) + bvSize + 2;
SkipToAligned(3 + bvSize + GetBigNumberSize(dataSize), itemSizeShifts);
WriteByte(type);
WriteNumber(dataSize);
if (numDefined == v.Size())
WriteByte(1);
else
{
WriteByte(0);
WriteBoolVector(v);
}
WriteByte(0); // 0 means no switching to external stream
}
void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type)
{
const unsigned numDefined = BoolVector_CountSum(v.Defs);
if (numDefined == 0)
return;
WriteAlignedBools(v.Defs, numDefined, type, 3);
for (unsigned i = 0; i < v.Defs.Size(); i++)
if (v.Defs[i])
WriteUInt64(v.Vals[i]);
}
HRESULT COutArchive::EncodeStream(
DECL_EXTERNAL_CODECS_LOC_VARS
CEncoder &encoder, const CByteBuffer &data,
CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders)
{
CBufInStream *streamSpec = new CBufInStream;
CMyComPtr<ISequentialInStream> stream = streamSpec;
streamSpec->Init(data, data.Size());
outFolders.FolderUnpackCRCs.Defs.Add(true);
outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size()));
// outFolders.NumUnpackStreamsVector.Add(1);
UInt64 dataSize64 = data.Size();
UInt64 unpackSize = data.Size();
RINOK(encoder.Encode(
EXTERNAL_CODECS_LOC_VARS
stream,
// NULL,
&dataSize64,
folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL))
return S_OK;
}
void COutArchive::WriteHeader(
const CArchiveDatabaseOut &db,
// const CHeaderOptions &headerOptions,
UInt64 &headerOffset)
{
/*
bool thereIsSecure = (db.SecureBuf.Size() != 0);
*/
_useAlign = true;
{
UInt64 packSize = 0;
FOR_VECTOR (i, db.PackSizes)
packSize += db.PackSizes[i];
headerOffset = packSize;
}
WriteByte(NID::kHeader);
/*
{
// It's example for per archive properies writing
WriteByte(NID::kArchiveProperties);
// you must use random 40-bit number that will identify you
// then you can use same kDeveloperID for any properties and methods
const UInt64 kDeveloperID = 0x123456789A; // change that value to real random 40-bit number
#define GENERATE_7Z_ID(developerID, subID) (((UInt64)0x3F << 56) | ((UInt64)developerID << 16) | subID)
{
const UInt64 kSubID = 0x1; // you can use small number for subID
const UInt64 kID = GENERATE_7Z_ID(kDeveloperID, kSubID);
WriteNumber(kID);
const unsigned kPropsSize = 3; // it's example size
WriteNumber(kPropsSize);
for (unsigned i = 0; i < kPropsSize; i++)
WriteByte((Byte)(i & 0xFF));
}
{
const UInt64 kSubID = 0x2; // you can use small number for subID
const UInt64 kID = GENERATE_7Z_ID(kDeveloperID, kSubID);
WriteNumber(kID);
const unsigned kPropsSize = 5; // it's example size
WriteNumber(kPropsSize);
for (unsigned i = 0; i < kPropsSize; i++)
WriteByte((Byte)(i + 16));
}
WriteByte(NID::kEnd);
}
*/
if (db.Folders.Size() > 0)
{
WriteByte(NID::kMainStreamsInfo);
WritePackInfo(0, db.PackSizes, db.PackCRCs);
WriteUnpackInfo(db.Folders, (const COutFolders &)db);
CRecordVector<UInt64> unpackSizes;
CUInt32DefVector digests;
FOR_VECTOR (i, db.Files)
{
const CFileItem &file = db.Files[i];
if (!file.HasStream)
continue;
unpackSizes.Add(file.Size);
digests.Defs.Add(file.CrcDefined);
digests.Vals.Add(file.Crc);
}
WriteSubStreamsInfo(db.Folders, (const COutFolders &)db, unpackSizes, digests);
WriteByte(NID::kEnd);
}
if (db.Files.IsEmpty())
{
WriteByte(NID::kEnd);
return;
}
WriteByte(NID::kFilesInfo);
WriteNumber(db.Files.Size());
{
/* ---------- Empty Streams ---------- */
CBoolVector emptyStreamVector;
emptyStreamVector.ClearAndSetSize(db.Files.Size());
unsigned numEmptyStreams = 0;
{
FOR_VECTOR (i, db.Files)
if (db.Files[i].HasStream)
emptyStreamVector[i] = false;
else
{
emptyStreamVector[i] = true;
numEmptyStreams++;
}
}
if (numEmptyStreams != 0)
{
WritePropBoolVector(NID::kEmptyStream, emptyStreamVector);
CBoolVector emptyFileVector, antiVector;
emptyFileVector.ClearAndSetSize(numEmptyStreams);
antiVector.ClearAndSetSize(numEmptyStreams);
bool thereAreEmptyFiles = false, thereAreAntiItems = false;
unsigned cur = 0;
FOR_VECTOR (i, db.Files)
{
const CFileItem &file = db.Files[i];
if (file.HasStream)
continue;
emptyFileVector[cur] = !file.IsDir;
if (!file.IsDir)
thereAreEmptyFiles = true;
bool isAnti = db.IsItemAnti(i);
antiVector[cur] = isAnti;
if (isAnti)
thereAreAntiItems = true;
cur++;
}
if (thereAreEmptyFiles)
WritePropBoolVector(NID::kEmptyFile, emptyFileVector);
if (thereAreAntiItems)
WritePropBoolVector(NID::kAnti, antiVector);
}
}
{
/* ---------- Names ---------- */
unsigned numDefined = 0;
size_t namesDataSize = 0;
FOR_VECTOR (i, db.Files)
{
const UString &name = db.Names[i];
if (!name.IsEmpty())
numDefined++;
const size_t numUtfChars =
/*
#if WCHAR_MAX > 0xffff
Get_Num_Utf16_chars_from_wchar_string(name.Ptr());
#else
*/
name.Len();
// #endif
namesDataSize += (numUtfChars + 1) * 2;
}
if (numDefined > 0)
{
namesDataSize++;
SkipToAligned(2 + GetBigNumberSize(namesDataSize), 4);
WriteByte(NID::kName);
WriteNumber(namesDataSize);
WriteByte(0);
FOR_VECTOR (i, db.Files)
{
const UString &name = db.Names[i];
for (unsigned t = 0; t <= name.Len(); t++)
{
wchar_t c = name[t];
/*
#if WCHAR_MAX > 0xffff
if (c >= 0x10000)
{
c -= 0x10000;
if (c < (1 << 20))
{
unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF);
WriteByte((Byte)c0);
WriteByte((Byte)(c0 >> 8));
c = 0xdc00 + (c & 0x3FF);
}
else
c = '_'; // we change character unsupported by UTF16
}
#endif
*/
WriteByte((Byte)c);
WriteByte((Byte)(c >> 8));
}
}
}
}
/* if (headerOptions.WriteCTime) */ WriteUInt64DefVector(db.CTime, NID::kCTime);
/* if (headerOptions.WriteATime) */ WriteUInt64DefVector(db.ATime, NID::kATime);
/* if (headerOptions.WriteMTime) */ WriteUInt64DefVector(db.MTime, NID::kMTime);
WriteUInt64DefVector(db.StartPos, NID::kStartPos);
{
/* ---------- Write Attrib ---------- */
const unsigned numDefined = BoolVector_CountSum(db.Attrib.Defs);
if (numDefined != 0)
{
WriteAlignedBools(db.Attrib.Defs, numDefined, NID::kWinAttrib, 2);
FOR_VECTOR (i, db.Attrib.Defs)
{
if (db.Attrib.Defs[i])
WriteUInt32(db.Attrib.Vals[i]);
}
}
}
/*
{
// ---------- Write IsAux ----------
if (BoolVector_CountSum(db.IsAux) != 0)
WritePropBoolVector(NID::kIsAux, db.IsAux);
}
{
// ---------- Write Parent ----------
CBoolVector boolVector;
boolVector.Reserve(db.Files.Size());
unsigned numIsDir = 0;
unsigned numParentLinks = 0;
for (i = 0; i < db.Files.Size(); i++)
{
const CFileItem &file = db.Files[i];
bool defined = !file.IsAltStream;
boolVector.Add(defined);
if (defined)
numIsDir++;
if (file.Parent >= 0)
numParentLinks++;
}
if (numParentLinks > 0)
{
// WriteAlignedBools(boolVector, numDefined, NID::kParent, 2);
const unsigned bvSize = (numIsDir == boolVector.Size()) ? 0 : Bv_GetSizeInBytes(boolVector);
const UInt64 dataSize = (UInt64)db.Files.Size() * 4 + bvSize + 1;
SkipToAligned(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 2);
WriteByte(NID::kParent);
WriteNumber(dataSize);
if (numIsDir == boolVector.Size())
WriteByte(1);
else
{
WriteByte(0);
WriteBoolVector(boolVector);
}
for (i = 0; i < db.Files.Size(); i++)
{
const CFileItem &file = db.Files[i];
// if (file.Parent >= 0)
WriteUInt32(file.Parent);
}
}
}
if (thereIsSecure)
{
UInt64 secureDataSize = 1 + 4 +
db.SecureBuf.Size() +
db.SecureSizes.Size() * 4;
// secureDataSize += db.SecureIDs.Size() * 4;
for (i = 0; i < db.SecureIDs.Size(); i++)
secureDataSize += GetBigNumberSize(db.SecureIDs[i]);
SkipToAligned(2 + GetBigNumberSize(secureDataSize), 2);
WriteByte(NID::kNtSecure);
WriteNumber(secureDataSize);
WriteByte(0);
WriteUInt32(db.SecureSizes.Size());
for (i = 0; i < db.SecureSizes.Size(); i++)
WriteUInt32(db.SecureSizes[i]);
WriteBytes(db.SecureBuf, db.SecureBuf.Size());
for (i = 0; i < db.SecureIDs.Size(); i++)
{
WriteNumber(db.SecureIDs[i]);
// WriteUInt32(db.SecureIDs[i]);
}
}
*/
WriteByte(NID::kEnd); // for files
WriteByte(NID::kEnd); // for headers
}
HRESULT COutArchive::WriteDatabase(
DECL_EXTERNAL_CODECS_LOC_VARS
const CArchiveDatabaseOut &db,
const CCompressionMethodMode *options,
const CHeaderOptions &headerOptions)
{
if (!db.CheckNumFiles())
return E_FAIL;
UInt64 headerOffset;
UInt32 headerCRC;
UInt64 headerSize;
if (db.IsEmpty())
{
headerSize = 0;
headerOffset = 0;
headerCRC = CrcCalc(0, 0);
}
else
{
bool encodeHeaders = false;
if (options != 0)
if (options->IsEmpty())
options = 0;
if (options != 0)
if (options->PasswordIsDefined || headerOptions.CompressMainHeader)
encodeHeaders = true;
_outByte.SetStream(SeqStream);
_outByte.Init();
_crc = CRC_INIT_VAL;
_countMode = encodeHeaders;
_writeToStream = true;
_countSize = 0;
WriteHeader(db, /* headerOptions, */ headerOffset);
if (encodeHeaders)
{
CByteBuffer buf(_countSize);
_outByte2.Init((Byte *)buf, _countSize);
_countMode = false;
_writeToStream = false;
WriteHeader(db, /* headerOptions, */ headerOffset);
if (_countSize != _outByte2.GetPos())
return E_FAIL;
CCompressionMethodMode encryptOptions;
encryptOptions.PasswordIsDefined = options->PasswordIsDefined;
encryptOptions.Password = options->Password;
CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions);
CRecordVector<UInt64> packSizes;
CObjectVector<CFolder> folders;
COutFolders outFolders;
RINOK(EncodeStream(
EXTERNAL_CODECS_LOC_VARS
encoder, buf,
packSizes, folders, outFolders));
_writeToStream = true;
if (folders.Size() == 0)
throw 1;
WriteID(NID::kEncodedHeader);
WritePackInfo(headerOffset, packSizes, CUInt32DefVector());
WriteUnpackInfo(folders, outFolders);
WriteByte(NID::kEnd);
FOR_VECTOR (i, packSizes)
headerOffset += packSizes[i];
}
RINOK(_outByte.Flush());
headerCRC = CRC_GET_DIGEST(_crc);
headerSize = _outByte.GetProcessedSize();
}
#ifdef _7Z_VOL
if (_endMarker)
{
CFinishHeader h;
h.NextHeaderSize = headerSize;
h.NextHeaderCRC = headerCRC;
h.NextHeaderOffset =
UInt64(0) - (headerSize +
4 + kFinishHeaderSize);
h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset;
h.AdditionalStartBlockSize = 0;
RINOK(WriteFinishHeader(h));
return WriteFinishSignature();
}
else
#endif
{
CStartHeader h;
h.NextHeaderSize = headerSize;
h.NextHeaderCRC = headerCRC;
h.NextHeaderOffset = headerOffset;
RINOK(Stream->Seek((Int64)_prefixHeaderPos, STREAM_SEEK_SET, NULL));
return WriteStartHeader(h);
}
}
void CUInt32DefVector::SetItem(unsigned index, bool defined, UInt32 value)
{
while (index >= Defs.Size())
Defs.Add(false);
Defs[index] = defined;
if (!defined)
return;
while (index >= Vals.Size())
Vals.Add(0);
Vals[index] = value;
}
void CUInt64DefVector::SetItem(unsigned index, bool defined, UInt64 value)
{
while (index >= Defs.Size())
Defs.Add(false);
Defs[index] = defined;
if (!defined)
return;
while (index >= Vals.Size())
Vals.Add(0);
Vals[index] = value;
}
void CArchiveDatabaseOut::AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name)
{
unsigned index = Files.Size();
CTime.SetItem(index, file2.CTimeDefined, file2.CTime);
ATime.SetItem(index, file2.ATimeDefined, file2.ATime);
MTime.SetItem(index, file2.MTimeDefined, file2.MTime);
StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos);
Attrib.SetItem(index, file2.AttribDefined, file2.Attrib);
SetItem_Anti(index, file2.IsAnti);
// SetItem_Aux(index, file2.IsAux);
Names.Add(name);
Files.Add(file);
}
}}

View File

@@ -0,0 +1,335 @@
// 7zOut.h
#ifndef __7Z_OUT_H
#define __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 {
class CWriteBufferLoc
{
Byte *_data;
size_t _size;
size_t _pos;
public:
CWriteBufferLoc(): _size(0), _pos(0) {}
void Init(Byte *data, size_t size)
{
_data = data;
_size = size;
_pos = 0;
}
void WriteBytes(const void *data, size_t size)
{
if (size == 0)
return;
if (size > _size - _pos)
throw 1;
memcpy(_data + _pos, data, size);
_pos += size;
}
void WriteByte(Byte b)
{
if (_size == _pos)
throw 1;
_data[_pos++] = b;
}
size_t GetPos() const { return _pos; }
};
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
{
UInt64 _prefixHeaderPos;
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 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 WriteBoolVector(const CBoolVector &boolVector);
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 WriteUInt64DefVector(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;
size_t _countSize;
UInt32 _crc;
COutBuffer _outByte;
CWriteBufferLoc _outByte2;
#ifdef _7Z_VOL
bool _endMarker;
#endif
bool _useAlign;
HRESULT WriteSignature();
#ifdef _7Z_VOL
HRESULT WriteFinishSignature();
#endif
HRESULT WriteStartHeader(const CStartHeader &h);
#ifdef _7Z_VOL
HRESULT WriteFinishHeader(const CFinishHeader &h);
#endif
CMyComPtr<IOutStream> Stream;
public:
COutArchive() { _outByte.Create(1 << 16); }
CMyComPtr<ISequentialOutStream> SeqStream;
HRESULT Create(ISequentialOutStream *stream, bool endMarker);
void Close();
HRESULT SkipPrefixArchiveHeader();
HRESULT WriteDatabase(
DECL_EXTERNAL_CODECS_LOC_VARS
const CArchiveDatabaseOut &db,
const CCompressionMethodMode *options,
const CHeaderOptions &headerOptions);
#ifdef _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

View File

@@ -0,0 +1,174 @@
// 7zProperties.cpp
#include "StdAfx.h"
#include "7zProperties.h"
#include "7zHeader.h"
#include "7zHandler.h"
// #define _MULTI_PACK
namespace NArchive {
namespace N7z {
struct CPropMap
{
UInt32 FilePropID;
CStatProp StatProp;
};
static const CPropMap kPropMap[] =
{
{ NID::kName, { NULL, kpidPath, VT_BSTR } },
{ NID::kSize, { NULL, kpidSize, VT_UI8 } },
{ NID::kPackInfo, { NULL, kpidPackSize, VT_UI8 } },
#ifdef _MULTI_PACK
{ 100, { "Pack0", kpidPackedSize0, VT_UI8 } },
{ 101, { "Pack1", kpidPackedSize1, VT_UI8 } },
{ 102, { "Pack2", kpidPackedSize2, VT_UI8 } },
{ 103, { "Pack3", kpidPackedSize3, VT_UI8 } },
{ 104, { "Pack4", kpidPackedSize4, VT_UI8 } },
#endif
{ NID::kCTime, { NULL, kpidCTime, VT_FILETIME } },
{ NID::kMTime, { NULL, kpidMTime, VT_FILETIME } },
{ NID::kATime, { NULL, kpidATime, VT_FILETIME } },
{ NID::kWinAttrib, { NULL, kpidAttrib, VT_UI4 } },
{ NID::kStartPos, { NULL, kpidPosition, VT_UI8 } },
{ NID::kCRC, { NULL, kpidCRC, VT_UI4 } },
// { NID::kIsAux, { NULL, kpidIsAux, VT_BOOL } },
{ NID::kAnti, { NULL, kpidIsAnti, VT_BOOL } }
#ifndef _SFX
,
{ 97, { NULL, kpidEncrypted, VT_BOOL } },
{ 98, { NULL, kpidMethod, VT_BSTR } },
{ 99, { NULL, kpidBlock, VT_UI4 } }
#endif
};
static void CopyOneItem(CRecordVector<UInt64> &src,
CRecordVector<UInt64> &dest, UInt32 item)
{
FOR_VECTOR (i, src)
if (src[i] == item)
{
dest.Add(item);
src.Delete(i);
return;
}
}
static void RemoveOneItem(CRecordVector<UInt64> &src, UInt32 item)
{
FOR_VECTOR (i, src)
if (src[i] == item)
{
src.Delete(i);
return;
}
}
static void InsertToHead(CRecordVector<UInt64> &dest, 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 _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 _SFX
_fileInfoPopIDs.Add(97);
_fileInfoPopIDs.Add(98);
_fileInfoPopIDs.Add(99);
#endif
#ifdef _MULTI_PACK
_fileInfoPopIDs.Add(100);
_fileInfoPopIDs.Add(101);
_fileInfoPopIDs.Add(102);
_fileInfoPopIDs.Add(103);
_fileInfoPopIDs.Add(104);
#endif
#ifndef _SFX
InsertToHead(_fileInfoPopIDs, NID::kMTime);
InsertToHead(_fileInfoPopIDs, NID::kPackInfo);
InsertToHead(_fileInfoPopIDs, NID::kSize);
InsertToHead(_fileInfoPopIDs, NID::kName);
#endif
}
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps)
{
*numProps = _fileInfoPopIDs.Size();
return S_OK;
}
STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)
{
if (index >= _fileInfoPopIDs.Size())
return E_INVALIDARG;
UInt64 id = _fileInfoPopIDs[index];
for (unsigned i = 0; i < ARRAY_SIZE(kPropMap); i++)
{
const CPropMap &pr = kPropMap[i];
if (pr.FilePropID == id)
{
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;
}
}}

View File

@@ -0,0 +1,22 @@
// 7zProperties.h
#ifndef __7Z_PROPERTIES_H
#define __7Z_PROPERTIES_H
#include "../../PropID.h"
namespace NArchive {
namespace N7z {
enum
{
kpidPackedSize0 = kpidUserDefined,
kpidPackedSize1,
kpidPackedSize2,
kpidPackedSize3,
kpidPackedSize4
};
}}
#endif

View File

@@ -0,0 +1,21 @@
// 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,
NULL);
}}

View File

@@ -0,0 +1,22 @@
// 7zSpecStream.cpp
#include "StdAfx.h"
#include "7zSpecStream.h"
STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 realProcessedSize;
HRESULT result = _stream->Read(data, size, &realProcessedSize);
_size += realProcessedSize;
if (processedSize)
*processedSize = realProcessedSize;
return result;
}
STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize(UInt64 subStream, UInt64 *value)
{
if (!_getSubStreamSize)
return E_NOTIMPL;
return _getSubStreamSize->GetSubStreamSize(subStream, value);
}

View File

@@ -0,0 +1,35 @@
// 7zSpecStream.h
#ifndef __7Z_SPEC_STREAM_H
#define __7Z_SPEC_STREAM_H
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
class CSequentialInStreamSizeCount2:
public ISequentialInStream,
public ICompressGetSubStreamSize,
public CMyUnknownImp
{
CMyComPtr<ISequentialInStream> _stream;
CMyComPtr<ICompressGetSubStreamSize> _getSubStreamSize;
UInt64 _size;
public:
void Init(ISequentialInStream *stream)
{
_size = 0;
_getSubStreamSize.Release();
_stream = stream;
_stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);
}
UInt64 GetSize() const { return _size; }
MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,139 @@
// 7zUpdate.h
#ifndef __7Z_UPDATE_H
#define __7Z_UPDATE_H
#include "../IArchive.h"
// #include "../../Common/UniqBlocks.h"
#include "7zCompressionMode.h"
#include "7zIn.h"
#include "7zOut.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;
// 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)
// 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;
CHeaderOptions HeaderOptions;
UInt64 NumSolidFiles;
UInt64 NumSolidBytes;
bool SolidExtension;
bool UseTypeSorting;
bool RemoveSfxBlock;
bool MultiThreadMixer;
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)
{}
};
HRESULT Update(
DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream,
const CDbEx *db,
const CObjectVector<CUpdateItem> &updateItems,
// const CObjectVector<CTreeFolder> &treeFolders, // treeFolders[0] is root
// const CUniqBlocks &secureBlocks,
COutArchive &archive,
CArchiveDatabaseOut &newDatabase,
ISequentialOutStream *seqOutStream,
IArchiveUpdateCallback *updateCallback,
const CUpdateOptions &options
#ifndef _NO_CRYPTO
, ICryptoGetTextPassword *getDecoderPassword
#endif
);
}}
#endif

View File

@@ -0,0 +1,3 @@
// StdAfx.cpp
#include "StdAfx.h"

View File

@@ -0,0 +1,8 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/Common.h"
#endif

View File

@@ -0,0 +1,12 @@
EXPORTS
CreateObject PRIVATE
GetHandlerProperty PRIVATE
GetNumberOfFormats PRIVATE
GetHandlerProperty2 PRIVATE
GetIsArc PRIVATE
SetCodecs PRIVATE
SetLargePageMode PRIVATE
SetCaseSensitive PRIVATE

View File

@@ -0,0 +1,19 @@
EXPORTS
CreateObject PRIVATE
GetHandlerProperty PRIVATE
GetNumberOfFormats PRIVATE
GetHandlerProperty2 PRIVATE
GetIsArc PRIVATE
GetNumberOfMethods PRIVATE
GetMethodProperty PRIVATE
CreateDecoder PRIVATE
CreateEncoder PRIVATE
GetHashers PRIVATE
SetCodecs PRIVATE
SetLargePageMode PRIVATE
SetCaseSensitive PRIVATE

View File

@@ -0,0 +1,156 @@
// ArchiveExports.cpp
#include "StdAfx.h"
#include "../../../C/7zVersion.h"
#include "../../Common/ComTry.h"
#include "../../Windows/PropVariant.h"
#include "../Common/RegisterArc.h"
static const unsigned kNumArcsMax = 64;
static unsigned g_NumArcs = 0;
static unsigned g_DefaultArcIndex = 0;
static const CArcInfo *g_Arcs[kNumArcsMax];
void RegisterArc(const CArcInfo *arcInfo) throw()
{
if (g_NumArcs < kNumArcsMax)
{
const char *p = arcInfo->Name;
if (p[0] == '7' && p[1] == 'z' && p[2] == 0)
g_DefaultArcIndex = g_NumArcs;
g_Arcs[g_NumArcs++] = arcInfo;
}
}
DEFINE_GUID(CLSID_CArchiveHandler,
k_7zip_GUID_Data1,
k_7zip_GUID_Data2,
k_7zip_GUID_Data3_Common,
0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
#define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5])
static inline HRESULT SetPropStrFromBin(const char *s, unsigned size, PROPVARIANT *value)
{
if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)
value->vt = VT_BSTR;
return S_OK;
}
static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
{
return SetPropStrFromBin((const char *)&guid, sizeof(guid), value);
}
static int FindFormatCalssId(const GUID *clsid)
{
GUID cls = *clsid;
CLS_ARC_ID_ITEM(cls) = 0;
if (cls != CLSID_CArchiveHandler)
return -1;
Byte id = CLS_ARC_ID_ITEM(*clsid);
for (unsigned i = 0; i < g_NumArcs; i++)
if (g_Arcs[i]->Id == id)
return (int)i;
return -1;
}
STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject);
STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject)
{
COM_TRY_BEGIN
{
int needIn = (*iid == IID_IInArchive);
int needOut = (*iid == IID_IOutArchive);
if (!needIn && !needOut)
return E_NOINTERFACE;
int formatIndex = FindFormatCalssId(clsid);
if (formatIndex < 0)
return CLASS_E_CLASSNOTAVAILABLE;
const CArcInfo &arc = *g_Arcs[formatIndex];
if (needIn)
{
*outObject = arc.CreateInArchive();
((IInArchive *)*outObject)->AddRef();
}
else
{
if (!arc.CreateOutArchive)
return CLASS_E_CLASSNOTAVAILABLE;
*outObject = arc.CreateOutArchive();
((IOutArchive *)*outObject)->AddRef();
}
}
COM_TRY_END
return S_OK;
}
STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value);
STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::PropVariant_Clear(value);
if (formatIndex >= g_NumArcs)
return E_INVALIDARG;
const CArcInfo &arc = *g_Arcs[formatIndex];
NWindows::NCOM::CPropVariant prop;
switch (propID)
{
case NArchive::NHandlerPropID::kName: prop = arc.Name; break;
case NArchive::NHandlerPropID::kClassID:
{
GUID clsId = CLSID_CArchiveHandler;
CLS_ARC_ID_ITEM(clsId) = arc.Id;
return SetPropGUID(clsId, value);
}
case NArchive::NHandlerPropID::kExtension: if (arc.Ext) prop = arc.Ext; break;
case NArchive::NHandlerPropID::kAddExtension: if (arc.AddExt) prop = arc.AddExt; break;
case NArchive::NHandlerPropID::kUpdate: prop = (bool)(arc.CreateOutArchive != NULL); break;
case NArchive::NHandlerPropID::kKeepName: prop = ((arc.Flags & NArcInfoFlags::kKeepName) != 0); break;
case NArchive::NHandlerPropID::kAltStreams: prop = ((arc.Flags & NArcInfoFlags::kAltStreams) != 0); break;
case NArchive::NHandlerPropID::kNtSecure: prop = ((arc.Flags & NArcInfoFlags::kNtSecure) != 0); break;
case NArchive::NHandlerPropID::kFlags: prop = (UInt32)arc.Flags; break;
case NArchive::NHandlerPropID::kSignatureOffset: prop = (UInt32)arc.SignatureOffset; break;
// case NArchive::NHandlerPropID::kVersion: prop = (UInt32)MY_VER_MIX; break;
case NArchive::NHandlerPropID::kSignature:
if (arc.SignatureSize != 0 && !arc.IsMultiSignature())
return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value);
break;
case NArchive::NHandlerPropID::kMultiSignature:
if (arc.SignatureSize != 0 && arc.IsMultiSignature())
return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value);
break;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value);
STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
{
return GetHandlerProperty2(g_DefaultArcIndex, propID, value);
}
STDAPI GetNumberOfFormats(UINT32 *numFormats);
STDAPI GetNumberOfFormats(UINT32 *numFormats)
{
*numFormats = g_NumArcs;
return S_OK;
}
STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc);
STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc)
{
*isArc = NULL;
if (formatIndex >= g_NumArcs)
return E_INVALIDARG;
*isArc = g_Arcs[formatIndex]->IsArc;
return S_OK;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,453 @@
// CoderMixer2.h
#ifndef __CODER_MIXER2_H
#define __CODER_MIXER2_H
#include "../../../Common/MyCom.h"
#include "../../../Common/MyVector.h"
#include "../../ICoder.h"
#include "../../Common/CreateCoder.h"
#ifdef _7ZIP_ST
#define USE_MIXER_ST
#else
#define USE_MIXER_MT
#ifndef _SFX
#define USE_MIXER_ST
#endif
#endif
#ifdef USE_MIXER_MT
#include "../../Common/StreamBinder.h"
#include "../../Common/VirtThread.h"
#endif
#ifdef USE_MIXER_ST
class CSequentialInStreamCalcSize:
public ISequentialInStream,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP1(ISequentialInStream)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
private:
CMyComPtr<ISequentialInStream> _stream;
UInt64 _size;
bool _wasFinished;
public:
void SetStream(ISequentialInStream *stream) { _stream = stream; }
void Init()
{
_size = 0;
_wasFinished = false;
}
void ReleaseStream() { _stream.Release(); }
UInt64 GetSize() const { return _size; }
bool WasFinished() const { return _wasFinished; }
};
class COutStreamCalcSize:
public ISequentialOutStream,
public IOutStreamFinish,
public CMyUnknownImp
{
CMyComPtr<ISequentialOutStream> _stream;
UInt64 _size;
public:
MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFinish)
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(OutStreamFinish)();
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
void ReleaseStream() { _stream.Release(); }
void Init() { _size = 0; }
UInt64 GetSize() const { return _size; }
};
#endif
namespace NCoderMixer2 {
struct CBond
{
UInt32 PackIndex;
UInt32 UnpackIndex;
UInt32 Get_InIndex(bool encodeMode) const { return encodeMode ? UnpackIndex : PackIndex; }
UInt32 Get_OutIndex(bool encodeMode) const { return encodeMode ? PackIndex : UnpackIndex; }
};
struct CCoderStreamsInfo
{
UInt32 NumStreams;
};
struct CBindInfo
{
CRecordVector<CCoderStreamsInfo> Coders;
CRecordVector<CBond> Bonds;
CRecordVector<UInt32> PackStreams;
unsigned UnpackCoder;
unsigned GetNum_Bonds_and_PackStreams() const { return Bonds.Size() + PackStreams.Size(); }
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 (int)i;
return -1;
}
bool SetUnpackCoder()
{
bool isOk = false;
FOR_VECTOR(i, Coders)
{
if (FindBond_for_UnpackStream(i) < 0)
{
if (isOk)
return false;
UnpackCoder = i;
isOk = true;
}
}
return isOk;
}
bool IsStream_in_PackStreams(UInt32 streamIndex) const
{
return FindStream_in_PackStreams(streamIndex) >= 0;
}
int FindStream_in_PackStreams(UInt32 streamIndex) const
{
FOR_VECTOR(i, PackStreams)
if (PackStreams[i] == streamIndex)
return (int)i;
return -1;
}
// that function is used before Maps is calculated
UInt32 GetStream_for_Coder(UInt32 coderIndex) const
{
UInt32 streamIndex = 0;
for (UInt32 i = 0; i < coderIndex; i++)
streamIndex += Coders[i].NumStreams;
return streamIndex;
}
// ---------- Maps Section ----------
CRecordVector<UInt32> Coder_to_Stream;
CRecordVector<UInt32> Stream_to_Coder;
void ClearMaps();
bool CalcMapsAndCheck();
// ---------- End of Maps Section ----------
void Clear()
{
Coders.Clear();
Bonds.Clear();
PackStreams.Clear();
ClearMaps();
}
void GetCoder_for_Stream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const
{
coderIndex = Stream_to_Coder[streamIndex];
coderStreamIndex = streamIndex - Coder_to_Stream[coderIndex];
}
};
class CCoder
{
CLASS_NO_COPY(CCoder);
public:
CMyComPtr<ICompressCoder> Coder;
CMyComPtr<ICompressCoder2> Coder2;
UInt32 NumStreams;
UInt64 UnpackSize;
const UInt64 *UnpackSizePointer;
CRecordVector<UInt64> PackSizes;
CRecordVector<const UInt64 *> PackSizePointers;
bool Finish;
CCoder(): Finish(false) {}
void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish);
HRESULT CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const;
IUnknown *GetUnknown() const
{
return Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;
}
HRESULT QueryInterface(REFGUID iid, void** pp) const
{
return GetUnknown()->QueryInterface(iid, pp);
}
};
class CMixer
{
bool Is_PackSize_Correct_for_Stream(UInt32 streamIndex);
protected:
CBindInfo _bi;
int FindBond_for_Stream(bool forInputStream, UInt32 streamIndex) const
{
if (EncodeMode == forInputStream)
return _bi.FindBond_for_UnpackStream(streamIndex);
else
return _bi.FindBond_for_PackStream(streamIndex);
}
CBoolVector IsFilter_Vector;
CBoolVector IsExternal_Vector;
bool EncodeMode;
public:
unsigned MainCoderIndex;
// bool InternalPackSizeError;
CMixer(bool encodeMode):
EncodeMode(encodeMode),
MainCoderIndex(0)
// , InternalPackSizeError(false)
{}
virtual ~CMixer() {};
/*
Sequence of calling:
SetBindInfo();
for each coder
AddCoder();
SelectMainCoder();
for each file
{
ReInit()
for each coder
SetCoderInfo();
Code();
}
*/
virtual HRESULT SetBindInfo(const CBindInfo &bindInfo)
{
_bi = bindInfo;
IsFilter_Vector.Clear();
MainCoderIndex = 0;
return S_OK;
}
virtual void AddCoder(const CCreatedCoder &cod) = 0;
virtual CCoder &GetCoder(unsigned index) = 0;
virtual void SelectMainCoder(bool useFirst) = 0;
virtual HRESULT ReInit2() = 0;
virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) = 0;
virtual HRESULT Code(
ISequentialInStream * const *inStreams,
ISequentialOutStream * const *outStreams,
ICompressProgressInfo *progress,
bool &dataAfterEnd_Error) = 0;
virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0;
bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex);
bool Is_PackSize_Correct_for_Coder(UInt32 coderIndex);
bool IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex);
};
#ifdef USE_MIXER_ST
struct CCoderST: public CCoder
{
bool CanRead;
bool CanWrite;
CCoderST(): CanRead(false), CanWrite(false) {}
};
struct CStBinderStream
{
CSequentialInStreamCalcSize *InStreamSpec;
COutStreamCalcSize *OutStreamSpec;
CMyComPtr<IUnknown> StreamRef;
CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {}
};
class CMixerST:
public IUnknown,
public CMixer,
public CMyUnknownImp
{
CLASS_NO_COPY(CMixerST)
HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
UInt32 outStreamIndex, ISequentialInStream **inStreamRes);
HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
UInt32 inStreamIndex, ISequentialInStream **inStreamRes);
HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
UInt32 outStreamIndex, ISequentialOutStream **outStreamRes);
HRESULT FinishStream(UInt32 streamIndex);
HRESULT FinishCoder(UInt32 coderIndex);
public:
CObjectVector<CCoderST> _coders;
CObjectVector<CStBinderStream> _binderStreams;
MY_UNKNOWN_IMP
CMixerST(bool encodeMode);
~CMixerST();
virtual void AddCoder(const CCreatedCoder &cod);
virtual CCoder &GetCoder(unsigned index);
virtual void SelectMainCoder(bool useFirst);
virtual HRESULT ReInit2();
virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish)
{ _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }
virtual HRESULT Code(
ISequentialInStream * const *inStreams,
ISequentialOutStream * const *outStreams,
ICompressProgressInfo *progress,
bool &dataAfterEnd_Error);
virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
HRESULT GetMainUnpackStream(
ISequentialInStream * const *inStreams,
ISequentialInStream **inStreamRes);
};
#endif
#ifdef USE_MIXER_MT
class CCoderMT: public CCoder, public CVirtThread
{
CLASS_NO_COPY(CCoderMT)
CRecordVector<ISequentialInStream*> InStreamPointers;
CRecordVector<ISequentialOutStream*> OutStreamPointers;
private:
void Execute();
public:
bool EncodeMode;
HRESULT Result;
CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
void Release()
{
InStreamPointers.Clear();
OutStreamPointers.Clear();
unsigned i;
for (i = 0; i < InStreams.Size(); i++)
InStreams[i].Release();
for (i = 0; i < OutStreams.Size(); i++)
OutStreams[i].Release();
}
class CReleaser
{
CLASS_NO_COPY(CReleaser)
CCoderMT &_c;
public:
CReleaser(CCoderMT &c): _c(c) {}
~CReleaser() { _c.Release(); }
};
CCoderMT(): EncodeMode(false) {}
virtual ~CCoderMT() { CVirtThread::WaitThreadFinish(); }
void Code(ICompressProgressInfo *progress);
};
class CMixerMT:
public IUnknown,
public CMixer,
public CMyUnknownImp
{
CLASS_NO_COPY(CMixerMT)
CObjectVector<CStreamBinder> _streamBinders;
HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams);
HRESULT ReturnIfError(HRESULT code);
// virtual ~CMixerMT() {};
public:
CObjectVector<CCoderMT> _coders;
MY_UNKNOWN_IMP
virtual HRESULT SetBindInfo(const CBindInfo &bindInfo);
virtual void AddCoder(const CCreatedCoder &cod);
virtual CCoder &GetCoder(unsigned index);
virtual void SelectMainCoder(bool useFirst);
virtual HRESULT ReInit2();
virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish)
{ _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }
virtual HRESULT Code(
ISequentialInStream * const *inStreams,
ISequentialOutStream * const *outStreams,
ICompressProgressInfo *progress,
bool &dataAfterEnd_Error);
virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
CMixerMT(bool encodeMode): CMixer(encodeMode) {}
};
#endif
}
#endif

View File

@@ -0,0 +1,17 @@
// DummyOutStream.cpp
#include "StdAfx.h"
#include "DummyOutStream.h"
STDMETHODIMP CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 realProcessedSize = size;
HRESULT res = S_OK;
if (_stream)
res = _stream->Write(data, size, &realProcessedSize);
_size += realProcessedSize;
if (processedSize)
*processedSize = realProcessedSize;
return res;
}

View File

@@ -0,0 +1,25 @@
// DummyOutStream.h
#ifndef __DUMMY_OUT_STREAM_H
#define __DUMMY_OUT_STREAM_H
#include "../../../Common/MyCom.h"
#include "../../IStream.h"
class CDummyOutStream:
public ISequentialOutStream,
public CMyUnknownImp
{
CMyComPtr<ISequentialOutStream> _stream;
UInt64 _size;
public:
void SetStream(ISequentialOutStream *outStream) { _stream = outStream; }
void ReleaseStream() { _stream.Release(); }
void Init() { _size = 0; }
MY_UNKNOWN_IMP
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
UInt64 GetSize() const { return _size; }
};
#endif

View File

@@ -0,0 +1,232 @@
// HandlerOut.cpp
#include "StdAfx.h"
#include "../../../Common/StringToInt.h"
#include "../Common/ParseProperties.h"
#include "HandlerOut.h"
namespace NArchive {
bool ParseSizeString(const wchar_t *s, const PROPVARIANT &prop, UInt64 percentsBase, UInt64 &res)
{
if (*s == 0)
{
switch (prop.vt)
{
case VT_UI4: res = prop.ulVal; return true;
case VT_UI8: res = prop.uhVal.QuadPart; return true;
case VT_BSTR:
s = prop.bstrVal;
break;
default: return false;
}
}
else if (prop.vt != VT_EMPTY)
return false;
const wchar_t *end;
UInt64 v = ConvertStringToUInt64(s, &end);
if (s == end)
return false;
wchar_t c = *end;
if (c == 0)
{
res = v;
return true;
}
if (end[1] != 0)
return false;
if (c == '%')
{
res = percentsBase / 100 * v;
return true;
}
unsigned numBits;
switch (MyCharLower_Ascii(c))
{
case 'b': numBits = 0; break;
case 'k': numBits = 10; break;
case 'm': numBits = 20; break;
case 'g': numBits = 30; break;
case 't': numBits = 40; break;
default: return false;
}
UInt64 val2 = v << numBits;
if ((val2 >> numBits) != v)
return false;
res = val2;
return true;
}
bool CCommonMethodProps::SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres)
{
hres = S_OK;
if (name.IsPrefixedBy_Ascii_NoCase("mt"))
{
#ifndef _7ZIP_ST
hres = ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads);
#endif
return true;
}
if (name.IsPrefixedBy_Ascii_NoCase("memuse"))
{
if (!ParseSizeString(name.Ptr(6), value, _memAvail, _memUsage))
hres = E_INVALIDARG;
return true;
}
return false;
}
#ifndef EXTRACT_ONLY
static void SetMethodProp32(COneMethodInfo &m, PROPID propID, UInt32 value)
{
if (m.FindProp(propID) < 0)
m.AddProp32(propID, value);
}
void CMultiMethodProps::SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const
{
UInt32 level = _level;
if (level != (UInt32)(Int32)-1)
SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level);
}
#ifndef _7ZIP_ST
void CMultiMethodProps::SetMethodThreadsTo(COneMethodInfo &oneMethodInfo, UInt32 numThreads)
{
SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
}
#endif
void CMultiMethodProps::InitMulti()
{
_level = (UInt32)(Int32)-1;
_analysisLevel = -1;
_crcSize = 4;
_autoFilter = true;
}
void CMultiMethodProps::Init()
{
InitCommon();
InitMulti();
_methods.Clear();
_filterMethod.Clear();
}
HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
{
UString name = nameSpec;
name.MakeLower_Ascii();
if (name.IsEmpty())
return E_INVALIDARG;
if (name[0] == 'x')
{
name.Delete(0);
_level = 9;
return ParsePropToUInt32(name, value, _level);
}
if (name.IsPrefixedBy_Ascii_NoCase("yx"))
{
name.Delete(0, 2);
UInt32 v = 9;
RINOK(ParsePropToUInt32(name, value, v));
_analysisLevel = (int)v;
return S_OK;
}
if (name.IsPrefixedBy_Ascii_NoCase("crc"))
{
name.Delete(0, 3);
_crcSize = 4;
return ParsePropToUInt32(name, value, _crcSize);
}
{
HRESULT hres;
if (SetCommonProperty(name, value, hres))
return hres;
}
UInt32 number;
unsigned index = ParseStringToUInt32(name, number);
UString realName = name.Ptr(index);
if (index == 0)
{
if (name.IsEqualTo("f"))
{
HRESULT res = PROPVARIANT_to_bool(value, _autoFilter);
if (res == S_OK)
return res;
if (value.vt != VT_BSTR)
return E_INVALIDARG;
return _filterMethod.ParseMethodFromPROPVARIANT(UString(), value);
}
number = 0;
}
if (number > 64)
return E_FAIL;
for (unsigned j = _methods.Size(); j <= number; j++)
_methods.AddNew();
return _methods[number].ParseMethodFromPROPVARIANT(realName, value);
}
void CSingleMethodProps::Init()
{
InitCommon();
InitSingle();
Clear();
}
HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
Init();
for (UInt32 i = 0; i < numProps; i++)
{
UString name = names[i];
name.MakeLower_Ascii();
if (name.IsEmpty())
return E_INVALIDARG;
const PROPVARIANT &value = values[i];
if (name[0] == L'x')
{
UInt32 a = 9;
RINOK(ParsePropToUInt32(name.Ptr(1), value, a));
_level = a;
AddProp_Level(a);
continue;
}
{
HRESULT hres;
if (SetCommonProperty(name, value, hres))
{
RINOK(hres)
continue;
}
}
RINOK(ParseMethodFromPROPVARIANT(names[i], value));
}
return S_OK;
}
#endif
}

View File

@@ -0,0 +1,110 @@
// HandlerOut.h
#ifndef __HANDLER_OUT_H
#define __HANDLER_OUT_H
#include "../../../Windows/System.h"
#include "../../Common/MethodProps.h"
namespace NArchive {
bool ParseSizeString(const wchar_t *name, const PROPVARIANT &prop, UInt64 percentsBase, UInt64 &res);
class CCommonMethodProps
{
protected:
void InitCommon()
{
#ifndef _7ZIP_ST
_numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors();
#endif
UInt64 memAvail = (UInt64)(sizeof(size_t)) << 28;
_memAvail = memAvail;
_memUsage = memAvail;
if (NWindows::NSystem::GetRamSize(memAvail))
{
_memAvail = memAvail;
_memUsage = memAvail / 32 * 17;
}
}
public:
#ifndef _7ZIP_ST
UInt32 _numThreads;
UInt32 _numProcessors;
#endif
UInt64 _memUsage;
UInt64 _memAvail;
bool SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres);
CCommonMethodProps() { InitCommon(); }
};
#ifndef EXTRACT_ONLY
class CMultiMethodProps: public CCommonMethodProps
{
UInt32 _level;
int _analysisLevel;
void InitMulti();
public:
UInt32 _crcSize;
CObjectVector<COneMethodInfo> _methods;
COneMethodInfo _filterMethod;
bool _autoFilter;
void SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const;
#ifndef _7ZIP_ST
static void SetMethodThreadsTo(COneMethodInfo &oneMethodInfo, UInt32 numThreads);
#endif
unsigned GetNumEmptyMethods() const
{
unsigned i;
for (i = 0; i < _methods.Size(); i++)
if (!_methods[i].IsEmpty())
break;
return i;
}
int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }
int GetAnalysisLevel() const { return _analysisLevel; }
void Init();
CMultiMethodProps() { InitMulti(); }
HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
};
class CSingleMethodProps: public COneMethodInfo, public CCommonMethodProps
{
UInt32 _level;
void InitSingle()
{
_level = (UInt32)(Int32)-1;
}
public:
void Init();
CSingleMethodProps() { InitSingle(); }
int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }
HRESULT SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
};
#endif
}
#endif

View File

@@ -0,0 +1,46 @@
// InStreamWithCRC.cpp
#include "StdAfx.h"
#include "InStreamWithCRC.h"
STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 realProcessed = 0;
HRESULT result = S_OK;
if (_stream)
result = _stream->Read(data, size, &realProcessed);
_size += realProcessed;
if (size != 0 && realProcessed == 0)
_wasFinished = true;
_crc = CrcUpdate(_crc, data, realProcessed);
if (processedSize)
*processedSize = realProcessed;
return result;
}
STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 realProcessed = 0;
HRESULT result = S_OK;
if (_stream)
result = _stream->Read(data, size, &realProcessed);
_size += realProcessed;
/*
if (size != 0 && realProcessed == 0)
_wasFinished = true;
*/
_crc = CrcUpdate(_crc, data, realProcessed);
if (processedSize)
*processedSize = realProcessed;
return result;
}
STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
{
if (seekOrigin != STREAM_SEEK_SET || offset != 0)
return E_FAIL;
_size = 0;
_crc = CRC_INIT_VAL;
return _stream->Seek(offset, seekOrigin, newPosition);
}

View File

@@ -0,0 +1,67 @@
// InStreamWithCRC.h
#ifndef __IN_STREAM_WITH_CRC_H
#define __IN_STREAM_WITH_CRC_H
#include "../../../../C/7zCrc.h"
#include "../../../Common/MyCom.h"
#include "../../IStream.h"
class CSequentialInStreamWithCRC:
public ISequentialInStream,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
private:
CMyComPtr<ISequentialInStream> _stream;
UInt64 _size;
UInt32 _crc;
bool _wasFinished;
public:
void SetStream(ISequentialInStream *stream) { _stream = stream; }
void Init()
{
_size = 0;
_wasFinished = false;
_crc = CRC_INIT_VAL;
}
void ReleaseStream() { _stream.Release(); }
UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
UInt64 GetSize() const { return _size; }
bool WasFinished() const { return _wasFinished; }
};
class CInStreamWithCRC:
public IInStream,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP1(IInStream)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
private:
CMyComPtr<IInStream> _stream;
UInt64 _size;
UInt32 _crc;
// bool _wasFinished;
public:
void SetStream(IInStream *stream) { _stream = stream; }
void Init()
{
_size = 0;
// _wasFinished = false;
_crc = CRC_INIT_VAL;
}
void ReleaseStream() { _stream.Release(); }
UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
UInt64 GetSize() const { return _size; }
// bool WasFinished() const { return _wasFinished; }
};
#endif

View File

@@ -0,0 +1,112 @@
// Archive/Common/ItemNameUtils.cpp
#include "StdAfx.h"
#include "ItemNameUtils.h"
namespace NArchive {
namespace NItemName {
static const wchar_t kOsPathSepar = WCHAR_PATH_SEPARATOR;
#if WCHAR_PATH_SEPARATOR != L'/'
static const wchar_t kUnixPathSepar = L'/';
#endif
void ReplaceSlashes_OsToUnix
#if WCHAR_PATH_SEPARATOR != L'/'
(UString &name)
{
name.Replace(kOsPathSepar, kUnixPathSepar);
}
#else
(UString &) {}
#endif
UString GetOsPath(const UString &name)
{
#if WCHAR_PATH_SEPARATOR != L'/'
UString newName = name;
newName.Replace(kUnixPathSepar, kOsPathSepar);
return newName;
#else
return name;
#endif
}
UString GetOsPath_Remove_TailSlash(const UString &name)
{
if (name.IsEmpty())
return UString();
UString newName = GetOsPath(name);
if (newName.Back() == kOsPathSepar)
newName.DeleteBack();
return newName;
}
void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool
#if WCHAR_PATH_SEPARATOR != L'/'
useBackslashReplacement
#endif
)
{
if (name.IsEmpty())
return;
#if WCHAR_PATH_SEPARATOR != L'/'
{
// name.Replace(kUnixPathSepar, kOsPathSepar);
const unsigned len = name.Len();
for (unsigned i = 0; i < len; i++)
{
wchar_t c = name[i];
if (c == L'/')
c = WCHAR_PATH_SEPARATOR;
else if (useBackslashReplacement && c == L'\\')
c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme
else
continue;
name.ReplaceOneCharAtPos(i, c);
}
}
#endif
if (name.Back() == kOsPathSepar)
name.DeleteBack();
}
bool HasTailSlash(const AString &name, UINT
#if defined(_WIN32) && !defined(UNDER_CE)
codePage
#endif
)
{
if (name.IsEmpty())
return false;
char c;
#if defined(_WIN32) && !defined(UNDER_CE)
if (codePage != CP_UTF8)
c = *CharPrevExA((WORD)codePage, name, name.Ptr(name.Len()), 0);
else
#endif
{
c = name.Back();
}
return (c == '/');
}
#ifndef _WIN32
UString WinPathToOsPath(const UString &name)
{
UString newName = name;
newName.Replace(L'\\', WCHAR_PATH_SEPARATOR);
return newName;
}
#endif
}}

View File

@@ -0,0 +1,28 @@
// Archive/Common/ItemNameUtils.h
#ifndef __ARCHIVE_ITEM_NAME_UTILS_H
#define __ARCHIVE_ITEM_NAME_UTILS_H
#include "../../../Common/MyString.h"
namespace NArchive {
namespace NItemName {
void ReplaceSlashes_OsToUnix(UString &name);
UString GetOsPath(const UString &name);
UString GetOsPath_Remove_TailSlash(const UString &name);
void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool useBackslashReplacement = false);
bool HasTailSlash(const AString &name, UINT codePage);
#ifdef _WIN32
inline UString WinPathToOsPath(const UString &name) { return name; }
#else
UString WinPathToOsPath(const UString &name);
#endif
}}
#endif

View File

@@ -0,0 +1,191 @@
// MultiStream.cpp
#include "StdAfx.h"
#include "MultiStream.h"
STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
if (processedSize)
*processedSize = 0;
if (size == 0)
return S_OK;
if (_pos >= _totalLength)
return S_OK;
{
unsigned left = 0, mid = _streamIndex, right = Streams.Size();
for (;;)
{
CSubStreamInfo &m = Streams[mid];
if (_pos < m.GlobalOffset)
right = mid;
else if (_pos >= m.GlobalOffset + m.Size)
left = mid + 1;
else
{
_streamIndex = mid;
break;
}
mid = (left + right) / 2;
}
_streamIndex = mid;
}
CSubStreamInfo &s = Streams[_streamIndex];
UInt64 localPos = _pos - s.GlobalOffset;
if (localPos != s.LocalPos)
{
RINOK(s.Stream->Seek((Int64)localPos, STREAM_SEEK_SET, &s.LocalPos));
}
UInt64 rem = s.Size - localPos;
if (size > rem)
size = (UInt32)rem;
HRESULT result = s.Stream->Read(data, size, &size);
_pos += size;
s.LocalPos += size;
if (processedSize)
*processedSize = size;
return result;
}
STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
{
switch (seekOrigin)
{
case STREAM_SEEK_SET: break;
case STREAM_SEEK_CUR: offset += _pos; break;
case STREAM_SEEK_END: offset += _totalLength; break;
default: return STG_E_INVALIDFUNCTION;
}
if (offset < 0)
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
_pos = (UInt64)offset;
if (newPosition)
*newPosition = (UInt64)offset;
return S_OK;
}
/*
class COutVolumeStream:
public ISequentialOutStream,
public CMyUnknownImp
{
unsigned _volIndex;
UInt64 _volSize;
UInt64 _curPos;
CMyComPtr<ISequentialOutStream> _volumeStream;
COutArchive _archive;
CCRC _crc;
public:
MY_UNKNOWN_IMP
CFileItem _file;
CUpdateOptions _options;
CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
void Init(IArchiveUpdateCallback2 *volumeCallback,
const UString &name)
{
_file.Name = name;
_file.IsStartPosDefined = true;
_file.StartPos = 0;
VolumeCallback = volumeCallback;
_volIndex = 0;
_volSize = 0;
}
HRESULT Flush();
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
};
HRESULT COutVolumeStream::Flush()
{
if (_volumeStream)
{
_file.UnPackSize = _curPos;
_file.FileCRC = _crc.GetDigest();
RINOK(WriteVolumeHeader(_archive, _file, _options));
_archive.Close();
_volumeStream.Release();
_file.StartPos += _file.UnPackSize;
}
return S_OK;
}
*/
/*
STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
if (processedSize)
*processedSize = 0;
while (size > 0)
{
if (_streamIndex >= Streams.Size())
{
CSubStreamInfo subStream;
RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size));
RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream));
subStream.Pos = 0;
Streams.Add(subStream);
continue;
}
CSubStreamInfo &subStream = Streams[_streamIndex];
if (_offsetPos >= subStream.Size)
{
_offsetPos -= subStream.Size;
_streamIndex++;
continue;
}
if (_offsetPos != subStream.Pos)
{
CMyComPtr<IOutStream> outStream;
RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));
RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
subStream.Pos = _offsetPos;
}
UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos);
UInt32 realProcessed;
RINOK(subStream.Stream->Write(data, curSize, &realProcessed));
data = (void *)((Byte *)data + realProcessed);
size -= realProcessed;
subStream.Pos += realProcessed;
_offsetPos += realProcessed;
_absPos += realProcessed;
if (_absPos > _length)
_length = _absPos;
if (processedSize)
*processedSize += realProcessed;
if (subStream.Pos == subStream.Size)
{
_streamIndex++;
_offsetPos = 0;
}
if (realProcessed != curSize && realProcessed == 0)
return E_FAIL;
}
return S_OK;
}
STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
{
switch (seekOrigin)
{
case STREAM_SEEK_SET: break;
case STREAM_SEEK_CUR: offset += _absPos; break;
case STREAM_SEEK_END: offset += _length; break;
default: return STG_E_INVALIDFUNCTION;
}
if (offset < 0)
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
_absPos = offset;
_offsetPos = _absPos;
_streamIndex = 0;
if (newPosition)
*newPosition = offset;
return S_OK;
}
*/

View File

@@ -0,0 +1,89 @@
// MultiStream.h
#ifndef __MULTI_STREAM_H
#define __MULTI_STREAM_H
#include "../../../Common/MyCom.h"
#include "../../../Common/MyVector.h"
#include "../../IStream.h"
class CMultiStream:
public IInStream,
public CMyUnknownImp
{
UInt64 _pos;
UInt64 _totalLength;
unsigned _streamIndex;
public:
struct CSubStreamInfo
{
CMyComPtr<IInStream> Stream;
UInt64 Size;
UInt64 GlobalOffset;
UInt64 LocalPos;
CSubStreamInfo(): Size(0), GlobalOffset(0), LocalPos(0) {}
};
CObjectVector<CSubStreamInfo> Streams;
HRESULT Init()
{
UInt64 total = 0;
FOR_VECTOR (i, Streams)
{
CSubStreamInfo &s = Streams[i];
s.GlobalOffset = total;
total += Streams[i].Size;
RINOK(s.Stream->Seek(0, STREAM_SEEK_CUR, &s.LocalPos));
}
_totalLength = total;
_pos = 0;
_streamIndex = 0;
return S_OK;
}
MY_UNKNOWN_IMP1(IInStream)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
};
/*
class COutMultiStream:
public IOutStream,
public CMyUnknownImp
{
unsigned _streamIndex; // required stream
UInt64 _offsetPos; // offset from start of _streamIndex index
UInt64 _absPos;
UInt64 _length;
struct CSubStreamInfo
{
CMyComPtr<ISequentialOutStream> Stream;
UInt64 Size;
UInt64 Pos;
};
CObjectVector<CSubStreamInfo> Streams;
public:
CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
void Init()
{
_streamIndex = 0;
_offsetPos = 0;
_absPos = 0;
_length = 0;
}
MY_UNKNOWN_IMP1(IOutStream)
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
};
*/
#endif

View File

@@ -0,0 +1,18 @@
// OutStreamWithCRC.cpp
#include "StdAfx.h"
#include "OutStreamWithCRC.h"
STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
HRESULT result = S_OK;
if (_stream)
result = _stream->Write(data, size, &size);
if (_calculate)
_crc = CrcUpdate(_crc, data, size);
_size += size;
if (processedSize != NULL)
*processedSize = size;
return result;
}

View File

@@ -0,0 +1,37 @@
// OutStreamWithCRC.h
#ifndef __OUT_STREAM_WITH_CRC_H
#define __OUT_STREAM_WITH_CRC_H
#include "../../../../C/7zCrc.h"
#include "../../../Common/MyCom.h"
#include "../../IStream.h"
class COutStreamWithCRC:
public ISequentialOutStream,
public CMyUnknownImp
{
CMyComPtr<ISequentialOutStream> _stream;
UInt64 _size;
UInt32 _crc;
bool _calculate;
public:
MY_UNKNOWN_IMP
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
void ReleaseStream() { _stream.Release(); }
void Init(bool calculate = true)
{
_size = 0;
_calculate = calculate;
_crc = CRC_INIT_VAL;
}
void EnableCalc(bool calculate) { _calculate = calculate; }
void InitCRC() { _crc = CRC_INIT_VAL; }
UInt64 GetSize() const { return _size; }
UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
};
#endif

View File

@@ -0,0 +1,3 @@
// ParseProperties.cpp
#include "StdAfx.h"

View File

@@ -0,0 +1,6 @@
// ParseProperties.h
#ifndef __PARSE_PROPERTIES_H
#define __PARSE_PROPERTIES_H
#endif

View File

@@ -0,0 +1,8 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/Common.h"
#endif

View File

@@ -0,0 +1,157 @@
// DLLExports2.cpp
#include "StdAfx.h"
#include "../../Common/MyWindows.h"
#include "../../Common/MyInitGuid.h"
#if defined(_7ZIP_LARGE_PAGES)
#include "../../../C/Alloc.h"
#endif
#include "../../Common/ComTry.h"
#include "../../Windows/NtCheck.h"
#include "../../Windows/PropVariant.h"
#include "../ICoder.h"
#include "../IPassword.h"
#include "../Common/CreateCoder.h"
#include "IArchive.h"
#ifdef _WIN32
#if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE)
#define NT_CHECK_FAIL_ACTION return FALSE;
#endif
HINSTANCE g_hInstance;
extern "C"
BOOL WINAPI DllMain(
#ifdef UNDER_CE
HANDLE
#else
HINSTANCE
#endif
hInstance, DWORD dwReason, LPVOID /*lpReserved*/);
extern "C"
BOOL WINAPI DllMain(
#ifdef UNDER_CE
HANDLE
#else
HINSTANCE
#endif
hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
// OutputDebugStringA("7z.dll DLL_PROCESS_ATTACH");
g_hInstance = (HINSTANCE)hInstance;
NT_CHECK;
}
/*
if (dwReason == DLL_PROCESS_DETACH)
{
OutputDebugStringA("7z.dll DLL_PROCESS_DETACH");
}
*/
return TRUE;
}
#else // _WIN32
#include "../../Common/StringConvert.h"
// #include <stdio.h>
// STDAPI LibStartup();
static __attribute__((constructor)) void Init_ForceToUTF8();
static __attribute__((constructor)) void Init_ForceToUTF8()
{
g_ForceToUTF8 = IsNativeUTF8();
// printf("\nDLLExports2.cpp::Init_ForceToUTF8 =%d\n", g_ForceToUTF8 ? 1 : 0);
}
#endif // _WIN32
DEFINE_GUID(CLSID_CArchiveHandler,
k_7zip_GUID_Data1,
k_7zip_GUID_Data2,
k_7zip_GUID_Data3_Common,
0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject);
STDAPI CreateHasher(const GUID *clsid, IHasher **hasher);
STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject);
STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject);
STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
{
// COM_TRY_BEGIN
*outObject = 0;
if (*iid == IID_ICompressCoder ||
*iid == IID_ICompressCoder2 ||
*iid == IID_ICompressFilter)
return CreateCoder(clsid, iid, outObject);
if (*iid == IID_IHasher)
return CreateHasher(clsid, (IHasher **)outObject);
return CreateArchiver(clsid, iid, outObject);
// COM_TRY_END
}
STDAPI SetLargePageMode();
STDAPI SetLargePageMode()
{
#if defined(_7ZIP_LARGE_PAGES)
#ifdef _WIN32
SetLargePageSize();
#endif
#endif
return S_OK;
}
extern bool g_CaseSensitive;
STDAPI SetCaseSensitive(Int32 caseSensitive);
STDAPI SetCaseSensitive(Int32 caseSensitive)
{
g_CaseSensitive = (caseSensitive != 0);
return S_OK;
}
#ifdef EXTERNAL_CODECS
CExternalCodecs g_ExternalCodecs;
STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo);
STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo)
{
COM_TRY_BEGIN
// OutputDebugStringA(compressCodecsInfo ? "SetCodecs" : "SetCodecs NULL");
if (compressCodecsInfo)
{
g_ExternalCodecs.GetCodecs = compressCodecsInfo;
return g_ExternalCodecs.Load();
}
g_ExternalCodecs.ClearAndRelease();
return S_OK;
COM_TRY_END
}
#else
STDAPI SetCodecs(ICompressCodecsInfo *);
STDAPI SetCodecs(ICompressCodecsInfo *)
{
return S_OK;
}
#endif

View File

@@ -0,0 +1,633 @@
// IArchive.h
#ifndef __IARCHIVE_H
#define __IARCHIVE_H
#include "../IProgress.h"
#include "../IStream.h"
#include "../PropID.h"
#define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x)
#define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x)
/*
How the function in 7-Zip returns object for output parameter via pointer
1) The caller sets the value of variable before function call:
PROPVARIANT : vt = VT_EMPTY
BSTR : NULL
IUnknown* and derived interfaces : NULL
another scalar types : any non-initialized value is allowed
2) The callee in current 7-Zip code now can free input object for output parameter:
PROPVARIANT : the callee calls VariantClear(propvaiant_ptr) for input
value stored in variable
another types : the callee ignores stored value.
3) The callee writes new value to variable for output parameter and
returns execution to caller.
4) The caller must free or release object returned by the callee:
PROPVARIANT : VariantClear(&propvaiant)
BSTR : SysFreeString(bstr)
IUnknown* and derived interfaces : if (ptr) ptr->Relase()
*/
namespace NFileTimeType
{
enum EEnum
{
kWindows,
kUnix,
kDOS
};
}
namespace NArcInfoFlags
{
const UInt32 kKeepName = 1 << 0; // keep name of file in archive name
const UInt32 kAltStreams = 1 << 1; // the handler supports alt streams
const UInt32 kNtSecure = 1 << 2; // the handler supports NT security
const UInt32 kFindSignature = 1 << 3; // the handler can find start of archive
const UInt32 kMultiSignature = 1 << 4; // there are several signatures
const UInt32 kUseGlobalOffset = 1 << 5; // the seek position of stream must be set as global offset
const UInt32 kStartOpen = 1 << 6; // call handler for each start position
const UInt32 kPureStartOpen = 1 << 7; // call handler only for start of file
const UInt32 kBackwardOpen = 1 << 8; // archive can be open backward
const UInt32 kPreArc = 1 << 9; // such archive can be stored before real archive (like SFX stub)
const UInt32 kSymLinks = 1 << 10; // the handler supports symbolic links
const UInt32 kHardLinks = 1 << 11; // the handler supports hard links
const UInt32 kByExtOnlyOpen = 1 << 12; // call handler only if file extension matches
}
namespace NArchive
{
namespace NHandlerPropID
{
enum
{
kName = 0, // VT_BSTR
kClassID, // binary GUID in VT_BSTR
kExtension, // VT_BSTR
kAddExtension, // VT_BSTR
kUpdate, // VT_BOOL
kKeepName, // VT_BOOL
kSignature, // binary in VT_BSTR
kMultiSignature, // binary in VT_BSTR
kSignatureOffset, // VT_UI4
kAltStreams, // VT_BOOL
kNtSecure, // VT_BOOL
kFlags // VT_UI4
// kVersion // VT_UI4 ((VER_MAJOR << 8) | VER_MINOR)
};
}
namespace NExtract
{
namespace NAskMode
{
enum
{
kExtract = 0,
kTest,
kSkip
};
}
namespace NOperationResult
{
enum
{
kOK = 0,
kUnsupportedMethod,
kDataError,
kCRCError,
kUnavailable,
kUnexpectedEnd,
kDataAfterEnd,
kIsNotArc,
kHeadersError,
kWrongPassword
};
}
}
namespace NEventIndexType
{
enum
{
kNoIndex = 0,
kInArcIndex,
kBlockIndex,
kOutArcIndex
};
}
namespace NUpdate
{
namespace NOperationResult
{
enum
{
kOK = 0
// , kError
};
}
}
}
#define INTERFACE_IArchiveOpenCallback(x) \
STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) x; \
STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) x; \
ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10)
{
INTERFACE_IArchiveOpenCallback(PURE);
};
/*
IArchiveExtractCallback::
7-Zip doesn't call IArchiveExtractCallback functions
GetStream()
PrepareOperation()
SetOperationResult()
from different threads simultaneously.
But 7-Zip can call functions for IProgress or ICompressProgressInfo functions
from another threads simultaneously with calls for IArchiveExtractCallback interface.
IArchiveExtractCallback::GetStream()
UInt32 index - index of item in Archive
Int32 askExtractMode (Extract::NAskMode)
if (askMode != NExtract::NAskMode::kExtract)
{
then the callee doesn't write data to stream: (*outStream == NULL)
}
Out:
(*outStream == NULL) - for directories
(*outStream == NULL) - if link (hard link or symbolic link) was created
if (*outStream == NULL && askMode == NExtract::NAskMode::kExtract)
{
then the caller must skip extracting of that file.
}
returns:
S_OK : OK
S_FALSE : data error (for decoders)
if (IProgress::SetTotal() was called)
{
IProgress::SetCompleted(completeValue) uses
packSize - for some stream formats (xz, gz, bz2, lzma, z, ppmd).
unpackSize - for another formats.
}
else
{
IProgress::SetCompleted(completeValue) uses packSize.
}
SetOperationResult()
7-Zip calls SetOperationResult at the end of extracting,
so the callee can close the file, set attributes, timestamps and security information.
Int32 opRes (NExtract::NOperationResult)
*/
#define INTERFACE_IArchiveExtractCallback(x) \
INTERFACE_IProgress(x) \
STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \
STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \
STDMETHOD(SetOperationResult)(Int32 opRes) x; \
ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20)
{
INTERFACE_IArchiveExtractCallback(PURE)
};
/*
IArchiveExtractCallbackMessage can be requested from IArchiveExtractCallback object
by Extract() or UpdateItems() functions to report about extracting errors
ReportExtractResult()
UInt32 indexType (NEventIndexType)
UInt32 index
Int32 opRes (NExtract::NOperationResult)
*/
#define INTERFACE_IArchiveExtractCallbackMessage(x) \
STDMETHOD(ReportExtractResult)(UInt32 indexType, UInt32 index, Int32 opRes) x; \
ARCHIVE_INTERFACE_SUB(IArchiveExtractCallbackMessage, IProgress, 0x21)
{
INTERFACE_IArchiveExtractCallbackMessage(PURE)
};
#define INTERFACE_IArchiveOpenVolumeCallback(x) \
STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \
STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \
ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30)
{
INTERFACE_IArchiveOpenVolumeCallback(PURE);
};
ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40)
{
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE;
};
ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50)
{
STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE;
};
/*
IInArchive::Open
stream
if (kUseGlobalOffset), stream current position can be non 0.
if (!kUseGlobalOffset), stream current position is 0.
if (maxCheckStartPosition == NULL), the handler can try to search archive start in stream
if (*maxCheckStartPosition == 0), the handler must check only current position as archive start
IInArchive::Extract:
indices must be sorted
numItems = (UInt32)(Int32)-1 = 0xFFFFFFFF means "all files"
testMode != 0 means "test files without writing to outStream"
IInArchive::GetArchiveProperty:
kpidOffset - start offset of archive.
VT_EMPTY : means offset = 0.
VT_UI4, VT_UI8, VT_I8 : result offset; negative values is allowed
kpidPhySize - size of archive. VT_EMPTY means unknown size.
kpidPhySize is allowed to be larger than file size. In that case it must show
supposed size.
kpidIsDeleted:
kpidIsAltStream:
kpidIsAux:
kpidINode:
must return VARIANT_TRUE (VT_BOOL), if archive can support that property in GetProperty.
Notes:
Don't call IInArchive functions for same IInArchive object from different threads simultaneously.
Some IInArchive handlers will work incorrectly in that case.
*/
#ifdef _MSC_VER
#define MY_NO_THROW_DECL_ONLY throw()
#else
#define MY_NO_THROW_DECL_ONLY
#endif
#define INTERFACE_IInArchive(x) \
STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback) MY_NO_THROW_DECL_ONLY x; \
STDMETHOD(Close)() MY_NO_THROW_DECL_ONLY x; \
STDMETHOD(GetNumberOfItems)(UInt32 *numItems) MY_NO_THROW_DECL_ONLY x; \
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) MY_NO_THROW_DECL_ONLY x; \
STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) MY_NO_THROW_DECL_ONLY x; \
STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) MY_NO_THROW_DECL_ONLY x; \
STDMETHOD(GetNumberOfProperties)(UInt32 *numProps) MY_NO_THROW_DECL_ONLY x; \
STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x; \
STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProps) MY_NO_THROW_DECL_ONLY x; \
STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x; \
ARCHIVE_INTERFACE(IInArchive, 0x60)
{
INTERFACE_IInArchive(PURE)
};
namespace NParentType
{
enum
{
kDir = 0,
kAltStream
};
};
namespace NPropDataType
{
const UInt32 kMask_ZeroEnd = 1 << 4;
// const UInt32 kMask_BigEndian = 1 << 5;
const UInt32 kMask_Utf = 1 << 6;
const UInt32 kMask_Utf8 = kMask_Utf | 0;
const UInt32 kMask_Utf16 = kMask_Utf | 1;
// const UInt32 kMask_Utf32 = kMask_Utf | 2;
const UInt32 kNotDefined = 0;
const UInt32 kRaw = 1;
const UInt32 kUtf8z = kMask_Utf8 | kMask_ZeroEnd;
const UInt32 kUtf16z = kMask_Utf16 | kMask_ZeroEnd;
};
// UTF string (pointer to wchar_t) with zero end and little-endian.
#define PROP_DATA_TYPE_wchar_t_PTR_Z_LE ((NPropDataType::kMask_Utf | NPropDataType::kMask_ZeroEnd) + (sizeof(wchar_t) >> 1))
/*
GetRawProp:
Result:
S_OK - even if property is not set
*/
#define INTERFACE_IArchiveGetRawProps(x) \
STDMETHOD(GetParent)(UInt32 index, UInt32 *parent, UInt32 *parentType) x; \
STDMETHOD(GetRawProp)(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) x; \
STDMETHOD(GetNumRawProps)(UInt32 *numProps) x; \
STDMETHOD(GetRawPropInfo)(UInt32 index, BSTR *name, PROPID *propID) x;
ARCHIVE_INTERFACE(IArchiveGetRawProps, 0x70)
{
INTERFACE_IArchiveGetRawProps(PURE)
};
#define INTERFACE_IArchiveGetRootProps(x) \
STDMETHOD(GetRootProp)(PROPID propID, PROPVARIANT *value) x; \
STDMETHOD(GetRootRawProp)(PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) x; \
ARCHIVE_INTERFACE(IArchiveGetRootProps, 0x71)
{
INTERFACE_IArchiveGetRootProps(PURE)
};
ARCHIVE_INTERFACE(IArchiveOpenSeq, 0x61)
{
STDMETHOD(OpenSeq)(ISequentialInStream *stream) PURE;
};
/*
OpenForSize
Result:
S_FALSE - is not archive
? - DATA error
*/
/*
const UInt32 kOpenFlags_RealPhySize = 1 << 0;
const UInt32 kOpenFlags_NoSeek = 1 << 1;
// const UInt32 kOpenFlags_BeforeExtract = 1 << 2;
*/
/*
Flags:
0 - opens archive with IInStream, if IInStream interface is supported
- if phySize is not available, it doesn't try to make full parse to get phySize
kOpenFlags_NoSeek - ArcOpen2 function doesn't use IInStream interface, even if it's available
kOpenFlags_RealPhySize - the handler will try to get PhySize, even if it requires full decompression for file
if handler is not allowed to use IInStream and the flag kOpenFlags_RealPhySize is not specified,
the handler can return S_OK, but it doesn't check even Signature.
So next Extract can be called for that sequential stream.
*/
/*
ARCHIVE_INTERFACE(IArchiveOpen2, 0x62)
{
STDMETHOD(ArcOpen2)(ISequentialInStream *stream, UInt32 flags, IArchiveOpenCallback *openCallback) PURE;
};
*/
// ---------- UPDATE ----------
/*
GetUpdateItemInfo outs:
*newData *newProps
0 0 - Copy data and properties from archive
0 1 - Copy data from archive, request new properties
1 0 - that combination is unused now
1 1 - Request new data and new properties. It can be used even for folders
indexInArchive = -1 if there is no item in archive, or if it doesn't matter.
GetStream out:
Result:
S_OK:
(*inStream == NULL) - only for directories
- the bug was fixed in 9.33: (*Stream == NULL) was in case of anti-file
(*inStream != NULL) - for any file, even for empty file or anti-file
S_FALSE - skip that file (don't add item to archive) - (client code can't open stream of that file by some reason)
(*inStream == NULL)
The order of calling for hard links:
- GetStream()
- GetProperty(kpidHardLink)
SetOperationResult()
Int32 opRes (NExtract::NOperationResult::kOK)
*/
#define INTERFACE_IArchiveUpdateCallback(x) \
INTERFACE_IProgress(x); \
STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProps, UInt32 *indexInArchive) x; \
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \
STDMETHOD(SetOperationResult)(Int32 operationResult) x; \
ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80)
{
INTERFACE_IArchiveUpdateCallback(PURE);
};
#define INTERFACE_IArchiveUpdateCallback2(x) \
INTERFACE_IArchiveUpdateCallback(x) \
STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) x; \
STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) x; \
ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82)
{
INTERFACE_IArchiveUpdateCallback2(PURE);
};
namespace NUpdateNotifyOp
{
enum
{
kAdd = 0,
kUpdate,
kAnalyze,
kReplicate,
kRepack,
kSkip,
kDelete,
kHeader
// kNumDefined
};
};
/*
IArchiveUpdateCallbackFile::ReportOperation
UInt32 indexType (NEventIndexType)
UInt32 index
UInt32 notifyOp (NUpdateNotifyOp)
*/
#define INTERFACE_IArchiveUpdateCallbackFile(x) \
STDMETHOD(GetStream2)(UInt32 index, ISequentialInStream **inStream, UInt32 notifyOp) x; \
STDMETHOD(ReportOperation)(UInt32 indexType, UInt32 index, UInt32 notifyOp) x; \
ARCHIVE_INTERFACE(IArchiveUpdateCallbackFile, 0x83)
{
INTERFACE_IArchiveUpdateCallbackFile(PURE);
};
/*
UpdateItems()
-------------
outStream: output stream. (the handler) MUST support the case when
Seek position in outStream is not ZERO.
but the caller calls with empty outStream and seek position is ZERO??
archives with stub:
If archive is open and the handler and (Offset > 0), then the handler
knows about stub size.
UpdateItems():
1) the handler MUST copy that stub to outStream
2) the caller MUST NOT copy the stub to outStream, if
"rsfx" property is set with SetProperties
the handler must support the case where
ISequentialOutStream *outStream
*/
#define INTERFACE_IOutArchive(x) \
STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \
STDMETHOD(GetFileTimeType)(UInt32 *type) x;
ARCHIVE_INTERFACE(IOutArchive, 0xA0)
{
INTERFACE_IOutArchive(PURE)
};
/*
ISetProperties::SetProperties()
PROPVARIANT values[i].vt:
VT_EMPTY
VT_BOOL
VT_UI4 - if 32-bit number
VT_UI8 - if 64-bit number
VT_BSTR
*/
ARCHIVE_INTERFACE(ISetProperties, 0x03)
{
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) PURE;
};
ARCHIVE_INTERFACE(IArchiveKeepModeForNextOpen, 0x04)
{
STDMETHOD(KeepModeForNextOpen)() PURE;
};
/* Exe handler: the handler for executable format (PE, ELF, Mach-O).
SFX archive: executable stub + some tail data.
before 9.31: exe handler didn't parse SFX archives as executable format.
for 9.31+: exe handler parses SFX archives as executable format, only if AllowTail(1) was called */
ARCHIVE_INTERFACE(IArchiveAllowTail, 0x05)
{
STDMETHOD(AllowTail)(Int32 allowTail) PURE;
};
#define IMP_IInArchive_GetProp(k) \
(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \
{ if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \
*propID = k[index]; *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID]; *name = 0; return S_OK; } \
struct CStatProp
{
const char *Name;
UInt32 PropID;
VARTYPE vt;
};
namespace NWindows {
namespace NCOM {
// PropVariant.cpp
BSTR AllocBstrFromAscii(const char *s) throw();
}}
#define IMP_IInArchive_GetProp_WITH_NAME(k) \
(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \
{ if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \
const CStatProp &prop = k[index]; \
*propID = (PROPID)prop.PropID; *varType = prop.vt; \
*name = NWindows::NCOM::AllocBstrFromAscii(prop.Name); return S_OK; } \
#define IMP_IInArchive_Props \
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) \
{ *numProps = ARRAY_SIZE(kProps); return S_OK; } \
STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps)
#define IMP_IInArchive_Props_WITH_NAME \
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) \
{ *numProps = ARRAY_SIZE(kProps); return S_OK; } \
STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps)
#define IMP_IInArchive_ArcProps \
STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \
{ *numProps = ARRAY_SIZE(kArcProps); return S_OK; } \
STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps)
#define IMP_IInArchive_ArcProps_WITH_NAME \
STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \
{ *numProps = ARRAY_SIZE(kArcProps); return S_OK; } \
STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps)
#define IMP_IInArchive_ArcProps_NO_Table \
STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \
{ *numProps = 0; return S_OK; } \
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \
{ return E_NOTIMPL; } \
#define IMP_IInArchive_ArcProps_NO \
IMP_IInArchive_ArcProps_NO_Table \
STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \
{ value->vt = VT_EMPTY; return S_OK; }
#define k_IsArc_Res_NO 0
#define k_IsArc_Res_YES 1
#define k_IsArc_Res_NEED_MORE 2
// #define k_IsArc_Res_YES_LOW_PROB 3
#define API_FUNC_IsArc EXTERN_C UInt32 WINAPI
#define API_FUNC_static_IsArc extern "C" { static UInt32 WINAPI
extern "C"
{
typedef HRESULT (WINAPI *Func_CreateObject)(const GUID *clsID, const GUID *iid, void **outObject);
typedef UInt32 (WINAPI *Func_IsArc)(const Byte *p, size_t size);
typedef HRESULT (WINAPI *Func_GetIsArc)(UInt32 formatIndex, Func_IsArc *isArc);
typedef HRESULT (WINAPI *Func_GetNumberOfFormats)(UInt32 *numFormats);
typedef HRESULT (WINAPI *Func_GetHandlerProperty)(PROPID propID, PROPVARIANT *value);
typedef HRESULT (WINAPI *Func_GetHandlerProperty2)(UInt32 index, PROPID propID, PROPVARIANT *value);
typedef HRESULT (WINAPI *Func_SetCaseSensitive)(Int32 caseSensitive);
typedef HRESULT (WINAPI *Func_SetLargePageMode)();
typedef IOutArchive * (*Func_CreateOutArchive)();
typedef IInArchive * (*Func_CreateInArchive)();
}
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@@ -0,0 +1,624 @@
// LzmaHandler.cpp
#include "StdAfx.h"
#include "../../../C/CpuArch.h"
#include "../../Common/ComTry.h"
#include "../../Common/IntToString.h"
#include "../../Windows/PropVariant.h"
#include "../Common/FilterCoder.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h"
#include "../Compress/BcjCoder.h"
#include "../Compress/LzmaDecoder.h"
#include "Common/DummyOutStream.h"
using namespace NWindows;
namespace NArchive {
namespace NLzma {
static bool CheckDicSize(const Byte *p)
{
UInt32 dicSize = GetUi32(p);
if (dicSize == 1)
return true;
for (unsigned i = 0; i <= 30; i++)
if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i))
return true;
return (dicSize == 0xFFFFFFFF);
}
static const Byte kProps[] =
{
kpidSize,
kpidPackSize,
kpidMethod
};
static const Byte kArcProps[] =
{
kpidNumStreams,
kpidMethod
};
struct CHeader
{
UInt64 Size;
Byte FilterID;
Byte LzmaProps[5];
Byte GetProp() const { return LzmaProps[0]; }
UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); }
bool HasSize() const { return (Size != (UInt64)(Int64)-1); }
bool Parse(const Byte *buf, bool isThereFilter);
};
bool CHeader::Parse(const Byte *buf, bool isThereFilter)
{
FilterID = 0;
if (isThereFilter)
FilterID = buf[0];
const Byte *sig = buf + (isThereFilter ? 1 : 0);
for (int i = 0; i < 5; i++)
LzmaProps[i] = sig[i];
Size = GetUi64(sig + 5);
return
LzmaProps[0] < 5 * 5 * 9 &&
FilterID < 2 &&
(!HasSize() || Size < ((UInt64)1 << 56))
&& CheckDicSize(LzmaProps + 1);
}
class CDecoder
{
CMyComPtr<ISequentialOutStream> _bcjStream;
CFilterCoder *_filterCoder;
CMyComPtr<ICompressCoder> _lzmaDecoder;
public:
NCompress::NLzma::CDecoder *_lzmaDecoderSpec;
~CDecoder();
HRESULT Create(bool filtered, ISequentialInStream *inStream);
HRESULT Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress);
UInt64 GetInputProcessedSize() const { return _lzmaDecoderSpec->GetInputProcessedSize(); }
void ReleaseInStream() { if (_lzmaDecoder) _lzmaDecoderSpec->ReleaseInStream(); }
HRESULT ReadInput(Byte *data, UInt32 size, UInt32 *processedSize)
{ return _lzmaDecoderSpec->ReadFromInputStream(data, size, processedSize); }
};
HRESULT CDecoder::Create(bool filteredMode, ISequentialInStream *inStream)
{
if (!_lzmaDecoder)
{
_lzmaDecoderSpec = new NCompress::NLzma::CDecoder;
_lzmaDecoderSpec->FinishStream = true;
_lzmaDecoder = _lzmaDecoderSpec;
}
if (filteredMode)
{
if (!_bcjStream)
{
_filterCoder = new CFilterCoder(false);
CMyComPtr<ICompressCoder> coder = _filterCoder;
_filterCoder->Filter = new NCompress::NBcj::CCoder(false);
_bcjStream = _filterCoder;
}
}
return _lzmaDecoderSpec->SetInStream(inStream);
}
CDecoder::~CDecoder()
{
ReleaseInStream();
}
HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,
ICompressProgressInfo *progress)
{
if (header.FilterID > 1)
return E_NOTIMPL;
RINOK(_lzmaDecoderSpec->SetDecoderProperties2(header.LzmaProps, 5));
bool filteredMode = (header.FilterID == 1);
if (filteredMode)
{
RINOK(_filterCoder->SetOutStream(outStream));
outStream = _bcjStream;
RINOK(_filterCoder->SetOutStreamSize(NULL));
}
const UInt64 *Size = header.HasSize() ? &header.Size : NULL;
HRESULT res = _lzmaDecoderSpec->CodeResume(outStream, Size, progress);
if (filteredMode)
{
{
HRESULT res2 = _filterCoder->OutStreamFinish();
if (res == S_OK)
res = res2;
}
HRESULT res2 = _filterCoder->ReleaseOutStream();
if (res == S_OK)
res = res2;
}
RINOK(res);
if (header.HasSize())
if (_lzmaDecoderSpec->GetOutputProcessedSize() != header.Size)
return S_FALSE;
return S_OK;
}
class CHandler:
public IInArchive,
public IArchiveOpenSeq,
public CMyUnknownImp
{
CHeader _header;
bool _lzma86;
CMyComPtr<IInStream> _stream;
CMyComPtr<ISequentialInStream> _seqStream;
bool _isArc;
bool _needSeekToStart;
bool _dataAfterEnd;
bool _needMoreInput;
bool _packSize_Defined;
bool _unpackSize_Defined;
bool _numStreams_Defined;
bool _unsupported;
bool _dataError;
UInt64 _packSize;
UInt64 _unpackSize;
UInt64 _numStreams;
void GetMethod(NCOM::CPropVariant &prop);
public:
MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq)
INTERFACE_IInArchive(;)
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
CHandler(bool lzma86) { _lzma86 = lzma86; }
unsigned GetHeaderSize() const { return 5 + 8 + (_lzma86 ? 1 : 0); }
};
IMP_IInArchive_Props
IMP_IInArchive_ArcProps
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
switch (propID)
{
case kpidPhySize: if (_packSize_Defined) prop = _packSize; break;
case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break;
case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break;
case kpidMethod: GetMethod(prop); break;
case kpidErrorFlags:
{
UInt32 v = 0;
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;;
if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;
if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;
if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;
if (_dataError) v |= kpv_ErrorFlags_DataError;
prop = v;
break;
}
}
prop.Detach(value);
return S_OK;
}
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
*numItems = 1;
return S_OK;
}
static char * DictSizeToString(UInt32 val, char *s)
{
for (unsigned i = 0; i <= 31; i++)
if (((UInt32)1 << i) == val)
return ::ConvertUInt32ToString(i, s);
char c = 'b';
if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }
else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
s = ::ConvertUInt32ToString(val, s);
*s++ = c;
*s = 0;
return s;
}
static char *AddProp32(char *s, const char *name, UInt32 v)
{
*s++ = ':';
s = MyStpCpy(s, name);
return ::ConvertUInt32ToString(v, s);
}
void CHandler::GetMethod(NCOM::CPropVariant &prop)
{
if (!_stream)
return;
char sz[64];
char *s = sz;
if (_header.FilterID != 0)
s = MyStpCpy(s, "BCJ ");
s = MyStpCpy(s, "LZMA:");
s = DictSizeToString(_header.GetDicSize(), s);
UInt32 d = _header.GetProp();
// if (d != 0x5D)
{
UInt32 lc = d % 9;
d /= 9;
UInt32 pb = d / 5;
UInt32 lp = d % 5;
if (lc != 3) s = AddProp32(s, "lc", lc);
if (lp != 0) s = AddProp32(s, "lp", lp);
if (pb != 2) s = AddProp32(s, "pb", pb);
}
prop = sz;
}
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
switch (propID)
{
case kpidSize: if (_stream && _header.HasSize()) prop = _header.Size; break;
case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;
case kpidMethod: GetMethod(prop); break;
}
prop.Detach(value);
return S_OK;
}
API_FUNC_static_IsArc IsArc_Lzma(const Byte *p, size_t size)
{
const UInt32 kHeaderSize = 1 + 4 + 8;
if (size < kHeaderSize)
return k_IsArc_Res_NEED_MORE;
if (p[0] >= 5 * 5 * 9)
return k_IsArc_Res_NO;
const UInt64 unpackSize = GetUi64(p + 1 + 4);
if (unpackSize != (UInt64)(Int64)-1)
{
if (unpackSize >= ((UInt64)1 << 56))
return k_IsArc_Res_NO;
}
if (unpackSize != 0)
{
if (size < kHeaderSize + 2)
return k_IsArc_Res_NEED_MORE;
if (p[kHeaderSize] != 0)
return k_IsArc_Res_NO;
if (unpackSize != (UInt64)(Int64)-1)
{
if ((p[kHeaderSize + 1] & 0x80) != 0)
return k_IsArc_Res_NO;
}
}
if (!CheckDicSize(p + 1))
// return k_IsArc_Res_YES_LOW_PROB;
return k_IsArc_Res_NO;
return k_IsArc_Res_YES;
}
}
API_FUNC_static_IsArc IsArc_Lzma86(const Byte *p, size_t size)
{
if (size < 1)
return k_IsArc_Res_NEED_MORE;
Byte filterID = p[0];
if (filterID != 0 && filterID != 1)
return k_IsArc_Res_NO;
return IsArc_Lzma(p + 1, size - 1);
}
}
STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *)
{
Close();
const unsigned headerSize = GetHeaderSize();
const UInt32 kBufSize = 1 << 7;
Byte buf[kBufSize];
size_t processedSize = kBufSize;
RINOK(ReadStream(inStream, buf, &processedSize));
if (processedSize < headerSize + 2)
return S_FALSE;
if (!_header.Parse(buf, _lzma86))
return S_FALSE;
const Byte *start = buf + headerSize;
if (start[0] != 0 /* || (start[1] & 0x80) != 0 */ ) // empty stream with EOS is not 0x80
return S_FALSE;
RINOK(inStream->Seek(0, STREAM_SEEK_END, &_packSize));
SizeT srcLen = processedSize - headerSize;
if (srcLen > 10
&& _header.Size == 0
// && _header.FilterID == 0
&& _header.LzmaProps[0] == 0
)
return S_FALSE;
CDecoder state;
const UInt32 outLimit = 1 << 11;
Byte outBuf[outLimit];
SizeT outSize = outLimit;
if (outSize > _header.Size)
outSize = (SizeT)_header.Size;
SizeT destLen = outSize;
ELzmaStatus status;
SRes res = LzmaDecode(outBuf, &destLen, start, &srcLen,
_header.LzmaProps, 5, LZMA_FINISH_ANY,
&status, &g_Alloc);
if (res != SZ_OK)
if (res != SZ_ERROR_INPUT_EOF)
return S_FALSE;
_isArc = true;
_stream = inStream;
_seqStream = inStream;
_needSeekToStart = true;
return S_OK;
}
STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
{
Close();
_isArc = true;
_seqStream = stream;
return S_OK;
}
STDMETHODIMP CHandler::Close()
{
_isArc = false;
_packSize_Defined = false;
_unpackSize_Defined = false;
_numStreams_Defined = false;
_dataAfterEnd = false;
_needMoreInput = false;
_unsupported = false;
_dataError = false;
_packSize = 0;
_needSeekToStart = false;
_stream.Release();
_seqStream.Release();
return S_OK;
}
class CCompressProgressInfoImp:
public ICompressProgressInfo,
public CMyUnknownImp
{
CMyComPtr<IArchiveOpenCallback> Callback;
public:
UInt64 Offset;
MY_UNKNOWN_IMP1(ICompressProgressInfo)
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
void Init(IArchiveOpenCallback *callback) { Callback = callback; }
};
STDMETHODIMP CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)
{
if (Callback)
{
const UInt64 files = 0;
const UInt64 val = Offset + *inSize;
return Callback->SetCompleted(&files, &val);
}
return S_OK;
}
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
if (numItems == 0)
return S_OK;
if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
return E_INVALIDARG;
if (_packSize_Defined)
extractCallback->SetTotal(_packSize);
CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
if (!testMode && !realOutStream)
return S_OK;
extractCallback->PrepareOperation(askMode);
CDummyOutStream *outStreamSpec = new CDummyOutStream;
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
outStreamSpec->SetStream(realOutStream);
outStreamSpec->Init();
realOutStream.Release();
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, true);
if (_needSeekToStart)
{
if (!_stream)
return E_FAIL;
RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
}
else
_needSeekToStart = true;
CDecoder decoder;
HRESULT result = decoder.Create(_lzma86, _seqStream);
RINOK(result);
bool firstItem = true;
UInt64 packSize = 0;
UInt64 unpackSize = 0;
UInt64 numStreams = 0;
bool dataAfterEnd = false;
for (;;)
{
lps->InSize = packSize;
lps->OutSize = unpackSize;
RINOK(lps->SetCur());
const UInt32 kBufSize = 1 + 5 + 8;
Byte buf[kBufSize];
const UInt32 headerSize = GetHeaderSize();
UInt32 processed;
RINOK(decoder.ReadInput(buf, headerSize, &processed));
if (processed != headerSize)
{
if (processed != 0)
dataAfterEnd = true;
break;
}
CHeader st;
if (!st.Parse(buf, _lzma86))
{
dataAfterEnd = true;
break;
}
numStreams++;
firstItem = false;
result = decoder.Code(st, outStream, progress);
packSize = decoder.GetInputProcessedSize();
unpackSize = outStreamSpec->GetSize();
if (result == E_NOTIMPL)
{
_unsupported = true;
result = S_FALSE;
break;
}
if (result == S_FALSE)
break;
RINOK(result);
}
if (firstItem)
{
_isArc = false;
result = S_FALSE;
}
else if (result == S_OK || result == S_FALSE)
{
if (dataAfterEnd)
_dataAfterEnd = true;
else if (decoder._lzmaDecoderSpec->NeedsMoreInput())
_needMoreInput = true;
_packSize = packSize;
_unpackSize = unpackSize;
_numStreams = numStreams;
_packSize_Defined = true;
_unpackSize_Defined = true;
_numStreams_Defined = true;
}
Int32 opResult = NExtract::NOperationResult::kOK;
if (!_isArc)
opResult = NExtract::NOperationResult::kIsNotArc;
else if (_needMoreInput)
opResult = NExtract::NOperationResult::kUnexpectedEnd;
else if (_unsupported)
opResult = NExtract::NOperationResult::kUnsupportedMethod;
else if (_dataAfterEnd)
opResult = NExtract::NOperationResult::kDataAfterEnd;
else if (result == S_FALSE)
opResult = NExtract::NOperationResult::kDataError;
else if (result == S_OK)
opResult = NExtract::NOperationResult::kOK;
else
return result;
outStream.Release();
return extractCallback->SetOperationResult(opResult);
COM_TRY_END
}
namespace NLzmaAr {
// 2, { 0x5D, 0x00 },
REGISTER_ARC_I_CLS_NO_SIG(
CHandler(false),
"lzma", "lzma", 0, 0xA,
0,
NArcInfoFlags::kStartOpen |
NArcInfoFlags::kKeepName,
IsArc_Lzma)
}
namespace NLzma86Ar {
REGISTER_ARC_I_CLS_NO_SIG(
CHandler(true),
"lzma86", "lzma86", 0, 0xB,
0,
NArcInfoFlags::kKeepName,
IsArc_Lzma86)
}
}}

View File

@@ -0,0 +1,359 @@
// SplitHandler.cpp
#include "StdAfx.h"
#include "../../Common/ComTry.h"
#include "../../Common/MyString.h"
#include "../../Windows/PropVariant.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
#include "../Compress/CopyCoder.h"
#include "Common/MultiStream.h"
using namespace NWindows;
namespace NArchive {
namespace NSplit {
static const Byte kProps[] =
{
kpidPath,
kpidSize
};
static const Byte kArcProps[] =
{
kpidNumVolumes,
kpidTotalPhySize
};
class CHandler:
public IInArchive,
public IInArchiveGetStream,
public CMyUnknownImp
{
CObjectVector<CMyComPtr<IInStream> > _streams;
CRecordVector<UInt64> _sizes;
UString _subName;
UInt64 _totalSize;
HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);
public:
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
INTERFACE_IInArchive(;)
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
};
IMP_IInArchive_Props
IMP_IInArchive_ArcProps
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
switch (propID)
{
case kpidMainSubfile: prop = (UInt32)0; break;
case kpidPhySize: if (!_sizes.IsEmpty()) prop = _sizes[0]; break;
case kpidTotalPhySize: prop = _totalSize; break;
case kpidNumVolumes: prop = (UInt32)_streams.Size(); break;
}
prop.Detach(value);
return S_OK;
}
struct CSeqName
{
UString _unchangedPart;
UString _changedPart;
bool _splitStyle;
bool GetNextName(UString &s)
{
{
unsigned i = _changedPart.Len();
for (;;)
{
wchar_t c = _changedPart[--i];
if (_splitStyle)
{
if (c == 'z')
{
_changedPart.ReplaceOneCharAtPos(i, L'a');
if (i == 0)
return false;
continue;
}
else if (c == 'Z')
{
_changedPart.ReplaceOneCharAtPos(i, L'A');
if (i == 0)
return false;
continue;
}
}
else
{
if (c == '9')
{
_changedPart.ReplaceOneCharAtPos(i, L'0');
if (i == 0)
{
_changedPart.InsertAtFront(L'1');
break;
}
continue;
}
}
c++;
_changedPart.ReplaceOneCharAtPos(i, c);
break;
}
}
s = _unchangedPart + _changedPart;
return true;
}
};
HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
{
Close();
if (!callback)
return S_FALSE;
CMyComPtr<IArchiveOpenVolumeCallback> volumeCallback;
callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&volumeCallback);
if (!volumeCallback)
return S_FALSE;
UString name;
{
NCOM::CPropVariant prop;
RINOK(volumeCallback->GetProperty(kpidName, &prop));
if (prop.vt != VT_BSTR)
return S_FALSE;
name = prop.bstrVal;
}
int dotPos = name.ReverseFind_Dot();
const UString prefix = name.Left((unsigned)(dotPos + 1));
const UString ext = name.Ptr((unsigned)(dotPos + 1));
UString ext2 = ext;
ext2.MakeLower_Ascii();
CSeqName seqName;
unsigned numLetters = 2;
bool splitStyle = false;
if (ext2.Len() >= 2 && StringsAreEqual_Ascii(ext2.RightPtr(2), "aa"))
{
splitStyle = true;
while (numLetters < ext2.Len())
{
if (ext2[ext2.Len() - numLetters - 1] != 'a')
break;
numLetters++;
}
}
else if (ext.Len() >= 2 && StringsAreEqual_Ascii(ext2.RightPtr(2), "01"))
{
while (numLetters < ext2.Len())
{
if (ext2[ext2.Len() - numLetters - 1] != '0')
break;
numLetters++;
}
if (numLetters != ext.Len())
return S_FALSE;
}
else
return S_FALSE;
seqName._unchangedPart = prefix + ext.Left(ext2.Len() - numLetters);
seqName._changedPart = ext.RightPtr(numLetters);
seqName._splitStyle = splitStyle;
if (prefix.Len() < 1)
_subName = "file";
else
_subName.SetFrom(prefix, prefix.Len() - 1);
UInt64 size;
{
/*
NCOM::CPropVariant prop;
RINOK(volumeCallback->GetProperty(kpidSize, &prop));
if (prop.vt != VT_UI8)
return E_INVALIDARG;
size = prop.uhVal.QuadPart;
*/
RINOK(stream->Seek(0, STREAM_SEEK_END, &size));
RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
}
_totalSize += size;
_sizes.Add(size);
_streams.Add(stream);
{
const UInt64 numFiles = _streams.Size();
RINOK(callback->SetCompleted(&numFiles, NULL));
}
for (;;)
{
UString fullName;
if (!seqName.GetNextName(fullName))
break;
CMyComPtr<IInStream> nextStream;
HRESULT result = volumeCallback->GetStream(fullName, &nextStream);
if (result == S_FALSE)
break;
if (result != S_OK)
return result;
if (!nextStream)
break;
{
/*
NCOM::CPropVariant prop;
RINOK(volumeCallback->GetProperty(kpidSize, &prop));
if (prop.vt != VT_UI8)
return E_INVALIDARG;
size = prop.uhVal.QuadPart;
*/
RINOK(nextStream->Seek(0, STREAM_SEEK_END, &size));
RINOK(nextStream->Seek(0, STREAM_SEEK_SET, NULL));
}
_totalSize += size;
_sizes.Add(size);
_streams.Add(nextStream);
{
const UInt64 numFiles = _streams.Size();
RINOK(callback->SetCompleted(&numFiles, NULL));
}
}
if (_streams.Size() == 1)
{
if (splitStyle)
return S_FALSE;
}
return S_OK;
}
STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback)
{
COM_TRY_BEGIN
HRESULT res = Open2(stream, callback);
if (res != S_OK)
Close();
return res;
COM_TRY_END
}
STDMETHODIMP CHandler::Close()
{
_totalSize = 0;
_subName.Empty();
_streams.Clear();
_sizes.Clear();
return S_OK;
}
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
*numItems = _streams.IsEmpty() ? 0 : 1;
return S_OK;
}
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
switch (propID)
{
case kpidPath: prop = _subName; break;
case kpidSize:
case kpidPackSize:
prop = _totalSize;
break;
}
prop.Detach(value);
return S_OK;
}
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
if (numItems == 0)
return S_OK;
if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
return E_INVALIDARG;
UInt64 currentTotalSize = 0;
RINOK(extractCallback->SetTotal(_totalSize));
CMyComPtr<ISequentialOutStream> outStream;
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
RINOK(extractCallback->GetStream(0, &outStream, askMode));
if (!testMode && !outStream)
return S_OK;
RINOK(extractCallback->PrepareOperation(askMode));
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false);
FOR_VECTOR (i, _streams)
{
lps->InSize = lps->OutSize = currentTotalSize;
RINOK(lps->SetCur());
IInStream *inStream = _streams[i];
RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
currentTotalSize += copyCoderSpec->TotalSize;
}
outStream.Release();
return extractCallback->SetOperationResult(NExtract::NOperationResult::kOK);
COM_TRY_END
}
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
{
COM_TRY_BEGIN
if (index != 0)
return E_INVALIDARG;
*stream = 0;
CMultiStream *streamSpec = new CMultiStream;
CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
FOR_VECTOR (i, _streams)
{
CMultiStream::CSubStreamInfo subStreamInfo;
subStreamInfo.Stream = _streams[i];
subStreamInfo.Size = _sizes[i];
streamSpec->Streams.Add(subStreamInfo);
}
streamSpec->Init();
*stream = streamTemp.Detach();
return S_OK;
COM_TRY_END
}
REGISTER_ARC_I_NO_SIG(
"Split", "001", 0, 0xEA,
0,
0,
NULL)
}}

View File

@@ -0,0 +1,8 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../Common/Common.h"
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
// XzHandler.h
#ifndef __XZ_HANDLER_H
#define __XZ_HANDLER_H
namespace NArchive {
namespace NXz {
}}
#endif

9
3rdparty/lzma/CPP/7zip/Asm.mak vendored Normal file
View File

@@ -0,0 +1,9 @@
!IFDEF ASM_OBJS
!IF "$(CPU)" == "ARM"
$(ASM_OBJS): ../../../../Asm/Arm/$(*B).asm
$(COMPL_ASM)
!ELSEIF "$(CPU)" != "IA64" && "$(CPU)" != "MIPS" && "$(CPU)" != "ARM64"
$(ASM_OBJS): ../../../../Asm/x86/$(*B).asm
$(COMPL_ASM)
!ENDIF
!ENDIF

File diff suppressed because it is too large Load Diff

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: "Alone"=.\Alone.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -0,0 +1,3 @@
// StdAfx.cpp
#include "StdAfx.h"

View File

@@ -0,0 +1,8 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/Common.h"
#endif

View File

@@ -0,0 +1,160 @@
PROG = 7zr.exe
# USE_C_AES = 1
CFLAGS = $(CFLAGS) -DPROG_VARIANT_R
COMMON_OBJS = \
$O\CommandLineParser.obj \
$O\CRC.obj \
$O\CrcReg.obj \
$O\IntToString.obj \
$O\ListFileUtils.obj \
$O\LzFindPrepare.obj \
$O\NewHandler.obj \
$O\StdInStream.obj \
$O\StdOutStream.obj \
$O\MyString.obj \
$O\Sha256Reg.obj \
$O\StringConvert.obj \
$O\StringToInt.obj \
$O\UTFConvert.obj \
$O\MyVector.obj \
$O\Wildcard.obj \
$O\XzCrc64Init.obj \
$O\XzCrc64Reg.obj \
WIN_OBJS = \
$O\DLL.obj \
$O\ErrorMsg.obj \
$O\FileDir.obj \
$O\FileFind.obj \
$O\FileIO.obj \
$O\FileLink.obj \
$O\FileName.obj \
$O\FileSystem.obj \
$O\MemoryLock.obj \
$O\PropVariant.obj \
$O\PropVariantConv.obj \
$O\Registry.obj \
$O\Synchronization.obj \
$O\System.obj \
$O\SystemInfo.obj \
$O\TimeUtils.obj \
7ZIP_COMMON_OBJS = \
$O\CreateCoder.obj \
$O\CWrappers.obj \
$O\FilePathAutoRename.obj \
$O\FileStreams.obj \
$O\InBuffer.obj \
$O\InOutTempBuffer.obj \
$O\FilterCoder.obj \
$O\LimitedStreams.obj \
$O\MethodId.obj \
$O\MethodProps.obj \
$O\OffsetStream.obj \
$O\OutBuffer.obj \
$O\ProgressUtils.obj \
$O\PropId.obj \
$O\StreamBinder.obj \
$O\StreamObjects.obj \
$O\StreamUtils.obj \
$O\UniqBlocks.obj \
$O\VirtThread.obj \
AR_OBJS = \
$O\LzmaHandler.obj \
$O\SplitHandler.obj \
$O\XzHandler.obj \
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
$O\DummyOutStream.obj \
$O\HandlerOut.obj \
$O\InStreamWithCRC.obj \
$O\ItemNameUtils.obj \
$O\MultiStream.obj \
$O\OutStreamWithCRC.obj \
$O\ParseProperties.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\7zRegister.obj \
$O\7zSpecStream.obj \
$O\7zUpdate.obj \
COMPRESS_OBJS = \
$O\Bcj2Coder.obj \
$O\Bcj2Register.obj \
$O\BcjCoder.obj \
$O\BcjRegister.obj \
$O\BranchMisc.obj \
$O\BranchRegister.obj \
$O\ByteSwap.obj \
$O\CopyCoder.obj \
$O\CopyRegister.obj \
$O\DeltaFilter.obj \
$O\Lzma2Decoder.obj \
$O\Lzma2Encoder.obj \
$O\Lzma2Register.obj \
$O\LzmaDecoder.obj \
$O\LzmaEncoder.obj \
$O\LzmaRegister.obj \
$O\XzDecoder.obj \
$O\XzEncoder.obj \
CRYPTO_OBJS = \
$O\7zAes.obj \
$O\7zAesRegister.obj \
$O\MyAes.obj \
$O\MyAesReg.obj \
$O\RandGen.obj \
C_OBJS = \
$O\7zStream.obj \
$O\Alloc.obj \
$O\Bcj2.obj \
$O\Bcj2Enc.obj \
$O\Bra.obj \
$O\Bra86.obj \
$O\BraIA64.obj \
$O\CpuArch.obj \
$O\Delta.obj \
$O\LzFind.obj \
$O\LzFindMt.obj \
$O\Lzma2Dec.obj \
$O\Lzma2DecMt.obj \
$O\Lzma2Enc.obj \
$O\LzmaDec.obj \
$O\LzmaEnc.obj \
$O\MtCoder.obj \
$O\MtDec.obj \
$O\Sort.obj \
$O\Threads.obj \
$O\Xz.obj \
$O\XzDec.obj \
$O\XzEnc.obj \
$O\XzIn.obj \
!include "../../UI/Console/Console.mak"
!include "../../Aes.mak"
!include "../../Crc.mak"
!include "../../Crc64.mak"
!include "../../LzFindOpt.mak"
!include "../../LzmaDec.mak"
!include "../../Sha256.mak"
!include "../../7zip.mak"

View File

@@ -0,0 +1,268 @@
PROG = 7zr
CONSOLE_VARIANT_FLAGS=-DPROG_VARIANT_R
# IS_X64 = 1
# USE_ASM = 1
# ST_MODE = 1
include ../../LzmaDec_gcc.mak
LOCAL_FLAGS_ST =
MT_OBJS =
ifdef ST_MODE
LOCAL_FLAGS_ST = -D_7ZIP_ST
ifdef SystemDrive
MT_OBJS = \
$O/Threads.o \
endif
else
MT_OBJS = \
$O/LzFindMt.o \
$O/LzFindOpt.o \
$O/StreamBinder.o \
$O/Synchronization.o \
$O/VirtThread.o \
$O/Threads.o \
endif
LOCAL_FLAGS_SYS =
ifdef SystemDrive
LOCAL_FLAGS_SYS = \
-D_7ZIP_LARGE_PAGES \
-DWIN_LONG_PATH \
-DSUPPORT_DEVICE_FILE \
SYS_OBJS = \
$O/FileSystem.o \
$O/Registry.o \
$O/MemoryLock.o \
$O/DLL.o \
$O/DllSecur.o \
$O/resource.o \
else
SYS_OBJS = \
$O/MyWindows.o \
endif
LOCAL_FLAGS = \
$(LOCAL_FLAGS_ST) \
$(LOCAL_FLAGS_SYS) \
# -D_LZMA_PROB32
CONSOLE_OBJS = \
$O/BenchCon.o \
$O/ConsoleClose.o \
$O/ExtractCallbackConsole.o \
$O/HashCon.o \
$O/List.o \
$O/Main.o \
$O/MainAr.o \
$O/OpenCallbackConsole.o \
$O/PercentPrinter.o \
$O/UpdateCallbackConsole.o \
$O/UserInputUtils.o \
UI_COMMON_OBJS = \
$O/ArchiveCommandLine.o \
$O/ArchiveExtractCallback.o \
$O/ArchiveOpenCallback.o \
$O/Bench.o \
$O/DefaultName.o \
$O/EnumDirItems.o \
$O/Extract.o \
$O/ExtractingFilePath.o \
$O/HashCalc.o \
$O/LoadCodecs.o \
$O/OpenArchive.o \
$O/PropIDUtils.o \
$O/SetProperties.o \
$O/SortUtils.o \
$O/TempFiles.o \
$O/Update.o \
$O/UpdateAction.o \
$O/UpdateCallback.o \
$O/UpdatePair.o \
$O/UpdateProduce.o \
COMMON_OBJS = \
$O/CommandLineParser.o \
$O/CRC.o \
$O/CrcReg.o \
$O/IntToString.o \
$O/ListFileUtils.o \
$O/LzFindPrepare.o \
$O/MyString.o \
$O/MyVector.o \
$O/NewHandler.o \
$O/Sha256Prepare.o \
$O/Sha256Reg.o \
$O/StringConvert.o \
$O/StringToInt.o \
$O/StdInStream.o \
$O/StdOutStream.o \
$O/UTFConvert.o \
$O/Wildcard.o \
$O/XzCrc64Init.o \
$O/XzCrc64Reg.o \
WIN_OBJS = \
$O/ErrorMsg.o \
$O/FileDir.o \
$O/FileFind.o \
$O/FileIO.o \
$O/FileLink.o \
$O/FileName.o \
$O/PropVariant.o \
$O/PropVariantConv.o \
$O/System.o \
$O/SystemInfo.o \
$O/TimeUtils.o \
7ZIP_COMMON_OBJS = \
$O/CreateCoder.o \
$O/CWrappers.o \
$O/FilePathAutoRename.o \
$O/FileStreams.o \
$O/InBuffer.o \
$O/InOutTempBuffer.o \
$O/FilterCoder.o \
$O/LimitedStreams.o \
$O/MethodId.o \
$O/MethodProps.o \
$O/OffsetStream.o \
$O/OutBuffer.o \
$O/ProgressUtils.o \
$O/PropId.o \
$O/StreamObjects.o \
$O/StreamUtils.o \
$O/UniqBlocks.o \
AR_OBJS = \
$O/LzmaHandler.o \
$O/SplitHandler.o \
$O/XzHandler.o \
AR_COMMON_OBJS = \
$O/CoderMixer2.o \
$O/DummyOutStream.o \
$O/HandlerOut.o \
$O/InStreamWithCRC.o \
$O/ItemNameUtils.o \
$O/MultiStream.o \
$O/OutStreamWithCRC.o \
$O/ParseProperties.o \
7Z_OBJS = \
$O/7zCompressionMode.o \
$O/7zDecode.o \
$O/7zEncode.o \
$O/7zExtract.o \
$O/7zFolderInStream.o \
$O/7zHandler.o \
$O/7zHandlerOut.o \
$O/7zHeader.o \
$O/7zIn.o \
$O/7zOut.o \
$O/7zProperties.o \
$O/7zRegister.o \
$O/7zSpecStream.o \
$O/7zUpdate.o \
COMPRESS_OBJS = \
$O/Bcj2Coder.o \
$O/Bcj2Register.o \
$O/BcjCoder.o \
$O/BcjRegister.o \
$O/BranchMisc.o \
$O/BranchRegister.o \
$O/ByteSwap.o \
$O/CopyCoder.o \
$O/CopyRegister.o \
$O/DeltaFilter.o \
$O/Lzma2Decoder.o \
$O/Lzma2Encoder.o \
$O/Lzma2Register.o \
$O/LzmaDecoder.o \
$O/LzmaEncoder.o \
$O/LzmaRegister.o \
$O/XzDecoder.o \
$O/XzEncoder.o \
CRYPTO_OBJS = \
$O/7zAes.o \
$O/7zAesRegister.o \
$O/MyAes.o \
$O/MyAesReg.o \
$O/RandGen.o \
C_OBJS = \
$O/7zStream.o \
$O/Alloc.o \
$O/Bcj2.o \
$O/Bcj2Enc.o \
$O/Bra.o \
$O/Bra86.o \
$O/BraIA64.o \
$O/CpuArch.o \
$O/Delta.o \
$O/LzFind.o \
$O/Lzma2Dec.o \
$O/Lzma2DecMt.o \
$O/Lzma2Enc.o \
$O/LzmaDec.o \
$O/LzmaEnc.o \
$O/MtCoder.o \
$O/MtDec.o \
$O/Sha256.o \
$O/Sha256Opt.o \
$O/Sort.o \
$O/Xz.o \
$O/XzDec.o \
$O/XzEnc.o \
$O/XzIn.o \
$O/XzCrc64.o \
$O/XzCrc64Opt.o \
$O/7zCrc.o \
$O/7zCrcOpt.o \
$O/Aes.o \
$O/AesOpt.o \
OBJS = \
$(LZMA_DEC_OPT_OBJS) \
$(C_OBJS) \
$(MT_OBJS) \
$(SYS_OBJS) \
$(COMMON_OBJS) \
$(WIN_OBJS) \
$(COMPRESS_OBJS) \
$(CRYPTO_OBJS) \
$(7ZIP_COMMON_OBJS) \
$(AR_OBJS) \
$(AR_COMMON_OBJS) \
$(7Z_OBJS) \
$(UI_COMMON_OBJS) \
$(CONSOLE_OBJS) \
include ../../7zip_gcc.mak

View File

@@ -0,0 +1,7 @@
#include "../../../../C/7zVersion.rc"
MY_VERSION_INFO_APP("7-Zip Reduced Standalone Console", "7zr")
#ifndef UNDER_CE
1 24 MOVEABLE PURE "../../UI/Console/Console.manifest"
#endif

View File

@@ -0,0 +1,3 @@
// StdAfx.cpp
#include "StdAfx.h"

View File

@@ -0,0 +1,8 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/Common.h"
#endif

View File

@@ -0,0 +1,96 @@
PROG = 7zxr.dll
DEF_FILE = ../../Archive/Archive2.def
CFLAGS = $(CFLAGS) \
-DEXTRACT_ONLY \
-D_NO_CRYPTO
COMMON_OBJS = \
$O\CRC.obj \
$O\CrcReg.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\PropVariant.obj \
$O\Synchronization.obj \
$O\System.obj \
7ZIP_COMMON_OBJS = \
$O\CreateCoder.obj \
$O\CWrappers.obj \
$O\InBuffer.obj \
$O\FilterCoder.obj \
$O\LimitedStreams.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 \
AR_OBJS = \
$O\ArchiveExports.obj \
$O\DllExports2.obj \
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
$O\HandlerOut.obj \
$O\ItemNameUtils.obj \
$O\OutStreamWithCRC.obj \
$O\ParseProperties.obj \
7Z_OBJS = \
$O\7zCompressionMode.obj \
$O\7zDecode.obj \
$O\7zExtract.obj \
$O\7zHandler.obj \
$O\7zHeader.obj \
$O\7zIn.obj \
$O\7zProperties.obj \
$O\7zRegister.obj \
COMPRESS_OBJS = \
$O\CodecExports.obj \
$O\Bcj2Coder.obj \
$O\Bcj2Register.obj \
$O\BcjCoder.obj \
$O\BcjRegister.obj \
$O\BranchMisc.obj \
$O\BranchRegister.obj \
$O\ByteSwap.obj \
$O\CopyCoder.obj \
$O\CopyRegister.obj \
$O\DeltaFilter.obj \
$O\Lzma2Decoder.obj \
$O\Lzma2Register.obj \
$O\LzmaDecoder.obj \
$O\LzmaRegister.obj \
C_OBJS = \
$O\Alloc.obj \
$O\Bcj2.obj \
$O\Bra.obj \
$O\Bra86.obj \
$O\BraIA64.obj \
$O\CpuArch.obj \
$O\Delta.obj \
$O\Lzma2Dec.obj \
$O\Lzma2DecMt.obj \
$O\LzmaDec.obj \
$O\MtDec.obj \
$O\Threads.obj \
!include "../../Crc.mak"
!include "../../LzmaDec.mak"
!include "../../7zip.mak"

View File

@@ -0,0 +1,5 @@
#include "../../../../C/7zVersion.rc"
MY_VERSION_INFO_DLL("7z Extracting Reduced Standalone Plugin", "7zxr")
101 ICON "../../Archive/Icons/7z.ico"

View File

@@ -0,0 +1,3 @@
// StdAfx.cpp
#include "StdAfx.h"

View File

@@ -0,0 +1,8 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/Common.h"
#endif

View File

@@ -0,0 +1,118 @@
PROG = 7zra.dll
DEF_FILE = ../../Archive/Archive2.def
CFLAGS = $(CFLAGS) \
-D_NO_CRYPTO
COMMON_OBJS = \
$O\CRC.obj \
$O\CrcReg.obj \
$O\IntToString.obj \
$O\LzFindPrepare.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\CWrappers.obj \
$O\InBuffer.obj \
$O\InOutTempBuffer.obj \
$O\FilterCoder.obj \
$O\LimitedStreams.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\UniqBlocks.obj \
$O\VirtThread.obj \
AR_OBJS = \
$O\ArchiveExports.obj \
$O\DllExports2.obj \
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
$O\HandlerOut.obj \
$O\InStreamWithCRC.obj \
$O\ItemNameUtils.obj \
$O\OutStreamWithCRC.obj \
$O\ParseProperties.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 \
COMPRESS_OBJS = \
$O\CodecExports.obj \
$O\Bcj2Coder.obj \
$O\Bcj2Register.obj \
$O\BcjCoder.obj \
$O\BcjRegister.obj \
$O\BranchMisc.obj \
$O\BranchRegister.obj \
$O\ByteSwap.obj \
$O\CopyCoder.obj \
$O\CopyRegister.obj \
$O\DeltaFilter.obj \
$O\Lzma2Decoder.obj \
$O\Lzma2Encoder.obj \
$O\Lzma2Register.obj \
$O\LzmaDecoder.obj \
$O\LzmaEncoder.obj \
$O\LzmaRegister.obj \
C_OBJS = \
$O\Alloc.obj \
$O\Bcj2.obj \
$O\Bcj2Enc.obj \
$O\Bra.obj \
$O\Bra86.obj \
$O\BraIA64.obj \
$O\CpuArch.obj \
$O\Delta.obj \
$O\LzFind.obj \
$O\LzFindMt.obj \
$O\Lzma2Dec.obj \
$O\Lzma2DecMt.obj \
$O\Lzma2Enc.obj \
$O\LzmaDec.obj \
$O\LzmaEnc.obj \
$O\MtCoder.obj \
$O\MtDec.obj \
$O\Threads.obj \
!include "../../Crc.mak"
!include "../../LzFindOpt.mak"
!include "../../LzmaDec.mak"
!include "../../7zip.mak"

View File

@@ -0,0 +1,5 @@
#include "../../../../C/7zVersion.rc"
MY_VERSION_INFO_DLL("7z Reduced Standalone Plugin", "7zr")
101 ICON "../../Archive/Icons/7z.ico"

View File

@@ -0,0 +1,810 @@
// LzmaAlone.cpp
#include "StdAfx.h"
// #include <stdio.h>
#include "../../../../C/CpuArch.h"
#if (defined(_WIN32) || defined(OS2) || defined(MSDOS)) && !defined(UNDER_CE)
#include <fcntl.h>
#include <io.h>
#define MY_SET_BINARY_MODE(file) _setmode(_fileno(file), O_BINARY)
#else
#define MY_SET_BINARY_MODE(file)
#endif
#include "../../../Common/MyWindows.h"
#include "../../../Common/MyInitGuid.h"
#include "../../../../C/7zVersion.h"
#include "../../../../C/Alloc.h"
#include "../../../../C/Lzma86.h"
#include "../../../Windows/NtCheck.h"
#ifndef _7ZIP_ST
#include "../../../Windows/System.h"
#endif
#include "../../../Common/IntToString.h"
#include "../../../Common/CommandLineParser.h"
#include "../../../Common/StringConvert.h"
#include "../../../Common/StringToInt.h"
#include "../../Common/FileStreams.h"
#include "../../Common/StreamUtils.h"
#include "../../Compress/LzmaDecoder.h"
#include "../../Compress/LzmaEncoder.h"
#include "../../UI/Console/BenchCon.h"
#include "../../UI/Console/ConsoleClose.h"
bool g_LargePagesMode = false;
using namespace NCommandLineParser;
static const unsigned kDictSizeLog = 24;
#define kCopyrightString "\nLZMA " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n"
static const char * const kHelpString =
"Usage: lzma <command> [inputFile] [outputFile] [<switches>...]\n"
"\n"
"<command>\n"
" e : Encode file\n"
" d : Decode file\n"
" b : Benchmark\n"
"<switches>\n"
" -a{N} : set compression mode : [0, 1] : default = 1 (max)\n"
" -d{N} : set dictionary size : [12, 30] : default = 24 (16 MiB)\n"
" -fb{N} : set number of fast bytes : [5, 273] : default = 128\n"
" -mc{N} : set number of cycles for match finder\n"
" -lc{N} : set number of literal context bits : [0, 8] : default = 3\n"
" -lp{N} : set number of literal pos bits : [0, 4] : default = 0\n"
" -pb{N} : set number of pos bits : [0, 4] : default = 2\n"
" -mf{M} : set match finder: [hc4, bt2, bt3, bt4] : default = bt4\n"
" -mt{N} : set number of CPU threads\n"
" -eos : write end of stream marker\n"
" -si : read data from stdin\n"
" -so : write data to stdout\n";
static const char * const kCantAllocate = "Cannot allocate memory";
static const char * const kReadError = "Read error";
static const char * const kWriteError = "Write error";
namespace NKey {
enum Enum
{
kHelp1 = 0,
kHelp2,
kMethod,
kLevel,
kAlgo,
kDict,
kFb,
kMc,
kLc,
kLp,
kPb,
kMatchFinder,
kMultiThread,
kEOS,
kStdIn,
kStdOut,
kFilter86
};
}
#define SWFRM_3(t, mu, mi) t, mu, mi, NULL
#define SWFRM_1(t) SWFRM_3(t, false, 0)
#define SWFRM_SIMPLE SWFRM_1(NSwitchType::kSimple)
#define SWFRM_STRING SWFRM_1(NSwitchType::kString)
#define SWFRM_STRING_SINGL(mi) SWFRM_3(NSwitchType::kString, false, mi)
static const CSwitchForm kSwitchForms[] =
{
{ "?", SWFRM_SIMPLE },
{ "H", SWFRM_SIMPLE },
{ "MM", SWFRM_STRING_SINGL(1) },
{ "X", SWFRM_STRING_SINGL(1) },
{ "A", SWFRM_STRING_SINGL(1) },
{ "D", SWFRM_STRING_SINGL(1) },
{ "FB", SWFRM_STRING_SINGL(1) },
{ "MC", SWFRM_STRING_SINGL(1) },
{ "LC", SWFRM_STRING_SINGL(1) },
{ "LP", SWFRM_STRING_SINGL(1) },
{ "PB", SWFRM_STRING_SINGL(1) },
{ "MF", SWFRM_STRING_SINGL(1) },
{ "MT", SWFRM_STRING },
{ "EOS", SWFRM_SIMPLE },
{ "SI", SWFRM_SIMPLE },
{ "SO", SWFRM_SIMPLE },
{ "F86", NSwitchType::kChar, false, 0, "+" }
};
static void Convert_UString_to_AString(const UString &s, AString &temp)
{
int codePage = CP_OEMCP;
/*
int g_CodePage = -1;
int codePage = g_CodePage;
if (codePage == -1)
codePage = CP_OEMCP;
if (codePage == CP_UTF8)
ConvertUnicodeToUTF8(s, temp);
else
*/
UnicodeStringToMultiByte2(temp, s, (UINT)codePage);
}
static void PrintErr(const char *s)
{
fputs(s, stderr);
}
static void PrintErr_LF(const char *s)
{
PrintErr(s);
fputc('\n', stderr);
}
static void PrintError(const char *s)
{
PrintErr("\nERROR: ");
PrintErr_LF(s);
}
static void PrintError2(const char *s1, const UString &s2)
{
PrintError(s1);
AString a;
Convert_UString_to_AString(s2, a);
PrintErr_LF(a);
}
static void PrintError_int(const char *s, int code)
{
PrintError(s);
char temp[32];
ConvertInt64ToString(code, temp);
PrintErr("Error code = ");
PrintErr_LF(temp);
}
static void Print(const char *s)
{
fputs(s, stdout);
}
static void Print_UInt64(UInt64 v)
{
char temp[32];
ConvertUInt64ToString(v, temp);
Print(temp);
}
static void Print_MB(UInt64 v)
{
Print_UInt64(v);
Print(" MiB");
}
static void Print_Size(const char *s, UInt64 v)
{
Print(s);
Print_UInt64(v);
Print(" (");
Print_MB(v >> 20);
Print(")\n");
}
static void PrintTitle()
{
Print(kCopyrightString);
}
static void PrintHelp()
{
PrintTitle();
Print(kHelpString);
}
class CProgressPrint:
public ICompressProgressInfo,
public CMyUnknownImp
{
UInt64 _size1;
UInt64 _size2;
public:
CProgressPrint(): _size1(0), _size2(0) {}
void ClosePrint();
MY_UNKNOWN_IMP1(ICompressProgressInfo)
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
};
#define BACK_STR \
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
static const char * const kBackSpaces =
BACK_STR
" "
BACK_STR;
void CProgressPrint::ClosePrint()
{
Print(kBackSpaces);
}
STDMETHODIMP CProgressPrint::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
{
if (NConsoleClose::TestBreakSignal())
return E_ABORT;
if (inSize)
{
UInt64 v1 = *inSize >> 20;
UInt64 v2 = _size2;
if (outSize)
v2 = *outSize >> 20;
if (v1 != _size1 || v2 != _size2)
{
_size1 = v1;
_size2 = v2;
ClosePrint();
Print_MB(_size1);
Print(" -> ");
Print_MB(_size2);
}
}
return S_OK;
}
MY_ATTR_NORETURN
static void IncorrectCommand()
{
throw "Incorrect command";
}
static UInt32 GetNumber(const wchar_t *s)
{
const wchar_t *end;
UInt32 v = ConvertStringToUInt32(s, &end);
if (*end != 0)
IncorrectCommand();
return v;
}
static void ParseUInt32(const CParser &parser, unsigned index, UInt32 &res)
{
if (parser[index].ThereIs)
res = GetNumber(parser[index].PostStrings[0]);
}
static int Error_HRESULT(const char *s, HRESULT res)
{
if (res == E_ABORT)
{
Print("\n\nBreak signaled\n");
return 255;
}
PrintError(s);
if (res == E_OUTOFMEMORY)
{
PrintErr_LF(kCantAllocate);
return 8;
}
if (res == E_INVALIDARG)
{
PrintErr_LF("Ununsupported parameter");
}
else
{
char temp[32];
ConvertUInt32ToHex(res, temp);
PrintErr("Error code = 0x");
PrintErr_LF(temp);
}
return 1;
}
#if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE)
#define NT_CHECK_FAIL_ACTION PrintError("Unsupported Windows version"); return 1;
#endif
static void AddProp(CObjectVector<CProperty> &props2, const char *name, const wchar_t *val)
{
CProperty &prop = props2.AddNew();
prop.Name = name;
prop.Value = val;
}
static int main2(int numArgs, const char *args[])
{
NT_CHECK
if (numArgs == 1)
{
PrintHelp();
return 0;
}
/*
bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 8);
if (unsupportedTypes)
throw "Unsupported base types. Edit Common/Types.h and recompile";
*/
UStringVector commandStrings;
for (int i = 1; i < numArgs; i++)
commandStrings.Add(MultiByteToUnicodeString(args[i]));
CParser parser;
try
{
if (!parser.ParseStrings(kSwitchForms, ARRAY_SIZE(kSwitchForms), commandStrings))
{
PrintError2(parser.ErrorMessage, parser.ErrorLine);
return 1;
}
}
catch(...)
{
IncorrectCommand();
}
if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)
{
PrintHelp();
return 0;
}
bool stdInMode = parser[NKey::kStdIn].ThereIs;
bool stdOutMode = parser[NKey::kStdOut].ThereIs;
if (!stdOutMode)
PrintTitle();
const UStringVector &params = parser.NonSwitchStrings;
unsigned paramIndex = 0;
if (paramIndex >= params.Size())
IncorrectCommand();
const UString &command = params[paramIndex++];
CObjectVector<CProperty> props2;
bool dictDefined = false;
UInt32 dict = (UInt32)(Int32)-1;
if (parser[NKey::kDict].ThereIs)
{
UInt32 dictLog;
const UString &s = parser[NKey::kDict].PostStrings[0];
dictLog = GetNumber(s);
dict = 1 << dictLog;
dictDefined = true;
AddProp(props2, "d", s);
}
if (parser[NKey::kLevel].ThereIs)
{
const UString &s = parser[NKey::kLevel].PostStrings[0];
/* UInt32 level = */ GetNumber(s);
AddProp(props2, "x", s);
}
UString mf ("BT4");
if (parser[NKey::kMatchFinder].ThereIs)
mf = parser[NKey::kMatchFinder].PostStrings[0];
UInt32 numThreads = (UInt32)(Int32)-1;
#ifndef _7ZIP_ST
if (parser[NKey::kMultiThread].ThereIs)
{
const UString &s = parser[NKey::kMultiThread].PostStrings[0];
if (s.IsEmpty())
numThreads = NWindows::NSystem::GetNumberOfProcessors();
else
numThreads = GetNumber(s);
AddProp(props2, "mt", s);
}
#endif
if (parser[NKey::kMethod].ThereIs)
{
const UString &s = parser[NKey::kMethod].PostStrings[0];
if (s.IsEmpty() || s[0] != '=')
IncorrectCommand();
AddProp(props2, "m", s.Ptr(1));
}
if (StringsAreEqualNoCase_Ascii(command, "b"))
{
UInt32 numIterations = 1;
if (paramIndex < params.Size())
numIterations = GetNumber(params[paramIndex++]);
if (params.Size() != paramIndex)
IncorrectCommand();
HRESULT res = BenchCon(props2, numIterations, stdout);
if (res == S_OK)
return 0;
return Error_HRESULT("Benchmark error", res);
}
{
UInt32 needParams = 3;
if (stdInMode) needParams--;
if (stdOutMode) needParams--;
if (needParams != params.Size())
IncorrectCommand();
}
if (numThreads == (UInt32)(Int32)-1)
numThreads = 1;
bool encodeMode = false;
if (StringsAreEqualNoCase_Ascii(command, "e"))
encodeMode = true;
else if (!StringsAreEqualNoCase_Ascii(command, "d"))
IncorrectCommand();
CMyComPtr<ISequentialInStream> inStream;
CInFileStream *inStreamSpec = NULL;
if (stdInMode)
{
inStream = new CStdInFileStream;
MY_SET_BINARY_MODE(stdin);
}
else
{
const UString &inputName = params[paramIndex++];
inStreamSpec = new CInFileStream;
inStream = inStreamSpec;
if (!inStreamSpec->Open(us2fs(inputName)))
{
PrintError2("Cannot open input file", inputName);
return 1;
}
}
CMyComPtr<ISequentialOutStream> outStream;
COutFileStream *outStreamSpec = NULL;
if (stdOutMode)
{
outStream = new CStdOutFileStream;
MY_SET_BINARY_MODE(stdout);
}
else
{
const UString &outputName = params[paramIndex++];
outStreamSpec = new COutFileStream;
outStream = outStreamSpec;
if (!outStreamSpec->Create(us2fs(outputName), true))
{
PrintError2("Cannot open output file", outputName);
return 1;
}
}
bool fileSizeDefined = false;
UInt64 fileSize = 0;
if (inStreamSpec)
{
if (!inStreamSpec->File.GetLength(fileSize))
throw "Cannot get file length";
fileSizeDefined = true;
if (!stdOutMode)
Print_Size("Input size: ", fileSize);
}
if (encodeMode && !dictDefined)
{
dict = 1 << kDictSizeLog;
if (fileSizeDefined)
{
unsigned i;
for (i = 16; i < kDictSizeLog; i++)
if ((UInt32)((UInt32)1 << i) >= fileSize)
break;
dict = (UInt32)1 << i;
}
}
if (parser[NKey::kFilter86].ThereIs)
{
/* -f86 switch is for x86 filtered mode: BCJ + LZMA.
It uses modified header format.
It's not recommended to use -f86 mode now.
You can use xz format instead, if you want to use filters */
if (parser[NKey::kEOS].ThereIs || stdInMode)
throw "Cannot use stdin in this mode";
size_t inSize = (size_t)fileSize;
if (inSize != fileSize)
throw "File is too big";
Byte *inBuffer = NULL;
if (inSize != 0)
{
inBuffer = (Byte *)MyAlloc((size_t)inSize);
if (!inBuffer)
throw kCantAllocate;
}
if (ReadStream_FAIL(inStream, inBuffer, inSize) != S_OK)
throw "Cannot read";
Byte *outBuffer = NULL;
size_t outSize;
if (encodeMode)
{
// we allocate 105% of original size for output buffer
UInt64 outSize64 = fileSize / 20 * 21 + (1 << 16);
outSize = (size_t)outSize64;
if (outSize != outSize64)
throw "File is too big";
if (outSize != 0)
{
outBuffer = (Byte *)MyAlloc((size_t)outSize);
if (!outBuffer)
throw kCantAllocate;
}
int res = Lzma86_Encode(outBuffer, &outSize, inBuffer, inSize,
5, dict, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO);
if (res != 0)
{
PrintError_int("Encode error", (int)res);
return 1;
}
}
else
{
UInt64 outSize64;
if (Lzma86_GetUnpackSize(inBuffer, inSize, &outSize64) != 0)
throw "data error";
outSize = (size_t)outSize64;
if (outSize != outSize64)
throw "Unpack size is too big";
if (outSize != 0)
{
outBuffer = (Byte *)MyAlloc(outSize);
if (!outBuffer)
throw kCantAllocate;
}
int res = Lzma86_Decode(outBuffer, &outSize, inBuffer, &inSize);
if (inSize != (size_t)fileSize)
throw "incorrect processed size";
if (res != 0)
{
PrintError_int("Decode error", (int)res);
return 1;
}
}
if (WriteStream(outStream, outBuffer, outSize) != S_OK)
throw kWriteError;
MyFree(outBuffer);
MyFree(inBuffer);
}
else
{
CProgressPrint *progressSpec = NULL;
CMyComPtr<ICompressProgressInfo> progress;
if (!stdOutMode)
{
progressSpec = new CProgressPrint;
progress = progressSpec;
}
if (encodeMode)
{
NCompress::NLzma::CEncoder *encoderSpec = new NCompress::NLzma::CEncoder;
CMyComPtr<ICompressCoder> encoder = encoderSpec;
UInt32 pb = 2;
UInt32 lc = 3; // = 0; for 32-bit data
UInt32 lp = 0; // = 2; for 32-bit data
UInt32 algo = 1;
UInt32 fb = 128;
UInt32 mc = 16 + fb / 2;
bool mcDefined = false;
bool eos = parser[NKey::kEOS].ThereIs || stdInMode;
ParseUInt32(parser, NKey::kAlgo, algo);
ParseUInt32(parser, NKey::kFb, fb);
ParseUInt32(parser, NKey::kLc, lc);
ParseUInt32(parser, NKey::kLp, lp);
ParseUInt32(parser, NKey::kPb, pb);
mcDefined = parser[NKey::kMc].ThereIs;
if (mcDefined)
mc = GetNumber(parser[NKey::kMc].PostStrings[0]);
const PROPID propIDs[] =
{
NCoderPropID::kDictionarySize,
NCoderPropID::kPosStateBits,
NCoderPropID::kLitContextBits,
NCoderPropID::kLitPosBits,
NCoderPropID::kAlgorithm,
NCoderPropID::kNumFastBytes,
NCoderPropID::kMatchFinder,
NCoderPropID::kEndMarker,
NCoderPropID::kNumThreads,
NCoderPropID::kMatchFinderCycles,
};
const unsigned kNumPropsMax = ARRAY_SIZE(propIDs);
PROPVARIANT props[kNumPropsMax];
for (int p = 0; p < 6; p++)
props[p].vt = VT_UI4;
props[0].ulVal = (UInt32)dict;
props[1].ulVal = (UInt32)pb;
props[2].ulVal = (UInt32)lc;
props[3].ulVal = (UInt32)lp;
props[4].ulVal = (UInt32)algo;
props[5].ulVal = (UInt32)fb;
props[6].vt = VT_BSTR;
props[6].bstrVal = const_cast<BSTR>((const wchar_t *)mf);
props[7].vt = VT_BOOL;
props[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE;
props[8].vt = VT_UI4;
props[8].ulVal = (UInt32)numThreads;
// it must be last in property list
props[9].vt = VT_UI4;
props[9].ulVal = (UInt32)mc;
unsigned numProps = kNumPropsMax;
if (!mcDefined)
numProps--;
HRESULT res = encoderSpec->SetCoderProperties(propIDs, props, numProps);
if (res != S_OK)
return Error_HRESULT("incorrect encoder properties", res);
if (encoderSpec->WriteCoderProperties(outStream) != S_OK)
throw kWriteError;
bool fileSizeWasUsed = true;
if (eos || stdInMode)
{
fileSize = (UInt64)(Int64)-1;
fileSizeWasUsed = false;
}
{
Byte temp[8];
for (int i = 0; i < 8; i++)
temp[i]= (Byte)(fileSize >> (8 * i));
if (WriteStream(outStream, temp, 8) != S_OK)
throw kWriteError;
}
res = encoder->Code(inStream, outStream, NULL, NULL, progress);
if (progressSpec)
progressSpec->ClosePrint();
if (res != S_OK)
return Error_HRESULT("Encoding error", res);
UInt64 processedSize = encoderSpec->GetInputProcessedSize();
if (fileSizeWasUsed && processedSize != fileSize)
throw "Incorrect size of processed data";
}
else
{
NCompress::NLzma::CDecoder *decoderSpec = new NCompress::NLzma::CDecoder;
CMyComPtr<ICompressCoder> decoder = decoderSpec;
decoderSpec->FinishStream = true;
const unsigned kPropertiesSize = 5;
Byte header[kPropertiesSize + 8];
if (ReadStream_FALSE(inStream, header, kPropertiesSize + 8) != S_OK)
throw kReadError;
if (decoderSpec->SetDecoderProperties2(header, kPropertiesSize) != S_OK)
throw "SetDecoderProperties error";
UInt64 unpackSize = 0;
for (int i = 0; i < 8; i++)
unpackSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i);
bool unpackSizeDefined = (unpackSize != (UInt64)(Int64)-1);
HRESULT res = decoder->Code(inStream, outStream, NULL, unpackSizeDefined ? &unpackSize : NULL, progress);
if (progressSpec)
progressSpec->ClosePrint();
if (res != S_OK)
{
if (res == S_FALSE)
{
PrintError("Decoding error");
return 1;
}
return Error_HRESULT("Decoding error", res);
}
if (unpackSizeDefined && unpackSize != decoderSpec->GetOutputProcessedSize())
throw "incorrect uncompressed size in header";
}
}
if (outStreamSpec)
{
if (!stdOutMode)
Print_Size("Output size: ", outStreamSpec->ProcessedSize);
if (outStreamSpec->Close() != S_OK)
throw "File closing error";
}
return 0;
}
int MY_CDECL main(int numArgs, const char *args[])
{
NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter;
try { return main2(numArgs, args); }
catch (const char *s)
{
PrintError(s);
return 1;
}
catch(...)
{
PrintError("Unknown Error");
return 1;
}
}

View File

@@ -0,0 +1,510 @@
# Microsoft Developer Studio Project File - Name="LzmaCon" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=LzmaCon - 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 "LzmaCon.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 "LzmaCon.mak" CFG="LzmaCon - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "LzmaCon - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "LzmaCon - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "LzmaCon - 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 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /c
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x419 /d "NDEBUG"
BSC32=bscmake.exe
# 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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"C:\Util\lzma.exe"
!ELSEIF "$(CFG)" == "LzmaCon - 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 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W4 /WX /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c
# ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x419 /d "_DEBUG"
BSC32=bscmake.exe
# 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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\Util\lzma.exe" /pdbtype:sept
!ENDIF
# Begin Target
# Name "LzmaCon - Win32 Release"
# Name "LzmaCon - Win32 Debug"
# Begin Group "Spec"
# PROP Default_Filter ""
# 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 "Compress"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\Compress\LzmaDecoder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\LzmaDecoder.h
# End Source File
# Begin Source File
SOURCE=..\..\Compress\LzmaEncoder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\LzmaEncoder.h
# End Source File
# Begin Source File
SOURCE=..\..\Compress\LzmaRegister.cpp
# End Source File
# End Group
# Begin Group "Windows"
# PROP Default_Filter ""
# 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\PropVariant.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\PropVariant.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Registry.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Registry.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Synchronization.cpp
# End Source File
# Begin Source File
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\SystemInfo.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\SystemInfo.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Thread.h
# End Source File
# End Group
# Begin Group "Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\Common\CommandLineParser.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\CommandLineParser.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\ComTry.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\CRC.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\CrcReg.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Defs.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\LzFindPrepare.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\MyCom.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\MyUnknown.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\MyWindows.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\MyWindows.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\NewHandler.cpp
# End Source File
# Begin Source File
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\Types.h
# End Source File
# End Group
# Begin Group "7zip 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\CWrappers.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\CWrappers.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\FileStreams.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\FileStreams.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\MethodProps.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\MethodProps.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
# End Group
# Begin Group "UI Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\UI\Common\Bench.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\Bench.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\LoadCodecs.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\LoadCodecs.h
# End Source File
# End Group
# Begin Group "Console"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\UI\Console\BenchCon.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Console\BenchCon.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Console\ConsoleClose.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Console\ConsoleClose.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\7zTypes.h
# 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\Bra.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Bra.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Bra86.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\BraIA64.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\CpuArch.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\CpuArch.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\LzFind.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\LzFind.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\LzFindMt.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\LzFindMt.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\LzFindOpt.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\LzHash.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Lzma86.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Lzma86Dec.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Lzma86Enc.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\LzmaDec.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\LzmaDec.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\LzmaEnc.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\LzmaEnc.h
# 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
# Begin Source File
SOURCE=.\LzmaAlone.cpp
# End Source File
# End Target
# End Project

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: "LzmaCon"=.\LzmaCon.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -0,0 +1,3 @@
// StdAfx.cpp
#include "StdAfx.h"

View File

@@ -0,0 +1,8 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/Common.h"
#endif

View File

@@ -0,0 +1,63 @@
PROG = lzma.exe
MY_CONSOLE = 1
CURRENT_OBJS = \
$O\LzmaAlone.obj \
COMPRESS_OBJS = \
$O\LzmaDecoder.obj \
$O\LzmaEncoder.obj \
$O\LzmaRegister.obj \
COMMON_OBJS = \
$O\CommandLineParser.obj \
$O\CRC.obj \
$O\CrcReg.obj \
$O\IntToString.obj \
$O\LzFindPrepare.obj \
$O\MyString.obj \
$O\MyVector.obj \
$O\NewHandler.obj \
$O\StringConvert.obj \
$O\StringToInt.obj \
WIN_OBJS = \
$O\FileIO.obj \
$O\PropVariant.obj \
$O\Registry.obj \
$O\System.obj \
$O\SystemInfo.obj \
7ZIP_COMMON_OBJS = \
$O\CreateCoder.obj \
$O\CWrappers.obj \
$O\FileStreams.obj \
$O\FilterCoder.obj \
$O\MethodProps.obj \
$O\StreamObjects.obj \
$O\StreamUtils.obj \
UI_COMMON_OBJS = \
$O\Bench.obj \
CONSOLE_OBJS = \
$O\ConsoleClose.obj \
$O\BenchCon.obj \
C_OBJS = \
$O\Alloc.obj \
$O\Bra86.obj \
$O\CpuArch.obj \
$O\LzFind.obj \
$O\LzFindMt.obj \
$O\Lzma86Dec.obj \
$O\Lzma86Enc.obj \
$O\LzmaDec.obj \
$O\LzmaEnc.obj \
$O\Threads.obj \
!include "../../Crc.mak"
!include "../../LzFindOpt.mak"
!include "../../LzmaDec.mak"
!include "../../7zip.mak"

View File

@@ -0,0 +1,116 @@
PROG = lzma
# IS_X64 = 1
# USE_ASM = 1
# ST_MODE = 1
include ../../LzmaDec_gcc.mak
LOCAL_FLAGS_ST =
MT_OBJS =
ifdef ST_MODE
LOCAL_FLAGS_ST = -D_7ZIP_ST
else
MT_OBJS = \
$O/LzFindMt.o \
$O/LzFindOpt.o \
$O/Synchronization.o \
$O/Threads.o \
endif
LOCAL_FLAGS_SYS =
ifdef SystemDrive
SYS_OBJS = \
$O/Registry.o \
$O/resource.o \
else
SYS_OBJS = \
$O/FileDir.o \
$O/FileFind.o \
$O/FileName.o \
$O/MyWindows.o \
$O/TimeUtils.o \
endif
LOCAL_FLAGS = \
$(LOCAL_FLAGS_ST) \
COMMON_OBJS = \
$O/CommandLineParser.o \
$O/CRC.o \
$O/CrcReg.o \
$O/IntToString.o \
$O/LzFindPrepare.o \
$O/MyString.o \
$O/MyVector.o \
$O/NewHandler.o \
$O/StringConvert.o \
$O/StringToInt.o \
$O/UTFConvert.o \
WIN_OBJS = \
$O/FileIO.o \
$O/PropVariant.o \
$O/System.o \
$O/SystemInfo.o \
COMPRESS_OBJS = \
$O/LzmaDecoder.o \
$O/LzmaEncoder.o \
$O/LzmaRegister.o \
CONSOLE_OBJS = \
$O/BenchCon.o \
$O/ConsoleClose.o \
7ZIP_COMMON_OBJS = \
$O/CreateCoder.o \
$O/CWrappers.o \
$O/FileStreams.o \
$O/FilterCoder.o \
$O/MethodProps.o \
$O/StreamObjects.o \
$O/StreamUtils.o \
C_OBJS = \
$O/7zCrc.o \
$O/7zCrcOpt.o \
$O/Alloc.o \
$O/Bra86.o \
$O/CpuArch.o \
$O/LzFind.o \
$O/LzmaDec.o \
$O/LzmaEnc.o \
$O/Lzma86Dec.o \
$O/Lzma86Enc.o \
OBJS = \
$(LZMA_DEC_OPT_OBJS) \
$(C_OBJS) \
$(MT_OBJS) \
$(SYS_OBJS) \
$(COMMON_OBJS) \
$(WIN_OBJS) \
$(COMPRESS_OBJS) \
$(7ZIP_COMMON_OBJS) \
$(CONSOLE_OBJS) \
$O/LzmaAlone.o \
$O/Bench.o \
include ../../7zip_gcc.mak

View File

@@ -0,0 +1,3 @@
#include "../../MyVersionInfo.rc"
MY_VERSION_INFO_APP("LZMA", "lzma")

View File

@@ -0,0 +1,715 @@
/* LzmaSpec.cpp -- LZMA Reference Decoder
2015-06-14 : Igor Pavlov : Public domain */
// This code implements LZMA file decoding according to LZMA specification.
// This code is not optimized for speed.
#include <stdio.h>
#ifdef _MSC_VER
#pragma warning(disable : 4710) // function not inlined
#pragma warning(disable : 4996) // This function or variable may be unsafe
#endif
typedef unsigned char Byte;
typedef unsigned short UInt16;
#ifdef _LZMA_UINT32_IS_ULONG
typedef unsigned long UInt32;
#else
typedef unsigned int UInt32;
#endif
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef unsigned __int64 UInt64;
#else
typedef unsigned long long int UInt64;
#endif
struct CInputStream
{
FILE *File;
UInt64 Processed;
void Init() { Processed = 0; }
Byte ReadByte()
{
int c = getc(File);
if (c < 0)
throw "Unexpected end of file";
Processed++;
return (Byte)c;
}
};
struct COutStream
{
FILE *File;
UInt64 Processed;
void Init() { Processed = 0; }
void WriteByte(Byte b)
{
if (putc(b, File) == EOF)
throw "File writing error";
Processed++;
}
};
class COutWindow
{
Byte *Buf;
UInt32 Pos;
UInt32 Size;
bool IsFull;
public:
unsigned TotalPos;
COutStream OutStream;
COutWindow(): Buf(NULL) {}
~COutWindow() { delete []Buf; }
void Create(UInt32 dictSize)
{
Buf = new Byte[dictSize];
Pos = 0;
Size = dictSize;
IsFull = false;
TotalPos = 0;
}
void PutByte(Byte b)
{
TotalPos++;
Buf[Pos++] = b;
if (Pos == Size)
{
Pos = 0;
IsFull = true;
}
OutStream.WriteByte(b);
}
Byte GetByte(UInt32 dist) const
{
return Buf[dist <= Pos ? Pos - dist : Size - dist + Pos];
}
void CopyMatch(UInt32 dist, unsigned len)
{
for (; len > 0; len--)
PutByte(GetByte(dist));
}
bool CheckDistance(UInt32 dist) const
{
return dist <= Pos || IsFull;
}
bool IsEmpty() const
{
return Pos == 0 && !IsFull;
}
};
#define kNumBitModelTotalBits 11
#define kNumMoveBits 5
typedef UInt16 CProb;
#define PROB_INIT_VAL ((1 << kNumBitModelTotalBits) / 2)
#define INIT_PROBS(p) \
{ for (unsigned i = 0; i < sizeof(p) / sizeof(p[0]); i++) p[i] = PROB_INIT_VAL; }
class CRangeDecoder
{
UInt32 Range;
UInt32 Code;
void Normalize();
public:
CInputStream *InStream;
bool Corrupted;
bool Init();
bool IsFinishedOK() const { return Code == 0; }
UInt32 DecodeDirectBits(unsigned numBits);
unsigned DecodeBit(CProb *prob);
};
bool CRangeDecoder::Init()
{
Corrupted = false;
Range = 0xFFFFFFFF;
Code = 0;
Byte b = InStream->ReadByte();
for (int i = 0; i < 4; i++)
Code = (Code << 8) | InStream->ReadByte();
if (b != 0 || Code == Range)
Corrupted = true;
return b == 0;
}
#define kTopValue ((UInt32)1 << 24)
void CRangeDecoder::Normalize()
{
if (Range < kTopValue)
{
Range <<= 8;
Code = (Code << 8) | InStream->ReadByte();
}
}
UInt32 CRangeDecoder::DecodeDirectBits(unsigned numBits)
{
UInt32 res = 0;
do
{
Range >>= 1;
Code -= Range;
UInt32 t = 0 - ((UInt32)Code >> 31);
Code += Range & t;
if (Code == Range)
Corrupted = true;
Normalize();
res <<= 1;
res += t + 1;
}
while (--numBits);
return res;
}
unsigned CRangeDecoder::DecodeBit(CProb *prob)
{
unsigned v = *prob;
UInt32 bound = (Range >> kNumBitModelTotalBits) * v;
unsigned symbol;
if (Code < bound)
{
v += ((1 << kNumBitModelTotalBits) - v) >> kNumMoveBits;
Range = bound;
symbol = 0;
}
else
{
v -= v >> kNumMoveBits;
Code -= bound;
Range -= bound;
symbol = 1;
}
*prob = (CProb)v;
Normalize();
return symbol;
}
unsigned BitTreeReverseDecode(CProb *probs, unsigned numBits, CRangeDecoder *rc)
{
unsigned m = 1;
unsigned symbol = 0;
for (unsigned i = 0; i < numBits; i++)
{
unsigned bit = rc->DecodeBit(&probs[m]);
m <<= 1;
m += bit;
symbol |= (bit << i);
}
return symbol;
}
template <unsigned NumBits>
class CBitTreeDecoder
{
CProb Probs[(unsigned)1 << NumBits];
public:
void Init()
{
INIT_PROBS(Probs);
}
unsigned Decode(CRangeDecoder *rc)
{
unsigned m = 1;
for (unsigned i = 0; i < NumBits; i++)
m = (m << 1) + rc->DecodeBit(&Probs[m]);
return m - ((unsigned)1 << NumBits);
}
unsigned ReverseDecode(CRangeDecoder *rc)
{
return BitTreeReverseDecode(Probs, NumBits, rc);
}
};
#define kNumPosBitsMax 4
#define kNumStates 12
#define kNumLenToPosStates 4
#define kNumAlignBits 4
#define kStartPosModelIndex 4
#define kEndPosModelIndex 14
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
#define kMatchMinLen 2
class CLenDecoder
{
CProb Choice;
CProb Choice2;
CBitTreeDecoder<3> LowCoder[1 << kNumPosBitsMax];
CBitTreeDecoder<3> MidCoder[1 << kNumPosBitsMax];
CBitTreeDecoder<8> HighCoder;
public:
void Init()
{
Choice = PROB_INIT_VAL;
Choice2 = PROB_INIT_VAL;
HighCoder.Init();
for (unsigned i = 0; i < (1 << kNumPosBitsMax); i++)
{
LowCoder[i].Init();
MidCoder[i].Init();
}
}
unsigned Decode(CRangeDecoder *rc, unsigned posState)
{
if (rc->DecodeBit(&Choice) == 0)
return LowCoder[posState].Decode(rc);
if (rc->DecodeBit(&Choice2) == 0)
return 8 + MidCoder[posState].Decode(rc);
return 16 + HighCoder.Decode(rc);
}
};
unsigned UpdateState_Literal(unsigned state)
{
if (state < 4) return 0;
else if (state < 10) return state - 3;
else return state - 6;
}
unsigned UpdateState_Match (unsigned state) { return state < 7 ? 7 : 10; }
unsigned UpdateState_Rep (unsigned state) { return state < 7 ? 8 : 11; }
unsigned UpdateState_ShortRep(unsigned state) { return state < 7 ? 9 : 11; }
#define LZMA_DIC_MIN (1 << 12)
class CLzmaDecoder
{
public:
CRangeDecoder RangeDec;
COutWindow OutWindow;
bool markerIsMandatory;
unsigned lc, pb, lp;
UInt32 dictSize;
UInt32 dictSizeInProperties;
void DecodeProperties(const Byte *properties)
{
unsigned d = properties[0];
if (d >= (9 * 5 * 5))
throw "Incorrect LZMA properties";
lc = d % 9;
d /= 9;
pb = d / 5;
lp = d % 5;
dictSizeInProperties = 0;
for (int i = 0; i < 4; i++)
dictSizeInProperties |= (UInt32)properties[i + 1] << (8 * i);
dictSize = dictSizeInProperties;
if (dictSize < LZMA_DIC_MIN)
dictSize = LZMA_DIC_MIN;
}
CLzmaDecoder(): LitProbs(NULL) {}
~CLzmaDecoder() { delete []LitProbs; }
void Create()
{
OutWindow.Create(dictSize);
CreateLiterals();
}
int Decode(bool unpackSizeDefined, UInt64 unpackSize);
private:
CProb *LitProbs;
void CreateLiterals()
{
LitProbs = new CProb[(UInt32)0x300 << (lc + lp)];
}
void InitLiterals()
{
UInt32 num = (UInt32)0x300 << (lc + lp);
for (UInt32 i = 0; i < num; i++)
LitProbs[i] = PROB_INIT_VAL;
}
void DecodeLiteral(unsigned state, UInt32 rep0)
{
unsigned prevByte = 0;
if (!OutWindow.IsEmpty())
prevByte = OutWindow.GetByte(1);
unsigned symbol = 1;
unsigned litState = ((OutWindow.TotalPos & ((1 << lp) - 1)) << lc) + (prevByte >> (8 - lc));
CProb *probs = &LitProbs[(UInt32)0x300 * litState];
if (state >= 7)
{
unsigned matchByte = OutWindow.GetByte(rep0 + 1);
do
{
unsigned matchBit = (matchByte >> 7) & 1;
matchByte <<= 1;
unsigned bit = RangeDec.DecodeBit(&probs[((1 + matchBit) << 8) + symbol]);
symbol = (symbol << 1) | bit;
if (matchBit != bit)
break;
}
while (symbol < 0x100);
}
while (symbol < 0x100)
symbol = (symbol << 1) | RangeDec.DecodeBit(&probs[symbol]);
OutWindow.PutByte((Byte)(symbol - 0x100));
}
CBitTreeDecoder<6> PosSlotDecoder[kNumLenToPosStates];
CBitTreeDecoder<kNumAlignBits> AlignDecoder;
CProb PosDecoders[1 + kNumFullDistances - kEndPosModelIndex];
void InitDist()
{
for (unsigned i = 0; i < kNumLenToPosStates; i++)
PosSlotDecoder[i].Init();
AlignDecoder.Init();
INIT_PROBS(PosDecoders);
}
unsigned DecodeDistance(unsigned len)
{
unsigned lenState = len;
if (lenState > kNumLenToPosStates - 1)
lenState = kNumLenToPosStates - 1;
unsigned posSlot = PosSlotDecoder[lenState].Decode(&RangeDec);
if (posSlot < 4)
return posSlot;
unsigned numDirectBits = (unsigned)((posSlot >> 1) - 1);
UInt32 dist = ((2 | (posSlot & 1)) << numDirectBits);
if (posSlot < kEndPosModelIndex)
dist += BitTreeReverseDecode(PosDecoders + dist - posSlot, numDirectBits, &RangeDec);
else
{
dist += RangeDec.DecodeDirectBits(numDirectBits - kNumAlignBits) << kNumAlignBits;
dist += AlignDecoder.ReverseDecode(&RangeDec);
}
return dist;
}
CProb IsMatch[kNumStates << kNumPosBitsMax];
CProb IsRep[kNumStates];
CProb IsRepG0[kNumStates];
CProb IsRepG1[kNumStates];
CProb IsRepG2[kNumStates];
CProb IsRep0Long[kNumStates << kNumPosBitsMax];
CLenDecoder LenDecoder;
CLenDecoder RepLenDecoder;
void Init()
{
InitLiterals();
InitDist();
INIT_PROBS(IsMatch);
INIT_PROBS(IsRep);
INIT_PROBS(IsRepG0);
INIT_PROBS(IsRepG1);
INIT_PROBS(IsRepG2);
INIT_PROBS(IsRep0Long);
LenDecoder.Init();
RepLenDecoder.Init();
}
};
#define LZMA_RES_ERROR 0
#define LZMA_RES_FINISHED_WITH_MARKER 1
#define LZMA_RES_FINISHED_WITHOUT_MARKER 2
int CLzmaDecoder::Decode(bool unpackSizeDefined, UInt64 unpackSize)
{
if (!RangeDec.Init())
return LZMA_RES_ERROR;
Init();
UInt32 rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
unsigned state = 0;
for (;;)
{
if (unpackSizeDefined && unpackSize == 0 && !markerIsMandatory)
if (RangeDec.IsFinishedOK())
return LZMA_RES_FINISHED_WITHOUT_MARKER;
unsigned posState = OutWindow.TotalPos & ((1 << pb) - 1);
if (RangeDec.DecodeBit(&IsMatch[(state << kNumPosBitsMax) + posState]) == 0)
{
if (unpackSizeDefined && unpackSize == 0)
return LZMA_RES_ERROR;
DecodeLiteral(state, rep0);
state = UpdateState_Literal(state);
unpackSize--;
continue;
}
unsigned len;
if (RangeDec.DecodeBit(&IsRep[state]) != 0)
{
if (unpackSizeDefined && unpackSize == 0)
return LZMA_RES_ERROR;
if (OutWindow.IsEmpty())
return LZMA_RES_ERROR;
if (RangeDec.DecodeBit(&IsRepG0[state]) == 0)
{
if (RangeDec.DecodeBit(&IsRep0Long[(state << kNumPosBitsMax) + posState]) == 0)
{
state = UpdateState_ShortRep(state);
OutWindow.PutByte(OutWindow.GetByte(rep0 + 1));
unpackSize--;
continue;
}
}
else
{
UInt32 dist;
if (RangeDec.DecodeBit(&IsRepG1[state]) == 0)
dist = rep1;
else
{
if (RangeDec.DecodeBit(&IsRepG2[state]) == 0)
dist = rep2;
else
{
dist = rep3;
rep3 = rep2;
}
rep2 = rep1;
}
rep1 = rep0;
rep0 = dist;
}
len = RepLenDecoder.Decode(&RangeDec, posState);
state = UpdateState_Rep(state);
}
else
{
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
len = LenDecoder.Decode(&RangeDec, posState);
state = UpdateState_Match(state);
rep0 = DecodeDistance(len);
if (rep0 == 0xFFFFFFFF)
return RangeDec.IsFinishedOK() ?
LZMA_RES_FINISHED_WITH_MARKER :
LZMA_RES_ERROR;
if (unpackSizeDefined && unpackSize == 0)
return LZMA_RES_ERROR;
if (rep0 >= dictSize || !OutWindow.CheckDistance(rep0))
return LZMA_RES_ERROR;
}
len += kMatchMinLen;
bool isError = false;
if (unpackSizeDefined && unpackSize < len)
{
len = (unsigned)unpackSize;
isError = true;
}
OutWindow.CopyMatch(rep0 + 1, len);
unpackSize -= len;
if (isError)
return LZMA_RES_ERROR;
}
}
static void Print(const char *s)
{
fputs(s, stdout);
}
static void PrintError(const char *s)
{
fputs(s, stderr);
}
#define CONVERT_INT_TO_STR(charType, tempSize) \
void ConvertUInt64ToString(UInt64 val, char *s)
{
char temp[32];
unsigned i = 0;
while (val >= 10)
{
temp[i++] = (char)('0' + (unsigned)(val % 10));
val /= 10;
}
*s++ = (char)('0' + (unsigned)val);
while (i != 0)
{
i--;
*s++ = temp[i];
}
*s = 0;
}
void PrintUInt64(const char *title, UInt64 v)
{
Print(title);
Print(" : ");
char s[32];
ConvertUInt64ToString(v, s);
Print(s);
Print(" bytes \n");
}
int main2(int numArgs, const char *args[])
{
Print("\nLZMA Reference Decoder 15.00 : Igor Pavlov : Public domain : 2015-04-16\n");
if (numArgs == 1)
Print("\nUse: lzmaSpec a.lzma outFile");
if (numArgs != 3)
throw "you must specify two parameters";
CInputStream inStream;
inStream.File = fopen(args[1], "rb");
inStream.Init();
if (inStream.File == 0)
throw "Can't open input file";
CLzmaDecoder lzmaDecoder;
lzmaDecoder.OutWindow.OutStream.File = fopen(args[2], "wb+");
lzmaDecoder.OutWindow.OutStream.Init();
if (inStream.File == 0)
throw "Can't open output file";
Byte header[13];
int i;
for (i = 0; i < 13; i++)
header[i] = inStream.ReadByte();
lzmaDecoder.DecodeProperties(header);
printf("\nlc=%d, lp=%d, pb=%d", lzmaDecoder.lc, lzmaDecoder.lp, lzmaDecoder.pb);
printf("\nDictionary Size in properties = %u", lzmaDecoder.dictSizeInProperties);
printf("\nDictionary Size for decoding = %u", lzmaDecoder.dictSize);
UInt64 unpackSize = 0;
bool unpackSizeDefined = false;
for (i = 0; i < 8; i++)
{
Byte b = header[5 + i];
if (b != 0xFF)
unpackSizeDefined = true;
unpackSize |= (UInt64)b << (8 * i);
}
lzmaDecoder.markerIsMandatory = !unpackSizeDefined;
Print("\n");
if (unpackSizeDefined)
PrintUInt64("Uncompressed Size", unpackSize);
else
Print("End marker is expected\n");
lzmaDecoder.RangeDec.InStream = &inStream;
Print("\n");
lzmaDecoder.Create();
int res = lzmaDecoder.Decode(unpackSizeDefined, unpackSize);
PrintUInt64("Read ", inStream.Processed);
PrintUInt64("Written ", lzmaDecoder.OutWindow.OutStream.Processed);
if (res == LZMA_RES_ERROR)
throw "LZMA decoding error";
else if (res == LZMA_RES_FINISHED_WITHOUT_MARKER)
Print("Finished without end marker");
else if (res == LZMA_RES_FINISHED_WITH_MARKER)
{
if (unpackSizeDefined)
{
if (lzmaDecoder.OutWindow.OutStream.Processed != unpackSize)
throw "Finished with end marker before than specified size";
Print("Warning: ");
}
Print("Finished with end marker");
}
else
throw "Internal Error";
Print("\n");
if (lzmaDecoder.RangeDec.Corrupted)
{
Print("\nWarning: LZMA stream is corrupted\n");
}
return 0;
}
int
#ifdef _MSC_VER
__cdecl
#endif
main(int numArgs, const char *args[])
{
try { return main2(numArgs, args); }
catch (const char *s)
{
PrintError("\nError:\n");
PrintError(s);
PrintError("\n");
return 1;
}
catch(...)
{
PrintError("\nError\n");
return 1;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,921 @@
# Microsoft Developer Studio Project File - Name="SFXCon" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=SFXCon - 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 "SFXCon.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 "SFXCon.mak" CFG="SFXCon - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "SFXCon - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "SFXCon - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "SFXCon - 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 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "EXTRACT_ONLY" /D "_SFX" /D "NO_READ_FROM_CODER" /Yu"StdAfx.h" /FD /c
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x419 /d "NDEBUG"
BSC32=bscmake.exe
# 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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"C:\Util\7zCon.exe" /opt:NOWIN98
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "SFXCon - 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 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "EXTRACT_ONLY" /D "_SFX" /D "NO_READ_FROM_CODER" /Yu"StdAfx.h" /FD /GZ /c
# ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x419 /d "_DEBUG"
BSC32=bscmake.exe
# 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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\Util\7zCon.exe" /pdbtype:sept
!ENDIF
# Begin Target
# Name "SFXCon - Win32 Release"
# Name "SFXCon - Win32 Debug"
# Begin Group "Spec"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\resource.h
# 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 "Archive Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\Archive\Common\CoderMixer2.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Common\CoderMixer2.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Common\HandlerOut.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Common\ItemNameUtils.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Common\ItemNameUtils.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Common\MultiStream.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Common\MultiStream.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Common\OutStreamWithCRC.h
# End Source File
# End Group
# Begin Group "Console"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\UI\Console\ConsoleClose.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Console\ConsoleClose.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Console\ExtractCallbackConsole.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Console\List.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Console\List.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Console\MainAr.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Console\OpenCallbackConsole.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Console\PercentPrinter.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Console\PercentPrinter.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Console\UserInputUtils.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Console\UserInputUtils.h
# End Source File
# End Group
# Begin Group "7z"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\Archive\7z\7zDecode.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\7z\7zDecode.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\7z\7zExtract.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\7z\7zHandler.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\7z\7zHandler.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\7z\7zHeader.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\7z\7zIn.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\7z\7zIn.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\7z\7zItem.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\7z\7zRegister.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\SplitHandler.cpp
# End Source File
# End Group
# Begin Group "Compress"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\Compress\Bcj2Coder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\Bcj2Register.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\BcjCoder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\BcjRegister.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\BranchMisc.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\BranchMisc.h
# End Source File
# Begin Source File
SOURCE=..\..\Compress\BranchRegister.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\CopyCoder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\CopyRegister.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\DeltaFilter.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\Lzma2Decoder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\Lzma2Decoder.h
# End Source File
# Begin Source File
SOURCE=..\..\Compress\Lzma2Register.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\LzmaDecoder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\LzmaRegister.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\PpmdDecoder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\PpmdRegister.cpp
# End Source File
# End Group
# Begin Group "Crypto"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\Crypto\7zAes.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Crypto\7zAes.h
# End Source File
# Begin Source File
SOURCE=..\..\Crypto\7zAesRegister.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Crypto\MyAes.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Crypto\MyAes.h
# End Source File
# End Group
# Begin Group "Windows"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\Windows\DLL.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\DLL.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\ErrorMsg.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\ErrorMsg.h
# End Source File
# 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\PropVariant.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\PropVariant.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\PropVariantConv.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\PropVariantConv.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
# End Group
# Begin Group "Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\Common\CommandLineParser.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\CommandLineParser.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\CRC.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\CRC.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\Sha256Prepare.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\StdInStream.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\StdInStream.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\StdOutStream.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\StdOutStream.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\UTFConvert.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\UTFConvert.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 "7zip 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\CWrappers.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\CWrappers.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\FilePathAutoRename.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\FilePathAutoRename.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\FileStreams.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\FileStreams.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\InBuffer.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\InBuffer.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\OffsetStream.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\OffsetStream.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 "UI"
# PROP Default_Filter ""
# Begin Group "UI Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\ArchiveExtractCallback.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\ArchiveOpenCallback.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\DefaultName.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\DefaultName.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\ExitCode.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\Extract.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\Extract.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\ExtractingFilePath.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\ExtractingFilePath.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\ExtractMode.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\LoadCodecs.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\LoadCodecs.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\OpenArchive.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\OpenArchive.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\PropIDUtils.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\PropIDUtils.h
# End Source File
# End Group
# 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\Aes.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Aes.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\AesOpt.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\Bcj2.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Bcj2.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Bra.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Bra.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Bra86.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\BraIA64.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\CpuArch.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Delta.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Delta.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\DllSecur.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\DllSecur.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Lzma2Dec.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Lzma2Dec.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Lzma2DecMt.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Lzma2DecMt.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\LzmaDec.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\LzmaDec.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\MtDec.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\MtDec.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd7.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd7.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Ppmd7Dec.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Sha256.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Sha256.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Sha256Opt.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Threads.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Threads.h
# End Source File
# End Group
# Begin Source File
SOURCE=.\7z.ico
# End Source File
# Begin Source File
SOURCE=..\..\Archive\IArchive.h
# End Source File
# Begin Source File
SOURCE=.\SfxCon.cpp
# End Source File
# End Target
# End Project

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: "SFXCon"=.\SFXCon.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -0,0 +1,504 @@
// Main.cpp
#include "StdAfx.h"
#include "../../../../C/CpuArch.h"
#include "../../../Common/MyWindows.h"
#include "../../../Common/MyInitGuid.h"
#include "../../../Common/CommandLineParser.h"
#include "../../../Common/MyException.h"
#ifdef _WIN32
#include "../../../Windows/DLL.h"
#else
#include "../../../Common/StringConvert.h"
#endif
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileName.h"
#include "../../UI/Common/ExitCode.h"
#include "../../UI/Common/Extract.h"
#include "../../UI/Console/ExtractCallbackConsole.h"
#include "../../UI/Console/List.h"
#include "../../UI/Console/OpenCallbackConsole.h"
#include "../../MyVersion.h"
#include "../../../../C/DllSecur.h"
using namespace NWindows;
using namespace NFile;
using namespace NDir;
using namespace NCommandLineParser;
#ifdef _WIN32
HINSTANCE g_hInstance = 0;
#endif
int g_CodePage = -1;
extern CStdOutStream *g_StdStream;
static const char * const kCopyrightString =
"\n7-Zip SFX " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n";
static const int kNumSwitches = 6;
namespace NKey {
enum Enum
{
kHelp1 = 0,
kHelp2,
kDisablePercents,
kYes,
kPassword,
kOutputDir
};
}
namespace NRecursedType {
enum EEnum
{
kRecursed,
kWildcardOnlyRecursed,
kNonRecursed
};
}
/*
static const char kRecursedIDChar = 'R';
namespace NRecursedPostCharIndex {
enum EEnum
{
kWildcardRecursionOnly = 0,
kNoRecursion = 1
};
}
static const char kFileListID = '@';
static const char kImmediateNameID = '!';
static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be
static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be
*/
#define SWFRM_3(t, mu, mi) t, mu, mi, NULL
#define SWFRM_1(t) SWFRM_3(t, false, 0)
#define SWFRM_SIMPLE SWFRM_1(NSwitchType::kSimple)
#define SWFRM_STRING_SINGL(mi) SWFRM_3(NSwitchType::kString, false, mi)
static const CSwitchForm kSwitchForms[kNumSwitches] =
{
{ "?", SWFRM_SIMPLE },
{ "H", SWFRM_SIMPLE },
{ "BD", SWFRM_SIMPLE },
{ "Y", SWFRM_SIMPLE },
{ "P", SWFRM_STRING_SINGL(1) },
{ "O", SWFRM_STRING_SINGL(1) },
};
static const int kNumCommandForms = 3;
static const NRecursedType::EEnum kCommandRecursedDefault[kNumCommandForms] =
{
NRecursedType::kRecursed
};
// static const bool kTestExtractRecursedDefault = true;
// static const bool kAddRecursedDefault = false;
static const char * const kUniversalWildcard = "*";
static const char * const kHelpString =
"\nUsage: 7zSFX [<command>] [<switches>...] [<file_name>...]\n"
"\n"
"<Commands>\n"
// " l: List contents of archive\n"
" t: Test integrity of archive\n"
" x: eXtract files with full pathname (default)\n"
"<Switches>\n"
// " -bd Disable percentage indicator\n"
" -o{Directory}: set Output directory\n"
" -p{Password}: set Password\n"
" -y: assume Yes on all queries\n";
// ---------------------------
// exception messages
static const char * const kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError
// static const char * const kIncorrectListFile = "Incorrect wildcard in listfile";
static const char * const kIncorrectWildcardInCommandLine = "Incorrect wildcard in command line";
// static const CSysString kFileIsNotArchiveMessageBefore = "File \"";
// static const CSysString kFileIsNotArchiveMessageAfter = "\" is not archive";
// static const char * const kProcessArchiveMessage = " archive: ";
static const char * const kCantFindSFX = " cannot find sfx";
namespace NCommandType
{
enum EEnum
{
kTest = 0,
kFullExtract,
kList
};
}
static const char *g_Commands = "txl";
struct CArchiveCommand
{
NCommandType::EEnum CommandType;
NRecursedType::EEnum DefaultRecursedType() const;
};
static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command)
{
UString s = commandString;
s.MakeLower_Ascii();
if (s.Len() != 1)
return false;
if (s[0] >= 0x80)
return false;
int index = FindCharPosInString(g_Commands, (char)s[0]);
if (index < 0)
return false;
command.CommandType = (NCommandType::EEnum)index;
return true;
}
NRecursedType::EEnum CArchiveCommand::DefaultRecursedType() const
{
return kCommandRecursedDefault[CommandType];
}
static void PrintHelp(void)
{
g_StdOut << kHelpString;
}
MY_ATTR_NORETURN
static void ShowMessageAndThrowException(const char *message, NExitCode::EEnum code)
{
g_StdOut << message << endl;
throw code;
}
MY_ATTR_NORETURN
static void PrintHelpAndExit() // yyy
{
PrintHelp();
ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError);
}
// ------------------------------------------------------------------
// filenames functions
static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor,
const UString &name, bool include, NRecursedType::EEnum type)
{
/*
if (!IsWildcardFilePathLegal(name))
return false;
*/
bool isWildcard = DoesNameContainWildcard(name);
bool recursed = false;
switch (type)
{
case NRecursedType::kWildcardOnlyRecursed:
recursed = isWildcard;
break;
case NRecursedType::kRecursed:
recursed = true;
break;
case NRecursedType::kNonRecursed:
recursed = false;
break;
}
wildcardCensor.AddPreItem(include, name, recursed, true);
return true;
}
static void AddCommandLineWildcardToCensor(NWildcard::CCensor &wildcardCensor,
const UString &name, bool include, NRecursedType::EEnum type)
{
if (!AddNameToCensor(wildcardCensor, name, include, type))
ShowMessageAndThrowException(kIncorrectWildcardInCommandLine, NExitCode::kUserError);
}
#ifndef _WIN32
static void GetArguments(int numArgs, char *args[], UStringVector &parts)
{
parts.Clear();
for (int i = 0; i < numArgs; i++)
{
UString s = MultiByteToUnicodeString(args[i]);
parts.Add(s);
}
}
#endif
int Main2(
#ifndef _WIN32
int numArgs, char *args[]
#endif
);
int Main2(
#ifndef _WIN32
int numArgs, char *args[]
#endif
)
{
#ifdef _WIN32
// do we need load Security DLLs for console program?
LoadSecurityDlls();
#endif
#if defined(_WIN32) && !defined(UNDER_CE)
SetFileApisToOEM();
#endif
#ifdef ENV_HAVE_LOCALE
MY_SetLocale();
#endif
g_StdOut << kCopyrightString;
UStringVector commandStrings;
#ifdef _WIN32
NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);
#else
GetArguments(numArgs, args, commandStrings);
#endif
#ifdef _WIN32
FString arcPath;
{
FString path;
NDLL::MyGetModuleFileName(path);
if (!MyGetFullPathName(path, arcPath))
{
g_StdOut << "GetFullPathName Error";
return NExitCode::kFatalError;
}
}
#else
if (commandStrings.IsEmpty())
return NExitCode::kFatalError;
const FString arcPath = us2fs(commandStrings.Front());
#endif
#ifndef UNDER_CE
if (commandStrings.Size() > 0)
commandStrings.Delete(0);
#endif
NCommandLineParser::CParser parser;
try
{
if (!parser.ParseStrings(kSwitchForms, kNumSwitches, commandStrings))
{
g_StdOut << "Command line error:" << endl
<< parser.ErrorMessage << endl
<< parser.ErrorLine << endl;
return NExitCode::kUserError;
}
}
catch(...)
{
PrintHelpAndExit();
}
if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)
{
PrintHelp();
return 0;
}
const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
unsigned curCommandIndex = 0;
CArchiveCommand command;
if (nonSwitchStrings.IsEmpty())
command.CommandType = NCommandType::kFullExtract;
else
{
const UString &cmd = nonSwitchStrings[curCommandIndex];
if (!ParseArchiveCommand(cmd, command))
{
g_StdOut << "ERROR: Unknown command:" << endl << cmd << endl;
return NExitCode::kUserError;
}
curCommandIndex = 1;
}
NRecursedType::EEnum recursedType;
recursedType = command.DefaultRecursedType();
NWildcard::CCensor wildcardCensor;
{
if (nonSwitchStrings.Size() == curCommandIndex)
AddCommandLineWildcardToCensor(wildcardCensor, (UString)kUniversalWildcard, true, recursedType);
for (; curCommandIndex < nonSwitchStrings.Size(); curCommandIndex++)
{
const UString &s = nonSwitchStrings[curCommandIndex];
if (s.IsEmpty())
throw "Empty file path";
AddCommandLineWildcardToCensor(wildcardCensor, s, true, recursedType);
}
}
bool yesToAll = parser[NKey::kYes].ThereIs;
// NExtractMode::EEnum extractMode;
// bool isExtractGroupCommand = command.IsFromExtractGroup(extractMode);
bool passwordEnabled = parser[NKey::kPassword].ThereIs;
UString password;
if (passwordEnabled)
password = parser[NKey::kPassword].PostStrings[0];
if (!NFind::DoesFileExist_FollowLink(arcPath))
throw kCantFindSFX;
FString outputDir;
if (parser[NKey::kOutputDir].ThereIs)
{
outputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]);
NName::NormalizeDirPathPrefix(outputDir);
}
wildcardCensor.AddPathsToCensor(NWildcard::k_RelatPath);
{
UStringVector v1, v2;
v1.Add(fs2us(arcPath));
v2.Add(fs2us(arcPath));
const NWildcard::CCensorNode &wildcardCensorHead =
wildcardCensor.Pairs.Front().Head;
CCodecs *codecs = new CCodecs;
CMyComPtr<
#ifdef EXTERNAL_CODECS
ICompressCodecsInfo
#else
IUnknown
#endif
> compressCodecsInfo = codecs;
{
HRESULT result = codecs->Load();
if (result != S_OK)
throw CSystemException(result);
}
if (command.CommandType != NCommandType::kList)
{
CExtractCallbackConsole *ecs = new CExtractCallbackConsole;
CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
ecs->Init(g_StdStream, &g_StdErr, g_StdStream);
#ifndef _NO_CRYPTO
ecs->PasswordIsDefined = passwordEnabled;
ecs->Password = password;
#endif
/*
COpenCallbackConsole openCallback;
openCallback.Init(g_StdStream, g_StdStream);
#ifndef _NO_CRYPTO
openCallback.PasswordIsDefined = passwordEnabled;
openCallback.Password = password;
#endif
*/
CExtractOptions eo;
eo.StdOutMode = false;
eo.YesToAll = yesToAll;
eo.TestMode = command.CommandType == NCommandType::kTest;
eo.PathMode = NExtract::NPathMode::kFullPaths;
eo.OverwriteMode = yesToAll ?
NExtract::NOverwriteMode::kOverwrite :
NExtract::NOverwriteMode::kAsk;
eo.OutputDir = outputDir;
UString errorMessage;
CDecompressStat stat;
HRESULT result = Extract(
codecs, CObjectVector<COpenType>(), CIntVector(),
v1, v2,
wildcardCensorHead,
eo, ecs, ecs,
// NULL, // hash
errorMessage, stat);
if (!errorMessage.IsEmpty())
{
(*g_StdStream) << endl << "Error: " << errorMessage;;
if (result == S_OK)
result = E_FAIL;
}
if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0)
{
if (ecs->NumArcsWithError != 0)
(*g_StdStream) << endl << "Archive Errors" << endl;
if (ecs->NumFileErrors != 0)
(*g_StdStream) << endl << "Sub items Errors: " << ecs->NumFileErrors << endl;
return NExitCode::kFatalError;
}
if (result != S_OK)
throw CSystemException(result);
}
else
{
throw CSystemException(E_NOTIMPL);
/*
UInt64 numErrors = 0;
UInt64 numWarnings = 0;
HRESULT result = ListArchives(
codecs, CObjectVector<COpenType>(), CIntVector(),
false, // stdInMode
v1, v2,
true, // processAltStreams
false, // showAltStreams
wildcardCensorHead,
true, // enableHeaders
false, // techMode
#ifndef _NO_CRYPTO
passwordEnabled, password,
#endif
numErrors, numWarnings);
if (numErrors > 0)
{
g_StdOut << endl << "Errors: " << numErrors;
return NExitCode::kFatalError;
}
if (result != S_OK)
throw CSystemException(result);
*/
}
}
return 0;
}

View File

@@ -0,0 +1,3 @@
// StdAfx.cpp
#include "StdAfx.h"

View File

@@ -0,0 +1,8 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/Common.h"
#endif

View File

@@ -0,0 +1,133 @@
PROG = 7zCon.sfx
MY_CONSOLE = 1
MY_FIXED = 1
CFLAGS = $(CFLAGS) \
-DEXTRACT_ONLY \
-DNO_READ_FROM_CODER \
-D_SFX \
CURRENT_OBJS = \
$O\SfxCon.obj \
CONSOLE_OBJS = \
$O\ConsoleClose.obj \
$O\ExtractCallbackConsole.obj \
$O\List.obj \
$O\MainAr.obj \
$O\OpenCallbackConsole.obj \
$O\PercentPrinter.obj \
$O\UserInputUtils.obj \
COMMON_OBJS = \
$O\CommandLineParser.obj \
$O\CRC.obj \
$O\IntToString.obj \
$O\MyString.obj \
$O\MyVector.obj \
$O\NewHandler.obj \
$O\StdInStream.obj \
$O\StdOutStream.obj \
$O\StringConvert.obj \
$O\UTFConvert.obj \
$O\Wildcard.obj \
WIN_OBJS = \
$O\DLL.obj \
$O\ErrorMsg.obj \
$O\FileDir.obj \
$O\FileFind.obj \
$O\FileIO.obj \
$O\FileName.obj \
$O\PropVariant.obj \
$O\PropVariantConv.obj \
$O\Synchronization.obj \
$O\System.obj \
7ZIP_COMMON_OBJS = \
$O\CreateCoder.obj \
$O\CWrappers.obj \
$O\FilePathAutoRename.obj \
$O\FileStreams.obj \
$O\InBuffer.obj \
$O\FilterCoder.obj \
$O\LimitedStreams.obj \
$O\OutBuffer.obj \
$O\ProgressUtils.obj \
$O\PropId.obj \
$O\StreamBinder.obj \
$O\StreamObjects.obj \
$O\StreamUtils.obj \
$O\VirtThread.obj \
UI_COMMON_OBJS = \
$O\ArchiveExtractCallback.obj \
$O\ArchiveOpenCallback.obj \
$O\DefaultName.obj \
$O\Extract.obj \
$O\ExtractingFilePath.obj \
$O\LoadCodecs.obj \
$O\OpenArchive.obj \
$O\PropIDUtils.obj \
AR_OBJS = \
$O\SplitHandler.obj \
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
$O\ItemNameUtils.obj \
$O\MultiStream.obj \
$O\OutStreamWithCRC.obj \
7Z_OBJS = \
$O\7zDecode.obj \
$O\7zExtract.obj \
$O\7zHandler.obj \
$O\7zIn.obj \
$O\7zRegister.obj \
COMPRESS_OBJS = \
$O\Bcj2Coder.obj \
$O\Bcj2Register.obj \
$O\BcjCoder.obj \
$O\BcjRegister.obj \
$O\BranchMisc.obj \
$O\BranchRegister.obj \
$O\CopyCoder.obj \
$O\CopyRegister.obj \
$O\DeltaFilter.obj \
$O\Lzma2Decoder.obj \
$O\Lzma2Register.obj \
$O\LzmaDecoder.obj \
$O\LzmaRegister.obj \
$O\PpmdDecoder.obj \
$O\PpmdRegister.obj \
CRYPTO_OBJS = \
$O\7zAes.obj \
$O\7zAesRegister.obj \
$O\MyAes.obj \
C_OBJS = \
$O\Alloc.obj \
$O\Bcj2.obj \
$O\Bra.obj \
$O\Bra86.obj \
$O\BraIA64.obj \
$O\CpuArch.obj \
$O\Delta.obj \
$O\DllSecur.obj \
$O\Lzma2Dec.obj \
$O\Lzma2DecMt.obj \
$O\LzmaDec.obj \
$O\MtDec.obj \
$O\Ppmd7.obj \
$O\Ppmd7Dec.obj \
$O\Threads.obj \
!include "../../Aes.mak"
!include "../../Crc.mak"
!include "../../LzmaDec.mak"
!include "../../Sha256.mak"
!include "../../7zip.mak"

View File

@@ -0,0 +1,204 @@
PROG = 7zCon
# IS_X64 = 1
# USE_ASM = 1
# ST_MODE = 1
include ../../LzmaDec_gcc.mak
LOCAL_FLAGS_ST =
MT_OBJS =
ifdef ST_MODE
LOCAL_FLAGS_ST = -D_7ZIP_ST
ifdef SystemDrive
MT_OBJS = \
$O/Threads.o \
endif
else
MT_OBJS = \
$O/StreamBinder.o \
$O/Synchronization.o \
$O/VirtThread.o \
$O/Threads.o \
endif
LOCAL_FLAGS_SYS =
ifdef SystemDrive
LOCAL_FLAGS_SYS = \
SYS_OBJS = \
$O/DLL.o \
$O/DllSecur.o \
$O/resource.o \
else
SYS_OBJS = \
$O/MyWindows.o \
endif
LOCAL_FLAGS = \
$(LOCAL_FLAGS_ST) \
$(LOCAL_FLAGS_SYS) \
-DEXTRACT_ONLY \
-DNO_READ_FROM_CODER \
-D_SFX \
CURRENT_OBJS = \
$O/SfxCon.o \
CONSOLE_OBJS = \
$O/ConsoleClose.o \
$O/ExtractCallbackConsole.o \
$O/List.o \
$O/MainAr.o \
$O/OpenCallbackConsole.o \
$O/PercentPrinter.o \
$O/UserInputUtils.o \
COMMON_OBJS = \
$O/CommandLineParser.o \
$O/CRC.o \
$O/IntToString.o \
$O/MyString.o \
$O/MyVector.o \
$O/NewHandler.o \
$O/Sha256Prepare.o \
$O/StdInStream.o \
$O/StdOutStream.o \
$O/StringConvert.o \
$O/UTFConvert.o \
$O/Wildcard.o \
WIN_OBJS = \
\
$O/ErrorMsg.o \
$O/FileDir.o \
$O/FileFind.o \
$O/FileIO.o \
$O/FileName.o \
$O/PropVariant.o \
$O/PropVariantConv.o \
\
$O/System.o \
$O/TimeUtils.o \
7ZIP_COMMON_OBJS = \
$O/CreateCoder.o \
$O/CWrappers.o \
$O/FilePathAutoRename.o \
$O/FileStreams.o \
$O/InBuffer.o \
$O/FilterCoder.o \
$O/LimitedStreams.o \
$O/OutBuffer.o \
$O/ProgressUtils.o \
$O/PropId.o \
\
$O/StreamObjects.o \
$O/StreamUtils.o \
\
UI_COMMON_OBJS = \
$O/ArchiveExtractCallback.o \
$O/ArchiveOpenCallback.o \
$O/DefaultName.o \
$O/Extract.o \
$O/ExtractingFilePath.o \
$O/LoadCodecs.o \
$O/OpenArchive.o \
$O/PropIDUtils.o \
AR_OBJS = \
$O/SplitHandler.o \
AR_COMMON_OBJS = \
$O/CoderMixer2.o \
$O/ItemNameUtils.o \
$O/MultiStream.o \
$O/OutStreamWithCRC.o \
7Z_OBJS = \
$O/7zDecode.o \
$O/7zExtract.o \
$O/7zHandler.o \
$O/7zIn.o \
$O/7zRegister.o \
COMPRESS_OBJS = \
$O/Bcj2Coder.o \
$O/Bcj2Register.o \
$O/BcjCoder.o \
$O/BcjRegister.o \
$O/BranchMisc.o \
$O/BranchRegister.o \
$O/CopyCoder.o \
$O/CopyRegister.o \
$O/DeltaFilter.o \
$O/Lzma2Decoder.o \
$O/Lzma2Register.o \
$O/LzmaDecoder.o \
$O/LzmaRegister.o \
$O/PpmdDecoder.o \
$O/PpmdRegister.o \
CRYPTO_OBJS = \
$O/7zAes.o \
$O/7zAesRegister.o \
$O/MyAes.o \
C_OBJS = \
$O/Alloc.o \
$O/Bcj2.o \
$O/Bra.o \
$O/Bra86.o \
$O/BraIA64.o \
$O/CpuArch.o \
$O/Delta.o \
\
$O/Lzma2Dec.o \
$O/Lzma2DecMt.o \
$O/LzmaDec.o \
$O/MtDec.o \
$O/Ppmd7.o \
$O/Ppmd7Dec.o \
$O/Sha256.o \
$O/Sha256Opt.o \
$O/7zCrc.o \
$O/7zCrcOpt.o \
$O/Aes.o \
$O/AesOpt.o \
OBJS = \
$(LZMA_DEC_OPT_OBJS) \
$(C_OBJS) \
$(MT_OBJS) \
$(SYS_OBJS) \
$(COMMON_OBJS) \
$(WIN_OBJS) \
$(COMPRESS_OBJS) \
$(CRYPTO_OBJS) \
$(7ZIP_COMMON_OBJS) \
$(AR_OBJS) \
$(AR_COMMON_OBJS) \
$(7Z_OBJS) \
$(UI_COMMON_OBJS) \
$(CONSOLE_OBJS) \
$(CURRENT_OBJS) \
include ../../7zip_gcc.mak

View File

@@ -0,0 +1,5 @@
#include "../../MyVersionInfo.rc"
MY_VERSION_INFO_APP("7z Console SFX", "7z.sfx")
101 ICON "7z.ico"

View File

@@ -0,0 +1,246 @@
// ExtractCallbackSfx.h
#include "StdAfx.h"
#include "../../../Common/Wildcard.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileFind.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/PropVariant.h"
#include "ExtractCallbackSfx.h"
using namespace NWindows;
using namespace NFile;
using namespace NDir;
static LPCSTR const kCantDeleteFile = "Cannot delete output file";
static LPCSTR const kCantOpenFile = "Cannot open output file";
static LPCSTR const kUnsupportedMethod = "Unsupported Method";
void CExtractCallbackImp::Init(IInArchive *archiveHandler,
const FString &directoryPath,
const UString &itemDefaultName,
const FILETIME &defaultMTime,
UInt32 defaultAttributes)
{
_message.Empty();
_isCorrupt = false;
_itemDefaultName = itemDefaultName;
_defaultMTime = defaultMTime;
_defaultAttributes = defaultAttributes;
_archiveHandler = archiveHandler;
_directoryPath = directoryPath;
NName::NormalizeDirPathPrefix(_directoryPath);
}
HRESULT CExtractCallbackImp::Open_CheckBreak()
{
#ifndef _NO_PROGRESS
return ProgressDialog.Sync.ProcessStopAndPause();
#else
return S_OK;
#endif
}
HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)
{
return S_OK;
}
HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)
{
#ifndef _NO_PROGRESS
return ProgressDialog.Sync.ProcessStopAndPause();
#else
return S_OK;
#endif
}
HRESULT CExtractCallbackImp::Open_Finished()
{
return S_OK;
}
STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 size)
{
#ifndef _NO_PROGRESS
ProgressDialog.Sync.SetProgress(size, 0);
#endif
return S_OK;
}
STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *completeValue)
{
#ifndef _NO_PROGRESS
RINOK(ProgressDialog.Sync.ProcessStopAndPause());
if (completeValue != NULL)
ProgressDialog.Sync.SetPos(*completeValue);
#endif
return S_OK;
}
void CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathParts)
{
FString fullPath = _directoryPath;
FOR_VECTOR (i, dirPathParts)
{
fullPath += us2fs(dirPathParts[i]);
CreateDir(fullPath);
fullPath.Add_PathSepar();
}
}
STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index,
ISequentialOutStream **outStream, Int32 askExtractMode)
{
#ifndef _NO_PROGRESS
if (ProgressDialog.Sync.GetStopped())
return E_ABORT;
#endif
_outFileStream.Release();
UString fullPath;
{
NCOM::CPropVariant prop;
RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop));
if (prop.vt == VT_EMPTY)
fullPath = _itemDefaultName;
else
{
if (prop.vt != VT_BSTR)
return E_FAIL;
fullPath.SetFromBstr(prop.bstrVal);
}
_filePath = fullPath;
}
if (askExtractMode == NArchive::NExtract::NAskMode::kExtract)
{
NCOM::CPropVariant prop;
RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop));
if (prop.vt == VT_EMPTY)
_processedFileInfo.Attributes = _defaultAttributes;
else
{
if (prop.vt != VT_UI4)
return E_FAIL;
_processedFileInfo.Attributes = prop.ulVal;
}
RINOK(_archiveHandler->GetProperty(index, kpidIsDir, &prop));
_processedFileInfo.IsDir = VARIANT_BOOLToBool(prop.boolVal);
bool isAnti = false;
{
NCOM::CPropVariant propTemp;
RINOK(_archiveHandler->GetProperty(index, kpidIsAnti, &propTemp));
if (propTemp.vt == VT_BOOL)
isAnti = VARIANT_BOOLToBool(propTemp.boolVal);
}
RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop));
switch (prop.vt)
{
case VT_EMPTY: _processedFileInfo.MTime = _defaultMTime; break;
case VT_FILETIME: _processedFileInfo.MTime = prop.filetime; break;
default: return E_FAIL;
}
UStringVector pathParts;
SplitPathToParts(fullPath, pathParts);
if (pathParts.IsEmpty())
return E_FAIL;
UString processedPath = fullPath;
if (!_processedFileInfo.IsDir)
pathParts.DeleteBack();
if (!pathParts.IsEmpty())
{
if (!isAnti)
CreateComplexDirectory(pathParts);
}
FString fullProcessedPath = _directoryPath + us2fs(processedPath);
if (_processedFileInfo.IsDir)
{
_diskFilePath = fullProcessedPath;
if (isAnti)
RemoveDir(_diskFilePath);
else
SetDirTime(_diskFilePath, NULL, NULL, &_processedFileInfo.MTime);
return S_OK;
}
NFind::CFileInfo fileInfo;
if (fileInfo.Find(fullProcessedPath))
{
if (!DeleteFileAlways(fullProcessedPath))
{
_message = kCantDeleteFile;
return E_FAIL;
}
}
if (!isAnti)
{
_outFileStreamSpec = new COutFileStream;
CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
if (!_outFileStreamSpec->Create(fullProcessedPath, true))
{
_message = kCantOpenFile;
return E_FAIL;
}
_outFileStream = outStreamLoc;
*outStream = outStreamLoc.Detach();
}
_diskFilePath = fullProcessedPath;
}
else
{
*outStream = NULL;
}
return S_OK;
}
STDMETHODIMP CExtractCallbackImp::PrepareOperation(Int32 askExtractMode)
{
_extractMode = (askExtractMode == NArchive::NExtract::NAskMode::kExtract);
return S_OK;
}
STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 resultEOperationResult)
{
switch (resultEOperationResult)
{
case NArchive::NExtract::NOperationResult::kOK:
break;
default:
{
_outFileStream.Release();
switch (resultEOperationResult)
{
case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
_message = kUnsupportedMethod;
break;
default:
_isCorrupt = true;
}
return E_FAIL;
}
}
if (_outFileStream != NULL)
{
_outFileStreamSpec->SetMTime(&_processedFileInfo.MTime);
RINOK(_outFileStreamSpec->Close());
}
_outFileStream.Release();
if (_extractMode)
SetFileAttrib(_diskFilePath, _processedFileInfo.Attributes);
return S_OK;
}

View File

@@ -0,0 +1,86 @@
// ExtractCallbackSfx.h
#ifndef __EXTRACT_CALLBACK_SFX_H
#define __EXTRACT_CALLBACK_SFX_H
#include "resource.h"
#include "../../../Windows/ResourceString.h"
#include "../../Archive/IArchive.h"
#include "../../Common/FileStreams.h"
#include "../../ICoder.h"
#include "../../UI/FileManager/LangUtils.h"
#ifndef _NO_PROGRESS
#include "../../UI/FileManager/ProgressDialog.h"
#endif
#include "../../UI/Common/ArchiveOpenCallback.h"
class CExtractCallbackImp:
public IArchiveExtractCallback,
public IOpenCallbackUI,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP
INTERFACE_IArchiveExtractCallback(;)
INTERFACE_IOpenCallbackUI(;)
private:
CMyComPtr<IInArchive> _archiveHandler;
FString _directoryPath;
UString _filePath;
FString _diskFilePath;
bool _extractMode;
struct CProcessedFileInfo
{
FILETIME MTime;
bool IsDir;
UInt32 Attributes;
} _processedFileInfo;
COutFileStream *_outFileStreamSpec;
CMyComPtr<ISequentialOutStream> _outFileStream;
UString _itemDefaultName;
FILETIME _defaultMTime;
UInt32 _defaultAttributes;
void CreateComplexDirectory(const UStringVector &dirPathParts);
public:
#ifndef _NO_PROGRESS
CProgressDialog ProgressDialog;
#endif
bool _isCorrupt;
UString _message;
void Init(IInArchive *archiveHandler,
const FString &directoryPath,
const UString &itemDefaultName,
const FILETIME &defaultMTime,
UInt32 defaultAttributes);
#ifndef _NO_PROGRESS
HRESULT StartProgressDialog(const UString &title, NWindows::CThread &thread)
{
ProgressDialog.Create(title, thread, 0);
{
ProgressDialog.SetText(LangString(IDS_PROGRESS_EXTRACTING));
}
ProgressDialog.Show(SW_SHOWNORMAL);
return S_OK;
}
virtual ~CExtractCallbackImp() { ProgressDialog.Destroy(); }
#endif
};
#endif

View File

@@ -0,0 +1,137 @@
// ExtractEngine.cpp
#include "StdAfx.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/Thread.h"
#include "../../UI/Common/OpenArchive.h"
#include "../../UI/FileManager/FormatUtils.h"
#include "../../UI/FileManager/LangUtils.h"
#include "ExtractCallbackSfx.h"
#include "ExtractEngine.h"
using namespace NWindows;
using namespace NFile;
using namespace NDir;
static LPCSTR const kCantFindArchive = "Cannot find archive file";
static LPCSTR const kCantOpenArchive = "Cannot open the file as archive";
struct CThreadExtracting
{
CCodecs *Codecs;
FString FileName;
FString DestFolder;
CExtractCallbackImp *ExtractCallbackSpec;
CMyComPtr<IArchiveExtractCallback> ExtractCallback;
CArchiveLink ArchiveLink;
HRESULT Result;
UString ErrorMessage;
void Process2()
{
NFind::CFileInfo fi;
if (!fi.Find(FileName))
{
ErrorMessage = kCantFindArchive;
Result = E_FAIL;
return;
}
CObjectVector<COpenType> incl;
CIntVector excl;
COpenOptions options;
options.codecs = Codecs;
options.types = &incl;
options.excludedFormats = &excl;
options.filePath = fs2us(FileName);
Result = ArchiveLink.Open2(options, ExtractCallbackSpec);
if (Result != S_OK)
{
ErrorMessage = kCantOpenArchive;
return;
}
FString dirPath = DestFolder;
NName::NormalizeDirPathPrefix(dirPath);
if (!CreateComplexDir(dirPath))
{
ErrorMessage = MyFormatNew(IDS_CANNOT_CREATE_FOLDER,
#ifdef LANG
0x02000603,
#endif
fs2us(dirPath));
Result = E_FAIL;
return;
}
ExtractCallbackSpec->Init(ArchiveLink.GetArchive(), dirPath, (UString)"Default", fi.MTime, 0);
Result = ArchiveLink.GetArchive()->Extract(0, (UInt32)(Int32)-1 , BoolToInt(false), ExtractCallback);
}
void Process()
{
try
{
#ifndef _NO_PROGRESS
CProgressCloser closer(ExtractCallbackSpec->ProgressDialog);
#endif
Process2();
}
catch(...) { Result = E_FAIL; }
}
static THREAD_FUNC_DECL MyThreadFunction(void *param)
{
((CThreadExtracting *)param)->Process();
return 0;
}
};
HRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString &destFolder,
bool showProgress, bool &isCorrupt, UString &errorMessage)
{
isCorrupt = false;
CThreadExtracting t;
t.Codecs = codecs;
t.FileName = fileName;
t.DestFolder = destFolder;
t.ExtractCallbackSpec = new CExtractCallbackImp;
t.ExtractCallback = t.ExtractCallbackSpec;
#ifndef _NO_PROGRESS
if (showProgress)
{
t.ExtractCallbackSpec->ProgressDialog.IconID = IDI_ICON;
NWindows::CThread thread;
RINOK(thread.Create(CThreadExtracting::MyThreadFunction, &t));
UString title;
LangString(IDS_PROGRESS_EXTRACTING, title);
t.ExtractCallbackSpec->StartProgressDialog(title, thread);
}
else
#endif
{
t.Process2();
}
errorMessage = t.ErrorMessage;
if (errorMessage.IsEmpty())
errorMessage = t.ExtractCallbackSpec->_message;
isCorrupt = t.ExtractCallbackSpec->_isCorrupt;
return t.Result;
}

View File

@@ -0,0 +1,11 @@
// ExtractEngine.h
#ifndef __EXTRACT_ENGINE_H
#define __EXTRACT_ENGINE_H
#include "../../UI/Common/LoadCodecs.h"
HRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString &destFolder,
bool showProgress, bool &isCorrupt, UString &errorMessage);
#endif

View File

@@ -0,0 +1,803 @@
# Microsoft Developer Studio Project File - Name="SFXSetup" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Application" 0x0101
CFG=SFXSetup - 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 "SFXSetup.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 "SFXSetup.mak" CFG="SFXSetup - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "SFXSetup - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "SFXSetup - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE "SFXSetup - Win32 ReleaseD" (based on "Win32 (x86) Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "SFXSetup - 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 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /Gz /MT /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "_SFX" /D "_NO_CRYPTO" /Yu"StdAfx.h" /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x419 /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 /subsystem:windows /machine:I386
# ADD LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7zS.sfx" /opt:NOWIN98
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "SFXSetup - 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 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "_SFX" /D "_NO_CRYPTO" /Yu"StdAfx.h" /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x419 /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 /subsystem:windows /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\UTIL\7zSfxS.exe" /pdbtype:sept
!ELSEIF "$(CFG)" == "SFXSetup - Win32 ReleaseD"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "ReleaseD"
# PROP BASE Intermediate_Dir "ReleaseD"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "ReleaseD"
# PROP Intermediate_Dir "ReleaseD"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "_SFX" /Yu"StdAfx.h" /FD /c
# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "_SFX" /D "_NO_CRYPTO" /Yu"StdAfx.h" /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x419 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\UTIL\7zWinSR.exe"
# SUBTRACT BASE LINK32 /debug /nodefaultlib
# ADD LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7zSD.sfx" /opt:NOWIN98
# SUBTRACT LINK32 /pdb:none
!ENDIF
# Begin Target
# Name "SFXSetup - Win32 Release"
# Name "SFXSetup - Win32 Debug"
# Name "SFXSetup - Win32 ReleaseD"
# Begin Group "Spec"
# PROP Default_Filter ""
# 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 "Interface"
# PROP Default_Filter ""
# End Group
# Begin Group "7z"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\Archive\7z\7zDecode.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\7z\7zDecode.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\7z\7zExtract.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\7z\7zHandler.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\7z\7zHandler.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\7z\7zHeader.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\7z\7zIn.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\7z\7zIn.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\7z\7zItem.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\7z\7zRegister.cpp
# End Source File
# End Group
# Begin Group "Archive Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\Archive\Common\CoderMixer2.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Common\CoderMixer2.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Common\ItemNameUtils.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Common\ItemNameUtils.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Common\OutStreamWithCRC.h
# End Source File
# End Group
# Begin Group "Compress"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\Compress\Bcj2Coder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\Bcj2Register.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\BcjCoder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\BcjRegister.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\BranchMisc.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\BranchMisc.h
# End Source File
# Begin Source File
SOURCE=..\..\Compress\BranchRegister.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\CopyCoder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\CopyRegister.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\DeltaFilter.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\Lzma2Decoder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\Lzma2Decoder.h
# End Source File
# Begin Source File
SOURCE=..\..\Compress\Lzma2Register.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\LzmaDecoder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\LzmaRegister.cpp
# End Source File
# End Group
# Begin Group "Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\Common\CommandLineParser.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\CommandLineParser.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\CRC.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\CRC.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\TextConfig.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\TextConfig.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\UTFConvert.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\UTFConvert.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 "Windows"
# PROP Default_Filter ""
# Begin Group "Control"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\Windows\Control\Dialog.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Control\Dialog.h
# End Source File
# End Group
# Begin Source File
SOURCE=..\..\..\Windows\DLL.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\DLL.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\ErrorMsg.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\ErrorMsg.h
# End Source File
# 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\PropVariant.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\PropVariant.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\ResourceString.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\ResourceString.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\Window.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Window.h
# End Source File
# End Group
# Begin Group "7z 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\CWrappers.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\CWrappers.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\FileStreams.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\FileStreams.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\InBuffer.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\InBuffer.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\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\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 "UI"
# PROP Default_Filter ""
# Begin Group "Explorer"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\UI\Explorer\MyMessages.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Explorer\MyMessages.h
# End Source File
# End Group
# Begin Group "UI Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\ArchiveOpenCallback.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\DefaultName.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\DefaultName.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\ExtractMode.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\LoadCodecs.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\LoadCodecs.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\OpenArchive.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\OpenArchive.h
# End Source File
# End Group
# End Group
# Begin Group "File Manager"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\UI\FileManager\FormatUtils.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\FileManager\FormatUtils.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\FileManager\LangUtils.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\FileManager\ProgressDialog.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\FileManager\ProgressDialog.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\Bcj2.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Bcj2.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Bra.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Bra.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Bra86.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\BraIA64.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\CpuArch.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\CpuArch.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Delta.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Delta.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\DllSecur.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\DllSecur.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Lzma2Dec.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Lzma2Dec.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Lzma2DecMt.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Lzma2DecMt.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\LzmaDec.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\LzmaDec.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\MtDec.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\MtDec.h
# 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
# Begin Source File
SOURCE=.\ExtractCallbackSfx.cpp
# End Source File
# Begin Source File
SOURCE=.\ExtractCallbackSfx.h
# End Source File
# Begin Source File
SOURCE=.\ExtractEngine.cpp
# End Source File
# Begin Source File
SOURCE=.\ExtractEngine.h
# End Source File
# Begin Source File
SOURCE=.\setup.ico
# End Source File
# Begin Source File
SOURCE=.\SfxSetup.cpp
# End Source File
# End Target
# End Project

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: "SFXSetup"=.\SFXSetup.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -0,0 +1,366 @@
// Main.cpp
#include "StdAfx.h"
#include "../../../Common/MyWindows.h"
#include "../../../Common/MyInitGuid.h"
#include "../../../Common/CommandLineParser.h"
#include "../../../Common/StringConvert.h"
#include "../../../Common/TextConfig.h"
#include "../../../Windows/DLL.h"
#include "../../../Windows/ErrorMsg.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileFind.h"
#include "../../../Windows/FileIO.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/NtCheck.h"
#include "../../../Windows/ResourceString.h"
#include "../../UI/Explorer/MyMessages.h"
#include "ExtractEngine.h"
#include "../../../../C/DllSecur.h"
#include "resource.h"
using namespace NWindows;
using namespace NFile;
using namespace NDir;
HINSTANCE g_hInstance;
static CFSTR const kTempDirPrefix = FTEXT("7zS");
#define _SHELL_EXECUTE
static bool ReadDataString(CFSTR fileName, LPCSTR startID,
LPCSTR endID, AString &stringResult)
{
stringResult.Empty();
NIO::CInFile inFile;
if (!inFile.Open(fileName))
return false;
const size_t kBufferSize = (1 << 12);
Byte buffer[kBufferSize];
const unsigned signatureStartSize = MyStringLen(startID);
const unsigned signatureEndSize = MyStringLen(endID);
size_t numBytesPrev = 0;
bool writeMode = false;
UInt64 posTotal = 0;
for (;;)
{
if (posTotal > (1 << 20))
return (stringResult.IsEmpty());
const size_t numReadBytes = kBufferSize - numBytesPrev;
size_t processedSize;
if (!inFile.ReadFull(buffer + numBytesPrev, numReadBytes, processedSize))
return false;
if (processedSize == 0)
return true;
const size_t numBytesInBuffer = numBytesPrev + processedSize;
UInt32 pos = 0;
for (;;)
{
if (writeMode)
{
if (pos + signatureEndSize > numBytesInBuffer)
break;
if (memcmp(buffer + pos, endID, signatureEndSize) == 0)
return true;
char b = buffer[pos];
if (b == 0)
return false;
stringResult += b;
pos++;
}
else
{
if (pos + signatureStartSize > numBytesInBuffer)
break;
if (memcmp(buffer + pos, startID, signatureStartSize) == 0)
{
writeMode = true;
pos += signatureStartSize;
}
else
pos++;
}
}
numBytesPrev = numBytesInBuffer - pos;
posTotal += pos;
memmove(buffer, buffer + pos, numBytesPrev);
}
}
static char kStartID[] = { ',','!','@','I','n','s','t','a','l','l','@','!','U','T','F','-','8','!', 0 };
static char kEndID[] = { ',','!','@','I','n','s','t','a','l','l','E','n','d','@','!', 0 };
struct CInstallIDInit
{
CInstallIDInit()
{
kStartID[0] = ';';
kEndID[0] = ';';
};
} g_CInstallIDInit;
#if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE)
#define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return 1;
#endif
static void ShowErrorMessageSpec(const UString &name)
{
UString message = NError::MyFormatMessage(::GetLastError());
int pos = message.Find(L"%1");
if (pos >= 0)
{
message.Delete(pos, 2);
message.Insert(pos, name);
}
ShowErrorMessage(NULL, message);
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
#ifdef UNDER_CE
LPWSTR
#else
LPSTR
#endif
/* lpCmdLine */,int /* nCmdShow */)
{
g_hInstance = (HINSTANCE)hInstance;
NT_CHECK
#ifdef _WIN32
LoadSecurityDlls();
#endif
// InitCommonControls();
UString archiveName, switches;
#ifdef _SHELL_EXECUTE
UString executeFile, executeParameters;
#endif
NCommandLineParser::SplitCommandLine(GetCommandLineW(), archiveName, switches);
FString fullPath;
NDLL::MyGetModuleFileName(fullPath);
switches.Trim();
bool assumeYes = false;
if (switches.IsPrefixedBy_Ascii_NoCase("-y"))
{
assumeYes = true;
switches = switches.Ptr(2);
switches.Trim();
}
AString config;
if (!ReadDataString(fullPath, kStartID, kEndID, config))
{
if (!assumeYes)
ShowErrorMessage(L"Can't load config info");
return 1;
}
UString dirPrefix ("." STRING_PATH_SEPARATOR);
UString appLaunched;
bool showProgress = true;
if (!config.IsEmpty())
{
CObjectVector<CTextConfigPair> pairs;
if (!GetTextConfig(config, pairs))
{
if (!assumeYes)
ShowErrorMessage(L"Config failed");
return 1;
}
UString friendlyName = GetTextConfigValue(pairs, "Title");
UString installPrompt = GetTextConfigValue(pairs, "BeginPrompt");
UString progress = GetTextConfigValue(pairs, "Progress");
if (progress.IsEqualTo_Ascii_NoCase("no"))
showProgress = false;
int index = FindTextConfigItem(pairs, "Directory");
if (index >= 0)
dirPrefix = pairs[index].String;
if (!installPrompt.IsEmpty() && !assumeYes)
{
if (MessageBoxW(0, installPrompt, friendlyName, MB_YESNO |
MB_ICONQUESTION) != IDYES)
return 0;
}
appLaunched = GetTextConfigValue(pairs, "RunProgram");
#ifdef _SHELL_EXECUTE
executeFile = GetTextConfigValue(pairs, "ExecuteFile");
executeParameters = GetTextConfigValue(pairs, "ExecuteParameters");
#endif
}
CTempDir tempDir;
if (!tempDir.Create(kTempDirPrefix))
{
if (!assumeYes)
ShowErrorMessage(L"Cannot create temp folder archive");
return 1;
}
CCodecs *codecs = new CCodecs;
CMyComPtr<IUnknown> compressCodecsInfo = codecs;
{
HRESULT result = codecs->Load();
if (result != S_OK)
{
ShowErrorMessage(L"Cannot load codecs");
return 1;
}
}
const FString tempDirPath = tempDir.GetPath();
// tempDirPath = L"M:\\1\\"; // to test low disk space
{
bool isCorrupt = false;
UString errorMessage;
HRESULT result = ExtractArchive(codecs, fullPath, tempDirPath, showProgress,
isCorrupt, errorMessage);
if (result != S_OK)
{
if (!assumeYes)
{
if (result == S_FALSE || isCorrupt)
{
NWindows::MyLoadString(IDS_EXTRACTION_ERROR_MESSAGE, errorMessage);
result = E_FAIL;
}
if (result != E_ABORT)
{
if (errorMessage.IsEmpty())
errorMessage = NError::MyFormatMessage(result);
::MessageBoxW(0, errorMessage, NWindows::MyLoadString(IDS_EXTRACTION_ERROR_TITLE), MB_ICONERROR);
}
}
return 1;
}
}
#ifndef UNDER_CE
CCurrentDirRestorer currentDirRestorer;
if (!SetCurrentDir(tempDirPath))
return 1;
#endif
HANDLE hProcess = 0;
#ifdef _SHELL_EXECUTE
if (!executeFile.IsEmpty())
{
CSysString filePath (GetSystemString(executeFile));
SHELLEXECUTEINFO execInfo;
execInfo.cbSize = sizeof(execInfo);
execInfo.fMask = SEE_MASK_NOCLOSEPROCESS
#ifndef UNDER_CE
| SEE_MASK_FLAG_DDEWAIT
#endif
;
execInfo.hwnd = NULL;
execInfo.lpVerb = NULL;
execInfo.lpFile = filePath;
if (!switches.IsEmpty())
{
executeParameters.Add_Space_if_NotEmpty();
executeParameters += switches;
}
CSysString parametersSys (GetSystemString(executeParameters));
if (parametersSys.IsEmpty())
execInfo.lpParameters = NULL;
else
execInfo.lpParameters = parametersSys;
execInfo.lpDirectory = NULL;
execInfo.nShow = SW_SHOWNORMAL;
execInfo.hProcess = 0;
/* BOOL success = */ ::ShellExecuteEx(&execInfo);
UINT32 result = (UINT32)(UINT_PTR)execInfo.hInstApp;
if (result <= 32)
{
if (!assumeYes)
ShowErrorMessage(L"Cannot open file");
return 1;
}
hProcess = execInfo.hProcess;
}
else
#endif
{
if (appLaunched.IsEmpty())
{
appLaunched = L"setup.exe";
if (!NFind::DoesFileExist_FollowLink(us2fs(appLaunched)))
{
if (!assumeYes)
ShowErrorMessage(L"Cannot find setup.exe");
return 1;
}
}
{
FString s2 = tempDirPath;
NName::NormalizeDirPathPrefix(s2);
appLaunched.Replace(L"%%T" WSTRING_PATH_SEPARATOR, fs2us(s2));
}
UString appNameForError = appLaunched; // actually we need to rtemove parameters also
appLaunched.Replace(L"%%T", fs2us(tempDirPath));
if (!switches.IsEmpty())
{
appLaunched.Add_Space();
appLaunched += switches;
}
STARTUPINFO startupInfo;
startupInfo.cb = sizeof(startupInfo);
startupInfo.lpReserved = 0;
startupInfo.lpDesktop = 0;
startupInfo.lpTitle = 0;
startupInfo.dwFlags = 0;
startupInfo.cbReserved2 = 0;
startupInfo.lpReserved2 = 0;
PROCESS_INFORMATION processInformation;
CSysString appLaunchedSys (GetSystemString(dirPrefix + appLaunched));
BOOL createResult = CreateProcess(NULL, (LPTSTR)(LPCTSTR)appLaunchedSys,
NULL, NULL, FALSE, 0, NULL, NULL /*tempDir.GetPath() */,
&startupInfo, &processInformation);
if (createResult == 0)
{
if (!assumeYes)
{
// we print name of exe file, if error message is
// ERROR_BAD_EXE_FORMAT: "%1 is not a valid Win32 application".
ShowErrorMessageSpec(appNameForError);
}
return 1;
}
::CloseHandle(processInformation.hThread);
hProcess = processInformation.hProcess;
}
if (hProcess != 0)
{
WaitForSingleObject(hProcess, INFINITE);
::CloseHandle(hProcess);
}
return 0;
}

Some files were not shown because too many files have changed in this diff Show More