Compare commits

...

4 Commits
9.11 ... 9.15

Author SHA1 Message Date
Igor Pavlov
e279500d76 9.15 2016-05-28 00:16:03 +01:00
Igor Pavlov
708873490e 9.14 2016-05-28 00:16:03 +01:00
Igor Pavlov
3dacb5eb8a 9.13 2016-05-28 00:16:03 +01:00
Igor Pavlov
76b173af78 9.12 2016-05-28 00:16:02 +01:00
121 changed files with 2576 additions and 1467 deletions

View File

@@ -1,7 +1,7 @@
#define MY_VER_MAJOR 9
#define MY_VER_MINOR 11
#define MY_VER_MINOR 15
#define MY_VER_BUILD 0
#define MY_VERSION "9.11 beta"
#define MY_DATE "2010-03-15"
#define MY_VERSION "9.15 beta"
#define MY_DATE "2010-06-20"
#define MY_COPYRIGHT ": Igor Pavlov : Public domain"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE

View File

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

View File

@@ -1,5 +1,5 @@
/* CpuArch.h -- CPU specific code
2010-03-11: Igor Pavlov : Public domain */
2010-05-20: Igor Pavlov : Public domain */
#ifndef __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 SetUi16(p, d) *(UInt16 *)(p) = (d);
#define SetUi32(p, d) *(UInt32 *)(p) = (d);
#define SetUi64(p, d) *(UInt64 *)(p) = (d);
#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))[3] = (Byte)(_x_ >> 24); }
#define SetUi64(p, d) { UInt64 _x64_ = (d); \
SetUi32(p, (UInt32)_x64_); \
SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); }
#endif
#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)

View File

@@ -1,5 +1,5 @@
/* Lzma2Enc.c -- LZMA2 Encoder
2009-11-24 : Igor Pavlov : Public domain */
2010-04-16 : Igor Pavlov : Public domain */
/* #include <stdio.h> */
#include <string.h>
@@ -141,7 +141,7 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
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;
outBuf[destPos++] = (Byte)(pm >> 8);
@@ -173,6 +173,65 @@ void Lzma2EncProps_Init(CLzma2EncProps *p)
p->blockSize = 0;
}
void Lzma2EncProps_Normalize(CLzma2EncProps *p)
{
int t1, t1n, t2, t3;
{
CLzmaEncProps lzmaProps = p->lzmaProps;
LzmaEncProps_Normalize(&lzmaProps);
t1n = lzmaProps.numThreads;
}
t1 = p->lzmaProps.numThreads;
t2 = p->numBlockThreads;
t3 = p->numTotalThreads;
if (t2 > NUM_MT_CODER_THREADS_MAX)
t2 = NUM_MT_CODER_THREADS_MAX;
if (t3 <= 0)
{
if (t2 <= 0)
t2 = 1;
t3 = t1n * t2;
}
else if (t2 <= 0)
{
t2 = t3 / t1n;
if (t2 == 0)
{
t1 = 1;
t2 = t3;
}
if (t2 > NUM_MT_CODER_THREADS_MAX)
t2 = NUM_MT_CODER_THREADS_MAX;
}
else if (t1 <= 0)
{
t1 = t3 / t2;
if (t1 == 0)
t1 = 1;
}
else
t3 = t1n * t2;
p->lzmaProps.numThreads = t1;
p->numBlockThreads = t2;
p->numTotalThreads = t3;
LzmaEncProps_Normalize(&p->lzmaProps);
if (p->blockSize == 0)
{
UInt32 dictSize = p->lzmaProps.dictSize;
UInt64 blockSize = (UInt64)dictSize << 2;
const UInt32 kMinSize = (UInt32)1 << 20;
const UInt32 kMaxSize = (UInt32)1 << 28;
if (blockSize < kMinSize) blockSize = kMinSize;
if (blockSize > kMaxSize) blockSize = kMaxSize;
if (blockSize < dictSize) blockSize = dictSize;
p->blockSize = (size_t)blockSize;
}
}
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
{
@@ -181,9 +240,7 @@ static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
/* ---------- Lzma2 ---------- */
extern struct _CLzma2Enc;
typedef struct _CLzma2Enc
typedef struct
{
Byte propEncoded;
CLzma2EncProps props;
@@ -351,70 +408,6 @@ void Lzma2Enc_Destroy(CLzma2EncHandle pp)
IAlloc_Free(p->alloc, pp);
}
void Lzma2EncProps_Normalize(CLzma2EncProps *p)
{
int t1, t1n, t2, t3;
CLzmaEncProps lzmaProps = p->lzmaProps;
LzmaEncProps_Normalize(&lzmaProps);
t1 = p->lzmaProps.numThreads;
t1n = lzmaProps.numThreads;
t2 = p->numBlockThreads;
t3 = p->numTotalThreads;
#ifndef _7ZIP_ST
if (t2 > NUM_MT_CODER_THREADS_MAX)
t2 = NUM_MT_CODER_THREADS_MAX;
#else
t2 = 1;
#endif
if (t3 <= 0)
{
if (t2 <= 0)
t2 = 1;
t3 = t1n * t2;
}
else
{
if (t2 <= 0)
{
t2 = t3 / t1n;
if (t2 == 0)
{
t1 = 1;
t2 = t3;
}
}
else if (t1 <= 0)
{
t1 = t3 / t2;
if (t1 == 0)
t1 = 1;
}
else
t3 = t1n * t2;
}
p->lzmaProps.numThreads = t1;
p->numBlockThreads = t2;
p->numTotalThreads = t3;
LzmaEncProps_Normalize(&p->lzmaProps);
if (p->blockSize == 0)
{
UInt64 blockSize = (UInt64)lzmaProps.dictSize << 2;
const UInt32 kMinSize = (UInt32)1 << 20;
const UInt32 kMaxSize = (UInt32)1 << 28;
if (blockSize < kMinSize) blockSize = kMinSize;
if (blockSize > kMaxSize) blockSize = kMaxSize;
if (blockSize < lzmaProps.dictSize)
blockSize = lzmaProps.dictSize;
p->blockSize = (size_t)blockSize;
}
}
SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props)
{
CLzma2Enc *p = (CLzma2Enc *)pp;

View File

@@ -1,5 +1,5 @@
/* LzmaEnc.c -- LZMA Encoder
2009-11-24 : Igor Pavlov : Public domain */
2010-04-16 : Igor Pavlov : Public domain */
#include <string.h>
@@ -395,7 +395,7 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
LzmaEncProps_Normalize(&props);
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;
p->dictSize = props.dictSize;
p->matchFinderCycles = props.mc;

View File

@@ -1,5 +1,5 @@
/* MtCoder.c -- Multi-thread Coder
2009-03-26 : Igor Pavlov : Public domain */
2010-03-24 : Igor Pavlov : Public domain */
#include <stdio.h>
@@ -306,7 +306,7 @@ SRes MtCoder_Code(CMtCoder *p)
for (i = 0; i < numThreads; i++)
{
CMtThread *t = &p->threads[i];
if (LoopThread_StartSubThread(&t->thread) != SZ_OK || i == 10)
if (LoopThread_StartSubThread(&t->thread) != SZ_OK)
{
res = SZ_ERROR_THREAD;
p->threads[0].stopReading = True;

View File

@@ -1,5 +1,5 @@
/* Ppmd8.c -- PPMdI codec
2010-03-15 : Igor Pavlov : Public domain
2010-03-24 : Igor Pavlov : Public domain
This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */
#include <memory.h>
@@ -410,6 +410,10 @@ static void Refresh(CPpmd8 *p, CTX_PTR ctx, unsigned oldNU, unsigned scale)
unsigned i = ctx->NumStats, escFreq, sumFreq, flags;
CPpmd_State *s = (CPpmd_State *)ShrinkUnits(p, STATS(ctx), oldNU, (i + 2) >> 1);
ctx->Stats = REF(s);
#ifdef PPMD8_FREEZE_SUPPORT
/* fixed over Shkarin's code. Fixed code is not compatible with original code for some files in FREEZE mode. */
scale |= (ctx->SummFreq >= ((UInt32)1 << 15));
#endif
flags = (ctx->Flags & (0x10 + 0x04 * scale)) + 0x08 * (s->Symbol >= 0x40);
escFreq = ctx->SummFreq - s->Freq;
sumFreq = (s->Freq = (Byte)((s->Freq + scale) >> scale));

View File

@@ -1,5 +1,5 @@
/* Ppmd8.h -- PPMdI codec
2010-03-12 : Igor Pavlov : Public domain
2010-03-24 : Igor Pavlov : Public domain
This code is based on:
PPMd var.I (2002): Dmitry Shkarin : Public domain
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
@@ -35,8 +35,9 @@ typedef struct CPpmd8_Context_
#define Ppmd8Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)
/* There is some bug in FREEZE mode (including original code,
so we disable FREEZE mode support */
/* The BUG in Shkarin's code for FREEZE mode was fixed, but that fixed
code is not compatible with original code for some files compressed
in FREEZE mode. So we disable FREEZE mode support. */
enum
{

View File

@@ -1,5 +1,5 @@
/* Ppmd8Dec.c -- PPMdI Decoder
2010-03-12 : Igor Pavlov : Public domain
2010-04-16 : Igor Pavlov : Public domain
This code is based on:
PPMd var.I (2002): Dmitry Shkarin : 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;
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->Range <<= 8;

View File

@@ -1,5 +1,5 @@
/* Ppmd8Enc.c -- PPMdI Encoder
2010-03-12 : Igor Pavlov : Public domain
2010-04-16 : Igor Pavlov : Public domain
This code is based on:
PPMd var.I (2002): Dmitry Shkarin : 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)
{
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->Range <<= 8;

View File

@@ -1,9 +1,9 @@
/* Crypto/Sha256.c -- SHA-256 Hash function
2008-11-06 : Igor Pavlov : Public domain
/* Crypto/Sha256.c -- SHA-256 Hash
2010-06-11 : Igor Pavlov : Public domain
This code is based on public domain code from Wei Dai's Crypto++ library. */
#include "Sha256.h"
#include "RotateDefs.h"
#include "Sha256.h"
/* define it for speed optimization */
/* #define _SHA256_UNROLL */
@@ -71,7 +71,7 @@ void Sha256_Init(CSha256 *p)
#endif
const UInt32 K[64] = {
static const UInt32 K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,

View File

@@ -1,14 +1,12 @@
/* Sha256.h -- SHA-256 Hash
2009-02-07 : Igor Pavlov : Public domain */
2010-06-11 : Igor Pavlov : Public domain */
#ifndef __CRYPTO_SHA256_H
#define __CRYPTO_SHA256_H
#include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
EXTERN_C_BEGIN
#define SHA256_DIGEST_SIZE 32
@@ -23,8 +21,6 @@ void Sha256_Init(CSha256 *p);
void Sha256_Update(CSha256 *p, const Byte *data, size_t size);
void Sha256_Final(CSha256 *p, Byte *digest);
#ifdef __cplusplus
}
#endif
EXTERN_C_END
#endif

View File

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

View File

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

View File

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

View File

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

View File

@@ -232,7 +232,7 @@ HRESULT CDecoder::Decode(
size_t size = props.GetCapacity();
if (size > 0xFFFFFFFF)
return E_NOTIMPL;
if (size > 0)
// if (size > 0)
{
RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size));
}

View File

@@ -2,15 +2,14 @@
#include "StdAfx.h"
#include "7zHandler.h"
#include "7zFolderOutStream.h"
#include "../../../Common/ComTry.h"
#include "../../Common/ProgressUtils.h"
#include "7zDecode.h"
// #include "7z1Decode.h"
#include "../../../Common/ComTry.h"
#include "../../Common/StreamObjects.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/LimitedStreams.h"
#include "7zFolderOutStream.h"
#include "7zHandler.h"
namespace NArchive {
namespace N7z {
@@ -73,13 +72,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
*/
CObjectVector<CExtractFolderInfo> extractFolderInfoVector;
for(UInt32 ii = 0; ii < numItems; ii++)
for (UInt32 ii = 0; ii < numItems; ii++)
{
// UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex];
UInt32 ref2Index = allFilesMode ? ii : indices[ii];
// const CRef2 &ref2 = _refs[ref2Index];
// for(UInt32 ri = 0; ri < ref2.Refs.Size(); ri++)
// for (UInt32 ri = 0; ri < ref2.Refs.Size(); ri++)
{
#ifdef _7Z_VOL
// const CRef &ref = ref2.Refs[ri];
@@ -138,7 +137,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
}
extractCallback->SetTotal(importantTotalUnpacked);
RINOK(extractCallback->SetTotal(importantTotalUnpacked));
CDecoder decoder(
#ifdef _ST_MODE
@@ -149,27 +148,26 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
);
// CDecoder1 decoder;
UInt64 currentTotalPacked = 0;
UInt64 currentTotalUnpacked = 0;
UInt64 totalFolderUnpacked;
UInt64 totalFolderPacked;
UInt64 totalPacked = 0;
UInt64 totalUnpacked = 0;
UInt64 curPacked, curUnpacked;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false);
for(int i = 0; i < extractFolderInfoVector.Size(); i++,
currentTotalUnpacked += totalFolderUnpacked,
currentTotalPacked += totalFolderPacked)
for (int i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked)
{
lps->OutSize = currentTotalUnpacked;
lps->InSize = currentTotalPacked;
lps->OutSize = totalUnpacked;
lps->InSize = totalPacked;
RINOK(lps->SetCur());
const CExtractFolderInfo &efi = extractFolderInfoVector[i];
totalFolderUnpacked = efi.UnpackSize;
if (i >= extractFolderInfoVector.Size())
break;
totalFolderPacked = 0;
const CExtractFolderInfo &efi = extractFolderInfoVector[i];
curUnpacked = efi.UnpackSize;
curPacked = 0;
CFolderOutStream *folderOutStream = new CFolderOutStream;
CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
@@ -187,7 +185,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
else
startIndex = db.FolderStartFileIndex[efi.FolderIndex];
HRESULT result = folderOutStream->Init(&db,
#ifdef _7Z_VOL
volume.StartRef2Index,
@@ -205,7 +202,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CNum folderIndex = efi.FolderIndex;
const CFolder &folderInfo = db.Folders[folderIndex];
totalFolderPacked = _db.GetFolderFullPackSize(folderIndex);
curPacked = _db.GetFolderFullPackSize(folderIndex);
CNum packStreamIndex = db.FolderStartPackStreamIndex[folderIndex];
UInt64 folderStartPackPos = db.GetFolderStreamPos(folderIndex, 0);

View File

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

View File

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

View File

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

View File

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

View File

@@ -382,6 +382,12 @@ static void MakeExeMethod(const CCompressionMethodMode &method,
prop.Value = kNumFastBytesForBCJ2_LZMA;
methodFull.Props.Add(prop);
}
{
CProp prop;
prop.Id = NCoderPropID::kNumThreads;
prop.Value = (UInt32)1;
methodFull.Props.Add(prop);
}
exeMethod.Methods.Add(methodFull);
exeMethod.Methods.Add(methodFull);

View File

@@ -85,6 +85,7 @@ STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject)
STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
if (formatIndex >= g_NumArcs)
return E_INVALIDARG;
const CArcInfo &arc = *g_Arcs[formatIndex];
@@ -119,6 +120,7 @@ STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
#include "../../../../C/Alloc.h"
#include "Common/Buffer.h"
#include "Common/ComTry.h"
#include "Common/Defs.h"
@@ -32,8 +34,6 @@ namespace NCab {
// #define _CAB_DETAILS
static const UInt32 kMaxTempBufSize = 1 << 20;
#ifdef _CAB_DETAILS
enum
{
@@ -41,7 +41,7 @@ enum
};
#endif
STATPROPSTG kProps[] =
static STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidSize, VT_UI8},
@@ -57,18 +57,18 @@ STATPROPSTG kProps[] =
#endif
};
static const wchar_t *kMethods[] =
static const char *kMethods[] =
{
L"None",
L"MSZip",
L"Quantum",
L"LZX"
"None",
"MSZip",
"Quantum",
"LZX"
};
static const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]);
static const wchar_t *kUnknownMethod = L"Unknown";
static const char *kUnknownMethod = "Unknown";
STATPROPSTG kArcProps[] =
static STATPROPSTG kArcProps[] =
{
{ NULL, kpidMethod, VT_BSTR},
// { NULL, kpidSolid, VT_BOOL},
@@ -87,7 +87,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
case kpidMethod:
{
UString resString;
AString resString;
CRecordVector<Byte> ids;
int i;
for (int v = 0; v < m_Database.Volumes.Size(); v++)
@@ -99,9 +99,9 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
for (i = 0; i < ids.Size(); i++)
{
Byte id = ids[i];
UString method = (id < kNumMethods) ? kMethods[id] : kUnknownMethod;
AString method = (id < kNumMethods) ? kMethods[id] : kUnknownMethod;
if (!resString.IsEmpty())
resString += L' ';
resString += ' ';
resString += method;
}
prop = resString;
@@ -171,12 +171,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
UInt32 realFolderIndex = item.GetFolderIndex(db.Folders.Size());
const CFolder &folder = db.Folders[realFolderIndex];
int methodIndex = folder.GetCompressionMethod();
UString method = (methodIndex < kNumMethods) ? kMethods[methodIndex] : kUnknownMethod;
AString method = (methodIndex < kNumMethods) ? kMethods[methodIndex] : kUnknownMethod;
if (methodIndex == NHeader::NCompressionMethodMajor::kLZX ||
methodIndex == NHeader::NCompressionMethodMajor::kQuantum)
{
method += L":";
wchar_t temp[32];
method += ':';
char temp[32];
ConvertUInt64ToString(folder.CompressionTypeMinor, temp);
method += temp;
}
@@ -344,9 +344,10 @@ private:
const CMvDatabaseEx *m_Database;
const CRecordVector<bool> *m_ExtractStatuses;
CByteBuffer TempBuf;
Byte *TempBuf;
UInt32 TempBufSize;
int NumIdenticalFiles;
bool TempBufMode;
bool IsSupported;
UInt32 m_BufStartFolderOffset;
int m_StartIndex;
@@ -362,12 +363,21 @@ private:
UInt64 m_FolderSize;
UInt64 m_PosInFolder;
void FreeTempBuf()
{
::MyFree(TempBuf);
TempBuf = NULL;
}
HRESULT OpenFile();
HRESULT CloseFileWithResOp(Int32 resOp);
HRESULT CloseFile();
HRESULT Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK);
public:
HRESULT WriteEmptyFiles();
CFolderOutStream(): TempBuf(NULL) {}
~CFolderOutStream() { FreeTempBuf(); }
void Init(
const CMvDatabaseEx *database,
const CRecordVector<bool> *extractStatuses,
@@ -403,32 +413,33 @@ void CFolderOutStream::Init(
m_FileIsOpen = false;
m_IsOk = true;
TempBufMode = false;
NumIdenticalFiles = 0;
}
HRESULT CFolderOutStream::CloseFileWithResOp(Int32 resOp)
{
m_RealOutStream.Release();
m_FileIsOpen = false;
NumIdenticalFiles--;
return m_ExtractCallback->SetOperationResult(resOp);
}
HRESULT CFolderOutStream::CloseFile()
{
m_RealOutStream.Release();
HRESULT res = m_ExtractCallback->SetOperationResult(m_IsOk ?
return CloseFileWithResOp(m_IsOk ?
NExtract::NOperationResult::kOK:
NExtract::NOperationResult::kDataError);
m_FileIsOpen = false;
return res;
}
HRESULT CFolderOutStream::OpenFile()
{
Int32 askMode = (*m_ExtractStatuses)[m_CurrentIndex] ? (m_TestMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract) :
NExtract::NAskMode::kSkip;
if (!TempBufMode)
if (NumIdenticalFiles == 0)
{
const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];
const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
int curIndex = m_CurrentIndex + 1;
for (; curIndex < m_ExtractStatuses->Size(); curIndex++)
if ((*m_ExtractStatuses)[curIndex])
int numExtractItems = 0;
int curIndex;
for (curIndex = m_CurrentIndex; curIndex < m_ExtractStatuses->Size(); curIndex++)
{
const CMvItem &mvItem2 = m_Database->Items[m_StartIndex + curIndex];
const CItem &item2 = m_Database->Volumes[mvItem2.VolumeIndex].Items[mvItem2.ItemIndex];
@@ -436,21 +447,46 @@ HRESULT CFolderOutStream::OpenFile()
item.Size != item2.Size ||
item.Size == 0)
break;
if (!m_TestMode && (*m_ExtractStatuses)[curIndex])
numExtractItems++;
}
if (curIndex > m_CurrentIndex + 1)
NumIdenticalFiles = (curIndex - m_CurrentIndex);
if (NumIdenticalFiles == 0)
NumIdenticalFiles = 1;
TempBufMode = false;
if (numExtractItems > 1)
{
size_t oldCapacity = TempBuf.GetCapacity();
IsSupported = (item.Size <= kMaxTempBufSize);
if (item.Size > oldCapacity && IsSupported)
if (!TempBuf || item.Size > TempBufSize)
{
TempBuf.SetCapacity(0);
TempBuf.SetCapacity(item.Size);
FreeTempBuf();
TempBuf = (Byte *)MyAlloc(item.Size);
TempBufSize = item.Size;
if (TempBuf == NULL)
return E_OUTOFMEMORY;
}
TempBufMode = true;
m_BufStartFolderOffset = item.Offset;
}
else if (numExtractItems == 1)
{
while (NumIdenticalFiles && !(*m_ExtractStatuses)[m_CurrentIndex])
{
CMyComPtr<ISequentialOutStream> stream;
RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &stream, NExtract::NAskMode::kSkip));
if (stream)
return E_FAIL;
RINOK(m_ExtractCallback->PrepareOperation(NExtract::NAskMode::kSkip));
m_CurrentIndex++;
m_FileIsOpen = true;
CloseFile();
}
}
}
Int32 askMode = (*m_ExtractStatuses)[m_CurrentIndex] ? (m_TestMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract) :
NExtract::NAskMode::kSkip;
RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode));
if (!m_RealOutStream && !m_TestMode)
askMode = NExtract::NAskMode::kSkip;
@@ -499,7 +535,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal);
numBytesToWrite = processedSizeLocal;
}
if (TempBufMode && IsSupported)
if (TempBufMode && TempBuf)
memcpy(TempBuf + (m_PosInFolder - m_BufStartFolderOffset), data, numBytesToWrite);
}
realProcessed += numBytesToWrite;
@@ -513,39 +549,28 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
return res;
if (m_RemainFileSize == 0)
{
m_RealOutStream.Release();
RINOK(CloseFile());
if (TempBufMode)
while (NumIdenticalFiles)
{
while (m_CurrentIndex < m_ExtractStatuses->Size())
{
const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];
const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
if (item.Offset != m_BufStartFolderOffset)
break;
HRESULT result = OpenFile();
m_FileIsOpen = true;
m_CurrentIndex++;
m_IsOk = true;
if (result == S_OK && m_RealOutStream && IsSupported)
result = WriteStream(m_RealOutStream, TempBuf, item.Size);
if (result == S_OK && m_RealOutStream && TempBuf)
result = WriteStream(m_RealOutStream, TempBuf, (size_t)(m_PosInFolder - m_BufStartFolderOffset));
if (IsSupported)
if (!TempBuf && TempBufMode && m_RealOutStream)
{
RINOK(CloseFile());
RINOK(result);
RINOK(CloseFileWithResOp(NExtract::NOperationResult::kUnSupportedMethod));
}
else
{
m_RealOutStream.Release();
RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
m_FileIsOpen = false;
RINOK(CloseFile());
}
RINOK(result);
}
TempBufMode = false;
}
}
if (realProcessed > 0)
break; // with this break this function works as Write-Part
}

