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_MAJOR 9
#define MY_VER_MINOR 11 #define MY_VER_MINOR 15
#define MY_VER_BUILD 0 #define MY_VER_BUILD 0
#define MY_VERSION "9.11 beta" #define MY_VERSION "9.15 beta"
#define MY_DATE "2010-03-15" #define MY_DATE "2010-06-20"
#define MY_COPYRIGHT ": Igor Pavlov : Public domain" #define MY_COPYRIGHT ": Igor Pavlov : Public domain"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/* Lzma2Enc.c -- LZMA2 Encoder /* Lzma2Enc.c -- LZMA2 Encoder
2009-11-24 : Igor Pavlov : Public domain */ 2010-04-16 : Igor Pavlov : Public domain */
/* #include <stdio.h> */ /* #include <stdio.h> */
#include <string.h> #include <string.h>
@@ -141,7 +141,7 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
PRF(printf(" ")); PRF(printf(" "));
outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | (u >> 16) & 0x1F); outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F));
outBuf[destPos++] = (Byte)(u >> 8); outBuf[destPos++] = (Byte)(u >> 8);
outBuf[destPos++] = (Byte)u; outBuf[destPos++] = (Byte)u;
outBuf[destPos++] = (Byte)(pm >> 8); outBuf[destPos++] = (Byte)(pm >> 8);
@@ -173,6 +173,65 @@ void Lzma2EncProps_Init(CLzma2EncProps *p)
p->blockSize = 0; 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) static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
{ {
@@ -181,9 +240,7 @@ static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
/* ---------- Lzma2 ---------- */ /* ---------- Lzma2 ---------- */
extern struct _CLzma2Enc; typedef struct
typedef struct _CLzma2Enc
{ {
Byte propEncoded; Byte propEncoded;
CLzma2EncProps props; CLzma2EncProps props;
@@ -351,70 +408,6 @@ void Lzma2Enc_Destroy(CLzma2EncHandle pp)
IAlloc_Free(p->alloc, 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) SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props)
{ {
CLzma2Enc *p = (CLzma2Enc *)pp; CLzma2Enc *p = (CLzma2Enc *)pp;

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/* Ppmd8.c -- PPMdI codec /* 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 */ This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */
#include <memory.h> #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; unsigned i = ctx->NumStats, escFreq, sumFreq, flags;
CPpmd_State *s = (CPpmd_State *)ShrinkUnits(p, STATS(ctx), oldNU, (i + 2) >> 1); CPpmd_State *s = (CPpmd_State *)ShrinkUnits(p, STATS(ctx), oldNU, (i + 2) >> 1);
ctx->Stats = REF(s); 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); flags = (ctx->Flags & (0x10 + 0x04 * scale)) + 0x08 * (s->Symbol >= 0x40);
escFreq = ctx->SummFreq - s->Freq; escFreq = ctx->SummFreq - s->Freq;
sumFreq = (s->Freq = (Byte)((s->Freq + scale) >> scale)); sumFreq = (s->Freq = (Byte)((s->Freq + scale) >> scale));

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -382,6 +382,12 @@ static void MakeExeMethod(const CCompressionMethodMode &method,
prop.Value = kNumFastBytesForBCJ2_LZMA; prop.Value = kNumFastBytesForBCJ2_LZMA;
methodFull.Props.Add(prop); 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);
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) STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value)
{ {
COM_TRY_BEGIN
if (formatIndex >= g_NumArcs) if (formatIndex >= g_NumArcs)
return E_INVALIDARG; return E_INVALIDARG;
const CArcInfo &arc = *g_Arcs[formatIndex]; const CArcInfo &arc = *g_Arcs[formatIndex];
@@ -119,6 +120,7 @@ STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value
} }
prop.Detach(value); prop.Detach(value);
return S_OK; return S_OK;
COM_TRY_END
} }
STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)

View File

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

View File

