Compare commits

..

4 Commits
9.13 ... 9.17

Author SHA1 Message Date
Igor Pavlov
2eb60a0598 9.17 2016-05-28 00:16:04 +01:00
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
163 changed files with 2749 additions and 1146 deletions

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/* Lzma2Enc.c -- LZMA2 Encoder
2010-03-25 : Igor Pavlov : Public domain */
2010-09-24 : Igor Pavlov : Public domain */
/* #include <stdio.h> */
#include <string.h>
@@ -141,7 +141,7 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
PRF(printf(" "));
outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | (u >> 16) & 0x1F);
outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F));
outBuf[destPos++] = (Byte)(u >> 8);
outBuf[destPos++] = (Byte)u;
outBuf[destPos++] = (Byte)(pm >> 8);
@@ -269,7 +269,7 @@ static SRes Lzma2Enc_EncodeMt1(CLzma2EncInt *p, CLzma2Enc *mainEncoder,
if (mainEncoder->outBuf == 0)
{
mainEncoder->outBuf = IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
mainEncoder->outBuf = (Byte *)IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
if (mainEncoder->outBuf == 0)
return SZ_ERROR_MEM;
}

View File

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

View File

@@ -1,5 +1,5 @@
/* MtCoder.c -- Multi-thread Coder
2010-03-24 : Igor Pavlov : Public domain */
2010-09-24 : Igor Pavlov : Public domain */
#include <stdio.h>
@@ -148,7 +148,7 @@ static void CMtThread_Destruct(CMtThread *p)
#define MY_BUF_ALLOC(buf, size, newSize) \
if (buf == 0 || size != newSize) \
{ IAlloc_Free(p->mtCoder->alloc, buf); \
size = newSize; buf = IAlloc_Alloc(p->mtCoder->alloc, size); \
size = newSize; buf = (Byte *)IAlloc_Alloc(p->mtCoder->alloc, size); \
if (buf == 0) return SZ_ERROR_MEM; }
static SRes CMtThread_Prepare(CMtThread *p)

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,5 @@
/* Sort.c -- Sort functions
2008-08-17
Igor Pavlov
Public domain */
2010-09-17 : Igor Pavlov : Public domain */
#include "Sort.h"
@@ -92,4 +90,4 @@ void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size)
}
while (size > 1);
}
*/
*/

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/* LzmaUtil.c -- Test application for LZMA compression
2009-08-14 : Igor Pavlov : Public domain */
2010-09-20 : Igor Pavlov : Public domain */
#define _CRT_SECURE_NO_WARNINGS
@@ -249,6 +249,6 @@ int MY_CDECL main(int numArgs, const char *args[])
{
char rs[800] = { 0 };
int res = main2(numArgs, args, rs);
printf(rs);
fputs(rs, stdout);
return res;
}

12
C/Xz.h
View File

@@ -1,14 +1,12 @@
/* Xz.h - Xz interface
2009-04-15 : Igor Pavlov : Public domain */
2010-09-17 : Igor Pavlov : Public domain */
#ifndef __XZ_H
#define __XZ_H
#include "Sha256.h"
#ifdef __cplusplus
extern "C" {
#endif
EXTERN_C_BEGIN
#define XZ_ID_Subblock 1
#define XZ_ID_Delta 3
@@ -140,7 +138,7 @@ typedef enum
CODER_STATUS_NOT_SPECIFIED, /* use main error code instead */
CODER_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
CODER_STATUS_NOT_FINISHED, /* stream was not finished */
CODER_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
CODER_STATUS_NEEDS_MORE_INPUT /* you must provide more input bytes */
} ECoderStatus;
typedef enum
@@ -249,8 +247,6 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p);
#ifdef __cplusplus
}
#endif
EXTERN_C_END
#endif

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -120,7 +120,7 @@ public:
kUnsupportedVersion = 0,
kUnsupported,
kIncorrect,
kEndOfData,
kEndOfData
} Cause;
CInArchiveException(CCauseType cause): Cause(cause) {};
};

View File

@@ -19,32 +19,33 @@ struct CPropMap
CPropMap kPropMap[] =
{
{ NID::kName, NULL, kpidPath, VT_BSTR},
{ NID::kSize, NULL, kpidSize, VT_UI8},
{ NID::kPackInfo, NULL, kpidPackSize, VT_UI8},
{ NID::kName, { NULL, kpidPath, VT_BSTR } },
{ NID::kSize, { NULL, kpidSize, VT_UI8 } },
{ NID::kPackInfo, { NULL, kpidPackSize, VT_UI8 } },
#ifdef _MULTI_PACK
{ 100, L"Pack0", kpidPackedSize0, VT_UI8},
{ 101, L"Pack1", kpidPackedSize1, VT_UI8},
{ 102, L"Pack2", kpidPackedSize2, VT_UI8},
{ 103, L"Pack3", kpidPackedSize3, VT_UI8},
{ 104, L"Pack4", kpidPackedSize4, VT_UI8},
{ 100, { L"Pack0", kpidPackedSize0, VT_UI8 } },
{ 101, { L"Pack1", kpidPackedSize1, VT_UI8 } },
{ 102, { L"Pack2", kpidPackedSize2, VT_UI8 } },
{ 103, { L"Pack3", kpidPackedSize3, VT_UI8 } },
{ 104, { L"Pack4", kpidPackedSize4, VT_UI8 } },
#endif
{ NID::kCTime, NULL, kpidCTime, VT_FILETIME},
{ NID::kMTime, NULL, kpidMTime, VT_FILETIME},
{ NID::kATime, NULL, kpidATime, VT_FILETIME},
{ NID::kWinAttributes, NULL, kpidAttrib, VT_UI4},
{ NID::kStartPos, NULL, kpidPosition, VT_UI4},
{ NID::kCTime, { NULL, kpidCTime, VT_FILETIME } },
{ NID::kMTime, { NULL, kpidMTime, VT_FILETIME } },
{ NID::kATime, { NULL, kpidATime, VT_FILETIME } },
{ NID::kWinAttributes, { NULL, kpidAttrib, VT_UI4 } },
{ NID::kStartPos, { NULL, kpidPosition, VT_UI4 } },
{ NID::kCRC, NULL, kpidCRC, VT_UI4},
{ NID::kCRC, { NULL, kpidCRC, VT_UI4 } },
{ NID::kAnti, NULL, kpidIsAnti, VT_BOOL},
{ NID::kAnti, { NULL, kpidIsAnti, VT_BOOL } }
#ifndef _SFX
{ 97, NULL, kpidEncrypted, VT_BOOL},
{ 98, NULL, kpidMethod, VT_BSTR},
{ 99, NULL, kpidBlock, VT_UI4}
,
{ 97, { NULL,kpidEncrypted, VT_BOOL } },
{ 98, { NULL,kpidMethod, VT_BSTR } },
{ 99, { NULL,kpidBlock, VT_UI4 } }
#endif
};

View File

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

View File

@@ -264,7 +264,7 @@ struct CInArchiveException
{
kUnexpectedEndOfArchive = 0,
kCRCError,
kIncorrectArchive,
kIncorrectArchive
}
Cause;
CInArchiveException(CCauseType cause): Cause(cause) {};

View File