View File

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

View File

@@ -54,7 +54,7 @@ static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
{
sizes.Clear();
sizePointers.Clear();
for(UInt32 i = 0; i < numItems; i++)
for (UInt32 i = 0; i < numItems; i++)
{
if (srcSizes == 0 || srcSizes[i] == NULL)
{
@@ -83,7 +83,7 @@ HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)
{
_bindInfo = bindInfo;
_streamBinders.Clear();
for(int i = 0; i < _bindInfo.BindPairs.Size(); i++)
for (int i = 0; i < _bindInfo.BindPairs.Size(); i++)
{
_streamBinders.Add(CStreamBinder());
RINOK(_streamBinders.Back().CreateEvents());
@@ -113,7 +113,7 @@ void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)
void CCoderMixer2MT::ReInit()
{
for(int i = 0; i < _streamBinders.Size(); i++)
for (int i = 0; i < _streamBinders.Size(); i++)
_streamBinders[i].ReInit();
}
@@ -125,20 +125,20 @@ HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStre
throw 0;
*/
int i;
for(i = 0; i < _coders.Size(); i++)
for (i = 0; i < _coders.Size(); i++)
{
CCoder2 &coderInfo = _coders[i];
const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i];
coderInfo.InStreams.Clear();
UInt32 j;
for(j = 0; j < coderStreamsInfo.NumInStreams; j++)
for (j = 0; j < coderStreamsInfo.NumInStreams; j++)
coderInfo.InStreams.Add(NULL);
coderInfo.OutStreams.Clear();
for(j = 0; j < coderStreamsInfo.NumOutStreams; j++)
for (j = 0; j < coderStreamsInfo.NumOutStreams; j++)
coderInfo.OutStreams.Add(NULL);
}
for(i = 0; i < _bindInfo.BindPairs.Size(); i++)
for (i = 0; i < _bindInfo.BindPairs.Size(); i++)
{
const CBindPair &bindPair = _bindInfo.BindPairs[i];
UInt32 inCoderIndex, inCoderStreamIndex;
@@ -149,16 +149,26 @@ HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStre
_streamBinders[i].CreateStreams(
&_coders[inCoderIndex].InStreams[inCoderStreamIndex],
&_coders[outCoderIndex].OutStreams[outCoderStreamIndex]);
CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize;
_coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize);
_coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize);
if (inSetSize && outSetSize)
{
const UInt32 kBufSize = 1 << 19;
inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize);
outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize);
}
}
for(i = 0; i < _bindInfo.InStreams.Size(); i++)
for (i = 0; i < _bindInfo.InStreams.Size(); i++)
{
UInt32 inCoderIndex, inCoderStreamIndex;
_bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex);
_coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i];
}
for(i = 0; i < _bindInfo.OutStreams.Size(); i++)
for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
{
UInt32 outCoderIndex, outCoderStreamIndex;
_bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex);

View File

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

View File

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

View File

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

View File

@@ -578,8 +578,12 @@ HRESULT CDatabase::Open()
return S_FALSE;
UInt64 fileSize;
RINOK(InStream->Seek(0, STREAM_SEEK_END, &fileSize));
/* we comment that check to support truncated images */
/*
if (fileSize < Header.GetPhySize())
return S_FALSE;
*/
if (Header.IsFat32())
{

View File

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

View File

@@ -8,6 +8,6 @@
static IInArchive *CreateArc() { return new NArchive::NIso::CHandler; }
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)

View File

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

View File

