PhysicsFS 2.0.3 imported.

This commit is contained in:
King_DuckZ 2014-02-12 23:59:58 +01:00
parent bcc0937726
commit 993311d151
459 changed files with 87785 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View file

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

View file

@ -0,0 +1,50 @@
// 7zCompressionMode.h
#ifndef __7Z_COMPRESSION_MODE_H
#define __7Z_COMPRESSION_MODE_H
#include "../../../Common/MyString.h"
#include "../../../Windows/PropVariant.h"
#include "../../Common/MethodProps.h"
namespace NArchive {
namespace N7z {
struct CMethodFull: public CMethod
{
UInt32 NumInStreams;
UInt32 NumOutStreams;
bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }
};
struct CBind
{
UInt32 InCoder;
UInt32 InStream;
UInt32 OutCoder;
UInt32 OutStream;
};
struct CCompressionMethodMode
{
CObjectVector<CMethodFull> Methods;
CRecordVector<CBind> Binds;
#ifdef COMPRESS_MT
UInt32 NumThreads;
#endif
bool PasswordIsDefined;
UString Password;
bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }
CCompressionMethodMode(): PasswordIsDefined(false)
#ifdef COMPRESS_MT
, NumThreads(1)
#endif
{}
};
}}
#endif

View file

@ -0,0 +1,330 @@
// 7zDecode.cpp
#include "StdAfx.h"
#include "7zDecode.h"
#include "../../IPassword.h"
#include "../../Common/LockedStream.h"
#include "../../Common/StreamObjects.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/LimitedStreams.h"
#include "../../Common/CreateCoder.h"
#include "../../Common/FilterCoder.h"
namespace NArchive {
namespace N7z {
static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,
CBindInfoEx &bindInfo)
{
bindInfo.Clear();
int i;
for (i = 0; i < folder.BindPairs.Size(); i++)
{
NCoderMixer::CBindPair bindPair;
bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;
bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;
bindInfo.BindPairs.Add(bindPair);
}
UInt32 outStreamIndex = 0;
for (i = 0; i < folder.Coders.Size(); i++)
{
NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
const CCoderInfo &coderInfo = folder.Coders[i];
coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;
coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;
bindInfo.Coders.Add(coderStreamsInfo);
bindInfo.CoderMethodIDs.Add(coderInfo.MethodID);
for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)
if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
bindInfo.OutStreams.Add(outStreamIndex);
}
for (i = 0; i < folder.PackStreams.Size(); i++)
bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]);
}
static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1,
const NCoderMixer::CCoderStreamsInfo &a2)
{
return (a1.NumInStreams == a2.NumInStreams) &&
(a1.NumOutStreams == a2.NumOutStreams);
}
static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2)
{
return (a1.InIndex == a2.InIndex) &&
(a1.OutIndex == a2.OutIndex);
}
static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
{
if (a1.Coders.Size() != a2.Coders.Size())
return false;
int i;
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())
return false;
for (i = 0; i < a1.BindPairs.Size(); i++)
if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[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())
return false;
if (a1.OutStreams.Size() != a2.OutStreams.Size())
return false;
return true;
}
CDecoder::CDecoder(bool multiThread)
{
#ifndef _ST_MODE
multiThread = true;
#endif
_multiThread = multiThread;
_bindInfoExPrevIsDefined = false;
}
HRESULT CDecoder::Decode(
DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream,
UInt64 startPos,
const UInt64 *packSizes,
const CFolder &folderInfo,
ISequentialOutStream *outStream,
ICompressProgressInfo *compressProgress
#ifndef _NO_CRYPTO
, ICryptoGetTextPassword *getTextPassword
#endif
#ifdef COMPRESS_MT
, bool mtMode, UInt32 numThreads
#endif
)
{
CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
CLockedInStream lockedInStream;
lockedInStream.Init(inStream);
for (int j = 0; j < folderInfo.PackStreams.Size(); j++)
{
CLockedSequentialInStreamImp *lockedStreamImpSpec = new
CLockedSequentialInStreamImp;
CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
lockedStreamImpSpec->Init(&lockedInStream, startPos);
startPos += packSizes[j];
CLimitedSequentialInStream *streamSpec = new
CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> inStream = streamSpec;
streamSpec->SetStream(lockedStreamImp);
streamSpec->Init(packSizes[j]);
inStreams.Add(inStream);
}
int numCoders = folderInfo.Coders.Size();
CBindInfoEx bindInfo;
ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
bool createNewCoders;
if (!_bindInfoExPrevIsDefined)
createNewCoders = true;
else
createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
if (createNewCoders)
{
int i;
_decoders.Clear();
// _decoders2.Clear();
_mixerCoder.Release();
if (_multiThread)
{
_mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT;
_mixerCoder = _mixerCoderMTSpec;
_mixerCoderCommon = _mixerCoderMTSpec;
}
else
{
#ifdef _ST_MODE
_mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST;
_mixerCoder = _mixerCoderSTSpec;
_mixerCoderCommon = _mixerCoderSTSpec;
#endif
}
RINOK(_mixerCoderCommon->SetBindInfo(bindInfo));
for (i = 0; i < numCoders; i++)
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
CMyComPtr<ICompressCoder> decoder;
CMyComPtr<ICompressCoder2> decoder2;
RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS
coderInfo.MethodID, decoder, decoder2, false));
CMyComPtr<IUnknown> decoderUnknown;
if (coderInfo.IsSimpleCoder())
{
if (decoder == 0)
return E_NOTIMPL;
decoderUnknown = (IUnknown *)decoder;
if (_multiThread)
_mixerCoderMTSpec->AddCoder(decoder);
#ifdef _ST_MODE
else
_mixerCoderSTSpec->AddCoder(decoder, false);
#endif
}
else
{
if (decoder2 == 0)
return E_NOTIMPL;
decoderUnknown = (IUnknown *)decoder2;
if (_multiThread)
_mixerCoderMTSpec->AddCoder2(decoder2);
#ifdef _ST_MODE
else
_mixerCoderSTSpec->AddCoder2(decoder2, false);
#endif
}
_decoders.Add(decoderUnknown);
#ifdef EXTERNAL_CODECS
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
if (setCompressCodecsInfo)
{
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));
}
#endif
}
_bindInfoExPrev = bindInfo;
_bindInfoExPrevIsDefined = true;
}
int i;
_mixerCoderCommon->ReInit();
UInt32 packStreamIndex = 0, unPackStreamIndex = 0;
UInt32 coderIndex = 0;
// UInt32 coder2Index = 0;
for (i = 0; i < numCoders; i++)
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
CMyComPtr<IUnknown> &decoder = _decoders[coderIndex];
{
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
if (setDecoderProperties)
{
const CByteBuffer &properties = coderInfo.Properties;
size_t size = properties.GetCapacity();
if (size > 0xFFFFFFFF)
return E_NOTIMPL;
if (size > 0)
{
RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, (UInt32)size));
}
}
}
#ifdef COMPRESS_MT
if (mtMode)
{
CMyComPtr<ICompressSetCoderMt> setCoderMt;
decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
if (setCoderMt)
{
RINOK(setCoderMt->SetNumberOfThreads(numThreads));
}
}
#endif
#ifndef _NO_CRYPTO
{
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
if (cryptoSetPassword)
{
if (getTextPassword == 0)
return E_FAIL;
CMyComBSTR password;
RINOK(getTextPassword->CryptoGetTextPassword(&password));
CByteBuffer buffer;
UString unicodePassword(password);
const UInt32 sizeInBytes = unicodePassword.Length() * 2;
buffer.SetCapacity(sizeInBytes);
for (int i = 0; i < unicodePassword.Length(); i++)
{
wchar_t c = unicodePassword[i];
((Byte *)buffer)[i * 2] = (Byte)c;
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
}
RINOK(cryptoSetPassword->CryptoSetPassword(
(const Byte *)buffer, sizeInBytes));
}
}
#endif
coderIndex++;
UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;
UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;
CRecordVector<const UInt64 *> packSizesPointers;
CRecordVector<const UInt64 *> unPackSizesPointers;
packSizesPointers.Reserve(numInStreams);
unPackSizesPointers.Reserve(numOutStreams);
UInt32 j;
for (j = 0; j < numOutStreams; j++, unPackStreamIndex++)
unPackSizesPointers.Add(&folderInfo.UnPackSizes[unPackStreamIndex]);
for (j = 0; j < numInStreams; j++, packStreamIndex++)
{
int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);
if (bindPairIndex >= 0)
packSizesPointers.Add(
&folderInfo.UnPackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]);
else
{
int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);
if (index < 0)
return E_FAIL;
packSizesPointers.Add(&packSizes[index]);
}
}
_mixerCoderCommon->SetCoderInfo(i,
&packSizesPointers.Front(),
&unPackSizesPointers.Front());
}
UInt32 mainCoder, temp;
bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);
if (_multiThread)
_mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);
/*
else
_mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;
*/
if (numCoders == 0)
return 0;
CRecordVector<ISequentialInStream *> inStreamPointers;
inStreamPointers.Reserve(inStreams.Size());
for (i = 0; i < inStreams.Size(); i++)
inStreamPointers.Add(inStreams[i]);
ISequentialOutStream *outStreamPointer = outStream;
return _mixerCoder->Code(&inStreamPointers.Front(), NULL,
inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress);
}
}}

View file

@ -0,0 +1,68 @@
// 7zDecode.h
#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 "7zItem.h"
namespace NArchive {
namespace N7z {
struct CBindInfoEx: public NCoderMixer::CBindInfo
{
CRecordVector<CMethodId> CoderMethodIDs;
void Clear()
{
CBindInfo::Clear();
CoderMethodIDs.Clear();
}
};
class CDecoder
{
bool _bindInfoExPrevIsDefined;
CBindInfoEx _bindInfoExPrev;
bool _multiThread;
#ifdef _ST_MODE
NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec;
#endif
NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec;
NCoderMixer::CCoderMixer2 *_mixerCoderCommon;
CMyComPtr<ICompressCoder2> _mixerCoder;
CObjectVector<CMyComPtr<IUnknown> > _decoders;
// CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2;
public:
CDecoder(bool multiThread);
HRESULT Decode(
DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream,
UInt64 startPos,
const UInt64 *packSizes,
const CFolder &folder,
ISequentialOutStream *outStream,
ICompressProgressInfo *compressProgress
#ifndef _NO_CRYPTO
, ICryptoGetTextPassword *getTextPasswordSpec
#endif
#ifdef COMPRESS_MT
, bool mtMode, UInt32 numThreads
#endif
);
};
}}
#endif

View file

@ -0,0 +1,453 @@
// Encode.cpp
#include "StdAfx.h"
#include "7zEncode.h"
#include "7zSpecStream.h"
#include "../../IPassword.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/LimitedStreams.h"
#include "../../Common/InOutTempBuffer.h"
#include "../../Common/StreamObjects.h"
#include "../../Common/CreateCoder.h"
#include "../../Common/FilterCoder.h"
static const UInt64 k_AES = 0x06F10701;
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)
{
folder.Coders.Clear();
// bindInfo.CoderMethodIDs.Clear();
// folder.OutStreams.Clear();
folder.PackStreams.Clear();
folder.BindPairs.Clear();
int i;
for (i = 0; i < bindInfo.BindPairs.Size(); i++)
{
CBindPair bindPair;
bindPair.InIndex = bindInfo.BindPairs[i].InIndex;
bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex;
folder.BindPairs.Add(bindPair);
}
for (i = 0; i < bindInfo.Coders.Size(); i++)
{
CCoderInfo coderInfo;
const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
coderInfo.NumInStreams = coderStreamsInfo.NumInStreams;
coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams;
coderInfo.MethodID = decompressionMethods[i];
folder.Coders.Add(coderInfo);
}
for (i = 0; i < bindInfo.InStreams.Size(); i++)
folder.PackStreams.Add(bindInfo.InStreams[i]);
}
HRESULT CEncoder::CreateMixerCoder(
DECL_EXTERNAL_CODECS_LOC_VARS
const UInt64 *inSizeForReduce)
{
_mixerCoderSpec = new NCoderMixer::CCoderMixer2MT;
_mixerCoder = _mixerCoderSpec;
RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo));
for (int i = 0; i < _options.Methods.Size(); i++)
{
const CMethodFull &methodFull = _options.Methods[i];
_codersInfo.Add(CCoderInfo());
CCoderInfo &encodingInfo = _codersInfo.Back();
encodingInfo.MethodID = methodFull.Id;
CMyComPtr<ICompressCoder> encoder;
CMyComPtr<ICompressCoder2> encoder2;
RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS
methodFull.Id, encoder, encoder2, true));
if (!encoder && !encoder2)
return E_FAIL;
CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2;
#ifdef COMPRESS_MT
{
CMyComPtr<ICompressSetCoderMt> setCoderMt;
encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
if (setCoderMt)
{
RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads));
}
}
#endif
RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon));
/*
CMyComPtr<ICryptoResetSalt> resetSalt;
encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt);
if (resetSalt != NULL)
{
resetSalt->ResetSalt();
}
*/
#ifdef EXTERNAL_CODECS
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
if (setCompressCodecsInfo)
{
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));
}
#endif
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
if (cryptoSetPassword)
{
CByteBuffer buffer;
const UInt32 sizeInBytes = _options.Password.Length() * 2;
buffer.SetCapacity(sizeInBytes);
for (int i = 0; i < _options.Password.Length(); i++)
{
wchar_t c = _options.Password[i];
((Byte *)buffer)[i * 2] = (Byte)c;
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
}
RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));
}
if (encoder)
_mixerCoderSpec->AddCoder(encoder);
else
_mixerCoderSpec->AddCoder2(encoder2);
}
return S_OK;
}
HRESULT CEncoder::Encode(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream,
const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,
CFolder &folderItem,
ISequentialOutStream *outStream,
CRecordVector<UInt64> &packSizes,
ICompressProgressInfo *compressProgress)
{
RINOK(EncoderConstr());
if (_mixerCoderSpec == NULL)
{
RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));
}
_mixerCoderSpec->ReInit();
// _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress);
CObjectVector<CInOutTempBuffer> inOutTempBuffers;
CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs;
CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
int numMethods = _bindInfo.Coders.Size();
int i;
for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
{
inOutTempBuffers.Add(CInOutTempBuffer());
inOutTempBuffers.Back().Create();
inOutTempBuffers.Back().InitWriting();
}
for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
{
CSequentialOutTempBufferImp *tempBufferSpec =
new CSequentialOutTempBufferImp;
CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
tempBufferSpec->Init(&inOutTempBuffers[i - 1]);
tempBuffers.Add(tempBuffer);
tempBufferSpecs.Add(tempBufferSpec);
}
for (i = 0; i < numMethods; i++)
_mixerCoderSpec->SetCoderInfo(i, NULL, NULL);
if (_bindInfo.InStreams.IsEmpty())
return E_FAIL;
UInt32 mainCoderIndex, mainStreamIndex;
_bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex);
if (inStreamSize != NULL)
{
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);
}
// UInt64 outStreamStartPos;
// RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos));
CSequentialInStreamSizeCount2 *inStreamSizeCountSpec =
new CSequentialInStreamSizeCount2;
CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
CSequentialOutStreamSizeCount *outStreamSizeCountSpec =
new CSequentialOutStreamSizeCount;
CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec;
inStreamSizeCountSpec->Init(inStream);
outStreamSizeCountSpec->SetStream(outStream);
outStreamSizeCountSpec->Init();
CRecordVector<ISequentialInStream *> inStreamPointers;
CRecordVector<ISequentialOutStream *> outStreamPointers;
inStreamPointers.Add(inStreamSizeCount);
outStreamPointers.Add(outStreamSizeCount);
for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
outStreamPointers.Add(tempBuffers[i - 1]);
for (i = 0; i < _codersInfo.Size(); i++)
{
CCoderInfo &encodingInfo = _codersInfo[i];
CMyComPtr<ICryptoResetInitVector> resetInitVector;
_mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
if (resetInitVector != NULL)
{
resetInitVector->ResetInitVector();
}
CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
_mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
if (writeCoderProperties != NULL)
{
CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp;
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
outStreamSpec->Init();
writeCoderProperties->WriteCoderProperties(outStream);
size_t size = outStreamSpec->GetSize();
encodingInfo.Properties.SetCapacity(size);
memmove(encodingInfo.Properties, outStreamSpec->GetBuffer(), size);
}
}
UInt32 progressIndex = mainCoderIndex;
for (i = 0; i < _codersInfo.Size(); i++)
{
const CCoderInfo &e = _codersInfo[i];
if ((e.MethodID == k_BCJ || e.MethodID == k_BCJ2) && i + 1 < _codersInfo.Size())
progressIndex = i + 1;
}
_mixerCoderSpec->SetProgressCoderIndex(progressIndex);
RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1,
&outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress));
ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods,
folderItem);
packSizes.Add(outStreamSizeCountSpec->GetSize());
for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
{
CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];
inOutTempBuffer.FlushWrite();
inOutTempBuffer.InitReading();
inOutTempBuffer.WriteToStream(outStream);
packSizes.Add(inOutTempBuffer.GetDataSize());
}
for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++)
{
int binder = _bindInfo.FindBinderForInStream(
_bindReverseConverter->DestOutToSrcInMap[i]);
UInt64 streamSize;
if (binder < 0)
streamSize = inStreamSizeCountSpec->GetSize();
else
streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder);
folderItem.UnPackSizes.Add(streamSize);
}
for (i = numMethods - 1; i >= 0; i--)
folderItem.Coders[numMethods - 1 - i].Properties = _codersInfo[i].Properties;
return S_OK;
}
CEncoder::CEncoder(const CCompressionMethodMode &options):
_bindReverseConverter(0),
_constructed(false)
{
if (options.IsEmpty())
throw 1;
_options = options;
_mixerCoderSpec = NULL;
}
HRESULT CEncoder::EncoderConstr()
{
if (_constructed)
return S_OK;
if (_options.Methods.IsEmpty())
{
// it has only password method;
if (!_options.PasswordIsDefined)
throw 1;
if (!_options.Binds.IsEmpty())
throw 1;
NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
CMethodFull method;
method.NumInStreams = 1;
method.NumOutStreams = 1;
coderStreamsInfo.NumInStreams = 1;
coderStreamsInfo.NumOutStreams = 1;
method.Id = k_AES;
_options.Methods.Add(method);
_bindInfo.Coders.Add(coderStreamsInfo);
_bindInfo.InStreams.Add(0);
_bindInfo.OutStreams.Add(0);
}
else
{
UInt32 numInStreams = 0, numOutStreams = 0;
int 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())
{
if (i < _options.Methods.Size() - 1)
{
NCoderMixer::CBindPair bindPair;
bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams;
bindPair.OutIndex = numOutStreams;
_bindInfo.BindPairs.Add(bindPair);
}
else
_bindInfo.OutStreams.Insert(0, numOutStreams);
for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++)
_bindInfo.OutStreams.Add(numOutStreams + j);
}
numInStreams += coderStreamsInfo.NumInStreams;
numOutStreams += coderStreamsInfo.NumOutStreams;
_bindInfo.Coders.Add(coderStreamsInfo);
}
if (!_options.Binds.IsEmpty())
{
for (i = 0; i < _options.Binds.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);
}
for (i = 0; i < (int)numOutStreams; i++)
if (_bindInfo.FindBinderForOutStream(i) == -1)
_bindInfo.OutStreams.Add(i);
}
for (i = 0; i < (int)numInStreams; i++)
if (_bindInfo.FindBinderForInStream(i) == -1)
_bindInfo.InStreams.Add(i);
if (_bindInfo.InStreams.IsEmpty())
throw 1; // this is error
// Make main stream first in list
int inIndex = _bindInfo.InStreams[0];
for (;;)
{
UInt32 coderIndex, coderStreamIndex;
_bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex);
UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);
int binder = _bindInfo.FindBinderForOutStream(outIndex);
if (binder >= 0)
{
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);
break;
}
break;
}
if (_options.PasswordIsDefined)
{
int numCryptoStreams = _bindInfo.OutStreams.Size();
for (i = 0; i < numCryptoStreams; i++)
{
NCoderMixer::CBindPair bindPair;
bindPair.InIndex = numInStreams + i;
bindPair.OutIndex = _bindInfo.OutStreams[i];
_bindInfo.BindPairs.Add(bindPair);
}
_bindInfo.OutStreams.Clear();
/*
if (numCryptoStreams == 0)
numCryptoStreams = 1;
*/
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.Id = k_AES;
_options.Methods.Add(method);
_bindInfo.Coders.Add(coderStreamsInfo);
_bindInfo.OutStreams.Add(numOutStreams + i);
}
}
}
for (int i = _options.Methods.Size() - 1; i >= 0; i--)
{
const CMethodFull &methodFull = _options.Methods[i];
_decompressionMethods.Add(methodFull.Id);
}
_bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo);
_bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo);
_constructed = true;
return S_OK;
}
CEncoder::~CEncoder()
{
delete _bindReverseConverter;
}
}}

View file

@ -0,0 +1,55 @@
// 7zEncode.h
#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"
namespace NArchive {
namespace N7z {
class CEncoder
{
NCoderMixer::CCoderMixer2MT *_mixerCoderSpec;
CMyComPtr<ICompressCoder2> _mixerCoder;
CObjectVector<CCoderInfo> _codersInfo;
CCompressionMethodMode _options;
NCoderMixer::CBindInfo _bindInfo;
NCoderMixer::CBindInfo _decompressBindInfo;
NCoderMixer::CBindReverseConverter *_bindReverseConverter;
CRecordVector<CMethodId> _decompressionMethods;
HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS
const UInt64 *inSizeForReduce);
bool _constructed;
public:
CEncoder(const CCompressionMethodMode &options);
~CEncoder();
HRESULT EncoderConstr();
HRESULT Encode(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream,
const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,
CFolder &folderItem,
ISequentialOutStream *outStream,
CRecordVector<UInt64> &packSizes,
ICompressProgressInfo *compressProgress);
};
}}
#endif

View file

