mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 21:14:58 -06:00
15.05
This commit is contained in:
committed by
Kornel Lesiński
parent
0713a3ab80
commit
54490d51d5
@@ -350,14 +350,6 @@ SOURCE=..\Common\CoderMixer2.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\CoderMixer2MT.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\CoderMixer2MT.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\CrossThreadProgress.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
@@ -9,37 +9,62 @@
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
struct CMethodFull: public CProps
|
||||
struct CMethodFull: public CMethodProps
|
||||
{
|
||||
CMethodId Id;
|
||||
UInt32 NumInStreams;
|
||||
UInt32 NumOutStreams;
|
||||
UInt32 NumStreams;
|
||||
|
||||
bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }
|
||||
bool IsSimpleCoder() const { return NumStreams == 1; }
|
||||
};
|
||||
|
||||
struct CBind
|
||||
struct CBond2
|
||||
{
|
||||
UInt32 InCoder;
|
||||
UInt32 InStream;
|
||||
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<CBind> Binds;
|
||||
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;
|
||||
|
||||
bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }
|
||||
CCompressionMethodMode(): PasswordIsDefined(false)
|
||||
CCompressionMethodMode():
|
||||
DefaultMethod_was_Inserted(false),
|
||||
Filter_was_Inserted(false),
|
||||
PasswordIsDefined(false)
|
||||
#ifndef _7ZIP_ST
|
||||
, NumThreads(1)
|
||||
, MultiThreadMixer(true)
|
||||
#endif
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
#include "../../Common/LockedStream.h"
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
#include "../../Common/StreamObjects.h"
|
||||
|
||||
@@ -12,50 +11,70 @@
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,
|
||||
CBindInfoEx &bindInfo)
|
||||
class CDecProgress:
|
||||
public ICompressProgressInfo,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
bindInfo.Clear();
|
||||
bindInfo.BindPairs.ClearAndSetSize(folder.BindPairs.Size());
|
||||
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.BindPairs.Size(); i++)
|
||||
for (i = 0; i < folder.Bonds.Size(); i++)
|
||||
{
|
||||
NCoderMixer::CBindPair &bindPair = bindInfo.BindPairs[i];
|
||||
bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;
|
||||
bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;
|
||||
NCoderMixer2::CBond &bond = bi.Bonds[i];
|
||||
const N7z::CBond &folderBond = folder.Bonds[i];
|
||||
bond.PackIndex = folderBond.PackIndex;
|
||||
bond.UnpackIndex = folderBond.UnpackIndex;
|
||||
}
|
||||
|
||||
bindInfo.Coders.ClearAndSetSize(folder.Coders.Size());
|
||||
bindInfo.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());
|
||||
|
||||
UInt32 outStreamIndex = 0;
|
||||
bi.Coders.ClearAndSetSize(folder.Coders.Size());
|
||||
bi.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());
|
||||
for (i = 0; i < folder.Coders.Size(); i++)
|
||||
{
|
||||
NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
|
||||
const CCoderInfo &coderInfo = folder.Coders[i];
|
||||
coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;
|
||||
coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;
|
||||
bindInfo.CoderMethodIDs[i] = coderInfo.MethodID;
|
||||
for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)
|
||||
if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
|
||||
bindInfo.OutStreams.Add(outStreamIndex);
|
||||
bi.Coders[i].NumStreams = coderInfo.NumStreams;
|
||||
bi.CoderMethodIDs[i] = coderInfo.MethodID;
|
||||
}
|
||||
bindInfo.InStreams.ClearAndSetSize(folder.PackStreams.Size());
|
||||
|
||||
/*
|
||||
if (!bi.SetUnpackCoder())
|
||||
throw 1112;
|
||||
*/
|
||||
bi.UnpackCoder = folder.UnpackCoder;
|
||||
bi.PackStreams.ClearAndSetSize(folder.PackStreams.Size());
|
||||
for (i = 0; i < folder.PackStreams.Size(); i++)
|
||||
bindInfo.InStreams[i] = (UInt32)folder.PackStreams[i];
|
||||
bi.PackStreams[i] = folder.PackStreams[i];
|
||||
}
|
||||
|
||||
static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1,
|
||||
const NCoderMixer::CCoderStreamsInfo &a2)
|
||||
static inline bool AreCodersEqual(
|
||||
const NCoderMixer2::CCoderStreamsInfo &a1,
|
||||
const NCoderMixer2::CCoderStreamsInfo &a2)
|
||||
{
|
||||
return (a1.NumInStreams == a2.NumInStreams) &&
|
||||
(a1.NumOutStreams == a2.NumOutStreams);
|
||||
return (a1.NumStreams == a2.NumStreams);
|
||||
}
|
||||
|
||||
static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2)
|
||||
static inline bool AreBondsEqual(
|
||||
const NCoderMixer2::CBond &a1,
|
||||
const NCoderMixer2::CBond &a2)
|
||||
{
|
||||
return (a1.InIndex == a2.InIndex) &&
|
||||
(a1.OutIndex == a2.OutIndex);
|
||||
return
|
||||
(a1.PackIndex == a2.PackIndex) &&
|
||||
(a1.UnpackIndex == a2.UnpackIndex);
|
||||
}
|
||||
|
||||
static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
|
||||
@@ -66,186 +85,284 @@ static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
|
||||
for (i = 0; i < a1.Coders.Size(); i++)
|
||||
if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
|
||||
return false;
|
||||
if (a1.BindPairs.Size() != a2.BindPairs.Size())
|
||||
|
||||
if (a1.Bonds.Size() != a2.Bonds.Size())
|
||||
return false;
|
||||
for (i = 0; i < a1.BindPairs.Size(); i++)
|
||||
if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))
|
||||
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.InStreams.Size() != a2.InStreams.Size())
|
||||
|
||||
if (a1.PackStreams.Size() != a2.PackStreams.Size())
|
||||
return false;
|
||||
if (a1.OutStreams.Size() != a2.OutStreams.Size())
|
||||
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 multiThread)
|
||||
CDecoder::CDecoder(bool useMixerMT):
|
||||
_bindInfoPrev_Defined(false),
|
||||
_useMixerMT(useMixerMT)
|
||||
{}
|
||||
|
||||
|
||||
struct CLockedInStream:
|
||||
public IUnknown,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
#ifndef _ST_MODE
|
||||
multiThread = true;
|
||||
CMyComPtr<IInStream> Stream;
|
||||
UInt64 Pos;
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
#ifdef USE_MIXER_MT
|
||||
NWindows::NSynchronization::CCriticalSection CriticalSection;
|
||||
#endif
|
||||
_multiThread = multiThread;
|
||||
_bindInfoExPrevIsDefined = false;
|
||||
};
|
||||
|
||||
|
||||
#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(_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(_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, int folderIndex,
|
||||
ISequentialOutStream *outStream,
|
||||
ICompressProgressInfo *compressProgress
|
||||
const CFolders &folders, unsigned folderIndex,
|
||||
const UInt64 *unpackSize
|
||||
|
||||
, ISequentialOutStream *outStream
|
||||
, ICompressProgressInfo *compressProgress
|
||||
, ISequentialInStream **
|
||||
|
||||
#ifdef USE_MIXER_ST
|
||||
inStreamMainRes
|
||||
#endif
|
||||
|
||||
_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
|
||||
#if !defined(_7ZIP_ST) && !defined(_SFX)
|
||||
, bool mtMode, UInt32 numThreads
|
||||
#endif
|
||||
)
|
||||
{
|
||||
const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]];
|
||||
CFolder folderInfo;
|
||||
folders.ParseFolderInfo(folderIndex, folderInfo);
|
||||
CFolderEx folderInfo;
|
||||
folders.ParseFolderEx(folderIndex, folderInfo);
|
||||
|
||||
if (!folderInfo.CheckStructure(folders.GetNumFolderUnpackSizes(folderIndex)))
|
||||
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
|
||||
*/
|
||||
|
||||
CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
|
||||
|
||||
CLockedInStream lockedInStream;
|
||||
lockedInStream.Init(inStream);
|
||||
|
||||
for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)
|
||||
if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev))
|
||||
{
|
||||
CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp;
|
||||
CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
|
||||
lockedStreamImpSpec->Init(&lockedInStream, startPos + packPositions[j]);
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> inStream = streamSpec;
|
||||
streamSpec->SetStream(lockedStreamImp);
|
||||
streamSpec->Init(packPositions[j + 1] - packPositions[j]);
|
||||
inStreams.Add(inStream);
|
||||
}
|
||||
|
||||
unsigned numCoders = folderInfo.Coders.Size();
|
||||
|
||||
CBindInfoEx bindInfo;
|
||||
ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
|
||||
bool createNewCoders;
|
||||
if (!_bindInfoExPrevIsDefined)
|
||||
createNewCoders = true;
|
||||
else
|
||||
createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
|
||||
if (createNewCoders)
|
||||
{
|
||||
unsigned i;
|
||||
_decoders.Clear();
|
||||
// _decoders2.Clear();
|
||||
|
||||
_mixerCoder.Release();
|
||||
_mixerRef.Release();
|
||||
|
||||
if (_multiThread)
|
||||
#ifdef USE_MIXER_MT
|
||||
#ifdef USE_MIXER_ST
|
||||
if (_useMixerMT)
|
||||
#endif
|
||||
{
|
||||
_mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT;
|
||||
_mixerCoder = _mixerCoderMTSpec;
|
||||
_mixerCoderCommon = _mixerCoderMTSpec;
|
||||
_mixerMT = new NCoderMixer2::CMixerMT(false);
|
||||
_mixerRef = _mixerMT;
|
||||
_mixer = _mixerMT;
|
||||
}
|
||||
#ifdef USE_MIXER_ST
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
#ifdef _ST_MODE
|
||||
_mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST;
|
||||
_mixerCoder = _mixerCoderSTSpec;
|
||||
_mixerCoderCommon = _mixerCoderSTSpec;
|
||||
#ifdef USE_MIXER_ST
|
||||
_mixerST = new NCoderMixer2::CMixerST(false);
|
||||
_mixerRef = _mixerST;
|
||||
_mixer = _mixerST;
|
||||
#endif
|
||||
}
|
||||
RINOK(_mixerCoderCommon->SetBindInfo(bindInfo));
|
||||
|
||||
for (i = 0; i < numCoders; i++)
|
||||
RINOK(_mixer->SetBindInfo(bindInfo));
|
||||
|
||||
FOR_VECTOR(i, folderInfo.Coders)
|
||||
{
|
||||
const CCoderInfo &coderInfo = folderInfo.Coders[i];
|
||||
|
||||
|
||||
CMyComPtr<ICompressCoder> decoder;
|
||||
CMyComPtr<ICompressCoder2> decoder2;
|
||||
CCreatedCoder cod;
|
||||
RINOK(CreateCoder(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
coderInfo.MethodID, decoder, decoder2, false));
|
||||
CMyComPtr<IUnknown> decoderUnknown;
|
||||
coderInfo.MethodID, false, cod));
|
||||
|
||||
if (coderInfo.IsSimpleCoder())
|
||||
{
|
||||
if (decoder == 0)
|
||||
if (!cod.Coder)
|
||||
return E_NOTIMPL;
|
||||
|
||||
decoderUnknown = (IUnknown *)decoder;
|
||||
|
||||
if (_multiThread)
|
||||
_mixerCoderMTSpec->AddCoder(decoder);
|
||||
#ifdef _ST_MODE
|
||||
else
|
||||
_mixerCoderSTSpec->AddCoder(decoder, false);
|
||||
#endif
|
||||
// CMethodId m = coderInfo.MethodID;
|
||||
// isFilter = (IsFilterMethod(m) || m == k_AES);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (decoder2 == 0)
|
||||
if (!cod.Coder2 || cod.NumStreams != coderInfo.NumStreams)
|
||||
return E_NOTIMPL;
|
||||
decoderUnknown = (IUnknown *)decoder2;
|
||||
if (_multiThread)
|
||||
_mixerCoderMTSpec->AddCoder2(decoder2);
|
||||
#ifdef _ST_MODE
|
||||
else
|
||||
_mixerCoderSTSpec->AddCoder2(decoder2, false);
|
||||
#endif
|
||||
}
|
||||
_decoders.Add(decoderUnknown);
|
||||
_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
|
||||
*/
|
||||
}
|
||||
_bindInfoExPrev = bindInfo;
|
||||
_bindInfoExPrevIsDefined = true;
|
||||
|
||||
_bindInfoPrev = bindInfo;
|
||||
_bindInfoPrev_Defined = true;
|
||||
}
|
||||
unsigned i;
|
||||
_mixerCoderCommon->ReInit();
|
||||
|
||||
_mixer->ReInit();
|
||||
|
||||
UInt32 packStreamIndex = 0;
|
||||
UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex];
|
||||
UInt32 unpackStreamIndex = unpackStreamIndexStart;
|
||||
UInt32 coderIndex = 0;
|
||||
// UInt32 coder2Index = 0;
|
||||
|
||||
for (i = 0; i < numCoders; i++)
|
||||
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < folderInfo.Coders.Size(); i++)
|
||||
{
|
||||
const CCoderInfo &coderInfo = folderInfo.Coders[i];
|
||||
CMyComPtr<IUnknown> &decoder = _decoders[coderIndex];
|
||||
|
||||
IUnknown *decoder = _mixer->GetCoder(i).GetUnknown();
|
||||
|
||||
{
|
||||
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
|
||||
decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
|
||||
decoder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);
|
||||
if (setDecoderProperties)
|
||||
{
|
||||
const CByteBuffer &props = coderInfo.Props;
|
||||
size_t size = props.Size();
|
||||
if (size > 0xFFFFFFFF)
|
||||
return E_NOTIMPL;
|
||||
// if (size > 0)
|
||||
{
|
||||
RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size));
|
||||
}
|
||||
HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size);
|
||||
if (res == E_INVALIDARG)
|
||||
res = E_NOTIMPL;
|
||||
RINOK(res);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,7 +370,7 @@ HRESULT CDecoder::Decode(
|
||||
if (mtMode)
|
||||
{
|
||||
CMyComPtr<ICompressSetCoderMt> setCoderMt;
|
||||
decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
|
||||
decoder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);
|
||||
if (setCoderMt)
|
||||
{
|
||||
RINOK(setCoderMt->SetNumberOfThreads(numThreads));
|
||||
@@ -264,7 +381,7 @@ HRESULT CDecoder::Decode(
|
||||
#ifndef _NO_CRYPTO
|
||||
{
|
||||
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
|
||||
decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
|
||||
decoder->QueryInterface(IID_ICryptoSetPassword, (void **)&cryptoSetPassword);
|
||||
if (cryptoSetPassword)
|
||||
{
|
||||
isEncrypted = true;
|
||||
@@ -273,9 +390,13 @@ HRESULT CDecoder::Decode(
|
||||
CMyComBSTR passwordBSTR;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR));
|
||||
passwordIsDefined = true;
|
||||
password.Empty();
|
||||
size_t len = 0;
|
||||
if (passwordBSTR)
|
||||
len = MyStringLen((BSTR)passwordBSTR);
|
||||
{
|
||||
password = passwordBSTR;
|
||||
len = password.Len();
|
||||
}
|
||||
CByteBuffer buffer(len * 2);
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
@@ -288,56 +409,129 @@ HRESULT CDecoder::Decode(
|
||||
}
|
||||
#endif
|
||||
|
||||
coderIndex++;
|
||||
|
||||
UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;
|
||||
UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;
|
||||
CObjArray<UInt64> packSizes(numInStreams);
|
||||
CObjArray<const UInt64 *> packSizesPointers(numInStreams);
|
||||
CObjArray<const UInt64 *> unpackSizesPointers(numOutStreams);
|
||||
UInt32 j;
|
||||
|
||||
for (j = 0; j < numOutStreams; j++, unpackStreamIndex++)
|
||||
unpackSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndex];
|
||||
|
||||
for (j = 0; j < numInStreams; j++, packStreamIndex++)
|
||||
{
|
||||
int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);
|
||||
if (bindPairIndex >= 0)
|
||||
packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + (UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex];
|
||||
else
|
||||
CMyComPtr<ICompressSetFinishMode> setFinishMode;
|
||||
decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode);
|
||||
if (setFinishMode)
|
||||
{
|
||||
int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);
|
||||
if (index < 0)
|
||||
return S_FALSE; // check it
|
||||
packSizes[j] = packPositions[index + 1] - packPositions[index];
|
||||
packSizesPointers[j] = &packSizes[j];
|
||||
RINOK(setFinishMode->SetFinishMode(BoolToInt(fullUnpack)));
|
||||
}
|
||||
}
|
||||
|
||||
_mixerCoderCommon->SetCoderInfo(i, packSizesPointers, unpackSizesPointers);
|
||||
}
|
||||
UInt32 mainCoder, temp;
|
||||
bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
if (_multiThread)
|
||||
_mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);
|
||||
/*
|
||||
else
|
||||
_mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;
|
||||
*/
|
||||
const UInt64 *unpackSizesPointer =
|
||||
(unpackSize && i == bindInfo.UnpackCoder) ?
|
||||
unpackSize :
|
||||
&folders.CoderUnpackSizes[unpackStreamIndexStart + i];
|
||||
|
||||
_mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers);
|
||||
}
|
||||
|
||||
if (outStream)
|
||||
{
|
||||
_mixer->SelectMainCoder(!fullUnpack);
|
||||
}
|
||||
|
||||
CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
|
||||
|
||||
CLockedInStream *lockedInStreamSpec = new CLockedInStream;
|
||||
CMyComPtr<IUnknown> lockedInStream = lockedInStreamSpec;
|
||||
|
||||
bool needMtLock = false;
|
||||
|
||||
if (folderInfo.PackStreams.Size() > 1)
|
||||
{
|
||||
// lockedInStream.Pos = (UInt64)(Int64)-1;
|
||||
// RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &lockedInStream.Pos));
|
||||
RINOK(inStream->Seek(startPos + packPositions[0], STREAM_SEEK_SET, &lockedInStreamSpec->Pos));
|
||||
lockedInStreamSpec->Stream = inStream;
|
||||
|
||||
#ifdef USE_MIXER_ST
|
||||
if (_mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex))
|
||||
#endif
|
||||
needMtLock = true;
|
||||
}
|
||||
|
||||
for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> packStream;
|
||||
UInt64 packPos = startPos + packPositions[j];
|
||||
|
||||
if (folderInfo.PackStreams.Size() == 1)
|
||||
{
|
||||
RINOK(inStream->Seek(packPos, STREAM_SEEK_SET, NULL));
|
||||
packStream = inStream;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef USE_MIXER_MT
|
||||
#ifdef USE_MIXER_ST
|
||||
if (_useMixerMT || 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]);
|
||||
}
|
||||
|
||||
if (numCoders == 0)
|
||||
return 0;
|
||||
unsigned num = inStreams.Size();
|
||||
CObjArray<ISequentialInStream *> inStreamPointers(num);
|
||||
for (i = 0; i < num; i++)
|
||||
inStreamPointers[i] = inStreams[i];
|
||||
ISequentialOutStream *outStreamPointer = outStream;
|
||||
return _mixerCoder->Code(
|
||||
inStreamPointers, NULL, num,
|
||||
&outStreamPointer, NULL, 1,
|
||||
compressProgress);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#ifdef USE_MIXER_ST
|
||||
return _mixerST->GetMainUnpackStream(inStreamPointers, inStreamMainRes);
|
||||
#else
|
||||
return E_FAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -3,25 +3,17 @@
|
||||
#ifndef __7Z_DECODE_H
|
||||
#define __7Z_DECODE_H
|
||||
|
||||
#include "../../IStream.h"
|
||||
#include "../../IPassword.h"
|
||||
|
||||
#include "../Common/CoderMixer2.h"
|
||||
#include "../Common/CoderMixer2MT.h"
|
||||
#ifdef _ST_MODE
|
||||
#include "../Common/CoderMixer2ST.h"
|
||||
#endif
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
|
||||
#include "7zIn.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
struct CBindInfoEx: public NCoderMixer::CBindInfo
|
||||
struct CBindInfoEx: public NCoderMixer2::CBindInfo
|
||||
{
|
||||
CRecordVector<CMethodId> CoderMethodIDs;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
CBindInfo::Clear();
|
||||
@@ -31,29 +23,40 @@ struct CBindInfoEx: public NCoderMixer::CBindInfo
|
||||
|
||||
class CDecoder
|
||||
{
|
||||
bool _bindInfoExPrevIsDefined;
|
||||
CBindInfoEx _bindInfoExPrev;
|
||||
bool _bindInfoPrev_Defined;
|
||||
CBindInfoEx _bindInfoPrev;
|
||||
|
||||
bool _multiThread;
|
||||
#ifdef _ST_MODE
|
||||
NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec;
|
||||
bool _useMixerMT;
|
||||
|
||||
#ifdef USE_MIXER_ST
|
||||
NCoderMixer2::CMixerST *_mixerST;
|
||||
#endif
|
||||
NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec;
|
||||
NCoderMixer::CCoderMixer2 *_mixerCoderCommon;
|
||||
|
||||
CMyComPtr<ICompressCoder2> _mixerCoder;
|
||||
CObjectVector<CMyComPtr<IUnknown> > _decoders;
|
||||
// CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2;
|
||||
#ifdef USE_MIXER_MT
|
||||
NCoderMixer2::CMixerMT *_mixerMT;
|
||||
#endif
|
||||
|
||||
NCoderMixer2::CMixer *_mixer;
|
||||
CMyComPtr<IUnknown> _mixerRef;
|
||||
|
||||
public:
|
||||
CDecoder(bool multiThread);
|
||||
|
||||
CDecoder(bool useMixerMT);
|
||||
|
||||
HRESULT Decode(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
IInStream *inStream,
|
||||
UInt64 startPos,
|
||||
const CFolders &folders, int folderIndex,
|
||||
ISequentialOutStream *outStream,
|
||||
ICompressProgressInfo *compressProgress
|
||||
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
|
||||
|
||||
_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
|
||||
#if !defined(_7ZIP_ST) && !defined(_SFX)
|
||||
, bool mtMode, UInt32 numThreads
|
||||
#endif
|
||||
|
||||
@@ -12,43 +12,80 @@
|
||||
#include "7zEncode.h"
|
||||
#include "7zSpecStream.h"
|
||||
|
||||
static const UInt64 k_Delta = 0x03;
|
||||
static const UInt64 k_BCJ = 0x03030103;
|
||||
static const UInt64 k_BCJ2 = 0x0303011B;
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo,
|
||||
const CRecordVector<CMethodId> decompressionMethods,
|
||||
CFolder &folder)
|
||||
void CEncoder::InitBindConv()
|
||||
{
|
||||
// bindInfo.CoderMethodIDs.Clear();
|
||||
// folder.OutStreams.Clear();
|
||||
folder.BindPairs.SetSize(bindInfo.BindPairs.Size());
|
||||
unsigned i;
|
||||
for (i = 0; i < bindInfo.BindPairs.Size(); i++)
|
||||
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;)
|
||||
{
|
||||
CBindPair &bp = folder.BindPairs[i];
|
||||
const NCoderMixer::CBindPair &mixerBp = bindInfo.BindPairs[i];
|
||||
bp.InIndex = mixerBp.InIndex;
|
||||
bp.OutIndex = mixerBp.OutIndex;
|
||||
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;
|
||||
}
|
||||
}
|
||||
folder.Coders.SetSize(bindInfo.Coders.Size());
|
||||
for (i = 0; i < bindInfo.Coders.Size(); i++)
|
||||
}
|
||||
|
||||
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 NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
|
||||
coderInfo.NumInStreams = coderStreamsInfo.NumInStreams;
|
||||
coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams;
|
||||
coderInfo.MethodID = decompressionMethods[i];
|
||||
// coderInfo.Props can be nonFree;
|
||||
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.InStreams.Size());
|
||||
for (i = 0; i < bindInfo.InStreams.Size(); i++)
|
||||
folder.PackStreams[i] = bindInfo.InStreams[i];
|
||||
|
||||
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;
|
||||
@@ -58,30 +95,75 @@ static HRESULT SetCoderProps2(const CProps &props, const UInt64 *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)
|
||||
{
|
||||
_mixerCoderSpec = new NCoderMixer::CCoderMixer2MT;
|
||||
_mixerCoder = _mixerCoderSpec;
|
||||
RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo));
|
||||
#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 (i, _options.Methods)
|
||||
{
|
||||
const CMethodFull &methodFull = _options.Methods[i];
|
||||
CCoderInfo &encodingInfo = _codersInfo.AddNew();
|
||||
encodingInfo.MethodID = methodFull.Id;
|
||||
CMyComPtr<ICompressCoder> encoder;
|
||||
CMyComPtr<ICompressCoder2> encoder2;
|
||||
|
||||
|
||||
CCreatedCoder cod;
|
||||
|
||||
RINOK(CreateCoder(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
methodFull.Id, encoder, encoder2, true));
|
||||
methodFull.Id, true, cod));
|
||||
|
||||
if (!encoder && !encoder2)
|
||||
if (cod.NumStreams != methodFull.NumStreams)
|
||||
return E_FAIL;
|
||||
if (!cod.Coder && !cod.Coder2)
|
||||
return E_FAIL;
|
||||
|
||||
CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2;
|
||||
CMyComPtr<IUnknown> encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
{
|
||||
@@ -105,21 +187,25 @@ HRESULT CEncoder::CreateMixerCoder(
|
||||
}
|
||||
*/
|
||||
|
||||
// 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 UInt32 sizeInBytes = _options.Password.Len() * 2;
|
||||
const unsigned sizeInBytes = _options.Password.Len() * 2;
|
||||
CByteBuffer buffer(sizeInBytes);
|
||||
for (unsigned i = 0; i < _options.Password.Len(); i++)
|
||||
{
|
||||
@@ -127,21 +213,79 @@ HRESULT CEncoder::CreateMixerCoder(
|
||||
((Byte *)buffer)[i * 2] = (Byte)c;
|
||||
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
|
||||
}
|
||||
RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));
|
||||
RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)sizeInBytes));
|
||||
}
|
||||
|
||||
if (encoder)
|
||||
_mixerCoderSpec->AddCoder(encoder);
|
||||
else
|
||||
_mixerCoderSpec->AddCoder2(encoder2);
|
||||
_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)
|
||||
{
|
||||
if (!_buf->Write(data, size))
|
||||
{
|
||||
if (processed)
|
||||
*processed = 0;
|
||||
return E_FAIL;
|
||||
}
|
||||
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,
|
||||
// const UInt64 *inStreamSize,
|
||||
const UInt64 *inSizeForReduce,
|
||||
CFolder &folderItem,
|
||||
CRecordVector<UInt64> &coderUnpackSizes,
|
||||
UInt64 &unpackSize,
|
||||
@@ -151,27 +295,37 @@ HRESULT CEncoder::Encode(
|
||||
{
|
||||
RINOK(EncoderConstr());
|
||||
|
||||
if (!_mixerCoderSpec)
|
||||
if (!_mixerRef)
|
||||
{
|
||||
RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));
|
||||
}
|
||||
_mixerCoderSpec->ReInit();
|
||||
// _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress);
|
||||
|
||||
_mixer->ReInit();
|
||||
|
||||
CMtEncMultiProgress *mtProgressSpec = NULL;
|
||||
CMyComPtr<ICompressProgressInfo> mtProgress;
|
||||
|
||||
CSequentialOutMtNotify *mtOutStreamNotifySpec = NULL;
|
||||
CMyComPtr<ISequentialOutStream> mtOutStreamNotify;
|
||||
|
||||
CObjectVector<CInOutTempBuffer> inOutTempBuffers;
|
||||
CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs;
|
||||
CObjectVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs;
|
||||
CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
|
||||
|
||||
unsigned numMethods = _bindInfo.Coders.Size();
|
||||
|
||||
unsigned i;
|
||||
for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
|
||||
|
||||
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
|
||||
{
|
||||
CInOutTempBuffer &iotb = inOutTempBuffers.AddNew();
|
||||
iotb.Create();
|
||||
iotb.InitWriting();
|
||||
}
|
||||
for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
|
||||
|
||||
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
|
||||
{
|
||||
CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp;
|
||||
CSequentialOutTempBufferImp2 *tempBufferSpec = new CSequentialOutTempBufferImp2;
|
||||
CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
|
||||
tempBufferSpec->Init(&inOutTempBuffers[i - 1]);
|
||||
tempBuffers.Add(tempBuffer);
|
||||
@@ -179,94 +333,111 @@ HRESULT CEncoder::Encode(
|
||||
}
|
||||
|
||||
for (i = 0; i < numMethods; i++)
|
||||
_mixerCoderSpec->SetCoderInfo(i, NULL, NULL);
|
||||
_mixer->SetCoderInfo(i, NULL, NULL);
|
||||
|
||||
if (_bindInfo.InStreams.IsEmpty())
|
||||
return E_FAIL;
|
||||
UInt32 mainCoderIndex, mainStreamIndex;
|
||||
_bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex);
|
||||
|
||||
|
||||
/* 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)
|
||||
{
|
||||
CRecordVector<const UInt64 *> sizePointers;
|
||||
for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++)
|
||||
if (i == mainStreamIndex)
|
||||
sizePointers.Add(inStreamSize);
|
||||
else
|
||||
sizePointers.Add(NULL);
|
||||
_mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL);
|
||||
}
|
||||
_mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL);
|
||||
*/
|
||||
|
||||
|
||||
// UInt64 outStreamStartPos;
|
||||
// RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos));
|
||||
|
||||
CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;
|
||||
CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
|
||||
|
||||
CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL;
|
||||
CMyComPtr<ISequentialOutStream> outStreamSizeCount;
|
||||
|
||||
inStreamSizeCountSpec->Init(inStream);
|
||||
|
||||
CRecordVector<ISequentialInStream *> inStreamPointers;
|
||||
ISequentialInStream *inStreamPointer = inStreamSizeCount;
|
||||
CRecordVector<ISequentialOutStream *> outStreamPointers;
|
||||
inStreamPointers.Add(inStreamSizeCount);
|
||||
|
||||
if (_bindInfo.OutStreams.Size() != 0)
|
||||
{
|
||||
outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
|
||||
outStreamSizeCount = outStreamSizeCountSpec;
|
||||
outStreamSizeCountSpec->SetStream(outStream);
|
||||
outStreamSizeCountSpec->Init();
|
||||
outStreamPointers.Add(outStreamSizeCount);
|
||||
}
|
||||
SetFolder(folderItem);
|
||||
|
||||
for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
|
||||
outStreamPointers.Add(tempBuffers[i - 1]);
|
||||
|
||||
for (i = 0; i < _codersInfo.Size(); i++)
|
||||
for (i = 0; i < numMethods; i++)
|
||||
{
|
||||
CCoderInfo &encodingInfo = _codersInfo[i];
|
||||
|
||||
IUnknown *coder = _mixer->GetCoder(i).GetUnknown();
|
||||
|
||||
CMyComPtr<ICryptoResetInitVector> resetInitVector;
|
||||
_mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
|
||||
coder->QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
|
||||
if (resetInitVector)
|
||||
{
|
||||
resetInitVector->ResetInitVector();
|
||||
}
|
||||
|
||||
CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
|
||||
_mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
|
||||
coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
|
||||
|
||||
CByteBuffer &props = folderItem.Coders[numMethods - 1 - i].Props;
|
||||
|
||||
if (writeCoderProperties)
|
||||
{
|
||||
CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;
|
||||
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
|
||||
CMyComPtr<ISequentialOutStream> dynOutStream(outStreamSpec);
|
||||
outStreamSpec->Init();
|
||||
writeCoderProperties->WriteCoderProperties(outStream);
|
||||
outStreamSpec->CopyToBuffer(encodingInfo.Props);
|
||||
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(i, tempBufferSpecs)
|
||||
{
|
||||
tempBufferSpecs[i]->_mtProgresSpec = mtProgressSpec;
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 progressIndex = mainCoderIndex;
|
||||
|
||||
for (i = 0; i + 1 < _codersInfo.Size(); i++)
|
||||
|
||||
|
||||
if (_bindInfo.PackStreams.Size() != 0)
|
||||
{
|
||||
UInt64 m = _codersInfo[i].MethodID;
|
||||
if (m == k_Delta || m == k_BCJ || m == k_BCJ2)
|
||||
progressIndex = i + 1;
|
||||
outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
|
||||
outStreamSizeCount = outStreamSizeCountSpec;
|
||||
outStreamSizeCountSpec->SetStream(mtOutStreamNotify ? (ISequentialOutStream *)mtOutStreamNotify : outStream);
|
||||
outStreamSizeCountSpec->Init();
|
||||
outStreamPointers.Add(outStreamSizeCount);
|
||||
}
|
||||
|
||||
_mixerCoderSpec->SetProgressCoderIndex(progressIndex);
|
||||
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
|
||||
outStreamPointers.Add(tempBuffers[i - 1]);
|
||||
|
||||
RINOK(_mixer->Code(
|
||||
&inStreamPointer,
|
||||
&outStreamPointers.Front(),
|
||||
mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress));
|
||||
|
||||
RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1,
|
||||
&outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress));
|
||||
|
||||
ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem);
|
||||
|
||||
if (_bindInfo.OutStreams.Size() != 0)
|
||||
if (_bindInfo.PackStreams.Size() != 0)
|
||||
packSizes.Add(outStreamSizeCountSpec->GetSize());
|
||||
|
||||
for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
|
||||
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
|
||||
{
|
||||
CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];
|
||||
RINOK(inOutTempBuffer.WriteToStream(outStream));
|
||||
@@ -274,37 +445,45 @@ HRESULT CEncoder::Encode(
|
||||
}
|
||||
|
||||
unpackSize = 0;
|
||||
for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++)
|
||||
|
||||
for (i = 0; i < _bindInfo.Coders.Size(); i++)
|
||||
{
|
||||
int binder = _bindInfo.FindBinderForInStream(
|
||||
_bindReverseConverter->DestOutToSrcInMap[i]);
|
||||
int bond = _bindInfo.FindBond_for_UnpackStream(_DestOut_to_SrcIn[i]);
|
||||
UInt64 streamSize;
|
||||
if (binder < 0)
|
||||
if (bond < 0)
|
||||
{
|
||||
streamSize = inStreamSizeCountSpec->GetSize();
|
||||
unpackSize = streamSize;
|
||||
}
|
||||
else
|
||||
streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder);
|
||||
streamSize = _mixer->GetBondStreamSize(bond);
|
||||
coderUnpackSizes.Add(streamSize);
|
||||
}
|
||||
for (i = 0; i < numMethods; i++)
|
||||
folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
CEncoder::CEncoder(const CCompressionMethodMode &options):
|
||||
_bindReverseConverter(0),
|
||||
_constructed(false)
|
||||
_constructed(false)
|
||||
{
|
||||
if (options.IsEmpty())
|
||||
throw 1;
|
||||
|
||||
_options = options;
|
||||
_mixerCoderSpec = NULL;
|
||||
|
||||
#ifdef USE_MIXER_ST
|
||||
_mixerST = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef USE_MIXER_MT
|
||||
_mixerMT = NULL;
|
||||
#endif
|
||||
|
||||
_mixer = NULL;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CEncoder::EncoderConstr()
|
||||
{
|
||||
if (_constructed)
|
||||
@@ -314,112 +493,125 @@ HRESULT CEncoder::EncoderConstr()
|
||||
// it has only password method;
|
||||
if (!_options.PasswordIsDefined)
|
||||
throw 1;
|
||||
if (!_options.Binds.IsEmpty())
|
||||
if (!_options.Bonds.IsEmpty())
|
||||
throw 1;
|
||||
NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
|
||||
|
||||
CMethodFull method;
|
||||
|
||||
method.NumInStreams = 1;
|
||||
method.NumOutStreams = 1;
|
||||
coderStreamsInfo.NumInStreams = 1;
|
||||
coderStreamsInfo.NumOutStreams = 1;
|
||||
method.Id = k_AES;
|
||||
|
||||
method.NumStreams = 1;
|
||||
_options.Methods.Add(method);
|
||||
|
||||
NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
|
||||
coderStreamsInfo.NumStreams = 1;
|
||||
_bindInfo.Coders.Add(coderStreamsInfo);
|
||||
|
||||
_bindInfo.InStreams.Add(0);
|
||||
_bindInfo.OutStreams.Add(0);
|
||||
_bindInfo.PackStreams.Add(0);
|
||||
_bindInfo.UnpackCoder = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
UInt32 numInStreams = 0, numOutStreams = 0;
|
||||
UInt32 numOutStreams = 0;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < _options.Methods.Size(); i++)
|
||||
{
|
||||
const CMethodFull &methodFull = _options.Methods[i];
|
||||
NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
|
||||
coderStreamsInfo.NumInStreams = methodFull.NumOutStreams;
|
||||
coderStreamsInfo.NumOutStreams = methodFull.NumInStreams;
|
||||
if (_options.Binds.IsEmpty())
|
||||
NCoderMixer2::CCoderStreamsInfo cod;
|
||||
|
||||
cod.NumStreams = methodFull.NumStreams;
|
||||
|
||||
if (_options.Bonds.IsEmpty())
|
||||
{
|
||||
if (i < _options.Methods.Size() - 1)
|
||||
// if there are no bonds in options, we create bonds via first streams of coders
|
||||
if (i != _options.Methods.Size() - 1)
|
||||
{
|
||||
NCoderMixer::CBindPair bindPair;
|
||||
bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams;
|
||||
bindPair.OutIndex = numOutStreams;
|
||||
_bindInfo.BindPairs.Add(bindPair);
|
||||
NCoderMixer2::CBond bond;
|
||||
bond.PackIndex = numOutStreams;
|
||||
bond.UnpackIndex = i + 1; // it's next coder
|
||||
_bindInfo.Bonds.Add(bond);
|
||||
}
|
||||
else if (coderStreamsInfo.NumOutStreams != 0)
|
||||
_bindInfo.OutStreams.Insert(0, numOutStreams);
|
||||
for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++)
|
||||
_bindInfo.OutStreams.Add(numOutStreams + j);
|
||||
else if (cod.NumStreams != 0)
|
||||
_bindInfo.PackStreams.Insert(0, numOutStreams);
|
||||
|
||||
for (UInt32 j = 1; j < cod.NumStreams; j++)
|
||||
_bindInfo.PackStreams.Add(numOutStreams + j);
|
||||
}
|
||||
|
||||
numInStreams += coderStreamsInfo.NumInStreams;
|
||||
numOutStreams += coderStreamsInfo.NumOutStreams;
|
||||
numOutStreams += cod.NumStreams;
|
||||
|
||||
_bindInfo.Coders.Add(coderStreamsInfo);
|
||||
_bindInfo.Coders.Add(cod);
|
||||
}
|
||||
|
||||
if (!_options.Binds.IsEmpty())
|
||||
if (!_options.Bonds.IsEmpty())
|
||||
{
|
||||
for (i = 0; i < _options.Binds.Size(); i++)
|
||||
for (i = 0; i < _options.Bonds.Size(); i++)
|
||||
{
|
||||
NCoderMixer::CBindPair bindPair;
|
||||
const CBind &bind = _options.Binds[i];
|
||||
bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream;
|
||||
bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream;
|
||||
_bindInfo.BindPairs.Add(bindPair);
|
||||
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 < (int)numOutStreams; i++)
|
||||
if (_bindInfo.FindBinderForOutStream(i) == -1)
|
||||
_bindInfo.OutStreams.Add(i);
|
||||
|
||||
for (i = 0; i < numOutStreams; i++)
|
||||
if (_bindInfo.FindBond_for_PackStream(i) == -1)
|
||||
_bindInfo.PackStreams.Add(i);
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)numInStreams; i++)
|
||||
if (_bindInfo.FindBinderForInStream(i) == -1)
|
||||
_bindInfo.InStreams.Add(i);
|
||||
if (!_bindInfo.SetUnpackCoder())
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (_bindInfo.InStreams.IsEmpty())
|
||||
throw 1; // this is error
|
||||
if (!_bindInfo.CalcMapsAndCheck())
|
||||
return E_INVALIDARG;
|
||||
|
||||
// Make main stream first in list
|
||||
int inIndex = _bindInfo.InStreams[0];
|
||||
for (;;)
|
||||
if (_bindInfo.PackStreams.Size() != 1)
|
||||
{
|
||||
UInt32 coderIndex, coderStreamIndex;
|
||||
_bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex);
|
||||
UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);
|
||||
int binder = _bindInfo.FindBinderForOutStream(outIndex);
|
||||
if (binder >= 0)
|
||||
/* 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 (;;)
|
||||
{
|
||||
inIndex = _bindInfo.BindPairs[binder].InIndex;
|
||||
continue;
|
||||
}
|
||||
for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
|
||||
if (_bindInfo.OutStreams[i] == outIndex)
|
||||
{
|
||||
_bindInfo.OutStreams.Delete(i);
|
||||
_bindInfo.OutStreams.Insert(0, outIndex);
|
||||
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[bond].UnpackIndex;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
int i = _bindInfo.FindStream_in_PackStreams(outIndex);
|
||||
if (i >= 0)
|
||||
_bindInfo.PackStreams.MoveToFront(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_options.PasswordIsDefined)
|
||||
{
|
||||
unsigned numCryptoStreams = _bindInfo.OutStreams.Size();
|
||||
unsigned numCryptoStreams = _bindInfo.PackStreams.Size();
|
||||
|
||||
unsigned numInStreams = _bindInfo.Coders.Size();
|
||||
|
||||
for (i = 0; i < numCryptoStreams; i++)
|
||||
{
|
||||
NCoderMixer::CBindPair bindPair;
|
||||
bindPair.InIndex = numInStreams + i;
|
||||
bindPair.OutIndex = _bindInfo.OutStreams[i];
|
||||
_bindInfo.BindPairs.Add(bindPair);
|
||||
NCoderMixer2::CBond bond;
|
||||
bond.UnpackIndex = numInStreams + i;
|
||||
bond.PackIndex = _bindInfo.PackStreams[i];
|
||||
_bindInfo.Bonds.Add(bond);
|
||||
}
|
||||
_bindInfo.OutStreams.Clear();
|
||||
_bindInfo.PackStreams.Clear();
|
||||
|
||||
/*
|
||||
if (numCryptoStreams == 0)
|
||||
@@ -428,37 +620,37 @@ HRESULT CEncoder::EncoderConstr()
|
||||
|
||||
for (i = 0; i < numCryptoStreams; i++)
|
||||
{
|
||||
NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
|
||||
CMethodFull method;
|
||||
method.NumInStreams = 1;
|
||||
method.NumOutStreams = 1;
|
||||
coderStreamsInfo.NumInStreams = method.NumOutStreams;
|
||||
coderStreamsInfo.NumOutStreams = method.NumInStreams;
|
||||
method.NumStreams = 1;
|
||||
method.Id = k_AES;
|
||||
|
||||
_options.Methods.Add(method);
|
||||
_bindInfo.Coders.Add(coderStreamsInfo);
|
||||
_bindInfo.OutStreams.Add(numOutStreams + i);
|
||||
|
||||
NCoderMixer2::CCoderStreamsInfo cod;
|
||||
cod.NumStreams = 1;
|
||||
_bindInfo.Coders.Add(cod);
|
||||
|
||||
_bindInfo.PackStreams.Add(numOutStreams++);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (int i = _options.Methods.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
const CMethodFull &methodFull = _options.Methods[i];
|
||||
_decompressionMethods.Add(methodFull.Id);
|
||||
}
|
||||
for (unsigned i = _options.Methods.Size(); i != 0;)
|
||||
_decompressionMethods.Add(_options.Methods[--i].Id);
|
||||
|
||||
_bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo);
|
||||
_bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo);
|
||||
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()
|
||||
{
|
||||
delete _bindReverseConverter;
|
||||
}
|
||||
CEncoder::~CEncoder() {}
|
||||
|
||||
}}
|
||||
|
||||
@@ -3,47 +3,82 @@
|
||||
#ifndef __7Z_ENCODE_H
|
||||
#define __7Z_ENCODE_H
|
||||
|
||||
// #include "../../Common/StreamObjects.h"
|
||||
|
||||
#include "7zCompressionMode.h"
|
||||
|
||||
#include "../Common/CoderMixer2.h"
|
||||
#include "../Common/CoderMixer2MT.h"
|
||||
#ifdef _ST_MODE
|
||||
#include "../Common/CoderMixer2ST.h"
|
||||
#endif
|
||||
#include "7zItem.h"
|
||||
|
||||
#include "../../Common/CreateCoder.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
|
||||
{
|
||||
NCoderMixer::CCoderMixer2MT *_mixerCoderSpec;
|
||||
CMyComPtr<ICompressCoder2> _mixerCoder;
|
||||
|
||||
CObjectVector<CCoderInfo> _codersInfo;
|
||||
#ifdef USE_MIXER_ST
|
||||
NCoderMixer2::CMixerST *_mixerST;
|
||||
#endif
|
||||
#ifdef USE_MIXER_MT
|
||||
NCoderMixer2::CMixerMT *_mixerMT;
|
||||
#endif
|
||||
|
||||
NCoderMixer2::CMixer *_mixer;
|
||||
CMyComPtr<IUnknown> _mixerRef;
|
||||
|
||||
CCompressionMethodMode _options;
|
||||
NCoderMixer::CBindInfo _bindInfo;
|
||||
NCoderMixer::CBindInfo _decompressBindInfo;
|
||||
NCoderMixer::CBindReverseConverter *_bindReverseConverter;
|
||||
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,
|
||||
// const UInt64 *inStreamSize,
|
||||
const UInt64 *inSizeForReduce,
|
||||
CFolder &folderItem,
|
||||
CRecordVector<UInt64> &coderUnpackSizes,
|
||||
UInt64 &unpackSize,
|
||||
|
||||
@@ -2,205 +2,327 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/7zCrc.h"
|
||||
|
||||
#include "../../../Common/ComTry.h"
|
||||
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
|
||||
#include "7zDecode.h"
|
||||
// #include "7z1Decode.h"
|
||||
#include "7zFolderOutStream.h"
|
||||
#include "7zHandler.h"
|
||||
|
||||
// EXTERN_g_ExternalCodecs
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
struct CExtractFolderInfo
|
||||
class CFolderOutStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
#ifdef _7Z_VOL
|
||||
int VolumeIndex;
|
||||
#endif
|
||||
CNum FileIndex;
|
||||
CNum FolderIndex;
|
||||
CBoolVector ExtractStatuses;
|
||||
UInt64 UnpackSize;
|
||||
CExtractFolderInfo(
|
||||
#ifdef _7Z_VOL
|
||||
int volumeIndex,
|
||||
#endif
|
||||
CNum fileIndex, CNum folderIndex):
|
||||
#ifdef _7Z_VOL
|
||||
VolumeIndex(volumeIndex),
|
||||
#endif
|
||||
FileIndex(fileIndex),
|
||||
FolderIndex(folderIndex),
|
||||
UnpackSize(0)
|
||||
{
|
||||
if (fileIndex != kNumNoIndex)
|
||||
{
|
||||
ExtractStatuses.ClearAndSetSize(1);
|
||||
ExtractStatuses[0] = true;
|
||||
}
|
||||
};
|
||||
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);
|
||||
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)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
bool testMode = (testModeSpec != 0);
|
||||
|
||||
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
|
||||
|
||||
UInt64 importantTotalUnpacked = 0;
|
||||
|
||||
// numItems = (UInt32)(Int32)-1;
|
||||
|
||||
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
|
||||
if (allFilesMode)
|
||||
numItems =
|
||||
#ifdef _7Z_VOL
|
||||
_refs.Size();
|
||||
#else
|
||||
_db.Files.Size();
|
||||
#endif
|
||||
numItems = _db.Files.Size();
|
||||
|
||||
if(numItems == 0)
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
|
||||
/*
|
||||
if(_volumes.Size() != 1)
|
||||
return E_FAIL;
|
||||
const CVolume &volume = _volumes.Front();
|
||||
const CDbEx &_db = volume.Database;
|
||||
IInStream *_inStream = volume.Stream;
|
||||
*/
|
||||
|
||||
CObjectVector<CExtractFolderInfo> extractFolderInfoVector;
|
||||
for (UInt32 ii = 0; ii < numItems; ii++)
|
||||
{
|
||||
// UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex];
|
||||
UInt32 ref2Index = allFilesMode ? ii : indices[ii];
|
||||
// const CRef2 &ref2 = _refs[ref2Index];
|
||||
|
||||
// for (UInt32 ri = 0; ri < ref2.Refs.Size(); ri++)
|
||||
CNum prevFolder = kNumNoIndex;
|
||||
UInt32 nextFile = 0;
|
||||
|
||||
UInt32 i;
|
||||
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
#ifdef _7Z_VOL
|
||||
// const CRef &ref = ref2.Refs[ri];
|
||||
const CRef &ref = _refs[ref2Index];
|
||||
|
||||
int volumeIndex = ref.VolumeIndex;
|
||||
const CVolume &volume = _volumes[volumeIndex];
|
||||
const CDbEx &db = volume.Database;
|
||||
UInt32 fileIndex = ref.ItemIndex;
|
||||
#else
|
||||
const CDbEx &db = _db;
|
||||
UInt32 fileIndex = ref2Index;
|
||||
#endif
|
||||
|
||||
CNum folderIndex = db.FileIndexToFolderIndexMap[fileIndex];
|
||||
UInt32 fileIndex = allFilesMode ? i : indices[i];
|
||||
CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];
|
||||
if (folderIndex == kNumNoIndex)
|
||||
{
|
||||
extractFolderInfoVector.Add(CExtractFolderInfo(
|
||||
#ifdef _7Z_VOL
|
||||
volumeIndex,
|
||||
#endif
|
||||
fileIndex, kNumNoIndex));
|
||||
continue;
|
||||
}
|
||||
if (extractFolderInfoVector.IsEmpty() ||
|
||||
folderIndex != extractFolderInfoVector.Back().FolderIndex
|
||||
#ifdef _7Z_VOL
|
||||
|| volumeIndex != extractFolderInfoVector.Back().VolumeIndex
|
||||
#endif
|
||||
)
|
||||
{
|
||||
extractFolderInfoVector.Add(CExtractFolderInfo(
|
||||
#ifdef _7Z_VOL
|
||||
volumeIndex,
|
||||
#endif
|
||||
kNumNoIndex, folderIndex));
|
||||
UInt64 unpackSize = db.GetFolderUnpackSize(folderIndex);
|
||||
importantTotalUnpacked += unpackSize;
|
||||
extractFolderInfoVector.Back().UnpackSize = unpackSize;
|
||||
}
|
||||
|
||||
CExtractFolderInfo &efi = extractFolderInfoVector.Back();
|
||||
|
||||
// const CFolderInfo &folderInfo = m_dam_Folders[folderIndex];
|
||||
CNum startIndex = db.FolderStartFileIndex[folderIndex];
|
||||
for (CNum index = efi.ExtractStatuses.Size();
|
||||
index <= fileIndex - startIndex; index++)
|
||||
{
|
||||
// UInt64 unpackSize = _db.Files[startIndex + index].UnpackSize;
|
||||
// Count partial_folder_size
|
||||
// efi.UnpackSize += unpackSize;
|
||||
// importantTotalUnpacked += unpackSize;
|
||||
efi.ExtractStatuses.Add(index == fileIndex - startIndex);
|
||||
}
|
||||
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));
|
||||
|
||||
CDecoder decoder(
|
||||
#ifdef _ST_MODE
|
||||
false
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
);
|
||||
// CDecoder1 decoder;
|
||||
|
||||
UInt64 totalPacked = 0;
|
||||
UInt64 totalUnpacked = 0;
|
||||
UInt64 curPacked, curUnpacked;
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(extractCallback, false);
|
||||
|
||||
for (unsigned i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked)
|
||||
CDecoder decoder(
|
||||
#ifndef USE_MIXER_ST
|
||||
false
|
||||
#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)
|
||||
{
|
||||
lps->OutSize = totalUnpacked;
|
||||
lps->InSize = totalPacked;
|
||||
RINOK(lps->SetCur());
|
||||
|
||||
if (i >= extractFolderInfoVector.Size())
|
||||
if (i >= numItems)
|
||||
break;
|
||||
|
||||
const CExtractFolderInfo &efi = extractFolderInfoVector[i];
|
||||
curUnpacked = efi.UnpackSize;
|
||||
|
||||
curUnpacked = 0;
|
||||
curPacked = 0;
|
||||
|
||||
CFolderOutStream *folderOutStream = new CFolderOutStream;
|
||||
CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
|
||||
UInt32 fileIndex = allFilesMode ? i : indices[i];
|
||||
CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];
|
||||
|
||||
#ifdef _7Z_VOL
|
||||
const CVolume &volume = _volumes[efi.VolumeIndex];
|
||||
const CDbEx &db = volume.Database;
|
||||
#else
|
||||
const CDbEx &db = _db;
|
||||
#endif
|
||||
UInt32 numSolidFiles = 1;
|
||||
|
||||
CNum startIndex;
|
||||
if (efi.FileIndex != kNumNoIndex)
|
||||
startIndex = efi.FileIndex;
|
||||
else
|
||||
startIndex = db.FolderStartFileIndex[efi.FolderIndex];
|
||||
if (folderIndex != kNumNoIndex)
|
||||
{
|
||||
curPacked = _db.GetFolderFullPackSize(folderIndex);
|
||||
UInt32 nextFile = fileIndex + 1;
|
||||
fileIndex = _db.FolderStartFileIndex[folderIndex];
|
||||
UInt32 k;
|
||||
|
||||
HRESULT result = folderOutStream->Init(&db,
|
||||
#ifdef _7Z_VOL
|
||||
volume.StartRef2Index,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
startIndex,
|
||||
&efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0);
|
||||
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);
|
||||
|
||||
if (efi.FileIndex != kNumNoIndex)
|
||||
// to test solid block with zero unpacked size we disable that code
|
||||
if (folderOutStream->WasWritingFinished())
|
||||
continue;
|
||||
|
||||
CNum folderIndex = efi.FolderIndex;
|
||||
curPacked = _db.GetFolderFullPackSize(folderIndex);
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
||||
if (extractCallback)
|
||||
@@ -212,50 +334,64 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
#ifndef _NO_CRYPTO
|
||||
bool isEncrypted = false;
|
||||
bool passwordIsDefined = false;
|
||||
UString password;
|
||||
#endif
|
||||
|
||||
|
||||
HRESULT result = decoder.Decode(
|
||||
EXTERNAL_CODECS_VARS
|
||||
#ifdef _7Z_VOL
|
||||
volume.Stream,
|
||||
#else
|
||||
_inStream,
|
||||
#endif
|
||||
db.ArcInfo.DataStartPosition,
|
||||
db, folderIndex,
|
||||
_inStream,
|
||||
_db.ArcInfo.DataStartPosition,
|
||||
_db, folderIndex,
|
||||
&curUnpacked,
|
||||
|
||||
outStream,
|
||||
progress
|
||||
progress,
|
||||
NULL // *inStreamMainRes
|
||||
|
||||
_7Z_DECODER_CRYPRO_VARS
|
||||
#if !defined(_7ZIP_ST) && !defined(_SFX)
|
||||
, true, _numThreads
|
||||
#endif
|
||||
);
|
||||
|
||||
if (result == S_FALSE)
|
||||
if (result == S_FALSE || result == E_NOTIMPL)
|
||||
{
|
||||
RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
|
||||
continue;
|
||||
}
|
||||
if (result == E_NOTIMPL)
|
||||
{
|
||||
RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kUnsupportedMethod));
|
||||
bool wasFinished = folderOutStream->WasWritingFinished();
|
||||
|
||||
int resOp = (result == S_FALSE ?
|
||||
NExtract::NOperationResult::kDataError :
|
||||
NExtract::NOperationResult::kUnsupportedMethod);
|
||||
|
||||
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;
|
||||
if (folderOutStream->WasWritingFinished() != S_OK)
|
||||
{
|
||||
RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
|
||||
continue;
|
||||
}
|
||||
|
||||
RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
|
||||
continue;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
|
||||
continue;
|
||||
// continue;
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
@@ -7,96 +7,103 @@
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
CFolderInStream::CFolderInStream()
|
||||
{
|
||||
_inStreamWithHashSpec = new CSequentialInStreamWithCRC;
|
||||
_inStreamWithHash = _inStreamWithHashSpec;
|
||||
}
|
||||
|
||||
void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,
|
||||
const UInt32 *fileIndices, UInt32 numFiles)
|
||||
const UInt32 *indexes, unsigned numFiles)
|
||||
{
|
||||
_updateCallback = updateCallback;
|
||||
_indexes = indexes;
|
||||
_numFiles = numFiles;
|
||||
_fileIndex = 0;
|
||||
_fileIndices = fileIndices;
|
||||
Processed.Clear();
|
||||
CRCs.Clear();
|
||||
Sizes.Clear();
|
||||
_fileIsOpen = false;
|
||||
_currentSizeIsDefined = false;
|
||||
_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()
|
||||
{
|
||||
_filePos = 0;
|
||||
while (_fileIndex < _numFiles)
|
||||
_pos = 0;
|
||||
_crc = CRC_INIT_VAL;
|
||||
_size_Defined = false;
|
||||
_size = 0;
|
||||
|
||||
while (_index < _numFiles)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> stream;
|
||||
HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream);
|
||||
if (result != S_OK && result != S_FALSE)
|
||||
return result;
|
||||
_fileIndex++;
|
||||
_inStreamWithHashSpec->SetStream(stream);
|
||||
_inStreamWithHashSpec->Init();
|
||||
HRESULT result = _updateCallback->GetStream(_indexes[_index], &stream);
|
||||
if (result != S_OK)
|
||||
{
|
||||
if (result != S_FALSE)
|
||||
return result;
|
||||
}
|
||||
|
||||
_stream = stream;
|
||||
|
||||
if (stream)
|
||||
{
|
||||
_fileIsOpen = true;
|
||||
CMyComPtr<IStreamGetSize> streamGetSize;
|
||||
stream.QueryInterface(IID_IStreamGetSize, &streamGetSize);
|
||||
if (streamGetSize)
|
||||
{
|
||||
RINOK(streamGetSize->GetSize(&_currentSize));
|
||||
_currentSizeIsDefined = true;
|
||||
if (streamGetSize->GetSize(&_size) == S_OK)
|
||||
_size_Defined = true;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
_index++;
|
||||
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
Sizes.Add(0);
|
||||
Processed.Add(result == S_OK);
|
||||
AddDigest();
|
||||
AddFileInfo(result == S_OK);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CFolderInStream::AddDigest()
|
||||
void CFolderInStream::AddFileInfo(bool isProcessed)
|
||||
{
|
||||
CRCs.Add(_inStreamWithHashSpec->GetCRC());
|
||||
}
|
||||
|
||||
HRESULT CFolderInStream::CloseStream()
|
||||
{
|
||||
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
_inStreamWithHashSpec->ReleaseStream();
|
||||
_fileIsOpen = false;
|
||||
_currentSizeIsDefined = false;
|
||||
Processed.Add(true);
|
||||
Sizes.Add(_filePos);
|
||||
AddDigest();
|
||||
return S_OK;
|
||||
Processed.Add(isProcessed);
|
||||
Sizes.Add(_pos);
|
||||
CRCs.Add(CRC_GET_DIGEST(_crc));
|
||||
}
|
||||
|
||||
STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize != 0)
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
while (size > 0)
|
||||
while (size != 0)
|
||||
{
|
||||
if (_fileIsOpen)
|
||||
if (_stream)
|
||||
{
|
||||
UInt32 processed2;
|
||||
RINOK(_inStreamWithHash->Read(data, size, &processed2));
|
||||
if (processed2 == 0)
|
||||
RINOK(_stream->Read(data, size, &processed2));
|
||||
if (processed2 != 0)
|
||||
{
|
||||
RINOK(CloseStream());
|
||||
continue;
|
||||
_crc = CrcUpdate(_crc, data, processed2);
|
||||
_pos += processed2;
|
||||
if (processedSize)
|
||||
*processedSize = processed2;
|
||||
return S_OK;
|
||||
}
|
||||
if (processedSize != 0)
|
||||
*processedSize = processed2;
|
||||
_filePos += processed2;
|
||||
break;
|
||||
|
||||
_stream.Release();
|
||||
_index++;
|
||||
AddFileInfo(true);
|
||||
|
||||
_pos = 0;
|
||||
_crc = CRC_INIT_VAL;
|
||||
_size_Defined = false;
|
||||
_size = 0;
|
||||
|
||||
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
}
|
||||
if (_fileIndex >= _numFiles)
|
||||
|
||||
if (_index >= _numFiles)
|
||||
break;
|
||||
RINOK(OpenStream());
|
||||
}
|
||||
@@ -106,17 +113,23 @@ STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSiz
|
||||
STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
|
||||
{
|
||||
*value = 0;
|
||||
unsigned index2 = (unsigned)subStream;
|
||||
if (subStream > Sizes.Size())
|
||||
return E_FAIL;
|
||||
if (index2 < Sizes.Size())
|
||||
return S_FALSE; // E_FAIL;
|
||||
|
||||
unsigned index = (unsigned)subStream;
|
||||
if (index < Sizes.Size())
|
||||
{
|
||||
*value = Sizes[index2];
|
||||
*value = Sizes[index];
|
||||
return S_OK;
|
||||
}
|
||||
if (!_currentSizeIsDefined)
|
||||
|
||||
if (!_size_Defined)
|
||||
{
|
||||
*value = _pos;
|
||||
return S_FALSE;
|
||||
*value = _currentSize;
|
||||
}
|
||||
|
||||
*value = (_pos > _size ? _pos : _size);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
#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"
|
||||
#include "../Common/InStreamWithCRC.h"
|
||||
|
||||
#include "7zItem.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
@@ -17,33 +19,34 @@ class CFolderInStream:
|
||||
public ICompressGetSubStreamSize,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CSequentialInStreamWithCRC *_inStreamWithHashSpec;
|
||||
CMyComPtr<ISequentialInStream> _inStreamWithHash;
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
UInt64 _pos;
|
||||
UInt32 _crc;
|
||||
bool _size_Defined;
|
||||
UInt64 _size;
|
||||
|
||||
const UInt32 *_indexes;
|
||||
unsigned _numFiles;
|
||||
unsigned _index;
|
||||
|
||||
CMyComPtr<IArchiveUpdateCallback> _updateCallback;
|
||||
|
||||
bool _currentSizeIsDefined;
|
||||
bool _fileIsOpen;
|
||||
UInt64 _currentSize;
|
||||
UInt64 _filePos;
|
||||
const UInt32 *_fileIndices;
|
||||
UInt32 _numFiles;
|
||||
UInt32 _fileIndex;
|
||||
|
||||
HRESULT OpenStream();
|
||||
HRESULT CloseStream();
|
||||
void AddDigest();
|
||||
void AddFileInfo(bool isProcessed);
|
||||
|
||||
public:
|
||||
CRecordVector<bool> Processed;
|
||||
CRecordVector<UInt32> CRCs;
|
||||
CRecordVector<UInt64> Sizes;
|
||||
|
||||
MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
|
||||
|
||||
CFolderInStream();
|
||||
void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles);
|
||||
void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles);
|
||||
|
||||
bool WasFinished() const { return _index == _numFiles; }
|
||||
|
||||
UInt64 GetFullSize() const
|
||||
{
|
||||
UInt64 size = 0;
|
||||
|
||||
@@ -1,149 +1,3 @@
|
||||
// 7zFolderOutStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "7zFolderOutStream.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
CFolderOutStream::CFolderOutStream()
|
||||
{
|
||||
_crcStreamSpec = new COutStreamWithCRC;
|
||||
_crcStream = _crcStreamSpec;
|
||||
}
|
||||
|
||||
HRESULT CFolderOutStream::Init(
|
||||
const CDbEx *db,
|
||||
UInt32 ref2Offset, UInt32 startIndex,
|
||||
const CBoolVector *extractStatuses,
|
||||
IArchiveExtractCallback *extractCallback,
|
||||
bool testMode, bool checkCrc)
|
||||
{
|
||||
_db = db;
|
||||
_ref2Offset = ref2Offset;
|
||||
_startIndex = startIndex;
|
||||
|
||||
_extractStatuses = extractStatuses;
|
||||
_extractCallback = extractCallback;
|
||||
_testMode = testMode;
|
||||
_checkCrc = checkCrc;
|
||||
|
||||
_currentIndex = 0;
|
||||
_fileIsOpen = false;
|
||||
return ProcessEmptyFiles();
|
||||
}
|
||||
|
||||
HRESULT CFolderOutStream::OpenFile()
|
||||
{
|
||||
Int32 askMode = ((*_extractStatuses)[_currentIndex]) ? (_testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract) :
|
||||
NExtract::NAskMode::kSkip;
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
UInt32 index = _startIndex + _currentIndex;
|
||||
RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));
|
||||
_crcStreamSpec->SetStream(realOutStream);
|
||||
_crcStreamSpec->Init(_checkCrc);
|
||||
_fileIsOpen = true;
|
||||
const CFileItem &fi = _db->Files[index];
|
||||
_rem = fi.Size;
|
||||
if (askMode == NExtract::NAskMode::kExtract && !realOutStream &&
|
||||
!_db->IsItemAnti(index) && !fi.IsDir)
|
||||
askMode = NExtract::NAskMode::kSkip;
|
||||
return _extractCallback->PrepareOperation(askMode);
|
||||
}
|
||||
|
||||
HRESULT CFolderOutStream::CloseFileAndSetResult(Int32 res)
|
||||
{
|
||||
_crcStreamSpec->ReleaseStream();
|
||||
_fileIsOpen = false;
|
||||
_currentIndex++;
|
||||
return _extractCallback->SetOperationResult(res);
|
||||
}
|
||||
|
||||
HRESULT CFolderOutStream::CloseFileAndSetResult()
|
||||
{
|
||||
const CFileItem &fi = _db->Files[_startIndex + _currentIndex];
|
||||
return CloseFileAndSetResult(
|
||||
(fi.IsDir || !fi.CrcDefined || !_checkCrc || fi.Crc == _crcStreamSpec->GetCRC()) ?
|
||||
NExtract::NOperationResult::kOK :
|
||||
NExtract::NOperationResult::kCRCError);
|
||||
}
|
||||
|
||||
HRESULT CFolderOutStream::ProcessEmptyFiles()
|
||||
{
|
||||
while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)
|
||||
{
|
||||
RINOK(OpenFile());
|
||||
RINOK(CloseFileAndSetResult());
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize != NULL)
|
||||
*processedSize = 0;
|
||||
while (size != 0)
|
||||
{
|
||||
if (_fileIsOpen)
|
||||
{
|
||||
UInt32 cur = size < _rem ? size : (UInt32)_rem;
|
||||
RINOK(_crcStream->Write(data, cur, &cur));
|
||||
if (cur == 0)
|
||||
break;
|
||||
data = (const Byte *)data + cur;
|
||||
size -= cur;
|
||||
_rem -= cur;
|
||||
if (processedSize != NULL)
|
||||
*processedSize += cur;
|
||||
if (_rem == 0)
|
||||
{
|
||||
RINOK(CloseFileAndSetResult());
|
||||
RINOK(ProcessEmptyFiles());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(ProcessEmptyFiles());
|
||||
if (_currentIndex == _extractStatuses->Size())
|
||||
{
|
||||
// we support partial extracting
|
||||
if (processedSize != NULL)
|
||||
*processedSize += size;
|
||||
break;
|
||||
}
|
||||
RINOK(OpenFile());
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFolderOutStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
|
||||
{
|
||||
*value = 0;
|
||||
if ((int)subStream >= _extractStatuses->Size())
|
||||
return S_FALSE;
|
||||
*value = _db->Files[_startIndex + (int)subStream].Size;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)
|
||||
{
|
||||
while (_currentIndex < _extractStatuses->Size())
|
||||
{
|
||||
if (_fileIsOpen)
|
||||
{
|
||||
RINOK(CloseFileAndSetResult(resultEOperationResult));
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(OpenFile());
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -3,56 +3,4 @@
|
||||
#ifndef __7Z_FOLDER_OUT_STREAM_H
|
||||
#define __7Z_FOLDER_OUT_STREAM_H
|
||||
|
||||
#include "../../IStream.h"
|
||||
#include "../IArchive.h"
|
||||
#include "../Common/OutStreamWithCRC.h"
|
||||
|
||||
#include "7zIn.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
class CFolderOutStream:
|
||||
public ISequentialOutStream,
|
||||
public ICompressGetSubStreamSize,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
COutStreamWithCRC *_crcStreamSpec;
|
||||
CMyComPtr<ISequentialOutStream> _crcStream;
|
||||
const CDbEx *_db;
|
||||
const CBoolVector *_extractStatuses;
|
||||
CMyComPtr<IArchiveExtractCallback> _extractCallback;
|
||||
UInt32 _ref2Offset;
|
||||
UInt32 _startIndex;
|
||||
unsigned _currentIndex;
|
||||
bool _testMode;
|
||||
bool _checkCrc;
|
||||
bool _fileIsOpen;
|
||||
UInt64 _rem;
|
||||
|
||||
HRESULT OpenFile();
|
||||
HRESULT CloseFileAndSetResult(Int32 res);
|
||||
HRESULT CloseFileAndSetResult();
|
||||
HRESULT ProcessEmptyFiles();
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
|
||||
|
||||
CFolderOutStream();
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
|
||||
|
||||
HRESULT Init(
|
||||
const CDbEx *db,
|
||||
UInt32 ref2Offset, UInt32 startIndex,
|
||||
const CBoolVector *extractStatuses,
|
||||
IArchiveExtractCallback *extractCallback,
|
||||
bool testMode, bool checkCrc);
|
||||
HRESULT FlushCorrupted(Int32 resultEOperationResult);
|
||||
HRESULT WasWritingFinished() const
|
||||
{ return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -150,22 +150,12 @@ static char *AddProp32(char *s, const char *name, UInt32 v)
|
||||
|
||||
void CHandler::AddMethodName(AString &s, UInt64 id)
|
||||
{
|
||||
UString methodName;
|
||||
FindMethod(EXTERNAL_CODECS_VARS id, methodName);
|
||||
if (methodName.IsEmpty())
|
||||
{
|
||||
for (unsigned i = 0; i < methodName.Len(); i++)
|
||||
if (methodName[i] >= 0x80)
|
||||
{
|
||||
methodName.Empty();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (methodName.IsEmpty())
|
||||
AString name;
|
||||
FindMethod(EXTERNAL_CODECS_VARS id, name);
|
||||
if (name.IsEmpty())
|
||||
ConvertMethodIdToString(s, id);
|
||||
else
|
||||
for (unsigned i = 0; i < methodName.Len(); i++)
|
||||
s += (char)methodName[i];
|
||||
s += name;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -186,8 +176,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
FOR_VECTOR (i, pm.IDs)
|
||||
{
|
||||
UInt64 id = pm.IDs[i];
|
||||
if (!s.IsEmpty())
|
||||
s += ' ';
|
||||
s.Add_Space_if_NotEmpty();
|
||||
char temp[16];
|
||||
if (id == k_LZMA2)
|
||||
{
|
||||
@@ -376,6 +365,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
|
||||
// numCoders == 0 ???
|
||||
CNum numCoders = inByte.ReadNum();
|
||||
bool needSpace = false;
|
||||
|
||||
for (; numCoders != 0; numCoders--, needSpace = true)
|
||||
{
|
||||
if (pos < 32) // max size of property
|
||||
@@ -500,17 +490,8 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
|
||||
}
|
||||
else
|
||||
{
|
||||
UString methodName;
|
||||
AString methodName;
|
||||
FindMethod(EXTERNAL_CODECS_VARS id64, methodName);
|
||||
if (methodName.IsEmpty())
|
||||
{
|
||||
for (unsigned j = 0; j < methodName.Len(); j++)
|
||||
if (methodName[j] >= 0x80)
|
||||
{
|
||||
methodName.Empty();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (needSpace)
|
||||
temp[--pos] = ' ';
|
||||
if (methodName.IsEmpty())
|
||||
@@ -522,10 +503,11 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
|
||||
break;
|
||||
pos -= len;
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
temp[pos + i] = (char)methodName[i];
|
||||
temp[pos + i] = methodName[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numCoders != 0 && pos >= 4)
|
||||
{
|
||||
temp[--pos] = ' ';
|
||||
@@ -533,6 +515,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
|
||||
temp[--pos] = '.';
|
||||
temp[--pos] = '.';
|
||||
}
|
||||
|
||||
return PropVarEm_Set_Str(prop, temp + pos);
|
||||
// }
|
||||
}
|
||||
@@ -555,7 +538,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
const CFileItem &item = _db.Files[index];
|
||||
UInt32 index2 = index;
|
||||
|
||||
switch(propID)
|
||||
switch (propID)
|
||||
{
|
||||
case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break;
|
||||
case kpidSize:
|
||||
@@ -608,7 +591,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
*/
|
||||
|
||||
case kpidPath: return _db.GetPath_Prop(index, value);
|
||||
|
||||
#ifndef _SFX
|
||||
|
||||
case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value);
|
||||
case kpidBlock:
|
||||
{
|
||||
@@ -617,30 +602,29 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
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)
|
||||
{
|
||||
const CFolder &folderInfo = _db.Folders[folderIndex];
|
||||
if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
|
||||
folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0))
|
||||
_db.FoStartPackStreamIndex[folderIndex + 1] -
|
||||
_db.FoStartPackStreamIndex[folderIndex] > (propID - kpidPackedSize0))
|
||||
{
|
||||
prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);
|
||||
PropVarEm_Set_UInt64(value, _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0));
|
||||
}
|
||||
else
|
||||
prop = (UInt64)0;
|
||||
}
|
||||
else
|
||||
prop = (UInt64)0;
|
||||
*/
|
||||
PropVarEm_Set_UInt64(value, 0);
|
||||
}
|
||||
break;
|
||||
*/
|
||||
|
||||
#endif
|
||||
}
|
||||
// prop.Detach(value);
|
||||
@@ -668,7 +652,13 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
|
||||
#endif
|
||||
|
||||
CInArchive archive;
|
||||
CInArchive archive(
|
||||
#ifdef __7Z_SET_PROPERTIES
|
||||
_useMultiThreadMixer
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
);
|
||||
_db.IsArc = false;
|
||||
RINOK(archive.Open(stream, maxCheckStartPosition));
|
||||
_db.IsArc = true;
|
||||
@@ -677,7 +667,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
EXTERNAL_CODECS_VARS
|
||||
_db
|
||||
#ifndef _NO_CRYPTO
|
||||
, getTextPassword, _isEncrypted, _passwordIsDefined
|
||||
, getTextPassword, _isEncrypted, _passwordIsDefined, _password
|
||||
#endif
|
||||
);
|
||||
RINOK(result);
|
||||
@@ -688,8 +678,9 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
{
|
||||
Close();
|
||||
// return E_INVALIDARG;
|
||||
// return S_FALSE;
|
||||
// we must return out_of_memory here
|
||||
return S_FALSE;
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
// _inStream = stream;
|
||||
#ifndef _SFX
|
||||
@@ -707,6 +698,7 @@ STDMETHODIMP CHandler::Close()
|
||||
#ifndef _NO_CRYPTO
|
||||
_isEncrypted = false;
|
||||
_passwordIsDefined = false;
|
||||
_password.Empty();
|
||||
#endif
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
@@ -715,11 +707,12 @@ STDMETHODIMP CHandler::Close()
|
||||
#ifdef __7Z_SET_PROPERTIES
|
||||
#ifdef EXTRACT_ONLY
|
||||
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
|
||||
_numThreads = numProcessors;
|
||||
_useMultiThreadMixer = true;
|
||||
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
@@ -732,7 +725,8 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
|
||||
int index = ParseStringToUInt32(name, number);
|
||||
if (index == 0)
|
||||
{
|
||||
if (name.IsPrefixedBy(L"mt"))
|
||||
if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer);
|
||||
if (name.IsPrefixedBy_Ascii_NoCase("mt"))
|
||||
{
|
||||
RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads));
|
||||
continue;
|
||||
|
||||
@@ -18,16 +18,6 @@
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
const UInt32 k_Copy = 0x0;
|
||||
const UInt32 k_Delta = 3;
|
||||
const UInt32 k_LZMA2 = 0x21;
|
||||
const UInt32 k_LZMA = 0x030101;
|
||||
const UInt32 k_PPMD = 0x030401;
|
||||
const UInt32 k_BCJ = 0x03030103;
|
||||
const UInt32 k_BCJ2 = 0x0303011B;
|
||||
const UInt32 k_Deflate = 0x040108;
|
||||
const UInt32 k_BZip2 = 0x040202;
|
||||
|
||||
#ifndef __7Z_SET_PROPERTIES
|
||||
|
||||
#ifdef EXTRACT_ONLY
|
||||
@@ -64,7 +54,9 @@ public:
|
||||
CBoolPair Write_ATime;
|
||||
CBoolPair Write_MTime;
|
||||
|
||||
bool _volumeMode;
|
||||
bool _useMultiThreadMixer;
|
||||
|
||||
// bool _volumeMode;
|
||||
|
||||
void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }
|
||||
void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); }
|
||||
@@ -117,7 +109,7 @@ public:
|
||||
INTERFACE_IArchiveGetRawProps(;)
|
||||
|
||||
#ifdef __7Z_SET_PROPERTIES
|
||||
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
|
||||
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
|
||||
#endif
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
@@ -131,28 +123,29 @@ public:
|
||||
private:
|
||||
CMyComPtr<IInStream> _inStream;
|
||||
NArchive::N7z::CDbEx _db;
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
bool _isEncrypted;
|
||||
bool _passwordIsDefined;
|
||||
UString _password;
|
||||
#endif
|
||||
|
||||
#ifdef EXTRACT_ONLY
|
||||
|
||||
#ifdef __7Z_SET_PROPERTIES
|
||||
UInt32 _numThreads;
|
||||
bool _useMultiThreadMixer;
|
||||
#endif
|
||||
|
||||
UInt32 _crcSize;
|
||||
|
||||
#else
|
||||
|
||||
CRecordVector<CBind> _binds;
|
||||
CRecordVector<CBond2> _bonds;
|
||||
|
||||
HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m);
|
||||
HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod);
|
||||
void AddDefaultMethod();
|
||||
HRESULT SetMainMethod(CCompressionMethodMode &method,
|
||||
CObjectVector<COneMethodInfo> &methodsInfo
|
||||
HRESULT SetMainMethod(CCompressionMethodMode &method
|
||||
#ifndef _7ZIP_ST
|
||||
, UInt32 numThreads
|
||||
#endif
|
||||
|
||||
@@ -18,11 +18,11 @@ using namespace NWindows;
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
static const wchar_t *k_LZMA_Name = L"LZMA";
|
||||
static const wchar_t *kDefaultMethodName = L"LZMA2";
|
||||
static const wchar_t *k_Copy_Name = L"Copy";
|
||||
static const char *k_LZMA_Name = "LZMA";
|
||||
static const char *kDefaultMethodName = "LZMA2";
|
||||
static const char *k_Copy_Name = "Copy";
|
||||
|
||||
static const wchar_t *k_MatchFinder_ForHeaders = L"BT2";
|
||||
static const char *k_MatchFinder_ForHeaders = "BT2";
|
||||
static const UInt32 k_NumFastBytes_ForHeaders = 273;
|
||||
static const UInt32 k_Level_ForHeaders = 5;
|
||||
static const UInt32 k_Dictionary_ForHeaders =
|
||||
@@ -42,7 +42,7 @@ HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodI
|
||||
{
|
||||
if (!FindMethod(
|
||||
EXTERNAL_CODECS_VARS
|
||||
m.MethodName, dest.Id, dest.NumInStreams, dest.NumOutStreams))
|
||||
m.MethodName, dest.Id, dest.NumStreams))
|
||||
return E_INVALIDARG;
|
||||
(CProps &)dest = (CProps &)m;
|
||||
return S_OK;
|
||||
@@ -54,48 +54,62 @@ HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod)
|
||||
return S_OK;
|
||||
COneMethodInfo m;
|
||||
m.MethodName = k_LZMA_Name;
|
||||
m.AddPropString(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders);
|
||||
m.AddProp32(NCoderPropID::kLevel, k_Level_ForHeaders);
|
||||
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.AddNumThreadsProp(1);
|
||||
m.AddProp_NumThreads(1);
|
||||
|
||||
CMethodFull methodFull;
|
||||
RINOK(PropsMethod_To_FullMethod(methodFull, m));
|
||||
headerMethod.Methods.Add(methodFull);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CHandler::AddDefaultMethod()
|
||||
{
|
||||
FOR_VECTOR (i, _methods)
|
||||
{
|
||||
UString &methodName = _methods[i].MethodName;
|
||||
if (methodName.IsEmpty())
|
||||
methodName = kDefaultMethodName;
|
||||
}
|
||||
if (_methods.IsEmpty())
|
||||
{
|
||||
COneMethodInfo m;
|
||||
m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName);
|
||||
_methods.Add(m);
|
||||
}
|
||||
CMethodFull &methodFull = headerMethod.Methods.AddNew();
|
||||
return PropsMethod_To_FullMethod(methodFull, m);
|
||||
}
|
||||
|
||||
HRESULT CHandler::SetMainMethod(
|
||||
CCompressionMethodMode &methodMode,
|
||||
CObjectVector<COneMethodInfo> &methods
|
||||
CCompressionMethodMode &methodMode
|
||||
#ifndef _7ZIP_ST
|
||||
, UInt32 numThreads
|
||||
#endif
|
||||
)
|
||||
{
|
||||
AddDefaultMethod();
|
||||
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) - 1;
|
||||
|
||||
bool needSolid = false;
|
||||
|
||||
FOR_VECTOR (i, methods)
|
||||
{
|
||||
COneMethodInfo &oneMethodInfo = methods[i];
|
||||
@@ -105,9 +119,8 @@ HRESULT CHandler::SetMainMethod(
|
||||
#endif
|
||||
);
|
||||
|
||||
CMethodFull methodFull;
|
||||
CMethodFull &methodFull = methodMode.Methods.AddNew();
|
||||
RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo));
|
||||
methodMode.Methods.Add(methodFull);
|
||||
|
||||
if (methodFull.Id != k_Copy)
|
||||
needSolid = true;
|
||||
@@ -125,6 +138,7 @@ HRESULT CHandler::SetMainMethod(
|
||||
case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break;
|
||||
default: continue;
|
||||
}
|
||||
|
||||
_numSolidBytes = (UInt64)dicSize << 7;
|
||||
if (_numSolidBytes < kSolidBytes_Min) _numSolidBytes = kSolidBytes_Min;
|
||||
if (_numSolidBytes > kSolidBytes_Max) _numSolidBytes = kSolidBytes_Max;
|
||||
@@ -517,18 +531,20 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
|
||||
CCompressionMethodMode methodMode, headerMethod;
|
||||
|
||||
HRESULT res = SetMainMethod(methodMode, _methods
|
||||
HRESULT res = SetMainMethod(methodMode
|
||||
#ifndef _7ZIP_ST
|
||||
, _numThreads
|
||||
#endif
|
||||
);
|
||||
RINOK(res);
|
||||
methodMode.Binds = _binds;
|
||||
|
||||
RINOK(SetHeaderMethod(headerMethod));
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
methodMode.NumThreads = _numThreads;
|
||||
methodMode.MultiThreadMixer = _useMultiThreadMixer;
|
||||
headerMethod.NumThreads = 1;
|
||||
headerMethod.MultiThreadMixer = _useMultiThreadMixer;
|
||||
#endif
|
||||
|
||||
CMyComPtr<ICryptoGetTextPassword2> getPassword2;
|
||||
@@ -542,7 +558,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
Int32 passwordIsDefined;
|
||||
RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password));
|
||||
methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
|
||||
if (methodMode.PasswordIsDefined && (BSTR)password)
|
||||
if (methodMode.PasswordIsDefined && password)
|
||||
methodMode.Password = password;
|
||||
}
|
||||
|
||||
@@ -550,6 +566,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
|
||||
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)
|
||||
@@ -569,12 +594,14 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
if (numItems < 2)
|
||||
compressMainHeader = false;
|
||||
|
||||
int level = GetLevel();
|
||||
|
||||
CUpdateOptions options;
|
||||
options.Method = &methodMode;
|
||||
options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0;
|
||||
int level = GetLevel();
|
||||
options.UseFilters = level != 0 && _autoFilter;
|
||||
options.MaxFilter = level >= 8;
|
||||
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;
|
||||
/*
|
||||
@@ -587,7 +614,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
options.NumSolidBytes = _numSolidBytes;
|
||||
options.SolidExtension = _solidExtension;
|
||||
options.RemoveSfxBlock = _removeSfxBlock;
|
||||
options.VolumeMode = _volumeMode;
|
||||
// options.VolumeMode = _volumeMode;
|
||||
|
||||
options.MultiThreadMixer = _useMultiThreadMixer;
|
||||
|
||||
COutArchive archive;
|
||||
CArchiveDatabaseOut newDatabase;
|
||||
@@ -635,20 +664,20 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream)
|
||||
static HRESULT ParseBond(UString &srcString, UInt32 &coder, UInt32 &stream)
|
||||
{
|
||||
stream = 0;
|
||||
int index = ParseStringToUInt32(srcString, coder);
|
||||
if (index == 0)
|
||||
return E_INVALIDARG;
|
||||
srcString.Delete(0, index);
|
||||
srcString.DeleteFrontal(index);
|
||||
if (srcString[0] == 's')
|
||||
{
|
||||
srcString.Delete(0);
|
||||
int index = ParseStringToUInt32(srcString, stream);
|
||||
if (index == 0)
|
||||
return E_INVALIDARG;
|
||||
srcString.Delete(0, index);
|
||||
srcString.DeleteFrontal(index);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
@@ -667,7 +696,10 @@ void COutHandler::InitProps()
|
||||
Write_ATime.Init();
|
||||
Write_MTime.Init();
|
||||
|
||||
_volumeMode = false;
|
||||
_useMultiThreadMixer = true;
|
||||
|
||||
// _volumeMode = false;
|
||||
|
||||
InitSolid();
|
||||
}
|
||||
|
||||
@@ -762,7 +794,7 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
|
||||
|
||||
UInt32 number;
|
||||
int index = ParseStringToUInt32(name, number);
|
||||
UString realName = name.Ptr(index);
|
||||
// UString realName = name.Ptr(index);
|
||||
if (index == 0)
|
||||
{
|
||||
if (name.IsEqualTo("rsfx")) return PROPVARIANT_to_bool(value, _removeSfxBlock);
|
||||
@@ -787,15 +819,17 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
|
||||
if (name.IsEqualTo("ta")) return PROPVARIANT_to_BoolPair(value, Write_ATime);
|
||||
if (name.IsEqualTo("tm")) return PROPVARIANT_to_BoolPair(value, Write_MTime);
|
||||
|
||||
if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode);
|
||||
if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer);
|
||||
|
||||
// if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode);
|
||||
}
|
||||
return CMultiMethodProps::SetProperty(name, value);
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
_binds.Clear();
|
||||
_bonds.Clear();
|
||||
InitProps();
|
||||
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
@@ -812,15 +846,19 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
|
||||
if (value.vt != VT_EMPTY)
|
||||
return E_INVALIDARG;
|
||||
name.Delete(0);
|
||||
CBind bind;
|
||||
RINOK(GetBindInfoPart(name, bind.OutCoder, bind.OutStream));
|
||||
|
||||
CBond2 bond;
|
||||
RINOK(ParseBond(name, bond.OutCoder, bond.OutStream));
|
||||
if (name[0] != ':')
|
||||
return E_INVALIDARG;
|
||||
name.Delete(0);
|
||||
RINOK(GetBindInfoPart(name, bind.InCoder, bind.InStream));
|
||||
UInt32 inStream = 0;
|
||||
RINOK(ParseBond(name, bond.InCoder, inStream));
|
||||
if (inStream != 0)
|
||||
return E_INVALIDARG;
|
||||
if (!name.IsEmpty())
|
||||
return E_INVALIDARG;
|
||||
_binds.Add(bind);
|
||||
_bonds.Add(bond);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -831,40 +869,27 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
|
||||
if (numEmptyMethods > 0)
|
||||
{
|
||||
unsigned k;
|
||||
for (k = 0; k < _binds.Size(); k++)
|
||||
for (k = 0; k < _bonds.Size(); k++)
|
||||
{
|
||||
const CBind &bind = _binds[k];
|
||||
if (bind.InCoder < (UInt32)numEmptyMethods ||
|
||||
bind.OutCoder < (UInt32)numEmptyMethods)
|
||||
const CBond2 &bond = _bonds[k];
|
||||
if (bond.InCoder < (UInt32)numEmptyMethods ||
|
||||
bond.OutCoder < (UInt32)numEmptyMethods)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
for (k = 0; k < _binds.Size(); k++)
|
||||
for (k = 0; k < _bonds.Size(); k++)
|
||||
{
|
||||
CBind &bind = _binds[k];
|
||||
bind.InCoder -= (UInt32)numEmptyMethods;
|
||||
bind.OutCoder -= (UInt32)numEmptyMethods;
|
||||
CBond2 &bond = _bonds[k];
|
||||
bond.InCoder -= (UInt32)numEmptyMethods;
|
||||
bond.OutCoder -= (UInt32)numEmptyMethods;
|
||||
}
|
||||
_methods.DeleteFrontal(numEmptyMethods);
|
||||
}
|
||||
|
||||
AddDefaultMethod();
|
||||
|
||||
if (!_filterMethod.MethodName.IsEmpty())
|
||||
FOR_VECTOR (k, _bonds)
|
||||
{
|
||||
FOR_VECTOR (k, _binds)
|
||||
{
|
||||
CBind &bind = _binds[k];
|
||||
bind.InCoder++;
|
||||
bind.OutCoder++;
|
||||
}
|
||||
_methods.Insert(0, _filterMethod);
|
||||
}
|
||||
|
||||
FOR_VECTOR (k, _binds)
|
||||
{
|
||||
const CBind &bind = _binds[k];
|
||||
if (bind.InCoder >= (UInt32)_methods.Size() ||
|
||||
bind.OutCoder >= (UInt32)_methods.Size())
|
||||
const CBond2 &bond = _bonds[k];
|
||||
if (bond.InCoder >= (UInt32)_methods.Size() ||
|
||||
bond.OutCoder >= (UInt32)_methods.Size())
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
|
||||
@@ -96,6 +96,53 @@ namespace NID
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
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_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
|
||||
|
||||
@@ -32,9 +32,6 @@ using namespace NCOM;
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
static const UInt32 k_LZMA2 = 0x21;
|
||||
static const UInt32 k_LZMA = 0x030101;
|
||||
|
||||
static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
|
||||
{
|
||||
v.ClearAndSetSize(size);
|
||||
@@ -43,78 +40,6 @@ static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
|
||||
p[i] = false;
|
||||
}
|
||||
|
||||
static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index)
|
||||
{
|
||||
if (index >= (UInt32)v.Size())
|
||||
return true;
|
||||
bool res = v[index];
|
||||
v[index] = true;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool CFolder::CheckStructure(unsigned numUnpackSizes) const
|
||||
{
|
||||
const unsigned kNumCodersMax = sizeof(UInt32) * 8; // don't change it
|
||||
const unsigned kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax
|
||||
const unsigned kNumBindsMax = 32;
|
||||
|
||||
if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax)
|
||||
return false;
|
||||
|
||||
{
|
||||
CBoolVector v;
|
||||
BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size());
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < BindPairs.Size(); i++)
|
||||
if (BoolVector_GetAndSet(v, BindPairs[i].InIndex))
|
||||
return false;
|
||||
for (i = 0; i < PackStreams.Size(); i++)
|
||||
if (BoolVector_GetAndSet(v, PackStreams[i]))
|
||||
return false;
|
||||
|
||||
BoolVector_Fill_False(v, numUnpackSizes);
|
||||
for (i = 0; i < BindPairs.Size(); i++)
|
||||
if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex))
|
||||
return false;
|
||||
}
|
||||
|
||||
UInt32 mask[kMaskSize];
|
||||
unsigned i;
|
||||
for (i = 0; i < kMaskSize; i++)
|
||||
mask[i] = 0;
|
||||
|
||||
{
|
||||
CUIntVector inStreamToCoder, outStreamToCoder;
|
||||
for (i = 0; i < Coders.Size(); i++)
|
||||
{
|
||||
CNum j;
|
||||
const CCoderInfo &coder = Coders[i];
|
||||
for (j = 0; j < coder.NumInStreams; j++)
|
||||
inStreamToCoder.Add(i);
|
||||
for (j = 0; j < coder.NumOutStreams; j++)
|
||||
outStreamToCoder.Add(i);
|
||||
}
|
||||
|
||||
for (i = 0; i < BindPairs.Size(); i++)
|
||||
{
|
||||
const CBindPair &bp = BindPairs[i];
|
||||
mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < kMaskSize; i++)
|
||||
for (unsigned j = 0; j < kMaskSize; j++)
|
||||
if (((1 << j) & mask[i]) != 0)
|
||||
mask[i] |= mask[j];
|
||||
|
||||
for (i = 0; i < kMaskSize; i++)
|
||||
if (((1 << i) & mask[i]) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class CInArchiveException {};
|
||||
class CUnsupportedFeatureException: public CInArchiveException {};
|
||||
|
||||
@@ -193,6 +118,8 @@ Byte CInByte2::ReadByte()
|
||||
|
||||
void CInByte2::ReadBytes(Byte *data, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return;
|
||||
if (size > _size - _pos)
|
||||
ThrowEndOfData();
|
||||
memcpy(data, _buffer + _pos, size);
|
||||
@@ -218,41 +145,48 @@ static UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed)
|
||||
processed = 0;
|
||||
return 0;
|
||||
}
|
||||
Byte firstByte = *p++;
|
||||
|
||||
unsigned b = *p++;
|
||||
size--;
|
||||
if ((firstByte & 0x80) == 0)
|
||||
|
||||
if ((b & 0x80) == 0)
|
||||
{
|
||||
processed = 1;
|
||||
return firstByte;
|
||||
return b;
|
||||
}
|
||||
Byte mask = 0x40;
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
processed = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
UInt64 value = (UInt64)*p;
|
||||
p++;
|
||||
size--;
|
||||
|
||||
for (unsigned i = 1; i < 8; i++)
|
||||
{
|
||||
if ((firstByte & mask) == 0)
|
||||
unsigned mask = (unsigned)0x80 >> i;
|
||||
if ((b & mask) == 0)
|
||||
{
|
||||
UInt64 highPart = firstByte & (mask - 1);
|
||||
value += (highPart << (i * 8));
|
||||
UInt64 high = b & (mask - 1);
|
||||
value |= (high << (i * 8));
|
||||
processed = i + 1;
|
||||
return value;
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
processed = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
value |= ((UInt64)*p << (i * 8));
|
||||
p++;
|
||||
size--;
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
processed = 9;
|
||||
return value;
|
||||
}
|
||||
@@ -344,6 +278,7 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
|
||||
for (;;)
|
||||
{
|
||||
UInt32 readSize = kBufSize - kHeaderSize;
|
||||
if (searchHeaderSizeLimit)
|
||||
{
|
||||
UInt64 rem = *searchHeaderSizeLimit - offset;
|
||||
if (readSize > rem)
|
||||
@@ -351,10 +286,12 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
|
||||
if (readSize == 0)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
UInt32 processed = 0;
|
||||
RINOK(stream->Read(buf + kHeaderSize, readSize, &processed));
|
||||
if (processed == 0)
|
||||
return S_FALSE;
|
||||
|
||||
for (UInt32 pos = 0;;)
|
||||
{
|
||||
const Byte *p = buf + pos + 1;
|
||||
@@ -376,6 +313,7 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
|
||||
return stream->Seek(_arhiveBeginStreamPosition + kHeaderSize, STREAM_SEEK_SET, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
offset += processed;
|
||||
memmove(buf, buf + processed, kHeaderSize);
|
||||
}
|
||||
@@ -415,13 +353,15 @@ void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)
|
||||
|
||||
void CInByte2::ParseFolder(CFolder &folder)
|
||||
{
|
||||
CNum numCoders = ReadNum();
|
||||
UInt32 numCoders = ReadNum();
|
||||
|
||||
if (numCoders == 0)
|
||||
ThrowUnsupported();
|
||||
|
||||
folder.Coders.SetSize(numCoders);
|
||||
|
||||
CNum numInStreams = 0;
|
||||
CNum numOutStreams = 0;
|
||||
CNum i;
|
||||
UInt32 numInStreams = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < numCoders; i++)
|
||||
{
|
||||
CCoderInfo &coder = folder.Coders[i];
|
||||
@@ -441,14 +381,14 @@ void CInByte2::ParseFolder(CFolder &folder)
|
||||
|
||||
if ((mainByte & 0x10) != 0)
|
||||
{
|
||||
coder.NumInStreams = ReadNum();
|
||||
coder.NumOutStreams = ReadNum();
|
||||
coder.NumStreams = ReadNum();
|
||||
/* numOutStreams = */ ReadNum();
|
||||
}
|
||||
else
|
||||
{
|
||||
coder.NumInStreams = 1;
|
||||
coder.NumOutStreams = 1;
|
||||
coder.NumStreams = 1;
|
||||
}
|
||||
|
||||
if ((mainByte & 0x20) != 0)
|
||||
{
|
||||
CNum propsSize = ReadNum();
|
||||
@@ -458,27 +398,27 @@ void CInByte2::ParseFolder(CFolder &folder)
|
||||
else
|
||||
coder.Props.Free();
|
||||
}
|
||||
numInStreams += coder.NumInStreams;
|
||||
numOutStreams += coder.NumOutStreams;
|
||||
numInStreams += coder.NumStreams;
|
||||
}
|
||||
|
||||
CNum numBindPairs = numOutStreams - 1;
|
||||
folder.BindPairs.SetSize(numBindPairs);
|
||||
for (i = 0; i < numBindPairs; i++)
|
||||
UInt32 numBonds = numCoders - 1;
|
||||
folder.Bonds.SetSize(numBonds);
|
||||
for (i = 0; i < numBonds; i++)
|
||||
{
|
||||
CBindPair &bp = folder.BindPairs[i];
|
||||
bp.InIndex = ReadNum();
|
||||
bp.OutIndex = ReadNum();
|
||||
CBond &bp = folder.Bonds[i];
|
||||
bp.PackIndex = ReadNum();
|
||||
bp.UnpackIndex = ReadNum();
|
||||
}
|
||||
|
||||
if (numInStreams < numBindPairs)
|
||||
if (numInStreams < numBonds)
|
||||
ThrowUnsupported();
|
||||
CNum numPackStreams = numInStreams - numBindPairs;
|
||||
UInt32 numPackStreams = numInStreams - numBonds;
|
||||
folder.PackStreams.SetSize(numPackStreams);
|
||||
|
||||
if (numPackStreams == 1)
|
||||
{
|
||||
for (i = 0; i < numInStreams; i++)
|
||||
if (folder.FindBindPairForInStream(i) < 0)
|
||||
if (folder.FindBond_for_PackStream(i) < 0)
|
||||
{
|
||||
folder.PackStreams[0] = i;
|
||||
break;
|
||||
@@ -509,12 +449,12 @@ void CDatabase::GetPath(unsigned index, UString &path) const
|
||||
return;
|
||||
|
||||
size_t offset = NameOffsets[index];
|
||||
size_t size = NameOffsets[index + 1] - offset - 1;
|
||||
size_t size = NameOffsets[index + 1] - offset;
|
||||
|
||||
if (size >= (1 << 20))
|
||||
if (size >= (1 << 28))
|
||||
return;
|
||||
|
||||
wchar_t *s = path.GetBuffer((unsigned)size);
|
||||
wchar_t *s = path.GetBuf((unsigned)size - 1);
|
||||
|
||||
const Byte *p = ((const Byte *)NamesBuf + offset * 2);
|
||||
|
||||
@@ -533,7 +473,7 @@ void CDatabase::GetPath(unsigned index, UString &path) const
|
||||
|
||||
#endif
|
||||
|
||||
path.ReleaseBuffer((unsigned)size);
|
||||
path.ReleaseBuf_SetLen((unsigned)size - 1);
|
||||
}
|
||||
|
||||
HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
|
||||
@@ -592,7 +532,7 @@ HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
|
||||
{
|
||||
unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1);
|
||||
const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2;
|
||||
do
|
||||
for (; len != 0; len--)
|
||||
{
|
||||
p -= 2;
|
||||
--s;
|
||||
@@ -601,7 +541,7 @@ HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
|
||||
c = WCHAR_PATH_SEPARATOR;
|
||||
*s = c;
|
||||
}
|
||||
while (--len);
|
||||
|
||||
const CFileItem &file = Files[cur];
|
||||
cur = file.Parent;
|
||||
if (cur < 0)
|
||||
@@ -639,6 +579,9 @@ void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs)
|
||||
}
|
||||
}
|
||||
|
||||
#define k_Scan_NumCoders_MAX 64
|
||||
#define k_Scan_NumCodersStreams_in_Folder_MAX 64
|
||||
|
||||
void CInArchive::ReadPackInfo(CFolders &f)
|
||||
{
|
||||
CNum numPackStreams = ReadNum();
|
||||
@@ -692,27 +635,31 @@ void CInArchive::ReadUnpackInfo(
|
||||
folders.FoCodersDataOffset.Alloc(numFolders + 1);
|
||||
folders.FoToCoderUnpackSizes.Alloc(numFolders + 1);
|
||||
|
||||
CRecordVector<bool> InStreamUsed;
|
||||
CRecordVector<bool> OutStreamUsed;
|
||||
CBoolVector StreamUsed;
|
||||
CBoolVector CoderUsed;
|
||||
|
||||
CNum packStreamIndex = 0;
|
||||
CNum fo;
|
||||
CInByte2 *inByte = _inByteBack;
|
||||
|
||||
for (fo = 0; fo < numFolders; fo++)
|
||||
{
|
||||
UInt32 numOutStreams = 0;
|
||||
UInt32 indexOfMainStream = 0;
|
||||
UInt32 numPackStreams = 0;
|
||||
folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr;
|
||||
|
||||
numOutStreams = 0;
|
||||
CNum numInStreams = 0;
|
||||
CNum numCoders = inByte->ReadNum();
|
||||
|
||||
if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)
|
||||
ThrowUnsupported();
|
||||
|
||||
for (CNum ci = 0; ci < numCoders; ci++)
|
||||
{
|
||||
Byte mainByte = inByte->ReadByte();
|
||||
if ((mainByte & 0xC0) != 0)
|
||||
ThrowUnsupported();
|
||||
|
||||
unsigned idSize = (mainByte & 0xF);
|
||||
if (idSize > 8)
|
||||
ThrowUnsupported();
|
||||
@@ -725,19 +672,21 @@ void CInArchive::ReadUnpackInfo(
|
||||
inByte->SkipDataNoCheck(idSize);
|
||||
if (folders.ParsedMethods.IDs.Size() < 128)
|
||||
folders.ParsedMethods.IDs.AddToUniqueSorted(id);
|
||||
|
||||
CNum coderInStreams = 1;
|
||||
CNum coderOutStreams = 1;
|
||||
if ((mainByte & 0x10) != 0)
|
||||
{
|
||||
coderInStreams = inByte->ReadNum();
|
||||
coderOutStreams = inByte->ReadNum();
|
||||
if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
|
||||
ThrowUnsupported();
|
||||
if (inByte->ReadNum() != 1)
|
||||
ThrowUnsupported();
|
||||
}
|
||||
|
||||
numInStreams += coderInStreams;
|
||||
if (numInStreams < coderInStreams)
|
||||
ThrowUnsupported();
|
||||
numOutStreams += coderOutStreams;
|
||||
if (numOutStreams < coderOutStreams)
|
||||
if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
|
||||
ThrowUnsupported();
|
||||
|
||||
if ((mainByte & 0x20) != 0)
|
||||
{
|
||||
CNum propsSize = inByte->ReadNum();
|
||||
@@ -759,7 +708,7 @@ void CInArchive::ReadUnpackInfo(
|
||||
}
|
||||
}
|
||||
|
||||
if (numOutStreams == 1 && numInStreams == 1)
|
||||
if (numCoders == 1 && numInStreams == 1)
|
||||
{
|
||||
indexOfMainStream = 0;
|
||||
numPackStreams = 1;
|
||||
@@ -767,55 +716,55 @@ void CInArchive::ReadUnpackInfo(
|
||||
else
|
||||
{
|
||||
UInt32 i;
|
||||
if (numOutStreams == 0)
|
||||
ThrowUnsupported();
|
||||
CNum numBindPairs = numOutStreams - 1;
|
||||
if (numInStreams < numBindPairs)
|
||||
ThrowUnsupported();
|
||||
if (numInStreams >= 256 || numOutStreams >= 256)
|
||||
CNum numBonds = numCoders - 1;
|
||||
if (numInStreams < numBonds)
|
||||
ThrowUnsupported();
|
||||
|
||||
InStreamUsed.ClearAndSetSize(numInStreams);
|
||||
for (i = 0; i < numInStreams; i++)
|
||||
InStreamUsed[i] = false;
|
||||
BoolVector_Fill_False(StreamUsed, numInStreams);
|
||||
BoolVector_Fill_False(CoderUsed, numCoders);
|
||||
|
||||
OutStreamUsed.ClearAndSetSize(numOutStreams);
|
||||
for (i = 0; i < numOutStreams; i++)
|
||||
OutStreamUsed[i] = false;
|
||||
|
||||
for (i = 0; i < numBindPairs; i++)
|
||||
for (i = 0; i < numBonds; i++)
|
||||
{
|
||||
CNum index = ReadNum();
|
||||
if (index >= numInStreams || InStreamUsed[index])
|
||||
if (index >= numInStreams || StreamUsed[index])
|
||||
ThrowUnsupported();
|
||||
InStreamUsed[index] = true;
|
||||
StreamUsed[index] = true;
|
||||
|
||||
index = ReadNum();
|
||||
if (index >= numOutStreams || OutStreamUsed[index])
|
||||
if (index >= numCoders || CoderUsed[index])
|
||||
ThrowUnsupported();
|
||||
OutStreamUsed[index] = true;
|
||||
CoderUsed[index] = true;
|
||||
}
|
||||
|
||||
numPackStreams = numInStreams - numBindPairs;
|
||||
numPackStreams = numInStreams - numBonds;
|
||||
|
||||
if (numPackStreams != 1)
|
||||
for (i = 0; i < numPackStreams; i++)
|
||||
inByte->ReadNum(); // PackStreams
|
||||
{
|
||||
CNum index = inByte->ReadNum(); // PackStreams
|
||||
if (index >= numInStreams || StreamUsed[index])
|
||||
ThrowUnsupported();
|
||||
StreamUsed[index] = true;
|
||||
}
|
||||
|
||||
for (i = 0; i < numOutStreams; i++)
|
||||
if (!OutStreamUsed[i])
|
||||
for (i = 0; i < numCoders; i++)
|
||||
if (!CoderUsed[i])
|
||||
{
|
||||
indexOfMainStream = i;
|
||||
break;
|
||||
}
|
||||
if (i == numOutStreams)
|
||||
|
||||
if (i == numCoders)
|
||||
ThrowUnsupported();
|
||||
}
|
||||
|
||||
folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
|
||||
numCodersOutStreams += numOutStreams;
|
||||
numCodersOutStreams += numCoders;
|
||||
folders.FoStartPackStreamIndex[fo] = packStreamIndex;
|
||||
packStreamIndex += numPackStreams;
|
||||
folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;
|
||||
}
|
||||
|
||||
size_t dataSize = _inByteBack->GetPtr() - startBufPtr;
|
||||
folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
|
||||
folders.FoStartPackStreamIndex[fo] = packStreamIndex;
|
||||
@@ -1105,13 +1054,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
|
||||
unpackSizes,
|
||||
digests);
|
||||
|
||||
CDecoder decoder(
|
||||
#ifdef _ST_MODE
|
||||
false
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
);
|
||||
CDecoder decoder(_useMixerMT);
|
||||
|
||||
for (CNum i = 0; i < folders.NumFolders; i++)
|
||||
{
|
||||
@@ -1127,14 +1070,20 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
|
||||
outStreamSpec->Init(data, unpackSize);
|
||||
|
||||
HRESULT result = decoder.Decode(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
_stream, baseOffset + dataOffset,
|
||||
folders, i,
|
||||
outStream, NULL
|
||||
_7Z_DECODER_CRYPRO_VARS
|
||||
#if !defined(_7ZIP_ST) && !defined(_SFX)
|
||||
, false, 1
|
||||
#endif
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
_stream, baseOffset + dataOffset,
|
||||
folders, i,
|
||||
NULL, // *unpackSize
|
||||
|
||||
outStream,
|
||||
NULL, // *compressProgress
|
||||
NULL // **inStreamMainRes
|
||||
|
||||
_7Z_DECODER_CRYPRO_VARS
|
||||
#if !defined(_7ZIP_ST) && !defined(_SFX)
|
||||
, false // mtMode
|
||||
, 1 // numThreads
|
||||
#endif
|
||||
);
|
||||
RINOK(result);
|
||||
|
||||
@@ -1208,7 +1157,7 @@ HRESULT CInArchive::ReadHeader(
|
||||
db.ArcInfo.FileInfoPopIDs.Add(NID::kSize);
|
||||
// if (!db.PackSizes.IsEmpty())
|
||||
db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo);
|
||||
if (numFiles > 0 && !digests.Defs.IsEmpty())
|
||||
if (numFiles > 0 && !digests.Defs.IsEmpty())
|
||||
db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC);
|
||||
|
||||
CBoolVector emptyStreamVector;
|
||||
@@ -1396,6 +1345,9 @@ HRESULT CInArchive::ReadHeader(
|
||||
|
||||
type = ReadID(); // Read (NID::kEnd) end of headers
|
||||
|
||||
if (numFiles - numEmptyStreams != unpackSizes.Size())
|
||||
ThrowUnsupported();
|
||||
|
||||
CNum emptyFileIndex = 0;
|
||||
CNum sizeIndex = 0;
|
||||
|
||||
@@ -1403,7 +1355,7 @@ HRESULT CInArchive::ReadHeader(
|
||||
for (i = 0; i < numEmptyStreams; i++)
|
||||
if (antiFileVector[i])
|
||||
numAntiItems++;
|
||||
|
||||
|
||||
for (i = 0; i < numFiles; i++)
|
||||
{
|
||||
CFileItem &file = db.Files[i];
|
||||
@@ -1444,13 +1396,13 @@ HRESULT CInArchive::ReadHeader(
|
||||
|
||||
void CDbEx::FillLinks()
|
||||
{
|
||||
FolderStartFileIndex.ClearAndSetSize(NumFolders);
|
||||
|
||||
FileIndexToFolderIndexMap.ClearAndSetSize(Files.Size());
|
||||
FolderStartFileIndex.Alloc(NumFolders);
|
||||
FileIndexToFolderIndexMap.Alloc(Files.Size());
|
||||
|
||||
CNum folderIndex = 0;
|
||||
CNum indexInFolder = 0;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < Files.Size(); i++)
|
||||
{
|
||||
bool emptyStream = !Files[i].HasStream;
|
||||
@@ -1489,6 +1441,7 @@ void CDbEx::FillLinks()
|
||||
if (indexInFolder != 0)
|
||||
ThrowIncorrect();
|
||||
*/
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (folderIndex >= NumFolders)
|
||||
|
||||
@@ -26,8 +26,8 @@ namespace N7z {
|
||||
#define _7Z_DECODER_CRYPRO_VARS_DECL
|
||||
#define _7Z_DECODER_CRYPRO_VARS
|
||||
#else
|
||||
#define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined
|
||||
#define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined
|
||||
#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
|
||||
@@ -39,6 +39,11 @@ struct CParsedMethods
|
||||
CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {}
|
||||
};
|
||||
|
||||
struct CFolderEx: public CFolder
|
||||
{
|
||||
unsigned UnpackCoder;
|
||||
};
|
||||
|
||||
struct CFolders
|
||||
{
|
||||
CNum NumPackStreams;
|
||||
@@ -47,10 +52,10 @@ struct CFolders
|
||||
CObjArray<UInt64> PackPositions; // NumPackStreams + 1
|
||||
// CUInt32DefVector PackCRCs; // we don't use PackCRCs now
|
||||
|
||||
CUInt32DefVector FolderCRCs; // NumFolders
|
||||
CUInt32DefVector FolderCRCs; // NumFolders
|
||||
CObjArray<CNum> NumUnpackStreamsVector; // NumFolders
|
||||
|
||||
CObjArray<UInt64> CoderUnpackSizes; // including unpack sizes of bind coders
|
||||
CObjArray<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders
|
||||
CObjArray<CNum> FoToCoderUnpackSizes; // NumFolders + 1
|
||||
CObjArray<CNum> FoStartPackStreamIndex; // NumFolders + 1
|
||||
CObjArray<Byte> FoToMainUnpackSizeIndex; // NumFolders
|
||||
@@ -61,10 +66,15 @@ struct CFolders
|
||||
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 FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex];
|
||||
return (unsigned)(FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]);
|
||||
}
|
||||
|
||||
UInt64 GetFolderUnpackSize(unsigned folderIndex) const
|
||||
@@ -103,9 +113,9 @@ struct CDatabase: public CFolders
|
||||
CUInt64DefVector ATime;
|
||||
CUInt64DefVector MTime;
|
||||
CUInt64DefVector StartPos;
|
||||
CRecordVector<bool> IsAnti;
|
||||
CBoolVector IsAnti;
|
||||
/*
|
||||
CRecordVector<bool> IsAux;
|
||||
CBoolVector IsAux;
|
||||
CByteBuffer SecureBuf;
|
||||
CRecordVector<UInt32> SecureIDs;
|
||||
*/
|
||||
@@ -148,13 +158,14 @@ struct CDatabase: public CFolders
|
||||
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
|
||||
/*
|
||||
const void* GetName(unsigned index) const
|
||||
{
|
||||
if (!NameOffsets || !NamesBuf)
|
||||
return NULL;
|
||||
return (const void *)((const Byte *)NamesBuf + NameOffsets[index] * 2);
|
||||
return (void *)((const Byte *)NamesBuf + NameOffsets[index] * 2);
|
||||
};
|
||||
|
||||
*/
|
||||
void GetPath(unsigned index, UString &path) const;
|
||||
HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw();
|
||||
};
|
||||
@@ -181,8 +192,9 @@ struct CInArchiveInfo
|
||||
struct CDbEx: public CDatabase
|
||||
{
|
||||
CInArchiveInfo ArcInfo;
|
||||
CRecordVector<CNum> FolderStartFileIndex;
|
||||
CRecordVector<CNum> FileIndexToFolderIndexMap;
|
||||
|
||||
CObjArray<CNum> FolderStartFileIndex;
|
||||
CObjArray<CNum> FileIndexToFolderIndexMap;
|
||||
|
||||
UInt64 HeadersSize;
|
||||
UInt64 PhySize;
|
||||
@@ -234,8 +246,8 @@ struct CDbEx: public CDatabase
|
||||
|
||||
// SecureOffsets.Clear();
|
||||
ArcInfo.Clear();
|
||||
FolderStartFileIndex.Clear();
|
||||
FileIndexToFolderIndexMap.Clear();
|
||||
FolderStartFileIndex.Free();
|
||||
FileIndexToFolderIndexMap.Free();
|
||||
|
||||
HeadersSize = 0;
|
||||
PhySize = 0;
|
||||
@@ -243,22 +255,22 @@ struct CDbEx: public CDatabase
|
||||
|
||||
void FillLinks();
|
||||
|
||||
UInt64 GetFolderStreamPos(unsigned folderIndex, unsigned indexInFolder) const
|
||||
UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const
|
||||
{
|
||||
return ArcInfo.DataStartPosition +
|
||||
PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder];
|
||||
}
|
||||
|
||||
UInt64 GetFolderFullPackSize(unsigned folderIndex) const
|
||||
UInt64 GetFolderFullPackSize(CNum folderIndex) const
|
||||
{
|
||||
return
|
||||
PackPositions[FoStartPackStreamIndex[folderIndex + 1]] -
|
||||
PackPositions[FoStartPackStreamIndex[folderIndex]];
|
||||
}
|
||||
|
||||
UInt64 GetFolderPackStreamSize(unsigned folderIndex, unsigned streamIndex) const
|
||||
UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const
|
||||
{
|
||||
unsigned i = FoStartPackStreamIndex[folderIndex] + streamIndex;
|
||||
size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex;
|
||||
return PackPositions[i + 1] - PackPositions[i];
|
||||
}
|
||||
|
||||
@@ -327,6 +339,8 @@ class CInArchive
|
||||
|
||||
UInt64 HeadersSize;
|
||||
|
||||
bool _useMixerMT;
|
||||
|
||||
void AddByteStream(const Byte *buffer, size_t size);
|
||||
|
||||
void DeleteByteStream(bool needUpdatePos)
|
||||
@@ -340,7 +354,6 @@ class CInArchive
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
|
||||
|
||||
void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
|
||||
@@ -396,7 +409,11 @@ private:
|
||||
_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
);
|
||||
public:
|
||||
CInArchive(): _numInByteBufs(0) { }
|
||||
CInArchive(bool useMixerMT):
|
||||
_numInByteBufs(0),
|
||||
_useMixerMT(useMixerMT)
|
||||
{}
|
||||
|
||||
HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
|
||||
void Close();
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
const UInt64 k_AES = 0x06F10701;
|
||||
|
||||
typedef UInt32 CNum;
|
||||
const CNum kNumMax = 0x7FFFFFFF;
|
||||
const CNum kNumNoIndex = 0xFFFFFFFF;
|
||||
@@ -23,71 +21,70 @@ struct CCoderInfo
|
||||
{
|
||||
CMethodId MethodID;
|
||||
CByteBuffer Props;
|
||||
CNum NumInStreams;
|
||||
CNum NumOutStreams;
|
||||
UInt32 NumStreams;
|
||||
|
||||
bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }
|
||||
bool IsSimpleCoder() const { return NumStreams == 1; }
|
||||
};
|
||||
|
||||
struct CBindPair
|
||||
struct CBond
|
||||
{
|
||||
CNum InIndex;
|
||||
CNum OutIndex;
|
||||
UInt32 PackIndex;
|
||||
UInt32 UnpackIndex;
|
||||
};
|
||||
|
||||
struct CFolder
|
||||
{
|
||||
CLASS_NO_COPY(CFolder)
|
||||
public:
|
||||
CObjArray2<CCoderInfo> Coders;
|
||||
CObjArray2<CBindPair> BindPairs;
|
||||
CObjArray2<CNum> PackStreams;
|
||||
CObjArray2<CBond> Bonds;
|
||||
CObjArray2<UInt32> PackStreams;
|
||||
|
||||
CNum GetNumOutStreams() const
|
||||
{
|
||||
CNum result = 0;
|
||||
FOR_VECTOR(i, Coders)
|
||||
result += Coders[i].NumOutStreams;
|
||||
return result;
|
||||
}
|
||||
CFolder() {}
|
||||
|
||||
int FindBindPairForInStream(CNum inStreamIndex) const
|
||||
{
|
||||
FOR_VECTOR(i, BindPairs)
|
||||
if (BindPairs[i].InIndex == inStreamIndex)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
int FindBindPairForOutStream(CNum outStreamIndex) const
|
||||
{
|
||||
FOR_VECTOR(i, BindPairs)
|
||||
if (BindPairs[i].OutIndex == outStreamIndex)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
int FindPackStreamArrayIndex(CNum inStreamIndex) const
|
||||
bool IsDecodingSupported() const { return Coders.Size() <= 32; }
|
||||
|
||||
int Find_in_PackStreams(UInt32 packStream) const
|
||||
{
|
||||
FOR_VECTOR(i, PackStreams)
|
||||
if (PackStreams[i] == inStreamIndex)
|
||||
if (PackStreams[i] == packStream)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int GetIndexOfMainOutStream() const
|
||||
int FindBond_for_PackStream(UInt32 packStream) const
|
||||
{
|
||||
for (int i = (int)GetNumOutStreams() - 1; i >= 0; i--)
|
||||
if (FindBindPairForOutStream(i) < 0)
|
||||
FOR_VECTOR(i, Bonds)
|
||||
if (Bonds[i].PackIndex == packStream)
|
||||
return i;
|
||||
throw 1;
|
||||
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 (int i = Coders.Size() - 1; i >= 0; i--)
|
||||
FOR_VECTOR(i, Coders)
|
||||
if (Coders[i].MethodID == k_AES)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CheckStructure(unsigned numUnpackSizes) const;
|
||||
};
|
||||
|
||||
struct CUInt32DefVector
|
||||
|
||||
@@ -199,7 +199,7 @@ void COutArchive::WriteNumber(UInt64 value)
|
||||
mask >>= 1;
|
||||
}
|
||||
WriteByte(firstByte);
|
||||
for (;i > 0; i--)
|
||||
for (; i > 0; i--)
|
||||
{
|
||||
WriteByte((Byte)value);
|
||||
value >>= 8;
|
||||
@@ -254,31 +254,33 @@ 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];
|
||||
{
|
||||
size_t propsSize = coder.Props.Size();
|
||||
|
||||
UInt64 id = coder.MethodID;
|
||||
int idSize;
|
||||
unsigned idSize;
|
||||
for (idSize = 1; idSize < sizeof(id); idSize++)
|
||||
if ((id >> (8 * idSize)) == 0)
|
||||
break;
|
||||
Byte longID[15];
|
||||
for (int t = idSize - 1; t >= 0 ; t--, id >>= 8)
|
||||
longID[t] = (Byte)(id & 0xFF);
|
||||
Byte b;
|
||||
b = (Byte)(idSize & 0xF);
|
||||
idSize &= 0xF;
|
||||
Byte temp[16];
|
||||
for (unsigned t = idSize; t != 0; t--, id >>= 8)
|
||||
temp[t] = (Byte)(id & 0xFF);
|
||||
|
||||
Byte b = (Byte)(idSize);
|
||||
bool isComplex = !coder.IsSimpleCoder();
|
||||
b |= (isComplex ? 0x10 : 0);
|
||||
b |= ((propsSize != 0) ? 0x20 : 0 );
|
||||
WriteByte(b);
|
||||
WriteBytes(longID, idSize);
|
||||
|
||||
size_t propsSize = coder.Props.Size();
|
||||
b |= ((propsSize != 0) ? 0x20 : 0);
|
||||
temp[0] = b;
|
||||
WriteBytes(temp, idSize + 1);
|
||||
if (isComplex)
|
||||
{
|
||||
WriteNumber(coder.NumInStreams);
|
||||
WriteNumber(coder.NumOutStreams);
|
||||
WriteNumber(coder.NumStreams);
|
||||
WriteNumber(1); // NumOutStreams;
|
||||
}
|
||||
if (propsSize == 0)
|
||||
continue;
|
||||
@@ -286,17 +288,17 @@ void COutArchive::WriteFolder(const CFolder &folder)
|
||||
WriteBytes(coder.Props, propsSize);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < folder.BindPairs.Size(); i++)
|
||||
|
||||
for (i = 0; i < folder.Bonds.Size(); i++)
|
||||
{
|
||||
const CBindPair &bindPair = folder.BindPairs[i];
|
||||
WriteNumber(bindPair.InIndex);
|
||||
WriteNumber(bindPair.OutIndex);
|
||||
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)
|
||||
@@ -521,7 +523,10 @@ HRESULT COutArchive::EncodeStream(
|
||||
UInt64 unpackSize;
|
||||
RINOK(encoder.Encode(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
stream, NULL, &dataSize64, folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL))
|
||||
stream,
|
||||
// NULL,
|
||||
&dataSize64,
|
||||
folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL))
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ public:
|
||||
}
|
||||
void WriteBytes(const void *data, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return;
|
||||
if (size > _size - _pos)
|
||||
throw 1;
|
||||
memcpy(_data + _pos, data, size);
|
||||
@@ -92,7 +94,7 @@ struct COutFolders
|
||||
CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only.
|
||||
|
||||
CRecordVector<CNum> NumUnpackStreamsVector;
|
||||
CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bind coders
|
||||
CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders
|
||||
|
||||
void OutFoldersClear()
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace N7z {
|
||||
|
||||
struct CPropMap
|
||||
{
|
||||
UInt64 FilePropID;
|
||||
UInt32 FilePropID;
|
||||
STATPROPSTG StatPROPSTG;
|
||||
};
|
||||
|
||||
@@ -35,7 +35,7 @@ static const CPropMap kPropMap[] =
|
||||
{ NID::kMTime, { NULL, kpidMTime, VT_FILETIME } },
|
||||
{ NID::kATime, { NULL, kpidATime, VT_FILETIME } },
|
||||
{ NID::kWinAttrib, { NULL, kpidAttrib, VT_UI4 } },
|
||||
{ NID::kStartPos, { NULL, kpidPosition, VT_UI4 } },
|
||||
{ NID::kStartPos, { NULL, kpidPosition, VT_UI8 } },
|
||||
|
||||
{ NID::kCRC, { NULL, kpidCRC, VT_UI4 } },
|
||||
|
||||
@@ -44,20 +44,12 @@ static const CPropMap kPropMap[] =
|
||||
|
||||
#ifndef _SFX
|
||||
,
|
||||
{ 97, { NULL,kpidEncrypted, VT_BOOL } },
|
||||
{ 98, { NULL,kpidMethod, VT_BSTR } },
|
||||
{ 99, { NULL,kpidBlock, VT_UI4 } }
|
||||
{ 97, { NULL, kpidEncrypted, VT_BOOL } },
|
||||
{ 98, { NULL, kpidMethod, VT_BSTR } },
|
||||
{ 99, { NULL, kpidBlock, VT_UI4 } }
|
||||
#endif
|
||||
};
|
||||
|
||||
static int FindPropInMap(UInt64 filePropID)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(kPropMap); i++)
|
||||
if (kPropMap[i].FilePropID == filePropID)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void CopyOneItem(CRecordVector<UInt64> &src,
|
||||
CRecordVector<UInt64> &dest, UInt32 item)
|
||||
{
|
||||
@@ -131,6 +123,7 @@ void CHandler::FillPopIDs()
|
||||
_fileInfoPopIDs.Add(98);
|
||||
_fileInfoPopIDs.Add(99);
|
||||
#endif
|
||||
|
||||
#ifdef _MULTI_PACK
|
||||
_fileInfoPopIDs.Add(100);
|
||||
_fileInfoPopIDs.Add(101);
|
||||
@@ -155,16 +148,27 @@ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps)
|
||||
|
||||
STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
{
|
||||
if ((int)index >= _fileInfoPopIDs.Size())
|
||||
if (index >= _fileInfoPopIDs.Size())
|
||||
return E_INVALIDARG;
|
||||
int indexInMap = FindPropInMap(_fileInfoPopIDs[index]);
|
||||
if (indexInMap == -1)
|
||||
return E_INVALIDARG;
|
||||
const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG;
|
||||
*propID = srcItem.propid;
|
||||
*varType = srcItem.vt;
|
||||
*name = 0;
|
||||
return S_OK;
|
||||
UInt64 id = _fileInfoPopIDs[index];
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(kPropMap); i++)
|
||||
{
|
||||
const CPropMap &pr = kPropMap[i];
|
||||
if (pr.FilePropID == id)
|
||||
{
|
||||
const STATPROPSTG &st = pr.StatPROPSTG;
|
||||
*propID = st.propid;
|
||||
*varType = st.vt;
|
||||
/*
|
||||
if (st.lpwstrName)
|
||||
*name = ::SysAllocString(st.lpwstrName);
|
||||
else
|
||||
*/
|
||||
*name = NULL;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -9,17 +9,13 @@
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
IMP_CreateArcIn
|
||||
IMP_CreateArcOut
|
||||
static Byte k_Signature_Dec[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C};
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "7z", "7z", 0, 7,
|
||||
6, {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C},
|
||||
REGISTER_ARC_IO_DECREMENT_SIG(
|
||||
"7z", "7z", NULL, 7,
|
||||
k_Signature_Dec,
|
||||
0,
|
||||
NArcInfoFlags::kFindSignature,
|
||||
REF_CreateArc_Pair };
|
||||
|
||||
REGISTER_ARC_DEC_SIG(7z)
|
||||
// REGISTER_ARC(7z)
|
||||
NULL);
|
||||
|
||||
}}
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
#ifndef __7Z_SPEC_STREAM_H
|
||||
#define __7Z_SPEC_STREAM_H
|
||||
|
||||
#include "../../IStream.h"
|
||||
#include "../../ICoder.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../ICoder.h"
|
||||
|
||||
class CSequentialInStreamSizeCount2:
|
||||
public ISequentialInStream,
|
||||
public ICompressGetSubStreamSize,
|
||||
@@ -18,14 +18,14 @@ class CSequentialInStreamSizeCount2:
|
||||
public:
|
||||
void Init(ISequentialInStream *stream)
|
||||
{
|
||||
_stream = stream;
|
||||
_getSubStreamSize = 0;
|
||||
_stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);
|
||||
_size = 0;
|
||||
_getSubStreamSize.Release();
|
||||
_stream = stream;
|
||||
_stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);
|
||||
}
|
||||
UInt64 GetSize() const { return _size; }
|
||||
|
||||
MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
|
||||
MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -65,6 +65,7 @@ struct CUpdateItem
|
||||
// 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),
|
||||
@@ -77,18 +78,19 @@ struct CUpdateItem
|
||||
MTimeDefined(false)
|
||||
// SecureIndex(0)
|
||||
{}
|
||||
void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); };
|
||||
void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); }
|
||||
|
||||
int GetExtensionPos() const;
|
||||
UString GetExtension() const;
|
||||
// unsigned GetExtensionPos() const;
|
||||
// UString GetExtension() const;
|
||||
};
|
||||
|
||||
struct CUpdateOptions
|
||||
{
|
||||
const CCompressionMethodMode *Method;
|
||||
const CCompressionMethodMode *HeaderMethod;
|
||||
bool UseFilters;
|
||||
bool MaxFilter;
|
||||
bool UseFilters; // use additional filters for some files
|
||||
bool MaxFilter; // use BCJ2 filter instead of BCJ
|
||||
int AnalysisLevel;
|
||||
|
||||
CHeaderOptions HeaderOptions;
|
||||
|
||||
@@ -96,7 +98,20 @@ struct CUpdateOptions
|
||||
UInt64 NumSolidBytes;
|
||||
bool SolidExtension;
|
||||
bool RemoveSfxBlock;
|
||||
bool VolumeMode;
|
||||
bool MultiThreadMixer;
|
||||
|
||||
CUpdateOptions():
|
||||
Method(NULL),
|
||||
HeaderMethod(NULL),
|
||||
UseFilters(false),
|
||||
MaxFilter(false),
|
||||
AnalysisLevel(-1),
|
||||
NumSolidFiles((UInt64)(Int64)(-1)),
|
||||
NumSolidBytes((UInt64)(Int64)(-1)),
|
||||
SolidExtension(false),
|
||||
RemoveSfxBlock(false),
|
||||
MultiThreadMixer(true)
|
||||
{}
|
||||
};
|
||||
|
||||
HRESULT Update(
|
||||
|
||||
@@ -376,15 +376,13 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
static const Byte k_Signature[] = { kSig0, kSig1 };
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "APM", "apm", 0, 0xD4,
|
||||
2, { kSig0, kSig1 },
|
||||
REGISTER_ARC_I(
|
||||
"APM", "apm", 0, 0xD4,
|
||||
k_Signature,
|
||||
0,
|
||||
0,
|
||||
CreateArc, NULL, IsArc_Apm };
|
||||
|
||||
REGISTER_ARC(Apm)
|
||||
IsArc_Apm)
|
||||
|
||||
}}
|
||||
|
||||
@@ -77,7 +77,7 @@ enum EType
|
||||
kType_Lib
|
||||
};
|
||||
|
||||
static const char *k_TypeExtionsions[] =
|
||||
static const char * const k_TypeExtionsions[] =
|
||||
{
|
||||
"ar"
|
||||
, "a"
|
||||
@@ -121,7 +121,7 @@ struct CItem
|
||||
int SameNameIndex;
|
||||
|
||||
CItem(): TextFileIndex(-1), SameNameIndex(-1) {}
|
||||
UInt64 GetDataPos() const { return HeaderPos + HeaderSize; };
|
||||
UInt64 GetDataPos() const { return HeaderPos + HeaderSize; }
|
||||
};
|
||||
|
||||
class CInArchive
|
||||
@@ -257,10 +257,9 @@ HRESULT CInArchive::GetNextItem(CItem &item, bool &filled)
|
||||
{
|
||||
SubType = kSubType_BSD;
|
||||
size_t processedSize = longNameLen;
|
||||
char *s = item.Name.GetBuffer(longNameLen);
|
||||
char *s = item.Name.GetBuf(longNameLen);
|
||||
HRESULT res = ReadStream(m_Stream, s, &processedSize);
|
||||
s[longNameLen] = 0;
|
||||
item.Name.ReleaseBuffer();
|
||||
item.Name.ReleaseBuf_CalcLen(longNameLen);
|
||||
RINOK(res);
|
||||
if (processedSize != longNameLen)
|
||||
return S_OK;
|
||||
@@ -683,11 +682,11 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
case kpidPhySize: prop = _phySize; break;
|
||||
case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;
|
||||
case kpidExtension: prop = k_TypeExtionsions[_type]; break;
|
||||
case kpidExtension: prop = k_TypeExtionsions[(unsigned)_type]; break;
|
||||
case kpidShortComment:
|
||||
case kpidSubType:
|
||||
{
|
||||
AString s = k_TypeExtionsions[_type];
|
||||
AString s = k_TypeExtionsions[(unsigned)_type];
|
||||
if (_subType == kSubType_BSD)
|
||||
s += ":BSD";
|
||||
prop = s;
|
||||
@@ -724,7 +723,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
case kpidSize:
|
||||
case kpidPackSize:
|
||||
if (item.TextFileIndex >= 0)
|
||||
prop = (UInt64)_libFiles[item.TextFileIndex].Len();
|
||||
prop = (UInt64)_libFiles[(unsigned)item.TextFileIndex].Len();
|
||||
else
|
||||
prop = item.Size;
|
||||
break;
|
||||
@@ -766,7 +765,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
const CItem &item = _items[allFilesMode ? i : indices[i]];
|
||||
totalSize +=
|
||||
(item.TextFileIndex >= 0) ?
|
||||
(UInt64)_libFiles[item.TextFileIndex].Len() : item.Size;
|
||||
(UInt64)_libFiles[(unsigned)item.TextFileIndex].Len() : item.Size;
|
||||
}
|
||||
extractCallback->SetTotal(totalSize);
|
||||
|
||||
@@ -795,7 +794,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
const CItem &item = _items[index];
|
||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
|
||||
currentTotalSize += (item.TextFileIndex >= 0) ?
|
||||
(UInt64)_libFiles[item.TextFileIndex].Len() : item.Size;
|
||||
(UInt64)_libFiles[(unsigned)item.TextFileIndex].Len() : item.Size;
|
||||
|
||||
if (!testMode && !realOutStream)
|
||||
continue;
|
||||
@@ -808,7 +807,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
bool isOk = true;
|
||||
if (item.TextFileIndex >= 0)
|
||||
{
|
||||
const AString &f = _libFiles[item.TextFileIndex];
|
||||
const AString &f = _libFiles[(unsigned)item.TextFileIndex];
|
||||
if (realOutStream)
|
||||
RINOK(WriteStream(realOutStream, f, f.Len()));
|
||||
}
|
||||
@@ -834,8 +833,8 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
const CItem &item = _items[index];
|
||||
if (item.TextFileIndex >= 0)
|
||||
{
|
||||
const AString &f = _libFiles[item.TextFileIndex];
|
||||
Create_BufInStream_WithNewBuf((const void *)(const char *)f, f.Len(), stream);
|
||||
const AString &f = _libFiles[(unsigned)item.TextFileIndex];
|
||||
Create_BufInStream_WithNewBuffer((const void *)(const char *)f, f.Len(), stream);
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
@@ -843,15 +842,11 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Ar", "ar a deb lib", 0, 0xEC,
|
||||
kSignatureLen, SIGNATURE,
|
||||
REGISTER_ARC_I(
|
||||
"Ar", "ar a deb lib", 0, 0xEC,
|
||||
kSignature,
|
||||
0,
|
||||
0,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Ar)
|
||||
NULL)
|
||||
|
||||
}}
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
EXPORTS
|
||||
CreateObject PRIVATE
|
||||
|
||||
GetHandlerProperty PRIVATE
|
||||
GetNumberOfFormats PRIVATE
|
||||
GetHandlerProperty2 PRIVATE
|
||||
CreateObject PRIVATE
|
||||
GetIsArc PRIVATE
|
||||
|
||||
SetCodecs PRIVATE
|
||||
|
||||
SetLargePageMode PRIVATE
|
||||
SetCaseSensitive PRIVATE
|
||||
|
||||
@@ -1,11 +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
|
||||
GetIsArc PRIVATE
|
||||
@@ -22,17 +22,19 @@ void RegisterArc(const CArcInfo *arcInfo) throw()
|
||||
const char *p = arcInfo->Name;
|
||||
if (p[0] == '7' && p[1] == 'z' && p[2] == 0)
|
||||
g_DefaultArcIndex = g_NumArcs;
|
||||
g_Arcs[g_NumArcs] = arcInfo;
|
||||
g_NumArcs++;
|
||||
g_Arcs[g_NumArcs++] = arcInfo;
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_GUID(CLSID_CArchiveHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
|
||||
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 SetPropString(const char *s, unsigned size, PROPVARIANT *value)
|
||||
static inline HRESULT SetPropStrFromBin(const char *s, unsigned size, PROPVARIANT *value)
|
||||
{
|
||||
if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)
|
||||
value->vt = VT_BSTR;
|
||||
@@ -41,18 +43,18 @@ static inline HRESULT SetPropString(const char *s, unsigned size, PROPVARIANT *v
|
||||
|
||||
static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
|
||||
{
|
||||
return SetPropString((const char *)&guid, sizeof(GUID), value);
|
||||
return SetPropStrFromBin((const char *)&guid, sizeof(guid), value);
|
||||
}
|
||||
|
||||
int FindFormatCalssId(const GUID *clsID)
|
||||
int FindFormatCalssId(const GUID *clsid)
|
||||
{
|
||||
GUID cls = *clsID;
|
||||
GUID cls = *clsid;
|
||||
CLS_ARC_ID_ITEM(cls) = 0;
|
||||
if (cls != CLSID_CArchiveHandler)
|
||||
return -1;
|
||||
Byte id = CLS_ARC_ID_ITEM(*clsID);
|
||||
Byte id = CLS_ARC_ID_ITEM(*clsid);
|
||||
for (unsigned i = 0; i < g_NumArcs; i++)
|
||||
if (g_Arcs[i]->ClassId == id)
|
||||
if (g_Arcs[i]->Id == id)
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
@@ -101,7 +103,7 @@ STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value
|
||||
case NArchive::NHandlerPropID::kClassID:
|
||||
{
|
||||
GUID clsId = CLSID_CArchiveHandler;
|
||||
CLS_ARC_ID_ITEM(clsId) = arc.ClassId;
|
||||
CLS_ARC_ID_ITEM(clsId) = arc.Id;
|
||||
return SetPropGUID(clsId, value);
|
||||
}
|
||||
case NArchive::NHandlerPropID::kExtension: if (arc.Ext) prop = arc.Ext; break;
|
||||
@@ -115,12 +117,12 @@ STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value
|
||||
// case NArchive::NHandlerPropID::kVersion: prop = (UInt32)MY_VER_MIX; break;
|
||||
|
||||
case NArchive::NHandlerPropID::kSignature:
|
||||
if (!arc.IsMultiSignature())
|
||||
return SetPropString((const char *)arc.Signature, arc.SignatureSize, value);
|
||||
if (arc.SignatureSize != 0 && !arc.IsMultiSignature())
|
||||
return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value);
|
||||
break;
|
||||
case NArchive::NHandlerPropID::kMultiSignature:
|
||||
if (arc.IsMultiSignature())
|
||||
return SetPropString((const char *)arc.Signature, arc.SignatureSize, value);
|
||||
if (arc.SignatureSize != 0 && arc.IsMultiSignature())
|
||||
return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value);
|
||||
break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
|
||||
@@ -17,13 +17,180 @@
|
||||
#include "../Common/StreamObjects.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "../Compress/ArjDecoder1.h"
|
||||
#include "../Compress/ArjDecoder2.h"
|
||||
#include "../Compress/CopyCoder.h"
|
||||
#include "../Compress/LzhDecoder.h"
|
||||
|
||||
#include "Common/ItemNameUtils.h"
|
||||
#include "Common/OutStreamWithCRC.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NArj {
|
||||
namespace NDecoder {
|
||||
|
||||
static const unsigned kMatchMinLen = 3;
|
||||
|
||||
static const UInt32 kWindowSize = 1 << 15; // must be >= (1 << 14)
|
||||
|
||||
class CCoder:
|
||||
public ICompressCoder,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CLzOutWindow _outWindow;
|
||||
NBitm::CDecoder<CInBuffer> _inBitStream;
|
||||
|
||||
class CCoderReleaser
|
||||
{
|
||||
CCoder *_coder;
|
||||
public:
|
||||
CCoderReleaser(CCoder *coder): _coder(coder) {}
|
||||
void Disable() { _coder = NULL; }
|
||||
~CCoderReleaser() { if (_coder) _coder->_outWindow.Flush(); }
|
||||
};
|
||||
friend class CCoderReleaser;
|
||||
|
||||
HRESULT CodeReal(UInt64 outSize, ICompressProgressInfo *progress);
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
bool FinishMode;
|
||||
CCoder(): FinishMode(false) {}
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
UInt64 GetInputProcessedSize() const { return _inBitStream.GetProcessedSize(); }
|
||||
};
|
||||
|
||||
HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress)
|
||||
{
|
||||
const UInt32 kStep = 1 << 20;
|
||||
UInt64 next = 0;
|
||||
if (rem > kStep && progress)
|
||||
next = rem - kStep;
|
||||
|
||||
while (rem != 0)
|
||||
{
|
||||
if (rem <= next)
|
||||
{
|
||||
if (_inBitStream.ExtraBitsWereRead())
|
||||
return S_FALSE;
|
||||
|
||||
UInt64 packSize = _inBitStream.GetProcessedSize();
|
||||
UInt64 pos = _outWindow.GetProcessedSize();
|
||||
RINOK(progress->SetRatioInfo(&packSize, &pos));
|
||||
next = 0;
|
||||
if (rem > kStep)
|
||||
next = rem - kStep;
|
||||
}
|
||||
|
||||
UInt32 len;
|
||||
|
||||
{
|
||||
const unsigned kNumBits = 7 + 7;
|
||||
UInt32 val = _inBitStream.GetValue(kNumBits);
|
||||
|
||||
if ((val & (1 << (kNumBits - 1))) == 0)
|
||||
{
|
||||
_outWindow.PutByte((Byte)(val >> 5));
|
||||
_inBitStream.MovePos(1 + 8);
|
||||
rem--;
|
||||
continue;
|
||||
}
|
||||
|
||||
UInt32 mask = 1 << (kNumBits - 2);
|
||||
unsigned w;
|
||||
|
||||
for (w = 1; w < 7; w++, mask >>= 1)
|
||||
if ((val & mask) == 0)
|
||||
break;
|
||||
|
||||
unsigned readBits = (w != 7 ? 1 : 0);
|
||||
readBits += w + w;
|
||||
len = (1 << w) - 1 + kMatchMinLen - 1 +
|
||||
(((val >> (kNumBits - readBits)) & ((1 << w) - 1)));
|
||||
_inBitStream.MovePos(readBits);
|
||||
}
|
||||
|
||||
{
|
||||
const unsigned kNumBits = 4 + 13;
|
||||
UInt32 val = _inBitStream.GetValue(kNumBits);
|
||||
|
||||
unsigned readBits = 1;
|
||||
unsigned w;
|
||||
|
||||
if ((val & ((UInt32)1 << 16)) == 0) w = 9;
|
||||
else if ((val & ((UInt32)1 << 15)) == 0) w = 10;
|
||||
else if ((val & ((UInt32)1 << 14)) == 0) w = 11;
|
||||
else if ((val & ((UInt32)1 << 13)) == 0) w = 12;
|
||||
else { w = 13; readBits = 0; }
|
||||
|
||||
readBits += w + w - 9;
|
||||
|
||||
UInt32 dist = ((UInt32)1 << w) - (1 << 9) +
|
||||
(((val >> (kNumBits - readBits)) & ((1 << w) - 1)));
|
||||
_inBitStream.MovePos(readBits);
|
||||
|
||||
if (len > rem)
|
||||
len = (UInt32)rem;
|
||||
|
||||
if (!_outWindow.CopyBlock(dist, len))
|
||||
return S_FALSE;
|
||||
rem -= len;
|
||||
}
|
||||
}
|
||||
|
||||
if (FinishMode)
|
||||
{
|
||||
if (_inBitStream.ReadAlignBits() != 0)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
if (_inBitStream.ExtraBitsWereRead())
|
||||
return S_FALSE;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!outSize)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (!_outWindow.Create(kWindowSize))
|
||||
return E_OUTOFMEMORY;
|
||||
if (!_inBitStream.Create(1 << 17))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
_outWindow.SetStream(outStream);
|
||||
_outWindow.Init(false);
|
||||
_inBitStream.SetStream(inStream);
|
||||
_inBitStream.Init();
|
||||
|
||||
CCoderReleaser coderReleaser(this);
|
||||
HRESULT res;
|
||||
{
|
||||
res = CodeReal(*outSize, progress);
|
||||
if (res != S_OK)
|
||||
return res;
|
||||
}
|
||||
|
||||
coderReleaser.Disable();
|
||||
return _outWindow.Flush();
|
||||
}
|
||||
catch(const CInBufferException &e) { return e.ErrorCode; }
|
||||
catch(const CLzOutWindowException &e) { return e.ErrorCode; }
|
||||
catch(...) { return S_FALSE; }
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
|
||||
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
#define Get16(p) GetUi16(p)
|
||||
@@ -95,7 +262,7 @@ namespace NHostOS
|
||||
};
|
||||
}
|
||||
|
||||
static const char *kHostOS[] =
|
||||
static const char * const kHostOS[] =
|
||||
{
|
||||
"MSDOS"
|
||||
, "PRIMOS"
|
||||
@@ -164,10 +331,10 @@ API_FUNC_static_IsArc IsArc_Arj(const Byte *p, size_t size)
|
||||
|
||||
static HRESULT ReadString(const Byte *p, unsigned &size, AString &res)
|
||||
{
|
||||
for (unsigned i = 0; i < size;)
|
||||
unsigned num = size;
|
||||
for (unsigned i = 0; i < num;)
|
||||
{
|
||||
char c = (char)p[i++];
|
||||
if (c == 0)
|
||||
if (p[i++] == 0)
|
||||
{
|
||||
size = i;
|
||||
res = (const char *)p;
|
||||
@@ -656,15 +823,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
{
|
||||
const CItem &item = _items[allFilesMode ? i : indices[i]];
|
||||
totalUnpacked += item.Size;
|
||||
totalPacked += item.PackSize;
|
||||
// totalPacked += item.PackSize;
|
||||
}
|
||||
extractCallback->SetTotal(totalUnpacked);
|
||||
|
||||
totalUnpacked = totalPacked = 0;
|
||||
UInt64 curUnpacked, curPacked;
|
||||
|
||||
CMyComPtr<ICompressCoder> arj1Decoder;
|
||||
CMyComPtr<ICompressCoder> arj2Decoder;
|
||||
NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = NULL;
|
||||
CMyComPtr<ICompressCoder> lzhDecoder;
|
||||
|
||||
NCompress::NArj::NDecoder::CCoder *arjDecoderSpec = NULL;
|
||||
CMyComPtr<ICompressCoder> arjDecoder;
|
||||
|
||||
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
|
||||
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
|
||||
|
||||
@@ -741,22 +912,37 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
case NCompressionMethod::kCompressed1b:
|
||||
case NCompressionMethod::kCompressed1c:
|
||||
{
|
||||
if (!arj1Decoder)
|
||||
arj1Decoder = new NCompress::NArj::NDecoder1::CCoder;
|
||||
result = arj1Decoder->Code(inStream, outStream, NULL, &curUnpacked, progress);
|
||||
if (!lzhDecoder)
|
||||
{
|
||||
lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder;
|
||||
lzhDecoder = lzhDecoderSpec;
|
||||
}
|
||||
lzhDecoderSpec->FinishMode = true;
|
||||
const UInt32 kHistorySize = 26624;
|
||||
lzhDecoderSpec->SetDictSize(kHistorySize);
|
||||
result = lzhDecoder->Code(inStream, outStream, NULL, &curUnpacked, progress);
|
||||
if (result == S_OK && lzhDecoderSpec->GetInputProcessedSize() != item.PackSize)
|
||||
result = S_FALSE;
|
||||
break;
|
||||
}
|
||||
case NCompressionMethod::kCompressed2:
|
||||
{
|
||||
if (!arj2Decoder)
|
||||
arj2Decoder = new NCompress::NArj::NDecoder2::CCoder;
|
||||
result = arj2Decoder->Code(inStream, outStream, NULL, &curUnpacked, progress);
|
||||
if (!arjDecoder)
|
||||
{
|
||||
arjDecoderSpec = new NCompress::NArj::NDecoder::CCoder;
|
||||
arjDecoder = arjDecoderSpec;
|
||||
}
|
||||
arjDecoderSpec->FinishMode = true;
|
||||
result = arjDecoder->Code(inStream, outStream, NULL, &curUnpacked, progress);
|
||||
if (result == S_OK && arjDecoderSpec->GetInputProcessedSize() != item.PackSize)
|
||||
result = S_FALSE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
opRes = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
}
|
||||
}
|
||||
|
||||
if (opRes == NExtract::NOperationResult::kOK)
|
||||
{
|
||||
if (result == S_FALSE)
|
||||
@@ -769,23 +955,23 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
NExtract::NOperationResult::kCRCError;
|
||||
}
|
||||
}
|
||||
|
||||
outStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(opRes));
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
static const Byte k_Signature[] = { kSig0, kSig1 };
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Arj", "arj", 0, 4,
|
||||
2, { kSig0, kSig1 },
|
||||
REGISTER_ARC_I(
|
||||
"Arj", "arj", 0, 4,
|
||||
k_Signature,
|
||||
0,
|
||||
0,
|
||||
CreateArc, NULL, IsArc_Arj };
|
||||
|
||||
REGISTER_ARC(Arj)
|
||||
IsArc_Arj)
|
||||
|
||||
}}
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
INTERFACE_IInArchive(;)
|
||||
INTERFACE_IOutArchive(;)
|
||||
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
|
||||
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
|
||||
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
|
||||
|
||||
CHandler() { }
|
||||
};
|
||||
@@ -367,6 +367,8 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
|
||||
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
|
||||
IArchiveUpdateCallback *updateCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
if (numItems != 1)
|
||||
return E_INVALIDARG;
|
||||
|
||||
@@ -381,13 +383,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));
|
||||
if (prop.vt == VT_BOOL)
|
||||
{
|
||||
if (prop.boolVal != VARIANT_FALSE)
|
||||
if (prop.vt != VT_EMPTY)
|
||||
if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
else if (prop.vt != VT_EMPTY)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -403,28 +401,43 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
}
|
||||
return UpdateArchive(size, outStream, _props, updateCallback);
|
||||
}
|
||||
|
||||
if (indexInArchive != 0)
|
||||
return E_INVALIDARG;
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(updateCallback, true);
|
||||
|
||||
CMyComPtr<IArchiveUpdateCallbackFile> opCallback;
|
||||
updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);
|
||||
if (opCallback)
|
||||
{
|
||||
RINOK(opCallback->ReportOperation(
|
||||
NEventIndexType::kInArcIndex, 0,
|
||||
NUpdateNotifyOp::kReplicate))
|
||||
}
|
||||
|
||||
if (_stream)
|
||||
RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
return NCompress::CopyStream(_stream, outStream, NULL);
|
||||
|
||||
return NCompress::CopyStream(_stream, outStream, progress);
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
return _props.SetProperties(names, values, numProps);
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
IMP_CreateArcOut
|
||||
static const Byte k_Signature[] = { 'B', 'Z', 'h' };
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "bzip2", "bz2 bzip2 tbz2 tbz", "* * .tar .tar", 2,
|
||||
3, { 'B', 'Z', 'h' },
|
||||
REGISTER_ARC_IO(
|
||||
"bzip2", "bz2 bzip2 tbz2 tbz", "* * .tar .tar", 2,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kKeepName,
|
||||
REF_CreateArc_Pair, IsArc_BZip2 };
|
||||
|
||||
REGISTER_ARC(BZip2)
|
||||
IsArc_BZip2)
|
||||
|
||||
}}
|
||||
|
||||
@@ -75,11 +75,14 @@ HRESULT CCabBlockInStream::PreRead(ISequentialInStream *stream, UInt32 &packSize
|
||||
|
||||
STDMETHODIMP CCabBlockInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 rem = _size - _pos;
|
||||
if (size > rem)
|
||||
size = rem;
|
||||
memcpy(data, _buf + _pos, size);
|
||||
_pos += size;
|
||||
if (size != 0)
|
||||
{
|
||||
UInt32 rem = _size - _pos;
|
||||
if (size > rem)
|
||||
size = rem;
|
||||
memcpy(data, _buf + _pos, size);
|
||||
_pos += size;
|
||||
}
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
|
||||
@@ -71,7 +71,7 @@ static const Byte kArcProps[] =
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
static const char *kMethods[] =
|
||||
static const char * const kMethods[] =
|
||||
{
|
||||
"None"
|
||||
, "MSZip"
|
||||
@@ -124,17 +124,19 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AString s;
|
||||
|
||||
for (unsigned i = 0; i < kNumMethodsMax; i++)
|
||||
{
|
||||
if ((mask & (1 << i)) == 0)
|
||||
continue;
|
||||
if (!s.IsEmpty())
|
||||
s += ' ';
|
||||
s.Add_Space_if_NotEmpty();
|
||||
char temp[kMethodNameBufSize];
|
||||
SetMethodName(temp, i, params[i == NHeader::NMethod::kQuantum ? 0 : 1]);
|
||||
s += temp;
|
||||
}
|
||||
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
@@ -466,8 +468,8 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
return result;
|
||||
|
||||
if (!_errorMessage.IsEmpty())
|
||||
_errorMessage += L"\n";
|
||||
_errorMessage += L"Can't open volume: ";
|
||||
_errorMessage.Add_LF();
|
||||
_errorMessage.AddAscii("Can't open volume: ");
|
||||
_errorMessage += fullName;
|
||||
|
||||
if (prevChecked)
|
||||
@@ -528,7 +530,7 @@ private:
|
||||
|
||||
Byte *TempBuf;
|
||||
UInt32 TempBufSize;
|
||||
int NumIdenticalFiles;
|
||||
unsigned NumIdenticalFiles;
|
||||
bool TempBufMode;
|
||||
UInt32 m_BufStartFolderOffset;
|
||||
|
||||
@@ -619,8 +621,9 @@ HRESULT CFolderOutStream::OpenFile()
|
||||
{
|
||||
const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];
|
||||
const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
|
||||
int numExtractItems = 0;
|
||||
unsigned numExtractItems = 0;
|
||||
unsigned curIndex;
|
||||
|
||||
for (curIndex = m_CurrentIndex; curIndex < m_ExtractStatuses->Size(); curIndex++)
|
||||
{
|
||||
const CMvItem &mvItem2 = m_Database->Items[m_StartIndex + curIndex];
|
||||
@@ -632,10 +635,12 @@ HRESULT CFolderOutStream::OpenFile()
|
||||
if (!m_TestMode && (*m_ExtractStatuses)[curIndex])
|
||||
numExtractItems++;
|
||||
}
|
||||
|
||||
NumIdenticalFiles = (curIndex - m_CurrentIndex);
|
||||
if (NumIdenticalFiles == 0)
|
||||
NumIdenticalFiles = 1;
|
||||
TempBufMode = false;
|
||||
|
||||
if (numExtractItems > 1)
|
||||
{
|
||||
if (!TempBuf || item.Size > TempBufSize)
|
||||
@@ -699,7 +704,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
UInt32 realProcessed = 0;
|
||||
if (processedSize != NULL)
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
while (size != 0)
|
||||
{
|
||||
@@ -707,7 +712,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
|
||||
{
|
||||
UInt32 numBytesToWrite = MyMin(m_RemainFileSize, size);
|
||||
HRESULT res = S_OK;
|
||||
if (numBytesToWrite > 0)
|
||||
if (numBytesToWrite != 0)
|
||||
{
|
||||
if (!isOK)
|
||||
m_IsOk = false;
|
||||
@@ -721,7 +726,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
|
||||
memcpy(TempBuf + (m_PosInFolder - m_BufStartFolderOffset), data, numBytesToWrite);
|
||||
}
|
||||
realProcessed += numBytesToWrite;
|
||||
if (processedSize != NULL)
|
||||
if (processedSize)
|
||||
*processedSize = realProcessed;
|
||||
data = (const void *)((const Byte *)data + numBytesToWrite);
|
||||
size -= numBytesToWrite;
|
||||
@@ -773,7 +778,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
|
||||
{
|
||||
UInt32 numBytesToWrite = MyMin(fileOffset - (UInt32)m_PosInFolder, size);
|
||||
realProcessed += numBytesToWrite;
|
||||
if (processedSize != NULL)
|
||||
if (processedSize)
|
||||
*processedSize = realProcessed;
|
||||
data = (const void *)((const Byte *)data + numBytesToWrite);
|
||||
size -= numBytesToWrite;
|
||||
@@ -799,24 +804,24 @@ STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *proc
|
||||
|
||||
HRESULT CFolderOutStream::FlushCorrupted()
|
||||
{
|
||||
const UInt32 kBufferSize = (1 << 10);
|
||||
Byte buffer[kBufferSize];
|
||||
for (int i = 0; i < kBufferSize; i++)
|
||||
buffer[i] = 0;
|
||||
const unsigned kBufSize = (1 << 10);
|
||||
Byte buf[kBufSize];
|
||||
for (unsigned i = 0; i < kBufSize; i++)
|
||||
buf[i] = 0;
|
||||
for (;;)
|
||||
{
|
||||
UInt64 remain = GetRemain();
|
||||
if (remain == 0)
|
||||
return S_OK;
|
||||
UInt32 size = (UInt32)MyMin(remain, (UInt64)kBufferSize);
|
||||
UInt32 size = (remain < kBufSize ? (UInt32)remain : (UInt32)kBufSize);
|
||||
UInt32 processedSizeLocal = 0;
|
||||
RINOK(Write2(buffer, size, &processedSizeLocal, false));
|
||||
RINOK(Write2(buf, size, &processedSizeLocal, false));
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CFolderOutStream::Unsupported()
|
||||
{
|
||||
while(m_CurrentIndex < m_ExtractStatuses->Size())
|
||||
while (m_CurrentIndex < m_ExtractStatuses->Size())
|
||||
{
|
||||
HRESULT result = OpenFile();
|
||||
if (result != S_FALSE && result != S_OK)
|
||||
@@ -844,9 +849,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
UInt32 i;
|
||||
int lastFolder = -2;
|
||||
UInt64 lastFolderSize = 0;
|
||||
for(i = 0; i < numItems; i++)
|
||||
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
int index = allFilesMode ? i : indices[i];
|
||||
unsigned index = allFilesMode ? i : indices[i];
|
||||
const CMvItem &mvItem = m_Database.Items[index];
|
||||
const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
|
||||
if (item.IsDir())
|
||||
@@ -857,6 +863,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
lastFolder = folderIndex;
|
||||
lastFolderSize = item.GetEndOffset();
|
||||
}
|
||||
|
||||
totalUnPacked += lastFolderSize;
|
||||
|
||||
extractCallback->SetTotal(totalUnPacked);
|
||||
@@ -887,9 +894,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
CRecordVector<bool> extractStatuses;
|
||||
for(i = 0; i < numItems;)
|
||||
|
||||
for (i = 0; i < numItems;)
|
||||
{
|
||||
int index = allFilesMode ? i : indices[i];
|
||||
unsigned index = allFilesMode ? i : indices[i];
|
||||
|
||||
const CMvItem &mvItem = m_Database.Items[index];
|
||||
const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex];
|
||||
@@ -909,7 +917,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
|
||||
continue;
|
||||
}
|
||||
|
||||
int folderIndex = m_Database.GetFolderIndex(&mvItem);
|
||||
|
||||
if (folderIndex < 0)
|
||||
{
|
||||
// If we need previous archive
|
||||
@@ -923,17 +933,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError));
|
||||
continue;
|
||||
}
|
||||
int startIndex2 = m_Database.FolderStartFileIndex[folderIndex];
|
||||
int startIndex = startIndex2;
|
||||
|
||||
unsigned startIndex2 = m_Database.FolderStartFileIndex[folderIndex];
|
||||
unsigned startIndex = startIndex2;
|
||||
extractStatuses.Clear();
|
||||
for (; startIndex < index; startIndex++)
|
||||
extractStatuses.Add(false);
|
||||
extractStatuses.Add(true);
|
||||
startIndex++;
|
||||
UInt64 curUnpack = item.GetEndOffset();
|
||||
|
||||
for (; i < numItems; i++)
|
||||
{
|
||||
int indexNext = allFilesMode ? i : indices[i];
|
||||
unsigned indexNext = allFilesMode ? i : indices[i];
|
||||
const CMvItem &mvItem = m_Database.Items[indexNext];
|
||||
const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
|
||||
if (item.IsDir())
|
||||
@@ -963,6 +975,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
cabBlockInStreamSpec->MsZip = false;
|
||||
HRESULT res = S_OK;
|
||||
|
||||
switch (folder.GetMethod())
|
||||
{
|
||||
case NHeader::NMethod::kNone:
|
||||
@@ -1009,7 +1022,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
int locFolderIndex = item.GetFolderIndex(db.Folders.Size());
|
||||
bool keepHistory = false;
|
||||
bool keepInputBuffer = false;
|
||||
for (UInt32 f = 0; cabFolderOutStream->GetRemain() != 0;)
|
||||
|
||||
for (UInt32 bl = 0; cabFolderOutStream->GetRemain() != 0;)
|
||||
{
|
||||
if (volIndex >= m_Database.Volumes.Size())
|
||||
{
|
||||
@@ -1019,19 +1033,32 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
const CDatabaseEx &db = m_Database.Volumes[volIndex];
|
||||
const CFolder &folder = db.Folders[locFolderIndex];
|
||||
if (f == 0)
|
||||
|
||||
if (bl == 0)
|
||||
{
|
||||
cabBlockInStreamSpec->ReservedSize = db.ArcInfo.GetDataBlockReserveSize();
|
||||
RINOK(db.Stream->Seek(db.StartPosition + folder.DataStart, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
if (f == folder.NumDataBlocks)
|
||||
|
||||
if (bl == folder.NumDataBlocks)
|
||||
{
|
||||
volIndex++;
|
||||
locFolderIndex = 0;
|
||||
f = 0;
|
||||
continue;
|
||||
/*
|
||||
CFolder::NumDataBlocks (CFFOLDER::cCFData in CAB specification) is 16-bit.
|
||||
But there are some big CAB archives from MS that contain more
|
||||
than (0xFFFF) CFDATA blocks in folder.
|
||||
Old cab extracting software can show error (or ask next volume)
|
||||
but cab extracting library in new Windows ignores this error.
|
||||
15.00 : We also try to ignore such error, if archive is not multi-volume.
|
||||
*/
|
||||
if (m_Database.Volumes.Size() > 1)
|
||||
{
|
||||
volIndex++;
|
||||
locFolderIndex = 0;
|
||||
bl = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
f++;
|
||||
bl++;
|
||||
|
||||
if (!keepInputBuffer)
|
||||
cabBlockInStreamSpec->InitForNewBlock();
|
||||
@@ -1059,7 +1086,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
unpackRemain = kBlockSizeMax;
|
||||
if (unpackRemain > unpackSize)
|
||||
unpackRemain = unpackSize;
|
||||
|
||||
|
||||
switch (folder.GetMethod())
|
||||
{
|
||||
case NHeader::NMethod::kNone:
|
||||
@@ -1092,14 +1119,17 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
res = quantumDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
if (res != S_OK)
|
||||
{
|
||||
if (res != S_FALSE)
|
||||
RINOK(res);
|
||||
break;
|
||||
}
|
||||
|
||||
keepHistory = true;
|
||||
}
|
||||
|
||||
if (res == S_OK)
|
||||
{
|
||||
RINOK(cabFolderOutStream->WriteEmptyFiles());
|
||||
@@ -1111,6 +1141,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
}
|
||||
totalUnPacked += curUnpack;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NHeader {
|
||||
|
||||
Byte kMarker[kMarkerSize] = {'M', 'S', 'C', 'F', 0, 0, 0, 0 };
|
||||
const Byte kMarker[kMarkerSize] = {'M', 'S', 'C', 'F', 0, 0, 0, 0 };
|
||||
|
||||
// struct CSignatureInitializer { CSignatureInitializer() { kMarker[0]--; }; } g_SignatureInitializer;
|
||||
// struct CSignatureInitializer { CSignatureInitializer() { kMarker[0]--; } } g_SignatureInitializer;
|
||||
|
||||
}}}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Archive/Cab/Header.h
|
||||
// Archive/CabHeader.h
|
||||
|
||||
#ifndef __ARCHIVE_CAB_HEADER_H
|
||||
#define __ARCHIVE_CAB_HEADER_H
|
||||
@@ -10,7 +10,7 @@ namespace NCab {
|
||||
namespace NHeader {
|
||||
|
||||
const unsigned kMarkerSize = 8;
|
||||
extern Byte kMarker[kMarkerSize];
|
||||
extern const Byte kMarker[kMarkerSize];
|
||||
|
||||
namespace NArcFlags
|
||||
{
|
||||
|
||||
@@ -40,8 +40,7 @@ void CInArchive::ReadName(AString &s)
|
||||
throw CUnexpectedEndException();
|
||||
if (b == 0)
|
||||
{
|
||||
memcpy(s.GetBuffer((unsigned)i), _tempBuf, i);
|
||||
s.ReleaseBuffer((unsigned)i);
|
||||
s.SetFrom((const char *)(const Byte *)_tempBuf, (unsigned)i);
|
||||
return;
|
||||
}
|
||||
if (_tempBuf.Size() == i)
|
||||
|
||||
@@ -17,6 +17,12 @@ struct COtherArc
|
||||
{
|
||||
AString FileName;
|
||||
AString DiskName;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
FileName.Empty();
|
||||
DiskName.Empty();
|
||||
}
|
||||
};
|
||||
|
||||
struct CArchInfo
|
||||
@@ -43,7 +49,9 @@ struct CArchInfo
|
||||
|
||||
CArchInfo()
|
||||
{
|
||||
Clear();
|
||||
PerCabinet_AreaSize = 0;
|
||||
PerFolder_AreaSize = 0;
|
||||
PerDataBlock_AreaSize = 0;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
@@ -51,6 +59,9 @@ struct CArchInfo
|
||||
PerCabinet_AreaSize = 0;
|
||||
PerFolder_AreaSize = 0;
|
||||
PerDataBlock_AreaSize = 0;
|
||||
|
||||
PrevArc.Clear();
|
||||
NextArc.Clear();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ struct CItem
|
||||
FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext;
|
||||
}
|
||||
|
||||
int GetFolderIndex(int numFolders) const
|
||||
int GetFolderIndex(unsigned numFolders) const
|
||||
{
|
||||
if (ContinuedFromPrev())
|
||||
return 0;
|
||||
|
||||
@@ -9,15 +9,11 @@
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Cab", "cab", 0, 8,
|
||||
8, { 'M', 'S', 'C', 'F', 0, 0, 0, 0 },
|
||||
REGISTER_ARC_I(
|
||||
"Cab", "cab", 0, 8,
|
||||
NHeader::kMarker,
|
||||
0,
|
||||
NArcInfoFlags::kFindSignature,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Cab)
|
||||
NULL)
|
||||
|
||||
}}
|
||||
|
||||
@@ -123,15 +123,16 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
case kpidPath:
|
||||
{
|
||||
UString us;
|
||||
if (ConvertUTF8ToUnicode(item.Name, us))
|
||||
// if (
|
||||
ConvertUTF8ToUnicode(item.Name, us);
|
||||
{
|
||||
if (!m_Database.LowLevel)
|
||||
{
|
||||
if (us.Len() > 1)
|
||||
if (us[0] == L'/')
|
||||
us.Delete(0);
|
||||
if (us.Len() > 1 && us[0] == L'/')
|
||||
us.Delete(0);
|
||||
}
|
||||
prop = NItemName::GetOSName2(us);
|
||||
NItemName::ConvertToOSName2(us);
|
||||
prop = us;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -141,7 +142,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
{
|
||||
if (!item.IsDir())
|
||||
if (item.Section == 0)
|
||||
prop = L"Copy";
|
||||
prop = "Copy";
|
||||
else if (item.Section < m_Database.Sections.Size())
|
||||
prop = m_Database.Sections[(int)item.Section].GetMethodName();
|
||||
break;
|
||||
@@ -734,30 +735,30 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
|
||||
namespace NChm {
|
||||
|
||||
IMP_CreateArcIn_2(CHandler(false))
|
||||
static const Byte k_Signature[] = { 'I', 'T', 'S', 'F', 3, 0, 0, 0, 0x60, 0, 0, 0 };
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Chm", "chm chi chq chw", 0, 0xE9,
|
||||
12, { 'I', 'T', 'S', 'F', 3, 0, 0, 0, 0x60, 0, 0, 0 },
|
||||
REGISTER_ARC_I_CLS(
|
||||
CHandler(false),
|
||||
"Chm", "chm chi chq chw", 0, 0xE9,
|
||||
k_Signature,
|
||||
0,
|
||||
0,
|
||||
CreateArc };
|
||||
NULL)
|
||||
|
||||
REGISTER_ARC(Chm)
|
||||
}
|
||||
|
||||
namespace NHxs {
|
||||
|
||||
IMP_CreateArcIn_2(CHandler(true))
|
||||
static const Byte k_Signature[] = { 'I', 'T', 'O', 'L', 'I', 'T', 'L', 'S', 1, 0, 0, 0, 0x28, 0, 0, 0 };
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Hxs", "hxs hxi hxr hxq hxw lit", 0, 0xCE,
|
||||
16, { 'I', 'T', 'O', 'L', 'I', 'T', 'L', 'S', 1, 0, 0, 0, 0x28, 0, 0, 0 },
|
||||
REGISTER_ARC_I_CLS(
|
||||
CHandler(true),
|
||||
"Hxs", "hxs hxi hxr hxq hxw lit", 0, 0xCE,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kFindSignature,
|
||||
CreateArc };
|
||||
NULL)
|
||||
|
||||
REGISTER_ARC(Hxs)
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -107,10 +107,10 @@ UString CMethodInfo::GetName() const
|
||||
UString s;
|
||||
if (IsLzx())
|
||||
{
|
||||
s = L"LZX:";
|
||||
wchar_t temp[16];
|
||||
s.SetFromAscii("LZX:");
|
||||
char temp[16];
|
||||
ConvertUInt32ToString(LzxInfo.GetNumDictBits(), temp);
|
||||
s += temp;
|
||||
s.AddAscii(temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -147,12 +147,12 @@ UString CSectionInfo::GetMethodName() const
|
||||
UString temp;
|
||||
if (ConvertUTF8ToUnicode(Name, temp))
|
||||
s += temp;
|
||||
s += L": ";
|
||||
s.AddAscii(": ");
|
||||
}
|
||||
FOR_VECTOR (i, Methods)
|
||||
{
|
||||
if (i != 0)
|
||||
s += L' ';
|
||||
s.Add_Space();
|
||||
s += Methods[i].GetName();
|
||||
}
|
||||
return s;
|
||||
@@ -584,9 +584,9 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
|
||||
AString s;
|
||||
ConvertUnicodeToUTF8(name, s);
|
||||
Byte b = ReadByte();
|
||||
s += ' ';
|
||||
s.Add_Space();
|
||||
PrintByte(b, s);
|
||||
s += ' ';
|
||||
s.Add_Space();
|
||||
UInt64 len = ReadEncInt();
|
||||
// then number of items ?
|
||||
// then length ?
|
||||
@@ -641,7 +641,10 @@ static const char *kTransformList = "List";
|
||||
|
||||
static AString GetSectionPrefix(const AString &name)
|
||||
{
|
||||
return AString(kStorage) + name + AString("/");
|
||||
AString s = kStorage;
|
||||
s += name;
|
||||
s += '/';
|
||||
return s;
|
||||
}
|
||||
|
||||
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
|
||||
@@ -721,8 +724,8 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
|
||||
ReadUString(nameLen, name);
|
||||
if (ReadUInt16() != 0)
|
||||
return S_FALSE;
|
||||
if (!ConvertUnicodeToUTF8(name, section.Name))
|
||||
return S_FALSE;
|
||||
ConvertUnicodeToUTF8(name, section.Name);
|
||||
// if (!ConvertUnicodeToUTF8(name, section.Name)) return S_FALSE;
|
||||
database.Sections.Add(section);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,10 +120,10 @@ struct CLzxInfo
|
||||
return 0;
|
||||
}
|
||||
|
||||
UInt64 GetFolderSize() const { return ResetTable.BlockSize * ResetInterval; };
|
||||
UInt64 GetFolder(UInt64 offset) const { return offset / GetFolderSize(); };
|
||||
UInt64 GetFolderPos(UInt64 folderIndex) const { return folderIndex * GetFolderSize(); };
|
||||
UInt64 GetBlockIndexFromFolderIndex(UInt64 folderIndex) const { return folderIndex * ResetInterval; };
|
||||
UInt64 GetFolderSize() const { return ResetTable.BlockSize * ResetInterval; }
|
||||
UInt64 GetFolder(UInt64 offset) const { return offset / GetFolderSize(); }
|
||||
UInt64 GetFolderPos(UInt64 folderIndex) const { return folderIndex * GetFolderSize(); }
|
||||
UInt64 GetBlockIndexFromFolderIndex(UInt64 folderIndex) const { return folderIndex * ResetInterval; }
|
||||
bool GetOffsetOfFolder(UInt64 folderIndex, UInt64 &offset) const
|
||||
{
|
||||
UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex);
|
||||
|
||||
@@ -27,8 +27,7 @@ namespace NArchive {
|
||||
namespace NCom {
|
||||
|
||||
#define SIGNATURE { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }
|
||||
static const UInt32 kSignatureSize = 8;
|
||||
static const Byte kSignature[kSignatureSize] = SIGNATURE;
|
||||
static const Byte kSignature[] = SIGNATURE;
|
||||
|
||||
enum EType
|
||||
{
|
||||
@@ -40,7 +39,7 @@ enum EType
|
||||
k_Type_Xls,
|
||||
};
|
||||
|
||||
static const char *kExtensions[] =
|
||||
static const char * const kExtensions[] =
|
||||
{
|
||||
"compound"
|
||||
, "msi"
|
||||
@@ -240,8 +239,8 @@ HRESULT CDatabase::AddNode(int parent, UInt32 did)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const char kCharOpenBracket = '[';
|
||||
static const char kCharCloseBracket = ']';
|
||||
static const wchar_t kCharOpenBracket = L'[';
|
||||
static const wchar_t kCharCloseBracket = L']';
|
||||
|
||||
static UString CompoundNameToFileName(const UString &s)
|
||||
{
|
||||
@@ -263,23 +262,25 @@ static UString CompoundNameToFileName(const UString &s)
|
||||
return res;
|
||||
}
|
||||
|
||||
static char g_MsiChars[] =
|
||||
static const char k_Msi_Chars[] =
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._";
|
||||
|
||||
static const wchar_t *kMsi_ID = L""; // L"{msi}";
|
||||
// static const char *k_Msi_ID = ""; // "{msi}";
|
||||
static const wchar_t k_Msi_SpecChar = L'!';
|
||||
|
||||
static const unsigned k_Msi_NumBits = 6;
|
||||
static const unsigned k_Msi_NumChars = 1 << k_Msi_NumBits;
|
||||
static const unsigned k_Msi_CharMask = k_Msi_NumChars - 1;
|
||||
static const unsigned k_Msi_StartUnicodeChar = 0x3800;
|
||||
static const unsigned k_Msi_UnicodeRange = k_Msi_NumChars * (k_Msi_NumChars + 1);
|
||||
|
||||
static const unsigned kMsiNumBits = 6;
|
||||
static const UInt32 kMsiNumChars = 1 << kMsiNumBits;
|
||||
static const UInt32 kMsiCharMask = kMsiNumChars - 1;
|
||||
static const UInt32 kMsiStartUnicodeChar = 0x3800;
|
||||
static const UInt32 kMsiUnicodeRange = kMsiNumChars * (kMsiNumChars + 1);
|
||||
|
||||
static bool IsMsiName(const Byte *p)
|
||||
{
|
||||
UInt32 c = Get16(p);
|
||||
return
|
||||
c >= kMsiStartUnicodeChar &&
|
||||
c <= kMsiStartUnicodeChar + kMsiUnicodeRange;
|
||||
c >= k_Msi_StartUnicodeChar &&
|
||||
c <= k_Msi_StartUnicodeChar + k_Msi_UnicodeRange;
|
||||
}
|
||||
|
||||
static bool AreEqualNames(const Byte *rawName, const char *asciiName)
|
||||
@@ -296,30 +297,32 @@ static bool AreEqualNames(const Byte *rawName, const char *asciiName)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool CompoundMsiNameToFileName(const UString &name, UString &resultName)
|
||||
static bool CompoundMsiNameToFileName(const UString &name, UString &res)
|
||||
{
|
||||
resultName.Empty();
|
||||
res.Empty();
|
||||
for (unsigned i = 0; i < name.Len(); i++)
|
||||
{
|
||||
wchar_t c = name[i];
|
||||
if (c < kMsiStartUnicodeChar || c > kMsiStartUnicodeChar + kMsiUnicodeRange)
|
||||
if (c < k_Msi_StartUnicodeChar || c > k_Msi_StartUnicodeChar + k_Msi_UnicodeRange)
|
||||
return false;
|
||||
/*
|
||||
if (i == 0)
|
||||
resultName += kMsi_ID;
|
||||
c -= kMsiStartUnicodeChar;
|
||||
res += k_Msi_ID;
|
||||
*/
|
||||
c -= k_Msi_StartUnicodeChar;
|
||||
|
||||
UInt32 c0 = c & kMsiCharMask;
|
||||
UInt32 c1 = c >> kMsiNumBits;
|
||||
unsigned c0 = (unsigned)c & k_Msi_CharMask;
|
||||
unsigned c1 = (unsigned)c >> k_Msi_NumBits;
|
||||
|
||||
if (c1 <= kMsiNumChars)
|
||||
if (c1 <= k_Msi_NumChars)
|
||||
{
|
||||
resultName += (wchar_t)g_MsiChars[c0];
|
||||
if (c1 == kMsiNumChars)
|
||||
res += (wchar_t)(Byte)k_Msi_Chars[c0];
|
||||
if (c1 == k_Msi_NumChars)
|
||||
break;
|
||||
resultName += (wchar_t)g_MsiChars[c1];
|
||||
res += (wchar_t)(Byte)k_Msi_Chars[c1];
|
||||
}
|
||||
else
|
||||
resultName += L'!';
|
||||
res += k_Msi_SpecChar;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -328,6 +331,7 @@ static UString ConvertName(const Byte *p, bool &isMsi)
|
||||
{
|
||||
isMsi = false;
|
||||
UString s;
|
||||
|
||||
for (unsigned i = 0; i < kNameSizeMax; i += 2)
|
||||
{
|
||||
wchar_t c = Get16(p + i);
|
||||
@@ -335,6 +339,7 @@ static UString ConvertName(const Byte *p, bool &isMsi)
|
||||
break;
|
||||
s += c;
|
||||
}
|
||||
|
||||
UString msiName;
|
||||
if (CompoundMsiNameToFileName(s, msiName))
|
||||
{
|
||||
@@ -416,7 +421,7 @@ HRESULT CDatabase::Open(IInStream *inStream)
|
||||
Byte p[kHeaderSize];
|
||||
PhySize = kHeaderSize;
|
||||
RINOK(ReadStream_FALSE(inStream, p, kHeaderSize));
|
||||
if (memcmp(p, kSignature, kSignatureSize) != 0)
|
||||
if (memcmp(p, kSignature, ARRAY_SIZE(kSignature)) != 0)
|
||||
return S_FALSE;
|
||||
if (Get16(p + 0x1A) > 4) // majorVer
|
||||
return S_FALSE;
|
||||
@@ -573,11 +578,14 @@ HRESULT CDatabase::Open(IInStream *inStream)
|
||||
continue;
|
||||
bool isMsiName;
|
||||
UString msiName = ConvertName(item.Name, isMsiName);
|
||||
if (isMsiName && msiName.Len() >= 4 &&
|
||||
MyStringCompareNoCase(msiName.RightPtr(4), L".cab") == 0)
|
||||
if (isMsiName)
|
||||
{
|
||||
numCabs++;
|
||||
MainSubfile = i;
|
||||
if (msiName.Len() >= 4 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(4), ".cab")
|
||||
|| msiName.Len() >= 3 && msiName[0] != k_Msi_SpecChar && StringsAreEqualNoCase_Ascii(msiName.RightPtr(3), "exe"))
|
||||
{
|
||||
numCabs++;
|
||||
MainSubfile = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (numCabs > 1)
|
||||
@@ -663,7 +671,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidExtension: prop = kExtensions[_db.Type]; break;
|
||||
case kpidExtension: prop = kExtensions[(unsigned)_db.Type]; break;
|
||||
case kpidPhySize: prop = _db.PhySize; break;
|
||||
case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break;
|
||||
case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break;
|
||||
@@ -861,15 +869,11 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Compound", "msi msp doc xls ppt", 0, 0xE5,
|
||||
kSignatureSize, SIGNATURE,
|
||||
REGISTER_ARC_I(
|
||||
"Compound", "msi msp doc xls ppt", 0, 0xE5,
|
||||
kSignature,
|
||||
0,
|
||||
0,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Com)
|
||||
NULL)
|
||||
|
||||
}}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,172 +8,430 @@
|
||||
|
||||
#include "../../ICoder.h"
|
||||
|
||||
namespace NCoderMixer {
|
||||
#include "../../Common/CreateCoder.h"
|
||||
|
||||
struct CBindPair
|
||||
#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
|
||||
{
|
||||
UInt32 InIndex;
|
||||
UInt32 OutIndex;
|
||||
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 NumInStreams;
|
||||
UInt32 NumOutStreams;
|
||||
UInt32 NumStreams;
|
||||
};
|
||||
|
||||
|
||||
struct CBindInfo
|
||||
{
|
||||
CRecordVector<CCoderStreamsInfo> Coders;
|
||||
CRecordVector<CBindPair> BindPairs;
|
||||
CRecordVector<UInt32> InStreams;
|
||||
CRecordVector<UInt32> OutStreams;
|
||||
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 i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FindBond_for_UnpackStream(UInt32 unpackStream) const
|
||||
{
|
||||
FOR_VECTOR (i, Bonds)
|
||||
if (Bonds[i].UnpackIndex == unpackStream)
|
||||
return 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 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();
|
||||
BindPairs.Clear();
|
||||
InStreams.Clear();
|
||||
OutStreams.Clear();
|
||||
}
|
||||
Bonds.Clear();
|
||||
PackStreams.Clear();
|
||||
|
||||
/*
|
||||
UInt32 GetCoderStartOutStream(UInt32 coderIndex) const
|
||||
{
|
||||
UInt32 numOutStreams = 0;
|
||||
for (UInt32 i = 0; i < coderIndex; i++)
|
||||
numOutStreams += Coders[i].NumOutStreams;
|
||||
return numOutStreams;
|
||||
ClearMaps();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const
|
||||
|
||||
void GetCoder_for_Stream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const
|
||||
{
|
||||
numInStreams = 0;
|
||||
numOutStreams = 0;
|
||||
FOR_VECTOR (i, Coders)
|
||||
{
|
||||
const CCoderStreamsInfo &coderStreamsInfo = Coders[i];
|
||||
numInStreams += coderStreamsInfo.NumInStreams;
|
||||
numOutStreams += coderStreamsInfo.NumOutStreams;
|
||||
}
|
||||
}
|
||||
|
||||
int FindBinderForInStream(UInt32 inStream) const
|
||||
{
|
||||
FOR_VECTOR (i, BindPairs)
|
||||
if (BindPairs[i].InIndex == inStream)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
int FindBinderForOutStream(UInt32 outStream) const
|
||||
{
|
||||
FOR_VECTOR (i, BindPairs)
|
||||
if (BindPairs[i].OutIndex == outStream)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const
|
||||
{
|
||||
UInt32 streamIndex = 0;
|
||||
for (UInt32 i = 0; i < coderIndex; i++)
|
||||
streamIndex += Coders[i].NumInStreams;
|
||||
return streamIndex;
|
||||
}
|
||||
|
||||
UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const
|
||||
{
|
||||
UInt32 streamIndex = 0;
|
||||
for (UInt32 i = 0; i < coderIndex; i++)
|
||||
streamIndex += Coders[i].NumOutStreams;
|
||||
return streamIndex;
|
||||
}
|
||||
|
||||
|
||||
void FindInStream(UInt32 streamIndex, UInt32 &coderIndex,
|
||||
UInt32 &coderStreamIndex) const
|
||||
{
|
||||
for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)
|
||||
{
|
||||
UInt32 curSize = Coders[coderIndex].NumInStreams;
|
||||
if (streamIndex < curSize)
|
||||
{
|
||||
coderStreamIndex = streamIndex;
|
||||
return;
|
||||
}
|
||||
streamIndex -= curSize;
|
||||
}
|
||||
throw 1;
|
||||
}
|
||||
void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex,
|
||||
UInt32 &coderStreamIndex) const
|
||||
{
|
||||
for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)
|
||||
{
|
||||
UInt32 curSize = Coders[coderIndex].NumOutStreams;
|
||||
if (streamIndex < curSize)
|
||||
{
|
||||
coderStreamIndex = streamIndex;
|
||||
return;
|
||||
}
|
||||
streamIndex -= curSize;
|
||||
}
|
||||
throw 1;
|
||||
coderIndex = Stream_to_Coder[streamIndex];
|
||||
coderStreamIndex = streamIndex - Coder_to_Stream[coderIndex];
|
||||
}
|
||||
};
|
||||
|
||||
class CBindReverseConverter
|
||||
|
||||
|
||||
class CCoder
|
||||
{
|
||||
UInt32 _numSrcOutStreams;
|
||||
NCoderMixer::CBindInfo _srcBindInfo;
|
||||
CRecordVector<UInt32> _srcInToDestOutMap;
|
||||
CRecordVector<UInt32> _srcOutToDestInMap;
|
||||
CRecordVector<UInt32> _destInToSrcOutMap;
|
||||
CLASS_NO_COPY(CCoder);
|
||||
public:
|
||||
UInt32 NumSrcInStreams;
|
||||
CRecordVector<UInt32> DestOutToSrcInMap;
|
||||
|
||||
CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo);
|
||||
void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo);
|
||||
};
|
||||
|
||||
void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
|
||||
CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems);
|
||||
|
||||
struct CCoderInfo2
|
||||
{
|
||||
CMyComPtr<ICompressCoder> Coder;
|
||||
CMyComPtr<ICompressCoder2> Coder2;
|
||||
UInt32 NumInStreams;
|
||||
UInt32 NumOutStreams;
|
||||
UInt32 NumStreams;
|
||||
|
||||
CRecordVector<UInt64> InSizes;
|
||||
CRecordVector<UInt64> OutSizes;
|
||||
CRecordVector<const UInt64 *> InSizePointers;
|
||||
CRecordVector<const UInt64 *> OutSizePointers;
|
||||
UInt64 UnpackSize;
|
||||
const UInt64 *UnpackSizePointer;
|
||||
|
||||
CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams):
|
||||
NumInStreams(numInStreams),
|
||||
NumOutStreams(numOutStreams) {}
|
||||
void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);
|
||||
CRecordVector<UInt64> PackSizes;
|
||||
CRecordVector<const UInt64 *> PackSizePointers;
|
||||
|
||||
CCoder() {}
|
||||
|
||||
void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes);
|
||||
|
||||
IUnknown *GetUnknown() const
|
||||
{
|
||||
return Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;
|
||||
}
|
||||
|
||||
HRESULT QueryInterface(REFGUID iid, void** pp) const
|
||||
{
|
||||
IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;
|
||||
return p->QueryInterface(iid, pp);
|
||||
return GetUnknown()->QueryInterface(iid, pp);
|
||||
}
|
||||
};
|
||||
|
||||
class CCoderMixer2
|
||||
|
||||
|
||||
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:
|
||||
virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0;
|
||||
unsigned MainCoderIndex;
|
||||
|
||||
CMixer(bool encodeMode):
|
||||
EncodeMode(encodeMode),
|
||||
MainCoderIndex(0)
|
||||
{}
|
||||
|
||||
/*
|
||||
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 void ReInit() = 0;
|
||||
virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0;
|
||||
virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) = 0;
|
||||
virtual HRESULT Code(
|
||||
ISequentialInStream * const *inStreams,
|
||||
ISequentialOutStream * const *outStreams,
|
||||
ICompressProgressInfo *progress) = 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
|
||||
{
|
||||
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 void ReInit();
|
||||
virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
|
||||
{ _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
|
||||
virtual HRESULT Code(
|
||||
ISequentialInStream * const *inStreams,
|
||||
ISequentialOutStream * const *outStreams,
|
||||
ICompressProgressInfo *progress);
|
||||
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) {}
|
||||
~CCoderMT() { CVirtThread::WaitThreadFinish(); }
|
||||
|
||||
void Code(ICompressProgressInfo *progress);
|
||||
};
|
||||
|
||||
|
||||
class CMixerMT:
|
||||
public IUnknown,
|
||||
public CMixer,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CObjectVector<CStreamBinder> _streamBinders;
|
||||
|
||||
HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams);
|
||||
HRESULT ReturnIfError(HRESULT code);
|
||||
|
||||
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 void ReInit();
|
||||
virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
|
||||
{ _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
|
||||
virtual HRESULT Code(
|
||||
ISequentialInStream * const *inStreams,
|
||||
ISequentialOutStream * const *outStreams,
|
||||
ICompressProgressInfo *progress);
|
||||
virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
|
||||
|
||||
CMixerMT(bool encodeMode): CMixer(encodeMode) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,125 +4,153 @@
|
||||
|
||||
#include "CoderMixer2MT.h"
|
||||
|
||||
namespace NCoderMixer {
|
||||
namespace NCoderMixer2 {
|
||||
|
||||
CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams):
|
||||
CCoderInfo2(numInStreams, numOutStreams)
|
||||
void CCoderMT::Execute() { Code(NULL); }
|
||||
|
||||
void CCoderMT::Code(ICompressProgressInfo *progress)
|
||||
{
|
||||
InStreams.ClearAndReserve(NumInStreams);
|
||||
OutStreams.ClearAndReserve(NumOutStreams);
|
||||
}
|
||||
unsigned numInStreams = EncodeMode ? 1 : NumStreams;
|
||||
unsigned numOutStreams = EncodeMode ? NumStreams : 1;
|
||||
|
||||
void CCoder2::Execute() { Code(NULL); }
|
||||
InStreamPointers.ClearAndReserve(numInStreams);
|
||||
OutStreamPointers.ClearAndReserve(numOutStreams);
|
||||
|
||||
void CCoder2::Code(ICompressProgressInfo *progress)
|
||||
{
|
||||
InStreamPointers.ClearAndReserve(NumInStreams);
|
||||
OutStreamPointers.ClearAndReserve(NumOutStreams);
|
||||
UInt32 i;
|
||||
for (i = 0; i < NumInStreams; i++)
|
||||
{
|
||||
if (InSizePointers[i])
|
||||
InSizePointers[i] = &InSizes[i];
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < numInStreams; i++)
|
||||
InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]);
|
||||
}
|
||||
for (i = 0; i < NumOutStreams; i++)
|
||||
{
|
||||
if (OutSizePointers[i])
|
||||
OutSizePointers[i] = &OutSizes[i];
|
||||
|
||||
for (i = 0; i < numOutStreams; i++)
|
||||
OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]);
|
||||
}
|
||||
|
||||
// we suppose that UnpackSizePointer and PackSizePointers contain correct pointers.
|
||||
/*
|
||||
if (UnpackSizePointer)
|
||||
UnpackSizePointer = &UnpackSize;
|
||||
for (i = 0; i < NumStreams; i++)
|
||||
if (PackSizePointers[i])
|
||||
PackSizePointers[i] = &PackSizes[i];
|
||||
*/
|
||||
|
||||
if (Coder)
|
||||
Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],
|
||||
InSizePointers[0], OutSizePointers[0], progress);
|
||||
EncodeMode ? UnpackSizePointer : PackSizePointers[0],
|
||||
EncodeMode ? PackSizePointers[0] : UnpackSizePointer,
|
||||
progress);
|
||||
else
|
||||
Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams,
|
||||
&OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress);
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < InStreams.Size(); i++)
|
||||
InStreams[i].Release();
|
||||
for (i = 0; i < OutStreams.Size(); i++)
|
||||
OutStreams[i].Release();
|
||||
}
|
||||
Result = Coder2->Code(
|
||||
&InStreamPointers.Front(), EncodeMode ? &UnpackSizePointer : &PackSizePointers.Front(), numInStreams,
|
||||
&OutStreamPointers.Front(), EncodeMode ? &PackSizePointers.Front(): &UnpackSizePointer, numOutStreams,
|
||||
progress);
|
||||
|
||||
InStreamPointers.Clear();
|
||||
OutStreamPointers.Clear();
|
||||
|
||||
for (i = 0; i < InStreams.Size(); i++)
|
||||
InStreams[i].Release();
|
||||
for (i = 0; i < OutStreams.Size(); i++)
|
||||
OutStreams[i].Release();
|
||||
}
|
||||
|
||||
/*
|
||||
void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)
|
||||
HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo)
|
||||
{
|
||||
SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
|
||||
SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
|
||||
}
|
||||
*/
|
||||
|
||||
//////////////////////////////////////
|
||||
// CCoderMixer2MT
|
||||
|
||||
HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)
|
||||
{
|
||||
_bindInfo = bindInfo;
|
||||
CMixer::SetBindInfo(bindInfo);
|
||||
|
||||
_streamBinders.Clear();
|
||||
FOR_VECTOR (i, _bindInfo.BindPairs)
|
||||
FOR_VECTOR (i, _bi.Bonds)
|
||||
{
|
||||
RINOK(_streamBinders.AddNew().CreateEvents());
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CCoderMixer2MT::AddCoderCommon()
|
||||
void CMixerMT::AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter)
|
||||
{
|
||||
const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()];
|
||||
CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams);
|
||||
_coders.Add(threadCoderInfo);
|
||||
const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
|
||||
CCoderMT &c2 = _coders.AddNew();
|
||||
c2.NumStreams = c.NumStreams;
|
||||
c2.EncodeMode = EncodeMode;
|
||||
c2.Coder = coder;
|
||||
c2.Coder2 = coder2;
|
||||
IsFilter_Vector.Add(isFilter);
|
||||
}
|
||||
|
||||
void CCoderMixer2MT::AddCoder(ICompressCoder *coder)
|
||||
CCoder &CMixerMT::GetCoder(unsigned index)
|
||||
{
|
||||
AddCoderCommon();
|
||||
_coders.Back().Coder = coder;
|
||||
return _coders[index];
|
||||
}
|
||||
|
||||
void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)
|
||||
{
|
||||
AddCoderCommon();
|
||||
_coders.Back().Coder2 = coder;
|
||||
}
|
||||
|
||||
|
||||
void CCoderMixer2MT::ReInit()
|
||||
void CMixerMT::ReInit()
|
||||
{
|
||||
FOR_VECTOR (i, _streamBinders)
|
||||
_streamBinders[i].ReInit();
|
||||
}
|
||||
|
||||
|
||||
HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams)
|
||||
void CMixerMT::SelectMainCoder(bool useFirst)
|
||||
{
|
||||
unsigned ci = _bi.UnpackCoder;
|
||||
|
||||
if (!useFirst)
|
||||
for (;;)
|
||||
{
|
||||
if (_coders[ci].NumStreams != 1)
|
||||
break;
|
||||
if (!IsFilter_Vector[ci])
|
||||
break;
|
||||
|
||||
UInt32 st = _bi.Coder_to_Stream[ci];
|
||||
if (_bi.IsStream_in_PackStreams(st))
|
||||
break;
|
||||
int bond = _bi.FindBond_for_PackStream(st);
|
||||
if (bond < 0)
|
||||
throw 20150213;
|
||||
ci = _bi.Bonds[bond].UnpackIndex;
|
||||
}
|
||||
|
||||
MainCoderIndex = ci;
|
||||
}
|
||||
|
||||
HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams)
|
||||
{
|
||||
/*
|
||||
if (_coders.Size() != _bindInfo.Coders.Size())
|
||||
throw 0;
|
||||
*/
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
CCoder2 &coderInfo = _coders[i];
|
||||
const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i];
|
||||
coderInfo.InStreams.Clear();
|
||||
CCoderMT &coderInfo = _coders[i];
|
||||
const CCoderStreamsInfo &csi = _bi.Coders[i];
|
||||
|
||||
UInt32 j;
|
||||
for (j = 0; j < coderStreamsInfo.NumInStreams; j++)
|
||||
coderInfo.InStreams.Add(NULL);
|
||||
|
||||
unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams;
|
||||
unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1;
|
||||
|
||||
coderInfo.InStreams.Clear();
|
||||
for (j = 0; j < numInStreams; j++)
|
||||
coderInfo.InStreams.AddNew();
|
||||
|
||||
coderInfo.OutStreams.Clear();
|
||||
for (j = 0; j < coderStreamsInfo.NumOutStreams; j++)
|
||||
coderInfo.OutStreams.Add(NULL);
|
||||
for (j = 0; j < numOutStreams; j++)
|
||||
coderInfo.OutStreams.AddNew();
|
||||
}
|
||||
|
||||
for (i = 0; i < _bindInfo.BindPairs.Size(); i++)
|
||||
for (i = 0; i < _bi.Bonds.Size(); i++)
|
||||
{
|
||||
const CBindPair &bindPair = _bindInfo.BindPairs[i];
|
||||
const CBond &bond = _bi.Bonds[i];
|
||||
|
||||
UInt32 inCoderIndex, inCoderStreamIndex;
|
||||
UInt32 outCoderIndex, outCoderStreamIndex;
|
||||
_bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex);
|
||||
_bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex);
|
||||
|
||||
{
|
||||
UInt32 coderIndex, coderStreamIndex;
|
||||
_bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex);
|
||||
|
||||
inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex;
|
||||
outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex;
|
||||
|
||||
inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex;
|
||||
outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0;
|
||||
}
|
||||
|
||||
_streamBinders[i].CreateStreams(
|
||||
&_coders[inCoderIndex].InStreams[inCoderStreamIndex],
|
||||
@@ -139,23 +167,29 @@ HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStre
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < _bindInfo.InStreams.Size(); i++)
|
||||
{
|
||||
UInt32 inCoderIndex, inCoderStreamIndex;
|
||||
_bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex);
|
||||
_coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i];
|
||||
CCoderMT &cod = _coders[_bi.UnpackCoder];
|
||||
if (EncodeMode)
|
||||
cod.InStreams[0] = inStreams[0];
|
||||
else
|
||||
cod.OutStreams[0] = outStreams[0];
|
||||
}
|
||||
|
||||
for (i = 0; i < _bi.PackStreams.Size(); i++)
|
||||
{
|
||||
UInt32 coderIndex, coderStreamIndex;
|
||||
_bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex);
|
||||
CCoderMT &cod = _coders[coderIndex];
|
||||
if (EncodeMode)
|
||||
cod.OutStreams[coderStreamIndex] = outStreams[i];
|
||||
else
|
||||
cod.InStreams[coderStreamIndex] = inStreams[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
|
||||
{
|
||||
UInt32 outCoderIndex, outCoderStreamIndex;
|
||||
_bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex);
|
||||
_coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i];
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code)
|
||||
HRESULT CMixerMT::ReturnIfError(HRESULT code)
|
||||
{
|
||||
FOR_VECTOR (i, _coders)
|
||||
if (_coders[i].Result == code)
|
||||
@@ -163,35 +197,28 @@ HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
|
||||
const UInt64 ** /* inSizes */,
|
||||
UInt32 numInStreams,
|
||||
ISequentialOutStream **outStreams,
|
||||
const UInt64 ** /* outSizes */,
|
||||
UInt32 numOutStreams,
|
||||
ICompressProgressInfo *progress)
|
||||
HRESULT CMixerMT::Code(
|
||||
ISequentialInStream * const *inStreams,
|
||||
ISequentialOutStream * const *outStreams,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||
|
||||
numOutStreams != (UInt32)_bindInfo.OutStreams.Size())
|
||||
return E_INVALIDARG;
|
||||
|
||||
Init(inStreams, outStreams);
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
if (i != _progressCoderIndex)
|
||||
if (i != MainCoderIndex)
|
||||
{
|
||||
RINOK(_coders[i].Create());
|
||||
}
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
if (i != _progressCoderIndex)
|
||||
if (i != MainCoderIndex)
|
||||
_coders[i].Start();
|
||||
|
||||
_coders[_progressCoderIndex].Code(progress);
|
||||
_coders[MainCoderIndex].Code(progress);
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
if (i != _progressCoderIndex)
|
||||
if (i != MainCoderIndex)
|
||||
_coders[i].WaitExecuteFinish();
|
||||
|
||||
RINOK(ReturnIfError(E_ABORT));
|
||||
@@ -200,7 +227,10 @@ STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
HRESULT result = _coders[i].Result;
|
||||
if (result != S_OK && result != E_FAIL && result != S_FALSE)
|
||||
if (result != S_OK
|
||||
&& result != k_My_HRESULT_WritingWasCut
|
||||
&& result != S_FALSE
|
||||
&& result != E_FAIL)
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -209,10 +239,16 @@ STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
HRESULT result = _coders[i].Result;
|
||||
if (result != S_OK)
|
||||
if (result != S_OK && result != k_My_HRESULT_WritingWasCut)
|
||||
return result;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const
|
||||
{
|
||||
return _streamBinders[bondIndex].ProcessedSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,81 +3,75 @@
|
||||
#ifndef __CODER_MIXER2_MT_H
|
||||
#define __CODER_MIXER2_MT_H
|
||||
|
||||
#include "CoderMixer2.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../Common/StreamBinder.h"
|
||||
#include "../../Common/VirtThread.h"
|
||||
|
||||
namespace NCoderMixer {
|
||||
#include "CoderMixer2.h"
|
||||
|
||||
struct CCoder2: public CCoderInfo2, public CVirtThread
|
||||
namespace NCoderMixer2 {
|
||||
|
||||
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;
|
||||
|
||||
CCoder2(UInt32 numInStreams, UInt32 numOutStreams);
|
||||
~CCoder2() { CVirtThread::WaitThreadFinish(); }
|
||||
// void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);
|
||||
virtual void Execute();
|
||||
CCoderMT(): EncodeMode(false) {}
|
||||
~CCoderMT() { CVirtThread::WaitThreadFinish(); }
|
||||
|
||||
void Code(ICompressProgressInfo *progress);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
SetBindInfo()
|
||||
for each coder
|
||||
AddCoder[2]()
|
||||
SetProgressIndex(UInt32 coderIndex);
|
||||
|
||||
for each file
|
||||
{
|
||||
ReInit()
|
||||
for each coder
|
||||
SetCoderInfo
|
||||
Code
|
||||
}
|
||||
*/
|
||||
|
||||
class CCoderMixer2MT:
|
||||
public ICompressCoder2,
|
||||
public CCoderMixer2,
|
||||
class CMixerMT:
|
||||
public IUnknown,
|
||||
public CMixer,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CBindInfo _bindInfo;
|
||||
CObjectVector<CStreamBinder> _streamBinders;
|
||||
unsigned _progressCoderIndex;
|
||||
|
||||
void AddCoderCommon();
|
||||
HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams);
|
||||
HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams);
|
||||
HRESULT ReturnIfError(HRESULT code);
|
||||
|
||||
public:
|
||||
CObjectVector<CCoder2> _coders;
|
||||
CObjectVector<CCoderMT> _coders;
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream **inStreams,
|
||||
const UInt64 **inSizes,
|
||||
UInt32 numInStreams,
|
||||
ISequentialOutStream **outStreams,
|
||||
const UInt64 **outSizes,
|
||||
UInt32 numOutStreams,
|
||||
virtual HRESULT SetBindInfo(const CBindInfo &bindInfo);
|
||||
|
||||
virtual void AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter);
|
||||
|
||||
virtual CCoder &GetCoder(unsigned index);
|
||||
|
||||
virtual void SelectMainCoder(bool useFirst);
|
||||
|
||||
virtual void ReInit();
|
||||
|
||||
virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
|
||||
{ _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
|
||||
|
||||
virtual HRESULT Code(
|
||||
ISequentialInStream * const *inStreams,
|
||||
ISequentialOutStream * const *outStreams,
|
||||
ICompressProgressInfo *progress);
|
||||
|
||||
HRESULT SetBindInfo(const CBindInfo &bindInfo);
|
||||
void AddCoder(ICompressCoder *coder);
|
||||
void AddCoder2(ICompressCoder2 *coder);
|
||||
void SetProgressCoderIndex(unsigned coderIndex) { _progressCoderIndex = coderIndex; }
|
||||
virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
|
||||
|
||||
void ReInit();
|
||||
void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes)
|
||||
{ _coders[coderIndex].SetCoderInfo(inSizes, outSizes); }
|
||||
UInt64 GetWriteProcessedSize(UInt32 binderIndex) const
|
||||
{ return _streamBinders[binderIndex].ProcessedSize; }
|
||||
CMixerMT(bool encodeMode): CMixer(encodeMode) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,236 +4,559 @@
|
||||
|
||||
#include "CoderMixer2ST.h"
|
||||
|
||||
namespace NCoderMixer {
|
||||
|
||||
CCoderMixer2ST::CCoderMixer2ST() {}
|
||||
|
||||
CCoderMixer2ST::~CCoderMixer2ST(){ }
|
||||
|
||||
HRESULT CCoderMixer2ST::SetBindInfo(const CBindInfo &bindInfo)
|
||||
STDMETHODIMP CSequentialInStreamCalcSize::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
_bindInfo = bindInfo;
|
||||
return S_OK;
|
||||
UInt32 realProcessed = 0;
|
||||
HRESULT result = S_OK;
|
||||
if (_stream)
|
||||
result = _stream->Read(data, size, &realProcessed);
|
||||
_size += realProcessed;
|
||||
if (size != 0 && realProcessed == 0)
|
||||
_wasFinished = true;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessed;
|
||||
return result;
|
||||
}
|
||||
|
||||
void CCoderMixer2ST::AddCoderCommon(bool isMain)
|
||||
|
||||
|
||||
STDMETHODIMP COutStreamCalcSize::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
const CCoderStreamsInfo &csi = _bindInfo.Coders[_coders.Size()];
|
||||
_coders.Add(CSTCoderInfo(csi.NumInStreams, csi.NumOutStreams, isMain));
|
||||
HRESULT result = S_OK;
|
||||
if (_stream)
|
||||
result = _stream->Write(data, size, &size);
|
||||
_size += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return result;
|
||||
}
|
||||
|
||||
void CCoderMixer2ST::AddCoder(ICompressCoder *coder, bool isMain)
|
||||
STDMETHODIMP COutStreamCalcSize::Flush()
|
||||
{
|
||||
AddCoderCommon(isMain);
|
||||
_coders.Back().Coder = coder;
|
||||
HRESULT result = S_OK;
|
||||
if (_stream)
|
||||
{
|
||||
CMyComPtr<IOutStreamFlush> outStreamFlush;
|
||||
_stream.QueryInterface(IID_IOutStreamFlush, &outStreamFlush);
|
||||
if (outStreamFlush)
|
||||
result = outStreamFlush->Flush();;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void CCoderMixer2ST::AddCoder2(ICompressCoder2 *coder, bool isMain)
|
||||
{
|
||||
AddCoderCommon(isMain);
|
||||
_coders.Back().Coder2 = coder;
|
||||
}
|
||||
|
||||
void CCoderMixer2ST::ReInit() { }
|
||||
|
||||
HRESULT CCoderMixer2ST::GetInStream(
|
||||
ISequentialInStream **inStreams, const UInt64 **inSizes,
|
||||
UInt32 streamIndex, ISequentialInStream **inStreamRes)
|
||||
namespace NCoderMixer2 {
|
||||
|
||||
CMixerST::CMixerST(bool encodeMode):
|
||||
CMixer(encodeMode)
|
||||
{}
|
||||
|
||||
CMixerST::~CMixerST() {}
|
||||
|
||||
void CMixerST::AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> seqInStream;
|
||||
int i;
|
||||
for (i = 0; i < _bindInfo.InStreams.Size(); i++)
|
||||
if (_bindInfo.InStreams[i] == streamIndex)
|
||||
IsFilter_Vector.Add(isFilter);
|
||||
const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
|
||||
CCoderST &c2 = _coders.AddNew();
|
||||
c2.NumStreams = c.NumStreams;
|
||||
c2.Coder = coder;
|
||||
c2.Coder2 = coder2;
|
||||
|
||||
/*
|
||||
if (isFilter)
|
||||
{
|
||||
c2.CanRead = true;
|
||||
c2.CanWrite = true;
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
IUnknown *unk = (coder ? (IUnknown *)coder : (IUnknown *)coder2);
|
||||
{
|
||||
seqInStream = inStreams[i];
|
||||
*inStreamRes = seqInStream.Detach();
|
||||
return S_OK;
|
||||
CMyComPtr<ISequentialInStream> s;
|
||||
unk->QueryInterface(IID_ISequentialInStream, (void**)&s);
|
||||
c2.CanRead = (s != NULL);
|
||||
}
|
||||
int binderIndex = _bindInfo.FindBinderForInStream(streamIndex);
|
||||
if (binderIndex < 0)
|
||||
return E_INVALIDARG;
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> s;
|
||||
unk->QueryInterface(IID_ISequentialOutStream, (void**)&s);
|
||||
c2.CanWrite = (s != NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 coderIndex, coderStreamIndex;
|
||||
_bindInfo.FindOutStream(_bindInfo.BindPairs[binderIndex].OutIndex,
|
||||
coderIndex, coderStreamIndex);
|
||||
CCoder &CMixerST::GetCoder(unsigned index)
|
||||
{
|
||||
return _coders[index];
|
||||
}
|
||||
|
||||
CCoderInfo2 &coder = _coders[coderIndex];
|
||||
if (!coder.Coder)
|
||||
return E_NOTIMPL;
|
||||
coder.Coder.QueryInterface(IID_ISequentialInStream, &seqInStream);
|
||||
void CMixerST::ReInit() {}
|
||||
|
||||
HRESULT CMixerST::GetInStream2(
|
||||
ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
|
||||
UInt32 outStreamIndex, ISequentialInStream **inStreamRes)
|
||||
{
|
||||
UInt32 coderIndex = outStreamIndex, coderStreamIndex = 0;
|
||||
|
||||
if (EncodeMode)
|
||||
{
|
||||
_bi.GetCoder_for_Stream(outStreamIndex, coderIndex, coderStreamIndex);
|
||||
if (coderStreamIndex != 0)
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
const CCoder &coder = _coders[coderIndex];
|
||||
|
||||
CMyComPtr<ISequentialInStream> seqInStream;
|
||||
coder.QueryInterface(IID_ISequentialInStream, (void **)&seqInStream);
|
||||
if (!seqInStream)
|
||||
return E_NOTIMPL;
|
||||
|
||||
UInt32 startIndex = _bindInfo.GetCoderInStreamIndex(coderIndex);
|
||||
UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams;
|
||||
UInt32 startIndex = EncodeMode ? coderIndex : _bi.Coder_to_Stream[coderIndex];
|
||||
|
||||
CMyComPtr<ICompressSetInStream> setInStream;
|
||||
if (!coder.Coder)
|
||||
return E_NOTIMPL;
|
||||
coder.Coder.QueryInterface(IID_ICompressSetInStream, &setInStream);
|
||||
if (!setInStream)
|
||||
return E_NOTIMPL;
|
||||
|
||||
if (coder.NumInStreams > 1)
|
||||
return E_NOTIMPL;
|
||||
for (i = 0; i < (int)coder.NumInStreams; i++)
|
||||
bool isSet = false;
|
||||
|
||||
if (numInStreams == 1)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> seqInStream2;
|
||||
RINOK(GetInStream(inStreams, inSizes, startIndex + i, &seqInStream2));
|
||||
RINOK(setInStream->SetInStream(seqInStream2));
|
||||
CMyComPtr<ICompressSetInStream> setStream;
|
||||
coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream);
|
||||
if (setStream)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> seqInStream2;
|
||||
RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2));
|
||||
RINOK(setStream->SetInStream(seqInStream2));
|
||||
isSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isSet && numInStreams != 0)
|
||||
{
|
||||
CMyComPtr<ICompressSetInStream2> setStream2;
|
||||
coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2);
|
||||
if (!setStream2)
|
||||
return E_NOTIMPL;
|
||||
|
||||
for (UInt32 i = 0; i < numInStreams; i++)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> seqInStream2;
|
||||
RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + i, &seqInStream2));
|
||||
RINOK(setStream2->SetInStream2(i, seqInStream2));
|
||||
}
|
||||
}
|
||||
|
||||
*inStreamRes = seqInStream.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CCoderMixer2ST::GetOutStream(
|
||||
ISequentialOutStream **outStreams, const UInt64 **outSizes,
|
||||
UInt32 streamIndex, ISequentialOutStream **outStreamRes)
|
||||
|
||||
HRESULT CMixerST::GetInStream(
|
||||
ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
|
||||
UInt32 inStreamIndex, ISequentialInStream **inStreamRes)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> seqInStream;
|
||||
|
||||
{
|
||||
int index = -1;
|
||||
if (EncodeMode)
|
||||
{
|
||||
if (_bi.UnpackCoder == inStreamIndex)
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
index = _bi.FindStream_in_PackStreams(inStreamIndex);
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
seqInStream = inStreams[index];
|
||||
*inStreamRes = seqInStream.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
int bond = FindBond_for_Stream(
|
||||
true, // forInputStream
|
||||
inStreamIndex);
|
||||
if (bond < 0)
|
||||
return E_INVALIDARG;
|
||||
|
||||
RINOK(GetInStream2(inStreams, /* inSizes, */
|
||||
_bi.Bonds[bond].Get_OutIndex(EncodeMode), &seqInStream));
|
||||
|
||||
while (_binderStreams.Size() <= (unsigned)bond)
|
||||
_binderStreams.AddNew();
|
||||
CStBinderStream &bs = _binderStreams[bond];
|
||||
|
||||
if (bs.StreamRef || bs.InStreamSpec)
|
||||
return E_NOTIMPL;
|
||||
|
||||
CSequentialInStreamCalcSize *spec = new CSequentialInStreamCalcSize;
|
||||
bs.StreamRef = spec;
|
||||
bs.InStreamSpec = spec;
|
||||
|
||||
spec->SetStream(seqInStream);
|
||||
spec->Init();
|
||||
|
||||
seqInStream = bs.InStreamSpec;
|
||||
|
||||
*inStreamRes = seqInStream.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMixerST::GetOutStream(
|
||||
ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
|
||||
UInt32 outStreamIndex, ISequentialOutStream **outStreamRes)
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> seqOutStream;
|
||||
int i;
|
||||
for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
|
||||
if (_bindInfo.OutStreams[i] == streamIndex)
|
||||
|
||||
{
|
||||
int index = -1;
|
||||
if (!EncodeMode)
|
||||
{
|
||||
seqOutStream = outStreams[i];
|
||||
if (_bi.UnpackCoder == outStreamIndex)
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
index = _bi.FindStream_in_PackStreams(outStreamIndex);
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
seqOutStream = outStreams[index];
|
||||
*outStreamRes = seqOutStream.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
int binderIndex = _bindInfo.FindBinderForOutStream(streamIndex);
|
||||
if (binderIndex < 0)
|
||||
}
|
||||
|
||||
int bond = FindBond_for_Stream(
|
||||
false, // forInputStream
|
||||
outStreamIndex);
|
||||
if (bond < 0)
|
||||
return E_INVALIDARG;
|
||||
|
||||
UInt32 coderIndex, coderStreamIndex;
|
||||
_bindInfo.FindInStream(_bindInfo.BindPairs[binderIndex].InIndex,
|
||||
coderIndex, coderStreamIndex);
|
||||
UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
|
||||
|
||||
CCoderInfo2 &coder = _coders[coderIndex];
|
||||
UInt32 coderIndex = inStreamIndex;
|
||||
UInt32 coderStreamIndex = 0;
|
||||
|
||||
if (!EncodeMode)
|
||||
_bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
|
||||
|
||||
CCoder &coder = _coders[coderIndex];
|
||||
|
||||
/*
|
||||
if (!coder.Coder)
|
||||
return E_NOTIMPL;
|
||||
coder.Coder.QueryInterface(IID_ISequentialOutStream, &seqOutStream);
|
||||
*/
|
||||
|
||||
coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream);
|
||||
if (!seqOutStream)
|
||||
return E_NOTIMPL;
|
||||
|
||||
UInt32 startIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);
|
||||
UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
|
||||
UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
|
||||
|
||||
CMyComPtr<ICompressSetOutStream> setOutStream;
|
||||
if (!coder.Coder)
|
||||
return E_NOTIMPL;
|
||||
coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
|
||||
if (!setOutStream)
|
||||
return E_NOTIMPL;
|
||||
bool isSet = false;
|
||||
|
||||
if (coder.NumOutStreams > 1)
|
||||
return E_NOTIMPL;
|
||||
for (i = 0; i < (int)coder.NumOutStreams; i++)
|
||||
if (numOutStreams == 1)
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> seqOutStream2;
|
||||
RINOK(GetOutStream(outStreams, outSizes, startIndex + i, &seqOutStream2));
|
||||
RINOK(setOutStream->SetOutStream(seqOutStream2));
|
||||
CMyComPtr<ICompressSetOutStream> setOutStream;
|
||||
coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
|
||||
if (setOutStream)
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> seqOutStream2;
|
||||
RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2));
|
||||
RINOK(setOutStream->SetOutStream(seqOutStream2));
|
||||
isSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isSet && numOutStreams != 0)
|
||||
{
|
||||
// return E_NOTIMPL;
|
||||
// /*
|
||||
CMyComPtr<ICompressSetOutStream2> setStream2;
|
||||
coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2);
|
||||
if (!setStream2)
|
||||
return E_NOTIMPL;
|
||||
for (UInt32 i = 0; i < numOutStreams; i++)
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> seqOutStream2;
|
||||
RINOK(GetOutStream(outStreams, startIndex + i, &seqOutStream2));
|
||||
RINOK(setStream2->SetOutStream2(i, seqOutStream2));
|
||||
}
|
||||
// */
|
||||
}
|
||||
|
||||
while (_binderStreams.Size() <= (unsigned)bond)
|
||||
_binderStreams.AddNew();
|
||||
CStBinderStream &bs = _binderStreams[bond];
|
||||
|
||||
if (bs.StreamRef || bs.OutStreamSpec)
|
||||
return E_NOTIMPL;
|
||||
|
||||
COutStreamCalcSize *spec = new COutStreamCalcSize;
|
||||
bs.StreamRef = (ISequentialOutStream *)spec;
|
||||
bs.OutStreamSpec = spec;
|
||||
|
||||
spec->SetStream(seqOutStream);
|
||||
spec->Init();
|
||||
|
||||
seqOutStream = bs.OutStreamSpec;
|
||||
|
||||
*outStreamRes = seqOutStream.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CCoderMixer2ST::Code(ISequentialInStream **inStreams,
|
||||
const UInt64 **inSizes,
|
||||
UInt32 numInStreams,
|
||||
ISequentialOutStream **outStreams,
|
||||
const UInt64 **outSizes,
|
||||
UInt32 numOutStreams,
|
||||
ICompressProgressInfo *progress)
|
||||
|
||||
static HRESULT GetError(HRESULT res, HRESULT res2)
|
||||
{
|
||||
if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||
|
||||
numOutStreams != (UInt32)_bindInfo.OutStreams.Size())
|
||||
if (res == res2)
|
||||
return res;
|
||||
if (res == S_OK)
|
||||
return res2;
|
||||
if (res == k_My_HRESULT_WritingWasCut)
|
||||
{
|
||||
if (res2 != S_OK)
|
||||
return res2;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMixerST::FlushStream(UInt32 streamIndex)
|
||||
{
|
||||
{
|
||||
int index = -1;
|
||||
if (!EncodeMode)
|
||||
{
|
||||
if (_bi.UnpackCoder == streamIndex)
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
index = _bi.FindStream_in_PackStreams(streamIndex);
|
||||
|
||||
if (index >= 0)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
int bond = FindBond_for_Stream(
|
||||
false, // forInputStream
|
||||
streamIndex);
|
||||
if (bond < 0)
|
||||
return E_INVALIDARG;
|
||||
|
||||
// Find main coder
|
||||
int _mainCoderIndex = -1;
|
||||
int i;
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
if (_coders[i].IsMain)
|
||||
{
|
||||
_mainCoderIndex = i;
|
||||
break;
|
||||
}
|
||||
if (_mainCoderIndex < 0)
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
if (_coders[i].NumInStreams > 1)
|
||||
{
|
||||
if (_mainCoderIndex >= 0)
|
||||
return E_NOTIMPL;
|
||||
_mainCoderIndex = i;
|
||||
}
|
||||
if (_mainCoderIndex < 0)
|
||||
_mainCoderIndex = 0;
|
||||
UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
|
||||
|
||||
UInt32 coderIndex = inStreamIndex;
|
||||
UInt32 coderStreamIndex = 0;
|
||||
if (!EncodeMode)
|
||||
_bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
|
||||
|
||||
CCoder &coder = _coders[coderIndex];
|
||||
CMyComPtr<IOutStreamFlush> flush;
|
||||
coder.QueryInterface(IID_IOutStreamFlush, (void **)&flush);
|
||||
HRESULT res = S_OK;
|
||||
if (flush)
|
||||
{
|
||||
res = flush->Flush();
|
||||
}
|
||||
return GetError(res, FlushCoder(coderIndex));
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMixerST::FlushCoder(UInt32 coderIndex)
|
||||
{
|
||||
CCoder &coder = _coders[coderIndex];
|
||||
|
||||
UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
|
||||
UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
|
||||
|
||||
HRESULT res = S_OK;
|
||||
for (unsigned i = 0; i < numOutStreams; i++)
|
||||
res = GetError(res, FlushStream(startIndex + i));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void CMixerST::SelectMainCoder(bool useFirst)
|
||||
{
|
||||
unsigned ci = _bi.UnpackCoder;
|
||||
|
||||
int firstNonFilter = -1;
|
||||
int firstAllowed = ci;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const CCoderST &coder = _coders[ci];
|
||||
// break;
|
||||
|
||||
if (ci != _bi.UnpackCoder)
|
||||
if (EncodeMode ? !coder.CanWrite : !coder.CanRead)
|
||||
{
|
||||
firstAllowed = ci;
|
||||
firstNonFilter = -2;
|
||||
}
|
||||
|
||||
if (coder.NumStreams != 1)
|
||||
break;
|
||||
|
||||
UInt32 st = _bi.Coder_to_Stream[ci];
|
||||
if (_bi.IsStream_in_PackStreams(st))
|
||||
break;
|
||||
int bond = _bi.FindBond_for_PackStream(st);
|
||||
if (bond < 0)
|
||||
throw 20150213;
|
||||
|
||||
if (EncodeMode ? !coder.CanRead : !coder.CanWrite)
|
||||
break;
|
||||
|
||||
if (firstNonFilter == -1 && !IsFilter_Vector[ci])
|
||||
firstNonFilter = ci;
|
||||
|
||||
ci = _bi.Bonds[bond].UnpackIndex;
|
||||
}
|
||||
|
||||
ci = firstNonFilter;
|
||||
if (firstNonFilter < 0 || useFirst)
|
||||
ci = firstAllowed;
|
||||
MainCoderIndex = ci;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMixerST::Code(
|
||||
ISequentialInStream * const *inStreams,
|
||||
ISequentialOutStream * const *outStreams,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
_binderStreams.Clear();
|
||||
unsigned ci = MainCoderIndex;
|
||||
|
||||
// _mainCoderIndex = 0;
|
||||
// _mainCoderIndex = _coders.Size() - 1;
|
||||
CCoderInfo2 &mainCoder = _coders[_mainCoderIndex];
|
||||
const CCoder &mainCoder = _coders[MainCoderIndex];
|
||||
|
||||
CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;
|
||||
CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;
|
||||
UInt32 startInIndex = _bindInfo.GetCoderInStreamIndex(_mainCoderIndex);
|
||||
UInt32 startOutIndex = _bindInfo.GetCoderOutStreamIndex(_mainCoderIndex);
|
||||
for (i = 0; i < (int)mainCoder.NumInStreams; i++)
|
||||
|
||||
UInt32 numInStreams = EncodeMode ? 1 : mainCoder.NumStreams;
|
||||
UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams;
|
||||
|
||||
UInt32 startInIndex = EncodeMode ? ci : _bi.Coder_to_Stream[ci];
|
||||
UInt32 startOutIndex = !EncodeMode ? ci : _bi.Coder_to_Stream[ci];
|
||||
|
||||
UInt32 i;
|
||||
|
||||
for (i = 0; i < numInStreams; i++)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> seqInStream;
|
||||
RINOK(GetInStream(inStreams, inSizes, startInIndex + i, &seqInStream));
|
||||
RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream));
|
||||
seqInStreams.Add(seqInStream);
|
||||
}
|
||||
for (i = 0; i < (int)mainCoder.NumOutStreams; i++)
|
||||
|
||||
for (i = 0; i < numOutStreams; i++)
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> seqOutStream;
|
||||
RINOK(GetOutStream(outStreams, outSizes, startOutIndex + i, &seqOutStream));
|
||||
RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream));
|
||||
seqOutStreams.Add(seqOutStream);
|
||||
}
|
||||
|
||||
CRecordVector< ISequentialInStream * > seqInStreamsSpec;
|
||||
CRecordVector< ISequentialOutStream * > seqOutStreamsSpec;
|
||||
for (i = 0; i < (int)mainCoder.NumInStreams; i++)
|
||||
|
||||
for (i = 0; i < numInStreams; i++)
|
||||
seqInStreamsSpec.Add(seqInStreams[i]);
|
||||
for (i = 0; i < (int)mainCoder.NumOutStreams; i++)
|
||||
for (i = 0; i < numOutStreams; i++)
|
||||
seqOutStreamsSpec.Add(seqOutStreams[i]);
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
if (i == _mainCoderIndex)
|
||||
if (i == ci)
|
||||
continue;
|
||||
CCoderInfo2 &coder = _coders[i];
|
||||
|
||||
CCoder &coder = _coders[i];
|
||||
|
||||
CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
|
||||
coder.Coder.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);
|
||||
coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
|
||||
if (setOutStreamSize)
|
||||
{
|
||||
RINOK(setOutStreamSize->SetOutStreamSize(coder.OutSizePointers[0]));
|
||||
RINOK(setOutStreamSize->SetOutStreamSize(
|
||||
EncodeMode ? coder.PackSizePointers[0] : coder.UnpackSizePointer));
|
||||
}
|
||||
}
|
||||
|
||||
const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : &mainCoder.PackSizePointers.Front();
|
||||
const UInt64 * const *outSizes2 = EncodeMode ? &mainCoder.PackSizePointers.Front() : &mainCoder.UnpackSizePointer;
|
||||
|
||||
HRESULT res;
|
||||
if (mainCoder.Coder)
|
||||
{
|
||||
RINOK(mainCoder.Coder->Code(
|
||||
res = mainCoder.Coder->Code(
|
||||
seqInStreamsSpec[0], seqOutStreamsSpec[0],
|
||||
mainCoder.InSizePointers[0], mainCoder.OutSizePointers[0],
|
||||
progress));
|
||||
isSizes2[0], outSizes2[0],
|
||||
progress);
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(mainCoder.Coder2->Code(
|
||||
&seqInStreamsSpec.Front(),
|
||||
&mainCoder.InSizePointers.Front(), mainCoder.NumInStreams,
|
||||
&seqOutStreamsSpec.Front(),
|
||||
&mainCoder.OutSizePointers.Front(), mainCoder.NumOutStreams,
|
||||
progress));
|
||||
res = mainCoder.Coder2->Code(
|
||||
&seqInStreamsSpec.Front(), isSizes2, numInStreams,
|
||||
&seqOutStreamsSpec.Front(), outSizes2, numOutStreams,
|
||||
progress);
|
||||
}
|
||||
CMyComPtr<IOutStreamFlush> flush;
|
||||
seqOutStreams.Front().QueryInterface(IID_IOutStreamFlush, &flush);
|
||||
if (flush)
|
||||
return flush->Flush();
|
||||
|
||||
if (res == k_My_HRESULT_WritingWasCut)
|
||||
res = S_OK;
|
||||
|
||||
if (res == S_OK || res == S_FALSE)
|
||||
{
|
||||
res = GetError(res, FlushCoder(ci));
|
||||
}
|
||||
|
||||
for (i = 0; i < _binderStreams.Size(); i++)
|
||||
{
|
||||
const CStBinderStream &bs = _binderStreams[i];
|
||||
if (bs.InStreamSpec)
|
||||
bs.InStreamSpec->ReleaseStream();
|
||||
else
|
||||
bs.OutStreamSpec->ReleaseStream();
|
||||
}
|
||||
|
||||
if (res == k_My_HRESULT_WritingWasCut)
|
||||
res = S_OK;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMixerST::GetMainUnpackStream(
|
||||
ISequentialInStream * const *inStreams,
|
||||
ISequentialInStream **inStreamRes)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> seqInStream;
|
||||
|
||||
RINOK(GetInStream2(inStreams, /* inSizes, */
|
||||
_bi.UnpackCoder, &seqInStream))
|
||||
|
||||
FOR_VECTOR (i, _coders)
|
||||
{
|
||||
CCoder &coder = _coders[i];
|
||||
CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
|
||||
coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
|
||||
if (setOutStreamSize)
|
||||
{
|
||||
RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer));
|
||||
}
|
||||
}
|
||||
|
||||
*inStreamRes = seqInStream.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
UInt64 CCoderMixer2ST::GetWriteProcessedSize(UInt32 binderIndex) const
|
||||
|
||||
UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const
|
||||
{
|
||||
return _streamBinders[binderIndex].ProcessedSize;
|
||||
const CStBinderStream &bs = _binderStreams[bondIndex];
|
||||
if (bs.InStreamSpec)
|
||||
return bs.InStreamSpec->GetSize();
|
||||
return bs.OutStreamSpec->GetSize();
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
@@ -3,84 +3,125 @@
|
||||
#ifndef __CODER_MIXER2_ST_H
|
||||
#define __CODER_MIXER2_ST_H
|
||||
|
||||
#include "CoderMixer2.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../ICoder.h"
|
||||
|
||||
namespace NCoderMixer {
|
||||
#include "CoderMixer2.h"
|
||||
|
||||
// SetBindInfo()
|
||||
// for each coder
|
||||
// {
|
||||
// AddCoder[2]()
|
||||
// }
|
||||
//
|
||||
// for each file
|
||||
// {
|
||||
// ReInit()
|
||||
// for each coder
|
||||
// {
|
||||
// SetCoderInfo
|
||||
// }
|
||||
// SetProgressIndex(UInt32 coderIndex);
|
||||
// Code
|
||||
// }
|
||||
|
||||
struct CSTCoderInfo: public CCoderInfo2
|
||||
{
|
||||
bool IsMain;
|
||||
CSTCoderInfo(UInt32 numInStreams, UInt32 numOutStreams, bool isMain):
|
||||
CCoderInfo2(numInStreams, numOutStreams), IsMain(isMain) {}
|
||||
};
|
||||
|
||||
class CCoderMixer2ST:
|
||||
public ICompressCoder2,
|
||||
public CCoderMixer2,
|
||||
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 IOutStreamFlush,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
UInt64 _size;
|
||||
public:
|
||||
MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFlush)
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Flush)();
|
||||
|
||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
void Init() { _size = 0; }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
namespace NCoderMixer2 {
|
||||
|
||||
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
|
||||
{
|
||||
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 FlushStream(UInt32 streamIndex);
|
||||
HRESULT FlushCoder(UInt32 coderIndex);
|
||||
|
||||
public:
|
||||
CObjectVector<CCoderST> _coders;
|
||||
|
||||
CObjectVector<CStBinderStream> _binderStreams;
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
HRESULT GetInStream(
|
||||
ISequentialInStream **inStreams, const UInt64 **inSizes,
|
||||
UInt32 streamIndex, ISequentialInStream **inStreamRes);
|
||||
HRESULT GetOutStream(
|
||||
ISequentialOutStream **outStreams, const UInt64 **outSizes,
|
||||
UInt32 streamIndex, ISequentialOutStream **outStreamRes);
|
||||
public:
|
||||
STDMETHOD(Code)(ISequentialInStream **inStreams,
|
||||
const UInt64 **inSizes,
|
||||
UInt32 numInStreams,
|
||||
ISequentialOutStream **outStreams,
|
||||
const UInt64 **outSizes,
|
||||
UInt32 numOutStreams,
|
||||
CMixerST(bool encodeMode);
|
||||
~CMixerST();
|
||||
|
||||
virtual void AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter);
|
||||
|
||||
virtual CCoder &GetCoder(unsigned index);
|
||||
|
||||
virtual void SelectMainCoder(bool useFirst);
|
||||
|
||||
virtual void ReInit();
|
||||
|
||||
virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
|
||||
{ _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
|
||||
|
||||
virtual HRESULT Code(
|
||||
ISequentialInStream * const *inStreams,
|
||||
ISequentialOutStream * const *outStreams,
|
||||
ICompressProgressInfo *progress);
|
||||
|
||||
CCoderMixer2ST();
|
||||
~CCoderMixer2ST();
|
||||
void AddCoderCommon(bool isMain);
|
||||
void AddCoder(ICompressCoder *coder, bool isMain);
|
||||
void AddCoder2(ICompressCoder2 *coder, bool isMain);
|
||||
|
||||
void ReInit();
|
||||
void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes)
|
||||
{
|
||||
{ _coders[coderIndex].SetCoderInfo(inSizes, outSizes); }
|
||||
}
|
||||
|
||||
void SetProgressCoderIndex(UInt32 /*coderIndex*/)
|
||||
{
|
||||
// _progressCoderIndex = coderIndex;
|
||||
}
|
||||
|
||||
// UInt64 GetWriteProcessedSize(UInt32 binderIndex) const;
|
||||
|
||||
private:
|
||||
CBindInfo _bindInfo;
|
||||
CObjectVector<CSTCoderInfo> _coders;
|
||||
int _mainCoderIndex;
|
||||
public:
|
||||
HRESULT SetBindInfo(const CBindInfo &bindInfo);
|
||||
virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
|
||||
|
||||
HRESULT GetMainUnpackStream(
|
||||
ISequentialInStream * const *inStreams,
|
||||
ISequentialInStream **inStreamRes);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ struct CCoder: public CCoderInfo, public CVirtThread
|
||||
|
||||
virtual void Execute();
|
||||
void Code(ICompressProgressInfo *progress);
|
||||
~CCoder() { CVirtThread::WaitThreadFinish(); }
|
||||
virtual ~CCoder() { CVirtThread::WaitThreadFinish(); }
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -29,6 +29,7 @@ void CMultiMethodProps::SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo
|
||||
UInt32 level = _level;
|
||||
if (level != (UInt32)(Int32)-1)
|
||||
SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level);
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
|
||||
#endif
|
||||
@@ -41,6 +42,8 @@ void CMultiMethodProps::Init()
|
||||
#endif
|
||||
|
||||
_level = (UInt32)(Int32)-1;
|
||||
_analysisLevel = -1;
|
||||
|
||||
_autoFilter = true;
|
||||
_crcSize = 4;
|
||||
_filterMethod.Clear();
|
||||
@@ -60,8 +63,17 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
|
||||
_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 == L"crc")
|
||||
if (name.IsEqualTo("crc"))
|
||||
{
|
||||
name.Delete(0, 3);
|
||||
_crcSize = 4;
|
||||
@@ -73,11 +85,12 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
|
||||
UString realName = name.Ptr(index);
|
||||
if (index == 0)
|
||||
{
|
||||
if (name.IsPrefixedBy(L"mt"))
|
||||
if (name.IsPrefixedBy_Ascii_NoCase("mt"))
|
||||
{
|
||||
#ifndef _7ZIP_ST
|
||||
RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads));
|
||||
#endif
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
if (name.IsEqualTo("f"))
|
||||
@@ -87,7 +100,7 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
|
||||
return res;
|
||||
if (value.vt != VT_BSTR)
|
||||
return E_INVALIDARG;
|
||||
return _filterMethod.ParseMethodFromPROPVARIANT(L"", value);
|
||||
return _filterMethod.ParseMethodFromPROPVARIANT(UString(), value);
|
||||
}
|
||||
number = 0;
|
||||
}
|
||||
@@ -101,14 +114,15 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
|
||||
void CSingleMethodProps::Init()
|
||||
{
|
||||
Clear();
|
||||
_level = (UInt32)(Int32)-1;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
_numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors();
|
||||
AddNumThreadsProp(_numThreads);
|
||||
AddProp_NumThreads(_numThreads);
|
||||
#endif
|
||||
_level = (UInt32)(Int32)-1;
|
||||
}
|
||||
|
||||
HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
|
||||
HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
Init();
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
@@ -123,13 +137,13 @@ HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIA
|
||||
UInt32 a = 9;
|
||||
RINOK(ParsePropToUInt32(name.Ptr(1), value, a));
|
||||
_level = a;
|
||||
AddLevelProp(a);
|
||||
AddProp_Level(a);
|
||||
}
|
||||
else if (name.IsPrefixedBy(L"mt"))
|
||||
else if (name.IsPrefixedBy_Ascii_NoCase("mt"))
|
||||
{
|
||||
#ifndef _7ZIP_ST
|
||||
RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads));
|
||||
AddNumThreadsProp(_numThreads);
|
||||
AddProp_NumThreads(_numThreads);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace NArchive {
|
||||
class CMultiMethodProps
|
||||
{
|
||||
UInt32 _level;
|
||||
int _analysisLevel;
|
||||
public:
|
||||
#ifndef _7ZIP_ST
|
||||
UInt32 _numThreads;
|
||||
@@ -37,6 +38,7 @@ public:
|
||||
}
|
||||
|
||||
int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }
|
||||
int GetAnalysisLevel() const { return _analysisLevel; }
|
||||
|
||||
void Init();
|
||||
|
||||
@@ -57,7 +59,7 @@ public:
|
||||
void Init();
|
||||
CSingleMethodProps() { Init(); }
|
||||
int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }
|
||||
HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
|
||||
HRESULT SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@ STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *pr
|
||||
if (_stream)
|
||||
result = _stream->Write(data, size, &size);
|
||||
if (_calculate)
|
||||
_sha.Update((const Byte *)data, size);
|
||||
Sha1_Update(&_sha, (const Byte *)data, size);
|
||||
_size += size;
|
||||
if (processedSize != NULL)
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#ifndef __OUT_STREAM_WITH_SHA1_H
|
||||
#define __OUT_STREAM_WITH_SHA1_H
|
||||
|
||||
#include "../../Crypto/Sha1.h"
|
||||
#include "../../../../C/Sha1.h"
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
@@ -15,7 +15,7 @@ class COutStreamWithSha1:
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
UInt64 _size;
|
||||
NCrypto::NSha1::CContext _sha;
|
||||
CSha1 _sha;
|
||||
bool _calculate;
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
@@ -26,11 +26,11 @@ public:
|
||||
{
|
||||
_size = 0;
|
||||
_calculate = calculate;
|
||||
_sha.Init();
|
||||
Sha1_Init(&_sha);
|
||||
}
|
||||
void InitSha1() { _sha.Init(); }
|
||||
void InitSha1() { Sha1_Init(&_sha); }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
void Final(Byte *digest) { _sha.Final(digest); }
|
||||
void Final(Byte *digest) { Sha1_Final(&_sha, digest); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -87,7 +87,7 @@ enum EType
|
||||
k_Type_HexCrc
|
||||
};
|
||||
|
||||
static const char *k_Types[] =
|
||||
static const char * const k_Types[] =
|
||||
{
|
||||
"Binary LE"
|
||||
, "Binary BE"
|
||||
@@ -396,11 +396,10 @@ HRESULT CInArchive::GetNextItem(CItem &item, EErrorType &errorType)
|
||||
return S_FALSE;
|
||||
if (nameSize == 0 || nameSize >= kNameSizeMax)
|
||||
return S_OK;
|
||||
char *s = item.Name.GetBuffer(nameSize);
|
||||
char *s = item.Name.GetBuf(nameSize);
|
||||
size_t processedSize = nameSize;
|
||||
RINOK(Read(s, &processedSize));
|
||||
s[nameSize] = 0;
|
||||
item.Name.ReleaseBuffer();
|
||||
item.Name.ReleaseBuf_CalcLen(nameSize);
|
||||
if (processedSize != nameSize)
|
||||
{
|
||||
errorType = k_ErrorType_UnexpectedEnd;
|
||||
@@ -451,7 +450,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidSubType: prop = k_Types[_Type]; break;
|
||||
case kpidSubType: prop = k_Types[(unsigned)_Type]; break;
|
||||
case kpidPhySize: prop = _phySize; break;
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
@@ -780,20 +779,16 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Cpio", "cpio", 0, 0xED,
|
||||
3 + 5 + 2 + 2,
|
||||
{
|
||||
static const Byte k_Signature[] = {
|
||||
5, '0', '7', '0', '7', '0',
|
||||
2, kMagicBin0, kMagicBin1,
|
||||
2, kMagicBin1, kMagicBin0,
|
||||
},
|
||||
2, kMagicBin1, kMagicBin0 };
|
||||
|
||||
REGISTER_ARC_I(
|
||||
"Cpio", "cpio", 0, 0xED,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kMultiSignature,
|
||||
CreateArc, NULL, IsArc_Cpio };
|
||||
|
||||
REGISTER_ARC(Cpio)
|
||||
IsArc_Cpio)
|
||||
|
||||
}}
|
||||
|
||||
@@ -26,8 +26,7 @@ namespace NCramfs {
|
||||
|
||||
#define SIGNATURE { 'C','o','m','p','r','e','s','s','e','d',' ','R','O','M','F','S' }
|
||||
|
||||
static const UInt32 kSignatureSize = 16;
|
||||
static const char kSignature[kSignatureSize] = SIGNATURE;
|
||||
static const Byte kSignature[] = SIGNATURE;
|
||||
|
||||
static const UInt32 kArcSizeMax = (256 + 16) << 20;
|
||||
static const UInt32 kNumFilesMax = (1 << 19);
|
||||
@@ -55,7 +54,7 @@ static const unsigned k_Flags_Method_Mask = 3;
|
||||
#define k_Flags_Method_ZLIB 1
|
||||
#define k_Flags_Method_LZMA 2
|
||||
|
||||
static const char *k_Methods[] =
|
||||
static const char * const k_Methods[] =
|
||||
{
|
||||
"Copy"
|
||||
, "ZLIB"
|
||||
@@ -145,7 +144,7 @@ struct CHeader
|
||||
|
||||
bool Parse(const Byte *p)
|
||||
{
|
||||
if (memcmp(p + 16, kSignature, kSignatureSize) != 0)
|
||||
if (memcmp(p + 16, kSignature, ARRAY_SIZE(kSignature)) != 0)
|
||||
return false;
|
||||
switch(GetUi32(p))
|
||||
{
|
||||
@@ -408,7 +407,7 @@ AString CHandler::GetPath(int index) const
|
||||
len--;
|
||||
|
||||
AString path;
|
||||
char *dest = path.GetBuffer(len) + len;
|
||||
char *dest = path.GetBuf_SetEnd(len) + len;
|
||||
index = indexMem;
|
||||
for (;;)
|
||||
{
|
||||
@@ -425,7 +424,6 @@ AString CHandler::GetPath(int index) const
|
||||
break;
|
||||
*(--dest) = CHAR_PATH_SEPARATOR;
|
||||
}
|
||||
path.ReleaseBuffer(len);
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -565,10 +563,6 @@ HRESULT CCramfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSi
|
||||
return Handler->ReadBlock(blockIndex, dest, blockSize);
|
||||
}
|
||||
|
||||
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
|
||||
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
|
||||
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
|
||||
HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
|
||||
{
|
||||
if (_method == k_Flags_Method_ZLIB)
|
||||
@@ -789,15 +783,11 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "CramFS", "cramfs", 0, 0xD3,
|
||||
kSignatureSize, SIGNATURE,
|
||||
REGISTER_ARC_I(
|
||||
"CramFS", "cramfs", 0, 0xD3,
|
||||
kSignature,
|
||||
16,
|
||||
0,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Cramfs)
|
||||
NULL)
|
||||
|
||||
}}
|
||||
|
||||
@@ -13,10 +13,13 @@
|
||||
#include "../../Windows/NtCheck.h"
|
||||
#include "../../Windows/PropVariant.h"
|
||||
|
||||
#include "IArchive.h"
|
||||
#include "../ICoder.h"
|
||||
#include "../IPassword.h"
|
||||
|
||||
#include "../Common/CreateCoder.h"
|
||||
|
||||
#include "IArchive.h"
|
||||
|
||||
HINSTANCE g_hInstance;
|
||||
|
||||
#define NT_CHECK_FAIL_ACTION return FALSE;
|
||||
@@ -33,7 +36,10 @@ BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
}
|
||||
|
||||
DEFINE_GUID(CLSID_CArchiveHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
|
||||
k_7zip_GUID_Data1,
|
||||
k_7zip_GUID_Data2,
|
||||
k_7zip_GUID_Data3_Common,
|
||||
0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
|
||||
|
||||
STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject);
|
||||
|
||||
@@ -49,3 +55,40 @@ STDAPI SetLargePageMode()
|
||||
#endif
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
extern bool g_CaseSensitive;
|
||||
|
||||
STDAPI SetCaseSensitive(Int32 caseSensitive)
|
||||
{
|
||||
g_CaseSensitive = (caseSensitive != 0);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
|
||||
CExternalCodecs g_ExternalCodecs;
|
||||
|
||||
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 *)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#include "../ICoder.h"
|
||||
#include "../IPassword.h"
|
||||
|
||||
#include "../Common/CreateCoder.h"
|
||||
|
||||
#include "IArchive.h"
|
||||
|
||||
HINSTANCE g_hInstance;
|
||||
@@ -33,23 +35,28 @@ BOOL WINAPI DllMain(
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
DEFINE_GUID(CLSID_CArchiveHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
|
||||
|
||||
static const UInt16 kDecodeId = 0x2790;
|
||||
|
||||
DEFINE_GUID(CLSID_CCodec,
|
||||
0x23170F69, 0x40C1, kDecodeId, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
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 *classID, const GUID *iid, void **outObject);
|
||||
STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject);
|
||||
|
||||
STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
|
||||
{
|
||||
@@ -80,3 +87,32 @@ STDAPI SetCaseSensitive(Int32 caseSensitive)
|
||||
g_CaseSensitive = (caseSensitive != 0);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
|
||||
CExternalCodecs g_ExternalCodecs;
|
||||
|
||||
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 *)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -48,6 +48,7 @@ static Byte *Base64ToBin(Byte *dest, const char *src)
|
||||
{
|
||||
UInt32 val = 1;
|
||||
UInt32 c = k_Base64Table[(Byte)(*src++)];
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/*
|
||||
@@ -88,12 +89,14 @@ static Byte *Base64ToBin(Byte *dest, const char *src)
|
||||
break;
|
||||
c = k_Base64Table[(Byte)(*src++)];
|
||||
}
|
||||
|
||||
if (val >= ((UInt32)1 << 12))
|
||||
{
|
||||
if (val >= ((UInt32)1 << 18))
|
||||
*dest++ = (Byte)(val >> 16);
|
||||
*dest++ = (Byte)(val);
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
@@ -195,7 +198,8 @@ public:
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
|
||||
};
|
||||
|
||||
const UInt32 kXmlSizeMax = ((UInt32)1 << 31) - (1 << 14);
|
||||
// that limit can be increased, if there are such dmg files
|
||||
static const size_t kXmlSizeMax = 0xFFFF0000; // 4 GB - 64 KB;
|
||||
|
||||
struct CMethods
|
||||
{
|
||||
@@ -216,7 +220,9 @@ void CMethods::Update(const CFile &file)
|
||||
void CMethods::GetString(AString &res) const
|
||||
{
|
||||
res.Empty();
|
||||
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < Types.Size(); i++)
|
||||
{
|
||||
UInt32 type = Types[i];
|
||||
@@ -234,10 +240,10 @@ void CMethods::GetString(AString &res) const
|
||||
case METHOD_BZIP2: s = "BZip2"; break;
|
||||
default: ConvertUInt32ToString(type, buf); s = buf;
|
||||
}
|
||||
if (!res.IsEmpty())
|
||||
res += ' ';
|
||||
res.Add_Space_if_NotEmpty();
|
||||
res += s;
|
||||
}
|
||||
|
||||
for (i = 0; i < ChecksumTypes.Size(); i++)
|
||||
{
|
||||
UInt32 type = ChecksumTypes[i];
|
||||
@@ -250,8 +256,7 @@ void CMethods::GetString(AString &res) const
|
||||
ConvertUInt32ToString(type, MyStpCpy(buf, "Check"));
|
||||
s = buf;
|
||||
}
|
||||
if (!res.IsEmpty())
|
||||
res += ' ';
|
||||
res.Add_Space_if_NotEmpty();
|
||||
res += s;
|
||||
}
|
||||
}
|
||||
@@ -325,8 +330,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
case kpidMainSubfile:
|
||||
{
|
||||
int mainIndex = -1;
|
||||
int numFS = 0;
|
||||
int numUnknown = 0;
|
||||
unsigned numFS = 0;
|
||||
unsigned numUnknown = 0;
|
||||
FOR_VECTOR (i, _files)
|
||||
{
|
||||
const AString &name = _files[i].Name;
|
||||
@@ -334,7 +339,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
for (n = 0; n < kNumAppleNames; n++)
|
||||
{
|
||||
const CAppleName &appleName = k_Names[n];
|
||||
if (name.Find(appleName.AppleName) >= 0)
|
||||
// if (name.Find(appleName.AppleName) >= 0)
|
||||
if (strstr(name, appleName.AppleName))
|
||||
{
|
||||
if (appleName.IsFs)
|
||||
{
|
||||
@@ -404,6 +410,7 @@ HRESULT CFile::Parse(const Byte *p, UInt32 size)
|
||||
|
||||
p += kHeadSize;
|
||||
UInt32 i;
|
||||
|
||||
for (i = 0; i < numBlocks; i++, p += kRecordSize)
|
||||
{
|
||||
CBlock b;
|
||||
@@ -426,6 +433,7 @@ HRESULT CFile::Parse(const Byte *p, UInt32 size)
|
||||
if (b.Type == METHOD_END)
|
||||
break;
|
||||
PackSize += b.PackSize;
|
||||
|
||||
if (b.UnpSize != 0)
|
||||
{
|
||||
if (b.Type == METHOD_ZERO_2)
|
||||
@@ -433,12 +441,14 @@ HRESULT CFile::Parse(const Byte *p, UInt32 size)
|
||||
Blocks.AddInReserved(b);
|
||||
}
|
||||
}
|
||||
|
||||
if (i != numBlocks - 1)
|
||||
return S_FALSE;
|
||||
if (!Blocks.IsEmpty())
|
||||
Size = Blocks.Back().GetNextUnpPos();
|
||||
if (Size != (numSectors << 9))
|
||||
return S_FALSE;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -463,8 +473,12 @@ static const AString *GetStringFromKeyPair(const CXmlItem &item, const AString &
|
||||
|
||||
static const unsigned HEADER_SIZE = 0x200;
|
||||
|
||||
static bool IsKoly(const Byte *p)
|
||||
static const Byte k_Signature[] = { 'k','o','l','y', 0, 0, 0, 4, 0, 0, 2, 0 };
|
||||
|
||||
static inline bool IsKoly(const Byte *p)
|
||||
{
|
||||
return memcmp(p, k_Signature, ARRAY_SIZE(k_Signature)) == 0;
|
||||
/*
|
||||
if (Get32(p) != 0x6B6F6C79) // "koly" signature
|
||||
return false;
|
||||
if (Get32(p + 4) != 4) // version
|
||||
@@ -472,6 +486,7 @@ static bool IsKoly(const Byte *p)
|
||||
if (Get32(p + 8) != HEADER_SIZE)
|
||||
return false;
|
||||
return true;
|
||||
*/
|
||||
}
|
||||
|
||||
HRESULT CHandler::Open2(IInStream *stream)
|
||||
@@ -510,6 +525,14 @@ HRESULT CHandler::Open2(IInStream *stream)
|
||||
UInt64 xmlOffset = Get64(buf + 0xD8);
|
||||
UInt64 xmlLen = Get64(buf + 0xE0);
|
||||
|
||||
if ( headerPos < dataForkOffset
|
||||
|| headerPos - dataForkOffset < dataForkLen
|
||||
|| headerPos < rsrcOffset
|
||||
|| headerPos - rsrcOffset < rsrcLen
|
||||
|| headerPos < xmlOffset
|
||||
|| headerPos - xmlOffset < xmlLen)
|
||||
return S_FALSE;
|
||||
|
||||
UInt64 totalLen = dataForkLen + rsrcLen + xmlLen;
|
||||
if (totalLen > headerPos)
|
||||
return S_FALSE;
|
||||
@@ -517,14 +540,6 @@ HRESULT CHandler::Open2(IInStream *stream)
|
||||
_phySize = totalLen + HEADER_SIZE;
|
||||
headerPos = totalLen;
|
||||
|
||||
if (headerPos < dataForkOffset ||
|
||||
headerPos < dataForkOffset + dataForkLen ||
|
||||
headerPos < rsrcOffset ||
|
||||
headerPos < rsrcOffset + rsrcLen ||
|
||||
headerPos < xmlOffset ||
|
||||
headerPos < xmlOffset + xmlLen)
|
||||
return S_FALSE;
|
||||
|
||||
// Byte reserved[0x78]
|
||||
|
||||
CChecksum masterChecksum;
|
||||
@@ -620,9 +635,7 @@ HRESULT CHandler::Open2(IInStream *stream)
|
||||
ConvertUInt32ToString(_files.Size(), extraName);
|
||||
extra.Name = extraName;
|
||||
}
|
||||
CByteBuffer &rawBuf = extra.Data;
|
||||
rawBuf.SetCapacity(blockSize);
|
||||
memcpy(rawBuf, pBlock + 4, blockSize);
|
||||
extra.Data.CopyFrom(pBlock + 4, blockSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -638,10 +651,10 @@ HRESULT CHandler::Open2(IInStream *stream)
|
||||
return S_FALSE;
|
||||
for (UInt32 r = 1; r <= nameLen; r++)
|
||||
{
|
||||
char c = namePtr[r];
|
||||
Byte c = namePtr[r];
|
||||
if (c < 0x20 || c >= 0x80)
|
||||
break;
|
||||
file.Name += c;
|
||||
file.Name += (char)c;
|
||||
}
|
||||
}
|
||||
RINOK(file.Parse(pBlock + 4, blockSize));
|
||||
@@ -652,36 +665,28 @@ HRESULT CHandler::Open2(IInStream *stream)
|
||||
{
|
||||
if (xmlLen >= kXmlSizeMax || xmlLen == 0)
|
||||
return S_FALSE;
|
||||
RINOK(stream->Seek(_startPos + dataForkLen, STREAM_SEEK_SET, NULL));
|
||||
size_t size = (size_t)xmlLen;
|
||||
if (size != xmlLen)
|
||||
return S_FALSE;
|
||||
|
||||
RINOK(stream->Seek(_startPos + dataForkLen, STREAM_SEEK_SET, NULL));
|
||||
|
||||
CXml xml;
|
||||
{
|
||||
AString xmlStr;
|
||||
char *ss = xmlStr.GetBuffer((int)size + 1);
|
||||
RINOK(ReadStream_FALSE(stream, ss, size));
|
||||
ss[size] = 0;
|
||||
{
|
||||
const char *p = ss;
|
||||
for (;;)
|
||||
{
|
||||
if (*p == 0) break; p++;
|
||||
if (*p == 0) break; p++;
|
||||
if (*p == 0) break; p++;
|
||||
if (*p == 0) break; p++;
|
||||
}
|
||||
xmlStr.ReleaseBuffer((int)(p - ss));
|
||||
}
|
||||
CObjArray<char> xmlStr(size + 1);
|
||||
RINOK(ReadStream_FALSE(stream, xmlStr, size));
|
||||
xmlStr[size] = 0;
|
||||
// if (strlen(xmlStr) != size) return S_FALSE;
|
||||
if (!xml.Parse(xmlStr))
|
||||
return S_FALSE;
|
||||
|
||||
#ifdef DMG_SHOW_RAW
|
||||
CExtraFile &extra = _extras.AddNew();
|
||||
extra.Name = "a.xml";
|
||||
extra.Data.SetCapacity(size);
|
||||
memcpy(extra.Data, ss, size);
|
||||
extra.Data.CopyFrom((const Byte *)(const char *)xmlStr, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (xml.Root.Name != "plist")
|
||||
return S_FALSE;
|
||||
|
||||
@@ -708,14 +713,14 @@ HRESULT CHandler::Open2(IInStream *stream)
|
||||
continue;
|
||||
|
||||
CByteBuffer rawBuf;
|
||||
int destLen = 0;
|
||||
unsigned destLen = 0;
|
||||
{
|
||||
const AString *dataString = GetStringFromKeyPair(item, "Data", "data");
|
||||
if (!dataString)
|
||||
return S_FALSE;
|
||||
destLen = dataString->Len() / 4 * 3 + 4;
|
||||
rawBuf.Alloc(destLen);
|
||||
destLen = (int)(Base64ToBin(rawBuf, *dataString) - rawBuf);
|
||||
destLen = (unsigned)(Base64ToBin(rawBuf, *dataString) - rawBuf);
|
||||
#ifdef DMG_SHOW_RAW
|
||||
CExtraFile &extra = _extras.AddNew();
|
||||
{
|
||||
@@ -723,8 +728,7 @@ HRESULT CHandler::Open2(IInStream *stream)
|
||||
ConvertUInt32ToString(_files.Size(), extraName);
|
||||
extra.Name = extraName;
|
||||
}
|
||||
extra.Data.SetCapacity(destLen);
|
||||
memcpy(extra.Data, rawBuf, destLen);
|
||||
extra.Data.CopyFrom(rawBuf, destLen);
|
||||
#endif
|
||||
}
|
||||
CFile &file = _files.AddNew();
|
||||
@@ -805,7 +809,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
|
||||
#ifdef DMG_SHOW_RAW
|
||||
if ((int)index >= _files.Size())
|
||||
if (index >= _files.Size())
|
||||
{
|
||||
const CExtraFile &extra = _extras[index - _files.Size()];
|
||||
switch (propID)
|
||||
@@ -897,7 +901,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
UString name2;
|
||||
ConvertUTF8ToUnicode(item.Name, name2);
|
||||
if (!name2.IsEmpty())
|
||||
name += L" - ";
|
||||
name.AddAscii(" - ");
|
||||
name += name2;
|
||||
}
|
||||
prop = name;
|
||||
@@ -1060,9 +1064,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
return S_OK;
|
||||
UInt64 totalSize = 0;
|
||||
UInt32 i;
|
||||
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
int index = (int)(allFilesMode ? i : indices[i]);
|
||||
UInt32 index = (allFilesMode ? i : indices[i]);
|
||||
#ifdef DMG_SHOW_RAW
|
||||
if (index >= _files.Size())
|
||||
totalSize += _extras[index - _files.Size()].Data.Size();
|
||||
@@ -1112,7 +1117,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 askMode = testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract;
|
||||
Int32 index = allFilesMode ? i : indices[i];
|
||||
UInt32 index = allFilesMode ? i : indices[i];
|
||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
|
||||
|
||||
if (!testMode && !realOutStream)
|
||||
@@ -1225,6 +1230,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
opRes = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
break;
|
||||
}
|
||||
|
||||
if (res != S_OK)
|
||||
{
|
||||
if (res != S_FALSE)
|
||||
@@ -1232,7 +1238,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
if (opRes == NExtract::NOperationResult::kOK)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
}
|
||||
|
||||
unpPos += block.UnpSize;
|
||||
|
||||
if (!outStreamSpec->IsFinishedOK())
|
||||
{
|
||||
if (realMethod && opRes == NExtract::NOperationResult::kOK)
|
||||
@@ -1247,6 +1255,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (needCrc && opRes == NExtract::NOperationResult::kOK)
|
||||
{
|
||||
if (outCrcStreamSpec->GetCRC() != item.Checksum.GetCrc32())
|
||||
@@ -1256,6 +1265,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
outStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(opRes));
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
@@ -1322,12 +1332,12 @@ public:
|
||||
};
|
||||
|
||||
|
||||
int FindBlock(const CRecordVector<CBlock> &blocks, UInt64 pos)
|
||||
unsigned FindBlock(const CRecordVector<CBlock> &blocks, UInt64 pos)
|
||||
{
|
||||
int left = 0, right = blocks.Size();
|
||||
unsigned left = 0, right = blocks.Size();
|
||||
for (;;)
|
||||
{
|
||||
int mid = (left + right) / 2;
|
||||
unsigned mid = (left + right) / 2;
|
||||
if (mid == left)
|
||||
return left;
|
||||
if (pos < blocks[mid].UnpPos)
|
||||
@@ -1359,23 +1369,27 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
if (_virtPos < block.UnpPos || (_virtPos - block.UnpPos) >= block.UnpSize)
|
||||
_latestBlock = -1;
|
||||
}
|
||||
|
||||
if (_latestBlock < 0)
|
||||
{
|
||||
_latestChunk = -1;
|
||||
int blockIndex = FindBlock(File->Blocks, _virtPos);
|
||||
unsigned blockIndex = FindBlock(File->Blocks, _virtPos);
|
||||
const CBlock &block = File->Blocks[blockIndex];
|
||||
|
||||
if (!block.IsZeroMethod() && block.Type != METHOD_COPY)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < _chunks.Size(); i++)
|
||||
if (_chunks[i].BlockIndex == blockIndex)
|
||||
if (_chunks[i].BlockIndex == (int)blockIndex)
|
||||
break;
|
||||
|
||||
if (i != _chunks.Size())
|
||||
_latestChunk = i;
|
||||
else
|
||||
{
|
||||
const int kNumChunksMax = 128;
|
||||
int chunkIndex;
|
||||
const unsigned kNumChunksMax = 128;
|
||||
unsigned chunkIndex;
|
||||
|
||||
if (_chunks.Size() != kNumChunksMax)
|
||||
chunkIndex = _chunks.Add(CChunk());
|
||||
else
|
||||
@@ -1385,9 +1399,11 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
if (_chunks[i].AccessMark < _chunks[chunkIndex].AccessMark)
|
||||
chunkIndex = i;
|
||||
}
|
||||
|
||||
CChunk &chunk = _chunks[chunkIndex];
|
||||
chunk.BlockIndex = -1;
|
||||
chunk.AccessMark = 0;
|
||||
|
||||
if (chunk.Buf.Size() < block.UnpSize)
|
||||
{
|
||||
chunk.Buf.Free();
|
||||
@@ -1395,12 +1411,14 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
return E_FAIL;
|
||||
chunk.Buf.Alloc((size_t)block.UnpSize);
|
||||
}
|
||||
|
||||
outStreamSpec->Init(chunk.Buf, (size_t)block.UnpSize);
|
||||
|
||||
RINOK(Stream->Seek(_startPos + File->StartPos + block.PackPos, STREAM_SEEK_SET, NULL));
|
||||
|
||||
limitedStreamSpec->Init(block.PackSize);
|
||||
HRESULT res = S_OK;
|
||||
|
||||
switch (block.Type)
|
||||
{
|
||||
case METHOD_COPY:
|
||||
@@ -1443,6 +1461,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
default:
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (res != S_OK)
|
||||
return res;
|
||||
if (block.Type != METHOD_COPY && outStreamSpec->GetPos() != block.UnpSize)
|
||||
@@ -1450,8 +1469,10 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
chunk.BlockIndex = blockIndex;
|
||||
_latestChunk = chunkIndex;
|
||||
}
|
||||
|
||||
_chunks[_latestChunk].AccessMark = _accessMark++;
|
||||
}
|
||||
|
||||
_latestBlock = blockIndex;
|
||||
}
|
||||
|
||||
@@ -1462,6 +1483,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
size = (UInt32)rem;
|
||||
|
||||
HRESULT res = S_OK;
|
||||
|
||||
if (block.Type == METHOD_COPY)
|
||||
{
|
||||
RINOK(Stream->Seek(_startPos + File->StartPos + block.PackPos + offset, STREAM_SEEK_SET, NULL));
|
||||
@@ -1469,11 +1491,13 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
}
|
||||
else if (block.IsZeroMethod())
|
||||
memset(data, 0, size);
|
||||
else
|
||||
else if (size != 0)
|
||||
memcpy(data, _chunks[_latestChunk].Buf + offset, size);
|
||||
|
||||
_virtPos += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
|
||||
return res;
|
||||
COM_TRY_END
|
||||
}
|
||||
@@ -1498,14 +1522,17 @@ STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPositio
|
||||
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
#ifdef DMG_SHOW_RAW
|
||||
if (index >= (UInt32)_files.Size())
|
||||
return S_FALSE;
|
||||
#endif
|
||||
|
||||
CInStream *spec = new CInStream;
|
||||
CMyComPtr<ISequentialInStream> specStream = spec;
|
||||
spec->File = &_files[index];
|
||||
const CFile &file = *spec->File;
|
||||
|
||||
FOR_VECTOR (i, file.Blocks)
|
||||
{
|
||||
const CBlock &block = file.Blocks[i];
|
||||
@@ -1523,24 +1550,22 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
spec->Stream = _inStream;
|
||||
spec->Size = spec->File->Size;
|
||||
RINOK(spec->InitAndSeek(_startPos));
|
||||
*stream = specStream.Detach();
|
||||
return S_OK;
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Dmg", "dmg", 0, 0xE4,
|
||||
12, { 'k','o','l','y', 0, 0, 0, 4, 0, 0, 2, 0 },
|
||||
REGISTER_ARC_I(
|
||||
"Dmg", "dmg", 0, 0xE4,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kBackwardOpen |
|
||||
NArcInfoFlags::kUseGlobalOffset,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Dmg)
|
||||
NULL)
|
||||
|
||||
}}
|
||||
|
||||
@@ -963,15 +963,13 @@ STDMETHODIMP CHandler::AllowTail(Int32 allowTail)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
static const Byte k_Signature[] = { 0x7F, 'E', 'L', 'F' };
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "ELF", "elf", 0, 0xDE,
|
||||
4, { 0x7F, 'E', 'L', 'F' },
|
||||
REGISTER_ARC_I(
|
||||
"ELF", "elf", 0, 0xDE,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kPreArc,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Elf)
|
||||
NULL)
|
||||
|
||||
}}
|
||||
|
||||
@@ -272,19 +272,27 @@ struct CItem
|
||||
UString GetVolName() const;
|
||||
};
|
||||
|
||||
static int CopyAndTrim(char *dest, const char *src, int size, bool toLower)
|
||||
static unsigned CopyAndTrim(char *dest, const char *src, unsigned size, bool toLower)
|
||||
{
|
||||
int i;
|
||||
memcpy(dest, src, size);
|
||||
if (toLower)
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
for (unsigned i = 0; i < size; i++)
|
||||
{
|
||||
char c = dest[i];
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
dest[i] = (char)(c + 0x20);
|
||||
}
|
||||
for (i = size - 1; i >= 0 && dest[i] == ' '; i--);
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
for (unsigned i = size;;)
|
||||
{
|
||||
if (i == 0)
|
||||
return 0;
|
||||
if (dest[i - 1] != ' ')
|
||||
return i;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
static UString FatStringToUnicode(const char *s)
|
||||
@@ -295,11 +303,11 @@ static UString FatStringToUnicode(const char *s)
|
||||
UString CItem::GetShortName() const
|
||||
{
|
||||
char s[16];
|
||||
int i = CopyAndTrim(s, DosName, 8, NameIsLow());
|
||||
unsigned i = CopyAndTrim(s, DosName, 8, NameIsLow());
|
||||
s[i++] = '.';
|
||||
int j = CopyAndTrim(s + i, DosName + 8, 3, ExtIsLow());
|
||||
unsigned j = CopyAndTrim(s + i, DosName + 8, 3, ExtIsLow());
|
||||
if (j == 0)
|
||||
j--;
|
||||
i--;
|
||||
s[i + j] = 0;
|
||||
return FatStringToUnicode(s);
|
||||
}
|
||||
@@ -316,7 +324,7 @@ UString CItem::GetVolName() const
|
||||
if (!UName.IsEmpty())
|
||||
return UName;
|
||||
char s[12];
|
||||
int i = CopyAndTrim(s, DosName, 11, false);
|
||||
unsigned i = CopyAndTrim(s, DosName, 11, false);
|
||||
s[i] = 0;
|
||||
return FatStringToUnicode(s);
|
||||
}
|
||||
@@ -348,7 +356,7 @@ struct CDatabase
|
||||
|
||||
UString GetItemPath(Int32 index) const;
|
||||
HRESULT Open();
|
||||
HRESULT ReadDir(Int32 parent, UInt32 cluster, int level);
|
||||
HRESULT ReadDir(Int32 parent, UInt32 cluster, unsigned level);
|
||||
|
||||
UInt64 GetHeadersSize() const
|
||||
{
|
||||
@@ -420,9 +428,9 @@ UString CDatabase::GetItemPath(Int32 index) const
|
||||
}
|
||||
}
|
||||
|
||||
static wchar_t *AddSubStringToName(wchar_t *dest, const Byte *p, int numChars)
|
||||
static wchar_t *AddSubStringToName(wchar_t *dest, const Byte *p, unsigned numChars)
|
||||
{
|
||||
for (int i = 0; i < numChars; i++)
|
||||
for (unsigned i = 0; i < numChars; i++)
|
||||
{
|
||||
wchar_t c = Get16(p + i * 2);
|
||||
if (c != 0 && c != 0xFFFF)
|
||||
@@ -432,9 +440,9 @@ static wchar_t *AddSubStringToName(wchar_t *dest, const Byte *p, int numChars)
|
||||
return dest;
|
||||
}
|
||||
|
||||
HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
|
||||
HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, unsigned level)
|
||||
{
|
||||
int startIndex = Items.Size();
|
||||
unsigned startIndex = Items.Size();
|
||||
if (startIndex >= (1 << 30) || level > 256)
|
||||
return S_FALSE;
|
||||
|
||||
@@ -451,6 +459,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
|
||||
UString curName;
|
||||
int checkSum = -1;
|
||||
int numLongRecords = -1;
|
||||
|
||||
for (UInt32 pos = blockSize;; pos += 32)
|
||||
{
|
||||
if (pos == blockSize)
|
||||
@@ -483,7 +492,9 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
|
||||
|
||||
RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize));
|
||||
}
|
||||
|
||||
const Byte *p = ByteBuf + pos;
|
||||
|
||||
if (p[0] == 0)
|
||||
{
|
||||
/*
|
||||
@@ -493,6 +504,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
if (p[0] == 0xE5)
|
||||
{
|
||||
if (numLongRecords > 0)
|
||||
@@ -545,7 +557,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
|
||||
if (checkSum >= 0)
|
||||
{
|
||||
Byte sum = 0;
|
||||
for (int i = 0; i < 11; i++)
|
||||
for (unsigned i = 0; i < 11; i++)
|
||||
sum = (Byte)(((sum & 1) ? 0x80 : 0) + (sum >> 1) + (Byte)item.DosName[i]);
|
||||
if (sum == checkSum)
|
||||
item.UName = curName;
|
||||
@@ -590,8 +602,8 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
|
||||
}
|
||||
}
|
||||
|
||||
int finishIndex = Items.Size();
|
||||
for (int i = startIndex; i < finishIndex; i++)
|
||||
unsigned finishIndex = Items.Size();
|
||||
for (unsigned i = startIndex; i < finishIndex; i++)
|
||||
{
|
||||
const CItem &item = Items[i];
|
||||
if (item.IsDir())
|
||||
@@ -831,7 +843,7 @@ static void FatTimeToProp(UInt32 dosTime, UInt32 ms10, NWindows::NCOM::CPropVari
|
||||
}
|
||||
|
||||
/*
|
||||
static void StringToProp(const Byte *src, int size, NWindows::NCOM::CPropVariant &prop)
|
||||
static void StringToProp(const Byte *src, unsigned size, NWindows::NCOM::CPropVariant &prop)
|
||||
{
|
||||
char dest[32];
|
||||
memcpy(dest, src, size);
|
||||
@@ -1021,15 +1033,13 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
static const Byte k_Signature[] = { 0x55, 0xAA };
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "FAT", "fat img", 0, 0xDA,
|
||||
2, { 0x55, 0xAA },
|
||||
REGISTER_ARC_I(
|
||||
"FAT", "fat img", 0, 0xDA,
|
||||
k_Signature,
|
||||
0x1FE,
|
||||
0,
|
||||
CreateArc, NULL, IsArc_Fat };
|
||||
|
||||
REGISTER_ARC(Fat)
|
||||
IsArc_Fat)
|
||||
|
||||
}}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
// #include <stdio.h>
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
@@ -69,12 +71,12 @@ class CHandler:
|
||||
{
|
||||
CMyComPtr<IInStream> _stream;
|
||||
CObjectVector<CItem2> _items2;
|
||||
// CByteBuffer _metadata;
|
||||
CByteBuffer _metadata;
|
||||
bool _isRaw;
|
||||
UInt64 _phySize;
|
||||
|
||||
HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);
|
||||
AString GetComment();
|
||||
// AString GetComment();
|
||||
public:
|
||||
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
|
||||
INTERFACE_IInArchive(;)
|
||||
@@ -195,10 +197,7 @@ AString CHandler::GetComment()
|
||||
break;
|
||||
{
|
||||
AString temp;
|
||||
char *sz = temp.GetBuffer(len);
|
||||
memcpy(sz, p, len);
|
||||
sz[len] = 0;
|
||||
temp.ReleaseBuffer();
|
||||
temp.SetFrom_CalcLen((const char *)p, len);
|
||||
if (!res.IsEmpty())
|
||||
res += '\n';
|
||||
res += temp;
|
||||
@@ -251,7 +250,6 @@ AString CHandler::GetComment()
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
@@ -413,8 +411,11 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
src += kTagHeaderSize + 1;
|
||||
size -= (kTagHeaderSize + 4 + 1);
|
||||
}
|
||||
memcpy(item2.BufSpec->Buf + item2.Size, src, size);
|
||||
item2.Size += size;
|
||||
if (size != 0)
|
||||
{
|
||||
memcpy(item2.BufSpec->Buf + item2.Size, src, size);
|
||||
item2.Size += size;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
@@ -513,15 +514,13 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
static const Byte k_Signature[] = { 'F', 'L', 'V', 1, };
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "FLV", "flv", 0, 0xD6,
|
||||
4, { 'F', 'L', 'V', 1, },
|
||||
REGISTER_ARC_I(
|
||||
"FLV", "flv", 0, 0xD6,
|
||||
k_Signature,
|
||||
0,
|
||||
0,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Flv)
|
||||
NULL)
|
||||
|
||||
}}
|
||||
|
||||
@@ -44,10 +44,10 @@ namespace NGz {
|
||||
|
||||
namespace NFlags
|
||||
{
|
||||
const Byte kIsText = 1 << 0;
|
||||
const Byte kCrc = 1 << 1;
|
||||
const Byte kExtra = 1 << 2;
|
||||
const Byte kName = 1 << 3;
|
||||
const Byte kIsText = 1 << 0;
|
||||
const Byte kCrc = 1 << 1;
|
||||
const Byte kExtra = 1 << 2;
|
||||
const Byte kName = 1 << 3;
|
||||
const Byte kComment = 1 << 4;
|
||||
const Byte kReserved = 0xE0;
|
||||
}
|
||||
@@ -85,7 +85,7 @@ namespace NGz {
|
||||
};
|
||||
}
|
||||
|
||||
static const char *kHostOSes[] =
|
||||
static const char * const kHostOSes[] =
|
||||
{
|
||||
"FAT"
|
||||
, "AMIGA"
|
||||
@@ -126,6 +126,38 @@ public:
|
||||
AString Comment;
|
||||
// CByteBuffer Extra;
|
||||
|
||||
CItem():
|
||||
Flags(0),
|
||||
ExtraFlags(0),
|
||||
HostOS(0),
|
||||
Time(0),
|
||||
Crc(0),
|
||||
Size32(0) {}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Name.Empty();
|
||||
Comment.Empty();
|
||||
// Extra.Free();
|
||||
}
|
||||
|
||||
void CopyMetaPropsFrom(const CItem &a)
|
||||
{
|
||||
Flags = a.Flags;
|
||||
HostOS = a.HostOS;
|
||||
Time = a.Time;
|
||||
Name = a.Name;
|
||||
Comment = a.Comment;
|
||||
// Extra = a.Extra;
|
||||
}
|
||||
|
||||
void CopyDataPropsFrom(const CItem &a)
|
||||
{
|
||||
ExtraFlags = a.ExtraFlags;
|
||||
Crc = a.Crc;
|
||||
Size32 = a.Size32;
|
||||
}
|
||||
|
||||
// bool IsText() const { return TestFlag(NFlags::kIsText); }
|
||||
bool HeaderCrcIsPresent() const { return TestFlag(NFlags::kCrc); }
|
||||
bool ExtraFieldIsPresent() const { return TestFlag(NFlags::kExtra); }
|
||||
@@ -133,13 +165,6 @@ public:
|
||||
bool CommentIsPresent() const { return TestFlag(NFlags::kComment); }
|
||||
bool IsSupported() const { return (Flags & NFlags::kReserved) == 0; }
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Name.Empty();
|
||||
Comment.Empty();
|
||||
// Extra.SetCapacity(0);
|
||||
}
|
||||
|
||||
HRESULT ReadHeader(NDecoder::CCOMCoder *stream);
|
||||
HRESULT ReadFooter1(NDecoder::CCOMCoder *stream);
|
||||
HRESULT ReadFooter2(ISequentialInStream *stream);
|
||||
@@ -459,7 +484,7 @@ public:
|
||||
INTERFACE_IInArchive(;)
|
||||
INTERFACE_IOutArchive(;)
|
||||
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
|
||||
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
|
||||
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
|
||||
|
||||
CHandler()
|
||||
{
|
||||
@@ -510,7 +535,11 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
}
|
||||
case kpidName:
|
||||
if (_item.NameIsPresent())
|
||||
prop = MultiByteToUnicodeString(_item.Name, CP_ACP) + L".gz";
|
||||
{
|
||||
UString s = MultiByteToUnicodeString(_item.Name, CP_ACP);
|
||||
s.AddAscii(".gz");
|
||||
prop = s;
|
||||
}
|
||||
break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
@@ -656,7 +685,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
|
||||
return E_INVALIDARG;
|
||||
|
||||
// if (_stream) extractCallback->SetTotal(_packSize);
|
||||
if (_packSize_Defined)
|
||||
extractCallback->SetTotal(_packSize);
|
||||
// UInt64 currentTotalPacked = 0;
|
||||
// RINOK(extractCallback->SetCompleted(¤tTotalPacked));
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
@@ -794,6 +824,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
result = S_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
// break; // we can use break, if we need only first stream
|
||||
}
|
||||
|
||||
} catch(const CInBufferException &e) { return e.ErrorCode; }
|
||||
@@ -844,7 +876,7 @@ static const Byte kHostOS =
|
||||
static HRESULT UpdateArchive(
|
||||
ISequentialOutStream *outStream,
|
||||
UInt64 unpackSize,
|
||||
const CItem &newItem,
|
||||
CItem &item,
|
||||
const CSingleMethodProps &props,
|
||||
IArchiveUpdateCallback *updateCallback)
|
||||
{
|
||||
@@ -865,7 +897,6 @@ static HRESULT UpdateArchive(
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(updateCallback, true);
|
||||
|
||||
CItem item = newItem;
|
||||
item.ExtraFlags = props.GetLevel() >= 7 ?
|
||||
NExtraFlags::kMaximum :
|
||||
NExtraFlags::kFastest;
|
||||
@@ -894,6 +925,8 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
|
||||
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
|
||||
IArchiveUpdateCallback *updateCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
if (numItems != 1)
|
||||
return E_INVALIDARG;
|
||||
|
||||
@@ -903,11 +936,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
return E_FAIL;
|
||||
RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));
|
||||
|
||||
CItem newItem = _item;
|
||||
newItem.ExtraFlags = 0;
|
||||
newItem.Flags = 0;
|
||||
if (IntToBool(newProps))
|
||||
CItem newItem;
|
||||
|
||||
if (!IntToBool(newProps))
|
||||
{
|
||||
newItem.CopyMetaPropsFrom(_item);
|
||||
}
|
||||
else
|
||||
{
|
||||
newItem.HostOS = kHostOS;
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(0, kpidMTime, &prop));
|
||||
@@ -924,9 +961,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
if (prop.vt == VT_BSTR)
|
||||
{
|
||||
UString name = prop.bstrVal;
|
||||
int dirDelimiterPos = name.ReverseFind(WCHAR_PATH_SEPARATOR);
|
||||
if (dirDelimiterPos >= 0)
|
||||
name = name.Ptr(dirDelimiterPos + 1);
|
||||
int slashPos = name.ReverseFind_PathSepar();
|
||||
if (slashPos >= 0)
|
||||
name.DeleteFrontal(slashPos + 1);
|
||||
newItem.Name = UnicodeStringToMultiByte(name, CP_ACP);
|
||||
if (!newItem.Name.IsEmpty())
|
||||
newItem.Flags |= NFlags::kName;
|
||||
@@ -937,13 +974,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));
|
||||
if (prop.vt == VT_BOOL)
|
||||
{
|
||||
if (prop.boolVal != VARIANT_FALSE)
|
||||
if (prop.vt != VT_EMPTY)
|
||||
if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
else if (prop.vt != VT_EMPTY)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -959,13 +992,28 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
}
|
||||
return UpdateArchive(outStream, size, newItem, _props, updateCallback);
|
||||
}
|
||||
|
||||
|
||||
if (indexInArchive != 0)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (!_stream)
|
||||
return E_NOTIMPL;
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(updateCallback, true);
|
||||
|
||||
CMyComPtr<IArchiveUpdateCallbackFile> opCallback;
|
||||
updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);
|
||||
if (opCallback)
|
||||
{
|
||||
RINOK(opCallback->ReportOperation(
|
||||
NEventIndexType::kInArcIndex, 0,
|
||||
NUpdateNotifyOp::kReplicate))
|
||||
}
|
||||
|
||||
newItem.CopyDataPropsFrom(_item);
|
||||
|
||||
UInt64 offset = 0;
|
||||
if (IntToBool(newProps))
|
||||
{
|
||||
@@ -973,24 +1021,24 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
offset += _headerSize;
|
||||
}
|
||||
RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL));
|
||||
return NCompress::CopyStream(_stream, outStream, NULL);
|
||||
|
||||
return NCompress::CopyStream(_stream, outStream, progress);
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
return _props.SetProperties(names, values, numProps);
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
IMP_CreateArcOut
|
||||
static const Byte k_Signature[] = { kSignature_0, kSignature_1, kSignature_2 };
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "gzip", "gz gzip tgz tpz", "* * .tar .tar", 0xEF,
|
||||
3, { kSignature_0, kSignature_1, kSignature_2 },
|
||||
REGISTER_ARC_IO(
|
||||
"gzip", "gz gzip tgz tpz", "* * .tar .tar", 0xEF,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kKeepName,
|
||||
REF_CreateArc_Pair, IsArc_Gz };
|
||||
|
||||
REGISTER_ARC(GZip)
|
||||
IsArc_Gz)
|
||||
|
||||
}}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
namespace NArchive {
|
||||
namespace NHfs {
|
||||
|
||||
static const wchar_t *kResFileName = L"rsrc"; // L"com.apple.ResourceFork";
|
||||
static const char *kResFileName = "rsrc"; // "com.apple.ResourceFork";
|
||||
|
||||
struct CExtent
|
||||
{
|
||||
@@ -655,12 +655,17 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec
|
||||
|
||||
static void LoadName(const Byte *data, unsigned len, UString &dest)
|
||||
{
|
||||
wchar_t *p = dest.GetBuffer(len);
|
||||
wchar_t *p = dest.GetBuf(len);
|
||||
unsigned i;
|
||||
for (i = 0; i < len; i++)
|
||||
p[i] = Get16(data + i * 2);
|
||||
{
|
||||
wchar_t c = Get16(data + i * 2);
|
||||
if (c == 0)
|
||||
break;
|
||||
p[i] = c;
|
||||
}
|
||||
p[i] = 0;
|
||||
dest.ReleaseBuffer();
|
||||
dest.ReleaseBuf_SetLen(i);
|
||||
}
|
||||
|
||||
static bool IsNameEqualTo(const Byte *data, const char *name)
|
||||
@@ -805,7 +810,7 @@ static const UInt32 kMethod_Resource = 4; // data stored in resource fork
|
||||
bool CDatabase::Parse_decmpgfs(const CAttr &attr, CItem &item, bool &skip)
|
||||
{
|
||||
skip = false;
|
||||
if (attr.Name != L"com.apple.decmpfs")
|
||||
if (!attr.Name.IsEqualTo("com.apple.decmpfs"))
|
||||
return true;
|
||||
if (item.UseAttr || !item.DataFork.IsEmpty())
|
||||
return false;
|
||||
@@ -961,13 +966,13 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents
|
||||
IsNameEqualTo(name + 8, "HFS+ Private Data"))
|
||||
{
|
||||
// it's folder for "Hard Links" files
|
||||
item.Name = L"[HFS+ Private Data]";
|
||||
item.Name.SetFromAscii("[HFS+ Private Data]");
|
||||
}
|
||||
}
|
||||
|
||||
// Some dmg files have ' ' folder item.
|
||||
if (item.Name.IsEmpty() || item.Name[0] == L' ')
|
||||
item.Name = L"[]";
|
||||
item.Name.SetFromAscii("[]");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1221,7 +1226,7 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress)
|
||||
return S_FALSE;
|
||||
*/
|
||||
|
||||
ResFileName = kResFileName;
|
||||
ResFileName.SetFromAscii(kResFileName);
|
||||
|
||||
CFork extentsFork, catalogFork, attrFork;
|
||||
// allocationFork.Parse(p + 0x70 + 0x50 * 0);
|
||||
@@ -1856,19 +1861,15 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
return GetForkStream(item.GetFork(ref.IsResource), stream);
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "HFS", "hfs hfsx", 0, 0xE3,
|
||||
2 * (4 + 1),
|
||||
{
|
||||
static const Byte k_Signature[] = {
|
||||
4, 'H', '+', 0, 4,
|
||||
4, 'H', 'X', 0, 5,
|
||||
},
|
||||
4, 'H', 'X', 0, 5 };
|
||||
|
||||
REGISTER_ARC_I(
|
||||
"HFS", "hfs hfsx", 0, 0xE3,
|
||||
k_Signature,
|
||||
kHeaderPadSize,
|
||||
NArcInfoFlags::kMultiSignature,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Hfs)
|
||||
NULL)
|
||||
|
||||
}}
|
||||
|
||||
@@ -82,10 +82,22 @@ namespace NArchive
|
||||
kUnexpectedEnd,
|
||||
kDataAfterEnd,
|
||||
kIsNotArc,
|
||||
kHeadersError
|
||||
kHeadersError,
|
||||
kWrongPassword
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace NEventIndexType
|
||||
{
|
||||
enum
|
||||
{
|
||||
kNoIndex = 0,
|
||||
kInArcIndex,
|
||||
kBlockIndex,
|
||||
kOutArcIndex
|
||||
};
|
||||
}
|
||||
|
||||
namespace NUpdate
|
||||
{
|
||||
@@ -110,17 +122,59 @@ ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10)
|
||||
};
|
||||
|
||||
/*
|
||||
IArchiveExtractCallback::GetStream
|
||||
Result:
|
||||
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 can not real stream: (*inStream == NULL)
|
||||
}
|
||||
|
||||
Out:
|
||||
(*inStream == NULL) - for directories
|
||||
(*inStream == NULL) - if link (hard link or symbolic link) was created
|
||||
if (*inStream == 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 resultEOperationResult) x; \
|
||||
STDMETHOD(SetOperationResult)(Int32 opRes) x; \
|
||||
|
||||
ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20)
|
||||
{
|
||||
@@ -128,6 +182,25 @@ ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20)
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
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; \
|
||||
@@ -183,9 +256,6 @@ Notes:
|
||||
Some IInArchive handlers will work incorrectly in that case.
|
||||
*/
|
||||
|
||||
/* MSVC allows the code where there is throw() in declaration of function,
|
||||
but there is no throw() in definition of function. */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define MY_NO_THROW_DECL_ONLY throw()
|
||||
#else
|
||||
@@ -202,7 +272,7 @@ Notes:
|
||||
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;
|
||||
STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x; \
|
||||
|
||||
ARCHIVE_INTERFACE(IInArchive, 0x60)
|
||||
{
|
||||
@@ -324,6 +394,8 @@ The order of calling for hard links:
|
||||
- GetStream()
|
||||
- GetProperty(kpidHardLink)
|
||||
|
||||
SetOperationResult()
|
||||
Int32 opRes (NExtract::NOperationResult::kOK)
|
||||
*/
|
||||
|
||||
#define INTERFACE_IArchiveUpdateCallback(x) \
|
||||
@@ -348,6 +420,40 @@ 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()
|
||||
-------------
|
||||
@@ -382,7 +488,7 @@ ARCHIVE_INTERFACE(IOutArchive, 0xA0)
|
||||
|
||||
ARCHIVE_INTERFACE(ISetProperties, 0x03)
|
||||
{
|
||||
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) PURE;
|
||||
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) PURE;
|
||||
};
|
||||
|
||||
ARCHIVE_INTERFACE(IArchiveKeepModeForNextOpen, 0x04)
|
||||
|
||||
@@ -85,7 +85,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
const CBlock &block = _blocks[index];
|
||||
switch (propID)
|
||||
{
|
||||
case kpidSize: prop = block.Data.GetPos(); break;
|
||||
case kpidSize: prop = (UInt64)block.Data.GetPos(); break;
|
||||
case kpidVa: prop = block.Offset; break;
|
||||
case kpidPath:
|
||||
{
|
||||
@@ -103,7 +103,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
static inline int HexToByte(char c)
|
||||
static inline int HexToByte(unsigned c)
|
||||
{
|
||||
if (c >= '0' && c <= '9') return c - '0';
|
||||
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
|
||||
@@ -138,9 +138,9 @@ API_FUNC_static_IsArc IsArc_Ihex(const Byte *p, size_t size)
|
||||
p++;
|
||||
size--;
|
||||
|
||||
const int kNumLinesToCheck = 3; // 1 line is OK also, but we don't want false detection
|
||||
const unsigned kNumLinesToCheck = 3; // 1 line is OK also, but we don't want false detection
|
||||
|
||||
for (int j = 0; j < kNumLinesToCheck; j++)
|
||||
for (unsigned j = 0; j < kNumLinesToCheck; j++)
|
||||
{
|
||||
if (size < 4 * 2)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
@@ -279,7 +279,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
|
||||
}
|
||||
|
||||
{
|
||||
size_t numPairs = (num + 4);
|
||||
size_t numPairs = ((unsigned)num + 4);
|
||||
size_t numBytes = numPairs * 2;
|
||||
if (s.ReadBytes(temp, numBytes) != numBytes)
|
||||
{
|
||||
@@ -287,7 +287,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
int sum = num;
|
||||
unsigned sum = num;
|
||||
for (size_t i = 0; i < numPairs; i++)
|
||||
{
|
||||
int a = Parse(temp + i * 2);
|
||||
@@ -339,7 +339,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
|
||||
block = &_blocks.AddNew();
|
||||
block->Offset = offs;
|
||||
}
|
||||
memcpy(block->Data.GetCurPtrAndGrow(num), temp + 3, num);
|
||||
block->Data.AddData(temp + 3, (unsigned)num);
|
||||
}
|
||||
}
|
||||
else if (type == kType_Eof)
|
||||
@@ -486,16 +486,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
// k_Signature: { ':', '1' }
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "IHex", "ihex", 0, 0xCD,
|
||||
0, { 0 },
|
||||
// 2, { ':', '1' },
|
||||
REGISTER_ARC_I_NO_SIG(
|
||||
"IHex", "ihex", 0, 0xCD,
|
||||
0,
|
||||
NArcInfoFlags::kStartOpen,
|
||||
CreateArc, NULL, IsArc_Ihex };
|
||||
|
||||
REGISTER_ARC(Z)
|
||||
IsArc_Ihex)
|
||||
|
||||
}}
|
||||
|
||||
@@ -79,8 +79,7 @@ static void AddString(AString &s, const char *name, const Byte *p, unsigned size
|
||||
if (i != 0)
|
||||
{
|
||||
AString d;
|
||||
memcpy(d.GetBuffer(i), p, i);
|
||||
d.ReleaseBuffer(i);
|
||||
d.SetFrom((const char *)p, i);
|
||||
s += '\n';
|
||||
s += name;
|
||||
s += ": ";
|
||||
@@ -170,11 +169,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
{
|
||||
case kpidPath:
|
||||
{
|
||||
// char name[16];
|
||||
// ConvertUInt32ToString(index + 1, name);
|
||||
AString s = "[BOOT]" STRING_PATH_SEPARATOR;
|
||||
// s += name;
|
||||
// s += '-';
|
||||
if (_archive.BootEntries.Size() != 1)
|
||||
{
|
||||
char temp[16];
|
||||
ConvertUInt32ToString(index + 1, temp);
|
||||
s += temp;
|
||||
s += '-';
|
||||
}
|
||||
s += be.GetName();
|
||||
prop = s;
|
||||
break;
|
||||
@@ -197,18 +199,18 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
{
|
||||
UString s;
|
||||
if (_archive.IsJoliet())
|
||||
s = item.GetPathU();
|
||||
item.GetPathU(s);
|
||||
else
|
||||
s = MultiByteToUnicodeString(item.GetPath(_archive.IsSusp, _archive.SuspSkipSize), CP_OEMCP);
|
||||
|
||||
int pos = s.ReverseFind(L';');
|
||||
if (pos >= 0 && pos == (int)s.Len() - 2)
|
||||
if (s.Back() == L'1')
|
||||
s.DeleteFrom(pos);
|
||||
if (!s.IsEmpty())
|
||||
if (s.Back() == L'.')
|
||||
s.DeleteBack();
|
||||
prop = (const wchar_t *)NItemName::GetOSName2(s);
|
||||
if (s.Len() >= 2 && s[s.Len() - 2] == ';' && s.Back() == '1')
|
||||
s.DeleteFrom(s.Len() - 2);
|
||||
|
||||
if (!s.IsEmpty() && s.Back() == L'.')
|
||||
s.DeleteBack();
|
||||
|
||||
NItemName::ConvertToOSName2(s);
|
||||
prop = s;
|
||||
}
|
||||
break;
|
||||
case kpidIsDir: prop = item.IsDir(); break;
|
||||
@@ -319,8 +321,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
UInt64 offset = 0;
|
||||
for (UInt32 e = 0; e < ref.NumExtents; e++)
|
||||
{
|
||||
if (e != 0)
|
||||
lps->InSize = lps->OutSize = currentTotalSize + offset;
|
||||
lps->InSize = lps->OutSize = currentTotalSize + offset;
|
||||
const CDir &item2 = ref.Dir->_subItems[ref.Index + e];
|
||||
RINOK(_stream->Seek((UInt64)item2.ExtentLocation * _archive.BlockSize, STREAM_SEEK_SET, NULL));
|
||||
streamSpec->Init(item2.Size);
|
||||
@@ -356,6 +357,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
*stream = 0;
|
||||
UInt64 blockIndex;
|
||||
UInt64 currentItemSize;
|
||||
|
||||
if (index < (UInt32)_archive.Refs.Size())
|
||||
{
|
||||
const CRef &ref = _archive.Refs[index];
|
||||
@@ -402,6 +404,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
currentItemSize = _archive.GetBootItemSize(bootIndex);
|
||||
blockIndex = be.LoadRBA;
|
||||
}
|
||||
|
||||
return CreateLimitedInStream(_stream, blockIndex * _archive.BlockSize, currentItemSize, stream);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
@@ -9,13 +9,4 @@ namespace NIso {
|
||||
|
||||
const char *kElToritoSpec = "EL TORITO SPECIFICATION\0\0\0\0\0\0\0\0\0";
|
||||
|
||||
const char *kMediaTypes[5] =
|
||||
{
|
||||
"NoEmulation"
|
||||
, "1.2M"
|
||||
, "1.44M"
|
||||
, "2.88M"
|
||||
, "HardDisk"
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -34,6 +34,11 @@ namespace NBootEntryId
|
||||
const Byte kValidationEntry = 1;
|
||||
const Byte kInitialEntryNotBootable = 0;
|
||||
const Byte kInitialEntryBootable = 0x88;
|
||||
|
||||
const Byte kMoreHeaders = 0x90;
|
||||
const Byte kFinalHeader = 0x91;
|
||||
|
||||
const Byte kExtensionIndicator = 0x44;
|
||||
}
|
||||
|
||||
namespace NBootPlatformId
|
||||
@@ -54,9 +59,6 @@ namespace NBootMediaType
|
||||
const Byte kHardDisk = 4;
|
||||
}
|
||||
|
||||
const unsigned kNumBootMediaTypes = 5;
|
||||
extern const char *kMediaTypes[];
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/CpuArch.h"
|
||||
|
||||
#include "../../../Common/MyException.h"
|
||||
|
||||
#include "../../Common/StreamUtils.h"
|
||||
@@ -10,11 +12,78 @@
|
||||
|
||||
namespace NArchive {
|
||||
namespace NIso {
|
||||
|
||||
|
||||
struct CUnexpectedEndException {};
|
||||
struct CHeaderErrorException {};
|
||||
struct CEndianErrorException {};
|
||||
|
||||
static const char * const kMediaTypes[] =
|
||||
{
|
||||
"NoEmul"
|
||||
, "1.2M"
|
||||
, "1.44M"
|
||||
, "2.88M"
|
||||
, "HardDisk"
|
||||
};
|
||||
|
||||
bool CBootInitialEntry::Parse(const Byte *p)
|
||||
{
|
||||
Bootable = (p[0] == NBootEntryId::kInitialEntryBootable);
|
||||
BootMediaType = p[1];
|
||||
LoadSegment = GetUi16(p + 2);
|
||||
SystemType = p[4];
|
||||
SectorCount = GetUi16(p + 6);
|
||||
LoadRBA = GetUi32(p + 8);
|
||||
memcpy(VendorSpec, p + 12, 20);
|
||||
if (p[5] != 0)
|
||||
return false;
|
||||
if (p[0] != NBootEntryId::kInitialEntryBootable
|
||||
&& p[0] != NBootEntryId::kInitialEntryNotBootable)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
AString CBootInitialEntry::GetName() const
|
||||
{
|
||||
AString s = (Bootable ? "Boot" : "NotBoot");
|
||||
s += '-';
|
||||
|
||||
if (BootMediaType < ARRAY_SIZE(kMediaTypes))
|
||||
s += kMediaTypes[BootMediaType];
|
||||
else
|
||||
{
|
||||
char name[16];
|
||||
ConvertUInt32ToString(BootMediaType, name);
|
||||
s += name;
|
||||
}
|
||||
|
||||
if (VendorSpec[0] == 1)
|
||||
{
|
||||
// "Language and Version Information (IBM)"
|
||||
|
||||
unsigned i;
|
||||
for (i = 1; i < sizeof(VendorSpec); i++)
|
||||
if (VendorSpec[i] > 0x7F)
|
||||
break;
|
||||
if (i == sizeof(VendorSpec))
|
||||
{
|
||||
s += '-';
|
||||
for (i = 1; i < sizeof(VendorSpec); i++)
|
||||
{
|
||||
char c = VendorSpec[i];
|
||||
if (c == 0)
|
||||
break;
|
||||
if (c == '\\' || c == '/')
|
||||
c = '_';
|
||||
s += c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s += ".img";
|
||||
return s;
|
||||
}
|
||||
|
||||
Byte CInArchive::ReadByte()
|
||||
{
|
||||
if (m_BufferPos >= BlockSize)
|
||||
@@ -58,15 +127,6 @@ void CInArchive::SkipZeros(size_t size)
|
||||
}
|
||||
}
|
||||
|
||||
UInt16 CInArchive::ReadUInt16Spec()
|
||||
{
|
||||
UInt16 val = 0;
|
||||
for (int i = 0; i < 2; i++)
|
||||
val |= ((UInt16)(ReadByte()) << (8 * i));
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
UInt16 CInArchive::ReadUInt16()
|
||||
{
|
||||
Byte b[4];
|
||||
@@ -179,15 +239,15 @@ void CInArchive::ReadDirRecord2(CDirRecord &r, Byte len)
|
||||
Byte idLen = ReadByte();
|
||||
r.FileId.Alloc(idLen);
|
||||
ReadBytes((Byte *)r.FileId, idLen);
|
||||
int padSize = 1 - (idLen & 1);
|
||||
unsigned padSize = 1 - (idLen & 1);
|
||||
|
||||
// SkipZeros(1 - (idLen & 1));
|
||||
Skip(1 - (idLen & 1)); // it's bug in some cd's. Must be zeros
|
||||
// SkipZeros(padSize);
|
||||
Skip(padSize); // it's bug in some cd's. Must be zeros
|
||||
|
||||
int curPos = 33 + idLen + padSize;
|
||||
unsigned curPos = 33 + idLen + padSize;
|
||||
if (curPos > len)
|
||||
throw CHeaderErrorException();
|
||||
int rem = len - curPos;
|
||||
unsigned rem = len - curPos;
|
||||
r.SystemUse.Alloc(rem);
|
||||
ReadBytes((Byte *)r.SystemUse, rem);
|
||||
}
|
||||
@@ -349,45 +409,94 @@ void CInArchive::ReadBootInfo()
|
||||
{
|
||||
if (!_bootIsDefined)
|
||||
return;
|
||||
HeadersError = true;
|
||||
|
||||
if (memcmp(_bootDesc.BootSystemId, kElToritoSpec, sizeof(_bootDesc.BootSystemId)) != 0)
|
||||
return;
|
||||
|
||||
const Byte *p = (const Byte *)_bootDesc.BootSystemUse;
|
||||
UInt32 blockIndex = p[0] | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16) | ((UInt32)p[3] << 24);
|
||||
UInt32 blockIndex = GetUi32(_bootDesc.BootSystemUse);
|
||||
SeekToBlock(blockIndex);
|
||||
Byte b = ReadByte();
|
||||
if (b != NBootEntryId::kValidationEntry)
|
||||
|
||||
Byte buf[32];
|
||||
ReadBytes(buf, 32);
|
||||
|
||||
if (buf[0] != NBootEntryId::kValidationEntry
|
||||
|| buf[2] != 0
|
||||
|| buf[3] != 0
|
||||
|| buf[30] != 0x55
|
||||
|| buf[31] != 0xAA)
|
||||
return;
|
||||
|
||||
{
|
||||
UInt32 sum = 0;
|
||||
for (unsigned i = 0; i < 32; i += 2)
|
||||
sum += GetUi16(buf + i);
|
||||
if ((sum & 0xFFFF) != 0)
|
||||
return;
|
||||
/*
|
||||
CBootValidationEntry e;
|
||||
e.PlatformId = ReadByte();
|
||||
if (ReadUInt16Spec() != 0)
|
||||
throw CHeaderErrorException();
|
||||
ReadBytes(e.Id, sizeof(e.Id));
|
||||
/* UInt16 checkSum = */ ReadUInt16Spec();
|
||||
if (ReadByte() != 0x55)
|
||||
throw CHeaderErrorException();
|
||||
if (ReadByte() != 0xAA)
|
||||
throw CHeaderErrorException();
|
||||
e.PlatformId = buf[1];
|
||||
memcpy(e.Id, buf + 4, sizeof(e.Id));
|
||||
// UInt16 checkSum = GetUi16(p + 28);
|
||||
*/
|
||||
}
|
||||
b = ReadByte();
|
||||
if (b == NBootEntryId::kInitialEntryBootable || b == NBootEntryId::kInitialEntryNotBootable)
|
||||
|
||||
ReadBytes(buf, 32);
|
||||
{
|
||||
CBootInitialEntry e;
|
||||
e.Bootable = (b == NBootEntryId::kInitialEntryBootable);
|
||||
e.BootMediaType = ReadByte();
|
||||
e.LoadSegment = ReadUInt16Spec();
|
||||
e.SystemType = ReadByte();
|
||||
if (ReadByte() != 0)
|
||||
throw CHeaderErrorException();
|
||||
e.SectorCount = ReadUInt16Spec();
|
||||
e.LoadRBA = ReadUInt32Le();
|
||||
if (ReadByte() != 0)
|
||||
throw CHeaderErrorException();
|
||||
if (!e.Parse(buf))
|
||||
return;
|
||||
BootEntries.Add(e);
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
bool error = false;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
ReadBytes(buf, 32);
|
||||
Byte headerIndicator = buf[0];
|
||||
if (headerIndicator != NBootEntryId::kMoreHeaders
|
||||
&& headerIndicator != NBootEntryId::kFinalHeader)
|
||||
break;
|
||||
|
||||
// Section Header
|
||||
// Byte platform = p[1];
|
||||
unsigned numEntries = GetUi16(buf + 2);
|
||||
// id[28]
|
||||
|
||||
for (unsigned i = 0; i < numEntries; i++)
|
||||
{
|
||||
ReadBytes(buf, 32);
|
||||
CBootInitialEntry e;
|
||||
if (!e.Parse(buf))
|
||||
{
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
if (e.BootMediaType & (1 << 5))
|
||||
{
|
||||
// Section entry extension
|
||||
for (unsigned j = 0;; j++)
|
||||
{
|
||||
ReadBytes(buf, 32);
|
||||
if (j > 32 || buf[0] != NBootEntryId::kExtensionIndicator)
|
||||
{
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
if ((buf[1] & (1 << 5)) == 0)
|
||||
break;
|
||||
// info += (buf + 2, 30)
|
||||
}
|
||||
}
|
||||
BootEntries.Add(e);
|
||||
}
|
||||
|
||||
if (headerIndicator != NBootEntryId::kMoreHeaders)
|
||||
break;
|
||||
}
|
||||
|
||||
HeadersError = error;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::Open2()
|
||||
|
||||
@@ -25,77 +25,92 @@ struct CDir: public CDirRecord
|
||||
_subItems.Clear();
|
||||
}
|
||||
|
||||
unsigned GetLen(bool checkSusp, unsigned skipSize) const
|
||||
{
|
||||
unsigned len = GetLenCur(checkSusp, skipSize);
|
||||
if (Parent != 0)
|
||||
if (Parent->Parent != 0)
|
||||
len += 1 + Parent->GetLen(checkSusp, skipSize);
|
||||
return len;
|
||||
}
|
||||
|
||||
unsigned GetLenU() const
|
||||
{
|
||||
unsigned len = (unsigned)(FileId.Size() / 2);
|
||||
if (Parent != 0)
|
||||
if (Parent->Parent != 0)
|
||||
len += 1 + Parent->GetLenU();
|
||||
return len;
|
||||
}
|
||||
|
||||
AString GetPath(bool checkSusp, unsigned skipSize) const
|
||||
{
|
||||
AString s;
|
||||
unsigned len = GetLen(checkSusp, skipSize);
|
||||
char *p = s.GetBuffer(len);
|
||||
p += len;
|
||||
*p = 0;
|
||||
|
||||
unsigned len = 0;
|
||||
const CDir *cur = this;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
unsigned curLen = cur->GetLenCur(checkSusp, skipSize);
|
||||
p -= curLen;
|
||||
memcpy(p, (const char *)(const Byte *)cur->GetNameCur(checkSusp, skipSize), curLen);
|
||||
unsigned curLen;
|
||||
cur->GetNameCur(checkSusp, skipSize, curLen);
|
||||
len += curLen;
|
||||
cur = cur->Parent;
|
||||
if (cur == 0)
|
||||
if (!cur || !cur->Parent)
|
||||
break;
|
||||
if (cur->Parent == 0)
|
||||
len++;
|
||||
}
|
||||
|
||||
char *p = s.GetBuf_SetEnd(len) + len;
|
||||
|
||||
cur = this;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
unsigned curLen;
|
||||
const Byte *name = cur->GetNameCur(checkSusp, skipSize, curLen);
|
||||
p -= curLen;
|
||||
if (curLen != 0)
|
||||
memcpy(p, name, curLen);
|
||||
cur = cur->Parent;
|
||||
if (!cur || !cur->Parent)
|
||||
break;
|
||||
p--;
|
||||
*p = CHAR_PATH_SEPARATOR;
|
||||
}
|
||||
s.ReleaseBuffer();
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
UString GetPathU() const
|
||||
void GetPathU(UString &s) const
|
||||
{
|
||||
UString s;
|
||||
unsigned len = GetLenU();
|
||||
wchar_t *p = s.GetBuffer(len);
|
||||
p += len;
|
||||
*p = 0;
|
||||
s.Empty();
|
||||
|
||||
unsigned len = 0;
|
||||
const CDir *cur = this;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
unsigned curLen = (unsigned)(cur->FileId.Size() / 2);
|
||||
p -= curLen;
|
||||
for (unsigned i = 0; i < curLen; i++)
|
||||
{
|
||||
Byte b0 = ((const Byte *)cur->FileId)[i * 2];
|
||||
Byte b1 = ((const Byte *)cur->FileId)[i * 2 + 1];
|
||||
p[i] = (wchar_t)(((wchar_t)b0 << 8) | b1);
|
||||
}
|
||||
const Byte *fid = cur->FileId;
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < curLen; i++)
|
||||
if (fid[i * 2] == 0 && fid[i * 2 + 1] == 0)
|
||||
break;
|
||||
len += i;
|
||||
cur = cur->Parent;
|
||||
if (cur == 0)
|
||||
if (!cur || !cur->Parent)
|
||||
break;
|
||||
if (cur->Parent == 0)
|
||||
len++;
|
||||
}
|
||||
|
||||
wchar_t *p = s.GetBuf_SetEnd(len) + len;
|
||||
|
||||
cur = this;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
unsigned curLen = (unsigned)(cur->FileId.Size() / 2);
|
||||
const Byte *fid = cur->FileId;
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < curLen; i++)
|
||||
if (fid[i * 2] == 0 && fid[i * 2 + 1] == 0)
|
||||
break;
|
||||
curLen = i;
|
||||
|
||||
p -= curLen;
|
||||
for (i = 0; i < curLen; i++)
|
||||
p[i] = (wchar_t)(((wchar_t)fid[i * 2] << 8) | fid[i * 2 + 1]);
|
||||
cur = cur->Parent;
|
||||
if (!cur || !cur->Parent)
|
||||
break;
|
||||
p--;
|
||||
*p = WCHAR_PATH_SEPARATOR;
|
||||
}
|
||||
s.ReleaseBuffer();
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -109,6 +124,7 @@ struct CDateTime
|
||||
Byte Second;
|
||||
Byte Hundredths;
|
||||
signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded.
|
||||
|
||||
bool NotSpecified() const { return Year == 0 && Month == 0 && Day == 0 &&
|
||||
Hour == 0 && Minute == 0 && Second == 0 && GmtOffset == 0; }
|
||||
|
||||
@@ -118,7 +134,7 @@ struct CDateTime
|
||||
bool res = NWindows::NTime::GetSecondsSince1601(Year, Month, Day, Hour, Minute, Second, value);
|
||||
if (res)
|
||||
{
|
||||
value -= (UInt64)((Int64)GmtOffset * 15 * 60);
|
||||
value -= (Int64)((Int32)GmtOffset * 15 * 60);
|
||||
value *= 10000000;
|
||||
}
|
||||
ft.dwLowDateTime = (DWORD)value;
|
||||
@@ -157,27 +173,16 @@ struct CBootInitialEntry
|
||||
UInt32 LoadRBA; // This is the start address of the virtual disk. CD<43>s use
|
||||
// Relative/Logical block addressing.
|
||||
|
||||
UInt64 GetSize() const
|
||||
Byte VendorSpec[20];
|
||||
|
||||
UInt32 GetSize() const
|
||||
{
|
||||
// if (BootMediaType == NBootMediaType::k1d44Floppy) (1440 << 10);
|
||||
return SectorCount * 512;
|
||||
return (UInt32)SectorCount * 512;
|
||||
}
|
||||
|
||||
AString GetName() const
|
||||
{
|
||||
AString s = (Bootable ? "Bootable" : "NotBootable");
|
||||
s += '_';
|
||||
if (BootMediaType < kNumBootMediaTypes)
|
||||
s += kMediaTypes[BootMediaType];
|
||||
else
|
||||
{
|
||||
char name[16];
|
||||
ConvertUInt32ToString(BootMediaType, name);
|
||||
s += name;
|
||||
}
|
||||
s += ".img";
|
||||
return s;
|
||||
}
|
||||
bool Parse(const Byte *p);
|
||||
AString GetName() const;
|
||||
};
|
||||
|
||||
struct CVolumeDescriptor
|
||||
@@ -247,7 +252,6 @@ class CInArchive
|
||||
void SkipZeros(size_t size);
|
||||
Byte ReadByte();
|
||||
void ReadBytes(Byte *data, UInt32 size);
|
||||
UInt16 ReadUInt16Spec();
|
||||
UInt16 ReadUInt16();
|
||||
UInt32 ReadUInt32Le();
|
||||
UInt32 ReadUInt32Be();
|
||||
|
||||
@@ -29,7 +29,7 @@ struct CRecordingDateTime
|
||||
bool res = NWindows::NTime::GetSecondsSince1601(Year + 1900, Month, Day, Hour, Minute, Second, value);
|
||||
if (res)
|
||||
{
|
||||
value -= (UInt64)((Int64)GmtOffset * 15 * 60);
|
||||
value -= (Int64)((Int32)GmtOffset * 15 * 60);
|
||||
value *= 10000000;
|
||||
}
|
||||
ft.dwLowDateTime = (DWORD)value;
|
||||
@@ -94,28 +94,23 @@ struct CDirRecord
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned GetLenCur(bool checkSusp, int skipSize) const
|
||||
const Byte* GetNameCur(bool checkSusp, int skipSize, unsigned &nameLenRes) const
|
||||
{
|
||||
const Byte *res = NULL;
|
||||
unsigned len = 0;
|
||||
if (checkSusp)
|
||||
res = FindSuspName(skipSize, len);
|
||||
if (!res)
|
||||
{
|
||||
unsigned len;
|
||||
const Byte *res = FindSuspName(skipSize, len);
|
||||
if (res != 0)
|
||||
return len;
|
||||
res = (const Byte *)FileId;
|
||||
len = (unsigned)FileId.Size();
|
||||
}
|
||||
return (unsigned)FileId.Size();
|
||||
}
|
||||
|
||||
const Byte* GetNameCur(bool checkSusp, int skipSize) const
|
||||
{
|
||||
if (checkSusp)
|
||||
{
|
||||
unsigned len;
|
||||
const Byte *res = FindSuspName(skipSize, len);
|
||||
if (res != 0)
|
||||
return res;
|
||||
}
|
||||
return (const Byte *)FileId;
|
||||
unsigned i;
|
||||
for (i = 0; i < len; i++)
|
||||
if (res[i] == 0)
|
||||
break;
|
||||
nameLenRes = i;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -9,15 +9,13 @@
|
||||
namespace NArchive {
|
||||
namespace NIso {
|
||||
|
||||
IMP_CreateArcIn
|
||||
static const Byte k_Signature[] = { 'C', 'D', '0', '0', '1' };
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Iso", "iso img", 0, 0xE7,
|
||||
5, { 'C', 'D', '0', '0', '1' },
|
||||
REGISTER_ARC_I(
|
||||
"Iso", "iso img", 0, 0xE7,
|
||||
k_Signature,
|
||||
NArchive::NIso::kStartPos + 1,
|
||||
0,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Iso)
|
||||
NULL)
|
||||
|
||||
}}
|
||||
|
||||
@@ -660,8 +660,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = 0;
|
||||
CMyComPtr<ICompressCoder> lzhDecoder;
|
||||
CMyComPtr<ICompressCoder> lzh1Decoder;
|
||||
CMyComPtr<ICompressCoder> arj2Decoder;
|
||||
// CMyComPtr<ICompressCoder> lzh1Decoder;
|
||||
// CMyComPtr<ICompressCoder> arj2Decoder;
|
||||
|
||||
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
|
||||
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
|
||||
@@ -736,8 +736,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder;
|
||||
lzhDecoder = lzhDecoderSpec;
|
||||
}
|
||||
lzhDecoderSpec->SetDictionary(item.GetNumDictBits());
|
||||
lzhDecoderSpec->FinishMode = true;
|
||||
lzhDecoderSpec->SetDictSize(1 << item.GetNumDictBits());
|
||||
result = lzhDecoder->Code(inStream, outStream, NULL, ¤tItemUnPacked, progress);
|
||||
if (result == S_OK && lzhDecoderSpec->GetInputProcessedSize() != item.PackSize)
|
||||
result = S_FALSE;
|
||||
}
|
||||
/*
|
||||
else if (item.IsLh1GroupMethod())
|
||||
@@ -773,15 +776,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
static const Byte k_Signature[] = { '-', 'l', 'h' };
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Lzh", "lzh lha", 0, 6,
|
||||
3, { '-', 'l', 'h' },
|
||||
REGISTER_ARC_I(
|
||||
"Lzh", "lzh lha", 0, 6,
|
||||
k_Signature,
|
||||
2,
|
||||
0,
|
||||
CreateArc, NULL, IsArc_Lzh };
|
||||
|
||||
REGISTER_ARC(Lzh)
|
||||
IsArc_Lzh)
|
||||
|
||||
}}
|
||||
|
||||
@@ -9,11 +9,12 @@
|
||||
|
||||
#include "../../Windows/PropVariant.h"
|
||||
|
||||
#include "../Common/CreateCoder.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"
|
||||
@@ -75,14 +76,14 @@ bool CHeader::Parse(const Byte *buf, bool isThereFilter)
|
||||
|
||||
class CDecoder
|
||||
{
|
||||
CMyComPtr<ICompressCoder> _lzmaDecoder;
|
||||
CMyComPtr<ISequentialOutStream> _bcjStream;
|
||||
CFilterCoder *_filterCoder;
|
||||
CMyComPtr<ICompressCoder> _lzmaDecoder;
|
||||
public:
|
||||
NCompress::NLzma::CDecoder *_lzmaDecoderSpec;
|
||||
|
||||
~CDecoder();
|
||||
HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
bool filtered, ISequentialInStream *inStream);
|
||||
HRESULT Create(bool filtered, ISequentialInStream *inStream);
|
||||
|
||||
HRESULT Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress);
|
||||
|
||||
@@ -94,11 +95,7 @@ public:
|
||||
{ return _lzmaDecoderSpec->ReadFromInputStream(data, size, processedSize); }
|
||||
};
|
||||
|
||||
static const UInt32 k_BCJ = 0x03030103;
|
||||
|
||||
HRESULT CDecoder::Create(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
bool filteredMode, ISequentialInStream *inStream)
|
||||
HRESULT CDecoder::Create(bool filteredMode, ISequentialInStream *inStream)
|
||||
{
|
||||
if (!_lzmaDecoder)
|
||||
{
|
||||
@@ -111,13 +108,10 @@ HRESULT CDecoder::Create(
|
||||
{
|
||||
if (!_bcjStream)
|
||||
{
|
||||
CMyComPtr<ICompressCoder> coder;
|
||||
RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false));
|
||||
if (!coder)
|
||||
return E_NOTIMPL;
|
||||
coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream);
|
||||
if (!_bcjStream)
|
||||
return E_NOTIMPL;
|
||||
_filterCoder = new CFilterCoder(false);
|
||||
CMyComPtr<ICompressCoder> coder = _filterCoder;
|
||||
_filterCoder->Filter = new CBcjCoder(false);
|
||||
_bcjStream = _filterCoder;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,17 +137,13 @@ HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,
|
||||
RINOK(setDecoderProperties->SetDecoderProperties2(header.LzmaProps, 5));
|
||||
}
|
||||
|
||||
CMyComPtr<ICompressSetOutStream> setOutStream;
|
||||
|
||||
bool filteredMode = (header.FilterID == 1);
|
||||
|
||||
if (filteredMode)
|
||||
{
|
||||
_bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
|
||||
if (!setOutStream)
|
||||
return E_NOTIMPL;
|
||||
RINOK(setOutStream->SetOutStream(outStream));
|
||||
RINOK(_filterCoder->SetOutStream(outStream));
|
||||
outStream = _bcjStream;
|
||||
RINOK(_filterCoder->SetOutStreamSize(NULL));
|
||||
}
|
||||
|
||||
const UInt64 *Size = header.HasSize() ? &header.Size : NULL;
|
||||
@@ -161,18 +151,16 @@ HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,
|
||||
|
||||
if (filteredMode)
|
||||
{
|
||||
CMyComPtr<IOutStreamFlush> flush;
|
||||
_bcjStream.QueryInterface(IID_IOutStreamFlush, &flush);
|
||||
if (flush)
|
||||
{
|
||||
HRESULT res2 = flush->Flush();
|
||||
HRESULT res2 = _filterCoder->OutStreamFinish();
|
||||
if (res == S_OK)
|
||||
res = res2;
|
||||
}
|
||||
HRESULT res2 = setOutStream->ReleaseOutStream();
|
||||
HRESULT res2 = _filterCoder->ReleaseOutStream();
|
||||
if (res == S_OK)
|
||||
res = res2;
|
||||
}
|
||||
|
||||
RINOK(res);
|
||||
|
||||
if (header.HasSize())
|
||||
@@ -186,7 +174,6 @@ HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
public IArchiveOpenSeq,
|
||||
PUBLIC_ISetCompressCodecsInfo
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CHeader _header;
|
||||
@@ -210,15 +197,8 @@ class CHandler:
|
||||
UInt64 _unpackSize;
|
||||
UInt64 _numStreams;
|
||||
|
||||
DECL_EXTERNAL_CODECS_VARS
|
||||
DECL_ISetCompressCodecsInfo
|
||||
|
||||
public:
|
||||
MY_QUERYINTERFACE_BEGIN2(IInArchive)
|
||||
MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq)
|
||||
QUERY_ENTRY_ISetCompressCodecsInfo
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq)
|
||||
|
||||
INTERFACE_IInArchive(;)
|
||||
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
|
||||
@@ -427,6 +407,7 @@ 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))
|
||||
@@ -466,9 +447,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
_needSeekToStart = true;
|
||||
|
||||
CDecoder decoder;
|
||||
HRESULT result = decoder.Create(
|
||||
EXTERNAL_CODECS_VARS
|
||||
_lzma86, _seqStream);
|
||||
HRESULT result = decoder.Create(_lzma86, _seqStream);
|
||||
RINOK(result);
|
||||
|
||||
bool firstItem = true;
|
||||
@@ -562,43 +541,33 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
outStream.Release();
|
||||
return extractCallback->SetOperationResult(opResult);
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMPL_ISetCompressCodecsInfo
|
||||
|
||||
namespace NLzmaAr {
|
||||
|
||||
IMP_CreateArcIn_2(CHandler(false))
|
||||
// 2, { 0x5D, 0x00 },
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "lzma", "lzma", 0, 0xA,
|
||||
0, { 0 },
|
||||
// 2, { 0x5D, 0x00 },
|
||||
REGISTER_ARC_I_CLS_NO_SIG(
|
||||
CHandler(false),
|
||||
"lzma", "lzma", 0, 0xA,
|
||||
0,
|
||||
NArcInfoFlags::kStartOpen |
|
||||
NArcInfoFlags::kKeepName,
|
||||
CreateArc, NULL,
|
||||
IsArc_Lzma };
|
||||
|
||||
REGISTER_ARC(Lzma)
|
||||
|
||||
IsArc_Lzma)
|
||||
|
||||
}
|
||||
|
||||
namespace NLzma86Ar {
|
||||
|
||||
IMP_CreateArcIn_2(CHandler(true))
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "lzma86", "lzma86", 0, 0xB,
|
||||
0, { 0 },
|
||||
REGISTER_ARC_I_CLS_NO_SIG(
|
||||
CHandler(true),
|
||||
"lzma86", "lzma86", 0, 0xB,
|
||||
0,
|
||||
NArcInfoFlags::kKeepName,
|
||||
CreateArc, NULL,
|
||||
IsArc_Lzma86 };
|
||||
|
||||
REGISTER_ARC(Lzma86)
|
||||
|
||||
IsArc_Lzma86)
|
||||
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace NMacho {
|
||||
|
||||
#define CPU_SUBTYPE_POWERPC_970 100
|
||||
|
||||
static const char *k_PowerPc_SubTypes[] =
|
||||
static const char * const k_PowerPc_SubTypes[] =
|
||||
{
|
||||
NULL
|
||||
, "601"
|
||||
@@ -297,7 +297,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
ConvertUInt32ToString(t, temp);
|
||||
n = temp;
|
||||
}
|
||||
s += ' ';
|
||||
s.Add_Space();
|
||||
s += n;
|
||||
}
|
||||
prop = s;
|
||||
@@ -310,7 +310,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
AString s = FlagsToString(g_ArcFlags, ARRAY_SIZE(g_ArcFlags), _flags);
|
||||
if (!s.IsEmpty())
|
||||
{
|
||||
res += ' ';
|
||||
res.Add_Space();
|
||||
res += s;
|
||||
}
|
||||
prop = res;
|
||||
@@ -354,7 +354,7 @@ static AString SectFlagsToString(UInt32 flags)
|
||||
AString s = FlagsToString(g_Flags, ARRAY_SIZE(g_Flags), flags & SECT_ATTR_MASK);
|
||||
if (!s.IsEmpty())
|
||||
{
|
||||
res += ' ';
|
||||
res.Add_Space();
|
||||
res += s;
|
||||
}
|
||||
return res;
|
||||
@@ -643,22 +643,18 @@ STDMETHODIMP CHandler::AllowTail(Int32 allowTail)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
static const Byte k_Signature[] = {
|
||||
4, 0xCE, 0xFA, 0xED, 0xFE,
|
||||
4, 0xCF, 0xFA, 0xED, 0xFE,
|
||||
4, 0xFE, 0xED, 0xFA, 0xCE,
|
||||
4, 0xFE, 0xED, 0xFA, 0xCF };
|
||||
|
||||
#define k_Signature { \
|
||||
4, 0xCE, 0xFA, 0xED, 0xFE, \
|
||||
4, 0xCF, 0xFA, 0xED, 0xFE, \
|
||||
4, 0xFE, 0xED, 0xFA, 0xCE, \
|
||||
4, 0xFE, 0xED, 0xFA, 0xCF }
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "MachO", "macho", 0, 0xDF,
|
||||
4 * 5, k_Signature,
|
||||
REGISTER_ARC_I(
|
||||
"MachO", "macho", 0, 0xDF,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kMultiSignature |
|
||||
NArcInfoFlags::kPreArc,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Macho)
|
||||
NULL)
|
||||
|
||||
}}
|
||||
|
||||
@@ -169,7 +169,7 @@ static const CPartType kPartTypes[] =
|
||||
|
||||
static int FindPartType(UInt32 type)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(kPartTypes); i++)
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(kPartTypes); i++)
|
||||
if (kPartTypes[i].Id == type)
|
||||
return i;
|
||||
return -1;
|
||||
@@ -193,19 +193,19 @@ class CHandler:
|
||||
UInt64 _totalSize;
|
||||
CByteBuffer _buffer;
|
||||
|
||||
HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int level);
|
||||
HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level);
|
||||
public:
|
||||
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
|
||||
INTERFACE_IInArchive(;)
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
|
||||
};
|
||||
|
||||
HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int level)
|
||||
HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level)
|
||||
{
|
||||
if (level >= 128 || _items.Size() >= 128)
|
||||
return S_FALSE;
|
||||
|
||||
const int kNumHeaderParts = 4;
|
||||
const unsigned kNumHeaderParts = 4;
|
||||
CPartition parts[kNumHeaderParts];
|
||||
|
||||
{
|
||||
@@ -221,7 +221,7 @@ HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int
|
||||
if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA)
|
||||
return S_FALSE;
|
||||
|
||||
for (int i = 0; i < kNumHeaderParts; i++)
|
||||
for (unsigned i = 0; i < kNumHeaderParts; i++)
|
||||
if (!parts[i].Parse(buf + 0x1BE + 16 * i))
|
||||
return S_FALSE;
|
||||
}
|
||||
@@ -232,13 +232,13 @@ HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int
|
||||
if (limLba == 0)
|
||||
return S_FALSE;
|
||||
|
||||
for (int i = 0; i < kNumHeaderParts; i++)
|
||||
for (unsigned i = 0; i < kNumHeaderParts; i++)
|
||||
{
|
||||
CPartition &part = parts[i];
|
||||
|
||||
if (part.IsEmpty())
|
||||
continue;
|
||||
PRF(printf("\n %2d ", (int)level));
|
||||
PRF(printf("\n %2d ", (unsigned)level));
|
||||
#ifdef SHOW_DEBUG_INFO
|
||||
part.Print();
|
||||
#endif
|
||||
@@ -402,8 +402,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
int typeIndex = FindPartType(part.Type);
|
||||
s += '.';
|
||||
const char *ext = "img";
|
||||
if (typeIndex >= 0 && kPartTypes[typeIndex].Ext != 0)
|
||||
ext = kPartTypes[typeIndex].Ext;
|
||||
if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Ext)
|
||||
ext = kPartTypes[(unsigned)typeIndex].Ext;
|
||||
s += ext;
|
||||
}
|
||||
prop = s;
|
||||
@@ -416,8 +416,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
ConvertUInt32ToString(part.Type, s);
|
||||
const char *res = s;
|
||||
int typeIndex = FindPartType(part.Type);
|
||||
if (typeIndex >= 0 && kPartTypes[typeIndex].Name)
|
||||
res = kPartTypes[typeIndex].Name;
|
||||
if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Name)
|
||||
res = kPartTypes[(unsigned)typeIndex].Name;
|
||||
prop = res;
|
||||
}
|
||||
break;
|
||||
@@ -499,17 +499,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "MBR", "mbr", 0, 0xDB,
|
||||
// 3, { 1, 1, 0 },
|
||||
// 2, { 0x55, 0x1FF },
|
||||
0, { 0 },
|
||||
|
||||
REGISTER_ARC_I_NO_SIG(
|
||||
"MBR", "mbr", 0, 0xDB,
|
||||
0,
|
||||
NArcInfoFlags::kPureStartOpen,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Mbr)
|
||||
NULL)
|
||||
|
||||
}}
|
||||
|
||||
@@ -111,11 +111,13 @@ static const unsigned kHeaderSize = kSignatureSize + 1 + 4;
|
||||
static const Byte kSignature[kSignatureSize] = MSLZ_SIGNATURE;
|
||||
|
||||
// we support only 3 chars strings here
|
||||
static const char *g_Exts[] =
|
||||
static const char * const g_Exts[] =
|
||||
{
|
||||
"dll"
|
||||
"bin"
|
||||
, "dll"
|
||||
, "exe"
|
||||
, "kmd"
|
||||
, "pdf"
|
||||
, "sys"
|
||||
};
|
||||
|
||||
@@ -147,14 +149,15 @@ void CHandler::ParseName(Byte replaceByte, IArchiveOpenCallback *callback)
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(g_Exts); i++)
|
||||
{
|
||||
const char *ext = g_Exts[i];
|
||||
if (s[s.Len() - 2] == ext[0] &&
|
||||
s[s.Len() - 1] == ext[1])
|
||||
if (s[s.Len() - 2] == (Byte)ext[0] &&
|
||||
s[s.Len() - 1] == (Byte)ext[1])
|
||||
{
|
||||
replaceByte = ext[2];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (replaceByte >= 0x20 && replaceByte < 0x80)
|
||||
_name += (wchar_t)replaceByte;
|
||||
}
|
||||
@@ -225,6 +228,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn
|
||||
Byte buf[kBufSize];
|
||||
UInt32 dest = 0;
|
||||
memset(buf, ' ', kBufSize);
|
||||
|
||||
while (dest < unpackSize)
|
||||
{
|
||||
Byte b;
|
||||
@@ -233,6 +237,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn
|
||||
needMoreData = true;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
for (unsigned mask = (unsigned)b | 0x100; mask > 1 && dest < unpackSize; mask >>= 1)
|
||||
{
|
||||
if (!inStream.ReadByte(b))
|
||||
@@ -240,6 +245,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn
|
||||
needMoreData = true;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
if (mask & 1)
|
||||
{
|
||||
buf[dest++ & kMask] = b;
|
||||
@@ -258,6 +264,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn
|
||||
unsigned len = (b1 & 0xF) + 3;
|
||||
if (len > kMaxLen || dest + len > unpackSize)
|
||||
return S_FALSE;
|
||||
|
||||
do
|
||||
{
|
||||
buf[dest++ & kMask] = buf[src++ & kMask];
|
||||
@@ -267,6 +274,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (outStream)
|
||||
RINOK(WriteStream(outStream, buf, dest & kMask));
|
||||
return S_OK;
|
||||
@@ -379,15 +387,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "MsLZ", "mslz", 0, 0xD5,
|
||||
kSignatureSize, MSLZ_SIGNATURE,
|
||||
REGISTER_ARC_I(
|
||||
"MsLZ", "mslz", 0, 0xD5,
|
||||
kSignature,
|
||||
0,
|
||||
0,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Mslz)
|
||||
NULL)
|
||||
|
||||
}}
|
||||
|
||||
@@ -292,22 +292,18 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
|
||||
namespace NBe {
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Mub", "mub", 0, 0xE2,
|
||||
2 + 7 + 4,
|
||||
{
|
||||
static const Byte k_Signature[] = {
|
||||
7, 0xCA, 0xFE, 0xBA, 0xBE, 0, 0, 0,
|
||||
4, 0xB9, 0xFA, 0xF1, 0x0E
|
||||
},
|
||||
4, 0xB9, 0xFA, 0xF1, 0x0E };
|
||||
|
||||
REGISTER_ARC_I(
|
||||
"Mub", "mub", 0, 0xE2,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kMultiSignature,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Mub)
|
||||
NULL)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "NsisDecode.h"
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
#include "../../Common/FilterCoder.h"
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
#include "../../Common/MethodId.h"
|
||||
|
||||
@@ -58,18 +57,11 @@ HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter)
|
||||
{
|
||||
if (!_filterInStream)
|
||||
{
|
||||
CFilterCoder *coderSpec = new CFilterCoder;
|
||||
CMyComPtr<ICompressCoder> coder = coderSpec;
|
||||
coderSpec->Filter = new CBCJ_x86_Decoder();
|
||||
coder.QueryInterface(IID_ISequentialInStream, &_filterInStream);
|
||||
if (!_filterInStream)
|
||||
return E_NOTIMPL;
|
||||
_filter = new CFilterCoder(false);
|
||||
_filterInStream = _filter;
|
||||
_filter->Filter = new CBcjCoder(false);
|
||||
}
|
||||
CMyComPtr<ICompressSetInStream> setInStream;
|
||||
_filterInStream.QueryInterface(IID_ICompressSetInStream, &setInStream);
|
||||
if (!setInStream)
|
||||
return E_NOTIMPL;
|
||||
RINOK(setInStream->SetInStream(_codecInStream));
|
||||
RINOK(_filter->SetInStream(_codecInStream));
|
||||
_decoderInStream = _filterInStream;
|
||||
}
|
||||
|
||||
@@ -99,13 +91,7 @@ HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter)
|
||||
|
||||
if (useFilter)
|
||||
{
|
||||
/*
|
||||
CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
|
||||
_filterInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);
|
||||
if (!setOutStreamSize)
|
||||
return E_NOTIMPL;
|
||||
RINOK(setOutStreamSize->SetOutStreamSize(NULL));
|
||||
*/
|
||||
RINOK(_filter->SetOutStreamSize(NULL));
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "../../../Common/MyBuffer.h"
|
||||
|
||||
#include "../../Common/FilterCoder.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "../../Compress/LzmaDecoder.h"
|
||||
@@ -31,6 +32,7 @@ class CDecoder
|
||||
{
|
||||
NMethodType::EEnum _curMethod; // method of created decoder
|
||||
|
||||
CFilterCoder *_filter;
|
||||
CMyComPtr<ISequentialInStream> _filterInStream;
|
||||
CMyComPtr<ISequentialInStream> _codecInStream;
|
||||
CMyComPtr<ISequentialInStream> _decoderInStream;
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace NNsis {
|
||||
static const char *kBcjMethod = "BCJ";
|
||||
static const char *kUnknownMethod = "Unknown";
|
||||
|
||||
static const char *kMethods[] =
|
||||
static const char * const kMethods[] =
|
||||
{
|
||||
"Copy"
|
||||
, "Deflate"
|
||||
@@ -84,9 +84,9 @@ static AString GetMethod(bool useFilter, NMethodType::EEnum method, UInt32 dict)
|
||||
if (useFilter)
|
||||
{
|
||||
s += kBcjMethod;
|
||||
s += ' ';
|
||||
s.Add_Space();
|
||||
}
|
||||
s += (method < ARRAY_SIZE(kMethods)) ? kMethods[method] : kUnknownMethod;
|
||||
s += ((unsigned)method < ARRAY_SIZE(kMethods)) ? kMethods[(unsigned)method] : kUnknownMethod;
|
||||
if (method == NMethodType::kLZMA)
|
||||
{
|
||||
s += ':';
|
||||
@@ -102,7 +102,7 @@ AString CHandler::GetMethod(NMethodType::EEnum method, bool useItemFilter, UInt3
|
||||
if (_archive.IsSolid && _archive.UseFilter || !_archive.IsSolid && useItemFilter)
|
||||
{
|
||||
s += kBcjMethod;
|
||||
s += ' ';
|
||||
s.Add_Space();
|
||||
}
|
||||
s += (method < ARRAY_SIZE(kMethods)) ? kMethods[method] : kUnknownMethod;
|
||||
if (method == NMethodType::kLZMA)
|
||||
@@ -126,8 +126,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
AString s = _archive.GetFormatDescription();
|
||||
if (!_archive.IsInstaller)
|
||||
{
|
||||
if (!s.IsEmpty())
|
||||
s += ' ';
|
||||
s.Add_Space_if_NotEmpty();
|
||||
s += "(Uninstall)";
|
||||
}
|
||||
if (!s.IsEmpty())
|
||||
@@ -138,8 +137,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
case kpidMethod: prop = _methodString; break;
|
||||
case kpidSolid: prop = _archive.IsSolid; break;
|
||||
case kpidOffset: prop = _archive.StartOffset; break;
|
||||
case kpidPhySize: prop = _archive.ExeStub.Size() + _archive.FirstHeader.ArcSize; break;
|
||||
case kpidEmbeddedStubSize: prop = _archive.ExeStub.Size(); break;
|
||||
case kpidPhySize: prop = (UInt64)((UInt64)_archive.ExeStub.Size() + _archive.FirstHeader.ArcSize); break;
|
||||
case kpidEmbeddedStubSize: prop = (UInt64)_archive.ExeStub.Size(); break;
|
||||
case kpidHeadersSize: prop = _archive.FirstHeader.HeaderSize; break;
|
||||
|
||||
case kpidErrorFlags:
|
||||
@@ -611,7 +610,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
HRESULT res = _archive.Decoder.Decode(
|
||||
writeToTemp1 ? &tempBuf : NULL,
|
||||
item.IsUninstaller, item.PatchSize,
|
||||
item.IsUninstaller ? NULL : realOutStream,
|
||||
item.IsUninstaller ? NULL : (ISequentialOutStream *)realOutStream,
|
||||
progress,
|
||||
curPacked, curUnpacked32);
|
||||
curUnpacked = curUnpacked32;
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace NNsis {
|
||||
|
||||
static const size_t kInputBufSize = 1 << 20;
|
||||
|
||||
static const Byte kSignature[kSignatureSize] = NSIS_SIGNATURE;
|
||||
const Byte kSignature[kSignatureSize] = NSIS_SIGNATURE;
|
||||
static const UInt32 kMask_IsCompressed = (UInt32)1 << 31;
|
||||
|
||||
static const unsigned kNumCommandParams = 6;
|
||||
@@ -30,7 +30,7 @@ static const unsigned kCmdSize = 4 + kNumCommandParams * 4;
|
||||
#define CR_LF "\x0D\x0A"
|
||||
#endif
|
||||
|
||||
static const char *kErrorStr = "$_ERROR_STR_";
|
||||
static const char * const kErrorStr = "$_ERROR_STR_";
|
||||
|
||||
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
|
||||
|
||||
@@ -244,7 +244,7 @@ static const CCommandInfo k_Commands[kNumCmds] =
|
||||
|
||||
#ifdef NSIS_SCRIPT
|
||||
|
||||
static const char *k_CommandNames[kNumCmds] =
|
||||
static const char * const k_CommandNames[kNumCmds] =
|
||||
{
|
||||
"Invalid"
|
||||
, NULL // Return
|
||||
@@ -331,7 +331,7 @@ static const char *k_CommandNames[kNumCmds] =
|
||||
Some NSIS shell names are not identical to WIN32 CSIDL_* names.
|
||||
NSIS doesn't use some CSIDL_* values. But we add name for all CSIDL_ (marked with '+'). */
|
||||
|
||||
static const char *kShellStrings[] =
|
||||
static const char * const kShellStrings[] =
|
||||
{
|
||||
"DESKTOP" // +
|
||||
, "INTERNET" // +
|
||||
@@ -526,7 +526,7 @@ void CInArchive::AddLicense(UInt32 param, Int32 langID)
|
||||
#define kVar_Spec_OUTDIR 31 // NSIS 2.26+
|
||||
|
||||
|
||||
static const char *kVarStrings[] =
|
||||
static const char * const kVarStrings[] =
|
||||
{
|
||||
"CMDLINE"
|
||||
, "INSTDIR"
|
||||
@@ -963,8 +963,7 @@ void CInArchive::GetNsisString_Unicode_Raw(const Byte *p)
|
||||
else // if (c == PARK_CODE_LANG)
|
||||
Add_LangStr(Raw_AString, n);
|
||||
}
|
||||
for (const Byte *s = (const Byte *)(const char *)Raw_AString; *s != 0; s++)
|
||||
Raw_UString += *s;
|
||||
Raw_UString.AddAscii(Raw_AString);
|
||||
continue;
|
||||
}
|
||||
c = n;
|
||||
@@ -1010,8 +1009,7 @@ void CInArchive::GetNsisString_Unicode_Raw(const Byte *p)
|
||||
else // if (c == NS_3_CODE_LANG)
|
||||
Add_LangStr(Raw_AString, n);
|
||||
}
|
||||
for (const Byte *s = (const Byte *)(const char *)Raw_AString; *s != 0; s++)
|
||||
Raw_UString += (wchar_t)*s;
|
||||
Raw_UString.AddAscii(Raw_AString);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1147,8 +1145,7 @@ void CInArchive::ReadString2_Raw(UInt32 pos)
|
||||
GetNsisString_Raw(_data + _stringsPos + pos);
|
||||
return;
|
||||
}
|
||||
for (const char *s = (const char *)Raw_AString; *s != 0; s++)
|
||||
Raw_UString += *s;
|
||||
Raw_UString.SetFromAscii(Raw_AString);
|
||||
}
|
||||
|
||||
bool CInArchive::IsGoodString(UInt32 param) const
|
||||
@@ -1417,7 +1414,7 @@ static const char *g_WinAttrib[] =
|
||||
|
||||
#define FLAGS_DELIMITER '|'
|
||||
|
||||
static void FlagsToString2(CDynLimBuf &s, const char **table, unsigned num, UInt32 flags)
|
||||
static void FlagsToString2(CDynLimBuf &s, const char * const *table, unsigned num, UInt32 flags)
|
||||
{
|
||||
bool filled = false;
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
@@ -1536,7 +1533,7 @@ inline bool IsProbablyEndOfFunc(UInt32 flag)
|
||||
return (flag != 0 && flag != CMD_REF_Goto);
|
||||
}
|
||||
|
||||
static const char *kOnFunc[] =
|
||||
static const char * const kOnFunc[] =
|
||||
{
|
||||
"Init"
|
||||
, "InstSuccess"
|
||||
@@ -1622,12 +1619,12 @@ static bool NoLabels(const UInt32 *labels, UInt32 num)
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *k_REBOOTOK = " /REBOOTOK";
|
||||
static const char * const k_REBOOTOK = " /REBOOTOK";
|
||||
|
||||
#define MY__MB_ABORTRETRYIGNORE 2
|
||||
#define MY__MB_RETRYCANCEL 5
|
||||
|
||||
static const char *k_MB_Buttons[] =
|
||||
static const char * const k_MB_Buttons[] =
|
||||
{
|
||||
"OK"
|
||||
, "OKCANCEL"
|
||||
@@ -1640,7 +1637,7 @@ static const char *k_MB_Buttons[] =
|
||||
|
||||
#define MY__MB_ICONSTOP (1 << 4)
|
||||
|
||||
static const char *k_MB_Icons[] =
|
||||
static const char * const k_MB_Icons[] =
|
||||
{
|
||||
NULL
|
||||
, "ICONSTOP"
|
||||
@@ -1649,7 +1646,7 @@ static const char *k_MB_Icons[] =
|
||||
, "ICONINFORMATION"
|
||||
};
|
||||
|
||||
static const char *k_MB_Flags[] =
|
||||
static const char * const k_MB_Flags[] =
|
||||
{
|
||||
"HELP"
|
||||
, "NOFOCUS"
|
||||
@@ -1664,7 +1661,7 @@ static const char *k_MB_Flags[] =
|
||||
#define MY__IDCANCEL 2
|
||||
#define MY__IDIGNORE 5
|
||||
|
||||
static const char *k_Button_IDs[] =
|
||||
static const char * const k_Button_IDs[] =
|
||||
{
|
||||
"0"
|
||||
, "IDOK"
|
||||
@@ -1702,31 +1699,6 @@ bool CInArchive::IsDirectString_Equal(UInt32 offset, const char *s) const
|
||||
return strcmp((const char *)(const Byte *)_data + _stringsPos + offset, s) == 0;
|
||||
}
|
||||
|
||||
static UInt32 ConvertHexStringToUInt32(const char *s, const char **end)
|
||||
{
|
||||
UInt32 result = 0;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
char c = *s;
|
||||
UInt32 v;
|
||||
if (c >= '0' && c <= '9') v = (c - '0');
|
||||
else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A');
|
||||
else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a');
|
||||
else
|
||||
{
|
||||
if (end != NULL)
|
||||
*end = s;
|
||||
return result;
|
||||
}
|
||||
result <<= 4;
|
||||
result |= v;
|
||||
s++;
|
||||
}
|
||||
if (end != NULL)
|
||||
*end = s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool StringToUInt32(const char *s, UInt32 &res)
|
||||
{
|
||||
const char *end;
|
||||
@@ -1816,7 +1788,7 @@ void CInArchive::Add_Color(UInt32 v)
|
||||
#define MY__SW_SHOWMINNOACTIVE 7
|
||||
#define MY__SW_SHOWNA 8
|
||||
|
||||
static const char *kShowWindow_Commands[] =
|
||||
static const char * const kShowWindow_Commands[] =
|
||||
{
|
||||
"HIDE"
|
||||
, "SHOWNORMAL" // "NORMAL"
|
||||
@@ -1854,7 +1826,7 @@ void CInArchive::Add_ShowWindow_Cmd(UInt32 cmd)
|
||||
Add_UInt(cmd);
|
||||
}
|
||||
|
||||
void CInArchive::Add_TypeFromList(const char **table, unsigned tableSize, UInt32 type)
|
||||
void CInArchive::Add_TypeFromList(const char * const *table, unsigned tableSize, UInt32 type)
|
||||
{
|
||||
if (type < tableSize)
|
||||
Script += table[type];
|
||||
@@ -1886,7 +1858,7 @@ enum
|
||||
};
|
||||
|
||||
// Names for NSIS exec_flags_t structure vars
|
||||
static const char *kExecFlags_VarsNames[] =
|
||||
static const char * const kExecFlags_VarsNames[] =
|
||||
{
|
||||
"AutoClose" // autoclose;
|
||||
, "ShellVarContext" // all_user_var;
|
||||
@@ -1940,7 +1912,7 @@ enum
|
||||
PWP_CUSTOM
|
||||
};
|
||||
|
||||
static const char *kPageTypes[] =
|
||||
static const char * const kPageTypes[] =
|
||||
{
|
||||
"license"
|
||||
, "components"
|
||||
@@ -2062,7 +2034,7 @@ void CInArchive::AddStringLF(const char *s)
|
||||
|
||||
// ---------- Section ----------
|
||||
|
||||
static const char *kSection_VarsNames[] =
|
||||
static const char * const kSection_VarsNames[] =
|
||||
{
|
||||
"Text"
|
||||
, "InstTypes"
|
||||
@@ -2240,7 +2212,7 @@ void CInArchive::NewLine()
|
||||
|
||||
static const UInt32 kPageSize = 16 * 4;
|
||||
|
||||
static const char *k_SetOverwrite_Modes[] =
|
||||
static const char * const k_SetOverwrite_Modes[] =
|
||||
{
|
||||
"on"
|
||||
, "off"
|
||||
@@ -2294,7 +2266,7 @@ void CInArchive::MessageBox_MB_Part(UInt32 param)
|
||||
else if (modal == 2) Script += "|MB_TASKMODAL";
|
||||
else if (modal == 3) Script += "|0x3000";
|
||||
UInt32 flags = (param >> 14);
|
||||
for (int i = 0; i < ARRAY_SIZE(k_MB_Flags); i++)
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(k_MB_Flags); i++)
|
||||
if ((flags & (1 << i)) != 0)
|
||||
{
|
||||
Script += "|MB_";
|
||||
@@ -2327,8 +2299,7 @@ static const UInt32 kSectionSize_16bit_Big = kSectionSize_base + 8196 * 2;
|
||||
|
||||
static void AddString(AString &dest, const char *src)
|
||||
{
|
||||
if (!dest.IsEmpty())
|
||||
dest += ' ';
|
||||
dest.Add_Space_if_NotEmpty();
|
||||
dest += src;
|
||||
}
|
||||
|
||||
@@ -3133,7 +3104,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
|
||||
}
|
||||
default: continue;
|
||||
}
|
||||
for (int i = 0; mask != 0; i++, mask >>= 1)
|
||||
for (unsigned i = 0; mask != 0; i++, mask >>= 1)
|
||||
if (mask & 1)
|
||||
{
|
||||
UInt32 param = Get32(p + 4 + 4 * i);
|
||||
@@ -3535,17 +3506,11 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
|
||||
pars[i] = Get32(p2 + i * 4 + 4);
|
||||
if (pars[0] == 10 + 4 && pars[2] == 0 && pars[3] == 0) // 10 + 4 means $R4
|
||||
{
|
||||
ReadString2_Raw(pars[1]);
|
||||
if (IsUnicode)
|
||||
{
|
||||
if (!Raw_UString.IsEmpty())
|
||||
item.NameU = Raw_UString;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Raw_AString.IsEmpty())
|
||||
item.NameA = Raw_AString;
|
||||
}
|
||||
item.Prefix = -1;
|
||||
item.NameA.Empty();
|
||||
item.NameU.Empty();
|
||||
SetItemName(item, pars[1]);
|
||||
// maybe here we can restore original item name, if new name is empty
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5011,7 +4976,7 @@ HRESULT CInArchive::SortItems()
|
||||
#define CH_FLAGS_COMP_ONLY_ON_CUSTOM 256
|
||||
#define CH_FLAGS_NO_CUSTOM 512
|
||||
|
||||
static const char *k_PostStrings[] =
|
||||
static const char * const k_PostStrings[] =
|
||||
{
|
||||
"install_directory_auto_append"
|
||||
, "uninstchild" // NSIS 2.25+, used by uninstaller:
|
||||
@@ -5242,7 +5207,7 @@ HRESULT CInArchive::Parse()
|
||||
AddRegRoot(rootKey);
|
||||
AddParam(subKey);
|
||||
AddParam(value);
|
||||
NewLine();
|
||||
AddLF();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5296,6 +5261,9 @@ HRESULT CInArchive::Parse()
|
||||
UInt32 langtable_size = Get32(p2 + 32);
|
||||
if (bhLangTables.Num > 0)
|
||||
{
|
||||
if (langtable_size == (UInt32)(Int32)-1)
|
||||
return E_NOTIMPL; // maybe it's old NSIS archive()
|
||||
|
||||
UInt32 numStrings = (langtable_size - 10) / 4;
|
||||
_numLangStrings = numStrings;
|
||||
AddLF();
|
||||
@@ -5310,7 +5278,7 @@ HRESULT CInArchive::Parse()
|
||||
{
|
||||
const Byte *p = _data + bhLangTables.Offset + langtable_size * i;
|
||||
LANGID langID = Get16(p);
|
||||
UInt32 val = Get32(p + 10 + licenseLangIndex * 4);
|
||||
UInt32 val = Get32(p + 10 + (UInt32)licenseLangIndex * 4);
|
||||
if (val != 0)
|
||||
{
|
||||
Script += "LicenseLangString ";
|
||||
@@ -5902,6 +5870,7 @@ void CInArchive::Clear2()
|
||||
Script.Empty();
|
||||
LicenseFiles.Clear();
|
||||
_numRootLicenses = 0;
|
||||
_numLangStrings = 0;
|
||||
langStrIDs.Clear();
|
||||
LangComment.Empty();
|
||||
noParseStringIndexes.Clear();
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace NNsis {
|
||||
const size_t kScriptSizeLimit = 1 << 27;
|
||||
|
||||
const unsigned kSignatureSize = 16;
|
||||
extern const Byte kSignature[kSignatureSize];
|
||||
#define NSIS_SIGNATURE { 0xEF, 0xBE, 0xAD, 0xDE, 'N', 'u', 'l', 'l', 's', 'o', 'f', 't', 'I', 'n', 's', 't' }
|
||||
|
||||
const UInt32 kFlagsMask = 0xF;
|
||||
@@ -261,7 +262,7 @@ private:
|
||||
void Add_ButtonID(UInt32 buttonID);
|
||||
|
||||
void Add_ShowWindow_Cmd(UInt32 cmd);
|
||||
void Add_TypeFromList(const char **table, unsigned tableSize, UInt32 type);
|
||||
void Add_TypeFromList(const char * const *table, unsigned tableSize, UInt32 type);
|
||||
void Add_ExecFlags(UInt32 flagsType);
|
||||
void Add_SectOp(UInt32 opType);
|
||||
|
||||
|
||||
@@ -9,16 +9,12 @@
|
||||
namespace NArchive {
|
||||
namespace NNsis {
|
||||
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Nsis", "nsis", 0, 0x9,
|
||||
NArchive::NNsis::kSignatureSize, NSIS_SIGNATURE,
|
||||
REGISTER_ARC_I(
|
||||
"Nsis", "nsis", 0, 0x9,
|
||||
kSignature,
|
||||
4,
|
||||
NArcInfoFlags::kFindSignature |
|
||||
NArcInfoFlags::kUseGlobalOffset,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Nsis)
|
||||
NULL)
|
||||
|
||||
}}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -37,7 +37,7 @@ using namespace NWindows;
|
||||
namespace NArchive {
|
||||
namespace NPe {
|
||||
|
||||
static const UInt32 k_Signature = 0x00004550;
|
||||
static const UInt32 k_Signature32 = 0x00004550;
|
||||
|
||||
static HRESULT CalcCheckSum(ISequentialInStream *stream, UInt32 size, UInt32 excludePos, UInt32 &res)
|
||||
{
|
||||
@@ -137,7 +137,7 @@ struct CHeader
|
||||
|
||||
bool CHeader::Parse(const Byte *p)
|
||||
{
|
||||
if (Get32(p) != k_Signature)
|
||||
if (Get32(p) != k_Signature32)
|
||||
return false;
|
||||
p += 4;
|
||||
G16( 0, Machine);
|
||||
@@ -364,19 +364,14 @@ struct CSection
|
||||
|
||||
static const unsigned kNameSize = 8;
|
||||
|
||||
static AString GetName(const Byte *name)
|
||||
static void GetName(const Byte *name, AString &res)
|
||||
{
|
||||
AString res;
|
||||
char *p = res.GetBuffer(kNameSize);
|
||||
memcpy(p, name, kNameSize);
|
||||
p[kNameSize] = 0;
|
||||
res.ReleaseBuffer();
|
||||
return res;
|
||||
res.SetFrom_CalcLen((const char *)name, kNameSize);
|
||||
}
|
||||
|
||||
void CSection::Parse(const Byte *p)
|
||||
{
|
||||
Name = GetName(p);
|
||||
GetName(p, Name);
|
||||
G32( 8, VSize);
|
||||
G32(12, Va);
|
||||
G32(16, PSize);
|
||||
@@ -484,33 +479,33 @@ static const CUInt32PCharPair g_SubSystems[] =
|
||||
{ 14, "XBOX" }
|
||||
};
|
||||
|
||||
static const wchar_t *g_ResTypes[] =
|
||||
static const char * const g_ResTypes[] =
|
||||
{
|
||||
NULL
|
||||
, L"CURSOR"
|
||||
, L"BITMAP"
|
||||
, L"ICON"
|
||||
, L"MENU"
|
||||
, L"DIALOG"
|
||||
, L"STRING"
|
||||
, L"FONTDIR"
|
||||
, L"FONT"
|
||||
, L"ACCELERATOR"
|
||||
, L"RCDATA"
|
||||
, L"MESSAGETABLE"
|
||||
, L"GROUP_CURSOR"
|
||||
, "CURSOR"
|
||||
, "BITMAP"
|
||||
, "ICON"
|
||||
, "MENU"
|
||||
, "DIALOG"
|
||||
, "STRING"
|
||||
, "FONTDIR"
|
||||
, "FONT"
|
||||
, "ACCELERATOR"
|
||||
, "RCDATA"
|
||||
, "MESSAGETABLE"
|
||||
, "GROUP_CURSOR"
|
||||
, NULL
|
||||
, L"GROUP_ICON"
|
||||
, "GROUP_ICON"
|
||||
, NULL
|
||||
, L"VERSION"
|
||||
, L"DLGINCLUDE"
|
||||
, "VERSION"
|
||||
, "DLGINCLUDE"
|
||||
, NULL
|
||||
, L"PLUGPLAY"
|
||||
, L"VXD"
|
||||
, L"ANICURSOR"
|
||||
, L"ANIICON"
|
||||
, L"HTML"
|
||||
, L"MANIFEST"
|
||||
, "PLUGPLAY"
|
||||
, "VXD"
|
||||
, "ANICURSOR"
|
||||
, "ANIICON"
|
||||
, "HTML"
|
||||
, "MANIFEST"
|
||||
};
|
||||
|
||||
static const UInt32 kFlag = (UInt32)1 << 31;
|
||||
@@ -561,7 +556,10 @@ struct CTextFile
|
||||
void NewLine();
|
||||
void AddString(const char *s);
|
||||
void AddSpaces(int num);
|
||||
void AddBytes(const Byte *p, size_t len);
|
||||
void AddBytes(const Byte *p, size_t size)
|
||||
{
|
||||
Buf.AddData(p, size);
|
||||
}
|
||||
|
||||
void OpenBlock(int num)
|
||||
{
|
||||
@@ -623,12 +621,6 @@ void CTextFile::AddSpaces(int num)
|
||||
AddChar(' ');
|
||||
}
|
||||
|
||||
void CTextFile::AddBytes(const Byte *data, size_t size)
|
||||
{
|
||||
Byte *p = Buf.GetCurPtrAndGrow(size);
|
||||
memcpy(p, data, size);
|
||||
}
|
||||
|
||||
struct CStringItem: public CTextFile
|
||||
{
|
||||
UInt32 Lang;
|
||||
@@ -648,7 +640,7 @@ struct CMixItem
|
||||
int VersionIndex;
|
||||
|
||||
CMixItem(): SectionIndex(-1), ResourceIndex(-1), StringIndex(-1), VersionIndex(-1) {}
|
||||
bool IsSectionItem() const { return ResourceIndex < 0 && StringIndex < 0 && VersionIndex < 0; };
|
||||
bool IsSectionItem() const { return ResourceIndex < 0 && StringIndex < 0 && VersionIndex < 0; }
|
||||
};
|
||||
|
||||
struct CUsedBitmap
|
||||
@@ -802,6 +794,7 @@ static const STATPROPSTG kArcProps[] =
|
||||
{ (LPOLESTR)L"Heap Commit", kpidHeapCommit, VT_UI8},
|
||||
{ (LPOLESTR)L"Image Base", kpidImageBase, VT_UI8},
|
||||
{ NULL, kpidComment, VT_BSTR},
|
||||
|
||||
// { (LPOLESTR)L"Address Of Entry Point", kpidAddressOfEntryPoint, VT_UI8},
|
||||
// { (LPOLESTR)L"Base Of Code", kpidBaseOfCode, VT_UI8},
|
||||
// { (LPOLESTR)L"Base Of Data", kpidBaseOfData32, VT_UI8},
|
||||
@@ -913,7 +906,7 @@ HRESULT CHandler::ReadString(UInt32 offset, UString &dest) const
|
||||
if ((rem - 2) / 2 < len)
|
||||
return S_FALSE;
|
||||
dest.Empty();
|
||||
wchar_t *destBuf = dest.GetBuffer(len);
|
||||
wchar_t *destBuf = dest.GetBuf(len);
|
||||
offset += 2;
|
||||
const Byte *src = _buf + offset;
|
||||
unsigned i;
|
||||
@@ -924,7 +917,8 @@ HRESULT CHandler::ReadString(UInt32 offset, UString &dest) const
|
||||
break;
|
||||
destBuf[i] = c;
|
||||
}
|
||||
dest.ReleaseBuffer(i);
|
||||
destBuf[i] = 0;
|
||||
dest.ReleaseBuf_SetLen(i);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -960,7 +954,7 @@ void CHandler::AddLangPrefix(UString &s, UInt32 lang) const
|
||||
if (!_oneLang)
|
||||
{
|
||||
AddResNameToString(s, lang);
|
||||
s += WCHAR_PATH_SEPARATOR;
|
||||
s.Add_PathSepar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -978,7 +972,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
{
|
||||
UString s = _resourcesPrefix;
|
||||
AddLangPrefix(s, item.Lang);
|
||||
s += L"string.txt";
|
||||
s.AddAscii("string.txt");
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
@@ -996,7 +990,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
{
|
||||
UString s = _resourcesPrefix;
|
||||
AddLangPrefix(s, item.Lang);
|
||||
s += L"version.txt";
|
||||
s.AddAscii("version.txt");
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
@@ -1015,22 +1009,22 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
UString s = _resourcesPrefix;
|
||||
AddLangPrefix(s, item.Lang);
|
||||
{
|
||||
const wchar_t *p = NULL;
|
||||
const char *p = NULL;
|
||||
if (item.Type < ARRAY_SIZE(g_ResTypes))
|
||||
p = g_ResTypes[item.Type];
|
||||
if (p)
|
||||
s += p;
|
||||
s.AddAscii(p);
|
||||
else
|
||||
AddResNameToString(s, item.Type);
|
||||
}
|
||||
s += WCHAR_PATH_SEPARATOR;
|
||||
s.Add_PathSepar();
|
||||
AddResNameToString(s, item.ID);
|
||||
if (item.HeaderSize != 0)
|
||||
{
|
||||
if (item.IsBmp())
|
||||
s += L".bmp";
|
||||
s.AddAscii(".bmp");
|
||||
else if (item.IsIcon())
|
||||
s += L".ico";
|
||||
s.AddAscii(".ico");
|
||||
}
|
||||
prop = s;
|
||||
break;
|
||||
@@ -1199,11 +1193,14 @@ static UInt32 SetBitmapHeader(Byte *dest, const Byte *src, UInt32 size)
|
||||
return 0;
|
||||
if (h.YSize < 0)
|
||||
h.YSize = -h.YSize;
|
||||
if (h.XSize > (1 << 26) || h.YSize > (1 << 26) || h.Planes != 1 || h.BitCount > 32 ||
|
||||
h.Compression != 0) // BI_RGB
|
||||
if (h.XSize > (1 << 26) || h.YSize > (1 << 26) || h.Planes != 1 || h.BitCount > 32)
|
||||
return 0;
|
||||
if (h.SizeImage == 0)
|
||||
{
|
||||
if (h.Compression != 0) // BI_RGB
|
||||
return 0;
|
||||
h.SizeImage = GetImageSize(h.XSize, h.YSize, h.BitCount);
|
||||
}
|
||||
UInt32 totalSize = kBmpHeaderSize + size;
|
||||
UInt32 offBits = totalSize - h.SizeImage;
|
||||
// BITMAPFILEHEADER
|
||||
@@ -1413,7 +1410,7 @@ static void PrintVersion(UString &s, UInt32 ms, UInt32 ls)
|
||||
PrintUInt32(s, LOWORD(ls));
|
||||
}
|
||||
|
||||
static const char *k_VS_FileFlags[] =
|
||||
static const char * const k_VS_FileFlags[] =
|
||||
{
|
||||
"DEBUG"
|
||||
, "PRERELEASE"
|
||||
@@ -1432,7 +1429,7 @@ static const CUInt32PCharPair k_VS_FileOS[] =
|
||||
{ 0x40004, "VOS_NT_WINDOWS32" }
|
||||
};
|
||||
|
||||
static const char *k_VS_FileOS_High[] =
|
||||
static const char * const k_VS_FileOS_High[] =
|
||||
{
|
||||
"VOS_UNKNOWN"
|
||||
, "VOS_DOS"
|
||||
@@ -1445,7 +1442,7 @@ static const char *k_VS_FileOS_High[] =
|
||||
static const UInt32 kMY_VFT_DRV = 3;
|
||||
static const UInt32 kMY_VFT_FONT = 4;
|
||||
|
||||
static const char *k_VS_FileOS_Low[] =
|
||||
static const char * const k_VS_FileOS_Low[] =
|
||||
{
|
||||
"VOS__BASE"
|
||||
, "VOS__WINDOWS16"
|
||||
@@ -1454,7 +1451,7 @@ static const char *k_VS_FileOS_Low[] =
|
||||
, "VOS__WINDOWS32"
|
||||
};
|
||||
|
||||
static const char *k_VS_FileType[] =
|
||||
static const char * const k_VS_FileType[] =
|
||||
{
|
||||
"VFT_UNKNOWN"
|
||||
, "VFT_APP"
|
||||
@@ -1467,7 +1464,7 @@ static const char *k_VS_FileType[] =
|
||||
};
|
||||
|
||||
// Subtype for VFT_DRV Type
|
||||
static const char *k_VS_FileSubType_DRV[] =
|
||||
static const char * const k_VS_FileSubType_DRV[] =
|
||||
{
|
||||
"0"
|
||||
, "PRINTER"
|
||||
@@ -1485,7 +1482,7 @@ static const char *k_VS_FileSubType_DRV[] =
|
||||
};
|
||||
|
||||
// Subtype for VFT_FONT Type
|
||||
static const char *k_VS_FileSubType_FONT[] =
|
||||
static const char * const k_VS_FileSubType_FONT[] =
|
||||
{
|
||||
"0"
|
||||
, "VFT2_FONT_RASTER"
|
||||
@@ -1493,10 +1490,10 @@ static const char *k_VS_FileSubType_FONT[] =
|
||||
, "VFT2_FONT_TRUETYPE"
|
||||
};
|
||||
|
||||
static int FindKey(CObjectVector<CStringKeyValue> &v, const UString &key)
|
||||
static int FindKey(CObjectVector<CStringKeyValue> &v, const char *key)
|
||||
{
|
||||
FOR_VECTOR (i, v)
|
||||
if (v[i].Key == key)
|
||||
if (v[i].Key.IsEqualTo(key))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
@@ -1665,7 +1662,7 @@ struct CVersionBlock
|
||||
UInt32 TotalLen;
|
||||
UInt32 ValueLen;
|
||||
bool IsTextValue;
|
||||
int StrSize;
|
||||
unsigned StrSize;
|
||||
|
||||
bool Parse(const Byte *p, UInt32 size);
|
||||
};
|
||||
@@ -1691,7 +1688,7 @@ bool CVersionBlock::Parse(const Byte *p, UInt32 size)
|
||||
return false;
|
||||
TotalLen = Get16(p);
|
||||
ValueLen = Get16(p + 2);
|
||||
if (TotalLen > size)
|
||||
if (TotalLen == 0 || TotalLen > size)
|
||||
return false;
|
||||
switch (Get16(p + 4))
|
||||
{
|
||||
@@ -1699,8 +1696,12 @@ bool CVersionBlock::Parse(const Byte *p, UInt32 size)
|
||||
case 1: IsTextValue = true; break;
|
||||
default: return false;
|
||||
}
|
||||
StrSize = Get_Utf16Str_Len_InBytes(p + k_ResoureBlockHeader_Size, TotalLen - k_ResoureBlockHeader_Size);
|
||||
return StrSize >= 0;
|
||||
StrSize = 0;
|
||||
int t = Get_Utf16Str_Len_InBytes(p + k_ResoureBlockHeader_Size, TotalLen - k_ResoureBlockHeader_Size);
|
||||
if (t < 0)
|
||||
return false;
|
||||
StrSize = t;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void AddParamString(CTextFile &f, const Byte *p, size_t sLen)
|
||||
@@ -1868,7 +1869,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
|
||||
int sLen = Get_Utf16Str_Len_InBytes(p + pos, endPos3 - pos);
|
||||
if (sLen < 0)
|
||||
return false;
|
||||
AddParamString(f, p + pos, sLen);
|
||||
AddParamString(f, p + pos, (unsigned)sLen);
|
||||
CopyToUString(p + pos, value);
|
||||
pos += sLen + 2;
|
||||
}
|
||||
@@ -2276,6 +2277,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
// _parseResources = false;
|
||||
|
||||
UInt64 mainSize = 0, mainSize2 = 0;
|
||||
|
||||
for (i = 0; i < _sections.Size(); i++)
|
||||
{
|
||||
const CSection § = _sections[i];
|
||||
@@ -2287,7 +2289,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
if (res == S_OK)
|
||||
{
|
||||
_resourcesPrefix.SetFromAscii(sect.Name);
|
||||
_resourcesPrefix += WCHAR_PATH_SEPARATOR;
|
||||
_resourcesPrefix.Add_PathSepar();
|
||||
FOR_VECTOR (j, _items)
|
||||
{
|
||||
const CResItem &item = _items[j];
|
||||
@@ -2348,7 +2350,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
mainSize = sect.PSize;
|
||||
_mainSubfile = _mixItems.Size();
|
||||
}
|
||||
else
|
||||
else if (sect.PSize >= mainSize2)
|
||||
mainSize2 = sect.PSize;
|
||||
}
|
||||
_mixItems.Add(mixItem);
|
||||
@@ -2370,7 +2372,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
for (i = 0; i < _versionKeys.Size(); i++)
|
||||
{
|
||||
if (i != 0)
|
||||
_versionFullString += L'\n';
|
||||
_versionFullString.Add_LF();
|
||||
const CStringKeyValue &k = _versionKeys[i];
|
||||
_versionFullString += k.Key;
|
||||
_versionFullString += L": ";
|
||||
@@ -2378,20 +2380,20 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
}
|
||||
|
||||
{
|
||||
int keyIndex = FindKey(_versionKeys, L"OriginalFilename");
|
||||
int keyIndex = FindKey(_versionKeys, "OriginalFilename");
|
||||
if (keyIndex >= 0)
|
||||
_originalFilename = _versionKeys[keyIndex].Value;
|
||||
}
|
||||
{
|
||||
int keyIndex = FindKey(_versionKeys, L"FileDescription");
|
||||
int keyIndex = FindKey(_versionKeys, "FileDescription");
|
||||
if (keyIndex >= 0)
|
||||
_versionShortString = _versionKeys[keyIndex].Value;
|
||||
}
|
||||
{
|
||||
int keyIndex = FindKey(_versionKeys, L"FileVersion");
|
||||
int keyIndex = FindKey(_versionKeys, "FileVersion");
|
||||
if (keyIndex >= 0)
|
||||
{
|
||||
_versionShortString += L' ';
|
||||
_versionShortString.Add_Space();
|
||||
_versionShortString += _versionKeys[keyIndex].Value;
|
||||
}
|
||||
}
|
||||
@@ -2597,7 +2599,8 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
}
|
||||
referenceBuf->Buf.Alloc(item.HeaderSize + item.Size);
|
||||
memcpy(referenceBuf->Buf, item.Header, item.HeaderSize);
|
||||
memcpy(referenceBuf->Buf + item.HeaderSize, _buf + offset, item.Size);
|
||||
if (item.Size != 0)
|
||||
memcpy(referenceBuf->Buf + item.HeaderSize, _buf + offset, item.Size);
|
||||
}
|
||||
inStreamSpec->Init(referenceBuf);
|
||||
|
||||
@@ -2612,17 +2615,15 @@ STDMETHODIMP CHandler::AllowTail(Int32 allowTail)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
static const Byte k_Signature[] = { 'M', 'Z' };
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "PE", "exe dll sys", 0, 0xDD,
|
||||
2, { 'M', 'Z' },
|
||||
REGISTER_ARC_I(
|
||||
"PE", "exe dll sys", 0, 0xDD,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kPreArc,
|
||||
CreateArc, NULL, IsArc_Pe };
|
||||
|
||||
REGISTER_ARC(Pe)
|
||||
|
||||
IsArc_Pe)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -2836,7 +2837,13 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
const CSection &item = _items[index];
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPath: prop = MultiByteToUnicodeString(NPe::GetName(item.Name)); break;
|
||||
case kpidPath:
|
||||
{
|
||||
AString name;
|
||||
NPe::GetName(item.Name, name);
|
||||
prop = MultiByteToUnicodeString(name);
|
||||
break;
|
||||
}
|
||||
case kpidSize:
|
||||
case kpidPackSize: prop = (UInt64)item.PSize; break;
|
||||
case kpidVirtualSize: prop = (UInt64)item.VSize; break;
|
||||
@@ -2995,16 +3002,14 @@ STDMETHODIMP CHandler::AllowTail(Int32 allowTail)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
static const Byte k_Signature[] = { 'V', 'Z' };
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "TE", "te", 0, 0xCF,
|
||||
2, { 'V', 'Z' },
|
||||
REGISTER_ARC_I(
|
||||
"TE", "te", 0, 0xCF,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kPreArc,
|
||||
CreateArc, NULL, IsArc_Te };
|
||||
|
||||
REGISTER_ARC(TE)
|
||||
IsArc_Te)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,10 +28,6 @@ using namespace NWindows;
|
||||
namespace NArchive {
|
||||
namespace NPpmd {
|
||||
|
||||
static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
|
||||
static void SzBigFree(void *, void *address) { BigFree(address); }
|
||||
static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
|
||||
|
||||
static const UInt32 kBufSize = (1 << 20);
|
||||
|
||||
struct CBuf
|
||||
@@ -90,11 +86,10 @@ HRESULT CItem::ReadHeader(ISequentialInStream *s, UInt32 &headerSize)
|
||||
nameLen &= 0x3FFF;
|
||||
if (nameLen > (1 << 9))
|
||||
return S_FALSE;
|
||||
char *name = Name.GetBuffer(nameLen + 1);
|
||||
char *name = Name.GetBuf(nameLen);
|
||||
HRESULT res = ReadStream_FALSE(s, name, nameLen);
|
||||
name[nameLen] = 0;
|
||||
Name.ReleaseBuf_CalcLen(nameLen);
|
||||
headerSize = kHeaderSize + nameLen;
|
||||
Name.ReleaseBuffer();
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -449,15 +444,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
return extractCallback->SetOperationResult(opRes);
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
static const Byte k_Signature[] = { 0x8F, 0xAF, 0xAC, 0x84 };
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Ppmd", "pmd", 0, 0xD,
|
||||
4, { 0x8F, 0xAF, 0xAC, 0x84 },
|
||||
REGISTER_ARC_I(
|
||||
"Ppmd", "pmd", 0, 0xD,
|
||||
k_Signature,
|
||||
0,
|
||||
0,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Ppmd)
|
||||
NULL)
|
||||
|
||||
}}
|
||||
|
||||
@@ -89,7 +89,7 @@ UInt32 CItem::GetWinAttrib() const
|
||||
return a;
|
||||
}
|
||||
|
||||
static const char *kHostOS[] =
|
||||
static const char * const kHostOS[] =
|
||||
{
|
||||
"MS DOS"
|
||||
, "OS/2"
|
||||
@@ -354,7 +354,7 @@ static int ReadTime(const Byte *p, unsigned size, Byte mask, CRarTime &rarTime)
|
||||
}
|
||||
|
||||
#define READ_TIME(_mask_, _ttt_) \
|
||||
{ int size2 = ReadTime(p, size, _mask_, _ttt_); if (size2 < 0) return false; p += size2, size -= size2; }
|
||||
{ int size2 = ReadTime(p, size, _mask_, _ttt_); if (size2 < 0) return false; p += (unsigned)size2, size -= (unsigned)size2; }
|
||||
|
||||
#define READ_TIME_2(_mask_, _def_, _ttt_) \
|
||||
_def_ = ((_mask_ & 8) != 0); if (_def_) \
|
||||
@@ -421,7 +421,7 @@ bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item)
|
||||
{
|
||||
item.IsAltStream = true;
|
||||
item.Name.Empty();
|
||||
item.UnicodeName = L".ACL";
|
||||
item.UnicodeName.SetFromAscii(".ACL");
|
||||
}
|
||||
else if (item.Name == "STM" && size != 0 && (size & 1) == 0)
|
||||
{
|
||||
@@ -517,7 +517,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
|
||||
RINOK(getTextPassword->CryptoGetTextPassword(&password))
|
||||
unsigned len = 0;
|
||||
if (password)
|
||||
len = MyStringLen((BSTR)password);
|
||||
len = MyStringLen(password);
|
||||
CByteBuffer buffer(len * 2);
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
@@ -645,6 +645,8 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
|
||||
error = k_ErrorType_Corrupted;
|
||||
ArcInfo.VolNumber = (UInt32)Get16(m_FileHeaderData + offset);
|
||||
}
|
||||
|
||||
ArcInfo.EndOfArchive_was_Read = true;
|
||||
}
|
||||
m_Position += processed;
|
||||
FinishCryptoBlock();
|
||||
@@ -668,7 +670,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
|
||||
bool okItem = ReadHeaderReal(m_FileHeaderData + 7, m_BlockHeader.HeadSize - 7, item);
|
||||
if (okItem)
|
||||
{
|
||||
if (!CheckHeaderCrc(m_FileHeaderData, m_BlockHeader.HeadSize - item.CommentSize))
|
||||
if (!CheckHeaderCrc(m_FileHeaderData, (unsigned)m_BlockHeader.HeadSize - item.CommentSize))
|
||||
{
|
||||
error = k_ErrorType_Corrupted; // ThrowExceptionWithCode(CInArchiveException::kFileHeaderCRCError);
|
||||
return S_OK;
|
||||
@@ -802,8 +804,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
// FLAGS_TO_PROP(k_Flags, _arcInfo.Flags, prop);
|
||||
if (_arcInfo.Is_DataCRC_Defined())
|
||||
{
|
||||
if (!s.IsEmpty())
|
||||
s += ' ';
|
||||
s.Add_Space_if_NotEmpty();
|
||||
s += "VolCRC";
|
||||
}
|
||||
prop = s;
|
||||
@@ -1008,27 +1009,28 @@ public:
|
||||
{
|
||||
_first = true;
|
||||
_newStyle = newStyle;
|
||||
int dotPos = name.ReverseFind('.');
|
||||
int dotPos = name.ReverseFind_Dot();
|
||||
UString basePart = name;
|
||||
|
||||
if (dotPos >= 0)
|
||||
{
|
||||
UString ext = name.Ptr(dotPos + 1);
|
||||
if (ext.IsEqualToNoCase(L"rar"))
|
||||
if (ext.IsEqualTo_Ascii_NoCase("rar"))
|
||||
{
|
||||
_afterPart = name.Ptr(dotPos);
|
||||
basePart = name.Left(dotPos);
|
||||
}
|
||||
else if (ext.IsEqualToNoCase(L"exe"))
|
||||
else if (ext.IsEqualTo_Ascii_NoCase("exe"))
|
||||
{
|
||||
_afterPart = L".rar";
|
||||
_afterPart.SetFromAscii(".rar");
|
||||
basePart = name.Left(dotPos);
|
||||
}
|
||||
else if (!_newStyle)
|
||||
{
|
||||
if (ext.IsEqualToNoCase(L"000") ||
|
||||
ext.IsEqualToNoCase(L"001") ||
|
||||
ext.IsEqualToNoCase(L"r00") ||
|
||||
ext.IsEqualToNoCase(L"r01"))
|
||||
if (ext.IsEqualTo_Ascii_NoCase("000") ||
|
||||
ext.IsEqualTo_Ascii_NoCase("001") ||
|
||||
ext.IsEqualTo_Ascii_NoCase("r00") ||
|
||||
ext.IsEqualTo_Ascii_NoCase("r01"))
|
||||
{
|
||||
_afterPart.Empty();
|
||||
_first = false;
|
||||
@@ -1042,18 +1044,21 @@ public:
|
||||
if (!_newStyle)
|
||||
{
|
||||
_afterPart.Empty();
|
||||
_unchangedPart = basePart + UString(L".");
|
||||
_changedPart = L"r00";
|
||||
_unchangedPart = basePart;
|
||||
_unchangedPart += L'.';
|
||||
_changedPart.SetFromAscii("r00");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (basePart.IsEmpty())
|
||||
return false;
|
||||
unsigned i = basePart.Len();
|
||||
|
||||
do
|
||||
if (!IsDigit(basePart[i - 1]))
|
||||
break;
|
||||
while (--i);
|
||||
|
||||
_unchangedPart = basePart.Left(i);
|
||||
_changedPart = basePart.Ptr(i);
|
||||
return true;
|
||||
@@ -1071,34 +1076,59 @@ public:
|
||||
|
||||
UString GetNextName()
|
||||
{
|
||||
UString newName;
|
||||
if (_newStyle || !_first)
|
||||
{
|
||||
for (int i = (int)_changedPart.Len() - 1; i >= 0; i--)
|
||||
unsigned i = _changedPart.Len();
|
||||
for (;;)
|
||||
{
|
||||
wchar_t c = _changedPart[i];
|
||||
wchar_t c = _changedPart[--i];
|
||||
if (c == L'9')
|
||||
{
|
||||
c = L'0';
|
||||
newName.InsertAtFront(c);
|
||||
_changedPart.ReplaceOneCharAtPos(i, c);
|
||||
if (i == 0)
|
||||
newName.InsertAtFront(L'1');
|
||||
{
|
||||
_changedPart.InsertAtFront(L'1');
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
c++;
|
||||
newName = UString(c) + newName;
|
||||
i--;
|
||||
for (; i >= 0; i--)
|
||||
newName.InsertAtFront(_changedPart[i]);
|
||||
_changedPart.ReplaceOneCharAtPos(i, c);
|
||||
break;
|
||||
}
|
||||
_changedPart = newName;
|
||||
}
|
||||
|
||||
_first = false;
|
||||
return _unchangedPart + _changedPart + _afterPart;
|
||||
}
|
||||
};
|
||||
|
||||
static HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize)
|
||||
{
|
||||
areThereNonZeros = false;
|
||||
numZeros = 0;
|
||||
const size_t kBufSize = 1 << 9;
|
||||
Byte buf[kBufSize];
|
||||
for (;;)
|
||||
{
|
||||
UInt32 size = 0;
|
||||
HRESULT(stream->Read(buf, kBufSize, &size));
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
for (UInt32 i = 0; i < size; i++)
|
||||
if (buf[i] != 0)
|
||||
{
|
||||
areThereNonZeros = true;
|
||||
numZeros += i;
|
||||
return S_OK;
|
||||
}
|
||||
numZeros += size;
|
||||
if (numZeros > maxSize)
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CHandler::Open2(IInStream *stream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *openCallback)
|
||||
@@ -1174,6 +1204,7 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
RINOK(archive.Open(inStream, maxCheckStartPosition));
|
||||
_isArc = true;
|
||||
CItem item;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (archive.m_Position > endPos)
|
||||
@@ -1181,11 +1212,13 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
_errorFlags |= kpv_ErrorFlags_UnexpectedEnd;
|
||||
break;
|
||||
}
|
||||
|
||||
EErrorType error;
|
||||
// bool decryptionError;
|
||||
// AString errorMessageLoc;
|
||||
bool filled;
|
||||
HRESULT result = archive.GetNextItem(item, getTextPassword, filled, error);
|
||||
|
||||
if (error != k_ErrorType_OK)
|
||||
{
|
||||
if (error == k_ErrorType_UnexpectedEnd)
|
||||
@@ -1198,16 +1231,33 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
// AddErrorMessage(errorMessageLoc);
|
||||
}
|
||||
RINOK(result);
|
||||
|
||||
if (!filled)
|
||||
{
|
||||
if (error == k_ErrorType_DecryptionError && _items.IsEmpty())
|
||||
return S_FALSE;
|
||||
|
||||
if (archive.ArcInfo.ExtraZeroTail_is_Possible())
|
||||
{
|
||||
/* if there is recovery record for multivolume archive,
|
||||
RAR adds 18 bytes (ZERO bytes) at the end for alignment.
|
||||
We must skip these bytes to prevent phySize warning. */
|
||||
RINOK(inStream->Seek(archive.ArcInfo.EndPos, STREAM_SEEK_SET, NULL));
|
||||
bool areThereNonZeros;
|
||||
UInt64 numZeros;
|
||||
const UInt64 maxSize = 1 << 12;
|
||||
RINOK(ReadZeroTail(inStream, areThereNonZeros, numZeros, maxSize));
|
||||
if (!areThereNonZeros && numZeros != 0 && numZeros <= maxSize)
|
||||
archive.ArcInfo.EndPos += numZeros;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (item.IgnoreItem())
|
||||
continue;
|
||||
|
||||
bool needAdd = true;
|
||||
|
||||
if (item.IsSplitBefore())
|
||||
{
|
||||
if (!_refItems.IsEmpty())
|
||||
@@ -1217,6 +1267,7 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
needAdd = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (needAdd)
|
||||
{
|
||||
CRefItem refItem;
|
||||
@@ -1225,7 +1276,9 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
refItem.VolumeIndex = _arcs.Size();
|
||||
_refItems.Add(refItem);
|
||||
}
|
||||
|
||||
_items.Add(item);
|
||||
|
||||
if (openCallback && _items.Size() % 100 == 0)
|
||||
{
|
||||
UInt64 numFiles = _items.Size();
|
||||
@@ -1256,7 +1309,7 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
|
||||
/*
|
||||
int baseFileIndex = -1;
|
||||
for (int i = 0; i < _refItems.Size(); i++)
|
||||
for (unsigned i = 0; i < _refItems.Size(); i++)
|
||||
{
|
||||
CItem &item = _items[_refItems[i].ItemIndex];
|
||||
if (item.IsAltStream)
|
||||
@@ -1430,7 +1483,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
unsigned lastIndex = 0;
|
||||
CRecordVector<int> importantIndexes;
|
||||
CRecordVector<unsigned> importantIndexes;
|
||||
CRecordVector<bool> extractStatuses;
|
||||
|
||||
for (UInt32 t = 0; t < numItems; t++)
|
||||
@@ -1470,7 +1523,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
|
||||
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
|
||||
|
||||
CFilterCoder *filterStreamSpec = new CFilterCoder;
|
||||
CFilterCoder *filterStreamSpec = new CFilterCoder(false);
|
||||
CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec;
|
||||
|
||||
NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec = NULL;
|
||||
@@ -1576,22 +1629,25 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
// unpackedPos += 0;
|
||||
|
||||
CMyComPtr<ISequentialInStream> inStream;
|
||||
|
||||
if (item.IsEncrypted())
|
||||
{
|
||||
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
|
||||
|
||||
if (item.UnPackVersion >= 29)
|
||||
{
|
||||
if (!rar29CryptoDecoder)
|
||||
{
|
||||
rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder;
|
||||
rar29CryptoDecoder = rar29CryptoDecoderSpec;
|
||||
// RINOK(rar29CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar29Decoder));
|
||||
}
|
||||
rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);
|
||||
/*
|
||||
CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties;
|
||||
RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,
|
||||
&cryptoProperties));
|
||||
RINOK(cryptoProperties->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
|
||||
*/
|
||||
RINOK(rar29CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
|
||||
filterStreamSpec->Filter = rar29CryptoDecoder;
|
||||
}
|
||||
else if (item.UnPackVersion >= 20)
|
||||
@@ -1600,7 +1656,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
{
|
||||
rar20CryptoDecoderSpec = new NCrypto::NRar20::CDecoder;
|
||||
rar20CryptoDecoder = rar20CryptoDecoderSpec;
|
||||
// RINOK(rar20CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar20Decoder));
|
||||
}
|
||||
filterStreamSpec->Filter = rar20CryptoDecoder;
|
||||
}
|
||||
@@ -1610,8 +1665,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod));
|
||||
continue;
|
||||
}
|
||||
RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword,
|
||||
&cryptoSetPassword));
|
||||
|
||||
RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
|
||||
|
||||
if (!getTextPassword)
|
||||
extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
|
||||
@@ -1624,7 +1679,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
UString unicodePassword;
|
||||
unsigned len = 0;
|
||||
if (password)
|
||||
len = MyStringLen((BSTR)password);
|
||||
len = MyStringLen(password);
|
||||
CByteBuffer buffer(len * 2);
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
@@ -1646,14 +1701,18 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
{
|
||||
RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
|
||||
}
|
||||
|
||||
filterStreamSpec->SetInStream(folderInStream);
|
||||
filterStreamSpec->SetOutStreamSize(NULL);
|
||||
inStream = filterStream;
|
||||
}
|
||||
else
|
||||
{
|
||||
inStream = folderInStream;
|
||||
}
|
||||
|
||||
CMyComPtr<ICompressCoder> commonCoder;
|
||||
|
||||
switch(item.Method)
|
||||
{
|
||||
case '0':
|
||||
@@ -1679,14 +1738,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
mi.Coder.Release();
|
||||
if (item.UnPackVersion <= 40)
|
||||
{
|
||||
UInt32 methodID = 0x040300;
|
||||
UInt32 methodID = 0x40300;
|
||||
if (item.UnPackVersion < 20)
|
||||
methodID += 1;
|
||||
else if (item.UnPackVersion < 29)
|
||||
methodID += 2;
|
||||
else
|
||||
methodID += 3;
|
||||
RINOK(CreateCoder(EXTERNAL_CODECS_VARS methodID, mi.Coder, false));
|
||||
RINOK(CreateCoder(EXTERNAL_CODECS_VARS methodID, false, mi.Coder));
|
||||
}
|
||||
|
||||
if (mi.Coder == 0)
|
||||
@@ -1722,7 +1781,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod));
|
||||
continue;
|
||||
}
|
||||
|
||||
HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &item.Size, progress);
|
||||
|
||||
if (item.IsEncrypted())
|
||||
filterStreamSpec->ReleaseInStream();
|
||||
if (result == S_FALSE)
|
||||
@@ -1771,15 +1832,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
IMPL_ISetCompressCodecsInfo
|
||||
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Rar", "rar r00", 0, 3,
|
||||
NHeader::kMarkerSize, SIGNATURE,
|
||||
REGISTER_ARC_I(
|
||||
"Rar", "rar r00", 0, 3,
|
||||
kMarker,
|
||||
0,
|
||||
NArcInfoFlags::kFindSignature,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Rar)
|
||||
NULL)
|
||||
|
||||
}}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Rar/Handler.h
|
||||
// RarHandler.h
|
||||
|
||||
#ifndef __RAR_HANDLER_H
|
||||
#define __RAR_HANDLER_H
|
||||
@@ -24,18 +24,25 @@ struct CInArcInfo
|
||||
UInt32 EndFlags;
|
||||
UInt32 VolNumber;
|
||||
UInt32 DataCRC;
|
||||
bool EndOfArchive_was_Read;
|
||||
|
||||
CInArcInfo(): EndFlags(0) {}
|
||||
CInArcInfo(): EndFlags(0), EndOfArchive_was_Read(false) {}
|
||||
|
||||
UInt64 GetPhySize() const { return EndPos - StartPos; }
|
||||
|
||||
bool IsSolid() const { return (Flags & NHeader::NArchive::kSolid) != 0; }
|
||||
bool IsCommented() const { return (Flags & NHeader::NArchive::kComment) != 0; }
|
||||
bool ExtraZeroTail_is_Possible() const { return IsVolume() && IsRecovery() && EndOfArchive_was_Read; }
|
||||
|
||||
bool IsVolume() const { return (Flags & NHeader::NArchive::kVolume) != 0; }
|
||||
bool IsCommented() const { return (Flags & NHeader::NArchive::kComment) != 0; }
|
||||
// kLock
|
||||
bool IsSolid() const { return (Flags & NHeader::NArchive::kSolid) != 0; }
|
||||
bool HaveNewVolumeName() const { return (Flags & NHeader::NArchive::kNewVolName) != 0; }
|
||||
bool IsFirstVolume() const { return (Flags & NHeader::NArchive::kFirstVolume) != 0; }
|
||||
// kAuthenticity
|
||||
bool IsRecovery() const { return (Flags & NHeader::NArchive::kRecovery) != 0; }
|
||||
bool IsEncrypted() const { return (Flags & NHeader::NArchive::kBlockEncryption) != 0; }
|
||||
bool IsFirstVolume() const { return (Flags & NHeader::NArchive::kFirstVolume) != 0; }
|
||||
bool IsThereEncryptVer() const { return (Flags & NHeader::NArchive::kEncryptVer) != 0; }
|
||||
|
||||
bool IsEncryptOld() const { return (!IsThereEncryptVer() || EncryptVersion < 36); }
|
||||
|
||||
bool Is_VolNumber_Defined() const { return (EndFlags & NHeader::NArchive::kEndOfArc_Flags_VolNumber) != 0; }
|
||||
|
||||
@@ -84,10 +84,10 @@ struct CItem
|
||||
|
||||
CItem() { Clear(); }
|
||||
|
||||
UInt64 GetFullSize() const { return MainPartSize + CommentSize + AlignSize + PackSize; };
|
||||
// DWORD GetHeaderWithCommentSize() const { return MainPartSize + CommentSize; };
|
||||
UInt64 GetCommentPosition() const { return Position + MainPartSize; };
|
||||
UInt64 GetDataPosition() const { return GetCommentPosition() + CommentSize + AlignSize; };
|
||||
UInt64 GetFullSize() const { return MainPartSize + CommentSize + AlignSize + PackSize; }
|
||||
// DWORD GetHeaderWithCommentSize() const { return MainPartSize + CommentSize; }
|
||||
UInt64 GetCommentPosition() const { return Position + MainPartSize; }
|
||||
UInt64 GetDataPosition() const { return GetCommentPosition() + CommentSize + AlignSize; }
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -77,7 +77,7 @@ enum
|
||||
k_EntryType_I18NSTRING
|
||||
};
|
||||
|
||||
static const char *k_CPUs[] =
|
||||
static const char * const k_CPUs[] =
|
||||
{
|
||||
"noarch"
|
||||
, "i386"
|
||||
@@ -101,7 +101,7 @@ static const char *k_CPUs[] =
|
||||
, "aarch64" // 19
|
||||
};
|
||||
|
||||
static const char *k_OS[] =
|
||||
static const char * const k_OS[] =
|
||||
{
|
||||
"0"
|
||||
, "Linux"
|
||||
@@ -299,12 +299,7 @@ AString CHandler::GetBaseName() const
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char *p = s.GetBuffer(kNameSize);
|
||||
memcpy(p, _lead.Name, kNameSize);
|
||||
p[kNameSize] = 0;
|
||||
s.ReleaseBuffer();
|
||||
}
|
||||
s.SetFrom_CalcLen(_lead.Name, kNameSize);
|
||||
|
||||
s += '.';
|
||||
if (_lead.Type == kRpmType_Src)
|
||||
@@ -553,7 +548,7 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader)
|
||||
for (UInt32 t = 0; t < entry.Count; t++)
|
||||
{
|
||||
if (t != 0)
|
||||
_metadata += ' ';
|
||||
_metadata.Add_Space();
|
||||
char temp[16];
|
||||
ConvertUInt32ToString(Get32(p + t * 4), temp);
|
||||
_metadata += temp;
|
||||
@@ -592,7 +587,7 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader)
|
||||
for (UInt32 t = 0; t < entry.Count; t++)
|
||||
{
|
||||
if (t != 0)
|
||||
_metadata += ' ';
|
||||
_metadata.Add_Space();
|
||||
char temp[16];
|
||||
ConvertUInt32ToString(Get16(p + t * 2), temp);
|
||||
_metadata += temp;
|
||||
@@ -777,15 +772,13 @@ STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
static const Byte k_Signature[] = { 0xED, 0xAB, 0xEE, 0xDB};
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Rpm", "rpm", 0, 0xEB,
|
||||
4, { 0xED, 0xAB, 0xEE, 0xDB},
|
||||
REGISTER_ARC_I(
|
||||
"Rpm", "rpm", 0, 0xEB,
|
||||
k_Signature,
|
||||
0,
|
||||
0,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Rpm)
|
||||
NULL)
|
||||
|
||||
}}
|
||||
|
||||
@@ -71,68 +71,53 @@ struct CSeqName
|
||||
UString _changedPart;
|
||||
bool _splitStyle;
|
||||
|
||||
UString GetNextName()
|
||||
bool GetNextName(UString &s)
|
||||
{
|
||||
UString newName;
|
||||
if (_splitStyle)
|
||||
{
|
||||
int i;
|
||||
int numLetters = _changedPart.Len();
|
||||
for (i = numLetters - 1; i >= 0; i--)
|
||||
unsigned i = _changedPart.Len();
|
||||
for (;;)
|
||||
{
|
||||
wchar_t c = _changedPart[i];
|
||||
if (c == 'z')
|
||||
wchar_t c = _changedPart[--i];
|
||||
|
||||
if (_splitStyle)
|
||||
{
|
||||
newName.InsertAtFront('a');
|
||||
continue;
|
||||
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 == 'Z')
|
||||
else
|
||||
{
|
||||
newName.InsertAtFront('A');
|
||||
continue;
|
||||
if (c == '9')
|
||||
{
|
||||
_changedPart.ReplaceOneCharAtPos(i, L'0');
|
||||
if (i == 0)
|
||||
{
|
||||
_changedPart.InsertAtFront(L'1');
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
c++;
|
||||
if ((c == 'z' || c == 'Z') && i == 0)
|
||||
{
|
||||
_unchangedPart += c;
|
||||
wchar_t newChar = (c == 'z') ? L'a' : L'A';
|
||||
newName.Empty();
|
||||
numLetters++;
|
||||
for (int k = 0; k < numLetters; k++)
|
||||
newName += newChar;
|
||||
break;
|
||||
}
|
||||
newName.InsertAtFront(c);
|
||||
i--;
|
||||
for (; i >= 0; i--)
|
||||
newName.InsertAtFront(_changedPart[i]);
|
||||
_changedPart.ReplaceOneCharAtPos(i, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
int numLetters = _changedPart.Len();
|
||||
for (i = numLetters - 1; i >= 0; i--)
|
||||
{
|
||||
wchar_t c = _changedPart[i];
|
||||
if (c == '9')
|
||||
{
|
||||
newName.InsertAtFront('0');
|
||||
if (i == 0)
|
||||
newName.InsertAtFront('1');
|
||||
continue;
|
||||
}
|
||||
c++;
|
||||
newName.InsertAtFront(c);
|
||||
i--;
|
||||
for (; i >= 0; i--)
|
||||
newName.InsertAtFront(_changedPart[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_changedPart = newName;
|
||||
return _unchangedPart + _changedPart;
|
||||
|
||||
s = _unchangedPart + _changedPart;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -156,7 +141,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
name = prop.bstrVal;
|
||||
}
|
||||
|
||||
int dotPos = name.ReverseFind('.');
|
||||
int dotPos = name.ReverseFind_Dot();
|
||||
const UString prefix = name.Left(dotPos + 1);
|
||||
const UString ext = name.Ptr(dotPos + 1);
|
||||
UString ext2 = ext;
|
||||
@@ -196,7 +181,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
seqName._splitStyle = splitStyle;
|
||||
|
||||
if (prefix.Len() < 1)
|
||||
_subName = L"file";
|
||||
_subName.SetFromAscii("file");
|
||||
else
|
||||
_subName.SetFrom(prefix, prefix.Len() - 1);
|
||||
|
||||
@@ -220,7 +205,9 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const UString fullName = seqName.GetNextName();
|
||||
UString fullName;
|
||||
if (!seqName.GetNextName(fullName))
|
||||
break;
|
||||
CMyComPtr<IInStream> nextStream;
|
||||
HRESULT result = volumeCallback->GetStream(fullName, &nextStream);
|
||||
if (result == S_FALSE)
|
||||
@@ -355,15 +342,10 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Split", "001", 0, 0xEA,
|
||||
0, { 0 },
|
||||
REGISTER_ARC_I_NO_SIG(
|
||||
"Split", "001", 0, 0xEA,
|
||||
0,
|
||||
0,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Split)
|
||||
NULL)
|
||||
|
||||
}}
|
||||
|
||||
@@ -28,10 +28,6 @@
|
||||
namespace NArchive {
|
||||
namespace NSquashfs {
|
||||
|
||||
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
|
||||
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
|
||||
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
|
||||
static const UInt32 kNumFilesMax = (1 << 28);
|
||||
static const unsigned kNumDirLevelsMax = (1 << 10);
|
||||
|
||||
@@ -68,7 +64,7 @@ static const UInt32 kSignature32_LZ = 0x71736873;
|
||||
#define kMethod_LZO 3
|
||||
#define kMethod_XZ 4
|
||||
|
||||
static const char *k_Methods[] =
|
||||
static const char * const k_Methods[] =
|
||||
{
|
||||
"Unknown"
|
||||
, "ZLIB"
|
||||
@@ -1652,13 +1648,12 @@ AString CHandler::GetPath(int index) const
|
||||
len--;
|
||||
|
||||
AString path;
|
||||
char *dest = path.GetBuffer(len) + len;
|
||||
char *dest = path.GetBuf_SetEnd(len) + len;
|
||||
index = indexMem;
|
||||
for (;;)
|
||||
{
|
||||
const CItem &item = _items[index];
|
||||
index = item.Parent;
|
||||
|
||||
const Byte *p = _dirs.Data + item.Ptr;
|
||||
unsigned size = (_h.IsOldVersion() ? (unsigned)p[2] : (unsigned)Get16(p + 6)) + 1;
|
||||
p += _h.GetFileNameOffset();
|
||||
@@ -1670,7 +1665,6 @@ AString CHandler::GetPath(int index) const
|
||||
break;
|
||||
*(--dest) = CHAR_PATH_SEPARATOR;
|
||||
}
|
||||
path.ReleaseBuffer(len);
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -1846,7 +1840,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
AString res = "SquashFS";
|
||||
if (_h.SeveralMethods)
|
||||
res += "-LZMA";
|
||||
res += ' ';
|
||||
res.Add_Space();
|
||||
char s[16];
|
||||
ConvertUInt32ToString(_h.Major, s);
|
||||
res += s;
|
||||
@@ -2049,7 +2043,8 @@ HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
|
||||
}
|
||||
if (offsetInBlock + blockSize > _cachedUnpackBlockSize)
|
||||
return S_FALSE;
|
||||
memcpy(dest, _cachedBlock + offsetInBlock, blockSize);
|
||||
if (blockSize != 0)
|
||||
memcpy(dest, _cachedBlock + offsetInBlock, blockSize);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -2208,20 +2203,16 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "SquashFS", "squashfs", 0, 0xD2,
|
||||
3 * (1 + 4),
|
||||
{
|
||||
static const Byte k_Signature[] = {
|
||||
4, 'h', 's', 'q', 's',
|
||||
4, 's', 'q', 's', 'h',
|
||||
4, 's', 'h', 's', 'q',
|
||||
},
|
||||
4, 's', 'h', 's', 'q' };
|
||||
|
||||
REGISTER_ARC_I(
|
||||
"SquashFS", "squashfs", 0, 0xD2,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kMultiSignature,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Cramfs)
|
||||
NULL)
|
||||
|
||||
}}
|
||||
|
||||
@@ -170,7 +170,7 @@ public:
|
||||
INTERFACE_IInArchive(;)
|
||||
INTERFACE_IOutArchive(;)
|
||||
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
|
||||
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
|
||||
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
|
||||
};
|
||||
|
||||
static const Byte kProps[] =
|
||||
@@ -218,7 +218,7 @@ static void DicSizeToString(char *s, UInt32 val)
|
||||
else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
|
||||
}
|
||||
::ConvertUInt32ToString(val, s);
|
||||
int pos = MyStringLen(s);
|
||||
unsigned pos = MyStringLen(s);
|
||||
s[pos++] = c;
|
||||
s[pos] = 0;
|
||||
}
|
||||
@@ -558,11 +558,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
return NCompress::CopyStream(_seqStream, outStream, NULL);
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
_lzmaMode = false;
|
||||
RINOK(_props.SetProperties(names, values, numProps));
|
||||
UString m = _props.MethodName;
|
||||
AString m = _props.MethodName;
|
||||
m.MakeLower_Ascii();
|
||||
if (m.IsEqualTo("lzma"))
|
||||
{
|
||||
@@ -576,21 +576,16 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
IMP_CreateArcOut
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "SWFc", "swf", "~.swf", 0xD8,
|
||||
2 + 3 + 3,
|
||||
{
|
||||
static const Byte k_Signature[] = {
|
||||
3, 'C', 'W', 'S',
|
||||
3, 'Z', 'W', 'S',
|
||||
},
|
||||
3, 'Z', 'W', 'S' };
|
||||
|
||||
REGISTER_ARC_IO(
|
||||
"SWFc", "swf", "~.swf", 0xD8,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kMultiSignature,
|
||||
REF_CreateArc_Pair, IsArc_Swfc };
|
||||
|
||||
REGISTER_ARC(Swfc)
|
||||
IsArc_Swfc)
|
||||
|
||||
}
|
||||
|
||||
@@ -978,15 +973,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
static const Byte k_Signature[] = { 'F', 'W', 'S' };
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "SWF", "swf", 0, 0xD7,
|
||||
3, { 'F', 'W', 'S' },
|
||||
REGISTER_ARC_I(
|
||||
"SWF", "swf", 0, 0xD7,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kKeepName,
|
||||
CreateArc, NULL, NSwfc::IsArc_Swf };
|
||||
|
||||
REGISTER_ARC(Swf)
|
||||
NSwfc::IsArc_Swf)
|
||||
|
||||
}}
|
||||
|
||||
@@ -143,10 +143,10 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
|
||||
if (!_forceCodePage)
|
||||
{
|
||||
if (utf8_OK) utf8_OK = CheckUTF8(item.Name);
|
||||
if (utf8_OK) utf8_OK = CheckUTF8(item.Name, item.NameCouldBeReduced);
|
||||
if (utf8_OK) utf8_OK = CheckUTF8(item.LinkName, item.LinkNameCouldBeReduced);
|
||||
if (utf8_OK) utf8_OK = CheckUTF8(item.User);
|
||||
if (utf8_OK) utf8_OK = CheckUTF8(item.Group);
|
||||
if (utf8_OK) utf8_OK = CheckUTF8(item.LinkName);
|
||||
}
|
||||
|
||||
RINOK(stream->Seek(item.GetPackSizeAligned(), STREAM_SEEK_CUR, &_phySize));
|
||||
@@ -298,19 +298,12 @@ void CHandler::TarStringToUnicode(const AString &s, NWindows::NCOM::CPropVariant
|
||||
{
|
||||
UString dest;
|
||||
if (_curCodePage == CP_UTF8)
|
||||
{
|
||||
if (!ConvertUTF8ToUnicode(s, dest))
|
||||
{
|
||||
prop = "[ERROR-NAME]";
|
||||
return;
|
||||
}
|
||||
}
|
||||
ConvertUTF8ToUnicode(s, dest);
|
||||
else
|
||||
dest = MultiByteToUnicodeString(s, _curCodePage);
|
||||
MultiByteToUnicodeString2(dest, s, _curCodePage);
|
||||
if (toOs)
|
||||
prop = NItemName::GetOSName2(dest);
|
||||
else
|
||||
prop = dest;
|
||||
NItemName::ConvertToOSName2(dest);
|
||||
prop = dest;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
@@ -632,10 +625,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
|
||||
if (item.IsSymLink())
|
||||
{
|
||||
CBufInStream *streamSpec = new CBufInStream;
|
||||
CMyComPtr<IInStream> streamTemp = streamSpec;
|
||||
streamSpec->Init((const Byte *)(const char *)item.LinkName, item.LinkName.Len(), (IInArchive *)this);
|
||||
*stream = streamTemp.Detach();
|
||||
Create_BufInStream_WithReference((const Byte *)(const char *)item.LinkName, item.LinkName.Len(), (IInArchive *)this, stream);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -651,7 +641,7 @@ void CHandler::Init()
|
||||
_curCodePage = _specifiedCodePage = CP_UTF8; // CP_OEMCP;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
Init();
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
INTERFACE_IOutArchive(;)
|
||||
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
|
||||
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
|
||||
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
|
||||
|
||||
void Init();
|
||||
CHandler();
|
||||
|
||||
@@ -36,8 +36,8 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro
|
||||
s = NItemName::MakeLegalName(s);
|
||||
if (codePage == CP_UTF8)
|
||||
{
|
||||
if (!ConvertUnicodeToUTF8(s, res))
|
||||
return E_INVALIDARG;
|
||||
ConvertUnicodeToUTF8(s, res);
|
||||
// if (!ConvertUnicodeToUTF8(s, res)) // return E_INVALIDARG;
|
||||
}
|
||||
else
|
||||
UnicodeStringToMultiByte2(res, s, codePage);
|
||||
|
||||
@@ -180,6 +180,9 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
|
||||
|
||||
error = k_ErrorType_Corrupted;
|
||||
ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize;
|
||||
item.NameCouldBeReduced =
|
||||
(item.Name.Len() == NFileHeader::kNameSize ||
|
||||
item.Name.Len() == NFileHeader::kNameSize - 1);
|
||||
|
||||
RIF(OctalToNumber32(p, 8, item.Mode)); p += 8;
|
||||
|
||||
@@ -198,6 +201,9 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
|
||||
item.LinkFlag = *p++;
|
||||
|
||||
ReadString(p, NFileHeader::kNameSize, item.LinkName); p += NFileHeader::kNameSize;
|
||||
item.LinkNameCouldBeReduced =
|
||||
(item.LinkName.Len() == NFileHeader::kNameSize ||
|
||||
item.LinkName.Len() == NFileHeader::kNameSize - 1);
|
||||
|
||||
memcpy(item.Magic, p, 8); p += 8;
|
||||
|
||||
@@ -207,12 +213,17 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
|
||||
item.DeviceMajorDefined = (p[0] != 0); if (item.DeviceMajorDefined) { RIF(OctalToNumber32(p, 8, item.DeviceMajor)); } p += 8;
|
||||
item.DeviceMinorDefined = (p[0] != 0); if (item.DeviceMinorDefined) { RIF(OctalToNumber32(p, 8, item.DeviceMinor)); } p += 8;
|
||||
|
||||
AString prefix;
|
||||
ReadString(p, NFileHeader::kPrefixSize, prefix);
|
||||
if (p[0] != 0)
|
||||
{
|
||||
AString prefix;
|
||||
ReadString(p, NFileHeader::kPrefixSize, prefix);
|
||||
if (!prefix.IsEmpty()
|
||||
&& item.IsUstarMagic()
|
||||
&& (item.LinkFlag != 'L' /* || prefix != "00000000000" */ ))
|
||||
item.Name = prefix + '/' + item.Name;
|
||||
}
|
||||
|
||||
p += NFileHeader::kPrefixSize;
|
||||
if (!prefix.IsEmpty() && item.IsUstarMagic() &&
|
||||
(item.LinkFlag != 'L' /* || prefix != "00000000000" */ ))
|
||||
item.Name = prefix + AString('/') + item.Name;
|
||||
|
||||
if (item.LinkFlag == NFileHeader::NLinkFlag::kHardLink)
|
||||
{
|
||||
@@ -353,12 +364,11 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErro
|
||||
if (item.PackSize > (1 << 14))
|
||||
return S_OK;
|
||||
unsigned packSize = (unsigned)item.GetPackSizeAligned();
|
||||
char *buf = name->GetBuffer(packSize);
|
||||
char *buf = name->GetBuf(packSize);
|
||||
size_t processedSize = packSize;
|
||||
HRESULT res = ReadStream(stream, buf, &processedSize);
|
||||
item.HeaderSize += (unsigned)processedSize;
|
||||
buf[(size_t)item.PackSize] = 0;
|
||||
name->ReleaseBuffer();
|
||||
name->ReleaseBuf_CalcLen((unsigned)item.PackSize);
|
||||
RINOK(res);
|
||||
if (processedSize != packSize)
|
||||
{
|
||||
@@ -392,8 +402,18 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErro
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (flagL) item.Name = nameL;
|
||||
if (flagK) item.LinkName = nameK;
|
||||
if (flagL)
|
||||
{
|
||||
item.Name = nameL;
|
||||
item.NameCouldBeReduced = false;
|
||||
}
|
||||
|
||||
if (flagK)
|
||||
{
|
||||
item.LinkName = nameK;
|
||||
item.LinkNameCouldBeReduced = false;
|
||||
}
|
||||
|
||||
error = k_ErrorType_OK;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user