@@ -54,7 +54,7 @@ static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
{ {
sizes.Clear(); sizes.Clear();
sizePointers.Clear(); sizePointers.Clear();
for(UInt32 i = 0; i < numItems; i++) for (UInt32 i = 0; i < numItems; i++)
{ {
if (srcSizes == 0 || srcSizes[i] == NULL) if (srcSizes == 0 || srcSizes[i] == NULL)
{ {
@@ -83,7 +83,7 @@ HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)
{ {
_bindInfo = bindInfo; _bindInfo = bindInfo;
_streamBinders.Clear(); _streamBinders.Clear();
for(int i = 0; i < _bindInfo.BindPairs.Size(); i++) for (int i = 0; i < _bindInfo.BindPairs.Size(); i++)
{ {
_streamBinders.Add(CStreamBinder()); _streamBinders.Add(CStreamBinder());
RINOK(_streamBinders.Back().CreateEvents()); RINOK(_streamBinders.Back().CreateEvents());
@@ -113,7 +113,7 @@ void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)
void CCoderMixer2MT::ReInit() void CCoderMixer2MT::ReInit()
{ {
for(int i = 0; i < _streamBinders.Size(); i++) for (int i = 0; i < _streamBinders.Size(); i++)
_streamBinders[i].ReInit(); _streamBinders[i].ReInit();
} }
@@ -125,20 +125,20 @@ HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStre
throw 0; throw 0;
*/ */
int i; int i;
for(i = 0; i < _coders.Size(); i++) for (i = 0; i < _coders.Size(); i++)
{ {
CCoder2 &coderInfo = _coders[i]; CCoder2 &coderInfo = _coders[i];
const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i]; const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i];
coderInfo.InStreams.Clear(); coderInfo.InStreams.Clear();
UInt32 j; UInt32 j;
for(j = 0; j < coderStreamsInfo.NumInStreams; j++) for (j = 0; j < coderStreamsInfo.NumInStreams; j++)
coderInfo.InStreams.Add(NULL); coderInfo.InStreams.Add(NULL);
coderInfo.OutStreams.Clear(); coderInfo.OutStreams.Clear();
for(j = 0; j < coderStreamsInfo.NumOutStreams; j++) for (j = 0; j < coderStreamsInfo.NumOutStreams; j++)
coderInfo.OutStreams.Add(NULL); 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]; const CBindPair &bindPair = _bindInfo.BindPairs[i];
UInt32 inCoderIndex, inCoderStreamIndex; UInt32 inCoderIndex, inCoderStreamIndex;
@@ -149,16 +149,26 @@ HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStre
_streamBinders[i].CreateStreams( _streamBinders[i].CreateStreams(
&_coders[inCoderIndex].InStreams[inCoderStreamIndex], &_coders[inCoderIndex].InStreams[inCoderStreamIndex],
&_coders[outCoderIndex].OutStreams[outCoderStreamIndex]); &_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; UInt32 inCoderIndex, inCoderStreamIndex;
_bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex); _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex);
_coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i]; _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; UInt32 outCoderIndex, outCoderStreamIndex;
_bindInfo.FindOutStream(_bindInfo.OutStreams[i], 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; UInt32 realProcessedSize;
HRESULT result = _stream->Read(data, size, &realProcessedSize); HRESULT result = _stream->Read(data, size, &realProcessedSize);
/*
if (size > 0 && realProcessedSize == 0) if (size > 0 && realProcessedSize == 0)
_wasFinished = true; _wasFinished = true;
*/
_size += realProcessedSize; _size += realProcessedSize;
_crc = CrcUpdate(_crc, data, realProcessedSize); _crc = CrcUpdate(_crc, data, realProcessedSize);
if(processedSize != NULL) if(processedSize != NULL)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -26,7 +26,7 @@ class CHandler:
bool GetUncompressedSize(int index, UInt32 &size); bool GetUncompressedSize(int index, UInt32 &size);
bool GetCompressedSize(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: public:
MY_QUERYINTERFACE_BEGIN2(IInArchive) MY_QUERYINTERFACE_BEGIN2(IInArchive)
QUERY_ENTRY_ISetCompressCodecsInfo QUERY_ENTRY_ISetCompressCodecsInfo

View File

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

View File

@@ -72,7 +72,7 @@ struct CItem
UInt32 DictionarySize; UInt32 DictionarySize;
CItem(): IsUnicode(false), UseFilter(false), IsCompressed(true), SizeIsDefined(false), 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 bool IsINSTDIR() const
{ {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -44,7 +44,7 @@ public:
void PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize, bool aesEncryption); void PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize, bool aesEncryption);
void WriteLocalHeader(const CLocalItem &item); 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 CreateStreamForCompressing(IOutStream **outStream);
void CreateStreamForCopying(ISequentialOutStream **outStream); void CreateStreamForCopying(ISequentialOutStream **outStream);

View File

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

View File

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

View File

@@ -1,3 +1,3 @@
#include "../../MyVersionInfo.rc" #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 # End Source File
# Begin 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 SOURCE=..\..\UI\FileManager\SettingsPage.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

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

View File

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

View File

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

View File

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

View File

@@ -21,9 +21,6 @@ class CEncoder:
public CMyUnknownImp public CMyUnknownImp
{ {
Byte *_buffer; Byte *_buffer;
public:
CEncoder(): _buffer(0) {};
~CEncoder();
bool Create(); bool Create();
COutBuffer _mainStream; COutBuffer _mainStream;
@@ -33,6 +30,7 @@ public:
NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusEncoder[256 + 2]; NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusEncoder[256 + 2];
HRESULT Flush(); HRESULT Flush();
public:
void ReleaseStreams() void ReleaseStreams()
{ {
_mainStream.ReleaseStream(); _mainStream.ReleaseStream();
@@ -50,32 +48,25 @@ public:
}; };
public: public:
MY_UNKNOWN_IMP MY_UNKNOWN_IMP
HRESULT CodeReal(ISequentialInStream **inStreams, HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
const UInt64 **inSizes, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress); ICompressProgressInfo *progress);
STDMETHOD(Code)(ISequentialInStream **inStreams, STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
const UInt64 **inSizes, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress); ICompressProgressInfo *progress);
CEncoder(): _buffer(0) {};
~CEncoder();
}; };
#endif #endif
class CDecoder: class CDecoder:
public ICompressCoder2, public ICompressCoder2,
public ICompressSetBufSize,
public CMyUnknownImp public CMyUnknownImp
{ {
public:
CInBuffer _mainInStream; CInBuffer _mainInStream;
CInBuffer _callStream; CInBuffer _callStream;
CInBuffer _jumpStream; CInBuffer _jumpStream;
@@ -83,7 +74,10 @@ public:
NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusDecoder[256 + 2]; NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusDecoder[256 + 2];
COutBuffer _outStream; COutBuffer _outStream;
UInt32 _inBufSizes[4];
UInt32 _outBufSize;
public:
void ReleaseStreams() void ReleaseStreams()
{ {
_mainInStream.ReleaseStream(); _mainInStream.ReleaseStream();
@@ -103,21 +97,17 @@ public:
}; };
public: public:
MY_UNKNOWN_IMP MY_UNKNOWN_IMP1(ICompressSetBufSize);
HRESULT CodeReal(ISequentialInStream **inStreams, HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
const UInt64 **inSizes, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress); ICompressProgressInfo *progress);
STDMETHOD(Code)(ISequentialInStream **inStreams, STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
const UInt64 **inSizes, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,
UInt32 numInStreams,
ISequentialOutStream **outStreams,
const UInt64 **outSizes,
UInt32 numOutStreams,
ICompressProgressInfo *progress); 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 NCompress {
namespace NLzma { namespace NLzma {
static const UInt32 kInBufSize = 1 << 20; CDecoder::CDecoder(): _inBuf(0), _propsWereSet(false), _outSizeDefined(false),
_inBufSize(1 << 20),
CDecoder::CDecoder(): _inBuf(0), _propsWereSet(false), _outSizeDefined(false), FinishStream(false) _outBufSize(1 << 22),
FinishStream(false)
{ {
_inSizeProcessed = 0; _inSizeProcessed = 0;
_inPos = _inSize = 0; _inPos = _inSize = 0;
@@ -43,13 +44,18 @@ CDecoder::~CDecoder()
MyFree(_inBuf); 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() HRESULT CDecoder::CreateInputBuffer()
{ {
if (_inBuf == 0) if (_inBuf == 0 || _inBufSize != _inBufSizeAllocated)
{ {
_inBuf = (Byte *)MyAlloc(kInBufSize); MyFree(_inBuf);
_inBuf = (Byte *)MyAlloc(_inBufSize);
if (_inBuf == 0) if (_inBuf == 0)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
_inBufSizeAllocated = _inBufSize;
} }
return S_OK; return S_OK;
} }
@@ -67,6 +73,7 @@ void CDecoder::SetOutStreamSizeResume(const UInt64 *outSize)
if (_outSizeDefined) if (_outSizeDefined)
_outSize = *outSize; _outSize = *outSize;
_outSizeProcessed = 0; _outSizeProcessed = 0;
_wrPos = 0;
LzmaDec_Init(&_state); LzmaDec_Init(&_state);
} }
@@ -85,19 +92,17 @@ HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *
UInt64 startInProgress = _inSizeProcessed; UInt64 startInProgress = _inSizeProcessed;
SizeT next = (_state.dicBufSize - _state.dicPos < _outBufSize) ? _state.dicBufSize : (_state.dicPos + _outBufSize);
for (;;) for (;;)
{ {
if (_inPos == _inSize) if (_inPos == _inSize)
{ {
_inPos = _inSize = 0; _inPos = _inSize = 0;
RINOK(inStream->Read(_inBuf, kInBufSize, &_inSize)); RINOK(inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize));
} }
SizeT dicPos = _state.dicPos; SizeT dicPos = _state.dicPos;
SizeT curSize = _state.dicBufSize - dicPos; SizeT curSize = next - dicPos;
const UInt32 kStepSize = ((UInt32)1 << 22);
if (curSize > kStepSize)
curSize = (SizeT)kStepSize;
ELzmaFinishMode finishMode = LZMA_FINISH_ANY; ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
if (_outSizeDefined) if (_outSizeDefined)
@@ -123,9 +128,18 @@ HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *
bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0); bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0);
bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize); 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) if (res != 0)
return S_FALSE; return S_FALSE;
RINOK(res2); RINOK(res2);
@@ -134,9 +148,6 @@ HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *
if (finished) if (finished)
return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE); return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE);
} }
if (_state.dicPos == _state.dicBufSize)
_state.dicPos = 0;
if (progress) if (progress)
{ {
UInt64 inSize = _inSizeProcessed - startInProgress; UInt64 inSize = _inSizeProcessed - startInProgress;
@@ -148,6 +159,8 @@ HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
{ {
if (_inBuf == 0)
return E_INVALIDARG;
SetOutStreamSize(outSize); SetOutStreamSize(outSize);
return CodeSpec(inStream, outStream, progress); return CodeSpec(inStream, outStream, progress);
} }
@@ -166,7 +179,7 @@ STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
if (_inPos == _inSize) if (_inPos == _inSize)
{ {
_inPos = _inSize = 0; _inPos = _inSize = 0;
RINOK(_inStream->Read(_inBuf, kInBufSize, &_inSize)); RINOK(_inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize));
} }
{ {
SizeT inProcessed = _inSize - _inPos; SizeT inProcessed = _inSize - _inPos;
@@ -214,7 +227,7 @@ HRESULT CDecoder::ReadFromInputStream(void *data, UInt32 size, UInt32 *processed
if (_inPos == _inSize) if (_inPos == _inSize)
{ {
_inPos = _inSize = 0; _inPos = _inSize = 0;
RINOK(_inStream->Read(_inBuf, kInBufSize, &_inSize)); RINOK(_inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize));
if (_inSize == 0) if (_inSize == 0)
break; break;
} }

View File

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

View File

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

View File

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

View File

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

View File

@@ -107,6 +107,12 @@ CODER_INTERFACE(ICompressSetOutStreamSize, 0x34)
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; 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) CODER_INTERFACE(ICompressFilter, 0x40)
{ {
STDMETHOD(Init)() PURE; STDMETHOD(Init)() PURE;

View File

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

View File

@@ -278,15 +278,15 @@ struct CArchiveItemPropertyTemp
VARTYPE Type; VARTYPE Type;
}; };
STDMETHODIMP CAgentFolder::GetNumberOfProperties(UInt32 *numProperties) STDMETHODIMP CAgentFolder::GetNumberOfProperties(UInt32 *numProps)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
RINOK(_agentSpec->GetArchive()->GetNumberOfProperties(numProperties)); RINOK(_agentSpec->GetArchive()->GetNumberOfProperties(numProps));
*numProperties += kNumProperties; *numProps += kNumProperties;
if (!_flatMode) if (!_flatMode)
(*numProperties)--; (*numProps)--;
if (!_agentSpec->_proxyArchive->ThereIsPathProp) if (!_agentSpec->_proxyArchive->ThereIsPathProp)
(*numProperties)++; (*numProps)++;
return S_OK; return S_OK;
COM_TRY_END COM_TRY_END
} }
@@ -294,8 +294,8 @@ STDMETHODIMP CAgentFolder::GetNumberOfProperties(UInt32 *numProperties)
STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
UInt32 numProperties; UInt32 numProps;
_agentSpec->GetArchive()->GetNumberOfProperties(&numProperties); _agentSpec->GetArchive()->GetNumberOfProperties(&numProps);
if (!_agentSpec->_proxyArchive->ThereIsPathProp) if (!_agentSpec->_proxyArchive->ThereIsPathProp)
{ {
if (index == 0) if (index == 0)
@@ -308,7 +308,7 @@ STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *pro
index--; index--;
} }
if (index < numProperties) if (index < numProps)
{ {
RINOK(_agentSpec->GetArchive()->GetPropertyInfo(index, name, propID, varType)); RINOK(_agentSpec->GetArchive()->GetPropertyInfo(index, name, propID, varType));
if (*propID == kpidPath) if (*propID == kpidPath)
@@ -316,7 +316,7 @@ STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *pro
} }
else else
{ {
const STATPROPSTG &srcItem = kProperties[index - numProperties]; const STATPROPSTG &srcItem = kProperties[index - numProps];
*propID = srcItem.propid; *propID = srcItem.propid;
*varType = srcItem.vt; *varType = srcItem.vt;
*name = 0; *name = 0;
@@ -356,9 +356,9 @@ STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
COM_TRY_END COM_TRY_END
} }
STDMETHODIMP CAgentFolder::GetNumberOfFolderProperties(UInt32 *numProperties) STDMETHODIMP CAgentFolder::GetNumberOfFolderProperties(UInt32 *numProps)
{ {
*numProperties = kNumFolderProps; *numProps = kNumFolderProps;
return S_OK; 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(); *object = temp.Detach();
return S_OK; return S_OK;
} }
@@ -468,6 +468,7 @@ CAgent::~CAgent()
STDMETHODIMP CAgent::Open( STDMETHODIMP CAgent::Open(
IInStream *inStream, IInStream *inStream,
const wchar_t *filePath, const wchar_t *filePath,
const wchar_t *arcFormat,
BSTR *archiveType, BSTR *archiveType,
IArchiveOpenCallback *openArchiveCallback) IArchiveOpenCallback *openArchiveCallback)
{ {
@@ -488,7 +489,11 @@ STDMETHODIMP CAgent::Open(
_compressCodecsInfo = _codecs; _compressCodecsInfo = _codecs;
RINOK(_codecs->Load()); 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(); CArc &arc = _archiveLink.Arcs.Back();
if (!inStream) if (!inStream)
@@ -573,10 +578,10 @@ STDMETHODIMP CAgent::Extract(
COM_TRY_END COM_TRY_END
} }
STDMETHODIMP CAgent::GetNumberOfProperties(UInt32 *numProperties) STDMETHODIMP CAgent::GetNumberOfProperties(UInt32 *numProps)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
return GetArchive()->GetNumberOfProperties(numProperties); return GetArchive()->GetNumberOfProperties(numProps);
COM_TRY_END COM_TRY_END
} }
@@ -591,25 +596,50 @@ STDMETHODIMP CAgent::GetPropertyInfo(UInt32 index,
COM_TRY_END 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 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 COM_TRY_END
} }
STDMETHODIMP CAgent::GetNumberOfArchiveProperties(UInt32 *numProperties) STDMETHODIMP CAgent::GetArcNumProps(UInt32 level, UInt32 *numProps)
{ {
COM_TRY_BEGIN return _archiveLink.Arcs[level].Archive->GetNumberOfArchiveProperties(numProps);
return GetArchive()->GetNumberOfArchiveProperties(numProperties);
COM_TRY_END
} }
STDMETHODIMP CAgent::GetArchivePropertyInfo(UInt32 index, STDMETHODIMP CAgent::GetArcPropInfo(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)
BSTR *name, PROPID *propID, VARTYPE *varType)
{ {
COM_TRY_BEGIN return _archiveLink.Arcs[level].Archive->GetArchivePropertyInfo(index, name, propID, varType);
return GetArchive()->GetArchivePropertyInfo(index, }
name, propID, varType);
COM_TRY_END // 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: class CAgentFolder:
public IFolderFolder, public IFolderFolder,
public IFolderProperties, public IFolderProperties,
public IGetFolderArchiveProperties, public IGetFolderArcProps,
public IArchiveFolder, public IArchiveFolder,
public IArchiveFolderInternal, public IArchiveFolderInternal,
public IInArchiveGetStream, public IInArchiveGetStream,
@@ -50,7 +50,7 @@ public:
MY_QUERYINTERFACE_BEGIN2(IFolderFolder) MY_QUERYINTERFACE_BEGIN2(IFolderFolder)
MY_QUERYINTERFACE_ENTRY(IFolderProperties) MY_QUERYINTERFACE_ENTRY(IFolderProperties)
MY_QUERYINTERFACE_ENTRY(IGetFolderArchiveProperties) MY_QUERYINTERFACE_ENTRY(IGetFolderArcProps)
MY_QUERYINTERFACE_ENTRY(IArchiveFolder) MY_QUERYINTERFACE_ENTRY(IArchiveFolder)
MY_QUERYINTERFACE_ENTRY(IArchiveFolderInternal) MY_QUERYINTERFACE_ENTRY(IArchiveFolderInternal)
MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream) MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream)
@@ -68,7 +68,7 @@ public:
INTERFACE_FolderFolder(;) INTERFACE_FolderFolder(;)
INTERFACE_FolderProperties(;) INTERFACE_FolderProperties(;)
STDMETHOD(GetFolderArchiveProperties)(IFolderArchiveProperties **object); STDMETHOD(GetFolderArcProps)(IFolderArcProps **object);
// IArchiveFolder // IArchiveFolder
STDMETHOD(Extract)(const UINT32 *indices, UINT32 numItems, STDMETHOD(Extract)(const UINT32 *indices, UINT32 numItems,
@@ -132,7 +132,7 @@ private:
class CAgent: class CAgent:
public IInFolderArchive, public IInFolderArchive,
public IFolderArchiveProperties, public IFolderArcProps,
#ifndef EXTRACT_ONLY #ifndef EXTRACT_ONLY
public IOutFolderArchive, public IOutFolderArchive,
public ISetProperties, public ISetProperties,
@@ -142,7 +142,7 @@ class CAgent:
public: public:
MY_QUERYINTERFACE_BEGIN2(IInFolderArchive) MY_QUERYINTERFACE_BEGIN2(IInFolderArchive)
MY_QUERYINTERFACE_ENTRY(IFolderArchiveProperties) MY_QUERYINTERFACE_ENTRY(IFolderArcProps)
#ifndef EXTRACT_ONLY #ifndef EXTRACT_ONLY
MY_QUERYINTERFACE_ENTRY(IOutFolderArchive) MY_QUERYINTERFACE_ENTRY(IOutFolderArchive)
MY_QUERYINTERFACE_ENTRY(ISetProperties) MY_QUERYINTERFACE_ENTRY(ISetProperties)
@@ -151,7 +151,7 @@ public:
MY_ADDREF_RELEASE MY_ADDREF_RELEASE
INTERFACE_IInFolderArchive(;) INTERFACE_IInFolderArchive(;)
INTERFACE_IFolderArchiveProperties(;) INTERFACE_IFolderArcProps(;)
#ifndef EXTRACT_ONLY #ifndef EXTRACT_ONLY
INTERFACE_IOutFolderArchive(;) INTERFACE_IOutFolderArchive(;)

View File

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

View File

@@ -27,7 +27,7 @@ FOLDER_ARCHIVE_INTERFACE(IArchiveFolder, 0x05)
}; };
#define INTERFACE_IInFolderArchive(x) \ #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(ReOpen)(IArchiveOpenCallback *openArchiveCallback) x; \
STDMETHOD(Close)() x; \ STDMETHOD(Close)() x; \
STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \ STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \
@@ -37,7 +37,7 @@ FOLDER_ARCHIVE_INTERFACE(IArchiveFolder, 0x05)
NExtract::NOverwriteMode::EEnum overwriteMode, const wchar_t *path, \ NExtract::NOverwriteMode::EEnum overwriteMode, const wchar_t *path, \
Int32 testMode, IFolderArchiveExtractCallback *extractCallback2) x; \ Int32 testMode, IFolderArchiveExtractCallback *extractCallback2) x; \
FOLDER_ARCHIVE_INTERFACE(IInFolderArchive, 0x0D) FOLDER_ARCHIVE_INTERFACE(IInFolderArchive, 0x0E)
{ {
INTERFACE_IInFolderArchive(PURE) INTERFACE_IInFolderArchive(PURE)
}; };

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,34 +1,24 @@
// ContextMenuFlags.h // ContextMenuFlags.h
#ifndef __SEVENZIP_CONTEXTMENUFLAGS_H #ifndef __CONTEXT_MENU_FLAGS_H
#define __SEVENZIP_CONTEXTMENUFLAGS_H #define __CONTEXT_MENU_FLAGS_H
namespace NContextMenuFlags namespace NContextMenuFlags
{ {
const UINT32 kExtract = 1 << 0; const UInt32 kExtract = 1 << 0;
const UINT32 kExtractHere = 1 << 1; const UInt32 kExtractHere = 1 << 1;
const UINT32 kExtractTo = 1 << 2; const UInt32 kExtractTo = 1 << 2;
// const UINT32 kExtractEach = 1 << 3;
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 kCompress = 1 << 8; const UInt32 kCompressEmail = 1 << 10;
const UINT32 kCompressTo7z = 1 << 9; const UInt32 kCompressTo7zEmail = 1 << 11;
const UINT32 kCompressEmail = 1 << 10; const UInt32 kCompressToZip = 1 << 12;
const UINT32 kCompressTo7zEmail = 1 << 11; const UInt32 kCompressToZipEmail = 1 << 13;
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; }
} }
#endif #endif

