mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 09:14:58 -06:00
15.06
This commit is contained in:
committed by
Kornel Lesiński
parent
54490d51d5
commit
cba375916f
14
C/7zDec.c
14
C/7zDec.c
@@ -1,5 +1,5 @@
|
||||
/* 7zDec.c -- Decoding from 7z folder
|
||||
2015-06-13 : Igor Pavlov : Public domain */
|
||||
2015-08-01 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -144,11 +144,11 @@ static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, I
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Byte *inBuf = NULL;
|
||||
const void *inBuf = NULL;
|
||||
size_t lookahead = (1 << 18);
|
||||
if (lookahead > inSize)
|
||||
lookahead = (size_t)inSize;
|
||||
res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
|
||||
res = inStream->Look(inStream, &inBuf, &lookahead);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
||||
@@ -197,11 +197,11 @@ static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize,
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Byte *inBuf = NULL;
|
||||
const void *inBuf = NULL;
|
||||
size_t lookahead = (1 << 18);
|
||||
if (lookahead > inSize)
|
||||
lookahead = (size_t)inSize;
|
||||
res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
|
||||
res = inStream->Look(inStream, &inBuf, &lookahead);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
||||
@@ -237,11 +237,11 @@ static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer
|
||||
{
|
||||
while (inSize > 0)
|
||||
{
|
||||
void *inBuf;
|
||||
const void *inBuf;
|
||||
size_t curSize = (1 << 18);
|
||||
if (curSize > inSize)
|
||||
curSize = (size_t)inSize;
|
||||
RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize));
|
||||
RINOK(inStream->Look(inStream, &inBuf, &curSize));
|
||||
if (curSize == 0)
|
||||
return SZ_ERROR_INPUT_EOF;
|
||||
memcpy(outBuffer, inBuf, curSize);
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#define MY_VER_MAJOR 15
|
||||
#define MY_VER_MINOR 05
|
||||
#define MY_VER_MINOR 06
|
||||
#define MY_VER_BUILD 00
|
||||
#define MY_VERSION "15.05 beta"
|
||||
#define MY_DATE "2015-06-14"
|
||||
#define MY_VERSION_NUMBERS "15.06"
|
||||
#define MY_VERSION "15.06 beta"
|
||||
#define MY_DATE "2015-08-09"
|
||||
#undef MY_COPYRIGHT
|
||||
#undef MY_VERSION_COPYRIGHT_DATE
|
||||
#define MY_AUTHOR_NAME "Igor Pavlov"
|
||||
#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
|
||||
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2015 Igor Pavlov"
|
||||
|
||||
|
||||
6
C/Bcj2.c
6
C/Bcj2.c
@@ -1,5 +1,5 @@
|
||||
/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)
|
||||
2014-11-09 : Igor Pavlov : Public domain */
|
||||
2015-08-01 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -178,8 +178,8 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p)
|
||||
p->state =
|
||||
p->bufs[BCJ2_STREAM_MAIN] ==
|
||||
p->lims[BCJ2_STREAM_MAIN] ?
|
||||
BCJ2_STREAM_MAIN :
|
||||
BCJ2_DEC_STATE_ORIG;
|
||||
(unsigned)BCJ2_STREAM_MAIN :
|
||||
(unsigned)BCJ2_DEC_STATE_ORIG;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
|
||||
48
C/Blake2.h
Normal file
48
C/Blake2.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* Blake2.h -- BLAKE2 Hash
|
||||
2015-06-30 : Igor Pavlov : Public domain
|
||||
2015 : Samuel Neves : Public domain */
|
||||
|
||||
#ifndef __BLAKE2_H
|
||||
#define __BLAKE2_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define BLAKE2S_BLOCK_SIZE 64
|
||||
#define BLAKE2S_DIGEST_SIZE 32
|
||||
#define BLAKE2SP_PARALLEL_DEGREE 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 h[8];
|
||||
UInt32 t[2];
|
||||
UInt32 f[2];
|
||||
Byte buf[BLAKE2S_BLOCK_SIZE];
|
||||
UInt32 bufPos;
|
||||
UInt32 lastNode_f1;
|
||||
UInt32 dummy[2]; /* for sizeof(CBlake2s) alignment */
|
||||
} CBlake2s;
|
||||
|
||||
/* You need to xor CBlake2s::h[i] with input parameter block after Blake2s_Init0() */
|
||||
/*
|
||||
void Blake2s_Init0(CBlake2s *p);
|
||||
void Blake2s_Update(CBlake2s *p, const Byte *data, size_t size);
|
||||
void Blake2s_Final(CBlake2s *p, Byte *digest);
|
||||
*/
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CBlake2s S[BLAKE2SP_PARALLEL_DEGREE];
|
||||
unsigned bufPos;
|
||||
} CBlake2sp;
|
||||
|
||||
|
||||
void Blake2sp_Init(CBlake2sp *p);
|
||||
void Blake2sp_Update(CBlake2sp *p, const Byte *data, size_t size);
|
||||
void Blake2sp_Final(CBlake2sp *p, Byte *digest);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
244
C/Blake2s.c
Normal file
244
C/Blake2s.c
Normal file
@@ -0,0 +1,244 @@
|
||||
/* Blake2s.c -- BLAKE2s and BLAKE2sp Hash
|
||||
2015-06-30 : Igor Pavlov : Public domain
|
||||
2015 : Samuel Neves : Public domain */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Blake2.h"
|
||||
#include "CpuArch.h"
|
||||
#include "RotateDefs.h"
|
||||
|
||||
#define rotr32 rotrFixed
|
||||
|
||||
#define BLAKE2S_NUM_ROUNDS 10
|
||||
#define BLAKE2S_FINAL_FLAG (~(UInt32)0)
|
||||
|
||||
static const UInt32 k_Blake2s_IV[8] =
|
||||
{
|
||||
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
|
||||
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
|
||||
};
|
||||
|
||||
static const Byte k_Blake2s_Sigma[BLAKE2S_NUM_ROUNDS][16] =
|
||||
{
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
|
||||
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
|
||||
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
|
||||
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
|
||||
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
|
||||
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
|
||||
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
|
||||
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
|
||||
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
|
||||
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
|
||||
};
|
||||
|
||||
|
||||
void Blake2s_Init0(CBlake2s *p)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < 8; i++)
|
||||
p->h[i] = k_Blake2s_IV[i];
|
||||
p->t[0] = 0;
|
||||
p->t[1] = 0;
|
||||
p->f[0] = 0;
|
||||
p->f[1] = 0;
|
||||
p->bufPos = 0;
|
||||
p->lastNode_f1 = 0;
|
||||
}
|
||||
|
||||
|
||||
static void Blake2s_Compress(CBlake2s *p)
|
||||
{
|
||||
UInt32 m[16];
|
||||
UInt32 v[16];
|
||||
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
m[i] = GetUi32(p->buf + i * sizeof(m[i]));
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
v[i] = p->h[i];
|
||||
}
|
||||
|
||||
v[ 8] = k_Blake2s_IV[0];
|
||||
v[ 9] = k_Blake2s_IV[1];
|
||||
v[10] = k_Blake2s_IV[2];
|
||||
v[11] = k_Blake2s_IV[3];
|
||||
|
||||
v[12] = p->t[0] ^ k_Blake2s_IV[4];
|
||||
v[13] = p->t[1] ^ k_Blake2s_IV[5];
|
||||
v[14] = p->f[0] ^ k_Blake2s_IV[6];
|
||||
v[15] = p->f[1] ^ k_Blake2s_IV[7];
|
||||
|
||||
#define G(r,i,a,b,c,d) \
|
||||
a += b + m[sigma[2*i+0]]; d ^= a; d = rotr32(d, 16); c += d; b ^= c; b = rotr32(b, 12); \
|
||||
a += b + m[sigma[2*i+1]]; d ^= a; d = rotr32(d, 8); c += d; b ^= c; b = rotr32(b, 7); \
|
||||
|
||||
#define R(r) \
|
||||
G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
|
||||
G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
|
||||
G(r,2,v[ 2],v[ 6],v[10],v[14]); \
|
||||
G(r,3,v[ 3],v[ 7],v[11],v[15]); \
|
||||
G(r,4,v[ 0],v[ 5],v[10],v[15]); \
|
||||
G(r,5,v[ 1],v[ 6],v[11],v[12]); \
|
||||
G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
|
||||
G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
|
||||
|
||||
{
|
||||
unsigned r;
|
||||
for (r = 0; r < BLAKE2S_NUM_ROUNDS; r++)
|
||||
{
|
||||
const Byte *sigma = k_Blake2s_Sigma[r];
|
||||
R(r);
|
||||
}
|
||||
/* R(0); R(1); R(2); R(3); R(4); R(5); R(6); R(7); R(8); R(9); */
|
||||
}
|
||||
|
||||
#undef G
|
||||
#undef R
|
||||
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < 8; i++)
|
||||
p->h[i] ^= v[i] ^ v[i + 8];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define Blake2s_Increment_Counter(S, inc) \
|
||||
{ p->t[0] += (inc); p->t[1] += (p->t[0] < (inc)); }
|
||||
|
||||
#define Blake2s_Set_LastBlock(p) \
|
||||
{ p->f[0] = BLAKE2S_FINAL_FLAG; p->f[1] = p->lastNode_f1; }
|
||||
|
||||
|
||||
static void Blake2s_Update(CBlake2s *p, const Byte *data, size_t size)
|
||||
{
|
||||
while (size != 0)
|
||||
{
|
||||
unsigned pos = (unsigned)p->bufPos;
|
||||
unsigned rem = BLAKE2S_BLOCK_SIZE - pos;
|
||||
|
||||
if (size <= rem)
|
||||
{
|
||||
memcpy(p->buf + pos, data, size);
|
||||
p->bufPos += (UInt32)size;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(p->buf + pos, data, rem);
|
||||
Blake2s_Increment_Counter(S, BLAKE2S_BLOCK_SIZE);
|
||||
Blake2s_Compress(p);
|
||||
p->bufPos = 0;
|
||||
data += rem;
|
||||
size -= rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void Blake2s_Final(CBlake2s *p, Byte *digest)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
Blake2s_Increment_Counter(S, (UInt32)p->bufPos);
|
||||
Blake2s_Set_LastBlock(p);
|
||||
memset(p->buf + p->bufPos, 0, BLAKE2S_BLOCK_SIZE - p->bufPos);
|
||||
Blake2s_Compress(p);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
SetUi32(digest + sizeof(p->h[i]) * i, p->h[i]);
|
||||
}
|
||||
|
||||
|
||||
/* ---------- BLAKE2s ---------- */
|
||||
|
||||
/* we need to xor CBlake2s::h[i] with input parameter block after Blake2s_Init0() */
|
||||
/*
|
||||
typedef struct
|
||||
{
|
||||
Byte digest_length;
|
||||
Byte key_length;
|
||||
Byte fanout;
|
||||
Byte depth;
|
||||
UInt32 leaf_length;
|
||||
Byte node_offset[6];
|
||||
Byte node_depth;
|
||||
Byte inner_length;
|
||||
Byte salt[BLAKE2S_SALTBYTES];
|
||||
Byte personal[BLAKE2S_PERSONALBYTES];
|
||||
} CBlake2sParam;
|
||||
*/
|
||||
|
||||
|
||||
static void Blake2sp_Init_Spec(CBlake2s *p, unsigned node_offset, unsigned node_depth)
|
||||
{
|
||||
Blake2s_Init0(p);
|
||||
|
||||
p->h[0] ^= (BLAKE2S_DIGEST_SIZE | ((UInt32)BLAKE2SP_PARALLEL_DEGREE << 16) | ((UInt32)2 << 24));
|
||||
p->h[2] ^= ((UInt32)node_offset);
|
||||
p->h[3] ^= ((UInt32)node_depth << 16) | ((UInt32)BLAKE2S_DIGEST_SIZE << 24);
|
||||
/*
|
||||
P->digest_length = BLAKE2S_DIGEST_SIZE;
|
||||
P->key_length = 0;
|
||||
P->fanout = BLAKE2SP_PARALLEL_DEGREE;
|
||||
P->depth = 2;
|
||||
P->leaf_length = 0;
|
||||
store48(P->node_offset, node_offset);
|
||||
P->node_depth = node_depth;
|
||||
P->inner_length = BLAKE2S_DIGEST_SIZE;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void Blake2sp_Init(CBlake2sp *p)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
p->bufPos = 0;
|
||||
|
||||
for (i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++)
|
||||
Blake2sp_Init_Spec(&p->S[i], i, 0);
|
||||
|
||||
p->S[BLAKE2SP_PARALLEL_DEGREE - 1].lastNode_f1 = BLAKE2S_FINAL_FLAG;
|
||||
}
|
||||
|
||||
|
||||
void Blake2sp_Update(CBlake2sp *p, const Byte *data, size_t size)
|
||||
{
|
||||
unsigned pos = p->bufPos;
|
||||
while (size != 0)
|
||||
{
|
||||
unsigned index = pos / BLAKE2S_BLOCK_SIZE;
|
||||
unsigned rem = BLAKE2S_BLOCK_SIZE - (pos & (BLAKE2S_BLOCK_SIZE - 1));
|
||||
if (rem > size)
|
||||
rem = (unsigned)size;
|
||||
Blake2s_Update(&p->S[index], data, rem);
|
||||
size -= rem;
|
||||
data += rem;
|
||||
pos += rem;
|
||||
pos &= (BLAKE2S_BLOCK_SIZE * BLAKE2SP_PARALLEL_DEGREE - 1);
|
||||
}
|
||||
p->bufPos = pos;
|
||||
}
|
||||
|
||||
|
||||
void Blake2sp_Final(CBlake2sp *p, Byte *digest)
|
||||
{
|
||||
CBlake2s R;
|
||||
unsigned i;
|
||||
|
||||
Blake2sp_Init_Spec(&R, 0, 1);
|
||||
R.lastNode_f1 = BLAKE2S_FINAL_FLAG;
|
||||
|
||||
for (i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++)
|
||||
{
|
||||
Byte hash[BLAKE2S_DIGEST_SIZE];
|
||||
Blake2s_Final(&p->S[i], hash);
|
||||
Blake2s_Update(&R, hash, BLAKE2S_DIGEST_SIZE);
|
||||
}
|
||||
|
||||
Blake2s_Final(&R, digest);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Compiler.h
|
||||
2015-03-25 : Igor Pavlov : Public domain */
|
||||
2015-08-02 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_COMPILER_H
|
||||
#define __7Z_COMPILER_H
|
||||
@@ -18,6 +18,7 @@
|
||||
#else
|
||||
#pragma warning(disable : 4511) // copy constructor could not be generated
|
||||
#pragma warning(disable : 4512) // assignment operator could not be generated
|
||||
#pragma warning(disable : 4514) // unreferenced inline function has been removed
|
||||
#pragma warning(disable : 4702) // unreachable code
|
||||
#pragma warning(disable : 4710) // not inlined
|
||||
#pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* CpuArch.h -- CPU specific code
|
||||
2015-03-25: Igor Pavlov : Public domain */
|
||||
2015-08-02: Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __CPU_ARCH_H
|
||||
#define __CPU_ARCH_H
|
||||
@@ -90,9 +90,10 @@ Stop_Compiling_Bad_Endian
|
||||
#define GetUi16(p) (*(const UInt16 *)(const void *)(p))
|
||||
#define GetUi32(p) (*(const UInt32 *)(const void *)(p))
|
||||
#define GetUi64(p) (*(const UInt64 *)(const void *)(p))
|
||||
#define SetUi16(p, v) *(UInt16 *)(p) = (v);
|
||||
#define SetUi32(p, v) *(UInt32 *)(p) = (v);
|
||||
#define SetUi64(p, v) *(UInt64 *)(p) = (v);
|
||||
|
||||
#define SetUi16(p, v) { *(UInt16 *)(p) = (v); }
|
||||
#define SetUi32(p, v) { *(UInt32 *)(p) = (v); }
|
||||
#define SetUi64(p, v) { *(UInt64 *)(p) = (v); }
|
||||
|
||||
#else
|
||||
|
||||
|
||||
11
C/LzmaDec.c
11
C/LzmaDec.c
@@ -1,5 +1,5 @@
|
||||
/* LzmaDec.c -- LZMA Decoder
|
||||
2015-05-14 : Igor Pavlov : Public domain */
|
||||
2015-06-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -438,10 +438,16 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
||||
if (checkDicSize == 0)
|
||||
{
|
||||
if (distance >= processedPos)
|
||||
{
|
||||
p->dicPos = dicPos;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
}
|
||||
else if (distance >= checkDicSize)
|
||||
{
|
||||
p->dicPos = dicPos;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
|
||||
}
|
||||
|
||||
@@ -453,7 +459,10 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
||||
SizeT pos;
|
||||
|
||||
if ((rem = limit - dicPos) == 0)
|
||||
{
|
||||
p->dicPos = dicPos;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
|
||||
curLen = ((rem < len) ? (unsigned)rem : len);
|
||||
pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* 7zMain.c - Test application for 7z Decoder
|
||||
2015-05-11 : Igor Pavlov : Public domain */
|
||||
2015-08-02 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -328,22 +328,20 @@ void PrintError(char *sz)
|
||||
printf("\nERROR: %s\n", sz);
|
||||
}
|
||||
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
static void GetAttribString(UInt32 wa, Bool isDir, char *s)
|
||||
{
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : '.');
|
||||
s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY ) != 0) ? 'R': '.');
|
||||
s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN ) != 0) ? 'H': '.');
|
||||
s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM ) != 0) ? 'S': '.');
|
||||
s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE ) != 0) ? 'A': '.');
|
||||
s[5] = '\0';
|
||||
s[5] = 0;
|
||||
#else
|
||||
s[0] = (char)(((wa & (1 << 4)) != 0 || isDir) ? 'D' : '.');
|
||||
s[1] = 0;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
static void GetAttribString(UInt32, Bool, char *s)
|
||||
{
|
||||
s[0] = '\0';
|
||||
}
|
||||
#endif
|
||||
|
||||
// #define NUM_PARENTS_MAX 128
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
PROG = 7zDec
|
||||
CXX = g++
|
||||
CXX = gcc
|
||||
LIB =
|
||||
RM = rm -f
|
||||
CFLAGS = -c -O2 -Wall
|
||||
|
||||
OBJS = 7zMain.o 7zAlloc.o 7zArcIn.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o CpuArch.o LzmaDec.o Lzma2Dec.o Bra.o Bra86.o Bcj2.o Ppmd7.o Ppmd7Dec.o 7zFile.o 7zStream.o
|
||||
OBJS = 7zMain.o 7zAlloc.o 7zArcIn.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o CpuArch.o Delta.o LzmaDec.o Lzma2Dec.o Bra.o Bra86.o BraIA64.o Bcj2.o Ppmd7.o Ppmd7Dec.o 7zFile.o 7zStream.o
|
||||
|
||||
all: $(PROG)
|
||||
|
||||
@@ -38,6 +38,9 @@ $(PROG): $(OBJS)
|
||||
CpuArch.o: ../../CpuArch.c
|
||||
$(CXX) $(CFLAGS) ../../CpuArch.c
|
||||
|
||||
Delta.o: ../../Delta.c
|
||||
$(CXX) $(CFLAGS) ../../Delta.c
|
||||
|
||||
LzmaDec.o: ../../LzmaDec.c
|
||||
$(CXX) $(CFLAGS) ../../LzmaDec.c
|
||||
|
||||
@@ -50,6 +53,9 @@ Bra.o: ../../Bra.c
|
||||
Bra86.o: ../../Bra86.c
|
||||
$(CXX) $(CFLAGS) ../../Bra86.c
|
||||
|
||||
BraIA64.o: ../../BraIA64.c
|
||||
$(CXX) $(CFLAGS) ../../BraIA64.c
|
||||
|
||||
Bcj2.o: ../../Bcj2.c
|
||||
$(CXX) $(CFLAGS) ../../Bcj2.c
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* 7zipInnstall.c - 7-Zip Installer
|
||||
2015-06-13 : Igor Pavlov : Public domain */
|
||||
/* 7zipInstall.c - 7-Zip Installer
|
||||
2015-08-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -37,7 +37,7 @@ static const WCHAR *k_Reg_Software_7zip = L"Software\\7-Zip";
|
||||
#define k_7zip_with_Ver_base L"7-Zip " LLL(MY_VERSION)
|
||||
|
||||
#ifdef _64BIT_INSTALLER
|
||||
#define k_7zip_with_Ver k_7zip_with_Ver_base L" x64"
|
||||
#define k_7zip_with_Ver k_7zip_with_Ver_base L" (x64)"
|
||||
#else
|
||||
#define k_7zip_with_Ver k_7zip_with_Ver_base
|
||||
#endif
|
||||
@@ -84,6 +84,8 @@ static HWND g_Path_HWND;
|
||||
static HWND g_InfoLine_HWND;
|
||||
static HWND g_Progress_HWND;
|
||||
|
||||
static DWORD g_TotalSize;
|
||||
|
||||
static WCHAR path[MAX_PATH * 2 + 40];
|
||||
|
||||
|
||||
@@ -143,7 +145,7 @@ static WRes CreateComplexDir()
|
||||
|
||||
if (IS_DRIVE_PATH(s))
|
||||
prefixSize = 3;
|
||||
else if (IS_SEPAR(s[1]) && IS_SEPAR(s[1]))
|
||||
else if (IS_SEPAR(s[0]) && IS_SEPAR(s[1]))
|
||||
prefixSize = 2;
|
||||
else
|
||||
return ERROR_INVALID_NAME;
|
||||
@@ -796,16 +798,30 @@ static void WriteShellEx()
|
||||
// wcscpy(destPath, path);
|
||||
// wcscat(destPath, L"7zFM.exe");
|
||||
MyRegistry_SetString(destKey, L"DisplayName", k_7zip_with_Ver_str);
|
||||
MyRegistry_SetString(destKey, L"DisplayVersion", LLL(MY_VERSION_NUMBERS));
|
||||
|
||||
MyRegistry_SetString(destKey, L"DisplayIcon", destPath);
|
||||
|
||||
wcscpy(destPath, path);
|
||||
// MyRegistry_SetString(destKey, L"InstallLocation", destPath);
|
||||
MyRegistry_SetString(destKey, L"InstallLocation", destPath);
|
||||
wcscat(destPath, L"Uninstall.exe");
|
||||
// wcscat(destPath, L"\"");
|
||||
MyRegistry_SetString(destKey, L"UninstallString", destPath);
|
||||
|
||||
MyRegistry_SetDWORD(destKey, L"NoModify", 1);
|
||||
MyRegistry_SetDWORD(destKey, L"NoRepair", 1);
|
||||
|
||||
MyRegistry_SetDWORD(destKey, L"EstimatedSize", g_TotalSize >> 10);
|
||||
|
||||
MyRegistry_SetDWORD(destKey, L"VersionMajor", MY_VER_MAJOR);
|
||||
MyRegistry_SetDWORD(destKey, L"VersionMinor", MY_VER_MINOR);
|
||||
|
||||
MyRegistry_SetString(destKey, L"Publisher", LLL(MY_AUTHOR_NAME));
|
||||
|
||||
// MyRegistry_SetString(destKey, L"HelpLink", L"http://www.7-zip.org/support.html");
|
||||
// MyRegistry_SetString(destKey, L"URLInfoAbout", L"http://www.7-zip.org/");
|
||||
// MyRegistry_SetString(destKey, L"URLUpdateInfo", L"http://www.7-zip.org/");
|
||||
|
||||
RegCloseKey(destKey);
|
||||
}
|
||||
}
|
||||
@@ -1108,6 +1124,23 @@ if (res == SZ_OK)
|
||||
FileInStream_CreateVTable(&archiveStream);
|
||||
LookToRead_CreateVTable(&lookStream, False);
|
||||
|
||||
{
|
||||
// Remove post spaces
|
||||
unsigned endPos = 0;
|
||||
unsigned i = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
wchar_t c = path[i++];
|
||||
if (c == 0)
|
||||
break;
|
||||
if (c != ' ')
|
||||
endPos = i;
|
||||
}
|
||||
|
||||
path[endPos] = 0;
|
||||
}
|
||||
|
||||
NormalizePrefix(path);
|
||||
winRes = CreateComplexDir();
|
||||
|
||||
@@ -1132,6 +1165,8 @@ if (res == SZ_OK)
|
||||
Byte *outBuf = NULL; /* it must be NULL before first call for each new archive. */
|
||||
size_t outBufSize = 0; /* it can have any value before first call, if(!outBuf) */
|
||||
|
||||
g_TotalSize = 0;
|
||||
|
||||
if (!g_SilentMode)
|
||||
{
|
||||
ShowWindow(g_Progress_HWND, SW_SHOW);
|
||||
@@ -1309,6 +1344,8 @@ if (res == SZ_OK)
|
||||
res = SZ_ERROR_FAIL;
|
||||
}
|
||||
|
||||
g_TotalSize += (DWORD)outSizeProcessed;
|
||||
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
if (SzBitWithVals_Check(&db.MTime, i))
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* 7zipUninstall.c - 7-Zip Uninstaller
|
||||
2015-06-13 : Igor Pavlov : Public domain */
|
||||
2015-08-09 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#define k_7zip_with_Ver_base L"7-Zip " LLL(MY_VERSION)
|
||||
|
||||
#ifdef _64BIT_INSTALLER
|
||||
#define k_7zip_with_Ver k_7zip_with_Ver_base L" x64"
|
||||
#define k_7zip_with_Ver k_7zip_with_Ver_base L" (x64)"
|
||||
#else
|
||||
#define k_7zip_with_Ver k_7zip_with_Ver_base
|
||||
#endif
|
||||
|
||||
@@ -301,6 +301,12 @@ HRESULT CDecoder::Decode(
|
||||
{
|
||||
const CCoderInfo &coderInfo = folderInfo.Coders[i];
|
||||
|
||||
#ifndef _SFX
|
||||
// we don't support RAR codecs here
|
||||
if ((coderInfo.MethodID >> 8) == 0x403)
|
||||
return E_NOTIMPL;
|
||||
#endif
|
||||
|
||||
CCreatedCoder cod;
|
||||
RINOK(CreateCoder(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
|
||||
@@ -44,6 +44,7 @@ public:
|
||||
UInt64 _numSolidBytes;
|
||||
bool _numSolidBytesDefined;
|
||||
bool _solidExtension;
|
||||
bool _useTypeSorting;
|
||||
|
||||
bool _compressHeaders;
|
||||
bool _encryptHeadersSpecified;
|
||||
|
||||
@@ -507,6 +507,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
ui.Name = name;
|
||||
|
||||
if (ui.NewData)
|
||||
{
|
||||
ui.Size = 0;
|
||||
if (!ui.IsDir)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(i, kpidSize, &prop));
|
||||
@@ -516,6 +519,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
if (ui.Size != 0 && ui.IsAnti)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
|
||||
updateItems.Add(ui);
|
||||
}
|
||||
|
||||
@@ -613,6 +618,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
options.NumSolidFiles = _numSolidFiles;
|
||||
options.NumSolidBytes = _numSolidBytes;
|
||||
options.SolidExtension = _solidExtension;
|
||||
options.UseTypeSorting = _useTypeSorting;
|
||||
|
||||
options.RemoveSfxBlock = _removeSfxBlock;
|
||||
// options.VolumeMode = _volumeMode;
|
||||
|
||||
@@ -701,6 +708,7 @@ void COutHandler::InitProps()
|
||||
// _volumeMode = false;
|
||||
|
||||
InitSolid();
|
||||
_useTypeSorting = false;
|
||||
}
|
||||
|
||||
HRESULT COutHandler::SetSolidFromString(const UString &s)
|
||||
@@ -821,6 +829,8 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
|
||||
|
||||
if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer);
|
||||
|
||||
if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting);
|
||||
|
||||
// if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode);
|
||||
}
|
||||
return CMultiMethodProps::SetProperty(name, value);
|
||||
|
||||
@@ -554,11 +554,11 @@ static int CompareEmptyItems(const unsigned *p1, const unsigned *p2, void *param
|
||||
}
|
||||
|
||||
static const char *g_Exts =
|
||||
" lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab ha lha lzh rar zoo"
|
||||
" 7z xz lzma ace arc arj bz tbz bz2 tbz2 cab deb gz tgz ha lha lzh lzo lzx pak rar rpm sit zoo"
|
||||
" zip jar ear war msi"
|
||||
" 3gp avi mov mpeg mpg mpe wmv"
|
||||
" aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav"
|
||||
" swf "
|
||||
" swf"
|
||||
" chm hxi hxs"
|
||||
" gif jpeg jpg jp2 png tiff bmp ico psd psp"
|
||||
" awg ps eps cgm dxf svg vrml wmf emf ai md"
|
||||
@@ -569,9 +569,9 @@ static const char *g_Exts =
|
||||
" vmdk dsk nvram vmem vmsd vmsn vmss vmtm"
|
||||
" inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def"
|
||||
" f77 f f90 f95"
|
||||
" asm sql manifest dep "
|
||||
" mak clw csproj vcproj sln dsp dsw "
|
||||
" class "
|
||||
" asm sql manifest dep"
|
||||
" mak clw csproj vcproj sln dsp dsw"
|
||||
" class"
|
||||
" bat cmd"
|
||||
" xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml"
|
||||
" awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs"
|
||||
@@ -580,7 +580,7 @@ static const char *g_Exts =
|
||||
" abw afp cwk lwp wpd wps wpt wrf wri"
|
||||
" abf afm bdf fon mgf otf pcf pfa snf ttf"
|
||||
" dbf mdb nsf ntf wdb db fdb gdb"
|
||||
" exe dll ocx vbx sfx sys tlb awx com obj lib out o so "
|
||||
" exe dll ocx vbx sfx sys tlb awx com obj lib out o so"
|
||||
" pdb pch idb ncb opt";
|
||||
|
||||
static unsigned GetExtIndex(const char *ext)
|
||||
@@ -2251,7 +2251,7 @@ HRESULT Update(
|
||||
continue;
|
||||
CRecordVector<CRefItem> refItems;
|
||||
refItems.ClearAndSetSize(numFiles);
|
||||
bool sortByType = (numSolidFiles > 1);
|
||||
bool sortByType = (options.UseTypeSorting && numSolidFiles > 1);
|
||||
for (i = 0; i < numFiles; i++)
|
||||
refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType);
|
||||
CSortParam sortParam;
|
||||
|
||||
@@ -97,6 +97,9 @@ struct CUpdateOptions
|
||||
UInt64 NumSolidFiles;
|
||||
UInt64 NumSolidBytes;
|
||||
bool SolidExtension;
|
||||
|
||||
bool UseTypeSorting;
|
||||
|
||||
bool RemoveSfxBlock;
|
||||
bool MultiThreadMixer;
|
||||
|
||||
@@ -109,6 +112,7 @@ struct CUpdateOptions
|
||||
NumSolidFiles((UInt64)(Int64)(-1)),
|
||||
NumSolidBytes((UInt64)(Int64)(-1)),
|
||||
SolidExtension(false),
|
||||
UseTypeSorting(true),
|
||||
RemoveSfxBlock(false),
|
||||
MultiThreadMixer(true)
|
||||
{}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
PROG = 7z.dll
|
||||
DEF_FILE = ../../Archive/Archive2.def
|
||||
DEF_FILE = ../Archive.def
|
||||
CFLAGS = $(CFLAGS) \
|
||||
-DEXTERNAL_CODECS \
|
||||
|
||||
@@ -60,9 +60,11 @@ WIN_OBJS = \
|
||||
$O\StreamUtils.obj \
|
||||
$O\VirtThread.obj \
|
||||
|
||||
COMPRESS_OBJS = \
|
||||
$O\CopyCoder.obj \
|
||||
|
||||
AR_COMMON_OBJS = \
|
||||
$O\CoderMixer2.obj \
|
||||
$O\CoderMixer2MT.obj \
|
||||
$O\CrossThreadProgress.obj \
|
||||
$O\HandlerOut.obj \
|
||||
$O\InStreamWithCRC.obj \
|
||||
@@ -76,4 +78,6 @@ C_OBJS = \
|
||||
$O\CpuArch.obj \
|
||||
$O\Threads.obj \
|
||||
|
||||
!include "../../Crc.mak"
|
||||
|
||||
!include "../../7zip.mak"
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
// CoderMixer.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "CoderMixer.h"
|
||||
|
||||
namespace NCoderMixer {
|
||||
|
||||
void CCoderInfo::SetCoderInfo(const UInt64 *inSize, const UInt64 *outSize)
|
||||
{
|
||||
InSizeAssigned = (inSize != 0);
|
||||
if (InSizeAssigned)
|
||||
InSizeValue = *inSize;
|
||||
OutSizeAssigned = (outSize != 0);
|
||||
if (OutSizeAssigned)
|
||||
OutSizeValue = *outSize;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
// CoderMixer.h
|
||||
|
||||
#ifndef __CODER_MIXER_H
|
||||
#define __CODER_MIXER_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../ICoder.h"
|
||||
|
||||
namespace NCoderMixer {
|
||||
|
||||
struct CCoderInfo
|
||||
{
|
||||
CMyComPtr<ICompressCoder> Coder;
|
||||
CMyComPtr<ISequentialInStream> InStream;
|
||||
CMyComPtr<ISequentialOutStream> OutStream;
|
||||
CMyComPtr<ICompressProgressInfo> Progress;
|
||||
|
||||
UInt64 InSizeValue;
|
||||
UInt64 OutSizeValue;
|
||||
bool InSizeAssigned;
|
||||
bool OutSizeAssigned;
|
||||
|
||||
void ReInit()
|
||||
{
|
||||
InSizeAssigned = OutSizeAssigned = false;
|
||||
}
|
||||
|
||||
void SetCoderInfo(const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -1,254 +0,0 @@
|
||||
// CoderMixer2MT.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "CoderMixer2MT.h"
|
||||
|
||||
namespace NCoderMixer2 {
|
||||
|
||||
void CCoderMT::Execute() { Code(NULL); }
|
||||
|
||||
void CCoderMT::Code(ICompressProgressInfo *progress)
|
||||
{
|
||||
unsigned numInStreams = EncodeMode ? 1 : NumStreams;
|
||||
unsigned numOutStreams = EncodeMode ? NumStreams : 1;
|
||||
|
||||
InStreamPointers.ClearAndReserve(numInStreams);
|
||||
OutStreamPointers.ClearAndReserve(numOutStreams);
|
||||
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < numInStreams; i++)
|
||||
InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]);
|
||||
|
||||
for (i = 0; i < numOutStreams; i++)
|
||||
OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]);
|
||||
|
||||
// we suppose that UnpackSizePointer and PackSizePointers contain correct pointers.
|
||||
/*
|
||||
if (UnpackSizePointer)
|
||||
UnpackSizePointer = &UnpackSize;
|
||||
for (i = 0; i < NumStreams; i++)
|
||||
if (PackSizePointers[i])
|
||||
PackSizePointers[i] = &PackSizes[i];
|
||||
*/
|
||||
|
||||
if (Coder)
|
||||
Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],
|
||||
EncodeMode ? UnpackSizePointer : PackSizePointers[0],
|
||||
EncodeMode ? PackSizePointers[0] : UnpackSizePointer,
|
||||
progress);
|
||||
else
|
||||
Result = Coder2->Code(
|
||||
&InStreamPointers.Front(), EncodeMode ? &UnpackSizePointer : &PackSizePointers.Front(), numInStreams,
|
||||
&OutStreamPointers.Front(), EncodeMode ? &PackSizePointers.Front(): &UnpackSizePointer, numOutStreams,
|
||||
progress);
|
||||
|
||||
InStreamPointers.Clear();
|
||||
OutStreamPointers.Clear();
|
||||
|
||||
for (i = 0; i < InStreams.Size(); i++)
|
||||
InStreams[i].Release();
|
||||
for (i = 0; i < OutStreams.Size(); i++)
|
||||
OutStreams[i].Release();
|
||||
}
|
||||
|
||||
HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo)
|
||||
{
|
||||
CMixer::SetBindInfo(bindInfo);
|
||||
|
||||
_streamBinders.Clear();
|
||||
FOR_VECTOR (i, _bi.Bonds)
|
||||
{
|
||||
RINOK(_streamBinders.AddNew().CreateEvents());
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CMixerMT::AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter)
|
||||
{
|
||||
const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
|
||||
CCoderMT &c2 = _coders.AddNew();
|
||||
c2.NumStreams = c.NumStreams;
|
||||
c2.EncodeMode = EncodeMode;
|
||||
c2.Coder = coder;
|
||||
c2.Coder2 = coder2;
|
||||
IsFilter_Vector.Add(isFilter);
|
||||
}
|
||||
|
||||
CCoder &CMixerMT::GetCoder(unsigned index)
|
||||
{
|
||||
return _coders[index];
|
||||
}
|
||||
|
||||
void CMixerMT::ReInit()
|
||||
{
|
||||
FOR_VECTOR (i, _streamBinders)
|
||||
_streamBinders[i].ReInit();
|
||||
}
|
||||
|
||||
void CMixerMT::SelectMainCoder(bool useFirst)
|
||||
{
|
||||
unsigned ci = _bi.UnpackCoder;
|
||||
|
||||
if (!useFirst)
|
||||
for (;;)
|
||||
{
|
||||
if (_coders[ci].NumStreams != 1)
|
||||
break;
|
||||
if (!IsFilter_Vector[ci])
|
||||
break;
|
||||
|
||||
UInt32 st = _bi.Coder_to_Stream[ci];
|
||||
if (_bi.IsStream_in_PackStreams(st))
|
||||
break;
|
||||
int bond = _bi.FindBond_for_PackStream(st);
|
||||
if (bond < 0)
|
||||
throw 20150213;
|
||||
ci = _bi.Bonds[bond].UnpackIndex;
|
||||
}
|
||||
|
||||
MainCoderIndex = ci;
|
||||
}
|
||||
|
||||
HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
CCoderMT &coderInfo = _coders[i];
|
||||
const CCoderStreamsInfo &csi = _bi.Coders[i];
|
||||
|
||||
UInt32 j;
|
||||
|
||||
unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams;
|
||||
unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1;
|
||||
|
||||
coderInfo.InStreams.Clear();
|
||||
for (j = 0; j < numInStreams; j++)
|
||||
coderInfo.InStreams.AddNew();
|
||||
|
||||
coderInfo.OutStreams.Clear();
|
||||
for (j = 0; j < numOutStreams; j++)
|
||||
coderInfo.OutStreams.AddNew();
|
||||
}
|
||||
|
||||
for (i = 0; i < _bi.Bonds.Size(); i++)
|
||||
{
|
||||
const CBond &bond = _bi.Bonds[i];
|
||||
|
||||
UInt32 inCoderIndex, inCoderStreamIndex;
|
||||
UInt32 outCoderIndex, outCoderStreamIndex;
|
||||
|
||||
{
|
||||
UInt32 coderIndex, coderStreamIndex;
|
||||
_bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex);
|
||||
|
||||
inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex;
|
||||
outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex;
|
||||
|
||||
inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex;
|
||||
outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0;
|
||||
}
|
||||
|
||||
_streamBinders[i].CreateStreams(
|
||||
&_coders[inCoderIndex].InStreams[inCoderStreamIndex],
|
||||
&_coders[outCoderIndex].OutStreams[outCoderStreamIndex]);
|
||||
|
||||
CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize;
|
||||
_coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize);
|
||||
_coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize);
|
||||
if (inSetSize && outSetSize)
|
||||
{
|
||||
const UInt32 kBufSize = 1 << 19;
|
||||
inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize);
|
||||
outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
CCoderMT &cod = _coders[_bi.UnpackCoder];
|
||||
if (EncodeMode)
|
||||
cod.InStreams[0] = inStreams[0];
|
||||
else
|
||||
cod.OutStreams[0] = outStreams[0];
|
||||
}
|
||||
|
||||
for (i = 0; i < _bi.PackStreams.Size(); i++)
|
||||
{
|
||||
UInt32 coderIndex, coderStreamIndex;
|
||||
_bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex);
|
||||
CCoderMT &cod = _coders[coderIndex];
|
||||
if (EncodeMode)
|
||||
cod.OutStreams[coderStreamIndex] = outStreams[i];
|
||||
else
|
||||
cod.InStreams[coderStreamIndex] = inStreams[i];
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CMixerMT::ReturnIfError(HRESULT code)
|
||||
{
|
||||
FOR_VECTOR (i, _coders)
|
||||
if (_coders[i].Result == code)
|
||||
return code;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CMixerMT::Code(
|
||||
ISequentialInStream * const *inStreams,
|
||||
ISequentialOutStream * const *outStreams,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
Init(inStreams, outStreams);
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
if (i != MainCoderIndex)
|
||||
{
|
||||
RINOK(_coders[i].Create());
|
||||
}
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
if (i != MainCoderIndex)
|
||||
_coders[i].Start();
|
||||
|
||||
_coders[MainCoderIndex].Code(progress);
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
if (i != MainCoderIndex)
|
||||
_coders[i].WaitExecuteFinish();
|
||||
|
||||
RINOK(ReturnIfError(E_ABORT));
|
||||
RINOK(ReturnIfError(E_OUTOFMEMORY));
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
HRESULT result = _coders[i].Result;
|
||||
if (result != S_OK
|
||||
&& result != k_My_HRESULT_WritingWasCut
|
||||
&& result != S_FALSE
|
||||
&& result != E_FAIL)
|
||||
return result;
|
||||
}
|
||||
|
||||
RINOK(ReturnIfError(S_FALSE));
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
HRESULT result = _coders[i].Result;
|
||||
if (result != S_OK && result != k_My_HRESULT_WritingWasCut)
|
||||
return result;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const
|
||||
{
|
||||
return _streamBinders[bondIndex].ProcessedSize;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
// CoderMixer2MT.h
|
||||
|
||||
#ifndef __CODER_MIXER2_MT_H
|
||||
#define __CODER_MIXER2_MT_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../Common/StreamBinder.h"
|
||||
#include "../../Common/VirtThread.h"
|
||||
|
||||
#include "CoderMixer2.h"
|
||||
|
||||
namespace NCoderMixer2 {
|
||||
|
||||
class CCoderMT: public CCoder, public CVirtThread
|
||||
{
|
||||
CLASS_NO_COPY(CCoderMT)
|
||||
CRecordVector<ISequentialInStream*> InStreamPointers;
|
||||
CRecordVector<ISequentialOutStream*> OutStreamPointers;
|
||||
|
||||
private:
|
||||
void Execute();
|
||||
public:
|
||||
bool EncodeMode;
|
||||
HRESULT Result;
|
||||
CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
|
||||
CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
|
||||
|
||||
CCoderMT(): EncodeMode(false) {}
|
||||
~CCoderMT() { CVirtThread::WaitThreadFinish(); }
|
||||
|
||||
void Code(ICompressProgressInfo *progress);
|
||||
};
|
||||
|
||||
|
||||
|
||||
class CMixerMT:
|
||||
public IUnknown,
|
||||
public CMixer,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CObjectVector<CStreamBinder> _streamBinders;
|
||||
|
||||
HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams);
|
||||
HRESULT ReturnIfError(HRESULT code);
|
||||
|
||||
public:
|
||||
CObjectVector<CCoderMT> _coders;
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
virtual HRESULT SetBindInfo(const CBindInfo &bindInfo);
|
||||
|
||||
virtual void AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter);
|
||||
|
||||
virtual CCoder &GetCoder(unsigned index);
|
||||
|
||||
virtual void SelectMainCoder(bool useFirst);
|
||||
|
||||
virtual void ReInit();
|
||||
|
||||
virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
|
||||
{ _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
|
||||
|
||||
virtual HRESULT Code(
|
||||
ISequentialInStream * const *inStreams,
|
||||
ISequentialOutStream * const *outStreams,
|
||||
ICompressProgressInfo *progress);
|
||||
|
||||
virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
|
||||
|
||||
CMixerMT(bool encodeMode): CMixer(encodeMode) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,562 +0,0 @@
|
||||
// CoderMixer2ST.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "CoderMixer2ST.h"
|
||||
|
||||
STDMETHODIMP CSequentialInStreamCalcSize::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessed = 0;
|
||||
HRESULT result = S_OK;
|
||||
if (_stream)
|
||||
result = _stream->Read(data, size, &realProcessed);
|
||||
_size += realProcessed;
|
||||
if (size != 0 && realProcessed == 0)
|
||||
_wasFinished = true;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessed;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
STDMETHODIMP COutStreamCalcSize::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
HRESULT result = S_OK;
|
||||
if (_stream)
|
||||
result = _stream->Write(data, size, &size);
|
||||
_size += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutStreamCalcSize::Flush()
|
||||
{
|
||||
HRESULT result = S_OK;
|
||||
if (_stream)
|
||||
{
|
||||
CMyComPtr<IOutStreamFlush> outStreamFlush;
|
||||
_stream.QueryInterface(IID_IOutStreamFlush, &outStreamFlush);
|
||||
if (outStreamFlush)
|
||||
result = outStreamFlush->Flush();;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace NCoderMixer2 {
|
||||
|
||||
CMixerST::CMixerST(bool encodeMode):
|
||||
CMixer(encodeMode)
|
||||
{}
|
||||
|
||||
CMixerST::~CMixerST() {}
|
||||
|
||||
void CMixerST::AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter)
|
||||
{
|
||||
IsFilter_Vector.Add(isFilter);
|
||||
const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
|
||||
CCoderST &c2 = _coders.AddNew();
|
||||
c2.NumStreams = c.NumStreams;
|
||||
c2.Coder = coder;
|
||||
c2.Coder2 = coder2;
|
||||
|
||||
/*
|
||||
if (isFilter)
|
||||
{
|
||||
c2.CanRead = true;
|
||||
c2.CanWrite = true;
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
IUnknown *unk = (coder ? (IUnknown *)coder : (IUnknown *)coder2);
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> s;
|
||||
unk->QueryInterface(IID_ISequentialInStream, (void**)&s);
|
||||
c2.CanRead = (s != NULL);
|
||||
}
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> s;
|
||||
unk->QueryInterface(IID_ISequentialOutStream, (void**)&s);
|
||||
c2.CanWrite = (s != NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CCoder &CMixerST::GetCoder(unsigned index)
|
||||
{
|
||||
return _coders[index];
|
||||
}
|
||||
|
||||
void CMixerST::ReInit() {}
|
||||
|
||||
HRESULT CMixerST::GetInStream2(
|
||||
ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
|
||||
UInt32 outStreamIndex, ISequentialInStream **inStreamRes)
|
||||
{
|
||||
UInt32 coderIndex = outStreamIndex, coderStreamIndex = 0;
|
||||
|
||||
if (EncodeMode)
|
||||
{
|
||||
_bi.GetCoder_for_Stream(outStreamIndex, coderIndex, coderStreamIndex);
|
||||
if (coderStreamIndex != 0)
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
const CCoder &coder = _coders[coderIndex];
|
||||
|
||||
CMyComPtr<ISequentialInStream> seqInStream;
|
||||
coder.QueryInterface(IID_ISequentialInStream, (void **)&seqInStream);
|
||||
if (!seqInStream)
|
||||
return E_NOTIMPL;
|
||||
|
||||
UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams;
|
||||
UInt32 startIndex = EncodeMode ? coderIndex : _bi.Coder_to_Stream[coderIndex];
|
||||
|
||||
bool isSet = false;
|
||||
|
||||
if (numInStreams == 1)
|
||||
{
|
||||
CMyComPtr<ICompressSetInStream> setStream;
|
||||
coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream);
|
||||
if (setStream)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> seqInStream2;
|
||||
RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2));
|
||||
RINOK(setStream->SetInStream(seqInStream2));
|
||||
isSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isSet && numInStreams != 0)
|
||||
{
|
||||
CMyComPtr<ICompressSetInStream2> setStream2;
|
||||
coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2);
|
||||
if (!setStream2)
|
||||
return E_NOTIMPL;
|
||||
|
||||
for (UInt32 i = 0; i < numInStreams; i++)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> seqInStream2;
|
||||
RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + i, &seqInStream2));
|
||||
RINOK(setStream2->SetInStream2(i, seqInStream2));
|
||||
}
|
||||
}
|
||||
|
||||
*inStreamRes = seqInStream.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMixerST::GetInStream(
|
||||
ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
|
||||
UInt32 inStreamIndex, ISequentialInStream **inStreamRes)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> seqInStream;
|
||||
|
||||
{
|
||||
int index = -1;
|
||||
if (EncodeMode)
|
||||
{
|
||||
if (_bi.UnpackCoder == inStreamIndex)
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
index = _bi.FindStream_in_PackStreams(inStreamIndex);
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
seqInStream = inStreams[index];
|
||||
*inStreamRes = seqInStream.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
int bond = FindBond_for_Stream(
|
||||
true, // forInputStream
|
||||
inStreamIndex);
|
||||
if (bond < 0)
|
||||
return E_INVALIDARG;
|
||||
|
||||
RINOK(GetInStream2(inStreams, /* inSizes, */
|
||||
_bi.Bonds[bond].Get_OutIndex(EncodeMode), &seqInStream));
|
||||
|
||||
while (_binderStreams.Size() <= (unsigned)bond)
|
||||
_binderStreams.AddNew();
|
||||
CStBinderStream &bs = _binderStreams[bond];
|
||||
|
||||
if (bs.StreamRef || bs.InStreamSpec)
|
||||
return E_NOTIMPL;
|
||||
|
||||
CSequentialInStreamCalcSize *spec = new CSequentialInStreamCalcSize;
|
||||
bs.StreamRef = spec;
|
||||
bs.InStreamSpec = spec;
|
||||
|
||||
spec->SetStream(seqInStream);
|
||||
spec->Init();
|
||||
|
||||
seqInStream = bs.InStreamSpec;
|
||||
|
||||
*inStreamRes = seqInStream.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMixerST::GetOutStream(
|
||||
ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
|
||||
UInt32 outStreamIndex, ISequentialOutStream **outStreamRes)
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> seqOutStream;
|
||||
|
||||
{
|
||||
int index = -1;
|
||||
if (!EncodeMode)
|
||||
{
|
||||
if (_bi.UnpackCoder == outStreamIndex)
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
index = _bi.FindStream_in_PackStreams(outStreamIndex);
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
seqOutStream = outStreams[index];
|
||||
*outStreamRes = seqOutStream.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
int bond = FindBond_for_Stream(
|
||||
false, // forInputStream
|
||||
outStreamIndex);
|
||||
if (bond < 0)
|
||||
return E_INVALIDARG;
|
||||
|
||||
UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
|
||||
|
||||
UInt32 coderIndex = inStreamIndex;
|
||||
UInt32 coderStreamIndex = 0;
|
||||
|
||||
if (!EncodeMode)
|
||||
_bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
|
||||
|
||||
CCoder &coder = _coders[coderIndex];
|
||||
|
||||
/*
|
||||
if (!coder.Coder)
|
||||
return E_NOTIMPL;
|
||||
*/
|
||||
|
||||
coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream);
|
||||
if (!seqOutStream)
|
||||
return E_NOTIMPL;
|
||||
|
||||
UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
|
||||
UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
|
||||
|
||||
bool isSet = false;
|
||||
|
||||
if (numOutStreams == 1)
|
||||
{
|
||||
CMyComPtr<ICompressSetOutStream> setOutStream;
|
||||
coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
|
||||
if (setOutStream)
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> seqOutStream2;
|
||||
RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2));
|
||||
RINOK(setOutStream->SetOutStream(seqOutStream2));
|
||||
isSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isSet && numOutStreams != 0)
|
||||
{
|
||||
// return E_NOTIMPL;
|
||||
// /*
|
||||
CMyComPtr<ICompressSetOutStream2> setStream2;
|
||||
coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2);
|
||||
if (!setStream2)
|
||||
return E_NOTIMPL;
|
||||
for (UInt32 i = 0; i < numOutStreams; i++)
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> seqOutStream2;
|
||||
RINOK(GetOutStream(outStreams, startIndex + i, &seqOutStream2));
|
||||
RINOK(setStream2->SetOutStream2(i, seqOutStream2));
|
||||
}
|
||||
// */
|
||||
}
|
||||
|
||||
while (_binderStreams.Size() <= (unsigned)bond)
|
||||
_binderStreams.AddNew();
|
||||
CStBinderStream &bs = _binderStreams[bond];
|
||||
|
||||
if (bs.StreamRef || bs.OutStreamSpec)
|
||||
return E_NOTIMPL;
|
||||
|
||||
COutStreamCalcSize *spec = new COutStreamCalcSize;
|
||||
bs.StreamRef = (ISequentialOutStream *)spec;
|
||||
bs.OutStreamSpec = spec;
|
||||
|
||||
spec->SetStream(seqOutStream);
|
||||
spec->Init();
|
||||
|
||||
seqOutStream = bs.OutStreamSpec;
|
||||
|
||||
*outStreamRes = seqOutStream.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
static HRESULT GetError(HRESULT res, HRESULT res2)
|
||||
{
|
||||
if (res == res2)
|
||||
return res;
|
||||
if (res == S_OK)
|
||||
return res2;
|
||||
if (res == k_My_HRESULT_WritingWasCut)
|
||||
{
|
||||
if (res2 != S_OK)
|
||||
return res2;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMixerST::FlushStream(UInt32 streamIndex)
|
||||
{
|
||||
{
|
||||
int index = -1;
|
||||
if (!EncodeMode)
|
||||
{
|
||||
if (_bi.UnpackCoder == streamIndex)
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
index = _bi.FindStream_in_PackStreams(streamIndex);
|
||||
|
||||
if (index >= 0)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
int bond = FindBond_for_Stream(
|
||||
false, // forInputStream
|
||||
streamIndex);
|
||||
if (bond < 0)
|
||||
return E_INVALIDARG;
|
||||
|
||||
UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
|
||||
|
||||
UInt32 coderIndex = inStreamIndex;
|
||||
UInt32 coderStreamIndex = 0;
|
||||
if (!EncodeMode)
|
||||
_bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
|
||||
|
||||
CCoder &coder = _coders[coderIndex];
|
||||
CMyComPtr<IOutStreamFlush> flush;
|
||||
coder.QueryInterface(IID_IOutStreamFlush, (void **)&flush);
|
||||
HRESULT res = S_OK;
|
||||
if (flush)
|
||||
{
|
||||
res = flush->Flush();
|
||||
}
|
||||
return GetError(res, FlushCoder(coderIndex));
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMixerST::FlushCoder(UInt32 coderIndex)
|
||||
{
|
||||
CCoder &coder = _coders[coderIndex];
|
||||
|
||||
UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
|
||||
UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
|
||||
|
||||
HRESULT res = S_OK;
|
||||
for (unsigned i = 0; i < numOutStreams; i++)
|
||||
res = GetError(res, FlushStream(startIndex + i));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void CMixerST::SelectMainCoder(bool useFirst)
|
||||
{
|
||||
unsigned ci = _bi.UnpackCoder;
|
||||
|
||||
int firstNonFilter = -1;
|
||||
int firstAllowed = ci;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const CCoderST &coder = _coders[ci];
|
||||
// break;
|
||||
|
||||
if (ci != _bi.UnpackCoder)
|
||||
if (EncodeMode ? !coder.CanWrite : !coder.CanRead)
|
||||
{
|
||||
firstAllowed = ci;
|
||||
firstNonFilter = -2;
|
||||
}
|
||||
|
||||
if (coder.NumStreams != 1)
|
||||
break;
|
||||
|
||||
UInt32 st = _bi.Coder_to_Stream[ci];
|
||||
if (_bi.IsStream_in_PackStreams(st))
|
||||
break;
|
||||
int bond = _bi.FindBond_for_PackStream(st);
|
||||
if (bond < 0)
|
||||
throw 20150213;
|
||||
|
||||
if (EncodeMode ? !coder.CanRead : !coder.CanWrite)
|
||||
break;
|
||||
|
||||
if (firstNonFilter == -1 && !IsFilter_Vector[ci])
|
||||
firstNonFilter = ci;
|
||||
|
||||
ci = _bi.Bonds[bond].UnpackIndex;
|
||||
}
|
||||
|
||||
ci = firstNonFilter;
|
||||
if (firstNonFilter < 0 || useFirst)
|
||||
ci = firstAllowed;
|
||||
MainCoderIndex = ci;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMixerST::Code(
|
||||
ISequentialInStream * const *inStreams,
|
||||
ISequentialOutStream * const *outStreams,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
_binderStreams.Clear();
|
||||
unsigned ci = MainCoderIndex;
|
||||
|
||||
const CCoder &mainCoder = _coders[MainCoderIndex];
|
||||
|
||||
CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;
|
||||
CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;
|
||||
|
||||
UInt32 numInStreams = EncodeMode ? 1 : mainCoder.NumStreams;
|
||||
UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams;
|
||||
|
||||
UInt32 startInIndex = EncodeMode ? ci : _bi.Coder_to_Stream[ci];
|
||||
UInt32 startOutIndex = !EncodeMode ? ci : _bi.Coder_to_Stream[ci];
|
||||
|
||||
UInt32 i;
|
||||
|
||||
for (i = 0; i < numInStreams; i++)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> seqInStream;
|
||||
RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream));
|
||||
seqInStreams.Add(seqInStream);
|
||||
}
|
||||
|
||||
for (i = 0; i < numOutStreams; i++)
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> seqOutStream;
|
||||
RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream));
|
||||
seqOutStreams.Add(seqOutStream);
|
||||
}
|
||||
|
||||
CRecordVector< ISequentialInStream * > seqInStreamsSpec;
|
||||
CRecordVector< ISequentialOutStream * > seqOutStreamsSpec;
|
||||
|
||||
for (i = 0; i < numInStreams; i++)
|
||||
seqInStreamsSpec.Add(seqInStreams[i]);
|
||||
for (i = 0; i < numOutStreams; i++)
|
||||
seqOutStreamsSpec.Add(seqOutStreams[i]);
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
if (i == ci)
|
||||
continue;
|
||||
|
||||
CCoder &coder = _coders[i];
|
||||
|
||||
CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
|
||||
coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
|
||||
if (setOutStreamSize)
|
||||
{
|
||||
RINOK(setOutStreamSize->SetOutStreamSize(
|
||||
EncodeMode ? coder.PackSizePointers[0] : coder.UnpackSizePointer));
|
||||
}
|
||||
}
|
||||
|
||||
const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : &mainCoder.PackSizePointers.Front();
|
||||
const UInt64 * const *outSizes2 = EncodeMode ? &mainCoder.PackSizePointers.Front() : &mainCoder.UnpackSizePointer;
|
||||
|
||||
HRESULT res;
|
||||
if (mainCoder.Coder)
|
||||
{
|
||||
res = mainCoder.Coder->Code(
|
||||
seqInStreamsSpec[0], seqOutStreamsSpec[0],
|
||||
isSizes2[0], outSizes2[0],
|
||||
progress);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = mainCoder.Coder2->Code(
|
||||
&seqInStreamsSpec.Front(), isSizes2, numInStreams,
|
||||
&seqOutStreamsSpec.Front(), outSizes2, numOutStreams,
|
||||
progress);
|
||||
}
|
||||
|
||||
if (res == k_My_HRESULT_WritingWasCut)
|
||||
res = S_OK;
|
||||
|
||||
if (res == S_OK || res == S_FALSE)
|
||||
{
|
||||
res = GetError(res, FlushCoder(ci));
|
||||
}
|
||||
|
||||
for (i = 0; i < _binderStreams.Size(); i++)
|
||||
{
|
||||
const CStBinderStream &bs = _binderStreams[i];
|
||||
if (bs.InStreamSpec)
|
||||
bs.InStreamSpec->ReleaseStream();
|
||||
else
|
||||
bs.OutStreamSpec->ReleaseStream();
|
||||
}
|
||||
|
||||
if (res == k_My_HRESULT_WritingWasCut)
|
||||
res = S_OK;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMixerST::GetMainUnpackStream(
|
||||
ISequentialInStream * const *inStreams,
|
||||
ISequentialInStream **inStreamRes)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> seqInStream;
|
||||
|
||||
RINOK(GetInStream2(inStreams, /* inSizes, */
|
||||
_bi.UnpackCoder, &seqInStream))
|
||||
|
||||
FOR_VECTOR (i, _coders)
|
||||
{
|
||||
CCoder &coder = _coders[i];
|
||||
CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
|
||||
coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
|
||||
if (setOutStreamSize)
|
||||
{
|
||||
RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer));
|
||||
}
|
||||
}
|
||||
|
||||
*inStreamRes = seqInStream.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const
|
||||
{
|
||||
const CStBinderStream &bs = _binderStreams[bondIndex];
|
||||
if (bs.InStreamSpec)
|
||||
return bs.InStreamSpec->GetSize();
|
||||
return bs.OutStreamSpec->GetSize();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
// CoderMixer2ST.h
|
||||
|
||||
#ifndef __CODER_MIXER2_ST_H
|
||||
#define __CODER_MIXER2_ST_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../ICoder.h"
|
||||
|
||||
#include "CoderMixer2.h"
|
||||
|
||||
class CSequentialInStreamCalcSize:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(ISequentialInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
private:
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
UInt64 _size;
|
||||
bool _wasFinished;
|
||||
public:
|
||||
void SetStream(ISequentialInStream *stream) { _stream = stream; }
|
||||
void Init()
|
||||
{
|
||||
_size = 0;
|
||||
_wasFinished = false;
|
||||
}
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
bool WasFinished() const { return _wasFinished; }
|
||||
};
|
||||
|
||||
|
||||
class COutStreamCalcSize:
|
||||
public ISequentialOutStream,
|
||||
public IOutStreamFlush,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
UInt64 _size;
|
||||
public:
|
||||
MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFlush)
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Flush)();
|
||||
|
||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
void Init() { _size = 0; }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
namespace NCoderMixer2 {
|
||||
|
||||
struct CCoderST: public CCoder
|
||||
{
|
||||
bool CanRead;
|
||||
bool CanWrite;
|
||||
|
||||
CCoderST(): CanRead(false), CanWrite(false) {}
|
||||
};
|
||||
|
||||
|
||||
struct CStBinderStream
|
||||
{
|
||||
CSequentialInStreamCalcSize *InStreamSpec;
|
||||
COutStreamCalcSize *OutStreamSpec;
|
||||
CMyComPtr<IUnknown> StreamRef;
|
||||
|
||||
CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {}
|
||||
};
|
||||
|
||||
|
||||
class CMixerST:
|
||||
public IUnknown,
|
||||
public CMixer,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
|
||||
UInt32 outStreamIndex, ISequentialInStream **inStreamRes);
|
||||
HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
|
||||
UInt32 inStreamIndex, ISequentialInStream **inStreamRes);
|
||||
HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
|
||||
UInt32 outStreamIndex, ISequentialOutStream **outStreamRes);
|
||||
|
||||
HRESULT FlushStream(UInt32 streamIndex);
|
||||
HRESULT FlushCoder(UInt32 coderIndex);
|
||||
|
||||
public:
|
||||
CObjectVector<CCoderST> _coders;
|
||||
|
||||
CObjectVector<CStBinderStream> _binderStreams;
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
CMixerST(bool encodeMode);
|
||||
~CMixerST();
|
||||
|
||||
virtual void AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter);
|
||||
|
||||
virtual CCoder &GetCoder(unsigned index);
|
||||
|
||||
virtual void SelectMainCoder(bool useFirst);
|
||||
|
||||
virtual void ReInit();
|
||||
|
||||
virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
|
||||
{ _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
|
||||
|
||||
virtual HRESULT Code(
|
||||
ISequentialInStream * const *inStreams,
|
||||
ISequentialOutStream * const *outStreams,
|
||||
ICompressProgressInfo *progress);
|
||||
|
||||
virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
|
||||
|
||||
HRESULT GetMainUnpackStream(
|
||||
ISequentialInStream * const *inStreams,
|
||||
ISequentialInStream **inStreamRes);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,99 +0,0 @@
|
||||
// CoderMixerMT.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "CoderMixerMT.h"
|
||||
|
||||
namespace NCoderMixer {
|
||||
|
||||
void CCoder::Execute() { Code(NULL); }
|
||||
|
||||
void CCoder::Code(ICompressProgressInfo *progress)
|
||||
{
|
||||
Result = Coder->Code(InStream, OutStream,
|
||||
InSizeAssigned ? &InSizeValue : NULL,
|
||||
OutSizeAssigned ? &OutSizeValue : NULL,
|
||||
progress);
|
||||
InStream.Release();
|
||||
OutStream.Release();
|
||||
}
|
||||
|
||||
void CCoderMixerMT::AddCoder(ICompressCoder *coder)
|
||||
{
|
||||
_coders.Add(CCoder());
|
||||
_coders.Back().Coder = coder;
|
||||
}
|
||||
|
||||
void CCoderMixerMT::ReInit()
|
||||
{
|
||||
for(int i = 0; i < _coders.Size(); i++)
|
||||
_coders[i].ReInit();
|
||||
}
|
||||
|
||||
HRESULT CCoderMixerMT::ReturnIfError(HRESULT code)
|
||||
{
|
||||
for (int i = 0; i < _coders.Size(); i++)
|
||||
if (_coders[i].Result == code)
|
||||
return code;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CCoderMixerMT::Code(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 * /* outSize */,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
_coders.Front().InStream = inStream;
|
||||
int i;
|
||||
_coders.Back().OutStream = outStream;
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
if (i != _progressCoderIndex)
|
||||
{
|
||||
RINOK(_coders[i].Create());
|
||||
}
|
||||
|
||||
_streamBinders.Clear();
|
||||
for (i = 0; i + 1 < _coders.Size(); i++)
|
||||
{
|
||||
_streamBinders.Add(CStreamBinder());
|
||||
CStreamBinder &sb = _streamBinders[i];
|
||||
RINOK(sb.CreateEvents());
|
||||
sb.CreateStreams(&_coders[i + 1].InStream, &_coders[i].OutStream);
|
||||
}
|
||||
|
||||
for(i = 0; i < _streamBinders.Size(); i++)
|
||||
_streamBinders[i].ReInit();
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
if (i != _progressCoderIndex)
|
||||
_coders[i].Start();
|
||||
|
||||
_coders[_progressCoderIndex].Code(progress);
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
if (i != _progressCoderIndex)
|
||||
_coders[i].WaitExecuteFinish();
|
||||
|
||||
RINOK(ReturnIfError(E_ABORT));
|
||||
RINOK(ReturnIfError(E_OUTOFMEMORY));
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
HRESULT result = _coders[i].Result;
|
||||
if (result != S_OK && result != E_FAIL && result != S_FALSE)
|
||||
return result;
|
||||
}
|
||||
|
||||
RINOK(ReturnIfError(S_FALSE));
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
HRESULT result = _coders[i].Result;
|
||||
if (result != S_OK)
|
||||
return result;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
// CoderMixerMT.h
|
||||
|
||||
#ifndef __CODER_MIXER_MT_H
|
||||
#define __CODER_MIXER_MT_H
|
||||
|
||||
#include "../../../Common/MyVector.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../ICoder.h"
|
||||
#include "../../Common/StreamBinder.h"
|
||||
#include "../../Common/VirtThread.h"
|
||||
#include "CoderMixer.h"
|
||||
|
||||
namespace NCoderMixer {
|
||||
|
||||
struct CCoder: public CCoderInfo, public CVirtThread
|
||||
{
|
||||
HRESULT Result;
|
||||
|
||||
virtual void Execute();
|
||||
void Code(ICompressProgressInfo *progress);
|
||||
virtual ~CCoder() { CVirtThread::WaitThreadFinish(); }
|
||||
};
|
||||
|
||||
/*
|
||||
for each coder
|
||||
AddCoder()
|
||||
SetProgressIndex(UInt32 coderIndex);
|
||||
|
||||
for each file
|
||||
{
|
||||
ReInit()
|
||||
for each coder
|
||||
SetCoderInfo
|
||||
Code
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
class CCoderMixerMT:
|
||||
public ICompressCoder,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CObjectVector<CStreamBinder> _streamBinders;
|
||||
int _progressCoderIndex;
|
||||
|
||||
HRESULT ReturnIfError(HRESULT code);
|
||||
public:
|
||||
CObjectVector<CCoder> _coders;
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize,
|
||||
ICompressProgressInfo *progress);
|
||||
|
||||
void AddCoder(ICompressCoder *coder);
|
||||
void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; }
|
||||
|
||||
void ReInit();
|
||||
void SetCoderInfo(UInt32 coderIndex, const UInt64 *inSize, const UInt64 *outSize)
|
||||
{ _coders[coderIndex].SetCoderInfo(inSize, outSize); }
|
||||
|
||||
/*
|
||||
UInt64 GetWriteProcessedSize(UInt32 binderIndex) const
|
||||
{ return _streamBinders[binderIndex].ProcessedSize; }
|
||||
*/
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../../../Common/MyBuffer.h"
|
||||
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// FindSignature.h
|
||||
|
||||
#ifndef __FINDSIGNATURE_H
|
||||
#define __FINDSIGNATURE_H
|
||||
#ifndef __FIND_SIGNATURE_H
|
||||
#define __FIND_SIGNATURE_H
|
||||
|
||||
#include "../../IStream.h"
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/MyWindows.h"
|
||||
|
||||
#include "../../Common/MyInitGuid.h"
|
||||
|
||||
#if defined(_7ZIP_LARGE_PAGES)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
/* If NSIS_SCRIPT is defined, it will decompile NSIS script to [NSIS].nsi file.
|
||||
The code is much larger in that case. */
|
||||
|
||||
#define NSIS_SCRIPT
|
||||
// #define NSIS_SCRIPT
|
||||
|
||||
namespace NArchive {
|
||||
namespace NNsis {
|
||||
|
||||
2683
CPP/7zip/Archive/Rar/Rar5Handler.cpp
Normal file
2683
CPP/7zip/Archive/Rar/Rar5Handler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
410
CPP/7zip/Archive/Rar/Rar5Handler.h
Normal file
410
CPP/7zip/Archive/Rar/Rar5Handler.h
Normal file
@@ -0,0 +1,410 @@
|
||||
// Rar5Handler.h
|
||||
|
||||
#ifndef __RAR5_HANDLER_H
|
||||
#define __RAR5_HANDLER_H
|
||||
|
||||
#include "../../../../C/Blake2.h"
|
||||
|
||||
#include "../../../Common/MyBuffer.h"
|
||||
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
|
||||
#include "../IArchive.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NRar5 {
|
||||
|
||||
namespace NHeaderFlags
|
||||
{
|
||||
const unsigned kExtra = 1 << 0;
|
||||
const unsigned kData = 1 << 1;
|
||||
// const unsigned kUnknown = 1 << 2;
|
||||
const unsigned kPrevVol = 1 << 3;
|
||||
const unsigned kNextVol = 1 << 4;
|
||||
// const unsigned kIsChild = 1 << 5;
|
||||
// const unsigned kPreserveChild = 1 << 6;
|
||||
}
|
||||
|
||||
namespace NHeaderType
|
||||
{
|
||||
enum
|
||||
{
|
||||
kArc = 1,
|
||||
kFile,
|
||||
kService,
|
||||
kArcEncrypt,
|
||||
kEndOfArc
|
||||
};
|
||||
}
|
||||
|
||||
namespace NArcFlags
|
||||
{
|
||||
const unsigned kVol = 1 << 0;
|
||||
const unsigned kVolNumber = 1 << 1;
|
||||
const unsigned kSolid = 1 << 2;
|
||||
// const unsigned kRecovery = 1 << 3;
|
||||
// const unsigned kLocked = 1 << 4;
|
||||
}
|
||||
|
||||
const unsigned kArcExtraRecordType_Locator = 1;
|
||||
|
||||
namespace NLocatorFlags
|
||||
{
|
||||
const unsigned kQuickOpen = 1 << 0;
|
||||
const unsigned kRecovery = 1 << 1;
|
||||
}
|
||||
|
||||
namespace NFileFlags
|
||||
{
|
||||
const unsigned kIsDir = 1 << 0;
|
||||
const unsigned kUnixTime = 1 << 1;
|
||||
const unsigned kCrc32 = 1 << 2;
|
||||
const unsigned kUnknownSize = 1 << 3;
|
||||
}
|
||||
|
||||
namespace NMethodFlags
|
||||
{
|
||||
// const unsigned kVersionMask = 0x3F;
|
||||
const unsigned kSolid = 1 << 6;
|
||||
}
|
||||
|
||||
namespace NArcEndFlags
|
||||
{
|
||||
const unsigned kMoreVols = 1 << 0;
|
||||
}
|
||||
|
||||
enum EHostOS
|
||||
{
|
||||
kHost_Windows = 0,
|
||||
kHost_Unix
|
||||
};
|
||||
|
||||
|
||||
|
||||
// ---------- Extra ----------
|
||||
|
||||
namespace NExtraRecordType
|
||||
{
|
||||
enum
|
||||
{
|
||||
kCrypto = 1,
|
||||
kHash,
|
||||
kTime,
|
||||
kVersion,
|
||||
kLink,
|
||||
kUnixOwner,
|
||||
kSubdata
|
||||
};
|
||||
}
|
||||
|
||||
// const unsigned kCryptoAlgo_AES = 0;
|
||||
|
||||
namespace NCryptoFlags
|
||||
{
|
||||
const unsigned kPswCheck = 1 << 0;
|
||||
const unsigned kUseMAC = 1 << 1;
|
||||
}
|
||||
|
||||
struct CCryptoInfo
|
||||
{
|
||||
UInt64 Algo;
|
||||
UInt64 Flags;
|
||||
Byte Cnt;
|
||||
|
||||
bool UseMAC() const { return (Flags & NCryptoFlags::kUseMAC) != 0; }
|
||||
bool IsThereCheck() const { return (Flags & NCryptoFlags::kPswCheck) != 0; }
|
||||
bool Parse(const Byte *p, size_t size);
|
||||
};
|
||||
|
||||
const unsigned kHashID_Blake2sp = 0;
|
||||
|
||||
namespace NTimeRecord
|
||||
{
|
||||
enum
|
||||
{
|
||||
k_Index_MTime = 0,
|
||||
k_Index_CTime,
|
||||
k_Index_ATime
|
||||
};
|
||||
|
||||
namespace NFlags
|
||||
{
|
||||
const unsigned kUnixTime = 1 << 0;
|
||||
const unsigned kMTime = 1 << 1;
|
||||
// const unsigned kCTime = 1 << 2;
|
||||
// const unsigned kATime = 1 << 3;
|
||||
}
|
||||
}
|
||||
|
||||
namespace NLinkType
|
||||
{
|
||||
enum
|
||||
{
|
||||
kUnixSymLink = 1,
|
||||
kWinSymLink,
|
||||
kWinJunction,
|
||||
kHardLink,
|
||||
kFileCopy
|
||||
};
|
||||
}
|
||||
|
||||
namespace NLinkFlags
|
||||
{
|
||||
const unsigned kTargetIsDir = 1 << 0;
|
||||
}
|
||||
|
||||
|
||||
struct CItem
|
||||
{
|
||||
UInt32 CommonFlags;
|
||||
UInt32 Flags;
|
||||
|
||||
Byte RecordType;
|
||||
bool Version_Defined;
|
||||
|
||||
int ACL;
|
||||
|
||||
AString Name;
|
||||
|
||||
int VolIndex;
|
||||
int NextItem;
|
||||
|
||||
UInt32 UnixMTime;
|
||||
UInt32 CRC;
|
||||
UInt32 Attrib;
|
||||
UInt32 Method;
|
||||
|
||||
CByteBuffer Extra;
|
||||
|
||||
UInt64 Size;
|
||||
UInt64 PackSize;
|
||||
UInt64 HostOS;
|
||||
|
||||
UInt64 DataPos;
|
||||
UInt64 Version;
|
||||
|
||||
CItem() { Clear(); }
|
||||
|
||||
void Clear()
|
||||
{
|
||||
CommonFlags = 0;
|
||||
Flags = 0;
|
||||
|
||||
VolIndex = 0;
|
||||
NextItem = -1;
|
||||
|
||||
Version_Defined = false;
|
||||
Version = 0;
|
||||
|
||||
Name.Empty();
|
||||
Extra.Free();
|
||||
ACL = -1;
|
||||
}
|
||||
|
||||
bool IsSplitBefore() const { return (CommonFlags & NHeaderFlags::kPrevVol) != 0; }
|
||||
bool IsSplitAfter() const { return (CommonFlags & NHeaderFlags::kNextVol) != 0; }
|
||||
bool IsSplit() const { return (CommonFlags & (NHeaderFlags::kPrevVol | NHeaderFlags::kNextVol)) != 0; }
|
||||
|
||||
bool IsDir() const { return (Flags & NFileFlags::kIsDir) != 0; }
|
||||
bool Has_UnixMTime() const { return (Flags & NFileFlags::kUnixTime) != 0; }
|
||||
bool Has_CRC() const { return (Flags & NFileFlags::kCrc32) != 0; }
|
||||
bool Is_UnknownSize() const { return (Flags & NFileFlags::kUnknownSize) != 0; }
|
||||
|
||||
bool IsNextForItem(const CItem &prev) const
|
||||
{
|
||||
return !IsDir() && !prev.IsDir() && IsSplitBefore() && prev.IsSplitAfter() && (Name == prev.Name);
|
||||
// && false;
|
||||
}
|
||||
|
||||
bool IsSolid() const { return ((UInt32)Method & NMethodFlags::kSolid) != 0; }
|
||||
unsigned GetAlgoVersion() const { return (unsigned)Method & 0x3F; }
|
||||
unsigned GetMethod() const { return ((unsigned)Method >> 7) & 0x7; }
|
||||
UInt32 GetDictSize() const { return (((UInt32)Method >> 10) & 0xF); }
|
||||
|
||||
bool IsService() const { return RecordType == NHeaderType::kService; }
|
||||
|
||||
bool Is_STM() const { return IsService() && Name == "STM"; }
|
||||
bool Is_CMT() const { return IsService() && Name == "CMT"; }
|
||||
bool Is_ACL() const { return IsService() && Name == "ACL"; }
|
||||
// bool Is_QO() const { return IsService() && Name == "QO"; }
|
||||
|
||||
int FindExtra(unsigned type, unsigned &recordDataSize) const;
|
||||
|
||||
bool IsEncrypted() const
|
||||
{
|
||||
unsigned size;
|
||||
return FindExtra(NExtraRecordType::kCrypto, size) >= 0;
|
||||
}
|
||||
|
||||
int FindExtra_Blake() const
|
||||
{
|
||||
unsigned size = 0;
|
||||
int offset = FindExtra(NExtraRecordType::kHash, size);
|
||||
if (offset >= 0
|
||||
&& size == BLAKE2S_DIGEST_SIZE + 1
|
||||
&& Extra[(unsigned)offset] == kHashID_Blake2sp)
|
||||
return offset + 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool FindExtra_Version(UInt64 &version) const;
|
||||
|
||||
struct CLinkInfo
|
||||
{
|
||||
UInt64 Type;
|
||||
UInt64 Flags;
|
||||
unsigned NameOffset;
|
||||
unsigned NameLen;
|
||||
};
|
||||
|
||||
bool FindExtra_Link(CLinkInfo &link) const;
|
||||
void Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) const;
|
||||
bool Is_CopyLink() const;
|
||||
|
||||
bool NeedUse_as_CopyLink() const { return PackSize == 0 && Is_CopyLink(); }
|
||||
|
||||
bool GetAltStreamName(AString &name) const;
|
||||
|
||||
UInt32 GetWinAttrib() const
|
||||
{
|
||||
UInt32 a;
|
||||
switch (HostOS)
|
||||
{
|
||||
case kHost_Windows: a = Attrib; break;
|
||||
case kHost_Unix: a = (Attrib << 16); break;
|
||||
default: a = 0;
|
||||
}
|
||||
// if (IsDir()) a |= FILE_ATTRIBUTE_DIRECTORY;
|
||||
return a;
|
||||
}
|
||||
|
||||
UInt64 GetDataPosition() const { return DataPos; }
|
||||
};
|
||||
|
||||
|
||||
struct CInArcInfo
|
||||
{
|
||||
UInt64 Flags;
|
||||
UInt64 VolNumber;
|
||||
UInt64 StartPos;
|
||||
UInt64 EndPos;
|
||||
|
||||
UInt64 EndFlags;
|
||||
bool EndOfArchive_was_Read;
|
||||
|
||||
bool IsEncrypted;
|
||||
|
||||
// CByteBuffer Extra;
|
||||
|
||||
/*
|
||||
struct CLocator
|
||||
{
|
||||
UInt64 Flags;
|
||||
UInt64 QuickOpen;
|
||||
UInt64 Recovery;
|
||||
|
||||
bool Is_QuickOpen() const { return (Flags & NLocatorFlags::kQuickOpen) != 0; }
|
||||
bool Is_Recovery() const { return (Flags & NLocatorFlags::kRecovery) != 0; }
|
||||
};
|
||||
|
||||
int FindExtra(unsigned type, unsigned &recordDataSize) const;
|
||||
bool FindExtra_Locator(CLocator &locator) const;
|
||||
*/
|
||||
|
||||
CInArcInfo():
|
||||
Flags(0),
|
||||
VolNumber(0),
|
||||
StartPos(0),
|
||||
EndPos(0),
|
||||
EndFlags(0),
|
||||
EndOfArchive_was_Read(false),
|
||||
IsEncrypted(false)
|
||||
{}
|
||||
|
||||
/*
|
||||
void Clear()
|
||||
{
|
||||
Flags = 0;
|
||||
VolNumber = 0;
|
||||
StartPos = 0;
|
||||
EndPos = 0;
|
||||
EndFlags = 0;
|
||||
EndOfArchive_was_Read = false;
|
||||
Extra.Free();
|
||||
}
|
||||
*/
|
||||
|
||||
UInt64 GetPhySize() const { return EndPos - StartPos; }
|
||||
|
||||
bool AreMoreVolumes() const { return (EndFlags & NArcEndFlags::kMoreVols) != 0; }
|
||||
|
||||
bool IsVolume() const { return (Flags & NArcFlags::kVol) != 0; }
|
||||
bool IsSolid() const { return (Flags & NArcFlags::kSolid) != 0; }
|
||||
bool Is_VolNumber_Defined() const { return (Flags & NArcFlags::kVolNumber) != 0; }
|
||||
|
||||
UInt64 GetVolIndex() const { return Is_VolNumber_Defined() ? VolNumber : 0; }
|
||||
};
|
||||
|
||||
|
||||
struct CRefItem
|
||||
{
|
||||
unsigned Item;
|
||||
unsigned Last;
|
||||
int Parent;
|
||||
int Link;
|
||||
};
|
||||
|
||||
|
||||
struct CArc
|
||||
{
|
||||
CMyComPtr<IInStream> Stream;
|
||||
CInArcInfo Info;
|
||||
};
|
||||
|
||||
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
public IArchiveGetRawProps,
|
||||
PUBLIC_ISetCompressCodecsInfo
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
CRecordVector<CRefItem> _refs;
|
||||
CObjectVector<CItem> _items;
|
||||
private:
|
||||
CObjectVector<CArc> _arcs;
|
||||
CObjectVector<CByteBuffer> _acls;
|
||||
|
||||
UInt32 _errorFlags;
|
||||
// UInt32 _warningFlags;
|
||||
bool _isArc;
|
||||
CByteBuffer _comment;
|
||||
|
||||
DECL_EXTERNAL_CODECS_VARS
|
||||
|
||||
UInt64 GetPackSize(unsigned refIndex) const;
|
||||
|
||||
void FillLinks();
|
||||
|
||||
HRESULT Open2(IInStream *stream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *openCallback);
|
||||
|
||||
public:
|
||||
MY_QUERYINTERFACE_BEGIN2(IInArchive)
|
||||
MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
|
||||
QUERY_ENTRY_ISetCompressCodecsInfo
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
INTERFACE_IInArchive(;)
|
||||
INTERFACE_IArchiveGetRawProps(;)
|
||||
|
||||
DECL_ISetCompressCodecsInfo
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "../Common/ItemNameUtils.h"
|
||||
#include "../Common/OutStreamWithCRC.h"
|
||||
|
||||
#include "RarVol.h"
|
||||
#include "RarHandler.h"
|
||||
|
||||
using namespace NWindows;
|
||||
@@ -44,6 +45,8 @@ namespace NRar {
|
||||
|
||||
static const Byte kMarker[NHeader::kMarkerSize] = SIGNATURE;
|
||||
|
||||
const unsigned kPasswordLen_MAX = 127;
|
||||
|
||||
bool CItem::IgnoreItem() const
|
||||
{
|
||||
switch (HostOS)
|
||||
@@ -131,7 +134,7 @@ class CInArchive
|
||||
CByteBuffer _comment;
|
||||
CByteBuffer m_FileHeaderData;
|
||||
NHeader::NBlock::CBlock m_BlockHeader;
|
||||
NCrypto::NRar29::CDecoder *m_RarAESSpec;
|
||||
NCrypto::NRar3::CDecoder *m_RarAESSpec;
|
||||
CMyComPtr<ICompressFilter> m_RarAES;
|
||||
CBuffer<Byte> m_DecryptedData;
|
||||
Byte *m_DecryptedDataAligned;
|
||||
@@ -362,6 +365,7 @@ static int ReadTime(const Byte *p, unsigned size, Byte mask, CRarTime &rarTime)
|
||||
_ttt_ .DosTime = Get32(p); p += 4; size -= 4; \
|
||||
READ_TIME(_mask_, _ttt_); } \
|
||||
|
||||
|
||||
bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item)
|
||||
{
|
||||
const Byte *pStart = p;
|
||||
@@ -500,7 +504,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
|
||||
}
|
||||
if (!m_RarAES)
|
||||
{
|
||||
m_RarAESSpec = new NCrypto::NRar29::CDecoder;
|
||||
m_RarAESSpec = new NCrypto::NRar3::CDecoder;
|
||||
m_RarAES = m_RarAESSpec;
|
||||
}
|
||||
m_RarAESSpec->SetRar350Mode(ArcInfo.IsEncryptOld());
|
||||
@@ -518,7 +522,10 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
|
||||
unsigned len = 0;
|
||||
if (password)
|
||||
len = MyStringLen(password);
|
||||
CByteBuffer buffer(len * 2);
|
||||
if (len > kPasswordLen_MAX)
|
||||
len = kPasswordLen_MAX;
|
||||
|
||||
CByteArr buffer(len * 2);
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
wchar_t c = password[i];
|
||||
@@ -526,7 +533,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
|
||||
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
|
||||
}
|
||||
|
||||
RINOK(m_RarAESSpec->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size()));
|
||||
m_RarAESSpec->SetPassword((const Byte *)buffer, len * 2);
|
||||
|
||||
const UInt32 kDecryptedBufferSize = (1 << 12);
|
||||
if (m_DecryptedData.Size() == 0)
|
||||
@@ -990,121 +997,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
static bool IsDigit(wchar_t c)
|
||||
{
|
||||
return c >= L'0' && c <= L'9';
|
||||
}
|
||||
|
||||
class CVolumeName
|
||||
{
|
||||
bool _first;
|
||||
bool _newStyle;
|
||||
UString _unchangedPart;
|
||||
UString _changedPart;
|
||||
UString _afterPart;
|
||||
public:
|
||||
CVolumeName(): _newStyle(true) {};
|
||||
|
||||
bool InitName(const UString &name, bool newStyle)
|
||||
{
|
||||
_first = true;
|
||||
_newStyle = newStyle;
|
||||
int dotPos = name.ReverseFind_Dot();
|
||||
UString basePart = name;
|
||||
|
||||
if (dotPos >= 0)
|
||||
{
|
||||
UString ext = name.Ptr(dotPos + 1);
|
||||
if (ext.IsEqualTo_Ascii_NoCase("rar"))
|
||||
{
|
||||
_afterPart = name.Ptr(dotPos);
|
||||
basePart = name.Left(dotPos);
|
||||
}
|
||||
else if (ext.IsEqualTo_Ascii_NoCase("exe"))
|
||||
{
|
||||
_afterPart.SetFromAscii(".rar");
|
||||
basePart = name.Left(dotPos);
|
||||
}
|
||||
else if (!_newStyle)
|
||||
{
|
||||
if (ext.IsEqualTo_Ascii_NoCase("000") ||
|
||||
ext.IsEqualTo_Ascii_NoCase("001") ||
|
||||
ext.IsEqualTo_Ascii_NoCase("r00") ||
|
||||
ext.IsEqualTo_Ascii_NoCase("r01"))
|
||||
{
|
||||
_afterPart.Empty();
|
||||
_first = false;
|
||||
_changedPart = ext;
|
||||
_unchangedPart = name.Left(dotPos + 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_newStyle)
|
||||
{
|
||||
_afterPart.Empty();
|
||||
_unchangedPart = basePart;
|
||||
_unchangedPart += L'.';
|
||||
_changedPart.SetFromAscii("r00");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (basePart.IsEmpty())
|
||||
return false;
|
||||
unsigned i = basePart.Len();
|
||||
|
||||
do
|
||||
if (!IsDigit(basePart[i - 1]))
|
||||
break;
|
||||
while (--i);
|
||||
|
||||
_unchangedPart = basePart.Left(i);
|
||||
_changedPart = basePart.Ptr(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
void MakeBeforeFirstName()
|
||||
{
|
||||
unsigned len = _changedPart.Len();
|
||||
_changedPart.Empty();
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
_changedPart += L'0';
|
||||
}
|
||||
*/
|
||||
|
||||
UString GetNextName()
|
||||
{
|
||||
if (_newStyle || !_first)
|
||||
{
|
||||
unsigned i = _changedPart.Len();
|
||||
for (;;)
|
||||
{
|
||||
wchar_t c = _changedPart[--i];
|
||||
if (c == L'9')
|
||||
{
|
||||
c = L'0';
|
||||
_changedPart.ReplaceOneCharAtPos(i, c);
|
||||
if (i == 0)
|
||||
{
|
||||
_changedPart.InsertAtFront(L'1');
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
c++;
|
||||
_changedPart.ReplaceOneCharAtPos(i, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_first = false;
|
||||
return _unchangedPart + _changedPart + _afterPart;
|
||||
}
|
||||
};
|
||||
|
||||
static HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize)
|
||||
HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize)
|
||||
{
|
||||
areThereNonZeros = false;
|
||||
numZeros = 0;
|
||||
@@ -1136,7 +1030,6 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
{
|
||||
CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
|
||||
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
||||
CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openCallback;
|
||||
|
||||
CVolumeName seqName;
|
||||
|
||||
@@ -1145,8 +1038,8 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
|
||||
if (openCallback)
|
||||
{
|
||||
openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);
|
||||
openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
|
||||
openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
|
||||
openCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
|
||||
}
|
||||
|
||||
CInArchive archive;
|
||||
@@ -1363,108 +1256,91 @@ struct CMethodItem
|
||||
};
|
||||
|
||||
|
||||
class CFolderInStream:
|
||||
class CVolsInStream:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 _rem;
|
||||
ISequentialInStream *_stream;
|
||||
const CObjectVector<CArc> *_arcs;
|
||||
const CObjectVector<CItem> *_items;
|
||||
CRefItem _refItem;
|
||||
unsigned _curIndex;
|
||||
UInt32 _crc;
|
||||
bool _calcCrc;
|
||||
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
private:
|
||||
const CObjectVector<CArc> *_archives;
|
||||
const CObjectVector<CItem> *_items;
|
||||
CRefItem _refItem;
|
||||
unsigned _curIndex;
|
||||
UInt32 _crc;
|
||||
bool _fileIsOpen;
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
|
||||
HRESULT OpenStream();
|
||||
HRESULT CloseStream();
|
||||
public:
|
||||
void Init(const CObjectVector<CArc> *archives,
|
||||
const CObjectVector<CItem> *items,
|
||||
const CRefItem &refItem);
|
||||
|
||||
CRecordVector<UInt32> CRCs;
|
||||
};
|
||||
|
||||
|
||||
ISequentialInStream* CArc::CreateLimitedStream(UInt64 offset, UInt64 size) const
|
||||
{
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> inStream(streamSpec);
|
||||
Stream->Seek(offset, STREAM_SEEK_SET, NULL);
|
||||
streamSpec->SetStream(Stream);
|
||||
streamSpec->Init(size);
|
||||
return inStream.Detach();
|
||||
}
|
||||
|
||||
void CFolderInStream::Init(
|
||||
const CObjectVector<CArc> *archives,
|
||||
void Init(const CObjectVector<CArc> *arcs,
|
||||
const CObjectVector<CItem> *items,
|
||||
const CRefItem &refItem)
|
||||
{
|
||||
_archives = archives;
|
||||
{
|
||||
_arcs = arcs;
|
||||
_items = items;
|
||||
_refItem = refItem;
|
||||
_curIndex = 0;
|
||||
CRCs.Clear();
|
||||
_fileIsOpen = false;
|
||||
}
|
||||
_stream = NULL;
|
||||
CrcIsOK = true;
|
||||
}
|
||||
|
||||
HRESULT CFolderInStream::OpenStream()
|
||||
bool CrcIsOK;
|
||||
};
|
||||
|
||||
|
||||
STDMETHODIMP CVolsInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
while (_curIndex < _refItem.NumItems)
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
UInt32 realProcessedSize = 0;
|
||||
|
||||
while (size != 0)
|
||||
{
|
||||
if (!_stream)
|
||||
{
|
||||
if (_curIndex >= _refItem.NumItems)
|
||||
break;
|
||||
const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex];
|
||||
IInStream *s = (*_arcs)[_refItem.VolumeIndex + _curIndex].Stream;
|
||||
RINOK(s->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL));
|
||||
_stream = s;
|
||||
_calcCrc = (CrcIsOK && item.IsSplitAfter());
|
||||
_crc = CRC_INIT_VAL;
|
||||
_rem = item.PackSize;
|
||||
}
|
||||
{
|
||||
UInt32 cur = size;
|
||||
if (cur > _rem)
|
||||
cur = (UInt32)_rem;
|
||||
UInt32 num = cur;
|
||||
HRESULT res = _stream->Read(data, cur, &cur);
|
||||
if (_calcCrc)
|
||||
_crc = CrcUpdate(_crc, data, cur);
|
||||
realProcessedSize += cur;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
data = (Byte *)data + cur;
|
||||
size -= cur;
|
||||
_rem -= cur;
|
||||
if (_rem == 0)
|
||||
{
|
||||
const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex];
|
||||
_stream.Attach((*_archives)[_refItem.VolumeIndex + _curIndex].
|
||||
CreateLimitedStream(item.GetDataPosition(), item.PackSize));
|
||||
_curIndex++;
|
||||
_fileIsOpen = true;
|
||||
_crc = CRC_INIT_VAL;
|
||||
if (_calcCrc && CRC_GET_DIGEST(_crc) != item.FileCRC)
|
||||
CrcIsOK = false;
|
||||
_stream = NULL;
|
||||
}
|
||||
if (res != S_OK)
|
||||
return res;
|
||||
if (realProcessedSize != 0)
|
||||
return S_OK;
|
||||
if (cur == 0 && num != 0)
|
||||
return S_OK;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CFolderInStream::CloseStream()
|
||||
{
|
||||
CRCs.Add(CRC_GET_DIGEST(_crc));
|
||||
_stream.Release();
|
||||
_fileIsOpen = false;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize = 0;
|
||||
while ((_curIndex < _refItem.NumItems || _fileIsOpen) && size > 0)
|
||||
{
|
||||
if (_fileIsOpen)
|
||||
{
|
||||
UInt32 localProcessedSize;
|
||||
RINOK(_stream->Read(
|
||||
((Byte *)data) + realProcessedSize, size, &localProcessedSize));
|
||||
_crc = CrcUpdate(_crc, ((Byte *)data) + realProcessedSize, localProcessedSize);
|
||||
if (localProcessedSize == 0)
|
||||
{
|
||||
RINOK(CloseStream());
|
||||
continue;
|
||||
}
|
||||
realProcessedSize += localProcessedSize;
|
||||
size -= localProcessedSize;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(OpenStream());
|
||||
}
|
||||
}
|
||||
if (processedSize != 0)
|
||||
*processedSize = realProcessedSize;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -1526,13 +1402,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
CFilterCoder *filterStreamSpec = new CFilterCoder(false);
|
||||
CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec;
|
||||
|
||||
NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec = NULL;
|
||||
NCrypto::NRar2::CDecoder *rar20CryptoDecoderSpec = NULL;
|
||||
CMyComPtr<ICompressFilter> rar20CryptoDecoder;
|
||||
NCrypto::NRar29::CDecoder *rar29CryptoDecoderSpec = NULL;
|
||||
CMyComPtr<ICompressFilter> rar29CryptoDecoder;
|
||||
NCrypto::NRar3::CDecoder *rar3CryptoDecoderSpec = NULL;
|
||||
CMyComPtr<ICompressFilter> rar3CryptoDecoder;
|
||||
|
||||
CFolderInStream *folderInStreamSpec = NULL;
|
||||
CMyComPtr<ISequentialInStream> folderInStream;
|
||||
CVolsInStream *volsInStreamSpec = NULL;
|
||||
CMyComPtr<ISequentialInStream> volsInStream;
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
@@ -1602,26 +1478,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
outStreamSpec->Init();
|
||||
realOutStream.Release();
|
||||
|
||||
/*
|
||||
for (unsigned partIndex = 0; partIndex < 1; partIndex++)
|
||||
if (!volsInStream)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> inStream;
|
||||
|
||||
// item redefinition
|
||||
const CItem &item = _items[refItem.ItemIndex + partIndex];
|
||||
|
||||
CInArchive &archive = _arcs[refItem.VolumeIndex + partIndex];
|
||||
|
||||
inStream.Attach(archive.CreateLimitedStream(item.GetDataPosition(),
|
||||
item.PackSize));
|
||||
*/
|
||||
if (!folderInStream)
|
||||
{
|
||||
folderInStreamSpec = new CFolderInStream;
|
||||
folderInStream = folderInStreamSpec;
|
||||
volsInStreamSpec = new CVolsInStream;
|
||||
volsInStream = volsInStreamSpec;
|
||||
}
|
||||
|
||||
folderInStreamSpec->Init(&_arcs, &_items, refItem);
|
||||
volsInStreamSpec->Init(&_arcs, &_items, refItem);
|
||||
|
||||
UInt64 packSize = currentPackSize;
|
||||
|
||||
@@ -1632,29 +1495,29 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
if (item.IsEncrypted())
|
||||
{
|
||||
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
|
||||
// CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
|
||||
|
||||
if (item.UnPackVersion >= 29)
|
||||
{
|
||||
if (!rar29CryptoDecoder)
|
||||
if (!rar3CryptoDecoder)
|
||||
{
|
||||
rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder;
|
||||
rar29CryptoDecoder = rar29CryptoDecoderSpec;
|
||||
rar3CryptoDecoderSpec = new NCrypto::NRar3::CDecoder;
|
||||
rar3CryptoDecoder = rar3CryptoDecoderSpec;
|
||||
}
|
||||
rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);
|
||||
rar3CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);
|
||||
/*
|
||||
CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties;
|
||||
RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,
|
||||
RINOK(rar3CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,
|
||||
&cryptoProperties));
|
||||
*/
|
||||
RINOK(rar29CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
|
||||
filterStreamSpec->Filter = rar29CryptoDecoder;
|
||||
RINOK(rar3CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
|
||||
filterStreamSpec->Filter = rar3CryptoDecoder;
|
||||
}
|
||||
else if (item.UnPackVersion >= 20)
|
||||
{
|
||||
if (!rar20CryptoDecoder)
|
||||
{
|
||||
rar20CryptoDecoderSpec = new NCrypto::NRar20::CDecoder;
|
||||
rar20CryptoDecoderSpec = new NCrypto::NRar2::CDecoder;
|
||||
rar20CryptoDecoder = rar20CryptoDecoderSpec;
|
||||
}
|
||||
filterStreamSpec->Filter = rar20CryptoDecoder;
|
||||
@@ -1666,49 +1529,66 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
continue;
|
||||
}
|
||||
|
||||
RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
|
||||
// RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
|
||||
|
||||
if (!getTextPassword)
|
||||
extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
|
||||
if (getTextPassword)
|
||||
|
||||
if (!getTextPassword)
|
||||
{
|
||||
outStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod));
|
||||
continue;
|
||||
}
|
||||
|
||||
// if (getTextPassword)
|
||||
{
|
||||
CMyComBSTR password;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword(&password));
|
||||
|
||||
if (item.UnPackVersion >= 29)
|
||||
{
|
||||
UString unicodePassword;
|
||||
unsigned len = 0;
|
||||
if (password)
|
||||
len = MyStringLen(password);
|
||||
CByteBuffer buffer(len * 2);
|
||||
if (len > kPasswordLen_MAX)
|
||||
len = kPasswordLen_MAX;
|
||||
CByteArr buffer(len * 2);
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
wchar_t c = password[i];
|
||||
((Byte *)buffer)[i * 2] = (Byte)c;
|
||||
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
|
||||
}
|
||||
RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size()));
|
||||
rar3CryptoDecoderSpec->SetPassword((const Byte *)buffer, len * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
AString oemPassword;
|
||||
if (password)
|
||||
oemPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP);
|
||||
RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)(const char *)oemPassword, oemPassword.Len()));
|
||||
{
|
||||
UString unicode = (LPCOLESTR)password;
|
||||
if (unicode.Len() > kPasswordLen_MAX)
|
||||
unicode.DeleteFrom(kPasswordLen_MAX);
|
||||
oemPassword = UnicodeStringToMultiByte(unicode, CP_OEMCP);
|
||||
}
|
||||
rar20CryptoDecoderSpec->SetPassword((const Byte *)(const char *)oemPassword, oemPassword.Len());
|
||||
}
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
|
||||
RINOK(cryptoSetPassword->CryptoSetPassword(NULL, 0));
|
||||
}
|
||||
*/
|
||||
|
||||
filterStreamSpec->SetInStream(folderInStream);
|
||||
filterStreamSpec->SetInStream(volsInStream);
|
||||
filterStreamSpec->SetOutStreamSize(NULL);
|
||||
inStream = filterStream;
|
||||
}
|
||||
else
|
||||
{
|
||||
inStream = folderInStream;
|
||||
inStream = volsInStream;
|
||||
}
|
||||
|
||||
CMyComPtr<ICompressCoder> commonCoder;
|
||||
@@ -1766,7 +1646,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Byte isSolid = (Byte)((IsSolid(index) || item.IsSplitBefore()) ? 1: 0);
|
||||
if (solidStart)
|
||||
{
|
||||
isSolid = false;
|
||||
isSolid = 0;
|
||||
solidStart = false;
|
||||
}
|
||||
|
||||
@@ -1786,46 +1666,25 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
if (item.IsEncrypted())
|
||||
filterStreamSpec->ReleaseInStream();
|
||||
if (result == S_FALSE)
|
||||
{
|
||||
outStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError));
|
||||
continue;
|
||||
}
|
||||
if (result != S_OK)
|
||||
return result;
|
||||
|
||||
/*
|
||||
if (refItem.NumItems == 1 &&
|
||||
!item.IsSplitBefore() && !item.IsSplitAfter())
|
||||
*/
|
||||
{
|
||||
const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
|
||||
bool crcOK = outStreamSpec->GetCRC() == lastItem.FileCRC;
|
||||
int opRes = (volsInStreamSpec->CrcIsOK && outStreamSpec->GetCRC() == lastItem.FileCRC) ?
|
||||
NExtract::NOperationResult::kOK:
|
||||
NExtract::NOperationResult::kCRCError;
|
||||
outStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(crcOK ?
|
||||
NExtract::NOperationResult::kOK:
|
||||
NExtract::NOperationResult::kCRCError));
|
||||
}
|
||||
/*
|
||||
|
||||
if (result != S_OK)
|
||||
{
|
||||
if (result == S_FALSE)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
else if (result == E_NOTIMPL)
|
||||
opRes = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
else
|
||||
{
|
||||
bool crcOK = true;
|
||||
for (unsigned partIndex = 0; partIndex < refItem.NumItems; partIndex++)
|
||||
{
|
||||
const CItem &item = _items[refItem.ItemIndex + partIndex];
|
||||
if (item.FileCRC != folderInStreamSpec->CRCs[partIndex])
|
||||
{
|
||||
crcOK = false;
|
||||
break;
|
||||
return result;
|
||||
}
|
||||
RINOK(extractCallback->SetOperationResult(opRes));
|
||||
}
|
||||
RINOK(extractCallback->SetOperationResult(crcOK ?
|
||||
NExtract::NOperationResult::kOK:
|
||||
NExtract::NOperationResult::kCRCError));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
129
CPP/7zip/Archive/Rar/RarVol.h
Normal file
129
CPP/7zip/Archive/Rar/RarVol.h
Normal file
@@ -0,0 +1,129 @@
|
||||
// RarVol.h
|
||||
|
||||
#ifndef __ARCHIVE_RAR_VOL_H
|
||||
#define __ARCHIVE_RAR_VOL_H
|
||||
|
||||
#include "../../../Common/StringConvert.h"
|
||||
|
||||
#include "RarHeader.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NRar {
|
||||
|
||||
inline bool IsDigit(wchar_t c)
|
||||
{
|
||||
return c >= L'0' && c <= L'9';
|
||||
}
|
||||
|
||||
class CVolumeName
|
||||
{
|
||||
bool _first;
|
||||
bool _newStyle;
|
||||
UString _unchangedPart;
|
||||
UString _changedPart;
|
||||
UString _afterPart;
|
||||
public:
|
||||
CVolumeName(): _newStyle(true) {};
|
||||
|
||||
bool InitName(const UString &name, bool newStyle = true)
|
||||
{
|
||||
_first = true;
|
||||
_newStyle = newStyle;
|
||||
int dotPos = name.ReverseFind_Dot();
|
||||
UString basePart = name;
|
||||
|
||||
if (dotPos >= 0)
|
||||
{
|
||||
UString ext = name.Ptr(dotPos + 1);
|
||||
if (ext.IsEqualTo_Ascii_NoCase("rar"))
|
||||
{
|
||||
_afterPart = name.Ptr(dotPos);
|
||||
basePart = name.Left(dotPos);
|
||||
}
|
||||
else if (ext.IsEqualTo_Ascii_NoCase("exe"))
|
||||
{
|
||||
_afterPart.SetFromAscii(".rar");
|
||||
basePart = name.Left(dotPos);
|
||||
}
|
||||
else if (!_newStyle)
|
||||
{
|
||||
if (ext.IsEqualTo_Ascii_NoCase("000") ||
|
||||
ext.IsEqualTo_Ascii_NoCase("001") ||
|
||||
ext.IsEqualTo_Ascii_NoCase("r00") ||
|
||||
ext.IsEqualTo_Ascii_NoCase("r01"))
|
||||
{
|
||||
_afterPart.Empty();
|
||||
_first = false;
|
||||
_changedPart = ext;
|
||||
_unchangedPart = name.Left(dotPos + 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_newStyle)
|
||||
{
|
||||
_afterPart.Empty();
|
||||
_unchangedPart = basePart;
|
||||
_unchangedPart += L'.';
|
||||
_changedPart.SetFromAscii("r00");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (basePart.IsEmpty())
|
||||
return false;
|
||||
unsigned i = basePart.Len();
|
||||
|
||||
do
|
||||
if (!IsDigit(basePart[i - 1]))
|
||||
break;
|
||||
while (--i);
|
||||
|
||||
_unchangedPart = basePart.Left(i);
|
||||
_changedPart = basePart.Ptr(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
void MakeBeforeFirstName()
|
||||
{
|
||||
unsigned len = _changedPart.Len();
|
||||
_changedPart.Empty();
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
_changedPart += L'0';
|
||||
}
|
||||
*/
|
||||
|
||||
UString GetNextName()
|
||||
{
|
||||
if (_newStyle || !_first)
|
||||
{
|
||||
unsigned i = _changedPart.Len();
|
||||
for (;;)
|
||||
{
|
||||
wchar_t c = _changedPart[--i];
|
||||
if (c == L'9')
|
||||
{
|
||||
c = L'0';
|
||||
_changedPart.ReplaceOneCharAtPos(i, c);
|
||||
if (i == 0)
|
||||
{
|
||||
_changedPart.InsertAtFront(L'1');
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
c++;
|
||||
_changedPart.ReplaceOneCharAtPos(i, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_first = false;
|
||||
return _unchangedPart + _changedPart + _afterPart;
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -29,11 +29,13 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(callback->GetProperty(index, propId, &prop));
|
||||
|
||||
if (prop.vt == VT_BSTR)
|
||||
{
|
||||
UString s = prop.bstrVal;
|
||||
if (convertSlash)
|
||||
s = NItemName::MakeLegalName(s);
|
||||
|
||||
if (codePage == CP_UTF8)
|
||||
{
|
||||
ConvertUnicodeToUTF8(s, res);
|
||||
@@ -44,9 +46,11 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro
|
||||
}
|
||||
else if (prop.vt != VT_EMPTY)
|
||||
return E_INVALIDARG;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
// sort old files with original order.
|
||||
|
||||
static int CompareUpdateItems(void *const *p1, void *const *p2, void *)
|
||||
@@ -57,33 +61,39 @@ static int CompareUpdateItems(void *const *p1, void *const *p2, void *)
|
||||
{
|
||||
if (u2.NewProps)
|
||||
return -1;
|
||||
return MyCompare(u1.IndexInArchive, u2.IndexInArchive);
|
||||
return MyCompare(u1.IndexInArc, u2.IndexInArc);
|
||||
}
|
||||
if (!u2.NewProps)
|
||||
return 1;
|
||||
return MyCompare(u1.IndexInClient, u2.IndexInClient);
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
|
||||
IArchiveUpdateCallback *callback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
if ((_stream && (_error != k_ErrorType_OK /* || _isSparse */)) || _seqStream)
|
||||
return E_NOTIMPL;
|
||||
CObjectVector<CUpdateItem> updateItems;
|
||||
UINT codePage = (_forceCodePage ? _specifiedCodePage : _openCodePage);
|
||||
|
||||
for (UInt32 i = 0; i < numItems; i++)
|
||||
{
|
||||
CUpdateItem ui;
|
||||
Int32 newData;
|
||||
Int32 newProps;
|
||||
UInt32 indexInArchive;
|
||||
UInt32 indexInArc;
|
||||
|
||||
if (!callback)
|
||||
return E_FAIL;
|
||||
RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
|
||||
|
||||
RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArc));
|
||||
|
||||
ui.NewProps = IntToBool(newProps);
|
||||
ui.NewData = IntToBool(newData);
|
||||
ui.IndexInArchive = indexInArchive;
|
||||
ui.IndexInArc = indexInArc;
|
||||
ui.IndexInClient = i;
|
||||
|
||||
if (IntToBool(newProps))
|
||||
@@ -109,6 +119,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
else
|
||||
ui.Mode = prop.ulVal;
|
||||
}
|
||||
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(callback->GetProperty(i, kpidMTime, &prop));
|
||||
@@ -119,6 +130,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
else
|
||||
ui.MTime = NTime::FileTimeToUnixTime64(prop.filetime);
|
||||
}
|
||||
|
||||
RINOK(GetPropString(callback, i, kpidPath, ui.Name, codePage, true));
|
||||
if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/')
|
||||
ui.Name += '/';
|
||||
@@ -139,14 +151,18 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
return E_INVALIDARG;
|
||||
*/
|
||||
}
|
||||
|
||||
updateItems.Add(ui);
|
||||
}
|
||||
|
||||
if (_thereIsPaxExtendedHeader)
|
||||
{
|
||||
// we restore original order of files, if there is pax header block
|
||||
updateItems.Sort(CompareUpdateItems, NULL);
|
||||
}
|
||||
|
||||
return UpdateArchive(_stream, outStream, _items, updateItems, codePage, callback);
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
if (ui.NewData)
|
||||
complexity += ui.Size;
|
||||
else
|
||||
complexity += inputItems[ui.IndexInArchive].GetFullSize();
|
||||
complexity += inputItems[ui.IndexInArc].GetFullSize();
|
||||
}
|
||||
|
||||
RINOK(updateCallback->SetTotal(complexity));
|
||||
@@ -68,12 +68,14 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
|
||||
const CUpdateItem &ui = updateItems[i];
|
||||
CItem item;
|
||||
|
||||
if (ui.NewProps)
|
||||
{
|
||||
item.Mode = ui.Mode;
|
||||
item.Name = ui.Name;
|
||||
item.User = ui.User;
|
||||
item.Group = ui.Group;
|
||||
|
||||
if (ui.IsDir)
|
||||
{
|
||||
item.LinkFlag = NFileHeader::NLinkFlag::kDirectory;
|
||||
@@ -84,6 +86,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
item.LinkFlag = NFileHeader::NLinkFlag::kNormal;
|
||||
item.PackSize = ui.Size;
|
||||
}
|
||||
|
||||
item.MTime = ui.MTime;
|
||||
item.DeviceMajorDefined = false;
|
||||
item.DeviceMinorDefined = false;
|
||||
@@ -92,7 +95,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
memcpy(item.Magic, NFileHeader::NMagic::kUsTar_00, 8);
|
||||
}
|
||||
else
|
||||
item = inputItems[ui.IndexInArchive];
|
||||
item = inputItems[ui.IndexInArc];
|
||||
|
||||
AString symLink;
|
||||
if (ui.NewData || ui.NewProps)
|
||||
@@ -116,6 +119,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
CMyComPtr<ISequentialInStream> fileInStream;
|
||||
|
||||
bool needWrite = true;
|
||||
|
||||
if (!symLink.IsEmpty())
|
||||
{
|
||||
item.PackSize = 0;
|
||||
@@ -124,6 +128,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
else
|
||||
{
|
||||
HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream);
|
||||
|
||||
if (res == S_FALSE)
|
||||
needWrite = false;
|
||||
else
|
||||
@@ -141,10 +146,17 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
if (getProps->GetProps(&size2, NULL, NULL, &mTime, NULL) == S_OK)
|
||||
{
|
||||
item.PackSize = size2;
|
||||
item.Size = size2;
|
||||
item.MTime = NWindows::NTime::FileTimeToUnixTime64(mTime);;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item.PackSize = 0;
|
||||
item.Size = 0;
|
||||
}
|
||||
|
||||
{
|
||||
AString hardLink;
|
||||
RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidHardLink, hardLink, codePage, true));
|
||||
@@ -183,13 +195,15 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
RINOK(outArchive.FillDataResidual(item.PackSize));
|
||||
}
|
||||
}
|
||||
|
||||
complexity += item.PackSize;
|
||||
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
}
|
||||
else
|
||||
{
|
||||
const CItemEx &existItem = inputItems[ui.IndexInArchive];
|
||||
const CItemEx &existItem = inputItems[ui.IndexInArc];
|
||||
UInt64 size;
|
||||
|
||||
if (ui.NewProps)
|
||||
{
|
||||
// memcpy(item.Magic, NFileHeader::NMagic::kEmpty, 8);
|
||||
@@ -225,12 +239,13 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
RINOK(inStream->Seek(existItem.HeaderPos, STREAM_SEEK_SET, NULL));
|
||||
size = existItem.GetFullSize();
|
||||
}
|
||||
|
||||
streamSpec->Init(size);
|
||||
|
||||
if (opCallback)
|
||||
{
|
||||
RINOK(opCallback->ReportOperation(
|
||||
NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArchive,
|
||||
NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArc,
|
||||
NUpdateNotifyOp::kReplicate))
|
||||
}
|
||||
|
||||
@@ -242,6 +257,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
complexity += size;
|
||||
}
|
||||
}
|
||||
|
||||
lps->InSize = lps->OutSize = complexity;
|
||||
RINOK(lps->SetCur());
|
||||
return outArchive.WriteFinishHeader();
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#define __TAR_UPDATE_H
|
||||
|
||||
#include "../IArchive.h"
|
||||
|
||||
#include "TarItem.h"
|
||||
|
||||
namespace NArchive {
|
||||
@@ -11,10 +12,10 @@ namespace NTar {
|
||||
|
||||
struct CUpdateItem
|
||||
{
|
||||
int IndexInArchive;
|
||||
int IndexInArc;
|
||||
int IndexInClient;
|
||||
Int64 MTime;
|
||||
UInt64 Size;
|
||||
Int64 MTime;
|
||||
UInt32 Mode;
|
||||
bool NewData;
|
||||
bool NewProps;
|
||||
@@ -22,6 +23,8 @@ struct CUpdateItem
|
||||
AString Name;
|
||||
AString User;
|
||||
AString Group;
|
||||
|
||||
CUpdateItem(): Size(0), IsDir(false) {}
|
||||
};
|
||||
|
||||
HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
|
||||
@@ -358,15 +358,24 @@ HRESULT CHandler::Open2(IInStream *stream)
|
||||
return S_FALSE;
|
||||
|
||||
UInt64 totalPackSize = 0;
|
||||
unsigned numMainFiles = 0;
|
||||
|
||||
FOR_VECTOR(i, _files)
|
||||
{
|
||||
const CFile &file = _files[i];
|
||||
file.UpdateTotalPackSize(totalPackSize);
|
||||
if (file.Name == "Payload")
|
||||
{
|
||||
_mainSubfile = i;
|
||||
numMainFiles++;
|
||||
}
|
||||
if (file.Name == "PackageInfo")
|
||||
_is_pkg = true;
|
||||
}
|
||||
|
||||
if (numMainFiles > 1)
|
||||
_mainSubfile = -1;
|
||||
|
||||
_phySize = _dataStartPos + totalPackSize;
|
||||
|
||||
return S_OK;
|
||||
|
||||
@@ -207,7 +207,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
}
|
||||
if (IntToBool(newData))
|
||||
{
|
||||
UInt64 size;
|
||||
UInt64 size = 0;
|
||||
if (!ui.IsDir)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(callback->GetProperty(i, kpidSize, &prop));
|
||||
@@ -219,6 +220,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
largestSizeDefined = true;
|
||||
}
|
||||
ui.Size = size;
|
||||
|
||||
// ui.Size -= ui.Size / 2;
|
||||
}
|
||||
updateItems.Add(ui);
|
||||
|
||||
@@ -591,6 +591,29 @@ static bool FlagsAreSame(const CItem &i1, const CItem &i2)
|
||||
return ((i1.Flags & mask) == (i2.Flags & mask));
|
||||
}
|
||||
|
||||
// #ifdef _WIN32
|
||||
static bool AreEqualPaths_IgnoreSlashes(const char *s1, const char *s2)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
char c1 = *s1++;
|
||||
char c2 = *s2++;
|
||||
if (c1 == c2)
|
||||
{
|
||||
if (c1 == 0)
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c1 == '\\') c1 = '/';
|
||||
if (c2 == '\\') c2 = '/';
|
||||
if (c1 != c2)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
|
||||
static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem)
|
||||
{
|
||||
if (!FlagsAreSame(cdItem, localItem))
|
||||
@@ -611,7 +634,30 @@ static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem)
|
||||
return false;
|
||||
*/
|
||||
if (cdItem.Name != localItem.Name)
|
||||
{
|
||||
// #ifdef _WIN32
|
||||
// some xap files use backslash in central dir items.
|
||||
// we can ignore such errors in windows, where all slashes are converted to backslashes
|
||||
unsigned hostOs = cdItem.GetHostOS();
|
||||
|
||||
if (hostOs == NFileHeader::NHostOS::kFAT ||
|
||||
hostOs == NFileHeader::NHostOS::kNTFS)
|
||||
{
|
||||
if (!AreEqualPaths_IgnoreSlashes(cdItem.Name, localItem.Name))
|
||||
{
|
||||
// pkzip 2.50 uses DOS encoding in central dir and WIN encoding in local header.
|
||||
// so we ignore that error
|
||||
if (hostOs != NFileHeader::NHostOS::kFAT
|
||||
|| cdItem.MadeByVersion.Version != 25)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*
|
||||
else
|
||||
#endif
|
||||
return false;
|
||||
*/
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,8 @@ static void SetFileHeader(
|
||||
item.ExtractVersion.Version = NFileHeader::NCompressionMethod::kExtractVersion_Dir;
|
||||
item.Method = kMethodForDirectory;
|
||||
item.PackSize = 0;
|
||||
item.Crc = 0; // test it
|
||||
item.Size = 0;
|
||||
item.Crc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -332,14 +332,6 @@ SOURCE=..\..\Archive\7z\7zUpdate.h
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Archive\Common\CoderMixer.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Archive\Common\CoderMixer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Archive\Common\CoderMixer2.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
@@ -141,6 +141,7 @@ NSIS_OBJS = \
|
||||
|
||||
RAR_OBJS = \
|
||||
$O\RarHandler.obj \
|
||||
$O\Rar5Handler.obj \
|
||||
|
||||
TAR_OBJS = \
|
||||
$O\TarHandler.obj \
|
||||
@@ -212,6 +213,7 @@ COMPRESS_OBJS = \
|
||||
$O\Rar2Decoder.obj \
|
||||
$O\Rar3Decoder.obj \
|
||||
$O\Rar3Vm.obj \
|
||||
$O\Rar5Decoder.obj \
|
||||
$O\RarCodecsRegister.obj \
|
||||
$O\ShrinkDecoder.obj \
|
||||
$O\ZlibDecoder.obj \
|
||||
@@ -222,11 +224,13 @@ CRYPTO_OBJS = \
|
||||
$O\7zAes.obj \
|
||||
$O\7zAesRegister.obj \
|
||||
$O\HmacSha1.obj \
|
||||
$O\HmacSha256.obj \
|
||||
$O\MyAes.obj \
|
||||
$O\MyAesReg.obj \
|
||||
$O\Pbkdf2HmacSha1.obj \
|
||||
$O\RandGen.obj \
|
||||
$O\Rar20Crypto.obj \
|
||||
$O\Rar5Aes.obj \
|
||||
$O\RarAes.obj \
|
||||
$O\WzAes.obj \
|
||||
$O\ZipCrypto.obj \
|
||||
@@ -239,6 +243,7 @@ C_OBJS = \
|
||||
$O\Alloc.obj \
|
||||
$O\Bcj2.obj \
|
||||
$O\Bcj2Enc.obj \
|
||||
$O\Blake2s.obj \
|
||||
$O\Bra.obj \
|
||||
$O\Bra86.obj \
|
||||
$O\BraIA64.obj \
|
||||
|
||||
@@ -243,6 +243,10 @@ SOURCE=..\..\..\Common\CrcReg.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\Defs.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\DynamicBuffer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -452,6 +456,24 @@ SOURCE=..\..\Compress\Rar3Vm.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Rar5Decoder.cpp
|
||||
|
||||
!IF "$(CFG)" == "7z - Win32 Release"
|
||||
|
||||
# ADD CPP /O2
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Rar5Decoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\RarCodecsRegister.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
@@ -821,6 +843,14 @@ SOURCE=..\..\Crypto\HmacSha1.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\HmacSha256.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\HmacSha256.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\MyAes.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -887,6 +917,14 @@ SOURCE=..\..\Crypto\Rar20Crypto.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\Rar5Aes.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\Rar5Aes.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Crypto\RarAes.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -1319,6 +1357,26 @@ SOURCE=..\..\..\..\C\Bcj2Enc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Blake2.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Blake2s.c
|
||||
|
||||
!IF "$(CFG)" == "7z - Win32 Release"
|
||||
|
||||
# ADD CPP /O2
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
|
||||
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Bra.c
|
||||
|
||||
!IF "$(CFG)" == "7z - Win32 Release"
|
||||
@@ -1874,6 +1932,14 @@ SOURCE=..\..\Archive\7z\7zUpdateItem.h
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Archive\Rar\Rar5Handler.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Archive\Rar\Rar5Handler.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Archive\Rar\RarHandler.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -1888,6 +1954,10 @@ SOURCE=..\..\Archive\Rar\RarHeader.h
|
||||
|
||||
SOURCE=..\..\Archive\Rar\RarItem.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Archive\Rar\RarVol.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Cab"
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#define MY_SET_BINARY_MODE(file)
|
||||
#endif
|
||||
|
||||
// #include "../../../Common/MyWindows.h"
|
||||
#include "../../../Common/MyWindows.h"
|
||||
#include "../../../Common/MyInitGuid.h"
|
||||
|
||||
#include "../../../../C/7zVersion.h"
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
|
||||
#include "../../../Common/MyInitGuid.h"
|
||||
|
||||
#include "../../../Common/CommandLineParser.h"
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
|
||||
#include "../../../Common/MyInitGuid.h"
|
||||
|
||||
#include "../../../Common/CommandLineParser.h"
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
|
||||
#include <Shlwapi.h>
|
||||
|
||||
#include "../../../Common/MyInitGuid.h"
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
struct CAlignedMidBuffer
|
||||
{
|
||||
#ifndef _WIN32
|
||||
#ifdef _WIN32
|
||||
|
||||
Byte *_buf;
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "LimitedStreams.h"
|
||||
#include "../../Common/Defs.h"
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/MyWindows.h"
|
||||
|
||||
#include "../PropID.h"
|
||||
|
||||
// VARTYPE
|
||||
@@ -101,5 +103,6 @@ const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] =
|
||||
VT_UI8,
|
||||
VT_UI8,
|
||||
VT_BOOL,
|
||||
VT_BSTR // kpidOutName
|
||||
VT_BSTR,
|
||||
VT_BSTR
|
||||
};
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "UniqBlocks.h"
|
||||
|
||||
unsigned CUniqBlocks::AddUniq(const Byte *data, size_t size)
|
||||
|
||||
@@ -2,3 +2,5 @@ EXPORTS
|
||||
CreateObject PRIVATE
|
||||
GetNumberOfMethods PRIVATE
|
||||
GetMethodProperty PRIVATE
|
||||
CreateDecoder PRIVATE
|
||||
CreateEncoder PRIVATE
|
||||
|
||||
@@ -130,14 +130,14 @@ CCoder::CCoder(bool deflate64Mode):
|
||||
m_Values(0),
|
||||
m_Tables(0)
|
||||
{
|
||||
{
|
||||
CEncProps props;
|
||||
SetProps(&props);
|
||||
}
|
||||
m_MatchMaxLen = deflate64Mode ? kMatchMaxLen64 : kMatchMaxLen32;
|
||||
m_NumLenCombinations = deflate64Mode ? kNumLenSymbols64 : kNumLenSymbols32;
|
||||
m_LenStart = deflate64Mode ? kLenStart64 : kLenStart32;
|
||||
m_LenDirectBits = deflate64Mode ? kLenDirectBits64 : kLenDirectBits32;
|
||||
{
|
||||
CEncProps props;
|
||||
SetProps(&props);
|
||||
}
|
||||
MatchFinder_Construct(&_lzInWindow);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,11 +22,13 @@ public:
|
||||
|
||||
bool SetCodeLengths(const Byte *lens)
|
||||
{
|
||||
unsigned lenCounts[kNumBitsMax + 1];
|
||||
UInt32 lenCounts[kNumBitsMax + 1];
|
||||
UInt32 tmpPositions[kNumBitsMax + 1];
|
||||
|
||||
unsigned i;
|
||||
for (i = 1; i <= kNumBitsMax; i++)
|
||||
lenCounts[i] = 0;
|
||||
|
||||
UInt32 symbol;
|
||||
|
||||
for (symbol = 0; symbol < m_NumSymbols; symbol++)
|
||||
@@ -42,7 +44,7 @@ public:
|
||||
m_Positions[0] = m_Limits[0] = 0;
|
||||
UInt32 startPos = 0;
|
||||
UInt32 index = 0;
|
||||
const UInt32 kMaxValue = (1 << kNumBitsMax);
|
||||
const UInt32 kMaxValue = (UInt32)1 << kNumBitsMax;
|
||||
|
||||
for (i = 1; i <= kNumBitsMax; i++)
|
||||
{
|
||||
@@ -74,14 +76,15 @@ public:
|
||||
UInt32 DecodeSymbol(TBitDecoder *bitStream)
|
||||
{
|
||||
unsigned numBits;
|
||||
UInt32 value = bitStream->GetValue(kNumBitsMax);
|
||||
if (value < m_Limits[kNumTableBits])
|
||||
numBits = m_Lengths[value >> (kNumBitsMax - kNumTableBits)];
|
||||
UInt32 val = bitStream->GetValue(kNumBitsMax);
|
||||
|
||||
if (val < m_Limits[kNumTableBits])
|
||||
numBits = m_Lengths[val >> (kNumBitsMax - kNumTableBits)];
|
||||
else
|
||||
for (numBits = kNumTableBits + 1; value >= m_Limits[numBits]; numBits++);
|
||||
for (numBits = kNumTableBits + 1; val >= m_Limits[numBits]; numBits++);
|
||||
|
||||
bitStream->MovePos(numBits);
|
||||
UInt32 index = m_Positions[numBits] +
|
||||
((value - m_Limits[numBits - 1]) >> (kNumBitsMax - numBits));
|
||||
UInt32 index = m_Positions[numBits] + ((val - m_Limits[numBits - 1]) >> (kNumBitsMax - numBits));
|
||||
if (index >= m_NumSymbols)
|
||||
// throw CDecoderException(); // test it
|
||||
return 0xFFFFFFFF;
|
||||
|
||||
@@ -486,7 +486,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
||||
{
|
||||
if (size < 1)
|
||||
return E_INVALIDARG;
|
||||
m_IsSolid = (data[0] != 0);
|
||||
m_IsSolid = ((data[0] & 1) != 0);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -394,7 +394,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
||||
{
|
||||
if (size < 1)
|
||||
return E_INVALIDARG;
|
||||
m_IsSolid = (data[0] != 0);
|
||||
m_IsSolid = ((data[0] & 1) != 0);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -140,6 +140,8 @@ void CDecoder::ExecuteFilter(int tempFilterIndex, NVm::CBlockRef &outBlockRef)
|
||||
NVm::SetValue32(&tempFilter->GlobalData[0x24], (UInt32)_writtenFileSize);
|
||||
NVm::SetValue32(&tempFilter->GlobalData[0x28], (UInt32)(_writtenFileSize >> 32));
|
||||
CFilter *filter = _filters[tempFilter->FilterIndex];
|
||||
if (!filter->IsSupported)
|
||||
_unsupportedFilter = true;
|
||||
_vm.Execute(filter, tempFilter, outBlockRef, filter->GlobalData);
|
||||
delete tempFilter;
|
||||
_tempFilters[tempFilterIndex] = 0;
|
||||
@@ -226,12 +228,15 @@ void CDecoder::InitFilters()
|
||||
_filters.Clear();
|
||||
}
|
||||
|
||||
static const unsigned MAX_UNPACK_FILTERS = 8192;
|
||||
|
||||
bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
|
||||
{
|
||||
CMemBitDecoder inp;
|
||||
inp.Init(_vmData, codeSize);
|
||||
|
||||
UInt32 filterIndex;
|
||||
|
||||
if (firstByte & 0x80)
|
||||
{
|
||||
filterIndex = inp.ReadEncodedUInt32();
|
||||
@@ -242,6 +247,7 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
|
||||
}
|
||||
else
|
||||
filterIndex = _lastFilter;
|
||||
|
||||
if (filterIndex > (UInt32)_filters.Size())
|
||||
return false;
|
||||
_lastFilter = filterIndex;
|
||||
@@ -251,7 +257,7 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
|
||||
if (newFilter)
|
||||
{
|
||||
// check if too many filters
|
||||
if (filterIndex > 1024)
|
||||
if (filterIndex > MAX_UNPACK_FILTERS)
|
||||
return false;
|
||||
filter = new CFilter;
|
||||
_filters.Add(filter);
|
||||
@@ -301,6 +307,8 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
|
||||
if (initMask & (1 << i))
|
||||
tempFilter->InitR[i] = inp.ReadEncodedUInt32();
|
||||
}
|
||||
|
||||
bool isOK = true;
|
||||
if (newFilter)
|
||||
{
|
||||
UInt32 vmCodeSize = inp.ReadEncodedUInt32();
|
||||
@@ -308,7 +316,7 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
|
||||
return false;
|
||||
for (UInt32 i = 0; i < vmCodeSize; i++)
|
||||
_vmCode[i] = (Byte)inp.ReadBits(8);
|
||||
filter->PrepareProgram(_vmCode, vmCodeSize);
|
||||
isOK = filter->PrepareProgram(_vmCode, vmCodeSize);
|
||||
}
|
||||
|
||||
Byte *globalData = &tempFilter->GlobalData[0];
|
||||
@@ -331,7 +339,8 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
|
||||
for (UInt32 i = 0; i < dataSize; i++)
|
||||
dest[i] = (Byte)inp.ReadBits(8);
|
||||
}
|
||||
return true;
|
||||
|
||||
return isOK;
|
||||
}
|
||||
|
||||
bool CDecoder::ReadVmCodeLZ()
|
||||
@@ -796,6 +805,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
|
||||
HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
|
||||
{
|
||||
_writtenFileSize = 0;
|
||||
_unsupportedFilter = false;
|
||||
if (!m_IsSolid)
|
||||
{
|
||||
_lzSize = 0;
|
||||
@@ -843,6 +853,10 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
|
||||
RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize));
|
||||
if (_writtenFileSize < _unpackSize)
|
||||
return S_FALSE;
|
||||
|
||||
if (_unsupportedFilter)
|
||||
return E_NOTIMPL;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -892,7 +906,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
||||
{
|
||||
if (size < 1)
|
||||
return E_INVALIDARG;
|
||||
m_IsSolid = (data[0] != 0);
|
||||
m_IsSolid = ((data[0] & 1) != 0);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -194,6 +194,7 @@ class CDecoder:
|
||||
bool m_IsSolid;
|
||||
|
||||
bool _lzMode;
|
||||
bool _unsupportedFilter;
|
||||
|
||||
UInt32 PrevAlignBits;
|
||||
UInt32 PrevAlignCount;
|
||||
|
||||
@@ -12,6 +12,8 @@ Note:
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../../../C/7zCrc.h"
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
@@ -55,6 +57,8 @@ namespace NVm {
|
||||
|
||||
static const UInt32 kStackRegIndex = kNumRegs - 1;
|
||||
|
||||
#ifdef RARVM_VM_ENABLE
|
||||
|
||||
static const UInt32 FLAG_C = 1;
|
||||
static const UInt32 FLAG_Z = 2;
|
||||
static const UInt32 FLAG_S = 0x80000000;
|
||||
@@ -113,11 +117,14 @@ static const Byte kCmdFlags[]=
|
||||
/* CMD_PRINT */ CF_OP0
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
CVm::CVm(): Mem(NULL) {}
|
||||
|
||||
bool CVm::Create()
|
||||
{
|
||||
if (Mem == NULL)
|
||||
if (!Mem)
|
||||
Mem = (Byte *)::MyAlloc(kSpaceSize + 4);
|
||||
return (Mem != NULL);
|
||||
}
|
||||
@@ -145,12 +152,14 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,
|
||||
memcpy(Mem + kGlobalOffset + globalSize, &prg->StaticData[0], staticSize);
|
||||
|
||||
bool res = true;
|
||||
|
||||
#ifdef RARVM_STANDARD_FILTERS
|
||||
if (prg->StandardFilterIndex >= 0)
|
||||
ExecuteStandardFilter(prg->StandardFilterIndex);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifdef RARVM_VM_ENABLE
|
||||
res = ExecuteCode(prg);
|
||||
if (!res)
|
||||
{
|
||||
@@ -158,7 +167,11 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,
|
||||
prg->Commands.Add(CCommand());
|
||||
prg->Commands.Back().OpCode = CMD_RET;
|
||||
}
|
||||
#else
|
||||
res = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
UInt32 newBlockPos = GetFixedGlobalValue32(NGlobalOffset::kBlockPos) & kSpaceMask;
|
||||
UInt32 newBlockSize = GetFixedGlobalValue32(NGlobalOffset::kBlockSize) & kSpaceMask;
|
||||
if (newBlockPos + newBlockSize >= kSpaceSize)
|
||||
@@ -175,9 +188,11 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,
|
||||
outGlobalData.ClearAndSetSize(dataSize);
|
||||
memcpy(&outGlobalData[0], Mem + kGlobalOffset, dataSize);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef RARVM_VM_ENABLE
|
||||
|
||||
#define SET_IP(IP) \
|
||||
if ((IP) >= numCommands) return true; \
|
||||
@@ -191,7 +206,7 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,
|
||||
|
||||
UInt32 CVm::GetOperand32(const COperand *op) const
|
||||
{
|
||||
switch(op->Type)
|
||||
switch (op->Type)
|
||||
{
|
||||
case OP_TYPE_REG: return R[op->Data];
|
||||
case OP_TYPE_REGMEM: return GetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask]);
|
||||
@@ -201,7 +216,7 @@ UInt32 CVm::GetOperand32(const COperand *op) const
|
||||
|
||||
void CVm::SetOperand32(const COperand *op, UInt32 val)
|
||||
{
|
||||
switch(op->Type)
|
||||
switch (op->Type)
|
||||
{
|
||||
case OP_TYPE_REG: R[op->Data] = val; return;
|
||||
case OP_TYPE_REGMEM: SetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask], val); return;
|
||||
@@ -210,7 +225,7 @@ void CVm::SetOperand32(const COperand *op, UInt32 val)
|
||||
|
||||
Byte CVm::GetOperand8(const COperand *op) const
|
||||
{
|
||||
switch(op->Type)
|
||||
switch (op->Type)
|
||||
{
|
||||
case OP_TYPE_REG: return (Byte)R[op->Data];
|
||||
case OP_TYPE_REGMEM: return Mem[(op->Base + R[op->Data]) & kSpaceMask];;
|
||||
@@ -220,7 +235,7 @@ Byte CVm::GetOperand8(const COperand *op) const
|
||||
|
||||
void CVm::SetOperand8(const COperand *op, Byte val)
|
||||
{
|
||||
switch(op->Type)
|
||||
switch (op->Type)
|
||||
{
|
||||
case OP_TYPE_REG: R[op->Data] = (R[op->Data] & 0xFFFFFF00) | val; return;
|
||||
case OP_TYPE_REGMEM: Mem[(op->Base + R[op->Data]) & kSpaceMask] = val; return;
|
||||
@@ -253,10 +268,8 @@ bool CVm::ExecuteCode(const CProgram *prg)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
switch(cmd->OpCode)
|
||||
switch (cmd->OpCode)
|
||||
{
|
||||
#ifndef RARVM_NO_VM
|
||||
|
||||
case CMD_MOV:
|
||||
SetOperand32(&cmd->Op1, GetOperand32(&cmd->Op2));
|
||||
break;
|
||||
@@ -619,8 +632,6 @@ bool CVm::ExecuteCode(const CProgram *prg)
|
||||
}
|
||||
break;
|
||||
|
||||
#endif
|
||||
|
||||
case CMD_RET:
|
||||
{
|
||||
if (R[kStackRegIndex] >= kSpaceSize)
|
||||
@@ -638,7 +649,6 @@ bool CVm::ExecuteCode(const CProgram *prg)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Read program
|
||||
|
||||
@@ -682,25 +692,31 @@ void CProgram::ReadProgram(const Byte *code, UInt32 codeSize)
|
||||
inp.Init(code, codeSize);
|
||||
|
||||
StaticData.Clear();
|
||||
|
||||
if (inp.ReadBit())
|
||||
{
|
||||
UInt32 dataSize = inp.ReadEncodedUInt32() + 1;
|
||||
for (UInt32 i = 0; inp.Avail() && i < dataSize; i++)
|
||||
StaticData.Add((Byte)inp.ReadBits(8));
|
||||
}
|
||||
|
||||
while (inp.Avail())
|
||||
{
|
||||
Commands.Add(CCommand());
|
||||
CCommand *cmd = &Commands.Back();
|
||||
|
||||
if (inp.ReadBit() == 0)
|
||||
cmd->OpCode = (ECommand)inp.ReadBits(3);
|
||||
else
|
||||
cmd->OpCode = (ECommand)(8 + inp.ReadBits(5));
|
||||
|
||||
if (kCmdFlags[(unsigned)cmd->OpCode] & CF_BYTEMODE)
|
||||
cmd->ByteMode = (inp.ReadBit()) ? true : false;
|
||||
else
|
||||
cmd->ByteMode = 0;
|
||||
|
||||
int opNum = (kCmdFlags[(unsigned)cmd->OpCode] & CF_OPMASK);
|
||||
|
||||
if (opNum > 0)
|
||||
{
|
||||
DecodeArg(inp, cmd->Op1, cmd->ByteMode);
|
||||
@@ -727,6 +743,7 @@ void CProgram::ReadProgram(const Byte *code, UInt32 codeSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd->ByteMode)
|
||||
{
|
||||
switch (cmd->OpCode)
|
||||
@@ -751,6 +768,9 @@ void CProgram::ReadProgram(const Byte *code, UInt32 codeSize)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef RARVM_STANDARD_FILTERS
|
||||
|
||||
enum EStandardFilter
|
||||
@@ -760,8 +780,8 @@ enum EStandardFilter
|
||||
SF_ITANIUM,
|
||||
SF_RGB,
|
||||
SF_AUDIO,
|
||||
SF_DELTA,
|
||||
SF_UPCASE
|
||||
SF_DELTA
|
||||
// SF_UPCASE
|
||||
};
|
||||
|
||||
static const struct CStandardFilterSignature
|
||||
@@ -777,8 +797,8 @@ kStdFilters[]=
|
||||
{ 120, 0x3769893f, SF_ITANIUM },
|
||||
{ 29, 0x0e06077d, SF_DELTA },
|
||||
{ 149, 0x1c2c5dc8, SF_RGB },
|
||||
{ 216, 0xbc85e701, SF_AUDIO },
|
||||
{ 40, 0x46b9c560, SF_UPCASE }
|
||||
{ 216, 0xbc85e701, SF_AUDIO }
|
||||
// { 40, 0x46b9c560, SF_UPCASE }
|
||||
};
|
||||
|
||||
static int FindStandardFilter(const Byte *code, UInt32 codeSize)
|
||||
@@ -795,28 +815,48 @@ static int FindStandardFilter(const Byte *code, UInt32 codeSize)
|
||||
|
||||
#endif
|
||||
|
||||
void CProgram::PrepareProgram(const Byte *code, UInt32 codeSize)
|
||||
{
|
||||
Byte xorSum = 0;
|
||||
for (UInt32 i = 1; i < codeSize; i++)
|
||||
xorSum ^= code[i];
|
||||
|
||||
bool CProgram::PrepareProgram(const Byte *code, UInt32 codeSize)
|
||||
{
|
||||
IsSupported = false;
|
||||
|
||||
#ifdef RARVM_VM_ENABLE
|
||||
Commands.Clear();
|
||||
#endif
|
||||
|
||||
#ifdef RARVM_STANDARD_FILTERS
|
||||
StandardFilterIndex = -1;
|
||||
#endif
|
||||
|
||||
if (xorSum == code[0] && codeSize > 0)
|
||||
bool isOK = false;
|
||||
|
||||
Byte xorSum = 0;
|
||||
for (UInt32 i = 0; i < codeSize; i++)
|
||||
xorSum ^= code[i];
|
||||
|
||||
if (xorSum == 0 && codeSize != 0)
|
||||
{
|
||||
IsSupported = true;
|
||||
isOK = true;
|
||||
#ifdef RARVM_STANDARD_FILTERS
|
||||
StandardFilterIndex = FindStandardFilter(code, codeSize);
|
||||
if (StandardFilterIndex >= 0)
|
||||
return;
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#ifdef RARVM_VM_ENABLE
|
||||
ReadProgram(code + 1, codeSize - 1);
|
||||
#else
|
||||
IsSupported = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef RARVM_VM_ENABLE
|
||||
Commands.Add(CCommand());
|
||||
Commands.Back().OpCode = CMD_RET;
|
||||
#endif
|
||||
|
||||
return isOK;
|
||||
}
|
||||
|
||||
void CVm::SetMemory(UInt32 pos, const Byte *data, UInt32 dataSize)
|
||||
@@ -833,12 +873,11 @@ static void E8E9Decode(Byte *data, UInt32 dataSize, UInt32 fileOffset, bool e9)
|
||||
return;
|
||||
dataSize -= 4;
|
||||
const UInt32 kFileSize = 0x1000000;
|
||||
Byte cmpByte2 = (Byte)(e9 ? 0xE9 : 0xE8);
|
||||
Byte cmpMask = (Byte)(e9 ? 0xFE : 0xFF);
|
||||
for (UInt32 curPos = 0; curPos < dataSize;)
|
||||
{
|
||||
Byte curByte = *(data++);
|
||||
curPos++;
|
||||
if (curByte == 0xE8 || curByte == cmpByte2)
|
||||
if (((*data++) & cmpMask) == 0xE8)
|
||||
{
|
||||
UInt32 offset = curPos + fileOffset;
|
||||
UInt32 addr = (Int32)GetValue32(data);
|
||||
@@ -852,9 +891,9 @@ static void E8E9Decode(Byte *data, UInt32 dataSize, UInt32 fileOffset, bool e9)
|
||||
}
|
||||
}
|
||||
|
||||
static inline UInt32 ItaniumGetOpType(const Byte *data, int bitPos)
|
||||
static inline UInt32 ItaniumGetOpType(const Byte *data, unsigned bitPos)
|
||||
{
|
||||
return (data[(unsigned int)bitPos >> 3] >> (bitPos & 7)) & 0xF;
|
||||
return (data[bitPos >> 3] >> (bitPos & 7)) & 0xF;
|
||||
}
|
||||
|
||||
static const Byte kCmdMasks[16] = {4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0};
|
||||
@@ -870,20 +909,20 @@ static void ItaniumDecode(Byte *data, UInt32 dataSize, UInt32 fileOffset)
|
||||
{
|
||||
Byte cmdMask = kCmdMasks[b];
|
||||
if (cmdMask != 0)
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (unsigned i = 0; i < 3; i++)
|
||||
if (cmdMask & (1 << i))
|
||||
{
|
||||
int startPos = i * 41 + 18;
|
||||
unsigned startPos = i * 41 + 18;
|
||||
if (ItaniumGetOpType(data, startPos + 24) == 5)
|
||||
{
|
||||
const UInt32 kMask = 0xFFFFF;
|
||||
Byte *p = data + ((unsigned int)startPos >> 3);
|
||||
Byte *p = data + (startPos >> 3);
|
||||
UInt32 bitField = ((UInt32)p[0]) | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16);
|
||||
int inBit = (startPos & 7);
|
||||
unsigned inBit = (startPos & 7);
|
||||
UInt32 offset = (bitField >> inBit) & kMask;
|
||||
UInt32 andMask = ~(kMask << inBit);
|
||||
bitField = ((offset - fileOffset) & kMask) << inBit;
|
||||
for (int j = 0; j < 3; j++)
|
||||
for (unsigned j = 0; j < 3; j++)
|
||||
{
|
||||
p[j] &= andMask;
|
||||
p[j] |= bitField;
|
||||
@@ -1016,6 +1055,7 @@ static void AudioDecode(Byte *srcData, UInt32 dataSize, UInt32 numChannels)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static UInt32 UpCaseDecode(Byte *data, UInt32 dataSize)
|
||||
{
|
||||
UInt32 srcPos = 0, destPos = dataSize;
|
||||
@@ -1028,6 +1068,7 @@ static UInt32 UpCaseDecode(Byte *data, UInt32 dataSize)
|
||||
}
|
||||
return destPos - dataSize;
|
||||
}
|
||||
*/
|
||||
|
||||
void CVm::ExecuteStandardFilter(unsigned filterIndex)
|
||||
{
|
||||
@@ -1068,6 +1109,7 @@ void CVm::ExecuteStandardFilter(unsigned filterIndex)
|
||||
SetBlockPos(dataSize);
|
||||
AudioDecode(Mem, dataSize, R[0]);
|
||||
break;
|
||||
/*
|
||||
case SF_UPCASE:
|
||||
if (dataSize >= kGlobalOffset / 2)
|
||||
break;
|
||||
@@ -1075,6 +1117,7 @@ void CVm::ExecuteStandardFilter(unsigned filterIndex)
|
||||
SetBlockSize(destSize);
|
||||
SetBlockPos(dataSize);
|
||||
break;
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/MyTypes.h"
|
||||
#include "../../Common/MyVector.h"
|
||||
|
||||
#define RARVM_STANDARD_FILTERS
|
||||
// #define RARVM_VM_ENABLE
|
||||
|
||||
namespace NCompress {
|
||||
namespace NRar3 {
|
||||
@@ -39,12 +39,12 @@ namespace NVm {
|
||||
inline UInt32 GetValue32(const void *addr) { return GetUi32(addr); }
|
||||
inline void SetValue32(void *addr, UInt32 value) { SetUi32(addr, value); }
|
||||
|
||||
const int kNumRegBits = 3;
|
||||
const unsigned kNumRegBits = 3;
|
||||
const UInt32 kNumRegs = 1 << kNumRegBits;
|
||||
const UInt32 kNumGpRegs = kNumRegs - 1;
|
||||
|
||||
const UInt32 kSpaceSize = 0x40000;
|
||||
const UInt32 kSpaceMask = kSpaceSize -1;
|
||||
const UInt32 kSpaceMask = kSpaceSize - 1;
|
||||
const UInt32 kGlobalOffset = 0x3C000;
|
||||
const UInt32 kGlobalSize = 0x2000;
|
||||
const UInt32 kFixedGlobalSize = 64;
|
||||
@@ -57,6 +57,9 @@ namespace NGlobalOffset
|
||||
const UInt32 kGlobalMemOutSize = 0x30;
|
||||
}
|
||||
|
||||
|
||||
#ifdef RARVM_VM_ENABLE
|
||||
|
||||
enum ECommand
|
||||
{
|
||||
CMD_MOV, CMD_CMP, CMD_ADD, CMD_SUB, CMD_JZ, CMD_JNZ, CMD_INC, CMD_DEC,
|
||||
@@ -89,27 +92,36 @@ struct CCommand
|
||||
COperand Op1, Op2;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
struct CBlockRef
|
||||
{
|
||||
UInt32 Offset;
|
||||
UInt32 Size;
|
||||
};
|
||||
|
||||
|
||||
class CProgram
|
||||
{
|
||||
#ifdef RARVM_VM_ENABLE
|
||||
void ReadProgram(const Byte *code, UInt32 codeSize);
|
||||
public:
|
||||
CRecordVector<CCommand> Commands;
|
||||
#endif
|
||||
|
||||
public:
|
||||
#ifdef RARVM_STANDARD_FILTERS
|
||||
int StandardFilterIndex;
|
||||
#endif
|
||||
|
||||
bool IsSupported;
|
||||
CRecordVector<Byte> StaticData;
|
||||
|
||||
private:
|
||||
void ReadProgram(const Byte *code, UInt32 codeSize);
|
||||
public:
|
||||
void PrepareProgram(const Byte *code, UInt32 codeSize);
|
||||
bool PrepareProgram(const Byte *code, UInt32 codeSize);
|
||||
};
|
||||
|
||||
|
||||
struct CProgramInitState
|
||||
{
|
||||
UInt32 InitR[kNumGpRegs];
|
||||
@@ -122,6 +134,7 @@ struct CProgramInitState
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CVm
|
||||
{
|
||||
static UInt32 GetValue(bool byteMode, const void *addr)
|
||||
@@ -146,15 +159,18 @@ class CVm
|
||||
void SetBlockPos(UInt32 v) { SetValue(&Mem[kGlobalOffset + NGlobalOffset::kBlockPos], v); }
|
||||
public:
|
||||
static void SetValue(void *addr, UInt32 value) { SetValue(false, addr, value); }
|
||||
|
||||
private:
|
||||
|
||||
#ifdef RARVM_VM_ENABLE
|
||||
UInt32 GetOperand32(const COperand *op) const;
|
||||
void SetOperand32(const COperand *op, UInt32 val);
|
||||
Byte GetOperand8(const COperand *op) const;
|
||||
void SetOperand8(const COperand *op, Byte val);
|
||||
UInt32 GetOperand(bool byteMode, const COperand *op) const;
|
||||
void SetOperand(bool byteMode, const COperand *op, UInt32 val);
|
||||
|
||||
bool ExecuteCode(const CProgram *prg);
|
||||
#endif
|
||||
|
||||
#ifdef RARVM_STANDARD_FILTERS
|
||||
void ExecuteStandardFilter(unsigned filterIndex);
|
||||
@@ -163,6 +179,7 @@ private:
|
||||
Byte *Mem;
|
||||
UInt32 R[kNumRegs + 1]; // R[kNumRegs] = 0 always (speed optimization)
|
||||
UInt32 Flags;
|
||||
|
||||
public:
|
||||
CVm();
|
||||
~CVm();
|
||||
@@ -171,7 +188,6 @@ public:
|
||||
bool Execute(CProgram *prg, const CProgramInitState *initState,
|
||||
CBlockRef &outBlockRef, CRecordVector<Byte> &outGlobalData);
|
||||
const Byte *GetDataPointer(UInt32 offset) const { return Mem + offset; }
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
960
CPP/7zip/Compress/Rar5Decoder.cpp
Normal file
960
CPP/7zip/Compress/Rar5Decoder.cpp
Normal file
@@ -0,0 +1,960 @@
|
||||
// Rar5Decoder.cpp
|
||||
// According to unRAR license, this code may not be used to develop
|
||||
// a program that creates RAR archives
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
// #include <stdio.h>
|
||||
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "Rar5Decoder.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NRar5 {
|
||||
|
||||
static const size_t kInputBufSize = 1 << 20;
|
||||
|
||||
void CBitDecoder::Prepare2() throw()
|
||||
{
|
||||
const unsigned kSize = 16;
|
||||
if (_buf > _bufLim)
|
||||
return;
|
||||
|
||||
size_t rem = _bufLim - _buf;
|
||||
if (rem != 0)
|
||||
memcpy(_bufBase, _buf, rem);
|
||||
|
||||
_bufLim = _bufBase + rem;
|
||||
_processedSize += (_buf - _bufBase);
|
||||
_buf = _bufBase;
|
||||
|
||||
if (!_wasFinished)
|
||||
{
|
||||
UInt32 processed = (UInt32)(kInputBufSize - rem);
|
||||
_hres = _stream->Read(_bufLim, (UInt32)processed, &processed);
|
||||
_bufLim += processed;
|
||||
_wasFinished = (processed == 0);
|
||||
if (_hres != S_OK)
|
||||
{
|
||||
_wasFinished = true;
|
||||
// throw CInBufferException(result);
|
||||
}
|
||||
}
|
||||
|
||||
rem = _bufLim - _buf;
|
||||
_bufCheck = _buf;
|
||||
if (rem < kSize)
|
||||
memset(_bufLim, 0xFF, kSize - rem);
|
||||
else
|
||||
_bufCheck = _bufLim - kSize;
|
||||
|
||||
SetCheck2();
|
||||
}
|
||||
|
||||
|
||||
enum FilterType
|
||||
{
|
||||
FILTER_DELTA = 0,
|
||||
FILTER_E8,
|
||||
FILTER_E8E9,
|
||||
FILTER_ARM
|
||||
};
|
||||
|
||||
static const size_t kWriteStep = (size_t)1 << 22;
|
||||
|
||||
CDecoder::CDecoder():
|
||||
_window(NULL),
|
||||
_winPos(0),
|
||||
_winSizeAllocated(0),
|
||||
_lzSize(0),
|
||||
_lzEnd(0),
|
||||
_writtenFileSize(0),
|
||||
_dictSizeLog(0),
|
||||
_isSolid(false),
|
||||
_wasInit(false),
|
||||
_inputBuf(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
CDecoder::~CDecoder()
|
||||
{
|
||||
::MidFree(_window);
|
||||
::MidFree(_inputBuf);
|
||||
}
|
||||
|
||||
HRESULT CDecoder::WriteData(const Byte *data, size_t size)
|
||||
{
|
||||
HRESULT res = S_OK;
|
||||
if (!_unpackSize_Defined || _writtenFileSize < _unpackSize)
|
||||
{
|
||||
size_t cur = size;
|
||||
if (_unpackSize_Defined)
|
||||
{
|
||||
UInt64 rem = _unpackSize - _writtenFileSize;
|
||||
if (cur > rem)
|
||||
cur = (size_t)rem;
|
||||
}
|
||||
res = WriteStream(_outStream, data, cur);
|
||||
if (res != S_OK)
|
||||
_writeError = true;
|
||||
}
|
||||
_writtenFileSize += size;
|
||||
return res;
|
||||
}
|
||||
|
||||
HRESULT CDecoder::ExecuteFilter(const CFilter &f)
|
||||
{
|
||||
bool useDest = false;
|
||||
|
||||
Byte *data = _filterSrc;
|
||||
UInt32 dataSize = f.Size;
|
||||
|
||||
// printf("\nType = %d offset = %9d size = %5d", f.Type, (unsigned)(f.Start - _lzFileStart), dataSize);
|
||||
|
||||
switch (f.Type)
|
||||
{
|
||||
case FILTER_E8:
|
||||
case FILTER_E8E9:
|
||||
{
|
||||
// printf(" FILTER_E8");
|
||||
if (dataSize > 4)
|
||||
{
|
||||
dataSize -= 4;
|
||||
UInt32 fileOffset = (UInt32)(f.Start - _lzFileStart);
|
||||
|
||||
const UInt32 kFileSize = (UInt32)1 << 24;
|
||||
Byte cmpMask = (Byte)(f.Type == FILTER_E8 ? 0xFF : 0xFE);
|
||||
|
||||
for (UInt32 curPos = 0; curPos < dataSize;)
|
||||
{
|
||||
curPos++;
|
||||
if (((*data++) & cmpMask) == 0xE8)
|
||||
{
|
||||
UInt32 offset = (curPos + fileOffset) & (kFileSize - 1);
|
||||
UInt32 addr = GetUi32(data);
|
||||
|
||||
if (addr < kFileSize)
|
||||
{
|
||||
SetUi32(data, addr - offset);
|
||||
}
|
||||
else if (addr > ((UInt32)0xFFFFFFFF - offset)) // (addr > ~(offset))
|
||||
{
|
||||
SetUi32(data, addr + kFileSize);
|
||||
}
|
||||
|
||||
data += 4;
|
||||
curPos += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case FILTER_ARM:
|
||||
{
|
||||
if (dataSize >= 4)
|
||||
{
|
||||
dataSize -= 4;
|
||||
UInt32 fileOffset = (UInt32)(f.Start - _lzFileStart);
|
||||
|
||||
for (UInt32 curPos = 0; curPos <= dataSize; curPos += 4)
|
||||
{
|
||||
Byte *d = data + curPos;
|
||||
if (d[3] == 0xEB)
|
||||
{
|
||||
UInt32 offset = d[0] | ((UInt32)d[1] << 8) | ((UInt32)d[2] << 16);
|
||||
offset -= (fileOffset + curPos) >> 2;
|
||||
d[0] = (Byte)offset;
|
||||
d[1] = (Byte)(offset >> 8);
|
||||
d[2] = (Byte)(offset >> 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case FILTER_DELTA:
|
||||
{
|
||||
// printf(" channels = %d", f.Channels);
|
||||
_filterDst.AllocAtLeast(dataSize);
|
||||
if (!_filterDst.IsAllocated())
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
Byte *dest = _filterDst;
|
||||
UInt32 numChannels = f.Channels;
|
||||
|
||||
for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++)
|
||||
{
|
||||
Byte prevByte = 0;
|
||||
for (UInt32 destPos = curChannel; destPos < dataSize; destPos += numChannels)
|
||||
dest[destPos] = (prevByte = (Byte)(prevByte - *data++));
|
||||
}
|
||||
useDest = true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
_unsupportedFilter = true;
|
||||
}
|
||||
|
||||
return WriteData(useDest ?
|
||||
(const Byte *)_filterDst :
|
||||
(const Byte *)_filterSrc,
|
||||
f.Size);
|
||||
}
|
||||
|
||||
|
||||
HRESULT CDecoder::WriteBuf()
|
||||
{
|
||||
DeleteUnusedFilters();
|
||||
|
||||
for (unsigned i = 0; i < _filters.Size();)
|
||||
{
|
||||
const CFilter &f = _filters[i];
|
||||
|
||||
UInt64 blockStart = f.Start;
|
||||
|
||||
size_t lzAvail = (size_t)(_lzSize - _lzWritten);
|
||||
if (lzAvail == 0)
|
||||
break;
|
||||
|
||||
if (blockStart > _lzWritten)
|
||||
{
|
||||
UInt64 rem = blockStart - _lzWritten;
|
||||
size_t size = lzAvail;
|
||||
if (size > rem)
|
||||
size = (size_t)rem;
|
||||
if (size != 0)
|
||||
{
|
||||
RINOK(WriteData(_window + _winPos - lzAvail, size));
|
||||
_lzWritten += size;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
UInt32 blockSize = f.Size;
|
||||
size_t offset = (size_t)(_lzWritten - blockStart);
|
||||
if (offset == 0)
|
||||
{
|
||||
_filterSrc.AllocAtLeast(blockSize);
|
||||
if (!_filterSrc.IsAllocated())
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
size_t blockRem = (size_t)blockSize - offset;
|
||||
size_t size = lzAvail;
|
||||
if (size > blockRem)
|
||||
size = blockRem;
|
||||
memcpy(_filterSrc + offset, _window + _winPos - lzAvail, size);
|
||||
_lzWritten += size;
|
||||
offset += size;
|
||||
if (offset != blockSize)
|
||||
return S_OK;
|
||||
|
||||
_numUnusedFilters = ++i;
|
||||
RINOK(ExecuteFilter(f));
|
||||
}
|
||||
|
||||
DeleteUnusedFilters();
|
||||
|
||||
if (!_filters.IsEmpty())
|
||||
return S_OK;
|
||||
|
||||
size_t lzAvail = (size_t)(_lzSize - _lzWritten);
|
||||
RINOK(WriteData(_window + _winPos - lzAvail, lzAvail));
|
||||
_lzWritten += lzAvail;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
static UInt32 ReadUInt32(CBitDecoder &bi)
|
||||
{
|
||||
unsigned numBytes = bi.ReadBits9fix(2) + 1;
|
||||
UInt32 v = 0;
|
||||
for (unsigned i = 0; i < numBytes; i++)
|
||||
v += ((UInt32)bi.ReadBits9fix(8) << (i * 8));
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
static const unsigned MAX_UNPACK_FILTERS = 8192;
|
||||
|
||||
HRESULT CDecoder::AddFilter(CBitDecoder &_bitStream)
|
||||
{
|
||||
DeleteUnusedFilters();
|
||||
|
||||
if (_filters.Size() >= MAX_UNPACK_FILTERS)
|
||||
{
|
||||
RINOK(WriteBuf());
|
||||
DeleteUnusedFilters();
|
||||
if (_filters.Size() >= MAX_UNPACK_FILTERS)
|
||||
{
|
||||
_unsupportedFilter = true;
|
||||
InitFilters();
|
||||
}
|
||||
}
|
||||
|
||||
_bitStream.Prepare();
|
||||
|
||||
CFilter f;
|
||||
UInt32 blockStart = ReadUInt32(_bitStream);
|
||||
f.Size = ReadUInt32(_bitStream);
|
||||
|
||||
// if (f.Size > ((UInt32)1 << 16)) _unsupportedFilter = true;
|
||||
|
||||
f.Type = (Byte)_bitStream.ReadBits9fix(3);
|
||||
if (f.Type == FILTER_DELTA)
|
||||
f.Channels = (Byte)(_bitStream.ReadBits9fix(5) + 1);
|
||||
f.Start = _lzSize + blockStart;
|
||||
|
||||
if (f.Start < _filterEnd)
|
||||
_unsupportedFilter = true;
|
||||
else
|
||||
{
|
||||
_filterEnd = f.Start + f.Size;
|
||||
if (f.Size != 0)
|
||||
_filters.Add(f);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
#define RIF(x) { if (!(x)) return S_FALSE; }
|
||||
|
||||
HRESULT CDecoder::ReadTables(CBitDecoder &_bitStream)
|
||||
{
|
||||
if (_progress)
|
||||
{
|
||||
UInt64 packSize = _bitStream.GetProcessedSize();
|
||||
RINOK(_progress->SetRatioInfo(&packSize, &_writtenFileSize));
|
||||
}
|
||||
|
||||
_bitStream.AlignToByte();
|
||||
_bitStream.Prepare();
|
||||
|
||||
unsigned flags = _bitStream.ReadByteInAligned();
|
||||
unsigned checkSum = _bitStream.ReadByteInAligned();
|
||||
checkSum ^= flags;
|
||||
|
||||
UInt32 blockSize;
|
||||
{
|
||||
unsigned num = (flags >> 3) & 3;
|
||||
if (num == 3)
|
||||
return S_FALSE;
|
||||
blockSize = _bitStream.ReadByteInAligned();
|
||||
if (num > 0)
|
||||
{
|
||||
blockSize += (UInt32)_bitStream.ReadByteInAligned() << 8;
|
||||
if (num > 1)
|
||||
blockSize += (UInt32)_bitStream.ReadByteInAligned() << 16;
|
||||
}
|
||||
}
|
||||
|
||||
checkSum ^= blockSize ^ (blockSize >> 8) ^ (blockSize >> 16);
|
||||
if ((Byte)checkSum != 0x5A)
|
||||
return S_FALSE;
|
||||
|
||||
unsigned blockSizeBits7 = (flags & 7) + 1;
|
||||
|
||||
if (blockSize == 0 && blockSizeBits7 != 8)
|
||||
return S_FALSE;
|
||||
|
||||
blockSize += (blockSizeBits7 >> 3);
|
||||
blockSize--;
|
||||
|
||||
_bitStream._blockEndBits7 = (Byte)(blockSizeBits7 & 7);
|
||||
_bitStream._blockEnd = _bitStream.GetProcessedSize_Round() + blockSize;
|
||||
|
||||
_bitStream.SetCheck2();
|
||||
|
||||
_isLastBlock = ((flags & 0x40) != 0);
|
||||
|
||||
if ((flags & 0x80) == 0)
|
||||
{
|
||||
if (!_tableWasFilled && blockSize != 0)
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
_tableWasFilled = false;
|
||||
|
||||
{
|
||||
Byte lens2[kLevelTableSize];
|
||||
|
||||
for (unsigned i = 0; i < kLevelTableSize;)
|
||||
{
|
||||
_bitStream.Prepare();
|
||||
unsigned len = (unsigned)_bitStream.ReadBits9fix(4);
|
||||
if (len == 15)
|
||||
{
|
||||
unsigned num = (unsigned)_bitStream.ReadBits9fix(4);
|
||||
if (num != 0)
|
||||
{
|
||||
num += 2;
|
||||
num += i;
|
||||
if (num > kLevelTableSize)
|
||||
num = kLevelTableSize;
|
||||
do
|
||||
lens2[i++] = 0;
|
||||
while (i < num);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
lens2[i++] = (Byte)len;
|
||||
}
|
||||
|
||||
if (_bitStream.IsBlockOverRead())
|
||||
return S_FALSE;
|
||||
|
||||
RIF(m_LevelDecoder.SetCodeLengths(lens2));
|
||||
}
|
||||
|
||||
Byte lens[kTablesSizesSum];
|
||||
unsigned i = 0;
|
||||
|
||||
while (i < kTablesSizesSum)
|
||||
{
|
||||
if (_bitStream._buf >= _bitStream._bufCheck2)
|
||||
{
|
||||
if (_bitStream._buf >= _bitStream._bufCheck)
|
||||
_bitStream.Prepare();
|
||||
if (_bitStream.IsBlockOverRead())
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
UInt32 sym = m_LevelDecoder.DecodeSymbol(&_bitStream);
|
||||
|
||||
if (sym < 16)
|
||||
lens[i++] = (Byte)sym;
|
||||
else if (sym > kLevelTableSize)
|
||||
return S_FALSE;
|
||||
else
|
||||
{
|
||||
sym -= 16;
|
||||
unsigned sh = ((sym & 1) << 2);
|
||||
unsigned num = (unsigned)_bitStream.ReadBits9(3 + sh) + 3 + (sh << 1);
|
||||
|
||||
num += i;
|
||||
if (num > kTablesSizesSum)
|
||||
num = kTablesSizesSum;
|
||||
|
||||
if (sym < 2)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
// return S_FALSE;
|
||||
continue; // original unRAR
|
||||
}
|
||||
Byte v = lens[i - 1];
|
||||
do
|
||||
lens[i++] = v;
|
||||
while (i < num);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
lens[i++] = 0;
|
||||
while (i < num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_bitStream.IsBlockOverRead())
|
||||
return S_FALSE;
|
||||
if (_bitStream.InputEofError())
|
||||
return S_FALSE;
|
||||
|
||||
RIF(m_MainDecoder.SetCodeLengths(&lens[0]));
|
||||
RIF(m_DistDecoder.SetCodeLengths(&lens[kMainTableSize]));
|
||||
RIF(m_AlignDecoder.SetCodeLengths(&lens[kMainTableSize + kDistTableSize]));
|
||||
RIF(m_LenDecoder.SetCodeLengths(&lens[kMainTableSize + kDistTableSize + kAlignTableSize]));
|
||||
|
||||
_useAlignBits = false;
|
||||
// _useAlignBits = true;
|
||||
for (i = 0; i < kAlignTableSize; i++)
|
||||
if (lens[kMainTableSize + kDistTableSize + i] != kNumAlignBits)
|
||||
{
|
||||
_useAlignBits = true;
|
||||
break;
|
||||
}
|
||||
|
||||
_tableWasFilled = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
static inline unsigned SlotToLen(CBitDecoder &_bitStream, unsigned slot)
|
||||
{
|
||||
if (slot < 8)
|
||||
return slot + 2;
|
||||
unsigned numBits = (slot >> 2) - 1;
|
||||
return 2 + ((4 | (slot & 3)) << numBits) + _bitStream.ReadBits9(numBits);
|
||||
}
|
||||
|
||||
|
||||
static const UInt32 kSymbolRep = 258;
|
||||
// static const unsigned kMaxMatchLen = 0x1001 + 3;
|
||||
|
||||
HRESULT CDecoder::DecodeLZ()
|
||||
{
|
||||
CBitDecoder _bitStream;
|
||||
_bitStream._stream = _inStream;
|
||||
_bitStream._bufBase = _inputBuf;
|
||||
_bitStream.Init();
|
||||
|
||||
UInt32 rep0 = _reps[0];
|
||||
|
||||
UInt32 remLen = 0;
|
||||
|
||||
size_t limit;
|
||||
{
|
||||
size_t rem = _winSize - _winPos;
|
||||
if (rem > kWriteStep)
|
||||
rem = kWriteStep;
|
||||
limit = _winPos + rem;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (_winPos >= limit)
|
||||
{
|
||||
RINOK(WriteBuf());
|
||||
if (_unpackSize_Defined && _writtenFileSize > _unpackSize)
|
||||
break; // return S_FALSE;
|
||||
|
||||
{
|
||||
size_t rem = _winSize - _winPos;
|
||||
|
||||
if (rem == 0)
|
||||
{
|
||||
_winPos = 0;
|
||||
rem = _winSize;
|
||||
}
|
||||
if (rem > kWriteStep)
|
||||
rem = kWriteStep;
|
||||
limit = _winPos + rem;
|
||||
}
|
||||
|
||||
if (remLen != 0)
|
||||
{
|
||||
size_t winPos = _winPos;
|
||||
size_t winMask = _winMask;
|
||||
size_t pos = (winPos - (size_t)rep0 - 1) & winMask;
|
||||
|
||||
Byte *win = _window;
|
||||
do
|
||||
{
|
||||
if (winPos >= limit)
|
||||
break;
|
||||
win[winPos] = win[pos];
|
||||
winPos++;
|
||||
pos = (pos + 1) & winMask;
|
||||
}
|
||||
while (--remLen != 0);
|
||||
|
||||
_lzSize += winPos - _winPos;
|
||||
_winPos = winPos;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (_bitStream._buf >= _bitStream._bufCheck2)
|
||||
{
|
||||
if (_bitStream.InputEofError())
|
||||
break; // return S_FALSE;
|
||||
if (_bitStream._buf >= _bitStream._bufCheck)
|
||||
_bitStream.Prepare2();
|
||||
|
||||
UInt64 processed = _bitStream.GetProcessedSize_Round();
|
||||
if (processed >= _bitStream._blockEnd)
|
||||
{
|
||||
if (processed > _bitStream._blockEnd)
|
||||
break; // return S_FALSE;
|
||||
{
|
||||
unsigned bits7 = _bitStream.GetProcessedBits7();
|
||||
if (bits7 > _bitStream._blockEndBits7)
|
||||
break; // return S_FALSE;
|
||||
if (bits7 == _bitStream._blockEndBits7)
|
||||
{
|
||||
if (_isLastBlock)
|
||||
{
|
||||
_reps[0] = rep0;
|
||||
|
||||
if (_bitStream.InputEofError())
|
||||
break;
|
||||
|
||||
/*
|
||||
// packSize can be 15 bytes larger for encrypted archive
|
||||
if (_packSize_Defined && _packSize < _bitStream.GetProcessedSize())
|
||||
break;
|
||||
*/
|
||||
|
||||
return _bitStream._hres;
|
||||
// break;
|
||||
}
|
||||
RINOK(ReadTables(_bitStream));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 sym = m_MainDecoder.DecodeSymbol(&_bitStream);
|
||||
|
||||
if (sym < 256)
|
||||
{
|
||||
size_t winPos = _winPos;
|
||||
_window[winPos] = (Byte)sym;
|
||||
_winPos = winPos + 1;
|
||||
_lzSize++;
|
||||
continue;
|
||||
}
|
||||
|
||||
UInt32 len;
|
||||
|
||||
if (sym < kSymbolRep + kNumReps)
|
||||
{
|
||||
if (sym >= kSymbolRep)
|
||||
{
|
||||
if (sym != kSymbolRep)
|
||||
{
|
||||
UInt32 dist;
|
||||
if (sym == kSymbolRep + 1)
|
||||
dist = _reps[1];
|
||||
else
|
||||
{
|
||||
if (sym == kSymbolRep + 2)
|
||||
dist = _reps[2];
|
||||
else
|
||||
{
|
||||
dist = _reps[3];
|
||||
_reps[3] = _reps[2];
|
||||
}
|
||||
_reps[2] = _reps[1];
|
||||
}
|
||||
_reps[1] = rep0;
|
||||
rep0 = dist;
|
||||
}
|
||||
|
||||
UInt32 sym = m_LenDecoder.DecodeSymbol(&_bitStream);
|
||||
if (sym >= kLenTableSize)
|
||||
break; // return S_FALSE;
|
||||
len = SlotToLen(_bitStream, sym);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sym == 256)
|
||||
{
|
||||
RINOK(AddFilter(_bitStream));
|
||||
continue;
|
||||
}
|
||||
else // if (sym == 257)
|
||||
{
|
||||
len = _lastLen;
|
||||
// if (len = 0), we ignore that symbol, like original unRAR code, but it can mean error in stream.
|
||||
// if (len == 0) return S_FALSE;
|
||||
if (len == 0)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sym >= kMainTableSize)
|
||||
break; // return S_FALSE;
|
||||
else
|
||||
{
|
||||
_reps[3] = _reps[2];
|
||||
_reps[2] = _reps[1];
|
||||
_reps[1] = rep0;
|
||||
len = SlotToLen(_bitStream, sym - (kSymbolRep + kNumReps));
|
||||
|
||||
rep0 = m_DistDecoder.DecodeSymbol(&_bitStream);
|
||||
|
||||
if (rep0 >= 4)
|
||||
{
|
||||
if (rep0 >= _numCorrectDistSymbols)
|
||||
break; // return S_FALSE;
|
||||
unsigned numBits = (rep0 >> 1) - 1;
|
||||
rep0 = (2 | (rep0 & 1)) << numBits;
|
||||
|
||||
if (numBits < kNumAlignBits)
|
||||
rep0 += _bitStream.ReadBits9(numBits);
|
||||
else
|
||||
{
|
||||
len += (numBits >= 7);
|
||||
len += (numBits >= 12);
|
||||
len += (numBits >= 17);
|
||||
|
||||
if (_useAlignBits)
|
||||
{
|
||||
// if (numBits > kNumAlignBits)
|
||||
rep0 += (_bitStream.ReadBits32(numBits - kNumAlignBits) << kNumAlignBits);
|
||||
UInt32 a = m_AlignDecoder.DecodeSymbol(&_bitStream);
|
||||
if (a >= kAlignTableSize)
|
||||
break; // return S_FALSE;
|
||||
rep0 += a;
|
||||
}
|
||||
else
|
||||
rep0 += _bitStream.ReadBits32(numBits);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_lastLen = len;
|
||||
|
||||
if (rep0 >= _lzSize)
|
||||
_lzError = true;
|
||||
|
||||
{
|
||||
UInt32 lenCur = len;
|
||||
size_t winPos = _winPos;
|
||||
size_t pos = (winPos - (size_t)rep0 - 1) & _winMask;
|
||||
{
|
||||
size_t rem = limit - winPos;
|
||||
// size_t rem = _winSize - winPos;
|
||||
|
||||
if (lenCur > rem)
|
||||
{
|
||||
lenCur = (UInt32)rem;
|
||||
remLen = len - lenCur;
|
||||
}
|
||||
}
|
||||
|
||||
Byte *win = _window;
|
||||
_lzSize += lenCur;
|
||||
_winPos = winPos + lenCur;
|
||||
if (_winSize - pos >= lenCur)
|
||||
{
|
||||
const Byte *src = win + pos;
|
||||
Byte *dest = win + winPos;
|
||||
do
|
||||
*dest++ = *src++;
|
||||
while (--lenCur != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
win[winPos] = win[pos];
|
||||
winPos++;
|
||||
pos = (pos + 1) & _winMask;
|
||||
}
|
||||
while (--lenCur != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_bitStream._hres != S_OK)
|
||||
return _bitStream._hres;
|
||||
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CDecoder::CodeReal()
|
||||
{
|
||||
_unsupportedFilter = false;
|
||||
_lzError = false;
|
||||
_writeError = false;
|
||||
|
||||
if (!_isSolid || !_wasInit)
|
||||
{
|
||||
size_t clearSize = _winSize;
|
||||
if (_lzSize < _winSize)
|
||||
clearSize = (size_t)_lzSize;
|
||||
memset(_window, 0, clearSize);
|
||||
|
||||
_wasInit = true;
|
||||
_lzSize = 0;
|
||||
_lzWritten = 0;
|
||||
_winPos = 0;
|
||||
|
||||
for (unsigned i = 0; i < kNumReps; i++)
|
||||
_reps[i] = (UInt32)0 - 1;
|
||||
|
||||
_lastLen = 0;
|
||||
_tableWasFilled = false;
|
||||
}
|
||||
|
||||
_isLastBlock = false;
|
||||
|
||||
InitFilters();
|
||||
|
||||
_filterEnd = 0;
|
||||
_writtenFileSize = 0;
|
||||
|
||||
_lzFileStart = _lzSize;
|
||||
_lzWritten = _lzSize;
|
||||
|
||||
HRESULT res = DecodeLZ();
|
||||
|
||||
HRESULT res2 = S_OK;
|
||||
if (!_writeError && res != E_OUTOFMEMORY)
|
||||
res2 = WriteBuf();
|
||||
|
||||
/*
|
||||
if (res == S_OK)
|
||||
if (InputEofError())
|
||||
res = S_FALSE;
|
||||
*/
|
||||
|
||||
if (res == S_OK)
|
||||
res = res2;
|
||||
|
||||
if (res == S_OK && _unpackSize_Defined && _writtenFileSize != _unpackSize)
|
||||
return S_FALSE;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
// Original unRAR claims that maximum possible filter block size is (1 << 16) now,
|
||||
// and (1 << 17) is minimum win size required to support filter.
|
||||
// Original unRAR uses (1 << 18) for "extra safety and possible filter area size expansion"
|
||||
// We can use any win size.
|
||||
|
||||
static const unsigned kWinSize_Log_Min = 17;
|
||||
|
||||
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_dictSizeLog >= sizeof(size_t) * 8)
|
||||
return E_NOTIMPL;
|
||||
|
||||
if (!_isSolid)
|
||||
_lzEnd = 0;
|
||||
else
|
||||
{
|
||||
if (_lzSize < _lzEnd)
|
||||
{
|
||||
if (_window)
|
||||
{
|
||||
UInt64 rem = _lzEnd - _lzSize;
|
||||
if (rem >= _winSize)
|
||||
memset(_window, 0, _winSize);
|
||||
else
|
||||
{
|
||||
size_t pos = (size_t)_lzSize & _winSize;
|
||||
size_t rem2 = _winSize - pos;
|
||||
if (rem2 > rem)
|
||||
rem2 = (size_t)rem;
|
||||
memset(_window + pos, 0, rem2);
|
||||
rem -= rem2;
|
||||
memset(_window, 0, (size_t)rem);
|
||||
}
|
||||
}
|
||||
_lzEnd &= ((((UInt64)1) << 33) - 1);
|
||||
_lzSize = _lzEnd;
|
||||
_winPos = (size_t)(_lzSize & _winSize);
|
||||
}
|
||||
_lzEnd = _lzSize;
|
||||
}
|
||||
|
||||
size_t newSize;
|
||||
{
|
||||
unsigned newSizeLog = _dictSizeLog;
|
||||
if (newSizeLog < kWinSize_Log_Min)
|
||||
newSizeLog = kWinSize_Log_Min;
|
||||
newSize = (size_t)1 << newSizeLog;
|
||||
_numCorrectDistSymbols = newSizeLog * 2;
|
||||
}
|
||||
|
||||
if (!_window || _winSize != newSize)
|
||||
{
|
||||
if (!_isSolid && newSize > _winSizeAllocated)
|
||||
{
|
||||
::MidFree(_window);
|
||||
_window = NULL;
|
||||
_winSizeAllocated = 0;
|
||||
}
|
||||
|
||||
Byte *win = _window;
|
||||
if (!_window || newSize > _winSizeAllocated)
|
||||
{
|
||||
win = (Byte *)::MidAlloc(newSize);
|
||||
if (!win)
|
||||
return E_OUTOFMEMORY;
|
||||
_winSizeAllocated = newSize;
|
||||
memset(win, 0, newSize);
|
||||
}
|
||||
|
||||
if (_isSolid && _window)
|
||||
{
|
||||
// original unRAR claims:
|
||||
// "Archiving code guarantees that win size does not grow in the same solid stream",
|
||||
// but the original unRAR decoder still supports such grow case.
|
||||
|
||||
Byte *winOld = _window;
|
||||
size_t oldSize = _winSize;
|
||||
size_t newMask = newSize - 1;
|
||||
size_t oldMask = _winSize - 1;
|
||||
size_t winPos = _winPos;
|
||||
for (size_t i = 1; i < oldSize; i++) // i < oldSize) ?
|
||||
win[(winPos - i) & newMask] = winOld[(winPos - i) & oldMask];
|
||||
::MidFree(_window);
|
||||
}
|
||||
|
||||
_window = win;
|
||||
_winSize = newSize;
|
||||
}
|
||||
|
||||
_winMask = _winSize - 1;
|
||||
|
||||
if (!_inputBuf)
|
||||
{
|
||||
_inputBuf = (Byte *)::MidAlloc(kInputBufSize);
|
||||
if (!_inputBuf)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
_inStream = inStream;
|
||||
_outStream = outStream;
|
||||
|
||||
/*
|
||||
_packSize = 0;
|
||||
_packSize_Defined = (inSize != NULL);
|
||||
if (_packSize_Defined)
|
||||
_packSize = *inSize;
|
||||
*/
|
||||
|
||||
_unpackSize = 0;
|
||||
_unpackSize_Defined = (outSize != NULL);
|
||||
if (_unpackSize_Defined)
|
||||
_unpackSize = *outSize;
|
||||
|
||||
if ((Int64)_unpackSize >= 0)
|
||||
_lzEnd += _unpackSize;
|
||||
else
|
||||
_lzEnd = 0;
|
||||
|
||||
_progress = progress;
|
||||
|
||||
HRESULT res = CodeReal();
|
||||
|
||||
if (res != S_OK)
|
||||
return res;
|
||||
if (_lzError)
|
||||
return S_FALSE;
|
||||
if (_unsupportedFilter)
|
||||
return E_NOTIMPL;
|
||||
return S_OK;
|
||||
}
|
||||
// catch(const CInBufferException &e) { return e.ErrorCode; }
|
||||
// catch(...) { return S_FALSE; }
|
||||
catch(...) { return E_OUTOFMEMORY; }
|
||||
// CNewException is possible here. But probably CNewException is caused
|
||||
// by error in data stream.
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
||||
{
|
||||
if (size != 2)
|
||||
return E_NOTIMPL;
|
||||
_dictSizeLog = (Byte)((data[0] & 0xF) + 17);
|
||||
_isSolid = ((data[1] & 1) != 0);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
335
CPP/7zip/Compress/Rar5Decoder.h
Normal file
335
CPP/7zip/Compress/Rar5Decoder.h
Normal file
@@ -0,0 +1,335 @@
|
||||
// Rar5Decoder.h
|
||||
// According to unRAR license, this code may not be used to develop
|
||||
// a program that creates RAR archives
|
||||
|
||||
#ifndef __COMPRESS_RAR5_DECODER_H
|
||||
#define __COMPRESS_RAR5_DECODER_H
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/MyBuffer.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Common/MyException.h"
|
||||
#include "../../Common/MyVector.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
|
||||
#include "HuffmanDecoder.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NRar5 {
|
||||
|
||||
class CMidBuffer
|
||||
{
|
||||
Byte *_data;
|
||||
size_t _size;
|
||||
|
||||
CLASS_NO_COPY(CMidBuffer)
|
||||
|
||||
public:
|
||||
CMidBuffer(): _data(NULL), _size(0) {};
|
||||
~CMidBuffer() { ::MidFree(_data); }
|
||||
|
||||
bool IsAllocated() const { return _data != NULL; }
|
||||
operator Byte *() { return _data; }
|
||||
operator const Byte *() const { return _data; }
|
||||
size_t Size() const { return _size; }
|
||||
|
||||
void AllocAtLeast(size_t size)
|
||||
{
|
||||
if (size > _size)
|
||||
{
|
||||
const size_t kMinSize = (1 << 16);
|
||||
if (size < kMinSize)
|
||||
size = kMinSize;
|
||||
::MidFree(_data);
|
||||
_data = (Byte *)::MidAlloc(size);
|
||||
_size = size;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
struct CInBufferException: public CSystemException
|
||||
{
|
||||
CInBufferException(HRESULT errorCode): CSystemException(errorCode) {}
|
||||
};
|
||||
*/
|
||||
|
||||
class CBitDecoder
|
||||
{
|
||||
public:
|
||||
const Byte *_buf;
|
||||
unsigned _bitPos;
|
||||
bool _wasFinished;
|
||||
Byte _blockEndBits7;
|
||||
const Byte *_bufCheck2;
|
||||
const Byte *_bufCheck;
|
||||
Byte *_bufLim;
|
||||
Byte *_bufBase;
|
||||
|
||||
UInt64 _processedSize;
|
||||
UInt64 _blockEnd;
|
||||
|
||||
ISequentialInStream *_stream;
|
||||
HRESULT _hres;
|
||||
|
||||
void SetCheck2()
|
||||
{
|
||||
_bufCheck2 = _bufCheck;
|
||||
if (_bufCheck > _buf)
|
||||
{
|
||||
UInt64 processed = GetProcessedSize_Round();
|
||||
if (_blockEnd < processed)
|
||||
_bufCheck2 = _buf;
|
||||
else
|
||||
{
|
||||
UInt64 delta = _blockEnd - processed;
|
||||
if ((size_t)(_bufCheck - _buf) > delta)
|
||||
_bufCheck2 = _buf + (size_t)delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IsBlockOverRead() const
|
||||
{
|
||||
UInt64 v = GetProcessedSize_Round();
|
||||
if (v < _blockEnd)
|
||||
return false;
|
||||
if (v > _blockEnd)
|
||||
return true;
|
||||
return _bitPos > _blockEndBits7;
|
||||
}
|
||||
|
||||
/*
|
||||
CBitDecoder() throw():
|
||||
_buf(0),
|
||||
_bufLim(0),
|
||||
_bufBase(0),
|
||||
_stream(0),
|
||||
_processedSize(0),
|
||||
_wasFinished(false)
|
||||
{}
|
||||
*/
|
||||
|
||||
void Init() throw()
|
||||
{
|
||||
_blockEnd = 0;
|
||||
_blockEndBits7 = 0;
|
||||
|
||||
_bitPos = 0;
|
||||
_processedSize = 0;
|
||||
_buf = _bufBase;
|
||||
_bufLim = _bufBase;
|
||||
_bufCheck = _buf;
|
||||
_bufCheck2 = _buf;
|
||||
_wasFinished = false;
|
||||
}
|
||||
|
||||
void Prepare2() throw();
|
||||
|
||||
void Prepare() throw()
|
||||
{
|
||||
if (_buf >= _bufCheck)
|
||||
Prepare2();
|
||||
}
|
||||
|
||||
bool ExtraBitsWereRead() const
|
||||
{
|
||||
return _buf >= _bufLim && (_buf > _bufLim || _bitPos != 0);
|
||||
}
|
||||
|
||||
bool InputEofError() const { return ExtraBitsWereRead(); }
|
||||
|
||||
unsigned GetProcessedBits7() const { return _bitPos; }
|
||||
UInt64 GetProcessedSize_Round() const { return _processedSize + (_buf - _bufBase); }
|
||||
UInt64 GetProcessedSize() const { return _processedSize + (_buf - _bufBase) + ((_bitPos + 7) >> 3); }
|
||||
|
||||
void AlignToByte()
|
||||
{
|
||||
_buf += (_bitPos + 7) >> 3;
|
||||
_bitPos = 0;
|
||||
}
|
||||
|
||||
Byte ReadByteInAligned()
|
||||
{
|
||||
return *_buf++;
|
||||
}
|
||||
|
||||
UInt32 GetValue(unsigned numBits)
|
||||
{
|
||||
UInt32 v = ((UInt32)_buf[0] << 16) | ((UInt32)_buf[1] << 8) | (UInt32)_buf[2];
|
||||
v >>= (24 - numBits - _bitPos);
|
||||
return v & ((1 << numBits) - 1);
|
||||
}
|
||||
|
||||
void MovePos(unsigned numBits)
|
||||
{
|
||||
_bitPos += numBits;
|
||||
_buf += (_bitPos >> 3);
|
||||
_bitPos &= 7;
|
||||
}
|
||||
|
||||
UInt32 ReadBits9(unsigned numBits)
|
||||
{
|
||||
const Byte *buf = _buf;
|
||||
UInt32 v = ((UInt32)buf[0] << 8) | (UInt32)buf[1];
|
||||
v &= ((UInt32)0xFFFF >> _bitPos);
|
||||
numBits += _bitPos;
|
||||
v >>= (16 - numBits);
|
||||
_buf = buf + (numBits >> 3);
|
||||
_bitPos = numBits & 7;
|
||||
return v;
|
||||
}
|
||||
|
||||
UInt32 ReadBits9fix(unsigned numBits)
|
||||
{
|
||||
const Byte *buf = _buf;
|
||||
UInt32 v = ((UInt32)buf[0] << 8) | (UInt32)buf[1];
|
||||
UInt32 mask = ((1 << numBits) - 1);
|
||||
numBits += _bitPos;
|
||||
v >>= (16 - numBits);
|
||||
_buf = buf + (numBits >> 3);
|
||||
_bitPos = numBits & 7;
|
||||
return v & mask;
|
||||
}
|
||||
|
||||
UInt32 ReadBits32(unsigned numBits)
|
||||
{
|
||||
UInt32 mask = ((1 << numBits) - 1);
|
||||
numBits += _bitPos;
|
||||
const Byte *buf = _buf;
|
||||
UInt32 v = GetBe32(buf);
|
||||
if (numBits > 32)
|
||||
{
|
||||
v <<= (numBits - 32);
|
||||
v |= (UInt32)buf[4] >> (40 - numBits);
|
||||
}
|
||||
else
|
||||
v >>= (32 - numBits);
|
||||
_buf = buf + (numBits >> 3);
|
||||
_bitPos = numBits & 7;
|
||||
return v & mask;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CFilter
|
||||
{
|
||||
Byte Type;
|
||||
Byte Channels;
|
||||
UInt32 Size;
|
||||
UInt64 Start;
|
||||
};
|
||||
|
||||
|
||||
const unsigned kNumReps = 4;
|
||||
const unsigned kLenTableSize = 11 * 4;
|
||||
const unsigned kMainTableSize = 256 + 1 + 1 + kNumReps + kLenTableSize;
|
||||
const unsigned kDistTableSize = 64;
|
||||
const unsigned kNumAlignBits = 4;
|
||||
const unsigned kAlignTableSize = (1 << kNumAlignBits);
|
||||
const unsigned kLevelTableSize = 20;
|
||||
const unsigned kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize + kLenTableSize;
|
||||
|
||||
const unsigned kNumHuffmanBits = 15;
|
||||
|
||||
class CDecoder:
|
||||
public ICompressCoder,
|
||||
public ICompressSetDecoderProperties2,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
bool _useAlignBits;
|
||||
bool _isLastBlock;
|
||||
bool _unpackSize_Defined;
|
||||
// bool _packSize_Defined;
|
||||
|
||||
bool _unsupportedFilter;
|
||||
bool _lzError;
|
||||
bool _writeError;
|
||||
|
||||
// CBitDecoder _bitStream;
|
||||
Byte *_window;
|
||||
size_t _winPos;
|
||||
size_t _winSize;
|
||||
size_t _winMask;
|
||||
|
||||
UInt64 _lzSize;
|
||||
|
||||
unsigned _numCorrectDistSymbols;
|
||||
unsigned _numUnusedFilters;
|
||||
|
||||
UInt64 _lzWritten;
|
||||
UInt64 _lzFileStart;
|
||||
UInt64 _unpackSize;
|
||||
// UInt64 _packSize;
|
||||
UInt64 _lzEnd;
|
||||
UInt64 _writtenFileSize;
|
||||
size_t _winSizeAllocated;
|
||||
|
||||
Byte _dictSizeLog;
|
||||
bool _tableWasFilled;
|
||||
bool _isSolid;
|
||||
bool _wasInit;
|
||||
|
||||
UInt32 _reps[kNumReps];
|
||||
UInt32 _lastLen;
|
||||
|
||||
UInt64 _filterEnd;
|
||||
CMidBuffer _filterSrc;
|
||||
CMidBuffer _filterDst;
|
||||
|
||||
CRecordVector<CFilter> _filters;
|
||||
|
||||
ISequentialInStream *_inStream;
|
||||
ISequentialOutStream *_outStream;
|
||||
ICompressProgressInfo *_progress;
|
||||
Byte *_inputBuf;
|
||||
|
||||
NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder;
|
||||
NHuffman::CDecoder<kNumHuffmanBits, kDistTableSize> m_DistDecoder;
|
||||
NHuffman::CDecoder<kNumHuffmanBits, kAlignTableSize> m_AlignDecoder;
|
||||
NHuffman::CDecoder<kNumHuffmanBits, kLenTableSize> m_LenDecoder;
|
||||
NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder;
|
||||
|
||||
|
||||
void InitFilters()
|
||||
{
|
||||
_numUnusedFilters = 0;
|
||||
_filters.Clear();
|
||||
}
|
||||
|
||||
void DeleteUnusedFilters()
|
||||
{
|
||||
if (_numUnusedFilters != 0)
|
||||
{
|
||||
_filters.DeleteFrontal(_numUnusedFilters);
|
||||
_numUnusedFilters = 0;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT WriteData(const Byte *data, size_t size);
|
||||
HRESULT ExecuteFilter(const CFilter &f);
|
||||
HRESULT WriteBuf();
|
||||
HRESULT AddFilter(CBitDecoder &_bitStream);
|
||||
|
||||
HRESULT ReadTables(CBitDecoder &_bitStream);
|
||||
HRESULT DecodeLZ();
|
||||
HRESULT CodeReal();
|
||||
|
||||
public:
|
||||
CDecoder();
|
||||
~CDecoder();
|
||||
|
||||
MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
|
||||
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -7,12 +7,14 @@
|
||||
#include "Rar1Decoder.h"
|
||||
#include "Rar2Decoder.h"
|
||||
#include "Rar3Decoder.h"
|
||||
#include "Rar5Decoder.h"
|
||||
|
||||
#define CREATE_CODEC(x) REGISTER_CODEC_CREATE(CreateCodec ## x, NCompress::NRar ## x::CDecoder())
|
||||
|
||||
CREATE_CODEC(1)
|
||||
CREATE_CODEC(2)
|
||||
CREATE_CODEC(3)
|
||||
CREATE_CODEC(5)
|
||||
|
||||
#define RAR_CODEC(x, name) { CreateCodec ## x, NULL, 0x40300 + x, "Rar" name, 1, false }
|
||||
|
||||
@@ -21,6 +23,7 @@ REGISTER_CODECS_VAR
|
||||
RAR_CODEC(1, "1"),
|
||||
RAR_CODEC(2, "2"),
|
||||
RAR_CODEC(3, "3"),
|
||||
RAR_CODEC(5, "5"),
|
||||
};
|
||||
|
||||
REGISTER_CODECS(Rar)
|
||||
|
||||
62
CPP/7zip/Crypto/HmacSha256.cpp
Normal file
62
CPP/7zip/Crypto/HmacSha256.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
// HmacSha256.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "HmacSha256.h"
|
||||
|
||||
namespace NCrypto {
|
||||
namespace NSha256 {
|
||||
|
||||
static const unsigned kBlockSize = 64;
|
||||
|
||||
void CHmac::SetKey(const Byte *key, size_t keySize)
|
||||
{
|
||||
Byte temp[kBlockSize];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < kBlockSize; i++)
|
||||
temp[i] = 0;
|
||||
|
||||
if (keySize > kBlockSize)
|
||||
{
|
||||
Sha256_Init(&_sha);
|
||||
Sha256_Update(&_sha, key, keySize);
|
||||
Sha256_Final(&_sha, temp);
|
||||
}
|
||||
else
|
||||
for (i = 0; i < keySize; i++)
|
||||
temp[i] = key[i];
|
||||
|
||||
for (i = 0; i < kBlockSize; i++)
|
||||
temp[i] ^= 0x36;
|
||||
|
||||
Sha256_Init(&_sha);
|
||||
Sha256_Update(&_sha, temp, kBlockSize);
|
||||
|
||||
for (i = 0; i < kBlockSize; i++)
|
||||
temp[i] ^= 0x36 ^ 0x5C;
|
||||
|
||||
Sha256_Init(&_sha2);
|
||||
Sha256_Update(&_sha2, temp, kBlockSize);
|
||||
}
|
||||
|
||||
void CHmac::Final(Byte *mac)
|
||||
{
|
||||
Sha256_Final(&_sha, mac);
|
||||
Sha256_Update(&_sha2, mac, SHA256_DIGEST_SIZE);
|
||||
Sha256_Final(&_sha2, mac);
|
||||
}
|
||||
|
||||
/*
|
||||
void CHmac::Final(Byte *mac, size_t macSize)
|
||||
{
|
||||
Byte digest[SHA256_DIGEST_SIZE];
|
||||
Final(digest);
|
||||
for (size_t i = 0; i < macSize; i++)
|
||||
mac[i] = digest[i];
|
||||
}
|
||||
*/
|
||||
|
||||
}}
|
||||
27
CPP/7zip/Crypto/HmacSha256.h
Normal file
27
CPP/7zip/Crypto/HmacSha256.h
Normal file
@@ -0,0 +1,27 @@
|
||||
// HmacSha256.h
|
||||
// Implements HMAC-SHA-256 (RFC2104, FIPS-198)
|
||||
|
||||
#ifndef __CRYPTO_HMAC_SHA256_H
|
||||
#define __CRYPTO_HMAC_SHA256_H
|
||||
|
||||
#include "../../../C/Sha256.h"
|
||||
|
||||
namespace NCrypto {
|
||||
namespace NSha256 {
|
||||
|
||||
const unsigned kDigestSize = SHA256_DIGEST_SIZE;
|
||||
|
||||
class CHmac
|
||||
{
|
||||
CSha256 _sha;
|
||||
CSha256 _sha2;
|
||||
public:
|
||||
void SetKey(const Byte *key, size_t keySize);
|
||||
void Update(const Byte *data, size_t dataSize) { Sha256_Update(&_sha, data, dataSize); }
|
||||
void Final(Byte *mac);
|
||||
// void Final(Byte *mac, size_t macSize);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "Rar20Crypto.h"
|
||||
|
||||
namespace NCrypto {
|
||||
namespace NRar20 {
|
||||
namespace NRar2 {
|
||||
|
||||
static const unsigned kNumRounds = 32;
|
||||
|
||||
@@ -39,44 +39,48 @@ void CData::UpdateKeys(const Byte *data)
|
||||
Keys[j] ^= g_CrcTable[data[i + j]];
|
||||
}
|
||||
|
||||
static void Swap(Byte *b1, Byte *b2)
|
||||
static inline void Swap(Byte &b1, Byte &b2)
|
||||
{
|
||||
Byte b = *b1;
|
||||
*b1 = *b2;
|
||||
*b2 = b;
|
||||
Byte b = b1;
|
||||
b1 = b2;
|
||||
b2 = b;
|
||||
}
|
||||
|
||||
void CData::SetPassword(const Byte *data, UInt32 size)
|
||||
void CData::SetPassword(const Byte *data, unsigned size)
|
||||
{
|
||||
Keys[0] = 0xD3A3B879L;
|
||||
Keys[1] = 0x3F6D12F7L;
|
||||
Keys[2] = 0x7515A235L;
|
||||
Keys[3] = 0xA4E7F123L;
|
||||
|
||||
Byte psw[256];
|
||||
if (size >= sizeof(psw))
|
||||
size = sizeof(psw) - 1;
|
||||
Byte psw[128];
|
||||
memset(psw, 0, sizeof(psw));
|
||||
if (size != 0)
|
||||
{
|
||||
if (size >= sizeof(psw))
|
||||
size = sizeof(psw) - 1;
|
||||
memcpy(psw, data, size);
|
||||
}
|
||||
|
||||
memcpy(SubstTable, g_InitSubstTable, sizeof(SubstTable));
|
||||
|
||||
for (UInt32 j = 0; j < 256; j++)
|
||||
for (UInt32 i = 0; i < size; i += 2)
|
||||
for (unsigned j = 0; j < 256; j++)
|
||||
for (unsigned i = 0; i < size; i += 2)
|
||||
{
|
||||
UInt32 n2 = (Byte)g_CrcTable[(psw[i + 1] + j) & 0xFF];
|
||||
UInt32 n1 = (Byte)g_CrcTable[(psw[i] - j) & 0xFF];
|
||||
for (UInt32 k = 1; (n1 & 0xFF) != n2; n1++, k++)
|
||||
Swap(&SubstTable[n1 & 0xFF], &SubstTable[(n1 + i + k) & 0xFF]);
|
||||
unsigned n1 = (Byte)g_CrcTable[(psw[i] - j) & 0xFF];
|
||||
unsigned n2 = (Byte)g_CrcTable[(psw[i + 1] + j) & 0xFF];
|
||||
for (unsigned k = 1; (n1 & 0xFF) != n2; n1++, k++)
|
||||
Swap(SubstTable[n1 & 0xFF], SubstTable[(n1 + i + k) & 0xFF]);
|
||||
}
|
||||
for (UInt32 i = 0; i < size; i += 16)
|
||||
EncryptBlock(&psw[i]);
|
||||
|
||||
for (unsigned i = 0; i < size; i += 16)
|
||||
EncryptBlock(psw + i);
|
||||
}
|
||||
|
||||
void CData::CryptBlock(Byte *buf, bool encrypt)
|
||||
{
|
||||
Byte inBuf[16];
|
||||
UInt32 A, B, C, D, T, TA, TB;
|
||||
UInt32 A, B, C, D;
|
||||
|
||||
A = GetUi32(buf + 0) ^ Keys[0];
|
||||
B = GetUi32(buf + 4) ^ Keys[1];
|
||||
@@ -89,14 +93,10 @@ void CData::CryptBlock(Byte *buf, bool encrypt)
|
||||
for (unsigned i = 0; i < kNumRounds; i++)
|
||||
{
|
||||
UInt32 key = Keys[(encrypt ? i : (kNumRounds - 1 - i)) & 3];
|
||||
T = ((C + rotlFixed(D, 11)) ^ key);
|
||||
TA = A ^ SubstLong(T);
|
||||
T = ((D ^ rotlFixed(C, 17)) + key);
|
||||
TB = B ^ SubstLong(T);
|
||||
A = C;
|
||||
B = D;
|
||||
C = TA;
|
||||
D = TB;
|
||||
UInt32 TA = A ^ SubstLong((C + rotlFixed(D, 11)) ^ key);
|
||||
UInt32 TB = B ^ SubstLong((D ^ rotlFixed(C, 17)) + key);
|
||||
A = C; C = TA;
|
||||
B = D; D = TB;
|
||||
}
|
||||
|
||||
SetUi32(buf + 0, C ^ Keys[0]);
|
||||
@@ -107,12 +107,6 @@ void CData::CryptBlock(Byte *buf, bool encrypt)
|
||||
UpdateKeys(encrypt ? buf : inBuf);
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size)
|
||||
{
|
||||
_cipher.SetPassword(data, size);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::Init()
|
||||
{
|
||||
return S_OK;
|
||||
@@ -126,10 +120,10 @@ STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)
|
||||
return 0;
|
||||
if (size < kBlockSize)
|
||||
return kBlockSize;
|
||||
UInt32 i;
|
||||
size -= kBlockSize;
|
||||
UInt32 i;
|
||||
for (i = 0; i <= size; i += kBlockSize)
|
||||
_cipher.DecryptBlock(data + i);
|
||||
DecryptBlock(data + i);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,13 +6,12 @@
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
#include "../IPassword.h"
|
||||
|
||||
namespace NCrypto {
|
||||
namespace NRar20 {
|
||||
namespace NRar2 {
|
||||
|
||||
/* ICompressFilter::Init() does nothing for this filter.
|
||||
Call CryptoSetPassword() to initialize filter. */
|
||||
Call SetPassword() to initialize filter. */
|
||||
|
||||
class CData
|
||||
{
|
||||
@@ -31,22 +30,17 @@ class CData
|
||||
public:
|
||||
void EncryptBlock(Byte *buf) { CryptBlock(buf, true); }
|
||||
void DecryptBlock(Byte *buf) { CryptBlock(buf, false); }
|
||||
void SetPassword(const Byte *password, UInt32 passwordLen);
|
||||
void SetPassword(const Byte *password, unsigned passwordLen);
|
||||
};
|
||||
|
||||
class CDecoder:
|
||||
public ICompressFilter,
|
||||
public ICryptoSetPassword,
|
||||
public CMyUnknownImp,
|
||||
public CData
|
||||
{
|
||||
CData _cipher;
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(ICryptoSetPassword)
|
||||
|
||||
STDMETHOD(Init)();
|
||||
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
|
||||
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
|
||||
MY_UNKNOWN_IMP
|
||||
INTERFACE_ICompressFilter(;)
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
257
CPP/7zip/Crypto/Rar5Aes.cpp
Normal file
257
CPP/7zip/Crypto/Rar5Aes.cpp
Normal file
@@ -0,0 +1,257 @@
|
||||
// Crypto/Rar5Aes.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
#include "../../Windows/Synchronization.h"
|
||||
#endif
|
||||
|
||||
#include "Rar5Aes.h"
|
||||
|
||||
namespace NCrypto {
|
||||
namespace NRar5 {
|
||||
|
||||
static const unsigned kNumIterationsLog_Max = 24;
|
||||
|
||||
static const unsigned kPswCheckCsumSize = 4;
|
||||
static const unsigned kCheckSize = kPswCheckSize + kPswCheckCsumSize;
|
||||
|
||||
CKey::CKey():
|
||||
_needCalc(true),
|
||||
_numIterationsLog(0)
|
||||
{
|
||||
for (unsigned i = 0; i < sizeof(_salt); i++)
|
||||
_salt[i] = 0;
|
||||
}
|
||||
|
||||
CDecoder::CDecoder(): CAesCbcDecoder(kAesKeySize) {}
|
||||
|
||||
static unsigned ReadVarInt(const Byte *p, unsigned maxSize, UInt64 *val)
|
||||
{
|
||||
unsigned i;
|
||||
*val = 0;
|
||||
|
||||
for (i = 0; i < maxSize;)
|
||||
{
|
||||
Byte b = p[i];
|
||||
if (i < 10)
|
||||
*val |= (UInt64)(b & 0x7F) << (7 * i++);
|
||||
if ((b & 0x80) == 0)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
HRESULT CDecoder::SetDecoderProps(const Byte *p, unsigned size, bool includeIV, bool isService)
|
||||
{
|
||||
UInt64 Version;
|
||||
|
||||
unsigned num = ReadVarInt(p, size, &Version);
|
||||
if (num == 0)
|
||||
return E_NOTIMPL;
|
||||
p += num;
|
||||
size -= num;
|
||||
|
||||
if (Version != 0)
|
||||
return E_NOTIMPL;
|
||||
|
||||
num = ReadVarInt(p, size, &Flags);
|
||||
if (num == 0)
|
||||
return E_NOTIMPL;
|
||||
p += num;
|
||||
size -= num;
|
||||
|
||||
bool isCheck = IsThereCheck();
|
||||
if (size != 1 + kSaltSize + (includeIV ? AES_BLOCK_SIZE : 0) + (unsigned)(isCheck ? kCheckSize : 0))
|
||||
return E_NOTIMPL;
|
||||
|
||||
if (_numIterationsLog != p[0])
|
||||
{
|
||||
_numIterationsLog = p[0];
|
||||
_needCalc = true;
|
||||
}
|
||||
|
||||
p++;
|
||||
|
||||
if (memcmp(_salt, p, kSaltSize) != 0)
|
||||
{
|
||||
memcpy(_salt, p, kSaltSize);
|
||||
_needCalc = true;
|
||||
}
|
||||
|
||||
p += kSaltSize;
|
||||
|
||||
if (includeIV)
|
||||
{
|
||||
memcpy(_iv, p, AES_BLOCK_SIZE);
|
||||
p += AES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
_canCheck = true;
|
||||
|
||||
if (isCheck)
|
||||
{
|
||||
memcpy(_check, p, kPswCheckSize);
|
||||
CSha256 sha;
|
||||
Byte digest[SHA256_DIGEST_SIZE];
|
||||
Sha256_Init(&sha);
|
||||
Sha256_Update(&sha, _check, kPswCheckSize);
|
||||
Sha256_Final(&sha, digest);
|
||||
_canCheck = (memcmp(digest, p + kPswCheckSize, kPswCheckCsumSize) == 0);
|
||||
if (_canCheck && isService)
|
||||
{
|
||||
// There was bug in RAR 5.21- : PswCheck field in service records ("QO") contained zeros.
|
||||
// so we disable password checking for such bad records.
|
||||
_canCheck = false;
|
||||
for (unsigned i = 0; i < kPswCheckSize; i++)
|
||||
if (p[i] != 0)
|
||||
{
|
||||
_canCheck = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (_numIterationsLog <= kNumIterationsLog_Max ? S_OK : E_NOTIMPL);
|
||||
}
|
||||
|
||||
|
||||
void CDecoder::SetPassword(const Byte *data, size_t size)
|
||||
{
|
||||
if (size != _password.Size() || memcmp(data, _password, size) != 0)
|
||||
{
|
||||
_needCalc = true;
|
||||
_password.CopyFrom(data, size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::Init()
|
||||
{
|
||||
CalcKey_and_CheckPassword();
|
||||
RINOK(SetKey(_key, kAesKeySize));
|
||||
RINOK(SetInitVector(_iv, AES_BLOCK_SIZE));
|
||||
return CAesCbcCoder::Init();
|
||||
}
|
||||
|
||||
|
||||
UInt32 CDecoder::Hmac_Convert_Crc32(UInt32 crc) const
|
||||
{
|
||||
NSha256::CHmac ctx;
|
||||
ctx.SetKey(_hashKey, NSha256::kDigestSize);
|
||||
Byte v[4];
|
||||
SetUi32(v, crc);
|
||||
ctx.Update(v, 4);
|
||||
Byte h[NSha256::kDigestSize];
|
||||
ctx.Final(h);
|
||||
crc = 0;
|
||||
for (unsigned i = 0; i < NSha256::kDigestSize; i++)
|
||||
crc ^= (UInt32)h[i] << ((i & 3) * 8);
|
||||
return crc;
|
||||
};
|
||||
|
||||
|
||||
void CDecoder::Hmac_Convert_32Bytes(Byte *data) const
|
||||
{
|
||||
NSha256::CHmac ctx;
|
||||
ctx.SetKey(_hashKey, NSha256::kDigestSize);
|
||||
ctx.Update(data, NSha256::kDigestSize);
|
||||
ctx.Final(data);
|
||||
};
|
||||
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
static CKey g_Key;
|
||||
static NWindows::NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection;
|
||||
#define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection);
|
||||
#else
|
||||
#define MT_LOCK
|
||||
#endif
|
||||
|
||||
bool CDecoder::CalcKey_and_CheckPassword()
|
||||
{
|
||||
if (_needCalc)
|
||||
{
|
||||
{
|
||||
MT_LOCK
|
||||
if (!g_Key._needCalc && IsKeyEqualTo(g_Key))
|
||||
{
|
||||
CopyCalcedKeysFrom(g_Key);
|
||||
_needCalc = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (_needCalc)
|
||||
{
|
||||
Byte pswCheck[SHA256_DIGEST_SIZE];
|
||||
|
||||
{
|
||||
// Pbkdf HMAC-SHA-256
|
||||
|
||||
NSha256::CHmac baseCtx;
|
||||
baseCtx.SetKey(_password, _password.Size());
|
||||
|
||||
NSha256::CHmac ctx = baseCtx;
|
||||
ctx.Update(_salt, sizeof(_salt));
|
||||
|
||||
Byte u[NSha256::kDigestSize];
|
||||
Byte key[NSha256::kDigestSize];
|
||||
|
||||
u[0] = 0;
|
||||
u[1] = 0;
|
||||
u[2] = 0;
|
||||
u[3] = 1;
|
||||
|
||||
ctx.Update(u, 4);
|
||||
ctx.Final(u);
|
||||
|
||||
memcpy(key, u, NSha256::kDigestSize);
|
||||
|
||||
UInt32 numIterations = ((UInt32)1 << _numIterationsLog) - 1;
|
||||
|
||||
for (unsigned i = 0; i < 3; i++)
|
||||
{
|
||||
UInt32 j = numIterations;
|
||||
|
||||
for (; j != 0; j--)
|
||||
{
|
||||
ctx = baseCtx;
|
||||
ctx.Update(u, NSha256::kDigestSize);
|
||||
ctx.Final(u);
|
||||
for (unsigned s = 0; s < NSha256::kDigestSize; s++)
|
||||
key[s] ^= u[s];
|
||||
}
|
||||
|
||||
// RAR uses additional iterations for additional keys
|
||||
memcpy((i == 0 ? _key : (i == 1 ? _hashKey : pswCheck)), key, NSha256::kDigestSize);
|
||||
numIterations = 16;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < kPswCheckSize; i++)
|
||||
_check_Calced[i] = pswCheck[i];
|
||||
|
||||
for (i = kPswCheckSize; i < SHA256_DIGEST_SIZE; i++)
|
||||
_check_Calced[i & (kPswCheckSize - 1)] ^= pswCheck[i];
|
||||
}
|
||||
|
||||
_needCalc = false;
|
||||
|
||||
{
|
||||
MT_LOCK
|
||||
g_Key = *this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsThereCheck() && _canCheck)
|
||||
return (memcmp(_check_Calced, _check, kPswCheckSize) == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
}}
|
||||
84
CPP/7zip/Crypto/Rar5Aes.h
Normal file
84
CPP/7zip/Crypto/Rar5Aes.h
Normal file
@@ -0,0 +1,84 @@
|
||||
// Crypto/Rar5Aes.h
|
||||
|
||||
#ifndef __CRYPTO_RAR5_AES_H
|
||||
#define __CRYPTO_RAR5_AES_H
|
||||
|
||||
#include "../../../C/Aes.h"
|
||||
|
||||
#include "../../Common/MyBuffer.h"
|
||||
|
||||
#include "HmacSha256.h"
|
||||
#include "MyAes.h"
|
||||
|
||||
namespace NCrypto {
|
||||
namespace NRar5 {
|
||||
|
||||
const unsigned kSaltSize = 16;
|
||||
const unsigned kPswCheckSize = 8;
|
||||
const unsigned kAesKeySize = 32;
|
||||
|
||||
namespace NCryptoFlags
|
||||
{
|
||||
const unsigned kPswCheck = 1 << 0;
|
||||
const unsigned kUseMAC = 1 << 1;
|
||||
}
|
||||
|
||||
struct CKey
|
||||
{
|
||||
bool _needCalc;
|
||||
|
||||
unsigned _numIterationsLog;
|
||||
Byte _salt[kSaltSize];
|
||||
CByteBuffer _password;
|
||||
|
||||
Byte _key[kAesKeySize];
|
||||
Byte _check_Calced[kPswCheckSize];
|
||||
Byte _hashKey[SHA256_DIGEST_SIZE];
|
||||
|
||||
void CopyCalcedKeysFrom(const CKey &k)
|
||||
{
|
||||
memcpy(_key, k._key, sizeof(_key));
|
||||
memcpy(_check_Calced, k._check_Calced, sizeof(_check_Calced));
|
||||
memcpy(_hashKey, k._hashKey, sizeof(_hashKey));
|
||||
}
|
||||
|
||||
bool IsKeyEqualTo(const CKey &key)
|
||||
{
|
||||
return (_numIterationsLog == key._numIterationsLog
|
||||
&& memcmp(_salt, key._salt, sizeof(_salt)) == 0
|
||||
&& _password == key._password);
|
||||
}
|
||||
|
||||
CKey();
|
||||
};
|
||||
|
||||
|
||||
class CDecoder:
|
||||
public CAesCbcDecoder,
|
||||
public CKey
|
||||
{
|
||||
Byte _check[kPswCheckSize];
|
||||
bool _canCheck;
|
||||
UInt64 Flags;
|
||||
|
||||
bool IsThereCheck() const { return ((Flags & NCryptoFlags::kPswCheck) != 0); }
|
||||
public:
|
||||
Byte _iv[AES_BLOCK_SIZE];
|
||||
|
||||
CDecoder();
|
||||
|
||||
STDMETHOD(Init)();
|
||||
|
||||
void SetPassword(const Byte *data, size_t size);
|
||||
HRESULT SetDecoderProps(const Byte *data, unsigned size, bool includeIV, bool isService);
|
||||
|
||||
bool CalcKey_and_CheckPassword();
|
||||
|
||||
bool UseMAC() const { return (Flags & NCryptoFlags::kUseMAC) != 0; }
|
||||
UInt32 Hmac_Convert_Crc32(UInt32 crc) const;
|
||||
void Hmac_Convert_32Bytes(Byte *data) const;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,4 @@
|
||||
// Crypto/RarAes.cpp
|
||||
// Note: you must include MyAes.cpp to project to initialize AES tables
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
@@ -7,10 +6,10 @@
|
||||
#include "Sha1Cls.h"
|
||||
|
||||
namespace NCrypto {
|
||||
namespace NRar29 {
|
||||
namespace NRar3 {
|
||||
|
||||
CDecoder::CDecoder():
|
||||
CAesCbcDecoder(kRarAesKeySize),
|
||||
CAesCbcDecoder(kAesKeySize),
|
||||
_thereIsSalt(false),
|
||||
_needCalc(true),
|
||||
_rar350Mode(false)
|
||||
@@ -19,7 +18,7 @@ CDecoder::CDecoder():
|
||||
_salt[i] = 0;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
||||
HRESULT CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
||||
{
|
||||
bool prev = _thereIsSalt;
|
||||
_thereIsSalt = false;
|
||||
@@ -53,12 +52,12 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const unsigned kPasswordLen_MAX = 127 * 2;
|
||||
static const unsigned kPasswordLen_Bytes_MAX = 127 * 2;
|
||||
|
||||
STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size)
|
||||
void CDecoder::SetPassword(const Byte *data, unsigned size)
|
||||
{
|
||||
if (size > kPasswordLen_MAX)
|
||||
size = kPasswordLen_MAX;
|
||||
if (size > kPasswordLen_Bytes_MAX)
|
||||
size = kPasswordLen_Bytes_MAX;
|
||||
bool same = false;
|
||||
if (size == _password.Size())
|
||||
{
|
||||
@@ -73,13 +72,12 @@ STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size)
|
||||
if (!_needCalc && !same)
|
||||
_needCalc = true;
|
||||
_password.CopyFrom(data, (size_t)size);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::Init()
|
||||
{
|
||||
CalcKey();
|
||||
RINOK(SetKey(_key, kRarAesKeySize));
|
||||
RINOK(SetKey(_key, kAesKeySize));
|
||||
RINOK(SetInitVector(_iv, AES_BLOCK_SIZE));
|
||||
return CAesCbcCoder::Init();
|
||||
}
|
||||
@@ -91,7 +89,7 @@ void CDecoder::CalcKey()
|
||||
|
||||
const unsigned kSaltSize = 8;
|
||||
|
||||
Byte buf[kPasswordLen_MAX + kSaltSize];
|
||||
Byte buf[kPasswordLen_Bytes_MAX + kSaltSize];
|
||||
|
||||
if (_password.Size() != 0)
|
||||
memcpy(buf, _password, _password.Size());
|
||||
@@ -109,7 +107,7 @@ void CDecoder::CalcKey()
|
||||
|
||||
Byte digest[NSha1::kDigestSize];
|
||||
// rar reverts hash for sha.
|
||||
const UInt32 kNumRounds = (1 << 18);
|
||||
const UInt32 kNumRounds = ((UInt32)1 << 18);
|
||||
UInt32 i;
|
||||
for (i = 0; i < kNumRounds; i++)
|
||||
{
|
||||
|
||||
@@ -12,14 +12,14 @@
|
||||
#include "MyAes.h"
|
||||
|
||||
namespace NCrypto {
|
||||
namespace NRar29 {
|
||||
namespace NRar3 {
|
||||
|
||||
const UInt32 kRarAesKeySize = 16;
|
||||
const unsigned kAesKeySize = 16;
|
||||
|
||||
class CDecoder:
|
||||
public CAesCbcDecoder,
|
||||
public CAesCbcDecoder
|
||||
// public ICompressSetDecoderProperties2,
|
||||
public ICryptoSetPassword
|
||||
// public ICryptoSetPassword
|
||||
{
|
||||
Byte _salt[8];
|
||||
bool _thereIsSalt;
|
||||
@@ -28,17 +28,20 @@ class CDecoder:
|
||||
|
||||
CByteBuffer _password;
|
||||
|
||||
Byte _key[kRarAesKeySize];
|
||||
Byte _key[kAesKeySize];
|
||||
Byte _iv[AES_BLOCK_SIZE];
|
||||
|
||||
void CalcKey();
|
||||
public:
|
||||
/*
|
||||
MY_UNKNOWN_IMP1(
|
||||
ICryptoSetPassword)
|
||||
ICryptoSetPassword
|
||||
// ICompressSetDecoderProperties2
|
||||
*/
|
||||
STDMETHOD(Init)();
|
||||
STDMETHOD(CryptoSetPassword)(const Byte *aData, UInt32 aSize);
|
||||
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
|
||||
|
||||
void SetPassword(const Byte *data, unsigned size);
|
||||
HRESULT SetDecoderProperties2(const Byte *data, UInt32 size);
|
||||
|
||||
CDecoder();
|
||||
void SetRar350Mode(bool rar350Mode) { _rar350Mode = rar350Mode; }
|
||||
|
||||
@@ -163,6 +163,7 @@ Handler GUIDs:
|
||||
0C xz
|
||||
0D ppmd
|
||||
|
||||
CC Rar5
|
||||
CD IHex
|
||||
CE Hxs
|
||||
CF TE
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#define __IPROGRESS_H
|
||||
|
||||
#include "../Common/MyTypes.h"
|
||||
#include "../Common/MyUnknown.h"
|
||||
|
||||
#include "IDecl.h"
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#define __ISTREAM_H
|
||||
|
||||
#include "../Common/MyTypes.h"
|
||||
#include "../Common/MyUnknown.h"
|
||||
#include "../Common/MyWindows.h"
|
||||
|
||||
#include "IDecl.h"
|
||||
|
||||
|
||||
@@ -102,6 +102,7 @@ enum
|
||||
kpidStreamId,
|
||||
kpidReadOnly,
|
||||
kpidOutName,
|
||||
kpidCopyLink,
|
||||
|
||||
kpid_NUM_DEFINED,
|
||||
|
||||
|
||||
@@ -380,6 +380,21 @@ STDMETHODIMP CAgent::DoOperation(
|
||||
HRESULT res = outArchive->UpdateItems(outArchiveStream, updatePairs2.Size(), updateCallback);
|
||||
if (res == S_OK && processedPaths)
|
||||
{
|
||||
{
|
||||
/* OutHandler for 7z archives doesn't report compression operation for empty files.
|
||||
So we must include these files manually */
|
||||
FOR_VECTOR(i, updatePairs2)
|
||||
{
|
||||
const CUpdatePair2 &up = updatePairs2[i];
|
||||
if (up.DirIndex >= 0 && up.NewData)
|
||||
{
|
||||
const CDirItem &di = dirItems.Items[up.DirIndex];
|
||||
if (!di.IsDir() && di.Size == 0)
|
||||
processedItems[up.DirIndex] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FOR_VECTOR (i, dirItems.Items)
|
||||
if (processedItems[i] != 0)
|
||||
processedPaths->Add(dirItems.GetPhyPath(i));
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
|
||||
#include "../../../Common/Defs.h"
|
||||
#include "../../../Common/MyInitGuid.h"
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#undef sprintf
|
||||
#undef printf
|
||||
|
||||
#include "../../../../C/Alloc.h"
|
||||
|
||||
#include "../../../Common/ComTry.h"
|
||||
#include "../../../Common/IntToString.h"
|
||||
#include "../../../Common/StringConvert.h"
|
||||
@@ -23,6 +25,7 @@
|
||||
#endif
|
||||
|
||||
#include "../../Common/FilePathAutoRename.h"
|
||||
// #include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "../Common/ExtractingFilePath.h"
|
||||
#include "../Common/PropIDUtils.h"
|
||||
@@ -541,11 +544,54 @@ static FString MakePath_from_2_Parts(const FString &prefix, const FString &path)
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
#ifdef SUPPORT_LINKS
|
||||
|
||||
struct CTempMidBuffer
|
||||
{
|
||||
void *Buf;
|
||||
|
||||
CTempMidBuffer(size_t size): Buf(NULL) { Buf = ::MidAlloc(size); }
|
||||
~CTempMidBuffer() { ::MidFree(Buf); }
|
||||
};
|
||||
|
||||
HRESULT CArchiveExtractCallback::MyCopyFile(ISequentialOutStream *outStream)
|
||||
{
|
||||
const size_t kBufSize = 1 << 16;
|
||||
CTempMidBuffer buf(kBufSize);
|
||||
if (!buf.Buf)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
NIO::CInFile inFile;
|
||||
NIO::COutFile outFile;
|
||||
|
||||
if (!inFile.Open(_CopyFile_Path))
|
||||
return SendMessageError_with_LastError("Open error", _CopyFile_Path);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
UInt32 num;
|
||||
|
||||
if (!inFile.Read(buf.Buf, kBufSize, num))
|
||||
return SendMessageError_with_LastError("Read error", _CopyFile_Path);
|
||||
|
||||
if (num == 0)
|
||||
return S_OK;
|
||||
|
||||
|
||||
RINOK(WriteStream(outStream, buf.Buf, num));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
*/
|
||||
|
||||
STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
*outStream = 0;
|
||||
*outStream = NULL;
|
||||
|
||||
#ifndef _SFX
|
||||
if (_hashStream)
|
||||
@@ -563,6 +609,11 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
|
||||
_curSizeDefined = false;
|
||||
_index = index;
|
||||
|
||||
#ifdef SUPPORT_LINKS
|
||||
// _CopyFile_Path.Empty();
|
||||
linkPath.Empty();
|
||||
#endif
|
||||
|
||||
IInArchive *archive = _arc->Archive;
|
||||
|
||||
#ifndef _SFX
|
||||
@@ -596,46 +647,56 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
|
||||
|
||||
#ifdef SUPPORT_LINKS
|
||||
|
||||
// bool isCopyLink = false;
|
||||
bool isHardLink = false;
|
||||
bool isJunction = false;
|
||||
bool isRelative = false;
|
||||
|
||||
UString linkPath;
|
||||
// RINOK(Archive_GetItemBoolProp(archive, index, kpidIsHardLink, isHardLink));
|
||||
// if (isHardLink)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(archive->GetProperty(index, kpidHardLink, &prop));
|
||||
if (prop.vt == VT_BSTR)
|
||||
{
|
||||
isHardLink = true;
|
||||
// isCopyLink = false;
|
||||
isRelative = false; // RAR5, TAR: hard links are from root folder of archive
|
||||
linkPath.SetFromBstr(prop.bstrVal);
|
||||
isRelative = false; // TAR: hard links are from root folder of archive
|
||||
}
|
||||
else if (prop.vt == VT_EMPTY)
|
||||
{
|
||||
// linkPath.Empty();
|
||||
}
|
||||
else
|
||||
else if (prop.vt != VT_EMPTY)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(archive->GetProperty(index, kpidCopyLink, &prop));
|
||||
if (prop.vt == VT_BSTR)
|
||||
{
|
||||
isHardLink = false;
|
||||
isCopyLink = true;
|
||||
isRelative = false; // RAR5: copy links are from root folder of archive
|
||||
linkPath.SetFromBstr(prop.bstrVal);
|
||||
}
|
||||
else if (prop.vt != VT_EMPTY)
|
||||
return E_FAIL;
|
||||
}
|
||||
*/
|
||||
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(archive->GetProperty(index, kpidSymLink, &prop));
|
||||
if (prop.vt == VT_BSTR)
|
||||
{
|
||||
isHardLink = false;
|
||||
// isCopyLink = false;
|
||||
isRelative = true; // RAR5, TAR: symbolic links can be relative
|
||||
linkPath.SetFromBstr(prop.bstrVal);
|
||||
isRelative = true; // TAR: symbolic links are relative
|
||||
}
|
||||
else if (prop.vt == VT_EMPTY)
|
||||
{
|
||||
// linkPath.Empty();
|
||||
}
|
||||
else
|
||||
else if (prop.vt != VT_EMPTY)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
||||
bool isOkReparse = false;
|
||||
|
||||
if (linkPath.IsEmpty() && _arc->GetRawProps)
|
||||
@@ -643,7 +704,9 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
|
||||
const void *data;
|
||||
UInt32 dataSize;
|
||||
UInt32 propType;
|
||||
|
||||
_arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType);
|
||||
|
||||
if (dataSize != 0)
|
||||
{
|
||||
if (propType != NPropDataType::kRaw)
|
||||
@@ -654,6 +717,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
|
||||
if (isOkReparse)
|
||||
{
|
||||
isHardLink = false;
|
||||
// isCopyLink = false;
|
||||
linkPath = reparse.GetPath();
|
||||
isJunction = reparse.IsMountPoint();
|
||||
isRelative = reparse.IsRelative();
|
||||
@@ -670,6 +734,13 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
|
||||
linkPath.Replace(L'/', WCHAR_PATH_SEPARATOR);
|
||||
#endif
|
||||
|
||||
// rar5 uses "\??\" prefix for absolute links
|
||||
if (linkPath.IsPrefixedBy(WSTRING_PATH_SEPARATOR L"??" WSTRING_PATH_SEPARATOR))
|
||||
{
|
||||
isRelative = false;
|
||||
linkPath.DeleteFrontal(4);
|
||||
}
|
||||
|
||||
for (;;)
|
||||
// while (NName::IsAbsolutePath(linkPath))
|
||||
{
|
||||
@@ -1108,7 +1179,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
|
||||
else
|
||||
{
|
||||
FString existPath;
|
||||
if (isHardLink || !isRelative)
|
||||
if (isHardLink /* || isCopyLink */ || !isRelative)
|
||||
{
|
||||
if (!NName::GetFullPath(_dirPathPrefix_Full, us2fs(relatPath), existPath))
|
||||
{
|
||||
@@ -1122,7 +1193,9 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
|
||||
|
||||
if (!existPath.IsEmpty())
|
||||
{
|
||||
if (isHardLink)
|
||||
if (isHardLink /* || isCopyLink */)
|
||||
{
|
||||
// if (isHardLink)
|
||||
{
|
||||
if (!MyCreateHardLink(fullProcessedPath, existPath))
|
||||
{
|
||||
@@ -1130,6 +1203,28 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
|
||||
// return S_OK;
|
||||
}
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
NFind::CFileInfo fi;
|
||||
if (!fi.Find(existPath))
|
||||
{
|
||||
RINOK(SendMessageError2("Can not find the file for copying", existPath, fullProcessedPath));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_curSizeDefined && _curSize == fi.Size)
|
||||
_CopyFile_Path = existPath;
|
||||
else
|
||||
{
|
||||
RINOK(SendMessageError2("File size collision for file copying", existPath, fullProcessedPath));
|
||||
}
|
||||
|
||||
// RINOK(MyCopyFile(existPath, fullProcessedPath));
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
else if (_ntOptions.SymLinks.Val)
|
||||
{
|
||||
// bool isSymLink = true; // = false for junction
|
||||
@@ -1161,7 +1256,8 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
|
||||
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
||||
if (linkPath.IsEmpty() /* || !_CopyFile_Path.IsEmpty() */)
|
||||
#endif // SUPPORT_LINKS
|
||||
{
|
||||
bool needWriteFile = true;
|
||||
@@ -1225,6 +1321,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
|
||||
{
|
||||
RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
|
||||
_outFileStream = outStreamLoc;
|
||||
}
|
||||
}
|
||||
@@ -1250,12 +1347,34 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
if (outStreamLoc)
|
||||
*outStream = outStreamLoc.Detach();
|
||||
{
|
||||
/*
|
||||
#ifdef SUPPORT_LINKS
|
||||
|
||||
if (!_CopyFile_Path.IsEmpty())
|
||||
{
|
||||
RINOK(PrepareOperation(askExtractMode));
|
||||
RINOK(MyCopyFile(outStreamLoc));
|
||||
return SetOperationResult(NArchive::NExtract::NOperationResult::kOK);
|
||||
}
|
||||
|
||||
if (isCopyLink && _testMode)
|
||||
return S_OK;
|
||||
|
||||
#endif
|
||||
*/
|
||||
|
||||
*outStream = outStreamLoc.Detach();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
@@ -1266,6 +1385,7 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
|
||||
#endif
|
||||
|
||||
_extractMode = false;
|
||||
|
||||
switch (askExtractMode)
|
||||
{
|
||||
case NArchive::NExtract::NAskMode::kExtract:
|
||||
@@ -1282,6 +1402,7 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
@@ -1346,6 +1467,7 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
|
||||
|
||||
if (!_curSizeDefined)
|
||||
GetUnpackSize();
|
||||
|
||||
if (_curSizeDefined)
|
||||
{
|
||||
#ifdef SUPPORT_ALT_STREAMS
|
||||
@@ -1367,8 +1489,11 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
|
||||
|
||||
if (_extractMode && _fi.AttribDefined)
|
||||
SetFileAttrib(_diskFilePath, _fi.Attrib);
|
||||
|
||||
RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted)));
|
||||
|
||||
return S_OK;
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
@@ -299,14 +299,23 @@ public:
|
||||
const UStringVector &removePathParts, bool removePartsForAltStreams,
|
||||
UInt64 packSize);
|
||||
|
||||
|
||||
#ifdef SUPPORT_LINKS
|
||||
|
||||
private:
|
||||
CHardLinks _hardLinks;
|
||||
UString linkPath;
|
||||
|
||||
// FString _CopyFile_Path;
|
||||
// HRESULT MyCopyFile(ISequentialOutStream *outStream);
|
||||
|
||||
public:
|
||||
// call PrepareHardLinks() after Init()
|
||||
HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices); // NULL means all items
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SUPPORT_ALT_STREAMS
|
||||
CObjectVector<CIndexToPathPair> _renamedFiles;
|
||||
#endif
|
||||
|
||||
@@ -48,18 +48,13 @@ class COpenCallbackImp:
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_QUERYINTERFACE_BEGIN2(IArchiveOpenVolumeCallback)
|
||||
MY_QUERYINTERFACE_ENTRY(IArchiveOpenSetSubArchiveName)
|
||||
#ifndef _NO_CRYPTO
|
||||
MY_UNKNOWN_IMP3(
|
||||
IArchiveOpenVolumeCallback,
|
||||
ICryptoGetTextPassword,
|
||||
IArchiveOpenSetSubArchiveName
|
||||
)
|
||||
#else
|
||||
MY_UNKNOWN_IMP2(
|
||||
IArchiveOpenVolumeCallback,
|
||||
IArchiveOpenSetSubArchiveName
|
||||
)
|
||||
MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
|
||||
#endif
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
INTERFACE_IArchiveOpenCallback(;)
|
||||
INTERFACE_IArchiveOpenVolumeCallback(;)
|
||||
@@ -93,7 +88,8 @@ public:
|
||||
CMyComPtr<IArchiveOpenCallback> ReOpenCallback;
|
||||
// UInt64 TotalSize;
|
||||
|
||||
COpenCallbackImp(): Callback(NULL) {}
|
||||
COpenCallbackImp(): Callback(NULL), _subArchiveMode(false) {}
|
||||
|
||||
void Init(const FString &folderPrefix, const FString &fileName)
|
||||
{
|
||||
_folderPrefix = folderPrefix;
|
||||
@@ -106,6 +102,7 @@ public:
|
||||
// TotalSize = 0;
|
||||
PasswordWasAsked = false;
|
||||
}
|
||||
|
||||
bool SetSecondFileInfo(CFSTR newName)
|
||||
{
|
||||
return _fileInfo.Find(newName) && !_fileInfo.IsDir();
|
||||
|
||||
@@ -1566,7 +1566,8 @@ static const CBenchHash g_Hash[] =
|
||||
{ 10, 339, 0x8F8FEDAB, "CRC32:8" },
|
||||
{ 10, 512, 0xDF1C17CC, "CRC64" },
|
||||
{ 10, 5100, 0x2D79FF2E, "SHA256" },
|
||||
{ 10, 2340, 0x4C25132B, "SHA1" }
|
||||
{ 10, 2340, 0x4C25132B, "SHA1" },
|
||||
{ 2, 5500, 0xE084E913, "BLAKE2sp" }
|
||||
};
|
||||
|
||||
struct CTotalBenchRes
|
||||
|
||||
@@ -865,7 +865,7 @@ STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder)
|
||||
{
|
||||
const CCodecLib &lib = Libs[ci.LibIndex];
|
||||
if (lib.CreateDecoder)
|
||||
return lib.CreateDecoder(index - NUM_EXPORT_CODECS, iid, (void **)coder);
|
||||
return lib.CreateDecoder(ci.CodecIndex, iid, (void **)coder);
|
||||
return lib.CreateObject(&ci.Decoder, iid, (void **)coder);
|
||||
}
|
||||
return S_OK;
|
||||
@@ -887,7 +887,7 @@ STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder)
|
||||
{
|
||||
const CCodecLib &lib = Libs[ci.LibIndex];
|
||||
if (lib.CreateEncoder)
|
||||
return lib.CreateEncoder(index - NUM_EXPORT_CODECS, iid, (void **)coder);
|
||||
return lib.CreateEncoder(ci.CodecIndex, iid, (void **)coder);
|
||||
return lib.CreateObject(&ci.Encoder, iid, (void **)coder);
|
||||
}
|
||||
return S_OK;
|
||||
|
||||
@@ -1083,6 +1083,7 @@ static bool IsNewStyleSignature(const CArcInfoEx &ai)
|
||||
|
||||
class CArchiveOpenCallback_Offset:
|
||||
public IArchiveOpenCallback,
|
||||
public IArchiveOpenVolumeCallback,
|
||||
#ifndef _NO_CRYPTO
|
||||
public ICryptoGetTextPassword,
|
||||
#endif
|
||||
@@ -1090,19 +1091,24 @@ class CArchiveOpenCallback_Offset:
|
||||
{
|
||||
public:
|
||||
CMyComPtr<IArchiveOpenCallback> Callback;
|
||||
CMyComPtr<IArchiveOpenVolumeCallback> OpenVolumeCallback;
|
||||
UInt64 Files;
|
||||
UInt64 Offset;
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
CMyComPtr<ICryptoGetTextPassword> GetTextPassword;
|
||||
MY_UNKNOWN_IMP2(
|
||||
IArchiveOpenCallback,
|
||||
ICryptoGetTextPassword)
|
||||
#else
|
||||
MY_UNKNOWN_IMP1(IArchiveOpenCallback)
|
||||
#endif
|
||||
STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes);
|
||||
STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes);
|
||||
|
||||
MY_QUERYINTERFACE_BEGIN2(IArchiveOpenCallback)
|
||||
MY_QUERYINTERFACE_ENTRY(IArchiveOpenVolumeCallback)
|
||||
#ifndef _NO_CRYPTO
|
||||
MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
|
||||
#endif
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
INTERFACE_IArchiveOpenCallback(;)
|
||||
INTERFACE_IArchiveOpenVolumeCallback(;)
|
||||
#ifndef _NO_CRYPTO
|
||||
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
|
||||
#endif
|
||||
@@ -1119,12 +1125,12 @@ STDMETHODIMP CArchiveOpenCallback_Offset::CryptoGetTextPassword(BSTR *password)
|
||||
}
|
||||
#endif
|
||||
|
||||
STDMETHODIMP CArchiveOpenCallback_Offset::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */)
|
||||
STDMETHODIMP CArchiveOpenCallback_Offset::SetTotal(const UInt64 *, const UInt64 *)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 * /* files */, const UInt64 *bytes)
|
||||
STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 *, const UInt64 *bytes)
|
||||
{
|
||||
if (!Callback)
|
||||
return S_OK;
|
||||
@@ -1134,8 +1140,25 @@ STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 * /* files *
|
||||
return Callback->SetCompleted(&Files, &value);
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveOpenCallback_Offset::GetProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
if (OpenVolumeCallback)
|
||||
return OpenVolumeCallback->GetProperty(propID, value);
|
||||
NCOM::PropVariant_Clear(value);
|
||||
return S_OK;
|
||||
// return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveOpenCallback_Offset::GetStream(const wchar_t *name, IInStream **inStream)
|
||||
{
|
||||
if (OpenVolumeCallback)
|
||||
return OpenVolumeCallback->GetStream(name, inStream);
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
UInt32 GetOpenArcErrorFlags(const NCOM::CPropVariant &prop, bool *isDefinedProp)
|
||||
{
|
||||
if (isDefinedProp != NULL)
|
||||
@@ -2208,9 +2231,6 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
|
||||
}
|
||||
|
||||
{
|
||||
CArchiveOpenCallback_Offset *openCallback_Offset_Spec = new CArchiveOpenCallback_Offset;
|
||||
CMyComPtr<IArchiveOpenCallback> openCallback_Offset = openCallback_Offset_Spec;
|
||||
|
||||
const size_t kBeforeSize = 1 << 16;
|
||||
const size_t kAfterSize = 1 << 20;
|
||||
const size_t kBufSize = 1 << 22; // it must be more than kBeforeSize + kAfterSize
|
||||
@@ -2288,14 +2308,18 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
|
||||
CMyComPtr<IInStream> limitedStream = limitedStreamSpec;
|
||||
limitedStreamSpec->SetStream(op.stream);
|
||||
|
||||
openCallback_Offset_Spec->Callback = op.callback;
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
CArchiveOpenCallback_Offset *openCallback_Offset_Spec = NULL;
|
||||
CMyComPtr<IArchiveOpenCallback> openCallback_Offset;
|
||||
if (op.callback)
|
||||
{
|
||||
openCallback_Offset_Spec = new CArchiveOpenCallback_Offset;
|
||||
openCallback_Offset = openCallback_Offset_Spec;
|
||||
openCallback_Offset_Spec->Callback = op.callback;
|
||||
openCallback_Offset_Spec->Callback.QueryInterface(IID_IArchiveOpenVolumeCallback, &openCallback_Offset_Spec->OpenVolumeCallback);
|
||||
#ifndef _NO_CRYPTO
|
||||
openCallback_Offset_Spec->Callback.QueryInterface(IID_ICryptoGetTextPassword, &openCallback_Offset_Spec->GetTextPassword);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (op.callback)
|
||||
RINOK(op.callback->SetTotal(NULL, &fileSize));
|
||||
@@ -2382,13 +2406,20 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
|
||||
}
|
||||
}
|
||||
|
||||
if (pos >= callbackPrev + (1 << 23))
|
||||
bool useOffsetCallback = false;
|
||||
if (openCallback_Offset)
|
||||
{
|
||||
openCallback_Offset_Spec->Files = handlerSpec->_items.Size();
|
||||
openCallback_Offset_Spec->Offset = pos;
|
||||
RINOK(openCallback_Offset->SetCompleted(NULL, NULL));
|
||||
|
||||
useOffsetCallback = (!op.openType.CanReturnArc || handlerSpec->_items.Size() > 1);
|
||||
|
||||
if (pos >= callbackPrev + (1 << 23))
|
||||
{
|
||||
RINOK(openCallback_Offset_Spec->SetCompleted(NULL, NULL));
|
||||
callbackPrev = pos;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
UInt64 endPos = bufPhyPos + bytesInBuf;
|
||||
@@ -2557,13 +2588,20 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
|
||||
}
|
||||
|
||||
UInt64 maxCheckStartPosition = 0;
|
||||
|
||||
if (openCallback_Offset)
|
||||
{
|
||||
openCallback_Offset_Spec->Files = handlerSpec->_items.Size();
|
||||
openCallback_Offset_Spec->Offset = startArcPos;
|
||||
}
|
||||
|
||||
// HRESULT result = archive->Open(limitedStream, &maxCheckStartPosition, openCallback_Offset);
|
||||
extractCallback_To_OpenCallback_Spec->Files = 0;
|
||||
extractCallback_To_OpenCallback_Spec->Offset = startArcPos;
|
||||
|
||||
HRESULT result = OpenArchiveSpec(archive, true, limitedStream, &maxCheckStartPosition, openCallback_Offset, extractCallback_To_OpenCallback);
|
||||
HRESULT result = OpenArchiveSpec(archive, true, limitedStream, &maxCheckStartPosition,
|
||||
useOffsetCallback ? (IArchiveOpenCallback *)openCallback_Offset : (IArchiveOpenCallback *)op.callback,
|
||||
extractCallback_To_OpenCallback);
|
||||
|
||||
RINOK(ReadBasicProps(archive, ai.Flags_UseGlobalOffset() ? 0 : startArcPos, result));
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace NUpdateArchive {
|
||||
{
|
||||
NPairAction::EEnum StateActions[NPairState::kNumValues];
|
||||
|
||||
const bool IsEqualTo(const CActionSet &a) const
|
||||
bool IsEqualTo(const CActionSet &a) const
|
||||
{
|
||||
for (unsigned i = 0; i < NPairState::kNumValues; i++)
|
||||
if (StateActions[i] != a.StateActions[i])
|
||||
|
||||
@@ -413,7 +413,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
|
||||
{
|
||||
case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break;
|
||||
case kpidIsDir: prop = di.IsDir(); break;
|
||||
case kpidSize: prop = di.Size; break;
|
||||
case kpidSize: prop = di.IsDir() ? (UInt64)0 : di.Size; break;
|
||||
case kpidAttrib: prop = di.Attrib; break;
|
||||
case kpidCTime: prop = di.CTime; break;
|
||||
case kpidATime: prop = di.ATime; break;
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
|
||||
#include "ConsoleClose.h"
|
||||
|
||||
#if !defined(UNDER_CE) && defined(_WIN32)
|
||||
#include "../../../Common/MyWindows.h"
|
||||
#endif
|
||||
|
||||
namespace NConsoleClose {
|
||||
|
||||
unsigned g_BreakCounter = 0;
|
||||
|
||||
@@ -123,6 +123,7 @@ static const char * const kPropIdToName[] =
|
||||
, "Stream ID"
|
||||
, "Read-only"
|
||||
, "Out Name"
|
||||
, "Copy Link"
|
||||
};
|
||||
|
||||
static const char kEmptyAttribChar = '.';
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
|
||||
#include <Psapi.h>
|
||||
|
||||
#include "../../../../C/CpuArch.h"
|
||||
@@ -230,21 +232,29 @@ static void PrintWarningsPaths(const CErrorPathCodes &pc, CStdOutStream &so)
|
||||
}
|
||||
|
||||
static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback,
|
||||
const CUpdateErrorInfo &errorInfo, CStdOutStream &so, bool showHeaders)
|
||||
const CUpdateErrorInfo &errorInfo,
|
||||
CStdOutStream *so,
|
||||
CStdOutStream *se,
|
||||
bool showHeaders)
|
||||
{
|
||||
int exitCode = NExitCode::kSuccess;
|
||||
|
||||
if (callback.ScanErrors.Paths.Size() != 0)
|
||||
{
|
||||
so << endl;
|
||||
so << "Scan WARNINGS for files and folders:" << endl << endl;
|
||||
PrintWarningsPaths(callback.ScanErrors, so);
|
||||
so << "Scan WARNINGS: " << callback.ScanErrors.Paths.Size();
|
||||
so << endl;
|
||||
if (se)
|
||||
{
|
||||
*se << endl;
|
||||
*se << "Scan WARNINGS for files and folders:" << endl << endl;
|
||||
PrintWarningsPaths(callback.ScanErrors, *se);
|
||||
*se << "Scan WARNINGS: " << callback.ScanErrors.Paths.Size();
|
||||
*se << endl;
|
||||
}
|
||||
exitCode = NExitCode::kWarning;
|
||||
}
|
||||
|
||||
if (result != S_OK || errorInfo.ThereIsError())
|
||||
{
|
||||
if (se)
|
||||
{
|
||||
UString message;
|
||||
if (!errorInfo.Message.IsEmpty())
|
||||
@@ -265,7 +275,8 @@ static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback,
|
||||
message.Add_LF();
|
||||
}
|
||||
if (!message.IsEmpty())
|
||||
so << L"\nError:\n" << message;
|
||||
*se << L"\nError:\n" << message;
|
||||
}
|
||||
|
||||
// we will work with (result) later
|
||||
// throw CSystemException(result);
|
||||
@@ -277,17 +288,25 @@ static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback,
|
||||
{
|
||||
if (showHeaders)
|
||||
if (callback.ScanErrors.Paths.Size() == 0)
|
||||
so << kEverythingIsOk << endl;
|
||||
if (so)
|
||||
{
|
||||
if (se)
|
||||
se->Flush();
|
||||
*so << kEverythingIsOk << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
so << endl;
|
||||
so << "WARNINGS for files:" << endl << endl;
|
||||
PrintWarningsPaths(callback.FailedFiles, so);
|
||||
so << "WARNING: Cannot open " << numErrors << " file";
|
||||
if (se)
|
||||
{
|
||||
*se << endl;
|
||||
*se << "WARNINGS for files:" << endl << endl;
|
||||
PrintWarningsPaths(callback.FailedFiles, *se);
|
||||
*se << "WARNING: Cannot open " << numErrors << " file";
|
||||
if (numErrors > 1)
|
||||
so << 's';
|
||||
so << endl;
|
||||
*se << 's';
|
||||
*se << endl;
|
||||
}
|
||||
exitCode = NExitCode::kWarning;
|
||||
}
|
||||
|
||||
@@ -474,9 +493,6 @@ int Main2(
|
||||
if (options.Number_for_Percents != k_OutStream_disabled)
|
||||
percentsStream = (options.Number_for_Percents == k_OutStream_stderr) ? &g_StdErr : &g_StdOut;;
|
||||
|
||||
CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
|
||||
|
||||
|
||||
if (options.HelpMode)
|
||||
{
|
||||
ShowCopyrightAndHelp(g_StdStream, true);
|
||||
@@ -589,6 +605,7 @@ int Main2(
|
||||
|
||||
if (options.Command.CommandType == NCommandType::kInfo)
|
||||
{
|
||||
CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
|
||||
unsigned i;
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
@@ -754,6 +771,7 @@ int Main2(
|
||||
}
|
||||
else if (options.Command.CommandType == NCommandType::kBenchmark)
|
||||
{
|
||||
CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
|
||||
hresultMain = BenchCon(EXTERNAL_CODECS_VARS_L
|
||||
options.Properties, options.NumIterations, (FILE *)so);
|
||||
if (hresultMain == S_FALSE)
|
||||
@@ -890,73 +908,91 @@ int Main2(
|
||||
hresultMain = E_FAIL;
|
||||
}
|
||||
|
||||
so << endl;
|
||||
CStdOutStream *so = g_StdStream;
|
||||
|
||||
bool isError = false;
|
||||
|
||||
if (so)
|
||||
{
|
||||
*so << endl;
|
||||
|
||||
if (ecs->NumTryArcs > 1)
|
||||
{
|
||||
so << "Archives: " << ecs->NumTryArcs << endl;
|
||||
so << "OK archives: " << ecs->NumOkArcs << endl;
|
||||
*so << "Archives: " << ecs->NumTryArcs << endl;
|
||||
*so << "OK archives: " << ecs->NumOkArcs << endl;
|
||||
}
|
||||
bool isError = false;
|
||||
}
|
||||
|
||||
if (ecs->NumCantOpenArcs != 0)
|
||||
{
|
||||
isError = true;
|
||||
so << "Can't open as archive: " << ecs->NumCantOpenArcs << endl;
|
||||
if (so)
|
||||
*so << "Can't open as archive: " << ecs->NumCantOpenArcs << endl;
|
||||
}
|
||||
|
||||
if (ecs->NumArcsWithError != 0)
|
||||
{
|
||||
isError = true;
|
||||
so << "Archives with Errors: " << ecs->NumArcsWithError << endl;
|
||||
if (so)
|
||||
*so << "Archives with Errors: " << ecs->NumArcsWithError << endl;
|
||||
}
|
||||
|
||||
if (so)
|
||||
{
|
||||
if (ecs->NumArcsWithWarnings != 0)
|
||||
so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl;
|
||||
*so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl;
|
||||
|
||||
if (ecs->NumOpenArcWarnings != 0)
|
||||
{
|
||||
so << endl;
|
||||
*so << endl;
|
||||
if (ecs->NumOpenArcWarnings != 0)
|
||||
so << "Warnings: " << ecs->NumOpenArcWarnings << endl;
|
||||
*so << "Warnings: " << ecs->NumOpenArcWarnings << endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (ecs->NumOpenArcErrors != 0)
|
||||
{
|
||||
isError = true;
|
||||
so << endl;
|
||||
if (so)
|
||||
{
|
||||
*so << endl;
|
||||
if (ecs->NumOpenArcErrors != 0)
|
||||
so << "Open Errors: " << ecs->NumOpenArcErrors << endl;
|
||||
*so << "Open Errors: " << ecs->NumOpenArcErrors << endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (isError)
|
||||
retCode = NExitCode::kFatalError;
|
||||
|
||||
if (so)
|
||||
if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0)
|
||||
{
|
||||
// if (ecs->NumArchives > 1)
|
||||
{
|
||||
so << endl;
|
||||
*so << endl;
|
||||
if (ecs->NumFileErrors != 0)
|
||||
so << "Sub items Errors: " << ecs->NumFileErrors << endl;
|
||||
*so << "Sub items Errors: " << ecs->NumFileErrors << endl;
|
||||
}
|
||||
}
|
||||
else if (hresultMain == S_OK)
|
||||
{
|
||||
if (stat.NumFolders != 0)
|
||||
so << "Folders: " << stat.NumFolders << endl;
|
||||
*so << "Folders: " << stat.NumFolders << endl;
|
||||
if (stat.NumFiles != 1 || stat.NumFolders != 0 || stat.NumAltStreams != 0)
|
||||
so << "Files: " << stat.NumFiles << endl;
|
||||
*so << "Files: " << stat.NumFiles << endl;
|
||||
if (stat.NumAltStreams != 0)
|
||||
{
|
||||
so << "Alternate Streams: " << stat.NumAltStreams << endl;
|
||||
so << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl;
|
||||
*so << "Alternate Streams: " << stat.NumAltStreams << endl;
|
||||
*so << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl;
|
||||
}
|
||||
|
||||
so
|
||||
*so
|
||||
<< "Size: " << stat.UnpackSize << endl
|
||||
<< "Compressed: " << stat.PackSize << endl;
|
||||
if (hashCalc)
|
||||
{
|
||||
so << endl;
|
||||
PrintHashStat(so, hb);
|
||||
*so << endl;
|
||||
PrintHashStat(*so, hb);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1047,9 +1083,14 @@ int Main2(
|
||||
|
||||
callback.ClosePercents2();
|
||||
|
||||
retCode = WarningsCheck(hresultMain, callback, errorInfo, so,
|
||||
// options.EnableHeaders
|
||||
true);
|
||||
CStdOutStream *se = g_StdStream;
|
||||
if (!se)
|
||||
se = g_ErrStream;
|
||||
|
||||
retCode = WarningsCheck(hresultMain, callback, errorInfo,
|
||||
g_StdStream, se,
|
||||
true // options.EnableHeaders
|
||||
);
|
||||
}
|
||||
else if (options.Command.CommandType == NCommandType::kHash)
|
||||
{
|
||||
@@ -1068,7 +1109,10 @@ int Main2(
|
||||
errorInfoString, &callback);
|
||||
CUpdateErrorInfo errorInfo;
|
||||
errorInfo.Message = errorInfoString;
|
||||
retCode = WarningsCheck(hresultMain, callback, errorInfo, so, options.EnableHeaders);
|
||||
CStdOutStream *se = g_StdStream;
|
||||
if (!se)
|
||||
se = g_ErrStream;
|
||||
retCode = WarningsCheck(hresultMain, callback, errorInfo, g_StdStream, se, options.EnableHeaders);
|
||||
}
|
||||
else
|
||||
ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError);
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
#ifndef __CONTEXT_MENU_H
|
||||
#define __CONTEXT_MENU_H
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
|
||||
#include <ShlObj.h>
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
#include "../FileManager/MyCom2.h"
|
||||
|
||||
@@ -8,11 +8,13 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/MyInitGuid.h"
|
||||
#include "../../../Common/MyWindows.h"
|
||||
|
||||
#include <ShlGuid.h>
|
||||
#include <OleCtl.h>
|
||||
|
||||
#include "../../../Common/MyInitGuid.h"
|
||||
|
||||
#include "../../../Common/ComTry.h"
|
||||
#include "../../../Common/StringConvert.h"
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
|
||||
#include "../../../Common/MyInitGuid.h"
|
||||
|
||||
#include "../../../Common/StringConvert.h"
|
||||
@@ -96,6 +98,7 @@ EXTERN_C void WINAPI SetStartupInfo(const PluginStartupInfo *info)
|
||||
class COpenArchiveCallback:
|
||||
public IArchiveOpenCallback,
|
||||
public IArchiveOpenVolumeCallback,
|
||||
public IArchiveOpenSetSubArchiveName,
|
||||
public IProgress,
|
||||
public ICryptoGetTextPassword,
|
||||
public CMyUnknownImp
|
||||
@@ -109,6 +112,8 @@ class COpenArchiveCallback:
|
||||
bool _numBytesTotalDefined;
|
||||
|
||||
NFind::CFileInfo _fileInfo;
|
||||
bool _subArchiveMode;
|
||||
UString _subArchiveName;
|
||||
public:
|
||||
bool PasswordIsDefined;
|
||||
UString Password;
|
||||
@@ -116,8 +121,9 @@ public:
|
||||
FString _folderPrefix;
|
||||
|
||||
public:
|
||||
MY_UNKNOWN_IMP3(
|
||||
MY_UNKNOWN_IMP4(
|
||||
IArchiveOpenVolumeCallback,
|
||||
IArchiveOpenSetSubArchiveName,
|
||||
IProgress,
|
||||
ICryptoGetTextPassword
|
||||
)
|
||||
@@ -134,13 +140,24 @@ public:
|
||||
STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value);
|
||||
STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream);
|
||||
|
||||
STDMETHOD(SetSubArchiveName(const wchar_t *name))
|
||||
{
|
||||
_subArchiveMode = true;
|
||||
_subArchiveName = name;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// ICryptoGetTextPassword
|
||||
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
|
||||
|
||||
COpenArchiveCallback(): _subArchiveMode(false) {}
|
||||
|
||||
void Init()
|
||||
{
|
||||
PasswordIsDefined = false;
|
||||
|
||||
_subArchiveMode = false;
|
||||
|
||||
_numFilesTotalDefined = false;
|
||||
_numBytesTotalDefined = false;
|
||||
|
||||
@@ -220,6 +237,8 @@ STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **in
|
||||
{
|
||||
if (WasEscPressed())
|
||||
return E_ABORT;
|
||||
if (_subArchiveMode)
|
||||
return S_FALSE;
|
||||
*inStream = NULL;
|
||||
FString fullPath = _folderPrefix + us2fs(name);
|
||||
if (!_fileInfo.Find(fullPath))
|
||||
@@ -238,6 +257,14 @@ STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **in
|
||||
STDMETHODIMP COpenArchiveCallback::GetProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
if (_subArchiveMode)
|
||||
{
|
||||
switch(propID)
|
||||
{
|
||||
case kpidName: prop = _subArchiveName; break;
|
||||
}
|
||||
}
|
||||
else
|
||||
switch(propID)
|
||||
{
|
||||
case kpidName: prop = GetUnicodeString(_fileInfo.Name, CP_OEMCP); break;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
namespace NMessageID {
|
||||
|
||||
const UINT k_Last_PropId_supported_by_plugin = kpidStreamId;
|
||||
const unsigned k_Last_PropId_supported_by_plugin = kpidStreamId;
|
||||
|
||||
enum EEnum
|
||||
{
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
|
||||
#include <commctrl.h>
|
||||
|
||||
#ifndef UNDER_CE
|
||||
#include "../../../Windows/CommonDialog.h"
|
||||
#include "../../../Windows/Shell.h"
|
||||
@@ -106,7 +110,7 @@ class CBrowseDialog: public NControl::CModalDialog
|
||||
virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
|
||||
virtual void OnOK();
|
||||
|
||||
void Post_RefreshPathEdit() { PostMessage(k_Message_RefreshPathEdit); }
|
||||
void Post_RefreshPathEdit() { PostMsg(k_Message_RefreshPathEdit); }
|
||||
|
||||
bool GetParentPath(const UString &path, UString &parentPrefix, UString &name);
|
||||
// Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter
|
||||
@@ -295,7 +299,7 @@ bool CBrowseDialog::OnInit()
|
||||
#ifndef UNDER_CE
|
||||
/* If we clear UISF_HIDEFOCUS, the focus rectangle in ListView will be visible,
|
||||
even if we use mouse for pressing the button to open this dialog. */
|
||||
PostMessage(MY__WM_UPDATEUISTATE, MAKEWPARAM(MY__UIS_CLEAR, MY__UISF_HIDEFOCUS));
|
||||
PostMsg(MY__WM_UPDATEUISTATE, MAKEWPARAM(MY__UIS_CLEAR, MY__UISF_HIDEFOCUS));
|
||||
#endif
|
||||
|
||||
return CModalDialog::OnInit();
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
|
||||
#include "../../../Common/MyInitGuid.h"
|
||||
|
||||
#include "../Agent/Agent.h"
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
|
||||
#include <shlwapi.h>
|
||||
|
||||
#include "../../../../C/Alloc.h"
|
||||
|
||||
#include "../../../Common/IntToString.h"
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
|
||||
#include <Winbase.h>
|
||||
|
||||
#include "../../../Common/Defs.h"
|
||||
@@ -585,7 +587,6 @@ STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
|
||||
|
||||
CCopyState state;
|
||||
state.ProgressInfo.TotalSize = stat.Size;
|
||||
state.ProgressInfo.TotalSize = stat.Size;
|
||||
state.ProgressInfo.StartPos = 0;
|
||||
state.ProgressInfo.Progress = callback;
|
||||
state.ProgressInfo.Init();
|
||||
@@ -593,7 +594,6 @@ STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
|
||||
state.MoveMode = IntToBool(moveMode);
|
||||
state.UseReadWriteMode = isAltDest;
|
||||
state.Prepare();
|
||||
state.TotalSize = stat.Size;
|
||||
|
||||
for (UInt32 i = 0; i < numItems; i++)
|
||||
{
|
||||
|
||||
@@ -42,7 +42,7 @@ static const UInt32 kLangIDs[] =
|
||||
|
||||
static bool GetSymLink(CFSTR path, CReparseAttr &attr)
|
||||
{
|
||||
NFile::NIO::CInFile file;
|
||||
NIO::CInFile file;
|
||||
if (!file.Open(path,
|
||||
FILE_SHARE_READ,
|
||||
OPEN_EXISTING,
|
||||
@@ -88,12 +88,13 @@ bool CLinkDialog::OnInit()
|
||||
LangSetWindowText(*this, IDD_LINK);
|
||||
LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
|
||||
#endif
|
||||
|
||||
_pathFromCombo.Attach(GetItem(IDC_LINK_PATH_FROM));
|
||||
_pathToCombo.Attach(GetItem(IDC_LINK_PATH_TO));
|
||||
|
||||
if (!FilePath.IsEmpty())
|
||||
{
|
||||
NFile::NFind::CFileInfo fi;
|
||||
NFind::CFileInfo fi;
|
||||
int linkType = 0;
|
||||
if (!fi.Find(us2fs(FilePath)))
|
||||
linkType = IDR_LINK_TYPE_SYM_FILE;
|
||||
@@ -219,7 +220,7 @@ void CLinkDialog::OnButton_SetPath(bool to)
|
||||
UString resultPath;
|
||||
if (!MyBrowseForFolder(*this, title, currentPath, resultPath))
|
||||
return;
|
||||
NFile::NName::NormalizeDirPathPrefix(resultPath);
|
||||
NName::NormalizeDirPathPrefix(resultPath);
|
||||
combo.SetCurSel(-1);
|
||||
combo.SetText(resultPath);
|
||||
}
|
||||
@@ -239,16 +240,23 @@ void CLinkDialog::OnButton_Link()
|
||||
UString from, to;
|
||||
_pathFromCombo.GetText(from);
|
||||
_pathToCombo.GetText(to);
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(k_LinkType_Buttons); i++)
|
||||
if (IsButtonCheckedBool(k_LinkType_Buttons[i]))
|
||||
break;
|
||||
|
||||
if (from.IsEmpty())
|
||||
return;
|
||||
if (!NName::IsAbsolutePath(from))
|
||||
from.Insert(0, CurDirPrefix);
|
||||
|
||||
int idb = -1;
|
||||
for (unsigned i = 0;; i++)
|
||||
{
|
||||
if (i >= ARRAY_SIZE(k_LinkType_Buttons))
|
||||
return;
|
||||
idb = k_LinkType_Buttons[i];
|
||||
if (IsButtonCheckedBool(idb))
|
||||
break;
|
||||
}
|
||||
|
||||
int idb = k_LinkType_Buttons[i];
|
||||
|
||||
NFile::NFind::CFileInfo info1, info2;
|
||||
NFind::CFileInfo info1, info2;
|
||||
bool finded1 = info1.Find(us2fs(from));
|
||||
bool finded2 = info2.Find(us2fs(to));
|
||||
|
||||
@@ -259,14 +267,13 @@ void CLinkDialog::OnButton_Link()
|
||||
if (finded1 && info1.IsDir() != isDirLink ||
|
||||
finded2 && info2.IsDir() != isDirLink)
|
||||
{
|
||||
ShowError(L"Incorrect linkType");
|
||||
ShowError(L"Incorrect link type");
|
||||
return;
|
||||
}
|
||||
|
||||
if (idb == IDR_LINK_TYPE_HARD)
|
||||
{
|
||||
bool res = NFile::NDir::MyCreateHardLink(us2fs(from), us2fs(to));
|
||||
if (!res)
|
||||
if (!NDir::MyCreateHardLink(us2fs(from), us2fs(to)))
|
||||
{
|
||||
ShowLastErrorMessage();
|
||||
return;
|
||||
@@ -291,9 +298,10 @@ void CLinkDialog::OnButton_Link()
|
||||
}
|
||||
|
||||
|
||||
if (!NFile::NIO::SetReparseData(us2fs(from), isDirLink, data, (DWORD)data.Size()))
|
||||
if (!NIO::SetReparseData(us2fs(from), isDirLink, data, (DWORD)data.Size()))
|
||||
{
|
||||
ShowLastErrorMessage();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,7 +329,8 @@ void CApp::Link()
|
||||
int index = indices[0];
|
||||
const UString itemName = srcPanel.GetItemName(index);
|
||||
|
||||
UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index);
|
||||
const UString fsPrefix = srcPanel.GetFsPath();
|
||||
const UString srcPath = fsPrefix + srcPanel.GetItemPrefix(index);
|
||||
UString path = srcPath;
|
||||
{
|
||||
int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
|
||||
@@ -332,6 +341,7 @@ void CApp::Link()
|
||||
}
|
||||
|
||||
CLinkDialog dlg;
|
||||
dlg.CurDirPrefix = fsPrefix;
|
||||
dlg.FilePath = srcPath + itemName;
|
||||
dlg.AnotherPath = path;
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ class CLinkDialog: public NWindows::NControl::CModalDialog
|
||||
void ShowError(const wchar_t *s);
|
||||
void Set_LinkType_Radio(int idb);
|
||||
public:
|
||||
UString CurDirPrefix;
|
||||
UString FilePath;
|
||||
UString AnotherPath;
|
||||
|
||||
|
||||
@@ -795,7 +795,7 @@ void CPanel::Change_ShowNtfsStrems_Mode()
|
||||
void CPanel::Post_Refresh_StatusBar()
|
||||
{
|
||||
if (_processStatusBar)
|
||||
PostMessage(kRefresh_StatusBar);
|
||||
PostMsg(kRefresh_StatusBar);
|
||||
}
|
||||
|
||||
void CPanel::AddToArchive()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user