Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2015-08-16 03:00:00 +0300
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:16:55 +0300
commitcba375916fb18db8b9101aedf4fa079e019311b3 (patch)
tree6275ae5fc2a8dd337ab0327180c871807e6ba5d4
parent54490d51d5c6b0d794dcbad2d634d4c95fc25b6c (diff)
15.0615.06
-rw-r--r--C/7zDec.c16
-rw-r--r--C/7zVersion.h8
-rw-r--r--C/Bcj2.c6
-rw-r--r--C/Blake2.h48
-rw-r--r--C/Blake2s.c244
-rw-r--r--C/Compiler.h3
-rw-r--r--C/CpuArch.h9
-rw-r--r--C/LzmaDec.c11
-rw-r--r--C/Util/7z/7zMain.c16
-rw-r--r--C/Util/7z/makefile.gcc10
-rw-r--r--C/Util/7zipInstall/7zipInstall.c47
-rw-r--r--C/Util/7zipUninstall/7zipUninstall.c4
-rw-r--r--CPP/7zip/Archive/7z/7zDecode.cpp6
-rw-r--r--CPP/7zip/Archive/7z/7zHandler.h1
-rw-r--r--CPP/7zip/Archive/7z/7zHandlerOut.cpp24
-rw-r--r--CPP/7zip/Archive/7z/7zUpdate.cpp14
-rw-r--r--CPP/7zip/Archive/7z/7zUpdate.h4
-rw-r--r--CPP/7zip/Archive/7z/makefile8
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer.cpp19
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer.h32
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2MT.cpp254
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2MT.h77
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2ST.cpp562
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2ST.h129
-rw-r--r--CPP/7zip/Archive/Common/CoderMixerMT.cpp99
-rw-r--r--CPP/7zip/Archive/Common/CoderMixerMT.h70
-rw-r--r--CPP/7zip/Archive/Common/FindSignature.cpp2
-rw-r--r--CPP/7zip/Archive/Common/FindSignature.h4
-rw-r--r--CPP/7zip/Archive/DllExports2.cpp2
-rw-r--r--CPP/7zip/Archive/Nsis/NsisIn.h2
-rw-r--r--CPP/7zip/Archive/Rar/Rar5Handler.cpp2683
-rw-r--r--CPP/7zip/Archive/Rar/Rar5Handler.h410
-rw-r--r--CPP/7zip/Archive/Rar/RarHandler.cpp417
-rw-r--r--CPP/7zip/Archive/Rar/RarVol.h129
-rw-r--r--CPP/7zip/Archive/Tar/TarHandlerOut.cpp24
-rw-r--r--CPP/7zip/Archive/Tar/TarUpdate.cpp24
-rw-r--r--CPP/7zip/Archive/Tar/TarUpdate.h7
-rw-r--r--CPP/7zip/Archive/XarHandler.cpp9
-rw-r--r--CPP/7zip/Archive/Zip/ZipHandlerOut.cpp4
-rw-r--r--CPP/7zip/Archive/Zip/ZipIn.cpp48
-rw-r--r--CPP/7zip/Archive/Zip/ZipUpdate.cpp3
-rw-r--r--CPP/7zip/Bundles/Fm/FM.dsp8
-rw-r--r--CPP/7zip/Bundles/Format7zF/Arc.mak5
-rw-r--r--CPP/7zip/Bundles/Format7zF/Format7z.dsp70
-rw-r--r--CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp2
-rw-r--r--CPP/7zip/Bundles/SFXCon/SfxCon.cpp2
-rw-r--r--CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp2
-rw-r--r--CPP/7zip/Bundles/SFXWin/SfxWin.cpp2
-rw-r--r--CPP/7zip/Common/FilterCoder.h2
-rw-r--r--CPP/7zip/Common/LimitedStreams.cpp2
-rw-r--r--CPP/7zip/Common/PropId.cpp5
-rw-r--r--CPP/7zip/Common/UniqBlocks.cpp2
-rw-r--r--CPP/7zip/Compress/Codec.def2
-rw-r--r--CPP/7zip/Compress/DeflateEncoder.cpp8
-rw-r--r--CPP/7zip/Compress/HuffmanDecoder.h19
-rw-r--r--CPP/7zip/Compress/Rar1Decoder.cpp2
-rw-r--r--CPP/7zip/Compress/Rar2Decoder.cpp2
-rw-r--r--CPP/7zip/Compress/Rar3Decoder.cpp22
-rw-r--r--CPP/7zip/Compress/Rar3Decoder.h1
-rw-r--r--CPP/7zip/Compress/Rar3Vm.cpp105
-rw-r--r--CPP/7zip/Compress/Rar3Vm.h34
-rw-r--r--CPP/7zip/Compress/Rar5Decoder.cpp960
-rw-r--r--CPP/7zip/Compress/Rar5Decoder.h335
-rw-r--r--CPP/7zip/Compress/RarCodecsRegister.cpp3
-rw-r--r--CPP/7zip/Crypto/HmacSha256.cpp62
-rw-r--r--CPP/7zip/Crypto/HmacSha256.h27
-rw-r--r--CPP/7zip/Crypto/Rar20Crypto.cpp62
-rw-r--r--CPP/7zip/Crypto/Rar20Crypto.h16
-rw-r--r--CPP/7zip/Crypto/Rar5Aes.cpp257
-rw-r--r--CPP/7zip/Crypto/Rar5Aes.h84
-rw-r--r--CPP/7zip/Crypto/RarAes.cpp22
-rw-r--r--CPP/7zip/Crypto/RarAes.h19
-rw-r--r--CPP/7zip/Guid.txt1
-rw-r--r--CPP/7zip/IProgress.h1
-rw-r--r--CPP/7zip/IStream.h2
-rw-r--r--CPP/7zip/PropID.h1
-rw-r--r--CPP/7zip/UI/Agent/AgentOut.cpp15
-rw-r--r--CPP/7zip/UI/Client7z/Client7z.cpp2
-rw-r--r--CPP/7zip/UI/Common/ArchiveExtractCallback.cpp165
-rw-r--r--CPP/7zip/UI/Common/ArchiveExtractCallback.h9
-rw-r--r--CPP/7zip/UI/Common/ArchiveOpenCallback.h19
-rw-r--r--CPP/7zip/UI/Common/Bench.cpp3
-rw-r--r--CPP/7zip/UI/Common/LoadCodecs.cpp4
-rw-r--r--CPP/7zip/UI/Common/OpenArchive.cpp84
-rw-r--r--CPP/7zip/UI/Common/UpdateAction.h2
-rw-r--r--CPP/7zip/UI/Common/UpdateCallback.cpp2
-rw-r--r--CPP/7zip/UI/Console/ConsoleClose.cpp4
-rw-r--r--CPP/7zip/UI/Console/List.cpp1
-rw-r--r--CPP/7zip/UI/Console/Main.cpp164
-rw-r--r--CPP/7zip/UI/Explorer/ContextMenu.h4
-rw-r--r--CPP/7zip/UI/Explorer/DllExportsExplorer.cpp4
-rw-r--r--CPP/7zip/UI/Far/Far.cpp29
-rw-r--r--CPP/7zip/UI/Far/Messages.h2
-rw-r--r--CPP/7zip/UI/FileManager/BrowseDialog.cpp8
-rw-r--r--CPP/7zip/UI/FileManager/ClassDefs.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/FM.cpp4
-rw-r--r--CPP/7zip/UI/FileManager/FSFolderCopy.cpp4
-rw-r--r--CPP/7zip/UI/FileManager/LinkDialog.cpp40
-rw-r--r--CPP/7zip/UI/FileManager/LinkDialog.h1
-rw-r--r--CPP/7zip/UI/FileManager/Panel.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/Panel.h4
-rw-r--r--CPP/7zip/UI/FileManager/PanelFolderChange.cpp10
-rw-r--r--CPP/7zip/UI/FileManager/PanelItemOpen.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/PanelOperations.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/PanelSelect.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog.h2
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog2.cpp4
-rw-r--r--CPP/7zip/UI/FileManager/PropertyName.rc1
-rw-r--r--CPP/7zip/UI/FileManager/PropertyNameRes.h1
-rw-r--r--CPP/7zip/UI/FileManager/RootFolder.cpp4
-rw-r--r--CPP/7zip/UI/FileManager/StdAfx.h8
-rw-r--r--CPP/7zip/UI/FileManager/SysIconUtils.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/SysIconUtils.h4
-rw-r--r--CPP/7zip/UI/FileManager/SystemPage.cpp4
-rw-r--r--CPP/7zip/UI/GUI/BenchmarkDialog.cpp2
-rw-r--r--CPP/7zip/UI/GUI/GUI.cpp4
-rw-r--r--CPP/7zip/UI/GUI/StdAfx.h6
-rw-r--r--CPP/Common/Defs.h15
-rw-r--r--CPP/Common/MyBuffer.h14
-rw-r--r--CPP/Common/MyString.cpp1
-rw-r--r--CPP/Common/MyString.h1
-rw-r--r--CPP/Common/MyUnknown.h4
-rw-r--r--CPP/Common/MyVector.h2
-rw-r--r--CPP/Common/NewHandler.h1
-rw-r--r--CPP/Common/Random.cpp2
-rw-r--r--CPP/Windows/CommonDialog.cpp2
-rw-r--r--CPP/Windows/Control/ComboBox.cpp6
-rw-r--r--CPP/Windows/Control/ComboBox.h38
-rw-r--r--CPP/Windows/Control/CommandBar.h12
-rw-r--r--CPP/Windows/Control/Edit.h2
-rw-r--r--CPP/Windows/Control/ListView.h10
-rw-r--r--CPP/Windows/Control/ProgressBar.h24
-rw-r--r--CPP/Windows/Control/PropertyPage.h2
-rw-r--r--CPP/Windows/Control/ReBar.h16
-rw-r--r--CPP/Windows/Control/Static.h8
-rw-r--r--CPP/Windows/Control/StatusBar.h8
-rw-r--r--CPP/Windows/Control/ToolBar.h16
-rw-r--r--CPP/Windows/FileFind.cpp10
-rw-r--r--CPP/Windows/FileIO.h2
-rw-r--r--CPP/Windows/MemoryGlobal.h2
-rw-r--r--CPP/Windows/MemoryLock.cpp2
-rw-r--r--CPP/Windows/MemoryLock.h4
-rw-r--r--CPP/Windows/NtCheck.h2
-rw-r--r--CPP/Windows/System.cpp2
-rw-r--r--CPP/Windows/TimeUtils.h1
-rw-r--r--CPP/Windows/Window.h21
-rw-r--r--DOC/7zip.inf4
-rw-r--r--DOC/7zip.nsi2
-rw-r--r--DOC/7zip.wxs2
-rw-r--r--DOC/Methods.txt19
-rw-r--r--DOC/readme.txt2
152 files changed, 6539 insertions, 1996 deletions
diff --git a/C/7zDec.c b/C/7zDec.c
index 1f326137..4ec6f373 100644
--- a/C/7zDec.c
+++ b/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);
@@ -429,7 +429,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
}
#endif
- else
+ else
return SZ_ERROR_UNSUPPORTED;
}
else if (coder->MethodID == k_BCJ2)
diff --git a/C/7zVersion.h b/C/7zVersion.h
index a3c2c272..170f7aee 100644
--- a/C/7zVersion.h
+++ b/C/7zVersion.h
@@ -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"
diff --git a/C/Bcj2.c b/C/Bcj2.c
index 371a9e6e..3c88e44f 100644
--- a/C/Bcj2.c
+++ b/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;
}
diff --git a/C/Blake2.h b/C/Blake2.h
new file mode 100644
index 00000000..14f3cb64
--- /dev/null
+++ b/C/Blake2.h
@@ -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
diff --git a/C/Blake2s.c b/C/Blake2s.c
new file mode 100644
index 00000000..6527415e
--- /dev/null
+++ b/C/Blake2s.c
@@ -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);
+}
diff --git a/C/Compiler.h b/C/Compiler.h
index 5c53d5b6..5bba7ee5 100644
--- a/C/Compiler.h
+++ b/C/Compiler.h
@@ -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
diff --git a/C/CpuArch.h b/C/CpuArch.h
index 38835189..ddd27d26 100644
--- a/C/CpuArch.h
+++ b/C/CpuArch.h
@@ -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
diff --git a/C/LzmaDec.c b/C/LzmaDec.c
index c8326667..27efbaba 100644
--- a/C/LzmaDec.c
+++ b/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);
diff --git a/C/Util/7z/7zMain.c b/C/Util/7z/7zMain.c
index c1e49bf4..ed6bab2a 100644
--- a/C/Util/7z/7zMain.c
+++ b/C/Util/7z/7zMain.c
@@ -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';
-}
-#else
-static void GetAttribString(UInt32, Bool, char *s)
-{
- s[0] = '\0';
+ s[5] = 0;
+ #else
+ s[0] = (char)(((wa & (1 << 4)) != 0 || isDir) ? 'D' : '.');
+ s[1] = 0;
+ #endif
}
-#endif
// #define NUM_PARENTS_MAX 128
diff --git a/C/Util/7z/makefile.gcc b/C/Util/7z/makefile.gcc
index 46018201..beeb72fe 100644
--- a/C/Util/7z/makefile.gcc
+++ b/C/Util/7z/makefile.gcc
@@ -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
diff --git a/C/Util/7zipInstall/7zipInstall.c b/C/Util/7zipInstall/7zipInstall.c
index dc636d64..9a360579 100644
--- a/C/Util/7zipInstall/7zipInstall.c
+++ b/C/Util/7zipInstall/7zipInstall.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();
@@ -1131,6 +1164,8 @@ if (res == SZ_OK)
UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call, if(!outBuf) */
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)
{
@@ -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))
{
diff --git a/C/Util/7zipUninstall/7zipUninstall.c b/C/Util/7zipUninstall/7zipUninstall.c
index 68a8b029..60984347 100644
--- a/C/Util/7zipUninstall/7zipUninstall.c
+++ b/C/Util/7zipUninstall/7zipUninstall.c
@@ -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
diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp
index d1a810cb..bfe1b24e 100644
--- a/CPP/7zip/Archive/7z/7zDecode.cpp
+++ b/CPP/7zip/Archive/7z/7zDecode.cpp
@@ -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
diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h
index 8a078e19..eb7791bc 100644
--- a/CPP/7zip/Archive/7z/7zHandler.h
+++ b/CPP/7zip/Archive/7z/7zHandler.h
@@ -44,6 +44,7 @@ public:
UInt64 _numSolidBytes;
bool _numSolidBytesDefined;
bool _solidExtension;
+ bool _useTypeSorting;
bool _compressHeaders;
bool _encryptHeadersSpecified;
diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
index 5cab6a82..7ece4c68 100644
--- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp
+++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
@@ -508,14 +508,19 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (ui.NewData)
{
- NCOM::CPropVariant prop;
- RINOK(updateCallback->GetProperty(i, kpidSize, &prop));
- if (prop.vt != VT_UI8)
- return E_INVALIDARG;
- ui.Size = (UInt64)prop.uhVal.QuadPart;
- if (ui.Size != 0 && ui.IsAnti)
- return E_INVALIDARG;
+ ui.Size = 0;
+ if (!ui.IsDir)
+ {
+ NCOM::CPropVariant prop;
+ RINOK(updateCallback->GetProperty(i, kpidSize, &prop));
+ if (prop.vt != VT_UI8)
+ return E_INVALIDARG;
+ ui.Size = (UInt64)prop.uhVal.QuadPart;
+ 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);
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp
index e7c9ecc6..345cd627 100644
--- a/CPP/7zip/Archive/7z/7zUpdate.cpp
+++ b/CPP/7zip/Archive/7z/7zUpdate.cpp
@@ -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;
diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h
index 3986af43..a7abf779 100644
--- a/CPP/7zip/Archive/7z/7zUpdate.h
+++ b/CPP/7zip/Archive/7z/7zUpdate.h
@@ -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)
{}
diff --git a/CPP/7zip/Archive/7z/makefile b/CPP/7zip/Archive/7z/makefile
index 19982112..49818371 100644
--- a/CPP/7zip/Archive/7z/makefile
+++ b/CPP/7zip/Archive/7z/makefile
@@ -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"
diff --git a/CPP/7zip/Archive/Common/CoderMixer.cpp b/CPP/7zip/Archive/Common/CoderMixer.cpp
deleted file mode 100644
index a19f0457..00000000
--- a/CPP/7zip/Archive/Common/CoderMixer.cpp
+++ /dev/null
@@ -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;
-}
-
-}
diff --git a/CPP/7zip/Archive/Common/CoderMixer.h b/CPP/7zip/Archive/Common/CoderMixer.h
deleted file mode 100644
index 6379dd80..00000000
--- a/CPP/7zip/Archive/Common/CoderMixer.h
+++ /dev/null
@@ -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
diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
deleted file mode 100644
index c0139862..00000000
--- a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
+++ /dev/null
@@ -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;
-}
-
-}
diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.h b/CPP/7zip/Archive/Common/CoderMixer2MT.h
deleted file mode 100644
index 41bb3e1c..00000000
--- a/CPP/7zip/Archive/Common/CoderMixer2MT.h
+++ /dev/null
@@ -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
diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp
deleted file mode 100644
index 127c1ed4..00000000
--- a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp
+++ /dev/null
@@ -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();
-}
-
-}
diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.h b/CPP/7zip/Archive/Common/CoderMixer2ST.h
deleted file mode 100644
index f2f7c4cb..00000000
--- a/CPP/7zip/Archive/Common/CoderMixer2ST.h
+++ /dev/null
@@ -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
diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.cpp b/CPP/7zip/Archive/Common/CoderMixerMT.cpp
deleted file mode 100644
index 96ea76a3..00000000
--- a/CPP/7zip/Archive/Common/CoderMixerMT.cpp
+++ /dev/null
@@ -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;
-}
-
-}
diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.h b/CPP/7zip/Archive/Common/CoderMixerMT.h
deleted file mode 100644
index d2891b26..00000000
--- a/CPP/7zip/Archive/Common/CoderMixerMT.h
+++ /dev/null
@@ -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
diff --git a/CPP/7zip/Archive/Common/FindSignature.cpp b/CPP/7zip/Archive/Common/FindSignature.cpp
index e9a0f032..fc952fa8 100644
--- a/CPP/7zip/Archive/Common/FindSignature.cpp
+++ b/CPP/7zip/Archive/Common/FindSignature.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include <string.h>
+
#include "../../../Common/MyBuffer.h"
#include "../../Common/StreamUtils.h"
diff --git a/CPP/7zip/Archive/Common/FindSignature.h b/CPP/7zip/Archive/Common/FindSignature.h
index e15af573..c359b9ed 100644
--- a/CPP/7zip/Archive/Common/FindSignature.h
+++ b/CPP/7zip/Archive/Common/FindSignature.h
@@ -1,7 +1,7 @@
// FindSignature.h
-#ifndef __FINDSIGNATURE_H
-#define __FINDSIGNATURE_H
+#ifndef __FIND_SIGNATURE_H
+#define __FIND_SIGNATURE_H
#include "../../IStream.h"
diff --git a/CPP/7zip/Archive/DllExports2.cpp b/CPP/7zip/Archive/DllExports2.cpp
index 2b196abe..979b4bf9 100644
--- a/CPP/7zip/Archive/DllExports2.cpp
+++ b/CPP/7zip/Archive/DllExports2.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../Common/MyWindows.h"
+
#include "../../Common/MyInitGuid.h"
#if defined(_7ZIP_LARGE_PAGES)
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h
index 2bab5299..498784b8 100644
--- a/CPP/7zip/Archive/Nsis/NsisIn.h
+++ b/CPP/7zip/Archive/Nsis/NsisIn.h
@@ -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 {
diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.cpp b/CPP/7zip/Archive/Rar/Rar5Handler.cpp
new file mode 100644
index 00000000..72fe4f68
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/Rar5Handler.cpp
@@ -0,0 +1,2683 @@
+// Rar5Handler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/7zCrc.h"
+#include "../../../../C/CpuArch.h"
+
+#include "../../../Common/ComTry.h"
+#include "../../../Common/IntToString.h"
+#include "../../../Common/UTFConvert.h"
+
+#include "../../../Windows/PropVariantUtils.h"
+#include "../../../Windows/TimeUtils.h"
+
+#include "../../IPassword.h"
+
+#include "../../Common/FilterCoder.h"
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/RegisterArc.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Common/StreamUtils.h"
+
+#include "../../Common/RegisterCodec.h"
+
+#include "../../Compress/CopyCoder.h"
+
+#include "../../Crypto/Rar5Aes.h"
+
+#include "../Common/FindSignature.h"
+#include "../Common/ItemNameUtils.h"
+
+#include "RarVol.h"
+#include "Rar5Handler.h"
+
+using namespace NWindows;
+
+#define Get32(p) GetUi32(p)
+
+namespace NArchive {
+
+namespace NRar {
+
+HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize);
+
+}
+
+namespace NRar5 {
+
+static const unsigned kMarkerSize = 8;
+
+#define SIGNATURE { 0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0 }
+
+static const Byte kMarker[kMarkerSize] = SIGNATURE;
+
+static const size_t kCommentSize_Max = (size_t)1 << 16;
+
+static const char * const kHostOS[] =
+{
+ "Windows"
+ , "Unix"
+};
+
+static const CUInt32PCharPair k_ArcFlags[] =
+{
+ { 0, "Volume" },
+ { 1, "VolumeField" },
+ { 2, "Solid" },
+ { 3, "Recovery" },
+ { 4, "Lock" }
+};
+
+
+
+template <unsigned alignMask>
+struct CAlignedBuffer
+{
+ Byte *_buf;
+ Byte *_bufBase;
+ size_t _size;
+
+ CAlignedBuffer(): _buf(NULL), _bufBase(NULL), _size(0) {}
+ ~CAlignedBuffer() { ::MyFree(_bufBase); }
+public:
+ operator Byte *() { return _buf; }
+ operator const Byte *() const { return _buf; }
+
+ void AllocAtLeast(size_t size)
+ {
+ if (_buf && _size >= size)
+ return;
+ ::MyFree(_bufBase);
+ _buf = NULL;
+ _size = 0;
+ _bufBase = (Byte *)::MyAlloc(size + alignMask);
+
+ if (_bufBase)
+ {
+ _size = size;
+ // _buf = (Byte *)(((uintptr_t)_bufBase + alignMask) & ~(uintptr_t)alignMask);
+ _buf = (Byte *)(((ptrdiff_t)_bufBase + alignMask) & ~(ptrdiff_t)alignMask);
+ }
+ }
+};
+
+static unsigned ReadVarInt(const Byte *p, size_t maxSize, UInt64 *val)
+{
+ *val = 0;
+
+ for (unsigned 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;
+}
+
+
+int CItem::FindExtra(unsigned type, unsigned &recordDataSize) const
+{
+ recordDataSize = 0;
+ size_t offset = 0;
+
+ for (;;)
+ {
+ size_t rem = Extra.Size() - offset;
+ if (rem == 0)
+ return -1;
+
+ {
+ UInt64 size;
+ unsigned num = ReadVarInt(Extra + offset, rem, &size);
+ if (num == 0)
+ return -1;
+ offset += num;
+ rem -= num;
+ if (size > rem)
+ return -1;
+ rem = (size_t)size;
+ }
+ {
+ UInt64 type2;
+ unsigned num = ReadVarInt(Extra + offset, rem, &type2);
+ if (num == 0)
+ return -1;
+ offset += num;
+ rem -= num;
+
+ // There was BUG in RAR 5.21- : it stored (size-1) instead of (size)
+ // for Subdata record in Service header.
+ // That record always was last in bad archives, so we can fix that case.
+ if (type2 == NExtraRecordType::kSubdata
+ && RecordType == NHeaderType::kService
+ && rem + 1 == Extra.Size() - offset)
+ rem++;
+
+ if (type2 == type)
+ {
+ recordDataSize = (unsigned)rem;
+ return (int)offset;
+ }
+
+ offset += rem;
+ }
+ }
+}
+
+
+bool CCryptoInfo::Parse(const Byte *p, size_t size)
+{
+ unsigned num = ReadVarInt(p, size, &Algo);
+ if (num == 0) return false; p += num; size -= num;
+
+ num = ReadVarInt(p, size, &Flags);
+ if (num == 0) return false; p += num; size -= num;
+
+ if (size != 1 + 16 + 16 + (unsigned)(IsThereCheck() ? 12 : 0))
+ return false;
+
+ Cnt = p[0];
+
+ return true;
+}
+
+
+bool CItem::FindExtra_Version(UInt64 &version) const
+{
+ unsigned size;
+ int offset = FindExtra(NExtraRecordType::kVersion, size);
+ if (offset < 0)
+ return false;
+ const Byte *p = Extra + (unsigned)offset;
+
+ UInt64 Flags;
+ unsigned num = ReadVarInt(p, size, &Flags);
+ if (num == 0) return false; p += num; size -= num;
+
+ num = ReadVarInt(p, size, &version);
+ if (num == 0) return false; p += num; size -= num;
+
+ return size == 0;
+}
+
+bool CItem::FindExtra_Link(CLinkInfo &link) const
+{
+ unsigned size;
+ int offset = FindExtra(NExtraRecordType::kLink, size);
+ if (offset < 0)
+ return false;
+ const Byte *p = Extra + (unsigned)offset;
+
+ unsigned num = ReadVarInt(p, size, &link.Type);
+ if (num == 0) return false; p += num; size -= num;
+
+ num = ReadVarInt(p, size, &link.Flags);
+ if (num == 0) return false; p += num; size -= num;
+
+ UInt64 len;
+ num = ReadVarInt(p, size, &len);
+ if (num == 0) return false; p += num; size -= num;
+
+ if (size != len)
+ return false;
+
+ link.NameLen = (unsigned)len;
+ link.NameOffset = (unsigned)(p - Extra);
+ return true;
+}
+
+bool CItem::Is_CopyLink() const
+{
+ CLinkInfo link;
+ return FindExtra_Link(link) && link.Type == NLinkType::kFileCopy;
+}
+
+void CItem::Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) const
+{
+ CLinkInfo link;
+ if (!FindExtra_Link(link))
+ return;
+
+ if (link.Type != linkType)
+ {
+ if (linkType != NLinkType::kUnixSymLink)
+ return;
+ switch ((unsigned)link.Type)
+ {
+ case NLinkType::kUnixSymLink:
+ case NLinkType::kWinSymLink:
+ case NLinkType::kWinJunction:
+ break;
+ default: return;
+ }
+ }
+
+ AString s;
+ s.SetFrom_CalcLen((const char *)(Extra + link.NameOffset), link.NameLen);
+
+ UString unicode;
+ if (ConvertUTF8ToUnicode(s, unicode))
+ prop = NItemName::GetOSName(unicode);
+}
+
+bool CItem::GetAltStreamName(AString &name) const
+{
+ name.Empty();
+ unsigned size;
+ int offset = FindExtra(NExtraRecordType::kSubdata, size);
+ if (offset < 0)
+ return false;
+ name.SetFrom_CalcLen((const char *)(Extra + (unsigned)offset), size);
+ return true;
+}
+
+
+class CHash
+{
+ bool _calcCRC;
+ UInt32 _crc;
+ int _blakeOffset;
+ CBlake2sp _blake;
+public:
+
+ void Init_NoCalc()
+ {
+ _calcCRC = false;
+ _crc = CRC_INIT_VAL;
+ _blakeOffset = -1;
+ }
+
+ void Init(const CItem &item);
+ void Update(const void *data, size_t size);
+ UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
+
+ bool Check(const CItem &item, NCrypto::NRar5::CDecoder *cryptoDecoderSpec);
+};
+
+void CHash::Init(const CItem &item)
+{
+ _crc = CRC_INIT_VAL;
+ _calcCRC = item.Has_CRC();
+
+ _blakeOffset = item.FindExtra_Blake();
+ if (_blakeOffset >= 0)
+ Blake2sp_Init(&_blake);
+}
+
+void CHash::Update(const void *data, size_t size)
+{
+ if (_calcCRC)
+ _crc = CrcUpdate(_crc, data, size);
+ if (_blakeOffset >= 0)
+ Blake2sp_Update(&_blake, (const Byte *)data, size);
+}
+
+bool CHash::Check(const CItem &item, NCrypto::NRar5::CDecoder *cryptoDecoderSpec)
+{
+ if (_calcCRC)
+ {
+ UInt32 crc = GetCRC();
+ if (cryptoDecoderSpec)
+ crc = cryptoDecoderSpec->Hmac_Convert_Crc32(crc);
+ if (crc != item.CRC)
+ return false;
+ }
+
+ if (_blakeOffset >= 0)
+ {
+ Byte digest[BLAKE2S_DIGEST_SIZE];
+ Blake2sp_Final(&_blake, digest);
+ if (cryptoDecoderSpec)
+ cryptoDecoderSpec->Hmac_Convert_32Bytes(digest);
+ if (memcmp(digest, &item.Extra[(unsigned)_blakeOffset], BLAKE2S_DIGEST_SIZE) != 0)
+ return false;
+ }
+
+ return true;
+}
+
+
+class COutStreamWithHash:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ ISequentialOutStream *_stream;
+ UInt64 _pos;
+ UInt64 _size;
+ bool _size_Defined;
+ Byte *_destBuf;
+public:
+ CHash _hash;
+
+ COutStreamWithHash(): _destBuf(NULL) {}
+
+ MY_UNKNOWN_IMP
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+ void Init(const CItem &item, Byte *destBuf)
+ {
+ _size_Defined = false;
+ _size = 0;
+ _destBuf = NULL;
+ if (!item.Is_UnknownSize())
+ {
+ _size_Defined = true;
+ _size = item.Size;
+ _destBuf = destBuf;
+ }
+ _pos = 0;
+ _hash.Init(item);
+ }
+ UInt64 GetPos() const { return _pos; }
+};
+
+
+STDMETHODIMP COutStreamWithHash::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ HRESULT result = S_OK;
+ if (_size_Defined)
+ {
+ UInt64 rem = _size - _pos;
+ if (size > rem)
+ size = (UInt32)rem;
+ }
+ if (_stream)
+ result = _stream->Write(data, size, &size);
+ if (_destBuf)
+ memcpy(_destBuf + (size_t)_pos, data, size);
+ _hash.Update(data, size);
+ _pos += size;
+ if (processedSize)
+ *processedSize = size;
+ return result;
+}
+
+
+
+
+
+class CInArchive
+{
+ CAlignedBuffer<AES_BLOCK_SIZE - 1> _buf;
+ size_t _bufSize;
+ size_t _bufPos;
+ ISequentialInStream *_stream;
+
+ NCrypto::NRar5::CDecoder *m_CryptoDecoderSpec;
+ CMyComPtr<ICompressFilter> m_CryptoDecoder;
+
+
+
+ HRESULT ReadStream_Check(void *data, size_t size);
+
+public:
+ bool m_CryptoMode;
+
+ bool WrongPassword;
+ bool IsArc;
+ bool UnexpectedEnd;
+
+ UInt64 StreamStartPosition;
+ UInt64 Position;
+
+ bool ReadVar(UInt64 &val);
+
+ struct CHeader
+ {
+ UInt64 Type;
+ UInt64 Flags;
+ size_t ExtraSize;
+ UInt64 DataSize;
+ };
+
+ HRESULT ReadBlockHeader(CHeader &h);
+ bool ReadFileHeader(const CHeader &header, CItem &item);
+ void AddToSeekValue(UInt64 addValue)
+ {
+ Position += addValue;
+ }
+
+ HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, ICryptoGetTextPassword *getTextPassword,
+ CInArcInfo &info);
+};
+
+
+static HRESULT MySetPassword(ICryptoGetTextPassword *getTextPassword, NCrypto::NRar5::CDecoder *cryptoDecoderSpec)
+{
+ CMyComBSTR password;
+ RINOK(getTextPassword->CryptoGetTextPassword(&password));
+ AString utf8;
+ const unsigned kPasswordLen_MAX = 127;
+ UString unicode = (LPCOLESTR)password;
+ if (unicode.Len() > kPasswordLen_MAX)
+ unicode.DeleteFrom(kPasswordLen_MAX);
+ ConvertUnicodeToUTF8(unicode, utf8);
+ cryptoDecoderSpec->SetPassword((const Byte *)(const char *)utf8, utf8.Len());
+ return S_OK;
+}
+
+
+bool CInArchive::ReadVar(UInt64 &val)
+{
+ unsigned offset = ReadVarInt(_buf + _bufPos, _bufSize - _bufPos, &val);
+ _bufPos += offset;
+ return (offset != 0);
+}
+
+
+HRESULT CInArchive::ReadStream_Check(void *data, size_t size)
+{
+ size_t size2 = size;
+ RINOK(ReadStream(_stream, data, &size2));
+ if (size2 == size)
+ return S_OK;
+ UnexpectedEnd = true;
+ return S_FALSE;
+}
+
+
+HRESULT CInArchive::ReadBlockHeader(CHeader &h)
+{
+ h.Type = 0;
+ h.Flags = 0;
+ h.ExtraSize = 0;
+ h.DataSize = 0;
+
+ const unsigned kStartSize = 4 + 3;
+ const unsigned kBufSize = AES_BLOCK_SIZE + AES_BLOCK_SIZE; // must be >= kStartSize;
+ Byte buf[kBufSize];
+ unsigned filled;
+
+ if (m_CryptoMode)
+ {
+ RINOK(ReadStream_Check(buf, kBufSize));
+ memcpy(m_CryptoDecoderSpec->_iv, buf, AES_BLOCK_SIZE);
+ RINOK(m_CryptoDecoderSpec->Init());
+
+ _buf.AllocAtLeast(1 << 12);
+ if (!(Byte *)_buf)
+ return E_OUTOFMEMORY;
+
+ memcpy(_buf, buf + AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+ if (m_CryptoDecoderSpec->Filter(_buf, AES_BLOCK_SIZE) != AES_BLOCK_SIZE)
+ return E_FAIL;
+ memcpy(buf, _buf, AES_BLOCK_SIZE);
+ filled = AES_BLOCK_SIZE;
+ }
+ else
+ {
+ RINOK(ReadStream_Check(buf, kStartSize));
+ filled = kStartSize;
+ }
+
+ UInt64 val;
+ unsigned offset = ReadVarInt(buf + 4, 3, &val);
+ if (offset == 0)
+ return S_FALSE;
+ {
+ size_t size = (size_t)val;
+ _bufPos = (4 + offset);
+ _bufSize = _bufPos + size;
+ if (size < 2)
+ return S_FALSE;
+ }
+
+ size_t allocSize = _bufSize;
+ if (m_CryptoMode)
+ allocSize = (allocSize + AES_BLOCK_SIZE - 1) & ~(size_t)(AES_BLOCK_SIZE - 1);
+ _buf.AllocAtLeast(allocSize);
+ if (!(Byte *)_buf)
+ return E_OUTOFMEMORY;
+
+ memcpy(_buf, buf, filled);
+
+ size_t rem = allocSize - filled;
+ AddToSeekValue(allocSize + (m_CryptoMode ? AES_BLOCK_SIZE : 0));
+ RINOK(ReadStream_Check(_buf + filled, rem));
+ if (m_CryptoMode)
+ {
+ if (m_CryptoDecoderSpec->Filter(_buf + filled, (UInt32)rem) != rem)
+ return E_FAIL;
+ }
+
+ if (CrcCalc(_buf + 4, _bufSize - 4) != Get32(buf))
+ return S_FALSE;
+
+ if (!ReadVar(h.Type)) return S_FALSE;
+ if (!ReadVar(h.Flags)) return S_FALSE;
+
+ if (h.Flags & NHeaderFlags::kExtra)
+ {
+ UInt64 extraSize;
+ if (!ReadVar(extraSize))
+ return S_FALSE;
+ if (extraSize > _bufSize)
+ return S_FALSE;
+ h.ExtraSize = (size_t)extraSize;
+ }
+
+ if (h.Flags & NHeaderFlags::kData)
+ {
+ if (!ReadVar(h.DataSize))
+ return S_FALSE;
+ }
+
+ return S_OK;
+}
+
+
+/*
+int CInArcInfo::FindExtra(unsigned type, unsigned &recordDataSize) const
+{
+ recordDataSize = 0;
+ size_t offset = 0;
+
+ for (;;)
+ {
+ size_t rem = Extra.Size() - offset;
+ if (rem == 0)
+ return -1;
+
+ {
+ UInt64 size;
+ unsigned num = ReadVarInt(Extra + offset, rem, &size);
+ if (num == 0)
+ return -1;
+ offset += num;
+ rem -= num;
+ if (size > rem)
+ return -1;
+ rem = (size_t)size;
+ }
+ {
+ UInt64 type2;
+ unsigned num = ReadVarInt(Extra + offset, rem, &type2);
+ if (num == 0)
+ return -1;
+ offset += num;
+ rem -= num;
+
+ if (type2 == type)
+ {
+ recordDataSize = (unsigned)rem;
+ return (int)offset;
+ }
+
+ offset += rem;
+ }
+ }
+}
+
+
+bool CInArcInfo::FindExtra_Locator(CLocator &locator) const
+{
+ locator.Flags = 0;
+ locator.QuickOpen = 0;
+ locator.Recovery = 0;
+
+ unsigned size;
+ int offset = FindExtra(kArcExtraRecordType_Locator, size);
+ if (offset < 0)
+ return false;
+ const Byte *p = Extra + (unsigned)offset;
+
+ unsigned num;
+
+ num = ReadVarInt(p, size, &locator.Flags);
+ if (num == 0) return false; p += num; size -= num;
+
+ if (locator.Is_QuickOpen())
+ {
+ num = ReadVarInt(p, size, &locator.QuickOpen);
+ if (num == 0) return false; p += num; size -= num;
+ }
+
+ if (locator.Is_Recovery())
+ {
+ num = ReadVarInt(p, size, &locator.Recovery);
+ if (num == 0) return false; p += num; size -= num;
+ }
+
+ return true;
+}
+*/
+
+
+HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit, ICryptoGetTextPassword *getTextPassword,
+ CInArcInfo &info)
+{
+ m_CryptoMode = false;
+
+ WrongPassword = false;
+ IsArc = false;
+ UnexpectedEnd = false;
+
+ Position = StreamStartPosition;
+
+ UInt64 arcStartPos = StreamStartPosition;
+ {
+ Byte marker[kMarkerSize];
+ RINOK(ReadStream_FALSE(stream, marker, kMarkerSize));
+ if (memcmp(marker, kMarker, kMarkerSize) == 0)
+ Position += kMarkerSize;
+ else
+ {
+ if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0)
+ return S_FALSE;
+ RINOK(stream->Seek(StreamStartPosition, STREAM_SEEK_SET, NULL));
+ RINOK(FindSignatureInStream(stream, kMarker, kMarkerSize,
+ searchHeaderSizeLimit, arcStartPos));
+ arcStartPos += StreamStartPosition;
+ Position = arcStartPos + kMarkerSize;
+ RINOK(stream->Seek(Position, STREAM_SEEK_SET, NULL));
+ }
+ }
+
+ info.StartPos = arcStartPos;
+ _stream = stream;
+
+ CHeader h;
+ RINOK(ReadBlockHeader(h));
+ info.IsEncrypted = false;
+
+ if (h.Type == NHeaderType::kArcEncrypt)
+ {
+ info.IsEncrypted = true;
+ IsArc = true;
+ if (!getTextPassword)
+ return E_NOTIMPL;
+
+ m_CryptoMode = true;
+
+ if (!m_CryptoDecoder)
+ {
+ m_CryptoDecoderSpec = new NCrypto::NRar5::CDecoder;
+ m_CryptoDecoder = m_CryptoDecoderSpec;
+ }
+
+ RINOK(m_CryptoDecoderSpec->SetDecoderProps(
+ _buf + _bufPos, (unsigned)(_bufSize - _bufPos), false, false));
+
+ RINOK(MySetPassword(getTextPassword, m_CryptoDecoderSpec));
+
+ if (!m_CryptoDecoderSpec->CalcKey_and_CheckPassword())
+ {
+ WrongPassword = True;
+ return S_FALSE;
+ }
+
+ RINOK(ReadBlockHeader(h));
+ }
+
+ if (h.Type != NHeaderType::kArc)
+ return S_FALSE;
+
+ IsArc = true;
+ info.VolNumber = 0;
+
+ if (!ReadVar(info.Flags))
+ return S_FALSE;
+
+ if (info.Flags & NArcFlags::kVolNumber)
+ if (!ReadVar(info.VolNumber))
+ return S_FALSE;
+
+ if (h.ExtraSize != 0)
+ {
+ if (_bufSize - _bufPos < h.ExtraSize)
+ return S_FALSE;
+ /*
+ info.Extra.Alloc(h.ExtraSize);
+ memcpy(info.Extra, _buf + _bufPos, h.ExtraSize);
+ */
+ _bufPos += h.ExtraSize;
+
+ /*
+ CInArcInfo::CLocator locator;
+ if (info.FindExtra_Locator(locator))
+ locator.Flags = locator.Flags;
+ */
+ }
+
+ if (_bufPos != _bufSize)
+ return S_FALSE;
+
+ return S_OK;
+}
+
+
+bool CInArchive::ReadFileHeader(const CHeader &header, CItem &item)
+{
+ item.UnixMTime = 0;
+ item.CRC = 0;
+ item.Flags = 0;
+
+ item.CommonFlags = (UInt32)header.Flags;
+ item.PackSize = header.DataSize;
+
+ UInt64 flags64;
+ if (!ReadVar(flags64)) return false;
+ item.Flags = (UInt32)flags64;
+
+ if (!ReadVar(item.Size)) return false;
+
+ {
+ UInt64 attrib;
+ if (!ReadVar(attrib)) return false;
+ item.Attrib = (UInt32)attrib;
+ }
+
+ if (item.Has_UnixMTime())
+ {
+ if (_bufSize - _bufPos < 4)
+ return false;
+ item.UnixMTime = Get32(_buf + _bufPos);
+ _bufPos += 4;
+ }
+
+ if (item.Has_CRC())
+ {
+ if (_bufSize - _bufPos < 4)
+ return false;
+ item.CRC = Get32(_buf + _bufPos);
+ _bufPos += 4;
+ }
+
+ {
+ UInt64 method;
+ if (!ReadVar(method)) return false;
+ item.Method = (UInt32)method;
+ }
+
+ if (!ReadVar(item.HostOS)) return false;
+
+ {
+ UInt64 len;
+ if (!ReadVar(len)) return false;
+ if (len > _bufSize - _bufPos)
+ return false;
+ item.Name.SetFrom_CalcLen((const char *)(_buf + _bufPos), (unsigned)len);
+ _bufPos += (unsigned)len;
+ }
+
+ item.Extra.Free();
+ size_t extraSize = header.ExtraSize;
+ if (extraSize != 0)
+ {
+ if (_bufSize - _bufPos < extraSize)
+ return false;
+ item.Extra.Alloc(extraSize);
+ memcpy(item.Extra, _buf + _bufPos, extraSize);
+ _bufPos += extraSize;
+ }
+
+
+ return (_bufPos == _bufSize);
+}
+
+
+
+struct CLinkFile
+{
+ unsigned Index;
+ unsigned NumLinks;
+ CByteBuffer Data;
+ HRESULT Res;
+ bool crcOK;
+
+ CLinkFile(): Index(0), NumLinks(0), Res(S_OK), crcOK(true) {}
+};
+
+
+struct CUnpacker
+{
+ NCompress::CCopyCoder *copyCoderSpec;
+ CMyComPtr<ICompressCoder> copyCoder;
+
+ CMyComPtr<ICompressCoder> LzCoders[2];
+ bool NeedClearSolid[2];
+
+ CFilterCoder *filterStreamSpec;
+ CMyComPtr<ISequentialInStream> filterStream;
+
+ NCrypto::NRar5::CDecoder *cryptoDecoderSpec;
+ CMyComPtr<ICompressFilter> cryptoDecoder;
+
+ CMyComPtr<ICryptoGetTextPassword> getTextPassword;
+
+ COutStreamWithHash *outStreamSpec;
+ CMyComPtr<ISequentialOutStream> outStream;
+
+ CByteBuffer _tempBuf;
+
+ CLinkFile *linkFile;
+
+ CUnpacker(): linkFile(NULL) { NeedClearSolid[0] = NeedClearSolid[1] = true; }
+
+ HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, bool isSolid, bool &wrongPassword);
+
+ HRESULT Code(const CItem &item, const CItem &lastItem, UInt64 packSize,
+ ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress,
+ bool &isCrcOK);
+
+ HRESULT DecodeToBuf(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, UInt64 packSize, ISequentialInStream *inStream, CByteBuffer &buffer);
+};
+
+
+static const unsigned kLzMethodMax = 5;
+
+HRESULT CUnpacker::Create(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, bool isSolid, bool &wrongPassword)
+{
+ wrongPassword = false;
+
+ if (item.GetAlgoVersion() != 0)
+ return E_NOTIMPL;
+
+ if (!outStream)
+ {
+ outStreamSpec = new COutStreamWithHash;
+ outStream = outStreamSpec;
+ }
+
+ unsigned method = item.GetMethod();
+
+ if (method == 0)
+ {
+ if (!copyCoder)
+ {
+ copyCoderSpec = new NCompress::CCopyCoder;
+ copyCoder = copyCoderSpec;
+ }
+ }
+ else
+ {
+ if (method > kLzMethodMax)
+ return E_NOTIMPL;
+
+ /*
+ if (item.IsSplitBefore())
+ return S_FALSE;
+ */
+
+ int lzIndex = item.IsService() ? 1 : 0;
+ CMyComPtr<ICompressCoder> &lzCoder = LzCoders[lzIndex];
+
+ if (!lzCoder)
+ {
+ const UInt32 methodID = 0x40305;
+ RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodID, false, lzCoder));
+ if (!lzCoder)
+ return E_NOTIMPL;
+ }
+
+ CMyComPtr<ICompressSetDecoderProperties2> csdp;
+ RINOK(lzCoder.QueryInterface(IID_ICompressSetDecoderProperties2, &csdp));
+
+ Byte props[2] = { (Byte)(item.GetDictSize()), (Byte)(isSolid ? 1 : 0) };
+ RINOK(csdp->SetDecoderProperties2(props, 2));
+ }
+
+ unsigned cryptoSize = 0;
+ int cryptoOffset = item.FindExtra(NExtraRecordType::kCrypto, cryptoSize);
+
+ if (cryptoOffset >= 0)
+ {
+ if (!filterStream)
+ {
+ filterStreamSpec = new CFilterCoder(false);
+ filterStream = filterStreamSpec;
+ }
+
+ if (!cryptoDecoder)
+ {
+ cryptoDecoderSpec = new NCrypto::NRar5::CDecoder;
+ cryptoDecoder = cryptoDecoderSpec;
+ }
+
+ RINOK(cryptoDecoderSpec->SetDecoderProps(item.Extra + (unsigned)cryptoOffset, cryptoSize, true, item.IsService()));
+
+ if (!getTextPassword)
+ {
+ wrongPassword = True;
+ return E_NOTIMPL;
+ }
+
+ RINOK(MySetPassword(getTextPassword, cryptoDecoderSpec));
+
+ if (!cryptoDecoderSpec->CalcKey_and_CheckPassword())
+ wrongPassword = True;
+ }
+
+ return S_OK;
+}
+
+
+HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSize,
+ ISequentialInStream *volsInStream, ISequentialOutStream *realOutStream, ICompressProgressInfo *progress,
+ bool &isCrcOK)
+{
+ isCrcOK = true;
+
+ unsigned method = item.GetMethod();
+ if (method > kLzMethodMax)
+ return E_NOTIMPL;
+
+ if (linkFile && !lastItem.Is_UnknownSize())
+ {
+ size_t dataSize = (size_t)lastItem.Size;
+ if (dataSize != lastItem.Size)
+ return E_NOTIMPL;
+ linkFile->Data.Alloc(dataSize);
+ }
+
+ bool isCryptoMode = false;
+ ISequentialInStream *inStream;
+
+ if (item.IsEncrypted())
+ {
+ filterStreamSpec->Filter = cryptoDecoder;
+ filterStreamSpec->SetInStream(volsInStream);
+ filterStreamSpec->SetOutStreamSize(NULL);
+ inStream = filterStream;
+ isCryptoMode = true;
+ }
+ else
+ inStream = volsInStream;
+
+ ICompressCoder *commonCoder = (method == 0) ? copyCoder : LzCoders[item.IsService() ? 1 : 0];
+
+ outStreamSpec->SetStream(realOutStream);
+ outStreamSpec->Init(lastItem, (linkFile ? (Byte *)linkFile->Data : NULL));
+
+ NeedClearSolid[item.IsService() ? 1 : 0] = false;
+
+ HRESULT res = S_OK;
+ if (packSize != 0 || lastItem.Is_UnknownSize() || lastItem.Size != 0)
+ {
+ res = commonCoder->Code(inStream, outStream, &packSize,
+ lastItem.Is_UnknownSize() ? NULL : &lastItem.Size, progress);
+ }
+ else
+ {
+ res = res;
+ }
+
+ if (isCryptoMode)
+ filterStreamSpec->ReleaseInStream();
+
+ UInt64 processedSize = outStreamSpec->GetPos();
+ if (res == S_OK && !lastItem.Is_UnknownSize() && processedSize != lastItem.Size)
+ res = S_FALSE;
+
+ // if (res == S_OK)
+ {
+ unsigned cryptoSize = 0;
+ int cryptoOffset = lastItem.FindExtra(NExtraRecordType::kCrypto, cryptoSize);
+ NCrypto::NRar5::CDecoder *crypto = NULL;
+
+ if (cryptoOffset >= 0)
+ {
+ CCryptoInfo cryptoInfo;
+ if (cryptoInfo.Parse(lastItem.Extra + (unsigned)cryptoOffset, cryptoSize))
+ if (cryptoInfo.UseMAC())
+ crypto = cryptoDecoderSpec;
+ }
+
+ isCrcOK = outStreamSpec->_hash.Check(lastItem, crypto);
+ }
+
+ if (linkFile)
+ {
+ linkFile->Res = res;
+ linkFile->crcOK = isCrcOK;
+ if (!lastItem.Is_UnknownSize() && processedSize != lastItem.Size)
+ linkFile->Data.ChangeSize_KeepData((size_t)processedSize, (size_t)processedSize);
+ }
+
+ return res;
+}
+
+
+HRESULT CUnpacker::DecodeToBuf(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, UInt64 packSize, ISequentialInStream *inStream, CByteBuffer &buffer)
+{
+ CBufPtrSeqOutStream *outSpec = new CBufPtrSeqOutStream;
+ CMyComPtr<ISequentialOutStream> out = outSpec;
+ _tempBuf.AllocAtLeast((size_t)item.Size);
+ outSpec->Init(_tempBuf, (size_t)item.Size);
+
+ bool wrongPassword;
+
+ if (item.IsSolid())
+ return E_NOTIMPL;
+
+ HRESULT res = Create(EXTERNAL_CODECS_LOC_VARS item, item.IsSolid(), wrongPassword);
+
+ if (res == S_OK)
+ {
+ if (wrongPassword)
+ return S_FALSE;
+
+ CLimitedSequentialInStream *limitedStreamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> limitedStream(limitedStreamSpec);
+ limitedStreamSpec->SetStream(inStream);
+ limitedStreamSpec->Init(packSize);
+
+ bool crcOK = true;
+ res = Code(item, item, packSize, limitedStream, out, NULL, crcOK);
+ if (res == S_OK)
+ {
+ if (!crcOK || outSpec->GetPos() != item.Size)
+ res = S_FALSE;
+ else
+ buffer.CopyFrom(_tempBuf, (size_t)item.Size);
+ }
+ }
+
+ return res;
+}
+
+
+struct CTempBuf
+{
+ CByteBuffer _buf;
+ size_t _offset;
+ bool _isOK;
+
+ void Clear()
+ {
+ _offset = 0;
+ _isOK = true;
+ }
+
+ CTempBuf() { Clear(); }
+
+ HRESULT Decode(DECL_EXTERNAL_CODECS_LOC_VARS
+ const CItem &item,
+ ISequentialInStream *inStream, CUnpacker &unpacker, CByteBuffer &destBuf);
+};
+
+
+HRESULT CTempBuf::Decode(DECL_EXTERNAL_CODECS_LOC_VARS
+ const CItem &item,
+ ISequentialInStream *inStream,
+ CUnpacker &unpacker,
+ CByteBuffer &destBuf)
+{
+ const size_t kPackSize_Max = (1 << 24);
+ if (item.Size > (1 << 24)
+ || item.Size == 0
+ || item.PackSize >= kPackSize_Max)
+ {
+ Clear();
+ return S_OK;
+ }
+
+ if (item.IsSplit() /* && _isOK */)
+ {
+ size_t packSize = (size_t)item.PackSize;
+ if (packSize > kPackSize_Max - _offset)
+ return S_OK;
+ size_t newSize = _offset + packSize;
+ if (newSize > _buf.Size())
+ _buf.ChangeSize_KeepData(newSize, _offset);
+
+ Byte *data = (Byte *)_buf + _offset;
+ RINOK(ReadStream_FALSE(inStream, data, packSize));
+
+ _offset += packSize;
+
+ if (item.IsSplitAfter())
+ {
+ CHash hash;
+ hash.Init(item);
+ hash.Update(data, packSize);
+ _isOK = hash.Check(item, NULL); // RAR5 doesn't use HMAC for packed part
+ }
+ }
+
+ if (_isOK)
+ {
+ if (!item.IsSplitAfter())
+ {
+ if (_offset == 0)
+ {
+ RINOK(unpacker.DecodeToBuf(EXTERNAL_CODECS_LOC_VARS
+ item, item.PackSize, inStream, destBuf));
+ }
+ else
+ {
+ CBufInStream *bufInStreamSpec = new CBufInStream;
+ CMyComPtr<ISequentialInStream> bufInStream = bufInStreamSpec;
+ bufInStreamSpec->Init(_buf, _offset);
+ RINOK(unpacker.DecodeToBuf(EXTERNAL_CODECS_LOC_VARS
+ item, _offset, bufInStream, destBuf));
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+
+
+static const Byte kProps[] =
+{
+ kpidPath,
+ kpidIsDir,
+ kpidSize,
+ kpidPackSize,
+ kpidMTime,
+ kpidCTime,
+ kpidATime,
+ kpidAttrib,
+
+ kpidIsAltStream,
+ kpidEncrypted,
+ kpidSolid,
+ kpidSplitBefore,
+ kpidSplitAfter,
+ kpidCRC,
+ kpidHostOS,
+ kpidMethod,
+
+ kpidSymLink,
+ kpidHardLink,
+ kpidCopyLink,
+};
+
+
+static const Byte kArcProps[] =
+{
+ kpidTotalPhySize,
+ kpidCharacts,
+ kpidSolid,
+ kpidNumBlocks,
+ kpidEncrypted,
+ kpidIsVolume,
+ kpidVolumeIndex,
+ kpidNumVolumes,
+ kpidComment
+};
+
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+
+UInt64 CHandler::GetPackSize(unsigned refIndex) const
+{
+ UInt64 size = 0;
+ unsigned index = _refs[refIndex].Item;
+ for (;;)
+ {
+ const CItem &item = _items[index];
+ size += item.PackSize;
+ if (item.NextItem < 0)
+ return size;
+ index = item.NextItem;
+ }
+}
+
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+
+ NCOM::CPropVariant prop;
+
+ const CInArcInfo *arcInfo = NULL;
+ if (!_arcs.IsEmpty())
+ arcInfo = &_arcs[0].Info;
+
+ switch (propID)
+ {
+ case kpidVolumeIndex: if (arcInfo && arcInfo->IsVolume()) prop = arcInfo->GetVolIndex(); break;
+ case kpidSolid: if (arcInfo) prop = arcInfo->IsSolid(); break;
+ case kpidCharacts:
+ {
+ if (!_arcs.IsEmpty())
+ {
+ FLAGS_TO_PROP(k_ArcFlags, (UInt32)arcInfo->Flags, prop);
+ }
+ break;
+ }
+ case kpidEncrypted: if (arcInfo) prop = arcInfo->IsEncrypted; break; // it's for encrypted names.
+ case kpidIsVolume: if (arcInfo) prop = arcInfo->IsVolume(); break;
+ case kpidNumVolumes: prop = (UInt32)_arcs.Size(); break;
+ case kpidOffset: if (arcInfo && arcInfo->StartPos != 0) prop = arcInfo->StartPos; break;
+
+ case kpidTotalPhySize:
+ {
+ if (_arcs.Size() > 1)
+ {
+ UInt64 sum = 0;
+ FOR_VECTOR (v, _arcs)
+ sum += _arcs[v].Info.GetPhySize();
+ prop = sum;
+ }
+ break;
+ }
+
+ case kpidPhySize:
+ {
+ if (arcInfo)
+ prop = arcInfo->GetPhySize();
+ break;
+ }
+
+ case kpidComment:
+ {
+ // if (!_arcs.IsEmpty())
+ {
+ // const CArc &arc = _arcs[0];
+ const CByteBuffer &cmt = _comment;
+ if (cmt.Size() != 0 && cmt.Size() < (1 << 16))
+ {
+ AString s;
+ s.SetFrom_CalcLen((const char *)(const Byte *)cmt, (unsigned)cmt.Size());
+ UString unicode;
+ if (ConvertUTF8ToUnicode(s, unicode))
+ prop = unicode;
+ }
+ }
+ break;
+ }
+
+ case kpidNumBlocks:
+ {
+ UInt32 numBlocks = 0;
+ FOR_VECTOR (i, _refs)
+ if (!_items[_refs[i].Item].IsSolid())
+ numBlocks++;
+ prop = (UInt32)numBlocks;
+ break;
+ }
+
+ case kpidErrorFlags:
+ {
+ UInt32 v = _errorFlags;
+ if (!_isArc)
+ v |= kpv_ErrorFlags_IsNotArc;
+ prop = v;
+ break;
+ }
+
+ /*
+ case kpidWarningFlags:
+ {
+ if (_warningFlags != 0)
+ prop = _warningFlags;
+ break;
+ }
+ */
+
+ case kpidExtension:
+ if (_arcs.Size() == 1)
+ {
+ if (arcInfo->IsVolume())
+ {
+ char sz[32];
+ ConvertUInt64ToString(arcInfo->GetVolIndex() + 1, sz);
+ unsigned len = MyStringLen(sz);
+ AString s = "part";
+ for (; len < 2; len++)
+ s += '0';
+ s += sz;
+ s += ".rar";
+ prop = s;
+ }
+ }
+ break;
+
+ case kpidIsAltStream: prop = true; break;
+ }
+
+ prop.Detach(value);
+ return S_OK;
+
+ COM_TRY_END
+}
+
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = _refs.Size();
+ return S_OK;
+}
+
+
+static const Byte kRawProps[] =
+{
+ kpidChecksum,
+ kpidNtSecure
+};
+
+
+STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps)
+{
+ *numProps = ARRAY_SIZE(kRawProps);
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID)
+{
+ *propID = kRawProps[index];
+ *name = 0;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType)
+{
+ *parentType = NParentType::kDir;
+ *parent = (UInt32)(Int32)-1;
+
+ if (index >= _refs.Size())
+ return S_OK;
+
+ const CRefItem &ref = _refs[index];
+ const CItem &item = _items[ref.Item];
+
+ if (item.Is_STM() && ref.Parent >= 0)
+ {
+ *parent = (UInt32)ref.Parent;
+ *parentType = NParentType::kAltStream;
+ }
+
+ return S_OK;
+}
+
+
+STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)
+{
+ *data = NULL;
+ *dataSize = 0;
+ *propType = 0;
+
+ if (index >= _refs.Size())
+ return E_INVALIDARG;
+
+ const CItem &item = _items[_refs[index].Item];
+
+ if (propID == kpidNtSecure)
+ {
+ if (item.ACL >= 0)
+ {
+ const CByteBuffer &buf = _acls[item.ACL];
+ *dataSize = (UInt32)buf.Size();
+ *propType = NPropDataType::kRaw;
+ *data = (const Byte *)buf;
+ }
+ return S_OK;
+ }
+
+ if (propID == kpidChecksum)
+ {
+ int hashRecOffset = item.FindExtra_Blake();
+ if (hashRecOffset >= 0)
+ {
+ *dataSize = BLAKE2S_DIGEST_SIZE;
+ *propType = NPropDataType::kRaw;
+ *data = &item.Extra[hashRecOffset];
+ }
+ return S_OK;
+ }
+
+ return S_OK;
+}
+
+
+static void TimeRecordToProp(const CItem &item, unsigned stampIndex, NCOM::CPropVariant &prop)
+{
+ unsigned size;
+ int offset = item.FindExtra(NExtraRecordType::kTime, size);
+ if (offset < 0)
+ return;
+
+ const Byte *p = item.Extra + (unsigned)offset;
+ UInt64 flags;
+ {
+ unsigned num = ReadVarInt(p, size, &flags);
+ if (num == 0)
+ return;
+ p += num;
+ size -= num;
+ }
+
+ if ((flags & (NTimeRecord::NFlags::kMTime << stampIndex)) == 0)
+ return;
+
+ unsigned numStamps = 0;
+ unsigned i;
+ for (i = 0; i < 3; i++)
+ if ((flags & (NTimeRecord::NFlags::kMTime << i)) != 0)
+ numStamps++;
+ unsigned stampSizeLog = ((flags & NTimeRecord::NFlags::kUnixTime) != 0) ? 2 : 3;
+
+ if ((numStamps << stampSizeLog) != size)
+ return;
+
+ numStamps = 0;
+ for (i = 0; i < stampIndex; i++)
+ if ((flags & (NTimeRecord::NFlags::kMTime << i)) != 0)
+ numStamps++;
+
+ p += (numStamps << stampSizeLog);
+
+ FILETIME ft;
+ if ((flags & NTimeRecord::NFlags::kUnixTime) != 0)
+ NWindows::NTime::UnixTimeToFileTime(Get32(p), ft);
+ else
+ {
+ ft.dwLowDateTime = Get32(p);
+ ft.dwHighDateTime = Get32(p + 4);
+ }
+
+ prop = ft;
+}
+
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+
+ NCOM::CPropVariant prop;
+ const CRefItem &ref = _refs[index];
+ const CItem &item = _items[ref.Item];
+ const CItem &lastItem = _items[ref.Last];
+
+ switch (propID)
+ {
+ case kpidPath:
+ {
+ UString unicodeName;
+
+ if (item.Is_STM())
+ {
+ AString s;
+ if (ref.Parent >= 0)
+ {
+ CItem &mainItem = _items[_refs[ref.Parent].Item];
+ s = mainItem.Name;
+ }
+
+ AString name;
+ item.GetAltStreamName(name);
+ if (name[0] != ':')
+ s += ':';
+ s += name;
+ if (!ConvertUTF8ToUnicode(s, unicodeName))
+ break;
+ }
+ else
+ {
+ if (!ConvertUTF8ToUnicode(item.Name, unicodeName))
+ break;
+ if (item.Version_Defined)
+ {
+ wchar_t temp[32];
+ // temp[0] = ';';
+ // ConvertUInt64ToString(item.Version, temp + 1);
+ // unicodeName += temp;
+ ConvertUInt64ToString(item.Version, temp);
+ UString s2 = L"[VER]" WSTRING_PATH_SEPARATOR;
+ s2 += temp;
+ s2.Add_PathSepar();
+ unicodeName.Insert(0, s2);
+ }
+ }
+
+ NItemName::ConvertToOSName2(unicodeName);
+ prop = unicodeName;
+
+ break;
+ }
+
+ case kpidIsDir: prop = item.IsDir(); break;
+ case kpidSize: if (!lastItem.Is_UnknownSize()) prop = lastItem.Size; break;
+ case kpidPackSize: prop = GetPackSize(index); break;
+
+ case kpidMTime:
+ {
+ TimeRecordToProp(item, NTimeRecord::k_Index_MTime, prop);
+ if (prop.vt == VT_EMPTY && item.Has_UnixMTime())
+ {
+ FILETIME ft;
+ NWindows::NTime::UnixTimeToFileTime(item.UnixMTime, ft);
+ prop = ft;
+ }
+ if (prop.vt == VT_EMPTY && ref.Parent >= 0)
+ {
+ const CItem &baseItem = _items[_refs[ref.Parent].Item];
+ TimeRecordToProp(baseItem, NTimeRecord::k_Index_MTime, prop);
+ if (prop.vt == VT_EMPTY && baseItem.Has_UnixMTime())
+ {
+ FILETIME ft;
+ NWindows::NTime::UnixTimeToFileTime(baseItem.UnixMTime, ft);
+ prop = ft;
+ }
+ }
+ break;
+ }
+ case kpidCTime: TimeRecordToProp(item, NTimeRecord::k_Index_CTime, prop); break;
+ case kpidATime: TimeRecordToProp(item, NTimeRecord::k_Index_ATime, prop); break;
+
+ case kpidName:
+ {
+ if (item.Is_STM())
+ {
+ AString name;
+ item.GetAltStreamName(name);
+ if (name[0] == ':')
+ {
+ name.DeleteFrontal(1);
+ UString unicodeName;
+ if (ConvertUTF8ToUnicode(name, unicodeName))
+ prop = unicodeName;
+ }
+ }
+ break;
+ }
+
+ case kpidIsAltStream: prop = item.Is_STM(); break;
+
+ case kpidSymLink: item.Link_to_Prop(NLinkType::kUnixSymLink, prop); break;
+ case kpidHardLink: item.Link_to_Prop(NLinkType::kHardLink, prop); break;
+ case kpidCopyLink: item.Link_to_Prop(NLinkType::kFileCopy, prop); break;
+
+ case kpidAttrib: prop = item.GetWinAttrib(); break;
+ case kpidEncrypted: prop = item.IsEncrypted(); break;
+ case kpidSolid: prop = item.IsSolid(); break;
+
+ case kpidSplitBefore: prop = item.IsSplitBefore(); break;
+ case kpidSplitAfter: prop = lastItem.IsSplitAfter(); break;
+ case kpidCRC:
+ {
+ const CItem *item2 = (lastItem.IsSplitAfter() ? &item : &lastItem);
+ if (item2->Has_CRC())
+ prop = item2->CRC;
+ break;
+ }
+
+ case kpidMethod:
+ {
+ char temp[64];
+ unsigned algo = item.GetAlgoVersion();
+ char *s = temp;
+ if (algo != 0)
+ {
+ ConvertUInt32ToString(algo, s);
+ s += MyStringLen(s);
+ *s++ = ':';
+ }
+ unsigned m = item.GetMethod();
+ {
+ s[0] = 'm';
+ s[1] = (char)(m + '0');
+ s[2] = 0;
+ if (!item.IsDir())
+ {
+ s[2] = ':';
+ ConvertUInt32ToString(item.GetDictSize() + 17, s + 3);
+ }
+ }
+
+ unsigned cryptoSize = 0;
+ int cryptoOffset = item.FindExtra(NExtraRecordType::kCrypto, cryptoSize);
+ if (cryptoOffset >= 0)
+ {
+ s = temp + strlen(temp);
+ *s++ = ' ';
+ strcpy(s, "AES:");
+ CCryptoInfo cryptoInfo;
+ if (cryptoInfo.Parse(item.Extra + (unsigned)cryptoOffset, cryptoSize))
+ {
+ s += strlen(s);
+ ConvertUInt32ToString(cryptoInfo.Cnt, s);
+ s += strlen(s);
+ *s++ = ':';
+ ConvertUInt64ToString(cryptoInfo.Flags, s);
+ }
+ }
+
+ prop = temp;
+ break;
+ }
+
+ case kpidHostOS:
+ if (item.HostOS < ARRAY_SIZE(kHostOS))
+ prop = kHostOS[(size_t)item.HostOS];
+ else
+ prop = (UInt64)item.HostOS;
+ break;
+ }
+
+ prop.Detach(value);
+ return S_OK;
+
+ COM_TRY_END
+}
+
+
+
+// ---------- Copy Links ----------
+
+static int CompareItemsPaths(const CHandler &handler, unsigned p1, unsigned p2, const AString *name1)
+{
+ const CItem &item1 = handler._items[handler._refs[p1].Item];
+ const CItem &item2 = handler._items[handler._refs[p2].Item];
+
+ if (item1.Version_Defined)
+ {
+ if (!item2.Version_Defined)
+ return -1;
+ int res = MyCompare(item1.Version, item2.Version);
+ if (res != 0)
+ return res;
+ }
+ else if (item2.Version_Defined)
+ return 1;
+
+ if (!name1)
+ name1 = &item1.Name;
+ return strcmp(*name1, item2.Name);
+}
+
+static int CompareItemsPaths2(const CHandler &handler, unsigned p1, unsigned p2, const AString *name1)
+{
+ int res = CompareItemsPaths(handler, p1, p2, name1);
+ if (res != 0)
+ return res;
+ return MyCompare(p1, p2);
+}
+
+static int CompareItemsPaths_Sort(const unsigned *p1, const unsigned *p2, void *param)
+{
+ return CompareItemsPaths2(*(const CHandler *)param, *p1, *p2, NULL);
+}
+
+static int FindLink(const CHandler &handler, const CUIntVector &sorted,
+ const AString &s, unsigned index)
+{
+ unsigned left = 0, right = sorted.Size();
+ for (;;)
+ {
+ if (left == right)
+ {
+ if (left > 0)
+ {
+ unsigned refIndex = sorted[left - 1];
+ if (CompareItemsPaths(handler, index, refIndex, &s) == 0)
+ return refIndex;
+ }
+ if (right < sorted.Size())
+ {
+ unsigned refIndex = sorted[right];
+ if (CompareItemsPaths(handler, index, refIndex, &s) == 0)
+ return refIndex;
+ }
+ return -1;
+ }
+
+ unsigned mid = (left + right) / 2;
+ unsigned refIndex = sorted[mid];
+ int compare = CompareItemsPaths2(handler, index, refIndex, &s);
+ if (compare == 0)
+ return refIndex;
+ if (compare < 0)
+ right = mid;
+ else
+ left = mid + 1;
+ }
+}
+
+void CHandler::FillLinks()
+{
+ unsigned i;
+
+ for (i = 0; i < _refs.Size(); i++)
+ {
+ const CItem &item = _items[_refs[i].Item];
+ if (!item.IsDir() && !item.IsService() && item.NeedUse_as_CopyLink())
+ break;
+ }
+
+ if (i == _refs.Size())
+ return;
+
+ CUIntVector sorted;
+ for (i = 0; i < _refs.Size(); i++)
+ {
+ const CItem &item = _items[_refs[i].Item];
+ if (!item.IsDir() && !item.IsService())
+ sorted.Add(i);
+ }
+
+ if (sorted.IsEmpty())
+ return;
+
+ sorted.Sort(CompareItemsPaths_Sort, (void *)this);
+
+ AString link;
+
+ for (i = 0; i < _refs.Size(); i++)
+ {
+ CRefItem &ref = _refs[i];
+ const CItem &item = _items[ref.Item];
+ if (item.IsDir() || item.IsService() || item.PackSize != 0)
+ continue;
+ CItem::CLinkInfo linkInfo;
+ if (!item.FindExtra_Link(linkInfo) || linkInfo.Type != NLinkType::kFileCopy)
+ continue;
+ link.SetFrom_CalcLen((const char *)(item.Extra + linkInfo.NameOffset), linkInfo.NameLen);
+ int linkIndex = FindLink(*this, sorted, link, i);
+ if (linkIndex < 0)
+ continue;
+ if ((unsigned)linkIndex >= i)
+ continue; // we don't support forward links that can lead to loops
+ const CRefItem &linkRef = _refs[linkIndex];
+ const CItem &linkItem = _items[linkRef.Item];
+ if (linkItem.Size == item.Size)
+ {
+ if (linkRef.Link >= 0)
+ ref.Link = linkRef.Link;
+ else if (!linkItem.NeedUse_as_CopyLink())
+ ref.Link = linkIndex;
+ }
+ }
+}
+
+
+
+HRESULT CHandler::Open2(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openCallback)
+{
+ CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
+ CMyComPtr<ICryptoGetTextPassword> getTextPassword;
+
+ NRar::CVolumeName seqName;
+
+ UInt64 totalBytes = 0;
+ UInt64 curBytes = 0;
+
+ if (openCallback)
+ {
+ openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
+ openCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
+ }
+
+ CTempBuf tempBuf;
+
+ CUnpacker unpacker;
+ unpacker.getTextPassword = getTextPassword;
+
+ int prevSplitFile = -1;
+ int prevMainFile = -1;
+
+ CInArchive arch;
+
+ for (;;)
+ {
+ CMyComPtr<IInStream> inStream;
+
+ if (_arcs.IsEmpty())
+ inStream = stream;
+ else
+ {
+ if (!openVolumeCallback)
+ break;
+
+ if (_arcs.Size() == 1)
+ {
+ UString baseName;
+ {
+ NCOM::CPropVariant prop;
+ RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
+ if (prop.vt != VT_BSTR)
+ break;
+ baseName = prop.bstrVal;
+ }
+ if (!seqName.InitName(baseName))
+ break;
+ }
+
+ HRESULT result = openVolumeCallback->GetStream(seqName.GetNextName(), &inStream);
+ if (result == S_FALSE)
+ break;
+ if (result != S_OK)
+ return result;
+ if (!inStream)
+ break;
+ }
+
+ UInt64 endPos = 0;
+ RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &arch.StreamStartPosition));
+ RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos));
+ RINOK(inStream->Seek(arch.StreamStartPosition, STREAM_SEEK_SET, NULL));
+
+ if (openCallback)
+ {
+ totalBytes += endPos;
+ RINOK(openCallback->SetTotal(NULL, &totalBytes));
+ }
+
+ CInArcInfo arcInfoOpen;
+ HRESULT res = arch.Open(inStream, maxCheckStartPosition, getTextPassword, arcInfoOpen);
+ if (arch.IsArc && arch.UnexpectedEnd)
+ _errorFlags |= kpv_ErrorFlags_UnexpectedEnd;
+ if (_arcs.IsEmpty())
+ {
+ _isArc = arch.IsArc;
+ }
+
+ if (res != S_OK)
+ {
+ if (res != S_FALSE)
+ return res;
+ if (_arcs.IsEmpty())
+ return res;
+ break;
+ }
+
+ CArc &arc = _arcs.AddNew();
+ CInArcInfo &arcInfo = arc.Info;
+ arcInfo = arcInfoOpen;
+ arc.Stream = inStream;
+
+ CItem item;
+
+ for (;;)
+ {
+ item.Clear();
+
+ arcInfo.EndPos = arch.Position;
+
+ if (arch.Position > endPos)
+ {
+ _errorFlags |= kpv_ErrorFlags_UnexpectedEnd;
+ break;
+ }
+
+ RINOK(inStream->Seek(arch.Position, STREAM_SEEK_SET, NULL));
+
+ {
+ CInArchive::CHeader h;
+ HRESULT res = arch.ReadBlockHeader(h);
+ if (res != S_OK)
+ {
+ if (res != S_FALSE)
+ return res;
+ if (arch.UnexpectedEnd)
+ {
+ _errorFlags |= kpv_ErrorFlags_UnexpectedEnd;
+ if (arcInfo.EndPos < arch.Position)
+ arcInfo.EndPos = arch.Position;
+ if (arcInfo.EndPos < endPos)
+ arcInfo.EndPos = endPos;
+ }
+ else
+ _errorFlags |= kpv_ErrorFlags_HeadersError;
+ break;
+ }
+
+ if (h.Type == NHeaderType::kEndOfArc)
+ {
+ arcInfo.EndPos = arch.Position;
+ arcInfo.EndOfArchive_was_Read = true;
+ if (!arch.ReadVar(arcInfo.EndFlags))
+ _errorFlags |= kpv_ErrorFlags_HeadersError;
+ if (arcInfo.IsVolume())
+ {
+ // for multivolume archives RAR can add ZERO bytes at the end for alignment.
+ // We must skip these bytes to prevent phySize warning.
+ RINOK(inStream->Seek(arcInfo.EndPos, STREAM_SEEK_SET, NULL));
+ bool areThereNonZeros;
+ UInt64 numZeros;
+ const UInt64 maxSize = 1 << 12;
+ RINOK(NRar::ReadZeroTail(inStream, areThereNonZeros, numZeros, maxSize));
+ if (!areThereNonZeros && numZeros != 0 && numZeros <= maxSize)
+ arcInfo.EndPos += numZeros;
+ }
+ break;
+ }
+
+ if (h.Type != NHeaderType::kFile &&
+ h.Type != NHeaderType::kService)
+ {
+ _errorFlags |= kpv_ErrorFlags_UnsupportedFeature;
+ break;
+ }
+
+ item.RecordType = (Byte)h.Type;
+
+ if (!arch.ReadFileHeader(h, item))
+ {
+ _errorFlags |= kpv_ErrorFlags_HeadersError;
+ break;
+ }
+
+ // item.MainPartSize = (UInt32)(Position - item.Position);
+ item.DataPos = arch.Position;
+ }
+
+ bool isOk_packSize = true;
+ {
+ arcInfo.EndPos = arch.Position;
+ if (arch.Position + item.PackSize < arch.Position)
+ {
+ isOk_packSize = false;
+ _errorFlags |= kpv_ErrorFlags_HeadersError;
+ if (arcInfo.EndPos < endPos)
+ arcInfo.EndPos = endPos;
+ }
+ else
+ {
+ arch.AddToSeekValue(item.PackSize); // Position points to next header;
+ arcInfo.EndPos = arch.Position;
+ }
+ }
+
+ bool needAdd = true;
+
+ {
+ if (_comment.Size() == 0
+ && item.Is_CMT()
+ && item.PackSize < kCommentSize_Max
+ && item.PackSize == item.Size
+ && item.PackSize != 0
+ && item.GetMethod() == 0
+ && !item.IsSplit())
+ {
+ RINOK(unpacker.DecodeToBuf(EXTERNAL_CODECS_VARS item, item.PackSize, inStream, _comment));
+ needAdd = false;
+ }
+ }
+
+ if (needAdd)
+ {
+ CRefItem ref;
+ ref.Item = _items.Size();
+ ref.Last = ref.Item;
+ ref.Parent = -1;
+ ref.Link = -1;
+
+ if (item.IsService())
+ {
+ if (item.Is_STM())
+ {
+ if (prevMainFile >= 0)
+ ref.Parent = prevMainFile;
+ }
+ else
+ {
+ needAdd = false;
+ if (item.Is_ACL() && (!item.IsEncrypted() || arch.m_CryptoMode))
+ {
+ if (prevMainFile >= 0 && item.Size < (1 << 24) && item.Size != 0)
+ {
+ CItem &mainItem = _items[_refs[prevMainFile].Item];
+
+ if (mainItem.ACL < 0)
+ {
+ CByteBuffer acl;
+ HRESULT res = tempBuf.Decode(EXTERNAL_CODECS_VARS item, inStream, unpacker, acl);
+ if (!item.IsSplitAfter())
+ tempBuf.Clear();
+ if (res != S_OK)
+ {
+ tempBuf.Clear();
+ if (res != S_FALSE && res != E_NOTIMPL)
+ return res;
+ }
+ // RINOK();
+
+ if (res == S_OK && acl.Size() != 0)
+ {
+ if (_acls.IsEmpty() || acl != _acls.Back())
+ _acls.Add(acl);
+ mainItem.ACL = _acls.Size() - 1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (needAdd)
+ {
+ if (item.IsSplitBefore())
+ {
+ if (prevSplitFile >= 0)
+ {
+ CRefItem &ref = _refs[prevSplitFile];
+ CItem &prevItem = _items[ref.Last];
+ if (item.IsNextForItem(prevItem))
+ {
+ ref.Last = _items.Size();
+ prevItem.NextItem = ref.Last;
+ needAdd = false;
+ }
+ }
+ }
+ }
+
+ if (needAdd)
+ {
+ if (item.IsSplitAfter())
+ prevSplitFile = _refs.Size();
+ if (!item.IsService())
+ prevMainFile = _refs.Size();
+ _refs.Add(ref);
+ }
+ }
+
+ {
+ UInt64 version;
+ if (item.FindExtra_Version(version))
+ {
+ item.Version_Defined = true;
+ item.Version = version;
+ }
+ }
+
+ item.VolIndex = _arcs.Size() - 1;
+ _items.Add(item);
+
+ if (openCallback && (_items.Size() & 0xFF) == 0)
+ {
+ UInt64 numFiles = _items.Size();
+ UInt64 numBytes = curBytes + item.DataPos;
+ RINOK(openCallback->SetCompleted(&numFiles, &numBytes));
+ }
+
+ if (!isOk_packSize)
+ break;
+ }
+
+ curBytes += endPos;
+ if (!arcInfo.IsVolume())
+ break;
+ if (arcInfo.EndOfArchive_was_Read
+ && !arcInfo.AreMoreVolumes())
+ break;
+ }
+
+ FillLinks();
+
+ return S_OK;
+}
+
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openCallback)
+{
+ COM_TRY_BEGIN
+ Close();
+ return Open2(stream, maxCheckStartPosition, openCallback);
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ COM_TRY_BEGIN
+ _errorFlags = 0;
+ // _warningFlags = 0;
+ _isArc = false;
+ _refs.Clear();
+ _items.Clear();
+ _arcs.Clear();
+ _acls.Clear();
+ _comment.Free();
+ return S_OK;
+ COM_TRY_END
+}
+
+
+class CVolsInStream:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ UInt64 _rem;
+ ISequentialInStream *_stream;
+ const CObjectVector<CArc> *_arcs;
+ const CObjectVector<CItem> *_items;
+ int _itemIndex;
+public:
+ bool CrcIsOK;
+private:
+ CHash _hash;
+public:
+ MY_UNKNOWN_IMP
+ void Init(const CObjectVector<CArc> *arcs,
+ const CObjectVector<CItem> *items,
+ unsigned itemIndex)
+ {
+ _arcs = arcs;
+ _items = items;
+ _itemIndex = itemIndex;
+ _stream = NULL;
+ CrcIsOK = true;
+ }
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CVolsInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+ UInt32 realProcessedSize = 0;
+
+ while (size != 0)
+ {
+ if (!_stream)
+ {
+ if (_itemIndex < 0)
+ break;
+ const CItem &item = (*_items)[_itemIndex];
+ IInStream *s = (*_arcs)[item.VolIndex].Stream;
+ RINOK(s->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL));
+ _stream = s;
+ if (CrcIsOK && item.IsSplitAfter())
+ _hash.Init(item);
+ else
+ _hash.Init_NoCalc();
+ _rem = item.PackSize;
+ }
+ {
+ UInt32 cur = size;
+ if (cur > _rem)
+ cur = (UInt32)_rem;
+ UInt32 num = cur;
+ HRESULT res = _stream->Read(data, cur, &cur);
+ _hash.Update(data, cur);
+ realProcessedSize += cur;
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ data = (Byte *)data + cur;
+ size -= cur;
+ _rem -= cur;
+ if (_rem == 0)
+ {
+ const CItem &item = (*_items)[_itemIndex];
+ _itemIndex = item.NextItem;
+ if (!_hash.Check(item, NULL)) // RAR doesn't use MAC here
+ 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;
+}
+
+
+static int FindLinkBuf(CObjectVector<CLinkFile> &linkFiles, unsigned index)
+{
+ unsigned left = 0, right = linkFiles.Size();
+ for (;;)
+ {
+ if (left == right)
+ return -1;
+ unsigned mid = (left + right) / 2;
+ unsigned linkIndex = linkFiles[mid].Index;
+ if (index == linkIndex)
+ return mid;
+ if (index < linkIndex)
+ right = mid;
+ else
+ left = mid + 1;
+ }
+}
+
+
+static inline int DecoderRes_to_OpRes(HRESULT res, bool crcOK)
+{
+ if (res == E_NOTIMPL)
+ return NExtract::NOperationResult::kUnsupportedMethod;
+ // if (res == S_FALSE)
+ if (res != S_OK)
+ return NExtract::NOperationResult::kDataError;
+ return crcOK ?
+ NExtract::NOperationResult::kOK :
+ NExtract::NOperationResult::kCRCError;
+}
+
+
+static HRESULT CopyData_with_Progress(const Byte *data, size_t size,
+ ISequentialOutStream *outStream, ICompressProgressInfo *progress)
+{
+ size_t pos = 0;
+
+ while (pos < size)
+ {
+ const UInt32 kStepSize = ((UInt32)1 << 24);
+ UInt32 cur32;
+ {
+ size_t cur = size - pos;
+ if (cur > kStepSize)
+ cur = kStepSize;
+ cur32 = (UInt32)cur;
+ }
+ RINOK(outStream->Write(data + pos, cur32, &cur32));
+ if (cur32 == 0)
+ return E_FAIL;
+ pos += cur32;
+ if (progress)
+ {
+ UInt64 pos64 = pos;
+ RINOK(progress->SetRatioInfo(&pos64, &pos64));
+ }
+ }
+
+ return S_OK;
+}
+
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+ Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+
+ bool allFilesMode = (numItems == (UInt32)(Int32)-1);
+ if (allFilesMode)
+ numItems = _refs.Size();
+ if (numItems == 0)
+ return S_OK;
+
+ CByteArr extractStatuses(_refs.Size());
+ memset(extractStatuses, 0, _refs.Size());
+
+ // we don't want to use temp buffer for big link files.
+ const size_t k_CopyLinkFile_MaxSize = (size_t)1 << (28 + sizeof(size_t) / 2);
+
+ const Byte kStatus_Extract = 1 << 0;
+ const Byte kStatus_Skip = 1 << 1;
+ const Byte kStatus_Link = 1 << 2;
+
+ CObjectVector<CLinkFile> linkFiles;
+
+ {
+ UInt64 total = 0;
+ bool thereAreLinks = false;
+
+ {
+ unsigned solidLimit = 0;
+ for (UInt32 t = 0; t < numItems; t++)
+ {
+ unsigned index = allFilesMode ? t : indices[t];
+ const CRefItem &ref = _refs[index];
+ const CItem &item = _items[ref.Item];
+
+ extractStatuses[index] |= kStatus_Extract;
+ total += item.Size;
+
+ if (ref.Link >= 0)
+ {
+ if (!testMode)
+ {
+ if ((unsigned)ref.Link < index)
+ {
+ const CItem &linkItem = _items[_refs[(unsigned)ref.Link].Item];
+ if (linkItem.IsSolid() && linkItem.Size <= k_CopyLinkFile_MaxSize)
+ {
+ if (extractStatuses[(unsigned)ref.Link] == 0)
+ total += linkItem.Size;
+ extractStatuses[(unsigned)ref.Link] |= kStatus_Link;
+ thereAreLinks = true;
+ }
+ }
+ }
+ continue;
+ }
+
+ if (item.IsService())
+ continue;
+
+ if (item.IsSolid())
+ {
+ unsigned j = index;
+
+ while (j > solidLimit)
+ {
+ j--;
+ const CItem &item2 = _items[_refs[j].Item];
+ if (!item2.IsService())
+ {
+ if (extractStatuses[j] == 0)
+ total += item2.Size;
+ extractStatuses[j] |= kStatus_Skip;
+ if (!item2.IsSolid())
+ break;
+ }
+ }
+ }
+
+ solidLimit = index + 1;
+ }
+ }
+
+ if (thereAreLinks)
+ {
+ unsigned solidLimit = 0;
+
+ FOR_VECTOR(i, _refs)
+ {
+ if ((extractStatuses[i] & kStatus_Link) == 0)
+ continue;
+ const CItem &item = _items[_refs[i].Item];
+ /*
+ if (item.IsService())
+ continue;
+ */
+
+ CLinkFile &linkFile = linkFiles.AddNew();
+ linkFile.Index = i;
+
+ if (item.IsSolid())
+ {
+ unsigned j = i;
+
+ while (j > solidLimit)
+ {
+ j--;
+ const CItem &item2 = _items[_refs[j].Item];
+ if (!item2.IsService())
+ {
+ if (extractStatuses[j] != 0)
+ break;
+ extractStatuses[j] = kStatus_Skip;
+ total += item2.Size;
+ if (!item2.IsSolid())
+ break;
+ }
+ }
+ }
+
+ solidLimit = i + 1;
+ }
+
+ for (UInt32 t = 0; t < numItems; t++)
+ {
+ unsigned index = allFilesMode ? t : indices[t];
+ const CRefItem &ref = _refs[index];
+
+ int linkIndex = ref.Link;
+ if (linkIndex < 0 || (unsigned)linkIndex >= index)
+ continue;
+ const CItem &linkItem = _items[_refs[(unsigned)linkIndex].Item];
+ if (!linkItem.IsSolid() || linkItem.Size > k_CopyLinkFile_MaxSize)
+ continue;
+ int bufIndex = FindLinkBuf(linkFiles, linkIndex);
+ if (bufIndex < 0)
+ return E_FAIL;
+ linkFiles[bufIndex].NumLinks++;
+ }
+ }
+
+ RINOK(extractCallback->SetTotal(total));
+ }
+
+
+ UInt64 totalUnpacked = 0;
+ UInt64 totalPacked = 0;
+ UInt64 curUnpackSize = 0;
+ UInt64 curPackSize = 0;
+
+ CUnpacker unpacker;
+
+ CVolsInStream *volsInStreamSpec = new CVolsInStream;
+ CMyComPtr<ISequentialInStream> volsInStream = volsInStreamSpec;
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(extractCallback, false);
+
+ // bool needClearSolid = true;
+
+ FOR_VECTOR(i, _refs)
+ {
+ if (extractStatuses[i] == 0)
+ continue;
+
+ totalUnpacked += curUnpackSize;
+ totalPacked += curPackSize;
+ lps->InSize = totalPacked;
+ lps->OutSize = totalUnpacked;
+ RINOK(lps->SetCur());
+
+ CMyComPtr<ISequentialOutStream> realOutStream;
+
+ Int32 askMode =
+ ((extractStatuses[i] & kStatus_Extract) != 0) ? (testMode ?
+ NExtract::NAskMode::kTest :
+ NExtract::NAskMode::kExtract) :
+ NExtract::NAskMode::kSkip;
+
+ unpacker.linkFile = NULL;
+
+ if (((extractStatuses[i] & kStatus_Link) != 0))
+ {
+ int bufIndex = FindLinkBuf(linkFiles, i);
+ if (bufIndex < 0)
+ return E_FAIL;
+ unpacker.linkFile = &linkFiles[bufIndex];
+ }
+
+ UInt32 index = i;
+
+ const CRefItem *ref = &_refs[index];
+ const CItem *item = &_items[ref->Item];
+
+ curUnpackSize = item->Size;
+ curPackSize = GetPackSize(index);
+
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+ bool isSolid;
+ {
+ bool &needClearSolid = unpacker.NeedClearSolid[item->IsService() ? 1 : 0];
+ isSolid = (item->IsSolid() && !needClearSolid);
+ if (item->IsService())
+ isSolid = false;
+ needClearSolid = !item->IsSolid();
+ }
+
+ if (item->IsDir())
+ {
+ RINOK(extractCallback->PrepareOperation(askMode));
+ RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+ continue;
+ }
+
+ int index2 = ref->Link;
+
+ int bufIndex = -1;
+
+ if (index2 >= 0)
+ {
+ const CRefItem &ref2 = _refs[index2];
+ const CItem &item2 = _items[ref2.Item];
+ if (!item2.IsSolid())
+ {
+ item = &item2;
+ ref = &ref2;
+ curUnpackSize = item->Size;
+ curPackSize = GetPackSize(index2);
+ }
+ else if ((unsigned)index2 < index)
+ bufIndex = FindLinkBuf(linkFiles, index2);
+ }
+
+ if (!realOutStream)
+ {
+ if (testMode)
+ {
+ if (item->Is_CopyLink() && item->PackSize == 0)
+ {
+ RINOK(extractCallback->PrepareOperation(askMode));
+ RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+ continue;
+ }
+ }
+ else
+ {
+ if (item->IsService())
+ continue;
+
+ bool needDecode = false;
+
+ for (unsigned n = i + 1; n < _refs.Size(); n++)
+ {
+ const CItem &nextItem = _items[_refs[n].Item];
+ if (nextItem.IsService())
+ continue;
+ if (!nextItem.IsSolid())
+ break;
+ if (extractStatuses[i] != 0)
+ {
+ needDecode = true;
+ break;
+ }
+ }
+
+ if (!needDecode)
+ continue;
+
+ askMode = NExtract::NAskMode::kSkip;
+ }
+ }
+
+ RINOK(extractCallback->PrepareOperation(askMode));
+
+ if (bufIndex >= 0)
+ {
+ CLinkFile &linkFile = linkFiles[bufIndex];
+ if (linkFile.NumLinks == 0)
+ return E_FAIL;
+ if (realOutStream)
+ {
+ RINOK(CopyData_with_Progress(linkFile.Data, linkFile.Data.Size(), realOutStream, progress));
+ }
+ if (--linkFile.NumLinks == 0)
+ linkFile.Data.Free();
+ RINOK(extractCallback->SetOperationResult(DecoderRes_to_OpRes(linkFile.Res, linkFile.crcOK)));
+ continue;
+ }
+
+ if (item->Is_CopyLink() && item->PackSize == 0)
+ {
+ RINOK(extractCallback->SetOperationResult(
+ realOutStream ?
+ NExtract::NOperationResult::kUnsupportedMethod:
+ NExtract::NOperationResult::kOK));
+ continue;
+ }
+
+ volsInStreamSpec->Init(&_arcs, &_items, ref->Item);
+
+ UInt64 packSize = curPackSize;
+
+ if (item->IsEncrypted())
+ if (!unpacker.getTextPassword)
+ extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&unpacker.getTextPassword);
+
+ bool wrongPassword;
+ HRESULT result = unpacker.Create(EXTERNAL_CODECS_VARS *item, isSolid, wrongPassword);
+
+ if (wrongPassword)
+ {
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kWrongPassword));
+ continue;
+ }
+
+ bool crcOK = true;
+ if (result == S_OK)
+ result = unpacker.Code(*item, _items[ref->Last], packSize, volsInStream, realOutStream, progress, crcOK);
+ realOutStream.Release();
+ if (!volsInStreamSpec->CrcIsOK)
+ crcOK = false;
+
+ int opRes = 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
+ return result;
+ }
+
+ RINOK(extractCallback->SetOperationResult(opRes));
+ }
+
+ {
+ FOR_VECTOR(i, linkFiles)
+ if (linkFiles[i].NumLinks != 0)
+ return E_FAIL;
+ }
+
+ return S_OK;
+
+ COM_TRY_END
+}
+
+
+IMPL_ISetCompressCodecsInfo
+
+REGISTER_ARC_I(
+ "Rar5", "rar r00", 0, 0xCC,
+ kMarker,
+ 0,
+ NArcInfoFlags::kFindSignature,
+ NULL)
+
+}}
+
+
+class CBlake2spHasher:
+ public IHasher,
+ public CMyUnknownImp
+{
+ CBlake2sp _blake;
+ Byte mtDummy[1 << 7];
+
+public:
+ CBlake2spHasher() { Init(); }
+
+ MY_UNKNOWN_IMP
+ INTERFACE_IHasher(;)
+};
+
+STDMETHODIMP_(void) CBlake2spHasher::Init() throw()
+{
+ Blake2sp_Init(&_blake);
+}
+
+STDMETHODIMP_(void) CBlake2spHasher::Update(const void *data, UInt32 size) throw()
+{
+ Blake2sp_Update(&_blake, (const Byte *)data, size);
+}
+
+STDMETHODIMP_(void) CBlake2spHasher::Final(Byte *digest) throw()
+{
+ Blake2sp_Final(&_blake, digest);
+}
+
+REGISTER_HASHER(CBlake2spHasher, 0x202, "BLAKE2sp", BLAKE2S_DIGEST_SIZE)
diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.h b/CPP/7zip/Archive/Rar/Rar5Handler.h
new file mode 100644
index 00000000..5eaf0075
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/Rar5Handler.h
@@ -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
diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp
index 516e5d7f..d6d894f4 100644
--- a/CPP/7zip/Archive/Rar/RarHandler.cpp
+++ b/CPP/7zip/Archive/Rar/RarHandler.cpp
@@ -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
{
-public:
- MY_UNKNOWN_IMP
-
- STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
-
-private:
- const CObjectVector<CArc> *_archives;
+ UInt64 _rem;
+ ISequentialInStream *_stream;
+ const CObjectVector<CArc> *_arcs;
const CObjectVector<CItem> *_items;
CRefItem _refItem;
unsigned _curIndex;
UInt32 _crc;
- bool _fileIsOpen;
- CMyComPtr<ISequentialInStream> _stream;
+ bool _calcCrc;
- 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,
- const CObjectVector<CItem> *items,
- const CRefItem &refItem)
-{
- _archives = archives;
- _items = items;
- _refItem = refItem;
- _curIndex = 0;
- CRCs.Clear();
- _fileIsOpen = false;
-}
+ MY_UNKNOWN_IMP
-HRESULT CFolderInStream::OpenStream()
-{
- while (_curIndex < _refItem.NumItems)
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+
+ void Init(const CObjectVector<CArc> *arcs,
+ const CObjectVector<CItem> *items,
+ const CRefItem &refItem)
{
- 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;
- return S_OK;
+ _arcs = arcs;
+ _items = items;
+ _refItem = refItem;
+ _curIndex = 0;
+ _stream = NULL;
+ CrcIsOK = true;
}
- return S_OK;
-}
-HRESULT CFolderInStream::CloseStream()
-{
- CRCs.Add(CRC_GET_DIGEST(_crc));
- _stream.Release();
- _fileIsOpen = false;
- return S_OK;
-}
+ bool CrcIsOK;
+};
-STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+
+STDMETHODIMP CVolsInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
+ if (processedSize)
+ *processedSize = 0;
UInt32 realProcessedSize = 0;
- while ((_curIndex < _refItem.NumItems || _fileIsOpen) && size > 0)
+
+ while (size != 0)
{
- if (_fileIsOpen)
+ if (!_stream)
{
- 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;
+ 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;
}
- else
{
- RINOK(OpenStream());
+ 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];
+ _curIndex++;
+ 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;
}
}
- 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++)
- {
- 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)
+ if (!volsInStream)
{
- 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;
+
+ const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
+ int opRes = (volsInStreamSpec->CrcIsOK && outStreamSpec->GetCRC() == lastItem.FileCRC) ?
+ NExtract::NOperationResult::kOK:
+ NExtract::NOperationResult::kCRCError;
+ outStream.Release();
- /*
- if (refItem.NumItems == 1 &&
- !item.IsSplitBefore() && !item.IsSplitAfter())
- */
- {
- const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
- bool crcOK = outStreamSpec->GetCRC() == lastItem.FileCRC;
- outStream.Release();
- RINOK(extractCallback->SetOperationResult(crcOK ?
- NExtract::NOperationResult::kOK:
- NExtract::NOperationResult::kCRCError));
- }
- /*
- else
+ if (result != S_OK)
{
- 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;
- }
- }
- RINOK(extractCallback->SetOperationResult(crcOK ?
- NExtract::NOperationResult::kOK:
- NExtract::NOperationResult::kCRCError));
+ if (result == S_FALSE)
+ opRes = NExtract::NOperationResult::kDataError;
+ else if (result == E_NOTIMPL)
+ opRes = NExtract::NOperationResult::kUnsupportedMethod;
+ else
+ return result;
}
- */
+ RINOK(extractCallback->SetOperationResult(opRes));
}
+
return S_OK;
COM_TRY_END
}
diff --git a/CPP/7zip/Archive/Rar/RarVol.h b/CPP/7zip/Archive/Rar/RarVol.h
new file mode 100644
index 00000000..d0f91de6
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/RarVol.h
@@ -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
diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
index ae005ac5..8dd99869 100644
--- a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
+++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
@@ -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
}
diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp
index 3adbdee9..0cdb30d1 100644
--- a/CPP/7zip/Archive/Tar/TarUpdate.cpp
+++ b/CPP/7zip/Archive/Tar/TarUpdate.cpp
@@ -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();
diff --git a/CPP/7zip/Archive/Tar/TarUpdate.h b/CPP/7zip/Archive/Tar/TarUpdate.h
index c2393416..b758635f 100644
--- a/CPP/7zip/Archive/Tar/TarUpdate.h
+++ b/CPP/7zip/Archive/Tar/TarUpdate.h
@@ -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,
diff --git a/CPP/7zip/Archive/XarHandler.cpp b/CPP/7zip/Archive/XarHandler.cpp
index 7e89bf48..5ef3bdf9 100644
--- a/CPP/7zip/Archive/XarHandler.cpp
+++ b/CPP/7zip/Archive/XarHandler.cpp
@@ -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;
diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
index f1c8b227..aa06c4f8 100644
--- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
@@ -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);
diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp
index 6f495305..3c466424 100644
--- a/CPP/7zip/Archive/Zip/ZipIn.cpp
+++ b/CPP/7zip/Archive/Zip/ZipIn.cpp
@@ -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)
- return false;
+ {
+ // #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;
}
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
index 9a9526cc..7d03056c 100644
--- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp
+++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
@@ -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;
}
}
diff --git a/CPP/7zip/Bundles/Fm/FM.dsp b/CPP/7zip/Bundles/Fm/FM.dsp
index dfb0bb47..057da977 100644
--- a/CPP/7zip/Bundles/Fm/FM.dsp
+++ b/CPP/7zip/Bundles/Fm/FM.dsp
@@ -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
diff --git a/CPP/7zip/Bundles/Format7zF/Arc.mak b/CPP/7zip/Bundles/Format7zF/Arc.mak
index c2f415cf..a1221c61 100644
--- a/CPP/7zip/Bundles/Format7zF/Arc.mak
+++ b/CPP/7zip/Bundles/Format7zF/Arc.mak
@@ -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 \
diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp
index 82df284c..169d9f0e 100644
--- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp
+++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp
@@ -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"
diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
index 5b64b524..0e8586e9 100644
--- a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
+++ b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
@@ -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"
diff --git a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp
index 01089c5e..781f810c 100644
--- a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp
+++ b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
#include "../../../Common/MyInitGuid.h"
#include "../../../Common/CommandLineParser.h"
diff --git a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
index 611ef651..cd2584fd 100644
--- a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
+++ b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
#include "../../../Common/MyInitGuid.h"
#include "../../../Common/CommandLineParser.h"
diff --git a/CPP/7zip/Bundles/SFXWin/SfxWin.cpp b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp
index ee57d445..c301ecf8 100644
--- a/CPP/7zip/Bundles/SFXWin/SfxWin.cpp
+++ b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
#include <Shlwapi.h>
#include "../../../Common/MyInitGuid.h"
diff --git a/CPP/7zip/Common/FilterCoder.h b/CPP/7zip/Common/FilterCoder.h
index cde33c88..224ff2ca 100644
--- a/CPP/7zip/Common/FilterCoder.h
+++ b/CPP/7zip/Common/FilterCoder.h
@@ -19,7 +19,7 @@
struct CAlignedMidBuffer
{
- #ifndef _WIN32
+ #ifdef _WIN32
Byte *_buf;
diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp
index 2ea718e7..77665ae1 100644
--- a/CPP/7zip/Common/LimitedStreams.cpp
+++ b/CPP/7zip/Common/LimitedStreams.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include <string.h>
+
#include "LimitedStreams.h"
#include "../../Common/Defs.h"
diff --git a/CPP/7zip/Common/PropId.cpp b/CPP/7zip/Common/PropId.cpp
index 2ce6fd85..11d20d55 100644
--- a/CPP/7zip/Common/PropId.cpp
+++ b/CPP/7zip/Common/PropId.cpp
@@ -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
};
diff --git a/CPP/7zip/Common/UniqBlocks.cpp b/CPP/7zip/Common/UniqBlocks.cpp
index a2cacdde..8f754e17 100644
--- a/CPP/7zip/Common/UniqBlocks.cpp
+++ b/CPP/7zip/Common/UniqBlocks.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include <string.h>
+
#include "UniqBlocks.h"
unsigned CUniqBlocks::AddUniq(const Byte *data, size_t size)
diff --git a/CPP/7zip/Compress/Codec.def b/CPP/7zip/Compress/Codec.def
index ebf73a3b..f55b2d57 100644
--- a/CPP/7zip/Compress/Codec.def
+++ b/CPP/7zip/Compress/Codec.def
@@ -2,3 +2,5 @@ EXPORTS
CreateObject PRIVATE
GetNumberOfMethods PRIVATE
GetMethodProperty PRIVATE
+ CreateDecoder PRIVATE
+ CreateEncoder PRIVATE
diff --git a/CPP/7zip/Compress/DeflateEncoder.cpp b/CPP/7zip/Compress/DeflateEncoder.cpp
index eb012e8d..94d0092b 100644
--- a/CPP/7zip/Compress/DeflateEncoder.cpp
+++ b/CPP/7zip/Compress/DeflateEncoder.cpp
@@ -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);
}
diff --git a/CPP/7zip/Compress/HuffmanDecoder.h b/CPP/7zip/Compress/HuffmanDecoder.h
index 6faf8005..65e0f93c 100644
--- a/CPP/7zip/Compress/HuffmanDecoder.h
+++ b/CPP/7zip/Compress/HuffmanDecoder.h
@@ -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;
diff --git a/CPP/7zip/Compress/Rar1Decoder.cpp b/CPP/7zip/Compress/Rar1Decoder.cpp
index 12de7e19..1aaedcc1 100644
--- a/CPP/7zip/Compress/Rar1Decoder.cpp
+++ b/CPP/7zip/Compress/Rar1Decoder.cpp
@@ -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;
}
diff --git a/CPP/7zip/Compress/Rar2Decoder.cpp b/CPP/7zip/Compress/Rar2Decoder.cpp
index 6f42d2e6..5082ded3 100644
--- a/CPP/7zip/Compress/Rar2Decoder.cpp
+++ b/CPP/7zip/Compress/Rar2Decoder.cpp
@@ -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;
}
diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp
index f0553c85..81eb8285 100644
--- a/CPP/7zip/Compress/Rar3Decoder.cpp
+++ b/CPP/7zip/Compress/Rar3Decoder.cpp
@@ -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;
}
diff --git a/CPP/7zip/Compress/Rar3Decoder.h b/CPP/7zip/Compress/Rar3Decoder.h
index 77379858..d8dfd11a 100644
--- a/CPP/7zip/Compress/Rar3Decoder.h
+++ b/CPP/7zip/Compress/Rar3Decoder.h
@@ -194,6 +194,7 @@ class CDecoder:
bool m_IsSolid;
bool _lzMode;
+ bool _unsupportedFilter;
UInt32 PrevAlignBits;
UInt32 PrevAlignCount;
diff --git a/CPP/7zip/Compress/Rar3Vm.cpp b/CPP/7zip/Compress/Rar3Vm.cpp
index 3cbfb0e1..5dca9eab 100644
--- a/CPP/7zip/Compress/Rar3Vm.cpp
+++ b/CPP/7zip/Compress/Rar3Vm.cpp
@@ -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)
+
+bool CProgram::PrepareProgram(const Byte *code, UInt32 codeSize)
{
- Byte xorSum = 0;
- for (UInt32 i = 1; i < codeSize; i++)
- xorSum ^= code[i];
+ 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;
+ */
}
}
diff --git a/CPP/7zip/Compress/Rar3Vm.h b/CPP/7zip/Compress/Rar3Vm.h
index 23f4abab..4272c93e 100644
--- a/CPP/7zip/Compress/Rar3Vm.h
+++ b/CPP/7zip/Compress/Rar3Vm.h
@@ -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
diff --git a/CPP/7zip/Compress/Rar5Decoder.cpp b/CPP/7zip/Compress/Rar5Decoder.cpp
new file mode 100644
index 00000000..9e3ff3e4
--- /dev/null
+++ b/CPP/7zip/Compress/Rar5Decoder.cpp
@@ -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;
+}
+
+}}
diff --git a/CPP/7zip/Compress/Rar5Decoder.h b/CPP/7zip/Compress/Rar5Decoder.h
new file mode 100644
index 00000000..b0a4dd12
--- /dev/null
+++ b/CPP/7zip/Compress/Rar5Decoder.h
@@ -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
diff --git a/CPP/7zip/Compress/RarCodecsRegister.cpp b/CPP/7zip/Compress/RarCodecsRegister.cpp
index 66fcc9a9..2f3a1138 100644
--- a/CPP/7zip/Compress/RarCodecsRegister.cpp
+++ b/CPP/7zip/Compress/RarCodecsRegister.cpp
@@ -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)
diff --git a/CPP/7zip/Crypto/HmacSha256.cpp b/CPP/7zip/Crypto/HmacSha256.cpp
new file mode 100644
index 00000000..2e1efb48
--- /dev/null
+++ b/CPP/7zip/Crypto/HmacSha256.cpp
@@ -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];
+}
+*/
+
+}}
diff --git a/CPP/7zip/Crypto/HmacSha256.h b/CPP/7zip/Crypto/HmacSha256.h
new file mode 100644
index 00000000..233424a0
--- /dev/null
+++ b/CPP/7zip/Crypto/HmacSha256.h
@@ -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
diff --git a/CPP/7zip/Crypto/Rar20Crypto.cpp b/CPP/7zip/Crypto/Rar20Crypto.cpp
index 1523151d..346d969e 100644
--- a/CPP/7zip/Crypto/Rar20Crypto.cpp
+++ b/CPP/7zip/Crypto/Rar20Crypto.cpp
@@ -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;
}
diff --git a/CPP/7zip/Crypto/Rar20Crypto.h b/CPP/7zip/Crypto/Rar20Crypto.h
index b0445932..b3033700 100644
--- a/CPP/7zip/Crypto/Rar20Crypto.h
+++ b/CPP/7zip/Crypto/Rar20Crypto.h
@@ -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(;)
};
}}
diff --git a/CPP/7zip/Crypto/Rar5Aes.cpp b/CPP/7zip/Crypto/Rar5Aes.cpp
new file mode 100644
index 00000000..648a3d4d
--- /dev/null
+++ b/CPP/7zip/Crypto/Rar5Aes.cpp
@@ -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;
+}
+
+}}
diff --git a/CPP/7zip/Crypto/Rar5Aes.h b/CPP/7zip/Crypto/Rar5Aes.h
new file mode 100644
index 00000000..c69b24e4
--- /dev/null
+++ b/CPP/7zip/Crypto/Rar5Aes.h
@@ -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
diff --git a/CPP/7zip/Crypto/RarAes.cpp b/CPP/7zip/Crypto/RarAes.cpp
index f562023a..5bae8529 100644
--- a/CPP/7zip/Crypto/RarAes.cpp
+++ b/CPP/7zip/Crypto/RarAes.cpp
@@ -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++)
{
diff --git a/CPP/7zip/Crypto/RarAes.h b/CPP/7zip/Crypto/RarAes.h
index 197a0b2d..083b4104 100644
--- a/CPP/7zip/Crypto/RarAes.h
+++ b/CPP/7zip/Crypto/RarAes.h
@@ -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; }
diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt
index 64214e80..1ab1b7a2 100644
--- a/CPP/7zip/Guid.txt
+++ b/CPP/7zip/Guid.txt
@@ -163,6 +163,7 @@ Handler GUIDs:
0C xz
0D ppmd
+ CC Rar5
CD IHex
CE Hxs
CF TE
diff --git a/CPP/7zip/IProgress.h b/CPP/7zip/IProgress.h
index 59c55aea..fac951ec 100644
--- a/CPP/7zip/IProgress.h
+++ b/CPP/7zip/IProgress.h
@@ -4,7 +4,6 @@
#define __IPROGRESS_H
#include "../Common/MyTypes.h"
-#include "../Common/MyUnknown.h"
#include "IDecl.h"
diff --git a/CPP/7zip/IStream.h b/CPP/7zip/IStream.h
index 70cb3620..9a0bcbf3 100644
--- a/CPP/7zip/IStream.h
+++ b/CPP/7zip/IStream.h
@@ -4,7 +4,7 @@
#define __ISTREAM_H
#include "../Common/MyTypes.h"
-#include "../Common/MyUnknown.h"
+#include "../Common/MyWindows.h"
#include "IDecl.h"
diff --git a/CPP/7zip/PropID.h b/CPP/7zip/PropID.h
index 3f3acb2d..1822f402 100644
--- a/CPP/7zip/PropID.h
+++ b/CPP/7zip/PropID.h
@@ -102,6 +102,7 @@ enum
kpidStreamId,
kpidReadOnly,
kpidOutName,
+ kpidCopyLink,
kpid_NUM_DEFINED,
diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp
index 3fed8cba..0468fdd1 100644
--- a/CPP/7zip/UI/Agent/AgentOut.cpp
+++ b/CPP/7zip/UI/Agent/AgentOut.cpp
@@ -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));
diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp
index 4df4b199..4d85754d 100644
--- a/CPP/7zip/UI/Client7z/Client7z.cpp
+++ b/CPP/7zip/UI/Client7z/Client7z.cpp
@@ -4,6 +4,8 @@
#include <stdio.h>
+#include "../../../Common/MyWindows.h"
+
#include "../../../Common/Defs.h"
#include "../../../Common/MyInitGuid.h"
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
index 8410756a..8e4936a9 100644
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
@@ -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)
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ }
+
+ /*
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetProperty(index, kpidCopyLink, &prop));
+ if (prop.vt == VT_BSTR)
{
- // linkPath.Empty();
+ isHardLink = false;
+ isCopyLink = true;
+ isRelative = false; // RAR5: copy links are from root folder of archive
+ linkPath.SetFromBstr(prop.bstrVal);
}
- else
+ 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();
@@ -669,6 +733,13 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
#ifdef _WIN32
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,13 +1193,37 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
if (!existPath.IsEmpty())
{
- if (isHardLink)
+ if (isHardLink /* || isCopyLink */)
{
- if (!MyCreateHardLink(fullProcessedPath, existPath))
+ // if (isHardLink)
{
- RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, existPath));
- // return S_OK;
+ if (!MyCreateHardLink(fullProcessedPath, existPath))
+ {
+ RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, existPath));
+ // 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)
{
@@ -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)
+ {
+ /*
+ #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
}
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
index 561a6e42..7d4155fe 100644
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
@@ -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
diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/CPP/7zip/UI/Common/ArchiveOpenCallback.h
index afa03766..e9575f56 100644
--- a/CPP/7zip/UI/Common/ArchiveOpenCallback.h
+++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.h
@@ -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();
diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp
index c38b132c..5f6373f4 100644
--- a/CPP/7zip/UI/Common/Bench.cpp
+++ b/CPP/7zip/UI/Common/Bench.cpp
@@ -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
diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp
index 696b6749..5435499b 100644
--- a/CPP/7zip/UI/Common/LoadCodecs.cpp
+++ b/CPP/7zip/UI/Common/LoadCodecs.cpp
@@ -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;
diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp
index acc10876..a7488044 100644
--- a/CPP/7zip/UI/Common/OpenArchive.cpp
+++ b/CPP/7zip/UI/Common/OpenArchive.cpp
@@ -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
}
- #endif
if (op.callback)
RINOK(op.callback->SetTotal(NULL, &fileSize));
@@ -2382,12 +2406,19 @@ 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));
- callbackPrev = pos;
+
+ useOffsetCallback = (!op.openType.CanReturnArc || handlerSpec->_items.Size() > 1);
+
+ if (pos >= callbackPrev + (1 << 23))
+ {
+ RINOK(openCallback_Offset_Spec->SetCompleted(NULL, NULL));
+ callbackPrev = pos;
+ }
}
{
@@ -2557,14 +2588,21 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
}
UInt64 maxCheckStartPosition = 0;
- openCallback_Offset_Spec->Files = handlerSpec->_items.Size();
- openCallback_Offset_Spec->Offset = startArcPos;
+
+ 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));
bool isOpen = false;
diff --git a/CPP/7zip/UI/Common/UpdateAction.h b/CPP/7zip/UI/Common/UpdateAction.h
index 28dd28c3..bc53fcdb 100644
--- a/CPP/7zip/UI/Common/UpdateAction.h
+++ b/CPP/7zip/UI/Common/UpdateAction.h
@@ -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])
diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp
index 993ab266..058e9153 100644
--- a/CPP/7zip/UI/Common/UpdateCallback.cpp
+++ b/CPP/7zip/UI/Common/UpdateCallback.cpp
@@ -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;
diff --git a/CPP/7zip/UI/Console/ConsoleClose.cpp b/CPP/7zip/UI/Console/ConsoleClose.cpp
index 75bd9e51..6bf2531d 100644
--- a/CPP/7zip/UI/Console/ConsoleClose.cpp
+++ b/CPP/7zip/UI/Console/ConsoleClose.cpp
@@ -4,6 +4,10 @@
#include "ConsoleClose.h"
+#if !defined(UNDER_CE) && defined(_WIN32)
+#include "../../../Common/MyWindows.h"
+#endif
+
namespace NConsoleClose {
unsigned g_BreakCounter = 0;
diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp
index 64abb1fb..e70f1b67 100644
--- a/CPP/7zip/UI/Console/List.cpp
+++ b/CPP/7zip/UI/Console/List.cpp
@@ -123,6 +123,7 @@ static const char * const kPropIdToName[] =
, "Stream ID"
, "Read-only"
, "Out Name"
+ , "Copy Link"
};
static const char kEmptyAttribChar = '.';
diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp
index 83e6ef5b..b9cb4eb9 100644
--- a/CPP/7zip/UI/Console/Main.cpp
+++ b/CPP/7zip/UI/Console/Main.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
#include <Psapi.h>
#include "../../../../C/CpuArch.h"
@@ -230,42 +232,51 @@ 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())
{
- UString message;
- if (!errorInfo.Message.IsEmpty())
- {
- message.AddAscii(errorInfo.Message);
- message.Add_LF();
- }
+ if (se)
{
- FOR_VECTOR(i, errorInfo.FileNames)
+ UString message;
+ if (!errorInfo.Message.IsEmpty())
{
- message += fs2us(errorInfo.FileNames[i]);
+ message.AddAscii(errorInfo.Message);
message.Add_LF();
}
+ {
+ FOR_VECTOR(i, errorInfo.FileNames)
+ {
+ message += fs2us(errorInfo.FileNames[i]);
+ message.Add_LF();
+ }
+ }
+ if (errorInfo.SystemError != 0)
+ {
+ message += NError::MyFormatMessage(errorInfo.SystemError);
+ message.Add_LF();
+ }
+ if (!message.IsEmpty())
+ *se << L"\nError:\n" << message;
}
- if (errorInfo.SystemError != 0)
- {
- message += NError::MyFormatMessage(errorInfo.SystemError);
- message.Add_LF();
- }
- if (!message.IsEmpty())
- so << 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 (numErrors > 1)
- so << 's';
- so << endl;
+ if (se)
+ {
+ *se << endl;
+ *se << "WARNINGS for files:" << endl << endl;
+ PrintWarningsPaths(callback.FailedFiles, *se);
+ *se << "WARNING: Cannot open " << numErrors << " file";
+ if (numErrors > 1)
+ *se << 's';
+ *se << endl;
+ }
exitCode = NExitCode::kWarning;
}
@@ -473,10 +492,7 @@ int Main2(
CStdOutStream *percentsStream = NULL;
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 (ecs->NumTryArcs > 1)
+ if (so)
{
- so << "Archives: " << ecs->NumTryArcs << endl;
- so << "OK archives: " << ecs->NumOkArcs << endl;
+ *so << endl;
+
+ if (ecs->NumTryArcs > 1)
+ {
+ *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 (ecs->NumArcsWithWarnings != 0)
- so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl;
- if (ecs->NumOpenArcWarnings != 0)
+ if (so)
{
- so << endl;
+ if (ecs->NumArcsWithWarnings != 0)
+ *so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl;
+
if (ecs->NumOpenArcWarnings != 0)
- so << "Warnings: " << ecs->NumOpenArcWarnings << endl;
+ {
+ *so << endl;
+ if (ecs->NumOpenArcWarnings != 0)
+ *so << "Warnings: " << ecs->NumOpenArcWarnings << endl;
+ }
}
if (ecs->NumOpenArcErrors != 0)
{
isError = true;
- so << endl;
- if (ecs->NumOpenArcErrors != 0)
- so << "Open Errors: " << ecs->NumOpenArcErrors << endl;
+ if (so)
+ {
+ *so << endl;
+ if (ecs->NumOpenArcErrors != 0)
+ *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);
diff --git a/CPP/7zip/UI/Explorer/ContextMenu.h b/CPP/7zip/UI/Explorer/ContextMenu.h
index a3b1174b..90ca0e64 100644
--- a/CPP/7zip/UI/Explorer/ContextMenu.h
+++ b/CPP/7zip/UI/Explorer/ContextMenu.h
@@ -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"
diff --git a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp
index d620cb70..3b04e7be 100644
--- a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp
+++ b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp
@@ -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"
diff --git a/CPP/7zip/UI/Far/Far.cpp b/CPP/7zip/UI/Far/Far.cpp
index 3ae5bba2..d5656e29 100644
--- a/CPP/7zip/UI/Far/Far.cpp
+++ b/CPP/7zip/UI/Far/Far.cpp
@@ -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;
diff --git a/CPP/7zip/UI/Far/Messages.h b/CPP/7zip/UI/Far/Messages.h
index e6972392..0697a163 100644
--- a/CPP/7zip/UI/Far/Messages.h
+++ b/CPP/7zip/UI/Far/Messages.h
@@ -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
{
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp
index 89a6b45a..8b605d0f 100644
--- a/CPP/7zip/UI/FileManager/BrowseDialog.cpp
+++ b/CPP/7zip/UI/FileManager/BrowseDialog.cpp
@@ -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();
diff --git a/CPP/7zip/UI/FileManager/ClassDefs.cpp b/CPP/7zip/UI/FileManager/ClassDefs.cpp
index b092a9ed..33197fc3 100644
--- a/CPP/7zip/UI/FileManager/ClassDefs.cpp
+++ b/CPP/7zip/UI/FileManager/ClassDefs.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
#include "../../../Common/MyInitGuid.h"
#include "../Agent/Agent.h"
diff --git a/CPP/7zip/UI/FileManager/FM.cpp b/CPP/7zip/UI/FileManager/FM.cpp
index 00b152c8..1a7ed060 100644
--- a/CPP/7zip/UI/FileManager/FM.cpp
+++ b/CPP/7zip/UI/FileManager/FM.cpp
@@ -2,6 +2,10 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
+#include <shlwapi.h>
+
#include "../../../../C/Alloc.h"
#include "../../../Common/IntToString.h"
diff --git a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
index 54dabc57..af0cd8cc 100644
--- a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
+++ b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
@@ -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++)
{
diff --git a/CPP/7zip/UI/FileManager/LinkDialog.cpp b/CPP/7zip/UI/FileManager/LinkDialog.cpp
index bc482e4b..07f046e1 100644
--- a/CPP/7zip/UI/FileManager/LinkDialog.cpp
+++ b/CPP/7zip/UI/FileManager/LinkDialog.cpp
@@ -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 (i >= ARRAY_SIZE(k_LinkType_Buttons))
+
+ if (from.IsEmpty())
return;
+ if (!NName::IsAbsolutePath(from))
+ from.Insert(0, CurDirPrefix);
- int idb = k_LinkType_Buttons[i];
+ 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;
+ }
- 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;
diff --git a/CPP/7zip/UI/FileManager/LinkDialog.h b/CPP/7zip/UI/FileManager/LinkDialog.h
index 8417fac8..56deec9d 100644
--- a/CPP/7zip/UI/FileManager/LinkDialog.h
+++ b/CPP/7zip/UI/FileManager/LinkDialog.h
@@ -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;
diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp
index a7416a4c..96a34af8 100644
--- a/CPP/7zip/UI/FileManager/Panel.cpp
+++ b/CPP/7zip/UI/FileManager/Panel.cpp
@@ -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()
diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h
index 39915a27..5d03f6da 100644
--- a/CPP/7zip/UI/FileManager/Panel.h
+++ b/CPP/7zip/UI/FileManager/Panel.h
@@ -3,6 +3,10 @@
#ifndef __PANEL_H
#define __PANEL_H
+#include "../../../Common/MyWindows.h"
+
+#include <ShlObj.h>
+
#include "../../../../C/Alloc.h"
#include "../../../Common/Defs.h"
diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
index cd70c727..4d9ce51f 100644
--- a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
+++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
@@ -359,7 +359,7 @@ LRESULT CPanel::OnNotifyComboBoxEnter(const UString &s)
{
if (BindToPathAndRefresh(GetUnicodeString(s)) == S_OK)
{
- PostMessage(kSetFocusToListView);
+ PostMsg(kSetFocusToListView);
return TRUE;
}
return FALSE;
@@ -370,7 +370,7 @@ bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDITW info, LRESULT &result)
if (info->iWhy == CBENF_ESCAPE)
{
_headerComboBox.SetText(_currentFolderPrefix);
- PostMessage(kSetFocusToListView);
+ PostMsg(kSetFocusToListView);
result = FALSE;
return true;
}
@@ -401,7 +401,7 @@ bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info, LRESULT &result)
if (info->iWhy == CBENF_ESCAPE)
{
_headerComboBox.SetText(_currentFolderPrefix);
- PostMessage(kSetFocusToListView);
+ PostMsg(kSetFocusToListView);
result = FALSE;
return true;
}
@@ -528,9 +528,9 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result)
// _headerComboBox.SetText(pass); // it's fix for seclecting by mouse.
if (BindToPathAndRefresh(pass) == S_OK)
{
- PostMessage(kSetFocusToListView);
+ PostMsg(kSetFocusToListView);
#ifdef UNDER_CE
- PostMessage(kRefresh_HeaderComboBox);
+ PostMsg(kRefresh_HeaderComboBox);
#endif
return true;
}
diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
index a485522f..b47a30a3 100644
--- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
+++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
#include <tlhelp32.h>
#include "../../../Common/AutoPtr.h"
diff --git a/CPP/7zip/UI/FileManager/PanelOperations.cpp b/CPP/7zip/UI/FileManager/PanelOperations.cpp
index 62a08e13..0afbc07b 100644
--- a/CPP/7zip/UI/FileManager/PanelOperations.cpp
+++ b/CPP/7zip/UI/FileManager/PanelOperations.cpp
@@ -354,7 +354,7 @@ BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh)
_dontShowMode = true;
- PostMessage(kReLoadMessage);
+ PostMsg(kReLoadMessage);
return TRUE;
}
diff --git a/CPP/7zip/UI/FileManager/PanelSelect.cpp b/CPP/7zip/UI/FileManager/PanelSelect.cpp
index 7b53eb00..de9cf4b5 100644
--- a/CPP/7zip/UI/FileManager/PanelSelect.cpp
+++ b/CPP/7zip/UI/FileManager/PanelSelect.cpp
@@ -70,7 +70,7 @@ void CPanel::OnArrowWithShift()
}
_prevFocusedItem = focusedItem;
- PostMessage(kShiftSelectMessage);
+ PostMsg(kShiftSelectMessage);
_listView.RedrawItem(focusedItem);
}
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.cpp b/CPP/7zip/UI/FileManager/ProgressDialog.cpp
index b4195c18..4b20f1a9 100644
--- a/CPP/7zip/UI/FileManager/ProgressDialog.cpp
+++ b/CPP/7zip/UI/FileManager/ProgressDialog.cpp
@@ -184,7 +184,7 @@ void CProgressDialog::CheckNeedClose()
{
if (_needClose)
{
- PostMessage(kCloseMessage);
+ PostMsg(kCloseMessage);
_needClose = false;
}
}
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.h b/CPP/7zip/UI/FileManager/ProgressDialog.h
index 175db017..0f41b57a 100644
--- a/CPP/7zip/UI/FileManager/ProgressDialog.h
+++ b/CPP/7zip/UI/FileManager/ProgressDialog.h
@@ -152,7 +152,7 @@ public:
{
WaitCreating();
if (_wasCreated)
- PostMessage(kCloseMessage);
+ PostMsg(kCloseMessage);
else
_needClose = true;
};
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
index 231d0ace..dc828e72 100644
--- a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
@@ -1229,7 +1229,7 @@ void CProgressDialog::CheckNeedClose()
{
if (_needClose)
{
- PostMessage(kCloseMessage);
+ PostMsg(kCloseMessage);
_needClose = false;
}
}
@@ -1241,7 +1241,7 @@ void CProgressDialog::ProcessWasFinished()
WaitCreating();
if (_wasCreated)
- PostMessage(kCloseMessage);
+ PostMsg(kCloseMessage);
else
_needClose = true;
}
diff --git a/CPP/7zip/UI/FileManager/PropertyName.rc b/CPP/7zip/UI/FileManager/PropertyName.rc
index 8b8c7899..5de5aeec 100644
--- a/CPP/7zip/UI/FileManager/PropertyName.rc
+++ b/CPP/7zip/UI/FileManager/PropertyName.rc
@@ -96,4 +96,5 @@ BEGIN
IDS_PROP_STREAM_ID "Stream ID"
IDS_PROP_READ_ONLY "Read-only"
IDS_PROP_OUT_NAME "Out Name"
+ IDS_PROP_COPY_LINK "Copy Link"
END
diff --git a/CPP/7zip/UI/FileManager/PropertyNameRes.h b/CPP/7zip/UI/FileManager/PropertyNameRes.h
index 3696ed2e..67f33902 100644
--- a/CPP/7zip/UI/FileManager/PropertyNameRes.h
+++ b/CPP/7zip/UI/FileManager/PropertyNameRes.h
@@ -92,3 +92,4 @@
#define IDS_PROP_STREAM_ID 1092
#define IDS_PROP_READ_ONLY 1093
#define IDS_PROP_OUT_NAME 1094
+#define IDS_PROP_COPY_LINK 1095
diff --git a/CPP/7zip/UI/FileManager/RootFolder.cpp b/CPP/7zip/UI/FileManager/RootFolder.cpp
index c5b57821..2a5d513a 100644
--- a/CPP/7zip/UI/FileManager/RootFolder.cpp
+++ b/CPP/7zip/UI/FileManager/RootFolder.cpp
@@ -2,6 +2,10 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
+#include <ShlObj.h>
+
#include "../../../Common/StringConvert.h"
#include "../../../Windows/DLL.h"
diff --git a/CPP/7zip/UI/FileManager/StdAfx.h b/CPP/7zip/UI/FileManager/StdAfx.h
index 85389112..e6d96041 100644
--- a/CPP/7zip/UI/FileManager/StdAfx.h
+++ b/CPP/7zip/UI/FileManager/StdAfx.h
@@ -12,8 +12,10 @@
#include "../../../Common/Common.h"
-#include <commctrl.h>
-#include <ShlObj.h>
-#include <shlwapi.h>
+// #include "../../../Common/MyWindows.h"
+
+// #include <commctrl.h>
+// #include <ShlObj.h>
+// #include <shlwapi.h>
#endif
diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.cpp b/CPP/7zip/UI/FileManager/SysIconUtils.cpp
index 2c35c191..c400bc29 100644
--- a/CPP/7zip/UI/FileManager/SysIconUtils.cpp
+++ b/CPP/7zip/UI/FileManager/SysIconUtils.cpp
@@ -10,6 +10,8 @@
#include "SysIconUtils.h"
+#include <ShlObj.h>
+
#ifndef _UNICODE
extern bool g_IsNT;
#endif
diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.h b/CPP/7zip/UI/FileManager/SysIconUtils.h
index 20199acb..f1b27fa1 100644
--- a/CPP/7zip/UI/FileManager/SysIconUtils.h
+++ b/CPP/7zip/UI/FileManager/SysIconUtils.h
@@ -3,6 +3,10 @@
#ifndef __SYS_ICON_UTILS_H
#define __SYS_ICON_UTILS_H
+#include "../../../Common/MyWindows.h"
+
+#include <commctrl.h>
+
#include "../../../Common/MyString.h"
struct CExtIconPair
diff --git a/CPP/7zip/UI/FileManager/SystemPage.cpp b/CPP/7zip/UI/FileManager/SystemPage.cpp
index a7f0c3fb..d60d7b4f 100644
--- a/CPP/7zip/UI/FileManager/SystemPage.cpp
+++ b/CPP/7zip/UI/FileManager/SystemPage.cpp
@@ -2,6 +2,10 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
+#include <ShlObj.h>
+
#include "../../../Common/StringConvert.h"
#include "../../../Common/Defs.h"
diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp
index 2f118846..db4b1378 100644
--- a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp
+++ b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp
@@ -114,7 +114,7 @@ bool CBenchmarkDialog::OnInit()
// f.lfFaceName[0] = 0;
_font.Create(&f);
if (_font._font)
- _consoleEdit.SendMessage(WM_SETFONT, (WPARAM)_font._font, TRUE);
+ _consoleEdit.SendMsg(WM_SETFONT, (WPARAM)_font._font, TRUE);
}
{
diff --git a/CPP/7zip/UI/GUI/GUI.cpp b/CPP/7zip/UI/GUI/GUI.cpp
index 134ac021..0f3cde94 100644
--- a/CPP/7zip/UI/GUI/GUI.cpp
+++ b/CPP/7zip/UI/GUI/GUI.cpp
@@ -2,6 +2,10 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
+#include <shlwapi.h>
+
#include "../../../../C/Alloc.h"
#include "../../../Common/MyInitGuid.h"
diff --git a/CPP/7zip/UI/GUI/StdAfx.h b/CPP/7zip/UI/GUI/StdAfx.h
index 9e322f96..64290769 100644
--- a/CPP/7zip/UI/GUI/StdAfx.h
+++ b/CPP/7zip/UI/GUI/StdAfx.h
@@ -9,9 +9,11 @@
#include "../../../Common/Common.h"
+// #include "../../../Common/MyWindows.h"
+
// #include <commctrl.h>
-#include <ShlObj.h>
-#include <shlwapi.h>
+// #include <ShlObj.h>
+// #include <shlwapi.h>
// #define printf(x) NO_PRINTF_(x)
// #define sprintf(x) NO_SPRINTF_(x)
diff --git a/CPP/Common/Defs.h b/CPP/Common/Defs.h
index dad3ae8f..1fbd78bd 100644
--- a/CPP/Common/Defs.h
+++ b/CPP/Common/Defs.h
@@ -3,18 +3,13 @@
#ifndef __COMMON_DEFS_H
#define __COMMON_DEFS_H
-template <class T> inline T MyMin(T a, T b)
- { return a < b ? a : b; }
-template <class T> inline T MyMax(T a, T b)
- { return a > b ? a : b; }
+template <class T> inline T MyMin(T a, T b) { return a < b ? a : b; }
+template <class T> inline T MyMax(T a, T b) { return a > b ? a : b; }
template <class T> inline int MyCompare(T a, T b)
- { return a < b ? -1 : (a == b ? 0 : 1); }
+ { return a == b ? 0 : (a < b ? -1 : 1); }
-inline int BoolToInt(bool value)
- { return (value ? 1: 0); }
-
-inline bool IntToBool(int value)
- { return (value != 0); }
+inline int BoolToInt(bool v) { return (v ? 1 : 0); }
+inline bool IntToBool(int v) { return (v != 0); }
#endif
diff --git a/CPP/Common/MyBuffer.h b/CPP/Common/MyBuffer.h
index 58caa2ff..379e0d2c 100644
--- a/CPP/Common/MyBuffer.h
+++ b/CPP/Common/MyBuffer.h
@@ -78,8 +78,10 @@ public:
if (newSize != 0)
{
newBuffer = new T[newSize];
- if (_size != 0)
- memcpy(newBuffer, _items, MyMin(MyMin(_size, keepSize), newSize) * sizeof(T));
+ if (keepSize > _size)
+ keepSize = _size;
+ if (keepSize != 0)
+ memcpy(newBuffer, _items, MyMin(keepSize, newSize) * sizeof(T));
}
delete []_items;
_items = newBuffer;
@@ -109,8 +111,8 @@ template <class T>
bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2)
{
size_t size1 = b1.Size();
- if (size1 == b2.Size())
- return false;
+ if (size1 != b2.Size())
+ return true;
if (size1 == 0)
return false;
return memcmp(b1, b2, size1 * sizeof(T)) != 0;
@@ -118,7 +120,7 @@ bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2)
typedef CBuffer<char> CCharBuffer;
-typedef CBuffer<wchar_t> CWCharBuffer;
+// typedef CBuffer<wchar_t> CWCharBuffer;
typedef CBuffer<unsigned char> CByteBuffer;
@@ -155,11 +157,9 @@ typedef CObjArray<unsigned char> CByteArr;
typedef CObjArray<bool> CBoolArr;
typedef CObjArray<int> CIntArr;
-// #define CRecArray CObjArray
template <class T> class CObjArray2
{
-// protected:
T *_items;
unsigned _size;
diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp
index f35ed71e..a2d4cc4e 100644
--- a/CPP/Common/MyString.cpp
+++ b/CPP/Common/MyString.cpp
@@ -3,7 +3,6 @@
#include "StdAfx.h"
#ifdef _WIN32
-#include <windows.h>
#include <wchar.h>
#else
#include <ctype.h>
diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h
index a0e88df5..2430230b 100644
--- a/CPP/Common/MyString.h
+++ b/CPP/Common/MyString.h
@@ -10,6 +10,7 @@
#include <wchar.h>
#endif
+#include "MyWindows.h"
#include "MyTypes.h"
#include "MyVector.h"
diff --git a/CPP/Common/MyUnknown.h b/CPP/Common/MyUnknown.h
index e9e8666b..ff025cb5 100644
--- a/CPP/Common/MyUnknown.h
+++ b/CPP/Common/MyUnknown.h
@@ -3,11 +3,15 @@
#ifndef __MY_UNKNOWN_H
#define __MY_UNKNOWN_H
+#include "MyWindows.h"
+
+/*
#ifdef _WIN32
#include <basetyps.h>
#include <unknwn.h>
#else
#include "MyWindows.h"
#endif
+*/
#endif
diff --git a/CPP/Common/MyVector.h b/CPP/Common/MyVector.h
index 28b26d68..14f7b11a 100644
--- a/CPP/Common/MyVector.h
+++ b/CPP/Common/MyVector.h
@@ -3,6 +3,8 @@
#ifndef __COMMON_MY_VECTOR_H
#define __COMMON_MY_VECTOR_H
+#include <string.h>
+
template <class T>
class CRecordVector
{
diff --git a/CPP/Common/NewHandler.h b/CPP/Common/NewHandler.h
index e3e7422c..dcad5688 100644
--- a/CPP/Common/NewHandler.h
+++ b/CPP/Common/NewHandler.h
@@ -21,6 +21,7 @@ problem for your code.
Also we declare delete(void *p) throw() that creates smaller code.
*/
+#include <stddef.h>
class CNewException {};
diff --git a/CPP/Common/Random.cpp b/CPP/Common/Random.cpp
index 4bd3fcf9..fbdb8c97 100644
--- a/CPP/Common/Random.cpp
+++ b/CPP/Common/Random.cpp
@@ -6,6 +6,8 @@
#ifndef _WIN32
#include <time.h>
+#else
+#include "MyWindows.h"
#endif
#include "Random.h"
diff --git a/CPP/Windows/CommonDialog.cpp b/CPP/Windows/CommonDialog.cpp
index 52ad77bc..8f4f56d3 100644
--- a/CPP/Windows/CommonDialog.cpp
+++ b/CPP/Windows/CommonDialog.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../Common/MyWindows.h"
+
#ifdef UNDER_CE
#include <commdlg.h>
#endif
diff --git a/CPP/Windows/Control/ComboBox.cpp b/CPP/Windows/Control/ComboBox.cpp
index 3c08309b..c6d5a8d6 100644
--- a/CPP/Windows/Control/ComboBox.cpp
+++ b/CPP/Windows/Control/ComboBox.cpp
@@ -34,7 +34,7 @@ LRESULT CComboBox::GetLBText(int index, CSysString &s)
LRESULT CComboBox::AddString(LPCWSTR s)
{
if (g_IsNT)
- return SendMessageW(CB_ADDSTRING, 0, (LPARAM)s);
+ return SendMsgW(CB_ADDSTRING, 0, (LPARAM)s);
return AddString(GetSystemString(s));
}
@@ -43,10 +43,10 @@ LRESULT CComboBox::GetLBText(int index, UString &s)
s.Empty();
if (g_IsNT)
{
- LRESULT len = SendMessageW(CB_GETLBTEXTLEN, index, 0);
+ LRESULT len = SendMsgW(CB_GETLBTEXTLEN, index, 0);
if (len == CB_ERR)
return len;
- LRESULT len2 = SendMessageW(CB_GETLBTEXT, index, (LPARAM)s.GetBuf((unsigned)len));
+ LRESULT len2 = SendMsgW(CB_GETLBTEXT, index, (LPARAM)s.GetBuf((unsigned)len));
if (len2 == CB_ERR)
return len;
if (len > len2)
diff --git a/CPP/Windows/Control/ComboBox.h b/CPP/Windows/Control/ComboBox.h
index 8c6fd381..1d5a4821 100644
--- a/CPP/Windows/Control/ComboBox.h
+++ b/CPP/Windows/Control/ComboBox.h
@@ -3,6 +3,8 @@
#ifndef __WINDOWS_CONTROL_COMBOBOX_H
#define __WINDOWS_CONTROL_COMBOBOX_H
+#include "../../Common/MyWindows.h"
+
#include <commctrl.h>
#include "../Window.h"
@@ -13,28 +15,28 @@ namespace NControl {
class CComboBox: public CWindow
{
public:
- void ResetContent() { SendMessage(CB_RESETCONTENT, 0, 0); }
- LRESULT AddString(LPCTSTR s) { return SendMessage(CB_ADDSTRING, 0, (LPARAM)s); }
+ void ResetContent() { SendMsg(CB_RESETCONTENT, 0, 0); }
+ LRESULT AddString(LPCTSTR s) { return SendMsg(CB_ADDSTRING, 0, (LPARAM)s); }
#ifndef _UNICODE
LRESULT AddString(LPCWSTR s);
#endif
- LRESULT SetCurSel(int index) { return SendMessage(CB_SETCURSEL, index, 0); }
- int GetCurSel() { return (int)SendMessage(CB_GETCURSEL, 0, 0); }
- int GetCount() { return (int)SendMessage(CB_GETCOUNT, 0, 0); }
+ LRESULT SetCurSel(int index) { return SendMsg(CB_SETCURSEL, index, 0); }
+ int GetCurSel() { return (int)SendMsg(CB_GETCURSEL, 0, 0); }
+ int GetCount() { return (int)SendMsg(CB_GETCOUNT, 0, 0); }
- LRESULT GetLBTextLen(int index) { return SendMessage(CB_GETLBTEXTLEN, index, 0); }
- LRESULT GetLBText(int index, LPTSTR s) { return SendMessage(CB_GETLBTEXT, index, (LPARAM)s); }
+ LRESULT GetLBTextLen(int index) { return SendMsg(CB_GETLBTEXTLEN, index, 0); }
+ LRESULT GetLBText(int index, LPTSTR s) { return SendMsg(CB_GETLBTEXT, index, (LPARAM)s); }
LRESULT GetLBText(int index, CSysString &s);
#ifndef _UNICODE
LRESULT GetLBText(int index, UString &s);
#endif
- LRESULT SetItemData(int index, LPARAM lParam) { return SendMessage(CB_SETITEMDATA, index, lParam); }
- LRESULT GetItemData(int index) { return SendMessage(CB_GETITEMDATA, index, 0); }
+ LRESULT SetItemData(int index, LPARAM lParam) { return SendMsg(CB_SETITEMDATA, index, lParam); }
+ LRESULT GetItemData(int index) { return SendMsg(CB_GETITEMDATA, index, 0); }
LRESULT GetItemData_of_CurSel() { return GetItemData(GetCurSel()); }
- void ShowDropDown(bool show = true) { SendMessage(CB_SHOWDROPDOWN, show ? TRUE : FALSE, 0); }
+ void ShowDropDown(bool show = true) { SendMsg(CB_SHOWDROPDOWN, show ? TRUE : FALSE, 0); }
};
#ifndef UNDER_CE
@@ -42,18 +44,18 @@ public:
class CComboBoxEx: public CComboBox
{
public:
- bool SetUnicodeFormat(bool fUnicode) { return LRESULTToBool(SendMessage(CBEM_SETUNICODEFORMAT, BOOLToBool(fUnicode), 0)); }
+ bool SetUnicodeFormat(bool fUnicode) { return LRESULTToBool(SendMsg(CBEM_SETUNICODEFORMAT, BOOLToBool(fUnicode), 0)); }
- LRESULT DeleteItem(int index) { return SendMessage(CBEM_DELETEITEM, index, 0); }
- LRESULT InsertItem(COMBOBOXEXITEM *item) { return SendMessage(CBEM_INSERTITEM, 0, (LPARAM)item); }
+ LRESULT DeleteItem(int index) { return SendMsg(CBEM_DELETEITEM, index, 0); }
+ LRESULT InsertItem(COMBOBOXEXITEM *item) { return SendMsg(CBEM_INSERTITEM, 0, (LPARAM)item); }
#ifndef _UNICODE
- LRESULT InsertItem(COMBOBOXEXITEMW *item) { return SendMessage(CBEM_INSERTITEMW, 0, (LPARAM)item); }
+ LRESULT InsertItem(COMBOBOXEXITEMW *item) { return SendMsg(CBEM_INSERTITEMW, 0, (LPARAM)item); }
#endif
- LRESULT SetItem(COMBOBOXEXITEM *item) { return SendMessage(CBEM_SETITEM, 0, (LPARAM)item); }
- DWORD SetExtendedStyle(DWORD exMask, DWORD exStyle) { return (DWORD)SendMessage(CBEM_SETEXTENDEDSTYLE, exMask, exStyle); }
- HWND GetEditControl() { return (HWND)SendMessage(CBEM_GETEDITCONTROL, 0, 0); }
- HIMAGELIST SetImageList(HIMAGELIST imageList) { return (HIMAGELIST)SendMessage(CBEM_SETIMAGELIST, 0, (LPARAM)imageList); }
+ LRESULT SetItem(COMBOBOXEXITEM *item) { return SendMsg(CBEM_SETITEM, 0, (LPARAM)item); }
+ DWORD SetExtendedStyle(DWORD exMask, DWORD exStyle) { return (DWORD)SendMsg(CBEM_SETEXTENDEDSTYLE, exMask, exStyle); }
+ HWND GetEditControl() { return (HWND)SendMsg(CBEM_GETEDITCONTROL, 0, 0); }
+ HIMAGELIST SetImageList(HIMAGELIST imageList) { return (HIMAGELIST)SendMsg(CBEM_SETIMAGELIST, 0, (LPARAM)imageList); }
};
#endif
diff --git a/CPP/Windows/Control/CommandBar.h b/CPP/Windows/Control/CommandBar.h
index 780211ec..a6197447 100644
--- a/CPP/Windows/Control/CommandBar.h
+++ b/CPP/Windows/Control/CommandBar.h
@@ -5,6 +5,10 @@
#ifdef UNDER_CE
+#include "../../Common/MyWindows.h"
+
+#include <commctrl.h>
+
#include "../Window.h"
namespace NWindows {
@@ -21,10 +25,10 @@ public:
// Macros
// void Destroy() { CommandBar_Destroy(_window); }
- // bool AddButtons(UINT numButtons, LPTBBUTTON buttons) { return BOOLToBool(SendMessage(TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)buttons)); }
- bool InsertButton(int iButton, LPTBBUTTON button) { return BOOLToBool(SendMessage(TB_INSERTBUTTON, (WPARAM)iButton, (LPARAM)button)); }
- BOOL AddToolTips(UINT numToolTips, LPTSTR toolTips) { return BOOLToBool(SendMessage(TB_SETTOOLTIPS, (WPARAM)numToolTips, (LPARAM)toolTips)); }
- void AutoSize() { SendMessage(TB_AUTOSIZE, 0, 0); }
+ // bool AddButtons(UINT numButtons, LPTBBUTTON buttons) { return BOOLToBool(SendMsg(TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)buttons)); }
+ bool InsertButton(int iButton, LPTBBUTTON button) { return BOOLToBool(SendMsg(TB_INSERTBUTTON, (WPARAM)iButton, (LPARAM)button)); }
+ BOOL AddToolTips(UINT numToolTips, LPTSTR toolTips) { return BOOLToBool(SendMsg(TB_SETTOOLTIPS, (WPARAM)numToolTips, (LPARAM)toolTips)); }
+ void AutoSize() { SendMsg(TB_AUTOSIZE, 0, 0); }
bool AddAdornments(DWORD dwFlags) { return BOOLToBool(::CommandBar_AddAdornments(_window, dwFlags, 0)); }
int AddBitmap(HINSTANCE hInst, int idBitmap, int iNumImages, int iImageWidth, int iImageHeight) { return ::CommandBar_AddBitmap(_window, hInst, idBitmap, iNumImages, iImageWidth, iImageHeight); }
diff --git a/CPP/Windows/Control/Edit.h b/CPP/Windows/Control/Edit.h
index 17ac9f13..51a22c53 100644
--- a/CPP/Windows/Control/Edit.h
+++ b/CPP/Windows/Control/Edit.h
@@ -11,7 +11,7 @@ namespace NControl {
class CEdit: public CWindow
{
public:
- void SetPasswordChar(WPARAM c) { SendMessage(EM_SETPASSWORDCHAR, c); }
+ void SetPasswordChar(WPARAM c) { SendMsg(EM_SETPASSWORDCHAR, c); }
};
}}
diff --git a/CPP/Windows/Control/ListView.h b/CPP/Windows/Control/ListView.h
index ceb297f8..eeae041c 100644
--- a/CPP/Windows/Control/ListView.h
+++ b/CPP/Windows/Control/ListView.h
@@ -3,10 +3,12 @@
#ifndef __WINDOWS_CONTROL_LISTVIEW_H
#define __WINDOWS_CONTROL_LISTVIEW_H
-#include "../Window.h"
+#include "../../Common/MyWindows.h"
#include <commctrl.h>
+#include "../Window.h"
+
namespace NWindows {
namespace NControl {
@@ -37,11 +39,11 @@ public:
#ifndef _UNICODE
- int InsertColumn(int columnIndex, const LVCOLUMNW *columnInfo) { return (int)SendMessage(LVM_INSERTCOLUMNW, (WPARAM)columnIndex, (LPARAM)columnInfo); }
+ int InsertColumn(int columnIndex, const LVCOLUMNW *columnInfo) { return (int)SendMsg(LVM_INSERTCOLUMNW, (WPARAM)columnIndex, (LPARAM)columnInfo); }
int InsertColumn(int columnIndex, LPCWSTR text, int width);
- int InsertItem(const LV_ITEMW* item) { return (int)SendMessage(LVM_INSERTITEMW, 0, (LPARAM)item); }
+ int InsertItem(const LV_ITEMW* item) { return (int)SendMsg(LVM_INSERTITEMW, 0, (LPARAM)item); }
int InsertItem(int index, LPCWSTR text);
- bool SetItem(const LV_ITEMW* item) { return BOOLToBool((BOOL)SendMessage(LVM_SETITEMW, 0, (LPARAM)item)); }
+ bool SetItem(const LV_ITEMW* item) { return BOOLToBool((BOOL)SendMsg(LVM_SETITEMW, 0, (LPARAM)item)); }
int SetSubItem(int index, int subIndex, LPCWSTR text);
#endif
diff --git a/CPP/Windows/Control/ProgressBar.h b/CPP/Windows/Control/ProgressBar.h
index 4591880a..38ebcb61 100644
--- a/CPP/Windows/Control/ProgressBar.h
+++ b/CPP/Windows/Control/ProgressBar.h
@@ -3,6 +3,10 @@
#ifndef __WINDOWS_CONTROL_PROGRESSBAR_H
#define __WINDOWS_CONTROL_PROGRESSBAR_H
+#include "../../Common/MyWindows.h"
+
+#include <commctrl.h>
+
#include "../Window.h"
namespace NWindows {
@@ -11,18 +15,18 @@ namespace NControl {
class CProgressBar: public CWindow
{
public:
- LRESULT SetPos(int pos) { return SendMessage(PBM_SETPOS, pos, 0); }
- LRESULT DeltaPos(int increment) { return SendMessage(PBM_DELTAPOS, increment, 0); }
- UINT GetPos() { return (UINT)SendMessage(PBM_GETPOS, 0, 0); }
- LRESULT SetRange(unsigned short minValue, unsigned short maxValue) { return SendMessage(PBM_SETRANGE, 0, MAKELPARAM(minValue, maxValue)); }
- DWORD SetRange32(int minValue, int maxValue) { return (DWORD)SendMessage(PBM_SETRANGE32, minValue, maxValue); }
- int SetStep(int step) { return (int)SendMessage(PBM_SETSTEP, step, 0); }
- LRESULT StepIt() { return SendMessage(PBM_STEPIT, 0, 0); }
- INT GetRange(bool minValue, PPBRANGE range) { return (INT)SendMessage(PBM_GETRANGE, BoolToBOOL(minValue), (LPARAM)range); }
+ LRESULT SetPos(int pos) { return SendMsg(PBM_SETPOS, pos, 0); }
+ LRESULT DeltaPos(int increment) { return SendMsg(PBM_DELTAPOS, increment, 0); }
+ UINT GetPos() { return (UINT)SendMsg(PBM_GETPOS, 0, 0); }
+ LRESULT SetRange(unsigned short minValue, unsigned short maxValue) { return SendMsg(PBM_SETRANGE, 0, MAKELPARAM(minValue, maxValue)); }
+ DWORD SetRange32(int minValue, int maxValue) { return (DWORD)SendMsg(PBM_SETRANGE32, minValue, maxValue); }
+ int SetStep(int step) { return (int)SendMsg(PBM_SETSTEP, step, 0); }
+ LRESULT StepIt() { return SendMsg(PBM_STEPIT, 0, 0); }
+ INT GetRange(bool minValue, PPBRANGE range) { return (INT)SendMsg(PBM_GETRANGE, BoolToBOOL(minValue), (LPARAM)range); }
#ifndef UNDER_CE
- COLORREF SetBarColor(COLORREF color) { return (COLORREF)SendMessage(PBM_SETBARCOLOR, 0, color); }
- COLORREF SetBackgroundColor(COLORREF color) { return (COLORREF)SendMessage(PBM_SETBKCOLOR, 0, color); }
+ COLORREF SetBarColor(COLORREF color) { return (COLORREF)SendMsg(PBM_SETBARCOLOR, 0, color); }
+ COLORREF SetBackgroundColor(COLORREF color) { return (COLORREF)SendMsg(PBM_SETBKCOLOR, 0, color); }
#endif
};
diff --git a/CPP/Windows/Control/PropertyPage.h b/CPP/Windows/Control/PropertyPage.h
index 7df8645e..4c4ddad9 100644
--- a/CPP/Windows/Control/PropertyPage.h
+++ b/CPP/Windows/Control/PropertyPage.h
@@ -3,6 +3,8 @@
#ifndef __WINDOWS_CONTROL_PROPERTYPAGE_H
#define __WINDOWS_CONTROL_PROPERTYPAGE_H
+#include "../../Common/MyWindows.h"
+
#include <prsht.h>
#include "Dialog.h"
diff --git a/CPP/Windows/Control/ReBar.h b/CPP/Windows/Control/ReBar.h
index bd475b10..c2d58dbe 100644
--- a/CPP/Windows/Control/ReBar.h
+++ b/CPP/Windows/Control/ReBar.h
@@ -12,21 +12,21 @@ class CReBar: public NWindows::CWindow
{
public:
bool SetBarInfo(LPREBARINFO barInfo)
- { return LRESULTToBool(SendMessage(RB_SETBARINFO, 0, (LPARAM)barInfo)); }
+ { return LRESULTToBool(SendMsg(RB_SETBARINFO, 0, (LPARAM)barInfo)); }
bool InsertBand(int index, LPREBARBANDINFO bandInfo)
- { return LRESULTToBool(SendMessage(RB_INSERTBAND, index, (LPARAM)bandInfo)); }
+ { return LRESULTToBool(SendMsg(RB_INSERTBAND, index, (LPARAM)bandInfo)); }
bool SetBandInfo(unsigned index, LPREBARBANDINFO bandInfo)
- { return LRESULTToBool(SendMessage(RB_SETBANDINFO, index, (LPARAM)bandInfo)); }
+ { return LRESULTToBool(SendMsg(RB_SETBANDINFO, index, (LPARAM)bandInfo)); }
void MaximizeBand(unsigned index, bool ideal)
- { SendMessage(RB_MAXIMIZEBAND, index, BoolToBOOL(ideal)); }
+ { SendMsg(RB_MAXIMIZEBAND, index, BoolToBOOL(ideal)); }
bool SizeToRect(LPRECT rect)
- { return LRESULTToBool(SendMessage(RB_SIZETORECT, 0, (LPARAM)rect)); }
+ { return LRESULTToBool(SendMsg(RB_SIZETORECT, 0, (LPARAM)rect)); }
UINT GetHeight()
- { return (UINT)SendMessage(RB_GETBARHEIGHT); }
+ { return (UINT)SendMsg(RB_GETBARHEIGHT); }
UINT GetBandCount()
- { return (UINT)SendMessage(RB_GETBANDCOUNT); }
+ { return (UINT)SendMsg(RB_GETBANDCOUNT); }
bool DeleteBand(UINT index)
- { return LRESULTToBool(SendMessage(RB_DELETEBAND, index)); }
+ { return LRESULTToBool(SendMsg(RB_DELETEBAND, index)); }
};
}}
diff --git a/CPP/Windows/Control/Static.h b/CPP/Windows/Control/Static.h
index cb3126dd..5523b2e6 100644
--- a/CPP/Windows/Control/Static.h
+++ b/CPP/Windows/Control/Static.h
@@ -11,15 +11,15 @@ namespace NControl {
class CStatic: public CWindow
{
public:
- HANDLE SetImage(WPARAM imageType, HANDLE handle) { return (HANDLE)SendMessage(STM_SETIMAGE, imageType, (LPARAM)handle); }
- HANDLE GetImage(WPARAM imageType) { return (HANDLE)SendMessage(STM_GETIMAGE, imageType, 0); }
+ HANDLE SetImage(WPARAM imageType, HANDLE handle) { return (HANDLE)SendMsg(STM_SETIMAGE, imageType, (LPARAM)handle); }
+ HANDLE GetImage(WPARAM imageType) { return (HANDLE)SendMsg(STM_GETIMAGE, imageType, 0); }
#ifdef UNDER_CE
HICON SetIcon(HICON icon) { return (HICON)SetImage(IMAGE_ICON, icon); }
HICON GetIcon() { return (HICON)GetImage(IMAGE_ICON); }
#else
- HICON SetIcon(HICON icon) { return (HICON)SendMessage(STM_SETICON, (WPARAM)icon, 0); }
- HICON GetIcon() { return (HICON)SendMessage(STM_GETICON, 0, 0); }
+ HICON SetIcon(HICON icon) { return (HICON)SendMsg(STM_SETICON, (WPARAM)icon, 0); }
+ HICON GetIcon() { return (HICON)SendMsg(STM_GETICON, 0, 0); }
#endif
};
diff --git a/CPP/Windows/Control/StatusBar.h b/CPP/Windows/Control/StatusBar.h
index f3e0d3ef..988b8470 100644
--- a/CPP/Windows/Control/StatusBar.h
+++ b/CPP/Windows/Control/StatusBar.h
@@ -16,7 +16,7 @@ public:
bool SetText(LPCTSTR text)
{ return CWindow::SetText(text); }
bool SetText(unsigned index, LPCTSTR text, UINT type)
- { return LRESULTToBool(SendMessage(SB_SETTEXT, index | type, (LPARAM)text)); }
+ { return LRESULTToBool(SendMsg(SB_SETTEXT, index | type, (LPARAM)text)); }
bool SetText(unsigned index, LPCTSTR text)
{ return SetText(index, text, 0); }
@@ -26,15 +26,15 @@ public:
bool SetText(LPCWSTR text)
{ return CWindow::SetText(text); }
bool SetText(unsigned index, LPCWSTR text, UINT type)
- { return LRESULTToBool(SendMessage(SB_SETTEXTW, index | type, (LPARAM)text)); }
+ { return LRESULTToBool(SendMsg(SB_SETTEXTW, index | type, (LPARAM)text)); }
bool SetText(unsigned index, LPCWSTR text)
{ return SetText(index, text, 0); }
#endif
bool SetParts(unsigned numParts, const int *edgePostions)
- { return LRESULTToBool(SendMessage(SB_SETPARTS, numParts, (LPARAM)edgePostions)); }
+ { return LRESULTToBool(SendMsg(SB_SETPARTS, numParts, (LPARAM)edgePostions)); }
void Simple(bool simple)
- { SendMessage(SB_SIMPLE, BoolToBOOL(simple), 0); }
+ { SendMsg(SB_SIMPLE, BoolToBOOL(simple), 0); }
};
}}
diff --git a/CPP/Windows/Control/ToolBar.h b/CPP/Windows/Control/ToolBar.h
index d579ab7d..7bc93a24 100644
--- a/CPP/Windows/Control/ToolBar.h
+++ b/CPP/Windows/Control/ToolBar.h
@@ -11,8 +11,8 @@ namespace NControl {
class CToolBar: public NWindows::CWindow
{
public:
- void AutoSize() { SendMessage(TB_AUTOSIZE, 0, 0); }
- DWORD GetButtonSize() { return (DWORD)SendMessage(TB_GETBUTTONSIZE, 0, 0); }
+ void AutoSize() { SendMsg(TB_AUTOSIZE, 0, 0); }
+ DWORD GetButtonSize() { return (DWORD)SendMsg(TB_GETBUTTONSIZE, 0, 0); }
bool GetMaxSize(LPSIZE size)
#ifdef UNDER_CE
@@ -25,16 +25,16 @@ public:
}
#else
{
- return LRESULTToBool(SendMessage(TB_GETMAXSIZE, 0, (LPARAM)size));
+ return LRESULTToBool(SendMsg(TB_GETMAXSIZE, 0, (LPARAM)size));
}
#endif
- bool EnableButton(UINT buttonID, bool enable) { return LRESULTToBool(SendMessage(TB_ENABLEBUTTON, buttonID, MAKELONG(BoolToBOOL(enable), 0))); }
- void ButtonStructSize() { SendMessage(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON)); }
- HIMAGELIST SetImageList(UINT listIndex, HIMAGELIST imageList) { return HIMAGELIST(SendMessage(TB_SETIMAGELIST, listIndex, (LPARAM)imageList)); }
- bool AddButton(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMessage(TB_ADDBUTTONS, numButtons, (LPARAM)buttons)); }
+ bool EnableButton(UINT buttonID, bool enable) { return LRESULTToBool(SendMsg(TB_ENABLEBUTTON, buttonID, MAKELONG(BoolToBOOL(enable), 0))); }
+ void ButtonStructSize() { SendMsg(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON)); }
+ HIMAGELIST SetImageList(UINT listIndex, HIMAGELIST imageList) { return HIMAGELIST(SendMsg(TB_SETIMAGELIST, listIndex, (LPARAM)imageList)); }
+ bool AddButton(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMsg(TB_ADDBUTTONS, numButtons, (LPARAM)buttons)); }
#ifndef _UNICODE
- bool AddButtonW(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMessage(TB_ADDBUTTONSW, numButtons, (LPARAM)buttons)); }
+ bool AddButtonW(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMsg(TB_ADDBUTTONSW, numButtons, (LPARAM)buttons)); }
#endif
};
diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp
index fdf77831..94486977 100644
--- a/CPP/Windows/FileFind.cpp
+++ b/CPP/Windows/FileFind.cpp
@@ -130,9 +130,11 @@ WinXP-64 FindFirstFile():
\\Server\ - ERROR_INVALID_NAME
\\Server\Share - ERROR_BAD_NETPATH
+ \\Server\Share - ERROR_BAD_NET_NAME (Win7)
\\Server\Share\ - ERROR_FILE_NOT_FOUND
\\?\UNC\Server\Share - ERROR_INVALID_NAME
+ \\?\UNC\Server\Share - ERROR_BAD_PATHNAME (Win7)
\\?\UNC\Server\Share\ - ERROR_FILE_NOT_FOUND
\\Server\Share_RootDrive - ERROR_INVALID_NAME
@@ -512,9 +514,11 @@ bool CFileInfo::Find(CFSTR path)
#if defined(_WIN32) && !defined(UNDER_CE)
{
DWORD lastError = GetLastError();
- if (lastError == ERROR_BAD_NETPATH ||
- lastError == ERROR_FILE_NOT_FOUND ||
- lastError == ERROR_INVALID_NAME // for "\\SERVER\shared" paths that are translated to "\\?\UNC\SERVER\shared"
+ if (lastError == ERROR_FILE_NOT_FOUND
+ || lastError == ERROR_BAD_NETPATH // XP64: "\\Server\Share"
+ || lastError == ERROR_BAD_NET_NAME // Win7: "\\Server\Share"
+ || lastError == ERROR_INVALID_NAME // XP64: "\\?\UNC\Server\Share"
+ || lastError == ERROR_BAD_PATHNAME // Win7: "\\?\UNC\Server\Share"
)
{
unsigned rootSize = 0;
diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h
index 4c8e694c..32c285fb 100644
--- a/CPP/Windows/FileIO.h
+++ b/CPP/Windows/FileIO.h
@@ -3,6 +3,8 @@
#ifndef __WINDOWS_FILE_IO_H
#define __WINDOWS_FILE_IO_H
+#include "../Common/MyWindows.h"
+
#if defined(_WIN32) && !defined(UNDER_CE)
#include <winioctl.h>
#endif
diff --git a/CPP/Windows/MemoryGlobal.h b/CPP/Windows/MemoryGlobal.h
index 94e5f508..c217510e 100644
--- a/CPP/Windows/MemoryGlobal.h
+++ b/CPP/Windows/MemoryGlobal.h
@@ -3,6 +3,8 @@
#ifndef __WINDOWS_MEMORY_GLOBAL_H
#define __WINDOWS_MEMORY_GLOBAL_H
+#include "../Common/MyWindows.h"
+
namespace NWindows {
namespace NMemory {
diff --git a/CPP/Windows/MemoryLock.cpp b/CPP/Windows/MemoryLock.cpp
index 674af007..b628a03e 100644
--- a/CPP/Windows/MemoryLock.cpp
+++ b/CPP/Windows/MemoryLock.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "MemoryLock.h"
+
namespace NWindows {
namespace NSecurity {
diff --git a/CPP/Windows/MemoryLock.h b/CPP/Windows/MemoryLock.h
index f08e5179..4a5dafcf 100644
--- a/CPP/Windows/MemoryLock.h
+++ b/CPP/Windows/MemoryLock.h
@@ -3,12 +3,14 @@
#ifndef __WINDOWS_MEMORY_LOCK_H
#define __WINDOWS_MEMORY_LOCK_H
+#include "../Common/MyWindows.h"
+
namespace NWindows {
namespace NSecurity {
#ifndef UNDER_CE
- bool EnablePrivilege(LPCTSTR privilegeName, bool enable = true);
+bool EnablePrivilege(LPCTSTR privilegeName, bool enable = true);
inline bool EnablePrivilege_LockMemory(bool enable = true)
{
diff --git a/CPP/Windows/NtCheck.h b/CPP/Windows/NtCheck.h
index e56318f0..a1b89ef2 100644
--- a/CPP/Windows/NtCheck.h
+++ b/CPP/Windows/NtCheck.h
@@ -5,6 +5,8 @@
#ifdef _WIN32
+#include "../Common/MyWindows.h"
+
#if !defined(_WIN64) && !defined(UNDER_CE)
static inline bool IsItWindowsNT()
{
diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp
index 4bc8d2a3..67551b6d 100644
--- a/CPP/Windows/System.cpp
+++ b/CPP/Windows/System.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../Common/MyWindows.h"
+
#include "../Common/Defs.h"
#include "System.h"
diff --git a/CPP/Windows/TimeUtils.h b/CPP/Windows/TimeUtils.h
index 2967214e..d3033ede 100644
--- a/CPP/Windows/TimeUtils.h
+++ b/CPP/Windows/TimeUtils.h
@@ -4,6 +4,7 @@
#define __WINDOWS_TIME_UTILS_H
#include "../Common/MyTypes.h"
+#include "../Common/MyWindows.h"
namespace NWindows {
namespace NTime {
diff --git a/CPP/Windows/Window.h b/CPP/Windows/Window.h
index 1b12d991..3bda6795 100644
--- a/CPP/Windows/Window.h
+++ b/CPP/Windows/Window.h
@@ -3,6 +3,7 @@
#ifndef __WINDOWS_WINDOW_H
#define __WINDOWS_WINDOW_H
+#include "../Common/MyWindows.h"
#include "../Common/MyString.h"
#include "Defs.h"
@@ -170,7 +171,7 @@ public:
bool Update() { return BOOLToBool(::UpdateWindow(_window)); }
bool InvalidateRect(LPCRECT rect, bool backgroundErase = true)
{ return BOOLToBool(::InvalidateRect(_window, rect, BoolToBOOL(backgroundErase))); }
- void SetRedraw(bool redraw = true) { SendMessage(WM_SETREDRAW, BoolToBOOL(redraw), 0); }
+ void SetRedraw(bool redraw = true) { SendMsg(WM_SETREDRAW, BoolToBOOL(redraw), 0); }
LONG_PTR SetStyle(LONG_PTR style) { return SetLongPtr(GWL_STYLE, style); }
LONG_PTR GetStyle() const { return GetLongPtr(GWL_STYLE); }
@@ -222,18 +223,18 @@ public:
HWND SetFocus() { return ::SetFocus(_window); }
- LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
- { return ::SendMessage(_window, message, wParam, lParam) ;}
+ LRESULT SendMsg(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
+ { return ::SendMessage(_window, message, wParam, lParam); }
#ifndef _UNICODE
- LRESULT SendMessageW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
- { return ::SendMessageW(_window, message, wParam, lParam) ;}
+ LRESULT SendMsgW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
+ { return ::SendMessageW(_window, message, wParam, lParam); }
#endif
- bool PostMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
- { return BOOLToBool(::PostMessage(_window, message, wParam, lParam)) ;}
+ bool PostMsg(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
+ { return BOOLToBool(::PostMessage(_window, message, wParam, lParam)); }
#ifndef _UNICODE
- LRESULT PostMessageW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
- { return ::PostMessageW(_window, message, wParam, lParam) ;}
+ bool PostMsgW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
+ { return BOOLToBool(::PostMessageW(_window, message, wParam, lParam)); }
#endif
bool SetText(LPCTSTR s) { return BOOLToBool(::SetWindowText(_window, s)); }
@@ -270,7 +271,7 @@ public:
bool KillTimer(UINT_PTR idEvent)
{return BOOLToBool(::KillTimer(_window, idEvent)); }
- HICON SetIcon(WPARAM sizeType, HICON icon) { return (HICON)SendMessage(WM_SETICON, sizeType, (LPARAM)icon); }
+ HICON SetIcon(WPARAM sizeType, HICON icon) { return (HICON)SendMsg(WM_SETICON, sizeType, (LPARAM)icon); }
};
#define RECT_SIZE_X(r) ((r).right - (r).left)
diff --git a/DOC/7zip.inf b/DOC/7zip.inf
index 8d9fda6d..f2cef56d 100644
--- a/DOC/7zip.inf
+++ b/DOC/7zip.inf
@@ -10,8 +10,8 @@ AppName = "7-Zip"
InstallDir = %CE1%\%AppName%
[Strings]
-AppVer = "15.05"
-AppDate = "2015-06-14"
+AppVer = "15.06"
+AppDate = "2015-08-09"
[CEDevice]
; ProcessorType = 2577 ; ARM
diff --git a/DOC/7zip.nsi b/DOC/7zip.nsi
index 0fe8a6dd..4d55fb0c 100644
--- a/DOC/7zip.nsi
+++ b/DOC/7zip.nsi
@@ -2,7 +2,7 @@
;Defines
!define VERSION_MAJOR 15
-!define VERSION_MINOR 05
+!define VERSION_MINOR 06
!define VERSION_POSTFIX_FULL " beta"
!ifdef WIN64
!ifdef IA64
diff --git a/DOC/7zip.wxs b/DOC/7zip.wxs
index 45f3b5ba..2df18ec7 100644
--- a/DOC/7zip.wxs
+++ b/DOC/7zip.wxs
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<?define VerMajor = "15" ?>
-<?define VerMinor = "05" ?>
+<?define VerMinor = "06" ?>
<?define VerBuild = "00" ?>
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
<?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?>
diff --git a/DOC/Methods.txt b/DOC/Methods.txt
index 7eb6c6bf..1a1c54c5 100644
--- a/DOC/Methods.txt
+++ b/DOC/Methods.txt
@@ -1,8 +1,8 @@
7-Zip method IDs for 7z and xz archives
---------------------------------------
-Version: 15.00
-Date: 2015-04-01
+Version: 15.06
+Date: 2015-06-23
Each compression or crypto method in 7z is associated with unique binary value (ID).
The length of ID in bytes is arbitrary but it can not exceed 63 bits (8 bytes).
@@ -22,7 +22,7 @@ If you want to add some new ID, you have two ways:
You can notify 7-Zip developers about your Developer ID / Method ID.
- Note: Use new ID only if old codec can not decode data encoded with new version.
+ Note: Use new ID, if old codec can not decode data encoded with new version.
List of defined IDs
@@ -85,9 +85,9 @@ List of defined IDs
06 - Implode
08 - Deflate
09 - Deflate64
- 10 - Imploding
- 12 - BZip2 (not used. Use {040202} instead)
- 14 - LZMA (LZMA-zip)
+ 0A - Imploding
+ 0C - BZip2 (not used. Use {040202} instead)
+ 0E - LZMA (LZMA-zip)
5F - xz
60 - Jpeg
61 - WavPack
@@ -98,9 +98,10 @@ List of defined IDs
02 - BZip2
03 - [Rar]
- 01 - Rar15
- 02 - Rar20
- 03 - Rar29
+ 01 - Rar1
+ 02 - Rar2
+ 03 - Rar3
+ 05 - Rar5
04 - [Arj]
01 - Arj(1,2,3)
diff --git a/DOC/readme.txt b/DOC/readme.txt
index ca1be590..c82a80b7 100644
--- a/DOC/readme.txt
+++ b/DOC/readme.txt
@@ -1,4 +1,4 @@
-7-Zip 15.05 Sources
+7-Zip 15.06 Sources
-------------------
7-Zip is a file archiver for Windows.