This commit is contained in:
Igor Pavlov
2010-06-04 00:00:00 +00:00
committed by Kornel Lesiński
parent 3dacb5eb8a
commit 708873490e
51 changed files with 1433 additions and 489 deletions

View File

@@ -1,7 +1,7 @@
#define MY_VER_MAJOR 9 #define MY_VER_MAJOR 9
#define MY_VER_MINOR 13 #define MY_VER_MINOR 14
#define MY_VER_BUILD 0 #define MY_VER_BUILD 0
#define MY_VERSION "9.13 beta" #define MY_VERSION "9.14 beta"
#define MY_DATE "2010-04-15" #define MY_DATE "2010-06-04"
#define MY_COPYRIGHT ": Igor Pavlov : Public domain" #define MY_COPYRIGHT ": Igor Pavlov : Public domain"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE

View File

@@ -1,5 +1,5 @@
/* Bra.c -- Converters for RISC code /* Bra.c -- Converters for RISC code
2008-10-04 : Igor Pavlov : Public domain */ 2010-04-16 : Igor Pavlov : Public domain */
#include "Bra.h" #include "Bra.h"
@@ -104,8 +104,8 @@ SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
size -= 4; size -= 4;
for (i = 0; i <= size; i += 4) for (i = 0; i <= size; i += 4)
{ {
if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 || if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) ||
data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0) (data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0))
{ {
UInt32 src = UInt32 src =
((UInt32)data[i + 0] << 24) | ((UInt32)data[i + 0] << 24) |

View File

@@ -1,5 +1,5 @@
/* CpuArch.h -- CPU specific code /* CpuArch.h -- CPU specific code
2010-03-11: Igor Pavlov : Public domain */ 2010-05-20: Igor Pavlov : Public domain */
#ifndef __CPU_ARCH_H #ifndef __CPU_ARCH_H
#define __CPU_ARCH_H #define __CPU_ARCH_H
@@ -55,6 +55,7 @@ If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of pla
#define GetUi64(p) (*(const UInt64 *)(p)) #define GetUi64(p) (*(const UInt64 *)(p))
#define SetUi16(p, d) *(UInt16 *)(p) = (d); #define SetUi16(p, d) *(UInt16 *)(p) = (d);
#define SetUi32(p, d) *(UInt32 *)(p) = (d); #define SetUi32(p, d) *(UInt32 *)(p) = (d);
#define SetUi64(p, d) *(UInt64 *)(p) = (d);
#else #else
@@ -78,6 +79,10 @@ If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of pla
((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \
((Byte *)(p))[3] = (Byte)(_x_ >> 24); } ((Byte *)(p))[3] = (Byte)(_x_ >> 24); }
#define SetUi64(p, d) { UInt64 _x64_ = (d); \
SetUi32(p, (UInt32)_x64_); \
SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); }
#endif #endif
#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) #if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)

View File

@@ -1,5 +1,5 @@
/* Lzma2Enc.c -- LZMA2 Encoder /* Lzma2Enc.c -- LZMA2 Encoder
2010-03-25 : Igor Pavlov : Public domain */ 2010-04-16 : Igor Pavlov : Public domain */
/* #include <stdio.h> */ /* #include <stdio.h> */
#include <string.h> #include <string.h>
@@ -141,7 +141,7 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
PRF(printf(" ")); PRF(printf(" "));
outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | (u >> 16) & 0x1F); outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F));
outBuf[destPos++] = (Byte)(u >> 8); outBuf[destPos++] = (Byte)(u >> 8);
outBuf[destPos++] = (Byte)u; outBuf[destPos++] = (Byte)u;
outBuf[destPos++] = (Byte)(pm >> 8); outBuf[destPos++] = (Byte)(pm >> 8);

View File

@@ -1,5 +1,5 @@
/* LzmaEnc.c -- LZMA Encoder /* LzmaEnc.c -- LZMA Encoder
2009-11-24 : Igor Pavlov : Public domain */ 2010-04-16 : Igor Pavlov : Public domain */
#include <string.h> #include <string.h>
@@ -395,7 +395,7 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
LzmaEncProps_Normalize(&props); LzmaEncProps_Normalize(&props);
if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX ||
props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30)) props.dictSize > ((UInt32)1 << kDicLogSizeMaxCompress) || props.dictSize > ((UInt32)1 << 30))
return SZ_ERROR_PARAM; return SZ_ERROR_PARAM;
p->dictSize = props.dictSize; p->dictSize = props.dictSize;
p->matchFinderCycles = props.mc; p->matchFinderCycles = props.mc;

View File

@@ -1,5 +1,5 @@
/* Ppmd8Dec.c -- PPMdI Decoder /* Ppmd8Dec.c -- PPMdI Decoder
2010-03-12 : Igor Pavlov : Public domain 2010-04-16 : Igor Pavlov : Public domain
This code is based on: This code is based on:
PPMd var.I (2002): Dmitry Shkarin : Public domain PPMd var.I (2002): Dmitry Shkarin : Public domain
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
@@ -33,7 +33,7 @@ static void RangeDec_Decode(CPpmd8 *p, UInt32 start, UInt32 size)
p->Range *= size; p->Range *= size;
while ((p->Low ^ (p->Low + p->Range)) < kTop || while ((p->Low ^ (p->Low + p->Range)) < kTop ||
p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1)) (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1)))
{ {
p->Code = (p->Code << 8) | p->Stream.In->Read(p->Stream.In); p->Code = (p->Code << 8) | p->Stream.In->Read(p->Stream.In);
p->Range <<= 8; p->Range <<= 8;

View File

@@ -1,5 +1,5 @@
/* Ppmd8Enc.c -- PPMdI Encoder /* Ppmd8Enc.c -- PPMdI Encoder
2010-03-12 : Igor Pavlov : Public domain 2010-04-16 : Igor Pavlov : Public domain
This code is based on: This code is based on:
PPMd var.I (2002): Dmitry Shkarin : Public domain PPMd var.I (2002): Dmitry Shkarin : Public domain
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
@@ -19,7 +19,7 @@ void Ppmd8_RangeEnc_FlushData(CPpmd8 *p)
static void RangeEnc_Normalize(CPpmd8 *p) static void RangeEnc_Normalize(CPpmd8 *p)
{ {
while ((p->Low ^ (p->Low + p->Range)) < kTop || while ((p->Low ^ (p->Low + p->Range)) < kTop ||
p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1)) (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1)))
{ {
p->Stream.Out->Write(p->Stream.Out, (Byte)(p->Low >> 24)); p->Stream.Out->Write(p->Stream.Out, (Byte)(p->Low >> 24));
p->Range <<= 8; p->Range <<= 8;

View File

@@ -1,5 +1,5 @@
/* Types.h -- Basic types /* Types.h -- Basic types
2010-03-11 : Igor Pavlov : Public domain */ 2010-04-16 : Igor Pavlov : Public domain */
#ifndef __7Z_TYPES_H #ifndef __7Z_TYPES_H
#define __7Z_TYPES_H #define __7Z_TYPES_H
@@ -77,9 +77,11 @@ typedef unsigned long UInt64;
#if defined(_MSC_VER) || defined(__BORLANDC__) #if defined(_MSC_VER) || defined(__BORLANDC__)
typedef __int64 Int64; typedef __int64 Int64;
typedef unsigned __int64 UInt64; typedef unsigned __int64 UInt64;
#define UINT64_CONST(n) n
#else #else
typedef long long int Int64; typedef long long int Int64;
typedef unsigned long long int UInt64; typedef unsigned long long int UInt64;
#define UINT64_CONST(n) n ## ULL
#endif #endif
#endif #endif

View File

@@ -1,9 +1,9 @@
/* XzCrc64.c -- CRC64 calculation /* XzCrc64.c -- CRC64 calculation
2009-04-15 : Igor Pavlov : Public domain */ 2010-04-16 : Igor Pavlov : Public domain */
#include "XzCrc64.h" #include "XzCrc64.h"
#define kCrc64Poly 0xC96C5795D7870F42 #define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42)
UInt64 g_Crc64Table[256]; UInt64 g_Crc64Table[256];
void MY_FAST_CALL Crc64GenerateTable(void) void MY_FAST_CALL Crc64GenerateTable(void)

View File

@@ -1,5 +1,5 @@
/* XzCrc64.c -- CRC64 calculation /* XzCrc64.h -- CRC64 calculation
2009-04-15 : Igor Pavlov : Public domain */ 2010-04-16 : Igor Pavlov : Public domain */
#ifndef __XZ_CRC64_H #ifndef __XZ_CRC64_H
#define __XZ_CRC64_H #define __XZ_CRC64_H
@@ -8,23 +8,19 @@
#include "Types.h" #include "Types.h"
#ifdef __cplusplus EXTERN_C_BEGIN
extern "C" {
#endif
extern UInt64 g_Crc64Table[]; extern UInt64 g_Crc64Table[];
void MY_FAST_CALL Crc64GenerateTable(void); void MY_FAST_CALL Crc64GenerateTable(void);
#define CRC64_INIT_VAL 0xFFFFFFFFFFFFFFFF #define CRC64_INIT_VAL UINT64_CONST(0xFFFFFFFFFFFFFFFF)
#define CRC64_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFFFFFFFFFF) #define CRC64_GET_DIGEST(crc) ((crc) ^ CRC64_INIT_VAL)
#define CRC64_UPDATE_BYTE(crc, b) (g_Crc64Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) #define CRC64_UPDATE_BYTE(crc, b) (g_Crc64Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt64 MY_FAST_CALL Crc64Update(UInt64 crc, const void *data, size_t size); UInt64 MY_FAST_CALL Crc64Update(UInt64 crc, const void *data, size_t size);
UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size); UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size);
#ifdef __cplusplus EXTERN_C_END
}
#endif
#endif #endif

View File

