Compare commits

...

3 Commits
9.13 ... 9.16

Author SHA1 Message Date
Igor Pavlov
044e4bb741 9.16 2016-05-28 00:16:03 +01:00
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
78 changed files with 1916 additions and 715 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,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,5 +1,5 @@
/* 7zMain.c - Test application for 7z Decoder /* 7zMain.c - Test application for 7z Decoder
2010-03-12 : Igor Pavlov : Public domain */ 2010-07-13 : Igor Pavlov : Public domain */
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@@ -104,7 +104,7 @@ static SRes Utf16_To_Utf8Buf(CBuf *dest, const UInt16 *src, size_t srcLen)
} }
#endif #endif
static WRes Utf16_To_Char(CBuf *buf, const UInt16 *s, int fileMode) static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s, int fileMode)
{ {
int len = 0; int len = 0;
for (len = 0; s[len] != '\0'; len++); for (len = 0; s[len] != '\0'; len++);
@@ -172,15 +172,16 @@ static WRes OutFile_OpenUtf16(CSzFile *p, const UInt16 *name)
#endif #endif
} }
static void PrintString(const UInt16 *s) static SRes PrintString(const UInt16 *s)
{ {
CBuf buf; CBuf buf;
SRes res;
Buf_Init(&buf); Buf_Init(&buf);
if (Utf16_To_Char(&buf, s, 0) == 0) res = Utf16_To_Char(&buf, s, 0);
{ if (res == SZ_OK)
printf("%s", buf.data); printf("%s", buf.data);
Buf_Free(&buf, &g_Alloc); Buf_Free(&buf, &g_Alloc);
} return res;
} }
static void UInt64ToStr(UInt64 value, char *s) static void UInt64ToStr(UInt64 value, char *s)
@@ -398,7 +399,9 @@ int MY_CDECL main(int numargs, char *args[])
} }
printf("%s %s %10s ", t, attr, s); printf("%s %s %10s ", t, attr, s);
PrintString(temp); res = PrintString(temp);
if (res != SZ_OK)
break;
if (f->IsDir) if (f->IsDir)
printf("/"); printf("/");
printf("\n"); printf("\n");
@@ -407,7 +410,9 @@ int MY_CDECL main(int numargs, char *args[])
printf(testCommand ? printf(testCommand ?
"Testing ": "Testing ":
"Extracting "); "Extracting ");
PrintString(temp); res = PrintString(temp);
if (res != SZ_OK)
break;
if (f->IsDir) if (f->IsDir)
printf("/"); printf("/");
else else

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

@@ -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)
{ {
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); _fileIsOpen = true;
Sizes.Add(0); CMyComPtr<IStreamGetSize> streamGetSize;
Processed.Add(result == S_OK); stream.QueryInterface(IID_IStreamGetSize, &streamGetSize);
AddDigest(); if (streamGetSize)
continue;
}
CMyComPtr<IStreamGetSize> streamGetSize;
if (stream.QueryInterface(IID_IStreamGetSize, &streamGetSize) == S_OK)
{
if(streamGetSize)
{ {
_currentSizeIsDefined = true;
RINOK(streamGetSize->GetSize(&_currentSize)); RINOK(streamGetSize->GetSize(&_currentSize));
_currentSizeIsDefined = true;
} }
return S_OK;
} }
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
_fileIsOpen = true; Sizes.Add(0);
return S_OK; Processed.Add(result == S_OK);
AddDigest();
} }
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

@@ -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

@@ -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;
} }

View File

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

View File

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

View File

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

View File

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

View File

@@ -526,7 +526,14 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
item.Attrib = attrib; item.Attrib = attrib;
item.Flags = p[12]; item.Flags = p[12];
item.Size = Get32(p + 28); item.Size = Get32(p + 28);
item.Cluster = Get16(p + 26) | ((UInt32)Get16(p + 20) << 16); item.Cluster = Get16(p + 26);
if (Header.NumFatBits > 16)
item.Cluster |= ((UInt32)Get16(p + 20) << 16);
else
{
// OS/2 and WinNT probably can store EA (extended atributes) in that field.
}
item.CTime = Get32(p + 14); item.CTime = Get32(p + 14);
item.CTime2 = p[13]; item.CTime2 = p[13];
item.ADate = Get16(p + 18); item.ADate = Get16(p + 18);
@@ -578,8 +585,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