@@ -41,7 +41,7 @@ namespace NMacho {
#define MACH_SECT_ATTR_ZEROFILL 1
const char *g_SectTypes[] =
static const char *g_SectTypes[] =
{
"REGULAR",
"ZEROFILL",
@@ -60,7 +60,7 @@ const char *g_SectTypes[] =
"16BYTE_LITERALS"
};
const char *g_FileTypes[] =
static const char *g_FileTypes[] =
{
"0",
"OBJECT",
@@ -111,11 +111,18 @@ struct CSection
char Name[kNameSize];
char SegName[kNameSize];
UInt64 Va;
UInt64 Size;
UInt32 Pa;
UInt64 Pa;
UInt64 VSize;
UInt64 PSize;
UInt32 Flags;
int SegmentIndex;
UInt64 GetPackSize() const { return Flags == MACH_SECT_ATTR_ZEROFILL ? 0 : Size; }
bool IsDummy;
CSection(): IsDummy(false) {}
// UInt64 GetPackSize() const { return Flags == MACH_SECT_ATTR_ZEROFILL ? 0 : Size; }
UInt64 GetPackSize() const { return PSize; }
};
@@ -195,8 +202,9 @@ bool CHandler::Parse(const Byte *buf, UInt32 size)
if (cmdSize < offs)
break;
{
UInt64 vmAddr, vmSize, phAddr, phSize;
{
if (cmd == MACH_CMD_SEGMENT_64)
{
vmAddr = Get64(buf + 0x18, be);
@@ -226,7 +234,19 @@ bool CHandler::Parse(const Byte *buf, UInt32 size)
if (numSections > (1 << 8))
return false;
while (numSections-- != 0)
if (numSections == 0)
{
CSection section;
section.IsDummy = true;
section.SegmentIndex = _segments.Size() - 1;
section.Va = vmAddr;
section.PSize = phSize;
section.VSize = vmSize;
section.Pa = phAddr;
section.Flags = 0;
_sections.Add(section);
}
else do
{
CSection section;
UInt32 headerSize = (cmd == MACH_CMD_SEGMENT_64) ? 0x50 : 0x44;
@@ -236,23 +256,29 @@ bool CHandler::Parse(const Byte *buf, UInt32 size)
if (cmd == MACH_CMD_SEGMENT_64)
{
section.Va = Get64(p + 0x20, be);
section.Size = Get64(p + 0x28, be);
section.VSize = Get64(p + 0x28, be);
section.Pa = Get32(p + 0x30, be);
section.Flags = Get32(p + 0x40, be);
}
else
{
section.Va = Get32(p + 0x20, be);
section.Size = Get32(p + 0x24, be);
section.VSize = Get32(p + 0x24, be);
section.Pa = Get32(p + 0x28, be);
section.Flags = Get32(p + 0x38, be);
}
if (section.Flags == MACH_SECT_ATTR_ZEROFILL)
section.PSize = 0;
else
section.PSize = section.VSize;
memcpy(section.Name, p, kNameSize);
memcpy(section.SegName, p + kNameSize, kNameSize);
section.SegmentIndex = _segments.Size() - 1;
_sections.Add(section);
offs += headerSize;
}
while (--numSections);
if (offs != cmdSize)
return false;
}
@@ -263,7 +289,7 @@ bool CHandler::Parse(const Byte *buf, UInt32 size)
return reduceCommands || (size == 0);
}
STATPROPSTG kArcProps[] =
static STATPROPSTG kArcProps[] =
{
{ NULL, kpidCpu, VT_BSTR},
{ NULL, kpidBit64, VT_BOOL},
@@ -273,7 +299,7 @@ STATPROPSTG kArcProps[] =
{ NULL, kpidHeadersSize, VT_UI4}
};
STATPROPSTG kProps[] =
static STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidSize, VT_UI8},
@@ -333,10 +359,17 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
const CSection &item = _sections[index];
switch(propID)
{
case kpidPath: StringToProp(GetName(_segments[item.SegmentIndex].Name) + GetName(item.Name), prop); break;
case kpidSize: prop = (UInt64)item.Size; break;
case kpidPath:
{
AString s = GetName(_segments[item.SegmentIndex].Name);
if (!item.IsDummy)
s += GetName(item.Name);
StringToProp(s, prop);
break;
}
case kpidSize: /* prop = (UInt64)item.VSize; break; */
case kpidPackSize: prop = (UInt64)item.GetPackSize(); break;
case kpidCharacts: StringToProp(SectFlagsToString(item.Flags), prop); break;
case kpidCharacts: if (!item.IsDummy) StringToProp(SectFlagsToString(item.Flags), prop); break;
case kpidOffset: prop = item.Pa; break;
case kpidVa: prop = item.Va; break;
}

View File

@@ -6,7 +6,6 @@
#include "Common/ComTry.h"
#include "Common/IntToString.h"
#include "Common/NewHandler.h"
#include "Windows/PropVariant.h"
@@ -23,20 +22,20 @@ using namespace NWindows;
namespace NArchive {
namespace NNsis {
static const wchar_t *kBcjMethod = L"BCJ";
static const wchar_t *kUnknownMethod = L"Unknown";
static const char *kBcjMethod = "BCJ";
static const char *kUnknownMethod = "Unknown";
static const wchar_t *kMethods[] =
static const char *kMethods[] =
{
L"Copy",
L"Deflate",
L"BZip2",
L"LZMA"
"Copy",
"Deflate",
"BZip2",
"LZMA"
};
static const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]);
STATPROPSTG kProps[] =
static STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidSize, VT_UI8},
@@ -46,7 +45,7 @@ STATPROPSTG kProps[] =
{ NULL, kpidSolid, VT_BOOL}
};
STATPROPSTG kArcProps[] =
static STATPROPSTG kArcProps[] =
{
{ NULL, kpidMethod, VT_BSTR},
{ NULL, kpidSolid, VT_BOOL}
@@ -116,50 +115,45 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
return S_OK;
}
static UString ConvertUInt32ToString(UInt32 value)
static AString UInt32ToString(UInt32 value)
{
wchar_t buffer[32];
ConvertUInt64ToString(value, buffer);
char buffer[16];
ConvertUInt32ToString(value, buffer);
return buffer;
}
static UString GetStringForSizeValue(UInt32 value)
static AString GetStringForSizeValue(UInt32 value)
{
for (int i = 31; i >= 0; i--)
if ((UInt32(1) << i) == value)
return ConvertUInt32ToString(i);
UString result;
if (((UInt32)1 << i) == value)
return UInt32ToString(i);
char c = 'b';
if (value % (1 << 20) == 0)
{
result += ConvertUInt32ToString(value >> 20);
result += L"m";
value >>= 20;
c = 'm';
}
else if (value % (1 << 10) == 0)
{
result += ConvertUInt32ToString(value >> 10);
result += L"k";
value >>= 10;
c = 'k';
}
else
{
result += ConvertUInt32ToString(value);
result += L"b";
}
return result;
return UInt32ToString(value) + c;
}
UString CHandler::GetMethod(bool useItemFilter, UInt32 dictionary) const
AString CHandler::GetMethod(bool useItemFilter, UInt32 dictionary) const
{
NMethodType::EEnum methodIndex = _archive.Method;
UString method;
AString method;
if (_archive.IsSolid && _archive.UseFilter || !_archive.IsSolid && useItemFilter)
{
method += kBcjMethod;
method += L" ";
method += ' ';
}
method += (methodIndex < kNumMethods) ? kMethods[methodIndex] : kUnknownMethod;
if (methodIndex == NMethodType::kLZMA)
{
method += L":";
method += ':';
method += GetStringForSizeValue(_archive.IsSolid ? _archive.DictionarySize: dictionary);
}
return method;

View File

@@ -26,7 +26,7 @@ class CHandler:
bool GetUncompressedSize(int index, UInt32 &size);
bool GetCompressedSize(int index, UInt32 &size);
UString GetMethod(bool useItemFilter, UInt32 dictionary) const;
AString GetMethod(bool useItemFilter, UInt32 dictionary) const;
public:
MY_QUERYINTERFACE_BEGIN2(IInArchive)
QUERY_ENTRY_ISetCompressCodecsInfo

View File

@@ -1290,6 +1290,7 @@ HRESULT CInArchive::Open2(
_headerIsCompressed = true;
IsSolid = true;
FilterFlag = false;
DictionarySize = 1;
UInt32 compressedHeaderSize = Get32(sig);

View File

@@ -72,7 +72,7 @@ struct CItem
UInt32 DictionarySize;
CItem(): IsUnicode(false), UseFilter(false), IsCompressed(true), SizeIsDefined(false),
CompressedSizeIsDefined(false), EstimatedSizeIsDefined(false), Size(0) {}
CompressedSizeIsDefined(false), EstimatedSizeIsDefined(false), Size(0), DictionarySize(1) {}
bool IsINSTDIR() const
{

View File

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

View File

@@ -145,7 +145,7 @@ struct COptHeader
// UInt32 AddressOfEntryPoint;
// UInt32 BaseOfCode;
// UInt32 BaseOfData32;
// UInt64 ImageBase;
UInt64 ImageBase;
UInt32 SectAlign;
UInt32 FileAlign;
@@ -202,8 +202,8 @@ bool COptHeader::Parse(const Byte *p, UInt32 size)
// AddressOfEntryPoint = Get32(p + 16);
// BaseOfCode = Get32(p + 20);
// BaseOfData32 = Get32(p + 24);
// ImageBase = hdr64 ? GetUi64(p + 24) :Get32(p + 28);
// BaseOfData32 = hdr64 ? 0: Get32(p + 24);
ImageBase = hdr64 ? GetUi64(p + 24) : Get32(p + 28);
SectAlign = Get32(p + 32);
FileAlign = Get32(p + 36);
@@ -450,6 +450,7 @@ struct CResItem
bool IsIcon() const { return Type == 3; }
bool IsString() const { return Type == 6; }
bool IsRcData() const { return Type == 10; }
bool IsRcDataOrUnknown() const { return IsRcData() || Type > 64; }
};
struct CStringItem
@@ -624,6 +625,10 @@ enum
kpidStackCommit,
kpidHeapReserve,
kpidHeapCommit,
kpidImageBase
// kpidAddressOfEntryPoint,
// kpidBaseOfCode,
// kpidBaseOfData32,
};
STATPROPSTG kArcProps[] =
@@ -651,6 +656,10 @@ STATPROPSTG kArcProps[] =
{ L"Stack Commit", kpidStackCommit, VT_UI8},
{ L"Heap Reserve", kpidHeapReserve, VT_UI8},
{ L"Heap Commit", kpidHeapCommit, VT_UI8},
{ L"Image Base", kpidImageBase, VT_UI8}
// { L"Address Of Entry Point", kpidAddressOfEntryPoint, VT_UI8},
// { L"Base Of Code", kpidBaseOfCode, VT_UI8},
// { L"Base Of Data", kpidBaseOfData32, VT_UI8},
};
STATPROPSTG kProps[] =
@@ -719,6 +728,12 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidStackCommit: prop = _optHeader.StackCommit; break;
case kpidHeapReserve: prop = _optHeader.HeapReserve; break;
case kpidHeapCommit: prop = _optHeader.HeapCommit; break;
case kpidImageBase: prop = _optHeader.ImageBase; break;
// case kpidAddressOfEntryPoint: prop = _optHeader.AddressOfEntryPoint; break;
// case kpidBaseOfCode: prop = _optHeader.BaseOfCode; break;
// case kpidBaseOfData32: if (!_optHeader.Is64Bit()) prop = _optHeader.BaseOfData32; break;
case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;
}
prop.Detach(value);
@@ -1392,7 +1407,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
_parseResources = true;
UInt64 mainSize = 0, mainSize2 = 0;
for (int i = 0; i < _sections.Size(); i++)
int i;
for (i = 0; i < _sections.Size(); i++)
{
const CSection &sect = _sections[i];
CMixItem mixItem;
@@ -1410,7 +1426,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
{
mixItem.ResourceIndex = j;
mixItem.StringIndex = -1;
if (item.IsRcData())
if (item.IsRcDataOrUnknown())
{
if (item.Size >= mainSize)
{
@@ -1468,8 +1484,20 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
}
_mixItems.Add(mixItem);
}
if (mainSize2 >= (1 << 20) && mainSize < mainSize2 * 2)
_mainSubfile = -1;
for (i = 0; i < _mixItems.Size(); i++)
{
const CMixItem &mixItem = _mixItems[i];
if (mixItem.StringIndex < 0 && mixItem.ResourceIndex < 0 && _sections[mixItem.SectionIndex].Name == "_winzip_")
{
_mainSubfile = i;
break;
}
}
return S_OK;
}

View File

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

View File

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

View File

@@ -69,11 +69,20 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
filled = false;
bool thereAreEmptyRecords = false;
for (;;)
{
processedSize = NFileHeader::kRecordSize;
RINOK(ReadStream(stream, buf, &processedSize));
if (processedSize == 0 || (processedSize == NFileHeader::kRecordSize && IsRecordLast(buf)))
if (processedSize == 0)
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;
ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize;

View File

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

View File

@@ -8,6 +8,6 @@
static IInArchive *CreateArc() { return new NArchive::NUdf::CHandler; }
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)

View File

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

View File

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

View File

@@ -0,0 +1,651 @@
// 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;
}
static 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);
// we can write 0 here only if there is no security data, imageX does it,
// but some programs expect size = 8
Set32((Byte *)meta, 8); // size of security data
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