@@ -1,5 +1,5 @@
/* XzDec.c -- Xz Decode /* XzDec.c -- Xz Decode
2009-06-08 : Igor Pavlov : Public domain */ 2010-04-16 : Igor Pavlov : Public domain */
/* #define XZ_DUMP */ /* #define XZ_DUMP */
@@ -858,6 +858,8 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
} }
break; break;
} }
case XZ_STATE_BLOCK: break; /* to disable GCC warning */
} }
} }
/* /*

View File

@@ -138,7 +138,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
} }
} }
extractCallback->SetTotal(importantTotalUnpacked); RINOK(extractCallback->SetTotal(importantTotalUnpacked));
CDecoder decoder( CDecoder decoder(
#ifdef _ST_MODE #ifdef _ST_MODE

View File

@@ -32,7 +32,6 @@ HRESULT CFolderInStream::OpenStream()
_filePos = 0; _filePos = 0;
while (_fileIndex < _numFiles) while (_fileIndex < _numFiles)
{ {
_currentSizeIsDefined = false;
CMyComPtr<ISequentialInStream> stream; CMyComPtr<ISequentialInStream> stream;
HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream); HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream);
if (result != S_OK && result != S_FALSE) if (result != S_OK && result != S_FALSE)
@@ -40,26 +39,22 @@ HRESULT CFolderInStream::OpenStream()
_fileIndex++; _fileIndex++;
_inStreamWithHashSpec->SetStream(stream); _inStreamWithHashSpec->SetStream(stream);
_inStreamWithHashSpec->Init(); _inStreamWithHashSpec->Init();
if (!stream) if (stream)
{ {
_fileIsOpen = true;
CMyComPtr<IStreamGetSize> streamGetSize;
stream.QueryInterface(IID_IStreamGetSize, &streamGetSize);
if (streamGetSize)
{
RINOK(streamGetSize->GetSize(&_currentSize));
_currentSizeIsDefined = true;
}
return S_OK;
}
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
Sizes.Add(0); Sizes.Add(0);
Processed.Add(result == S_OK); Processed.Add(result == S_OK);
AddDigest(); AddDigest();
continue;
}
CMyComPtr<IStreamGetSize> streamGetSize;
if (stream.QueryInterface(IID_IStreamGetSize, &streamGetSize) == S_OK)
{
if(streamGetSize)
{
_currentSizeIsDefined = true;
RINOK(streamGetSize->GetSize(&_currentSize));
}
}
_fileIsOpen = true;
return S_OK;
} }
return S_OK; return S_OK;
} }
@@ -74,6 +69,7 @@ HRESULT CFolderInStream::CloseStream()
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
_inStreamWithHashSpec->ReleaseStream(); _inStreamWithHashSpec->ReleaseStream();
_fileIsOpen = false; _fileIsOpen = false;
_currentSizeIsDefined = false;
Processed.Add(true); Processed.Add(true);
Sizes.Add(_filePos); Sizes.Add(_filePos);
AddDigest(); AddDigest();
@@ -82,43 +78,40 @@ HRESULT CFolderInStream::CloseStream()
STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{ {
UInt32 realProcessedSize = 0; if (processedSize != 0)
while ((_fileIndex < _numFiles || _fileIsOpen) && size > 0) *processedSize = 0;
while (size > 0)
{ {
if (_fileIsOpen) if (_fileIsOpen)
{ {
UInt32 localProcessedSize; UInt32 processed2;
RINOK(_inStreamWithHash->Read( RINOK(_inStreamWithHash->Read(data, size, &processed2));
((Byte *)data) + realProcessedSize, size, &localProcessedSize)); if (processed2 == 0)
if (localProcessedSize == 0)
{ {
RINOK(CloseStream()); RINOK(CloseStream());
continue; continue;
} }
realProcessedSize += localProcessedSize; if (processedSize != 0)
_filePos += localProcessedSize; *processedSize = processed2;
size -= localProcessedSize; _filePos += processed2;
break; break;
} }
else if (_fileIndex >= _numFiles)
{ break;
RINOK(OpenStream()); RINOK(OpenStream());
} }
}
if (processedSize != 0)
*processedSize = realProcessedSize;
return S_OK; return S_OK;
} }
STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
{ {
*value = 0; *value = 0;
int subStreamIndex = (int)subStream; int index2 = (int)subStream;
if (subStreamIndex < 0 || subStream > Sizes.Size()) if (index2 < 0 || subStream > Sizes.Size())
return E_FAIL; return E_FAIL;
if (subStreamIndex < Sizes.Size()) if (index2 < Sizes.Size())
{ {
*value= Sizes[subStreamIndex]; *value = Sizes[index2];
return S_OK; return S_OK;
} }
if (!_currentSizeIsDefined) if (!_currentSizeIsDefined)

View File

@@ -1,15 +1,13 @@
// 7z/FolderInStream.h // 7zFolderInStream.h
#ifndef __7Z_FOLDERINSTREAM_H #ifndef __7Z_FOLDER_IN_STREAM_H
#define __7Z_FOLDERINSTREAM_H #define __7Z_FOLDER_IN_STREAM_H
#include "7zItem.h"
#include "7zHeader.h"
#include "../../ICoder.h"
#include "../IArchive.h" #include "../IArchive.h"
#include "../Common/InStreamWithCRC.h" #include "../Common/InStreamWithCRC.h"
#include "../../IStream.h"
#include "../../ICoder.h" #include "7zItem.h"
namespace NArchive { namespace NArchive {
namespace N7z { namespace N7z {
@@ -19,26 +17,14 @@ class CFolderInStream:
public ICompressGetSubStreamSize, public ICompressGetSubStreamSize,
public CMyUnknownImp public CMyUnknownImp
{ {
public:
MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
CFolderInStream();
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
private:
CSequentialInStreamWithCRC *_inStreamWithHashSpec; CSequentialInStreamWithCRC *_inStreamWithHashSpec;
CMyComPtr<ISequentialInStream> _inStreamWithHash; CMyComPtr<ISequentialInStream> _inStreamWithHash;
CMyComPtr<IArchiveUpdateCallback> _updateCallback; CMyComPtr<IArchiveUpdateCallback> _updateCallback;
bool _currentSizeIsDefined; bool _currentSizeIsDefined;
UInt64 _currentSize;
bool _fileIsOpen; bool _fileIsOpen;
UInt64 _currentSize;
UInt64 _filePos; UInt64 _filePos;
const UInt32 *_fileIndices; const UInt32 *_fileIndices;
UInt32 _numFiles; UInt32 _numFiles;
UInt32 _fileIndex; UInt32 _fileIndex;
@@ -46,12 +32,18 @@ private:
HRESULT OpenStream(); HRESULT OpenStream();
HRESULT CloseStream(); HRESULT CloseStream();
void AddDigest(); void AddDigest();
public: public:
void Init(IArchiveUpdateCallback *updateCallback,
const UInt32 *fileIndices, UInt32 numFiles);
CRecordVector<bool> Processed; CRecordVector<bool> Processed;
CRecordVector<UInt32> CRCs; CRecordVector<UInt32> CRCs;
CRecordVector<UInt64> Sizes; CRecordVector<UInt64> Sizes;
MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
CFolderInStream();
void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles);
UInt64 GetFullSize() const UInt64 GetFullSize() const
{ {
UInt64 size = 0; UInt64 size = 0;

View File

@@ -14,13 +14,13 @@ CFolderOutStream::CFolderOutStream()
} }
HRESULT CFolderOutStream::Init( HRESULT CFolderOutStream::Init(
const CArchiveDatabaseEx *archiveDatabase, const CArchiveDatabaseEx *db,
UInt32 ref2Offset, UInt32 startIndex, UInt32 ref2Offset, UInt32 startIndex,
const CBoolVector *extractStatuses, const CBoolVector *extractStatuses,
IArchiveExtractCallback *extractCallback, IArchiveExtractCallback *extractCallback,
bool testMode, bool checkCrc) bool testMode, bool checkCrc)
{ {
_db = archiveDatabase; _db = db;
_ref2Offset = ref2Offset; _ref2Offset = ref2Offset;
_startIndex = startIndex; _startIndex = startIndex;
@@ -121,6 +121,15 @@ STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *proc
return S_OK; return S_OK;
} }
STDMETHODIMP CFolderOutStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
{
*value = 0;
if ((int)subStream >= _extractStatuses->Size())
return S_FALSE;
*value = _db->Files[_startIndex + (int)subStream].Size;
return S_OK;
}
HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult) HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)
{ {
while (_currentIndex < _extractStatuses->Size()) while (_currentIndex < _extractStatuses->Size())

View File

@@ -3,17 +3,18 @@
#ifndef __7Z_FOLDER_OUT_STREAM_H #ifndef __7Z_FOLDER_OUT_STREAM_H
#define __7Z_FOLDER_OUT_STREAM_H #define __7Z_FOLDER_OUT_STREAM_H
#include "7zIn.h"
#include "../../IStream.h" #include "../../IStream.h"
#include "../IArchive.h" #include "../IArchive.h"
#include "../Common/OutStreamWithCRC.h" #include "../Common/OutStreamWithCRC.h"
#include "7zIn.h"
namespace NArchive { namespace NArchive {
namespace N7z { namespace N7z {
class CFolderOutStream: class CFolderOutStream:
public ISequentialOutStream, public ISequentialOutStream,
public ICompressGetSubStreamSize,
public CMyUnknownImp public CMyUnknownImp
{ {
COutStreamWithCRC *_crcStreamSpec; COutStreamWithCRC *_crcStreamSpec;
@@ -34,14 +35,15 @@ class CFolderOutStream:
HRESULT CloseFileAndSetResult(); HRESULT CloseFileAndSetResult();
HRESULT ProcessEmptyFiles(); HRESULT ProcessEmptyFiles();
public: public:
MY_UNKNOWN_IMP MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
CFolderOutStream(); CFolderOutStream();
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
HRESULT Init( HRESULT Init(
const CArchiveDatabaseEx *archiveDatabase, const CArchiveDatabaseEx *db,
UInt32 ref2Offset, UInt32 startIndex, UInt32 ref2Offset, UInt32 startIndex,
const CBoolVector *extractStatuses, const CBoolVector *extractStatuses,
IArchiveExtractCallback *extractCallback, IArchiveExtractCallback *extractCallback,

View File

@@ -87,7 +87,7 @@ CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams):
{ {
InSizes.Reserve(NumInStreams); InSizes.Reserve(NumInStreams);
InSizePointers.Reserve(NumInStreams); InSizePointers.Reserve(NumInStreams);
OutSizePointers.Reserve(NumOutStreams); OutSizes.Reserve(NumOutStreams);
OutSizePointers.Reserve(NumOutStreams); OutSizePointers.Reserve(NumOutStreams);
} }

View File

@@ -21,8 +21,10 @@ STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSi
{ {
UInt32 realProcessedSize; UInt32 realProcessedSize;
HRESULT result = _stream->Read(data, size, &realProcessedSize); HRESULT result = _stream->Read(data, size, &realProcessedSize);
/*
if (size > 0 && realProcessedSize == 0) if (size > 0 && realProcessedSize == 0)
_wasFinished = true; _wasFinished = true;
*/
_size += realProcessedSize; _size += realProcessedSize;
_crc = CrcUpdate(_crc, data, realProcessedSize); _crc = CrcUpdate(_crc, data, realProcessedSize);
if(processedSize != NULL) if(processedSize != NULL)

View File

@@ -49,19 +49,19 @@ private:
CMyComPtr<IInStream> _stream; CMyComPtr<IInStream> _stream;
UInt64 _size; UInt64 _size;
UInt32 _crc; UInt32 _crc;
bool _wasFinished; // bool _wasFinished;
public: public:
void SetStream(IInStream *stream) { _stream = stream; } void SetStream(IInStream *stream) { _stream = stream; }
void Init() void Init()
{ {
_size = 0; _size = 0;
_wasFinished = false; // _wasFinished = false;
_crc = CRC_INIT_VAL; _crc = CRC_INIT_VAL;
} }
void ReleaseStream() { _stream.Release(); } void ReleaseStream() { _stream.Release(); }
UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
UInt64 GetSize() const { return _size; } UInt64 GetSize() const { return _size; }
bool WasFinished() const { return _wasFinished; } // bool WasFinished() const { return _wasFinished; }
}; };
#endif #endif

View File

@@ -3,8 +3,6 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "Common/ComTry.h" #include "Common/ComTry.h"
#include "Common/Defs.h"
#include "Common/NewHandler.h"
#include "Common/StringConvert.h" #include "Common/StringConvert.h"
#include "Common/StringToInt.h" #include "Common/StringToInt.h"

View File