@@ -7,15 +7,14 @@
#include "../../Common/StreamUtils.h" #include "../../Common/StreamUtils.h"
#include "../../Common/MethodId.h" #include "../../Common/MethodId.h"
#include "../../Common/CreateCoder.h"
#include "../../Compress/BZip2Decoder.h"
#include "../../Compress/DeflateDecoder.h"
#include "../../Compress/LzmaDecoder.h"
namespace NArchive { namespace NArchive {
namespace NNsis { namespace NNsis {
static const CMethodId k_Copy = 0x0;
static const CMethodId k_Deflate = 0x040901;
static const CMethodId k_BZip2 = 0x040902;
static const CMethodId k_LZMA = 0x030101;
static const CMethodId k_BCJ_X86 = 0x03030103; static const CMethodId k_BCJ_X86 = 0x03030103;
HRESULT CDecoder::Init( HRESULT CDecoder::Init(
@@ -31,24 +30,14 @@ HRESULT CDecoder::Init(
_method = method; _method = method;
if (!_codecInStream) if (!_codecInStream)
{ {
CMethodId methodID;
switch (method) switch (method)
{ {
case NMethodType::kCopy: methodID = k_Copy; break; // case NMethodType::kCopy: return E_NOTIMPL;
case NMethodType::kDeflate: methodID = k_Deflate; break; case NMethodType::kDeflate: _codecInStream = new NCompress::NDeflate::NDecoder::CNsisCOMCoder(); break;
case NMethodType::kBZip2: methodID = k_BZip2; break; case NMethodType::kBZip2: _codecInStream = new NCompress::NBZip2::CNsisDecoder(); break;
case NMethodType::kLZMA: methodID = k_LZMA; break; case NMethodType::kLZMA: _codecInStream = new NCompress::NLzma::CDecoder(); break;
default: return E_NOTIMPL; default: return E_NOTIMPL;
} }
CMyComPtr<ICompressCoder> coder;
RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS
methodID, coder, false));
if (!coder)
return E_NOTIMPL;
coder.QueryInterface(IID_ISequentialInStream, &_codecInStream);
if (!_codecInStream)
return E_NOTIMPL;
} }
if (thereIsFilterFlag) if (thereIsFilterFlag)

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"
@@ -88,7 +87,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * maxCheckStartPosit
COM_TRY_BEGIN COM_TRY_BEGIN
Close(); Close();
{ {
if(_archive.Open( if (_archive.Open(
EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS
stream, maxCheckStartPosition) != S_OK) stream, maxCheckStartPosition) != S_OK)
return S_FALSE; return S_FALSE;
@@ -265,12 +264,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
bool allFilesMode = (numItems == (UInt32)-1); bool allFilesMode = (numItems == (UInt32)-1);
if (allFilesMode) if (allFilesMode)
GetNumberOfItems(&numItems); GetNumberOfItems(&numItems);
if(numItems == 0) if (numItems == 0)
return S_OK; return S_OK;
UInt64 totalSize = 0; UInt64 totalSize = 0;
UInt32 i; UInt32 i;
for(i = 0; i < numItems; i++) for (i = 0; i < numItems; i++)
{ {
UInt32 index = (allFilesMode ? i : indices[i]); UInt32 index = (allFilesMode ? i : indices[i]);
#ifdef NSIS_SCRIPT #ifdef NSIS_SCRIPT
@@ -314,6 +313,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
byteBuf.SetCapacity(kBufferLength); byteBuf.SetCapacity(kBufferLength);
Byte *buffer = byteBuf; Byte *buffer = byteBuf;
CByteBuffer tempBuf;
bool dataError = false; bool dataError = false;
for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
{ {
@@ -331,7 +332,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (index >= (UInt32)_archive.Items.Size()) if (index >= (UInt32)_archive.Items.Size())
{ {
currentItemSize = _archive.Script.Length(); currentItemSize = _archive.Script.Length();
if(!testMode && !realOutStream) if (!testMode && !realOutStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
if (!testMode) if (!testMode)
@@ -347,7 +348,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
else else
GetCompressedSize(index, currentItemSize); GetCompressedSize(index, currentItemSize);
if(!testMode && !realOutStream) if (!testMode && !realOutStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
@@ -358,10 +359,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
bool sizeIsKnown = false; bool sizeIsKnown = false;
UInt32 fullSize = 0; UInt32 fullSize = 0;
bool writeToTemp = false;
bool readFromTemp = false;
if (_archive.IsSolid) if (_archive.IsSolid)
{ {
UInt64 pos = _archive.GetPosOfSolidItem(index); UInt64 pos = _archive.GetPosOfSolidItem(index);
while(streamPos < pos) while (streamPos < pos)
{ {
size_t processedSize = (UInt32)MyMin(pos - streamPos, (UInt64)kBufferLength); size_t processedSize = (UInt32)MyMin(pos - streamPos, (UInt64)kBufferLength);
HRESULT res = _archive.Decoder.Read(buffer, &processedSize); HRESULT res = _archive.Decoder.Read(buffer, &processedSize);
@@ -390,7 +394,20 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
fullSize = Get32(buffer2); fullSize = Get32(buffer2);
sizeIsKnown = true; sizeIsKnown = true;
needDecompress = true; needDecompress = true;
if (!testMode && i + 1 < numItems)
{
UInt64 nextPos = _archive.GetPosOfSolidItem(allFilesMode ? i : indices[i + 1]);
if (nextPos < streamPos + fullSize)
{
tempBuf.Free();
tempBuf.SetCapacity(fullSize);
writeToTemp = true;
}
}
} }
else
readFromTemp = true;
} }
else else
{ {
@@ -414,7 +431,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (needDecompress) if (needDecompress)
{ {
UInt64 offset = 0; UInt64 offset = 0;
while(!sizeIsKnown || fullSize > 0) while (!sizeIsKnown || fullSize > 0)
{ {
UInt32 curSize = kBufferLength; UInt32 curSize = kBufferLength;
if (sizeIsKnown && curSize > fullSize) if (sizeIsKnown && curSize > fullSize)
@@ -435,6 +452,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
break; break;
} }
if (writeToTemp)
memcpy((Byte *)tempBuf + (size_t)offset, buffer, processedSize);
fullSize -= (UInt32)processedSize; fullSize -= (UInt32)processedSize;
streamPos += processedSize; streamPos += processedSize;
offset += processedSize; offset += processedSize;
@@ -451,7 +471,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
} }
else else
{ {
while(fullSize > 0) if (readFromTemp)
{
if (!testMode)
RINOK(WriteStream(realOutStream, tempBuf, tempBuf.GetCapacity()));
}
else
while (fullSize > 0)
{ {
UInt32 curSize = MyMin(fullSize, kBufferLength); UInt32 curSize = MyMin(fullSize, kBufferLength);
UInt32 processedSize; UInt32 processedSize;

View File

@@ -1151,16 +1151,25 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
bool sameName = IsUnicode ? bool sameName = IsUnicode ?
(Items[i].NameU == Items[i + 1].NameU) : (Items[i].NameU == Items[i + 1].NameU) :
(Items[i].NameA == Items[i + 1].NameA); (Items[i].NameA == Items[i + 1].NameA);
if (Items[i].Pos == Items[i + 1].Pos && (IsSolid || sameName)) if (Items[i].Pos == Items[i + 1].Pos && sameName)
Items.Delete(i + 1); Items.Delete(i + 1);
else else
i++; i++;
} }
for (i = 0; i + 1 < Items.Size(); i++) for (i = 0; i < Items.Size(); i++)
{ {
CItem &item = Items[i]; CItem &item = Items[i];
item.EstimatedSizeIsDefined = true; UInt32 curPos = item.Pos + 4;
item.EstimatedSize = Items[i + 1].Pos - item.Pos - 4; for (int nextIndex = i + 1; nextIndex < Items.Size(); nextIndex++)
{
UInt32 nextPos = Items[nextIndex].Pos;
if (curPos <= nextPos)
{
item.EstimatedSizeIsDefined = true;
item.EstimatedSize = nextPos - curPos;
break;
}
}
} }
if (!IsSolid) if (!IsSolid)
{ {
@@ -1275,6 +1284,11 @@ static bool IsLZMA(const Byte *p, UInt32 &dictionary, bool &thereIsFlag)
return false; return false;
} }
static bool IsBZip2(const Byte *p)
{
return (p[0] == 0x31 && p[1] < 14);
}
HRESULT CInArchive::Open2( HRESULT CInArchive::Open2(
DECL_EXTERNAL_CODECS_LOC_VARS2 DECL_EXTERNAL_CODECS_LOC_VARS2
) )
@@ -1312,7 +1326,14 @@ HRESULT CInArchive::Open2(
else if (sig[3] == 0x80) else if (sig[3] == 0x80)
{ {
IsSolid = false; IsSolid = false;
Method = NMethodType::kDeflate; if (IsBZip2(sig + 4))
Method = NMethodType::kBZip2;
else
Method = NMethodType::kDeflate;
}
else if (IsBZip2(sig))
{
Method = NMethodType::kBZip2;
} }
else else
{ {

View File

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

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

@@ -107,8 +107,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (prop.vt != VT_UI8) if (prop.vt != VT_UI8)
return E_INVALIDARG; return E_INVALIDARG;
ui.Size = prop.uhVal.QuadPart; ui.Size = prop.uhVal.QuadPart;
/*
// now we support GNU extension for big files
if (ui.Size >= ((UInt64)1 << 33)) if (ui.Size >= ((UInt64)1 << 33))
return E_INVALIDARG; return E_INVALIDARG;
*/
} }
updateItems.Add(ui); updateItems.Add(ui);
} }

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "../../../../C/CpuArch.h"
#include "Common/StringToInt.h" #include "Common/StringToInt.h"
#include "../../Common/StreamUtils.h" #include "../../Common/StreamUtils.h"
@@ -69,11 +71,20 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
filled = false; filled = false;
processedSize = NFileHeader::kRecordSize; bool thereAreEmptyRecords = false;
RINOK(ReadStream(stream, buf, &processedSize)); for (;;)
if (processedSize == 0 || (processedSize == NFileHeader::kRecordSize && IsRecordLast(buf))) {
return S_OK; processedSize = NFileHeader::kRecordSize;
if (processedSize < NFileHeader::kRecordSize) RINOK(ReadStream(stream, buf, &processedSize));
if (processedSize == 0)
return S_OK;
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;
@@ -83,7 +94,16 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
if (!OctalToNumber32(p, 8, item.UID)) item.UID = 0; p += 8; if (!OctalToNumber32(p, 8, item.UID)) item.UID = 0; p += 8;
if (!OctalToNumber32(p, 8, item.GID)) item.GID = 0; p += 8; if (!OctalToNumber32(p, 8, item.GID)) item.GID = 0; p += 8;
RIF(OctalToNumber(p, 12, item.Size)); p += 12; if (GetBe32(p) == (UInt32)1 << 31)
{
// GNU extension
item.Size = GetBe64(p + 4);
}
else
{
RIF(OctalToNumber(p, 12, item.Size));
}
p += 12;
RIF(OctalToNumber32(p, 12, item.MTime)); p += 12; RIF(OctalToNumber32(p, 12, item.MTime)); p += 12;
UInt32 checkSum; UInt32 checkSum;

View File

@@ -53,17 +53,23 @@ static bool MakeOctalString8(char *s, UInt32 value)
return true; return true;
} }
static bool MakeOctalString12(char *s, UInt64 value) static void MakeOctalString12(char *s, UInt64 value)
{ {
AString tempString = MakeOctalString(value); AString tempString = MakeOctalString(value);
const int kMaxSize = 12; const int kMaxSize = 12;
if (tempString.Length() > kMaxSize) if (tempString.Length() > kMaxSize)
return false; {
// GNU extension;
s[0] = (char)(Byte)0x80;
s[1] = s[2] = s[3] = 0;
for (int i = 0; i < 8; i++, value <<= 8)
s[4 + i] = (char)(value >> 56);
return;
}
int numSpaces = kMaxSize - tempString.Length(); int numSpaces = kMaxSize - tempString.Length();
for(int i = 0; i < numSpaces; i++) for(int i = 0; i < numSpaces; i++)
s[i] = ' '; s[i] = ' ';
memmove(s + numSpaces, (const char *)tempString, tempString.Length()); memmove(s + numSpaces, (const char *)tempString, tempString.Length());
return true;
} }
static bool CopyString(char *dest, const AString &src, int maxSize) static bool CopyString(char *dest, const AString &src, int maxSize)
@@ -90,17 +96,12 @@ HRESULT COutArchive::WriteHeaderReal(const CItem &item)
MyStrNCpy(cur, item.Name, NFileHeader::kNameSize); MyStrNCpy(cur, item.Name, NFileHeader::kNameSize);
cur += NFileHeader::kNameSize; cur += NFileHeader::kNameSize;
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.Mode)); RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.Mode)); cur += 8;
cur += 8; RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.UID)); cur += 8;
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.UID)); RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.GID)); cur += 8;
cur += 8;
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.GID));
cur += 8;
RETURN_IF_NOT_TRUE(MakeOctalString12(cur, item.Size)); MakeOctalString12(cur, item.Size); cur += 12;
cur += 12; MakeOctalString12(cur, item.MTime); cur += 12;
RETURN_IF_NOT_TRUE(MakeOctalString12(cur, item.MTime));
cur += 12;
memmove(cur, NFileHeader::kCheckSumBlanks, 8); memmove(cur, NFileHeader::kCheckSumBlanks, 8);
cur += 8; cur += 8;

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);
{ for (size_t i = 2; i < size; i += 2)
wchar_t *chars = s.GetBuffer((int)size / 2 + 1); *chars++ = (wchar_t)Get16(p + i);
for (size_t i = 2; i < size; i += 2) *chars = 0;
*chars++ = (wchar_t)Get16(p + i); s.ReleaseBuffer();
*chars = 0; }
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];
@@ -270,27 +258,176 @@ void CResource::Parse(const Byte *p)
#define GetResource(p, res) res.Parse(p) #define GetResource(p, res) res.Parse(p)
static void GetStream(const Byte *p, CStreamInfo &s) static void GetStream(bool oldVersion, const Byte *p, CStreamInfo &s)
{ {
s.Resource.Parse(p); s.Resource.Parse(p);
s.PartNumber = Get16(p + 24); if (oldVersion)
s.RefCount = Get32(p + 26); {
memcpy(s.Hash, p + 30, kHashSize); s.PartNumber = 1;
s.RefCount = 1;
// UInt32 id = Get32(p + 24);
// UInt32 unknown = Get32(p + 28);
memcpy(s.Hash, p + 32, kHashSize);
}
else
{
s.PartNumber = Get16(p + 24);
s.RefCount = Get32(p + 26);
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];
index = item.Parent;
if (index >= 0 || !SkipRoot)
size += item.Name.Length() + newLevel;
if (index < 0)
break;
if ((UInt32)size >= ((UInt32)1 << 16))
return kLongPath;
}
wchar_t temp[16];
int imageLen = 0;
if (ShowImageNumber)
{
ConvertUInt32ToString(-1 - index, temp);
imageLen = MyStringLen(temp);
size += imageLen + 1;
}
if ((UInt32)size >= ((UInt32)1 << 16))
return kLongPath;
UString path;
wchar_t *s = path.GetBuffer(size);
s[size] = 0;
if (ShowImageNumber)
{
memcpy(s, temp, imageLen * sizeof(wchar_t));
s[imageLen] = WCHAR_PATH_SEPARATOR;
}
index = index1;
for (newLevel = 0;; newLevel = 1)
{
const CItem &item = Items[index];
index = item.Parent;
if (index >= 0 || !SkipRoot)
{
if (newLevel)
s[--size] = WCHAR_PATH_SEPARATOR;
size -= item.Name.Length();
memcpy(s + size, item.Name, sizeof(wchar_t) * item.Name.Length());
}
if (index < 0)
{
path.ReleaseBuffer();
return path;
}
}
}
static void GetFileTimeFromMem(const Byte *p, FILETIME *ft)
{
ft->dwLowDateTime = Get32(p);
ft->dwHighDateTime = Get32(p + 4);
}
static HRESULT ReadName(const Byte *p, int size, UString &dest)
{
if (size == 0)
return S_OK;
if (Get16(p + size) != 0)
return S_FALSE;
wchar_t *s = dest.GetBuffer(size / 2);
for (int i = 0; i <= size; i += 2)
*s++ = Get16(p + i);
dest.ReleaseBuffer();
return S_OK;
}
HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
{
if ((pos & 7) != 0)
return S_FALSE;
int prevIndex = -1;
for (int numItems = 0;; numItems++)
{
if (OpenCallback)
{
UInt64 numFiles = Items.Size();
if ((numFiles & 0x3FF) == 0)
{
RINOK(OpenCallback->SetCompleted(&numFiles, NULL));
}
}
size_t rem = DirSize - pos;
if (pos < DirStartOffset || pos > DirSize || rem < 8)
return S_FALSE; return S_FALSE;
const Byte *p = base + pos; const Byte *p = DirData + pos;
UInt64 length = Get64(p); UInt64 len = Get64(p);
if (length == 0) if (len == 0)
{
if (parent < 0 && numItems != 1)
SkipRoot = false;
DirProcessed += 8;
return S_OK; return S_OK;
if (pos + 102 > size || pos + length + 8 > size || length > ((UInt64)1 << 62)) }
if ((len & 7) != 0 || len < 0x28 || rem < len)
return S_FALSE; 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 +437,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 +504,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 +517,141 @@ static HRESULT ParseDir(const Byte *base, size_t size,
if (pos != totalLength) if (pos != totalLength)
return S_FALSE; return S_FALSE;
*/ */
pos = totalLength; if (totalLength == 0)
pos = 8;
else if (totalLength < 8)
return S_FALSE;
else
pos = totalLength;
} }
return ParseDirItem(base, pos, size, prefix, items); DirStartOffset = DirProcessed = pos;
RINOK(ParseDirItem(pos, parent));
if (DirProcessed == DirSize)
return S_OK;
/* Original program writes additional 8 bytes (END_OF_ROOT_FOLDER), but
reference to that folder is empty */
if (DirProcessed == DirSize - 8 && DirProcessed - DirStartOffset == 112 &&
Get64(p + DirSize - 8) == 0)
return S_OK;
return S_FALSE;
} }
static int CompareHashRefs(const int *p1, const int *p2, void *param) HRESULT CHeader::Parse(const Byte *p)
{ {
const CRecordVector<CStreamInfo> &streams = *(const CRecordVector<CStreamInfo> *)param; UInt32 headerSize = Get32(p + 8);
return memcmp(streams[*p1].Hash, streams[*p2].Hash, kHashSize); 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;
int offset;
if (IsOldVersion())
{
if (headerSize != 0x60)
return S_FALSE;
memset(Guid, 0, 16);
offset = 0x18;
PartNumber = 1;
NumParts = 1;
}
else
{
if (headerSize < 0x74)
return S_FALSE;
memcpy(Guid, p + 0x18, 16);
PartNumber = Get16(p + 0x28);
NumParts = Get16(p + 0x2A);
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 (headerSize < 0xD0)
return S_FALSE;
BootIndex = Get32(p + 0x48);
IntegrityResource.Parse(p + offset + 0x4C);
}
if (IsOldVersion())
return S_FALSE;
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(bool oldVersion, IInStream *inStream, const CHeader &h, CDatabase &db)
{
CByteBuffer offsetBuf;
RINOK(UnpackData(inStream, h.OffsetResource, h.IsLzxMode(), offsetBuf, NULL));
size_t i;
size_t streamInfoSize = oldVersion ? kStreamInfoSize + 2 : kStreamInfoSize;
for (i = 0; offsetBuf.GetCapacity() - i >= streamInfoSize; i += streamInfoSize)
{
CStreamInfo s;
GetStream(oldVersion, (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(h.IsOldVersion(), 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 +660,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 +689,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 j = 0; j < db.Streams.Size(); j++)
{ {
// if (imageIndex > 1) break; for (int i = 0; i < Streams.Size(); i++)
const CStreamInfo &si = db.Streams[j]; sortedByHash.Add(i);
if (!si.Resource.IsMetadata() || si.PartNumber != h.PartNumber) sortedByHash.Sort(CompareHashRefs, &Streams);
continue;
Byte hash[kHashSize];
CByteBuffer metadata;
RINOK(UnpackData(inStream, si.Resource, h.IsLzxMode(), metadata, hash));
if (memcmp(hash, si.Hash, kHashSize) != 0)
return S_FALSE;
wchar_t sz[16];
ConvertUInt32ToString(imageIndex++, sz);
UString s = sz;
s += WCHAR_PATH_SEPARATOR;
RINOK(ParseDir(metadata, metadata.GetCapacity(), s, db.Items));
if (needBootMetadata)
if (h.MetadataResource.Offset == si.Resource.Offset)
needBootMetadata = false;
}
}
if (needBootMetadata)
{
CByteBuffer metadata;
RINOK(UnpackData(inStream, h.MetadataResource, h.IsLzxMode(), metadata, NULL));
RINOK(ParseDir(metadata, metadata.GetCapacity(), L"0" WSTRING_PATH_SEPARATOR, db.Items));
}
return S_OK;
}
HRESULT SortDatabase(CDatabase &db)
{
db.Streams.Sort(CompareStreamsByPos, NULL);
{
CRecordVector<int> sortedByHash;
{
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++) for (int i = 0; i < Items.Size(); i++)
{ {
CItem &item = db.Items[i]; CItem &item = Items[i];
item.StreamIndex = -1; item.StreamIndex = -1;
if (item.HasStream()) if (item.HasStream())
item.StreamIndex = FindHash(db.Streams, sortedByHash, item.Hash); item.StreamIndex = FindHash(Streams, sortedByHash, item.Hash);
} }
} }
{ {
CRecordVector<bool> used; CRecordVector<bool> used;
int j; int i;
for (j = 0; j < db.Streams.Size(); j++) for (i = 0; i < Streams.Size(); i++)
{ {
const CStreamInfo &s = db.Streams[j]; const CStreamInfo &s = Streams[i];
used.Add(s.Resource.IsMetadata() && s.PartNumber == 1); used.Add(s.Resource.IsMetadata() && s.PartNumber == 1);
// used.Add(false);
} }
for (int i = 0; i < db.Items.Size(); i++) for (i = 0; i < Items.Size(); i++)
{ {
CItem &item = db.Items[i]; CItem &item = Items[i];
if (item.StreamIndex >= 0) if (item.StreamIndex >= 0)
used[item.StreamIndex] = true; used[item.StreamIndex] = true;
} }
for (j = 0; j < db.Streams.Size(); j++) for (i = 0; i < Streams.Size(); i++)
if (!used[j]) if (!used[i])
{ {
CItem item; CItem item;
item.StreamIndex = j; item.StreamIndex = i;
item.HasMetadata = false; item.HasMetadata = false;
db.Items.Add(item); Items.Add(item);
} }
} }
db.Items.Sort(CompareItems, NULL); SortedItems.Reserve(Items.Size());
for (int i = (skipRootDir ? 1 : 0); i < Items.Size(); i++)
SortedItems.Add(i);
SortedItems.Sort(CompareItems, this);
return S_OK; return S_OK;
} }

View File

@@ -9,6 +9,8 @@
#include "../../Compress/CopyCoder.h" #include "../../Compress/CopyCoder.h"
#include "../../Compress/LzxDecoder.h" #include "../../Compress/LzxDecoder.h"
#include "../IArchive.h"
namespace NArchive { namespace NArchive {
namespace NWim { namespace NWim {
@@ -56,7 +58,7 @@ public:
} }
}; };
const int kNumHuffmanBits = 16; const unsigned kNumHuffmanBits = 16;
const UInt32 kMatchMinLen = 3; const UInt32 kMatchMinLen = 3;
const UInt32 kNumLenSlots = 16; const UInt32 kNumLenSlots = 16;
const UInt32 kNumPosSlots = 16; const UInt32 kNumPosSlots = 16;
@@ -85,8 +87,10 @@ public:
namespace NResourceFlags namespace NResourceFlags
{ {
const Byte Compressed = 4; const Byte kFree = 1;
const Byte kMetadata = 2; const Byte kMetadata = 2;
const Byte Compressed = 4;
const Byte Spanned = 4;
} }
struct CResource struct CResource
@@ -96,9 +100,18 @@ struct CResource
UInt64 UnpackSize; UInt64 UnpackSize;
Byte Flags; Byte Flags;
void Clear()
{
PackSize = 0;
Offset = 0;
UnpackSize = 0;
Flags = 0;
}
void Parse(const Byte *p); void Parse(const Byte *p);
bool IsCompressed() const { return (Flags & NResourceFlags::Compressed) != 0; } void WriteTo(Byte *p) const;
bool IsFree() const { return (Flags & NResourceFlags::kFree) != 0; }
bool IsMetadata() const { return (Flags & NResourceFlags::kMetadata) != 0; } bool IsMetadata() const { return (Flags & NResourceFlags::kMetadata) != 0; }
bool IsCompressed() const { return (Flags & NResourceFlags::Compressed) != 0; }
bool IsEmpty() const { return (UnpackSize == 0); } bool IsEmpty() const { return (UnpackSize == 0); }
}; };
@@ -111,30 +124,38 @@ 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 IsOldVersion() const { return (Version == 0x010A00); }
bool IsNewVersion()const { return (Version > 0x010C00); } bool IsNewVersion()const { return (Version > 0x010C00); }
bool AreFromOnArchive(const CHeader &h) bool AreFromOnArchive(const CHeader &h)
@@ -152,11 +173,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 +194,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 +248,26 @@ struct CDatabase
{ {
Streams.Clear(); Streams.Clear();
Items.Clear(); Items.Clear();
SortedItems.Clear();
NumImages = 0;
SkipRoot = true;
ShowImageNumber = true;
} }
UString GetItemPath(int index) const;
HRESULT Open(IInStream *inStream, const CHeader &h, CByteBuffer &xml, IArchiveOpenCallback *openCallback);
void DetectPathMode()
{
ShowImageNumber = (NumImages != 1);
}
HRESULT Sort(bool skipRootDir);
}; };
HRESULT ReadHeader(IInStream *inStream, CHeader &header); HRESULT ReadHeader(IInStream *inStream, CHeader &header);
HRESULT OpenArchive(IInStream *inStream, const CHeader &header, CByteBuffer &xml, CDatabase &database);
HRESULT SortDatabase(CDatabase &database);
class CUnpacker class CUnpacker
{ {

View File

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

View File

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

View File

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

View File

@@ -78,7 +78,7 @@ namespace NFileHeader
kWzAES = 0x63 kWzAES = 0x63
}; };
const int kNumCompressionMethods = 11; const int kNumCompressionMethods = 11;
const Byte kMadeByProgramVersion = 20; const Byte kMadeByProgramVersion = 63;
const Byte kExtractVersion_Default = 10; const Byte kExtractVersion_Default = 10;
const Byte kExtractVersion_Dir = 20; const Byte kExtractVersion_Dir = 20;

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

@@ -322,6 +322,7 @@ UDF_OBJS = \
WIM_OBJS = \ WIM_OBJS = \
$O\WimHandler.obj \ $O\WimHandler.obj \
$O\WimHandlerOut.obj \
$O\WimIn.obj \ $O\WimIn.obj \
$O\WimRegister.obj \ $O\WimRegister.obj \
@@ -357,7 +358,6 @@ COMPRESS_OBJS = \
$O\Deflate64Register.obj \ $O\Deflate64Register.obj \
$O\DeflateDecoder.obj \ $O\DeflateDecoder.obj \
$O\DeflateEncoder.obj \ $O\DeflateEncoder.obj \
$O\DeflateNsisRegister.obj \
$O\DeflateRegister.obj \ $O\DeflateRegister.obj \
$O\DeltaFilter.obj \ $O\DeltaFilter.obj \
$O\ImplodeDecoder.obj \ $O\ImplodeDecoder.obj \

View File

@@ -539,10 +539,6 @@ SOURCE=..\..\Compress\DeflateEncoder.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\Compress\DeflateNsisRegister.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\DeflateRegister.cpp SOURCE=..\..\Compress\DeflateRegister.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -2229,6 +2225,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 \
@@ -209,7 +210,6 @@ COMPRESS_OBJS = \
$O\Deflate64Register.obj \ $O\Deflate64Register.obj \
$O\DeflateDecoder.obj \ $O\DeflateDecoder.obj \
$O\DeflateEncoder.obj \ $O\DeflateEncoder.obj \
$O\DeflateNsisRegister.obj \
$O\DeflateRegister.obj \ $O\DeflateRegister.obj \
$O\DeltaFilter.obj \ $O\DeltaFilter.obj \
$O\ImplodeDecoder.obj \ $O\ImplodeDecoder.obj \

View File

@@ -32,5 +32,5 @@ MY_VERSION_INFO_DLL("7z Standalone Plugin", "7za")
STRINGTABLE STRINGTABLE
BEGIN BEGIN
100 "7z:0 zip:1 bz2:2 bzip2:2 tbz2:2 tbz:2 rar:3 arj:4 z:5 taz:5 lzh:6 lha:6 cab:7 iso:8 001:9 rpm:10 deb:11 cpio:12 tar:13 gz:14 gzip:14 tgz:14 tpz:14 wim:15 swm:15 lzma:16 dmg:17 hfs:18 xar:19 vhd:20 fat:21 ntfs:22 xz:23" 100 "7z:0 zip:1 bz2:2 bzip2:2 tbz2:2 tbz:2 rar:3 arj:4 z:5 taz:5 lzh:6 lha:6 cab:7 iso:8 001:9 rpm:10 deb:11 cpio:12 tar:13 gz:14 gzip:14 tgz:14 tpz:14 wim:15 swm:15 lzma:16 dmg:17 hfs:18 xar:19 vhd:20 fat:21 ntfs:22 xz:23 txz:23"
END END

View File

@@ -164,7 +164,7 @@ Byte CByteInBufWrap::ReadByteFromNewBlock()
return 0; return 0;
} }
extern "C" static Byte Wrap_ReadByte(void *pp) static Byte Wrap_ReadByte(void *pp)
{ {
CByteInBufWrap *p = (CByteInBufWrap *)pp; CByteInBufWrap *p = (CByteInBufWrap *)pp;
if (p->Cur != p->Lim) if (p->Cur != p->Lim)
@@ -210,7 +210,7 @@ HRESULT CByteOutBufWrap::Flush()
return Res; return Res;
} }
extern "C" static void Wrap_WriteByte(void *pp, Byte b) static void Wrap_WriteByte(void *pp, Byte b)
{ {
CByteOutBufWrap *p = (CByteOutBufWrap *)pp; CByteOutBufWrap *p = (CByteOutBufWrap *)pp;
Byte *dest = p->Cur; Byte *dest = p->Cur;

View File

@@ -4,9 +4,6 @@
#include "../../../C/Alloc.h" #include "../../../C/Alloc.h"
#include "../../Common/Defs.h"
#include "BZip2Crc.h"
#include "BZip2Decoder.h" #include "BZip2Decoder.h"
#include "Mtf8.h" #include "Mtf8.h"
@@ -15,11 +12,11 @@ namespace NBZip2 {
#define NO_INLINE MY_FAST_CALL #define NO_INLINE MY_FAST_CALL
const UInt32 kNumThreadsMax = 4; static const UInt32 kNumThreadsMax = 4;
static const UInt32 kBufferSize = (1 << 17); static const UInt32 kBufferSize = (1 << 17);
static Int16 kRandNums[512] = { static const UInt16 kRandNums[512] = {
619, 720, 127, 481, 931, 816, 813, 233, 566, 247, 619, 720, 127, 481, 931, 816, 813, 233, 566, 247,
985, 724, 205, 454, 863, 491, 741, 242, 949, 214, 985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
733, 859, 335, 708, 621, 574, 73, 654, 730, 472, 733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
@@ -76,8 +73,8 @@ static Int16 kRandNums[512] = {
bool CState::Alloc() bool CState::Alloc()
{ {
if (Counters == 0) if (!Counters)
Counters = (UInt32 *)BigAlloc((256 + kBlockSizeMax) * sizeof(UInt32)); Counters = (UInt32 *)::BigAlloc((256 + kBlockSizeMax) * sizeof(UInt32));
return (Counters != 0); return (Counters != 0);
} }
@@ -87,7 +84,7 @@ void CState::Free()
Counters = 0; Counters = 0;
} }
UInt32 CDecoder::ReadBits(int numBits) { return m_InStream.ReadBits(numBits); } UInt32 CDecoder::ReadBits(unsigned numBits) { return m_InStream.ReadBits(numBits); }
Byte CDecoder::ReadByte() {return (Byte)ReadBits(8); } Byte CDecoder::ReadByte() {return (Byte)ReadBits(8); }
bool CDecoder::ReadBit() { return ReadBits(1) != 0; } bool CDecoder::ReadBit() { return ReadBits(1) != 0; }
@@ -102,21 +99,22 @@ UInt32 CDecoder::ReadCrc()
return crc; return crc;
} }
UInt32 NO_INLINE ReadBits(NBitm::CDecoder<CInBuffer> *m_InStream, int num) static UInt32 NO_INLINE ReadBits(NBitm::CDecoder<CInBuffer> *m_InStream, unsigned num)
{ {
return m_InStream->ReadBits(num); return m_InStream->ReadBits(num);
} }
UInt32 NO_INLINE ReadBit(NBitm::CDecoder<CInBuffer> *m_InStream) static UInt32 NO_INLINE ReadBit(NBitm::CDecoder<CInBuffer> *m_InStream)
{ {
return m_InStream->ReadBits(1); return m_InStream->ReadBits(1);
} }
static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder<CInBuffer> *m_InStream, static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder<CInBuffer> *m_InStream,
UInt32 *CharCounters, UInt32 blockSizeMax, Byte *m_Selectors, CHuffmanDecoder *m_HuffmanDecoders, UInt32 *CharCounters, UInt32 blockSizeMax, Byte *m_Selectors, CHuffmanDecoder *m_HuffmanDecoders,
UInt32 *blockSizeRes, UInt32 *origPtrRes, bool *randRes) UInt32 *blockSizeRes, UInt32 *origPtrRes, bool *randRes)
{ {
*randRes = ReadBit(m_InStream) ? true : false; if (randRes)
*randRes = ReadBit(m_InStream) ? true : false;
*origPtrRes = ReadBits(m_InStream, kNumOrigBits); *origPtrRes = ReadBits(m_InStream, kNumOrigBits);
// in original code it compares OrigPtr to (UInt32)(10 + blockSizeMax)) : why ? // in original code it compares OrigPtr to (UInt32)(10 + blockSizeMax)) : why ?
@@ -258,7 +256,7 @@ static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder<CInBuffer> *m_InStream,
return (*origPtrRes < blockSize) ? S_OK : S_FALSE; return (*origPtrRes < blockSize) ? S_OK : S_FALSE;
} }
void NO_INLINE DecodeBlock1(UInt32 *charCounters, UInt32 blockSize) static void NO_INLINE DecodeBlock1(UInt32 *charCounters, UInt32 blockSize)
{ {
{ {
UInt32 sum = 0; UInt32 sum = 0;
@@ -283,13 +281,13 @@ static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32
// it's for speed optimization: prefetch & prevByte_init; // it's for speed optimization: prefetch & prevByte_init;
UInt32 tPos = tt[tt[OrigPtr] >> 8]; UInt32 tPos = tt[tt[OrigPtr] >> 8];
unsigned int prevByte = (unsigned int)(tPos & 0xFF); unsigned prevByte = (unsigned)(tPos & 0xFF);
int numReps = 0; unsigned numReps = 0;
do do
{ {
unsigned int b = (unsigned int)(tPos & 0xFF); unsigned b = (unsigned)(tPos & 0xFF);
tPos = tt[tPos >> 8]; tPos = tt[tPos >> 8];
if (numReps == kRleModeRepSize) if (numReps == kRleModeRepSize)
@@ -315,7 +313,7 @@ static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32
m_OutStream.WriteByte((Byte)b); m_OutStream.WriteByte((Byte)b);
for (; --blockSize != 0;) for (; --blockSize != 0;)
{ {
b = (unsigned int)(tPos & 0xFF); b = (unsigned)(tPos & 0xFF);
tPos = tt[tPos >> 8]; tPos = tt[tPos >> 8];
crc.UpdateByte(b); crc.UpdateByte(b);
m_OutStream.WriteByte((Byte)b); m_OutStream.WriteByte((Byte)b);
@@ -327,7 +325,7 @@ static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32
if (--blockSize == 0) if (--blockSize == 0)
break; break;
b = (unsigned int)(tPos & 0xFF); b = (unsigned)(tPos & 0xFF);
tPos = tt[tPos >> 8]; tPos = tt[tPos >> 8];
crc.UpdateByte(b); crc.UpdateByte(b);
m_OutStream.WriteByte((Byte)b); m_OutStream.WriteByte((Byte)b);
@@ -339,7 +337,7 @@ static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32
if (--blockSize == 0) if (--blockSize == 0)
break; break;
b = (unsigned int)(tPos & 0xFF); b = (unsigned)(tPos & 0xFF);
tPos = tt[tPos >> 8]; tPos = tt[tPos >> 8];
crc.UpdateByte(b); crc.UpdateByte(b);
m_OutStream.WriteByte((Byte)b); m_OutStream.WriteByte((Byte)b);
@@ -354,7 +352,7 @@ static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32
if (blockSize == 0) if (blockSize == 0)
break; break;
b = (unsigned int)(tPos & 0xFF); b = (unsigned)(tPos & 0xFF);
tPos = tt[tPos >> 8]; tPos = tt[tPos >> 8];
for (; b > 0; b--) for (; b > 0; b--)
@@ -375,15 +373,15 @@ static UInt32 NO_INLINE DecodeBlock2Rand(const UInt32 *tt, UInt32 blockSize, UIn
UInt32 randIndex = 1; UInt32 randIndex = 1;
UInt32 randToGo = kRandNums[0] - 2; UInt32 randToGo = kRandNums[0] - 2;
int numReps = 0; unsigned numReps = 0;
// it's for speed optimization: prefetch & prevByte_init; // it's for speed optimization: prefetch & prevByte_init;
UInt32 tPos = tt[tt[OrigPtr] >> 8]; UInt32 tPos = tt[tt[OrigPtr] >> 8];
unsigned int prevByte = (unsigned int)(tPos & 0xFF); unsigned prevByte = (unsigned)(tPos & 0xFF);
do do
{ {
unsigned int b = (unsigned int)(tPos & 0xFF); unsigned b = (unsigned)(tPos & 0xFF);
tPos = tt[tPos >> 8]; tPos = tt[tPos >> 8];
{ {
@@ -449,7 +447,7 @@ HRESULT CDecoder::Create()
try try
{ {
m_States = new CState[NumThreads]; m_States = new CState[NumThreads];
if (m_States == 0) if (!m_States)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
catch(...) { return E_OUTOFMEMORY; } catch(...) { return E_OUTOFMEMORY; }
@@ -487,6 +485,7 @@ void CDecoder::Free()
delete []m_States; delete []m_States;
m_States = 0; m_States = 0;
} }
#endif #endif
HRESULT CDecoder::ReadSignatures(bool &wasFinished, UInt32 &crc) HRESULT CDecoder::ReadSignatures(bool &wasFinished, UInt32 &crc)
@@ -794,6 +793,7 @@ STDMETHODIMP CDecoder::SetNumberOfThreads(UInt32 numThreads)
NumThreads = kNumThreadsMax; NumThreads = kNumThreadsMax;
return S_OK; return S_OK;
} }
#endif #endif
HRESULT CDecoder::SetRatioProgress(UInt64 packSize) HRESULT CDecoder::SetRatioProgress(UInt64 packSize)
@@ -805,4 +805,138 @@ HRESULT CDecoder::SetRatioProgress(UInt64 packSize)
return Progress->SetRatioInfo(&packSize, &unpackSize); return Progress->SetRatioInfo(&packSize, &unpackSize);
} }
// ---------- NSIS ----------
enum
{
NSIS_STATE_INIT,
NSIS_STATE_NEW_BLOCK,
NSIS_STATE_DATA,
NSIS_STATE_FINISHED,
NSIS_STATE_ERROR
};
STDMETHODIMP CNsisDecoder::SetInStream(ISequentialInStream *inStream) { m_InStream.SetStream(inStream); return S_OK; }
STDMETHODIMP CNsisDecoder::ReleaseInStream() { m_InStream.ReleaseStream(); return S_OK; }
STDMETHODIMP CNsisDecoder::SetOutStreamSize(const UInt64 * /* outSize */)
{
_nsisState = NSIS_STATE_INIT;
return S_OK;
}
STDMETHODIMP CNsisDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
{
try {
*processedSize = 0;
if (_nsisState == NSIS_STATE_FINISHED)
return S_OK;
if (_nsisState == NSIS_STATE_ERROR)
return S_FALSE;
if (size == 0)
return S_OK;
CState &state = m_State;
if (_nsisState == NSIS_STATE_INIT)
{
if (!m_InStream.Create(kBufferSize))
return E_OUTOFMEMORY;
if (!state.Alloc())
return E_OUTOFMEMORY;
m_InStream.Init();
_nsisState = NSIS_STATE_NEW_BLOCK;
}
if (_nsisState == NSIS_STATE_NEW_BLOCK)
{
Byte b = (Byte)m_InStream.ReadBits(8);
if (b == kFinSig0)
{
_nsisState = NSIS_STATE_FINISHED;
return S_OK;
}
if (b != kBlockSig0)
{
_nsisState = NSIS_STATE_ERROR;
return S_FALSE;
}
UInt32 origPtr;
RINOK(ReadBlock(&m_InStream, state.Counters, 9 * kBlockSizeStep,
m_Selectors, m_HuffmanDecoders, &_blockSize, &origPtr, NULL));
DecodeBlock1(state.Counters, _blockSize);
const UInt32 *tt = state.Counters + 256;
_tPos = tt[tt[origPtr] >> 8];
_prevByte = (unsigned)(_tPos & 0xFF);
_numReps = 0;
_repRem = 0;
_nsisState = NSIS_STATE_DATA;
}
UInt32 tPos = _tPos;
unsigned prevByte = _prevByte;
unsigned numReps = _numReps;
UInt32 blockSize = _blockSize;
const UInt32 *tt = state.Counters + 256;
while (_repRem)
{
_repRem--;
*(Byte *)data = (Byte)prevByte;
data = (Byte *)data + 1;
(*processedSize)++;
if (--size == 0)
return S_OK;
}
if (blockSize == 0)
{
_nsisState = NSIS_STATE_NEW_BLOCK;
return S_OK;
}
do
{
unsigned b = (unsigned)(tPos & 0xFF);
tPos = tt[tPos >> 8];
blockSize--;
if (numReps == kRleModeRepSize)
{
numReps = 0;
while (b)
{
b--;
*(Byte *)data = (Byte)prevByte;
data = (Byte *)data + 1;
(*processedSize)++;
if (--size == 0)
break;
}
_repRem = b;
continue;
}
if (b != prevByte)
numReps = 0;
numReps++;
prevByte = b;
*(Byte *)data = (Byte)b;
data = (Byte *)data + 1;
(*processedSize)++;
size--;
}
while (size && blockSize);
_tPos = tPos;
_prevByte = prevByte;
_numReps = numReps;
_blockSize = blockSize;
return S_OK;
}
catch(const CInBufferException &e) { return e.ErrorCode; }
catch(...) { return S_FALSE; }
}
}} }}

View File

@@ -76,11 +76,10 @@ private:
bool _needInStreamInit; bool _needInStreamInit;
UInt32 ReadBits(int numBits); UInt32 ReadBits(unsigned numBits);
Byte ReadByte(); Byte ReadByte();
bool ReadBit(); bool ReadBit();
UInt32 ReadCrc(); UInt32 ReadCrc();
HRESULT PrepareBlock(CState &state);
HRESULT DecodeFile(bool &isBZ, ICompressProgressInfo *progress); HRESULT DecodeFile(bool &isBZ, ICompressProgressInfo *progress);
HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
bool &isBZ, ICompressProgressInfo *progress); bool &isBZ, ICompressProgressInfo *progress);
@@ -168,6 +167,39 @@ public:
#endif #endif
}; };
class CNsisDecoder :
public ISequentialInStream,
public ICompressSetInStream,
public ICompressSetOutStreamSize,
public CMyUnknownImp
{
NBitm::CDecoder<CInBuffer> m_InStream;
Byte m_Selectors[kNumSelectorsMax];
CHuffmanDecoder m_HuffmanDecoders[kNumTablesMax];
CState m_State;
int _nsisState;
UInt32 _tPos;
unsigned _prevByte;
unsigned _repRem;
unsigned _numReps;
UInt32 _blockSize;
public:
MY_QUERYINTERFACE_BEGIN2(ISequentialInStream)
MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
STDMETHOD(ReleaseInStream)();
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
};
}} }}
#endif #endif

