This commit is contained in:
Igor Pavlov
2015-06-15 00:00:00 +00:00
committed by Kornel Lesiński
parent 0713a3ab80
commit 54490d51d5
591 changed files with 34932 additions and 16390 deletions

View File

@@ -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

View 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
{}
};

View File

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

View File

@@ -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

View File

@@ -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() {}
}}

View File

@@ -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,

View File

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

View File

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

View File

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

View File

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

View File

@@ -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

View File

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

View File

@@ -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

View File

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

View File

@@ -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

View File

@@ -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)

View File

@@ -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();

View File

@@ -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

View File

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

View File

@@ -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()
{

View File

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

View File

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

View File

@@ -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);

View File

File diff suppressed because it is too large Load Diff

View File

@@ -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(

View File

@@ -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)
}}

View File

@@ -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)
}}

View File

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

View File

@@ -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

View File

@@ -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);

View File

@@ -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)
}}

View File

@@ -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)
}}

View File

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

View File

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

View File

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

View File

@@ -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
{

View File

@@ -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)

View File

@@ -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();
}
};

View File

@@ -51,7 +51,7 @@ struct CItem
FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext;
}
int GetFolderIndex(int numFolders) const
int GetFolderIndex(unsigned numFolders) const
{
if (ContinuedFromPrev())
return 0;

View File

@@ -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)
}}

View File

@@ -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)
}
}}

View File

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

View File

@@ -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);

View File

@@ -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)
}}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

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

View File

@@ -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

View File

@@ -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();
}
*/
}

View File

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

View File

@@ -18,7 +18,7 @@ struct CCoder: public CCoderInfo, public CVirtThread
virtual void Execute();
void Code(ICompressProgressInfo *progress);
~CCoder() { CVirtThread::WaitThreadFinish(); }
virtual ~CCoder() { CVirtThread::WaitThreadFinish(); }
};
/*

View File

@@ -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

View File

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

View File

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

View File

@@ -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

View File

@@ -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)
}}

View File

@@ -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)
}}

View File

@@ -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

View File

@@ -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

View File

@@ -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)
}}

View File

@@ -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)
}}

View File

@@ -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)
}}

View File

@@ -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)
}}

View File

@@ -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(&currentTotalPacked));
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)
}}

View File

@@ -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)
}}

View File

@@ -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)

View File

@@ -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)
}}

View File

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

View File

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

View File

@@ -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

View File

@@ -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()

View File

@@ -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();

View File

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

View File

@@ -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)
}}

View File

@@ -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, &currentItemUnPacked, 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)
}}

View File

@@ -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)
}
}}

View File

@@ -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)
}}

View File

@@ -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)
}}

View File

@@ -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)
}}

View File

@@ -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)
}

View File

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

View File

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

View File

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

View File

@@ -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();

View File

@@ -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);

View File

@@ -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)
}}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -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 &sect = _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)
}
}

View File

@@ -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)
}}

View File

@@ -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)
}}

View File

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

View File

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

View File

@@ -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)
}}

View File

@@ -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)
}}

View File

@@ -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)
}}

View File

@@ -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)
}}

View File

@@ -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();

View File

@@ -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();

View File

@@ -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);

View File

@@ -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