@ -0,0 +1,269 @@
// 7zExtract.cpp
#include "StdAfx.h"
#include "7zHandler.h"
#include "7zFolderOutStream.h"
#include "7zDecode.h"
// #include "7z1Decode.h"
#include "../../../Common/ComTry.h"
#include "../../Common/StreamObjects.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/LimitedStreams.h"
namespace NArchive {
namespace N7z {
struct CExtractFolderInfo
{
#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.Reserve(1);
ExtractStatuses.Add(true);
}
};
};
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;
bool allFilesMode = (numItems == UInt32(-1));
if (allFilesMode)
numItems =
#ifdef _7Z_VOL
_refs.Size();
#else
_database.Files.Size();
#endif
if(numItems == 0)
return S_OK;
/*
if(_volumes.Size() != 1)
return E_FAIL;
const CVolume &volume = _volumes.Front();
const CArchiveDatabaseEx &_database = 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++)
{
#ifdef _7Z_VOL
// const CRef &ref = ref2.Refs[ri];
const CRef &ref = _refs[ref2Index];
int volumeIndex = ref.VolumeIndex;
const CVolume &volume = _volumes[volumeIndex];
const CArchiveDatabaseEx &database = volume.Database;
UInt32 fileIndex = ref.ItemIndex;
#else
const CArchiveDatabaseEx &database = _database;
UInt32 fileIndex = ref2Index;
#endif
CNum folderIndex = database.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));
const CFolder &folderInfo = database.Folders[folderIndex];
UInt64 unPackSize = folderInfo.GetUnPackSize();
importantTotalUnPacked += unPackSize;
extractFolderInfoVector.Back().UnPackSize = unPackSize;
}
CExtractFolderInfo &efi = extractFolderInfoVector.Back();
// const CFolderInfo &folderInfo = m_dam_Folders[folderIndex];
CNum startIndex = database.FolderStartFileIndex[folderIndex];
for (CNum index = efi.ExtractStatuses.Size();
index <= fileIndex - startIndex; index++)
{
// UInt64 unPackSize = _database.Files[startIndex + index].UnPackSize;
// Count partial_folder_size
// efi.UnPackSize += unPackSize;
// importantTotalUnPacked += unPackSize;
efi.ExtractStatuses.Add(index == fileIndex - startIndex);
}
}
}
extractCallback->SetTotal(importantTotalUnPacked);
CDecoder decoder(
#ifdef _ST_MODE
false
#else
true
#endif
);
// CDecoder1 decoder;
UInt64 currentTotalPacked = 0;
UInt64 currentTotalUnPacked = 0;
UInt64 totalFolderUnPacked;
UInt64 totalFolderPacked;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false);
for(int i = 0; i < extractFolderInfoVector.Size(); i++,
currentTotalUnPacked += totalFolderUnPacked,
currentTotalPacked += totalFolderPacked)
{
lps->OutSize = currentTotalUnPacked;
lps->InSize = currentTotalPacked;
RINOK(lps->SetCur());
const CExtractFolderInfo &efi = extractFolderInfoVector[i];
totalFolderUnPacked = efi.UnPackSize;
totalFolderPacked = 0;
CFolderOutStream *folderOutStream = new CFolderOutStream;
CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
#ifdef _7Z_VOL
const CVolume &volume = _volumes[efi.VolumeIndex];
const CArchiveDatabaseEx &database = volume.Database;
#else
const CArchiveDatabaseEx &database = _database;
#endif
CNum startIndex;
if (efi.FileIndex != kNumNoIndex)
startIndex = efi.FileIndex;
else
startIndex = database.FolderStartFileIndex[efi.FolderIndex];
HRESULT result = folderOutStream->Init(&database,
#ifdef _7Z_VOL
volume.StartRef2Index,
#else
0,
#endif
startIndex,
&efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0);
RINOK(result);
if (efi.FileIndex != kNumNoIndex)
continue;
CNum folderIndex = efi.FolderIndex;
const CFolder &folderInfo = database.Folders[folderIndex];
totalFolderPacked = _database.GetFolderFullPackSize(folderIndex);
CNum packStreamIndex = database.FolderStartPackStreamIndex[folderIndex];
UInt64 folderStartPackPos = database.GetFolderStreamPos(folderIndex, 0);
#ifndef _NO_CRYPTO
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
if (extractCallback)
extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
#endif
try
{
HRESULT result = decoder.Decode(
EXTERNAL_CODECS_VARS
#ifdef _7Z_VOL
volume.Stream,
#else
_inStream,
#endif
folderStartPackPos,
&database.PackSizes[packStreamIndex],
folderInfo,
outStream,
progress
#ifndef _NO_CRYPTO
, getTextPassword
#endif
#ifdef COMPRESS_MT
, true, _numThreads
#endif
);
if (result == S_FALSE)
{
RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError));
continue;
}
if (result == E_NOTIMPL)
{
RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
continue;
}
if (result != S_OK)
return result;
if (folderOutStream->WasWritingFinished() != S_OK)
{
RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError));
continue;
}
}
catch(...)
{
RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError));
continue;
}
}
return S_OK;
COM_TRY_END
}
}}

View file

@ -0,0 +1,130 @@
// 7zFolderInStream.cpp
#include "StdAfx.h"
#include "7zFolderInStream.h"
namespace NArchive {
namespace N7z {
CFolderInStream::CFolderInStream()
{
_inStreamWithHashSpec = new CSequentialInStreamWithCRC;
_inStreamWithHash = _inStreamWithHashSpec;
}
void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,
const UInt32 *fileIndices, UInt32 numFiles)
{
_updateCallback = updateCallback;
_numFiles = numFiles;
_fileIndex = 0;
_fileIndices = fileIndices;
Processed.Clear();
CRCs.Clear();
Sizes.Clear();
_fileIsOpen = false;
_currentSizeIsDefined = false;
}
HRESULT CFolderInStream::OpenStream()
{
_filePos = 0;
while (_fileIndex < _numFiles)
{
_currentSizeIsDefined = false;
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();
if (!stream)
{
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
Sizes.Add(0);
Processed.Add(result == S_OK);
AddDigest();
continue;
}
CMyComPtr<IStreamGetSize> streamGetSize;
if (stream.QueryInterface(IID_IStreamGetSize, &streamGetSize) == S_OK)
{
if(streamGetSize)
{
_currentSizeIsDefined = true;
RINOK(streamGetSize->GetSize(&_currentSize));
}
}
_fileIsOpen = true;
return S_OK;
}
return S_OK;
}
void CFolderInStream::AddDigest()
{
CRCs.Add(_inStreamWithHashSpec->GetCRC());
}
HRESULT CFolderInStream::CloseStream()
{
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
_inStreamWithHashSpec->ReleaseStream();
_fileIsOpen = false;
Processed.Add(true);
Sizes.Add(_filePos);
AddDigest();
return S_OK;
}
STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 realProcessedSize = 0;
while ((_fileIndex < _numFiles || _fileIsOpen) && size > 0)
{
if (_fileIsOpen)
{
UInt32 localProcessedSize;
RINOK(_inStreamWithHash->Read(
((Byte *)data) + realProcessedSize, size, &localProcessedSize));
if (localProcessedSize == 0)
{
RINOK(CloseStream());
continue;
}
realProcessedSize += localProcessedSize;
_filePos += localProcessedSize;
size -= localProcessedSize;
break;
}
else
{
RINOK(OpenStream());
}
}
if (processedSize != 0)
*processedSize = realProcessedSize;
return S_OK;
}
STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
{
*value = 0;
int subStreamIndex = (int)subStream;
if (subStreamIndex < 0 || subStream > Sizes.Size())
return E_FAIL;
if (subStreamIndex < Sizes.Size())
{
*value= Sizes[subStreamIndex];
return S_OK;
}
if (!_currentSizeIsDefined)
return S_FALSE;
*value = _currentSize;
return S_OK;
}
}}

View file

@ -0,0 +1,66 @@
// 7z/FolderInStream.h
#ifndef __7Z_FOLDERINSTREAM_H
#define __7Z_FOLDERINSTREAM_H
#include "7zItem.h"
#include "7zHeader.h"
#include "../IArchive.h"
#include "../Common/InStreamWithCRC.h"
#include "../../IStream.h"
#include "../../ICoder.h"
namespace NArchive {
namespace N7z {
class CFolderInStream:
public ISequentialInStream,
public ICompressGetSubStreamSize,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
CFolderInStream();
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
private:
CSequentialInStreamWithCRC *_inStreamWithHashSpec;
CMyComPtr<ISequentialInStream> _inStreamWithHash;
CMyComPtr<IArchiveUpdateCallback> _updateCallback;
bool _currentSizeIsDefined;
UInt64 _currentSize;
bool _fileIsOpen;
UInt64 _filePos;
const UInt32 *_fileIndices;
UInt32 _numFiles;
UInt32 _fileIndex;
HRESULT OpenStream();
HRESULT CloseStream();
void AddDigest();
public:
void Init(IArchiveUpdateCallback *updateCallback,
const UInt32 *fileIndices, UInt32 numFiles);
CRecordVector<bool> Processed;
CRecordVector<UInt32> CRCs;
CRecordVector<UInt64> Sizes;
UInt64 GetFullSize() const
{
UInt64 size = 0;
for (int i = 0; i < Sizes.Size(); i++)
size += Sizes[i];
return size;
}
};
}}
#endif

View file

@ -0,0 +1,165 @@
// 7zFolderOutStream.cpp
#include "StdAfx.h"
#include "7zFolderOutStream.h"
namespace NArchive {
namespace N7z {
CFolderOutStream::CFolderOutStream()
{
_outStreamWithHashSpec = new COutStreamWithCRC;
_outStreamWithHash = _outStreamWithHashSpec;
}
HRESULT CFolderOutStream::Init(
const CArchiveDatabaseEx *archiveDatabase,
UInt32 ref2Offset,
UInt32 startIndex,
const CBoolVector *extractStatuses,
IArchiveExtractCallback *extractCallback,
bool testMode,
bool checkCrc)
{
_archiveDatabase = archiveDatabase;
_ref2Offset = ref2Offset;
_startIndex = startIndex;
_extractStatuses = extractStatuses;
_extractCallback = extractCallback;
_testMode = testMode;
_checkCrc = checkCrc;
_currentIndex = 0;
_fileIsOpen = false;
return WriteEmptyFiles();
}
HRESULT CFolderOutStream::OpenFile()
{
Int32 askMode;
if((*_extractStatuses)[_currentIndex])
askMode = _testMode ?
NArchive::NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract;
else
askMode = NArchive::NExtract::NAskMode::kSkip;
CMyComPtr<ISequentialOutStream> realOutStream;
UInt32 index = _startIndex + _currentIndex;
RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));
_outStreamWithHashSpec->SetStream(realOutStream);
_outStreamWithHashSpec->Init(_checkCrc);
if (askMode == NArchive::NExtract::NAskMode::kExtract &&
(!realOutStream))
{
const CFileItem &fileInfo = _archiveDatabase->Files[index];
if (!fileInfo.IsAnti && !fileInfo.IsDirectory)
askMode = NArchive::NExtract::NAskMode::kSkip;
}
return _extractCallback->PrepareOperation(askMode);
}
HRESULT CFolderOutStream::WriteEmptyFiles()
{
for(;_currentIndex < _extractStatuses->Size(); _currentIndex++)
{
UInt32 index = _startIndex + _currentIndex;
const CFileItem &fileInfo = _archiveDatabase->Files[index];
if (!fileInfo.IsAnti && !fileInfo.IsDirectory && fileInfo.UnPackSize != 0)
return S_OK;
RINOK(OpenFile());
RINOK(_extractCallback->SetOperationResult(
NArchive::NExtract::NOperationResult::kOK));
_outStreamWithHashSpec->ReleaseStream();
}
return S_OK;
}
STDMETHODIMP CFolderOutStream::Write(const void *data,
UInt32 size, UInt32 *processedSize)
{
UInt32 realProcessedSize = 0;
while(_currentIndex < _extractStatuses->Size())
{
if (_fileIsOpen)
{
UInt32 index = _startIndex + _currentIndex;
const CFileItem &fileInfo = _archiveDatabase->Files[index];
UInt64 fileSize = fileInfo.UnPackSize;
UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - _filePos,
UInt64(size - realProcessedSize));
UInt32 processedSizeLocal;
RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize,
numBytesToWrite, &processedSizeLocal));
_filePos += processedSizeLocal;
realProcessedSize += processedSizeLocal;
if (_filePos == fileSize)
{
bool digestsAreEqual;
if (fileInfo.IsFileCRCDefined && _checkCrc)
digestsAreEqual = fileInfo.FileCRC == _outStreamWithHashSpec->GetCRC();
else
digestsAreEqual = true;
RINOK(_extractCallback->SetOperationResult(
digestsAreEqual ?
NArchive::NExtract::NOperationResult::kOK :
NArchive::NExtract::NOperationResult::kCRCError));
_outStreamWithHashSpec->ReleaseStream();
_fileIsOpen = false;
_currentIndex++;
}
if (realProcessedSize == size)
{
if (processedSize != NULL)
*processedSize = realProcessedSize;
return WriteEmptyFiles();
}
}
else
{
RINOK(OpenFile());
_fileIsOpen = true;
_filePos = 0;
}
}
if (processedSize != NULL)
*processedSize = size;
return S_OK;
}
HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)
{
while(_currentIndex < _extractStatuses->Size())
{
if (_fileIsOpen)
{
RINOK(_extractCallback->SetOperationResult(resultEOperationResult));
_outStreamWithHashSpec->ReleaseStream();
_fileIsOpen = false;
_currentIndex++;
}
else
{
RINOK(OpenFile());
_fileIsOpen = true;
}
}
return S_OK;
}
HRESULT CFolderOutStream::WasWritingFinished()
{
if (_currentIndex == _extractStatuses->Size())
return S_OK;
return E_FAIL;
}
}}

View file

@ -0,0 +1,60 @@
// 7zFolderOutStream.h
#ifndef __7Z_FOLDEROUTSTREAM_H
#define __7Z_FOLDEROUTSTREAM_H
#include "7zIn.h"
#include "../../IStream.h"
#include "../IArchive.h"
#include "../Common/OutStreamWithCRC.h"
namespace NArchive {
namespace N7z {
class CFolderOutStream:
public ISequentialOutStream,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP
CFolderOutStream();
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
private:
COutStreamWithCRC *_outStreamWithHashSpec;
CMyComPtr<ISequentialOutStream> _outStreamWithHash;
const CArchiveDatabaseEx *_archiveDatabase;
const CBoolVector *_extractStatuses;
UInt32 _startIndex;
UInt32 _ref2Offset;
int _currentIndex;
// UInt64 _currentDataPos;
CMyComPtr<IArchiveExtractCallback> _extractCallback;
bool _testMode;
bool _fileIsOpen;
bool _checkCrc;
UInt64 _filePos;
HRESULT OpenFile();
HRESULT WriteEmptyFiles();
public:
HRESULT Init(
const CArchiveDatabaseEx *archiveDatabase,
UInt32 ref2Offset,
UInt32 startIndex,
const CBoolVector *extractStatuses,
IArchiveExtractCallback *extractCallback,
bool testMode,
bool checkCrc);
HRESULT FlushCorrupted(Int32 resultEOperationResult);
HRESULT WasWritingFinished();
};
}}
#endif

View file

@ -0,0 +1,793 @@
// 7zHandler.cpp
#include "StdAfx.h"
#include "7zHandler.h"
#include "7zProperties.h"
#include "../../../Common/IntToString.h"
#include "../../../Common/ComTry.h"
#include "../../../Windows/Defs.h"
#include "../Common/ItemNameUtils.h"
#ifdef _7Z_VOL
#include "../Common/MultiStream.h"
#endif
#ifdef __7Z_SET_PROPERTIES
#ifdef EXTRACT_ONLY
#include "../Common/ParseProperties.h"
#endif
#endif
#ifdef COMPRESS_MT
#include "../../../Windows/System.h"
#endif
using namespace NWindows;
extern UString ConvertMethodIdToString(UInt64 id);
namespace NArchive {
namespace N7z {
CHandler::CHandler()
{
_crcSize = 4;
#ifdef EXTRACT_ONLY
#ifdef COMPRESS_MT
_numThreads = NWindows::NSystem::GetNumberOfProcessors();
#endif
#else
Init();
#endif
}
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
*numItems =
#ifdef _7Z_VOL
_refs.Size();
#else
*numItems = _database.Files.Size();
#endif
return S_OK;
}
#ifdef _SFX
IMP_IInArchive_ArcProps_NO
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */)
{
return E_NOTIMPL;
}
STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
{
return E_NOTIMPL;
}
#else
STATPROPSTG kArcProps[] =
{
{ NULL, kpidMethod, VT_BSTR},
{ NULL, kpidSolid, VT_BOOL},
{ NULL, kpidNumBlocks, VT_UI4}
};
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
switch(propID)
{
case kpidMethod:
{
UString resString;
CRecordVector<UInt64> ids;
int i;
for (i = 0; i < _database.Folders.Size(); i++)
{
const CFolder &f = _database.Folders[i];
for (int j = f.Coders.Size() - 1; j >= 0; j--)
ids.AddToUniqueSorted(f.Coders[j].MethodID);
}
for (i = 0; i < ids.Size(); i++)
{
UInt64 id = ids[i];
UString methodName;
/* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName);
if (methodName.IsEmpty())
methodName = ConvertMethodIdToString(id);
if (!resString.IsEmpty())
resString += L' ';
resString += methodName;
}
prop = resString;
break;
}
case kpidSolid: prop = _database.IsSolid(); break;
case kpidNumBlocks: prop = (UInt32)_database.Folders.Size(); break;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
IMP_IInArchive_ArcProps
#endif
static void MySetFileTime(bool timeDefined, FILETIME unixTime, NWindows::NCOM::CPropVariant &prop)
{
if (timeDefined)
prop = unixTime;
}
#ifndef _SFX
static UString ConvertUInt32ToString(UInt32 value)
{
wchar_t buffer[32];
ConvertUInt64ToString(value, buffer);
return buffer;
}
static UString GetStringForSizeValue(UInt32 value)
{
for (int i = 31; i >= 0; i--)
if ((UInt32(1) << i) == value)
return ConvertUInt32ToString(i);
UString result;
if (value % (1 << 20) == 0)
{
result += ConvertUInt32ToString(value >> 20);
result += L"m";
}
else if (value % (1 << 10) == 0)
{
result += ConvertUInt32ToString(value >> 10);
result += L"k";
}
else
{
result += ConvertUInt32ToString(value);
result += L"b";
}
return result;
}
static const UInt64 k_Copy = 0x0;
static const UInt64 k_LZMA = 0x030101;
static const UInt64 k_PPMD = 0x030401;
static wchar_t GetHex(Byte value)
{
return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10)));
}
static inline UString GetHex2(Byte value)
{
UString result;
result += GetHex((Byte)(value >> 4));
result += GetHex((Byte)(value & 0xF));
return result;
}
#endif
static const UInt64 k_AES = 0x06F10701;
#ifndef _SFX
static inline UInt32 GetUInt32FromMemLE(const Byte *p)
{
return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24);
}
#endif
bool CHandler::IsEncrypted(UInt32 index2) const
{
CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
if (folderIndex != kNumNoIndex)
{
const CFolder &folderInfo = _database.Folders[folderIndex];
for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
if (folderInfo.Coders[i].MethodID == k_AES)
return true;
}
return false;
}
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
/*
const CRef2 &ref2 = _refs[index];
if (ref2.Refs.IsEmpty())
return E_FAIL;
const CRef &ref = ref2.Refs.Front();
*/
#ifdef _7Z_VOL
const CRef &ref = _refs[index];
const CVolume &volume = _volumes[ref.VolumeIndex];
const CArchiveDatabaseEx &_database = volume.Database;
UInt32 index2 = ref.ItemIndex;
const CFileItem &item = _database.Files[index2];
#else
const CFileItem &item = _database.Files[index];
UInt32 index2 = index;
#endif
switch(propID)
{
case kpidPath:
{
if (!item.Name.IsEmpty())
prop = NItemName::GetOSName(item.Name);
break;
}
case kpidIsFolder:
prop = item.IsDirectory;
break;
case kpidSize:
{
prop = item.UnPackSize;
// prop = ref2.UnPackSize;
break;
}
case kpidPosition:
{
/*
if (ref2.Refs.Size() > 1)
prop = ref2.StartPos;
else
*/
if (item.IsStartPosDefined)
prop = item.StartPos;
break;
}
case kpidPackedSize:
{
// prop = ref2.PackSize;
{
CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
if (folderIndex != kNumNoIndex)
{
if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2)
prop = _database.GetFolderFullPackSize(folderIndex);
/*
else
prop = (UInt64)0;
*/
}
else
prop = (UInt64)0;
}
break;
}
case kpidLastAccessTime:
MySetFileTime(item.IsLastAccessTimeDefined, item.LastAccessTime, prop);
break;
case kpidCreationTime:
MySetFileTime(item.IsCreationTimeDefined, item.CreationTime, prop);
break;
case kpidLastWriteTime:
MySetFileTime(item.IsLastWriteTimeDefined, item.LastWriteTime, prop);
break;
case kpidAttributes:
if (item.AreAttributesDefined)
prop = item.Attributes;
break;
case kpidCRC:
if (item.IsFileCRCDefined)
prop = item.FileCRC;
break;
case kpidEncrypted:
{
prop = IsEncrypted(index2);
break;
}
#ifndef _SFX
case kpidMethod:
{
CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
if (folderIndex != kNumNoIndex)
{
const CFolder &folderInfo = _database.Folders[folderIndex];
UString methodsString;
for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
if (!methodsString.IsEmpty())
methodsString += L' ';
{
UString methodName;
bool methodIsKnown = FindMethod(
EXTERNAL_CODECS_VARS
coderInfo.MethodID, methodName);
if (methodIsKnown)
{
methodsString += methodName;
if (coderInfo.MethodID == k_LZMA)
{
if (coderInfo.Properties.GetCapacity() >= 5)
{
methodsString += L":";
UInt32 dicSize = GetUInt32FromMemLE(
((const Byte *)coderInfo.Properties + 1));
methodsString += GetStringForSizeValue(dicSize);
}
}
else if (coderInfo.MethodID == k_PPMD)
{
if (coderInfo.Properties.GetCapacity() >= 5)
{
Byte order = *(const Byte *)coderInfo.Properties;
methodsString += L":o";
methodsString += ConvertUInt32ToString(order);
methodsString += L":mem";
UInt32 dicSize = GetUInt32FromMemLE(
((const Byte *)coderInfo.Properties + 1));
methodsString += GetStringForSizeValue(dicSize);
}
}
else if (coderInfo.MethodID == k_AES)
{
if (coderInfo.Properties.GetCapacity() >= 1)
{
methodsString += L":";
const Byte *data = (const Byte *)coderInfo.Properties;
Byte firstByte = *data++;
UInt32 numCyclesPower = firstByte & 0x3F;
methodsString += ConvertUInt32ToString(numCyclesPower);
/*
if ((firstByte & 0xC0) != 0)
{
methodsString += L":";
return S_OK;
UInt32 saltSize = (firstByte >> 7) & 1;
UInt32 ivSize = (firstByte >> 6) & 1;
if (coderInfo.Properties.GetCapacity() >= 2)
{
Byte secondByte = *data++;
saltSize += (secondByte >> 4);
ivSize += (secondByte & 0x0F);
}
}
*/
}
}
else
{
if (coderInfo.Properties.GetCapacity() > 0)
{
methodsString += L":[";
for (size_t bi = 0; bi < coderInfo.Properties.GetCapacity(); bi++)
{
if (bi > 5 && bi + 1 < coderInfo.Properties.GetCapacity())
{
methodsString += L"..";
break;
}
else
methodsString += GetHex2(coderInfo.Properties[bi]);
}
methodsString += L"]";
}
}
}
else
{
methodsString += ConvertMethodIdToString(coderInfo.MethodID);
}
}
}
prop = methodsString;
}
}
break;
case kpidBlock:
{
CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
if (folderIndex != kNumNoIndex)
prop = (UInt32)folderIndex;
}
break;
case kpidPackedSize0:
case kpidPackedSize1:
case kpidPackedSize2:
case kpidPackedSize3:
case kpidPackedSize4:
{
CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
if (folderIndex != kNumNoIndex)
{
const CFolder &folderInfo = _database.Folders[folderIndex];
if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0))
{
prop = _database.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);
}
else
prop = (UInt64)0;
}
else
prop = (UInt64)0;
}
break;
#endif
case kpidIsAnti:
prop = item.IsAnti;
break;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
#ifdef _7Z_VOL
static const wchar_t *kExt = L"7z";
static const wchar_t *kAfterPart = L".7z";
class CVolumeName
{
bool _first;
UString _unchangedPart;
UString _changedPart;
UString _afterPart;
public:
bool InitName(const UString &name)
{
_first = true;
int dotPos = name.ReverseFind('.');
UString basePart = name;
if (dotPos >= 0)
{
UString ext = name.Mid(dotPos + 1);
if (ext.CompareNoCase(kExt)==0 ||
ext.CompareNoCase(L"EXE") == 0)
{
_afterPart = kAfterPart;
basePart = name.Left(dotPos);
}
}
int numLetters = 1;
bool splitStyle = false;
if (basePart.Right(numLetters) == L"1")
{
while (numLetters < basePart.Length())
{
if (basePart[basePart.Length() - numLetters - 1] != '0')
break;
numLetters++;
}
}
else
return false;
_unchangedPart = basePart.Left(basePart.Length() - numLetters);
_changedPart = basePart.Right(numLetters);
return true;
}
UString GetNextName()
{
UString newName;
// if (_newStyle || !_first)
{
int i;
int numLetters = _changedPart.Length();
for (i = numLetters - 1; i >= 0; i--)
{
wchar_t c = _changedPart[i];
if (c == L'9')
{
c = L'0';
newName = c + newName;
if (i == 0)
newName = UString(L'1') + newName;
continue;
}
c++;
newName = UString(c) + newName;
i--;
for (; i >= 0; i--)
newName = _changedPart[i] + newName;
break;
}
_changedPart = newName;
}
_first = false;
return _unchangedPart + _changedPart + _afterPart;
}
};
#endif
STDMETHODIMP CHandler::Open(IInStream *stream,
const UInt64 *maxCheckStartPosition,
IArchiveOpenCallback *openArchiveCallback)
{
COM_TRY_BEGIN
Close();
#ifndef _SFX
_fileInfoPopIDs.Clear();
#endif
try
{
CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;
#ifdef _7Z_VOL
CVolumeName seqName;
CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
#endif
#ifndef _NO_CRYPTO
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
if (openArchiveCallback)
{
openArchiveCallbackTemp.QueryInterface(
IID_ICryptoGetTextPassword, &getTextPassword);
}
#endif
#ifdef _7Z_VOL
if (openArchiveCallback)
{
openArchiveCallbackTemp.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);
}
for (;;)
{
CMyComPtr<IInStream> inStream;
if (!_volumes.IsEmpty())
{
if (!openVolumeCallback)
break;
if(_volumes.Size() == 1)
{
UString baseName;
{
NCOM::CPropVariant prop;
RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
if (prop.vt != VT_BSTR)
break;
baseName = prop.bstrVal;
}
seqName.InitName(baseName);
}
UString fullName = seqName.GetNextName();
HRESULT result = openVolumeCallback->GetStream(fullName, &inStream);
if (result == S_FALSE)
break;
if (result != S_OK)
return result;
if (!stream)
break;
}
else
inStream = stream;
CInArchive archive;
RINOK(archive.Open(inStream, maxCheckStartPosition));
_volumes.Add(CVolume());
CVolume &volume = _volumes.Back();
CArchiveDatabaseEx &database = volume.Database;
volume.Stream = inStream;
volume.StartRef2Index = _refs.Size();
HRESULT result = archive.ReadDatabase(database
#ifndef _NO_CRYPTO
, getTextPassword
#endif
);
if (result != S_OK)
{
_volumes.Clear();
return result;
}
database.Fill();
for(int i = 0; i < database.Files.Size(); i++)
{
CRef refNew;
refNew.VolumeIndex = _volumes.Size() - 1;
refNew.ItemIndex = i;
_refs.Add(refNew);
/*
const CFileItem &file = database.Files[i];
int j;
*/
/*
for (j = _refs.Size() - 1; j >= 0; j--)
{
CRef2 &ref2 = _refs[j];
const CRef &ref = ref2.Refs.Back();
const CVolume &volume2 = _volumes[ref.VolumeIndex];
const CArchiveDatabaseEx &database2 = volume2.Database;
const CFileItem &file2 = database2.Files[ref.ItemIndex];
if (file2.Name.CompareNoCase(file.Name) == 0)
{
if (!file.IsStartPosDefined)
continue;
if (file.StartPos != ref2.StartPos + ref2.UnPackSize)
continue;
ref2.Refs.Add(refNew);
break;
}
}
*/
/*
j = -1;
if (j < 0)
{
CRef2 ref2New;
ref2New.Refs.Add(refNew);
j = _refs.Add(ref2New);
}
CRef2 &ref2 = _refs[j];
ref2.UnPackSize += file.UnPackSize;
ref2.PackSize += database.GetFilePackSize(i);
if (ref2.Refs.Size() == 1 && file.IsStartPosDefined)
ref2.StartPos = file.StartPos;
*/
}
if (database.Files.Size() != 1)
break;
const CFileItem &file = database.Files.Front();
if (!file.IsStartPosDefined)
break;
}
#else
CInArchive archive;
RINOK(archive.Open(stream, maxCheckStartPosition));
HRESULT result = archive.ReadDatabase(
EXTERNAL_CODECS_VARS
_database
#ifndef _NO_CRYPTO
, getTextPassword
#endif
);
RINOK(result);
_database.Fill();
_inStream = stream;
#endif
}
catch(...)
{
Close();
return S_FALSE;
}
// _inStream = stream;
#ifndef _SFX
FillPopIDs();
#endif
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::Close()
{
COM_TRY_BEGIN
#ifdef _7Z_VOL
_volumes.Clear();
_refs.Clear();
#else
_inStream.Release();
_database.Clear();
#endif
return S_OK;
COM_TRY_END
}
#ifdef _7Z_VOL
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
{
if (index != 0)
return E_INVALIDARG;
*stream = 0;
CMultiStream *streamSpec = new CMultiStream;
CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
UInt64 pos = 0;
const UString *fileName;
for (int i = 0; i < _refs.Size(); i++)
{
const CRef &ref = _refs[i];
const CVolume &volume = _volumes[ref.VolumeIndex];
const CArchiveDatabaseEx &database = volume.Database;
const CFileItem &file = database.Files[ref.ItemIndex];
if (i == 0)
fileName = &file.Name;
else
if (fileName->Compare(file.Name) != 0)
return S_FALSE;
if (!file.IsStartPosDefined)
return S_FALSE;
if (file.StartPos != pos)
return S_FALSE;
CNum folderIndex = database.FileIndexToFolderIndexMap[ref.ItemIndex];
if (folderIndex == kNumNoIndex)
{
if (file.UnPackSize != 0)
return E_FAIL;
continue;
}
if (database.NumUnPackStreamsVector[folderIndex] != 1)
return S_FALSE;
const CFolder &folder = database.Folders[folderIndex];
if (folder.Coders.Size() != 1)
return S_FALSE;
const CCoderInfo &coder = folder.Coders.Front();
if (coder.NumInStreams != 1 || coder.NumOutStreams != 1)
return S_FALSE;
if (coder.MethodID != k_Copy)
return S_FALSE;
pos += file.UnPackSize;
CMultiStream::CSubStreamInfo subStreamInfo;
subStreamInfo.Stream = volume.Stream;
subStreamInfo.Pos = database.GetFolderStreamPos(folderIndex, 0);
subStreamInfo.Size = file.UnPackSize;
streamSpec->Streams.Add(subStreamInfo);
}
streamSpec->Init();
*stream = streamTemp.Detach();
return S_OK;
}
#endif
#ifdef __7Z_SET_PROPERTIES
#ifdef EXTRACT_ONLY
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
{
COM_TRY_BEGIN
#ifdef COMPRESS_MT
const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
_numThreads = numProcessors;
#endif
for (int i = 0; i < numProperties; i++)
{
UString name = names[i];
name.MakeUpper();
if (name.IsEmpty())
return E_INVALIDARG;
const PROPVARIANT &value = values[i];
UInt32 number;
int index = ParseStringToUInt32(name, number);
if (index == 0)
{
if(name.Left(2).CompareNoCase(L"MT") == 0)
{
#ifdef COMPRESS_MT
RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));
#endif
continue;
}
else
return E_INVALIDARG;
}
}
return S_OK;
COM_TRY_END
}
#endif
#endif
IMPL_ISetCompressCodecsInfo
}}

View file