View File

@@ -1,14 +0,0 @@
// DeflateNsisRegister.cpp
#include "StdAfx.h"
#include "../Common/RegisterCodec.h"
#include "DeflateDecoder.h"
static void *CreateCodecDeflateNsis() { return (void *)(ICompressCoder *)(new NCompress::NDeflate::NDecoder::CNsisCOMCoder); }
static CCodecInfo g_CodecInfo =
{ CreateCodecDeflateNsis, 0, 0x040901, L"DeflateNSIS", 1, false };
REGISTER_CODEC(DeflateNsis)

View File

@@ -627,7 +627,6 @@ public:
CCoderReleaser(CDecoder *coder): m_Coder(coder) {} CCoderReleaser(CDecoder *coder): m_Coder(coder) {}
~CCoderReleaser() ~CCoderReleaser()
{ {
// m_Coder->m_OutWindowStream.Flush();
m_Coder->ReleaseStreams(); m_Coder->ReleaseStreams();
} }
}; };
@@ -821,7 +820,7 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
return S_OK; return S_OK;
} }
for(;;) for (;;)
{ {
bool keepDecompressing; bool keepDecompressing;
if (_lzMode) if (_lzMode)
@@ -838,9 +837,10 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
break; break;
} }
RINOK(WriteBuf()); RINOK(WriteBuf());
UInt64 packSize = m_InBitStream.bitDecoder.GetProcessedSize();
RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize));
if (_writtenFileSize < _unpackSize) if (_writtenFileSize < _unpackSize)
return S_FALSE; return S_FALSE;
// return m_OutWindowStream.Flush();
return S_OK; return S_OK;
} }