@@ -18,11 +18,8 @@
#define Get32(p) GetUi32(p)
#define Get64(p) GetUi64(p)
namespace NArchive{
namespace NWim{
static const int kChunkSizeBits = 15;
static const UInt32 kChunkSize = (1 << kChunkSizeBits);
namespace NArchive {
namespace NWim {
namespace NXpress {
@@ -44,7 +41,7 @@ HRESULT CDecoder::CodeSpec(UInt32 outSize)
{
{
Byte levels[kMainTableSize];
for (int i = 0; i < kMainTableSize; i += 2)
for (unsigned i = 0; i < kMainTableSize; i += 2)
{
Byte b = m_InBitStream.DirectReadByte();
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,
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);
}
static const UInt32 kSignatureSize = 8;
static const Byte kSignature[kSignatureSize] = { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 };
void CResource::Parse(const Byte *p)
{
Flags = p[7];
@@ -278,19 +266,157 @@ static void GetStream(const Byte *p, CStreamInfo &s)
memcpy(s.Hash, p + 30, kHashSize);
}
static HRESULT ParseDirItem(const Byte *base, size_t pos, size_t size,
const UString &prefix, CObjectVector<CItem> &items)
static const wchar_t *kLongPath = L"[LongPath]";
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)
return S_FALSE;
const Byte *p = base + pos;
UInt64 length = Get64(p);
if (length == 0)
const CItem &item = Items[index];
index = item.Parent;
if (index >= 0 || !SkipRoot)
size += item.Name.Length() + newLevel;
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;
if (pos + 102 > size || pos + length + 8 > size || length > ((UInt64)1 << 62))
if (Get16(p + size) != 0)
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)
return S_FALSE;
/* Probably different versions of ImageX can use different number of
additional ZEROs. So we don't use exact check. */
UInt32 fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2);
if (((0x26 + fileNameLen2 + 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;
item.Attrib = Get32(p + 8);
// item.SecurityId = Get32(p + 0xC);
@@ -300,43 +426,64 @@ static HRESULT ParseDirItem(const Byte *base, size_t pos, size_t size,
GetFileTimeFromMem(p + 0x38, &item.MTime);
memcpy(item.Hash, p + 0x40, kHashSize);
// UInt16 shortNameLen = Get16(p + 98);
UInt16 fileNameLen = Get16(p + 100);
size_t tempPos = pos + 102;
if (tempPos + fileNameLen > size)
UInt32 shortNameLen = Get16(p + 98);
UInt32 fileNameLen = Get16(p + 100);
if ((shortNameLen & 1) != 0 || (fileNameLen & 1) != 0)
return S_FALSE;
wchar_t *sz = item.Name.GetBuffer(prefix.Length() + fileNameLen / 2 + 1);
MyStringCopy(sz, (const wchar_t *)prefix);
sz += prefix.Length();
for (UInt16 i = 0; i + 2 <= fileNameLen; i += 2)
*sz++ = Get16(base + tempPos + i);
*sz++ = '\0';
item.Name.ReleaseBuffer();
if (fileNameLen == 0 && item.isDir() && !item.HasStream())
UInt32 shortNameLen2 = (shortNameLen == 0 ? shortNameLen : shortNameLen + 2);
UInt32 fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2);
if (((kDirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7) > len)
return S_FALSE;
p += kDirRecordSize;
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.Name.Delete(item.Name.Length() - 1);
}
items.Add(item);
pos += (size_t)length;
if (item.isDir() && (subdirOffset != 0))
item.Parent = parent;
prevIndex = Items.Add(item);
if (item.IsDir() && subdirOffset != 0)
{
if (subdirOffset >= size)
return S_FALSE;
RINOK(ParseDirItem(base, (size_t)subdirOffset, size, item.Name + WCHAR_PATH_SEPARATOR, items));
RINOK(ParseDirItem((size_t)subdirOffset, prevIndex));
}
Items[prevIndex].Order = Order++;
pos += (size_t)len;
}
}
static HRESULT ParseDir(const Byte *base, size_t size,
const UString &prefix, CObjectVector<CItem> &items)
HRESULT CDatabase::ParseImageDirs(const CByteBuffer &buf, int parent)
{
DirData = buf;
DirSize = buf.GetCapacity();
size_t pos = 0;
if (pos + 8 > size)
if (DirSize < 8)
return S_FALSE;
const Byte *p = base + pos;
const Byte *p = DirData;
UInt32 totalLength = Get32(p);
// UInt32 numEntries = Get32(p + 4);
pos += 8;
@@ -346,7 +493,7 @@ static HRESULT ParseDir(const Byte *base, size_t size,
UInt64 sum = 0;
for (UInt32 i = 0; i < numEntries; i++)
{
if (pos + 8 > size)
if (pos + 8 > DirSize)
return S_FALSE;
UInt64 len = Get64(p + pos);
entryLens.Add(len);
@@ -359,17 +506,125 @@ static HRESULT ParseDir(const Byte *base, size_t size,
if (pos != totalLength)
return S_FALSE;
*/
if (totalLength == 0)
pos = 8;
else if (totalLength < 8)
return S_FALSE;
else
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;
return memcmp(streams[*p1].Hash, streams[*p2].Hash, kHashSize);
UInt32 haderSize = Get32(p + 8);
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 */)
{
int res = MyCompare(p1->PartNumber, p2->PartNumber);
@@ -378,24 +633,14 @@ static int CompareStreamsByPos(const CStreamInfo *p1, const CStreamInfo *p2, voi
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 CItem &i2 = **((const CItem **)a2);
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);
const CRecordVector<CStreamInfo> &streams = *(const CRecordVector<CStreamInfo> *)param;
return memcmp(streams[*p1].Hash, streams[*p2].Hash, kHashSize);
}
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();
while (left != right)
@@ -417,153 +662,70 @@ static int FindHash(const CRecordVector<CStreamInfo> &streams,
return -1;
}
HRESULT CHeader::Parse(const Byte *p)
static int CompareItems(const int *a1, const int *a2, void *param)
{
UInt32 haderSize = Get32(p + 8);
if (haderSize < 0x74)
return S_FALSE;
Version = Get32(p + 0x0C);
Flags = Get32(p + 0x10);
if (!IsSupported())
return S_FALSE;
UInt32 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;
IntegrityResource.Parse(p + offset + 0x4C);
BootIndex = Get32(p + 0x48);
}
*/
return S_OK;
const CObjectVector<CItem> &items = ((CDatabase *)param)->Items;
const CItem &i1 = items[*a1];
const CItem &i2 = items[*a2];
if (i1.IsDir() != i2.IsDir())
return i1.IsDir() ? 1 : -1;
int res = MyCompare(i1.StreamIndex, i2.StreamIndex);
if (res != 0)
return res;
return MyCompare(i1.Order, i2.Order);
}
HRESULT ReadHeader(IInStream *inStream, CHeader &h)
HRESULT CDatabase::Sort(bool skipRootDir)
{
const UInt32 kHeaderSizeMax = 0xD0;
Byte p[kHeaderSizeMax];
RINOK(ReadStream_FALSE(inStream, p, kHeaderSizeMax));
if (memcmp(p, kSignature, kSignatureSize) != 0)
return S_FALSE;
return h.Parse(p);
}
Streams.Sort(CompareStreamsByPos, NULL);
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)
CIntVector sortedByHash;
{
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;
}
for (int i = 0; i < Streams.Size(); i++)
sortedByHash.Add(i);
sortedByHash.Sort(CompareHashRefs, &Streams);
}
if (needBootMetadata)
for (int i = 0; i < Items.Size(); i++)
{
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;
{
for (int j = 0; j < db.Streams.Size(); j++)
sortedByHash.Add(j);
sortedByHash.Sort(CompareHashRefs, &db.Streams);
}
for (int i = 0; i < db.Items.Size(); i++)
{
CItem &item = db.Items[i];
CItem &item = Items[i];
item.StreamIndex = -1;
if (item.HasStream())
item.StreamIndex = FindHash(db.Streams, sortedByHash, item.Hash);
item.StreamIndex = FindHash(Streams, sortedByHash, item.Hash);
}
}
{
CRecordVector<bool> used;
int j;
for (j = 0; j < db.Streams.Size(); j++)
int i;
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(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)
used[item.StreamIndex] = true;
}
for (j = 0; j < db.Streams.Size(); j++)
if (!used[j])
for (i = 0; i < Streams.Size(); i++)
if (!used[i])
{
CItem item;
item.StreamIndex = j;
item.StreamIndex = i;
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;
}

View File

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

View File

@@ -6,8 +6,13 @@
#include "WimHandler.h"
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 =
{ 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)

View File

@@ -244,14 +244,14 @@ HRESULT CAddCommon::Compress(
_compressEncoder = encoder;
NWindows::NCOM::CPropVariant props[] =
{
// _options.Algo,
_options.Algo,
_options.MemSize,
_options.Order
};
PROPID propIDs[] =
{
// NCoderPropID::kAlgorithm,
NCoderPropID::kAlgorithm,
NCoderPropID::kUsedMemorySize,
NCoderPropID::kOrder
};

View File

@@ -128,7 +128,9 @@ static STATPROPSTG kProps[] =
static STATPROPSTG kArcProps[] =
{
{ NULL, kpidBit64, VT_BOOL},
{ NULL, kpidComment, VT_BSTR}
{ NULL, kpidComment, VT_BSTR},
{ NULL, kpidPhySize, VT_UI8},
{ NULL, kpidOffset, VT_UI8}
};
CHandler::CHandler()
@@ -160,9 +162,9 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
switch(propID)
{
case kpidBit64: if (m_Archive.IsZip64) prop = m_Archive.IsZip64; break;
case kpidComment:
prop = MultiByteToUnicodeString(BytesToString(m_Archive.m_ArchiveInfo.Comment), CP_ACP);
break;
case kpidComment: prop = MultiByteToUnicodeString(BytesToString(m_Archive.ArcInfo.Comment), CP_ACP); break;
case kpidPhySize: prop = m_Archive.ArcInfo.GetPhySize(); break;
case kpidOffset: if (m_Archive.ArcInfo.StartPosition != 0) prop = m_Archive.ArcInfo.StartPosition; break;
}
prop.Detach(value);
COM_TRY_END

View File

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

View File

@@ -51,18 +51,6 @@ static const UInt32 kLzmaDicSizeX5 = 1 << 24;
static const UInt32 kLzmaDicSizeX7 = 1 << 25;
static const UInt32 kLzmaDicSizeX9 = 1 << 26;
static const UInt32 kPpmdMemSizeX1 = (1 << 20);
static const UInt32 kPpmdMemSizeX3 = (1 << 22);
static const UInt32 kPpmdMemSizeX5 = (1 << 24);
static const UInt32 kPpmdMemSizeX7 = (1 << 26);
static const UInt32 kPpmdMemSizeX9 = (1 << 27);
static const UInt32 kPpmdOrderX1 = 4;
static const UInt32 kPpmdOrderX3 = 6;
static const UInt32 kPpmdOrderX5 = 8;
static const UInt32 kPpmdOrderX7 = 10;
static const UInt32 kPpmdOrderX9 = 16;
static const UInt32 kBZip2NumPassesX1 = 1;
static const UInt32 kBZip2NumPassesX7 = 2;
static const UInt32 kBZip2NumPassesX9 = 7;
@@ -201,11 +189,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
name += kSlash;
bool tryUtf8 = true;
if (m_ForseLocal || !m_ForseUtf8)
if (m_ForceLocal || !m_ForceUtf8)
{
bool defaultCharWasUsed;
ui.Name = UnicodeStringToMultiByte(name, CP_OEMCP, '_', defaultCharWasUsed);
tryUtf8 = (!m_ForseLocal && (defaultCharWasUsed ||
tryUtf8 = (!m_ForceLocal && (defaultCharWasUsed ||
MultiByteToUnicodeString(ui.Name, CP_OEMCP) != name));
}
@@ -362,23 +350,18 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
}
if (mainMethod == NFileHeader::NCompressionMethod::kPPMd)
{
int level2 = level;
if (level2 < 1) level2 = 1;
if (level2 > 9) level2 = 9;
if (options.MemSize == 0xFFFFFFFF)
options.MemSize =
(level >= 9 ? kPpmdMemSizeX9 :
(level >= 7 ? kPpmdMemSizeX7 :
(level >= 5 ? kPpmdMemSizeX5 :
(level >= 3 ? kPpmdMemSizeX3 :
kPpmdMemSizeX1))));
options.MemSize = (1 << (19 + (level2 > 8 ? 8 : level2)));
if (options.Order == 0xFFFFFFFF)
options.Order =
(level >= 9 ? kPpmdOrderX9 :
(level >= 7 ? kPpmdOrderX7 :
(level >= 5 ? kPpmdOrderX5 :
(level >= 3 ? kPpmdOrderX3 :
kPpmdOrderX1))));
options.Order = 3 + level2;
options.Algo = 0;
if (options.Algo == 0xFFFFFFFF)
options.Algo = (level2 >= 7 ? 1 : 0);
}
return Update(
@@ -482,13 +465,13 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
}
else if (name.Left(3) == L"MEM")
{
UInt32 memSize = kPpmdMemSizeX5;
UInt32 memSize = 1 << 24;
RINOK(ParsePropDictionaryValue(name.Mid(3), prop, memSize));
m_MemSize = memSize;
}
else if (name[0] == L'O')
{
UInt32 order = kPpmdOrderX5;
UInt32 order = 8;
RINOK(ParsePropValue(name.Mid(1), prop, order));
m_Order = order;
}
@@ -529,15 +512,15 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
}
else if (name.CompareNoCase(L"CL") == 0)
{
RINOK(SetBoolProperty(m_ForseLocal, prop));
if (m_ForseLocal)
m_ForseUtf8 = false;
RINOK(SetBoolProperty(m_ForceLocal, prop));
if (m_ForceLocal)
m_ForceUtf8 = false;
}
else if (name.CompareNoCase(L"CU") == 0)
{
RINOK(SetBoolProperty(m_ForseUtf8, prop));
if (m_ForseUtf8)
m_ForseLocal = false;
RINOK(SetBoolProperty(m_ForceUtf8, prop));
if (m_ForceUtf8)
m_ForceLocal = false;
}
else
return E_INVALIDARG;

View File

@@ -63,7 +63,7 @@ static inline bool TestMarkerCandidate2(const Byte *p, UInt32 &value)
HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
{
m_ArchiveInfo.Clear();
ArcInfo.Clear();
m_Position = m_StreamStartPosition;
Byte marker[NSignature::kMarkerSize];
@@ -99,7 +99,7 @@ HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchHea
if (TestMarkerCandidate2(buffer + pos, m_Signature))
{
curTestPos += pos;
m_ArchiveInfo.StartPosition = curTestPos;
ArcInfo.StartPosition = curTestPos;
m_Position = curTestPos + NSignature::kMarkerSize;
return S_OK;
}
@@ -208,11 +208,6 @@ void CInArchive::ReadFileName(UInt32 nameSize, AString &dest)
dest.ReleaseBuffer();
}
void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const
{
archiveInfo = m_ArchiveInfo;
}
void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock,
UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber)
{
@@ -332,7 +327,7 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item)
return S_OK;
try
{
RINOK(Seek(m_ArchiveInfo.Base + item.LocalHeaderPosition));
RINOK(Seek(ArcInfo.Base + item.LocalHeaderPosition));
CItemEx localItem;
if (ReadUInt32() != NSignature::kLocalFileHeader)
return S_FALSE;
@@ -419,7 +414,7 @@ HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item)
RINOK(ReadLocalItemAfterCdItem(item));
if (item.HasDescriptor())
{
RINOK(Seek(m_ArchiveInfo.Base + item.GetDataPosition() + item.PackSize));
RINOK(Seek(ArcInfo.Base + item.GetDataPosition() + item.PackSize));
if (ReadUInt32() != NSignature::kDataDescriptor)
return S_FALSE;
UInt32 crc = ReadUInt32();
@@ -534,9 +529,9 @@ HRESULT CInArchive::FindCd(CCdInfo &cdInfo)
UInt64 ecd64Offset = Get64(locator + 8);
if (TryEcd64(ecd64Offset, cdInfo) == S_OK)
return S_OK;
if (TryEcd64(m_ArchiveInfo.StartPosition + ecd64Offset, cdInfo) == S_OK)
if (TryEcd64(ArcInfo.StartPosition + ecd64Offset, cdInfo) == S_OK)
{
m_ArchiveInfo.Base = m_ArchiveInfo.StartPosition;
ArcInfo.Base = ArcInfo.StartPosition;
return S_OK;
}
}
@@ -548,8 +543,8 @@ HRESULT CInArchive::FindCd(CCdInfo &cdInfo)
cdInfo.Offset = Get32(buf + i + 16);
UInt64 curPos = endPosition - bufSize + i;
UInt64 cdEnd = cdInfo.Size + cdInfo.Offset;
if (curPos > cdEnd)
m_ArchiveInfo.Base = curPos - cdEnd;
if (curPos != cdEnd)
ArcInfo.Base = curPos - cdEnd;
return S_OK;
}
}
@@ -585,18 +580,18 @@ HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, UInt64 cdOffset, UI
HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt64 &cdOffset, UInt64 &cdSize, CProgressVirt *progress)
{
m_ArchiveInfo.Base = 0;
ArcInfo.Base = 0;
CCdInfo cdInfo;
RINOK(FindCd(cdInfo));
HRESULT res = S_FALSE;
cdSize = cdInfo.Size;
cdOffset = cdInfo.Offset;
res = TryReadCd(items, m_ArchiveInfo.Base + cdOffset, cdSize, progress);
if (res == S_FALSE && m_ArchiveInfo.Base == 0)
res = TryReadCd(items, ArcInfo.Base + cdOffset, cdSize, progress);
if (res == S_FALSE && ArcInfo.Base == 0)
{
res = TryReadCd(items, cdInfo.Offset + m_ArchiveInfo.StartPosition, cdSize, progress);
res = TryReadCd(items, cdInfo.Offset + ArcInfo.StartPosition, cdSize, progress);
if (res == S_OK)
m_ArchiveInfo.Base = m_ArchiveInfo.StartPosition;
ArcInfo.Base = ArcInfo.StartPosition;
}
if (!ReadUInt32(m_Signature))
return S_FALSE;
@@ -645,7 +640,7 @@ HRESULT CInArchive::ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt
CItemEx &item = items[j];
if (item.Name == cdItem.Name)
{
m_ArchiveInfo.Base = item.LocalHeaderPosition - cdItem.LocalHeaderPosition;
ArcInfo.Base = item.LocalHeaderPosition - cdItem.LocalHeaderPosition;
break;
}
}
@@ -660,7 +655,7 @@ HRESULT CInArchive::ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt
if (left >= right)
return S_FALSE;
index = (left + right) / 2;
UInt64 position = items[index].LocalHeaderPosition - m_ArchiveInfo.Base;
UInt64 position = items[index].LocalHeaderPosition - ArcInfo.Base;
if (cdItem.LocalHeaderPosition == position)
break;
if (cdItem.LocalHeaderPosition < position)
@@ -693,7 +688,7 @@ HRESULT CInArchive::ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt
return S_FALSE;
}
for (i = 0; i < items.Size(); i++)
items[i].LocalHeaderPosition -= m_ArchiveInfo.Base;
items[i].LocalHeaderPosition -= ArcInfo.Base;
return S_OK;
}
@@ -781,20 +776,20 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr
if (res == S_FALSE)
{
_inBufMode = false;
m_ArchiveInfo.Base = 0;
RINOK(m_Stream->Seek(m_ArchiveInfo.StartPosition, STREAM_SEEK_SET, &m_Position));
if (m_Position != m_ArchiveInfo.StartPosition)
ArcInfo.Base = 0;
RINOK(m_Stream->Seek(ArcInfo.StartPosition, STREAM_SEEK_SET, &m_Position));
if (m_Position != ArcInfo.StartPosition)
return S_FALSE;
if (!ReadUInt32(m_Signature))
return S_FALSE;
RINOK(ReadLocalsAndCd(items, progress, cdStartOffset, numCdItems));
cdSize = (m_Position - 4) - cdStartOffset;
cdStartOffset -= m_ArchiveInfo.Base;
cdStartOffset -= ArcInfo.Base;
}
CEcd64 ecd64;
bool isZip64 = false;
UInt64 zip64EcdStartOffset = m_Position - 4 - m_ArchiveInfo.Base;
UInt64 zip64EcdStartOffset = m_Position - 4 - ArcInfo.Base;
if (m_Signature == NSignature::kZip64EndOfCentralDir)
{
IsZip64 = isZip64 = true;
@@ -843,7 +838,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr
COPY_ECD_ITEM_32(cdSize);
COPY_ECD_ITEM_32(cdStartOffset);
ReadBuffer(m_ArchiveInfo.Comment, ecd.commentSize);
ReadBuffer(ArcInfo.Comment, ecd.commentSize);
if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0)
throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);
@@ -857,6 +852,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr
_inBufMode = false;
_inBuffer.Free();
IsOkHeaders = (numCdItems == items.Size());
ArcInfo.FinishPosition = m_Position;
return S_OK;
}
@@ -864,7 +860,7 @@ ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 siz
{
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> stream(streamSpec);
SeekInArchive(m_ArchiveInfo.Base + position);
SeekInArchive(ArcInfo.Base + position);
streamSpec->SetStream(m_Stream);
streamSpec->Init(size);
return stream.Detach();

View File

@@ -38,8 +38,11 @@ class CInArchiveInfo
public:
UInt64 Base;
UInt64 StartPosition;
UInt64 FinishPosition;
CByteBuffer Comment;
CInArchiveInfo(): Base(0), StartPosition(0) {}
UInt64 GetPhySize() const { return FinishPosition - StartPosition; }
void Clear()
{
Base = 0;
@@ -101,7 +104,7 @@ class CInArchive
HRESULT ReadCd(CObjectVector<CItemEx> &items, UInt64 &cdOffset, UInt64 &cdSize, CProgressVirt *progress);
HRESULT ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt *progress, UInt64 &cdOffset, int &numCdItems);
public:
CInArchiveInfo m_ArchiveInfo;
CInArchiveInfo ArcInfo;
bool IsZip64;
bool IsOkHeaders;
@@ -110,7 +113,6 @@ public:
HRESULT ReadLocalItemAfterCdItemFull(CItemEx &item);
HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
void Close();
void GetArchiveInfo(CInArchiveInfo &archiveInfo) const;
bool SeekInArchive(UInt64 position);
ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size);
IInStream* CreateStream();

