mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-07 11:14:58 -06:00
4.43 beta
This commit is contained in:
committed by
Kornel Lesiński
parent
0ec42ff829
commit
804edc5756
@@ -140,7 +140,7 @@ CDecoder::CDecoder(bool multiThread)
|
||||
multiThread = true;
|
||||
#endif
|
||||
_multiThread = multiThread;
|
||||
_bindInfoExPrevIsDefinded = false;
|
||||
_bindInfoExPrevIsDefined = false;
|
||||
#ifndef EXCLUDE_COM
|
||||
LoadMethodMap();
|
||||
#endif
|
||||
@@ -176,7 +176,8 @@ HRESULT CDecoder::Decode(IInStream *inStream,
|
||||
CLimitedSequentialInStream *streamSpec = new
|
||||
CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> inStream = streamSpec;
|
||||
streamSpec->Init(lockedStreamImp, packSizes[j]);
|
||||
streamSpec->SetStream(lockedStreamImp);
|
||||
streamSpec->Init(packSizes[j]);
|
||||
inStreams.Add(inStream);
|
||||
}
|
||||
|
||||
@@ -185,7 +186,7 @@ HRESULT CDecoder::Decode(IInStream *inStream,
|
||||
CBindInfoEx bindInfo;
|
||||
ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
|
||||
bool createNewCoders;
|
||||
if (!_bindInfoExPrevIsDefinded)
|
||||
if (!_bindInfoExPrevIsDefined)
|
||||
createNewCoders = true;
|
||||
else
|
||||
createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
|
||||
@@ -319,7 +320,7 @@ HRESULT CDecoder::Decode(IInStream *inStream,
|
||||
}
|
||||
}
|
||||
_bindInfoExPrev = bindInfo;
|
||||
_bindInfoExPrevIsDefinded = true;
|
||||
_bindInfoExPrevIsDefined = true;
|
||||
}
|
||||
int i;
|
||||
_mixerCoderCommon->ReInit();
|
||||
@@ -336,7 +337,7 @@ HRESULT CDecoder::Decode(IInStream *inStream,
|
||||
|
||||
{
|
||||
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
|
||||
HRESULT result = decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
|
||||
decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
|
||||
if (setDecoderProperties)
|
||||
{
|
||||
const CByteBuffer &properties = altCoderInfo.Properties;
|
||||
@@ -365,7 +366,7 @@ HRESULT CDecoder::Decode(IInStream *inStream,
|
||||
#ifndef _NO_CRYPTO
|
||||
{
|
||||
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
|
||||
HRESULT result = decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
|
||||
decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
|
||||
if (cryptoSetPassword)
|
||||
{
|
||||
if (getTextPassword == 0)
|
||||
|
||||
@@ -36,7 +36,7 @@ class CDecoder
|
||||
CCoderLibraries _libraries;
|
||||
#endif
|
||||
|
||||
bool _bindInfoExPrevIsDefinded;
|
||||
bool _bindInfoExPrevIsDefined;
|
||||
CBindInfoEx _bindInfoExPrev;
|
||||
|
||||
bool _multiThread;
|
||||
|
||||
@@ -19,6 +19,7 @@ static NArchive::N7z::CMethodID k_Copy = { { 0x0 }, 1 };
|
||||
#endif
|
||||
|
||||
static NArchive::N7z::CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
|
||||
static NArchive::N7z::CMethodID k_LZMA2 = { { 0x3, 0x1, 0x2 }, 3 };
|
||||
|
||||
#ifdef COMPRESS_LZMA
|
||||
#include "../../Compress/LZMA/LZMAEncoder.h"
|
||||
@@ -207,9 +208,9 @@ HRESULT CEncoder::CreateMixerCoder(const UInt64 *inSizeForReduce)
|
||||
|
||||
bool tryReduce = false;
|
||||
UInt32 reducedDictionarySize = 1 << 10;
|
||||
if (inSizeForReduce != 0 && methodFull.MethodID == k_LZMA)
|
||||
if (inSizeForReduce != 0 && (methodFull.MethodID == k_LZMA || methodFull.MethodID == k_LZMA2))
|
||||
{
|
||||
while (true)
|
||||
for (;;)
|
||||
{
|
||||
const UInt32 step = (reducedDictionarySize >> 1);
|
||||
if (reducedDictionarySize >= *inSizeForReduce)
|
||||
@@ -383,7 +384,8 @@ HRESULT CEncoder::Encode(ISequentialInStream *inStream,
|
||||
CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec;
|
||||
|
||||
inStreamSizeCountSpec->Init(inStream);
|
||||
outStreamSizeCountSpec->Init(outStream);
|
||||
outStreamSizeCountSpec->SetStream(outStream);
|
||||
outStreamSizeCountSpec->Init();
|
||||
|
||||
CRecordVector<ISequentialInStream *> inStreamPointers;
|
||||
CRecordVector<ISequentialOutStream *> outStreamPointers;
|
||||
@@ -528,7 +530,7 @@ CEncoder::CEncoder(const CCompressionMethodMode &options):
|
||||
|
||||
// Make main stream first in list
|
||||
int inIndex = _bindInfo.InStreams[0];
|
||||
while (true)
|
||||
for (;;)
|
||||
{
|
||||
UInt32 coderIndex, coderStreamIndex;
|
||||
_bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex);
|
||||
|
||||
@@ -38,7 +38,8 @@ HRESULT CFolderInStream::OpenStream()
|
||||
if (result != S_OK && result != S_FALSE)
|
||||
return result;
|
||||
_fileIndex++;
|
||||
_inStreamWithHashSpec->Init(stream);
|
||||
_inStreamWithHashSpec->SetStream(stream);
|
||||
_inStreamWithHashSpec->Init();
|
||||
if (!stream)
|
||||
{
|
||||
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
|
||||
@@ -48,7 +48,8 @@ HRESULT CFolderOutStream::OpenFile()
|
||||
UInt32 index = _startIndex + _currentIndex;
|
||||
RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));
|
||||
|
||||
_outStreamWithHashSpec->Init(realOutStream);
|
||||
_outStreamWithHashSpec->SetStream(realOutStream);
|
||||
_outStreamWithHashSpec->Init();
|
||||
if (askMode == NArchive::NExtract::NAskMode::kExtract &&
|
||||
(!realOutStream))
|
||||
{
|
||||
|
||||
@@ -40,7 +40,6 @@ CHandler::CHandler()
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
*numItems =
|
||||
#ifdef _7Z_VOL
|
||||
_refs.Size();
|
||||
@@ -48,10 +47,9 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
*numItems = _database.Files.Size();
|
||||
#endif
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value)
|
||||
{
|
||||
value->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
@@ -59,13 +57,13 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
|
||||
#ifdef _SFX
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties)
|
||||
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,
|
||||
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
@@ -79,8 +77,8 @@ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */,
|
||||
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
@@ -93,26 +91,6 @@ static void MySetFileTime(bool timeDefined, FILETIME unixTime,
|
||||
propVariant = unixTime;
|
||||
}
|
||||
|
||||
/*
|
||||
inline static wchar_t GetHex(Byte value)
|
||||
{
|
||||
return (value < 10) ? ('0' + value) : ('A' + (value - 10));
|
||||
}
|
||||
|
||||
static UString ConvertBytesToHexString(const Byte *data, UInt32 size)
|
||||
{
|
||||
UString result;
|
||||
for (UInt32 i = 0; i < size; i++)
|
||||
{
|
||||
Byte b = data[i];
|
||||
result += GetHex(b >> 4);
|
||||
result += GetHex(b & 0xF);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _SFX
|
||||
|
||||
static UString ConvertUInt32ToString(UInt32 value)
|
||||
@@ -151,28 +129,48 @@ static CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
|
||||
static CMethodID k_BCJ = { { 0x3, 0x3, 0x1, 0x3 }, 4 };
|
||||
static CMethodID k_BCJ2 = { { 0x3, 0x3, 0x1, 0x1B }, 4 };
|
||||
static CMethodID k_PPMD = { { 0x3, 0x4, 0x1 }, 3 };
|
||||
static CMethodID k_Deflate = { { 0x4, 0x1, 0x8 }, 3 };
|
||||
static CMethodID k_Deflate = { { 0x4, 0x1, 0x8 }, 3 };
|
||||
static CMethodID k_Deflate64 = { { 0x4, 0x1, 0x9 }, 3 };
|
||||
static CMethodID k_BZip2 = { { 0x4, 0x2, 0x2 }, 3 };
|
||||
|
||||
static inline char GetHex(Byte value)
|
||||
static wchar_t GetHex(Byte value)
|
||||
{
|
||||
return (value < 10) ? ('0' + value) : ('A' + (value - 10));
|
||||
return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10)));
|
||||
}
|
||||
static inline UString GetHex2(Byte value)
|
||||
{
|
||||
UString result;
|
||||
result += GetHex(value >> 4);
|
||||
result += GetHex(value & 0xF);
|
||||
result += GetHex((Byte)(value >> 4));
|
||||
result += GetHex((Byte)(value & 0xF));
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static CMethodID k_AES = { { 0x6, 0xF1, 0x7, 0x1}, 4 };
|
||||
|
||||
static inline UInt32 GetUInt32FromMemLE(const Byte *p)
|
||||
{
|
||||
return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24);
|
||||
}
|
||||
|
||||
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--)
|
||||
{
|
||||
const CCoderInfo &coderInfo = folderInfo.Coders[i];
|
||||
for (int j = 0; j < coderInfo.AltCoders.Size(); j++)
|
||||
if (coderInfo.AltCoders[j].MethodID == k_AES)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
@@ -260,6 +258,11 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
if (item.IsFileCRCDefined)
|
||||
propVariant = item.FileCRC;
|
||||
break;
|
||||
case kpidEncrypted:
|
||||
{
|
||||
propVariant = IsEncrypted(index2);
|
||||
break;
|
||||
}
|
||||
#ifndef _SFX
|
||||
case kpidMethod:
|
||||
{
|
||||
@@ -299,8 +302,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
methodName = L"PPMD";
|
||||
else if (altCoderInfo.MethodID == k_Deflate)
|
||||
methodName = L"Deflate";
|
||||
else if (altCoderInfo.MethodID == k_Deflate64)
|
||||
methodName = L"Deflate64";
|
||||
else if (altCoderInfo.MethodID == k_BZip2)
|
||||
methodName = L"BZip2";
|
||||
else if (altCoderInfo.MethodID == k_AES)
|
||||
methodName = L"7zAES";
|
||||
else
|
||||
methodIsKnown = false;
|
||||
|
||||
@@ -338,6 +345,32 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
methodsString += GetStringForSizeValue(dicSize);
|
||||
}
|
||||
}
|
||||
else if (altCoderInfo.MethodID == k_AES)
|
||||
{
|
||||
if (altCoderInfo.Properties.GetCapacity() >= 1)
|
||||
{
|
||||
methodsString += L":";
|
||||
const Byte *data = (const Byte *)altCoderInfo.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 (altCoderInfo.Properties.GetCapacity() >= 2)
|
||||
{
|
||||
Byte secondByte = *data++;
|
||||
saltSize += (secondByte >> 4);
|
||||
ivSize += (secondByte & 0x0F);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (altCoderInfo.Properties.GetCapacity() > 0)
|
||||
@@ -345,7 +378,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
methodsString += L":[";
|
||||
for (size_t bi = 0; bi < altCoderInfo.Properties.GetCapacity(); bi++)
|
||||
{
|
||||
if (bi > 2 && bi + 1 < altCoderInfo.Properties.GetCapacity())
|
||||
if (bi > 5 && bi + 1 < altCoderInfo.Properties.GetCapacity())
|
||||
{
|
||||
methodsString += L"..";
|
||||
break;
|
||||
@@ -517,7 +550,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
{
|
||||
openArchiveCallbackTemp.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);
|
||||
}
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
CMyComPtr<IInStream> inStream;
|
||||
if (!_volumes.IsEmpty())
|
||||
@@ -724,8 +757,10 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
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++)
|
||||
{
|
||||
@@ -740,7 +775,9 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
|
||||
{
|
||||
if(name.Left(2).CompareNoCase(L"MT") == 0)
|
||||
{
|
||||
#ifdef COMPRESS_MT
|
||||
RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -85,6 +85,9 @@ class CHandler:
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
#if !defined(_7Z_VOL) && !defined(__7Z_SET_PROPERTIES) && defined(EXTRACT_ONLY)
|
||||
MY_UNKNOWN_IMP
|
||||
#else
|
||||
MY_QUERYINTERFACE_BEGIN
|
||||
#ifdef _7Z_VOL
|
||||
MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream)
|
||||
@@ -97,6 +100,8 @@ public:
|
||||
#endif
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
#endif
|
||||
|
||||
|
||||
STDMETHOD(Open)(IInStream *stream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
@@ -167,6 +172,11 @@ private:
|
||||
bool _compressHeadersFull;
|
||||
bool _encryptHeaders;
|
||||
|
||||
bool WriteModified;
|
||||
bool WriteCreated;
|
||||
bool WriteAccessed;
|
||||
|
||||
|
||||
bool _autoFilter;
|
||||
UInt32 _level;
|
||||
|
||||
@@ -176,8 +186,7 @@ private:
|
||||
HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value);
|
||||
HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString);
|
||||
|
||||
HRESULT SetPassword(CCompressionMethodMode &methodMode,
|
||||
IArchiveUpdateCallback *updateCallback);
|
||||
HRESULT SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback);
|
||||
|
||||
HRESULT SetCompressionMethod(CCompressionMethodMode &method,
|
||||
CObjectVector<COneMethodInfo> &methodsInfo
|
||||
@@ -191,7 +200,8 @@ private:
|
||||
CCompressionMethodMode &headerMethod);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
bool IsEncrypted(UInt32 index2) const;
|
||||
#ifndef _SFX
|
||||
|
||||
CRecordVector<UInt64> _fileInfoPopIDs;
|
||||
@@ -217,6 +227,11 @@ private:
|
||||
_compressHeaders = true;
|
||||
_compressHeadersFull = true;
|
||||
_encryptHeaders = false;
|
||||
|
||||
WriteModified = true;
|
||||
WriteCreated = false;
|
||||
WriteAccessed = false;
|
||||
|
||||
#ifdef COMPRESS_MT
|
||||
_numThreads = NWindows::NSystem::GetNumberOfProcessors();
|
||||
#endif
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace N7z {
|
||||
|
||||
#ifdef COMPRESS_LZMA
|
||||
static CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
|
||||
static CMethodID k_LZMA2 = { { 0x3, 0x1, 0x2 }, 3 };
|
||||
#endif
|
||||
|
||||
#ifdef COMPRESS_PPMD
|
||||
@@ -64,6 +65,7 @@ static CMethodID k_BZip2 = { { 0x4, 0x2, 0x2 }, 3 };
|
||||
|
||||
const wchar_t *kCopyMethod = L"Copy";
|
||||
const wchar_t *kLZMAMethodName = L"LZMA";
|
||||
const wchar_t *kLZMA2MethodName = L"LZMA2";
|
||||
const wchar_t *kBZip2MethodName = L"BZip2";
|
||||
const wchar_t *kPpmdMethodName = L"PPMd";
|
||||
const wchar_t *kDeflateMethodName = L"Deflate";
|
||||
@@ -121,9 +123,16 @@ static bool IsCopyMethod(const UString &methodName)
|
||||
{ return (methodName.CompareNoCase(kCopyMethod) == 0); }
|
||||
|
||||
static bool IsLZMAMethod(const UString &methodName)
|
||||
{ return (methodName.CompareNoCase(kLZMAMethodName) == 0); }
|
||||
{
|
||||
return
|
||||
(methodName.CompareNoCase(kLZMAMethodName) == 0) ||
|
||||
(methodName.CompareNoCase(kLZMA2MethodName) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
static bool IsLZMethod(const UString &methodName)
|
||||
{ return IsLZMAMethod(methodName); }
|
||||
*/
|
||||
|
||||
static bool IsBZip2Method(const UString &methodName)
|
||||
{ return (methodName.CompareNoCase(kBZip2MethodName) == 0); }
|
||||
@@ -157,7 +166,8 @@ HRESULT CHandler::SetPassword(CCompressionMethodMode &methodMode,
|
||||
Int32 passwordIsDefined;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword2(
|
||||
&passwordIsDefined, &password));
|
||||
if (methodMode.PasswordIsDefined = IntToBool(passwordIsDefined))
|
||||
methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
|
||||
if (methodMode.PasswordIsDefined)
|
||||
methodMode.Password = password;
|
||||
}
|
||||
else
|
||||
@@ -532,6 +542,21 @@ HRESULT CHandler::SetCompressionMethod(
|
||||
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)
|
||||
{
|
||||
@@ -583,8 +608,13 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
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.LastWriteTimeIsDefined = fileItem.IsLastWriteTimeDefined;
|
||||
updateItem.IsLastWriteTimeDefined = fileItem.IsLastWriteTimeDefined;
|
||||
updateItem.LastAccessTime = fileItem.LastAccessTime;
|
||||
updateItem.IsLastAccessTimeDefined = fileItem.IsLastAccessTimeDefined;
|
||||
}
|
||||
|
||||
if (updateItem.NewProperties)
|
||||
@@ -604,32 +634,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
updateItem.AttributesAreDefined = true;
|
||||
}
|
||||
}
|
||||
{
|
||||
NCOM::CPropVariant propVariant;
|
||||
RINOK(updateCallback->GetProperty(i, kpidCreationTime, &propVariant));
|
||||
if (propVariant.vt == VT_EMPTY)
|
||||
updateItem.CreationTimeIsDefined = false;
|
||||
else if (propVariant.vt != VT_FILETIME)
|
||||
return E_INVALIDARG;
|
||||
else
|
||||
{
|
||||
updateItem.CreationTime = propVariant.filetime;
|
||||
updateItem.CreationTimeIsDefined = true;
|
||||
}
|
||||
}
|
||||
{
|
||||
NCOM::CPropVariant propVariant;
|
||||
RINOK(updateCallback->GetProperty(i, kpidLastWriteTime, &propVariant));
|
||||
if (propVariant.vt == VT_EMPTY)
|
||||
updateItem.LastWriteTimeIsDefined = false;
|
||||
else if (propVariant.vt != VT_FILETIME)
|
||||
return E_INVALIDARG;
|
||||
else
|
||||
{
|
||||
updateItem.LastWriteTime = propVariant.filetime;
|
||||
updateItem.LastWriteTimeIsDefined = 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));
|
||||
@@ -671,8 +680,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
if (updateItem.IsAnti)
|
||||
{
|
||||
updateItem.AttributesAreDefined = false;
|
||||
updateItem.CreationTimeIsDefined = false;
|
||||
updateItem.LastWriteTimeIsDefined = false;
|
||||
|
||||
updateItem.IsCreationTimeDefined = false;
|
||||
updateItem.IsLastWriteTimeDefined = false;
|
||||
updateItem.IsLastAccessTimeDefined = false;
|
||||
|
||||
updateItem.Size = 0;
|
||||
}
|
||||
|
||||
@@ -728,8 +740,13 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
&headerMethod : 0;
|
||||
options.UseFilters = _level != 0 && _autoFilter;
|
||||
options.MaxFilter = _level >= 8;
|
||||
options.UseAdditionalHeaderStreams = useAdditionalHeaderStreams;
|
||||
options.CompressMainHeader = compressMainHeader;
|
||||
|
||||
options.HeaderOptions.UseAdditionalHeaderStreams = useAdditionalHeaderStreams;
|
||||
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;
|
||||
@@ -1048,6 +1065,21 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
|
||||
RINOK(SetBoolProperty(_encryptHeaders, value));
|
||||
continue;
|
||||
}
|
||||
else if (name.CompareNoCase(L"TM") == 0)
|
||||
{
|
||||
RINOK(SetBoolProperty(WriteModified, value));
|
||||
continue;
|
||||
}
|
||||
else if (name.CompareNoCase(L"TC") == 0)
|
||||
{
|
||||
RINOK(SetBoolProperty(WriteCreated, value));
|
||||
continue;
|
||||
}
|
||||
else if (name.CompareNoCase(L"TA") == 0)
|
||||
{
|
||||
RINOK(SetBoolProperty(WriteAccessed, value));
|
||||
continue;
|
||||
}
|
||||
else if (name.CompareNoCase(L"V") == 0)
|
||||
{
|
||||
RINOK(SetBoolProperty(_volumeMode, value));
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
#include "../../Common/StreamUtils.h"
|
||||
#include "../../../Common/CRC.h"
|
||||
|
||||
// define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader
|
||||
// #define FORMAT_7Z_RECOVERY
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
@@ -214,16 +217,16 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
|
||||
UInt32 numPrevBytes = kSignatureSize - 1;
|
||||
memmove(buffer, signature + 1, numPrevBytes);
|
||||
UInt64 curTestPos = _arhiveBeginStreamPosition + 1;
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
if (searchHeaderSizeLimit != NULL)
|
||||
if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit)
|
||||
return S_FALSE;
|
||||
break;
|
||||
UInt32 numReadBytes = kBufferSize - numPrevBytes;
|
||||
RINOK(ReadDirect(stream, buffer + numPrevBytes, numReadBytes, &processedSize));
|
||||
UInt32 numBytesInBuffer = numPrevBytes + processedSize;
|
||||
if (numBytesInBuffer < kSignatureSize)
|
||||
return S_FALSE;
|
||||
break;
|
||||
UInt32 numTests = numBytesInBuffer - kSignatureSize + 1;
|
||||
for(UInt32 pos = 0; pos < numTests; pos++, curTestPos++)
|
||||
{
|
||||
@@ -237,6 +240,7 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
|
||||
numPrevBytes = numBytesInBuffer - numTests;
|
||||
memmove(buffer, buffer + numTests, numPrevBytes);
|
||||
}
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
// Out: _position must point to end of signature
|
||||
@@ -335,9 +339,9 @@ HRESULT CInArchive::SkeepData()
|
||||
return SkeepData(size);
|
||||
}
|
||||
|
||||
HRESULT CInArchive::ReadArchiveProperties(CInArchiveInfo &archiveInfo)
|
||||
HRESULT CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)
|
||||
{
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
UInt64 type;
|
||||
RINOK(ReadID(type));
|
||||
@@ -363,13 +367,13 @@ HRESULT CInArchive::GetNextFolderItem(CFolder &folder)
|
||||
folder.Coders.Add(CCoderInfo());
|
||||
CCoderInfo &coder = folder.Coders.Back();
|
||||
|
||||
while (true)
|
||||
for (;;)
|
||||
{
|
||||
coder.AltCoders.Add(CAltCoderInfo());
|
||||
CAltCoderInfo &altCoder = coder.AltCoders.Back();
|
||||
Byte mainByte;
|
||||
Byte mainByte = 0;
|
||||
RINOK(ReadByte(mainByte));
|
||||
altCoder.MethodID.IDSize = mainByte & 0xF;
|
||||
altCoder.MethodID.IDSize = (Byte)(mainByte & 0xF);
|
||||
RINOK(ReadBytes(altCoder.MethodID.ID, altCoder.MethodID.IDSize));
|
||||
if ((mainByte & 0x10) != 0)
|
||||
{
|
||||
@@ -432,7 +436,7 @@ HRESULT CInArchive::GetNextFolderItem(CFolder &folder)
|
||||
|
||||
HRESULT CInArchive::WaitAttribute(UInt64 attribute)
|
||||
{
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
UInt64 type;
|
||||
RINOK(ReadID(type));
|
||||
@@ -453,7 +457,7 @@ HRESULT CInArchive::ReadHashDigests(int numItems,
|
||||
digests.Reserve(numItems);
|
||||
for(int i = 0; i < numItems; i++)
|
||||
{
|
||||
UInt32 crc;
|
||||
UInt32 crc = 0;
|
||||
if (digestsDefined[i])
|
||||
RINOK(ReadUInt32(crc));
|
||||
digests.Add(crc);
|
||||
@@ -482,7 +486,7 @@ HRESULT CInArchive::ReadPackInfo(
|
||||
}
|
||||
|
||||
UInt64 type;
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
RINOK(ReadID(type));
|
||||
if (type == NID::kEnd)
|
||||
@@ -545,7 +549,7 @@ HRESULT CInArchive::ReadUnPackInfo(
|
||||
}
|
||||
}
|
||||
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
UInt64 type;
|
||||
RINOK(ReadID(type));
|
||||
@@ -578,7 +582,7 @@ HRESULT CInArchive::ReadSubStreamsInfo(
|
||||
numUnPackStreamsInFolders.Clear();
|
||||
numUnPackStreamsInFolders.Reserve(folders.Size());
|
||||
UInt64 type;
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
RINOK(ReadID(type));
|
||||
if (type == NID::kNumUnPackStream)
|
||||
@@ -638,7 +642,7 @@ HRESULT CInArchive::ReadSubStreamsInfo(
|
||||
numDigestsTotal += numSubstreams;
|
||||
}
|
||||
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
if (type == NID::kCRC)
|
||||
{
|
||||
@@ -697,7 +701,7 @@ HRESULT CInArchive::ReadStreamsInfo(
|
||||
CRecordVector<bool> &digestsDefined,
|
||||
CRecordVector<UInt32> &digests)
|
||||
{
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
UInt64 type;
|
||||
RINOK(ReadID(type));
|
||||
@@ -732,7 +736,7 @@ HRESULT CInArchive::ReadFileNames(CObjectVector<CFileItem> &files)
|
||||
{
|
||||
UString &name = files[i].Name;
|
||||
name.Empty();
|
||||
while (true)
|
||||
for (;;)
|
||||
{
|
||||
wchar_t c;
|
||||
RINOK(ReadWideCharLE(c));
|
||||
@@ -748,7 +752,7 @@ HRESULT CInArchive::ReadBoolVector(int numItems, CBoolVector &v)
|
||||
{
|
||||
v.Clear();
|
||||
v.Reserve(numItems);
|
||||
Byte b;
|
||||
Byte b = 0;
|
||||
Byte mask = 0;
|
||||
for(int i = 0; i < numItems; i++)
|
||||
{
|
||||
@@ -789,6 +793,8 @@ HRESULT CInArchive::ReadTime(const CObjectVector<CByteBuffer> &dataVector,
|
||||
{
|
||||
CFileItem &file = files[i];
|
||||
CArchiveFileTime fileTime;
|
||||
fileTime.dwLowDateTime = 0;
|
||||
fileTime.dwHighDateTime = 0;
|
||||
bool defined = boolVector[i];
|
||||
if (defined)
|
||||
{
|
||||
@@ -989,7 +995,7 @@ HRESULT CInArchive::ReadHeader(CArchiveDatabaseEx &database
|
||||
// int sizePrev = -1;
|
||||
// int posPrev = 0;
|
||||
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
/*
|
||||
if (sizePrev >= 0)
|
||||
@@ -1025,7 +1031,8 @@ HRESULT CInArchive::ReadHeader(CArchiveDatabaseEx &database
|
||||
for(i = 0; i < numFiles; i++)
|
||||
{
|
||||
CFileItem &file = database.Files[i];
|
||||
if (file.AreAttributesDefined = boolVector[i])
|
||||
file.AreAttributesDefined = boolVector[i];
|
||||
if (file.AreAttributesDefined)
|
||||
{
|
||||
RINOK(ReadUInt32(file.Attributes));
|
||||
}
|
||||
@@ -1041,7 +1048,8 @@ HRESULT CInArchive::ReadHeader(CArchiveDatabaseEx &database
|
||||
for(i = 0; i < numFiles; i++)
|
||||
{
|
||||
CFileItem &file = database.Files[i];
|
||||
if (file.IsStartPosDefined = boolVector[i])
|
||||
file.IsStartPosDefined = boolVector[i];
|
||||
if (file.IsStartPosDefined)
|
||||
{
|
||||
RINOK(ReadUInt64(file.StartPos));
|
||||
}
|
||||
@@ -1162,7 +1170,7 @@ void CArchiveDatabaseEx::FillFolderStartFileIndex()
|
||||
{
|
||||
// v3.13 incorrectly worked with empty folders
|
||||
// v4.07: Loop for skipping empty folders
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
if (folderIndex >= Folders.Size())
|
||||
throw CInArchiveException(CInArchiveException::kIncorrectHeader);
|
||||
@@ -1208,19 +1216,52 @@ HRESULT CInArchive::ReadDatabase(CArchiveDatabaseEx &database
|
||||
#endif
|
||||
|
||||
UInt32 crcFromArchive;
|
||||
RINOK(SafeReadDirectUInt32(crcFromArchive));
|
||||
|
||||
UInt64 nextHeaderOffset;
|
||||
UInt64 nextHeaderSize;
|
||||
UInt32 nextHeaderCRC;
|
||||
CCRC crc;
|
||||
RINOK(SafeReadDirectUInt32(crcFromArchive));
|
||||
RINOK(SafeReadDirectUInt64(nextHeaderOffset));
|
||||
crc.UpdateUInt64(nextHeaderOffset);
|
||||
RINOK(SafeReadDirectUInt64(nextHeaderSize));
|
||||
crc.UpdateUInt64(nextHeaderSize);
|
||||
RINOK(SafeReadDirectUInt32(nextHeaderCRC));
|
||||
|
||||
#ifdef FORMAT_7Z_RECOVERY
|
||||
if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0)
|
||||
{
|
||||
UInt64 cur, cur2;
|
||||
RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur));
|
||||
const int kCheckSize = 500;
|
||||
Byte buf[kCheckSize];
|
||||
RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2));
|
||||
int checkSize = kCheckSize;
|
||||
if (cur2 - cur < kCheckSize)
|
||||
checkSize = (int)(cur2 - cur);
|
||||
RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2));
|
||||
|
||||
UInt32 realProcessedSize;
|
||||
RINOK(ReadDirect(buf, (UInt32)kCheckSize, &realProcessedSize));
|
||||
|
||||
int i;
|
||||
for (i = (int)realProcessedSize - 2; i >= 0; i--)
|
||||
if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04)
|
||||
break;
|
||||
if (i < 0)
|
||||
return S_FALSE;
|
||||
nextHeaderSize = realProcessedSize - i;
|
||||
nextHeaderOffset = cur2 - cur + i;
|
||||
nextHeaderCRC = CCRC::CalculateDigest(buf + i, (size_t)nextHeaderSize);
|
||||
RINOK(_stream->Seek(cur, STREAM_SEEK_SET, &_position));
|
||||
}
|
||||
#endif
|
||||
|
||||
crc.UpdateUInt64(nextHeaderOffset);
|
||||
crc.UpdateUInt64(nextHeaderSize);
|
||||
crc.UpdateUInt32(nextHeaderCRC);
|
||||
|
||||
#ifdef FORMAT_7Z_RECOVERY
|
||||
crcFromArchive = crc.GetDigest();
|
||||
#endif
|
||||
|
||||
#ifdef _7Z_VOL
|
||||
UInt64 archiveStartOffset; // data offset from end if that struct
|
||||
UInt64 additionalStartBlockSize; // start signature & start header size
|
||||
@@ -1259,7 +1300,7 @@ HRESULT CInArchive::ReadDatabase(CArchiveDatabaseEx &database
|
||||
|
||||
CObjectVector<CByteBuffer> dataVector;
|
||||
|
||||
while (true)
|
||||
for (;;)
|
||||
{
|
||||
UInt64 type;
|
||||
RINOK(ReadID(type));
|
||||
|
||||
@@ -201,13 +201,13 @@ private:
|
||||
|
||||
HRESULT ReadWideCharLE(wchar_t &c)
|
||||
{
|
||||
Byte b1;
|
||||
Byte b1 = 0;
|
||||
if (!_inByteBack->ReadByte(b1))
|
||||
return E_FAIL;
|
||||
Byte b2;
|
||||
Byte b2 = 0;
|
||||
if (!_inByteBack->ReadByte(b2))
|
||||
return E_FAIL;
|
||||
c = (wchar_t(b2) << 8) + b1;
|
||||
c = (wchar_t)(((wchar_t)(b2) << 8) + b1);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,17 +9,17 @@ namespace N7z {
|
||||
|
||||
static wchar_t GetHex(Byte value)
|
||||
{
|
||||
return (value < 10) ? ('0' + value) : ('A' + (value - 10));
|
||||
return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
|
||||
}
|
||||
|
||||
static bool HexCharToInt(wchar_t value, Byte &result)
|
||||
{
|
||||
if (value >= '0' && value <= '9')
|
||||
result = value - '0';
|
||||
result = (Byte)(value - '0');
|
||||
else if (value >= 'a' && value <= 'f')
|
||||
result = 10 + value - 'a';
|
||||
result = (Byte)(10 + value - 'a');
|
||||
else if (value >= 'A' && value <= 'F')
|
||||
result = 10 + value - 'A';
|
||||
result = (Byte)(10 + value - 'A');
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
@@ -32,7 +32,7 @@ static bool TwoHexCharsToInt(wchar_t valueHigh, wchar_t valueLow, Byte &result)
|
||||
return false;
|
||||
if (!HexCharToInt(valueLow, resultLow))
|
||||
return false;
|
||||
result = (resultHigh << 4) + resultLow;
|
||||
result = (Byte)((resultHigh << 4) + resultLow);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -42,8 +42,8 @@ UString CMethodID::ConvertToString() const
|
||||
for (int i = 0; i < IDSize; i++)
|
||||
{
|
||||
Byte b = ID[i];
|
||||
result += GetHex(b >> 4);
|
||||
result += GetHex(b & 0xF);
|
||||
result += GetHex((Byte)(b >> 4));
|
||||
result += GetHex((Byte)(b & 0xF));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -53,7 +53,7 @@ bool CMethodID::ConvertFromString(const UString &srcString)
|
||||
int length = srcString.Length();
|
||||
if ((length & 1) != 0 || (length >> 1) > kMethodIDSize)
|
||||
return false;
|
||||
IDSize = length / 2;
|
||||
IDSize = (Byte)(length / 2);
|
||||
UInt32 i;
|
||||
for(i = 0; i < IDSize; i++)
|
||||
if (!TwoHexCharsToInt(srcString[i * 2], srcString[i * 2 + 1], ID[i]))
|
||||
|
||||
@@ -64,7 +64,7 @@ static void Load(const CSysString &folderPrefix)
|
||||
continue;
|
||||
if (propVariant.vt != VT_BSTR)
|
||||
continue;
|
||||
info.MethodID.IDSize = SysStringByteLen(propVariant.bstrVal);
|
||||
info.MethodID.IDSize = (Byte)SysStringByteLen(propVariant.bstrVal);
|
||||
memmove(info.MethodID.ID, propVariant.bstrVal, info.MethodID.IDSize);
|
||||
propVariant.Clear();
|
||||
|
||||
|
||||
@@ -274,7 +274,7 @@ HRESULT COutArchive::WriteFolder(const CFolder &folder)
|
||||
size_t propertiesSize = altCoder.Properties.GetCapacity();
|
||||
|
||||
Byte b;
|
||||
b = altCoder.MethodID.IDSize & 0xF;
|
||||
b = (Byte)(altCoder.MethodID.IDSize & 0xF);
|
||||
bool isComplex = !coder.IsSimpleCoder();
|
||||
b |= (isComplex ? 0x10 : 0);
|
||||
b |= ((propertiesSize != 0) ? 0x20 : 0 );
|
||||
@@ -548,6 +548,8 @@ HRESULT COutArchive::WriteTime(
|
||||
{
|
||||
const CFileItem &item = files[i];
|
||||
CArchiveFileTime timeValue;
|
||||
timeValue.dwLowDateTime = 0;
|
||||
timeValue.dwHighDateTime = 0;
|
||||
switch(type)
|
||||
{
|
||||
case NID::kCreationTime:
|
||||
@@ -608,7 +610,9 @@ static void WriteUInt64ToBuffer(Byte *data, UInt64 value)
|
||||
|
||||
|
||||
HRESULT COutArchive::WriteHeader(const CArchiveDatabase &database,
|
||||
const CCompressionMethodMode *options, UInt64 &headerOffset)
|
||||
const CCompressionMethodMode *options,
|
||||
const CHeaderOptions &headerOptions,
|
||||
UInt64 &headerOffset)
|
||||
{
|
||||
CObjectVector<CFolder> folders;
|
||||
|
||||
@@ -628,7 +632,7 @@ HRESULT COutArchive::WriteHeader(const CArchiveDatabase &database,
|
||||
//////////////////////////
|
||||
// Folders
|
||||
|
||||
CNum externalFoldersStreamIndex;
|
||||
CNum externalFoldersStreamIndex = 0;
|
||||
bool externalFolders = (compressHeaders && database.Folders.Size() > 8);
|
||||
if (externalFolders)
|
||||
{
|
||||
@@ -675,7 +679,7 @@ HRESULT COutArchive::WriteHeader(const CArchiveDatabase &database,
|
||||
}
|
||||
|
||||
CByteBuffer namesData;
|
||||
CNum externalNamesStreamIndex;
|
||||
CNum externalNamesStreamIndex = 0;
|
||||
bool externalNames = (compressHeaders && database.Files.Size() > 8);
|
||||
if (numDefinedNames > 0)
|
||||
{
|
||||
@@ -715,7 +719,7 @@ HRESULT COutArchive::WriteHeader(const CArchiveDatabase &database,
|
||||
}
|
||||
|
||||
CByteBuffer attributesData;
|
||||
CNum externalAttributesStreamIndex;
|
||||
CNum externalAttributesStreamIndex = 0;
|
||||
bool externalAttributes = (compressHeaders && numDefinedAttributes > 8);
|
||||
if (numDefinedAttributes > 0)
|
||||
{
|
||||
@@ -751,7 +755,7 @@ HRESULT COutArchive::WriteHeader(const CArchiveDatabase &database,
|
||||
}
|
||||
|
||||
CByteBuffer startsData;
|
||||
CNum externalStartStreamIndex;
|
||||
CNum externalStartStreamIndex = 0;
|
||||
bool externalStarts = (compressHeaders && numDefinedStarts > 8);
|
||||
if (numDefinedStarts > 0)
|
||||
{
|
||||
@@ -775,7 +779,7 @@ HRESULT COutArchive::WriteHeader(const CArchiveDatabase &database,
|
||||
|
||||
/////////////////////////////////
|
||||
// Write Last Write Time
|
||||
CNum externalLastWriteTimeStreamIndex;
|
||||
CNum externalLastWriteTimeStreamIndex = 0;
|
||||
bool externalLastWriteTime = false;
|
||||
// /*
|
||||
CNum numDefinedLastWriteTimes = 0;
|
||||
@@ -949,11 +953,20 @@ HRESULT COutArchive::WriteHeader(const CArchiveDatabase &database,
|
||||
|
||||
}
|
||||
|
||||
RINOK(WriteTime(database.Files, NID::kCreationTime, false, 0));
|
||||
RINOK(WriteTime(database.Files, NID::kLastAccessTime, false, 0));
|
||||
RINOK(WriteTime(database.Files, NID::kLastWriteTime,
|
||||
if (headerOptions.WriteCreated)
|
||||
{
|
||||
RINOK(WriteTime(database.Files, NID::kCreationTime, false, 0));
|
||||
}
|
||||
if (headerOptions.WriteModified)
|
||||
{
|
||||
RINOK(WriteTime(database.Files, NID::kLastWriteTime,
|
||||
// false, 0));
|
||||
externalLastWriteTime, externalLastWriteTimeStreamIndex));
|
||||
}
|
||||
if (headerOptions.WriteAccessed)
|
||||
{
|
||||
RINOK(WriteTime(database.Files, NID::kLastAccessTime, false, 0));
|
||||
}
|
||||
|
||||
if (numDefinedAttributes > 0)
|
||||
{
|
||||
@@ -1031,7 +1044,7 @@ HRESULT COutArchive::WriteHeader(const CArchiveDatabase &database,
|
||||
|
||||
HRESULT COutArchive::WriteDatabase(const CArchiveDatabase &database,
|
||||
const CCompressionMethodMode *options,
|
||||
bool useAdditionalStreams, bool compressMainHeader)
|
||||
const CHeaderOptions &headerOptions)
|
||||
{
|
||||
UInt64 headerOffset;
|
||||
UInt32 headerCRC;
|
||||
@@ -1051,23 +1064,23 @@ HRESULT COutArchive::WriteDatabase(const CArchiveDatabase &database,
|
||||
if (options->IsEmpty())
|
||||
options = 0;
|
||||
const CCompressionMethodMode *additionalStreamsOptions = options;
|
||||
if (!useAdditionalStreams)
|
||||
if (!headerOptions.UseAdditionalHeaderStreams)
|
||||
additionalStreamsOptions = 0;
|
||||
/*
|
||||
if (database.Files.Size() < 2)
|
||||
compressMainHeader = false;
|
||||
*/
|
||||
if (options != 0)
|
||||
if (options->PasswordIsDefined || compressMainHeader)
|
||||
if (options->PasswordIsDefined || headerOptions.CompressMainHeader)
|
||||
_dynamicMode = true;
|
||||
RINOK(WriteHeader(database, additionalStreamsOptions, headerOffset));
|
||||
RINOK(WriteHeader(database, additionalStreamsOptions, headerOptions, headerOffset));
|
||||
|
||||
if (_dynamicMode)
|
||||
{
|
||||
CCompressionMethodMode encryptOptions;
|
||||
encryptOptions.PasswordIsDefined = options->PasswordIsDefined;
|
||||
encryptOptions.Password = options->Password;
|
||||
CEncoder encoder(compressMainHeader ? *options : encryptOptions);
|
||||
CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions);
|
||||
CRecordVector<UInt64> packSizes;
|
||||
CObjectVector<CFolder> folders;
|
||||
RINOK(EncodeStream(encoder, _dynamicBuffer,
|
||||
|
||||
@@ -60,6 +60,21 @@ public:
|
||||
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
|
||||
{
|
||||
@@ -127,6 +142,7 @@ class COutArchive
|
||||
CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders);
|
||||
HRESULT WriteHeader(const CArchiveDatabase &database,
|
||||
const CCompressionMethodMode *options,
|
||||
const CHeaderOptions &headerOptions,
|
||||
UInt64 &headerOffset);
|
||||
|
||||
bool _mainMode;
|
||||
@@ -162,8 +178,7 @@ public:
|
||||
HRESULT SkeepPrefixArchiveHeader();
|
||||
HRESULT WriteDatabase(const CArchiveDatabase &database,
|
||||
const CCompressionMethodMode *options,
|
||||
bool useAdditionalHeaderStreams,
|
||||
bool compressMainHeader);
|
||||
const CHeaderOptions &headerOptions);
|
||||
|
||||
#ifdef _7Z_VOL
|
||||
static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false);
|
||||
|
||||
@@ -43,7 +43,8 @@ static HRESULT WriteRange(
|
||||
CLimitedSequentialInStream *streamSpec = new
|
||||
CLimitedSequentialInStream;
|
||||
CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec);
|
||||
streamSpec->Init(inStream, size);
|
||||
streamSpec->SetStream(inStream);
|
||||
streamSpec->Init(size);
|
||||
|
||||
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;
|
||||
@@ -195,49 +196,125 @@ static int CompareEmptyItems(const int *p1, const int *p2, void *param)
|
||||
const CUpdateItem &u1 = updateItems[*p1];
|
||||
const CUpdateItem &u2 = updateItems[*p2];
|
||||
if (u1.IsDirectory != u2.IsDirectory)
|
||||
{
|
||||
if (u1.IsDirectory)
|
||||
return u1.IsAnti ? 1: -1;
|
||||
return u2.IsAnti ? -1: 1;
|
||||
}
|
||||
return (u1.IsDirectory) ? 1 : -1;
|
||||
if (u1.IsDirectory)
|
||||
{
|
||||
if (u1.IsAnti != u2.IsAnti)
|
||||
return (u1.IsAnti ? 1 : -1);
|
||||
int n = MyStringCompareNoCase(u1.Name, u2.Name);
|
||||
return (u1.IsAnti ? (-n) : n);
|
||||
return -n;
|
||||
}
|
||||
if (u1.IsAnti != u2.IsAnti)
|
||||
return (u1.IsAnti ? 1 : -1);
|
||||
return MyStringCompareNoCase(u1.Name, u2.Name);
|
||||
}
|
||||
|
||||
static const char *g_Exts =
|
||||
" lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab ha lha lzh rar zoo"
|
||||
" zip jar ear war msi"
|
||||
" 3gp avi mov mpeg mpg mpe wmv"
|
||||
" aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav"
|
||||
" swf "
|
||||
" chm hxi hxs"
|
||||
" gif jpeg jpg jp2 png tiff bmp ico psd psp"
|
||||
" awg ps eps cgm dxf svg vrml wmf emf ai md"
|
||||
" cad dwg pps key sxi"
|
||||
" max 3ds"
|
||||
" iso bin nrg mdf img pdi tar cpio xpi"
|
||||
" vfd vhd vud vmc vsv"
|
||||
" vmdk dsk nvram vmem vmsd vmsn vmss vmtm"
|
||||
" inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def"
|
||||
" f77 f f90 f95"
|
||||
" asm sql manifest dep "
|
||||
" mak clw csproj vcproj sln dsp dsw "
|
||||
" class "
|
||||
" bat cmd"
|
||||
" xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml"
|
||||
" awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs"
|
||||
" text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf"
|
||||
" sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf"
|
||||
" abw afp cwk lwp wpd wps wpt wrf wri"
|
||||
" abf afm bdf fon mgf otf pcf pfa snf ttf"
|
||||
" dbf mdb nsf ntf wdb db fdb gdb"
|
||||
" exe dll ocx vbx sfx sys tlb awx com obj lib out o so "
|
||||
" pdb pch idb ncb opt";
|
||||
|
||||
int GetExtIndex(const char *ext)
|
||||
{
|
||||
int extIndex = 1;
|
||||
const char *p = g_Exts;
|
||||
for (;;)
|
||||
{
|
||||
char c = *p++;
|
||||
if (c == 0)
|
||||
return extIndex;
|
||||
if (c == ' ')
|
||||
continue;
|
||||
int pos = 0;
|
||||
for (;;)
|
||||
{
|
||||
char c2 = ext[pos++];
|
||||
if (c2 == 0 && (c == 0 || c == ' '))
|
||||
return extIndex;
|
||||
if (c != c2)
|
||||
break;
|
||||
c = *p++;
|
||||
}
|
||||
extIndex++;
|
||||
for (;;)
|
||||
{
|
||||
if (c == 0)
|
||||
return extIndex;
|
||||
if (c == ' ')
|
||||
break;
|
||||
c = *p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CRefItem
|
||||
{
|
||||
UInt32 Index;
|
||||
const CUpdateItem *UpdateItem;
|
||||
UInt32 ExtensionPos;
|
||||
UInt32 NamePos;
|
||||
bool SortByType;
|
||||
int ExtensionIndex;
|
||||
CRefItem(UInt32 index, const CUpdateItem &updateItem, bool sortByType):
|
||||
SortByType(sortByType),
|
||||
Index(index),
|
||||
UpdateItem(&updateItem),
|
||||
ExtensionPos(0),
|
||||
NamePos(0)
|
||||
NamePos(0),
|
||||
ExtensionIndex(0)
|
||||
{
|
||||
if (sortByType)
|
||||
{
|
||||
int slashPos = GetReverseSlashPos(updateItem.Name);
|
||||
if (slashPos >= 0)
|
||||
NamePos = slashPos + 1;
|
||||
else
|
||||
NamePos = 0;
|
||||
NamePos = ((slashPos >= 0) ? (slashPos + 1) : 0);
|
||||
int dotPos = updateItem.Name.ReverseFind(L'.');
|
||||
if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))
|
||||
ExtensionPos = updateItem.Name.Length();
|
||||
else
|
||||
{
|
||||
ExtensionPos = dotPos + 1;
|
||||
UString us = updateItem.Name.Mid(ExtensionPos);
|
||||
if (!us.IsEmpty())
|
||||
{
|
||||
us.MakeLower();
|
||||
int i;
|
||||
AString s;
|
||||
for (i = 0; i < us.Length(); i++)
|
||||
{
|
||||
wchar_t c = us[i];
|
||||
if (c >= 0x80)
|
||||
break;
|
||||
s += (char)c;
|
||||
}
|
||||
if (i == us.Length())
|
||||
ExtensionIndex = GetExtIndex(s);
|
||||
else
|
||||
ExtensionIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -250,23 +327,21 @@ static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *para
|
||||
const CUpdateItem &u2 = *a2.UpdateItem;
|
||||
int n;
|
||||
if (u1.IsDirectory != u2.IsDirectory)
|
||||
{
|
||||
if (u1.IsDirectory)
|
||||
return u1.IsAnti ? 1: -1;
|
||||
return u2.IsAnti ? -1: 1;
|
||||
}
|
||||
return (u1.IsDirectory) ? 1 : -1;
|
||||
if (u1.IsDirectory)
|
||||
{
|
||||
if (u1.IsAnti != u2.IsAnti)
|
||||
return (u1.IsAnti ? 1 : -1);
|
||||
n = MyStringCompareNoCase(u1.Name, u2.Name);
|
||||
return (u1.IsAnti ? (-n) : n);
|
||||
return -n;
|
||||
}
|
||||
if (a1.SortByType)
|
||||
bool sortByType = *(bool *)param;
|
||||
if (sortByType)
|
||||
{
|
||||
RINOZ(MyCompare(a1.ExtensionIndex, a2.ExtensionIndex))
|
||||
RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos));
|
||||
RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos));
|
||||
if (u1.LastWriteTimeIsDefined && u2.LastWriteTimeIsDefined)
|
||||
if (u1.IsLastWriteTimeDefined && u2.IsLastWriteTimeDefined)
|
||||
RINOZ(CompareFileTime(&u1.LastWriteTime, &u2.LastWriteTime));
|
||||
RINOZ(MyCompare(u1.Size, u2.Size))
|
||||
}
|
||||
@@ -448,11 +523,12 @@ static void FromUpdateItemToFileItem(const CUpdateItem &updateItem,
|
||||
if (updateItem.AttributesAreDefined)
|
||||
file.SetAttributes(updateItem.Attributes);
|
||||
|
||||
// if (updateItem.CreationTimeIsDefined)
|
||||
// file.SetCreationTime(updateItem.ItemInfo.CreationTime);
|
||||
|
||||
if (updateItem.LastWriteTimeIsDefined)
|
||||
if (updateItem.IsCreationTimeDefined)
|
||||
file.SetCreationTime(updateItem.CreationTime);
|
||||
if (updateItem.IsLastWriteTimeDefined)
|
||||
file.SetLastWriteTime(updateItem.LastWriteTime);
|
||||
if (updateItem.IsLastAccessTimeDefined)
|
||||
file.SetLastAccessTime(updateItem.LastAccessTime);
|
||||
|
||||
file.UnPackSize = updateItem.Size;
|
||||
file.IsDirectory = updateItem.IsDirectory;
|
||||
@@ -485,7 +561,8 @@ static HRESULT Update2(
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> limitedStream(streamSpec);
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
streamSpec->Init(inStream, startBlockSize);
|
||||
streamSpec->SetStream(inStream);
|
||||
streamSpec->Init(startBlockSize);
|
||||
RINOK(CopyBlock(limitedStream, seqOutStream, NULL));
|
||||
}
|
||||
|
||||
@@ -534,36 +611,6 @@ static HRESULT Update2(
|
||||
|
||||
CArchiveDatabase newDatabase;
|
||||
|
||||
/////////////////////////////////////////
|
||||
// Write Empty Files & Folders
|
||||
|
||||
CRecordVector<int> emptyRefs;
|
||||
for(i = 0; i < updateItems.Size(); i++)
|
||||
{
|
||||
const CUpdateItem &updateItem = updateItems[i];
|
||||
if (updateItem.NewData)
|
||||
{
|
||||
if (updateItem.HasStream())
|
||||
continue;
|
||||
}
|
||||
else
|
||||
if (updateItem.IndexInArchive != -1)
|
||||
if (database->Files[updateItem.IndexInArchive].HasStream)
|
||||
continue;
|
||||
emptyRefs.Add(i);
|
||||
}
|
||||
emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);
|
||||
for(i = 0; i < emptyRefs.Size(); i++)
|
||||
{
|
||||
const CUpdateItem &updateItem = updateItems[emptyRefs[i]];
|
||||
CFileItem file;
|
||||
if (updateItem.NewProperties)
|
||||
FromUpdateItemToFileItem(updateItem, file);
|
||||
else
|
||||
file = database->Files[updateItem.IndexInArchive];
|
||||
newDatabase.Files.Add(file);
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
|
||||
COutArchive archive;
|
||||
@@ -664,10 +711,10 @@ static HRESULT Update2(
|
||||
continue;
|
||||
CRecordVector<CRefItem> refItems;
|
||||
refItems.Reserve(numFiles);
|
||||
bool sortByType = (numSolidFiles > 1);
|
||||
for (i = 0; i < numFiles; i++)
|
||||
refItems.Add(CRefItem(group.Indices[i],
|
||||
updateItems[group.Indices[i]], numSolidFiles > 1));
|
||||
refItems.Sort(CompareUpdateItems, 0);
|
||||
refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType));
|
||||
refItems.Sort(CompareUpdateItems, (void *)&sortByType);
|
||||
|
||||
CRecordVector<UInt32> indices;
|
||||
indices.Reserve(numFiles);
|
||||
@@ -780,15 +827,49 @@ static HRESULT Update2(
|
||||
i += numSubFiles;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
/////////////////////////////////////////
|
||||
// Write Empty Files & Folders
|
||||
|
||||
CRecordVector<int> emptyRefs;
|
||||
for(i = 0; i < updateItems.Size(); i++)
|
||||
{
|
||||
const CUpdateItem &updateItem = updateItems[i];
|
||||
if (updateItem.NewData)
|
||||
{
|
||||
if (updateItem.HasStream())
|
||||
continue;
|
||||
}
|
||||
else
|
||||
if (updateItem.IndexInArchive != -1)
|
||||
if (database->Files[updateItem.IndexInArchive].HasStream)
|
||||
continue;
|
||||
emptyRefs.Add(i);
|
||||
}
|
||||
emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);
|
||||
for(i = 0; i < emptyRefs.Size(); i++)
|
||||
{
|
||||
const CUpdateItem &updateItem = updateItems[emptyRefs[i]];
|
||||
CFileItem file;
|
||||
if (updateItem.NewProperties)
|
||||
FromUpdateItemToFileItem(updateItem, file);
|
||||
else
|
||||
file = database->Files[updateItem.IndexInArchive];
|
||||
newDatabase.Files.Add(file);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (newDatabase.Files.Size() != updateItems.Size())
|
||||
return E_FAIL;
|
||||
*/
|
||||
|
||||
return archive.WriteDatabase(newDatabase, options.HeaderMethod,
|
||||
options.UseAdditionalHeaderStreams, options.CompressMainHeader);
|
||||
return archive.WriteDatabase(newDatabase, options.HeaderMethod, options.HeaderOptions);
|
||||
}
|
||||
|
||||
#ifdef _7Z_VOL
|
||||
|
||||
static HRESULT WriteVolumeHeader(COutArchive &archive, CFileItem &file, const CUpdateOptions &options)
|
||||
{
|
||||
CAltCoderInfo altCoder;
|
||||
@@ -831,7 +912,6 @@ static HRESULT WriteVolumeHeader(COutArchive &archive, CFileItem &file, const CU
|
||||
false);
|
||||
}
|
||||
|
||||
#ifdef _7Z_VOL
|
||||
HRESULT UpdateVolume(
|
||||
IInStream *inStream,
|
||||
const CArchiveDatabaseEx *database,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#define __7Z_UPDATE_H
|
||||
|
||||
#include "7zIn.h"
|
||||
#include "7zOut.h"
|
||||
#include "7zCompressionMode.h"
|
||||
|
||||
#include "../IArchive.h"
|
||||
@@ -21,6 +22,7 @@ struct CUpdateItem
|
||||
UInt32 Attributes;
|
||||
FILETIME CreationTime;
|
||||
FILETIME LastWriteTime;
|
||||
FILETIME LastAccessTime;
|
||||
|
||||
UInt64 Size;
|
||||
UString Name;
|
||||
@@ -28,13 +30,20 @@ struct CUpdateItem
|
||||
bool IsAnti;
|
||||
bool IsDirectory;
|
||||
|
||||
bool CreationTimeIsDefined;
|
||||
bool LastWriteTimeIsDefined;
|
||||
bool IsCreationTimeDefined;
|
||||
bool IsLastWriteTimeDefined;
|
||||
bool IsLastAccessTimeDefined;
|
||||
bool AttributesAreDefined;
|
||||
|
||||
const bool HasStream() const
|
||||
{ return !IsDirectory && !IsAnti && Size != 0; }
|
||||
CUpdateItem(): IsAnti(false) {}
|
||||
CUpdateItem():
|
||||
IsAnti(false),
|
||||
AttributesAreDefined(false),
|
||||
IsCreationTimeDefined(false),
|
||||
IsLastWriteTimeDefined(false),
|
||||
IsLastAccessTimeDefined(false)
|
||||
{}
|
||||
void SetDirectoryStatusFromAttributes()
|
||||
{ IsDirectory = ((Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0); };
|
||||
|
||||
@@ -48,8 +57,9 @@ struct CUpdateOptions
|
||||
const CCompressionMethodMode *HeaderMethod;
|
||||
bool UseFilters;
|
||||
bool MaxFilter;
|
||||
bool UseAdditionalHeaderStreams;
|
||||
bool CompressMainHeader;
|
||||
|
||||
CHeaderOptions HeaderOptions;
|
||||
|
||||
UInt64 NumSolidFiles;
|
||||
UInt64 NumSolidBytes;
|
||||
bool SolidExtension;
|
||||
|
||||
@@ -38,6 +38,8 @@ SZ_RESULT SzExtract(
|
||||
Byte *inBuffer = 0;
|
||||
size_t processedSize;
|
||||
#endif
|
||||
if (unPackSize != (size_t)unPackSize)
|
||||
return SZE_OUTOFMEMORY;
|
||||
*blockIndex = folderIndex;
|
||||
allocMain->Free(*outBuffer);
|
||||
*outBuffer = 0;
|
||||
|
||||
@@ -44,18 +44,8 @@ CFileSize GetFilePackSize(int fileIndex) const
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
SZ_RESULT MySzInAlloc(void **p, size_t size, void * (*allocFunc)(size_t size))
|
||||
{
|
||||
if (size == 0)
|
||||
*p = 0;
|
||||
else
|
||||
{
|
||||
*p = allocFunc(size);
|
||||
RINOM(*p);
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
#define MY_ALLOC(T, p, size, allocFunc) { if ((size) == 0) p = 0; else \
|
||||
if ((p = (T *)allocFunc((size) * sizeof(T))) == 0) return SZE_OUTOFMEMORY; }
|
||||
|
||||
SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size))
|
||||
{
|
||||
@@ -64,14 +54,14 @@ SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size))
|
||||
UInt32 i;
|
||||
UInt32 folderIndex = 0;
|
||||
UInt32 indexInFolder = 0;
|
||||
RINOK(MySzInAlloc((void **)&db->FolderStartPackStreamIndex, db->Database.NumFolders * sizeof(UInt32), allocFunc));
|
||||
MY_ALLOC(UInt32, db->FolderStartPackStreamIndex, db->Database.NumFolders, allocFunc);
|
||||
for(i = 0; i < db->Database.NumFolders; i++)
|
||||
{
|
||||
db->FolderStartPackStreamIndex[i] = startPos;
|
||||
startPos += db->Database.Folders[i].NumPackStreams;
|
||||
}
|
||||
|
||||
RINOK(MySzInAlloc((void **)&db->PackStreamStartPositions, db->Database.NumPackStreams * sizeof(CFileSize), allocFunc));
|
||||
MY_ALLOC(CFileSize, db->PackStreamStartPositions, db->Database.NumPackStreams, allocFunc);
|
||||
|
||||
for(i = 0; i < db->Database.NumPackStreams; i++)
|
||||
{
|
||||
@@ -79,8 +69,8 @@ SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size))
|
||||
startPosSize += db->Database.PackSizes[i];
|
||||
}
|
||||
|
||||
RINOK(MySzInAlloc((void **)&db->FolderStartFileIndex, db->Database.NumFolders * sizeof(UInt32), allocFunc));
|
||||
RINOK(MySzInAlloc((void **)&db->FileIndexToFolderIndexMap, db->Database.NumFiles * sizeof(UInt32), allocFunc));
|
||||
MY_ALLOC(UInt32, db->FolderStartFileIndex, db->Database.NumFolders, allocFunc);
|
||||
MY_ALLOC(UInt32, db->FileIndexToFolderIndexMap, db->Database.NumFiles, allocFunc);
|
||||
|
||||
for (i = 0; i < db->Database.NumFiles; i++)
|
||||
{
|
||||
@@ -97,7 +87,7 @@ SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size))
|
||||
v3.13 incorrectly worked with empty folders
|
||||
v4.07: Loop for skipping empty folders
|
||||
*/
|
||||
while(1)
|
||||
for (;;)
|
||||
{
|
||||
if (folderIndex >= db->Database.NumFolders)
|
||||
return SZE_ARCHIVE_ERROR;
|
||||
@@ -237,7 +227,7 @@ SZ_RESULT SafeReadDirectUInt64(ISzInStream *inStream, UInt64 *value)
|
||||
{
|
||||
Byte b;
|
||||
RINOK(SafeReadDirectByte(inStream, &b));
|
||||
*value |= ((UInt32)b << (8 * i));
|
||||
*value |= ((UInt64)b << (8 * i));
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
@@ -355,7 +345,7 @@ SZ_RESULT SzSkeepData(CSzData *sd)
|
||||
|
||||
SZ_RESULT SzReadArchiveProperties(CSzData *sd)
|
||||
{
|
||||
while(1)
|
||||
for (;;)
|
||||
{
|
||||
UInt64 type;
|
||||
RINOK(SzReadID(sd, &type));
|
||||
@@ -368,7 +358,7 @@ SZ_RESULT SzReadArchiveProperties(CSzData *sd)
|
||||
|
||||
SZ_RESULT SzWaitAttribute(CSzData *sd, UInt64 attribute)
|
||||
{
|
||||
while(1)
|
||||
for (;;)
|
||||
{
|
||||
UInt64 type;
|
||||
RINOK(SzReadID(sd, &type));
|
||||
@@ -385,8 +375,8 @@ SZ_RESULT SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, void * (*allo
|
||||
Byte b = 0;
|
||||
Byte mask = 0;
|
||||
size_t i;
|
||||
RINOK(MySzInAlloc((void **)v, numItems * sizeof(Byte), allocFunc));
|
||||
for(i = 0; i < numItems; i++)
|
||||
MY_ALLOC(Byte, *v, numItems, allocFunc);
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
if (mask == 0)
|
||||
{
|
||||
@@ -406,7 +396,7 @@ SZ_RESULT SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, void * (*all
|
||||
RINOK(SzReadByte(sd, &allAreDefined));
|
||||
if (allAreDefined == 0)
|
||||
return SzReadBoolVector(sd, numItems, v, allocFunc);
|
||||
RINOK(MySzInAlloc((void **)v, numItems * sizeof(Byte), allocFunc));
|
||||
MY_ALLOC(Byte, *v, numItems, allocFunc);
|
||||
for(i = 0; i < numItems; i++)
|
||||
(*v)[i] = 1;
|
||||
return SZ_OK;
|
||||
@@ -421,7 +411,7 @@ SZ_RESULT SzReadHashDigests(
|
||||
{
|
||||
size_t i;
|
||||
RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, allocFunc));
|
||||
RINOK(MySzInAlloc((void **)digests, numItems * sizeof(UInt32), allocFunc));
|
||||
MY_ALLOC(UInt32, *digests, numItems, allocFunc);
|
||||
for(i = 0; i < numItems; i++)
|
||||
if ((*digestsDefined)[i])
|
||||
{
|
||||
@@ -445,14 +435,14 @@ SZ_RESULT SzReadPackInfo(
|
||||
|
||||
RINOK(SzWaitAttribute(sd, k7zIdSize));
|
||||
|
||||
RINOK(MySzInAlloc((void **)packSizes, (size_t)*numPackStreams * sizeof(CFileSize), allocFunc));
|
||||
MY_ALLOC(CFileSize, *packSizes, (size_t)*numPackStreams, allocFunc);
|
||||
|
||||
for(i = 0; i < *numPackStreams; i++)
|
||||
{
|
||||
RINOK(SzReadSize(sd, (*packSizes) + i));
|
||||
}
|
||||
|
||||
while(1)
|
||||
for (;;)
|
||||
{
|
||||
UInt64 type;
|
||||
RINOK(SzReadID(sd, &type));
|
||||
@@ -467,8 +457,8 @@ SZ_RESULT SzReadPackInfo(
|
||||
}
|
||||
if (*packCRCsDefined == 0)
|
||||
{
|
||||
RINOK(MySzInAlloc((void **)packCRCsDefined, (size_t)*numPackStreams * sizeof(Byte), allocFunc));
|
||||
RINOK(MySzInAlloc((void **)packCRCs, (size_t)*numPackStreams * sizeof(UInt32), allocFunc));
|
||||
MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, allocFunc);
|
||||
MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, allocFunc);
|
||||
for(i = 0; i < *numPackStreams; i++)
|
||||
{
|
||||
(*packCRCsDefined)[i] = 0;
|
||||
@@ -496,7 +486,7 @@ SZ_RESULT SzGetNextFolderItem(CSzData *sd, CFolder *folder, void * (*allocFunc)(
|
||||
RINOK(SzReadNumber32(sd, &numCoders));
|
||||
folder->NumCoders = numCoders;
|
||||
|
||||
RINOK(MySzInAlloc((void **)&folder->Coders, (size_t)numCoders * sizeof(CCoderInfo), allocFunc));
|
||||
MY_ALLOC(CCoderInfo, folder->Coders, (size_t)numCoders, allocFunc);
|
||||
|
||||
for (i = 0; i < numCoders; i++)
|
||||
SzCoderInfoInit(folder->Coders + i);
|
||||
@@ -553,7 +543,7 @@ SZ_RESULT SzGetNextFolderItem(CSzData *sd, CFolder *folder, void * (*allocFunc)(
|
||||
folder->NumBindPairs = numBindPairs;
|
||||
|
||||
|
||||
RINOK(MySzInAlloc((void **)&folder->BindPairs, (size_t)numBindPairs * sizeof(CBindPair), allocFunc));
|
||||
MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, allocFunc);
|
||||
|
||||
for (i = 0; i < numBindPairs; i++)
|
||||
{
|
||||
@@ -565,7 +555,7 @@ SZ_RESULT SzGetNextFolderItem(CSzData *sd, CFolder *folder, void * (*allocFunc)(
|
||||
numPackedStreams = numInStreams - (UInt32)numBindPairs;
|
||||
|
||||
folder->NumPackStreams = numPackedStreams;
|
||||
RINOK(MySzInAlloc((void **)&folder->PackStreams, (size_t)numPackedStreams * sizeof(UInt32), allocFunc));
|
||||
MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackedStreams, allocFunc);
|
||||
|
||||
if (numPackedStreams == 1)
|
||||
{
|
||||
@@ -599,8 +589,7 @@ SZ_RESULT SzReadUnPackInfo(
|
||||
{
|
||||
RINOK(SzReadSwitch(sd));
|
||||
|
||||
|
||||
RINOK(MySzInAlloc((void **)folders, (size_t)*numFolders * sizeof(CFolder), allocFunc));
|
||||
MY_ALLOC(CFolder, *folders, (size_t)*numFolders, allocFunc);
|
||||
|
||||
for(i = 0; i < *numFolders; i++)
|
||||
SzFolderInit((*folders) + i);
|
||||
@@ -619,7 +608,7 @@ SZ_RESULT SzReadUnPackInfo(
|
||||
CFolder *folder = (*folders) + i;
|
||||
UInt32 numOutStreams = SzFolderGetNumOutStreams(folder);
|
||||
|
||||
RINOK(MySzInAlloc((void **)&folder->UnPackSizes, (size_t)numOutStreams * sizeof(CFileSize), allocFunc));
|
||||
MY_ALLOC(CFileSize, folder->UnPackSizes, (size_t)numOutStreams, allocFunc);
|
||||
|
||||
for(j = 0; j < numOutStreams; j++)
|
||||
{
|
||||
@@ -627,7 +616,7 @@ SZ_RESULT SzReadUnPackInfo(
|
||||
}
|
||||
}
|
||||
|
||||
while(1)
|
||||
for (;;)
|
||||
{
|
||||
UInt64 type;
|
||||
RINOK(SzReadID(sd, &type));
|
||||
@@ -676,7 +665,7 @@ SZ_RESULT SzReadSubStreamsInfo(
|
||||
folders[i].NumUnPackStreams = 1;
|
||||
*numUnPackStreams = numFolders;
|
||||
|
||||
while(1)
|
||||
for (;;)
|
||||
{
|
||||
RINOK(SzReadID(sd, &type));
|
||||
if (type == k7zIdNumUnPackStream)
|
||||
@@ -756,7 +745,7 @@ SZ_RESULT SzReadSubStreamsInfo(
|
||||
|
||||
|
||||
si = 0;
|
||||
while(1)
|
||||
for (;;)
|
||||
{
|
||||
if (type == k7zIdCRC)
|
||||
{
|
||||
@@ -814,7 +803,7 @@ SZ_RESULT SzReadStreamsInfo(
|
||||
void * (*allocFunc)(size_t size),
|
||||
ISzAlloc *allocTemp)
|
||||
{
|
||||
while(1)
|
||||
for (;;)
|
||||
{
|
||||
UInt64 type;
|
||||
RINOK(SzReadID(sd, &type));
|
||||
@@ -887,7 +876,7 @@ SZ_RESULT SzReadFileNames(CSzData *sd, UInt32 numFiles, CFileItem *files,
|
||||
len += numAdds;
|
||||
}
|
||||
|
||||
RINOK(MySzInAlloc((void **)&file->Name, (size_t)len * sizeof(char), allocFunc));
|
||||
MY_ALLOC(char, file->Name, (size_t)len, allocFunc);
|
||||
|
||||
len = 0;
|
||||
while(2 <= sd->Size)
|
||||
@@ -973,13 +962,13 @@ SZ_RESULT SzReadHeader2(
|
||||
RINOK(SzReadNumber32(sd, &numFiles));
|
||||
db->Database.NumFiles = numFiles;
|
||||
|
||||
RINOK(MySzInAlloc((void **)&files, (size_t)numFiles * sizeof(CFileItem), allocMain->Alloc));
|
||||
MY_ALLOC(CFileItem, files, (size_t)numFiles, allocMain->Alloc);
|
||||
|
||||
db->Database.Files = files;
|
||||
for(i = 0; i < numFiles; i++)
|
||||
SzFileInit(files + i);
|
||||
|
||||
while(1)
|
||||
for (;;)
|
||||
{
|
||||
UInt64 type;
|
||||
UInt64 size;
|
||||
@@ -1122,7 +1111,7 @@ SZ_RESULT SzReadAndDecodePackedStreams2(
|
||||
for (i = 0; i < db->NumPackStreams; i++)
|
||||
packSize += db->PackSizes[i];
|
||||
|
||||
RINOK(MySzInAlloc((void **)inBuffer, (size_t)packSize, allocTemp->Alloc));
|
||||
MY_ALLOC(Byte, *inBuffer, (size_t)packSize, allocTemp->Alloc);
|
||||
|
||||
RINOK(SafeReadDirect(inStream, *inBuffer, (size_t)packSize));
|
||||
#endif
|
||||
@@ -1238,9 +1227,10 @@ SZ_RESULT SzArchiveOpen2(
|
||||
res = SafeReadDirect(inStream, buffer.Items, (size_t)nextHeaderSize);
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
res = SZE_ARCHIVE_ERROR;
|
||||
if (CrcVerifyDigest(nextHeaderCRC, buffer.Items, (UInt32)nextHeaderSize))
|
||||
{
|
||||
while (1)
|
||||
for (;;)
|
||||
{
|
||||
UInt64 type;
|
||||
sd.Data = buffer.Items;
|
||||
|
||||
@@ -1,21 +1,122 @@
|
||||
/*
|
||||
7zMain.c
|
||||
Test application for 7z Decoder
|
||||
LZMA SDK 4.26 Copyright (c) 1999-2005 Igor Pavlov (2005-08-02)
|
||||
LZMA SDK 4.43 Copyright (c) 1999-2006 Igor Pavlov (2006-06-04)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define USE_WINDOWS_FUNCTIONS
|
||||
#endif
|
||||
|
||||
#ifdef USE_WINDOWS_FUNCTIONS
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "7zCrc.h"
|
||||
#include "7zIn.h"
|
||||
#include "7zExtract.h"
|
||||
|
||||
|
||||
#ifdef USE_WINDOWS_FUNCTIONS
|
||||
typedef HANDLE MY_FILE_HANDLE;
|
||||
#else
|
||||
typedef FILE *MY_FILE_HANDLE;
|
||||
#endif
|
||||
|
||||
void ConvertNumberToString(CFileSize value, char *s)
|
||||
{
|
||||
char temp[32];
|
||||
int pos = 0;
|
||||
do
|
||||
{
|
||||
temp[pos++] = (char)('0' + (int)(value % 10));
|
||||
value /= 10;
|
||||
}
|
||||
while (value != 0);
|
||||
do
|
||||
*s++ = temp[--pos];
|
||||
while(pos > 0);
|
||||
*s = '\0';
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_WINDOWS_FUNCTIONS
|
||||
// ReadFile and WriteFile functions in Windows have BUG:
|
||||
// If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)
|
||||
// from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES
|
||||
// (Insufficient system resources exist to complete the requested service).
|
||||
#define kChunkSizeMax (1 << 24)
|
||||
#endif
|
||||
|
||||
size_t MyReadFile(MY_FILE_HANDLE file, void *data, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return 0;
|
||||
#ifdef USE_WINDOWS_FUNCTIONS
|
||||
{
|
||||
size_t processedSize = 0;
|
||||
do
|
||||
{
|
||||
DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size;
|
||||
DWORD processedLoc = 0;
|
||||
BOOL res = ReadFile(file, data, curSize, &processedLoc, NULL);
|
||||
data = (void *)((unsigned char *)data + processedLoc);
|
||||
size -= processedLoc;
|
||||
processedSize += processedLoc;
|
||||
if (!res || processedLoc == 0)
|
||||
break;
|
||||
}
|
||||
while (size > 0);
|
||||
return processedSize;
|
||||
}
|
||||
#else
|
||||
return fread(data, 1, size, file);
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t MyWriteFile(MY_FILE_HANDLE file, void *data, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return 0;
|
||||
#ifdef USE_WINDOWS_FUNCTIONS
|
||||
{
|
||||
size_t processedSize = 0;
|
||||
do
|
||||
{
|
||||
DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size;
|
||||
DWORD processedLoc = 0;
|
||||
BOOL res = WriteFile(file, data, curSize, &processedLoc, NULL);
|
||||
data = (void *)((unsigned char *)data + processedLoc);
|
||||
size -= processedLoc;
|
||||
processedSize += processedLoc;
|
||||
if (!res)
|
||||
break;
|
||||
}
|
||||
while (size > 0);
|
||||
return processedSize;
|
||||
}
|
||||
#else
|
||||
return fwrite(data, 1, size, file);
|
||||
#endif
|
||||
}
|
||||
|
||||
int MyCloseFile(MY_FILE_HANDLE file)
|
||||
{
|
||||
#ifdef USE_WINDOWS_FUNCTIONS
|
||||
return (CloseHandle(file) != FALSE) ? 0 : 1;
|
||||
#else
|
||||
return fclose(file);
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef struct _CFileInStream
|
||||
{
|
||||
ISzInStream InStream;
|
||||
FILE *File;
|
||||
MY_FILE_HANDLE File;
|
||||
} CFileInStream;
|
||||
|
||||
#ifdef _LZMA_IN_CB
|
||||
@@ -29,7 +130,7 @@ SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, siz
|
||||
size_t processedSizeLoc;
|
||||
if (maxRequiredSize > kBufferSize)
|
||||
maxRequiredSize = kBufferSize;
|
||||
processedSizeLoc = fread(g_Buffer, 1, maxRequiredSize, s->File);
|
||||
processedSizeLoc = MyReadFile(s->File, g_Buffer, maxRequiredSize);
|
||||
*buffer = g_Buffer;
|
||||
if (processedSize != 0)
|
||||
*processedSize = processedSizeLoc;
|
||||
@@ -41,7 +142,7 @@ SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, siz
|
||||
SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size, size_t *processedSize)
|
||||
{
|
||||
CFileInStream *s = (CFileInStream *)object;
|
||||
size_t processedSizeLoc = fread(buffer, 1, size, s->File);
|
||||
size_t processedSizeLoc = MyReadFile(s->File, buffer, size);
|
||||
if (processedSize != 0)
|
||||
*processedSize = processedSizeLoc;
|
||||
return SZ_OK;
|
||||
@@ -52,10 +153,24 @@ SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size, size_t *process
|
||||
SZ_RESULT SzFileSeekImp(void *object, CFileSize pos)
|
||||
{
|
||||
CFileInStream *s = (CFileInStream *)object;
|
||||
|
||||
#ifdef USE_WINDOWS_FUNCTIONS
|
||||
{
|
||||
LARGE_INTEGER value;
|
||||
value.LowPart = (DWORD)pos;
|
||||
value.HighPart = (LONG)(pos >> 32);
|
||||
value.LowPart = SetFilePointer(s->File, value.LowPart, &value.HighPart, FILE_BEGIN);
|
||||
if (value.LowPart == 0xFFFFFFFF)
|
||||
if(GetLastError() != NO_ERROR)
|
||||
return SZE_FAIL;
|
||||
return SZ_OK;
|
||||
}
|
||||
#else
|
||||
int res = fseek(s->File, (long)pos, SEEK_SET);
|
||||
if (res == 0)
|
||||
return SZ_OK;
|
||||
return SZE_FAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void PrintError(char *sz)
|
||||
@@ -71,7 +186,7 @@ int main(int numargs, char *args[])
|
||||
ISzAlloc allocImp;
|
||||
ISzAlloc allocTempImp;
|
||||
|
||||
printf("\n7z ANSI-C Decoder 4.30 Copyright (c) 1999-2005 Igor Pavlov 2005-11-20\n");
|
||||
printf("\n7z ANSI-C Decoder 4.44 Copyright (c) 1999-2006 Igor Pavlov 2006-08-27\n");
|
||||
if (numargs == 1)
|
||||
{
|
||||
printf(
|
||||
@@ -88,8 +203,15 @@ int main(int numargs, char *args[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
archiveStream.File =
|
||||
#ifdef USE_WINDOWS_FUNCTIONS
|
||||
CreateFile(args[2], GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (archiveStream.File == INVALID_HANDLE_VALUE)
|
||||
#else
|
||||
archiveStream.File = fopen(args[2], "rb");
|
||||
if (archiveStream.File == 0)
|
||||
#endif
|
||||
{
|
||||
PrintError("can not open input file");
|
||||
return 1;
|
||||
@@ -126,18 +248,22 @@ int main(int numargs, char *args[])
|
||||
for (i = 0; i < db.Database.NumFiles; i++)
|
||||
{
|
||||
CFileItem *f = db.Database.Files + i;
|
||||
printf("%10d %s\n", (int)f->Size, f->Name);
|
||||
char s[32];
|
||||
ConvertNumberToString(f->Size, s);
|
||||
printf("%10s %s\n", s, f->Name);
|
||||
}
|
||||
}
|
||||
else if (testCommand || extractCommand)
|
||||
{
|
||||
UInt32 i;
|
||||
|
||||
// if you need cache, use these 3 variables.
|
||||
// if you use external function, you can make these variable as static.
|
||||
UInt32 blockIndex = 0xFFFFFFFF; // it can have any value before first call (if outBuffer = 0)
|
||||
Byte *outBuffer = 0; // it must be 0 before first call for each new archive.
|
||||
size_t outBufferSize = 0; // it can have any value before first call (if outBuffer = 0)
|
||||
/*
|
||||
if you need cache, use these 3 variables.
|
||||
if you use external function, you can make these variable as static.
|
||||
*/
|
||||
UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
|
||||
Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
|
||||
size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
|
||||
|
||||
printf("\n");
|
||||
for (i = 0; i < db.Database.NumFiles; i++)
|
||||
@@ -165,7 +291,7 @@ int main(int numargs, char *args[])
|
||||
break;
|
||||
if (!testCommand)
|
||||
{
|
||||
FILE *outputHandle;
|
||||
MY_FILE_HANDLE outputHandle;
|
||||
UInt32 processedSize;
|
||||
char *fileName = f->Name;
|
||||
size_t nameLen = strlen(f->Name);
|
||||
@@ -176,21 +302,28 @@ int main(int numargs, char *args[])
|
||||
break;
|
||||
}
|
||||
|
||||
outputHandle = fopen(fileName, "wb+");
|
||||
outputHandle =
|
||||
#ifdef USE_WINDOWS_FUNCTIONS
|
||||
CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_READ,
|
||||
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (outputHandle == INVALID_HANDLE_VALUE)
|
||||
#else
|
||||
fopen(fileName, "wb+");
|
||||
if (outputHandle == 0)
|
||||
#endif
|
||||
{
|
||||
PrintError("can not open output file");
|
||||
res = SZE_FAIL;
|
||||
break;
|
||||
}
|
||||
processedSize = fwrite(outBuffer + offset, 1, outSizeProcessed, outputHandle);
|
||||
processedSize = MyWriteFile(outputHandle, outBuffer + offset, outSizeProcessed);
|
||||
if (processedSize != outSizeProcessed)
|
||||
{
|
||||
PrintError("can not write output file");
|
||||
res = SZE_FAIL;
|
||||
break;
|
||||
}
|
||||
if (fclose(outputHandle))
|
||||
if (MyCloseFile(outputHandle))
|
||||
{
|
||||
PrintError("can not close output file");
|
||||
res = SZE_FAIL;
|
||||
@@ -209,7 +342,7 @@ int main(int numargs, char *args[])
|
||||
}
|
||||
SzArDbExFree(&db, allocImp.Free);
|
||||
|
||||
fclose(archiveStream.File);
|
||||
MyCloseFile(archiveStream.File);
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
printf("\nEverything is Ok\n");
|
||||
|
||||
@@ -3,32 +3,38 @@
|
||||
#ifndef __COMMON_TYPES_H
|
||||
#define __COMMON_TYPES_H
|
||||
|
||||
#ifndef UInt32
|
||||
#ifndef _7ZIP_BYTE_DEFINED
|
||||
#define _7ZIP_BYTE_DEFINED
|
||||
typedef unsigned char Byte;
|
||||
#endif
|
||||
|
||||
#ifndef _7ZIP_UINT16_DEFINED
|
||||
#define _7ZIP_UINT16_DEFINED
|
||||
typedef unsigned short UInt16;
|
||||
#endif
|
||||
|
||||
#ifndef _7ZIP_UINT32_DEFINED
|
||||
#define _7ZIP_UINT32_DEFINED
|
||||
#ifdef _LZMA_UINT32_IS_ULONG
|
||||
#define UInt32 unsigned long
|
||||
typedef unsigned long UInt32;
|
||||
#else
|
||||
#define UInt32 unsigned int
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef Byte
|
||||
#define Byte unsigned char
|
||||
#endif
|
||||
|
||||
#ifndef UInt16
|
||||
#define UInt16 unsigned short
|
||||
typedef unsigned int UInt32;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* #define _SZ_NO_INT_64 */
|
||||
/* define it your compiler doesn't support long long int */
|
||||
|
||||
#ifndef _7ZIP_UINT64_DEFINED
|
||||
#define _7ZIP_UINT64_DEFINED
|
||||
#ifdef _SZ_NO_INT_64
|
||||
#define UInt64 unsigned long
|
||||
typedef unsigned long UInt64;
|
||||
#else
|
||||
#ifdef _MSC_VER
|
||||
#define UInt64 unsigned __int64
|
||||
typedef unsigned __int64 UInt64;
|
||||
#else
|
||||
#define UInt64 unsigned long long int
|
||||
typedef unsigned long long int UInt64;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -38,9 +44,9 @@
|
||||
|
||||
#ifndef CFileSize
|
||||
#ifdef _SZ_FILE_SIZE_64
|
||||
#define CFileSize UInt64
|
||||
typedef UInt64 CFileSize;
|
||||
#else
|
||||
#define CFileSize UInt32
|
||||
typedef UInt32 CFileSize;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ RSC=rc.exe
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W4 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /c
|
||||
# ADD CPP /nologo /W4 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /D "_SZ_FILE_SIZE_64" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x419 /d "NDEBUG"
|
||||
# ADD RSC /l 0x419 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
@@ -66,7 +66,7 @@ LINK32=link.exe
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /D "_SZ_FILE_SIZE_64" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x419 /d "_DEBUG"
|
||||
# ADD RSC /l 0x419 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
@@ -93,6 +93,10 @@ SOURCE=..\..\Compress\LZMA_C\LzmaDecode.c
|
||||
|
||||
SOURCE=..\..\Compress\LZMA_C\LzmaDecode.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\LZMA_C\LzmaTypes.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ STATPROPSTG kProperties[] =
|
||||
CHandler::CHandler()
|
||||
{}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value)
|
||||
{
|
||||
value->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
@@ -117,8 +117,8 @@ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */,
|
||||
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
@@ -225,7 +225,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
UInt64 numFiles = _items.Size();
|
||||
RINOK(callback->SetCompleted(&numFiles, NULL));
|
||||
}
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
CItemEx itemInfo;
|
||||
bool filled;
|
||||
@@ -328,7 +328,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
{
|
||||
COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
|
||||
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
|
||||
outStreamSpec->Init(realOutStream);
|
||||
outStreamSpec->SetStream(realOutStream);
|
||||
outStreamSpec->Init();
|
||||
realOutStream.Release();
|
||||
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
@@ -337,7 +338,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
UInt64 pos;
|
||||
_stream->Seek(itemInfo.DataPosition, STREAM_SEEK_SET, &pos);
|
||||
|
||||
streamSpec->Init(_stream, itemInfo.PackSize);
|
||||
streamSpec->SetStream(_stream);
|
||||
streamSpec->Init(itemInfo.PackSize);
|
||||
|
||||
|
||||
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||
|
||||
@@ -25,7 +25,7 @@ HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize)
|
||||
|
||||
static inline UInt16 GetUInt16FromMemLE(const Byte *p)
|
||||
{
|
||||
return p[0] | (((UInt32)p[1]) << 8);
|
||||
return (UInt16)(p[0] | (((UInt16)p[1]) << 8));
|
||||
}
|
||||
|
||||
static inline UInt32 GetUInt32FromMemLE(const Byte *p)
|
||||
@@ -79,7 +79,7 @@ bool CInArchive::FindAndReadMarker(const UInt64 *searchHeaderSizeLimit)
|
||||
UInt32 numBytesPrev = processedSize - 1;
|
||||
memmove(buffer, buffer + 1, numBytesPrev);
|
||||
UInt64 curTestPos = _streamStartPosition + 1;
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
if (searchHeaderSizeLimit != NULL)
|
||||
if (curTestPos - _streamStartPosition > *searchHeaderSizeLimit)
|
||||
@@ -192,7 +192,7 @@ bool CInArchive::Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit)
|
||||
return false;
|
||||
if (!ReadBlock2())
|
||||
return false;
|
||||
while(true)
|
||||
for (;;)
|
||||
if (!ReadBlock())
|
||||
break;
|
||||
return true;
|
||||
@@ -270,7 +270,7 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
|
||||
for (; _blockPos < _blockSize;)
|
||||
item.Name += (char)ReadByte();
|
||||
|
||||
while(true)
|
||||
for (;;)
|
||||
if (!ReadBlock())
|
||||
break;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ DEFINE_GUID(CLSID_CArjHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x04, 0x00, 0x00);
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /*lpReserved*/)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ STATPROPSTG kProperties[] =
|
||||
{ NULL, kpidPackedSize, VT_UI8},
|
||||
};
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value)
|
||||
{
|
||||
value->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
@@ -68,8 +68,8 @@ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */,
|
||||
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
@@ -101,8 +101,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *openArchiveCallback)
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback * /* openArchiveCallback */)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
try
|
||||
@@ -219,10 +219,10 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
RINOK(_stream->Seek(_streamStartPosition, STREAM_SEEK_SET, NULL));
|
||||
|
||||
|
||||
HRESULT result;
|
||||
HRESULT result = S_OK;
|
||||
|
||||
bool firstItem = true;
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
localCompressProgressSpec->Init(progress,
|
||||
¤tTotalPacked,
|
||||
|
||||
@@ -33,8 +33,7 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT CopyStreams(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, IArchiveUpdateCallback *updateCallback)
|
||||
static HRESULT CopyStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream)
|
||||
{
|
||||
CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
|
||||
return copyCoder->Code(inStream, outStream, NULL, NULL, NULL);
|
||||
@@ -101,7 +100,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
if (indexInArchive != 0)
|
||||
return E_INVALIDARG;
|
||||
RINOK(_stream->Seek(_streamStartPosition, STREAM_SEEK_SET, NULL));
|
||||
return CopyStreams(_stream, outStream, updateCallback);
|
||||
return CopyStreams(_stream, outStream);
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
|
||||
|
||||
@@ -68,7 +68,7 @@ static const wchar_t *kMethods[] =
|
||||
static const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]);
|
||||
static const wchar_t *kUnknownMethod = L"Unknown";
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value)
|
||||
{
|
||||
value->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
@@ -101,8 +101,8 @@ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */,
|
||||
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
@@ -153,7 +153,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
|
||||
case kpidMethod:
|
||||
{
|
||||
UInt16 realFolderIndex = item.GetFolderIndex(db.Folders.Size());
|
||||
UInt32 realFolderIndex = item.GetFolderIndex(db.Folders.Size());
|
||||
const CFolder &folder = db.Folders[realFolderIndex];
|
||||
int methodIndex = folder.GetCompressionMethod();
|
||||
UString method = (methodIndex < kNumMethods) ? kMethods[methodIndex] : kUnknownMethod;
|
||||
@@ -223,7 +223,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
Close();
|
||||
HRESULT res;
|
||||
HRESULT res = S_FALSE;
|
||||
CInArchive archive;
|
||||
CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
|
||||
{
|
||||
@@ -269,7 +269,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
RINOK(openArchiveCallback->SetCompleted(&numItems, NULL));
|
||||
|
||||
nextStream = 0;
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
const COtherArchive *otherArchive = 0;
|
||||
if (!prevChecked)
|
||||
@@ -511,7 +511,7 @@ HRESULT CCabFolderOutStream::FlushCorrupted()
|
||||
Byte buffer[kBufferSize];
|
||||
for (int i = 0; i < kBufferSize; i++)
|
||||
buffer[i] = 0;
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
UInt64 remain = GetRemain();
|
||||
if (remain == 0)
|
||||
@@ -548,7 +548,6 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
return S_OK;
|
||||
bool testMode = (_aTestMode != 0);
|
||||
UInt64 totalUnPacked = 0;
|
||||
int lastIndex = 0;
|
||||
|
||||
UInt32 i;
|
||||
int lastFolder = -2;
|
||||
@@ -806,10 +805,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
*numItems = m_Database.Items.Size();
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
namespace NArchive{
|
||||
namespace NCab{
|
||||
|
||||
/*
|
||||
static HRESULT ReadBytes(IInStream *inStream, void *data, UInt32 size)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
@@ -37,6 +38,7 @@ static void SafeInByteRead(::CInBuffer &inBuffer, void *data, UInt32 size)
|
||||
if(realProcessedSize != size)
|
||||
throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
|
||||
}
|
||||
*/
|
||||
|
||||
Byte CInArchive::ReadByte()
|
||||
{
|
||||
@@ -71,7 +73,7 @@ UInt32 CInArchive::ReadUInt32()
|
||||
AString CInArchive::SafeReadName()
|
||||
{
|
||||
AString name;
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
Byte b = ReadByte();
|
||||
if (b == 0)
|
||||
@@ -107,7 +109,7 @@ HRESULT CInArchive::Open2(IInStream *inStream,
|
||||
UInt64 value = 0;
|
||||
const int kSignatureSize = 8;
|
||||
UInt64 kSignature64 = NHeader::NArchive::kSignature;
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
Byte b;
|
||||
if (!inBuffer.ReadByte(b))
|
||||
|
||||
@@ -57,7 +57,7 @@ STATPROPSTG kProperties[] =
|
||||
|
||||
static const int kNumProperties = sizeof(kProperties) / sizeof(kProperties[0]);
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value)
|
||||
{
|
||||
value->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
@@ -90,8 +90,8 @@ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */,
|
||||
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
@@ -146,7 +146,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
if (item.Section == 0)
|
||||
propVariant = L"Copy";
|
||||
else if (item.Section < m_Database.Sections.Size())
|
||||
propVariant = m_Database.Sections[(size_t)item.Section].GetMethodName();
|
||||
propVariant = m_Database.Sections[(int)item.Section].GetMethodName();
|
||||
break;
|
||||
}
|
||||
case kpidBlock:
|
||||
@@ -486,7 +486,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
}
|
||||
|
||||
RINOK(m_Stream->Seek(m_Database.ContentOffset + item.Offset, STREAM_SEEK_SET, NULL));
|
||||
streamSpec->Init(m_Stream, item.Size);
|
||||
streamSpec->SetStream(m_Stream);
|
||||
streamSpec->Init(item.Size);
|
||||
|
||||
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
|
||||
@@ -519,7 +520,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
currentTotalSize += item.Size;
|
||||
continue;
|
||||
}
|
||||
const CSectionInfo §ion = m_Database.Sections[(size_t)item.Section];
|
||||
const CSectionInfo §ion = m_Database.Sections[(int)item.Section];
|
||||
if (section.IsLzx())
|
||||
{
|
||||
const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo;
|
||||
@@ -581,7 +582,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
if (!testMode && item.Size != 0)
|
||||
{
|
||||
RINOK(m_Stream->Seek(m_Database.ContentOffset + item.Offset, STREAM_SEEK_SET, NULL));
|
||||
streamSpec->Init(m_Stream, item.Size);
|
||||
streamSpec->SetStream(m_Stream);
|
||||
streamSpec->Init(item.Size);
|
||||
if(!copyCoder)
|
||||
copyCoder = new NCompress::CCopyCoder;
|
||||
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, compressProgress));
|
||||
@@ -592,7 +594,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
continue;
|
||||
}
|
||||
|
||||
const CSectionInfo §ion = m_Database.Sections[(size_t)sectionIndex];
|
||||
const CSectionInfo §ion = m_Database.Sections[(int)sectionIndex];
|
||||
|
||||
if (!section.IsLzx())
|
||||
{
|
||||
@@ -631,7 +633,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
extractStatuses.Clear();
|
||||
extractStatuses.Add(true);
|
||||
|
||||
for (;true; folderIndex++)
|
||||
for (;; folderIndex++)
|
||||
{
|
||||
RINOK(extractCallback->SetCompleted(¤tTotalSize));
|
||||
|
||||
@@ -695,9 +697,10 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
UInt64 rem = finishPos - chmFolderOutStream->m_PosInSection;
|
||||
if (rem > rt.BlockSize)
|
||||
rem = rt.BlockSize;
|
||||
const UInt64 *offsets = (const UInt64 *)&rt.ResetOffsets.Front();
|
||||
// const UInt64 *offsets = (const UInt64 *)&rt.ResetOffsets.Front();
|
||||
RINOK(m_Stream->Seek(compressedPos + offset, STREAM_SEEK_SET, NULL));
|
||||
streamSpec->Init(m_Stream, compressedSize);
|
||||
streamSpec->SetStream(m_Stream);
|
||||
streamSpec->Init(compressedSize);
|
||||
lzxDecoderSpec->SetKeepHistory(b > 0, (int)((offset - startOffset) & 1));
|
||||
RINOK(lzxDecoder->Code(inStream, outStream, NULL, &rem, NULL));
|
||||
}
|
||||
@@ -718,13 +721,11 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
*numItems = m_Database.NewFormat ? 1:
|
||||
(m_Database.LowLevel ?
|
||||
m_Database.Items.Size():
|
||||
m_Database.Indices.Size());
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -38,7 +38,7 @@ static bool AreGuidsEqual(REFGUID g1, REFGUID g2)
|
||||
|
||||
static char GetHex(Byte value)
|
||||
{
|
||||
return (value < 10) ? ('0' + value) : ('A' + (value - 10));
|
||||
return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
|
||||
}
|
||||
|
||||
static void PrintByte(Byte b, AString &s)
|
||||
@@ -248,7 +248,8 @@ HRESULT CInArchive::ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size)
|
||||
RINOK(inStream->Seek(pos, STREAM_SEEK_SET, NULL));
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> limitedStream(streamSpec);
|
||||
streamSpec->Init(inStream, size);
|
||||
streamSpec->SetStream(inStream);
|
||||
streamSpec->Init(size);
|
||||
_inBuffer.SetStream(limitedStream);
|
||||
_inBuffer.Init();
|
||||
return S_OK;
|
||||
@@ -276,12 +277,12 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database)
|
||||
UInt32 unknown1 = ReadUInt32();
|
||||
if (unknown1 != 0 && unknown1 != 1) // it's 0 in one .sll file
|
||||
return S_FALSE;
|
||||
UInt32 timeStamp = ReadUInt32();
|
||||
/* UInt32 timeStamp = */ ReadUInt32();
|
||||
// Considered as a big-endian DWORD, it appears to contain seconds (MSB) and
|
||||
// fractional seconds (second byte).
|
||||
// The third and fourth bytes may contain even more fractional bits.
|
||||
// The 4 least significant bits in the last byte are constant.
|
||||
UInt32 lang = ReadUInt32();
|
||||
/* UInt32 lang = */ ReadUInt32();
|
||||
GUID g;
|
||||
ReadGUID(g); // {7C01FD10-7BAA-11D0-9E0C-00A0-C922-E6EC}
|
||||
ReadGUID(g); // {7C01FD11-7BAA-11D0-9E0C-00A0-C922-E6EC}
|
||||
@@ -319,23 +320,23 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database)
|
||||
return S_FALSE;
|
||||
if (ReadUInt32() != 1) // version
|
||||
return S_FALSE;
|
||||
UInt32 dirHeaderSize = ReadUInt32();
|
||||
/* UInt32 dirHeaderSize = */ ReadUInt32();
|
||||
ReadUInt32(); // 0x0A (unknown)
|
||||
UInt32 dirChunkSize = ReadUInt32(); // $1000
|
||||
if (dirChunkSize < 32)
|
||||
return S_FALSE;
|
||||
UInt32 density = ReadUInt32(); // "Density" of quickref section, usually 2.
|
||||
UInt32 depth = ReadUInt32(); // Depth of the index tree: 1 there is no index,
|
||||
/* UInt32 density = */ ReadUInt32(); // "Density" of quickref section, usually 2.
|
||||
/* UInt32 depth = */ ReadUInt32(); // Depth of the index tree: 1 there is no index,
|
||||
// 2 if there is one level of PMGI chunks.
|
||||
|
||||
UInt32 chunkNumber = ReadUInt32(); // Chunk number of root index chunk, -1 if there is none
|
||||
/* UInt32 chunkNumber = */ ReadUInt32(); // Chunk number of root index chunk, -1 if there is none
|
||||
// (though at least one file has 0 despite there being no
|
||||
// index chunk, probably a bug.)
|
||||
UInt32 firstPmglChunkNumber = ReadUInt32(); // Chunk number of first PMGL (listing) chunk
|
||||
UInt32 lastPmglChunkNumber = ReadUInt32(); // Chunk number of last PMGL (listing) chunk
|
||||
/* UInt32 firstPmglChunkNumber = */ ReadUInt32(); // Chunk number of first PMGL (listing) chunk
|
||||
/* UInt32 lastPmglChunkNumber = */ ReadUInt32(); // Chunk number of last PMGL (listing) chunk
|
||||
ReadUInt32(); // -1 (unknown)
|
||||
UInt32 numDirChunks = ReadUInt32(); // Number of directory chunks (total)
|
||||
UInt32 windowsLangId = ReadUInt32();
|
||||
/* UInt32 windowsLangId = */ ReadUInt32();
|
||||
ReadGUID(g); // {5D02926A-212E-11D0-9DF9-00A0C922E6EC}
|
||||
ReadUInt32(); // 0x54 (This is the length again)
|
||||
ReadUInt32(); // -1 (unknown)
|
||||
@@ -360,7 +361,7 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database)
|
||||
ReadUInt32(); // Chunk number of next listing chunk when reading
|
||||
// directory in sequence (-1 if this is the last listing chunk)
|
||||
int numItems = 0;
|
||||
while (true)
|
||||
for (;;)
|
||||
{
|
||||
UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos;
|
||||
UInt32 offsetLimit = dirChunkSize - quickrefLength;
|
||||
@@ -448,7 +449,7 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
|
||||
UInt32 caolLength = ReadUInt32(); // $50 (Length of the CAOL section, which includes the ITSF section)
|
||||
if (caolLength >= 0x2C)
|
||||
{
|
||||
UInt32 c7 = ReadUInt16(); // Unknown. Remains the same when identical files are built.
|
||||
/* UInt32 c7 = */ ReadUInt16(); // Unknown. Remains the same when identical files are built.
|
||||
// Does not appear to be a checksum. Many files have
|
||||
// 'HH' (HTML Help?) here, indicating this may be a compiler ID
|
||||
// field. But at least one ITOL/ITLS compiler does not set this
|
||||
@@ -479,13 +480,13 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
|
||||
if (unknown != 0 && unknown != 1) // = 0 for some HxW files, 1 in other cases;
|
||||
return S_FALSE;
|
||||
database.ContentOffset = _startPosition + ReadUInt64();
|
||||
UInt32 timeStamp = ReadUInt32();
|
||||
/* UInt32 timeStamp = */ ReadUInt32();
|
||||
// A timestamp of some sort.
|
||||
// Considered as a big-endian DWORD, it appears to contain
|
||||
// seconds (MSB) and fractional seconds (second byte).
|
||||
// The third and fourth bytes may contain even more fractional
|
||||
// bits. The 4 least significant bits in the last byte are constant.
|
||||
UInt32 lang = ReadUInt32(); // BE?
|
||||
/* UInt32 lang = */ ReadUInt32(); // BE?
|
||||
}
|
||||
else
|
||||
return S_FALSE;
|
||||
@@ -539,7 +540,7 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
|
||||
ReadUInt32(); // 0 (unknown)
|
||||
|
||||
int numItems = 0;
|
||||
while (true)
|
||||
for (;;)
|
||||
{
|
||||
UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos;
|
||||
UInt32 offsetLimit = dirChunkSize - quickrefLength;
|
||||
@@ -684,7 +685,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
|
||||
{
|
||||
// The NameList file
|
||||
RINOK(DecompressStream(inStream, database, kNameList));
|
||||
UInt16 length = ReadUInt16();
|
||||
/* UInt16 length = */ ReadUInt16();
|
||||
UInt16 numSections = ReadUInt16();
|
||||
for (int i = 0; i < numSections; i++)
|
||||
{
|
||||
@@ -849,7 +850,7 @@ HRESULT CInArchive::Open2(IInStream *inStream,
|
||||
const int kSignatureSize = 8;
|
||||
UInt64 hxsSignature = NHeader::GetHxsSignature();
|
||||
UInt64 chmSignature = ((UInt64)chmVersion << 32)| NHeader::kItsfSignature;
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
Byte b;
|
||||
if (!_inBuffer.ReadByte(b))
|
||||
|
||||
@@ -76,11 +76,11 @@ struct CResetTable
|
||||
{
|
||||
if (blockIndex >= ResetOffsets.Size())
|
||||
return false;
|
||||
UInt64 startPos = ResetOffsets[(size_t)blockIndex];
|
||||
UInt64 startPos = ResetOffsets[(int)blockIndex];
|
||||
if (blockIndex + numBlocks >= ResetOffsets.Size())
|
||||
size = CompressedSize - startPos;
|
||||
else
|
||||
size = ResetOffsets[(size_t)blockIndex + numBlocks] - startPos;
|
||||
size = ResetOffsets[(int)(blockIndex + numBlocks)] - startPos;
|
||||
return true;
|
||||
}
|
||||
bool GetCompressedSizeOfBlock(UInt64 blockIndex, UInt64 &size) const
|
||||
@@ -121,7 +121,7 @@ struct CLzxInfo
|
||||
UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex);
|
||||
if (blockIndex >= ResetTable.ResetOffsets.Size())
|
||||
return false;
|
||||
offset = ResetTable.ResetOffsets[(size_t)blockIndex];
|
||||
offset = ResetTable.ResetOffsets[(int)blockIndex];
|
||||
return true;
|
||||
}
|
||||
bool GetCompressedSizeOfFolder(UInt64 folderIndex, UInt64 &size) const
|
||||
@@ -168,7 +168,7 @@ public:
|
||||
UInt64 GetFolder(int fileIndex) const
|
||||
{
|
||||
const CItem &item = Items[Indices[fileIndex]];
|
||||
const CSectionInfo §ion = Sections[(size_t)item.Section];
|
||||
const CSectionInfo §ion = Sections[(int)item.Section];
|
||||
if (section.IsLzx())
|
||||
return section.Methods[0].LzxInfo.GetFolder(item.Offset);
|
||||
return 0;
|
||||
@@ -177,7 +177,7 @@ public:
|
||||
UInt64 GetLastFolder(int fileIndex) const
|
||||
{
|
||||
const CItem &item = Items[Indices[fileIndex]];
|
||||
const CSectionInfo §ion = Sections[(size_t)item.Section];
|
||||
const CSectionInfo §ion = Sections[(int)item.Section];
|
||||
if (section.IsLzx())
|
||||
return section.Methods[0].LzxInfo.GetFolder(item.Offset + item.Size - 1);
|
||||
return 0;
|
||||
|
||||
@@ -13,7 +13,7 @@ DEFINE_GUID(CLSID_CChmHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xE9, 0x00, 0x00);
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /*lpReserved*/)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ struct CBindInfo
|
||||
class CBindReverseConverter
|
||||
{
|
||||
UInt32 _numSrcOutStreams;
|
||||
const NCoderMixer2::CBindInfo _srcBindInfo;
|
||||
NCoderMixer2::CBindInfo _srcBindInfo;
|
||||
CRecordVector<UInt32> _srcInToDestOutMap;
|
||||
CRecordVector<UInt32> _srcOutToDestInMap;
|
||||
CRecordVector<UInt32> _destInToSrcOutMap;
|
||||
|
||||
@@ -125,7 +125,7 @@ void CThreadCoderInfo::SetCoderInfo(const UInt64 **inSizes,
|
||||
|
||||
static DWORD WINAPI CoderThread(void *threadCoderInfo)
|
||||
{
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
if (!((CThreadCoderInfo *)threadCoderInfo)->WaitAndCode())
|
||||
return 0;
|
||||
@@ -137,7 +137,7 @@ static DWORD WINAPI CoderThread(void *threadCoderInfo)
|
||||
|
||||
static DWORD WINAPI MainCoderThread(void *threadCoderInfo)
|
||||
{
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
if (!((CCoderMixer2MT *)threadCoderInfo)->MyCode())
|
||||
return 0;
|
||||
@@ -282,7 +282,7 @@ bool CCoderMixer2MT::MyCode()
|
||||
|
||||
for(int i = 0; i < _coderInfoVector.Size(); i++)
|
||||
_coderInfoVector[i].CompressEvent->Set();
|
||||
DWORD result = ::WaitForMultipleObjects(_compressingCompletedEvents.Size(),
|
||||
/* DWORD result = */ ::WaitForMultipleObjects(_compressingCompletedEvents.Size(),
|
||||
&_compressingCompletedEvents.Front(), TRUE, INFINITE);
|
||||
|
||||
_compressingFinishedEvent.Set();
|
||||
@@ -292,10 +292,10 @@ bool CCoderMixer2MT::MyCode()
|
||||
|
||||
|
||||
STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
|
||||
const UInt64 **inSizes,
|
||||
const UInt64 ** /* inSizes */,
|
||||
UInt32 numInStreams,
|
||||
ISequentialOutStream **outStreams,
|
||||
const UInt64 **outSizes,
|
||||
const UInt64 ** /* outSizes */,
|
||||
UInt32 numOutStreams,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
@@ -315,7 +315,7 @@ STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
|
||||
_startCompressingEvent.Set();
|
||||
|
||||
|
||||
while (true)
|
||||
for (;;)
|
||||
{
|
||||
HANDLE events[2] = {_compressingFinishedEvent, progressSpec->ProgressEvent };
|
||||
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
|
||||
|
||||
@@ -66,7 +66,8 @@ public:
|
||||
{
|
||||
{ _coders[coderIndex].SetCoderInfo(inSizes, outSizes); }
|
||||
}
|
||||
void SetProgressCoderIndex(UInt32 coderIndex)
|
||||
|
||||
void SetProgressCoderIndex(UInt32 /*coderIndex*/)
|
||||
{
|
||||
// _progressCoderIndex = coderIndex;
|
||||
}
|
||||
|
||||
@@ -37,12 +37,13 @@ HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 siz
|
||||
|
||||
|
||||
STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
|
||||
ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
RINOK(Init());
|
||||
UInt32 bufferPos = 0;
|
||||
if (_outSizeIsDefined = (outSize != 0))
|
||||
_outSizeIsDefined = (outSize != 0);
|
||||
if (_outSizeIsDefined)
|
||||
_outSize = *outSize;
|
||||
|
||||
while(NeedMore())
|
||||
|
||||
@@ -4,23 +4,25 @@
|
||||
|
||||
#include "InStreamWithCRC.h"
|
||||
|
||||
STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data,
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
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.Update(data, realProcessedSize);
|
||||
if(processedSize != NULL)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP CInStreamWithCRC::Read(void *data,
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
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.Update(data, realProcessedSize);
|
||||
if(processedSize != NULL)
|
||||
|
||||
@@ -19,16 +19,19 @@ private:
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
UInt64 _size;
|
||||
CCRC _crc;
|
||||
bool _wasFinished;
|
||||
public:
|
||||
void Init(ISequentialInStream *stream)
|
||||
void SetStream(ISequentialInStream *stream) { _stream = stream; }
|
||||
void Init()
|
||||
{
|
||||
_stream = stream;
|
||||
_size = 0;
|
||||
_wasFinished = false;
|
||||
_crc.Init();
|
||||
}
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
UInt32 GetCRC() const { return _crc.GetDigest(); }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
bool WasFinished() const { return _wasFinished; }
|
||||
};
|
||||
|
||||
class CInStreamWithCRC:
|
||||
@@ -44,16 +47,19 @@ private:
|
||||
CMyComPtr<IInStream> _stream;
|
||||
UInt64 _size;
|
||||
CCRC _crc;
|
||||
bool _wasFinished;
|
||||
public:
|
||||
void Init(IInStream *stream)
|
||||
void SetStream(IInStream *stream) { _stream = stream; }
|
||||
void Init()
|
||||
{
|
||||
_stream = stream;
|
||||
_size = 0;
|
||||
_wasFinished = false;
|
||||
_crc.Init();
|
||||
}
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
UInt32 GetCRC() const { return _crc.GetDigest(); }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
bool WasFinished() const { return _wasFinished; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -40,7 +40,7 @@ bool HasTailSlash(const AString &name, UINT codePage)
|
||||
return false;
|
||||
LPCSTR prev =
|
||||
#ifdef _WIN32
|
||||
CharPrevExA(codePage, name, &name[name.Length()], 0);
|
||||
CharPrevExA((WORD)codePage, name, &name[name.Length()], 0);
|
||||
#else
|
||||
(LPCSTR)(name) + (name.Length() - 1);
|
||||
#endif
|
||||
|
||||
@@ -37,8 +37,6 @@ STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin,
|
||||
UInt64 *newPosition)
|
||||
{
|
||||
UInt64 newPos;
|
||||
if(seekOrigin >= 3)
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
switch(seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET:
|
||||
@@ -50,6 +48,8 @@ STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin,
|
||||
case STREAM_SEEK_END:
|
||||
newPos = _totalLength + offset;
|
||||
break;
|
||||
default:
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
_seekPos = 0;
|
||||
for (_streamIndex = 0; _streamIndex < Streams.Size(); _streamIndex++)
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
|
||||
#include "OutStreamWithCRC.h"
|
||||
|
||||
STDMETHODIMP COutStreamWithCRC::Write(const void *data,
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result;
|
||||
@@ -16,7 +15,9 @@ STDMETHODIMP COutStreamWithCRC::Write(const void *data,
|
||||
}
|
||||
else
|
||||
result = _stream->Write(data, size, &realProcessedSize);
|
||||
_crc.Update(data, realProcessedSize);
|
||||
if (_calculateCrc)
|
||||
_crc.Update(data, realProcessedSize);
|
||||
_size += realProcessedSize;
|
||||
if(processedSize != NULL)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
|
||||
@@ -16,18 +16,22 @@ public:
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
private:
|
||||
CCRC _crc;
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
UInt64 _size;
|
||||
CCRC _crc;
|
||||
bool _calculateCrc;
|
||||
public:
|
||||
void Init(ISequentialOutStream *stream)
|
||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||
void Init(bool calculateCrc = true)
|
||||
{
|
||||
_stream = stream;
|
||||
_size = 0;
|
||||
_calculateCrc = calculateCrc;
|
||||
_crc.Init();
|
||||
}
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
UInt32 GetCRC() const { return _crc.GetDigest(); }
|
||||
void InitCRC() { _crc.Init(); }
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -35,7 +35,7 @@ STATPROPSTG kProperties[] =
|
||||
{ NULL, kpidLastWriteTime, VT_FILETIME}
|
||||
};
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value)
|
||||
{
|
||||
value->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
@@ -65,19 +65,18 @@ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */,
|
||||
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback *openArchiveCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
bool mustBeClosed = true;
|
||||
{
|
||||
CInArchive archive;
|
||||
if(archive.Open(stream) != S_OK)
|
||||
@@ -91,7 +90,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
|
||||
}
|
||||
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
CItemEx itemInfo;
|
||||
bool filled;
|
||||
@@ -217,7 +216,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
RINOK(_inStream->Seek(itemInfo.GetDataPosition(), STREAM_SEEK_SET, NULL));
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> inStream(streamSpec);
|
||||
streamSpec->Init(_inStream, itemInfo.Size);
|
||||
streamSpec->SetStream(_inStream);
|
||||
streamSpec->Init(itemInfo.Size);
|
||||
|
||||
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
|
||||
|
||||
@@ -37,10 +37,21 @@ HRESULT CInArchive::Open(IInStream *inStream)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void MyStrNCpy(char *dest, const char *src, int size)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
char c = src[i];
|
||||
dest[i] = c;
|
||||
if (c == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool OctalToNumber(const char *s, int size, UInt64 &res)
|
||||
{
|
||||
char sz[32];
|
||||
strncpy(sz, s, size);
|
||||
MyStrNCpy(sz, s, size);
|
||||
sz[size] = 0;
|
||||
const char *end;
|
||||
int i;
|
||||
@@ -61,7 +72,7 @@ static bool OctalToNumber32(const char *s, int size, UInt32 &res)
|
||||
static bool DecimalToNumber(const char *s, int size, UInt64 &res)
|
||||
{
|
||||
char sz[32];
|
||||
strncpy(sz, s, size);
|
||||
MyStrNCpy(sz, s, size);
|
||||
sz[size] = 0;
|
||||
const char *end;
|
||||
int i;
|
||||
@@ -96,7 +107,7 @@ HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item)
|
||||
return S_OK;
|
||||
|
||||
char tempString[kNameSize + 1];
|
||||
strncpy(tempString, cur, kNameSize);
|
||||
MyStrNCpy(tempString, cur, kNameSize);
|
||||
cur += kNameSize;
|
||||
tempString[kNameSize] = '\0';
|
||||
item.Name = tempString;
|
||||
@@ -123,7 +134,7 @@ HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item)
|
||||
|
||||
HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
|
||||
{
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
RINOK(GetNextItemReal(filled, item));
|
||||
if (!filled)
|
||||
@@ -134,7 +145,6 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
|
||||
return S_OK;
|
||||
SkeepData(item.Size);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::Skeep(UInt64 numBytes)
|
||||
|
||||
@@ -13,9 +13,9 @@ DEFINE_GUID(CLSID_CDebHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEC, 0x00, 0x00);
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /*lpReserved*/)
|
||||
{
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
STDAPI CreateObject(
|
||||
|
||||
@@ -85,7 +85,7 @@ STATPROPSTG kProperties[] =
|
||||
// { L"Is Text", kpidIsText, VT_BOOL},
|
||||
};
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value)
|
||||
{
|
||||
value->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
@@ -113,21 +113,19 @@ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */,
|
||||
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
*numItems = 1;
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant propVariant;
|
||||
@@ -192,8 +190,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *openArchiveCallback)
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback * /* openArchiveCallback */)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
try
|
||||
@@ -259,7 +257,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
|
||||
COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
|
||||
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
|
||||
outStreamSpec->Init(realOutStream);
|
||||
outStreamSpec->SetStream(realOutStream);
|
||||
outStreamSpec->Init();
|
||||
realOutStream.Release();
|
||||
|
||||
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||
@@ -276,7 +275,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
CMyComPtr<ICompressCoder> deflateDecoder;
|
||||
bool firstItem = true;
|
||||
RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL));
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
localCompressProgressSpec->Init(progress,
|
||||
¤tTotalPacked,
|
||||
@@ -352,10 +351,11 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
if((outStreamSpec->GetCRC() != postItem.FileCRC))
|
||||
{
|
||||
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kCRCError))
|
||||
return S_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
COM_TRY_END
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -36,8 +36,7 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT CopyStreams(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, IArchiveUpdateCallback *updateCallback)
|
||||
static HRESULT CopyStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream)
|
||||
{
|
||||
CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
|
||||
return copyCoder->Code(inStream, outStream, NULL, NULL, NULL);
|
||||
@@ -56,8 +55,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
UInt32 itemIndex = 0;
|
||||
if (!updateCallback)
|
||||
return E_FAIL;
|
||||
RINOK(updateCallback->GetUpdateItemInfo(0,
|
||||
&newData, &newProperties, &indexInArchive));
|
||||
RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProperties, &indexInArchive));
|
||||
|
||||
CItem newItem = m_Item;
|
||||
newItem.ExtraFlags = 0;
|
||||
@@ -157,7 +155,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
{
|
||||
RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
return CopyStreams(m_Stream, outStream, updateCallback);
|
||||
return CopyStreams(m_Stream, outStream);
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
|
||||
|
||||
@@ -55,7 +55,7 @@ HRESULT CInArchive::ReadUInt32(ISequentialInStream *inStream, UInt32 &value)
|
||||
HRESULT CInArchive::ReadZeroTerminatedString(ISequentialInStream *inStream, AString &resString, CCRC &crc)
|
||||
{
|
||||
resString.Empty();
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
Byte c;
|
||||
RINOK(ReadByte(inStream, c));
|
||||
|
||||
@@ -48,7 +48,7 @@ HRESULT COutArchive::WriteHeader(const CItem &item)
|
||||
{
|
||||
RINOK(WriteUInt16(kSignature));
|
||||
RINOK(WriteByte(item.CompressionMethod));
|
||||
RINOK(WriteByte(item.Flags & NFileHeader::NFlags::kNameIsPresent));
|
||||
RINOK(WriteByte((Byte)(item.Flags & NFileHeader::NFlags::kNameIsPresent)));
|
||||
RINOK(WriteUInt32(item.Time));
|
||||
RINOK(WriteByte(item.ExtraFlags));
|
||||
RINOK(WriteByte(item.HostOS));
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace NGZip {
|
||||
|
||||
static const Byte kHostOS = NFileHeader::NHostOS::kFAT;
|
||||
|
||||
HRESULT UpdateArchive(IInStream *inStream,
|
||||
HRESULT UpdateArchive(IInStream * /* inStream */,
|
||||
UInt64 unpackSize,
|
||||
ISequentialOutStream *outStream,
|
||||
const CItem &newItem,
|
||||
@@ -59,7 +59,8 @@ HRESULT UpdateArchive(IInStream *inStream,
|
||||
|
||||
CSequentialInStreamWithCRC *inStreamSpec = new CSequentialInStreamWithCRC;
|
||||
CMyComPtr<ISequentialInStream> crcStream(inStreamSpec);
|
||||
inStreamSpec->Init(fileInStream);
|
||||
inStreamSpec->SetStream(fileInStream);
|
||||
inStreamSpec->Init();
|
||||
|
||||
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;
|
||||
|
||||
@@ -13,7 +13,7 @@ DEFINE_GUID(CLSID_CIsoHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xE7, 0x00, 0x00);
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /* lpReserved */)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ STATPROPSTG kProperties[] =
|
||||
{ NULL, kpidLastWriteTime, VT_FILETIME}
|
||||
};
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value)
|
||||
{
|
||||
value->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
@@ -64,18 +64,17 @@ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */,
|
||||
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *openArchiveCallback)
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback * /* openArchiveCallback */)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
bool mustBeClosed = true;
|
||||
Close();
|
||||
// try
|
||||
{
|
||||
@@ -267,7 +266,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
RINOK(_inStream->Seek(blockIndex * _archive.BlockSize, STREAM_SEEK_SET, NULL));
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> inStream(streamSpec);
|
||||
streamSpec->Init(_inStream, currentItemSize);
|
||||
streamSpec->SetStream(_inStream);
|
||||
streamSpec->Init(currentItemSize);
|
||||
|
||||
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
|
||||
|
||||
@@ -76,7 +76,7 @@ UInt16 CInArchive::ReadUInt16()
|
||||
throw 1;
|
||||
value |= ((UInt16)(b[i]) << (8 * i));
|
||||
}
|
||||
return value;
|
||||
return (UInt16)value;
|
||||
}
|
||||
|
||||
UInt32 CInArchive::ReadUInt32Le()
|
||||
@@ -134,13 +134,13 @@ UInt32 CInArchive::ReadDigits(int numDigits)
|
||||
|
||||
void CInArchive::ReadDateTime(CDateTime &d)
|
||||
{
|
||||
d.Year = ReadDigits(4);
|
||||
d.Month = ReadDigits(2);
|
||||
d.Day = ReadDigits(2);
|
||||
d.Hour = ReadDigits(2);
|
||||
d.Minute = ReadDigits(2);
|
||||
d.Second = ReadDigits(2);
|
||||
d.Hundredths = ReadDigits(2);
|
||||
d.Year = (UInt16)ReadDigits(4);
|
||||
d.Month = (Byte)ReadDigits(2);
|
||||
d.Day = (Byte)ReadDigits(2);
|
||||
d.Hour = (Byte)ReadDigits(2);
|
||||
d.Minute = (Byte)ReadDigits(2);
|
||||
d.Second = (Byte)ReadDigits(2);
|
||||
d.Hundredths = (Byte)ReadDigits(2);
|
||||
d.GmtOffset = (signed char)ReadByte();
|
||||
}
|
||||
|
||||
@@ -254,7 +254,7 @@ void CInArchive::ReadDir(CDir &d, int level)
|
||||
UInt64 startPos = _position;
|
||||
|
||||
bool firstItem = true;
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
UInt64 offset = _position - startPos;
|
||||
if (offset >= d.DataLength)
|
||||
@@ -311,7 +311,7 @@ void CInArchive::ReadBootInfo()
|
||||
if (ReadUInt16Spec() != 0)
|
||||
throw 1;
|
||||
ReadBytes(e.Id, sizeof(e.Id));
|
||||
UInt16 checkSum = ReadUInt16Spec();
|
||||
/* UInt16 checkSum = */ ReadUInt16Spec();
|
||||
if (ReadByte() != 0x55)
|
||||
throw 1;
|
||||
if (ReadByte() != 0xAA)
|
||||
@@ -346,14 +346,17 @@ HRESULT CInArchive::Open2()
|
||||
m_BufferPos = 0;
|
||||
BlockSize = kBlockSize;
|
||||
VolDescs.Add(CVolumeDescriptor());
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
Byte sig[6];
|
||||
ReadBytes(sig, 6);
|
||||
if (!CheckDescriptorSignature(sig + 1))
|
||||
return S_FALSE;
|
||||
if (ReadByte() != kVersion)
|
||||
throw 1;
|
||||
// version = 2 for ISO 9660:1999?
|
||||
Byte ver = ReadByte();
|
||||
if (ver > 2)
|
||||
throw S_FALSE;
|
||||
|
||||
if (sig[0] == NVolDescType::kTerminator)
|
||||
break;
|
||||
switch(sig[0])
|
||||
|
||||
@@ -36,7 +36,7 @@ struct CDir: public CDirRecord
|
||||
|
||||
int GetLengthU() const
|
||||
{
|
||||
int len = FileId.GetCapacity() / 2;
|
||||
int len = (int)(FileId.GetCapacity() / 2);
|
||||
if (Parent != 0)
|
||||
if (Parent->Parent != 0)
|
||||
len += 1 + Parent->GetLengthU();
|
||||
@@ -51,7 +51,7 @@ struct CDir: public CDirRecord
|
||||
p += len;
|
||||
*p = 0;
|
||||
const CDir *cur = this;
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
int curLen = cur->GetLengthCur(checkSusp, skipSize);
|
||||
p -= curLen;
|
||||
@@ -76,15 +76,15 @@ struct CDir: public CDirRecord
|
||||
p += len;
|
||||
*p = 0;
|
||||
const CDir *cur = this;
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
int curLen = cur->FileId.GetCapacity() / 2;
|
||||
int curLen = (int)(cur->FileId.GetCapacity() / 2);
|
||||
p -= curLen;
|
||||
for (int i = 0; i < curLen; i++)
|
||||
{
|
||||
Byte b0 = ((const Byte *)cur->FileId)[i * 2];
|
||||
Byte b1 = ((const Byte *)cur->FileId)[i * 2 + 1];
|
||||
p[i] = ((wchar_t)b0 << 8) | (wchar_t)b1;
|
||||
p[i] = (wchar_t)(((wchar_t)b0 << 8) | b1);
|
||||
}
|
||||
cur = cur->Parent;
|
||||
if (cur == 0)
|
||||
|
||||
@@ -25,7 +25,7 @@ struct CRecordingDateTime
|
||||
bool GetFileTime(FILETIME &ft) const
|
||||
{
|
||||
SYSTEMTIME st;
|
||||
st.wYear = Year + 1900;
|
||||
st.wYear = (WORD)(Year + 1900);
|
||||
st.wMonth = Month;
|
||||
st.wDayOfWeek = 0; // check it
|
||||
st.wDay = Day;
|
||||
@@ -69,7 +69,7 @@ struct CDirRecord
|
||||
{
|
||||
lenRes = 0;
|
||||
const Byte *p = (const Byte *)SystemUse + skipSize;
|
||||
int length = SystemUse.GetCapacity() - skipSize;
|
||||
int length = (int)(SystemUse.GetCapacity() - skipSize);
|
||||
while (length >= 5)
|
||||
{
|
||||
int len = p[2];
|
||||
@@ -93,7 +93,7 @@ struct CDirRecord
|
||||
if (res != 0)
|
||||
return len;
|
||||
}
|
||||
return FileId.GetCapacity();
|
||||
return (int)FileId.GetCapacity();
|
||||
}
|
||||
|
||||
const Byte* GetNameCur(bool checkSusp, int skipSize) const
|
||||
@@ -127,7 +127,7 @@ struct CDirRecord
|
||||
bool CheckSusp(int &startPos) const
|
||||
{
|
||||
const Byte *p = (const Byte *)SystemUse;
|
||||
int length = SystemUse.GetCapacity();
|
||||
int length = (int)SystemUse.GetCapacity();
|
||||
const int kMinLen = 7;
|
||||
if (length < kMinLen)
|
||||
return false;
|
||||
|
||||
@@ -13,7 +13,7 @@ DEFINE_GUID(CLSID_CLzhHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x06, 0x00, 0x00);
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /* lpReserved */)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ void CCRC::Update(const void *data, size_t size)
|
||||
UInt16 v = _value;
|
||||
const Byte *p = (const Byte *)data;
|
||||
for (; size > 0; size--, p++)
|
||||
v = Table[((Byte)(v)) ^ *p] ^ (v >> 8);
|
||||
v = (UInt16)(Table[((Byte)(v)) ^ *p] ^ (v >> 8));
|
||||
_value = v;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace NLzh {
|
||||
|
||||
class CCRC
|
||||
{
|
||||
UInt32 _value;
|
||||
UInt16 _value;
|
||||
public:
|
||||
static UInt16 Table[256];
|
||||
static void InitTable();
|
||||
|
||||
@@ -89,7 +89,7 @@ STATPROPSTG kProperties[] =
|
||||
CHandler::CHandler()
|
||||
{}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value)
|
||||
{
|
||||
value->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
@@ -119,8 +119,8 @@ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */,
|
||||
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
@@ -226,7 +226,7 @@ STDMETHODIMP CPropgressImp::SetCompleted(const UInt64 *numFiles)
|
||||
*/
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback)
|
||||
const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *callback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
try
|
||||
@@ -240,7 +240,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
UInt64 numFiles = _items.Size();
|
||||
RINOK(callback->SetCompleted(&numFiles, NULL));
|
||||
}
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
CItemEx itemInfo;
|
||||
bool filled;
|
||||
@@ -307,7 +307,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0;
|
||||
UInt64 currentItemUnPacked, currentItemPacked;
|
||||
|
||||
NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec;
|
||||
NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = 0;
|
||||
CMyComPtr<ICompressCoder> lzhDecoder;
|
||||
CMyComPtr<ICompressCoder> lzh1Decoder;
|
||||
CMyComPtr<ICompressCoder> arj2Decoder;
|
||||
@@ -357,7 +357,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
UInt64 pos;
|
||||
_stream->Seek(itemInfo.DataPosition, STREAM_SEEK_SET, &pos);
|
||||
|
||||
streamSpec->Init(_stream, itemInfo.PackSize);
|
||||
streamSpec->SetStream(_stream);
|
||||
streamSpec->Init(itemInfo.PackSize);
|
||||
|
||||
|
||||
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||
|
||||
@@ -66,9 +66,9 @@ static const Byte *ReadString(const Byte *p, size_t size, AString &s)
|
||||
static Byte CalcSum(const Byte *data, size_t size)
|
||||
{
|
||||
Byte sum = 0;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
sum += data[i];
|
||||
return sum;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
sum = (Byte)(sum + data[i]);
|
||||
return sum;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
|
||||
|
||||
@@ -150,7 +150,7 @@ public:
|
||||
AString GetName() const
|
||||
{
|
||||
AString dirName = GetDirName();
|
||||
dirName.Replace((char)0xFF, '\\');
|
||||
dirName.Replace((char)(unsigned char)0xFF, '\\');
|
||||
if (!dirName.IsEmpty())
|
||||
{
|
||||
char c = dirName[dirName.Length() - 1];
|
||||
|
||||
@@ -42,7 +42,7 @@ STATPROPSTG kProperties[] =
|
||||
{ NULL, kpidSolid, VT_BOOL}
|
||||
};
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value)
|
||||
{
|
||||
value->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
@@ -71,15 +71,15 @@ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */,
|
||||
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback)
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * maxCheckStartPosition, IArchiveOpenCallback * /* openArchiveCallback */)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
bool mustBeClosed = true;
|
||||
Close();
|
||||
{
|
||||
if(_archive.Open(stream, maxCheckStartPosition) != S_OK)
|
||||
|
||||
@@ -53,7 +53,7 @@ void CInArchive::ReadBlockHeader(CBlockHeader &bh)
|
||||
|
||||
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
|
||||
|
||||
static int CompareItems(void *const *p1, void *const *p2, void *param)
|
||||
static int CompareItems(void *const *p1, void *const *p2, void * /* param */)
|
||||
{
|
||||
RINOZ(MyCompare(
|
||||
(**(const CItem **)p1).Pos,
|
||||
@@ -65,17 +65,19 @@ AString CInArchive::ReadString(UInt32 pos)
|
||||
{
|
||||
AString s;
|
||||
UInt32 offset = GetOffset() + _stringsPos + pos;
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
if (offset >= _size)
|
||||
throw 1;
|
||||
char c = _data[offset++];
|
||||
if (c == 0)
|
||||
return s;
|
||||
break;
|
||||
s += c;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
static AString ParsePrefix(const AString &prefix)
|
||||
{
|
||||
AString res = prefix;
|
||||
@@ -88,7 +90,7 @@ static AString ParsePrefix(const AString &prefix)
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
#define SYSREGKEY "Software\\Microsoft\\Windows\\CurrentVersion"
|
||||
|
||||
@@ -525,13 +527,19 @@ AString CInArchive::ReadString2(UInt32 pos)
|
||||
#define DEL_REBOOT 4
|
||||
// #define DEL_SIMPLE 8
|
||||
|
||||
const int kNumEntryParams = 6;
|
||||
static const int kNumEntryParams = 6;
|
||||
|
||||
struct CEntry
|
||||
{
|
||||
UInt32 Which;
|
||||
UInt32 Params[kNumEntryParams];
|
||||
AString GetParamsString(int numParams);
|
||||
CEntry()
|
||||
{
|
||||
Which = 0;
|
||||
for (UInt32 j = 0; j < kNumEntryParams; j++)
|
||||
Params[j] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
AString CEntry::GetParamsString(int numParams)
|
||||
@@ -584,12 +592,12 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
|
||||
{
|
||||
CItem item;
|
||||
item.Prefix = prefix;
|
||||
UInt32 overwriteFlag = e.Params[0];
|
||||
/* UInt32 overwriteFlag = e.Params[0]; */
|
||||
item.Name = ReadString2(e.Params[1]);
|
||||
item.Pos = e.Params[2];
|
||||
item.DateTime.dwLowDateTime = e.Params[3];
|
||||
item.DateTime.dwHighDateTime = e.Params[4];
|
||||
UInt32 allowIgnore = e.Params[5];
|
||||
/* UInt32 allowIgnore = e.Params[5]; */
|
||||
if (Items.Size() > 0)
|
||||
{
|
||||
/*
|
||||
@@ -949,7 +957,7 @@ HRESULT CInArchive::Parse()
|
||||
{
|
||||
// UInt32 offset = ReadUInt32();
|
||||
// ???? offset == FirstHeader.HeaderLength
|
||||
UInt32 ehFlags = ReadUInt32();
|
||||
/* UInt32 ehFlags = */ ReadUInt32();
|
||||
CBlockHeader bhPages, bhSections, bhEntries, bhStrings, bhLangTables, bhCtlColors, bhData;
|
||||
// CBlockHeader bgFont;
|
||||
ReadBlockHeader(bhPages);
|
||||
@@ -1034,7 +1042,8 @@ HRESULT CInArchive::Open2()
|
||||
_posInData = 0;
|
||||
if (!IsSolid)
|
||||
{
|
||||
if (_headerIsCompressed = ((compressedHeaderSize & 0x80000000) != 0))
|
||||
_headerIsCompressed = ((compressedHeaderSize & 0x80000000) != 0);
|
||||
if (_headerIsCompressed)
|
||||
compressedHeaderSize &= ~0x80000000;
|
||||
_nonSolidStartOffset = compressedHeaderSize;
|
||||
RINOK(_stream->Seek(StreamOffset + 4, STREAM_SEEK_SET, NULL));
|
||||
@@ -1113,7 +1122,7 @@ HRESULT CInArchive::Open(IInStream *inStream, const UInt64 *maxCheckStartPositio
|
||||
Byte buffer[kStep];
|
||||
bool found = false;
|
||||
|
||||
UInt64 headerPosition;
|
||||
UInt64 headerPosition = 0;
|
||||
while (position <= maxSize)
|
||||
{
|
||||
UInt32 processedSize;
|
||||
|
||||
@@ -13,9 +13,9 @@ DEFINE_GUID(CLSID_CRpmHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEB, 0x00, 0x00);
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /* lpReserved */)
|
||||
{
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
STDAPI CreateObject(
|
||||
|
||||
@@ -33,7 +33,7 @@ STATPROPSTG kProperties[] =
|
||||
{ NULL, kpidPackedSize, VT_UI8}
|
||||
};
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value)
|
||||
{
|
||||
value->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
@@ -63,15 +63,15 @@ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */,
|
||||
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *openArchiveCallback)
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback * /* openArchiveCallback */)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
try
|
||||
@@ -104,7 +104,7 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant propVariant;
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace NRpm {
|
||||
|
||||
static UInt16 GetUInt16(const char *data)
|
||||
{
|
||||
return (Byte)data[1] | (((UInt16)(Byte)data[0]) << 8);
|
||||
return (UInt16)((Byte)data[1] | (((UInt16)(Byte)data[0]) << 8));
|
||||
}
|
||||
|
||||
static UInt32 GetUInt32(const char *data)
|
||||
|
||||
@@ -351,14 +351,6 @@ SOURCE=..\..\Crypto\RarAES\RarAES.cpp
|
||||
|
||||
SOURCE=..\..\Crypto\RarAES\RarAES.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\RarAES\sha1.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\RarAES\sha1.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Rar20"
|
||||
|
||||
@@ -380,6 +372,28 @@ SOURCE=..\..\Crypto\Rar20\Rar20Crypto.cpp
|
||||
SOURCE=..\..\Crypto\Rar20\Rar20Crypto.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Hash"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\Hash\Sha1.cpp
|
||||
|
||||
!IF "$(CFG)" == "Rar - Win32 Release"
|
||||
|
||||
# ADD CPP /O2
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Rar - Win32 Debug"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\Hash\Sha1.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Group
|
||||
# Begin Group "7-zip Common"
|
||||
|
||||
|
||||
@@ -360,7 +360,6 @@ public:
|
||||
}
|
||||
|
||||
int numLetters = 1;
|
||||
bool splitStyle = false;
|
||||
if (basePart.Right(numLetters) == L"1")
|
||||
{
|
||||
while (numLetters < basePart.Length())
|
||||
@@ -432,7 +431,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
|
||||
}
|
||||
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
CMyComPtr<IInStream> inStream;
|
||||
if (!_archives.IsEmpty())
|
||||
@@ -475,7 +474,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
archive.GetArchiveInfo(_archiveInfo);
|
||||
|
||||
CItemEx item;
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
HRESULT result = archive.GetNextItem(item, getTextPassword);
|
||||
if (result == S_FALSE)
|
||||
@@ -618,9 +617,9 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
CFilterCoder *filterStreamSpec = new CFilterCoder;
|
||||
CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec;
|
||||
|
||||
NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec;
|
||||
NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec = NULL;
|
||||
CMyComPtr<ICompressFilter> rar20CryptoDecoder;
|
||||
NCrypto::NRar29::CDecoder *rar29CryptoDecoderSpec;
|
||||
NCrypto::NRar29::CDecoder *rar29CryptoDecoderSpec = NULL;
|
||||
CMyComPtr<ICompressFilter> rar29CryptoDecoder;
|
||||
|
||||
CFolderInStream *folderInStreamSpec = NULL;
|
||||
@@ -681,7 +680,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
|
||||
COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
|
||||
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
|
||||
outStreamSpec->Init(realOutStream);
|
||||
outStreamSpec->SetStream(realOutStream);
|
||||
outStreamSpec->Init();
|
||||
realOutStream.Release();
|
||||
|
||||
UInt64 packedPos = currentImportantTotalPacked;
|
||||
@@ -866,8 +866,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
RINOK(decoder.QueryInterface(IID_ICompressSetDecoderProperties2,
|
||||
&compressSetDecoderProperties));
|
||||
|
||||
Byte isSolid =
|
||||
(IsSolid(index) || item.IsSplitBefore()) ? 1: 0;
|
||||
Byte isSolid = (Byte)((IsSolid(index) || item.IsSplitBefore()) ? 1: 0);
|
||||
|
||||
RINOK(compressSetDecoderProperties->SetDecoderProperties2(&isSolid, 1));
|
||||
|
||||
|
||||
@@ -72,16 +72,16 @@ bool CInArchive::FindAndReadMarker(const UInt64 *searchHeaderSizeLimit)
|
||||
UInt32 numBytesPrev = NHeader::kMarkerSize - 1;
|
||||
memmove(buffer, marker + 1, numBytesPrev);
|
||||
UInt64 curTestPos = m_StreamStartPosition + 1;
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
if (searchHeaderSizeLimit != NULL)
|
||||
if (curTestPos - m_StreamStartPosition > *searchHeaderSizeLimit)
|
||||
return false;
|
||||
break;
|
||||
UInt32 numReadBytes = kSearchMarkerBufferSize - numBytesPrev;
|
||||
ReadBytes(buffer + numBytesPrev, numReadBytes, &processedSize);
|
||||
UInt32 numBytesInBuffer = numBytesPrev + processedSize;
|
||||
if (numBytesInBuffer < NHeader::kMarkerSize)
|
||||
return false;
|
||||
break;
|
||||
UInt32 numTests = numBytesInBuffer - NHeader::kMarkerSize + 1;
|
||||
for(UInt32 pos = 0; pos < numTests; pos++, curTestPos++)
|
||||
{
|
||||
@@ -174,7 +174,6 @@ bool CInArchive::ReadMarkerAndArchiveHeader(const UInt64 *searchHeaderSizeLimit)
|
||||
crc.UpdateByte(m_ArchiveHeader.EncryptVersion);
|
||||
}
|
||||
|
||||
UInt32 u = crc.GetDigest();
|
||||
if(m_ArchiveHeader.CRC != (crc.GetDigest() & 0xFFFF))
|
||||
ThrowExceptionWithCode(CInArchiveException::kArchiveHeaderCRCError);
|
||||
if (m_ArchiveHeader.Type != NHeader::NBlockType::kArchiveHeader)
|
||||
@@ -197,7 +196,7 @@ void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const
|
||||
archiveInfo.StartPosition = m_ArchiveStartPosition;
|
||||
archiveInfo.Flags = m_ArchiveHeader.Flags;
|
||||
archiveInfo.CommentPosition = m_ArchiveCommentPosition;
|
||||
archiveInfo.CommentSize = m_ArchiveHeader.Size - NHeader::NArchive::kArchiveHeaderSize;
|
||||
archiveInfo.CommentSize = (UInt16)(m_ArchiveHeader.Size - NHeader::NArchive::kArchiveHeaderSize);
|
||||
}
|
||||
|
||||
static void DecodeUnicodeFileName(const char *name, const Byte *encName,
|
||||
@@ -221,10 +220,10 @@ static void DecodeUnicodeFileName(const char *name, const Byte *encName,
|
||||
unicodeName[decPos++] = encName[encPos++];
|
||||
break;
|
||||
case 1:
|
||||
unicodeName[decPos++] = encName[encPos++] + (highByte << 8);
|
||||
unicodeName[decPos++] = (wchar_t)(encName[encPos++] + (highByte << 8));
|
||||
break;
|
||||
case 2:
|
||||
unicodeName[decPos++] = encName[encPos] + (encName[encPos + 1] << 8);
|
||||
unicodeName[decPos++] = (wchar_t)(encName[encPos] + (encName[encPos + 1] << 8));
|
||||
encPos += 2;
|
||||
break;
|
||||
case 3:
|
||||
@@ -235,7 +234,7 @@ static void DecodeUnicodeFileName(const char *name, const Byte *encName,
|
||||
Byte correction = encName[encPos++];
|
||||
for (length = (length & 0x7f) + 2;
|
||||
length > 0 && decPos < maxDecSize; length--, decPos++)
|
||||
unicodeName[decPos] = ((name[decPos] + correction) & 0xff) + (highByte << 8);
|
||||
unicodeName[decPos] = (wchar_t)(((name[decPos] + correction) & 0xff) + (highByte << 8));
|
||||
}
|
||||
else
|
||||
for (length += 2; length > 0 && decPos < maxDecSize; length--, decPos++)
|
||||
@@ -316,7 +315,7 @@ UInt32 CInArchive::ReadUInt32()
|
||||
|
||||
void CInArchive::ReadTime(Byte mask, CRarTime &rarTime)
|
||||
{
|
||||
rarTime.LowSecond = ((mask & 4) != 0) ? 1 : 0;
|
||||
rarTime.LowSecond = (Byte)(((mask & 4) != 0) ? 1 : 0);
|
||||
int numDigits = (mask & 3);
|
||||
rarTime.SubTime[0] = rarTime.SubTime[1] = rarTime.SubTime[2] = 0;
|
||||
for (int i = 0; i < numDigits; i++)
|
||||
@@ -353,20 +352,23 @@ void CInArchive::ReadHeaderReal(CItemEx &item)
|
||||
for (int i = 0; i < sizeof(item.Salt); i++)
|
||||
item.Salt[i] = ReadByte();
|
||||
|
||||
if (item.HasExtTime())
|
||||
// some rar archives have HasExtTime flag without field.
|
||||
if (m_CurPos < m_PosLimit && item.HasExtTime())
|
||||
{
|
||||
Byte accessMask = ReadByte() >> 4;
|
||||
Byte accessMask = (Byte)(ReadByte() >> 4);
|
||||
Byte b = ReadByte();
|
||||
Byte modifMask = b >> 4;
|
||||
Byte createMask = b & 0xF;
|
||||
Byte modifMask = (Byte)(b >> 4);
|
||||
Byte createMask = (Byte)(b & 0xF);
|
||||
if ((modifMask & 8) != 0)
|
||||
ReadTime(modifMask, item.LastWriteTime);
|
||||
if (item.IsCreationTimeDefined = ((createMask & 8) != 0))
|
||||
item.IsCreationTimeDefined = ((createMask & 8) != 0);
|
||||
if (item.IsCreationTimeDefined)
|
||||
{
|
||||
item.CreationTime.DosTime = ReadUInt32();
|
||||
ReadTime(createMask, item.CreationTime);
|
||||
}
|
||||
if (item.IsLastAccessTimeDefined = ((accessMask & 8) != 0))
|
||||
item.IsLastAccessTimeDefined = ((accessMask & 8) != 0);
|
||||
if (item.IsLastAccessTimeDefined)
|
||||
{
|
||||
item.LastAccessTime.DosTime = ReadUInt32();
|
||||
ReadTime(accessMask, item.LastAccessTime);
|
||||
@@ -377,10 +379,10 @@ void CInArchive::ReadHeaderReal(CItemEx &item)
|
||||
|
||||
item.Position = m_Position;
|
||||
item.MainPartSize = fileHeaderWithNameSize;
|
||||
item.CommentSize = m_BlockHeader.HeadSize - fileHeaderWithNameSize;
|
||||
item.CommentSize = (UInt16)(m_BlockHeader.HeadSize - fileHeaderWithNameSize);
|
||||
|
||||
if (m_CryptoMode)
|
||||
item.AlignSize = (16 - ((m_BlockHeader.HeadSize) & 0xF)) & 0xF;
|
||||
item.AlignSize = (UInt16)((16 - ((m_BlockHeader.HeadSize) & 0xF)) & 0xF);
|
||||
else
|
||||
item.AlignSize = 0;
|
||||
AddToSeekValue(m_BlockHeader.HeadSize);
|
||||
@@ -395,7 +397,7 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa
|
||||
{
|
||||
if (m_SeekOnArchiveComment)
|
||||
SkipArchiveComment();
|
||||
while (true)
|
||||
for (;;)
|
||||
{
|
||||
if(!SeekInArchive(m_Position))
|
||||
return S_FALSE;
|
||||
@@ -525,7 +527,8 @@ ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 siz
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> inStream(streamSpec);
|
||||
SeekInArchive(position);
|
||||
streamSpec->Init(m_Stream, size);
|
||||
streamSpec->SetStream(m_Stream);
|
||||
streamSpec->Init(size);
|
||||
return inStream.Detach();
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,17 @@ UInt32 CItem::GetDictSize() const
|
||||
|
||||
bool CItem::IsDirectory() const
|
||||
{
|
||||
return (GetDictSize() == NHeader::NFile::kDictDirectoryValue);
|
||||
if (GetDictSize() == NHeader::NFile::kDictDirectoryValue)
|
||||
return true;
|
||||
switch(HostOS)
|
||||
{
|
||||
case NHeader::NFile::kHostMSDOS:
|
||||
case NHeader::NFile::kHostOS2:
|
||||
case NHeader::NFile::kHostWin32:
|
||||
if ((Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
UInt32 CItem::GetWinAttributes() const
|
||||
@@ -68,41 +78,41 @@ UInt32 CItem::GetWinAttributes() const
|
||||
void CItem::ClearFlags()
|
||||
{ Flags = 0; }
|
||||
|
||||
void CItem::SetFlagBits(int aStartBitNumber, int aNumBits, int aValue)
|
||||
void CItem::SetFlagBits(int startBitNumber, int numBits, int value)
|
||||
{
|
||||
UInt16 mask = ((1 << aNumBits) - 1) << aStartBitNumber;
|
||||
UInt16 mask = (UInt16)(((1 << numBits) - 1) << startBitNumber);
|
||||
Flags &= ~mask;
|
||||
Flags |= aValue << aStartBitNumber;
|
||||
Flags |= value << startBitNumber;
|
||||
}
|
||||
|
||||
void CItem::SetBitMask(int aBitMask, bool anEnable)
|
||||
void CItem::SetBitMask(int bitMask, bool enable)
|
||||
{
|
||||
if(anEnable)
|
||||
Flags |= aBitMask;
|
||||
if(enable)
|
||||
Flags |= bitMask;
|
||||
else
|
||||
Flags &= ~aBitMask;
|
||||
Flags &= ~bitMask;
|
||||
}
|
||||
|
||||
void CItem::SetDictSize(UInt32 aSize)
|
||||
void CItem::SetDictSize(UInt32 size)
|
||||
{
|
||||
SetFlagBits(NHeader::NFile::kDictBitStart, NHeader::NFile::kNumDictBits, (aSize & NHeader::NFile::kDictMask));
|
||||
SetFlagBits(NHeader::NFile::kDictBitStart, NHeader::NFile::kNumDictBits, (size & NHeader::NFile::kDictMask));
|
||||
}
|
||||
|
||||
void CItem::SetAsDirectory(bool aDirectory)
|
||||
void CItem::SetAsDirectory(bool directory)
|
||||
{
|
||||
if (aDirectory)
|
||||
if (directory)
|
||||
SetDictSize(NHeader::NFile::kDictDirectoryValue);
|
||||
}
|
||||
|
||||
void CItem::SetEncrypted(bool anEncrypted)
|
||||
{ SetBitMask(NHeader::NFile::kEncrypted, anEncrypted); }
|
||||
void CItem::SetSolid(bool aSolid)
|
||||
{ SetBitMask(NHeader::NFile::kSolid, aSolid); }
|
||||
void CItem::SetCommented(bool aCommented)
|
||||
{ SetBitMask(NHeader::NFile::kComment, aCommented); }
|
||||
void CItem::SetSplitBefore(bool aSplitBefore)
|
||||
{ SetBitMask(NHeader::NFile::kSplitBefore, aSplitBefore); }
|
||||
void CItem::SetSplitAfter(bool aSplitAfter)
|
||||
{ SetBitMask(NHeader::NFile::kSplitAfter, aSplitAfter); }
|
||||
void CItem::SetEncrypted(bool encrypted)
|
||||
{ SetBitMask(NHeader::NFile::kEncrypted, encrypted); }
|
||||
void CItem::SetSolid(bool solid)
|
||||
{ SetBitMask(NHeader::NFile::kSolid, solid); }
|
||||
void CItem::SetCommented(bool commented)
|
||||
{ SetBitMask(NHeader::NFile::kComment, commented); }
|
||||
void CItem::SetSplitBefore(bool splitBefore)
|
||||
{ SetBitMask(NHeader::NFile::kSplitBefore, splitBefore); }
|
||||
void CItem::SetSplitAfter(bool splitAfter)
|
||||
{ SetBitMask(NHeader::NFile::kSplitAfter, splitAfter); }
|
||||
|
||||
}}
|
||||
|
||||
@@ -58,17 +58,17 @@ public:
|
||||
|
||||
CItem(): IsCreationTimeDefined(false), IsLastAccessTimeDefined(false) {}
|
||||
private:
|
||||
void SetFlagBits(int aStartBitNumber, int aNumBits, int aValue);
|
||||
void SetBitMask(int aBitMask, bool anEnable);
|
||||
void SetFlagBits(int startBitNumber, int numBits, int value);
|
||||
void SetBitMask(int bitMask, bool enable);
|
||||
public:
|
||||
void ClearFlags();
|
||||
void SetDictSize(UInt32 aSize);
|
||||
void SetAsDirectory(bool aDirectory);
|
||||
void SetEncrypted(bool anEncrypted);
|
||||
void SetSolid(bool aSolid);
|
||||
void SetCommented(bool aCommented);
|
||||
void SetSplitBefore(bool aSplitBefore);
|
||||
void SetSplitAfter(bool aSplitAfter);
|
||||
void SetDictSize(UInt32 size);
|
||||
void SetAsDirectory(bool directory);
|
||||
void SetEncrypted(bool encrypted);
|
||||
void SetSolid(bool solid);
|
||||
void SetCommented(bool commented);
|
||||
void SetSplitBefore(bool splitBefore);
|
||||
void SetSplitAfter(bool splitAfter);
|
||||
};
|
||||
|
||||
class CItemEx: public CItem
|
||||
|
||||
@@ -42,13 +42,15 @@ AR_COMMON_OBJS = \
|
||||
$O\7zMethodID.obj \
|
||||
$O\7zMethods.obj \
|
||||
|
||||
CRYPTO_HASH_OBJS = \
|
||||
$O\Sha1.obj \
|
||||
|
||||
CRYPTO_RAR20_OBJS = \
|
||||
$O\Rar20Cipher.obj \
|
||||
$O\Rar20Crypto.obj \
|
||||
|
||||
CRYPTO_RARAES_OBJS = \
|
||||
$O\RarAES.obj \
|
||||
$O\sha1.obj \
|
||||
|
||||
OBJS = \
|
||||
$O\StdAfx.obj \
|
||||
@@ -58,6 +60,7 @@ OBJS = \
|
||||
$(7ZIP_COMMON_OBJS) \
|
||||
$(AR_COMMON_OBJS) \
|
||||
$(7Z_OBJS) \
|
||||
$(CRYPTO_HASH_OBJS) \
|
||||
$(CRYPTO_RAR20_OBJS) \
|
||||
$(CRYPTO_RARAES_OBJS) \
|
||||
$O\CopyCoder.obj \
|
||||
@@ -77,6 +80,8 @@ $(AR_COMMON_OBJS): ../Common/$(*B).cpp
|
||||
$(COMPL)
|
||||
$(7Z_OBJS): ../7z/$(*B).cpp
|
||||
$(COMPL)
|
||||
$(CRYPTO_HASH_OBJS): ../../Crypto/Hash/$(*B).cpp
|
||||
$(COMPL_O2)
|
||||
$(CRYPTO_RAR20_OBJS): ../../Crypto/Rar20/$(*B).cpp
|
||||
$(COMPL)
|
||||
$(CRYPTO_RARAES_OBJS): ../../Crypto/RarAES/$(*B).cpp
|
||||
|
||||
@@ -13,9 +13,9 @@ DEFINE_GUID(CLSID_CSplitHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEA, 0x00, 0x00);
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /* lpReserved */)
|
||||
{
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
STDAPI CreateObject(
|
||||
|
||||
@@ -31,7 +31,7 @@ STATPROPSTG kProperties[] =
|
||||
{ NULL, kpidPackedSize, VT_UI8},
|
||||
};
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value)
|
||||
{
|
||||
value->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
@@ -61,8 +61,8 @@ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */,
|
||||
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
@@ -142,7 +142,7 @@ public:
|
||||
};
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback *openArchiveCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
@@ -235,7 +235,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
|
||||
}
|
||||
|
||||
while (true)
|
||||
for (;;)
|
||||
{
|
||||
UString fullName = seqName.GetNextName();
|
||||
CMyComPtr<IInStream> nextStream;
|
||||
@@ -286,7 +286,7 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant propVariant;
|
||||
|
||||
@@ -13,7 +13,7 @@ DEFINE_GUID(CLSID_CTarHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEE, 0x00, 0x00);
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /* lpReserved */)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ STATPROPSTG kProperties[] =
|
||||
{ NULL, kpidGroup, VT_BSTR},
|
||||
};
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value)
|
||||
{
|
||||
value->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
@@ -66,14 +66,14 @@ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */,
|
||||
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback *openArchiveCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
@@ -93,7 +93,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
|
||||
}
|
||||
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
CItemEx item;
|
||||
bool filled;
|
||||
@@ -242,7 +242,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
RINOK(_inStream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL));
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> inStream(streamSpec);
|
||||
streamSpec->Init(_inStream, item.Size);
|
||||
streamSpec->SetStream(_inStream);
|
||||
streamSpec->Init(item.Size);
|
||||
|
||||
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace NFileHeader {
|
||||
const char *kCheckSumBlanks = " "; // 8 blanks, no null
|
||||
|
||||
const char *kLongLink = "././@LongLink";
|
||||
const char *kLongLink2 = "@LongLink";
|
||||
|
||||
// The magic field is filled with this if uname and gname are valid.
|
||||
namespace NMagic
|
||||
|
||||
@@ -81,7 +81,8 @@ namespace NFileHeader
|
||||
// The checksum field is filled with this while the checksum is computed.
|
||||
extern const char *kCheckSumBlanks;// = " "; // 8 blanks, no null
|
||||
|
||||
extern const char *kLongLink; // = "././@LongLink";
|
||||
extern const char *kLongLink; // = "././@LongLink";
|
||||
extern const char *kLongLink2; // = "@LongLink";
|
||||
|
||||
// The magic field is filled with this if uname and gname are valid.
|
||||
namespace NMagic
|
||||
|
||||
@@ -27,10 +27,21 @@ HRESULT CInArchive::Open(IInStream *inStream)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void MyStrNCpy(char *dest, const char *src, int size)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
char c = src[i];
|
||||
dest[i] = c;
|
||||
if (c == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool OctalToNumber(const char *srcString, int size, UInt64 &res)
|
||||
{
|
||||
char sz[32];
|
||||
strncpy(sz, srcString, size);
|
||||
MyStrNCpy(sz, srcString, size);
|
||||
sz[size] = 0;
|
||||
const char *end;
|
||||
int i;
|
||||
@@ -63,14 +74,14 @@ static void ReadString(const char *s, int size, AString &result)
|
||||
if (size > NFileHeader::kRecordSize)
|
||||
size = NFileHeader::kNameSize;
|
||||
char tempString[NFileHeader::kRecordSize + 1];
|
||||
strncpy(tempString, s, size);
|
||||
MyStrNCpy(tempString, s, size);
|
||||
tempString[size] = '\0';
|
||||
result = tempString;
|
||||
}
|
||||
|
||||
static char GetHex(Byte value)
|
||||
{
|
||||
return (value < 10) ? ('0' + value) : ('A' + (value - 10));
|
||||
return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
|
||||
}
|
||||
|
||||
HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item)
|
||||
@@ -109,8 +120,8 @@ HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item)
|
||||
if (((Byte)c) < 0x20)
|
||||
{
|
||||
item.Name += '[';
|
||||
item.Name += GetHex(((Byte)c) >> 4);
|
||||
item.Name += GetHex(((Byte)c) & 0xF);
|
||||
item.Name += GetHex((Byte)(((Byte)c) >> 4));
|
||||
item.Name += GetHex((Byte)(((Byte)c) & 0xF));
|
||||
item.Name += ']';
|
||||
}
|
||||
else
|
||||
@@ -190,7 +201,8 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
|
||||
if (item.LinkFlag == 'L')
|
||||
{
|
||||
if (item.Name.Compare(NFileHeader::kLongLink) != 0)
|
||||
return S_FALSE;
|
||||
if (item.Name.Compare(NFileHeader::kLongLink2) != 0)
|
||||
return S_FALSE;
|
||||
UInt64 headerPosition = item.HeaderPosition;
|
||||
|
||||
UInt32 processedSize;
|
||||
|
||||
@@ -33,6 +33,17 @@ static AString MakeOctalString(UInt64 value)
|
||||
return AString(s) + ' ';
|
||||
}
|
||||
|
||||
static void MyStrNCpy(char *dest, const char *src, int size)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
char c = src[i];
|
||||
dest[i] = c;
|
||||
if (c == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool MakeOctalString8(char *s, UInt32 value)
|
||||
{
|
||||
AString tempString = MakeOctalString(value);
|
||||
@@ -43,7 +54,7 @@ static bool MakeOctalString8(char *s, UInt32 value)
|
||||
int numSpaces = kMaxSize - (tempString.Length() + 1);
|
||||
for(int i = 0; i < numSpaces; i++)
|
||||
s[i] = ' ';
|
||||
strcpy(s + numSpaces, tempString);
|
||||
MyStringCopy(s + numSpaces, (const char *)tempString);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -64,7 +75,7 @@ static bool CopyString(char *dest, const AString &src, int maxSize)
|
||||
{
|
||||
if (src.Length() >= maxSize)
|
||||
return false;
|
||||
strcpy(dest, src);
|
||||
MyStringCopy(dest, (const char *)src);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -81,7 +92,7 @@ HRESULT COutArchive::WriteHeaderReal(const CItem &item)
|
||||
// RETURN_IF_NOT_TRUE(CopyString(header.Name, item.Name, NFileHeader::kNameSize));
|
||||
if (item.Name.Length() > NFileHeader::kNameSize)
|
||||
return E_FAIL;
|
||||
strncpy(cur, item.Name, NFileHeader::kNameSize);
|
||||
MyStrNCpy(cur, item.Name, NFileHeader::kNameSize);
|
||||
cur += NFileHeader::kNameSize;
|
||||
|
||||
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.Mode));
|
||||
|
||||
@@ -139,13 +139,15 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
RINOK(outArchive.WriteHeader(item));
|
||||
RINOK(inStream->Seek(existItemInfo.GetDataPosition(),
|
||||
STREAM_SEEK_SET, NULL));
|
||||
streamSpec->Init(inStream, existItemInfo.Size);
|
||||
streamSpec->SetStream(inStream);
|
||||
streamSpec->Init(existItemInfo.Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(inStream->Seek(existItemInfo.HeaderPosition,
|
||||
STREAM_SEEK_SET, NULL));
|
||||
streamSpec->Init(inStream, existItemInfo.GetFullSize());
|
||||
streamSpec->SetStream(inStream);
|
||||
streamSpec->Init(existItemInfo.GetFullSize());
|
||||
}
|
||||
RINOK(CopyBlock(inStreamLimited, outStream, compressProgress));
|
||||
RINOK(outArchive.FillDataResidual(existItemInfo.Size));
|
||||
|
||||
@@ -12,13 +12,9 @@
|
||||
DEFINE_GUID(CLSID_CZHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x05, 0x00, 0x00);
|
||||
|
||||
HINSTANCE g_hInstance;
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /* lpReserved */)
|
||||
{
|
||||
if (dwReason == DLL_PROCESS_ATTACH)
|
||||
g_hInstance = hInstance;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ STATPROPSTG kProperties[] =
|
||||
{ NULL, kpidPackedSize, VT_UI8},
|
||||
};
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value)
|
||||
{
|
||||
value->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
@@ -55,8 +55,8 @@ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */,
|
||||
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
@@ -90,8 +90,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
static const int kSignatureSize = 3;
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *openArchiveCallback)
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback * /* openArchiveCallback */)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
try
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include "Windows/PropVariant.h"
|
||||
#include "../../ICoder.h"
|
||||
#include "../../IPassword.h"
|
||||
#include "../../Crypto/WzAES/WzAES.h"
|
||||
#include "../Common/CodecsPath.h"
|
||||
|
||||
// {23170F69-40C1-278B-0401-080000000100}
|
||||
DEFINE_GUID(CLSID_CCompressDeflateEncoder,
|
||||
@@ -62,6 +64,12 @@ static bool IsItWindowsNT()
|
||||
}
|
||||
#endif
|
||||
|
||||
void GetCryptoFolderPrefix(TCHAR *path)
|
||||
{
|
||||
CSysString s = GetCodecsFolderPrefix();
|
||||
lstrcpy(path, s);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
{
|
||||
|
||||
@@ -142,6 +142,14 @@ SOURCE=..\..\..\Common\CRC.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\IntToString.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\IntToString.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\NewHandler.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -216,6 +224,18 @@ SOURCE=..\..\..\Windows\PropVariant.cpp
|
||||
|
||||
SOURCE=..\..\..\Windows\PropVariant.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\Synchronization.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\Synchronization.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\Thread.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Archive Common"
|
||||
|
||||
@@ -306,6 +326,14 @@ SOURCE=..\..\Common\LSBFDecoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\MemBlocks.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\MemBlocks.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\OffsetStream.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -322,6 +350,22 @@ SOURCE=..\..\Common\OutBuffer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\OutMemStream.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\OutMemStream.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\ProgressMt.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\ProgressMt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\ProgressUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -420,6 +464,88 @@ SOURCE=.\ZipUpdate.h
|
||||
# Begin Group "Crypto"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Group "WzAes"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\WzAES\WzAES.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\WzAES\WzAES.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Hash"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\Hash\HmacSha1.cpp
|
||||
|
||||
!IF "$(CFG)" == "Zip - Win32 Release"
|
||||
|
||||
# ADD CPP /O2
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Zip - Win32 Debug"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\Hash\HmacSha1.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\Hash\Pbkdf2HmacSha1.cpp
|
||||
|
||||
!IF "$(CFG)" == "Zip - Win32 Release"
|
||||
|
||||
# ADD CPP /O2
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Zip - Win32 Debug"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\Hash\Pbkdf2HmacSha1.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\Hash\RandGen.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\Hash\RandGen.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\Hash\RotateDefs.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\Hash\Sha1.cpp
|
||||
|
||||
!IF "$(CFG)" == "Zip - Win32 Release"
|
||||
|
||||
# ADD CPP /O2
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Zip - Win32 Debug"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\Hash\Sha1.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\Zip\ZipCipher.cpp
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "Windows/Defs.h"
|
||||
#include "../../ICoder.h"
|
||||
#include "../../IPassword.h"
|
||||
#include "../Common/InStreamWithCRC.h"
|
||||
#include "../7z/7zMethods.h"
|
||||
|
||||
#include "ZipAddCommon.h"
|
||||
@@ -48,9 +49,6 @@ DEFINE_GUID(CLSID_CCryptoZipEncoder,
|
||||
namespace NArchive {
|
||||
namespace NZip {
|
||||
|
||||
static const Byte kMethodIDForEmptyStream = NFileHeader::NCompressionMethod::kStored;
|
||||
static const Byte kExtractVersionForEmptyStream = NFileHeader::NCompressionMethod::kStoreExtractVersion;
|
||||
|
||||
CAddCommon::CAddCommon(const CCompressionMethodMode &options):
|
||||
_options(options),
|
||||
_copyCoderSpec(NULL),
|
||||
@@ -63,7 +61,7 @@ static HRESULT GetStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC)
|
||||
crc.Init();
|
||||
const UInt32 kBufferSize = (1 << 14);
|
||||
Byte buffer[kBufferSize];
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
RINOK(inStream->Read(buffer, kBufferSize, &realProcessedSize));
|
||||
@@ -77,36 +75,47 @@ static HRESULT GetStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC)
|
||||
}
|
||||
|
||||
HRESULT CAddCommon::Compress(ISequentialInStream *inStream, IOutStream *outStream,
|
||||
UInt64 inSize, ICompressProgressInfo *progress, CCompressingResult &operationResult)
|
||||
ICompressProgressInfo *progress, CCompressingResult &operationResult)
|
||||
{
|
||||
/*
|
||||
if(inSize == 0)
|
||||
CSequentialInStreamWithCRC *inSecCrcStreamSpec = 0;
|
||||
CInStreamWithCRC *inCrcStreamSpec = 0;
|
||||
CMyComPtr<ISequentialInStream> inCrcStream;
|
||||
{
|
||||
operationResult.PackSize = 0;
|
||||
operationResult.Method = kMethodIDForEmptyStream;
|
||||
operationResult.ExtractVersion = kExtractVersionForEmptyStream;
|
||||
return S_OK;
|
||||
CMyComPtr<IInStream> inStream2;
|
||||
// we don't support stdin, since stream from stdin can require 64-bit size header
|
||||
RINOK(inStream->QueryInterface(IID_IInStream, (void **)&inStream2));
|
||||
if (inStream2)
|
||||
{
|
||||
inCrcStreamSpec = new CInStreamWithCRC;
|
||||
inCrcStream = inCrcStreamSpec;
|
||||
inCrcStreamSpec->SetStream(inStream2);
|
||||
inCrcStreamSpec->Init();
|
||||
}
|
||||
else
|
||||
{
|
||||
inSecCrcStreamSpec = new CSequentialInStreamWithCRC;
|
||||
inCrcStream = inSecCrcStreamSpec;
|
||||
inSecCrcStreamSpec->SetStream(inStream);
|
||||
inSecCrcStreamSpec->Init();
|
||||
}
|
||||
}
|
||||
*/
|
||||
CMyComPtr<IInStream> inStream2;
|
||||
|
||||
int numTestMethods = _options.MethodSequence.Size();
|
||||
if (numTestMethods > 1 || _options.PasswordIsDefined)
|
||||
{
|
||||
inStream->QueryInterface(IID_IInStream, (void **)&inStream2);
|
||||
if (!inStream2)
|
||||
if (inCrcStreamSpec == 0)
|
||||
{
|
||||
if (_options.PasswordIsDefined)
|
||||
return E_NOTIMPL;
|
||||
numTestMethods = 1;
|
||||
}
|
||||
}
|
||||
Byte method;
|
||||
UInt64 resultSize = 0;
|
||||
Byte method = 0;
|
||||
COutStreamReleaser outStreamReleaser;
|
||||
for(int i = 0; i < numTestMethods; i++)
|
||||
{
|
||||
if (inStream2)
|
||||
RINOK(inStream2->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
if (inCrcStreamSpec != 0)
|
||||
RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
if (_options.PasswordIsDefined)
|
||||
{
|
||||
@@ -114,18 +123,28 @@ HRESULT CAddCommon::Compress(ISequentialInStream *inStream, IOutStream *outStrea
|
||||
{
|
||||
_cryptoStreamSpec = new CFilterCoder;
|
||||
_cryptoStream = _cryptoStreamSpec;
|
||||
_filterSpec = new NCrypto::NZip::CEncoder;
|
||||
_cryptoStreamSpec->Filter = _filterSpec;
|
||||
}
|
||||
RINOK(_filterSpec->CryptoSetPassword(
|
||||
(const Byte *)(const char *)_options.Password, _options.Password.Length()));
|
||||
UInt32 crc;
|
||||
RINOK(GetStreamCRC(inStream, crc));
|
||||
RINOK(inStream2->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
if (_options.IsAesMode)
|
||||
{
|
||||
_cryptoStreamSpec->Filter = _aesFilter = _filterAesSpec = new NCrypto::NWzAES::CEncoder;
|
||||
_filterAesSpec->SetKeyMode(_options.AesKeyMode);
|
||||
RINOK(_filterAesSpec->CryptoSetPassword(
|
||||
(const Byte *)(const char *)_options.Password, _options.Password.Length()));
|
||||
RINOK(_filterAesSpec->WriteHeader(outStream));
|
||||
}
|
||||
else
|
||||
{
|
||||
_cryptoStreamSpec->Filter = _zipCryptoFilter = _filterSpec = new NCrypto::NZip::CEncoder;
|
||||
RINOK(_filterSpec->CryptoSetPassword(
|
||||
(const Byte *)(const char *)_options.Password, _options.Password.Length()));
|
||||
UInt32 crc = 0;
|
||||
RINOK(GetStreamCRC(inStream, crc));
|
||||
RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
RINOK(_filterSpec->CryptoSetCRC(crc));
|
||||
RINOK(_filterSpec->WriteHeader(outStream));
|
||||
}
|
||||
RINOK(_cryptoStreamSpec->SetOutStream(outStream));
|
||||
outStreamReleaser.FilterCoder = _cryptoStreamSpec;
|
||||
RINOK(_filterSpec->CryptoSetCRC(crc));
|
||||
RINOK(_filterSpec->WriteHeader(outStream));
|
||||
}
|
||||
|
||||
method = _options.MethodSequence[i];
|
||||
@@ -143,8 +162,7 @@ HRESULT CAddCommon::Compress(ISequentialInStream *inStream, IOutStream *outStrea
|
||||
outStreamNew = _cryptoStream;
|
||||
else
|
||||
outStreamNew = outStream;
|
||||
RINOK(_copyCoder->Code(inStream, outStreamNew,
|
||||
NULL, NULL, progress));
|
||||
RINOK(_copyCoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress));
|
||||
operationResult.ExtractVersion = NFileHeader::NCompressionMethod::kStoreExtractVersion;
|
||||
break;
|
||||
}
|
||||
@@ -251,24 +269,41 @@ HRESULT CAddCommon::Compress(ISequentialInStream *inStream, IOutStream *outStrea
|
||||
outStreamNew = _cryptoStream;
|
||||
else
|
||||
outStreamNew = outStream;
|
||||
RINOK(_compressEncoder->Code(inStream, outStreamNew, NULL, NULL, progress));
|
||||
RINOK(_compressEncoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress));
|
||||
operationResult.ExtractVersion = NFileHeader::NCompressionMethod::kDeflateExtractVersion;
|
||||
break;
|
||||
}
|
||||
}
|
||||
outStream->Seek(0, STREAM_SEEK_CUR, &resultSize);
|
||||
|
||||
RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &operationResult.PackSize));
|
||||
|
||||
if (inCrcStreamSpec != 0)
|
||||
{
|
||||
operationResult.CRC = inCrcStreamSpec->GetCRC();
|
||||
operationResult.UnpackSize = inCrcStreamSpec->GetSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
operationResult.CRC = inSecCrcStreamSpec->GetCRC();
|
||||
operationResult.UnpackSize = inSecCrcStreamSpec->GetSize();
|
||||
}
|
||||
|
||||
if (_options.PasswordIsDefined)
|
||||
{
|
||||
if(resultSize < inSize + 12)
|
||||
if (operationResult.PackSize < operationResult.UnpackSize +
|
||||
(_options.IsAesMode ? _filterAesSpec->GetHeaderSize() : NCrypto::NZip::kHeaderSize))
|
||||
break;
|
||||
}
|
||||
else if(resultSize < inSize)
|
||||
else if (operationResult.PackSize < operationResult.UnpackSize)
|
||||
break;
|
||||
}
|
||||
RINOK(outStream->SetSize(resultSize));
|
||||
operationResult.PackSize = resultSize;
|
||||
if (_options.IsAesMode)
|
||||
{
|
||||
RINOK(_filterAesSpec->WriteFooter(outStream));
|
||||
RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &operationResult.PackSize));
|
||||
}
|
||||
operationResult.Method = method;
|
||||
return S_OK;
|
||||
return outStream->SetSize(operationResult.PackSize);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -12,14 +12,17 @@
|
||||
#include "../Common/FilterCoder.h"
|
||||
#include "ZipCompressionMode.h"
|
||||
#include "../../Crypto/Zip/ZipCipher.h"
|
||||
#include "../../Crypto/WzAES/WzAES.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NZip {
|
||||
|
||||
struct CCompressingResult
|
||||
{
|
||||
Byte Method;
|
||||
UInt64 UnpackSize;
|
||||
UInt64 PackSize;
|
||||
UInt32 CRC;
|
||||
UInt16 Method;
|
||||
Byte ExtractVersion;
|
||||
};
|
||||
|
||||
@@ -38,11 +41,16 @@ class CAddCommon
|
||||
CMyComPtr<ISequentialOutStream> _cryptoStream;
|
||||
|
||||
NCrypto::NZip::CEncoder *_filterSpec;
|
||||
NCrypto::NWzAES::CEncoder *_filterAesSpec;
|
||||
|
||||
CMyComPtr<ICompressFilter> _zipCryptoFilter;
|
||||
CMyComPtr<ICompressFilter> _aesFilter;
|
||||
|
||||
|
||||
public:
|
||||
CAddCommon(const CCompressionMethodMode &options);
|
||||
HRESULT Compress(ISequentialInStream *inStream, IOutStream *outStream,
|
||||
UInt64 inSize, ICompressProgressInfo *progress, CCompressingResult &operationResult);
|
||||
ICompressProgressInfo *progress, CCompressingResult &operationResult);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -23,7 +23,15 @@ struct CCompressionMethodMode
|
||||
#endif
|
||||
bool PasswordIsDefined;
|
||||
AString Password;
|
||||
CCompressionMethodMode(): NumMatchFinderCyclesDefined(false) {}
|
||||
bool IsAesMode;
|
||||
Byte AesKeyMode;
|
||||
|
||||
CCompressionMethodMode():
|
||||
NumMatchFinderCyclesDefined(false),
|
||||
PasswordIsDefined(false),
|
||||
IsAesMode(false),
|
||||
AesKeyMode(3)
|
||||
{}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "Common/CRC.h"
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Common/ComTry.h"
|
||||
#include "Common/IntToString.h"
|
||||
|
||||
#include "Windows/Time.h"
|
||||
#include "Windows/PropVariant.h"
|
||||
@@ -61,6 +62,7 @@ DEFINE_GUID(CLSID_CCompressBZip2Decoder,
|
||||
#endif
|
||||
|
||||
#include "../../Crypto/Zip/ZipCipher.h"
|
||||
#include "../../Crypto/WzAES/WzAES.h"
|
||||
|
||||
#ifndef EXCLUDE_COM
|
||||
#include "../Common/CoderLoader.h"
|
||||
@@ -147,8 +149,10 @@ const wchar_t *kMethods[] =
|
||||
};
|
||||
|
||||
const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]);
|
||||
const wchar_t *kUnknownMethod = L"Unknown";
|
||||
// const wchar_t *kUnknownMethod = L"Unknown";
|
||||
const wchar_t *kPPMdMethod = L"PPMd";
|
||||
const wchar_t *kAESMethod = L"AES";
|
||||
const wchar_t *kZipCryptoMethod = L"ZipCrypto";
|
||||
|
||||
CHandler::CHandler():
|
||||
m_ArchiveIsOpen(false)
|
||||
@@ -156,7 +160,7 @@ CHandler::CHandler():
|
||||
InitMethodProperties();
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value)
|
||||
{
|
||||
value->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
@@ -186,8 +190,8 @@ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */,
|
||||
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
@@ -198,6 +202,17 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void MyStrNCpy(char *dest, const char *src, int size)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
char c = src[i];
|
||||
dest[i] = c;
|
||||
if (c == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID aPropID, PROPVARIANT *aValue)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
@@ -244,7 +259,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID aPropID, PROPVARIANT *a
|
||||
{
|
||||
AString s;
|
||||
char *p = s.GetBuffer(size + 1);
|
||||
strncpy(p, (const char *)(const Byte *)item.Comment, size);
|
||||
MyStrNCpy(p, (const char *)(const Byte *)item.Comment, size);
|
||||
p[size] = '\0';
|
||||
s.ReleaseBuffer();
|
||||
propVariant = MultiByteToUnicodeString(s, item.GetCodePage());
|
||||
@@ -252,19 +267,46 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID aPropID, PROPVARIANT *a
|
||||
break;
|
||||
}
|
||||
case kpidCRC:
|
||||
propVariant = item.FileCRC;
|
||||
if (item.IsThereCrc())
|
||||
propVariant = item.FileCRC;
|
||||
break;
|
||||
case kpidMethod:
|
||||
{
|
||||
UInt16 methodId = item.CompressionMethod;
|
||||
UString method;
|
||||
if (item.CompressionMethod < kNumMethods)
|
||||
method = kMethods[item.CompressionMethod];
|
||||
else if (item.CompressionMethod == NFileHeader::NCompressionMethod::kWinZipPPMd)
|
||||
method = kPPMdMethod;
|
||||
if (item.IsEncrypted())
|
||||
{
|
||||
if (methodId == NFileHeader::NCompressionMethod::kWzAES)
|
||||
{
|
||||
method = kAESMethod;
|
||||
CWzAesExtraField aesField;
|
||||
if (item.CentralExtra.GetWzAesField(aesField))
|
||||
{
|
||||
method += L"-";
|
||||
wchar_t s[32];
|
||||
ConvertUInt64ToString((aesField.Strength + 1) * 64 , s);
|
||||
method += s;
|
||||
method += L" ";
|
||||
methodId = aesField.Method;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
method += kZipCryptoMethod;
|
||||
method += L" ";
|
||||
}
|
||||
}
|
||||
if (methodId < kNumMethods)
|
||||
method += kMethods[methodId];
|
||||
else if (methodId == NFileHeader::NCompressionMethod::kWzPPMd)
|
||||
method += kPPMdMethod;
|
||||
else
|
||||
method = kUnknownMethod;
|
||||
{
|
||||
wchar_t s[32];
|
||||
ConvertUInt64ToString(methodId, s);
|
||||
method += s;
|
||||
}
|
||||
propVariant = method;
|
||||
// propVariant = item.CompressionMethod;
|
||||
break;
|
||||
}
|
||||
case kpidHostOS:
|
||||
@@ -334,17 +376,303 @@ STDMETHODIMP CHandler::Close()
|
||||
|
||||
struct CMethodItem
|
||||
{
|
||||
Byte ZipMethod;
|
||||
UInt16 ZipMethod;
|
||||
CMyComPtr<ICompressCoder> Coder;
|
||||
};
|
||||
|
||||
class CZipDecoder
|
||||
{
|
||||
NCrypto::NZip::CDecoder *_zipCryptoDecoderSpec;
|
||||
NCrypto::NWzAES::CDecoder *_aesDecoderSpec;
|
||||
CMyComPtr<ICompressFilter> _zipCryptoDecoder;
|
||||
CMyComPtr<ICompressFilter> _aesDecoder;
|
||||
CFilterCoder *filterStreamSpec;
|
||||
CMyComPtr<ISequentialInStream> filterStream;
|
||||
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
||||
#ifndef EXCLUDE_COM
|
||||
CCoderLibraries libraries;
|
||||
#endif
|
||||
CObjectVector<CMethodItem> methodItems;
|
||||
|
||||
public:
|
||||
CZipDecoder(): _zipCryptoDecoderSpec(0), _aesDecoderSpec(0), filterStreamSpec(0) {}
|
||||
|
||||
static void Init()
|
||||
{
|
||||
#ifndef EXCLUDE_COM
|
||||
N7z::LoadMethodMap();
|
||||
#endif
|
||||
}
|
||||
|
||||
HRESULT Decode(CInArchive &archive, const CItemEx &item,
|
||||
ISequentialOutStream *realOutStream,
|
||||
IArchiveExtractCallback *extractCallback,
|
||||
ICompressProgressInfo *compressProgress,
|
||||
UInt32 numThreads, Int32 &res);
|
||||
};
|
||||
|
||||
HRESULT CZipDecoder::Decode(CInArchive &archive, const CItemEx &item,
|
||||
ISequentialOutStream *realOutStream,
|
||||
IArchiveExtractCallback *extractCallback,
|
||||
ICompressProgressInfo *compressProgress,
|
||||
UInt32 numThreads, Int32 &res)
|
||||
{
|
||||
res = NArchive::NExtract::NOperationResult::kDataError;
|
||||
CInStreamReleaser inStreamReleaser;
|
||||
|
||||
bool needCRC = true;
|
||||
bool aesMode = false;
|
||||
UInt16 methodId = item.CompressionMethod;
|
||||
if (item.IsEncrypted())
|
||||
if (methodId == NFileHeader::NCompressionMethod::kWzAES)
|
||||
{
|
||||
CWzAesExtraField aesField;
|
||||
if (item.CentralExtra.GetWzAesField(aesField))
|
||||
{
|
||||
aesMode = true;
|
||||
needCRC = aesField.NeedCrc();
|
||||
}
|
||||
}
|
||||
|
||||
COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;;
|
||||
CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
|
||||
outStreamSpec->SetStream(realOutStream);
|
||||
outStreamSpec->Init(needCRC);
|
||||
|
||||
UInt64 authenticationPos;
|
||||
|
||||
CMyComPtr<ISequentialInStream> inStream;
|
||||
{
|
||||
UInt64 packSize = item.PackSize;
|
||||
if (aesMode)
|
||||
{
|
||||
if (packSize < NCrypto::NWzAES::kMacSize)
|
||||
return S_OK;
|
||||
packSize -= NCrypto::NWzAES::kMacSize;
|
||||
}
|
||||
UInt64 dataPos = item.GetDataPosition();
|
||||
inStream.Attach(archive.CreateLimitedStream(dataPos, packSize));
|
||||
authenticationPos = dataPos + packSize;
|
||||
}
|
||||
|
||||
CMyComPtr<ICompressFilter> cryptoFilter;
|
||||
if (item.IsEncrypted())
|
||||
{
|
||||
if (aesMode)
|
||||
{
|
||||
CWzAesExtraField aesField;
|
||||
if (!item.CentralExtra.GetWzAesField(aesField))
|
||||
return S_OK;
|
||||
methodId = aesField.Method;
|
||||
if (!_aesDecoder)
|
||||
{
|
||||
_aesDecoderSpec = new NCrypto::NWzAES::CDecoder;
|
||||
_aesDecoder = _aesDecoderSpec;
|
||||
}
|
||||
cryptoFilter = _aesDecoder;
|
||||
Byte properties = aesField.Strength;
|
||||
RINOK(_aesDecoderSpec->SetDecoderProperties2(&properties, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_zipCryptoDecoder)
|
||||
{
|
||||
_zipCryptoDecoderSpec = new NCrypto::NZip::CDecoder;
|
||||
_zipCryptoDecoder = _zipCryptoDecoderSpec;
|
||||
}
|
||||
cryptoFilter = _zipCryptoDecoder;
|
||||
}
|
||||
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
|
||||
RINOK(cryptoFilter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
|
||||
|
||||
if (!getTextPassword)
|
||||
extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
|
||||
|
||||
if (getTextPassword)
|
||||
{
|
||||
CMyComBSTR password;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword(&password));
|
||||
AString charPassword;
|
||||
if (aesMode)
|
||||
{
|
||||
charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_ACP);
|
||||
/*
|
||||
for (int i = 0;; i++)
|
||||
{
|
||||
wchar_t c = password[i];
|
||||
if (c == 0)
|
||||
break;
|
||||
if (c >= 0x80)
|
||||
{
|
||||
res = NArchive::NExtract::NOperationResult::kDataError;
|
||||
return S_OK;
|
||||
}
|
||||
charPassword += (char)c;
|
||||
}
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
// we use OEM. WinZip/Windows probably use ANSI for some files
|
||||
charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP);
|
||||
}
|
||||
HRESULT res = cryptoSetPassword->CryptoSetPassword(
|
||||
(const Byte *)(const char *)charPassword, charPassword.Length());
|
||||
if (res != S_OK)
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
int m;
|
||||
for (m = 0; m < methodItems.Size(); m++)
|
||||
if (methodItems[m].ZipMethod == methodId)
|
||||
break;
|
||||
|
||||
if (m == methodItems.Size())
|
||||
{
|
||||
CMethodItem mi;
|
||||
mi.ZipMethod = methodId;
|
||||
if (methodId == NFileHeader::NCompressionMethod::kStored)
|
||||
mi.Coder = new NCompress::CCopyCoder;
|
||||
else if (methodId == NFileHeader::NCompressionMethod::kShrunk)
|
||||
mi.Coder = new NCompress::NShrink::CDecoder;
|
||||
else if (methodId == NFileHeader::NCompressionMethod::kImploded)
|
||||
mi.Coder = new NCompress::NImplode::NDecoder::CCoder;
|
||||
else
|
||||
{
|
||||
#ifdef EXCLUDE_COM
|
||||
switch(methodId)
|
||||
{
|
||||
case NFileHeader::NCompressionMethod::kDeflated:
|
||||
mi.Coder = new NCompress::NDeflate::NDecoder::CCOMCoder;
|
||||
break;
|
||||
case NFileHeader::NCompressionMethod::kDeflated64:
|
||||
mi.Coder = new NCompress::NDeflate::NDecoder::CCOMCoder64;
|
||||
break;
|
||||
case NFileHeader::NCompressionMethod::kBZip2:
|
||||
mi.Coder = new NCompress::NBZip2::CDecoder;
|
||||
break;
|
||||
default:
|
||||
res = NArchive::NExtract::NOperationResult::kUnSupportedMethod;
|
||||
return S_OK;
|
||||
}
|
||||
#else
|
||||
N7z::CMethodID methodID = { { 0x04, 0x01 } , 3 };
|
||||
if (methodId > 0xFF)
|
||||
{
|
||||
res = NArchive::NExtract::NOperationResult::kUnSupportedMethod;
|
||||
return S_OK;
|
||||
}
|
||||
methodID.ID[2] = (Byte)methodId;
|
||||
if (methodId == NFileHeader::NCompressionMethod::kStored)
|
||||
{
|
||||
methodID.ID[0] = 0;
|
||||
methodID.IDSize = 1;
|
||||
}
|
||||
else if (methodId == NFileHeader::NCompressionMethod::kBZip2)
|
||||
{
|
||||
methodID.ID[1] = 0x02;
|
||||
methodID.ID[2] = 0x02;
|
||||
}
|
||||
|
||||
N7z::CMethodInfo methodInfo;
|
||||
if (!N7z::GetMethodInfo(methodID, methodInfo))
|
||||
{
|
||||
res = NArchive::NExtract::NOperationResult::kUnSupportedMethod;
|
||||
return S_OK;
|
||||
}
|
||||
RINOK(libraries.CreateCoder(methodInfo.FilePath, methodInfo.Decoder, &mi.Coder));
|
||||
#endif
|
||||
}
|
||||
m = methodItems.Add(mi);
|
||||
}
|
||||
ICompressCoder *coder = methodItems[m].Coder;
|
||||
|
||||
{
|
||||
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
|
||||
coder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);
|
||||
if (setDecoderProperties)
|
||||
{
|
||||
Byte properties = (Byte)item.Flags;
|
||||
RINOK(setDecoderProperties->SetDecoderProperties2(&properties, 1));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef COMPRESS_MT
|
||||
{
|
||||
CMyComPtr<ICompressSetCoderMt> setCoderMt;
|
||||
coder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);
|
||||
if (setCoderMt)
|
||||
{
|
||||
RINOK(setCoderMt->SetNumberOfThreads(numThreads));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
HRESULT result;
|
||||
CMyComPtr<ISequentialInStream> inStreamNew;
|
||||
if (item.IsEncrypted())
|
||||
{
|
||||
if (!filterStream)
|
||||
{
|
||||
filterStreamSpec = new CFilterCoder;
|
||||
filterStream = filterStreamSpec;
|
||||
}
|
||||
filterStreamSpec->Filter = cryptoFilter;
|
||||
if (aesMode)
|
||||
{
|
||||
RINOK(_aesDecoderSpec->ReadHeader(inStream));
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(_zipCryptoDecoderSpec->ReadHeader(inStream));
|
||||
}
|
||||
RINOK(filterStreamSpec->SetInStream(inStream));
|
||||
inStreamReleaser.FilterCoder = filterStreamSpec;
|
||||
inStreamNew = filterStream;
|
||||
|
||||
if (aesMode)
|
||||
{
|
||||
if (!_aesDecoderSpec->CheckPasswordVerifyCode())
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
inStreamNew = inStream;
|
||||
result = coder->Code(inStreamNew, outStream, NULL, &item.UnPackSize, compressProgress);
|
||||
if (result == S_FALSE)
|
||||
return S_OK;
|
||||
RINOK(result);
|
||||
}
|
||||
bool crcOK = true;
|
||||
bool authOk = true;
|
||||
if (needCRC)
|
||||
crcOK = (outStreamSpec->GetCRC() == item.FileCRC);
|
||||
if (aesMode)
|
||||
{
|
||||
inStream.Attach(archive.CreateLimitedStream(authenticationPos, NCrypto::NWzAES::kMacSize));
|
||||
if (_aesDecoderSpec->CheckMac(inStream, authOk) != S_OK)
|
||||
authOk = false;
|
||||
}
|
||||
|
||||
res = ((crcOK && authOk) ?
|
||||
NArchive::NExtract::NOperationResult::kOK :
|
||||
NArchive::NExtract::NOperationResult::kCRCError);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
Int32 _aTestMode, IArchiveExtractCallback *_anExtractCallback)
|
||||
Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
||||
CZipDecoder myDecoder;
|
||||
bool testMode = (_aTestMode != 0);
|
||||
CMyComPtr<IArchiveExtractCallback> extractCallback = _anExtractCallback;
|
||||
UInt64 totalUnPacked = 0, totalPacked = 0;
|
||||
bool allFilesMode = (numItems == UInt32(-1));
|
||||
if (allFilesMode)
|
||||
@@ -363,37 +691,14 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0;
|
||||
UInt64 currentItemUnPacked, currentItemPacked;
|
||||
|
||||
|
||||
#ifndef EXCLUDE_COM
|
||||
N7z::LoadMethodMap();
|
||||
CCoderLibraries libraries;
|
||||
#endif
|
||||
CObjectVector<CMethodItem> methodItems;
|
||||
/*
|
||||
CCoderLibraries _libraries;
|
||||
#ifndef COMPRESS_IMPLODE
|
||||
CCoderLibrary implodeLib;
|
||||
#endif
|
||||
|
||||
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
|
||||
CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo;
|
||||
CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
|
||||
|
||||
CMyComPtr<ICompressCoder> implodeDecoder;
|
||||
CMyComPtr<ICompressCoder> deflateDecoder;
|
||||
CMyComPtr<ICompressCoder> deflate64Decoder;
|
||||
CMyComPtr<ICompressCoder> bzip2Decoder;
|
||||
CZipDecoder::Init();
|
||||
|
||||
#ifndef CRYPTO_ZIP
|
||||
CCoderLibrary cryptoLib;
|
||||
#endif
|
||||
*/
|
||||
|
||||
NCrypto::NZip::CDecoder *cryptoDecoderSpec;
|
||||
CMyComPtr<ICompressFilter> cryptoDecoder;
|
||||
CFilterCoder *filterStreamSpec;
|
||||
CMyComPtr<ISequentialInStream> filterStream;
|
||||
|
||||
// UInt16 mixerCoderMethod;
|
||||
|
||||
for(i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked,
|
||||
for (i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked,
|
||||
currentTotalPacked += currentItemPacked)
|
||||
{
|
||||
currentItemUnPacked = 0;
|
||||
@@ -401,222 +706,58 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
|
||||
RINOK(extractCallback->SetCompleted(¤tTotalUnPacked));
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
Int32 askMode;
|
||||
askMode = testMode ? NArchive::NExtract::NAskMode::kTest :
|
||||
Int32 askMode = testMode ?
|
||||
NArchive::NExtract::NAskMode::kTest :
|
||||
NArchive::NExtract::NAskMode::kExtract;
|
||||
Int32 index = allFilesMode ? i : indices[i];
|
||||
const CItemEx &item = m_Items[index];
|
||||
|
||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
|
||||
|
||||
if(item.IsDirectory() || item.IgnoreItem())
|
||||
CItemEx item = m_Items[index];
|
||||
if (!item.FromLocal)
|
||||
{
|
||||
HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item);
|
||||
if (res == S_FALSE)
|
||||
{
|
||||
if (item.IsDirectory() || realOutStream || testMode)
|
||||
{
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
realOutStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
RINOK(res);
|
||||
}
|
||||
|
||||
if (item.IsDirectory() || item.IgnoreItem())
|
||||
{
|
||||
// if (!testMode)
|
||||
{
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
realOutStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
currentItemUnPacked = item.UnPackSize;
|
||||
currentItemPacked = item.PackSize;
|
||||
|
||||
if (!testMode && (!realOutStream))
|
||||
continue;
|
||||
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
currentItemUnPacked = item.UnPackSize;
|
||||
currentItemPacked = item.PackSize;
|
||||
|
||||
CInStreamReleaser inStreamReleaser;
|
||||
{
|
||||
COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
|
||||
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
|
||||
outStreamSpec->Init(realOutStream);
|
||||
realOutStream.Release();
|
||||
|
||||
CMyComPtr<ISequentialInStream> inStream;
|
||||
inStream.Attach(m_Archive.CreateLimitedStream(item.GetDataPosition(),
|
||||
item.PackSize));
|
||||
|
||||
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
|
||||
localProgressSpec->Init(extractCallback, false);
|
||||
|
||||
CLocalCompressProgressInfo *localCompressProgressSpec =
|
||||
new CLocalCompressProgressInfo;
|
||||
CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
|
||||
localCompressProgressSpec->Init(progress,
|
||||
¤tTotalPacked,
|
||||
¤tTotalUnPacked);
|
||||
|
||||
if (item.IsEncrypted())
|
||||
{
|
||||
if (!cryptoDecoder)
|
||||
{
|
||||
cryptoDecoderSpec = new NCrypto::NZip::CDecoder;
|
||||
cryptoDecoder = cryptoDecoderSpec;
|
||||
}
|
||||
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
|
||||
RINOK(cryptoDecoder.QueryInterface(
|
||||
IID_ICryptoSetPassword, &cryptoSetPassword));
|
||||
|
||||
if (!getTextPassword)
|
||||
extractCallback.QueryInterface(
|
||||
IID_ICryptoGetTextPassword, &getTextPassword);
|
||||
|
||||
if (getTextPassword)
|
||||
{
|
||||
CMyComBSTR password;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword(&password));
|
||||
AString anOemPassword = UnicodeStringToMultiByte(
|
||||
(const wchar_t *)password, CP_OEMCP);
|
||||
RINOK(cryptoSetPassword->CryptoSetPassword(
|
||||
(const Byte *)(const char *)anOemPassword, anOemPassword.Length()));
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
int m;
|
||||
for (m = 0; m < methodItems.Size(); m++)
|
||||
if (methodItems[m].ZipMethod == item.CompressionMethod)
|
||||
break;
|
||||
if (m == methodItems.Size())
|
||||
{
|
||||
CMethodItem mi;
|
||||
mi.ZipMethod = (Byte)item.CompressionMethod;
|
||||
if (item.CompressionMethod == NFileHeader::NCompressionMethod::kStored)
|
||||
mi.Coder = new NCompress::CCopyCoder;
|
||||
else if (item.CompressionMethod == NFileHeader::NCompressionMethod::kShrunk)
|
||||
mi.Coder = new NCompress::NShrink::CDecoder;
|
||||
else if (item.CompressionMethod == NFileHeader::NCompressionMethod::kImploded)
|
||||
mi.Coder = new NCompress::NImplode::NDecoder::CCoder;
|
||||
else
|
||||
{
|
||||
#ifdef EXCLUDE_COM
|
||||
switch(item.CompressionMethod)
|
||||
{
|
||||
case NFileHeader::NCompressionMethod::kDeflated:
|
||||
mi.Coder = new NCompress::NDeflate::NDecoder::CCOMCoder;
|
||||
break;
|
||||
case NFileHeader::NCompressionMethod::kDeflated64:
|
||||
mi.Coder = new NCompress::NDeflate::NDecoder::CCOMCoder64;
|
||||
break;
|
||||
case NFileHeader::NCompressionMethod::kBZip2:
|
||||
mi.Coder = new NCompress::NBZip2::CDecoder;
|
||||
break;
|
||||
default:
|
||||
RINOK(extractCallback->SetOperationResult(
|
||||
NArchive::NExtract::NOperationResult::kUnSupportedMethod));
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
N7z::CMethodID methodID = { { 0x04, 0x01 } , 3 };
|
||||
methodID.ID[2] = mi.ZipMethod;
|
||||
if (item.CompressionMethod == NFileHeader::NCompressionMethod::kStored)
|
||||
{
|
||||
methodID.ID[0] = 0;
|
||||
methodID.IDSize = 1;
|
||||
}
|
||||
else if (item.CompressionMethod == NFileHeader::NCompressionMethod::kBZip2)
|
||||
{
|
||||
methodID.ID[1] = 0x02;
|
||||
methodID.ID[2] = 0x02;
|
||||
}
|
||||
|
||||
N7z::CMethodInfo methodInfo;
|
||||
if (!N7z::GetMethodInfo(methodID, methodInfo))
|
||||
{
|
||||
RINOK(extractCallback->SetOperationResult(
|
||||
NArchive::NExtract::NOperationResult::kUnSupportedMethod));
|
||||
continue;
|
||||
}
|
||||
RINOK(libraries.CreateCoder(methodInfo.FilePath,
|
||||
methodInfo.Decoder, &mi.Coder));
|
||||
#endif
|
||||
}
|
||||
m = methodItems.Add(mi);
|
||||
}
|
||||
ICompressCoder *coder = methodItems[m].Coder;
|
||||
|
||||
{
|
||||
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
|
||||
coder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);
|
||||
if (setDecoderProperties)
|
||||
{
|
||||
Byte properties = (Byte)item.Flags;
|
||||
RINOK(setDecoderProperties->SetDecoderProperties2(&properties, 1));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef COMPRESS_MT
|
||||
{
|
||||
CMyComPtr<ICompressSetCoderMt> setCoderMt;
|
||||
coder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);
|
||||
if (setCoderMt)
|
||||
{
|
||||
RINOK(setCoderMt->SetNumberOfThreads(_numThreads));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// case NFileHeader::NCompressionMethod::kImploded:
|
||||
// switch(item.CompressionMethod)
|
||||
try
|
||||
{
|
||||
HRESULT result;
|
||||
CMyComPtr<ISequentialInStream> inStreamNew;
|
||||
if (item.IsEncrypted())
|
||||
{
|
||||
if (!filterStream)
|
||||
{
|
||||
filterStreamSpec = new CFilterCoder;
|
||||
filterStream = filterStreamSpec;
|
||||
filterStreamSpec->Filter = cryptoDecoder;
|
||||
}
|
||||
RINOK(cryptoDecoderSpec->ReadHeader(inStream));
|
||||
RINOK(filterStreamSpec->SetInStream(inStream));
|
||||
inStreamReleaser.FilterCoder = filterStreamSpec;
|
||||
|
||||
/*
|
||||
switch(item.CompressionMethod)
|
||||
{
|
||||
case NFileHeader::NCompressionMethod::kStored:
|
||||
mixerCoderSpec->SetCoderInfo(0, ¤tItemPacked,
|
||||
¤tItemUnPacked);
|
||||
mixerCoderSpec->SetCoderInfo(1, NULL, NULL);
|
||||
break;
|
||||
default:
|
||||
mixerCoderSpec->SetCoderInfo(0, ¤tItemPacked, NULL);
|
||||
mixerCoderSpec->SetCoderInfo(1, NULL, ¤tItemUnPacked);
|
||||
break;
|
||||
}
|
||||
*/
|
||||
inStreamNew = filterStream;
|
||||
}
|
||||
else
|
||||
{
|
||||
inStreamNew = inStream;
|
||||
}
|
||||
result = coder->Code(inStreamNew, outStream,
|
||||
NULL, ¤tItemUnPacked, compressProgress);
|
||||
if (result == S_FALSE)
|
||||
throw "data error";
|
||||
if (result != S_OK)
|
||||
return result;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
outStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(
|
||||
NArchive::NExtract::NOperationResult::kDataError));
|
||||
continue;
|
||||
}
|
||||
bool crcOK = outStreamSpec->GetCRC() == item.FileCRC;
|
||||
outStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(crcOK ? NArchive::NExtract::NOperationResult::kOK :
|
||||
NArchive::NExtract::NOperationResult::kCRCError))
|
||||
}
|
||||
localProgressSpec->Init(extractCallback, false);
|
||||
localCompressProgressSpec->Init(progress, ¤tTotalPacked, ¤tTotalUnPacked);
|
||||
|
||||
Int32 res;
|
||||
RINOK(myDecoder.Decode(m_Archive, item, realOutStream, extractCallback,
|
||||
compressProgress, _numThreads, res));
|
||||
realOutStream.Release();
|
||||
|
||||
RINOK(extractCallback->SetOperationResult(res))
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
|
||||
@@ -71,6 +71,9 @@ private:
|
||||
UInt32 m_NumMatchFinderCycles;
|
||||
bool m_NumMatchFinderCyclesDefined;
|
||||
|
||||
bool m_IsAesMode;
|
||||
Byte m_AesKeyMode;
|
||||
|
||||
#ifdef COMPRESS_MT
|
||||
UInt32 _numThreads;
|
||||
#endif
|
||||
@@ -84,6 +87,8 @@ private:
|
||||
m_NumFastBytes =
|
||||
m_NumMatchFinderCycles = 0xFFFFFFFF;
|
||||
m_NumMatchFinderCyclesDefined = false;
|
||||
m_IsAesMode = false;
|
||||
m_AesKeyMode = 3; // aes-256
|
||||
#ifdef COMPRESS_MT
|
||||
_numThreads = NWindows::NSystem::GetNumberOfProcessors();;
|
||||
#endif
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "../../IPassword.h"
|
||||
#include "../Common/ItemNameUtils.h"
|
||||
#include "../Common/ParseProperties.h"
|
||||
#include "../../Crypto/WzAES/WzAES.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NCOM;
|
||||
@@ -45,6 +46,17 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static bool IsAsciiString(const UString &s)
|
||||
{
|
||||
for (int i = 0; i < s.Length(); i++)
|
||||
{
|
||||
wchar_t c = s[i];
|
||||
if (c < 0x20 || c > 0x7F)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
|
||||
IArchiveUpdateCallback *updateCallback)
|
||||
{
|
||||
@@ -138,6 +150,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
if (needSlash)
|
||||
name += kSlash;
|
||||
updateItem.Name = UnicodeStringToMultiByte(name, CP_OEMCP);
|
||||
if (updateItem.Name.Length() > 0xFFFF)
|
||||
return E_INVALIDARG;
|
||||
|
||||
updateItem.IndexInClient = i;
|
||||
/*
|
||||
@@ -183,10 +197,21 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
{
|
||||
CMyComBSTR password;
|
||||
Int32 passwordIsDefined;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword2(
|
||||
&passwordIsDefined, &password));
|
||||
if (options.PasswordIsDefined = IntToBool(passwordIsDefined))
|
||||
RINOK(getTextPassword->CryptoGetTextPassword2(&passwordIsDefined, &password));
|
||||
options.PasswordIsDefined = IntToBool(passwordIsDefined);
|
||||
if (options.PasswordIsDefined)
|
||||
{
|
||||
if (!IsAsciiString((const wchar_t *)password))
|
||||
return E_INVALIDARG;
|
||||
if (m_IsAesMode)
|
||||
{
|
||||
if (options.Password.Length() > NCrypto::NWzAES::kPasswordSizeMax)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
options.Password = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP);
|
||||
options.IsAesMode = m_IsAesMode;
|
||||
options.AesKeyMode = m_AesKeyMode;
|
||||
}
|
||||
}
|
||||
else
|
||||
options.PasswordIsDefined = false;
|
||||
@@ -197,9 +222,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
|
||||
Byte mainMethod;
|
||||
if (m_MainMethod < 0)
|
||||
mainMethod = ((level == 0) ?
|
||||
mainMethod = (Byte)(((level == 0) ?
|
||||
NFileHeader::NCompressionMethod::kStored :
|
||||
NFileHeader::NCompressionMethod::kDeflated);
|
||||
NFileHeader::NCompressionMethod::kDeflated));
|
||||
else
|
||||
mainMethod = (Byte)m_MainMethod;
|
||||
options.MethodSequence.Add(mainMethod);
|
||||
@@ -301,6 +326,33 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
else if (name.Left(2) == L"EM")
|
||||
{
|
||||
if (prop.vt == VT_BSTR)
|
||||
{
|
||||
UString valueString = prop.bstrVal;
|
||||
valueString.MakeUpper();
|
||||
if (valueString.Left(3) == L"AES")
|
||||
{
|
||||
valueString = valueString.Mid(3);
|
||||
if (valueString == L"128")
|
||||
m_AesKeyMode = 1;
|
||||
else if (valueString == L"192")
|
||||
m_AesKeyMode = 2;
|
||||
else if (valueString == L"256" || valueString.IsEmpty())
|
||||
m_AesKeyMode = 3;
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
m_IsAesMode = true;
|
||||
}
|
||||
else if (valueString == L"ZIPCRYPTO")
|
||||
m_IsAesMode = false;
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
else if (name[0] == L'D')
|
||||
{
|
||||
UInt32 dicSize = kBZip2DicSizeX5;
|
||||
|
||||
@@ -20,8 +20,9 @@ namespace NSignature
|
||||
static const UInt32 kMarkerSize = 4;
|
||||
}
|
||||
|
||||
const UInt32 kZip64EndOfCentralDirRecordSize = 44;
|
||||
|
||||
const UInt32 kEcdSize = 22;
|
||||
const UInt32 kZip64EcdSize = 44;
|
||||
const UInt32 kZip64EcdLocatorSize = 20;
|
||||
/*
|
||||
struct CEndOfCentralDirectoryRecord
|
||||
{
|
||||
@@ -68,7 +69,8 @@ namespace NFileHeader
|
||||
kPKImploding = 10,
|
||||
|
||||
kBZip2 = 12,
|
||||
kWinZipPPMd = 0x62
|
||||
kWzPPMd = 0x62,
|
||||
kWzAES = 0x63
|
||||
};
|
||||
const int kNumCompressionMethods = 11;
|
||||
const Byte kMadeByProgramVersion = 20;
|
||||
@@ -79,6 +81,15 @@ namespace NFileHeader
|
||||
const Byte kSupportedVersion = 20;
|
||||
}
|
||||
|
||||
namespace NExtraID
|
||||
{
|
||||
enum
|
||||
{
|
||||
kZip64 = 0x01,
|
||||
kWzAES = 0x9901
|
||||
};
|
||||
}
|
||||
|
||||
const UInt32 kLocalBlockSize = 26;
|
||||
/*
|
||||
struct CLocalBlock
|
||||
|
||||
@@ -28,6 +28,11 @@ void CInArchive::Close()
|
||||
m_Stream.Release();
|
||||
}
|
||||
|
||||
HRESULT CInArchive::Seek(UInt64 offset)
|
||||
{
|
||||
return m_Stream->Seek(offset, STREAM_SEEK_SET, NULL);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// Markers
|
||||
|
||||
@@ -41,9 +46,8 @@ static inline bool TestMarkerCandidate(const Byte *p, UInt32 &value)
|
||||
bool CInArchive::FindAndReadMarker(const UInt64 *searchHeaderSizeLimit)
|
||||
{
|
||||
m_ArchiveInfo.Clear();
|
||||
m_ArchiveInfo.StartPosition = 0;
|
||||
m_Position = m_StreamStartPosition;
|
||||
if(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL) != S_OK)
|
||||
if(Seek(m_StreamStartPosition) != S_OK)
|
||||
return false;
|
||||
|
||||
Byte marker[NSignature::kMarkerSize];
|
||||
@@ -61,24 +65,26 @@ bool CInArchive::FindAndReadMarker(const UInt64 *searchHeaderSizeLimit)
|
||||
UInt32 numBytesPrev = NSignature::kMarkerSize - 1;
|
||||
memmove(buffer, marker + 1, numBytesPrev);
|
||||
UInt64 curTestPos = m_StreamStartPosition + 1;
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
if (searchHeaderSizeLimit != NULL)
|
||||
if (curTestPos - m_StreamStartPosition > *searchHeaderSizeLimit)
|
||||
return false;
|
||||
break;
|
||||
UInt32 numReadBytes = kSearchMarkerBufferSize - numBytesPrev;
|
||||
ReadBytes(buffer + numBytesPrev, numReadBytes, &processedSize);
|
||||
UInt32 numBytesInBuffer = numBytesPrev + processedSize;
|
||||
if (numBytesInBuffer < NSignature::kMarkerSize)
|
||||
return false;
|
||||
break;
|
||||
UInt32 numTests = numBytesInBuffer - NSignature::kMarkerSize + 1;
|
||||
for(UInt32 pos = 0; pos < numTests; pos++, curTestPos++)
|
||||
{
|
||||
if (TestMarkerCandidate(buffer + pos, m_Signature))
|
||||
{
|
||||
m_ArchiveInfo.StartPosition = curTestPos;
|
||||
// m_ArchiveInfo.Base = m_ArchiveInfo.StartPosition;
|
||||
// m_ArchiveInfo.Base = 0;
|
||||
m_Position = curTestPos + NSignature::kMarkerSize;
|
||||
if(m_Stream->Seek(m_Position, STREAM_SEEK_SET, NULL) != S_OK)
|
||||
if(Seek(m_Position) != S_OK)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@@ -86,6 +92,7 @@ bool CInArchive::FindAndReadMarker(const UInt64 *searchHeaderSizeLimit)
|
||||
numBytesPrev = numBytesInBuffer - numTests;
|
||||
memmove(buffer, buffer + numTests, numBytesPrev);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize)
|
||||
@@ -184,10 +191,12 @@ void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const
|
||||
archiveInfo = m_ArchiveInfo;
|
||||
}
|
||||
|
||||
/*
|
||||
void CInArchive::ThrowIncorrectArchiveException()
|
||||
{
|
||||
throw CInArchiveException(CInArchiveException::kIncorrectArchive);
|
||||
}
|
||||
*/
|
||||
|
||||
static UInt32 GetUInt32(const Byte *data)
|
||||
{
|
||||
@@ -198,6 +207,21 @@ static UInt32 GetUInt32(const Byte *data)
|
||||
(((UInt32)(Byte)data[3]) << 24);
|
||||
}
|
||||
|
||||
/*
|
||||
static UInt16 GetUInt16(const Byte *data)
|
||||
{
|
||||
return
|
||||
((UInt16)(Byte)data[0]) |
|
||||
(((UInt16)(Byte)data[1]) << 8);
|
||||
}
|
||||
*/
|
||||
|
||||
static UInt64 GetUInt64(const Byte *data)
|
||||
{
|
||||
return GetUInt32(data) | ((UInt64)GetUInt32(data + 4) << 32);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock,
|
||||
UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber)
|
||||
@@ -212,7 +236,7 @@ void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock,
|
||||
remain -= 4;
|
||||
if (dataSize > remain) // it's bug
|
||||
dataSize = remain;
|
||||
if (subBlock.ID == 0x1)
|
||||
if (subBlock.ID == NFileHeader::NExtraID::kZip64)
|
||||
{
|
||||
if (unpackSize == 0xFFFFFFFF)
|
||||
{
|
||||
@@ -259,108 +283,298 @@ void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock,
|
||||
IncreaseRealPosition(remain);
|
||||
}
|
||||
|
||||
HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress)
|
||||
HRESULT CInArchive::ReadLocalItem(CItemEx &item)
|
||||
{
|
||||
// m_Signature must be kLocalFileHeaderSignature or
|
||||
// kEndOfCentralDirSignature
|
||||
// m_Position points to next byte after signature
|
||||
|
||||
items.Clear();
|
||||
|
||||
if (progress != 0)
|
||||
item.ExtractVersion.Version = ReadByte();
|
||||
item.ExtractVersion.HostOS = ReadByte();
|
||||
item.Flags = ReadUInt16(); // & NFileHeader::NFlags::kUsedBitsMask;
|
||||
item.CompressionMethod = ReadUInt16();
|
||||
item.Time = ReadUInt32();
|
||||
item.FileCRC = ReadUInt32();
|
||||
item.PackSize = ReadUInt32();
|
||||
item.UnPackSize = ReadUInt32();
|
||||
UInt32 fileNameSize = ReadUInt16();
|
||||
item.LocalExtraSize = ReadUInt16();
|
||||
item.Name = ReadFileName(fileNameSize);
|
||||
item.FileHeaderWithNameSize = 4 + NFileHeader::kLocalBlockSize + fileNameSize;
|
||||
if (item.LocalExtraSize > 0)
|
||||
{
|
||||
UInt64 numItems = items.Size();
|
||||
RINOK(progress->SetCompleted(&numItems));
|
||||
UInt64 localHeaderOffset = 0;
|
||||
UInt32 diskStartNumber = 0;
|
||||
ReadExtra(item.LocalExtraSize, item.LocalExtra, item.UnPackSize, item.PackSize,
|
||||
localHeaderOffset, diskStartNumber);
|
||||
}
|
||||
/*
|
||||
if (item.IsDirectory())
|
||||
item.UnPackSize = 0; // check It
|
||||
*/
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item)
|
||||
{
|
||||
if (item.FromLocal)
|
||||
return S_OK;
|
||||
try
|
||||
{
|
||||
RINOK(Seek(m_ArchiveInfo.Base + item.LocalHeaderPosition));
|
||||
CItemEx localItem;
|
||||
if (ReadUInt32() != NSignature::kLocalFileHeader)
|
||||
return S_FALSE;
|
||||
RINOK(ReadLocalItem(localItem));
|
||||
if (item.Flags != localItem.Flags)
|
||||
{
|
||||
if (item.CompressionMethod != NFileHeader::NCompressionMethod::kDeflated ||
|
||||
(item.Flags & 0xFFFC) != (localItem.Flags & 0xFFFC))
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
if (item.CompressionMethod != localItem.CompressionMethod ||
|
||||
// item.Time != localItem.Time ||
|
||||
(!localItem.HasDescriptor() &&
|
||||
(
|
||||
item.FileCRC != localItem.FileCRC ||
|
||||
item.PackSize != localItem.PackSize ||
|
||||
item.UnPackSize != localItem.UnPackSize
|
||||
)
|
||||
) ||
|
||||
item.Name.Length() != localItem.Name.Length()
|
||||
)
|
||||
return S_FALSE;
|
||||
item.FileHeaderWithNameSize = localItem.FileHeaderWithNameSize;
|
||||
item.LocalExtraSize = localItem.LocalExtraSize;
|
||||
item.LocalExtra = localItem.LocalExtra;
|
||||
item.FromLocal = true;
|
||||
}
|
||||
catch(...) { return S_FALSE; }
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item)
|
||||
{
|
||||
if (item.HasDescriptor())
|
||||
{
|
||||
const int kBufferSize = (1 << 12);
|
||||
Byte buffer[kBufferSize];
|
||||
|
||||
UInt32 numBytesInBuffer = 0;
|
||||
UInt32 packedSize = 0;
|
||||
|
||||
bool descriptorWasFound = false;
|
||||
for (;;)
|
||||
{
|
||||
UInt32 processedSize;
|
||||
RINOK(ReadBytes(buffer + numBytesInBuffer, kBufferSize - numBytesInBuffer, &processedSize));
|
||||
numBytesInBuffer += processedSize;
|
||||
if (numBytesInBuffer < NFileHeader::kDataDescriptorSize)
|
||||
return S_FALSE;
|
||||
UInt32 i;
|
||||
for (i = 0; i <= numBytesInBuffer - NFileHeader::kDataDescriptorSize; i++)
|
||||
{
|
||||
// descriptorSignature field is Info-ZIP's extension
|
||||
// to Zip specification.
|
||||
UInt32 descriptorSignature = GetUInt32(buffer + i);
|
||||
|
||||
// !!!! It must be fixed for Zip64 archives
|
||||
UInt32 descriptorPackSize = GetUInt32(buffer + i + 8);
|
||||
if (descriptorSignature== NSignature::kDataDescriptor && descriptorPackSize == packedSize + i)
|
||||
{
|
||||
descriptorWasFound = true;
|
||||
item.FileCRC = GetUInt32(buffer + i + 4);
|
||||
item.PackSize = descriptorPackSize;
|
||||
item.UnPackSize = GetUInt32(buffer + i + 12);
|
||||
IncreaseRealPosition(Int64(Int32(0 - (numBytesInBuffer - i - NFileHeader::kDataDescriptorSize))));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (descriptorWasFound)
|
||||
break;
|
||||
packedSize += i;
|
||||
int j;
|
||||
for (j = 0; i < numBytesInBuffer; i++, j++)
|
||||
buffer[j] = buffer[i];
|
||||
numBytesInBuffer = j;
|
||||
}
|
||||
}
|
||||
else
|
||||
IncreaseRealPosition(item.PackSize);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item)
|
||||
{
|
||||
if (item.FromLocal)
|
||||
return S_OK;
|
||||
try
|
||||
{
|
||||
RINOK(ReadLocalItemAfterCdItem(item));
|
||||
if (item.HasDescriptor())
|
||||
{
|
||||
RINOK(Seek(m_ArchiveInfo.Base + item.GetDataPosition() + item.PackSize));
|
||||
if (ReadUInt32() != NSignature::kDataDescriptor)
|
||||
return S_FALSE;
|
||||
UInt32 crc = ReadUInt32();
|
||||
UInt32 packSize = ReadUInt32();
|
||||
UInt32 unpackSize = ReadUInt32();
|
||||
if (crc != item.FileCRC || item.PackSize != packSize || item.UnPackSize != unpackSize)
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
catch(...) { return S_FALSE; }
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::ReadCdItem(CItemEx &item)
|
||||
{
|
||||
item.FromCentral = true;
|
||||
item.MadeByVersion.Version = ReadByte();
|
||||
item.MadeByVersion.HostOS = ReadByte();
|
||||
item.ExtractVersion.Version = ReadByte();
|
||||
item.ExtractVersion.HostOS = ReadByte();
|
||||
item.Flags = ReadUInt16(); // & NFileHeader::NFlags::kUsedBitsMask;
|
||||
item.CompressionMethod = ReadUInt16();
|
||||
item.Time = ReadUInt32();
|
||||
item.FileCRC = ReadUInt32();
|
||||
item.PackSize = ReadUInt32();
|
||||
item.UnPackSize = ReadUInt32();
|
||||
UInt16 headerNameSize = ReadUInt16();
|
||||
UInt16 headerExtraSize = ReadUInt16();
|
||||
UInt16 headerCommentSize = ReadUInt16();
|
||||
UInt32 headerDiskNumberStart = ReadUInt16();
|
||||
item.InternalAttributes = ReadUInt16();
|
||||
item.ExternalAttributes = ReadUInt32();
|
||||
item.LocalHeaderPosition = ReadUInt32();
|
||||
item.Name = ReadFileName(headerNameSize);
|
||||
|
||||
if (headerExtraSize > 0)
|
||||
{
|
||||
ReadExtra(headerExtraSize, item.CentralExtra, item.UnPackSize, item.PackSize,
|
||||
item.LocalHeaderPosition, headerDiskNumberStart);
|
||||
}
|
||||
|
||||
while(m_Signature == NSignature::kLocalFileHeader)
|
||||
if (headerDiskNumberStart != 0)
|
||||
throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);
|
||||
|
||||
// May be these strings must be deleted
|
||||
/*
|
||||
if (item.IsDirectory())
|
||||
item.UnPackSize = 0;
|
||||
*/
|
||||
|
||||
ReadBuffer(item.Comment, headerCommentSize);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo)
|
||||
{
|
||||
RINOK(Seek(offset));
|
||||
const UInt32 kEcd64Size = 56;
|
||||
Byte buf[kEcd64Size];
|
||||
if(!ReadBytesAndTestSize(buf, kEcd64Size))
|
||||
return S_FALSE;
|
||||
if (GetUInt32(buf) != NSignature::kZip64EndOfCentralDir)
|
||||
return S_FALSE;
|
||||
// cdInfo.NumEntries = GetUInt64(buf + 24);
|
||||
cdInfo.Size = GetUInt64(buf + 40);
|
||||
cdInfo.Offset = GetUInt64(buf + 48);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::FindCd(CCdInfo &cdInfo)
|
||||
{
|
||||
UInt64 endPosition;
|
||||
RINOK(m_Stream->Seek(0, STREAM_SEEK_END, &endPosition));
|
||||
const UInt32 kBufSizeMax = (1 << 16) + kEcdSize + kZip64EcdLocatorSize;
|
||||
Byte buf[kBufSizeMax];
|
||||
UInt32 bufSize = (endPosition < kBufSizeMax) ? (UInt32)endPosition : kBufSizeMax;
|
||||
if (bufSize < kEcdSize)
|
||||
return S_FALSE;
|
||||
UInt64 startPosition = endPosition - bufSize;
|
||||
RINOK(m_Stream->Seek(startPosition, STREAM_SEEK_SET, &m_Position));
|
||||
if (m_Position != startPosition)
|
||||
return S_FALSE;
|
||||
if (!ReadBytesAndTestSize(buf, bufSize))
|
||||
return S_FALSE;
|
||||
for (int i = (int)(bufSize - kEcdSize); i >= 0; i--)
|
||||
{
|
||||
if (GetUInt32(buf + i) == NSignature::kEndOfCentralDir)
|
||||
{
|
||||
if (i >= kZip64EcdLocatorSize)
|
||||
{
|
||||
const Byte *locator = buf + i - kZip64EcdLocatorSize;
|
||||
if (GetUInt32(locator) == NSignature::kZip64EndOfCentralDirLocator)
|
||||
{
|
||||
UInt64 ecd64Offset = GetUInt64(locator + 8);
|
||||
if (TryEcd64(ecd64Offset, cdInfo) == S_OK)
|
||||
return S_OK;
|
||||
if (TryEcd64(m_ArchiveInfo.StartPosition + ecd64Offset, cdInfo) == S_OK)
|
||||
{
|
||||
m_ArchiveInfo.Base = m_ArchiveInfo.StartPosition;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (GetUInt32(buf + i + 4) == 0)
|
||||
{
|
||||
// cdInfo.NumEntries = GetUInt16(buf + i + 10);
|
||||
cdInfo.Size = GetUInt32(buf + i + 12);
|
||||
cdInfo.Offset = GetUInt32(buf + i + 16);
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, UInt64 cdOffset, UInt64 cdSize)
|
||||
{
|
||||
items.Clear();
|
||||
RINOK(m_Stream->Seek(cdOffset, STREAM_SEEK_SET, &m_Position));
|
||||
if (m_Position != cdOffset)
|
||||
return S_FALSE;
|
||||
while(m_Position - cdOffset < cdSize)
|
||||
{
|
||||
if(ReadUInt32() != NSignature::kCentralFileHeader)
|
||||
return S_FALSE;
|
||||
CItemEx cdItem;
|
||||
RINOK(ReadCdItem(cdItem));
|
||||
items.Add(cdItem);
|
||||
}
|
||||
return (m_Position - cdOffset == cdSize) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt64 &cdOffset, UInt64 &cdSize)
|
||||
{
|
||||
m_ArchiveInfo.Base = 0;
|
||||
CCdInfo cdInfo;
|
||||
RINOK(FindCd(cdInfo));
|
||||
HRESULT res = S_FALSE;
|
||||
cdSize = cdInfo.Size;
|
||||
cdOffset = cdInfo.Offset;
|
||||
res = TryReadCd(items, m_ArchiveInfo.Base + cdOffset, cdSize);
|
||||
if (res == S_FALSE && m_ArchiveInfo.Base == 0)
|
||||
{
|
||||
res = TryReadCd(items, cdInfo.Offset + m_ArchiveInfo.StartPosition, cdSize);
|
||||
if (res == S_OK)
|
||||
m_ArchiveInfo.Base = m_ArchiveInfo.StartPosition;
|
||||
}
|
||||
if (!ReadUInt32(m_Signature))
|
||||
return S_FALSE;
|
||||
return res;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt *progress, UInt64 &cdOffset)
|
||||
{
|
||||
items.Clear();
|
||||
while (m_Signature == NSignature::kLocalFileHeader)
|
||||
{
|
||||
// FSeek points to next byte after signature
|
||||
// NFileHeader::CLocalBlock localHeader;
|
||||
CItemEx item;
|
||||
item.LocalHeaderPosition = m_Position - m_StreamStartPosition - 4; // points to signature;
|
||||
|
||||
// SafeReadBytes(&localHeader, sizeof(localHeader));
|
||||
|
||||
item.ExtractVersion.Version = ReadByte();
|
||||
item.ExtractVersion.HostOS = ReadByte();
|
||||
item.Flags = ReadUInt16() & NFileHeader::NFlags::kUsedBitsMask;
|
||||
item.CompressionMethod = ReadUInt16();
|
||||
item.Time = ReadUInt32();
|
||||
item.FileCRC = ReadUInt32();
|
||||
item.PackSize = ReadUInt32();
|
||||
item.UnPackSize = ReadUInt32();
|
||||
UInt32 fileNameSize = ReadUInt16();
|
||||
item.LocalExtraSize = ReadUInt16();
|
||||
item.Name = ReadFileName(fileNameSize);
|
||||
/*
|
||||
if (!NItemName::IsNameLegal(item.Name))
|
||||
ThrowIncorrectArchiveException();
|
||||
*/
|
||||
|
||||
item.FileHeaderWithNameSize = 4 +
|
||||
NFileHeader::kLocalBlockSize + fileNameSize;
|
||||
|
||||
// IncreaseRealPosition(item.LocalExtraSize);
|
||||
if (item.LocalExtraSize > 0)
|
||||
{
|
||||
UInt64 localHeaderOffset = 0;
|
||||
UInt32 diskStartNumber = 0;
|
||||
CExtraBlock extraBlock;
|
||||
ReadExtra(item.LocalExtraSize, extraBlock, item.UnPackSize, item.PackSize,
|
||||
localHeaderOffset, diskStartNumber);
|
||||
}
|
||||
|
||||
if (item.HasDescriptor())
|
||||
{
|
||||
const int kBufferSize = (1 << 12);
|
||||
Byte buffer[kBufferSize];
|
||||
|
||||
UInt32 numBytesInBuffer = 0;
|
||||
UInt32 packedSize = 0;
|
||||
|
||||
bool descriptorWasFound = false;
|
||||
while (true)
|
||||
{
|
||||
UInt32 processedSize;
|
||||
RINOK(ReadBytes(buffer + numBytesInBuffer,
|
||||
kBufferSize - numBytesInBuffer, &processedSize));
|
||||
numBytesInBuffer += processedSize;
|
||||
if (numBytesInBuffer < NFileHeader::kDataDescriptorSize)
|
||||
ThrowIncorrectArchiveException();
|
||||
UInt32 i;
|
||||
for (i = 0; i <= numBytesInBuffer - NFileHeader::kDataDescriptorSize; i++)
|
||||
{
|
||||
// descriptorSignature field is Info-ZIP's extension
|
||||
// to Zip specification.
|
||||
UInt32 descriptorSignature = GetUInt32(buffer + i);
|
||||
|
||||
// !!!! It must be fixed for Zip64 archives
|
||||
UInt32 descriptorPackSize = GetUInt32(buffer + i + 8);
|
||||
if (descriptorSignature== NSignature::kDataDescriptor &&
|
||||
descriptorPackSize == packedSize + i)
|
||||
{
|
||||
descriptorWasFound = true;
|
||||
item.FileCRC = GetUInt32(buffer + i + 4);
|
||||
item.PackSize = descriptorPackSize;
|
||||
item.UnPackSize = GetUInt32(buffer + i + 12);
|
||||
IncreaseRealPosition(Int64(Int32(0 - (numBytesInBuffer - i -
|
||||
NFileHeader::kDataDescriptorSize))));
|
||||
break;
|
||||
};
|
||||
}
|
||||
if (descriptorWasFound)
|
||||
break;
|
||||
packedSize += i;
|
||||
int j;
|
||||
for (j = 0; i < numBytesInBuffer; i++, j++)
|
||||
buffer[j] = buffer[i];
|
||||
numBytesInBuffer = j;
|
||||
}
|
||||
}
|
||||
else
|
||||
IncreaseRealPosition(item.PackSize);
|
||||
|
||||
RINOK(ReadLocalItem(item));
|
||||
item.FromLocal = true;
|
||||
ReadLocalItemDescriptor(item);
|
||||
items.Add(item);
|
||||
if (progress != 0)
|
||||
{
|
||||
@@ -370,8 +584,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr
|
||||
if (!ReadUInt32(m_Signature))
|
||||
break;
|
||||
}
|
||||
UInt64 centralDirectorySize = 0;
|
||||
UInt64 centralDirectoryStartOffset = m_Position - 4;
|
||||
cdOffset = m_Position - 4;
|
||||
for(int i = 0; i < items.Size(); i++)
|
||||
{
|
||||
if (progress != 0)
|
||||
@@ -379,152 +592,143 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr
|
||||
UInt64 numItems = items.Size();
|
||||
RINOK(progress->SetCompleted(&numItems));
|
||||
}
|
||||
// if(m_Signature == NSignature::kEndOfCentralDir)
|
||||
// break;
|
||||
if(m_Signature != NSignature::kCentralFileHeader)
|
||||
ThrowIncorrectArchiveException();
|
||||
|
||||
// NFileHeader::CBlock header;
|
||||
// SafeReadBytes(&header, sizeof(header));
|
||||
return S_FALSE;
|
||||
|
||||
Byte headerMadeByVersionVersion = ReadByte();
|
||||
Byte headerMadeByVersionHostOS = ReadByte();
|
||||
Byte centalHeaderExtractVersionVersion = ReadByte();
|
||||
Byte centalHeaderExtractVersionHostOS = ReadByte();
|
||||
UInt16 headerFlags = ReadUInt16() & NFileHeader::NFlags::kUsedBitsMask;
|
||||
UInt16 headerCompressionMethod = ReadUInt16();
|
||||
UInt32 headerTime = ReadUInt32();
|
||||
UInt32 headerFileCRC = ReadUInt32();
|
||||
UInt64 headerPackSize = ReadUInt32();
|
||||
UInt64 headerUnPackSize = ReadUInt32();
|
||||
UInt16 headerNameSize = ReadUInt16();
|
||||
UInt16 headerExtraSize = ReadUInt16();
|
||||
UInt16 headerCommentSize = ReadUInt16();
|
||||
UInt32 headerDiskNumberStart = ReadUInt16();
|
||||
UInt16 headerInternalAttributes = ReadUInt16();
|
||||
UInt32 headerExternalAttributes = ReadUInt32();
|
||||
UInt64 localHeaderOffset = ReadUInt32();
|
||||
AString centralName = ReadFileName(headerNameSize);
|
||||
|
||||
// item.Name = ReadFileName(fileNameSize);
|
||||
CItemEx cdItem;
|
||||
RINOK(ReadCdItem(cdItem));
|
||||
|
||||
CExtraBlock centralExtra;
|
||||
if (headerExtraSize > 0)
|
||||
if (i == 0)
|
||||
{
|
||||
ReadExtra(headerExtraSize, centralExtra, headerUnPackSize, headerPackSize, localHeaderOffset, headerDiskNumberStart);
|
||||
if (cdItem.LocalHeaderPosition == 0)
|
||||
m_ArchiveInfo.Base = m_ArchiveInfo.StartPosition;
|
||||
}
|
||||
|
||||
|
||||
int index;
|
||||
int left = 0, right = items.Size();
|
||||
while(true)
|
||||
for (;;)
|
||||
{
|
||||
if (left >= right)
|
||||
ThrowIncorrectArchiveException();
|
||||
return S_FALSE;
|
||||
index = (left + right) / 2;
|
||||
UInt64 position = items[index].LocalHeaderPosition;
|
||||
if (localHeaderOffset == position)
|
||||
UInt64 position = items[index].LocalHeaderPosition - m_ArchiveInfo.Base;
|
||||
if (cdItem.LocalHeaderPosition == position)
|
||||
break;
|
||||
if (localHeaderOffset < position)
|
||||
if (cdItem.LocalHeaderPosition < position)
|
||||
right = index;
|
||||
else
|
||||
left = index + 1;
|
||||
}
|
||||
CItemEx &item = items[index];
|
||||
item.MadeByVersion.Version = headerMadeByVersionVersion;
|
||||
item.MadeByVersion.HostOS = headerMadeByVersionHostOS;
|
||||
item.CentralExtra = centralExtra;
|
||||
item.LocalHeaderPosition = cdItem.LocalHeaderPosition;
|
||||
item.MadeByVersion = cdItem.MadeByVersion;
|
||||
item.CentralExtra = cdItem.CentralExtra;
|
||||
|
||||
if (
|
||||
// item.ExtractVersion != centalHeaderExtractVersion ||
|
||||
item.Flags != headerFlags ||
|
||||
item.CompressionMethod != headerCompressionMethod ||
|
||||
// item.Time != header.Time ||
|
||||
item.FileCRC != headerFileCRC)
|
||||
ThrowIncorrectArchiveException();
|
||||
|
||||
if (item.Name.Length() != centralName.Length())
|
||||
ThrowIncorrectArchiveException(); // test it maybe better compare names
|
||||
item.Name = centralName;
|
||||
|
||||
// item.CentralExtraPosition = m_Position;
|
||||
// item.CentralExtraSize = headerExtraSize;
|
||||
// item.CommentSize = headerCommentSize;
|
||||
if (headerDiskNumberStart != 0)
|
||||
throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);
|
||||
item.InternalAttributes = headerInternalAttributes;
|
||||
item.ExternalAttributes = headerExternalAttributes;
|
||||
|
||||
// May be these strings must be deleted
|
||||
if (item.IsDirectory())
|
||||
{
|
||||
// if (item.PackSize != 0 /* || item.UnPackSize != 0 */)
|
||||
// ThrowIncorrectArchiveException();
|
||||
item.UnPackSize = 0;
|
||||
}
|
||||
|
||||
UInt32 currentRecordSize = 4 + NFileHeader::kCentralBlockSize +
|
||||
headerNameSize + headerExtraSize + headerCommentSize;
|
||||
|
||||
centralDirectorySize += currentRecordSize;
|
||||
|
||||
// IncreaseRealPosition(headerExtraSize);
|
||||
|
||||
if (
|
||||
item.PackSize != headerPackSize ||
|
||||
item.UnPackSize != headerUnPackSize
|
||||
)
|
||||
ThrowIncorrectArchiveException();
|
||||
|
||||
// IncreaseRealPosition(headerCommentSize);
|
||||
ReadBuffer(item.Comment, headerCommentSize);
|
||||
// item.ExtractVersion != cdItem.ExtractVersion ||
|
||||
item.Flags != cdItem.Flags ||
|
||||
item.CompressionMethod != cdItem.CompressionMethod ||
|
||||
// item.Time != cdItem.Time ||
|
||||
item.FileCRC != cdItem.FileCRC)
|
||||
return S_FALSE;
|
||||
|
||||
if (item.Name.Length() != cdItem.Name.Length() ||
|
||||
item.PackSize != cdItem.PackSize ||
|
||||
item.UnPackSize != cdItem.UnPackSize
|
||||
)
|
||||
return S_FALSE;
|
||||
item.Name = cdItem.Name;
|
||||
item.InternalAttributes = cdItem.InternalAttributes;
|
||||
item.ExternalAttributes = cdItem.ExternalAttributes;
|
||||
item.Comment = cdItem.Comment;
|
||||
item.FromCentral = cdItem.FromCentral;
|
||||
if (!ReadUInt32(m_Signature))
|
||||
break;
|
||||
return S_FALSE;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress)
|
||||
{
|
||||
// m_Signature must be kLocalFileHeaderSignature or
|
||||
// kEndOfCentralDirSignature
|
||||
// m_Position points to next byte after signature
|
||||
|
||||
items.Clear();
|
||||
if (progress != 0)
|
||||
{
|
||||
UInt64 numItems = items.Size();
|
||||
RINOK(progress->SetCompleted(&numItems));
|
||||
}
|
||||
|
||||
UInt64 cdSize, cdStartOffset;
|
||||
HRESULT res = ReadCd(items, cdStartOffset, cdSize);
|
||||
if (res != S_FALSE && res != S_OK)
|
||||
return res;
|
||||
|
||||
/*
|
||||
if (res != S_OK)
|
||||
return res;
|
||||
res = S_FALSE;
|
||||
*/
|
||||
|
||||
if (res == S_FALSE)
|
||||
{
|
||||
m_ArchiveInfo.Base = 0;
|
||||
RINOK(m_Stream->Seek(m_ArchiveInfo.StartPosition, STREAM_SEEK_SET, &m_Position));
|
||||
if (m_Position != m_ArchiveInfo.StartPosition)
|
||||
return S_FALSE;
|
||||
if (!ReadUInt32(m_Signature))
|
||||
return S_FALSE;
|
||||
RINOK(ReadLocalsAndCd(items, progress, cdStartOffset));
|
||||
cdSize = (m_Position - 4) - cdStartOffset;
|
||||
cdStartOffset -= m_ArchiveInfo.Base;
|
||||
}
|
||||
|
||||
UInt32 thisDiskNumber = 0;
|
||||
UInt32 startCDDiskNumber = 0;
|
||||
UInt64 numEntriesInCDOnThisDisk = 0;
|
||||
UInt64 numEntriesInCD = 0;
|
||||
UInt64 cdSize = 0;
|
||||
UInt64 cdSizeFromRecord = 0;
|
||||
UInt64 cdStartOffsetFromRecord = 0;
|
||||
bool isZip64 = false;
|
||||
UInt64 zip64EndOfCDStartOffset = m_Position - 4;
|
||||
UInt64 zip64EcdStartOffset = m_Position - 4 - m_ArchiveInfo.Base;
|
||||
if(m_Signature == NSignature::kZip64EndOfCentralDir)
|
||||
{
|
||||
isZip64 = true;
|
||||
UInt64 recordSize = ReadUInt64();
|
||||
UInt16 versionMade = ReadUInt16();
|
||||
UInt16 versionNeedExtract = ReadUInt16();
|
||||
/* UInt16 versionMade = */ ReadUInt16();
|
||||
/* UInt16 versionNeedExtract = */ ReadUInt16();
|
||||
thisDiskNumber = ReadUInt32();
|
||||
startCDDiskNumber = ReadUInt32();
|
||||
numEntriesInCDOnThisDisk = ReadUInt64();
|
||||
numEntriesInCD = ReadUInt64();
|
||||
cdSize = ReadUInt64();
|
||||
cdSizeFromRecord = ReadUInt64();
|
||||
cdStartOffsetFromRecord = ReadUInt64();
|
||||
IncreaseRealPosition(recordSize - kZip64EndOfCentralDirRecordSize);
|
||||
IncreaseRealPosition(recordSize - kZip64EcdSize);
|
||||
if (!ReadUInt32(m_Signature))
|
||||
return S_FALSE;
|
||||
if (thisDiskNumber != 0 || startCDDiskNumber != 0)
|
||||
throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);
|
||||
if (numEntriesInCDOnThisDisk != items.Size() ||
|
||||
numEntriesInCD != items.Size() ||
|
||||
cdSize != centralDirectorySize ||
|
||||
(cdStartOffsetFromRecord != centralDirectoryStartOffset &&
|
||||
cdSizeFromRecord != cdSize ||
|
||||
(cdStartOffsetFromRecord != cdStartOffset &&
|
||||
(!items.IsEmpty())))
|
||||
ThrowIncorrectArchiveException();
|
||||
return S_FALSE;
|
||||
}
|
||||
if(m_Signature == NSignature::kZip64EndOfCentralDirLocator)
|
||||
{
|
||||
UInt32 startEndCDDiskNumber = ReadUInt32();
|
||||
/* UInt32 startEndCDDiskNumber = */ ReadUInt32();
|
||||
UInt64 endCDStartOffset = ReadUInt64();
|
||||
UInt32 numberOfDisks = ReadUInt32();
|
||||
if (zip64EndOfCDStartOffset != endCDStartOffset)
|
||||
ThrowIncorrectArchiveException();
|
||||
/* UInt32 numberOfDisks = */ ReadUInt32();
|
||||
if (zip64EcdStartOffset != endCDStartOffset)
|
||||
return S_FALSE;
|
||||
if (!ReadUInt32(m_Signature))
|
||||
return S_FALSE;
|
||||
}
|
||||
if(m_Signature != NSignature::kEndOfCentralDir)
|
||||
ThrowIncorrectArchiveException();
|
||||
return S_FALSE;
|
||||
|
||||
UInt16 thisDiskNumber16 = ReadUInt16();
|
||||
if (!isZip64 || thisDiskNumber16)
|
||||
@@ -542,9 +746,9 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr
|
||||
if (!isZip64 || numEntriesInCD16 != 0xFFFF)
|
||||
numEntriesInCD = numEntriesInCD16;
|
||||
|
||||
UInt32 cdSize32 = ReadUInt32();
|
||||
if (!isZip64 || cdSize32 != 0xFFFFFFFF)
|
||||
cdSize = cdSize32;
|
||||
UInt32 cdSizeFromRecord32 = ReadUInt32();
|
||||
if (!isZip64 || cdSizeFromRecord32 != 0xFFFFFFFF)
|
||||
cdSizeFromRecord = cdSizeFromRecord32;
|
||||
|
||||
UInt32 cdStartOffsetFromRecord32 = ReadUInt32();
|
||||
if (!isZip64 || cdStartOffsetFromRecord32 != 0xFFFFFFFF)
|
||||
@@ -557,10 +761,10 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr
|
||||
throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);
|
||||
if ((UInt16)numEntriesInCDOnThisDisk != ((UInt16)items.Size()) ||
|
||||
(UInt16)numEntriesInCD != ((UInt16)items.Size()) ||
|
||||
(UInt32)cdSize != (UInt32)centralDirectorySize ||
|
||||
((UInt32)(cdStartOffsetFromRecord) != (UInt32)centralDirectoryStartOffset &&
|
||||
(UInt32)cdSizeFromRecord != (UInt32)cdSize ||
|
||||
((UInt32)(cdStartOffsetFromRecord) != (UInt32)cdStartOffset &&
|
||||
(!items.IsEmpty())))
|
||||
ThrowIncorrectArchiveException();
|
||||
return S_FALSE;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -569,8 +773,9 @@ ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 siz
|
||||
{
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> inStream(streamSpec);
|
||||
SeekInArchive(position);
|
||||
streamSpec->Init(m_Stream, size);
|
||||
SeekInArchive(m_ArchiveInfo.Base + position);
|
||||
streamSpec->SetStream(m_Stream);
|
||||
streamSpec->Init(size);
|
||||
return inStream.Detach();
|
||||
}
|
||||
|
||||
|
||||
@@ -33,9 +33,16 @@ public:
|
||||
class CInArchiveInfo
|
||||
{
|
||||
public:
|
||||
UInt64 Base;
|
||||
UInt64 StartPosition;
|
||||
CByteBuffer Comment;
|
||||
void Clear() { Comment.SetCapacity(0); }
|
||||
CInArchiveInfo(): Base(0), StartPosition(0) {}
|
||||
void Clear()
|
||||
{
|
||||
Base = 0;
|
||||
StartPosition = 0;
|
||||
Comment.SetCapacity(0);
|
||||
}
|
||||
};
|
||||
|
||||
class CProgressVirt
|
||||
@@ -44,6 +51,13 @@ public:
|
||||
STDMETHOD(SetCompleted)(const UInt64 *numFiles) PURE;
|
||||
};
|
||||
|
||||
struct CCdInfo
|
||||
{
|
||||
// UInt64 NumEntries;
|
||||
UInt64 Size;
|
||||
UInt64 Offset;
|
||||
};
|
||||
|
||||
class CInArchive
|
||||
{
|
||||
CMyComPtr<IInStream> m_Stream;
|
||||
@@ -53,6 +67,8 @@ class CInArchive
|
||||
CInArchiveInfo m_ArchiveInfo;
|
||||
AString m_NameBuffer;
|
||||
|
||||
HRESULT Seek(UInt64 offset);
|
||||
|
||||
bool FindAndReadMarker(const UInt64 *searchHeaderSizeLimit);
|
||||
bool ReadUInt32(UInt32 &signature);
|
||||
AString ReadFileName(UInt32 nameSize);
|
||||
@@ -67,16 +83,24 @@ class CInArchive
|
||||
UInt64 ReadUInt64();
|
||||
|
||||
void IncreaseRealPosition(UInt64 addValue);
|
||||
void ThrowIncorrectArchiveException();
|
||||
|
||||
void ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock,
|
||||
UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber);
|
||||
HRESULT ReadLocalItem(CItemEx &item);
|
||||
HRESULT ReadLocalItemDescriptor(CItemEx &item);
|
||||
HRESULT ReadCdItem(CItemEx &item);
|
||||
HRESULT TryEcd64(UInt64 offset, CCdInfo &cdInfo);
|
||||
HRESULT FindCd(CCdInfo &cdInfo);
|
||||
HRESULT TryReadCd(CObjectVector<CItemEx> &items, UInt64 cdOffset, UInt64 cdSize);
|
||||
HRESULT ReadCd(CObjectVector<CItemEx> &items, UInt64 &cdOffset, UInt64 &cdSize);
|
||||
HRESULT ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt *progress, UInt64 &cdOffset);
|
||||
public:
|
||||
HRESULT ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress);
|
||||
HRESULT ReadLocalItemAfterCdItem(CItemEx &item);
|
||||
HRESULT ReadLocalItemAfterCdItemFull(CItemEx &item);
|
||||
bool Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit);
|
||||
void Close();
|
||||
void GetArchiveInfo(CInArchiveInfo &archiveInfo) const;
|
||||
void DirectGetBytes(void *data, UInt32 num);
|
||||
bool SeekInArchive(UInt64 position);
|
||||
ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size);
|
||||
IInStream* CreateStream();
|
||||
|
||||
@@ -19,31 +19,38 @@ bool operator!=(const CVersion &v1, const CVersion &v2)
|
||||
return !(v1 == v2);
|
||||
}
|
||||
|
||||
bool CItem::IsEncrypted() const
|
||||
bool CLocalItem::IsEncrypted() const
|
||||
{ return (Flags & NFileHeader::NFlags::kEncryptedMask) != 0; }
|
||||
bool CItem::HasDescriptor() const
|
||||
bool CLocalItem::HasDescriptor() const
|
||||
{ return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; }
|
||||
|
||||
bool CItem::IsImplodeBigDictionary() const
|
||||
bool CLocalItem::IsImplodeBigDictionary() const
|
||||
{
|
||||
if (CompressionMethod != NFileHeader::NCompressionMethod::kImploded)
|
||||
throw 12312212;
|
||||
return (Flags & NFileHeader::NFlags::kImplodeDictionarySizeMask) != 0;
|
||||
}
|
||||
|
||||
bool CItem::IsImplodeLiteralsOn() const
|
||||
bool CLocalItem::IsImplodeLiteralsOn() const
|
||||
{
|
||||
if (CompressionMethod != NFileHeader::NCompressionMethod::kImploded)
|
||||
if (CompressionMethod != NFileHeader::NCompressionMethod::kImploded)
|
||||
throw 12312213;
|
||||
return (Flags & NFileHeader::NFlags::kImplodeLiteralsOnMask) != 0;
|
||||
}
|
||||
|
||||
static const char *kUnknownAttributes = "Unknown file attributes";
|
||||
|
||||
bool CLocalItem::IsDirectory() const
|
||||
{
|
||||
return NItemName::HasTailSlash(Name, GetCodePage());
|
||||
}
|
||||
|
||||
bool CItem::IsDirectory() const
|
||||
{
|
||||
if (NItemName::HasTailSlash(Name, GetCodePage()))
|
||||
return true;
|
||||
if (!FromCentral)
|
||||
return false;
|
||||
WORD highAttributes = WORD((ExternalAttributes >> 16 ) & 0xFFFF);
|
||||
switch(MadeByVersion.HostOS)
|
||||
{
|
||||
@@ -83,34 +90,40 @@ bool CItem::IsDirectory() const
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 CLocalItem::GetWinAttributes() const
|
||||
{
|
||||
DWORD winAttributes = 0;
|
||||
if (IsDirectory())
|
||||
winAttributes |= FILE_ATTRIBUTE_DIRECTORY;
|
||||
return winAttributes;
|
||||
}
|
||||
|
||||
UInt32 CItem::GetWinAttributes() const
|
||||
{
|
||||
DWORD winAttributes;
|
||||
DWORD winAttributes = 0;
|
||||
switch(MadeByVersion.HostOS)
|
||||
{
|
||||
case NFileHeader::NHostOS::kFAT:
|
||||
case NFileHeader::NHostOS::kNTFS:
|
||||
winAttributes = ExternalAttributes;
|
||||
if (FromCentral)
|
||||
winAttributes = ExternalAttributes;
|
||||
break;
|
||||
default:
|
||||
winAttributes = 0; // must be converted from unix value;;
|
||||
winAttributes = 0; // must be converted from unix value;
|
||||
}
|
||||
if (IsDirectory()) // test it;
|
||||
winAttributes |= FILE_ATTRIBUTE_DIRECTORY;
|
||||
return winAttributes;
|
||||
}
|
||||
|
||||
void CItem::ClearFlags()
|
||||
{ Flags = 0; }
|
||||
|
||||
void CItem::SetFlagBits(int startBitNumber, int numBits, int value)
|
||||
void CLocalItem::SetFlagBits(int startBitNumber, int numBits, int value)
|
||||
{
|
||||
WORD mask = ((1 << numBits) - 1) << startBitNumber;
|
||||
UInt16 mask = (UInt16)(((1 << numBits) - 1) << startBitNumber);
|
||||
Flags &= ~mask;
|
||||
Flags |= value << startBitNumber;
|
||||
}
|
||||
|
||||
void CItem::SetBitMask(int bitMask, bool enable)
|
||||
void CLocalItem::SetBitMask(int bitMask, bool enable)
|
||||
{
|
||||
if(enable)
|
||||
Flags |= bitMask;
|
||||
@@ -118,7 +131,7 @@ void CItem::SetBitMask(int bitMask, bool enable)
|
||||
Flags &= ~bitMask;
|
||||
}
|
||||
|
||||
void CItem::SetEncrypted(bool encrypted)
|
||||
void CLocalItem::SetEncrypted(bool encrypted)
|
||||
{ SetBitMask(NFileHeader::NFlags::kEncryptedMask, encrypted); }
|
||||
|
||||
}}
|
||||
|
||||
@@ -27,6 +27,46 @@ struct CExtraSubBlock
|
||||
CByteBuffer Data;
|
||||
};
|
||||
|
||||
struct CWzAesExtraField
|
||||
{
|
||||
UInt16 VendorVersion; // 0x0001 - AE-1, 0x0002 - AE-2,
|
||||
// UInt16 VendorId; // "AE"
|
||||
Byte Strength; // 1 - 128-bit , 2 - 192-bit , 3 - 256-bit
|
||||
UInt16 Method;
|
||||
|
||||
CWzAesExtraField(): VendorVersion(2), Strength(3), Method(0) {}
|
||||
|
||||
bool NeedCrc() const { return (VendorVersion == 1); }
|
||||
|
||||
bool ParseFromSubBlock(const CExtraSubBlock &sb)
|
||||
{
|
||||
if (sb.ID != NFileHeader::NExtraID::kWzAES)
|
||||
return false;
|
||||
if (sb.Data.GetCapacity() < 7)
|
||||
return false;
|
||||
const Byte *p = (const Byte *)sb.Data;
|
||||
VendorVersion = (((UInt16)p[1]) << 8) | p[0];
|
||||
if (p[2] != 'A' || p[3] != 'E')
|
||||
return false;
|
||||
Strength = p[4];
|
||||
Method = (((UInt16)p[6]) << 16) | p[5];
|
||||
return true;
|
||||
}
|
||||
void SetSubBlock(CExtraSubBlock &sb) const
|
||||
{
|
||||
sb.Data.SetCapacity(7);
|
||||
sb.ID = NFileHeader::NExtraID::kWzAES;
|
||||
Byte *p = (Byte *)sb.Data;
|
||||
p[0] = (Byte)VendorVersion;
|
||||
p[1] = (Byte)(VendorVersion >> 8);
|
||||
p[2] = 'A';
|
||||
p[3] = 'E';
|
||||
p[4] = Strength;
|
||||
p[5] = (Byte)Method;
|
||||
p[6] = (Byte)(Method >> 8);
|
||||
}
|
||||
};
|
||||
|
||||
struct CExtraBlock
|
||||
{
|
||||
CObjectVector<CExtraSubBlock> SubBlocks;
|
||||
@@ -38,13 +78,38 @@ struct CExtraBlock
|
||||
res += SubBlocks[i].Data.GetCapacity() + 2 + 2;
|
||||
return res;
|
||||
}
|
||||
bool GetWzAesField(CWzAesExtraField &aesField) const
|
||||
{
|
||||
// size_t res = 0;
|
||||
for (int i = 0; i < SubBlocks.Size(); i++)
|
||||
if (aesField.ParseFromSubBlock(SubBlocks[i]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HasWzAesField() const
|
||||
{
|
||||
CWzAesExtraField aesField;
|
||||
return GetWzAesField(aesField);
|
||||
}
|
||||
|
||||
void RemoveUnknownSubBlocks()
|
||||
{
|
||||
for (int i = SubBlocks.Size() - 1; i >= 0;)
|
||||
{
|
||||
const CExtraSubBlock &subBlock = SubBlocks[i];
|
||||
if (subBlock.ID != NFileHeader::NExtraID::kWzAES)
|
||||
SubBlocks.Delete(i);
|
||||
else
|
||||
i--;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CItem
|
||||
class CLocalItem
|
||||
{
|
||||
public:
|
||||
CVersion MadeByVersion;
|
||||
CVersion ExtractVersion;
|
||||
UInt16 Flags;
|
||||
UInt16 CompressionMethod;
|
||||
@@ -52,16 +117,10 @@ public:
|
||||
UInt32 FileCRC;
|
||||
UInt64 PackSize;
|
||||
UInt64 UnPackSize;
|
||||
UInt16 InternalAttributes;
|
||||
UInt32 ExternalAttributes;
|
||||
|
||||
AString Name;
|
||||
|
||||
UInt64 LocalHeaderPosition;
|
||||
UInt16 LocalExtraSize;
|
||||
|
||||
CExtraBlock CentralExtra;
|
||||
CByteBuffer Comment;
|
||||
|
||||
CExtraBlock LocalExtra;
|
||||
|
||||
bool IsEncrypted() const;
|
||||
|
||||
@@ -74,19 +133,55 @@ public:
|
||||
|
||||
bool HasDescriptor() const;
|
||||
|
||||
WORD GetCodePage() const
|
||||
{
|
||||
return (MadeByVersion.HostOS == NFileHeader::NHostOS::kFAT
|
||||
|| MadeByVersion.HostOS == NFileHeader::NHostOS::kNTFS
|
||||
) ? CP_OEMCP : CP_ACP;
|
||||
}
|
||||
|
||||
private:
|
||||
void SetFlagBits(int startBitNumber, int numBits, int value);
|
||||
void SetBitMask(int bitMask, bool enable);
|
||||
public:
|
||||
void ClearFlags();
|
||||
void ClearFlags() { Flags = 0; }
|
||||
void SetEncrypted(bool encrypted);
|
||||
|
||||
WORD GetCodePage() const
|
||||
{
|
||||
return CP_OEMCP;
|
||||
}
|
||||
};
|
||||
|
||||
class CItem: public CLocalItem
|
||||
{
|
||||
public:
|
||||
CVersion MadeByVersion;
|
||||
UInt16 InternalAttributes;
|
||||
UInt32 ExternalAttributes;
|
||||
|
||||
UInt64 LocalHeaderPosition;
|
||||
|
||||
CExtraBlock CentralExtra;
|
||||
CByteBuffer Comment;
|
||||
|
||||
bool FromLocal;
|
||||
bool FromCentral;
|
||||
|
||||
bool IsDirectory() const;
|
||||
UInt32 GetWinAttributes() const;
|
||||
|
||||
bool IsThereCrc() const
|
||||
{
|
||||
if (CompressionMethod == NFileHeader::NCompressionMethod::kWzAES)
|
||||
{
|
||||
CWzAesExtraField aesField;
|
||||
if (CentralExtra.GetWzAesField(aesField))
|
||||
return aesField.NeedCrc();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
WORD GetCodePage() const
|
||||
{
|
||||
return (WORD)((MadeByVersion.HostOS == NFileHeader::NHostOS::kFAT
|
||||
|| MadeByVersion.HostOS == NFileHeader::NHostOS::kNTFS
|
||||
) ? CP_OEMCP : CP_ACP);
|
||||
}
|
||||
CItem() : FromLocal(false), FromCentral(false) {}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -13,6 +13,7 @@ class CItemEx: public CItem
|
||||
{
|
||||
public:
|
||||
UInt32 FileHeaderWithNameSize;
|
||||
UInt16 LocalExtraSize;
|
||||
|
||||
UInt64 GetLocalFullSize() const
|
||||
{ return FileHeaderWithNameSize + LocalExtraSize + PackSize +
|
||||
|
||||
@@ -22,26 +22,28 @@ void COutArchive::MoveBasePosition(UInt64 distanceToMove)
|
||||
m_BasePosition += distanceToMove; // test overflow
|
||||
}
|
||||
|
||||
void COutArchive::PrepareWriteCompressedDataZip64(UInt16 fileNameLength, bool isZip64)
|
||||
void COutArchive::PrepareWriteCompressedDataZip64(UInt16 fileNameLength, bool isZip64, bool aesEncryption)
|
||||
{
|
||||
m_IsZip64 = isZip64;
|
||||
m_ExtraSize = isZip64 ? (4 + 8 + 8) : 0;
|
||||
if (aesEncryption)
|
||||
m_ExtraSize += 4 + 7;
|
||||
m_LocalFileHeaderSize = 4 + NFileHeader::kLocalBlockSize + fileNameLength + m_ExtraSize;
|
||||
}
|
||||
|
||||
void COutArchive::PrepareWriteCompressedData(UInt16 fileNameLength, UInt64 unPackSize)
|
||||
void COutArchive::PrepareWriteCompressedData(UInt16 fileNameLength, UInt64 unPackSize, bool aesEncryption)
|
||||
{
|
||||
// We test it to 0xF8000000 to support case when compressed size
|
||||
// can be larger than uncompressed size.
|
||||
PrepareWriteCompressedDataZip64(fileNameLength, unPackSize >= 0xF8000000);
|
||||
PrepareWriteCompressedDataZip64(fileNameLength, unPackSize >= 0xF8000000, aesEncryption);
|
||||
}
|
||||
|
||||
void COutArchive::PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize)
|
||||
void COutArchive::PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize, bool aesEncryption)
|
||||
{
|
||||
bool isUnPack64 = unPackSize >= 0xFFFFFFFF;
|
||||
bool isPack64 = packSize >= 0xFFFFFFFF;
|
||||
bool isZip64 = isPack64 || isUnPack64;
|
||||
PrepareWriteCompressedDataZip64(fileNameLength, isZip64);
|
||||
PrepareWriteCompressedDataZip64(fileNameLength, isZip64, aesEncryption);
|
||||
}
|
||||
|
||||
void COutArchive::WriteBytes(const void *buffer, UInt32 size)
|
||||
@@ -86,7 +88,21 @@ void COutArchive::WriteUInt64(UInt64 value)
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT COutArchive::WriteLocalHeader(const CItem &item)
|
||||
void COutArchive::WriteExtra(const CExtraBlock &extra)
|
||||
{
|
||||
if (extra.SubBlocks.Size() != 0)
|
||||
{
|
||||
for (int i = 0; i < extra.SubBlocks.Size(); i++)
|
||||
{
|
||||
const CExtraSubBlock &subBlock = extra.SubBlocks[i];
|
||||
WriteUInt16(subBlock.ID);
|
||||
WriteUInt16((UInt16)subBlock.Data.GetCapacity());
|
||||
WriteBytes(subBlock.Data, (UInt32)subBlock.Data.GetCapacity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT COutArchive::WriteLocalHeader(const CLocalItem &item)
|
||||
{
|
||||
m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL);
|
||||
|
||||
@@ -101,29 +117,32 @@ HRESULT COutArchive::WriteLocalHeader(const CItem &item)
|
||||
WriteUInt32(item.FileCRC);
|
||||
WriteUInt32(isZip64 ? 0xFFFFFFFF: (UInt32)item.PackSize);
|
||||
WriteUInt32(isZip64 ? 0xFFFFFFFF: (UInt32)item.UnPackSize);
|
||||
WriteUInt16(item.Name.Length());
|
||||
UInt16 localExtraSize = isZip64 ? (4 + 16): 0;
|
||||
if (localExtraSize > m_ExtraSize)
|
||||
return E_FAIL;
|
||||
WriteUInt16(m_ExtraSize); // test it;
|
||||
WriteBytes((const char *)item.Name, item.Name.Length());
|
||||
if (m_ExtraSize > 0)
|
||||
WriteUInt16((UInt16)item.Name.Length());
|
||||
{
|
||||
UInt16 remain = m_ExtraSize - 4;
|
||||
WriteUInt16(0x1); // Zip64 Tag;
|
||||
WriteUInt16(remain);
|
||||
if (isZip64)
|
||||
{
|
||||
WriteUInt64(item.UnPackSize);
|
||||
WriteUInt64(item.PackSize);
|
||||
remain -= 16;
|
||||
}
|
||||
for (int i = 0; i < remain; i++)
|
||||
WriteByte(0);
|
||||
UInt16 localExtraSize = (UInt16)((isZip64 ? (4 + 16): 0) + item.LocalExtra.GetSize());
|
||||
if (localExtraSize > m_ExtraSize)
|
||||
return E_FAIL;
|
||||
}
|
||||
WriteUInt16((UInt16)m_ExtraSize); // test it;
|
||||
WriteBytes((const char *)item.Name, item.Name.Length());
|
||||
|
||||
UInt32 extraPos = 0;
|
||||
if (isZip64)
|
||||
{
|
||||
extraPos += 4 + 16;
|
||||
WriteUInt16(NFileHeader::NExtraID::kZip64);
|
||||
WriteUInt16(16);
|
||||
WriteUInt64(item.UnPackSize);
|
||||
WriteUInt64(item.PackSize);
|
||||
}
|
||||
|
||||
WriteExtra(item.LocalExtra);
|
||||
extraPos += (UInt32)item.LocalExtra.GetSize();
|
||||
for (; extraPos < m_ExtraSize; extraPos++)
|
||||
WriteByte(0);
|
||||
|
||||
MoveBasePosition(item.PackSize);
|
||||
m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL);
|
||||
return S_OK;
|
||||
return m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL);
|
||||
}
|
||||
|
||||
void COutArchive::WriteCentralHeader(const CItem &item)
|
||||
@@ -146,10 +165,10 @@ void COutArchive::WriteCentralHeader(const CItem &item)
|
||||
WriteUInt32(item.FileCRC);
|
||||
WriteUInt32(isPack64 ? 0xFFFFFFFF: (UInt32)item.PackSize);
|
||||
WriteUInt32(isUnPack64 ? 0xFFFFFFFF: (UInt32)item.UnPackSize);
|
||||
WriteUInt16(item.Name.Length());
|
||||
UInt16 zip64ExtraSize = (isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0);
|
||||
UInt16 centralExtraSize = isZip64 ? (4 + zip64ExtraSize) : 0;
|
||||
centralExtraSize += (UInt16)item.CentralExtra.GetSize();
|
||||
WriteUInt16((UInt16)item.Name.Length());
|
||||
UInt16 zip64ExtraSize = (UInt16)((isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0));
|
||||
UInt16 centralExtraSize = (UInt16)(isZip64 ? (4 + zip64ExtraSize) : 0);
|
||||
centralExtraSize = (UInt16)(centralExtraSize + item.CentralExtra.GetSize());
|
||||
WriteUInt16(centralExtraSize); // test it;
|
||||
WriteUInt16((UInt16)item.Comment.GetCapacity());
|
||||
WriteUInt16(0); // DiskNumberStart;
|
||||
@@ -159,7 +178,7 @@ void COutArchive::WriteCentralHeader(const CItem &item)
|
||||
WriteBytes((const char *)item.Name, item.Name.Length());
|
||||
if (isZip64)
|
||||
{
|
||||
WriteUInt16(0x1); // Zip64 Tag;
|
||||
WriteUInt16(NFileHeader::NExtraID::kZip64);
|
||||
WriteUInt16(zip64ExtraSize);
|
||||
if(isUnPack64)
|
||||
WriteUInt64(item.UnPackSize);
|
||||
@@ -168,16 +187,7 @@ void COutArchive::WriteCentralHeader(const CItem &item)
|
||||
if(isPosition64)
|
||||
WriteUInt64(item.LocalHeaderPosition);
|
||||
}
|
||||
if (item.CentralExtra.SubBlocks.Size() != 0)
|
||||
{
|
||||
for (int i = 0; i < item.CentralExtra.SubBlocks.Size(); i++)
|
||||
{
|
||||
CExtraSubBlock subBlock = item.CentralExtra.SubBlocks[i];
|
||||
WriteUInt16(subBlock.ID);
|
||||
WriteUInt16((UInt16)subBlock.Data.GetCapacity());
|
||||
WriteBytes(subBlock.Data, (UInt32)subBlock.Data.GetCapacity());
|
||||
}
|
||||
}
|
||||
WriteExtra(item.CentralExtra);
|
||||
if (item.Comment.GetCapacity() > 0)
|
||||
WriteBytes(item.Comment, (UInt32)item.Comment.GetCapacity());
|
||||
}
|
||||
@@ -199,7 +209,7 @@ void COutArchive::WriteCentralDir(const CObjectVector<CItem> &items, const CByte
|
||||
if (isZip64)
|
||||
{
|
||||
WriteUInt32(NSignature::kZip64EndOfCentralDir);
|
||||
WriteUInt64(kZip64EndOfCentralDirRecordSize); // ThisDiskNumber = 0;
|
||||
WriteUInt64(kZip64EcdSize); // ThisDiskNumber = 0;
|
||||
WriteUInt16(45); // version
|
||||
WriteUInt16(45); // version
|
||||
WriteUInt32(0); // ThisDiskNumber = 0;
|
||||
@@ -217,8 +227,8 @@ void COutArchive::WriteCentralDir(const CObjectVector<CItem> &items, const CByte
|
||||
WriteUInt32(NSignature::kEndOfCentralDir);
|
||||
WriteUInt16(0); // ThisDiskNumber = 0;
|
||||
WriteUInt16(0); // StartCentralDirectoryDiskNumber;
|
||||
WriteUInt16(items64 ? 0xFFFF: (UInt16)items.Size());
|
||||
WriteUInt16(items64 ? 0xFFFF: (UInt16)items.Size());
|
||||
WriteUInt16((UInt16)(items64 ? 0xFFFF: items.Size()));
|
||||
WriteUInt16((UInt16)(items64 ? 0xFFFF: items.Size()));
|
||||
WriteUInt32(cdSize64 ? 0xFFFFFFFF: (UInt32)cdSize);
|
||||
WriteUInt32(cdOffset64 ? 0xFFFFFFFF: (UInt32)cdOffset);
|
||||
UInt16 commentSize = (UInt16)comment.GetCapacity();
|
||||
|
||||
@@ -29,14 +29,15 @@ class COutArchive
|
||||
|
||||
void WriteExtraHeader(const CItem &item);
|
||||
void WriteCentralHeader(const CItem &item);
|
||||
void WriteExtra(const CExtraBlock &extra);
|
||||
public:
|
||||
void Create(IOutStream *outStream);
|
||||
void MoveBasePosition(UInt64 distanceToMove);
|
||||
UInt64 GetCurrentPosition() const { return m_BasePosition; };
|
||||
void PrepareWriteCompressedDataZip64(UInt16 fileNameLength, bool isZip64);
|
||||
void PrepareWriteCompressedData(UInt16 fileNameLength, UInt64 unPackSize);
|
||||
void PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize);
|
||||
HRESULT WriteLocalHeader(const CItem &item);
|
||||
void PrepareWriteCompressedDataZip64(UInt16 fileNameLength, bool isZip64, bool aesEncryption);
|
||||
void PrepareWriteCompressedData(UInt16 fileNameLength, UInt64 unPackSize, bool aesEncryption);
|
||||
void PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize, bool aesEncryption);
|
||||
HRESULT WriteLocalHeader(const CLocalItem &item);
|
||||
|
||||
void WriteCentralDir(const CObjectVector<CItem> &items, const CByteBuffer &comment);
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ZipUpdate.h"
|
||||
#include "ZipAddCommon.h"
|
||||
#include "ZipOut.h"
|
||||
@@ -10,180 +12,246 @@
|
||||
#include "Common/AutoPtr.h"
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Windows/Defs.h"
|
||||
#include "Windows/Thread.h"
|
||||
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
#ifdef COMPRESS_MT
|
||||
#include "../../Common/ProgressMt.h"
|
||||
#endif
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
#include "../../Common/OutMemStream.h"
|
||||
|
||||
#include "../../Compress/Copy/CopyCoder.h"
|
||||
|
||||
#include "../Common/InStreamWithCRC.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NSynchronization;
|
||||
|
||||
namespace NArchive {
|
||||
namespace NZip {
|
||||
|
||||
class CCriticalSectionLock2
|
||||
{
|
||||
CCriticalSection *_object;
|
||||
void Unlock() { if (_object != 0) _object->Leave(); }
|
||||
public:
|
||||
CCriticalSectionLock2(): _object(0) {}
|
||||
void Set(CCriticalSection &object) { _object = &object; _object->Enter(); }
|
||||
~CCriticalSectionLock2() { Unlock(); }
|
||||
};
|
||||
|
||||
static const Byte kMadeByHostOS = NFileHeader::NHostOS::kFAT;
|
||||
static const Byte kExtractHostOS = NFileHeader::NHostOS::kFAT;
|
||||
|
||||
static const Byte kMethodForDirectory = NFileHeader::NCompressionMethod::kStored;
|
||||
static const Byte kExtractVersionForDirectory = NFileHeader::NCompressionMethod::kStoreExtractVersion;
|
||||
|
||||
static HRESULT CopyBlock(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, ICompressProgressInfo *progress)
|
||||
{
|
||||
CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
|
||||
return copyCoder->Code(inStream, outStream, NULL, NULL, progress);
|
||||
}
|
||||
|
||||
HRESULT CopyBlockToArchive(ISequentialInStream *inStream,
|
||||
static HRESULT CopyBlockToArchive(ISequentialInStream *inStream,
|
||||
COutArchive &outArchive, ICompressProgressInfo *progress)
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> outStream;
|
||||
outArchive.CreateStreamForCopying(&outStream);
|
||||
return CopyBlock(inStream, outStream, progress);
|
||||
CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
|
||||
return copyCoder->Code(inStream, outStream, NULL, NULL, progress);
|
||||
}
|
||||
|
||||
static HRESULT WriteRange(IInStream *inStream,
|
||||
COutArchive &outArchive,
|
||||
const CUpdateRange &range,
|
||||
IProgress *progress,
|
||||
UInt64 ¤tComplexity)
|
||||
static HRESULT WriteRange(IInStream *inStream, COutArchive &outArchive,
|
||||
const CUpdateRange &range, ICompressProgressInfo *progress)
|
||||
{
|
||||
UInt64 position;
|
||||
inStream->Seek(range.Position, STREAM_SEEK_SET, &position);
|
||||
RINOK(inStream->Seek(range.Position, STREAM_SEEK_SET, &position));
|
||||
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec);
|
||||
streamSpec->Init(inStream, range.Size);
|
||||
streamSpec->SetStream(inStream);
|
||||
streamSpec->Init(range.Size);
|
||||
|
||||
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;
|
||||
localProgressSpec->Init(progress, true);
|
||||
|
||||
CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo;
|
||||
CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
|
||||
|
||||
localCompressProgressSpec->Init(localProgress, ¤tComplexity, ¤tComplexity);
|
||||
|
||||
HRESULT result = CopyBlockToArchive(inStreamLimited, outArchive, compressProgress);
|
||||
currentComplexity += range.Size;
|
||||
return result;
|
||||
RINOK(CopyBlockToArchive(inStreamLimited, outArchive, progress));
|
||||
return progress->SetRatioInfo(&range.Size, &range.Size);
|
||||
}
|
||||
|
||||
|
||||
static HRESULT UpdateOneFile(IInStream *inStream,
|
||||
static void SetFileHeader(
|
||||
COutArchive &archive,
|
||||
const CCompressionMethodMode &options,
|
||||
CAddCommon &compressor,
|
||||
const CUpdateItem &updateItem,
|
||||
UInt64 ¤tComplexity,
|
||||
IArchiveUpdateCallback *updateCallback,
|
||||
CItemEx &fileHeader,
|
||||
CMyComPtr<ISequentialInStream> &fileInStream2)
|
||||
CItem &item)
|
||||
{
|
||||
CMyComPtr<IInStream> fileInStream;
|
||||
if (fileInStream2)
|
||||
{
|
||||
RINOK(fileInStream2.QueryInterface(IID_IInStream, &fileInStream));
|
||||
}
|
||||
|
||||
item.UnPackSize = updateItem.Size;
|
||||
bool isDirectory;
|
||||
UInt64 fileSize = updateItem.Size;
|
||||
fileHeader.UnPackSize = fileSize;
|
||||
|
||||
if (updateItem.NewProperties)
|
||||
{
|
||||
isDirectory = updateItem.IsDirectory;
|
||||
fileHeader.Name = updateItem.Name;
|
||||
fileHeader.ExternalAttributes = updateItem.Attributes;
|
||||
fileHeader.Time = updateItem.Time;
|
||||
item.Name = updateItem.Name;
|
||||
item.ExternalAttributes = updateItem.Attributes;
|
||||
item.Time = updateItem.Time;
|
||||
}
|
||||
else
|
||||
isDirectory = fileHeader.IsDirectory();
|
||||
isDirectory = item.IsDirectory();
|
||||
|
||||
archive.PrepareWriteCompressedData(fileHeader.Name.Length(), fileSize);
|
||||
|
||||
fileHeader.LocalHeaderPosition = archive.GetCurrentPosition();
|
||||
fileHeader.MadeByVersion.HostOS = kMadeByHostOS;
|
||||
fileHeader.MadeByVersion.Version = NFileHeader::NCompressionMethod::kMadeByProgramVersion;
|
||||
item.LocalHeaderPosition = archive.GetCurrentPosition();
|
||||
item.MadeByVersion.HostOS = kMadeByHostOS;
|
||||
item.MadeByVersion.Version = NFileHeader::NCompressionMethod::kMadeByProgramVersion;
|
||||
|
||||
fileHeader.ExtractVersion.HostOS = kExtractHostOS;
|
||||
item.ExtractVersion.HostOS = kExtractHostOS;
|
||||
|
||||
fileHeader.InternalAttributes = 0; // test it
|
||||
fileHeader.ClearFlags();
|
||||
if(isDirectory)
|
||||
item.InternalAttributes = 0; // test it
|
||||
item.ClearFlags();
|
||||
item.SetEncrypted(!isDirectory && options.PasswordIsDefined);
|
||||
if (isDirectory)
|
||||
{
|
||||
fileHeader.ExtractVersion.Version = kExtractVersionForDirectory;
|
||||
fileHeader.CompressionMethod = kMethodForDirectory;
|
||||
|
||||
fileHeader.PackSize = 0;
|
||||
fileHeader.FileCRC = 0; // test it
|
||||
item.ExtractVersion.Version = kExtractVersionForDirectory;
|
||||
item.CompressionMethod = kMethodForDirectory;
|
||||
item.PackSize = 0;
|
||||
item.FileCRC = 0; // test it
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
CSequentialInStreamWithCRC *inSecStreamSpec = 0;
|
||||
CInStreamWithCRC *inStreamSpec = 0;
|
||||
CMyComPtr<ISequentialInStream> fileSecInStream;
|
||||
if (fileInStream)
|
||||
{
|
||||
inStreamSpec = new CInStreamWithCRC;
|
||||
fileSecInStream = inStreamSpec;
|
||||
inStreamSpec->Init(fileInStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
inSecStreamSpec = new CSequentialInStreamWithCRC;
|
||||
fileSecInStream = inSecStreamSpec;
|
||||
inSecStreamSpec->Init(fileInStream2);
|
||||
}
|
||||
|
||||
CCompressingResult compressingResult;
|
||||
CMyComPtr<IOutStream> outStream;
|
||||
archive.CreateStreamForCompressing(&outStream);
|
||||
|
||||
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;
|
||||
localProgressSpec->Init(updateCallback, true);
|
||||
|
||||
CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo;
|
||||
CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
|
||||
|
||||
localCompressProgressSpec->Init(localProgress, ¤tComplexity, NULL);
|
||||
|
||||
RINOK(compressor.Compress(fileSecInStream, outStream, fileSize, compressProgress, compressingResult));
|
||||
|
||||
fileHeader.PackSize = compressingResult.PackSize;
|
||||
fileHeader.CompressionMethod = compressingResult.Method;
|
||||
fileHeader.ExtractVersion.Version = compressingResult.ExtractVersion;
|
||||
if (inStreamSpec != 0)
|
||||
{
|
||||
fileHeader.FileCRC = inStreamSpec->GetCRC();
|
||||
fileHeader.UnPackSize = inStreamSpec->GetSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
fileHeader.FileCRC = inSecStreamSpec->GetCRC();
|
||||
fileHeader.UnPackSize = inSecStreamSpec->GetSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
fileHeader.SetEncrypted(!isDirectory && options.PasswordIsDefined);
|
||||
/*
|
||||
fileHeader.CommentSize = (updateItem.Commented) ?
|
||||
WORD(updateItem.CommentRange.Size) : 0;
|
||||
*/
|
||||
|
||||
fileHeader.LocalExtraSize = 0;
|
||||
|
||||
// fileHeader.CentralExtraSize = 0;
|
||||
|
||||
RINOK(archive.WriteLocalHeader(fileHeader));
|
||||
currentComplexity += fileSize;
|
||||
return updateCallback->SetOperationResult(
|
||||
NArchive::NUpdate::NOperationResult::kOK);
|
||||
}
|
||||
|
||||
static void SetItemInfoFromCompressingResult(const CCompressingResult &compressingResult,
|
||||
bool isAesMode, Byte aesKeyMode, CItem &item)
|
||||
{
|
||||
item.ExtractVersion.Version = compressingResult.ExtractVersion;
|
||||
item.CompressionMethod = compressingResult.Method;
|
||||
item.FileCRC = compressingResult.CRC;
|
||||
item.UnPackSize = compressingResult.UnpackSize;
|
||||
item.PackSize = compressingResult.PackSize;
|
||||
|
||||
item.LocalExtra.Clear();
|
||||
item.CentralExtra.Clear();
|
||||
|
||||
if (isAesMode)
|
||||
{
|
||||
CWzAesExtraField wzAesField;
|
||||
wzAesField.Strength = aesKeyMode;
|
||||
wzAesField.Method = compressingResult.Method;
|
||||
item.CompressionMethod = NFileHeader::NCompressionMethod::kWzAES;
|
||||
item.FileCRC = 0;
|
||||
CExtraSubBlock sb;
|
||||
wzAesField.SetSubBlock(sb);
|
||||
item.LocalExtra.SubBlocks.Add(sb);
|
||||
item.CentralExtra.SubBlocks.Add(sb);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef COMPRESS_MT
|
||||
|
||||
static DWORD WINAPI CoderThread(void *threadCoderInfo);
|
||||
|
||||
struct CThreadInfo
|
||||
{
|
||||
NWindows::CThread Thread;
|
||||
CAutoResetEvent *CompressEvent;
|
||||
CAutoResetEvent *CompressionCompletedEvent;
|
||||
bool ExitThread;
|
||||
|
||||
CMtCompressProgress *ProgressSpec;
|
||||
CMyComPtr<ICompressProgressInfo> Progress;
|
||||
|
||||
COutMemStream *OutStreamSpec;
|
||||
CMyComPtr<IOutStream> OutStream;
|
||||
CMyComPtr<ISequentialInStream> InStream;
|
||||
|
||||
CAddCommon Coder;
|
||||
HRESULT Result;
|
||||
CCompressingResult CompressingResult;
|
||||
|
||||
bool IsFree;
|
||||
UInt32 UpdateIndex;
|
||||
|
||||
CThreadInfo(const CCompressionMethodMode &options):
|
||||
CompressEvent(NULL),
|
||||
CompressionCompletedEvent(NULL),
|
||||
ExitThread(false),
|
||||
ProgressSpec(0),
|
||||
OutStreamSpec(0),
|
||||
Coder(options)
|
||||
{}
|
||||
|
||||
void CreateEvents()
|
||||
{
|
||||
CompressEvent = new CAutoResetEvent(false);
|
||||
CompressionCompletedEvent = new CAutoResetEvent(false);
|
||||
}
|
||||
bool CreateThread() { return Thread.Create(CoderThread, this); }
|
||||
~CThreadInfo();
|
||||
|
||||
void WaitAndCode();
|
||||
void StopWaitClose()
|
||||
{
|
||||
ExitThread = true;
|
||||
if (OutStreamSpec != 0)
|
||||
OutStreamSpec->StopWriting(E_ABORT);
|
||||
if (CompressEvent != NULL)
|
||||
CompressEvent->Set();
|
||||
Thread.Wait();
|
||||
Thread.Close();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CThreadInfo::~CThreadInfo()
|
||||
{
|
||||
if (CompressEvent != NULL)
|
||||
delete CompressEvent;
|
||||
if (CompressionCompletedEvent != NULL)
|
||||
delete CompressionCompletedEvent;
|
||||
}
|
||||
|
||||
void CThreadInfo::WaitAndCode()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
CompressEvent->Lock();
|
||||
if (ExitThread)
|
||||
return;
|
||||
Result = Coder.Compress(InStream, OutStream, Progress, CompressingResult);
|
||||
if (Result == S_OK && Progress)
|
||||
Result = Progress->SetRatioInfo(&CompressingResult.UnpackSize, &CompressingResult.PackSize);
|
||||
CompressionCompletedEvent->Set();
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD WINAPI CoderThread(void *threadCoderInfo)
|
||||
{
|
||||
((CThreadInfo *)threadCoderInfo)->WaitAndCode();
|
||||
return 0;
|
||||
}
|
||||
|
||||
class CThreads
|
||||
{
|
||||
public:
|
||||
CObjectVector<CThreadInfo> Threads;
|
||||
~CThreads()
|
||||
{
|
||||
for (int i = 0; i < Threads.Size(); i++)
|
||||
Threads[i].StopWaitClose();
|
||||
}
|
||||
};
|
||||
|
||||
struct CMemBlocks2: public CMemLockBlocks
|
||||
{
|
||||
CCompressingResult CompressingResult;
|
||||
bool Defined;
|
||||
bool Skip;
|
||||
CMemBlocks2(): Defined(false), Skip(false) {}
|
||||
};
|
||||
|
||||
class CMemRefs
|
||||
{
|
||||
public:
|
||||
CMemBlockManagerMt *Manager;
|
||||
CObjectVector<CMemBlocks2> Refs;
|
||||
CMemRefs(CMemBlockManagerMt *manager): Manager(manager) {} ;
|
||||
~CMemRefs()
|
||||
{
|
||||
for (int i = 0; i < Refs.Size(); i++)
|
||||
Refs[i].FreeOpt(Manager);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static HRESULT Update2(COutArchive &archive,
|
||||
CInArchive *inArchive,
|
||||
IInStream *inStream,
|
||||
const CObjectVector<CItemEx> &inputItems,
|
||||
const CObjectVector<CUpdateItem> &updateItems,
|
||||
@@ -192,6 +260,8 @@ static HRESULT Update2(COutArchive &archive,
|
||||
IArchiveUpdateCallback *updateCallback)
|
||||
{
|
||||
UInt64 complexity = 0;
|
||||
UInt64 numFilesToCompress = 0;
|
||||
UInt64 numBytesToCompress = 0;
|
||||
|
||||
int i;
|
||||
for(i = 0; i < updateItems.Size(); i++)
|
||||
@@ -200,6 +270,8 @@ static HRESULT Update2(COutArchive &archive,
|
||||
if (updateItem.NewData)
|
||||
{
|
||||
complexity += updateItem.Size;
|
||||
numBytesToCompress += updateItem.Size;
|
||||
numFilesToCompress++;
|
||||
/*
|
||||
if (updateItem.Commented)
|
||||
complexity += updateItem.CommentRange.Size;
|
||||
@@ -207,7 +279,9 @@ static HRESULT Update2(COutArchive &archive,
|
||||
}
|
||||
else
|
||||
{
|
||||
const CItemEx &inputItem = inputItems[updateItem.IndexInArchive];
|
||||
CItemEx inputItem = inputItems[updateItem.IndexInArchive];
|
||||
if (inArchive->ReadLocalItemAfterCdItemFull(inputItem) != S_OK)
|
||||
return E_NOTIMPL;
|
||||
complexity += inputItem.GetLocalFullSize();
|
||||
// complexity += inputItem.GetCentralExtraPlusCommentSize();
|
||||
}
|
||||
@@ -217,51 +291,345 @@ static HRESULT Update2(COutArchive &archive,
|
||||
|
||||
if (comment != 0)
|
||||
complexity += comment.GetCapacity();
|
||||
|
||||
complexity++; // end of central
|
||||
|
||||
updateCallback->SetTotal(complexity);
|
||||
CMyAutoPtr<CAddCommon> compressor;
|
||||
|
||||
CAddCommon compressor(*options);
|
||||
|
||||
complexity = 0;
|
||||
|
||||
CObjectVector<CItem> items;
|
||||
CRecordVector<UInt32> updateIndices;
|
||||
|
||||
for(i = 0; i < updateItems.Size(); i++)
|
||||
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;
|
||||
localProgressSpec->Init(updateCallback, true);
|
||||
|
||||
CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo;
|
||||
CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
|
||||
|
||||
|
||||
#ifdef COMPRESS_MT
|
||||
|
||||
const size_t kNumMaxThreads = (1 << 10);
|
||||
UInt32 numThreads = options->NumThreads;
|
||||
if (numThreads > kNumMaxThreads)
|
||||
numThreads = kNumMaxThreads;
|
||||
|
||||
const size_t kMemPerThread = (1 << 25);
|
||||
const size_t kBlockSize = 1 << 16;
|
||||
|
||||
CCompressionMethodMode options2;
|
||||
if (options != 0)
|
||||
options2 = *options;
|
||||
|
||||
bool mtMode = ((options != 0) && (numThreads > 1));
|
||||
|
||||
if (numFilesToCompress <= 1)
|
||||
mtMode = false;
|
||||
|
||||
if (mtMode)
|
||||
{
|
||||
const CUpdateItem &updateItem = updateItems[i];
|
||||
RINOK(updateCallback->SetCompleted(&complexity));
|
||||
Byte method = options->MethodSequence.Front();
|
||||
if (method == NFileHeader::NCompressionMethod::kStored && !options->PasswordIsDefined)
|
||||
mtMode = false;
|
||||
if (method == NFileHeader::NCompressionMethod::kBZip2)
|
||||
{
|
||||
UInt64 averageSize = numBytesToCompress / numFilesToCompress;
|
||||
UInt32 blockSize = options->DicSize;
|
||||
if (blockSize == 0)
|
||||
blockSize = 1;
|
||||
UInt64 averageNumberOfBlocks = averageSize / blockSize;
|
||||
UInt32 numBZip2Threads = 32;
|
||||
if (averageNumberOfBlocks < numBZip2Threads)
|
||||
numBZip2Threads = (UInt32)averageNumberOfBlocks;
|
||||
if (numBZip2Threads < 1)
|
||||
numBZip2Threads = 1;
|
||||
numThreads = numThreads / numBZip2Threads;
|
||||
options2.NumThreads = numBZip2Threads;
|
||||
if (numThreads <= 1)
|
||||
mtMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CMtCompressProgressMixer mtCompressProgressMixer;
|
||||
mtCompressProgressMixer.Init(numThreads + 1, localProgress);
|
||||
|
||||
// we need one item for main stream
|
||||
CMtCompressProgress *progressMainSpec = new CMtCompressProgress();
|
||||
CMyComPtr<ICompressProgressInfo> progressMain = progressMainSpec;
|
||||
progressMainSpec->Init(&mtCompressProgressMixer, (int)numThreads);
|
||||
|
||||
CMemBlockManagerMt memManager(kBlockSize);
|
||||
CMemRefs refs(&memManager);
|
||||
|
||||
CThreads threads;
|
||||
CRecordVector<HANDLE> compressingCompletedEvents;
|
||||
CRecordVector<int> threadIndices; // list threads in order of updateItems
|
||||
|
||||
if (mtMode)
|
||||
{
|
||||
if (!memManager.AllocateSpaceAlways((size_t)numThreads * (kMemPerThread / kBlockSize)))
|
||||
return E_OUTOFMEMORY;
|
||||
for(i = 0; i < updateItems.Size(); i++)
|
||||
refs.Refs.Add(CMemBlocks2());
|
||||
|
||||
UInt32 i;
|
||||
for (i = 0; i < numThreads; i++)
|
||||
threads.Threads.Add(CThreadInfo(options2));
|
||||
|
||||
for (i = 0; i < numThreads; i++)
|
||||
{
|
||||
CThreadInfo &threadInfo = threads.Threads[i];
|
||||
threadInfo.CreateEvents();
|
||||
threadInfo.OutStreamSpec = new COutMemStream(&memManager);
|
||||
threadInfo.OutStream = threadInfo.OutStreamSpec;
|
||||
threadInfo.IsFree = true;
|
||||
threadInfo.ProgressSpec = new CMtCompressProgress();
|
||||
threadInfo.Progress = threadInfo.ProgressSpec;
|
||||
threadInfo.ProgressSpec->Init(&mtCompressProgressMixer, (int)i);
|
||||
if (!threadInfo.CreateThread())
|
||||
return ::GetLastError();
|
||||
}
|
||||
}
|
||||
int mtItemIndex = 0;
|
||||
|
||||
#endif
|
||||
|
||||
int itemIndex = 0;
|
||||
int lastRealStreamItemIndex = -1;
|
||||
|
||||
while(itemIndex < updateItems.Size())
|
||||
{
|
||||
#ifdef COMPRESS_MT
|
||||
if (!mtMode)
|
||||
#endif
|
||||
{
|
||||
RINOK(updateCallback->SetCompleted(&complexity));
|
||||
}
|
||||
|
||||
#ifdef COMPRESS_MT
|
||||
if (mtMode && (UInt32)threadIndices.Size() < numThreads && mtItemIndex < updateItems.Size())
|
||||
{
|
||||
const CUpdateItem &updateItem = updateItems[mtItemIndex++];
|
||||
if (!updateItem.NewData)
|
||||
continue;
|
||||
CItemEx item;
|
||||
if (updateItem.NewProperties)
|
||||
{
|
||||
if (updateItem.IsDirectory)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
item = inputItems[updateItem.IndexInArchive];
|
||||
if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK)
|
||||
return E_NOTIMPL;
|
||||
if (item.IsDirectory())
|
||||
continue;
|
||||
}
|
||||
CMyComPtr<ISequentialInStream> fileInStream;
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(mtCompressProgressMixer.CriticalSection);
|
||||
HRESULT res = updateCallback->GetStream(updateItem.IndexInClient, &fileInStream);
|
||||
if (res == S_FALSE)
|
||||
{
|
||||
complexity += updateItem.Size;
|
||||
complexity++;
|
||||
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
refs.Refs[mtItemIndex - 1].Skip = true;
|
||||
continue;
|
||||
}
|
||||
RINOK(res);
|
||||
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
}
|
||||
|
||||
for (UInt32 i = 0; i < numThreads; i++)
|
||||
{
|
||||
CThreadInfo &threadInfo = threads.Threads[i];
|
||||
if (threadInfo.IsFree)
|
||||
{
|
||||
threadInfo.IsFree = false;
|
||||
threadInfo.InStream = fileInStream;
|
||||
threadInfo.OutStreamSpec->Init();
|
||||
threadInfo.ProgressSpec->Reinit();
|
||||
threadInfo.CompressEvent->Set();
|
||||
threadInfo.UpdateIndex = mtItemIndex - 1;
|
||||
|
||||
compressingCompletedEvents.Add(*threadInfo.CompressionCompletedEvent);
|
||||
threadIndices.Add(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (mtMode)
|
||||
if (refs.Refs[itemIndex].Skip)
|
||||
{
|
||||
itemIndex++;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
const CUpdateItem &updateItem = updateItems[itemIndex];
|
||||
|
||||
CItemEx item;
|
||||
if (!updateItem.NewProperties || !updateItem.NewData)
|
||||
{
|
||||
item = inputItems[updateItem.IndexInArchive];
|
||||
if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK)
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
||||
bool isDirectory;
|
||||
if (updateItem.NewProperties)
|
||||
isDirectory = updateItem.IsDirectory;
|
||||
else
|
||||
isDirectory = item.IsDirectory();
|
||||
|
||||
if (updateItem.NewData)
|
||||
{
|
||||
if(compressor.get() == NULL)
|
||||
#ifdef COMPRESS_MT
|
||||
if (mtMode && !isDirectory)
|
||||
{
|
||||
CMyAutoPtr<CAddCommon> tmp(new CAddCommon(*options));
|
||||
compressor = tmp;
|
||||
if (lastRealStreamItemIndex < itemIndex)
|
||||
{
|
||||
lastRealStreamItemIndex = itemIndex;
|
||||
SetFileHeader(archive, *options, updateItem, item);
|
||||
// file Size can be 64-bit !!!
|
||||
archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), updateItem.Size, options->IsAesMode);
|
||||
}
|
||||
|
||||
CMemBlocks2 &memRef = refs.Refs[itemIndex];
|
||||
if (memRef.Defined)
|
||||
{
|
||||
CMyComPtr<IOutStream> outStream;
|
||||
archive.CreateStreamForCompressing(&outStream);
|
||||
memRef.WriteToStream(memManager.GetBlockSize(), outStream);
|
||||
SetItemInfoFromCompressingResult(memRef.CompressingResult,
|
||||
options->IsAesMode, options->AesKeyMode, item);
|
||||
SetFileHeader(archive, *options, updateItem, item);
|
||||
RINOK(archive.WriteLocalHeader(item));
|
||||
complexity += item.UnPackSize;
|
||||
// RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
memRef.FreeOpt(&memManager);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
CThreadInfo &thread = threads.Threads[threadIndices.Front()];
|
||||
if (!thread.OutStreamSpec->WasUnlockEventSent())
|
||||
{
|
||||
CMyComPtr<IOutStream> outStream;
|
||||
archive.CreateStreamForCompressing(&outStream);
|
||||
thread.OutStreamSpec->SetOutStream(outStream);
|
||||
thread.OutStreamSpec->SetRealStreamMode();
|
||||
}
|
||||
}
|
||||
|
||||
DWORD result = ::WaitForMultipleObjects(compressingCompletedEvents.Size(),
|
||||
&compressingCompletedEvents.Front(), FALSE, INFINITE);
|
||||
int t = (int)(result - WAIT_OBJECT_0);
|
||||
CThreadInfo &threadInfo = threads.Threads[threadIndices[t]];
|
||||
threadInfo.InStream.Release();
|
||||
threadInfo.IsFree = true;
|
||||
RINOK(threadInfo.Result);
|
||||
threadIndices.Delete(t);
|
||||
compressingCompletedEvents.Delete(t);
|
||||
if (t == 0)
|
||||
{
|
||||
RINOK(threadInfo.OutStreamSpec->WriteToRealStream());
|
||||
threadInfo.OutStreamSpec->ReleaseOutStream();
|
||||
SetItemInfoFromCompressingResult(threadInfo.CompressingResult,
|
||||
options->IsAesMode, options->AesKeyMode, item);
|
||||
SetFileHeader(archive, *options, updateItem, item);
|
||||
RINOK(archive.WriteLocalHeader(item));
|
||||
complexity += item.UnPackSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
CMemBlocks2 &memRef = refs.Refs[threadInfo.UpdateIndex];
|
||||
threadInfo.OutStreamSpec->DetachData(memRef);
|
||||
memRef.CompressingResult = threadInfo.CompressingResult;
|
||||
memRef.Defined = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
CMyComPtr<ISequentialInStream> fileInStream2;
|
||||
HRESULT res = updateCallback->GetStream(updateItem.IndexInClient, &fileInStream2);
|
||||
if (res == S_FALSE)
|
||||
else
|
||||
#endif
|
||||
{
|
||||
complexity += updateItem.Size;
|
||||
complexity++;
|
||||
RINOK(updateCallback->SetOperationResult(
|
||||
NArchive::NUpdate::NOperationResult::kOK));
|
||||
continue;
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> fileInStream;
|
||||
{
|
||||
#ifdef COMPRESS_MT
|
||||
CCriticalSectionLock2 lock;
|
||||
if (mtMode)
|
||||
lock.Set(mtCompressProgressMixer.CriticalSection);
|
||||
#endif
|
||||
HRESULT res = updateCallback->GetStream(updateItem.IndexInClient, &fileInStream);
|
||||
if (res == S_FALSE)
|
||||
{
|
||||
complexity += updateItem.Size;
|
||||
complexity++;
|
||||
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
itemIndex++;
|
||||
continue;
|
||||
}
|
||||
RINOK(res);
|
||||
|
||||
#ifdef COMPRESS_MT
|
||||
if (mtMode)
|
||||
{
|
||||
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// file Size can be 64-bit !!!
|
||||
SetFileHeader(archive, *options, updateItem, item);
|
||||
archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), updateItem.Size, options->IsAesMode);
|
||||
|
||||
if(!isDirectory)
|
||||
{
|
||||
CCompressingResult compressingResult;
|
||||
CMyComPtr<IOutStream> outStream;
|
||||
archive.CreateStreamForCompressing(&outStream);
|
||||
|
||||
localCompressProgressSpec->Init(localProgress, &complexity, NULL);
|
||||
|
||||
RINOK(compressor.Compress(fileInStream, outStream, compressProgress, compressingResult));
|
||||
|
||||
SetItemInfoFromCompressingResult(compressingResult,
|
||||
options->IsAesMode, options->AesKeyMode, item);
|
||||
}
|
||||
}
|
||||
RINOK(archive.WriteLocalHeader(item));
|
||||
complexity += item.UnPackSize;
|
||||
#ifdef COMPRESS_MT
|
||||
if (!mtMode)
|
||||
#endif
|
||||
{
|
||||
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
}
|
||||
}
|
||||
RINOK(res);
|
||||
RINOK(UpdateOneFile(inStream, archive, *options,
|
||||
*compressor, updateItem, complexity, updateCallback, item,
|
||||
fileInStream2));
|
||||
}
|
||||
else
|
||||
{
|
||||
// item = inputItems[copyIndices[copyIndexIndex++]];
|
||||
|
||||
#ifdef COMPRESS_MT
|
||||
if (mtMode)
|
||||
progressMainSpec->Reinit();
|
||||
#endif
|
||||
|
||||
localCompressProgressSpec->Init(localProgress, &complexity, NULL);
|
||||
ICompressProgressInfo *progress = compressProgress;
|
||||
#ifdef COMPRESS_MT
|
||||
if (mtMode)
|
||||
progress = progressMain;
|
||||
#endif
|
||||
|
||||
if (updateItem.NewProperties)
|
||||
{
|
||||
if (item.HasDescriptor())
|
||||
@@ -275,13 +643,14 @@ static HRESULT Update2(COutArchive &archive,
|
||||
// Test it
|
||||
item.Name = updateItem.Name;
|
||||
item.Time = updateItem.Time;
|
||||
item.CentralExtra.Clear();
|
||||
item.LocalExtraSize = 0;
|
||||
item.CentralExtra.RemoveUnknownSubBlocks();
|
||||
item.LocalExtra.RemoveUnknownSubBlocks();
|
||||
|
||||
archive.PrepareWriteCompressedData2(item.Name.Length(), item.UnPackSize, item.PackSize);
|
||||
archive.PrepareWriteCompressedData2((UInt16)item.Name.Length(), item.UnPackSize, item.PackSize, item.LocalExtra.HasWzAesField());
|
||||
item.LocalHeaderPosition = archive.GetCurrentPosition();
|
||||
archive.SeekToPackedDataPosition();
|
||||
RINOK(WriteRange(inStream, archive, range, updateCallback, complexity));
|
||||
RINOK(WriteRange(inStream, archive, range, progress));
|
||||
complexity += range.Size;
|
||||
archive.WriteLocalHeader(item);
|
||||
}
|
||||
else
|
||||
@@ -291,15 +660,15 @@ static HRESULT Update2(COutArchive &archive,
|
||||
// set new header position
|
||||
item.LocalHeaderPosition = archive.GetCurrentPosition();
|
||||
|
||||
RINOK(WriteRange(inStream, archive, range, updateCallback, complexity));
|
||||
RINOK(WriteRange(inStream, archive, range, progress));
|
||||
complexity += range.Size;
|
||||
archive.MoveBasePosition(range.Size);
|
||||
}
|
||||
}
|
||||
items.Add(item);
|
||||
updateIndices.Add(i);
|
||||
complexity += NFileHeader::kLocalBlockSize;
|
||||
itemIndex++;
|
||||
}
|
||||
|
||||
archive.WriteCentralDir(items, comment);
|
||||
return S_OK;
|
||||
}
|
||||
@@ -319,7 +688,11 @@ HRESULT Update(
|
||||
|
||||
CInArchiveInfo archiveInfo;
|
||||
if(inArchive != 0)
|
||||
{
|
||||
inArchive->GetArchiveInfo(archiveInfo);
|
||||
if (archiveInfo.Base != 0)
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
else
|
||||
archiveInfo.StartPosition = 0;
|
||||
|
||||
@@ -336,7 +709,7 @@ HRESULT Update(
|
||||
if(inArchive != 0)
|
||||
inStream.Attach(inArchive->CreateStream());
|
||||
|
||||
return Update2(outArchive, inStream,
|
||||
return Update2(outArchive, inArchive, inStream,
|
||||
inputItems, updateItems,
|
||||
compressionMethodMode,
|
||||
archiveInfo.Comment, updateCallback);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user