@@ -41,7 +41,7 @@ enum
};
#endif
STATPROPSTG kProps[] =
static STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidSize, VT_UI8},
@@ -57,18 +57,18 @@ STATPROPSTG kProps[] =
#endif
};
static const wchar_t *kMethods[] =
static const char *kMethods[] =
{
L"None",
L"MSZip",
L"Quantum",
L"LZX"
"None",
"MSZip",
"Quantum",
"LZX"
};
static const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]);
static const wchar_t *kUnknownMethod = L"Unknown";
static const char *kUnknownMethod = "Unknown";
STATPROPSTG kArcProps[] =
static STATPROPSTG kArcProps[] =
{
{ NULL, kpidMethod, VT_BSTR},
// { NULL, kpidSolid, VT_BOOL},
@@ -87,7 +87,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
case kpidMethod:
{
UString resString;
AString resString;
CRecordVector<Byte> ids;
int i;
for (int v = 0; v < m_Database.Volumes.Size(); v++)
@@ -99,9 +99,9 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
for (i = 0; i < ids.Size(); i++)
{
Byte id = ids[i];
UString method = (id < kNumMethods) ? kMethods[id] : kUnknownMethod;
AString method = (id < kNumMethods) ? kMethods[id] : kUnknownMethod;
if (!resString.IsEmpty())
resString += L' ';
resString += ' ';
resString += method;
}
prop = resString;
@@ -171,12 +171,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
UInt32 realFolderIndex = item.GetFolderIndex(db.Folders.Size());
const CFolder &folder = db.Folders[realFolderIndex];
int methodIndex = folder.GetCompressionMethod();
UString method = (methodIndex < kNumMethods) ? kMethods[methodIndex] : kUnknownMethod;
AString method = (methodIndex < kNumMethods) ? kMethods[methodIndex] : kUnknownMethod;
if (methodIndex == NHeader::NCompressionMethodMajor::kLZX ||
methodIndex == NHeader::NCompressionMethodMajor::kQuantum)
{
method += L":";
wchar_t temp[32];
method += ':';
char temp[32];
ConvertUInt64ToString(folder.CompressionTypeMinor, temp);
method += temp;
}

View File

@@ -9,18 +9,15 @@
#include "ChmIn.h"
namespace NArchive{
namespace NChm{
namespace NArchive {
namespace NChm {
// define CHM_LOW, if you want to see low level items
// #define CHM_LOW
static const GUID kChmLzxGuid =
{ 0x7FC28940, 0x9D31, 0x11D0, 0x9B, 0x27, 0x00, 0xA0, 0xC9, 0x1E, 0x9C, 0x7C };
static const GUID kHelp2LzxGuid =
{ 0x0A9007C6, 0x4076, 0x11D3, 0x87, 0x89, 0x00, 0x00, 0xF8, 0x10, 0x57, 0x54 };
static const GUID kDesGuid =
{ 0x67F6E4A2, 0x60BF, 0x11D3, 0x85, 0x40, 0x00, 0xC0, 0x4F, 0x58, 0xC3, 0xCF };
static const GUID kChmLzxGuid = { 0x7FC28940, 0x9D31, 0x11D0, { 0x9B, 0x27, 0x00, 0xA0, 0xC9, 0x1E, 0x9C, 0x7C } };
static const GUID kHelp2LzxGuid = { 0x0A9007C6, 0x4076, 0x11D3, { 0x87, 0x89, 0x00, 0x00, 0xF8, 0x10, 0x57, 0x54 } };
static const GUID kDesGuid = { 0x67F6E4A2, 0x60BF, 0x11D3, { 0x85, 0x40, 0x00, 0xC0, 0x4F, 0x58, 0xC3, 0xCF } };
static bool AreGuidsEqual(REFGUID g1, REFGUID g2)
{

View File

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

View File

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

View File

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

View File

@@ -3,8 +3,8 @@
#include "StdAfx.h"
#include "Common/ComTry.h"
#include "Common/StringToInt.h"
#include "Common/StringConvert.h"
#include "Common/StringToInt.h"
#include "Windows/PropVariant.h"
#include "Windows/Time.h"
@@ -25,10 +25,10 @@ namespace NFileHeader
{
namespace NMagic
{
extern const char *kMagic1 = "070701";
extern const char *kMagic2 = "070702";
extern const char *kMagic3 = "070707";
extern const char *kEndName = "TRAILER!!!";
const char *kMagic1 = "070701";
const char *kMagic2 = "070702";
const char *kMagic3 = "070707";
const char *kEndName = "TRAILER!!!";
const Byte kMagicForRecord2[2] = { 0xC7, 0x71 };
}

View File

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

View File

@@ -526,7 +526,14 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
item.Attrib = attrib;
item.Flags = p[12];
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.CTime2 = p[13];
item.ADate = Get16(p + 18);
@@ -578,8 +585,12 @@ HRESULT CDatabase::Open()
return S_FALSE;
UInt64 fileSize;
RINOK(InStream->Seek(0, STREAM_SEEK_END, &fileSize));
/* we comment that check to support truncated images */
/*
if (fileSize < Header.GetPhySize())
return S_FALSE;
*/
if (Header.IsFat32())
{

View File

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

View File

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

View File

@@ -378,7 +378,7 @@ static const char *GetOS(Byte osId)
if (g_OsPairs[i].Id == osId)
return g_OsPairs[i].Name;
return kUnknownOS;
};
}
static STATPROPSTG kProps[] =
{
@@ -400,7 +400,7 @@ public:
static UInt16 Table[256];
static void InitTable();
CCRC(): _value(0){};
CCRC(): _value(0) {}
void Init() { _value = 0; }
void Update(const void *data, size_t size);
UInt16 GetDigest() const { return _value; }
@@ -460,7 +460,6 @@ public:
void ReleaseStream() { _stream.Release(); }
UInt32 GetCRC() const { return _crc.GetDigest(); }
void InitCRC() { _crc.Init(); }
};
STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)
@@ -646,7 +645,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
totalUnPacked += item.Size;
totalPacked += item.PackSize;
}
extractCallback->SetTotal(totalUnPacked);
RINOK(extractCallback->SetTotal(totalUnPacked));
UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0;
UInt64 currentItemUnPacked, currentItemPacked;

View File

@@ -332,7 +332,7 @@ enum
{
kpidPrimary = kpidUserDefined,
kpidBegChs,
kpidEndChs,
kpidEndChs
};
STATPROPSTG kProps[] =

View File

@@ -7,15 +7,14 @@
#include "../../Common/StreamUtils.h"
#include "../../Common/MethodId.h"
#include "../../Common/CreateCoder.h"
#include "../../Compress/BZip2Decoder.h"
#include "../../Compress/DeflateDecoder.h"
#include "../../Compress/LzmaDecoder.h"
namespace NArchive {
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;
HRESULT CDecoder::Init(
@@ -31,24 +30,14 @@ HRESULT CDecoder::Init(
_method = method;
if (!_codecInStream)
{
CMethodId methodID;
switch (method)
{
case NMethodType::kCopy: methodID = k_Copy; break;
case NMethodType::kDeflate: methodID = k_Deflate; break;
case NMethodType::kBZip2: methodID = k_BZip2; break;
case NMethodType::kLZMA: methodID = k_LZMA; break;
// case NMethodType::kCopy: return E_NOTIMPL;
case NMethodType::kDeflate: _codecInStream = new NCompress::NDeflate::NDecoder::CNsisCOMCoder(); break;
case NMethodType::kBZip2: _codecInStream = new NCompress::NBZip2::CNsisDecoder(); break;
case NMethodType::kLZMA: _codecInStream = new NCompress::NLzma::CDecoder(); break;
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)

View File

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

View File

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

View File

@@ -156,7 +156,7 @@ struct CMftRef
#define ATNAME(n) ATTR_TYPE_ ## n
#define DEF_ATTR_TYPE(v, n) ATNAME(n) = v
typedef enum
enum
{
DEF_ATTR_TYPE(0x00, UNUSED),
DEF_ATTR_TYPE(0x10, STANDARD_INFO),
@@ -873,7 +873,7 @@ STDMETHODIMP CByteBufStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo
return S_OK;
}
HRESULT DataParseExtents(int clusterSizeLog, const CObjectVector<CAttr> attrs,
static HRESULT DataParseExtents(int clusterSizeLog, const CObjectVector<CAttr> &attrs,
int attrIndex, int attrIndexLim, UInt64 numPhysClusters, CRecordVector<CExtent> &Extents)
{
CExtent e;
@@ -969,6 +969,7 @@ struct CMftRec
void ParseDataNames();
HRESULT GetStream(IInStream *mainStream, int dataIndex,
int clusterSizeLog, UInt64 numPhysClusters, IInStream **stream) const;
int GetNumExtents(int dataIndex, int clusterSizeLog, UInt64 numPhysClusters) const;
UInt64 GetSize(int dataIndex) const { return DataAttrs[DataRefs[dataIndex].Start].GetSize(); }
@@ -1036,6 +1037,35 @@ HRESULT CMftRec::GetStream(IInStream *mainStream, int dataIndex,
return S_OK;
}
int CMftRec::GetNumExtents(int dataIndex, int clusterSizeLog, UInt64 numPhysClusters) const
{
if (dataIndex < 0)
return 0;
{
const CDataRef &ref = DataRefs[dataIndex];
int numNonResident = 0;
int i;
for (i = ref.Start; i < ref.Start + ref.Num; i++)
if (DataAttrs[i].NonResident)
numNonResident++;
const CAttr &attr0 = DataAttrs[ref.Start];
if (numNonResident != 0 || ref.Num != 1)
{
if (numNonResident != ref.Num || !attr0.IsCompressionUnitSupported())
return 0; // error;
CRecordVector<CExtent> extents;
if (DataParseExtents(clusterSizeLog, DataAttrs, ref.Start, ref.Start + ref.Num, numPhysClusters, extents) != S_OK)
return 0; // error;
return extents.Size() - 1;
}
// if (attr0.Data.GetCapacity() != 0)
// return 1;
return 0;
}
}
bool CMftRec::Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNumber,
CObjectVector<CAttr> *attrs)
{
@@ -1283,9 +1313,11 @@ HRESULT CDatabase::Open()
{
if (OpenCallback)
{
// Sleep(0);
UInt64 numFiles = Recs.Size();
RINOK(OpenCallback->SetCompleted(&numFiles, &pos64));
if ((numFiles & 0x3FF) == 0)
{
RINOK(OpenCallback->SetCompleted(&numFiles, &pos64));
}
}
UInt32 readSize = kBufSize;
UInt64 rem = mftSize - pos64;
@@ -1423,7 +1455,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
STATPROPSTG kProps[] =
static const STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL},
@@ -1433,10 +1465,11 @@ STATPROPSTG kProps[] =
{ NULL, kpidCTime, VT_FILETIME},
{ NULL, kpidATime, VT_FILETIME},
{ NULL, kpidAttrib, VT_UI4},
{ NULL, kpidLinks, VT_UI4}
{ NULL, kpidLinks, VT_UI4},
{ NULL, kpidNumBlocks, VT_UI4}
};
STATPROPSTG kArcProps[] =
static const STATPROPSTG kArcProps[] =
{
{ NULL, kpidVolumeName, VT_BSTR},
{ NULL, kpidFileSystem, VT_BSTR},
@@ -1580,6 +1613,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidLinks: prop = rec.MyNumNameLinks; break;
case kpidSize: if (data) prop = data->GetSize(); break;
case kpidPackSize: if (data) prop = data->GetPackSize(); break;
case kpidNumBlocks: if (data) prop = (UInt32)rec.GetNumExtents(item.DataIndex, Header.ClusterSizeLog, Header.NumClusters); break;
}
prop.Detach(value);
return S_OK;

View File

@@ -98,7 +98,7 @@ void CDirLink::Parse(const Byte *p)
{
Va = Get32(p);
Size = Get32(p + 4);
};
}
enum
{
@@ -991,7 +991,7 @@ bool CBitmapInfoHeader::Parse(const Byte *p, size_t size)
Compression = Get32(p + 16);
SizeImage = Get32(p + 20);
return true;
};
}
static UInt32 GetImageSize(UInt32 xSize, UInt32 ySize, UInt32 bitCount)
{

View File

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

View File

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

View File

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

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
#include "../../../../C/CpuArch.h"
#include "Common/StringToInt.h"
#include "../../Common/StreamUtils.h"
@@ -69,11 +71,20 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
filled = false;
processedSize = NFileHeader::kRecordSize;
RINOK(ReadStream(stream, buf, &processedSize));
if (processedSize == 0 || (processedSize == NFileHeader::kRecordSize && IsRecordLast(buf)))
return S_OK;
if (processedSize < NFileHeader::kRecordSize)
bool thereAreEmptyRecords = false;
for (;;)
{
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;
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.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;
UInt32 checkSum;

View File

@@ -53,17 +53,23 @@ static bool MakeOctalString8(char *s, UInt32 value)
return true;
}
static bool MakeOctalString12(char *s, UInt64 value)
static void MakeOctalString12(char *s, UInt64 value)
{
AString tempString = MakeOctalString(value);
const int kMaxSize = 12;
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();
for(int i = 0; i < numSpaces; i++)
s[i] = ' ';
memmove(s + numSpaces, (const char *)tempString, tempString.Length());
return true;
}
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);
cur += NFileHeader::kNameSize;
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.Mode));
cur += 8;
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.UID));
cur += 8;
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.GID));
cur += 8;
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.Mode)); cur += 8;
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.UID)); cur += 8;
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.GID)); cur += 8;
RETURN_IF_NOT_TRUE(MakeOctalString12(cur, item.Size));
cur += 12;
RETURN_IF_NOT_TRUE(MakeOctalString12(cur, item.MTime));
cur += 12;
MakeOctalString12(cur, item.Size); cur += 12;
MakeOctalString12(cur, item.MTime); cur += 12;
memmove(cur, NFileHeader::kCheckSumBlanks, 8);
cur += 8;