@ -0,0 +1,146 @@
// 7z/Handler.h
#ifndef __7Z_HANDLER_H
#define __7Z_HANDLER_H
#include "../../ICoder.h"
#include "../IArchive.h"
#include "7zIn.h"
#include "7zCompressionMode.h"
#include "../../Common/CreateCoder.h"
#ifndef EXTRACT_ONLY
#include "../Common/HandlerOut.h"
#endif
namespace NArchive {
namespace N7z {
#ifdef _7Z_VOL
struct CRef
{
int VolumeIndex;
int ItemIndex;
};
struct CVolume
{
int StartRef2Index;
CMyComPtr<IInStream> Stream;
CArchiveDatabaseEx Database;
};
#endif
#ifndef __7Z_SET_PROPERTIES
#ifdef EXTRACT_ONLY
#ifdef COMPRESS_MT
#define __7Z_SET_PROPERTIES
#endif
#else
#define __7Z_SET_PROPERTIES
#endif
#endif
class CHandler:
#ifndef EXTRACT_ONLY
public NArchive::COutHandler,
#endif
public IInArchive,
#ifdef _7Z_VOL
public IInArchiveGetStream,
#endif
#ifdef __7Z_SET_PROPERTIES
public ISetProperties,
#endif
#ifndef EXTRACT_ONLY
public IOutArchive,
#endif
PUBLIC_ISetCompressCodecsInfo
public CMyUnknownImp
{
public:
MY_QUERYINTERFACE_BEGIN2(IInArchive)
#ifdef _7Z_VOL
MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream)
#endif
#ifdef __7Z_SET_PROPERTIES
MY_QUERYINTERFACE_ENTRY(ISetProperties)
#endif
#ifndef EXTRACT_ONLY
MY_QUERYINTERFACE_ENTRY(IOutArchive)
#endif
QUERY_ENTRY_ISetCompressCodecsInfo
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
INTERFACE_IInArchive(;)
#ifdef _7Z_VOL
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
#endif
#ifdef __7Z_SET_PROPERTIES
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties);
#endif
#ifndef EXTRACT_ONLY
INTERFACE_IOutArchive(;)
#endif
DECL_ISetCompressCodecsInfo
CHandler();
private:
#ifdef _7Z_VOL
CObjectVector<CVolume> _volumes;
CObjectVector<CRef> _refs;
#else
CMyComPtr<IInStream> _inStream;
NArchive::N7z::CArchiveDatabaseEx _database;
#endif
#ifdef EXTRACT_ONLY
#ifdef COMPRESS_MT
UInt32 _numThreads;
#endif
UInt32 _crcSize;
#else
CRecordVector<CBind> _binds;
HRESULT SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback);
HRESULT SetCompressionMethod(CCompressionMethodMode &method,
CObjectVector<COneMethodInfo> &methodsInfo
#ifdef COMPRESS_MT
, UInt32 numThreads
#endif
);
HRESULT SetCompressionMethod(
CCompressionMethodMode &method,
CCompressionMethodMode &headerMethod);
#endif
bool IsEncrypted(UInt32 index2) const;
#ifndef _SFX
CRecordVector<UInt64> _fileInfoPopIDs;
void FillPopIDs();
#endif
};
}}
#endif

View file

@ -0,0 +1,464 @@
// 7zHandlerOut.cpp
#include "StdAfx.h"
#include "7zHandler.h"
#include "7zOut.h"
#include "7zUpdate.h"
#include "../../../Windows/PropVariant.h"
#include "../../../Common/ComTry.h"
#include "../../../Common/StringToInt.h"
#include "../../IPassword.h"
#include "../../ICoder.h"
#include "../Common/ItemNameUtils.h"
#include "../Common/ParseProperties.h"
using namespace NWindows;
namespace NArchive {
namespace N7z {
static const wchar_t *kLZMAMethodName = L"LZMA";
static const wchar_t *kCopyMethod = L"Copy";
static const wchar_t *kDefaultMethodName = kLZMAMethodName;
static const UInt32 kLzmaAlgorithmX5 = 1;
static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";
static const UInt32 kDictionaryForHeaders = 1 << 20;
static const UInt32 kNumFastBytesForHeaders = 273;
static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5;
static inline bool IsCopyMethod(const UString &methodName)
{ return (methodName.CompareNoCase(kCopyMethod) == 0); }
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
{
*type = NFileTimeType::kWindows;
return S_OK;
}
HRESULT CHandler::SetPassword(CCompressionMethodMode &methodMode,
IArchiveUpdateCallback *updateCallback)
{
CMyComPtr<ICryptoGetTextPassword2> getTextPassword;
if (!getTextPassword)
{
CMyComPtr<IArchiveUpdateCallback> udateCallback2(updateCallback);
udateCallback2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword);
}
if (getTextPassword)
{
CMyComBSTR password;
Int32 passwordIsDefined;
RINOK(getTextPassword->CryptoGetTextPassword2(
&passwordIsDefined, &password));
methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
if (methodMode.PasswordIsDefined)
methodMode.Password = password;
}
else
methodMode.PasswordIsDefined = false;
return S_OK;
}
HRESULT CHandler::SetCompressionMethod(
CCompressionMethodMode &methodMode,
CCompressionMethodMode &headerMethod)
{
HRESULT res = SetCompressionMethod(methodMode, _methods
#ifdef COMPRESS_MT
, _numThreads
#endif
);
RINOK(res);
methodMode.Binds = _binds;
if (_compressHeaders)
{
// headerMethod.Methods.Add(methodMode.Methods.Back());
CObjectVector<COneMethodInfo> headerMethodInfoVector;
COneMethodInfo oneMethodInfo;
oneMethodInfo.MethodName = kLZMAMethodName;
{
CProp property;
property.Id = NCoderPropID::kMatchFinder;
property.Value = kLzmaMatchFinderForHeaders;
oneMethodInfo.Properties.Add(property);
}
{
CProp property;
property.Id = NCoderPropID::kAlgorithm;
property.Value = kAlgorithmForHeaders;
oneMethodInfo.Properties.Add(property);
}
{
CProp property;
property.Id = NCoderPropID::kNumFastBytes;
property.Value = UInt32(kNumFastBytesForHeaders);
oneMethodInfo.Properties.Add(property);
}
{
CProp property;
property.Id = NCoderPropID::kDictionarySize;
property.Value = UInt32(kDictionaryForHeaders);
oneMethodInfo.Properties.Add(property);
}
headerMethodInfoVector.Add(oneMethodInfo);
HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector
#ifdef COMPRESS_MT
,1
#endif
);
RINOK(res);
}
return S_OK;
}
HRESULT CHandler::SetCompressionMethod(
CCompressionMethodMode &methodMode,
CObjectVector<COneMethodInfo> &methodsInfo
#ifdef COMPRESS_MT
, UInt32 numThreads
#endif
)
{
UInt32 level = _level;
if (methodsInfo.IsEmpty())
{
COneMethodInfo oneMethodInfo;
oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName);
methodsInfo.Add(oneMethodInfo);
}
bool needSolid = false;
for(int i = 0; i < methodsInfo.Size(); i++)
{
COneMethodInfo &oneMethodInfo = methodsInfo[i];
SetCompressionMethod2(oneMethodInfo
#ifdef COMPRESS_MT
, numThreads
#endif
);
if (!IsCopyMethod(oneMethodInfo.MethodName))
needSolid = true;
CMethodFull methodFull;
if (!FindMethod(
EXTERNAL_CODECS_VARS
oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams))
return E_INVALIDARG;
methodFull.Properties = oneMethodInfo.Properties;
methodMode.Methods.Add(methodFull);
if (!_numSolidBytesDefined)
{
for (int j = 0; j < methodFull.Properties.Size(); j++)
{
const CProp &prop = methodFull.Properties[j];
if ((prop.Id == NCoderPropID::kDictionarySize ||
prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4)
{
_numSolidBytes = ((UInt64)prop.Value.ulVal) << 7;
const UInt64 kMinSize = (1 << 24);
if (_numSolidBytes < kMinSize)
_numSolidBytes = kMinSize;
_numSolidBytesDefined = true;
break;
}
}
}
}
if (!needSolid && !_numSolidBytesDefined)
{
_numSolidBytesDefined = true;
_numSolidBytes = 0;
}
return S_OK;
}
static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, PROPID propID, CArchiveFileTime &filetime, bool &filetimeIsDefined)
{
filetimeIsDefined = false;
NCOM::CPropVariant propVariant;
RINOK(updateCallback->GetProperty(index, propID, &propVariant));
if (propVariant.vt == VT_FILETIME)
{
filetime = propVariant.filetime;
filetimeIsDefined = true;
}
else if (propVariant.vt != VT_EMPTY)
return E_INVALIDARG;
return S_OK;
}
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *updateCallback)
{
COM_TRY_BEGIN
const CArchiveDatabaseEx *database = 0;
#ifdef _7Z_VOL
if(_volumes.Size() > 1)
return E_FAIL;
const CVolume *volume = 0;
if (_volumes.Size() == 1)
{
volume = &_volumes.Front();
database = &volume->Database;
}
#else
if (_inStream != 0)
database = &_database;
#endif
// CRecordVector<bool> compressStatuses;
CObjectVector<CUpdateItem> updateItems;
// CRecordVector<UInt32> copyIndices;
// CMyComPtr<IUpdateCallback2> updateCallback2;
// updateCallback->QueryInterface(&updateCallback2);
for(UInt32 i = 0; i < numItems; i++)
{
Int32 newData;
Int32 newProperties;
UInt32 indexInArchive;
if (!updateCallback)
return E_FAIL;
RINOK(updateCallback->GetUpdateItemInfo(i,
&newData, &newProperties, &indexInArchive));
CUpdateItem updateItem;
updateItem.NewProperties = IntToBool(newProperties);
updateItem.NewData = IntToBool(newData);
updateItem.IndexInArchive = indexInArchive;
updateItem.IndexInClient = i;
updateItem.IsAnti = false;
updateItem.Size = 0;
if (updateItem.IndexInArchive != -1)
{
const CFileItem &fileItem = database->Files[updateItem.IndexInArchive];
updateItem.Name = fileItem.Name;
updateItem.IsDirectory = fileItem.IsDirectory;
updateItem.Size = fileItem.UnPackSize;
updateItem.IsAnti = fileItem.IsAnti;
updateItem.CreationTime = fileItem.CreationTime;
updateItem.IsCreationTimeDefined = fileItem.IsCreationTimeDefined;
updateItem.LastWriteTime = fileItem.LastWriteTime;
updateItem.IsLastWriteTimeDefined = fileItem.IsLastWriteTimeDefined;
updateItem.LastAccessTime = fileItem.LastAccessTime;
updateItem.IsLastAccessTimeDefined = fileItem.IsLastAccessTimeDefined;
}
if (updateItem.NewProperties)
{
bool nameIsDefined;
bool folderStatusIsDefined;
{
NCOM::CPropVariant propVariant;
RINOK(updateCallback->GetProperty(i, kpidAttributes, &propVariant));
if (propVariant.vt == VT_EMPTY)
updateItem.AttributesAreDefined = false;
else if (propVariant.vt != VT_UI4)
return E_INVALIDARG;
else
{
updateItem.Attributes = propVariant.ulVal;
updateItem.AttributesAreDefined = true;
}
}
RINOK(GetTime(updateCallback, i, kpidCreationTime, updateItem.CreationTime, updateItem.IsCreationTimeDefined));
RINOK(GetTime(updateCallback, i, kpidLastWriteTime, updateItem.LastWriteTime , updateItem.IsLastWriteTimeDefined));
RINOK(GetTime(updateCallback, i, kpidLastAccessTime, updateItem.LastAccessTime, updateItem.IsLastAccessTimeDefined));
{
NCOM::CPropVariant propVariant;
RINOK(updateCallback->GetProperty(i, kpidPath, &propVariant));
if (propVariant.vt == VT_EMPTY)
nameIsDefined = false;
else if (propVariant.vt != VT_BSTR)
return E_INVALIDARG;
else
{
updateItem.Name = NItemName::MakeLegalName(propVariant.bstrVal);
nameIsDefined = true;
}
}
{
NCOM::CPropVariant propVariant;
RINOK(updateCallback->GetProperty(i, kpidIsFolder, &propVariant));
if (propVariant.vt == VT_EMPTY)
folderStatusIsDefined = false;
else if (propVariant.vt != VT_BOOL)
return E_INVALIDARG;
else
{
updateItem.IsDirectory = (propVariant.boolVal != VARIANT_FALSE);
folderStatusIsDefined = true;
}
}
{
NCOM::CPropVariant propVariant;
RINOK(updateCallback->GetProperty(i, kpidIsAnti, &propVariant));
if (propVariant.vt == VT_EMPTY)
updateItem.IsAnti = false;
else if (propVariant.vt != VT_BOOL)
return E_INVALIDARG;
else
updateItem.IsAnti = (propVariant.boolVal != VARIANT_FALSE);
}
if (updateItem.IsAnti)
{
updateItem.AttributesAreDefined = false;
updateItem.IsCreationTimeDefined = false;
updateItem.IsLastWriteTimeDefined = false;
updateItem.IsLastAccessTimeDefined = false;
updateItem.Size = 0;
}
if (!folderStatusIsDefined && updateItem.AttributesAreDefined)
updateItem.SetDirectoryStatusFromAttributes();
}
if (updateItem.NewData)
{
NCOM::CPropVariant propVariant;
RINOK(updateCallback->GetProperty(i, kpidSize, &propVariant));
if (propVariant.vt != VT_UI8)
return E_INVALIDARG;
updateItem.Size = (UInt64)propVariant.uhVal.QuadPart;
if (updateItem.Size != 0 && updateItem.IsAnti)
return E_INVALIDARG;
}
updateItems.Add(updateItem);
}
CCompressionMethodMode methodMode, headerMethod;
RINOK(SetCompressionMethod(methodMode, headerMethod));
#ifdef COMPRESS_MT
methodMode.NumThreads = _numThreads;
headerMethod.NumThreads = 1;
#endif
RINOK(SetPassword(methodMode, updateCallback));
bool compressMainHeader = _compressHeaders; // check it
if (methodMode.PasswordIsDefined)
{
compressMainHeader = true;
if(_encryptHeaders)
RINOK(SetPassword(headerMethod, updateCallback));
}
if (numItems < 2)
compressMainHeader = false;
CUpdateOptions options;
options.Method = &methodMode;
options.HeaderMethod = (_compressHeaders ||
(methodMode.PasswordIsDefined && _encryptHeaders)) ?
&headerMethod : 0;
options.UseFilters = _level != 0 && _autoFilter;
options.MaxFilter = _level >= 8;
options.HeaderOptions.CompressMainHeader = compressMainHeader;
options.HeaderOptions.WriteModified = WriteModified;
options.HeaderOptions.WriteCreated = WriteCreated;
options.HeaderOptions.WriteAccessed = WriteAccessed;
options.NumSolidFiles = _numSolidFiles;
options.NumSolidBytes = _numSolidBytes;
options.SolidExtension = _solidExtension;
options.RemoveSfxBlock = _removeSfxBlock;
options.VolumeMode = _volumeMode;
return Update(
EXTERNAL_CODECS_VARS
#ifdef _7Z_VOL
volume ? volume->Stream: 0,
volume ? database: 0,
#else
_inStream,
database,
#endif
updateItems, outStream, updateCallback, options);
COM_TRY_END
}
static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream)
{
stream = 0;
int index = ParseStringToUInt32(srcString, coder);
if (index == 0)
return E_INVALIDARG;
srcString.Delete(0, index);
if (srcString[0] == 'S')
{
srcString.Delete(0);
int index = ParseStringToUInt32(srcString, stream);
if (index == 0)
return E_INVALIDARG;
srcString.Delete(0, index);
}
return S_OK;
}
static HRESULT GetBindInfo(UString &srcString, CBind &bind)
{
RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream));
if (srcString[0] != ':')
return E_INVALIDARG;
srcString.Delete(0);
RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream));
if (!srcString.IsEmpty())
return E_INVALIDARG;
return S_OK;
}
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
{
COM_TRY_BEGIN
_binds.Clear();
BeforeSetProperty();
for (int i = 0; i < numProperties; i++)
{
UString name = names[i];
name.MakeUpper();
if (name.IsEmpty())
return E_INVALIDARG;
const PROPVARIANT &value = values[i];
if (name[0] == 'B')
{
name.Delete(0);
CBind bind;
RINOK(GetBindInfo(name, bind));
_binds.Add(bind);
continue;
}
RINOK(SetProperty(name, value));
}
return S_OK;
COM_TRY_END
}
}}

View file

@ -0,0 +1,27 @@
// 7z/Header.cpp
#include "StdAfx.h"
#include "7zHeader.h"
namespace NArchive {
namespace N7z {
Byte kSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C};
#ifdef _7Z_VOL
Byte kFinishSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C + 1};
#endif
class SignatureInitializer
{
public:
SignatureInitializer()
{
kSignature[0]--;
#ifdef _7Z_VOL
kFinishSignature[0]--;
#endif
};
} g_SignatureInitializer;
}}

View file

@ -0,0 +1,96 @@
// 7z/7zHeader.h
#ifndef __7Z_HEADER_H
#define __7Z_HEADER_H
#include "../../../Common/Types.h"
namespace NArchive {
namespace N7z {
const int kSignatureSize = 6;
extern Byte kSignature[kSignatureSize];
// #define _7Z_VOL
// 7z-MultiVolume is not finished yet.
// It can work already, but I still do not like some
// things of that new multivolume format.
// So please keep it commented.
#ifdef _7Z_VOL
extern Byte kFinishSignature[kSignatureSize];
#endif
struct CArchiveVersion
{
Byte Major;
Byte Minor;
};
const Byte kMajorVersion = 0;
struct CStartHeader
{
UInt64 NextHeaderOffset;
UInt64 NextHeaderSize;
UInt32 NextHeaderCRC;
};
const UInt32 kStartHeaderSize = 20;
#ifdef _7Z_VOL
struct CFinishHeader: public CStartHeader
{
UInt64 ArchiveStartOffset; // data offset from end if that struct
UInt64 AdditionalStartBlockSize; // start signature & start header size
};
const UInt32 kFinishHeaderSize = kStartHeaderSize + 16;
#endif
namespace NID
{
enum EEnum
{
kEnd,
kHeader,
kArchiveProperties,
kAdditionalStreamsInfo,
kMainStreamsInfo,
kFilesInfo,
kPackInfo,
kUnPackInfo,
kSubStreamsInfo,
kSize,
kCRC,
kFolder,
kCodersUnPackSize,
kNumUnPackStream,
kEmptyStream,
kEmptyFile,
kAnti,
kName,
kCreationTime,
kLastAccessTime,
kLastWriteTime,
kWinAttributes,
kComment,
kEncodedHeader,
kStartPos
};
}
}}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,235 @@
// 7zIn.h
#ifndef __7Z_IN_H
#define __7Z_IN_H
#include "../../../Common/MyCom.h"
#include "../../IStream.h"
#include "../../IPassword.h"
#include "../../Common/CreateCoder.h"
#include "../../Common/InBuffer.h"
#include "7zItem.h"
namespace NArchive {
namespace N7z {
struct CInArchiveInfo
{
CArchiveVersion Version;
UInt64 StartPosition;
UInt64 StartPositionAfterHeader;
UInt64 DataStartPosition;
UInt64 DataStartPosition2;
CRecordVector<UInt64> FileInfoPopIDs;
void Clear()
{
FileInfoPopIDs.Clear();
}
};
struct CArchiveDatabaseEx: public CArchiveDatabase
{
CInArchiveInfo ArchiveInfo;
CRecordVector<UInt64> PackStreamStartPositions;
CRecordVector<CNum> FolderStartPackStreamIndex;
CRecordVector<CNum> FolderStartFileIndex;
CRecordVector<CNum> FileIndexToFolderIndexMap;
void Clear()
{
CArchiveDatabase::Clear();
ArchiveInfo.Clear();
PackStreamStartPositions.Clear();
FolderStartPackStreamIndex.Clear();
FolderStartFileIndex.Clear();
FileIndexToFolderIndexMap.Clear();
}
void FillFolderStartPackStream();
void FillStartPos();
void FillFolderStartFileIndex();
void Fill()
{
FillFolderStartPackStream();
FillStartPos();
FillFolderStartFileIndex();
}
UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const
{
return ArchiveInfo.DataStartPosition +
PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder];
}
UInt64 GetFolderFullPackSize(int folderIndex) const
{
CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex];
const CFolder &folder = Folders[folderIndex];
UInt64 size = 0;
for (int i = 0; i < folder.PackStreams.Size(); i++)
size += PackSizes[packStreamIndex + i];
return size;
}
UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const
{
return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];
}
UInt64 GetFilePackSize(CNum fileIndex) const
{
CNum folderIndex = FileIndexToFolderIndexMap[fileIndex];
if (folderIndex != kNumNoIndex)
if (FolderStartFileIndex[folderIndex] == fileIndex)
return GetFolderFullPackSize(folderIndex);
return 0;
}
};
class CInByte2
{
const Byte *_buffer;
size_t _size;
size_t _pos;
public:
void Init(const Byte *buffer, size_t size)
{
_buffer = buffer;
_size = size;
_pos = 0;
}
Byte ReadByte();
void ReadBytes(Byte *data, size_t size);
void SkeepData(UInt64 size);
void SkeepData();
UInt64 ReadNumber();
CNum ReadNum();
UInt32 ReadUInt32();
UInt64 ReadUInt64();
void ReadString(UString &s);
};
class CStreamSwitch;
const UInt32 kHeaderSize = 32;
class CInArchive
{
friend class CStreamSwitch;
CMyComPtr<IInStream> _stream;
CObjectVector<CInByte2> _inByteVector;
CInByte2 *_inByteBack;
UInt64 _arhiveBeginStreamPosition;
Byte _header[kHeaderSize];
void AddByteStream(const Byte *buffer, size_t size)
{
_inByteVector.Add(CInByte2());
_inByteBack = &_inByteVector.Back();
_inByteBack->Init(buffer, size);
}
void DeleteByteStream()
{
_inByteVector.DeleteBack();
if (!_inByteVector.IsEmpty())
_inByteBack = &_inByteVector.Back();
}
private:
HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
Byte ReadByte() { return _inByteBack->ReadByte(); }
UInt64 ReadNumber() { return _inByteBack->ReadNumber(); }
CNum ReadNum() { return _inByteBack->ReadNum(); }
UInt64 ReadID() { return _inByteBack->ReadNumber(); }
UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }
UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }
void SkeepData(UInt64 size) { _inByteBack->SkeepData(size); }
void SkeepData() { _inByteBack->SkeepData(); }
void WaitAttribute(UInt64 attribute);
void ReadArchiveProperties(CInArchiveInfo &archiveInfo);
void GetNextFolderItem(CFolder &itemInfo);
void ReadHashDigests(int numItems,
CRecordVector<bool> &digestsDefined, CRecordVector<UInt32> &digests);
void ReadPackInfo(
UInt64 &dataOffset,
CRecordVector<UInt64> &packSizes,
CRecordVector<bool> &packCRCsDefined,
CRecordVector<UInt32> &packCRCs);
void ReadUnPackInfo(
const CObjectVector<CByteBuffer> *dataVector,
CObjectVector<CFolder> &folders);
void ReadSubStreamsInfo(
const CObjectVector<CFolder> &folders,
CRecordVector<CNum> &numUnPackStreamsInFolders,
CRecordVector<UInt64> &unPackSizes,
CRecordVector<bool> &digestsDefined,
CRecordVector<UInt32> &digests);
void ReadStreamsInfo(
const CObjectVector<CByteBuffer> *dataVector,
UInt64 &dataOffset,
CRecordVector<UInt64> &packSizes,
CRecordVector<bool> &packCRCsDefined,
CRecordVector<UInt32> &packCRCs,
CObjectVector<CFolder> &folders,
CRecordVector<CNum> &numUnPackStreamsInFolders,
CRecordVector<UInt64> &unPackSizes,
CRecordVector<bool> &digestsDefined,
CRecordVector<UInt32> &digests);
void ReadBoolVector(int numItems, CBoolVector &v);
void ReadBoolVector2(int numItems, CBoolVector &v);
void ReadTime(const CObjectVector<CByteBuffer> &dataVector,
CObjectVector<CFileItem> &files, UInt32 type);
HRESULT ReadAndDecodePackedStreams(
DECL_EXTERNAL_CODECS_LOC_VARS
UInt64 baseOffset, UInt64 &dataOffset,
CObjectVector<CByteBuffer> &dataVector
#ifndef _NO_CRYPTO
, ICryptoGetTextPassword *getTextPassword
#endif
);
HRESULT ReadHeader(
DECL_EXTERNAL_CODECS_LOC_VARS
CArchiveDatabaseEx &database
#ifndef _NO_CRYPTO
,ICryptoGetTextPassword *getTextPassword
#endif
);
HRESULT ReadDatabase2(
DECL_EXTERNAL_CODECS_LOC_VARS
CArchiveDatabaseEx &database
#ifndef _NO_CRYPTO
,ICryptoGetTextPassword *getTextPassword
#endif
);
public:
HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
void Close();
HRESULT ReadDatabase(
DECL_EXTERNAL_CODECS_LOC_VARS
CArchiveDatabaseEx &database
#ifndef _NO_CRYPTO
,ICryptoGetTextPassword *getTextPassword
#endif
);
};
}}
#endif

View file