View File

@@ -221,7 +221,7 @@ void COutArchive::WriteCentralHeader(const CItem &item)
WriteBytes(item.Comment, (UInt32)item.Comment.GetCapacity());
}
void COutArchive::WriteCentralDir(const CObjectVector<CItem> &items, const CByteBuffer &comment)
void COutArchive::WriteCentralDir(const CObjectVector<CItem> &items, const CByteBuffer *comment)
{
SeekTo(m_BasePosition);
@@ -260,10 +260,10 @@ void COutArchive::WriteCentralDir(const CObjectVector<CItem> &items, const CByte
WriteUInt16((UInt16)(items64 ? 0xFFFF: items.Size()));
WriteUInt32(cdSize64 ? 0xFFFFFFFF: (UInt32)cdSize);
WriteUInt32(cdOffset64 ? 0xFFFFFFFF: (UInt32)cdOffset);
UInt16 commentSize = (UInt16)comment.GetCapacity();
WriteUInt16(commentSize);
UInt32 commentSize = (UInt32)(comment ? comment->GetCapacity() : 0);
WriteUInt16((UInt16)commentSize);
if (commentSize > 0)
WriteBytes((const Byte *)comment, commentSize);
WriteBytes((const Byte *)*comment, commentSize);
m_OutBuffer.FlushWithCheck();
}

View File

@@ -44,7 +44,7 @@ public:
void PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize, bool aesEncryption);
void WriteLocalHeader(const CLocalItem &item);
void WriteCentralDir(const CObjectVector<CItem> &items, const CByteBuffer &comment);
void WriteCentralDir(const CObjectVector<CItem> &items, const CByteBuffer *comment);
void CreateStreamForCompressing(IOutStream **outStream);
void CreateStreamForCopying(ISequentialOutStream **outStream);

View File

@@ -398,7 +398,7 @@ static HRESULT Update2St(
const CObjectVector<CItemEx> &inputItems,
const CObjectVector<CUpdateItem> &updateItems,
const CCompressionMethodMode *options,
const CByteBuffer &comment,
const CByteBuffer *comment,
IArchiveUpdateCallback *updateCallback)
{
CLocalProgress *lps = new CLocalProgress;
@@ -482,7 +482,7 @@ static HRESULT Update2(
const CObjectVector<CItemEx> &inputItems,
const CObjectVector<CUpdateItem> &updateItems,
const CCompressionMethodMode *options,
const CByteBuffer &comment,
const CByteBuffer *comment,
IArchiveUpdateCallback *updateCallback)
{
UInt64 complexity = 0;
@@ -515,8 +515,8 @@ static HRESULT Update2(
complexity += NFileHeader::kCentralBlockSize;
}
if (comment != 0)
complexity += comment.GetCapacity();
if (comment)
complexity += comment->GetCapacity();
complexity++; // end of central
updateCallback->SetTotal(complexity);
@@ -812,27 +812,27 @@ HRESULT Update(
if (!outStream)
return E_NOTIMPL;
CInArchiveInfo archiveInfo;
if(inArchive != 0)
if (inArchive)
{
inArchive->GetArchiveInfo(archiveInfo);
if (archiveInfo.Base != 0 || !inArchive->IsOkHeaders)
if (inArchive->ArcInfo.Base != 0 ||
inArchive->ArcInfo.StartPosition != 0 ||
!inArchive->IsOkHeaders)
return E_NOTIMPL;
}
else
archiveInfo.StartPosition = 0;
COutArchive outArchive;
outArchive.Create(outStream);
if (archiveInfo.StartPosition > 0)
/*
if (inArchive && inArchive->ArcInfo.StartPosition > 0)
{
CMyComPtr<ISequentialInStream> inStream;
inStream.Attach(inArchive->CreateLimitedStream(0, archiveInfo.StartPosition));
inStream.Attach(inArchive->CreateLimitedStream(0, inArchive->ArcInfo.StartPosition));
RINOK(CopyBlockToArchive(inStream, outArchive, NULL));
outArchive.MoveBasePosition(archiveInfo.StartPosition);
outArchive.MoveBasePosition(inArchive->ArcInfo.StartPosition);
}
*/
CMyComPtr<IInStream> inStream;
if(inArchive != 0)
if (inArchive)
inStream.Attach(inArchive->CreateStream());
return Update2(
@@ -840,7 +840,8 @@ HRESULT Update(
outArchive, inArchive, inStream,
inputItems, updateItems,
compressionMethodMode,
archiveInfo.Comment, updateCallback);
inArchive ? &inArchive->ArcInfo.Comment : NULL,
updateCallback);
}
}}

View File

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

View File

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

View File

@@ -440,14 +440,6 @@ SOURCE=..\..\UI\FileManager\OptionsDialog.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\FileManager\PluginsPage.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\FileManager\PluginsPage.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\FileManager\SettingsPage.cpp
# End Source File
# Begin Source File

View File

@@ -65,7 +65,6 @@ FM_OBJS = \
$O\MessagesDialog.obj \
$O\OverwriteDialog.obj \
$O\PasswordDialog.obj \
$O\PluginsPage.obj \
$O\ProgressDialog2.obj \
$O\SettingsPage.obj \
$O\SplitDialog.obj \
@@ -323,6 +322,7 @@ UDF_OBJS = \
WIM_OBJS = \
$O\WimHandler.obj \
$O\WimHandlerOut.obj \
$O\WimIn.obj \
$O\WimRegister.obj \

View File

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

View File

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

View File

@@ -57,12 +57,8 @@ HRESULT CEncoder::Flush()
const UInt32 kDefaultLimit = (1 << 24);
HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 ** /* outSizes */,
UInt32 numOutStreams,
HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams,
ICompressProgressInfo *progress)
{
if (numInStreams != 1 || numOutStreams != 4)
@@ -81,6 +77,8 @@ HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams,
sizeIsDefined = true;
}
CCoderReleaser releaser(this);
ISequentialInStream *inStream = inStreams[0];
_mainStream.SetStream(outStreams[0]);
@@ -93,7 +91,6 @@ HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams,
_rangeEncoder.Init();
for (int i = 0; i < 256 + 2; i++)
_statusEncoder[i].Init();
CCoderReleaser releaser(this);
CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize;
{
@@ -253,18 +250,13 @@ HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams,
}
}
STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,
ICompressProgressInfo *progress)
{
try
{
return CodeReal(inStreams, inSizes, numInStreams,
outStreams, outSizes,numOutStreams, progress);
return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress);
}
catch(const COutBufferException &e) { return e.ErrorCode; }
catch(...) { return S_FALSE; }
@@ -272,28 +264,39 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams,
#endif
HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams,
const UInt64 ** /* inSizes */,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 ** /* outSizes */,
UInt32 numOutStreams,
STDMETHODIMP CDecoder::SetInBufSize(UInt32 streamIndex, UInt32 size) { _inBufSizes[streamIndex] = size; return S_OK; }
STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; }
CDecoder::CDecoder():
_outBufSize(1 << 16)
{
_inBufSizes[0] = 1 << 20;
_inBufSizes[1] = 1 << 20;
_inBufSizes[2] = 1 << 20;
_inBufSizes[3] = 1 << 20;
}
HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams,
ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams,
ICompressProgressInfo *progress)
{
if (numInStreams != 4 || numOutStreams != 1)
return E_INVALIDARG;
if (!_mainInStream.Create(1 << 16))
if (!_mainInStream.Create(_inBufSizes[0]))
return E_OUTOFMEMORY;
if (!_callStream.Create(1 << 20))
if (!_callStream.Create(_inBufSizes[1]))
return E_OUTOFMEMORY;
if (!_jumpStream.Create(1 << 16))
if (!_jumpStream.Create(_inBufSizes[2]))
return E_OUTOFMEMORY;
if (!_rangeDecoder.Create(1 << 20))
if (!_rangeDecoder.Create(_inBufSizes[3]))
return E_OUTOFMEMORY;
if (!_outStream.Create(1 << 16))
if (!_outStream.Create(_outBufSize))
return E_OUTOFMEMORY;
CCoderReleaser releaser(this);
_mainInStream.SetStream(inStreams[0]);
_callStream.SetStream(inStreams[1]);
_jumpStream.SetStream(inStreams[2]);
@@ -309,8 +312,6 @@ HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams,
for (int i = 0; i < 256 + 2; i++)
_statusDecoder[i].Init();
CCoderReleaser releaser(this);
Byte prevByte = 0;
UInt32 processedBytes = 0;
for (;;)
@@ -369,18 +370,13 @@ HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams,
}
}
STDMETHODIMP CDecoder::Code(ISequentialInStream **inStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
STDMETHODIMP CDecoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,
ICompressProgressInfo *progress)
{
try
{
return CodeReal(inStreams, inSizes, numInStreams,
outStreams, outSizes,numOutStreams, progress);
return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress);
}
catch(const CInBufferException &e) { return e.ErrorCode; }
catch(const COutBufferException &e) { return e.ErrorCode; }

View File

@@ -21,9 +21,6 @@ class CEncoder:
public CMyUnknownImp
{
Byte *_buffer;
public:
CEncoder(): _buffer(0) {};
~CEncoder();
bool Create();
COutBuffer _mainStream;
@@ -33,6 +30,7 @@ public:
NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusEncoder[256 + 2];
HRESULT Flush();
public:
void ReleaseStreams()
{
_mainStream.ReleaseStream();
@@ -50,32 +48,25 @@ public:
};
public:
MY_UNKNOWN_IMP
HRESULT CodeReal(ISequentialInStream **inStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,
ICompressProgressInfo *progress);
STDMETHOD(Code)(ISequentialInStream **inStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,
ICompressProgressInfo *progress);
CEncoder(): _buffer(0) {};
~CEncoder();
};
#endif
class CDecoder:
public ICompressCoder2,
public ICompressSetBufSize,
public CMyUnknownImp
{
public:
CInBuffer _mainInStream;
CInBuffer _callStream;
CInBuffer _jumpStream;
@@ -83,7 +74,10 @@ public:
NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusDecoder[256 + 2];
COutBuffer _outStream;
UInt32 _inBufSizes[4];
UInt32 _outBufSize;
public:
void ReleaseStreams()
{
_mainInStream.ReleaseStream();
@@ -103,21 +97,17 @@ public:
};
public:
MY_UNKNOWN_IMP
HRESULT CodeReal(ISequentialInStream **inStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
MY_UNKNOWN_IMP1(ICompressSetBufSize);
HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,
ICompressProgressInfo *progress);
STDMETHOD(Code)(ISequentialInStream **inStreams,
const UInt64 **inSizes,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,
ICompressProgressInfo *progress);
STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);
STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);
CDecoder();
};
}}

View File

@@ -24,9 +24,10 @@ static HRESULT SResToHRESULT(SRes res)
namespace NCompress {
namespace NLzma {
static const UInt32 kInBufSize = 1 << 20;
CDecoder::CDecoder(): _inBuf(0), _propsWereSet(false), _outSizeDefined(false), FinishStream(false)
CDecoder::CDecoder(): _inBuf(0), _propsWereSet(false), _outSizeDefined(false),
_inBufSize(1 << 20),
_outBufSize(1 << 22),
FinishStream(false)
{
_inSizeProcessed = 0;
_inPos = _inSize = 0;
@@ -43,13 +44,18 @@ CDecoder::~CDecoder()
MyFree(_inBuf);
}
STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; }
STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; }
HRESULT CDecoder::CreateInputBuffer()
{
if (_inBuf == 0)
if (_inBuf == 0 || _inBufSize != _inBufSizeAllocated)
{
_inBuf = (Byte *)MyAlloc(kInBufSize);
MyFree(_inBuf);
_inBuf = (Byte *)MyAlloc(_inBufSize);
if (_inBuf == 0)
return E_OUTOFMEMORY;
_inBufSizeAllocated = _inBufSize;
}
return S_OK;
}
@@ -67,6 +73,7 @@ void CDecoder::SetOutStreamSizeResume(const UInt64 *outSize)
if (_outSizeDefined)
_outSize = *outSize;
_outSizeProcessed = 0;
_wrPos = 0;
LzmaDec_Init(&_state);
}
@@ -85,19 +92,17 @@ HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *
UInt64 startInProgress = _inSizeProcessed;
SizeT next = (_state.dicBufSize - _state.dicPos < _outBufSize) ? _state.dicBufSize : (_state.dicPos + _outBufSize);
for (;;)
{
if (_inPos == _inSize)
{
_inPos = _inSize = 0;
RINOK(inStream->Read(_inBuf, kInBufSize, &_inSize));
RINOK(inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize));
}
SizeT dicPos = _state.dicPos;
SizeT curSize = _state.dicBufSize - dicPos;
const UInt32 kStepSize = ((UInt32)1 << 22);
if (curSize > kStepSize)
curSize = (SizeT)kStepSize;
SizeT curSize = next - dicPos;
ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
if (_outSizeDefined)
@@ -123,9 +128,18 @@ HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *
bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0);
bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize);
if (res != 0 || _state.dicPos == _state.dicBufSize || finished || stopDecoding)
if (res != 0 || _state.dicPos == next || finished || stopDecoding)
{
HRESULT res2 = WriteStream(outStream, _state.dic, _state.dicPos);
HRESULT res2 = WriteStream(outStream, _state.dic + _wrPos, _state.dicPos - _wrPos);
_wrPos = _state.dicPos;
if (_state.dicPos == _state.dicBufSize)
{
_state.dicPos = 0;
_wrPos = 0;
}
next = (_state.dicBufSize - _state.dicPos < _outBufSize) ? _state.dicBufSize : (_state.dicPos + _outBufSize);
if (res != 0)
return S_FALSE;
RINOK(res2);
@@ -134,9 +148,6 @@ HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *
if (finished)
return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE);
}
if (_state.dicPos == _state.dicBufSize)
_state.dicPos = 0;
if (progress)
{
UInt64 inSize = _inSizeProcessed - startInProgress;
@@ -148,6 +159,8 @@ HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
{
if (_inBuf == 0)
return E_INVALIDARG;
SetOutStreamSize(outSize);
return CodeSpec(inStream, outStream, progress);
}
@@ -166,7 +179,7 @@ STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
if (_inPos == _inSize)
{
_inPos = _inSize = 0;
RINOK(_inStream->Read(_inBuf, kInBufSize, &_inSize));
RINOK(_inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize));
}
{
SizeT inProcessed = _inSize - _inPos;
@@ -214,7 +227,7 @@ HRESULT CDecoder::ReadFromInputStream(void *data, UInt32 size, UInt32 *processed
if (_inPos == _inSize)
{
_inPos = _inSize = 0;
RINOK(_inStream->Read(_inBuf, kInBufSize, &_inSize));
RINOK(_inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize));
if (_inSize == 0)
break;
}

View File

@@ -14,6 +14,7 @@ namespace NLzma {
class CDecoder:
public ICompressCoder,
public ICompressSetDecoderProperties2,
public ICompressSetBufSize,
#ifndef NO_READ_FROM_CODER
public ICompressSetInStream,
public ICompressSetOutStreamSize,
@@ -32,6 +33,11 @@ class CDecoder:
UInt64 _inSizeProcessed;
UInt64 _outSizeProcessed;
UInt32 _inBufSizeAllocated;
UInt32 _inBufSize;
UInt32 _outBufSize;
SizeT _wrPos;
HRESULT CreateInputBuffer();
HRESULT CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress);
void SetOutStreamSizeResume(const UInt64 *outSize);
@@ -39,6 +45,7 @@ class CDecoder:
public:
MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2)
MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize)
#ifndef NO_READ_FROM_CODER
MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)
@@ -51,6 +58,8 @@ public:
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);
STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);
#ifndef NO_READ_FROM_CODER
@@ -68,7 +77,6 @@ public:
CDecoder();
virtual ~CDecoder();
};
}}