View File

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

View File

@@ -35,4 +35,3 @@ public:
}}
#endif

View File

@@ -202,7 +202,7 @@ enum EDescriptorType
DESC_TYPE_UnallocatedSpace = 263,
DESC_TYPE_SpaceBitmap = 264,
DESC_TYPE_PartitionIntegrity = 265,
DESC_TYPE_ExtendedFile = 266,
DESC_TYPE_ExtendedFile = 266
};

View File

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

View File

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

View File

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

View File

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

View File

@@ -18,11 +18,8 @@
#define Get32(p) GetUi32(p)
#define Get64(p) GetUi64(p)
namespace NArchive{
namespace NWim{
static const int kChunkSizeBits = 15;
static const UInt32 kChunkSize = (1 << kChunkSizeBits);
namespace NArchive {
namespace NWim {
namespace NXpress {
@@ -44,7 +41,7 @@ HRESULT CDecoder::CodeSpec(UInt32 outSize)
{
{
Byte levels[kMainTableSize];
for (int i = 0; i < kMainTableSize; i += 2)
for (unsigned i = 0; i < kMainTableSize; i += 2)
{
Byte b = m_InBitStream.DirectReadByte();
levels[i] = b & 0xF;
@@ -128,12 +125,6 @@ HRESULT CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outS
}
static void GetFileTimeFromMem(const Byte *p, FILETIME *ft)
{
ft->dwLowDateTime = Get32(p);
ft->dwHighDateTime = Get32(p + 4);
}
HRESULT CUnpacker::Unpack(IInStream *inStream, const CResource &resource, bool lzxMode,
ISequentialOutStream *outStream, ICompressProgressInfo *progress)
{
@@ -257,9 +248,6 @@ static HRESULT UnpackData(IInStream *inStream, const CResource &resource, bool l
return unpacker.Unpack(inStream, resource, lzxMode, outStream, NULL, digest);
}
static const UInt32 kSignatureSize = 8;
static const Byte kSignature[kSignatureSize] = { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 };
void CResource::Parse(const Byte *p)
{
Flags = p[7];
@@ -270,74 +258,300 @@ void CResource::Parse(const Byte *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.PartNumber = Get16(p + 24);
s.RefCount = Get32(p + 26);
memcpy(s.Hash, p + 30, kHashSize);
if (oldVersion)
{
s.PartNumber = 1;
s.Id = Get32(p + 24);
s.RefCount = 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,
const UString &prefix, CObjectVector<CItem> &items)
{
for (;;)
{
if (pos + 8 > size)
return S_FALSE;
const Byte *p = base + pos;
UInt64 length = Get64(p);
if (length == 0)
return S_OK;
if (pos + 102 > size || pos + length + 8 > size || length > ((UInt64)1 << 62))
return S_FALSE;
CItem item;
item.Attrib = Get32(p + 8);
// item.SecurityId = Get32(p + 0xC);
UInt64 subdirOffset = Get64(p + 0x10);
GetFileTimeFromMem(p + 0x28, &item.CTime);
GetFileTimeFromMem(p + 0x30, &item.ATime);
GetFileTimeFromMem(p + 0x38, &item.MTime);
memcpy(item.Hash, p + 0x40, kHashSize);
static const wchar_t *kLongPath = L"[LongPath]";
// UInt16 shortNameLen = Get16(p + 98);
UInt16 fileNameLen = Get16(p + 100);
size_t tempPos = pos + 102;
if (tempPos + fileNameLen > size)
return S_FALSE;
wchar_t *sz = item.Name.GetBuffer(prefix.Length() + fileNameLen / 2 + 1);
MyStringCopy(sz, (const wchar_t *)prefix);
sz += prefix.Length();
for (UInt16 i = 0; i + 2 <= fileNameLen; i += 2)
*sz++ = Get16(base + tempPos + i);
*sz++ = '\0';
item.Name.ReleaseBuffer();
if (fileNameLen == 0 && item.isDir() && !item.HasStream())
UString CDatabase::GetItemPath(const int index1) const
{
int size = 0;
int index = index1;
int newLevel;
for (newLevel = 0;; newLevel = 1)
{
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)
{
item.Attrib = 0x10; // some swm archives have system/hidden attributes for root
item.Name.Delete(item.Name.Length() - 1);
if (newLevel)
s[--size] = WCHAR_PATH_SEPARATOR;
size -= item.Name.Length();
memcpy(s + size, item.Name, sizeof(wchar_t) * item.Name.Length());
}
items.Add(item);
pos += (size_t)length;
if (item.isDir() && (subdirOffset != 0))
if (index < 0)
{
if (subdirOffset >= size)
return S_FALSE;
RINOK(ParseDirItem(base, (size_t)subdirOffset, size, item.Name + WCHAR_PATH_SEPARATOR, items));
path.ReleaseBuffer();
return path;
}
}
}
static HRESULT ParseDir(const Byte *base, size_t size,
const UString &prefix, CObjectVector<CItem> &items)
static void GetFileTimeFromMem(const Byte *p, FILETIME *ft)
{
size_t pos = 0;
if (pos + 8 > size)
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;
const Byte *p = base + pos;
wchar_t *s = dest.GetBuffer(size / 2);
for (int i = 0; i <= size; i += 2)
*s++ = Get16(p + i);
dest.ReleaseBuffer();
return S_OK;
}
HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
{
if ((pos & 7) != 0)
return S_FALSE;
int prevIndex = -1;
for (int numItems = 0;; numItems++)
{
if (OpenCallback)
{
UInt64 numFiles = Items.Size();
if ((numFiles & 0x3FF) == 0)
{
RINOK(OpenCallback->SetCompleted(&numFiles, NULL));
}
}
size_t rem = DirSize - pos;
if (pos < DirStartOffset || pos > DirSize || rem < 8)
return S_FALSE;
const Byte *p = DirData + pos;
UInt64 len = Get64(p);
if (len == 0)
{
if (parent < 0 && numItems != 1)
SkipRoot = false;
DirProcessed += 8;
return S_OK;
}
if ((len & 7) != 0 || rem < len)
return S_FALSE;
if (!IsOldVersion)
if (len < 0x28)
return S_FALSE;
DirProcessed += (size_t)len;
if (DirProcessed > DirSize)
return S_FALSE;
int extraOffset = 0;
if (IsOldVersion)
{
if (len < 0x40 || (/* Get32(p + 12) == 0 && */ Get32(p + 0x14) != 0))
{
extraOffset = 0x10;
}
}
else if (Get64(p + 8) == 0)
extraOffset = 0x24;
if (extraOffset)
{
if (prevIndex == -1)
return S_FALSE;
UInt32 fileNameLen = Get16(p + extraOffset);
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 (((extraOffset + 2 + fileNameLen2 + 6) & ~7) > len)
return S_FALSE;
UString name;
RINOK(ReadName(p + extraOffset + 2, fileNameLen, name));
CItem &prevItem = Items[prevIndex];
if (name.IsEmpty() && !prevItem.HasStream())
{
if (IsOldVersion)
prevItem.Id = Get32(p + 8);
else
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;
if (IsOldVersion)
{
item.Id = Get32(p + 8);
memset(item.Hash, 0, kHashSize);
}
else
memcpy(item.Hash, p + 0x10, kHashSize);
item.Attrib = 0;
item.Order = Order++;
item.Parent = parent;
Items.Add(item);
}
pos += (size_t)len;
continue;
}
UInt32 dirRecordSize = IsOldVersion ? kDirRecordSizeOld : kDirRecordSize;
if (len < dirRecordSize)
return S_FALSE;
CItem item;
item.Attrib = Get32(p + 8);
// item.SecurityId = Get32(p + 0xC);
UInt64 subdirOffset = Get64(p + 0x10);
UInt32 timeOffset = IsOldVersion ? 0x18: 0x28;
GetFileTimeFromMem(p + timeOffset, &item.CTime);
GetFileTimeFromMem(p + timeOffset + 8, &item.ATime);
GetFileTimeFromMem(p + timeOffset + 16, &item.MTime);
if (IsOldVersion)
{
item.Id = Get32(p + 0x10);
memset(item.Hash, 0, kHashSize);
}
else
{
memcpy(item.Hash, p + 0x40, kHashSize);
}
// UInt32 numStreams = Get16(p + dirRecordSize - 6);
UInt32 shortNameLen = Get16(p + dirRecordSize - 4);
UInt32 fileNameLen = Get16(p + dirRecordSize - 2);
if ((shortNameLen & 1) != 0 || (fileNameLen & 1) != 0)
return S_FALSE;
UInt32 shortNameLen2 = (shortNameLen == 0 ? shortNameLen : shortNameLen + 2);
UInt32 fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2);
if (((dirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7) > len)
return S_FALSE;
p += dirRecordSize;
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 -= dirRecordSize;
p += ((dirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7);
if (((dirRecordSize + 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.Parent = parent;
prevIndex = Items.Add(item);
if (item.IsDir() && subdirOffset != 0)
{
RINOK(ParseDirItem((size_t)subdirOffset, prevIndex));
}
Items[prevIndex].Order = Order++;
pos += (size_t)len;
}
}
HRESULT CDatabase::ParseImageDirs(const CByteBuffer &buf, int parent)
{
DirData = buf;
DirSize = buf.GetCapacity();
size_t pos = 0;
if (DirSize < 8)
return S_FALSE;
const Byte *p = DirData;
UInt32 totalLength = Get32(p);
if (IsOldVersion)
{
for (pos = 4;; pos += 8)
{
if (pos + 4 > DirSize)
return S_FALSE;
UInt32 n = Get32(p + pos);
if (n == 0)
break;
if (pos + 8 > DirSize)
return S_FALSE;
totalLength += Get32(p + pos + 4);
if (totalLength > DirSize)
return S_FALSE;
}
pos += totalLength + 4;
pos = (pos + 7) & ~(size_t)7;
if (pos > DirSize)
return S_FALSE;
}
else
{
// UInt32 numEntries = Get32(p + 4);
pos += 8;
{
@@ -346,30 +560,163 @@ static HRESULT ParseDir(const Byte *base, size_t size,
UInt64 sum = 0;
for (UInt32 i = 0; i < numEntries; i++)
{
if (pos + 8 > size)
if (pos + 8 > DirSize)
return S_FALSE;
UInt64 len = Get64(p + pos);
entryLens.Add(len);
sum += len;
pos += 8;
}
pos += sum; // skip security descriptors
pos += (size_t)sum; // skip security descriptors
while ((pos & 7) != 0)
pos++;
if (pos != totalLength)
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;
return memcmp(streams[*p1].Hash, streams[*p2].Hash, kHashSize);
UInt32 headerSize = Get32(p + 8);
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);
}
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;
}
static bool IsEmptySha(const Byte *data)
{
for (int i = 0; i < kHashSize; i++)
if (data[i] != 0)
return false;
return true;
}
HRESULT CDatabase::Open(IInStream *inStream, const CHeader &h, CByteBuffer &xml, IArchiveOpenCallback *openCallback)
{
OpenCallback = openCallback;
IsOldVersion = h.IsOldVersion();
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 &&
!(h.IsOldVersion() && IsEmptySha(si.Hash)))
return S_FALSE;
NumImages++;
RINOK(ParseImageDirs(metadata, -(int)(++imageIndex)));
if (needBootMetadata)
if (h.MetadataResource.Offset == si.Resource.Offset)
needBootMetadata = false;
}
}
if (needBootMetadata)
{
CByteBuffer metadata;
RINOK(UnpackData(inStream, h.MetadataResource, h.IsLzxMode(), metadata, NULL));
RINOK(ParseImageDirs(metadata, -1));
NumImages++;
}
return S_OK;
}
static int CompareStreamsByPos(const CStreamInfo *p1, const CStreamInfo *p2, void * /* param */)
{
int res = MyCompare(p1->PartNumber, p2->PartNumber);
@@ -378,24 +725,39 @@ static int CompareStreamsByPos(const CStreamInfo *p1, const CStreamInfo *p2, voi
return MyCompare(p1->Resource.Offset, p2->Resource.Offset);
}
int CompareItems(void *const *a1, void *const *a2, void * /* param */)
static int CompareIDs(const int *p1, const int *p2, void *param)
{
const CItem &i1 = **((const CItem **)a1);
const CItem &i2 = **((const CItem **)a2);
const CRecordVector<CStreamInfo> &streams = *(const CRecordVector<CStreamInfo> *)param;
return MyCompare(streams[*p1].Id, streams[*p2].Id);
}
if (i1.isDir() != i2.isDir())
return (i1.isDir()) ? 1 : -1;
if (i1.isDir())
return -MyStringCompareNoCase(i1.Name, i2.Name);
static int CompareHashRefs(const int *p1, const int *p2, void *param)
{
const CRecordVector<CStreamInfo> &streams = *(const CRecordVector<CStreamInfo> *)param;
return memcmp(streams[*p1].Hash, streams[*p2].Hash, kHashSize);
}
int res = MyCompare(i1.StreamIndex, i2.StreamIndex);
if (res != 0)
return res;
return MyStringCompareNoCase(i1.Name, i2.Name);
static int FindId(const CRecordVector<CStreamInfo> &streams,
const CIntVector &sortedByHash, UInt32 id)
{
int left = 0, right = streams.Size();
while (left != right)
{
int mid = (left + right) / 2;
int streamIndex = sortedByHash[mid];
UInt32 id2 = streams[streamIndex].Id;
if (id == id2)
return streamIndex;
if (id < id2)
right = mid;
else
left = mid + 1;
}
return -1;
}
static int FindHash(const CRecordVector<CStreamInfo> &streams,
const CRecordVector<int> &sortedByHash, const Byte *hash)
const CIntVector &sortedByHash, const Byte *hash)
{
int left = 0, right = streams.Size();
while (left != right)
@@ -417,153 +779,76 @@ static int FindHash(const CRecordVector<CStreamInfo> &streams,
return -1;
}
HRESULT CHeader::Parse(const Byte *p)
static int CompareItems(const int *a1, const int *a2, void *param)
{
UInt32 haderSize = Get32(p + 8);
if (haderSize < 0x74)
return S_FALSE;
Version = Get32(p + 0x0C);
Flags = Get32(p + 0x10);
if (!IsSupported())
return S_FALSE;
UInt32 chunkSize = Get32(p + 0x14);
if (chunkSize != kChunkSize && chunkSize != 0)
return S_FALSE;
memcpy(Guid, p + 0x18, 16);
PartNumber = Get16(p + 0x28);
NumParts = Get16(p + 0x2A);
int offset = 0x2C;
if (IsNewVersion())
{
NumImages = Get32(p + offset);
offset += 4;
}
GetResource(p + offset, OffsetResource);
GetResource(p + offset + 0x18, XmlResource);
GetResource(p + offset + 0x30, MetadataResource);
/*
if (IsNewVersion())
{
if (haderSize < 0xD0)
return S_FALSE;
IntegrityResource.Parse(p + offset + 0x4C);
BootIndex = Get32(p + 0x48);
}
*/
return S_OK;
const CObjectVector<CItem> &items = ((CDatabase *)param)->Items;
const CItem &i1 = items[*a1];
const CItem &i2 = items[*a2];
if (i1.IsDir() != i2.IsDir())
return i1.IsDir() ? 1 : -1;
int res = MyCompare(i1.StreamIndex, i2.StreamIndex);
if (res != 0)
return res;
return MyCompare(i1.Order, i2.Order);
}
HRESULT ReadHeader(IInStream *inStream, CHeader &h)
HRESULT CDatabase::Sort(bool skipRootDir)
{
const UInt32 kHeaderSizeMax = 0xD0;
Byte p[kHeaderSizeMax];
RINOK(ReadStream_FALSE(inStream, p, kHeaderSizeMax));
if (memcmp(p, kSignature, kSignatureSize) != 0)
return S_FALSE;
return h.Parse(p);
}
Streams.Sort(CompareStreamsByPos, NULL);
HRESULT ReadStreams(IInStream *inStream, const CHeader &h, CDatabase &db)
{
CByteBuffer offsetBuf;
RINOK(UnpackData(inStream, h.OffsetResource, h.IsLzxMode(), offsetBuf, NULL));
for (size_t i = 0; i + kStreamInfoSize <= offsetBuf.GetCapacity(); i += kStreamInfoSize)
{
CStreamInfo s;
GetStream((const Byte *)offsetBuf + i, s);
if (s.PartNumber == h.PartNumber)
db.Streams.Add(s);
}
return S_OK;
}
HRESULT OpenArchive(IInStream *inStream, const CHeader &h, CByteBuffer &xml, CDatabase &db)
{
RINOK(UnpackData(inStream, h.XmlResource, h.IsLzxMode(), xml, NULL));
RINOK(ReadStreams(inStream, h, db));
bool needBootMetadata = !h.MetadataResource.IsEmpty();
if (h.PartNumber == 1)
{
int imageIndex = 1;
for (int j = 0; j < db.Streams.Size(); j++)
CIntVector sortedByHash;
{
// if (imageIndex > 1) break;
const CStreamInfo &si = db.Streams[j];
if (!si.Resource.IsMetadata() || si.PartNumber != h.PartNumber)
continue;
Byte hash[kHashSize];
CByteBuffer metadata;
RINOK(UnpackData(inStream, si.Resource, h.IsLzxMode(), metadata, hash));
if (memcmp(hash, si.Hash, kHashSize) != 0)
return S_FALSE;
wchar_t sz[16];
ConvertUInt32ToString(imageIndex++, sz);
UString s = sz;
s += WCHAR_PATH_SEPARATOR;
RINOK(ParseDir(metadata, metadata.GetCapacity(), s, db.Items));
if (needBootMetadata)
if (h.MetadataResource.Offset == si.Resource.Offset)
needBootMetadata = false;
}
}
if (needBootMetadata)
{
CByteBuffer metadata;
RINOK(UnpackData(inStream, h.MetadataResource, h.IsLzxMode(), metadata, NULL));
RINOK(ParseDir(metadata, metadata.GetCapacity(), L"0" WSTRING_PATH_SEPARATOR, db.Items));
}
return S_OK;
}
HRESULT SortDatabase(CDatabase &db)
{
db.Streams.Sort(CompareStreamsByPos, NULL);
{
CRecordVector<int> sortedByHash;
{
for (int j = 0; j < db.Streams.Size(); j++)
sortedByHash.Add(j);
sortedByHash.Sort(CompareHashRefs, &db.Streams);
for (int i = 0; i < Streams.Size(); i++)
sortedByHash.Add(i);
if (IsOldVersion)
sortedByHash.Sort(CompareIDs, &Streams);
else
sortedByHash.Sort(CompareHashRefs, &Streams);
}
for (int i = 0; i < db.Items.Size(); i++)
for (int i = 0; i < Items.Size(); i++)
{
CItem &item = db.Items[i];
CItem &item = Items[i];
item.StreamIndex = -1;
if (item.HasStream())
item.StreamIndex = FindHash(db.Streams, sortedByHash, item.Hash);
if (IsOldVersion)
item.StreamIndex = FindId(Streams, sortedByHash, item.Id);
else
item.StreamIndex = FindHash(Streams, sortedByHash, item.Hash);
}
}
{
CRecordVector<bool> used;
int j;
for (j = 0; j < db.Streams.Size(); j++)
int i;
for (i = 0; i < Streams.Size(); i++)
{
const CStreamInfo &s = db.Streams[j];
const CStreamInfo &s = Streams[i];
used.Add(s.Resource.IsMetadata() && s.PartNumber == 1);
// used.Add(false);
}
for (int i = 0; i < db.Items.Size(); i++)
for (i = 0; i < Items.Size(); i++)
{
CItem &item = db.Items[i];
CItem &item = Items[i];
if (item.StreamIndex >= 0)
used[item.StreamIndex] = true;
}
for (j = 0; j < db.Streams.Size(); j++)
if (!used[j])
for (i = 0; i < Streams.Size(); i++)
if (!used[i])
{
CItem item;
item.StreamIndex = j;
item.StreamIndex = i;
item.HasMetadata = false;
db.Items.Add(item);
}
Items.Add(item);
}
}
db.Items.Sort(CompareItems, NULL);
SortedItems.Reserve(Items.Size());
for (int i = (skipRootDir ? 1 : 0); i < Items.Size(); i++)
SortedItems.Add(i);
SortedItems.Sort(CompareItems, this);
return S_OK;
}

View File

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

View File

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

View File

@@ -146,6 +146,7 @@ HRESULT CAddCommon::Compress(
opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default;
if (inCrcStreamSpec != 0)
RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
RINOK(outStream->SetSize(0));
RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL));
if (_options.PasswordIsDefined)
{
@@ -218,7 +219,7 @@ HRESULT CAddCommon::Compress(
_options.Algo,
_options.DicSize,
_options.NumFastBytes,
(BSTR)(const wchar_t *)_options.MatchFinder,
const_cast<BSTR>((const wchar_t *)_options.MatchFinder),
_options.NumMatchFinderCycles
};
PROPID propIDs[] =
@@ -373,7 +374,7 @@ HRESULT CAddCommon::Compress(
RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize));
}
opRes.Method = method;
return outStream->SetSize(opRes.PackSize);
return S_OK;
}
}}

View File

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

View File

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

View File

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

View File

@@ -544,7 +544,17 @@ HRESULT CInArchive::FindCd(CCdInfo &cdInfo)
UInt64 curPos = endPosition - bufSize + i;
UInt64 cdEnd = cdInfo.Size + cdInfo.Offset;
if (curPos != cdEnd)
ArcInfo.Base = curPos - cdEnd;
{
/*
if (cdInfo.Offset <= 16 && cdInfo.Size != 0)
{
// here we support some rare ZIP files with Central directory at the start
ArcInfo.Base = 0;
}
else
*/
ArcInfo.Base = curPos - cdEnd;
}
return S_OK;
}
}

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
#include "../../../../C/Alloc.h"
#include "Common/AutoPtr.h"
#include "Common/Defs.h"
#include "Common/StringConvert.h"
@@ -16,6 +18,7 @@
#ifndef _7ZIP_ST
#include "../../Common/ProgressMt.h"
#endif
#include "../../Common/StreamUtils.h"
#include "../../Compress/CopyCoder.h"
@@ -798,6 +801,216 @@ static HRESULT Update2(
#endif
}
static const size_t kCacheBlockSize = (1 << 20);
static const size_t kCacheSize = (kCacheBlockSize << 2);
static const size_t kCacheMask = (kCacheSize - 1);
class CCacheOutStream:
public IOutStream,
public CMyUnknownImp
{
CMyComPtr<IOutStream> _stream;
Byte *_cache;
UInt64 _virtPos;
UInt64 _virtSize;
UInt64 _phyPos;
UInt64 _phySize; // <= _virtSize
UInt64 _cachedPos; // (_cachedPos + _cachedSize) <= _virtSize
size_t _cachedSize;
HRESULT MyWrite(size_t size);
HRESULT MyWriteBlock()
{
return MyWrite(kCacheBlockSize - ((size_t)_cachedPos & (kCacheBlockSize - 1)));
}
HRESULT FlushCache();
public:
CCacheOutStream(): _cache(0) {}
~CCacheOutStream();
bool Allocate();
HRESULT Init(IOutStream *stream);
MY_UNKNOWN_IMP
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
STDMETHOD(SetSize)(UInt64 newSize);
};
bool CCacheOutStream::Allocate()
{
if (!_cache)
_cache = (Byte *)::MidAlloc(kCacheSize);
return (_cache != NULL);
}
HRESULT CCacheOutStream::Init(IOutStream *stream)
{
_virtPos = _phyPos = 0;
_stream = stream;
RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &_virtPos));
RINOK(_stream->Seek(0, STREAM_SEEK_END, &_virtSize));
RINOK(_stream->Seek(_virtPos, STREAM_SEEK_SET, &_virtPos));
_phyPos = _virtPos;
_phySize = _virtSize;
_cachedPos = 0;
_cachedSize = 0;
return S_OK;
}
HRESULT CCacheOutStream::MyWrite(size_t size)
{
while (size != 0 && _cachedSize != 0)
{
if (_phyPos != _cachedPos)
{
RINOK(_stream->Seek(_cachedPos, STREAM_SEEK_SET, &_phyPos));
}
size_t pos = (size_t)_cachedPos & kCacheMask;
size_t curSize = MyMin(kCacheSize - pos, _cachedSize);
curSize = MyMin(curSize, size);
RINOK(WriteStream(_stream, _cache + pos, curSize));
_phyPos += curSize;
if (_phySize < _phyPos)
_phySize = _phyPos;
_cachedPos += curSize;
_cachedSize -= curSize;
size -= curSize;
}
return S_OK;
}
HRESULT CCacheOutStream::FlushCache()
{
return MyWrite(_cachedSize);
}
CCacheOutStream::~CCacheOutStream()
{
FlushCache();
if (_virtSize != _phySize)
_stream->SetSize(_virtSize);
if (_virtPos != _phyPos)
_stream->Seek(_virtPos, STREAM_SEEK_SET, NULL);
::MidFree(_cache);
}
STDMETHODIMP CCacheOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
if (processedSize)
*processedSize = 0;
if (size == 0)
return S_OK;
UInt64 zerosStart = _virtPos;
if (_cachedSize != 0)
{
if (_virtPos < _cachedPos)
{
RINOK(FlushCache());
}
else
{
UInt64 cachedEnd = _cachedPos + _cachedSize;
if (cachedEnd < _virtPos)
{
if (cachedEnd < _phySize)
{
RINOK(FlushCache());
}
else
zerosStart = cachedEnd;
}
}
}
if (_cachedSize == 0 && _phySize < _virtPos)
_cachedPos = zerosStart = _phySize;
if (zerosStart != _virtPos)
{
// write zeros to [cachedEnd ... _virtPos)
for (;;)
{
UInt64 cachedEnd = _cachedPos + _cachedSize;
size_t endPos = (size_t)cachedEnd & kCacheMask;
size_t curSize = kCacheSize - endPos;
if (curSize > _virtPos - cachedEnd)
curSize = (size_t)(_virtPos - cachedEnd);
if (curSize == 0)
break;
while (curSize > (kCacheSize - _cachedSize))
{
RINOK(MyWriteBlock());
}
memset(_cache + endPos, 0, curSize);
_cachedSize += curSize;
}
}
if (_cachedSize == 0)
_cachedPos = _virtPos;
size_t pos = (size_t)_virtPos & kCacheMask;
size = (UInt32)MyMin((size_t)size, kCacheSize - pos);
UInt64 cachedEnd = _cachedPos + _cachedSize;
if (_virtPos != cachedEnd) // _virtPos < cachedEnd
size = (UInt32)MyMin((size_t)size, (size_t)(cachedEnd - _virtPos));
else
{
// _virtPos == cachedEnd
if (_cachedSize == kCacheSize)
{
RINOK(MyWriteBlock());
}
size_t startPos = (size_t)_cachedPos & kCacheMask;
if (startPos > pos)
size = (UInt32)MyMin((size_t)size, (size_t)(startPos - pos));
_cachedSize += size;
}
memcpy(_cache + pos, data, size);
if (processedSize)
*processedSize = size;
_virtPos += size;
if (_virtSize < _virtPos)
_virtSize = _virtPos;
return S_OK;
}
STDMETHODIMP CCacheOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
{
switch(seekOrigin)
{
case STREAM_SEEK_SET: _virtPos = offset; break;
case STREAM_SEEK_CUR: _virtPos += offset; break;
case STREAM_SEEK_END: _virtPos = _virtSize + offset; break;
default: return STG_E_INVALIDFUNCTION;
}
if (newPosition)
*newPosition = _virtPos;
return S_OK;
}
STDMETHODIMP CCacheOutStream::SetSize(UInt64 newSize)
{
_virtSize = newSize;
if (newSize < _phySize)
{
RINOK(_stream->SetSize(newSize));
_phySize = newSize;
}
if (newSize <= _cachedPos)
{
_cachedSize = 0;
_cachedPos = newSize;
}
if (newSize < _cachedPos + _cachedSize)
_cachedSize = (size_t)(newSize - _cachedPos);
return S_OK;
}
HRESULT Update(
DECL_EXTERNAL_CODECS_LOC_VARS
const CObjectVector<CItemEx> &inputItems,
@@ -808,9 +1021,17 @@ HRESULT Update(
IArchiveUpdateCallback *updateCallback)
{
CMyComPtr<IOutStream> outStream;
RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream));
if (!outStream)
return E_NOTIMPL;
{
CMyComPtr<IOutStream> outStreamReal;
seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStreamReal);
if (!outStreamReal)
return E_NOTIMPL;
CCacheOutStream *cacheStream = new CCacheOutStream();
outStream = cacheStream;
if (!cacheStream->Allocate())
return E_OUTOFMEMORY;
RINOK(cacheStream->Init(outStreamReal));
}
if (inArchive)
{

View File

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

View File

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

View File

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

View File

@@ -539,10 +539,6 @@ SOURCE=..\..\Compress\DeflateEncoder.h
# End Source File
# Begin Source File
SOURCE=..\..\Compress\DeflateNsisRegister.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Compress\DeflateRegister.cpp
# End Source File
# Begin Source File
@@ -2229,6 +2225,10 @@ SOURCE=..\..\Archive\Wim\WimHandler.h
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Wim\WimHandlerOut.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Wim\WimIn.cpp
# End Source File
# Begin Source File

View File

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

View File

@@ -32,5 +32,5 @@ MY_VERSION_INFO_DLL("7z Standalone Plugin", "7za")
STRINGTABLE
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

View File

@@ -88,7 +88,7 @@ static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]);
static void PrintMessage(const char *s)
{
fprintf(stderr, s);
fputs(s, stderr);
}
static void PrintHelp()
@@ -425,7 +425,7 @@ int main2(int numArgs, const char *args[])
props[5].ulVal = (UInt32)fb;
props[6].vt = VT_BSTR;
props[6].bstrVal = (BSTR)(const wchar_t *)mf;
props[6].bstrVal = const_cast<BSTR>((const wchar_t *)mf);
props[7].vt = VT_BOOL;
props[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE;

View File

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

View File

@@ -353,7 +353,7 @@ STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo
#endif
}
STDMETHODIMP COutFileStream::SetSize(Int64 newSize)
STDMETHODIMP COutFileStream::SetSize(UInt64 newSize)
{
#ifdef USE_WIN_FILE
UInt64 currentPos;
@@ -418,4 +418,5 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro
return S_OK;
#endif
}
#endif

View File

@@ -127,7 +127,7 @@ public:
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
STDMETHOD(SetSize)(Int64 newSize);
STDMETHOD(SetSize)(UInt64 newSize);
};
class CStdOutFileStream:

View File

@@ -92,7 +92,7 @@ STDMETHODIMP CFilterCoder::ReleaseOutStream()
{
_outStream.Release();
return S_OK;
};
}
STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize)
@@ -164,7 +164,7 @@ STDMETHODIMP CFilterCoder::ReleaseInStream()
{
_inStream.Release();
return S_OK;
};
}
STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
{

View File

@@ -29,7 +29,7 @@ STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin,
return result;
}
STDMETHODIMP COffsetOutStream::SetSize(Int64 newSize)
STDMETHODIMP COffsetOutStream::SetSize(UInt64 newSize)
{
return _stream->SetSize(_offset + newSize);
}

View File

@@ -19,7 +19,7 @@ public:
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
STDMETHOD(SetSize)(Int64 newSize);
STDMETHOD(SetSize)(UInt64 newSize);
};
#endif

View File

@@ -129,7 +129,7 @@ STDMETHODIMP COutMemStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPos
return S_OK;
}
STDMETHODIMP COutMemStream::SetSize(Int64 newSize)
STDMETHODIMP COutMemStream::SetSize(UInt64 newSize)
{
if (_realStreamMode)
{

View File

@@ -90,7 +90,7 @@ public:
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
STDMETHOD(SetSize)(Int64 newSize);
STDMETHOD(SetSize)(UInt64 newSize);
};
#endif

View File

@@ -4,22 +4,20 @@
#include "../../../C/Alloc.h"
#include "../../Common/Defs.h"
#include "BZip2Crc.h"
#include "BZip2Decoder.h"
#include "Mtf8.h"
namespace NCompress {
namespace NBZip2 {
#define NO_INLINE MY_FAST_CALL
const UInt32 kNumThreadsMax = 4;
#undef NO_INLINE
#define NO_INLINE
static const UInt32 kNumThreadsMax = 4;
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,
985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
@@ -76,8 +74,8 @@ static Int16 kRandNums[512] = {
bool CState::Alloc()
{
if (Counters == 0)
Counters = (UInt32 *)BigAlloc((256 + kBlockSizeMax) * sizeof(UInt32));
if (!Counters)
Counters = (UInt32 *)::BigAlloc((256 + kBlockSizeMax) * sizeof(UInt32));
return (Counters != 0);
}
@@ -87,7 +85,7 @@ void CState::Free()
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); }
bool CDecoder::ReadBit() { return ReadBits(1) != 0; }
@@ -102,21 +100,22 @@ UInt32 CDecoder::ReadCrc()
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);
}
UInt32 NO_INLINE ReadBit(NBitm::CDecoder<CInBuffer> *m_InStream)
static UInt32 NO_INLINE ReadBit(NBitm::CDecoder<CInBuffer> *m_InStream)
{
return m_InStream->ReadBits(1);
}
static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder<CInBuffer> *m_InStream,
UInt32 *CharCounters, UInt32 blockSizeMax, Byte *m_Selectors, CHuffmanDecoder *m_HuffmanDecoders,
UInt32 *blockSizeRes, UInt32 *origPtrRes, bool *randRes)
UInt32 *CharCounters, UInt32 blockSizeMax, Byte *m_Selectors, CHuffmanDecoder *m_HuffmanDecoders,
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);
// in original code it compares OrigPtr to (UInt32)(10 + blockSizeMax)) : why ?
@@ -258,7 +257,7 @@ static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder<CInBuffer> *m_InStream,
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;
@@ -283,13 +282,13 @@ static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32
// it's for speed optimization: prefetch & prevByte_init;
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
{
unsigned int b = (unsigned int)(tPos & 0xFF);
unsigned b = (unsigned)(tPos & 0xFF);
tPos = tt[tPos >> 8];
if (numReps == kRleModeRepSize)
@@ -315,7 +314,7 @@ static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32
m_OutStream.WriteByte((Byte)b);
for (; --blockSize != 0;)
{
b = (unsigned int)(tPos & 0xFF);
b = (unsigned)(tPos & 0xFF);
tPos = tt[tPos >> 8];
crc.UpdateByte(b);
m_OutStream.WriteByte((Byte)b);
@@ -327,7 +326,7 @@ static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32
if (--blockSize == 0)
break;
b = (unsigned int)(tPos & 0xFF);
b = (unsigned)(tPos & 0xFF);
tPos = tt[tPos >> 8];
crc.UpdateByte(b);
m_OutStream.WriteByte((Byte)b);
@@ -339,7 +338,7 @@ static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32
if (--blockSize == 0)
break;
b = (unsigned int)(tPos & 0xFF);
b = (unsigned)(tPos & 0xFF);
tPos = tt[tPos >> 8];
crc.UpdateByte(b);
m_OutStream.WriteByte((Byte)b);
@@ -354,7 +353,7 @@ static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32
if (blockSize == 0)
break;
b = (unsigned int)(tPos & 0xFF);
b = (unsigned)(tPos & 0xFF);
tPos = tt[tPos >> 8];
for (; b > 0; b--)
@@ -375,15 +374,15 @@ static UInt32 NO_INLINE DecodeBlock2Rand(const UInt32 *tt, UInt32 blockSize, UIn
UInt32 randIndex = 1;
UInt32 randToGo = kRandNums[0] - 2;
int numReps = 0;
unsigned numReps = 0;
// it's for speed optimization: prefetch & prevByte_init;
UInt32 tPos = tt[tt[OrigPtr] >> 8];
unsigned int prevByte = (unsigned int)(tPos & 0xFF);
unsigned prevByte = (unsigned)(tPos & 0xFF);
do
{
unsigned int b = (unsigned int)(tPos & 0xFF);
unsigned b = (unsigned)(tPos & 0xFF);
tPos = tt[tPos >> 8];
{
@@ -424,7 +423,7 @@ CDecoder::CDecoder()
m_States = 0;
m_NumThreadsPrev = 0;
NumThreads = 1;
#endif;
#endif
_needInStreamInit = true;
}
@@ -449,7 +448,7 @@ HRESULT CDecoder::Create()
try
{
m_States = new CState[NumThreads];
if (m_States == 0)
if (!m_States)
return E_OUTOFMEMORY;
}
catch(...) { return E_OUTOFMEMORY; }
@@ -487,6 +486,7 @@ void CDecoder::Free()
delete []m_States;
m_States = 0;
}
#endif
HRESULT CDecoder::ReadSignatures(bool &wasFinished, UInt32 &crc)
@@ -794,6 +794,7 @@ STDMETHODIMP CDecoder::SetNumberOfThreads(UInt32 numThreads)
NumThreads = kNumThreadsMax;
return S_OK;
}
#endif
HRESULT CDecoder::SetRatioProgress(UInt64 packSize)
@@ -805,4 +806,138 @@ HRESULT CDecoder::SetRatioProgress(UInt64 packSize)
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;
UInt32 ReadBits(int numBits);
UInt32 ReadBits(unsigned numBits);
Byte ReadByte();
bool ReadBit();
UInt32 ReadCrc();
HRESULT PrepareBlock(CState &state);
HRESULT DecodeFile(bool &isBZ, ICompressProgressInfo *progress);
HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
bool &isBZ, ICompressProgressInfo *progress);
@@ -168,6 +167,39 @@ public:
#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

View File

@@ -9,8 +9,10 @@
#include "DeflateEncoder.h"
#if _MSC_VER >= 1300
#define NO_INLINE __declspec(noinline)
#undef NO_INLINE
#ifdef _MSC_VER
#define NO_INLINE MY_NO_INLINE
#else
#define NO_INLINE
#endif
@@ -580,7 +582,7 @@ NO_INLINE UInt32 Huffman_GetPrice(const UInt32 *freqs, const Byte *lens, UInt32
for (i = 0; i < num; i++)
price += lens[i] * freqs[i];
return price;
};
}
NO_INLINE UInt32 Huffman_GetPrice_Spec(const UInt32 *freqs, const Byte *lens, UInt32 num, const Byte *extraBits, UInt32 extraBase)
{

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

@@ -164,7 +164,7 @@ void CDecoder::ClearPrevLevels()
m_LastMainLevels[i] = 0;
for (i = 0; i < kNumLenSymbols; i++)
m_LastLenLevels[i] = 0;
};
}
HRESULT CDecoder::CodeSpec(UInt32 curSize)