@ -0,0 +1,184 @@
// 7zItem.h
#ifndef __7Z_ITEM_H
#define __7Z_ITEM_H
#include "../../../Common/Buffer.h"
#include "../../../Common/MyString.h"
#include "../../Common/MethodId.h"
#include "7zHeader.h"
namespace NArchive {
namespace N7z {
typedef UInt32 CNum;
const CNum kNumMax = 0x7FFFFFFF;
const CNum kNumNoIndex = 0xFFFFFFFF;
struct CCoderInfo
{
CMethodId MethodID;
CByteBuffer Properties;
CNum NumInStreams;
CNum NumOutStreams;
bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }
};
struct CBindPair
{
CNum InIndex;
CNum OutIndex;
};
struct CFolder
{
CObjectVector<CCoderInfo> Coders;
CRecordVector<CBindPair> BindPairs;
CRecordVector<CNum> PackStreams;
CRecordVector<UInt64> UnPackSizes;
UInt32 UnPackCRC;
bool UnPackCRCDefined;
CFolder(): UnPackCRCDefined(false) {}
UInt64 GetUnPackSize() const // test it
{
if (UnPackSizes.IsEmpty())
return 0;
for (int i = UnPackSizes.Size() - 1; i >= 0; i--)
if (FindBindPairForOutStream(i) < 0)
return UnPackSizes[i];
throw 1;
}
CNum GetNumOutStreams() const
{
CNum result = 0;
for (int i = 0; i < Coders.Size(); i++)
result += Coders[i].NumOutStreams;
return result;
}
int FindBindPairForInStream(CNum inStreamIndex) const
{
for(int i = 0; i < BindPairs.Size(); i++)
if (BindPairs[i].InIndex == inStreamIndex)
return i;
return -1;
}
int FindBindPairForOutStream(CNum outStreamIndex) const
{
for(int i = 0; i < BindPairs.Size(); i++)
if (BindPairs[i].OutIndex == outStreamIndex)
return i;
return -1;
}
int FindPackStreamArrayIndex(CNum inStreamIndex) const
{
for(int i = 0; i < PackStreams.Size(); i++)
if (PackStreams[i] == inStreamIndex)
return i;
return -1;
}
};
typedef FILETIME CArchiveFileTime;
class CFileItem
{
public:
CArchiveFileTime CreationTime;
CArchiveFileTime LastWriteTime;
CArchiveFileTime LastAccessTime;
UInt64 UnPackSize;
UInt64 StartPos;
UInt32 Attributes;
UInt32 FileCRC;
UString Name;
bool HasStream; // Test it !!! it means that there is
// stream in some folder. It can be empty stream
bool IsDirectory;
bool IsAnti;
bool IsFileCRCDefined;
bool AreAttributesDefined;
bool IsCreationTimeDefined;
bool IsLastWriteTimeDefined;
bool IsLastAccessTimeDefined;
bool IsStartPosDefined;
/*
const bool HasStream() const {
return !IsDirectory && !IsAnti && UnPackSize != 0; }
*/
CFileItem():
HasStream(true),
IsDirectory(false),
IsAnti(false),
IsFileCRCDefined(false),
AreAttributesDefined(false),
IsCreationTimeDefined(false),
IsLastWriteTimeDefined(false),
IsLastAccessTimeDefined(false),
IsStartPosDefined(false)
{}
void SetAttributes(UInt32 attributes)
{
AreAttributesDefined = true;
Attributes = attributes;
}
void SetCreationTime(const CArchiveFileTime &creationTime)
{
IsCreationTimeDefined = true;
CreationTime = creationTime;
}
void SetLastWriteTime(const CArchiveFileTime &lastWriteTime)
{
IsLastWriteTimeDefined = true;
LastWriteTime = lastWriteTime;
}
void SetLastAccessTime(const CArchiveFileTime &lastAccessTime)
{
IsLastAccessTimeDefined = true;
LastAccessTime = lastAccessTime;
}
};
struct CArchiveDatabase
{
CRecordVector<UInt64> PackSizes;
CRecordVector<bool> PackCRCsDefined;
CRecordVector<UInt32> PackCRCs;
CObjectVector<CFolder> Folders;
CRecordVector<CNum> NumUnPackStreamsVector;
CObjectVector<CFileItem> Files;
void Clear()
{
PackSizes.Clear();
PackCRCsDefined.Clear();
PackCRCs.Clear();
Folders.Clear();
NumUnPackStreamsVector.Clear();
Files.Clear();
}
bool IsEmpty() const
{
return (PackSizes.IsEmpty() &&
PackCRCsDefined.IsEmpty() &&
PackCRCs.IsEmpty() &&
Folders.IsEmpty() &&
NumUnPackStreamsVector.IsEmpty() &&
Files.IsEmpty());
}
bool IsSolid() const
{
for (int i = 0; i < NumUnPackStreamsVector.Size(); i++)
if (NumUnPackStreamsVector[i] > 1)
return true;
return false;
}
};
}}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,193 @@
// 7z/Out.h
#ifndef __7Z_OUT_H
#define __7Z_OUT_H
#include "7zHeader.h"
#include "7zItem.h"
#include "7zCompressionMode.h"
#include "7zEncode.h"
#include "../../Common/OutBuffer.h"
#include "../../../Common/DynamicBuffer.h"
namespace NArchive {
namespace N7z {
class CWriteBufferLoc
{
Byte *_data;
size_t _size;
size_t _pos;
public:
CWriteBufferLoc(): _size(0), _pos(0) {}
void Init(Byte *data, size_t size)
{
_pos = 0;
_data = data;
_size = size;
}
HRESULT Write(const void *data, size_t size)
{
if (_pos + size > _size)
return E_FAIL;
memmove(_data + _pos, data, size);
_pos += size;
return S_OK;
}
};
class CWriteDynamicBuffer
{
CByteDynamicBuffer _buffer;
size_t _pos;
public:
CWriteDynamicBuffer(): _pos(0) {}
void Init()
{
_pos = 0;
}
void Write(const void *data, size_t size)
{
if (_pos + size > _buffer.GetCapacity())
_buffer.EnsureCapacity(_pos + size);
memmove(((Byte *)_buffer) +_pos, data, size);
_pos += size;
}
operator Byte *() { return (Byte *)_buffer; };
operator const Byte *() const { return (const Byte *)_buffer; };
size_t GetSize() const { return _pos; }
};
struct CHeaderOptions
{
// bool UseAdditionalHeaderStreams;
bool CompressMainHeader;
bool WriteModified;
bool WriteCreated;
bool WriteAccessed;
CHeaderOptions():
// UseAdditionalHeaderStreams(false),
CompressMainHeader(true),
WriteModified(true),
WriteCreated(false),
WriteAccessed(false) {}
};
class COutArchive
{
UInt64 _prefixHeaderPos;
HRESULT WriteDirect(const void *data, UInt32 size);
HRESULT WriteDirectByte(Byte b) { return WriteDirect(&b, 1); }
HRESULT WriteDirectUInt32(UInt32 value);
HRESULT WriteDirectUInt64(UInt64 value);
HRESULT WriteBytes(const void *data, size_t size);
HRESULT WriteBytes(const CByteBuffer &data);
HRESULT WriteByte(Byte b);
HRESULT WriteUInt32(UInt32 value);
HRESULT WriteNumber(UInt64 value);
HRESULT WriteID(UInt64 value) { return WriteNumber(value); }
HRESULT WriteFolder(const CFolder &folder);
HRESULT WriteFileHeader(const CFileItem &itemInfo);
HRESULT WriteBoolVector(const CBoolVector &boolVector);
HRESULT WriteHashDigests(
const CRecordVector<bool> &digestsDefined,
const CRecordVector<UInt32> &hashDigests);
HRESULT WritePackInfo(
UInt64 dataOffset,
const CRecordVector<UInt64> &packSizes,
const CRecordVector<bool> &packCRCsDefined,
const CRecordVector<UInt32> &packCRCs);
HRESULT WriteUnPackInfo(const CObjectVector<CFolder> &folders);
HRESULT WriteSubStreamsInfo(
const CObjectVector<CFolder> &folders,
const CRecordVector<CNum> &numUnPackStreamsInFolders,
const CRecordVector<UInt64> &unPackSizes,
const CRecordVector<bool> &digestsDefined,
const CRecordVector<UInt32> &hashDigests);
/*
HRESULT WriteStreamsInfo(
UInt64 dataOffset,
const CRecordVector<UInt64> &packSizes,
const CRecordVector<bool> &packCRCsDefined,
const CRecordVector<UInt32> &packCRCs,
bool externalFolders,
UInt64 externalFoldersStreamIndex,
const CObjectVector<CFolder> &folders,
const CRecordVector<CNum> &numUnPackStreamsInFolders,
const CRecordVector<UInt64> &unPackSizes,
const CRecordVector<bool> &digestsDefined,
const CRecordVector<UInt32> &hashDigests);
*/
HRESULT WriteTime(const CObjectVector<CFileItem> &files, Byte type);
HRESULT EncodeStream(
DECL_EXTERNAL_CODECS_LOC_VARS
CEncoder &encoder, const Byte *data, size_t dataSize,
CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders);
HRESULT EncodeStream(
DECL_EXTERNAL_CODECS_LOC_VARS
CEncoder &encoder, const CByteBuffer &data,
CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders);
HRESULT WriteHeader(
const CArchiveDatabase &database,
const CHeaderOptions &headerOptions,
UInt64 &headerOffset);
bool _mainMode;
bool _dynamicMode;
bool _countMode;
size_t _countSize;
COutBuffer _outByte;
CWriteBufferLoc _outByte2;
CWriteDynamicBuffer _dynamicBuffer;
UInt32 _crc;
#ifdef _7Z_VOL
bool _endMarker;
#endif
HRESULT WriteSignature();
#ifdef _7Z_VOL
HRESULT WriteFinishSignature();
#endif
HRESULT WriteStartHeader(const CStartHeader &h);
#ifdef _7Z_VOL
HRESULT WriteFinishHeader(const CFinishHeader &h);
#endif
CMyComPtr<IOutStream> Stream;
public:
COutArchive() { _outByte.Create(1 << 16); }
CMyComPtr<ISequentialOutStream> SeqStream;
HRESULT Create(ISequentialOutStream *stream, bool endMarker);
void Close();
HRESULT SkeepPrefixArchiveHeader();
HRESULT WriteDatabase(
DECL_EXTERNAL_CODECS_LOC_VARS
const CArchiveDatabase &database,
const CCompressionMethodMode *options,
const CHeaderOptions &headerOptions);
#ifdef _7Z_VOL
static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false);
static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false);
#endif
};
}}
#endif

View file

@ -0,0 +1,162 @@
// 7zProperties.cpp
#include "StdAfx.h"
#include "7zProperties.h"
#include "7zHeader.h"
#include "7zHandler.h"
// #define _MULTI_PACK
namespace NArchive {
namespace N7z {
struct CPropMap
{
UInt64 FilePropID;
STATPROPSTG StatPROPSTG;
};
CPropMap kPropMap[] =
{
{ NID::kName, NULL, kpidPath, VT_BSTR},
{ NID::kSize, NULL, kpidSize, VT_UI8},
{ NID::kPackInfo, NULL, kpidPackedSize, VT_UI8},
#ifdef _MULTI_PACK
{ 100, L"Pack0", kpidPackedSize0, VT_UI8},
{ 101, L"Pack1", kpidPackedSize1, VT_UI8},
{ 102, L"Pack2", kpidPackedSize2, VT_UI8},
{ 103, L"Pack3", kpidPackedSize3, VT_UI8},
{ 104, L"Pack4", kpidPackedSize4, VT_UI8},
#endif
{ NID::kCreationTime, NULL, kpidCreationTime, VT_FILETIME},
{ NID::kLastWriteTime, NULL, kpidLastWriteTime, VT_FILETIME},
{ NID::kLastAccessTime, NULL, kpidLastAccessTime, VT_FILETIME},
{ NID::kWinAttributes, NULL, kpidAttributes, VT_UI4},
{ NID::kStartPos, NULL, kpidPosition, VT_UI4},
{ NID::kCRC, NULL, kpidCRC, VT_UI4},
{ NID::kAnti, NULL, kpidIsAnti, VT_BOOL},
// { 97, NULL, kpidSolid, VT_BOOL},
#ifndef _SFX
{ 98, NULL, kpidMethod, VT_BSTR},
{ 99, NULL, kpidBlock, VT_UI4}
#endif
};
static const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]);
static int FindPropInMap(UInt64 filePropID)
{
for (int i = 0; i < kPropMapSize; i++)
if (kPropMap[i].FilePropID == filePropID)
return i;
return -1;
}
static void CopyOneItem(CRecordVector<UInt64> &src,
CRecordVector<UInt64> &dest, UInt32 item)
{
for (int i = 0; i < src.Size(); i++)
if (src[i] == item)
{
dest.Add(item);
src.Delete(i);
return;
}
}
static void RemoveOneItem(CRecordVector<UInt64> &src, UInt32 item)
{
for (int i = 0; i < src.Size(); i++)
if (src[i] == item)
{
src.Delete(i);
return;
}
}
static void InsertToHead(CRecordVector<UInt64> &dest, UInt32 item)
{
for (int i = 0; i < dest.Size(); i++)
if (dest[i] == item)
{
dest.Delete(i);
break;
}
dest.Insert(0, item);
}
void CHandler::FillPopIDs()
{
_fileInfoPopIDs.Clear();
#ifdef _7Z_VOL
if(_volumes.Size() < 1)
return;
const CVolume &volume = _volumes.Front();
const CArchiveDatabaseEx &_database = volume.Database;
#endif
CRecordVector<UInt64> fileInfoPopIDs = _database.ArchiveInfo.FileInfoPopIDs;
RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream);
RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kName);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kAnti);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kSize);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kPackInfo);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCreationTime);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kLastWriteTime);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kLastAccessTime);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kWinAttributes);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCRC);
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kComment);
_fileInfoPopIDs += fileInfoPopIDs;
#ifndef _SFX
_fileInfoPopIDs.Add(98);
_fileInfoPopIDs.Add(99);
#endif
#ifdef _MULTI_PACK
_fileInfoPopIDs.Add(100);
_fileInfoPopIDs.Add(101);
_fileInfoPopIDs.Add(102);
_fileInfoPopIDs.Add(103);
_fileInfoPopIDs.Add(104);
#endif
#ifndef _SFX
InsertToHead(_fileInfoPopIDs, NID::kLastWriteTime);
InsertToHead(_fileInfoPopIDs, NID::kPackInfo);
InsertToHead(_fileInfoPopIDs, NID::kSize);
InsertToHead(_fileInfoPopIDs, NID::kName);
#endif
}
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties)
{
*numProperties = _fileInfoPopIDs.Size();
return S_OK;
}
STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index,
BSTR *name, PROPID *propID, VARTYPE *varType)
{
if((int)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;
}
}}

View file

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

View file

@ -0,0 +1,18 @@
// 7zRegister.cpp
#include "StdAfx.h"
#include "../../Common/RegisterArc.h"
#include "7zHandler.h"
static IInArchive *CreateArc() { return new NArchive::N7z::CHandler; }
#ifndef EXTRACT_ONLY
static IOutArchive *CreateArcOut() { return new NArchive::N7z::CHandler; }
#else
#define CreateArcOut 0
#endif
static CArcInfo g_ArcInfo =
{ L"7z", L"7z", 0, 7, {'7' + 1 , 'z', 0xBC, 0xAF, 0x27, 0x1C}, 6, false, CreateArc, CreateArcOut };
REGISTER_ARC_DEC_SIG(7z)

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,80 @@
// 7zUpdate.h
#ifndef __7Z_UPDATE_H
#define __7Z_UPDATE_H
#include "7zIn.h"
#include "7zOut.h"
#include "7zCompressionMode.h"
#include "../IArchive.h"
namespace NArchive {
namespace N7z {
struct CUpdateItem
{
bool NewData;
bool NewProperties;
int IndexInArchive;
int IndexInClient;
UInt32 Attributes;
FILETIME CreationTime;
FILETIME LastWriteTime;
FILETIME LastAccessTime;
UInt64 Size;
UString Name;
bool IsAnti;
bool IsDirectory;
bool IsCreationTimeDefined;
bool IsLastWriteTimeDefined;
bool IsLastAccessTimeDefined;
bool AttributesAreDefined;
bool HasStream() const
{ return !IsDirectory && !IsAnti && Size != 0; }
CUpdateItem():
IsAnti(false),
AttributesAreDefined(false),
IsCreationTimeDefined(false),
IsLastWriteTimeDefined(false),
IsLastAccessTimeDefined(false)
{}
void SetDirectoryStatusFromAttributes()
{ IsDirectory = ((Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0); };
int GetExtensionPos() const;
UString GetExtension() const;
};
struct CUpdateOptions
{
const CCompressionMethodMode *Method;
const CCompressionMethodMode *HeaderMethod;
bool UseFilters;
bool MaxFilter;
CHeaderOptions HeaderOptions;
UInt64 NumSolidFiles;
UInt64 NumSolidBytes;
bool SolidExtension;
bool RemoveSfxBlock;
bool VolumeMode;
};
HRESULT Update(
DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream,
const CArchiveDatabaseEx *database,
const CObjectVector<CUpdateItem> &updateItems,
ISequentialOutStream *seqOutStream,
IArchiveUpdateCallback *updateCallback,
const CUpdateOptions &options);
}}
#endif

View file

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

View file

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

View file

@ -0,0 +1,6 @@
EXPORTS
CreateObject PRIVATE
GetHandlerProperty PRIVATE
GetNumberOfFormats PRIVATE
GetHandlerProperty2 PRIVATE
CreateObject PRIVATE

View file

@ -0,0 +1,9 @@
EXPORTS
CreateObject PRIVATE
GetHandlerProperty PRIVATE
GetNumberOfFormats PRIVATE
GetHandlerProperty2 PRIVATE
CreateObject PRIVATE
GetNumberOfMethods PRIVATE
GetMethodProperty PRIVATE
SetLargePageMode PRIVATE

View file

@ -0,0 +1,130 @@
// ArchiveExports.cpp
#include "StdAfx.h"
#include "../../Common/ComTry.h"
#include "../../Common/Types.h"
#include "../../Windows/PropVariant.h"
#include "../Common/RegisterArc.h"
#include "IArchive.h"
#include "../ICoder.h"
#include "../IPassword.h"
static const unsigned int kNumArcsMax = 32;
static unsigned int g_NumArcs = 0;
static const CArcInfo *g_Arcs[kNumArcsMax];
void RegisterArc(const CArcInfo *arcInfo)
{
if (g_NumArcs < kNumArcsMax)
g_Arcs[g_NumArcs++] = arcInfo;
}
DEFINE_GUID(CLSID_CArchiveHandler,
0x23170F69, 0x40C1, 0x278A, 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 int size, PROPVARIANT *value)
{
if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)
value->vt = VT_BSTR;
return S_OK;
}
static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
{
return SetPropString((const char *)&guid, sizeof(GUID), value);
}
int FindFormatCalssId(const GUID *clsID)
{
GUID cls = *clsID;
CLS_ARC_ID_ITEM(cls) = 0;
if (cls != CLSID_CArchiveHandler)
return -1;
Byte id = CLS_ARC_ID_ITEM(*clsID);
for (UInt32 i = 0; i < g_NumArcs; i++)
if (g_Arcs[i]->ClassId == id)
return i;
return -1;
}
STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject)
{
COM_TRY_BEGIN
{
int needIn = (*iid == IID_IInArchive);
int needOut = (*iid == IID_IOutArchive);
if (!needIn && !needOut)
return E_NOINTERFACE;
int formatIndex = FindFormatCalssId(clsid);
if (formatIndex < 0)
return CLASS_E_CLASSNOTAVAILABLE;
const CArcInfo &arc = *g_Arcs[formatIndex];
if (needIn)
{
*outObject = arc.CreateInArchive();
((IInArchive *)*outObject)->AddRef();
}
else
{
if (!arc.CreateOutArchive)
return CLASS_E_CLASSNOTAVAILABLE;
*outObject = arc.CreateOutArchive();
((IOutArchive *)*outObject)->AddRef();
}
}
COM_TRY_END
return S_OK;
}
STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value)
{
if (formatIndex >= g_NumArcs)
return E_INVALIDARG;
const CArcInfo &arc = *g_Arcs[formatIndex];
NWindows::NCOM::CPropVariant prop;
switch(propID)
{
case NArchive::kName:
prop = arc.Name;
break;
case NArchive::kClassID:
{
GUID clsId = CLSID_CArchiveHandler;
CLS_ARC_ID_ITEM(clsId) = arc.ClassId;
return SetPropGUID(clsId, value);
}
case NArchive::kExtension:
if (arc.Ext != 0)
prop = arc.Ext;
break;
case NArchive::kAddExtension:
if (arc.AddExt != 0)
prop = arc.AddExt;
break;
case NArchive::kUpdate:
prop = (bool)(arc.CreateOutArchive != 0);
break;
case NArchive::kKeepName:
prop = arc.KeepName;
break;
case NArchive::kStartSignature:
return SetPropString((const char *)arc.Signature, arc.SignatureSize, value);
}
prop.Detach(value);
return S_OK;
}
STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
{
return GetHandlerProperty2(0, propID, value);
}
STDAPI GetNumberOfFormats(UINT32 *numFormats)
{
*numFormats = g_NumArcs;
return S_OK;
}

View file

@ -0,0 +1,121 @@
// CoderMixer2.cpp
#include "StdAfx.h"
#include "CoderMixer2.h"
namespace NCoderMixer {
CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo):
_srcBindInfo(srcBindInfo)
{
srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams);
UInt32 j;
for (j = 0; j < NumSrcInStreams; j++)
{
_srcInToDestOutMap.Add(0);
DestOutToSrcInMap.Add(0);
}
for (j = 0; j < _numSrcOutStreams; j++)
{
_srcOutToDestInMap.Add(0);
_destInToSrcOutMap.Add(0);
}
UInt32 destInOffset = 0;
UInt32 destOutOffset = 0;
UInt32 srcInOffset = NumSrcInStreams;
UInt32 srcOutOffset = _numSrcOutStreams;
for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--)
{
const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i];
srcInOffset -= srcCoderInfo.NumInStreams;
srcOutOffset -= srcCoderInfo.NumOutStreams;
UInt32 j;
for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++)
{
UInt32 index = srcInOffset + j;
_srcInToDestOutMap[index] = destOutOffset;
DestOutToSrcInMap[destOutOffset] = index;
}
for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++)
{
UInt32 index = srcOutOffset + j;
_srcOutToDestInMap[index] = destInOffset;
_destInToSrcOutMap[destInOffset] = index;
}
}
}
void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo)
{
destBindInfo.Coders.Clear();
destBindInfo.BindPairs.Clear();
destBindInfo.InStreams.Clear();
destBindInfo.OutStreams.Clear();
int i;
for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--)
{
const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i];
CCoderStreamsInfo destCoderInfo;
destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams;
destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams;
destBindInfo.Coders.Add(destCoderInfo);
}
for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--)
{
const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i];
CBindPair destBindPair;
destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex];
destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex];
destBindInfo.BindPairs.Add(destBindPair);
}
for (i = 0; i < _srcBindInfo.InStreams.Size(); i++)
destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]);
for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++)
destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]);
}
CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams):
NumInStreams(numInStreams),
NumOutStreams(numOutStreams)
{
InSizes.Reserve(NumInStreams);
InSizePointers.Reserve(NumInStreams);
OutSizePointers.Reserve(NumOutStreams);
OutSizePointers.Reserve(NumOutStreams);
}
static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)
{
sizes.Clear();
sizePointers.Clear();
for(UInt32 i = 0; i < numItems; i++)
{
if (srcSizes == 0 || srcSizes[i] == NULL)
{
sizes.Add(0);
sizePointers.Add(NULL);
}
else
{
sizes.Add(*srcSizes[i]);
sizePointers.Add(&sizes.Back());
}
}
}
void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes,
const UInt64 **outSizes)
{
SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
}
}

View file

@ -0,0 +1,174 @@
// CoderMixer2.h
#ifndef __CODER_MIXER2_H
#define __CODER_MIXER2_H
#include "../../../Common/MyVector.h"
#include "../../../Common/Types.h"
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
namespace NCoderMixer {
struct CBindPair
{
UInt32 InIndex;
UInt32 OutIndex;
};
struct CCoderStreamsInfo
{
UInt32 NumInStreams;
UInt32 NumOutStreams;
};
struct CBindInfo
{
CRecordVector<CCoderStreamsInfo> Coders;
CRecordVector<CBindPair> BindPairs;
CRecordVector<UInt32> InStreams;
CRecordVector<UInt32> OutStreams;
void Clear()
{
Coders.Clear();
BindPairs.Clear();
InStreams.Clear();
OutStreams.Clear();
}
/*
UInt32 GetCoderStartOutStream(UInt32 coderIndex) const
{
UInt32 numOutStreams = 0;
for (UInt32 i = 0; i < coderIndex; i++)
numOutStreams += Coders[i].NumOutStreams;
return numOutStreams;
}
*/
void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const
{
numInStreams = 0;
numOutStreams = 0;
for (int i = 0; i < Coders.Size(); i++)
{
const CCoderStreamsInfo &coderStreamsInfo = Coders[i];
numInStreams += coderStreamsInfo.NumInStreams;
numOutStreams += coderStreamsInfo.NumOutStreams;
}
}
int FindBinderForInStream(UInt32 inStream) const
{
for (int i = 0; i < BindPairs.Size(); i++)
if (BindPairs[i].InIndex == inStream)
return i;
return -1;
}
int FindBinderForOutStream(UInt32 outStream) const
{
for (int i = 0; i < BindPairs.Size(); i++)
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;
}
};
class CBindReverseConverter
{
UInt32 _numSrcOutStreams;
NCoderMixer::CBindInfo _srcBindInfo;
CRecordVector<UInt32> _srcInToDestOutMap;
CRecordVector<UInt32> _srcOutToDestInMap;
CRecordVector<UInt32> _destInToSrcOutMap;
public:
UInt32 NumSrcInStreams;
CRecordVector<UInt32> DestOutToSrcInMap;
CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo);
void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo);
};
struct CCoderInfo2
{
CMyComPtr<ICompressCoder> Coder;
CMyComPtr<ICompressCoder2> Coder2;
UInt32 NumInStreams;
UInt32 NumOutStreams;
CRecordVector<UInt64> InSizes;
CRecordVector<UInt64> OutSizes;
CRecordVector<const UInt64 *> InSizePointers;
CRecordVector<const UInt64 *> OutSizePointers;
CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams);
void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);
HRESULT QueryInterface(REFGUID iid, void** pp) const
{
IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;
return p->QueryInterface(iid, pp);
}
};
class CCoderMixer2
{
public:
virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0;
virtual void ReInit() = 0;
virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0;
};
}
#endif

View file

@ -0,0 +1,228 @@
// CoderMixer2MT.cpp
#include "StdAfx.h"
#include "CoderMixer2MT.h"
namespace NCoderMixer {
CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams):
CCoderInfo2(numInStreams, numOutStreams)
{
InStreams.Reserve(NumInStreams);
InStreamPointers.Reserve(NumInStreams);
OutStreams.Reserve(NumOutStreams);
OutStreamPointers.Reserve(NumOutStreams);
}
void CCoder2::Execute() { Code(NULL); }
void CCoder2::Code(ICompressProgressInfo *progress)
{
InStreamPointers.Clear();
OutStreamPointers.Clear();
UInt32 i;
for (i = 0; i < NumInStreams; i++)
{
if (InSizePointers[i] != NULL)
InSizePointers[i] = &InSizes[i];
InStreamPointers.Add((ISequentialInStream *)InStreams[i]);
}
for (i = 0; i < NumOutStreams; i++)
{
if (OutSizePointers[i] != NULL)
OutSizePointers[i] = &OutSizes[i];
OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]);
}
if (Coder)
Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],
InSizePointers[0], OutSizePointers[0], progress);
else
Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams,
&OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress);
{
int i;
for (i = 0; i < InStreams.Size(); i++)
InStreams[i].Release();
for (i = 0; i < OutStreams.Size(); i++)
OutStreams[i].Release();
}
}
static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)
{
sizes.Clear();
sizePointers.Clear();
for(UInt32 i = 0; i < numItems; i++)
{
if (srcSizes == 0 || srcSizes[i] == NULL)
{
sizes.Add(0);
sizePointers.Add(NULL);
}
else
{
sizes.Add(*srcSizes[i]);
sizePointers.Add(&sizes.Back());
}
}
}
void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)
{
SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
}
//////////////////////////////////////
// CCoderMixer2MT
HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)
{
_bindInfo = bindInfo;
_streamBinders.Clear();
for(int i = 0; i < _bindInfo.BindPairs.Size(); i++)
{
_streamBinders.Add(CStreamBinder());
RINOK(_streamBinders.Back().CreateEvents());
}
return S_OK;
}
void CCoderMixer2MT::AddCoderCommon()
{
const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()];
CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams);
_coders.Add(threadCoderInfo);
}
void CCoderMixer2MT::AddCoder(ICompressCoder *coder)
{
AddCoderCommon();
_coders.Back().Coder = coder;
}
void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)
{
AddCoderCommon();
_coders.Back().Coder2 = coder;
}
void CCoderMixer2MT::ReInit()
{
for(int i = 0; i < _streamBinders.Size(); i++)
_streamBinders[i].ReInit();
}
HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams)
{
/*
if (_coders.Size() != _bindInfo.Coders.Size())
throw 0;
*/
int i;
for(i = 0; i < _coders.Size(); i++)
{
CCoder2 &coderInfo = _coders[i];
const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i];
coderInfo.InStreams.Clear();
UInt32 j;
for(j = 0; j < coderStreamsInfo.NumInStreams; j++)
coderInfo.InStreams.Add(NULL);
coderInfo.OutStreams.Clear();
for(j = 0; j < coderStreamsInfo.NumOutStreams; j++)
coderInfo.OutStreams.Add(NULL);
}
for(i = 0; i < _bindInfo.BindPairs.Size(); i++)
{
const CBindPair &bindPair = _bindInfo.BindPairs[i];
UInt32 inCoderIndex, inCoderStreamIndex;
UInt32 outCoderIndex, outCoderStreamIndex;
_bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex);
_bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex);
_streamBinders[i].CreateStreams(
&_coders[inCoderIndex].InStreams[inCoderStreamIndex],
&_coders[outCoderIndex].OutStreams[outCoderStreamIndex]);
}
for(i = 0; i < _bindInfo.InStreams.Size(); i++)
{
UInt32 inCoderIndex, inCoderStreamIndex;
_bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex);
_coders[inCoderIndex].InStreams[inCoderStreamIndex] = 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)
{
for (int i = 0; i < _coders.Size(); i++)
if (_coders[i].Result == code)
return code;
return S_OK;
}
STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
const UInt64 ** /* inSizes */,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 ** /* outSizes */,
UInt32 numOutStreams,
ICompressProgressInfo *progress)
{
if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||
numOutStreams != (UInt32)_bindInfo.OutStreams.Size())
return E_INVALIDARG;
Init(inStreams, outStreams);
int i;
for (i = 0; i < _coders.Size(); i++)
if (i != _progressCoderIndex)
{
RINOK(_coders[i].Create());
}
for (i = 0; i < _coders.Size(); i++)
if (i != _progressCoderIndex)
_coders[i].Start();
_coders[_progressCoderIndex].Code(progress);
for (i = 0; i < _coders.Size(); i++)
if (i != _progressCoderIndex)
_coders[i].WaitFinish();
RINOK(ReturnIfError(E_ABORT));
RINOK(ReturnIfError(E_OUTOFMEMORY));
RINOK(ReturnIfError(S_FALSE));
for (i = 0; i < _coders.Size(); i++)
{
HRESULT result = _coders[i].Result;
if (result != S_OK && result != E_FAIL)
return result;
}
for (i = 0; i < _coders.Size(); i++)
{
HRESULT result = _coders[i].Result;
if (result != S_OK)
return result;
}
return S_OK;
}
}