View File

@@ -114,6 +114,12 @@ HRESULT CDecoder::CheckPassword(bool &passwOK)
_key.KeySize = 16 + algId * 8; _key.KeySize = 16 + algId * 8;
if ((flags & 1) == 0) if ((flags & 1) == 0)
return E_NOTIMPL; return E_NOTIMPL;
if ((flags & 0x4000) != 0)
{
// Use 3DES
return E_NOTIMPL;
}
UInt32 rdSize = GetUi16(p + 8); UInt32 rdSize = GetUi16(p + 8);
if ((rdSize & 0xF) != 0 || rdSize + 16 > _remSize) if ((rdSize & 0xF) != 0 || rdSize + 16 > _remSize)
return E_NOTIMPL; return E_NOTIMPL;

View File

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

View File

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

View File

@@ -514,11 +514,9 @@ 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);
@@ -536,11 +534,9 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices,
CMyComBSTR name; CMyComBSTR name;
PROPID propID; PROPID propID;
VARTYPE vt; VARTYPE vt;
if (archive->GetPropertyInfo(j, &name, &propID, &vt) != S_OK) RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt));
continue;
NCOM::CPropVariant prop; NCOM::CPropVariant prop;
if (archive->GetProperty(mainIndex, propID, &prop) != S_OK) RINOK(archive->GetProperty(mainIndex, 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);

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

@@ -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

@@ -236,12 +236,12 @@ private:
void ChangeWindowSize(int xSize, int ySize); void ChangeWindowSize(int xSize, int ySize);
void InitColumns(); HRESULT InitColumns();
// void InitColumns2(PROPID sortID); // void InitColumns2(PROPID sortID);
void InsertColumn(int index); void InsertColumn(int index);
void SetFocusedSelectedItem(int index, bool select); void SetFocusedSelectedItem(int index, bool select);
void RefreshListCtrl(const UString &focusedName, int focusedPos, bool selectFocused, HRESULT RefreshListCtrl(const UString &focusedName, int focusedPos, bool selectFocused,
const UStringVector &selectedNames); const UStringVector &selectedNames);
void OnShiftSelectMessage(); void OnShiftSelectMessage();
@@ -335,8 +335,8 @@ public:
void GetSelectedNames(UStringVector &selectedNames); void GetSelectedNames(UStringVector &selectedNames);
void SaveSelectedState(CSelectedState &s); void SaveSelectedState(CSelectedState &s);
void RefreshListCtrl(const CSelectedState &s); HRESULT RefreshListCtrl(const CSelectedState &s);
void RefreshListCtrlSaveFocused(); HRESULT RefreshListCtrlSaveFocused();
UString GetItemName(int itemIndex) const; UString GetItemName(int itemIndex) const;
UString GetItemPrefix(int itemIndex) const; UString GetItemPrefix(int itemIndex) const;
@@ -517,7 +517,7 @@ public:
// bool _passwordIsDefined; // bool _passwordIsDefined;
// UString _password; // UString _password;
void RefreshListCtrl(); HRESULT RefreshListCtrl();
void MessageBoxInfo(LPCWSTR message, LPCWSTR caption); void MessageBoxInfo(LPCWSTR message, LPCWSTR caption);
void MessageBox(LPCWSTR message); void MessageBox(LPCWSTR message);

View File

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

View File

@@ -55,7 +55,7 @@ static int GetColumnAlign(PROPID propID, VARTYPE varType)
} }
} }
void CPanel::InitColumns() HRESULT CPanel::InitColumns()
{ {
if (_needSaveInfo) if (_needSaveInfo)
SaveListViewInfo(); SaveListViewInfo();
@@ -88,8 +88,7 @@ void CPanel::InitColumns()
PROPID propID; PROPID propID;
VARTYPE varType; VARTYPE varType;
if (_folder->GetPropertyInfo(i, &name, &propID, &varType) != S_OK) RINOK(_folder->GetPropertyInfo(i, &name, &propID, &varType));
throw 1;
if (propID == kpidIsDir) if (propID == kpidIsDir)
continue; continue;
@@ -110,7 +109,7 @@ void CPanel::InitColumns()
break; break;
int order = 0; int order = 0;
for(i = 0; i < _listViewInfo.Columns.Size(); i++) for (i = 0; i < _listViewInfo.Columns.Size(); i++)
{ {
const CColumnInfo &columnInfo = _listViewInfo.Columns[i]; const CColumnInfo &columnInfo = _listViewInfo.Columns[i];
int index = _properties.FindItemWithID(columnInfo.PropID); int index = _properties.FindItemWithID(columnInfo.PropID);
@@ -124,7 +123,7 @@ void CPanel::InitColumns()
continue; continue;
} }
} }
for(i = 0; i < _properties.Size(); i++) for (i = 0; i < _properties.Size(); i++)
{ {
CItemProperty &item = _properties[i]; CItemProperty &item = _properties[i];
if (item.Order < 0) if (item.Order < 0)
@@ -155,6 +154,7 @@ void CPanel::InitColumns()
{ {
InsertColumn(i); InsertColumn(i);
} }
return S_OK;
} }
void CPanel::InsertColumn(int index) void CPanel::InsertColumn(int index)
@@ -170,9 +170,9 @@ void CPanel::InsertColumn(int index)
_listView.InsertColumn(index, &column); _listView.InsertColumn(index, &column);
} }
void CPanel::RefreshListCtrl() HRESULT CPanel::RefreshListCtrl()
{ {
RefreshListCtrl(UString(), -1, true, UStringVector()); return RefreshListCtrl(UString(), -1, true, UStringVector());
} }
int CALLBACK CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData); int CALLBACK CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData);
@@ -239,19 +239,19 @@ void CPanel::SaveSelectedState(CSelectedState &s)
GetSelectedNames(s.SelectedNames); GetSelectedNames(s.SelectedNames);
} }
void CPanel::RefreshListCtrl(const CSelectedState &s) HRESULT CPanel::RefreshListCtrl(const CSelectedState &s)
{ {
bool selectFocused = s.SelectFocused; bool selectFocused = s.SelectFocused;
if (_mySelectMode) if (_mySelectMode)
selectFocused = true; selectFocused = true;
RefreshListCtrl(s.FocusedName, s.FocusedItem, selectFocused, s.SelectedNames); return RefreshListCtrl(s.FocusedName, s.FocusedItem, selectFocused, s.SelectedNames);
} }
void CPanel::RefreshListCtrlSaveFocused() HRESULT CPanel::RefreshListCtrlSaveFocused()
{ {
CSelectedState state; CSelectedState state;
SaveSelectedState(state); SaveSelectedState(state);
RefreshListCtrl(state); return RefreshListCtrl(state);
} }
void CPanel::SetFocusedSelectedItem(int index, bool select) void CPanel::SetFocusedSelectedItem(int index, bool select)
@@ -268,7 +268,7 @@ void CPanel::SetFocusedSelectedItem(int index, bool select)
} }
} }
void CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool selectFocused, HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool selectFocused,
const UStringVector &selectedNames) const UStringVector &selectedNames)
{ {
_dontShowMode = false; _dontShowMode = false;
@@ -309,11 +309,8 @@ void CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool se
if (folderSetFlatMode) if (folderSetFlatMode)
folderSetFlatMode->SetFlatMode(BoolToInt(_flatMode)); folderSetFlatMode->SetFlatMode(BoolToInt(_flatMode));
if (_folder->LoadItems() != S_OK) RINOK(_folder->LoadItems());
return; RINOK(InitColumns());
InitColumns();
// OutputDebugString(TEXT("Start Dir\n")); // OutputDebugString(TEXT("Start Dir\n"));
UInt32 numItems; UInt32 numItems;
@@ -345,13 +342,13 @@ void CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool se
item.iImage = _extToIconMap.GetIconIndex(attrib, itemName); item.iImage = _extToIconMap.GetIconIndex(attrib, itemName);
if (item.iImage < 0) if (item.iImage < 0)
item.iImage = 0; item.iImage = 0;
if(_listView.InsertItem(&item) == -1) if (_listView.InsertItem(&item) == -1)
return; return E_FAIL;
} }
// OutputDebugStringA("S1\n"); // OutputDebugStringA("S1\n");
for(UInt32 i = 0; i < numItems; i++) for (UInt32 i = 0; i < numItems; i++)
{ {
UString itemName = GetItemName(i); UString itemName = GetItemName(i);
const UString relPath = GetItemRelPath(i); const UString relPath = GetItemRelPath(i);
@@ -400,7 +397,7 @@ void CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool se
item.pszText = (wchar_t *)(const wchar_t *)itemName; item.pszText = (wchar_t *)(const wchar_t *)itemName;
NCOM::CPropVariant prop; NCOM::CPropVariant prop;
_folder->GetProperty(i, kpidAttrib, &prop); RINOK(_folder->GetProperty(i, kpidAttrib, &prop));
UInt32 attrib = 0; UInt32 attrib = 0;
if (prop.vt == VT_UI4) if (prop.vt == VT_UI4)
attrib = prop.ulVal; attrib = prop.ulVal;
@@ -430,12 +427,12 @@ void CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool se
if (item.iImage < 0) if (item.iImage < 0)
item.iImage = 0; item.iImage = 0;
if(_listView.InsertItem(&item) == -1) if (_listView.InsertItem(&item) == -1)
return; // error return E_FAIL; // error
} }
// OutputDebugStringA("End2\n"); // OutputDebugStringA("End2\n");
if(_listView.GetItemCount() > 0 && cursorIndex >= 0) if (_listView.GetItemCount() > 0 && cursorIndex >= 0)
SetFocusedSelectedItem(cursorIndex, selectFocused); SetFocusedSelectedItem(cursorIndex, selectFocused);
_listView.SortItems(CompareItems, (LPARAM)this); _listView.SortItems(CompareItems, (LPARAM)this);
if (cursorIndex < 0 && _listView.GetItemCount() > 0) if (cursorIndex < 0 && _listView.GetItemCount() > 0)
@@ -452,6 +449,7 @@ void CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool se
/* /*
_listView.UpdateWindow(); _listView.UpdateWindow();
*/ */
return S_OK;
} }
void CPanel::GetSelectedItemsIndices(CRecordVector<UInt32> &indices) const void CPanel::GetSelectedItemsIndices(CRecordVector<UInt32> &indices) const
@@ -482,7 +480,7 @@ void CPanel::GetOperatedItemIndices(CRecordVector<UInt32> &indices) const
int focusedItem = _listView.GetFocusedItem(); int focusedItem = _listView.GetFocusedItem();
if (focusedItem >= 0) if (focusedItem >= 0)
{ {
if(_listView.GetItemState(focusedItem, LVIS_SELECTED) == LVIS_SELECTED) if (_listView.GetItemState(focusedItem, LVIS_SELECTED) == LVIS_SELECTED)
{ {
int realIndex = GetRealItemIndex(focusedItem); int realIndex = GetRealItemIndex(focusedItem);
if (realIndex != kParentIndex) if (realIndex != kParentIndex)
@@ -572,7 +570,7 @@ void CPanel::OpenSelectedItems(bool tryInternal)
} }
bool dirIsStarted = false; bool dirIsStarted = false;
for(int i = 0; i < indices.Size(); i++) for (int i = 0; i < indices.Size(); i++)
{ {
UInt32 index = indices[i]; UInt32 index = indices[i];
// CFileInfo &aFile = m_Files[index]; // CFileInfo &aFile = m_Files[index];
@@ -666,7 +664,7 @@ void CPanel::ReadListViewInfo()
void CPanel::SaveListViewInfo() void CPanel::SaveListViewInfo()
{ {
int i; int i;
for(i = 0; i < _visibleProperties.Size(); i++) for (i = 0; i < _visibleProperties.Size(); i++)
{ {
CItemProperty &prop = _visibleProperties[i]; CItemProperty &prop = _visibleProperties[i];
LVCOLUMN winColumnInfo; LVCOLUMN winColumnInfo;
@@ -683,7 +681,7 @@ void CPanel::SaveListViewInfo()
PROPID sortPropID = _sortID; PROPID sortPropID = _sortID;
_visibleProperties.Sort(); _visibleProperties.Sort();
for(i = 0; i < _visibleProperties.Size(); i++) for (i = 0; i < _visibleProperties.Size(); i++)
{ {
const CItemProperty &prop = _visibleProperties[i]; const CItemProperty &prop = _visibleProperties[i];
CColumnInfo columnInfo; CColumnInfo columnInfo;
@@ -692,7 +690,7 @@ void CPanel::SaveListViewInfo()
columnInfo.Width = prop.Width; columnInfo.Width = prop.Width;
viewInfo.Columns.Add(columnInfo); viewInfo.Columns.Add(columnInfo);
} }
for(i = 0; i < _properties.Size(); i++) for (i = 0; i < _properties.Size(); i++)
{ {
const CItemProperty &prop = _properties[i]; const CItemProperty &prop = _properties[i];
if (!prop.IsVisible) if (!prop.IsVisible)
@@ -719,7 +717,7 @@ void CPanel::SaveListViewInfo()
bool CPanel::OnRightClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActiveate, LRESULT &result) bool CPanel::OnRightClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActiveate, LRESULT &result)
{ {
if(itemActiveate->hdr.hwndFrom == HWND(_listView)) if (itemActiveate->hdr.hwndFrom == HWND(_listView))
return false; return false;
POINT point; POINT point;
::GetCursorPos(&point); ::GetCursorPos(&point);
@@ -737,7 +735,7 @@ void CPanel::ShowColumnsContextMenu(int x, int y)
menu.CreatePopup(); menu.CreatePopup();
const int kCommandStart = 100; const int kCommandStart = 100;
for(int i = 0; i < _properties.Size(); i++) for (int i = 0; i < _properties.Size(); i++)
{ {
const CItemProperty &prop = _properties[i]; const CItemProperty &prop = _properties[i];
UINT flags = MF_STRING; UINT flags = MF_STRING;
@@ -785,7 +783,9 @@ void CPanel::ShowColumnsContextMenu(int x, int y)
void CPanel::OnReload() void CPanel::OnReload()
{ {
RefreshListCtrlSaveFocused(); HRESULT res = RefreshListCtrlSaveFocused();
if (res != S_OK)
MessageBoxError(res);
OnRefreshStatusBar(); OnRefreshStatusBar();
} }

View File

@@ -149,9 +149,10 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
if (needRead) if (needRead)
*/ */
if (_folder->GetProperty(realIndex, propID, &prop) != S_OK) HRESULT res = _folder->GetProperty(realIndex, propID, &prop);
throw 2723407; if (res != S_OK)
s = UString(L"Error: ") + HResultToMessage(res);
else
if ((prop.vt == VT_UI8 || prop.vt == VT_UI4) && ( if ((prop.vt == VT_UI8 || prop.vt == VT_UI4) && (
propID == kpidSize || propID == kpidSize ||
propID == kpidPackSize || propID == kpidPackSize ||

View File

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

View File

@@ -50,6 +50,8 @@ CPropVariant& CPropVariant::operator=(BSTR bstrSrc)
return *this; return *this;
} }
static const char *kMemException = "out of memory";
CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc)
{ {
InternalClear(); InternalClear();
@@ -58,8 +60,9 @@ CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc)
bstrVal = ::SysAllocString(lpszSrc); bstrVal = ::SysAllocString(lpszSrc);
if (bstrVal == NULL && lpszSrc != NULL) if (bstrVal == NULL && lpszSrc != NULL)
{ {
vt = VT_ERROR; throw kMemException;
scode = E_OUTOFMEMORY; // vt = VT_ERROR;
// scode = E_OUTOFMEMORY;
} }
return *this; return *this;
} }
@@ -74,8 +77,9 @@ CPropVariant& CPropVariant::operator=(const char *s)
bstrVal = ::SysAllocStringByteLen(0, (UINT)len * sizeof(OLECHAR)); bstrVal = ::SysAllocStringByteLen(0, (UINT)len * sizeof(OLECHAR));
if (bstrVal == NULL) if (bstrVal == NULL)
{ {
vt = VT_ERROR; throw kMemException;
scode = E_OUTOFMEMORY; // vt = VT_ERROR;
// scode = E_OUTOFMEMORY;
} }
else else
{ {
@@ -204,6 +208,8 @@ void CPropVariant::InternalCopy(const PROPVARIANT *pSrc)
HRESULT hr = Copy(pSrc); HRESULT hr = Copy(pSrc);
if (FAILED(hr)) if (FAILED(hr))
{ {
if (hr == E_OUTOFMEMORY)
throw kMemException;
vt = VT_ERROR; vt = VT_ERROR;
scode = hr; scode = hr;
} }

View File

@@ -62,7 +62,6 @@ fm\index.htm
fm\menu.htm fm\menu.htm
fm\about.htm fm\about.htm
fm\plugins\index.htm fm\plugins\index.htm
fm\plugins\7-zip\options.htm
fm\plugins\7-zip\extract.htm fm\plugins\7-zip\extract.htm
fm\plugins\7-zip\index.htm fm\plugins\7-zip\index.htm
fm\plugins\7-zip\add.htm fm\plugins\7-zip\add.htm

View File

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

View File

@@ -2,7 +2,7 @@
;Defines ;Defines
!define VERSION_MAJOR 9 !define VERSION_MAJOR 9
!define VERSION_MINOR 13 !define VERSION_MINOR 16
!define VERSION_POSTFIX_FULL " beta" !define VERSION_POSTFIX_FULL " beta"
!ifdef WIN64 !ifdef WIN64
!ifdef IA64 !ifdef IA64
@@ -206,7 +206,9 @@ Section
File fur.txt File fur.txt
File fy.txt File fy.txt
File gl.txt File gl.txt
File gu.txt
File he.txt File he.txt
File hi.txt
File hr.txt File hr.txt
File hu.txt File hu.txt
File hy.txt File hy.txt
@@ -237,6 +239,7 @@ Section
File pt-br.txt File pt-br.txt
File ro.txt File ro.txt
File ru.txt File ru.txt
File sa.txt
File si.txt File si.txt
File sk.txt File sk.txt
File sl.txt File sl.txt
@@ -397,7 +400,9 @@ Section "Uninstall"
Delete $INSTDIR\Lang\fur.txt Delete $INSTDIR\Lang\fur.txt
Delete $INSTDIR\Lang\fy.txt Delete $INSTDIR\Lang\fy.txt
Delete $INSTDIR\Lang\gl.txt Delete $INSTDIR\Lang\gl.txt
Delete $INSTDIR\Lang\gu.txt
Delete $INSTDIR\Lang\he.txt Delete $INSTDIR\Lang\he.txt
Delete $INSTDIR\Lang\hi.txt
Delete $INSTDIR\Lang\hr.txt Delete $INSTDIR\Lang\hr.txt
Delete $INSTDIR\Lang\hu.txt Delete $INSTDIR\Lang\hu.txt
Delete $INSTDIR\Lang\hy.txt Delete $INSTDIR\Lang\hy.txt
@@ -428,6 +433,7 @@ Section "Uninstall"
Delete $INSTDIR\Lang\pt-br.txt Delete $INSTDIR\Lang\pt-br.txt
Delete $INSTDIR\Lang\ro.txt Delete $INSTDIR\Lang\ro.txt
Delete $INSTDIR\Lang\ru.txt Delete $INSTDIR\Lang\ru.txt
Delete $INSTDIR\Lang\sa.txt
Delete $INSTDIR\Lang\si.txt Delete $INSTDIR\Lang\si.txt
Delete $INSTDIR\Lang\sk.txt Delete $INSTDIR\Lang\sk.txt
Delete $INSTDIR\Lang\sl.txt Delete $INSTDIR\Lang\sl.txt

View File

@@ -1,7 +1,7 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<?define VerMajor = "9" ?> <?define VerMajor = "9" ?>
<?define VerMinor = "13" ?> <?define VerMinor = "16" ?>
<?define VerBuild = "00" ?> <?define VerBuild = "00" ?>
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?> <?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
<?define MmHex = "0$(var.VerMajor)$(var.VerMinor)" ?> <?define MmHex = "0$(var.VerMajor)$(var.VerMinor)" ?>
@@ -248,7 +248,9 @@
<File Id="fur.txt" Name="fur.txt" /> <File Id="fur.txt" Name="fur.txt" />
<File Id="fy.txt" Name="fy.txt" /> <File Id="fy.txt" Name="fy.txt" />
<File Id="gl.txt" Name="gl.txt" /> <File Id="gl.txt" Name="gl.txt" />
<File Id="gu.txt" Name="gu.txt" />
<File Id="he.txt" Name="he.txt" /> <File Id="he.txt" Name="he.txt" />
<File Id="hi.txt" Name="hi.txt" />
<File Id="hr.txt" Name="hr.txt" /> <File Id="hr.txt" Name="hr.txt" />
<File Id="hu.txt" Name="hu.txt" /> <File Id="hu.txt" Name="hu.txt" />
<File Id="hy.txt" Name="hy.txt" /> <File Id="hy.txt" Name="hy.txt" />
@@ -279,6 +281,7 @@
<File Id="pt_br.txt" Name="pt-br.txt" /> <File Id="pt_br.txt" Name="pt-br.txt" />
<File Id="ro.txt" Name="ro.txt" /> <File Id="ro.txt" Name="ro.txt" />
<File Id="ru.txt" Name="ru.txt" /> <File Id="ru.txt" Name="ru.txt" />
<File Id="sa.txt" Name="sa.txt" />
<File Id="si.txt" Name="si.txt" /> <File Id="si.txt" Name="si.txt" />
<File Id="sk.txt" Name="sk.txt" /> <File Id="sk.txt" Name="sk.txt" />
<File Id="sl.txt" Name="sl.txt" /> <File Id="sl.txt" Name="sl.txt" />

View File

@@ -1,4 +1,4 @@
LZMA SDK 9.12 LZMA SDK 9.16
------------- -------------
LZMA SDK provides the documentation, samples, header files, libraries, LZMA SDK provides the documentation, samples, header files, libraries,
@@ -20,7 +20,7 @@ LICENSE
LZMA SDK is written and placed in the public domain by Igor Pavlov. LZMA SDK is written and placed in the public domain by Igor Pavlov.
Some code in LZMA is based on public domain code from another developers: Some code in LZMA SDK is based on public domain code from another developers:
1) PPMd var.H (2001): Dmitry Shkarin 1) PPMd var.H (2001): Dmitry Shkarin
2) SHA-256: Wei Dai (Crypto++ library) 2) SHA-256: Wei Dai (Crypto++ library)
@@ -37,7 +37,7 @@ LZMA SDK includes:
UNIX/Linux version UNIX/Linux version
------------------ ------------------
To compile C++ version of file->file LZMA encoding, go to directory To compile C++ version of file->file LZMA encoding, go to directory
C++/7zip/Compress/LZMA_Alone CPP/7zip/Bundles/LzmaCon
and call make to recompile it: and call make to recompile it:
make -f makefile.gcc clean all make -f makefile.gcc clean all
@@ -91,8 +91,6 @@ CPP/ -- CPP files
Compress - files related to compression/decompression Compress - files related to compression/decompression
LZMA_Alone - file->file LZMA compression/decompression
Archive - files related to archiving Archive - files related to archiving
Common - common files for archive handling Common - common files for archive handling
@@ -101,6 +99,7 @@ CPP/ -- CPP files
Bundles - Modules that are bundles of other modules Bundles - Modules that are bundles of other modules
Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2 Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2
LzmaCon - lzma.exe: LZMA compression/decompression
Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2 Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2
Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2. Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2.

View File

@@ -1,4 +1,4 @@
7-Zip 9.13 Sources 7-Zip 9.16 Sources
------------------ ------------------
7-Zip is a file archiver for Windows. 7-Zip is a file archiver for Windows.