View File

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

View File

@@ -778,13 +778,13 @@ struct StandardFilterSignature
}
kStdFilters[]=
{
53, 0xad576887, SF_E8,
57, 0x3cd7e57e, SF_E8E9,
120, 0x3769893f, SF_ITANIUM,
29, 0x0e06077d, SF_DELTA,
149, 0x1c2c5dc8, SF_RGB,
216, 0xbc85e701, SF_AUDIO,
40, 0x46b9c560, SF_UPCASE
{ 53, 0xad576887, SF_E8 },
{ 57, 0x3cd7e57e, SF_E8E9 },
{ 120, 0x3769893f, SF_ITANIUM },
{ 29, 0x0e06077d, SF_DELTA },
{ 149, 0x1c2c5dc8, SF_RGB },
{ 216, 0xbc85e701, SF_AUDIO },
{ 40, 0x46b9c560, SF_UPCASE }
};
static int FindStandardFilter(const Byte *code, UInt32 codeSize)

View File

@@ -106,9 +106,9 @@ void CDecoder::Calculate()
unsigned i;
for (i = 0; i < kNumRounds; i++)
{
sha.Update(rawPassword, rawLength, _rar350Mode);
sha.UpdateRar(rawPassword, rawLength, _rar350Mode);
Byte pswNum[3] = { (Byte)i, (Byte)(i >> 8), (Byte)(i >> 16) };
sha.Update(pswNum, 3, _rar350Mode);
sha.UpdateRar(pswNum, 3, _rar350Mode);
if (i % (kNumRounds / 16) == 0)
{
NSha1::CContext shaTemp = sha;

View File

@@ -112,11 +112,29 @@ void CContextBase::PrepareBlock(UInt32 *block, unsigned size) const
block[curBufferPos++] = (UInt32)(lenInBits);
}
void CContext::Update(Byte *data, size_t size, bool rar350Mode)
void CContext::Update(const Byte *data, size_t size)
{
unsigned curBufferPos = _count2;
while (size--)
{
int pos = (int)(curBufferPos & 3);
if (pos == 0)
_buffer[curBufferPos >> 2] = 0;
_buffer[curBufferPos >> 2] |= ((UInt32)*data++) << (8 * (3 - pos));
if (++curBufferPos == kBlockSize)
{
curBufferPos = 0;
CContextBase::UpdateBlock(_buffer, false);
}
}
_count2 = curBufferPos;
}
void CContext::UpdateRar(Byte *data, size_t size, bool rar350Mode)
{
bool returnRes = false;
unsigned curBufferPos = _count2;
while (size-- > 0)
while (size--)
{
int pos = (int)(curBufferPos & 3);
if (pos == 0)
@@ -179,7 +197,7 @@ void CContext::Final(Byte *digest)
void CContext32::Update(const UInt32 *data, size_t size)
{
while (size-- > 0)
while (size--)
{
_buffer[_count2++] = *data++;
if (_count2 == kBlockSizeInWords)

View File

@@ -51,8 +51,8 @@ public:
class CContext: public CContextBase2
{
public:
void Update(Byte *data, size_t size, bool rar350Mode = false);
void Update(const Byte *data, size_t size) { Update((Byte *)data, size, false); }
void Update(const Byte *data, size_t size);
void UpdateRar(Byte *data, size_t size, bool rar350Mode);
void Final(Byte *digest);
};

View File

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

View File

@@ -42,7 +42,7 @@ STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03)
STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04)
{
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;
STDMETHOD(SetSize)(Int64 newSize) PURE;
STDMETHOD(SetSize)(UInt64 newSize) PURE;
};
STREAM_INTERFACE(IStreamGetSize, 0x06)

View File

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

View File

@@ -118,4 +118,4 @@ HRESULT CUpdateCallbackAgent::ShowDeleteFile(const wchar_t *name)
{
return Callback->DeleteOperation(name);
}
*/
*/

View File

@@ -86,7 +86,7 @@ enum Enum
kTechMode,
kShareForWrite,
kCaseSensitive,
kCalcCrc,
kCalcCrc
};
}
@@ -191,12 +191,12 @@ static const char *kSameTerminalError = "I won't write data and program's messag
static void ThrowException(const char *errorMessage)
{
throw CArchiveCommandLineException(errorMessage);
};
}
static void ThrowUserErrorException()
{
ThrowException(kUserErrorMessage);
};
}
// ---------------------------