View file

@ -0,0 +1,80 @@
// CoderMixer2MT.h
#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 {
struct CCoder2: public CCoderInfo2, public CVirtThread
{
HRESULT Result;
CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
CRecordVector<ISequentialInStream*> InStreamPointers;
CRecordVector<ISequentialOutStream*> OutStreamPointers;
CCoder2(UInt32 numInStreams, UInt32 numOutStreams);
void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);
virtual void Execute();
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,
public CMyUnknownImp
{
CBindInfo _bindInfo;
CObjectVector<CStreamBinder> _streamBinders;
int _progressCoderIndex;
void AddCoderCommon();
HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams);
HRESULT ReturnIfError(HRESULT code);
public:
CObjectVector<CCoder2> _coders;
MY_UNKNOWN_IMP
STDMETHOD(Code)(ISequentialInStream **inStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress);
HRESULT SetBindInfo(const CBindInfo &bindInfo);
void AddCoder(ICompressCoder *coder);
void AddCoder2(ICompressCoder2 *coder);
void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; }
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; }
};
}
#endif

View file

@ -0,0 +1,15 @@
// CrossThreadProgress.cpp
#include "StdAfx.h"
#include "CrossThreadProgress.h"
STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
{
InSize = inSize;
OutSize = outSize;
ProgressEvent.Set();
WaitEvent.Lock();
return Result;
}

View file

@ -0,0 +1,37 @@
// CrossThreadProgress.h
#ifndef __CROSSTHREADPROGRESS_H
#define __CROSSTHREADPROGRESS_H
#include "../../ICoder.h"
#include "../../../Windows/Synchronization.h"
#include "../../../Common/MyCom.h"
class CCrossThreadProgress:
public ICompressProgressInfo,
public CMyUnknownImp
{
public:
const UInt64 *InSize;
const UInt64 *OutSize;
HRESULT Result;
NWindows::NSynchronization::CAutoResetEvent ProgressEvent;
NWindows::NSynchronization::CAutoResetEvent WaitEvent;
HRes Create()
{
RINOK(ProgressEvent.CreateIfNotCreated());
return WaitEvent.CreateIfNotCreated();
}
void Init()
{
ProgressEvent.Reset();
WaitEvent.Reset();
}
MY_UNKNOWN_IMP
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
};
#endif

View file

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

View file

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

View file

@ -0,0 +1,618 @@
// HandlerOutCommon.cpp
#include "StdAfx.h"
#include "HandlerOut.h"
#include "../../../Windows/PropVariant.h"
#include "../../../Common/StringToInt.h"
#include "../../ICoder.h"
#include "../Common/ParseProperties.h"
#ifdef COMPRESS_MT
#include "../../../Windows/System.h"
#endif
using namespace NWindows;
namespace NArchive {
static const wchar_t *kCopyMethod = L"Copy";
static const wchar_t *kLZMAMethodName = L"LZMA";
static const wchar_t *kLZMA2MethodName = L"LZMA2";
static const wchar_t *kBZip2MethodName = L"BZip2";
static const wchar_t *kPpmdMethodName = L"PPMd";
static const wchar_t *kDeflateMethodName = L"Deflate";
static const wchar_t *kDeflate64MethodName = L"Deflate64";
static const wchar_t *kLzmaMatchFinderX1 = L"HC4";
static const wchar_t *kLzmaMatchFinderX5 = L"BT4";
static const UInt32 kLzmaAlgoX1 = 0;
static const UInt32 kLzmaAlgoX5 = 1;
static const UInt32 kLzmaDicSizeX1 = 1 << 16;
static const UInt32 kLzmaDicSizeX3 = 1 << 20;
static const UInt32 kLzmaDicSizeX5 = 1 << 24;
static const UInt32 kLzmaDicSizeX7 = 1 << 25;
static const UInt32 kLzmaDicSizeX9 = 1 << 26;
static const UInt32 kLzmaFastBytesX1 = 32;
static const UInt32 kLzmaFastBytesX7 = 64;
static const UInt32 kPpmdMemSizeX1 = (1 << 22);
static const UInt32 kPpmdMemSizeX5 = (1 << 24);
static const UInt32 kPpmdMemSizeX7 = (1 << 26);
static const UInt32 kPpmdMemSizeX9 = (192 << 20);
static const UInt32 kPpmdOrderX1 = 4;
static const UInt32 kPpmdOrderX5 = 6;
static const UInt32 kPpmdOrderX7 = 16;
static const UInt32 kPpmdOrderX9 = 32;
static const UInt32 kDeflateAlgoX1 = 0;
static const UInt32 kDeflateAlgoX5 = 1;
static const UInt32 kDeflateFastBytesX1 = 32;
static const UInt32 kDeflateFastBytesX7 = 64;
static const UInt32 kDeflateFastBytesX9 = 128;
static const UInt32 kDeflatePassesX1 = 1;
static const UInt32 kDeflatePassesX7 = 3;
static const UInt32 kDeflatePassesX9 = 10;
static const UInt32 kBZip2NumPassesX1 = 1;
static const UInt32 kBZip2NumPassesX7 = 2;
static const UInt32 kBZip2NumPassesX9 = 7;
static const UInt32 kBZip2DicSizeX1 = 100000;
static const UInt32 kBZip2DicSizeX3 = 500000;
static const UInt32 kBZip2DicSizeX5 = 900000;
static const wchar_t *kDefaultMethodName = kLZMAMethodName;
static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";
static const UInt32 kDictionaryForHeaders = 1 << 20;
static const UInt32 kNumFastBytesForHeaders = 273;
static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5;
static bool AreEqual(const UString &methodName, const wchar_t *s)
{ return (methodName.CompareNoCase(s) == 0); }
static inline bool IsLZMAMethod(const UString &methodName)
{
return
AreEqual(methodName, kLZMAMethodName) ||
AreEqual(methodName, kLZMA2MethodName);
}
static inline bool IsBZip2Method(const UString &methodName)
{ return AreEqual(methodName, kBZip2MethodName); }
static inline bool IsPpmdMethod(const UString &methodName)
{ return AreEqual(methodName, kPpmdMethodName); }
static inline bool IsDeflateMethod(const UString &methodName)
{
return
AreEqual(methodName, kDeflateMethodName) ||
AreEqual(methodName, kDeflate64MethodName);
}
struct CNameToPropID
{
PROPID PropID;
VARTYPE VarType;
const wchar_t *Name;
};
CNameToPropID g_NameToPropID[] =
{
{ NCoderPropID::kOrder, VT_UI4, L"O" },
{ NCoderPropID::kPosStateBits, VT_UI4, L"PB" },
{ NCoderPropID::kLitContextBits, VT_UI4, L"LC" },
{ NCoderPropID::kLitPosBits, VT_UI4, L"LP" },
{ NCoderPropID::kEndMarker, VT_BOOL, L"eos" },
{ NCoderPropID::kNumPasses, VT_UI4, L"Pass" },
{ NCoderPropID::kNumFastBytes, VT_UI4, L"fb" },
{ NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" },
{ NCoderPropID::kAlgorithm, VT_UI4, L"a" },
{ NCoderPropID::kMatchFinder, VT_BSTR, L"mf" },
{ NCoderPropID::kNumThreads, VT_UI4, L"mt" }
};
static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)
{
if (varType == srcProp.vt)
{
destProp = srcProp;
return true;
}
if (varType == VT_UI1)
{
if (srcProp.vt == VT_UI4)
{
UInt32 value = srcProp.ulVal;
if (value > 0xFF)
return false;
destProp = (Byte)value;
return true;
}
}
else if (varType == VT_BOOL)
{
bool res;
if (SetBoolProperty(res, srcProp) != S_OK)
return false;
destProp = res;
return true;
}
return false;
}
static int FindPropIdFromStringName(const UString &name)
{
for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++)
if (name.CompareNoCase(g_NameToPropID[i].Name) == 0)
return i;
return -1;
}
static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID,
const NWindows::NCOM::CPropVariant &value)
{
for (int j = 0; j < oneMethodInfo.Properties.Size(); j++)
if (oneMethodInfo.Properties[j].Id == propID)
return;
CProp property;
property.Id = propID;
property.Value = value;
oneMethodInfo.Properties.Add(property);
}
void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
#ifdef COMPRESS_MT
, UInt32 numThreads
#endif
)
{
UInt32 level = _level;
if (oneMethodInfo.MethodName.IsEmpty())
oneMethodInfo.MethodName = kDefaultMethodName;
if (IsLZMAMethod(oneMethodInfo.MethodName))
{
UInt32 dicSize =
(level >= 9 ? kLzmaDicSizeX9 :
(level >= 7 ? kLzmaDicSizeX7 :
(level >= 5 ? kLzmaDicSizeX5 :
(level >= 3 ? kLzmaDicSizeX3 :
kLzmaDicSizeX1))));
UInt32 algo =
(level >= 5 ? kLzmaAlgoX5 :
kLzmaAlgoX1);
UInt32 fastBytes =
(level >= 7 ? kLzmaFastBytesX7 :
kLzmaFastBytesX1);
const wchar_t *matchFinder =
(level >= 5 ? kLzmaMatchFinderX5 :
kLzmaMatchFinderX1);
SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder);
#ifdef COMPRESS_MT
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
#endif
}
else if (IsDeflateMethod(oneMethodInfo.MethodName))
{
UInt32 fastBytes =
(level >= 9 ? kDeflateFastBytesX9 :
(level >= 7 ? kDeflateFastBytesX7 :
kDeflateFastBytesX1));
UInt32 numPasses =
(level >= 9 ? kDeflatePassesX9 :
(level >= 7 ? kDeflatePassesX7 :
kDeflatePassesX1));
UInt32 algo =
(level >= 5 ? kDeflateAlgoX5 :
kDeflateAlgoX1);
SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
}
else if (IsBZip2Method(oneMethodInfo.MethodName))
{
UInt32 numPasses =
(level >= 9 ? kBZip2NumPassesX9 :
(level >= 7 ? kBZip2NumPassesX7 :
kBZip2NumPassesX1));
UInt32 dicSize =
(level >= 5 ? kBZip2DicSizeX5 :
(level >= 3 ? kBZip2DicSizeX3 :
kBZip2DicSizeX1));
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
#ifdef COMPRESS_MT
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
#endif
}
else if (IsPpmdMethod(oneMethodInfo.MethodName))
{
UInt32 useMemSize =
(level >= 9 ? kPpmdMemSizeX9 :
(level >= 7 ? kPpmdMemSizeX7 :
(level >= 5 ? kPpmdMemSizeX5 :
kPpmdMemSizeX1)));
UInt32 order =
(level >= 9 ? kPpmdOrderX9 :
(level >= 7 ? kPpmdOrderX7 :
(level >= 5 ? kPpmdOrderX5 :
kPpmdOrderX1)));
SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize);
SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order);
}
}
static void SplitParams(const UString &srcString, UStringVector &subStrings)
{
subStrings.Clear();
UString name;
int len = srcString.Length();
if (len == 0)
return;
for (int i = 0; i < len; i++)
{
wchar_t c = srcString[i];
if (c == L':')
{
subStrings.Add(name);
name.Empty();
}
else
name += c;
}
subStrings.Add(name);
}
static void SplitParam(const UString &param, UString &name, UString &value)
{
int eqPos = param.Find(L'=');
if (eqPos >= 0)
{
name = param.Left(eqPos);
value = param.Mid(eqPos + 1);
return;
}
for(int i = 0; i < param.Length(); i++)
{
wchar_t c = param[i];
if (c >= L'0' && c <= L'9')
{
name = param.Left(i);
value = param.Mid(i);
return;
}
}
name = param;
}
HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value)
{
CProp property;
if (
name.CompareNoCase(L"D") == 0 ||
name.CompareNoCase(L"MEM") == 0)
{
UInt32 dicSize;
RINOK(ParsePropDictionaryValue(value, dicSize));
if (name.CompareNoCase(L"D") == 0)
property.Id = NCoderPropID::kDictionarySize;
else
property.Id = NCoderPropID::kUsedMemorySize;
property.Value = dicSize;
oneMethodInfo.Properties.Add(property);
}
else
{
int index = FindPropIdFromStringName(name);
if (index < 0)
return E_INVALIDARG;
const CNameToPropID &nameToPropID = g_NameToPropID[index];
property.Id = nameToPropID.PropID;
NCOM::CPropVariant propValue;
if (nameToPropID.VarType == VT_BSTR)
propValue = value;
else if (nameToPropID.VarType == VT_BOOL)
{
bool res;
if (!StringToBool(value, res))
return E_INVALIDARG;
propValue = res;
}
else
{
UInt32 number;
if (ParseStringToUInt32(value, number) == value.Length())
propValue = number;
else
propValue = value;
}
if (!ConvertProperty(propValue, nameToPropID.VarType, property.Value))
return E_INVALIDARG;
oneMethodInfo.Properties.Add(property);
}
return S_OK;
}
HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString)
{
UStringVector params;
SplitParams(srcString, params);
if (params.Size() > 0)
oneMethodInfo.MethodName = params[0];
for (int i = 1; i < params.Size(); i++)
{
const UString &param = params[i];
UString name, value;
SplitParam(param, name, value);
RINOK(SetParam(oneMethodInfo, name, value));
}
return S_OK;
}
HRESULT COutHandler::SetSolidSettings(const UString &s)
{
bool res;
if (StringToBool(s, res))
{
if (res)
InitSolid();
else
_numSolidFiles = 1;
return S_OK;
}
UString s2 = s;
s2.MakeUpper();
for (int i = 0; i < s2.Length();)
{
const wchar_t *start = ((const wchar_t *)s2) + i;
const wchar_t *end;
UInt64 v = ConvertStringToUInt64(start, &end);
if (start == end)
{
if (s2[i++] != 'E')
return E_INVALIDARG;
_solidExtension = true;
continue;
}
i += (int)(end - start);
if (i == s2.Length())
return E_INVALIDARG;
wchar_t c = s2[i++];
switch(c)
{
case 'F':
if (v < 1)
v = 1;
_numSolidFiles = v;
break;
case 'B':
_numSolidBytes = v;
_numSolidBytesDefined = true;
break;
case 'K':
_numSolidBytes = (v << 10);
_numSolidBytesDefined = true;
break;
case 'M':
_numSolidBytes = (v << 20);
_numSolidBytesDefined = true;
break;
case 'G':
_numSolidBytes = (v << 30);
_numSolidBytesDefined = true;
break;
default:
return E_INVALIDARG;
}
}
return S_OK;
}
HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value)
{
switch(value.vt)
{
case VT_EMPTY:
InitSolid();
return S_OK;
case VT_BSTR:
return SetSolidSettings(value.bstrVal);
default:
return E_INVALIDARG;
}
}
void COutHandler::Init()
{
_removeSfxBlock = false;
_compressHeaders = true;
_encryptHeaders = false;
WriteModified = true;
WriteCreated = false;
WriteAccessed = false;
#ifdef COMPRESS_MT
_numThreads = NWindows::NSystem::GetNumberOfProcessors();
#endif
_level = 5;
_autoFilter = true;
_volumeMode = false;
_crcSize = 4;
InitSolid();
}
void COutHandler::BeforeSetProperty()
{
Init();
#ifdef COMPRESS_MT
numProcessors = NSystem::GetNumberOfProcessors();
#endif
mainDicSize = 0xFFFFFFFF;
mainDicMethodIndex = 0xFFFFFFFF;
minNumber = 0;
_crcSize = 4;
}
HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
{
UString name = nameSpec;
name.MakeUpper();
if (name.IsEmpty())
return E_INVALIDARG;
if (name[0] == 'X')
{
name.Delete(0);
_level = 9;
return ParsePropValue(name, value, _level);
}
if (name[0] == L'S')
{
name.Delete(0);
if (name.IsEmpty())
return SetSolidSettings(value);
if (value.vt != VT_EMPTY)
return E_INVALIDARG;
return SetSolidSettings(name);
}
if (name == L"CRC")
{
_crcSize = 4;
name.Delete(0, 3);
return ParsePropValue(name, value, _crcSize);
}
UInt32 number;
int index = ParseStringToUInt32(name, number);
UString realName = name.Mid(index);
if (index == 0)
{
if(name.Left(2).CompareNoCase(L"MT") == 0)
{
#ifdef COMPRESS_MT
RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));
#endif
return S_OK;
}
if (name.CompareNoCase(L"RSFX") == 0)
return SetBoolProperty(_removeSfxBlock, value);
if (name.CompareNoCase(L"F") == 0)
return SetBoolProperty(_autoFilter, value);
if (name.CompareNoCase(L"HC") == 0)
return SetBoolProperty(_compressHeaders, value);
if (name.CompareNoCase(L"HCF") == 0)
{
bool compressHeadersFull = true;
RINOK(SetBoolProperty(compressHeadersFull, value));
if (!compressHeadersFull)
return E_INVALIDARG;
return S_OK;
}
if (name.CompareNoCase(L"HE") == 0)
return SetBoolProperty(_encryptHeaders, value);
if (name.CompareNoCase(L"TM") == 0)
return SetBoolProperty(WriteModified, value);
if (name.CompareNoCase(L"TC") == 0)
return SetBoolProperty(WriteCreated, value);
if (name.CompareNoCase(L"TA") == 0)
return SetBoolProperty(WriteAccessed, value);
if (name.CompareNoCase(L"V") == 0)
return SetBoolProperty(_volumeMode, value);
number = 0;
}
if (number > 10000)
return E_FAIL;
if (number < minNumber)
return E_INVALIDARG;
number -= minNumber;
for(int j = _methods.Size(); j <= (int)number; j++)
{
COneMethodInfo oneMethodInfo;
_methods.Add(oneMethodInfo);
}
COneMethodInfo &oneMethodInfo = _methods[number];
if (realName.Length() == 0)
{
if (value.vt != VT_BSTR)
return E_INVALIDARG;
RINOK(SetParams(oneMethodInfo, value.bstrVal));
}
else
{
CProp property;
if (realName.Left(1).CompareNoCase(L"D") == 0)
{
UInt32 dicSize;
RINOK(ParsePropDictionaryValue(realName.Mid(1), value, dicSize));
property.Id = NCoderPropID::kDictionarySize;
property.Value = dicSize;
oneMethodInfo.Properties.Add(property);
if (number <= mainDicMethodIndex)
mainDicSize = dicSize;
}
else if (realName.Left(3).CompareNoCase(L"MEM") == 0)
{
UInt32 dicSize;
RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize));
property.Id = NCoderPropID::kUsedMemorySize;
property.Value = dicSize;
oneMethodInfo.Properties.Add(property);
if (number <= mainDicMethodIndex)
mainDicSize = dicSize;
}
else
{
int index = FindPropIdFromStringName(realName);
if (index < 0)
return E_INVALIDARG;
const CNameToPropID &nameToPropID = g_NameToPropID[index];
property.Id = nameToPropID.PropID;
if (!ConvertProperty(value, nameToPropID.VarType, property.Value))
return E_INVALIDARG;
oneMethodInfo.Properties.Add(property);
}
}
return S_OK;
}
}

View file

@ -0,0 +1,86 @@
// HandlerOut.h
#ifndef __HANDLER_OUT_H
#define __HANDLER_OUT_H
#include "../../Common/MethodProps.h"
#include "../../Common/CreateCoder.h"
namespace NArchive {
struct COneMethodInfo
{
CObjectVector<CProp> Properties;
UString MethodName;
};
class COutHandler
{
public:
HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
HRESULT SetSolidSettings(const UString &s);
HRESULT SetSolidSettings(const PROPVARIANT &value);
#ifdef COMPRESS_MT
UInt32 _numThreads;
#endif
UInt32 _crcSize;
CObjectVector<COneMethodInfo> _methods;
bool _removeSfxBlock;
UInt64 _numSolidFiles;
UInt64 _numSolidBytes;
bool _numSolidBytesDefined;
bool _solidExtension;
bool _compressHeaders;
bool _encryptHeaders;
bool WriteModified;
bool WriteCreated;
bool WriteAccessed;
bool _autoFilter;
UInt32 _level;
bool _volumeMode;
HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value);
HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString);
void SetCompressionMethod2(COneMethodInfo &oneMethodInfo
#ifdef COMPRESS_MT
, UInt32 numThreads
#endif
);
void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }
void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); }
void InitSolid()
{
InitSolidFiles();
InitSolidSize();
_solidExtension = false;
_numSolidBytesDefined = false;
}
void Init();
COutHandler() { Init(); }
void BeforeSetProperty();
UInt32 minNumber;
UInt32 numProcessors;
UInt32 mainDicSize;
UInt32 mainDicMethodIndex;
DECL_EXTERNAL_CODECS_VARS
};
}
#endif

View file

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

View file

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

View file

@ -0,0 +1,59 @@
// Archive/Common/ItemNameUtils.cpp
#include "StdAfx.h"
#include "ItemNameUtils.h"
namespace NArchive {
namespace NItemName {
static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR;
static const wchar_t kDirDelimiter = L'/';
UString MakeLegalName(const UString &name)
{
UString zipName = name;
zipName.Replace(kOSDirDelimiter, kDirDelimiter);
return zipName;
}
UString GetOSName(const UString &name)
{
UString newName = name;
newName.Replace(kDirDelimiter, kOSDirDelimiter);
return newName;
}
UString GetOSName2(const UString &name)
{
if (name.IsEmpty())
return UString();
UString newName = GetOSName(name);
if (newName[newName.Length() - 1] == kOSDirDelimiter)
newName.Delete(newName.Length() - 1);
return newName;
}
bool HasTailSlash(const AString &name, UINT codePage)
{
if (name.IsEmpty())
return false;
LPCSTR prev =
#ifdef _WIN32
CharPrevExA((WORD)codePage, name, &name[name.Length()], 0);
#else
(LPCSTR)(name) + (name.Length() - 1);
#endif
return (*prev == '/');
}
#ifndef _WIN32
UString WinNameToOSName(const UString &name)
{
UString newName = name;
newName.Replace(L'\\', kOSDirDelimiter);
return newName;
}
#endif
}}

View file

@ -0,0 +1,24 @@
// Archive/Common/ItemNameUtils.h
#ifndef __ARCHIVE_ITEMNAMEUTILS_H
#define __ARCHIVE_ITEMNAMEUTILS_H
#include "../../../Common/MyString.h"
namespace NArchive {
namespace NItemName {
UString MakeLegalName(const UString &name);
UString GetOSName(const UString &name);
UString GetOSName2(const UString &name);
bool HasTailSlash(const AString &name, UINT codePage);
#ifdef _WIN32
inline UString WinNameToOSName(const UString &name) { return name; }
#else
UString WinNameToOSName(const UString &name);
#endif
}}
#endif

View file

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

View file

@ -0,0 +1,76 @@
// MultiStream.h
#ifndef __MULTISTREAM_H
#define __MULTISTREAM_H
#include "../../../Common/MyCom.h"
#include "../../../Common/MyVector.h"
#include "../../Archive/IArchive.h"
class CMultiStream:
public IInStream,
public CMyUnknownImp
{
int _streamIndex;
UInt64 _pos;
UInt64 _seekPos;
UInt64 _totalLength;
public:
struct CSubStreamInfo
{
CMyComPtr<IInStream> Stream;
UInt64 Pos;
UInt64 Size;
};
CObjectVector<CSubStreamInfo> Streams;
void Init()
{
_streamIndex = 0;
_pos = 0;
_seekPos = 0;
_totalLength = 0;
for (int i = 0; i < Streams.Size(); i++)
_totalLength += Streams[i].Size;
}
MY_UNKNOWN_IMP1(IInStream)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
};
/*
class COutMultiStream:
public IOutStream,
public CMyUnknownImp
{
int _streamIndex; // required stream
UInt64 _offsetPos; // offset from start of _streamIndex index
UInt64 _absPos;
UInt64 _length;
struct CSubStreamInfo
{
CMyComPtr<ISequentialOutStream> Stream;
UInt64 Size;
UInt64 Pos;
};
CObjectVector<CSubStreamInfo> Streams;
public:
CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
void Init()
{
_streamIndex = 0;
_offsetPos = 0;
_absPos = 0;
_length = 0;
}
MY_UNKNOWN_IMP1(IOutStream)
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
};
*/
#endif

View file

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

View file

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

View file

@ -0,0 +1,174 @@
// ParseProperties.cpp
#include "StdAfx.h"
#include "ParseProperties.h"
#include "Common/StringToInt.h"
#include "Common/MyCom.h"
HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
{
if (prop.vt == VT_UI4)
{
if (!name.IsEmpty())
return E_INVALIDARG;
resValue = prop.ulVal;
}
else if (prop.vt == VT_EMPTY)
{
if(!name.IsEmpty())
{
const wchar_t *start = name;
const wchar_t *end;
UInt64 v = ConvertStringToUInt64(start, &end);
if (end - start != name.Length())
return E_INVALIDARG;
resValue = (UInt32)v;
}
}
else
return E_INVALIDARG;
return S_OK;
}
static const int kLogarithmicSizeLimit = 32;
static const wchar_t kByteSymbol = L'B';
static const wchar_t kKiloByteSymbol = L'K';
static const wchar_t kMegaByteSymbol = L'M';
HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize)
{
UString srcString = srcStringSpec;
srcString.MakeUpper();
const wchar_t *start = srcString;
const wchar_t *end;
UInt64 number = ConvertStringToUInt64(start, &end);
int numDigits = (int)(end - start);
if (numDigits == 0 || srcString.Length() > numDigits + 1)
return E_INVALIDARG;
if (srcString.Length() == numDigits)
{
if (number >= kLogarithmicSizeLimit)
return E_INVALIDARG;
dicSize = (UInt32)1 << (int)number;
return S_OK;
}
switch (srcString[numDigits])
{
case kByteSymbol:
if (number >= ((UInt64)1 << kLogarithmicSizeLimit))
return E_INVALIDARG;
dicSize = (UInt32)number;
break;
case kKiloByteSymbol:
if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10)))
return E_INVALIDARG;
dicSize = (UInt32)(number << 10);
break;
case kMegaByteSymbol:
if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20)))
return E_INVALIDARG;
dicSize = (UInt32)(number << 20);
break;
default:
return E_INVALIDARG;
}
return S_OK;
}
HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
{
if (name.IsEmpty())
{
if (prop.vt == VT_UI4)
{
UInt32 logDicSize = prop.ulVal;
if (logDicSize >= 32)
return E_INVALIDARG;
resValue = (UInt32)1 << logDicSize;
return S_OK;
}
if (prop.vt == VT_BSTR)
return ParsePropDictionaryValue(prop.bstrVal, resValue);
return E_INVALIDARG;
}
return ParsePropDictionaryValue(name, resValue);
}
bool StringToBool(const UString &s, bool &res)
{
if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0)
{
res = true;
return true;
}
if (s.CompareNoCase(L"OFF") == 0)
{
res = false;
return true;
}
return false;
}
HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value)
{
switch(value.vt)
{
case VT_EMPTY:
dest = true;
return S_OK;
/*
case VT_UI4:
dest = (value.ulVal != 0);
break;
*/
case VT_BSTR:
return StringToBool(value.bstrVal, dest) ? S_OK : E_INVALIDARG;
}
return E_INVALIDARG;
}
int ParseStringToUInt32(const UString &srcString, UInt32 &number)
{
const wchar_t *start = srcString;
const wchar_t *end;
UInt64 number64 = ConvertStringToUInt64(start, &end);
if (number64 > 0xFFFFFFFF)
{
number = 0;
return 0;
}
number = (UInt32)number64;
return (int)(end - start);
}
HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads)
{
if (name.IsEmpty())
{
switch(prop.vt)
{
case VT_UI4:
numThreads = prop.ulVal;
break;
default:
{
bool val;
RINOK(SetBoolProperty(val, prop));
numThreads = (val ? defaultNumThreads : 1);
break;
}
}
}
else
{
UInt32 number;
int index = ParseStringToUInt32(name, number);
if (index != name.Length())
return E_INVALIDARG;
numThreads = number;
}
return S_OK;
}