View File

@@ -1,5 +1,5 @@
// PpmdZip.cpp
// 2010-03-11 : Igor Pavlov : Public domain
// 2010-03-24 : Igor Pavlov : Public domain
#include "StdAfx.h"

View File

@@ -4,8 +4,6 @@
#ifndef __COMPRESS_PPMD_ZIP_H
#define __COMPRESS_PPMD_ZIP_H
#include "StdAfx.h"
#include "../../../C/Alloc.h"
#include "../../../C/Ppmd8.h"

View File

@@ -11,8 +11,9 @@
07 IFileExtractCallback.h::IFolderArchiveExtractCallback
0A IOutFolderArchive
0B IFolderArchiveUpdateCallback
0<EFBFBD> Agent.h::IArchiveFolderInternal
0D IInFolderArchive
0C Agent.h::IArchiveFolderInternal
0D
0E IInFolderArchive
03 IStream.h
@@ -40,6 +41,7 @@
32 ICompressSetOutStream
33 ICompressSetInStreamSize
34 ICompressSetOutStreamSize
35 ICompressSetBufSize
40 ICompressFilter
60 ICompressCodecsInfo
61 ISetCompressCodecsInfo
@@ -88,24 +90,24 @@
09 IFolderClone
0A IFolderSetFlatMode
0B IFolderOperationsExtractCallback
0C IFolderArchiveProperties
0D IGetFolderArchiveProperties
0C //
0D //
0E IFolderProperties
0F
10 IFolderArcProps
11 IGetFolderArcProps
09 IFolder.h :: FOLDER_MANAGER_INTERFACE
00 - 03 // old IFolderManager
04 IFolderManager
00 - 04 // old IFolderManager
05 IFolderManager
------------------
{23170F69-40C1-278D-0000-000100010000} PluginInterface::IInitContextMenu
{23170F69-40C1-278D-0000-000100020100} PluginInterface::IPluginOptionsCallback
{23170F69-40C1-278D-0000-000100020000} PluginInterface::IPluginOptions
// 0A PluginInterface.h
00 IInitContextMenu
01 IPluginOptionsCallback
02 IPluginOptions
Handler GUIDs:

View File

@@ -107,6 +107,12 @@ CODER_INTERFACE(ICompressSetOutStreamSize, 0x34)
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE;
};
CODER_INTERFACE(ICompressSetBufSize, 0x35)
{
STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size) PURE;
STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size) PURE;
};
CODER_INTERFACE(ICompressFilter, 0x40)
{
STDMETHOD(Init)() PURE;

View File

@@ -1,8 +1,8 @@
#define MY_VER_MAJOR 9
#define MY_VER_MINOR 11
#define MY_VER_MINOR 15
#define MY_VER_BUILD 0
#define MY_VERSION "9.11 beta"
#define MY_7ZIP_VERSION "7-Zip 9.11 beta"
#define MY_DATE "2010-03-15"
#define MY_VERSION "9.15 beta"
#define MY_7ZIP_VERSION "7-Zip 9.15 beta"
#define MY_DATE "2010-06-20"
#define MY_COPYRIGHT "Copyright (c) 1999-2010 Igor Pavlov"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE

View File

@@ -278,15 +278,15 @@ struct CArchiveItemPropertyTemp
VARTYPE Type;
};
STDMETHODIMP CAgentFolder::GetNumberOfProperties(UInt32 *numProperties)
STDMETHODIMP CAgentFolder::GetNumberOfProperties(UInt32 *numProps)
{
COM_TRY_BEGIN
RINOK(_agentSpec->GetArchive()->GetNumberOfProperties(numProperties));
*numProperties += kNumProperties;
RINOK(_agentSpec->GetArchive()->GetNumberOfProperties(numProps));
*numProps += kNumProperties;
if (!_flatMode)
(*numProperties)--;
(*numProps)--;
if (!_agentSpec->_proxyArchive->ThereIsPathProp)
(*numProperties)++;
(*numProps)++;
return S_OK;
COM_TRY_END
}
@@ -294,8 +294,8 @@ STDMETHODIMP CAgentFolder::GetNumberOfProperties(UInt32 *numProperties)
STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)
{
COM_TRY_BEGIN
UInt32 numProperties;
_agentSpec->GetArchive()->GetNumberOfProperties(&numProperties);
UInt32 numProps;
_agentSpec->GetArchive()->GetNumberOfProperties(&numProps);
if (!_agentSpec->_proxyArchive->ThereIsPathProp)
{
if (index == 0)
@@ -308,7 +308,7 @@ STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *pro
index--;
}
if (index < numProperties)
if (index < numProps)
{
RINOK(_agentSpec->GetArchive()->GetPropertyInfo(index, name, propID, varType));
if (*propID == kpidPath)
@@ -316,7 +316,7 @@ STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *pro
}
else
{
const STATPROPSTG &srcItem = kProperties[index - numProperties];
const STATPROPSTG &srcItem = kProperties[index - numProps];
*propID = srcItem.propid;
*varType = srcItem.vt;
*name = 0;
@@ -356,9 +356,9 @@ STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
COM_TRY_END
}
STDMETHODIMP CAgentFolder::GetNumberOfFolderProperties(UInt32 *numProperties)
STDMETHODIMP CAgentFolder::GetNumberOfFolderProperties(UInt32 *numProps)
{
*numProperties = kNumFolderProps;
*numProps = kNumFolderProps;
return S_OK;
}
@@ -374,9 +374,9 @@ STDMETHODIMP CAgentFolder::GetFolderPropertyInfo(UInt32 index, BSTR *name, PROPI
}
}
STDMETHODIMP CAgentFolder::GetFolderArchiveProperties(IFolderArchiveProperties **object)
STDMETHODIMP CAgentFolder::GetFolderArcProps(IFolderArcProps **object)
{
CMyComPtr<IFolderArchiveProperties> temp = _agentSpec;
CMyComPtr<IFolderArcProps> temp = _agentSpec;
*object = temp.Detach();
return S_OK;
}
@@ -468,6 +468,7 @@ CAgent::~CAgent()
STDMETHODIMP CAgent::Open(
IInStream *inStream,
const wchar_t *filePath,
const wchar_t *arcFormat,
BSTR *archiveType,
IArchiveOpenCallback *openArchiveCallback)
{
@@ -488,7 +489,11 @@ STDMETHODIMP CAgent::Open(
_compressCodecsInfo = _codecs;
RINOK(_codecs->Load());
RINOK(_archiveLink.Open(_codecs, CIntVector(), false, inStream, _archiveFilePath, openArchiveCallback));
CIntVector formatIndices;
if (!_codecs->FindFormatForArchiveType(arcFormat, formatIndices))
return S_FALSE;
RINOK(_archiveLink.Open(_codecs, formatIndices, false, inStream, _archiveFilePath, openArchiveCallback));
CArc &arc = _archiveLink.Arcs.Back();
if (!inStream)
@@ -573,10 +578,10 @@ STDMETHODIMP CAgent::Extract(
COM_TRY_END
}
STDMETHODIMP CAgent::GetNumberOfProperties(UInt32 *numProperties)
STDMETHODIMP CAgent::GetNumberOfProperties(UInt32 *numProps)
{
COM_TRY_BEGIN
return GetArchive()->GetNumberOfProperties(numProperties);
return GetArchive()->GetNumberOfProperties(numProps);
COM_TRY_END
}
@@ -591,25 +596,50 @@ STDMETHODIMP CAgent::GetPropertyInfo(UInt32 index,
COM_TRY_END
}
STDMETHODIMP CAgent::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
STDMETHODIMP CAgent::GetArcNumLevels(UInt32 *numLevels)
{
*numLevels = _archiveLink.Arcs.Size();
return S_OK;
}
STDMETHODIMP CAgent::GetArcProp(UInt32 level, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
return GetArchive()->GetArchiveProperty(propID, value);
NWindows::NCOM::CPropVariant prop;
CArc &arc = _archiveLink.Arcs[level];
switch(propID)
{
case kpidType: prop = _codecs->Formats[arc.FormatIndex].Name; break;
case kpidPath: prop = arc.Path; break;
default: return arc.Archive->GetArchiveProperty(propID, value);
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
STDMETHODIMP CAgent::GetNumberOfArchiveProperties(UInt32 *numProperties)
STDMETHODIMP CAgent::GetArcNumProps(UInt32 level, UInt32 *numProps)
{
COM_TRY_BEGIN
return GetArchive()->GetNumberOfArchiveProperties(numProperties);
COM_TRY_END
return _archiveLink.Arcs[level].Archive->GetNumberOfArchiveProperties(numProps);
}
STDMETHODIMP CAgent::GetArchivePropertyInfo(UInt32 index,
BSTR *name, PROPID *propID, VARTYPE *varType)
STDMETHODIMP CAgent::GetArcPropInfo(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)
{
COM_TRY_BEGIN
return GetArchive()->GetArchivePropertyInfo(index,
name, propID, varType);
COM_TRY_END
return _archiveLink.Arcs[level].Archive->GetArchivePropertyInfo(index, name, propID, varType);
}
// MainItemProperty
STDMETHODIMP CAgent::GetArcProp2(UInt32 level, PROPID propID, PROPVARIANT *value)
{
return _archiveLink.Arcs[level - 1].Archive->GetProperty(_archiveLink.Arcs[level].SubfileIndex, propID, value);
}
STDMETHODIMP CAgent::GetArcNumProps2(UInt32 level, UInt32 *numProps)
{
return _archiveLink.Arcs[level - 1].Archive->GetNumberOfProperties(numProps);
}
STDMETHODIMP CAgent::GetArcPropInfo2(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)
{
return _archiveLink.Arcs[level - 1].Archive->GetPropertyInfo(index, name, propID, varType);
}

View File

@@ -36,7 +36,7 @@ class CAgent;
class CAgentFolder:
public IFolderFolder,
public IFolderProperties,
public IGetFolderArchiveProperties,
public IGetFolderArcProps,
public IArchiveFolder,
public IArchiveFolderInternal,
public IInArchiveGetStream,
@@ -50,7 +50,7 @@ public:
MY_QUERYINTERFACE_BEGIN2(IFolderFolder)
MY_QUERYINTERFACE_ENTRY(IFolderProperties)
MY_QUERYINTERFACE_ENTRY(IGetFolderArchiveProperties)
MY_QUERYINTERFACE_ENTRY(IGetFolderArcProps)
MY_QUERYINTERFACE_ENTRY(IArchiveFolder)
MY_QUERYINTERFACE_ENTRY(IArchiveFolderInternal)
MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream)
@@ -68,7 +68,7 @@ public:
INTERFACE_FolderFolder(;)
INTERFACE_FolderProperties(;)
STDMETHOD(GetFolderArchiveProperties)(IFolderArchiveProperties **object);
STDMETHOD(GetFolderArcProps)(IFolderArcProps **object);
// IArchiveFolder
STDMETHOD(Extract)(const UINT32 *indices, UINT32 numItems,
@@ -132,7 +132,7 @@ private:
class CAgent:
public IInFolderArchive,
public IFolderArchiveProperties,
public IFolderArcProps,
#ifndef EXTRACT_ONLY
public IOutFolderArchive,
public ISetProperties,
@@ -142,7 +142,7 @@ class CAgent:
public:
MY_QUERYINTERFACE_BEGIN2(IInFolderArchive)
MY_QUERYINTERFACE_ENTRY(IFolderArchiveProperties)
MY_QUERYINTERFACE_ENTRY(IFolderArcProps)
#ifndef EXTRACT_ONLY
MY_QUERYINTERFACE_ENTRY(IOutFolderArchive)
MY_QUERYINTERFACE_ENTRY(ISetProperties)
@@ -151,7 +151,7 @@ public:
MY_ADDREF_RELEASE
INTERFACE_IInFolderArchive(;)
INTERFACE_IFolderArchiveProperties(;)
INTERFACE_IFolderArcProps(;)
#ifndef EXTRACT_ONLY
INTERFACE_IOutFolderArchive(;)

View File

@@ -34,7 +34,8 @@ int CArchiveFolderManager::FindFormat(const UString &type)
return -1;
}
STDMETHODIMP CArchiveFolderManager::OpenFolderFile(IInStream *inStream, const wchar_t *filePath,
STDMETHODIMP CArchiveFolderManager::OpenFolderFile(IInStream *inStream,
const wchar_t *filePath, const wchar_t *arcFormat,
IFolderFolder **resultFolder, IProgress *progress)
{
CMyComPtr<IArchiveOpenCallback> openArchiveCallback;
@@ -45,7 +46,7 @@ STDMETHODIMP CArchiveFolderManager::OpenFolderFile(IInStream *inStream, const wc
}
CAgent *agent = new CAgent();
CMyComPtr<IInFolderArchive> archive = agent;
RINOK(agent->Open(inStream, filePath, NULL, openArchiveCallback));
RINOK(agent->Open(inStream, filePath, arcFormat, NULL, openArchiveCallback));
return agent->BindToRootFolder(resultFolder);
}

View File

@@ -27,7 +27,7 @@ FOLDER_ARCHIVE_INTERFACE(IArchiveFolder, 0x05)
};
#define INTERFACE_IInFolderArchive(x) \
STDMETHOD(Open)(IInStream *inStream, const wchar_t *filePath, BSTR *archiveType, IArchiveOpenCallback *openArchiveCallback) x; \
STDMETHOD(Open)(IInStream *inStream, const wchar_t *filePath, const wchar_t *arcFormat, BSTR *archiveTypeRes, IArchiveOpenCallback *openArchiveCallback) x; \
STDMETHOD(ReOpen)(IArchiveOpenCallback *openArchiveCallback) x; \
STDMETHOD(Close)() x; \
STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \
@@ -37,7 +37,7 @@ FOLDER_ARCHIVE_INTERFACE(IArchiveFolder, 0x05)
NExtract::NOverwriteMode::EEnum overwriteMode, const wchar_t *path, \
Int32 testMode, IFolderArchiveExtractCallback *extractCallback2) x; \
FOLDER_ARCHIVE_INTERFACE(IInFolderArchive, 0x0D)
FOLDER_ARCHIVE_INTERFACE(IInFolderArchive, 0x0E)
{
INTERFACE_IInFolderArchive(PURE)
};

View File

@@ -696,9 +696,13 @@ HRESULT LzmaBench(
const UInt32 kLzmaId = 0x030101;
RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS kLzmaId, encoder.encoder, true));
if (!encoder.encoder)
return E_NOTIMPL;
for (UInt32 j = 0; j < numSubDecoderThreads; j++)
{
RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS kLzmaId, encoder.decoders[j], false));
if (!encoder.decoders[j])
return E_NOTIMPL;
}
}