View File

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

View File

@@ -82,7 +82,7 @@ public:
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
STDMETHOD(SetSize)(Int64 newSize);
STDMETHOD(SetSize)(UInt64 newSize);
};
// static NSynchronization::CCriticalSection g_TempPathsCS;
@@ -204,7 +204,7 @@ STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *n
return S_OK;
}
STDMETHODIMP COutMultiVolStream::SetSize(Int64 newSize)
STDMETHODIMP COutMultiVolStream::SetSize(UInt64 newSize)
{
if (newSize < 0)
return E_INVALIDARG;
@@ -905,4 +905,3 @@ HRESULT UpdateArchive(
#endif
return S_OK;
}

View File

@@ -7,7 +7,7 @@
namespace NUpdateArchive {
const CActionSet kAddActionSet =
{
{{
NPairAction::kCopy,
NPairAction::kCopy,
NPairAction::kCompress,
@@ -15,10 +15,10 @@ const CActionSet kAddActionSet =
NPairAction::kCompress,
NPairAction::kCompress,
NPairAction::kCompress
};
}};
const CActionSet kUpdateActionSet =
{
{{
NPairAction::kCopy,
NPairAction::kCopy,
NPairAction::kCompress,
@@ -26,10 +26,10 @@ const CActionSet kUpdateActionSet =
NPairAction::kCompress,
NPairAction::kCopy,
NPairAction::kCompress
};
}};
const CActionSet kFreshActionSet =
{
{{
NPairAction::kCopy,
NPairAction::kCopy,
NPairAction::kIgnore,
@@ -37,10 +37,10 @@ const CActionSet kFreshActionSet =
NPairAction::kCompress,
NPairAction::kCopy,
NPairAction::kCompress
};
}};
const CActionSet kSynchronizeActionSet =
{
{{
NPairAction::kCopy,
NPairAction::kIgnore,
NPairAction::kCompress,
@@ -48,10 +48,10 @@ const CActionSet kSynchronizeActionSet =
NPairAction::kCompress,
NPairAction::kCopy,
NPairAction::kCompress,
};
}};
const CActionSet kDeleteActionSet =
{
{{
NPairAction::kCopy,
NPairAction::kIgnore,
NPairAction::kIgnore,
@@ -59,6 +59,6 @@ const CActionSet kDeleteActionSet =
NPairAction::kIgnore,
NPairAction::kIgnore,
NPairAction::kIgnore
};
}};
}

View File

@@ -19,6 +19,7 @@ namespace NUpdateArchive {
kUnknowNewerFiles
};
}
namespace NPairAction
{
enum EEnum
@@ -29,6 +30,7 @@ namespace NUpdateArchive {
kCompressAsAnti
};
}
struct CActionSet
{
NPairAction::EEnum StateActions[NPairState::kNumValues];
@@ -44,14 +46,12 @@ namespace NUpdateArchive {
return false;
}
};
extern const CActionSet kAddActionSet;
extern const CActionSet kUpdateActionSet;
extern const CActionSet kFreshActionSet;
extern const CActionSet kSynchronizeActionSet;
extern const CActionSet kDeleteActionSet;
};
}
#endif

View File

@@ -24,8 +24,8 @@
virtual HRESULT SetOperationResult(Int32 operationResult) x; \
virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \
virtual HRESULT CryptoGetTextPassword(BSTR *password) x; \
// virtual HRESULT ShowDeleteFile(const wchar_t *name) x; \
// virtual HRESULT CloseProgress() { return S_OK; };
/* virtual HRESULT ShowDeleteFile(const wchar_t *name) x; */ \
/* virtual HRESULT CloseProgress() { return S_OK; }; */
struct IUpdateCallbackUI
{

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