View file

@ -0,0 +1,18 @@
// ParseProperties.h
#ifndef __PARSEPROPERTIES_H
#define __PARSEPROPERTIES_H
#include "Common/MyString.h"
#include "Common/Types.h"
HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize);
HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
bool StringToBool(const UString &s, bool &res);
HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value);
int ParseStringToUInt32(const UString &srcString, UInt32 &number);
HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads);
#endif

View file

@ -0,0 +1,82 @@
// DLLExports.cpp
#include "StdAfx.h"
#include "../../Common/MyInitGuid.h"
#include "../../Common/ComTry.h"
#include "../../Common/Types.h"
#include "../../Windows/PropVariant.h"
#if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)
extern "C"
{
#include "../../../C/Alloc.h"
}
#endif
#include "IArchive.h"
#include "../ICoder.h"
#include "../IPassword.h"
HINSTANCE g_hInstance;
#ifndef _UNICODE
#ifdef _WIN32
bool g_IsNT = false;
static bool IsItWindowsNT()
{
OSVERSIONINFO versionInfo;
versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
if (!::GetVersionEx(&versionInfo))
return false;
return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
}
#endif
#endif
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
g_hInstance = hInstance;
#ifndef _UNICODE
#ifdef _WIN32
g_IsNT = IsItWindowsNT();
#endif
#endif
}
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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject);
STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject);
STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
{
// COM_TRY_BEGIN
*outObject = 0;
if (*iid == IID_ICompressCoder || *iid == IID_ICompressCoder2 || *iid == IID_ICompressFilter)
{
return CreateCoder(clsid, iid, outObject);
}
else
{
return CreateArchiver(clsid, iid, outObject);
}
// COM_TRY_END
}
STDAPI SetLargePageMode()
{
#if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)
SetLargePageSize();
#endif
return S_OK;
}

View file

@ -0,0 +1,207 @@
// IArchive.h
#ifndef __IARCHIVE_H
#define __IARCHIVE_H
#include "../IStream.h"
#include "../IProgress.h"
#include "../PropID.h"
#define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x)
#define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x)
namespace NFileTimeType
{
enum EEnum
{
kWindows,
kUnix,
kDOS
};
}
namespace NArchive
{
enum
{
kName = 0,
kClassID,
kExtension,
kAddExtension,
kUpdate,
kKeepName,
kStartSignature,
kFinishSignature,
kAssociate
};
namespace NExtract
{
namespace NAskMode
{
enum
{
kExtract = 0,
kTest,
kSkip
};
}
namespace NOperationResult
{
enum
{
kOK = 0,
kUnSupportedMethod,
kDataError,
kCRCError
};
}
}
namespace NUpdate
{
namespace NOperationResult
{
enum
{
kOK = 0,
kError
};
}
}
}
ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10)
{
STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) PURE;
STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) PURE;
};
ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20)
{
STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream,
Int32 askExtractMode) PURE;
// GetStream OUT: S_OK - OK, S_FALSE - skeep this file
STDMETHOD(PrepareOperation)(Int32 askExtractMode) PURE;
STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) PURE;
};
ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30)
{
STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) PURE;
STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) PURE;
};
ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40)
{
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE;
};
ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50)
{
STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE;
};
/*
IInArchive::Extract:
indices must be sorted
numItems = 0xFFFFFFFF means "all files"
testMode != 0 means "test files without writing to outStream"
*/
#define INTERFACE_IInArchive(x) \
STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \
STDMETHOD(Close)() x; \
STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \
STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \
STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \
STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \
STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \
STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \
STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x;
ARCHIVE_INTERFACE(IInArchive, 0x60)
{
INTERFACE_IInArchive(PURE)
};
ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80)
{
STDMETHOD(GetUpdateItemInfo)(UInt32 index,
Int32 *newData, // 1 - new data, 0 - old data
Int32 *newProperties, // 1 - new properties, 0 - old properties
UInt32 *indexInArchive // -1 if there is no in archive, or if doesn't matter
) PURE;
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE;
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) PURE;
STDMETHOD(SetOperationResult)(Int32 operationResult) PURE;
};
ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82)
{
STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) PURE;
STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) PURE;
};
#define INTERFACE_IOutArchive(x) \
STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \
STDMETHOD(GetFileTimeType)(UInt32 *type) x;
ARCHIVE_INTERFACE(IOutArchive, 0xA0)
{
INTERFACE_IOutArchive(PURE)
};
ARCHIVE_INTERFACE(ISetProperties, 0x03)
{
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE;
};
#define IMP_IInArchive_GetProp(k) \
(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \
{ if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \
const STATPROPSTG &srcItem = k[index]; \
*propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \
#define IMP_IInArchive_GetProp_WITH_NAME(k) \
(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \
{ if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \
const STATPROPSTG &srcItem = k[index]; \
*propID = srcItem.propid; *varType = srcItem.vt; \
if (srcItem.lpwstrName == 0) *name = 0; else *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } \
#define IMP_IInArchive_Props \
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \
{ *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \
STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps)
#define IMP_IInArchive_Props_WITH_NAME \
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \
{ *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \
STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps)
#define IMP_IInArchive_ArcProps \
STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \
{ *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \
STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps)
#define IMP_IInArchive_ArcProps_NO \
STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \
{ *numProperties = 0; return S_OK; } \
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \
{ return E_NOTIMPL; } \
STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \
{ value->vt = VT_EMPTY; return S_OK; }
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "Alone"=.\Alone.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View file

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

View file

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

View file

@ -0,0 +1,236 @@
PROG = 7za.exe
LIBS = $(LIBS) user32.lib oleaut32.lib Advapi32.lib
CFLAGS = $(CFLAGS) -I ../../../ \
-D_NO_CRYPTO \
-DWIN_LONG_PATH \
-DCOMPRESS_MT \
-DCOMPRESS_MF_MT \
-D_NO_CRYPTO \
-DBREAK_HANDLER \
-DBENCH_MT \
CONSOLE_OBJS = \
$O\ConsoleClose.obj \
$O\ExtractCallbackConsole.obj \
$O\List.obj \
$O\Main.obj \
$O\MainAr.obj \
$O\OpenCallbackConsole.obj \
$O\PercentPrinter.obj \
$O\UpdateCallbackConsole.obj \
$O\UserInputUtils.obj \
COMMON_OBJS = \
$O\CommandLineParser.obj \
$O\CRC.obj \
$O\IntToString.obj \
$O\ListFileUtils.obj \
$O\NewHandler.obj \
$O\StdInStream.obj \
$O\StdOutStream.obj \
$O\MyString.obj \
$O\StringConvert.obj \
$O\StringToInt.obj \
$O\UTFConvert.obj \
$O\MyVector.obj \
$O\Wildcard.obj \
WIN_OBJS = \
$O\DLL.obj \
$O\Error.obj \
$O\FileDir.obj \
$O\FileFind.obj \
$O\FileIO.obj \
$O\FileName.obj \
$O\MemoryLock.obj \
$O\PropVariant.obj \
$O\PropVariantConversions.obj \
$O\Synchronization.obj \
$O\System.obj \
7ZIP_COMMON_OBJS = \
$O\CreateCoder.obj \
$O\FilePathAutoRename.obj \
$O\FileStreams.obj \
$O\InBuffer.obj \
$O\InOutTempBuffer.obj \
$O\FilterCoder.obj \
$O\LimitedStreams.obj \
$O\LockedStream.obj \
$O\MethodId.obj \
$O\MethodProps.obj \
$O\OffsetStream.obj \
$O\OutBuffer.obj \
$O\ProgressUtils.obj \
$O\StreamBinder.obj \
$O\StreamObjects.obj \
$O\StreamUtils.obj \
$O\VirtThread.obj \
UI_COMMON_OBJS = \
$O\ArchiveCommandLine.obj \
$O\ArchiveExtractCallback.obj \
$O\ArchiveOpenCallback.obj \
$O\DefaultName.obj \
$O\EnumDirItems.obj \
$O\Extract.obj \
$O\ExtractingFilePath.obj \
$O\LoadCodecs.obj \
$O\OpenArchive.obj \
$O\PropIDUtils.obj \
$O\SetProperties.obj \
$O\SortUtils.obj \
$O\TempFiles.obj \
$O\Update.obj \
$O\UpdateAction.obj \
$O\UpdateCallback.obj \
$O\UpdatePair.obj \
$O\UpdateProduce.obj \
$O\WorkDir.obj \
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
$O\CoderMixer2MT.obj \
$O\CrossThreadProgress.obj \
$O\DummyOutStream.obj \
$O\HandlerOut.obj \
$O\InStreamWithCRC.obj \
$O\ItemNameUtils.obj \
$O\MultiStream.obj \
$O\OutStreamWithCRC.obj \
$O\ParseProperties.obj \
7Z_OBJS = \
$O\7zCompressionMode.obj \
$O\7zDecode.obj \
$O\7zEncode.obj \
$O\7zExtract.obj \
$O\7zFolderInStream.obj \
$O\7zFolderOutStream.obj \
$O\7zHandler.obj \
$O\7zHandlerOut.obj \
$O\7zHeader.obj \
$O\7zIn.obj \
$O\7zOut.obj \
$O\7zProperties.obj \
$O\7zRegister.obj \
$O\7zSpecStream.obj \
$O\7zUpdate.obj \
BRANCH_OPT_OBJS = \
$O\BranchCoder.obj \
$O\x86.obj \
$O\x86_2.obj \
$O\ARM.obj \
$O\ARMThumb.obj \
$O\IA64.obj \
$O\PPC.obj \
$O\SPARC.obj \
$O\BranchRegister.obj \
$O\BCJRegister.obj \
$O\BCJ2Register.obj \
SWAP_OPT_OBJS = \
$O\ByteSwap.obj \
$O\ByteSwapRegister.obj \
COPY_OBJS = \
$O\CopyCoder.obj \
$O\CopyRegister.obj \
LZ_OBJS = \
$O\LZOutWindow.obj \
LZMA_OPT_OBJS = \
$O\LZMADecoder.obj \
$O\LZMAEncoder.obj \
$O\LZMARegister.obj \
LZMA_BENCH_OBJS = \
$O\LzmaBench.obj \
$O\LzmaBenchCon.obj \
C_OBJS = \
$O\Alloc.obj \
$O\7zCrc.obj \
$O\Sort.obj \
$O\Threads.obj \
C_LZ_OBJS = \
$O\MatchFinder.obj \
$O\MatchFinderMt.obj \
C_BRANCH_OBJS = \
$O\BranchARM.obj \
$O\BranchARMThumb.obj \
$O\BranchIA64.obj \
$O\BranchPPC.obj \
$O\BranchSPARC.obj \
$O\BranchX86.obj \
OBJS = \
$O\StdAfx.obj \
$(CONSOLE_OBJS) \
$(COMMON_OBJS) \
$(WIN_OBJS) \
$(7ZIP_COMMON_OBJS) \
$(UI_COMMON_OBJS) \
$(AR_COMMON_OBJS) \
$(7Z_OBJS) \
$(BRANCH_OPT_OBJS) \
$(SWAP_OPT_OBJS) \
$(COPY_OBJS) \
$(LZ_OBJS) \
$(LZMA_OPT_OBJS) \
$(LZMA_BENCH_OBJS) \
$(C_OBJS) \
$(C_LZ_OBJS) \
$(C_BRANCH_OBJS) \
$O\RangeCoderBit.obj \
$(CRC_OBJS) \
$O\resource.res
!include "../../../Build.mak"
$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp
$(COMPL)
$(COMMON_OBJS): ../../../Common/$(*B).cpp
$(COMPL)
$(WIN_OBJS): ../../../Windows/$(*B).cpp
$(COMPL)
$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
$(COMPL)
$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp
$(COMPL)
$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp
$(COMPL)
$(7Z_OBJS): ../../Archive/7z/$(*B).cpp
$(COMPL)
$(BRANCH_OPT_OBJS): ../../Compress/Branch/$(*B).cpp
$(COMPL_O2)
$(SWAP_OPT_OBJS): ../../Compress/ByteSwap/$(*B).cpp
$(COMPL_O2)
$(COPY_OBJS): ../../Compress/Copy/$(*B).cpp
$(COMPL)
$(LZ_OBJS): ../../Compress/LZ/$(*B).cpp
$(COMPL)
$(LZMA_OPT_OBJS): ../../Compress/LZMA/$(*B).cpp
$(COMPL_O2)
$(LZMA_BENCH_OBJS): ../../Compress/LZMA_Alone/$(*B).cpp
$(COMPL)
$O\RangeCoderBit.obj: ../../Compress/RangeCoder/$(*B).cpp
$(COMPL)
$(C_OBJS): ../../../../C/$(*B).c
$(COMPL_O2)
$(C_LZ_OBJS): ../../../../C/Compress/Lz/$(*B).c
$(COMPL_O2)
$(C_BRANCH_OBJS): ../../../../C/Compress/Branch/$(*B).c
$(COMPL_O2)

View file

@ -0,0 +1,3 @@
#include "../../MyVersionInfo.rc"
MY_VERSION_INFO_APP("7-Zip Standalone Console", "7za")

View file

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

View file

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

View file

@ -0,0 +1,165 @@
PROG = 7zxr.dll
DEF_FILE = ../../Archive/Archive2.def
LIBS = $(LIBS) user32.lib oleaut32.lib
CFLAGS = $(CFLAGS) -I ../../../ \
-DEXTRACT_ONLY \
-DCOMPRESS_MT \
-D_NO_CRYPTO
COMMON_OBJS = \
$O\CRC.obj \
$O\IntToString.obj \
$O\NewHandler.obj \
$O\MyString.obj \
$O\StringConvert.obj \
$O\StringToInt.obj \
$O\MyVector.obj \
$O\Wildcard.obj \
WIN_OBJS = \
$O\FileDir.obj \
$O\FileFind.obj \
$O\FileIO.obj \
$O\PropVariant.obj \
$O\Synchronization.obj \
$O\System.obj \
7ZIP_COMMON_OBJS = \
$O\CreateCoder.obj \
$O\InBuffer.obj \
$O\InOutTempBuffer.obj \
$O\FilterCoder.obj \
$O\LimitedStreams.obj \
$O\LockedStream.obj \
$O\MethodId.obj \
$O\MethodProps.obj \
$O\OutBuffer.obj \
$O\ProgressUtils.obj \
$O\StreamBinder.obj \
$O\StreamObjects.obj \
$O\StreamUtils.obj \
$O\VirtThread.obj \
AR_OBJS = \
$O\ArchiveExports.obj \
$O\DllExports2.obj \
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
$O\CoderMixer2MT.obj \
$O\CrossThreadProgress.obj \
$O\HandlerOut.obj \
$O\ItemNameUtils.obj \
$O\OutStreamWithCRC.obj \
$O\ParseProperties.obj \
7Z_OBJS = \
$O\7zCompressionMode.obj \
$O\7zDecode.obj \
$O\7zExtract.obj \
$O\7zFolderOutStream.obj \
$O\7zHandler.obj \
$O\7zHeader.obj \
$O\7zIn.obj \
$O\7zProperties.obj \
$O\7zRegister.obj \
COMPRESS_OBJS = \
$O\CodecExports.obj \
SWAP_OPT_OBJS = \
$O\ByteSwap.obj \
$O\ByteSwapRegister.obj \
BRANCH_OPT_OBJS = \
$O\BranchCoder.obj \
$O\x86.obj \
$O\x86_2.obj \
$O\ARM.obj \
$O\ARMThumb.obj \
$O\IA64.obj \
$O\PPC.obj \
$O\SPARC.obj \
$O\BranchRegister.obj \
$O\BCJRegister.obj \
$O\BCJ2Register.obj \
COPY_OBJS = \
$O\CopyCoder.obj \
$O\CopyRegister.obj \
LZ_OBJS = \
$O\LZOutWindow.obj \
LZMA_OPT_OBJS = \
$O\LZMADecoder.obj \
$O\LZMARegister.obj \
C_OBJS = \
$O\Alloc.obj \
$O\7zCrc.obj \
$O\Threads.obj \
C_BRANCH_OBJS = \
$O\BranchARM.obj \
$O\BranchARMThumb.obj \
$O\BranchIA64.obj \
$O\BranchPPC.obj \
$O\BranchSPARC.obj \
$O\BranchX86.obj \
OBJS = \
$O\StdAfx.obj \
$(CONSOLE_OBJS) \
$(COMMON_OBJS) \
$(WIN_OBJS) \
$(7ZIP_COMMON_OBJS) \
$(AR_OBJS) \
$(AR_COMMON_OBJS) \
$(7Z_OBJS) \
$(COMPRESS_OBJS) \
$(BRANCH_OPT_OBJS) \
$(SWAP_OPT_OBJS) \
$(COPY_OBJS) \
$(LZ_OBJS) \
$(LZMA_OPT_OBJS) \
$(C_OBJS) \
$(C_BRANCH_OBJS) \
$O\resource.res
!include "../../../Build.mak"
$(COMMON_OBJS): ../../../Common/$(*B).cpp
$(COMPL)
$(WIN_OBJS): ../../../Windows/$(*B).cpp
$(COMPL)
$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
$(COMPL)
$(AR_OBJS): ../../Archive/$(*B).cpp
$(COMPL)
$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp
$(COMPL)
$(7Z_OBJS): ../../Archive/7z/$(*B).cpp
$(COMPL)
$(COMPRESS_OBJS): ../../Compress/$(*B).cpp
$(COMPL)
$(BRANCH_OPT_OBJS): ../../Compress/Branch/$(*B).cpp
$(COMPL_O2)
$(SWAP_OPT_OBJS): ../../Compress/ByteSwap/$(*B).cpp
$(COMPL_O2)
$(COPY_OBJS): ../../Compress/Copy/$(*B).cpp
$(COMPL)
$(LZ_OBJS): ../../Compress/LZ/$(*B).cpp
$(COMPL)
$(LZMA_OPT_OBJS): ../../Compress/LZMA/$(*B).cpp
$(COMPL_O2)
$(C_OBJS): ../../../../C/$(*B).c
$(COMPL_O2)
$(C_BRANCH_OBJS): ../../../../C/Compress/Branch/$(*B).c
$(COMPL_O2)

View file

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

View file

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

View file

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

View file

@ -0,0 +1,188 @@
PROG = 7zra.dll
DEF_FILE = ../../Archive/Archive2.def
LIBS = $(LIBS) user32.lib oleaut32.lib
CFLAGS = $(CFLAGS) -I ../../../ \
-DCOMPRESS_MT \
-DCOMPRESS_MF_MT \
-D_NO_CRYPTO
COMMON_OBJS = \
$O\CRC.obj \
$O\IntToString.obj \
$O\NewHandler.obj \
$O\MyString.obj \
$O\StringConvert.obj \
$O\StringToInt.obj \
$O\MyVector.obj \
$O\Wildcard.obj \
WIN_OBJS = \
$O\FileDir.obj \
$O\FileFind.obj \
$O\FileIO.obj \
$O\PropVariant.obj \
$O\Synchronization.obj \
$O\System.obj \
7ZIP_COMMON_OBJS = \
$O\CreateCoder.obj \
$O\InBuffer.obj \
$O\InOutTempBuffer.obj \
$O\FilterCoder.obj \
$O\LimitedStreams.obj \
$O\LockedStream.obj \
$O\MethodId.obj \
$O\MethodProps.obj \
$O\OutBuffer.obj \
$O\ProgressUtils.obj \
$O\StreamBinder.obj \
$O\StreamObjects.obj \
$O\StreamUtils.obj \
$O\VirtThread.obj \
AR_OBJS = \
$O\ArchiveExports.obj \
$O\DllExports2.obj \
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
$O\CoderMixer2MT.obj \
$O\CrossThreadProgress.obj \
$O\HandlerOut.obj \
$O\InStreamWithCRC.obj \
$O\ItemNameUtils.obj \
$O\OutStreamWithCRC.obj \
$O\ParseProperties.obj \
7Z_OBJS = \
$O\7zCompressionMode.obj \
$O\7zDecode.obj \
$O\7zEncode.obj \
$O\7zExtract.obj \
$O\7zFolderInStream.obj \
$O\7zFolderOutStream.obj \
$O\7zHandler.obj \
$O\7zHandlerOut.obj \
$O\7zHeader.obj \
$O\7zIn.obj \
$O\7zOut.obj \
$O\7zProperties.obj \
$O\7zSpecStream.obj \
$O\7zUpdate.obj \
$O\7zRegister.obj \
COMPRESS_OBJS = \
$O\CodecExports.obj \
BRANCH_OPT_OBJS = \
$O\BranchCoder.obj \
$O\x86.obj \
$O\x86_2.obj \
$O\ARM.obj \
$O\ARMThumb.obj \
$O\IA64.obj \
$O\PPC.obj \
$O\SPARC.obj \
$O\BranchRegister.obj \
$O\BCJRegister.obj \
$O\BCJ2Register.obj \
SWAP_OPT_OBJS = \
$O\ByteSwap.obj \
$O\ByteSwapRegister.obj \
COPY_OBJS = \
$O\CopyCoder.obj \
$O\CopyRegister.obj \
LZ_OBJS = \
$O\LZOutWindow.obj \
LZMA_OPT_OBJS = \
$O\LZMADecoder.obj \
$O\LZMAEncoder.obj \
$O\LZMARegister.obj \
C_OBJS = \
$O\Alloc.obj \
$O\7zCrc.obj \
$O\Sort.obj \
$O\Threads.obj \
C_LZ_OBJS = \
$O\MatchFinder.obj \
$O\MatchFinderMt.obj \
C_BRANCH_OBJS = \
$O\BranchARM.obj \
$O\BranchARMThumb.obj \
$O\BranchIA64.obj \
$O\BranchPPC.obj \
$O\BranchSPARC.obj \
$O\BranchX86.obj \
OBJS = \
$O\StdAfx.obj \
$(CONSOLE_OBJS) \
$(COMMON_OBJS) \
$(WIN_OBJS) \
$(7ZIP_COMMON_OBJS) \
$(AR_OBJS) \
$(AR_COMMON_OBJS) \
$(7Z_OBJS) \
$(BZIP2_OBJS) \
$(BZIP2_OPT_OBJS) \
$(COMPRESS_OBJS) \
$(BRANCH_OPT_OBJS) \
$(SWAP_OPT_OBJS) \
$(COPY_OBJS) \
$(DEFLATE_OPT_OBJS) \
$(LZ_OBJS) \
$(LZMA_OPT_OBJS) \
$(PPMD_OPT_OBJS) \
$(C_OBJS) \
$(C_LZ_OBJS) \
$(C_BRANCH_OBJS) \
$O\RangeCoderBit.obj \
$O\resource.res
!include "../../../Build.mak"
$(COMMON_OBJS): ../../../Common/$(*B).cpp
$(COMPL)
$(WIN_OBJS): ../../../Windows/$(*B).cpp
$(COMPL)
$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
$(COMPL)
$(AR_OBJS): ../../Archive/$(*B).cpp
$(COMPL)
$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp
$(COMPL)
$(7Z_OBJS): ../../Archive/7z/$(*B).cpp
$(COMPL)
$(COMPRESS_OBJS): ../../Compress/$(*B).cpp
$(COMPL)
$(BRANCH_OPT_OBJS): ../../Compress/Branch/$(*B).cpp
$(COMPL_O2)
$(SWAP_OPT_OBJS): ../../Compress/ByteSwap/$(*B).cpp
$(COMPL_O2)
$(COPY_OBJS): ../../Compress/Copy/$(*B).cpp
$(COMPL)
$(LZ_OBJS): ../../Compress/LZ/$(*B).cpp
$(COMPL)
$(LZMA_OPT_OBJS): ../../Compress/LZMA/$(*B).cpp
$(COMPL_O2)
$O\RangeCoderBit.obj: ../../Compress/RangeCoder/$(*B).cpp
$(COMPL)
$(C_OBJS): ../../../../C/$(*B).c
$(COMPL_O2)
$(C_LZ_OBJS): ../../../../C/Compress/Lz/$(*B).c
$(COMPL_O2)
$(C_BRANCH_OBJS): ../../../../C/Compress/Branch/$(*B).c
$(COMPL_O2)

View file

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

View file

@ -0,0 +1,292 @@
// CreateCoder.cpp
#include "StdAfx.h"
#include "CreateCoder.h"
#include "../../Windows/PropVariant.h"
#include "../../Windows/Defs.h"
#include "FilterCoder.h"
#include "RegisterCodec.h"
static const unsigned int kNumCodecsMax = 64;
unsigned int g_NumCodecs = 0;
const CCodecInfo *g_Codecs[kNumCodecsMax];
void RegisterCodec(const CCodecInfo *codecInfo)
{
if (g_NumCodecs < kNumCodecsMax)
g_Codecs[g_NumCodecs++] = codecInfo;
}
#ifdef EXTERNAL_CODECS
static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res)
{
NWindows::NCOM::CPropVariant prop;
RINOK(codecsInfo->GetProperty(index, propID, &prop));
if (prop.vt == VT_EMPTY)
res = 1;
else if (prop.vt == VT_UI4)
res = prop.ulVal;
else
return E_INVALIDARG;
return S_OK;
}
static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res)
{
NWindows::NCOM::CPropVariant prop;
RINOK(codecsInfo->GetProperty(index, propID, &prop));
if (prop.vt == VT_EMPTY)
res = true;
else if (prop.vt == VT_BOOL)
res = VARIANT_BOOLToBool(prop.boolVal);
else
return E_INVALIDARG;
return S_OK;
}
HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs)
{
UInt32 num;
RINOK(codecsInfo->GetNumberOfMethods(&num));
for (UInt32 i = 0; i < num; i++)
{
CCodecInfoEx info;
NWindows::NCOM::CPropVariant prop;
RINOK(codecsInfo->GetProperty(i, NMethodPropID::kID, &prop));
// if (prop.vt != VT_BSTR)
// info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal);
// memmove(info.Id.ID, prop.bstrVal, info.Id.IDSize);
if (prop.vt != VT_UI8)
{
continue; // old Interface
// return E_INVALIDARG;
}
info.Id = prop.uhVal.QuadPart;
prop.Clear();
RINOK(codecsInfo->GetProperty(i, NMethodPropID::kName, &prop));
if (prop.vt == VT_BSTR)
info.Name = prop.bstrVal;
else if (prop.vt != VT_EMPTY)
return E_INVALIDARG;;
RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kInStreams, info.NumInStreams));
RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kOutStreams, info.NumOutStreams));
RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned));
RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned));
externalCodecs.Add(info);
}
return S_OK;
}
#endif
bool FindMethod(
#ifdef EXTERNAL_CODECS
ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs,
#endif
const UString &name,
CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams)
{
UInt32 i;
for (i = 0; i < g_NumCodecs; i++)
{
const CCodecInfo &codec = *g_Codecs[i];
if (name.CompareNoCase(codec.Name) == 0)
{
methodId = codec.Id;
numInStreams = codec.NumInStreams;
numOutStreams = 1;
return true;
}
}
#ifdef EXTERNAL_CODECS
if (externalCodecs)
for (i = 0; i < (UInt32)externalCodecs->Size(); i++)
{
const CCodecInfoEx &codec = (*externalCodecs)[i];
if (codec.Name.CompareNoCase(name) == 0)
{
methodId = codec.Id;
numInStreams = codec.NumInStreams;
numOutStreams = codec.NumOutStreams;
return true;
}
}
#endif
return false;
}
bool FindMethod(
#ifdef EXTERNAL_CODECS
ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs,
#endif
CMethodId methodId, UString &name)
{
UInt32 i;
for (i = 0; i < g_NumCodecs; i++)
{
const CCodecInfo &codec = *g_Codecs[i];
if (methodId == codec.Id)
{
name = codec.Name;
return true;
}
}
#ifdef EXTERNAL_CODECS
if (externalCodecs)
for (i = 0; i < (UInt32)externalCodecs->Size(); i++)
{
const CCodecInfoEx &codec = (*externalCodecs)[i];
if (methodId == codec.Id)
{
name = codec.Name;
return true;
}
}
#endif
return false;
}
HRESULT CreateCoder(
DECL_EXTERNAL_CODECS_LOC_VARS
CMethodId methodId,
CMyComPtr<ICompressFilter> &filter,
CMyComPtr<ICompressCoder> &coder,
CMyComPtr<ICompressCoder2> &coder2,
bool encode, bool onlyCoder)
{
bool created = false;
UInt32 i;
for (i = 0; i < g_NumCodecs; i++)
{
const CCodecInfo &codec = *g_Codecs[i];
if (codec.Id == methodId)
{
if (encode)
{
if (codec.CreateEncoder)
{
void *p = codec.CreateEncoder();
if (codec.IsFilter) filter = (ICompressFilter *)p;
else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p;
else coder2 = (ICompressCoder2 *)p;
created = (p != 0);
break;
}
}
else
if (codec.CreateDecoder)
{
void *p = codec.CreateDecoder();
if (codec.IsFilter) filter = (ICompressFilter *)p;
else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p;
else coder2 = (ICompressCoder2 *)p;
created = (p != 0);
break;
}
}
}
#ifdef EXTERNAL_CODECS
if (!created && externalCodecs)
for (i = 0; i < (UInt32)externalCodecs->Size(); i++)
{
const CCodecInfoEx &codec = (*externalCodecs)[i];
if (codec.Id == methodId)
{
if (encode)
{
if (codec.EncoderIsAssigned)
{
if (codec.IsSimpleCodec())
{
HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder);
if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE)
return result;
if (!coder)
{
RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter));
}
}
else
{
RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2));
}
break;
}
}
else
if (codec.DecoderIsAssigned)
{
if (codec.IsSimpleCodec())
{
HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder);
if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE)
return result;
if (!coder)
{
RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter));
}
}
else
{
RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2));
}
break;
}
}
}
#endif
if (onlyCoder && filter)
{
CFilterCoder *coderSpec = new CFilterCoder;
coder = coderSpec;
coderSpec->Filter = filter;
}
return S_OK;
}
HRESULT CreateCoder(
DECL_EXTERNAL_CODECS_LOC_VARS
CMethodId methodId,
CMyComPtr<ICompressCoder> &coder,
CMyComPtr<ICompressCoder2> &coder2,
bool encode)
{
CMyComPtr<ICompressFilter> filter;
return CreateCoder(
EXTERNAL_CODECS_LOC_VARS
methodId,
filter, coder, coder2, encode, true);
}
HRESULT CreateCoder(
DECL_EXTERNAL_CODECS_LOC_VARS
CMethodId methodId,
CMyComPtr<ICompressCoder> &coder, bool encode)
{
CMyComPtr<ICompressFilter> filter;
CMyComPtr<ICompressCoder2> coder2;
return CreateCoder(
EXTERNAL_CODECS_LOC_VARS
methodId,
coder, coder2, encode);
}
HRESULT CreateFilter(
DECL_EXTERNAL_CODECS_LOC_VARS
CMethodId methodId,
CMyComPtr<ICompressFilter> &filter,
bool encode)
{
CMyComPtr<ICompressCoder> coder;
CMyComPtr<ICompressCoder2> coder2;
return CreateCoder(
EXTERNAL_CODECS_LOC_VARS
methodId,
filter, coder, coder2, encode, false);
}