View File

@@ -26,6 +26,10 @@
#include "ContextMenu.h" #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; using namespace NWindows;
HINSTANCE g_hInstance = 0; HINSTANCE g_hInstance = 0;

View File

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

View File

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

View File

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

View File

@@ -21,6 +21,6 @@ CAPTION "About 7-Zip"
ICON IDI_LOGO, -1, m, m, 32, 32, SS_REALSIZEIMAGE ICON IDI_LOGO, -1, m, m, 32, 32, SS_REALSIZEIMAGE
LTEXT MY_7ZIP_VERSION, -1, m, 54, xc, 8 LTEXT MY_7ZIP_VERSION, -1, m, 54, xc, 8
LTEXT MY_COPYRIGHT, -1, m, 67, 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) IDC_ABOUT_STATIC_REGISTER_INFO, m, y, xc, (by - y - 1)
} }

View File

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

View File

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

View File

@@ -4,8 +4,4 @@
#include "Common/MyInitGuid.h" #include "Common/MyInitGuid.h"
#include "PluginInterface.h"
#include "../Agent/Agent.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; HWND g_HWND;
bool g_OpenArchive = false; bool g_OpenArchive = false;
static UString g_MainPath; static UString g_MainPath;
static UString g_ArcFormat;
static bool g_Maximized = false; static bool g_Maximized = false;
#ifndef UNDER_CE #ifndef UNDER_CE
@@ -443,7 +444,9 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
UString paramString, tailString; UString paramString, tailString;
SplitStringToTwoStrings(commandsString, paramString, tailString); SplitStringToTwoStrings(commandsString, paramString, tailString);
paramString.Trim(); paramString.Trim();
tailString.Trim();
if (tailString.Left(2) == L"-t")
g_ArcFormat = tailString.Mid(2);
if (!paramString.IsEmpty()) if (!paramString.IsEmpty())
{ {
g_MainPath = paramString; g_MainPath = paramString;
@@ -639,7 +642,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
if (NFile::NFind::DoesFileExist(g_MainPath)) if (NFile::NFind::DoesFileExist(g_MainPath))
needOpenFile = true; 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) if (res == E_ABORT)
{ {

View File

@@ -442,14 +442,6 @@ SOURCE=.\OptionsDialog.cpp
# End Source File # End Source File
# Begin 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 SOURCE=.\SettingsPage.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

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

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