View File

@@ -24,6 +24,27 @@ void ConvertUInt32ToHex(UInt32 value, wchar_t *s)
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'-';
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)
break;
UString res;
UInt32 a = prop.ulVal;
if (NFile::NFind::NAttributes::IsReadOnly(a)) res += L'R';
if (NFile::NFind::NAttributes::IsHidden(a)) res += L'H';
if (NFile::NFind::NAttributes::IsSystem(a)) res += L'S';
if (NFile::NFind::NAttributes::IsDir(a)) res += L'D';
if (NFile::NFind::NAttributes::IsArchived(a)) res += L'A';
if (NFile::NFind::NAttributes::IsCompressed(a)) res += L'C';
if (NFile::NFind::NAttributes::IsEncrypted(a)) res += L'E';
return res;
wchar_t sz[32];
int pos = 0;
for (int i = 0; i < 16; i++)
if (a & (1 << i) && i != 7)
sz[pos++] = g_WinAttrib[i];
sz[pos] = '\0';
return sz;
}
case kpidPosixAttrib:
{

View File

@@ -160,6 +160,14 @@ SOURCE=.\StdAfx.h
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\BenchCon.cpp
# End Source File
# Begin Source File
SOURCE=.\BenchCon.h
# End Source File
# Begin Source File
SOURCE=.\ConsoleClose.cpp
# End Source File
# Begin Source File
@@ -184,14 +192,6 @@ SOURCE=.\List.h
# End Source File
# Begin Source File
SOURCE=.\BenchCon.cpp
# End Source File
# Begin Source File
SOURCE=.\BenchCon.h
# End Source File
# Begin Source File
SOURCE=.\Main.cpp
# End Source File
# Begin Source File
@@ -364,10 +364,6 @@ SOURCE=..\..\..\Common\Defs.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Exception.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\IntToString.cpp
# End Source File
# Begin Source File
@@ -488,7 +484,11 @@ SOURCE=..\Common\ArchiveOpenCallback.h
# End Source File
# Begin Source File
SOURCE=..\Common\CompressionMode.h
SOURCE=..\Common\Bench.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\Bench.h
# End Source File
# Begin Source File
@@ -532,10 +532,6 @@ SOURCE=..\Common\ExtractingFilePath.h
# End Source File
# Begin Source File
SOURCE=..\Common\HandlerLoader.h
# End Source File
# Begin Source File
SOURCE=..\Common\IFileExtractCallback.h
# End Source File
# Begin Source File
@@ -548,14 +544,6 @@ SOURCE=..\Common\LoadCodecs.h
# End Source File
# Begin Source File
SOURCE=..\Common\Bench.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\Bench.h
# End Source File
# Begin Source File
SOURCE=..\Common\OpenArchive.cpp
# End Source File
# Begin Source File

View File

@@ -502,7 +502,7 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices,
{
const CArc &arc = archiveLink.Arcs[i];
g_StdOut << "----\n";
g_StdOut << "--\n";
PrintPropPair(L"Path", arc.Path);
PrintPropPair(L"Type", codecs->Formats[arc.FormatIndex].Name);
UInt32 numProps;
@@ -514,16 +514,36 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices,
CMyComBSTR name;
PROPID propID;
VARTYPE vt;
if (archive->GetArchivePropertyInfo(j, &name, &propID, &vt) != S_OK)
continue;
RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt));
NCOM::CPropVariant prop;
if (archive->GetArchiveProperty(propID, &prop) != S_OK)
continue;
RINOK(archive->GetArchiveProperty(propID, &prop));
UString s = ConvertPropertyToString(prop, propID);
if (!s.IsEmpty())
PrintPropPair(GetPropName(propID, name), s);
}
}
if (i != archiveLink.Arcs.Size() - 1)
{
UInt32 numProps;
g_StdOut << "----\n";
if (archive->GetNumberOfProperties(&numProps) == S_OK)
{
UInt32 mainIndex = archiveLink.Arcs[i + 1].SubfileIndex;
for (UInt32 j = 0; j < numProps; j++)
{
CMyComBSTR name;
PROPID propID;
VARTYPE vt;
RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt));
NCOM::CPropVariant prop;
RINOK(archive->GetProperty(mainIndex, propID, &prop));
UString s = ConvertPropertyToString(prop, propID);
if (!s.IsEmpty())
PrintPropPair(GetPropName(propID, name), s);
}
}
}
}
g_StdOut << endl;
if (techMode)

View File

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

View File

@@ -94,11 +94,10 @@ STDMETHODIMP CZipContextMenu::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT
return GetFileNames(dataObject, _fileNames);
}
STDMETHODIMP CZipContextMenu::InitContextMenu(const wchar_t * /* folder */,
const wchar_t **names, UINT32 numFiles)
HRESULT CZipContextMenu::InitContextMenu(const wchar_t * /* folder */, const wchar_t **names, UInt32 numFiles)
{
_fileNames.Clear();
for (UINT32 i = 0; i < numFiles; i++)
for (UInt32 i = 0; i < numFiles; i++)
_fileNames.Add(names[i]);
_dropMode = false;
return S_OK;
@@ -124,12 +123,12 @@ static LPCTSTR kCompressToEmailVerb = TEXT("SevenCompressToEmail");
struct CContextMenuCommand
{
UINT32 flag;
UInt32 flag;
CZipContextMenu::ECommandInternalID CommandInternalID;
LPCWSTR Verb;
UINT ResourceID;
UINT ResourceHelpID;
UINT32 LangID;
UInt32 LangID;
};
static CContextMenuCommand g_Commands[] =
@@ -224,7 +223,7 @@ static CContextMenuCommand g_Commands[] =
}
};
int FindCommand(CZipContextMenu::ECommandInternalID &id)
static int FindCommand(CZipContextMenu::ECommandInternalID &id)
{
for (int i = 0; i < sizeof(g_Commands) / sizeof(g_Commands[0]); i++)
if (g_Commands[i].CommandInternalID == id)
@@ -336,6 +335,9 @@ static const char *kExtractExludeExtensions =
" xml xsd xsl xslt"
" ";
static const char *kNoOpenAsExtensions =
" 7z arj bz2 cab chm cpio dmg flv gz lha lzh lzma rar swm tar tbz2 tgz wim xar xz z zip ";
static bool FindExt(const char *p, const UString &name)
{
int extPos = name.ReverseFind('.');
@@ -415,19 +417,22 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
if (!fileInfo.IsDir() && DoNeedExtract(fileInfo.Name))
{
// Open
if ((contextMenuFlags & NContextMenuFlags::kOpen) != 0)
bool thereIsMainOpenItem = ((contextMenuFlags & NContextMenuFlags::kOpen) != 0);
if (thereIsMainOpenItem)
{
CCommandMapItem commandMapItem;
FillCommand(kOpen, mainString, commandMapItem);
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
_commandMap.Add(commandMapItem);
/*
if (FindExt(" exe dll ", fileInfo.Name))
}
if ((contextMenuFlags & NContextMenuFlags::kOpenAs) != 0 &&
(!thereIsMainOpenItem || !FindExt(kNoOpenAsExtensions, fileInfo.Name)))
{
CMenu subMenu;
if (subMenu.CreatePopup())
{
CCommandMapItem commandMapItem;
CMenuItem menuItem;
menuItem.fType = MFT_STRING;
menuItem.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID;
@@ -435,21 +440,33 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
menuItem.hSubMenu = subMenu;
menuItem.StringValue = LangString(IDS_CONTEXT_OPEN, 0x02000103);
popupMenu.InsertItem(subIndex++, true, menuItem);
const wchar_t *exts[] = { L"7z", L"cab", L"rar", L"zip", L"pe" };
for (int i = 0; i < sizeof(exts) / sizeof(exts[0]); i++)
commandMapItem.CommandInternalID = kCommandNULL;
commandMapItem.Verb = kMainVerb;
commandMapItem.HelpString = LangString(IDS_CONTEXT_OPEN_HELP, 0x02000104);
_commandMap.Add(commandMapItem);
UINT subIndex2 = 0;
const wchar_t *exts[] = { L"", L"*", L"7z", L"zip", L"cab", L"rar" };
for (int i = (thereIsMainOpenItem ? 1 : 0); i < sizeof(exts) / sizeof(exts[0]); i++)
{
CCommandMapItem commandMapItem;
FillCommand(kOpenAs, mainString, commandMapItem);
if (i == 0)
FillCommand(kOpen, mainString, commandMapItem);
else
{
mainString = exts[i];
commandMapItem.ArchiveType = mainString;
MyInsertMenu(subMenu, subIndex++, currentCommandID++, mainString);
commandMapItem.CommandInternalID = kOpen;
commandMapItem.Verb = (UString)kMainVerb + L".Open." + mainString;
commandMapItem.HelpString = mainString;
commandMapItem.ArcType = mainString;
}
MyInsertMenu(subMenu, subIndex2++, currentCommandID++, mainString);
_commandMap.Add(commandMapItem);
}
subMenu.Detach();
}
}
*/
}
}
}
@@ -542,7 +559,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
commandMapItem.Folder = _dropPath;
else
commandMapItem.Folder = archivePathPrefix;
commandMapItem.Archive = archiveName;
commandMapItem.ArcName = archiveName;
FillCommand(kCompress, mainString, commandMapItem);
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
_commandMap.Add(commandMapItem);
@@ -553,7 +570,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
if ((contextMenuFlags & NContextMenuFlags::kCompressEmail) != 0 && !_dropMode)
{
CCommandMapItem commandMapItem;
commandMapItem.Archive = archiveName;
commandMapItem.ArcName = archiveName;
FillCommand(kCompressEmail, mainString, commandMapItem);
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
_commandMap.Add(commandMapItem);
@@ -570,8 +587,8 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
commandMapItem.Folder = _dropPath;
else
commandMapItem.Folder = archivePathPrefix;
commandMapItem.Archive = archiveName7z;
commandMapItem.ArchiveType = L"7z";
commandMapItem.ArcName = archiveName7z;
commandMapItem.ArcType = L"7z";
s = MyFormatNew(s, GetQuotedReducedString(archiveName7z));
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);
_commandMap.Add(commandMapItem);
@@ -584,8 +601,8 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
CCommandMapItem commandMapItem;
UString s;
FillCommand(kCompressTo7zEmail, s, commandMapItem);
commandMapItem.Archive = archiveName7z;
commandMapItem.ArchiveType = L"7z";
commandMapItem.ArcName = archiveName7z;
commandMapItem.ArcType = L"7z";
s = MyFormatNew(s, GetQuotedReducedString(archiveName7z));
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);
_commandMap.Add(commandMapItem);
@@ -602,8 +619,8 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
commandMapItem.Folder = _dropPath;
else
commandMapItem.Folder = archivePathPrefix;
commandMapItem.Archive = archiveNameZip;
commandMapItem.ArchiveType = L"zip";
commandMapItem.ArcName = archiveNameZip;
commandMapItem.ArcType = L"zip";
s = MyFormatNew(s, GetQuotedReducedString(archiveNameZip));
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);
_commandMap.Add(commandMapItem);
@@ -616,8 +633,8 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
CCommandMapItem commandMapItem;
UString s;
FillCommand(kCompressToZipEmail, s, commandMapItem);
commandMapItem.Archive = archiveNameZip;
commandMapItem.ArchiveType = L"zip";
commandMapItem.ArcName = archiveNameZip;
commandMapItem.ArcType = L"zip";
s = MyFormatNew(s, GetQuotedReducedString(archiveNameZip));
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);
_commandMap.Add(commandMapItem);
@@ -691,15 +708,21 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo)
return E_FAIL;
const CCommandMapItem commandMapItem = _commandMap[commandOffset];
ECommandInternalID commandInternalID = commandMapItem.CommandInternalID;
ECommandInternalID cmdID = commandMapItem.CommandInternalID;
try
{
switch(commandInternalID)
switch(cmdID)
{
case kOpen:
{
UString params = GetQuotedString(_fileNames[0]);
UString params;
params = GetQuotedString(_fileNames[0]);
if (commandMapItem.ArcType)
{
params += L" -t";
params += commandMapItem.ArcType;
}
MyCreateProcess(Get7zFmPath(), params);
break;
}
@@ -707,7 +730,7 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo)
case kExtractHere:
case kExtractTo:
{
ExtractArchives(_fileNames, commandMapItem.Folder, (commandInternalID == kExtract));
ExtractArchives(_fileNames, commandMapItem.Folder, (cmdID == kExtract));
break;
}
case kTest:
@@ -723,14 +746,14 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo)
case kCompressToZipEmail:
{
bool email =
(commandInternalID == kCompressEmail) ||
(commandInternalID == kCompressTo7zEmail) ||
(commandInternalID == kCompressToZipEmail);
(cmdID == kCompressEmail) ||
(cmdID == kCompressTo7zEmail) ||
(cmdID == kCompressToZipEmail);
bool showDialog =
(commandInternalID == kCompress) ||
(commandInternalID == kCompressEmail);
(cmdID == kCompress) ||
(cmdID == kCompressEmail);
CompressFiles(commandMapItem.Folder,
commandMapItem.Archive, commandMapItem.ArchiveType,
commandMapItem.ArcName, commandMapItem.ArcType,
_fileNames, email, showDialog, false);
break;
}

View File

@@ -3,20 +3,13 @@
#ifndef __CONTEXT_MENU_H
#define __CONTEXT_MENU_H
// {23170F69-40C1-278A-1000-000100020000}
DEFINE_GUID(CLSID_CZipContextMenu,
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00);
#include "Common/MyString.h"
#include "../FileManager/PluginInterface.h"
#include "../FileManager/MyCom2.h"
class CZipContextMenu:
public IContextMenu,
public IShellExtInit,
public IInitContextMenu,
public CMyUnknownImp
{
public:
@@ -37,17 +30,7 @@ public:
kCompressToZipEmail
};
struct CCommandMapItem
{
ECommandInternalID CommandInternalID;
UString Verb;
UString HelpString;
UString Folder;
UString Archive;
UString ArchiveType;
};
MY_UNKNOWN_IMP3_MT(IContextMenu, IShellExtInit, IInitContextMenu)
MY_UNKNOWN_IMP2_MT(IContextMenu, IShellExtInit)
// IShellExtInit
STDMETHOD(Initialize)(LPCITEMIDLIST pidlFolder, LPDATAOBJECT dataObject, HKEY hkeyProgID);
@@ -57,22 +40,31 @@ public:
STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO lpici);
STDMETHOD(GetCommandString)(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax);
// IInitContextMenu
STDMETHOD(InitContextMenu)(const wchar_t *folder, const wchar_t **names, UINT32 numFiles);
HRESULT InitContextMenu(const wchar_t *folder, const wchar_t **names, UINT32 numFiles);
CZipContextMenu();
~CZipContextMenu();
private:
struct CCommandMapItem
{
ECommandInternalID CommandInternalID;
UString Verb;
UString HelpString;
UString Folder;
UString ArcName;
UString ArcType;
};
UStringVector _fileNames;
bool _dropMode;
UString _dropPath;
CObjectVector<CCommandMapItem> _commandMap;
HRESULT GetFileNames(LPDATAOBJECT dataObject, UStringVector &fileNames);
int FindVerb(const UString &verb);
void FillCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &commandMapItem);
public:
CZipContextMenu();
~CZipContextMenu();
};
#endif