View file

@ -0,0 +1,98 @@
// CreateCoder.h
#ifndef __CREATECODER_H
#define __CREATECODER_H
#include "Common/MyCom.h"
#include "Common/MyString.h"
#include "../ICoder.h"
#include "MethodId.h"
#ifdef EXTERNAL_CODECS
struct CCodecInfoEx
{
UString Name;
CMethodId Id;
UInt32 NumInStreams;
UInt32 NumOutStreams;
bool EncoderIsAssigned;
bool DecoderIsAssigned;
bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; }
CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {}
};
HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs);
#define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo,
#define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo)
#define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo);
#define IMPL_ISetCompressCodecsInfo2(x) \
STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \
COM_TRY_BEGIN _codecsInfo = compressCodecsInfo; return LoadExternalCodecs(_codecsInfo, _externalCodecs); COM_TRY_END }
#define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler)
#define EXTERNAL_CODECS_VARS2 _codecsInfo, &_externalCodecs
#define DECL_EXTERNAL_CODECS_VARS CMyComPtr<ICompressCodecsInfo> _codecsInfo; CObjectVector<CCodecInfoEx> _externalCodecs;
#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2,
#define DECL_EXTERNAL_CODECS_LOC_VARS2 ICompressCodecsInfo *codecsInfo, const CObjectVector<CCodecInfoEx> *externalCodecs
#define EXTERNAL_CODECS_LOC_VARS2 codecsInfo, externalCodecs
#define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2,
#define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2,
#else
#define PUBLIC_ISetCompressCodecsInfo
#define QUERY_ENTRY_ISetCompressCodecsInfo
#define DECL_ISetCompressCodecsInfo
#define IMPL_ISetCompressCodecsInfo
#define EXTERNAL_CODECS_VARS2
#define DECL_EXTERNAL_CODECS_VARS
#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2
#define DECL_EXTERNAL_CODECS_LOC_VARS2
#define EXTERNAL_CODECS_LOC_VARS2
#define DECL_EXTERNAL_CODECS_LOC_VARS
#define EXTERNAL_CODECS_LOC_VARS
#endif
bool FindMethod(
DECL_EXTERNAL_CODECS_LOC_VARS
const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams);
bool FindMethod(
DECL_EXTERNAL_CODECS_LOC_VARS
CMethodId methodId, UString &name);
HRESULT CreateCoder(
DECL_EXTERNAL_CODECS_LOC_VARS
CMethodId methodId,
CMyComPtr<ICompressFilter> &filter,
CMyComPtr<ICompressCoder> &coder,
CMyComPtr<ICompressCoder2> &coder2,
bool encode, bool onlyCoder);
HRESULT CreateCoder(
DECL_EXTERNAL_CODECS_LOC_VARS
CMethodId methodId,
CMyComPtr<ICompressCoder> &coder,
CMyComPtr<ICompressCoder2> &coder2,
bool encode);
HRESULT CreateCoder(
DECL_EXTERNAL_CODECS_LOC_VARS
CMethodId methodId,
CMyComPtr<ICompressCoder> &coder, bool encode);
HRESULT CreateFilter(
DECL_EXTERNAL_CODECS_LOC_VARS
CMethodId methodId,
CMyComPtr<ICompressFilter> &filter,
bool encode);
#endif

View file

@ -0,0 +1,57 @@
// FilePathAutoRename.cpp
#include "StdAfx.h"
#include "FilePathAutoRename.h"
#include "Common/Defs.h"
#include "Common/IntToString.h"
#include "Windows/FileName.h"
#include "Windows/FileFind.h"
using namespace NWindows;
static bool MakeAutoName(const UString &name,
const UString &extension, int value, UString &path)
{
wchar_t number[32];
ConvertUInt64ToString(value, number);
path = name;
path += number;
path += extension;
return NFile::NFind::DoesFileExist(path);
}
bool AutoRenamePath(UString &fullProcessedPath)
{
UString path;
int dotPos = fullProcessedPath.ReverseFind(L'.');
int slashPos = fullProcessedPath.ReverseFind(L'/');
#ifdef _WIN32
int slash1Pos = fullProcessedPath.ReverseFind(L'\\');
slashPos = MyMax(slashPos, slash1Pos);
#endif
UString name, extension;
if (dotPos > slashPos && dotPos > 0)
{
name = fullProcessedPath.Left(dotPos);
extension = fullProcessedPath.Mid(dotPos);
}
else
name = fullProcessedPath;
name += L'_';
int indexLeft = 1, indexRight = (1 << 30);
while (indexLeft != indexRight)
{
int indexMid = (indexLeft + indexRight) / 2;
if (MakeAutoName(name, extension, indexMid, path))
indexLeft = indexMid + 1;
else
indexRight = indexMid;
}
if (MakeAutoName(name, extension, indexRight, fullProcessedPath))
return false;
return true;
}

View file

@ -0,0 +1,10 @@
// Util/FilePathAutoRename.h
#ifndef __FILEPATHAUTORENAME_H
#define __FILEPATHAUTORENAME_H
#include "Common/MyString.h"
bool AutoRenamePath(UString &fullProcessedPath);
#endif

View file

@ -0,0 +1,261 @@
// FileStreams.cpp
#include "StdAfx.h"
#ifndef _WIN32
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#endif
#include "FileStreams.h"
static inline HRESULT ConvertBoolToHRESULT(bool result)
{
#ifdef _WIN32
if (result)
return S_OK;
DWORD lastError = ::GetLastError();
if (lastError == 0)
return E_FAIL;
return lastError;
#else
return result ? S_OK: E_FAIL;
#endif
}
bool CInFileStream::Open(LPCTSTR fileName)
{
return File.Open(fileName);
}
#ifdef USE_WIN_FILE
#ifndef _UNICODE
bool CInFileStream::Open(LPCWSTR fileName)
{
return File.Open(fileName);
}
#endif
#endif
bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite)
{
return File.OpenShared(fileName, shareForWrite);
}
#ifdef USE_WIN_FILE
#ifndef _UNICODE
bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite)
{
return File.OpenShared(fileName, shareForWrite);
}
#endif
#endif
STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
#ifdef USE_WIN_FILE
UInt32 realProcessedSize;
bool result = File.ReadPart(data, size, realProcessedSize);
if(processedSize != NULL)
*processedSize = realProcessedSize;
return ConvertBoolToHRESULT(result);
#else
if(processedSize != NULL)
*processedSize = 0;
ssize_t res = File.Read(data, (size_t)size);
if (res == -1)
return E_FAIL;
if(processedSize != NULL)
*processedSize = (UInt32)res;
return S_OK;
#endif
}
#ifndef _WIN32_WCE
STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
#ifdef _WIN32
UInt32 realProcessedSize;
BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE),
data, size, (DWORD *)&realProcessedSize, NULL);
if(processedSize != NULL)
*processedSize = realProcessedSize;
if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE)
return S_OK;
return ConvertBoolToHRESULT(res != FALSE);
#else
if(processedSize != NULL)
*processedSize = 0;
ssize_t res;
do
{
res = read(0, data, (size_t)size);
}
while (res < 0 && (errno == EINTR));
if (res == -1)
return E_FAIL;
if(processedSize != NULL)
*processedSize = (UInt32)res;
return S_OK;
#endif
}
#endif
STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin,
UInt64 *newPosition)
{
if(seekOrigin >= 3)
return STG_E_INVALIDFUNCTION;
#ifdef USE_WIN_FILE
UInt64 realNewPosition;
bool result = File.Seek(offset, seekOrigin, realNewPosition);
if(newPosition != NULL)
*newPosition = realNewPosition;
return ConvertBoolToHRESULT(result);
#else
off_t res = File.Seek(offset, seekOrigin);
if (res == -1)
return E_FAIL;
if(newPosition != NULL)
*newPosition = (UInt64)res;
return S_OK;
#endif
}
STDMETHODIMP CInFileStream::GetSize(UInt64 *size)
{
return ConvertBoolToHRESULT(File.GetLength(*size));
}
//////////////////////////
// COutFileStream
HRESULT COutFileStream::Close()
{
return ConvertBoolToHRESULT(File.Close());
}
STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
#ifdef USE_WIN_FILE
UInt32 realProcessedSize;
bool result = File.WritePart(data, size, realProcessedSize);
ProcessedSize += realProcessedSize;
if(processedSize != NULL)
*processedSize = realProcessedSize;
return ConvertBoolToHRESULT(result);
#else
if(processedSize != NULL)
*processedSize = 0;
ssize_t res = File.Write(data, (size_t)size);
if (res == -1)
return E_FAIL;
if(processedSize != NULL)
*processedSize = (UInt32)res;
ProcessedSize += res;
return S_OK;
#endif
}
STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
{
if(seekOrigin >= 3)
return STG_E_INVALIDFUNCTION;
#ifdef USE_WIN_FILE
UInt64 realNewPosition;
bool result = File.Seek(offset, seekOrigin, realNewPosition);
if(newPosition != NULL)
*newPosition = realNewPosition;
return ConvertBoolToHRESULT(result);
#else
off_t res = File.Seek(offset, seekOrigin);
if (res == -1)
return E_FAIL;
if(newPosition != NULL)
*newPosition = (UInt64)res;
return S_OK;
#endif
}
STDMETHODIMP COutFileStream::SetSize(Int64 newSize)
{
#ifdef USE_WIN_FILE
UInt64 currentPos;
if(!File.Seek(0, FILE_CURRENT, currentPos))
return E_FAIL;
bool result = File.SetLength(newSize);
UInt64 currentPos2;
result = result && File.Seek(currentPos, currentPos2);
return result ? S_OK : E_FAIL;
#else
return E_FAIL;
#endif
}
#ifndef _WIN32_WCE
STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
if(processedSize != NULL)
*processedSize = 0;
#ifdef _WIN32
UInt32 realProcessedSize;
BOOL res = TRUE;
if (size > 0)
{
// Seems that Windows doesn't like big amounts writing to stdout.
// So we limit portions by 32KB.
UInt32 sizeTemp = (1 << 15);
if (sizeTemp > size)
sizeTemp = size;
res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),
data, sizeTemp, (DWORD *)&realProcessedSize, NULL);
size -= realProcessedSize;
data = (const void *)((const Byte *)data + realProcessedSize);
if(processedSize != NULL)
*processedSize += realProcessedSize;
}
return ConvertBoolToHRESULT(res != FALSE);
#else
ssize_t res;
do
{
res = write(1, data, (size_t)size);
}
while (res < 0 && (errno == EINTR));
if (res == -1)
return E_FAIL;
if(processedSize != NULL)
*processedSize = (UInt32)res;
return S_OK;
return S_OK;
#endif
}
#endif

View file

@ -0,0 +1,143 @@
// FileStreams.h
#ifndef __FILESTREAMS_H
#define __FILESTREAMS_H
#ifdef _WIN32
#define USE_WIN_FILE
#endif
#ifdef USE_WIN_FILE
#include "../../Windows/FileIO.h"
#else
#include "../../Common/C_FileIO.h"
#endif
#include "../IStream.h"
#include "../../Common/MyCom.h"
class CInFileStream:
public IInStream,
public IStreamGetSize,
public CMyUnknownImp
{
public:
#ifdef USE_WIN_FILE
NWindows::NFile::NIO::CInFile File;
#else
NC::NFile::NIO::CInFile File;
#endif
CInFileStream() {}
virtual ~CInFileStream() {}
bool Open(LPCTSTR fileName);
#ifdef USE_WIN_FILE
#ifndef _UNICODE
bool Open(LPCWSTR fileName);
#endif
#endif
bool OpenShared(LPCTSTR fileName, bool shareForWrite);
#ifdef USE_WIN_FILE
#ifndef _UNICODE
bool OpenShared(LPCWSTR fileName, bool shareForWrite);
#endif
#endif
MY_UNKNOWN_IMP2(IInStream, IStreamGetSize)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
STDMETHOD(GetSize)(UInt64 *size);
};
#ifndef _WIN32_WCE
class CStdInFileStream:
public ISequentialInStream,
public CMyUnknownImp
{
public:
// HANDLE File;
// CStdInFileStream() File(INVALID_HANDLE_VALUE): {}
// void Open() { File = GetStdHandle(STD_INPUT_HANDLE); };
MY_UNKNOWN_IMP
virtual ~CStdInFileStream() {}
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
};
#endif
class COutFileStream:
public IOutStream,
public CMyUnknownImp
{
#ifdef USE_WIN_FILE
NWindows::NFile::NIO::COutFile File;
#else
NC::NFile::NIO::COutFile File;
#endif
public:
virtual ~COutFileStream() {}
bool Create(LPCTSTR fileName, bool createAlways)
{
ProcessedSize = 0;
return File.Create(fileName, createAlways);
}
bool Open(LPCTSTR fileName, DWORD creationDisposition)
{
ProcessedSize = 0;
return File.Open(fileName, creationDisposition);
}
#ifdef USE_WIN_FILE
#ifndef _UNICODE
bool Create(LPCWSTR fileName, bool createAlways)
{
ProcessedSize = 0;
return File.Create(fileName, createAlways);
}
bool Open(LPCWSTR fileName, DWORD creationDisposition)
{
ProcessedSize = 0;
return File.Open(fileName, creationDisposition);
}
#endif
#endif
HRESULT Close();
UInt64 ProcessedSize;
#ifdef USE_WIN_FILE
bool SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime)
{
return File.SetTime(creationTime, lastAccessTime, lastWriteTime);
}
bool SetLastWriteTime(const FILETIME *lastWriteTime)
{
return File.SetLastWriteTime(lastWriteTime);
}
#endif
MY_UNKNOWN_IMP1(IOutStream)
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
STDMETHOD(SetSize)(Int64 newSize);
};
#ifndef _WIN32_WCE
class CStdOutFileStream:
public ISequentialOutStream,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP
virtual ~CStdOutFileStream() {}
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
};
#endif
#endif

View file

@ -0,0 +1,264 @@
// FilterCoder.cpp
#include "StdAfx.h"
#include "FilterCoder.h"
extern "C"
{
#include "../../../C/Alloc.h"
}
#include "../../Common/Defs.h"
#include "StreamUtils.h"
static const UInt32 kBufferSize = 1 << 17;
CFilterCoder::CFilterCoder()
{
_buffer = (Byte *)::MidAlloc(kBufferSize);
}
CFilterCoder::~CFilterCoder()
{
::MidFree(_buffer);
}
HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size)
{
if (_outSizeIsDefined)
{
UInt64 remSize = _outSize - _nowPos64;
if (size > remSize)
size = (UInt32)remSize;
}
UInt32 processedSize = 0;
RINOK(WriteStream(outStream, _buffer, size, &processedSize));
if (size != processedSize)
return E_FAIL;
_nowPos64 += processedSize;
return S_OK;
}
STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
RINOK(Init());
UInt32 bufferPos = 0;
_outSizeIsDefined = (outSize != 0);
if (_outSizeIsDefined)
_outSize = *outSize;
while(NeedMore())
{
UInt32 processedSize;
// Change it: It can be optimized using ReadPart
RINOK(ReadStream(inStream, _buffer + bufferPos, kBufferSize - bufferPos, &processedSize));
UInt32 endPos = bufferPos + processedSize;
bufferPos = Filter->Filter(_buffer, endPos);
if (bufferPos > endPos)
{
for (; endPos< bufferPos; endPos++)
_buffer[endPos] = 0;
bufferPos = Filter->Filter(_buffer, endPos);
}
if (bufferPos == 0)
{
if (endPos > 0)
return WriteWithLimit(outStream, endPos);
return S_OK;
}
RINOK(WriteWithLimit(outStream, bufferPos));
if (progress != NULL)
{
RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64));
}
UInt32 i = 0;
while(bufferPos < endPos)
_buffer[i++] = _buffer[bufferPos++];
bufferPos = i;
}
return S_OK;
}
// #ifdef _ST_MODE
STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream)
{
_bufferPos = 0;
_outStream = outStream;
return Init();
}
STDMETHODIMP CFilterCoder::ReleaseOutStream()
{
_outStream.Release();
return S_OK;
};
STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 processedSizeTotal = 0;
while(size > 0)
{
UInt32 sizeMax = kBufferSize - _bufferPos;
UInt32 sizeTemp = size;
if (sizeTemp > sizeMax)
sizeTemp = sizeMax;
memmove(_buffer + _bufferPos, data, sizeTemp);
size -= sizeTemp;
processedSizeTotal += sizeTemp;
data = (const Byte *)data + sizeTemp;
UInt32 endPos = _bufferPos + sizeTemp;
_bufferPos = Filter->Filter(_buffer, endPos);
if (_bufferPos == 0)
{
_bufferPos = endPos;
break;
}
if (_bufferPos > endPos)
{
if (size != 0)
return E_FAIL;
break;
}
RINOK(WriteWithLimit(_outStream, _bufferPos));
UInt32 i = 0;
while(_bufferPos < endPos)
_buffer[i++] = _buffer[_bufferPos++];
_bufferPos = i;
}
if (processedSize != NULL)
*processedSize = processedSizeTotal;
return S_OK;
}
STDMETHODIMP CFilterCoder::Flush()
{
if (_bufferPos != 0)
{
UInt32 endPos = Filter->Filter(_buffer, _bufferPos);
if (endPos > _bufferPos)
{
for (; _bufferPos < endPos; _bufferPos++)
_buffer[_bufferPos] = 0;
if (Filter->Filter(_buffer, endPos) != endPos)
return E_FAIL;
}
UInt32 processedSize;
RINOK(WriteStream(_outStream, _buffer, _bufferPos, &processedSize));
if (_bufferPos != processedSize)
return E_FAIL;
_bufferPos = 0;
}
CMyComPtr<IOutStreamFlush> flush;
_outStream.QueryInterface(IID_IOutStreamFlush, &flush);
if (flush)
return flush->Flush();
return S_OK;
}
STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream)
{
_convertedPosBegin = _convertedPosEnd = _bufferPos = 0;
_inStream = inStream;
return Init();
}
STDMETHODIMP CFilterCoder::ReleaseInStream()
{
_inStream.Release();
return S_OK;
};
STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 processedSizeTotal = 0;
while(size > 0)
{
if (_convertedPosBegin != _convertedPosEnd)
{
UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin);
memmove(data, _buffer + _convertedPosBegin, sizeTemp);
_convertedPosBegin += sizeTemp;
data = (void *)((Byte *)data + sizeTemp);
size -= sizeTemp;
processedSizeTotal += sizeTemp;
break;
}
int i;
for (i = 0; _convertedPosEnd + i < _bufferPos; i++)
_buffer[i] = _buffer[i + _convertedPosEnd];
_bufferPos = i;
_convertedPosBegin = _convertedPosEnd = 0;
UInt32 processedSizeTemp;
UInt32 size0 = kBufferSize - _bufferPos;
// Optimize it:
RINOK(ReadStream(_inStream, _buffer + _bufferPos, size0, &processedSizeTemp));
_bufferPos = _bufferPos + processedSizeTemp;
_convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
if (_convertedPosEnd == 0)
{
if (_bufferPos == 0)
break;
else
{
_convertedPosEnd = _bufferPos; // check it
continue;
}
}
if (_convertedPosEnd > _bufferPos)
{
for (; _bufferPos < _convertedPosEnd; _bufferPos++)
_buffer[_bufferPos] = 0;
_convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
}
}
if (processedSize != NULL)
*processedSize = processedSizeTotal;
return S_OK;
}
// #endif // _ST_MODE
#ifndef _NO_CRYPTO
STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)
{
return _setPassword->CryptoSetPassword(data, size);
}
#endif
#ifndef EXTRACT_ONLY
STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs,
const PROPVARIANT *properties, UInt32 numProperties)
{
return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties);
}
STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)
{
return _writeCoderProperties->WriteCoderProperties(outStream);
}
/*
STDMETHODIMP CFilterCoder::ResetSalt()
{
return _CryptoResetSalt->ResetSalt();
}
*/
STDMETHODIMP CFilterCoder::ResetInitVector()
{
return _CryptoResetInitVector->ResetInitVector();
}
#endif
STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size)
{
return _setDecoderProperties->SetDecoderProperties2(data, size);
}

View file

@ -0,0 +1,143 @@
// FilterCoder.h
#ifndef __FILTERCODER_H
#define __FILTERCODER_H
#include "../../Common/MyCom.h"
#include "../ICoder.h"
#include "../IPassword.h"
#define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) if (iid == IID_ ## i) \
{ if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \
*outObject = (void *)(i *)this; AddRef(); return S_OK; }
class CFilterCoder:
public ICompressCoder,
// #ifdef _ST_MODE
public ICompressSetInStream,
public ISequentialInStream,
public ICompressSetOutStream,
public ISequentialOutStream,
public IOutStreamFlush,
// #endif
#ifndef _NO_CRYPTO
public ICryptoSetPassword,
#endif
#ifndef EXTRACT_ONLY
public ICompressSetCoderProperties,
public ICompressWriteCoderProperties,
// public ICryptoResetSalt,
public ICryptoResetInitVector,
#endif
public ICompressSetDecoderProperties2,
public CMyUnknownImp
{
protected:
Byte *_buffer;
// #ifdef _ST_MODE
CMyComPtr<ISequentialInStream> _inStream;
CMyComPtr<ISequentialOutStream> _outStream;
UInt32 _bufferPos;
UInt32 _convertedPosBegin;
UInt32 _convertedPosEnd;
// #endif
bool _outSizeIsDefined;
UInt64 _outSize;
UInt64 _nowPos64;
HRESULT Init()
{
_nowPos64 = 0;
_outSizeIsDefined = false;
return Filter->Init();
}
CMyComPtr<ICryptoSetPassword> _setPassword;
#ifndef EXTRACT_ONLY
CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties;
CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties;
// CMyComPtr<ICryptoResetSalt> _CryptoResetSalt;
CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector;
#endif
CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties;
public:
CMyComPtr<ICompressFilter> Filter;
CFilterCoder();
~CFilterCoder();
HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size);
bool NeedMore() const
{ return (!_outSizeIsDefined || (_nowPos64 < _outSize)); }
public:
MY_QUERYINTERFACE_BEGIN
MY_QUERYINTERFACE_ENTRY(ICompressCoder)
// #ifdef _ST_MODE
MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
MY_QUERYINTERFACE_ENTRY(ISequentialInStream)
MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream)
MY_QUERYINTERFACE_ENTRY(ISequentialOutStream)
MY_QUERYINTERFACE_ENTRY(IOutStreamFlush)
// #endif
#ifndef _NO_CRYPTO
MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword)
#endif
#ifndef EXTRACT_ONLY
MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties)
MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties)
// MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt)
MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector)
#endif
MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties)
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
STDMETHOD(Code)(ISequentialInStream *inStream,
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
// #ifdef _ST_MODE
STDMETHOD(ReleaseInStream)();
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \
STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);
STDMETHOD(ReleaseOutStream)();
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Flush)();
// #endif
#ifndef _NO_CRYPTO
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
#endif
#ifndef EXTRACT_ONLY
STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
const PROPVARIANT *properties, UInt32 numProperties);
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
// STDMETHOD(ResetSalt)();
STDMETHOD(ResetInitVector)();
#endif
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
};
// #ifdef _ST_MODE
class CInStreamReleaser
{
public:
CFilterCoder *FilterCoder;
CInStreamReleaser(): FilterCoder(0) {}
~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); }
};
class COutStreamReleaser
{
public:
CFilterCoder *FilterCoder;
COutStreamReleaser(): FilterCoder(0) {}
~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); }
};
// #endif
#endif

View file