@@ -3,9 +3,7 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "Common/ComTry.h" #include "Common/ComTry.h"
#include "Common/Defs.h"
#include "Common/IntToString.h" #include "Common/IntToString.h"
#include "Common/NewHandler.h"
#include "Common/StringConvert.h" #include "Common/StringConvert.h"
#include "Windows/PropVariant.h" #include "Windows/PropVariant.h"
@@ -26,7 +24,7 @@ using namespace NTime;
namespace NArchive { namespace NArchive {
namespace NIso { namespace NIso {
STATPROPSTG kProps[] = static STATPROPSTG kProps[] =
{ {
{ NULL, kpidPath, VT_BSTR}, { NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL}, { NULL, kpidIsDir, VT_BOOL},

View File

@@ -8,6 +8,6 @@
static IInArchive *CreateArc() { return new NArchive::NIso::CHandler; } static IInArchive *CreateArc() { return new NArchive::NIso::CHandler; }
static CArcInfo g_ArcInfo = static CArcInfo g_ArcInfo =
{ L"Iso", L"iso", 0, 0xE7, { 'C', 'D', '0', '0', '1', 0x1 }, 7, false, CreateArc, 0 }; { L"Iso", L"iso img", 0, 0xE7, { 'C', 'D', '0', '0', '1', 0x1 }, 7, false, CreateArc, 0 };
REGISTER_ARC(Iso) REGISTER_ARC(Iso)

View File

@@ -646,7 +646,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
totalUnPacked += item.Size; totalUnPacked += item.Size;
totalPacked += item.PackSize; totalPacked += item.PackSize;
} }
extractCallback->SetTotal(totalUnPacked); RINOK(extractCallback->SetTotal(totalUnPacked));
UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0; UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0;
UInt64 currentItemUnPacked, currentItemPacked; UInt64 currentItemUnPacked, currentItemPacked;

View File

@@ -6,7 +6,6 @@
#include "Common/ComTry.h" #include "Common/ComTry.h"
#include "Common/IntToString.h" #include "Common/IntToString.h"
#include "Common/NewHandler.h"
#include "Windows/PropVariant.h" #include "Windows/PropVariant.h"

View File

@@ -1283,10 +1283,12 @@ HRESULT CDatabase::Open()
{ {
if (OpenCallback) if (OpenCallback)
{ {
// Sleep(0);
UInt64 numFiles = Recs.Size(); UInt64 numFiles = Recs.Size();
if ((numFiles & 0x3FF) == 0)
{
RINOK(OpenCallback->SetCompleted(&numFiles, &pos64)); RINOK(OpenCallback->SetCompleted(&numFiles, &pos64));
} }
}
UInt32 readSize = kBufSize; UInt32 readSize = kBufSize;
UInt64 rem = mftSize - pos64; UInt64 rem = mftSize - pos64;
if (readSize > rem) if (readSize > rem)

View File

@@ -520,7 +520,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
lastIndex = index + 1; lastIndex = index + 1;
} }
extractCallback->SetTotal(importantTotalUnPacked); RINOK(extractCallback->SetTotal(importantTotalUnPacked));
UInt64 currentImportantTotalUnPacked = 0; UInt64 currentImportantTotalUnPacked = 0;
UInt64 currentImportantTotalPacked = 0; UInt64 currentImportantTotalPacked = 0;
UInt64 currentUnPackSize, currentPackSize; UInt64 currentUnPackSize, currentPackSize;

View File

@@ -3,8 +3,6 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "Common/ComTry.h" #include "Common/ComTry.h"
#include "Common/Defs.h"
#include "Common/NewHandler.h"
#include "Common/StringConvert.h" #include "Common/StringConvert.h"
#include "Windows/PropVariant.h" #include "Windows/PropVariant.h"
@@ -23,7 +21,7 @@ using namespace NWindows;
namespace NArchive { namespace NArchive {
namespace NTar { namespace NTar {
STATPROPSTG kProps[] = static STATPROPSTG kProps[] =
{ {
{ NULL, kpidPath, VT_BSTR}, { NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL}, { NULL, kpidIsDir, VT_BOOL},

View File

@@ -69,11 +69,20 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
filled = false; filled = false;
bool thereAreEmptyRecords = false;
for (;;)
{
processedSize = NFileHeader::kRecordSize; processedSize = NFileHeader::kRecordSize;
RINOK(ReadStream(stream, buf, &processedSize)); RINOK(ReadStream(stream, buf, &processedSize));
if (processedSize == 0 || (processedSize == NFileHeader::kRecordSize && IsRecordLast(buf))) if (processedSize == 0)
return S_OK; return S_OK;
if (processedSize < NFileHeader::kRecordSize) if (processedSize != NFileHeader::kRecordSize)
return S_FALSE;
if (!IsRecordLast(buf))
break;
thereAreEmptyRecords = true;
}
if (thereAreEmptyRecords)
return S_FALSE; return S_FALSE;
ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize; ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize;

View File

@@ -3,7 +3,6 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "Common/ComTry.h" #include "Common/ComTry.h"
#include "Common/NewHandler.h"
#include "Windows/PropVariant.h" #include "Windows/PropVariant.h"
#include "Windows/Time.h" #include "Windows/Time.h"
@@ -34,7 +33,7 @@ void UdfTimeToFileTime(const CTime &t, NWindows::NCOM::CPropVariant &prop)
prop = ft; prop = ft;
} }
STATPROPSTG kProps[] = static STATPROPSTG kProps[] =
{ {
{ NULL, kpidPath, VT_BSTR}, { NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL}, { NULL, kpidIsDir, VT_BOOL},
@@ -44,7 +43,7 @@ STATPROPSTG kProps[] =
{ NULL, kpidATime, VT_FILETIME} { NULL, kpidATime, VT_FILETIME}
}; };
STATPROPSTG kArcProps[] = static STATPROPSTG kArcProps[] =
{ {
{ NULL, kpidComment, VT_BSTR}, { NULL, kpidComment, VT_BSTR},
{ NULL, kpidClusterSize, VT_UI4}, { NULL, kpidClusterSize, VT_UI4},

View File

@@ -8,6 +8,6 @@
static IInArchive *CreateArc() { return new NArchive::NUdf::CHandler; } static IInArchive *CreateArc() { return new NArchive::NUdf::CHandler; }
static CArcInfo g_ArcInfo = static CArcInfo g_ArcInfo =
{ L"Udf", L"iso", 0, 0xE0, { 0, 'N', 'S', 'R', '0' }, 5, false, CreateArc, 0 }; { L"Udf", L"iso img", 0, 0xE0, { 0, 'N', 'S', 'R', '0' }, 5, false, CreateArc, 0 };
REGISTER_ARC(Udf) REGISTER_ARC(Udf)

View File

@@ -2,18 +2,17 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "Common/IntToString.h" #include "../../../../C/CpuArch.h"
#include "Common/Defs.h"
#include "Common/ComTry.h" #include "Common/ComTry.h"
#include "Common/IntToString.h"
#include "Common/StringToInt.h" #include "Common/StringToInt.h"
#include "Common/UTFConvert.h" #include "Common/UTFConvert.h"
#include "Windows/PropVariant.h" #include "Windows/PropVariant.h"
#include "../../Common/StreamUtils.h"
#include "../../Common/ProgressUtils.h" #include "../../Common/ProgressUtils.h"
#include "../../Common/StreamUtils.h"
#include "../../../../C/CpuArch.h"
#include "WimHandler.h" #include "WimHandler.h"
@@ -28,17 +27,18 @@ namespace NWim {
#define WIM_DETAILS #define WIM_DETAILS
STATPROPSTG kProps[] = static STATPROPSTG kProps[] =
{ {
{ NULL, kpidPath, VT_BSTR}, { NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL}, { NULL, kpidIsDir, VT_BOOL},
{ NULL, kpidSize, VT_UI8}, { NULL, kpidSize, VT_UI8},
{ NULL, kpidPackSize, VT_UI8}, { NULL, kpidPackSize, VT_UI8},
{ NULL, kpidAttrib, VT_UI4},
{ NULL, kpidMethod, VT_BSTR},
{ NULL, kpidMTime, VT_FILETIME}, { NULL, kpidMTime, VT_FILETIME},
{ NULL, kpidCTime, VT_FILETIME}, { NULL, kpidCTime, VT_FILETIME},
{ NULL, kpidATime, VT_FILETIME} { NULL, kpidATime, VT_FILETIME},
{ NULL, kpidAttrib, VT_UI4},
{ NULL, kpidMethod, VT_BSTR},
{ NULL, kpidShortName, VT_BSTR}
#ifdef WIM_DETAILS #ifdef WIM_DETAILS
, { NULL, kpidVolume, VT_UI4} , { NULL, kpidVolume, VT_UI4}
@@ -47,14 +47,14 @@ STATPROPSTG kProps[] =
#endif #endif
}; };
STATPROPSTG kArcProps[] = static STATPROPSTG kArcProps[] =
{ {
{ NULL, kpidSize, VT_UI8}, { NULL, kpidSize, VT_UI8},
{ NULL, kpidPackSize, VT_UI8}, { NULL, kpidPackSize, VT_UI8},
{ NULL, kpidMethod, VT_BSTR}, { NULL, kpidMethod, VT_BSTR},
{ NULL, kpidCTime, VT_FILETIME}, { NULL, kpidCTime, VT_FILETIME},
{ NULL, kpidMTime, VT_FILETIME}, { NULL, kpidMTime, VT_FILETIME},
{ NULL, kpidComment, VT_FILETIME}, { NULL, kpidComment, VT_BSTR},
{ NULL, kpidIsVolume, VT_BOOL}, { NULL, kpidIsVolume, VT_BOOL},
{ NULL, kpidVolume, VT_UI4}, { NULL, kpidVolume, VT_UI4},
{ NULL, kpidNumVolumes, VT_UI4} { NULL, kpidNumVolumes, VT_UI4}
@@ -87,49 +87,51 @@ static bool ParseNumber32(const AString &s, UInt32 &res)
return true; return true;
} }
void ParseTime(const CXmlItem &item, bool &defined, FILETIME &ft, const AString &s) bool ParseTime(const CXmlItem &item, FILETIME &ft, const char *tag)
{ {
defined = false; int index = item.FindSubTag(tag);
int cTimeIndex = item.FindSubTag(s); if (index >= 0)
if (cTimeIndex >= 0)
{ {
const CXmlItem &timeItem = item.SubItems[cTimeIndex]; const CXmlItem &timeItem = item.SubItems[index];
UInt32 high = 0, low = 0; UInt32 low = 0, high = 0;
if (ParseNumber32(timeItem.GetSubStringForTag("HIGHPART"), high) && if (ParseNumber32(timeItem.GetSubStringForTag("LOWPART"), low) &&
ParseNumber32(timeItem.GetSubStringForTag("LOWPART"), low)) ParseNumber32(timeItem.GetSubStringForTag("HIGHPART"), high))
{ {
defined = true;
ft.dwHighDateTime = high;
ft.dwLowDateTime = low; ft.dwLowDateTime = low;
ft.dwHighDateTime = high;
return true;
} }
} }
return false;
} }
void CImageInfo::Parse(const CXmlItem &item) void CImageInfo::Parse(const CXmlItem &item)
{ {
ParseTime(item, CTimeDefined, CTime, "CREATIONTIME"); CTimeDefined = ParseTime(item, CTime, "CREATIONTIME");
ParseTime(item, MTimeDefined, MTime, "LASTMODIFICATIONTIME"); MTimeDefined = ParseTime(item, MTime, "LASTMODIFICATIONTIME");
NameDefined = ConvertUTF8ToUnicode(item.GetSubStringForTag("NAME"), Name); NameDefined = ConvertUTF8ToUnicode(item.GetSubStringForTag("NAME"), Name);
// IndexDefined = ParseNumber32(item.GetPropertyValue("INDEX"), Index); // IndexDefined = ParseNumber32(item.GetPropertyValue("INDEX"), Index);
} }
void CXml::Parse() void CXml::ToUnicode(UString &s)
{ {
size_t size = Data.GetCapacity(); size_t size = Data.GetCapacity();
if (size < 2 || (size & 1) != 0 || (size > 1 << 24)) if (size < 2 || (size & 1) != 0 || size > (1 << 24))
return; return;
const Byte *p = Data; const Byte *p = Data;
if (Get16(p) != 0xFEFF) if (Get16(p) != 0xFEFF)
return; return;
UString s; wchar_t *chars = s.GetBuffer((int)size / 2);
{
wchar_t *chars = s.GetBuffer((int)size / 2 + 1);
for (size_t i = 2; i < size; i += 2) for (size_t i = 2; i < size; i += 2)
*chars++ = (wchar_t)Get16(p + i); *chars++ = (wchar_t)Get16(p + i);
*chars = 0; *chars = 0;
s.ReleaseBuffer(); s.ReleaseBuffer();
} }
void CXml::Parse()
{
UString s;
ToUnicode(s);
AString utf; AString utf;
if (!ConvertUnicodeToUTF8(s, utf)) if (!ConvertUnicodeToUTF8(s, utf))
return; return;
@@ -151,10 +153,9 @@ void CXml::Parse()
} }
} }
static const wchar_t *kStreamsNamePrefix = L"Files" WSTRING_PATH_SEPARATOR; static const char *kMethodLZX = "LZX";
static const wchar_t *kMethodLZX = L"LZX"; static const char *kMethodXpress = "XPress";
static const wchar_t *kMethodXpress = L"XPress"; static const char *kMethodCopy = "Copy";
static const wchar_t *kMethodCopy = L"Copy";
IMP_IInArchive_Props IMP_IInArchive_Props
IMP_IInArchive_ArcProps IMP_IInArchive_ArcProps
@@ -165,22 +166,22 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
NWindows::NCOM::CPropVariant prop; NWindows::NCOM::CPropVariant prop;
const CImageInfo *image = NULL; const CImageInfo *image = NULL;
if (m_Xmls.Size() == 1) if (_xmls.Size() == 1)
{ {
const CXml &xml = m_Xmls[0]; const CXml &xml = _xmls[0];
if (xml.Images.Size() == 1) if (xml.Images.Size() == 1)
image = &xml.Images[0]; image = &xml.Images[0];
} }
switch(propID) switch(propID)
{ {
case kpidSize: prop = m_Database.GetUnpackSize(); break; case kpidSize: prop = _db.GetUnpackSize(); break;
case kpidPackSize: prop = m_Database.GetPackSize(); break; case kpidPackSize: prop = _db.GetPackSize(); break;
case kpidCTime: case kpidCTime:
if (m_Xmls.Size() == 1) if (_xmls.Size() == 1)
{ {
const CXml &xml = m_Xmls[0]; const CXml &xml = _xmls[0];
int index = -1; int index = -1;
for (int i = 0; i < xml.Images.Size(); i++) for (int i = 0; i < xml.Images.Size(); i++)
{ {
@@ -195,9 +196,9 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
break; break;
case kpidMTime: case kpidMTime:
if (m_Xmls.Size() == 1) if (_xmls.Size() == 1)
{ {
const CXml &xml = m_Xmls[0]; const CXml &xml = _xmls[0];
int index = -1; int index = -1;
for (int i = 0; i < xml.Images.Size(); i++) for (int i = 0; i < xml.Images.Size(); i++)
{ {
@@ -211,32 +212,43 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
} }
break; break;
case kpidComment: if (image != NULL && image->NameDefined) prop = image->Name; break; case kpidComment:
if (image != NULL)
{
if (_xmlInComments)
{
UString s;
_xmls[0].ToUnicode(s);
prop = s;
}
else if (image->NameDefined)
prop = image->Name;
}
break;
case kpidIsVolume: case kpidIsVolume:
if (m_Xmls.Size() > 0) if (_xmls.Size() > 0)
{ {
UInt16 volIndex = m_Xmls[0].VolIndex; UInt16 volIndex = _xmls[0].VolIndex;
if (volIndex < m_Volumes.Size()) if (volIndex < _volumes.Size())
prop = (m_Volumes[volIndex].Header.NumParts > 1); prop = (_volumes[volIndex].Header.NumParts > 1);
} }
break; break;
case kpidVolume: case kpidVolume:
if (m_Xmls.Size() > 0) if (_xmls.Size() > 0)
{ {
UInt16 volIndex = m_Xmls[0].VolIndex; UInt16 volIndex = _xmls[0].VolIndex;
if (volIndex < m_Volumes.Size()) if (volIndex < _volumes.Size())
prop = (UInt32)m_Volumes[volIndex].Header.PartNumber; prop = (UInt32)_volumes[volIndex].Header.PartNumber;
} }
break; break;
case kpidNumVolumes: if (m_Volumes.Size() > 0) prop = (UInt32)(m_Volumes.Size() - 1); break; case kpidNumVolumes: if (_volumes.Size() > 0) prop = (UInt32)(_volumes.Size() - 1); break;
case kpidMethod: case kpidMethod:
{ {
bool lzx = false, xpress = false, copy = false; bool lzx = false, xpress = false, copy = false;
for (int i = 0; i < m_Xmls.Size(); i++) for (int i = 0; i < _xmls.Size(); i++)
{ {
const CVolume &vol = m_Volumes[m_Xmls[i].VolIndex]; const CHeader &header = _volumes[_xmls[i].VolIndex].Header;
const CHeader &header = vol.Header;
if (header.IsCompressed()) if (header.IsCompressed())
if (header.IsLzxMode()) if (header.IsLzxMode())
lzx = true; lzx = true;
@@ -245,19 +257,19 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
else else
copy = true; copy = true;
} }
UString res; AString res;
if (lzx) if (lzx)
res = kMethodLZX; res = kMethodLZX;
if (xpress) if (xpress)
{ {
if (!res.IsEmpty()) if (!res.IsEmpty())
res += L' '; res += ' ';
res += kMethodXpress; res += kMethodXpress;
} }
if (copy) if (copy)
{ {
if (!res.IsEmpty()) if (!res.IsEmpty())
res += L' '; res += ' ';
res += kMethodCopy; res += kMethodCopy;
} }
prop = res; prop = res;
@@ -272,35 +284,41 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop; NWindows::NCOM::CPropVariant prop;
if (index < (UInt32)m_Database.Items.Size()) if (index < (UInt32)_db.SortedItems.Size())
{ {
const CItem &item = m_Database.Items[index]; int realIndex = _db.SortedItems[index];
const CItem &item = _db.Items[realIndex];
const CStreamInfo *si = NULL; const CStreamInfo *si = NULL;
const CVolume *vol = NULL; const CVolume *vol = NULL;
if (item.StreamIndex >= 0) if (item.StreamIndex >= 0)
{ {
si = &m_Database.Streams[item.StreamIndex]; si = &_db.Streams[item.StreamIndex];
vol = &m_Volumes[si->PartNumber]; vol = &_volumes[si->PartNumber];
} }
switch(propID) switch(propID)
{ {
case kpidPath: case kpidPath:
if (item.HasMetadata) if (item.HasMetadata)
prop = item.Name; prop = _db.GetItemPath(realIndex);
else else
{ {
wchar_t sz[32]; char sz[32];
ConvertUInt64ToString(item.StreamIndex, sz); ConvertUInt64ToString(item.StreamIndex, sz);
UString s = sz; AString s = sz;
while (s.Length() < m_NameLenForStreams) while (s.Length() < _nameLenForStreams)
s = L'0' + s; s = '0' + s;
s = UString(kStreamsNamePrefix) + s; /*
if (si->Resource.IsFree())
prefix = "[Free]";
*/
s = "[Files]" STRING_PATH_SEPARATOR + s;
prop = s; prop = s;
break;
} }
break; break;
case kpidIsDir: prop = item.isDir(); break; case kpidShortName: if (item.HasMetadata) prop = item.ShortName; break;
case kpidIsDir: prop = item.IsDir(); break;
case kpidAttrib: if (item.HasMetadata) prop = item.Attrib; break; case kpidAttrib: if (item.HasMetadata) prop = item.Attrib; break;
case kpidCTime: if (item.HasMetadata) prop = item.CTime; break; case kpidCTime: if (item.HasMetadata) prop = item.CTime; break;
case kpidATime: if (item.HasMetadata) prop = item.ATime; break; case kpidATime: if (item.HasMetadata) prop = item.ATime; break;
@@ -318,22 +336,21 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
} }
else else
{ {
index -= m_Database.Items.Size(); index -= _db.SortedItems.Size();
{ {
switch(propID) switch(propID)
{ {
case kpidPath: case kpidPath:
{ {
wchar_t sz[32]; char sz[32];
ConvertUInt64ToString(m_Xmls[index].VolIndex, sz); ConvertUInt64ToString(_xmls[index].VolIndex, sz);
UString s = (UString)sz + L".xml"; prop = (AString)"[" + (AString)sz + "].xml";
prop = s;
break; break;
} }
case kpidIsDir: prop = false; break; case kpidIsDir: prop = false; break;
case kpidPackSize: case kpidPackSize:
case kpidSize: prop = (UInt64)m_Xmls[index].Data.GetCapacity(); break; case kpidSize: prop = (UInt64)_xmls[index].Data.GetCapacity(); break;
case kpidMethod: prop = L"Copy"; break; case kpidMethod: prop = kMethodCopy; break;
} }
} }
} }
@@ -411,13 +428,13 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
return res; return res;
} }
if (firstVolumeIndex >= 0) if (firstVolumeIndex >= 0)
if (!header.AreFromOnArchive(m_Volumes[firstVolumeIndex].Header)) if (!header.AreFromOnArchive(_volumes[firstVolumeIndex].Header))
break; break;
if (m_Volumes.Size() > header.PartNumber && m_Volumes[header.PartNumber].Stream) if (_volumes.Size() > header.PartNumber && _volumes[header.PartNumber].Stream)
break; break;
CXml xml; CXml xml;
xml.VolIndex = header.PartNumber; xml.VolIndex = header.PartNumber;
res = OpenArchive(curStream, header, xml.Data, m_Database); res = _db.Open(curStream, header, xml.Data, openArchiveCallback);
if (res != S_OK) if (res != S_OK)
{ {
if (i == 1) if (i == 1)
@@ -427,22 +444,22 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
return res; return res;
} }
while (m_Volumes.Size() <= header.PartNumber) while (_volumes.Size() <= header.PartNumber)
m_Volumes.Add(CVolume()); _volumes.Add(CVolume());
CVolume &volume = m_Volumes[header.PartNumber]; CVolume &volume = _volumes[header.PartNumber];
volume.Header = header; volume.Header = header;
volume.Stream = curStream; volume.Stream = curStream;
firstVolumeIndex = header.PartNumber; firstVolumeIndex = header.PartNumber;
bool needAddXml = true; bool needAddXml = true;
if (m_Xmls.Size() != 0) if (_xmls.Size() != 0)
if (xml.Data == m_Xmls[0].Data) if (xml.Data == _xmls[0].Data)
needAddXml = false; needAddXml = false;
if (needAddXml) if (needAddXml)
{ {
xml.Parse(); xml.Parse();
m_Xmls.Add(xml); _xmls.Add(xml);
} }
if (i == 1) if (i == 1)
@@ -462,11 +479,14 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
} }
} }
RINOK(SortDatabase(m_Database)); _db.DetectPathMode();
RINOK(_db.Sort(_db.SkipRoot));
wchar_t sz[32]; wchar_t sz[32];
ConvertUInt64ToString(m_Database.Streams.Size(), sz); ConvertUInt64ToString(_db.Streams.Size(), sz);
m_NameLenForStreams = MyStringLen(sz); _nameLenForStreams = MyStringLen(sz);
_xmlInComments = (_xmls.Size() == 1 && !_db.ShowImageNumber);
} }
catch(...) catch(...)
{ {
@@ -478,10 +498,10 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
STDMETHODIMP CHandler::Close() STDMETHODIMP CHandler::Close()
{ {
m_Database.Clear(); _db.Clear();
m_Volumes.Clear(); _volumes.Clear();
m_Xmls.Clear(); _xmls.Clear();
m_NameLenForStreams = 0; _nameLenForStreams = 0;
return S_OK; return S_OK;
} }
@@ -492,7 +512,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
bool allFilesMode = (numItems == (UInt32)-1); bool allFilesMode = (numItems == (UInt32)-1);
if (allFilesMode) if (allFilesMode)
numItems = m_Database.Items.Size() + m_Xmls.Size(); numItems = _db.SortedItems.Size() + _xmls.Size();
if (numItems == 0) if (numItems == 0)
return S_OK; return S_OK;
@@ -501,17 +521,17 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
for (i = 0; i < numItems; i++) for (i = 0; i < numItems; i++)
{ {
UInt32 index = allFilesMode ? i : indices[i]; UInt32 index = allFilesMode ? i : indices[i];
if (index < (UInt32)m_Database.Items.Size()) if (index < (UInt32)_db.SortedItems.Size())
{ {
int streamIndex = m_Database.Items[index].StreamIndex; int streamIndex = _db.Items[_db.SortedItems[index]].StreamIndex;
if (streamIndex >= 0) if (streamIndex >= 0)
{ {
const CStreamInfo &si = m_Database.Streams[streamIndex]; const CStreamInfo &si = _db.Streams[streamIndex];
totalSize += si.Resource.UnpackSize; totalSize += si.Resource.UnpackSize;
} }
} }
else else
totalSize += m_Xmls[index - (UInt32)m_Database.Items.Size()].Data.GetCapacity(); totalSize += _xmls[index - (UInt32)_db.SortedItems.Size()].Data.GetCapacity();
} }
RINOK(extractCallback->SetTotal(totalSize)); RINOK(extractCallback->SetTotal(totalSize));
@@ -546,12 +566,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
if (index >= (UInt32)m_Database.Items.Size()) if (index >= (UInt32)_db.SortedItems.Size())
{ {
if (!testMode && !realOutStream) if (!testMode && !realOutStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
const CByteBuffer &data = m_Xmls[index - (UInt32)m_Database.Items.Size()].Data; const CByteBuffer &data = _xmls[index - (UInt32)_db.SortedItems.Size()].Data;
currentItemUnPacked = data.GetCapacity(); currentItemUnPacked = data.GetCapacity();
if (realOutStream) if (realOutStream)
{ {
@@ -562,7 +582,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
continue; continue;
} }
const CItem &item = m_Database.Items[index]; const CItem &item = _db.Items[_db.SortedItems[index]];
int streamIndex = item.StreamIndex; int streamIndex = item.StreamIndex;
if (streamIndex < 0) if (streamIndex < 0)
{ {
@@ -576,7 +596,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
continue; continue;
} }
const CStreamInfo &si = m_Database.Streams[streamIndex]; const CStreamInfo &si = _db.Streams[streamIndex];
currentItemUnPacked = si.Resource.UnpackSize; currentItemUnPacked = si.Resource.UnpackSize;
currentItemPacked = si.Resource.PackSize; currentItemPacked = si.Resource.PackSize;
@@ -587,7 +607,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (streamIndex != prevSuccessStreamIndex || realOutStream) if (streamIndex != prevSuccessStreamIndex || realOutStream)
{ {
Byte digest[20]; Byte digest[20];
const CVolume &vol = m_Volumes[si.PartNumber]; const CVolume &vol = _volumes[si.PartNumber];
HRESULT res = unpacker.Unpack(vol.Stream, si.Resource, vol.Header.IsLzxMode(), HRESULT res = unpacker.Unpack(vol.Stream, si.Resource, vol.Header.IsLzxMode(),
realOutStream, progress, digest); realOutStream, progress, digest);
if (res == S_OK) if (res == S_OK)
@@ -611,7 +631,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{ {
*numItems = m_Database.Items.Size() + m_Xmls.Size(); *numItems = _db.SortedItems.Size();
if (!_xmlInComments)
*numItems += _xmls.Size();
return S_OK; return S_OK;
} }

View File

@@ -6,7 +6,6 @@
#include "Common/MyCom.h" #include "Common/MyCom.h"
#include "Common/MyXml.h" #include "Common/MyXml.h"
#include "../IArchive.h"
#include "WimIn.h" #include "WimIn.h"
namespace NArchive { namespace NArchive {
@@ -40,25 +39,35 @@ struct CXml
{ {
CByteBuffer Data; CByteBuffer Data;
UInt16 VolIndex; UInt16 VolIndex;
CObjectVector<CImageInfo> Images; CObjectVector<CImageInfo> Images;
void ToUnicode(UString &s);
void Parse(); void Parse();
}; };
class CHandler: class CHandler:
public IInArchive, public IInArchive,
public CMyUnknownImp public CMyUnknownImp
{ {
CDatabase _db;
CObjectVector<CVolume> _volumes;
CObjectVector<CXml> _xmls;
int _nameLenForStreams;
bool _xmlInComments;
public: public:
MY_UNKNOWN_IMP1(IInArchive) MY_UNKNOWN_IMP1(IInArchive)
INTERFACE_IInArchive(;) INTERFACE_IInArchive(;)
};
private: class COutHandler:
CDatabase m_Database; public IOutArchive,
CObjectVector<CVolume> m_Volumes; public CMyUnknownImp
CObjectVector<CXml> m_Xmls; {
int m_NameLenForStreams; public:
MY_UNKNOWN_IMP1(IOutArchive)
INTERFACE_IOutArchive(;)
}; };
}} }}

View File

@@ -0,0 +1,647 @@
// WimHandlerOut.cpp
#include "StdAfx.h"
#include "../../../../C/CpuArch.h"
#include "Common/ComTry.h"
#include "Common/IntToString.h"
#include "Windows/PropVariant.h"
#include "Windows/Time.h"
#include "../../Common/LimitedStreams.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamUtils.h"
#include "../../Crypto/RandGen.h"
#include "../../Crypto/Sha1.h"
#include "WimHandler.h"
using namespace NWindows;
namespace NArchive {
namespace NWim {
struct CSha1Hash
{
Byte Hash[kHashSize];
};
struct CHashList
{
CRecordVector<CSha1Hash> Digests;
CIntVector Sorted;
int AddUnique(const CSha1Hash &h);
};
int CHashList::AddUnique(const CSha1Hash &h)
{
int left = 0, right = Sorted.Size();
while (left != right)
{
int mid = (left + right) / 2;
int index = Sorted[mid];
UInt32 i;
const Byte *hash2 = Digests[index].Hash;
for (i = 0; i < kHashSize; i++)
if (h.Hash[i] != hash2[i])
break;
if (i == kHashSize)
return index;
if (h.Hash[i] < hash2[i])
right = mid;
else
left = mid + 1;
}
Sorted.Insert(left, Digests.Add(h));
return -1;
}
struct CUpdateItem
{
UString Name;
UInt64 Size;
FILETIME CTime;
FILETIME ATime;
FILETIME MTime;
UInt32 Attrib;
bool IsDir;
int HashIndex;
CUpdateItem(): HashIndex(-1) {}
};
struct CDir
{
int Index;
UString Name;
CObjectVector<CDir> Dirs;
CIntVector Files;
CDir(): Index(-1) {}
bool IsLeaf() const { return Index >= 0; }
UInt64 GetNumDirs() const;
UInt64 GetNumFiles() const;
CDir* AddDir(CObjectVector<CUpdateItem> &items, const UString &name, int index);
};
UInt64 CDir::GetNumDirs() const
{
UInt64 num = Dirs.Size();
for (int i = 0; i < Dirs.Size(); i++)
num += Dirs[i].GetNumDirs();
return num;
}
UInt64 CDir::GetNumFiles() const
{
UInt64 num = Files.Size();
for (int i = 0; i < Dirs.Size(); i++)
num += Dirs[i].GetNumFiles();
return num;
}
CDir* CDir::AddDir(CObjectVector<CUpdateItem> &items, const UString &name, int index)
{
int left = 0, right = Dirs.Size();
while (left != right)
{
int mid = (left + right) / 2;
CDir &d = Dirs[mid];
int compare = name.CompareNoCase(d.IsLeaf() ? items[Dirs[mid].Index].Name : d.Name);
if (compare == 0)
{
if (index >= 0)
d.Index = index;
return &d;
}
if (compare < 0)
right = mid;
else
left = mid + 1;
}
Dirs.Insert(left, CDir());
CDir &d = Dirs[left];
d.Index = index;
if (index < 0)
d.Name = name;
return &d;
}
STDMETHODIMP COutHandler::GetFileTimeType(UInt32 *type)
{
*type = NFileTimeType::kWindows;
return S_OK;
}
static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propID, FILETIME &ft)
{
ft.dwLowDateTime = ft.dwHighDateTime = 0;
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(index, propID, &prop));
if (prop.vt == VT_FILETIME)
ft = prop.filetime;
else if (prop.vt != VT_EMPTY)
return E_INVALIDARG;
return S_OK;
}
#define Set16(p, d) SetUi16(p, d)
#define Set32(p, d) SetUi32(p, d)
#define Set64(p, d) SetUi64(p, d)
void CResource::WriteTo(Byte *p) const
{
Set64(p, PackSize);
p[7] = Flags;
Set64(p + 8, Offset);
Set64(p + 16, UnpackSize);
}
void CHeader::WriteTo(Byte *p) const
{
memcpy(p, kSignature, kSignatureSize);
Set32(p + 8, kHeaderSizeMax);
Set32(p + 0xC, Version);
Set32(p + 0x10, Flags);
Set32(p + 0x14, ChunkSize);
memcpy(p + 0x18, Guid, 16);
Set16(p + 0x28, PartNumber);
Set16(p + 0x2A, NumParts);
Set32(p + 0x2C, NumImages);
OffsetResource.WriteTo(p + 0x30);
XmlResource.WriteTo(p + 0x48);
MetadataResource.WriteTo(p + 0x60);
IntegrityResource.WriteTo(p + 0x7C);
Set32(p + 0x78, BootIndex);
memset(p + 0x94, 0, 60);
}
void CStreamInfo::WriteTo(Byte *p) const
{
Resource.WriteTo(p);
Set16(p + 0x18, PartNumber);
Set32(p + 0x1A, RefCount);
memcpy(p + 0x1E, Hash, kHashSize);
}
class CInStreamWithSha1:
public ISequentialInStream,
public CMyUnknownImp
{
CMyComPtr<ISequentialInStream> _stream;
UInt64 _size;
NCrypto::NSha1::CContext _sha;
public:
MY_UNKNOWN_IMP1(IInStream)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
void SetStream(ISequentialInStream *stream) { _stream = stream; }
void Init()
{
_size = 0;
_sha.Init();
}
void ReleaseStream() { _stream.Release(); }
UInt64 GetSize() const { return _size; }
void Final(Byte *digest) { _sha.Final(digest); }
};
STDMETHODIMP CInStreamWithSha1::Read(void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 realProcessedSize;
HRESULT result = _stream->Read(data, size, &realProcessedSize);
_size += realProcessedSize;
_sha.Update((const Byte *)data, realProcessedSize);
if (processedSize != NULL)
*processedSize = realProcessedSize;
return result;
}
static void SetFileTimeToMem(Byte *p, const FILETIME &ft)
{
Set32(p, ft.dwLowDateTime);
Set32(p + 4, ft.dwHighDateTime);
}
static size_t WriteItem(const CUpdateItem &item, Byte *p, const Byte *hash)
{
int fileNameLen = item.Name.Length() * 2;
int fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2);
size_t totalLen = ((kDirRecordSize + fileNameLen2 + 6) & ~7);
if (p)
{
memset(p, 0, totalLen);
Set64(p, totalLen);
Set64(p + 8, item.Attrib);
Set32(p + 0xC, (UInt32)(Int32)-1); // item.SecurityId
// Set64(p + 0x10, 0); // subdirOffset
SetFileTimeToMem(p + 0x28, item.CTime);
SetFileTimeToMem(p + 0x30, item.ATime);
SetFileTimeToMem(p + 0x38, item.MTime);
if (hash)
memcpy(p + 0x40, hash, kHashSize);
/*
else
memset(p + 0x40, 0, kHashSize);
*/
// Set16(p + 98, 0); // shortNameLen
Set16(p + 100, (UInt16)fileNameLen);
for (int i = 0; i * 2 < fileNameLen; i++)
Set16(p + kDirRecordSize + i * 2, item.Name[i]);
}
return totalLen;
}
void WriteTree(const CDir &tree, CRecordVector<CSha1Hash> &digests,
CUpdateItem &defaultDirItem,
CObjectVector<CUpdateItem> &updateItems, Byte *dest, size_t &pos)
{
int i;
for (i = 0; i < tree.Files.Size(); i++)
{
const CUpdateItem &ui = updateItems[tree.Files[i]];
pos += WriteItem(ui, dest ? dest + pos : NULL,
ui.HashIndex >= 0 ? digests[ui.HashIndex].Hash : NULL);
}
size_t posStart = pos;
for (i = 0; i < tree.Dirs.Size(); i++)
{
const CDir &subfolder = tree.Dirs[i];
CUpdateItem *item = &defaultDirItem;
if (subfolder.IsLeaf())
item = &updateItems[subfolder.Index];
else
defaultDirItem.Name = subfolder.Name;
pos += WriteItem(*item, NULL, NULL);
}
if (dest)
Set64(dest + pos, 0);
pos += 8;
for (i = 0; i < tree.Dirs.Size(); i++)
{
const CDir &subfolder = tree.Dirs[i];
if (dest)
{
CUpdateItem *item = &defaultDirItem;
if (subfolder.IsLeaf())
item = &updateItems[subfolder.Index];
else
defaultDirItem.Name = subfolder.Name;
size_t len = WriteItem(*item, dest + posStart, NULL);
Set64(dest + posStart + 0x10, pos);
posStart += len;
}
WriteTree(subfolder, digests, defaultDirItem, updateItems, dest, pos);
}
}
static void AddTag(AString &s, const char *name, const AString &value)
{
s += "<";
s += name;
s += ">";
s += value;
s += "</";
s += name;
s += ">";
}
static void AddTagUInt64(AString &s, const char *name, UInt64 value)
{
char temp[32];
ConvertUInt64ToString(value, temp);
AddTag(s, name, temp);
}
static void ConvertUInt32ToHex(UInt32 value, char *s)
{
for (int i = 0; i < 8; i++)
{
int t = value & 0xF;
value >>= 4;
s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
}
s[8] = '\0';
}
static AString TimeToXml(FILETIME &ft)
{
AString res;
char temp[16] = { '0', 'x' };
ConvertUInt32ToHex(ft.dwHighDateTime, temp + 2);
AddTag(res, "HIGHPART", temp);
ConvertUInt32ToHex(ft.dwLowDateTime, temp + 2);
AddTag(res, "LOWPART", temp);
return res;
}
void CHeader::SetDefaultFields(bool useLZX)
{
Version = kWimVersion;
Flags = NHeaderFlags::kRpFix;
ChunkSize = 0;
if (useLZX)
{
Flags |= NHeaderFlags::kCompression | NHeaderFlags::kLZX;
ChunkSize = kChunkSize;
}
g_RandomGenerator.Generate(Guid, 16);
PartNumber = 1;
NumParts = 1;
NumImages = 1;
BootIndex = 0;
OffsetResource.Clear();
XmlResource.Clear();
MetadataResource.Clear();
IntegrityResource.Clear();
}
static HRESULT UpdateArchive(ISequentialOutStream *seqOutStream,
CDir &rootFolder,
CObjectVector<CUpdateItem> &updateItems,
IArchiveUpdateCallback *callback)
{
CMyComPtr<IOutStream> outStream;
RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream));
if (!outStream)
return E_NOTIMPL;
UInt64 complexity = 0;
int i;
for (i = 0; i < updateItems.Size(); i++)
complexity += updateItems[i].Size;
RINOK(callback->SetTotal(complexity));
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(callback, true);
complexity = 0;
bool useCompression = false;
CHeader header;
header.SetDefaultFields(useCompression);
Byte buf[kHeaderSizeMax];
header.WriteTo(buf);
RINOK(WriteStream(outStream, buf, kHeaderSizeMax));
CHashList hashes;
CObjectVector<CStreamInfo> streams;
UInt64 curPos = kHeaderSizeMax;
UInt64 unpackTotalSize = 0;
for (i = 0; i < updateItems.Size(); i++)
{
lps->InSize = lps->OutSize = complexity;
RINOK(lps->SetCur());
CUpdateItem &ui = updateItems[i];
if (ui.IsDir || ui.Size == 0)
continue;
CInStreamWithSha1 *inShaStreamSpec = new CInStreamWithSha1;
CMyComPtr<ISequentialInStream> inShaStream = inShaStreamSpec;
{
CMyComPtr<ISequentialInStream> fileInStream;
HRESULT res = callback->GetStream(i, &fileInStream);
if (res != S_FALSE)
{
RINOK(res);
inShaStreamSpec->SetStream(fileInStream);
fileInStream.Release();
inShaStreamSpec->Init();
UInt64 offsetBlockSize = 0;
if (useCompression)
{
for (UInt64 t = kChunkSize; t < ui.Size; t += kChunkSize)
{
Byte buf[8];
SetUi32(buf, (UInt32)t);
RINOK(WriteStream(outStream, buf, 4));
offsetBlockSize += 4;
}
}
RINOK(copyCoder->Code(inShaStream, outStream, NULL, NULL, progress));
ui.Size = copyCoderSpec->TotalSize;
CSha1Hash hash;
unpackTotalSize += ui.Size;
UInt64 packSize = offsetBlockSize + ui.Size;
inShaStreamSpec->Final(hash.Hash);
int index = hashes.AddUnique(hash);
if (index >= 0)
{
ui.HashIndex = index;
streams[index].RefCount++;
outStream->Seek(-(Int64)packSize, STREAM_SEEK_CUR, &curPos);
outStream->SetSize(curPos);
}
else
{
ui.HashIndex = hashes.Digests.Size() - 1;
CStreamInfo s;
s.Resource.PackSize = packSize;
s.Resource.Offset = curPos;
s.Resource.UnpackSize = ui.Size;
s.Resource.Flags = 0;
if (useCompression)
s.Resource.Flags = NResourceFlags::Compressed;
s.PartNumber = 1;
s.RefCount = 1;
memcpy(s.Hash, hash.Hash, kHashSize);
streams.Add(s);
curPos += packSize;
}
}
fileInStream.Release();
complexity += ui.Size;
RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
}
}
CUpdateItem ri;
FILETIME ft;
NTime::GetCurUtcFileTime(ft);
ri.MTime = ri.ATime = ri.CTime = ft;
ri.Attrib = FILE_ATTRIBUTE_DIRECTORY;
const UInt32 kSecuritySize = 8;
size_t pos = kSecuritySize;
WriteTree(rootFolder, hashes.Digests, ri, updateItems, NULL, pos);
CByteBuffer meta;
meta.SetCapacity(pos);
// memset(meta, 0, kSecuritySize);
Set32((Byte *)meta, 0); // only if there is no security data, we can use 0 here.
Set32((Byte *)meta + 4, 0); // num security entries
pos = kSecuritySize;
WriteTree(rootFolder, hashes.Digests, ri, updateItems, (Byte *)meta, pos);
{
NCrypto::NSha1::CContext sha;
sha.Init();
sha.Update((const Byte *)meta, pos);
CSha1Hash digest;
sha.Final(digest.Hash);
CStreamInfo s;
s.Resource.PackSize = pos;
s.Resource.Offset = curPos;
s.Resource.UnpackSize = pos;
s.Resource.Flags = NResourceFlags::kMetadata;
s.PartNumber = 1;
s.RefCount = 1;
memcpy(s.Hash, digest.Hash, kHashSize);
streams.Add(s);
RINOK(WriteStream(outStream, (const Byte *)meta, pos));
meta.Free();
curPos += pos;
}
header.OffsetResource.UnpackSize = header.OffsetResource.PackSize = (UInt64)streams.Size() * kStreamInfoSize;
header.OffsetResource.Offset = curPos;
header.OffsetResource.Flags = NResourceFlags::kMetadata;
for (i = 0; i < streams.Size(); i++)
{
Byte buf[kStreamInfoSize];
streams[i].WriteTo(buf);
RINOK(WriteStream(outStream, buf, kStreamInfoSize));
curPos += kStreamInfoSize;
}
AString xml = "<WIM>";
AddTagUInt64(xml, "TOTALBYTES", curPos);
xml += "<IMAGE INDEX=\"1\"><NAME>1</NAME>";
AddTagUInt64(xml, "DIRCOUNT", rootFolder.GetNumDirs());
AddTagUInt64(xml, "FILECOUNT", rootFolder.GetNumFiles());
AddTagUInt64(xml, "TOTALBYTES", unpackTotalSize);
NTime::GetCurUtcFileTime(ft);
AddTag(xml, "CREATIONTIME", TimeToXml(ft));
AddTag(xml, "LASTMODIFICATIONTIME", TimeToXml(ft));
xml += "</IMAGE></WIM>";
size_t xmlSize = (xml.Length() + 1) * 2;
meta.SetCapacity(xmlSize);
Set16((Byte *)meta, 0xFEFF);
for (i = 0; i < xml.Length(); i++)
Set16((Byte *)meta + 2 + i * 2, xml[i]);
RINOK(WriteStream(outStream, (const Byte *)meta, xmlSize));
meta.Free();
header.XmlResource.UnpackSize = header.XmlResource.PackSize = xmlSize;
header.XmlResource.Offset = curPos;
header.XmlResource.Flags = NResourceFlags::kMetadata;
outStream->Seek(0, STREAM_SEEK_SET, NULL);
header.WriteTo(buf);
return WriteStream(outStream, buf, kHeaderSizeMax);
}
STDMETHODIMP COutHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *callback)
{
COM_TRY_BEGIN
CObjectVector<CUpdateItem> updateItems;
CDir tree;
tree.Dirs.Add(CDir());
CDir &rootFolder = tree.Dirs.Back();
for (UInt32 i = 0; i < numItems; i++)
{
CUpdateItem ui;
Int32 newData, newProps;
UInt32 indexInArchive;
if (!callback)
return E_FAIL;
RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
{
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidIsDir, &prop));
if (prop.vt == VT_EMPTY)
ui.IsDir = false;
else if (prop.vt != VT_BOOL)
return E_INVALIDARG;
else
ui.IsDir = (prop.boolVal != VARIANT_FALSE);
}
{
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidAttrib, &prop));
if (prop.vt == VT_EMPTY)
ui.Attrib = (ui.IsDir ? FILE_ATTRIBUTE_DIRECTORY : 0);
else if (prop.vt != VT_UI4)
return E_INVALIDARG;
else
ui.Attrib = prop.ulVal;
}
RINOK(GetTime(callback, i, kpidCTime, ui.CTime));
RINOK(GetTime(callback, i, kpidATime, ui.ATime));
RINOK(GetTime(callback, i, kpidMTime, ui.MTime));
{
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidSize, &prop));
if (prop.vt != VT_UI8)
return E_INVALIDARG;
ui.Size = prop.uhVal.QuadPart;
}
UString path;
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidPath, &prop));
if (prop.vt == VT_BSTR)
path = prop.bstrVal;
else if (prop.vt != VT_EMPTY)
return E_INVALIDARG;
CDir *curItem = &rootFolder;
int len = path.Length();
UString fileName;
for (int j = 0; j < len; j++)
{
wchar_t c = path[j];
if (c == WCHAR_PATH_SEPARATOR || c == L'/')
{
curItem = curItem->AddDir(updateItems, fileName, -1);
fileName.Empty();
}
else
fileName += c;
}
ui.Name = fileName;
updateItems.Add(ui);
if (ui.IsDir)
curItem->AddDir(updateItems, fileName, (int)i);
else
curItem->Files.Add(i);
}
return UpdateArchive(outStream, tree, updateItems, callback);
COM_TRY_END
}
}}

View File

@@ -21,9 +21,6 @@
namespace NArchive { namespace NArchive {
namespace NWim { namespace NWim {
static const int kChunkSizeBits = 15;
static const UInt32 kChunkSize = (1 << kChunkSizeBits);
namespace NXpress { namespace NXpress {
class CDecoderFlusher class CDecoderFlusher
@@ -44,7 +41,7 @@ HRESULT CDecoder::CodeSpec(UInt32 outSize)
{ {
{ {
Byte levels[kMainTableSize]; Byte levels[kMainTableSize];
for (int i = 0; i < kMainTableSize; i += 2) for (unsigned i = 0; i < kMainTableSize; i += 2)
{ {
Byte b = m_InBitStream.DirectReadByte(); Byte b = m_InBitStream.DirectReadByte();
levels[i] = b & 0xF; levels[i] = b & 0xF;
@@ -128,12 +125,6 @@ HRESULT CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outS
} }
static void GetFileTimeFromMem(const Byte *p, FILETIME *ft)
{
ft->dwLowDateTime = Get32(p);
ft->dwHighDateTime = Get32(p + 4);
}
HRESULT CUnpacker::Unpack(IInStream *inStream, const CResource &resource, bool lzxMode, HRESULT CUnpacker::Unpack(IInStream *inStream, const CResource &resource, bool lzxMode,
ISequentialOutStream *outStream, ICompressProgressInfo *progress) ISequentialOutStream *outStream, ICompressProgressInfo *progress)
{ {
@@ -257,9 +248,6 @@ static HRESULT UnpackData(IInStream *inStream, const CResource &resource, bool l
return unpacker.Unpack(inStream, resource, lzxMode, outStream, NULL, digest); return unpacker.Unpack(inStream, resource, lzxMode, outStream, NULL, digest);
} }
static const UInt32 kSignatureSize = 8;
static const Byte kSignature[kSignatureSize] = { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 };
void CResource::Parse(const Byte *p) void CResource::Parse(const Byte *p)
{ {
Flags = p[7]; Flags = p[7];
@@ -278,19 +266,152 @@ static void GetStream(const Byte *p, CStreamInfo &s)
memcpy(s.Hash, p + 30, kHashSize); memcpy(s.Hash, p + 30, kHashSize);
} }
static HRESULT ParseDirItem(const Byte *base, size_t pos, size_t size, static const wchar_t *kLongPath = L"[LongPath]";
const UString &prefix, CObjectVector<CItem> &items)
UString CDatabase::GetItemPath(const int index1) const
{ {
for (;;) int size = 0;
int index = index1;
int newLevel;
for (newLevel = 0;; newLevel = 1)
{ {
if (pos + 8 > size) const CItem &item = Items[index];
return S_FALSE; index = item.Parent;
const Byte *p = base + pos; if (index >= 0 || !SkipRoot)
UInt64 length = Get64(p); size += item.Name.Length() + newLevel;
if (length == 0) if (index < 0)
break;
if ((UInt32)size >= ((UInt32)1 << 16))
return kLongPath;
}
wchar_t temp[16];
int imageLen = 0;
if (ShowImageNumber)
{
ConvertUInt32ToString(-1 - index, temp);
imageLen = MyStringLen(temp);
size += imageLen + 1;
}
if ((UInt32)size >= ((UInt32)1 << 16))
return kLongPath;
UString path;
wchar_t *s = path.GetBuffer(size);
s[size] = 0;
if (ShowImageNumber)
{
memcpy(s, temp, imageLen * sizeof(wchar_t));
s[imageLen] = WCHAR_PATH_SEPARATOR;
}
index = index1;
for (newLevel = 0;; newLevel = 1)
{
const CItem &item = Items[index];
index = item.Parent;
if (index >= 0 || !SkipRoot)
{
if (newLevel)
s[--size] = WCHAR_PATH_SEPARATOR;
size -= item.Name.Length();
memcpy(s + size, item.Name, sizeof(wchar_t) * item.Name.Length());
}
if (index < 0)
{
path.ReleaseBuffer();
return path;
}
}
}
static void GetFileTimeFromMem(const Byte *p, FILETIME *ft)
{
ft->dwLowDateTime = Get32(p);
ft->dwHighDateTime = Get32(p + 4);
}
static HRESULT ReadName(const Byte *p, int size, UString &dest)
{
if (size == 0)
return S_OK; return S_OK;
if (pos + 102 > size || pos + length + 8 > size || length > ((UInt64)1 << 62)) if (Get16(p + size) != 0)
return S_FALSE; return S_FALSE;
wchar_t *s = dest.GetBuffer(size / 2);
for (int i = 0; i <= size; i += 2)
*s++ = Get16(p + i);
dest.ReleaseBuffer();
return S_OK;
}
HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
{
if ((pos & 7) != 0)
return S_FALSE;
int prevIndex = -1;
for (int numItems = 0;; numItems++)
{
if (OpenCallback)
{
UInt64 numFiles = Items.Size();
if ((numFiles & 0x3FF) == 0)
{
RINOK(OpenCallback->SetCompleted(&numFiles, NULL));
}
}
size_t rem = DirSize - pos;
if (pos < DirStartOffset || pos > DirSize || rem < 8)
return S_FALSE;
const Byte *p = DirData + pos;
UInt64 len = Get64(p);
if (len == 0)
{
if (parent < 0 && numItems != 1)
SkipRoot = false;
DirProcessed += 8;
return S_OK;
}
if ((len & 7) != 0 || len < 0x28 || rem < len)
return S_FALSE;
DirProcessed += (size_t)len;
if (DirProcessed > DirSize)
return S_FALSE;
if (Get64(p + 8) == 0)
{
if (prevIndex == -1)
return S_FALSE;
UInt32 fileNameLen = Get16(p + 0x24);
if ((fileNameLen & 1) != 0 || ((0x26 + fileNameLen + 6) & ~7) != len)
return S_FALSE;
UString name;
RINOK(ReadName(p + 0x26, fileNameLen, name));
CItem &prevItem = Items[prevIndex];
if (name.IsEmpty() && !prevItem.HasStream())
memcpy(prevItem.Hash, p + 0x10, kHashSize);
else
{
CItem item;
item.Name = prevItem.Name + L':' + name;
item.CTime = prevItem.CTime;
item.ATime = prevItem.ATime;
item.MTime = prevItem.MTime;
memcpy(item.Hash, p + 0x10, kHashSize);
item.Attrib = 0;
item.Order = Order++;
item.Parent = parent;
Items.Add(item);
}
pos += (size_t)len;
continue;
}
if (len < kDirRecordSize)
return S_FALSE;
CItem item; CItem item;
item.Attrib = Get32(p + 8); item.Attrib = Get32(p + 8);
// item.SecurityId = Get32(p + 0xC); // item.SecurityId = Get32(p + 0xC);
@@ -300,43 +421,64 @@ static HRESULT ParseDirItem(const Byte *base, size_t pos, size_t size,
GetFileTimeFromMem(p + 0x38, &item.MTime); GetFileTimeFromMem(p + 0x38, &item.MTime);
memcpy(item.Hash, p + 0x40, kHashSize); memcpy(item.Hash, p + 0x40, kHashSize);
// UInt16 shortNameLen = Get16(p + 98); UInt32 shortNameLen = Get16(p + 98);
UInt16 fileNameLen = Get16(p + 100); UInt32 fileNameLen = Get16(p + 100);
if ((shortNameLen & 1) != 0 || (fileNameLen & 1) != 0)
size_t tempPos = pos + 102;
if (tempPos + fileNameLen > size)
return S_FALSE; return S_FALSE;
wchar_t *sz = item.Name.GetBuffer(prefix.Length() + fileNameLen / 2 + 1); UInt32 shortNameLen2 = (shortNameLen == 0 ? shortNameLen : shortNameLen + 2);
MyStringCopy(sz, (const wchar_t *)prefix); UInt32 fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2);
sz += prefix.Length();
for (UInt16 i = 0; i + 2 <= fileNameLen; i += 2) if (((kDirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7) > len)
*sz++ = Get16(base + tempPos + i); return S_FALSE;
*sz++ = '\0';
item.Name.ReleaseBuffer(); p += kDirRecordSize;
if (fileNameLen == 0 && item.isDir() && !item.HasStream())
RINOK(ReadName(p, fileNameLen, item.Name));
RINOK(ReadName(p + fileNameLen2, shortNameLen, item.ShortName));
if (parent < 0 && (shortNameLen || fileNameLen || !item.IsDir()))
SkipRoot = false;
/*
// there are some extra data for some files.
p -= kDirRecordSize;
p += ((kDirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7);
if (((kDirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7) != len)
p = p;
*/
/*
if (parent >= 0)
{ {
UString s = GetItemPath(parent) + L"\\" + item.Name;
printf("\n%s %8x %S", item.IsDir() ? "D" : " ", (int)subdirOffset, (const wchar_t *)s);
}
*/
if (fileNameLen == 0 && item.IsDir() && !item.HasStream())
item.Attrib = 0x10; // some swm archives have system/hidden attributes for root item.Attrib = 0x10; // some swm archives have system/hidden attributes for root
item.Name.Delete(item.Name.Length() - 1);
} item.Parent = parent;
items.Add(item); prevIndex = Items.Add(item);
pos += (size_t)length; if (item.IsDir() && subdirOffset != 0)
if (item.isDir() && (subdirOffset != 0))
{ {
if (subdirOffset >= size) RINOK(ParseDirItem((size_t)subdirOffset, prevIndex));
return S_FALSE;
RINOK(ParseDirItem(base, (size_t)subdirOffset, size, item.Name + WCHAR_PATH_SEPARATOR, items));
} }
Items[prevIndex].Order = Order++;
pos += (size_t)len;
} }
} }
static HRESULT ParseDir(const Byte *base, size_t size, HRESULT CDatabase::ParseImageDirs(const CByteBuffer &buf, int parent)
const UString &prefix, CObjectVector<CItem> &items)
{ {
DirData = buf;
DirSize = buf.GetCapacity();
size_t pos = 0; size_t pos = 0;
if (pos + 8 > size) if (DirSize < 8)
return S_FALSE; return S_FALSE;
const Byte *p = base + pos; const Byte *p = DirData;
UInt32 totalLength = Get32(p); UInt32 totalLength = Get32(p);
// UInt32 numEntries = Get32(p + 4); // UInt32 numEntries = Get32(p + 4);
pos += 8; pos += 8;
@@ -346,7 +488,7 @@ static HRESULT ParseDir(const Byte *base, size_t size,
UInt64 sum = 0; UInt64 sum = 0;
for (UInt32 i = 0; i < numEntries; i++) for (UInt32 i = 0; i < numEntries; i++)
{ {
if (pos + 8 > size) if (pos + 8 > DirSize)
return S_FALSE; return S_FALSE;
UInt64 len = Get64(p + pos); UInt64 len = Get64(p + pos);
entryLens.Add(len); entryLens.Add(len);
@@ -359,16 +501,124 @@ static HRESULT ParseDir(const Byte *base, size_t size,
if (pos != totalLength) if (pos != totalLength)
return S_FALSE; return S_FALSE;
*/ */
if (totalLength == 0)
pos = 8;
else if (totalLength < 8)
return S_FALSE;
else
pos = totalLength; pos = totalLength;
} }
return ParseDirItem(base, pos, size, prefix, items); DirStartOffset = DirProcessed = pos;
RINOK(ParseDirItem(pos, parent));
if (DirProcessed == DirSize)
return S_OK;
/* Original program writes additional 8 bytes (END_OF_ROOT_FOLDER), but
reference to that folder is empty */
if (DirProcessed == DirSize - 8 && DirProcessed - DirStartOffset == 112 &&
Get64(p + DirSize - 8) == 0)
return S_OK;
return S_FALSE;
} }
static int CompareHashRefs(const int *p1, const int *p2, void *param) HRESULT CHeader::Parse(const Byte *p)
{ {
const CRecordVector<CStreamInfo> &streams = *(const CRecordVector<CStreamInfo> *)param; UInt32 haderSize = Get32(p + 8);
return memcmp(streams[*p1].Hash, streams[*p2].Hash, kHashSize); if (haderSize < 0x74)
return S_FALSE;
Version = Get32(p + 0x0C);
Flags = Get32(p + 0x10);
if (!IsSupported())
return S_FALSE;
ChunkSize = Get32(p + 0x14);
if (ChunkSize != kChunkSize && ChunkSize != 0)
return S_FALSE;
memcpy(Guid, p + 0x18, 16);
PartNumber = Get16(p + 0x28);
NumParts = Get16(p + 0x2A);
int offset = 0x2C;
if (IsNewVersion())
{
NumImages = Get32(p + offset);
offset += 4;
} }
GetResource(p + offset, OffsetResource);
GetResource(p + offset + 0x18, XmlResource);
GetResource(p + offset + 0x30, MetadataResource);
if (IsNewVersion())
{
if (haderSize < 0xD0)
return S_FALSE;
BootIndex = Get32(p + 0x48);
IntegrityResource.Parse(p + offset + 0x4C);
}
return S_OK;
}
const Byte kSignature[kSignatureSize] = { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 };
HRESULT ReadHeader(IInStream *inStream, CHeader &h)
{
Byte p[kHeaderSizeMax];
RINOK(ReadStream_FALSE(inStream, p, kHeaderSizeMax));
if (memcmp(p, kSignature, kSignatureSize) != 0)
return S_FALSE;
return h.Parse(p);
}
static HRESULT ReadStreams(IInStream *inStream, const CHeader &h, CDatabase &db)
{
CByteBuffer offsetBuf;
RINOK(UnpackData(inStream, h.OffsetResource, h.IsLzxMode(), offsetBuf, NULL));
size_t i;
for (i = 0; offsetBuf.GetCapacity() - i >= kStreamInfoSize; i += kStreamInfoSize)
{
CStreamInfo s;
GetStream((const Byte *)offsetBuf + i, s);
if (s.PartNumber == h.PartNumber)
db.Streams.Add(s);
}
return (i == offsetBuf.GetCapacity()) ? S_OK : S_FALSE;
}
HRESULT CDatabase::Open(IInStream *inStream, const CHeader &h, CByteBuffer &xml, IArchiveOpenCallback *openCallback)
{
OpenCallback = openCallback;
RINOK(UnpackData(inStream, h.XmlResource, h.IsLzxMode(), xml, NULL));
RINOK(ReadStreams(inStream, h, *this));
bool needBootMetadata = !h.MetadataResource.IsEmpty();
Order = 0;
if (h.PartNumber == 1)
{
int imageIndex = 1;
for (int i = 0; i < Streams.Size(); i++)
{
// if (imageIndex > 1) break;
const CStreamInfo &si = Streams[i];
if (!si.Resource.IsMetadata() || si.PartNumber != h.PartNumber)
continue;
Byte hash[kHashSize];
CByteBuffer metadata;
RINOK(UnpackData(inStream, si.Resource, h.IsLzxMode(), metadata, hash));
if (memcmp(hash, si.Hash, kHashSize) != 0)
return S_FALSE;
NumImages++;
RINOK(ParseImageDirs(metadata, -(int)(++imageIndex)));
if (needBootMetadata)
if (h.MetadataResource.Offset == si.Resource.Offset)
needBootMetadata = false;
}
}
if (needBootMetadata)
{
CByteBuffer metadata;
RINOK(UnpackData(inStream, h.MetadataResource, h.IsLzxMode(), metadata, NULL));
RINOK(ParseImageDirs(metadata, -1));
NumImages++;
}
return S_OK;
}
static int CompareStreamsByPos(const CStreamInfo *p1, const CStreamInfo *p2, void * /* param */) static int CompareStreamsByPos(const CStreamInfo *p1, const CStreamInfo *p2, void * /* param */)
{ {
@@ -378,24 +628,14 @@ static int CompareStreamsByPos(const CStreamInfo *p1, const CStreamInfo *p2, voi
return MyCompare(p1->Resource.Offset, p2->Resource.Offset); return MyCompare(p1->Resource.Offset, p2->Resource.Offset);
} }
int CompareItems(void *const *a1, void *const *a2, void * /* param */) static int CompareHashRefs(const int *p1, const int *p2, void *param)
{ {
const CItem &i1 = **((const CItem **)a1); const CRecordVector<CStreamInfo> &streams = *(const CRecordVector<CStreamInfo> *)param;
const CItem &i2 = **((const CItem **)a2); return memcmp(streams[*p1].Hash, streams[*p2].Hash, kHashSize);
if (i1.isDir() != i2.isDir())
return (i1.isDir()) ? 1 : -1;
if (i1.isDir())
return -MyStringCompareNoCase(i1.Name, i2.Name);
int res = MyCompare(i1.StreamIndex, i2.StreamIndex);
if (res != 0)
return res;
return MyStringCompareNoCase(i1.Name, i2.Name);
} }
static int FindHash(const CRecordVector<CStreamInfo> &streams, static int FindHash(const CRecordVector<CStreamInfo> &streams,
const CRecordVector<int> &sortedByHash, const Byte *hash) const CIntVector &sortedByHash, const Byte *hash)
{ {
int left = 0, right = streams.Size(); int left = 0, right = streams.Size();
while (left != right) while (left != right)
@@ -417,153 +657,70 @@ static int FindHash(const CRecordVector<CStreamInfo> &streams,
return -1; return -1;
} }
HRESULT CHeader::Parse(const Byte *p) static int CompareItems(const int *a1, const int *a2, void *param)
{ {
UInt32 haderSize = Get32(p + 8); const CObjectVector<CItem> &items = ((CDatabase *)param)->Items;
if (haderSize < 0x74) const CItem &i1 = items[*a1];
return S_FALSE; const CItem &i2 = items[*a2];
Version = Get32(p + 0x0C);
Flags = Get32(p + 0x10); if (i1.IsDir() != i2.IsDir())
if (!IsSupported()) return i1.IsDir() ? 1 : -1;
return S_FALSE; int res = MyCompare(i1.StreamIndex, i2.StreamIndex);
UInt32 chunkSize = Get32(p + 0x14); if (res != 0)
if (chunkSize != kChunkSize && chunkSize != 0) return res;
return S_FALSE; return MyCompare(i1.Order, i2.Order);
memcpy(Guid, p + 0x18, 16);
PartNumber = Get16(p + 0x28);
NumParts = Get16(p + 0x2A);
int offset = 0x2C;
if (IsNewVersion())
{
NumImages = Get32(p + offset);
offset += 4;
}
GetResource(p + offset, OffsetResource);
GetResource(p + offset + 0x18, XmlResource);
GetResource(p + offset + 0x30, MetadataResource);
/*
if (IsNewVersion())
{
if (haderSize < 0xD0)
return S_FALSE;
IntegrityResource.Parse(p + offset + 0x4C);
BootIndex = Get32(p + 0x48);
}
*/
return S_OK;
} }
HRESULT ReadHeader(IInStream *inStream, CHeader &h) HRESULT CDatabase::Sort(bool skipRootDir)
{ {
const UInt32 kHeaderSizeMax = 0xD0; Streams.Sort(CompareStreamsByPos, NULL);
Byte p[kHeaderSizeMax];
RINOK(ReadStream_FALSE(inStream, p, kHeaderSizeMax));
if (memcmp(p, kSignature, kSignatureSize) != 0)
return S_FALSE;
return h.Parse(p);
}
HRESULT ReadStreams(IInStream *inStream, const CHeader &h, CDatabase &db)
{
CByteBuffer offsetBuf;
RINOK(UnpackData(inStream, h.OffsetResource, h.IsLzxMode(), offsetBuf, NULL));
for (size_t i = 0; i + kStreamInfoSize <= offsetBuf.GetCapacity(); i += kStreamInfoSize)
{
CStreamInfo s;
GetStream((const Byte *)offsetBuf + i, s);
if (s.PartNumber == h.PartNumber)
db.Streams.Add(s);
}
return S_OK;
}
HRESULT OpenArchive(IInStream *inStream, const CHeader &h, CByteBuffer &xml, CDatabase &db)
{
RINOK(UnpackData(inStream, h.XmlResource, h.IsLzxMode(), xml, NULL));
RINOK(ReadStreams(inStream, h, db));
bool needBootMetadata = !h.MetadataResource.IsEmpty();
if (h.PartNumber == 1)
{
int imageIndex = 1;
for (int j = 0; j < db.Streams.Size(); j++)
{
// if (imageIndex > 1) break;
const CStreamInfo &si = db.Streams[j];
if (!si.Resource.IsMetadata() || si.PartNumber != h.PartNumber)
continue;
Byte hash[kHashSize];
CByteBuffer metadata;
RINOK(UnpackData(inStream, si.Resource, h.IsLzxMode(), metadata, hash));
if (memcmp(hash, si.Hash, kHashSize) != 0)
return S_FALSE;
wchar_t sz[16];
ConvertUInt32ToString(imageIndex++, sz);
UString s = sz;
s += WCHAR_PATH_SEPARATOR;
RINOK(ParseDir(metadata, metadata.GetCapacity(), s, db.Items));
if (needBootMetadata)
if (h.MetadataResource.Offset == si.Resource.Offset)
needBootMetadata = false;
}
}
if (needBootMetadata)
{
CByteBuffer metadata;
RINOK(UnpackData(inStream, h.MetadataResource, h.IsLzxMode(), metadata, NULL));
RINOK(ParseDir(metadata, metadata.GetCapacity(), L"0" WSTRING_PATH_SEPARATOR, db.Items));
}
return S_OK;
}
HRESULT SortDatabase(CDatabase &db)
{
db.Streams.Sort(CompareStreamsByPos, NULL);
{ {
CRecordVector<int> sortedByHash; CIntVector sortedByHash;
{ {
for (int j = 0; j < db.Streams.Size(); j++) for (int i = 0; i < Streams.Size(); i++)
sortedByHash.Add(j); sortedByHash.Add(i);
sortedByHash.Sort(CompareHashRefs, &db.Streams); sortedByHash.Sort(CompareHashRefs, &Streams);
} }
for (int i = 0; i < db.Items.Size(); i++) for (int i = 0; i < Items.Size(); i++)
{ {
CItem &item = db.Items[i]; CItem &item = Items[i];
item.StreamIndex = -1; item.StreamIndex = -1;
if (item.HasStream()) if (item.HasStream())
item.StreamIndex = FindHash(db.Streams, sortedByHash, item.Hash); item.StreamIndex = FindHash(Streams, sortedByHash, item.Hash);
} }
} }
{ {
CRecordVector<bool> used; CRecordVector<bool> used;
int j; int i;
for (j = 0; j < db.Streams.Size(); j++) for (i = 0; i < Streams.Size(); i++)
{ {
const CStreamInfo &s = db.Streams[j]; const CStreamInfo &s = Streams[i];
used.Add(s.Resource.IsMetadata() && s.PartNumber == 1); used.Add(s.Resource.IsMetadata() && s.PartNumber == 1);
// used.Add(false);
} }
for (int i = 0; i < db.Items.Size(); i++) for (i = 0; i < Items.Size(); i++)
{ {
CItem &item = db.Items[i]; CItem &item = Items[i];
if (item.StreamIndex >= 0) if (item.StreamIndex >= 0)
used[item.StreamIndex] = true; used[item.StreamIndex] = true;
} }
for (j = 0; j < db.Streams.Size(); j++) for (i = 0; i < Streams.Size(); i++)
if (!used[j]) if (!used[i])
{ {
CItem item; CItem item;
item.StreamIndex = j; item.StreamIndex = i;
item.HasMetadata = false; item.HasMetadata = false;
db.Items.Add(item); Items.Add(item);
} }
} }
db.Items.Sort(CompareItems, NULL); SortedItems.Reserve(Items.Size());
for (int i = (skipRootDir ? 1 : 0); i < Items.Size(); i++)
SortedItems.Add(i);
SortedItems.Sort(CompareItems, this);
return S_OK; return S_OK;
} }

View File

@@ -9,6 +9,8 @@
#include "../../Compress/CopyCoder.h" #include "../../Compress/CopyCoder.h"
#include "../../Compress/LzxDecoder.h" #include "../../Compress/LzxDecoder.h"
#include "../IArchive.h"
namespace NArchive { namespace NArchive {
namespace NWim { namespace NWim {
@@ -56,7 +58,7 @@ public:
} }
}; };
const int kNumHuffmanBits = 16; const unsigned kNumHuffmanBits = 16;
const UInt32 kMatchMinLen = 3; const UInt32 kMatchMinLen = 3;
const UInt32 kNumLenSlots = 16; const UInt32 kNumLenSlots = 16;
const UInt32 kNumPosSlots = 16; const UInt32 kNumPosSlots = 16;
@@ -85,8 +87,10 @@ public:
namespace NResourceFlags namespace NResourceFlags
{ {
const Byte Compressed = 4; const Byte kFree = 1;
const Byte kMetadata = 2; const Byte kMetadata = 2;
const Byte Compressed = 4;
const Byte Spanned = 4;
} }
struct CResource struct CResource
@@ -96,9 +100,18 @@ struct CResource
UInt64 UnpackSize; UInt64 UnpackSize;
Byte Flags; Byte Flags;
void Clear()
{
PackSize = 0;
Offset = 0;
UnpackSize = 0;
Flags = 0;
}
void Parse(const Byte *p); void Parse(const Byte *p);
bool IsCompressed() const { return (Flags & NResourceFlags::Compressed) != 0; } void WriteTo(Byte *p) const;
bool IsFree() const { return (Flags & NResourceFlags::kFree) != 0; }
bool IsMetadata() const { return (Flags & NResourceFlags::kMetadata) != 0; } bool IsMetadata() const { return (Flags & NResourceFlags::kMetadata) != 0; }
bool IsCompressed() const { return (Flags & NResourceFlags::Compressed) != 0; }
bool IsEmpty() const { return (UnpackSize == 0); } bool IsEmpty() const { return (UnpackSize == 0); }
}; };
@@ -111,30 +124,37 @@ namespace NHeaderFlags
const UInt32 kLZX = 0x40000; const UInt32 kLZX = 0x40000;
} }
const UInt32 kWimVersion = 0x010D00;
const UInt32 kHeaderSizeMax = 0xD0;
const UInt32 kSignatureSize = 8;
extern const Byte kSignature[kSignatureSize];
const unsigned kChunkSizeBits = 15;
const UInt32 kChunkSize = (1 << kChunkSizeBits);
struct CHeader struct CHeader
{ {
UInt32 Flags;
UInt32 Version; UInt32 Version;
// UInt32 ChunkSize; UInt32 Flags;
UInt32 ChunkSize;
Byte Guid[16];
UInt16 PartNumber; UInt16 PartNumber;
UInt16 NumParts; UInt16 NumParts;
UInt32 NumImages; UInt32 NumImages;
Byte Guid[16];
CResource OffsetResource; CResource OffsetResource;
CResource XmlResource; CResource XmlResource;
CResource MetadataResource; CResource MetadataResource;
/*
CResource IntegrityResource; CResource IntegrityResource;
UInt32 BootIndex; UInt32 BootIndex;
*/
void SetDefaultFields(bool useLZX);
void WriteTo(Byte *p) const;
HRESULT Parse(const Byte *p); HRESULT Parse(const Byte *p);
bool IsCompressed() const { return (Flags & NHeaderFlags::kCompression) != 0; } bool IsCompressed() const { return (Flags & NHeaderFlags::kCompression) != 0; }
bool IsSupported() const { return (!IsCompressed() || (Flags & NHeaderFlags::kLZX) != 0 || (Flags & NHeaderFlags::kXPRESS) != 0 ) ; } bool IsSupported() const { return (!IsCompressed() || (Flags & NHeaderFlags::kLZX) != 0 || (Flags & NHeaderFlags::kXPRESS) != 0 ) ; }
bool IsLzxMode() const { return (Flags & NHeaderFlags::kLZX) != 0; } bool IsLzxMode() const { return (Flags & NHeaderFlags::kLZX) != 0; }
bool IsSpanned() const { return (!IsCompressed() || (Flags & NHeaderFlags::kSpanned) != 0); } bool IsSpanned() const { return (!IsCompressed() || (Flags & NHeaderFlags::kSpanned) != 0); }
bool IsNewVersion()const { return (Version > 0x010C00); } bool IsNewVersion()const { return (Version > 0x010C00); }
bool AreFromOnArchive(const CHeader &h) bool AreFromOnArchive(const CHeader &h)
@@ -152,11 +172,16 @@ struct CStreamInfo
UInt16 PartNumber; UInt16 PartNumber;
UInt32 RefCount; UInt32 RefCount;
BYTE Hash[kHashSize]; BYTE Hash[kHashSize];
void WriteTo(Byte *p) const;
}; };
const UInt32 kDirRecordSize = 102;
struct CItem struct CItem
{ {
UString Name; UString Name;
UString ShortName;
UInt32 Attrib; UInt32 Attrib;
// UInt32 SecurityId; // UInt32 SecurityId;
BYTE Hash[kHashSize]; BYTE Hash[kHashSize];
@@ -168,22 +193,39 @@ struct CItem
// UInt16 NumStreams; // UInt16 NumStreams;
// UInt16 ShortNameLen; // UInt16 ShortNameLen;
int StreamIndex; int StreamIndex;
int Parent;
unsigned Order;
bool HasMetadata; bool HasMetadata;
CItem(): HasMetadata(true), StreamIndex(-1) {} CItem(): HasMetadata(true), StreamIndex(-1) {}
bool isDir() const { return HasMetadata && ((Attrib & 0x10) != 0); } bool IsDir() const { return HasMetadata && ((Attrib & 0x10) != 0); }
bool HasStream() const bool HasStream() const
{ {
for (int i = 0; i < kHashSize; i++) for (unsigned i = 0; i < kHashSize; i++)
if (Hash[i] != 0) if (Hash[i] != 0)
return true; return true;
return false; return false;
} }
}; };
struct CDatabase class CDatabase
{ {
const Byte *DirData;
size_t DirSize;
size_t DirProcessed;
size_t DirStartOffset;
int Order;
IArchiveOpenCallback *OpenCallback;
HRESULT ParseDirItem(size_t pos, int parent);
HRESULT ParseImageDirs(const CByteBuffer &buf, int parent);
public:
CRecordVector<CStreamInfo> Streams; CRecordVector<CStreamInfo> Streams;
CObjectVector<CItem> Items; CObjectVector<CItem> Items;
CIntVector SortedItems;
int NumImages;
bool SkipRoot;
bool ShowImageNumber;
UInt64 GetUnpackSize() const UInt64 GetUnpackSize() const
{ {
@@ -205,12 +247,26 @@ struct CDatabase
{ {
Streams.Clear(); Streams.Clear();
Items.Clear(); Items.Clear();
SortedItems.Clear();
NumImages = 0;
SkipRoot = true;
ShowImageNumber = true;
} }
UString GetItemPath(int index) const;
HRESULT Open(IInStream *inStream, const CHeader &h, CByteBuffer &xml, IArchiveOpenCallback *openCallback);
void DetectPathMode()
{
ShowImageNumber = (NumImages != 1);
}
HRESULT Sort(bool skipRootDir);
}; };
HRESULT ReadHeader(IInStream *inStream, CHeader &header); HRESULT ReadHeader(IInStream *inStream, CHeader &header);
HRESULT OpenArchive(IInStream *inStream, const CHeader &header, CByteBuffer &xml, CDatabase &database);
HRESULT SortDatabase(CDatabase &database);
class CUnpacker class CUnpacker
{ {

View File

@@ -6,8 +6,13 @@
#include "WimHandler.h" #include "WimHandler.h"
static IInArchive *CreateArc() { return new NArchive::NWim::CHandler; } static IInArchive *CreateArc() { return new NArchive::NWim::CHandler; }
#ifndef EXTRACT_ONLY
static IOutArchive *CreateArcOut() { return new NArchive::NWim::COutHandler; }
#else
#define CreateArcOut 0
#endif
static CArcInfo g_ArcInfo = static CArcInfo g_ArcInfo =
{ L"Wim", L"wim swm", 0, 0xE6, { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 }, 8, false, CreateArc, 0 }; { L"wim", L"wim swm", 0, 0xE6, { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 }, 8, false, CreateArc, CreateArcOut };
REGISTER_ARC(Wim) REGISTER_ARC(Wim)

View File

@@ -63,8 +63,8 @@ private:
Byte m_AesKeyMode; Byte m_AesKeyMode;
bool m_WriteNtfsTimeExtra; bool m_WriteNtfsTimeExtra;
bool m_ForseLocal; bool m_ForceLocal;
bool m_ForseUtf8; bool m_ForceUtf8;
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
UInt32 _numThreads; UInt32 _numThreads;
@@ -88,8 +88,8 @@ private:
m_IsAesMode = false; m_IsAesMode = false;
m_AesKeyMode = 3; // aes-256 m_AesKeyMode = 3; // aes-256
m_WriteNtfsTimeExtra = true; m_WriteNtfsTimeExtra = true;
m_ForseLocal = false; m_ForceLocal = false;
m_ForseUtf8 = false; m_ForceUtf8 = false;
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
_numThreads = NWindows::NSystem::GetNumberOfProcessors();; _numThreads = NWindows::NSystem::GetNumberOfProcessors();;
#endif #endif

View File

@@ -189,11 +189,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
name += kSlash; name += kSlash;
bool tryUtf8 = true; bool tryUtf8 = true;
if (m_ForseLocal || !m_ForseUtf8) if (m_ForceLocal || !m_ForceUtf8)
{ {
bool defaultCharWasUsed; bool defaultCharWasUsed;
ui.Name = UnicodeStringToMultiByte(name, CP_OEMCP, '_', defaultCharWasUsed); ui.Name = UnicodeStringToMultiByte(name, CP_OEMCP, '_', defaultCharWasUsed);
tryUtf8 = (!m_ForseLocal && (defaultCharWasUsed || tryUtf8 = (!m_ForceLocal && (defaultCharWasUsed ||
MultiByteToUnicodeString(ui.Name, CP_OEMCP) != name)); MultiByteToUnicodeString(ui.Name, CP_OEMCP) != name));
} }
@@ -512,15 +512,15 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
} }
else if (name.CompareNoCase(L"CL") == 0) else if (name.CompareNoCase(L"CL") == 0)
{ {
RINOK(SetBoolProperty(m_ForseLocal, prop)); RINOK(SetBoolProperty(m_ForceLocal, prop));
if (m_ForseLocal) if (m_ForceLocal)
m_ForseUtf8 = false; m_ForceUtf8 = false;
} }
else if (name.CompareNoCase(L"CU") == 0) else if (name.CompareNoCase(L"CU") == 0)
{ {
RINOK(SetBoolProperty(m_ForseUtf8, prop)); RINOK(SetBoolProperty(m_ForceUtf8, prop));
if (m_ForseUtf8) if (m_ForceUtf8)
m_ForseLocal = false; m_ForceLocal = false;
} }
else else
return E_INVALIDARG; return E_INVALIDARG;

View File

@@ -97,7 +97,6 @@ AR_OBJS = \
$O\DeflateProps.obj \ $O\DeflateProps.obj \
$O\GzHandler.obj \ $O\GzHandler.obj \
$O\LzmaHandler.obj \ $O\LzmaHandler.obj \
$O\PpmdHandler.obj \
$O\SplitHandler.obj \ $O\SplitHandler.obj \
$O\XzHandler.obj \ $O\XzHandler.obj \
$O\ZHandler.obj \ $O\ZHandler.obj \

View File

@@ -322,6 +322,7 @@ UDF_OBJS = \
WIM_OBJS = \ WIM_OBJS = \
$O\WimHandler.obj \ $O\WimHandler.obj \
$O\WimHandlerOut.obj \
$O\WimIn.obj \ $O\WimIn.obj \
$O\WimRegister.obj \ $O\WimRegister.obj \

View File

@@ -2229,6 +2229,10 @@ SOURCE=..\..\Archive\Wim\WimHandler.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\Archive\Wim\WimHandlerOut.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Wim\WimIn.cpp SOURCE=..\..\Archive\Wim\WimIn.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@@ -173,6 +173,7 @@ UDF_OBJS = \
WIM_OBJS = \ WIM_OBJS = \
$O\WimHandler.obj \ $O\WimHandler.obj \
$O\WimHandlerOut.obj \
$O\WimIn.obj \ $O\WimIn.obj \
$O\WimRegister.obj \ $O\WimRegister.obj \

View File

@@ -1,8 +1,8 @@
#define MY_VER_MAJOR 9 #define MY_VER_MAJOR 9
#define MY_VER_MINOR 13 #define MY_VER_MINOR 14
#define MY_VER_BUILD 0 #define MY_VER_BUILD 0
#define MY_VERSION "9.13 beta" #define MY_VERSION "9.14 beta"
#define MY_7ZIP_VERSION "7-Zip 9.13 beta" #define MY_7ZIP_VERSION "7-Zip 9.14 beta"
#define MY_DATE "2010-04-15" #define MY_DATE "2010-06-04"
#define MY_COPYRIGHT "Copyright (c) 1999-2010 Igor Pavlov" #define MY_COPYRIGHT "Copyright (c) 1999-2010 Igor Pavlov"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE

View File

@@ -24,6 +24,27 @@ void ConvertUInt32ToHex(UInt32 value, wchar_t *s)
s[8] = L'\0'; s[8] = L'\0';
} }
static const char g_WinAttrib[17] = "RHS8DAdNTsrCOnE_";
/*
0 READONLY
1 HIDDEN
3 SYSTEM
4 DIRECTORY
5 ARCHIVE
6 DEVICE
7 NORMAL
8 TEMPORARY
9 SPARSE_FILE
10 REPARSE_POINT
11 COMPRESSED
12 OFFLINE
13 NOT_CONTENT_INDEXED
14 ENCRYPTED
16 VIRTUAL
*/
#define MY_ATTR_CHAR(a, n, c) ((a )& (1 << (n))) ? c : L'-'; #define MY_ATTR_CHAR(a, n, c) ((a )& (1 << (n))) ? c : L'-';
UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool full) UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool full)
@@ -55,16 +76,14 @@ UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool ful
{ {
if (prop.vt != VT_UI4) if (prop.vt != VT_UI4)
break; break;
UString res;
UInt32 a = prop.ulVal; UInt32 a = prop.ulVal;
if (NFile::NFind::NAttributes::IsReadOnly(a)) res += L'R'; wchar_t sz[32];
if (NFile::NFind::NAttributes::IsHidden(a)) res += L'H'; int pos = 0;
if (NFile::NFind::NAttributes::IsSystem(a)) res += L'S'; for (int i = 0; i < 16; i++)
if (NFile::NFind::NAttributes::IsDir(a)) res += L'D'; if (a & (1 << i) && i != 7)
if (NFile::NFind::NAttributes::IsArchived(a)) res += L'A'; sz[pos++] = g_WinAttrib[i];
if (NFile::NFind::NAttributes::IsCompressed(a)) res += L'C'; sz[pos] = '\0';
if (NFile::NFind::NAttributes::IsEncrypted(a)) res += L'E'; return sz;
return res;
} }
case kpidPosixAttrib: case kpidPosixAttrib:
{ {

View File

@@ -26,6 +26,7 @@ NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream)
for (;;) for (;;)
{ {
(*outStream) << kHelpQuestionMessage; (*outStream) << kHelpQuestionMessage;
outStream->Flush();
AString scannedString = g_StdIn.ScanStringUntilNewLine(); AString scannedString = g_StdIn.ScanStringUntilNewLine();
scannedString.Trim(); scannedString.Trim();
if (!scannedString.IsEmpty()) if (!scannedString.IsEmpty())

View File

@@ -163,40 +163,51 @@ HRESULT CPanel::OpenParentArchiveFolder()
return S_OK; return S_OK;
} }
static const wchar_t *kStartExtensions[] = static const char *kStartExtensions =
{
#ifdef UNDER_CE #ifdef UNDER_CE
L"cab", " cab"
#endif #endif
L"exe", L"bat", L"com", " exe bat com"
L"chm", " chm"
L"msi", L"doc", L"xls", L"ppt", L"pps", L"wps", L"wpt", L"wks", L"xlr", L"wdb", " msi doc xls ppt pps wps wpt wks xlr wdb"
L"docx", L"docm", L"dotx", L"dotm", L"xlsx", L"xlsm", L"xltx", L"xltm", L"xlsb", " docx docm dotx dotm xlsx xlsm xltx xltm xlsb"
L"xlam", L"pptx", L"pptm", L"potx", L"potm", L"ppam", L"ppsx", L"ppsm", L"xsn", " xlam pptx pptm potx potm ppam ppsx ppsm xsn"
L"msg", " mpp"
L"dwf", " msg"
" dwf"
L"flv", L"swf", " flv swf"
L"odt", L"ods", " odt ods"
L"wb3", " wb3"
L"pdf" " pdf"
}; " ";
static bool DoItemAlwaysStart(const UString &name) static bool FindExt(const char *p, const UString &name)
{ {
int extPos = name.ReverseFind('.'); int extPos = name.ReverseFind('.');
if (extPos < 0) if (extPos < 0)
return false; return false;
UString ext = name.Mid(extPos + 1); UString ext = name.Mid(extPos + 1);
ext.MakeLower(); ext.MakeLower();
for (int i = 0; i < sizeof(kStartExtensions) / sizeof(kStartExtensions[0]); i++) AString ext2 = UnicodeStringToMultiByte(ext);
if (ext.Compare(kStartExtensions[i]) == 0) for (int i = 0; p[i] != 0;)
{
int j;
for (j = i; p[j] != ' '; j++);
if (ext2.Length() == j - i && memcmp(p + i, (const char *)ext2, ext2.Length()) == 0)
return true; return true;
i = j + 1;
}
return false; return false;
} }
static bool DoItemAlwaysStart(const UString &name)
{
return FindExt(kStartExtensions, name);
}
static UString GetQuotedString(const UString &s) static UString GetQuotedString(const UString &s)
{ {
return UString(L'\"') + s + UString(L'\"'); return UString(L'\"') + s + UString(L'\"');

View File

@@ -229,6 +229,12 @@ static const CFormatInfo g_Formats[] =
(1 << 0), (1 << 0),
0, 0, 0, 0,
false, false, false, false, false, false false, false, false, false, false, false
},
{
L"wim",
(1 << 0),
0, 0,
false, false, false, false, false, false
} }
}; };
@@ -1032,7 +1038,7 @@ void CCompressDialog::SetDictionary()
if (i == 20 && j > 0) if (i == 20 && j > 0)
continue; continue;
UInt32 dictionary = (1 << i) + (j << (i - 1)); UInt32 dictionary = (1 << i) + (j << (i - 1));
if (dictionary >= (1 << 31)) if (dictionary > (1 << 30))
continue; continue;
AddDictionarySize(dictionary); AddDictionarySize(dictionary);
UInt64 decomprSize; UInt64 decomprSize;

View File

@@ -10,8 +10,8 @@ AppName = "7-Zip"
InstallDir = %CE1%\%AppName% InstallDir = %CE1%\%AppName%
[Strings] [Strings]
AppVer = "9.13" AppVer = "9.14"
AppDate = "2010-04-15" AppDate = "2010-06-04"
[CEDevice] [CEDevice]
; ProcessorType = 2577 ; ARM ; ProcessorType = 2577 ; ARM

View File

@@ -2,7 +2,7 @@
;Defines ;Defines
!define VERSION_MAJOR 9 !define VERSION_MAJOR 9
!define VERSION_MINOR 13 !define VERSION_MINOR 14
!define VERSION_POSTFIX_FULL " beta" !define VERSION_POSTFIX_FULL " beta"
!ifdef WIN64 !ifdef WIN64
!ifdef IA64 !ifdef IA64

View File

@@ -1,7 +1,7 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<?define VerMajor = "9" ?> <?define VerMajor = "9" ?>
<?define VerMinor = "13" ?> <?define VerMinor = "14" ?>
<?define VerBuild = "00" ?> <?define VerBuild = "00" ?>
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?> <?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
<?define MmHex = "0$(var.VerMajor)$(var.VerMinor)" ?> <?define MmHex = "0$(var.VerMajor)$(var.VerMinor)" ?>

View File

@@ -1,4 +1,4 @@
LZMA SDK 9.12 LZMA SDK 9.14
------------- -------------
LZMA SDK provides the documentation, samples, header files, libraries, LZMA SDK provides the documentation, samples, header files, libraries,
@@ -20,7 +20,7 @@ LICENSE
LZMA SDK is written and placed in the public domain by Igor Pavlov. LZMA SDK is written and placed in the public domain by Igor Pavlov.
Some code in LZMA is based on public domain code from another developers: Some code in LZMA SDK is based on public domain code from another developers:
1) PPMd var.H (2001): Dmitry Shkarin 1) PPMd var.H (2001): Dmitry Shkarin
2) SHA-256: Wei Dai (Crypto++ library) 2) SHA-256: Wei Dai (Crypto++ library)