View File

@@ -1,34 +1,24 @@
// ContextMenuFlags.h
#ifndef __SEVENZIP_CONTEXTMENUFLAGS_H
#define __SEVENZIP_CONTEXTMENUFLAGS_H
#ifndef __CONTEXT_MENU_FLAGS_H
#define __CONTEXT_MENU_FLAGS_H
namespace NContextMenuFlags
{
const UINT32 kExtract = 1 << 0;
const UINT32 kExtractHere = 1 << 1;
const UINT32 kExtractTo = 1 << 2;
// const UINT32 kExtractEach = 1 << 3;
const UInt32 kExtract = 1 << 0;
const UInt32 kExtractHere = 1 << 1;
const UInt32 kExtractTo = 1 << 2;
const UINT32 kTest = 1 << 4;
const UInt32 kTest = 1 << 4;
const UInt32 kOpen = 1 << 5;
const UInt32 kOpenAs = 1 << 6;
const UINT32 kOpen = 1 << 5;
const UINT32 kCompress = 1 << 8;
const UINT32 kCompressTo7z = 1 << 9;
const UINT32 kCompressEmail = 1 << 10;
const UINT32 kCompressTo7zEmail = 1 << 11;
const UINT32 kCompressToZip = 1 << 12;
const UINT32 kCompressToZipEmail = 1 << 13;
inline UINT32 GetDefaultFlags() {
return
kOpen | kTest |
kExtract | kExtractHere | kExtractTo |
kCompress | kCompressEmail |
kCompressTo7z | kCompressTo7zEmail |
kCompressToZip | kCompressToZipEmail; }
const UInt32 kCompress = 1 << 8;
const UInt32 kCompressTo7z = 1 << 9;
const UInt32 kCompressEmail = 1 << 10;
const UInt32 kCompressTo7zEmail = 1 << 11;
const UInt32 kCompressToZip = 1 << 12;
const UInt32 kCompressToZipEmail = 1 << 13;
}
#endif

View File

@@ -26,6 +26,10 @@
#include "ContextMenu.h"
// {23170F69-40C1-278A-1000-000100020000}
DEFINE_GUID(CLSID_CZipContextMenu,
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00);
using namespace NWindows;
HINSTANCE g_hInstance = 0;

View File

@@ -365,7 +365,7 @@ static HANDLE MyOpenFilePlugin(const char *name)
archiveHandler = new CAgent;
CMyComBSTR archiveType;
HRESULT result = archiveHandler->Open(NULL,
GetUnicodeString(fullName, CP_OEMCP), &archiveType, openArchiveCallback);
GetUnicodeString(fullName, CP_OEMCP), UString(), &archiveType, openArchiveCallback);
/*
HRESULT result = ::OpenArchive(fullName, &archiveHandler,
archiverInfoResult, defaultName, openArchiveCallback);

View File

@@ -20,6 +20,7 @@ enum EEnum
kYes,
kNo,
kPath,
kName,
kExtension,
kIsFolder,

View File

@@ -275,6 +275,7 @@ struct CPROPIDToName
static CPROPIDToName kPROPIDToName[] =
{
{ kpidPath, NMessageID::kPath },
{ kpidName, NMessageID::kName },
{ kpidExtension, NMessageID::kExtension },
{ kpidIsDir, NMessageID::kIsFolder },
@@ -501,6 +502,32 @@ static AString PropToString2(const NCOM::CPropVariant &prop, PROPID propID)
return s;
}
static void AddPropertyString(InfoPanelLine *lines, int &numItems, PROPID propID, const wchar_t *name,
const NCOM::CPropVariant &prop)
{
if (prop.vt != VT_EMPTY)
{
AString val = PropToString2(prop, propID);
if (!val.IsEmpty())
{
InfoPanelLine &item = lines[numItems++];
COPY_STR_LIMITED(item.Text, GetNameOfProp2(propID, name));
COPY_STR_LIMITED(item.Data, val);
}
}
}
static void InsertSeparator(InfoPanelLine *lines, int &numItems)
{
if (numItems < kNumInfoLinesMax)
{
InfoPanelLine &item = lines[numItems++];
MyStringCopy(item.Text, "");
MyStringCopy(item.Data, "");
item.Separator = TRUE;
}
}
void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info)
{
info->StructSize = sizeof(*info);
@@ -574,44 +601,71 @@ void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info)
}
}
/*
if (numItems < kNumInfoLinesMax)
{
InfoPanelLine &item = m_InfoLines[numItems++];
MyStringCopy(item.Text, "");
MyStringCopy(item.Data, "");
item.Separator = TRUE;
InsertSeparator(m_InfoLines, numItems);
}
*/
{
CMyComPtr<IGetFolderArchiveProperties> getFolderArchiveProperties;
_folder.QueryInterface(IID_IGetFolderArchiveProperties, &getFolderArchiveProperties);
if (getFolderArchiveProperties)
CMyComPtr<IGetFolderArcProps> getFolderArcProps;
_folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps);
if (getFolderArcProps)
{
CMyComPtr<IFolderArchiveProperties> getProps;
getFolderArchiveProperties->GetFolderArchiveProperties(&getProps);
CMyComPtr<IFolderArcProps> getProps;
getFolderArcProps->GetFolderArcProps(&getProps);
if (getProps)
{
UInt32 numProps;
if (getProps->GetNumberOfArchiveProperties(&numProps) == S_OK)
UInt32 numLevels;
if (getProps->GetArcNumLevels(&numLevels) != S_OK)
numLevels = 0;
for (UInt32 level2 = 0; level2 < numLevels; level2++)
{
/*
if (numProps > 0)
message += kSeparator;
*/
for (UInt32 i = 0; i < numProps && numItems < kNumInfoLinesMax; i++)
{
UInt32 level = numLevels - 1 - level2;
UInt32 numProps;
if (getProps->GetArcNumProps(level, &numProps) == S_OK)
{
InsertSeparator(m_InfoLines, numItems);
for (Int32 i = -2; i < (Int32)numProps && numItems < kNumInfoLinesMax; i++)
{
CMyComBSTR name;
PROPID propID;
VARTYPE vt;
if (getProps->GetArchivePropertyInfo(i, &name, &propID, &vt) != S_OK)
if (i == -2)
propID = kpidPath;
else if (i == -1)
propID = kpidType;
else if (getProps->GetArcPropInfo(level, i, &name, &propID, &vt) != S_OK)
continue;
NCOM::CPropVariant prop;
if (getProps->GetArchiveProperty(propID, &prop) != S_OK || prop.vt == VT_EMPTY)
if (getProps->GetArcProp(level, propID, &prop) != S_OK)
continue;
InfoPanelLine &item = m_InfoLines[numItems++];
COPY_STR_LIMITED(item.Text, GetNameOfProp2(propID, name));
COPY_STR_LIMITED(item.Data, PropToString2(prop, propID));
AddPropertyString(m_InfoLines, numItems, propID, name, prop);
}
}
}
if (level2 != numLevels - 1)
{
UInt32 level = numLevels - 1 - level2;
UInt32 numProps;
if (getProps->GetArcNumProps2(level, &numProps) == S_OK)
{
InsertSeparator(m_InfoLines, numItems);
for (Int32 i = 0; i < (Int32)numProps && numItems < kNumInfoLinesMax; i++)
{
CMyComBSTR name;
PROPID propID;
VARTYPE vt;
if (getProps->GetArcPropInfo2(level, i, &name, &propID, &vt) != S_OK)
continue;
NCOM::CPropVariant prop;
if (getProps->GetArcProp2(level, propID, &prop) != S_OK)
continue;
AddPropertyString(m_InfoLines, numItems, propID, name, prop);
}
}
}
}
}

View File

@@ -692,7 +692,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
// CLSID realClassID;
CMyComBSTR archiveType;
RINOK(agentSpec->Open(NULL,
GetUnicodeString(fullArchiveName, CP_OEMCP),
GetUnicodeString(fullArchiveName, CP_OEMCP), UString(),
// &realClassID,
&archiveType,
NULL));

View File

@@ -21,6 +21,6 @@ CAPTION "About 7-Zip"
ICON IDI_LOGO, -1, m, m, 32, 32, SS_REALSIZEIMAGE
LTEXT MY_7ZIP_VERSION, -1, m, 54, xc, 8
LTEXT MY_COPYRIGHT, -1, m, 67, xc, 8
LTEXT "7-Zip is free software. However, you can support development of 7-Zip by registering.",
LTEXT "7-Zip is free software",
IDC_ABOUT_STATIC_REGISTER_INFO, m, y, xc, (by - y - 1)
}

View File

@@ -107,7 +107,8 @@ void CApp::SetShowSystemMenu()
#define ILC_COLOR32 0x0020
#endif
HRESULT CApp::CreateOnePanel(int panelIndex, const UString &mainPath, bool &archiveIsOpened, bool &encrypted)
HRESULT CApp::CreateOnePanel(int panelIndex, const UString &mainPath, const UString &arcFormat,
bool &archiveIsOpened, bool &encrypted)
{
if (PanelsCreated[panelIndex])
return S_OK;
@@ -122,7 +123,7 @@ HRESULT CApp::CreateOnePanel(int panelIndex, const UString &mainPath, bool &arch
path = mainPath;
int id = 1000 + 100 * panelIndex;
RINOK(Panels[panelIndex].Create(_window, _window,
id, path, &m_PanelCallbackImp[panelIndex], &AppState, archiveIsOpened, encrypted));
id, path, arcFormat, &m_PanelCallbackImp[panelIndex], &AppState, archiveIsOpened, encrypted));
PanelsCreated[panelIndex] = true;
return S_OK;
}
@@ -269,7 +270,7 @@ void CApp::SaveToolbarChanges()
void MyLoadMenu();
HRESULT CApp::Create(HWND hwnd, const UString &mainPath, int xSizes[2], bool &archiveIsOpened, bool &encrypted)
HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool &archiveIsOpened, bool &encrypted)
{
_window.Attach(hwnd);
#ifdef UNDER_CE
@@ -310,7 +311,7 @@ HRESULT CApp::Create(HWND hwnd, const UString &mainPath, int xSizes[2], bool &ar
bool archiveIsOpened2 = false;
bool encrypted2 = false;
bool mainPanel = (i == LastFocusedPanel);
RINOK(CreateOnePanel(i, mainPanel ? mainPath : L"", archiveIsOpened2, encrypted2));
RINOK(CreateOnePanel(i, mainPanel ? mainPath : L"", arcFormat, archiveIsOpened2, encrypted2));
if (mainPanel)
{
archiveIsOpened = archiveIsOpened2;
@@ -328,7 +329,7 @@ HRESULT CApp::SwitchOnOffOnePanel()
{
NumPanels++;
bool archiveIsOpened, encrypted;
RINOK(CreateOnePanel(1 - LastFocusedPanel, UString(), archiveIsOpened, encrypted));
RINOK(CreateOnePanel(1 - LastFocusedPanel, UString(), UString(), archiveIsOpened, encrypted));
Panels[1 - LastFocusedPanel].Enable(true);
Panels[1 - LastFocusedPanel].Show(SW_SHOWNORMAL);
}
@@ -596,8 +597,10 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
}
#endif
if (indices.Size() > 1 || (!destPath.IsEmpty() && destPath.Back() == WCHAR_PATH_SEPARATOR) ||
NFind::DoesDirExist(destPath))
if (indices.Size() > 1 ||
(!destPath.IsEmpty() && destPath.Back() == WCHAR_PATH_SEPARATOR) ||
NFind::DoesDirExist(destPath) ||
srcPanel.IsArcFolder())
{
NDirectory::CreateComplexDirectory(destPath);
NName::NormalizeDirPathPrefix(destPath);

View File

@@ -161,8 +161,8 @@ public:
void OnSetSameFolder(int srcPanelIndex);
void OnSetSubFolder(int srcPanelIndex);
HRESULT CreateOnePanel(int panelIndex, const UString &mainPath, bool &archiveIsOpened, bool &encrypted);
HRESULT Create(HWND hwnd, const UString &mainPath, int xSizes[2], bool &archiveIsOpened, bool &encrypted);
HRESULT CreateOnePanel(int panelIndex, const UString &mainPath, const UString &arcFormat, bool &archiveIsOpened, bool &encrypted);
HRESULT Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool &archiveIsOpened, bool &encrypted);
void Read();
void Save();
void Release();

View File

@@ -4,8 +4,4 @@
#include "Common/MyInitGuid.h"
#include "PluginInterface.h"
#include "../Agent/Agent.h"
DEFINE_GUID(CLSID_CZipContextMenu,
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00);

View File

@@ -37,6 +37,7 @@ HINSTANCE g_hInstance;
HWND g_HWND;
bool g_OpenArchive = false;
static UString g_MainPath;
static UString g_ArcFormat;
static bool g_Maximized = false;
#ifndef UNDER_CE
@@ -443,7 +444,9 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
UString paramString, tailString;
SplitStringToTwoStrings(commandsString, paramString, tailString);
paramString.Trim();
tailString.Trim();
if (tailString.Left(2) == L"-t")
g_ArcFormat = tailString.Mid(2);
if (!paramString.IsEmpty())
{
g_MainPath = paramString;
@@ -639,7 +642,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
if (NFile::NFind::DoesFileExist(g_MainPath))
needOpenFile = true;
}
HRESULT res = g_App.Create(hWnd, g_MainPath, xSizes, archiveIsOpened, encrypted);
HRESULT res = g_App.Create(hWnd, g_MainPath, g_ArcFormat, xSizes, archiveIsOpened, encrypted);
if (res == E_ABORT)
{

View File

@@ -442,14 +442,6 @@ SOURCE=.\OptionsDialog.cpp
# End Source File
# Begin Source File
SOURCE=.\PluginsPage.cpp
# End Source File
# Begin Source File
SOURCE=.\PluginsPage.h
# End Source File
# Begin Source File
SOURCE=.\SettingsPage.cpp
# End Source File
# Begin Source File

View File

@@ -20,6 +20,7 @@ using namespace NRegistryAssociations;
struct CThreadArchiveOpen
{
UString Path;
UString ArcFormat;
CMyComPtr<IInStream> InStream;
CMyComPtr<IFolderManager> FolderManager;
CMyComPtr<IProgress> OpenCallback;
@@ -33,7 +34,7 @@ struct CThreadArchiveOpen
try
{
CProgressCloser closer(OpenCallbackSpec->ProgressDialog);
Result = FolderManager->OpenFolderFile(InStream, Path, &Folder, OpenCallback);
Result = FolderManager->OpenFolderFile(InStream, Path, ArcFormat, &Folder, OpenCallback);
}
catch(...) { Result = E_FAIL; }
}
@@ -58,6 +59,7 @@ static int FindPlugin(const CObjectVector<CPluginInfo> &plugins, const UString &
HRESULT OpenFileFolderPlugin(
IInStream *inStream,
const UString &path,
const UString &arcFormat,
HMODULE *module,
IFolderFolder **resultFolder,
HWND parentWindow,
@@ -128,6 +130,7 @@ HRESULT OpenFileFolderPlugin(
t.InStream = inStream;
t.Path = path;
t.ArcFormat = arcFormat;
UString progressTitle = LangString(IDS_OPENNING, 0x03020283);
t.OpenCallbackSpec->ProgressDialog.MainWindow = parentWindow;

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