@ -0,0 +1,83 @@
// InBuffer.cpp
#include "StdAfx.h"
#include "InBuffer.h"
extern "C"
{
#include "../../../C/Alloc.h"
}
CInBuffer::CInBuffer():
_buffer(0),
_bufferLimit(0),
_bufferBase(0),
_stream(0),
_bufferSize(0)
{}
bool CInBuffer::Create(UInt32 bufferSize)
{
const UInt32 kMinBlockSize = 1;
if (bufferSize < kMinBlockSize)
bufferSize = kMinBlockSize;
if (_bufferBase != 0 && _bufferSize == bufferSize)
return true;
Free();
_bufferSize = bufferSize;
_bufferBase = (Byte *)::MidAlloc(bufferSize);
return (_bufferBase != 0);
}
void CInBuffer::Free()
{
::MidFree(_bufferBase);
_bufferBase = 0;
}
void CInBuffer::SetStream(ISequentialInStream *stream)
{
_stream = stream;
}
void CInBuffer::Init()
{
_processedSize = 0;
_buffer = _bufferBase;
_bufferLimit = _buffer;
_wasFinished = false;
#ifdef _NO_EXCEPTIONS
ErrorCode = S_OK;
#endif
}
bool CInBuffer::ReadBlock()
{
#ifdef _NO_EXCEPTIONS
if (ErrorCode != S_OK)
return false;
#endif
if (_wasFinished)
return false;
_processedSize += (_buffer - _bufferBase);
UInt32 numProcessedBytes;
HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes);
#ifdef _NO_EXCEPTIONS
ErrorCode = result;
#else
if (result != S_OK)
throw CInBufferException(result);
#endif
_buffer = _bufferBase;
_bufferLimit = _buffer + numProcessedBytes;
_wasFinished = (numProcessedBytes == 0);
return (!_wasFinished);
}
Byte CInBuffer::ReadBlock2()
{
if(!ReadBlock())
return 0xFF;
return *_buffer++;
}

View file

@ -0,0 +1,75 @@
// InBuffer.h
#ifndef __INBUFFER_H
#define __INBUFFER_H
#include "../IStream.h"
#include "../../Common/MyCom.h"
#include "../../Common/MyException.h"
#ifndef _NO_EXCEPTIONS
struct CInBufferException: public CSystemException
{
CInBufferException(HRESULT errorCode): CSystemException(errorCode) {}
};
#endif
class CInBuffer
{
Byte *_buffer;
Byte *_bufferLimit;
Byte *_bufferBase;
CMyComPtr<ISequentialInStream> _stream;
UInt64 _processedSize;
UInt32 _bufferSize;
bool _wasFinished;
bool ReadBlock();
Byte ReadBlock2();
public:
#ifdef _NO_EXCEPTIONS
HRESULT ErrorCode;
#endif
CInBuffer();
~CInBuffer() { Free(); }
bool Create(UInt32 bufferSize);
void Free();
void SetStream(ISequentialInStream *stream);
void Init();
void ReleaseStream() { _stream.Release(); }
bool ReadByte(Byte &b)
{
if(_buffer >= _bufferLimit)
if(!ReadBlock())
return false;
b = *_buffer++;
return true;
}
Byte ReadByte()
{
if(_buffer >= _bufferLimit)
return ReadBlock2();
return *_buffer++;
}
void ReadBytes(void *data, UInt32 size, UInt32 &processedSize)
{
for(processedSize = 0; processedSize < size; processedSize++)
if (!ReadByte(((Byte *)data)[processedSize]))
return;
}
bool ReadBytes(void *data, UInt32 size)
{
UInt32 processedSize;
ReadBytes(data, size, processedSize);
return (processedSize == size);
}
UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); }
bool WasFinished() const { return _wasFinished; }
};
#endif

View file

@ -0,0 +1,122 @@
// InOutTempBuffer.cpp
#include "StdAfx.h"
#include "InOutTempBuffer.h"
#include "../../Common/Defs.h"
// #include "Windows/Defs.h"
#include "StreamUtils.h"
using namespace NWindows;
using namespace NFile;
using namespace NDirectory;
static UInt32 kTmpBufferMemorySize = (1 << 20);
static LPCTSTR kTempFilePrefixString = TEXT("iot");
CInOutTempBuffer::CInOutTempBuffer():
_buffer(NULL)
{
}
void CInOutTempBuffer::Create()
{
_buffer = new Byte[kTmpBufferMemorySize];
}
CInOutTempBuffer::~CInOutTempBuffer()
{
delete []_buffer;
}
void CInOutTempBuffer::InitWriting()
{
_bufferPosition = 0;
_tmpFileCreated = false;
_fileSize = 0;
}
bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size)
{
if (size == 0)
return true;
if(!_tmpFileCreated)
{
CSysString tempDirPath;
if(!MyGetTempPath(tempDirPath))
return false;
if (_tempFile.Create(tempDirPath, kTempFilePrefixString, _tmpFileName) == 0)
return false;
// _outFile.SetOpenCreationDispositionCreateAlways();
if(!_outFile.Create(_tmpFileName, true))
return false;
_tmpFileCreated = true;
}
UInt32 processedSize;
if(!_outFile.Write(data, size, processedSize))
return false;
_fileSize += processedSize;
return (processedSize == size);
}
bool CInOutTempBuffer::FlushWrite()
{
return _outFile.Close();
}
bool CInOutTempBuffer::Write(const void *data, UInt32 size)
{
if(_bufferPosition < kTmpBufferMemorySize)
{
UInt32 curSize = MyMin(kTmpBufferMemorySize - _bufferPosition, size);
memmove(_buffer + _bufferPosition, (const Byte *)data, curSize);
_bufferPosition += curSize;
size -= curSize;
data = ((const Byte *)data) + curSize;
_fileSize += curSize;
}
return WriteToFile(data, size);
}
bool CInOutTempBuffer::InitReading()
{
_currentPositionInBuffer = 0;
if(_tmpFileCreated)
return _inFile.Open(_tmpFileName);
return true;
}
HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream)
{
if (_currentPositionInBuffer < _bufferPosition)
{
UInt32 sizeToWrite = _bufferPosition - _currentPositionInBuffer;
RINOK(WriteStream(stream, _buffer + _currentPositionInBuffer, sizeToWrite, NULL));
_currentPositionInBuffer += sizeToWrite;
}
if (!_tmpFileCreated)
return true;
for (;;)
{
UInt32 localProcessedSize;
if (!_inFile.ReadPart(_buffer, kTmpBufferMemorySize, localProcessedSize))
return E_FAIL;
if (localProcessedSize == 0)
return S_OK;
RINOK(WriteStream(stream, _buffer, localProcessedSize, NULL));
}
}
STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
if (!_buffer->Write(data, size))
{
if (processedSize != NULL)
*processedSize = 0;
return E_FAIL;
}
if (processedSize != NULL)
*processedSize = size;
return S_OK;
}

View file

@ -0,0 +1,55 @@
// Util/InOutTempBuffer.h
#ifndef __IN_OUT_TEMP_BUFFER_H
#define __IN_OUT_TEMP_BUFFER_H
#include "../../Windows/FileIO.h"
#include "../../Windows/FileDir.h"
#include "../../Common/MyCom.h"
#include "../IStream.h"
class CInOutTempBuffer
{
NWindows::NFile::NDirectory::CTempFile _tempFile;
NWindows::NFile::NIO::COutFile _outFile;
NWindows::NFile::NIO::CInFile _inFile;
Byte *_buffer;
UInt32 _bufferPosition;
UInt32 _currentPositionInBuffer;
CSysString _tmpFileName;
bool _tmpFileCreated;
UInt64 _fileSize;
bool WriteToFile(const void *data, UInt32 size);
public:
CInOutTempBuffer();
~CInOutTempBuffer();
void Create();
void InitWriting();
bool Write(const void *data, UInt32 size);
UInt64 GetDataSize() const { return _fileSize; }
bool FlushWrite();
bool InitReading();
HRESULT WriteToStream(ISequentialOutStream *stream);
};
class CSequentialOutTempBufferImp:
public ISequentialOutStream,
public CMyUnknownImp
{
CInOutTempBuffer *_buffer;
public:
// CSequentialOutStreamImp(): _size(0) {}
// UInt32 _size;
void Init(CInOutTempBuffer *buffer) { _buffer = buffer; }
// UInt32 GetSize() const { return _size; }
MY_UNKNOWN_IMP
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
};
#endif

View file

@ -0,0 +1,24 @@
// LimitedStreams.cpp
#include "StdAfx.h"
#include "LimitedStreams.h"
#include "../../Common/Defs.h"
STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 realProcessedSize = 0;
UInt32 sizeToRead = (UInt32)MyMin((_size - _pos), (UInt64)size);
HRESULT result = S_OK;
if (sizeToRead > 0)
{
result = _stream->Read(data, sizeToRead, &realProcessedSize);
_pos += realProcessedSize;
if (realProcessedSize == 0)
_wasFinished = true;
}
if(processedSize != NULL)
*processedSize = realProcessedSize;
return result;
}

View file

@ -0,0 +1,33 @@
// LimitedStreams.h
#ifndef __LIMITEDSTREAMS_H
#define __LIMITEDSTREAMS_H
#include "../../Common/MyCom.h"
#include "../IStream.h"
class CLimitedSequentialInStream:
public ISequentialInStream,
public CMyUnknownImp
{
CMyComPtr<ISequentialInStream> _stream;
UInt64 _size;
UInt64 _pos;
bool _wasFinished;
public:
void SetStream(ISequentialInStream *stream) { _stream = stream; }
void Init(UInt64 streamSize)
{
_size = streamSize;
_pos = 0;
_wasFinished = false;
}
MY_UNKNOWN_IMP
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
UInt64 GetSize() const { return _pos; }
bool WasFinished() const { return _wasFinished; }
};
#endif

View file

@ -0,0 +1,23 @@
// LockedStream.cpp
#include "StdAfx.h"
#include "LockedStream.h"
HRESULT CLockedInStream::Read(UInt64 startPos, void *data, UInt32 size,
UInt32 *processedSize)
{
NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
RINOK(_stream->Seek(startPos, STREAM_SEEK_SET, NULL));
return _stream->Read(data, size, processedSize);
}
STDMETHODIMP CLockedSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 realProcessedSize = 0;
HRESULT result = _lockedInStream->Read(_pos, data, size, &realProcessedSize);
_pos += realProcessedSize;
if (processedSize != NULL)
*processedSize = realProcessedSize;
return result;
}

View file

@ -0,0 +1,38 @@
// LockedStream.h
#ifndef __LOCKEDSTREAM_H
#define __LOCKEDSTREAM_H
#include "../../Windows/Synchronization.h"
#include "../../Common/MyCom.h"
#include "../IStream.h"
class CLockedInStream
{
CMyComPtr<IInStream> _stream;
NWindows::NSynchronization::CCriticalSection _criticalSection;
public:
void Init(IInStream *stream)
{ _stream = stream; }
HRESULT Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize);
};
class CLockedSequentialInStreamImp:
public ISequentialInStream,
public CMyUnknownImp
{
CLockedInStream *_lockedInStream;
UInt64 _pos;
public:
void Init(CLockedInStream *lockedInStream, UInt64 startPos)
{
_lockedInStream = lockedInStream;
_pos = startPos;
}
MY_UNKNOWN_IMP
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
};
#endif

View file

@ -0,0 +1,27 @@
// MethodId.cpp
#include "StdAfx.h"
#include "MethodId.h"
#include "../../Common/MyString.h"
static inline wchar_t GetHex(Byte value)
{
return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
}
UString ConvertMethodIdToString(UInt64 id)
{
wchar_t s[32];
int len = 32;
s[--len] = 0;
do
{
s[--len] = GetHex((Byte)id & 0xF);
id >>= 4;
s[--len] = GetHex((Byte)id & 0xF);
id >>= 4;
}
while (id != 0);
return s + len;
}

View file

@ -0,0 +1,10 @@
// MethodId.h
#ifndef __7Z_METHOD_ID_H
#define __7Z_METHOD_ID_H
#include "../../Common/Types.h"
typedef UInt64 CMethodId;
#endif

View file

@ -0,0 +1,96 @@
// MethodProps.cpp
#include "StdAfx.h"
#include "MethodProps.h"
#include "../../Common/MyCom.h"
static UInt64 k_LZMA = 0x030101;
// static UInt64 k_LZMA2 = 0x030102;
HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder)
{
bool tryReduce = false;
UInt32 reducedDictionarySize = 1 << 10;
if (inSizeForReduce != 0 && (method.Id == k_LZMA /* || methodFull.MethodID == k_LZMA2 */))
{
for (;;)
{
const UInt32 step = (reducedDictionarySize >> 1);
if (reducedDictionarySize >= *inSizeForReduce)
{
tryReduce = true;
break;
}
reducedDictionarySize += step;
if (reducedDictionarySize >= *inSizeForReduce)
{
tryReduce = true;
break;
}
if (reducedDictionarySize >= ((UInt32)3 << 30))
break;
reducedDictionarySize += step;
}
}
{
int numProperties = method.Properties.Size();
CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties);
if (setCoderProperties == NULL)
{
if (numProperties != 0)
return E_INVALIDARG;
}
else
{
CRecordVector<PROPID> propIDs;
NWindows::NCOM::CPropVariant *values = new NWindows::NCOM::CPropVariant[numProperties];
HRESULT res = S_OK;
try
{
for (int i = 0; i < numProperties; i++)
{
const CProp &prop = method.Properties[i];
propIDs.Add(prop.Id);
NWindows::NCOM::CPropVariant &value = values[i];
value = prop.Value;
// if (tryReduce && prop.Id == NCoderPropID::kDictionarySize && value.vt == VT_UI4 && reducedDictionarySize < value.ulVal)
if (tryReduce)
if (prop.Id == NCoderPropID::kDictionarySize)
if (value.vt == VT_UI4)
if (reducedDictionarySize < value.ulVal)
value.ulVal = reducedDictionarySize;
}
CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties);
res = setCoderProperties->SetCoderProperties(&propIDs.Front(), values, numProperties);
}
catch(...)
{
delete []values;
throw;
}
delete []values;
RINOK(res);
}
}
/*
CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
if (writeCoderProperties != NULL)
{
CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp;
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
outStreamSpec->Init();
RINOK(writeCoderProperties->WriteCoderProperties(outStream));
size_t size = outStreamSpec->GetSize();
filterProps.SetCapacity(size);
memmove(filterProps, outStreamSpec->GetBuffer(), size);
}
*/
return S_OK;
}

View file

@ -0,0 +1,41 @@
// MethodProps.h
#ifndef __7Z_METHOD_PROPS_H
#define __7Z_METHOD_PROPS_H
#include "MethodId.h"
#include "../../Windows/PropVariant.h"
#include "../../Common/MyVector.h"
#include "../ICoder.h"
struct CProp
{
PROPID Id;
NWindows::NCOM::CPropVariant Value;
};
struct CMethod
{
CMethodId Id;
CObjectVector<CProp> Properties;
};
struct CMethodsMode
{
CObjectVector<CMethod> Methods;
#ifdef COMPRESS_MT
UInt32 NumThreads;
#endif
CMethodsMode()
#ifdef COMPRESS_MT
: NumThreads(1)
#endif
{}
bool IsEmpty() const { return Methods.IsEmpty() ; }
};
HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder);
#endif

View file

@ -0,0 +1,35 @@
// OffsetStream.cpp
#include "StdAfx.h"
#include "Common/Defs.h"
#include "OffsetStream.h"
HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset)
{
_offset = offset;
_stream = stream;
return _stream->Seek(offset, STREAM_SEEK_SET, NULL);
}
STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
return _stream->Write(data, size, processedSize);
}
STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin,
UInt64 *newPosition)
{
UInt64 absoluteNewPosition;
if (seekOrigin == STREAM_SEEK_SET)
offset += _offset;
HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition);
if (newPosition != NULL)
*newPosition = absoluteNewPosition - _offset;
return result;
}
STDMETHODIMP COffsetOutStream::SetSize(Int64 newSize)
{
return _stream->SetSize(_offset + newSize);
}

View file

@ -0,0 +1,25 @@
// OffsetStream.h
#ifndef __OFFSETSTREAM_H
#define __OFFSETSTREAM_H
#include "Common/MyCom.h"
#include "../IStream.h"
class COffsetOutStream:
public IOutStream,
public CMyUnknownImp
{
UInt64 _offset;
CMyComPtr<IOutStream> _stream;
public:
HRESULT Init(IOutStream *stream, UInt64 offset);
MY_UNKNOWN_IMP
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
STDMETHOD(SetSize)(Int64 newSize);
};
#endif

View file

@ -0,0 +1,119 @@
// OutByte.cpp
#include "StdAfx.h"
#include "OutBuffer.h"
extern "C"
{
#include "../../../C/Alloc.h"
}
bool COutBuffer::Create(UInt32 bufferSize)
{
const UInt32 kMinBlockSize = 1;
if (bufferSize < kMinBlockSize)
bufferSize = kMinBlockSize;
if (_buffer != 0 && _bufferSize == bufferSize)
return true;
Free();
_bufferSize = bufferSize;
_buffer = (Byte *)::MidAlloc(bufferSize);
return (_buffer != 0);
}
void COutBuffer::Free()
{
::MidFree(_buffer);
_buffer = 0;
}
void COutBuffer::SetStream(ISequentialOutStream *stream)
{
_stream = stream;
}
void COutBuffer::Init()
{
_streamPos = 0;
_limitPos = _bufferSize;
_pos = 0;
_processedSize = 0;
_overDict = false;
#ifdef _NO_EXCEPTIONS
ErrorCode = S_OK;
#endif
}
UInt64 COutBuffer::GetProcessedSize() const
{
UInt64 res = _processedSize + _pos - _streamPos;
if (_streamPos > _pos)
res += _bufferSize;
return res;
}
HRESULT COutBuffer::FlushPart()
{
// _streamPos < _bufferSize
UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos);
HRESULT result = S_OK;
#ifdef _NO_EXCEPTIONS
result = ErrorCode;
#endif
if (_buffer2 != 0)
{
memmove(_buffer2, _buffer + _streamPos, size);
_buffer2 += size;
}
if (_stream != 0
#ifdef _NO_EXCEPTIONS
&& (ErrorCode == S_OK)
#endif
)
{
UInt32 processedSize = 0;
result = _stream->Write(_buffer + _streamPos, size, &processedSize);
size = processedSize;
}
_streamPos += size;
if (_streamPos == _bufferSize)
_streamPos = 0;
if (_pos == _bufferSize)
{
_overDict = true;
_pos = 0;
}
_limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize;
_processedSize += size;
return result;
}
HRESULT COutBuffer::Flush()
{
#ifdef _NO_EXCEPTIONS
if (ErrorCode != S_OK)
return ErrorCode;
#endif
while(_streamPos != _pos)
{
HRESULT result = FlushPart();
if (result != S_OK)
return result;
}
return S_OK;
}
void COutBuffer::FlushWithCheck()
{
HRESULT result = Flush();
#ifdef _NO_EXCEPTIONS
ErrorCode = result;
#else
if (result != S_OK)
throw COutBufferException(result);
#endif
}

View file

@ -0,0 +1,64 @@
// OutBuffer.h
#ifndef __OUTBUFFER_H
#define __OUTBUFFER_H
#include "../IStream.h"
#include "../../Common/MyCom.h"
#include "../../Common/MyException.h"
#ifndef _NO_EXCEPTIONS
struct COutBufferException: public CSystemException
{
COutBufferException(HRESULT errorCode): CSystemException(errorCode) {}
};
#endif
class COutBuffer
{
protected:
Byte *_buffer;
UInt32 _pos;
UInt32 _limitPos;
UInt32 _streamPos;
UInt32 _bufferSize;
CMyComPtr<ISequentialOutStream> _stream;
UInt64 _processedSize;
Byte *_buffer2;
bool _overDict;
HRESULT FlushPart();
public:
#ifdef _NO_EXCEPTIONS
HRESULT ErrorCode;
#endif
COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {}
~COutBuffer() { Free(); }
bool Create(UInt32 bufferSize);
void Free();
void SetMemStream(Byte *buffer) { _buffer2 = buffer; }
void SetStream(ISequentialOutStream *stream);
void Init();
HRESULT Flush();
void FlushWithCheck();
void ReleaseStream() { _stream.Release(); }
void WriteByte(Byte b)
{
_buffer[_pos++] = b;
if(_pos == _limitPos)
FlushWithCheck();
}
void WriteBytes(const void *data, size_t size)
{
for (size_t i = 0; i < size; i++)
WriteByte(((const Byte *)data)[i]);
}
UInt64 GetProcessedSize() const;
};
#endif

View file

@ -0,0 +1,42 @@
// ProgressUtils.h
#include "StdAfx.h"
#include "ProgressUtils.h"
CLocalProgress::CLocalProgress()
{
ProgressOffset = InSize = OutSize = 0;
SendRatio = SendProgress = true;
}
void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain)
{
_ratioProgress.Release();
_progress = progress;
_progress.QueryInterface(IID_ICompressProgressInfo, &_ratioProgress);
_inSizeIsMain = inSizeIsMain;
}
STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
{
UInt64 inSizeNew = InSize, outSizeNew = OutSize;
if (inSize)
inSizeNew += (*inSize);
if (outSize)
outSizeNew += (*outSize);
if (SendRatio && _ratioProgress)
{
RINOK(_ratioProgress->SetRatioInfo(&inSizeNew, &outSizeNew));
}
inSizeNew += ProgressOffset;
outSizeNew += ProgressOffset;
if (SendProgress)
return _progress->SetCompleted(_inSizeIsMain ? &inSizeNew : &outSizeNew);
return S_OK;
}
HRESULT CLocalProgress::SetCur()
{
return SetRatioInfo(NULL, NULL);
}

View file

@ -0,0 +1,34 @@
// ProgressUtils.h
#ifndef __PROGRESSUTILS_H
#define __PROGRESSUTILS_H
#include "../../Common/MyCom.h"
#include "../ICoder.h"
#include "../IProgress.h"
class CLocalProgress:
public ICompressProgressInfo,
public CMyUnknownImp
{
CMyComPtr<IProgress> _progress;
CMyComPtr<ICompressProgressInfo> _ratioProgress;
bool _inSizeIsMain;
public:
UInt64 ProgressOffset;
UInt64 InSize;
UInt64 OutSize;
bool SendRatio;
bool SendProgress;
CLocalProgress();
void Init(IProgress *progress, bool inSizeIsMain);
HRESULT SetCur();
MY_UNKNOWN_IMP
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
};
#endif

View file

@ -0,0 +1,36 @@
// RegisterArc.h
#ifndef __REGISTERARC_H
#define __REGISTERARC_H
#include "../Archive/IArchive.h"
typedef IInArchive * (*CreateInArchiveP)();
typedef IOutArchive * (*CreateOutArchiveP)();
struct CArcInfo
{
const wchar_t *Name;
const wchar_t *Ext;
const wchar_t *AddExt;
Byte ClassId;
Byte Signature[16];
int SignatureSize;
bool KeepName;
CreateInArchiveP CreateInArchive;
CreateOutArchiveP CreateOutArchive;
};
void RegisterArc(const CArcInfo *arcInfo);
#define REGISTER_ARC_NAME(x) CRegister ## x
#define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) { \
REGISTER_ARC_NAME(x)() { g_ArcInfo.Signature[0]--; RegisterArc(&g_ArcInfo); }}; \
static REGISTER_ARC_NAME(x) g_RegisterArc;
#define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \
REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \
static REGISTER_ARC_NAME(x) g_RegisterArc;
#endif

View file

@ -0,0 +1,33 @@
// RegisterCodec.h
#ifndef __REGISTERCODEC_H
#define __REGISTERCODEC_H
#include "../Common/MethodId.h"
typedef void * (*CreateCodecP)();
struct CCodecInfo
{
CreateCodecP CreateDecoder;
CreateCodecP CreateEncoder;
CMethodId Id;
const wchar_t *Name;
UInt32 NumInStreams;
bool IsFilter;
};
void RegisterCodec(const CCodecInfo *codecInfo);
#define REGISTER_CODEC_NAME(x) CRegisterCodec ## x
#define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \
REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \
static REGISTER_CODEC_NAME(x) g_RegisterCodec;
#define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x
#define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \
REGISTER_CODECS_NAME(x)() { for (int i = 0; i < sizeof(g_CodecsInfo) / sizeof(g_CodecsInfo[0]); i++) \
RegisterCodec(&g_CodecsInfo[i]); }}; \
static REGISTER_CODECS_NAME(x) g_RegisterCodecs;
#endif

View file

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

View file

@ -0,0 +1,150 @@
// StreamBinder.cpp
#include "StdAfx.h"
#include "StreamBinder.h"
#include "../../Common/Defs.h"
#include "../../Common/MyCom.h"
using namespace NWindows;
using namespace NSynchronization;
class CSequentialInStreamForBinder:
public ISequentialInStream,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
private:
CStreamBinder *m_StreamBinder;
public:
~CSequentialInStreamForBinder() { m_StreamBinder->CloseRead(); }
void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; }
};
STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize)
{ return m_StreamBinder->Read(data, size, processedSize); }
class CSequentialOutStreamForBinder:
public ISequentialOutStream,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
private:
CStreamBinder *m_StreamBinder;
public:
~CSequentialOutStreamForBinder() { m_StreamBinder->CloseWrite(); }
void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; }
};
STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)
{ return m_StreamBinder->Write(data, size, processedSize); }
//////////////////////////
// CStreamBinder
// (_thereAreBytesToReadEvent && _bufferSize == 0) means that stream is finished.
HRes CStreamBinder::CreateEvents()
{
RINOK(_allBytesAreWritenEvent.Create(true));
RINOK(_thereAreBytesToReadEvent.Create());
return _readStreamIsClosedEvent.Create();
}
void CStreamBinder::ReInit()
{
_thereAreBytesToReadEvent.Reset();
_readStreamIsClosedEvent.Reset();
ProcessedSize = 0;
}
void CStreamBinder::CreateStreams(ISequentialInStream **inStream,
ISequentialOutStream **outStream)
{
CSequentialInStreamForBinder *inStreamSpec = new
CSequentialInStreamForBinder;
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
inStreamSpec->SetBinder(this);
*inStream = inStreamLoc.Detach();
CSequentialOutStreamForBinder *outStreamSpec = new
CSequentialOutStreamForBinder;
CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec);
outStreamSpec->SetBinder(this);
*outStream = outStreamLoc.Detach();
_buffer = NULL;
_bufferSize= 0;
ProcessedSize = 0;
}
HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 sizeToRead = size;
if (size > 0)
{
RINOK(_thereAreBytesToReadEvent.Lock());
sizeToRead = MyMin(_bufferSize, size);
if (_bufferSize > 0)
{
MoveMemory(data, _buffer, sizeToRead);
_buffer = ((const Byte *)_buffer) + sizeToRead;
_bufferSize -= sizeToRead;
if (_bufferSize == 0)
{
_thereAreBytesToReadEvent.Reset();
_allBytesAreWritenEvent.Set();
}
}
}
if (processedSize != NULL)
*processedSize = sizeToRead;
ProcessedSize += sizeToRead;
return S_OK;
}
void CStreamBinder::CloseRead()
{
_readStreamIsClosedEvent.Set();
}
HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
if (size > 0)
{
_buffer = data;
_bufferSize = size;
_allBytesAreWritenEvent.Reset();
_thereAreBytesToReadEvent.Set();
HANDLE events[2];
events[0] = _allBytesAreWritenEvent;
events[1] = _readStreamIsClosedEvent;
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
if (waitResult != WAIT_OBJECT_0 + 0)
{
// ReadingWasClosed = true;
return S_FALSE;
}
// if(!_allBytesAreWritenEvent.Lock())
// return E_FAIL;
}
if (processedSize != NULL)
*processedSize = size;
return S_OK;
}
void CStreamBinder::CloseWrite()
{
// _bufferSize must be = 0
_thereAreBytesToReadEvent.Set();
}

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